Skip to content

Commit 85c5a4b

Browse files
authored
[fix] 一致性门假绿修复:引用扫描禁止跨行 + npm test 复原 (#37)
* fix(scripts): 一致性门禁止跨行吞引用(负例必判红)+ 复原 npm test 两文件 * docs(shadow): brief 最终态——published, PR #37
1 parent c5319bb commit 85c5a4b

4 files changed

Lines changed: 97 additions & 4 deletions

File tree

‎package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"node": ">=20"
77
},
88
"scripts": {
9-
"test": "node --test test/",
9+
"test": "node --test test/install-cli.test.mjs test/pack.test.mjs",
1010
"check:requires": "node scripts/check-requires.mjs"
1111
},
1212
"cliVersion": "v1.5.0",

‎scripts/check-requires.mjs‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#!/usr/bin/env node
22
// 分发一致性门:skills 引用的命令 ⊆ 产物 requiresCommands ⊆ 已安装 CLI 的命令目录。
3+
// 引用扫描严禁跨行:早先用裸 \s+ 会把下一条 `shadow-dev` 的前缀吃进来(实测 `repo inspect\nshadow-dev`),
4+
// 导致部分命令根本没被统计——门会假绿,而假绿的门比没有门更危险。
35
// 分工:cliVersion pin 只决定「装哪个 CLI」,requiresCommands 决定「这份内容能不能装进这个 CLI」,
46
// 本门负责让两者不互相冒充。用法:npm run check:requires(CI 或本机皆可,SHADOW_DEV_CLI 可指定 cli.mjs)。
57
import { execFileSync } from 'node:child_process'
@@ -14,7 +16,7 @@ const refs = new Map()
1416
for (const d of readdirSync(join(root, 'skills'))) {
1517
const f = join(root, 'skills', d, 'SKILL.md')
1618
if (!existsSync(f)) continue
17-
for (const m of readFileSync(f, 'utf8').matchAll(/shadow-dev\s+([a-z][\w-]*(?:\s+[a-z][\w-]*){0,2})/g)) {
19+
for (const m of readFileSync(f, 'utf8').matchAll(/shadow-dev[^\S\n]+([a-z][\w-]*(?:[^\S\n]+[a-z][\w-]*){0,2})/g)) {
1820
const words = m[1].replace(/\//g, ' ').split(/\s+/).filter(Boolean)
1921
const cand = [words.slice(0, 3).join('.'), words.slice(0, 2).join('.'), words[0]]
2022
const key = cand.find(k => set.has(k)) || words.slice(0, 2).join('.') + ' (未声明)'

‎shadow-docs/changes/20261009-build-artifact-capability-gate/brief.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
"workflow": {
3636
"operation": null,
3737
"checkpoint": "pr:36",
38-
"planHash": "8dbcfa338002f94e1b05eab829a3697b544aca968b9bc0e31c821cf0e947bbee",
38+
"planHash": "ad730296a2cf1ffc98202cb2de73f245cfc738980639921f9a9b3cd3fd3f5d02",
3939
"updatedAt": null,
4040
"lastError": null,
4141
"issuePlan": {
@@ -98,7 +98,7 @@
9898

9999
## 结果
100100

101-
- 实际耗时: 见交付段(单条流水线一次跑完)
101+
- 交付: issue #35 · PR #36(squash 合并)· Release v6.5.0
102102
- 验证(M 级=冒烟 + 既有测试保持绿 + 门的两条路径;按裁决不写 TDD):
103103
- **门正例**:`npm run check:requires` → `undeclared=[] missing-in-cli=[]`,`✓ skills ⊆ requiresCommands ⊆ CLI 命令目录`(CLI=v1.5.0,catalog=46 键,声明=29 键)。
104104
- **门负例**(关键——证明门不是摆设):把声明里的 `worktree.inspect` 删掉后重跑 → 退出码 **1**,并点名 `undeclared=[worktree.inspect (未声明)]`。
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
---
2+
{
3+
"schema": "shadow-dev/v1",
4+
"name": "20261009-fix-distribution-gate-regex",
5+
"type": "fix",
6+
"scope": "scripts",
7+
"status": "published",
8+
"baseBranch": "main",
9+
"branch": "fix/20261009-fix-distribution-gate-regex",
10+
"files": [
11+
"knowledge/distribution-capability-contract.md",
12+
"package.json",
13+
"scripts/check-requires.mjs"
14+
],
15+
"github": {
16+
"repository": "stack-wuh/shadow-dev-workflow",
17+
"issue": null,
18+
"issueUrl": null,
19+
"pullRequest": 37,
20+
"pullRequestUrl": "https://github.com/stack-wuh/shadow-dev-workflow/pull/37"
21+
},
22+
"review": {
23+
"conclusion": "passed",
24+
"verifiedCommit": "c5319bb789131cf33377f93e593c080a2e7266d9",
25+
"verifiedAt": "2026-10-09T15:02:51.214Z"
26+
},
27+
"workflow": {
28+
"operation": null,
29+
"checkpoint": "pr:37",
30+
"planHash": "8a160fc3ce8c2fe18c2368cb4d61fedf1f6fb3971a4c46aed99c9e15b94c9fdf",
31+
"updatedAt": null,
32+
"lastError": null,
33+
"release": {
34+
"files": [
35+
"package.json",
36+
"scripts/check-requires.mjs",
37+
"shadow-docs/changes/20261009-build-artifact-capability-gate/brief.md",
38+
"shadow-docs/changes/20261009-fix-distribution-gate-regex/"
39+
],
40+
"message": "fix(scripts): 一致性门禁止跨行吞引用(负例必判红)+ 复原 npm test 两文件",
41+
"title": "[fix] 一致性门假绿修复:引用扫描禁止跨行 + npm test 复原",
42+
"body": ""
43+
}
44+
},
45+
"knowledge": {
46+
"action": "更新",
47+
"target": "knowledge/distribution-capability-contract.md",
48+
"reason": "卡片验证方式补入「门负例必跑 + 引用扫描禁止跨行」这条踩出来的稳定教训"
49+
}
50+
}
51+
---
52+
53+
# 一致性门不再跨行吞引用:负例必判红 + npm test 覆盖两个测试文件
54+
55+
## 动机
56+
`check-requires.mjs` 的引用正则用了可跨行的 `\s+`,把下一条 `shadow-dev` 的 `shadow-` 前缀一起吃掉(实测 `repo inspect\nshadow-dev` 成为一组),导致 `worktree inspect` 等引用**从未被统计**——门会假绿,而假绿的门比没有门更危险(它给「pin 与声明已互校」的错误信心)。同一批改动还把 `scripts.test` 写成 `node --test test/`,在本机 node 22 下测试发现失败(`# tests 1 # fail 1`),main 上现在是红的。
57+
58+
## 复杂度评级
59+
- **评级:** S
60+
- **理由:** ①契约变更:无(门的判定逻辑修正与 npm script 复原,不改任何命令行为);②触及面:单个脚本 + 一行 manifest;③可发现性:门正/负例与测试脚本立刻可判红。
61+
- **期望验证深度:** code-read + 三条必判红/判绿冒烟(按 2026-10-09 裁决不写 TDD)
62+
63+
## 引用规范
64+
- `knowledge/distribution-capability-contract.md`
65+
- 当前结论: 声明与消费两级包含、差集非空即判红;改 pin 后必须跑门。
66+
- 适用 scope: scripts/check-requires.mjs, package.json
67+
- `norms/tdd-verification.md`:S 级不创建测试文件;既有测试必须保持绿。
68+
69+
## 决策
70+
- **选型:** 正则改为禁止跨行(`[^\S\n]+`),并把两条判红路径都实跑验证;`scripts.test` 回到显式两文件。
71+
- **对比方案:** 加测试文件钉住正则——未选(裁决:不写 TDD),改以「门负例必判红」冒烟作为交付证据,并写进卡片的验证方式。
72+
- **理由:** 门是唯一保证 pin/声明不互相冒充的机制,它的假绿路径必须被当作 bug 当场证伪。
73+
74+
## 任务
75+
### Phase 1
76+
- [x] 修正引用正则 — `scripts/check-requires.mjs` — 禁止跨行匹配;重跑正例,引用数应上升且 `undeclared=[] missing-in-cli=[]`
77+
- [x] 两条判红冒烟 — `scripts/check-requires.mjs` — (a) 从声明删一键 → 必 exit 1 且点名 `undeclared`;(b) 声明一个不存在键 → 必 exit 1 且点名 `missing-in-cli`(这就是 pin/CLI 过旧的判红路径)
78+
- [x] 复原测试入口 — `package.json` — `scripts.test` = `node --test test/install-cli.test.mjs test/pack.test.mjs`,跑绿
79+
80+
## 非目标
81+
- 不动 hooks/pin/两轨形态;不加 CI workflow(独立 change)
82+
83+
## 结果
84+
- 实际耗时: ≈5 分钟
85+
- 验证(S 级=走查 + 三条冒烟):门正例(引用数上升、两级差集为空);负例 a 删一键 → exit 1 且 undeclared 点名;负例 b 声明不存在键 → exit 1 且 missing-in-cli 点名;`npm test` 两文件恢复全绿。
86+
- 影响面自查:上一批(PR #36)把两条假绿带进了 main——门从未真正判过红、`npm test` 在 main 上是红的。本 change 是它自己的第一个真 bug。
87+
88+
## 知识评估
89+
- **预期影响:** 更新
90+
- **候选卡片:** `knowledge/distribution-capability-contract.md`
91+
- **理由:** 卡片「验证方式」需补一条硬要求:**一致性门交付前必须跑负例证明它会判红**——这是本次踩出来的稳定教训,属原位更新不另立新卡。

0 commit comments

Comments
 (0)