@azure-id/orc 1.0.0 → 1.2.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 (48) hide show
  1. package/CHANGELOG.md +151 -0
  2. package/README.md +84 -34
  3. package/bin/cli.js +1110 -0
  4. package/bin/verify-contracts.js +112 -1
  5. package/bin/verify-package.js +568 -563
  6. package/bin/webui/api.js +15 -0
  7. package/bin/webui/app.html +210 -207
  8. package/bin/webui/css/panels/wait.css +123 -0
  9. package/bin/webui/fixtures/index.js +7 -0
  10. package/bin/webui/fixtures/wait.js +97 -0
  11. package/bin/webui/i18n/en/nav.json +21 -20
  12. package/bin/webui/i18n/en/wait.json +41 -0
  13. package/bin/webui/i18n/id/nav.json +21 -20
  14. package/bin/webui/i18n/id/wait.json +41 -0
  15. package/bin/webui/js/01-i18n.js +151 -150
  16. package/bin/webui/js/panels/wait.js +253 -0
  17. package/package.json +1 -1
  18. package/templates/commands/orc-wait.md +19 -0
  19. package/templates/hooks/orc-statusline.js +227 -1
  20. package/templates/skills/_shared/phases/execution.md +2 -0
  21. package/templates/skills/_shared/phases/preflight.md +22 -0
  22. package/templates/skills/_shared/return-validation.md +222 -145
  23. package/templates/skills/_shared/wait.md +240 -0
  24. package/templates/skills/orc/SKILL.md +247 -238
  25. package/templates/skills/orc-aftermath/SKILL.md +6 -1
  26. package/templates/skills/orc-analyze/SKILL.md +6 -1
  27. package/templates/skills/orc-boundary/SKILL.md +6 -1
  28. package/templates/skills/orc-brainstorm/SKILL.md +6 -1
  29. package/templates/skills/orc-budget/SKILL.md +6 -1
  30. package/templates/skills/orc-challenge/SKILL.md +6 -1
  31. package/templates/skills/orc-claude/SKILL.md +6 -1
  32. package/templates/skills/orc-diy/SKILL.md +6 -1
  33. package/templates/skills/orc-doc/SKILL.md +490 -481
  34. package/templates/skills/orc-explain/SKILL.md +5 -0
  35. package/templates/skills/orc-export/SKILL.md +5 -0
  36. package/templates/skills/orc-fast/SKILL.md +222 -215
  37. package/templates/skills/orc-grill/SKILL.md +6 -1
  38. package/templates/skills/orc-learn/SKILL.md +6 -1
  39. package/templates/skills/orc-mini/SKILL.md +252 -244
  40. package/templates/skills/orc-pact/SKILL.md +6 -1
  41. package/templates/skills/orc-pattern/SKILL.md +6 -1
  42. package/templates/skills/orc-poly/SKILL.md +6 -1
  43. package/templates/skills/orc-quick/SKILL.md +353 -346
  44. package/templates/skills/orc-retro/SKILL.md +6 -1
  45. package/templates/skills/orc-route/SKILL.md +6 -1
  46. package/templates/skills/orc-verify/SKILL.md +6 -1
  47. package/templates/skills/orc-wait/SKILL.md +163 -0
  48. package/templates/skills/orc-wiki/SKILL.md +180 -171
package/CHANGELOG.md CHANGED
@@ -10,6 +10,157 @@ Format: `### v<version> — <title> _(<date>)_`.
10
10
 
11
11
  ---
12
12
 
13
+ ### v1.2.0 - a retry that cloned the agent, and a window you can watch empty _(2026-09-04)_
14
+
15
+ **Still on the unscoped `orc` package?** Do this once first — your `orc upgrade`
16
+ is the pre-v0.56.0 one and cannot install itself. Full detail in the CAUTION at
17
+ the top of this file.
18
+
19
+ - **Step 1 — release the command from the old package:** `npm uninstall -g orc`
20
+ - **Step 2 — install the current package:** `npm i -g @azure-id/orc`
21
+ - **Step 3 — re-apply it to your project:** `orc update`
22
+
23
+ **Do not use `npm i -g -f`.** Full detail in v0.56.0 below.
24
+
25
+ A Task error does not kill the subagent behind it. Every lane's retry rule
26
+ assumed it did. One graded `/orc-quick` entry put **three** `orc-executor-opus-5-low`
27
+ agents on the same task — 50m19s, 115m22s and 100m53s, **266 minutes of Opus 5
28
+ for one authorised dispatch**, all editing the same files inside a 2h04m window.
29
+ The trace hook had recorded every one of them. Nothing had ever read it.
30
+
31
+ - **`orc run inflight`** — the one reader of the pending sidecar the trace hook
32
+ has written on every `SPAWN` since v0.34. `0` clear · `1` in-flight ·
33
+ `2` unknown. Every lane that re-dispatches now asks it first.
34
+ - **A re-dispatch is refused over a live attempt.** New registered contract
35
+ token, `_shared/return-validation.md` **§0**, placed above every existing rule
36
+ because every one of them ends in "re-dispatch". The refusal names the agent,
37
+ the task and its age, and always offers "dispatch anyway" — never as the
38
+ default.
39
+ - **Exit 2 refuses, and it is the one place in ORC where an absent reading
40
+ blocks.** `orc usage check` exit 2 never stops a run; an UNCHECKABLE pact
41
+ never raises an exit code. It inverts here because the two errors are not the
42
+ same size: a wrongly-refused dispatch costs one question, a wrongly-issued one
43
+ costs a second Opus agent for an hour.
44
+ - **An interrupted turn is UNKNOWN, never FAILED.** A usage limit, an API error
45
+ or a `Ctrl+C` between a dispatch and its return says nothing about the agent.
46
+ Classifying that as a failure is what made the incident compound: it paid
47
+ twice, hit the limit sooner, and retried again.
48
+ - **Unknown is not zero.** A missing sidecar, an unreadable one, records older
49
+ than six hours, or a sidecar that disagrees with the trace's own SPAWN/RETURN
50
+ balance all read `unknown` — never `clear`.
51
+ - **The honest limit is stated, not papered over.** It cannot see an *ad-hoc*
52
+ dispatch (`/orc-quick` recon, dispatched by model+effort rather than a pinned
53
+ `orc-*` agent): the hook writes no `SPAWN` for one, so no record exists. Those
54
+ are read-only and short, and a lane must never read `clear` as proof one
55
+ finished.
56
+
57
+ The other half — **you can now watch the window empty**:
58
+
59
+ - **`orc usage report`** — 5-hour, 7-day and context in one place, plus the line
60
+ the snapshot could never give you: **"This session has consumed 59% of the
61
+ 5-hour window and is still counting"**, with the caveat that other sessions on
62
+ the same account share that window.
63
+ - **A window reset mid-session is not a refund.** The statusline keeps a
64
+ per-session ledger beside `usage.json` — raw numbers only, never a computed
65
+ word — and banks what was spent before a reset so the running total keeps
66
+ counting across the boundary. A new session re-baselines.
67
+ - **The statusline grew a second line, and a `sess +X%` segment on the first.**
68
+
69
+ ```
70
+ 🚀 ORC-boosted Opus 5/high · 22% ctx · 5h 69% (1h30m) ↔ wk 30% · sess +59%
71
+ agents 4 (1 running) · orc-extra: on · lanes: mini, quick · 41m
72
+ ```
73
+
74
+ `agents` counts what this session spawned and **never hides what is still
75
+ running** — the thing that was invisible while three agents worked on one
76
+ task. Dispatches are attributed by the trace's **own line timestamps**, not
77
+ the file's mtime, so a run that was already going when the session started is
78
+ not counted twice. A lane is named only if it actually dispatched, and
79
+ `lanes: none yet` keeps its slot rather than vanishing. The scan is throttled
80
+ to once every 5s, because a statusline re-renders on every keystroke.
81
+
82
+ - **Top 5 by measured wall time, and it says that is what it is.** Claude Code
83
+ records **no token usage for a dispatched subagent** — `isSidechain` is never
84
+ set and no sidechain message carries a usage block — so a per-agent token
85
+ figure cannot be measured. Every Claude row reports `tokens: null` and the
86
+ reason, **never `0`**, which would tell you the work was free. Only
87
+ `orc extra` foreign workers report real four-kind vectors, and those rows say
88
+ so. Inventing the rest would be the same class of bug as the one above.
89
+
90
+ **Nothing here is on by default that was not already.** `usage_gate` still ships
91
+ `off`. The in-flight guard adds one free CLI read before a re-dispatch — it
92
+ changes no dispatch that was already correct.
93
+
94
+ ### v1.1.0 - the wait, and a window ORC can finally see _(2026-08-31)_
95
+
96
+ **Still on the unscoped `orc` package?** Do this once first — your `orc upgrade`
97
+ is the pre-v0.56.0 one and cannot install itself. Full detail in the CAUTION at
98
+ the top of this file.
99
+
100
+ - **Step 1 — release the command from the old package:** `npm uninstall -g orc`
101
+ - **Step 2 — install the current package:** `npm i -g @azure-id/orc`
102
+ - **Step 3 — re-apply it to your project:** `orc update`
103
+
104
+ **Do not use `npm i -g -f`.** Full detail in v0.56.0 below.
105
+
106
+ Until now the only thing in ORC that could see how full your 5-hour and 7-day
107
+ windows were was the statusline, which drew a string and threw the numbers away.
108
+ So a lane started a wave with no idea it was about to run out, and the wave
109
+ stopped in the middle.
110
+
111
+ - **`/orc-wait`** - a wall-clock pause that does not lose the run. Type
112
+ `/orc-wait 30` and ORC writes the hand-back, waits in detached hops, and picks
113
+ the run up where it stopped. **The waiting costs zero tokens** - a detached
114
+ command does it, and no model runs. It never dispatches an agent to wait,
115
+ because an agent would spend the very window you are waiting for.
116
+ - **Three modes, and they differ in one thing only: how much finishes first.**
117
+ `safe` finishes the current wave and loses nothing. `soft` stops at the next
118
+ turn but **forces** the checkpoint - and if that write fails it does not stop.
119
+ `hard` stops at the next turn with the hand-back alone.
120
+ - **`/orc-wait block <reason>`** - the veto. It tells ORC not to stop this run at
121
+ all. The reason is required, it is never written to your config, and it is
122
+ re-printed with its age at every gate it suppresses.
123
+ - **`orc usage check`** - one reader, three answers: `0` ok, `1` low, `2`
124
+ unknown. **The worst window decides.** A weekly window at 96% is not a green
125
+ light because the 5-hour one is at 20%.
126
+ - **`orc ui` gains a Wait panel** - your windows, a wait in progress, a standing
127
+ block and its age. It cannot start a wait: a wait lives in a Claude Code
128
+ session, and the panel never runs a lane.
129
+ - **Every lane supports it, in one release.** 24 spines carry the contract, each
130
+ naming what it checkpoints and where its safe point is - generated from one
131
+ registry, so a spine cannot disagree with the CLI.
132
+
133
+ > [!CAUTION]
134
+ > **`/orc-wait ... hard` can lose work.** It stops at the first moment ORC can
135
+ > act - it does not wait for the current wave, phase or gate to finish, and it
136
+ > dispatches nothing, so it writes `RESUME.md` and skips the checkpoint. What
137
+ > you can lose: a dispatch that was in flight (its file writes may still land,
138
+ > but its return is never validated), the checkpoint, and that phase's trace
139
+ > packet. Use `hard` when losing the current wave is cheaper than losing the
140
+ > window; use `soft` when you can spare a few seconds; use no keyword at all
141
+ > when you can wait for the wave to end.
142
+ >
143
+ > **A wait longer than one hour ends the prompt cache.** The first turn after it
144
+ > re-reads your whole context at full input price, exactly when your quota is
145
+ > lowest. When the context is large ORC stops and offers a fresh session
146
+ > instead - **it cannot clear its own context**, only offer the swap.
147
+ >
148
+ > **`/orc-wait block` moves the risk to you, deliberately.** It suppresses every
149
+ > computed stop for the rest of the run. If the window empties mid-wave, the
150
+ > wave stops in the middle and you keep the pieces.
151
+ >
152
+ > **Nothing here is on by default.** `usage_gate` ships `off` and
153
+ > `wait_default_mode` ships `ask`. A fresh install behaves exactly as it did
154
+ > before this release. You choose every stop.
155
+
156
+ **Five new config keys**, every default off or ask: `usage_gate` (`off`),
157
+ `usage_stop_pct` (`10`), `wait_default_mode` (`ask`), `wait_hop_minutes` (`30`),
158
+ `wait_max_hops` (`5`).
159
+
160
+ **One honest limit:** a reading is only as fresh as the last statusline render,
161
+ so during a long dispatch it goes stale. Anything older than 30 minutes reads as
162
+ `unknown`, and **unknown never stops a run**.
163
+
13
164
  ### v1.0.0 - config, phases and calls stop being prose _(2026-08-30)_
14
165
 
15
166
  **Still on the unscoped `orc` package?** Do this once before anything else -
package/README.md CHANGED
@@ -7,14 +7,14 @@
7
7
  *Intake → analyze → plan → score → parallel subagents → review → verify → ship.*
8
8
 
9
9
  ![npm](https://img.shields.io/npm/v/%40azure-id%2Forc?style=for-the-badge&color=cb3837&logo=npm)
10
- ![Version](https://img.shields.io/badge/version-1.0.0-blue.svg?style=for-the-badge)
10
+ ![Version](https://img.shields.io/badge/version-1.2.0-blue.svg?style=for-the-badge)
11
11
  ![License](https://img.shields.io/badge/license-MIT-green.svg?style=for-the-badge)
12
12
  ![Node](https://img.shields.io/badge/node-%3E%3D18-brightgreen.svg?style=for-the-badge)
13
13
  ![Claude Code](https://img.shields.io/badge/Claude_Code-Skills-purple.svg?style=for-the-badge)
14
14
  ![Dependencies](https://img.shields.io/badge/dependencies-zero-lightgrey.svg?style=for-the-badge)
15
15
  ![GitHub stars](https://img.shields.io/github/stars/azure-id/orc?style=for-the-badge&color=yellow)
16
16
 
17
- **Latest: v1.0.0** · updated 2026-08-30 · [full changelog](CHANGELOG.md)
17
+ **Latest: v1.2.0** · updated 2026-09-04 · [full changelog](CHANGELOG.md)
18
18
 
19
19
  **On npm: [`@azure-id/orc`](https://www.npmjs.com/package/@azure-id/orc)** — `npm i -g @azure-id/orc`
20
20
 
@@ -254,6 +254,7 @@ ORC have terminal hook to see: Context Window %, 5 Hour usage %, Weekly usage %
254
254
  | **`/orc-mini`** | One Sonnet 5 executor, a build + test smoke gate, ship. Skips full review and verify. Switches to the full flow mid-run on request. | [see it](templates/skills/orc-mini/examples/mini-run-mock.md) |
255
255
  | **`/orc-fast`** | The fastest lane. Needs a fresh wiki **and** a cached code pattern; then it skips the analyst and planner entirely. A missing prerequisite falls back to `/orc-mini` — the chat never stops. | [see it](mock-run/orc-fast.md) |
256
256
  | **`/orc-quick`** | Ask for anything: a fix, a question, a defect hunt, a dependency bump, PR comments. Look → ask once → do. **It always asks which agent to dispatch**, and no setting can change that. | [see it](mock-run/orc-quick.md) |
257
+ | **`/orc-wait`** | Wall-clock pause without losing the run. You see the window is nearly full, type `/orc-wait 30`, and ORC hands the run back to disk, waits in detached hops that **cost zero tokens**, and picks up where it stopped. Three modes decide how much finishes first: `safe` · `soft` (forces the checkpoint) · `hard` (fastest, can lose an in-flight return). `/orc-wait block <reason>` tells it not to stop you at all. | — |
257
258
  | **`/orc-diy`** | Your own lane, composed in the terminal with `orc diy` and compiled. Unconfigured or stale → it refuses and offers plain `/orc`. | [see it](mock-run/orc-diy.md) |
258
259
 
259
260
  ### Work out what to build
@@ -574,7 +575,7 @@ a current audit: [EVAL-REPORT.md](EVAL-REPORT.md).
574
575
  **Full history: [CHANGELOG.md](CHANGELOG.md)** — or `orc changelog`, which prints
575
576
  only what is newer than the version you have.
576
577
 
577
- ### v1.0.0 - config, phases and calls stop being prose _(2026-08-30)_
578
+ ### v1.2.0 - a retry that cloned the agent, and a window you can watch empty _(2026-09-04)_
578
579
 
579
580
  **Still on the unscoped `orc` package?** Do this once first — your `orc upgrade`
580
581
  is the pre-v0.56.0 one and cannot install itself. Full detail in the CAUTION at
@@ -584,40 +585,89 @@ the top of this file.
584
585
  - **Step 2 — install the current package:** `npm i -g @azure-id/orc`
585
586
  - **Step 3 — re-apply it to your project:** `orc update`
586
587
 
587
- **Nothing you configure changes meaning, and no command you run is renamed.**
588
- Three things actually change behaviour; everything else is ORC finally reading
589
- its own payload the way it has been telling you to read yours.
590
-
591
- - **The score to model table ends `opus-5-low [65,90)` · `opus-5-med [90,100]`.**
592
- Two bands in six now want an Opus 5 main session where one in eight did.
593
- - **A foreign worker that stalls twice in one run steps aside** for the rest of
594
- that run. Two clocks, never merged; it writes no new measurement and never
595
- writes your config; a promote is a watermark, not a mute, and needs a reason.
596
- - **`orc diy init` defaults to `opus-5-high`.** The old default silently
597
- collapsed the top third of your ladder onto one agent before you chose
598
- anything.
599
-
600
- The structural half - **config, phases and calls stop being prose**:
601
-
602
- - **`orc lane config <lane>`** answers what a lane's config resolved to, with
603
- every shadow already worded. A lane never merges the config file itself again,
604
- and **a rank below a resolved rank is not read at all**.
605
- - **`orc lane phases <lane>`** and **`orc lane calls --all`** do the same for the
606
- shared phase library and the CLI call catalogue - one canonical copy each,
607
- where there were 14-59 restatements per call.
608
- - **`orc ui` renders all of it**: a rank ladder showing which setting ANSWERED,
609
- the lanes that read each key, a Lanes panel, and Extra Recovery's demotion
610
- row with Promote. `orc doctor` gains `lane-keys-drifted`.
611
-
612
- **It did not make the payload smaller** - 208 files became 291, 26,507 lines
613
- became 33,204. Most waves measured as correctness, not deduplication. What
614
- changed is that there is now one place to fix each of these, and a lint that
615
- fails when a copy grows back. Two planned deletions were **measured and
616
- refused**, and the test suite's four-wave flake was diagnosed - with the honest
617
- caveat that three green runs are the gate and not proof.
588
+ **Do not use `npm i -g -f`.** Full detail in v0.56.0 below.
589
+
590
+ A Task error does not kill the subagent behind it. Every lane's retry rule
591
+ assumed it did. One graded `/orc-quick` entry put **three** `orc-executor-opus-5-low`
592
+ agents on the same task 50m19s, 115m22s and 100m53s, **266 minutes of Opus 5
593
+ for one authorised dispatch**, all editing the same files inside a 2h04m window.
594
+ The trace hook had recorded every one of them. Nothing had ever read it.
595
+
596
+ - **`orc run inflight`** the one reader of the pending sidecar the trace hook
597
+ has written on every `SPAWN` since v0.34. `0` clear · `1` in-flight ·
598
+ `2` unknown. Every lane that re-dispatches now asks it first.
599
+ - **A re-dispatch is refused over a live attempt.** New registered contract
600
+ token, `_shared/return-validation.md` **§0**, placed above every existing rule
601
+ because every one of them ends in "re-dispatch". The refusal names the agent,
602
+ the task and its age, and always offers "dispatch anyway" — never as the
603
+ default.
604
+ - **Exit 2 refuses, and it is the one place in ORC where an absent reading
605
+ blocks.** `orc usage check` exit 2 never stops a run; an UNCHECKABLE pact
606
+ never raises an exit code. It inverts here because the two errors are not the
607
+ same size: a wrongly-refused dispatch costs one question, a wrongly-issued one
608
+ costs a second Opus agent for an hour.
609
+ - **An interrupted turn is UNKNOWN, never FAILED.** A usage limit, an API error
610
+ or a `Ctrl+C` between a dispatch and its return says nothing about the agent.
611
+ Classifying that as a failure is what made the incident compound: it paid
612
+ twice, hit the limit sooner, and retried again.
613
+ - **Unknown is not zero.** A missing sidecar, an unreadable one, records older
614
+ than six hours, or a sidecar that disagrees with the trace's own SPAWN/RETURN
615
+ balance all read `unknown` never `clear`.
616
+ - **The honest limit is stated, not papered over.** It cannot see an *ad-hoc*
617
+ dispatch (`/orc-quick` recon, dispatched by model+effort rather than a pinned
618
+ `orc-*` agent): the hook writes no `SPAWN` for one, so no record exists. Those
619
+ are read-only and short, and a lane must never read `clear` as proof one
620
+ finished.
621
+
622
+ The other half — **you can now watch the window empty**:
623
+
624
+ - **`orc usage report`** — 5-hour, 7-day and context in one place, plus the line
625
+ the snapshot could never give you: **"This session has consumed 59% of the
626
+ 5-hour window and is still counting"**, with the caveat that other sessions on
627
+ the same account share that window.
628
+ - **A window reset mid-session is not a refund.** The statusline keeps a
629
+ per-session ledger beside `usage.json` — raw numbers only, never a computed
630
+ word — and banks what was spent before a reset so the running total keeps
631
+ counting across the boundary. A new session re-baselines.
632
+ - **The statusline grew a second line, and a `sess +X%` segment on the first.**
633
+
634
+ ```
635
+ 🚀 ORC-boosted Opus 5/high · 22% ctx · 5h 69% (1h30m) ↔ wk 30% · sess +59%
636
+ agents 4 (1 running) · orc-extra: on · lanes: mini, quick · 41m
637
+ ```
638
+
639
+ `agents` counts what this session spawned and **never hides what is still
640
+ running** — the thing that was invisible while three agents worked on one
641
+ task. Dispatches are attributed by the trace's **own line timestamps**, not
642
+ the file's mtime, so a run that was already going when the session started is
643
+ not counted twice. A lane is named only if it actually dispatched, and
644
+ `lanes: none yet` keeps its slot rather than vanishing. The scan is throttled
645
+ to once every 5s, because a statusline re-renders on every keystroke.
646
+
647
+ - **Top 5 by measured wall time, and it says that is what it is.** Claude Code
648
+ records **no token usage for a dispatched subagent** — `isSidechain` is never
649
+ set and no sidechain message carries a usage block — so a per-agent token
650
+ figure cannot be measured. Every Claude row reports `tokens: null` and the
651
+ reason, **never `0`**, which would tell you the work was free. Only
652
+ `orc extra` foreign workers report real four-kind vectors, and those rows say
653
+ so. Inventing the rest would be the same class of bug as the one above.
654
+
655
+ **Nothing here is on by default that was not already.** `usage_gate` still ships
656
+ `off`. The in-flight guard adds one free CLI read before a re-dispatch — it
657
+ changes no dispatch that was already correct.
618
658
 
619
659
  **Full entry: [CHANGELOG.md](CHANGELOG.md).**
620
660
 
661
+ <details>
662
+ <summary>Earlier releases</summary>
663
+
664
+ - **v1.1.0 - the wait, and a window ORC can finally see — _(2026-08-31)_**
665
+ - **v1.0.0 - config, phases and calls stop being prose — _(2026-08-30)_**
666
+
667
+ Full bodies for every one of these are in [CHANGELOG.md](CHANGELOG.md).
668
+
669
+ </details>
670
+
621
671
  ---
622
672
 
623
673
  ## Requirements