@orkestrel/scaffold 0.0.76 → 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 (154) 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 -927
  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 +15 -32
  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 +20 -23
  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 +322 -185
  122. package/dist/host/scripts/codex.sh +2 -2
  123. package/dist/host/tests/config.test.ts +68 -46
  124. package/dist/host/tests/policy.test.ts +1 -5
  125. package/dist/host/tests/setupPolicy.ts +179 -4
  126. package/dist/src/core/index.cjs +255 -84
  127. package/dist/src/core/index.cjs.map +1 -1
  128. package/dist/src/core/index.d.cts +94 -29
  129. package/dist/src/core/index.d.ts +94 -29
  130. package/dist/src/core/index.js +253 -85
  131. package/dist/src/core/index.js.map +1 -1
  132. package/dist/src/server/index.cjs +55 -9
  133. package/dist/src/server/index.cjs.map +1 -1
  134. package/dist/src/server/index.d.cts +29 -4
  135. package/dist/src/server/index.d.ts +29 -4
  136. package/dist/src/server/index.js +56 -11
  137. package/dist/src/server/index.js.map +1 -1
  138. package/package.json +15 -11
  139. package/dist/host/CLAUDE.md +0 -61
  140. package/dist/host/agents/skills/orkestrel-prove-journey/agents/openai.yaml +0 -4
  141. package/dist/host/agents/transports/claude.md +0 -49
  142. package/dist/host/claude/agents/application.md +0 -36
  143. package/dist/host/claude/agents/sol.md +0 -61
  144. package/dist/host/claude/skills/orkestrel-polish-surface/SKILL.md +0 -12
  145. package/dist/host/codex/agents/application.toml +0 -25
  146. package/dist/host/codex/agents/sol.toml +0 -19
  147. /package/dist/host/agents/skills/{orkestrel-align-packages → orkestrel-align}/references/integration.md +0 -0
  148. /package/dist/host/agents/skills/{orkestrel-harden-package → orkestrel-harden}/references/centralization.md +0 -0
  149. /package/dist/host/agents/skills/{orkestrel-harden-package → orkestrel-harden}/references/contract.md +0 -0
  150. /package/dist/host/agents/skills/{orkestrel-harden-package → orkestrel-harden}/references/research.md +0 -0
  151. /package/dist/host/agents/skills/{orkestrel-prove-journey → orkestrel-journey}/references/decide.md +0 -0
  152. /package/dist/host/agents/skills/{orkestrel-prove-journey → orkestrel-journey}/references/layer.md +0 -0
  153. /package/dist/host/agents/skills/{orkestrel-prove-journey → orkestrel-journey}/references/statechart.md +0 -0
  154. /package/dist/host/agents/skills/{orkestrel-prove-journey → orkestrel-journey}/references/styles.md +0 -0
@@ -4,7 +4,7 @@ let _orkestrel_template = require("@orkestrel/template");
4
4
  let _orkestrel_emitter = require("@orkestrel/emitter");
5
5
  var package_default = {
6
6
  name: "@orkestrel/scaffold",
7
- version: "0.0.76",
7
+ version: "0.0.78",
8
8
  description: "Scaffold workspaces with commands: new, audit, repair, catalog, and overwrite.",
9
9
  keywords: [
10
10
  "audit",
@@ -25,6 +25,7 @@ var package_default = {
25
25
  "dist/src",
26
26
  "dist/bin",
27
27
  "dist/host",
28
+ "dist/agents",
28
29
  "README.md"
29
30
  ],
30
31
  type: "module",
@@ -60,56 +61,59 @@ var package_default = {
60
61
  "copy": "node -e \"const fs=require('node:fs'),p=require('node:path'),a=process.argv[1],b=process.argv[2];fs.mkdirSync(p.dirname(b),{recursive:true});fs.cpSync(a,b,{force:true});console.log('Copied: '+a+' to '+b)\"",
61
62
  "scaffold": "node ./dist/bin/main.js",
62
63
  "lint": "oxlint --config .oxlintrc.json --fix .",
63
- "check": "tsc --noEmit --project tsconfig.json && npm run check:src",
64
+ "check": "tsc --noEmit --project tsconfig.json && npm run check:src && npm run check:skills",
64
65
  "check:src": "npm run check:src:core && npm run check:src:server && npm run check:src:bin",
65
66
  "check:src:core": "tsc --noEmit -p configs/src/tsconfig.core.json",
66
67
  "check:src:server": "tsc --noEmit -p configs/src/tsconfig.server.json",
67
68
  "check:src:bin": "tsc --noEmit -p configs/src/tsconfig.bin.json",
69
+ "check:skills": "tsc --noEmit -p configs/agents/tsconfig.skills.json",
68
70
  "format": "oxfmt --config .oxfmtrc.json --write .",
69
71
  "format:check": "oxfmt --config .oxfmtrc.json --check .",
70
72
  "lint:check": "oxlint --config .oxlintrc.json --deny-warnings .",
71
- "test": "npm run test:src:core && npm run test:src:server && npm run test:src:bin && npm run test:policy && npm run test:config && npm run test:setup && npm run test:guides",
73
+ "test": "npm run test:src:core && npm run test:src:server && npm run test:src:bin && npm run test:policy && npm run test:config && npm run test:setup && npm run test:skills && npm run test:guides",
72
74
  "test:src:core": "vitest run --config vite.config.ts --no-cache --reporter=dot --project src:core",
73
75
  "test:src:server": "vitest run --config vite.config.ts --no-cache --reporter=dot --project src:server",
74
76
  "test:src:bin": "vitest run --config vite.config.ts --no-cache --reporter=dot --project src:bin",
75
77
  "test:policy": "vitest run --config vite.config.ts --no-cache --reporter=dot --project policy",
76
78
  "test:config": "vitest run --config vite.config.ts --no-cache --reporter=dot --project config",
77
79
  "test:guides": "node --experimental-strip-types tests/guides.test.ts",
80
+ "test:skills": "vitest run --config vite.config.ts --no-cache --reporter=dot --project skills",
78
81
  "test:distribution": "vitest run --config vite.config.ts --no-cache --reporter=dot --project distribution",
79
82
  "test:probe": "vitest run --config vite.config.ts --no-cache --reporter=verbose --project probe",
80
83
  "test:bench": "vitest bench --config vite.config.ts --no-cache --project probe",
81
84
  "test:setup": "vitest run --config vite.config.ts --no-cache --reporter=dot --project setup",
82
- "build": "npm run clean && npm run build:src && npm run build:host && npm run build:inventory",
85
+ "build": "npm run clean && npm run build:src && npm run build:host && npm run build:skills && npm run build:inventory",
83
86
  "build:src": "npm run build:src:core && npm run build:src:server && npm run build:src:bin",
84
87
  "build:src:core": "vite build --config configs/src/vite.core.config.ts && npm run copy dist/src/core/index.d.ts dist/src/core/index.d.cts",
85
88
  "build:src:server": "vite build --config configs/src/vite.server.config.ts && npm run copy dist/src/server/index.d.ts dist/src/server/index.d.cts",
86
89
  "build:src:bin": "vite build --config configs/src/vite.bin.config.ts",
87
90
  "build:host": "node -e \"import('./dist/src/server/index.js').then((m)=>{const n=m.stageHost(process.cwd(),'dist/host',{report: (message) => console.error(message)}).length;console.log('build-host: staged '+n+' file(s) into dist/host')})\"",
88
91
  "build:inventory": "node -e \"import('./dist/src/server/index.js').then((m)=>{const p=process.argv[1]??'host.json',n=m.stageInventory(process.cwd(),p).entries.length;console.log('build-inventory: staged '+n+' file(s) into '+p)})\"",
92
+ "build:skills": "tsc -p configs/agents/tsconfig.skills.json --noEmit false --allowImportingTsExtensions false --rewriteRelativeImportExtensions --declaration false --sourceMap false --rootDir .agents/skills --outDir dist/agents/skills && npm run copy .agents/templates/brief.md dist/agents/templates/brief.md",
89
93
  "prepack": "npm run build",
90
94
  "prepublishOnly": "npm run format:check && npm run lint:check && npm run check && npm run build && npm test && npm run test:distribution -- --mode release"
91
95
  },
92
96
  dependencies: {
93
97
  "@orkestrel/console": "^0.0.14",
94
- "@orkestrel/contract": "^0.0.17",
98
+ "@orkestrel/contract": "^0.0.18",
95
99
  "@orkestrel/emitter": "^0.0.10",
96
100
  "@orkestrel/markdown": "^0.0.15",
97
101
  "@orkestrel/process": "^0.0.13",
98
102
  "@orkestrel/template": "^0.0.8"
99
103
  },
100
104
  devDependencies: {
101
- "@microsoft/api-extractor": "^7.59.1",
105
+ "@microsoft/api-extractor": "^7.59.3",
102
106
  "@orkestrel/guide": "^0.0.20",
103
107
  "@orkestrel/html": "^0.0.10",
104
108
  "@orkestrel/probe": "^0.0.16",
105
- "@orkestrel/test": "^0.0.18",
106
- "@types/node": "^26.5.1",
109
+ "@orkestrel/test": "^0.0.24",
110
+ "@types/node": "^26.6.3",
107
111
  "@vitest/browser-playwright": "^4.1.11",
108
- "oxfmt": "^0.68.0",
109
- "oxlint": "^1.83.0",
112
+ "oxfmt": "^0.71.0",
113
+ "oxlint": "^1.86.0",
110
114
  "playwright": "^1.63.0",
111
115
  "typescript": "^6.0.3",
112
- "vite": "^8.3.0",
116
+ "vite": "^8.3.1",
113
117
  "vitest": "^4.1.11"
114
118
  },
115
119
  engines: { "node": ">=22.18.0" }
@@ -257,8 +261,8 @@ var HOST_PATHS = Object.freeze([
257
261
  * Staging walks these beside {@link HOST_PATHS}, so a release ships them and a
258
262
  * reader reaches them two ways: a scaffold checkout sitting beside the
259
263
  * repository, or the `node_modules/@orkestrel/scaffold/dist/host/` root inside
260
- * the installed package. The `AGENTS.md` and `CLAUDE.md` pointers scaffold plans
261
- * are what name each location.
264
+ * the installed package. The `AGENTS.md` pointer scaffold plans is what names
265
+ * each location.
262
266
  *
263
267
  * This list, {@link HOST_PATHS}, and {@link REFERENCE_PATHS} are disjoint by
264
268
  * prefix in every direction: no member equals or sits beneath another list's
@@ -267,18 +271,22 @@ var HOST_PATHS = Object.freeze([
267
271
  * name twice, which refuses the stage.
268
272
  *
269
273
  * The plan claims paths inside the canon deliberately, and each has a reason.
270
- * `blueprintToDocumentArtifacts` claims `AGENTS.md` and `CLAUDE.md` as this
271
- * package's own template pointers. `blueprintToHostArtifacts` claims
274
+ * `blueprintToDocumentArtifacts` claims `AGENTS.md` as this package's own
275
+ * template pointer. `blueprintToHostArtifacts` claims
272
276
  * {@link CATALOG_AGENT_PATH}, because the catalog verb refuses a target that
273
277
  * lacks the file and repair restores its absence.
274
278
  *
275
279
  * A target therefore holds a file at a canon path only where the plan claims it.
276
280
  * That is the rule every verb obeys, and it is what makes a copy found anywhere
277
- * else superseded.
281
+ * else superseded. A member this checkout no longer holds, `CLAUDE.md` since
282
+ * Claude Code began reading `AGENTS.md` directly, stays listed for exactly that
283
+ * reason: the stager ships nothing for it, `audit` reports a target's copy
284
+ * `foreign`, and `overwrite` deletes it.
278
285
  */
279
286
  var CANON_PATHS = Object.freeze([
280
287
  "AGENTS.md",
281
288
  "CLAUDE.md",
289
+ ".claude/AGENTS.md",
282
290
  ".mcp.json",
283
291
  ".agents/orchestration.md",
284
292
  ".agents/skills",
@@ -400,6 +408,26 @@ var CATALOG_OPENING_MARKER = "<!-- orkestrel:catalog -->";
400
408
  * refused rather than rewritten.
401
409
  */
402
410
  var CATALOG_CLOSING_MARKER = "<!-- /orkestrel:catalog -->";
411
+ /**
412
+ * Lists the package-facing skills a target receives pointers for, frozen and alphabetical.
413
+ *
414
+ * @remarks
415
+ * `blueprintToHostArtifacts` plans, for each name, the Claude bridge, the Codex
416
+ * sidecar, and the derived `SKILL.md` pointer, so every harness discovers the
417
+ * skill while its body, references, and scripts stay in the installed package.
418
+ * `orkestrel-align`, `orkestrel-dispatch`, `orkestrel-publish`, and
419
+ * `orkestrel-scout` are excluded because they run from the scaffold checkout
420
+ * and a target is not an orchestration host.
421
+ */
422
+ var TARGET_SKILL_NAMES = Object.freeze([
423
+ "enterprise-bootstrap",
424
+ "orkestrel-build",
425
+ "orkestrel-debrief",
426
+ "orkestrel-falsify",
427
+ "orkestrel-harden",
428
+ "orkestrel-journey",
429
+ "orkestrel-polish"
430
+ ]);
403
431
  /** Names the inventory skeleton a workspace with declared service vendors is given once. */
404
432
  var SERVICE_SCRIPT_PATH = "scripts/service.sh";
405
433
  /** Names the shared Vitest global-setup module whose presence makes a workspace `global`. */
@@ -437,6 +465,8 @@ var SERVICE_TEST_INCLUDE = "tests/service/**/*.test.ts";
437
465
  var SHOWCASE_CONFIG_PATH = "configs/app/vite.showcase.config.ts";
438
466
  /** Names the Vite wrapper whose presence makes a workspace `journey`. */
439
467
  var JOURNEY_CONFIG_PATH = "configs/app/vite.journey.config.ts";
468
+ /** Names the TypeScript wrapper whose presence makes a workspace `skills`. */
469
+ var SKILLS_CONFIG_PATH = "configs/agents/tsconfig.skills.json";
440
470
  /** Matches the bare workspace name syntax: lowercase alphanumeric with hyphens, letter first. */
441
471
  var NAME_PATTERN = /^[a-z][a-z0-9-]*$/;
442
472
  /**
@@ -713,7 +743,11 @@ const resolve = {
713
743
  // override receives that record in the same position. A \`UserConfig\` declares \`mode\`
714
744
  // but not \`command\`, and the invocation record always carries both, so a value
715
745
  // carrying the pair is that record rather than an override. The merge returns the
716
- // base unchanged and reports nothing. The \`tests/config.test.ts\` file drives every
746
+ // base in the record's \`mode\` and carries none of the record's other fields. Vitest
747
+ // runs a project that declares no \`mode\` in its own run mode, \`test\`, rather than in
748
+ // the \`--mode\` value it was invoked with, so a distribution proof run with
749
+ // \`--mode release\` would read \`test\` and skip where it must fail. A record whose
750
+ // \`mode\` is not a string throws. The \`tests/config.test.ts\` file drives every
717
751
  // registered factory through it.
718
752
  //
719
753
  // \`mergeConfig\` concatenates arrays, so an override carrying \`plugins\` would otherwise
@@ -726,7 +760,13 @@ const resolve = {
726
760
  // merges it, so an override's arrays elsewhere concatenate with the base's rather than
727
761
  // replacing them.
728
762
  export function mergeOverride(base: UserConfig, override?: UserConfig): UserConfig {
729
- if (override === undefined || ('command' in override && 'mode' in override)) return base
763
+ if (override === undefined) return base
764
+ if ('command' in override && 'mode' in override) {
765
+ if (typeof override.mode !== 'string') {
766
+ throw new Error('The project invocation carries no string mode')
767
+ }
768
+ return { ...base, mode: override.mode }
769
+ }
730
770
  const merged: UserConfig = mergeConfig(base, override)
731
771
  if (merged.plugins === undefined) return merged
732
772
  const candidates = override.plugins ?? []
@@ -1135,6 +1175,25 @@ export function appShowcase(override?: UserConfig): UserConfig {
1135
1175
  }
1136
1176
  return mergeOverride(project, override)
1137
1177
  }
1178
+ `,
1179
+ skills: `// The skill scripts this package ships as canon, each driven as a child process against a
1180
+ // scratch fixture from its mirrored proof under \`tests/agents/skills/<skill>/scripts/\`. The
1181
+ // \`configs/agents/tsconfig.skills.json\` wrapper selects the project.
1182
+ export function skills(override?: UserConfig): UserConfig {
1183
+ const project: UserConfig = {
1184
+ resolve,
1185
+ test: {
1186
+ name: { label: 'skills', color: 'blue' },
1187
+ include: ['tests/agents/**/*.test.ts'],
1188
+ setupFiles: ['./tests/setup.ts'],
1189
+ environment: 'node',
1190
+ browser: { enabled: false },
1191
+ // Each case spawns node on a script; a census case runs \`vitest list\` over this checkout.
1192
+ testTimeout: 60_000,
1193
+ },
1194
+ }
1195
+ return mergeOverride(project, override)
1196
+ }
1138
1197
  `,
1139
1198
  conformance: `// Where this package drifts from the official tooling it stays compatible with.
1140
1199
  // The subject is this package, so the proof is hermetic and stays in \`npm test\`.
@@ -1189,7 +1248,7 @@ export function service(override?: UserConfig): UserConfig {
1189
1248
  }
1190
1249
  `,
1191
1250
  probe: `// A workbench, not a proof. No gate selects this project. Run in test mode by the
1192
- // \`test:probe\` script, it collects \`tmp/probe/**/*.test.ts\`. Run in benchmark mode by the
1251
+ // \`test:probe\` script, it collects \`tmp/probes/**/*.test.ts\`. Run in benchmark mode by the
1193
1252
  // \`test:bench\` script, the same workbench also collects \`tests/**/*.test.ts\` for a \`bench\` block,
1194
1253
  // so a suite may carry a bench beside its ordinary tests without a second project. The mode
1195
1254
  // guard around each \`bench\` call keeps it out of test mode, so it never executes there.
@@ -1198,13 +1257,13 @@ export function probe(override?: UserConfig): UserConfig {
1198
1257
  resolve,
1199
1258
  test: {
1200
1259
  name: { label: 'probe', color: 'black' },
1201
- include: ['tmp/probe/**/*.test.ts'],
1260
+ include: ['tmp/probes/**/*.test.ts'],
1202
1261
  setupFiles: ['./tests/setup.ts'],
1203
1262
  environment: 'node',
1204
1263
  browser: { enabled: false },
1205
1264
  fileParallelism: false,
1206
1265
  pool: 'threads',
1207
- benchmark: { include: ['tmp/probe/**/*.test.ts', 'tests/**/*.test.ts'] },
1266
+ benchmark: { include: ['tmp/probes/**/*.test.ts', 'tests/**/*.test.ts'] },
1208
1267
  },
1209
1268
  }
1210
1269
  return mergeOverride(project, override)
@@ -1345,6 +1404,16 @@ export function probe(override?: UserConfig): UserConfig {
1345
1404
  "../../src/bin/**/*.tsx"
1346
1405
  ]
1347
1406
  }
1407
+ `,
1408
+ skills: `{
1409
+ "extends": "../../tsconfig.json",
1410
+ "compilerOptions": {
1411
+ "lib": ["ESNext"],
1412
+ "types": ["node"]
1413
+ },
1414
+ "include": ["../../.agents/skills/*/scripts/*.ts"],
1415
+ "exclude": ["../../node_modules"]
1416
+ }
1348
1417
  `
1349
1418
  }),
1350
1419
  vites: Object.freeze({
@@ -1885,7 +1954,8 @@ const TSC = createRequire(join(ROOT, 'package.json')).resolve('typescript/bin/ts
1885
1954
  // rather than an exit code a caller can read. Every following argument is a literal or
1886
1955
  // a path this file built, so the shell has nothing to escape.
1887
1956
  const SHELL = process.platform === 'win32'
1888
- // \`prepublishOnly\` runs this proof as \`npm run test:distribution -- --mode release\`.
1957
+ // \`prepublishOnly\` runs this proof as \`npm run test:distribution -- --mode release\`,
1958
+ // and the root configuration's project factories carry that mode into this project.
1889
1959
  // Release is the publish gate, so evidence it cannot obtain fails there and skips
1890
1960
  // everywhere else: a gate that passes on missing evidence proves nothing.
1891
1961
  const RELEASE = import.meta.env.MODE === 'release'
@@ -2958,20 +3028,21 @@ Resolve every one of those paths against scaffold, never against this repository
2958
3028
  \`node_modules/@orkestrel/scaffold/dist/host/claude/rules/\` directory, and the
2959
3029
  \`node_modules/@orkestrel/scaffold/dist/host/agents/skills/\` directory.
2960
3030
 
2961
- Every path a scaffold-supplied file names resolves the same way. The files this repository carries
3031
+ Every path a scaffold-supplied file names resolves the same way. Run a script such a file names
3032
+ through its built twin: replace \`node .agents/skills/\` with
3033
+ \`node node_modules/@orkestrel/scaffold/dist/agents/skills/\` and the \`.ts\` extension with \`.js\`,
3034
+ because Node runs no \`.ts\` file under \`node_modules\`. The files this repository carries
2962
3035
  — the \`.claude/agents/orkestrel.md\` catalog file, the \`.claude/settings.json\` permission file,
2963
- and the bench scripts under \`scripts/\` — are this repository's own copies and resolve here.
3036
+ the bench scripts under \`scripts/\`, and the skill pointers under \`.agents/skills/\` and
3037
+ \`.claude/skills/\`, which name the canonical skills and how to run their scripts — are this
3038
+ repository's own copies and resolve here.
3039
+
3040
+ In Claude Code, also read the Claude bridge: \`../scaffold/.claude/AGENTS.md\` beside a checkout, or
3041
+ \`node_modules/@orkestrel/scaffold/dist/host/claude/AGENTS.md\` from the installed copy. Keep no
3042
+ \`CLAUDE.md\` in this repository; one stops Claude Code from reading this file.
2964
3043
 
2965
3044
  Edit none of the scaffold-owned files here. The \`scaffold repair\` command restores them, so a
2966
3045
  change to one is a commit in the scaffold repository followed by a release.
2967
- `,
2968
- claude: `# CLAUDE.md
2969
-
2970
- Read the \`AGENTS.md\` file in this repository first. It names the coding and orchestration
2971
- authority and where to read each contract.
2972
-
2973
- This file imports nothing. An \`@path\` import inlines the imported file into every context that
2974
- loads it, which is the cost this pointer removes.
2975
3046
  `
2976
3047
  }),
2977
3048
  guides: Object.freeze({ readme: `# Guides
@@ -2990,12 +3061,28 @@ loads it, which is the cost this pointer removes.
2990
3061
 
2991
3062
  {{directories}}
2992
3063
  ` }),
2993
- orchestration: Object.freeze({ service: `#!/usr/bin/env sh
3064
+ orchestration: Object.freeze({
3065
+ skill: `
3066
+ # Load the canonical skill
3067
+
3068
+ This file is a pointer the \`@orkestrel/scaffold\` package writes into every fleet workspace; the
3069
+ skill itself ships with that package. Read the canonical \`SKILL.md\` completely and follow it:
3070
+
3071
+ - beside a scaffold checkout, \`../scaffold/.agents/skills/{{name}}/SKILL.md\`;
3072
+ - otherwise, \`node_modules/@orkestrel/scaffold/dist/host/agents/skills/{{name}}/SKILL.md\`.
3073
+
3074
+ Resolve every path the canonical skill names against the same root; under \`node_modules\` each
3075
+ segment drops its opening dot. Run a script the skill names through its built twin, as this
3076
+ repository's \`AGENTS.md\` states. This pointer carries no process of its own; \`AGENTS.md\`, the applicable
3077
+ rules, and the canonical skill remain authoritative in that order.
3078
+ `,
3079
+ service: `#!/usr/bin/env sh
2994
3080
  set -eu
2995
3081
 
2996
3082
  printf '%s\\n' \\
2997
3083
  {{vendors}}
2998
- ` })
3084
+ `
3085
+ })
2999
3086
  });
3000
3087
  //#endregion
3001
3088
  //#region src/core/errors.ts
@@ -3320,7 +3407,8 @@ var isBlueprint = (0, _orkestrel_contract.recordOf)({
3320
3407
  vendors: (0, _orkestrel_contract.andOf)(isCollection, (0, _orkestrel_contract.arrayOf)(_orkestrel_contract.isString)),
3321
3408
  global: _orkestrel_contract.isBoolean,
3322
3409
  showcase: _orkestrel_contract.isBoolean,
3323
- journey: _orkestrel_contract.isBoolean
3410
+ journey: _orkestrel_contract.isBoolean,
3411
+ skills: _orkestrel_contract.isBoolean
3324
3412
  }, ["description"]);
3325
3413
  /**
3326
3414
  * Narrows a value to an {@link Artifact}.
@@ -3345,8 +3433,13 @@ var isArtifact = (0, _orkestrel_contract.unionOf)((0, _orkestrel_contract.record
3345
3433
  ownership: (0, _orkestrel_contract.literalOf)("presence", "birth"),
3346
3434
  environment: isEnvironment,
3347
3435
  origin: (0, _orkestrel_contract.literalOf)("host"),
3348
- source: isPath
3349
- }, ["environment", "source"]), (0, _orkestrel_contract.recordOf)({
3436
+ source: isPath,
3437
+ pointer: _orkestrel_contract.isBoolean
3438
+ }, [
3439
+ "environment",
3440
+ "source",
3441
+ "pointer"
3442
+ ]), (0, _orkestrel_contract.recordOf)({
3350
3443
  path: isPath,
3351
3444
  group: isGroup,
3352
3445
  ownership: (0, _orkestrel_contract.literalOf)("content"),
@@ -3845,10 +3938,11 @@ function isDeferredPath(path) {
3845
3938
  * boundary, so a sibling whose name opens with a member's name —
3846
3939
  * `.claude/rulesets` beside `.claude/rules` — stays outside.
3847
3940
  *
3848
- * Membership answers where a path's bytes are staged, not whether a plan claims
3849
- * it. A plan claims `AGENTS.md`, `CLAUDE.md`, and {@link CATALOG_AGENT_PATH} at
3850
- * canon paths deliberately, so a consumer deciding whether to write, restore, or
3851
- * remove a path reads the plan rather than this predicate.
3941
+ * Membership answers whether scaffold owns the path, not whether a plan claims
3942
+ * it. A plan claims `AGENTS.md` and {@link CATALOG_AGENT_PATH} at canon paths
3943
+ * deliberately, so a consumer deciding whether to write, restore, or remove a
3944
+ * path reads the plan rather than this predicate. A member the checkout no
3945
+ * longer holds is still canon, so a copy a target keeps reports as foreign.
3852
3946
  *
3853
3947
  * @example
3854
3948
  * ```ts
@@ -4644,6 +4738,36 @@ function manifestToDependencies(manifest) {
4644
4738
  peer: (0, _orkestrel_contract.limitEntries)(peer, MAX_COLLECTION_ITEMS)
4645
4739
  };
4646
4740
  }
4741
+ /**
4742
+ * Renders the `SKILL.md` pointer a target carries in place of a canonical skill.
4743
+ *
4744
+ * @param canonical - The canonical `SKILL.md` text, which opens with a frontmatter block.
4745
+ * @param name - The skill directory name the pointer body names.
4746
+ * @returns The canonical frontmatter block copied line for line, from its opening `---` line through
4747
+ * its closing `---` line, then the filled `ARTIFACT_TEMPLATES.orchestration.skill` body, with `\n`
4748
+ * line endings; `undefined` when the canonical text does not open with a complete frontmatter block.
4749
+ *
4750
+ * @remarks
4751
+ * The frontmatter is copied rather than rewritten, so every harness that
4752
+ * discovers the pointer reads the canonical `name` and `description` and
4753
+ * triggers the skill exactly as the canonical file would. A CRLF canonical
4754
+ * text yields the same pointer as its LF form.
4755
+ *
4756
+ * @example
4757
+ * ```ts
4758
+ * import { renderSkillPointer } from '@orkestrel/scaffold'
4759
+ *
4760
+ * renderSkillPointer('---\nname: orkestrel-harden\ndescription: Hardens a package.\n---\n\n# Harden\n', 'orkestrel-harden')?.startsWith('---\nname: orkestrel-harden\ndescription: Hardens a package.\n---\n\n# Load the canonical skill\n') // true
4761
+ * renderSkillPointer('# Harden\n', 'orkestrel-harden') // undefined
4762
+ * ```
4763
+ */
4764
+ function renderSkillPointer(canonical, name) {
4765
+ const lines = canonical.split(/\r\n|\n/u);
4766
+ if (lines[0] !== "---") return void 0;
4767
+ const closing = lines.indexOf("---", 1);
4768
+ if (closing === -1) return void 0;
4769
+ return `${lines.slice(0, closing + 1).join("\n")}\n${(0, _orkestrel_template.fillTemplate)(ARTIFACT_TEMPLATES.orchestration.skill, { name })}`;
4770
+ }
4647
4771
  //#endregion
4648
4772
  //#region src/core/compilers.ts
4649
4773
  /**
@@ -4860,7 +4984,8 @@ function blueprintToScripts(blueprint) {
4860
4984
  check: [
4861
4985
  "tsc --noEmit --project tsconfig.json",
4862
4986
  ...compiles ? ["npm run check:src"] : [],
4863
- ...blueprint.app.length > 0 ? ["npm run check:app"] : []
4987
+ ...blueprint.app.length > 0 ? ["npm run check:app"] : [],
4988
+ ...blueprint.skills ? ["npm run check:skills"] : []
4864
4989
  ].join(" && ")
4865
4990
  };
4866
4991
  if (compiles) {
@@ -4872,6 +4997,7 @@ function blueprintToScripts(blueprint) {
4872
4997
  scripts["check:app"] = blueprint.app.map((environment) => `npm run check:app:${environment}`).join(" && ");
4873
4998
  for (const environment of blueprint.app) scripts[`check:app:${environment}`] = environment === "browser" ? "vue-tsc --noEmit -p configs/app/tsconfig.browser.json" : `tsc --noEmit -p configs/app/tsconfig.${environment}.json`;
4874
4999
  }
5000
+ if (blueprint.skills) scripts["check:skills"] = `tsc --noEmit -p ${SKILLS_CONFIG_PATH}`;
4875
5001
  scripts.test = [
4876
5002
  ...compiles ? ["npm run test:src"] : [],
4877
5003
  ...blueprint.app.length > 0 ? ["npm run test:app"] : [],
@@ -4880,6 +5006,7 @@ function blueprintToScripts(blueprint) {
4880
5006
  "npm run test:config",
4881
5007
  ...blueprint.setup.includes("node") ? ["npm run test:setup"] : [],
4882
5008
  ...blueprint.setup.includes("browser") ? ["npm run test:setup:browser"] : [],
5009
+ ...blueprint.skills ? ["npm run test:skills"] : [],
4883
5010
  ...blueprint.guides ? ["npm run test:guides"] : [],
4884
5011
  ...blueprint.conformance ? ["npm run test:conformance"] : [],
4885
5012
  ...integrates ? ["npm run test:integration"] : [],
@@ -4903,6 +5030,7 @@ function blueprintToScripts(blueprint) {
4903
5030
  if (blueprint.setup.includes("node")) scripts["test:setup"] = `${vitest} --project setup`;
4904
5031
  if (blueprint.setup.includes("browser")) scripts["test:setup:browser"] = `${vitest} --project setup:browser`;
4905
5032
  if (blueprint.journey && blueprint.app.includes("browser")) scripts["test:journey"] = `vitest run --config ${JOURNEY_CONFIG_PATH} --no-cache --reporter=dot`;
5033
+ if (blueprint.skills) scripts["test:skills"] = `${vitest} --project skills`;
4906
5034
  if (blueprint.guides) scripts["test:guides"] = `node --experimental-strip-types ${GUIDES_TEST_PATH}`;
4907
5035
  if (blueprint.conformance) scripts["test:conformance"] = `${vitest} --project conformance`;
4908
5036
  scripts["test:probe"] = "vitest run --config vite.config.ts --no-cache --reporter=verbose --project probe";
@@ -4959,7 +5087,7 @@ function blueprintToScripts(blueprint) {
4959
5087
  * Every direct `test:<project>` script is writable, together with the probe and
4960
5088
  * benchmark workbench scripts. A workspace carrying guides adds `test:guides`,
4961
5089
  * whose package-owned entry runs the guides project and handles explicit parity
4962
- * rewrites. Publishing adds the pack and publication lifecycle scripts.
5090
+ * rewrites, and one carrying skills adds `test:skills`. Publishing adds the pack and publication lifecycle scripts.
4963
5091
  * Aggregate test scripts and
4964
5092
  * maintainer-owned gate chains stay outside the region.
4965
5093
  *
@@ -5293,6 +5421,10 @@ function blueprintToRootVite(blueprint) {
5293
5421
  factories.push(CONFIG_TEMPLATES.factories.guides);
5294
5422
  projects.push("guides");
5295
5423
  }
5424
+ if (blueprint.skills) {
5425
+ factories.push(CONFIG_TEMPLATES.factories.skills);
5426
+ projects.push("skills");
5427
+ }
5296
5428
  if (blueprint.conformance) {
5297
5429
  factories.push(CONFIG_TEMPLATES.factories.conformance);
5298
5430
  projects.push("conformance");
@@ -5447,6 +5579,13 @@ ${paths.join("\n")}
5447
5579
  environment: "browser",
5448
5580
  content: CONFIG_TEMPLATES.vites.app.journey
5449
5581
  });
5582
+ if (blueprint.skills) artifacts.push({
5583
+ path: SKILLS_CONFIG_PATH,
5584
+ group: "configs",
5585
+ ownership: "content",
5586
+ origin: "template",
5587
+ content: CONFIG_TEMPLATES.tsconfigs.skills
5588
+ });
5450
5589
  return artifacts;
5451
5590
  }
5452
5591
  /**
@@ -5733,21 +5872,23 @@ function blueprintToGuideArtifacts(blueprint) {
5733
5872
  *
5734
5873
  * @param blueprint - The workspace specification.
5735
5874
  * @returns The birth-owned package front page and the content-owned `AGENTS.md`
5736
- * and `CLAUDE.md` pointers.
5875
+ * pointer.
5737
5876
  *
5738
5877
  * @remarks
5739
5878
  * The front page is the workspace's own prose, so it is written once and left
5740
- * alone from then on. The pointers are scaffold's, so they are content-owned and
5741
- * restored whenever they drift.
5879
+ * alone from then on. The pointer is scaffold's, so it is content-owned and
5880
+ * restored whenever it drifts.
5742
5881
  *
5743
- * A pointer is planned here rather than vendored because `stageHost` refuses two
5744
- * vendored paths at one storage name, and `AGENTS.md` and `CLAUDE.md` already
5745
- * store the canon a release ships. Planning them as this package's own content
5746
- * leaves each path with one claimant.
5882
+ * The pointer is planned here rather than vendored because `stageHost` refuses two
5883
+ * vendored paths at one storage name, and `AGENTS.md` already stores the canon a
5884
+ * release ships. Planning it as this package's own content leaves the path with
5885
+ * one claimant. No `CLAUDE.md` is planned: a target holding one stops Claude Code
5886
+ * from reading `AGENTS.md`, so the path stays canon without a claimant, `audit`
5887
+ * reports a copy `foreign`, and `overwrite` deletes it.
5747
5888
  *
5748
- * Neither pointer carries a varying span, so neither is filled: a workspace's
5749
- * name never reaches the text, and the paths a reader follows are the same in
5750
- * every target.
5889
+ * The pointer carries no varying span, so it is not filled: a workspace's name
5890
+ * never reaches the text, and the paths a reader follows are the same in every
5891
+ * target.
5751
5892
  *
5752
5893
  * @example
5753
5894
  * ```ts
@@ -5755,39 +5896,29 @@ function blueprintToGuideArtifacts(blueprint) {
5755
5896
  *
5756
5897
  * const blueprint = createBlueprint('router', { src: ['core'] })
5757
5898
  *
5758
- * blueprintToDocumentArtifacts(blueprint).map((artifact) => artifact.path) // ['README.md', 'AGENTS.md', 'CLAUDE.md']
5899
+ * blueprintToDocumentArtifacts(blueprint).map((artifact) => artifact.path) // ['README.md', 'AGENTS.md']
5759
5900
  * ```
5760
5901
  */
5761
5902
  function blueprintToDocumentArtifacts(blueprint) {
5762
5903
  const publishes = blueprint.src.length > 0;
5763
5904
  const name = publishes ? `@orkestrel/${blueprint.name}` : blueprint.name;
5764
5905
  const description = blueprint.description ?? (publishes ? `The ${name} package.` : `The ${name} application.`);
5765
- return [
5766
- {
5767
- path: "README.md",
5768
- group: "docs",
5769
- ownership: "birth",
5770
- origin: "template",
5771
- content: (0, _orkestrel_template.fillTemplate)(ARTIFACT_TEMPLATES.docs.readme, {
5772
- package: name,
5773
- description
5774
- })
5775
- },
5776
- {
5777
- path: "AGENTS.md",
5778
- group: "docs",
5779
- ownership: "content",
5780
- origin: "template",
5781
- content: ARTIFACT_TEMPLATES.docs.agents
5782
- },
5783
- {
5784
- path: "CLAUDE.md",
5785
- group: "docs",
5786
- ownership: "content",
5787
- origin: "template",
5788
- content: ARTIFACT_TEMPLATES.docs.claude
5789
- }
5790
- ];
5906
+ return [{
5907
+ path: "README.md",
5908
+ group: "docs",
5909
+ ownership: "birth",
5910
+ origin: "template",
5911
+ content: (0, _orkestrel_template.fillTemplate)(ARTIFACT_TEMPLATES.docs.readme, {
5912
+ package: name,
5913
+ description
5914
+ })
5915
+ }, {
5916
+ path: "AGENTS.md",
5917
+ group: "docs",
5918
+ ownership: "content",
5919
+ origin: "template",
5920
+ content: ARTIFACT_TEMPLATES.docs.agents
5921
+ }];
5791
5922
  }
5792
5923
  /**
5793
5924
  * Compiles the blueprint-dependent orchestration artifacts.
@@ -5847,13 +5978,20 @@ function blueprintToOrchestrationArtifacts(blueprint) {
5847
5978
  * staged bytes; and the `.claude/agents` directory in `CANON_PATHS` is what
5848
5979
  * stages those bytes, so listing the file in `HOST_PATHS` as well would claim one
5849
5980
  * storage name twice and refuse the stage. The rest of the canon a target reads
5850
- * from the installed package, at the locations the `AGENTS.md` and `CLAUDE.md`
5851
- * pointers {@link blueprintToDocumentArtifacts} emits name.
5981
+ * from the installed package, at the locations the `AGENTS.md` pointer
5982
+ * {@link blueprintToDocumentArtifacts} emits names.
5852
5983
  *
5853
5984
  * The {@link SEED_GUIDE_PATHS} mirrors are claimed explicitly
5854
5985
  * from `REFERENCE_PATHS`. The target's own guide is excluded by
5855
5986
  * {@link selectHostPaths}; the remaining reference guides grant no target claim.
5856
5987
  *
5988
+ * The skill pointer set follows, for each name in {@link TARGET_SKILL_NAMES}:
5989
+ * the `.claude/skills/<name>/SKILL.md` bridge and the
5990
+ * `.agents/skills/<name>/agents/openai.yaml` sidecar as copies, then the
5991
+ * `.agents/skills/<name>/SKILL.md` pointer with `pointer` set, whose bytes
5992
+ * hydration derives from the canonical skill. A blueprint with `skills` set
5993
+ * ships its own skill canon, so it plans no pointer set.
5994
+ *
5857
5995
  * @example
5858
5996
  * ```ts
5859
5997
  * import { blueprintToHostArtifacts, createBlueprint } from '@orkestrel/scaffold'
@@ -5862,15 +6000,44 @@ function blueprintToOrchestrationArtifacts(blueprint) {
5862
6000
  *
5863
6001
  * blueprintToHostArtifacts(blueprint).some((artifact) => artifact.path === 'tests/guides.test.ts') // false
5864
6002
  * blueprintToHostArtifacts(blueprint).some((artifact) => artifact.path === 'guides/router.md') // false
6003
+ * blueprintToHostArtifacts(blueprint).find((artifact) => artifact.path === '.agents/skills/orkestrel-harden/SKILL.md')?.pointer // true
5865
6004
  * ```
5866
6005
  */
5867
6006
  function blueprintToHostArtifacts(blueprint) {
5868
- return [...selectHostPaths([...HOST_PATHS, ...SEED_GUIDE_PATHS], blueprint.name), CATALOG_AGENT_PATH].map((path) => ({
6007
+ const vendored = [...selectHostPaths([...HOST_PATHS, ...SEED_GUIDE_PATHS], blueprint.name), CATALOG_AGENT_PATH].map((path) => ({
5869
6008
  path,
5870
6009
  group: inferGroup(path),
5871
6010
  ownership: "presence",
5872
6011
  origin: "host"
5873
6012
  }));
6013
+ if (blueprint.skills) return vendored;
6014
+ const skills = TARGET_SKILL_NAMES.flatMap((name) => {
6015
+ const bridge = `.claude/skills/${name}/SKILL.md`;
6016
+ const sidecar = `.agents/skills/${name}/agents/openai.yaml`;
6017
+ const pointer = `.agents/skills/${name}/SKILL.md`;
6018
+ return [
6019
+ {
6020
+ path: bridge,
6021
+ group: inferGroup(bridge),
6022
+ ownership: "presence",
6023
+ origin: "host"
6024
+ },
6025
+ {
6026
+ path: sidecar,
6027
+ group: inferGroup(sidecar),
6028
+ ownership: "presence",
6029
+ origin: "host"
6030
+ },
6031
+ {
6032
+ path: pointer,
6033
+ group: inferGroup(pointer),
6034
+ ownership: "presence",
6035
+ origin: "host",
6036
+ pointer: true
6037
+ }
6038
+ ];
6039
+ });
6040
+ return [...vendored, ...skills];
5874
6041
  }
5875
6042
  /**
5876
6043
  * Replaces the content of every drafted artifact an override names.
@@ -6836,7 +7003,8 @@ function createBlueprint(name, input) {
6836
7003
  vendors: input?.vendors ?? [],
6837
7004
  global: input?.global ?? false,
6838
7005
  showcase: input?.showcase ?? false,
6839
- journey: input?.journey ?? false
7006
+ journey: input?.journey ?? false,
7007
+ skills: input?.skills ?? false
6840
7008
  }));
6841
7009
  if (blueprint === void 0) throw new ScaffoldError("INVALID", "The filled record is not a blueprint.", { name });
6842
7010
  return blueprint;
@@ -7210,10 +7378,12 @@ exports.SERVICE_SETUP_PATH = SERVICE_SETUP_PATH;
7210
7378
  exports.SERVICE_TEST_INCLUDE = SERVICE_TEST_INCLUDE;
7211
7379
  exports.SHOWCASE_CONFIG_PATH = SHOWCASE_CONFIG_PATH;
7212
7380
  exports.SHOWCASE_DEV_DEPENDENCIES = SHOWCASE_DEV_DEPENDENCIES;
7381
+ exports.SKILLS_CONFIG_PATH = SKILLS_CONFIG_PATH;
7213
7382
  exports.SOURCE_BROWSER_DEV_DEPENDENCIES = SOURCE_BROWSER_DEV_DEPENDENCIES;
7214
7383
  exports.SRC_MATRIX = SRC_MATRIX;
7215
7384
  exports.ScaffoldError = ScaffoldError;
7216
7385
  exports.TAB_WIDTH = TAB_WIDTH;
7386
+ exports.TARGET_SKILL_NAMES = TARGET_SKILL_NAMES;
7217
7387
  exports.VERSION_PATTERN = VERSION_PATTERN;
7218
7388
  exports.WORKSPACE_DEV_ENGINES = WORKSPACE_DEV_ENGINES;
7219
7389
  exports.WORKSPACE_OWNED_PATHS = WORKSPACE_OWNED_PATHS;
@@ -7293,6 +7463,7 @@ exports.pathToCondition = pathToCondition;
7293
7463
  exports.planToFindings = planToFindings;
7294
7464
  exports.planToHash = planToHash;
7295
7465
  exports.planToSummary = planToSummary;
7466
+ exports.renderSkillPointer = renderSkillPointer;
7296
7467
  exports.replaceManifestRanges = replaceManifestRanges;
7297
7468
  exports.replaceManifestScripts = replaceManifestScripts;
7298
7469
  exports.replacePlanRanges = replacePlanRanges;