@orkestrel/scaffold 0.0.44 → 0.0.46

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 (69) hide show
  1. package/README.md +10 -10
  2. package/dist/bin/main.js +31 -31
  3. package/dist/bin/main.js.map +1 -1
  4. package/dist/host/AGENTS.md +7 -2
  5. package/dist/host/agents/orchestration.md +232 -56
  6. package/dist/host/agents/skills/enterprise-bootstrap/SKILL.md +7 -7
  7. package/dist/host/agents/skills/enterprise-bootstrap/references/bootstrap-reference.md +11 -9
  8. package/dist/host/agents/skills/enterprise-bootstrap/references/components.md +3 -3
  9. package/dist/host/agents/skills/enterprise-bootstrap/references/frontend-design.md +3 -3
  10. package/dist/host/agents/skills/enterprise-bootstrap/references/utilities.md +1 -1
  11. package/dist/host/agents/skills/orkestrel-align-packages/SKILL.md +1 -1
  12. package/dist/host/agents/skills/orkestrel-build-application/SKILL.md +2 -2
  13. package/dist/host/agents/skills/orkestrel-debrief/SKILL.md +1 -1
  14. package/dist/host/agents/skills/orkestrel-debrief/references/field-testing.md +2 -2
  15. package/dist/host/agents/skills/orkestrel-debrief/references/instruction-audit.md +8 -8
  16. package/dist/host/agents/skills/orkestrel-falsify/SKILL.md +16 -14
  17. package/dist/host/agents/skills/orkestrel-falsify/references/brief.md +3 -3
  18. package/dist/host/agents/skills/orkestrel-falsify/references/reconcile.md +14 -14
  19. package/dist/host/agents/skills/orkestrel-harden-package/SKILL.md +1 -1
  20. package/dist/host/agents/skills/orkestrel-human-journey/SKILL.md +3 -3
  21. package/dist/host/agents/skills/orkestrel-human-journey/references/captures.md +3 -3
  22. package/dist/host/agents/skills/orkestrel-human-journey/references/layer.md +3 -3
  23. package/dist/host/agents/skills/orkestrel-polish-surface/SKILL.md +3 -3
  24. package/dist/host/claude/agents/analyst.md +2 -2
  25. package/dist/host/claude/agents/checker.md +2 -2
  26. package/dist/host/claude/agents/codex.md +5 -5
  27. package/dist/host/claude/agents/orkestrel.md +10 -8
  28. package/dist/host/claude/agents/planner.md +1 -1
  29. package/dist/host/claude/agents/researcher.md +2 -2
  30. package/dist/host/claude/agents/reviewer.md +1 -1
  31. package/dist/host/claude/agents/scout.md +2 -2
  32. package/dist/host/claude/agents/sol.md +3 -3
  33. package/dist/host/claude/agents/verifier.md +8 -0
  34. package/dist/host/claude/rules/application.md +7 -7
  35. package/dist/host/claude/rules/architecture.md +6 -6
  36. package/dist/host/claude/rules/documentation.md +1 -0
  37. package/dist/host/claude/rules/patterns.md +3 -3
  38. package/dist/host/claude/rules/quality.md +3 -3
  39. package/dist/host/claude/rules/tests.md +9 -2
  40. package/dist/host/claude/rules/workspace.md +7 -7
  41. package/dist/host/claude/rules/writing.md +12 -2
  42. package/dist/host/codex/agents/planner.toml +1 -1
  43. package/dist/host/codex/config.toml +4 -0
  44. package/dist/host/configs/helpers.ts +21 -1
  45. package/dist/host/cursor/mcp.json +4 -0
  46. package/dist/host/cursor/rules/orchestration.mdc +1 -1
  47. package/dist/host/dotfiles/gitignore +4 -1
  48. package/dist/host/dotfiles/mcp.json +4 -0
  49. package/dist/host/guides/scaffold.md +134 -119
  50. package/dist/host/scripts/codex.sh +0 -0
  51. package/dist/host/scripts/cursor.sh +0 -0
  52. package/dist/host/scripts/deps.sh +0 -0
  53. package/dist/host/scripts/ollama.sh +0 -0
  54. package/dist/host/tests/config.test.ts +40 -1
  55. package/dist/host/tests/policy.test.ts +2 -2
  56. package/dist/host/tests/setupPolicy.ts +8 -5
  57. package/dist/src/core/index.cjs +144 -149
  58. package/dist/src/core/index.cjs.map +1 -1
  59. package/dist/src/core/index.d.cts +1624 -1643
  60. package/dist/src/core/index.d.ts +1624 -1643
  61. package/dist/src/core/index.js +145 -149
  62. package/dist/src/core/index.js.map +1 -1
  63. package/dist/src/server/index.cjs +82 -97
  64. package/dist/src/server/index.cjs.map +1 -1
  65. package/dist/src/server/index.d.cts +1844 -1871
  66. package/dist/src/server/index.d.ts +1844 -1871
  67. package/dist/src/server/index.js +83 -96
  68. package/dist/src/server/index.js.map +1 -1
  69. package/package.json +4 -3
@@ -41,7 +41,7 @@ so network-controlled descriptions never enter agent instruction context.
41
41
  | `@orkestrel/brief` | `0.0.3` | L4 | `@orkestrel/contract` `^0.0.12`, `@orkestrel/emitter` `^0.0.7`, `@orkestrel/interpret` `^0.0.10`, `@orkestrel/reason` `^0.0.7` |
42
42
  | `@orkestrel/browser` | `0.0.11` | L3 | `@orkestrel/contract` `^0.0.12`, `@orkestrel/emitter` `^0.0.7`, `@orkestrel/html` `^0.0.4`, `@orkestrel/websocket` `^0.0.9` |
43
43
  | `@orkestrel/budget` | `0.0.7` | L1 | `@orkestrel/contract` `^0.0.12` |
44
- | `@orkestrel/console` | `0.0.8` | L2 | `@orkestrel/contract` `^0.0.12`, `@orkestrel/emitter` `^0.0.7` |
44
+ | `@orkestrel/console` | `0.0.9` | L2 | `@orkestrel/contract` `^0.0.12`, `@orkestrel/emitter` `^0.0.7` |
45
45
  | `@orkestrel/contract` | `0.0.12` | L0 | |
46
46
  | `@orkestrel/csv` | `0.0.4` | L1 | `@orkestrel/contract` `^0.0.12` |
47
47
  | `@orkestrel/database` | `0.0.11` | L2 | `@orkestrel/contract` `^0.0.12`, `@orkestrel/emitter` `^0.0.7`, `@orkestrel/indexeddb` `^0.0.8`, `@orkestrel/sqlite` `^0.0.8` |
@@ -52,12 +52,14 @@ so network-controlled descriptions never enter agent instruction context.
52
52
  | `@orkestrel/indexeddb` | `0.0.8` | L1 | `@orkestrel/contract` `^0.0.12` |
53
53
  | `@orkestrel/interpret` | `0.0.10` | L3 | `@orkestrel/contract` `^0.0.12`, `@orkestrel/emitter` `^0.0.7`, `@orkestrel/reason` `^0.0.7`, `@orkestrel/template` `^0.0.4` |
54
54
  | `@orkestrel/markdown` | `0.0.9` | L2 | `@orkestrel/contract` `^0.0.12`, `@orkestrel/html` `^0.0.4` |
55
- | `@orkestrel/mcp` | `0.0.18` | L3 | `@orkestrel/contract` `^0.0.12`, `@orkestrel/emitter` `^0.0.7`, `@orkestrel/sse` `^0.0.5`, `@orkestrel/tool` `^0.0.11`, `@orkestrel/websocket` `^0.0.9` |
55
+ | `@orkestrel/mcp` | `0.0.20` | L3 | `@orkestrel/contract` `^0.0.12`, `@orkestrel/emitter` `^0.0.7`, `@orkestrel/process` `^0.0.4`, `@orkestrel/sse` `^0.0.5`, `@orkestrel/tool` `^0.0.11`, `@orkestrel/websocket` `^0.0.9` |
56
56
  | `@orkestrel/middleware` | `0.0.16` | L2 | `@orkestrel/abort` `^0.0.7`, `@orkestrel/budget` `^0.0.7`, `@orkestrel/contract` `^0.0.12`, `@orkestrel/timeout` `^0.0.7` |
57
57
  | `@orkestrel/msg` | `0.0.7` | L0 | |
58
58
  | `@orkestrel/ndjson` | `0.0.7` | L1 | `@orkestrel/contract` `^0.0.12` |
59
59
  | `@orkestrel/ollama` | `0.0.10` | L6 | `@orkestrel/agent` `^0.0.16`, `@orkestrel/budget` `^0.0.7`, `@orkestrel/contract` `^0.0.12`, `@orkestrel/ndjson` `^0.0.7`, `@orkestrel/timeout` `^0.0.7`, `@orkestrel/tool` `^0.0.11` |
60
60
  | `@orkestrel/pool` | `0.0.8` | L2 | `@orkestrel/emitter` `^0.0.7` |
61
+ | `@orkestrel/probe` | `0.0.1` | L4 | `@orkestrel/contract` `^0.0.12`, `@orkestrel/emitter` `^0.0.7`, `@orkestrel/mcp` `^0.0.20`, `@orkestrel/queue` `^0.0.9`, `@orkestrel/timeout` `^0.0.7`, `@orkestrel/tool` `^0.0.11` |
62
+ | `@orkestrel/process` | `0.0.4` | L2 | `@orkestrel/contract` `^0.0.12`, `@orkestrel/emitter` `^0.0.7` |
61
63
  | `@orkestrel/program` | `0.0.9` | L4 | `@orkestrel/contract` `^0.0.12`, `@orkestrel/emitter` `^0.0.7`, `@orkestrel/qualifier` `^0.0.10`, `@orkestrel/rater` `^0.0.11`, `@orkestrel/reason` `^0.0.7` |
62
64
  | `@orkestrel/qualifier` | `0.0.10` | L3 | `@orkestrel/contract` `^0.0.12`, `@orkestrel/emitter` `^0.0.7`, `@orkestrel/reason` `^0.0.7` |
63
65
  | `@orkestrel/queue` | `0.0.9` | L3 | `@orkestrel/abort` `^0.0.7`, `@orkestrel/contract` `^0.0.12`, `@orkestrel/database` `^0.0.10`, `@orkestrel/emitter` `^0.0.7`, `@orkestrel/timeout` `^0.0.7` |
@@ -65,8 +67,8 @@ so network-controlled descriptions never enter agent instruction context.
65
67
  | `@orkestrel/reason` | `0.0.7` | L2 | `@orkestrel/contract` `^0.0.12`, `@orkestrel/emitter` `^0.0.7` |
66
68
  | `@orkestrel/relation` | `0.0.9` | L3 | `@orkestrel/contract` `^0.0.12`, `@orkestrel/database` `^0.0.10`, `@orkestrel/emitter` `^0.0.7` |
67
69
  | `@orkestrel/router` | `0.0.10` | L2 | `@orkestrel/abort` `^0.0.7`, `@orkestrel/contract` `^0.0.12`, `@orkestrel/emitter` `^0.0.7` |
68
- | `@orkestrel/scaffold` | `0.0.42` | L3 | `@orkestrel/console` `^0.0.8`, `@orkestrel/contract` `^0.0.12`, `@orkestrel/emitter` `^0.0.7`, `@orkestrel/markdown` `^0.0.9`, `@orkestrel/template` `^0.0.4` |
69
- | `@orkestrel/sea` | `0.0.8` | L2 | `@orkestrel/contract` `^0.0.12`, `@orkestrel/emitter` `^0.0.7` |
70
+ | `@orkestrel/scaffold` | `0.0.45` | L3 | `@orkestrel/console` `^0.0.9`, `@orkestrel/contract` `^0.0.12`, `@orkestrel/emitter` `^0.0.7`, `@orkestrel/markdown` `^0.0.9`, `@orkestrel/process` `^0.0.4`, `@orkestrel/template` `^0.0.4` |
71
+ | `@orkestrel/sea` | `0.0.9` | L3 | `@orkestrel/contract` `^0.0.12`, `@orkestrel/emitter` `^0.0.7`, `@orkestrel/process` `^0.0.3` |
70
72
  | `@orkestrel/server` | `0.0.14` | L3 | `@orkestrel/abort` `^0.0.7`, `@orkestrel/contract` `^0.0.12`, `@orkestrel/emitter` `^0.0.7`, `@orkestrel/router` `^0.0.10`, `@orkestrel/timeout` `^0.0.7` |
71
73
  | `@orkestrel/sqlite` | `0.0.8` | L1 | `@orkestrel/contract` `^0.0.12` |
72
74
  | `@orkestrel/sse` | `0.0.5` | L0 | |
@@ -110,12 +112,12 @@ account rather than on the dependency's. A superfluous diff obliges nothing.
110
112
  The `Layer` column above is the publish round, derived from the runtime edges in the same
111
113
  row. `L0` depends on nothing else in the fleet and publishes first; each later layer
112
114
  publishes only after every layer before it is on the registry. A row with no layer sits in
113
- a cycle and cannot be placed in a round at all. Two packages in one layer are independent
115
+ a cycle and cannot be placed in a round at all. Packages in one layer are independent
114
116
  of each other and may publish in any order within it.
115
117
 
116
- Report a disagreeing pin as a defect, never as drift to tidy later. When two packages in
117
- one install graph pin different versions of a third, npm installs both copies, and the
118
- compiler reads the two copies as two distinct types. The symptom is a type error naming
118
+ Report a disagreeing pin as a defect, never as drift to tidy later. When packages in
119
+ one install graph pin different versions of a dependency, npm installs both copies, and the
120
+ compiler reads those copies as distinct types. The symptom is a type error naming
119
121
  one type as not assignable to itself. `npm ls @orkestrel/<name>` is the evidence: one line
120
122
  is sound, and nesting is the finding.
121
123
 
@@ -25,7 +25,7 @@ Return only:
25
25
  - `Units`: bounded work, each naming its role AND engine so the routing ledger is
26
26
  derivable, with ownership, dependencies, and acceptance criteria.
27
27
  - `Tensions`: the choices your lane made on judgment, named for the other lane to
28
- challenge — or, when you hold both lanes, for the Orchestrator to rule.
28
+ challenge — or, when you hold every lane, for the Orchestrator to rule.
29
29
  - `Risks`: design-fit risks and the evidence needed to settle them.
30
30
 
31
31
  Your proposal is input to the Orchestrator, never the final decision.
@@ -26,8 +26,8 @@ you never design, implement, or accept. You are an Executor: spawn nothing.
26
26
  - Return the distillate only: findings with citations, contradictions surfaced,
27
27
  gaps named as gaps. No raw dumps, no process diary, and nothing applied.
28
28
 
29
- Scope note: research belongs to Grok first. You are the last step of the
30
- tedious-work ladder Grok, then Luna on Codex, then you — so a dispatch reaching
29
+ Scope note: research belongs to Grok first. You sit at the end of the
30
+ tedious-work ladder, after Grok and Luna on Codex, so a dispatch reaching
31
31
  you should already record why the benches above it were unavailable. Heavy
32
32
  cross-file reading and repository-scale absorption are never yours: if a dispatch
33
33
  exceeds a bounded primary-source question, say so instead of absorbing it.
@@ -73,7 +73,7 @@ rather than adjudicating it.
73
73
  - Each required change carries file:line, what is wrong, why it matters, and what
74
74
  right looks like — actionable enough to re-dispatch verbatim.
75
75
  - **Referrals** — specifically evidenced questions outside your lane, addressed to
76
- the other lane when it is running and to the Orchestrator when you hold both, with
76
+ the other lane when it is running and to the Orchestrator when you hold every lane, with
77
77
  no verdict from you.
78
78
 
79
79
  You are read-only: you never edit. Return only the verdict, never your process.
@@ -16,8 +16,8 @@ Executor: spawn nothing.
16
16
 
17
17
  - Read **AGENTS.md** first; the repository model and rule map orient every
18
18
  answer. This charter restates nothing they own.
19
- - Reconnaissance belongs to Grok first. You are the last step of the tedious-work
20
- ladder Grok, then Luna on Codex, then you — so a dispatch reaching you should
19
+ - Reconnaissance belongs to Grok first. You sit at the end of the tedious-work
20
+ ladder, after Grok and Luna on Codex, so a dispatch reaching you should
21
21
  already record why the benches above it were unavailable.
22
22
  - Locate, do not absorb: read excerpts sufficient to identify a seam, an owner,
23
23
  or a shape. Deep reading and synthesis belong to the `grok` bench, and quality
@@ -17,10 +17,10 @@ Read `.agents/orchestration.md` first.
17
17
 
18
18
  `.claude/agents/codex.md` owns the Sol transport contract in full — work class to transport, the
19
19
  exact `codex exec` form, the journal and session-id discipline, the recovery ladder, and the
20
- Windows notes. **Read it and follow it.** It is not restated here; two copies of a transport
21
- contract drift, and the one you are not reading is the one that is right.
20
+ Windows notes. **Read it and follow it.** It is not restated here; a restated transport
21
+ contract drifts, and the copy you are not reading is the one that is right.
22
22
 
23
- This role pins the one thing that file leaves to the dispatch: **the route is `implementer`, and
23
+ This role pins what that file leaves to the dispatch: **the route is `implementer`, and
24
24
  its sandbox is `workspace-write`.** A unit that needs no write is a misrouted unit — stop and
25
25
  report, do not switch routes.
26
26
 
@@ -36,3 +36,11 @@ Executor: run the gates yourself, spawn nothing.
36
36
 
37
37
  You never edit files and never "quick-fix" a failure — you report it. Return only
38
38
  the gate report, never your process.
39
+
40
+ ## Never discard a working-tree change
41
+
42
+ - Never run `git checkout`, `git restore`, `git stash`, `git reset`, or `git clean`. Each discards
43
+ a working-tree change silently.
44
+ - Where a dispatch has you plant a line to prove a gate can fail, remove exactly the line you added.
45
+ Never revert the file it sits in.
46
+ - Read a dirty `git status` as the expected state.
@@ -27,13 +27,13 @@ paths:
27
27
  `node:*` external.
28
28
  - Browser and server integrate across a contract and transport boundary. Neither
29
29
  environment imports the other's implementation.
30
- - Four tools enforce that boundary, and none of them is replaceable by a custom
31
- parser or source-language analyzer: `.oxlintrc.json` `no-restricted-imports`
32
- enforces declared package, alias, and conventional relative import direction;
33
- scoped TypeScript configurations remove Node and DOM globals from the wrong
34
- environment; Vite's real browser and server builds resolve Vue, assets, CSS,
35
- workers, and runtime module graphs; and generated-consumer tests exercise all
36
- three.
30
+ - The project toolchain enforces that boundary, and none of its tools is
31
+ replaceable by a custom parser or source-language analyzer: `.oxlintrc.json`
32
+ `no-restricted-imports` enforces declared package, alias, and conventional
33
+ relative import direction; scoped TypeScript configurations remove Node and
34
+ DOM globals from the wrong environment; Vite's real browser and server builds
35
+ resolve Vue, assets, CSS, workers, and runtime module graphs; and
36
+ generated-consumer tests exercise those real configurations.
37
37
  - Generated consumers must pass lint, scoped typechecking, production builds, and
38
38
  real integration tests.
39
39
  - Scoped checks include `.ts`, `.tsx`, `.mts`, and `.cts`. Vue SFCs and CSS
@@ -58,13 +58,13 @@ Use only the centralized files an environment needs.
58
58
  - Module-scope constants live only in `constants.ts`, use UPPER_SNAKE_CASE, and freeze object/array data with `Object.freeze`.
59
59
  - A camelCase namespace containing functions is helper behavior, not constant data; place it in `helpers.ts`.
60
60
  - `helpers.ts` is exported reusable infrastructure. A reusable regex, parser, header flattener, signer, or similar fragment has one implementation used by source, tests, and fixtures.
61
- - A would-be helper has two outcomes:
61
+ - A would-be helper has these outcomes:
62
62
  - trivial and genuinely single-use → fold into its caller;
63
63
  - non-trivial or reusable → extract, export, unit-test, and route every duplicate through it.
64
64
  - `factories.ts`, `compilers.ts`, and `parsers.ts` are centralized files, not hiding places. Factory glue extracts to `helpers.ts`; pure compiler/parser recursion remains exported in its own kind file.
65
65
  - Every exported function in `parsers.ts` is named `parse*`. Every exported function in
66
66
  `factories.ts` is named `create*`.
67
- - The two name forms are one-directional. A name does not place a function: `createWriteDirectory`
67
+ - Those name forms are one-directional. A name does not place a function: `createWriteDirectory`
68
68
  creates a directory rather than an entity and `isVacant` is a predicate rather than a `Guard<T>`,
69
69
  so both stay in `helpers.ts`. Placement follows what the function is; the name form follows
70
70
  placement.
@@ -85,7 +85,7 @@ Use only the centralized files an environment needs.
85
85
  graph: they import types, constants, errors, and each other, and they import no implementation
86
86
  class. Every file that constructs or drives a class — `cloners.ts`, `compilers.ts`, `factories.ts`,
87
87
  `shapers.ts` — sits above them, consumes them, and is never consumed by them. One cycle between
88
- the two leaves is the shape this produces and is acceptable; an edge running downward from a
88
+ the leaves is the shape this produces and is acceptable; an edge running downward from a
89
89
  class-importing file into the leaf pair is not.
90
90
  - `templates.ts` and `contracts.ts` hold data only — shipped template definitions and compiled
91
91
  contracts. A function that builds either belongs in the kind file for what it builds.
@@ -110,7 +110,7 @@ kind. It reads declaration syntax and file name, never meaning.
110
110
  returns, so `Object.freeze([…])` and any other call initializer are one syntax to it. The freeze
111
111
  obligation in the kind-purity rules above binds regardless; only the bare literal is mechanical.
112
112
  - It does not tell one function kind from another. Every centralized file that permits functions
113
- reads the same to it apart from the two name forms above: `cloners.ts`, `combinators.ts`,
113
+ reads the same to it apart from the `parse*` and `create*` name forms: `cloners.ts`, `combinators.ts`,
114
114
  `compilers.ts`, `errors.ts`, `factories.ts`, `handlers.ts`, `helpers.ts`, `inferers.ts`,
115
115
  `middlewares.ts`, `parsers.ts`, `relations.ts`, `schemas.ts`, `seeders.ts`, `shapers.ts`, and
116
116
  `validators.ts`. That list is exhaustive, a new function kind joins it, and no later version of
@@ -150,7 +150,7 @@ A wrapper survives only when it adds a real boundary, invariant, composition, tr
150
150
  - The only in-body function expressions allowed are an anonymous callback passed directly as an argument and an anonymous function returned directly as the result (the factory/combinator pattern).
151
151
  - Instance-bound work that reaches state or sibling methods is a method, not a free function.
152
152
 
153
- Separate three roles:
153
+ Separate these roles:
154
154
 
155
155
  1. **Public method:** implements the interface and genuinely composes behavior; never forwards 1:1 to one helper.
156
156
  2. **`#` private method:** stateful/instance-bound orchestration or the class's defining recursive/compositional algorithm.
@@ -225,7 +225,7 @@ Choose the access shape:
225
225
  - **Point access:** `get`, `set`, `delete`.
226
226
  - **Bulk restore:** `save`, `load`, `remove`, `clear`.
227
227
 
228
- Both obey:
228
+ Every shape obeys:
229
229
 
230
230
  - The stored value carries its own id; do not pass a separate id to `set`/`save`.
231
231
  - Every primitive is async and returns a `Promise`.
@@ -34,6 +34,7 @@ Documentation is an enforced contract, not explanatory decoration. The Writing r
34
34
  - A parity failure identifies drift; never suppress or weaken the test.
35
35
  - A vendored dependency guide is a mirror. Its relative links address the upstream tree and resolve to nothing here, so they are outside local-link parity. Refresh a mirror rather than rewriting it: a rewritten copy is a translation, and no comparison against the fetched bytes can check it.
36
36
  - Falsify a prose claim the way you falsify a code claim. The parity test proves a name exists, never that a sentence about behavior is true, so run the example and read what it returns. A `// false` beside a call that returns `true` is a defect of the same kind as a wrong return value, and it reaches every consumer who installs the package. That proof has a home: `tests/guides.test.ts` executes the flagship fences, per `.claude/rules/tests.md`. An ordered behaviour with no gate is not a gate.
37
+ Asserting that the sentence appears is not asserting that it is true. `expect(text).toContain('a spawn fault reports null')` passes unchanged when the code starts returning something else, so it guards the documentation's presence and nothing about the behaviour. Where a prose claim about behaviour sits under no fence, add the executed assertion that would break if the claim went false, and keep the substring check only as a presence guard beside it. A row whose close condition names a behaviour does not close on a substring.
37
38
  - Re-read the prose last, against what actually shipped. Where a change chose to document a limit rather than close it, the sentence was often drafted for the option that lost, or written more confidently than the code earns. Code rulings survive review because a test can break them; prose rulings survive because nothing tries.
38
39
 
39
40
  For behavioral interfaces/classes:
@@ -51,7 +51,7 @@ Examples: `timeout(id)`/`timeouts()`, `agent(id)`/`agents()`.
51
51
 
52
52
  ### Batch operations
53
53
 
54
- One single-word verb carries three overloads:
54
+ One single-word verb carries these overloads:
55
55
 
56
56
  ```ts
57
57
  method(): void
@@ -108,7 +108,7 @@ Choose one event model per environment. `Emitter<TMap>` remains the default outs
108
108
 
109
109
  ## Validation and contracts
110
110
 
111
- Use four orthogonal contract mechanisms:
111
+ Use these orthogonal contract mechanisms:
112
112
 
113
113
  | Surface | Contract |
114
114
  | ---------------- | ----------------------------------------------------------------------------- |
@@ -118,7 +118,7 @@ Use four orthogonal contract mechanisms:
118
118
  | Shape DSL | One `ContractShape` compiled into schema, guard, parser, and seeded generator |
119
119
 
120
120
  - Use plain guards/parsers for small contracts.
121
- - Use the shape DSL only when four-way validation/serialization/generation parity earns its complexity.
121
+ - Use the shape DSL only when validation, serialization, and generation parity earns its complexity.
122
122
  - When `@orkestrel/contract` is declared, use its exact installed guards, parsers, combinators, outcomes, `attempt` boundary, and shape DSL wherever their semantics match. Do not maintain a local copy of those primitives.
123
123
  - A guard never throws for adversarial input, cycles, deep nesting, or hostile prototypes; return false.
124
124
  - Recursive guards track ancestors and cap depth.
@@ -42,7 +42,7 @@ A question a probe can settle is settled by the probe, whether or not anyone has
42
42
  - Do not read a result into a tool's failure to find your probe. "No tests found", an empty match, a skipped file, a runner that resolved nothing — these report on the harness, not the subject. Confirm the probe was collected and executed first.
43
43
  - Prefer an observation over a derivation, including your own. When a measurement and an argument disagree, the argument is wrong until the measurement is shown to be broken.
44
44
  - Diagnose from the artifact the work produces — the file, the count, the exit code, the timestamp on what changed — never from a wrapper or a proxy signal that merely correlates with progress. Read a gate bare: a pipeline stage after it (`| tail`, `| grep`) reports the stage's exit status and hides the gate's failing lines.
45
- - Verify a comment or an agent's report against the call sites before relying on it. A code comment is not evidence. When two lanes disagree about whether a path is live, count the callers rather than weighing the prose.
45
+ - Verify a comment or an agent's report against the call sites before relying on it. A code comment is not evidence. When lanes disagree about whether a path is live, count the callers rather than weighing the prose.
46
46
  - What a round proves is what it ran. A conclusion carried from one door to another is a hypothesis at the second door. Re-run it there.
47
47
 
48
48
  ## Falsification
@@ -82,7 +82,7 @@ A review that reads a diff finds what the diff shows. A review that tries to bre
82
82
  - Document the obligation instead when a defect is reachable only through a hypothetical foreign implementation of a contract this package publishes. State it on the interface that owns it and prove the documentation. Do not build coordination machinery against a requirement nobody wrote down. Attacks are unlimited; reachable ones are not, and only the reachable set is a work list.
83
83
  - **Three rounds at one seam is the budget.** Repeated rounds against one seam are evidence about the design, not evidence of diligence. At the third round the next unit is a ruling — on the threat model, the mechanism, or the boundary — taken with the same adversarial pass a design gets, not a fourth repair.
84
84
  - Write the round count down in the capability/defect matrix row that owns the seam, when the seam opens, so it is a fact rather than a feeling. A seam that has consumed more rounds than the rest of the matrix combined has already answered the question.
85
- - State the ruling that ends a seam as three things: the invariant the code will obey, the constraint bounding it against over-correction, and the interface where a consumer meets the obligation. A ruling that names only the defect it replaces produces the opposite defect next round.
85
+ - State the ruling that ends a seam as the invariant the code will obey, the constraint bounding it against over-correction, and the interface where a consumer meets the obligation. A ruling that names only the defect it replaces produces the opposite defect next round.
86
86
  - Give every behavioural audit the means to run its attacks. An auditor that cannot execute cannot falsify a behavioural claim: it returns derivations, and a derivation reads exactly like a verdict while being a different thing — it will confirm a claim one probe would break. Treat a report with no executed evidence as a review of the source, and label it as such.
87
87
 
88
88
  ## Ecosystem reuse
@@ -106,7 +106,7 @@ The root laws on inspecting declared `@orkestrel/*` capabilities, reusing a matc
106
106
 
107
107
  ## Completion
108
108
 
109
- The root completion law — finish every in-scope capability now, leave no TODO, deferral, or hidden follow-up, and run the applicable repository skill for comprehensive work — binds here without restatement. This file adds three obligations:
109
+ The root completion law — finish every in-scope capability now, leave no TODO, deferral, or hidden follow-up, and run the applicable repository skill for comprehensive work — binds here without restatement. This file adds these obligations:
110
110
 
111
111
  - Perform a final centralization, wrapper, test-helper, and text-integrity sweep after implementation and before gates.
112
112
  - Produce local quality gates and relevant output inspection as required evidence.
@@ -93,7 +93,7 @@ its own:
93
93
 
94
94
  A probe is a throwaway instrument that settles one question. It is not a test and never ships.
95
95
 
96
- Two kinds, split by which tool has to see the probe:
96
+ The kinds split by which tool has to see the probe:
97
97
 
98
98
  - A **type probe** is read by `tsc`, whose scoped project includes only its own environment, so it
99
99
  lives in the source tree beside what it measures. Delete it before the unit returns; a leaked one
@@ -106,7 +106,7 @@ Run a probe before relying on an unverified belief about behaviour: what a funct
106
106
  configuration resolves to, whether a path is reached at all. Prefer a probe to an argument whenever
107
107
  the probe is cheap.
108
108
 
109
- Three rules bind every probe:
109
+ These rules bind every probe:
110
110
 
111
111
  - **Prove the instrument can fail before trusting that it passed.** Pair it with a control drawn
112
112
  from outside the population it covers.
@@ -194,6 +194,13 @@ Import `waitForDelay` from `@orkestrel/test`; never repeat an inline timeout pro
194
194
  function waitForDelay(ms?: number): Promise<void>
195
195
  ```
196
196
 
197
+ Use it to yield, never to wait for something another process produces. A fixed delay chosen to
198
+ outlast a child's startup is a race whose loss looks like a product defect: the test measures
199
+ interpreter bootstrap rather than the behaviour it names, and it fails on a loaded host and passes on
200
+ an idle one. Wait until a named condition holds instead, polling with `waitForDelay` inside a budget
201
+ measured by `performance.now()`, and fail with the condition's own description when the budget
202
+ expires.
203
+
197
204
  ### Scratch
198
205
 
199
206
  Import `createScratch` from `@orkestrel/test/server` when a proof needs real files. It allocates a temporary directory it owns, contains every path against escape, and removes the directory on `destroy`:
@@ -106,8 +106,8 @@ Environment rules:
106
106
 
107
107
  ## Test project matrix
108
108
 
109
- `vite.config.ts` defines Vitest projects on two axes. The first is one project per src/app axis ×
110
- environment:
109
+ `vite.config.ts` defines Vitest projects on an environment axis and a workspace-proof axis. The
110
+ environment axis is one project per src/app axis × environment:
111
111
 
112
112
  | Project | Files | Environment | Setup |
113
113
  | ------------- | ---------------------- | ------------------- | ----------------------------------------------- |
@@ -120,7 +120,7 @@ environment:
120
120
  | `app:browser` | `tests/app/browser/**` | Playwright Chromium | `setup.ts`, `setupBrowser.ts` |
121
121
  | `app:server` | `tests/app/server/**` | Node | `setup.ts`, `setupServer.ts` |
122
122
 
123
- The second axis is cross-cutting workspace proofs. Each one covers the whole workspace rather than
123
+ The workspace-proof axis is cross-cutting. Each proof covers the whole workspace rather than
124
124
  one environment, so each is its own project:
125
125
 
126
126
  | Project | Files | Proves | Gate |
@@ -138,7 +138,7 @@ one environment, so each is its own project:
138
138
  Include every matching file. When registered, emit `test:setup` and run it from `test`. When no
139
139
  file matches, emit neither the project nor the script.
140
140
 
141
- `conformance`, `integration`, `distribution`, and `service` are four subjects, not four names for
141
+ `conformance`, `integration`, `distribution`, and `service` are separate subjects, not names for
142
142
  one.
143
143
  Keep `conformance` in `test`: measure this package against an installed official artifact, and start
144
144
  any server the proof drives itself. Keep `integration` in `test`: compose the workspace's public
@@ -155,7 +155,7 @@ script names its project, so no gate runs it; its directory is ignored by git; a
155
155
  `.claude/rules/tests.md` governs what may live there.
156
156
 
157
157
  - Define a cross-cutting project only for a proof the package actually has.
158
- - A live-service project is the fifth kind. It is the `service` project above, `scripts/service.sh`
158
+ - A live-service project is the `service` project in the preceding table, `scripts/service.sh`
159
159
  provisions what it drives, and `.claude/rules/tests.md` governs it. Name it `service` whatever it
160
160
  drives.
161
161
  - In a publishing workspace, a project leaves the default run when it drives a live external
@@ -241,7 +241,7 @@ Run `show` only **after** formatting. The committed `demo/showcase.html` is gene
241
241
 
242
242
  Policy instruments:
243
243
 
244
- - Put every rule of the policy law in exactly one of two instruments. `configs/policy.ts` — the
244
+ - Put every rule of the policy law in exactly one instrument. `configs/policy.ts` — the
245
245
  oxlint plugin, namespace `policy` — takes the rules a single file's AST decides. The policy sweep
246
246
  (`tests/setupPolicy.ts`) takes the rules that are path- or text-shaped, and every rule whose
247
247
  subject is suppression itself.
@@ -252,7 +252,7 @@ Policy instruments:
252
252
  a named module-scope `report{Noun}` function. Never write rule logic inline in the table. That
253
253
  arrow is the sanctioned exception to the in-body function-expression limits in
254
254
  `.claude/rules/architecture.md` for exactly that table.
255
- - Name no individual rule id here. This section fixes the two instruments and how work is assigned
255
+ - Name no individual rule id here. This section fixes the instruments and how work is assigned
256
256
  between them; each rule's substance stays with the law it enforces.
257
257
 
258
258
  ## Text integrity
@@ -75,8 +75,9 @@ first, and these rules wherever a rule here names no different form for it.
75
75
  - Expand an abbreviation the reader may not know on first use, with the short form in parentheses.
76
76
  Skip the expansion for one this audience reads daily, such as `API`, `CLI`, `JSON`, `URL`, or a
77
77
  file format.
78
- - Write a numeral for a technical quantity, a version, or a count. Write a date as `YYYY-MM-DD` in
79
- evidence, commit messages, and reports.
78
+ - Write a numeral for a technical quantity, a version, or a measurement. Write a date as
79
+ `YYYY-MM-DD` in evidence, commit messages, and reports. See `AGENTS.md` § Writing for what
80
+ separates a value from a count.
80
81
  - Use the serial comma. Mark omitted code with a comment in the sample's language, never with `...`.
81
82
 
82
83
  ## Substitutions
@@ -106,6 +107,15 @@ is exempt from every row.
106
107
  | `blacklist`, `whitelist` | `denylist`, `allowlist` |
107
108
  | `master`, `slave` | `primary`, `replica` |
108
109
 
110
+ - Sweep case-insensitively and across inflections when checking prose against the preceding table. A
111
+ pattern for `easy` reaches neither `Easy` nor `easier`, and a temporal `once` most often appears
112
+ as a sentence-initial `Once`.
113
+ - Rule every hit by the sense its row bans, not by the match. `once` counts as often as it means
114
+ `after`, and `new` names a value as often as it dates one. Record a hit in a permitted sense as
115
+ permitted rather than dropping it.
116
+ - Name the pattern and the paths behind every sweep result, including a clean one. A result naming
117
+ neither reports on the population its pattern admitted rather than on the population it was drawn
118
+ from.
109
119
  - Write singular `they` for a person of unstated gender.
110
120
  - This table carries no row for `execute`, `abort`, `kill`, `terminate`, or `run`:
111
121
  `.claude/rules/names.md` § Fixed lifecycle vocabulary owns those words, and no row here overrides
@@ -12,7 +12,7 @@ This route pins `--permission-mode plan`.
12
12
  The brief asks for coherent API shape, vocabulary, and ergonomics; at most two
13
13
  alternatives; bounded units that each name their role and engine; tensions named for
14
14
  the other lane to challenge, or for the Orchestrator to rule when one engine holds
15
- both lanes; and risks. It forbids edits, commands, reconciliation, orchestration, and
15
+ every lane; and risks. It forbids edits, commands, reconciliation, orchestration, and
16
16
  acceptance.
17
17
 
18
18
  Return the Opus proposal labeled untrusted plus any CLI/auth deviation.
@@ -37,3 +37,7 @@ contract owns when each is used; this is only the mapping:
37
37
  enabled = true
38
38
  max_concurrent_threads_per_session = 3
39
39
  interrupt_message = true
40
+
41
+ [mcp_servers.probe]
42
+ command = "node"
43
+ args = ["node_modules/@orkestrel/probe/dist/bin/main.js"]
@@ -1,4 +1,4 @@
1
- import type { Plugin } from 'vite'
1
+ import type { Plugin, Rolldown } from 'vite'
2
2
  import { parseSync, transformWithOxc, Visitor } from 'vite'
3
3
  import { fileURLToPath } from 'node:url'
4
4
  import { isBuiltin } from 'node:module'
@@ -25,6 +25,26 @@ export function hasAsciiUrlControl(value: string): boolean {
25
25
  export const PACKAGE_MANIFEST_BYTES = 1_048_576
26
26
  export const ENVIRONMENT_MODULE_BYTES = 8_388_608
27
27
 
28
+ /**
29
+ * Throws on a CommonJS import-meta rewrite and forwards every other build log.
30
+ *
31
+ * @param level - The Rolldown log level.
32
+ * @param log - The structured Rolldown log.
33
+ * @param report - The active default log handler.
34
+ * @returns Nothing.
35
+ * @throws An error when Rolldown reports `EMPTY_IMPORT_META`.
36
+ */
37
+ export function enforceBuildLog(
38
+ level: Rolldown.LogLevel,
39
+ log: Rolldown.RolldownLog,
40
+ report: Rolldown.LogOrStringHandler,
41
+ ): void {
42
+ if (log.code === 'EMPTY_IMPORT_META') {
43
+ throw new Error(`[orkestrel-build] ${log.message}`)
44
+ }
45
+ report(level, log)
46
+ }
47
+
28
48
  export const WORKSPACE_ROOT = realpathSync.native(
29
49
  resolvePath(dirname(fileURLToPath(import.meta.url)), '..'),
30
50
  )
@@ -7,6 +7,10 @@
7
7
  "claude": {
8
8
  "command": "claude",
9
9
  "args": ["mcp", "serve"]
10
+ },
11
+ "probe": {
12
+ "command": "node",
13
+ "args": ["node_modules/@orkestrel/probe/dist/bin/main.js"]
10
14
  }
11
15
  }
12
16
  }
@@ -14,7 +14,7 @@ rule, and they are not repeated here. This file adds only how a Cursor session i
14
14
 
15
15
  ## Which posture
16
16
 
17
- A Cursor session is one of two things. Establish which before acting.
17
+ A Cursor session takes one of these postures. Establish which before acting.
18
18
 
19
19
  - **Invoked through the `grok` bridge** — a read-only Executor. Return distilled evidence with
20
20
  `file:line` pointers. Never edit, decide, or accept.
@@ -40,4 +40,7 @@ test-results/
40
40
  playwright-report/
41
41
 
42
42
  # Model files
43
- *.gguf
43
+ *.gguf
44
+
45
+ # Agent worktrees (created by an isolated subagent dispatch, never committed)
46
+ .claude/worktrees/
@@ -3,6 +3,10 @@
3
3
  "codex": {
4
4
  "command": "codex",
5
5
  "args": ["mcp-server"]
6
+ },
7
+ "probe": {
8
+ "command": "node",
9
+ "args": ["node_modules/@orkestrel/probe/dist/bin/main.js"]
6
10
  }
7
11
  }
8
12
  }