agentic-flow-kit 1.7.16 → 1.8.0

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 (160) hide show
  1. package/README.md +11 -7
  2. package/modules/hosts/claude/commands/wf-build.md +1 -1
  3. package/modules/hosts/claude/commands/wf-maintain.md +1 -1
  4. package/modules/hosts/claude/commands/wf-new-task.md +9 -8
  5. package/modules/hosts/claude/commands/wf-plan.md +1 -1
  6. package/modules/hosts/claude/commands/wf-review.md +1 -1
  7. package/modules/hosts/claude/commands/wf-test.md +1 -1
  8. package/modules/hosts/codex/commands/wf-build.md +1 -1
  9. package/modules/hosts/codex/commands/wf-maintain.md +1 -1
  10. package/modules/hosts/codex/commands/wf-new-task.md +9 -8
  11. package/modules/hosts/codex/commands/wf-plan.md +1 -1
  12. package/modules/hosts/codex/commands/wf-review.md +1 -1
  13. package/modules/hosts/codex/commands/wf-test.md +1 -1
  14. package/modules/hosts/cursor/commands/wf-build.md +1 -1
  15. package/modules/hosts/cursor/commands/wf-maintain.md +1 -1
  16. package/modules/hosts/cursor/commands/wf-new-task.md +9 -8
  17. package/modules/hosts/cursor/commands/wf-plan.md +1 -1
  18. package/modules/hosts/cursor/commands/wf-review.md +1 -1
  19. package/modules/hosts/cursor/commands/wf-test.md +1 -1
  20. package/modules/hosts/opencode/commands/wf-build.md +1 -1
  21. package/modules/hosts/opencode/commands/wf-maintain.md +1 -1
  22. package/modules/hosts/opencode/commands/wf-new-task.md +9 -8
  23. package/modules/hosts/opencode/commands/wf-plan.md +1 -1
  24. package/modules/hosts/opencode/commands/wf-review.md +1 -1
  25. package/modules/hosts/opencode/commands/wf-test.md +1 -1
  26. package/modules/hosts/trae/commands/wf-build.md +1 -1
  27. package/modules/hosts/trae/commands/wf-maintain.md +1 -1
  28. package/modules/hosts/trae/commands/wf-new-task.md +9 -8
  29. package/modules/hosts/trae/commands/wf-plan.md +1 -1
  30. package/modules/hosts/trae/commands/wf-review.md +1 -1
  31. package/modules/hosts/trae/commands/wf-test.md +1 -1
  32. package/package.json +1 -1
  33. package/src/cli.mjs +6 -2
  34. package/src/doctor.mjs +11 -2
  35. package/src/executor.mjs +25 -8
  36. package/src/executor.test.mjs +4 -1
  37. package/src/fresh-init.test.mjs +1 -1
  38. package/src/init.mjs +20 -3
  39. package/src/profiles.mjs +7 -3
  40. package/src/rule-budget.test.mjs +2 -2
  41. package/src/stack-profile.test.mjs +6 -0
  42. package/src/validate.mjs +6 -1
  43. package/src/validate.test.mjs +1 -1
  44. package/templates/.gitattributes +4 -1
  45. package/templates/AGENTS.md +2 -2
  46. package/templates/_agents/commands/build.md +1 -1
  47. package/templates/_agents/commands/maintain.md +1 -1
  48. package/templates/_agents/commands/new-task.md +9 -8
  49. package/templates/_agents/commands/plan.md +1 -1
  50. package/templates/_agents/commands/review.md +1 -1
  51. package/templates/_agents/commands/test.md +1 -1
  52. package/templates/_agents/engine-lock.json +130 -42
  53. package/templates/_agents/hooks/check-index-incremental.mjs +48 -0
  54. package/templates/_agents/hooks/check-pairing-incremental.mjs +66 -0
  55. package/templates/_agents/hooks/check-wiki-ledger.mjs +30 -0
  56. package/templates/_agents/lane-surfaces.txt +4 -1
  57. package/templates/_agents/level-hints.txt +1 -1
  58. package/templates/_agents/loop/papercut-debt/DESIGN.md +112 -0
  59. package/templates/_agents/mechanism-registry.md +27 -0
  60. package/templates/_agents/rule-budgets.txt +2 -2
  61. package/templates/_agents/scripts/agg-delegations.cjs +21 -3
  62. package/templates/_agents/scripts/agg-gate-stats.mjs +3 -3
  63. package/templates/_agents/scripts/agg-judgments.mjs +80 -0
  64. package/templates/_agents/scripts/agg-judgments.test.mjs +45 -0
  65. package/templates/_agents/scripts/archive-sweep.mjs +233 -0
  66. package/templates/_agents/scripts/archive-sweep.test.mjs +129 -0
  67. package/templates/_agents/scripts/check-attribution.mjs +37 -0
  68. package/templates/_agents/scripts/check-convergence.mjs +119 -0
  69. package/templates/_agents/scripts/check-engine-integrity.mjs +4 -1
  70. package/templates/_agents/scripts/check-funnel.mjs +56 -0
  71. package/templates/_agents/scripts/check-hygiene.mjs +5 -5
  72. package/templates/_agents/scripts/check-index-incremental.test.mjs +73 -0
  73. package/templates/_agents/scripts/check-lane-surface.mjs +2 -2
  74. package/templates/_agents/scripts/check-lane-surface.test.mjs +5 -5
  75. package/templates/_agents/scripts/check-ledger-invariant.mjs +403 -152
  76. package/templates/_agents/scripts/check-ledger-invariant.test.mjs +433 -3
  77. package/templates/_agents/scripts/check-loop-rev.test.mjs +8 -5
  78. package/templates/_agents/scripts/check-loop-unit.test.mjs +8 -0
  79. package/templates/_agents/scripts/check-loop.mjs +215 -34
  80. package/templates/_agents/scripts/check-loop.test.mjs +570 -49
  81. package/templates/_agents/scripts/check-prejudgment.mjs +59 -0
  82. package/templates/_agents/scripts/check-registry.mjs +45 -0
  83. package/templates/_agents/scripts/check-scope.mjs +96 -0
  84. package/templates/_agents/scripts/check-scope.test.mjs +96 -0
  85. package/templates/_agents/scripts/check-scripts-syntax.mjs +61 -0
  86. package/templates/_agents/scripts/check-scripts-syntax.test.mjs +72 -0
  87. package/templates/_agents/scripts/check-spec-verif.mjs +47 -0
  88. package/templates/_agents/scripts/compact-ledgers.mjs +3 -3
  89. package/templates/_agents/scripts/confirm-doc.mjs +114 -38
  90. package/templates/_agents/scripts/confirm-doc.test.mjs +180 -4
  91. package/templates/_agents/scripts/edit-face-check.mjs +5 -3
  92. package/templates/_agents/scripts/fill-intent.mjs +5 -3
  93. package/templates/_agents/scripts/fill-intent.test.mjs +19 -1
  94. package/templates/_agents/scripts/fill-plan.mjs +10 -6
  95. package/templates/_agents/scripts/fill-plan.test.mjs +19 -3
  96. package/templates/_agents/scripts/fill-spec.mjs +6 -3
  97. package/templates/_agents/scripts/fill-spec.test.mjs +12 -4
  98. package/templates/_agents/scripts/fixture-scripts.mjs +2 -2
  99. package/templates/_agents/scripts/fixture-scripts.test.mjs +6 -1
  100. package/templates/_agents/scripts/gate-checklist.mjs +6 -0
  101. package/templates/_agents/scripts/gate-seg.mjs +1 -1
  102. package/templates/_agents/scripts/gen-effective-policy.mjs +107 -0
  103. package/templates/_agents/scripts/gen-effective-policy.test.mjs +100 -0
  104. package/templates/_agents/scripts/gen-verify-evidence.mjs +107 -0
  105. package/templates/_agents/scripts/gen-verify-evidence.test.mjs +84 -0
  106. package/templates/_agents/scripts/gen-workflow-dashboard.mjs +8 -3
  107. package/templates/_agents/scripts/gen-workflow-dashboard.test.mjs +2 -1
  108. package/templates/_agents/scripts/gen-workflow-metrics.mjs +3 -3
  109. package/templates/_agents/scripts/git-core.mjs +45 -0
  110. package/templates/_agents/scripts/judgment-ledger.mjs +65 -0
  111. package/templates/_agents/scripts/judgment-ledger.test.mjs +129 -0
  112. package/templates/_agents/scripts/kb-search.mjs +19 -4
  113. package/templates/_agents/scripts/kb-search.test.mjs +33 -0
  114. package/templates/_agents/scripts/lane-surface-audit.mjs +143 -0
  115. package/templates/_agents/scripts/lane-surface-audit.test.mjs +93 -0
  116. package/templates/_agents/scripts/ledger-shards.mjs +307 -0
  117. package/templates/_agents/scripts/ledger-shards.test.mjs +339 -0
  118. package/templates/_agents/scripts/level-criteria.mjs +9 -10
  119. package/templates/_agents/scripts/level-criteria.test.mjs +7 -5
  120. package/templates/_agents/scripts/papercut-debt-controller.mjs +141 -0
  121. package/templates/_agents/scripts/papercut-debt-controller.test.mjs +127 -0
  122. package/templates/_agents/scripts/papercut-debt-sensor.mjs +170 -0
  123. package/templates/_agents/scripts/papercut-debt-sensor.test.mjs +146 -0
  124. package/templates/_agents/scripts/pipeline-run.mjs +6 -22
  125. package/templates/_agents/scripts/pipeline-run.test.mjs +22 -42
  126. package/templates/_agents/scripts/policy.mjs +28 -0
  127. package/templates/_agents/scripts/resolve-merge-conflicts.mjs +110 -0
  128. package/templates/_agents/scripts/resolve-merge-conflicts.test.mjs +87 -0
  129. package/templates/_agents/scripts/rewrite-file.mjs +133 -0
  130. package/templates/_agents/scripts/rewrite-file.test.mjs +148 -0
  131. package/templates/_agents/scripts/rule-budget.mjs +83 -0
  132. package/templates/_agents/scripts/run-tests.mjs +99 -0
  133. package/templates/_agents/scripts/run-tests.test.mjs +105 -0
  134. package/templates/_agents/scripts/solidify-task.test.mjs +1 -1
  135. package/templates/_agents/scripts/stage-gates.mjs +34 -12
  136. package/templates/_agents/scripts/trust-mode.mjs +4 -4
  137. package/templates/_agents/scripts/trust-mode.test.mjs +1 -1
  138. package/templates/_agents/scripts/verify.mjs +135 -58
  139. package/templates/_agents/scripts/verify.test.mjs +156 -47
  140. package/templates/_agents/scripts/wf-journal.mjs +8 -4
  141. package/templates/_agents/scripts/workflow-board-server.test.mjs +2 -2
  142. package/templates/_agents/scripts/workflow-enums.test.mjs +14 -5
  143. package/templates/_agents/scripts-test-exempt.txt +1 -0
  144. package/templates/_agents/skills/papercut-fix/SKILL.md +60 -0
  145. package/templates/_agents/skills/papercut-fix/references/response-template.md +81 -0
  146. package/templates/_agents/workflow-enums.txt +8 -1
  147. package/templates/_githooks/pre-commit +110 -90
  148. package/templates/_githooks/pre-merge-commit +27 -23
  149. package/templates/_githooks/pre-push +4 -3
  150. package/templates/_github/workflows/kit-ci.yml +4 -3
  151. package/templates/workflow/README.md +14 -7
  152. package/templates/workflow/incidents/_TEMPLATE.md +4 -1
  153. package/templates/workflow/intents/_TEMPLATE.md +4 -2
  154. package/templates/workflow/papercuts.md +2 -0
  155. package/templates/workflow/plans/_TEMPLATE.md +10 -5
  156. package/templates/workflow/regression-checklist.md +1 -0
  157. package/templates/workflow/specs/_TEMPLATE.md +17 -1
  158. package/templates/_agents/hooks/check-pairing-incremental.sh +0 -43
  159. package/templates/_agents/hooks/check-wiki-ledger.sh +0 -18
  160. package/templates/_agents/scripts/rule-budget.sh +0 -74
@@ -1,6 +1,6 @@
1
1
  // workflow-enums.test.mjs — 枚举单源读取器测试(2026-09-25 enum-single-source)
2
2
  // 判据:① 真实单源文件解析 + 不变量通过 ② 坏数据(坏行/重复键/重复值/缺键/子集破/重叠)fail-loud
3
- // ③ 缺文件 fail-loud ④ sh 消费方同口径(sed 可取到全部 8 键)
3
+ // ③ 缺文件 fail-loud ④ sh 消费方同口径(sed 可取到全部键)
4
4
  // 用法:node templates/_agents/scripts/workflow-enums.test.mjs(npm test 随跑)
5
5
  import path from 'node:path';
6
6
  import { execSync } from 'node:child_process';
@@ -20,14 +20,22 @@ const throwsWith = (fn, kw) => {
20
20
  const SCRIPT_DIR = path.dirname(fileURLToPath(import.meta.url));
21
21
  const ENUMS_TXT = path.join(SCRIPT_DIR, '..', 'workflow-enums.txt');
22
22
 
23
- // ---- S1 模块级 ENUMS 即加载即校验(真实文件),8 键齐 ----
23
+ // ---- S1 模块级 ENUMS 即加载即校验(真实文件),10 键齐(2026-10-13 自 Shipyard 回灌归因两键)----
24
24
  {
25
25
  const keys = Object.keys(ENUMS).sort();
26
- check('S1 真实单源文件加载成功且 8 键齐',
27
- keys.length === 8 && keys.join(',') === 'doc.status.abandoned,doc.status.active,doc.status.all,doc.status.confirmed,doc.status.terminal,incident.status.active,incident.status.all,level.all',
26
+ check('S1 真实单源文件加载成功且 10 键齐',
27
+ keys.length === 10 && keys.join(',') === 'doc.status.abandoned,doc.status.active,doc.status.all,doc.status.confirmed,doc.status.terminal,incident.env.all,incident.source.all,incident.status.active,incident.status.all,level.all',
28
28
  JSON.stringify(keys));
29
29
  }
30
30
 
31
+ // ---- S1b 归因两键值域逐字对齐 Shipyard(incident.source.all / incident.env.all)----
32
+ {
33
+ check('S1b 归因两键值域:source=self user test monitor、env=dev staging prod none',
34
+ ENUMS['incident.source.all'].join('+') === 'self+user+test+monitor'
35
+ && ENUMS['incident.env.all'].join('+') === 'dev+staging+prod+none',
36
+ JSON.stringify(ENUMS));
37
+ }
38
+
31
39
  // ---- S2 真实文件关键值口径(check-loop/看板/检索的行为锚点,值变更须连本测试一起改)----
32
40
  {
33
41
  check('S2 关键集值口径:confirmed 不含 draft、active=draft+approved、terminal 含 done、abandoned ⊆ terminal',
@@ -35,7 +43,8 @@ const ENUMS_TXT = path.join(SCRIPT_DIR, '..', 'workflow-enums.txt');
35
43
  && ENUMS['doc.status.active'].join('+') === 'draft+approved'
36
44
  && ENUMS['doc.status.terminal'].includes('done')
37
45
  && ENUMS['doc.status.abandoned'].every((v) => ENUMS['doc.status.terminal'].includes(v))
38
- && ENUMS['level.all'].length === 4,
46
+ // level.all=L1 L2 L3——L0 已退役(2026-10-13 自源仓收敛系列 1 回灌)
47
+ && ENUMS['level.all'].join('+') === 'L1+L2+L3',
39
48
  JSON.stringify(ENUMS));
40
49
  }
41
50
 
@@ -4,6 +4,7 @@
4
4
  # 新增引擎脚本默认必须带同名 .test.mjs(README 规范条目);确属库件/工具才登记本文件。
5
5
  # 2026-10-09 A2 评估:verify-wiki-consistency 已移出(补测 3 场景);wiki-search 已移出(转发壳,判定单源 kb-search.test 覆盖)。
6
6
  check-metric-claims.mjs | 经 check-loop.mjs 消费 | 由 check-loop.test.mjs 间接覆盖其调用路径
7
+ rule-budget.mjs | 判定器(2026-10-13 自 .sh 移植 node;经 check-hygiene 检查 13 与 pre-commit 消费,Shipyard 侧同无直测) | check-loop.test.mjs 场景 28-30(含 --staged 硬拦两态)+ check-loop-rev.test.mjs 间接覆盖;src/rule-budget.test.mjs 平行实现作口径对照
7
8
  ensure-board.mjs | 看板启动器 | 永久工具豁免(需真实端口/进程环境,自动化覆盖无性价比——2026-10-09 engine-quality-round2 A2 评估定性)
8
9
  policy.mjs | 库件 | 被 check-loop.test.mjs 直接 import 覆盖
9
10
  # 2026-10-12 needs-clarification:stage-gates.mjs 已建同名直测(stage-gates.test.mjs 15 断言),
@@ -0,0 +1,60 @@
1
+ ---
2
+ name: papercut-fix
3
+ description: 修 workflow/papercuts.md 里指定的未升级 papercut 条目(把存量债降到 0 的回路执行器)。按控制器给的行号定位症状、照「拟修」列改权威文件、回写台账并跑验证门。
4
+ ---
5
+
6
+ # papercut-fix — 单条 papercut 升级执行器
7
+
8
+ ## 目标
9
+ 将 `workflow/papercuts.md` 中指定的一条 papercut 条目状态更新为「已消债」。
10
+
11
+ ## 触发条件
12
+ - 用户指令:`跑一轮 papercut 回路` / `清 papercut 存量` / `修第 N 条 papercut`。
13
+
14
+ ## 约束与红线
15
+ - **单一目标**:每轮执行仅处理一条目标,禁止顺手修复相邻条目或夹带其他改动。
16
+ - **范围限制**:改动仅限文档面(`.agents/commands/`, `.agents/roles/`, `.agents/skills/`, `.githooks/`, `.agents/scripts/`, `workflow/`)。
17
+ - **绝对禁区**:禁止修改 `backend/`, `frontend/`, `tests/`, `wiki/`,禁止连接数据库——与控制器 scope gate(`OUT_OF_SCOPE` 正则)同一清单,命中即停。超出范围时必须停止并报告用户。
18
+ - **验证优先**:禁止凭台账描述臆测现状。必须先读权威文件验证症状是否成立。
19
+ - **编辑规范**:修改 `workflow/` 文档必须使用 Edit 工具。禁止使用 `node -e` 或脚本批量替换(CRLF 环境下会静默失败)。
20
+ - **消债判定**:分支 A(修复)与分支 B(暂缓/失效)**均**满足 `debt -1` 不变量。
21
+
22
+ ## 工作流
23
+
24
+ ### 1. 定位与预检
25
+ - 从控制器输出提取:`行号` (Lxx), `位置` (路径), `症状`, `拟修`。
26
+ - 使用 Read 工具读取该行及其上下文。
27
+
28
+ ### 2. 现状验证
29
+ - 读取「位置」列指定的权威文件。
30
+ - **判定结论**:
31
+ - **缺陷仍在** $\rightarrow$ 进入分支 A。
32
+ - **已失效** (已被其他改动修复/文件已删除) $\rightarrow$ 进入分支 B。
33
+ - **方向相反/描述有误** $\rightarrow$ 重新定性后再执行。
34
+
35
+ ### 3. 执行修复
36
+ - **分支 A (缺陷仍在)**:
37
+ 1. 对权威文件执行最小化修复。
38
+ 2. 在 `workflow/papercuts.md`(或承载该条目的 `workflow/papercuts.d/` 分片)该行末尾追加:`✅ 已升级修复(YYYY-MM-DD): <改动描述> <commit>`。
39
+ 3. 若原「拟修」描述已不适用,在追加记录中写明实际修法。
40
+ - **分支 B (已失效)**:
41
+ 1. 在 `workflow/papercuts.md`(或承载该条目的分片)该行末尾追加:`⏸ 暂缓(YYYY-MM-DD): <失效理由>`。理由必须明确。
42
+ 2. **核实纪律**:
43
+ - 检查用户级技能目录(`~/.claude/skills/`、`~/.trae/skills/` 等宿主适配目录)确认文件是否仅是迁移而非删除。
44
+ - 区分「环境约束」与「代码缺陷」。
45
+ - 针对「跨环境」症状,使用 `git worktree` 构建真实检出态实验证伪。
46
+ - 针对「已落地」症状,使用 `git log -S` 追溯引入提交日期。
47
+ - **分支 C (越界)**:停止执行,报告理由并请求授权。
48
+
49
+ ### 4. 验证与收尾
50
+ - **备份**:修改台账(主台账或分片)前强制 `cp <台账文件> tmp/papercuts.wip-backup.md`。
51
+ - **运行检查**:
52
+ - `node .agents/scripts/papercut-debt-sensor.mjs` $\rightarrow$ `debt` 必须恰好减少 1。
53
+ - `node .agents/scripts/papercut-debt-controller.mjs` $\rightarrow$ 确认目标推进。
54
+ - 检查台账(主台账 ∪ 分片)的总行数(`total` 不得减少——`debt` 符合预期 ≠ 文件没被压行)、列数分布及是否存在超长行(压行信号)。
55
+ - **体积检查**:若修改了 `.agents/commands/`,跑 `node .agents/scripts/rule-budget.mjs --staged` 对比 `.agents/rule-budgets.txt` 上限(一进一出;禁用工作区 `wc -c` 核对——CRLF 膨胀会误报)。
56
+
57
+ ## 回报要求
58
+ - 参照 `references/response-template.md` 输出。
59
+ - 包含:行号、位置、分支结论(A/B/C)、改动文件、验证结果(debt 前后值)、待决策事项。
60
+ - **禁令**:禁止自动 commit 或 push。
@@ -0,0 +1,81 @@
1
+ # papercut-fix 回应模板
2
+
3
+ 单轮回路执行器的最终输出格式。给用户看,决定他是否放行这次改动。
4
+
5
+ ---
6
+
7
+ ## 模板
8
+
9
+ ```markdown
10
+ papercut 回路 · 第 N 轮
11
+
12
+ **目标**:L{line} `{location}`({date},第 {hits} 次命中)
13
+ **结论**:{A 缺陷仍在 / B 已失效 / B2 账未销(拟修已由别的改动落地)/ B3 台账方向记反(检出态实验证伪)/ C 越界待授权}
14
+
15
+ ### 改动
16
+
17
+ | 文件 | 改了什么 |
18
+ |---|---|
19
+ | `{权威文件路径}` | {一句话} |
20
+ | `workflow/papercuts.md` | 回写行标记:{`✅ 已升级修复(日期)` / `⏸ 暂缓(日期):理由`} |
21
+
22
+ ### 验证
23
+
24
+ - `papercut-debt-sensor.mjs`:debt {before} → {after}(预期 -1)
25
+ - {其他检查,如体积预算核对:通过 / 不适用}
26
+
27
+ ### 台账依据
28
+
29
+ {若实际修法与「拟修」列描述不一致,在此说明「拟修」列写的什么、实际怎么做的、为什么。
30
+ B2 结论必须写出落地提交:`由 <sha>(<日期>,<标题>)落地`。}
31
+
32
+ ### 需你决定
33
+
34
+ {列出需要用户拍板的事项;没有则写「无」。典型场景:
35
+ - 结论为 C(越界)——是否单独授权改源码/连库
36
+ - 「拟修」列描述已过期——是否更新该列文本
37
+ - 控制器列出的「待人工定性」条目——是否本轮顺带定性
38
+ - 改动触及常驻面体积预算——是否接受,或改为下沉/删除被取代条目}
39
+ ```
40
+
41
+ ---
42
+
43
+ ## 格式要求
44
+
45
+ 1. **先给结论,再给细节**。用户扫第一行就要知道"修了哪条、结论是什么"。
46
+ 2. **「需你决定」不许空着**。即使本轮无事,也显式写「无」——让"没有待决事项"和"忘了写"可区分。
47
+ 3. **验证值给具体数字**,不要只说"验证通过"。debt 的前后值是设定点误差,必须可核。
48
+ 4. **不粉饰失败**。验证门红了就写红,附命令与原始报错摘要。回路的价值在于给出可信的账,不是好看的账。
49
+ 5. **不写"建议接下来…"式的空话**。要写就写具体动作 + 具体条目编号。
50
+
51
+ ---
52
+
53
+ ## 示例(结论 A,示意——占位符形态,非真实条目)
54
+
55
+ ```markdown
56
+ papercut 回路 · 第 3 轮
57
+
58
+ **目标**:L34 `.agents/commands/test.md`(静态门清单 §2 缺一条豁免说明)(<日期>)
59
+ **结论**:A 缺陷仍在
60
+
61
+ ### 改动
62
+
63
+ | 文件 | 改了什么 |
64
+ |---|---|
65
+ | `.agents/commands/test.md` | §2 补一条:跳过条件的判据以 <权威判据> 为准,不以 <表象> 为准;§常见误判 补对应条目 |
66
+ | `workflow/papercuts.md` | 回写 L34 标记:`✅ 已升级修复(YYYY-MM-DD)` |
67
+
68
+ ### 验证
69
+
70
+ - `papercut-debt-sensor.mjs`:debt 16 → 15(预期 -1)
71
+ - 体积预算:`node .agents/scripts/rule-budget.mjs --staged` 通过(未触 `.agents/commands/` 上限)
72
+
73
+ ### 台账依据
74
+
75
+ 「拟修」列写的是「补一条 <表象> 的判定说明」。实际执行时发现症状描述的是 <相邻机制>,而 §2 真正缺的是**判据本身**(<相邻机制> 只在特定前提后需要,判据该按 <权威判据>)。两者相邻但不同,已按判据写,相邻条目并入同节。
76
+
77
+ ### 需你决定
78
+
79
+ - 「拟修」列文本与实际修法有偏差(见上),是否更新该列描述以免下次复发时对不上?
80
+ - 控制器列出的「待人工定性」3 条(位置列路径已不存在)——其中 1 条指向的脚本性能问题已随某次重构解决,本轮修完后建议一并定性。要不要现在处理?
81
+ ```
@@ -16,4 +16,11 @@ doc.status.terminal=done superseded cancelled
16
16
  doc.status.abandoned=superseded cancelled
17
17
  incident.status.all=open fixed closed
18
18
  incident.status.active=open
19
- level.all=L0 L1 L2 L3
19
+ # 归因枚举(2026-10-13 自 Shipyard 回灌 incident-attribution):归因检查(B6b 落地后编号以 check-loop.mjs 头部清单为准)校验 incident frontmatter 的「来源:」/「影响环境:」。
20
+ # source = 谁发现(self=AI 自查 / user=用户报出 / test=测试或实测暴露 / monitor=监控告警)
21
+ # env = 缺陷触达的环境(none=未触达任何运行环境,如仅静态检查发现)
22
+ # 锚前存量不回填;新 open 件必填(生效锚随 B6b 归因检查落地)。
23
+ incident.source.all=self user test monitor
24
+ incident.env.all=dev staging prod none
25
+ # 级别三档(2026-10-13 L0 退役自源仓收敛系列 1 回灌):L1 = 一份 plan 即入口(协作道);L2/L3 = 防御道。
26
+ level.all=L1 L2 L3
@@ -1,101 +1,121 @@
1
- #!/bin/sh
2
- # Git 原生 pre-commit hook(经 core.hooksPath 挂载,git 执行、不依赖 agent 客户端)— agentic-flow-kit 通用编排
3
- # 通用门禁序:闭环配对(增量) → 泳道完整性(增量) → wiki 台账(增量) → 常驻面体积预算(增量) → 确认台账不变量(暂存触台账) → 项目门禁(local-pre-commit) → 敏感信息扫描+条件构建(commit-check.cjs)
4
- # 项目专属门禁(架构红线/业务守卫等)放 .agents/hooks/local-pre-commit——存在即在本钩子内执行,返回非零即阻断提交
5
- # 合并提交场景由 .githooks/pre-merge-commit 原样转发到本脚本(合并时 git 调的是 pre-merge-commit,
6
- # 不是 pre-commit)——门禁清单只此一份,避免两处分叉
1
+ #!/usr/bin/env node
2
+ // Git 原生 pre-commit hook(经 core.hooksPath 挂载)— agentic-flow-kit 通用编排
3
+ // 2026-10-13 门禁去 sh 化(B2,自 Shipyard.Material 参考实现回灌):钩子体不再含 sh 逻辑——git 仍以自带
4
+ // sh 启动本文件(钩子机制要求),但 shebang 即 node,PATH 无 sh 不再影响任何逻辑;语言单化后 CI 代理/
5
+ // 本地行为一致。写法为 CommonJS——无扩展名文件 node 缺省按 CJS 解析,不依赖 ≥22.7 的 ESM 语法探测。
6
+ // 通用门禁序:闭环配对(增量) → 泳道完整性(增量) → wiki 台账(增量) → 索引漂移(增量) → 常驻面体积预算(增量) → 确认台账不变量(暂存触台账) → 项目门禁(local-pre-commit) → 敏感信息扫描+条件构建(commit-check.cjs)
7
+ // 项目专属门禁(架构红线/业务守卫等)放 .agents/hooks/local-pre-commit——sh 挂载点(add-gate 生态按行接线),
8
+ // 存在即在本钩子内以 sh(缺则 bash)执行,返回非零即阻断提交
9
+ // 合并提交场景由 .githooks/pre-merge-commit 原样转发到本脚本(合并时 git 调的是 pre-merge-commit,
10
+ // 不是 pre-commit)——门禁清单只此一份,避免两处分叉
11
+ // fail-closed(沿 Shipyard 2026-10-09 口径;node 化后天然成立——本进程即 node):门脚本缺失 = 拒提交;
12
+ // 仅 local-pre-commit 保留「存在即执行」挂载点语义(缺失打 advisory)。
13
+ const { spawnSync } = require('node:child_process');
14
+ const fs = require('node:fs');
7
15
 
8
- cd "$(git rev-parse --show-toplevel)" || exit 1
9
-
10
- # run_gate <标签> <脚本> [参数...]:sh 优先、无 sh 用 bash;非零即阻断
11
- run_gate() {
12
- gate_label="$1"; shift
13
- if command -v sh >/dev/null 2>&1; then sh "$@"; else bash "$@"; fi
14
- rc=$?
15
- if [ $rc -ne 0 ]; then
16
- echo "pre-commit: $gate_label 未通过,提交已阻止" >&2
17
- exit $rc
18
- fi
16
+ const top = spawnSync('git', ['rev-parse', '--show-toplevel'], { encoding: 'utf8' });
17
+ if (top.status !== 0 || !top.stdout.trim()) {
18
+ console.error('pre-commit: 无法定位仓库根(git rev-parse --show-toplevel 失败)——提交已阻止');
19
+ process.exit(1);
19
20
  }
21
+ process.chdir(top.stdout.trim());
20
22
 
21
- # 闭环配对门禁(增量版,check-pairing-incremental.sh:本次暂存的 intents/incidents 入口须已有同名 plan)
22
- # experiment/* 泳道分支(2026-09-30 hybrid-governance-explore-hardening):降级为 advisory——快速 PoC
23
- # 迭代不因闭环文档断档被拦(断档报告照出),转正合入 main 由 pre-push 加固门(check-loop --hardening)兜底。
24
- # 仅降级闭环文档面:常驻面 / 敏感信息扫描等门禁不豁免。分支不可判(detached HEAD 等)走严格模式。
25
- pairing_gate_mode=strict
26
- case "$(git rev-parse --abbrev-ref HEAD 2>/dev/null)" in
27
- experiment/*) pairing_gate_mode=advisory ;;
28
- esac
29
- if [ "$pairing_gate_mode" = "advisory" ]; then
30
- echo "pre-commit: experiment/* 泳道分支——闭环配对门禁降级为 advisory(报告不阻断;转正入 main 须过加固门)" >&2
31
- if command -v sh >/dev/null 2>&1; then
32
- sh .agents/hooks/check-pairing-incremental.sh || echo "pre-commit: (advisory)闭环配对断档已在上方列出——experiment 泳道不阻断提交" >&2
33
- else
34
- bash .agents/hooks/check-pairing-incremental.sh || echo "pre-commit: (advisory)闭环配对断档已在上方列出——experiment 泳道不阻断提交" >&2
35
- fi
36
- else
37
- run_gate "闭环配对(增量)" .agents/hooks/check-pairing-incremental.sh
38
- fi
23
+ // gate(label, script, args):node 直跑门脚本,非零即阻断(含 fail-closed 缺失检查)
24
+ const requireScript = (rel) => {
25
+ if (!fs.existsSync(rel)) {
26
+ console.error(`pre-commit: 门脚本缺失 ${rel}——提交已阻止(脚本随包下发;flow-kit sync 恢复后重试)`);
27
+ process.exit(1);
28
+ }
29
+ };
30
+ const gate = (label, script, args = []) => {
31
+ requireScript(script);
32
+ const r = spawnSync(process.execPath, [script, ...args], { stdio: 'inherit' });
33
+ if (r.status !== 0) {
34
+ console.error(`pre-commit: ${label} 未通过,提交已阻止`);
35
+ process.exit(r.status === null ? 1 : r.status);
36
+ }
37
+ };
39
38
 
40
- # 泳道完整性(增量,check-lane-surface.mjs——2026-10-01 drift-hardening):
41
- # 检查 A「触达面判低」——暂存命中项目 L2 触达面(.agents/lane-surfaces.txt,ERE 逐行;缺失/空=跳过,
42
- # 装户无感)且活跃入口(draft/approved / open/fixed)全为 L0/L1 → 拦;有活跃 L2/L3 → 放行;无活跃入口 →
43
- # 仅 advisory(docs/bootstrap 豁免类)。experiment/* 分支降级 advisory(转正由 pre-push 加固门兜底)。
44
- # 检查 B「探索标记缺失」——experiment/* 分支暂存 intent 缺「阶段: exploring」→ 拦(标记零成本,
45
- # advisory 免纪律不免标记——标记是加固门覆盖率的前提)。
46
- # 旧装副本无脚本自然跳过;node 缺失时本门跳过(其后 commit-check 节点检查仍会拦提交,无空洞)。
47
- # 注意:不经 run_gate(其实现为 sh "$@",会把 node 当脚本解释——直接 node 调用)。
48
- if [ -f .agents/scripts/check-lane-surface.mjs ] && command -v node >/dev/null 2>&1; then
49
- if ! node .agents/scripts/check-lane-surface.mjs; then
50
- echo "pre-commit: 泳道完整性(增量)未通过,提交已阻止" >&2
51
- exit 1
52
- fi
53
- fi
39
+ // 闭环配对门禁(增量版,check-pairing-incremental.mjs:本次暂存的 intents/incidents 入口须已有同名 plan;
40
+ // L2/L3 另须同名 spec)。experiment/* 泳道分支(2026-09-30 hybrid-governance-explore-hardening):
41
+ // 降级为 advisory——快速 PoC 迭代不因闭环文档断档被拦(断档报告照出),转正合入 main 由 pre-push
42
+ // 加固门(check-loop --hardening)兜底。仅降级闭环文档面:常驻面 / 台账 / 敏感信息扫描等门禁不豁免。
43
+ // 分支不可判(detached HEAD 等)走严格模式。
44
+ const branch = spawnSync('git', ['rev-parse', '--abbrev-ref', 'HEAD'], { encoding: 'utf8' });
45
+ const branchName = branch.status === 0 ? branch.stdout.trim() : '';
46
+ if (branchName.startsWith('experiment/')) {
47
+ console.error('pre-commit: experiment/* 泳道分支——闭环配对门禁降级为 advisory(报告不阻断;转正入 main 须过加固门)');
48
+ const adv = spawnSync(process.execPath, ['.agents/hooks/check-pairing-incremental.mjs'], { stdio: 'inherit' });
49
+ if (adv.status !== 0) console.error('pre-commit: (advisory)闭环配对断档已在上方列出——experiment 泳道不阻断提交');
50
+ } else {
51
+ gate('闭环配对(增量)', '.agents/hooks/check-pairing-incremental.mjs');
52
+ }
54
53
 
55
- # wiki 台账门禁(增量,check-wiki-ledger.sh:暂存区触及 wiki/ 时跑 verify-wiki-consistency 三方一致性;
56
- # 无 wiki/ 变更即跳过)
57
- run_gate "wiki 台账(增量)" .agents/hooks/check-wiki-ledger.sh
54
+ // 泳道完整性(增量,check-lane-surface.mjs——2026-10-01 drift-hardening):
55
+ // 检查 A「触达面判低」——暂存命中项目 L2 触达面(.agents/lane-surfaces.txt,ERE 逐行;缺失/空=跳过,
56
+ // 装户无感)且活跃入口(draft/approved / open/fixed)全为 L0/L1 → 拦;有活跃 L2/L3 → 放行;无活跃入口 →
57
+ // 仅 advisory(docs/bootstrap 豁免类)。experiment/* 分支降级 advisory(转正由 pre-push 加固门兜底)。
58
+ // 检查 B「探索标记缺失」——experiment/* 分支暂存 intent 缺「阶段: exploring」→ 拦(标记零成本,
59
+ // advisory 免纪律不免标记——标记是加固门覆盖率的前提)。
60
+ // 脚本缺失 fail-closed 阻断(见 gate())。
61
+ gate('泳道完整性(增量)', '.agents/scripts/check-lane-surface.mjs');
58
62
 
59
- # 常驻面体积预算(增量硬拦,rule-budget.sh --staged:只查本次暂存触及的条目与触及目录的合计;
60
- # 超限即阻断——常驻面只增不减,须先删除或下沉一条被取代条目再增)
61
- if [ -f .agents/scripts/rule-budget.sh ] && [ -f .agents/rule-budgets.txt ]; then
62
- run_gate "常驻面体积预算" .agents/scripts/rule-budget.sh --staged
63
- fi
63
+ // wiki 台账门禁(增量,check-wiki-ledger.mjs:暂存区触及 wiki/ 时跑 verify-wiki-consistency 三方一致性;
64
+ // 无 wiki/ 变更即跳过。脚本缺失 fail-closed)
65
+ gate('wiki 台账(增量)', '.agents/hooks/check-wiki-ledger.mjs');
64
66
 
65
- # 确认台账不变量前置(--staged,2026-10-02 ledger-ci-invariant):暂存的 confirmations.jsonl 必须
66
- # 是 HEAD 的逐字节前缀扩展(append-only)——本地提交时刻即拦「顺手重写台账」,CI 历史全扫兜底。
67
- # guard 旧装副本自然跳过;暂存未触台账静默。
68
- if [ -f .agents/scripts/check-ledger-invariant.mjs ] && command -v node >/dev/null 2>&1; then
69
- if git -c core.quotepath=off diff --cached --name-only | grep -q '^\.agents/confirmations\.jsonl$'; then
70
- if ! node .agents/scripts/check-ledger-invariant.mjs --staged; then
71
- echo "pre-commit: 确认台账不变量未通过,提交已阻止——历史行禁删改(append-only),修正走追加补偿行" >&2
72
- exit 1
73
- fi
74
- fi
75
- fi
67
+ // 索引漂移(增量硬拦,check-index-incremental.mjs):暂存触及 workflow 四目录 / 归档 / INDEX.md 时,
68
+ // gen-workflow-index.mjs --check 不一致即拒。卫生段检查 11 仍是 WARN,挡不住关单提交。
69
+ // 未触及这些路径则脚本内跳过。脚本缺失 fail-closed。
70
+ gate('索引漂移(增量)', '.agents/hooks/check-index-incremental.mjs');
76
71
 
77
- # 项目门禁挂载点:.agents/hooks/local-pre-commit(项目自建门禁/门禁模块接线处,存在即执行)
78
- if [ -f .agents/hooks/local-pre-commit ]; then
79
- run_gate "项目门禁(local-pre-commit)" .agents/hooks/local-pre-commit
80
- fi
72
+ // 常驻面体积预算(增量硬拦,rule-budget.mjs --staged:只查本次暂存触及的条目与触及目录的合计;
73
+ // 超限即阻断——常驻面只增不减,须先删除或下沉一条被取代条目再增。预算登记表缺失同样 fail-closed)
74
+ requireScript('.agents/rule-budgets.txt');
75
+ gate('常驻面体积预算', '.agents/scripts/rule-budget.mjs', ['--staged']);
81
76
 
82
- if ! command -v node >/dev/null 2>&1; then
83
- echo "pre-commit: 未找到 node——敏感信息扫描与条件构建无法执行,提交已阻止(安装 Node.js 后重试)" >&2
84
- exit 1
85
- fi
77
+ // 确认台账不变量前置(--staged,2026-10-02 ledger-ci-invariant):暂存的 confirmations.jsonl 与分片
78
+ // confirmations.d/*.jsonl(2026-10-13 ledger-shard-default 起分片为默认写入口径,触发面同步扩大)必须
79
+ // 是 HEAD 的逐字节前缀扩展(append-only)——本地提交时刻即拦「顺手重写台账」,CI 历史全扫兜底。
80
+ // 暂存未触台账静默;触台账而脚本缺失 fail-closed 阻断。
81
+ const staged = spawnSync('git', ['-c', 'core.quotepath=off', 'diff', '--cached', '--name-only'], { encoding: 'utf8' });
82
+ const stagedFiles = String(staged.stdout || '').split(/\r?\n/).filter(Boolean).map((f) => f.replace(/\\/g, '/'));
83
+ const touchesLedger = stagedFiles.some((f) => /^\.agents\/confirmations\.jsonl$|^\.agents\/confirmations\.d\/[^/]+\.jsonl$/.test(f));
84
+ if (touchesLedger) {
85
+ requireScript('.agents/scripts/check-ledger-invariant.mjs');
86
+ const li = spawnSync(process.execPath, ['.agents/scripts/check-ledger-invariant.mjs', '--staged'], { stdio: 'inherit' });
87
+ if (li.status !== 0) {
88
+ console.error('pre-commit: 确认台账不变量未通过,提交已阻止——历史行禁删改(append-only),修正走追加补偿行');
89
+ process.exit(li.status === null ? 1 : li.status);
90
+ }
91
+ }
86
92
 
87
- # 合并提交 → 构建验证覆盖【完整合并树】,不做按扩展名的条件裁剪。
88
- # 两条路径:`git merge` 自动提交由 .githooks/pre-merge-commit 显式传 `--full` 转发到本脚本;
89
- # 冲突解决后手动 `git commit` 由 git 直接调本脚本,此处按 MERGE_HEAD 探测补上(此时合并仍在进行)。
90
- full_args="$*"
91
- if [ -z "$full_args" ] && git rev-parse -q --verify MERGE_HEAD >/dev/null 2>&1; then
92
- full_args=--full
93
- fi
93
+ // 项目门禁挂载点:.agents/hooks/local-pre-commit(项目自建门禁/门禁模块接线处,add-gate 生态往里写行)。
94
+ // 保持 sh 形态:以 sh(缺则 bash)执行;存在即执行、缺失打 advisory 不阻断(挂载点可选语义),
95
+ // 但缺失不再无声——该文件随包下发,advisory 即误删信号。
96
+ if (fs.existsSync('.agents/hooks/local-pre-commit')) {
97
+ const shBin = spawnSync('sh', ['-c', 'true']).status === 0 ? 'sh' : 'bash';
98
+ const lp = spawnSync(shBin, ['.agents/hooks/local-pre-commit'], { stdio: 'inherit' });
99
+ if (lp.status !== 0) {
100
+ console.error('pre-commit: 项目门禁(local-pre-commit)未通过,提交已阻止');
101
+ process.exit(lp.status === null ? 1 : lp.status);
102
+ }
103
+ } else {
104
+ console.error('pre-commit: (advisory)项目门禁挂载点 .agents/hooks/local-pre-commit 不在场——add-gate 接线处随包下发,若为误删请 flow-kit sync 恢复');
105
+ }
94
106
 
95
- node .agents/hooks/commit-check.cjs $full_args
96
- rc=$?
97
- if [ $rc -ne 0 ]; then
98
- echo "pre-commit: 验证未通过,提交已阻止" >&2
99
- exit $rc
100
- fi
101
- exit 0
107
+ // 合并提交 → 构建验证覆盖【完整合并树】,不做按扩展名的条件裁剪。
108
+ // 两条路径:`git merge` 自动提交由 .githooks/pre-merge-commit 显式传 `--full` 转发到本脚本;
109
+ // 冲突解决后手动 `git commit` 由 git 直接调本脚本,此处按 MERGE_HEAD 探测补上(此时合并仍在进行)。
110
+ let fullArgs = process.argv.slice(2);
111
+ if (fullArgs.length === 0) {
112
+ const mergeHead = spawnSync('git', ['rev-parse', '-q', '--verify', 'MERGE_HEAD'], { encoding: 'utf8' });
113
+ if (mergeHead.status === 0) fullArgs = ['--full'];
114
+ }
115
+
116
+ const cc = spawnSync(process.execPath, ['.agents/hooks/commit-check.cjs', ...fullArgs], { stdio: 'inherit' });
117
+ if (cc.status !== 0) {
118
+ console.error('pre-commit: 验证未通过,提交已阻止');
119
+ process.exit(cc.status === null ? 1 : cc.status);
120
+ }
121
+ process.exit(0);
@@ -1,24 +1,28 @@
1
- #!/bin/sh
2
- # Git 原生 pre-merge-commit hook(经 core.hooksPath 挂载,git 执行、不依赖 agent 客户端)
3
- #
4
- # 背景:git 对 `git merge` 调的是**本钩子**,不是 pre-commit。此前仓库只挂了
5
- # pre-commit / pre-push / commit-msg,故合并提交绕过全部门禁、未经任何校验直接落库
6
- # (2026-09-19 实测,见 workflow/papercuts.md 同日行——那次合并带入后端 .cs 改动,
7
- # 靠人工补跑静态门 + 全量测试才覆盖到)。
8
- #
9
- # 做法:转发到 .githooks/pre-commit(门禁清单只此一份,避免两份拷贝日后分叉),
10
- # 并显式传 `--full`——本钩子「只对 merge 触发」这一身份就是最强信号,无需再去探测
11
- # MERGE_HEAD(2026-09-19 实测:本时点 MERGE_HEAD 已不可靠)。`--full` 令编译验证
12
- # 覆盖【完整合并树】、不按扩展名条件裁剪:合并结果是没人验证过的新状态,且其 diff
13
- # 相对第一父,裁剪会漏掉需要重跑的一侧。
14
- #
15
- # 冲突解决后手动 `git commit` 走的是 pre-commit 自身,那条路径由 pre-commit 内部的
16
- # MERGE_HEAD 探测覆盖(此时合并仍在进行,MERGE_HEAD 确定存在)。
1
+ #!/usr/bin/env node
2
+ // Git 原生 pre-merge-commit hook(经 core.hooksPath 挂载;2026-10-13 随 pre-commit node 化(B2)改为 node 转发
3
+ // ——转发不再经 sh。CommonJS——无扩展名文件 node 缺省按 CJS 解析,不依赖 ESM 语法探测)
4
+ //
5
+ // 背景:git 对 `git merge` 调的是**本钩子**,不是 pre-commit。此前仓库只挂了
6
+ // pre-commit / pre-push / commit-msg,故合并提交绕过全部门禁、未经任何校验直接落库
7
+ // (2026-09-19 实测,见 workflow/papercuts.md 同日行——那次合并带入后端 .cs 改动,
8
+ // 靠人工补跑静态门 + 全量测试才覆盖到)。
9
+ //
10
+ // 做法:转发到 .githooks/pre-commit(门禁清单只此一份,避免两份拷贝日后分叉),
11
+ // 并显式传 `--full`——本钩子「只对 merge 触发」这一身份就是最强信号,无需再去探测
12
+ // MERGE_HEAD(2026-09-19 实测:本时点 MERGE_HEAD 已不可靠)。`--full` 令编译验证
13
+ // 覆盖【完整合并树】、不按扩展名的条件裁剪:合并结果是没人验证过的新状态,且其 diff
14
+ // 相对第一父,裁剪会漏掉需要重跑的一侧。
15
+ //
16
+ // 冲突解决后手动 `git commit` 走的是 pre-commit 自身,那条路径由 pre-commit 内部的
17
+ // MERGE_HEAD 探测覆盖(此时合并仍在进行,MERGE_HEAD 确定存在)。
18
+ const { spawnSync } = require('node:child_process');
19
+ const path = require('node:path');
17
20
 
18
- cd "$(git rev-parse --show-toplevel)" || exit 1
19
-
20
- if command -v sh >/dev/null 2>&1; then
21
- exec sh .githooks/pre-commit --full
22
- else
23
- exec bash .githooks/pre-commit --full
24
- fi
21
+ const top = spawnSync('git', ['rev-parse', '--show-toplevel'], { encoding: 'utf8' });
22
+ if (top.status !== 0 || !top.stdout.trim()) {
23
+ console.error('pre-merge-commit: 无法定位仓库根——合并提交已阻止');
24
+ process.exit(1);
25
+ }
26
+ const hook = path.join(top.stdout.trim(), '.githooks', 'pre-commit');
27
+ const r = spawnSync(process.execPath, [hook, '--full'], { stdio: 'inherit' });
28
+ process.exit(r.status === null ? 1 : r.status);
@@ -1,8 +1,9 @@
1
1
  #!/bin/sh
2
2
  # Git 原生 pre-push hook(经 core.hooksPath 挂载,git push 时触发)
3
- # 跑 .agents/scripts/check-loop.sh:扫 workflow/ 闭环骨架断档
4
- # - 硬阻断(exit 1)= 配对断裂 / 回路断档 → push 立即阻断
5
- # - 警告(advisory)= 状态未确认 / 模板占位残留 / 引用漂移 等卫生项 → 仅打印提示
3
+ # 跑 .agents/scripts/check-loop.sh:扫 workflow/ 闭环骨架断档(2026-10-13 分道——默认只扫硬门,源仓同款)
4
+ # - 硬阻断(exit 1)= 配对断裂 / 回路断档 等硬门违例 → push 立即阻断
5
+ # - 卫生项(索引/宿主/词表/体积预算等 WARN 面)不进 push 门——要看时手跑 check-loop.mjs --hygiene
6
+ # (--all 两面都跑 = 分道前的裸跑全量)
6
7
  # stdin 有行时,每个非删除的本地 sha 用 --rev 扫那棵树。没有行时(手跑钩子)仍无参数扫工作区。
7
8
  #
8
9
  # experiment/* 泳道(2026-09-30 hybrid-governance-explore-hardening):**目标分支**为 experiment/* 时,
@@ -1,7 +1,8 @@
1
1
  # kit-ci —— agentic-flow-kit 装户远端门(GitHub Actions 薄模板,2026-10-07 adopter-ci-github)
2
2
  # 语义:本地 git hooks 可被 --no-verify / 未配 hooksPath 的克隆绕过——本工作流在 GitHub runner 上复跑
3
- # 统一入口 node .agents/scripts/verify.mjs(测试【有根 package.json 才跑】+ check-loop),任一非零即红;
4
- # 不在 YAML 里复制门禁逻辑(本地/远端单源,防口径漂移)。
3
+ # 统一入口 node .agents/scripts/verify.mjs(七门 GATES 编排:语法自检 / 测试【有根 package.json 才跑】/
4
+ # 编排脚本检查 / 常驻面预算 / 生效规则视图漂移 / check-loop 闭环硬门 / 台账不变量历史全扫——门清单见
5
+ # verify.mjs --list),任一门红即红;不在 YAML 里复制门禁逻辑(本地/远端单源,防口径漂移)。
5
6
  # 本文件归装户自持(owned):触发分支 / node 版本 / 测试命令可自改,flow-kit sync 永不覆盖。
6
7
  # 装户仓工程在子目录(根无 package.json)时 verify 会跳过测试——改用
7
8
  # node .agents/scripts/verify.mjs --test-cmd "<项目测试命令>"
@@ -24,7 +25,7 @@ jobs:
24
25
  - name: 安装依赖(有根 package.json 才跑;私有源在此加 registry 配置)
25
26
  if: hashFiles('package.json') != ''
26
27
  run: npm ci || npm install || npm install --registry=https://registry.npmjs.org # 末级官方源兜底(2026-10-09 engine-quality-round3 W3:镜像故障不阻塞 CI)
27
- - name: 远端门(测试 + 闭环校验)
28
+ - name: 远端门(verify 七门编排)
28
29
  run: node .agents/scripts/verify.mjs
29
30
  - name: CI 红回溯点名(2026-10-09 engine-quality-round2 B3:红时列出最近关单,复核优先)
30
31
  if: failure()
@@ -12,15 +12,18 @@
12
12
  | `specs/` | 设计规格:功能行为、数据流、系统改动、约束遵守映射 | 与入口文档(intent / incident)同名 |
13
13
  | `plans/` | 计划文档:与入口文档同名配对,任务拆解 + 判据 + 风险 | 与入口文档(intent / incident)同名 |
14
14
  | `incidents/` | 事故复盘:时间线、根因、为什么没拦住、复盘三件套 | `YYYY-MM-DD-<主题>.md` |
15
+ | `archive/` | 终态件归档(`<YYYY-MM>/<类型>/`):同名家族滚动归档的落点,整族退出活跃面——INDEX、check-loop 配对门与 kb 活跃语料只扫四目录直下,台账行原路径未命中时 check-ledger-invariant 会探到此处 | `YYYY-MM/` |
15
16
 
16
17
  **命名一律英文 kebab-case**(如 `2026-09-07-<主题>.md`),**禁中文文件名**——check-loop 对非 ASCII 文件名给 warning。文档内容(标题/正文)不受此限。
17
18
 
18
- **文档协议(frontmatter 受限子集)**:四类文档头部一律为 YAML frontmatter(每行 `键: 值`,机器字段唯一来源)——`状态`(intent/spec/plan:draft/approved/done/superseded/cancelled;incident:open/fixed/closed,**严格枚举,单源 `.agents/workflow-enums.txt`**——check-loop / 看板 / 检索 / fill-* 一律读它,改枚举改那边;附注写 `备注:` 键)、`级别`(L0-L3,同单源)、intent 的 `risk_level`(=级别,混合治理风险泳道选道字段,fill-intent 落)、`日期`/`发现`(YYYY-MM-DD)、`模块`(**新建文档必填**,取值见 `.agents/workflow-modules.txt` 词表,单值取主导模块;存量不回填,AI 触碰时顺手补)、L3 spec 的 `确认结果`/`确认时间`、回填件 `流程: legacy`。**`状态` 迁移须经 `approved`**(确认环节的机器可见态,`done` 只在关单出现):新建的 spec/plan 若已 done 而 git 历史中从未出现行首 `状态: approved`,check-loop 报「确认态缺失」warning。check-loop 只扫 frontmatter 取机器字段(`fm_get` 字段断言),正文不再写「状态:/级别:」行;叙述性字段(独立复核/复盘三件套/验收勾验)仍留正文按节锚定。
19
+ **文档协议(frontmatter 受限子集)**:四类文档头部一律为 YAML frontmatter(每行 `键: 值`,机器字段唯一来源)——`状态`(intent/spec/plan:draft/approved/done/superseded/cancelled;incident:open/fixed/closed,**严格枚举,单源 `.agents/workflow-enums.txt`**——check-loop / 看板 / 检索 / fill-* 一律读它,改枚举改那边;附注写 `备注:` 键)、`级别`(L1-L3,同单源;L0 已退役,存量件改 L1 或标 `流程: legacy`)、intent 的 `risk_level`(=级别,混合治理风险泳道选道字段,fill-intent 落)、`日期`/`发现`(YYYY-MM-DD)、`模块`(**新建文档必填**,取值见 `.agents/workflow-modules.txt` 词表,单值取主导模块;存量不回填,AI 触碰时顺手补)、L3 spec 的 `确认结果`/`确认时间`、回填件 `流程: legacy`。**`状态` 迁移须经 `approved`**(确认环节的机器可见态,`done` 只在关单出现):新建的 spec/plan 若已 done 而 git 历史中从未出现行首 `状态: approved`,check-loop 报「确认态缺失」warning。check-loop 只扫 frontmatter 取机器字段(`fm_get` 字段断言),正文不再写「状态:/级别:」行;叙述性字段(独立复核/复盘三件套/验收勾验)仍留正文按节锚定。
19
20
 
20
21
  各子目录内 `_TEMPLATE.md` 为起步模板,复制后填写,不直接改动模板本身。
21
22
 
22
23
  根目录 `regression-checklist.md` 为**活文档回归清单**:deploy 回归必过条目与 incident 防复发验证的统一落点,随模块上线补充、随 incident 追加。
23
24
 
25
+ **三份 append-only 台账已分片**(2026-10-13 ledger-shard-ledgers):`regression-checklist` / `delegations` / `papercuts` 的数据行按月存 `workflow/<台账>.d/<YYYY-MM>.md`,主台账只留说明、表头与 GENERATED 区——消除「每次追加全量重写整文件」的体积与合并冲突面。读写单源 = `.agents/scripts/ledger-shards.mjs`(读侧自动合并主台账 ∪ 全部分片,既有消费者无需改动);追加一行用 `node .agents/scripts/ledger-shards.mjs --append <台账> --row "<行>"`。
26
+
24
27
  ## 使用方式
25
28
 
26
29
  - **发起新任务**:执行 `.agents/commands/new-task.md` 定义的流程(6 阶段总入口)
@@ -30,11 +33,13 @@
30
33
  - **评审**:`.agents/commands/review.md`(按 P0 / P1 / P2 分级:机器兜底 + AI 自查出清单,用户决策定性与合入)
31
34
  - **上线**:`.agents/commands/deploy.md`(上线前必跑清单)
32
35
  - **量化**:委派/自做结果记 `delegations.md`,聚合跑 `node .agents/scripts/agg-delegations.cjs`(**并发扩容门槛见该文件——数字达标前不扩并发**);语料与常驻面体积的**月度快照**跑 `node .agents/scripts/gen-workflow-metrics.mjs`(每月一行落 `metrics.md`,同月重跑即更新;明细看 stdout)
36
+ - **归档**:终态件滚动归档跑 `node .agents/scripts/archive-sweep.mjs`(缺省 dry-run 预览;`--window 21 --execute` 执行 git mv)——归档单位 = **同名家族**(intent/spec/plan/incident 同进同退:任一成员非终态 / 未满窗 / 被活跃引用 / 无日期,整族留守);终态时间三级锚 = 确认台账终态行 ts → 内容 last-touch(frontmatter-only 提交不刷新)→ 文件名日期;落点 `workflow/archive/<家族最晚终态月>/<类型>/`
37
+ - **papercut 回路(存量债清偿,手动触发)**:命令/技能卡壳记 `workflow/papercuts.md` 攒成的未升级条目 = 存量债;要清时跑 `node .agents/scripts/papercut-debt-sensor.mjs`(测 debt)→ `node .agents/scripts/papercut-debt-controller.mjs`(确定性选本轮唯一目标;源码/数据库面条目被 scope gate 拦下等授权)→ 按 `.agents/skills/papercut-fix/SKILL.md` 执行(改完 debt 应恰好 -1)。判定与排序口径单源 `.agents/loop/papercut-debt/DESIGN.md`,改口径先改设计文件
33
38
  - **追溯**:git 即审计——文档随代码同 commit、上线打 `release/<日期>` tag,`git log` 全链路可查;多人评审暂缓,git 历史即评审记录
34
- - **级别**:L0 例行 | L1 实现级(页面 / 交互 / 样式等,未命中 L2/L3)| L2 规则 / 契约(编码权威 / 共享契约 / 既有接口语义 / 全局横切口径,触达面闭集见 `.agents/commands/new-task.md` §级别判断)| L3 数据与运行时结构(schema / 迁移 SQL / DI 链 / 认证与中间件管线);混合改动就高不就低
35
- - **风险泳道(混合治理)**:级别即风险级(L0 最低 → L3 最高),按级选道——**L0 / L1 协作道(敏捷优先)**:L0 豁免 intent 直接 commit;L1 已确认 intent + 极简 plan 即动工,独立复核不设同步前置,审计异步补(check-loop、事后 review 兜底);**L2 / L3 防御道(严谨优先)**:同步确认门——spec 确认通过方可起草 plan、plan 确认后方可动手(闭环规则 1-2),L3 加新会话独立复核,未确认不放行。intent frontmatter 以 `risk_level`(=级别)落机器可读标记;批量代录与 AI 自治(confirm-doc `--batch` / `--auto`,trust-mode Standard|Trusted)均限协作道 L0/L1,协作道勾触达红线会被 check-loop 判「红线判低」hard 拦截
36
- - **探索泳道(experiment/ 前缀分支,Explore-to-Harden,2026-09-30 hybrid-governance-explore-hardening)**:experiment/ 前缀分支上的 PoC 任务在 intent frontmatter 加 `阶段: exploring` 标记——提交/推送门降级 advisory(pre-commit 闭环配对、pre-push 闭环扫描报告不阻断);L0/L1 的 draft intent 允许 spec/plan 起草与确认先于入口确认(stage-gates 起草门泳道豁免,「先起草后确认」)。**转正(合入 main)必须过加固门**:pre-push 对目标 refs/heads/main 以 `check-loop --hardening` 运行——exploring 任务的 intent 须为 approved/done、同名 plan 在场且收口(L2/L3 另须同名 spec),未收口 hard 阻断;探索作废走显式放弃态 superseded/cancelled(出列不加固)。诚实边界:分支名不进 commit——experiment/* 分支上暂存 intent 缺「阶段: exploring」由 pre-commit「泳道完整性」门禁拦截(2026-10-01 drift-hardening),残余暴露面仅剩绕过本地钩子的提交(`--no-verify` 禁令纪律覆盖)
37
- - **Trusted 自动泳道(2026-09-30 hybrid-governance-explore-hardening)**:trust-mode.json = Trusted(level 2)时,confirm-doc 的非 TTY 单份调用对 L0/L1 文档**免旗标**(无需 `--delegated` 原话 / `--auto`)自动按 AI 自治放行(台账 source=ai-auto-trust-L2);L2/L3 与 incidents 仍须人工,Standard / Strict 不隐式(fail-closed)
39
+ - **级别**:L1 实现级(未命中 L2/L3;新需求的入口是 plan)| L2 规则 / 契约(编码权威 / 共享契约 / 既有接口语义 / 全局横切口径,触达面闭集见 `.agents/commands/new-task.md` §级别判断)| L3 数据与运行时结构(schema / 迁移 SQL / DI 链 / 认证与中间件管线);混合改动就高不就低
40
+ - **风险泳道(混合治理)**:级别即风险级(L1 最低 → L3 最高),按级选道——**L1 协作道(敏捷优先)**:一份 plan 即入口,不另立 intent,独立复核不设同步前置,审计异步补(check-loop、事后 review 兜底);**L2 / L3 防御道(严谨优先)**:同步确认门——spec 确认通过方可起草 plan、plan 确认后方可动手(闭环规则 1-2),L3 加新会话独立复核,未确认不放行。intent frontmatter 以 `risk_level`(=级别)落机器可读标记;批量代录与 AI 自治(confirm-doc `--batch` / `--auto`,trust-mode Standard|Trusted)均限协作道 L1,协作道勾触达红线会被 check-loop 判「红线判低」hard 拦截
41
+ - **探索泳道(experiment/ 前缀分支,Explore-to-Harden,2026-09-30 hybrid-governance-explore-hardening)**:experiment/ 前缀分支上的 PoC 任务在 intent frontmatter 加 `阶段: exploring` 标记——提交/推送门降级 advisory(pre-commit 闭环配对、pre-push 闭环扫描报告不阻断);L1 的 draft intent 允许 spec/plan 起草与确认先于入口确认(stage-gates 起草门泳道豁免,「先起草后确认」)。**转正(合入 main)必须过加固门**:pre-push 对目标 refs/heads/main 以 `check-loop --hardening` 运行——exploring 任务的 intent 须为 approved/done、同名 plan 在场且收口(L2/L3 另须同名 spec),未收口 hard 阻断;探索作废走显式放弃态 superseded/cancelled(出列不加固)。诚实边界:分支名不进 commit——experiment/* 分支上暂存 intent 缺「阶段: exploring」由 pre-commit「泳道完整性」门禁拦截(2026-10-01 drift-hardening),残余暴露面仅剩绕过本地钩子的提交(`--no-verify` 禁令纪律覆盖)
42
+ - **Trusted 自动泳道(2026-09-30 hybrid-governance-explore-hardening)**:trust-mode.json = Trusted(level 2)时,confirm-doc 的非 TTY 单份调用对 L1 文档**免旗标**(无需 `--delegated` 原话 / `--auto`)自动按 AI 自治放行(台账 source=ai-auto-trust-L2);L2/L3 与 incidents 仍须人工,Standard / Strict 不隐式(fail-closed)
38
43
 
39
44
  ## 执行模型
40
45
 
@@ -59,12 +64,14 @@
59
64
  | 形态 | 机制 | 用法 |
60
65
  |---|---|---|
61
66
  | 多人/多分支合并冲突 | `.gitattributes` 的 `.agents/*.jsonl merge=jsonl-union` → `git-merge-jsonl.mjs` 并集去重(两侧行全保留,无冲突可解) | 需目标仓 `.gitattributes` 有该行 + 本机 `git config merge.jsonl-union.driver "node .agents/scripts/git-merge-jsonl.mjs %O %A %B"`(`init` 自动配) |
62
- | 单机多 worktree 并行 append | `confirm-doc --shard` 写 `.agents/confirmations.d/<doc>.jsonl`,各写各的互不覆盖;里程碑跑 `compact-ledgers.mjs [--execute]` 并回主台账 | `--shard` **依赖 doc 链口径**(`kit.json` 须 `policyVersion: 8`+),缺锚时参数期直接拒 |
67
+ | 单机多 worktree 并行 append | 确认行**默认**写分片 `.agents/confirmations.d/<doc>.jsonl`(2026-10-13 ledger-shard-default),各写各的互不覆盖;`--no-shard` / `CONFIRM_SHARDED=0` 回退主台账;里程碑可选跑 `compact-ledgers.mjs [--execute]` 并回主台账 | 分片默认**依赖 doc 链口径**(`kit.json` 须 `policyVersion: 8`+):缺锚时自动回退主台账并出 ℹ️(存量装户行为零变化);显式 `--shard` 缺锚仍参数期直接拒 |
63
68
  | 所有者明令删某批文档 | **特许修剪**:同笔提交 `.agents/ledger-prune-manifest.json`(`{ts, authority, reason, removes:[被删行 sha256], docs:[家族名]}`),门禁逐行对账放行 | 无 manifest 的删/改/重排**仍全拦** |
64
69
 
65
70
  哈希链的域是「同一 doc 的逻辑序」而非文件物理序——并发 append / 并集合并 / 分片归并都不会打断它;就地改行、删行、插行三类篡改照拦。诚实边界:manifest 是可写文件,**刻意伪造即可让任意删行合法化**(与「台账本地可写」同级),本通道只把「顺手手改」抬到「提交一份可被 git 历史对质的凭据」。
66
71
 
67
- > **存量装户迁移动作**:`merge=jsonl-union` 属 `.gitattributes`,而该文件是**项目自持(owned)**、`sync` 永不覆盖——升级后**不会自动获得**,需手动在目标仓 `.gitattributes` 补一行 `.agents/*.jsonl merge=jsonl-union`。driver 是本机态配置、不跨机共享(漏配退化为文本冲突,不静默丢数据但要人工解)。
72
+ > **存量装户迁移动作**:`merge=jsonl-union` 属 `.gitattributes`,而该文件是**项目自持(owned)**、`sync` 永不覆盖——升级后**不会自动获得**,需手动在目标仓 `.gitattributes` 补两行:`.agents/*.jsonl merge=jsonl-union` 与 `.agents/confirmations.d/*.jsonl merge=jsonl-union`(2026-10-13 ledger-shard-default 起分片为默认写入口径,分片行漏配则并行分支合并分片仍走文本冲突)。driver 是本机态配置、不跨机共享(漏配退化为文本冲突,不静默丢数据但要人工解)。
73
+
74
+ > **冲突自愈兜底**:gitattributes 行或 driver 漏配退化为文本冲突时,跑 `node .agents/scripts/resolve-merge-conflicts.mjs` 一键消解派生面——`workflow/INDEX.md` 冲突取当前侧后全量重生成 + `git add`;`.agents/` 下 `*.jsonl`(主台账与 `confirmations.d/` 分片同判定面)UU/AA 双方并集去重 + `git add`;删除/改删型(DD/UD/AU/DU)不写入只提示人工裁决,业务代码冲突原样保留交人收尾。
68
75
 
69
76
  其余检查(占位符、引用、模块字段、常驻面预算、量化签名、阶段索引、适配器断线、引擎脚本测试覆盖(检查 20,包源环境——新增引擎脚本默认必须带 `.test.mjs`,库件/工具须登记 `.agents/scripts-test-exempt.txt`,2026-10-01 gate-script-test-coverage))只在 `audit` 不是 `false` 时出警告。
70
77