@azure-id/orc 0.55.0 → 0.56.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.
package/CHANGELOG.md CHANGED
@@ -1,2017 +1,2139 @@
1
- # Changelog
2
-
3
- All notable changes to ORC, newest first.
4
-
5
- The **latest release** is also summarised in the [README](README.md#changelog).
6
- This file is the full history, and it is the file `orc changelog` reads — that
7
- command prints only the entries **newer than the version you have installed**.
8
-
9
- Format: `### v<version> — <title> _(<date>)_`.
10
-
11
- ---
12
-
13
- ### v0.55.0 a score is what a band needs, and four lanes do not have one _(2026-08-26)_
14
-
15
- **A score is what a band needs, and four lanes do not have one.** `/orc-quick`,
16
- `/orc-fast`, `/orc-doc` and `/orc-wiki` pin an agent to a POSITION rather than
17
- scoring a task. `orc extra` routed them anyway by resolving the pinned agent's
18
- score band at both edges, which is arithmetic on a number nobody chose.
19
-
20
- It was wrong twice and dead once. A document set to `checker` resolved the
21
- **writer's** band for a role it was not routing. `/orc-wiki` asked for a role
22
- named `scanner` that `extra_roles` refuses by name, so that lane could never
23
- route however it was configured — `orc extra lanes` printed `claude` forever,
24
- with a reason that read like a user's choice. And `orc extra dispatch` required a
25
- `score` unconditionally, so **no non-scored dispatch had ever reached the bridge
26
- at all** not the fence, not the journal, not the spend log.
27
-
28
- - **`orc extra role` holds six POSITIONS**: `quick-executor` · `fast-executor` ·
29
- `doc-writer` · `doc-checker` · `wiki-scanner-deep` · `wiki-scanner-light`. One
30
- named position, one chosen `profile/model`, and **a row's presence is the
31
- arming**. `list` prints all six always — an unrouted position keeps its slot
32
- and reads as the Claude agent it falls through to, because "I left the checker
33
- on Claude on purpose" and "there is no checker" must never look the same.
34
- - **A second resolver that never touches a band.** `orc extra resolve --slot
35
- <slot>` is the sibling of the score shape, same answer, same exit codes, and
36
- the Claude answer it carries is a **pinned NAME rather than an interval**
37
- strictly more honest than what the scored half can offer. Nine hold-backs, each
38
- answered by name; a cited risk is never invented for a lane that has none.
39
- - **Precedence, one sentence for both shapes:** extra decides *whether* a Claude
40
- agent runs at all; `opus5_only` and the score tables only decide *which* Claude
41
- agent runs where extra did not take it. Under a taken slot `opus5_only` is **not
42
- consulted** and it stays fully live for every position with no row. `orc
43
- config list` and `orc config set` now name the taken POSITIONS beside the taken
44
- bands.
45
- - **The bridge accepts a slot.** Exactly one of `score` or `slot`; both is
46
- refused by name; `band` becomes `slot:<slot>` so the trace parser, the
47
- eight-field dedupe and `orc extra stats` are untouched and each position gets
48
- its own cost row for free. **Zero new engines, zero new dispatch paths, zero new
49
- agents** the fence, the cap, the credential triangle, the journal, the spend
50
- log and the resume ladder all come along unchanged.
51
- - **Per lane:** `/orc-doc` resolves each role against its OWN slot and `orc doc
52
- next` names the model per role before the wave (a document's voice is the
53
- deliverable); `/orc-wiki` prints its target beside the tier it already prints;
54
- `/orc-fast` names the agent it displaced in the F0 line; **`/orc-quick` gets a
55
- THIRD OPTION on its menu** never a default, never sticky, re-asked after a
56
- failure, because that gate's whole premise is asking.
57
- - **`orc ui Extra Routing` grows a second ladder** below the bands, and
58
- **zero config keys were added** a second master gate, per-lane switches,
59
- `extra_quick_ask` and a per-slot model key were all considered and are written
60
- down as refused.
61
-
62
- ---
63
-
64
- ### v0.54.0 a failed dispatch is a POSITION, not a blank page _(2026-08-25)_
65
-
66
- **A worker on another model wrote six of seven lines and lost its connection.
67
- ORC sent the same task to Claude from scratch — onto a file that was already
68
- two-thirds written.**
69
-
70
- `orc extra` had exactly one recovery move: re-dispatch the SAME slice to the
71
- Claude band. That move assumes the worktree is where the dispatch found it. **It
72
- usually is not.** The replacement executor's three plausible moves were all
73
- wrong: `Write` the file whole and discard work you already paid for · `Edit`
74
- against a stale mental model so `old_string` does not match and it improvises ·
75
- read first and then guess whether what is there is its own earlier work, a
76
- teammate's, or garbage. No field in the slice could have told it, and no field in
77
- the return contract could have carried it.
78
-
79
- **The registered token, sixth in its family:** `a lane that re-does work the
80
- worktree already contains` has broken this contract. It joins `a lane that
81
- answers its own interview question`, `a lane that picks its own favourite`, `a
82
- lane that fixes what it judged`, `a lane that picks its own council`, `a lane
83
- that reads its own document`, and `a lane that sends work off Claude without
84
- saying so`.
85
-
86
- - **THE JOURNAL IS THE CLI'S, AND IT IS WRITTEN BEFORE THE FIRST BYTE LEAVES THE
87
- MACHINE.** `.claude/orc/extra-journal/<task_id>/` — a header carrying HEAD,
88
- `git status --short` in full and a hash plus a line count for every
89
- `declared_files` entry; a progress log appended as the dispatch runs; a result
90
- written beside the spend append. It is written by `orc extra dispatch` itself,
91
- which is the **fourth** time this repo has chosen a written-by-the-CLI fact
92
- over a relayed one (v0.32.0 narration, v0.49.5's hand-back page, v0.53.2's
93
- spend log). No lane writes it, no lane can forget it, and it is best effort by
94
- construction: a journal that cannot be written never takes the dispatch down.
95
- The header is the only record of what the repository looked like before a
96
- third party touched it, which is the only thing that makes a reconciliation
97
- possible at all.
98
- - **`orc extra reconcile <task_id>` — FREE, deterministic, and it runs before
99
- anything paid.** Five states, five exit codes (0 `resumable` · 1
100
- `nothing-to-resume` · 2 `no-journal` · 3 `complete` · 4 `in-flight`), and 0 is
101
- the answer the command exists to give rather than "healthy". Per declared file:
102
- `untouched` · `created` · `modified` · `deleted` · `reverted`, with line counts
103
- where they can be computed EXACTLY and `null` where they cannot — **unknown is
104
- not zero**. Plus `touched_undeclared[]` (a fence breach, surfaced here because
105
- a crashed dispatch is exactly when the worktree delta never ran), the last
106
- recorded action, and the partial token vector.
107
- - **It deliberately does NOT decide whether a file is finished.** No brace
108
- counter, no truncation heuristic, no language sniffing /orc-doc's house-rule
109
- boundary verbatim: the CLI cannot parse intent, so it does not pretend to, and
110
- **a fake validator would be worse than none.** The checks that answer "is this
111
- done" already exist and are already engine-blind. Reconciliation's job is to
112
- point them at the right thing.
113
- - **ATTRIBUTION whose fault it was, with the evidence.** Five verdicts, each
114
- carrying a different correct recovery: `provider` · `network` · `local` ·
115
- `worker` · `orc`. **`network` HOLDS THE WAVE** a Claude fallback cannot
116
- succeed when the machine has no network, so falling back would be a second
117
- failure and a second cost for nothing. The two are told apart by ONE
118
- unauthenticated 3-second request on a path that has already failed, made only
119
- on the reasons that cannot be separated without it. `orc` is on the list on
120
- purpose: a report about a third party with no way to blame its own author is
121
- not a report anybody should trust v0.53.3 was exactly an ORC bug that
122
- presented as a bad key.
123
- - **`orc extra resume-slice <task_id> --out <f>` composes the continuation, and
124
- the CLI owns the wording.** It is a NEW DISPATCH OF A DERIVED SLICE through the
125
- ordinary bridge zero new engines, zero new dispatch paths, **zero new
126
- agents** so the fence, the concurrency cap, the credential rules, the spend
127
- log and the worktree delta all come along unchanged. It **never widens
128
- `declared_files`**, **never moves `acceptance[]`**, **never moves the score**
129
- (a resume is not a discount), and **refuses on a drifted slice**, naming both
130
- hashes.
131
- - **Where a resume goes is DERIVED, never a config key.** Retryable → the same
132
- profile in a new session, up to `extra_resume_max`. Non-retryable → the Claude
133
- band, **still as a RESUME slice** — which is what fixes the original bug: the
134
- Claude fallback stops being a from-scratch dispatch, which it should never have
135
- been. A key here would let somebody configure "always the same profile" and
136
- then wait out the cap × a 401.
137
- - **Six refusals, each NAMED, each writing NOTHING** (`not-resumable` ·
138
- `in-flight` · `reverted-file` · `slice-drifted` · `resume-cap` ·
139
- `resume-disabled`). **A live attempt is never resumed:** a dropped socket does
140
- not prove a provider stopped streaming, so a resume is gated on the pid being
141
- gone OR the lease having expired — and past the lease a live pid is treated as
142
- somebody else's process, stated as the honest bound it is rather than as proof.
143
- **A `reverted` declared file blocks and names the paths:** resuming on top of a
144
- possible destructive action is the one case where continuing is worse than
145
- starting over, and ORC does not get to make that call.
146
- - **Two new failure classes make the recovery choosable.** `stream-interrupted`
147
- (the connection was established and then died `unreachable` means it never
148
- opened, and those two want opposite recoveries) and `connection-lost-local`
149
- (the same, with the probe also failing). A taxonomy that returned one word for
150
- both could not pick either, which is why there was only ever one recovery.
151
- - **JOURNAL FIDELITY IS DECLARED PER ENGINE and never rendered stronger than it
152
- is.** `api` and `claude-shim` are `per-turn`; engine `cli` is
153
- `streamed-opaque` its child's stdout now goes to a FILE DESCRIPTOR rather
154
- than a buffer in a parent that dies, so a wall-clock kill leaves the bytes on
155
- disk and `output_file` stops being `null`. ORC captured them and did not
156
- interpret them, and **a gap that is not reported reads as a capability**.
157
- - **A killed dispatch's spend is recoverable.** `appendExtraSpend` runs after the
158
- engine returns, so a killed parent left real money invisible to every cost
159
- report the v0.53.2 hole through a different door. Reconcile writes the
160
- journal's running vector once, idempotently, as `recovered: true, complete:
161
- false`. **Measured is not unknown; unknown is not zero; a recovered vector is a
162
- FLOOR and says so.**
163
- - **Orphans are REPORTED at preflight and never resumed.** `orc extra preflight`
164
- lists every journal with a header, no result and an expired lease and does
165
- **not** change its exit code, because an orphan is a finding, not a stop.
166
- Silently continuing a third party's half-finished write into somebody's
167
- repository is the same class of act as routing off Claude without saying so.
168
- - **Reliability becomes a MEASURED property of a profile.** `orc extra stats`
169
- gains per-profile `dispatches` · `failed` · `resumed` · `orphaned` · mean time
170
- to failure · the attribution split, and **below 10 dispatches there is no rate
171
- at all** — a percentage from three tries is noise with a percent sign on it.
172
- `orc extra doctor` gains `extra-orphan-dispatch` and `extra-profile-unreliable`
173
- (never below the floor). Both ABSENT counts are named.
174
- - **`orc ui Extra Recovery`** a sixth tab, not a tenth card. One row per
175
- journal, **expanded in place** (the Runs-row rule), and the free/paid line is
176
- visible: `reconcile` is a button, `resume-slice` is a copy-able command,
177
- because the panel never runs a lane. A row with nothing to show KEEPS ITS SLOT;
178
- `in-flight` renders as a refusal with its reason; prune is preview-then-apply
179
- and **names every directory**. Spending gains the reliability strip. Overview
180
- gets one line, only when there is something to say, and it never offers to
181
- continue anything.
182
- - **Two new config keys, and the four that were refused are written down.**
183
- `extra_resume` (`on`) and `extra_resume_max` (`2`) — nine keys became eleven.
184
- Deliberately NOT added: a key for where a resume goes, a key for the retry
185
- ladder (`extra_timeout_s` is already the budget), a key to disable the journal
186
- or its 30-day retention (**a record you can switch off is off on the run you
187
- needed it for**), and a key for the network probe. `extra_resume` is INERT in
188
- `/orc-quick`, announced at the agent gate.
189
- - **New trace verbs** `EXTRA resume` and `EXTRA orphan`, composed by the CLI and
190
- copied verbatim — a resume that leaves no line cannot be counted by
191
- `orc extra stats` or `/orc-retro`. New mocked run: `mock-run/extra-recovery.md`.
192
-
193
- ---
194
-
195
- ### v0.53.4 the reload that dropped its own token _(2026-08-24)_
196
-
197
- **Every `orc update` from the panel ended on `This link is missing its session
198
- token.` and the token was never missing.**
199
-
200
- v0.53.2 taught the server to hand itself over to a fresh process on the SAME
201
- port and the SAME token, so the URL in the address bar stays valid and the open
202
- tab only has to reload. That half worked. The reload did not: the panel strips
203
- `?t=` out of the visible URL at boot (`00-core.js`, so the token never lands in
204
- a screenshot or a pasted link), and the hand-over then called
205
- `location.reload()` which re-requests **the stripped address**. No `?t=`, no
206
- `x-orc-token` header on a document request, and the server correctly answered
207
- with the un-authenticated page. Deterministic, on every maintenance action that
208
- declares `restarts_ui`.
209
-
210
- - **A reload is not `location.reload()` here.** `reloadWithToken()` re-attaches
211
- the in-memory token and `location.replace()`s that URL. It is the only reload
212
- route in the panel, and a test fails on any bare `location.reload()` in
213
- `app.js` the stripping is deliberate, so the fix has to be the reload, not
214
- the strip.
215
- - Nothing about the server, the successor, the lock, the token generation or the
216
- `restarts_ui` declaration changed. The upgrade had already installed by the
217
- time the page broke; the user's recovery `orc ui --stop` then `orc ui` — was
218
- producing a *new* token for a server that was already the new build.
219
-
220
- ---
221
-
222
- ### v0.53.3 the key it never sent _(2026-08-24)_
223
-
224
- **A vaulted, verified, routed connection authenticated every wave with the wrong
225
- secret, and four separate green checks agreed it was fine.**
226
-
227
- `orc extra dispatch` resolved the credential by passing `inMemory:
228
- process.env.ORC_EXTRA_KEY` into `extraCredentialValue`, and that option
229
- short-circuited the vault branch **on its first line**. So whenever
230
- `ORC_EXTRA_KEY` was set in the environmenta leftover from another profile,
231
- another provider, another day dispatch sent *that* value and never opened the
232
- vault at all. The profile's real, verified, vaulted key was never consulted.
233
-
234
- Only `dispatch` and `conform` passed that option. `ping`, `models --test` and
235
- `preflight` all resolved without it, opened the vault, and succeeded. Hence the
236
- part that made this expensive to find:
237
-
238
- ```
239
- orc extra doctor → nothing to report.
240
- orc extra list → dipkshit deepseek/api verified key vault
241
- orc extra preflight → dipkshit ok saved until 2027-08-19
242
- orc extra models dipkshit --test <model> → answered in 1866ms
243
- ```
244
-
245
- Four checks, each honest about the path it exercised, **none of them exercising
246
- the path a dispatch takes**. Then the wave died at HTTP 401
247
- `Your api key: ****w5f7 is invalid` pointing at the vaulted key the user had
248
- verified four minutes earlier, while the key ORC actually sent came from an
249
- environment variable the message never named. Nothing was written and nothing was
250
- billed; the run halted at F2 under `extra_on_failure: stop`.
251
-
252
- - **The two in-memory options were one option, and they are different facts.**
253
- `opts.inMemory` is an **explicit** key supplied for this invocation
254
- (`--key-stdin`) the key being tested and then stored, so it still wins.
255
- `opts.ambientKey` is a key found lying in the environment, and it is now what
256
- it was always written to be: the **unattended-wave fallback**, applying only to
257
- a vault that cannot be opened here (`extra_unlock: per-dispatch`, where nothing
258
- is cached on purpose). **A vault ORC can open always wins.**
259
- - **A passphrase in hand that the vault refuses is a real answer about the
260
- declared source,** not a reason to reach for a leftover variable. It returns the
261
- refusal rather than burning an attempt and then sending the wrong secret anyway.
262
- - **The return now reports the source it USED.** `credential.source` is one of
263
- `vault` · `env` · `ambient` · `memory` · `tool`, and it describes what happened
264
- rather than what the profile declares the two disagreed for a release, so the
265
- one field that could have named the bug confirmed the wrong story instead.
266
- `credential_override` is printed whenever the profile's declared source was not
267
- the one used, pass or fail: an override nobody was told about is the same class
268
- of silence as work leaving Claude with no `extra:` line.
269
- - **A 401 names the source that produced the rejected secret.** The provider's
270
- message describes what it saw; only ORC knows where that came from. It was a
271
- five-minute fix and a multi-step diagnosis.
272
-
273
- **`ORC_EXTRA_KEY` holds the KEY, and `orc extra keyhelp` said it was the
274
- passphrase.** For a vaulted profile it rendered a per-OS instruction to export
275
- `ORC_EXTRA_KEY="<your passphrase>"` — into the exact variable a dispatch sends to
276
- the provider in an `Authorization` header. Following ORC's own instruction handed
277
- the secret that opens the vault to a third party. The block is gone. In its place
278
- the route **with a deadline on it** renders first (`orc extra session <name>
279
- --save --ttl 30`, the v0.52.0 design), then the variable, described as the key,
280
- with the warning that a passphrase must never go there. Nothing in ORC reads a
281
- passphrase from the environment, so `passphrase_env` is now always `null`.
282
-
283
- **One completions URL, and the probes speak it.** `ping` rung 2 and
284
- `models --test` hardcoded `{base}/chat/completions` while dispatch derived
285
- `{base}/v1/chat/completions` through `apiCompletionsUrl` and neither probe
286
- honoured a profile's `completions_path` at all. DeepSeek accepts both spellings,
287
- so this was not the 401; on a provider that accepts only one it produces a
288
- profile that verifies **green** and dispatches into a 404, which is the same lie
289
- wearing a different status code. Both probes now call the same builder.
290
-
291
- **And the unknown-model escape has to be about the model.** A 400/404/422 on the
292
- probe's invented model id was read as proof that the endpoint authenticated
293
- before declining the name which is only true if the endpoint is the one it was
294
- aiming at. A gateway answering `Unknown request URL` with a 404 authenticated
295
- nothing. The rejection must now name the model asked for, or say something about
296
- a model/engine/deployment; otherwise the ping fails honestly instead of
297
- verifying. `verify_credential_source` records which credential earned the badge.
298
-
299
- **The fake provider was more permissive than the provider.** It answered a
300
- completion on **any** path, which is precisely why two probes could hardcode the
301
- wrong one for three releases with a green suite. It now serves exactly the path
302
- `apiCompletionsUrl` derives and 404s the rest the v0.53.0 rule, applied to the
303
- third surface in a row that broke on it.
304
-
305
- ---
306
-
307
- ### v0.53.2 the cost that was paid and never written down _(2026-08-24)_
308
-
309
- **Two foreign dispatches ran, cost real money, and every cost report read zero.**
310
-
311
- `orc extra dispatch` composes an `EXTRA …` trace line and hands it back for the
312
- lane to copy into a phase packet. That is a RELAY THROUGH A MODEL — the
313
- remembered-not-dispatched pattern this repo has already lost to twice — and it
314
- broke in both directions on two graded runs of the same feature:
315
-
316
- - one wrote `EXTRA Codex/gpt-5.4-mini :: engine=cli …`, adding the trace's own
317
- `verb :: tail` separator, which the parser did not accept;
318
- - one dropped the line entirely and folded the token vector into a free-form
319
- `VERIFY` sentence.
320
-
321
- Both dispatches SUCCEEDED. `return.json` and `return-fast.json` were sitting in
322
- the run folder with complete four-kind vectors 27,029 / 0 / 159,616 / 1,895 for
323
- codex, 136 / 0 / 20,032 / 134 for opencode and a perfectly formed `trace_line`
324
- inside each. `orc extra stats` reported **0 dispatches from 2 traces**, `orc extra
325
- rates` had no pair to price, and `orc ui Extra Spending` read **`0 tasks
326
- sent`**. A cost report that reads zero when money was spent is worse than no
327
- report, because a zero gets believed.
328
-
329
- - **THE BRIDGE WRITES THE SPEND DOWN ITSELF.** Every dispatch appends one JSON
330
- object to `.claude/orc/extra-spend.jsonl` at the moment it holds the numbers —
331
- profile, provider, model, engine, task, band, the four token kinds unblended,
332
- outcome, duration, the run it belonged to, and the `trace_line` it composed.
333
- The `RESUME.md` lesson from v0.49.5 applied to money: **the fact is recorded by
334
- the hand that computed it.** Best effort by construction a record that cannot
335
- be written never takes a dispatch down and the dispatch says `spend_logged`
336
- either way, because a dispatch no cost report can see is worth one line now
337
- rather than a mystery later.
338
- - **The trace line is NOT retired, it is DEMOTED to the second source.** It is
339
- still the run's narrative and still what `/orc-retro` reads; it is no longer
340
- what the money depends on. The two are DEDUPED on the eight fields the line
341
- itself carries, so a lane that relays correctly is counted exactly once —
342
- double-counting a correct relay would punish the behaviour the contract asks
343
- for.
344
- - **The parser now accepts the ` :: ` a trace writer reaches for by reflex.**
345
- Every other verb in a trace is `VERB … :: tail`. A line that is faithful about
346
- the numbers and off by two characters in its punctuation must still parse.
347
- Tolerance is a net under the contract, not a licence to reshape the line.
348
- - **A saved dispatch return backfills a run made before any of this existed.**
349
- `{run_dir}/<slug>/*.json` is read as a THIRD source when — and only when — it
350
- carries `dispatched: true` and a `trace_line` this parser accepts. That is the
351
- CLI's own payload read back, not a narrative about it, which is what separates
352
- a recovery from an invention. It carries no date and **none is derived from an
353
- mtime** (the `/orc-pact` UNCHECKABLE rule), so `--since` excludes those rows and
354
- says how many.
355
- - **Every count says which source it came from,** on both surfaces. "ORC wrote
356
- this down itself" and "a trace happened to mention it" are different levels of
357
- confidence in the same total. Two ABSENT counts are named rather than absorbed:
358
- a torn log line, and an undated saved return a date filter dropped — a report
359
- that is quietly short by three rows is the exact failure being fixed.
360
-
361
- **And the panel now survives its own upgrade.**
362
-
363
- `orc upgrade` replaces the package the running `orc ui` server was loaded from.
364
- Node read `bin/webui` at require time and `STATIC` is a one-time walk at boot, so
365
- an upgraded panel keeps serving the old bytes: the version in the rail does not
366
- move, a new panel does not appear, and a fixed bug is still there. The remedy was
367
- three manual steps nobody was told about stop the server, re-run `orc ui`, open
368
- the new URL.
369
-
370
- - **The server hands itself over.** After a maintenance action DECLARED as
371
- replacing the install (`update`, `prune`, `fix`, `upgrade` never
372
- `update-global`, which targets `~/.claude`) succeeds, the panel restarts on the
373
- **same port and the same token** and the open tab reloads itself. A successor on
374
- a new address is not a restart; it is a second server, and the tab you are
375
- looking at would still point at the corpse.
376
- - **CLIENT-TRIGGERED, never automatic on the job's close handler.** The job's
377
- output lives in the server's memory, so restarting the instant a command
378
- finished would destroy the record of what it did before anyone read it. It also
379
- means a tab that is already closed leaves the old process running, which is the
380
- safe resting state.
381
- - **The token travels in the ENVIRONMENT, never in argv** it authenticates a
382
- write surface, which puts it in the same class as the credentials `orc extra`
383
- refuses on a command line. It is read once at boot and deleted from
384
- `process.env`, so no CLI subprocess the server shells out to inherits it.
385
- - **A failed handover is a note and two commands, never a broken page.** The old
386
- panel keeps working; it just prints `orc ui --stop` and `orc ui`. And the
387
- confirmation says the restart is coming BEFORE the apply a panel that reloads
388
- itself with no warning reads as a crash.
389
-
390
- ---
391
-
392
- ### v0.53.1 "up to date" now names what it checked _(2026-08-23)_
393
-
394
- **A one-line diagnostic for the update check that could not be questioned.**
395
-
396
- The update check was never broken, and that was the problem. `orc version` reads
397
- `package.json` from `UPDATE_URL`; `orc upgrade` installs from `TARBALL_SPEC`.
398
- They are two different URLs on what is *normally* the same branch — and only the
399
- second one was ever printed, on either surface. The Maintenance panel's `source`
400
- row shows the install tarball, so a reader concludes the version comparison read
401
- main too.
402
-
403
- That gap makes a true statement unfalsifiable. A maintainer who cut v0.53.0 on an
404
- unmerged release branch saw `✓ up to date` against a main that was still at
405
- 0.52.0, with nothing on screen to distinguish "you are current" from "the release
406
- never reached the ref this reads". There is no way to tell those apart from the
407
- output, which is why it reads as a defect in the checker.
408
-
409
- So the number and the ref it came from now travel together, everywhere the number
410
- is reported:
411
-
412
- - **`orc version`** prints `✓ up to date (azure-id/orc@main is at 0.52.0)`, and
413
- the offline branch names the unreachable ref rather than saying "source".
414
- - **`orc version --json`** gains `checked_source` (the URL) and `checked_ref` (the
415
- `owner/repo@ref` label). This is not a new idea: `orc changelog --json` has
416
- always carried its own `source`, and this is that field's missing twin — a
417
- field the human path implied and the JSON omitted.
418
- - **`orc ui` Maintenance** gains a `version read from` row beside `source`, so
419
- the two URLs are visibly two URLs. The fixture carries both fields.
420
-
421
- `checkSourceLabel()` shortens a `raw.githubusercontent.com` URL to
422
- `owner/repo@ref` and returns anything else verbatim a custom `ORC_VERSION_URL`
423
- is shown as written rather than mangled into a label that does not describe it.
424
-
425
- **Nothing about the check itself changed.** No new request, no new cache, no
426
- change to the 24h TTL, `ORC_NO_UPDATE_CHECK` or the comparison. The only thing
427
- that is new is that the answer can now be checked.
428
-
429
- ### v0.53.0 — the schema the provider rejected, and a routing table you can read _(2026-08-23)_
430
-
431
- **One outage, one defect visible at a glance, and the Extra panel rebuilt.**
432
-
433
- **The outage.** Engine `cli` on **codex** had been 100% dead for a release, and
434
- the suite was green the whole time. ORC handed codex an `--output-schema` with
435
- `additionalProperties: true`; OpenAI structured outputs require a **closed**
436
- object at every level, so every dispatch was an **HTTP 400 raised before the
437
- model was ever reached** — fast, free, and reported as something vague. Flipping
438
- only that flag is a **second** 400, this time naming `files_changed`, because
439
- `required` must list every key in `properties`. An optional field is a nullable
440
- union now, never an omission from `required`, and the shape is documented as
441
- **provider-dictated rather than chosen** — the comment calling it "deliberately
442
- minimal" is what produced the bug.
443
-
444
- Three things went with it:
445
-
446
- - **The classifier was reading the wrong stream.** codex relays the upstream
447
- `invalid_request_error` inside its own event stream on stdout while printing a
448
- benign notice on stderr, so a precisely-diagnosable, non-retryable failure came
449
- back as `unknown` and `retry: false` was reached by luck. The codex adapter
450
- now classifies from **the provider's own error object** first, and
451
- `classified_from` says which of the two answered a field that reports where
452
- a verdict came from must not lie about it.
453
- - **A measurement was being reported as unknown.** codex *does* report
454
- `cache_write_input_tokens`; the adapter declared three usage kinds, so ORC
455
- threw a real number away and then said it was never measured.
456
- `reasoning_output_tokens` is still deliberately unreadthe Responses API
457
- counts it inside `output_tokens`, and an unproven pricing change is worse than
458
- a missing one.
459
- - **And the reason it shipped green: the fake was more permissive than the
460
- provider.** It asserted the schema existed and mentioned `status`, and modelled
461
- none of OpenAI's rules. That is the **third release in a row** broken by the
462
- same shape `--auto` renamed, a greedy `-f` array, now an open schema. **A
463
- strict third-party parser fails for free, and it looks like a model problem.**
464
- The defence is the same every time: the fake must be at least as strict as the
465
- real thing. It now rejects both 400s by name.
466
-
467
- **The ellipse.** A ready-and-verified tool card drew its "connected as" chip as a
468
- 250px green ellipse. `.ex-tool` declared `grid-template-rows: auto auto auto 1fr
469
- auto` but **four states carry four different numbers of children**, so the chip
470
- landed in the `1fr` slack row, stretched (a grid item's default), and a 999px
471
- radius did the rest. It hit whichever ready card had the shortest content in its
472
- row, so it was never about one tool. The card is a flex column now, with no row
473
- template at all. The old test asserted the property was *present* which it was,
474
- while the panel drew an ellipse.
475
-
476
- **The Extra panel.** It was nine cards in one 8,786px scroll: no first step, no
477
- last step, no way to be *done* with a section.
478
-
479
- - **Five tabs** on the panel's own precedent Setup, Routing, Limits, Spending,
480
- Providers. The header strip and "what needs your attention" stay outside them,
481
- because a caution you have to go looking for is a caution nobody reads. The
482
- open tab survives a re-render, and the gate still decides what **exists**: with
483
- nothing connected, three tabs are not rendered as empty shells.
484
- - **One vertical band ladder** replaces the horizontal rail *and* the duplicate
485
- list of rows below it. The target is no longer truncated, the widths no longer
486
- lie (a `min-width` floor was fighting the percentage), nothing is off-screen,
487
- there is a **legend** green means the work leaves your machine and the row
488
- you read is the row you edit.
489
- - **The plain-language range is the CLI's.** `orc extra route` gains `range`
490
- ("scores 0 to 29") and `meaning` per row, printed on the human path as well.
491
- Writing "simple work" beside a score in the panel would be the panel deciding
492
- what a score means.
493
- - **One sentence and one control per tool state**, with the diagnostics behind a
494
- disclosure.
495
- - **Wording**: the panel was serving **design rationale as user instruction**.
496
- Six keys split the instruction first, in Simplified Technical English, the
497
- reasoning collapsed underneath. Nothing deleted, both languages, and the
498
- rationale keeps its voice.
499
-
500
- Setup per provider: **[`guides/extra-models.md`](guides/extra-models.md)**.
501
-
502
- ---
503
-
504
- ### v0.52.0 the connection that could not be used, and the routing nobody could see _(2026-08-23)_
505
-
506
- **Eleven defects, one release.** Five came out of a real `/orc-fast` run against
507
- a verified, routed local tool a run that fell back to Claude twice over, for
508
- two unrelated reasons, neither of which was the model. Six more came out of
509
- reading the panel afterwards, and they are one theme with several faces:
510
- **Extra was invisible to every surface that is not the Extra panel.**
511
-
512
- **The two that killed that run.**
513
-
514
- - **`opencode` dispatch was dead on arrival.** `-f` is a yargs **array** flag,
515
- and a yargs array is **greedy**: every non-flag token after it is swallowed as
516
- another file path. ORC pushed the message last, so `message..` arrived empty
517
- and opencode exited 1 in its own parser — `dur=0m01s`, `tok=none`,
518
- `outcome=failed`, looking exactly like a model problem. Engine `cli` on that
519
- tool was 100% dead for a release. The message comes first now, `-f` comes
520
- last where it has nothing left to eat, and the test fixture asserts **that a
521
- message arrived** rather than that a flag was present.
522
- - **A tool that signs itself in was being forced into the vault.** `--tool-auth`
523
- has existed in the CLI since v0.51.0 and the panel offered two radios, so a
524
- connection that needed **no key from ORC at all** got a vault, and the vault
525
- then locked the run. There is a third credential source in the form now,
526
- offered only where it can be true, and pre-selected when the card you pressed
527
- Connect on says the tool is already signed in.
528
-
529
- **The passphrase finally has a lifecycle, and a deadline.** A vaulted key needed
530
- `ORC_EXTRA_KEY` in the environment or nothing, so a green, verified, routed
531
- connection answered `locked` at wave 1 and the run announced a Claude fallback.
532
-
533
- - `orc extra session <name> --save --ttl <days>` saves it, **on stdin** —
534
- `--passphrase <value>` is refused by name, like every other secret here. The
535
- deadlines are a closed set (1 · 3 · 7 · 14 · 30 · 90 · 180 · 360): no `0`, no
536
- "forever", and **no auto-extend on use** a deadline that renews itself is
537
- not a deadline.
538
- - The cache lives **in the project**, gitignored beside the vault, and is
539
- encrypted under the pepper that lives in your home directory. **A copy of the
540
- project folder opens nothing.** That is the one genuine property this file
541
- has, and it is said out loud wherever the countdown appears — along with the
542
- honest half: while it is saved, anything running as you on this computer can
543
- open the connection.
544
- - **`orc extra preflight` is a P0 gate before wave 1.** Active is fine; expiring
545
- is fine and names the date; **expired or missing STOPS the run**. It never
546
- falls back — `extra_on_failure` is about an endpoint that failed, and a
547
- deadline you set 30 days ago deserves a stop, not a substitution. The
548
- credential is deleted and the connection stamped expired; **the routing rows
549
- survive**, because the bands are work you did.
550
- - The save modal at connect time **has no exit but Save**, and one destructive
551
- escape that is named rather than a Cancel.
552
-
553
- **Extra is visible outside its own panel now.**
554
-
555
- - **`orc extra lanes`** answers the question a band cannot: *which lane does this
556
- govern?* `/orc` scores every task; `/orc-fast` pins one executor and resolves
557
- its band **at both edges**, requiring them to agree. That rule was implemented
558
- and written down and rendered nowhere. The lane table is code now, mirrored
559
- against the markdown in both directions by a golden test.
560
- - **The Flow score table sees Extra.** With `extra: on` it renders the composite
561
- instead of the Claude ladder a band that cannot route **keeps its row** and
562
- names its fall-through, and `extra: off` renders byte-identically to before.
563
- - **`fixed_executor` can name a foreign target** (`extra:<profile>/<provider>/<model>`),
564
- offered only for verified connections. The session-tier rule is skipped for it
565
- — it is not a Claude model — and **the compiled flow says so**, because a rule
566
- silently disabled is worse than no rule.
567
- - **`/orc-doc` has its own switch.** `orc doc extra <slug> --set
568
- off|writer|checker|both`, stored per document, default off. A global setting
569
- turning Extra on for a throwaway runbook also turned it on for the PRD you
570
- ship, and a document's voice is the deliverable. `orc doc next` names the
571
- sections going off Claude **before** the wave.
572
-
573
- **Three panel defects, and one of them was in every modal.**
574
-
575
- - A **connected** tool no longer offers Connect. `connected` and `verified` are
576
- computed by the CLI, never joined in the panel, and the verified card **has no
577
- Connect button at all** rather than a disabled one.
578
- - **Scrolling inside a modal scrolled the page behind it** — every modal in the
579
- app, not just Extra's. Fixed with scroll containment and a body lock.
580
- - **Two tool cards no longer sit at different heights.** A card declares its rows
581
- now, so the button in one lines up with the button in the other.
582
-
583
- **Wording.** The Extra panel's instruction text labels, hints, errors, gates,
584
- countdowns, the passphrase modal end to end is Simplified Technical English,
585
- with a one-page term list at `bin/webui/i18n/TERMS.md` and a test for the cheap
586
- half. Rationale prose keeps its voice and only gets shorter: flattening *"it
587
- stops someone at your keyboard, not someone who copied the file"* makes it true
588
- and useless. One rule is not negotiable and now has a test: **never simplify a
589
- CLI-computed value** a simplified state word is a state that does not exist.
590
-
591
- New: `orc extra session`, `orc extra preflight`, `orc extra lanes`, `orc doc
592
- extra`, `orc extra dispatch --passphrase-stdin`, and one config key
593
- (`extra_passphrase_ttl_days`, default 30). `orc extra keyhelp` now carries the
594
- per-OS command for setting an environment variable with a placeholder, never a
595
- key, and ORC still refuses to run `setx` or write to your shell profile itself.
596
-
597
- ---
598
-
599
- ### v0.51.0 the tools you already have, and a connection that proves itself _(2026-08-22)_
600
-
601
- **`orc extra` connections.** Two of the things ORC can hand work to are not
602
- websites they are **programs on your own machine**, and the last release could
603
- only reach them by hand-typing a binary name into a `custom` profile. They are
604
- first-class providers now, with a connect box each, a model dropdown built from
605
- what **your** account can actually reach, and a connection test that proves
606
- something answered rather than proving a file exists.
607
-
608
- - **A program can simply not be installed, and the panel says that FIRST.** Four
609
- states, computed fresh every time and never remembered: `absent`,
610
- `outdated`, `unauthenticated`, `ready`. An absent tool gets no Connect
611
- button, no Test button and no model list every one of those is a button that
612
- cannot succeed. `orc extra add` refuses too, and names the install command
613
- instead of leaving you a profile that will never work.
614
- - **ORC opens your own terminal and runs the install there.** Not a hidden
615
- background job inside one, an administrator prompt, a permissions error, an
616
- 80 MB download and a forty-second wait all look identical: *nothing happened*.
617
- The exact command is on screen before the button, the window is yours to read
618
- and Ctrl-C, **ORC never asks for administrator rights**, and if no terminal can
619
- be opened you get the command to paste rather than a dead button.
620
- - **One tool has an install-free route and one does not**, and `null` means
621
- *there is none* rather than *ORC did not look*. The two never render the same.
622
- - **The connection test is a ladder now, and every rung reads as itself.** Is the
623
- program there · is it new enough · does it have a sign-in · which models can
624
- this account reach · and — only when you ask — **does a real message actually
625
- come back**, with the round trip, the reply, and the four token counts kept
626
- separate. Free rungs always run; the paid one is its own button, and what it
627
- costs is quoted before you press it.
628
- - **A model that is LISTED is not a model that WORKS.** A live list is what the
629
- provider offers; an id in it can be dead upstream. `orc extra models <name>
630
- --test <id>` is the only thing that tells those two apart, and the caveat rides
631
- beside every dropdown.
632
- - **Neither local tool says which model answered**, so a quiet substitution is
633
- invisible on that engine. ORC prints that sentence rather than an empty field —
634
- and one of the two reports three token kinds, not four, so the missing one
635
- reads as an em dash and never as a zero.
636
- - **A models list anyone can read is not proof of your key.** A provider that
637
- serves its catalogue without a credential would otherwise mark a connection
638
- verified with a typo'd key. That answer is now recorded for what it was and the
639
- test carries on to something that actually needs the key.
640
- - **`extra_enabled` cannot be switched on before anything has answered.** It
641
- would have armed nothing every task would fall straight back to Claude, so
642
- the switch read ON and meant OFF. The refusal names what to do next, and the
643
- Extra panel shows only the connect surfaces until then: no routing table, no
644
- limits, no cost report.
645
- - **A fix, not a feature:** every dispatch to one of the two local tools was
646
- failing, and failing in a way that looked like a bad model id. One of them
647
- renamed a permission flag and refuses unknown ones outright. ORC picks the flag
648
- from the version it probed, and a tool that answers with its own help text is
649
- now reported as a flag problem by name.
650
- - **ORC never writes another tool's credential store.** Your key stays in ORC's
651
- vault or in your own environment variable and is handed to the program for each
652
- run so nothing global changes, revoking it in ORC actually revokes it, and if
653
- you already signed that tool in yourself, ORC leaves it alone.
654
-
655
- ---
656
-
657
- ### v0.50.0 work that runs somewhere else _(2026-08-22)_
658
-
659
- **`orc extra`** — a band of ORC's score ladder can now be answered by a
660
- **non-Claude worker**: DeepSeek, Z.ai (GLM), Moonshot (Kimi), MiniMax, Qwen,
661
- Xiaomi MiMo, StepFun, SiliconFlow, OpenRouter, a local Ollama, any
662
- OpenAI-/Anthropic-compatible endpoint you name, or an agentic CLI you already
663
- have (`opencode`, `codex`). ORC's own session never movesthis routes
664
- **workers**, not the conductor.
665
-
666
- - **Off by default, and a connection that has never answered can never be used.**
667
- `orc extra ping` is the gate, it climbs the cheapest rung first (a free model
668
- list; only then a one-token completion), and it records WHICH rung answered —
669
- "verified by a models list" and "verified by a real completion" are different
670
- guarantees and one green tick for both would be a lie.
671
- - **Every armed run says so BEFORE the work starts.** An `extra:` line joins the
672
- Phase-1 preflight naming how many tasks will cross the boundary and where they
673
- go. It has no quiet version. The failure this whole subsystem is shaped around
674
- is not a wrong answer — it is work leaving your machine without anybody saying
675
- so.
676
- - **A gap in the routing table is not a hole — it is Claude**, and it is printed
677
- with the exact agent it resolves to, so "I left the top band on Opus on
678
- purpose" and "there is no top band" can never look the same. Overlapping rows
679
- are refused by name.
680
- - **Risky work stays.** A task whose plan cites `risk[]` (money, auth, security,
681
- migration, concurrency, data-integrity) never leaves Claude, and neither does
682
- anything in an area a boundary card marks REFUSE — in `warn` mode as well as
683
- `block`.
684
- - **Three engines, and only one composes the request body.** `api` is therefore
685
- the only one that can enforce the declared-files fence or carry a privacy
686
- policy, so a return claiming the fence held on the other two is rendered as a
687
- WARNING: a constraint that was never applied is never reported as kept.
688
- - **Your key never reaches a command line.** `--key <value>` is refused by name.
689
- Use an environment variable (recommended) or the encrypted vault
690
- AES-256-GCM under a passphrase ORC does not store and cannot recover, stored
691
- only after a green test, with a countdown that prints every time and a
692
- self-destruct at ten wrong attempts that keeps the profile. New in this
693
- release: `orc extra ping --passphrase-stdin` re-tests a key that is already
694
- stored.
695
- - **No shipped model ids and no shipped prices.** Both go stale within a quarter
696
- and both get believed. `orc extra ping` reads the live model list from the
697
- provider; `orc extra rates` prints the JSON to paste for a price. Until a pair
698
- has a rate, `usd` reads as an em dash a cost ORC did not price itself is
699
- never printed.
700
- - **`orc extra stats`** joins ORC's own traces per profile per band and reports
701
- four token kinds separately, plus the three things only it can see: a
702
- SUBSTITUTION (you did not get the model you asked for), a REROUTE (you got the
703
- model and a different company served it) and a FALLBACK (it did not work and
704
- Claude finished the job).
705
- - **A failed foreign dispatch is never a dead run.** It falls back to the Claude
706
- band that task would have had, announced. `extra_on_failure: stop` is there for
707
- people who would rather stop than quietly start paying full rates.
708
- - **New panel: `orc ui` Extra.** The boundary paragraph renders always, never
709
- behind a click. One 0→100 rail, green where your connection runs the work and
710
- blue where Claude does, with every unrouted range keeping its slot. Staging a
711
- change previews it before anything is written. The panel names no provider, no
712
- model and no agent — it draws what the CLI computed.
713
- - **The `orc ui` boundary is NARROWED, not broken.** The panel still never runs a
714
- lane and never does agentic model work; the one model-shaped thing it can
715
- trigger is a connectivity probe, and even that runs through the CLI in a
716
- subprocess like every other action. A probe is a diagnostic, the family
717
- `orc doctor` is in.
718
- - **Nine config keys**, one canonical contract
719
- (`_shared/extra-dispatch.md`), a new `EXTRA` trace verb, `orc extra doctor`
720
- with eleven findings, and a stance stated in exactly one place for every other
721
- laneincluding `/orc-challenge`, which never routes foreign, because swapping
722
- a lens for a different model does not make the lane cheaper, it changes what is
723
- being measured.
724
- - **Also:** the test suite pins `--test-concurrency=8`. At one worker per core,
725
- the files that spawn real child processes and the one that derives scrypt at
726
- N=2^17 starved each other and produced failures that looked exactly like
727
- regressions. Determinism is worth 11% of the wall clock.
728
-
729
- Setup detail per provider: **[`guides/extra-models.md`](guides/extra-models.md)**.
730
- A full walkthrough: `orc mock-run orc-extra`.
731
-
732
- ---
733
-
734
- ### v0.49.5 house rules are text, and the hand-back writes itself _(2026-08-21)_
735
-
736
- Two fixes to `/orc-doc`, both the same shape: stop making a person work around
737
- the tool.
738
-
739
- - **House rules are a PLAIN TEXT config now, not a form.** The first cut modelled
740
- a rule as a row one line, one id, a P0/P1/P2 dropdown, an enable flag, added
741
- one at a time. Nobody's real P0 fits on one line, and filing it as four
742
- separate rows to keep the CLI's argv simple was the tool asking the user to
743
- work around it. The ledger is now `.claude/orc/doc-house-rules.md`: three
744
- headings, and **as much text under each one as you want**, handed to every
745
- writer verbatim. Open it in your editor, or edit it in **one box** in
746
- `orc ui` **Docs**no dropdown, no Add button, no per-rule row.
747
- - **New: `orc doc rules set|add|clear --priority P0 --text "…"`** (multi-line is
748
- the point), plus `set-all` for the whole file and `--set-file` for a bulk
749
- replace. `remove`, `enable`, `disable` and `move` are **refused by name** — a
750
- command that used to work and now does nothing is worse than one that says
751
- what replaced it.
752
- - **Migration is lazy, free and non-destructive.** The old `doc-house-rules.json`
753
- is read once, converted, and **left exactly where it was**. A rule you had
754
- DISABLED is never resurrected it is left behind and counted in the output.
755
- - **`RESUME.md` is written by the CLI, on every state change.** It used to be
756
- prose the orchestrator was told to write at every stop, which is the bet this
757
- repo has already lost twice: the hand-back you are TOLD to write is the one
758
- that goes missing on the run a usage limit killed. `doc.json` has exactly one
759
- writer, so the hand-back hangs off that it exists from `orc doc init` onward
760
- and is never behind the disk. `orc doc resume-file <slug>` writes it on demand.
761
- - **Every question `/orc-doc` asks you now ends by pointing at it** (hard rule
762
- 16): the file path, and the one line to paste into a brand-new session. The
763
- page itself is written for someone who does not read code what the document
764
- is, where the files are, what is not written yet, and what happens next.
765
-
766
- ---
767
-
768
- ### v0.49.4 the panel was being handed half an answer _(2026-08-20)_
769
-
770
- One bug, and it could hit any `--json` read big enough.
771
-
772
- - **Fixed: a large `--json` payload was truncated whenever something read it
773
- through a pipe.** `emitJson` wrote to stdout and then called `process.exit()`.
774
- On macOS and Linux a pipe write is asynchronous, so the exit threw away
775
- whatever had not flushed and `orc ui` reads every panel through a pipe. On a
776
- 1,100-file repo `orc wiki coverage --json` computed a perfect 30 KB object, the
777
- server received the first 9 KB, `JSON.parse` failed, and **Knowledge ▸
778
- Coverage** reported that the repo had neither a registered wiki nor a git
779
- repositoryon a wiki that was FRESH and 39% covered. `orc wiki docs` was hit
780
- the same way; `wiki status` escaped only because it prints and returns instead
781
- of exiting. Windows pipes are synchronous, which is why it never showed up in
782
- development. Every `--json` read now writes through fd 1 synchronously.
783
- - **The Knowledge panel no longer reports a broken read as an empty repo.** A
784
- failed request renders the CLI's own reason and output, the way every other
785
- panel has since v0.49.2 the generic "it needs a registered wiki and a git
786
- repository" line is for a repo that actually has neither.
787
- - **Also: git output is no longer capped at Node's 1 MB default** (v0.49.3),
788
- which would have truncated `git ls-files` on a repo of roughly 25,000 files.
789
-
790
- ---
791
-
792
- ### v0.49.3 coverage on a large repo _(2026-08-19)_
793
-
794
- One fix, and the bigger the repo the more it mattered.
795
-
796
- - **Fixed: `orc wiki coverage` reported "not a git repository" on a large,
797
- freshly refreshed wiki.** Every git call ORC makes ran through `spawnSync` on
798
- Node's **1 MB** default output buffer. `git ls-files` in a big repo prints more
799
- than that, the child is killed with `ENOBUFS`, and the exit status comes back
800
- `null` which the code read as *there is no git here*. So `orc ui` ▸
801
- **Knowledge** **Coverage** showed no numbers at all on the repos where the
802
- number matters most, and `orc wiki impact` was one wide diff away from the same
803
- failure. The buffer is now **256 MB**, and a spawn error is read as an error
804
- instead of being inferred from the status code.
805
-
806
- ---
807
-
808
- ### v0.49.2 house rules, a run map before you pay, and three defects _(2026-08-18)_
809
-
810
- Quality of life on `/orc-doc`, plus three bugs one of which was breaking a
811
- panel outright. **Zero new agents, zero new skills.** Everything here obeys the
812
- standing rule: **the CLI computes, the panel and the skill render.**
813
-
814
- #### `/orc-doc` house rules
815
-
816
- A **house rule** is your project's own standing instruction about **what a
817
- document says and how it reads**: *"open with a one-paragraph summary a PM can
818
- read on a phone"*, *"money always carries its currency"*, *"use the customer's
819
- words, not the internal table name"*. Before this, the shipped rules were the
820
- only rules.
821
-
822
- - Three priorities. **P0** must, and it beats every ORC style preference; **P1**
823
- should, and breaking it is recorded as a gap; **P2** prefer.
824
- - Stored **verbatim** in `.claude/orc/doc-house-rules.json` one writer,
825
- `orc doc rules`, outside `templates/` so `orc update` never touches it. A rule
826
- is one line; a multi-line one is refused by name with the hint to add two.
827
- - **Each document freezes the set it started with.** If a P0 changes at wave 3,
828
- half the document silently no longer complies and nothing on disk says so — so
829
- `orc doc rules <slug>` reports frozen-vs-project and **names every rule that
830
- was added, changed or removed**, never a "rules changed" boolean.
831
- `--sync` re-freezes deliberately and **lists the sections that predate the
832
- change**. It re-writes nothing: that would be ORC spending your money applying
833
- a rule change retroactively without being asked.
834
- - **Read FIRST in every dispatched slice**, above ORC's own rules — that order is
835
- the contract.
836
- - **The boundary is declared, not detected.** House rules govern content and
837
- style; they can never change how the lane RUNS. The CLI cannot parse intent, so
838
- it does not pretend to: it prints the boundary everywhere it matters, and a
839
- rule that asks for a structural break comes back as `unsupported_request`.
840
- - New: `orc doc rules [add|remove|enable|disable|move|--sync|--set-file|--reset]`,
841
- a **House rules** card at the top of `orc ui ▸ Docs` (staged and batched, like
842
- every other write in the panel), and a `house-rules-drifted` audit finding.
843
-
844
- #### `/orc-doc` four rules ORC applies to every document, all free
845
-
846
- All four are deterministic lint rules, which is what makes them worth having:
847
- **no model is ever paid to notice a `TODO`.** Every one is narrow on purpose — a
848
- broad rule that argues with the author gets switched off.
849
-
850
- - **No questions or confirmations in the body.** The deliverable answers; it does
851
- not ask. `TBD`, `TODO`, `TBA`, *"to be confirmed"*, and a line that is only a
852
- question put to you as an approver. **Two exemptions:** fenced code, and a
853
- section your own outline calls *open questions / risks / assumptions*.
854
- - **Missing information is `N/A` plus one short line, never filler.** A warning,
855
- never an error — you may have a reason.
856
- - **A section well over its planned length is a finding** (1.5× its budget), plus
857
- per-section line and word counts in `orc doc lint --json`. Signals, not gates.
858
- - **No local-only references.** No `src/foo.ts:42`, no absolute path, no
859
- `./relative`, no `localhost`, no `file://`, no link to a local `.md` — the
860
- person reading a PRD has no repository. Fenced code is always exempt, because a
861
- code example that *shows* a path is content. New config `doc_local_refs`
862
- (`off|warn|error`, default `error`): a genuinely internal runbook legitimately
863
- names local paths, and a lint rule with no switch gets fought instead of used.
864
-
865
- #### `/orc-doc` a supplied template is a cage, not a suggestion
866
-
867
- `--template` set the outline and then nothing stopped a writer adding a heading
868
- it never had. It now locks by default: the slice carries the allowed headings,
869
- `orc doc lint` errors on a stray one, **`orc doc parts --confirm` refuses the
870
- part that grew one and writes nothing**, and `orc doc audit` reports both
871
- `template-drift` and `template-moved` (your template file itself changed
872
- reported, never auto-synced). `--template-soft` opts out; a shipped base template
873
- stays a floor.
874
-
875
- #### `/orc-doc` what it will cost, and what it did cost
876
-
877
- - **`orc doc forecast <slug>` the run map, once, before the first paid wave.**
878
- How many sections, how many waves, how many agents per wave, **how many times
879
- it will stop**, and a token range with its sample count. Computed from the same
880
- batcher the dispatch uses, so it can never describe a run that will not happen.
881
- Every honesty rule of `/orc-budget` is inherited: four token kinds never
882
- blended, no dollars without a dated price table, no quota without a known plan
883
- and **with no history it refuses rather than invent**, offering the
884
- `--naive` price-table floor instead. `orc doc next` names it exactly once; a
885
- changed outline or write mode invalidates it.
886
- - **`orc doc cost <slug>` joined across every session the document spanned.**
887
- `orc budget actual` works per run, and a document is not a run. Per role and
888
- per section, from ORC's traces joined to your local usage transcripts. A slice
889
- that covered two sections splits evenly, said out loud; **a section nothing can
890
- be joined to reads `—`, never `0`.** `unattributed` is always printed.
891
- - Both render in `orc ui ▸ Docs` with a stacked four-kind token bar, so
892
- cache-read stays visibly separate from the rest.
893
-
894
- #### `/orc-doc` an edit round tells you where to look
895
-
896
- `orc doc lint <slug> --section <id>` lints one **section file** and returns
897
- **part-local** line numbers, and every finding on an edit-round slice carries its
898
- file and line. The skill prints one line per finding
899
- (`sections/03-scope.md · line 42 · long-sentence`) and, after the round, each
900
- file it touched. The compiled `document.md` line number is deliberately never
901
- carried: it is stale the moment anything is written.
902
-
903
- #### Fixed the Overview card printed over itself
904
-
905
- `.run-card` is a four-column grid (caret · chip · mid · age) and the Overview
906
- built a card with **three children and no caret**, so the chip landed in the 16px
907
- caret column and printed straight over an 88px slug, which wrapped one word per
908
- line. A grid never complains. Every variant now declares its own column count —
909
- `.no-caret` for a row that navigates, `.has-extra` for an optional second chip
910
- and the same collision in the Docs list (from its "you edited it" chip) is fixed
911
- the same way. The age column now carries the age `run list --json` always knew.
912
-
913
- #### Fixed — a run could never be marked done
914
-
915
- `RESUME.md` existing IS the "unfinished" flag, and ORC deletes it at `FINISH`. So
916
- a run you abandoned was waiting **forever**: `orc resume` kept offering it, the
917
- Overview kept counting it, and the upgrade preview kept refusing with "N run(s)
918
- are still waiting" with no way out short of deleting a file by hand.
919
-
920
- `orc run close <slug> --reason "<why>"` **moves** `RESUME.md` to
921
- `RESUME.closed.md` and records why. **It deletes nothing**, and `orc run reopen`
922
- puts it back byte for byte. The new state is **`closed`**, deliberately not
923
- `done`: the disk cannot prove a run finished, only that you said you were
924
- finished with it. A reason is required a state change nobody wrote a reason for
925
- is a state nobody can audit. Everything else follows from one boolean: `resume`
926
- skips it, `run list` keeps the row *and* its reason, and the upgrade unblocks.
927
- Buttons for both in `orc ui ▸ Runs`, and inline on the Overview card that was
928
- complaining.
929
-
930
- #### Fixedone corrupt challenge ledger 500'd the whole panel
931
-
932
- Two crash classes: a ledger truncated by a killed session, and a ledger with no
933
- `goals` key. Both threw a Node stack with nothing parseable on stdout, so
934
- `orc ui Challenge` showed a bare 500 — and **every healthy cycle disappeared
935
- with the broken one**, which is the opposite of what a listing is for.
936
-
937
- - A broken cycle is now a **row** that reads `UNREADABLE` and carries the parse
938
- error. It is a list-level state: it never reaches the pass gate and never
939
- claims a verdict.
940
- - **No `--json` read can emit a stack trace any more.** A throw comes back as
941
- `{ok: false, reason: "crashed", command, error, hint}` with its own exit code —
942
- every `--json` route inherits it.
943
- - A 500 from the panel's API now carries the CLI's own reason, and the panel
944
- renders it. A 500 with no message is what you actually saw.
945
-
946
- ### v0.49.1 the challenge council, and a `--json` that stops throwing things away _(2026-08-18)_
947
-
948
- One release, two workstreams, and **zero new skills**. They ship together because
949
- they are the same defect seen twice: **ORC computes far more than it shows.**
950
- `computeWikiFreshness` builds a per-doc table that `--json` threw away;
951
- `challenge record` computes per-dimension, per-severity, per-iteration detail
952
- that the panel rendered as one chip. Both halves are "stop discarding what you
953
- already computed" and only one of them also adds new thinking.
954
-
955
- ---
956
-
957
- ## Part A — the challenge council
958
-
959
- ### Five more ways of looking, and none of them is ORC's to choose
960
-
961
- `/orc-challenge` had one grounded opinion (the judge) and one blind one (the cold
962
- reader), and both read the artifact the same way: *does this document do what a
963
- document is supposed to do?* Five ways of looking were missing, and each one is
964
- missed for a different reason:
965
-
966
- | Role | It asks | It fails when |
967
- |---|---|---|
968
- | **The Contrarian** | where is the fatal flaw? | it assumes the artifact is fine and stops looking |
969
- | **The First Principles Thinker** | are we even solving the right problem? | it accepts the framing it was handed |
970
- | **The Expansionist** | what is being undervalued here? | it only counts what is wrong |
971
- | **The Outsider** | what does this assume I already know? | it is an expert and cannot un-know things |
972
- | **The Executor** | what do you actually do on Monday morning? | it grades the theory and never the first step |
973
-
974
- > **A lens raises; only the judge resolves. ORC proposes the council; the user
975
- > picks it.**
976
-
977
- **`a lane that picks its own council` has broken this contract** — registered as
978
- the fourth member of the family with `a lane that answers its own interview
979
- question`, `a lane that picks its own favourite` and `a lane that fixes what it
980
- judged`. A council chosen by ORC is ORC deciding **which kinds of criticism the
981
- user is allowed to hear**, which is a bigger decision than any single finding in
982
- the run. So `orc challenge init --council` has **no default** and refuses by
983
- name, exactly like `--goal` since v0.47.0:
984
-
985
- ```
986
- ❌ --council is required and has no default. ORC SUGGESTS a roster (from the kind
987
- and the goal); the user PICKS it. […] Suggested for --kind tsd:
988
- reader,contrarian,executor.
989
- (a lane that picks its own council has broken this contract)
990
- ```
991
-
992
- `none` is a first-class answer and reproduces the v0.47.0 review exactly. The
993
- cost is stated in **dispatches**, never in dollars `/orc-budget`'s rule: no
994
- dollar figure without a dated price table.
995
-
996
- ### Two of them cannot produce a finding without lying
997
-
998
- This is the most important decision in the release.
999
-
1000
- **The expansionist.** A finding must carry `serves` the goal element it
1001
- advances and `record` DROPS one without it. Its entire brief is *"what upside
1002
- is everyone missing?"*, which by construction is **not** in the stated goal.
1003
- Given a `serves` field it would either invent a goal element or be silently
1004
- dropped. So it returns an **opportunity**: no severity, never in `findings[]`,
1005
- never near the pass gate, always with a `first_step` and a route
1006
- (`brainstorm | pact | grill | none`). It is conserved `--take` or `--drop`,
1007
- both requiring a reason and **this lane never builds one**.
1008
-
1009
- **The first-principles thinker.** Its most valuable output is *"you are asking
1010
- the wrong question entirely"*, and in this lane the question is the **frozen
1011
- goal**. A finding is measured against the goal; a premise challenge disputes the
1012
- **yardstick**. Those cannot be the same object. It returns a **premise**, and
1013
- exactly two resolutions exist, both a human's: adopt it (`orc challenge goals
1014
- --set`, a `regoal` that bumps `goals.version`) or dismiss it with a mandatory
1015
- reason that stays in the report forever. **The judge never sees that report** —
1016
- handing a judge a document arguing the frozen goal is wrong would bend every
1017
- finding it produced afterwards.
1018
-
1019
- > The three finding lenses feed **the judge**. The two non-finding lenses feed
1020
- > **the user**. That sentence is the whole architecture.
1021
-
1022
- ### The gate that makes five extra reviewers safe
1023
-
1024
- The obvious failure of adding five reviewers is that the judge quietly ignores
1025
- four of them and the run looks identical while costing five times more.
1026
-
1027
- > **Every id the council raised must appear in the judge's return with exactly
1028
- > ONE disposition and a reason. `council_coverage_pct` must be 100.**
1029
-
1030
- That is conservation applied to **input** instead of to carry-forward, and the
1031
- CLI enforces it without reading a word of prose: the orchestrator writes a
1032
- machine JSON beside every council report, and **`orc challenge record` reads that
1033
- directory itself**. The judge cannot shrink the set by omission, because the set
1034
- was never the judge's to report.
1035
-
1036
- ```
1037
- malformed verdict council coverage is below 100% every id the council
1038
- raised needs exactly ONE disposition (adopted | merged | rejected |
1039
- out-of-goal). Missing: O-003
1040
- ```
1041
-
1042
- **An adopted finding keeps the raiser's id.** `C-004` stays `C-004` in the
1043
- verdict, in the report, in iteration 9 which is what lets the panel say *"the
1044
- contrarian raised four of the six blockers this iteration"*, and how a user finds
1045
- out within two rounds whether a lens is worth its money.
1046
-
1047
- **PASS is computed exactly as before.** An adopted council finding is an ordinary
1048
- finding from that moment on; `challengeBlocking()`, `challengeOpen()`,
1049
- `challengeCounts()` and `challengeStateOf()` are untouched. The pass gate learns
1050
- nothing about the council.
1051
-
1052
- ### A selected role is never silently absent
1053
-
1054
- Rule 6 (`NOT-CHECKED` is never silent), extended from dimensions to roles. A
1055
- roster lens returns either a report or an explicit `{ "lens": …, "ran": false,
1056
- "reason": }`, and silence is rejected by name:
1057
-
1058
- ```
1059
- malformed verdict executor is on the roster but returned neither a report
1060
- nor an explicit { "lens": "executor", "ran": false, "reason": "…" }.
1061
- A selected role is never silently absent.
1062
- ```
1063
-
1064
- The trace carries it too, so `orc stats` and `/orc-retro` see a NOT-RUN lens and
1065
- not only the panel:
1066
-
1067
- ```
1068
- CHALLENGE iter=2 findings=P0:1/P1:3/P2:6 coverage=100% council=4/5 raised=C:6,O:3,E:2 adopted=9 verdict=FAIL
1069
- ```
1070
-
1071
- ### Effort is a measurement, not a cost choice
1072
-
1073
- `outsider` is `low` for the same reason the cold reader is: a harder-thinking
1074
- outsider reasons its way *around* an unexplained acronym and reports the document
1075
- is fine, which is exactly the gap the instrument exists to find. **Nothing may
1076
- ever upgrade it.** `contrarian` is `high` because at low effort it returns the
1077
- three surface complaints the free lint already caught for nothing.
1078
-
1079
- That is why there is **no model or effort config key**: a key that lets
1080
- `outsider: low` be tuned is a key that lets the instrument be broken.
1081
-
1082
- All seven lenses are `claude-opus-5`, so **`opus5_only` is a no-op for this lane —
1083
- it is unaffected, not exempt** — and the agent count moves 46 51 with no paired
1084
- variants.
1085
-
1086
- ### The reader / outsider seam
1087
-
1088
- These two are the closest pair in ORC and the one place this release could have
1089
- shipped a duplicate instrument. The distinction is structural:
1090
-
1091
- | | `reader` | `outsider` |
1092
- |---|---|---|
1093
- | Told the audience | **yes** | **no** |
1094
- | What it generates | 8–15 questions the artifact *promised* to answer | nothing — it reacts to what is on the page |
1095
- | What it returns | a **scored** questionnaire (`8/12`) | an **unscored** ranked list of assumed knowledge |
1096
- | The measurement | *can this be answered from the page?* | *what does this page assume you already know?* |
1097
-
1098
- They are dispatched with no knowledge of each other. Where they agree, that is
1099
- recorded as `corroborated_by` the strongest comprehension evidence the lane can
1100
- produce, and **never an automatic severity bump**.
1101
-
1102
- ### The roster is frozen, and `council: null` is a real state
1103
-
1104
- Ledger `version: 2`, additive: every v1 key keeps its name, meaning and position.
1105
- The roster is a per-cycle **frozen** decision changed only by a recorded
1106
- `recouncil` event, which bumps `council_version` exactly like `goals.version` —
1107
- and the iteration rail draws a **third** version break for it, because comparing
1108
- an iteration judged by three lenses to one judged by six is not a comparison.
1109
-
1110
- **There is no `challenge_council` config key.** A global default roster would
1111
- silently answer the one question this release exists to ask. A cycle opened
1112
- before v0.49.1 reads back with `council: null` and `record` refuses the next
1113
- iteration by name until it is answered — `orc challenge council <slug>` exits 1
1114
- for that state, because **UNSET is an answer, not an error**.
1115
-
1116
- ### New commands
1117
-
1118
- | Command | Does |
1119
- |---|---|
1120
- | `orc challenge roles [--kind k] [--json]` | the lens catalogue. Static — it works with no cycle at all |
1121
- | `orc challenge council <slug> [--json]` | the frozen roster + per-iteration participation (0 set · 1 unset · 3 unknown) |
1122
- | `orc challenge council <slug> --set <csv\|all\|none> --reason "…"` | a recorded `recouncil` |
1123
- | `orc challenge note <slug> --from <json>` | opportunities and premises ONLY — it refuses a `findings[]` key by name |
1124
- | `orc challenge premise <slug> <id> --dismiss --reason "…"` | |
1125
- | `orc challenge opportunity <slug> <id> --take\|--drop --reason "…"` | |
1126
-
1127
- ### The panel
1128
-
1129
- It **derives nothing**: it does not name a lens, does not know which class
1130
- blocks, does not compute a disposition and does not decide the suggestion. A test
1131
- greps the panel for every lens display name, every disposition word and every
1132
- agent name and fails if it finds one.
1133
-
1134
- New: a **Council card** directly under the goal (a NOT-RUN row keeps its slot
1135
- with its reason; a NOT-SELECTED row is muted with the line that would add it; the
1136
- council executor's `monday_morning` list sits here, because it is the most
1137
- legible thing this lane produces for a non-engineer); a **premise card** that is
1138
- the loudest thing on the panel when one is open and sits *above* the findings; an
1139
- **opportunities card** with no severity colour anywhere in it; a lens chip and an
1140
- `also found by` chip on every finding; and a per-lens legend under the
1141
- convergence chart.
1142
-
1143
- There is deliberately **no route for `council --set`** — changing the roster is a
1144
- decision with a recorded reason the *lane* takes in conversation.
1145
-
1146
- ### Deliberately absent
1147
-
1148
- - **An anonymised peer-review round.** It doubles the dispatch count, and the
1149
- judge's adoption pass already reconciles the lenses. The payoff — *"two
1150
- advisors independently hit the same thing"* — is `corroborated_by[]` at zero
1151
- extra cost.
1152
- - **A chairman agent.** ORC already has one: the advisor groups findings by root
1153
- cause and orders the fix. Rule 5 still holds no advisor on PASS.
1154
- - **A `challenge_council` key, any model or effort key, a `block` mode on a
1155
- council output, a loop cap, and auto-severity from corroboration.**
1156
-
1157
- ---
1158
-
1159
- ## Part B — the knowledge deepening
1160
-
1161
- ### `--json is not a summary`
1162
-
1163
- > A read's `--json` is the WHOLE computed object, not a summary. **A field the
1164
- > human path prints and the JSON omits is drift and it is drift no lint can
1165
- > see, because both halves live in one function.**
1166
-
1167
- `wikiStatus()` computes `computeWikiFreshness(...)` and the terminal branch
1168
- printed the per-doc FRESH/AGING/STALE counts, **the worst doc's filename** (the
1169
- thing actually pinning the tier), the top five stale docs with their own
1170
- distances, and the crosslink boundary state. The `--json` branch emitted five
1171
- scalars and `blind` **as a count**. The panel therefore *could not* be as
1172
- detailed as the terminal, no matter how it was written.
1173
-
1174
- `wiki status --json` now carries `counts`, `worst`, `per_doc[]`, `blind_spot` as
1175
- the **file list it always was**, `orientation`, `crosslink`, and `free_repairs`
1176
- reused verbatim from `wiki plan` a user must never be able to pay for what a
1177
- free step fixes. **Every legacy key keeps its name, position and meaning** (`orc
1178
- doctor`, the overview tile and `_shared/detecting-artifacts.md` all read them)
1179
- and the exit code stays 0 in every state.
1180
-
1181
- ### You can finally see what the wiki contains
1182
-
1183
- `orc wiki` had six subcommands and **not one of them listed the docs**. A user
1184
- could learn the wiki was STALE with 14 docs and 47 commits of drift, and could
1185
- not learn what any of those 14 docs was about.
1186
-
1187
- | Command | Returns | Exit |
1188
- |---|---|---|
1189
- | `orc wiki docs [--json]` | the doc table: tier, its OWN distance, covers, usage, tags, retire hint | 0 · 1 none · 3 unregistered |
1190
- | `orc wiki show <doc> [--body]` | one doc + its tags + the free repairs that apply to IT | 0 · 2 unreadable · 3 unknown |
1191
- | `orc wiki coverage [--json]` | % of tracked files covered by ≥1 doc, uncovered set by DIRECTORY | 0 full · 1 gaps |
1192
- | `orc pattern show <lang> [--body]` | headings, conventions vs invariants, flagged conflicts | 0 · 1 absent · 2 unknown key |
1193
- | `orc gotcha show <id>` | one entry, EVERY field | 0 · 3 unknown |
1194
- | `orc gotcha list --archived` | the archive | 0 · 1 none |
1195
- | `orc gotcha prune --dry-run` | exactly what eviction would archive, and why | 0 none · 1 would prune |
1196
-
1197
- **`orc wiki coverage` is a REPORT and never a gate.** No threshold, no config
1198
- key, nothing branches on it a repo that deliberately documents four subsystems
1199
- out of forty is not broken, and a coverage percentage that starts nagging becomes
1200
- a number people game. The uncovered set is collapsed to directories and ranked by
1201
- file count, because *"240 uncovered files, all in `vendor/`"* and *"12 uncovered
1202
- files, all in `src/payments/`"* are opposite situations.
1203
-
1204
- **`--body` is opt-in** on both `wiki show` and `pattern show`: prose is returned
1205
- only on an explicit request, exactly one artifact at a time, rendered as DOM and
1206
- never as HTML.
1207
-
1208
- **`orc pattern show` invents nothing.** The codifier may not write a parseable
1209
- header today; with none it returns `headered: false` plus the headings it could
1210
- parse, and says so in one line. It **never** derives a "codified at" from the
1211
- file's mtime the `/orc-pact` UNCHECKABLE rule.
1212
-
1213
- ### Two doctor findings, and the restraint is the design
1214
-
1215
- | id | Warns when | Fix |
1216
- |---|---|---|
1217
- | `wiki-unregistered` | the wiki is unregistered, drifted or corrupt | `orc wiki sync` free, instant, and until it is done nothing can read the wiki at all |
1218
- | `wiki-debt` | tier is **STALE** and `wiki plan` has pending rows | `/orc-wiki refresh --top 2` |
1219
-
1220
- **`wiki-debt` fires on STALE and never on AGING.** Aging is a normal state every
1221
- living repo passes through, and a doctor that warns about it is a doctor people
1222
- learn to ignore. Deliberately not added: `pattern-missing` — a project with no
1223
- cached pattern is not misconfigured, and warning about it would be ORC nagging
1224
- for a paid scan.
1225
-
1226
- Both route to the Knowledge panel: *a caution routes to the panel that can CLEAR
1227
- it*, and `orc wiki sync` is a button there.
1228
-
1229
- ### `orc ui Knowledge` five tabs
1230
-
1231
- ```
1232
- Knowledge [ Wiki ] [ Coverage ] [ Code patterns ] [ Memory ] [ Peers ]
1233
- ```
1234
-
1235
- A header strip renders above them alltier · docs · covered % · blind ·
1236
- pending · patterns · repair notes — and **a value the CLI could not compute
1237
- renders as an em dash, never as a guess.**
1238
-
1239
- - **Wiki** — the tier card with the **worst doc named** (a hash is not something
1240
- anybody can go and refresh), the per-doc counts as a stacked bar, free repairs
1241
- above everything priced, and **the doc table**. A row expands in place, one at
1242
- a time, detail fetched on first open.
1243
- - **Coverage** one honestly-qualified number, the uncovered set by directory,
1244
- the structural blind spot as the file list it always was, and one line that is
1245
- not optional chrome: coverage is a report, not a target.
1246
- - **Code patterns** per language, with **the conflicts the codifier flagged in
1247
- their own block**: they are the most decision-shaped thing in the file and were
1248
- invisible outside it. Reveal shows the text that is injected literally into
1249
- every executor slice; a user who cannot read it cannot trust it.
1250
- - **Memory** — every field the CLI already emitted, headroom against
1251
- `gotchas_max`, and a **preview-then-apply prune that names every entry** (a
1252
- count is not consent). The archive is reachable and labelled recoverable.
1253
- - **Peers** compact, read-only, every word the CLI's. It links to Crosslink and
1254
- never duplicates its editor: one boundary, one picture.
1255
-
1256
- ### Guards
1257
-
1258
- Five new agent files named explicitly in `verify-package.js` (floor 46 → 51,
1259
- skills unchanged at 38); five new contract-lint entries; a golden test comparing
1260
- `CHALLENGE_LENS_META` to `council.md`'s roster table; and one test per new read,
1261
- because `--json is not a summary` is drift no lint can catch.
1262
-
1263
- `css/panels/knowledge.css` is a new file, so it is `<link>`ed in `app.html` **and**
1264
- named in `verify-package.js` — the manifest is the load order, and a file the
1265
- manifest forgot is a file the test suite never sees.
1266
-
1267
- ---
1268
-
1269
- ### v0.49.0 — the document is a folder, and the file is a build artifact _(2026-08-17)_
1270
-
1271
- `/orc-doc` only. No other lane changes, and **zero new agents**.
1272
-
1273
- Three quarters of what this release is about already existed: `orc doc plan`
1274
- already wrote one part file per section, the ids were already number-then-name,
1275
- the split already cut on `## ` alone, and `orc doc assemble` was already pure
1276
- Node **zero model tokens, and it always was**. Anyone who tells you this
1277
- release made compiling cheaper is selling something.
1278
-
1279
- What was wrong was the direction of the arrow.
1280
-
1281
- #### `sections/` is the source of truth
1282
-
1283
- `.work/` was scratch and `document.md` was the truth, so after the first
1284
- assemble every later change was *extract* (copy a section OUT of the monolith) →
1285
- edit *splice* (write it back IN). The section files existed and were dead. A
1286
- resumed session, an update and a re-check all routed through the 10,000-line
1287
- file.
1288
-
1289
- Now each section lives in `sections/<NN>-<slug>.md` a real, visible folder you
1290
- can open, edit and read in a pull request — and **`document.md` is a build
1291
- artifact** that `orc doc compile` rebuilds from those files, for free, when you
1292
- ask. `orc doc split` goes the other way and recovers the sections from a
1293
- document a human reshaped by hand; **`split` then `compile` reproduces the file
1294
- byte for byte**, and there is a test.
1295
-
1296
- The join key is the **filename**. No comment markers inside the files: an HTML
1297
- comment is a lint error in this lane and mangles on a Notion or Google Docs
1298
- import, and the deliverable's cleanliness is the lane's entire product. A marker
1299
- that buys nothing costs the import.
1300
-
1301
- #### You can look before you buy the rest
1302
-
1303
- `orc doc compile --partial` writes exactly the sections that exist and **names
1304
- the rest outside the document** — nothing is ever stubbed into the deliverable.
1305
- Paired with the new `doc_write_mode` (`ask` · `partial` · `all`, asked once per
1306
- run and stored), `orc doc plan --role write` returns **wave 1 only**, with
1307
- `more_waves: N`. You read what it wrote, and waves 2..N are bought only if wave 1
1308
- was right. That is the single biggest saving in the lane, and it has nothing to
1309
- do with the compile.
1310
-
1311
- #### A wave is a stop you can walk away from
1312
-
1313
- The write loop used to live in the orchestrator's head, and `/orc-doc`'s
1314
- `RESUME.md` sat in the document folder where `orc resume` and `orc run list`
1315
- never look carrying a `## Where it stands:` line that the line-anchored parser
1316
- **could never match**, and no phase and no wave even if it had.
1317
-
1318
- All four are fixed. `RESUME.md` moves to `{run_dir}/{slug}/`, the line is at
1319
- column 0 and gains a phase D6 · wave 2 of 7` suffix (the byte-stable prefix is
1320
- untouched), and a test feeds the shipped template to the real `parseStands`. The
1321
- section files on disk ARE the progress, so `K of N` is **computed** by counting
1322
- waves whose sections are all hash-confirmed. A part on disk that no validated
1323
- return ever confirmed is `unconfirmed` exactly what a usage limit leaves — and
1324
- it is re-written, never shipped.
1325
-
1326
- #### The deliverable carries content only
1327
-
1328
- `> **Open:**` and `> **Assumption:**` lines are no longer written into your
1329
- document, and the section state no longer sniffs the body text for them. This
1330
- does not relax "never invent a fact"; it moves where the honesty is written down.
1331
- A gap goes to `orc doc log --kind gap` and lands in a derived `gaps.md`, and is
1332
- raised with you.
1333
-
1334
- `orc doc lint` gains `annotation-in-body` as an **error**, matching an exact,
1335
- narrow set of ORC's own markers and nothing else a line of yours beginning
1336
- "Note:" is content and is never flagged. `compile` **reports** every match and
1337
- never silently strips one: we cannot tell whose line it is.
1338
-
1339
- #### A live bug, fixed by construction
1340
-
1341
- A slice covering two sections wrote **one** file, named after the first, while
1342
- `assemble` looked one up per outline id. The second section's file never existed:
1343
- if it was required, assemble refused forever; if it was optional, it silently
1344
- vanished from the deliverable. **One file per section** now, per slice entry, with
1345
- a regression test.
1346
-
1347
- #### A section too big for one file
1348
-
1349
- It splits **underneath** `sections/04-detailed-design/{00-head,01-data-model,…}.md`
1350
- — cut on its own `### ` headings, which `docScan` already collected and merely
1351
- filtered out. The reader never knows: the compiled document has exactly one `## `
1352
- for it, and `orc doc map`, `lint`, `ship` and `audit` are completely unchanged.
1353
- Five refuse-and-name rules make the nesting safe, and a changed sub-part is
1354
- detected on its own, so a re-check inside a 900-line section reads ~150 lines.
1355
-
1356
- **No new config key** for it: `doc_max_lines_per_agent` is already the threshold.
1357
-
1358
- #### The rest
1359
-
1360
- - **`doc_max_parallel` hard cap is now 2** (default 2, was 4/4). A larger value
1361
- is clamped and the clamp is announced.
1362
- - **`orc doc parts`** is the new wave-boundary read, and the one that works
1363
- before a single compile has ever run. `--confirm <ids>` is how a validated
1364
- return becomes a recorded hash.
1365
- - **`orc doc ship` refuses on a stale `document.md`**, naming the sections —
1366
- coverage-relative, one step earlier than `shipped-drifted`.
1367
- - **`orc doc audit`** gains `part-missing`, `part-orphan`, `part-misnumbered`,
1368
- `part-unconfirmed`, `subpart-bad-level`, `document-stale`,
1369
- `annotation-in-body`, `legacy-work` and `resume-misplaced`.
1370
- - **`orc doc outline --set` renames the files on disk** when a renumber moves
1371
- them, in the same step.
1372
- - **A checker now reads ONE bounded part file**, so there is no line arithmetic
1373
- anywhere in the check loop.
1374
- - The Docs panel gains a **Section files** card with nested sub-part rows, a wave
1375
- strip, a compile button and a migrate button. It derives nothing new: the CLI's
1376
- state words, verbatim.
1377
-
1378
- #### Nothing is lost on the way
1379
-
1380
- `doc.json` goes to `version: 2` and a v1 document migrates the first time you
1381
- touch it lazy, free, idempotent, non-destructive. `document.md` is **never
1382
- deleted** (it becomes the build artifact, and starts life fresh rather than
1383
- stale), a pending extract wins as the newer edit, an `> **Open:**` stub does not
1384
- survive, `RESUME.md` is moved and its prefix stripped, and an **unparseable**
1385
- document is REFUSED with `version` left at 1 a guessed structure is worse than
1386
- none. `assemble`, `extract` and `splice` survive as thin aliases for one release,
1387
- with their exit codes preserved.
1388
-
1389
- ---
1390
-
1391
- ### v0.48.1one file per thing, and a document that can be finished _(2026-08-16)_
1392
-
1393
- Two halves, deliberately kept separate so that **any** behaviour difference
1394
- observed after this release is attributable to the second one and to nothing
1395
- else.
1396
-
1397
- #### The panel is an architecture now
1398
-
1399
- `bin/webui/` was four monoliths: a 6 500-line `app.js`, a 2 500-line
1400
- stylesheet, a 1 700-line fixture module and two 800-key string tables. Any
1401
- change to one panel meant paging through all of it to find three places.
1402
-
1403
- It is now ~60 named files — one per panel, one per CSS layer, one per i18n
1404
- namespace, one per fixture set — and the **filename is the load order**, so a
1405
- future session never has to reason about dependencies.
1406
-
1407
- - **Classic scripts, not ES modules,** and the constraint that decided it:
1408
- `serve.js` requires the per-launch token on every static request, and **an
1409
- `import` carries no query string**. A module graph would 401 on every import
1410
- unless static auth were weakened, which was not on the table. Classic scripts
1411
- also share one global lexical scope, so the split added no `import`/`export`
1412
- and changed no call site.
1413
- - **`serve.js` builds its static map from a one-time walk at boot.** A request
1414
- path is still a KEY LOOKUP in a frozen table, never a path join — directory
1415
- traversal stays structurally impossible. Server-side code (`serve.js`,
1416
- `api.js`, `fixtures/`) is never served.
1417
- - **Token stamping is generic.** Naming two files was fine when there were two;
1418
- with ~55 the pattern has to be the rule, or the next `<script>` tag someone
1419
- adds 401s silently. A test parses `app.html` and asserts every reference comes
1420
- back stamped **and** resolves.
1421
- - **`06-responsive.css` and `04-motion.css` load last, and that is
1422
- load-bearing.** Several reduced-motion rules are deliberately not
1423
- `!important` `.vault-pulse` and `.step-flow` are removed with
1424
- `display: none`, because capping an infinite animation to one iteration
1425
- freezes it mid-cycle so an equal-specificity rule loading afterwards would
1426
- win on order and switch the animation back on.
1427
- - **`verify-package.js` names every file AND asserts set equality** with the
1428
- directory, in both directions: the agent-file pattern, applied to the panel.
1429
- - The test suite is split to match (`test/cli/`, `test/lanes/`, `test/webui/`),
1430
- using an `appJs()` / `appCss()` helper that concatenates exactly what
1431
- `app.html` loads — so a file the manifest forgot cannot hide behind a passing
1432
- suite.
1433
-
1434
- **No behaviour changed.** All 274 tests pass, all 17 panels render in both
1435
- themes and both languages with zero console errors, and the guided tour runs end
1436
- to end.
1437
-
1438
- #### `/orc-doc` has a finish line
1439
-
1440
- - **`orc doc next`** turns the pipeline from something the orchestrator
1441
- REMEMBERS into something the CLI COMPUTES the Flow-stepper shape, and for
1442
- the same reason: D6–D9 was prose a session had to hold in its head across a
1443
- resume that might be months later in a fresh context. Exit **0** = an action
1444
- is available (`command`, plus `paid` so a caller knows button vs copy-able
1445
- command), **1** = waiting on a human decision, **named** in `blocked_by`,
1446
- **2** = unknown slug.
1447
- - **`orc doc ship` records delivery as a DECISION** (`/orc-pact`'s rule) while
1448
- the resulting state stays **COMPUTED** (`/orc-challenge`'s rule). `--where`
1449
- has **no default** — "shipped" with nowhere to point at is not a fact, it is a
1450
- feeling and shipping an incomplete document needs `--force --reason`,
1451
- recorded verbatim. `unship` needs a reason and keeps the old record in
1452
- `ship_history[]`.
1453
- - **`shipped-drifted` names the sections that moved,** by diffing the recorded
1454
- per-section hashes against the live map. Coverage-relative, the
1455
- `computeWikiFreshness` lesson applied to a document: a whole-file "something
1456
- changed" cannot tell you what to re-read. It exits **1**, because the document
1457
- moved after it was delivered and that is work.
1458
- - **`orc doc audit`** reports every drift class from disk an extract never
1459
- spliced back, an extract whose section moved under it, a heading a hand edit
1460
- deleted or added, a target that no longer matches the file, a reference file
1461
- that moved, a cycle count that disagrees with itself — each with a fix command
1462
- and the panel that can clear it. A hand-edited section is **reported and never
1463
- counted as a finding**: flagging it would teach people to stop editing their
1464
- own document. `orc doctor` gains a `doc-drifted` finding routed to Docs.
1465
-
1466
- #### And it remembers what you asked for
1467
-
1468
- This was a **data** gap, not a rendering one. `created_at` existed and
1469
- `orc doc show --json` never emitted it; `context.md` and `context-sources.md`
1470
- were files the CLI never opened; and what the user actually ASKED FOR, in order,
1471
- across every session, lived nowhere at all.
1472
-
1473
- - **`orc doc log` / `journal`** record and serve it. The journal merges four
1474
- sources into one chronological array with the provenance of every row attached
1475
- `recorded` (the user's own words, verbatim), `derived` (a cycle, a ship
1476
- record), `observed` (a section that turned `user-edited`) and **it never
1477
- invents an entry**: a cycle that ran with nothing logged renders as an explicit
1478
- gap, never a plausible reconstruction from file mtimes. The `/orc-pact`
1479
- UNCHECKABLE rule: not knowing is an answer, and faking it teaches people to
1480
- distrust the rows that are real.
1481
- - **`orc doc context`** returns the frozen brief — the verbatim request first,
1482
- because that is the memory-regain payload plus the D2 reference table with a
1483
- live state per file: `ok`, `MISSING`, `SOURCE-DRIFTED`. A source is stale
1484
- only when THAT FILE moved, never because the repository did, and it is a
1485
- **warning, never an error**: a frozen context is *supposed* to be old.
1486
- - **`orc doc read`** is a reader for the HUMAN — and the rule table says out
1487
- loud that the orchestrator never runs it, registered as a contract token so
1488
- the sentence cannot quietly disappear.
1489
- - **The Docs panel is rebuilt around this: MEMORY FIRST, state second.** The
1490
- header strip, the brief, the reference files and the journal come before the
1491
- ribbon because a user coming back after three weeks did not come back to ask
1492
- what state the document is in.
1493
-
1494
- #### One more way in
1495
-
1496
- D4 and D5 gain a `RETURN-TO` suspend into **`/orc-grill`** gated on all
1497
- three of the `_shared/lane-suspend.md` tests (a DECISION not a fact, a
1498
- PREREQUISITE that changes the option set, a SUBTREE with more than one question
1499
- hanging off it), or it asks inline. The snapshot is **run state, never the
1500
- deliverable**, so hard rule 10 still holds; and on resume the lane re-writes
1501
- `.current` and touches the trace file in the same step, because `/orc-grill`
1502
- deleted the pointer at its own `FINISH`. Two traces for one document is
1503
- correcttwo lanes ran.
1504
-
1505
- ---
1506
-
1507
- ### v0.48.0 a document long enough to end a session, written anyway _(2026-08-13)_
1508
-
1509
- **`/orc-doc`** writes the long document — a PRD, a TSD, a cross-team
1510
- collaboration agreement, a status report or a workflow/runbook — as portable
1511
- Markdown, and it survives the session that started it.
1512
-
1513
- Two contracts hold the lane together, and everything else serves them:
1514
-
1515
- > **The orchestrator never reads the document body.** It knows the document only
1516
- > through the CLI's derived section map and through what the agents it
1517
- > dispatched report back. **a lane that reads its own document** has broken this
1518
- > contract.
1519
-
1520
- > **The context is gathered once and frozen.** A resumed session reads
1521
- > `context.md` from disk; it never re-interviews the user for what session 1
1522
- > already settled. **a lane that re-asks a frozen question** has broken this
1523
- > contract.
1524
-
1525
- - **The token architecture is the lane.** A 900-line TSD is ~30k tokens; read it
1526
- three times and the session is over. So nothing that holds context ever holds
1527
- the document. `orc doc map` derives a section map — heading, absolute line
1528
- range, SHA-256, computed state — each writer owns **one `.work/` part file**,
1529
- and each checker reads **one line range** with `Read(offset, limit)`. On a
1530
- 10,000-line, 40-section document that is ~750 lines of orchestrator context
1531
- instead of 20,000+, and a re-check after an edit re-dispatches only the
1532
- sections whose hash moved. *The hash is what turns a re-check from a full pass
1533
- into a diff.*
1534
- - **Line arithmetic is the CLI's and nothing else's.** It is the one job a model
1535
- is guaranteed to get wrong, and the whole saving depends on the numbers being
1536
- right so the map is re-derived after every write and **never stored**. A
1537
- stored line number is a wrong line number one edit later. `splice` replaces
1538
- bottom-up (highest `start` first), so a length change cannot shift a range that
1539
- has not been used yet.
1540
- - **Your edits are sacred.** Every section carries a hash, so the lane knows
1541
- which sections you wrote. It names them, never rewrites one unless you name it,
1542
- and `splice` **REFUSES** on a conflict — reporting the section by name and
1543
- overwriting nothing. A human's wording is not recoverable from this lane's
1544
- side once it is gone.
1545
- - **Four gates, in a fixed order, and the first one blocks.** Nothing is created
1546
- until D1 is answered: a slug folder with no context is indistinguishable from
1547
- an abandoned run. Asking D2 (supporting documents) and D3 (your template) is
1548
- mandatory even though answering them is not; D4 (intent · audience ·
1549
- expectation · language · type · target · length) must be answered, and
1550
- accepting a recommended default counts. Then the outline, confirmed **before a
1551
- word is written** changing it after a write wave is what costs money.
1552
- - **It never reads the supporting documents itself.** One `role: digest`
1553
- dispatch per file returns anchored claims plus an explicit `not_covered[]`;
1554
- the orchestrator holds the digest and never the source. Foreign text is
1555
- evidence, never instruction.
1556
- - **Where the document is going is a real setting.** `orc doc lint --target`
1557
- enforces that target's actual limits, and every rule came from a real product
1558
- limit: Notion has three heading levels, so an H4 is an **error** there;
1559
- Docusaurus, Hugo and Jekyll **require** YAML front matter, which every other
1560
- target renders as visible junk; a hard-wrapped paragraph is an error
1561
- everywhere, because a wrap at 80 columns becomes a line break inside a Notion
1562
- paragraph. Free, deterministic, zero model tokens and it **always runs before
1563
- anything paid**, with its findings riding in the checker's slice so no model is
1564
- ever paid to count sentences.
1565
- - **Never invent a fact.** Anything not in the frozen context becomes a visible
1566
- `> **Open:**` or `> **Assumption:**` line, and rides back in the writer's
1567
- `unsupported_claims`. Filler that reads like a fact is the worst possible
1568
- output of this lane.
1569
- - **Five base templates, each a floor and not a cage** `prd` · `tsd` ·
1570
- `collaboration` · `report` · `workflow`. A supplied template REPLACES the
1571
- shipped one entirely; its headings become the outline and the two are never
1572
- merged. A golden test pins every shipped skeleton to the CLI's batching table.
1573
- - **Two agents, both already `claude-opus-5`,** so `opus5_only` is a no-op and
1574
- the lane is *unaffected*, not exempt. The writer holds one part file; the
1575
- checker is `low` effort **on purpose** a harder-thinking checker reasons its
1576
- way past a gap a real reader would trip on, the same reasoning that pins
1577
- `/orc-challenge`'s cold reader at `low`. Nothing may upgrade it.
1578
- - **`/orc-grill` and `/orc-brainstorm` gain a "write this up" exit**, so an
1579
- interview's settled decisions arrive as a pre-answered D1 and D4 and the user
1580
- only confirms. At handoff `/orc-doc` offers `/orc-challenge`in a separate
1581
- session, which is the separation `/orc-challenge`'s own contract already
1582
- enforces from the other side.
1583
- - **The `orc doc` CLI family** (13 subcommands, every read `--json`, every one an
1584
- exit-code contract), four config keys (`doc_max_lines_per_agent`,
1585
- `doc_max_parallel` with a **hard cap of 4**, `doc_language`, `doc_dir`), and a
1586
- **Docs panel** in `orc ui` whose ribbon draws the whole document in one
1587
- picture — one block per section, sized by its length and coloured by its state.
1588
- - Counts move: **skills 37 38 · commands 28 → 29 · agent files 44 → 46.**
1589
-
1590
- ---
1591
-
1592
- ### v0.47.0 the lane that refuses to produce _(2026-08-12)_
1593
-
1594
- **Every other lane in ORC — and nearly every other skill in the ecosystem —
1595
- produces. This one refuses to.** `/orc-challenge` grades a finished artifact,
1596
- writes down what is wrong, and then stops and makes the user go away and fix it
1597
- somewhere else. The stopping is not friction: **the separation is the measuring
1598
- instrument.**
1599
-
1600
- **The one-sentence contract: ORC judges, the user fixes, ORC re-judges — and ORC
1601
- never fixes what it judged.** A session that just wrote the fix will grade its
1602
- own homework and it will always pass. That registers as the third member of an
1603
- existing pair `a lane that answers its own interview question` (v0.42.0),
1604
- `a lane that picks its own favourite` (v0.45.0), and now **`a lane that fixes
1605
- what it judged`**. Same split every time: facts and findings are ORC's, the work
1606
- and the decision are the user's.
1607
-
1608
- **Rule 0 precedes every other rule: it never guesses the goal.** A finding is
1609
- only a finding relative to a goal the same TSD is *finished* for one purpose
1610
- and nowhere near done for another. A lane that assumes will attack the wrong
1611
- thing with total confidence, and every one of its findings will be *defensible*,
1612
- which is worse than being obviously wrong: the user spends three iterations
1613
- fixing what did not matter. So intake ASKS, in ONE round, for the goal, the
1614
- audience, what "done" means, the template, and where the fixed version will go —
1615
- and freezes them to `goals.md`. **`orc challenge init` has no default for
1616
- `--goal`, `--audience` or `--done-means`**, so a run that tried to skip the round
1617
- fails at the CLI by name instead of inventing a purpose. Every finding must name
1618
- which goal element it `serves`; one that cannot is **dropped**, which is the
1619
- mechanism that stops a large context window from reviewing the entire universe.
1620
-
1621
- **Three agents, and they are three different INSTRUMENTS, not three tiers.**
1622
-
1623
- - **`orc-challenge-reader-opus-5-low`** the cold read. Tools: `Read` and
1624
- nothing else. It is given the artifact and the audience line, never the goal,
1625
- and it answers questions FROM the artifact rather than reviewing it. Returns a
1626
- scored questionnaire (`8/12`). **`low` effort is a measurement choice, not a
1627
- cost one:** a harder-thinking reader reasons around exactly the gaps this
1628
- exists to find, so a stronger configuration is a WORSE instrument.
1629
- - **`orc-challenge-judge-opus-5-high`**grades against the frozen template and
1630
- goal. Its slice is **SEALED**: paths and finding ids only, never prose from the
1631
- session, never a diff summary, never "the user says they fixed #4". A fix is a
1632
- claim; a verdict is evidence. **It cannot declare a pass**`orc challenge
1633
- record` computes that, which removes leniency as a possibility.
1634
- - **`orc-challenge-advisor-opus-5-med`** — dispatched only on a FAIL (advice on a
1635
- passed artifact is invented work and it costs money). Twelve findings are
1636
- usually three causes: it groups them by root cause, orders them with the
1637
- dependency reason, and flags the ones that are really unmade DECISIONS. No
1638
- prose, no diffs handing over wording is fixing by another name.
1639
-
1640
- All three are already `claude-opus-5`, so `opus5_only` is a no-op here: zero new
1641
- pairs, no rename churn. The lane is **unaffected, not exempt**.
1642
-
1643
- **`orc challenge lint` the deterministic engine, and it costs zero model
1644
- tokens.** Structure against the frozen template (missing / out-of-order /
1645
- invented / empty-ceremony sections, table column drift, untagged code fences,
1646
- links and `file:line` anchors that do not resolve) plus prose (acronyms used
1647
- before they are defined, sentences over 25 words with a p50/p90 distribution, a
1648
- passive-voice percentage, curated idioms and phrasal verbs, ambiguous
1649
- quantifiers, bare-pronoun openers, placeholder markers, a Flesch–Kincaid
1650
- estimate). **Sentences are measured over PARAGRAPHS, not lines** a hard-wrapped
1651
- 43-word sentence is still a 43-word sentence, and splitting at the newline is how
1652
- a length check silently passes every wrapped document. Two honesty rules are
1653
- printed by the command itself: it is a SIGNAL, not a verdict, and it is
1654
- English-specific and heuristic. Its real payoff is that `lint.json` rides in the
1655
- judge's slice, so the judge never spends tokens counting. It is useful with no
1656
- cycle, no model and no ORC run at all: `orc challenge lint README.md`.
1657
-
1658
- **Conservationnothing evaporates.** Every finding from iteration N−1 appears
1659
- in N with exactly ONE outcome (`resolved` · `still-open` · `superseded` ·
1660
- `withdrawn` · `accepted`) and a reason; below 100% coverage the verdict is
1661
- malformed and `record` rejects it **naming the missing ids**. A silently dropped
1662
- finding is indistinguishable from a fixed one, and that is the classic way a
1663
- review cycle appears to converge. `record` also rejects an unknown carry id, a
1664
- reasonless withdrawal, an uncited supersede, an **ignored rebuttal**, and a
1665
- **silent dimension** `NOT-CHECKED` with a reason is allowed, silence is not.
1666
-
1667
- **Two escape valves, because a loop with no exit is a trap.** `orc challenge
1668
- accept <slug> <id> "reason"` the finding stops blocking immediately and stays
1669
- visible forever in the report with the reason; never automatic (the `/orc-pact`
1670
- retirement rule). `orc challenge rebut <slug> <id> "reason"` the next judge
1671
- must answer it explicitly, `withdrawn` with an admission or `upheld` with new
1672
- evidence, and a verdict that ignores it is rejected. Without it, one wrong
1673
- finding loops forever and the user's only move is to give up.
1674
-
1675
- **Convergence, not a cap.** There is deliberately no loop cap and no config key
1676
- for one: every other loop in ORC runs inside a single session and costs tokens
1677
- per turn, but here each turn is a separate human sitting down to work, and a cap
1678
- that refused on iteration 6 would be refusing to review a hard document. It
1679
- reports `stalled` instead once, with three honest options.
1680
-
1681
- **Seven states, all COMPUTED, none stored** `AWAITING-JUDGE`, `AWAITING-FIX`,
1682
- `AWAITING-RECHECK`, `PASSED`, `STALE-PASS` (honest, not a failure the
1683
- `UNCHECKABLE` precedent), `MISSING-REVISION`, and `TAMPERED` (a verdict file
1684
- changed after it was recorded: reported, never silently re-graded). Two flags
1685
- ride alongside rather than becoming states of their own, because a state that
1686
- means two things is a state that lies: `stalled` and `no_template`.
1687
-
1688
- **The resumed session never asks where the fix went.** `revision_mode` is
1689
- declared at intake and restated in a `Where to put the revised version` block in
1690
- every fix brief; `orc challenge diff` resolves the expectation first and then
1691
- reports which carried findings the change actually TOUCHED
1692
- coverage-relative, the `computeWikiFreshness` lesson applied to findings, and a
1693
- hint for the human that is **never an input to the judge**. When the declared
1694
- path is not there, `MISSING-REVISION` **lists candidates and never adopts one**:
1695
- picking the closest-looking file would point the judge at the wrong artifact and
1696
- produce a page of confident, useless findings. The escape (`orc challenge expect
1697
- --set`) is a recorded command.
1698
-
1699
- **The CLI half: 12 subcommands, every read with an exit-code contract and
1700
- `--json`.** `list` (0/1/3) · `status` (0/1/2/3) · `show` · `diff` (0/1/2/3) ·
1701
- `expect` · `lint` (0/1/2) · `outline` · `record` (the GATE, not a store) ·
1702
- `accept` · `rebut` · `template`/`goals` (re-freezing is a recorded event that
1703
- needs a reason, and prior iterations keep their stamp) · `report` (derives
1704
- `CHALLENGE.md`, plus the final report on a pass). `challenge.json` has exactly
1705
- one writer, and it is never a model.
1706
-
1707
- **The `orc ui` Challenge panel** renders it and decides nothing about it: the
1708
- goal block above everything, the state chip with its ONE next action inline, an
1709
- iteration timeline whose **geometry is solved from the box size** (with a dashed
1710
- version break wherever a goal or template was re-frozen), the convergence chart
1711
- stacked by severity, a dimension strip where `NOT-CHECKED` keeps its slot and
1712
- carries its reason, the cold reader's score, and the findings with their accept /
1713
- rebut buttons. **A free action gets a button, a paid action gets a copy-able
1714
- command**running an iteration has no write route at all. `--fixtures` carries
1715
- one of every state including the ugly ones, and a test asserts it.
1716
-
1717
- **Four config keys**, all `common`: `challenge_pass_severity` (default `p1`),
1718
- `challenge_stall_after` (3), `challenge_reader` (`on`; `off` makes D4 report
1719
- `NOT-CHECKED` with that reason, never silently), and `challenge_gate` (`warn`;
1720
- there is deliberately no `block` — the `/orc-pact` precedent). Deliberately NOT
1721
- added: a same-session escape hatch (that is how the premise dies), any model or
1722
- effort key, and any loop cap.
1723
-
1724
- **Seams:** `/orc` prints one preflight line when it is about to build from a
1725
- document that has not passed its own review; `/orc-analyze` prints the cycle
1726
- state at Phase A (the two compose in one order challenge it, then analyze it);
1727
- `/orc-pact` gains the finding-that-is-really-a-decision harvest; intake's "I
1728
- don't know yet" suspends into `/orc-grill` and comes back; `/orc-export` can
1729
- carry a PASSED cycle as portable evidence.
1730
-
1731
- **Trace:** lane `challenge`, **Iterative tier** (one packet per completed
1732
- iteration), and a new `CHALLENGE iter=…` verb whose line the CLI assembles so
1733
- nothing composes a second wording for the same number. Several trace files for
1734
- one cycle is CORRECT several sessions ran.
1735
-
1736
- ### v0.46.1 see a lane run before you pay for one _(2026-08-12)_
1737
-
1738
- **The docs answered "what is ORC" four times and never answered "what does a
1739
- lane look like when it runs".** Rides on top of v0.46.0, below.
1740
-
1741
- **`mock-run/` one written walkthrough per lane.** What you type, what ORC
1742
- prints back, what lands on disk, in easy English, all on one shared example
1743
- project. Nothing was executed to make them: they exist so nobody has to spend
1744
- tokens to find out what a command does. Start at `mock-run/INDEX.md`.
1745
-
1746
- **`orc mock-run list | show <slug>`** reads the same catalogue from the
1747
- terminal, and **`orc ui` grows a Mocked Skill Use panel** every walkthrough,
1748
- grouped, searchable, with a reading pane. The catalogue is DERIVED from the
1749
- files on disk (title from the heading, lane from whether the command really
1750
- exists), so adding a walkthrough needs no list edited anywhere; the panel
1751
- renders it and decides nothing about it, exactly like the Flow stepper.
1752
-
1753
- **The README is 928 lines shorter and current.** It was still describing an
1754
- older payload the six v0.46.0 lanes were missing from the panel list, the
1755
- config table showed 11 of 52 keys, and the eval section quoted a round from four
1756
- releases ago. History moved here to `CHANGELOG.md`, which is now what `orc
1757
- changelog` fetches: a README carrying one entry would have answered a user ten
1758
- releases behind with a single line. The detail that used to bloat it lives in
1759
- `guides/configuration.md` and `guides/model-selection.md`.
1760
-
1761
- **Two real bugs found while building it.** The panel's markdown renderer looped
1762
- forever on a malformed table row (the paragraph branch is the fall-through, so a
1763
- line every branch declined never advanced the cursor), and an upgrade modal
1764
- showed the newest release with `## Earlier releases` glued to the end of it —
1765
- an entry now stops at the next section heading, not just at the next release.
1766
-
1767
- ---
1768
-
1769
- ### v0.46.0 a lane that remembers, a lane that declines, and a lane that measures _(2026-08-10)_
1770
-
1771
- **The ecosystem has a thousand skills that GENERATE.** This release builds the
1772
- three things a generator structurally cannot be, plus the wiki work that pays for
1773
- them and the panels that make them visible. Six new lanes, one new agent, and the
1774
- biggest cost cut available to ORC so far.
1775
-
1776
- **`/orc-pact` the lane that remembers.** `/orc-grill` and `/orc-brainstorm`
1777
- already settle constraints, and a plan already carries them into every executor
1778
- slice. Then the run ends and they evaporate. The pact is a ledger that outlives
1779
- the run, with four states that are **computed on read, never stored**: HOLDING,
1780
- **DRIFTED** (commits since it was verified touched the files it anchors —
1781
- coverage-relative, so a promise about payments does not fall into doubt because
1782
- the README changed), **UNCHECKABLE** (nothing cheap proves it the honest state,
1783
- and it never counts against you), and BROKEN. It never invents a promise: every
1784
- entry records where it came from. It never retires one for you. And the payoff is
1785
- automatic at planning time, a drifted promise whose files your plan is about to
1786
- touch is injected into the planner as a constraint, so last month's decision
1787
- constrains this month's work. `PACT.md` is a committed, PM-readable file at your
1788
- project root, rendered by the CLI from the ledger so the two can never disagree.
1789
-
1790
- **`/orc-boundary` — the lane that declines.** Every skill you can install assumes
1791
- the answer to *"should the agent do this?"* is yes; agents spend 5×–50× longer
1792
- than human experts on a task, and most of the excess goes into attempts that were
1793
- never going to succeed. Three verdicts per area EXECUTE, ESCALATE, REFUSE — each
1794
- derived from four questions answered from things already on disk: can it verify
1795
- itself, does it know this area, is the change reversible, is this a decision
1796
- rather than a fact. **A REFUSE always names what would make it a yes** — "no" with
1797
- no "unless" is a shrug, so a refusal with no checklist is treated as a malformed
1798
- card. It gates ORC's own dispatch, never you: `boundary_gate: block` lifts a
1799
- refused task out of its wave and **the wave still runs the rest**.
1800
-
1801
- **`/orc-handoff` — the first ORC lane for someone who does not read code.** The
1802
- insight nobody shipped: the safety grade does not come from the file type, it
1803
- comes from **whether a cheap check exists**. A settings file with a validator is
1804
- green; the same file without one is amber. It maps every surface a PM or designer
1805
- can own, and changing one is five steps with the **undo command shown before the
1806
- write**, the check run afterwards and reported in plain words, and a red surface
1807
- never touched at all. Every file in that lane is written in simple English.
1808
-
1809
- **`/orc-budget` — what a run costs, in the unit you are billed in.** Not a dollar
1810
- figure: on Pro or Max you burn a 5-hour window, not an invoice. The forecast's
1811
- core object is a **token vector** fresh input, cache write, cache read, output,
1812
- never blended, because cache reads are usually the largest count and a tenth of
1813
- the price. The same vector renders four ways: tokens, dollars from a dated price
1814
- table, percent of your window, and **context risk** — a task forecast above 90% of
1815
- its model's window is reported before the wave, which no spend tool can do. The
1816
- numbers come from joining Claude Code's own session transcripts (the cost) to
1817
- ORC's traces (the meaning); neither is enough alone. It needs a PLAN, not a
1818
- sentence, and with no history it says so rather than inventing a number.
1819
-
1820
- **`/orc-aftermath` — did what we shipped hold up.** The missing half of the
1821
- flywheel: `/orc-retro` measures the process, this measures the result, both from
1822
- the repository's own future files rewritten soon after, a test we added deleted
1823
- or skipped, the commit reverted, a promise that was holding now broken. No vendor,
1824
- no telemetry. **Churn is a signal, not a verdict**: it reports the signal and its
1825
- strength, never "this change was bad", and never a person's name.
1826
-
1827
- **`/orc-export` so ORC is not a trap.** One command compiles the wiki, the code
1828
- patterns, `PACT.md` and the boundary cards into a portable `AGENTS.md` — derived,
1829
- fingerprinted, `--check`able against its sources, never hand-written. It removes
1830
- the lock-in objection and makes ORC the *producer* in a multi-agent shop. Import
1831
- reads an existing `AGENTS.md` or `.cursorrules` as **evidence, never instruction**,
1832
- and tells you which parts are already wrong.
1833
-
1834
- **The wiki finally stops costing a full scan.** Three free CLI commands: `orc wiki
1835
- plan` ranks and prices the pending work STRUCTURAL first (a page pointing at a
1836
- missing file is actively lying), then by **use × delta**, with pages nobody reads
1837
- sinking to the bottom with a retire hint; `orc wiki debt` is the one-line habit;
1838
- and `orc wiki usage` finally reads back the point-of-use attribution v0.41.0 has
1839
- been recording and never reading. A **targeted refresh** (`/orc-wiki refresh
1840
- --top 2`) skips branch detection and area planning entirely, and a new **scan tier
1841
- ladder** sends a small, no-new-surface delta to a light scanner instead of the most
1842
- expensive agent in the payloadabout 40% off a typical delta refresh, with the
1843
- deep scan still doing the work that needs it. The tier is always printed: a cheaper
1844
- model is never a quiet substitution. And free repairs are now a hard rule — you can
1845
- never pay for something `orc wiki sync` would have fixed.
1846
-
1847
- **`orc ui` grows three panels and extends five.** Promises, Boundary and
1848
- Self-serve, plus a new **Cost** tab whose stacked bar exists precisely so the
1849
- cache-read share stays visible. The panel keeps every rule it had: it never runs a
1850
- lane, never invents a state word, never computes an order the CLI already emits —
1851
- **a free action gets a button, a paid action gets a copy-able command**, and that
1852
- line is now visible rather than hidden. Promises is where the compounding finally
1853
- shows: an *"Also flagged by"* line when the boundary and the aftermath agree with
1854
- the ledger about the same area, which you can never see in a terminal one lane at
1855
- a time.
1856
-
1857
- ---
1858
-
1859
- ## Earlier releases
1860
-
1861
- ### v0.45.0 `/orc-brainstorm`: for when you do not have the idea yet _(2026-08-10)_
1862
-
1863
- ### v0.44.1 apply when you say so, and a spotlight that survives a banner _(2026-08-09)_
1864
-
1865
- ### v0.44.0 the panel stops making you type what it already knows _(2026-08-09)_
1866
-
1867
- ### v0.43.7 — the flow you can see, and a boundary you can read _(2026-08-09)_
1868
-
1869
- ### v0.43.6 — `orc ui` in two languages, and panels that point at the right page _(2026-08-08)_
1870
-
1871
- ### v0.43.5 the update check works, and the UI teaches itself _(2026-08-08)_
1872
-
1873
- ### v0.43.4 a warning that finally clears, an Experiment panel, crosslink from the UI _(2026-08-08)_
1874
-
1875
- ### v0.43.3 `orc ui`: it tells you about updates, and 36 keys stop being a wall _(2026-08-08)_
1876
-
1877
- ### v0.43.2 `orc ui`: boxes stop colliding, because the container owns the gap _(2026-08-08)_
1878
-
1879
- ### v0.43.1 the panel's stylesheet and script actually reach the browser _(2026-08-08)_
1880
-
1881
- ### v0.43.0 `orc ui`: a control panel for everything that is not ai _(2026-08-08)_
1882
-
1883
- ### v0.42.0 Say what you mean, see what it costs, find your way back _(2026-08-08)_
1884
-
1885
- ### v0.41.0 A wiki that can tell you it is fresh, and TDD only where it can fail _(2026-08-06)_
1886
-
1887
- ### v0.40.0 Gotchas: repair memory that outlives the run _(2026-08-06)_
1888
-
1889
- ### v0.39.0 — The read ladder, and foreign input that is evidence rather than instruction _(2026-08-06)_
1890
-
1891
- ### v0.38.1`orc doctor --json` + handoff carry-over that says what is re-derived _(2026-08-06)_
1892
-
1893
- ### v0.38.0 `/orc-quick`: the quick lane, and the gate no config can collapse _(2026-08-05)_
1894
-
1895
- ### v0.37.0 Stacked pull requests: a measured ship gate + two standalone lanes _(2026-08-03)_
1896
-
1897
- ### v0.36.0 — `opus5_only`: one model for every role, not just executors _(2026-08-02)_
1898
-
1899
- ### v0.35.0 `opus5_executor_only`: one model, effort as the cost dial _(2026-08-02)_
1900
-
1901
- ### v0.34.8 `orc pattern status` rejects a language key the payload has never heard of _(2026-08-01)_
1902
-
1903
- ### v0.34.7 — DIY: a usable status contract, and compile docs that match the compiler _(2026-08-01)_
1904
-
1905
- ### v0.34.6 Analyze: the evidence gate now covers the rows a good analysis produces _(2026-08-01)_
1906
-
1907
- ### v0.34.5 Wiki: stop losing tags silently, let a delta clear its own delta _(2026-08-01)_
1908
-
1909
- ### v0.34.4 Planner: scorable facets, and TDD rules scoped to reality _(2026-08-01)_
1910
-
1911
- ### v0.34.3 — Slice boundary: the worktree, not the editor _(2026-08-01)_
1912
-
1913
- ### v0.34.2 Trace subsystem: the pointer clobber, and a writer contract that holds _(2026-08-01)_
1914
-
1915
- ### v0.34.1 Install integrity: run state survives `orc update` _(2026-08-01)_
1916
-
1917
- ### v0.34.0 Opus 5: top scoring band, every core role, medium-effort session tier _(2026-07-25)_
1918
-
1919
- ### v0.33.0 Knowledge deepening + verification revamp _(2026-07-25)_
1920
-
1921
- ### v0.32.0 Trace revamp: narration is dispatched, not remembered _(2026-07-24)_
1922
-
1923
- ### v0.31.0 Execution-integrity revamp: plan handoff, attributable traces, facet scoring _(2026-07-23)_
1924
-
1925
- ### v0.30.0 Scoring revamp, Fable 5 role override, tier-aware guards, `orc onboarding` _(2026-07-23)_
1926
-
1927
- ### v0.29.0 Drift-prevention hardening: install manifest + prune, `orc doctor`, a real test suite _(2026-07-22)_
1928
-
1929
- ### v0.28.1 Defect fixes: package encoding, trace event routing, count/doc drift _(2026-07-22)_
1930
-
1931
- ### v0.28.0 Run integrity: rich full-lane traces, deterministic wave stop, visible knowledge gates _(2026-07-21)_
1932
-
1933
- ### v0.27.0 `/orc-poly`: plan one change across two-or-more repos without drift _(2026-07-20)_
1934
-
1935
- ### v0.26.0 Test-gen output pinned to a visible `test-generator/<change-slug>/` deliverable _(2026-07-19)_
1936
-
1937
- ### v0.25.1 Eval report: the full 17-lane suite graded against the v0.25.0 payload _(2026-07-18)_
1938
-
1939
- ### v0.25.0 Deterministic artifact detection: a generated wiki/pattern is never missed _(2026-07-18)_
1940
-
1941
- ### v0.24.0 — Crosslink fused into wiki generation: always-on, per-scan-task, never wiped _(2026-07-18)_
1942
-
1943
- ### v0.23.0 — Trace fix: SPAWN restored on the `Agent` tool, stale runs rotate to fresh files _(2026-07-18)_
1944
-
1945
- ### v0.22.0 `/orc-learn`: per-feature onboarding docs learning.md + knowledge.md, wiki-deep, git-ignored _(2026-07-17)_
1946
-
1947
- ### v0.21.0 Statusline shows live subscription usage: 5h weekly, official numbers _(2026-07-16)_
1948
-
1949
- ### v0.20.0 One source of truth: generated executor agents + shared cross-lane contracts _(2026-07-16)_
1950
-
1951
- ### v0.19.0 Thin spines: skill compaction, budget lint, and a trace that logs every phase _(2026-07-16)_
1952
-
1953
- ### v0.18.0 `orc wiki sync`: the wiki registers itself — a paused scan is no longer an invisible wiki _(2026-07-15)_
1954
-
1955
- ### v0.17.3 — Trace the wiki consult: Phase 1 now logs whether the run grounded in the wiki (and if it was stale) _(2026-07-14)_
1956
-
1957
- ### v0.17.2 Behavior-trace logging is permanent + the trace folder is now created deterministically _(2026-07-14)_
1958
-
1959
- ### v0.17.1 Complete cross-repo crosslink setup guide in the orc-wiki README _(2026-07-14)_
1960
-
1961
- ### v0.17.0 `orc crosslink`: cross-repo wiki references — advisory boundary contracts _(2026-07-14)_
1962
-
1963
- ### v0.16.1 Interactive `orc diy` composer + numbered picks in `orc config` _(2026-07-14)_
1964
-
1965
- ### v0.16.0 `/orc-diy`: build your own lane CLI-composed flow, compiled, hard-gated _(2026-07-14)_
1966
-
1967
- ### v0.15.0 Wiki v2: evidence-anchored docs · per-file staleness registry · integrity gate _(2026-07-14)_
1968
-
1969
- ### v0.14.0 Postgres data-access playbook: cross-cutting query grounding _(2026-07-13)_
1970
-
1971
- ### v0.13.0 `/orc-claude`: local CLAUDE.md builder fenced sections, fingerprint refresh, zero questions _(2026-07-12)_
1972
-
1973
- ### v0.12.0 Lossless context-combiner: conservation gate · overlap taxonomy · evidence freshness _(2026-07-12)_
1974
-
1975
- ### v0.11.0 `/orc-fast`: knowledge-gated speed lane + wiki freshness infrastructure _(2026-07-12)_
1976
-
1977
- ### v0.10.1 — README: a fuller "Why ORC exists" _(2026-07-12)_
1978
-
1979
- ### v0.10.0 — `/orc-ultra`: max-effort advisor + three judgment gates for ultra-complex work _(2026-07-12)_
1980
-
1981
- ### v0.9.0 — Trust-but-verify the analyst→planner chain: quote-anchored evidence · coverage gate · anchored judgment _(2026-07-12)_
1982
-
1983
- ### v0.8.1/orc-retro delivers upstream: PR/issue to the ORC repo, channel-gated _(2026-07-12)_
1984
-
1985
- ### v0.8.0Close the loop: grounded intake · scoring anchors · OUTCOME marker · /orc-retro trace miner · eval harness _(2026-07-12)_
1986
-
1987
- ### v0.7.0 — Evidence everywhere: grounded plans · verbatim proof · anchored findings · contract lint · trace fixes _(2026-07-12)_
1988
-
1989
- ### v0.6.0P0–P3 ladder · house rules · deep playbooks + wired gates · 3 new languages · FE rule packs · security pass _(2026-07-11)_
1990
-
1991
- ### v0.5.1Statusline false-degrade fix _(2026-07-11)_
1992
-
1993
- ### v0.5.0Code-pattern findings: executors match your house style, invariants always enforced
1994
-
1995
- ### v0.4.5Rewrite weak worker descriptions (the real score lever)
1996
-
1997
- ### v0.4.4Act on external review: raise sub-70 workers, fix cross-spine paths
1998
-
1999
- ### v0.4.3 — `orc-analyze`: trim description under the 1024-char skill-spec limit
2000
-
2001
- ### v0.4.2External-review pass: worked examples + sharper mini-analyst activation
2002
-
2003
- ### v0.4.1 — `orc-mini`: faster, safer fast-lane smoke gate, opt-in tests, trimmed ceremony
2004
-
2005
- ### v0.4.0 — Opt-in Phase 6.5 Test Authoring (writes test cases, never runs them)
2006
-
2007
- ### v0.3.0 — Opt-in behavior-trace logging + claimed-vs-actual model verification
2008
-
2009
- ### v0.2.4`orc-analyze`: gather anchored adjacent-scope context (non-actionable)
2010
-
2011
- ### v0.2.3Context Combiner: merge 2+ related analyses into one combined spec
2012
-
2013
- ### v0.2.2Config: enforce per-key override-first resolution
2014
-
2015
- ### v0.2.1Move config editing into the `orc config` CLI (zero-token); drop `/orc-config`
2016
-
2017
- ### v0.2.0 — Doc-optional evidence-backed analyst + deep mode
1
+ # Changelog
2
+
3
+ All notable changes to ORC, newest first.
4
+
5
+ The **latest release** is also summarised in the [README](README.md#changelog).
6
+ This file is the full history, and it is the file `orc changelog` reads — that
7
+ command prints only the entries **newer than the version you have installed**.
8
+
9
+ Format: `### v<version> — <title> _(<date>)_`.
10
+
11
+ ---
12
+
13
+ ### v0.56.0 - a rename moved the command, and nobody could reach the fix _(2026-08-27)_
14
+
15
+ **READ THIS FIRST IF YOUR `orc upgrade` IS FAILING.** If you are on a version
16
+ before v0.56.0, this release cannot install itself - your `orc upgrade` is the
17
+ OLD one and it fails the same way every other route does. Run these three lines
18
+ once, by hand, and you are across for good:
19
+
20
+ - **Step 1 - release the command from the old package:** `npm uninstall -g orc`
21
+ - **Step 2 - install the current package:** `npm i -g @azure-id/orc`
22
+ - **Step 3 - re-apply it to your project:** `orc update` (add `--global` to also
23
+ refresh `~/.claude`)
24
+
25
+ Then check it worked: `orc version` should print 0.56.0 or newer, and
26
+ `orc doctor` should no longer mention `legacy-global-package`. Nothing in your
27
+ `.claude/` is touched by any of this, and your `orc.config.yaml` survives.
28
+ **Do not use `npm i -g -f`** - `--force` overwrites the command file and leaves
29
+ the old package installed underneath, owning nothing and never updated again.
30
+ From v0.56.0 onward `orc upgrade` does all three steps for you, announced.
31
+
32
+ **The package moved from the unscoped `orc` to `@azure-id/orc`, and every
33
+ upgrade path in the field died at once.** Both names declare the same `orc` bin.
34
+ npm links a bin only if the shim is unowned or owned by the installing package,
35
+ so with the old `orc` package still on disk globally, installing the new scoped
36
+ one failed with `EEXIST` on the command file itself. That error is about a FILE,
37
+ not a source - which is exactly why swapping sources changed nothing: the
38
+ tarball, the `github:` spec and the registry all failed identically, `orc
39
+ upgrade` walked all three and then printed npm's error wall, and `orc ui`'s
40
+ upgrade action did the same. `npm i -g -f` was the only thing that "worked", and
41
+ only by overwriting the command file and leaving the superseded package
42
+ installed underneath as a ghost that owns nothing and is never updated again.
43
+
44
+ - **The legacy package is EVICTED BEFORE any source is tried.** `orc upgrade`
45
+ now looks for a globally-installed package that is not this one and whose
46
+ `bin` declares `orc`, and uninstalls it first. Ordering is the point: the
47
+ collision fails every source identically, so walking the ladder first only
48
+ spends three network round trips arriving at the same `EEXIST`. It is
49
+ announced, never silent - it is a global npm mutation on the user's machine,
50
+ and the only one ORC makes for them.
51
+ - **Detection is by OWNERSHIP, never by directory name.** A directory called
52
+ `orc` that holds THIS package is not legacy, and a package that declares no
53
+ `orc` bin blocks nothing. A machine that never saw the rename land must not
54
+ have its working install uninstalled.
55
+ - **`--force` survives, scoped to the one case it is right for.** If a
56
+ collision remains after the eviction there was nothing to uninstall - an
57
+ ORPHANED shim npm left behind with no package owning it. `--force` overwrites
58
+ a file that belongs to nobody, which is the case it exists for.
59
+ `isBinShimCollision` requires the `EEXIST` code AND a path component that IS
60
+ the bin name, so it never reaches for `--force` on an unrelated `EEXIST`
61
+ deeper in a dependency tree.
62
+ - **The npm REGISTRY is now tried first**, then the tarball, then the `github:`
63
+ spec. The registry resolves a VERSION rather than a branch tip; the `github:`
64
+ spec shells out to git and fails under restricted git / NVM, so it stays last.
65
+ `--from` and `ORC_INSTALL_SPEC` still win outright, and the remembered
66
+ `last_good_spec` still leads.
67
+ - **`freshCliPath()` resolves the SCOPED directory first.** It looked only under
68
+ `<npm root -g>/orc`, which after the rename is the LEGACY package - so on a
69
+ machine mid-rename it resolved a path that existed and step 2 re-applied the
70
+ very templates step 1 had just superseded. A hit is now accepted only if the
71
+ manifest there says the current package name: a directory that exists is not
72
+ proof of identity.
73
+ - **`orc doctor` reports it by name.** `legacy-global-package` is the one
74
+ finding that explains why `orc upgrade` cannot fix anything else in the
75
+ report. It is deliberately NOT `--fix`-able: `orc doctor --fix` is scoped to
76
+ this project's `.claude/`, and evicting a global npm package is neither
77
+ project-scoped nor something to do without saying so - so its `fix_command`
78
+ points at `orc upgrade`, which does it announced. `FINDING_ROUTE` sends it to
79
+ Maintenance, where the upgrade action is.
80
+ - **A CAUTION at the top of the README carries the one-time manual fix**, because
81
+ the fix cannot reach the people who need it most: a user still on the old
82
+ package does not have this code, so their `orc upgrade` still fails. Two lines
83
+ (`npm uninstall -g orc` then `npm i -g @azure-id/orc`) get them across once,
84
+ and from here `orc upgrade` handles it.
85
+
86
+ ---
87
+
88
+ ### v0.55.2 - a gate that is never probed is a gate that is always off _(2026-08-27)_
89
+
90
+ **`/orc-quick` and `/orc-fast` documented the foreign-worker option and then
91
+ never went and looked for it.** Both lanes carried the full `orc extra` slot
92
+ contract - the menu line, the dispatch call, the failure path - but neither
93
+ preflight ever RAN the probe that answers whether a position is held. orc-quick's
94
+ Q0 said "read `log_dir` only, read no other key"; orc-fast's F0 had gates a, b
95
+ and c and no extra step, while the F2 prose claimed the `extra:` line "joins the
96
+ F0 preflight". So a user who armed `extra_enabled` and set
97
+ `orc extra role set quick-executor ds/deepseek-chat` was still offered the two
98
+ shipped Claude executors and nothing else, with no way to tell configuration
99
+ from a bug.
100
+
101
+ - **orc-quick Q0 gains one PROBE**, named as the single exception to
102
+ "read no other key": `orc extra resolve --slot quick-executor --json`. One
103
+ command answers the master gate, the position and the routing together, so the
104
+ code-writing menu can render line 3. It is still an OPTION - never a default,
105
+ never sticky, re-asked after a failure.
106
+ - **orc-fast F0 gains gate `d`**, a probe rather than a gate:
107
+ `orc extra resolve --slot fast-executor --json`. Resolved `extra` prints the
108
+ P0 `extra:` line where the prose always said it would, naming the agent it
109
+ displaces (`orc-executor-sonnet-4-6-high`); resolved `claude` prints nothing
110
+ and never falls back - no row on a slot is an ANSWER, not a gap.
111
+ - **`/orc-doc` was never affected.** Its targets are resolved by
112
+ `docExtraResolve` inside `orc doc next`, so the CLI computes them and no
113
+ preflight step can forget to ask. That is the shape the other two now borrow.
114
+
115
+ No CLI change, no config key, no agent change.
116
+
117
+ ### v0.55.1 ORC is on npm _(2026-08-27)_
118
+
119
+ **ORC is published as [`@azure-id/orc`](https://www.npmjs.com/package/@azure-id/orc).**
120
+ The GitHub tarball still works and nothing about the payload changed no skill,
121
+ no agent, no CLI behaviour moved. This is the install path getting a name.
122
+
123
+ - **`npm i -g @azure-id/orc`** is the install, and
124
+ **`npm i -g @azure-id/orc@latest`** is the update. `orc upgrade` already
125
+ fetched the newest package and then applied it, and it continues to;
126
+ `orc upgrade --from @azure-id/orc` names npm explicitly.
127
+ - **The GitHub tarball is the fallback now**, not the headline kept in the
128
+ Quick start behind a fold for forks and for anyone pinning a branch.
129
+ - **`orc update` is unchanged**: it re-copies the package you already have and
130
+ never touches the network, so `npm i -g @azure-id/orc@latest && orc update`
131
+ is the manual spelling of `orc upgrade`.
132
+
133
+ ---
134
+
135
+ ### v0.55.0 a score is what a band needs, and four lanes do not have one _(2026-08-26)_
136
+
137
+ **A score is what a band needs, and four lanes do not have one.** `/orc-quick`,
138
+ `/orc-fast`, `/orc-doc` and `/orc-wiki` pin an agent to a POSITION rather than
139
+ scoring a task. `orc extra` routed them anyway by resolving the pinned agent's
140
+ score band at both edges, which is arithmetic on a number nobody chose.
141
+
142
+ It was wrong twice and dead once. A document set to `checker` resolved the
143
+ **writer's** band for a role it was not routing. `/orc-wiki` asked for a role
144
+ named `scanner` that `extra_roles` refuses by name, so that lane could never
145
+ route however it was configured `orc extra lanes` printed `claude` forever,
146
+ with a reason that read like a user's choice. And `orc extra dispatch` required a
147
+ `score` unconditionally, so **no non-scored dispatch had ever reached the bridge
148
+ at all** — not the fence, not the journal, not the spend log.
149
+
150
+ - **`orc extra role` holds six POSITIONS**: `quick-executor` · `fast-executor` ·
151
+ `doc-writer` · `doc-checker` · `wiki-scanner-deep` · `wiki-scanner-light`. One
152
+ named position, one chosen `profile/model`, and **a row's presence is the
153
+ arming**. `list` prints all six always an unrouted position keeps its slot
154
+ and reads as the Claude agent it falls through to, because "I left the checker
155
+ on Claude on purpose" and "there is no checker" must never look the same.
156
+ - **A second resolver that never touches a band.** `orc extra resolve --slot
157
+ <slot>` is the sibling of the score shape, same answer, same exit codes, and
158
+ the Claude answer it carries is a **pinned NAME rather than an interval** —
159
+ strictly more honest than what the scored half can offer. Nine hold-backs, each
160
+ answered by name; a cited risk is never invented for a lane that has none.
161
+ - **Precedence, one sentence for both shapes:** extra decides *whether* a Claude
162
+ agent runs at all; `opus5_only` and the score tables only decide *which* Claude
163
+ agent runs where extra did not take it. Under a taken slot `opus5_only` is **not
164
+ consulted** and it stays fully live for every position with no row. `orc
165
+ config list` and `orc config set` now name the taken POSITIONS beside the taken
166
+ bands.
167
+ - **The bridge accepts a slot.** Exactly one of `score` or `slot`; both is
168
+ refused by name; `band` becomes `slot:<slot>` so the trace parser, the
169
+ eight-field dedupe and `orc extra stats` are untouched and each position gets
170
+ its own cost row for free. **Zero new engines, zero new dispatch paths, zero new
171
+ agents** — the fence, the cap, the credential triangle, the journal, the spend
172
+ log and the resume ladder all come along unchanged.
173
+ - **Per lane:** `/orc-doc` resolves each role against its OWN slot and `orc doc
174
+ next` names the model per role before the wave (a document's voice is the
175
+ deliverable); `/orc-wiki` prints its target beside the tier it already prints;
176
+ `/orc-fast` names the agent it displaced in the F0 line; **`/orc-quick` gets a
177
+ THIRD OPTION on its menu** never a default, never sticky, re-asked after a
178
+ failure, because that gate's whole premise is asking.
179
+ - **`orc ui Extra Routing` grows a second ladder** below the bands, and
180
+ **zero config keys were added** a second master gate, per-lane switches,
181
+ `extra_quick_ask` and a per-slot model key were all considered and are written
182
+ down as refused.
183
+
184
+ ---
185
+
186
+ ### v0.54.0 a failed dispatch is a POSITION, not a blank page _(2026-08-25)_
187
+
188
+ **A worker on another model wrote six of seven lines and lost its connection.
189
+ ORC sent the same task to Claude from scratch onto a file that was already
190
+ two-thirds written.**
191
+
192
+ `orc extra` had exactly one recovery move: re-dispatch the SAME slice to the
193
+ Claude band. That move assumes the worktree is where the dispatch found it. **It
194
+ usually is not.** The replacement executor's three plausible moves were all
195
+ wrong: `Write` the file whole and discard work you already paid for · `Edit`
196
+ against a stale mental model so `old_string` does not match and it improvises ·
197
+ read first and then guess whether what is there is its own earlier work, a
198
+ teammate's, or garbage. No field in the slice could have told it, and no field in
199
+ the return contract could have carried it.
200
+
201
+ **The registered token, sixth in its family:** `a lane that re-does work the
202
+ worktree already contains` has broken this contract. It joins `a lane that
203
+ answers its own interview question`, `a lane that picks its own favourite`, `a
204
+ lane that fixes what it judged`, `a lane that picks its own council`, `a lane
205
+ that reads its own document`, and `a lane that sends work off Claude without
206
+ saying so`.
207
+
208
+ - **THE JOURNAL IS THE CLI'S, AND IT IS WRITTEN BEFORE THE FIRST BYTE LEAVES THE
209
+ MACHINE.** `.claude/orc/extra-journal/<task_id>/` — a header carrying HEAD,
210
+ `git status --short` in full and a hash plus a line count for every
211
+ `declared_files` entry; a progress log appended as the dispatch runs; a result
212
+ written beside the spend append. It is written by `orc extra dispatch` itself,
213
+ which is the **fourth** time this repo has chosen a written-by-the-CLI fact
214
+ over a relayed one (v0.32.0 narration, v0.49.5's hand-back page, v0.53.2's
215
+ spend log). No lane writes it, no lane can forget it, and it is best effort by
216
+ construction: a journal that cannot be written never takes the dispatch down.
217
+ The header is the only record of what the repository looked like before a
218
+ third party touched it, which is the only thing that makes a reconciliation
219
+ possible at all.
220
+ - **`orc extra reconcile <task_id>` — FREE, deterministic, and it runs before
221
+ anything paid.** Five states, five exit codes (0 `resumable` · 1
222
+ `nothing-to-resume` · 2 `no-journal` · 3 `complete` · 4 `in-flight`), and 0 is
223
+ the answer the command exists to give rather than "healthy". Per declared file:
224
+ `untouched` · `created` · `modified` · `deleted` · `reverted`, with line counts
225
+ where they can be computed EXACTLY and `null` where they cannot **unknown is
226
+ not zero**. Plus `touched_undeclared[]` (a fence breach, surfaced here because
227
+ a crashed dispatch is exactly when the worktree delta never ran), the last
228
+ recorded action, and the partial token vector.
229
+ - **It deliberately does NOT decide whether a file is finished.** No brace
230
+ counter, no truncation heuristic, no language sniffing /orc-doc's house-rule
231
+ boundary verbatim: the CLI cannot parse intent, so it does not pretend to, and
232
+ **a fake validator would be worse than none.** The checks that answer "is this
233
+ done" already exist and are already engine-blind. Reconciliation's job is to
234
+ point them at the right thing.
235
+ - **ATTRIBUTION whose fault it was, with the evidence.** Five verdicts, each
236
+ carrying a different correct recovery: `provider` · `network` · `local` ·
237
+ `worker` · `orc`. **`network` HOLDS THE WAVE** — a Claude fallback cannot
238
+ succeed when the machine has no network, so falling back would be a second
239
+ failure and a second cost for nothing. The two are told apart by ONE
240
+ unauthenticated 3-second request on a path that has already failed, made only
241
+ on the reasons that cannot be separated without it. `orc` is on the list on
242
+ purpose: a report about a third party with no way to blame its own author is
243
+ not a report anybody should trust — v0.53.3 was exactly an ORC bug that
244
+ presented as a bad key.
245
+ - **`orc extra resume-slice <task_id> --out <f>` composes the continuation, and
246
+ the CLI owns the wording.** It is a NEW DISPATCH OF A DERIVED SLICE through the
247
+ ordinary bridge zero new engines, zero new dispatch paths, **zero new
248
+ agents** so the fence, the concurrency cap, the credential rules, the spend
249
+ log and the worktree delta all come along unchanged. It **never widens
250
+ `declared_files`**, **never moves `acceptance[]`**, **never moves the score**
251
+ (a resume is not a discount), and **refuses on a drifted slice**, naming both
252
+ hashes.
253
+ - **Where a resume goes is DERIVED, never a config key.** Retryable the same
254
+ profile in a new session, up to `extra_resume_max`. Non-retryable the Claude
255
+ band, **still as a RESUME slice** which is what fixes the original bug: the
256
+ Claude fallback stops being a from-scratch dispatch, which it should never have
257
+ been. A key here would let somebody configure "always the same profile" and
258
+ then wait out the cap × a 401.
259
+ - **Six refusals, each NAMED, each writing NOTHING** (`not-resumable` ·
260
+ `in-flight` · `reverted-file` · `slice-drifted` · `resume-cap` ·
261
+ `resume-disabled`). **A live attempt is never resumed:** a dropped socket does
262
+ not prove a provider stopped streaming, so a resume is gated on the pid being
263
+ gone OR the lease having expired and past the lease a live pid is treated as
264
+ somebody else's process, stated as the honest bound it is rather than as proof.
265
+ **A `reverted` declared file blocks and names the paths:** resuming on top of a
266
+ possible destructive action is the one case where continuing is worse than
267
+ starting over, and ORC does not get to make that call.
268
+ - **Two new failure classes make the recovery choosable.** `stream-interrupted`
269
+ (the connection was established and then died `unreachable` means it never
270
+ opened, and those two want opposite recoveries) and `connection-lost-local`
271
+ (the same, with the probe also failing). A taxonomy that returned one word for
272
+ both could not pick either, which is why there was only ever one recovery.
273
+ - **JOURNAL FIDELITY IS DECLARED PER ENGINE and never rendered stronger than it
274
+ is.** `api` and `claude-shim` are `per-turn`; engine `cli` is
275
+ `streamed-opaque` — its child's stdout now goes to a FILE DESCRIPTOR rather
276
+ than a buffer in a parent that dies, so a wall-clock kill leaves the bytes on
277
+ disk and `output_file` stops being `null`. ORC captured them and did not
278
+ interpret them, and **a gap that is not reported reads as a capability**.
279
+ - **A killed dispatch's spend is recoverable.** `appendExtraSpend` runs after the
280
+ engine returns, so a killed parent left real money invisible to every cost
281
+ report the v0.53.2 hole through a different door. Reconcile writes the
282
+ journal's running vector once, idempotently, as `recovered: true, complete:
283
+ false`. **Measured is not unknown; unknown is not zero; a recovered vector is a
284
+ FLOOR and says so.**
285
+ - **Orphans are REPORTED at preflight and never resumed.** `orc extra preflight`
286
+ lists every journal with a header, no result and an expired lease — and does
287
+ **not** change its exit code, because an orphan is a finding, not a stop.
288
+ Silently continuing a third party's half-finished write into somebody's
289
+ repository is the same class of act as routing off Claude without saying so.
290
+ - **Reliability becomes a MEASURED property of a profile.** `orc extra stats`
291
+ gains per-profile `dispatches` · `failed` · `resumed` · `orphaned` · mean time
292
+ to failure · the attribution split, and **below 10 dispatches there is no rate
293
+ at all** a percentage from three tries is noise with a percent sign on it.
294
+ `orc extra doctor` gains `extra-orphan-dispatch` and `extra-profile-unreliable`
295
+ (never below the floor). Both ABSENT counts are named.
296
+ - **`orc ui ▸ Extra ▸ Recovery`** — a sixth tab, not a tenth card. One row per
297
+ journal, **expanded in place** (the Runs-row rule), and the free/paid line is
298
+ visible: `reconcile` is a button, `resume-slice` is a copy-able command,
299
+ because the panel never runs a lane. A row with nothing to show KEEPS ITS SLOT;
300
+ `in-flight` renders as a refusal with its reason; prune is preview-then-apply
301
+ and **names every directory**. Spending gains the reliability strip. Overview
302
+ gets one line, only when there is something to say, and it never offers to
303
+ continue anything.
304
+ - **Two new config keys, and the four that were refused are written down.**
305
+ `extra_resume` (`on`) and `extra_resume_max` (`2`) — nine keys became eleven.
306
+ Deliberately NOT added: a key for where a resume goes, a key for the retry
307
+ ladder (`extra_timeout_s` is already the budget), a key to disable the journal
308
+ or its 30-day retention (**a record you can switch off is off on the run you
309
+ needed it for**), and a key for the network probe. `extra_resume` is INERT in
310
+ `/orc-quick`, announced at the agent gate.
311
+ - **New trace verbs** `EXTRA resume` and `EXTRA orphan`, composed by the CLI and
312
+ copied verbatim a resume that leaves no line cannot be counted by
313
+ `orc extra stats` or `/orc-retro`. New mocked run: `mock-run/extra-recovery.md`.
314
+
315
+ ---
316
+
317
+ ### v0.53.4 the reload that dropped its own token _(2026-08-24)_
318
+
319
+ **Every `orc update` from the panel ended on `This link is missing its session
320
+ token.` — and the token was never missing.**
321
+
322
+ v0.53.2 taught the server to hand itself over to a fresh process on the SAME
323
+ port and the SAME token, so the URL in the address bar stays valid and the open
324
+ tab only has to reload. That half worked. The reload did not: the panel strips
325
+ `?t=` out of the visible URL at boot (`00-core.js`, so the token never lands in
326
+ a screenshot or a pasted link), and the hand-over then called
327
+ `location.reload()` which re-requests **the stripped address**. No `?t=`, no
328
+ `x-orc-token` header on a document request, and the server correctly answered
329
+ with the un-authenticated page. Deterministic, on every maintenance action that
330
+ declares `restarts_ui`.
331
+
332
+ - **A reload is not `location.reload()` here.** `reloadWithToken()` re-attaches
333
+ the in-memory token and `location.replace()`s that URL. It is the only reload
334
+ route in the panel, and a test fails on any bare `location.reload()` in
335
+ `app.js` the stripping is deliberate, so the fix has to be the reload, not
336
+ the strip.
337
+ - Nothing about the server, the successor, the lock, the token generation or the
338
+ `restarts_ui` declaration changed. The upgrade had already installed by the
339
+ time the page broke; the user's recovery `orc ui --stop` then `orc ui` was
340
+ producing a *new* token for a server that was already the new build.
341
+
342
+ ---
343
+
344
+ ### v0.53.3 the key it never sent _(2026-08-24)_
345
+
346
+ **A vaulted, verified, routed connection authenticated every wave with the wrong
347
+ secret, and four separate green checks agreed it was fine.**
348
+
349
+ `orc extra dispatch` resolved the credential by passing `inMemory:
350
+ process.env.ORC_EXTRA_KEY` into `extraCredentialValue`, and that option
351
+ short-circuited the vault branch **on its first line**. So whenever
352
+ `ORC_EXTRA_KEY` was set in the environment a leftover from another profile,
353
+ another provider, another day dispatch sent *that* value and never opened the
354
+ vault at all. The profile's real, verified, vaulted key was never consulted.
355
+
356
+ Only `dispatch` and `conform` passed that option. `ping`, `models --test` and
357
+ `preflight` all resolved without it, opened the vault, and succeeded. Hence the
358
+ part that made this expensive to find:
359
+
360
+ ```
361
+ orc extra doctor → nothing to report.
362
+ orc extra list → dipkshit deepseek/api verified key vault
363
+ orc extra preflight → dipkshit ok saved until 2027-08-19
364
+ orc extra models dipkshit --test <model> → answered in 1866ms
365
+ ```
366
+
367
+ Four checks, each honest about the path it exercised, **none of them exercising
368
+ the path a dispatch takes**. Then the wave died at HTTP 401 —
369
+ `Your api key: ****w5f7 is invalid` — pointing at the vaulted key the user had
370
+ verified four minutes earlier, while the key ORC actually sent came from an
371
+ environment variable the message never named. Nothing was written and nothing was
372
+ billed; the run halted at F2 under `extra_on_failure: stop`.
373
+
374
+ - **The two in-memory options were one option, and they are different facts.**
375
+ `opts.inMemory` is an **explicit** key supplied for this invocation
376
+ (`--key-stdin`) the key being tested and then stored, so it still wins.
377
+ `opts.ambientKey` is a key found lying in the environment, and it is now what
378
+ it was always written to be: the **unattended-wave fallback**, applying only to
379
+ a vault that cannot be opened here (`extra_unlock: per-dispatch`, where nothing
380
+ is cached on purpose). **A vault ORC can open always wins.**
381
+ - **A passphrase in hand that the vault refuses is a real answer about the
382
+ declared source,** not a reason to reach for a leftover variable. It returns the
383
+ refusal rather than burning an attempt and then sending the wrong secret anyway.
384
+ - **The return now reports the source it USED.** `credential.source` is one of
385
+ `vault` · `env` · `ambient` · `memory` · `tool`, and it describes what happened
386
+ rather than what the profile declares the two disagreed for a release, so the
387
+ one field that could have named the bug confirmed the wrong story instead.
388
+ `credential_override` is printed whenever the profile's declared source was not
389
+ the one used, pass or fail: an override nobody was told about is the same class
390
+ of silence as work leaving Claude with no `extra:` line.
391
+ - **A 401 names the source that produced the rejected secret.** The provider's
392
+ message describes what it saw; only ORC knows where that came from. It was a
393
+ five-minute fix and a multi-step diagnosis.
394
+
395
+ **`ORC_EXTRA_KEY` holds the KEY, and `orc extra keyhelp` said it was the
396
+ passphrase.** For a vaulted profile it rendered a per-OS instruction to export
397
+ `ORC_EXTRA_KEY="<your passphrase>"` into the exact variable a dispatch sends to
398
+ the provider in an `Authorization` header. Following ORC's own instruction handed
399
+ the secret that opens the vault to a third party. The block is gone. In its place
400
+ the route **with a deadline on it** renders first (`orc extra session <name>
401
+ --save --ttl 30`, the v0.52.0 design), then the variable, described as the key,
402
+ with the warning that a passphrase must never go there. Nothing in ORC reads a
403
+ passphrase from the environment, so `passphrase_env` is now always `null`.
404
+
405
+ **One completions URL, and the probes speak it.** `ping` rung 2 and
406
+ `models --test` hardcoded `{base}/chat/completions` while dispatch derived
407
+ `{base}/v1/chat/completions` through `apiCompletionsUrl` and neither probe
408
+ honoured a profile's `completions_path` at all. DeepSeek accepts both spellings,
409
+ so this was not the 401; on a provider that accepts only one it produces a
410
+ profile that verifies **green** and dispatches into a 404, which is the same lie
411
+ wearing a different status code. Both probes now call the same builder.
412
+
413
+ **And the unknown-model escape has to be about the model.** A 400/404/422 on the
414
+ probe's invented model id was read as proof that the endpoint authenticated
415
+ before declining the name — which is only true if the endpoint is the one it was
416
+ aiming at. A gateway answering `Unknown request URL` with a 404 authenticated
417
+ nothing. The rejection must now name the model asked for, or say something about
418
+ a model/engine/deployment; otherwise the ping fails honestly instead of
419
+ verifying. `verify_credential_source` records which credential earned the badge.
420
+
421
+ **The fake provider was more permissive than the provider.** It answered a
422
+ completion on **any** path, which is precisely why two probes could hardcode the
423
+ wrong one for three releases with a green suite. It now serves exactly the path
424
+ `apiCompletionsUrl` derives and 404s the rest — the v0.53.0 rule, applied to the
425
+ third surface in a row that broke on it.
426
+
427
+ ---
428
+
429
+ ### v0.53.2 — the cost that was paid and never written down _(2026-08-24)_
430
+
431
+ **Two foreign dispatches ran, cost real money, and every cost report read zero.**
432
+
433
+ `orc extra dispatch` composes an `EXTRA …` trace line and hands it back for the
434
+ lane to copy into a phase packet. That is a RELAY THROUGH A MODEL — the
435
+ remembered-not-dispatched pattern this repo has already lost to twice — and it
436
+ broke in both directions on two graded runs of the same feature:
437
+
438
+ - one wrote `EXTRA Codex/gpt-5.4-mini :: engine=cli …`, adding the trace's own
439
+ `verb :: tail` separator, which the parser did not accept;
440
+ - one dropped the line entirely and folded the token vector into a free-form
441
+ `VERIFY` sentence.
442
+
443
+ Both dispatches SUCCEEDED. `return.json` and `return-fast.json` were sitting in
444
+ the run folder with complete four-kind vectors — 27,029 / 0 / 159,616 / 1,895 for
445
+ codex, 136 / 0 / 20,032 / 134 for opencode — and a perfectly formed `trace_line`
446
+ inside each. `orc extra stats` reported **0 dispatches from 2 traces**, `orc extra
447
+ rates` had no pair to price, and `orc ui Extra ▸ Spending` read **`0 tasks
448
+ sent`**. A cost report that reads zero when money was spent is worse than no
449
+ report, because a zero gets believed.
450
+
451
+ - **THE BRIDGE WRITES THE SPEND DOWN ITSELF.** Every dispatch appends one JSON
452
+ object to `.claude/orc/extra-spend.jsonl` at the moment it holds the numbers —
453
+ profile, provider, model, engine, task, band, the four token kinds unblended,
454
+ outcome, duration, the run it belonged to, and the `trace_line` it composed.
455
+ The `RESUME.md` lesson from v0.49.5 applied to money: **the fact is recorded by
456
+ the hand that computed it.** Best effort by construction a record that cannot
457
+ be written never takes a dispatch down and the dispatch says `spend_logged`
458
+ either way, because a dispatch no cost report can see is worth one line now
459
+ rather than a mystery later.
460
+ - **The trace line is NOT retired, it is DEMOTED to the second source.** It is
461
+ still the run's narrative and still what `/orc-retro` reads; it is no longer
462
+ what the money depends on. The two are DEDUPED on the eight fields the line
463
+ itself carries, so a lane that relays correctly is counted exactly once
464
+ double-counting a correct relay would punish the behaviour the contract asks
465
+ for.
466
+ - **The parser now accepts the ` :: ` a trace writer reaches for by reflex.**
467
+ Every other verb in a trace is `VERB :: tail`. A line that is faithful about
468
+ the numbers and off by two characters in its punctuation must still parse.
469
+ Tolerance is a net under the contract, not a licence to reshape the line.
470
+ - **A saved dispatch return backfills a run made before any of this existed.**
471
+ `{run_dir}/<slug>/*.json` is read as a THIRD source when and only when it
472
+ carries `dispatched: true` and a `trace_line` this parser accepts. That is the
473
+ CLI's own payload read back, not a narrative about it, which is what separates
474
+ a recovery from an invention. It carries no date and **none is derived from an
475
+ mtime** (the `/orc-pact` UNCHECKABLE rule), so `--since` excludes those rows and
476
+ says how many.
477
+ - **Every count says which source it came from,** on both surfaces. "ORC wrote
478
+ this down itself" and "a trace happened to mention it" are different levels of
479
+ confidence in the same total. Two ABSENT counts are named rather than absorbed:
480
+ a torn log line, and an undated saved return a date filter dropped — a report
481
+ that is quietly short by three rows is the exact failure being fixed.
482
+
483
+ **And the panel now survives its own upgrade.**
484
+
485
+ `orc upgrade` replaces the package the running `orc ui` server was loaded from.
486
+ Node read `bin/webui` at require time and `STATIC` is a one-time walk at boot, so
487
+ an upgraded panel keeps serving the old bytes: the version in the rail does not
488
+ move, a new panel does not appear, and a fixed bug is still there. The remedy was
489
+ three manual steps nobody was told about — stop the server, re-run `orc ui`, open
490
+ the new URL.
491
+
492
+ - **The server hands itself over.** After a maintenance action DECLARED as
493
+ replacing the install (`update`, `prune`, `fix`, `upgrade` never
494
+ `update-global`, which targets `~/.claude`) succeeds, the panel restarts on the
495
+ **same port and the same token** and the open tab reloads itself. A successor on
496
+ a new address is not a restart; it is a second server, and the tab you are
497
+ looking at would still point at the corpse.
498
+ - **CLIENT-TRIGGERED, never automatic on the job's close handler.** The job's
499
+ output lives in the server's memory, so restarting the instant a command
500
+ finished would destroy the record of what it did before anyone read it. It also
501
+ means a tab that is already closed leaves the old process running, which is the
502
+ safe resting state.
503
+ - **The token travels in the ENVIRONMENT, never in argv** — it authenticates a
504
+ write surface, which puts it in the same class as the credentials `orc extra`
505
+ refuses on a command line. It is read once at boot and deleted from
506
+ `process.env`, so no CLI subprocess the server shells out to inherits it.
507
+ - **A failed handover is a note and two commands, never a broken page.** The old
508
+ panel keeps working; it just prints `orc ui --stop` and `orc ui`. And the
509
+ confirmation says the restart is coming BEFORE the apply a panel that reloads
510
+ itself with no warning reads as a crash.
511
+
512
+ ---
513
+
514
+ ### v0.53.1 "up to date" now names what it checked _(2026-08-23)_
515
+
516
+ **A one-line diagnostic for the update check that could not be questioned.**
517
+
518
+ The update check was never broken, and that was the problem. `orc version` reads
519
+ `package.json` from `UPDATE_URL`; `orc upgrade` installs from `TARBALL_SPEC`.
520
+ They are two different URLs on what is *normally* the same branch and only the
521
+ second one was ever printed, on either surface. The Maintenance panel's `source`
522
+ row shows the install tarball, so a reader concludes the version comparison read
523
+ main too.
524
+
525
+ That gap makes a true statement unfalsifiable. A maintainer who cut v0.53.0 on an
526
+ unmerged release branch saw `✓ up to date` against a main that was still at
527
+ 0.52.0, with nothing on screen to distinguish "you are current" from "the release
528
+ never reached the ref this reads". There is no way to tell those apart from the
529
+ output, which is why it reads as a defect in the checker.
530
+
531
+ So the number and the ref it came from now travel together, everywhere the number
532
+ is reported:
533
+
534
+ - **`orc version`** prints `✓ up to date (azure-id/orc@main is at 0.52.0)`, and
535
+ the offline branch names the unreachable ref rather than saying "source".
536
+ - **`orc version --json`** gains `checked_source` (the URL) and `checked_ref` (the
537
+ `owner/repo@ref` label). This is not a new idea: `orc changelog --json` has
538
+ always carried its own `source`, and this is that field's missing twin — a
539
+ field the human path implied and the JSON omitted.
540
+ - **`orc ui` Maintenance** gains a `version read from` row beside `source`, so
541
+ the two URLs are visibly two URLs. The fixture carries both fields.
542
+
543
+ `checkSourceLabel()` shortens a `raw.githubusercontent.com` URL to
544
+ `owner/repo@ref` and returns anything else verbatim a custom `ORC_VERSION_URL`
545
+ is shown as written rather than mangled into a label that does not describe it.
546
+
547
+ **Nothing about the check itself changed.** No new request, no new cache, no
548
+ change to the 24h TTL, `ORC_NO_UPDATE_CHECK` or the comparison. The only thing
549
+ that is new is that the answer can now be checked.
550
+
551
+ ### v0.53.0 the schema the provider rejected, and a routing table you can read _(2026-08-23)_
552
+
553
+ **One outage, one defect visible at a glance, and the Extra panel rebuilt.**
554
+
555
+ **The outage.** Engine `cli` on **codex** had been 100% dead for a release, and
556
+ the suite was green the whole time. ORC handed codex an `--output-schema` with
557
+ `additionalProperties: true`; OpenAI structured outputs require a **closed**
558
+ object at every level, so every dispatch was an **HTTP 400 raised before the
559
+ model was ever reached** fast, free, and reported as something vague. Flipping
560
+ only that flag is a **second** 400, this time naming `files_changed`, because
561
+ `required` must list every key in `properties`. An optional field is a nullable
562
+ union now, never an omission from `required`, and the shape is documented as
563
+ **provider-dictated rather than chosen** the comment calling it "deliberately
564
+ minimal" is what produced the bug.
565
+
566
+ Three things went with it:
567
+
568
+ - **The classifier was reading the wrong stream.** codex relays the upstream
569
+ `invalid_request_error` inside its own event stream on stdout while printing a
570
+ benign notice on stderr, so a precisely-diagnosable, non-retryable failure came
571
+ back as `unknown` and `retry: false` was reached by luck. The codex adapter
572
+ now classifies from **the provider's own error object** first, and
573
+ `classified_from` says which of the two answered a field that reports where
574
+ a verdict came from must not lie about it.
575
+ - **A measurement was being reported as unknown.** codex *does* report
576
+ `cache_write_input_tokens`; the adapter declared three usage kinds, so ORC
577
+ threw a real number away and then said it was never measured.
578
+ `reasoning_output_tokens` is still deliberately unread the Responses API
579
+ counts it inside `output_tokens`, and an unproven pricing change is worse than
580
+ a missing one.
581
+ - **And the reason it shipped green: the fake was more permissive than the
582
+ provider.** It asserted the schema existed and mentioned `status`, and modelled
583
+ none of OpenAI's rules. That is the **third release in a row** broken by the
584
+ same shape `--auto` renamed, a greedy `-f` array, now an open schema. **A
585
+ strict third-party parser fails for free, and it looks like a model problem.**
586
+ The defence is the same every time: the fake must be at least as strict as the
587
+ real thing. It now rejects both 400s by name.
588
+
589
+ **The ellipse.** A ready-and-verified tool card drew its "connected as" chip as a
590
+ 250px green ellipse. `.ex-tool` declared `grid-template-rows: auto auto auto 1fr
591
+ auto` but **four states carry four different numbers of children**, so the chip
592
+ landed in the `1fr` slack row, stretched (a grid item's default), and a 999px
593
+ radius did the rest. It hit whichever ready card had the shortest content in its
594
+ row, so it was never about one tool. The card is a flex column now, with no row
595
+ template at all. The old test asserted the property was *present* which it was,
596
+ while the panel drew an ellipse.
597
+
598
+ **The Extra panel.** It was nine cards in one 8,786px scroll: no first step, no
599
+ last step, no way to be *done* with a section.
600
+
601
+ - **Five tabs** on the panel's own precedent Setup, Routing, Limits, Spending,
602
+ Providers. The header strip and "what needs your attention" stay outside them,
603
+ because a caution you have to go looking for is a caution nobody reads. The
604
+ open tab survives a re-render, and the gate still decides what **exists**: with
605
+ nothing connected, three tabs are not rendered as empty shells.
606
+ - **One vertical band ladder** replaces the horizontal rail *and* the duplicate
607
+ list of rows below it. The target is no longer truncated, the widths no longer
608
+ lie (a `min-width` floor was fighting the percentage), nothing is off-screen,
609
+ there is a **legend** green means the work leaves your machine — and the row
610
+ you read is the row you edit.
611
+ - **The plain-language range is the CLI's.** `orc extra route` gains `range`
612
+ ("scores 0 to 29") and `meaning` per row, printed on the human path as well.
613
+ Writing "simple work" beside a score in the panel would be the panel deciding
614
+ what a score means.
615
+ - **One sentence and one control per tool state**, with the diagnostics behind a
616
+ disclosure.
617
+ - **Wording**: the panel was serving **design rationale as user instruction**.
618
+ Six keys split the instruction first, in Simplified Technical English, the
619
+ reasoning collapsed underneath. Nothing deleted, both languages, and the
620
+ rationale keeps its voice.
621
+
622
+ Setup per provider: **[`guides/extra-models.md`](guides/extra-models.md)**.
623
+
624
+ ---
625
+
626
+ ### v0.52.0 the connection that could not be used, and the routing nobody could see _(2026-08-23)_
627
+
628
+ **Eleven defects, one release.** Five came out of a real `/orc-fast` run against
629
+ a verified, routed local tool a run that fell back to Claude twice over, for
630
+ two unrelated reasons, neither of which was the model. Six more came out of
631
+ reading the panel afterwards, and they are one theme with several faces:
632
+ **Extra was invisible to every surface that is not the Extra panel.**
633
+
634
+ **The two that killed that run.**
635
+
636
+ - **`opencode` dispatch was dead on arrival.** `-f` is a yargs **array** flag,
637
+ and a yargs array is **greedy**: every non-flag token after it is swallowed as
638
+ another file path. ORC pushed the message last, so `message..` arrived empty
639
+ and opencode exited 1 in its own parser `dur=0m01s`, `tok=none`,
640
+ `outcome=failed`, looking exactly like a model problem. Engine `cli` on that
641
+ tool was 100% dead for a release. The message comes first now, `-f` comes
642
+ last where it has nothing left to eat, and the test fixture asserts **that a
643
+ message arrived** rather than that a flag was present.
644
+ - **A tool that signs itself in was being forced into the vault.** `--tool-auth`
645
+ has existed in the CLI since v0.51.0 and the panel offered two radios, so a
646
+ connection that needed **no key from ORC at all** got a vault, and the vault
647
+ then locked the run. There is a third credential source in the form now,
648
+ offered only where it can be true, and pre-selected when the card you pressed
649
+ Connect on says the tool is already signed in.
650
+
651
+ **The passphrase finally has a lifecycle, and a deadline.** A vaulted key needed
652
+ `ORC_EXTRA_KEY` in the environment or nothing, so a green, verified, routed
653
+ connection answered `locked` at wave 1 and the run announced a Claude fallback.
654
+
655
+ - `orc extra session <name> --save --ttl <days>` saves it, **on stdin** —
656
+ `--passphrase <value>` is refused by name, like every other secret here. The
657
+ deadlines are a closed set (1 · 3 · 7 · 14 · 30 · 90 · 180 · 360): no `0`, no
658
+ "forever", and **no auto-extend on use** — a deadline that renews itself is
659
+ not a deadline.
660
+ - The cache lives **in the project**, gitignored beside the vault, and is
661
+ encrypted under the pepper that lives in your home directory. **A copy of the
662
+ project folder opens nothing.** That is the one genuine property this file
663
+ has, and it is said out loud wherever the countdown appears along with the
664
+ honest half: while it is saved, anything running as you on this computer can
665
+ open the connection.
666
+ - **`orc extra preflight` is a P0 gate before wave 1.** Active is fine; expiring
667
+ is fine and names the date; **expired or missing STOPS the run**. It never
668
+ falls back `extra_on_failure` is about an endpoint that failed, and a
669
+ deadline you set 30 days ago deserves a stop, not a substitution. The
670
+ credential is deleted and the connection stamped expired; **the routing rows
671
+ survive**, because the bands are work you did.
672
+ - The save modal at connect time **has no exit but Save**, and one destructive
673
+ escape that is named rather than a Cancel.
674
+
675
+ **Extra is visible outside its own panel now.**
676
+
677
+ - **`orc extra lanes`** answers the question a band cannot: *which lane does this
678
+ govern?* `/orc` scores every task; `/orc-fast` pins one executor and resolves
679
+ its band **at both edges**, requiring them to agree. That rule was implemented
680
+ and written down and rendered nowhere. The lane table is code now, mirrored
681
+ against the markdown in both directions by a golden test.
682
+ - **The Flow score table sees Extra.** With `extra: on` it renders the composite
683
+ instead of the Claude ladder — a band that cannot route **keeps its row** and
684
+ names its fall-through, and `extra: off` renders byte-identically to before.
685
+ - **`fixed_executor` can name a foreign target** (`extra:<profile>/<provider>/<model>`),
686
+ offered only for verified connections. The session-tier rule is skipped for it
687
+ it is not a Claude model and **the compiled flow says so**, because a rule
688
+ silently disabled is worse than no rule.
689
+ - **`/orc-doc` has its own switch.** `orc doc extra <slug> --set
690
+ off|writer|checker|both`, stored per document, default off. A global setting
691
+ turning Extra on for a throwaway runbook also turned it on for the PRD you
692
+ ship, and a document's voice is the deliverable. `orc doc next` names the
693
+ sections going off Claude **before** the wave.
694
+
695
+ **Three panel defects, and one of them was in every modal.**
696
+
697
+ - A **connected** tool no longer offers Connect. `connected` and `verified` are
698
+ computed by the CLI, never joined in the panel, and the verified card **has no
699
+ Connect button at all** rather than a disabled one.
700
+ - **Scrolling inside a modal scrolled the page behind it** every modal in the
701
+ app, not just Extra's. Fixed with scroll containment and a body lock.
702
+ - **Two tool cards no longer sit at different heights.** A card declares its rows
703
+ now, so the button in one lines up with the button in the other.
704
+
705
+ **Wording.** The Extra panel's instruction text labels, hints, errors, gates,
706
+ countdowns, the passphrase modal end to end is Simplified Technical English,
707
+ with a one-page term list at `bin/webui/i18n/TERMS.md` and a test for the cheap
708
+ half. Rationale prose keeps its voice and only gets shorter: flattening *"it
709
+ stops someone at your keyboard, not someone who copied the file"* makes it true
710
+ and useless. One rule is not negotiable and now has a test: **never simplify a
711
+ CLI-computed value** a simplified state word is a state that does not exist.
712
+
713
+ New: `orc extra session`, `orc extra preflight`, `orc extra lanes`, `orc doc
714
+ extra`, `orc extra dispatch --passphrase-stdin`, and one config key
715
+ (`extra_passphrase_ttl_days`, default 30). `orc extra keyhelp` now carries the
716
+ per-OS command for setting an environment variable with a placeholder, never a
717
+ key, and ORC still refuses to run `setx` or write to your shell profile itself.
718
+
719
+ ---
720
+
721
+ ### v0.51.0 the tools you already have, and a connection that proves itself _(2026-08-22)_
722
+
723
+ **`orc extra` connections.** Two of the things ORC can hand work to are not
724
+ websites — they are **programs on your own machine**, and the last release could
725
+ only reach them by hand-typing a binary name into a `custom` profile. They are
726
+ first-class providers now, with a connect box each, a model dropdown built from
727
+ what **your** account can actually reach, and a connection test that proves
728
+ something answered rather than proving a file exists.
729
+
730
+ - **A program can simply not be installed, and the panel says that FIRST.** Four
731
+ states, computed fresh every time and never remembered: `absent`,
732
+ `outdated`, `unauthenticated`, `ready`. An absent tool gets no Connect
733
+ button, no Test button and no model list — every one of those is a button that
734
+ cannot succeed. `orc extra add` refuses too, and names the install command
735
+ instead of leaving you a profile that will never work.
736
+ - **ORC opens your own terminal and runs the install there.** Not a hidden
737
+ background job — inside one, an administrator prompt, a permissions error, an
738
+ 80 MB download and a forty-second wait all look identical: *nothing happened*.
739
+ The exact command is on screen before the button, the window is yours to read
740
+ and Ctrl-C, **ORC never asks for administrator rights**, and if no terminal can
741
+ be opened you get the command to paste rather than a dead button.
742
+ - **One tool has an install-free route and one does not**, and `null` means
743
+ *there is none* rather than *ORC did not look*. The two never render the same.
744
+ - **The connection test is a ladder now, and every rung reads as itself.** Is the
745
+ program there · is it new enough · does it have a sign-in · which models can
746
+ this account reach · and only when you ask **does a real message actually
747
+ come back**, with the round trip, the reply, and the four token counts kept
748
+ separate. Free rungs always run; the paid one is its own button, and what it
749
+ costs is quoted before you press it.
750
+ - **A model that is LISTED is not a model that WORKS.** A live list is what the
751
+ provider offers; an id in it can be dead upstream. `orc extra models <name>
752
+ --test <id>` is the only thing that tells those two apart, and the caveat rides
753
+ beside every dropdown.
754
+ - **Neither local tool says which model answered**, so a quiet substitution is
755
+ invisible on that engine. ORC prints that sentence rather than an empty field
756
+ and one of the two reports three token kinds, not four, so the missing one
757
+ reads as an em dash and never as a zero.
758
+ - **A models list anyone can read is not proof of your key.** A provider that
759
+ serves its catalogue without a credential would otherwise mark a connection
760
+ verified with a typo'd key. That answer is now recorded for what it was and the
761
+ test carries on to something that actually needs the key.
762
+ - **`extra_enabled` cannot be switched on before anything has answered.** It
763
+ would have armed nothing every task would fall straight back to Claude, so
764
+ the switch read ON and meant OFF. The refusal names what to do next, and the
765
+ Extra panel shows only the connect surfaces until then: no routing table, no
766
+ limits, no cost report.
767
+ - **A fix, not a feature:** every dispatch to one of the two local tools was
768
+ failing, and failing in a way that looked like a bad model id. One of them
769
+ renamed a permission flag and refuses unknown ones outright. ORC picks the flag
770
+ from the version it probed, and a tool that answers with its own help text is
771
+ now reported as a flag problem by name.
772
+ - **ORC never writes another tool's credential store.** Your key stays in ORC's
773
+ vault or in your own environment variable and is handed to the program for each
774
+ run so nothing global changes, revoking it in ORC actually revokes it, and if
775
+ you already signed that tool in yourself, ORC leaves it alone.
776
+
777
+ ---
778
+
779
+ ### v0.50.0 work that runs somewhere else _(2026-08-22)_
780
+
781
+ **`orc extra`** a band of ORC's score ladder can now be answered by a
782
+ **non-Claude worker**: DeepSeek, Z.ai (GLM), Moonshot (Kimi), MiniMax, Qwen,
783
+ Xiaomi MiMo, StepFun, SiliconFlow, OpenRouter, a local Ollama, any
784
+ OpenAI-/Anthropic-compatible endpoint you name, or an agentic CLI you already
785
+ have (`opencode`, `codex`). ORC's own session never moves this routes
786
+ **workers**, not the conductor.
787
+
788
+ - **Off by default, and a connection that has never answered can never be used.**
789
+ `orc extra ping` is the gate, it climbs the cheapest rung first (a free model
790
+ list; only then a one-token completion), and it records WHICH rung answered —
791
+ "verified by a models list" and "verified by a real completion" are different
792
+ guarantees and one green tick for both would be a lie.
793
+ - **Every armed run says so BEFORE the work starts.** An `extra:` line joins the
794
+ Phase-1 preflight naming how many tasks will cross the boundary and where they
795
+ go. It has no quiet version. The failure this whole subsystem is shaped around
796
+ is not a wrong answer it is work leaving your machine without anybody saying
797
+ so.
798
+ - **A gap in the routing table is not a hole it is Claude**, and it is printed
799
+ with the exact agent it resolves to, so "I left the top band on Opus on
800
+ purpose" and "there is no top band" can never look the same. Overlapping rows
801
+ are refused by name.
802
+ - **Risky work stays.** A task whose plan cites `risk[]` (money, auth, security,
803
+ migration, concurrency, data-integrity) never leaves Claude, and neither does
804
+ anything in an area a boundary card marks REFUSE — in `warn` mode as well as
805
+ `block`.
806
+ - **Three engines, and only one composes the request body.** `api` is therefore
807
+ the only one that can enforce the declared-files fence or carry a privacy
808
+ policy, so a return claiming the fence held on the other two is rendered as a
809
+ WARNING: a constraint that was never applied is never reported as kept.
810
+ - **Your key never reaches a command line.** `--key <value>` is refused by name.
811
+ Use an environment variable (recommended) or the encrypted vault
812
+ AES-256-GCM under a passphrase ORC does not store and cannot recover, stored
813
+ only after a green test, with a countdown that prints every time and a
814
+ self-destruct at ten wrong attempts that keeps the profile. New in this
815
+ release: `orc extra ping --passphrase-stdin` re-tests a key that is already
816
+ stored.
817
+ - **No shipped model ids and no shipped prices.** Both go stale within a quarter
818
+ and both get believed. `orc extra ping` reads the live model list from the
819
+ provider; `orc extra rates` prints the JSON to paste for a price. Until a pair
820
+ has a rate, `usd` reads as an em dash — a cost ORC did not price itself is
821
+ never printed.
822
+ - **`orc extra stats`** joins ORC's own traces per profile per band and reports
823
+ four token kinds separately, plus the three things only it can see: a
824
+ SUBSTITUTION (you did not get the model you asked for), a REROUTE (you got the
825
+ model and a different company served it) and a FALLBACK (it did not work and
826
+ Claude finished the job).
827
+ - **A failed foreign dispatch is never a dead run.** It falls back to the Claude
828
+ band that task would have had, announced. `extra_on_failure: stop` is there for
829
+ people who would rather stop than quietly start paying full rates.
830
+ - **New panel: `orc ui` Extra.** The boundary paragraph renders always, never
831
+ behind a click. One 0→100 rail, green where your connection runs the work and
832
+ blue where Claude does, with every unrouted range keeping its slot. Staging a
833
+ change previews it before anything is written. The panel names no provider, no
834
+ model and no agent it draws what the CLI computed.
835
+ - **The `orc ui` boundary is NARROWED, not broken.** The panel still never runs a
836
+ lane and never does agentic model work; the one model-shaped thing it can
837
+ trigger is a connectivity probe, and even that runs through the CLI in a
838
+ subprocess like every other action. A probe is a diagnostic, the family
839
+ `orc doctor` is in.
840
+ - **Nine config keys**, one canonical contract
841
+ (`_shared/extra-dispatch.md`), a new `EXTRA` trace verb, `orc extra doctor`
842
+ with eleven findings, and a stance stated in exactly one place for every other
843
+ lane — including `/orc-challenge`, which never routes foreign, because swapping
844
+ a lens for a different model does not make the lane cheaper, it changes what is
845
+ being measured.
846
+ - **Also:** the test suite pins `--test-concurrency=8`. At one worker per core,
847
+ the files that spawn real child processes and the one that derives scrypt at
848
+ N=2^17 starved each other and produced failures that looked exactly like
849
+ regressions. Determinism is worth 11% of the wall clock.
850
+
851
+ Setup detail per provider: **[`guides/extra-models.md`](guides/extra-models.md)**.
852
+ A full walkthrough: `orc mock-run orc-extra`.
853
+
854
+ ---
855
+
856
+ ### v0.49.5 house rules are text, and the hand-back writes itself _(2026-08-21)_
857
+
858
+ Two fixes to `/orc-doc`, both the same shape: stop making a person work around
859
+ the tool.
860
+
861
+ - **House rules are a PLAIN TEXT config now, not a form.** The first cut modelled
862
+ a rule as a row one line, one id, a P0/P1/P2 dropdown, an enable flag, added
863
+ one at a time. Nobody's real P0 fits on one line, and filing it as four
864
+ separate rows to keep the CLI's argv simple was the tool asking the user to
865
+ work around it. The ledger is now `.claude/orc/doc-house-rules.md`: three
866
+ headings, and **as much text under each one as you want**, handed to every
867
+ writer verbatim. Open it in your editor, or edit it in **one box** in
868
+ `orc ui` **Docs** no dropdown, no Add button, no per-rule row.
869
+ - **New: `orc doc rules set|add|clear --priority P0 --text "…"`** (multi-line is
870
+ the point), plus `set-all` for the whole file and `--set-file` for a bulk
871
+ replace. `remove`, `enable`, `disable` and `move` are **refused by name** a
872
+ command that used to work and now does nothing is worse than one that says
873
+ what replaced it.
874
+ - **Migration is lazy, free and non-destructive.** The old `doc-house-rules.json`
875
+ is read once, converted, and **left exactly where it was**. A rule you had
876
+ DISABLED is never resurrected — it is left behind and counted in the output.
877
+ - **`RESUME.md` is written by the CLI, on every state change.** It used to be
878
+ prose the orchestrator was told to write at every stop, which is the bet this
879
+ repo has already lost twice: the hand-back you are TOLD to write is the one
880
+ that goes missing on the run a usage limit killed. `doc.json` has exactly one
881
+ writer, so the hand-back hangs off that it exists from `orc doc init` onward
882
+ and is never behind the disk. `orc doc resume-file <slug>` writes it on demand.
883
+ - **Every question `/orc-doc` asks you now ends by pointing at it** (hard rule
884
+ 16): the file path, and the one line to paste into a brand-new session. The
885
+ page itself is written for someone who does not read code — what the document
886
+ is, where the files are, what is not written yet, and what happens next.
887
+
888
+ ---
889
+
890
+ ### v0.49.4 the panel was being handed half an answer _(2026-08-20)_
891
+
892
+ One bug, and it could hit any `--json` read big enough.
893
+
894
+ - **Fixed: a large `--json` payload was truncated whenever something read it
895
+ through a pipe.** `emitJson` wrote to stdout and then called `process.exit()`.
896
+ On macOS and Linux a pipe write is asynchronous, so the exit threw away
897
+ whatever had not flushed — and `orc ui` reads every panel through a pipe. On a
898
+ 1,100-file repo `orc wiki coverage --json` computed a perfect 30 KB object, the
899
+ server received the first 9 KB, `JSON.parse` failed, and **Knowledge
900
+ Coverage** reported that the repo had neither a registered wiki nor a git
901
+ repository on a wiki that was FRESH and 39% covered. `orc wiki docs` was hit
902
+ the same way; `wiki status` escaped only because it prints and returns instead
903
+ of exiting. Windows pipes are synchronous, which is why it never showed up in
904
+ development. Every `--json` read now writes through fd 1 synchronously.
905
+ - **The Knowledge panel no longer reports a broken read as an empty repo.** A
906
+ failed request renders the CLI's own reason and output, the way every other
907
+ panel has since v0.49.2 the generic "it needs a registered wiki and a git
908
+ repository" line is for a repo that actually has neither.
909
+ - **Also: git output is no longer capped at Node's 1 MB default** (v0.49.3),
910
+ which would have truncated `git ls-files` on a repo of roughly 25,000 files.
911
+
912
+ ---
913
+
914
+ ### v0.49.3 — coverage on a large repo _(2026-08-19)_
915
+
916
+ One fix, and the bigger the repo the more it mattered.
917
+
918
+ - **Fixed: `orc wiki coverage` reported "not a git repository" on a large,
919
+ freshly refreshed wiki.** Every git call ORC makes ran through `spawnSync` on
920
+ Node's **1 MB** default output buffer. `git ls-files` in a big repo prints more
921
+ than that, the child is killed with `ENOBUFS`, and the exit status comes back
922
+ `null` which the code read as *there is no git here*. So `orc ui` ▸
923
+ **Knowledge** **Coverage** showed no numbers at all on the repos where the
924
+ number matters most, and `orc wiki impact` was one wide diff away from the same
925
+ failure. The buffer is now **256 MB**, and a spawn error is read as an error
926
+ instead of being inferred from the status code.
927
+
928
+ ---
929
+
930
+ ### v0.49.2house rules, a run map before you pay, and three defects _(2026-08-18)_
931
+
932
+ Quality of life on `/orc-doc`, plus three bugs one of which was breaking a
933
+ panel outright. **Zero new agents, zero new skills.** Everything here obeys the
934
+ standing rule: **the CLI computes, the panel and the skill render.**
935
+
936
+ #### `/orc-doc` — house rules
937
+
938
+ A **house rule** is your project's own standing instruction about **what a
939
+ document says and how it reads**: *"open with a one-paragraph summary a PM can
940
+ read on a phone"*, *"money always carries its currency"*, *"use the customer's
941
+ words, not the internal table name"*. Before this, the shipped rules were the
942
+ only rules.
943
+
944
+ - Three priorities. **P0** must, and it beats every ORC style preference; **P1**
945
+ should, and breaking it is recorded as a gap; **P2** prefer.
946
+ - Stored **verbatim** in `.claude/orc/doc-house-rules.json` one writer,
947
+ `orc doc rules`, outside `templates/` so `orc update` never touches it. A rule
948
+ is one line; a multi-line one is refused by name with the hint to add two.
949
+ - **Each document freezes the set it started with.** If a P0 changes at wave 3,
950
+ half the document silently no longer complies and nothing on disk says so — so
951
+ `orc doc rules <slug>` reports frozen-vs-project and **names every rule that
952
+ was added, changed or removed**, never a "rules changed" boolean.
953
+ `--sync` re-freezes deliberately and **lists the sections that predate the
954
+ change**. It re-writes nothing: that would be ORC spending your money applying
955
+ a rule change retroactively without being asked.
956
+ - **Read FIRST in every dispatched slice**, above ORC's own rules — that order is
957
+ the contract.
958
+ - **The boundary is declared, not detected.** House rules govern content and
959
+ style; they can never change how the lane RUNS. The CLI cannot parse intent, so
960
+ it does not pretend to: it prints the boundary everywhere it matters, and a
961
+ rule that asks for a structural break comes back as `unsupported_request`.
962
+ - New: `orc doc rules [add|remove|enable|disable|move|--sync|--set-file|--reset]`,
963
+ a **House rules** card at the top of `orc ui Docs` (staged and batched, like
964
+ every other write in the panel), and a `house-rules-drifted` audit finding.
965
+
966
+ #### `/orc-doc` four rules ORC applies to every document, all free
967
+
968
+ All four are deterministic lint rules, which is what makes them worth having:
969
+ **no model is ever paid to notice a `TODO`.** Every one is narrow on purpose a
970
+ broad rule that argues with the author gets switched off.
971
+
972
+ - **No questions or confirmations in the body.** The deliverable answers; it does
973
+ not ask. `TBD`, `TODO`, `TBA`, *"to be confirmed"*, and a line that is only a
974
+ question put to you as an approver. **Two exemptions:** fenced code, and a
975
+ section your own outline calls *open questions / risks / assumptions*.
976
+ - **Missing information is `N/A` plus one short line, never filler.** A warning,
977
+ never an error you may have a reason.
978
+ - **A section well over its planned length is a finding** (1.5× its budget), plus
979
+ per-section line and word counts in `orc doc lint --json`. Signals, not gates.
980
+ - **No local-only references.** No `src/foo.ts:42`, no absolute path, no
981
+ `./relative`, no `localhost`, no `file://`, no link to a local `.md` the
982
+ person reading a PRD has no repository. Fenced code is always exempt, because a
983
+ code example that *shows* a path is content. New config `doc_local_refs`
984
+ (`off|warn|error`, default `error`): a genuinely internal runbook legitimately
985
+ names local paths, and a lint rule with no switch gets fought instead of used.
986
+
987
+ #### `/orc-doc` a supplied template is a cage, not a suggestion
988
+
989
+ `--template` set the outline and then nothing stopped a writer adding a heading
990
+ it never had. It now locks by default: the slice carries the allowed headings,
991
+ `orc doc lint` errors on a stray one, **`orc doc parts --confirm` refuses the
992
+ part that grew one and writes nothing**, and `orc doc audit` reports both
993
+ `template-drift` and `template-moved` (your template file itself changed
994
+ reported, never auto-synced). `--template-soft` opts out; a shipped base template
995
+ stays a floor.
996
+
997
+ #### `/orc-doc` — what it will cost, and what it did cost
998
+
999
+ - **`orc doc forecast <slug>` — the run map, once, before the first paid wave.**
1000
+ How many sections, how many waves, how many agents per wave, **how many times
1001
+ it will stop**, and a token range with its sample count. Computed from the same
1002
+ batcher the dispatch uses, so it can never describe a run that will not happen.
1003
+ Every honesty rule of `/orc-budget` is inherited: four token kinds never
1004
+ blended, no dollars without a dated price table, no quota without a known plan
1005
+ and **with no history it refuses rather than invent**, offering the
1006
+ `--naive` price-table floor instead. `orc doc next` names it exactly once; a
1007
+ changed outline or write mode invalidates it.
1008
+ - **`orc doc cost <slug>` — joined across every session the document spanned.**
1009
+ `orc budget actual` works per run, and a document is not a run. Per role and
1010
+ per section, from ORC's traces joined to your local usage transcripts. A slice
1011
+ that covered two sections splits evenly, said out loud; **a section nothing can
1012
+ be joined to reads `—`, never `0`.** `unattributed` is always printed.
1013
+ - Both render in `orc ui ▸ Docs` with a stacked four-kind token bar, so
1014
+ cache-read stays visibly separate from the rest.
1015
+
1016
+ #### `/orc-doc` an edit round tells you where to look
1017
+
1018
+ `orc doc lint <slug> --section <id>` lints one **section file** and returns
1019
+ **part-local** line numbers, and every finding on an edit-round slice carries its
1020
+ file and line. The skill prints one line per finding
1021
+ (`sections/03-scope.md · line 42 · long-sentence`) and, after the round, each
1022
+ file it touched. The compiled `document.md` line number is deliberately never
1023
+ carried: it is stale the moment anything is written.
1024
+
1025
+ #### Fixed the Overview card printed over itself
1026
+
1027
+ `.run-card` is a four-column grid (caret · chip · mid · age) and the Overview
1028
+ built a card with **three children and no caret**, so the chip landed in the 16px
1029
+ caret column and printed straight over an 88px slug, which wrapped one word per
1030
+ line. A grid never complains. Every variant now declares its own column count —
1031
+ `.no-caret` for a row that navigates, `.has-extra` for an optional second chip
1032
+ and the same collision in the Docs list (from its "you edited it" chip) is fixed
1033
+ the same way. The age column now carries the age `run list --json` always knew.
1034
+
1035
+ #### Fixed — a run could never be marked done
1036
+
1037
+ `RESUME.md` existing IS the "unfinished" flag, and ORC deletes it at `FINISH`. So
1038
+ a run you abandoned was waiting **forever**: `orc resume` kept offering it, the
1039
+ Overview kept counting it, and the upgrade preview kept refusing with "N run(s)
1040
+ are still waiting" — with no way out short of deleting a file by hand.
1041
+
1042
+ `orc run close <slug> --reason "<why>"` **moves** `RESUME.md` to
1043
+ `RESUME.closed.md` and records why. **It deletes nothing**, and `orc run reopen`
1044
+ puts it back byte for byte. The new state is **`closed`**, deliberately not
1045
+ `done`: the disk cannot prove a run finished, only that you said you were
1046
+ finished with it. A reason is required — a state change nobody wrote a reason for
1047
+ is a state nobody can audit. Everything else follows from one boolean: `resume`
1048
+ skips it, `run list` keeps the row *and* its reason, and the upgrade unblocks.
1049
+ Buttons for both in `orc ui ▸ Runs`, and inline on the Overview card that was
1050
+ complaining.
1051
+
1052
+ #### Fixed one corrupt challenge ledger 500'd the whole panel
1053
+
1054
+ Two crash classes: a ledger truncated by a killed session, and a ledger with no
1055
+ `goals` key. Both threw a Node stack with nothing parseable on stdout, so
1056
+ `orc ui Challenge` showed a bare 500 — and **every healthy cycle disappeared
1057
+ with the broken one**, which is the opposite of what a listing is for.
1058
+
1059
+ - A broken cycle is now a **row** that reads `UNREADABLE` and carries the parse
1060
+ error. It is a list-level state: it never reaches the pass gate and never
1061
+ claims a verdict.
1062
+ - **No `--json` read can emit a stack trace any more.** A throw comes back as
1063
+ `{ok: false, reason: "crashed", command, error, hint}` with its own exit code —
1064
+ every `--json` route inherits it.
1065
+ - A 500 from the panel's API now carries the CLI's own reason, and the panel
1066
+ renders it. A 500 with no message is what you actually saw.
1067
+
1068
+ ### v0.49.1 the challenge council, and a `--json` that stops throwing things away _(2026-08-18)_
1069
+
1070
+ One release, two workstreams, and **zero new skills**. They ship together because
1071
+ they are the same defect seen twice: **ORC computes far more than it shows.**
1072
+ `computeWikiFreshness` builds a per-doc table that `--json` threw away;
1073
+ `challenge record` computes per-dimension, per-severity, per-iteration detail
1074
+ that the panel rendered as one chip. Both halves are "stop discarding what you
1075
+ already computed" and only one of them also adds new thinking.
1076
+
1077
+ ---
1078
+
1079
+ ## Part A the challenge council
1080
+
1081
+ ### Five more ways of looking, and none of them is ORC's to choose
1082
+
1083
+ `/orc-challenge` had one grounded opinion (the judge) and one blind one (the cold
1084
+ reader), and both read the artifact the same way: *does this document do what a
1085
+ document is supposed to do?* Five ways of looking were missing, and each one is
1086
+ missed for a different reason:
1087
+
1088
+ | Role | It asks | It fails when |
1089
+ |---|---|---|
1090
+ | **The Contrarian** | where is the fatal flaw? | it assumes the artifact is fine and stops looking |
1091
+ | **The First Principles Thinker** | are we even solving the right problem? | it accepts the framing it was handed |
1092
+ | **The Expansionist** | what is being undervalued here? | it only counts what is wrong |
1093
+ | **The Outsider** | what does this assume I already know? | it is an expert and cannot un-know things |
1094
+ | **The Executor** | what do you actually do on Monday morning? | it grades the theory and never the first step |
1095
+
1096
+ > **A lens raises; only the judge resolves. ORC proposes the council; the user
1097
+ > picks it.**
1098
+
1099
+ **`a lane that picks its own council` has broken this contract** registered as
1100
+ the fourth member of the family with `a lane that answers its own interview
1101
+ question`, `a lane that picks its own favourite` and `a lane that fixes what it
1102
+ judged`. A council chosen by ORC is ORC deciding **which kinds of criticism the
1103
+ user is allowed to hear**, which is a bigger decision than any single finding in
1104
+ the run. So `orc challenge init --council` has **no default** and refuses by
1105
+ name, exactly like `--goal` since v0.47.0:
1106
+
1107
+ ```
1108
+ --council is required and has no default. ORC SUGGESTS a roster (from the kind
1109
+ and the goal); the user PICKS it. […] Suggested for --kind tsd:
1110
+ reader,contrarian,executor.
1111
+ (a lane that picks its own council has broken this contract)
1112
+ ```
1113
+
1114
+ `none` is a first-class answer and reproduces the v0.47.0 review exactly. The
1115
+ cost is stated in **dispatches**, never in dollars — `/orc-budget`'s rule: no
1116
+ dollar figure without a dated price table.
1117
+
1118
+ ### Two of them cannot produce a finding without lying
1119
+
1120
+ This is the most important decision in the release.
1121
+
1122
+ **The expansionist.** A finding must carry `serves` the goal element it
1123
+ advances and `record` DROPS one without it. Its entire brief is *"what upside
1124
+ is everyone missing?"*, which by construction is **not** in the stated goal.
1125
+ Given a `serves` field it would either invent a goal element or be silently
1126
+ dropped. So it returns an **opportunity**: no severity, never in `findings[]`,
1127
+ never near the pass gate, always with a `first_step` and a route
1128
+ (`brainstorm | pact | grill | none`). It is conserved — `--take` or `--drop`,
1129
+ both requiring a reason and **this lane never builds one**.
1130
+
1131
+ **The first-principles thinker.** Its most valuable output is *"you are asking
1132
+ the wrong question entirely"*, and in this lane the question is the **frozen
1133
+ goal**. A finding is measured against the goal; a premise challenge disputes the
1134
+ **yardstick**. Those cannot be the same object. It returns a **premise**, and
1135
+ exactly two resolutions exist, both a human's: adopt it (`orc challenge goals
1136
+ --set`, a `regoal` that bumps `goals.version`) or dismiss it with a mandatory
1137
+ reason that stays in the report forever. **The judge never sees that report** —
1138
+ handing a judge a document arguing the frozen goal is wrong would bend every
1139
+ finding it produced afterwards.
1140
+
1141
+ > The three finding lenses feed **the judge**. The two non-finding lenses feed
1142
+ > **the user**. That sentence is the whole architecture.
1143
+
1144
+ ### The gate that makes five extra reviewers safe
1145
+
1146
+ The obvious failure of adding five reviewers is that the judge quietly ignores
1147
+ four of them and the run looks identical while costing five times more.
1148
+
1149
+ > **Every id the council raised must appear in the judge's return with exactly
1150
+ > ONE disposition and a reason. `council_coverage_pct` must be 100.**
1151
+
1152
+ That is conservation applied to **input** instead of to carry-forward, and the
1153
+ CLI enforces it without reading a word of prose: the orchestrator writes a
1154
+ machine JSON beside every council report, and **`orc challenge record` reads that
1155
+ directory itself**. The judge cannot shrink the set by omission, because the set
1156
+ was never the judge's to report.
1157
+
1158
+ ```
1159
+ malformed verdictcouncil coverage is below 100% — every id the council
1160
+ raised needs exactly ONE disposition (adopted | merged | rejected |
1161
+ out-of-goal). Missing: O-003
1162
+ ```
1163
+
1164
+ **An adopted finding keeps the raiser's id.** `C-004` stays `C-004` in the
1165
+ verdict, in the report, in iteration 9 which is what lets the panel say *"the
1166
+ contrarian raised four of the six blockers this iteration"*, and how a user finds
1167
+ out within two rounds whether a lens is worth its money.
1168
+
1169
+ **PASS is computed exactly as before.** An adopted council finding is an ordinary
1170
+ finding from that moment on; `challengeBlocking()`, `challengeOpen()`,
1171
+ `challengeCounts()` and `challengeStateOf()` are untouched. The pass gate learns
1172
+ nothing about the council.
1173
+
1174
+ ### A selected role is never silently absent
1175
+
1176
+ Rule 6 (`NOT-CHECKED` is never silent), extended from dimensions to roles. A
1177
+ roster lens returns either a report or an explicit `{ "lens": …, "ran": false,
1178
+ "reason": }`, and silence is rejected by name:
1179
+
1180
+ ```
1181
+ malformed verdict executor is on the roster but returned neither a report
1182
+ nor an explicit { "lens": "executor", "ran": false, "reason": "…" }.
1183
+ A selected role is never silently absent.
1184
+ ```
1185
+
1186
+ The trace carries it too, so `orc stats` and `/orc-retro` see a NOT-RUN lens and
1187
+ not only the panel:
1188
+
1189
+ ```
1190
+ CHALLENGE iter=2 findings=P0:1/P1:3/P2:6 coverage=100% council=4/5 raised=C:6,O:3,E:2 adopted=9 verdict=FAIL
1191
+ ```
1192
+
1193
+ ### Effort is a measurement, not a cost choice
1194
+
1195
+ `outsider` is `low` for the same reason the cold reader is: a harder-thinking
1196
+ outsider reasons its way *around* an unexplained acronym and reports the document
1197
+ is fine, which is exactly the gap the instrument exists to find. **Nothing may
1198
+ ever upgrade it.** `contrarian` is `high` because at low effort it returns the
1199
+ three surface complaints the free lint already caught for nothing.
1200
+
1201
+ That is why there is **no model or effort config key**: a key that lets
1202
+ `outsider: low` be tuned is a key that lets the instrument be broken.
1203
+
1204
+ All seven lenses are `claude-opus-5`, so **`opus5_only` is a no-op for this lane —
1205
+ it is unaffected, not exempt** and the agent count moves 46 51 with no paired
1206
+ variants.
1207
+
1208
+ ### The reader / outsider seam
1209
+
1210
+ These two are the closest pair in ORC and the one place this release could have
1211
+ shipped a duplicate instrument. The distinction is structural:
1212
+
1213
+ | | `reader` | `outsider` |
1214
+ |---|---|---|
1215
+ | Told the audience | **yes** | **no** |
1216
+ | What it generates | 8–15 questions the artifact *promised* to answer | nothing — it reacts to what is on the page |
1217
+ | What it returns | a **scored** questionnaire (`8/12`) | an **unscored** ranked list of assumed knowledge |
1218
+ | The measurement | *can this be answered from the page?* | *what does this page assume you already know?* |
1219
+
1220
+ They are dispatched with no knowledge of each other. Where they agree, that is
1221
+ recorded as `corroborated_by` the strongest comprehension evidence the lane can
1222
+ produce, and **never an automatic severity bump**.
1223
+
1224
+ ### The roster is frozen, and `council: null` is a real state
1225
+
1226
+ Ledger `version: 2`, additive: every v1 key keeps its name, meaning and position.
1227
+ The roster is a per-cycle **frozen** decision changed only by a recorded
1228
+ `recouncil` event, which bumps `council_version` exactly like `goals.version` —
1229
+ and the iteration rail draws a **third** version break for it, because comparing
1230
+ an iteration judged by three lenses to one judged by six is not a comparison.
1231
+
1232
+ **There is no `challenge_council` config key.** A global default roster would
1233
+ silently answer the one question this release exists to ask. A cycle opened
1234
+ before v0.49.1 reads back with `council: null` and `record` refuses the next
1235
+ iteration by name until it is answered`orc challenge council <slug>` exits 1
1236
+ for that state, because **UNSET is an answer, not an error**.
1237
+
1238
+ ### New commands
1239
+
1240
+ | Command | Does |
1241
+ |---|---|
1242
+ | `orc challenge roles [--kind k] [--json]` | the lens catalogue. Static — it works with no cycle at all |
1243
+ | `orc challenge council <slug> [--json]` | the frozen roster + per-iteration participation (0 set · 1 unset · 3 unknown) |
1244
+ | `orc challenge council <slug> --set <csv\|all\|none> --reason "…"` | a recorded `recouncil` |
1245
+ | `orc challenge note <slug> --from <json>` | opportunities and premises ONLY — it refuses a `findings[]` key by name |
1246
+ | `orc challenge premise <slug> <id> --dismiss --reason "…"` | |
1247
+ | `orc challenge opportunity <slug> <id> --take\|--drop --reason "…"` | |
1248
+
1249
+ ### The panel
1250
+
1251
+ It **derives nothing**: it does not name a lens, does not know which class
1252
+ blocks, does not compute a disposition and does not decide the suggestion. A test
1253
+ greps the panel for every lens display name, every disposition word and every
1254
+ agent name and fails if it finds one.
1255
+
1256
+ New: a **Council card** directly under the goal (a NOT-RUN row keeps its slot
1257
+ with its reason; a NOT-SELECTED row is muted with the line that would add it; the
1258
+ council executor's `monday_morning` list sits here, because it is the most
1259
+ legible thing this lane produces for a non-engineer); a **premise card** that is
1260
+ the loudest thing on the panel when one is open and sits *above* the findings; an
1261
+ **opportunities card** with no severity colour anywhere in it; a lens chip and an
1262
+ `also found by` chip on every finding; and a per-lens legend under the
1263
+ convergence chart.
1264
+
1265
+ There is deliberately **no route for `council --set`** — changing the roster is a
1266
+ decision with a recorded reason the *lane* takes in conversation.
1267
+
1268
+ ### Deliberately absent
1269
+
1270
+ - **An anonymised peer-review round.** It doubles the dispatch count, and the
1271
+ judge's adoption pass already reconciles the lenses. The payoff — *"two
1272
+ advisors independently hit the same thing"* — is `corroborated_by[]` at zero
1273
+ extra cost.
1274
+ - **A chairman agent.** ORC already has one: the advisor groups findings by root
1275
+ cause and orders the fix. Rule 5 still holds no advisor on PASS.
1276
+ - **A `challenge_council` key, any model or effort key, a `block` mode on a
1277
+ council output, a loop cap, and auto-severity from corroboration.**
1278
+
1279
+ ---
1280
+
1281
+ ## Part B the knowledge deepening
1282
+
1283
+ ### `--json is not a summary`
1284
+
1285
+ > A read's `--json` is the WHOLE computed object, not a summary. **A field the
1286
+ > human path prints and the JSON omits is drift and it is drift no lint can
1287
+ > see, because both halves live in one function.**
1288
+
1289
+ `wikiStatus()` computes `computeWikiFreshness(...)` and the terminal branch
1290
+ printed the per-doc FRESH/AGING/STALE counts, **the worst doc's filename** (the
1291
+ thing actually pinning the tier), the top five stale docs with their own
1292
+ distances, and the crosslink boundary state. The `--json` branch emitted five
1293
+ scalars and `blind` **as a count**. The panel therefore *could not* be as
1294
+ detailed as the terminal, no matter how it was written.
1295
+
1296
+ `wiki status --json` now carries `counts`, `worst`, `per_doc[]`, `blind_spot` as
1297
+ the **file list it always was**, `orientation`, `crosslink`, and `free_repairs`
1298
+ reused verbatim from `wiki plan` a user must never be able to pay for what a
1299
+ free step fixes. **Every legacy key keeps its name, position and meaning** (`orc
1300
+ doctor`, the overview tile and `_shared/detecting-artifacts.md` all read them)
1301
+ and the exit code stays 0 in every state.
1302
+
1303
+ ### You can finally see what the wiki contains
1304
+
1305
+ `orc wiki` had six subcommands and **not one of them listed the docs**. A user
1306
+ could learn the wiki was STALE with 14 docs and 47 commits of drift, and could
1307
+ not learn what any of those 14 docs was about.
1308
+
1309
+ | Command | Returns | Exit |
1310
+ |---|---|---|
1311
+ | `orc wiki docs [--json]` | the doc table: tier, its OWN distance, covers, usage, tags, retire hint | 0 · 1 none · 3 unregistered |
1312
+ | `orc wiki show <doc> [--body]` | one doc + its tags + the free repairs that apply to IT | 0 · 2 unreadable · 3 unknown |
1313
+ | `orc wiki coverage [--json]` | % of tracked files covered by ≥1 doc, uncovered set by DIRECTORY | 0 full · 1 gaps |
1314
+ | `orc pattern show <lang> [--body]` | headings, conventions vs invariants, flagged conflicts | 0 · 1 absent · 2 unknown key |
1315
+ | `orc gotcha show <id>` | one entry, EVERY field | 0 · 3 unknown |
1316
+ | `orc gotcha list --archived` | the archive | 0 · 1 none |
1317
+ | `orc gotcha prune --dry-run` | exactly what eviction would archive, and why | 0 none · 1 would prune |
1318
+
1319
+ **`orc wiki coverage` is a REPORT and never a gate.** No threshold, no config
1320
+ key, nothing branches on it a repo that deliberately documents four subsystems
1321
+ out of forty is not broken, and a coverage percentage that starts nagging becomes
1322
+ a number people game. The uncovered set is collapsed to directories and ranked by
1323
+ file count, because *"240 uncovered files, all in `vendor/`"* and *"12 uncovered
1324
+ files, all in `src/payments/`"* are opposite situations.
1325
+
1326
+ **`--body` is opt-in** on both `wiki show` and `pattern show`: prose is returned
1327
+ only on an explicit request, exactly one artifact at a time, rendered as DOM and
1328
+ never as HTML.
1329
+
1330
+ **`orc pattern show` invents nothing.** The codifier may not write a parseable
1331
+ header today; with none it returns `headered: false` plus the headings it could
1332
+ parse, and says so in one line. It **never** derives a "codified at" from the
1333
+ file's mtime — the `/orc-pact` UNCHECKABLE rule.
1334
+
1335
+ ### Two doctor findings, and the restraint is the design
1336
+
1337
+ | id | Warns when | Fix |
1338
+ |---|---|---|
1339
+ | `wiki-unregistered` | the wiki is unregistered, drifted or corrupt | `orc wiki sync` — free, instant, and until it is done nothing can read the wiki at all |
1340
+ | `wiki-debt` | tier is **STALE** and `wiki plan` has pending rows | `/orc-wiki refresh --top 2` |
1341
+
1342
+ **`wiki-debt` fires on STALE and never on AGING.** Aging is a normal state every
1343
+ living repo passes through, and a doctor that warns about it is a doctor people
1344
+ learn to ignore. Deliberately not added: `pattern-missing` a project with no
1345
+ cached pattern is not misconfigured, and warning about it would be ORC nagging
1346
+ for a paid scan.
1347
+
1348
+ Both route to the Knowledge panel: *a caution routes to the panel that can CLEAR
1349
+ it*, and `orc wiki sync` is a button there.
1350
+
1351
+ ### `orc ui Knowledge` five tabs
1352
+
1353
+ ```
1354
+ Knowledge [ Wiki ] [ Coverage ] [ Code patterns ] [ Memory ] [ Peers ]
1355
+ ```
1356
+
1357
+ A header strip renders above them all — tier · docs · covered % · blind ·
1358
+ pending · patterns · repair notes — and **a value the CLI could not compute
1359
+ renders as an em dash, never as a guess.**
1360
+
1361
+ - **Wiki** the tier card with the **worst doc named** (a hash is not something
1362
+ anybody can go and refresh), the per-doc counts as a stacked bar, free repairs
1363
+ above everything priced, and **the doc table**. A row expands in place, one at
1364
+ a time, detail fetched on first open.
1365
+ - **Coverage** one honestly-qualified number, the uncovered set by directory,
1366
+ the structural blind spot as the file list it always was, and one line that is
1367
+ not optional chrome: coverage is a report, not a target.
1368
+ - **Code patterns** — per language, with **the conflicts the codifier flagged in
1369
+ their own block**: they are the most decision-shaped thing in the file and were
1370
+ invisible outside it. Reveal shows the text that is injected literally into
1371
+ every executor slice; a user who cannot read it cannot trust it.
1372
+ - **Memory** every field the CLI already emitted, headroom against
1373
+ `gotchas_max`, and a **preview-then-apply prune that names every entry** (a
1374
+ count is not consent). The archive is reachable and labelled recoverable.
1375
+ - **Peers** compact, read-only, every word the CLI's. It links to Crosslink and
1376
+ never duplicates its editor: one boundary, one picture.
1377
+
1378
+ ### Guards
1379
+
1380
+ Five new agent files named explicitly in `verify-package.js` (floor 46 51,
1381
+ skills unchanged at 38); five new contract-lint entries; a golden test comparing
1382
+ `CHALLENGE_LENS_META` to `council.md`'s roster table; and one test per new read,
1383
+ because `--json is not a summary` is drift no lint can catch.
1384
+
1385
+ `css/panels/knowledge.css` is a new file, so it is `<link>`ed in `app.html` **and**
1386
+ named in `verify-package.js` the manifest is the load order, and a file the
1387
+ manifest forgot is a file the test suite never sees.
1388
+
1389
+ ---
1390
+
1391
+ ### v0.49.0the document is a folder, and the file is a build artifact _(2026-08-17)_
1392
+
1393
+ `/orc-doc` only. No other lane changes, and **zero new agents**.
1394
+
1395
+ Three quarters of what this release is about already existed: `orc doc plan`
1396
+ already wrote one part file per section, the ids were already number-then-name,
1397
+ the split already cut on `## ` alone, and `orc doc assemble` was already pure
1398
+ Node — **zero model tokens, and it always was**. Anyone who tells you this
1399
+ release made compiling cheaper is selling something.
1400
+
1401
+ What was wrong was the direction of the arrow.
1402
+
1403
+ #### `sections/` is the source of truth
1404
+
1405
+ `.work/` was scratch and `document.md` was the truth, so after the first
1406
+ assemble every later change was *extract* (copy a section OUT of the monolith) →
1407
+ edit *splice* (write it back IN). The section files existed and were dead. A
1408
+ resumed session, an update and a re-check all routed through the 10,000-line
1409
+ file.
1410
+
1411
+ Now each section lives in `sections/<NN>-<slug>.md` a real, visible folder you
1412
+ can open, edit and read in a pull request — and **`document.md` is a build
1413
+ artifact** that `orc doc compile` rebuilds from those files, for free, when you
1414
+ ask. `orc doc split` goes the other way and recovers the sections from a
1415
+ document a human reshaped by hand; **`split` then `compile` reproduces the file
1416
+ byte for byte**, and there is a test.
1417
+
1418
+ The join key is the **filename**. No comment markers inside the files: an HTML
1419
+ comment is a lint error in this lane and mangles on a Notion or Google Docs
1420
+ import, and the deliverable's cleanliness is the lane's entire product. A marker
1421
+ that buys nothing costs the import.
1422
+
1423
+ #### You can look before you buy the rest
1424
+
1425
+ `orc doc compile --partial` writes exactly the sections that exist and **names
1426
+ the rest outside the document** nothing is ever stubbed into the deliverable.
1427
+ Paired with the new `doc_write_mode` (`ask` · `partial` · `all`, asked once per
1428
+ run and stored), `orc doc plan --role write` returns **wave 1 only**, with
1429
+ `more_waves: N`. You read what it wrote, and waves 2..N are bought only if wave 1
1430
+ was right. That is the single biggest saving in the lane, and it has nothing to
1431
+ do with the compile.
1432
+
1433
+ #### A wave is a stop you can walk away from
1434
+
1435
+ The write loop used to live in the orchestrator's head, and `/orc-doc`'s
1436
+ `RESUME.md` sat in the document folder — where `orc resume` and `orc run list`
1437
+ never look — carrying a `## Where it stands:` line that the line-anchored parser
1438
+ **could never match**, and no phase and no wave even if it had.
1439
+
1440
+ All four are fixed. `RESUME.md` moves to `{run_dir}/{slug}/`, the line is at
1441
+ column 0 and gains a phase D6 · wave 2 of 7` suffix (the byte-stable prefix is
1442
+ untouched), and a test feeds the shipped template to the real `parseStands`. The
1443
+ section files on disk ARE the progress, so `K of N` is **computed** by counting
1444
+ waves whose sections are all hash-confirmed. A part on disk that no validated
1445
+ return ever confirmed is `unconfirmed` — exactly what a usage limit leaves and
1446
+ it is re-written, never shipped.
1447
+
1448
+ #### The deliverable carries content only
1449
+
1450
+ `> **Open:**` and `> **Assumption:**` lines are no longer written into your
1451
+ document, and the section state no longer sniffs the body text for them. This
1452
+ does not relax "never invent a fact"; it moves where the honesty is written down.
1453
+ A gap goes to `orc doc log --kind gap` and lands in a derived `gaps.md`, and is
1454
+ raised with you.
1455
+
1456
+ `orc doc lint` gains `annotation-in-body` as an **error**, matching an exact,
1457
+ narrow set of ORC's own markers and nothing else — a line of yours beginning
1458
+ "Note:" is content and is never flagged. `compile` **reports** every match and
1459
+ never silently strips one: we cannot tell whose line it is.
1460
+
1461
+ #### A live bug, fixed by construction
1462
+
1463
+ A slice covering two sections wrote **one** file, named after the first, while
1464
+ `assemble` looked one up per outline id. The second section's file never existed:
1465
+ if it was required, assemble refused forever; if it was optional, it silently
1466
+ vanished from the deliverable. **One file per section** now, per slice entry, with
1467
+ a regression test.
1468
+
1469
+ #### A section too big for one file
1470
+
1471
+ It splits **underneath** `sections/04-detailed-design/{00-head,01-data-model,…}.md`
1472
+ — cut on its own `### ` headings, which `docScan` already collected and merely
1473
+ filtered out. The reader never knows: the compiled document has exactly one `## `
1474
+ for it, and `orc doc map`, `lint`, `ship` and `audit` are completely unchanged.
1475
+ Five refuse-and-name rules make the nesting safe, and a changed sub-part is
1476
+ detected on its own, so a re-check inside a 900-line section reads ~150 lines.
1477
+
1478
+ **No new config key** for it: `doc_max_lines_per_agent` is already the threshold.
1479
+
1480
+ #### The rest
1481
+
1482
+ - **`doc_max_parallel` hard cap is now 2** (default 2, was 4/4). A larger value
1483
+ is clamped and the clamp is announced.
1484
+ - **`orc doc parts`** is the new wave-boundary read, and the one that works
1485
+ before a single compile has ever run. `--confirm <ids>` is how a validated
1486
+ return becomes a recorded hash.
1487
+ - **`orc doc ship` refuses on a stale `document.md`**, naming the sections
1488
+ coverage-relative, one step earlier than `shipped-drifted`.
1489
+ - **`orc doc audit`** gains `part-missing`, `part-orphan`, `part-misnumbered`,
1490
+ `part-unconfirmed`, `subpart-bad-level`, `document-stale`,
1491
+ `annotation-in-body`, `legacy-work` and `resume-misplaced`.
1492
+ - **`orc doc outline --set` renames the files on disk** when a renumber moves
1493
+ them, in the same step.
1494
+ - **A checker now reads ONE bounded part file**, so there is no line arithmetic
1495
+ anywhere in the check loop.
1496
+ - The Docs panel gains a **Section files** card with nested sub-part rows, a wave
1497
+ strip, a compile button and a migrate button. It derives nothing new: the CLI's
1498
+ state words, verbatim.
1499
+
1500
+ #### Nothing is lost on the way
1501
+
1502
+ `doc.json` goes to `version: 2` and a v1 document migrates the first time you
1503
+ touch it lazy, free, idempotent, non-destructive. `document.md` is **never
1504
+ deleted** (it becomes the build artifact, and starts life fresh rather than
1505
+ stale), a pending extract wins as the newer edit, an `> **Open:**` stub does not
1506
+ survive, `RESUME.md` is moved and its prefix stripped, and an **unparseable**
1507
+ document is REFUSED with `version` left at 1 a guessed structure is worse than
1508
+ none. `assemble`, `extract` and `splice` survive as thin aliases for one release,
1509
+ with their exit codes preserved.
1510
+
1511
+ ---
1512
+
1513
+ ### v0.48.1 one file per thing, and a document that can be finished _(2026-08-16)_
1514
+
1515
+ Two halves, deliberately kept separate so that **any** behaviour difference
1516
+ observed after this release is attributable to the second one and to nothing
1517
+ else.
1518
+
1519
+ #### The panel is an architecture now
1520
+
1521
+ `bin/webui/` was four monoliths: a 6 500-line `app.js`, a 2 500-line
1522
+ stylesheet, a 1 700-line fixture module and two 800-key string tables. Any
1523
+ change to one panel meant paging through all of it to find three places.
1524
+
1525
+ It is now ~60 named files one per panel, one per CSS layer, one per i18n
1526
+ namespace, one per fixture set — and the **filename is the load order**, so a
1527
+ future session never has to reason about dependencies.
1528
+
1529
+ - **Classic scripts, not ES modules,** and the constraint that decided it:
1530
+ `serve.js` requires the per-launch token on every static request, and **an
1531
+ `import` carries no query string**. A module graph would 401 on every import
1532
+ unless static auth were weakened, which was not on the table. Classic scripts
1533
+ also share one global lexical scope, so the split added no `import`/`export`
1534
+ and changed no call site.
1535
+ - **`serve.js` builds its static map from a one-time walk at boot.** A request
1536
+ path is still a KEY LOOKUP in a frozen table, never a path join — directory
1537
+ traversal stays structurally impossible. Server-side code (`serve.js`,
1538
+ `api.js`, `fixtures/`) is never served.
1539
+ - **Token stamping is generic.** Naming two files was fine when there were two;
1540
+ with ~55 the pattern has to be the rule, or the next `<script>` tag someone
1541
+ adds 401s silently. A test parses `app.html` and asserts every reference comes
1542
+ back stamped **and** resolves.
1543
+ - **`06-responsive.css` and `04-motion.css` load last, and that is
1544
+ load-bearing.** Several reduced-motion rules are deliberately not
1545
+ `!important` `.vault-pulse` and `.step-flow` are removed with
1546
+ `display: none`, because capping an infinite animation to one iteration
1547
+ freezes it mid-cycle so an equal-specificity rule loading afterwards would
1548
+ win on order and switch the animation back on.
1549
+ - **`verify-package.js` names every file AND asserts set equality** with the
1550
+ directory, in both directions: the agent-file pattern, applied to the panel.
1551
+ - The test suite is split to match (`test/cli/`, `test/lanes/`, `test/webui/`),
1552
+ using an `appJs()` / `appCss()` helper that concatenates exactly what
1553
+ `app.html` loads — so a file the manifest forgot cannot hide behind a passing
1554
+ suite.
1555
+
1556
+ **No behaviour changed.** All 274 tests pass, all 17 panels render in both
1557
+ themes and both languages with zero console errors, and the guided tour runs end
1558
+ to end.
1559
+
1560
+ #### `/orc-doc` has a finish line
1561
+
1562
+ - **`orc doc next`** turns the pipeline from something the orchestrator
1563
+ REMEMBERS into something the CLI COMPUTES the Flow-stepper shape, and for
1564
+ the same reason: D6–D9 was prose a session had to hold in its head across a
1565
+ resume that might be months later in a fresh context. Exit **0** = an action
1566
+ is available (`command`, plus `paid` so a caller knows button vs copy-able
1567
+ command), **1** = waiting on a human decision, **named** in `blocked_by`,
1568
+ **2** = unknown slug.
1569
+ - **`orc doc ship` records delivery as a DECISION** (`/orc-pact`'s rule) while
1570
+ the resulting state stays **COMPUTED** (`/orc-challenge`'s rule). `--where`
1571
+ has **no default** — "shipped" with nowhere to point at is not a fact, it is a
1572
+ feeling and shipping an incomplete document needs `--force --reason`,
1573
+ recorded verbatim. `unship` needs a reason and keeps the old record in
1574
+ `ship_history[]`.
1575
+ - **`shipped-drifted` names the sections that moved,** by diffing the recorded
1576
+ per-section hashes against the live map. Coverage-relative, the
1577
+ `computeWikiFreshness` lesson applied to a document: a whole-file "something
1578
+ changed" cannot tell you what to re-read. It exits **1**, because the document
1579
+ moved after it was delivered and that is work.
1580
+ - **`orc doc audit`** reports every drift class from disk an extract never
1581
+ spliced back, an extract whose section moved under it, a heading a hand edit
1582
+ deleted or added, a target that no longer matches the file, a reference file
1583
+ that moved, a cycle count that disagrees with itself each with a fix command
1584
+ and the panel that can clear it. A hand-edited section is **reported and never
1585
+ counted as a finding**: flagging it would teach people to stop editing their
1586
+ own document. `orc doctor` gains a `doc-drifted` finding routed to Docs.
1587
+
1588
+ #### And it remembers what you asked for
1589
+
1590
+ This was a **data** gap, not a rendering one. `created_at` existed and
1591
+ `orc doc show --json` never emitted it; `context.md` and `context-sources.md`
1592
+ were files the CLI never opened; and what the user actually ASKED FOR, in order,
1593
+ across every session, lived nowhere at all.
1594
+
1595
+ - **`orc doc log` / `journal`** record and serve it. The journal merges four
1596
+ sources into one chronological array with the provenance of every row attached
1597
+ `recorded` (the user's own words, verbatim), `derived` (a cycle, a ship
1598
+ record), `observed` (a section that turned `user-edited`) — and **it never
1599
+ invents an entry**: a cycle that ran with nothing logged renders as an explicit
1600
+ gap, never a plausible reconstruction from file mtimes. The `/orc-pact`
1601
+ UNCHECKABLE rule: not knowing is an answer, and faking it teaches people to
1602
+ distrust the rows that are real.
1603
+ - **`orc doc context`** returns the frozen brief the verbatim request first,
1604
+ because that is the memory-regain payload plus the D2 reference table with a
1605
+ live state per file: `ok`, `MISSING`, `SOURCE-DRIFTED`. A source is stale
1606
+ only when THAT FILE moved, never because the repository did, and it is a
1607
+ **warning, never an error**: a frozen context is *supposed* to be old.
1608
+ - **`orc doc read`** is a reader for the HUMAN — and the rule table says out
1609
+ loud that the orchestrator never runs it, registered as a contract token so
1610
+ the sentence cannot quietly disappear.
1611
+ - **The Docs panel is rebuilt around this: MEMORY FIRST, state second.** The
1612
+ header strip, the brief, the reference files and the journal come before the
1613
+ ribbon because a user coming back after three weeks did not come back to ask
1614
+ what state the document is in.
1615
+
1616
+ #### One more way in
1617
+
1618
+ D4 and D5 gain a `RETURN-TO` suspend into **`/orc-grill`** gated on all
1619
+ three of the `_shared/lane-suspend.md` tests (a DECISION not a fact, a
1620
+ PREREQUISITE that changes the option set, a SUBTREE with more than one question
1621
+ hanging off it), or it asks inline. The snapshot is **run state, never the
1622
+ deliverable**, so hard rule 10 still holds; and on resume the lane re-writes
1623
+ `.current` and touches the trace file in the same step, because `/orc-grill`
1624
+ deleted the pointer at its own `FINISH`. Two traces for one document is
1625
+ correct two lanes ran.
1626
+
1627
+ ---
1628
+
1629
+ ### v0.48.0a document long enough to end a session, written anyway _(2026-08-13)_
1630
+
1631
+ **`/orc-doc`** writes the long document a PRD, a TSD, a cross-team
1632
+ collaboration agreement, a status report or a workflow/runbookas portable
1633
+ Markdown, and it survives the session that started it.
1634
+
1635
+ Two contracts hold the lane together, and everything else serves them:
1636
+
1637
+ > **The orchestrator never reads the document body.** It knows the document only
1638
+ > through the CLI's derived section map and through what the agents it
1639
+ > dispatched report back. **a lane that reads its own document** has broken this
1640
+ > contract.
1641
+
1642
+ > **The context is gathered once and frozen.** A resumed session reads
1643
+ > `context.md` from disk; it never re-interviews the user for what session 1
1644
+ > already settled. **a lane that re-asks a frozen question** has broken this
1645
+ > contract.
1646
+
1647
+ - **The token architecture is the lane.** A 900-line TSD is ~30k tokens; read it
1648
+ three times and the session is over. So nothing that holds context ever holds
1649
+ the document. `orc doc map` derives a section map — heading, absolute line
1650
+ range, SHA-256, computed state each writer owns **one `.work/` part file**,
1651
+ and each checker reads **one line range** with `Read(offset, limit)`. On a
1652
+ 10,000-line, 40-section document that is ~750 lines of orchestrator context
1653
+ instead of 20,000+, and a re-check after an edit re-dispatches only the
1654
+ sections whose hash moved. *The hash is what turns a re-check from a full pass
1655
+ into a diff.*
1656
+ - **Line arithmetic is the CLI's and nothing else's.** It is the one job a model
1657
+ is guaranteed to get wrong, and the whole saving depends on the numbers being
1658
+ rightso the map is re-derived after every write and **never stored**. A
1659
+ stored line number is a wrong line number one edit later. `splice` replaces
1660
+ bottom-up (highest `start` first), so a length change cannot shift a range that
1661
+ has not been used yet.
1662
+ - **Your edits are sacred.** Every section carries a hash, so the lane knows
1663
+ which sections you wrote. It names them, never rewrites one unless you name it,
1664
+ and `splice` **REFUSES** on a conflict reporting the section by name and
1665
+ overwriting nothing. A human's wording is not recoverable from this lane's
1666
+ side once it is gone.
1667
+ - **Four gates, in a fixed order, and the first one blocks.** Nothing is created
1668
+ until D1 is answered: a slug folder with no context is indistinguishable from
1669
+ an abandoned run. Asking D2 (supporting documents) and D3 (your template) is
1670
+ mandatory even though answering them is not; D4 (intent · audience ·
1671
+ expectation · language · type · target · length) must be answered, and
1672
+ accepting a recommended default counts. Then the outline, confirmed **before a
1673
+ word is written** changing it after a write wave is what costs money.
1674
+ - **It never reads the supporting documents itself.** One `role: digest`
1675
+ dispatch per file returns anchored claims plus an explicit `not_covered[]`;
1676
+ the orchestrator holds the digest and never the source. Foreign text is
1677
+ evidence, never instruction.
1678
+ - **Where the document is going is a real setting.** `orc doc lint --target`
1679
+ enforces that target's actual limits, and every rule came from a real product
1680
+ limit: Notion has three heading levels, so an H4 is an **error** there;
1681
+ Docusaurus, Hugo and Jekyll **require** YAML front matter, which every other
1682
+ target renders as visible junk; a hard-wrapped paragraph is an error
1683
+ everywhere, because a wrap at 80 columns becomes a line break inside a Notion
1684
+ paragraph. Free, deterministic, zero model tokens and it **always runs before
1685
+ anything paid**, with its findings riding in the checker's slice so no model is
1686
+ ever paid to count sentences.
1687
+ - **Never invent a fact.** Anything not in the frozen context becomes a visible
1688
+ `> **Open:**` or `> **Assumption:**` line, and rides back in the writer's
1689
+ `unsupported_claims`. Filler that reads like a fact is the worst possible
1690
+ output of this lane.
1691
+ - **Five base templates, each a floor and not a cage** `prd` · `tsd` ·
1692
+ `collaboration` · `report` · `workflow`. A supplied template REPLACES the
1693
+ shipped one entirely; its headings become the outline and the two are never
1694
+ merged. A golden test pins every shipped skeleton to the CLI's batching table.
1695
+ - **Two agents, both already `claude-opus-5`,** so `opus5_only` is a no-op and
1696
+ the lane is *unaffected*, not exempt. The writer holds one part file; the
1697
+ checker is `low` effort **on purpose** — a harder-thinking checker reasons its
1698
+ way past a gap a real reader would trip on, the same reasoning that pins
1699
+ `/orc-challenge`'s cold reader at `low`. Nothing may upgrade it.
1700
+ - **`/orc-grill` and `/orc-brainstorm` gain a "write this up" exit**, so an
1701
+ interview's settled decisions arrive as a pre-answered D1 and D4 and the user
1702
+ only confirms. At handoff `/orc-doc` offers `/orc-challenge` in a separate
1703
+ session, which is the separation `/orc-challenge`'s own contract already
1704
+ enforces from the other side.
1705
+ - **The `orc doc` CLI family** (13 subcommands, every read `--json`, every one an
1706
+ exit-code contract), four config keys (`doc_max_lines_per_agent`,
1707
+ `doc_max_parallel` with a **hard cap of 4**, `doc_language`, `doc_dir`), and a
1708
+ **Docs panel** in `orc ui` whose ribbon draws the whole document in one
1709
+ picture one block per section, sized by its length and coloured by its state.
1710
+ - Counts move: **skills 37 38 · commands 28 29 · agent files 44 → 46.**
1711
+
1712
+ ---
1713
+
1714
+ ### v0.47.0 the lane that refuses to produce _(2026-08-12)_
1715
+
1716
+ **Every other lane in ORC — and nearly every other skill in the ecosystem —
1717
+ produces. This one refuses to.** `/orc-challenge` grades a finished artifact,
1718
+ writes down what is wrong, and then stops and makes the user go away and fix it
1719
+ somewhere else. The stopping is not friction: **the separation is the measuring
1720
+ instrument.**
1721
+
1722
+ **The one-sentence contract: ORC judges, the user fixes, ORC re-judges — and ORC
1723
+ never fixes what it judged.** A session that just wrote the fix will grade its
1724
+ own homework and it will always pass. That registers as the third member of an
1725
+ existing pair `a lane that answers its own interview question` (v0.42.0),
1726
+ `a lane that picks its own favourite` (v0.45.0), and now **`a lane that fixes
1727
+ what it judged`**. Same split every time: facts and findings are ORC's, the work
1728
+ and the decision are the user's.
1729
+
1730
+ **Rule 0 precedes every other rule: it never guesses the goal.** A finding is
1731
+ only a finding relative to a goal the same TSD is *finished* for one purpose
1732
+ and nowhere near done for another. A lane that assumes will attack the wrong
1733
+ thing with total confidence, and every one of its findings will be *defensible*,
1734
+ which is worse than being obviously wrong: the user spends three iterations
1735
+ fixing what did not matter. So intake ASKS, in ONE round, for the goal, the
1736
+ audience, what "done" means, the template, and where the fixed version will go —
1737
+ and freezes them to `goals.md`. **`orc challenge init` has no default for
1738
+ `--goal`, `--audience` or `--done-means`**, so a run that tried to skip the round
1739
+ fails at the CLI by name instead of inventing a purpose. Every finding must name
1740
+ which goal element it `serves`; one that cannot is **dropped**, which is the
1741
+ mechanism that stops a large context window from reviewing the entire universe.
1742
+
1743
+ **Three agents, and they are three different INSTRUMENTS, not three tiers.**
1744
+
1745
+ - **`orc-challenge-reader-opus-5-low`** — the cold read. Tools: `Read` and
1746
+ nothing else. It is given the artifact and the audience line, never the goal,
1747
+ and it answers questions FROM the artifact rather than reviewing it. Returns a
1748
+ scored questionnaire (`8/12`). **`low` effort is a measurement choice, not a
1749
+ cost one:** a harder-thinking reader reasons around exactly the gaps this
1750
+ exists to find, so a stronger configuration is a WORSE instrument.
1751
+ - **`orc-challenge-judge-opus-5-high`** grades against the frozen template and
1752
+ goal. Its slice is **SEALED**: paths and finding ids only, never prose from the
1753
+ session, never a diff summary, never "the user says they fixed #4". A fix is a
1754
+ claim; a verdict is evidence. **It cannot declare a pass** `orc challenge
1755
+ record` computes that, which removes leniency as a possibility.
1756
+ - **`orc-challenge-advisor-opus-5-med`** dispatched only on a FAIL (advice on a
1757
+ passed artifact is invented work and it costs money). Twelve findings are
1758
+ usually three causes: it groups them by root cause, orders them with the
1759
+ dependency reason, and flags the ones that are really unmade DECISIONS. No
1760
+ prose, no diffs — handing over wording is fixing by another name.
1761
+
1762
+ All three are already `claude-opus-5`, so `opus5_only` is a no-op here: zero new
1763
+ pairs, no rename churn. The lane is **unaffected, not exempt**.
1764
+
1765
+ **`orc challenge lint` the deterministic engine, and it costs zero model
1766
+ tokens.** Structure against the frozen template (missing / out-of-order /
1767
+ invented / empty-ceremony sections, table column drift, untagged code fences,
1768
+ links and `file:line` anchors that do not resolve) plus prose (acronyms used
1769
+ before they are defined, sentences over 25 words with a p50/p90 distribution, a
1770
+ passive-voice percentage, curated idioms and phrasal verbs, ambiguous
1771
+ quantifiers, bare-pronoun openers, placeholder markers, a Flesch–Kincaid
1772
+ estimate). **Sentences are measured over PARAGRAPHS, not lines** a hard-wrapped
1773
+ 43-word sentence is still a 43-word sentence, and splitting at the newline is how
1774
+ a length check silently passes every wrapped document. Two honesty rules are
1775
+ printed by the command itself: it is a SIGNAL, not a verdict, and it is
1776
+ English-specific and heuristic. Its real payoff is that `lint.json` rides in the
1777
+ judge's slice, so the judge never spends tokens counting. It is useful with no
1778
+ cycle, no model and no ORC run at all: `orc challenge lint README.md`.
1779
+
1780
+ **Conservation nothing evaporates.** Every finding from iteration N−1 appears
1781
+ in N with exactly ONE outcome (`resolved` · `still-open` · `superseded` ·
1782
+ `withdrawn` · `accepted`) and a reason; below 100% coverage the verdict is
1783
+ malformed and `record` rejects it **naming the missing ids**. A silently dropped
1784
+ finding is indistinguishable from a fixed one, and that is the classic way a
1785
+ review cycle appears to converge. `record` also rejects an unknown carry id, a
1786
+ reasonless withdrawal, an uncited supersede, an **ignored rebuttal**, and a
1787
+ **silent dimension** `NOT-CHECKED` with a reason is allowed, silence is not.
1788
+
1789
+ **Two escape valves, because a loop with no exit is a trap.** `orc challenge
1790
+ accept <slug> <id> "reason"` — the finding stops blocking immediately and stays
1791
+ visible forever in the report with the reason; never automatic (the `/orc-pact`
1792
+ retirement rule). `orc challenge rebut <slug> <id> "reason"` the next judge
1793
+ must answer it explicitly, `withdrawn` with an admission or `upheld` with new
1794
+ evidence, and a verdict that ignores it is rejected. Without it, one wrong
1795
+ finding loops forever and the user's only move is to give up.
1796
+
1797
+ **Convergence, not a cap.** There is deliberately no loop cap and no config key
1798
+ for one: every other loop in ORC runs inside a single session and costs tokens
1799
+ per turn, but here each turn is a separate human sitting down to work, and a cap
1800
+ that refused on iteration 6 would be refusing to review a hard document. It
1801
+ reports `stalled` instead once, with three honest options.
1802
+
1803
+ **Seven states, all COMPUTED, none stored** `AWAITING-JUDGE`, `AWAITING-FIX`,
1804
+ `AWAITING-RECHECK`, `PASSED`, `STALE-PASS` (honest, not a failure the
1805
+ `UNCHECKABLE` precedent), `MISSING-REVISION`, and `TAMPERED` (a verdict file
1806
+ changed after it was recorded: reported, never silently re-graded). Two flags
1807
+ ride alongside rather than becoming states of their own, because a state that
1808
+ means two things is a state that lies: `stalled` and `no_template`.
1809
+
1810
+ **The resumed session never asks where the fix went.** `revision_mode` is
1811
+ declared at intake and restated in a `Where to put the revised version` block in
1812
+ every fix brief; `orc challenge diff` resolves the expectation first and then
1813
+ reports which carried findings the change actually TOUCHED
1814
+ coverage-relative, the `computeWikiFreshness` lesson applied to findings, and a
1815
+ hint for the human that is **never an input to the judge**. When the declared
1816
+ path is not there, `MISSING-REVISION` **lists candidates and never adopts one**:
1817
+ picking the closest-looking file would point the judge at the wrong artifact and
1818
+ produce a page of confident, useless findings. The escape (`orc challenge expect
1819
+ --set`) is a recorded command.
1820
+
1821
+ **The CLI half: 12 subcommands, every read with an exit-code contract and
1822
+ `--json`.** `list` (0/1/3) · `status` (0/1/2/3) · `show` · `diff` (0/1/2/3) ·
1823
+ `expect` · `lint` (0/1/2) · `outline` · `record` (the GATE, not a store) ·
1824
+ `accept` · `rebut` · `template`/`goals` (re-freezing is a recorded event that
1825
+ needs a reason, and prior iterations keep their stamp) · `report` (derives
1826
+ `CHALLENGE.md`, plus the final report on a pass). `challenge.json` has exactly
1827
+ one writer, and it is never a model.
1828
+
1829
+ **The `orc ui` Challenge panel** renders it and decides nothing about it: the
1830
+ goal block above everything, the state chip with its ONE next action inline, an
1831
+ iteration timeline whose **geometry is solved from the box size** (with a dashed
1832
+ version break wherever a goal or template was re-frozen), the convergence chart
1833
+ stacked by severity, a dimension strip where `NOT-CHECKED` keeps its slot and
1834
+ carries its reason, the cold reader's score, and the findings with their accept /
1835
+ rebut buttons. **A free action gets a button, a paid action gets a copy-able
1836
+ command** running an iteration has no write route at all. `--fixtures` carries
1837
+ one of every state including the ugly ones, and a test asserts it.
1838
+
1839
+ **Four config keys**, all `common`: `challenge_pass_severity` (default `p1`),
1840
+ `challenge_stall_after` (3), `challenge_reader` (`on`; `off` makes D4 report
1841
+ `NOT-CHECKED` with that reason, never silently), and `challenge_gate` (`warn`;
1842
+ there is deliberately no `block`the `/orc-pact` precedent). Deliberately NOT
1843
+ added: a same-session escape hatch (that is how the premise dies), any model or
1844
+ effort key, and any loop cap.
1845
+
1846
+ **Seams:** `/orc` prints one preflight line when it is about to build from a
1847
+ document that has not passed its own review; `/orc-analyze` prints the cycle
1848
+ state at Phase A (the two compose in one order challenge it, then analyze it);
1849
+ `/orc-pact` gains the finding-that-is-really-a-decision harvest; intake's "I
1850
+ don't know yet" suspends into `/orc-grill` and comes back; `/orc-export` can
1851
+ carry a PASSED cycle as portable evidence.
1852
+
1853
+ **Trace:** lane `challenge`, **Iterative tier** (one packet per completed
1854
+ iteration), and a new `CHALLENGE iter=…` verb whose line the CLI assembles so
1855
+ nothing composes a second wording for the same number. Several trace files for
1856
+ one cycle is CORRECT — several sessions ran.
1857
+
1858
+ ### v0.46.1 — see a lane run before you pay for one _(2026-08-12)_
1859
+
1860
+ **The docs answered "what is ORC" four times and never answered "what does a
1861
+ lane look like when it runs".** Rides on top of v0.46.0, below.
1862
+
1863
+ **`mock-run/`one written walkthrough per lane.** What you type, what ORC
1864
+ prints back, what lands on disk, in easy English, all on one shared example
1865
+ project. Nothing was executed to make them: they exist so nobody has to spend
1866
+ tokens to find out what a command does. Start at `mock-run/INDEX.md`.
1867
+
1868
+ **`orc mock-run list | show <slug>`** reads the same catalogue from the
1869
+ terminal, and **`orc ui` grows a Mocked Skill Use panel** every walkthrough,
1870
+ grouped, searchable, with a reading pane. The catalogue is DERIVED from the
1871
+ files on disk (title from the heading, lane from whether the command really
1872
+ exists), so adding a walkthrough needs no list edited anywhere; the panel
1873
+ renders it and decides nothing about it, exactly like the Flow stepper.
1874
+
1875
+ **The README is 928 lines shorter and current.** It was still describing an
1876
+ older payload — the six v0.46.0 lanes were missing from the panel list, the
1877
+ config table showed 11 of 52 keys, and the eval section quoted a round from four
1878
+ releases ago. History moved here to `CHANGELOG.md`, which is now what `orc
1879
+ changelog` fetches: a README carrying one entry would have answered a user ten
1880
+ releases behind with a single line. The detail that used to bloat it lives in
1881
+ `guides/configuration.md` and `guides/model-selection.md`.
1882
+
1883
+ **Two real bugs found while building it.** The panel's markdown renderer looped
1884
+ forever on a malformed table row (the paragraph branch is the fall-through, so a
1885
+ line every branch declined never advanced the cursor), and an upgrade modal
1886
+ showed the newest release with `## Earlier releases` glued to the end of it —
1887
+ an entry now stops at the next section heading, not just at the next release.
1888
+
1889
+ ---
1890
+
1891
+ ### v0.46.0a lane that remembers, a lane that declines, and a lane that measures _(2026-08-10)_
1892
+
1893
+ **The ecosystem has a thousand skills that GENERATE.** This release builds the
1894
+ three things a generator structurally cannot be, plus the wiki work that pays for
1895
+ them and the panels that make them visible. Six new lanes, one new agent, and the
1896
+ biggest cost cut available to ORC so far.
1897
+
1898
+ **`/orc-pact` — the lane that remembers.** `/orc-grill` and `/orc-brainstorm`
1899
+ already settle constraints, and a plan already carries them into every executor
1900
+ slice. Then the run ends and they evaporate. The pact is a ledger that outlives
1901
+ the run, with four states that are **computed on read, never stored**: HOLDING,
1902
+ **DRIFTED** (commits since it was verified touched the files it anchors —
1903
+ coverage-relative, so a promise about payments does not fall into doubt because
1904
+ the README changed), **UNCHECKABLE** (nothing cheap proves it — the honest state,
1905
+ and it never counts against you), and BROKEN. It never invents a promise: every
1906
+ entry records where it came from. It never retires one for you. And the payoff is
1907
+ automaticat planning time, a drifted promise whose files your plan is about to
1908
+ touch is injected into the planner as a constraint, so last month's decision
1909
+ constrains this month's work. `PACT.md` is a committed, PM-readable file at your
1910
+ project root, rendered by the CLI from the ledger so the two can never disagree.
1911
+
1912
+ **`/orc-boundary` — the lane that declines.** Every skill you can install assumes
1913
+ the answer to *"should the agent do this?"* is yes; agents spend 5×–50× longer
1914
+ than human experts on a task, and most of the excess goes into attempts that were
1915
+ never going to succeed. Three verdicts per area EXECUTE, ESCALATE, REFUSE — each
1916
+ derived from four questions answered from things already on disk: can it verify
1917
+ itself, does it know this area, is the change reversible, is this a decision
1918
+ rather than a fact. **A REFUSE always names what would make it a yes** — "no" with
1919
+ no "unless" is a shrug, so a refusal with no checklist is treated as a malformed
1920
+ card. It gates ORC's own dispatch, never you: `boundary_gate: block` lifts a
1921
+ refused task out of its wave and **the wave still runs the rest**.
1922
+
1923
+ **`/orc-handoff`the first ORC lane for someone who does not read code.** The
1924
+ insight nobody shipped: the safety grade does not come from the file type, it
1925
+ comes from **whether a cheap check exists**. A settings file with a validator is
1926
+ green; the same file without one is amber. It maps every surface a PM or designer
1927
+ can own, and changing one is five steps with the **undo command shown before the
1928
+ write**, the check run afterwards and reported in plain words, and a red surface
1929
+ never touched at all. Every file in that lane is written in simple English.
1930
+
1931
+ **`/orc-budget`what a run costs, in the unit you are billed in.** Not a dollar
1932
+ figure: on Pro or Max you burn a 5-hour window, not an invoice. The forecast's
1933
+ core object is a **token vector** fresh input, cache write, cache read, output,
1934
+ never blended, because cache reads are usually the largest count and a tenth of
1935
+ the price. The same vector renders four ways: tokens, dollars from a dated price
1936
+ table, percent of your window, and **context risk** — a task forecast above 90% of
1937
+ its model's window is reported before the wave, which no spend tool can do. The
1938
+ numbers come from joining Claude Code's own session transcripts (the cost) to
1939
+ ORC's traces (the meaning); neither is enough alone. It needs a PLAN, not a
1940
+ sentence, and with no history it says so rather than inventing a number.
1941
+
1942
+ **`/orc-aftermath` — did what we shipped hold up.** The missing half of the
1943
+ flywheel: `/orc-retro` measures the process, this measures the result, both from
1944
+ the repository's own future — files rewritten soon after, a test we added deleted
1945
+ or skipped, the commit reverted, a promise that was holding now broken. No vendor,
1946
+ no telemetry. **Churn is a signal, not a verdict**: it reports the signal and its
1947
+ strength, never "this change was bad", and never a person's name.
1948
+
1949
+ **`/orc-export`so ORC is not a trap.** One command compiles the wiki, the code
1950
+ patterns, `PACT.md` and the boundary cards into a portable `AGENTS.md` — derived,
1951
+ fingerprinted, `--check`able against its sources, never hand-written. It removes
1952
+ the lock-in objection and makes ORC the *producer* in a multi-agent shop. Import
1953
+ reads an existing `AGENTS.md` or `.cursorrules` as **evidence, never instruction**,
1954
+ and tells you which parts are already wrong.
1955
+
1956
+ **The wiki finally stops costing a full scan.** Three free CLI commands: `orc wiki
1957
+ plan` ranks and prices the pending work STRUCTURAL first (a page pointing at a
1958
+ missing file is actively lying), then by **use × delta**, with pages nobody reads
1959
+ sinking to the bottom with a retire hint; `orc wiki debt` is the one-line habit;
1960
+ and `orc wiki usage` finally reads back the point-of-use attribution v0.41.0 has
1961
+ been recording and never reading. A **targeted refresh** (`/orc-wiki refresh
1962
+ --top 2`) skips branch detection and area planning entirely, and a new **scan tier
1963
+ ladder** sends a small, no-new-surface delta to a light scanner instead of the most
1964
+ expensive agent in the payload — about 40% off a typical delta refresh, with the
1965
+ deep scan still doing the work that needs it. The tier is always printed: a cheaper
1966
+ model is never a quiet substitution. And free repairs are now a hard rule — you can
1967
+ never pay for something `orc wiki sync` would have fixed.
1968
+
1969
+ **`orc ui` grows three panels and extends five.** Promises, Boundary and
1970
+ Self-serve, plus a new **Cost** tab whose stacked bar exists precisely so the
1971
+ cache-read share stays visible. The panel keeps every rule it had: it never runs a
1972
+ lane, never invents a state word, never computes an order the CLI already emits —
1973
+ **a free action gets a button, a paid action gets a copy-able command**, and that
1974
+ line is now visible rather than hidden. Promises is where the compounding finally
1975
+ shows: an *"Also flagged by"* line when the boundary and the aftermath agree with
1976
+ the ledger about the same area, which you can never see in a terminal one lane at
1977
+ a time.
1978
+
1979
+ ---
1980
+
1981
+ ## Earlier releases
1982
+
1983
+ ### v0.45.0`/orc-brainstorm`: for when you do not have the idea yet _(2026-08-10)_
1984
+
1985
+ ### v0.44.1apply when you say so, and a spotlight that survives a banner _(2026-08-09)_
1986
+
1987
+ ### v0.44.0 — the panel stops making you type what it already knows _(2026-08-09)_
1988
+
1989
+ ### v0.43.7the flow you can see, and a boundary you can read _(2026-08-09)_
1990
+
1991
+ ### v0.43.6`orc ui` in two languages, and panels that point at the right page _(2026-08-08)_
1992
+
1993
+ ### v0.43.5 — the update check works, and the UI teaches itself _(2026-08-08)_
1994
+
1995
+ ### v0.43.4 — a warning that finally clears, an Experiment panel, crosslink from the UI _(2026-08-08)_
1996
+
1997
+ ### v0.43.3`orc ui`: it tells you about updates, and 36 keys stop being a wall _(2026-08-08)_
1998
+
1999
+ ### v0.43.2 — `orc ui`: boxes stop colliding, because the container owns the gap _(2026-08-08)_
2000
+
2001
+ ### v0.43.1the panel's stylesheet and script actually reach the browser _(2026-08-08)_
2002
+
2003
+ ### v0.43.0 — `orc ui`: a control panel for everything that is not ai _(2026-08-08)_
2004
+
2005
+ ### v0.42.0 — Say what you mean, see what it costs, find your way back _(2026-08-08)_
2006
+
2007
+ ### v0.41.0 — A wiki that can tell you it is fresh, and TDD only where it can fail _(2026-08-06)_
2008
+
2009
+ ### v0.40.0Gotchas: repair memory that outlives the run _(2026-08-06)_
2010
+
2011
+ ### v0.39.0The read ladder, and foreign input that is evidence rather than instruction _(2026-08-06)_
2012
+
2013
+ ### v0.38.1`orc doctor --json` + handoff carry-over that says what is re-derived _(2026-08-06)_
2014
+
2015
+ ### v0.38.0`/orc-quick`: the quick lane, and the gate no config can collapse _(2026-08-05)_
2016
+
2017
+ ### v0.37.0 — Stacked pull requests: a measured ship gate + two standalone lanes _(2026-08-03)_
2018
+
2019
+ ### v0.36.0 — `opus5_only`: one model for every role, not just executors _(2026-08-02)_
2020
+
2021
+ ### v0.35.0 — `opus5_executor_only`: one model, effort as the cost dial _(2026-08-02)_
2022
+
2023
+ ### v0.34.8 — `orc pattern status` rejects a language key the payload has never heard of _(2026-08-01)_
2024
+
2025
+ ### v0.34.7 — DIY: a usable status contract, and compile docs that match the compiler _(2026-08-01)_
2026
+
2027
+ ### v0.34.6 — Analyze: the evidence gate now covers the rows a good analysis produces _(2026-08-01)_
2028
+
2029
+ ### v0.34.5 — Wiki: stop losing tags silently, let a delta clear its own delta _(2026-08-01)_
2030
+
2031
+ ### v0.34.4 — Planner: scorable facets, and TDD rules scoped to reality _(2026-08-01)_
2032
+
2033
+ ### v0.34.3 — Slice boundary: the worktree, not the editor _(2026-08-01)_
2034
+
2035
+ ### v0.34.2 — Trace subsystem: the pointer clobber, and a writer contract that holds _(2026-08-01)_
2036
+
2037
+ ### v0.34.1 — Install integrity: run state survives `orc update` _(2026-08-01)_
2038
+
2039
+ ### v0.34.0 — Opus 5: top scoring band, every core role, medium-effort session tier _(2026-07-25)_
2040
+
2041
+ ### v0.33.0 — Knowledge deepening + verification revamp _(2026-07-25)_
2042
+
2043
+ ### v0.32.0 — Trace revamp: narration is dispatched, not remembered _(2026-07-24)_
2044
+
2045
+ ### v0.31.0 — Execution-integrity revamp: plan handoff, attributable traces, facet scoring _(2026-07-23)_
2046
+
2047
+ ### v0.30.0 — Scoring revamp, Fable 5 role override, tier-aware guards, `orc onboarding` _(2026-07-23)_
2048
+
2049
+ ### v0.29.0 — Drift-prevention hardening: install manifest + prune, `orc doctor`, a real test suite _(2026-07-22)_
2050
+
2051
+ ### v0.28.1 — Defect fixes: package encoding, trace event routing, count/doc drift _(2026-07-22)_
2052
+
2053
+ ### v0.28.0 — Run integrity: rich full-lane traces, deterministic wave stop, visible knowledge gates _(2026-07-21)_
2054
+
2055
+ ### v0.27.0 — `/orc-poly`: plan one change across two-or-more repos without drift _(2026-07-20)_
2056
+
2057
+ ### v0.26.0 — Test-gen output pinned to a visible `test-generator/<change-slug>/` deliverable _(2026-07-19)_
2058
+
2059
+ ### v0.25.1 — Eval report: the full 17-lane suite graded against the v0.25.0 payload _(2026-07-18)_
2060
+
2061
+ ### v0.25.0 — Deterministic artifact detection: a generated wiki/pattern is never missed _(2026-07-18)_
2062
+
2063
+ ### v0.24.0 — Crosslink fused into wiki generation: always-on, per-scan-task, never wiped _(2026-07-18)_
2064
+
2065
+ ### v0.23.0 — Trace fix: SPAWN restored on the `Agent` tool, stale runs rotate to fresh files _(2026-07-18)_
2066
+
2067
+ ### v0.22.0 — `/orc-learn`: per-feature onboarding docs — learning.md + knowledge.md, wiki-deep, git-ignored _(2026-07-17)_
2068
+
2069
+ ### v0.21.0 — Statusline shows live subscription usage: 5h ↔ weekly, official numbers _(2026-07-16)_
2070
+
2071
+ ### v0.20.0 — One source of truth: generated executor agents + shared cross-lane contracts _(2026-07-16)_
2072
+
2073
+ ### v0.19.0 — Thin spines: skill compaction, budget lint, and a trace that logs every phase _(2026-07-16)_
2074
+
2075
+ ### v0.18.0 — `orc wiki sync`: the wiki registers itself — a paused scan is no longer an invisible wiki _(2026-07-15)_
2076
+
2077
+ ### v0.17.3 — Trace the wiki consult: Phase 1 now logs whether the run grounded in the wiki (and if it was stale) _(2026-07-14)_
2078
+
2079
+ ### v0.17.2 — Behavior-trace logging is permanent + the trace folder is now created deterministically _(2026-07-14)_
2080
+
2081
+ ### v0.17.1 — Complete cross-repo crosslink setup guide in the orc-wiki README _(2026-07-14)_
2082
+
2083
+ ### v0.17.0 — `orc crosslink`: cross-repo wiki references — advisory boundary contracts _(2026-07-14)_
2084
+
2085
+ ### v0.16.1 — Interactive `orc diy` composer + numbered picks in `orc config` _(2026-07-14)_
2086
+
2087
+ ### v0.16.0 — `/orc-diy`: build your own lane — CLI-composed flow, compiled, hard-gated _(2026-07-14)_
2088
+
2089
+ ### v0.15.0 — Wiki v2: evidence-anchored docs · per-file staleness registry · integrity gate _(2026-07-14)_
2090
+
2091
+ ### v0.14.0 — Postgres data-access playbook: cross-cutting query grounding _(2026-07-13)_
2092
+
2093
+ ### v0.13.0 — `/orc-claude`: local CLAUDE.md builder — fenced sections, fingerprint refresh, zero questions _(2026-07-12)_
2094
+
2095
+ ### v0.12.0 — Lossless context-combiner: conservation gate · overlap taxonomy · evidence freshness _(2026-07-12)_
2096
+
2097
+ ### v0.11.0 — `/orc-fast`: knowledge-gated speed lane + wiki freshness infrastructure _(2026-07-12)_
2098
+
2099
+ ### v0.10.1 — README: a fuller "Why ORC exists" _(2026-07-12)_
2100
+
2101
+ ### v0.10.0 — `/orc-ultra`: max-effort advisor + three judgment gates for ultra-complex work _(2026-07-12)_
2102
+
2103
+ ### v0.9.0 — Trust-but-verify the analyst→planner chain: quote-anchored evidence · coverage gate · anchored judgment _(2026-07-12)_
2104
+
2105
+ ### v0.8.1 — /orc-retro delivers upstream: PR/issue to the ORC repo, channel-gated _(2026-07-12)_
2106
+
2107
+ ### v0.8.0 — Close the loop: grounded intake · scoring anchors · OUTCOME marker · /orc-retro trace miner · eval harness _(2026-07-12)_
2108
+
2109
+ ### v0.7.0 — Evidence everywhere: grounded plans · verbatim proof · anchored findings · contract lint · trace fixes _(2026-07-12)_
2110
+
2111
+ ### v0.6.0 — P0–P3 ladder · house rules · deep playbooks + wired gates · 3 new languages · FE rule packs · security pass _(2026-07-11)_
2112
+
2113
+ ### v0.5.1 — Statusline false-degrade fix _(2026-07-11)_
2114
+
2115
+ ### v0.5.0 — Code-pattern findings: executors match your house style, invariants always enforced
2116
+
2117
+ ### v0.4.5 — Rewrite weak worker descriptions (the real score lever)
2118
+
2119
+ ### v0.4.4 — Act on external review: raise sub-70 workers, fix cross-spine paths
2120
+
2121
+ ### v0.4.3 — `orc-analyze`: trim description under the 1024-char skill-spec limit
2122
+
2123
+ ### v0.4.2 — External-review pass: worked examples + sharper mini-analyst activation
2124
+
2125
+ ### v0.4.1 — `orc-mini`: faster, safer fast-lane — smoke gate, opt-in tests, trimmed ceremony
2126
+
2127
+ ### v0.4.0 — Opt-in Phase 6.5 Test Authoring (writes test cases, never runs them)
2128
+
2129
+ ### v0.3.0 — Opt-in behavior-trace logging + claimed-vs-actual model verification
2130
+
2131
+ ### v0.2.4 — `orc-analyze`: gather anchored adjacent-scope context (non-actionable)
2132
+
2133
+ ### v0.2.3 — Context Combiner: merge 2+ related analyses into one combined spec
2134
+
2135
+ ### v0.2.2 — Config: enforce per-key override-first resolution
2136
+
2137
+ ### v0.2.1 — Move config editing into the `orc config` CLI (zero-token); drop `/orc-config`
2138
+
2139
+ ### v0.2.0 — Doc-optional evidence-backed analyst + deep mode