@azure-id/orc 0.56.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +228 -0
- package/README-id.md +143 -53
- package/README.md +124 -103
- package/bin/build-agents.js +18 -11
- package/bin/cli.js +4139 -315
- package/bin/onboarding-content.js +0 -3
- package/bin/test-run.js +491 -0
- package/bin/verify-contracts.js +4256 -3277
- package/bin/verify-package.js +563 -498
- package/bin/webui/api.js +1186 -1163
- package/bin/webui/app.html +9 -0
- package/bin/webui/css/06-responsive.css +120 -108
- package/bin/webui/css/panels/extra.css +29 -0
- package/bin/webui/css/panels/lanes.css +134 -0
- package/bin/webui/css/panels/settings.css +79 -3
- package/bin/webui/fixtures/extra.js +2036 -1934
- package/bin/webui/fixtures/flow.js +2 -2
- package/bin/webui/fixtures/index.js +503 -486
- package/bin/webui/fixtures/lanes.js +218 -0
- package/bin/webui/fixtures/settings.js +261 -34
- package/bin/webui/fixtures/stats.js +3 -3
- package/bin/webui/i18n/TERMS.md +135 -134
- package/bin/webui/i18n/en/extra.json +345 -313
- package/bin/webui/i18n/en/lanes.json +29 -0
- package/bin/webui/i18n/en/nav.json +1 -0
- package/bin/webui/i18n/en/overview.json +2 -0
- package/bin/webui/i18n/en/settings.json +16 -5
- package/bin/webui/i18n/id/extra.json +345 -313
- package/bin/webui/i18n/id/lanes.json +29 -0
- package/bin/webui/i18n/id/nav.json +1 -0
- package/bin/webui/i18n/id/overview.json +2 -0
- package/bin/webui/i18n/id/settings.json +15 -4
- package/bin/webui/js/01-i18n.js +1 -0
- package/bin/webui/js/panels/extra.js +3199 -3011
- package/bin/webui/js/panels/lanes.js +259 -0
- package/bin/webui/js/panels/overview.js +10 -0
- package/bin/webui/js/panels/settings.js +149 -3
- package/package.json +3 -3
- package/templates/agents/MODEL-MAPPING.md +23 -35
- package/templates/agents/orc-executor-opus-4-7-high.md +1 -1
- package/templates/agents/orc-executor-opus-4-7-med.md +1 -1
- package/templates/agents/orc-executor-opus-4-8-high.md +1 -1
- package/templates/agents/orc-executor-opus-5-high.md +1 -1
- package/templates/agents/orc-executor-opus-5-low.md +1 -1
- package/templates/agents/orc-executor-opus-5-med.md +1 -1
- package/templates/agents/orc-retro-opus-5-med.md +73 -73
- package/templates/agents/orc-retro-sonnet-5-high.md +72 -72
- package/templates/agents/orc-trace-writer-haiku-4-5.md +107 -107
- package/templates/commands/orc-route.md +1 -1
- package/templates/commands/orc.md +1 -1
- package/templates/skills/_shared/README.md +7 -3
- package/templates/skills/_shared/config-precedence.md +198 -0
- package/templates/skills/_shared/drift-recovery.md +1 -1
- package/templates/skills/_shared/extra-dispatch.md +292 -6
- package/templates/skills/_shared/interview.md +1 -1
- package/templates/skills/_shared/opus5-only.md +9 -7
- package/templates/skills/_shared/phases/README.md +82 -0
- package/templates/skills/{orc/references → _shared/phases}/analyst-gates.md +15 -3
- package/templates/skills/_shared/phases/execution.md +143 -0
- package/templates/skills/{orc/references → _shared/phases}/house-rules.md +13 -1
- package/templates/skills/{orc/references → _shared/phases}/intake.md +15 -2
- package/templates/skills/_shared/phases/mock-example.md +56 -0
- package/templates/skills/{orc/references → _shared/phases}/plan-handoff.md +16 -3
- package/templates/skills/_shared/phases/planning.md +135 -0
- package/templates/skills/_shared/phases/preflight.md +76 -0
- package/templates/skills/_shared/phases/review.md +53 -0
- package/templates/skills/_shared/phases/scoring.md +65 -0
- package/templates/skills/{orc/references → _shared/phases}/security-checklist.md +12 -1
- package/templates/skills/_shared/phases/security.md +55 -0
- package/templates/skills/_shared/phases/ship.md +88 -0
- package/templates/skills/{orc/references/stop-and-resume.md → _shared/phases/stop-resume.md} +169 -160
- package/templates/skills/_shared/phases/summary.md +48 -0
- package/templates/skills/_shared/phases/testgen.md +51 -0
- package/templates/skills/{orc/references/trace-protocol.md → _shared/phases/trace.md} +49 -6
- package/templates/skills/_shared/phases/verify.md +70 -0
- package/templates/skills/{orc/references → _shared/phases}/wave-grouping.md +14 -2
- package/templates/skills/{orc/references → _shared/phases}/wiki-consult.md +13 -1
- package/templates/skills/_shared/read-ladder.md +48 -0
- package/templates/skills/context-combiner/SKILL.md +214 -187
- package/templates/skills/orc/README.md +148 -150
- package/templates/skills/orc/SKILL.md +70 -358
- package/templates/skills/orc/config.md +137 -389
- package/templates/skills/orc/examples/full-run-mock.md +1 -1
- package/templates/skills/orc/references/effort-and-mode.md +16 -18
- package/templates/skills/orc/references/phases/intake.md +47 -0
- package/templates/skills/orc/references/phases/integration.md +19 -0
- package/templates/skills/orc/references/preflight-report.md +4 -4
- package/templates/skills/orc/references/ultra-mode.md +117 -123
- package/templates/skills/orc/schemas/planning-output.md +279 -279
- package/templates/skills/orc/subskills/orc-planner/SKILL.md +260 -264
- package/templates/skills/orc/subskills/orc-pr/stack-gate.md +4 -1
- package/templates/skills/orc-aftermath/SKILL.md +153 -136
- package/templates/skills/orc-analyze/SKILL.md +247 -220
- package/templates/skills/orc-analyze/references/branching.md +51 -51
- package/templates/skills/orc-analyze/references/thin-input.md +1 -1
- package/templates/skills/orc-analyze-mini/SKILL.md +128 -112
- package/templates/skills/orc-boundary/SKILL.md +244 -208
- package/templates/skills/orc-brainstorm/SKILL.md +372 -339
- package/templates/skills/orc-budget/SKILL.md +243 -225
- package/templates/skills/orc-challenge/README.md +1 -1
- package/templates/skills/orc-challenge/SKILL.md +293 -255
- package/templates/skills/orc-challenge/examples/council-full-roster.md +1 -1
- package/templates/skills/orc-claude/SKILL.md +216 -199
- package/templates/skills/orc-diy/README.md +2 -1
- package/templates/skills/orc-diy/SKILL.md +129 -70
- package/templates/skills/orc-diy/references/blocks/analyze.md +1 -1
- package/templates/skills/orc-diy/references/compile.md +21 -7
- package/templates/skills/orc-diy/references/flow-schema.md +2 -2
- package/templates/skills/orc-doc/SKILL.md +44 -7
- package/templates/skills/orc-explain/SKILL.md +19 -0
- package/templates/skills/orc-export/SKILL.md +26 -5
- package/templates/skills/orc-fast/SKILL.md +215 -187
- package/templates/skills/orc-grill/SKILL.md +233 -207
- package/templates/skills/orc-handoff/SKILL.md +223 -204
- package/templates/skills/orc-learn/SKILL.md +176 -156
- package/templates/skills/orc-mini/SKILL.md +41 -23
- package/templates/skills/orc-pact/SKILL.md +250 -218
- package/templates/skills/orc-pattern/SKILL.md +149 -124
- package/templates/skills/orc-poly/SKILL.md +237 -216
- package/templates/skills/orc-poly/references/gather.md +1 -1
- package/templates/skills/orc-pr-driver/SKILL.md +196 -167
- package/templates/skills/orc-pr-driver/references/orc-run-split.md +1 -1
- package/templates/skills/orc-pr-setup/SKILL.md +212 -184
- package/templates/skills/orc-quick/README.md +2 -2
- package/templates/skills/orc-quick/SKILL.md +346 -313
- package/templates/skills/orc-quick/references/dispatch-gate.md +12 -4
- package/templates/skills/orc-retro/SKILL.md +244 -222
- package/templates/skills/orc-retro/examples/retro-mock.md +171 -171
- package/templates/skills/orc-route/SKILL.md +183 -165
- package/templates/skills/orc-verify/SKILL.md +100 -86
- package/templates/skills/orc-wiki/SKILL.md +55 -206
- package/templates/skills/orc-wiki/references/phases/phase-0.md +71 -0
- package/templates/skills/orc-wiki/references/phases/phase-1.md +35 -0
- package/templates/skills/orc-wiki/references/phases/phase-2.md +52 -0
- package/templates/skills/orc-wiki/references/phases/phase-3.md +57 -0
- package/templates/skills/orc-wiki/references/phases/phase-3c.md +36 -0
- package/templates/agents/orc-advisor-fable-5.md +0 -50
- package/templates/agents/orc-analyst-fable-5.md +0 -115
- package/templates/agents/orc-judge-fable-5.md +0 -79
- package/templates/agents/orc-planner-fable-5.md +0 -152
- package/templates/agents/orc-reviewer-fable-5.md +0 -57
- package/templates/skills/_shared/fable5-override.md +0 -56
- package/templates/skills/orc-diy/references/blocks/execution.md +0 -42
- package/templates/skills/orc-diy/references/blocks/mock-example.md +0 -22
- package/templates/skills/orc-diy/references/blocks/planning.md +0 -34
- package/templates/skills/orc-diy/references/blocks/review.md +0 -18
- package/templates/skills/orc-diy/references/blocks/scoring.md +0 -16
- package/templates/skills/orc-diy/references/blocks/security.md +0 -25
- package/templates/skills/orc-diy/references/blocks/ship.md +0 -25
- package/templates/skills/orc-diy/references/blocks/summary.md +0 -18
- package/templates/skills/orc-diy/references/blocks/testgen.md +0 -17
- package/templates/skills/orc-diy/references/blocks/trace.md +0 -28
- package/templates/skills/orc-diy/references/blocks/verify.md +0 -25
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# Shared contract — config precedence: ranks, families, and one resolver per lane
|
|
2
|
+
|
|
3
|
+
Canonical rule for how EVERY ORC lane learns what it is configured to do.
|
|
4
|
+
Consumed by every lane that reads a setting; the lint pins the
|
|
5
|
+
`config-precedence.md` pointer into each of them.
|
|
6
|
+
|
|
7
|
+
Two sentences carry the whole file:
|
|
8
|
+
|
|
9
|
+
> **ONE resolver, and it is not you:** `orc lane config <lane> --json`.
|
|
10
|
+
>
|
|
11
|
+
> **Read a family top-down and stop at the first rank that resolves.**
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 1. The resolver
|
|
16
|
+
|
|
17
|
+
A lane never reads `.claude/orc.config.yaml`. It runs
|
|
18
|
+
`orc lane config <lane> --json` once, at preflight, and obeys the answer.
|
|
19
|
+
|
|
20
|
+
| field | what a lane does with it |
|
|
21
|
+
|---|---|
|
|
22
|
+
| `effective` | the flat answer. Obey it and reason about nothing. |
|
|
23
|
+
| `announce[]` | print every line VERBATIM at preflight, before the first dispatch |
|
|
24
|
+
| `stops[]` | every value that can HARD-STOP this run; honour each before wave 1 |
|
|
25
|
+
| `keys[]` | per key: `value`, `default`, `prio`, `family`, `state`, `is_shadowed` / `shadow_reason`, `is_inert` / `inert_reason` |
|
|
26
|
+
| `families{}` | which rank answered each question, and why the rest were not read |
|
|
27
|
+
| `not_read[]` | the keys this lane deliberately ignores |
|
|
28
|
+
|
|
29
|
+
`not_read[]` is an ANSWER, not a gap. "This lane does not read `doc_language`"
|
|
30
|
+
is information, and it is what makes the two-way registry lint possible.
|
|
31
|
+
|
|
32
|
+
**Never re-derive a value, a precedence, or an inertness.** A key this lane does
|
|
33
|
+
not read is not in the answer; a key another key shadows comes back already
|
|
34
|
+
marked, with the sentence already worded. A lane that reasons *"`opus5_only` is
|
|
35
|
+
on, so the fable block must be inert"* has forked the resolver — it reads
|
|
36
|
+
`is_shadowed` and prints `shadow_reason`.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## 2. Ranks, and the rule that makes them mean something
|
|
41
|
+
|
|
42
|
+
Every key declares `answers[]`: which FAMILY question it answers, at which
|
|
43
|
+
RANK (`P0` · `P1` · `P2` · `P3`), in which MODE.
|
|
44
|
+
|
|
45
|
+
> **Read a family top-down and stop at the first rank that resolves.**
|
|
46
|
+
> If the P0 key of a family resolves, P1, P2 and P3 of that family are **not
|
|
47
|
+
> read at all** — not consulted, not defaulted, not mentioned as a fallback. A
|
|
48
|
+
> rank below a resolved rank has no effect and no meaning for this decision.
|
|
49
|
+
|
|
50
|
+
**A rank compares only INSIDE its family.** `log_dir` being P2 and `opus5_only`
|
|
51
|
+
being P1 says nothing whatever: they never compete. A family whose keys do not
|
|
52
|
+
compete has every key at P2, the neutral rank, and the lint asserts it — rank
|
|
53
|
+
distinctness is required only where a family is declared contested.
|
|
54
|
+
|
|
55
|
+
| `mode` | resolves when | effect on the ranks below it |
|
|
56
|
+
|---|---|---|
|
|
57
|
+
| `replace` | the key is set to a truthy / non-default value | every lower rank is shadowed, entirely |
|
|
58
|
+
| `overlay` | the key is on **and** at least one row applies to THIS decision | lower ranks are shadowed only for the ranges or slots it covers |
|
|
59
|
+
| `gate` | — | it never resolves the family; it makes its own dependants **inert** (§4) |
|
|
60
|
+
|
|
61
|
+
An `overlay` resolves PARTIALLY, so the honest report is WHICH ranges and WHICH
|
|
62
|
+
positions it took — never a single word. The ranges it did not take fall through
|
|
63
|
+
to the next rank normally. That is what lets "cheap work goes to a foreign
|
|
64
|
+
worker, hard work stays on Opus 5" be two rows rather than a table rewrite.
|
|
65
|
+
|
|
66
|
+
**The lowest rank of a contested family is TOTAL.** Something must answer when
|
|
67
|
+
nothing above resolved, so that terminal row is the shipped default and it is
|
|
68
|
+
declared as a row, not as a key — a fall-through is not a setting.
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## 3. The two contested families
|
|
73
|
+
|
|
74
|
+
Everything else is uncontested: one question, no competition, every key P2.
|
|
75
|
+
|
|
76
|
+
**`executor-band` — which model executes a SCORED task**
|
|
77
|
+
|
|
78
|
+
| rank | key | mode | |
|
|
79
|
+
|---|---|---|---|
|
|
80
|
+
| P0 | `extra_enabled` | overlay | a route row covering this score sends it off Claude |
|
|
81
|
+
| P1 | `opus5_only` | replace | the fixed 2-band Opus 5 ladder |
|
|
82
|
+
| P2 | `rubric_bands_override` | replace | hand-edited, registry-less by design; resolves on PRESENCE |
|
|
83
|
+
| P3 | — | terminal | the shipped score→model table |
|
|
84
|
+
|
|
85
|
+
**`fixed-role-model` — which model runs a role that has no score**
|
|
86
|
+
|
|
87
|
+
| rank | key | mode | |
|
|
88
|
+
|---|---|---|---|
|
|
89
|
+
| P0 | `extra_enabled` | overlay | a slot row holds that POSITION |
|
|
90
|
+
| P1 | `opus5_only` | replace | the shipped Opus 5 variant of that position's agent |
|
|
91
|
+
| P2 | — | terminal | the agent shipped for that position |
|
|
92
|
+
|
|
93
|
+
Said once, for both shapes: **extra decides whether a Claude agent runs at all;
|
|
94
|
+
`opus5_only` and the score tables only decide WHICH Claude agent runs where
|
|
95
|
+
extra did not take it.** Under a taken band or a taken slot, `opus5_only` is
|
|
96
|
+
**not consulted** — not "inert" — and it stays fully live everywhere else.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## 4. A gate is not a rank — it is inertness
|
|
101
|
+
|
|
102
|
+
`extra_enabled: false` does not lose a precedence contest. It means **no
|
|
103
|
+
`extra_*` key is consulted at all**. A key declares `gated_by`, inherits its
|
|
104
|
+
gate's row, and comes back `inert` with the reason already worded.
|
|
105
|
+
|
|
106
|
+
Lane-level inertness is a THIRD thing, with nothing in the config file involved:
|
|
107
|
+
|
|
108
|
+
| lane | inert | reason (must not be softened) |
|
|
109
|
+
|---|---|---|
|
|
110
|
+
| `/orc-quick` | `opus5_only`, `rubric_bands_override`, `extra_*` | this lane asks WHICH AGENT before every dispatch — a config that silently answered that question would break the lane's entire premise |
|
|
111
|
+
| `/orc-challenge` | `opus5_only` | every agent in this lane is already `claude-opus-5` — a **no-op; the lane is unaffected, not exempt** |
|
|
112
|
+
| `/orc-doc` | `opus5_only` | the same — unaffected, not exempt |
|
|
113
|
+
|
|
114
|
+
**"Unaffected, not exempt"** survives verbatim. A generic "not applicable" loses
|
|
115
|
+
the fact that turning the key on breaks nothing here.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## 5. `announce[]` — and its exact boundary
|
|
120
|
+
|
|
121
|
+
A shadowed setting must never be silent, and work must never leave Claude
|
|
122
|
+
without the run saying so. Those lines are computed, worded once by the CLI, and
|
|
123
|
+
printed by the lane verbatim.
|
|
124
|
+
|
|
125
|
+
| goes in `announce[]` | stays with the lane |
|
|
126
|
+
|---|---|
|
|
127
|
+
| anything derivable from config + disk the CLI already reads: the wiki tier, pattern-cache presence, crosslink state, extra route rows and taken slots, pact / boundary / challenge state, which keys are shadowed or inert, the resolved scan tier, a run-scoped demotion | anything needing a per-task or per-run value the CLI cannot know: a task's score, a task id, a slug, a file count, a forecast number, a wave index |
|
|
128
|
+
|
|
129
|
+
A line needing a runtime value is **not** emitted as a template with holes. Half
|
|
130
|
+
a sentence from the CLI and half from the model is worse than either — it is a
|
|
131
|
+
sentence nobody owns. Those lines stay with the lane.
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## 6. The ladder can move at runtime
|
|
136
|
+
|
|
137
|
+
A profile that stalls twice in one run, or holds one live attempt quiet past
|
|
138
|
+
`extra_demote_stale_min`, is DEMOTED to the bottom of its families for the rest
|
|
139
|
+
of that run — so the next rank down becomes the effective P0. The verdict is
|
|
140
|
+
recomputed from disk on every read and never stored; it is run-scoped and never
|
|
141
|
+
touches the config file; it is never promoted back on its own; and it is
|
|
142
|
+
ANNOUNCED, because the mirror of sending work off Claude silently is quietly
|
|
143
|
+
stopping. Full rule: `extra-dispatch.md`.
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## 7. When the CLI is not there
|
|
148
|
+
|
|
149
|
+
Exit ≠ 0, or the command is not found:
|
|
150
|
+
|
|
151
|
+
1. **Say so, in one line.** Fail open with the failure stated.
|
|
152
|
+
2. Use the documented defaults below.
|
|
153
|
+
3. Treat **every P0 forcing mode as OFF**.
|
|
154
|
+
4. Never guess a user override, and never present a default as a resolved value.
|
|
155
|
+
|
|
156
|
+
The floor is the keys a run cannot start without — `max_wave_tasks: 3` ·
|
|
157
|
+
`batch_pause_every: 2` · `rubric_bands: 5` · `max_scouts: 3` ·
|
|
158
|
+
`default_analysis_depth: standard` · `generate_tests: false` ·
|
|
159
|
+
`pattern_findings: ask` · `security_review: off`.
|
|
160
|
+
|
|
161
|
+
Every other key's default is the CLI's to state. **A lane never guesses one** —
|
|
162
|
+
if a decision needs a key not on that list and the CLI cannot answer, the lane
|
|
163
|
+
says which key it could not resolve and stops, rather than inventing a value the
|
|
164
|
+
user may have overridden.
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## 8. The `## Config` section every lane carries
|
|
169
|
+
|
|
170
|
+
Verbatim, and identical in every lane but its own name:
|
|
171
|
+
|
|
172
|
+
```markdown
|
|
173
|
+
## Config
|
|
174
|
+
|
|
175
|
+
**ONE resolver, and it is not you:** `orc lane config <lane> --json`. Obey
|
|
176
|
+
`effective`, print every line in `announce[]` VERBATIM at preflight, and honour
|
|
177
|
+
`stops[]` before wave 1. Never re-derive a value, a precedence or an inertness
|
|
178
|
+
from `.claude/orc.config.yaml` — a key this lane does not read is not in the
|
|
179
|
+
answer, and a key another key shadows comes back already marked. Exit ≠ 0 → say
|
|
180
|
+
the CLI is unavailable and fall back to `../_shared/config-precedence.md`'s
|
|
181
|
+
documented defaults, out loud. Priorities and families:
|
|
182
|
+
`../_shared/config-precedence.md`.
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## 9. The file the user edits
|
|
188
|
+
|
|
189
|
+
`.claude/orc.config.yaml` holds only the keys the user changed, sits outside
|
|
190
|
+
`templates/` (so `orc update` never clobbers it), and is written exclusively by
|
|
191
|
+
`orc config set`. It is grouped by the QUESTION each key answers, ordered by
|
|
192
|
+
rank only inside a contested family.
|
|
193
|
+
|
|
194
|
+
`orc config set` regenerates its own group comments on every write and
|
|
195
|
+
**never rewrites a value it was not given**: a comment the user wrote stays with
|
|
196
|
+
the key it sits above, and a hand-edited multi-line block survives byte for
|
|
197
|
+
byte. A key written under a retired spelling is rebuilt under its current name —
|
|
198
|
+
a renamed mechanism must never be a silent revert.
|
|
@@ -29,7 +29,7 @@ never in `.claude/`, never in the run folder):
|
|
|
29
29
|
**Who builds it: NOT you.** The example is DISPATCHED like any task (orc hard
|
|
30
30
|
rule 1 — the orchestrator never implements, not even the smallest task). It is
|
|
31
31
|
an orchestrator-SYNTHESIZED task, so it is scored from a DERIVED vector, never a
|
|
32
|
-
judged one — see `
|
|
32
|
+
judged one — see `_shared/phases/wave-grouping.md` "Orchestrator-synthesized
|
|
33
33
|
tasks".
|
|
34
34
|
|
|
35
35
|
**Git: NEVER committed.** The ship phase explicitly excludes `mock-examples/`
|
|
@@ -169,7 +169,7 @@ A slot is a **point**, not an interval, so the band table's overlap refusal has
|
|
|
169
169
|
no analogue here and none is invented. `orc extra role set` on an occupied slot
|
|
170
170
|
REPLACES, and says what it replaced.
|
|
171
171
|
|
|
172
|
-
### The
|
|
172
|
+
### The ten hold-backs, each answered by name
|
|
173
173
|
|
|
174
174
|
1. **unknown slot** — refused, exit 2, listing the six.
|
|
175
175
|
2. **`extra_enabled` false** — claude. The master gate.
|
|
@@ -191,6 +191,11 @@ REPLACES, and says what it replaced.
|
|
|
191
191
|
preflight` STOPS the run. `extra_on_failure` never covers it: that key is
|
|
192
192
|
about an endpoint that failed, and a deadline you set 30 days ago deserves a
|
|
193
193
|
stop.
|
|
194
|
+
10. **the profile is DEMOTED in this run** (v1.0.0) — claude, named, with the
|
|
195
|
+
promote command. The tenth hold-back and the only one that is about the RUN
|
|
196
|
+
rather than about the row: two consecutive stalls, a 20-minute stale live
|
|
197
|
+
attempt, or a human running `orc extra demote`. The position falls through
|
|
198
|
+
to the SAME pinned Claude agent it always had.
|
|
194
199
|
|
|
195
200
|
### What it hands back
|
|
196
201
|
|
|
@@ -202,7 +207,7 @@ REPLACES, and says what it replaced.
|
|
|
202
207
|
| `band` | the ROUTE row's band, not the Claude band. On a slot answer it is the string **`slot:<slot>`** — the field NAME is unchanged, so the trace parser, the eight-field dedupe and the ` :: ` tolerance keep working untouched |
|
|
203
208
|
| `slot` · `lane` · `asks` | present on a slot answer only. `score` is `null` there, and **is not derived from anything** |
|
|
204
209
|
| `claude` | `{via, band, agent, table}` — **always present**, on both answers. It is the fall-through target AND the fallback target, so nothing ever needs a second lookup |
|
|
205
|
-
| `held_back` | `null` · `role` · `risk` · `boundary` · `missing-profile` · `unverified` |
|
|
210
|
+
| `held_back` | `null` · `role` · `risk` · `boundary` · `missing-profile` · `unverified` · `demoted` |
|
|
206
211
|
| `verify_state` · `needs_reping` | `FRESH` / `STALE`. **A STALE profile still routes** — a stale check is not a failed one |
|
|
207
212
|
| `model_known` | whether the routed model id was in the last ping's `models_seen`. `false` is a WARNING, never a block: the list is a cache, not an authority |
|
|
208
213
|
| `credential` | `{source, key_name, present}` — never a value |
|
|
@@ -228,7 +233,7 @@ One sentence, and it is the same sentence for both shapes:
|
|
|
228
233
|
an extra route row covering this score (only for the scores it covers)
|
|
229
234
|
> opus5_only
|
|
230
235
|
> rubric_bands_override
|
|
231
|
-
> the default
|
|
236
|
+
> the default 6-band table
|
|
232
237
|
```
|
|
233
238
|
|
|
234
239
|
**A slot**, highest wins:
|
|
@@ -260,7 +265,7 @@ it, `orc extra route set` names the Claude band each new row displaces, and
|
|
|
260
265
|
`orc config list --json`'s `score_table.active` can read `extra+opus5_only` —
|
|
261
266
|
a composite, because the truth is a composite and a single word would be a lie.
|
|
262
267
|
|
|
263
|
-
**`/orc-quick` is a GATED CHOICE, not a route.** `opus5_only`,
|
|
268
|
+
**`/orc-quick` is a GATED CHOICE, not a route.** `opus5_only`,
|
|
264
269
|
`rubric_bands_override` and `extra_resume` stay INERT there — that lane asks
|
|
265
270
|
*which agent* before every dispatch, so a config that silently answered that
|
|
266
271
|
question, or that silently continued the previous foreign worker's half-finished
|
|
@@ -686,7 +691,7 @@ only moment anyone can act on it is now.
|
|
|
686
691
|
|
|
687
692
|
The trace line is still yours to relay, and it still matters: it is the
|
|
688
693
|
human-readable narrative of the run, it is what `/orc-retro` reads, and the
|
|
689
|
-
trace-cadence rule in `
|
|
694
|
+
trace-cadence rule in `phases/trace.md` still binds every phase.
|
|
690
695
|
What changed is that the SPEND no longer depends on it.
|
|
691
696
|
|
|
692
697
|
One `EXTRA` line per foreign dispatch, plus its continuations. **Copy
|
|
@@ -978,12 +983,289 @@ supplies it pre-composed in `trace_extras[]`.
|
|
|
978
983
|
|
|
979
984
|
---
|
|
980
985
|
|
|
981
|
-
## The
|
|
986
|
+
## The stall — a worker that is alive and doing nothing (v0.56.1)
|
|
987
|
+
|
|
988
|
+
### `a lane that waits out a wall clock on a worker that stopped` has broken this contract
|
|
989
|
+
|
|
990
|
+
A wall clock cannot tell a worker that is thinking hard from a worker that has
|
|
991
|
+
stopped. Both look like fifteen minutes of nothing. So until v0.56.1 an opencode
|
|
992
|
+
session that went quiet mid-task — the thing you fix by hand by typing
|
|
993
|
+
`continue` into its window — burned the whole `extra_timeout_s` budget and then
|
|
994
|
+
reported `timeout`, which is a statement about **ORC's patience** and not about
|
|
995
|
+
what happened. It read as a budget somebody should raise. It was a **position
|
|
996
|
+
somebody should resume from**.
|
|
997
|
+
|
|
998
|
+
### What the stall clock measures
|
|
999
|
+
|
|
1000
|
+
`config.extra_stall_s` (default **180**, `0` disables) is the seconds a foreign
|
|
1001
|
+
worker may produce **nothing at all** before the dispatch is stopped. It is not
|
|
1002
|
+
a second wall clock: it is reset by **observable progress**, in the only three
|
|
1003
|
+
places progress can show up.
|
|
1004
|
+
|
|
1005
|
+
| signal | why it counts |
|
|
1006
|
+
|---|---|
|
|
1007
|
+
| new bytes on the worker's own stream | it is talking |
|
|
1008
|
+
| new bytes on its stderr | it is complaining, which is still working |
|
|
1009
|
+
| a **declared file** changed size or mtime on disk | it just wrote something, whatever its stream is doing |
|
|
1010
|
+
|
|
1011
|
+
Any one of the three resets the clock. All three quiet for the whole budget is
|
|
1012
|
+
the finding. That third row is what stops the clock firing on a worker that
|
|
1013
|
+
thinks for four minutes and then writes a file in one go.
|
|
1014
|
+
|
|
1015
|
+
Ordered with the other three, once, in `extraTimeouts`: **stall < idle < api <
|
|
1016
|
+
wall**. A budget at or past the wall clock could never fire, so it is CLAMPED
|
|
1017
|
+
rather than honoured, and `orc extra health` reports the clamp.
|
|
1018
|
+
|
|
1019
|
+
**Engine `cli` only.** Engine `api` already has a per-request inactivity timeout
|
|
1020
|
+
on its own socket, and engine `claude-shim` gets one from the child's own byte
|
|
1021
|
+
watchdog. Adding a fourth clock to either would be three timeouts disagreeing
|
|
1022
|
+
about which one fires first, which is the bug `extraTimeouts` exists to prevent.
|
|
1023
|
+
|
|
1024
|
+
### `stalled` is its own failure class, and it is RETRYABLE
|
|
1025
|
+
|
|
1026
|
+
`EXTRA_FAILURES.stalled` — *"the worker went quiet and stopped changing
|
|
1027
|
+
anything"*, `retry: true`. That is the whole point: a stall is retryable, so the
|
|
1028
|
+
recovery procedure above applies to it unchanged. `orc extra reconcile` reads the
|
|
1029
|
+
position out of the journal baseline; `orc extra resume-slice` composes the
|
|
1030
|
+
continuation carrying what is already on disk; `extra_resume` continues from
|
|
1031
|
+
there instead of starting over.
|
|
1032
|
+
|
|
1033
|
+
**That IS ORC's spelling of typing `continue`.** There is deliberately no key
|
|
1034
|
+
that nudges the child on its stdin: `opencode run` is not an interactive session,
|
|
1035
|
+
so a keystroke nobody reads would be a fake fix — and a fake fix here is worse
|
|
1036
|
+
than none, because it would look like the problem was handled.
|
|
1037
|
+
|
|
1038
|
+
### Every outcome carries a TIMELINE
|
|
1039
|
+
|
|
1040
|
+
`timeline` rides on every engine-`cli` return, not only on a stall:
|
|
1041
|
+
`first_byte_ms` · `last_progress_ms` · `longest_gap_ms` · `quiet_for_ms` ·
|
|
1042
|
+
`stall_budget_ms` · `wall_budget_ms`. Print it. **A budget you can only see when
|
|
1043
|
+
it fires is a budget nobody can set before it does** — and `first_byte_ms: null`
|
|
1044
|
+
is the honest reading of a worker that never said anything, never `0`.
|
|
1045
|
+
|
|
1046
|
+
### `orc extra health <profile> [--model <id>]` — does this model stall?
|
|
1047
|
+
|
|
1048
|
+
Exit **0** answered · **1** stalled or failed · **2** unknown profile.
|
|
1049
|
+
|
|
1050
|
+
It runs the live probe through **the same watchdog a dispatch uses** — not a
|
|
1051
|
+
second idea of the path, which is the v0.53.3 rule that a green badge must be
|
|
1052
|
+
earned by the path a wave actually runs. What it adds over
|
|
1053
|
+
`orc extra ping --live` is the timeline and the verdict: `answered` · `stalled` ·
|
|
1054
|
+
`timeout` · `failed` · `spawn-failed`, plus the bytes the worker produced, capped
|
|
1055
|
+
and rendered as text.
|
|
1056
|
+
|
|
1057
|
+
A **listed** model is not a **working** model and a working model is not a model
|
|
1058
|
+
that **finishes**: those are three different facts and this is the command that
|
|
1059
|
+
tells the third one apart. Run it before routing a band at a model you have not
|
|
1060
|
+
used. A CLI ping is not a cheap ping — say so.
|
|
1061
|
+
|
|
1062
|
+
---
|
|
1063
|
+
|
|
1064
|
+
## The demotion — the ladder moves at runtime (v1.0.0)
|
|
1065
|
+
|
|
1066
|
+
### `a lane that keeps paying a provider that stopped working` has broken this contract
|
|
1067
|
+
|
|
1068
|
+
`extra_stall_s` stops ONE dispatch. It has nothing to say about the second one,
|
|
1069
|
+
or the third. A provider that goes quiet twice in a row is not having a bad
|
|
1070
|
+
minute — it is costing you a wave and buying nothing — and ORC used to keep
|
|
1071
|
+
handing it the next task anyway, because nothing counted.
|
|
1072
|
+
|
|
1073
|
+
So it counts now. **Two consecutive `stalled` dispatches on one profile inside
|
|
1074
|
+
one run, or one live attempt with no observable progress for 20 minutes, drop
|
|
1075
|
+
that profile to the BOTTOM of its families for the rest of the run.**
|
|
1076
|
+
`opus5_only` — or the shipped score→model table — becomes the effective P0, and
|
|
1077
|
+
the work stays on Claude.
|
|
1078
|
+
|
|
1079
|
+
### It writes no new measurement, and it is never remembered
|
|
1080
|
+
|
|
1081
|
+
Every fact the trigger reads already shipped: `EXTRA_FAILURES.stalled` and the
|
|
1082
|
+
`timeline` block (v0.56.1), and the extra journal written by `orc extra dispatch`
|
|
1083
|
+
itself before the first byte leaves the machine (v0.54.0). The demotion READS
|
|
1084
|
+
the journal and decides — **computed by the CLI from disk on every read, never
|
|
1085
|
+
stored as a verdict and never carried in your head.** That is the lesson this
|
|
1086
|
+
repo has now lost to four times: v0.32.0 narration, v0.49.5 the hand-back,
|
|
1087
|
+
v0.53.2 the spend log, v0.54.0 the journal. **A fact relayed through a model's
|
|
1088
|
+
memory is a fact this repo has already lost.**
|
|
1089
|
+
|
|
1090
|
+
The only thing written to disk is the HUMAN half — a promote or a manual demote,
|
|
1091
|
+
with its reason — under `{run_dir}/{slug}/extra-demotion.json`, beside
|
|
1092
|
+
`RESUME.md`. That is a decision, not a verdict, and it is deleted with the run.
|
|
1093
|
+
|
|
1094
|
+
### The two clocks measure different things and stay two clocks
|
|
1095
|
+
|
|
1096
|
+
```
|
|
1097
|
+
demote(profile, run) ⇔
|
|
1098
|
+
consecutive_stalls(profile, run) >= extra_demote_after (default 2)
|
|
1099
|
+
OR a LIVE attempt quiet for >= extra_demote_stale_min minutes (default 20)
|
|
1100
|
+
```
|
|
1101
|
+
|
|
1102
|
+
- **The consecutive clock is about attempts that ENDED.** A stall is a stall
|
|
1103
|
+
whether its resume succeeded or not: a profile that needs a continuation twice
|
|
1104
|
+
in a row is costing more than it saves.
|
|
1105
|
+
- **The stale clock is about an attempt that has NOT ended.** `extra_stall_s`
|
|
1106
|
+
already stops one dispatch after 180 seconds of silence. This one is about the
|
|
1107
|
+
RUN — two workers in flight, both quiet, and a wave that is going nowhere.
|
|
1108
|
+
Different question, different budget, its own key and its own off value.
|
|
1109
|
+
**Neither is a simplification of the other**, and merging them "for
|
|
1110
|
+
simplicity" is the failure this paragraph exists to prevent.
|
|
1111
|
+
- **The counter is per PROFILE**, not per provider and not global. Two profiles
|
|
1112
|
+
on one provider can hold different keys, different models and different
|
|
1113
|
+
reliability.
|
|
1114
|
+
- **A resume of the same stalled attempt is the SAME stall.** It neither
|
|
1115
|
+
increments the counter nor resets it.
|
|
1116
|
+
- **`consecutive` resets on a completed dispatch that was not a stall** —
|
|
1117
|
+
including a 401.
|
|
1118
|
+
- **ONLY `stalled` counts.** Not `timeout` (the budget was the operator's
|
|
1119
|
+
choice), not `rate_limit`, not `authentication_failed`. Each of those has its
|
|
1120
|
+
own answer — `extra_on_failure`, the vault, `extra_resume` — and **a demotion
|
|
1121
|
+
triggered by a 401 would hide a credential problem behind a routing change**,
|
|
1122
|
+
where the user would never see the real fault.
|
|
1123
|
+
- **`extra_stall_s: 0` silently turns the consecutive clock off too:** no
|
|
1124
|
+
dispatch is ever classified `stalled`, so the counter can never move and only
|
|
1125
|
+
the stale clock remains. `orc extra demotion` says so rather than reporting a
|
|
1126
|
+
clock that cannot fire.
|
|
1127
|
+
|
|
1128
|
+
### The four things it must never do
|
|
1129
|
+
|
|
1130
|
+
1. **It never writes your config.** Run-scoped, like `/orc-ultra`'s
|
|
1131
|
+
`ultra_mode`. A run that had a bad afternoon must not silently turn off a
|
|
1132
|
+
subsystem you paid to set up.
|
|
1133
|
+
2. **It never auto-promotes inside the run.** Two stalls is evidence, and a
|
|
1134
|
+
timer that re-arms a provider spends money on the evidence it already has.
|
|
1135
|
+
`orc extra promote <run> --reason "<why>"` is a human action and the reason is
|
|
1136
|
+
stored verbatim — the `/orc-pact` retirement rule. **A promote is a
|
|
1137
|
+
WATERMARK, not a mute:** it forgives the evidence it saw, and two fresh stalls
|
|
1138
|
+
after it demote again.
|
|
1139
|
+
3. **It never changes WHAT.** The score does not move, `declared_files` is not
|
|
1140
|
+
widened, `acceptance[]` is not touched — `extra_fallback_agent`'s rule
|
|
1141
|
+
inherited verbatim. **A demotion changes WHERE the work runs and nothing
|
|
1142
|
+
else**, and the task lands on the SAME Claude agent it would have had.
|
|
1143
|
+
4. **It never abandons the position.** A demoted run still goes
|
|
1144
|
+
`orc extra reconcile` → `orc extra resume-slice` → an ordinary Claude
|
|
1145
|
+
dispatch. `a lane that re-does work the worktree already contains` applies
|
|
1146
|
+
here exactly as it applies to the fallback, and it is the same code path.
|
|
1147
|
+
|
|
1148
|
+
### It is ANNOUNCED, and that is not optional
|
|
1149
|
+
|
|
1150
|
+
The mirror of `a lane that sends work off Claude without saying so` is **a lane
|
|
1151
|
+
that quietly STOPS.** A user who connected a provider deserves to be told the
|
|
1152
|
+
run left it. The line is CLI-worded (`announce` on the demotion state), it
|
|
1153
|
+
arrives in `orc lane config`'s `announce[]`, and it must be printed **before the
|
|
1154
|
+
next dispatch**. `orc lane config` renders the overlay rank as `state:
|
|
1155
|
+
"demoted"` — its own word, keeping its slot, because rendering it as
|
|
1156
|
+
`extra: off` would make *"I turned this off"* and *"this run left your provider
|
|
1157
|
+
after two stalls"* look identical.
|
|
1158
|
+
|
|
1159
|
+
The trace verb is **CLI-composed and copied verbatim**, because **a demotion
|
|
1160
|
+
that leaves no line cannot be counted** (the v0.53.2 rule, restated):
|
|
1161
|
+
|
|
1162
|
+
```
|
|
1163
|
+
EXTRA demote run=<slug> :: profile=<p> reason=<consecutive-stall|stale-live-attempt|manual> n=<k> → <the ladder that answers now>
|
|
1164
|
+
```
|
|
1165
|
+
|
|
1166
|
+
### The three commands
|
|
1167
|
+
|
|
1168
|
+
| command | exit codes | notes |
|
|
1169
|
+
|---|---|---|
|
|
1170
|
+
| `orc extra demotion [<run>] [--json]` | `0` armed · `1` demoted · `2` unknown run | a READ, and the exit code is the answer. `--json is not a summary`: it carries both clocks, the counter, the evidence task ids, the ladder before and after, and the announce line |
|
|
1171
|
+
| `orc extra promote <run> --reason "<why>"` | `0` promoted · `1` nothing was demoted · `2` unknown run | the reason is REQUIRED and stored verbatim |
|
|
1172
|
+
| `orc extra demote <run> --reason "<why>"` | `0` demoted · `2` unknown run | the manual half. Somebody who knows the provider is down should not have to wait for two stalls |
|
|
1173
|
+
|
|
1174
|
+
`orc extra preflight` **reports a live demotion and does not move its exit
|
|
1175
|
+
code** — a demotion is a finding, not a stop, the `extra-orphan-dispatch`
|
|
1176
|
+
precedent. `orc doctor` gains **`extra-demoted-run`**, routed to the Extra
|
|
1177
|
+
panel's Recovery tab, which is where `orc extra promote` lives.
|
|
1178
|
+
|
|
1179
|
+
`orc extra stats` aggregates it **per profile across every run the journal still
|
|
1180
|
+
holds** — a provider that demotes in every run is a pattern; one that demoted
|
|
1181
|
+
once is an afternoon, and the difference is only visible if somebody counts.
|
|
1182
|
+
There is **no rate below 3 runs**, the `extra-profile-unreliable` restraint
|
|
1183
|
+
verbatim.
|
|
1184
|
+
|
|
1185
|
+
### The keys, and the two that were refused
|
|
1186
|
+
|
|
1187
|
+
| key | default | off |
|
|
1188
|
+
|---|---:|---|
|
|
1189
|
+
| `config.extra_demote_after` | `2` | `0` — never demote on consecutive stalls |
|
|
1190
|
+
| `config.extra_demote_stale_min` | `20` | `0` — never demote on a stale live attempt |
|
|
1191
|
+
|
|
1192
|
+
Both gated by `extra_enabled`. **Setting both to `0` is the honest off switch**,
|
|
1193
|
+
which is why there is no third key:
|
|
1194
|
+
|
|
1195
|
+
- **REFUSED — `extra_demote` (`on`/`off`).** The two zeros already are it, and a
|
|
1196
|
+
master switch over two numbers is a third spelling of one thing — the drift
|
|
1197
|
+
this subsystem lints for everywhere else.
|
|
1198
|
+
- **REFUSED — `extra_promote_after` (an auto re-promote timer).** A timer that
|
|
1199
|
+
re-arms a provider which stalled twice is a timer that spends money on the
|
|
1200
|
+
evidence it already has. Promotion is a human decision with a recorded reason.
|
|
1201
|
+
|
|
1202
|
+
---
|
|
1203
|
+
|
|
1204
|
+
## Who picks the task up — `extra_fallback_agent` (v0.56.1)
|
|
1205
|
+
|
|
1206
|
+
`fallback_to` has always carried the band's (or the slot's) own Claude agent.
|
|
1207
|
+
That is the right default and the only one ORC can compute on its own: **a
|
|
1208
|
+
fallback that changes tier is a re-plan nobody asked for.**
|
|
1209
|
+
|
|
1210
|
+
What it could not do is let a human choose. A stall costs real minutes before
|
|
1211
|
+
anybody hears about it, and by the time the wave stops the user often knows
|
|
1212
|
+
something ORC does not — that this slice wants more thinking than its band
|
|
1213
|
+
bought, or less.
|
|
1214
|
+
|
|
1215
|
+
| `extra_fallback_agent` | what the lane does |
|
|
1216
|
+
|---|---|
|
|
1217
|
+
| `band` (default) | dispatch `fallback.agent`, which is `fallback_to.agent`. Pre-v0.56.1 behaviour, unchanged. |
|
|
1218
|
+
| `ask` | **STOP and put `fallback.options[]` to the user.** Dispatch what they pick. |
|
|
1219
|
+
| any `orc-…` agent name | dispatch that one, and say it overrode the task's own agent. |
|
|
1220
|
+
|
|
1221
|
+
The return carries `fallback` beside `fallback_to`: `mode`, `agent`,
|
|
1222
|
+
`band_agent`, `options[]` (each with `agent`, `why`, `is_band`) and a `note` that
|
|
1223
|
+
is already worded — print it rather than composing a second wording.
|
|
1224
|
+
|
|
1225
|
+
Three rules hold it together.
|
|
1226
|
+
|
|
1227
|
+
1. **Under `ask` the lane does not choose.** `fallback.agent` is `null` and the
|
|
1228
|
+
trace line says `→ pending (extra_fallback_agent=ask)`. A lane that picked the
|
|
1229
|
+
first option would be answering the one question the setting exists to ask,
|
|
1230
|
+
and `/orc-retro` would aggregate a decision nobody made.
|
|
1231
|
+
2. **The menu is COMPUTED and the band's own agent LEADS it.** It is what
|
|
1232
|
+
happens if the user just presses enter. The three alternates —
|
|
1233
|
+
`orc-executor-opus-5-med`, `orc-executor-opus-5-low`,
|
|
1234
|
+
`orc-executor-sonnet-4-6-high` — are offered, and so is any installed agent
|
|
1235
|
+
name, because the roster is generated and a closed list here would go stale
|
|
1236
|
+
the next time a band moves.
|
|
1237
|
+
3. **It changes WHO, never WHAT.** The score does not move, `declared_files` is
|
|
1238
|
+
not widened, `acceptance[]` is not touched, and a resume slice stays a resume
|
|
1239
|
+
slice. This is the `extra resume-slice` rule applied to the fallback.
|
|
1240
|
+
|
|
1241
|
+
**`/orc-quick` is INERT here too,** and announces it at the agent gate — beside
|
|
1242
|
+
`extra_enabled`, `extra_on_failure`, `extra_resume`, `opus5_only` and
|
|
1243
|
+
`rubric_bands_override`. That lane asks which agent before every dispatch, so a
|
|
1244
|
+
config that pre-answered it would be the exact failure the gate exists to
|
|
1245
|
+
prevent.
|
|
1246
|
+
|
|
1247
|
+
---
|
|
1248
|
+
|
|
1249
|
+
## The config surface — fifteen keys, and the count is still the point
|
|
982
1250
|
|
|
983
1251
|
The combinatorial part — providers × models × bands **× positions** — is a
|
|
984
1252
|
**ledger with a CLI and a panel** (`orc extra`), not a YAML block nobody can hold
|
|
985
1253
|
in their head.
|
|
986
1254
|
|
|
1255
|
+
**v1.0.0 added TWO** — `extra_demote_after` and `extra_demote_stale_min` — and
|
|
1256
|
+
both are NUMBERS WITH A DOCUMENTED OFF VALUE rather than a switch, because the
|
|
1257
|
+
two zeros already are the off switch and a master key over them would be a third
|
|
1258
|
+
spelling of one thing. Two more were refused and are written down above.
|
|
1259
|
+
|
|
1260
|
+
**v0.56.1 added TWO**, and both come from the same observed failure: a foreign
|
|
1261
|
+
worker that goes quiet mid-task. Three more were refused and are written down so
|
|
1262
|
+
nobody proposes them again — **a stdin nudge** (`opencode run` is not an
|
|
1263
|
+
interactive session, so a keystroke nobody reads is a fake fix, and a fake fix
|
|
1264
|
+
looks like the problem was handled), **a per-profile stall budget** (the number
|
|
1265
|
+
describes ORC's patience, not a provider), and **a key to disable the timeline**
|
|
1266
|
+
(the spend-log reasoning verbatim: a record you can switch off is off on the run
|
|
1267
|
+
you needed it for).
|
|
1268
|
+
|
|
987
1269
|
**v0.55.0 added ZERO keys.** A slot row's presence is its arming, so the four
|
|
988
1270
|
that were proposed were all refused: **`extra_slots_enabled`** (a second master
|
|
989
1271
|
gate — `extra_enabled` is one), **per-lane on/off keys** (`extra_doc`,
|
|
@@ -1008,6 +1290,10 @@ of being a string nobody checked).
|
|
|
1008
1290
|
| `config.extra_verify_max_days` | `7` | Past this a verification reads STALE and is re-pinged before wave 1. **A STALE profile still routes** — a stale check is not a failed one. |
|
|
1009
1291
|
| `config.extra_resume` | `on` | Whether a partial or crashed foreign dispatch is RESUMED rather than re-done. **Default `on`, because `off` is what is broken.** INERT in `/orc-quick`. |
|
|
1010
1292
|
| `config.extra_resume_max` | `2` | Resume attempts per task before P6 takes over. The cap STOPS with an honest report naming the Claude agent — never a silent third loop, the same shape as every other bounded repair loop in ORC. |
|
|
1293
|
+
| `config.extra_stall_s` | `180` | Seconds a foreign worker may produce NOTHING before the dispatch is stopped as `stalled`. Reset by observable progress — the worker's stream, its stderr, or a declared file that changed on disk — so it never fires on a worker that is merely slow. `0` disables and the wall clock is the only stop again. **Clamped below `extra_timeout_s`**, because a budget that can never fire is worse than none. Engine `cli` only. |
|
|
1294
|
+
| `config.extra_demote_after` | `2` | Consecutive `stalled` dispatches on ONE profile inside one run before that profile is DEMOTED to the bottom of the ladder for the rest of the run. Only `stalled` counts; a resume of the same stall is the same stall; a completed dispatch that was not a stall resets it. Run state — it never writes your config, it is ANNOUNCED, and it is never promoted back on its own. `0` turns this clock off. |
|
|
1295
|
+
| `config.extra_demote_stale_min` | `20` | Minutes a LIVE attempt may show no observable progress before its profile is demoted. A different question from `extra_stall_s`, which stops ONE dispatch: this clock is about the RUN. `0` turns this clock off. |
|
|
1296
|
+
| `config.extra_fallback_agent` | `band` | WHICH Claude agent picks up a task the foreign worker could not finish. `band` is the pre-v0.56.1 behaviour. `ask` STOPS and puts the menu to the user. Any installed agent name pins one. It changes WHO, never the score, the declared files or the acceptance criteria. INERT in `/orc-quick`. |
|
|
1011
1297
|
|
|
1012
1298
|
**Keys deliberately NOT added, and why each one would be a trap:**
|
|
1013
1299
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Canonical file: `_shared/interview.md`. THE canonical way any ORC lane
|
|
4
4
|
interrogates a human until an idea is sharp enough to act on. Load it wherever a
|
|
5
5
|
lane must ask more than a fixed questionnaire's worth of questions: `/orc-grill`
|
|
6
|
-
runs it end to end, and `
|
|
6
|
+
runs it end to end, and `phases/intake.md` borrows its round format when a
|
|
7
7
|
tier's question set runs long.
|
|
8
8
|
|
|
9
9
|
This is not "ask good questions". It is a specific mechanic with a termination
|
|
@@ -13,14 +13,18 @@ is inert.
|
|
|
13
13
|
|
|
14
14
|
## The mapping (only when `opus5_only: true`)
|
|
15
15
|
|
|
16
|
-
**Scored executors** — one model, EFFORT as the cost dial, replacing the
|
|
16
|
+
**Scored executors** — one model, EFFORT as the cost dial, replacing the 6-band
|
|
17
17
|
mixed-model table:
|
|
18
18
|
|
|
19
19
|
| Score | Executor agent |
|
|
20
20
|
|-----------|---------------------------|
|
|
21
|
-
| `[0,
|
|
22
|
-
| `[
|
|
23
|
-
|
|
21
|
+
| `[0,90)` | `orc-executor-opus-5-low` |
|
|
22
|
+
| `[90,100]` | `orc-executor-opus-5-med` |
|
|
23
|
+
|
|
24
|
+
Two bands, sharing the 90 edge with the default table's top two rows. Since
|
|
25
|
+
v1.0.0 the default table's high end is ALREADY Opus 5 with effort as the dial,
|
|
26
|
+
so this mode differs from it only below 65 — a third band here would be a
|
|
27
|
+
distinction the default table stopped making.
|
|
24
28
|
|
|
25
29
|
**Fixed roles** — dispatch the Opus 5 variant **instead of** the default role
|
|
26
30
|
agent: same task slice, same return contract, same phase.
|
|
@@ -77,12 +81,10 @@ exists to prevent. Ladder: `../orc-wiki/references/partial-refresh.md`.
|
|
|
77
81
|
`opus5_only: true` outranks every other dispatch selector:
|
|
78
82
|
|
|
79
83
|
- each role's default frontmatter pin;
|
|
80
|
-
- **`fable5_enabled` / `fable5_roles`** — the Fable 5 role override is fully
|
|
81
|
-
INERT while the mode is on (`../_shared/fable5-override.md` does not apply);
|
|
82
84
|
- **`rubric_bands_override`** — a hand-written executor table is ignored while
|
|
83
85
|
the mode is on.
|
|
84
86
|
|
|
85
|
-
Turning the mode off restores
|
|
87
|
+
Turning the mode off restores both. `rubric_bands` remains granularity
|
|
86
88
|
only, never a preset selector, in both modes.
|
|
87
89
|
|
|
88
90
|
The forcing is flat across every lane that HONORS the mode — `orc-quick` does
|