@orkestrel/scaffold 0.0.25 → 0.0.27

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.
@@ -139,6 +139,25 @@ var HOST_PATHS = Object.freeze([
139
139
  "guides/scaffold.md"
140
140
  ]);
141
141
  /**
142
+ * The vendored paths a target receives with its executable bit set, frozen.
143
+ *
144
+ * @remarks
145
+ * Declared rather than read from the staging host's filesystem, because that
146
+ * reading is not portable: Windows carries no executable bit, so a host staged
147
+ * there reports every file non-executable and every target receives hooks it
148
+ * cannot run. Declaring the set here makes one checkout stage one manifest on
149
+ * every host.
150
+ *
151
+ * Every entry is also a {@link HOST_PATHS} member or sits beneath one. A file
152
+ * that must run when a target invokes it belongs here the moment it is vendored.
153
+ */
154
+ var EXECUTABLE_PATHS = Object.freeze([
155
+ "scripts/codex.sh",
156
+ "scripts/cursor.sh",
157
+ "scripts/deps.sh",
158
+ "scripts/ollama.sh"
159
+ ]);
160
+ /**
142
161
  * The path prefixes whose contents instruct or wire an agent, frozen.
143
162
  *
144
163
  * @remarks
@@ -226,7 +245,7 @@ var ENGINES_PATTERN = /^>=(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)$/;
226
245
  var HEX_PATTERN = /^(?:[0-9a-f]{2})*$/;
227
246
  /** Unicode controls, formatting controls, and line and paragraph separators rejected in text. */
228
247
  var CONTROL_CHARACTER_PATTERN = /[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]/u;
229
- /** Visible characters a portable path and a Markdown path cell both forbid. */
248
+ /** Visible characters a target-relative path and a Markdown path cell both forbid. */
230
249
  var INVALID_PATH_CHARACTER_PATTERN = /[<>:"|?*\\]/;
231
250
  /**
232
251
  * Maximum bare workspace name length.
@@ -244,6 +263,8 @@ var MAX_RANGE_LENGTH = 2048;
244
263
  var MAX_PATH_LENGTH = 32767;
245
264
  /** Maximum items accepted in one public collection. */
246
265
  var MAX_COLLECTION_ITEMS = 1e3;
266
+ /** Maximum findings one audit can produce from a bounded plan and snapshot. */
267
+ var MAX_AUDIT_FINDINGS = MAX_COLLECTION_ITEMS * 2;
247
268
  /** Maximum bytes accepted for one artifact. */
248
269
  var MAX_ARTIFACT_BYTES = 5242880;
249
270
  /** Maximum length of the hexadecimal string carrying one artifact's bytes. */
@@ -261,8 +282,8 @@ var DEFAULT_ENGINES = `>=${MINIMUM_NODE_VERSION}`;
261
282
  /** The tooling versions scaffold and every generated workspace share. */
262
283
  var BASE_DEV_DEPENDENCIES = Object.freeze({
263
284
  "@microsoft/api-extractor": "^7.58.12",
264
- "@orkestrel/guide": "^0.0.9",
265
- "@orkestrel/scaffold": "^0.0.25",
285
+ "@orkestrel/guide": "^0.0.10",
286
+ "@orkestrel/scaffold": "^0.0.27",
266
287
  "@types/node": "^26.2.0",
267
288
  oxfmt: "^0.62.0",
268
289
  oxlint: "^1.77.0",
@@ -277,11 +298,11 @@ var SOURCE_BROWSER_DEV_DEPENDENCIES = Object.freeze({
277
298
  playwright: "^1.62.1"
278
299
  });
279
300
  /** The development dependency every private `app` environment adds. */
280
- var APP_DEV_DEPENDENCIES = Object.freeze({ "@orkestrel/contract": "^0.0.10" });
301
+ var APP_DEV_DEPENDENCIES = Object.freeze({ "@orkestrel/contract": "^0.0.11" });
281
302
  /** The development dependencies a private Vue browser application adds. */
282
303
  var APP_BROWSER_DEV_DEPENDENCIES = Object.freeze({
283
304
  ...SOURCE_BROWSER_DEV_DEPENDENCIES,
284
- "@orkestrel/html": "^0.0.2",
305
+ "@orkestrel/html": "^0.0.3",
285
306
  "@vitejs/plugin-vue": "^6.0.8",
286
307
  vue: "^3.5.40",
287
308
  "vue-tsc": "^3.3.7"
@@ -299,10 +320,10 @@ var APP_BROWSER_DEV_DEPENDENCIES = Object.freeze({
299
320
  var SHOWCASE_DEV_DEPENDENCIES = Object.freeze({ "vite-plugin-singlefile": "^2.3.3" });
300
321
  /** The development dependencies a private server application adds. */
301
322
  var APP_SERVER_DEV_DEPENDENCIES = Object.freeze({
302
- "@orkestrel/emitter": "^0.0.5",
303
- "@orkestrel/middleware": "^0.0.9",
304
- "@orkestrel/router": "^0.0.8",
305
- "@orkestrel/server": "^0.0.10"
323
+ "@orkestrel/emitter": "^0.0.6",
324
+ "@orkestrel/middleware": "^0.0.10",
325
+ "@orkestrel/router": "^0.0.9",
326
+ "@orkestrel/server": "^0.0.11"
306
327
  });
307
328
  //#endregion
308
329
  //#region src/core/templates.ts
@@ -355,12 +376,10 @@ var CONFIG_TEMPLATES = Object.freeze({
355
376
  "exclude": ["node_modules", "dist", "tmp"]
356
377
  }
357
378
  `,
358
- vite: `import type { UserConfig } from 'vite'
359
- {{imports}}
360
- import { defineConfig, mergeConfig } from 'vitest/config'
379
+ vite: `import type { {{viteTypes}} } from 'vite'
380
+ {{imports}}import { defineConfig, mergeConfig } from 'vitest/config'
361
381
  import tsconfig from './tsconfig.json' with { type: 'json' }
362
- import { environmentBoundary, outputBoundary } from './configs/helpers.js'
363
- import { lstatSync, readdirSync, realpathSync } from 'node:fs'
382
+ {{helpers}}import { lstatSync, readdirSync, realpathSync } from 'node:fs'
364
383
  import { basename, join, parse, relative, resolve as resolvePath, sep } from 'node:path'
365
384
  import { fileURLToPath, URL } from 'node:url'
366
385
 
@@ -552,14 +571,9 @@ const resolve = {
552
571
  `,
553
572
  browser: `function applicationBrowser(showcase: boolean): UserConfig {
554
573
  const output = showcase ? 'dist/showcase' : 'dist/app/browser'
555
- return {
574
+ {{showcasePlugins}} return {
556
575
  resolve,
557
- plugins: [
558
- outputBoundary(output),
559
- environmentBoundary('app/browser'),
560
- vue(),
561
- {{showcasePlugin}} ],
562
- root: resolveWorkspacePath('app/browser'),
576
+ {{plugins}} root: resolveWorkspacePath('app/browser'),
563
577
  publicDir: false,
564
578
  build: {
565
579
  {{showcaseBuild}} emptyOutDir: true,
@@ -942,9 +956,13 @@ export default defineConfig(appShowcase())
942
956
  *
943
957
  * @remarks
944
958
  * Builders in `compilers.ts` fill every varying span through
945
- * `@orkestrel/template`. Empty barrels and setup modules are intentional: the
946
- * generated workspace starts with no sample domain API, while each selected
947
- * Vitest project gets a real test that proves its barrel has no starter exports.
959
+ * `@orkestrel/template`. Empty barrels, entries, and setup modules are
960
+ * intentional: the generated workspace starts with no sample domain API, while
961
+ * each selected Vitest project gets a real test that proves its barrel has no
962
+ * starter exports. An entry starts empty for the same reason its barrel does,
963
+ * and because the vendored lint config refuses an unassigned import outside a
964
+ * stylesheet, so a starter `import './index.js'` would fail the workspace's own
965
+ * `lint:check` on the day it is written.
948
966
  *
949
967
  * @example
950
968
  * ```ts
@@ -956,8 +974,6 @@ export default defineConfig(appShowcase())
956
974
  var ARTIFACT_TEMPLATES = Object.freeze({
957
975
  source: Object.freeze({
958
976
  empty: "",
959
- main: `import './index.js'
960
- `,
961
977
  browser: `<!doctype html>
962
978
  <html lang="en">
963
979
  <head>
@@ -1142,16 +1158,20 @@ printf '%s\\n' \\
1142
1158
  * The one error this package throws, carrying the coded reason it was raised.
1143
1159
  *
1144
1160
  * @remarks
1145
- * A throw is reserved for a caller the package cannot serve: `INVALID` for
1146
- * off-contract input, `DESTROYED` for any call made after teardown, `TARGET`
1147
- * for a destination that is not what the caller's observation said it was,
1148
- * `WRITE` for a mutation that could not be completed, and `FETCH` for an
1149
- * upstream read that produced no answer the caller can be given.
1150
- *
1151
- * A refused blueprint is not one of these. The gate fails closed and returns
1152
- * the questions that closed it, and `BLOCKED` is the code those stage records
1153
- * carry, so a caller reads a refusal from the value it asked for rather than
1154
- * from a stack.
1161
+ * Each code names one cause: `INVALID` for off-contract input, `DESTROYED` for
1162
+ * any call made after teardown, `TARGET` for a destination that is not what the
1163
+ * caller's observation said it was, `WRITE` for a mutation that could not be
1164
+ * completed, `FETCH` for an upstream read that produced no answer the caller can
1165
+ * be given, and `BLOCKED` for a refused blueprint.
1166
+ *
1167
+ * `BLOCKED` covers both refusals a blueprint can meet, because they are one fact
1168
+ * this blueprint will not be built and the questions say which. The compiler
1169
+ * answers its refusal rather than throwing it: the gate fails closed, returns the
1170
+ * questions that closed it, and records `BLOCKED` on its stage, so a caller reads
1171
+ * that refusal from the value it asked for. A verb that creates a workspace
1172
+ * throws it, because it chose the shape and has nothing to hand back. A blocking
1173
+ * question closed the gate; a non-blocking one is a shape this package can
1174
+ * describe and declines to create.
1155
1175
  *
1156
1176
  * `context` carries whatever the raising site can say about the failure. It is
1157
1177
  * `unknown` because nothing narrows it usefully at the catch site; read it for
@@ -1205,19 +1225,20 @@ function isScaffoldError(value) {
1205
1225
  //#endregion
1206
1226
  //#region src/core/validators.ts
1207
1227
  /**
1208
- * Narrow a value to a portable target-relative path.
1228
+ * Narrow a value to a logical target-relative path.
1209
1229
  *
1210
1230
  * @param value - The candidate path.
1211
1231
  * @returns `true` for a bounded relative path with no traversal, empty segment,
1212
- * control character, or non-portable visible character.
1232
+ * control character, or reserved syntax character.
1213
1233
  *
1214
1234
  * @remarks
1215
1235
  * Every path this package reads or writes passes here, so one law covers a
1216
1236
  * planned artifact, an override target, an audit finding, a guide mirror, and a
1217
1237
  * snapshot key. Rejecting `..`, a leading `/`, and a backslash at the guard is
1218
1238
  * what stops a caller-supplied path from naming a destination outside the
1219
- * target, and rejecting the non-portable visible characters is what keeps a
1220
- * generated workspace checkable out on every supported filesystem.
1239
+ * target. Host-location validation is a separate server boundary: this guard
1240
+ * does not reject a device spelling, a trailing dot or space, or a segment that
1241
+ * exceeds a host filesystem's byte ceiling.
1221
1242
  *
1222
1243
  * @example
1223
1244
  * ```ts
@@ -1495,20 +1516,34 @@ var isQuestion = recordOf({
1495
1516
  * @remarks
1496
1517
  * `observed` is required exactly where the mutation it precedes is held to it,
1497
1518
  * absent where the destination had no bytes to record, and optional where the
1498
- * comparison may not have been made.
1519
+ * comparison may not have been made. Planned findings require `ownership`;
1520
+ * foreign findings forbid it because no artifact was planned for their path.
1521
+ *
1522
+ * That is the whole claim. This guard proves the shape a reader may destructure
1523
+ * and nothing about whether the verdict is one an audit could have reached: the
1524
+ * correlation between `ownership`, `drift`, and `observed` belongs to
1525
+ * {@link inferDrift}, and it is re-derived at the verb that acts on the finding.
1499
1526
  */
1500
1527
  var isFinding = unionOf(recordOf({
1501
1528
  path: isPath,
1502
1529
  group: isGroup,
1503
- drift: literalOf("stale", "foreign"),
1530
+ ownership: literalOf("content", "presence", "birth"),
1531
+ drift: literalOf("stale"),
1532
+ observed: isHex
1533
+ }), recordOf({
1534
+ path: isPath,
1535
+ group: isGroup,
1536
+ drift: literalOf("foreign"),
1504
1537
  observed: isHex
1505
1538
  }), recordOf({
1506
1539
  path: isPath,
1507
1540
  group: isGroup,
1541
+ ownership: literalOf("content", "presence", "birth"),
1508
1542
  drift: literalOf("missing")
1509
1543
  }), recordOf({
1510
1544
  path: isPath,
1511
1545
  group: isGroup,
1546
+ ownership: literalOf("content", "presence", "birth"),
1512
1547
  drift: literalOf("aligned"),
1513
1548
  observed: isHex
1514
1549
  }, ["observed"]));
@@ -1517,10 +1552,11 @@ var isFinding = unionOf(recordOf({
1517
1552
  *
1518
1553
  * @remarks
1519
1554
  * An audit reaches the writer and the destructive verb, so it is guarded as
1520
- * strictly as the plan beside it.
1555
+ * strictly as the plan beside it. Findings use the sum of the two producer
1556
+ * bounds: one per planned artifact, then one per unplanned snapshot path.
1521
1557
  */
1522
1558
  var isAudit = recordOf({
1523
- findings: andOf(isCollection, arrayOf(isFinding)),
1559
+ findings: andOf((value) => holds(() => isArray(value) && value.length <= 2e3), arrayOf(isFinding)),
1524
1560
  questions: andOf(isCollection, arrayOf(isQuestion))
1525
1561
  });
1526
1562
  /**
@@ -1554,7 +1590,8 @@ var isMirror = unionOf(recordOf({
1554
1590
  var isCatalogEntry = unionOf(recordOf({
1555
1591
  name: isDependencyName,
1556
1592
  lookup: literalOf("found"),
1557
- version: isString
1593
+ version: isString,
1594
+ dependencies: andOf(isCollection, arrayOf(isDependency))
1558
1595
  }), recordOf({
1559
1596
  name: isDependencyName,
1560
1597
  lookup: literalOf("missing", "failed"),
@@ -2110,6 +2147,71 @@ function inferDrift(artifact, observed) {
2110
2147
  return observed === artifactToHex(artifact) ? "aligned" : "stale";
2111
2148
  }
2112
2149
  /**
2150
+ * Test whether {@link inferDrift} could have produced a finding for an ownership.
2151
+ *
2152
+ * @param ownership - What scaffold claims at the planned path.
2153
+ * @param finding - The audit verdict to test.
2154
+ * @returns Whether the ownership and verdict are reachable through {@link inferDrift}.
2155
+ *
2156
+ * @remarks
2157
+ * This predicate keeps the comparison law beside the reachability law it
2158
+ * restates. A mutation uses it so a refusal can distinguish an impossible
2159
+ * verdict from a target that genuinely moved after its audit.
2160
+ */
2161
+ function matchesDriftReachability(ownership, finding) {
2162
+ if (finding.drift === "aligned") return ownership === "birth" || finding.observed !== void 0;
2163
+ if (finding.drift === "missing") return ownership !== "birth";
2164
+ return finding.drift === "stale" && ownership === "content";
2165
+ }
2166
+ /**
2167
+ * Project a catalog into the layers it publishes in.
2168
+ *
2169
+ * @param entries - The catalog rows to order.
2170
+ * @returns One layer per round, each holding the names publishable together,
2171
+ * sorted within the layer; a name whose edges never resolve is omitted.
2172
+ *
2173
+ * @remarks
2174
+ * A layer is a deterministic function of the catalog's own edges, so it is
2175
+ * computed here rather than stored on a row that could disagree with them.
2176
+ * Only RUNTIME edges between catalogued packages count: a development
2177
+ * dependency reaches no consumer, so it constrains nothing about publish order,
2178
+ * and an edge leaving the fleet is a package this catalog does not publish.
2179
+ *
2180
+ * The order matters because these packages are `0.0.x`, where a caret pins one
2181
+ * exact release. Publishing a dependent before its dependency leaves the
2182
+ * dependent pinned to the older release, and two ranges that disagree install
2183
+ * two copies of one package that the compiler reads as two distinct types.
2184
+ *
2185
+ * A cycle cannot be published in rounds, so its members are omitted rather than
2186
+ * placed in an order that would be wrong. An absent name is the report: compare
2187
+ * the returned names against the catalog to find one.
2188
+ *
2189
+ * @example
2190
+ * ```ts
2191
+ * import { catalogToLayers } from '@orkestrel/scaffold'
2192
+ *
2193
+ * catalogToLayers(entries)[0] // the names that depend on nothing in the fleet
2194
+ * ```
2195
+ */
2196
+ function catalogToLayers(entries) {
2197
+ const published = new Set(entries.filter((entry) => entry.lookup === "found").map((entry) => entry.name));
2198
+ const pending = /* @__PURE__ */ new Map();
2199
+ for (const entry of entries) {
2200
+ if (entry.lookup !== "found") continue;
2201
+ const edges = entry.dependencies.map((dependency) => dependency.name);
2202
+ pending.set(entry.name, new Set(edges.filter((name) => published.has(name))));
2203
+ }
2204
+ const layers = [];
2205
+ while (pending.size > 0) {
2206
+ const ready = [...pending].filter(([, edges]) => edges.size === 0).map(([name]) => name);
2207
+ if (ready.length === 0) break;
2208
+ for (const name of ready) pending.delete(name);
2209
+ for (const edges of pending.values()) for (const name of ready) edges.delete(name);
2210
+ layers.push(ready.sort());
2211
+ }
2212
+ return layers;
2213
+ }
2214
+ /**
2113
2215
  * Project a plan into its tally by artifact origin.
2114
2216
  *
2115
2217
  * @param plan - The plan to summarize.
@@ -2537,10 +2639,9 @@ function srcToExports(src) {
2537
2639
  *
2538
2640
  * @example
2539
2641
  * ```ts
2540
- * import type { Blueprint } from '@orkestrel/scaffold'
2541
- * import { blueprintToDevDependencies } from '@orkestrel/scaffold'
2642
+ * import { blueprintToDevDependencies, createBlueprint } from '@orkestrel/scaffold'
2542
2643
  *
2543
- * declare const blueprint: Blueprint
2644
+ * const blueprint = createBlueprint('router', { src: ['core'] })
2544
2645
  *
2545
2646
  * blueprintToDevDependencies(blueprint).typescript // the shared TypeScript pin
2546
2647
  * ```
@@ -2551,7 +2652,7 @@ function blueprintToDevDependencies(blueprint) {
2551
2652
  ...blueprint.src.includes("browser") ? SOURCE_BROWSER_DEV_DEPENDENCIES : {},
2552
2653
  ...blueprint.app.length > 0 ? APP_DEV_DEPENDENCIES : {},
2553
2654
  ...blueprint.app.includes("browser") ? APP_BROWSER_DEV_DEPENDENCIES : {},
2554
- ...blueprint.showcase ? SHOWCASE_DEV_DEPENDENCIES : {},
2655
+ ...blueprint.showcase && blueprint.app.includes("browser") ? SHOWCASE_DEV_DEPENDENCIES : {},
2555
2656
  ...blueprint.app.includes("server") ? APP_SERVER_DEV_DEPENDENCIES : {}
2556
2657
  };
2557
2658
  for (const extra of blueprint.extras) merged[extra.name] = extra.range;
@@ -2580,10 +2681,9 @@ function blueprintToDevDependencies(blueprint) {
2580
2681
  *
2581
2682
  * @example
2582
2683
  * ```ts
2583
- * import type { Blueprint } from '@orkestrel/scaffold'
2584
- * import { blueprintToScripts } from '@orkestrel/scaffold'
2684
+ * import { blueprintToScripts, createBlueprint } from '@orkestrel/scaffold'
2585
2685
  *
2586
- * declare const blueprint: Blueprint
2686
+ * const blueprint = createBlueprint('router', { src: ['core'] })
2587
2687
  *
2588
2688
  * blueprintToScripts(blueprint)['format:check'] // 'oxfmt --config .oxfmtrc.json --check .'
2589
2689
  * ```
@@ -2699,10 +2799,9 @@ function blueprintToScripts(blueprint) {
2699
2799
  *
2700
2800
  * @example
2701
2801
  * ```ts
2702
- * import type { Blueprint } from '@orkestrel/scaffold'
2703
- * import { blueprintToManifest } from '@orkestrel/scaffold'
2802
+ * import { blueprintToManifest, createBlueprint } from '@orkestrel/scaffold'
2704
2803
  *
2705
- * declare const blueprint: Blueprint
2804
+ * const blueprint = createBlueprint('router', { src: ['core'] })
2706
2805
  *
2707
2806
  * blueprintToManifest(blueprint).endsWith('}\n') // true
2708
2807
  * ```
@@ -2778,12 +2877,11 @@ function blueprintToManifest(blueprint) {
2778
2877
  *
2779
2878
  * @example
2780
2879
  * ```ts
2781
- * import type { Blueprint } from '@orkestrel/scaffold'
2782
- * import { blueprintToMachinery } from '@orkestrel/scaffold'
2880
+ * import { blueprintToMachinery, createBlueprint } from '@orkestrel/scaffold'
2783
2881
  *
2784
- * declare const blueprint: Blueprint
2882
+ * const blueprint = createBlueprint('router', { app: ['browser'] })
2785
2883
  *
2786
- * blueprintToMachinery(blueprint).vue // true when the app declares browser
2884
+ * blueprintToMachinery(blueprint).vue // true
2787
2885
  * ```
2788
2886
  */
2789
2887
  function blueprintToMachinery(blueprint) {
@@ -2803,10 +2901,9 @@ function blueprintToMachinery(blueprint) {
2803
2901
  *
2804
2902
  * @example
2805
2903
  * ```ts
2806
- * import type { Blueprint } from '@orkestrel/scaffold'
2807
- * import { blueprintToRootTsconfig } from '@orkestrel/scaffold'
2904
+ * import { blueprintToRootTsconfig, createBlueprint } from '@orkestrel/scaffold'
2808
2905
  *
2809
- * declare const blueprint: Blueprint
2906
+ * const blueprint = createBlueprint('router', { src: ['core'] })
2810
2907
  *
2811
2908
  * blueprintToRootTsconfig(blueprint).startsWith('{') // true
2812
2909
  * ```
@@ -2831,10 +2928,9 @@ function blueprintToRootTsconfig(blueprint) {
2831
2928
  *
2832
2929
  * @example
2833
2930
  * ```ts
2834
- * import type { Blueprint } from '@orkestrel/scaffold'
2835
- * import { blueprintToRootVite } from '@orkestrel/scaffold'
2931
+ * import { blueprintToRootVite, createBlueprint } from '@orkestrel/scaffold'
2836
2932
  *
2837
- * declare const blueprint: Blueprint
2933
+ * const blueprint = createBlueprint('router', { src: ['core'] })
2838
2934
  *
2839
2935
  * blueprintToRootVite(blueprint).includes('defineConfig') // true
2840
2936
  * ```
@@ -2864,8 +2960,7 @@ function blueprintToRootVite(blueprint) {
2864
2960
  const core = blueprint.src.includes("core");
2865
2961
  factories.push(fillTemplate(CONFIG_TEMPLATES.factories.src.server, {
2866
2962
  external: core ? `external: (id: string) =>
2867
- id === '@src/core' || id.startsWith('node:') || id.startsWith('@orkestrel/'),` : `external: (id: string) =>
2868
- id.startsWith('node:') || id.startsWith('@orkestrel/'),`,
2963
+ id === '@src/core' || id.startsWith('node:') || id.startsWith('@orkestrel/'),` : "external: (id: string) => id.startsWith('node:') || id.startsWith('@orkestrel/'),",
2869
2964
  output: core ? `\t\t\t\t\toutput: [
2870
2965
  {
2871
2966
  format: 'es',
@@ -2891,28 +2986,35 @@ function blueprintToRootVite(blueprint) {
2891
2986
  projects.push("appCore");
2892
2987
  }
2893
2988
  if (blueprint.app.includes("browser")) {
2894
- const showcasePlugin = machinery.showcase ? `\t\t\t...(showcase
2895
- ? [
2896
- viteSingleFile({
2897
- removeViteModuleLoader: true,
2898
- useRecommendedBuildConfig: true,
2899
- }),
2900
- {
2901
- name: 'orkestrel-showcase-html',
2902
- transformIndexHtml: {
2903
- order: 'post',
2904
- handler(html) {
2905
- const stamp = new Date().toISOString()
2906
- return html.replace(
2907
- '</head>',
2908
- '\t\t<meta name="build-id" content="' + stamp + '" />\\n\t</head>',
2909
- )
2910
- },
2911
- },
2989
+ const showcasePlugins = machinery.showcase ? ` const showcasePlugins: PluginOption[] = showcase
2990
+ ? [
2991
+ viteSingleFile({
2992
+ removeViteModuleLoader: true,
2993
+ useRecommendedBuildConfig: true,
2994
+ }),
2995
+ {
2996
+ name: 'orkestrel-showcase-html',
2997
+ transformIndexHtml: {
2998
+ order: 'post',
2999
+ handler(html) {
3000
+ const stamp = new Date().toISOString()
3001
+ return html.replace(
3002
+ '</head>',
3003
+ '\t\t<meta name="build-id" content="' + stamp + '" />\\n\t</head>',
3004
+ )
2912
3005
  },
2913
- ]
2914
- : []),
3006
+ },
3007
+ },
3008
+ ]
3009
+ : []
2915
3010
  ` : "";
3011
+ const plugins = machinery.showcase ? `\t\tplugins: [
3012
+ outputBoundary(output),
3013
+ environmentBoundary('app/browser'),
3014
+ vue(),
3015
+ ...showcasePlugins,
3016
+ ],
3017
+ ` : " plugins: [outputBoundary(output), environmentBoundary('app/browser'), vue()],\n";
2916
3018
  const showcaseBuild = machinery.showcase ? `\t\t\t...(showcase
2917
3019
  ? {
2918
3020
  cssMinify: 'lightningcss',
@@ -2931,11 +3033,12 @@ export function appShowcase(...options: never[]): UserConfig {
2931
3033
  }
2932
3034
  ` : "";
2933
3035
  factories.push(fillTemplate(CONFIG_TEMPLATES.factories.app.browser, {
2934
- showcasePlugin,
3036
+ plugins,
3037
+ showcasePlugins,
2935
3038
  showcaseBuild,
2936
3039
  showcaseFactory
2937
3040
  }));
2938
- projects.push("appBrowser");
3041
+ projects.push("appBrowser()");
2939
3042
  }
2940
3043
  if (blueprint.app.includes("server")) {
2941
3044
  factories.push(CONFIG_TEMPLATES.factories.app.server);
@@ -2956,9 +3059,13 @@ export function appShowcase(...options: never[]): UserConfig {
2956
3059
  const projectRows = `\t\tprojects: [
2957
3060
  ${projects.map((project) => `\t\t\t${project},`).join("\n")}
2958
3061
  \t],`;
3062
+ const body = `${factories.join("\n")}\n`;
3063
+ const boundaries = ["environmentBoundary", "outputBoundary"].filter((boundary) => body.includes(boundary));
2959
3064
  return fillTemplate(CONFIG_TEMPLATES.root.vite, {
3065
+ viteTypes: machinery.showcase ? "PluginOption, UserConfig" : "UserConfig",
2960
3066
  imports: imports.length === 0 ? "" : `${imports.join("\n")}\n`,
2961
- factories: `${factories.join("\n")}\n`,
3067
+ helpers: boundaries.length === 0 ? "" : `import { ${boundaries.join(", ")} } from './configs/helpers.js'\n`,
3068
+ factories: body,
2962
3069
  projects: projectRows
2963
3070
  });
2964
3071
  }
@@ -2970,10 +3077,9 @@ ${projects.map((project) => `\t\t\t${project},`).join("\n")}
2970
3077
  *
2971
3078
  * @example
2972
3079
  * ```ts
2973
- * import type { Blueprint } from '@orkestrel/scaffold'
2974
- * import { blueprintToConfigArtifacts } from '@orkestrel/scaffold'
3080
+ * import { blueprintToConfigArtifacts, createBlueprint } from '@orkestrel/scaffold'
2975
3081
  *
2976
- * declare const blueprint: Blueprint
3082
+ * const blueprint = createBlueprint('router', { src: ['core'] })
2977
3083
  *
2978
3084
  * blueprintToConfigArtifacts(blueprint)[0]?.path // 'tsconfig.json'
2979
3085
  * ```
@@ -2999,7 +3105,8 @@ function blueprintToConfigArtifacts(blueprint) {
2999
3105
  else if (path === "configs/src/tsconfig.browser.json") content = CONFIG_TEMPLATES.tsconfigs.src.browser;
3000
3106
  else if (path === "configs/src/vite.server.config.ts") {
3001
3107
  const packageName = serializeTypeScriptString(`@orkestrel/${blueprint.name}`);
3002
- const replacement = packageName.length <= 36 ? `\t\t\t\t\t\t? content.replaceAll(/(?:\\.\\.\\/)+core\\/index\\.ts/g, ${packageName})` : [
3108
+ const joined = `\t\t\t\t\t\t? content.replaceAll(/(?:\\.\\.\\/)+core\\/index\\.ts/g, ${packageName})`;
3109
+ const replacement = joined.replaceAll(" ", " ").length <= 100 ? joined : [
3003
3110
  " ? content.replaceAll(",
3004
3111
  " /(?:\\.\\.\\/)+core\\/index\\.ts/g,",
3005
3112
  `\t\t\t\t\t\t\t\t${packageName},`,
@@ -3064,7 +3171,7 @@ ${paths.join("\n")}
3064
3171
  content
3065
3172
  });
3066
3173
  }
3067
- if (blueprint.showcase) artifacts.push({
3174
+ if (blueprint.showcase && blueprint.app.includes("browser")) artifacts.push({
3068
3175
  path: SHOWCASE_CONFIG_PATH,
3069
3176
  group: "configs",
3070
3177
  ownership: "content",
@@ -3081,16 +3188,18 @@ ${paths.join("\n")}
3081
3188
  * @returns Empty published barrels, selected application entries, and the optional bin entry.
3082
3189
  *
3083
3190
  * @remarks
3084
- * The barrels and bin entry intentionally export nothing. A generated sample
3085
- * entity is too easy to mistake for package implementation, so the scaffold
3086
- * establishes only the selected environment boundaries.
3191
+ * The barrels and every runtime entry intentionally hold nothing. A generated
3192
+ * sample entity is too easy to mistake for package implementation, so the
3193
+ * scaffold establishes only the selected environment boundaries. An application
3194
+ * entry is empty for the same reason the bin entry is, and because the vendored
3195
+ * lint config refuses an unassigned import outside a stylesheet, so the entry
3196
+ * cannot start by importing its barrel for effect either.
3087
3197
  *
3088
3198
  * @example
3089
3199
  * ```ts
3090
- * import type { Blueprint } from '@orkestrel/scaffold'
3091
- * import { blueprintToSourceArtifacts } from '@orkestrel/scaffold'
3200
+ * import { blueprintToSourceArtifacts, createBlueprint } from '@orkestrel/scaffold'
3092
3201
  *
3093
- * declare const blueprint: Blueprint
3202
+ * const blueprint = createBlueprint('router', { src: ['core'] })
3094
3203
  *
3095
3204
  * blueprintToSourceArtifacts(blueprint).every(({ group }) => group === 'source') // true
3096
3205
  * ```
@@ -3120,7 +3229,7 @@ function blueprintToSourceArtifacts(blueprint) {
3120
3229
  ownership: "birth",
3121
3230
  origin: "template",
3122
3231
  environment,
3123
- content: ARTIFACT_TEMPLATES.source.main
3232
+ content: ARTIFACT_TEMPLATES.source.empty
3124
3233
  }, {
3125
3234
  path: "app/browser/index.html",
3126
3235
  group: "source",
@@ -3135,7 +3244,7 @@ function blueprintToSourceArtifacts(blueprint) {
3135
3244
  ownership: "birth",
3136
3245
  origin: "template",
3137
3246
  environment,
3138
- content: ARTIFACT_TEMPLATES.source.main
3247
+ content: ARTIFACT_TEMPLATES.source.empty
3139
3248
  });
3140
3249
  }
3141
3250
  if (blueprint.bin) artifacts.push({
@@ -3163,10 +3272,9 @@ function blueprintToSourceArtifacts(blueprint) {
3163
3272
  *
3164
3273
  * @example
3165
3274
  * ```ts
3166
- * import type { Blueprint } from '@orkestrel/scaffold'
3167
- * import { blueprintToTestArtifacts } from '@orkestrel/scaffold'
3275
+ * import { blueprintToTestArtifacts, createBlueprint } from '@orkestrel/scaffold'
3168
3276
  *
3169
- * declare const blueprint: Blueprint
3277
+ * const blueprint = createBlueprint('router', { src: ['core'] })
3170
3278
  *
3171
3279
  * blueprintToTestArtifacts(blueprint)[0]?.path // 'tests/setup.ts'
3172
3280
  * ```
@@ -3376,10 +3484,9 @@ function nameToHostArtifacts(name) {
3376
3484
  *
3377
3485
  * @example
3378
3486
  * ```ts
3379
- * import type { Artifact } from '@orkestrel/scaffold'
3380
- * import { applyOverrides } from '@orkestrel/scaffold'
3487
+ * import { applyOverrides, blueprintToConfigArtifacts, createBlueprint } from '@orkestrel/scaffold'
3381
3488
  *
3382
- * declare const artifacts: readonly Artifact[]
3489
+ * const artifacts = blueprintToConfigArtifacts(createBlueprint('router', { src: ['core'] }))
3383
3490
  *
3384
3491
  * applyOverrides(artifacts, [{ path: 'README.md', content: '# Title\n' }])
3385
3492
  * ```
@@ -3417,12 +3524,11 @@ function applyOverrides(artifacts, overrides) {
3417
3524
  *
3418
3525
  * @example
3419
3526
  * ```ts
3420
- * import type { Plan } from '@orkestrel/scaffold'
3421
- * import { planToHash } from '@orkestrel/scaffold'
3527
+ * import { createBlueprint, createCompiler, planToHash } from '@orkestrel/scaffold'
3422
3528
  *
3423
- * declare const plan: Plan
3529
+ * const { plan } = createCompiler().compile(createBlueprint('router', { src: ['core'] }))
3424
3530
  *
3425
- * planToHash(plan)?.length // 16
3531
+ * plan === undefined ? undefined : planToHash(plan)?.length // 16
3426
3532
  * ```
3427
3533
  */
3428
3534
  function planToHash(plan) {
@@ -3440,13 +3546,16 @@ function planToHash(plan) {
3440
3546
  * @param artifact - The planned artifact.
3441
3547
  * @param observed - The destination's exact bytes as hexadecimal; absent when
3442
3548
  * the destination holds no file.
3443
- * @returns The finding, carrying `observed` exactly where bytes were read.
3549
+ * @returns The finding, carrying the artifact's ownership and `observed`
3550
+ * exactly where bytes were read.
3444
3551
  *
3445
3552
  * @remarks
3446
3553
  * The comparison itself is {@link inferDrift}'s, so ownership decides it here
3447
3554
  * exactly as it does everywhere else. This adds only the shape: a missing
3448
3555
  * destination has no bytes to record, and every other verdict records the bytes
3449
3556
  * it was given, which is the precondition the mutation that follows is held to.
3557
+ * Ownership is copied rather than inferred from drift because aligned findings
3558
+ * span all three ownership tiers.
3450
3559
  *
3451
3560
  * `foreign` is not answerable here, because it describes a path no artifact was
3452
3561
  * planned for.
@@ -3458,29 +3567,34 @@ function planToHash(plan) {
3458
3567
  * artifactToFinding(
3459
3568
  * { path: 'README.md', group: 'docs', ownership: 'content', origin: 'computed', content: 'hi\n' },
3460
3569
  * '6279650a',
3461
- * ) // { path: 'README.md', group: 'docs', drift: 'stale', observed: '6279650a' }
3570
+ * ) // { path: 'README.md', group: 'docs', ownership: 'content', drift: 'stale', observed: '6279650a' }
3462
3571
  * ```
3463
3572
  */
3464
3573
  function artifactToFinding(artifact, observed) {
3465
3574
  const path = artifact.path;
3466
3575
  const group = artifact.group;
3576
+ const ownership = artifact.ownership;
3467
3577
  if (observed === void 0) return inferDrift(artifact) === "aligned" ? {
3468
3578
  path,
3469
3579
  group,
3580
+ ownership,
3470
3581
  drift: "aligned"
3471
3582
  } : {
3472
3583
  path,
3473
3584
  group,
3585
+ ownership,
3474
3586
  drift: "missing"
3475
3587
  };
3476
3588
  return inferDrift(artifact, observed) === "stale" ? {
3477
3589
  path,
3478
3590
  group,
3591
+ ownership,
3479
3592
  drift: "stale",
3480
3593
  observed
3481
3594
  } : {
3482
3595
  path,
3483
3596
  group,
3597
+ ownership,
3484
3598
  drift: "aligned",
3485
3599
  observed
3486
3600
  };
@@ -3504,12 +3618,11 @@ function artifactToFinding(artifact, observed) {
3504
3618
  *
3505
3619
  * @example
3506
3620
  * ```ts
3507
- * import type { Plan } from '@orkestrel/scaffold'
3508
- * import { planToFindings } from '@orkestrel/scaffold'
3621
+ * import { createBlueprint, createCompiler, planToFindings } from '@orkestrel/scaffold'
3509
3622
  *
3510
- * declare const plan: Plan
3623
+ * const { plan } = createCompiler().compile(createBlueprint('router', { src: ['core'] }))
3511
3624
  *
3512
- * planToFindings(plan, { 'AGENTS.md': '68690a' })
3625
+ * plan === undefined ? [] : planToFindings(plan, { 'AGENTS.md': '68690a' })
3513
3626
  * ```
3514
3627
  */
3515
3628
  function planToFindings(plan, current) {
@@ -3593,8 +3706,8 @@ function dependenciesToQuestions(dependencies, field, name, range) {
3593
3706
  * Measure a blueprint against every law its own fields decide.
3594
3707
  *
3595
3708
  * @param blueprint - The workspace specification.
3596
- * @returns One blocking question per rejected field, in blueprint field order,
3597
- * with the rules that span several fields last.
3709
+ * @returns One question per rejected field, in blueprint field order, with the
3710
+ * rules that span several fields last.
3598
3711
  *
3599
3712
  * @remarks
3600
3713
  * Only the laws a blueprint answers alone are here. The structural record and
@@ -3605,19 +3718,25 @@ function dependenciesToQuestions(dependencies, field, name, range) {
3605
3718
  * a drafted plan belong to {@link artifactsToQuestions} and
3606
3719
  * {@link overridesToQuestions}.
3607
3720
  *
3608
- * Every question is blocking, because each one describes a workspace this
3609
- * package cannot generate rather than one it can generate imperfectly. An
3610
- * environment question carries `ENVIRONMENTS` as its candidates, so a caller
3611
- * reads the accepted values from the refusal instead of from the documentation.
3721
+ * A question blocks when it describes a workspace this package cannot generate.
3722
+ * Three do not, because each describes a workspace it can describe honestly and
3723
+ * should not create: a published axis of several environments without core, whose
3724
+ * manifest names a core build the workspace never runs, and a structural flag
3725
+ * whose required axis is absent, which emits nothing. Blocking those closed the
3726
+ * gate for every verb, and the verbs that read an existing workspace need the
3727
+ * plan the gate refused. The caller that chooses the shape refuses the advisory;
3728
+ * the callers that read one report it.
3729
+ *
3730
+ * An environment question carries `ENVIRONMENTS` as its candidates, so a caller
3731
+ * reads the accepted values from the question instead of from the documentation.
3612
3732
  *
3613
3733
  * @example
3614
3734
  * ```ts
3615
- * import type { Blueprint } from '@orkestrel/scaffold'
3616
- * import { blueprintToQuestions } from '@orkestrel/scaffold'
3735
+ * import { blueprintToQuestions, createBlueprint } from '@orkestrel/scaffold'
3617
3736
  *
3618
- * declare const blueprint: Blueprint
3737
+ * const blueprint = createBlueprint('router', { src: ['core'] })
3619
3738
  *
3620
- * blueprintToQuestions(blueprint).length === 0 // true when the gate passes
3739
+ * blueprintToQuestions(blueprint).length === 0 // true
3621
3740
  * ```
3622
3741
  */
3623
3742
  function blueprintToQuestions(blueprint) {
@@ -3643,6 +3762,12 @@ function blueprintToQuestions(blueprint) {
3643
3762
  blocking: true,
3644
3763
  candidates: ENVIRONMENTS
3645
3764
  });
3765
+ if (blueprint.src.length > 1 && !blueprint.src.includes("core")) questions.push({
3766
+ field: "src",
3767
+ message: "Several published environments put core at the package root, so this manifest names a core build the workspace never runs. Declare core on src, or publish one environment.",
3768
+ blocking: false,
3769
+ candidates: ENVIRONMENTS
3770
+ });
3646
3771
  for (const environment of ENVIRONMENTS) {
3647
3772
  if (blueprint.src.filter((declared) => declared === environment).length > 1) questions.push({
3648
3773
  field: "src",
@@ -3657,11 +3782,10 @@ function blueprintToQuestions(blueprint) {
3657
3782
  candidates: ENVIRONMENTS
3658
3783
  });
3659
3784
  }
3660
- if (blueprint.showcase && !blueprint.app.includes("browser")) questions.push({
3661
- field: "showcase",
3662
- message: "A showcase projects the browser application, which app does not declare.",
3663
- blocking: true,
3664
- candidates: ENVIRONMENTS
3785
+ if (blueprint.integration && blueprint.src.length === 0) questions.push({
3786
+ field: "integration",
3787
+ message: "integration projects a published src, and this workspace declares none, so it emits nothing.",
3788
+ blocking: false
3665
3789
  });
3666
3790
  const services = /* @__PURE__ */ new Set();
3667
3791
  for (const service of blueprint.services) {
@@ -3677,6 +3801,11 @@ function blueprintToQuestions(blueprint) {
3677
3801
  });
3678
3802
  services.add(service);
3679
3803
  }
3804
+ if (blueprint.showcase && !blueprint.app.includes("browser")) questions.push({
3805
+ field: "showcase",
3806
+ message: "showcase projects a browser app, and this workspace declares none, so it emits nothing.",
3807
+ blocking: false
3808
+ });
3680
3809
  questions.push(...dependenciesToQuestions(blueprint.dependencies, "dependencies", DEPENDENCY_NAME_PATTERN, ORKESTREL_RANGE_PATTERN), ...dependenciesToQuestions(blueprint.peers, "peers", DEPENDENCY_NAME_PATTERN, ORKESTREL_RANGE_PATTERN), ...dependenciesToQuestions(blueprint.extras, "extras", EXTRA_NAME_PATTERN, EXTRA_RANGE_PATTERN));
3681
3810
  const lists = [
3682
3811
  ["dependencies", blueprint.dependencies],
@@ -3725,12 +3854,11 @@ function blueprintToQuestions(blueprint) {
3725
3854
  *
3726
3855
  * @example
3727
3856
  * ```ts
3728
- * import type { Artifact } from '@orkestrel/scaffold'
3729
- * import { artifactsToQuestions } from '@orkestrel/scaffold'
3857
+ * import { artifactsToQuestions, blueprintToConfigArtifacts, createBlueprint } from '@orkestrel/scaffold'
3730
3858
  *
3731
- * declare const artifacts: readonly Artifact[]
3859
+ * const artifacts = blueprintToConfigArtifacts(createBlueprint('router', { src: ['core'] }))
3732
3860
  *
3733
- * artifactsToQuestions(artifacts).length === 0 // true when the draft is sound
3861
+ * artifactsToQuestions(artifacts).length === 0 // true
3734
3862
  * ```
3735
3863
  */
3736
3864
  function artifactsToQuestions(artifacts) {
@@ -3782,10 +3910,9 @@ function artifactsToQuestions(artifacts) {
3782
3910
  *
3783
3911
  * @example
3784
3912
  * ```ts
3785
- * import type { Artifact } from '@orkestrel/scaffold'
3786
- * import { overridesToQuestions } from '@orkestrel/scaffold'
3913
+ * import { blueprintToConfigArtifacts, createBlueprint, overridesToQuestions } from '@orkestrel/scaffold'
3787
3914
  *
3788
- * declare const artifacts: readonly Artifact[]
3915
+ * const artifacts = blueprintToConfigArtifacts(createBlueprint('router', { src: ['core'] }))
3789
3916
  *
3790
3917
  * overridesToQuestions([{ path: 'package.json', content: '{}\n' }], artifacts).length // 1
3791
3918
  * ```
@@ -3912,12 +4039,19 @@ var Compiler = class {
3912
4039
  * carries no plan, then `compile` with the whole outcome either way, so an
3913
4040
  * observer reads every compile from one event and the refusals from the other.
3914
4041
  *
4042
+ * A plan says the blueprint can be built. It does not say the blueprint should
4043
+ * be created, and the questions beside it are what this compiler could not
4044
+ * settle. A caller creating a fresh workspace answers them first and writes
4045
+ * nothing while any remains, which is the rule the `new` verb applies; a caller
4046
+ * describing or repairing an existing target carries them through instead.
4047
+ * Nothing downstream repeats that check, because only the caller knows which of
4048
+ * the two it is.
4049
+ *
3915
4050
  * @example
3916
4051
  * ```ts
3917
- * import type { Blueprint } from '@orkestrel/scaffold'
3918
- * import { createCompiler } from '@orkestrel/scaffold'
4052
+ * import { createBlueprint, createCompiler } from '@orkestrel/scaffold'
3919
4053
  *
3920
- * declare const blueprint: Blueprint
4054
+ * const blueprint = createBlueprint('router', { src: ['core'] })
3921
4055
  *
3922
4056
  * createCompiler().compile(blueprint, ['manifest']).plan?.artifacts.length // 1
3923
4057
  * ```
@@ -3945,14 +4079,19 @@ var Compiler = class {
3945
4079
  * reports no findings and carries the questions instead. Emits `block` in that
3946
4080
  * case, then `audit` with the verdict either way.
3947
4081
  *
4082
+ * Ownership decides each verdict, not absence. A birth-owned path is never
4083
+ * compared and reads `aligned` against a target holding nothing, while a
4084
+ * content-owned path with no bytes to read is `missing`. An empty snapshot
4085
+ * therefore produces both verdicts rather than one.
4086
+ *
3948
4087
  * @example
3949
4088
  * ```ts
3950
- * import type { Blueprint } from '@orkestrel/scaffold'
3951
- * import { createCompiler } from '@orkestrel/scaffold'
4089
+ * import { createBlueprint, createCompiler } from '@orkestrel/scaffold'
3952
4090
  *
3953
- * declare const blueprint: Blueprint
4091
+ * const blueprint = createBlueprint('router', { src: ['core'] })
3954
4092
  *
3955
- * createCompiler().audit(blueprint, {}).findings.every(({ drift }) => drift === 'missing') // true
4093
+ * createCompiler().audit(blueprint, {}, ['manifest']).findings[0]?.drift // 'aligned'
4094
+ * createCompiler().audit(blueprint, {}, ['configs']).findings[0]?.drift // 'missing'
3956
4095
  * ```
3957
4096
  */
3958
4097
  audit(blueprint, current, groups) {
@@ -3990,7 +4129,10 @@ var Compiler = class {
3990
4129
  }
3991
4130
  #scaffold(blueprint, groups) {
3992
4131
  const stages = [];
3993
- const artifacts = this.#draft(blueprint, groups);
4132
+ const draft = this.#draft(blueprint);
4133
+ const selected = [];
4134
+ for (const group of groups) for (const artifact of draft) if (artifact.group === group) selected.push(artifact);
4135
+ const artifacts = applyOverrides(selected, blueprint.overrides);
3994
4136
  stages.push({
3995
4137
  stage: "draft",
3996
4138
  input: {
@@ -3999,7 +4141,7 @@ var Compiler = class {
3999
4141
  },
4000
4142
  output: artifacts
4001
4143
  });
4002
- const questions = this.#gate(blueprint, artifacts);
4144
+ const questions = this.#gate(blueprint, draft, artifacts);
4003
4145
  const blocking = questions.filter((question) => question.blocking);
4004
4146
  if (blocking.length > 0) {
4005
4147
  stages.push({
@@ -4068,8 +4210,8 @@ var Compiler = class {
4068
4210
  stages
4069
4211
  };
4070
4212
  }
4071
- #draft(blueprint, groups) {
4072
- const drafted = [
4213
+ #draft(blueprint) {
4214
+ return [
4073
4215
  {
4074
4216
  path: "package.json",
4075
4217
  group: "manifest",
@@ -4085,14 +4227,11 @@ var Compiler = class {
4085
4227
  ...blueprintToOrchestrationArtifacts(blueprint),
4086
4228
  ...nameToHostArtifacts(blueprint.name)
4087
4229
  ];
4088
- const covered = [];
4089
- for (const group of groups) for (const artifact of drafted) if (artifact.group === group) covered.push(artifact);
4090
- return applyOverrides(covered, blueprint.overrides);
4091
4230
  }
4092
- #gate(blueprint, artifacts) {
4231
+ #gate(blueprint, draft, artifacts) {
4093
4232
  return [
4094
4233
  ...blueprintToQuestions(blueprint),
4095
- ...overridesToQuestions(blueprint.overrides, artifacts),
4234
+ ...overridesToQuestions(blueprint.overrides, draft),
4096
4235
  ...artifactsToQuestions(artifacts)
4097
4236
  ];
4098
4237
  }
@@ -4197,6 +4336,6 @@ function createCompiler(options) {
4197
4336
  return new Compiler(options);
4198
4337
  }
4199
4338
  //#endregion
4200
- export { APP_BROWSER_DEV_DEPENDENCIES, APP_DEV_DEPENDENCIES, APP_MATRIX, APP_SERVER_DEV_DEPENDENCIES, ARTIFACT_TEMPLATES, BASE_DEV_DEPENDENCIES, BIN_CONFIGS, BIN_ENTRY_PATH, CATALOG_AGENT_PATH, CONFIG_TEMPLATES, CONTROL_CHARACTER_PATTERN, Compiler, DEFAULT_ENGINES, DEFAULT_VERSION, DEPENDENCY_NAME_PATTERN, ENGINES_PATTERN, ENVIRONMENTS, EXTRA_NAME_PATTERN, EXTRA_RANGE_PATTERN, GLOBAL_SETUP_PATH, GROUPS, GUIDES_TEST_PATH, HEX_PATTERN, HOST_PATHS, INTEGRATION_TEST_PATH, INVALID_PATH_CHARACTER_PATTERN, MAX_ARTIFACT_BYTES, MAX_ARTIFACT_HEX_LENGTH, MAX_COLLECTION_ITEMS, MAX_DEPENDENCY_NAME_LENGTH, MAX_MANIFEST_BYTES, MAX_NAME_LENGTH, MAX_PATH_LENGTH, MAX_RANGE_LENGTH, MAX_TOTAL_ARTIFACT_BYTES, MINIMUM_NODE_VERSION, NAME_PATTERN, ORCHESTRATION_PATH_NAMES, ORCHESTRATION_PATH_PREFIXES, ORKESTREL_RANGE_PATTERN, SERVICE_SCRIPT_PATH, SHOWCASE_CONFIG_PATH, SHOWCASE_DEV_DEPENDENCIES, SOURCE_BROWSER_DEV_DEPENDENCIES, SRC_MATRIX, ScaffoldError, VERSION_PATTERN, applyOverrides, artifactToFinding, artifactToHex, artifactsToQuestions, blueprintToConfigArtifacts, blueprintToDevDependencies, blueprintToDocumentArtifacts, blueprintToGuideArtifacts, blueprintToMachinery, blueprintToManifest, blueprintToOrchestrationArtifacts, blueprintToQuestions, blueprintToRootTsconfig, blueprintToRootVite, blueprintToScripts, blueprintToSourceArtifacts, blueprintToTestArtifacts, bytesToHex, cloneValue, compareVersions, computeBytes, computeHash, contentToHex, createBlueprint, createCompiler, dependenciesToQuestions, extractVersion, inferDrift, inferGroup, isArtifact, isAudit, isBlueprint, isCatalogEntry, isCollection, isCompilerHooks, isCompilerOptions, isContent, isDependency, isDependencyName, isEnvironment, isFinding, isGroup, isGroups, isHex, isMirror, isOverride, isPath, isPlan, isQuestion, isScaffoldError, isSnapshot, manifestToDependencies, manifestToName, matchesEngines, matchesOrchestrationPath, matchesRange, nameToGuide, nameToHostArtifacts, overridesToQuestions, parseBlueprint, parseCompilerOptions, parseGroups, parseSnapshot, pathToCondition, planToFindings, planToHash, planToSummary, selectGroups, selectHostPaths, serializeTypeScriptString, srcToEntry, srcToExports, srcToRoot };
4339
+ export { APP_BROWSER_DEV_DEPENDENCIES, APP_DEV_DEPENDENCIES, APP_MATRIX, APP_SERVER_DEV_DEPENDENCIES, ARTIFACT_TEMPLATES, BASE_DEV_DEPENDENCIES, BIN_CONFIGS, BIN_ENTRY_PATH, CATALOG_AGENT_PATH, CONFIG_TEMPLATES, CONTROL_CHARACTER_PATTERN, Compiler, DEFAULT_ENGINES, DEFAULT_VERSION, DEPENDENCY_NAME_PATTERN, ENGINES_PATTERN, ENVIRONMENTS, EXECUTABLE_PATHS, EXTRA_NAME_PATTERN, EXTRA_RANGE_PATTERN, GLOBAL_SETUP_PATH, GROUPS, GUIDES_TEST_PATH, HEX_PATTERN, HOST_PATHS, INTEGRATION_TEST_PATH, INVALID_PATH_CHARACTER_PATTERN, MAX_ARTIFACT_BYTES, MAX_ARTIFACT_HEX_LENGTH, MAX_AUDIT_FINDINGS, MAX_COLLECTION_ITEMS, MAX_DEPENDENCY_NAME_LENGTH, MAX_MANIFEST_BYTES, MAX_NAME_LENGTH, MAX_PATH_LENGTH, MAX_RANGE_LENGTH, MAX_TOTAL_ARTIFACT_BYTES, MINIMUM_NODE_VERSION, NAME_PATTERN, ORCHESTRATION_PATH_NAMES, ORCHESTRATION_PATH_PREFIXES, ORKESTREL_RANGE_PATTERN, SERVICE_SCRIPT_PATH, SHOWCASE_CONFIG_PATH, SHOWCASE_DEV_DEPENDENCIES, SOURCE_BROWSER_DEV_DEPENDENCIES, SRC_MATRIX, ScaffoldError, VERSION_PATTERN, applyOverrides, artifactToFinding, artifactToHex, artifactsToQuestions, blueprintToConfigArtifacts, blueprintToDevDependencies, blueprintToDocumentArtifacts, blueprintToGuideArtifacts, blueprintToMachinery, blueprintToManifest, blueprintToOrchestrationArtifacts, blueprintToQuestions, blueprintToRootTsconfig, blueprintToRootVite, blueprintToScripts, blueprintToSourceArtifacts, blueprintToTestArtifacts, bytesToHex, catalogToLayers, cloneValue, compareVersions, computeBytes, computeHash, contentToHex, createBlueprint, createCompiler, dependenciesToQuestions, extractVersion, inferDrift, inferGroup, isArtifact, isAudit, isBlueprint, isCatalogEntry, isCollection, isCompilerHooks, isCompilerOptions, isContent, isDependency, isDependencyName, isEnvironment, isFinding, isGroup, isGroups, isHex, isMirror, isOverride, isPath, isPlan, isQuestion, isScaffoldError, isSnapshot, manifestToDependencies, manifestToName, matchesDriftReachability, matchesEngines, matchesOrchestrationPath, matchesRange, nameToGuide, nameToHostArtifacts, overridesToQuestions, parseBlueprint, parseCompilerOptions, parseGroups, parseSnapshot, pathToCondition, planToFindings, planToHash, planToSummary, selectGroups, selectHostPaths, serializeTypeScriptString, srcToEntry, srcToExports, srcToRoot };
4201
4340
 
4202
4341
  //# sourceMappingURL=index.js.map