@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
@@ -91,6 +91,7 @@ export declare function computeFileDigest(path: string): string | undefined;
91
91
  *
92
92
  * @param entries - The ordered file membership declarations.
93
93
  * @param roots - The ordered directory membership declarations.
94
+ * @param surface - The ordered Surface collisions and their ordered guide owners.
94
95
  * @returns The SHA-256 of that exact membership, in that exact order.
95
96
  *
96
97
  * @remarks
@@ -105,10 +106,10 @@ export declare function computeFileDigest(path: string): string | undefined;
105
106
  * ```ts
106
107
  * import { computeManifestDigest } from '@orkestrel/scaffold/server'
107
108
  *
108
- * computeManifestDigest([], []) // the digest of the empty membership
109
+ * computeManifestDigest([], [], []) // the digest of the empty membership
109
110
  * ```
110
111
  */
111
- export declare function computeManifestDigest(entries: readonly ManifestEntry[], roots: readonly string[]): string;
112
+ export declare function computeManifestDigest(entries: readonly ManifestEntry[], roots: readonly string[], surface: readonly SurfaceCollision[]): string;
112
113
 
113
114
  /** Holds the repository branch a raw content read addresses when a caller names none. */
114
115
  export declare const DEFAULT_BRANCH = "main";
@@ -263,8 +264,9 @@ export declare interface HostInventory {
263
264
  *
264
265
  * @remarks
265
266
  * `roots` is the sorted directory inventory, which is what distinguishes a
266
- * declared empty directory. `digest` is the SHA-256 of that exact entry and
267
- * root membership, so a membership edit that did not update the digest is
267
+ * declared empty directory. `surface` records only names claimed by distinct
268
+ * guides, sorted by name with each owner list sorted. `digest` is the SHA-256
269
+ * of the exact entries, roots, and surface, so an edit without its digest is
268
270
  * detected. A self-consistent replacement manifest defines its own smaller
269
271
  * membership; authenticating omitted membership is outside a checksum's
270
272
  * contract.
@@ -272,9 +274,25 @@ export declare interface HostInventory {
272
274
  export declare interface HostManifest {
273
275
  readonly entries: readonly ManifestEntry[];
274
276
  readonly roots: readonly string[];
277
+ readonly surface: readonly SurfaceCollision[];
275
278
  readonly digest: string;
276
279
  }
277
280
 
281
+ /**
282
+ * Configures the committed inventory baseline and staging reports.
283
+ *
284
+ * @remarks
285
+ * `report` receives the baseline location or its absence. Default: no reporting.
286
+ * `inventory` is relative to the checkout. Default: `host.json`.
287
+ * `establish`: if `true`, an absent inventory establishes the baseline; if `false`,
288
+ * an absent inventory refuses staging. Default: `false`.
289
+ */
290
+ export declare interface HostStageOptions {
291
+ readonly inventory?: string;
292
+ readonly establish?: boolean;
293
+ readonly report?: (message: string) => void;
294
+ }
295
+
278
296
  /**
279
297
  * Matches the visible characters no host path segment may carry.
280
298
  *
@@ -427,18 +445,19 @@ export declare function isFilesystemPath(value: unknown): value is string;
427
445
  * directory a caller named, so both halves are guarded: the manifest by the same
428
446
  * membership law a read root is held to, and the bytes by the core snapshot law,
429
447
  * which bounds the fill and reads every key as a path and every value as exact
430
- * lowercase hexadecimal. Whether those halves agree with each other is the
448
+ * lowercase hexadecimal. The manifest's digest must match its declared entries,
449
+ * roots, and Surface collisions. Whether the fill agrees with the manifest is the
431
450
  * reader's question rather than this one's, because a guard has only `false` to
432
451
  * say and a mismatch has a path to name.
433
452
  *
434
453
  * @example
435
454
  * ```ts
436
- * import { isHost } from '@orkestrel/scaffold/server'
455
+ * import { computeManifestDigest, isHost } from '@orkestrel/scaffold/server'
437
456
  *
438
- * const digest = 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'
457
+ * const digest = computeManifestDigest([], [], [])
439
458
  *
440
- * isHost({ manifest: { entries: [], roots: [], digest }, bytes: {} }) // true
441
- * isHost({ manifest: { entries: [], roots: [], digest } }) // false
459
+ * isHost({ manifest: { entries: [], roots: [], surface: [], digest }, bytes: {} }) // true
460
+ * isHost({ manifest: { entries: [], roots: [], surface: [], digest } }) // false
442
461
  * ```
443
462
  */
444
463
  export declare const isHost: Guard<Host>;
@@ -449,7 +468,8 @@ export declare const isHost: Guard<Host>;
449
468
  * @remarks
450
469
  * The manifest is read from a directory a caller named, so it is the least
451
470
  * trusted value the server face handles and is guarded whole: every entry, every
452
- * declared root, and the digest that authenticates their membership.
471
+ * declared root, sorted Surface collisions with distinct sorted owners, and
472
+ * the syntax of the digest that authenticates that membership.
453
473
  */
454
474
  export declare const isHostManifest: Guard<HostManifest>;
455
475
 
@@ -1095,7 +1115,8 @@ export declare class Materializer implements MaterializerInterface {
1095
1115
  *
1096
1116
  * @param plan - The compiled plan to compare.
1097
1117
  * @param target - The directory to inspect.
1098
- * @returns Findings for hydrated planned paths and selected foreign candidates.
1118
+ * @returns Findings for hydrated planned paths and selected foreign candidates,
1119
+ * plus non-blocking questions for present foreign mirrors differing from hosted guides.
1099
1120
  * @throws {@link ScaffoldError} coded `INVALID` when an argument is not the
1100
1121
  * exact shape, `TARGET` when the host or target cannot be read within its
1101
1122
  * bounds, and `DESTROYED` after teardown.
@@ -1169,9 +1190,9 @@ export declare class Materializer implements MaterializerInterface {
1169
1190
  * the write cannot be staged or committed, and `DESTROYED` after teardown.
1170
1191
  *
1171
1192
  * @remarks
1172
- * A verdict carrying no bytes carries a cause instead, so it is skipped rather
1173
- * than written: one unreachable package never costs the caller the rest of the
1174
- * fetch, and it never empties a mirror it could not replace.
1193
+ * A failed or absent upstream guide uses the verified hosted guide only when
1194
+ * the observed target copy was absent. A present copy stays untouched. A guide
1195
+ * unavailable from the host is skipped, retaining the upstream verdict.
1175
1196
  */
1176
1197
  mirror(mirrors: readonly Mirror[], target: string): MaterializeResult;
1177
1198
  /**
@@ -1356,6 +1377,10 @@ export declare class Materializer implements MaterializerInterface {
1356
1377
  * @param mirrors - The fetched guides; each carries the local bytes its write is held to.
1357
1378
  * @param target - The directory to write into.
1358
1379
  * @returns The mirror paths written and skipped; a mirror already current is skipped.
1380
+ * @remarks
1381
+ * A missing target mirror can use the hosted guide after an upstream failure
1382
+ * or absence. A present mirror stays untouched when upstream supplies no bytes.
1383
+ * The observed target bytes remain the write precondition for either source.
1359
1384
  */
1360
1385
  mirror(mirrors: readonly Mirror[], target: string): MaterializeResult;
1361
1386
  /**
@@ -1793,6 +1818,48 @@ export declare class Materializer implements MaterializerInterface {
1793
1818
  */
1794
1819
  export declare function readSnapshot(target: string, paths: readonly string[]): Snapshot;
1795
1820
 
1821
+ /**
1822
+ * Reads the Surface collision baseline from a committed inventory.
1823
+ *
1824
+ * @param root - The checkout's host path.
1825
+ * @param name - The checkout-relative inventory path. Default: `host.json`.
1826
+ * @returns The recorded collisions, or `undefined` when the inventory is absent.
1827
+ * @throws `ScaffoldError('INVALID', …)` when `root` is not a host path or `name` leaves it.
1828
+ * @throws `ScaffoldError('TARGET', …)` when an existing inventory is unreadable,
1829
+ * malformed, or inconsistent with its digest.
1830
+ *
1831
+ * @example
1832
+ * ```ts
1833
+ * import { readSurfaceBaseline } from '@orkestrel/scaffold/server'
1834
+ *
1835
+ * readSurfaceBaseline('.') // the recorded collisions, if the inventory exists
1836
+ * ```
1837
+ */
1838
+ export declare function readSurfaceBaseline(root: string, name?: string): readonly SurfaceCollision[] | undefined;
1839
+
1840
+ /**
1841
+ * Reads bare Surface names claimed by distinct package guides.
1842
+ *
1843
+ * @param root - The physical directory containing the package guides.
1844
+ * @returns Colliding names and their distinct owners, sorted by name and owner.
1845
+ * @throws `ScaffoldError('TARGET', …)` when the directory or a guide cannot be read.
1846
+ * @throws `ScaffoldError('TARGET', …)` when `@orkestrel/guide` cannot be loaded.
1847
+ *
1848
+ * @remarks
1849
+ * Reads immediate `.md` files except `README.md` through `createGuide().surface()`.
1850
+ * Requires `@orkestrel/guide` in this module's resolution path; Scaffold declares it
1851
+ * only for development. Loads it only when called, so importing the server entry
1852
+ * requires no guide tooling in a production install.
1853
+ *
1854
+ * @example
1855
+ * ```ts
1856
+ * import { readSurfaceCollisions } from '@orkestrel/scaffold/server'
1857
+ *
1858
+ * readSurfaceCollisions('./guides').get('Shared') // the guides claiming Shared, if it collides
1859
+ * ```
1860
+ */
1861
+ export declare function readSurfaceCollisions(root: string): ReadonlyMap<string, readonly string[]>;
1862
+
1796
1863
  /**
1797
1864
  * Matches the Windows device names that stay reserved even when an extension follows.
1798
1865
  *
@@ -1944,13 +2011,17 @@ export declare class Materializer implements MaterializerInterface {
1944
2011
  *
1945
2012
  * @param checkout - The checkout the vendored paths are read from.
1946
2013
  * @param host - The vendored host root to fill; it must be absent or empty.
2014
+ * @param options - The inventory selection, establishment switch, and reporting callback.
2015
+ * Default: no reporting.
1947
2016
  * @returns One entry per staged file, sorted by storage name.
1948
2017
  * @throws `ScaffoldError('INVALID', …)` when either argument is not a host path
1949
2018
  * or a vendored path leaves the checkout or the host root.
1950
2019
  * @throws `ScaffoldError('TARGET', …)` when the checkout is not a directory, the
1951
2020
  * host root is not vacant, the checkout does not carry every vendored path, two
1952
2021
  * vendored files claim one storage name, a vendored file is not a plain file
1953
- * within the artifact ceiling, or the staged manifest does not read back.
2022
+ * within the artifact ceiling, published guides are unreadable, a staged
2023
+ * collision's owner set is not a subset of its published owner set, the inventory is absent without
2024
+ * `establish: true`, or the staged manifest does not read back.
1954
2025
  * @throws `ScaffoldError('WRITE', …)` when a staged file or the manifest cannot
1955
2026
  * be written.
1956
2027
  *
@@ -1968,8 +2039,8 @@ export declare class Materializer implements MaterializerInterface {
1968
2039
  * still; a build output holds nothing, is deleted whole before every build, and
1969
2040
  * has no concurrent reader. What replaces it is refusing early and ordering the
1970
2041
  * writes: the whole membership is derived before anything is created, so a
1971
- * checkout this refuses leaves no host root at all, and `manifest.json` is
1972
- * written last, so a stage that failed part way through leaves a root every
2042
+ * membership refusal leaves no host root at all, and `manifest.json` is
2043
+ * written last, so a copy or Surface refusal leaves a root every
1973
2044
  * reader treats as a raw checkout and fails loudly on.
1974
2045
  *
1975
2046
  * A missing vendored path is refused rather than staged around. A partial root
@@ -1979,15 +2050,20 @@ export declare class Materializer implements MaterializerInterface {
1979
2050
  * once. A directory is the same case — declaring an absent directory as an empty
1980
2051
  * root would create an empty directory in every generated workspace.
1981
2052
  *
1982
- * The walk covers `HOST_PATHS` and `CANON_PATHS` together, because a release
1983
- * ships both: a target receives the first set, and reads the second one out of
1984
- * the installed package. Everything downstream — the missing-path refusal, the
2053
+ * The walk covers `HOST_PATHS`, `CANON_PATHS`, and `REFERENCE_PATHS` together.
2054
+ * A plan selects the paths a target receives; the installed package also carries
2055
+ * the canon and reference files for reading. Every catalog package must have a
2056
+ * guide in the discovered membership before the host is written.
2057
+ * Copied guides must carry no collision whose name and exact owner set the
2058
+ * committed inventory lacks. An absent inventory requires `establish: true`;
2059
+ * an inventory without a valid recorded Surface is refused.
2060
+ * Everything downstream — the missing-path refusal, the
1985
2061
  * storage collision guard, the sort, the digests, and the root inventory — reads
1986
- * the union, so a canon path is staged under exactly the law a vendored one is.
2062
+ * the union, so every staged path follows the same law.
1987
2063
  *
1988
2064
  * The vendoring deny-list applies to what the walk discovers beneath a staged
1989
2065
  * directory, where a maintainer's local credential can legitimately sit, and
1990
- * such a path is skipped. A path either list names itself is curated data
2066
+ * such a path is skipped. A path a staging list names itself is curated data
1991
2067
  * rather than discovery, so it is staged or the stage is refused.
1992
2068
  *
1993
2069
  * @example Vendored data root
@@ -1997,7 +2073,7 @@ export declare class Materializer implements MaterializerInterface {
1997
2073
  * stageHost(process.cwd(), 'dist/host') // one ManifestEntry per file staged
1998
2074
  * ```
1999
2075
  */
2000
- export declare function stageHost(checkout: string, host: string): readonly ManifestEntry[];
2076
+ export declare function stageHost(checkout: string, host: string, options?: HostStageOptions): readonly ManifestEntry[];
2001
2077
 
2002
2078
  /**
2003
2079
  * Stages the committed inventory of the files a vendored host carries.
@@ -2024,7 +2100,13 @@ export declare class Materializer implements MaterializerInterface {
2024
2100
  * stageInventory(process.cwd(), 'host.json') // the committed host inventory
2025
2101
  * ```
2026
2102
  */
2027
- export declare function stageInventory(checkout: string, path: string): HostManifest;
2103
+ export declare function stageInventory(checkout: string, path?: string): HostManifest;
2104
+
2105
+ /** Represents a Surface name claimed by distinct package guides. */
2106
+ export declare interface SurfaceCollision {
2107
+ readonly name: string;
2108
+ readonly owners: readonly string[];
2109
+ }
2028
2110
 
2029
2111
  /**
2030
2112
  * Reports the outcome of one bounded read whose body is taken as text.
@@ -91,6 +91,7 @@ export declare function computeFileDigest(path: string): string | undefined;
91
91
  *
92
92
  * @param entries - The ordered file membership declarations.
93
93
  * @param roots - The ordered directory membership declarations.
94
+ * @param surface - The ordered Surface collisions and their ordered guide owners.
94
95
  * @returns The SHA-256 of that exact membership, in that exact order.
95
96
  *
96
97
  * @remarks
@@ -105,10 +106,10 @@ export declare function computeFileDigest(path: string): string | undefined;
105
106
  * ```ts
106
107
  * import { computeManifestDigest } from '@orkestrel/scaffold/server'
107
108
  *
108
- * computeManifestDigest([], []) // the digest of the empty membership
109
+ * computeManifestDigest([], [], []) // the digest of the empty membership
109
110
  * ```
110
111
  */
111
- export declare function computeManifestDigest(entries: readonly ManifestEntry[], roots: readonly string[]): string;
112
+ export declare function computeManifestDigest(entries: readonly ManifestEntry[], roots: readonly string[], surface: readonly SurfaceCollision[]): string;
112
113
 
113
114
  /** Holds the repository branch a raw content read addresses when a caller names none. */
114
115
  export declare const DEFAULT_BRANCH = "main";
@@ -263,8 +264,9 @@ export declare interface HostInventory {
263
264
  *
264
265
  * @remarks
265
266
  * `roots` is the sorted directory inventory, which is what distinguishes a
266
- * declared empty directory. `digest` is the SHA-256 of that exact entry and
267
- * root membership, so a membership edit that did not update the digest is
267
+ * declared empty directory. `surface` records only names claimed by distinct
268
+ * guides, sorted by name with each owner list sorted. `digest` is the SHA-256
269
+ * of the exact entries, roots, and surface, so an edit without its digest is
268
270
  * detected. A self-consistent replacement manifest defines its own smaller
269
271
  * membership; authenticating omitted membership is outside a checksum's
270
272
  * contract.
@@ -272,9 +274,25 @@ export declare interface HostInventory {
272
274
  export declare interface HostManifest {
273
275
  readonly entries: readonly ManifestEntry[];
274
276
  readonly roots: readonly string[];
277
+ readonly surface: readonly SurfaceCollision[];
275
278
  readonly digest: string;
276
279
  }
277
280
 
281
+ /**
282
+ * Configures the committed inventory baseline and staging reports.
283
+ *
284
+ * @remarks
285
+ * `report` receives the baseline location or its absence. Default: no reporting.
286
+ * `inventory` is relative to the checkout. Default: `host.json`.
287
+ * `establish`: if `true`, an absent inventory establishes the baseline; if `false`,
288
+ * an absent inventory refuses staging. Default: `false`.
289
+ */
290
+ export declare interface HostStageOptions {
291
+ readonly inventory?: string;
292
+ readonly establish?: boolean;
293
+ readonly report?: (message: string) => void;
294
+ }
295
+
278
296
  /**
279
297
  * Matches the visible characters no host path segment may carry.
280
298
  *
@@ -427,18 +445,19 @@ export declare function isFilesystemPath(value: unknown): value is string;
427
445
  * directory a caller named, so both halves are guarded: the manifest by the same
428
446
  * membership law a read root is held to, and the bytes by the core snapshot law,
429
447
  * which bounds the fill and reads every key as a path and every value as exact
430
- * lowercase hexadecimal. Whether those halves agree with each other is the
448
+ * lowercase hexadecimal. The manifest's digest must match its declared entries,
449
+ * roots, and Surface collisions. Whether the fill agrees with the manifest is the
431
450
  * reader's question rather than this one's, because a guard has only `false` to
432
451
  * say and a mismatch has a path to name.
433
452
  *
434
453
  * @example
435
454
  * ```ts
436
- * import { isHost } from '@orkestrel/scaffold/server'
455
+ * import { computeManifestDigest, isHost } from '@orkestrel/scaffold/server'
437
456
  *
438
- * const digest = 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'
457
+ * const digest = computeManifestDigest([], [], [])
439
458
  *
440
- * isHost({ manifest: { entries: [], roots: [], digest }, bytes: {} }) // true
441
- * isHost({ manifest: { entries: [], roots: [], digest } }) // false
459
+ * isHost({ manifest: { entries: [], roots: [], surface: [], digest }, bytes: {} }) // true
460
+ * isHost({ manifest: { entries: [], roots: [], surface: [], digest } }) // false
442
461
  * ```
443
462
  */
444
463
  export declare const isHost: Guard<Host>;
@@ -449,7 +468,8 @@ export declare const isHost: Guard<Host>;
449
468
  * @remarks
450
469
  * The manifest is read from a directory a caller named, so it is the least
451
470
  * trusted value the server face handles and is guarded whole: every entry, every
452
- * declared root, and the digest that authenticates their membership.
471
+ * declared root, sorted Surface collisions with distinct sorted owners, and
472
+ * the syntax of the digest that authenticates that membership.
453
473
  */
454
474
  export declare const isHostManifest: Guard<HostManifest>;
455
475
 
@@ -1095,7 +1115,8 @@ export declare class Materializer implements MaterializerInterface {
1095
1115
  *
1096
1116
  * @param plan - The compiled plan to compare.
1097
1117
  * @param target - The directory to inspect.
1098
- * @returns Findings for hydrated planned paths and selected foreign candidates.
1118
+ * @returns Findings for hydrated planned paths and selected foreign candidates,
1119
+ * plus non-blocking questions for present foreign mirrors differing from hosted guides.
1099
1120
  * @throws {@link ScaffoldError} coded `INVALID` when an argument is not the
1100
1121
  * exact shape, `TARGET` when the host or target cannot be read within its
1101
1122
  * bounds, and `DESTROYED` after teardown.
@@ -1169,9 +1190,9 @@ export declare class Materializer implements MaterializerInterface {
1169
1190
  * the write cannot be staged or committed, and `DESTROYED` after teardown.
1170
1191
  *
1171
1192
  * @remarks
1172
- * A verdict carrying no bytes carries a cause instead, so it is skipped rather
1173
- * than written: one unreachable package never costs the caller the rest of the
1174
- * fetch, and it never empties a mirror it could not replace.
1193
+ * A failed or absent upstream guide uses the verified hosted guide only when
1194
+ * the observed target copy was absent. A present copy stays untouched. A guide
1195
+ * unavailable from the host is skipped, retaining the upstream verdict.
1175
1196
  */
1176
1197
  mirror(mirrors: readonly Mirror[], target: string): MaterializeResult;
1177
1198
  /**
@@ -1356,6 +1377,10 @@ export declare class Materializer implements MaterializerInterface {
1356
1377
  * @param mirrors - The fetched guides; each carries the local bytes its write is held to.
1357
1378
  * @param target - The directory to write into.
1358
1379
  * @returns The mirror paths written and skipped; a mirror already current is skipped.
1380
+ * @remarks
1381
+ * A missing target mirror can use the hosted guide after an upstream failure
1382
+ * or absence. A present mirror stays untouched when upstream supplies no bytes.
1383
+ * The observed target bytes remain the write precondition for either source.
1359
1384
  */
1360
1385
  mirror(mirrors: readonly Mirror[], target: string): MaterializeResult;
1361
1386
  /**
@@ -1793,6 +1818,48 @@ export declare class Materializer implements MaterializerInterface {
1793
1818
  */
1794
1819
  export declare function readSnapshot(target: string, paths: readonly string[]): Snapshot;
1795
1820
 
1821
+ /**
1822
+ * Reads the Surface collision baseline from a committed inventory.
1823
+ *
1824
+ * @param root - The checkout's host path.
1825
+ * @param name - The checkout-relative inventory path. Default: `host.json`.
1826
+ * @returns The recorded collisions, or `undefined` when the inventory is absent.
1827
+ * @throws `ScaffoldError('INVALID', …)` when `root` is not a host path or `name` leaves it.
1828
+ * @throws `ScaffoldError('TARGET', …)` when an existing inventory is unreadable,
1829
+ * malformed, or inconsistent with its digest.
1830
+ *
1831
+ * @example
1832
+ * ```ts
1833
+ * import { readSurfaceBaseline } from '@orkestrel/scaffold/server'
1834
+ *
1835
+ * readSurfaceBaseline('.') // the recorded collisions, if the inventory exists
1836
+ * ```
1837
+ */
1838
+ export declare function readSurfaceBaseline(root: string, name?: string): readonly SurfaceCollision[] | undefined;
1839
+
1840
+ /**
1841
+ * Reads bare Surface names claimed by distinct package guides.
1842
+ *
1843
+ * @param root - The physical directory containing the package guides.
1844
+ * @returns Colliding names and their distinct owners, sorted by name and owner.
1845
+ * @throws `ScaffoldError('TARGET', …)` when the directory or a guide cannot be read.
1846
+ * @throws `ScaffoldError('TARGET', …)` when `@orkestrel/guide` cannot be loaded.
1847
+ *
1848
+ * @remarks
1849
+ * Reads immediate `.md` files except `README.md` through `createGuide().surface()`.
1850
+ * Requires `@orkestrel/guide` in this module's resolution path; Scaffold declares it
1851
+ * only for development. Loads it only when called, so importing the server entry
1852
+ * requires no guide tooling in a production install.
1853
+ *
1854
+ * @example
1855
+ * ```ts
1856
+ * import { readSurfaceCollisions } from '@orkestrel/scaffold/server'
1857
+ *
1858
+ * readSurfaceCollisions('./guides').get('Shared') // the guides claiming Shared, if it collides
1859
+ * ```
1860
+ */
1861
+ export declare function readSurfaceCollisions(root: string): ReadonlyMap<string, readonly string[]>;
1862
+
1796
1863
  /**
1797
1864
  * Matches the Windows device names that stay reserved even when an extension follows.
1798
1865
  *
@@ -1944,13 +2011,17 @@ export declare class Materializer implements MaterializerInterface {
1944
2011
  *
1945
2012
  * @param checkout - The checkout the vendored paths are read from.
1946
2013
  * @param host - The vendored host root to fill; it must be absent or empty.
2014
+ * @param options - The inventory selection, establishment switch, and reporting callback.
2015
+ * Default: no reporting.
1947
2016
  * @returns One entry per staged file, sorted by storage name.
1948
2017
  * @throws `ScaffoldError('INVALID', …)` when either argument is not a host path
1949
2018
  * or a vendored path leaves the checkout or the host root.
1950
2019
  * @throws `ScaffoldError('TARGET', …)` when the checkout is not a directory, the
1951
2020
  * host root is not vacant, the checkout does not carry every vendored path, two
1952
2021
  * vendored files claim one storage name, a vendored file is not a plain file
1953
- * within the artifact ceiling, or the staged manifest does not read back.
2022
+ * within the artifact ceiling, published guides are unreadable, a staged
2023
+ * collision's owner set is not a subset of its published owner set, the inventory is absent without
2024
+ * `establish: true`, or the staged manifest does not read back.
1954
2025
  * @throws `ScaffoldError('WRITE', …)` when a staged file or the manifest cannot
1955
2026
  * be written.
1956
2027
  *
@@ -1968,8 +2039,8 @@ export declare class Materializer implements MaterializerInterface {
1968
2039
  * still; a build output holds nothing, is deleted whole before every build, and
1969
2040
  * has no concurrent reader. What replaces it is refusing early and ordering the
1970
2041
  * writes: the whole membership is derived before anything is created, so a
1971
- * checkout this refuses leaves no host root at all, and `manifest.json` is
1972
- * written last, so a stage that failed part way through leaves a root every
2042
+ * membership refusal leaves no host root at all, and `manifest.json` is
2043
+ * written last, so a copy or Surface refusal leaves a root every
1973
2044
  * reader treats as a raw checkout and fails loudly on.
1974
2045
  *
1975
2046
  * A missing vendored path is refused rather than staged around. A partial root
@@ -1979,15 +2050,20 @@ export declare class Materializer implements MaterializerInterface {
1979
2050
  * once. A directory is the same case — declaring an absent directory as an empty
1980
2051
  * root would create an empty directory in every generated workspace.
1981
2052
  *
1982
- * The walk covers `HOST_PATHS` and `CANON_PATHS` together, because a release
1983
- * ships both: a target receives the first set, and reads the second one out of
1984
- * the installed package. Everything downstream — the missing-path refusal, the
2053
+ * The walk covers `HOST_PATHS`, `CANON_PATHS`, and `REFERENCE_PATHS` together.
2054
+ * A plan selects the paths a target receives; the installed package also carries
2055
+ * the canon and reference files for reading. Every catalog package must have a
2056
+ * guide in the discovered membership before the host is written.
2057
+ * Copied guides must carry no collision whose name and exact owner set the
2058
+ * committed inventory lacks. An absent inventory requires `establish: true`;
2059
+ * an inventory without a valid recorded Surface is refused.
2060
+ * Everything downstream — the missing-path refusal, the
1985
2061
  * storage collision guard, the sort, the digests, and the root inventory — reads
1986
- * the union, so a canon path is staged under exactly the law a vendored one is.
2062
+ * the union, so every staged path follows the same law.
1987
2063
  *
1988
2064
  * The vendoring deny-list applies to what the walk discovers beneath a staged
1989
2065
  * directory, where a maintainer's local credential can legitimately sit, and
1990
- * such a path is skipped. A path either list names itself is curated data
2066
+ * such a path is skipped. A path a staging list names itself is curated data
1991
2067
  * rather than discovery, so it is staged or the stage is refused.
1992
2068
  *
1993
2069
  * @example Vendored data root
@@ -1997,7 +2073,7 @@ export declare class Materializer implements MaterializerInterface {
1997
2073
  * stageHost(process.cwd(), 'dist/host') // one ManifestEntry per file staged
1998
2074
  * ```
1999
2075
  */
2000
- export declare function stageHost(checkout: string, host: string): readonly ManifestEntry[];
2076
+ export declare function stageHost(checkout: string, host: string, options?: HostStageOptions): readonly ManifestEntry[];
2001
2077
 
2002
2078
  /**
2003
2079
  * Stages the committed inventory of the files a vendored host carries.
@@ -2024,7 +2100,13 @@ export declare class Materializer implements MaterializerInterface {
2024
2100
  * stageInventory(process.cwd(), 'host.json') // the committed host inventory
2025
2101
  * ```
2026
2102
  */
2027
- export declare function stageInventory(checkout: string, path: string): HostManifest;
2103
+ export declare function stageInventory(checkout: string, path?: string): HostManifest;
2104
+
2105
+ /** Represents a Surface name claimed by distinct package guides. */
2106
+ export declare interface SurfaceCollision {
2107
+ readonly name: string;
2108
+ readonly owners: readonly string[];
2109
+ }
2028
2110
 
2029
2111
  /**
2030
2112
  * Reports the outcome of one bounded read whose body is taken as text.