@orkestrel/scaffold 0.0.44 → 0.0.45

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 (66) 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 +9 -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/configs/helpers.ts +21 -1
  44. package/dist/host/cursor/rules/orchestration.mdc +1 -1
  45. package/dist/host/dotfiles/gitignore +4 -1
  46. package/dist/host/guides/scaffold.md +134 -119
  47. package/dist/host/scripts/codex.sh +0 -0
  48. package/dist/host/scripts/cursor.sh +0 -0
  49. package/dist/host/scripts/deps.sh +0 -0
  50. package/dist/host/scripts/ollama.sh +0 -0
  51. package/dist/host/tests/config.test.ts +40 -1
  52. package/dist/host/tests/policy.test.ts +2 -2
  53. package/dist/host/tests/setupPolicy.ts +8 -5
  54. package/dist/src/core/index.cjs +143 -149
  55. package/dist/src/core/index.cjs.map +1 -1
  56. package/dist/src/core/index.d.cts +1624 -1643
  57. package/dist/src/core/index.d.ts +1624 -1643
  58. package/dist/src/core/index.js +144 -149
  59. package/dist/src/core/index.js.map +1 -1
  60. package/dist/src/server/index.cjs +82 -97
  61. package/dist/src/server/index.cjs.map +1 -1
  62. package/dist/src/server/index.d.cts +1844 -1871
  63. package/dist/src/server/index.d.ts +1844 -1871
  64. package/dist/src/server/index.js +83 -96
  65. package/dist/src/server/index.js.map +1 -1
  66. package/package.json +3 -3
@@ -39,7 +39,7 @@ var RESERVED_SEGMENT_PATTERN = /^(?:con|prn|aux|nul|com[1-9]|lpt[1-9]|conin\$|co
39
39
  *
40
40
  * @remarks
41
41
  * Fixed length, unlike the core byte encoding, because a digest is one value of
42
- * one algorithm rather than a variable run of bytes. Lowercase only, so two
42
+ * one algorithm rather than a variable run of bytes. Lowercase only, so separate
43
43
  * spellings of one digest can never compare unequal.
44
44
  */
45
45
  var DIGEST_PATTERN = /^[0-9a-f]{64}$/;
@@ -131,7 +131,7 @@ var MANIFEST_NAME = "manifest.json";
131
131
  * the byte ceiling. The character ceiling is read first so an oversized string is
132
132
  * refused before it is split.
133
133
  *
134
- * The two spellings of an empty segment are answered differently. A trailing
134
+ * The spellings of an empty segment are answered differently. A trailing
135
135
  * separator terminates a directory rather than opening a segment, and every
136
136
  * supported filesystem and every Node path API reads `project/` and `project` as
137
137
  * one location, so it is admitted. A doubled separator is a genuine empty
@@ -199,7 +199,7 @@ var isDigest = (0, _orkestrel_contract.stringOf)({ pattern: DIGEST_PATTERN });
199
199
  * composed, and for the same reason: the item count is settled before anything
200
200
  * walks the items, and a hostile `length` accessor answers `false` rather than
201
201
  * escaping as a throw. It exists beside that guard rather than reusing it
202
- * because the two bound different things — one bounds what a caller may hand a
202
+ * because they bound different things — one bounds what a caller may hand a
203
203
  * public method, this one bounds what a checkout may contain.
204
204
  *
205
205
  * @example
@@ -367,8 +367,8 @@ var isMaterializerOptions = (0, _orkestrel_contract.recordOf)({
367
367
  * Narrow a value to the upstream reader's initial listener record.
368
368
  *
369
369
  * @remarks
370
- * Closed to the reader's own four events for the same reason the materializer's
371
- * record is closed to its five.
370
+ * Closed to the reader's own events for the same reason the materializer's
371
+ * record is closed to its own.
372
372
  */
373
373
  var isUpstreamHooks = (0, _orkestrel_contract.recordOf)({
374
374
  release: _orkestrel_contract.isFunction,
@@ -384,7 +384,7 @@ var isUpstreamHooks = (0, _orkestrel_contract.recordOf)({
384
384
  * the wrong entity is refused rather than ignored. Every numeric leaf is a whole
385
385
  * number inside a ceiling: an unbounded concurrency, retry count, response
386
386
  * limit, or call budget is a way to exhaust the caller, so the ceiling is stated
387
- * here rather than left to the reader. The two byte ceilings are the core
387
+ * here rather than left to the reader. The byte ceilings are the core
388
388
  * artifact and total-artifact limits, because a fetched guide is an artifact and
389
389
  * a whole call retains no more than a whole plan.
390
390
  *
@@ -424,7 +424,7 @@ var isUpstreamOptions = (0, _orkestrel_contract.recordOf)({
424
424
  * @remarks
425
425
  * The one place absence is told apart from failure. Every read here answers
426
426
  * `undefined` or an empty result for a path that is not there and reports a path
427
- * that is there but unreadable, so the two must never be read from the same
427
+ * that is there but unreadable, so they must never be read from the same
428
428
  * caught value by eye. Total for any caught value, including a hostile one.
429
429
  *
430
430
  * @example
@@ -445,7 +445,7 @@ function matchesMissingPath(error) {
445
445
  * @returns `true` for `.git` and for anything beneath it.
446
446
  *
447
447
  * @remarks
448
- * The one home of the `.git` membership rule, read from two directions. A target
448
+ * The one home of the `.git` membership rule, read in either direction. A target
449
449
  * holding nothing but this directory is still vacant, because a checkout of an
450
450
  * empty repository is where a fresh workspace legitimately starts. A path
451
451
  * beneath it is never removed and never vendored, because deleting a target's
@@ -472,11 +472,13 @@ function matchesGitPath(path) {
472
472
  * @remarks
473
473
  * The deletion deny-list, stated as a rule over paths rather than as a list of
474
474
  * directories. It is the inversion the contract asks for: the candidate set
475
- * comes from an audit's foreign findings narrowed by what git tracks, and this
476
- * is what that set is then measured against. Repository metadata is protected
477
- * because losing history is not a repair, and a target's own `src` and `app`
478
- * trees are protected because a workspace's source is the one thing scaffold
479
- * never plans and never owns, whatever an audit reports about it.
475
+ * is re-derived from the plan and narrowed by what git tracks, and the audit
476
+ * must agree with that derivation rather than supply the set itself.
477
+ * Repository metadata is protected because losing history is not a repair,
478
+ * and a target's own `src` and `app` trees are protected because a
479
+ * workspace's source is the one thing scaffold never plans and never owns. A
480
+ * plan the compiler emits never maps a protected root, so this guard exists
481
+ * for the caller-authored plan a consumer can still supply.
480
482
  *
481
483
  * @example
482
484
  * ```ts
@@ -611,7 +613,7 @@ function computeDigest(content) {
611
613
  * detect a membership edit that did not update it. Order is part of the claim
612
614
  * rather than normalized away, because a staged manifest sorts its entries and
613
615
  * roots once and a reordered copy is a different file. Each entry is projected
614
- * to exactly the three declared fields, so a hand-added property cannot ride
616
+ * to exactly the declared fields, so a hand-added property cannot ride
615
617
  * into the digest and cannot change it either.
616
618
  *
617
619
  * @example
@@ -700,8 +702,8 @@ function isExactCaseFile(path) {
700
702
  * @returns `true` only for a directory that is not a link.
701
703
  *
702
704
  * @remarks
703
- * A junction and a directory symbolic link both report as directories once
704
- * followed, so the inspection deliberately does not follow: a redirected
705
+ * A junction and a directory symbolic link both report as directories after
706
+ * they are followed, so the inspection deliberately does not follow: a redirected
705
707
  * directory is refused here rather than silently accepted as the one the caller
706
708
  * named.
707
709
  *
@@ -1125,7 +1127,7 @@ function listDirectories(root) {
1125
1127
  * snapshot all compare as the same digits. The file's identity and size are
1126
1128
  * measured before and after the read, and one extra byte is requested past the
1127
1129
  * declared size, so a file that grew or was replaced mid-read answers
1128
- * `undefined` rather than half of two files.
1130
+ * `undefined` rather than half of one file and half of another.
1129
1131
  *
1130
1132
  * @example
1131
1133
  * ```ts
@@ -1214,7 +1216,7 @@ function readFileText(root, path, limit = _src_core.MAX_ARTIFACT_BYTES) {
1214
1216
  * The one door from a real directory into the vocabulary an audit compares in.
1215
1217
  * Absence is omission rather than an empty value, because core reads a missing
1216
1218
  * key as a missing destination and an empty string as a present directory; the
1217
- * two are different verdicts. A path that is there but unreadable throws instead
1219
+ * they are different verdicts. A path that is there but unreadable throws instead
1218
1220
  * of being omitted, because omission would report it as missing and a repair
1219
1221
  * would then overwrite whatever is actually sitting there.
1220
1222
  *
@@ -1274,7 +1276,7 @@ function readSnapshot(target, paths) {
1274
1276
  * read, is not the declared shape, or does not match its own membership.
1275
1277
  *
1276
1278
  * @remarks
1277
- * The two failures are held apart deliberately. A host with no manifest is a
1279
+ * The failures are held apart deliberately. A host with no manifest is a
1278
1280
  * raw checkout, and a caller reads it by mapping each path one to one. A host
1279
1281
  * with a manifest that does not verify is a staged host that has been edited,
1280
1282
  * and answering `undefined` there would degrade it to that same one-to-one
@@ -1322,8 +1324,8 @@ function readHostManifest(host) {
1322
1324
  * package will vendor or carries more bytes than one artifact may.
1323
1325
  *
1324
1326
  * @remarks
1325
- * The one place the three declared fields are decided together, because they are
1326
- * three readings of one path: {@link pathToStorage} decides where it is stored,
1327
+ * The one place the declared fields are decided together, because they are
1328
+ * readings of one path: {@link pathToStorage} decides where it is stored,
1327
1329
  * the destination is the path it answers for, and {@link matchesExecutablePath}
1328
1330
  * decides whether a target receives it executable.
1329
1331
  *
@@ -1372,7 +1374,7 @@ function readManifestEntry(destination, source) {
1372
1374
  * every destination to what the caller observed, and rolls a failed commit back.
1373
1375
  * This reads this package's own checkout at build time and fills its own build
1374
1376
  * output. Different direction, different lifetime, no consumer target involved,
1375
- * so the two do not overlap and neither one belongs inside the other.
1377
+ * so they do not overlap and neither one belongs inside the other.
1376
1378
  *
1377
1379
  * Staging is plain rather than transactional for the same reason. A
1378
1380
  * `WriteTransaction` exists to hold a directory that already holds work
@@ -1546,7 +1548,7 @@ function readAnchor(path) {
1546
1548
  * @remarks
1547
1549
  * This binds location rather than history. `true` means the path still resolves
1548
1550
  * to the same physical directory on the same device, so the next write lands
1549
- * where the last one did. A path now holding nothing, a file, or a symlink
1551
+ * where the last one did. A path holding nothing, a file, or a symlink
1550
1552
  * answers `false`; a directory swapped in by `rename` also answers `false`
1551
1553
  * because the replacement carries its own inode. A directory deleted and made
1552
1554
  * again under the same name can receive the old inode back and answers `true`,
@@ -1617,7 +1619,7 @@ function readExpectation(path) {
1617
1619
  * Test whether a destination still holds what was captured of it.
1618
1620
  *
1619
1621
  * @param expectation - The state captured earlier.
1620
- * @returns `true` when re-reading the destination now produces that same state.
1622
+ * @returns `true` when re-reading the destination produces that same state.
1621
1623
  *
1622
1624
  * @remarks
1623
1625
  * Compared field for field against a fresh {@link readExpectation}, so an
@@ -1678,7 +1680,7 @@ function matchesPrecondition(precondition) {
1678
1680
  * has not touched the target at all. Commit is the only step that mutates the
1679
1681
  * target, and it is the only step that can need rolling back.
1680
1682
  *
1681
- * Two bindings hold a destination still. A **precondition** is what the caller
1683
+ * A precondition and an expectation hold a destination still. A **precondition** is what the caller
1682
1684
  * observed earlier and is checked once, at construction, so a target that moved
1683
1685
  * between the caller's read and this transaction fails before anything is
1684
1686
  * created. An **expectation** is captured here, at construction, and re-checked
@@ -1702,7 +1704,7 @@ function matchesPrecondition(precondition) {
1702
1704
  * elsewhere, or nothing is refused. An ancestor deleted and recreated under
1703
1705
  * the same name can receive its old inode back and is indistinguishable here
1704
1706
  * from one that never moved.
1705
- * - **No crash atomicity across destinations.** A process killed between two
1707
+ * - **No crash atomicity across destinations.** A process killed between
1706
1708
  * promotions leaves the target holding some new files and some old ones, and
1707
1709
  * leaves the private root behind. Nothing here is a journal, and the private
1708
1710
  * root's name is the only record a later run could read.
@@ -1835,7 +1837,7 @@ var WriteTransaction = class {
1835
1837
  * Stage one text file.
1836
1838
  *
1837
1839
  * @param path - The target-relative path to write.
1838
- * @param content - The exact UTF-8 text the destination should hold.
1840
+ * @param content - The exact UTF-8 text the destination must hold.
1839
1841
  * @returns Nothing.
1840
1842
  * @throws {@link ScaffoldError} coded `INVALID` when the path is not one this
1841
1843
  * transaction opened or is already staged, `TARGET` when the destination holds
@@ -1867,7 +1869,7 @@ var WriteTransaction = class {
1867
1869
  *
1868
1870
  * @param path - The target-relative path to write.
1869
1871
  * @param source - The resolved absolute path to copy the bytes from.
1870
- * @param executable - Whether the destination should carry the executable bit.
1872
+ * @param executable - If `true`, the destination carries the executable bit; if `false`, it does not.
1871
1873
  * @returns Nothing.
1872
1874
  * @throws {@link ScaffoldError} coded `INVALID` when the path is not one this
1873
1875
  * transaction opened or is already staged, `TARGET` when the destination holds
@@ -1917,7 +1919,7 @@ var WriteTransaction = class {
1917
1919
  * created segment is captured by device and inode, so a segment swapped
1918
1920
  * underneath the transaction is detected rather than written into.
1919
1921
  */
1920
- directory(path) {
1922
+ establish(path) {
1921
1923
  this.#assertOpen();
1922
1924
  if (this.#expectation(path).shape === "file") throw new _src_core.ScaffoldError("TARGET", `The destination at ${path} holds a file.`, { path });
1923
1925
  const established = (0, _orkestrel_contract.attempt)(() => this.#establish(this.#resolve(this.#target, path)));
@@ -2180,7 +2182,7 @@ var WriteTransaction = class {
2180
2182
  * The mutation spine: read the vendored host, re-derive the target, stage, swap.
2181
2183
  *
2182
2184
  * @remarks
2183
- * Every verb runs the same three steps. It snapshots each caller-supplied value
2185
+ * Every verb runs the same steps. It snapshots each caller-supplied value
2184
2186
  * and guards the snapshot, so a property backed by an accessor never reaches a
2185
2187
  * decision. It re-derives what it is about to touch and compares that against
2186
2188
  * the observation the caller handed in, refusing the whole call when anything
@@ -2403,7 +2405,7 @@ var Materializer = class Materializer {
2403
2405
  /**
2404
2406
  * Rewrite the marker-bounded package table in the target's catalog agent file.
2405
2407
  *
2406
- * @param entries - The published packages the table should list.
2408
+ * @param entries - The published packages the table must list.
2407
2409
  * @param target - The directory to write into.
2408
2410
  * @returns The catalog path, written when the region's bytes moved and skipped otherwise.
2409
2411
  * @throws {@link ScaffoldError} coded `INVALID` when an argument is not the
@@ -2412,7 +2414,7 @@ var Materializer = class Materializer {
2412
2414
  * `DESTROYED` after teardown.
2413
2415
  *
2414
2416
  * @remarks
2415
- * Only the text between the two markers is replaced, so every word a consumer
2417
+ * Only the text between the markers is replaced, so every word a consumer
2416
2418
  * wrote around the table survives the call. A row whose lookup produced no
2417
2419
  * version prints the cause it carries instead, because dropping the row would
2418
2420
  * hide a package the organization publishes behind one failed request.
@@ -2426,7 +2428,7 @@ var Materializer = class Materializer {
2426
2428
  /**
2427
2429
  * Rewrite the `@orkestrel/*` range set in the target's manifest.
2428
2430
  *
2429
- * @param dependencies - The names and ranges the manifest should declare.
2431
+ * @param dependencies - The names and ranges the manifest must declare.
2430
2432
  * @param target - The directory to write into.
2431
2433
  * @returns The manifest path, written when a declared range moved and skipped otherwise.
2432
2434
  * @throws {@link ScaffoldError} coded `INVALID` when an argument is not the
@@ -2448,9 +2450,10 @@ var Materializer = class Materializer {
2448
2450
  return this.#rewrite(directory, "package.json", _src_core.MAX_MANIFEST_BYTES, this.#redeclare(accepted));
2449
2451
  }
2450
2452
  /**
2451
- * Delete the files the plan does not own.
2453
+ * Re-derive and delete the tracked files the plan does not own.
2452
2454
  *
2453
- * @param audit - The preview returned by this materializer's `audit` method; its foreign findings are the candidate set.
2455
+ * @param plan - The compiled plan that decides which paths are foreign.
2456
+ * @param audit - The preview returned by this materializer's `audit` method; it must agree with the candidate set this call re-derives.
2454
2457
  * @param repository - The target's git state; only a tracked path is ever deleted.
2455
2458
  * @param target - The directory to delete from.
2456
2459
  * @returns The paths removed.
@@ -2467,9 +2470,14 @@ var Materializer = class Materializer {
2467
2470
  * the audit reports, and neither is anything git does not track: git is the
2468
2471
  * recovery mechanism, so a path it cannot restore is not one this verb takes.
2469
2472
  * A tree carrying uncommitted work is refused whole for the same reason.
2473
+ *
2474
+ * The whole call refuses when the preview disagrees with the re-derivation on
2475
+ * any foreign finding, including one the deletion itself would skip, because a
2476
+ * preview stale anywhere is stale evidence.
2470
2477
  */
2471
- remove(audit, repository, target) {
2478
+ remove(plan, audit, repository, target) {
2472
2479
  this.#assertAlive();
2480
+ const accepted = this.#accept(plan, _src_core.isPlan, "plan");
2473
2481
  const preview = this.#accept(audit, _src_core.isAudit, "audit");
2474
2482
  const state = this.#accept(repository, isRepository, "repository");
2475
2483
  const directory = this.#accept(target, isFilesystemPath, "target");
@@ -2477,28 +2485,21 @@ var Materializer = class Materializer {
2477
2485
  target: directory,
2478
2486
  dirty: state.dirty.length
2479
2487
  });
2488
+ const derived = this.#derive(accepted, directory);
2489
+ this.#reconfirmCandidates(derived.findings, preview.findings, directory);
2480
2490
  const tracked = new Set(state.tracked);
2481
- const observed = /* @__PURE__ */ new Map();
2482
2491
  const removals = [];
2483
2492
  const skipped = [];
2484
- for (const finding of preview.findings) {
2493
+ for (const finding of derived.findings) {
2485
2494
  if (finding.drift !== "foreign") continue;
2486
2495
  if (!tracked.has(finding.path) || matchesProtectedPath(finding.path)) {
2487
2496
  skipped.push(finding.path);
2488
2497
  continue;
2489
2498
  }
2490
- observed.set(finding.path, finding.observed);
2491
2499
  removals.push(finding.path);
2492
2500
  }
2493
- const current = readSnapshot(directory, removals);
2494
2501
  const preconditions = [];
2495
- for (const path of removals) {
2496
- if (current[path] !== observed.get(path)) throw this.#error("TARGET", `The path ${path} moved since its audit.`, {
2497
- target: directory,
2498
- path
2499
- });
2500
- preconditions.push(this.#bind(directory, path, false));
2501
- }
2502
+ for (const path of removals) preconditions.push(this.#bind(directory, path, false));
2502
2503
  return this.#purge(directory, removals, skipped, preconditions);
2503
2504
  }
2504
2505
  /**
@@ -2729,6 +2730,35 @@ var Materializer = class Materializer {
2729
2730
  });
2730
2731
  }
2731
2732
  }
2733
+ #reconfirmCandidates(derived, preview, target) {
2734
+ const current = derived.filter((finding) => finding.drift === "foreign");
2735
+ const supplied = preview.filter((finding) => finding.drift === "foreign");
2736
+ const candidates = new Map(current.map((finding) => [finding.path, finding]));
2737
+ const previewed = new Map(supplied.map((finding) => [finding.path, finding]));
2738
+ if (candidates.size !== current.length || previewed.size !== supplied.length) throw this.#error("TARGET", "The audit repeats a deletion candidate.", { target });
2739
+ for (const finding of supplied) {
2740
+ const candidate = candidates.get(finding.path);
2741
+ if (candidate === void 0) throw this.#error("TARGET", `The path ${finding.path} is not a deletion candidate for this plan.`, {
2742
+ target,
2743
+ path: finding.path
2744
+ });
2745
+ if (candidate.group !== finding.group) throw this.#error("TARGET", `The path ${finding.path} carries a group this plan does not derive.`, {
2746
+ target,
2747
+ path: finding.path
2748
+ });
2749
+ if (candidate.observed !== finding.observed) throw this.#error("TARGET", `The path ${finding.path} moved since its audit.`, {
2750
+ target,
2751
+ path: finding.path
2752
+ });
2753
+ }
2754
+ for (const finding of current) {
2755
+ if (previewed.has(finding.path)) continue;
2756
+ throw this.#error("TARGET", `The path ${finding.path} is not covered by its audit.`, {
2757
+ target,
2758
+ path: finding.path
2759
+ });
2760
+ }
2761
+ }
2732
2762
  #bind(target, path, absent) {
2733
2763
  const destination = resolveContainedPath(target, path);
2734
2764
  if (destination === void 0) throw this.#error("INVALID", `The path ${path} is off contract or leaves its target.`, {
@@ -2783,7 +2813,7 @@ var Materializer = class Materializer {
2783
2813
  const staged = (0, _orkestrel_contract.attempt)(() => {
2784
2814
  for (const artifact of writes) if (artifact.origin === "host") this.#copy(transaction, artifact);
2785
2815
  else transaction.write(artifact.path, artifact.content);
2786
- for (const path of directories) transaction.directory(path);
2816
+ for (const path of directories) transaction.establish(path);
2787
2817
  });
2788
2818
  const written = this.#close(transaction, staged, target);
2789
2819
  for (const path of written) this.#emitter.emit("write", path);
@@ -2961,7 +2991,7 @@ var Materializer = class Materializer {
2961
2991
  * This is the package's only network reader, and it never writes. Every call
2962
2992
  * opens one byte allowance and spends it across every read the call makes, so a
2963
2993
  * caller is bounded twice over: `limit` refuses one oversized answer and
2964
- * `budget` refuses many small ones. The two are separate exhaustion routes and
2994
+ * `budget` refuses many small ones. They are separate exhaustion routes and
2965
2995
  * neither bound covers the other.
2966
2996
  *
2967
2997
  * A per-package failure never escapes as a throw. It is projected into the
@@ -3017,7 +3047,7 @@ var Upstream = class Upstream {
3017
3047
  /**
3018
3048
  * Construct a reader over one guide host and one registry.
3019
3049
  *
3020
- * @param options - The two endpoints, the request bounds, the initial
3050
+ * @param options - The endpoints, the request bounds, the initial
3021
3051
  * listeners, and the listener-error handler.
3022
3052
  * @throws {@link ScaffoldError} coded `INVALID` when `options` is present but
3023
3053
  * is not an option bag this reader accepts, or when either endpoint names a
@@ -3027,7 +3057,7 @@ var Upstream = class Upstream {
3027
3057
  * `isEndpoint` bounds an endpoint's length and nothing else, so the scheme and
3028
3058
  * host law is settled here, where a refusal can say which endpoint was refused
3029
3059
  * and why. An endpoint must be HTTPS, or HTTP to a loopback host — the one
3030
- * place an unencrypted request has no network between the two ends. That
3060
+ * place an unencrypted request has no network between its ends. That
3031
3061
  * refuses `file:`, `data:`, and plain HTTP to a real host, and it is what
3032
3062
  * keeps a fixture reachable without weakening transport security anywhere a
3033
3063
  * real request goes. An endpoint carrying credentials, a query, or a fragment
@@ -3099,7 +3129,7 @@ var Upstream = class Upstream {
3099
3129
  * always answers for the file it names. `observed` is carried through from
3100
3130
  * `current` whatever the lookup produced, because it is the precondition the
3101
3131
  * later write is held to and a failed fetch does not change what the target
3102
- * currently holds.
3132
+ * holds.
3103
3133
  *
3104
3134
  * @example
3105
3135
  * ```ts
@@ -3459,49 +3489,6 @@ var Upstream = class Upstream {
3459
3489
  }
3460
3490
  };
3461
3491
  //#endregion
3462
- //#region src/server/factories.ts
3463
- /**
3464
- * Construct a {@link Materializer}.
3465
- *
3466
- * @param options - The vendored host root, the initial listeners, and the listener-error handler.
3467
- * @returns The materializer, typed as the contract consumers program against.
3468
- * @throws {@link ScaffoldError} coded `INVALID` when `options` is present but is
3469
- * not an option bag the materializer accepts, and `TARGET` when the host carries
3470
- * a manifest that cannot be read or does not match what it stores.
3471
- *
3472
- * @example
3473
- * ```ts
3474
- * import { createMaterializer } from '@orkestrel/scaffold/server'
3475
- *
3476
- * const materializer = createMaterializer({ host: './dist/host' })
3477
- * materializer.destroy()
3478
- * ```
3479
- */
3480
- function createMaterializer(options) {
3481
- return new Materializer(options);
3482
- }
3483
- /**
3484
- * Construct an {@link Upstream}.
3485
- *
3486
- * @param options - The two endpoints, the request bounds, the initial listeners,
3487
- * and the listener-error handler.
3488
- * @returns The reader, typed as the contract consumers program against.
3489
- * @throws {@link ScaffoldError} coded `INVALID` when `options` is present but is
3490
- * not an option bag the reader accepts, or when either endpoint names a scheme,
3491
- * host, or form the reader will not request.
3492
- *
3493
- * @example
3494
- * ```ts
3495
- * import { createUpstream } from '@orkestrel/scaffold/server'
3496
- *
3497
- * const upstream = createUpstream({ guides: { branch: 'main' } })
3498
- * upstream.destroy()
3499
- * ```
3500
- */
3501
- function createUpstream(options) {
3502
- return new Upstream(options);
3503
- }
3504
- //#endregion
3505
3492
  exports.BRANCH_PATTERN = BRANCH_PATTERN;
3506
3493
  exports.DIGEST_PATTERN = DIGEST_PATTERN;
3507
3494
  exports.DRIVE_PATTERN = DRIVE_PATTERN;
@@ -3522,8 +3509,6 @@ exports.WriteTransaction = WriteTransaction;
3522
3509
  exports.computeDigest = computeDigest;
3523
3510
  exports.computeFileDigest = computeFileDigest;
3524
3511
  exports.computeManifestDigest = computeManifestDigest;
3525
- exports.createMaterializer = createMaterializer;
3526
- exports.createUpstream = createUpstream;
3527
3512
  exports.isBranch = isBranch;
3528
3513
  exports.isCatalogEntries = isCatalogEntries;
3529
3514
  exports.isDependencies = isDependencies;