sillyspec 3.25.9 → 3.25.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/.claude/skills/sillyspec-auto/SKILL.md +8 -13
  2. package/.claude/skills/sillyspec-brainstorm/SKILL.md +8 -6
  3. package/.claude/skills/sillyspec-continue/SKILL.md +3 -3
  4. package/.claude/skills/sillyspec-doctor/SKILL.md +1 -1
  5. package/.claude/skills/sillyspec-execute/SKILL.md +10 -4
  6. package/.claude/skills/sillyspec-plan/SKILL.md +1 -1
  7. package/.claude/skills/sillyspec-verify/SKILL.md +1 -1
  8. package/README.md +9 -0
  9. package/package.json +2 -2
  10. package/src/change-list.js +11 -8
  11. package/src/change-risk-profile.js +22 -0
  12. package/src/db.js +160 -159
  13. package/src/dispatch/backends/local-agent.js +152 -0
  14. package/src/dispatch/backends/sillyhub-mcp.js +242 -0
  15. package/src/dispatch/probe.js +208 -0
  16. package/src/dispatch/strategy.js +121 -0
  17. package/src/doctor-diagnostics.js +19 -25
  18. package/src/fs-atomic.js +69 -69
  19. package/src/git-helper.js +66 -0
  20. package/src/hooks/worktree-guard.js +64 -55
  21. package/src/index.js +176 -34
  22. package/src/init.js +7 -14
  23. package/src/machine-interface.js +54 -19
  24. package/src/migrate.js +14 -4
  25. package/src/modules.js +16 -5
  26. package/src/progress/change-registry.js +72 -70
  27. package/src/progress/consistency-doctor.js +71 -14
  28. package/src/progress/shared.js +6 -3
  29. package/src/progress/stage-machine.js +61 -65
  30. package/src/progress/step-store.js +62 -67
  31. package/src/progress.js +155 -233
  32. package/src/quicklog.js +13 -5
  33. package/src/run/command.js +65 -37
  34. package/src/run/complete-handlers.js +1005 -889
  35. package/src/run/complete.js +115 -208
  36. package/src/run/concurrent-detect.js +132 -0
  37. package/src/run/gates.js +289 -17
  38. package/src/run/prompt.js +22 -68
  39. package/src/run/quick-audit.js +10 -9
  40. package/src/run/shared.js +648 -600
  41. package/src/run/stage.js +43 -24
  42. package/src/scan-postcheck.js +9 -31
  43. package/src/sillyhub-mcp/client.js +389 -0
  44. package/src/spec-dir-typo.js +71 -0
  45. package/src/stage-contract-engine.js +22 -1
  46. package/src/stage-contract-spec.js +11 -4
  47. package/src/stage-contract.js +26 -3
  48. package/src/stage-review.js +13 -9
  49. package/src/stages/archive.js +4 -6
  50. package/src/stages/brainstorm-auto.js +26 -20
  51. package/src/stages/brainstorm.js +29 -5
  52. package/src/stages/cmd-existence.js +145 -0
  53. package/src/stages/doctor.js +9 -6
  54. package/src/stages/execute.js +61 -20
  55. package/src/stages/plan-postcheck.js +152 -0
  56. package/src/stages/plan.js +16 -31
  57. package/src/stages/quick.js +1 -1
  58. package/src/stages/scan.js +9 -3
  59. package/src/stages/status.js +0 -1
  60. package/src/stages/verify.js +12 -7
  61. package/src/sync.js +4 -4
  62. package/src/task-review.js +30 -1
  63. package/src/verify-postcheck.js +933 -862
  64. package/src/version.js +19 -0
  65. package/src/worktree-apply.js +85 -68
  66. package/src/worktree-deps.js +89 -5
  67. package/src/worktree.js +213 -111
  68. package/templates/prompts/taskcard-rules.md +27 -0
  69. package/templates/prompts/verify-probes.md +3 -3
  70. package/.claude/skills/sillyspec-propose/SKILL.md +0 -87
  71. package/src/stages/propose.js +0 -181
@@ -59,24 +59,19 @@ sillyspec run auto --input "<用户需求>" [--mode <模式>]
59
59
  | `--spec-dir <path>` | 指定规范目录 |
60
60
  | `--non-interactive` | CI/脚本下禁用交互 |
61
61
 
62
- ## 阶段审核门控
62
+ ## 阶段审核门控(Stage Review Gate)
63
63
 
64
- **brainstorm 完成后**,评估需求复杂度(基于 design.md 的模块拆分、批量操作、多角色交互特征):
64
+ 审核发生在 brainstorm / plan / execute 各阶段的 review 步骤,**分级由 CLI 按变更规模自动判定**(不是 agent 凭关键词或复杂度启发式判断):
65
65
 
66
- | 复杂度 | 审核策略 |
67
- |--------|---------|
68
- | 简单(无拆分、无批量) | 不审核,直接进入 plan |
69
- | 中等(有拆分或批量) | 启动 1 个审核子代理(QA 视角)审查 design.md |
70
- | 复杂(拆分 + 批量/多角色) | 启动 2-3 个审核子代理多角度审查 |
66
+ - **tier=self**(变更 ≤3 文件):当前 agent 自审,直接产 review.json。
67
+ - **tier=independent**(变更 >3 文件):必须派发**独立 QA 子代理**(独立上下文,不共享实现者分析)产 review.json。
71
68
 
72
- 多角度审核子代理分工:
73
- - **架构师** — 设计合理性、技术选型 trade-off、模块划分
74
- - **安全专家** — 安全隐患、权限设计、数据校验
75
- - **QA 专家** — 需求覆盖率、边界场景、验收标准
69
+ CLI 会在 review 步骤注入:完整 JSON schema 表 + 示例 + docHash 算法 + 自动决策 checklist(AC-001 起,逐条核验公共 API / schema / 鉴权 / 文件边界 / 依赖 / 核心模块 / 兼容性 / 业务等维度)。你按**实际注入的契约与 tier 指令**执行:
76
70
 
77
- 审核流程:暂停提示复杂度 → 用户确认 → 启动子代理读 design/requirements/tasks → 汇总问题 → 询问是否修改 → 需要则修复重审,不需要则进下一阶段。
71
+ - checklist 全 ✅ 且方案唯一合理 → AUTO_DECIDED,推进下一阶段
72
+ - checklist 有 ❌(影响架构/数据/接口/权限/兼容性/业务)→ 暂停,用 AskUserQuestion 让用户选择
78
73
 
79
- **plan 完成后**,同样评估复杂度启动审核(项目经理审拆解粒度、工程师审可行性、QA 审验收标准)。
74
+ **不要**自行编造"简单/中等/复杂 → N 个审核子代理"规则——审核子代理数量由 tier 决定(self=0 额外子代理,independent=1 个独立 QA),不是复杂度启发式;以 CLI 实际注入的 tier 与 checklist 为准。
80
75
 
81
76
  ## 关键规则
82
77
 
@@ -50,16 +50,18 @@ sillyspec run brainstorm --done --answer "..." --output "..." # 一步完成
50
50
 
51
51
  > 自动去重:若前置 step 已对同一问题(waitReason 归一化后相同)确认过,后续重复 wait 会自动跳过,无需再 `--wait`。
52
52
 
53
- - **方式一(推荐)**:AI 自行与用户交互后,一步完成:
54
- ```bash
55
- sillyspec run brainstorm --done --change <名> --answer "用户回答" --output "需求已澄清"
56
- ```
57
- - **方式二**:分步——先 `--wait` 记录等待,再 `--continue --answer`,最后 `--done`:
53
+ - **方式一(推荐)**:分步——先 `--wait` 记录等待,让用户亲眼看到 CLI 打出的选项再作答,再 `--continue --answer`,最后 `--done`:
58
54
  ```bash
59
55
  sillyspec run brainstorm --wait --change <名> --reason "等待用户回答" --output "探索问题"
60
56
  sillyspec run brainstorm --continue --answer "用户回答" --change <名>
61
57
  sillyspec run brainstorm --done --change <名> --output "需求已澄清"
62
58
  ```
59
+ - **方式二**:AI 自行与用户交互后,一步完成(仅在用户已在对话中明确给出答案、无需再走 CLI 等待展示时用):
60
+ ```bash
61
+ sillyspec run brainstorm --done --change <名> --answer "用户回答" --output "需求已澄清"
62
+ ```
63
+
64
+ > ⚠️ 两种方式都要求 `--answer` 是**用户真实的回答**,不是你替用户编的回答。`requiresWait` 门只校验 `--answer` 非空,挡不住「AI 伪造用户回答」——所以对方案选择/设计确认这类关键决策,优先用方式一让用户亲手作答,而不是 AI 中继一句话带过。
63
65
 
64
66
  ## 阶段流转
65
67
 
@@ -99,7 +101,7 @@ brainstorm 在 `tier=independent` 规模下除 design.md 等四件套外,还
99
101
  ```
100
102
 
101
103
  - `docHash` = `sha256(主审查文档内容)`(hex)—— brainstorm 主文档是 `design.md`(即 `reviewedFiles[0]`)。CLI 重算 sha256 比对,不符判伪造(fail-closed)。改 design.md 后须重算 docHash。`tier=self`(≤3 文件)降级为当前 agent 自审,不强制独立子代理。
102
- - 运行时 CLI 通过 `{REVIEW_JSON_CONTRACT}` 注入精确 schema+示例,以注入版为权威逐字模板。
104
+ - 运行时 CLI 会把精确 schema 表 + 完整 JSON 示例 + docHash 算法注入到该步 prompt,以你实际收到的注入版契约为权威逐字模板。
103
105
 
104
106
  ## 铁律
105
107
 
@@ -16,15 +16,15 @@ description: 自动判断并执行下一步
16
16
 
17
17
  2. .sillyspec/changes/ 有进行中的变更?
18
18
  2a. 没有任何文件 → 提示检查 proposal 是否需要完善
19
- 2b. 没有 design.md → 提示补充 design
20
- 2c. 没有 tasks.md → 执行 /sillyspec:propose(补全规范)
19
+ 2b. 没有 design.md → 提示补充 design(运行 /sillyspec:brainstorm 推进到设计产物步)
20
+ 2c. 没有 tasks.md → 执行 /sillyspec:brainstorm(规范文件 proposal/requirements/tasks 由 brainstorm 末步生成)
21
21
  2d. 有 tasks.md 但没有 plan.md → 执行 /sillyspec:plan
22
22
  2e. tasks.md 有未完成项 + 有计划文件 → 执行 /sillyspec:execute
23
23
  2f. tasks.md 全完成 + 没验证 → 执行 /sillyspec:verify
24
24
  2g. 已验证通过 → 执行 /sillyspec:archive
25
25
 
26
26
  3. 有设计文档但没有对应变更?
27
- → 提示运行 /sillyspec:propose <name>
27
+ → 提示运行 /sillyspec:brainstorm(基于设计文档建立变更并生成规范文件)
28
28
 
29
29
  4. 有 .sillyspec/docs/*/scan/ 但没有进行中的工作?
30
30
  → 提示运行 /sillyspec:brainstorm "你的想法"
@@ -62,7 +62,7 @@ sillyspec runtime list # 枚举 .si
62
62
  >
63
63
  > `--cleanup-remnant` 清理 init/平台切换残留的 0 字节空 db(占位但无数据)。默认 dry-run 只报告,`--confirm` 才删。绝不删有内容的 db。
64
64
  >
65
- > `runtime list` 是只读枚举:列出 `.sillyspec/.runtime/` 下的 db、doctor-diagnosis.json、workflow-runs/、gate-status.json、user-inputs.md 等产物及用途。多会话/压缩后想知道「我手上有哪些证据文件」时用。加 `--json` 程序化读取。
65
+ > `runtime list` 是只读枚举:列出 `.sillyspec/.runtime/` 下的 db、doctor-diagnosis.json、workflow-runs/、user-inputs.md 等产物及用途。多会话/压缩后想知道「我手上有哪些证据文件」时用。加 `--json` 程序化读取。
66
66
 
67
67
  ## 铁律
68
68
 
@@ -42,7 +42,7 @@ sillyspec run execute --reopen --from-step N # 重新打开已完成阶段修
42
42
  - worktree 路径在步骤 prompt 中输出(`worktreePath`),后续子代理的 cwd 必须设为该路径
43
43
  - **禁止跳过 worktree 或在主仓库直接写代码**
44
44
  - worktree 创建失败时 CLI 报错退出,排查后重试
45
- - dirty 状态/未提交文件**不影响** worktree 创建和进入,直接按 CLI 输出的路径操作,不要自行检查 git 状态
45
+ - worktree 创建/进入不依赖工作区 git 状态(dirty/未提交文件均可):直接按 CLI 输出的路径操作,无需自行检查 git 状态;`sillyspec worktree apply` 步以命令实际输出为准(apply 会校验 dirty,按输出处理)
46
46
  - create 时若检测到 base 落后/分叉 `origin/<默认分支>`,CLI 会醒目报告(⚠️「落后 N 个 commit」+ 对齐命令),**不阻断** execute。看到此报告时评估是否提示用户先对齐 main,但**不要自行 fetch/ff**——对齐是用户/主仓库的显式动作
47
47
 
48
48
  ### 依赖门控(depsStatus)
@@ -88,7 +88,7 @@ execute 完成时,每个 task 必须有 `review.json` 且 verdict 通过,否
88
88
  execute 还有**第二道**独立的 stage 级审查:除逐 task review.json 外,整个 execute 阶段完成还需一个 stage 级 `review.json`(在 "完成确认"/acceptance 步骤产出)。CLI `Stage Review Gate` 硬校验其 schema 与 `docHash` 真实性。
89
89
 
90
90
  - 路径:`.sillyspec/.runtime/stage-reviews/execute-review-<stage-review-run-id>/review.json`(目录可能不存在需手建;run-id 由该步 `--done` prompt 输出指定)。marker 文件 `.runtime/current-stage-review-run-id-execute-<变更名>`。
91
- - 字段(`schemaVersion:1`,`reviewType=acceptance` —— 区别于 brainstorm/plan/propose 的 `"design"`):
91
+ - 字段(`schemaVersion:1`,`reviewType=acceptance` —— 区别于 brainstorm/plan 的 `"design"`):
92
92
 
93
93
  ```json
94
94
  {
@@ -106,11 +106,17 @@ execute 还有**第二道**独立的 stage 级审查:除逐 task review.json
106
106
  }
107
107
  ```
108
108
 
109
- - `docHash` = `sha256(主审查文档内容)`(hex)—— execute 主审查文档是 `design.md`,即 `reviewedFiles[0]`。CLI 会重算 sha256 比对,不符判伪造(fail-closed);找不到主文档也 fail。**改 design.md 后须重算 docHash 再写**,可用 `sillyspec run execute --done` 触发的 prompt 注入版契约(`{REVIEW_JSON_CONTRACT}`)逐字改值。
109
+ - `docHash` = `sha256(主审查文档内容)`(hex)—— execute 主审查文档是 `design.md`,即 `reviewedFiles[0]`。CLI 会重算 sha256 比对,不符判伪造(fail-closed);找不到主文档也 fail。**改 design.md 后须重算 docHash 再写**,可用 `sillyspec run execute --done` 触发的 prompt 注入版契约(运行时注入的 schema 表 + JSON 示例 + docHash 算法)逐字改值。
110
110
  - `tier=independent` 时必须由独立 QA 子代理产出该 review.json(独立上下文,不共享实现者分析);`tier=self`(变更 ≤3 文件)降级为当前 agent 自审。
111
111
  - 该 acceptance review 同时覆盖"代码审查"视角,后续代码审查步骤仅需轻量复审。
112
112
 
113
- > 运行时 CLI 会把精确 schema 表 + 完整 JSON 示例 + docHash 算法通过 `{REVIEW_JSON_CONTRACT}` 占位符注入到该步 prompt(源码 `src/stage-review.js: renderReviewJsonContract()`)。本段为常驻摘要;以运行时注入的契约为权威逐字模板。
113
+ > 运行时 CLI 会把精确 schema 表 + 完整 JSON 示例 + docHash 算法注入到该步 prompt。本段为常驻摘要;以你实际收到的注入版契约为权威逐字模板。
114
+
115
+ ## 派发模式(SillyHub MCP,可选)
116
+
117
+ `execute` Wave 内的子代理默认用本机 Agent tool 执行。若消费方配置了 SillyHub MCP(`SILLYHUB_MCP_URL` / `SILLYHUB_MCP_TOKEN`),Wave 步骤 prompt 运行时可能注入一段 SillyHub 派发指令——**出现就照其中的指令执行**(创建 mission / dispatch_worker / 轮询结果 / 本机兜底),**没出现就用本机 Agent tool**。未配置 MCP 时完全不注入,行为与无此机制一致。
118
+
119
+ 可选:`sillyspec dispatch probe` 查看 SillyHub 是否可用。
114
120
 
115
121
  ## worktree 子命令(execute 相关)
116
122
 
@@ -70,7 +70,7 @@ plan 的步骤是动态的:`generate_plan`(生成分级计划)→ `review_
70
70
  ```
71
71
 
72
72
  - `docHash` = `sha256(主审查文档内容)`(hex)—— plan 主文档是 `plan.md`(`reviewedFiles[0]`)。CLI 重算 sha256 比对,不符判伪造(fail-closed)。改 plan.md 后须重算 docHash。`tier=self`(≤3 文件)降级为当前 agent 自审。
73
- - 运行时 CLI 通过 `{REVIEW_JSON_CONTRACT}` 注入精确 schema+示例,以注入版为权威逐字模板。
73
+ - 运行时 CLI 会把精确 schema 表 + 完整 JSON 示例 + docHash 算法注入到该步 prompt,以你实际收到的注入版契约为权威逐字模板。
74
74
 
75
75
  ### 契约门控(阻断完成)
76
76
 
@@ -44,7 +44,7 @@ verify 是只读阶段(**禁止改代码/改 git 状态**,只检查 + 写报
44
44
  - **必须产出 `verify-result.md`**——不存在则阻断完成(不能跳过报告直接 `--done`)
45
45
  - **结论为 `FAIL` 则阻断完成**——不能带着 FAIL 标记 verify 完成
46
46
  - **`integration-critical` / `deployment-critical` 变更**(design/plan 含 daemon/session/lease/lifecycle 等关键词):结论 PASS WITH NOTES 降级为 FAIL,必须有真实集成证据(Runtime Evidence section)——该证据为 Agent 自报告,CLI 仅校验其字面存在、不独立运行时核验,须真实执行过
47
- - `verify-required-evidence.json`(execute 写入)中每条 missing evidence → 阻断
47
+ - `verify-required-evidence.json`(execute 写入,schema `{items:[{task,verdict,evidence:[]}]}`)中 cannot_verify 任务未在 verify-result.md 体现 → **advisory warn(不阻断归档)**;evidence 是否真满足(satisfied/missing/partial)由 agent 在 verify-result.md 自报告,CLI 只查任务被提及、不替你语义判定。结论能否 PASS 由你诚实判定(有 missing evidence 不应 PASS)。
48
48
 
49
49
  被阻断时 CLI 打印 ❌ 校验失败,不会提示"验证通过"。修复 `verify-result.md` 后重新 `--done`。
50
50
 
package/README.md CHANGED
@@ -57,6 +57,15 @@ npx sillyspec init --interactive # 完整引导
57
57
 
58
58
  > 💡 启动 AI 时推荐使用跳过权限模式(如 `claude --dangerously-skip-permissions`)。SillySpec 会频繁执行 git、文件读写、校验脚本等操作,逐个批准会打断节奏——这也是 GSD / OpenSpec 的预期使用方式。
59
59
 
60
+ ## 平台支持
61
+
62
+ SillySpec 进度库使用 SQLite 持久化(基于 better-sqlite3 原生绑定)。安装支持情况如下:
63
+
64
+ - **主流平台(prebuilt 零编译安装)**:Node.js >= 18 的 Linux x64、macOS x64 / macOS arm64、Windows x64。安装时直接下载预编译二进制,无需本地 C++ 工具链。
65
+ - **边缘平台不保证**:Alpine(musl libc)、Windows arm64、BSD 等平台可能没有对应的 prebuilt 二进制,安装时可能触发 node-gyp 从源码编译(此时需要本机具备 C++ 编译工具链)。
66
+
67
+ 如遇边缘平台编译失败,建议在受支持的平台或容器(如 Debian/Ubuntu 基镜像)中运行。
68
+
60
69
  ## 从哪里开始
61
70
 
62
71
  | 场景 | 命令 |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sillyspec",
3
- "version": "3.25.9",
3
+ "version": "3.25.11",
4
4
  "description": "SillySpec CLI — 流程状态机,让 AI 严格按步骤来",
5
5
  "icon": "logo.jpg",
6
6
  "homepage": "https://sillyspec.ppdmq.top/",
@@ -29,12 +29,12 @@
29
29
  },
30
30
  "dependencies": {
31
31
  "@inquirer/prompts": "^7.10.1",
32
+ "better-sqlite3": "^11.0.0",
32
33
  "chalk": "^5.6.2",
33
34
  "chokidar": "^4.0",
34
35
  "js-yaml": "^4.2.0",
35
36
  "open": "^10.1",
36
37
  "ora": "^9.3.0",
37
- "sql.js": "^1.14.1",
38
38
  "ws": "^8.18"
39
39
  }
40
40
  }
@@ -152,7 +152,7 @@ const INCIDENTAL_RE = /顺带修复|附带修复|顺带|drive-?by|incidental/i
152
152
  * ① 表格:`| 操作 | 文件路径 | 说明 |`(brainstorm 模板默认)
153
153
  * ② 分类列表:`### 新增文件` / `### 修改文件` / `### 不修改文件` 下的 `- path`
154
154
  * 表头列顺序自适应(定位「文件/路径/file/path」列,列顺序写反时不会把操作名当路径);
155
- * 忽略 `.sillyspec/` 与占位符(`—`/`-`/`N/A`/`无`);「不修改/暂缓」子段下的路径会被排除;
155
+ * 忽略 `.sillyspec/`(keepSillyspecDocs=true 时保留 `.sillyspec/docs/`)与占位符(`—`/`-`/`N/A`/`无`);「不修改/暂缓」子段下的路径会被排除;
156
156
  * CRLF 容错。incidental 嗅探:表格非路径列(说明列)+ 路径 cell 原始值(剥注释前的括号内容)+ 列表项原文。
157
157
  *
158
158
  * 内核函数:parseFileChangeList(Set 包装,向后兼容)与 parseFileChangeListDetailed 共用,
@@ -160,7 +160,7 @@ const INCIDENTAL_RE = /顺带修复|附带修复|顺带|drive-?by|incidental/i
160
160
  * @param {string} designMdPath - design.md 文件路径
161
161
  * @returns {Array<{ path: string, operation: string|null, incidental: boolean }>}(顺序按首次出现,exclude 子段移除)
162
162
  */
163
- function _parseFileListDetailed(designMdPath) {
163
+ function _parseFileListDetailed(designMdPath, { keepSillyspecDocs = false } = {}) {
164
164
  if (!designMdPath || !existsSync(designMdPath)) return []
165
165
 
166
166
  const content = readFileSync(designMdPath, 'utf8').replace(/\r\n/g, '\n')
@@ -219,7 +219,7 @@ function _parseFileListDetailed(designMdPath) {
219
219
  const filePath = normalizePath(cells[pathColIdx] || '')
220
220
  // 列定位兜底:取到纯操作词(表头未命中且列顺序异常)→ 跳过,避免把「修改」当路径
221
221
  if (/^(新增|修改|删除|重命名|new|modify|update|delete|create|rename)$/i.test(filePath)) continue
222
- if (isPlaceholder(filePath) || filePath.startsWith('.sillyspec/')) continue
222
+ if (isPlaceholder(filePath) || (filePath.startsWith('.sillyspec/') && !(keepSillyspecDocs && filePath.startsWith('.sillyspec/docs/')))) continue
223
223
  if (!looksLikePath(filePath)) continue // 脏描述兜底:丢弃非路径自由文本(防虚高 fileCount)
224
224
  // operation:操作列 cell 分类(无操作列 → null)
225
225
  const operation = opColIdx >= 0 ? classifyOperation(cells[opColIdx] || '') : null
@@ -235,7 +235,7 @@ function _parseFileListDetailed(designMdPath) {
235
235
  const listItem = line.match(/^\s*-\s+(.+)/)
236
236
  if (listItem) {
237
237
  const filePath = normalizePath(listItem[1])
238
- if (isPlaceholder(filePath) || filePath.startsWith('.sillyspec/')) continue
238
+ if (isPlaceholder(filePath) || (filePath.startsWith('.sillyspec/') && !(keepSillyspecDocs && filePath.startsWith('.sillyspec/docs/')))) continue
239
239
  if (!looksLikePath(filePath)) continue // 脏描述兜底
240
240
  const incidental = INCIDENTAL_RE.test(listItem[1])
241
241
  if (listMode === 'exclude') { entries.delete(filePath); continue }
@@ -249,10 +249,12 @@ function _parseFileListDetailed(designMdPath) {
249
249
  /**
250
250
  * 从 design.md 解析文件变更清单(路径集合,向后兼容)。
251
251
  * @param {string} designMdPath - design.md 文件路径
252
+ * @param {string} designMdPath - design.md 文件路径
253
+ * @param {{ keepSillyspecDocs?: boolean }} [opts] - keepSillyspecDocs=true 时保留 `.sillyspec/docs/`(dogfood 模块文档=交付物,apply gate 需识别;默认 false 跳过全部 .sillyspec/ 保持 fileCount 判档不变)
252
254
  * @returns {Set<string>} 文件路径集合(相对路径,如 "src/worktree.js")
253
255
  */
254
- export function parseFileChangeList(designMdPath) {
255
- return new Set(_parseFileListDetailed(designMdPath).map(e => e.path))
256
+ export function parseFileChangeList(designMdPath, opts) {
257
+ return new Set(_parseFileListDetailed(designMdPath, opts).map(e => e.path))
256
258
  }
257
259
 
258
260
  /**
@@ -260,8 +262,9 @@ export function parseFileChangeList(designMdPath) {
260
262
  * operation 供 verify 删除探针对账(声明「新增/修改」却整文件删除 = 高风险);
261
263
  * incidental 供 assess allowed_paths 豁免。
262
264
  * @param {string} designMdPath - design.md 文件路径
265
+ * @param {{ keepSillyspecDocs?: boolean }} [opts] - 同 parseFileChangeList
263
266
  * @returns {Array<{ path: string, operation: string|null, incidental: boolean }>}
264
267
  */
265
- export function parseFileChangeListDetailed(designMdPath) {
266
- return _parseFileListDetailed(designMdPath)
268
+ export function parseFileChangeListDetailed(designMdPath, opts) {
269
+ return _parseFileListDetailed(designMdPath, opts)
267
270
  }
@@ -92,6 +92,28 @@ export const INTEGRATION_FILE_PATTERNS = [
92
92
  /startup/i,
93
93
  ]
94
94
 
95
+ /**
96
+ * task 级「端到端/deployment-critical」文本判定(execute 批量完成 autoCheckPlanFromReviews 用)。
97
+ *
98
+ * 聚焦需要真实集成/启动验证的 task,区别于 change 级 INTEGRATION_CRITICAL_PATTERNS(含 backend/session
99
+ * 等泛词——task 级用会误伤普通后端 task)。命中端到端集成语义(端到端/真实集成/daemon↔backend/
100
+ * integration test/e2e)或部署启动入口(cli.ts/main.ts/entrypoint/server/bootstrap/startup/docker)。
101
+ * 坑 execute-batch-complete-endtoend-checkbox:这类 task 的 review cannot_verify 不算 checked,
102
+ * 阻断 execute 批量完成(必须 pass),防端到端未真验就被批量放行(verify integration-evidence 兜底外的
103
+ * execute 侧前置门)。
104
+ * @param {string} text task 描述文本(plan.md task 行 + tasks/task-XX.md 内容)
105
+ * @returns {boolean}
106
+ */
107
+ const END_TO_END_TASK_KEYWORDS = [
108
+ /端到端/, /真实集成/, /daemon.*backend/i, /integration\s*test/i, /e2e\s*test/i,
109
+ /runtime\s*evidence/i, /运行时证据/,
110
+ /\bcli\.ts\b/i, /\bmain\.ts\b/i, /\bentrypoint\b/i, /\bserver\.(js|ts)\b/i,
111
+ /\bbootstrap\b/i, /\bstartup\b/i, /启动/, /\bdockerfile\b/i, /\bdocker.?compose\b/i,
112
+ ]
113
+ export function isEndToEndTaskText(text = '') {
114
+ return END_TO_END_TASK_KEYWORDS.some(re => re.test(text))
115
+ }
116
+
95
117
  // ============ 核心检测函数 ============
96
118
 
97
119
  /**