@azure-id/orc 0.56.1 → 1.0.0

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