@orkestrel/scaffold 0.0.45 → 0.0.47

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 (37) hide show
  1. package/dist/bin/main.js +179 -44
  2. package/dist/bin/main.js.map +1 -1
  3. package/dist/host/AGENTS.md +1 -0
  4. package/dist/host/agents/orchestration.md +3 -1
  5. package/dist/host/claude/agents/codex.md +4 -4
  6. package/dist/host/claude/agents/orkestrel.md +6 -5
  7. package/dist/host/claude/rules/documentation.md +2 -1
  8. package/dist/host/claude/rules/quality.md +3 -0
  9. package/dist/host/claude/rules/tests.md +19 -0
  10. package/dist/host/claude/rules/workspace.md +28 -21
  11. package/dist/host/claude/settings.json +781 -2
  12. package/dist/host/codex/config.toml +4 -0
  13. package/dist/host/configs/policy.ts +167 -10
  14. package/dist/host/cursor/mcp.json +4 -0
  15. package/dist/host/dotfiles/mcp.json +4 -0
  16. package/dist/host/dotfiles/oxlintrc.json +9 -0
  17. package/dist/host/guides/scaffold.md +143 -44
  18. package/dist/host/scripts/codex.sh +0 -0
  19. package/dist/host/scripts/cursor.sh +0 -0
  20. package/dist/host/scripts/deps.sh +0 -0
  21. package/dist/host/scripts/ollama.sh +0 -0
  22. package/dist/host/tests/config.test.ts +126 -11
  23. package/dist/host/tests/policy.test.ts +7 -0
  24. package/dist/host/tests/setupPolicy.ts +222 -8
  25. package/dist/src/core/index.cjs +420 -23
  26. package/dist/src/core/index.cjs.map +1 -1
  27. package/dist/src/core/index.d.cts +102 -9
  28. package/dist/src/core/index.d.ts +102 -9
  29. package/dist/src/core/index.js +416 -24
  30. package/dist/src/core/index.js.map +1 -1
  31. package/dist/src/server/index.cjs +41 -49
  32. package/dist/src/server/index.cjs.map +1 -1
  33. package/dist/src/server/index.d.cts +9 -8
  34. package/dist/src/server/index.d.ts +9 -8
  35. package/dist/src/server/index.js +42 -50
  36. package/dist/src/server/index.js.map +1 -1
  37. package/package.json +8 -5
@@ -1,6 +1,118 @@
1
1
  import { andOf, arrayOf, attempt, canonicalStringify, cloneJSONValue, compareValues, enumerableKeys, holds, isArray, isBoolean, isFunction, isRecord, isString, limitEntries, literalOf, parseJSON, recordOf, sortValues, stringOf, unionOf } from "@orkestrel/contract";
2
2
  import { fillTemplate } from "@orkestrel/template";
3
3
  import { Emitter } from "@orkestrel/emitter";
4
+ var package_default = {
5
+ name: "@orkestrel/scaffold",
6
+ version: "0.0.47",
7
+ description: "Scaffold workspaces with five commands: new, audit, repair, catalog, and overwrite.",
8
+ keywords: [
9
+ "audit",
10
+ "catalog",
11
+ "new",
12
+ "overwrite",
13
+ "repair"
14
+ ],
15
+ homepage: "https://github.com/orkestrel/scaffold#readme",
16
+ bugs: "https://github.com/orkestrel/scaffold/issues",
17
+ license: "MIT",
18
+ repository: {
19
+ "type": "git",
20
+ "url": "git+https://github.com/orkestrel/scaffold.git"
21
+ },
22
+ bin: { "scaffold": "dist/bin/main.js" },
23
+ files: [
24
+ "dist/src",
25
+ "dist/bin",
26
+ "dist/host",
27
+ "README.md"
28
+ ],
29
+ type: "module",
30
+ sideEffects: ["./src/bin/main.ts", "./dist/bin/main.js"],
31
+ main: "./dist/src/core/index.cjs",
32
+ module: "./dist/src/core/index.js",
33
+ exports: {
34
+ ".": {
35
+ "import": {
36
+ "types": "./dist/src/core/index.d.ts",
37
+ "default": "./dist/src/core/index.js"
38
+ },
39
+ "require": {
40
+ "types": "./dist/src/core/index.d.cts",
41
+ "default": "./dist/src/core/index.cjs"
42
+ }
43
+ },
44
+ "./server": {
45
+ "import": {
46
+ "types": "./dist/src/server/index.d.ts",
47
+ "default": "./dist/src/server/index.js"
48
+ },
49
+ "require": {
50
+ "types": "./dist/src/server/index.d.cts",
51
+ "default": "./dist/src/server/index.cjs"
52
+ }
53
+ },
54
+ "./package.json": "./package.json"
55
+ },
56
+ publishConfig: { "access": "public" },
57
+ scripts: {
58
+ "clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
59
+ "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)\"",
60
+ "scaffold": "node ./dist/bin/main.js",
61
+ "lint": "oxlint --config .oxlintrc.json --fix --deny-warnings .",
62
+ "check": "tsc --noEmit --project tsconfig.json && npm run check:src",
63
+ "check:src": "npm run check:src:core && npm run check:src:server && npm run check:src:bin",
64
+ "check:src:core": "tsc --noEmit -p configs/src/tsconfig.core.json",
65
+ "check:src:server": "tsc --noEmit -p configs/src/tsconfig.server.json",
66
+ "check:src:bin": "tsc --noEmit -p configs/src/tsconfig.bin.json",
67
+ "format": "oxfmt --config .oxfmtrc.json --write .",
68
+ "format:check": "oxfmt --config .oxfmtrc.json --check .",
69
+ "lint:check": "oxlint --config .oxlintrc.json --deny-warnings .",
70
+ "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:guides",
71
+ "test:src:core": "vitest run --config vite.config.ts --no-cache --reporter=dot --project src:core",
72
+ "test:src:server": "vitest run --config vite.config.ts --no-cache --reporter=dot --project src:server",
73
+ "test:src:bin": "vitest run --config vite.config.ts --no-cache --reporter=dot --project src:bin",
74
+ "test:policy": "vitest run --config vite.config.ts --no-cache --reporter=dot --project policy",
75
+ "test:config": "vitest run --config vite.config.ts --no-cache --reporter=dot --project config",
76
+ "test:guides": "vitest run --config vite.config.ts --no-cache --reporter=dot --project guides",
77
+ "test:distribution": "vitest run --config vite.config.ts --no-cache --reporter=dot --project distribution",
78
+ "test:probe": "vitest run --config vite.config.ts --no-cache --reporter=verbose --project probe",
79
+ "test:bench": "vitest bench --config vite.config.ts --no-cache --project probe",
80
+ "build": "npm run clean && npm run build:src && npm run build:host",
81
+ "build:src": "npm run build:src:core && npm run build:src:server && npm run build:src:bin",
82
+ "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",
83
+ "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",
84
+ "build:src:bin": "vite build --config configs/src/vite.bin.config.ts",
85
+ "build:host": "node -e \"import('./dist/src/server/index.js').then((m)=>{const n=m.stageHost(process.cwd(),'dist/host').length;console.log('build-host: staged '+n+' file(s) into dist/host')})\"",
86
+ "prepack": "npm run build",
87
+ "prepublishOnly": "npm run format:check && npm run lint:check && npm run check && npm run build && npm test && npm run test:distribution -- --mode release"
88
+ },
89
+ dependencies: {
90
+ "@orkestrel/console": "^0.0.9",
91
+ "@orkestrel/contract": "^0.0.13",
92
+ "@orkestrel/emitter": "^0.0.7",
93
+ "@orkestrel/markdown": "^0.0.9",
94
+ "@orkestrel/process": "^0.0.4",
95
+ "@orkestrel/template": "^0.0.4"
96
+ },
97
+ devDependencies: {
98
+ "@microsoft/api-extractor": "^7.59.0",
99
+ "@orkestrel/guide": "^0.0.12",
100
+ "@orkestrel/html": "^0.0.4",
101
+ "@orkestrel/probe": "^0.0.2",
102
+ "@orkestrel/test": "^0.0.8",
103
+ "@types/node": "^26.2.0",
104
+ "@vitest/browser-playwright": "^4.1.11",
105
+ "oxfmt": "^0.64.0",
106
+ "oxlint": "^1.79.0",
107
+ "playwright": "^1.62.1",
108
+ "typescript": "^6.0.3",
109
+ "vite": "^8.2.2",
110
+ "vite-plugin-dts": "^5.0.3",
111
+ "vitest": "^4.1.11"
112
+ },
113
+ engines: { "node": ">=22.12.0" }
114
+ };
115
+ //#endregion
4
116
  //#region src/core/constants.ts
5
117
  /**
6
118
  * The `Environment` values, frozen.
@@ -301,6 +413,24 @@ var MAX_AUDIT_FINDINGS = MAX_COLLECTION_ITEMS * 2;
301
413
  var MAX_ARTIFACT_BYTES = 5242880;
302
414
  /** Maximum length of the hexadecimal string carrying one artifact's bytes. */
303
415
  var MAX_ARTIFACT_HEX_LENGTH = MAX_ARTIFACT_BYTES * 2;
416
+ /**
417
+ * Maximum decoded bytes accepted from one registry response.
418
+ *
419
+ * @remarks
420
+ * The 2026-08-21 abbreviated-packument measurements were 8,647,138 bytes for
421
+ * TypeScript, 8,077,438 for Playwright, 2,315,360 for `@types/node`, 2,298,256
422
+ * for Vite, and 1,272,652 for Vitest. The bound leaves headroom above those
423
+ * registry answers.
424
+ */
425
+ var MAX_REGISTRY_BYTES = 33554432;
426
+ /**
427
+ * Maximum decoded bytes accepted across one registry-reading call.
428
+ *
429
+ * @remarks
430
+ * The 2026-08-21 browser-workspace registry set measured about 24 MiB. The
431
+ * bound leaves headroom for that set to grow without making a call unbounded.
432
+ */
433
+ var MAX_TOTAL_REGISTRY_BYTES = 100663296;
304
434
  /** Maximum bytes accepted for one package or vendored-host manifest. */
305
435
  var MAX_MANIFEST_BYTES = 1048576;
306
436
  /** Maximum bytes retained across one whole plan or audit. */
@@ -313,32 +443,33 @@ var DEFAULT_VERSION = "0.0.1";
313
443
  var DEFAULT_ENGINES = `>=${MINIMUM_NODE_VERSION}`;
314
444
  /** The tooling versions scaffold and every generated workspace share. */
315
445
  var BASE_DEV_DEPENDENCIES = Object.freeze({
316
- "@orkestrel/guide": "^0.0.12",
317
- "@orkestrel/scaffold": "^0.0.45",
318
- "@orkestrel/test": "^0.0.7",
319
- "@types/node": "^26.2.0",
320
- oxfmt: "^0.64.0",
321
- oxlint: "^1.79.0",
322
- typescript: "^6.0.3",
323
- vite: "~8.2.1",
324
- vitest: "^4.1.11"
446
+ "@orkestrel/guide": package_default.devDependencies["@orkestrel/guide"],
447
+ "@orkestrel/probe": package_default.devDependencies["@orkestrel/probe"],
448
+ "@orkestrel/scaffold": `^${package_default.version}`,
449
+ "@orkestrel/test": package_default.devDependencies["@orkestrel/test"],
450
+ "@types/node": package_default.devDependencies["@types/node"],
451
+ oxfmt: package_default.devDependencies.oxfmt,
452
+ oxlint: package_default.devDependencies.oxlint,
453
+ typescript: package_default.devDependencies.typescript,
454
+ vite: package_default.devDependencies.vite,
455
+ vitest: package_default.devDependencies.vitest
325
456
  });
326
457
  /** The development dependencies that emit declarations for published source or an executable. */
327
458
  var DECLARATION_DEV_DEPENDENCIES = Object.freeze({
328
- "@microsoft/api-extractor": "^7.58.12",
329
- "vite-plugin-dts": "^5.0.3"
459
+ "@microsoft/api-extractor": package_default.devDependencies["@microsoft/api-extractor"],
460
+ "vite-plugin-dts": package_default.devDependencies["vite-plugin-dts"]
330
461
  });
331
462
  /** The development dependencies a published browser `src` environment adds. */
332
463
  var SOURCE_BROWSER_DEV_DEPENDENCIES = Object.freeze({
333
- "@vitest/browser-playwright": "^4.1.11",
334
- playwright: "^1.62.1"
464
+ "@vitest/browser-playwright": package_default.devDependencies["@vitest/browser-playwright"],
465
+ playwright: package_default.devDependencies.playwright
335
466
  });
336
467
  /** The development dependency every private `app` environment adds. */
337
- var APP_DEV_DEPENDENCIES = Object.freeze({ "@orkestrel/contract": "^0.0.12" });
468
+ var APP_DEV_DEPENDENCIES = Object.freeze({ "@orkestrel/contract": package_default.dependencies["@orkestrel/contract"] });
338
469
  /** The development dependencies a private Vue browser application adds. */
339
470
  var APP_BROWSER_DEV_DEPENDENCIES = Object.freeze({
340
471
  ...SOURCE_BROWSER_DEV_DEPENDENCIES,
341
- "@orkestrel/html": "^0.0.4",
472
+ "@orkestrel/html": package_default.devDependencies["@orkestrel/html"],
342
473
  "@vitejs/plugin-vue": "^6.0.8",
343
474
  vue: "^3.5.40",
344
475
  "vue-tsc": "^3.3.7"
@@ -350,13 +481,13 @@ var APP_BROWSER_DEV_DEPENDENCIES = Object.freeze({
350
481
  * ```ts
351
482
  * import { SHOWCASE_DEV_DEPENDENCIES } from '@orkestrel/scaffold'
352
483
  *
353
- * SHOWCASE_DEV_DEPENDENCIES['vite-plugin-singlefile'] // '^2.3.3'
484
+ * SHOWCASE_DEV_DEPENDENCIES['vite-plugin-singlefile'] // the showcase plugin range
354
485
  * ```
355
486
  */
356
487
  var SHOWCASE_DEV_DEPENDENCIES = Object.freeze({ "vite-plugin-singlefile": "^2.3.3" });
357
488
  /** The development dependencies a private server application adds. */
358
489
  var APP_SERVER_DEV_DEPENDENCIES = Object.freeze({
359
- "@orkestrel/emitter": "^0.0.7",
490
+ "@orkestrel/emitter": package_default.dependencies["@orkestrel/emitter"],
360
491
  "@orkestrel/middleware": "^0.0.16",
361
492
  "@orkestrel/router": "^0.0.10",
362
493
  "@orkestrel/server": "^0.0.14"
@@ -792,7 +923,11 @@ export const service = (options?: UserConfig): UserConfig =>
792
923
  options ?? {},
793
924
  )
794
925
  `,
795
- probe: `// A workbench, not a proof. No gate selects this project.
926
+ probe: `// A workbench, not a proof. No gate selects this project. Run in test mode by the
927
+ // \`test:probe\` script, it collects \`tmp/probe/**/*.test.ts\`. Run in benchmark mode by the
928
+ // \`test:bench\` script, the same workbench also collects \`tests/**/*.test.ts\` for a \`bench\` block,
929
+ // so a suite may carry a bench beside its ordinary tests without a second project. The mode
930
+ // guard around each \`bench\` call keeps it out of test mode, so it never executes there.
796
931
  export const probe = (options?: UserConfig): UserConfig =>
797
932
  mergeConfig(
798
933
  {
@@ -803,6 +938,9 @@ export const probe = (options?: UserConfig): UserConfig =>
803
938
  setupFiles: ['./tests/setup.ts'],
804
939
  environment: 'node',
805
940
  browser: { enabled: false },
941
+ fileParallelism: false,
942
+ pool: 'threads',
943
+ benchmark: { include: ['tmp/probe/**/*.test.ts', 'tests/**/*.test.ts'] },
806
944
  },
807
945
  },
808
946
  options ?? {},
@@ -2690,6 +2828,32 @@ function extractVersion(version) {
2690
2828
  ];
2691
2829
  }
2692
2830
  /**
2831
+ * Extract the major component of an admitted dependency range.
2832
+ *
2833
+ * @param range - The candidate range text.
2834
+ * @returns The major number, or `undefined` when the text is not a canonical
2835
+ * major caret or an admitted full-version form.
2836
+ *
2837
+ * @remarks
2838
+ * A canonical toolchain range is `^MAJOR`. Existing consumer declarations may
2839
+ * instead carry an exact `major.minor.patch` version or that version under a
2840
+ * caret or tilde. The projection reads those forms without deciding whether a
2841
+ * version satisfies them; {@link matchesRange} owns that separate question.
2842
+ *
2843
+ * @example
2844
+ * ```ts
2845
+ * import { extractRangeMajor } from '@orkestrel/scaffold'
2846
+ *
2847
+ * extractRangeMajor('^6') // the declared major
2848
+ * extractRangeMajor('>=6.0.0') // undefined
2849
+ * ```
2850
+ */
2851
+ function extractRangeMajor(range) {
2852
+ const match = /^(?:\^(0|[1-9]\d*)|(?:\^|~)?(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-]*))*)?)$/.exec(range);
2853
+ const major = match?.[1] ?? match?.[2];
2854
+ return major === void 0 ? void 0 : Number(major);
2855
+ }
2856
+ /**
2693
2857
  * Compare two versions by their numeric components.
2694
2858
  *
2695
2859
  * @param left - The version ordered first when it compares lower.
@@ -3169,6 +3333,7 @@ function blueprintToScripts(blueprint) {
3169
3333
  if (blueprint.guides) scripts["test:guides"] = `${vitest} --project guides`;
3170
3334
  if (blueprint.conformance) scripts["test:conformance"] = `${vitest} --project conformance`;
3171
3335
  scripts["test:probe"] = "vitest run --config vite.config.ts --no-cache --reporter=verbose --project probe";
3336
+ scripts["test:bench"] = "vitest bench --config vite.config.ts --no-cache --project probe";
3172
3337
  if (distributes) scripts["test:distribution"] = `${vitest} --project distribution`;
3173
3338
  if (integrates) scripts["test:integration"] = `${vitest} --project integration`;
3174
3339
  if (blueprint.service) scripts["test:service"] = `${vitest} --project service`;
@@ -3201,11 +3366,14 @@ function blueprintToScripts(blueprint) {
3201
3366
  scripts.serve = "node dist/app/server/main.cjs";
3202
3367
  scripts["serve:build"] = "npm run build:app:server && npm run serve";
3203
3368
  }
3204
- if (publishes) scripts.prepublishOnly = [
3205
- "npm run format:check && npm run lint:check && npm run check && npm run build && npm test",
3206
- ...distributes ? ["npm run test:distribution -- --mode release"] : [],
3207
- ...blueprint.service ? ["npm run test:service"] : []
3208
- ].join(" && ");
3369
+ if (publishes) {
3370
+ scripts.prepack = scripts.build;
3371
+ scripts.prepublishOnly = [
3372
+ "npm run format:check && npm run lint:check && npm run check && npm run build && npm test",
3373
+ ...distributes ? ["npm run test:distribution -- --mode release"] : [],
3374
+ ...blueprint.service ? ["npm run test:service"] : []
3375
+ ].join(" && ");
3376
+ }
3209
3377
  return scripts;
3210
3378
  }
3211
3379
  /**
@@ -4012,6 +4180,230 @@ function applyOverrides(artifacts, overrides) {
4012
4180
  });
4013
4181
  }
4014
4182
  /**
4183
+ * Replace declared dependency ranges in package manifest text.
4184
+ *
4185
+ * @param manifest - The manifest text to compile.
4186
+ * @param dependencies - The declared names and replacement ranges.
4187
+ * @returns The manifest with every matching dependency-section value replaced,
4188
+ * or `undefined` when any name has no quoted declaration in those sections.
4189
+ *
4190
+ * @remarks
4191
+ * The compiler replaces values in place instead of serializing the manifest,
4192
+ * so description, keywords, scripts, key order, indentation, and every byte
4193
+ * outside the named ranges survive. Every occurrence in `dependencies`,
4194
+ * `devDependencies`, and `peerDependencies` moves, which keeps duplicate
4195
+ * declarations aligned until the manifest's own validation reports the
4196
+ * duplicate. An override or resolution with the same name stays untouched.
4197
+ *
4198
+ * @example
4199
+ * ```ts
4200
+ * import { replaceManifestRanges } from '@orkestrel/scaffold'
4201
+ *
4202
+ * const manifest = '{"devDependencies":{"typescript":"^6"}}\n'
4203
+ * replaceManifestRanges(manifest, [{ name: 'typescript', range: '^7' }])
4204
+ * // the manifest with the declared range replaced
4205
+ * ```
4206
+ */
4207
+ function replaceManifestRanges(manifest, dependencies) {
4208
+ if (dependencies.length === 0) return manifest;
4209
+ const sectionNames = /* @__PURE__ */ new Set([
4210
+ "dependencies",
4211
+ "devDependencies",
4212
+ "peerDependencies"
4213
+ ]);
4214
+ const sections = [];
4215
+ let depth = 0;
4216
+ let cursor = 0;
4217
+ while (cursor < manifest.length) {
4218
+ const character = manifest.charAt(cursor);
4219
+ if (character === "{") {
4220
+ depth += 1;
4221
+ cursor += 1;
4222
+ continue;
4223
+ }
4224
+ if (character === "}") {
4225
+ depth -= 1;
4226
+ cursor += 1;
4227
+ continue;
4228
+ }
4229
+ if (character !== "\"") {
4230
+ cursor += 1;
4231
+ continue;
4232
+ }
4233
+ const start = cursor;
4234
+ cursor += 1;
4235
+ while (cursor < manifest.length) {
4236
+ if (manifest.charAt(cursor) === "\\") {
4237
+ cursor += 2;
4238
+ continue;
4239
+ }
4240
+ if (manifest.charAt(cursor) === "\"") break;
4241
+ cursor += 1;
4242
+ }
4243
+ if (cursor >= manifest.length) return void 0;
4244
+ const end = cursor + 1;
4245
+ if (depth === 1) {
4246
+ const key = parseJSON(manifest.slice(start, end));
4247
+ let value = end;
4248
+ while (value < manifest.length && /\s/u.test(manifest.charAt(value))) value += 1;
4249
+ if (manifest.charAt(value) === ":") {
4250
+ value += 1;
4251
+ while (value < manifest.length && /\s/u.test(manifest.charAt(value))) value += 1;
4252
+ if (typeof key === "string" && sectionNames.has(key) && manifest.charAt(value) === "{") {
4253
+ let sectionDepth = 0;
4254
+ let sectionCursor = value;
4255
+ while (sectionCursor < manifest.length) {
4256
+ const sectionCharacter = manifest.charAt(sectionCursor);
4257
+ if (sectionCharacter === "\"") {
4258
+ sectionCursor += 1;
4259
+ while (sectionCursor < manifest.length) {
4260
+ if (manifest.charAt(sectionCursor) === "\\") {
4261
+ sectionCursor += 2;
4262
+ continue;
4263
+ }
4264
+ if (manifest.charAt(sectionCursor) === "\"") break;
4265
+ sectionCursor += 1;
4266
+ }
4267
+ if (sectionCursor >= manifest.length) return void 0;
4268
+ } else if (sectionCharacter === "{") sectionDepth += 1;
4269
+ else if (sectionCharacter === "}") {
4270
+ sectionDepth -= 1;
4271
+ if (sectionDepth === 0) {
4272
+ sections.push({
4273
+ start: value,
4274
+ end: sectionCursor + 1
4275
+ });
4276
+ break;
4277
+ }
4278
+ }
4279
+ sectionCursor += 1;
4280
+ }
4281
+ }
4282
+ }
4283
+ }
4284
+ cursor = end;
4285
+ }
4286
+ const replacements = new Map(dependencies.map(({ name, range }) => [name, range]));
4287
+ const declared = /* @__PURE__ */ new Set();
4288
+ let compiled = manifest;
4289
+ for (const bounds of sections.reverse()) {
4290
+ let section = compiled.slice(bounds.start, bounds.end);
4291
+ let sectionDepth = 0;
4292
+ let sectionCursor = 0;
4293
+ while (sectionCursor < section.length) {
4294
+ const character = section.charAt(sectionCursor);
4295
+ if (character === "{") {
4296
+ sectionDepth += 1;
4297
+ sectionCursor += 1;
4298
+ continue;
4299
+ }
4300
+ if (character === "}") {
4301
+ sectionDepth -= 1;
4302
+ sectionCursor += 1;
4303
+ continue;
4304
+ }
4305
+ if (character !== "\"") {
4306
+ sectionCursor += 1;
4307
+ continue;
4308
+ }
4309
+ const keyStart = sectionCursor;
4310
+ sectionCursor += 1;
4311
+ while (sectionCursor < section.length) {
4312
+ if (section.charAt(sectionCursor) === "\\") {
4313
+ sectionCursor += 2;
4314
+ continue;
4315
+ }
4316
+ if (section.charAt(sectionCursor) === "\"") break;
4317
+ sectionCursor += 1;
4318
+ }
4319
+ if (sectionCursor >= section.length) return void 0;
4320
+ const keyEnd = sectionCursor + 1;
4321
+ const key = parseJSON(section.slice(keyStart, keyEnd));
4322
+ let valueStart = keyEnd;
4323
+ while (valueStart < section.length && /\s/u.test(section.charAt(valueStart))) valueStart += 1;
4324
+ if (sectionDepth !== 1 || section.charAt(valueStart) !== ":") {
4325
+ sectionCursor = keyEnd;
4326
+ continue;
4327
+ }
4328
+ valueStart += 1;
4329
+ while (valueStart < section.length && /\s/u.test(section.charAt(valueStart))) valueStart += 1;
4330
+ if (typeof key !== "string" || section.charAt(valueStart) !== "\"") {
4331
+ sectionCursor = keyEnd;
4332
+ continue;
4333
+ }
4334
+ const replacement = replacements.get(key);
4335
+ if (replacement === void 0) {
4336
+ sectionCursor = keyEnd;
4337
+ continue;
4338
+ }
4339
+ let valueEnd = valueStart + 1;
4340
+ while (valueEnd < section.length) {
4341
+ if (section.charAt(valueEnd) === "\\") {
4342
+ valueEnd += 2;
4343
+ continue;
4344
+ }
4345
+ if (section.charAt(valueEnd) === "\"") break;
4346
+ valueEnd += 1;
4347
+ }
4348
+ if (valueEnd >= section.length) return void 0;
4349
+ const range = JSON.stringify(replacement);
4350
+ section = section.slice(0, valueStart) + range + section.slice(valueEnd + 1);
4351
+ declared.add(key);
4352
+ sectionCursor = valueStart + range.length;
4353
+ }
4354
+ compiled = compiled.slice(0, bounds.start) + section + compiled.slice(bounds.end);
4355
+ }
4356
+ return dependencies.every(({ name }) => declared.has(name)) ? compiled : void 0;
4357
+ }
4358
+ /**
4359
+ * Replace dependency ranges in a plan's manifest and recompute its identity.
4360
+ *
4361
+ * @param plan - The plan carrying the manifest artifact to compile.
4362
+ * @param dependencies - The declared names and replacement ranges.
4363
+ * @returns A plan with replaced manifest ranges and a matching hash, or
4364
+ * `undefined` when the manifest or its identity cannot be compiled.
4365
+ *
4366
+ * @remarks
4367
+ * The blueprint remains the workspace specification that produced the plan.
4368
+ * Registry answers alter only the manifest artifact that materialization will
4369
+ * write. Recomputing the hash in the same compiler keeps the plan's identity
4370
+ * tied to those final bytes rather than to the unresolved floor.
4371
+ *
4372
+ * @example
4373
+ * ```ts
4374
+ * import { replacePlanRanges } from '@orkestrel/scaffold'
4375
+ *
4376
+ * replacePlanRanges(plan, releases) // the plan carrying the resolved manifest ranges
4377
+ * ```
4378
+ */
4379
+ function replacePlanRanges(plan, dependencies) {
4380
+ let replaced = false;
4381
+ let refused = false;
4382
+ const artifacts = plan.artifacts.map((artifact) => {
4383
+ if (artifact.path !== "package.json" || artifact.origin === "host") return artifact;
4384
+ const content = replaceManifestRanges(artifact.content, dependencies);
4385
+ if (content === void 0) {
4386
+ refused = true;
4387
+ return artifact;
4388
+ }
4389
+ replaced = true;
4390
+ return {
4391
+ ...artifact,
4392
+ content
4393
+ };
4394
+ });
4395
+ if (!replaced || refused) return void 0;
4396
+ const compiled = {
4397
+ ...plan,
4398
+ artifacts
4399
+ };
4400
+ const hash = planToHash(compiled);
4401
+ return hash === void 0 ? void 0 : {
4402
+ ...compiled,
4403
+ hash
4404
+ };
4405
+ }
4406
+ /**
4015
4407
  * Compute a plan's content identity.
4016
4408
  *
4017
4409
  * @param plan - The plan to identify.
@@ -4842,6 +5234,6 @@ var Compiler = class {
4842
5234
  }
4843
5235
  };
4844
5236
  //#endregion
4845
- 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, CONFORMANCE_TEST_PATH, CONTROL_CHARACTER_PATTERN, Compiler, DECLARATION_DEV_DEPENDENCIES, DEFAULT_ENGINES, DEFAULT_VERSION, DEPENDENCY_NAME_PATTERN, DISTRIBUTION_TEST_PATH, ENGINES_PATTERN, ENVIRONMENTS, EXECUTABLE_PATHS, EXTRA_RANGE_PATTERN, FLOOR_RANGE_PATTERN, FOREIGN_NAME_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, PRINT_WIDTH, SERVICE_SCRIPT_PATH, SERVICE_SETUP_PATH, SERVICE_TEST_INCLUDE, SHOWCASE_CONFIG_PATH, SHOWCASE_DEV_DEPENDENCIES, SOURCE_BROWSER_DEV_DEPENDENCIES, SRC_MATRIX, ScaffoldError, TAB_WIDTH, VERSION_PATTERN, WORKSPACE_OWNED_PATHS, 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, 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, matchesPrintWidth, matchesRange, nameToGuide, nameToHostArtifacts, nameToRewrite, overridesToQuestions, parseBlueprint, parseCompilerOptions, parseGroups, parseSnapshot, pathToCondition, planToFindings, planToHash, planToSummary, selectGroups, selectHostPaths, serializeTypeScriptString, srcToEntry, srcToExports, srcToRoot };
5237
+ 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, CONFORMANCE_TEST_PATH, CONTROL_CHARACTER_PATTERN, Compiler, DECLARATION_DEV_DEPENDENCIES, DEFAULT_ENGINES, DEFAULT_VERSION, DEPENDENCY_NAME_PATTERN, DISTRIBUTION_TEST_PATH, ENGINES_PATTERN, ENVIRONMENTS, EXECUTABLE_PATHS, EXTRA_RANGE_PATTERN, FLOOR_RANGE_PATTERN, FOREIGN_NAME_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_REGISTRY_BYTES, MAX_TOTAL_ARTIFACT_BYTES, MAX_TOTAL_REGISTRY_BYTES, MINIMUM_NODE_VERSION, NAME_PATTERN, ORCHESTRATION_PATH_NAMES, ORCHESTRATION_PATH_PREFIXES, ORKESTREL_RANGE_PATTERN, PRINT_WIDTH, SERVICE_SCRIPT_PATH, SERVICE_SETUP_PATH, SERVICE_TEST_INCLUDE, SHOWCASE_CONFIG_PATH, SHOWCASE_DEV_DEPENDENCIES, SOURCE_BROWSER_DEV_DEPENDENCIES, SRC_MATRIX, ScaffoldError, TAB_WIDTH, VERSION_PATTERN, WORKSPACE_OWNED_PATHS, 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, dependenciesToQuestions, extractRangeMajor, 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, matchesPrintWidth, matchesRange, nameToGuide, nameToHostArtifacts, nameToRewrite, overridesToQuestions, parseBlueprint, parseCompilerOptions, parseGroups, parseSnapshot, pathToCondition, planToFindings, planToHash, planToSummary, replaceManifestRanges, replacePlanRanges, selectGroups, selectHostPaths, serializeTypeScriptString, srcToEntry, srcToExports, srcToRoot };
4846
5238
 
4847
5239
  //# sourceMappingURL=index.js.map