@orkestrel/scaffold 0.0.67 → 0.0.68

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 (74) hide show
  1. package/dist/bin/main.js +67 -44
  2. package/dist/bin/main.js.map +1 -1
  3. package/dist/host/agents/templates/brief.md +9 -0
  4. package/dist/host/claude/agents/orkestrel.md +4 -4
  5. package/dist/host/claude/rules/names.md +15 -0
  6. package/dist/host/claude/rules/tests.md +33 -4
  7. package/dist/host/claude/rules/workspace.md +14 -2
  8. package/dist/host/dotfiles/prettierignore +3 -0
  9. package/dist/host/guides/README.md +65 -0
  10. package/dist/host/guides/abort.md +169 -0
  11. package/dist/host/guides/agent.md +1509 -0
  12. package/dist/host/guides/brief.md +1266 -0
  13. package/dist/host/guides/browser.md +2200 -0
  14. package/dist/host/guides/budget.md +196 -0
  15. package/dist/host/guides/codec.md +519 -0
  16. package/dist/host/guides/console.md +785 -0
  17. package/dist/host/guides/contract.md +1193 -0
  18. package/dist/host/guides/csv.md +541 -0
  19. package/dist/host/guides/database.md +2518 -0
  20. package/dist/host/guides/emitter.md +233 -0
  21. package/dist/host/guides/form.md +1791 -0
  22. package/dist/host/guides/html.md +717 -0
  23. package/dist/host/guides/indexeddb.md +505 -0
  24. package/dist/host/guides/interpret.md +1029 -0
  25. package/dist/host/guides/lsp.md +515 -0
  26. package/dist/host/guides/markdown.md +964 -0
  27. package/dist/host/guides/mcp.md +5554 -0
  28. package/dist/host/guides/middleware.md +927 -0
  29. package/dist/host/guides/msg.md +440 -0
  30. package/dist/host/guides/ndjson.md +120 -0
  31. package/dist/host/guides/ollama.md +380 -0
  32. package/dist/host/guides/pool.md +280 -0
  33. package/dist/host/guides/probe.md +1210 -0
  34. package/dist/host/guides/process.md +1620 -0
  35. package/dist/host/guides/program.md +1110 -0
  36. package/dist/host/guides/qualifier.md +854 -0
  37. package/dist/host/guides/queue.md +370 -0
  38. package/dist/host/guides/rater.md +330 -0
  39. package/dist/host/guides/reason.md +1122 -0
  40. package/dist/host/guides/relation.md +373 -0
  41. package/dist/host/guides/router.md +753 -0
  42. package/dist/host/guides/scaffold.md +192 -31
  43. package/dist/host/guides/sea.md +383 -0
  44. package/dist/host/guides/server.md +752 -0
  45. package/dist/host/guides/sqlite.md +330 -0
  46. package/dist/host/guides/sse.md +187 -0
  47. package/dist/host/guides/supervisor.md +4890 -0
  48. package/dist/host/guides/table.md +1556 -0
  49. package/dist/host/guides/template.md +280 -0
  50. package/dist/host/guides/terminal.md +1145 -0
  51. package/dist/host/guides/test.md +2969 -0
  52. package/dist/host/guides/timeout.md +252 -0
  53. package/dist/host/guides/tool.md +311 -0
  54. package/dist/host/guides/toolbox.md +1038 -0
  55. package/dist/host/guides/websocket.md +282 -0
  56. package/dist/host/guides/worker.md +615 -0
  57. package/dist/host/guides/workflow.md +1507 -0
  58. package/dist/host/guides/workspace.md +595 -0
  59. package/dist/host/manifest.json +1218 -10
  60. package/dist/host/tests/policy.test.ts +279 -2
  61. package/dist/host/tests/setupPolicy.ts +437 -6
  62. package/dist/src/core/index.cjs +38 -16
  63. package/dist/src/core/index.cjs.map +1 -1
  64. package/dist/src/core/index.d.cts +33 -9
  65. package/dist/src/core/index.d.ts +33 -9
  66. package/dist/src/core/index.js +37 -17
  67. package/dist/src/core/index.js.map +1 -1
  68. package/dist/src/server/index.cjs +1750 -1567
  69. package/dist/src/server/index.cjs.map +1 -1
  70. package/dist/src/server/index.d.cts +106 -24
  71. package/dist/src/server/index.d.ts +106 -24
  72. package/dist/src/server/index.js +1751 -1570
  73. package/dist/src/server/index.js.map +1 -1
  74. package/package.json +3 -3
@@ -9,19 +9,23 @@ does not work. Scaffold makes the shared set data — a vendored data root shipp
9
9
  — and gives it verbs: create a workspace from it, report how a workspace differs from it, and
10
10
  write the difference back.
11
11
 
12
- That root stages the vendored set and the instruction canon, and a target meets them differently.
13
- `HOST_PATHS` names the vendored set — the licence, the harness permission file, the
14
- session-start hooks, the shared policy register, the shared policy
15
- proof, the shared policy plugin, the shared configuration leaf and its proof, the byte-identical
16
- root dotfiles, and the guide mirrors a generated workspace starts from, never its own guide — and
17
- each target carries its own copy of the paths it selects, which the verbs write and compare.
12
+ That root stages the vendored set, the instruction canon, and the fleet's guides, and a target meets
13
+ each of them differently. `HOST_PATHS` names the vendored set — the licence, the harness permission
14
+ file, the session-start hooks, the shared policy register, the shared policy
15
+ proof, the shared policy plugin, the shared configuration leaf and its proof, and the
16
+ byte-identical root dotfiles — and each target carries its own copy of the paths it selects, which
17
+ the verbs write and compare.
18
18
  `CANON_PATHS` names the instruction canon — the coding and orchestration contracts, the rules, the
19
19
  skills, the templates, the transport contracts, the agent roles, the bench configuration, and the
20
20
  MCP registrations — which stays in one place and is published for reading. A target carries the
21
21
  `AGENTS.md` and `CLAUDE.md` pointers that name where a reader finds it, and the catalog agent file
22
22
  the `catalog` verb rewrites. It carries nothing else at a canon path: a file found at one is a
23
- superseded copy, and `overwrite` deletes it. Vendored data root states how each set is staged and
24
- how a pointer resolves.
23
+ superseded copy, and `overwrite` deletes it.
24
+ `REFERENCE_PATHS` names the `guides` directory — a mirror of every published `@orkestrel` guide
25
+ beside this package's own — which is staged for reading at `dist/host/guides/` and claims nothing in
26
+ a target on its own. The `SEED_GUIDE_PATHS` constant names the mirrors the compiler claims, so
27
+ a generated workspace starts with the guides it works from, and never with its own guide. Vendored
28
+ data root states how each set is staged and how a pointer resolves.
25
29
 
26
30
  Every following code fence is illustrative. [`tests/guides.test.ts`](../tests/guides.test.ts)
27
31
  keeps the command reference aligned with the executable and transcribes the pure blueprint-default,
@@ -130,8 +134,8 @@ Exported from `@orkestrel/scaffold`, and reachable from
130
134
  | `GROUPS` | const | Lists the `Group` values in plan order, frozen. |
131
135
  | `GUIDES_TEST_PATH` | const | Names the package-owned guide-parity entry used by `test:guides` and to select the `guides` project. |
132
136
  | `HEX_PATTERN` | const | Matches exact lowercase hexadecimal bytes: two digits per byte, and empty content is valid. |
133
- | `HOST_PATHS` | const | Lists the paths a target receives from the vendored data root, frozen. |
134
137
  | `HOST_INVENTORY_PATH` | const | Names the repository-relative path where the committed vendored-file inventory is served. |
138
+ | `HOST_PATHS` | const | Lists the paths a target receives from the vendored data root, frozen. |
135
139
  | `INTEGRATION_TEST_PATH` | const | Names the cross-environment composition proof whose presence makes a workspace `integration`. |
136
140
  | `INVALID_PATH_CHARACTER_PATTERN` | const | Matches the visible characters a target-relative path and a Markdown path cell both forbid. |
137
141
  | `MANIFEST_PATH` | const | Names the manifest path every compiler plan emits with birth ownership. |
@@ -155,7 +159,9 @@ Exported from `@orkestrel/scaffold`, and reachable from
155
159
  | `ORCHESTRATION_PATH_PREFIXES` | const | Lists the path prefixes whose contents instruct or wire an agent, frozen. |
156
160
  | `ORKESTREL_RANGE_PATTERN` | const | Matches the exact caret-pinned pre-1.0 range accepted for an `@orkestrel/*` runtime dependency. |
157
161
  | `PRINT_WIDTH` | const | Caps the columns one emitted line may occupy, matching `printWidth` in `.oxfmtrc.json`. |
162
+ | `REFERENCE_PATHS` | const | Lists the reference paths staged for offline reading, frozen. |
158
163
  | `RELEASE_PROOF_COMMAND` | const | Names the `prepublishOnly` row that runs the packed-package proof against a real registry. |
164
+ | `SEED_GUIDE_PATHS` | const | Lists the guide paths a generated workspace starts with, frozen. |
159
165
  | `SERVICE_SCRIPT_PATH` | const | Names the inventory skeleton a workspace with declared service vendors is given once. |
160
166
  | `SERVICE_SETUP_PATH` | const | Names the live-service readiness module whose presence makes a workspace `service`. |
161
167
  | `SERVICE_TEST_INCLUDE` | const | Names the include the live-service project covers, which is a directory rather than one proof. |
@@ -305,11 +311,13 @@ Exported from `@orkestrel/scaffold/server`, and reachable from
305
311
  | `Host` | interface | Represents a whole vendored host supplied as a value: the membership beside the bytes filling it. |
306
312
  | `HostInventory` | interface | Represents the committed vendored-file inventory as one call's reads are decided against. |
307
313
  | `HostManifest` | interface | Represents the complete vendored-host inventory. |
314
+ | `HostStageOptions` | interface | Configures the committed inventory baseline and staging reports. |
308
315
  | `ManifestEntry` | interface | Represents one file record of the vendored host's manifest. |
309
316
  | `MaterializeResult` | interface | Reports the outcome of one mutation of a target. |
310
317
  | `MaterializerInterface` | interface | Describes the mutation contract: the package's only filesystem writer. |
311
318
  | `MaterializerOptions` | interface | Represents the options for the materializer. |
312
319
  | `ReadAllowance` | interface | Represents the byte allowance one whole upstream call spends across every read it makes. |
320
+ | `SurfaceCollision` | interface | Represents a Surface name claimed by distinct package guides. |
313
321
  | `TextReadResult` | interface | Reports the outcome of one bounded read whose body is taken as text. |
314
322
  | `Worktree` | interface | Describes what git reports about a target's working tree. |
315
323
  | `UpstreamInterface` | interface | Describes the upstream contract: the package's only network reader, and it never writes. |
@@ -319,6 +327,15 @@ Exported from `@orkestrel/scaffold/server`, and reachable from
319
327
  | `WriteExpectation` | interface | Represents one destination snapshot captured before a write and required to survive it. |
320
328
  | `WritePrecondition` | interface | Describes the narrower caller-observed destination state a write transaction must still match. |
321
329
 
330
+ The inventory contracts carry these data members.
331
+
332
+ | Member | Contract |
333
+ | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
334
+ | `HostManifest.surface` | Required readonly `SurfaceCollision[]`, sorted by name; each collision has distinct sorted owners and is included in the manifest digest. |
335
+ | `HostStageOptions.inventory` | Optional checkout-relative inventory path. Default: `HOST_INVENTORY_PATH` (`host.json`). |
336
+ | `HostStageOptions.establish` | Optional boolean. If `true`, an absent inventory establishes the baseline; if `false`, staging refuses it. Default: `false`. |
337
+ | `HostStageOptions.report` | Optional callback receiving the baseline location or its absence. Default: no reporting. |
338
+
322
339
  #### Constants
323
340
 
324
341
  | Name | Kind | Summary |
@@ -407,6 +424,8 @@ Exported from `@orkestrel/scaffold/server`, and reachable from
407
424
  | `readHostManifest` | function | Reads a vendored host's manifest, when it carries one. |
408
425
  | `readManifestEntry` | function | Derives one vendored-host manifest entry from a file in a checkout. |
409
426
  | `readSnapshot` | function | Reads a target's current bytes at the paths a plan claims. |
427
+ | `readSurfaceBaseline` | function | Reads the Surface collision baseline from a committed inventory. |
428
+ | `readSurfaceCollisions` | function | Reads bare Surface names claimed by distinct package guides. |
410
429
  | `resolveContainedPath` | function | Resolves a root-relative path and refuses one that leaves its root. |
411
430
  | `resolveRealPath` | function | Resolves a path through the real filesystem, keeping the part that does not exist yet. |
412
431
  | `stageBytes` | function | Stages the named destinations of a value host into a private root. |
@@ -487,8 +506,11 @@ option grants a write.
487
506
 
488
507
  Every remote surface reads its live source first and falls back, whole, to the copy the installed
489
508
  package distributes; each operation reports one baseline word per surface. A surface can select
490
- `floor` only where the package distributes a copy. The registry's organization membership ships
491
- nowhere, so `catalog` refuses when that read fails.
509
+ `floor` only where the package distributes a copy. When organization membership is unreachable,
510
+ `catalog` performs a guide-only refresh and preserves the catalog table and dependency ranges.
511
+ It selects declared packages by default and the hosted catalog's names with `--all`, excluding
512
+ the target's own package. The result carries an explanatory `note` and omits `membership`,
513
+ claims no version provenance, and exits `1`.
492
514
 
493
515
  For `new`, `repair`, `catalog`, and `overwrite`, authoritative absence on a version surface never
494
516
  selects `floor`. A registry `404` or a packument with no admitted version stays a `FETCH` refusal,
@@ -498,8 +520,11 @@ refusals, byte-bound refusals, and integrity refusals can select the floor.
498
520
 
499
521
  The guide surface is the per-row exception to whole-surface fallback, for absence as well as for
500
522
  faults. A foreign guide the host could not serve — a failed read, or the `404` a published package
501
- with a private repository answers with — keeps the target's existing mirror as its floor, while the
502
- other guide rows can still update. When at least one selected guide keeps its mirror,
523
+ with a private repository answers with — keeps the target's existing mirror as its floor. If the
524
+ target has no copy, the Materializer writes the verified hosted guide from `dist/host/guides`.
525
+ The observed target bytes remain the write precondition. A path unavailable from upstream and the
526
+ host stays unresolved, and its mirror verdict retains the original failure. Other guide rows can
527
+ still update. When at least one selected guide fails to resolve live,
503
528
  `provenance.guides` is `floor` for the result; it is `live` only when every selected guide resolved
504
529
  live.
505
530
 
@@ -748,13 +773,46 @@ deletion.
748
773
  `--json` replaces the report with one JSON value on standard output. Warnings and refusals go to
749
774
  standard error, so a piped value is never polluted.
750
775
 
751
- | Verb | Value |
752
- | ----------- | -------------------------------------------------------------------------------------------------------- |
753
- | `new` | `MaterializeResult` — `target`, `written`, `skipped`, `removed` — plus `provenance` |
754
- | `audit` | `Audit` — `findings` and `questions` — plus `releases` and `provenance`; findings carry `ownership` |
755
- | `repair` | `MaterializeResult` plus `audit`, the terminal audit taken after the write, `releases`, and `provenance` |
756
- | `catalog` | `MaterializeResult` plus `entries`, `mirrors`, `dropped`, `releases`, and `provenance` |
757
- | `overwrite` | The `catalog` value plus `audit` and `note` on a partial run |
776
+ | Verb | Value |
777
+ | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
778
+ | `new` | `MaterializeResult` — `target`, `written`, `skipped`, `removed` — plus `provenance` |
779
+ | `audit` | `Audit` — `findings` and `questions` — plus `releases` and `provenance`; findings carry `ownership` |
780
+ | `repair` | `MaterializeResult` plus `audit`, the terminal audit taken after the write, `releases`, and `provenance` |
781
+ | `catalog` | `MaterializeResult` plus `mirrors`, `provenance`, optional `membership` with `entries`, `dropped`, and `releases`, and an explanatory `note` on a partial run |
782
+ | `overwrite` | The `catalog` value plus `audit` and top-level `releases` from its version read; `note` explains a partial run |
783
+
784
+ The `membership` entity is present only when the catalog read completes. Its `entries` holds the
785
+ package table, `dropped` names packages the preceding table carried that the registry no longer
786
+ lists, and `releases` measures declared fleet ranges against the catalog read. The `overwrite`
787
+ result also retains top-level `releases` from its separate version read, including foreign tools.
788
+ An absent `membership` identifies an incomplete catalog read; `note` explains the cause.
789
+
790
+ The following JSON excerpt shows the membership evidence in a completed catalog result:
791
+
792
+ ```text
793
+ {
794
+ "membership": {
795
+ "entries": [
796
+ {
797
+ "name": "@orkestrel/emitter",
798
+ "lookup": "found",
799
+ "version": "0.0.6",
800
+ "dependencies": [],
801
+ "peers": []
802
+ }
803
+ ],
804
+ "dropped": [],
805
+ "releases": [
806
+ {
807
+ "name": "@orkestrel/emitter",
808
+ "range": "^0.0.5",
809
+ "lookup": "found",
810
+ "latest": "0.0.6"
811
+ }
812
+ ]
813
+ }
814
+ }
815
+ ```
758
816
 
759
817
  Every failure reports the same envelope instead: `{ "error": { "code": …, "message": … } }`. The
760
818
  code is a `ScaffoldErrorCode`, or `USAGE` for a command line that never became a command, or
@@ -1031,6 +1089,50 @@ fetched bytes rather than prose this workspace wrote, and it reports a top-level
1031
1089
  neither this package's own, nor `guides/README.md`, nor a catalog row, so an exclusion always
1032
1090
  carries its evidence.
1033
1091
 
1092
+ The `surface` rule in `inspectPolicyWorkspace` compares live barrel exports and target-owned root
1093
+ `tests/setup*.ts` exports with the hosted guides. It matches bare names case-sensitively across
1094
+ environments and declaration kinds. Source names claimed by the target's own hosted guide are
1095
+ grandfathered; setup exports have no grandfather, and setup paths selected by `HOST_PATHS` are
1096
+ excluded. A scaffold checkout reads its own `guides/` directory and its own catalog; every other
1097
+ target reads `node_modules/@orkestrel/scaffold/dist/host/guides/` and the catalog staged beside it.
1098
+ The population it compares is what the parser accounts for: each exported declaration — a variable
1099
+ declarator, function, class, interface, type alias, enum, or namespace — every name an export list
1100
+ or a re-export list names, the alias of a namespace re-export, and the names a relative star export
1101
+ reaches through the file that declares them. Every other form is refused rather than passed over.
1102
+ Unreadable syntax, a default export, an `export =` assignment, an `export as namespace`
1103
+ declaration, a binding that is not an identifier, a barrel statement outside the one-line relative
1104
+ `.js` star form, and a star target the sweep cannot resolve to a file it reads each report a
1105
+ `surface` violation naming the path and the line.
1106
+ A missing guide root, an empty catalog, a catalog row with no hosted guide, and a hosted guide
1107
+ carrying no `Surface` section report one the same way, so a reading the sweep could not complete
1108
+ never reports clean. A collision reads
1109
+ `surface name belongs to one package: NAME (OWNER)` and carries the declaring path and line, sorted
1110
+ by path, line, and message. Which package keeps a claimed name is the answer
1111
+ `.claude/rules/names.md` § Fleet name ownership gives; the rule carries no allowlist and no
1112
+ suppression.
1113
+
1114
+ ### Policy setup surface
1115
+
1116
+ These `tests/setupPolicy.ts` exports implement the `surface` rule: its declarations, its constants,
1117
+ its readers, and the fixtures its controls run against. Every other
1118
+ export in that module serves another rule of the sweep or every rule of it, and no name in either
1119
+ set is reachable through a published specifier.
1120
+
1121
+ | Name | Kind | Summary |
1122
+ | ------------------------------- | --------- | ------------------------------------------------------------------------------------ |
1123
+ | `PolicySurfaceDeclaration` | interface | Describes one reachable declaration and its physical source location. |
1124
+ | `PolicySurfacePopulation` | interface | Groups reachable declarations with refusals of incomplete barrel evidence. |
1125
+ | `POLICY_SURFACE_BARREL_PATTERN` | const | Matches the complete physical barrel rows the parser accepts. |
1126
+ | `POLICY_SURFACE_CATALOG` | const | Names the staged catalog's storage path beneath the installed host. |
1127
+ | `POLICY_SURFACE_EXPORT_CASES` | const | Supplies export forms that must participate in the fleet comparison. |
1128
+ | `POLICY_SURFACE_HOST` | const | Names the installed host root containing the fleet's reference guides. |
1129
+ | `createPolicySurfaceFixture` | function | Creates a scratch target with a complete installed guide population. |
1130
+ | `createPolicySurfaceGuide` | function | Creates a guide whose surface claims the supplied fixture names. |
1131
+ | `inspectPolicySurface` | function | Inspects source and target-owned setup names against the hosted fleet guides. |
1132
+ | `readPolicyDeclarations` | function | Locates parsed exports at their physical declaration lines. |
1133
+ | `readPolicySurface` | function | Reads reachable source declarations and refuses unread barrel statements or targets. |
1134
+ | `writePolicySurfaceHost` | function | Writes a complete hosted reference population for a physical policy control. |
1135
+
1034
1136
  `tests/guides.test.ts` invokes the public `GuideCommand` class with this package's inventory policy,
1035
1137
  the Guide reader, and the real Vitest runner. Its anonymous worker callback owns the package
1036
1138
  assertions: a guide's `Summary` cell against its export's description paragraph, a titled guide
@@ -1130,6 +1232,13 @@ target holds. The refusal is deliberate at `0.0.x` and there is no migration pat
1130
1232
 
1131
1233
  ## Fleet catalog
1132
1234
 
1235
+ During `audit`, a present foreign guide whose bytes differ from the hosted guide produces a
1236
+ non-blocking question whose `field` is `guides`. Its message names the mirror path and `catalog`
1237
+ as the refresh action. The message says
1238
+ "differs from the hosted guide": byte inequality establishes no chronology. The question sits
1239
+ outside repair findings, so `repair` preserves a present mirror. The target's own guide and its
1240
+ guide index are excluded, and the comparison follows the `guides` group selection.
1241
+
1133
1242
  `catalog` rewrites one marker-bounded region in `CATALOG_AGENT_PATH` and nothing else in that file.
1134
1243
  The region holds a table with these columns:
1135
1244
 
@@ -1226,7 +1335,7 @@ committed before a later catalog refusal and records that refusal in `note`.
1226
1335
  | `new` | Declared versions and the vendored host | Writes the distributed version and host floors; exits `0` after creating the workspace | Reads no upstream surface, writes the same floors, and exits `0` after creating the workspace |
1227
1336
  | `audit` | Declared versions and the vendored host | Compares through the distributed floors and exits `1` | Compares through the floors; exits `0` for an aligned target or `1` for drift |
1228
1337
  | `repair` | Declared versions and the vendored host | Repairs from the distributed floors and exits `1`, even when the terminal audit is aligned | Repairs from the floors; the terminal audit decides exit `0` or `1` |
1229
- | `catalog` | Organization membership, its packuments, and the selected guides | Refuses a membership or version failure with `FETCH` and exit `1`; preserves the local mirror of each guide that failed or is absent upstream and exits `1` | Is a usage error; exits `2` and writes nothing |
1338
+ | `catalog` | Organization membership, its packuments, and the selected guides | Refreshes guides alone on a membership outage; refuses version failure; preserves present mirrors or fills absent mirrors from the verified host; exits `1` | Is a usage error; exits `2` and writes nothing |
1230
1339
  | `overwrite` | Everything `repair` and `catalog` read | Keeps completed repair and deletion work, names each floor or refused catalog step in `note`, and exits `1` | Repairs, deletes, and writes version floors; skips `catalog`, records that refusal in `note`, and exits `1` |
1231
1340
 
1232
1341
  A fleet row is compared exactly — `^0.1.0` is stale the moment the registry serves `0.1.2` — and
@@ -1250,15 +1359,15 @@ generating a workspace with no network receives.
1250
1359
  ## Vendored data root
1251
1360
 
1252
1361
  The vendored data root is the shared file set, staged into the published package as plain data.
1253
- Staging walks `HOST_PATHS` and `CANON_PATHS`, and a release ships what both name.
1362
+ Staging walks `HOST_PATHS`, `CANON_PATHS`, and `REFERENCE_PATHS`, and a release ships what those
1363
+ lists name.
1254
1364
 
1255
1365
  `HOST_PATHS` is the vendored set, and a target receives a copy of each path it selects: the
1256
1366
  licence, the harness permission file, the scaffold-owned `scripts` directory, the
1257
1367
  shared policy register, the shared policy proof, the shared policy plugin, the shared configuration
1258
- leaf and its proof, the byte-identical root dotfiles, and the guide mirrors a generated workspace
1259
- starts from. It is a candidate list rather than a plan, because a workspace never mirrors its own
1260
- guide. The session-start hooks inside `scripts` split by job. The bench probe reports whether a
1261
- bench CLI resolves, and the dependency hook installs the lockfile's closure in a remote session.
1368
+ leaf and its proof, and the byte-identical root dotfiles. The session-start hooks inside `scripts`
1369
+ split by job. The bench probe reports whether a bench CLI resolves, and the dependency hook installs
1370
+ the lockfile's closure in a remote session.
1262
1371
  The Ollama hook invokes `scripts/ollama.sh` only when `CLAUDE_CODE_REMOTE=true`; direct invocation
1263
1372
  remains available for live-service setup. What wires a bench stays in the canon, and a session reads
1264
1373
  it at its primary root.
@@ -1295,15 +1404,36 @@ the canon a target holds nothing, and a reader reaches the contracts from a scaf
1295
1404
  beside the repository, or from the `node_modules/@orkestrel/scaffold/dist/host/` root inside the
1296
1405
  installed package, which is what the `AGENTS.md` pointer scaffold plans into a target names.
1297
1406
 
1298
- `HOST_PATHS` and `CANON_PATHS` are disjoint by prefix in either direction: no member of one equals or
1299
- sits beneath a member of the other. Staging depends on that, because the walk covers the union and a
1407
+ `REFERENCE_PATHS` is the fleet's guides, staged for reading like the canon and owned like neither
1408
+ of the other lists. It holds the `guides` directory, so a release stages this repository's mirror of
1409
+ every published `@orkestrel` guide beside `guides/scaffold.md` itself, each at
1410
+ `dist/host/guides/<name>.md` inside the installed package. Reference membership grants a target
1411
+ nothing: it is neither an ownership claim the verbs write and compare, nor canon membership
1412
+ `isCanonPath` reports. What a target holds at a guide path comes from a claim made elsewhere.
1413
+ `blueprintToHostArtifacts` claims the mirrors named by `SEED_GUIDE_PATHS`, which is the
1414
+ seed a generated workspace starts from, and `selectHostPaths` drops the workspace's own guide from
1415
+ that claim, because that file is the workspace's own product. Every other guide reaches a target
1416
+ through `catalog`, which fetches the live file and falls back to the staged copy. Baselines states
1417
+ that fallback.
1418
+
1419
+ The hosted set is also what the fleet's name-ownership gate reads. `readSurfaceCollisions` reads
1420
+ each staged guide's `## Surface` names and reports every bare name distinct guides claim.
1421
+ `readSurfaceCollisions` requires `@orkestrel/guide` in the server module's resolution path;
1422
+ Scaffold declares it only for development and reports `ScaffoldError('TARGET', …)` when it
1423
+ cannot load that module. `stageHost` compares the reading against the baseline during staging.
1424
+ Staging and the
1425
+ `surface` rule in Ownership and drift therefore answer from one population.
1426
+
1427
+ `HOST_PATHS`, `CANON_PATHS`, and `REFERENCE_PATHS` are disjoint by prefix in every direction: no
1428
+ member of one equals or sits beneath a member of another. Staging depends on that, because the walk
1429
+ covers the union and a
1300
1430
  path it discovers twice claims one storage name twice, which refuses the stage. `isCanonPath` is the
1301
1431
  one reading of canon membership, matching a member and anything beneath a member that is a directory,
1302
1432
  so staging, the live overlay, and the executable's fetch list never disagree about what a path is.
1303
1433
  Membership says where a path's bytes are staged, not whether a plan claims it:
1304
1434
  `blueprintToHostArtifacts` appends `CATALOG_AGENT_PATH` to what `HOST_PATHS` selects rather than
1305
- listing it there, which is what keeps the file planned without putting a canon path in the vendored
1306
- list.
1435
+ listing it there, and claims the seed guide mirrors the same way, which is what keeps each file
1436
+ planned without putting a canon or reference path in the vendored list.
1307
1437
 
1308
1438
  The `host.json` file at the repository root is the committed live inventory. Each entry carries the
1309
1439
  SHA-256 digest of its file content, and the inventory carries a membership digest over its declared
@@ -1358,7 +1488,8 @@ Each staged path is copied to a storage name, and every dot that opens a segment
1358
1488
  because npm's own ignore rules would drop a leading-dot entry from the tarball. A dotted file at the
1359
1489
  root moves under `dotfiles/` so it cannot collide with an undotted sibling. `manifest.json` is
1360
1490
  written last and declares the whole membership: one entry per file with a digest computed from the
1361
- staged destination after its copy, the sorted directory inventory, and a SHA-256 digest over both.
1491
+ staged destination after its copy, the sorted directory inventory, the sorted `surface` collision
1492
+ collection, and a SHA-256 digest over that membership.
1362
1493
  The membership digest detects an edit that did not update the manifest, and the directory inventory
1363
1494
  makes a declared empty directory survive a file walk.
1364
1495
 
@@ -1374,6 +1505,36 @@ A missing staged path is refused rather than staged around, and the refusal name
1374
1505
  path at once. That is why `guides/scaffold.md` — this file — must exist before `npm run build`
1375
1506
  completes.
1376
1507
 
1508
+ The stage reads the guides it discovered and refuses on what it finds there, failing the build that
1509
+ produced the fault rather than a consumer's terminal. Every package the catalog table lists must
1510
+ have a staged guide, because a row whose guide never shipped is a row the offline floor and the
1511
+ `surface` rule cannot answer for. The copied guides must also carry no Surface collision the
1512
+ committed inventory does not already record: `stageHost` reads the baseline through
1513
+ `readSurfaceBaseline` before the build rewrites the inventory, and refuses a name whose staged
1514
+ owner set differs from the inventory — absent from the record, or not a subset of its recorded
1515
+ owners — which is what stops a release from widening the set of names more than one package claims.
1516
+ A collision the baseline records and the stage no longer produces, or whose staged owners are a
1517
+ narrower subset of the recorded set, is accepted, so closing one needs no separate step. `HostStageOptions.inventory` selects the
1518
+ checkout-relative inventory path, defaulting to `HOST_INVENTORY_PATH` (`host.json`).
1519
+ `HostStageOptions.report` receives the baseline location or its absence; its default reports
1520
+ nothing. The `build:host` script passes a sink that writes the report to standard error.
1521
+ An absent inventory refuses staging unless `HostStageOptions.establish` is `true`. Use that
1522
+ option to bootstrap a fresh checkout deliberately. An inventory whose `surface` is missing,
1523
+ malformed, or at odds with its digest is refused even during bootstrap.
1524
+
1525
+ `npm run build` is the release path, and it passes neither `HostStageOptions.inventory` nor
1526
+ `HostStageOptions.establish`. Its `build:host` step stages
1527
+ `dist/host`, and its `build:inventory` step stages a temporary root and writes the manifest that
1528
+ run produced to `host.json`; each reads the committed inventory at the default path, refuses an
1529
+ absent one, and compares the staged collisions against what that inventory records. Deleting
1530
+ `host.json` therefore makes the release refuse rather than record a fresh baseline, and the
1531
+ inventory a release writes is what the checkout committed minus the collisions the stage no longer
1532
+ produces. `HostStageOptions.inventory` and `HostStageOptions.establish` are the package's own
1533
+ routes past that refusal: a caller can stage against another checkout-relative record or establish
1534
+ a fresh one, and `computeManifestDigest` makes such a record self-consistent. Neither route changes
1535
+ what a release reads until that record is committed as `host.json`, so review reads a widened or
1536
+ re-established baseline as a diff of that file.
1537
+
1377
1538
  The `Materializer` reads the root once, at construction, and cross-checks the manifest against the
1378
1539
  files actually stored. It defaults to the root inside the installed package, resolved from the
1379
1540
  module's own location rather than from the caller's working directory. `--from` points it somewhere