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