@azure-id/orc 1.7.1 → 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 (58) hide show
  1. package/CHANGELOG.md +3649 -3381
  2. package/README-id.md +923 -844
  3. package/README.md +836 -788
  4. package/bin/build-agents.js +43 -27
  5. package/bin/cli.js +701 -3
  6. package/bin/graph-extract.js +927 -0
  7. package/bin/graph-notes.js +188 -0
  8. package/bin/graph-query.js +808 -0
  9. package/bin/graph-resolve.js +178 -0
  10. package/bin/graph-signals.js +277 -0
  11. package/bin/graph.js +605 -0
  12. package/bin/verify-contracts.js +4669 -4553
  13. package/bin/verify-package.js +626 -616
  14. package/bin/webui/api.js +1419 -1414
  15. package/bin/webui/fixtures/index.js +579 -576
  16. package/bin/webui/fixtures/knowledge.js +316 -291
  17. package/bin/webui/i18n/en/knowledge.json +167 -151
  18. package/bin/webui/i18n/en/overview.json +101 -100
  19. package/bin/webui/i18n/id/knowledge.json +167 -151
  20. package/bin/webui/i18n/id/overview.json +101 -100
  21. package/bin/webui/js/panels/knowledge.js +1065 -1006
  22. package/bin/webui/js/panels/overview.js +492 -488
  23. package/package.json +39 -39
  24. package/templates/agents/MODEL-MAPPING.md +163 -158
  25. package/templates/agents/orc-executor-haiku-4-5.md +133 -121
  26. package/templates/agents/orc-executor-opus-4-7-high.md +134 -122
  27. package/templates/agents/orc-executor-opus-4-7-med.md +134 -122
  28. package/templates/agents/orc-executor-opus-4-8-high.md +134 -122
  29. package/templates/agents/orc-executor-opus-5-high.md +134 -122
  30. package/templates/agents/orc-executor-opus-5-low.md +134 -122
  31. package/templates/agents/orc-executor-opus-5-med.md +134 -122
  32. package/templates/agents/orc-executor-sonnet-4-6-high.md +134 -122
  33. package/templates/agents/orc-executor-sonnet-4-6-med.md +134 -122
  34. package/templates/agents/orc-executor-sonnet-5-high.md +134 -122
  35. package/templates/agents/orc-graph-noter-sonnet-4-6-med.md +86 -0
  36. package/templates/hooks/README.md +444 -396
  37. package/templates/hooks/orc-graph-hook.js +336 -0
  38. package/templates/hooks/orc-statusline-render.js +922 -921
  39. package/templates/hooks/orc-statusline.js +1596 -1545
  40. package/templates/skills/_shared/README.md +4 -0
  41. package/templates/skills/_shared/code-graph.md +220 -0
  42. package/templates/skills/_shared/opus5-only.md +4 -0
  43. package/templates/skills/_shared/phases/execution.md +166 -147
  44. package/templates/skills/_shared/phases/planning.md +142 -135
  45. package/templates/skills/_shared/phases/preflight.md +132 -118
  46. package/templates/skills/_shared/phases/review.md +63 -53
  47. package/templates/skills/_shared/phases/ship.md +96 -88
  48. package/templates/skills/_shared/phases/trace.md +6 -0
  49. package/templates/skills/_shared/phases/wiki-consult.md +194 -189
  50. package/templates/skills/_shared/read-ladder.md +124 -102
  51. package/templates/skills/_shared/return-validation.md +259 -250
  52. package/templates/skills/orc/SKILL.md +255 -254
  53. package/templates/skills/orc-diy/references/flow-schema.md +101 -100
  54. package/templates/skills/orc-fast/SKILL.md +236 -229
  55. package/templates/skills/orc-mini/SKILL.md +267 -259
  56. package/templates/skills/orc-quick/SKILL.md +378 -361
  57. package/templates/skills/orc-quick/references/dispatch-gate.md +6 -0
  58. package/templates/skills/orc-wiki/references/staleness.md +294 -288
@@ -1,616 +1,626 @@
1
- #!/usr/bin/env node
2
- "use strict";
3
- /**
4
- * Package integrity check. Fails LOUDLY if any critical file is missing —
5
- * so an incomplete push (e.g. corrupted by OneDrive sync) errors immediately
6
- * instead of installing a dangling `orc` command.
7
- * Runs on prepack (before publish/pack) and can be run manually: node bin/verify-package.js
8
- */
9
- const fs = require("fs");
10
- const path = require("path");
11
-
12
- const ROOT = path.join(__dirname, "..");
13
- const required = [
14
- "bin/cli.js",
15
- "package.json",
16
- "README.md",
17
- // The `orc ui` web panel (v0.43.0). Named file by file, not covered by a
18
- // count: the panel is a set of files that only work together, and a publish
19
- // missing any one of them serves a page that 500s or renders blank. NOTE the
20
- // folder — `bin/ui.js` is the TERMINAL styling kit and is a different thing.
21
- "bin/webui/serve.js",
22
- "bin/webui/api.js",
23
- "bin/webui/app.html",
24
- // The stylesheet layers (v0.48.1). The <link> order in app.html is the
25
- // cascade order; 06-responsive and 04-motion are last on purpose.
26
- "bin/webui/css/00-tokens.css",
27
- "bin/webui/css/01-base.css",
28
- "bin/webui/css/02-shell.css",
29
- "bin/webui/css/03-components.css",
30
- "bin/webui/css/04-motion.css",
31
- "bin/webui/css/05-tour.css",
32
- "bin/webui/css/06-responsive.css",
33
- "bin/webui/css/panels/overview.css",
34
- "bin/webui/css/panels/settings.css",
35
- "bin/webui/css/panels/lanes.css",
36
- "bin/webui/css/panels/rules.css",
37
- "bin/webui/css/panels/runs.css",
38
- "bin/webui/css/panels/knowledge.css",
39
- // No knowledge.css: that panel is composed entirely from shared primitives
40
- // (.card, .chip, .tbl, .bar-track). An empty stylesheet would be one more
41
- // request and one more thing to keep in the manifest for no rules at all.
42
- "bin/webui/css/panels/stats.css",
43
- "bin/webui/css/panels/flow.css",
44
- "bin/webui/css/panels/crosslink.css",
45
- "bin/webui/css/panels/learn.css",
46
- "bin/webui/css/panels/mockrun.css",
47
- "bin/webui/css/panels/maintenance.css",
48
- "bin/webui/css/panels/pact.css",
49
- "bin/webui/css/panels/boundary.css",
50
- "bin/webui/css/panels/wait.css",
51
- "bin/webui/css/panels/hookui.css",
52
- "bin/webui/css/panels/handoff.css",
53
- "bin/webui/css/panels/challenge.css",
54
- "bin/webui/css/panels/docs.css",
55
- "bin/webui/css/panels/extra.css",
56
- "bin/webui/css/panels/test.css",
57
- "bin/webui/css/panels/experiment.css",
58
- // The client modules (v0.48.1). The <script> order in app.html is the load
59
- // order and the numeric prefix is that order; 99-boot.js must be last.
60
- "bin/webui/js/00-core.js",
61
- "bin/webui/js/01-i18n.js",
62
- "bin/webui/js/02-ui.js",
63
- "bin/webui/js/03-md.js",
64
- "bin/webui/js/04-router.js",
65
- "bin/webui/js/05-banners.js",
66
- "bin/webui/js/06-edit.js",
67
- "bin/webui/js/panels/overview.js",
68
- "bin/webui/js/panels/settings.js",
69
- "bin/webui/js/panels/lanes.js",
70
- "bin/webui/js/panels/rules.js",
71
- "bin/webui/js/panels/runs.js",
72
- "bin/webui/js/panels/knowledge.js",
73
- "bin/webui/js/panels/stats.js",
74
- "bin/webui/js/panels/flow.js",
75
- "bin/webui/js/panels/crosslink.js",
76
- "bin/webui/js/panels/learn.js",
77
- "bin/webui/js/panels/mockrun.js",
78
- "bin/webui/js/panels/experiment.js",
79
- "bin/webui/js/panels/maintenance.js",
80
- "bin/webui/js/panels/pact.js",
81
- "bin/webui/js/panels/boundary.js",
82
- "bin/webui/js/panels/wait.js",
83
- "bin/webui/js/panels/hookui.js",
84
- "bin/webui/js/panels/handoff.js",
85
- "bin/webui/js/panels/challenge.js",
86
- "bin/webui/js/panels/docs.js",
87
- "bin/webui/js/panels/extra.js",
88
- "bin/webui/js/panels/test.js",
89
- "bin/webui/js/90-tour.js",
90
- "bin/webui/js/91-shortcuts.js",
91
- "bin/webui/js/99-boot.js",
92
- // The canned data (v0.48.1), one file per panel. index.js is the ROUTER;
93
- // every other file is data. --fixtures must carry ONE OF EVERY STATE.
94
- "bin/webui/fixtures/index.js",
95
- "bin/webui/fixtures/shell.js",
96
- "bin/webui/fixtures/settings.js",
97
- "bin/webui/fixtures/lanes.js",
98
- "bin/webui/fixtures/rules.js",
99
- "bin/webui/fixtures/wiki-one.js",
100
- "bin/webui/fixtures/knowledge.js",
101
- "bin/webui/fixtures/runs.js",
102
- "bin/webui/fixtures/stats.js",
103
- "bin/webui/fixtures/pact.js",
104
- "bin/webui/fixtures/boundary.js",
105
- "bin/webui/fixtures/wait.js",
106
- "bin/webui/fixtures/hookui.js",
107
- "bin/webui/fixtures/handoff.js",
108
- "bin/webui/fixtures/maintenance.js",
109
- "bin/webui/fixtures/challenge.js",
110
- "bin/webui/fixtures/docs.js",
111
- "bin/webui/fixtures/flow.js",
112
- "bin/webui/fixtures/crosslink.js",
113
- "bin/webui/fixtures/mockrun.js",
114
- "bin/webui/fixtures/extra.js",
115
- "bin/webui/fixtures/test.js",
116
- // The string tables (v0.43.6). Named here for the same reason: English is the
117
- // FALLBACK table every other language falls back to, so a publish that drops
118
- // it renders raw dotted keys on every panel, in every language.
119
- // v0.52.0 - the TERM LIST. It is not a string table and is never fetched by
120
- // the page; it is the one page that keeps the next two hundred strings
121
- // consistent, and without it a wording pass drifts back within two releases.
122
- "bin/webui/i18n/TERMS.md",
123
- "bin/webui/i18n/en/common.json",
124
- "bin/webui/i18n/en/nav.json",
125
- "bin/webui/i18n/en/banner.json",
126
- "bin/webui/i18n/en/overview.json",
127
- "bin/webui/i18n/en/settings.json",
128
- "bin/webui/i18n/en/lanes.json",
129
- "bin/webui/i18n/en/rules.json",
130
- "bin/webui/i18n/en/runs.json",
131
- "bin/webui/i18n/en/knowledge.json",
132
- "bin/webui/i18n/en/stats.json",
133
- "bin/webui/i18n/en/flow.json",
134
- "bin/webui/i18n/en/crosslink.json",
135
- "bin/webui/i18n/en/learn.json",
136
- "bin/webui/i18n/en/mockrun.json",
137
- "bin/webui/i18n/en/maintenance.json",
138
- "bin/webui/i18n/en/pact.json",
139
- "bin/webui/i18n/en/boundary.json",
140
- "bin/webui/i18n/en/wait.json",
141
- "bin/webui/i18n/en/hookui.json",
142
- "bin/webui/i18n/en/handoff.json",
143
- "bin/webui/i18n/en/challenge.json",
144
- "bin/webui/i18n/en/docs.json",
145
- "bin/webui/i18n/en/extra.json",
146
- "bin/webui/i18n/en/test.json",
147
- "bin/webui/i18n/en/experiment.json",
148
- "bin/webui/i18n/en/tour.json",
149
- "bin/webui/i18n/id/common.json",
150
- "bin/webui/i18n/id/nav.json",
151
- "bin/webui/i18n/id/banner.json",
152
- "bin/webui/i18n/id/overview.json",
153
- "bin/webui/i18n/id/settings.json",
154
- "bin/webui/i18n/id/lanes.json",
155
- "bin/webui/i18n/id/rules.json",
156
- "bin/webui/i18n/id/runs.json",
157
- "bin/webui/i18n/id/knowledge.json",
158
- "bin/webui/i18n/id/stats.json",
159
- "bin/webui/i18n/id/flow.json",
160
- "bin/webui/i18n/id/crosslink.json",
161
- "bin/webui/i18n/id/learn.json",
162
- "bin/webui/i18n/id/mockrun.json",
163
- "bin/webui/i18n/id/maintenance.json",
164
- "bin/webui/i18n/id/pact.json",
165
- "bin/webui/i18n/id/boundary.json",
166
- "bin/webui/i18n/id/wait.json",
167
- "bin/webui/i18n/id/hookui.json",
168
- "bin/webui/i18n/id/handoff.json",
169
- "bin/webui/i18n/id/challenge.json",
170
- "bin/webui/i18n/id/docs.json",
171
- "bin/webui/i18n/id/extra.json",
172
- "bin/webui/i18n/id/test.json",
173
- "bin/webui/i18n/id/experiment.json",
174
- "bin/webui/i18n/id/tour.json",
175
- // The mocked runs (v0.46.x): the catalogue module plus the folder it reads.
176
- // Both `orc mock-run` and the panel's Mocked Skill Use page are empty without
177
- // them, and an empty catalogue looks like a broken feature rather than a
178
- // publish that dropped a folder.
179
- "bin/mockrun-catalog.js",
180
- // The two DATED data files (v0.50.0). Both ship inside the package and both
181
- // are load-bearing on absence rather than on content: without the catalog
182
- // `orc extra providers` is a packaging bug it reports as one, and without the
183
- // price table every `usd` reads as an em dash forever. They are named here for
184
- // the same reason every webui file is — a publish that drops one serves a
185
- // feature that looks broken rather than missing.
186
- "bin/providers.json",
187
- "bin/pricing.json",
188
- "mock-run",
189
- "mock-run/INDEX.md",
190
- "templates",
191
- "templates/skills/orc/SKILL.md",
192
- "templates/skills/orc/references/ultra-mode.md",
193
- "templates/skills/orc-advisor/SKILL.md",
194
- "templates/skills/orc-judge/SKILL.md",
195
- "templates/skills/orc-fast/SKILL.md",
196
- "templates/skills/orc-claude/SKILL.md",
197
- "templates/skills/orc-claude/references/template.md",
198
- "templates/skills/orc-claude/references/refresh.md",
199
- "templates/skills/orc-wiki/references/staleness.md",
200
- "templates/skills/orc-learn/SKILL.md",
201
- "templates/skills/orc-learn/references/refresh.md",
202
- "templates/skills/orc-poly/SKILL.md",
203
- "templates/skills/orc-poly/references/poly-spec.md",
204
- "templates/skills/orc-poly/references/gather.md",
205
- // Stacked pull requests (v0.37.0) — two standalone lanes plus the three
206
- // canonical shared contracts they and ORC's ship gate all read. A missing
207
- // shared file makes the ship gate hand off to a lane that cannot preflight.
208
- "templates/skills/orc-pr-setup/SKILL.md",
209
- "templates/skills/orc-pr-setup/README.md",
210
- "templates/skills/orc-pr-setup/references/layer-taxonomy.md",
211
- "templates/skills/orc-pr-setup/references/certainty-gate.md",
212
- "templates/skills/orc-pr-driver/SKILL.md",
213
- "templates/skills/orc-pr-driver/README.md",
214
- "templates/skills/orc-pr-driver/references/green-gate.md",
215
- "templates/skills/orc-pr-driver/references/orc-run-split.md",
216
- "templates/skills/orc-pr-driver/references/conflict-playbook.md",
217
- "templates/skills/_shared/stack-plan.md",
218
- "templates/skills/_shared/gh-stack-commands.md",
219
- "templates/skills/_shared/pr-templates.md",
220
- "templates/skills/orc/subskills/orc-pr/stack-gate.md",
221
- "templates/skills/orc-diy/SKILL.md",
222
- "templates/skills/orc-diy/README.md",
223
- "templates/skills/orc-diy/references/compile.md",
224
- "templates/skills/orc-diy/references/flow-schema.md",
225
- "templates/skills/orc-diy/references/locked-blocks.md",
226
- "templates/skills/orc-diy/references/blocks/header.md",
227
- "templates/skills/orc-quick/SKILL.md",
228
- "templates/skills/orc-quick/README.md",
229
- "templates/skills/orc-quick/references/context-doc.md",
230
- "templates/skills/orc-quick/references/dispatch-gate.md",
231
- "templates/skills/orc-quick/references/gh-mode.md",
232
- // Quality-of-life lanes (v0.42.0). Three skills, ZERO new agents — the grill
233
- // dispatches read-only recon ad-hoc (the orc-quick precedent) and the other
234
- // two dispatch nothing at all. `_shared/interview.md` is the canonical
235
- // mechanic both the grill and intake.md run; a missing copy of it makes the
236
- // grill a lane with no procedure.
237
- "templates/skills/_shared/interview.md",
238
- "templates/skills/orc-grill/SKILL.md",
239
- "templates/skills/orc-grill/references/grill-doc.md",
240
- // v0.45.0 — /orc-brainstorm, again with ZERO new agents. `lane-suspend.md` is
241
- // the RETURN-TO contract BOTH halves of the brainstorm↔grill trip read: a
242
- // publish missing it leaves a lane that suspends into another lane with no
243
- // definition of how (or whether) it comes back. `lenses.md` is the only place
244
- // ORC generates options on purpose — without it B2 is a mood, not a phase.
245
- "templates/skills/_shared/lane-suspend.md",
246
- "templates/skills/orc-brainstorm/SKILL.md",
247
- "templates/skills/orc-brainstorm/references/brainstorm-doc.md",
248
- "templates/skills/orc-brainstorm/references/lenses.md",
249
- "templates/commands/orc-brainstorm.md",
250
- // v0.46.0 — the six new lanes. Named file by file for the same reason the
251
- // panel's files are: each SKILL.md is useless without its references (a lane
252
- // whose card/ledger/surface shape is missing dispatches against a contract it
253
- // cannot read), and the two CONSUMER gate files are what /orc loads at Phase 1
254
- // — a publish that drops one leaves the spine pointing at nothing.
255
- "templates/skills/orc-pact/SKILL.md",
256
- "templates/skills/orc-pact/references/ledger.md",
257
- "templates/skills/orc-pact/references/gate.md",
258
- "templates/skills/orc-boundary/SKILL.md",
259
- "templates/skills/orc-boundary/references/card.md",
260
- "templates/skills/orc-boundary/references/gate.md",
261
- "templates/skills/orc-handoff/SKILL.md",
262
- "templates/skills/orc-handoff/references/surfaces.md",
263
- "templates/skills/orc-handoff/references/handoff-log.md",
264
- "templates/skills/orc-budget/SKILL.md",
265
- "templates/skills/orc-budget/references/corpus.md",
266
- "templates/skills/orc-aftermath/SKILL.md",
267
- "templates/skills/orc-aftermath/references/report.md",
268
- "templates/skills/orc-export/SKILL.md",
269
- // W1 — the partial-refresh reference is the whole tier ladder + the budget cap
270
- // + the retirement offer; without it orc-wiki's spine points at a missing file
271
- // at exactly the moment it has to choose which scanner to dispatch.
272
- "templates/skills/orc-wiki/references/partial-refresh.md",
273
- // v0.47.0 — /orc-challenge. Named file by file for the reason every lane's
274
- // files are: the SKILL.md is a spine and its references ARE the contract. A
275
- // publish that drops `sealed-slice.md` ships a judge whose slice has no
276
- // definition, which is the one thing this lane exists to prevent; a publish
277
- // that drops `intake.md` ships a lane with no goal contract, so rule 0 becomes
278
- // a sentence nobody can act on.
279
- "templates/skills/orc-challenge/SKILL.md",
280
- "templates/skills/orc-challenge/README.md",
281
- "templates/skills/orc-challenge/references/intake.md",
282
- "templates/skills/orc-challenge/references/dimensions.md",
283
- "templates/skills/orc-challenge/references/kinds.md",
284
- "templates/skills/orc-challenge/references/rubric.md",
285
- "templates/skills/orc-challenge/references/sealed-slice.md",
286
- "templates/skills/orc-challenge/references/cycle-state.md",
287
- "templates/skills/orc-challenge/references/verdict-doc.md",
288
- "templates/skills/orc-challenge/references/fix-brief.md",
289
- "templates/skills/orc-challenge/references/plain-english.md",
290
- "templates/skills/orc-challenge/references/conservation.md",
291
- // v0.49.1 — the council's canonical prose. The spine keeps the token and a
292
- // pointer; this file is the one copy (the `_shared/` discipline).
293
- "templates/skills/orc-challenge/references/council.md",
294
- "templates/skills/orc-challenge/examples/council-full-roster.md",
295
- // v0.48.0 — /orc-doc. Named file by file for the reason every lane's files
296
- // are: `chunking.md` IS the token architecture (a publish that drops it ships
297
- // an orchestrator with no definition of what it may hold, which is the one
298
- // thing this lane exists to bound), `resume-protocol.md` is the whole reason
299
- // the context is frozen, and `templates/` is the five base skeletons the
300
- // batching table is pinned to by a golden test.
301
- "templates/skills/orc-doc/SKILL.md",
302
- "templates/skills/orc-doc/README.md",
303
- "templates/skills/orc-doc/references/gates.md",
304
- "templates/skills/orc-doc/references/chunking.md",
305
- "templates/skills/orc-doc/references/resume-protocol.md",
306
- "templates/skills/orc-doc/references/portable-markdown.md",
307
- "templates/skills/orc-doc/references/plain-language.md",
308
- "templates/skills/orc-doc/references/import-targets.md",
309
- // v0.49.2 — the project's own house rules, and ORC's own generation rules.
310
- // Two files because they are read in that ORDER and the order is the contract.
311
- "templates/skills/orc-doc/references/house-rules.md",
312
- "templates/skills/orc-doc/references/generation-rules.md",
313
- "templates/skills/orc-doc/references/templates/prd.md",
314
- "templates/skills/orc-doc/references/templates/tsd.md",
315
- "templates/skills/orc-doc/references/templates/collaboration.md",
316
- "templates/skills/orc-doc/references/templates/report.md",
317
- "templates/skills/orc-doc/references/templates/workflow.md",
318
- "templates/commands/orc-doc.md",
319
- "templates/commands/orc-challenge.md",
320
- "templates/commands/orc-pact.md",
321
- "templates/commands/orc-boundary.md",
322
- "templates/commands/orc-handoff.md",
323
- "templates/commands/orc-budget.md",
324
- "templates/commands/orc-aftermath.md",
325
- "templates/commands/orc-export.md",
326
- "templates/skills/orc-route/SKILL.md",
327
- "templates/skills/orc-explain/SKILL.md",
328
- "templates/skills/orc-analyze/references/thin-input.md",
329
- // v1.0.0 W7 — the ONE config doc. `orc/config.md` stopped restating 72 key
330
- // defaults and now points here for the ranks, the families, the gates, the
331
- // `announce[]` boundary and the CLI-absent floor. A publish missing this file
332
- // leaves every lane's `## Config` section pointing at nothing — and the
333
- // fallback that is supposed to fire when the CLI cannot answer is exactly the
334
- // moment there is no CLI to ask instead.
335
- "templates/skills/_shared/config-precedence.md",
336
- // v1.0.0 W11 — the phase library. The shared phase material already existed
337
- // and was already shared; it just lived in ONE lane's private folder with 26
338
- // other lanes reaching across into it. A publish missing any of these leaves
339
- // every one of those lanes pointing at nothing — and `trace.md` in particular
340
- // is the file that says how a run records itself, so its absence is silent by
341
- // construction. README.md carries the CLOSED layer set, which is what stops a
342
- // trimmed lane reading a full-lane procedure.
343
- "templates/skills/_shared/phases/README.md",
344
- "templates/skills/_shared/phases/trace.md",
345
- "templates/skills/_shared/phases/preflight.md",
346
- "templates/skills/_shared/phases/stop-resume.md",
347
- // v1.0.0 W12 — the seven files that were already SHARED while living in one
348
- // lane's private `references/`. Their consumers are measured, not believed:
349
- // the C.6 lint asserts every declared reader really points at the file.
350
- "templates/skills/_shared/phases/intake.md",
351
- "templates/skills/_shared/phases/plan-handoff.md",
352
- "templates/skills/_shared/phases/wave-grouping.md",
353
- "templates/skills/_shared/phases/analyst-gates.md",
354
- "templates/skills/_shared/phases/wiki-consult.md",
355
- "templates/skills/_shared/phases/security-checklist.md",
356
- "templates/skills/_shared/phases/house-rules.md",
357
- // v1.0.0 W13 — the ten build phases orc-diy became the second reader of.
358
- // Each carries TWO layers: `full` (/orc's procedure) and `composed` (what
359
- // `orc diy compile` stitches). A publish missing one breaks BOTH lanes, and
360
- // breaks orc-diy loudly — the compiler names the file and refuses.
361
- "templates/skills/_shared/phases/planning.md",
362
- "templates/skills/_shared/phases/scoring.md",
363
- "templates/skills/_shared/phases/execution.md",
364
- "templates/skills/_shared/phases/review.md",
365
- "templates/skills/_shared/phases/security.md",
366
- "templates/skills/_shared/phases/verify.md",
367
- "templates/skills/_shared/phases/testgen.md",
368
- "templates/skills/_shared/phases/mock-example.md",
369
- "templates/skills/_shared/phases/summary.md",
370
- "templates/skills/_shared/phases/ship.md",
371
- // v1.0.0 W12 — /orc's own phase bodies, W13 — down to the two nothing else
372
- // runs. The spine is loaded IN FULL on activation and these are loaded when
373
- // their phase fires; a publish missing one leaves the manifest naming a file
374
- // that is not there, which is a phase that silently does nothing.
375
- "templates/skills/orc/references/phases/intake.md",
376
- "templates/skills/orc/references/phases/integration.md",
377
- // v1.0.0 W14 — orc-wiki's five phase bodies. A wiki run reaches FEW of them
378
- // (Phase 0 auto-branches into fresh / resume / refresh / repair, 3c is a legacy
379
- // backfill), which is what makes a file per phase pay here and not elsewhere.
380
- // A publish missing one leaves the manifest naming a file that is not there.
381
- "templates/skills/orc-wiki/references/phases/phase-0.md",
382
- "templates/skills/orc-wiki/references/phases/phase-1.md",
383
- "templates/skills/orc-wiki/references/phases/phase-2.md",
384
- "templates/skills/orc-wiki/references/phases/phase-3.md",
385
- "templates/skills/orc-wiki/references/phases/phase-3c.md",
386
- "templates/commands/orc-grill.md",
387
- "templates/commands/orc-route.md",
388
- "templates/commands/orc-explain.md",
389
- "templates/commands/orc.md",
390
- "templates/commands/orc-quick.md",
391
- "templates/commands/orc-diy.md",
392
- "templates/commands/orc-ultra.md",
393
- "templates/commands/orc-fast.md",
394
- "templates/commands/orc-claude.md",
395
- "templates/commands/orc-learn.md",
396
- "templates/commands/orc-poly.md",
397
- "templates/commands/orc-pr-setup.md",
398
- "templates/commands/orc-pr-driver.md",
399
- "templates/agents/MODEL-MAPPING.md",
400
- "templates/agents/orc-advisor-opus-5-xhigh.md",
401
- "templates/agents/orc-judge-opus-5-xhigh.md",
402
- "templates/agents/orc-claude-writer-opus-4-8-high.md",
403
- "templates/agents/orc-learn-writer-opus-5-low.md",
404
- "templates/agents/orc-trace-writer-haiku-4-5.md",
405
- // Core non-generated agents — named explicitly so a dropped file is REPORTED
406
- // by name, not merely absorbed by the count floor. (The 8 executor agents are
407
- // checked separately by `build-agents.js --check`.)
408
- "templates/agents/orc-system-analyst-opus-5-high.md",
409
- "templates/agents/orc-planner-opus-5-med.md",
410
- "templates/agents/orc-reviewer-opus-5-med.md",
411
- "templates/agents/orc-verifier-opus-5-med.md",
412
- "templates/agents/orc-scout-sonnet-4-6-high.md",
413
- "templates/agents/orc-test-author-opus-5-med.md",
414
- "templates/agents/orc-pattern-codifier-sonnet-5-high.md",
415
- "templates/agents/orc-retro-sonnet-5-high.md",
416
- "templates/agents/orc-wiki-scanner-opus-4-8-high.md",
417
- // v0.46.0 — the LIGHT half of the wiki scan tier ladder. Both halves must ship:
418
- // the ladder resolves at dispatch time, so a missing light scanner makes every
419
- // small-delta refresh dispatch a nonexistent agent.
420
- "templates/agents/orc-wiki-scanner-sonnet-5-high.md",
421
- "templates/agents/orc-context-combiner-opus-5-high.md",
422
- // The orc-mini lane's agent pair and the whole Fable 5 role-override feature
423
- // were guarded by nothing but the count floor — a publish missing any of them
424
- // ships a lane that dispatches a nonexistent agent.
425
- "templates/agents/orc-analyze-mini-sonnet-5-high.md",
426
- "templates/agents/orc-planner-mini-sonnet-5-high.md",
427
- // The Opus-5-only mode roster (v0.36.0). Both halves of every pair must ship:
428
- // the mode is a runtime toggle, so a missing variant makes `opus5_only: true`
429
- // dispatch a nonexistent agent for that role.
430
- "templates/agents/orc-analyze-mini-opus-5-med.md",
431
- "templates/agents/orc-planner-mini-opus-5-med.md",
432
- "templates/agents/orc-scout-opus-5-low.md",
433
- "templates/agents/orc-pattern-codifier-opus-5-med.md",
434
- "templates/agents/orc-wiki-scanner-opus-5-med.md",
435
- "templates/agents/orc-claude-writer-opus-5-med.md",
436
- "templates/agents/orc-retro-opus-5-med.md",
437
- // v0.47.0 — the three /orc-challenge agents. All THREE must ship: a cycle that
438
- // cannot dispatch the reader silently loses D4, and one that cannot dispatch
439
- // the advisor turns a FAIL into a list with no order. All three are already
440
- // Opus 5, so `opus5_only` needs no twin for any of them.
441
- "templates/agents/orc-challenge-judge-opus-5-high.md",
442
- "templates/agents/orc-challenge-advisor-opus-5-med.md",
443
- "templates/agents/orc-challenge-reader-opus-5-low.md",
444
- // v0.49.1 — THE COUNCIL. Five DIFFERENT INSTRUMENTS, not five tiers of one:
445
- // the contrarian assumes a fatal flaw, the outsider knows nothing and may not
446
- // be told, the council executor asks what you do Monday morning, the
447
- // first-principles thinker disputes the goal itself, and the expansionist is
448
- // the only lens not looking for a defect. All five must ship: a roster lens
449
- // that cannot be dispatched is a NOT-RUN row a user paid to select, and rule
450
- // 15 makes that loud rather than silent. All five are claude-opus-5, so
451
- // `opus5_only` adds NO pair and the floor moves by exactly five.
452
- "templates/agents/orc-challenge-contrarian-opus-5-high.md",
453
- "templates/agents/orc-challenge-outsider-opus-5-low.md",
454
- "templates/agents/orc-challenge-executor-opus-5-med.md",
455
- "templates/agents/orc-challenge-principles-opus-5-high.md",
456
- "templates/agents/orc-challenge-expansionist-opus-5-med.md",
457
- // v0.48.0 — the two /orc-doc agents. BOTH must ship: a write wave that cannot
458
- // dispatch the writer has nothing to assemble, and a check wave that cannot
459
- // dispatch the checker silently turns the only judgment step into the free
460
- // lint. Both are already Opus 5, so `opus5_only` adds no twin for either.
461
- "templates/agents/orc-doc-writer-opus-5-med.md",
462
- "templates/agents/orc-doc-checker-opus-5-low.md",
463
- // v1.5.0 - /orc-test's two agents, and they are two INSTRUMENTS rather than
464
- // two tiers of one. The designer is `high` because the cheap answer to
465
- // "design some test cases" is the list the CLI already derived for free; the
466
- // interpreter is `low` because a harder-thinking interpreter reasons its way
467
- // to why a leaked stack trace is probably fine in staging, which is exactly
468
- // the gap it exists to find. Nothing may ever upgrade the interpreter. Both
469
- // are claude-opus-5, so `opus5_only` adds NO pair and the floor moves by two.
470
- "templates/agents/orc-test-designer-opus-5-high.md",
471
- "templates/agents/orc-test-interpreter-opus-5-low.md",
472
- // v1.2.1 — the status line explained for the person reading it, in
473
- // Simplified Technical English. It ships INTO .claude/hooks/ next to the hook
474
- // it describes, because that is where somebody looking at a segment they do
475
- // not recognise will look for it.
476
- "templates/hooks/README.md",
477
- "templates/hooks/orc-effort-guard.js",
478
- "templates/hooks/orc-statusline.js",
479
- // v1.3.0 — THE RENDER ENGINE, and it is required by BOTH halves: the hook
480
- // requires it as a sibling out of .claude/hooks/, and bin/cli.js requires it
481
- // out of templates/hooks/ for `orc statusline preview`. That is what makes
482
- // the panel's preview and the bar's real output byte-identical BY
483
- // CONSTRUCTION. A missing file here breaks the status line AND the panel.
484
- "templates/hooks/orc-statusline-render.js",
485
- // v1.4.0 — the SECOND board, and the per-agent token record that rides with
486
- // it. Wired even with the board off, because the measurement is handed over
487
- // either way.
488
- "templates/hooks/orc-subagent-line.js",
489
- // v1.6.0 — the read gate. The one layer that can refuse an oversized read by
490
- // the ORCHESTRATOR. Ships wired but OFF; `read_gate` arms it.
491
- "templates/hooks/orc-read-gate.js",
492
- "templates/hooks/orc-trace.js",
493
- ];
494
-
495
- const missing = [];
496
- for (const rel of required) {
497
- if (!fs.existsSync(path.join(ROOT, rel))) missing.push(rel);
498
- }
499
-
500
- // Every skill dir must contain at least one SKILL.md; every agent file must be non-empty.
501
- function walkCount(dir, ext) {
502
- let n = 0;
503
- if (!fs.existsSync(dir)) return 0;
504
- for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
505
- const p = path.join(dir, e.name);
506
- if (e.isDirectory()) n += walkCount(p, ext);
507
- else if (e.name.endsWith(ext)) n += 1;
508
- }
509
- return n;
510
- }
511
-
512
- const skillCount = walkCount(path.join(ROOT, "templates/skills"), "SKILL.md");
513
- const agentCount = walkCount(path.join(ROOT, "templates/agents"), ".md");
514
- // Floors sit AT current reality (26 skills / 40 agent files: 39 agents +
515
- // MODEL-MAPPING.md — +7 fixed-role variants for the opus5_only mode) so a
516
- // dropped file fails the count check instead of sliding
517
- // into the slack an under-set floor grants. Raise them with the payload.
518
- // v0.38.0: +1 skill (orc-quick) and NO new agent — the quick lane reuses
519
- // shipped executors and dispatches read-only recon ad-hoc by model name.
520
- // v0.42.0: +3 skills (orc-grill, orc-route, orc-explain) and still NO new
521
- // agent — same precedent. The agent floor deliberately does NOT move: a QoL
522
- // lane that needed a pinned agent would also need its opus5_only twin, a
523
- // MODEL-MAPPING row and a golden test, which is why none of them has one.
524
- // v0.45.0: +1 skill (orc-brainstorm) and STILL no new agent — its divergent
525
- // generation is the orchestrator's own work and its recon is dispatched ad-hoc
526
- // by model+effort, so the agent floor holds at 40.
527
- // v0.46.0: +6 skills (orc-pact, orc-boundary, orc-handoff, orc-budget,
528
- // orc-aftermath, orc-export) and +1 agent — and the split is the point. Five of
529
- // the six lanes ship ZERO agents (the v0.38.0/v0.45.0 precedent: read-only recon
530
- // is dispatched ad-hoc by model+effort, and three of them dispatch nothing at
531
- // all because their work is deterministic CLI). The ONE new agent is the wiki
532
- // scan ladder's LIGHT half, which is a real dispatch target with a real name and
533
- // therefore earns a MODEL-MAPPING row, an explicit guard entry above, and a
534
- // place in the opus5_only table's prose.
535
- // v0.47.0: +1 skill (orc-challenge) and +3 agents — the first lane since v0.42.0
536
- // to earn any, and it earns three because each is a DIFFERENT INSTRUMENT, not a
537
- // tier of the same one. The reader is `low` on purpose (a harder-thinking reader
538
- // papers over exactly the gaps D4 measures), the judge is `high` because D2 is
539
- // the only dimension no computer can reach, and the advisor is `medium` because
540
- // grouping findings is pattern work. All three are claude-opus-5, so `opus5_only`
541
- // adds NO pair and the floor moves by exactly three.
542
- // v0.48.0: +1 skill (orc-doc) and +2 agents. The split follows v0.47.0's rule —
543
- // an agent exists when it is a DIFFERENT INSTRUMENT, not a tier of the same one.
544
- // The writer holds one part file and never `document.md`; the checker holds one
545
- // LINE RANGE and has `Read` only. The checker is `low` on purpose (a
546
- // harder-thinking checker reasons its way past a gap a real reader would trip
547
- // on — the challenge cold reader's reasoning), so nothing may upgrade it. Both
548
- // are claude-opus-5, so `opus5_only` adds NO pair and the floor moves by two.
549
- // v0.49.1: +0 skills and +5 agents — THE COUNCIL. Same rule as v0.47.0, applied
550
- // five times: each of these is a DIFFERENT INSTRUMENT, not a tier of one. The
551
- // outsider is `low` and the contrarian is `high` for the same class of reason
552
- // the cold reader is `low` — effort here is a MEASUREMENT choice, not a cost
553
- // one, and a key that let either be tuned would be a key that let the
554
- // instrument be broken. All five are claude-opus-5, so `opus5_only` adds NO
555
- // pair and the floor moves by exactly five.
556
- // v1.0.0 W3: +0 skills and -5 agents — the Fable 5 role override is REMOVED.
557
- // It is the first time this floor has ever gone DOWN, and the reason it may is
558
- // that the five files are not a tier of anything: they were a whole second
559
- // answer to "which model runs a role", competing with `opus5_only` for the same
560
- // decision. Deleting them removes a rank from `fixed-role-model` rather than a
561
- // capability from a lane. Fable 5 survives as a SESSION model (the effort guard
562
- // and the statusline still clear it at medium) — that is a different question,
563
- // and this wave does not touch it.
564
- // v1.5.0: +1 skill (orc-test) and +2 agents - the designer and the interpreter.
565
- // The lane's recon (T2's `unresolved[]`, T4's flow trace) is dispatched AD-HOC
566
- // by model+effort and earns no agent, the v0.38.0/v0.45.0 precedent, and that
567
- // limit is stated in the skill: no `SPAWN` line, so `/orc-retro` cannot
568
- // aggregate it.
569
- if (skillCount < 39) missing.push(`templates/skills (expected >=39 SKILL.md, found ${skillCount})`);
570
- if (agentCount < 48) missing.push(`templates/agents (expected >=48 .md, found ${agentCount})`);
571
-
572
- // B4 — encoding/mojibake guard. The OneDrive corruption rule becomes a gate:
573
- // scan every shipped text file for the U+FFFD replacement char (invalid UTF-8
574
- // decodes to it) and for a whitespace-flanked run of three-or-more question
575
- // marks — the shape a mangled em/en-dash or curly quote collapses into (a
576
- // space-flanked dash becoming space-Q-Q-Q-space). A genuine "What???" has no
577
- // leading space, so it is not flagged.
578
- const MOJIBAKE = /(^|\s)\?{3,}(\s|$)/;
579
- // U+FFFD needle built from its code point so this scanner never flags its own source.
580
- const REPL = String.fromCharCode(0xfffd);
581
- function scanEncoding(dir, hits) {
582
- if (!fs.existsSync(dir)) return;
583
- const st = fs.statSync(dir);
584
- if (st.isFile()) {
585
- let text;
586
- try {
587
- text = fs.readFileSync(dir, "utf8");
588
- } catch (_) {
589
- return; // unreadable → not our concern here
590
- }
591
- const rel = path.relative(ROOT, dir).replace(/\\/g, "/");
592
- // Reference U+FFFD via escape, never as a literal, so this scanner does not
593
- // flag its own source.
594
- if (text.includes(REPL)) hits.push(`${rel} (U+FFFD replacement char — corrupted bytes)`);
595
- else if (MOJIBAKE.test(text)) hits.push(`${rel} (whitespace-flanked "???" — likely mangled dash/quote)`);
596
- return;
597
- }
598
- for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
599
- scanEncoding(path.join(dir, e.name), hits);
600
- }
601
- }
602
- const encodingHits = [];
603
- scanEncoding(path.join(ROOT, "package.json"), encodingHits);
604
- scanEncoding(path.join(ROOT, "bin"), encodingHits);
605
- scanEncoding(path.join(ROOT, "templates"), encodingHits);
606
- for (const h of encodingHits) missing.push("encoding: " + h);
607
-
608
- if (missing.length) {
609
- console.error("\n❌ ORC package integrity check FAILED. Missing / incomplete:");
610
- for (const m of missing) console.error(" - " + m);
611
- console.error("\nDo NOT publish or push this tree. Likely cause: files were not");
612
- console.error("committed (OneDrive sync can corrupt commits). Rebuild the repo");
613
- console.error("OUTSIDE any cloud-synced folder, `git add -A`, verify, then push.\n");
614
- process.exit(1);
615
- }
616
- console.log(`✅ ORC package OK — ${skillCount} skills, ${agentCount} agent files, cli present.`);
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * Package integrity check. Fails LOUDLY if any critical file is missing —
5
+ * so an incomplete push (e.g. corrupted by OneDrive sync) errors immediately
6
+ * instead of installing a dangling `orc` command.
7
+ * Runs on prepack (before publish/pack) and can be run manually: node bin/verify-package.js
8
+ */
9
+ const fs = require("fs");
10
+ const path = require("path");
11
+
12
+ const ROOT = path.join(__dirname, "..");
13
+ const required = [
14
+ "bin/cli.js",
15
+ "package.json",
16
+ "README.md",
17
+ // The `orc ui` web panel (v0.43.0). Named file by file, not covered by a
18
+ // count: the panel is a set of files that only work together, and a publish
19
+ // missing any one of them serves a page that 500s or renders blank. NOTE the
20
+ // folder — `bin/ui.js` is the TERMINAL styling kit and is a different thing.
21
+ "bin/webui/serve.js",
22
+ "bin/webui/api.js",
23
+ "bin/webui/app.html",
24
+ // The stylesheet layers (v0.48.1). The <link> order in app.html is the
25
+ // cascade order; 06-responsive and 04-motion are last on purpose.
26
+ "bin/webui/css/00-tokens.css",
27
+ "bin/webui/css/01-base.css",
28
+ "bin/webui/css/02-shell.css",
29
+ "bin/webui/css/03-components.css",
30
+ "bin/webui/css/04-motion.css",
31
+ "bin/webui/css/05-tour.css",
32
+ "bin/webui/css/06-responsive.css",
33
+ "bin/webui/css/panels/overview.css",
34
+ "bin/webui/css/panels/settings.css",
35
+ "bin/webui/css/panels/lanes.css",
36
+ "bin/webui/css/panels/rules.css",
37
+ "bin/webui/css/panels/runs.css",
38
+ "bin/webui/css/panels/knowledge.css",
39
+ // No knowledge.css: that panel is composed entirely from shared primitives
40
+ // (.card, .chip, .tbl, .bar-track). An empty stylesheet would be one more
41
+ // request and one more thing to keep in the manifest for no rules at all.
42
+ "bin/webui/css/panels/stats.css",
43
+ "bin/webui/css/panels/flow.css",
44
+ "bin/webui/css/panels/crosslink.css",
45
+ "bin/webui/css/panels/learn.css",
46
+ "bin/webui/css/panels/mockrun.css",
47
+ "bin/webui/css/panels/maintenance.css",
48
+ "bin/webui/css/panels/pact.css",
49
+ "bin/webui/css/panels/boundary.css",
50
+ "bin/webui/css/panels/wait.css",
51
+ "bin/webui/css/panels/hookui.css",
52
+ "bin/webui/css/panels/handoff.css",
53
+ "bin/webui/css/panels/challenge.css",
54
+ "bin/webui/css/panels/docs.css",
55
+ "bin/webui/css/panels/extra.css",
56
+ "bin/webui/css/panels/test.css",
57
+ "bin/webui/css/panels/experiment.css",
58
+ // The client modules (v0.48.1). The <script> order in app.html is the load
59
+ // order and the numeric prefix is that order; 99-boot.js must be last.
60
+ "bin/webui/js/00-core.js",
61
+ "bin/webui/js/01-i18n.js",
62
+ "bin/webui/js/02-ui.js",
63
+ "bin/webui/js/03-md.js",
64
+ "bin/webui/js/04-router.js",
65
+ "bin/webui/js/05-banners.js",
66
+ "bin/webui/js/06-edit.js",
67
+ "bin/webui/js/panels/overview.js",
68
+ "bin/webui/js/panels/settings.js",
69
+ "bin/webui/js/panels/lanes.js",
70
+ "bin/webui/js/panels/rules.js",
71
+ "bin/webui/js/panels/runs.js",
72
+ "bin/webui/js/panels/knowledge.js",
73
+ "bin/webui/js/panels/stats.js",
74
+ "bin/webui/js/panels/flow.js",
75
+ "bin/webui/js/panels/crosslink.js",
76
+ "bin/webui/js/panels/learn.js",
77
+ "bin/webui/js/panels/mockrun.js",
78
+ "bin/webui/js/panels/experiment.js",
79
+ "bin/webui/js/panels/maintenance.js",
80
+ "bin/webui/js/panels/pact.js",
81
+ "bin/webui/js/panels/boundary.js",
82
+ "bin/webui/js/panels/wait.js",
83
+ "bin/webui/js/panels/hookui.js",
84
+ "bin/webui/js/panels/handoff.js",
85
+ "bin/webui/js/panels/challenge.js",
86
+ "bin/webui/js/panels/docs.js",
87
+ "bin/webui/js/panels/extra.js",
88
+ "bin/webui/js/panels/test.js",
89
+ "bin/webui/js/90-tour.js",
90
+ "bin/webui/js/91-shortcuts.js",
91
+ "bin/webui/js/99-boot.js",
92
+ // The canned data (v0.48.1), one file per panel. index.js is the ROUTER;
93
+ // every other file is data. --fixtures must carry ONE OF EVERY STATE.
94
+ "bin/webui/fixtures/index.js",
95
+ "bin/webui/fixtures/shell.js",
96
+ "bin/webui/fixtures/settings.js",
97
+ "bin/webui/fixtures/lanes.js",
98
+ "bin/webui/fixtures/rules.js",
99
+ "bin/webui/fixtures/wiki-one.js",
100
+ "bin/webui/fixtures/knowledge.js",
101
+ "bin/webui/fixtures/runs.js",
102
+ "bin/webui/fixtures/stats.js",
103
+ "bin/webui/fixtures/pact.js",
104
+ "bin/webui/fixtures/boundary.js",
105
+ "bin/webui/fixtures/wait.js",
106
+ "bin/webui/fixtures/hookui.js",
107
+ "bin/webui/fixtures/handoff.js",
108
+ "bin/webui/fixtures/maintenance.js",
109
+ "bin/webui/fixtures/challenge.js",
110
+ "bin/webui/fixtures/docs.js",
111
+ "bin/webui/fixtures/flow.js",
112
+ "bin/webui/fixtures/crosslink.js",
113
+ "bin/webui/fixtures/mockrun.js",
114
+ "bin/webui/fixtures/extra.js",
115
+ "bin/webui/fixtures/test.js",
116
+ // The string tables (v0.43.6). Named here for the same reason: English is the
117
+ // FALLBACK table every other language falls back to, so a publish that drops
118
+ // it renders raw dotted keys on every panel, in every language.
119
+ // v0.52.0 - the TERM LIST. It is not a string table and is never fetched by
120
+ // the page; it is the one page that keeps the next two hundred strings
121
+ // consistent, and without it a wording pass drifts back within two releases.
122
+ "bin/webui/i18n/TERMS.md",
123
+ "bin/webui/i18n/en/common.json",
124
+ "bin/webui/i18n/en/nav.json",
125
+ "bin/webui/i18n/en/banner.json",
126
+ "bin/webui/i18n/en/overview.json",
127
+ "bin/webui/i18n/en/settings.json",
128
+ "bin/webui/i18n/en/lanes.json",
129
+ "bin/webui/i18n/en/rules.json",
130
+ "bin/webui/i18n/en/runs.json",
131
+ "bin/webui/i18n/en/knowledge.json",
132
+ "bin/webui/i18n/en/stats.json",
133
+ "bin/webui/i18n/en/flow.json",
134
+ "bin/webui/i18n/en/crosslink.json",
135
+ "bin/webui/i18n/en/learn.json",
136
+ "bin/webui/i18n/en/mockrun.json",
137
+ "bin/webui/i18n/en/maintenance.json",
138
+ "bin/webui/i18n/en/pact.json",
139
+ "bin/webui/i18n/en/boundary.json",
140
+ "bin/webui/i18n/en/wait.json",
141
+ "bin/webui/i18n/en/hookui.json",
142
+ "bin/webui/i18n/en/handoff.json",
143
+ "bin/webui/i18n/en/challenge.json",
144
+ "bin/webui/i18n/en/docs.json",
145
+ "bin/webui/i18n/en/extra.json",
146
+ "bin/webui/i18n/en/test.json",
147
+ "bin/webui/i18n/en/experiment.json",
148
+ "bin/webui/i18n/en/tour.json",
149
+ "bin/webui/i18n/id/common.json",
150
+ "bin/webui/i18n/id/nav.json",
151
+ "bin/webui/i18n/id/banner.json",
152
+ "bin/webui/i18n/id/overview.json",
153
+ "bin/webui/i18n/id/settings.json",
154
+ "bin/webui/i18n/id/lanes.json",
155
+ "bin/webui/i18n/id/rules.json",
156
+ "bin/webui/i18n/id/runs.json",
157
+ "bin/webui/i18n/id/knowledge.json",
158
+ "bin/webui/i18n/id/stats.json",
159
+ "bin/webui/i18n/id/flow.json",
160
+ "bin/webui/i18n/id/crosslink.json",
161
+ "bin/webui/i18n/id/learn.json",
162
+ "bin/webui/i18n/id/mockrun.json",
163
+ "bin/webui/i18n/id/maintenance.json",
164
+ "bin/webui/i18n/id/pact.json",
165
+ "bin/webui/i18n/id/boundary.json",
166
+ "bin/webui/i18n/id/wait.json",
167
+ "bin/webui/i18n/id/hookui.json",
168
+ "bin/webui/i18n/id/handoff.json",
169
+ "bin/webui/i18n/id/challenge.json",
170
+ "bin/webui/i18n/id/docs.json",
171
+ "bin/webui/i18n/id/extra.json",
172
+ "bin/webui/i18n/id/test.json",
173
+ "bin/webui/i18n/id/experiment.json",
174
+ "bin/webui/i18n/id/tour.json",
175
+ // The mocked runs (v0.46.x): the catalogue module plus the folder it reads.
176
+ // Both `orc mock-run` and the panel's Mocked Skill Use page are empty without
177
+ // them, and an empty catalogue looks like a broken feature rather than a
178
+ // publish that dropped a folder.
179
+ "bin/mockrun-catalog.js",
180
+ // The code graph engine (v1.8.0). `orc graph` requires it at call time, so a
181
+ // publish that drops it breaks only that command — silently, until a lane asks.
182
+ "bin/graph.js",
183
+ "bin/graph-extract.js",
184
+ "bin/graph-query.js",
185
+ "bin/graph-resolve.js",
186
+ "bin/graph-signals.js",
187
+ "bin/graph-notes.js",
188
+ // The two DATED data files (v0.50.0). Both ship inside the package and both
189
+ // are load-bearing on absence rather than on content: without the catalog
190
+ // `orc extra providers` is a packaging bug it reports as one, and without the
191
+ // price table every `usd` reads as an em dash forever. They are named here for
192
+ // the same reason every webui file is — a publish that drops one serves a
193
+ // feature that looks broken rather than missing.
194
+ "bin/providers.json",
195
+ "bin/pricing.json",
196
+ "mock-run",
197
+ "mock-run/INDEX.md",
198
+ "templates",
199
+ "templates/skills/orc/SKILL.md",
200
+ "templates/skills/orc/references/ultra-mode.md",
201
+ "templates/skills/orc-advisor/SKILL.md",
202
+ "templates/skills/orc-judge/SKILL.md",
203
+ "templates/skills/orc-fast/SKILL.md",
204
+ "templates/skills/orc-claude/SKILL.md",
205
+ "templates/skills/orc-claude/references/template.md",
206
+ "templates/skills/orc-claude/references/refresh.md",
207
+ "templates/skills/orc-wiki/references/staleness.md",
208
+ "templates/skills/orc-learn/SKILL.md",
209
+ "templates/skills/orc-learn/references/refresh.md",
210
+ "templates/skills/orc-poly/SKILL.md",
211
+ "templates/skills/orc-poly/references/poly-spec.md",
212
+ "templates/skills/orc-poly/references/gather.md",
213
+ // Stacked pull requests (v0.37.0) — two standalone lanes plus the three
214
+ // canonical shared contracts they and ORC's ship gate all read. A missing
215
+ // shared file makes the ship gate hand off to a lane that cannot preflight.
216
+ "templates/skills/orc-pr-setup/SKILL.md",
217
+ "templates/skills/orc-pr-setup/README.md",
218
+ "templates/skills/orc-pr-setup/references/layer-taxonomy.md",
219
+ "templates/skills/orc-pr-setup/references/certainty-gate.md",
220
+ "templates/skills/orc-pr-driver/SKILL.md",
221
+ "templates/skills/orc-pr-driver/README.md",
222
+ "templates/skills/orc-pr-driver/references/green-gate.md",
223
+ "templates/skills/orc-pr-driver/references/orc-run-split.md",
224
+ "templates/skills/orc-pr-driver/references/conflict-playbook.md",
225
+ "templates/skills/_shared/stack-plan.md",
226
+ "templates/skills/_shared/gh-stack-commands.md",
227
+ "templates/skills/_shared/pr-templates.md",
228
+ "templates/skills/orc/subskills/orc-pr/stack-gate.md",
229
+ "templates/skills/orc-diy/SKILL.md",
230
+ "templates/skills/orc-diy/README.md",
231
+ "templates/skills/orc-diy/references/compile.md",
232
+ "templates/skills/orc-diy/references/flow-schema.md",
233
+ "templates/skills/orc-diy/references/locked-blocks.md",
234
+ "templates/skills/orc-diy/references/blocks/header.md",
235
+ "templates/skills/orc-quick/SKILL.md",
236
+ "templates/skills/orc-quick/README.md",
237
+ "templates/skills/orc-quick/references/context-doc.md",
238
+ "templates/skills/orc-quick/references/dispatch-gate.md",
239
+ "templates/skills/orc-quick/references/gh-mode.md",
240
+ // Quality-of-life lanes (v0.42.0). Three skills, ZERO new agents — the grill
241
+ // dispatches read-only recon ad-hoc (the orc-quick precedent) and the other
242
+ // two dispatch nothing at all. `_shared/interview.md` is the canonical
243
+ // mechanic both the grill and intake.md run; a missing copy of it makes the
244
+ // grill a lane with no procedure.
245
+ "templates/skills/_shared/interview.md",
246
+ "templates/skills/orc-grill/SKILL.md",
247
+ "templates/skills/orc-grill/references/grill-doc.md",
248
+ // v0.45.0 — /orc-brainstorm, again with ZERO new agents. `lane-suspend.md` is
249
+ // the RETURN-TO contract BOTH halves of the brainstorm↔grill trip read: a
250
+ // publish missing it leaves a lane that suspends into another lane with no
251
+ // definition of how (or whether) it comes back. `lenses.md` is the only place
252
+ // ORC generates options on purpose — without it B2 is a mood, not a phase.
253
+ "templates/skills/_shared/lane-suspend.md",
254
+ "templates/skills/orc-brainstorm/SKILL.md",
255
+ "templates/skills/orc-brainstorm/references/brainstorm-doc.md",
256
+ "templates/skills/orc-brainstorm/references/lenses.md",
257
+ "templates/commands/orc-brainstorm.md",
258
+ // v0.46.0 — the six new lanes. Named file by file for the same reason the
259
+ // panel's files are: each SKILL.md is useless without its references (a lane
260
+ // whose card/ledger/surface shape is missing dispatches against a contract it
261
+ // cannot read), and the two CONSUMER gate files are what /orc loads at Phase 1
262
+ // — a publish that drops one leaves the spine pointing at nothing.
263
+ "templates/skills/orc-pact/SKILL.md",
264
+ "templates/skills/orc-pact/references/ledger.md",
265
+ "templates/skills/orc-pact/references/gate.md",
266
+ "templates/skills/orc-boundary/SKILL.md",
267
+ "templates/skills/orc-boundary/references/card.md",
268
+ "templates/skills/orc-boundary/references/gate.md",
269
+ "templates/skills/orc-handoff/SKILL.md",
270
+ "templates/skills/orc-handoff/references/surfaces.md",
271
+ "templates/skills/orc-handoff/references/handoff-log.md",
272
+ "templates/skills/orc-budget/SKILL.md",
273
+ "templates/skills/orc-budget/references/corpus.md",
274
+ "templates/skills/orc-aftermath/SKILL.md",
275
+ "templates/skills/orc-aftermath/references/report.md",
276
+ "templates/skills/orc-export/SKILL.md",
277
+ // W1 — the partial-refresh reference is the whole tier ladder + the budget cap
278
+ // + the retirement offer; without it orc-wiki's spine points at a missing file
279
+ // at exactly the moment it has to choose which scanner to dispatch.
280
+ "templates/skills/orc-wiki/references/partial-refresh.md",
281
+ // v0.47.0 — /orc-challenge. Named file by file for the reason every lane's
282
+ // files are: the SKILL.md is a spine and its references ARE the contract. A
283
+ // publish that drops `sealed-slice.md` ships a judge whose slice has no
284
+ // definition, which is the one thing this lane exists to prevent; a publish
285
+ // that drops `intake.md` ships a lane with no goal contract, so rule 0 becomes
286
+ // a sentence nobody can act on.
287
+ "templates/skills/orc-challenge/SKILL.md",
288
+ "templates/skills/orc-challenge/README.md",
289
+ "templates/skills/orc-challenge/references/intake.md",
290
+ "templates/skills/orc-challenge/references/dimensions.md",
291
+ "templates/skills/orc-challenge/references/kinds.md",
292
+ "templates/skills/orc-challenge/references/rubric.md",
293
+ "templates/skills/orc-challenge/references/sealed-slice.md",
294
+ "templates/skills/orc-challenge/references/cycle-state.md",
295
+ "templates/skills/orc-challenge/references/verdict-doc.md",
296
+ "templates/skills/orc-challenge/references/fix-brief.md",
297
+ "templates/skills/orc-challenge/references/plain-english.md",
298
+ "templates/skills/orc-challenge/references/conservation.md",
299
+ // v0.49.1 — the council's canonical prose. The spine keeps the token and a
300
+ // pointer; this file is the one copy (the `_shared/` discipline).
301
+ "templates/skills/orc-challenge/references/council.md",
302
+ "templates/skills/orc-challenge/examples/council-full-roster.md",
303
+ // v0.48.0 — /orc-doc. Named file by file for the reason every lane's files
304
+ // are: `chunking.md` IS the token architecture (a publish that drops it ships
305
+ // an orchestrator with no definition of what it may hold, which is the one
306
+ // thing this lane exists to bound), `resume-protocol.md` is the whole reason
307
+ // the context is frozen, and `templates/` is the five base skeletons the
308
+ // batching table is pinned to by a golden test.
309
+ "templates/skills/orc-doc/SKILL.md",
310
+ "templates/skills/orc-doc/README.md",
311
+ "templates/skills/orc-doc/references/gates.md",
312
+ "templates/skills/orc-doc/references/chunking.md",
313
+ "templates/skills/orc-doc/references/resume-protocol.md",
314
+ "templates/skills/orc-doc/references/portable-markdown.md",
315
+ "templates/skills/orc-doc/references/plain-language.md",
316
+ "templates/skills/orc-doc/references/import-targets.md",
317
+ // v0.49.2 — the project's own house rules, and ORC's own generation rules.
318
+ // Two files because they are read in that ORDER and the order is the contract.
319
+ "templates/skills/orc-doc/references/house-rules.md",
320
+ "templates/skills/orc-doc/references/generation-rules.md",
321
+ "templates/skills/orc-doc/references/templates/prd.md",
322
+ "templates/skills/orc-doc/references/templates/tsd.md",
323
+ "templates/skills/orc-doc/references/templates/collaboration.md",
324
+ "templates/skills/orc-doc/references/templates/report.md",
325
+ "templates/skills/orc-doc/references/templates/workflow.md",
326
+ "templates/commands/orc-doc.md",
327
+ "templates/commands/orc-challenge.md",
328
+ "templates/commands/orc-pact.md",
329
+ "templates/commands/orc-boundary.md",
330
+ "templates/commands/orc-handoff.md",
331
+ "templates/commands/orc-budget.md",
332
+ "templates/commands/orc-aftermath.md",
333
+ "templates/commands/orc-export.md",
334
+ "templates/skills/orc-route/SKILL.md",
335
+ "templates/skills/orc-explain/SKILL.md",
336
+ "templates/skills/orc-analyze/references/thin-input.md",
337
+ // v1.0.0 W7 — the ONE config doc. `orc/config.md` stopped restating 72 key
338
+ // defaults and now points here for the ranks, the families, the gates, the
339
+ // `announce[]` boundary and the CLI-absent floor. A publish missing this file
340
+ // leaves every lane's `## Config` section pointing at nothing — and the
341
+ // fallback that is supposed to fire when the CLI cannot answer is exactly the
342
+ // moment there is no CLI to ask instead.
343
+ "templates/skills/_shared/config-precedence.md",
344
+ // v1.0.0 W11 — the phase library. The shared phase material already existed
345
+ // and was already shared; it just lived in ONE lane's private folder with 26
346
+ // other lanes reaching across into it. A publish missing any of these leaves
347
+ // every one of those lanes pointing at nothing — and `trace.md` in particular
348
+ // is the file that says how a run records itself, so its absence is silent by
349
+ // construction. README.md carries the CLOSED layer set, which is what stops a
350
+ // trimmed lane reading a full-lane procedure.
351
+ "templates/skills/_shared/phases/README.md",
352
+ "templates/skills/_shared/phases/trace.md",
353
+ "templates/skills/_shared/phases/preflight.md",
354
+ "templates/skills/_shared/phases/stop-resume.md",
355
+ // v1.0.0 W12 — the seven files that were already SHARED while living in one
356
+ // lane's private `references/`. Their consumers are measured, not believed:
357
+ // the C.6 lint asserts every declared reader really points at the file.
358
+ "templates/skills/_shared/phases/intake.md",
359
+ "templates/skills/_shared/phases/plan-handoff.md",
360
+ "templates/skills/_shared/phases/wave-grouping.md",
361
+ "templates/skills/_shared/phases/analyst-gates.md",
362
+ "templates/skills/_shared/phases/wiki-consult.md",
363
+ "templates/skills/_shared/phases/security-checklist.md",
364
+ "templates/skills/_shared/phases/house-rules.md",
365
+ // v1.0.0 W13 — the ten build phases orc-diy became the second reader of.
366
+ // Each carries TWO layers: `full` (/orc's procedure) and `composed` (what
367
+ // `orc diy compile` stitches). A publish missing one breaks BOTH lanes, and
368
+ // breaks orc-diy loudly — the compiler names the file and refuses.
369
+ "templates/skills/_shared/phases/planning.md",
370
+ "templates/skills/_shared/phases/scoring.md",
371
+ "templates/skills/_shared/phases/execution.md",
372
+ "templates/skills/_shared/phases/review.md",
373
+ "templates/skills/_shared/phases/security.md",
374
+ "templates/skills/_shared/phases/verify.md",
375
+ "templates/skills/_shared/phases/testgen.md",
376
+ "templates/skills/_shared/phases/mock-example.md",
377
+ "templates/skills/_shared/phases/summary.md",
378
+ "templates/skills/_shared/phases/ship.md",
379
+ // v1.0.0 W12 — /orc's own phase bodies, W13 — down to the two nothing else
380
+ // runs. The spine is loaded IN FULL on activation and these are loaded when
381
+ // their phase fires; a publish missing one leaves the manifest naming a file
382
+ // that is not there, which is a phase that silently does nothing.
383
+ "templates/skills/orc/references/phases/intake.md",
384
+ "templates/skills/orc/references/phases/integration.md",
385
+ // v1.0.0 W14 — orc-wiki's five phase bodies. A wiki run reaches FEW of them
386
+ // (Phase 0 auto-branches into fresh / resume / refresh / repair, 3c is a legacy
387
+ // backfill), which is what makes a file per phase pay here and not elsewhere.
388
+ // A publish missing one leaves the manifest naming a file that is not there.
389
+ "templates/skills/orc-wiki/references/phases/phase-0.md",
390
+ "templates/skills/orc-wiki/references/phases/phase-1.md",
391
+ "templates/skills/orc-wiki/references/phases/phase-2.md",
392
+ "templates/skills/orc-wiki/references/phases/phase-3.md",
393
+ "templates/skills/orc-wiki/references/phases/phase-3c.md",
394
+ "templates/commands/orc-grill.md",
395
+ "templates/commands/orc-route.md",
396
+ "templates/commands/orc-explain.md",
397
+ "templates/commands/orc.md",
398
+ "templates/commands/orc-quick.md",
399
+ "templates/commands/orc-diy.md",
400
+ "templates/commands/orc-ultra.md",
401
+ "templates/commands/orc-fast.md",
402
+ "templates/commands/orc-claude.md",
403
+ "templates/commands/orc-learn.md",
404
+ "templates/commands/orc-poly.md",
405
+ "templates/commands/orc-pr-setup.md",
406
+ "templates/commands/orc-pr-driver.md",
407
+ "templates/agents/MODEL-MAPPING.md",
408
+ "templates/agents/orc-advisor-opus-5-xhigh.md",
409
+ "templates/agents/orc-judge-opus-5-xhigh.md",
410
+ "templates/agents/orc-claude-writer-opus-4-8-high.md",
411
+ "templates/agents/orc-learn-writer-opus-5-low.md",
412
+ "templates/agents/orc-trace-writer-haiku-4-5.md",
413
+ // v1.8.0 — the code graph's notes writer (Layer 2).
414
+ "templates/agents/orc-graph-noter-sonnet-4-6-med.md",
415
+ // Core non-generated agents — named explicitly so a dropped file is REPORTED
416
+ // by name, not merely absorbed by the count floor. (The 8 executor agents are
417
+ // checked separately by `build-agents.js --check`.)
418
+ "templates/agents/orc-system-analyst-opus-5-high.md",
419
+ "templates/agents/orc-planner-opus-5-med.md",
420
+ "templates/agents/orc-reviewer-opus-5-med.md",
421
+ "templates/agents/orc-verifier-opus-5-med.md",
422
+ "templates/agents/orc-scout-sonnet-4-6-high.md",
423
+ "templates/agents/orc-test-author-opus-5-med.md",
424
+ "templates/agents/orc-pattern-codifier-sonnet-5-high.md",
425
+ "templates/agents/orc-retro-sonnet-5-high.md",
426
+ "templates/agents/orc-wiki-scanner-opus-4-8-high.md",
427
+ // v0.46.0 — the LIGHT half of the wiki scan tier ladder. Both halves must ship:
428
+ // the ladder resolves at dispatch time, so a missing light scanner makes every
429
+ // small-delta refresh dispatch a nonexistent agent.
430
+ "templates/agents/orc-wiki-scanner-sonnet-5-high.md",
431
+ "templates/agents/orc-context-combiner-opus-5-high.md",
432
+ // The orc-mini lane's agent pair and the whole Fable 5 role-override feature
433
+ // were guarded by nothing but the count floor — a publish missing any of them
434
+ // ships a lane that dispatches a nonexistent agent.
435
+ "templates/agents/orc-analyze-mini-sonnet-5-high.md",
436
+ "templates/agents/orc-planner-mini-sonnet-5-high.md",
437
+ // The Opus-5-only mode roster (v0.36.0). Both halves of every pair must ship:
438
+ // the mode is a runtime toggle, so a missing variant makes `opus5_only: true`
439
+ // dispatch a nonexistent agent for that role.
440
+ "templates/agents/orc-analyze-mini-opus-5-med.md",
441
+ "templates/agents/orc-planner-mini-opus-5-med.md",
442
+ "templates/agents/orc-scout-opus-5-low.md",
443
+ "templates/agents/orc-pattern-codifier-opus-5-med.md",
444
+ "templates/agents/orc-wiki-scanner-opus-5-med.md",
445
+ "templates/agents/orc-claude-writer-opus-5-med.md",
446
+ "templates/agents/orc-retro-opus-5-med.md",
447
+ // v0.47.0 — the three /orc-challenge agents. All THREE must ship: a cycle that
448
+ // cannot dispatch the reader silently loses D4, and one that cannot dispatch
449
+ // the advisor turns a FAIL into a list with no order. All three are already
450
+ // Opus 5, so `opus5_only` needs no twin for any of them.
451
+ "templates/agents/orc-challenge-judge-opus-5-high.md",
452
+ "templates/agents/orc-challenge-advisor-opus-5-med.md",
453
+ "templates/agents/orc-challenge-reader-opus-5-low.md",
454
+ // v0.49.1 — THE COUNCIL. Five DIFFERENT INSTRUMENTS, not five tiers of one:
455
+ // the contrarian assumes a fatal flaw, the outsider knows nothing and may not
456
+ // be told, the council executor asks what you do Monday morning, the
457
+ // first-principles thinker disputes the goal itself, and the expansionist is
458
+ // the only lens not looking for a defect. All five must ship: a roster lens
459
+ // that cannot be dispatched is a NOT-RUN row a user paid to select, and rule
460
+ // 15 makes that loud rather than silent. All five are claude-opus-5, so
461
+ // `opus5_only` adds NO pair and the floor moves by exactly five.
462
+ "templates/agents/orc-challenge-contrarian-opus-5-high.md",
463
+ "templates/agents/orc-challenge-outsider-opus-5-low.md",
464
+ "templates/agents/orc-challenge-executor-opus-5-med.md",
465
+ "templates/agents/orc-challenge-principles-opus-5-high.md",
466
+ "templates/agents/orc-challenge-expansionist-opus-5-med.md",
467
+ // v0.48.0 — the two /orc-doc agents. BOTH must ship: a write wave that cannot
468
+ // dispatch the writer has nothing to assemble, and a check wave that cannot
469
+ // dispatch the checker silently turns the only judgment step into the free
470
+ // lint. Both are already Opus 5, so `opus5_only` adds no twin for either.
471
+ "templates/agents/orc-doc-writer-opus-5-med.md",
472
+ "templates/agents/orc-doc-checker-opus-5-low.md",
473
+ // v1.5.0 - /orc-test's two agents, and they are two INSTRUMENTS rather than
474
+ // two tiers of one. The designer is `high` because the cheap answer to
475
+ // "design some test cases" is the list the CLI already derived for free; the
476
+ // interpreter is `low` because a harder-thinking interpreter reasons its way
477
+ // to why a leaked stack trace is probably fine in staging, which is exactly
478
+ // the gap it exists to find. Nothing may ever upgrade the interpreter. Both
479
+ // are claude-opus-5, so `opus5_only` adds NO pair and the floor moves by two.
480
+ "templates/agents/orc-test-designer-opus-5-high.md",
481
+ "templates/agents/orc-test-interpreter-opus-5-low.md",
482
+ // v1.2.1 — the status line explained for the person reading it, in
483
+ // Simplified Technical English. It ships INTO .claude/hooks/ next to the hook
484
+ // it describes, because that is where somebody looking at a segment they do
485
+ // not recognise will look for it.
486
+ "templates/hooks/README.md",
487
+ "templates/hooks/orc-effort-guard.js",
488
+ "templates/hooks/orc-statusline.js",
489
+ // v1.3.0 — THE RENDER ENGINE, and it is required by BOTH halves: the hook
490
+ // requires it as a sibling out of .claude/hooks/, and bin/cli.js requires it
491
+ // out of templates/hooks/ for `orc statusline preview`. That is what makes
492
+ // the panel's preview and the bar's real output byte-identical BY
493
+ // CONSTRUCTION. A missing file here breaks the status line AND the panel.
494
+ "templates/hooks/orc-statusline-render.js",
495
+ // v1.4.0 — the SECOND board, and the per-agent token record that rides with
496
+ // it. Wired even with the board off, because the measurement is handed over
497
+ // either way.
498
+ "templates/hooks/orc-subagent-line.js",
499
+ // v1.6.0 — the read gate. The one layer that can refuse an oversized read by
500
+ // the ORCHESTRATOR. Ships wired but OFF; `read_gate` arms it.
501
+ "templates/hooks/orc-read-gate.js",
502
+ "templates/hooks/orc-trace.js",
503
+ ];
504
+
505
+ const missing = [];
506
+ for (const rel of required) {
507
+ if (!fs.existsSync(path.join(ROOT, rel))) missing.push(rel);
508
+ }
509
+
510
+ // Every skill dir must contain at least one SKILL.md; every agent file must be non-empty.
511
+ function walkCount(dir, ext) {
512
+ let n = 0;
513
+ if (!fs.existsSync(dir)) return 0;
514
+ for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
515
+ const p = path.join(dir, e.name);
516
+ if (e.isDirectory()) n += walkCount(p, ext);
517
+ else if (e.name.endsWith(ext)) n += 1;
518
+ }
519
+ return n;
520
+ }
521
+
522
+ const skillCount = walkCount(path.join(ROOT, "templates/skills"), "SKILL.md");
523
+ const agentCount = walkCount(path.join(ROOT, "templates/agents"), ".md");
524
+ // Floors sit AT current reality (26 skills / 40 agent files: 39 agents +
525
+ // MODEL-MAPPING.md — +7 fixed-role variants for the opus5_only mode) so a
526
+ // dropped file fails the count check instead of sliding
527
+ // into the slack an under-set floor grants. Raise them with the payload.
528
+ // v0.38.0: +1 skill (orc-quick) and NO new agent — the quick lane reuses
529
+ // shipped executors and dispatches read-only recon ad-hoc by model name.
530
+ // v0.42.0: +3 skills (orc-grill, orc-route, orc-explain) and still NO new
531
+ // agent — same precedent. The agent floor deliberately does NOT move: a QoL
532
+ // lane that needed a pinned agent would also need its opus5_only twin, a
533
+ // MODEL-MAPPING row and a golden test, which is why none of them has one.
534
+ // v0.45.0: +1 skill (orc-brainstorm) and STILL no new agent — its divergent
535
+ // generation is the orchestrator's own work and its recon is dispatched ad-hoc
536
+ // by model+effort, so the agent floor holds at 40.
537
+ // v0.46.0: +6 skills (orc-pact, orc-boundary, orc-handoff, orc-budget,
538
+ // orc-aftermath, orc-export) and +1 agent — and the split is the point. Five of
539
+ // the six lanes ship ZERO agents (the v0.38.0/v0.45.0 precedent: read-only recon
540
+ // is dispatched ad-hoc by model+effort, and three of them dispatch nothing at
541
+ // all because their work is deterministic CLI). The ONE new agent is the wiki
542
+ // scan ladder's LIGHT half, which is a real dispatch target with a real name and
543
+ // therefore earns a MODEL-MAPPING row, an explicit guard entry above, and a
544
+ // place in the opus5_only table's prose.
545
+ // v0.47.0: +1 skill (orc-challenge) and +3 agents — the first lane since v0.42.0
546
+ // to earn any, and it earns three because each is a DIFFERENT INSTRUMENT, not a
547
+ // tier of the same one. The reader is `low` on purpose (a harder-thinking reader
548
+ // papers over exactly the gaps D4 measures), the judge is `high` because D2 is
549
+ // the only dimension no computer can reach, and the advisor is `medium` because
550
+ // grouping findings is pattern work. All three are claude-opus-5, so `opus5_only`
551
+ // adds NO pair and the floor moves by exactly three.
552
+ // v0.48.0: +1 skill (orc-doc) and +2 agents. The split follows v0.47.0's rule —
553
+ // an agent exists when it is a DIFFERENT INSTRUMENT, not a tier of the same one.
554
+ // The writer holds one part file and never `document.md`; the checker holds one
555
+ // LINE RANGE and has `Read` only. The checker is `low` on purpose (a
556
+ // harder-thinking checker reasons its way past a gap a real reader would trip
557
+ // on — the challenge cold reader's reasoning), so nothing may upgrade it. Both
558
+ // are claude-opus-5, so `opus5_only` adds NO pair and the floor moves by two.
559
+ // v0.49.1: +0 skills and +5 agents — THE COUNCIL. Same rule as v0.47.0, applied
560
+ // five times: each of these is a DIFFERENT INSTRUMENT, not a tier of one. The
561
+ // outsider is `low` and the contrarian is `high` for the same class of reason
562
+ // the cold reader is `low` — effort here is a MEASUREMENT choice, not a cost
563
+ // one, and a key that let either be tuned would be a key that let the
564
+ // instrument be broken. All five are claude-opus-5, so `opus5_only` adds NO
565
+ // pair and the floor moves by exactly five.
566
+ // v1.0.0 W3: +0 skills and -5 agents — the Fable 5 role override is REMOVED.
567
+ // It is the first time this floor has ever gone DOWN, and the reason it may is
568
+ // that the five files are not a tier of anything: they were a whole second
569
+ // answer to "which model runs a role", competing with `opus5_only` for the same
570
+ // decision. Deleting them removes a rank from `fixed-role-model` rather than a
571
+ // capability from a lane. Fable 5 survives as a SESSION model (the effort guard
572
+ // and the statusline still clear it at medium) — that is a different question,
573
+ // and this wave does not touch it.
574
+ // v1.5.0: +1 skill (orc-test) and +2 agents - the designer and the interpreter.
575
+ // The lane's recon (T2's `unresolved[]`, T4's flow trace) is dispatched AD-HOC
576
+ // by model+effort and earns no agent, the v0.38.0/v0.45.0 precedent, and that
577
+ // limit is stated in the skill: no `SPAWN` line, so `/orc-retro` cannot
578
+ // aggregate it.
579
+ if (skillCount < 39) missing.push(`templates/skills (expected >=39 SKILL.md, found ${skillCount})`);
580
+ if (agentCount < 48) missing.push(`templates/agents (expected >=48 .md, found ${agentCount})`);
581
+
582
+ // B4 — encoding/mojibake guard. The OneDrive corruption rule becomes a gate:
583
+ // scan every shipped text file for the U+FFFD replacement char (invalid UTF-8
584
+ // decodes to it) and for a whitespace-flanked run of three-or-more question
585
+ // marks — the shape a mangled em/en-dash or curly quote collapses into (a
586
+ // space-flanked dash becoming space-Q-Q-Q-space). A genuine "What???" has no
587
+ // leading space, so it is not flagged.
588
+ const MOJIBAKE = /(^|\s)\?{3,}(\s|$)/;
589
+ // U+FFFD needle built from its code point so this scanner never flags its own source.
590
+ const REPL = String.fromCharCode(0xfffd);
591
+ function scanEncoding(dir, hits) {
592
+ if (!fs.existsSync(dir)) return;
593
+ const st = fs.statSync(dir);
594
+ if (st.isFile()) {
595
+ let text;
596
+ try {
597
+ text = fs.readFileSync(dir, "utf8");
598
+ } catch (_) {
599
+ return; // unreadable → not our concern here
600
+ }
601
+ const rel = path.relative(ROOT, dir).replace(/\\/g, "/");
602
+ // Reference U+FFFD via escape, never as a literal, so this scanner does not
603
+ // flag its own source.
604
+ if (text.includes(REPL)) hits.push(`${rel} (U+FFFD replacement char — corrupted bytes)`);
605
+ else if (MOJIBAKE.test(text)) hits.push(`${rel} (whitespace-flanked "???" — likely mangled dash/quote)`);
606
+ return;
607
+ }
608
+ for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
609
+ scanEncoding(path.join(dir, e.name), hits);
610
+ }
611
+ }
612
+ const encodingHits = [];
613
+ scanEncoding(path.join(ROOT, "package.json"), encodingHits);
614
+ scanEncoding(path.join(ROOT, "bin"), encodingHits);
615
+ scanEncoding(path.join(ROOT, "templates"), encodingHits);
616
+ for (const h of encodingHits) missing.push("encoding: " + h);
617
+
618
+ if (missing.length) {
619
+ console.error("\n❌ ORC package integrity check FAILED. Missing / incomplete:");
620
+ for (const m of missing) console.error(" - " + m);
621
+ console.error("\nDo NOT publish or push this tree. Likely cause: files were not");
622
+ console.error("committed (OneDrive sync can corrupt commits). Rebuild the repo");
623
+ console.error("OUTSIDE any cloud-synced folder, `git add -A`, verify, then push.\n");
624
+ process.exit(1);
625
+ }
626
+ console.log(`✅ ORC package OK — ${skillCount} skills, ${agentCount} agent files, cli present.`);