agentic-flow-kit 1.7.15 → 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.
- package/README.md +41 -3
- package/modules/hosts/claude/commands/wf-design.md +5 -4
- package/modules/hosts/claude/commands/wf-new-task.md +42 -21
- package/modules/hosts/claude/commands/wf-review.md +1 -1
- package/modules/hosts/claude/commands/wf-sync-hosts.md +7 -13
- package/modules/hosts/claude/commands/wf-test.md +1 -1
- package/modules/hosts/codex/commands/wf-design.md +5 -4
- package/modules/hosts/codex/commands/wf-new-task.md +42 -21
- package/modules/hosts/codex/commands/wf-review.md +1 -1
- package/modules/hosts/codex/commands/wf-sync-hosts.md +7 -13
- package/modules/hosts/codex/commands/wf-test.md +1 -1
- package/modules/hosts/cursor/commands/wf-design.md +5 -4
- package/modules/hosts/cursor/commands/wf-new-task.md +42 -21
- package/modules/hosts/cursor/commands/wf-review.md +1 -1
- package/modules/hosts/cursor/commands/wf-sync-hosts.md +7 -13
- package/modules/hosts/cursor/commands/wf-test.md +1 -1
- package/modules/hosts/opencode/commands/wf-design.md +5 -4
- package/modules/hosts/opencode/commands/wf-new-task.md +42 -21
- package/modules/hosts/opencode/commands/wf-review.md +1 -1
- package/modules/hosts/opencode/commands/wf-sync-hosts.md +7 -13
- package/modules/hosts/opencode/commands/wf-test.md +1 -1
- package/modules/hosts/trae/commands/wf-design.md +5 -4
- package/modules/hosts/trae/commands/wf-new-task.md +42 -21
- package/modules/hosts/trae/commands/wf-review.md +1 -1
- package/modules/hosts/trae/commands/wf-sync-hosts.md +7 -13
- package/modules/hosts/trae/commands/wf-test.md +1 -1
- package/package.json +1 -1
- package/src/cli.mjs +43 -4
- package/src/doctor.mjs +37 -1
- package/src/executor.mjs +245 -0
- package/src/executor.test.mjs +292 -0
- package/src/init.mjs +7 -0
- package/src/profiles.mjs +3 -0
- package/src/render.mjs +3 -3
- package/src/sync-hosts.mjs +37 -43
- package/src/sync-hosts.test.mjs +67 -56
- package/templates/.gitattributes +8 -0
- package/templates/AGENTS.md +1 -1
- package/templates/_agents/commands/design.md +5 -4
- package/templates/_agents/commands/new-task.md +42 -21
- package/templates/_agents/commands/review.md +1 -1
- package/templates/_agents/commands/sync-hosts.md +7 -13
- package/templates/_agents/commands/test.md +1 -1
- package/templates/_agents/control-surfaces.txt +1 -1
- package/templates/_agents/engine-lock.json +246 -0
- package/templates/_agents/lane-surfaces.txt +1 -1
- package/templates/_agents/level-hints.txt +30 -0
- package/templates/_agents/scripts/agg-delegations.test.mjs +5 -3
- package/templates/_agents/scripts/check-engine-integrity.mjs +55 -126
- package/templates/_agents/scripts/check-engine-integrity.test.mjs +33 -45
- package/templates/_agents/scripts/check-lane-surface.mjs +72 -23
- package/templates/_agents/scripts/check-lane-surface.test.mjs +66 -0
- package/templates/_agents/scripts/check-ledger-invariant.mjs +112 -14
- package/templates/_agents/scripts/check-ledger-invariant.test.mjs +5 -1
- package/templates/_agents/scripts/check-loop-rev.test.mjs +6 -4
- package/templates/_agents/scripts/check-loop.mjs +49 -41
- package/templates/_agents/scripts/check-loop.test.mjs +18 -13
- package/templates/_agents/scripts/check-metric-claims.mjs +4 -2
- package/templates/_agents/scripts/compact-ledgers.mjs +97 -0
- package/templates/_agents/scripts/compact-ledgers.test.mjs +162 -0
- package/templates/_agents/scripts/confirm-doc.mjs +40 -11
- package/templates/_agents/scripts/doctor.test.mjs +44 -1
- package/templates/_agents/scripts/edit-face-check.test.mjs +5 -4
- package/templates/_agents/scripts/fill-intent.mjs +2 -2
- package/templates/_agents/scripts/fixture-scripts.mjs +153 -0
- package/templates/_agents/scripts/fixture-scripts.test.mjs +107 -0
- package/templates/_agents/scripts/gate-checklist.mjs +4 -9
- package/templates/_agents/scripts/gate-checklist.test.mjs +2 -11
- package/templates/_agents/scripts/gen-workflow-dashboard.mjs +8 -11
- package/templates/_agents/scripts/gen-workflow-metrics.mjs +9 -33
- package/templates/_agents/scripts/git-merge-jsonl.mjs +63 -0
- package/templates/_agents/scripts/git-merge-jsonl.test.mjs +125 -0
- package/templates/_agents/scripts/ledger-doc-chain.test.mjs +166 -0
- package/templates/_agents/scripts/ledger-loader.mjs +108 -0
- package/templates/_agents/scripts/ledger-loader.test.mjs +131 -0
- package/templates/_agents/scripts/ledger-prune.mjs +96 -0
- package/templates/_agents/scripts/ledger-prune.test.mjs +120 -0
- package/templates/_agents/scripts/ledger-ts-monotonic.test.mjs +135 -0
- package/templates/_agents/scripts/level-criteria.mjs +232 -0
- package/templates/_agents/scripts/level-criteria.test.mjs +279 -0
- package/templates/_agents/scripts/pipeline-run.mjs +4 -2
- package/templates/_agents/scripts/policy.mjs +47 -0
- package/templates/_agents/scripts/stage-gates.mjs +4 -9
- package/templates/_agents/scripts/wf-journal.test.mjs +1 -1
- package/templates/_agents/scripts/wiki-search.test.mjs +5 -6
- package/templates/_agents/scripts/workflows-check.mjs +1 -1
- package/templates/_agents/workflows/pipeline-closing.md +4 -5
- package/templates/_githooks/pre-commit +3 -34
- package/templates/_githooks/pre-push +3 -3
- package/templates/workflow/README.md +11 -0
- package/modules/hosts/claude/commands/wf-source-sync-check.md +0 -89
- package/modules/hosts/codex/commands/wf-source-sync-check.md +0 -89
- package/modules/hosts/cursor/commands/wf-source-sync-check.md +0 -89
- package/modules/hosts/opencode/commands/wf-source-sync-check.md +0 -89
- package/modules/hosts/trae/commands/wf-source-sync-check.md +0 -90
- package/templates/_agents/commands/source-sync-check.md +0 -103
- package/templates/_agents/scripts/check-ledger.mjs +0 -109
- package/templates/_agents/scripts/check-ledger.test.mjs +0 -199
- package/templates/_agents/scripts/source-sync-check.mjs +0 -156
- package/templates/_agents/scripts/source-sync-check.test.mjs +0 -286
- 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
|
-
#
|
|
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/
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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' });
|
|
@@ -7,39 +7,44 @@
|
|
|
7
7
|
// ② CI 的机器门跑的是**被测分支自己的** `.agents/scripts/check-loop.mjs`(ci.yml:42)——被改坏的
|
|
8
8
|
// 裁判验证自己的篡改,无外部参照,CI 全绿。
|
|
9
9
|
//
|
|
10
|
-
// 本门的做法:把「门禁本体当前的硬拦面」**冻结进一个入库基线**
|
|
11
|
-
// 判定 =
|
|
12
|
-
//
|
|
10
|
+
// 本门的做法:把「门禁本体当前的硬拦面」**冻结进一个入库基线** `templates/_agents/engine-lock.json`,
|
|
11
|
+
// 判定 = 包源盘面向量 ↔ 基线逐项比对(哈希 + 硬拦单位数)。它不是签名、也不宣称不可伪造——
|
|
12
|
+
// 它把「静默改弱」变成「必须显式 --update 的改弱」:
|
|
13
13
|
// · 硬拦单位数**下降**(删 blocker / 删 exit 1 / 从面清单删行 / 从 CI 删一次门调用)→ 无条件 BLOCK;
|
|
14
|
-
// · 内容变了但硬拦面没缩 →
|
|
15
|
-
// · 基线本身在受检面内(engine-lock.json
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
// 删掉本脚本仍可绕过本地门,兜底 = CI 复跑(本脚本被 ci.yml 调用)+ 分支保护;本地信任边界内
|
|
14
|
+
// · 内容变了但硬拦面没缩 → 同样 BLOCK,直到跑 --update 把新盘面显式入账;
|
|
15
|
+
// · 基线本身在受检面内(control-surfaces 列了 templates/_agents/engine-lock.json),
|
|
16
|
+
// 改基线同样要过本门(对基线的改动 = 受检面内容变更 → 未入新基线即拦)。
|
|
17
|
+
// 诚实边界:`--no-verify` / 不挂 hooksPath / 删掉本脚本仍可绕过本地门,兜底 = CI 复跑
|
|
18
|
+
// (本脚本被 .github/workflows 的 engine-integrity job 调用)+ 分支保护;本地信任边界内
|
|
20
19
|
// 不可机器防这一点不掩盖(沿 policy.mjs#ledgerChainHash 与 README 确认门口径)。
|
|
21
20
|
//
|
|
21
|
+
// **无声明式豁免(2026-10-13 移除入口退路)**:此前本门有两档豁免——本地层「正文提及即认」、
|
|
22
|
+
// 锚层「活跃 L2/L3 入口在 §改动面 点名」,参照物是 `<root>/workflow/{intents,incidents}`。
|
|
23
|
+
// 但 1.7.15「卸掉同仓双身份」后**包源仓已无该目录**(装户端内容清理),退路在本仓结构性不可达:
|
|
24
|
+
// 门消息让包源维护者去「立 L2 入口」,而立不了——不可达的能力等于误导。故整体移除(连带
|
|
25
|
+
// T4b/T4c/T4d 与锚层严格档测试):本仓只认 --update 这一条显式演进路径,语义更少、更可核对。
|
|
26
|
+
// **代价(诚实记录)**:跨提交锚只比对**硬拦单位数**、不比 sha,故「改写某检查的语义但保住
|
|
27
|
+
// exit 1 计数 + --update」这一形态两层都绿。补法是让锚层也比对 sha,代价是每次合法演进都需一份
|
|
28
|
+
// 显式凭据(改判据面,未决)。
|
|
29
|
+
//
|
|
22
30
|
// 可选外部锚两条(都是「不受被测对象控制的参照物」,缺省不启用=无外部副本/无历史时不误报):
|
|
23
31
|
// --against <目录> 逐字比对包源件与外部副本(装户/发布仓:node_modules/agentic-flow-kit)
|
|
24
32
|
// --against-ref <ref> 跨提交锚(破 CI 自指的关键一环):从**历史 ref** 读基线(git show <ref>:<lock>),
|
|
25
33
|
// 与盘面硬拦单位数做单调比较。本地门只比「盘面 ↔ 同分支基线」——恶意分支可同时改弱门禁并 --update
|
|
26
34
|
// 重写基线,两者自洽、CI 全绿(「裁判给自己判无罪」的第二形态)。跨提交锚的参照物在**祖先提交**里,
|
|
27
35
|
// 改它要 rewrite history + 强推(分支保护拦住),CI 由此获得一个不受被测分支控制的参照。
|
|
28
|
-
//
|
|
29
|
-
// L2/L3 入口在 §改动面 段落点名该文件(正文顺手提及不豁免;否则存量无关 L2 文档可替任意改弱背书)。
|
|
36
|
+
// 硬拦面收缩在本层**无豁免出口**:锚的参照物分支改不动,只能改判据基线并走评审。
|
|
30
37
|
// ref 不可解析 / 该 ref 无基线(首个入账提交)→ 跳过并报 ℹ️(锚缺失不误报)。
|
|
31
38
|
//
|
|
32
|
-
// 判据原则(沿 check-lane-surface
|
|
33
|
-
//
|
|
39
|
+
// 判据原则(沿 check-lane-surface):只用一手事实——盘面字节哈希与可数单位;
|
|
40
|
+
// 不从时间戳反推过程、不靠文档正文为改动背书。
|
|
34
41
|
// 用法:node check-engine-integrity.mjs [--root <dir>] [--update] [--against <dir>] [--against-ref <ref>] [--quiet]
|
|
35
|
-
// --update
|
|
36
|
-
// 退出码:0 通过(含基线缺失=未启用);1 阻断(stderr 出 [标签]
|
|
42
|
+
// --update 按当前盘面重生成基线(合法演进的唯一路径:演进=显式改基线,不存在自动放行)
|
|
43
|
+
// 退出码:0 通过(含基线缺失=未启用);1 阻断(stderr 出 [标签] 与修法,或目标根不是包源仓);2 用法错误(如 --against 目录不存在)
|
|
37
44
|
import fs from 'node:fs';
|
|
38
45
|
import path from 'node:path';
|
|
39
46
|
import { createHash } from 'node:crypto';
|
|
40
47
|
import { spawnSync } from 'node:child_process';
|
|
41
|
-
import { laneOfEntry, laneOfDoc } from './stage-gates.mjs';
|
|
42
|
-
import { loadKitPolicy } from './policy.mjs';
|
|
43
48
|
|
|
44
49
|
const argv = process.argv.slice(2);
|
|
45
50
|
const argOf = (k) => {
|
|
@@ -53,24 +58,19 @@ const ROOT = argOf('--root') || (() => {
|
|
|
53
58
|
const r = spawnSync('git', ['-C', process.cwd(), 'rev-parse', '--show-toplevel'], { encoding: 'utf8' });
|
|
54
59
|
return r.status === 0 ? String(r.stdout || '').trim() : process.cwd();
|
|
55
60
|
})();
|
|
56
|
-
//
|
|
57
|
-
//
|
|
58
|
-
//
|
|
59
|
-
//
|
|
60
|
-
//
|
|
61
|
-
//
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
? LOCK_CANDIDATES[0]
|
|
70
|
-
: LOCK_CANDIDATES[1];
|
|
71
|
-
return { rel: fallback, abs: path.join(ROOT, fallback) };
|
|
72
|
-
};
|
|
73
|
-
const { rel: LOCK_REL, abs: LOCK_ABS } = resolveLock();
|
|
61
|
+
// 只认包源。基线固定 templates/_agents/engine-lock.json。受检面只扫包源模板
|
|
62
|
+
// (scripts / _githooks / templates/_github / .github/workflows / templates/AGENTS.md / templates/_agents/*.txt)。
|
|
63
|
+
// `.github/workflows/*.yml` 是包源自身的 CI 编排——本门的调用点在那儿,不纳入就等于门可被无声关闭。
|
|
64
|
+
// 不扫 .agents、不扫项目根 .githooks、不按「有没有 .agents」猜布局。
|
|
65
|
+
// 无 templates/_agents 时所有模式都拒绝:静默扫到 0 个文件会看起来像通过。
|
|
66
|
+
// render.mjs 排除 .agents/engine-lock.json,避免把包源基线下发进装户。
|
|
67
|
+
const pkgAgents = path.join(ROOT, 'templates', '_agents');
|
|
68
|
+
if (!fs.existsSync(pkgAgents)) {
|
|
69
|
+
console.error(`check-engine-integrity 只在包源仓运行(需要 templates/_agents)。目标根 ${ROOT} 不是包源仓。`);
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
const LOCK_REL = 'templates/_agents/engine-lock.json';
|
|
73
|
+
const LOCK_ABS = path.join(ROOT, LOCK_REL);
|
|
74
74
|
|
|
75
75
|
// ---- 受检面(单源:本函数;基线与比对同一份清单,防「基线少记一项」的静默空洞)----
|
|
76
76
|
const gateFiles = () => {
|
|
@@ -86,18 +86,20 @@ const gateFiles = () => {
|
|
|
86
86
|
}
|
|
87
87
|
};
|
|
88
88
|
addDir('templates/_agents/scripts', (r) => /\.mjs$/.test(r) && !r.endsWith('.test.mjs'));
|
|
89
|
-
addDir('.agents/scripts', (r) => /\.mjs$/.test(r) && !r.endsWith('.test.mjs'));
|
|
90
89
|
addDir('templates/_githooks');
|
|
91
|
-
addDir('.githooks');
|
|
92
|
-
addDir('.agents/hooks');
|
|
93
|
-
addDir('.github/workflows', (r) => r.endsWith('.yml'));
|
|
94
90
|
addDir('templates/_github/workflows', (r) => r.endsWith('.yml'));
|
|
91
|
+
// 包源自身的机器门编排(.github/workflows/*.yml)。**刻意纳入**:本门是「唯一能防改弱门禁本体」的检查,
|
|
92
|
+
// 而门要成为门就得有人调用它——调用点只存在于 CI 编排里。不纳入的话,删掉编排里的本门调用
|
|
93
|
+
// (或整个 job)没有任何检查会发现:被保护面之外的空白,正是它自身失效的那条路径。
|
|
94
|
+
addDir('.github/workflows', (r) => r.endsWith('.yml'));
|
|
95
95
|
for (const f of ['lane-surfaces.txt', 'control-surfaces.txt', 'workflow-enums.txt', 'workflow-modules.txt',
|
|
96
|
-
'scripts-test-exempt.txt', 'rule-budgets.txt', 'metric-claims.txt'
|
|
97
|
-
|
|
96
|
+
'scripts-test-exempt.txt', 'rule-budgets.txt', 'metric-claims.txt',
|
|
97
|
+
// level-hints.txt(2026-10-13 flow-kit-route 补录):风险级别的**路径下限**清单,直接驱动
|
|
98
|
+
// flow-kit route 定级结果,且语法错会 fail-loud 抛 LEVEL_HINTS_INVALID 改判级结论。
|
|
99
|
+
// 与 lane-surfaces.txt / workflow-modules.txt 同属「喂判据的输入面」,此前漏在受检面外。
|
|
100
|
+
'level-hints.txt']) {
|
|
98
101
|
add(`templates/_agents/${f}`);
|
|
99
102
|
}
|
|
100
|
-
add('AGENTS.md');
|
|
101
103
|
add('templates/AGENTS.md');
|
|
102
104
|
return [...out].sort();
|
|
103
105
|
};
|
|
@@ -135,71 +137,6 @@ const readJson = (p) => {
|
|
|
135
137
|
try { return JSON.parse(fs.readFileSync(p, 'utf8')); } catch { return null; }
|
|
136
138
|
};
|
|
137
139
|
|
|
138
|
-
// 活跃 L2/L3(泳道 high)入口集合:一次扫描,宽松/严格两档判据共用同一份盘面事实
|
|
139
|
-
const HIGH_ENTRIES = (() => {
|
|
140
|
-
const ACTIVE = { intent: new Set(['draft', 'approved']), incident: new Set(['open', 'fixed']) };
|
|
141
|
-
const fmGet = (lines, key) => {
|
|
142
|
-
for (let i = 1; i < lines.length; i++) {
|
|
143
|
-
if (/^---\s*$/.test(lines[i])) break;
|
|
144
|
-
const m = lines[i].match(new RegExp(`^${key}:\\s*(.*)$`));
|
|
145
|
-
if (m) return m[1].trim();
|
|
146
|
-
}
|
|
147
|
-
return '';
|
|
148
|
-
};
|
|
149
|
-
const pol = loadKitPolicy(ROOT);
|
|
150
|
-
const cache = [];
|
|
151
|
-
for (const [dir, kind] of [['intents', 'intent'], ['incidents', 'incident']]) {
|
|
152
|
-
const dp = path.join(ROOT, 'workflow', dir);
|
|
153
|
-
if (!fs.existsSync(dp)) continue;
|
|
154
|
-
for (const f of fs.readdirSync(dp)) {
|
|
155
|
-
if (!f.endsWith('.md') || f === '_TEMPLATE.md') continue;
|
|
156
|
-
const abs = path.join(dp, f);
|
|
157
|
-
let lines;
|
|
158
|
-
try { lines = fs.readFileSync(abs, 'utf8').replace(/\r\n/g, '\n').split('\n'); } catch { continue; }
|
|
159
|
-
if (!/^---\s*$/.test(lines[0] || '')) continue;
|
|
160
|
-
const st = fmGet(lines, '状态');
|
|
161
|
-
if (!ACTIVE[kind].has(st)) continue;
|
|
162
|
-
const level = fmGet(lines, '级别');
|
|
163
|
-
const lane = kind === 'intent'
|
|
164
|
-
? laneOfEntry(level, fmGet(lines, 'risk_level'), pol.riskLevelSince, fmGet(lines, '日期'))
|
|
165
|
-
: laneOfDoc(level);
|
|
166
|
-
if (lane !== 'high') continue;
|
|
167
|
-
cache.push({ rel: `workflow/${dir}/${f}`, text: lines.join('\n') });
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
return cache;
|
|
171
|
-
})();
|
|
172
|
-
|
|
173
|
-
// 宽松档(本地层):整条 rel 或 basename 出现在正文即认——口径同检查 8 的「声明改动面 ↔ 提交文件」
|
|
174
|
-
// 模糊匹配,宁松不假阳性;精确性由 confirm-doc 指纹与台账承担。
|
|
175
|
-
const entryNamesFile = (fileRel) => {
|
|
176
|
-
const base = path.basename(fileRel);
|
|
177
|
-
return HIGH_ENTRIES.find((e) => e.text.includes(fileRel) || e.text.includes(base)) || null;
|
|
178
|
-
};
|
|
179
|
-
|
|
180
|
-
// 严格档(仅跨提交锚用):入口须在**声明改动面**段落点名该文件,而非正文任意一处提及。
|
|
181
|
-
// 为什么分层:本地层的模糊放行代价低(内容漂移本就允许「声明过的演进」);锚层拦的是
|
|
182
|
-
// 「硬拦单位数下降」——若一句顺手提及就能豁免,本仓实测三份**与本批无关的存量 L2 incident**
|
|
183
|
-
// (2026-09-28-metric-claim-gate / 2026-10-03-plan-confirm-boiler 正文含 check-loop.mjs,
|
|
184
|
-
// 2026-09-26-managed-ledger-adopt 含 pre-commit)即可替任意改弱行为背书,锚等于没有。
|
|
185
|
-
// 严格档的误拦修法就是协议本意:把该文件写进入口的 §改动面。
|
|
186
|
-
const entryDeclaresFile = (() => {
|
|
187
|
-
const SECTION = /^[^\n]{0,40}改动面/;
|
|
188
|
-
const declared = (text) => {
|
|
189
|
-
const lines = text.split('\n');
|
|
190
|
-
const out = [];
|
|
191
|
-
for (let i = 0; i < lines.length; i++) {
|
|
192
|
-
if (/^---\s*$/.test(lines[i]) || !SECTION.test(lines[i])) continue;
|
|
193
|
-
// 含标题行本身(「§改动面 点名 x.mjs」是常见的一行式声明)与标题后到下一个 heading 前的全部正文
|
|
194
|
-
for (let j = i; j < lines.length && (j === i || !/^\s*#{1,6}\s/.test(lines[j])); j++) out.push(lines[j]);
|
|
195
|
-
}
|
|
196
|
-
return out.join('\n');
|
|
197
|
-
};
|
|
198
|
-
return (fileRel) => {
|
|
199
|
-
const base = path.basename(fileRel);
|
|
200
|
-
return HIGH_ENTRIES.find((e) => { const s = declared(e.text); return s.includes(fileRel) || s.includes(base); }) || null;
|
|
201
|
-
};
|
|
202
|
-
})();
|
|
203
140
|
|
|
204
141
|
if (UPDATE) {
|
|
205
142
|
fs.mkdirSync(path.dirname(LOCK_ABS), { recursive: true });
|
|
@@ -211,7 +148,7 @@ if (UPDATE) {
|
|
|
211
148
|
console.log(`引擎基线已更新:${LOCK_REL}(受检面 ${Object.keys(lock.files).length} 个文件)`);
|
|
212
149
|
if (changed.length) console.log(` 本次入账为改动件:${changed.length} 个`);
|
|
213
150
|
if (removed.length) console.log(` 本次移除(文件已不在盘):${removed.join(' ')}`);
|
|
214
|
-
console.log(' ⚠️
|
|
151
|
+
console.log(' ⚠️ 基线更新本身是控制面改动:须与该次演进的 CHANGELOG 记录同批提交(改基线 = 受检面内容变更,不入新基线即被本门拦)');
|
|
215
152
|
process.exit(0);
|
|
216
153
|
}
|
|
217
154
|
|
|
@@ -223,14 +160,10 @@ for (const rel of gateFiles()) current[rel] = { sha256: shaOf(path.join(ROOT, re
|
|
|
223
160
|
// ---- 跨提交锚(先于本地基线判定:恶意分支把盘面 engine-lock.json 删掉也逃不掉这一层——参照物读自 git 对象库)----
|
|
224
161
|
if (argOf('--against-ref')) {
|
|
225
162
|
const ref = argOf('--against-ref');
|
|
226
|
-
// 两候选径都试(装户径 / 包源径)——纯包源仓的基线在 templates/_agents/ 下,锚须读得到
|
|
227
163
|
let anchor = null;
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
if (anchor && anchor.files) break;
|
|
232
|
-
anchor = null;
|
|
233
|
-
}
|
|
164
|
+
const r = spawnSync('git', ['-C', ROOT, 'show', `${ref}:${LOCK_REL}`], { encoding: 'utf8', maxBuffer: 64 * 1024 * 1024 });
|
|
165
|
+
try { anchor = JSON.parse(String(r.stdout || '')); } catch { /* 该 ref 无基线 */ }
|
|
166
|
+
if (!anchor || !anchor.files) anchor = null;
|
|
234
167
|
if (!anchor) {
|
|
235
168
|
if (!QUIET) console.log(`ℹ️ 跨提交锚缺失(${ref} 无 ${LOCK_REL})——该层跳过(首个入账提交/浅克隆)`);
|
|
236
169
|
} else {
|
|
@@ -238,16 +171,13 @@ if (argOf('--against-ref')) {
|
|
|
238
171
|
const got = current[rel];
|
|
239
172
|
if (!got) { problems.push(`[门禁件消失(跨提交锚)] ${rel} 在 ${ref} 的基线内但盘面不存在——删除一道门等于禁用该检查`); continue; }
|
|
240
173
|
if (typeof was.hard !== 'number' || got.hard >= was.hard) continue;
|
|
241
|
-
|
|
242
|
-
if (!e) {
|
|
243
|
-
problems.push(`[硬拦面收缩(跨提交锚)] ${rel} 硬拦单位数 ${was.hard}(见 ${ref})→ 盘面 ${got.hard},减少 ${was.hard - got.hard}——祖先提交是参照物,本分支改不动它;确需退役该判据须有活跃 L2/L3 入口在**声明改动面**段落点名该文件(正文顺手提及不算——存量无关文档会替任意改弱行为背书)`);
|
|
244
|
-
}
|
|
174
|
+
problems.push(`[硬拦面收缩(跨提交锚)] ${rel} 硬拦单位数 ${was.hard}(见 ${ref})→ 盘面 ${got.hard},减少 ${was.hard - got.hard}——祖先提交是参照物,本分支改不动它。本门无声明式豁免出口(2026-10-13 移除:入口退路在本仓结构性不可达,详见文件头),收缩一律拦`);
|
|
245
175
|
}
|
|
246
176
|
}
|
|
247
177
|
}
|
|
248
178
|
|
|
249
179
|
if (!lock || !lock.files) {
|
|
250
|
-
if (!QUIET) console.log(`ℹ️ 引擎基线未启用(无 ${LOCK_REL})——跑 node
|
|
180
|
+
if (!QUIET) console.log(`ℹ️ 引擎基线未启用(无 ${LOCK_REL})——跑 node templates/_agents/scripts/check-engine-integrity.mjs --update 生成(跨提交锚与外部副本锚照常执行)`);
|
|
251
181
|
} else {
|
|
252
182
|
for (const [rel, want] of Object.entries(lock.files)) {
|
|
253
183
|
const got = current[rel];
|
|
@@ -255,14 +185,13 @@ if (!lock || !lock.files) {
|
|
|
255
185
|
if (!got) { problems.push(`[门禁件消失] ${rel} 在基线内但盘面不存在——删除一道门等于禁用该检查`); continue; }
|
|
256
186
|
if (got.sha256 === want.sha256) continue;
|
|
257
187
|
if (typeof want.hard === 'number' && got.hard < want.hard) {
|
|
258
|
-
problems.push(`[硬拦面收缩] ${rel} 硬拦单位数 ${want.hard} → ${got.hard}(减少 ${want.hard - got.hard})——删 blocker/exit
|
|
188
|
+
problems.push(`[硬拦面收缩] ${rel} 硬拦单位数 ${want.hard} → ${got.hard}(减少 ${want.hard - got.hard})——删 blocker/exit/判据行的结构性形态,一律拦`);
|
|
259
189
|
} else {
|
|
260
|
-
|
|
261
|
-
if (!e) problems.push(`[控制面改动无入口] ${rel} 内容与基线不符(${name} 硬拦单位数 ${want.hard} → ${got.hard})——无活跃 L2/L3 入口正文点名该文件`);
|
|
190
|
+
problems.push(`[控制面改动未入基线] ${rel} 内容与基线不符(${name} 硬拦单位数 ${want.hard} → ${got.hard})——门禁本体的每次演进都要显式更新基线,不存在「声明过的改动」自动放行`);
|
|
262
191
|
}
|
|
263
192
|
}
|
|
264
193
|
for (const rel of Object.keys(current)) {
|
|
265
|
-
if (!lock.files[rel]) problems.push(`[门禁件未入基线] ${rel} 是新出现的受检文件——合法新增判据须跑 --update
|
|
194
|
+
if (!lock.files[rel]) problems.push(`[门禁件未入基线] ${rel} 是新出现的受检文件——合法新增判据须跑 --update 入账`);
|
|
266
195
|
}
|
|
267
196
|
}
|
|
268
197
|
|
|
@@ -280,8 +209,8 @@ if (argOf('--against')) {
|
|
|
280
209
|
|
|
281
210
|
if (problems.length) {
|
|
282
211
|
console.error(`引擎完整性 — HARD-BLOCK:\n\n${problems.map((p) => `- ${p}`).join('\n')}\n`);
|
|
283
|
-
console.error(` 修法:确属门禁演进 →
|
|
284
|
-
console.error(' 修法:非演进(误改/被他人改动)→ git diff
|
|
212
|
+
console.error(` 修法:确属门禁演进 → 跑 node templates/_agents/scripts/check-engine-integrity.mjs --update 入账,并与 CHANGELOG 记录同批提交(提交评审即对质场;本门无声明式豁免出口,见文件头)`);
|
|
213
|
+
console.error(' 修法:非演进(误改/被他人改动)→ git diff 核对并回退,勿改基线绕过(基线本身在控制面清单内,改它同样是受检面变更)');
|
|
285
214
|
process.exit(1);
|
|
286
215
|
}
|
|
287
216
|
if (!QUIET) console.log(`✅ 引擎完整性:受检面 ${Object.keys(current).length} 个文件(硬拦面无收缩${lock && lock.files ? '、盘面与基线一致' : '、本地基线未启用'})`);
|