@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
@@ -1060,7 +1060,7 @@ export declare class Compiler implements CompilerInterface {
1060
1060
  conformance: "// Where this package drifts from the official tooling it stays compatible with.\n// The subject is this package, so the proof is hermetic and stays in `npm test`.\nexport const conformance = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'conformance', color: 'magenta' },\n\t\t\t\tinclude: ['tests/conformance.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
1061
1061
  service: "// The live external services this package drives. It starts nothing itself:\n// `scripts/service.sh` provisions, `tests/setupService.ts` proves readiness, and\n// the project stays out of `npm test` because a real service answers it.\nexport const service = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'service', color: 'red' },\n\t\t\t\tinclude: ['tests/service/**/*.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts', './tests/setupService.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t\ttestTimeout: 120_000,\n\t\t\t\thookTimeout: 120_000,\n\t\t\t\tfileParallelism: false,\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
1062
1062
  distribution: "export const distribution = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'distribution', color: 'cyan' },\n\t\t\t\tinclude: ['tests/distribution.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\ttestTimeout: 120_000,\n\t\t\t\thookTimeout: 120_000,\n\t\t\t\tfileParallelism: false,\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
1063
- probe: "// A workbench, not a proof. No gate selects this project.\nexport const probe = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'probe', color: 'gray' },\n\t\t\t\tinclude: ['tmp/probe/**/*.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
1063
+ probe: "// A workbench, not a proof. No gate selects this project. Run in test mode by the\n// `test:probe` script, it collects `tmp/probe/**/*.test.ts`. Run in benchmark mode by the\n// `test:bench` script, the same workbench also collects `tests/**/*.test.ts` for a `bench` block,\n// so a suite may carry a bench beside its ordinary tests without a second project. The mode\n// guard around each `bench` call keeps it out of test mode, so it never executes there.\nexport const probe = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'probe', color: 'gray' },\n\t\t\t\tinclude: ['tmp/probe/**/*.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t\tfileParallelism: false,\n\t\t\t\tpool: 'threads',\n\t\t\t\tbenchmark: { include: ['tmp/probe/**/*.test.ts', 'tests/**/*.test.ts'] },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
1064
1064
  integration: "export const integration = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'integration', color: 'blue' },\n\t\t\t\tinclude: ['tests/integration.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n{{global}}\t\t\t\tenvironment: 'node',\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
1065
1065
  }>;
1066
1066
  tsconfigs: Readonly<{
@@ -1283,6 +1283,29 @@ export declare class Compiler implements CompilerInterface {
1283
1283
  /** The registry-only semver subset accepted for a development extra's range. */
1284
1284
  export declare const EXTRA_RANGE_PATTERN: RegExp;
1285
1285
 
1286
+ /**
1287
+ * Extract the major component of an admitted dependency range.
1288
+ *
1289
+ * @param range - The candidate range text.
1290
+ * @returns The major number, or `undefined` when the text is not a canonical
1291
+ * major caret or an admitted full-version form.
1292
+ *
1293
+ * @remarks
1294
+ * A canonical toolchain range is `^MAJOR`. Existing consumer declarations may
1295
+ * instead carry an exact `major.minor.patch` version or that version under a
1296
+ * caret or tilde. The projection reads those forms without deciding whether a
1297
+ * version satisfies them; {@link matchesRange} owns that separate question.
1298
+ *
1299
+ * @example
1300
+ * ```ts
1301
+ * import { extractRangeMajor } from '@orkestrel/scaffold'
1302
+ *
1303
+ * extractRangeMajor('^6') // the declared major
1304
+ * extractRangeMajor('>=6.0.0') // undefined
1305
+ * ```
1306
+ */
1307
+ export declare function extractRangeMajor(range: string): number | undefined;
1308
+
1286
1309
  /**
1287
1310
  * Extract the major, minor, and patch components of an exact version.
1288
1311
  *
@@ -2078,9 +2101,29 @@ export declare class Compiler implements CompilerInterface {
2078
2101
  /** Maximum length of one declared package range. */
2079
2102
  export declare const MAX_RANGE_LENGTH = 2048;
2080
2103
 
2104
+ /**
2105
+ * Maximum decoded bytes accepted from one registry response.
2106
+ *
2107
+ * @remarks
2108
+ * The 2026-08-21 abbreviated-packument measurements were 8,647,138 bytes for
2109
+ * TypeScript, 8,077,438 for Playwright, 2,315,360 for `@types/node`, 2,298,256
2110
+ * for Vite, and 1,272,652 for Vitest. The bound leaves headroom above those
2111
+ * registry answers.
2112
+ */
2113
+ export declare const MAX_REGISTRY_BYTES = 33554432;
2114
+
2081
2115
  /** Maximum bytes retained across one whole plan or audit. */
2082
2116
  export declare const MAX_TOTAL_ARTIFACT_BYTES = 104857600;
2083
2117
 
2118
+ /**
2119
+ * Maximum decoded bytes accepted across one registry-reading call.
2120
+ *
2121
+ * @remarks
2122
+ * The 2026-08-21 browser-workspace registry set measured about 24 MiB. The
2123
+ * bound leaves headroom for that set to grow without making a call unbounded.
2124
+ */
2125
+ export declare const MAX_TOTAL_REGISTRY_BYTES = 100663296;
2126
+
2084
2127
  /** The oldest Node version the generated toolchain supports. */
2085
2128
  export declare const MINIMUM_NODE_VERSION = "22.12.0";
2086
2129
 
@@ -2527,30 +2570,80 @@ export declare class Compiler implements CompilerInterface {
2527
2570
  }
2528
2571
 
2529
2572
  /**
2530
- * One declared dependency range measured against the registry's latest release.
2573
+ * One declared dependency range measured against a registry release.
2531
2574
  *
2532
2575
  * @remarks
2533
- * A found lookup carries the version upstream reported; one that produced no
2534
- * answer carries the cause and no version. Whether the declared range already
2535
- * admits that version is not recorded, because it is a deterministic function
2536
- * of `range` and `latest`: a stored answer could only disagree with the
2537
- * fields beside it. One centralized helper decides it, and every caller reads
2538
- * the same decision.
2576
+ * `range` is the declared range, and `latest` is the version the producer
2577
+ * selected. A found lookup carries that selected version; one that produced no
2578
+ * answer carries the cause and no selected version. `major`, when present, is
2579
+ * the stable major named by the registry's latest tag in the same answer.
2539
2580
  */
2540
2581
  export declare type Release = {
2541
2582
  readonly name: string;
2542
2583
  readonly range: string;
2543
2584
  readonly lookup: 'found';
2544
2585
  readonly latest: string;
2586
+ readonly major?: number;
2545
2587
  readonly note?: never;
2546
2588
  } | {
2547
2589
  readonly name: string;
2548
2590
  readonly range: string;
2549
2591
  readonly lookup: 'missing' | 'failed';
2550
2592
  readonly note: string;
2593
+ readonly major?: number;
2551
2594
  readonly latest?: never;
2552
2595
  };
2553
2596
 
2597
+ /**
2598
+ * Replace declared dependency ranges in package manifest text.
2599
+ *
2600
+ * @param manifest - The manifest text to compile.
2601
+ * @param dependencies - The declared names and replacement ranges.
2602
+ * @returns The manifest with every matching dependency-section value replaced,
2603
+ * or `undefined` when any name has no quoted declaration in those sections.
2604
+ *
2605
+ * @remarks
2606
+ * The compiler replaces values in place instead of serializing the manifest,
2607
+ * so description, keywords, scripts, key order, indentation, and every byte
2608
+ * outside the named ranges survive. Every occurrence in `dependencies`,
2609
+ * `devDependencies`, and `peerDependencies` moves, which keeps duplicate
2610
+ * declarations aligned until the manifest's own validation reports the
2611
+ * duplicate. An override or resolution with the same name stays untouched.
2612
+ *
2613
+ * @example
2614
+ * ```ts
2615
+ * import { replaceManifestRanges } from '@orkestrel/scaffold'
2616
+ *
2617
+ * const manifest = '{"devDependencies":{"typescript":"^6"}}\n'
2618
+ * replaceManifestRanges(manifest, [{ name: 'typescript', range: '^7' }])
2619
+ * // the manifest with the declared range replaced
2620
+ * ```
2621
+ */
2622
+ export declare function replaceManifestRanges(manifest: string, dependencies: readonly Dependency[]): string | undefined;
2623
+
2624
+ /**
2625
+ * Replace dependency ranges in a plan's manifest and recompute its identity.
2626
+ *
2627
+ * @param plan - The plan carrying the manifest artifact to compile.
2628
+ * @param dependencies - The declared names and replacement ranges.
2629
+ * @returns A plan with replaced manifest ranges and a matching hash, or
2630
+ * `undefined` when the manifest or its identity cannot be compiled.
2631
+ *
2632
+ * @remarks
2633
+ * The blueprint remains the workspace specification that produced the plan.
2634
+ * Registry answers alter only the manifest artifact that materialization will
2635
+ * write. Recomputing the hash in the same compiler keeps the plan's identity
2636
+ * tied to those final bytes rather than to the unresolved floor.
2637
+ *
2638
+ * @example
2639
+ * ```ts
2640
+ * import { replacePlanRanges } from '@orkestrel/scaffold'
2641
+ *
2642
+ * replacePlanRanges(plan, releases) // the plan carrying the resolved manifest ranges
2643
+ * ```
2644
+ */
2645
+ export declare function replacePlanRanges(plan: Plan, dependencies: readonly Dependency[]): Plan | undefined;
2646
+
2554
2647
  /**
2555
2648
  * The one error this package throws, carrying the coded reason it was raised.
2556
2649
  *
@@ -2702,7 +2795,7 @@ export declare class Compiler implements CompilerInterface {
2702
2795
  * ```ts
2703
2796
  * import { SHOWCASE_DEV_DEPENDENCIES } from '@orkestrel/scaffold'
2704
2797
  *
2705
- * SHOWCASE_DEV_DEPENDENCIES['vite-plugin-singlefile'] // '^2.3.3'
2798
+ * SHOWCASE_DEV_DEPENDENCIES['vite-plugin-singlefile'] // the showcase plugin range
2706
2799
  * ```
2707
2800
  */
2708
2801
  export declare const SHOWCASE_DEV_DEPENDENCIES: Readonly<Record<string, string>>;
@@ -1060,7 +1060,7 @@ export declare class Compiler implements CompilerInterface {
1060
1060
  conformance: "// Where this package drifts from the official tooling it stays compatible with.\n// The subject is this package, so the proof is hermetic and stays in `npm test`.\nexport const conformance = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'conformance', color: 'magenta' },\n\t\t\t\tinclude: ['tests/conformance.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
1061
1061
  service: "// The live external services this package drives. It starts nothing itself:\n// `scripts/service.sh` provisions, `tests/setupService.ts` proves readiness, and\n// the project stays out of `npm test` because a real service answers it.\nexport const service = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'service', color: 'red' },\n\t\t\t\tinclude: ['tests/service/**/*.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts', './tests/setupService.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t\ttestTimeout: 120_000,\n\t\t\t\thookTimeout: 120_000,\n\t\t\t\tfileParallelism: false,\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
1062
1062
  distribution: "export const distribution = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'distribution', color: 'cyan' },\n\t\t\t\tinclude: ['tests/distribution.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\ttestTimeout: 120_000,\n\t\t\t\thookTimeout: 120_000,\n\t\t\t\tfileParallelism: false,\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
1063
- probe: "// A workbench, not a proof. No gate selects this project.\nexport const probe = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'probe', color: 'gray' },\n\t\t\t\tinclude: ['tmp/probe/**/*.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
1063
+ probe: "// A workbench, not a proof. No gate selects this project. Run in test mode by the\n// `test:probe` script, it collects `tmp/probe/**/*.test.ts`. Run in benchmark mode by the\n// `test:bench` script, the same workbench also collects `tests/**/*.test.ts` for a `bench` block,\n// so a suite may carry a bench beside its ordinary tests without a second project. The mode\n// guard around each `bench` call keeps it out of test mode, so it never executes there.\nexport const probe = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'probe', color: 'gray' },\n\t\t\t\tinclude: ['tmp/probe/**/*.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t\tfileParallelism: false,\n\t\t\t\tpool: 'threads',\n\t\t\t\tbenchmark: { include: ['tmp/probe/**/*.test.ts', 'tests/**/*.test.ts'] },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
1064
1064
  integration: "export const integration = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'integration', color: 'blue' },\n\t\t\t\tinclude: ['tests/integration.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n{{global}}\t\t\t\tenvironment: 'node',\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
1065
1065
  }>;
1066
1066
  tsconfigs: Readonly<{
@@ -1283,6 +1283,29 @@ export declare class Compiler implements CompilerInterface {
1283
1283
  /** The registry-only semver subset accepted for a development extra's range. */
1284
1284
  export declare const EXTRA_RANGE_PATTERN: RegExp;
1285
1285
 
1286
+ /**
1287
+ * Extract the major component of an admitted dependency range.
1288
+ *
1289
+ * @param range - The candidate range text.
1290
+ * @returns The major number, or `undefined` when the text is not a canonical
1291
+ * major caret or an admitted full-version form.
1292
+ *
1293
+ * @remarks
1294
+ * A canonical toolchain range is `^MAJOR`. Existing consumer declarations may
1295
+ * instead carry an exact `major.minor.patch` version or that version under a
1296
+ * caret or tilde. The projection reads those forms without deciding whether a
1297
+ * version satisfies them; {@link matchesRange} owns that separate question.
1298
+ *
1299
+ * @example
1300
+ * ```ts
1301
+ * import { extractRangeMajor } from '@orkestrel/scaffold'
1302
+ *
1303
+ * extractRangeMajor('^6') // the declared major
1304
+ * extractRangeMajor('>=6.0.0') // undefined
1305
+ * ```
1306
+ */
1307
+ export declare function extractRangeMajor(range: string): number | undefined;
1308
+
1286
1309
  /**
1287
1310
  * Extract the major, minor, and patch components of an exact version.
1288
1311
  *
@@ -2078,9 +2101,29 @@ export declare class Compiler implements CompilerInterface {
2078
2101
  /** Maximum length of one declared package range. */
2079
2102
  export declare const MAX_RANGE_LENGTH = 2048;
2080
2103
 
2104
+ /**
2105
+ * Maximum decoded bytes accepted from one registry response.
2106
+ *
2107
+ * @remarks
2108
+ * The 2026-08-21 abbreviated-packument measurements were 8,647,138 bytes for
2109
+ * TypeScript, 8,077,438 for Playwright, 2,315,360 for `@types/node`, 2,298,256
2110
+ * for Vite, and 1,272,652 for Vitest. The bound leaves headroom above those
2111
+ * registry answers.
2112
+ */
2113
+ export declare const MAX_REGISTRY_BYTES = 33554432;
2114
+
2081
2115
  /** Maximum bytes retained across one whole plan or audit. */
2082
2116
  export declare const MAX_TOTAL_ARTIFACT_BYTES = 104857600;
2083
2117
 
2118
+ /**
2119
+ * Maximum decoded bytes accepted across one registry-reading call.
2120
+ *
2121
+ * @remarks
2122
+ * The 2026-08-21 browser-workspace registry set measured about 24 MiB. The
2123
+ * bound leaves headroom for that set to grow without making a call unbounded.
2124
+ */
2125
+ export declare const MAX_TOTAL_REGISTRY_BYTES = 100663296;
2126
+
2084
2127
  /** The oldest Node version the generated toolchain supports. */
2085
2128
  export declare const MINIMUM_NODE_VERSION = "22.12.0";
2086
2129
 
@@ -2527,30 +2570,80 @@ export declare class Compiler implements CompilerInterface {
2527
2570
  }
2528
2571
 
2529
2572
  /**
2530
- * One declared dependency range measured against the registry's latest release.
2573
+ * One declared dependency range measured against a registry release.
2531
2574
  *
2532
2575
  * @remarks
2533
- * A found lookup carries the version upstream reported; one that produced no
2534
- * answer carries the cause and no version. Whether the declared range already
2535
- * admits that version is not recorded, because it is a deterministic function
2536
- * of `range` and `latest`: a stored answer could only disagree with the
2537
- * fields beside it. One centralized helper decides it, and every caller reads
2538
- * the same decision.
2576
+ * `range` is the declared range, and `latest` is the version the producer
2577
+ * selected. A found lookup carries that selected version; one that produced no
2578
+ * answer carries the cause and no selected version. `major`, when present, is
2579
+ * the stable major named by the registry's latest tag in the same answer.
2539
2580
  */
2540
2581
  export declare type Release = {
2541
2582
  readonly name: string;
2542
2583
  readonly range: string;
2543
2584
  readonly lookup: 'found';
2544
2585
  readonly latest: string;
2586
+ readonly major?: number;
2545
2587
  readonly note?: never;
2546
2588
  } | {
2547
2589
  readonly name: string;
2548
2590
  readonly range: string;
2549
2591
  readonly lookup: 'missing' | 'failed';
2550
2592
  readonly note: string;
2593
+ readonly major?: number;
2551
2594
  readonly latest?: never;
2552
2595
  };
2553
2596
 
2597
+ /**
2598
+ * Replace declared dependency ranges in package manifest text.
2599
+ *
2600
+ * @param manifest - The manifest text to compile.
2601
+ * @param dependencies - The declared names and replacement ranges.
2602
+ * @returns The manifest with every matching dependency-section value replaced,
2603
+ * or `undefined` when any name has no quoted declaration in those sections.
2604
+ *
2605
+ * @remarks
2606
+ * The compiler replaces values in place instead of serializing the manifest,
2607
+ * so description, keywords, scripts, key order, indentation, and every byte
2608
+ * outside the named ranges survive. Every occurrence in `dependencies`,
2609
+ * `devDependencies`, and `peerDependencies` moves, which keeps duplicate
2610
+ * declarations aligned until the manifest's own validation reports the
2611
+ * duplicate. An override or resolution with the same name stays untouched.
2612
+ *
2613
+ * @example
2614
+ * ```ts
2615
+ * import { replaceManifestRanges } from '@orkestrel/scaffold'
2616
+ *
2617
+ * const manifest = '{"devDependencies":{"typescript":"^6"}}\n'
2618
+ * replaceManifestRanges(manifest, [{ name: 'typescript', range: '^7' }])
2619
+ * // the manifest with the declared range replaced
2620
+ * ```
2621
+ */
2622
+ export declare function replaceManifestRanges(manifest: string, dependencies: readonly Dependency[]): string | undefined;
2623
+
2624
+ /**
2625
+ * Replace dependency ranges in a plan's manifest and recompute its identity.
2626
+ *
2627
+ * @param plan - The plan carrying the manifest artifact to compile.
2628
+ * @param dependencies - The declared names and replacement ranges.
2629
+ * @returns A plan with replaced manifest ranges and a matching hash, or
2630
+ * `undefined` when the manifest or its identity cannot be compiled.
2631
+ *
2632
+ * @remarks
2633
+ * The blueprint remains the workspace specification that produced the plan.
2634
+ * Registry answers alter only the manifest artifact that materialization will
2635
+ * write. Recomputing the hash in the same compiler keeps the plan's identity
2636
+ * tied to those final bytes rather than to the unresolved floor.
2637
+ *
2638
+ * @example
2639
+ * ```ts
2640
+ * import { replacePlanRanges } from '@orkestrel/scaffold'
2641
+ *
2642
+ * replacePlanRanges(plan, releases) // the plan carrying the resolved manifest ranges
2643
+ * ```
2644
+ */
2645
+ export declare function replacePlanRanges(plan: Plan, dependencies: readonly Dependency[]): Plan | undefined;
2646
+
2554
2647
  /**
2555
2648
  * The one error this package throws, carrying the coded reason it was raised.
2556
2649
  *
@@ -2702,7 +2795,7 @@ export declare class Compiler implements CompilerInterface {
2702
2795
  * ```ts
2703
2796
  * import { SHOWCASE_DEV_DEPENDENCIES } from '@orkestrel/scaffold'
2704
2797
  *
2705
- * SHOWCASE_DEV_DEPENDENCIES['vite-plugin-singlefile'] // '^2.3.3'
2798
+ * SHOWCASE_DEV_DEPENDENCIES['vite-plugin-singlefile'] // the showcase plugin range
2706
2799
  * ```
2707
2800
  */
2708
2801
  export declare const SHOWCASE_DEV_DEPENDENCIES: Readonly<Record<string, string>>;