agentic-flow-kit 1.7.16 → 1.8.1

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 (161) 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 +2 -2
  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 +2 -2
  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 +2 -2
  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 +2 -2
  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 +2 -2
  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 +2 -2
  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 +582 -49
  81. package/templates/_agents/scripts/check-prejudgment.mjs +64 -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/skills/review-method/SKILL.md +55 -0
  147. package/templates/_agents/workflow-enums.txt +8 -1
  148. package/templates/_githooks/pre-commit +110 -90
  149. package/templates/_githooks/pre-merge-commit +27 -23
  150. package/templates/_githooks/pre-push +4 -3
  151. package/templates/_github/workflows/kit-ci.yml +4 -3
  152. package/templates/workflow/README.md +14 -7
  153. package/templates/workflow/incidents/_TEMPLATE.md +4 -1
  154. package/templates/workflow/intents/_TEMPLATE.md +4 -2
  155. package/templates/workflow/papercuts.md +2 -0
  156. package/templates/workflow/plans/_TEMPLATE.md +10 -5
  157. package/templates/workflow/regression-checklist.md +1 -0
  158. package/templates/workflow/specs/_TEMPLATE.md +17 -1
  159. package/templates/_agents/hooks/check-pairing-incremental.sh +0 -43
  160. package/templates/_agents/hooks/check-wiki-ledger.sh +0 -18
  161. package/templates/_agents/scripts/rule-budget.sh +0 -74
@@ -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
 
@@ -2,12 +2,15 @@
2
2
  状态: open
3
3
  级别: L1
4
4
  发现: YYYY-MM-DD
5
+ 来源: <self | user | test | monitor——谁发现,见 .agents/workflow-enums.txt incident.source.all>
6
+ 影响环境: <dev | staging | prod | none——缺陷触达的环境,none=未触达运行环境>
5
7
  模块: <词表之一,见 .agents/workflow-modules.txt>
6
8
  沉淀: <可选:复盘沉淀到 wiki 的相对仓根路径,如 wiki/项目规范/权限收敛方案.md;不沉淀写「无」,留空待 check-loop 提醒;关单时可跑 node .agents/scripts/draft-sediment.mjs 自动抽草稿并回写本字段>
7
9
  ---
8
10
  # INCIDENT — <日期 主题>
9
11
  <!-- 复制为 YYYY-MM-DD-<主题>.md;线上或实测发现的功能缺陷都记录,历史 BUG 可回填 -->
10
- <!-- frontmatter 受限子集(2026-09-13):状态∈open/fixed/closed(严格枚举,附注写备注键);级别∈L0/L1/L2/L3;闭环引擎启用前的回填件加一行 `流程: legacy`(豁免级别/配对检查);正文不再写状态/级别/发现行 -->
12
+ <!-- frontmatter 受限子集(2026-09-13):状态∈open/fixed/closed(严格枚举,附注写备注键);级别∈L1/L2/L3;闭环引擎启用前的回填件加一行 `流程: legacy`(豁免级别/配对检查;存量 L0 件同样改 L1 或标 `流程: legacy`);正文不再写状态/级别/发现行 -->
13
+ <!-- 归因两键(2026-10-13 自 Shipyard 回灌 incident-attribution;归因检查 B6b 落地后编号以 check-loop.mjs 头部清单为准):新建件必填、锚前存量不回填;「来源」是缺陷发现方(供来源×环境交叉表机器复算,替代逐件人工判读),「影响环境」写实际触达环境(未触达写 none) -->
11
14
 
12
15
  ## 时间线
13
16
  - <发现 → 定位 → 止血 → 恢复,带时刻>
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  状态: draft
3
3
  级别: L1
4
+ 预判: <可选:kind=<require|fix|verify|review|deploy> level=<L1|L2|L3>>
4
5
  日期: YYYY-MM-DD
5
6
  模块: <词表之一,见 .agents/workflow-modules.txt>
6
7
  沉淀: <可选:沉淀到 wiki 的相对仓根路径,如 wiki/项目规范/权限收敛方案.md;不沉淀写「无」,留空待 check-loop 提醒;关单时可跑 node .agents/scripts/draft-sediment.mjs 自动抽草稿并回写本字段>
@@ -8,8 +9,9 @@
8
9
  ---
9
10
  # INTENT — <主题>
10
11
  <!-- 复制本模板为 YYYY-MM-DD-<主题>.md 后填写;plans/ 下同名文件与本文件配对 -->
11
- <!-- frontmatter 受限子集(2026-09-13):每行 `键: 值`;状态∈draft/approved/done/superseded/cancelled(严格枚举,附注写备注键);级别∈L0/L1/L2/L3;check-loop 只扫 frontmatter 取机器字段,正文不再写状态/级别行 -->
12
- <!-- 探索泳道(可选,2026-09-30 hybrid-governance-explore-hardening):experiment/ 前缀分支上的 PoC 任务在 frontmatter 加「阶段: exploring」——提交/推送门降级 advisory,spec/plan 可先于本入口确认起草(限 L0/L1);转正合入 main 前须收口(本档 approved/done + 同名 plan/spec 在场,check-loop --hardening 加固门),或显式放弃(superseded/cancelled) -->
12
+ <!-- frontmatter 受限子集(2026-09-13):每行 `键: 值`;状态∈draft/approved/done/superseded/cancelled(严格枚举,附注写备注键);级别∈L1/L2/L3;check-loop 只扫 frontmatter 取机器字段,正文不再写状态/级别行 -->
13
+ <!-- 探索泳道(可选,2026-09-30 hybrid-governance-explore-hardening):experiment/ 前缀分支上的 PoC 任务在 frontmatter 加「阶段: exploring」——提交/推送门降级 advisory,spec/plan 可先于本入口确认起草(限 L1);转正合入 main 前须收口(本档 approved/done + 同名 plan/spec 在场,check-loop --hardening 加固门),或显式放弃(superseded/cancelled) -->
14
+ <!-- 预判(可选,2026-10-13 自 Shipyard 回灌 prejudgment-ledger):定级时先做结构化预判,结果如实写「预判: kind=<require|fix|verify|review|deploy> level=<L1|L2|L3>」——intents≡require、incidents≡fix;与实际落位不符时 check-loop 路由预判一致性检查(B6b 落地后编号以 check-loop.mjs 头部清单为准)出 WARN 留账。缺字段零告警(存量宽容不回填,不做强制前置)——advisory 灰度口径 -->
13
15
 
14
16
  ## 背景与问题
15
17
  <为什么做;写明需求来源(工单 / 沟通记录 / 待办事项)>
@@ -2,6 +2,8 @@
2
2
 
3
3
  > `.agents/commands/`、`.agents/roles/` 或已装技能在真实任务中卡住、误导、缺步骤时记一行,**不当场顺手改**。
4
4
  > 同一文件命中第 2 次或用户点名时,升级为 docs 修复 commit。
5
+ > **分片(2026-10-13 ledger-shard-ledgers)**:数据行按月存 `workflow/papercuts.d/<YYYY-MM>.md`(本文件只留说明与表头)。追加一行用 `node .agents/scripts/ledger-shards.mjs --append papercuts --row "<行>"`(缺省按行内日期定月,`--month` 可覆盖);读侧(`papercut-debt-sensor.mjs` 等)自动合并主台账 ∪ 全部分片,无需改动。手工编辑分片亦可,但须自带表头。
6
+ > **存量债回路**:未升级条目累积 = 存量债,清理跑 papercut 回路(传感器测 debt → 控制器选目标 → `papercut-fix` 技能执行),口径单源 `.agents/loop/papercut-debt/DESIGN.md`。
5
7
 
6
8
  | 日期 | 位置 | 症状 | 拟修 |
7
9
  |------|------|------|------|
@@ -5,25 +5,30 @@
5
5
  ---
6
6
  # PLAN — <与入口文档同名主题>
7
7
  <!-- 与 intents/ 或 incidents/ 下同名入口文档配对;L2/L3 必须先有 ../specs/ 同名 spec 确认通过;AI 起草、用户对话内确认后开工 -->
8
- <!-- frontmatter 受限子集(2026-09-13):状态∈draft/approved/done/superseded/cancelled(严格枚举,附注写备注键);级别∈L0/L1/L2/L3;正文不再写状态/级别行 -->
8
+ <!-- frontmatter 受限子集(2026-09-13):状态∈draft/approved/done/superseded/cancelled(严格枚举,附注写备注键);级别∈L1/L2/L3;正文不再写状态/级别行 -->
9
9
  <!-- L1 极简形态(Quick-Plan,与 fill-plan.mjs 单源一致):单/少文件微改动只填「改动方案」+「约束与风险」+「验证计划」三节(L1 主节标题模板正文用「改动面」,fill-plan 生成「改动方案」——check-loop 证据校验对 改动面/任务拆解/改动方案 三种节名均识别为声明文件来源)——改动方案逐条列改哪个文件做什么(判据细节直接写进条目),验证计划一行静态门 + 按需 UI 实测;任务拆解/执行顺序仅 L1 多文件多步骤时保留 -->
10
+ <!-- L1 直达(2026-10-13 自 Shipyard 回灌):新单用 fill-plan.mjs --level L1,本文件即入口,不另立 intent(无同名 intent/incident 时起草门放行;文件已在则级别以文件为准,禁用 --level L1 放行存量 L2 plan)。修复类另保留 ../incidents/ 同名件 -->
10
11
  <!-- 待澄清标记(2026-10-12 needs-clarification):判据不明 / 依赖不确定 / 用户没说的细节,照实写一行
11
12
  `- 待澄清:<你卡在哪>`,不要猜(语义说明同 specs 模板:占位符=忘了填,本标记=我不知道)。
12
13
  起草不拦,draft→approved 确认时仍挂着会被 confirm-doc 拒绝;解决后改行首为 `- 已澄清:` 或删行。 -->
13
14
 
14
- 对应入口:../intents/YYYY-MM-DD-<主题>.md 或 ../incidents/YYYY-MM-DD-<主题>.md(保留实际一项)
15
- 对应 spec:../specs/YYYY-MM-DD-<主题>.md(L1 可省略)
15
+ 对应入口:L1 = 本 plan。修复类另保留 ../incidents/YYYY-MM-DD-<主题>.md。L2/L3 = ../intents/YYYY-MM-DD-<主题>.md
16
+ 对应 spec:../specs/YYYY-MM-DD-<主题>.md(仅 L2/L3)
16
17
 
17
18
  ## 改动面(L1 极简形态主节;L2/L3 可作任务拆解的汇总或删本节)
18
19
  - <文件/组件>:<做什么;判据细节直接写进条目,如「L771 message.success 改『更新成功』」>
20
+ <!-- build.md 确认的改动清单确认后回填本节落盘(对话留痕仅供当次)——改动面 + 任务勾选态 + git status = 会话重入三锚(2026-10-11 session-context,自 Shipyard 回灌) -->
19
21
 
20
22
  ## 任务拆解(L2/L3 必填;L1 仅多文件多步骤时用,单任务微改动删本节)
21
- 1. <任务>
23
+ <!-- 任务即勾选态(2026-10-11 session-context,自 Shipyard 回灌):完成一项立刻勾选并回填留痕;压缩 / 新会话续作先读本表勾选态 + git status 重建进度,禁凭记忆补勾 -->
24
+ - [ ] 1. <任务>
22
25
  - 判据:<怎样算完成;尽量对应一个测试或可复现操作>
23
26
  - 风险:低 / 中 / 高(<原因>)
24
- 2. <任务>
27
+ - 留痕:(勾选时回填 commit SHA / 测试名 / 实测输出)
28
+ - [ ] 2. <任务>
25
29
  - 判据:…
26
30
  - 风险:…
31
+ - 留痕:…
27
32
 
28
33
  ## 执行顺序(L2/L3 必填;L1 单文件微改动删本节)
29
34
  <1 → 2 → 3;标注依赖关系>
@@ -10,6 +10,7 @@
10
10
  3. **模块上线/走查后**:为该模块补关键路径条目
11
11
  4. 条目过时(功能下线/行为变更)时删除或改写,不保留失效条目
12
12
  5. **新增防复发条目落点优先级**:自动化用例 > 脚本化断言 > 人工步骤(仅剩视觉/交互断言无法脚本化时)
13
+ 6. **分片(2026-10-13 ledger-shard-ledgers)**:「防复发验证」节的数据行按月存 `workflow/regression-checklist.d/<YYYY-MM>.md`(该节是唯一 append-only 追加区;上方模块节为稳定参考内容,留守本文件)。追加一行用 `node .agents/scripts/ledger-shards.mjs --append regression-checklist --row "<行>"`;读侧自动合并主台账 ∪ 全部分片。
13
14
 
14
15
  ## 回归必过
15
16
 
@@ -50,6 +50,22 @@ THEN 行是机器对账断言:声明了场景却缺「- THEN <可观测结果>
50
50
  | <示例:schema / 迁移路径约束> | <涉及路径与处理方式> |
51
51
  | <示例:前端或客户端约定(如有)> | <本 spec 涉及哪些约定> |
52
52
 
53
+ ## 验收判据
54
+ <!-- 判据级收敛对账的机器输入(check-loop 验收判据对账段,2026-10-13 自 Shipyard 回灌;B6b 落地后编号以 check-loop.mjs 头部清单为准):
55
+ 每行一条判据,「证据」须机器可解析。路径:文件必须存在。机器不读正文,不判断它和判据是否相关(那一步留给新会话复核)。
56
+ 命令:只认全量门跑过的 `npm test` / `node .agents/scripts/verify.mjs`(kit 全量门 = verify.mjs 七门编排;
57
+ 装户项目测试命令各异,verify.mjs `--test-cmd` 注入的算 npm test 面)。
58
+ 还须 workflow/verify-evidence.md 有一行时间不早于本 spec「日期」的全绿凭证;没有这行 = 未覆盖。
59
+ 日期口径:frontmatter「日期」与全绿行时间同为 UTC(fill-spec 默认即此);手写勿用本地时区日期——
60
+ UTC+8 凌晨 0–8 点落的全绿行日期为前一日,会对不上(硬拦,08:00 后重跑门即解)。
61
+ 不在全量门里的检查(UI 实测 / 回归冒烟等)改记证据文件路径。
62
+ 「状态」写「覆盖」而证据无效仍判未覆盖。人工走查状态写「人工」,证据列留空(仅「人工+空证据」豁免机器对账;
63
+ 截图等图片不在路径白名单,需留痕改存 .md 报告后引路径)。
64
+ 无本节或表为空 → WARN;证据无效的 WARN / HARD-BLOCK 分档与生效锚随 B6b 对账段落地。 -->
65
+ | 判据(可观察行为) | 证据(测试文件 / 命令 / 证据文件) | 状态 |
66
+ |---|---|---|
67
+ | <行为 1> | <路径或命令> | <覆盖 / 未覆盖 / 人工> |
68
+
53
69
  ## 风险评估
54
70
  - <风险点 1> | 应对:<测试 / hook / 评审>
55
71
  - <风险点 2> | 应对:…
@@ -58,7 +74,7 @@ THEN 行是机器对账断言:声明了场景却缺「- THEN <可观测结果>
58
74
  > 个人工作流:确认 = 用户在对话内一句话通过;无第二审批人,追溯靠 git(commit 记录确认时点)。
59
75
  > 确认结果 / 确认时间写在文件头 frontmatter(L3 由 check-loop 强制校验);本节只留叙述性复核记录。
60
76
 
61
- - 独立复核:<L3 强制:另开新会话由 AI 复核本 spec,记录复核会话与结论;L1 / L2 无则删除本行>
77
+ - 独立复核:<L3 强制:另开新会话由 AI 复核本 spec,记录复核会话与结论;L1 / L2 无则删除本行。复核行须落「复核上下文:<会话/子代理 id>」——隔离前提的机器事实,advisory>
62
78
  - 复核结论:<无则删除本行>
63
79
  - 返修意见:<无则删除本行>
64
80
  - 确认通过后,方可起草 ../plans/YYYY-MM-DD-<主题>.md
@@ -1,43 +0,0 @@
1
- #!/bin/sh
2
- # 闭环配对(增量版):本次暂存的 intents/ incidents/ 入口文档必须已有同名 plan(L2/L3 另须同名 spec)
3
- # 目的:把 check-loop.sh「配对断裂」hard-block 的发现时机从 pre-push 提前到 commit
4
- # (papercut 2026-09-15:maintain.md 只写「incident≡intent 免另立 intent」,未把配 plan 写成显式步骤,
5
- # 按文档字面执行三次 commit 全绿、push 才爆红,只能后补;
6
- # 2026-09-27 audit-gate-hardening 补齐 spec 档——此前只查 plan,L2/L3 缺 spec 仍要拖到 push 才爆红)
7
- # 口径与 check-loop.sh 对齐:入口文档(intents/ incidents/ 直下 .md)↔ workflow/plans/ 同名,
8
- # L2/L3 级别另须 workflow/specs/ 同名(check-loop 检查 1 同款分档);
9
- # 同 commit 携带 plan/spec 合法(检查的是工作区文件存在,staged 新建同样命中)。
10
- # 已知边界:legacy 豁免与级别读取均基于工作区文件而非暂存 blob——add 后又改工作区时可能误豁免/误拦(逐文件取 blob 的 fork 成本大于收益,接受)。
11
-
12
- cd "$(git rev-parse --show-toplevel)" || exit 1
13
-
14
- fail=0
15
- # -c core.quotepath=off:quotepath 默认 true 时非 ASCII 路径被引号转义("workflow/\346..."),
16
- # ^workflow/ 前缀匹配失配 → 门禁静默跳过——教训与修法同 check-wiki-ledger.sh(2026-09-27 gate-coverage)
17
- for f in $(git -c core.quotepath=off diff --cached --name-only --diff-filter=ACMR | grep -E '^workflow/(intents|incidents)/[^/]+\.md$' | grep -v '_TEMPLATE\.md$'); do
18
- # 闭环引擎启用前的回填件带「流程: legacy」豁免配对检查(与 check-loop 同口径)
19
- if grep -q '^流程: legacy' "$f"; then
20
- continue
21
- fi
22
- base=$(basename "$f" .md)
23
- if [ ! -f "workflow/plans/$base.md" ]; then
24
- echo "闭环配对(增量)— BLOCK:"
25
- echo " 入口缺同名 plan: $f(应在 workflow/plans/$base.md)"
26
- echo " L1 极简 plan 只需「改动面 + 验证方式」两节(复制 workflow/plans/_TEMPLATE.md)"
27
- fail=1
28
- fi
29
- lvl=$(sed -n 's/^级别:[[:space:]]*//p' "$f" | head -1)
30
- if [ "$lvl" = "L2" ] || [ "$lvl" = "L3" ]; then
31
- if [ ! -f "workflow/specs/$base.md" ]; then
32
- echo "闭环配对(增量)— BLOCK:"
33
- echo " 入口缺同名 spec: $f(级别 $lvl 须三件套,应在 workflow/specs/$base.md)"
34
- echo " 与 pre-push check-loop 检查 1 同口径——先起草 spec 走 design.md,再提交"
35
- fail=1
36
- fi
37
- fi
38
- done
39
-
40
- if [ $fail -ne 0 ]; then
41
- echo "pre-commit: 入口文档配对不全(plan / L2-L3 spec),提交已阻止(与 pre-push check-loop 同口径,发现时机提前到 commit)" >&2
42
- fi
43
- exit $fail
@@ -1,18 +0,0 @@
1
- #!/bin/sh
2
- # wiki 台账一致性(增量版):本次暂存触及 wiki/ 时跑 verify 三方校验(磁盘 ↔ INDEX ↔ 看板 DATA)
3
- # 目的:给「登记动作」装触发点——verify 此前无任何钩子调用,只能靠「触及 wiki 时手跑」的文字纪律
4
- # (incident 2026-09-16-wiki-drift-and-verifier-gaps 认定的根因);本脚本把发现时机提前到 commit。
5
- # 口径与 .agents/scripts/verify-wiki-consistency.mjs 一致:活层新增/删除/移动未登记、数据维护批次目录未入台账即拦。
6
- # 注意 `-c core.quotepath=off`:core.quotepath 为 git 默认 true 时中文路径被转义加引号——实测输出
7
- # `"wiki/\346\265\213\350\257\225..."`,`^wiki/` 前缀匹配失配 → 门禁静默跳过(本机 .gitconfig 恰好设 false,本地不复现)。
8
-
9
- cd "$(git rev-parse --show-toplevel)" || exit 1
10
-
11
- git -c core.quotepath=off diff --cached --name-only | grep -q '^wiki/' || exit 0
12
-
13
- if ! node .agents/scripts/verify-wiki-consistency.mjs; then
14
- echo "wiki 台账(增量)— BLOCK:"
15
- echo " 先跑 node .agents/scripts/gen-wiki-board.mjs 补 INDEX/看板(或补 wiki/数据维护/README.md 登记行),再原路重试提交"
16
- exit 1
17
- fi
18
- exit 0
@@ -1,74 +0,0 @@
1
- #!/bin/sh
2
- # 常驻面体积预算检查(单源:本脚本 + .agents/rule-budgets.txt;两个触发点共用)
3
- # 用法:sh .agents/scripts/rule-budget.sh [--all|--staged]
4
- # --all 查「提交后树」全量(check-loop.sh 检查 13 调用,warning 侧)
5
- # --staged 仅查本次暂存触及的条目 + 触及目录的合计(.githooks/pre-commit 调用,超限即硬拦)
6
- # 退出码:0 通过;1 有超限(违例逐条打到 stdout,调用方决定警告还是阻断)
7
- # 「提交后树」= 索引(index)内容:staged 版优先于 HEAD;无 git(fixture 沙箱)时回退工作区文件。
8
- # 预算表按字节读,显式去 \r——本仓库 core.autocrlf=true,表文件检出即 CRLF,行尾残留会让数值比较失配。
9
- # 字节口径 = 索引 / HEAD 内容(git cat-file,LF 归一)。**禁用 wc -c 核对**——工作区文件是 CRLF,量出来系统性偏大
10
- # (2026-09-21 实测 .agents/commands/ 工作区 39963B vs 索引 39451B,差 ~500B,一度误判「已超限」)。
11
- cd "$(git rev-parse --show-toplevel 2>/dev/null)" || true # 非 git 环境(fixture)留在原地
12
- MODE=${1:---all}
13
- BUDGETS=.agents/rule-budgets.txt
14
- [ -f "$BUDGETS" ] || exit 0
15
-
16
- # 取「提交后」字节数:索引 → HEAD → 工作区
17
- fsize() { # <path>
18
- if git cat-file -e ":$1" 2>/dev/null; then git cat-file -s ":$1"
19
- elif git cat-file -e "HEAD:$1" 2>/dev/null; then git cat-file -s "HEAD:$1"
20
- else wc -c < "$1" 2>/dev/null | tr -d '[:space:]'
21
- fi
22
- }
23
-
24
- staged_list=""
25
- if [ "$MODE" = "--staged" ]; then
26
- staged_list=$(git -c core.quotepath=off diff --cached --name-only 2>/dev/null)
27
- fi
28
-
29
- viol=0
30
- while IFS= read -r line; do
31
- line=$(printf '%s' "$line" | tr -d '\r')
32
- pat=${line%% *}
33
- lim=${line##* }
34
- case "$pat" in ''|'#'*) continue ;; esac
35
- case "$lim" in ''|*[!0-9]*) continue ;; esac
36
- case "$pat" in
37
- */) # 目录合计:--staged 下仅当暂存触及该目录内文件才查(case 字面前缀匹配——pat 含 . 时不能当正则用,2026-09-24)
38
- if [ "$MODE" = "--staged" ]; then
39
- found=0
40
- while IFS= read -r sf; do
41
- case "$sf" in "$pat"*) found=1 ;; esac
42
- done <<EOF
43
- $staged_list
44
- EOF
45
- [ "$found" = "1" ] || continue
46
- fi
47
- total=0
48
- for f in "$pat"*; do
49
- [ -f "$f" ] || continue
50
- total=$((total + $(fsize "$f")))
51
- done
52
- if [ "$total" -gt "$lim" ]; then
53
- echo "常驻面超限:${pat} 合计 ${total}B > 上限 ${lim}B"
54
- viol=1
55
- fi
56
- ;;
57
- *) # 逐文件(glob 刻意不加引号以展开;无命中时 [ -f ] 兜住)
58
- for f in $pat; do
59
- [ -f "$f" ] || continue
60
- if [ "$MODE" = "--staged" ]; then
61
- printf '%s\n' "$staged_list" | grep -qxF "$f" || continue
62
- fi
63
- b=$(fsize "$f")
64
- if [ "$b" -gt "$lim" ]; then
65
- echo "常驻面超限:$f = ${b}B > 上限 ${lim}B"
66
- viol=1
67
- fi
68
- done
69
- ;;
70
- esac
71
- done < "$BUDGETS"
72
-
73
- [ "$viol" -eq 0 ] || exit 1
74
- exit 0