@orkestrel/scaffold 0.0.77 → 0.0.78

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/dist/agents/skills/orkestrel-dispatch/scripts/bench.js +204 -0
  2. package/dist/agents/skills/orkestrel-dispatch/scripts/brief.js +102 -0
  3. package/dist/agents/skills/orkestrel-dispatch/scripts/cite.js +95 -0
  4. package/dist/agents/skills/orkestrel-dispatch/scripts/helpers.js +207 -0
  5. package/dist/agents/skills/orkestrel-dispatch/scripts/launch.js +108 -0
  6. package/dist/agents/skills/orkestrel-dispatch/scripts/login.js +114 -0
  7. package/dist/agents/skills/orkestrel-dispatch/scripts/result.js +108 -0
  8. package/dist/agents/skills/orkestrel-dispatch/scripts/sweep.js +156 -0
  9. package/dist/agents/skills/orkestrel-harden/scripts/discovery.js +196 -0
  10. package/dist/agents/skills/orkestrel-publish/scripts/compare.js +206 -0
  11. package/dist/agents/skills/orkestrel-publish/scripts/pins.js +93 -0
  12. package/dist/agents/skills/orkestrel-publish/scripts/wave.js +458 -0
  13. package/dist/agents/skills/orkestrel-publish/scripts/window.js +188 -0
  14. package/dist/agents/skills/orkestrel-scout/scripts/map.js +300 -0
  15. package/dist/agents/templates/brief.md +55 -0
  16. package/dist/bin/main.js +4 -2
  17. package/dist/bin/main.js.map +1 -1
  18. package/dist/host/AGENTS.md +77 -135
  19. package/dist/host/agents/orchestration.md +147 -998
  20. package/dist/host/agents/skills/enterprise-bootstrap/SKILL.md +2 -2
  21. package/dist/host/agents/skills/enterprise-bootstrap/references/inspection.md +1 -1
  22. package/dist/host/agents/skills/{orkestrel-align-packages → orkestrel-align}/SKILL.md +6 -13
  23. package/dist/host/agents/skills/{orkestrel-align-packages → orkestrel-align}/agents/openai.yaml +1 -1
  24. package/dist/host/agents/skills/{orkestrel-align-packages → orkestrel-align}/references/fleet.md +5 -7
  25. package/dist/host/agents/skills/{orkestrel-build-application → orkestrel-build}/SKILL.md +11 -22
  26. package/dist/host/agents/skills/{orkestrel-build-application → orkestrel-build}/agents/openai.yaml +1 -1
  27. package/dist/host/agents/skills/orkestrel-debrief/SKILL.md +8 -16
  28. package/dist/host/agents/skills/orkestrel-debrief/references/instruction-audit.md +3 -3
  29. package/dist/host/agents/skills/orkestrel-debrief/references/retention.md +13 -13
  30. package/dist/host/agents/skills/orkestrel-dispatch/SKILL.md +61 -0
  31. package/dist/host/agents/skills/orkestrel-dispatch/agents/openai.yaml +4 -0
  32. package/dist/host/agents/skills/orkestrel-dispatch/references/bench.md +25 -0
  33. package/dist/host/agents/skills/orkestrel-dispatch/references/launch.md +32 -0
  34. package/dist/host/agents/skills/orkestrel-dispatch/scripts/bench.ts +259 -0
  35. package/dist/host/agents/skills/orkestrel-dispatch/scripts/brief.ts +110 -0
  36. package/dist/host/agents/skills/orkestrel-dispatch/scripts/cite.ts +115 -0
  37. package/dist/host/agents/skills/orkestrel-dispatch/scripts/helpers.ts +239 -0
  38. package/dist/host/agents/skills/orkestrel-dispatch/scripts/launch.ts +124 -0
  39. package/dist/host/agents/skills/orkestrel-dispatch/scripts/login.ts +123 -0
  40. package/dist/host/agents/skills/orkestrel-dispatch/scripts/result.ts +129 -0
  41. package/dist/host/agents/skills/orkestrel-dispatch/scripts/sweep.ts +157 -0
  42. package/dist/host/agents/skills/orkestrel-falsify/SKILL.md +42 -193
  43. package/dist/host/agents/skills/orkestrel-falsify/references/brief.md +38 -108
  44. package/dist/host/agents/skills/orkestrel-falsify/references/reconcile.md +35 -134
  45. package/dist/host/agents/skills/{orkestrel-harden-package → orkestrel-harden}/SKILL.md +10 -14
  46. package/dist/host/agents/skills/{orkestrel-harden-package → orkestrel-harden}/agents/openai.yaml +1 -1
  47. package/dist/host/agents/skills/{orkestrel-harden-package → orkestrel-harden}/references/hardening.md +3 -4
  48. package/dist/host/agents/skills/orkestrel-harden/scripts/discovery.ts +228 -0
  49. package/dist/host/agents/skills/{orkestrel-prove-journey → orkestrel-journey}/SKILL.md +15 -23
  50. package/dist/host/agents/skills/orkestrel-journey/agents/openai.yaml +4 -0
  51. package/dist/host/agents/skills/{orkestrel-prove-journey → orkestrel-journey}/references/captures.md +1 -1
  52. package/dist/host/agents/skills/{orkestrel-polish-surface → orkestrel-polish}/SKILL.md +25 -33
  53. package/dist/host/agents/skills/{orkestrel-polish-surface → orkestrel-polish}/agents/openai.yaml +1 -1
  54. package/dist/host/agents/skills/{orkestrel-polish-surface → orkestrel-polish}/references/capture-harness.md +3 -3
  55. package/dist/host/agents/skills/orkestrel-publish/SKILL.md +33 -20
  56. package/dist/host/agents/skills/orkestrel-publish/references/release.md +39 -0
  57. package/dist/host/agents/skills/orkestrel-publish/references/wave.md +22 -21
  58. package/dist/host/agents/skills/orkestrel-publish/references/window.md +27 -14
  59. package/dist/host/agents/skills/orkestrel-publish/scripts/compare.ts +220 -0
  60. package/dist/host/agents/skills/orkestrel-publish/scripts/pins.ts +114 -0
  61. package/dist/host/agents/skills/orkestrel-publish/scripts/wave.ts +629 -0
  62. package/dist/host/agents/skills/orkestrel-publish/scripts/window.ts +242 -0
  63. package/dist/host/agents/skills/orkestrel-scout/SKILL.md +28 -0
  64. package/dist/host/agents/skills/orkestrel-scout/agents/openai.yaml +4 -0
  65. package/dist/host/agents/skills/orkestrel-scout/scripts/map.ts +352 -0
  66. package/dist/host/agents/templates/brief.md +21 -142
  67. package/dist/host/agents/transports/claude-cli.md +21 -0
  68. package/dist/host/agents/transports/codex.md +38 -159
  69. package/dist/host/agents/transports/cursor.md +16 -65
  70. package/dist/host/claude/AGENTS.md +38 -0
  71. package/dist/host/claude/agents/analyst.md +14 -53
  72. package/dist/host/claude/agents/astra.md +26 -0
  73. package/dist/host/claude/agents/builder.md +14 -30
  74. package/dist/host/claude/agents/checker.md +13 -57
  75. package/dist/host/claude/agents/distiller.md +11 -26
  76. package/dist/host/claude/agents/grok.md +12 -35
  77. package/dist/host/claude/agents/opus.md +14 -30
  78. package/dist/host/claude/agents/planner.md +10 -44
  79. package/dist/host/claude/agents/researcher.md +11 -30
  80. package/dist/host/claude/agents/reviewer.md +11 -95
  81. package/dist/host/claude/agents/scout.md +9 -23
  82. package/dist/host/claude/agents/verifier.md +15 -33
  83. package/dist/host/claude/rules/documentation.md +8 -2
  84. package/dist/host/claude/rules/portability.md +7 -1
  85. package/dist/host/claude/rules/quality.md +36 -96
  86. package/dist/host/claude/rules/styles.md +3 -0
  87. package/dist/host/claude/rules/tests.md +6 -3
  88. package/dist/host/claude/rules/workspace.md +19 -15
  89. package/dist/host/claude/rules/writing.md +57 -108
  90. package/dist/host/claude/settings.json +5 -3
  91. package/dist/host/claude/skills/enterprise-bootstrap/SKILL.md +1 -1
  92. package/dist/host/claude/skills/{orkestrel-align-packages → orkestrel-align}/SKILL.md +2 -2
  93. package/dist/host/claude/skills/{orkestrel-build-application → orkestrel-build}/SKILL.md +2 -2
  94. package/dist/host/claude/skills/orkestrel-dispatch/SKILL.md +11 -0
  95. package/dist/host/claude/skills/orkestrel-falsify/SKILL.md +2 -1
  96. package/dist/host/claude/skills/{orkestrel-harden-package → orkestrel-harden}/SKILL.md +2 -2
  97. package/dist/host/claude/skills/{orkestrel-prove-journey → orkestrel-journey}/SKILL.md +2 -2
  98. package/dist/host/claude/skills/orkestrel-polish/SKILL.md +12 -0
  99. package/dist/host/claude/skills/orkestrel-scout/SKILL.md +11 -0
  100. package/dist/host/codex/agents/analyst.toml +14 -31
  101. package/dist/host/codex/agents/astra.toml +25 -0
  102. package/dist/host/codex/agents/builder.toml +13 -20
  103. package/dist/host/codex/agents/checker.toml +13 -27
  104. package/dist/host/codex/agents/distiller.toml +9 -22
  105. package/dist/host/codex/agents/grok.toml +11 -30
  106. package/dist/host/codex/agents/opus.toml +14 -22
  107. package/dist/host/codex/agents/orkestrel.toml +1 -1
  108. package/dist/host/codex/agents/planner.toml +11 -28
  109. package/dist/host/codex/agents/researcher.toml +10 -22
  110. package/dist/host/codex/agents/reviewer.toml +11 -27
  111. package/dist/host/codex/agents/scout.toml +11 -17
  112. package/dist/host/codex/agents/verifier.toml +16 -12
  113. package/dist/host/codex/config.toml +18 -21
  114. package/dist/host/cursor/mcp.json +0 -4
  115. package/dist/host/cursor/rules/orchestration.mdc +12 -20
  116. package/dist/host/dotfiles/mcp.json +0 -4
  117. package/dist/host/dotfiles/oxlintrc.json +7 -0
  118. package/dist/host/guides/probe.md +9 -9
  119. package/dist/host/guides/scaffold.md +117 -71
  120. package/dist/host/guides/test.md +1 -1
  121. package/dist/host/manifest.json +321 -184
  122. package/dist/host/scripts/codex.sh +0 -0
  123. package/dist/host/scripts/cursor.sh +0 -0
  124. package/dist/host/scripts/deps.sh +0 -0
  125. package/dist/host/scripts/ollama.sh +0 -0
  126. package/dist/host/tests/config.test.ts +68 -46
  127. package/dist/host/tests/policy.test.ts +1 -5
  128. package/dist/host/tests/setupPolicy.ts +179 -4
  129. package/dist/src/core/index.cjs +255 -84
  130. package/dist/src/core/index.cjs.map +1 -1
  131. package/dist/src/core/index.d.cts +94 -29
  132. package/dist/src/core/index.d.ts +94 -29
  133. package/dist/src/core/index.js +253 -85
  134. package/dist/src/core/index.js.map +1 -1
  135. package/dist/src/server/index.cjs +55 -9
  136. package/dist/src/server/index.cjs.map +1 -1
  137. package/dist/src/server/index.d.cts +29 -4
  138. package/dist/src/server/index.d.ts +29 -4
  139. package/dist/src/server/index.js +56 -11
  140. package/dist/src/server/index.js.map +1 -1
  141. package/package.json +15 -11
  142. package/dist/host/CLAUDE.md +0 -61
  143. package/dist/host/agents/skills/orkestrel-prove-journey/agents/openai.yaml +0 -4
  144. package/dist/host/agents/transports/claude.md +0 -49
  145. package/dist/host/claude/agents/application.md +0 -36
  146. package/dist/host/claude/agents/sol.md +0 -61
  147. package/dist/host/claude/skills/orkestrel-polish-surface/SKILL.md +0 -12
  148. package/dist/host/codex/agents/application.toml +0 -25
  149. package/dist/host/codex/agents/sol.toml +0 -19
  150. /package/dist/host/agents/skills/{orkestrel-align-packages → orkestrel-align}/references/integration.md +0 -0
  151. /package/dist/host/agents/skills/{orkestrel-harden-package → orkestrel-harden}/references/centralization.md +0 -0
  152. /package/dist/host/agents/skills/{orkestrel-harden-package → orkestrel-harden}/references/contract.md +0 -0
  153. /package/dist/host/agents/skills/{orkestrel-harden-package → orkestrel-harden}/references/research.md +0 -0
  154. /package/dist/host/agents/skills/{orkestrel-prove-journey → orkestrel-journey}/references/decide.md +0 -0
  155. /package/dist/host/agents/skills/{orkestrel-prove-journey → orkestrel-journey}/references/layer.md +0 -0
  156. /package/dist/host/agents/skills/{orkestrel-prove-journey → orkestrel-journey}/references/statechart.md +0 -0
  157. /package/dist/host/agents/skills/{orkestrel-prove-journey → orkestrel-journey}/references/styles.md +0 -0
@@ -111,6 +111,29 @@ export declare function computeFileDigest(path: string): string | undefined;
111
111
  */
112
112
  export declare function computeManifestDigest(entries: readonly ManifestEntry[], roots: readonly string[], surface: readonly SurfaceCollision[]): string;
113
113
 
114
+ /**
115
+ * Decodes exact bytes stated in hexadecimal as strict UTF-8 text.
116
+ *
117
+ * @param hex - The exact lowercase hexadecimal bytes to decode.
118
+ * @returns The decoded text, or `undefined` when the bytes are not valid UTF-8.
119
+ * @throws Thrown when `hex` is not exact bounded lowercase hexadecimal text; the error is a
120
+ * `ScaffoldError` coded `INVALID`.
121
+ *
122
+ * @remarks
123
+ * Decoding is strict, so an invalid sequence answers `undefined` rather than
124
+ * text carrying replacement characters: every caller parses or derives from the
125
+ * text next, and a lossy decode would hand it bytes the file never held.
126
+ *
127
+ * @example
128
+ * ```ts
129
+ * import { decodeHexText } from '@orkestrel/scaffold/server'
130
+ *
131
+ * decodeHexText('e282ac0a') // '€\n'
132
+ * decodeHexText('fffe00') // undefined
133
+ * ```
134
+ */
135
+ export declare function decodeHexText(hex: string): string | undefined;
136
+
114
137
  /** Holds the repository branch a raw content read addresses when a caller names none. */
115
138
  export declare const DEFAULT_BRANCH = "main";
116
139
 
@@ -209,8 +232,8 @@ export declare function filesToHost(files: readonly HostFile[], floor: Host): Ho
209
232
  *
210
233
  * @param hex - The exact lowercase hexadecimal bytes to digest.
211
234
  * @returns Sixty-four lowercase hexadecimal digits.
212
- * @throws `ScaffoldError('INVALID', …)` when `hex` is not exact bounded
213
- * lowercase hexadecimal text.
235
+ * @throws Thrown when `hex` is not exact bounded lowercase hexadecimal text; the error is a
236
+ * `ScaffoldError` coded `INVALID`.
214
237
  *
215
238
  * @example
216
239
  * ```ts
@@ -805,7 +828,7 @@ export declare function listDirectories(root: string): readonly string[];
805
828
  * ```ts
806
829
  * import { listFiles } from '@orkestrel/scaffold/server'
807
830
  *
808
- * listFiles('./dist/host') // ['AGENTS.md', 'CLAUDE.md', 'LICENSE', …]
831
+ * listFiles('./dist/host') // ['AGENTS.md', 'LICENSE', 'agents', …]
809
832
  * ```
810
833
  */
811
834
  export declare function listFiles(root: string): readonly string[];
@@ -2050,7 +2073,9 @@ export declare class Materializer implements MaterializerInterface {
2050
2073
  * whichever path the plan reached first. Refusing here fails the build that
2051
2074
  * produced it, where the maintainer can act, and it names every missing path at
2052
2075
  * once. A directory is the same case — declaring an absent directory as an empty
2053
- * root would create an empty directory in every generated workspace.
2076
+ * root would create an empty directory in every generated workspace. A canon file
2077
+ * member the checkout no longer holds is the one exception: scaffold keeps owning
2078
+ * the path so a target's copy reports foreign, and the stage ships nothing for it.
2054
2079
  *
2055
2080
  * The walk covers `HOST_PATHS`, `CANON_PATHS`, and `REFERENCE_PATHS` together.
2056
2081
  * A plan selects the paths a target receives; the installed package also carries
@@ -111,6 +111,29 @@ export declare function computeFileDigest(path: string): string | undefined;
111
111
  */
112
112
  export declare function computeManifestDigest(entries: readonly ManifestEntry[], roots: readonly string[], surface: readonly SurfaceCollision[]): string;
113
113
 
114
+ /**
115
+ * Decodes exact bytes stated in hexadecimal as strict UTF-8 text.
116
+ *
117
+ * @param hex - The exact lowercase hexadecimal bytes to decode.
118
+ * @returns The decoded text, or `undefined` when the bytes are not valid UTF-8.
119
+ * @throws Thrown when `hex` is not exact bounded lowercase hexadecimal text; the error is a
120
+ * `ScaffoldError` coded `INVALID`.
121
+ *
122
+ * @remarks
123
+ * Decoding is strict, so an invalid sequence answers `undefined` rather than
124
+ * text carrying replacement characters: every caller parses or derives from the
125
+ * text next, and a lossy decode would hand it bytes the file never held.
126
+ *
127
+ * @example
128
+ * ```ts
129
+ * import { decodeHexText } from '@orkestrel/scaffold/server'
130
+ *
131
+ * decodeHexText('e282ac0a') // '€\n'
132
+ * decodeHexText('fffe00') // undefined
133
+ * ```
134
+ */
135
+ export declare function decodeHexText(hex: string): string | undefined;
136
+
114
137
  /** Holds the repository branch a raw content read addresses when a caller names none. */
115
138
  export declare const DEFAULT_BRANCH = "main";
116
139
 
@@ -209,8 +232,8 @@ export declare function filesToHost(files: readonly HostFile[], floor: Host): Ho
209
232
  *
210
233
  * @param hex - The exact lowercase hexadecimal bytes to digest.
211
234
  * @returns Sixty-four lowercase hexadecimal digits.
212
- * @throws `ScaffoldError('INVALID', …)` when `hex` is not exact bounded
213
- * lowercase hexadecimal text.
235
+ * @throws Thrown when `hex` is not exact bounded lowercase hexadecimal text; the error is a
236
+ * `ScaffoldError` coded `INVALID`.
214
237
  *
215
238
  * @example
216
239
  * ```ts
@@ -805,7 +828,7 @@ export declare function listDirectories(root: string): readonly string[];
805
828
  * ```ts
806
829
  * import { listFiles } from '@orkestrel/scaffold/server'
807
830
  *
808
- * listFiles('./dist/host') // ['AGENTS.md', 'CLAUDE.md', 'LICENSE', …]
831
+ * listFiles('./dist/host') // ['AGENTS.md', 'LICENSE', 'agents', …]
809
832
  * ```
810
833
  */
811
834
  export declare function listFiles(root: string): readonly string[];
@@ -2050,7 +2073,9 @@ export declare class Materializer implements MaterializerInterface {
2050
2073
  * whichever path the plan reached first. Refusing here fails the build that
2051
2074
  * produced it, where the maintainer can act, and it names every missing path at
2052
2075
  * once. A directory is the same case — declaring an absent directory as an empty
2053
- * root would create an empty directory in every generated workspace.
2076
+ * root would create an empty directory in every generated workspace. A canon file
2077
+ * member the checkout no longer holds is the one exception: scaffold keeps owning
2078
+ * the path so a target's copy reports foreign, and the stage ships nothing for it.
2054
2079
  *
2055
2080
  * The walk covers `HOST_PATHS`, `CANON_PATHS`, and `REFERENCE_PATHS` together.
2056
2081
  * A plan selects the paths a target receives; the installed package also carries
@@ -1,6 +1,6 @@
1
1
  import { createRequire } from "node:module";
2
2
  import { andOf, arrayOf, attempt, boundsOf, compareValues, holds, isArray, isBoolean, isError, isFunction, isInteger, isNumber, isRecord, isString, parseJSON, parseJSONAs, parseStringField, recordOf, stringOf, unionOf, whereOf } from "@orkestrel/contract";
3
- import { CANON_PATHS, CATALOG_AGENT_PATH, CATALOG_CLOSING_MARKER, CATALOG_OPENING_MARKER, CONTROL_CHARACTER_PATTERN, DEPENDENCY_NAME_PATTERN, EXECUTABLE_PATHS, HOST_INVENTORY_PATH, HOST_PATHS, MAX_ARTIFACT_BYTES, MAX_COLLECTION_ITEMS, MAX_DEPENDENCY_NAME_LENGTH, MAX_MANIFEST_BYTES, MAX_PATH_LENGTH, MAX_RANGE_LENGTH, MAX_REGISTRY_BYTES, MAX_TOTAL_ARTIFACT_BYTES, MAX_TOTAL_REGISTRY_BYTES, REFERENCE_PATHS, ScaffoldError, bytesToHex, catalogToLayers, cloneValue, compareVersions, computeBytes, contentToHex, extractRangeMajor, extractVersion, inferGroup, isAudit, isCatalogEntry, isCollection, isDependency, isDependencyName, isFloorPath, isHex, isManifestScript, isMirror, isPath, isPlan, isRetainedPath, isSnapshot, matchesDriftReachability, matchesRange, nameToGuide, planToFindings, replaceManifestRanges, replaceManifestScripts } from "../core/index.js";
3
+ import { CANON_PATHS, CATALOG_AGENT_PATH, CATALOG_CLOSING_MARKER, CATALOG_OPENING_MARKER, CONTROL_CHARACTER_PATTERN, DEPENDENCY_NAME_PATTERN, EXECUTABLE_PATHS, HOST_INVENTORY_PATH, HOST_PATHS, MAX_ARTIFACT_BYTES, MAX_COLLECTION_ITEMS, MAX_DEPENDENCY_NAME_LENGTH, MAX_MANIFEST_BYTES, MAX_PATH_LENGTH, MAX_RANGE_LENGTH, MAX_REGISTRY_BYTES, MAX_TOTAL_ARTIFACT_BYTES, MAX_TOTAL_REGISTRY_BYTES, REFERENCE_PATHS, ScaffoldError, bytesToHex, catalogToLayers, cloneValue, compareVersions, computeBytes, contentToHex, extractRangeMajor, extractVersion, inferGroup, isAudit, isCatalogEntry, isCollection, isDependency, isDependencyName, isFloorPath, isHex, isManifestScript, isMirror, isPath, isPlan, isRetainedPath, isSnapshot, matchesDriftReachability, matchesRange, nameToGuide, planToFindings, renderSkillPointer, replaceManifestRanges, replaceManifestScripts } from "../core/index.js";
4
4
  import { createHash, randomUUID } from "node:crypto";
5
5
  import { chmodSync, closeSync, constants, copyFileSync, fstatSync, linkSync, lstatSync, mkdirSync, mkdtempSync, openSync, opendirSync, readSync, readdirSync, readlinkSync, realpathSync, renameSync, rmSync, rmdirSync, writeFileSync } from "node:fs";
6
6
  import { tmpdir } from "node:os";
@@ -354,8 +354,8 @@ function computeDigest(content) {
354
354
  *
355
355
  * @param hex - The exact lowercase hexadecimal bytes to digest.
356
356
  * @returns Sixty-four lowercase hexadecimal digits.
357
- * @throws `ScaffoldError('INVALID', …)` when `hex` is not exact bounded
358
- * lowercase hexadecimal text.
357
+ * @throws Thrown when `hex` is not exact bounded lowercase hexadecimal text; the error is a
358
+ * `ScaffoldError` coded `INVALID`.
359
359
  *
360
360
  * @example
361
361
  * ```ts
@@ -369,6 +369,32 @@ function hexToDigest(hex) {
369
369
  return createHash("sha256").update(Buffer.from(hex, "hex")).digest("hex");
370
370
  }
371
371
  /**
372
+ * Decodes exact bytes stated in hexadecimal as strict UTF-8 text.
373
+ *
374
+ * @param hex - The exact lowercase hexadecimal bytes to decode.
375
+ * @returns The decoded text, or `undefined` when the bytes are not valid UTF-8.
376
+ * @throws Thrown when `hex` is not exact bounded lowercase hexadecimal text; the error is a
377
+ * `ScaffoldError` coded `INVALID`.
378
+ *
379
+ * @remarks
380
+ * Decoding is strict, so an invalid sequence answers `undefined` rather than
381
+ * text carrying replacement characters: every caller parses or derives from the
382
+ * text next, and a lossy decode would hand it bytes the file never held.
383
+ *
384
+ * @example
385
+ * ```ts
386
+ * import { decodeHexText } from '@orkestrel/scaffold/server'
387
+ *
388
+ * decodeHexText('e282ac0a') // '€\n'
389
+ * decodeHexText('fffe00') // undefined
390
+ * ```
391
+ */
392
+ function decodeHexText(hex) {
393
+ if (!isHex(hex)) throw new ScaffoldError("INVALID", "Decode input is not exact hexadecimal bytes", { hex });
394
+ const decoded = attempt(() => new TextDecoder("utf-8", { fatal: true }).decode(Buffer.from(hex, "hex")));
395
+ return decoded.success ? decoded.value : void 0;
396
+ }
397
+ /**
372
398
  * Computes the digest of a vendored host's declared membership.
373
399
  *
374
400
  * @param entries - The ordered file membership declarations.
@@ -724,7 +750,7 @@ function isVacant(target) {
724
750
  * ```ts
725
751
  * import { listFiles } from '@orkestrel/scaffold/server'
726
752
  *
727
- * listFiles('./dist/host') // ['AGENTS.md', 'CLAUDE.md', 'LICENSE', …]
753
+ * listFiles('./dist/host') // ['AGENTS.md', 'LICENSE', 'agents', …]
728
754
  * ```
729
755
  */
730
756
  function listFiles(root) {
@@ -1059,9 +1085,7 @@ function readFileHex(root, path, limit = MAX_ARTIFACT_BYTES) {
1059
1085
  */
1060
1086
  function readFileText(root, path, limit = MAX_ARTIFACT_BYTES) {
1061
1087
  const hex = readFileHex(root, path, limit);
1062
- if (hex === void 0) return void 0;
1063
- const decoded = attempt(() => new TextDecoder("utf-8", { fatal: true }).decode(Buffer.from(hex, "hex")));
1064
- return decoded.success ? decoded.value : void 0;
1088
+ return hex === void 0 ? void 0 : decodeHexText(hex);
1065
1089
  }
1066
1090
  /**
1067
1091
  * Reads a target's current bytes at the paths a plan claims.
@@ -1447,7 +1471,9 @@ function stageBytes(host, root, destinations) {
1447
1471
  * whichever path the plan reached first. Refusing here fails the build that
1448
1472
  * produced it, where the maintainer can act, and it names every missing path at
1449
1473
  * once. A directory is the same case — declaring an absent directory as an empty
1450
- * root would create an empty directory in every generated workspace.
1474
+ * root would create an empty directory in every generated workspace. A canon file
1475
+ * member the checkout no longer holds is the one exception: scaffold keeps owning
1476
+ * the path so a target's copy reports foreign, and the stage ships nothing for it.
1451
1477
  *
1452
1478
  * The walk covers `HOST_PATHS`, `CANON_PATHS`, and `REFERENCE_PATHS` together.
1453
1479
  * A plan selects the paths a target receives; the installed package also carries
@@ -1496,7 +1522,7 @@ function stageHost(checkout, host, options) {
1496
1522
  continue;
1497
1523
  }
1498
1524
  if (!isPhysicalDirectory(full)) {
1499
- missing.push(path);
1525
+ if (!CANON_PATHS.includes(path)) missing.push(path);
1500
1526
  continue;
1501
1527
  }
1502
1528
  roots.push(path);
@@ -3282,7 +3308,7 @@ var Materializer = class {
3282
3308
  continue;
3283
3309
  }
3284
3310
  const expanded = this.#expand(artifact, remaining);
3285
- for (const one of expanded) remaining -= (one.hex?.length ?? 0) / 2;
3311
+ for (const one of expanded) remaining -= one.origin === "host" ? (one.hex?.length ?? 0) / 2 : computeBytes(one.content);
3286
3312
  artifacts.push(...expanded);
3287
3313
  }
3288
3314
  if (remaining < 0) throw this.#error("TARGET", "The hydrated plan retains more bytes than one plan may.", {
@@ -3444,6 +3470,14 @@ var Materializer = class {
3444
3470
  };
3445
3471
  }
3446
3472
  #hydrated(artifact, path, destination, hex) {
3473
+ if ("pointer" in artifact && artifact.pointer === true) return {
3474
+ path,
3475
+ group: artifact.group,
3476
+ ownership: "content",
3477
+ origin: "computed",
3478
+ ...artifact.environment === void 0 ? {} : { environment: artifact.environment },
3479
+ content: this.#point(path, destination, hex)
3480
+ };
3447
3481
  return {
3448
3482
  path,
3449
3483
  group: artifact.group,
@@ -3454,6 +3488,17 @@ var Materializer = class {
3454
3488
  hex
3455
3489
  };
3456
3490
  }
3491
+ #point(path, destination, hex) {
3492
+ const name = path.endsWith("/SKILL.md") ? path.split("/").at(-2) : void 0;
3493
+ const decoded = decodeHexText(hex);
3494
+ const pointer = name === void 0 || decoded === void 0 ? void 0 : renderSkillPointer(decoded, name);
3495
+ if (pointer === void 0) throw this.#error("TARGET", `The vendored skill at ${destination} cannot derive the pointer at ${path}.`, {
3496
+ host: this.#root,
3497
+ source: destination,
3498
+ path
3499
+ });
3500
+ return pointer;
3501
+ }
3457
3502
  #read(entry, budget) {
3458
3503
  const held = this.#value?.bytes[entry.destination];
3459
3504
  if (held === void 0) return this.#readRoot(entry.storage, budget);
@@ -4480,6 +4525,6 @@ var Upstream = class {
4480
4525
  }
4481
4526
  };
4482
4527
  //#endregion
4483
- export { BRANCH_PATTERN, DEFAULT_BRANCH, DEFAULT_REGISTRY_BASE, DEFAULT_REPOSITORY_BASE, DEFAULT_UPSTREAM_CONCURRENCY, DEFAULT_UPSTREAM_RETRIES, DEFAULT_UPSTREAM_TIMEOUT, DIGEST_PATTERN, DRIVE_PATTERN, INVALID_SEGMENT_CHARACTER_PATTERN, MANIFEST_NAME, MAX_BRANCH_LENGTH, MAX_ENDPOINT_LENGTH, MAX_INVENTORY_PATHS, MAX_PATH_DEPTH, MAX_PATH_SEGMENT_BYTES, MAX_UPSTREAM_CONCURRENCY, MAX_UPSTREAM_RETRIES, MAX_UPSTREAM_TIMEOUT, Materializer, ORKESTREL_SCOPE, PACKUMENT_MEDIA_TYPE, RESERVED_SEGMENT_PATTERN, SCAFFOLD_REPOSITORY, UNREADABLE_VERSION_NOTE, Upstream, WriteTransaction, computeDigest, computeFileDigest, computeManifestDigest, filesToHost, hexToDigest, isBranch, isCatalogEntries, isDependencies, isDependencyNames, isDigest, isEndpoint, isExactCaseFile, isFilesystemPath, isHost, isHostManifest, isInventory, isManifestEntry, isManifestRegionSet, isMaterializerHooks, isMaterializerOptions, isMirrors, isPaths, isPhysicalDirectory, isPhysicalFile, isTimeout, isUpstreamHooks, isUpstreamOptions, isVacant, isWorktree, listCanonPaths, listDirectories, listFiles, matchesAnchor, matchesExecutablePath, matchesExpectation, matchesGitPath, matchesMissingPath, matchesPrecondition, matchesProtectedPath, matchesSensitivePath, pathToStorage, pruneEmptiedDirectories, readAnchor, readExpectation, readFileHex, readFileText, readHostFloor, readHostManifest, readManifestEntry, readSnapshot, readSurfaceBaseline, readSurfaceCollisions, resolveContainedPath, resolveRealPath, stageBytes, stageHost, stageInventory };
4528
+ export { BRANCH_PATTERN, DEFAULT_BRANCH, DEFAULT_REGISTRY_BASE, DEFAULT_REPOSITORY_BASE, DEFAULT_UPSTREAM_CONCURRENCY, DEFAULT_UPSTREAM_RETRIES, DEFAULT_UPSTREAM_TIMEOUT, DIGEST_PATTERN, DRIVE_PATTERN, INVALID_SEGMENT_CHARACTER_PATTERN, MANIFEST_NAME, MAX_BRANCH_LENGTH, MAX_ENDPOINT_LENGTH, MAX_INVENTORY_PATHS, MAX_PATH_DEPTH, MAX_PATH_SEGMENT_BYTES, MAX_UPSTREAM_CONCURRENCY, MAX_UPSTREAM_RETRIES, MAX_UPSTREAM_TIMEOUT, Materializer, ORKESTREL_SCOPE, PACKUMENT_MEDIA_TYPE, RESERVED_SEGMENT_PATTERN, SCAFFOLD_REPOSITORY, UNREADABLE_VERSION_NOTE, Upstream, WriteTransaction, computeDigest, computeFileDigest, computeManifestDigest, decodeHexText, filesToHost, hexToDigest, isBranch, isCatalogEntries, isDependencies, isDependencyNames, isDigest, isEndpoint, isExactCaseFile, isFilesystemPath, isHost, isHostManifest, isInventory, isManifestEntry, isManifestRegionSet, isMaterializerHooks, isMaterializerOptions, isMirrors, isPaths, isPhysicalDirectory, isPhysicalFile, isTimeout, isUpstreamHooks, isUpstreamOptions, isVacant, isWorktree, listCanonPaths, listDirectories, listFiles, matchesAnchor, matchesExecutablePath, matchesExpectation, matchesGitPath, matchesMissingPath, matchesPrecondition, matchesProtectedPath, matchesSensitivePath, pathToStorage, pruneEmptiedDirectories, readAnchor, readExpectation, readFileHex, readFileText, readHostFloor, readHostManifest, readManifestEntry, readSnapshot, readSurfaceBaseline, readSurfaceCollisions, resolveContainedPath, resolveRealPath, stageBytes, stageHost, stageInventory };
4484
4529
 
4485
4530
  //# sourceMappingURL=index.js.map