agentic-flow-kit 1.7.0 → 1.7.16

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 (162) hide show
  1. package/README.md +81 -9
  2. package/modules/gates/README.md +1 -0
  3. package/modules/gates/test-protect/README.md +23 -0
  4. package/modules/gates/test-protect/check-test-protect.mjs +64 -0
  5. package/modules/gates/test-protect/local-pre-commit.line +1 -0
  6. package/modules/hosts/README.md +57 -0
  7. package/modules/hosts/claude/commands/wf-build.md +5 -24
  8. package/modules/hosts/claude/commands/wf-deploy.md +1 -0
  9. package/modules/hosts/claude/commands/wf-design.md +7 -6
  10. package/modules/hosts/claude/commands/wf-gate-checklist.md +1 -3
  11. package/modules/hosts/claude/commands/wf-new-task.md +42 -21
  12. package/modules/hosts/claude/commands/wf-plan.md +1 -1
  13. package/modules/hosts/claude/commands/wf-review.md +1 -1
  14. package/modules/hosts/claude/commands/wf-sync-hosts.md +8 -16
  15. package/modules/hosts/claude/commands/wf-test.md +5 -4
  16. package/modules/hosts/codex/commands/wf-build.md +5 -24
  17. package/modules/hosts/codex/commands/wf-deploy.md +1 -0
  18. package/modules/hosts/codex/commands/wf-design.md +7 -6
  19. package/modules/hosts/codex/commands/wf-gate-checklist.md +1 -3
  20. package/modules/hosts/codex/commands/wf-new-task.md +42 -21
  21. package/modules/hosts/codex/commands/wf-plan.md +1 -1
  22. package/modules/hosts/codex/commands/wf-review.md +1 -1
  23. package/modules/hosts/codex/commands/wf-sync-hosts.md +8 -16
  24. package/modules/hosts/codex/commands/wf-test.md +5 -4
  25. package/modules/hosts/cursor/commands/wf-build.md +5 -24
  26. package/modules/hosts/cursor/commands/wf-deploy.md +1 -0
  27. package/modules/hosts/cursor/commands/wf-design.md +7 -6
  28. package/modules/hosts/cursor/commands/wf-gate-checklist.md +1 -3
  29. package/modules/hosts/cursor/commands/wf-new-task.md +42 -21
  30. package/modules/hosts/cursor/commands/wf-plan.md +1 -1
  31. package/modules/hosts/cursor/commands/wf-review.md +1 -1
  32. package/modules/hosts/cursor/commands/wf-sync-hosts.md +8 -16
  33. package/modules/hosts/cursor/commands/wf-test.md +5 -4
  34. package/modules/hosts/opencode/commands/wf-build.md +5 -24
  35. package/modules/hosts/opencode/commands/wf-deploy.md +1 -0
  36. package/modules/hosts/opencode/commands/wf-design.md +7 -6
  37. package/modules/hosts/opencode/commands/wf-gate-checklist.md +1 -3
  38. package/modules/hosts/opencode/commands/wf-new-task.md +42 -21
  39. package/modules/hosts/opencode/commands/wf-plan.md +1 -1
  40. package/modules/hosts/opencode/commands/wf-review.md +1 -1
  41. package/modules/hosts/opencode/commands/wf-sync-hosts.md +8 -16
  42. package/modules/hosts/opencode/commands/wf-test.md +5 -4
  43. package/modules/hosts/trae/commands/wf-build.md +5 -24
  44. package/modules/hosts/trae/commands/wf-deploy.md +1 -0
  45. package/modules/hosts/trae/commands/wf-design.md +7 -6
  46. package/modules/hosts/trae/commands/wf-gate-checklist.md +1 -3
  47. package/modules/hosts/trae/commands/wf-new-task.md +42 -21
  48. package/modules/hosts/trae/commands/wf-plan.md +1 -1
  49. package/modules/hosts/trae/commands/wf-review.md +1 -1
  50. package/modules/hosts/trae/commands/wf-sync-hosts.md +8 -16
  51. package/modules/hosts/trae/commands/wf-test.md +5 -4
  52. package/package.json +2 -2
  53. package/src/add-gate.mjs +25 -1
  54. package/src/add-gate.test.mjs +103 -0
  55. package/src/cli.mjs +59 -5
  56. package/src/doctor.mjs +136 -12
  57. package/src/executor.mjs +245 -0
  58. package/src/executor.test.mjs +292 -0
  59. package/src/gates.test.mjs +17 -0
  60. package/src/init.mjs +14 -1
  61. package/src/init.test.mjs +19 -0
  62. package/src/instance-ref.test.mjs +62 -0
  63. package/src/jscpd-drift.test.mjs +144 -0
  64. package/src/profiles.mjs +3 -0
  65. package/src/render.mjs +6 -1
  66. package/src/rule-budget.test.mjs +103 -0
  67. package/src/sync-hosts.mjs +41 -45
  68. package/src/sync-hosts.test.mjs +67 -56
  69. package/src/trae-hooks.test.mjs +15 -3
  70. package/src/validate.mjs +72 -0
  71. package/src/validate.test.mjs +95 -0
  72. package/templates/.gitattributes +8 -0
  73. package/templates/AGENTS.md +2 -1
  74. package/templates/_agents/commands/build.md +5 -24
  75. package/templates/_agents/commands/deploy.md +1 -0
  76. package/templates/_agents/commands/design.md +7 -6
  77. package/templates/_agents/commands/gate-checklist.md +1 -3
  78. package/templates/_agents/commands/new-task.md +42 -21
  79. package/templates/_agents/commands/plan.md +1 -1
  80. package/templates/_agents/commands/review.md +1 -1
  81. package/templates/_agents/commands/sync-hosts.md +8 -16
  82. package/templates/_agents/commands/test.md +5 -4
  83. package/templates/_agents/control-surfaces.txt +53 -0
  84. package/templates/_agents/engine-lock.json +246 -0
  85. package/templates/_agents/lane-surfaces.txt +1 -1
  86. package/templates/_agents/level-hints.txt +30 -0
  87. package/templates/_agents/scripts/agg-delegations.cjs +51 -6
  88. package/templates/_agents/scripts/agg-delegations.test.mjs +84 -4
  89. package/templates/_agents/scripts/check-engine-integrity.mjs +217 -0
  90. package/templates/_agents/scripts/check-engine-integrity.test.mjs +215 -0
  91. package/templates/_agents/scripts/check-lane-surface.mjs +78 -24
  92. package/templates/_agents/scripts/check-lane-surface.test.mjs +66 -0
  93. package/templates/_agents/scripts/check-ledger-invariant.mjs +112 -14
  94. package/templates/_agents/scripts/check-ledger-invariant.test.mjs +5 -1
  95. package/templates/_agents/scripts/check-loop-rev.test.mjs +6 -4
  96. package/templates/_agents/scripts/check-loop.mjs +255 -45
  97. package/templates/_agents/scripts/check-loop.test.mjs +330 -15
  98. package/templates/_agents/scripts/check-metric-claims.mjs +4 -2
  99. package/templates/_agents/scripts/compact-ledgers.mjs +97 -0
  100. package/templates/_agents/scripts/compact-ledgers.test.mjs +162 -0
  101. package/templates/_agents/scripts/confirm-doc.mjs +54 -12
  102. package/templates/_agents/scripts/confirm-doc.test.mjs +59 -0
  103. package/templates/_agents/scripts/doctor.test.mjs +294 -1
  104. package/templates/_agents/scripts/draft-sediment.mjs +178 -0
  105. package/templates/_agents/scripts/draft-sediment.test.mjs +272 -0
  106. package/templates/_agents/scripts/edit-face-check.test.mjs +5 -4
  107. package/templates/_agents/scripts/fill-intent.mjs +2 -2
  108. package/templates/_agents/scripts/fixture-scripts.mjs +153 -0
  109. package/templates/_agents/scripts/fixture-scripts.test.mjs +107 -0
  110. package/templates/_agents/scripts/gate-checklist.mjs +6 -3
  111. package/templates/_agents/scripts/gate-checklist.test.mjs +2 -5
  112. package/templates/_agents/scripts/gen-wiki-board.mjs +61 -6
  113. package/templates/_agents/scripts/gen-wiki-board.test.mjs +74 -1
  114. package/templates/_agents/scripts/gen-workflow-dashboard.mjs +10 -13
  115. package/templates/_agents/scripts/gen-workflow-metrics.mjs +12 -30
  116. package/templates/_agents/scripts/git-merge-jsonl.mjs +63 -0
  117. package/templates/_agents/scripts/git-merge-jsonl.test.mjs +125 -0
  118. package/templates/_agents/scripts/kb-search.mjs +87 -12
  119. package/templates/_agents/scripts/kb-search.test.mjs +83 -0
  120. package/templates/_agents/scripts/ledger-doc-chain.test.mjs +166 -0
  121. package/templates/_agents/scripts/ledger-loader.mjs +108 -0
  122. package/templates/_agents/scripts/ledger-loader.test.mjs +131 -0
  123. package/templates/_agents/scripts/ledger-prune.mjs +96 -0
  124. package/templates/_agents/scripts/ledger-prune.test.mjs +120 -0
  125. package/templates/_agents/scripts/ledger-ts-monotonic.test.mjs +135 -0
  126. package/templates/_agents/scripts/level-criteria.mjs +232 -0
  127. package/templates/_agents/scripts/level-criteria.test.mjs +279 -0
  128. package/templates/_agents/scripts/pipeline-run.mjs +5 -3
  129. package/templates/_agents/scripts/policy.mjs +47 -0
  130. package/templates/_agents/scripts/solidify-task.mjs +1 -1
  131. package/templates/_agents/scripts/stage-gates.mjs +52 -10
  132. package/templates/_agents/scripts/stage-gates.test.mjs +105 -0
  133. package/templates/_agents/scripts/verify-wiki-consistency.mjs +34 -0
  134. package/templates/_agents/scripts/verify-wiki-consistency.test.mjs +44 -2
  135. package/templates/_agents/scripts/verify.mjs +1 -1
  136. package/templates/_agents/scripts/wf-journal.test.mjs +1 -1
  137. package/templates/_agents/scripts/wiki-search.test.mjs +5 -6
  138. package/templates/_agents/scripts/workflows-check.mjs +1 -1
  139. package/templates/_agents/scripts-test-exempt.txt +3 -1
  140. package/templates/_agents/skills/wiki/SKILL.md +5 -3
  141. package/templates/_agents/workflows/pipeline-closing.md +4 -5
  142. package/templates/_githooks/pre-commit +3 -34
  143. package/templates/_githooks/pre-push +3 -3
  144. package/templates/wiki/INDEX.md +44 -1
  145. package/templates/wiki//347/237/245/350/257/206/346/262/211/346/267/200/346/200/273/350/247/210.html +22 -1
  146. package/templates/workflow/README.md +11 -0
  147. package/templates/workflow/delegations.md +5 -4
  148. package/templates/workflow/incidents/_TEMPLATE.md +2 -0
  149. package/templates/workflow/intents/_TEMPLATE.md +3 -0
  150. package/templates/workflow/plans/_TEMPLATE.md +4 -0
  151. package/templates/workflow/specs/_TEMPLATE.md +23 -0
  152. package/modules/hosts/claude/commands/wf-source-sync-check.md +0 -91
  153. package/modules/hosts/codex/commands/wf-source-sync-check.md +0 -91
  154. package/modules/hosts/cursor/commands/wf-source-sync-check.md +0 -91
  155. package/modules/hosts/opencode/commands/wf-source-sync-check.md +0 -91
  156. package/modules/hosts/trae/commands/wf-source-sync-check.md +0 -92
  157. package/templates/_agents/commands/source-sync-check.md +0 -105
  158. package/templates/_agents/scripts/check-ledger.mjs +0 -109
  159. package/templates/_agents/scripts/check-ledger.test.mjs +0 -197
  160. package/templates/_agents/scripts/source-sync-check.mjs +0 -156
  161. package/templates/_agents/scripts/source-sync-check.test.mjs +0 -281
  162. package/templates/_agents/workflows/source-sync-repair.md +0 -30
@@ -0,0 +1,246 @@
1
+ {
2
+ "schema": 1,
3
+ "generatedAt": "2026-10-13T08:17:26.315Z",
4
+ "files": {
5
+ ".github/workflows/ci.yml": {
6
+ "sha256": "ae6b751a29ce08f28f8831fc9b64770acce4d42fc6a5bd60286eca67e8488bd9",
7
+ "hard": 3
8
+ },
9
+ ".github/workflows/release.yml": {
10
+ "sha256": "c8032a042da93974d7481b37a5a51eefa421b1eacc065424f35095ccd00b7c6b",
11
+ "hard": 0
12
+ },
13
+ "templates/AGENTS.md": {
14
+ "sha256": "013df60e0236f3bbd22ca9d8140cc922cdfd603a3efdf58b13a95a6e561d0017",
15
+ "hard": 27
16
+ },
17
+ "templates/_agents/control-surfaces.txt": {
18
+ "sha256": "ae6072b58fde4cf2ad65ce27d0216133dabbd189b0542a0dbf11bbd9e0608407",
19
+ "hard": 29
20
+ },
21
+ "templates/_agents/lane-surfaces.txt": {
22
+ "sha256": "e378c19f5a85bd9118a1e2e04fb18645482990e886df32ea97c4d65411d850e6",
23
+ "hard": 5
24
+ },
25
+ "templates/_agents/level-hints.txt": {
26
+ "sha256": "6cb3a2c9f2bdd9b0f859c3eb67c310e2dab12d8777a5bd82a31a8634890b0a43",
27
+ "hard": 0
28
+ },
29
+ "templates/_agents/metric-claims.txt": {
30
+ "sha256": "e668589d817d589b9f81ba73460c0bd024d6d34203c9f1fa36bb9019d5e8b3ce",
31
+ "hard": 8
32
+ },
33
+ "templates/_agents/rule-budgets.txt": {
34
+ "sha256": "cd5fee0ae3eebe0398f2b15d4c801bc7f30c4ec20d46508033eeebb4a417a960",
35
+ "hard": 3
36
+ },
37
+ "templates/_agents/scripts-test-exempt.txt": {
38
+ "sha256": "05a96ae19289deb074392ca4de212aa277dabf2ea8bc7be8bceb9f3c7a234fbd",
39
+ "hard": 5
40
+ },
41
+ "templates/_agents/scripts/agg-gate-stats.mjs": {
42
+ "sha256": "488517dfdc37b79b327e1f47603c94fc1fc236145d12df213e6ce2de60f11730",
43
+ "hard": 0
44
+ },
45
+ "templates/_agents/scripts/check-engine-integrity.mjs": {
46
+ "sha256": "e62a23c861d060ee74f15aae57410cfce8e644e29517ebc5b1c1c3d85e5935c1",
47
+ "hard": 2
48
+ },
49
+ "templates/_agents/scripts/check-hygiene.mjs": {
50
+ "sha256": "0fecd44c28f1b5759a4bb01f3c19213cace48a162e27802f2f1c1df67eec15ff",
51
+ "hard": 0
52
+ },
53
+ "templates/_agents/scripts/check-lane-surface.mjs": {
54
+ "sha256": "c22ad9ab80070051d2c9db344f407c70e9d9a2815dc0c73066f43bc16592bf98",
55
+ "hard": 2
56
+ },
57
+ "templates/_agents/scripts/check-ledger-invariant.mjs": {
58
+ "sha256": "2d187a82781a5e076985d91f1a4734b45cd507c1b87942064bad949bd0b3f806",
59
+ "hard": 2
60
+ },
61
+ "templates/_agents/scripts/check-loop.mjs": {
62
+ "sha256": "a7af1f7c065b20e81b137027d02762d1414ea2ead778e45b5f17dcb7c14017f4",
63
+ "hard": 32
64
+ },
65
+ "templates/_agents/scripts/check-metric-claims.mjs": {
66
+ "sha256": "2c2d8615e9418117d43202dc67cd4131e43fb6c095686363dfcd2fd2cb542f2a",
67
+ "hard": 0
68
+ },
69
+ "templates/_agents/scripts/check-stage-index.mjs": {
70
+ "sha256": "9118b8fe57b80b5d36a0db38ed141c08036629895c143a64f0c29e301b2218c8",
71
+ "hard": 0
72
+ },
73
+ "templates/_agents/scripts/compact-ledgers.mjs": {
74
+ "sha256": "b517a775bcbcaaca8b8e58ed85c611c9fc1a40f64b19ee0f40ea137b40a0042e",
75
+ "hard": 1
76
+ },
77
+ "templates/_agents/scripts/confirm-doc.mjs": {
78
+ "sha256": "8d9f8478fa80be447c8e372a94be4b991c02a9077c7bd087bbf8e77feb65834e",
79
+ "hard": 12
80
+ },
81
+ "templates/_agents/scripts/draft-sediment.mjs": {
82
+ "sha256": "a9c51e3fd139adf32755d882e0de53f208784be68a75c1881658c3886605c76d",
83
+ "hard": 1
84
+ },
85
+ "templates/_agents/scripts/edit-face-check.mjs": {
86
+ "sha256": "24faba555101f0aacd652e3728c99982f95461cd57de844f9483df6a6923d1fa",
87
+ "hard": 0
88
+ },
89
+ "templates/_agents/scripts/ensure-board.mjs": {
90
+ "sha256": "8d2211ddaa5f29e961d6ad435fa780baca45722dc79cdd9a01931f8688a5359c",
91
+ "hard": 0
92
+ },
93
+ "templates/_agents/scripts/fill-intent.mjs": {
94
+ "sha256": "b5e386e2a088c2cfbb9101379233295ce199d668866ddef596140fc76db6d766",
95
+ "hard": 1
96
+ },
97
+ "templates/_agents/scripts/fill-plan.mjs": {
98
+ "sha256": "ea60a3e478236e4fc3b25c84bb74217f3eb5130968d3165665e17ae7cc2329af",
99
+ "hard": 1
100
+ },
101
+ "templates/_agents/scripts/fill-spec.mjs": {
102
+ "sha256": "27aa4d55a9c17be40b8c3a89191b3336661340ca975cf04397dd62afe4ec2431",
103
+ "hard": 1
104
+ },
105
+ "templates/_agents/scripts/fixture-scripts.mjs": {
106
+ "sha256": "9f27ff097b8a4172de5f96aa23c1c625801bc5625e2434c332c30482b1761380",
107
+ "hard": 0
108
+ },
109
+ "templates/_agents/scripts/gate-checklist.mjs": {
110
+ "sha256": "99ec369fddee6867a2baeced610760e58a3f85506f95f8a4131bcc584a3a3109",
111
+ "hard": 1
112
+ },
113
+ "templates/_agents/scripts/gate-seg.mjs": {
114
+ "sha256": "b579593ff67e7876e4e1051f62c9a7451032fb2255a2efe5e437a6a2e2c1ce9f",
115
+ "hard": 0
116
+ },
117
+ "templates/_agents/scripts/gen-wiki-board.mjs": {
118
+ "sha256": "c0e86110c8b686b591080f836d7cde6dc4a933820541ceb35928ac249b5d0fb6",
119
+ "hard": 6
120
+ },
121
+ "templates/_agents/scripts/gen-workflow-dashboard.mjs": {
122
+ "sha256": "335485bf6979b43f642e613abae951b69ad4d6b6ed0b026dfdde7f14cd2aebdc",
123
+ "hard": 0
124
+ },
125
+ "templates/_agents/scripts/gen-workflow-index.mjs": {
126
+ "sha256": "5e8bcab656c056d2e07b3286b9869705bff3deebbc97a131f731c360236fe9dd",
127
+ "hard": 3
128
+ },
129
+ "templates/_agents/scripts/gen-workflow-metrics.mjs": {
130
+ "sha256": "c91b6ff9fd5e3b391c8c50af1d68f35058286ef432dddb325f284e0d60833d56",
131
+ "hard": 2
132
+ },
133
+ "templates/_agents/scripts/git-merge-jsonl.mjs": {
134
+ "sha256": "e8c037dcce1f9e52dd9d63ef812ce3ace03f1ecf3e55cb363e58bd8b50352655",
135
+ "hard": 2
136
+ },
137
+ "templates/_agents/scripts/kb-cache-evict.mjs": {
138
+ "sha256": "bd74ac72e611142e839df76e80e22d8e9c6b351dc498c7bb07e807d2e32e7fdb",
139
+ "hard": 0
140
+ },
141
+ "templates/_agents/scripts/kb-search.mjs": {
142
+ "sha256": "3439e59cdafc8a52549fc8cee3bab8eaec384e4761d3f87a7f18db0a8e289d0c",
143
+ "hard": 7
144
+ },
145
+ "templates/_agents/scripts/ledger-loader.mjs": {
146
+ "sha256": "855619ec778eae07540f71ebab0c2f30de0e6b97b522ad69e4d1757cc4202713",
147
+ "hard": 0
148
+ },
149
+ "templates/_agents/scripts/ledger-prune.mjs": {
150
+ "sha256": "82ca3086bf76087ece4436bf2c23a2e102c22dffd6c987c08096286c3d16a0b7",
151
+ "hard": 0
152
+ },
153
+ "templates/_agents/scripts/level-criteria.mjs": {
154
+ "sha256": "384fc339ba1d24815a1db226cb8be165b4c042b983bc7af6c6623114ddc35234",
155
+ "hard": 1
156
+ },
157
+ "templates/_agents/scripts/pipeline-run-docs.mjs": {
158
+ "sha256": "d54085b21d857f4db6df7d5fc7b6a65ffc2391c9e0f100754d1e76a844a318c1",
159
+ "hard": 0
160
+ },
161
+ "templates/_agents/scripts/pipeline-run-run.mjs": {
162
+ "sha256": "b5bda64bee55dcd1fc44170a5e3ab5a5c96c404529d19885fd5b2d6b9d5143bf",
163
+ "hard": 0
164
+ },
165
+ "templates/_agents/scripts/pipeline-run.mjs": {
166
+ "sha256": "6cdf2de3bcbf94d59ccf5e6c4015e89b6032c844c2cc540fdc4f9e02244faa9c",
167
+ "hard": 0
168
+ },
169
+ "templates/_agents/scripts/policy.mjs": {
170
+ "sha256": "eab1a54334d83b93f276593be4e10a17af7734a7c44f8c28a6383946f735613e",
171
+ "hard": 0
172
+ },
173
+ "templates/_agents/scripts/solidify-task.mjs": {
174
+ "sha256": "5e5983b9ab6ae4eaaeced150018592b2501c4d6885b4913d03c6f29138630825",
175
+ "hard": 3
176
+ },
177
+ "templates/_agents/scripts/stage-gates.mjs": {
178
+ "sha256": "6c70ff01f785d19dfa7206cc01c1608baa3249ba59f57190b19b64f318e34e72",
179
+ "hard": 0
180
+ },
181
+ "templates/_agents/scripts/trust-mode.mjs": {
182
+ "sha256": "5800b52af787d6b3fd9a8ea314b36466e19a3adc90f70e93c5054cd530c68bff",
183
+ "hard": 1
184
+ },
185
+ "templates/_agents/scripts/verify-wiki-consistency.mjs": {
186
+ "sha256": "1f58ace65b6bab02eba5df1c69f5b55528df5c098e6d06f8197594912d764c32",
187
+ "hard": 4
188
+ },
189
+ "templates/_agents/scripts/verify.mjs": {
190
+ "sha256": "a40a23193dae79e189c9c7b1f8b1c4c6e1865baa94052c85ed59802864aa46b9",
191
+ "hard": 3
192
+ },
193
+ "templates/_agents/scripts/wf-journal.mjs": {
194
+ "sha256": "b14620e5c9f9c930f4a916084543ce190a135216f11bc4150dcb246c8cdb0e83",
195
+ "hard": 1
196
+ },
197
+ "templates/_agents/scripts/wiki-search.mjs": {
198
+ "sha256": "a493c85924644613619b83334b6f8e4db40ebf0d398960738422116d3afd3015",
199
+ "hard": 0
200
+ },
201
+ "templates/_agents/scripts/workflow-board-server.mjs": {
202
+ "sha256": "1ef41d13f192f119cd7307dcf59710be9e185308333a60067d3e1ebfb149e9f4",
203
+ "hard": 1
204
+ },
205
+ "templates/_agents/scripts/workflow-enums.mjs": {
206
+ "sha256": "540ce00ec954f90a67d886dcf10f2ebb0661056187f563ba55ec34bf9c0afecd",
207
+ "hard": 0
208
+ },
209
+ "templates/_agents/scripts/workflows-check.mjs": {
210
+ "sha256": "d29f5df709bb3d95b227202bb44a9e056af33bbe4f3afb87eefb94d96a2205cc",
211
+ "hard": 1
212
+ },
213
+ "templates/_agents/workflow-enums.txt": {
214
+ "sha256": "b28a83418133e24f3e4daee7f454c4f31ac98a943a94aa33008a944ae751d25a",
215
+ "hard": 8
216
+ },
217
+ "templates/_agents/workflow-modules.txt": {
218
+ "sha256": "d03593598f6b0495ebc650019c474da0d6538da06c6f58ccc00bd5a9cdc760f1",
219
+ "hard": 7
220
+ },
221
+ "templates/_githooks/commit-msg": {
222
+ "sha256": "3e946cbf3f59a469ec977a036ff8bfc960be7febe36318a0fd112b7adaadfc75",
223
+ "hard": 1
224
+ },
225
+ "templates/_githooks/post-commit": {
226
+ "sha256": "cb97b622a957027e6cfc04c3b7220da476e64d4c3ec902ea00ee14e570c6f3f1",
227
+ "hard": 0
228
+ },
229
+ "templates/_githooks/pre-commit": {
230
+ "sha256": "d65b6bd9adc59582e5209c1ddbdfe11a231d1312362c8f594e2579e7d3700e86",
231
+ "hard": 4
232
+ },
233
+ "templates/_githooks/pre-merge-commit": {
234
+ "sha256": "ab6d11707e78ac19261bc7d667056f7721466456d443cabf85ad7ba24dc797ac",
235
+ "hard": 1
236
+ },
237
+ "templates/_githooks/pre-push": {
238
+ "sha256": "c28d0c19204f0202dd270bbdb8e9b5d0362e56d67e2fbfbff33267ec7f592c9f",
239
+ "hard": 2
240
+ },
241
+ "templates/_github/workflows/kit-ci.yml": {
242
+ "sha256": "08c6e09992df9c1c3805ded11f01d33cea49ee64c4c5950ba3de15a8227e6464",
243
+ "hard": 3
244
+ }
245
+ }
246
+ }
@@ -3,7 +3,7 @@
3
3
  # # 注释与空行忽略;本文件缺失或清单为空 = 检查跳过(装户无感升级)。
4
4
  # 正则语法错误行 → 门禁 fail-closed 阻断(防静默空洞,修配置后重试)。
5
5
  # 语义:命中任一模式 = 本次改动触及「一处定义、多处消费」的契约 / 规则面(L2 触达面,
6
- # 判据见 .agents/commands/new-task.md §级别判断)。此时须有活跃(draft/approved / open/fixed)
6
+ # 判据单源见 .agents/scripts/level-criteria.mjs 的 L2_SURFACES)。此时须有活跃(draft/approved / open/fixed)
7
7
  # L2/L3 入口罩着;活跃入口全为 L0/L1 会被 pre-commit「触达面判低」拦截(三选修法见门禁消息)。
8
8
  # 无任何活跃入口时仅 advisory——docs / bootstrap 豁免类改动(new-task.md §intent 豁免)不受阻。
9
9
  # 本仓默认面(引擎 / 契约面,行为承载目录——commands/roles 纯提示文本属 docs 级不列入;按项目自行改):
@@ -0,0 +1,30 @@
1
+ # 风险级别路径提示清单(单源消费方:templates/_agents/scripts/level-criteria.mjs)
2
+ #
3
+ # 用途:登记「哪些路径一碰就**至少**是 L2 / L3」。定级是**意图面**的语义判定(「一处定义、多处消费」),
4
+ # 机器判不了语义;但「路径下限」可以登记,避免明显高风险的改动被拍脑袋判成 L1。
5
+ # 与 lane-surfaces.txt 的分工:那是**提交面**的触达判据(改这些面须有活跃 L2/L3 入口),
6
+ # 本文件是**意图面**的档位提示(改这些面就该按更高档走)。两者不同档,各司其职。
7
+ #
8
+ # 格式:每行一条 `<档位> <ERE>`,ERE 为 grep -E 兼容正则,匹配仓库相对路径(/ 分隔)。
9
+ # 档位**只收 L2 / L3**:本清单登记的是「一碰就至少是中/高风险面」的下限。L0/L1 不构成门槛,
10
+ # 登记了只会让提交面判低门(L2 触达面门)对无关改动出手——那正是要避免的噪声。
11
+ # **ERE 与注释必须分两行**:写 `L3 ^a\.sql$ # 迁移 SQL` 会把 `# 迁移 SQL` 编进正则,
12
+ # 若含 $ 锚点该条就永不命中,且不报任何错(路径下限与提交面兜底同时静默失效)。
13
+ # 确需匹配路径里的 # 时写 \#。非法档位 / 行内注释 / 正则语法错 → **fail-loud 抛错**
14
+ # (写错配置比没配置危险:没配置会提示补,写错会误判)。
15
+ # # 注释与空行忽略;本文件缺失或清单为空 = 纯语义定级(判据面全程静默,不阻断)。
16
+ #
17
+ # 默认留空(刻意):本清单内容是**项目私有**的——按你自己的代码布局登记,照抄别人的清单等于没登记。
18
+ # 建议起步:从「改什么几乎必然是 L2/L3」的高频面挑 3~5 条先登记,跑一段时间再补。
19
+ #
20
+ # ---- 示例(取消注释并按项目实际路径改写;本仓为 node 包源,下例仅示意形态)----
21
+ # # 迁移 SQL(注释单独成行,不要接在 ERE 后面)
22
+ # L3 ^src/db/migrations/.*\.sql$
23
+ # # schema 定义
24
+ # L3 ^src/db/schema/
25
+ # # 认证与中间件管线 / DI 链
26
+ # L3 ^(src/(auth|middleware)/|src/.*\.(auth|di)\.(ts|js)$)
27
+ # # 共享契约(DTO / 接口签名)
28
+ # L2 ^src/contracts/
29
+ # # 编码权威(取号 / 命名规则生成器)
30
+ # L2 ^src/coding/
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  /* agg-delegations: 量化证据聚合
3
3
  * 读 workflow/delegations.md 两张结果表(按表头签名识别:委派表含「被委派方」列、自做表=日期+任务一句话;不依赖 ## 节标题)+ 扫 workflow/incidents/ 按月计数,
4
- * 输出各月指标(一次通过率 / 平均返工次数 / 主兜底占比)、并发扩容门判定、可粘贴的月度快照行。
4
+ * 输出各月指标(一次通过率 / 平均返工次数 / 主兜底占比 / **产出接受率**)、并发扩容门判定、可粘贴的月度快照行。
5
5
  * 结果取值:一次通过 | 返工×N | 返工×N(门禁噪声)| 主兜底 | 返工待修(未闭环,不计入率)。
6
6
  * 门禁噪声档(2026-10-08 selfmeasure-and-modularize):剥离「返工由门禁面而非设计面触发」的形态——
7
7
  * 扩容门第 3 项只对设计返工判 =0,门禁噪声返工单列观测。存量行零回填(旧四档解析逐条不变)。
@@ -58,6 +58,25 @@ function parseResult(raw) {
58
58
  return { kind: 'unknown', rework: 0, reworkNoise: 0 };
59
59
  }
60
60
 
61
+ // parseVerdict:合入结论列解析(2026-10-12 merge-accept-rate)
62
+ // 三档:合入 / 返工后合入 / 未合入;空与未知一律 return null(**不计入接受率分母**——
63
+ // 存量行零回填是硬约定,未记录 ≠ 未合入,混进去会凭空造出一个低接受率)。
64
+ // 判据边界:结论由人工/独立复核写入,机器不判真伪(同 --delegated 信任边界);
65
+ // 本项是**观测不是门槛**,不进 gateMonth(理由见 workflow/delegations.md 头部)。
66
+ // 与结果列(过程质量)刻意分开:结果列量「跑了几遍」,本列量「人愿不愿意合」——
67
+ // METR 2026-03 实测两者落差约 24 个百分点,混列即被前者盖过后者。
68
+ function parseVerdict(raw) {
69
+ const v = (raw || '').trim();
70
+ if (/^合入$/.test(v)) return 'accepted';
71
+ if (/^返工后合入$/.test(v)) return 'accepted-after-rework';
72
+ if (/^未合入$/.test(v)) return 'rejected';
73
+ return null; // 留空 / 未登记取值 = 未记录(不进分母)
74
+ }
75
+
76
+ // ACCEPT_MIN_SAMPLE:接受率最小样本护栏(样本 <5 不出率,沿 agg 既有护栏口径——
77
+ // 样本过小的比率是噪声不是信号,且一旦进门禁就会产出不可消退的告警)。
78
+ const ACCEPT_MIN_SAMPLE = 5;
79
+
61
80
  // splitTables:按表头签名识别两张结果表——节标题只服务人类阅读,表头才是数据边界
62
81
  // (2026-09-24 修复:曾按 `## 委派结果` 节标题定位,节结构漂移时已有记录被静默读成「台账为空」)
63
82
  // ⚠️ 互引(2026-10-08 papercuts-cleanup-batch 修 2):check-loop.mjs delegationResultRows 已对齐本签名
@@ -91,18 +110,20 @@ function readLedger(root = ROOT, opts = {}) {
91
110
  date: c[0],
92
111
  actor: c[1],
93
112
  result: c[3] || '',
113
+ verdict: c[5] || '',
94
114
  }));
95
115
  const selfDone = parseTableRows(tables.self.join('\n')).map((c) => ({
96
116
  scope: '自做',
97
117
  date: c[0],
98
118
  actor: '主智能体',
99
119
  result: c[2] || '',
120
+ verdict: c[4] || '',
100
121
  }));
101
122
  const rows = delegated.concat(selfDone);
102
123
  // 零数据行时区分「台账真空」与「结构漂移」:有日期开头的数据行却识别不到表 → fail-loud,不再静默「台账为空」
103
124
  if (!rows.length && /^\s*\|\s*\d{4}-\d{2}-\d{2}\s*\|/m.test(text)) {
104
125
  if (opts.soft) return [];
105
- fail(`台账结构漂移:${ledger} 存在日期开头的数据行但未识别到结果表(委派表表头须含「被委派方」列,自做表表头须为「日期 | 任务一句话 | 结果 | 备注」)`);
126
+ fail(`台账结构漂移:${ledger} 存在日期开头的数据行但未识别到结果表(委派表表头须含「被委派方」列,自做表表头须为「日期 | 任务一句话 | 结果 | 备注」——末列「合入结论」可缺省,存量表不要求补)`);
106
127
  }
107
128
  return rows;
108
129
  }
@@ -142,6 +163,18 @@ function metrics(rows) {
142
163
  if (p.kind === 'rework-noise' || p.kind === 'rework-mixed') reworkNoiseSum += p.reworkNoise;
143
164
  }
144
165
  const delegatedValid = valid.filter((r) => r.scope === '委派');
166
+ // 接受率(2026-10-12 merge-accept-rate):分母 = **已记录合入结论**的行数(parseVerdict 非 null),
167
+ // 分子 = accepted + accepted-after-rework。留空行不计入——存量行零回填,未记录 ≠ 未合入。
168
+ // 分母不足 ACCEPT_MIN_SAMPLE 时 acceptRate = null(输出 '—'),不给小样本比率。
169
+ let verdictRecorded = 0, accepted = 0, rejected = 0;
170
+ for (const r of valid) {
171
+ const v = parseVerdict(r.verdict);
172
+ if (!v) continue;
173
+ verdictRecorded += 1;
174
+ if (v === 'accepted' || v === 'accepted-after-rework') accepted += 1;
175
+ if (v === 'rejected') rejected += 1;
176
+ }
177
+ const acceptRate = verdictRecorded >= ACCEPT_MIN_SAMPLE ? accepted / verdictRecorded : null;
145
178
  return {
146
179
  total: valid.length,
147
180
  pending,
@@ -154,9 +187,20 @@ function metrics(rows) {
154
187
  delegatedValid: delegatedValid.length,
155
188
  fallback,
156
189
  fallbackRate: delegatedValid.length ? fallback / delegatedValid.length : null,
190
+ verdictRecorded,
191
+ accepted,
192
+ rejected,
193
+ acceptRate,
157
194
  };
158
195
  }
159
196
 
197
+ // fmtAccept:接受率展示(分母为 0 或未过护栏 → '—' 并注明原因,不打 0%)
198
+ function fmtAccept(m) {
199
+ if (!m.verdictRecorded) return '—(合入结论零记录)';
200
+ if (m.acceptRate == null) return `—(样本 ${m.verdictRecorded}/${ACCEPT_MIN_SAMPLE})`;
201
+ return `${(m.acceptRate * 100).toFixed(0)}%(${m.accepted}/${m.verdictRecorded})`;
202
+ }
203
+
160
204
  function fmtRate(x, digits = 0) {
161
205
  return x == null ? '—' : `${(x * 100).toFixed(digits)}%`;
162
206
  }
@@ -211,16 +255,17 @@ function main() {
211
255
  const prevYm = (() => { const [y, mo] = ym.split('-').map(Number); const d = new Date(Date.UTC(y, mo - 2, 1)); return `${d.getUTCFullYear()}-${String(d.getUTCMonth() + 1).padStart(2, '0')}`; })();
212
256
  const verdict = expansionVerdict(monthOk, monthResults.get(prevYm), !months.includes(prevYm), items);
213
257
  console.log(`## ${ym}`);
214
- console.log(` 有效任务 ${m.total}(待修 ${m.pending}${m.unknown ? `、未知结果 ${m.unknown}` : ''})|一次通过 ${m.pass}(${fmtRate(m.passRate)})|设计返工 ${m.reworkSum} 次 / 门禁噪声返工 ${m.reworkNoiseSum} 次(合计返工 ${m.reworkSum + m.reworkNoiseSum},平均 ${fmtNum(m.avgRework)})|主兜底 ${m.fallback}/${m.delegatedValid}(${fmtRate(m.fallbackRate)})|incident ${incidents[ym] || 0} 起`);
258
+ console.log(` 有效任务 ${m.total}(待修 ${m.pending}${m.unknown ? `、未知结果 ${m.unknown}` : ''})|一次通过 ${m.pass}(${fmtRate(m.passRate)})|设计返工 ${m.reworkSum} 次 / 门禁噪声返工 ${m.reworkNoiseSum} 次(合计返工 ${m.reworkSum + m.reworkNoiseSum},平均 ${fmtNum(m.avgRework)})|主兜底 ${m.fallback}/${m.delegatedValid}(${fmtRate(m.fallbackRate)})|产出接受率 ${fmtAccept(m)}|incident ${incidents[ym] || 0} 起`);
259
+ console.log(` 接受率说明(观测项,非门槛):已记录合入结论 ${m.verdictRecorded} 行|合入 ${m.accepted}|未合入 ${m.rejected}|留空未记录行不入分母`);
215
260
  for (const i of items) console.log(` 门${i.no}[${i.kind}] ${i.ok === null ? '[人工]' : i.ok ? '✅' : '❌'} ${i.desc}`);
216
261
  console.log(` 扩容门判定:${verdict}\n`);
217
- snapshotRows.push(`| ${ym} | ${m.total} | ${fmtRate(m.passRate)} | ${fmtNum(m.avgRework)} | ${fmtRate(m.fallbackRate)} | ${incidents[ym] || 0} | ${verdict} | 样本含待修${m.pending}${m.unknown ? `、未知${m.unknown}` : ''} |`);
262
+ snapshotRows.push(`| ${ym} | ${m.total} | ${fmtRate(m.passRate)} | ${fmtNum(m.avgRework)} | ${fmtRate(m.fallbackRate)} | ${incidents[ym] || 0} | ${fmtAccept(m)} | ${verdict} | 样本含待修${m.pending}${m.unknown ? `、未知${m.unknown}` : ''} |`);
218
263
  }
219
264
 
220
265
  if (!argMonth && rows.length) {
221
266
  const m = metrics(rows);
222
267
  console.log(`## 全量累计`);
223
- console.log(` 有效任务 ${m.total}(待修 ${m.pending}${m.unknown ? `、未知结果 ${m.unknown}` : ''})|一次通过 ${fmtRate(m.passRate)}|平均返工 ${fmtNum(m.avgRework)}|主兜底 ${fmtRate(m.fallbackRate)}|incident 合计 ${Object.values(incidents).reduce((a, b) => a + b, 0)} 起\n`);
268
+ console.log(` 有效任务 ${m.total}(待修 ${m.pending}${m.unknown ? `、未知结果 ${m.unknown}` : ''})|一次通过 ${fmtRate(m.passRate)}|平均返工 ${fmtNum(m.avgRework)}|主兜底 ${fmtRate(m.fallbackRate)}|产出接受率 ${fmtAccept(m)}|incident 合计 ${Object.values(incidents).reduce((a, b) => a + b, 0)} 起\n`);
224
269
  }
225
270
 
226
271
  console.log(`## 可粘贴快照行(粘到 workflow/delegations.md §月度聚合快照)`);
@@ -235,5 +280,5 @@ function main() {
235
280
  if (require.main === module) {
236
281
  main();
237
282
  } else {
238
- module.exports = { parseResult, metrics, gateMonth, expansionVerdict, GATE, readLedger };
283
+ module.exports = { parseResult, parseVerdict, metrics, gateMonth, expansionVerdict, fmtAccept, GATE, ACCEPT_MIN_SAMPLE, readLedger };
239
284
  }
@@ -8,10 +8,12 @@ import fs from 'node:fs';
8
8
  import os from 'node:os';
9
9
  import path from 'node:path';
10
10
  import { spawnSync } from 'node:child_process';
11
- import { fileURLToPath } from 'node:url';
11
+ import { fileURLToPath, pathToFileURL } from 'node:url';
12
12
 
13
13
  const SCRIPT_DIR = path.dirname(fileURLToPath(import.meta.url));
14
- const SRC = path.join(SCRIPT_DIR, 'agg-delegations.cjs');
14
+ // 夹具闭包(2026-10-12 fixture-closure-rootfix):入口 agg-delegations.cjs 的传递依赖自动带入(当前无,
15
+ // 但日后加 import 不必回来改这里——漏拷 = 假绿)。
16
+ const { copyScriptClosure } = await import(pathToFileURL(path.join(SCRIPT_DIR, 'fixture-scripts.mjs')).href);
15
17
  const USAGE = '用法:node .agents/scripts/agg-delegations.test.mjs';
16
18
 
17
19
  let pass = 0;
@@ -26,7 +28,7 @@ const mkfix = (ledgerText) => {
26
28
  fs.mkdirSync(path.join(root, '.agents', 'scripts'), { recursive: true });
27
29
  fs.mkdirSync(path.join(root, 'workflow', 'incidents'), { recursive: true });
28
30
  fs.writeFileSync(path.join(root, 'workflow', 'delegations.md'), ledgerText, 'utf8');
29
- fs.copyFileSync(SRC, path.join(root, '.agents', 'scripts', 'agg-delegations.cjs'));
31
+ copyScriptClosure(path.join(root, '.agents', 'scripts'), ['agg-delegations.cjs']);
30
32
  return root;
31
33
  };
32
34
  const runAgg = (root) => spawnSync(process.execPath, [path.join(root, '.agents', 'scripts', 'agg-delegations.cjs')], { cwd: root, encoding: 'utf8' });
@@ -91,7 +93,7 @@ const runAgg = (root) => spawnSync(process.execPath, [path.join(root, '.agents',
91
93
  // 纯函数经 module.exports require(isMain 守卫后 import 不执行 main)
92
94
  import { createRequire } from 'node:module';
93
95
  const requireCjs = createRequire(import.meta.url);
94
- const { metrics, gateMonth, expansionVerdict, parseResult } = requireCjs(path.join(SCRIPT_DIR, 'agg-delegations.cjs'));
96
+ const { metrics, gateMonth, expansionVerdict, parseResult, parseVerdict, fmtAccept, ACCEPT_MIN_SAMPLE } = requireCjs(path.join(SCRIPT_DIR, 'agg-delegations.cjs'));
95
97
 
96
98
  // 场景 4:审查反例——30 任务、2 主兜底、平均返工 0.25(旧口径四门全过,声明口径下必须 ❌)
97
99
  {
@@ -194,6 +196,84 @@ const { metrics, gateMonth, expansionVerdict, parseResult } = requireCjs(path.jo
194
196
  withDesign.ok === false, JSON.stringify(withDesign));
195
197
  }
196
198
 
199
+ // 场景 8:产出接受率(2026-10-12 merge-accept-rate)
200
+ // 动机(METR 2026-03):agent 生成的 SWE-bench 通过 PR,维护者合并判定比自动评分低约 24 个百分点、
201
+ // 约一半不会被合入——「自动门全绿」与「人愿意合」是两个维度,混列必被前者盖过后者。
202
+ {
203
+ check('场景 8:parseVerdict 三档 + 留空/乱填落 null(未记录 ≠ 未合入)',
204
+ parseVerdict('合入') === 'accepted' && parseVerdict('返工后合入') === 'accepted-after-rework'
205
+ && parseVerdict('未合入') === 'rejected'
206
+ && parseVerdict('') === null && parseVerdict(undefined) === null && parseVerdict('已上线') === null,
207
+ JSON.stringify([parseVerdict('合入'), parseVerdict('返工后合入'), parseVerdict('未合入'), parseVerdict(''), parseVerdict('已上线')]));
208
+
209
+ // 反例钉子:一次通过率 100% 但接受率低 —— 这正是混列会掩盖的形态
210
+ const rows = [
211
+ ...Array.from({ length: 8 }, () => ({ scope: '自做', result: '一次通过', verdict: '合入' })),
212
+ { scope: '自做', result: '一次通过', verdict: '未合入' },
213
+ { scope: '自做', result: '一次通过', verdict: '返工后合入' },
214
+ { scope: '自做', result: '一次通过' }, // 留空 = 未记录,不入分母
215
+ ];
216
+ const m = metrics(rows);
217
+ check('场景 8:一次通过率 100% 但接受率 90%(8 合入 + 1 返工后合入 / 10 已记录)',
218
+ Math.abs(m.passRate - 1) < 1e-9 && Math.abs(m.acceptRate - 0.9) < 1e-9,
219
+ JSON.stringify({ passRate: m.passRate, acceptRate: m.acceptRate }));
220
+ check('场景 8:留空行不入分母(verdictRecorded=10 而非 11)',
221
+ m.verdictRecorded === 10 && m.accepted === 9 && m.rejected === 1, JSON.stringify(m));
222
+ check('场景 8:接受率不影响任何扩容门项(观测项非门槛项——METR 缺口不靠加门堵)',
223
+ gateMonth(m).items.length === 6, JSON.stringify(gateMonth(m).items.map((i) => i.no)));
224
+
225
+ // 样本护栏:不足 ACCEPT_MIN_SAMPLE 条不出率(给小样本比率 = 给噪声开门)
226
+ check('场景 8:护栏阈值 = 5 且与脚本常量同源(文档写死一处会漂)', ACCEPT_MIN_SAMPLE === 5, String(ACCEPT_MIN_SAMPLE));
227
+ const tiny = metrics([{ scope: '自做', result: '一次通过', verdict: '未合入' }]);
228
+ check('场景 8:样本 <5 → acceptRate=null 且 fmtAccept 注明样本数',
229
+ tiny.acceptRate === null && fmtAccept(tiny).includes(`样本 1/${ACCEPT_MIN_SAMPLE}`), `${String(tiny.acceptRate)} | ${fmtAccept(tiny)}`);
230
+ check('场景 8:零记录 → fmtAccept 显式说明而非打 0%',
231
+ fmtAccept(metrics([{ scope: '自做', result: '一次通过' }])).includes('零记录'), fmtAccept(metrics([{ scope: '自做', result: '一次通过' }])));
232
+
233
+ // 存量兼容:无 verdict 字段的行(旧行对象)零影响
234
+ const legacy = metrics([{ scope: '自做', result: '一次通过' }, { scope: '委派', result: '返工×1' }]);
235
+ check('场景 8:存量行(无 verdict 键)零影响——verdictRecorded=0 / 一次通过率与旧口径一致',
236
+ legacy.verdictRecorded === 0 && legacy.total === 2 && Math.abs(legacy.passRate - 0.5) < 1e-9,
237
+ JSON.stringify(legacy));
238
+ }
239
+
240
+ // 场景 9:表结构兼容 —— 末列缺省不误判(存量表不要求补列)
241
+ {
242
+ const root = mkfix([
243
+ '# 量化证据台账(fixture)',
244
+ '',
245
+ '## 委派结果',
246
+ '',
247
+ '| 日期 | 被委派方(模型) | 任务一句话 | 结果 | 备注 |',
248
+ '|------|----------------|------------|------|------|',
249
+ '| 2026-09-23 | executor(子代理) | 旧表结构行(无合入结论列) | 一次通过 | fixture |',
250
+ '',
251
+ ].join('\n'));
252
+ const r = runAgg(root);
253
+ check('场景 9:存量五列表 → exit 0 且正常入账', r.status === 0 && /有效任务 1(/.test(r.stdout), `exit=${r.status}\n${r.stdout}${r.stderr}`);
254
+ check('场景 9:合入结论零记录 → 接受率显示「零记录」', r.stdout.includes('零记录'), r.stdout);
255
+ fs.rmSync(root, { recursive: true, force: true });
256
+
257
+ const root2 = mkfix([
258
+ '# 量化证据台账(fixture)',
259
+ '',
260
+ '## 委派结果',
261
+ '',
262
+ '| 日期 | 被委派方(模型) | 任务一句话 | 结果 | 备注 | 合入结论 |',
263
+ '|------|----------------|------------|------|------|----------|',
264
+ ...Array.from({ length: 8 }, (_, i) => `| 2026-10-0${i + 1} | executor(子代理) | 新表结构行 | 一次通过 | fixture | 合入 |`),
265
+ '| 2026-10-09 | executor(子代理) | 新表结构行 | 一次通过 | fixture | 未合入 |',
266
+ '| 2026-10-10 | executor(子代理) | 新表结构行 | 一次通过 | fixture | 返工后合入 |',
267
+ '',
268
+ ].join('\n'));
269
+ const r2 = runAgg(root2);
270
+ check('场景 9:六列表 → 末列正确解析(已记录 10 / 合入 9 / 未合入 1)',
271
+ r2.status === 0 && /已记录合入结论 10 行|合入 9|未合入 1/.test(r2.stdout), `exit=${r2.status}\n${r2.stdout}${r2.stderr}`);
272
+ check('场景 9:快照行含接受率列(90%(9/10)——样本过护栏才出率)',
273
+ /\|\s*90%(9\/10)\s*\|/.test(r2.stdout), r2.stdout);
274
+ fs.rmSync(root2, { recursive: true, force: true });
275
+ }
276
+
197
277
  console.log(`\n合计: PASS ${pass} / FAIL ${fail}`);
198
278
  if (fail) {
199
279
  console.log(`\n${USAGE}`);