@orkestrel/scaffold 0.0.44 → 0.0.46

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 (69) 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 +10 -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/codex/config.toml +4 -0
  44. package/dist/host/configs/helpers.ts +21 -1
  45. package/dist/host/cursor/mcp.json +4 -0
  46. package/dist/host/cursor/rules/orchestration.mdc +1 -1
  47. package/dist/host/dotfiles/gitignore +4 -1
  48. package/dist/host/dotfiles/mcp.json +4 -0
  49. package/dist/host/guides/scaffold.md +134 -119
  50. package/dist/host/scripts/codex.sh +0 -0
  51. package/dist/host/scripts/cursor.sh +0 -0
  52. package/dist/host/scripts/deps.sh +0 -0
  53. package/dist/host/scripts/ollama.sh +0 -0
  54. package/dist/host/tests/config.test.ts +40 -1
  55. package/dist/host/tests/policy.test.ts +2 -2
  56. package/dist/host/tests/setupPolicy.ts +8 -5
  57. package/dist/src/core/index.cjs +144 -149
  58. package/dist/src/core/index.cjs.map +1 -1
  59. package/dist/src/core/index.d.cts +1624 -1643
  60. package/dist/src/core/index.d.ts +1624 -1643
  61. package/dist/src/core/index.js +145 -149
  62. package/dist/src/core/index.js.map +1 -1
  63. package/dist/src/server/index.cjs +82 -97
  64. package/dist/src/server/index.cjs.map +1 -1
  65. package/dist/src/server/index.d.cts +1844 -1871
  66. package/dist/src/server/index.d.ts +1844 -1871
  67. package/dist/src/server/index.js +83 -96
  68. package/dist/src/server/index.js.map +1 -1
  69. package/package.json +4 -3
@@ -4,7 +4,7 @@ let _orkestrel_template = require("@orkestrel/template");
4
4
  let _orkestrel_emitter = require("@orkestrel/emitter");
5
5
  //#region src/core/constants.ts
6
6
  /**
7
- * The three `Environment` values, frozen.
7
+ * The `Environment` values, frozen.
8
8
  *
9
9
  * @remarks
10
10
  * A blueprint's `src` and `app` axes are caller-supplied, so the gate measures
@@ -18,7 +18,7 @@ var ENVIRONMENTS = Object.freeze([
18
18
  "server"
19
19
  ]);
20
20
  /**
21
- * The seven `Group` values in plan order, frozen.
21
+ * The `Group` values in plan order, frozen.
22
22
  *
23
23
  * @remarks
24
24
  * A compile that names no groups covers every one of them, so this list is the
@@ -70,7 +70,7 @@ var SRC_MATRIX = Object.freeze({
70
70
  * @remarks
71
71
  * An application environment declares no exports, so it carries a runtime
72
72
  * entry instead of a subpath and formats. Core carries none because it is
73
- * shared logic the other two import rather than a host that runs.
73
+ * shared logic the other environments import rather than a host that runs.
74
74
  */
75
75
  var APP_MATRIX = Object.freeze({
76
76
  core: Object.freeze({
@@ -98,8 +98,8 @@ var BIN_ENTRY_PATH = "src/bin/main.ts";
98
98
  * @remarks
99
99
  * These are the files the fleet shares verbatim: the root instruction
100
100
  * documents, the licence, the canonical orchestration contract every harness
101
- * bridge points at, the four harness directories, the session hook scripts,
102
- * the shared policy register, the byte-identical root dotfiles, and the two
101
+ * bridge points at, the harness directories, the session hook scripts,
102
+ * the shared policy register, the byte-identical root dotfiles, and the
103
103
  * guide mirrors a generated workspace starts from. A directory entry vendors
104
104
  * everything beneath it.
105
105
  *
@@ -245,7 +245,7 @@ var DEPENDENCY_NAME_PATTERN = /^@orkestrel\/[a-z][a-z0-9-]*$/;
245
245
  * is admitted, so the shape cannot express a traversal.
246
246
  */
247
247
  var FOREIGN_NAME_PATTERN = /^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/;
248
- /** The exact three-component version syntax a blueprint declares. */
248
+ /** The exact `major.minor.patch` version syntax a blueprint declares. */
249
249
  var VERSION_PATTERN = /^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)$/;
250
250
  /**
251
251
  * The exact caret-pinned pre-1.0 range accepted for an `@orkestrel/*` runtime dependency.
@@ -260,7 +260,7 @@ var ORKESTREL_RANGE_PATTERN = /^\^0\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)$/;
260
260
  /** The registry-only semver subset accepted for a development extra's range. */
261
261
  var EXTRA_RANGE_PATTERN = /^(?:\^|~)?(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*))*)?$/;
262
262
  /**
263
- * The exact three-component floor accepted for a foreign peer's range.
263
+ * The exact `major.minor.patch` floor accepted for a foreign peer's range.
264
264
  *
265
265
  * @remarks
266
266
  * This is independent from {@link ENGINES_PATTERN}. An engine floors the Node
@@ -315,14 +315,15 @@ var DEFAULT_ENGINES = `>=${MINIMUM_NODE_VERSION}`;
315
315
  /** The tooling versions scaffold and every generated workspace share. */
316
316
  var BASE_DEV_DEPENDENCIES = Object.freeze({
317
317
  "@orkestrel/guide": "^0.0.12",
318
- "@orkestrel/scaffold": "^0.0.44",
318
+ "@orkestrel/probe": "^0.0.1",
319
+ "@orkestrel/scaffold": "^0.0.46",
319
320
  "@orkestrel/test": "^0.0.7",
320
321
  "@types/node": "^26.2.0",
321
- oxfmt: "^0.62.0",
322
- oxlint: "^1.77.0",
322
+ oxfmt: "^0.64.0",
323
+ oxlint: "^1.79.0",
323
324
  typescript: "^6.0.3",
324
- vite: "~8.2.0",
325
- vitest: "^4.1.10"
325
+ vite: "~8.2.1",
326
+ vitest: "^4.1.11"
326
327
  });
327
328
  /** The development dependencies that emit declarations for published source or an executable. */
328
329
  var DECLARATION_DEV_DEPENDENCIES = Object.freeze({
@@ -331,7 +332,7 @@ var DECLARATION_DEV_DEPENDENCIES = Object.freeze({
331
332
  });
332
333
  /** The development dependencies a published browser `src` environment adds. */
333
334
  var SOURCE_BROWSER_DEV_DEPENDENCIES = Object.freeze({
334
- "@vitest/browser-playwright": "^4.1.10",
335
+ "@vitest/browser-playwright": "^4.1.11",
335
336
  playwright: "^1.62.1"
336
337
  });
337
338
  /** The development dependency every private `app` environment adds. */
@@ -358,9 +359,9 @@ var SHOWCASE_DEV_DEPENDENCIES = Object.freeze({ "vite-plugin-singlefile": "^2.3.
358
359
  /** The development dependencies a private server application adds. */
359
360
  var APP_SERVER_DEV_DEPENDENCIES = Object.freeze({
360
361
  "@orkestrel/emitter": "^0.0.7",
361
- "@orkestrel/middleware": "^0.0.13",
362
+ "@orkestrel/middleware": "^0.0.16",
362
363
  "@orkestrel/router": "^0.0.10",
363
- "@orkestrel/server": "^0.0.13"
364
+ "@orkestrel/server": "^0.0.14"
364
365
  });
365
366
  //#endregion
366
367
  //#region src/core/templates.ts
@@ -462,6 +463,7 @@ const resolve = {
462
463
  emptyOutDir: true,
463
464
  sourcemap: true,
464
465
  minify: false,
466
+ rolldownOptions: { onLog: enforceBuildLog },
465
467
  },
466
468
  test: {
467
469
  name: { label: 'src:core', color: 'magenta' },
@@ -491,6 +493,7 @@ const resolve = {
491
493
  },
492
494
  outDir: 'dist/src/browser',
493
495
  rolldownOptions: {
496
+ onLog: enforceBuildLog,
494
497
  {{external}}
495
498
  {{output}}
496
499
  },
@@ -529,6 +532,7 @@ const resolve = {
529
532
  outDir: 'dist/src/server',
530
533
  target: 'node22',
531
534
  rolldownOptions: {
535
+ onLog: enforceBuildLog,
532
536
  platform: 'node',
533
537
  {{external}}
534
538
  {{output}}
@@ -563,6 +567,7 @@ const resolve = {
563
567
  outDir: 'dist/bin',
564
568
  target: 'node22',
565
569
  rolldownOptions: {
570
+ onLog: enforceBuildLog,
566
571
  external: (id: string) =>
567
572
  id.startsWith('node:') ||
568
573
  id.startsWith('@orkestrel/') ||
@@ -613,7 +618,10 @@ const resolve = {
613
618
  build: {
614
619
  {{showcaseBuild}} emptyOutDir: true,
615
620
  outDir: resolveWorkspacePath(output),
616
- rolldownOptions: { input: resolveWorkspacePath('app/browser/index.html') },
621
+ rolldownOptions: {
622
+ onLog: enforceBuildLog,
623
+ input: resolveWorkspacePath('app/browser/index.html'),
624
+ },
617
625
  },
618
626
  test: {
619
627
  name: { label: 'app:browser', color: 'blue' },
@@ -650,7 +658,10 @@ export function appBrowser(): UserConfig {
650
658
  },
651
659
  outDir: resolveWorkspacePath('dist/app/server'),
652
660
  target: 'node22',
653
- rolldownOptions: { external: (id: string) => id.startsWith('node:') },
661
+ rolldownOptions: {
662
+ onLog: enforceBuildLog,
663
+ external: (id: string) => id.startsWith('node:'),
664
+ },
654
665
  },
655
666
  test: {
656
667
  name: { label: 'app:server', color: 'green' },
@@ -1034,7 +1045,7 @@ export default defineConfig(
1034
1045
  import { srcBin } from '../../vite.config.ts'
1035
1046
 
1036
1047
  // The \`scaffold\` executable build — a single ESM lib file, no declarations (an
1037
- // executable ships no types), with the \`#!/usr/bin/env node\` shebang re-emitted via
1048
+ // executable ships no types), with the \`#!/usr/bin/env node\` shebang re-emitted through
1038
1049
  // \`output.banner\` (rolldown strips shebangs from source during bundling), and
1039
1050
  // \`output.paths\` rewriting the externalized \`@src/*\` specifiers to the built sibling
1040
1051
  // src environments (relative to \`dist/bin/\`), so the emitted bin resolves at runtime.
@@ -1286,7 +1297,7 @@ export function resolveBundledBrowser(platform: NodeJS.Platform, root: string):
1286
1297
  /**
1287
1298
  * Resolve the first installed stable system Chromium channel.
1288
1299
  *
1289
- * @param platform - The Node platform whose standard layouts should be probed.
1300
+ * @param platform - The Node platform whose standard layouts this call probes.
1290
1301
  * @param environment - The process environment supplying Windows installation roots.
1291
1302
  * @returns \`chrome\`, then \`msedge\`, or \`undefined\` when neither is executable.
1292
1303
  *
@@ -1331,7 +1342,7 @@ export function resolveSystemBrowser(
1331
1342
  * Resolve Playwright provider options for whatever browser this host can actually launch.
1332
1343
  *
1333
1344
  * @param pinned - The executable path for Playwright's pinned Chromium revision, when it has one.
1334
- * @param platform - The Node platform whose standard layouts should be probed.
1345
+ * @param platform - The Node platform whose standard layouts this call probes.
1335
1346
  * @param environment - The process environment supplying operator overrides and Windows roots.
1336
1347
  * @param root - The managed-container bundled browsers directory to search.
1337
1348
  * @returns Provider options naming an executable, a WebSocket endpoint, or a channel.
@@ -1340,7 +1351,7 @@ export function resolveSystemBrowser(
1340
1351
  * Precedence, most important first: \`PLAYWRIGHT_EXECUTABLE_PATH\`, \`PLAYWRIGHT_WS_ENDPOINT\`,
1341
1352
  * \`PLAYWRIGHT_CHANNEL\`, the managed Playwright Chromium, the container's bundled Chromium, a
1342
1353
  * verified system channel, then the platform default channel. An operator override outranks
1343
- * discovery and is returned exactly as given: none of those three environment values is checked
1354
+ * discovery and is returned exactly as given: none of those environment values is checked
1344
1355
  * against the filesystem, because verifying an override would defeat the override. The pinned
1345
1356
  * managed revision outranks anything found on the host because it is deterministic. The installed
1346
1357
  * pinned revision returns empty options so Playwright keeps its own default launch semantics. Only
@@ -1617,7 +1628,7 @@ var isHex = (0, _orkestrel_contract.stringOf)({
1617
1628
  * The bound is a code-unit ceiling rather than a byte count, because a string
1618
1629
  * of more code units than {@link MAX_ARTIFACT_BYTES} cannot encode within that
1619
1630
  * budget under any encoding this package writes. The exact UTF-8 measurement
1620
- * belongs to the compiler and the writer, which are the two places the bytes
1631
+ * belongs to the compiler and the writer, which are the places the bytes
1621
1632
  * are actually produced.
1622
1633
  */
1623
1634
  var isContent = (0, _orkestrel_contract.stringOf)({ max: MAX_ARTIFACT_BYTES });
@@ -1890,7 +1901,7 @@ var isFinding = (0, _orkestrel_contract.unionOf)((0, _orkestrel_contract.recordO
1890
1901
  *
1891
1902
  * @remarks
1892
1903
  * An audit reaches the writer and the destructive verb, so it is guarded as
1893
- * strictly as the plan beside it. Findings use the sum of the two producer
1904
+ * strictly as the plan beside it. Findings use the sum of the producer
1894
1905
  * bounds: one per planned artifact, then one per unplanned snapshot path.
1895
1906
  */
1896
1907
  var isAudit = (0, _orkestrel_contract.recordOf)({
@@ -1902,7 +1913,7 @@ var isAudit = (0, _orkestrel_contract.recordOf)({
1902
1913
  *
1903
1914
  * @remarks
1904
1915
  * `content` is the fetched guide text and `observed` is the local mirror's
1905
- * exact bytes, so the two carry different laws: one is content this package
1916
+ * exact bytes, so they carry different laws: one is content this package
1906
1917
  * writes, the other is the precondition that write is held to.
1907
1918
  */
1908
1919
  var isMirror = (0, _orkestrel_contract.unionOf)((0, _orkestrel_contract.recordOf)({
@@ -2269,7 +2280,7 @@ function matchesOrchestrationPath(path) {
2269
2280
  * @returns The group that owns the path.
2270
2281
  *
2271
2282
  * @remarks
2272
- * A path is grouped by what it governs rather than by where it sits. The two
2283
+ * A path is grouped by what it governs rather than by where it sits. The
2273
2284
  * manifest files are named exactly; anything
2274
2285
  * {@link matchesOrchestrationPath} accepts is orchestration; `src` and `app`
2275
2286
  * are source; `tests`, `guides`, and `docs` carry their own names; the licence
@@ -2401,7 +2412,7 @@ function matchesPrintWidth(line) {
2401
2412
  * module's own relative depth, so a nested module emits a path that escapes
2402
2413
  * `dist/src` and a flat one resolves only by luck. Both faces rewrite the same
2403
2414
  * relative core path to the package's published root export, so the branch is
2404
- * derived once here. The extension alternation is what the two permitted import
2415
+ * derived once here. The extension alternation is what the permitted import
2405
2416
  * spellings produce: an `@src/core` alias resolves to the core source module and
2406
2417
  * prints `.ts`, while a relative import prints the `.js` specifier it was
2407
2418
  * written with. The formatter keeps the call on one line only while the line it
@@ -2581,8 +2592,8 @@ function matchesDriftReachability(ownership, finding) {
2581
2592
  *
2582
2593
  * The order matters because these packages are `0.0.x`, where a caret pins one
2583
2594
  * exact release. Publishing a dependent before its dependency leaves the
2584
- * dependent pinned to the older release, and two ranges that disagree install
2585
- * two copies of one package that the compiler reads as two distinct types.
2595
+ * dependent pinned to the older release, and ranges that disagree install
2596
+ * duplicate copies of one package that the compiler reads as distinct types.
2586
2597
  *
2587
2598
  * A cycle cannot be published in rounds, so its members are omitted rather than
2588
2599
  * placed in an order that would be wrong. An absent name is the report: compare
@@ -2651,11 +2662,11 @@ function planToSummary(plan) {
2651
2662
  };
2652
2663
  }
2653
2664
  /**
2654
- * Extract the three numeric components of an exact version.
2665
+ * Extract the major, minor, and patch components of an exact version.
2655
2666
  *
2656
2667
  * @param version - The candidate version text.
2657
2668
  * @returns The major, minor, and patch numbers, or `undefined` when the text is
2658
- * not the exact three-component syntax.
2669
+ * not the exact `major.minor.patch` syntax.
2659
2670
  *
2660
2671
  * @remarks
2661
2672
  * Deliberately narrow: a prerelease or build suffix is not extracted, because
@@ -2725,10 +2736,10 @@ function compareVersions(left, right) {
2725
2736
  * @remarks
2726
2737
  * The one place this comparison is made. A `Release` records the declared range
2727
2738
  * and the reported version and stores no verdict beside them, because a stored
2728
- * verdict could only disagree with the two fields it sits next to.
2739
+ * verdict could only disagree with the fields it sits next to.
2729
2740
  *
2730
2741
  * Readability is decided first, and it is `EXTRA_RANGE_PATTERN`: an optional
2731
- * caret or tilde over three numeric components and an optional prerelease
2742
+ * caret or tilde over `major.minor.patch` and an optional prerelease
2732
2743
  * suffix. That pattern already covers every `ORKESTREL_RANGE_PATTERN` range and
2733
2744
  * every `VERSION_PATTERN` version, so the subset is stated once rather than
2734
2745
  * assembled here. Text outside it is never admitted, including text handed in on
@@ -3035,7 +3046,7 @@ function srcToExports(src) {
3035
3046
  * not installed by the workspace that declares it and developing against one
3036
3047
  * requires it present. A runtime dependency is the opposite case and is removed:
3037
3048
  * it is already installed, so a second declaration would state one fact twice
3038
- * and the two ranges would be free to disagree.
3049
+ * and the ranges would be free to disagree.
3039
3050
  *
3040
3051
  * A workspace never declares itself, so its own package name is removed. That
3041
3052
  * matters for a workspace named after a package the baseline already carries:
@@ -3219,7 +3230,7 @@ function blueprintToScripts(blueprint) {
3219
3230
  * artifact serialized directly.
3220
3231
  *
3221
3232
  * The artifact carrying this text is claimed by birth. A workspace owns its own
3222
- * manifest once it exists: its description, its keywords, and any script it
3233
+ * manifest after it exists: its description, its keywords, and any script it
3223
3234
  * added are the consumer's, so a repair that replaced the file would take them.
3224
3235
  * The one part scaffold keeps current afterwards is the declared `@orkestrel/*`
3225
3236
  * range set, and that is a region with its own writer rather than a claim over
@@ -3289,7 +3300,7 @@ function blueprintToManifest(blueprint) {
3289
3300
  * Derive the host-specific machinery a generated root Vite configuration carries.
3290
3301
  *
3291
3302
  * @param blueprint - The workspace specification.
3292
- * @returns The four pipelines the generated configuration selects.
3303
+ * @returns The pipelines the generated configuration selects.
3293
3304
  *
3294
3305
  * @remarks
3295
3306
  * The sole derivation of that set: every renderer reads it rather than
@@ -3520,11 +3531,15 @@ export function appShowcase(): UserConfig {
3520
3531
  ${projects.map((project) => `\t\t\t${project},`).join("\n")}
3521
3532
  \t],`;
3522
3533
  const body = `${factories.join("\n")}\n`;
3523
- const boundaries = ["environmentBoundary", "outputBoundary"].filter((boundary) => body.includes(boundary));
3534
+ const helpers = [
3535
+ "enforceBuildLog",
3536
+ "environmentBoundary",
3537
+ "outputBoundary"
3538
+ ].filter((helper) => body.includes(helper));
3524
3539
  return (0, _orkestrel_template.fillTemplate)(CONFIG_TEMPLATES.root.vite, {
3525
3540
  viteTypes: machinery.showcase ? "PluginOption, UserConfig" : "UserConfig",
3526
3541
  imports: imports.length === 0 ? "" : `${imports.join("\n")}\n`,
3527
- helpers: boundaries.length === 0 ? "" : `import { ${boundaries.join(", ")} } from './configs/helpers.js'\n`,
3542
+ helpers: helpers.length === 0 ? "" : `import { ${helpers.join(", ")} } from './configs/helpers.js'\n`,
3528
3543
  browsers: machinery.browser ? "import { resolveBrowser, resolvePinnedBrowser } from './configs/browsers.js'\n" : "",
3529
3544
  options: machinery.browser ? "const browserOptions = resolveBrowser(resolvePinnedBrowser(), process.platform, process.env)\n\n" : "",
3530
3545
  factories: body,
@@ -3649,7 +3664,7 @@ ${paths.join("\n")}
3649
3664
  *
3650
3665
  * @remarks
3651
3666
  * The barrels and every runtime entry intentionally hold nothing. A generated
3652
- * sample entity is too easy to mistake for package implementation, so the
3667
+ * sample entity would read as package implementation, so the
3653
3668
  * scaffold establishes only the selected environment boundaries. An application
3654
3669
  * entry is empty for the same reason the bin entry is, and because the vendored
3655
3670
  * lint config refuses an unassigned import outside a stylesheet, so the entry
@@ -4019,9 +4034,9 @@ function applyOverrides(artifacts, overrides) {
4019
4034
  *
4020
4035
  * @example
4021
4036
  * ```ts
4022
- * import { createBlueprint, createCompiler, planToHash } from '@orkestrel/scaffold'
4037
+ * import { Compiler, createBlueprint, planToHash } from '@orkestrel/scaffold'
4023
4038
  *
4024
- * const { plan } = createCompiler().compile(createBlueprint('router', { src: ['core'] }))
4039
+ * const { plan } = new Compiler().compile(createBlueprint('router', { src: ['core'] }))
4025
4040
  *
4026
4041
  * plan === undefined ? undefined : planToHash(plan)?.length // 16
4027
4042
  * ```
@@ -4050,7 +4065,7 @@ function planToHash(plan) {
4050
4065
  * destination has no bytes to record, and every other verdict records the bytes
4051
4066
  * it was given, which is the precondition the mutation that follows is held to.
4052
4067
  * Ownership is copied rather than inferred from drift because aligned findings
4053
- * span all three ownership tiers.
4068
+ * span every ownership tier.
4054
4069
  *
4055
4070
  * `foreign` is not answerable here, because it describes a path no artifact was
4056
4071
  * planned for.
@@ -4113,9 +4128,9 @@ function artifactToFinding(artifact, observed) {
4113
4128
  *
4114
4129
  * @example
4115
4130
  * ```ts
4116
- * import { createBlueprint, createCompiler, planToFindings } from '@orkestrel/scaffold'
4131
+ * import { Compiler, createBlueprint, planToFindings } from '@orkestrel/scaffold'
4117
4132
  *
4118
- * const { plan } = createCompiler().compile(createBlueprint('router', { src: ['core'] }))
4133
+ * const { plan } = new Compiler().compile(createBlueprint('router', { src: ['core'] }))
4119
4134
  *
4120
4135
  * plan === undefined ? [] : planToFindings(plan, { 'AGENTS.md': '68690a' })
4121
4136
  * ```
@@ -4151,7 +4166,7 @@ function planToFindings(plan, current) {
4151
4166
  * range, in list order.
4152
4167
  *
4153
4168
  * @remarks
4154
- * The declared lists and peer partitions differ only in the two syntaxes they
4169
+ * The declared lists and peer partitions differ only in the syntaxes they
4155
4170
  * accept, so the rules live here once and each caller supplies its own patterns.
4156
4171
  * A runtime dependency name reaches a path through its guide mirror and is
4157
4172
  * fixed to the `@orkestrel` scope. A foreign peer or development extra reaches
@@ -4208,14 +4223,14 @@ function dependenciesToQuestions(dependencies, field, name, range) {
4208
4223
  * Only the laws a blueprint answers alone are here. The structural record and
4209
4224
  * its bounds are already settled by `isBlueprint`, which refuses a value that is
4210
4225
  * not a blueprint at all; what remains is the syntax of a name, a version, a
4211
- * range, and an engines floor, the combinations the two environment axes admit,
4212
- * and the overlaps between the three declared package lists. The laws that need
4226
+ * range, and an engines floor, the combinations the environment axes admit,
4227
+ * and the overlaps between the declared package lists. The laws that need
4213
4228
  * a drafted plan belong to {@link artifactsToQuestions} and
4214
4229
  * {@link overridesToQuestions}.
4215
4230
  *
4216
4231
  * A question blocks when it describes a workspace this package cannot generate.
4217
- * Three do not, because each describes a workspace it can describe honestly and
4218
- * should not create: a published axis of several environments without core,
4232
+ * These do not, because each describes a workspace it can describe honestly but
4233
+ * will not create: a published axis of several environments without core,
4219
4234
  * whose manifest names a core build the workspace never runs; a showcase flag
4220
4235
  * whose required browser axis is absent, which emits nothing; and an
4221
4236
  * integration flag over fewer than two environments, whose seed does emit and
@@ -4462,6 +4477,72 @@ function overridesToQuestions(overrides, artifacts) {
4462
4477
  return questions;
4463
4478
  }
4464
4479
  //#endregion
4480
+ //#region src/core/factories.ts
4481
+ /**
4482
+ * Construct a {@link Blueprint} from a name and the fields that differ from the defaults.
4483
+ *
4484
+ * @param name - The bare workspace name.
4485
+ * @param input - The fields to set; every omitted field takes its default.
4486
+ * @returns The filled blueprint, owned by the caller and sharing nothing with `input`.
4487
+ * @throws {@link ScaffoldError} coded `INVALID` when the filled record is not a
4488
+ * blueprint.
4489
+ *
4490
+ * @remarks
4491
+ * A blueprint is a closed record, and most of its fields have one sensible
4492
+ * starting value: an empty list, a cleared flag, `DEFAULT_VERSION`, and
4493
+ * `DEFAULT_ENGINES`. Filling them here is what lets a caller state only what its
4494
+ * workspace actually declares.
4495
+ *
4496
+ * This is the construction door, and {@link parseBlueprint} is the coercing one.
4497
+ * They differ in every part: this fills the defaults and takes a
4498
+ * partial specification, where the parser fills nothing and takes an untrusted
4499
+ * value; and this refuses by throwing, where the parser refuses by answering
4500
+ * `undefined`. What they share is the law — both accept exactly what
4501
+ * `isBlueprint` accepts.
4502
+ *
4503
+ * That law is structural only. Whether the name is a name, the version a
4504
+ * version, and the environment axes a combination this package can generate
4505
+ * are the gate's laws, and the gate answers them with {@link Question}s carrying
4506
+ * their accepted candidates. Deciding them here as well would restate that law
4507
+ * and let the answers disagree, so a blueprint the gate will
4508
+ * refuse is still constructible.
4509
+ *
4510
+ * @example
4511
+ * ```ts
4512
+ * import { createBlueprint } from '@orkestrel/scaffold'
4513
+ *
4514
+ * createBlueprint('router', { src: ['core'] }).version // '0.0.1'
4515
+ * createBlueprint('Router').name // 'Router' — the gate refuses it, this does not
4516
+ * ```
4517
+ */
4518
+ function createBlueprint(name, input) {
4519
+ const blueprint = parseBlueprint(cloneValue({
4520
+ name,
4521
+ ...input?.description === void 0 ? {} : { description: input.description },
4522
+ keywords: input?.keywords ?? [],
4523
+ src: input?.src ?? [],
4524
+ app: input?.app ?? [],
4525
+ dependencies: input?.dependencies ?? [],
4526
+ peers: input?.peers ?? [],
4527
+ extras: input?.extras ?? [],
4528
+ version: input?.version ?? "0.0.1",
4529
+ engines: input?.engines ?? DEFAULT_ENGINES,
4530
+ overrides: input?.overrides ?? [],
4531
+ bin: input?.bin ?? false,
4532
+ setup: input?.setup ?? false,
4533
+ guides: input?.guides ?? false,
4534
+ distribution: input?.distribution ?? false,
4535
+ integration: input?.integration ?? false,
4536
+ conformance: input?.conformance ?? false,
4537
+ service: input?.service ?? false,
4538
+ vendors: input?.vendors ?? [],
4539
+ global: input?.global ?? false,
4540
+ showcase: input?.showcase ?? false
4541
+ }));
4542
+ if (blueprint === void 0) throw new ScaffoldError("INVALID", "The filled record is not a blueprint.", { name });
4543
+ return blueprint;
4544
+ }
4545
+ //#endregion
4465
4546
  //#region src/core/Compiler.ts
4466
4547
  /**
4467
4548
  * The compile spine: draft, gate, pin, run in that order over a blueprint.
@@ -4484,7 +4565,7 @@ function overridesToQuestions(overrides, artifacts) {
4484
4565
  * `INVALID`. Structure raises; the laws a well-formed blueprint can still break
4485
4566
  * are the gate's, and they answer with questions.
4486
4567
  *
4487
- * Two consequences of that order are worth stating, because they are the ones a
4568
+ * The consequences of that order are worth stating, because they are the ones a
4488
4569
  * JavaScript caller meets first. A property backed by an accessor is refused
4489
4570
  * rather than read, which is what closes the race a guard cannot close from
4490
4571
  * inside; the accessor never runs. And an optional field present with the value
@@ -4546,21 +4627,21 @@ var Compiler = class {
4546
4627
  * carries no plan, then `compile` with the whole outcome either way, so an
4547
4628
  * observer reads every compile from one event and the refusals from the other.
4548
4629
  *
4549
- * A plan says the blueprint can be built. It does not say the blueprint should
4550
- * be created, and the questions beside it are what this compiler could not
4551
- * settle. A caller creating a fresh workspace answers them first and writes
4552
- * nothing while any remains, which is the rule the `new` verb applies; a caller
4553
- * describing or repairing an existing target carries them through instead.
4554
- * Nothing downstream repeats that check, because only the caller knows which of
4555
- * the two it is.
4630
+ * A plan says the blueprint can be built. It does not decide whether to create
4631
+ * it, and the questions beside it are what this compiler could not settle. A
4632
+ * caller creating a fresh workspace answers them first and writes nothing while
4633
+ * any remains, which is the rule the `new` verb applies; a caller describing or
4634
+ * repairing an existing target carries them through instead.
4635
+ * Nothing downstream repeats that check, because only the caller knows which
4636
+ * case it is.
4556
4637
  *
4557
4638
  * @example
4558
4639
  * ```ts
4559
- * import { createBlueprint, createCompiler } from '@orkestrel/scaffold'
4640
+ * import { Compiler, createBlueprint } from '@orkestrel/scaffold'
4560
4641
  *
4561
4642
  * const blueprint = createBlueprint('router', { src: ['core'] })
4562
4643
  *
4563
- * createCompiler().compile(blueprint, ['manifest']).plan?.artifacts.length // 1
4644
+ * new Compiler().compile(blueprint, ['manifest']).plan?.artifacts.length // 1
4564
4645
  * ```
4565
4646
  */
4566
4647
  compile(blueprint, groups) {
@@ -4593,12 +4674,12 @@ var Compiler = class {
4593
4674
  *
4594
4675
  * @example
4595
4676
  * ```ts
4596
- * import { createBlueprint, createCompiler } from '@orkestrel/scaffold'
4677
+ * import { Compiler, createBlueprint } from '@orkestrel/scaffold'
4597
4678
  *
4598
4679
  * const blueprint = createBlueprint('router', { src: ['core'] })
4599
4680
  *
4600
- * createCompiler().audit(blueprint, {}, ['manifest']).findings[0]?.drift // 'aligned'
4601
- * createCompiler().audit(blueprint, {}, ['configs']).findings[0]?.drift // 'missing'
4681
+ * new Compiler().audit(blueprint, {}, ['manifest']).findings[0]?.drift // 'aligned'
4682
+ * new Compiler().audit(blueprint, {}, ['configs']).findings[0]?.drift // 'missing'
4602
4683
  * ```
4603
4684
  */
4604
4685
  audit(blueprint, current, groups) {
@@ -4621,9 +4702,9 @@ var Compiler = class {
4621
4702
  *
4622
4703
  * @example
4623
4704
  * ```ts
4624
- * import { createCompiler } from '@orkestrel/scaffold'
4705
+ * import { Compiler } from '@orkestrel/scaffold'
4625
4706
  *
4626
- * const compiler = createCompiler()
4707
+ * const compiler = new Compiler()
4627
4708
  * compiler.destroy()
4628
4709
  * compiler.emitter.destroyed // true
4629
4710
  * ```
@@ -4763,91 +4844,6 @@ var Compiler = class {
4763
4844
  }
4764
4845
  };
4765
4846
  //#endregion
4766
- //#region src/core/factories.ts
4767
- /**
4768
- * Construct a {@link Blueprint} from a name and the fields that differ from the defaults.
4769
- *
4770
- * @param name - The bare workspace name.
4771
- * @param input - The fields to set; every omitted field takes its default.
4772
- * @returns The filled blueprint, owned by the caller and sharing nothing with `input`.
4773
- * @throws {@link ScaffoldError} coded `INVALID` when the filled record is not a
4774
- * blueprint.
4775
- *
4776
- * @remarks
4777
- * A blueprint is a closed record, and most of its fields have one sensible
4778
- * starting value: an empty list, a cleared flag, `DEFAULT_VERSION`, and
4779
- * `DEFAULT_ENGINES`. Filling them here is what lets a caller state only what its
4780
- * workspace actually declares.
4781
- *
4782
- * This is the construction door, and {@link parseBlueprint} is the coercing one.
4783
- * They differ in all three of their parts: this fills the defaults and takes a
4784
- * partial specification, where the parser fills nothing and takes an untrusted
4785
- * value; and this refuses by throwing, where the parser refuses by answering
4786
- * `undefined`. What they share is the law — both accept exactly what
4787
- * `isBlueprint` accepts.
4788
- *
4789
- * That law is structural only. Whether the name is a name, the version a
4790
- * version, and the two environment axes a combination this package can generate
4791
- * are the gate's laws, and the gate answers them with {@link Question}s carrying
4792
- * their accepted candidates. Deciding them here as well would state one law in
4793
- * two places and let the two answers disagree, so a blueprint the gate will
4794
- * refuse is still constructible.
4795
- *
4796
- * @example
4797
- * ```ts
4798
- * import { createBlueprint } from '@orkestrel/scaffold'
4799
- *
4800
- * createBlueprint('router', { src: ['core'] }).version // '0.0.1'
4801
- * createBlueprint('Router').name // 'Router' — the gate refuses it, this does not
4802
- * ```
4803
- */
4804
- function createBlueprint(name, input) {
4805
- const blueprint = parseBlueprint(cloneValue({
4806
- name,
4807
- ...input?.description === void 0 ? {} : { description: input.description },
4808
- keywords: input?.keywords ?? [],
4809
- src: input?.src ?? [],
4810
- app: input?.app ?? [],
4811
- dependencies: input?.dependencies ?? [],
4812
- peers: input?.peers ?? [],
4813
- extras: input?.extras ?? [],
4814
- version: input?.version ?? "0.0.1",
4815
- engines: input?.engines ?? DEFAULT_ENGINES,
4816
- overrides: input?.overrides ?? [],
4817
- bin: input?.bin ?? false,
4818
- setup: input?.setup ?? false,
4819
- guides: input?.guides ?? false,
4820
- distribution: input?.distribution ?? false,
4821
- integration: input?.integration ?? false,
4822
- conformance: input?.conformance ?? false,
4823
- service: input?.service ?? false,
4824
- vendors: input?.vendors ?? [],
4825
- global: input?.global ?? false,
4826
- showcase: input?.showcase ?? false
4827
- }));
4828
- if (blueprint === void 0) throw new ScaffoldError("INVALID", "The filled record is not a blueprint.", { name });
4829
- return blueprint;
4830
- }
4831
- /**
4832
- * Construct a {@link Compiler}.
4833
- *
4834
- * @param options - The initial listeners and the listener-error handler.
4835
- * @returns The compiler, typed as the contract consumers program against.
4836
- * @throws {@link ScaffoldError} coded `INVALID` when `options` is present but is
4837
- * not an option bag the compiler accepts.
4838
- *
4839
- * @example
4840
- * ```ts
4841
- * import { createCompiler } from '@orkestrel/scaffold'
4842
- *
4843
- * const compiler = createCompiler({ on: { block: (questions) => report(questions) } })
4844
- * compiler.destroy()
4845
- * ```
4846
- */
4847
- function createCompiler(options) {
4848
- return new Compiler(options);
4849
- }
4850
- //#endregion
4851
4847
  exports.APP_BROWSER_DEV_DEPENDENCIES = APP_BROWSER_DEV_DEPENDENCIES;
4852
4848
  exports.APP_DEV_DEPENDENCIES = APP_DEV_DEPENDENCIES;
4853
4849
  exports.APP_MATRIX = APP_MATRIX;
@@ -4931,7 +4927,6 @@ exports.computeBytes = computeBytes;
4931
4927
  exports.computeHash = computeHash;
4932
4928
  exports.contentToHex = contentToHex;
4933
4929
  exports.createBlueprint = createBlueprint;
4934
- exports.createCompiler = createCompiler;
4935
4930
  exports.dependenciesToQuestions = dependenciesToQuestions;
4936
4931
  exports.extractVersion = extractVersion;
4937
4932
  exports.inferDrift = inferDrift;