@orkestrel/scaffold 0.0.108 → 0.0.109

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/dist/agents/skills/orkestrel-dispatch/scripts/bench.js +326 -91
  2. package/dist/agents/skills/orkestrel-dispatch/scripts/brief.js +110 -14
  3. package/dist/agents/skills/orkestrel-dispatch/scripts/chain.js +280 -0
  4. package/dist/agents/skills/orkestrel-dispatch/scripts/cite.js +188 -26
  5. package/dist/agents/skills/orkestrel-dispatch/scripts/launch.js +142 -43
  6. package/dist/agents/skills/orkestrel-dispatch/scripts/login.js +240 -62
  7. package/dist/agents/skills/orkestrel-dispatch/scripts/patch.js +323 -0
  8. package/dist/agents/skills/orkestrel-dispatch/scripts/result.js +169 -32
  9. package/dist/agents/skills/orkestrel-dispatch/scripts/sweep.js +290 -69
  10. package/dist/agents/skills/orkestrel-falsify/scripts/mutate.js +560 -0
  11. package/dist/agents/skills/orkestrel-harden/scripts/discovery.js +1052 -205
  12. package/dist/agents/skills/orkestrel-harden/scripts/measure.js +361 -0
  13. package/dist/agents/skills/orkestrel-harden/scripts/titles.js +455 -80
  14. package/dist/agents/skills/orkestrel-parallel/scripts/cases.js +327 -0
  15. package/dist/agents/skills/orkestrel-publish/scripts/compare.js +298 -51
  16. package/dist/agents/skills/orkestrel-publish/scripts/pins.js +170 -13
  17. package/dist/agents/skills/orkestrel-publish/scripts/swap.js +956 -191
  18. package/dist/agents/skills/orkestrel-publish/scripts/wave.js +707 -112
  19. package/dist/agents/skills/orkestrel-publish/scripts/window.js +235 -41
  20. package/dist/agents/skills/orkestrel-scout/scripts/map.js +341 -54
  21. package/dist/agents/templates/brief.md +1 -1
  22. package/dist/bin/main.js +51 -46
  23. package/dist/bin/main.js.map +1 -1
  24. package/dist/host/AGENTS.md +23 -21
  25. package/dist/host/agents/orchestration.md +43 -18
  26. package/dist/host/agents/platforms/windows.md +3 -3
  27. package/dist/host/agents/skills/orkestrel-align/SKILL.md +10 -13
  28. package/dist/host/agents/skills/orkestrel-align/references/fleet.md +4 -10
  29. package/dist/host/agents/skills/orkestrel-align/references/integration.md +1 -1
  30. package/dist/host/agents/skills/orkestrel-build/SKILL.md +16 -48
  31. package/dist/host/agents/skills/orkestrel-build/agents/openai.yaml +1 -1
  32. package/dist/host/agents/skills/orkestrel-debrief/SKILL.md +19 -16
  33. package/dist/host/agents/skills/orkestrel-debrief/agents/openai.yaml +1 -1
  34. package/dist/host/agents/skills/orkestrel-debrief/references/field-testing.md +15 -28
  35. package/dist/host/agents/skills/orkestrel-debrief/references/instruction-audit.md +5 -6
  36. package/dist/host/agents/skills/orkestrel-debrief/references/retention.md +4 -6
  37. package/dist/host/agents/skills/orkestrel-dispatch/SKILL.md +31 -20
  38. package/dist/host/agents/skills/orkestrel-dispatch/references/launch.md +3 -4
  39. package/dist/host/agents/skills/orkestrel-dispatch/scripts/bench.ts +366 -75
  40. package/dist/host/agents/skills/orkestrel-dispatch/scripts/brief.ts +126 -16
  41. package/dist/host/agents/skills/orkestrel-dispatch/scripts/chain.ts +323 -0
  42. package/dist/host/agents/skills/orkestrel-dispatch/scripts/cite.ts +220 -31
  43. package/dist/host/agents/skills/orkestrel-dispatch/scripts/launch.ts +176 -33
  44. package/dist/host/agents/skills/orkestrel-dispatch/scripts/login.ts +294 -59
  45. package/dist/host/agents/skills/orkestrel-dispatch/scripts/patch.ts +401 -0
  46. package/dist/host/agents/skills/orkestrel-dispatch/scripts/result.ts +199 -34
  47. package/dist/host/agents/skills/orkestrel-dispatch/scripts/sweep.ts +330 -69
  48. package/dist/host/agents/skills/orkestrel-falsify/SKILL.md +10 -8
  49. package/dist/host/agents/skills/orkestrel-falsify/references/brief.md +1 -5
  50. package/dist/host/agents/skills/orkestrel-falsify/references/reconcile.md +1 -1
  51. package/dist/host/agents/skills/orkestrel-falsify/scripts/mutate.ts +701 -0
  52. package/dist/host/agents/skills/orkestrel-harden/SKILL.md +16 -12
  53. package/dist/host/agents/skills/orkestrel-harden/references/bindings.md +23 -81
  54. package/dist/host/agents/skills/orkestrel-harden/references/centralization.md +4 -5
  55. package/dist/host/agents/skills/orkestrel-harden/references/contract.md +2 -0
  56. package/dist/host/agents/skills/orkestrel-harden/references/document.md +33 -0
  57. package/dist/host/agents/skills/orkestrel-harden/references/equivalence.md +6 -3
  58. package/dist/host/agents/skills/orkestrel-harden/references/hardening.md +8 -4
  59. package/dist/host/agents/skills/orkestrel-harden/references/research.md +2 -0
  60. package/dist/host/agents/skills/orkestrel-harden/scripts/discovery.ts +1272 -279
  61. package/dist/host/agents/skills/orkestrel-harden/scripts/measure.ts +425 -0
  62. package/dist/host/agents/skills/orkestrel-harden/scripts/titles.ts +603 -98
  63. package/dist/host/agents/skills/orkestrel-journey/SKILL.md +75 -98
  64. package/dist/host/agents/skills/orkestrel-journey/references/captures.md +54 -17
  65. package/dist/host/agents/skills/orkestrel-journey/references/decide.md +1 -20
  66. package/dist/host/agents/skills/orkestrel-journey/references/layer.md +21 -31
  67. package/dist/host/agents/skills/orkestrel-journey/references/styles.md +1 -1
  68. package/dist/host/agents/skills/orkestrel-parallel/SKILL.md +28 -24
  69. package/dist/host/agents/skills/orkestrel-parallel/references/claude.md +15 -13
  70. package/dist/host/agents/skills/orkestrel-parallel/references/codex.md +1 -0
  71. package/dist/host/agents/skills/orkestrel-parallel/references/cursor.md +13 -13
  72. package/dist/host/agents/skills/orkestrel-parallel/scripts/cases.ts +389 -0
  73. package/dist/host/agents/skills/orkestrel-polish/SKILL.md +16 -20
  74. package/dist/host/agents/skills/orkestrel-polish/references/capture-harness.md +16 -26
  75. package/dist/host/agents/skills/orkestrel-publish/SKILL.md +12 -26
  76. package/dist/host/agents/skills/orkestrel-publish/agents/openai.yaml +2 -2
  77. package/dist/host/agents/skills/orkestrel-publish/references/adopt.md +23 -0
  78. package/dist/host/agents/skills/orkestrel-publish/references/release.md +4 -4
  79. package/dist/host/agents/skills/orkestrel-publish/references/wave.md +10 -9
  80. package/dist/host/agents/skills/orkestrel-publish/references/window.md +20 -25
  81. package/dist/host/agents/skills/orkestrel-publish/scripts/compare.ts +348 -59
  82. package/dist/host/agents/skills/orkestrel-publish/scripts/pins.ts +202 -22
  83. package/dist/host/agents/skills/orkestrel-publish/scripts/swap.ts +1061 -191
  84. package/dist/host/agents/skills/orkestrel-publish/scripts/wave.ts +812 -140
  85. package/dist/host/agents/skills/orkestrel-publish/scripts/window.ts +280 -38
  86. package/dist/host/agents/skills/orkestrel-scout/SKILL.md +3 -3
  87. package/dist/host/agents/skills/orkestrel-scout/scripts/map.ts +428 -70
  88. package/dist/host/agents/templates/brief.md +1 -1
  89. package/dist/host/agents/transports/claude-cli.md +3 -3
  90. package/dist/host/agents/transports/codex.md +2 -7
  91. package/dist/host/agents/transports/cursor.md +2 -3
  92. package/dist/host/claude/AGENTS.md +2 -2
  93. package/dist/host/claude/agents/analyst.md +3 -3
  94. package/dist/host/claude/agents/astra.md +3 -3
  95. package/dist/host/claude/agents/builder.md +1 -1
  96. package/dist/host/claude/agents/checker.md +1 -1
  97. package/dist/host/claude/agents/distiller.md +1 -1
  98. package/dist/host/claude/agents/grok.md +1 -1
  99. package/dist/host/claude/agents/opus.md +2 -2
  100. package/dist/host/claude/agents/orkestrel.md +57 -90
  101. package/dist/host/claude/agents/researcher.md +1 -1
  102. package/dist/host/claude/agents/reviewer.md +4 -0
  103. package/dist/host/claude/agents/scout.md +1 -1
  104. package/dist/host/claude/agents/verifier.md +1 -1
  105. package/dist/host/claude/rules/application.md +14 -21
  106. package/dist/host/claude/rules/architecture.md +34 -44
  107. package/dist/host/claude/rules/browser.md +3 -4
  108. package/dist/host/claude/rules/campaign.md +2 -2
  109. package/dist/host/claude/rules/documentation.md +25 -12
  110. package/dist/host/claude/rules/names.md +9 -4
  111. package/dist/host/claude/rules/patterns.md +6 -7
  112. package/dist/host/claude/rules/portability.md +1 -1
  113. package/dist/host/claude/rules/quality.md +4 -5
  114. package/dist/host/claude/rules/styles.md +2 -2
  115. package/dist/host/claude/rules/tests.md +57 -114
  116. package/dist/host/claude/rules/typescript.md +7 -9
  117. package/dist/host/claude/rules/workspace.md +21 -19
  118. package/dist/host/claude/rules/writing.md +2 -5
  119. package/dist/host/claude/skills/orkestrel-dispatch/SKILL.md +1 -1
  120. package/dist/host/claude/skills/orkestrel-harden/SKILL.md +1 -1
  121. package/dist/host/claude/skills/orkestrel-publish/SKILL.md +1 -1
  122. package/dist/host/claude/skills/orkestrel-scout/SKILL.md +1 -1
  123. package/dist/host/codex/agents/analyst.toml +9 -3
  124. package/dist/host/codex/agents/astra.toml +3 -4
  125. package/dist/host/codex/agents/builder.toml +1 -1
  126. package/dist/host/codex/agents/opus.toml +3 -4
  127. package/dist/host/codex/agents/orkestrel.toml +1 -1
  128. package/dist/host/codex/agents/researcher.toml +2 -2
  129. package/dist/host/codex/agents/verifier.toml +1 -1
  130. package/dist/host/configs/helpers.ts +21 -1
  131. package/dist/host/configs/policy.ts +299 -15
  132. package/dist/host/dotfiles/oxlintrc.json +137 -3
  133. package/dist/host/guides/agent.md +111 -134
  134. package/dist/host/guides/capture.md +801 -0
  135. package/dist/host/guides/probe.md +27 -8
  136. package/dist/host/guides/scaffold.md +96 -18
  137. package/dist/host/guides/study.md +534 -440
  138. package/dist/host/guides/test.md +111 -44
  139. package/dist/host/manifest.json +160 -240
  140. package/dist/host/tests/config.test.ts +971 -187
  141. package/dist/host/tests/policy.test.ts +127 -1
  142. package/dist/host/tests/setupPolicy.ts +893 -33
  143. package/dist/src/core/index.cjs +214 -86
  144. package/dist/src/core/index.cjs.map +1 -1
  145. package/dist/src/core/index.d.cts +122 -38
  146. package/dist/src/core/index.d.ts +122 -38
  147. package/dist/src/core/index.js +209 -85
  148. package/dist/src/core/index.js.map +1 -1
  149. package/dist/src/server/index.cjs +20 -27
  150. package/dist/src/server/index.cjs.map +1 -1
  151. package/dist/src/server/index.js +21 -28
  152. package/dist/src/server/index.js.map +1 -1
  153. package/package.json +11 -11
  154. package/dist/agents/skills/orkestrel-dispatch/scripts/helpers.js +0 -283
  155. package/dist/host/agents/skills/orkestrel-dispatch/references/bench.md +0 -25
  156. package/dist/host/agents/skills/orkestrel-dispatch/scripts/helpers.ts +0 -333
  157. package/dist/host/guides/supervisor.md +0 -4890
@@ -18,10 +18,6 @@ description: Prove a browser application the way a person uses it — real keyst
18
18
  7. The `*/types.ts` of every environment the journeys drive, plus the application's root component,
19
19
  route entry, and store contract.
20
20
 
21
- Treat a retained readiness verdict as evidence to re-verify against the current tip, never as a plan
22
- to resume. Re-take every ruling it records that this run's acceptance depends on, and name the commit
23
- each ruling was taken at.
24
-
25
21
  ## Declare the families
26
22
 
27
23
  Declare in the browser environment's `integration.test.ts` which families that screen carries, and
@@ -82,19 +78,19 @@ start, and let it choose the capture destination, the matrix row, and the statec
82
78
  browser application is born with. Its presence is the journey axis. Rename and extend the seeded
83
79
  viewports for this application.
84
80
  - Activate the axis in a workspace born before it: write `configs/app/vite.journey.config.ts`, run
85
- `scaffold repair`, then add `npm run test:journey` to the `test` script after `npm run test:app`.
86
- The repair defines `appJourney` in the root configuration, emits the `test:journey` script, and
87
- excludes the journey suite from the ordinary `app:browser` project. It does not rewrite the `test`
81
+ `scaffold audit`, and add any missing planned dependencies it names before `scaffold repair`.
82
+ Then add `npm run test:journey` to the `test` script after `npm run test:app`.
83
+ The repair defines `appJourney` in the root configuration, emits `test:journey`, `journey`, and
84
+ `capture`, and excludes the journey suite from the ordinary `app:browser` project. It does not rewrite the `test`
88
85
  chain, so the chain entry is yours to add. Add that entry before the repair instead where you
89
86
  prefer: `test:journey` names a configuration rather than a project, so neither order blocks the
90
87
  repair.
91
- - Name each variant for the theme and the viewport it renders, such as `dark-390`. Never split the
92
- theme from the viewport; a split writes a filename naming a combination the run did not render.
88
+ - Name each variant per [captures.md](references/captures.md) → Variants.
93
89
  - Keep the provided variants as serializable `JourneyVariant` data: `name`, `width`, and `height`.
94
90
  Compose no callback merely to pass that data to a capture.
95
- - Run the axis with `npm run test:journey`, which runs that wrapper and joins the `test` chain. Set
96
- `CAPTURE` to `1` in your own shell and run `npm run test:journey` again to write the frames; the
97
- root configuration reads that variable and provides it as `capture`.
91
+ - Keep `npm run test:journey` as the whole-suite gate in the `test` chain. Use the scoped commands
92
+ under Choosing what to run for iteration and stamped frames; keep the root configuration's
93
+ `CAPTURE === '1'` read and its `capture` provide unchanged.
98
94
  - Keep the journeys in `tests/app/browser/integration.test.ts`, and the journeys of the `vue`
99
95
  extension's application in `tests/app/vue/integration.test.ts`, which `npm run test:journey:vue`
100
96
  runs. Each variant project of a mode collects that file alone, and the application's ordinary
@@ -104,19 +100,65 @@ start, and let it choose the capture destination, the matrix row, and the statec
104
100
  - Render exactly one variant per run for the capture family
105
101
  ([captures.md](references/captures.md) → Variants).
106
102
 
107
- `scaffold audit` reports a manifest and a wrapper that disagree as one of the following questions.
108
- Settle the one it reports before trusting a green run.
103
+ `scaffold audit` reports a manifest and a wrapper that disagree as one of these findings. Settle the one it reports before trusting a green run.
109
104
 
110
- | The question `scaffold audit` reports | Settle it by |
111
- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------- |
112
- | `The manifest at <target> names a Vitest configuration the plan does not emit and the target does not hold: test:journey --config configs/app/vite.journey.config.ts. Add the configuration, or remove the script that names it and its invocation from the test chain.` | Writing the wrapper and running `scaffold repair`, or removing the `test:journey` script and its chain invocation |
113
- | `The manifest at <target> does not invoke npm run test:journey from its test chain. Add npm run test:journey after npm run test:app.` | Adding `npm run test:journey` to the `test` script after `npm run test:app` |
105
+ - The manifest names a Vitest configuration for `test:journey` that the plan does not emit and the target does not hold. Write the wrapper and run `scaffold repair`, or remove the `test:journey` script and its chain invocation.
106
+ - The manifest does not invoke `npm run test:journey` from its `test` chain. Add `npm run test:journey` to the `test` script after `npm run test:app`.
114
107
 
115
108
  `scaffold audit` reports the invocation question only when no chain from `test` reaches
116
109
  `npm run test:journey` through literal `npm run` calls, so a chain reaching it through an
117
110
  intermediate script raises none. It reports the configuration question only for a `test:*` script
118
111
  whose text names `vitest`, so a script naming another runner's configuration raises none either.
119
112
 
113
+ ### Choosing what to run
114
+
115
+ - Run the installed `@orkestrel/capture` package at `node_modules/@orkestrel/capture` through
116
+ `npm run journey -- <selector>` (`capture journey`) for owner-selected behavior with capture
117
+ off, and `npm run capture -- <selector>` (`capture frames`) for capture-bearing journeys with
118
+ `CAPTURE=1`. Keep the commands separate; never append capture work to a behavior run.
119
+ - Before using scoped commands, wire the adopter-owned journey wrapper's discovery, selection
120
+ request, tags, portfolios, registry, and final-case records to the package protocol. Read the
121
+ `@orkestrel/capture` guide's Runner and Runner selection and process protocol sections; scaffold
122
+ seeds the commands and dependency, while the application supplies these declarations.
123
+ - Select `all` or a colon-delimited owner path from the wrapper's tags: `<scope>`,
124
+ `<scope>:<owner>`, or further declared descendants. Use the wrapper's names, never infer them
125
+ from filenames. Keep behavior on the positive `owner:` filter and frames on its intersection
126
+ with the selected capture tags; include the final case in each selection.
127
+ - Narrow with `--variant <name>` (repeatable) and `--case <exact-full-name>`. Use `--state <name>`
128
+ only with frames to resolve its declaring case from fresh evidence. Use `--config <path>` to
129
+ select another wrapper. Give each value-taking flag a nonempty value; use `--flag=value` when
130
+ the value starts with `-`. Pass no second `--` terminator to the executable.
131
+ - Replace the selector with `--changed <ref>` to select changed owners; use `HEAD` for uncommitted
132
+ work. Inspect `--changed <ref> --plan` first: discovery runs, but no execution child starts.
133
+ Read each path's `own`, `shared`, or `outside` classification and the exact next commands.
134
+ Follow a shared-input refusal's explicit whole-suite command; never widen automatically.
135
+ - Refuse a bare command, an unknown selector or variant, an unknown or command-inappropriate
136
+ flag, a repeated single-value flag, a selector beside `--changed`, and `--plan` without
137
+ `--changed`. Treat an empty workload as failure. Follow the reported refresh command when
138
+ state evidence or the accepted registry is missing, stale, or ambiguous.
139
+ - Read the authenticated selection request in the wrapper. Before a behavioral body writes a
140
+ frame, refuse a selected case that declares a state outside the selected owner; split that
141
+ case instead of parking its outside states. Keep the full behavioral placement proof when
142
+ `--state` projects only the requested written frame.
143
+ - Run selected journey variants together in declaration order with capture off. For frames,
144
+ produce the declared first variant in `narrow` before `rest`; when that variant is not
145
+ selected, run only `rest`. Stop after a failed stage, and add no unselected variant or owner.
146
+
147
+ Climb this ladder using only declared owner, case, and variant names:
148
+
149
+ 1. One case on one variant: `npm run journey -- pages:mail --case 'mail shows the inbox' --variant light-390`.
150
+ 2. The changed set: inspect `npm run journey -- --changed HEAD --plan`, then run
151
+ `npm run journey -- --changed HEAD`. For frames, inspect `npm run capture -- --changed HEAD --plan`
152
+ before `npm run capture -- --changed HEAD`.
153
+ 3. A section or page: `npm run journey -- pages:mail:inbox` or `npm run journey -- pages:mail`.
154
+ 4. A group: `npm run journey -- pages`.
155
+ 5. `all` at the gate: `npm run journey -- all`, retaining `npm run test:journey` in the repository's
156
+ whole-suite test chain.
157
+
158
+ Follow a refusal's exact next commands before widening a selection. Use the matching `capture`
159
+ script only when the work needs frames, and apply [captures.md](references/captures.md) before
160
+ judging their freshness or completeness.
161
+
120
162
  ### Prepare the capture theme
121
163
 
122
164
  - Where the application ships a theme control, await the theme action through that interface
@@ -182,41 +224,15 @@ await PORTFOLIO.place('home')
182
224
 
183
225
  ## Apply the journey laws
184
226
 
185
- 1. **Drive only what a person can see and reach.** Resolve every interactive target by its ARIA
186
- role and its accessible name as rendered. Never reach into a component instance, a store, a
187
- transport, a copied credential, or a test-only hook to make a step succeed. Report a step that
188
- cannot be performed through the interface as a finding about the interface.
189
- 2. **Assert what is seen.** Quote the rendered text a person reads, which is `innerText` — a label
190
- under `text-uppercase` asserts as `TRACE` where the source says `Trace`. Never let an entity
191
- state read replace a perception assertion; it may only corroborate one, and
192
- `.claude/rules/tests.md` fixes which entity state a test may read at all.
193
- 3. **Assert what the interface withholds.** Assert every refusal through the resolver's exact
194
- failure voice, and distinguish an absent control from a present but humanly unreachable one.
195
- 4. **Keep transport and persistence proofs in their own declared block,** never inside a journey.
196
- Assert every live or asynchronous fact by convergence — poll until it contains or equals — never
197
- by an identity read of one frame.
198
- 5. **Generate the portfolio from the acceptance journeys.** Place each registered state inside the
199
- journey that reaches it, and never register a state no journey reaches.
200
- 6. **Commit a value through an act a person performs:** `pressKeys('{Enter}')` on the focused
201
- control, a Tab away, or a named button. Report a screen that commits on a timer, on an
202
- unpredictable event, or only after work the person cannot observe as a screen finding, and never
203
- work around it in the layer.
204
- 7. **Type only what a person would.** Journeys carry trusted input; inputs no person would type
205
- belong to the transport family and the parser suites.
206
- 8. **Perform every interaction step unconditionally.** Never gate a step on whether the control it
207
- is about to drive exists or is reachable, and never branch a journey on `readRefusal`. Let the
208
- resolver's failure voice name what the interface withheld. A guarded step passes whether or not
209
- the control was there, so the run goes green on a screen that removed the control.
227
+ - Write every journey under `.claude/rules/tests.md` § Journey tests.
228
+ - Generate the portfolio from the acceptance journeys. Place each registered state inside the
229
+ journey that reaches it, and never register a state no journey reaches.
210
230
 
211
231
  ## Import the journey layer
212
232
 
213
- - Import every journey verb, reader, wait, and fixture builder from `@orkestrel/test/browser`, and
214
- every host-independent wait and table type from `@orkestrel/test`. Write one of your own only
215
- where those entries publish none for the act ([layer.md](references/layer.md) → Import, never
233
+ - Write a verb, reader, or wait of your own only where the entries `.claude/rules/tests.md`
234
+ § Journey tests names publish none for the act ([layer.md](references/layer.md) → Import, never
216
235
  implement).
217
- - Send every key sequence through `pressKeys`, which refuses a sequence sent while nothing but the
218
- document body holds focus. Never reach past it to the provider's own keyboard function from a
219
- journey, a matrix reading, or a statechart phase.
220
236
  - Place a helper you must write in the workspace's browser test setup module, name it for the act,
221
237
  and export it from there under `.claude/rules/tests.md`. Never declare a resolver inside a test
222
238
  file.
@@ -231,30 +247,8 @@ await PORTFOLIO.place('home')
231
247
 
232
248
  Write one journey per user intent, named for what the person achieves rather than for the
233
249
  components it passes through. Place them in the browser environment's `integration.test.ts`, whose
234
- placement and scope `.claude/rules/tests.md` fixes.
235
-
236
- - Enter through the real entry: mount the shipped root component with a real store and the route a
237
- person lands on, and let the application load itself.
238
- - Reach each screen's own controls through forward Tab traversal in at least one journey.
239
- - Type keystroke by keystroke where the keystrokes are the subject; fill in one operation where the
240
- text is only a payload the person pastes.
241
- - Poll every fact the application produces asynchronously until it converges. Never assert one from
242
- a single read after the action. A poll's predicate must be able to go false-to-true after the
243
- action it observes; a predicate already true when the poll starts binds nothing.
244
- - Assert the state the flow must reach, never the transient path taken to it. A criterion that bans
245
- a harmless transient over-refuses and breaks on the next honest implementation.
246
- - Assert the negative beside the positive whenever a value replaces another: name the arriving
247
- sentence and carry the replaced one in `absent`, so the reading that resolves carries one and not
248
- the other ([layer.md](references/layer.md) → The waits).
249
- - Assert the state a control announces beside every drive that sets it, and on an unselected
250
- sibling. A control announcing state owes this assertion whether or not the screen carries the
251
- statechart family.
252
- - After a confirmed destructive action, assert through trusted input that focus landed on a visible,
253
- announced location.
254
- - Assert the whole page's perception never matches the vocabulary the product does not speak —
255
- engine, schema, and implementation words the interface is supposed to translate.
256
- - Report a bare accessible name that answers for more than one reachable element on one screen as a screen
257
- finding, and target through role or region until the screen is fixed.
250
+ placement and scope `.claude/rules/tests.md` fixes. Carry a replaced value in `absent` as
251
+ [layer.md](references/layer.md) → The waits shows.
258
252
 
259
253
  ### The intents every screen owes
260
254
 
@@ -352,34 +346,17 @@ Mutate each assertion class once, read the red, restore, and read the green.
352
346
 
353
347
  Completion requires all of:
354
348
 
355
- - every in-scope user intent reaching its outcome through the interface, with no step that reaches
356
- past it;
357
- - the intents every screen owes present wherever the screen has the state, each outcome taken from
358
- the product guide and every missing one reported as a product finding;
359
- - keyboard-only reachability proven on every screen the journeys cover;
349
+ - every in-scope user intent, the intents every screen owes included, reaching its outcome through the interface with no step that reaches past it, and keyboard-only reachability proven on every screen the journeys cover;
360
350
  - a refusal family per screen, each asserting one exact failure voice;
361
- - the transport family declared separately, driven through real implementations, and convergent;
362
- - the declared families each proven, and the declaration itself asserted;
363
- - the matrix family read once per declared variant, each style reading carrying its published
364
- control from [styles.md](references/styles.md) → The published controls in the same run, and the
365
- contrast reading's control straddling its declared bar;
366
- - the authored-class census and the `extractStyles` reading taken on the mounted screen, each
367
- reporting the population it walked;
368
- - the statechart table driven to a terminal status with no failed row, and the harness tally read
369
- from the object and from its markup;
370
- - the registry-times-variants filename proof and the state-placement proof green in an ordinary run;
371
- - one capture run per variant writing every registered file, and the disk-membership proof green;
372
- - the written artifact produced for every variant the run rendered, named by that variant;
373
- - perception assertions quoting rendered text, and the vocabulary sweep green on the whole page;
374
- - the browser test setup module proven by `tests/setupBrowser.test.ts` in the `setup:browser`
375
- project `scaffold repair` registers;
351
+ - the declared families each proven, the declaration asserted, and the transport family driven through real implementations;
352
+ - the matrix family read once per declared variant, each style reading carrying its published control from [styles.md](references/styles.md) → The published controls, and the authored-class census and the `extractStyles` reading each reporting the population it walked;
353
+ - the statechart table driven to a terminal status with no failed row, and the harness tally read from the object and from its markup;
354
+ - the registry-times-variants filename proof and the state-placement proof green in an ordinary run, one capture run per variant writing every registered file, and the written artifact produced for every variant, named by that variant;
355
+ - the browser test setup module proven by `tests/setupBrowser.test.ts` in the `setup:browser` project `scaffold repair` registers;
376
356
  - each assertion class mutated, with the red reading and the green reading recorded;
377
- - the repository gates green, under the independent-verification law in `.agents/orchestration.md`.
357
+ - the repository gates green, per `.agents/orchestration.md` § Acceptance.
378
358
 
379
- State the engine bound with the verdict. The gate renders one engine, so a claim about a second
380
- engine is unproven until a reading on that engine records it. The emitted `configs/browsers.ts` doc
381
- block is the home of that limit and of the condition that reopens it. Cite that doc block, and copy
382
- neither into a verdict.
359
+ State the engine bound with the verdict, per [styles.md](references/styles.md) → The engine bound.
383
360
 
384
361
  Report each journey by the intent it proves, the refusals it establishes, the states it placed, the
385
362
  variants it read, the statechart outcome it reached, and every screen finding the layer's refusals
@@ -11,7 +11,7 @@ import type { JourneyVariant } from '@orkestrel/test'
11
11
  import type {
12
12
  CaptureVariant,
13
13
  FrameOptions,
14
- FrameReading,
14
+ FrameResult,
15
15
  PortfolioInterface,
16
16
  PortfolioOptions,
17
17
  } from '@orkestrel/test/browser'
@@ -54,12 +54,38 @@ Declare the state names once in the journey file, and build the portfolio from t
54
54
 
55
55
  - Name a state for its screen and its condition — `answer-partial`, `start-storage-failure`,
56
56
  `case-delete-confirmation`.
57
- - Register the states the design work actually needs, and place every registered one. Never leave a
58
- registered state unplaced.
57
+ - Register the states the design work needs, and give every registered state a declaring case.
58
+ In a complete run, place every registered state; in a scoped run, place every state the cases
59
+ that ran declare.
59
60
  - Place a capture state from inside the journey that reaches it, immediately after the assertion
60
61
  that proves the screen is in the condition that state names.
61
62
  - Record each placed name in the suite's own set in the same step that calls `place`. That set, not
62
63
  `placements`, is what the always-on placement proof reads.
64
+ - Give each owner-bearing case registry-derived `owner:` tags. Declare a placing case's states in
65
+ `meta.states`, derive its capture scope and part tags from those states, and place only states
66
+ of that owner. Give behavior-only cases no capture tag.
67
+ - Derive variant-conditional declarations and placements from the same predicate. Keep the
68
+ ownerless infrastructure cases explicit, outside behavioral work counts and completeness.
69
+ - Store frames in their declared per-scope directories, and pass those roots to the wrapper's
70
+ portfolio declarations.
71
+
72
+ ## Scoped commands
73
+
74
+ - Run `npm run journey -- <selector>` for behavior and `npm run capture -- <selector>` for frames.
75
+ Take both commands from `node_modules/@orkestrel/capture`; follow
76
+ [SKILL.md](../SKILL.md#choosing-what-to-run) for selector grammar, flags, refusals, and the
77
+ case, changed-set, section or page, group, and `all` ladder. Retain `test:journey` as the
78
+ whole-suite gate.
79
+ - Inspect the changed set with `--changed <ref> --plan` before executing it. Keep a shared-input
80
+ refusal explicit, and follow its next command without silently capturing the complement.
81
+ - Use the authenticated selection request to refuse a case whose declared states cross the
82
+ selected owner before any behavioral body runs. Split the case; never park the outside states.
83
+ - Resolve a frames-only `--state` request from fresh registry and passing case evidence. Keep the
84
+ declaring case's behavior and full placement proof, projecting only the written frames onto
85
+ the requested state. Follow the explicit refresh command when the lookup refuses.
86
+ - Keep each variant project on one rendered variant. Produce the selected first variant in
87
+ `narrow`, then the remaining selected variants in `rest`; omit `narrow` when its variant is
88
+ not selected and stop after a failed stage.
63
89
 
64
90
  ## Variants
65
91
 
@@ -71,37 +97,47 @@ these.
71
97
  application's to set, and the presence of that file is the journey axis.
72
98
  - Prepare the theme under [SKILL.md](../SKILL.md#prepare-the-capture-theme) before driving the
73
99
  captured state, and use the variant list that preparation requires.
74
- - Name each variant for the theme and the viewport it renders, such as `dark-390`. The name is the
75
- second half of every filename the run writes, so a variant named for one alone produces a
76
- portfolio nobody can tell apart.
100
+ - Name each variant for the theme and the viewport it renders, such as `dark-390`. Never split the
101
+ theme from the viewport. The name is the second half of every filename the run writes, so a
102
+ variant named for one alone writes a filename naming a combination the run did not render.
77
103
  - Pass the whole declared list as `variants` and `inject('variant')` as `variant`.
78
104
  `createPortfolio` refuses a `variant` no declared variant carries, and `files` expands the
79
105
  registry across the whole list rather than across the one being rendered.
80
- - Produce the portfolio — the registry times the variants — by running the axis once per variant,
81
- which `npm run test:journey` does in one command.
106
+ - Produce the complete stamped portfolio with `npm run capture -- all`, which runs the declared
107
+ variant projects through the capture runner. Keep `npm run test:journey` as the complete
108
+ behavioral gate; a bare capture-flag run supplies no manifest stamp.
82
109
 
83
110
  ## The proofs the suite owes
84
111
 
85
112
  Write each of the following proofs into the suite. The package asserts none of them.
86
113
 
87
- | Proof | Runs | Asserts |
88
- | -------------------- | -------------- | ---------------------------------------------------------------------------------- |
89
- | Filename expansion | Always | `expandCaptures(states, variants)` has one entry per state and variant, all unique |
90
- | Placement membership | Always | The suite's placed set equals the registry, as sets |
91
- | Disk membership | Under the flag | The filenames on disk equal the expansion for this run's variant |
114
+ | Proof | Runs | Asserts |
115
+ | -------------------- | -------------- | ------------------------------------------------------------------------------------------------------- |
116
+ | Filename expansion | Always | `expandCaptures(states, variants)` has one entry per state and variant, all unique |
117
+ | Declaration coverage | Always | The case declarations cover the registry, are disjoint, and match the owner and capture tag definitions |
118
+ | Placement membership | Always | The suite's placed set equals the states declared by the cases that ran, as sets |
119
+ | Disk membership | Under the flag | The written filenames equal the selected expansion for this run's variant, with no orphan on disk |
92
120
 
93
121
  - Keep the filename proof always-on, so a registry edit that introduces a duplicate or a collision
94
122
  fails the ordinary run. Compare `expandCaptures(states, variants)` against `files` and against a
95
123
  set built from it; a length equal to the set's size is what proves the expansion unique.
96
- - Assert placement as set equality against the registry, in every run.
124
+ - Assert declaration coverage even in a scoped run: fail a registered state declared nowhere,
125
+ overlapping declarations, or an owner or capture tag definition that differs from the registry.
126
+ - Assert placement as set equality against the union of the states the cases that ran declare.
127
+ When every case ran, require that union to equal the registry. Derive completeness from the
128
+ recorded cases that ran and passed, never from the selector or a task's mode alone.
97
129
  - Read the placement proof from the suite's own set rather than from `placements`, which stays empty
98
130
  in an ordinary run. `place` refuses an unregistered name and a second placement of one state in
99
131
  every run, but a registered state that no journey placed reaches no refusal; the always-on
100
132
  placement proof catches it.
101
- - Under the flag, assert the written filenames equal the registry expanded for the run's variant.
133
+ - Under the flag, assert the written filenames equal the ran cases' declared states expanded for
134
+ the run's variant, or the explicit state's projection. Keep the full placement assertion in
135
+ that projected run, and refuse an orphan on disk while retaining untouched registered frames.
102
136
  `captureFrame` already reads each file back and compares its bytes against the frame it shot, so
103
137
  the path `place` returns is proof the file exists and holds that frame.
104
138
  - Put the membership proof last in the file, after every journey that feeds its tally.
139
+ - At group closure, prove the union of the group's declarations and its cross-section
140
+ interactions. Run the whole-registry census only when complete reference coverage ran.
105
141
 
106
142
  ## Transient states
107
143
 
@@ -118,7 +154,8 @@ after the click returns.
118
154
  - Take each frame after the paint settles. Reach for `waitForAnimations` on the element whose
119
155
  transition was running ([layer.md](layer.md) → The waits); a frame shot mid-transition pictures a
120
156
  state the interface never rests in.
121
- - Regenerate the whole matrix from the journeys after any screen change. Never judge a round
122
- against a portfolio that is part old and part new.
157
+ - Judge only frames the capture manifest records as current: every source digest the frame
158
+ recorded must equal the tree's. Recapture what the staleness report names before the round.
159
+ Admit a portfolio assembled from several runs only when every judged frame is current.
123
160
  - Route review of the portfolio to the `orkestrel-polish` campaign, which owns preflight,
124
161
  verdicts, and reconciliation. This reference owns only how the journeys generate it.
@@ -26,26 +26,7 @@ follow it there rather than restating it here.
26
26
 
27
27
  ## The limit that decides the split
28
28
 
29
- `prove` cannot serve a browser project, and the limit belongs to the installed `@orkestrel/probe`
30
- rather than to a version this file names. Confirm it against the copy this workspace holds before
31
- routing a rendered question, and record the version you read beside the ruling.
32
-
33
- Read the pool pin, the project lookup, and the guide's own statement. Any of them holding is the
34
- limit holding:
35
-
36
- - **The pool pin.** Read the runtime stage in the installed server entry. Where it pins the
37
- `threads` pool, a browser project's specification runs in a Node worker,
38
- `@orkestrel/test/browser` imports `vitest/browser` at module scope, and the browser setup file
39
- throws before the case runs.
40
- - **The project lookup.** The runtime stage looks a project up by the name it infers from the test
41
- path, and a browser project is instantiated under its browser-expanded name, so the lookup finds
42
- nothing and the claim is refused as missing.
43
- - **The guide's statement.** Read what `@orkestrel/probe`'s own guide says the stages serve. Where
44
- it names no browser project, no stage claims one.
45
-
46
- Never route a rendered question to `prove` while any of them holds. The pinned-pool refusal arrives
47
- as a case failure, which reads exactly like a broken claim. Record the version, the pool pin you
48
- read, and what the guide says, so the next round re-reads rather than re-deriving.
29
+ `prove` cannot serve a browser project. The runtime stage of `@orkestrel/probe` creates each specification with the `threads` pool (the `createSpecification` call in `node_modules/@orkestrel/probe/dist/src/server/index.js`), so a browser project's specification runs in a Node worker, where `@orkestrel/test/browser` imports `vitest/browser` and the browser setup file throws before the case runs. The refusal arrives as a case failure and reads like a broken claim. Never route a rendered question to `prove`; re-read that call in the installed copy when the package changes.
49
30
 
50
31
  ## The rendered artifact
51
32
 
@@ -153,35 +153,27 @@ act itself scrolls into view.
153
153
  ### The failure voices
154
154
 
155
155
  Assert the one voice the case means. Never write an assertion that accepts more than one. This table
156
- carries this layer's own voices. Read the statechart voices in [statechart.md](statechart.md) and
157
- the capture voices in [captures.md](captures.md).
158
-
159
- | Condition | The voice thrown | Thrown by |
160
- | ------------------------------------------------------ | ---------------------------------------------------------------------------------------- | ----------------------- |
161
- | No element carries the name | `No interactive element has the accessible name "<name>"` | `resolveRendered` |
162
- | Every match fails a reachability condition | `Interactive target "<name>" is not visible and focus-reachable` | `resolveRendered` |
163
- | Several matches are reachable | `Interactive target "<name>" is ambiguous across <n> elements` | `resolveRendered` |
164
- | Still off-viewport after being scrolled to | `Interactive target "<name>" is unreachable after scrolling` | `resolveAccessible` |
165
- | The region holds no reachable match | `Interactive target "<name>" is not reachable inside "<region>"` | `clickAccessibleWithin` |
166
- | The region holds several reachable matches | `Interactive target "<name>" is ambiguous across <n> elements inside "<region>"` | `clickAccessibleWithin` |
167
- | No native disclosure is reachable under the name | `Native disclosure "<name>" is not visible and focus-reachable` | `clickDisclosure` |
168
- | Several native disclosures carry the name | `Native disclosure "<name>" is ambiguous across <n> elements` | `clickDisclosure` |
169
- | Forward Tab never lands on the target | `Interactive target "<name>" is not reachable through forward Tab traversal: <trail>` | `traverseAccessible` |
170
- | The named region is hidden | `Named region "<name>" is not visible` | `readPerception` |
171
- | Several named regions carry the name | `Named region "<name>" is ambiguous across <n> elements` | `readPerception` |
172
- | The resolved control renders no value | `Interactive target "<name>" does not carry a value` | `readValue` |
173
- | A key sequence reached nothing | `Key sequence "<keys>" was sent with nothing focused` | `pressKeys` |
174
- | The state never arrived or never left | `Condition "<subject>" did not hold within <n>ms (waited <n>ms) (last states: <states>)` | `waitForState` |
175
- | The animation subject is in no document | `Animation subject is not connected` | `waitForAnimations` |
176
- | The paint never stopped moving | `Animation "<subject>" did not settle within <n>ms (waited <n>ms): <animations>` | `waitForAnimations` |
177
- | The sentence never arrived | `Condition "<description>" did not hold within <n>ms (waited <n>ms)` | `waitForText` |
178
- | A host withholds `getItem`, `setItem`, or `removeItem` | `Access is denied for <operation> "<key>"` | `createStorage` |
179
- | A host withholds `length`, `clear`, or `key` | `Access is denied for <operation>` | `createStorage` |
180
- | A write ran past the declared quota | `No room is left for <key>` | `createStorage` |
181
- | A style reading has no computed color | `Computed foreground color is unavailable` | `readContrast` |
182
- | A class census walked nothing | `Class census walked no element` | `readCensus` |
183
- | A contrast control cannot straddle its bar | `Contrast control cannot straddle the bar <bar>` | `buildContrast` |
184
- | A database deletion was blocked | `IndexedDB database "<name>" is blocked by an open connection` | `removeDatabase` |
156
+ carries the voices a journey asserts. Read the statechart voices in [statechart.md](statechart.md),
157
+ the capture voices in [captures.md](captures.md), and every other voice in `guides/test.md` § Voices.
158
+
159
+ | Condition | The voice thrown | Thrown by |
160
+ | ------------------------------------------------------ | ------------------------------------------------------------------------------------- | ----------------------- |
161
+ | No element carries the name | `No interactive element has the accessible name "<name>"` | `resolveRendered` |
162
+ | Every match fails a reachability condition | `Interactive target "<name>" is not visible and focus-reachable` | `resolveRendered` |
163
+ | Several matches are reachable | `Interactive target "<name>" is ambiguous across <n> elements` | `resolveRendered` |
164
+ | Still off-viewport after being scrolled to | `Interactive target "<name>" is unreachable after scrolling` | `resolveAccessible` |
165
+ | The region holds no reachable match | `Interactive target "<name>" is not reachable inside "<region>"` | `clickAccessibleWithin` |
166
+ | The region holds several reachable matches | `Interactive target "<name>" is ambiguous across <n> elements inside "<region>"` | `clickAccessibleWithin` |
167
+ | No native disclosure is reachable under the name | `Native disclosure "<name>" is not visible and focus-reachable` | `clickDisclosure` |
168
+ | Several native disclosures carry the name | `Native disclosure "<name>" is ambiguous across <n> elements` | `clickDisclosure` |
169
+ | Forward Tab never lands on the target | `Interactive target "<name>" is not reachable through forward Tab traversal: <trail>` | `traverseAccessible` |
170
+ | The named region is hidden | `Named region "<name>" is not visible` | `readPerception` |
171
+ | Several named regions carry the name | `Named region "<name>" is ambiguous across <n> elements` | `readPerception` |
172
+ | The resolved control renders no value | `Interactive target "<name>" does not carry a value` | `readValue` |
173
+ | A key sequence reached nothing | `Key sequence "<keys>" was sent with nothing focused` | `pressKeys` |
174
+ | A host withholds `getItem`, `setItem`, or `removeItem` | `Access is denied for <operation> "<key>"` | `createStorage` |
175
+ | A host withholds `length`, `clear`, or `key` | `Access is denied for <operation>` | `createStorage` |
176
+ | A write ran past the declared quota | `No room is left for <key>` | `createStorage` |
185
177
 
186
178
  - Report an absent control and a present-but-unreachable one as different findings: absence names
187
179
  a missing control, and unreachability names the interface gating one that exists.
@@ -195,8 +187,6 @@ the capture voices in [captures.md](captures.md).
195
187
  - Read a refused bound as a test defect rather than a finding. The wait family validates its budget
196
188
  and its interval and names the argument the caller passed, under the subject `Wait` or
197
189
  `Animation`.
198
- - Read the package's own voice table before asserting a message this file does not list. A workspace
199
- that transcribes a voice by memory asserts a sentence the package does not throw.
200
190
 
201
191
  ## Input and traversal
202
192
 
@@ -11,7 +11,7 @@ here, and the control from the builder this layer publishes for it.
11
11
  import type {
12
12
  CaptureVariant,
13
13
  CensusFixture,
14
- CensusReading,
14
+ CensusResult,
15
15
  Color,
16
16
  ContrastFixture,
17
17
  EscapeFixture,
@@ -16,13 +16,19 @@ description: >-
16
16
  - Read the page for each harness that hosts a lane before its first launch: `references/claude.md`, `references/codex.md`, `references/cursor.md`, or `references/t3.md`. A harness without a page carries no writer or runner lane until § Bring up a harness is answered on a page of its own.
17
17
  - Apply `.agents/orchestration.md` for routing, session reuse, consultation, independence, and acceptance.
18
18
 
19
+ ## Scripts
20
+
21
+ Run from the checkout root. The script's opening comment owns its behavior.
22
+
23
+ - `scripts/cases.ts --report FILE.json [--passed NAME ...] [--failed NAME ...]` reads a Vitest `--reporter=json` report and requires every case a `--passed` name matches to have passed and every case a `--failed` name matches to have failed. A name matches a case's full name or its own title exactly; both flags repeat. A name that matches no case is missing, and a failed case no name matches is refused, as is a test file that failed with no failed case (it did not collect, or a hook threw) and a report whose `success` is false while nothing in it failed. It prints one summary line, each difference, and `ok` or `differences=N`. Exit 0 when the report matches, 3 when it does not, 2 when the report cannot be read as a Vitest report, 64 usage.
24
+
19
25
  ## Bound the host
20
26
 
21
27
  The host budget counts every lane on the machine: this session's, each peer session's, and the Orchestrator's own commands.
22
28
 
23
29
  - Set the lane bound in the plan before the first dispatch. Run one process-running lane at a time on the host: tests, checks, builds, browsers, captures, and launchers, the Orchestrator's included. Report to the user before a launch that would start a second. Lanes that run no shell command run beside it.
24
30
  - Count running lanes and owned test processes at each launch.
25
- - Limit terminal launches: chain commands that do not gate each other into one launch, write long output to a file and read it once, never poll with repeated short calls, never retry a run in a loop, and check once for owned leftovers before a launch.
31
+ - Limit terminal launches: chain commands that do not gate each other into one launch (as a plan for `.agents/skills/orkestrel-dispatch/scripts/chain.ts`), write long output to a file and read it once, never poll with repeated short calls, never retry a run in a loop, and check once for owned leftovers before a launch.
26
32
  - Find the cause of an interrupted run before relaunching it.
27
33
  - While a lane that runs shell commands is live, count orphaned console and window processes. Brief a lane that needs no shell to run no command. Kill only a recorded process id, and clear orphans only when none of your lanes is live. Never kill another session's or lane's process; ask the user.
28
34
  - While a timing or live-model measurement runs, start no other test, build, or model work on the host.
@@ -34,12 +40,12 @@ The host budget counts every lane on the machine: this session's, each peer sess
34
40
 
35
41
  ## Assign lanes
36
42
 
37
- | Lane | Responsibility | Write boundary |
38
- | ------------ | ---------------------------------------------------------------- | --------------------------------------------------------------------- |
39
- | Orchestrator | Own the protocol, roster, scope, rulings, holds, and acceptance. | Assigned coordination records and serial integration. |
40
- | Runner | Run requested tests, checks, and builds as the verifier. | Assigned evidence and declared command outputs; never source repairs. |
41
- | Writer | Implement its bounded unit under its assigned role. | Owned files and regions, plus its own log. |
42
- | Reviewer | Independently assess the subject the size gate names. | None; return the verdict to the Orchestrator. |
43
+ | Lane | Responsibility | Write boundary |
44
+ | ------------ | -------------------------------------------------------- | --------------------------------------------------------------------- |
45
+ | Orchestrator | Own the roster, scope, rulings, holds, and acceptance. | Assigned coordination records and serial integration. |
46
+ | Runner | Run requested tests, checks, and builds as the verifier. | Assigned evidence and declared command outputs; never source repairs. |
47
+ | Writer | Implement its bounded unit under its assigned role. | Owned files and regions. |
48
+ | Reviewer | Independently assess the subject the size gate names. | None; return the verdict to the Orchestrator. |
43
49
 
44
50
  - Keep active lanes within the harness limit and § Bound the host. Reserve capacity for the runner; queue work that does not fit.
45
51
  - Assign every editable region to one writer. Name shared regions by their declarations or sections. Serialize units that rewrite the same region.
@@ -48,21 +54,19 @@ The host budget counts every lane on the machine: this session's, each peer sess
48
54
  ## Prepare the round
49
55
 
50
56
  1. Commit the accepted baseline before a writing dispatch.
51
- 2. Write `tmp/units/<round>/coord/protocol.md`: the skill path, baseline, lanes, owned regions, dependencies, acceptance commands, and exclusive resources. Mark each command whose input set must be held while it runs.
52
- 3. Write `coord/roster.md` with each lane's roster fields per `.agents/orchestration.md` § Sessions and consultation. Create `coord/results/` and `coord/runs/`.
53
- 4. Resume a suitable runner or launch one. Require its ready acknowledgment, then let its idle turn end.
54
- 5. Resume or launch writers as capacity permits. Fill each roster row from the actual launch or continuation result, never from an earlier session's pattern, and send each lane the peer addresses it messages.
55
- 6. When adopting a running lane, send the protocol, ownership, log path, and next request number. Require acknowledgment before coordinated work begins.
57
+ 2. Write `tmp/units/<round>/coord/roster.md`: each lane's roster fields per `.agents/orchestration.md` § Sessions and consultation, plus the baseline, owned regions, dependencies, acceptance commands, and exclusive resources. Create `coord/runs/` for journals, errors, and results.
58
+ 3. Resume a suitable runner or launch one, and start it with its first request.
59
+ 4. Resume or launch writers as capacity permits. Fill each roster row from the actual launch or continuation result, never from an earlier session's pattern, and send each lane the peer addresses it messages.
60
+ 5. When a running lane joins the round, put the roster path, its ownership, and its next request number in the first request you send it.
56
61
 
57
62
  ## Exchange requests and results
58
63
 
59
- - Append only to your own `coord/<lane>.md` log: `<lane> | <request or phase> | <kind> | <text>`. Reviewers write no log.
60
64
  - Number requests monotonically per lane across continuations and fixes. Preserve earlier requests and results.
61
- - Send each request through the wake-capable channel in the request shape that closes this section.
62
- - The runner publishes a result by writing it under a temporary name and renaming it to `coord/results/<lane>-<request>.md` after command exit and cleanup, then sends its path and request identity to the requester and the Orchestrator.
65
+ - Send each request through the wake-capable channel in the request shape that closes this section. Name each hold in `holds:` and proceed on send; the named owners stop edits to the held inputs until the result arrives. Nobody acknowledges a request, a hold, or a withdrawn `FINAL`.
66
+ - The runner writes a result to `coord/runs/<lane>-<request>.md` after command exit and cleanup, then sends its path and request identity to the requester and the Orchestrator.
63
67
  - Wait for the harness's completion or message notice; run no watcher agent and no file-poll loop. When the notice is missing and the result is needed, read that request's durable result or task status once, reconcile the request identity, and suspend an unresolved delivery rather than launching duplicate work.
64
68
  - Escalate per `.agents/orchestration.md` § Deviation protocol. Continue independent work. Share cross-lane facts directly; only the Orchestrator changes scope or rules on acceptance.
65
- - End an idle runner turn after acknowledging readiness or publishing a result, so queued requests reach it. Never hold the runner in a wait for requests.
69
+ - End the runner's turn after it sends a result, so queued requests reach it. Never hold the runner in a wait for requests.
66
70
  - After compaction or a harness restart, reconcile the roster against the live session and process state. When continuation is unsupported or unavailable, dispatch a successor brief that carries the prior evidence and unresolved work.
67
71
 
68
72
  Use this request shape:
@@ -80,32 +84,32 @@ expect: <red or green, named cases, required artifact>
80
84
 
81
85
  ## Implement in phases
82
86
 
83
- - Log the applicable phases: types, failing proof, source, and documentation. Request the corresponding checks from the runner.
87
+ - At each applicable phase (types, failing proof, source, and documentation), request the corresponding checks from the runner.
84
88
  - Read a shared region immediately before each small, syntactically complete patch. On a context mismatch, reread and reapply only the owned hunk.
85
89
  - Keep read-only shell searches within § Bound the host. Send every test, check, lint, format, and build request to the runner.
86
90
  - Run no formatter. Apply the exact formatting hunk the Orchestrator supplies, then request a read-only format check.
87
- - Before a temporary mutation, obtain the runner's hold on conflicting commands and each affected writer's hold on edits. Mutate only after their acknowledgments. Restore the exact input, verify the restoration, and release the holds through the runner.
91
+ - Before a temporary mutation, send the runner a request whose `holds:` names the conflicting commands and each affected writer, and mutate after the command then running returns its result. Restore the exact input, verify the restoration, and release the holds in the next request.
88
92
  - When the unit's required checks pass, send `FINAL <lane>` with source identity and evidence, write the report, and end the turn. Preserve the session for suitable follow-up work.
89
93
 
90
94
  ## Run evidence commands
91
95
 
92
96
  - Before a command, verify its input holds and exclusive resources. Hold all writers when the command reads the whole tree; otherwise hold every owner in its input closure. Do not infer that closure from the requesting writer's files alone.
93
97
  - When a conflicting process occupies a declared resource, record its owner, process id, command, and a bounded wait based on the expected work. If it remains after that wait, suspend the request for an Orchestrator ruling. Never terminate another lane's or repository's process.
94
- - Launch through `node .agents/skills/orkestrel-dispatch/scripts/launch.ts` with a cap grounded in prior runs, separate journal and error paths under `coord/runs/`, and the request identity in each filename. Follow the `orkestrel-dispatch` skill's reference Long-running commands for ownership, process tracking, and cleanup.
98
+ - Launch through `node .agents/skills/orkestrel-dispatch/scripts/launch.ts` with a cap grounded in prior runs, journal and error paths under `coord/runs/` carrying the request identity in each filename. Follow the `orkestrel-dispatch` skill's reference Long-running commands for ownership, process tracking, and cleanup.
95
99
  - State in each long command's request which line is its terminal record; that line ends the wait.
96
100
  - When the shell yields before the command exits, keep its output in the assigned file and resume its tracked session per the harness page until the terminal record arrives. Start nothing else meanwhile, and never replace the command with a second launch. Confirm owned descendants have exited before publishing completion. Escalate incomplete cleanup before releasing files or starting another command.
97
- - Run the commands the accepted unit and the size gate require, narrowest first, and add no standing root, guide, or entry check beyond the request. Preserve receipts and rerun checks per `.agents/orchestration.md` § Parallelism.
98
- - Stop on the first unexpected failure. Return the complete diagnostic and the owning file, and classify the failure as an assertion failure, an invocation error, a reporting failure, a cap, or an interruption. Preserve every receipt obtained before the stop.
101
+ - Run the commands the accepted unit and the size gate require, narrowest first, and add no standing root, guide, or entry check beyond the request. Preserve receipts and rerun checks per `.agents/orchestration.md` § Pace.
102
+ - Stop on the first unexpected failure. Return the complete diagnostic and the owning file, and classify the failure as an assertion failure, an invocation error, a reporting failure, a cap, or an interruption. Preserve every receipt obtained before the stop. Check an `expect:` that names cases against the command's `--reporter=json` report with `scripts/cases.ts`.
99
103
  - Record the command's input identity and expected outputs before launch. When an input changes during the run, report that result as invalid and retain each result whose input set stayed stable.
100
- - After every writer's current `FINAL`, the integrated review, and the acknowledged write holds, run the Orchestrator's closing acceptance request under a unique gate number. Publish `coord/results/closing-<gate>.md`, reply with that identity, and end the turn.
104
+ - After every writer's current `FINAL` and the integrated review, run the Orchestrator's closing acceptance request under a unique gate number. Write `coord/runs/closing-<gate>.md`, reply with that identity, and end the turn.
101
105
 
102
106
  ## Integrate and close
103
107
 
104
108
  - Before ruling on an escalation, inspect its cited evidence. Bound the ruling to the changed claim and affected owners.
105
109
  - When the format check reports only a filename, inspect the difference and send the writer the exact hunk.
106
110
  - Run the size gate's independent review on a pinned subject; a unit review can overlap unrelated writing only while its whole subject stays unchanged. Use unit evidence for the integrated review, then run the closing acceptance gate in the order `.agents/orchestration.md` § Campaign fixes: Audit, then Verify.
107
- - Before reopening a writer, invalidate that lane's `FINAL` with the runner and require acknowledgment. Keep every other valid `FINAL` result. Release the reopened writer only when no active gate reads its inputs.
108
- - Before a closing request, obtain affected write-hold acknowledgments and hold your own source edits. Keep them until the matching complete result arrives. After a fix, request only the checks invalidated by that fix plus any unmet acceptance requirement.
111
+ - Before reopening a writer, tell the runner in the next request that the lane's `FINAL` is withdrawn. Keep every other valid `FINAL` result. Release the reopened writer only when no active gate reads its inputs.
112
+ - Name every affected writer in the closing request's `holds:` and hold your own source edits until the matching complete result arrives. After a fix, request only the checks invalidated by that fix plus any unmet acceptance requirement.
109
113
  - Commit after the required gates and review pass. When shared hunks form one integration, commit the batch and identify its units and fixes.
110
114
 
111
115
  ## Share an execution lane between sessions