@azure-id/orc 1.9.2 → 2.1.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 (228) hide show
  1. package/CHANGELOG.md +722 -0
  2. package/README-id.md +56 -42
  3. package/README.md +58 -41
  4. package/bin/build-agents.js +125 -29
  5. package/bin/clear-logs.js +620 -0
  6. package/bin/cli.js +1873 -180
  7. package/bin/fix.js +459 -0
  8. package/bin/gotcha-import.js +1081 -0
  9. package/bin/gotcha.js +1566 -0
  10. package/bin/graph-query.js +1 -1
  11. package/bin/graph.js +717 -717
  12. package/bin/habit.js +1538 -0
  13. package/bin/mockrun-catalog.js +284 -276
  14. package/bin/onboarding-content.js +2 -1
  15. package/bin/pricing.json +28 -21
  16. package/bin/run-undo.js +398 -0
  17. package/bin/trace-write.js +869 -0
  18. package/bin/verify-contracts.js +627 -100
  19. package/bin/verify-package.js +68 -10
  20. package/bin/webui/api.js +151 -6
  21. package/bin/webui/app.html +239 -232
  22. package/bin/webui/css/00-tokens.css +110 -92
  23. package/bin/webui/css/04-motion.css +87 -0
  24. package/bin/webui/css/06-responsive.css +203 -178
  25. package/bin/webui/css/panels/behaviour.css +205 -0
  26. package/bin/webui/css/panels/hookui.css +79 -0
  27. package/bin/webui/fixtures/behaviour.js +562 -0
  28. package/bin/webui/fixtures/extra.js +9 -9
  29. package/bin/webui/fixtures/flow.js +81 -81
  30. package/bin/webui/fixtures/hookui.js +506 -431
  31. package/bin/webui/fixtures/index.js +66 -3
  32. package/bin/webui/fixtures/knowledge.js +9 -3
  33. package/bin/webui/fixtures/maintenance.js +123 -42
  34. package/bin/webui/fixtures/rules.js +1007 -1002
  35. package/bin/webui/fixtures/settings.js +6 -7
  36. package/bin/webui/fixtures/stats.js +25 -6
  37. package/bin/webui/fixtures/wait.js +98 -97
  38. package/bin/webui/i18n/en/behaviour.json +156 -0
  39. package/bin/webui/i18n/en/hookui.json +290 -194
  40. package/bin/webui/i18n/en/maintenance.json +71 -52
  41. package/bin/webui/i18n/en/nav.json +25 -24
  42. package/bin/webui/i18n/en/settings.json +60 -60
  43. package/bin/webui/i18n/en/tour.json +37 -35
  44. package/bin/webui/i18n/id/behaviour.json +156 -0
  45. package/bin/webui/i18n/id/hookui.json +290 -194
  46. package/bin/webui/i18n/id/maintenance.json +71 -52
  47. package/bin/webui/i18n/id/nav.json +25 -24
  48. package/bin/webui/i18n/id/settings.json +60 -60
  49. package/bin/webui/i18n/id/tour.json +37 -35
  50. package/bin/webui/js/01-i18n.js +155 -154
  51. package/bin/webui/js/05-banners.js +181 -172
  52. package/bin/webui/js/06-edit.js +193 -183
  53. package/bin/webui/js/90-tour.js +498 -494
  54. package/bin/webui/js/91-shortcuts.js +126 -126
  55. package/bin/webui/js/99-boot.js +121 -118
  56. package/bin/webui/js/panels/behaviour.js +1087 -0
  57. package/bin/webui/js/panels/hookui.js +2196 -1691
  58. package/bin/webui/js/panels/maintenance.js +336 -235
  59. package/bin/webui/js/panels/settings.js +726 -719
  60. package/mock-run/INDEX.md +110 -107
  61. package/mock-run/extra-slots.md +1 -1
  62. package/mock-run/gotcha-import.md +118 -0
  63. package/mock-run/habits.md +129 -0
  64. package/mock-run/orc-aftermath.md +392 -392
  65. package/mock-run/orc-budget.md +29 -33
  66. package/mock-run/orc-cli.md +200 -200
  67. package/mock-run/orc-explain.md +86 -86
  68. package/mock-run/orc-extra.md +389 -392
  69. package/mock-run/orc-fix.md +87 -0
  70. package/mock-run/orc-pattern.md +112 -112
  71. package/mock-run/orc-quick.md +6 -1
  72. package/mock-run/orc.md +157 -157
  73. package/package.json +1 -1
  74. package/templates/agents/MODEL-MAPPING.md +37 -34
  75. package/templates/agents/orc-advisor-opus-5-xhigh.md +1 -7
  76. package/templates/agents/orc-analyze-mini-opus-5-med.md +1 -6
  77. package/templates/agents/orc-analyze-mini-sonnet-5-high.md +2 -5
  78. package/templates/agents/{orc-claude-writer-opus-4-8-high.md → orc-claude-writer-opus-5-low.md} +48 -53
  79. package/templates/agents/orc-context-combiner-opus-5-high.md +1 -11
  80. package/templates/agents/orc-executor-haiku-4-5.md +14 -6
  81. package/templates/agents/orc-executor-opus-4-7-high.md +14 -6
  82. package/templates/agents/orc-executor-opus-4-7-med.md +14 -6
  83. package/templates/agents/orc-executor-opus-4-8-high.md +14 -6
  84. package/templates/agents/orc-executor-opus-5-high.md +14 -6
  85. package/templates/agents/orc-executor-opus-5-low.md +14 -6
  86. package/templates/agents/orc-executor-opus-5-med.md +14 -6
  87. package/templates/agents/orc-executor-sonnet-4-6-high.md +14 -6
  88. package/templates/agents/orc-executor-sonnet-4-6-med.md +14 -6
  89. package/templates/agents/orc-executor-sonnet-5-high.md +15 -7
  90. package/templates/agents/orc-executor-sonnet-5-low.md +155 -0
  91. package/templates/agents/orc-executor-sonnet-5-med.md +155 -0
  92. package/templates/agents/orc-graph-noter-sonnet-4-6-med.md +1 -10
  93. package/templates/agents/orc-judge-opus-5-xhigh.md +5 -9
  94. package/templates/agents/orc-learn-writer-opus-5-low.md +1 -7
  95. package/templates/agents/orc-pattern-codifier-opus-5-med.md +1 -8
  96. package/templates/agents/orc-pattern-codifier-sonnet-5-high.md +58 -63
  97. package/templates/agents/orc-planner-mini-opus-5-med.md +1 -4
  98. package/templates/agents/orc-planner-mini-sonnet-5-high.md +2 -3
  99. package/templates/agents/orc-planner-opus-5-med.md +1 -4
  100. package/templates/agents/orc-recon-opus-5-low.md +1 -8
  101. package/templates/agents/orc-recon-sonnet-4-6-med.md +1 -8
  102. package/templates/agents/orc-retro-opus-5-med.md +6 -8
  103. package/templates/agents/orc-retro-sonnet-5-high.md +7 -8
  104. package/templates/agents/orc-reviewer-opus-5-low.md +96 -0
  105. package/templates/agents/orc-scout-opus-5-low.md +1 -6
  106. package/templates/agents/orc-scout-sonnet-4-6-high.md +35 -39
  107. package/templates/agents/orc-system-analyst-opus-5-high.md +1 -6
  108. package/templates/agents/orc-test-author-opus-5-med.md +4 -5
  109. package/templates/agents/orc-trace-writer-haiku-4-5.md +3 -7
  110. package/templates/agents/orc-verifier-opus-5-med.md +16 -8
  111. package/templates/agents/{orc-wiki-scanner-opus-4-8-high.md → orc-wiki-scanner-opus-5-low.md} +74 -79
  112. package/templates/agents/orc-wiki-scanner-sonnet-5-high.md +97 -106
  113. package/templates/commands/orc-analyze.md +13 -21
  114. package/templates/commands/orc-fast.md +10 -15
  115. package/templates/commands/orc-fix.md +18 -0
  116. package/templates/commands/orc-poly.md +12 -21
  117. package/templates/commands/orc-pr-driver.md +11 -30
  118. package/templates/commands/orc-pr-setup.md +10 -31
  119. package/templates/commands/orc-route.md +11 -41
  120. package/templates/commands/orc-test.md +5 -60
  121. package/templates/commands/orc-wiki.md +64 -64
  122. package/templates/hooks/README.md +109 -7
  123. package/templates/hooks/orc-session-hook.js +339 -0
  124. package/templates/hooks/orc-statusline-render.js +317 -23
  125. package/templates/hooks/orc-statusline.js +165 -50
  126. package/templates/hooks/orc-subagent-line.js +23 -5
  127. package/templates/hooks/orc-weather-fetch.js +123 -0
  128. package/templates/skills/_shared/README.md +9 -0
  129. package/templates/skills/_shared/code-graph.md +47 -55
  130. package/templates/skills/_shared/config-precedence.md +3 -1
  131. package/templates/skills/_shared/extra-dispatch.md +78 -93
  132. package/templates/skills/_shared/gotchas.md +248 -177
  133. package/templates/skills/_shared/habits.md +101 -0
  134. package/templates/skills/_shared/lane-contract.md +84 -0
  135. package/templates/skills/_shared/opus5-only.md +14 -14
  136. package/templates/skills/_shared/phases/README.md +142 -83
  137. package/templates/skills/_shared/phases/analyst-gates.md +10 -21
  138. package/templates/skills/_shared/phases/execution.md +8 -14
  139. package/templates/skills/_shared/phases/house-rules.md +27 -32
  140. package/templates/skills/_shared/phases/intake.md +127 -133
  141. package/templates/skills/_shared/phases/mock-example.md +46 -56
  142. package/templates/skills/_shared/phases/plan-handoff.md +91 -97
  143. package/templates/skills/_shared/phases/planning.md +7 -17
  144. package/templates/skills/_shared/phases/preflight.md +19 -42
  145. package/templates/skills/_shared/phases/review.md +24 -28
  146. package/templates/skills/_shared/phases/rules.md +18 -42
  147. package/templates/skills/_shared/phases/scoring.md +55 -65
  148. package/templates/skills/_shared/phases/security-checklist.md +46 -50
  149. package/templates/skills/_shared/phases/security.md +45 -55
  150. package/templates/skills/_shared/phases/ship.md +6 -15
  151. package/templates/skills/_shared/phases/stop-resume.md +2 -5
  152. package/templates/skills/_shared/phases/summary.md +73 -48
  153. package/templates/skills/_shared/phases/testgen.md +41 -51
  154. package/templates/skills/_shared/phases/trace-verbs.md +447 -0
  155. package/templates/skills/_shared/phases/trace.md +66 -297
  156. package/templates/skills/_shared/phases/verify.md +62 -70
  157. package/templates/skills/_shared/phases/wave-grouping.md +128 -133
  158. package/templates/skills/_shared/phases/wiki-consult.md +10 -6
  159. package/templates/skills/_shared/read-ladder.md +2 -55
  160. package/templates/skills/_shared/return-validation.md +17 -70
  161. package/templates/skills/_shared/review-slice.md +106 -0
  162. package/templates/skills/_shared/smoke-gate.md +46 -28
  163. package/templates/skills/_shared/wait.md +1 -0
  164. package/templates/skills/context-combiner/SKILL.md +15 -44
  165. package/templates/skills/orc/README.md +2 -2
  166. package/templates/skills/orc/SKILL.md +35 -63
  167. package/templates/skills/orc/config.md +25 -27
  168. package/templates/skills/orc/examples/full-run-mock.md +2 -1
  169. package/templates/skills/orc/references/effort-and-mode.md +17 -17
  170. package/templates/skills/orc/references/pattern-gate.md +89 -89
  171. package/templates/skills/orc/references/phases/intake.md +41 -47
  172. package/templates/skills/orc/references/phases/integration.md +13 -19
  173. package/templates/skills/orc/references/preflight-report.md +11 -12
  174. package/templates/skills/orc/references/ultra-mode.md +9 -7
  175. package/templates/skills/orc/schemas/checkpoint.md +122 -122
  176. package/templates/skills/orc/subskills/orc-execution/SKILL.md +27 -73
  177. package/templates/skills/orc/subskills/orc-execution/core.md +12 -99
  178. package/templates/skills/orc/subskills/orc-execution/subagent.md +14 -13
  179. package/templates/skills/orc/subskills/orc-review-verify/SKILL.md +12 -53
  180. package/templates/skills/orc/subskills/orc-review-verify/core.md +52 -135
  181. package/templates/skills/orc/subskills/orc-review-verify/subagent.md +7 -7
  182. package/templates/skills/orc/subskills/orc-testgen/SKILL.md +11 -22
  183. package/templates/skills/orc/subskills/orc-testgen/core.md +20 -59
  184. package/templates/skills/orc/subskills/orc-testgen/subagent.md +7 -7
  185. package/templates/skills/orc-advisor/SKILL.md +56 -60
  186. package/templates/skills/orc-analyze/SKILL.md +33 -67
  187. package/templates/skills/orc-analyze/schemas/report-audit.md +2 -1
  188. package/templates/skills/orc-analyze/schemas/report-prose.md +2 -1
  189. package/templates/skills/orc-analyze-mini/SKILL.md +35 -70
  190. package/templates/skills/orc-claude/SKILL.md +14 -14
  191. package/templates/skills/orc-claude/examples/claude-run-mock.md +65 -65
  192. package/templates/skills/orc-diy/README.md +31 -0
  193. package/templates/skills/orc-diy/SKILL.md +27 -78
  194. package/templates/skills/orc-diy/references/blocks/pattern.md +18 -18
  195. package/templates/skills/orc-fast/SKILL.md +49 -75
  196. package/templates/skills/orc-fix/SKILL.md +110 -0
  197. package/templates/skills/orc-judge/SKILL.md +77 -82
  198. package/templates/skills/orc-mini/SKILL.md +64 -112
  199. package/templates/skills/orc-mini/examples/mini-run-mock.md +4 -2
  200. package/templates/skills/orc-pattern/SKILL.md +27 -48
  201. package/templates/skills/orc-poly/SKILL.md +32 -61
  202. package/templates/skills/orc-pr-driver/SKILL.md +25 -51
  203. package/templates/skills/orc-pr-driver/references/green-gate.md +113 -105
  204. package/templates/skills/orc-pr-setup/SKILL.md +20 -45
  205. package/templates/skills/orc-quick/README.md +44 -3
  206. package/templates/skills/orc-quick/SKILL.md +77 -108
  207. package/templates/skills/orc-quick/references/dispatch-gate.md +18 -6
  208. package/templates/skills/orc-quick/references/gh-mode.md +50 -1
  209. package/templates/skills/orc-quick/references/look.md +3 -1
  210. package/templates/skills/orc-retro/SKILL.md +20 -19
  211. package/templates/skills/orc-retro/examples/retro-mock.md +17 -17
  212. package/templates/skills/orc-route/SKILL.md +25 -45
  213. package/templates/skills/orc-test/SKILL.md +16 -37
  214. package/templates/skills/orc-verify/SKILL.md +14 -32
  215. package/templates/skills/orc-wait/SKILL.md +156 -163
  216. package/templates/skills/orc-wiki/README.md +325 -325
  217. package/templates/skills/orc-wiki/SKILL.md +195 -195
  218. package/templates/skills/orc-wiki/examples/wiki-run-mock.md +37 -37
  219. package/templates/skills/orc-wiki/references/extra.md +2 -2
  220. package/templates/skills/orc-wiki/references/partial-refresh.md +276 -271
  221. package/templates/skills/orc-wiki/references/phases/phase-0.md +2 -7
  222. package/templates/skills/orc-wiki/references/phases/phase-1.md +1 -6
  223. package/templates/skills/orc-wiki/references/phases/phase-2.md +4 -9
  224. package/templates/skills/orc-wiki/references/phases/phase-3.md +1 -6
  225. package/templates/skills/orc-wiki/references/phases/phase-3c.md +4 -8
  226. package/templates/agents/orc-claude-writer-opus-5-med.md +0 -55
  227. package/templates/agents/orc-reviewer-opus-5-med.md +0 -60
  228. package/templates/agents/orc-wiki-scanner-opus-5-med.md +0 -81
@@ -46,6 +46,7 @@ const required = [
46
46
  "bin/webui/css/panels/mockrun.css",
47
47
  "bin/webui/css/panels/maintenance.css",
48
48
  "bin/webui/css/panels/pact.css",
49
+ "bin/webui/css/panels/behaviour.css",
49
50
  "bin/webui/css/panels/boundary.css",
50
51
  "bin/webui/css/panels/wait.css",
51
52
  "bin/webui/css/panels/hookui.css",
@@ -78,6 +79,7 @@ const required = [
78
79
  "bin/webui/js/panels/experiment.js",
79
80
  "bin/webui/js/panels/maintenance.js",
80
81
  "bin/webui/js/panels/pact.js",
82
+ "bin/webui/js/panels/behaviour.js",
81
83
  "bin/webui/js/panels/boundary.js",
82
84
  "bin/webui/js/panels/wait.js",
83
85
  "bin/webui/js/panels/hookui.js",
@@ -101,6 +103,7 @@ const required = [
101
103
  "bin/webui/fixtures/runs.js",
102
104
  "bin/webui/fixtures/stats.js",
103
105
  "bin/webui/fixtures/pact.js",
106
+ "bin/webui/fixtures/behaviour.js",
104
107
  "bin/webui/fixtures/boundary.js",
105
108
  "bin/webui/fixtures/wait.js",
106
109
  "bin/webui/fixtures/hookui.js",
@@ -136,6 +139,7 @@ const required = [
136
139
  "bin/webui/i18n/en/mockrun.json",
137
140
  "bin/webui/i18n/en/maintenance.json",
138
141
  "bin/webui/i18n/en/pact.json",
142
+ "bin/webui/i18n/en/behaviour.json",
139
143
  "bin/webui/i18n/en/boundary.json",
140
144
  "bin/webui/i18n/en/wait.json",
141
145
  "bin/webui/i18n/en/hookui.json",
@@ -162,6 +166,7 @@ const required = [
162
166
  "bin/webui/i18n/id/mockrun.json",
163
167
  "bin/webui/i18n/id/maintenance.json",
164
168
  "bin/webui/i18n/id/pact.json",
169
+ "bin/webui/i18n/id/behaviour.json",
165
170
  "bin/webui/i18n/id/boundary.json",
166
171
  "bin/webui/i18n/id/wait.json",
167
172
  "bin/webui/i18n/id/hookui.json",
@@ -202,6 +207,30 @@ const required = [
202
207
  // the only answer that says WHY a THIN map is thin. Without it the status
203
208
  // line still says THIN and names a command that is not there.
204
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",
205
234
 
206
235
  // The two DATED data files (v0.50.0). Both ship inside the package and both
207
236
  // are load-bearing on absence rather than on content: without the catalog
@@ -351,6 +380,7 @@ const required = [
351
380
  "templates/commands/orc-export.md",
352
381
  "templates/skills/orc-route/SKILL.md",
353
382
  "templates/skills/orc-explain/SKILL.md",
383
+ "templates/skills/orc-fix/SKILL.md",
354
384
  "templates/skills/orc-analyze/references/thin-input.md",
355
385
  // v1.0.0 W7 — the ONE config doc. `orc/config.md` stopped restating 72 key
356
386
  // defaults and now points here for the ranks, the families, the gates, the
@@ -368,6 +398,18 @@ const required = [
368
398
  // trimmed lane reading a full-lane procedure.
369
399
  "templates/skills/_shared/phases/README.md",
370
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",
371
413
  "templates/skills/_shared/phases/preflight.md",
372
414
  "templates/skills/_shared/phases/stop-resume.md",
373
415
  // v1.0.0 W12 — the seven files that were already SHARED while living in one
@@ -412,6 +454,7 @@ const required = [
412
454
  "templates/commands/orc-grill.md",
413
455
  "templates/commands/orc-route.md",
414
456
  "templates/commands/orc-explain.md",
457
+ "templates/commands/orc-fix.md",
415
458
  "templates/commands/orc.md",
416
459
  "templates/commands/orc-quick.md",
417
460
  "templates/commands/orc-diy.md",
@@ -425,17 +468,19 @@ const required = [
425
468
  "templates/agents/MODEL-MAPPING.md",
426
469
  "templates/agents/orc-advisor-opus-5-xhigh.md",
427
470
  "templates/agents/orc-judge-opus-5-xhigh.md",
428
- "templates/agents/orc-claude-writer-opus-4-8-high.md",
471
+ "templates/agents/orc-claude-writer-opus-5-low.md",
429
472
  "templates/agents/orc-learn-writer-opus-5-low.md",
430
473
  "templates/agents/orc-trace-writer-haiku-4-5.md",
431
474
  // v1.8.0 — the code graph's notes writer (Layer 2).
432
475
  "templates/agents/orc-graph-noter-sonnet-4-6-med.md",
433
476
  // Core non-generated agents — named explicitly so a dropped file is REPORTED
434
- // by name, not merely absorbed by the count floor. (The 8 executor agents are
435
- // checked separately by `build-agents.js --check`.)
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.)
436
481
  "templates/agents/orc-system-analyst-opus-5-high.md",
437
482
  "templates/agents/orc-planner-opus-5-med.md",
438
- "templates/agents/orc-reviewer-opus-5-med.md",
483
+ "templates/agents/orc-reviewer-opus-5-low.md",
439
484
  "templates/agents/orc-verifier-opus-5-med.md",
440
485
  "templates/agents/orc-scout-sonnet-4-6-high.md",
441
486
  // v1.9.0 — the /orc-quick recon pair. Both halves must ship: the gate offers
@@ -445,7 +490,7 @@ const required = [
445
490
  "templates/agents/orc-test-author-opus-5-med.md",
446
491
  "templates/agents/orc-pattern-codifier-sonnet-5-high.md",
447
492
  "templates/agents/orc-retro-sonnet-5-high.md",
448
- "templates/agents/orc-wiki-scanner-opus-4-8-high.md",
493
+ "templates/agents/orc-wiki-scanner-opus-5-low.md",
449
494
  // v0.46.0 — the LIGHT half of the wiki scan tier ladder. Both halves must ship:
450
495
  // the ladder resolves at dispatch time, so a missing light scanner makes every
451
496
  // small-delta refresh dispatch a nonexistent agent.
@@ -463,8 +508,6 @@ const required = [
463
508
  "templates/agents/orc-planner-mini-opus-5-med.md",
464
509
  "templates/agents/orc-scout-opus-5-low.md",
465
510
  "templates/agents/orc-pattern-codifier-opus-5-med.md",
466
- "templates/agents/orc-wiki-scanner-opus-5-med.md",
467
- "templates/agents/orc-claude-writer-opus-5-med.md",
468
511
  "templates/agents/orc-retro-opus-5-med.md",
469
512
  // v0.47.0 — the three /orc-challenge agents. All THREE must ship: a cycle that
470
513
  // cannot dispatch the reader silently loses D4, and one that cannot dispatch
@@ -514,6 +557,7 @@ const required = [
514
557
  // the panel's preview and the bar's real output byte-identical BY
515
558
  // CONSTRUCTION. A missing file here breaks the status line AND the panel.
516
559
  "templates/hooks/orc-statusline-render.js",
560
+ "templates/hooks/orc-weather-fetch.js",
517
561
  // v1.4.0 — the SECOND board, and the per-agent token record that rides with
518
562
  // it. Wired even with the board off, because the measurement is handed over
519
563
  // either way.
@@ -522,6 +566,9 @@ const required = [
522
566
  // the ORCHESTRATOR. Ships wired but OFF; `read_gate` arms it.
523
567
  "templates/hooks/orc-read-gate.js",
524
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",
525
572
  ];
526
573
 
527
574
  const missing = [];
@@ -608,7 +655,9 @@ const agentCount = walkCount(path.join(ROOT, "templates/agents"), ".md");
608
655
  // hatch survives on the menu as line 3 (model only). Both names earn an
609
656
  // explicit guard entry above and a MODEL-MAPPING row; `opus5_only` adds no
610
657
  // pair, because orc-quick is the lane that key is inert in.
611
- if (skillCount < 39) missing.push(`templates/skills (expected >=39 SKILL.md, found ${skillCount})`);
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})`);
612
661
  if (agentCount < 50) missing.push(`templates/agents (expected >=50 .md, found ${agentCount})`);
613
662
 
614
663
  // B4 — encoding/mojibake guard. The OneDrive corruption rule becomes a gate:
@@ -624,13 +673,22 @@ function scanEncoding(dir, hits) {
624
673
  if (!fs.existsSync(dir)) return;
625
674
  const st = fs.statSync(dir);
626
675
  if (st.isFile()) {
627
- let text;
676
+ let buf;
628
677
  try {
629
- text = fs.readFileSync(dir, "utf8");
678
+ buf = fs.readFileSync(dir);
630
679
  } catch (_) {
631
680
  return; // unreadable → not our concern here
632
681
  }
633
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");
634
692
  // Reference U+FFFD via escape, never as a literal, so this scanner does not
635
693
  // flag its own source.
636
694
  if (text.includes(REPL)) hits.push(`${rel} (U+FFFD replacement char — corrupted bytes)`);
package/bin/webui/api.js CHANGED
@@ -284,6 +284,9 @@ const READS = {
284
284
  // applies these to a copy of the saved layout before it compiles.
285
285
  if (q.theme) argv.push("--theme", String(q.theme));
286
286
  if (q.glyphs) argv.push("--glyphs", String(q.glyphs));
287
+ // v2.0.4 — an animated preview: N frames, M ms apart. Render-only.
288
+ if (q.frames) argv.push("--frames", String(q.frames));
289
+ if (q.frame_ms) argv.push("--frame-ms", String(q.frame_ms));
287
290
  return argv;
288
291
  },
289
292
  "/api/statusline/explain": (q) => ["statusline", "explain", String(q.at || "1:1"), ...slBoard(q)],
@@ -453,6 +456,22 @@ const READS = {
453
456
  "/api/test/ui": () => ["test", "ui", "tools"],
454
457
  "/api/patterns": () => ["pattern", "status"],
455
458
  "/api/gotchas": () => ["gotcha", "list"],
459
+ // v2.0.0 W7 — the Behaviour panel. Every one is a CLI read, and every exit
460
+ // code is DATA: `habit show` 0 · 1 no ASK lines yet · 3 `habits: off`;
461
+ // `habit log` 0 · 1 empty; `gotcha card` 0 · 1 no match (an ANSWER: no card);
462
+ // `gotcha quality` 0 · 1 below the 5-review floor. The window is DROPPED
463
+ // unless it is one of the three the CLI knows — a query string is user input.
464
+ "/api/habits": (q) => (["30d", "90d", "all"].includes(String(q.window || "")) ? ["habit", "show", "--window", String(q.window)] : ["habit", "show"]),
465
+ "/api/habits/log": () => ["habit", "log", "--limit", "40"],
466
+ "/api/habits/states": () => ["habit", "log", "--states"],
467
+ "/api/habits/points": () => ["habit", "points"],
468
+ "/api/gotcha/card": (q) => ["gotcha", "card", "--files", String(q.files || ""), "--full"],
469
+ // The panel window (30d · 90d · all) in the days `gotcha quality --window` takes.
470
+ "/api/gotcha/quality": (q) => {
471
+ const days = { "30d": "30", "90d": "90", all: "3650" }[String(q.window || "")];
472
+ return days ? ["gotcha", "quality", "--window", days] : ["gotcha", "quality"];
473
+ },
474
+ "/api/gotcha/candidates": () => ["gotcha", "list", "--candidates"],
456
475
  "/api/stats": (q) => (q.since ? ["stats", "--since", String(q.since)] : ["stats"]),
457
476
  "/api/diy": () => ["diy", "show"],
458
477
  "/api/crosslink": () => ["crosslink", "list"],
@@ -511,17 +530,41 @@ const WRITES = {
511
530
  ["width", "--width"], ["precision", "--precision"],
512
531
  ["min_width", "--min-width"], ["min_cols", "--min-cols"],
513
532
  ["max_cols", "--max-cols"], ["priority", "--priority"],
533
+ // v2.0.4 — the design fields. Same rule: absent sends nothing, "" clears.
534
+ ["label_pos", "--label-pos"], ["value_pos", "--value-pos"],
535
+ ["caption", "--caption"], ["caption_pos", "--caption-pos"],
536
+ ["caption_align", "--caption-align"], ["caption_color", "--caption-color"],
537
+ ["caption_case", "--caption-case"], ["fill_color", "--fill-color"],
538
+ ["empty_color", "--empty-color"], ["ramp_colors", "--ramp-colors"],
539
+ ["ramp_stops", "--ramp-stops"], ["fill_char", "--fill-char"],
540
+ ["empty_char", "--empty-char"], ["brackets", "--brackets"],
541
+ ["threshold", "--threshold"], ["pad_left", "--pad-left"],
542
+ ["pad_right", "--pad-right"], ["align", "--align"], ["sign", "--sign"],
543
+ ["max_len", "--max-len"], ["unknown", "--unknown"],
544
+ ["color_by_state", "--state-color"], ["glyph_by_state", "--state-glyph"],
514
545
  ]) {
515
- if (b[k] !== undefined && b[k] !== null && b[k] !== "") argv.push(f, String(b[k]));
546
+ // An absent key sends nothing; a PRESENT "" or null sends `<flag> ""`,
547
+ // which the CLI reads as "delete the key" (inherit). Dropping it made a
548
+ // clear "succeed" while it changed nothing.
549
+ if (b[k] === undefined) continue;
550
+ argv.push(f, b[k] === null ? "" : String(b[k]));
516
551
  }
517
552
  if (b.draw_empty) argv.push("--draw-empty");
553
+ // `params` is an OBJECT, one `--param k=v` per key. The CLI scans every
554
+ // `--param`, and `k=` (a null or "" value) deletes that key.
555
+ if (b.params && typeof b.params === "object")
556
+ for (const [k, v] of Object.entries(b.params)) argv.push("--param", String(k) + "=" + (v === null || v === undefined ? "" : String(v)));
518
557
  return argv.concat(slBoard(b));
519
558
  },
520
559
  "/api/statusline/move": (b) => ["statusline", "move", String(b.from), String(b.to), ...slBoard(b)],
521
560
  "/api/statusline/remove": (b) => ["statusline", "remove", String(b.at), ...slBoard(b)],
522
561
  "/api/statusline/line": (b) => {
523
562
  const argv = ["statusline", "line", String(b.line)];
524
- if (b.separator !== undefined) argv.push("--separator", String(b.separator));
563
+ // A PRESENT key is forwarded even when it is "" — that is the clear.
564
+ for (const [k, f] of [["separator", "--separator"], ["prefix", "--prefix"], ["align", "--align"], ["sep_color", "--sep-color"]]) {
565
+ if (b[k] === undefined) continue;
566
+ argv.push(f, b[k] === null ? "" : String(b[k]));
567
+ }
525
568
  if (b.theme) argv.push("--theme", String(b.theme));
526
569
  if (b.max_width !== undefined) argv.push("--max-width", String(b.max_width));
527
570
  return argv.concat(slBoard(b));
@@ -548,6 +591,8 @@ const WRITES = {
548
591
  "/api/statusline/clone": (b) => ["statusline", "clone", String(b.at), ...slBoard(b)],
549
592
  "/api/statusline/reset": (b) => ["statusline", "reset", ...slBoard(b)],
550
593
  "/api/statusline/compile": (b) => ["statusline", "compile", ...slBoard(b)],
594
+ // v2.0.4 — the redraw timer: a settings write, not a layout op.
595
+ "/api/statusline/refresh": (b) => ["statusline", "refresh", String(b.seconds), ...slBoard(b)],
551
596
  "/api/wait/unblock": (b) => (b.slug ? ["wait", "unblock", String(b.slug)] : ["wait", "unblock"]),
552
597
  "/api/wait/cancel": (b) => (b.slug ? ["wait", "cancel", String(b.slug)] : ["wait", "cancel"]),
553
598
  "/api/wiki/sync": () => ["wiki", "sync"],
@@ -555,6 +600,16 @@ const WRITES = {
555
600
  "/api/graph/update": () => ["graph", "update"],
556
601
  "/api/wiki/usage/rebuild": () => ["wiki", "usage", "--rebuild"],
557
602
  "/api/gotcha/prune": () => ["gotcha", "prune"],
603
+ // v2.0.0 W7 — the Behaviour panel writes. FREE, local and reversible: each
604
+ // one changes `.claude/orc/habits-state.json` only (or promotes ONE gotcha
605
+ // candidate), and each is a person's click on a confirmation that names the
606
+ // command. `--by panel` is how the history says who made the change. The
607
+ // learning switch itself is `/api/config/set` — no second route for it.
608
+ "/api/habit/accept": (b) => ["habit", "accept", String(b.id), "--by", "panel"],
609
+ "/api/habit/decline": (b) => (b.never ? ["habit", "decline", String(b.id), "--never", "--by", "panel"] : ["habit", "decline", String(b.id), "--by", "panel"]),
610
+ "/api/habit/forget": (b) => ["habit", "forget", String(b.id), "--by", "panel"],
611
+ "/api/habit/reset": (b) => ["habit", "reset", String(b.id), "--by", "panel"],
612
+ "/api/gotcha/accept": (b) => ["gotcha", "accept", String(b.id)],
558
613
  "/api/pact/check": (b) => (b.id ? ["pact", "check", String(b.id)] : ["pact", "check"]),
559
614
  "/api/pact/sync": () => ["pact", "sync"],
560
615
  // The surface id, the key and the value all come from the browser — and all
@@ -810,6 +865,20 @@ const MAINTENANCE = {
810
865
  label: "Recompile AGENTS.md from the wiki, patterns, PACT.md and boundary cards",
811
866
  preview: ["export", "--check"],
812
867
  },
868
+ // v2.1.0 W7 — clear old logs. The preview is the CLI's own print mode, which
869
+ // names EVERY file it would delete and every file it keeps, with the reason
870
+ // (a count is not consent). The day value comes from config
871
+ // (`log_retention_days`): the panel sends only this id. `status` is the
872
+ // no-scan summary the row shows before any preview (days, last sweep).
873
+ "clear-logs": {
874
+ apply: ["clear", "logs", "--apply"],
875
+ restarts_ui: false,
876
+ label: "Delete finished traces and run folders older than log_retention_days (never user data, never a waiting run)",
877
+ preview: ["clear", "logs"],
878
+ status: ["clear", "logs", "--summary"],
879
+ names_files: true,
880
+ danger: true,
881
+ },
813
882
  // ADVANCED (v0.44.0) — the one action on this panel that does not target the
814
883
  // project. Every other route pins `--dir <projectRoot>`; `--global` outranks
815
884
  // `--dir` in `resolveClaudeDir`, so this pair reaches ~/.claude and its
@@ -1120,7 +1189,11 @@ async function handleApi(req, res, url, ctx) {
1120
1189
  try {
1121
1190
  body = await readBody(req);
1122
1191
  } catch (_) {}
1123
- const canned = fixtures.post(route, body);
1192
+ // The staged preview has nothing to replay here, so it answers with the
1193
+ // canned picture — the shape the panel reads, not "nothing ran".
1194
+ if (route === "/api/statusline/stage-preview")
1195
+ return json(res, 200, { ok: true, preview: fixtures.get("/api/statusline/preview", body), show: fixtures.get("/api/statusline/show", body) });
1196
+ const canned = fixtures.post(route, body);
1124
1197
  if (canned)
1125
1198
  return json(res, 200, {
1126
1199
  ok: true,
@@ -1183,6 +1256,9 @@ async function handleApi(req, res, url, ctx) {
1183
1256
  names_files: !!m.names_files,
1184
1257
  advanced: !!m.advanced,
1185
1258
  restarts_ui: !!m.restarts_ui,
1259
+ danger: !!m.danger,
1260
+ // The CLI's own no-scan summary (v2.1.0 W7) — never a number the panel computes.
1261
+ status: m.status ? readCli(m.status, ctx).data || null : null,
1186
1262
  }));
1187
1263
  return json(res, 200, { ok: true, exit_code: 0, data: { actions } });
1188
1264
  }
@@ -1200,6 +1276,7 @@ async function handleApi(req, res, url, ctx) {
1200
1276
  network: !!m.network,
1201
1277
  names_files: !!m.names_files,
1202
1278
  advanced: !!m.advanced,
1279
+ danger: !!m.danger,
1203
1280
  // Said in the confirmation, not discovered afterwards. A panel that
1204
1281
  // reloads itself without warning reads as a crash.
1205
1282
  restarts_ui: !!m.restarts_ui,
@@ -1382,6 +1459,10 @@ async function handleApi(req, res, url, ctx) {
1382
1459
  return json(res, 200, { ok: true, ...started });
1383
1460
  }
1384
1461
 
1462
+ // v2.0.4 — the staged preview. NOT a mutation of this project: it runs in a
1463
+ // throwaway copy, so it neither waits on nor blocks a running job.
1464
+ if (route === "/api/statusline/stage-preview") return json(res, 200, stagePreview(body, ctx));
1465
+
1385
1466
  const build = WRITES[route];
1386
1467
  if (!build) return json(res, 404, { error: "unknown endpoint " + route });
1387
1468
  if (job && job.running) return json(res, 409, { error: "busy", job: jobView() });
@@ -1391,8 +1472,7 @@ async function handleApi(req, res, url, ctx) {
1391
1472
  } catch (_) {
1392
1473
  return json(res, 400, { error: "bad request body" });
1393
1474
  }
1394
- if (argv.some((a) => a === "undefined" || a === "null" || a === ""))
1395
- return json(res, 400, { error: "missing argument" });
1475
+ if (!argvComplete(argv)) return json(res, 400, { error: "missing argument" });
1396
1476
  const out = runCli(argv, ctx);
1397
1477
  clearCache();
1398
1478
  // A write's exit code is a REAL failure signal (validators exit 1), unlike a
@@ -1406,6 +1486,71 @@ async function handleApi(req, res, url, ctx) {
1406
1486
  });
1407
1487
  }
1408
1488
 
1489
+ // A write's argv is complete when no element is a lost value. `""` is a real
1490
+ // value right after a `--flag` — it is how a v2.0.3 clear is spelled — and is
1491
+ // refused only as a positional, together with "undefined" and "null".
1492
+ function argvComplete(argv) {
1493
+ return !argv.some((a, i) => {
1494
+ if (a === "undefined" || a === "null") return true;
1495
+ if (a !== "") return false;
1496
+ const prev = argv[i - 1];
1497
+ return !(typeof prev === "string" && prev.startsWith("--"));
1498
+ });
1499
+ }
1500
+
1501
+ // The files a board's layout lives in, under `.claude/orc/`. The CLI's own
1502
+ // names; only the AUTHORED file is copied — the rest is compiled from it.
1503
+ const SL_LAYOUT_FILE = { status: "statusline-layout.json", subagent: "subagent-layout.json" };
1504
+
1505
+ // v2.0.4 — THE STAGED PREVIEW. The staged writes are replayed through the SAME
1506
+ // `WRITES` builders against a throwaway copy of this project's layout, then
1507
+ // the copy is previewed by the hook's own engine. Nothing touches the real
1508
+ // project, and the copy is always deleted.
1509
+ function stagePreview(body, ctx) {
1510
+ const b = body || {};
1511
+ const board = b.board === "subagent" ? "subagent" : "status";
1512
+ const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "orc-stage-"));
1513
+ const sub = { ...ctx, projectRoot: tmp };
1514
+ try {
1515
+ const orcDir = path.join(tmp, ".claude", "orc");
1516
+ fs.mkdirSync(orcDir, { recursive: true });
1517
+ const src = path.join(ctx.projectRoot || "", ".claude", "orc", SL_LAYOUT_FILE[board]);
1518
+ if (ctx.projectRoot && fs.existsSync(src)) fs.copyFileSync(src, path.join(orcDir, SL_LAYOUT_FILE[board]));
1519
+ const actions = Array.isArray(b.actions) ? b.actions : [];
1520
+ for (let i = 0; i < actions.length; i++) {
1521
+ const a = actions[i] || {};
1522
+ const route = String(a.route || "");
1523
+ const build = route.startsWith("/api/statusline/") ? WRITES[route] : null;
1524
+ let argv = null;
1525
+ try {
1526
+ argv = build ? build(Object.assign({}, a.body || {}, { board: board })) : null;
1527
+ } catch (_) {
1528
+ argv = null;
1529
+ }
1530
+ if (!argv || !argvComplete(argv)) return { ok: false, failed: { index: i, output: "refused: " + route } };
1531
+ const out = runCli(argv, sub);
1532
+ if (out.exit_code !== 0)
1533
+ return { ok: false, failed: { index: i, output: (out.stdout + (out.stderr ? chr10 + out.stderr : "")).trim() } };
1534
+ }
1535
+ const q = { board };
1536
+ if (b.width) q.width = b.width;
1537
+ if (b.state) q.state = b.state;
1538
+ if (b.frames) q.frames = b.frames;
1539
+ if (b.frame_ms) q.frame_ms = b.frame_ms;
1540
+ const preview = runCli(READS["/api/statusline/preview"](q), sub, { json: true });
1541
+ const show = runCli(READS["/api/statusline/show"](q), sub, { json: true });
1542
+ return { ok: true, preview: preview.data, show: show.data };
1543
+ } finally {
1544
+ rmTree(tmp);
1545
+ }
1546
+ }
1547
+
1548
+ function rmTree(dir) {
1549
+ try {
1550
+ fs.rmSync(dir, { recursive: true, force: true });
1551
+ } catch (_) {}
1552
+ }
1553
+
1409
1554
  // `orc upgrade` replaces the package while your working tree may hold changes.
1410
1555
  // Worth a warning before, not a surprise after.
1411
1556
  function isDirtyTree(ctx) {
@@ -1422,4 +1567,4 @@ function isDirtyTree(ctx) {
1422
1567
  }
1423
1568
  }
1424
1569
 
1425
- module.exports = { handleApi, clearCache, encodeBody, READS, WRITES, MAINTENANCE };
1570
+ module.exports = { handleApi, clearCache, encodeBody, READS, WRITES, MAINTENANCE, argvComplete, stagePreview };