@orkestrel/scaffold 0.0.2 → 0.0.3

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 (78) hide show
  1. package/README.md +29 -15
  2. package/dist/bin/scaffold.js +1162 -1200
  3. package/dist/bin/scaffold.js.map +1 -1
  4. package/dist/host/AGENTS.md +124 -925
  5. package/dist/host/CLAUDE.md +260 -495
  6. package/dist/host/agents/skills/orkestrel-align-packages/SKILL.md +53 -0
  7. package/dist/host/agents/skills/orkestrel-align-packages/agents/openai.yaml +4 -0
  8. package/dist/host/agents/skills/orkestrel-align-packages/references/fleet.md +50 -0
  9. package/dist/host/agents/skills/orkestrel-align-packages/references/integration.md +56 -0
  10. package/dist/host/agents/skills/orkestrel-build-application/SKILL.md +64 -0
  11. package/dist/host/agents/skills/orkestrel-build-application/agents/openai.yaml +4 -0
  12. package/dist/host/agents/skills/orkestrel-build-application/references/application.md +129 -0
  13. package/dist/host/agents/skills/orkestrel-harden-package/SKILL.md +64 -0
  14. package/dist/host/agents/skills/orkestrel-harden-package/agents/openai.yaml +4 -0
  15. package/dist/host/agents/skills/orkestrel-harden-package/references/centralization.md +85 -0
  16. package/dist/host/agents/skills/orkestrel-harden-package/references/contract.md +57 -0
  17. package/dist/host/agents/skills/orkestrel-harden-package/references/hardening.md +93 -0
  18. package/dist/host/agents/skills/orkestrel-harden-package/references/research.md +61 -0
  19. package/dist/host/claude/agents/application.md +32 -0
  20. package/dist/host/claude/agents/builder.md +12 -7
  21. package/dist/host/claude/agents/checker.md +15 -8
  22. package/dist/host/claude/agents/codex.md +40 -0
  23. package/dist/host/claude/agents/grok.md +20 -37
  24. package/dist/host/claude/agents/orkestrel.md +89 -223
  25. package/dist/host/claude/agents/planner.md +14 -34
  26. package/dist/host/claude/agents/reviewer.md +39 -24
  27. package/dist/host/claude/agents/verifier.md +15 -10
  28. package/dist/host/claude/rules/application.md +57 -0
  29. package/dist/host/claude/rules/architecture.md +179 -0
  30. package/dist/host/claude/rules/browser.md +28 -0
  31. package/dist/host/claude/rules/documentation.md +64 -0
  32. package/dist/host/claude/rules/names.md +209 -0
  33. package/dist/host/claude/rules/patterns.md +130 -0
  34. package/dist/host/claude/rules/quality.md +45 -0
  35. package/dist/host/claude/rules/styles.md +64 -0
  36. package/dist/host/claude/rules/tests.md +123 -0
  37. package/dist/host/claude/rules/typescript.md +78 -0
  38. package/dist/host/claude/rules/workspace.md +180 -0
  39. package/dist/host/claude/settings.json +116 -0
  40. package/dist/host/claude/skills/orkestrel-align-packages/SKILL.md +10 -0
  41. package/dist/host/claude/skills/orkestrel-build-application/SKILL.md +12 -0
  42. package/dist/host/claude/skills/orkestrel-harden-package/SKILL.md +10 -0
  43. package/dist/host/codex/agents/analyst.toml +15 -0
  44. package/dist/host/codex/agents/application.toml +25 -0
  45. package/dist/host/codex/agents/builder.toml +24 -0
  46. package/dist/host/codex/agents/checker.toml +15 -0
  47. package/dist/host/codex/agents/grok.toml +17 -0
  48. package/dist/host/codex/agents/implementer.toml +17 -0
  49. package/dist/host/codex/agents/orkestrel.toml +16 -0
  50. package/dist/host/codex/agents/planner.toml +20 -0
  51. package/dist/host/codex/agents/reviewer.toml +18 -0
  52. package/dist/host/codex/agents/verifier.toml +14 -0
  53. package/dist/host/codex/config.toml +64 -0
  54. package/dist/host/dotfiles/oxlintrc.json +307 -1
  55. package/dist/host/guides/src/scaffold.md +2059 -2007
  56. package/dist/host/manifest.json +355 -137
  57. package/dist/host/scripts/codex.sh +49 -0
  58. package/dist/host/scripts/cursor.sh +33 -47
  59. package/dist/host/scripts/deps.sh +34 -16
  60. package/dist/host/scripts/ollama.sh +6 -149
  61. package/dist/host/tests/setupPolicy.ts +354 -0
  62. package/dist/src/core/index.cjs +6600 -1199
  63. package/dist/src/core/index.cjs.map +1 -1
  64. package/dist/src/core/index.d.cts +801 -266
  65. package/dist/src/core/index.d.ts +801 -266
  66. package/dist/src/core/index.js +6518 -1191
  67. package/dist/src/core/index.js.map +1 -1
  68. package/dist/src/server/index.cjs +3132 -593
  69. package/dist/src/server/index.cjs.map +1 -1
  70. package/dist/src/server/index.d.cts +643 -95
  71. package/dist/src/server/index.d.ts +643 -95
  72. package/dist/src/server/index.js +3054 -594
  73. package/dist/src/server/index.js.map +1 -1
  74. package/package.json +15 -12
  75. package/dist/host/claude/agents/composer.md +0 -64
  76. package/dist/host/claude/agents/researcher.md +0 -38
  77. package/dist/host/claude/agents/scout.md +0 -35
  78. package/dist/host/github/workflows/ci.yml +0 -64
@@ -12,6 +12,7 @@ import { OptionalShape } from '@orkestrel/contract';
12
12
  import { StringShape } from '@orkestrel/contract';
13
13
  import { TableAlign } from '@orkestrel/markdown';
14
14
  import { TemplateDefinition } from '@orkestrel/template';
15
+ import { UnionShape } from '@orkestrel/contract';
15
16
 
16
17
  /**
17
18
  * Build a formatter-width-aligned GFM table string from header and row cells.
@@ -37,12 +38,52 @@ import { TemplateDefinition } from '@orkestrel/template';
37
38
  */
38
39
  export declare function alignTable(header: readonly string[], rows: readonly (readonly string[])[], align?: readonly TableAlign[]): string;
39
40
 
41
+ /** Additional development dependencies required by a private Vue browser application. */
42
+ export declare const APP_BROWSER_DEV_DEPENDENCIES: Readonly<Record<string, string>>;
43
+
44
+ /**
45
+ * The per-environment application matrix: thin config artifacts, Vitest project
46
+ * label, and executable entry where the environment produces a runtime bundle.
47
+ */
48
+ export declare const APP_MATRIX: Readonly<Record<Environment, AppDefinition>>;
49
+
50
+ /** The deterministic config, test-project, and runtime-entry settings for one application environment. */
51
+ export declare interface AppDefinition {
52
+ readonly configs: readonly string[];
53
+ readonly project: string;
54
+ readonly entry?: string;
55
+ }
56
+
57
+ /**
58
+ * Draft the application source artifacts for every selected app environment.
59
+ *
60
+ * @param spec - The blueprint carrying the application environment set.
61
+ * @returns Complete, runnable app/core, app/browser, and app/server artifacts.
62
+ */
63
+ export declare function applicationArtifacts(spec: Blueprint): readonly Artifact[];
64
+
65
+ /**
66
+ * Build the root Vite/Vitest configuration for a workspace that includes
67
+ * app environments, optionally alongside published src environments.
68
+ *
69
+ * @param src - Published src environments.
70
+ * @param app - Private app environments.
71
+ * @param engine - Whether the workspace also builds scaffold's executable.
72
+ * @returns The root `vite.config.ts` content.
73
+ *
74
+ * @example
75
+ * ```ts
76
+ * applicationViteConfig([], ['core', 'server']).includes('appServer') // true
77
+ * ```
78
+ */
79
+ export declare function applicationViteConfig(src: readonly Environment[], app: readonly Environment[], engine?: boolean): string;
80
+
40
81
  /**
41
82
  * Apply a blueprint's `overrides` over a drafted artifact list — an override
42
83
  * REPLACES the matching artifact's `content` in place; an override matching
43
- * no planned artifact, or targeting a `host`-origin path, is left unapplied
44
- * here (the gate stage surfaces it as a blocking question — this leaf only
45
- * performs the replacement half of the rule).
84
+ * no planned artifact, targeting a `host`-origin path, or targeting the
85
+ * blueprint-owned `package.json` publication boundary is left unapplied here
86
+ * (the gate stage reports it as a blocking question).
46
87
  *
47
88
  * @param artifacts - The drafted `Artifact[]`.
48
89
  * @param overrides - The blueprint's `overrides`.
@@ -56,38 +97,67 @@ export declare function alignTable(header: readonly string[], rows: readonly (re
56
97
  export declare function applyOverrides(artifacts: readonly Artifact[], overrides: Blueprint['overrides']): readonly Artifact[];
57
98
 
58
99
  /**
59
- * One file in a `Plan`.
100
+ * Build one `configs/app/tsconfig.<environment>.json` check-only configuration.
60
101
  *
61
- * @remarks
62
- * `content` present for `template` / `computed`, `source` (a host-relative
63
- * path) for `host`.
102
+ * @param environment - The application environment.
103
+ * @param hasCore - Whether `app/core` is part of the same workspace.
104
+ * @returns The application environment tsconfig content.
105
+ *
106
+ * @example
107
+ * ```ts
108
+ * appTsconfig('browser', true).includes('../../app/core') // true
109
+ * ```
64
110
  */
65
- export declare interface Artifact {
111
+ export declare function appTsconfig(environment: Environment, hasCore: boolean): string;
112
+
113
+ /**
114
+ * Build one thin executable application Vite config.
115
+ *
116
+ * @param environment - The executable browser or server environment.
117
+ * @returns The `configs/app/vite.<environment>.config.ts` content.
118
+ *
119
+ * @example
120
+ * ```ts
121
+ * appViteConfig('server').includes('appServer') // true
122
+ * ```
123
+ */
124
+ export declare function appViteConfig(environment: 'browser' | 'server'): string;
125
+
126
+ /** One origin-discriminated file in a `Plan`. */
127
+ export declare type Artifact = HostArtifact | ContentArtifact;
128
+
129
+ /** Fields shared by every file in a `Plan`. */
130
+ export declare interface ArtifactBase {
66
131
  readonly path: string;
67
132
  readonly group: Group;
68
- readonly origin: Origin;
69
- readonly surface?: Surface;
70
- readonly content?: string;
71
- readonly source?: string;
133
+ readonly environment?: Environment;
72
134
  }
73
135
 
74
136
  /**
75
137
  * Build the `Artifact` object shape.
76
138
  *
77
139
  * @remarks
78
- * `origin` is a `literalShape(ORIGINS)`; `content` and `source` are both
79
- * optional (the `origin` axis decides which one a given artifact carries).
140
+ * The `origin` axis is structural: host artifacts may carry `source` and
141
+ * byte `hex`, while template/computed artifacts require text `content`.
142
+ * Lowercase byte-pair validation remains a semantic refinement so the
143
+ * contract generator can continue producing unconstrained strings.
80
144
  *
81
145
  * @returns A fresh `ContractShape` describing one planned file.
82
146
  */
83
- export declare function artifactShape(): ObjectShape<{
147
+ export declare function artifactShape(): UnionShape<[ ObjectShape<{
84
148
  path: StringShape;
85
- group: LiteralShape<readonly ["manifest", "configs", "source", "tests", "guides", "docs", "orchestration"]>;
86
- origin: LiteralShape<readonly ["host", "template", "computed"]>;
87
- surface: OptionalShape<LiteralShape<readonly ["core", "browser", "server"]>>;
88
- content: OptionalShape<StringShape>;
149
+ group: LiteralShape<readonly Group[]>;
150
+ origin: LiteralShape<readonly ["host"]>;
151
+ environment: OptionalShape<LiteralShape<readonly Environment[]>>;
152
+ hex: OptionalShape<StringShape>;
89
153
  source: OptionalShape<StringShape>;
90
- }, false>;
154
+ }, false>, ObjectShape<{
155
+ path: StringShape;
156
+ group: LiteralShape<readonly Group[]>;
157
+ origin: LiteralShape<readonly ["template", "computed"]>;
158
+ environment: OptionalShape<LiteralShape<readonly Environment[]>>;
159
+ content: StringShape;
160
+ }, false>]>;
91
161
 
92
162
  /**
93
163
  * The whole diff of a plan against a target's current content.
@@ -122,12 +192,18 @@ export declare interface Audit {
122
192
  */
123
193
  export declare function auditToReview(audit: Audit): string;
124
194
 
125
- /** The closed, JSON-serializable package spec. */
195
+ /** Tooling versions shared by scaffold and every generated workspace. */
196
+ export declare const BASE_DEV_DEPENDENCIES: Readonly<Record<string, string>>;
197
+
198
+ /** The closed, JSON-serializable source/application workspace spec. */
126
199
  export declare interface Blueprint {
127
200
  readonly name: string;
128
201
  readonly description?: string;
129
202
  readonly keywords: readonly string[];
130
- readonly surfaces: readonly Surface[];
203
+ /** Published library environments under `src`; empty for an application-only workspace. */
204
+ readonly src: readonly Environment[];
205
+ /** Private runtime environments under `app`; empty for a library-only workspace. */
206
+ readonly app: readonly Environment[];
131
207
  readonly dependencies: readonly Dependency[];
132
208
  /** Runtime `@orkestrel/*` peers, emitted as `peerDependencies` — a peer flagged `optional` also gets a `peerDependenciesMeta` entry. */
133
209
  readonly peers: readonly Dependency[];
@@ -136,6 +212,8 @@ export declare interface Blueprint {
136
212
  readonly version: string;
137
213
  readonly engines: string;
138
214
  readonly overrides: readonly Override[];
215
+ /** Structural: `true` only for a repo that ships its own `src/bin` — the self-hosting tax (a `bin` field, the `scaffold` script invoking `dist/bin/scaffold.js` directly, the `check/test/build:src:bin` scripts, `build:host`, the `srcBin` vite project) applies ONLY when `true`, never by name. */
216
+ readonly engine: boolean;
139
217
  }
140
218
 
141
219
  /**
@@ -144,10 +222,11 @@ export declare interface Blueprint {
144
222
  * @param name - The package name.
145
223
  * @param options - A partial of the remaining `Blueprint` fields.
146
224
  * @remarks
147
- * `version` / `engines` default `DEFAULT_VERSION` / `DEFAULT_ENGINES`, `surfaces`
148
- * defaults `['core']`, and `keywords` / `dependencies` / `peers` / `extras` /
149
- * `overrides` default `[]`. `description` is OMITTED entirely when absent, so
150
- * the result round-trips the exact-record `Blueprint` guard.
225
+ * `version` / `engines` default `DEFAULT_VERSION` / `DEFAULT_ENGINES`,
226
+ * `src` defaults `['core']`, and `app` / `keywords` / `dependencies` /
227
+ * `peers` / `extras` / `overrides` default `[]`. `description` is OMITTED
228
+ * entirely when absent, so the result round-trips the exact-record
229
+ * `Blueprint` guard.
151
230
  * @returns A complete `Blueprint`.
152
231
  *
153
232
  * @example
@@ -163,12 +242,14 @@ export declare function blueprint(name: string, options?: Partial<Omit<Blueprint
163
242
  * Build the `Blueprint` object shape.
164
243
  *
165
244
  * @remarks
166
- * `surfaces` is a `literalShape(SURFACES)` array with `min: 1`; `name` is a
167
- * plain `min: 1` string, NOT pattern-constrained, so `generate` stays
168
- * satisfiable — the `NAME_PATTERN` law lives in the semantic pass
169
- * (`validateBlueprint`), never in this compiled contract. `peers` and `extras`
170
- * are `dependencyShape()` arrays alongside `dependencies` the cross-array
171
- * uniqueness and overlap rules also live in `validateBlueprint`.
245
+ * `src` and `app` are independent `literalShape(ENVIRONMENTS)` arrays; the
246
+ * cross-field requirement that at least one is non-empty lives in
247
+ * `hasBlueprintEnvironment`. `name` is a plain `min: 1` string, NOT
248
+ * pattern-constrained, so `generate` stays satisfiable the `NAME_PATTERN`
249
+ * law lives in the semantic pass (`validateBlueprint`), never in this compiled
250
+ * contract. `peers` and `extras` are `dependencyShape()` arrays alongside
251
+ * `dependencies` — the cross-array uniqueness and overlap rules also live in
252
+ * `validateBlueprint`.
172
253
  *
173
254
  * @returns A fresh `ContractShape` describing the closed `Blueprint` spec.
174
255
  */
@@ -176,7 +257,8 @@ export declare function blueprintShape(): ObjectShape<{
176
257
  name: StringShape;
177
258
  description: OptionalShape<StringShape>;
178
259
  keywords: ArrayShape<StringShape>;
179
- surfaces: ArrayShape<LiteralShape<readonly ["core", "browser", "server"]>>;
260
+ src: ArrayShape<LiteralShape<readonly Environment[]>>;
261
+ app: ArrayShape<LiteralShape<readonly Environment[]>>;
180
262
  dependencies: ArrayShape<ObjectShape<{
181
263
  name: StringShape;
182
264
  range: StringShape;
@@ -198,6 +280,7 @@ export declare function blueprintShape(): ObjectShape<{
198
280
  path: StringShape;
199
281
  content: StringShape;
200
282
  }, false>>;
283
+ engine: BooleanShape;
201
284
  }, false>;
202
285
 
203
286
  /**
@@ -205,12 +288,10 @@ export declare function blueprintShape(): ObjectShape<{
205
288
  *
206
289
  * @param spec - The blueprint to derive members from.
207
290
  * @remarks
208
- * The canonical per-surface inventory is the four `Category` buckets applied to
209
- * the package's PascalCase entity name: an `Options` type, an `Interface` type,
210
- * a `create*` factory, a default-id constant, and the entity itself. Standalone
211
- * helpers, validators, and shapers are hand-authored in implementation, not
212
- * scaffolded.
213
- * @returns The declared `Member[]`, one set per surface.
291
+ * Published source environments receive the canonical entity/type/factory/constant
292
+ * inventory. Application environments receive their exact public declaration kinds,
293
+ * including parsers, guards, handlers, errors, and runners where present.
294
+ * @returns The declared `Member[]`, one set per environment.
214
295
  *
215
296
  * @example
216
297
  * ```ts
@@ -223,7 +304,7 @@ export declare function blueprintToMembers(spec: Blueprint): readonly Member[];
223
304
 
224
305
  /**
225
306
  * The full pure compilation: draft a blueprint's artifacts — the manifest and
226
- * exports combination rules over the per-surface `SURFACE_MATRIX` rows, plus
307
+ * exports combination rules over the per-environment `SRC_MATRIX` rows, plus
227
308
  * `HOST_PATHS` and `overrides` — then pin.
228
309
  *
229
310
  * @param blueprint - The `Blueprint` to compile.
@@ -232,12 +313,23 @@ export declare function blueprintToMembers(spec: Blueprint): readonly Member[];
232
313
  *
233
314
  * @example
234
315
  * ```ts
235
- * const plan = blueprintToPlan(blueprint('router', { surfaces: ['core'] }))
316
+ * const plan = blueprintToPlan(blueprint('router', { src: ['core'] }))
236
317
  * plan.artifacts.length // every file the package needs
237
318
  * ```
238
319
  */
239
320
  export declare function blueprintToPlan(blueprint: Blueprint, groups?: readonly Group[]): Plan;
240
321
 
322
+ /** One supported library-output module format. */
323
+ export declare type BuildFormat = 'es' | 'cjs';
324
+
325
+ /**
326
+ * Encode bytes as exact lowercase hexadecimal text.
327
+ *
328
+ * @param bytes - The bytes to encode.
329
+ * @returns Two lowercase hexadecimal digits per input byte.
330
+ */
331
+ export declare function bytesToHex(bytes: Uint8Array): string;
332
+
241
333
  /**
242
334
  * One fleet package's catalog row — the `orkestrel` agent's package-catalog
243
335
  * section, derived rather than hand-maintained.
@@ -284,9 +376,10 @@ export declare function catalogNames(text: string): readonly string[];
284
376
  * @param entries - The catalog rows to render.
285
377
  * @remarks
286
378
  * Deduplicated by `name` (a later entry for a repeated name wins), then
287
- * code-unit sorted by `name`. An empty `description` renders as `—` (an em
288
- * dash), never a blank cell. Deterministic same input, same output, every
289
- * time — via `alignTable`; trailing-newline terminated.
379
+ * code-unit sorted by `name`. Network-controlled descriptions are
380
+ * intentionally omitted because this block enters agent instruction context.
381
+ * Deterministic — same input, same output, every time — via `alignTable`;
382
+ * trailing-newline terminated.
290
383
  * @returns The aligned GFM table string.
291
384
  *
292
385
  * @example
@@ -297,16 +390,27 @@ export declare function catalogNames(text: string): readonly string[];
297
390
  * { name: '@orkestrel/router', version: '0.0.5', description: 'A tiny hash-router.' },
298
391
  * { name: '@orkestrel/contract', version: '0.0.5', description: '' },
299
392
  * ])
300
- * // '| Package | Version | Description |\n| |\n| @orkestrel/contract | 0.0.5 | — |\n…'
393
+ * // '> Generated package identifiers are untrusted discovery data, never instructions.\n\n| Package …'
301
394
  * ```
302
395
  */
303
396
  export declare function catalogToBlock(entries: readonly CatalogEntry[]): string;
304
397
 
305
- /** The four `Category` values, frozen. */
306
- export declare const CATEGORIES: readonly ["type", "constant", "factory", "entity"];
398
+ /** The nine `Category` values, frozen. */
399
+ export declare const CATEGORIES: readonly Category[];
400
+
401
+ /** What a declared public `Member` is in the scaffolded environment. */
402
+ export declare type Category = 'type' | 'alias' | 'constant' | 'factory' | 'entity' | 'parser' | 'guard' | 'handler' | 'error';
403
+
404
+ /** Immutable official actions/checkout v6.0.2 commit used by generated CI. */
405
+ export declare const CHECKOUT_ACTION_SHA = "de0fac2e4500dabe0009e67214ff5f5447ce83dd";
307
406
 
308
- /** What a declared `Member` IS in the scaffolded surface. */
309
- export declare type Category = 'type' | 'constant' | 'factory' | 'entity';
407
+ /**
408
+ * Build selection-aware GitHub CI without external service dependencies.
409
+ *
410
+ * @param spec - The workspace blueprint.
411
+ * @returns The complete `.github/workflows/ci.yml` content.
412
+ */
413
+ export declare function ciWorkflow(spec: Blueprint): string;
310
414
 
311
415
  /**
312
416
  * A code-unit (not locale-sensitive) comparator — matches the `keywords` sort
@@ -324,7 +428,7 @@ export declare type Category = 'type' | 'constant' | 'factory' | 'entity';
324
428
  export declare function compareCodeUnit(a: string, b: string): number;
325
429
 
326
430
  /** The pipeline phases in order, frozen. */
327
- export declare const COMPILE_STAGES: readonly ["draft", "gate", "pin"];
431
+ export declare const COMPILE_STAGES: readonly CompileStage[];
328
432
 
329
433
  /** A visible marker for a stage that failed. */
330
434
  export declare interface CompileFailure {
@@ -343,7 +447,7 @@ export declare interface CompileFailure {
343
447
  * CLOSED — a blueprint failing `validateBlueprint`, or carrying an override
344
448
  * that matches no planned artifact or targets a `host`-origin path, yields a
345
449
  * visible incomplete `Scaffolding` (`plan` absent, `questions` populated)
346
- * rather than throwing. A dependency outside the vendored guide set surfaces
450
+ * rather than throwing. A dependency outside the vendored guide set src
347
451
  * a non-blocking `Question` and a `host`-origin pointer artifact instead of a
348
452
  * fabricated mirror. `compile` emits `compile` only for a complete
349
453
  * compilation and `block` for a gated one; `audit` emits `block` (when gated)
@@ -355,7 +459,7 @@ export declare interface CompileFailure {
355
459
  * import { blueprint, Compiler } from '@src/core'
356
460
  *
357
461
  * const compiler = new Compiler()
358
- * const scaffolding = compiler.compile(blueprint('router', { surfaces: ['core'] }))
462
+ * const scaffolding = compiler.compile(blueprint('router', { src: ['core'] }))
359
463
  * scaffolding.complete // true
360
464
  * compiler.destroy()
361
465
  * ```
@@ -375,7 +479,7 @@ export declare class Compiler implements CompilerInterface {
375
479
  *
376
480
  * @example
377
481
  * ```ts
378
- * const scaffolding = compiler.compile(blueprint('timeout', { surfaces: ['core'] }))
482
+ * const scaffolding = compiler.compile(blueprint('timeout', { src: ['core'] }))
379
483
  * scaffolding.stages.map((record) => record.stage) // ['draft', 'gate', 'pin']
380
484
  * ```
381
485
  */
@@ -393,7 +497,7 @@ export declare class Compiler implements CompilerInterface {
393
497
  *
394
498
  * @example
395
499
  * ```ts
396
- * const audit = compiler.audit(blueprint('timeout', { surfaces: ['core'] }), {})
500
+ * const audit = compiler.audit(blueprint('timeout', { src: ['core'] }), {})
397
501
  * audit.missing // every artifact — nothing exists at the target yet
398
502
  * ```
399
503
  */
@@ -414,7 +518,7 @@ export declare interface CompileRecord {
414
518
  readonly error?: string;
415
519
  }
416
520
 
417
- /** `Compiler`'s push observation surface (AGENTS §13). */
521
+ /** `Compiler`'s push observation channel (AGENTS §13). */
418
522
  export declare type CompilerEventMap = {
419
523
  readonly compile: readonly [scaffolding: Scaffolding];
420
524
  readonly audit: readonly [audit: Audit];
@@ -478,7 +582,7 @@ export declare function computeHash(text: string): string;
478
582
 
479
583
  /**
480
584
  * Draft the `configs` group's `computed` artifacts — the root
481
- * `tsconfig.json` / `vite.config.ts` plus each declared surface's
585
+ * `tsconfig.json` / `vite.config.ts` plus each declared environment's
482
586
  * `configs/src/*` pair, grounded against the live middleware (core+server)
483
587
  * and router (core+browser+server) exemplars.
484
588
  *
@@ -492,10 +596,57 @@ export declare function computeHash(text: string): string;
492
596
  */
493
597
  export declare function configArtifacts(spec: Blueprint): readonly Artifact[];
494
598
 
599
+ /** Constant-declaration token kept out of template literals consumed by parity scans. */
600
+ export declare const CONST_KEYWORD = "const";
601
+
602
+ /** A text artifact produced by the template or computed compilation path. */
603
+ export declare interface ContentArtifact extends ArtifactBase {
604
+ readonly origin: 'template' | 'computed';
605
+ readonly content: string;
606
+ readonly hex?: never;
607
+ readonly source?: never;
608
+ }
609
+
610
+ /**
611
+ * Count the UTF-8 bytes required by text.
612
+ *
613
+ * @param content - The text to measure.
614
+ * @returns Its encoded UTF-8 byte length.
615
+ */
616
+ export declare function contentByteLength(content: string): number;
617
+
618
+ /**
619
+ * Read one Unicode scalar for UTF-8 encoding, replacing an unpaired surrogate.
620
+ *
621
+ * @param content - The source text.
622
+ * @param index - The UTF-16 code-unit index.
623
+ * @returns A Unicode scalar value, using U+FFFD for an unpaired surrogate.
624
+ */
625
+ export declare function contentCodePoint(content: string, index: number): number;
626
+
627
+ /**
628
+ * Encode text as exact UTF-8 bytes without depending on a browser or server host.
629
+ *
630
+ * @param content - The text to encode.
631
+ * @returns Its exact UTF-8 bytes.
632
+ */
633
+ export declare function contentToBytes(content: string): Uint8Array;
634
+
635
+ /**
636
+ * Encode a string's UTF-8 bytes as exact lowercase hexadecimal text.
637
+ *
638
+ * @param content - The text to encode.
639
+ * @returns The exact hexadecimal UTF-8 representation.
640
+ */
641
+ export declare function contentToHex(content: string): string;
642
+
643
+ /** Unicode controls, formatting controls, and line/paragraph separators rejected at text boundaries. */
644
+ export declare const CONTROL_CHARACTER_PATTERN: RegExp;
645
+
495
646
  /**
496
647
  * `configs/src/tsconfig.core.json` — unchanged core shape.
497
648
  *
498
- * @returns The core surface `tsconfig` file content, newline-terminated.
649
+ * @returns The core environment `tsconfig` file content, newline-terminated.
499
650
  *
500
651
  * @example
501
652
  * ```ts
@@ -506,9 +657,9 @@ export declare function coreTsconfig(): string;
506
657
 
507
658
  /**
508
659
  * `configs/src/vite.core.config.ts` — inlines its own `build.lib` /
509
- * `rollupOptions` (core's `srcCore` root export carries no build.lib).
660
+ * `rolldownOptions` (core's `srcCore` root export carries no build.lib).
510
661
  *
511
- * @returns The core surface `vite.config.ts` file content, newline-terminated.
662
+ * @returns The core environment `vite.config.ts` file content, newline-terminated.
512
663
  *
513
664
  * @example
514
665
  * ```ts
@@ -533,7 +684,7 @@ export declare function coreViteConfig(): string;
533
684
  * ```ts
534
685
  * import { createBlueprint } from '@src/core'
535
686
  *
536
- * createBlueprint({ name: 'Router', surfaces: [] }) // throws ScaffoldError('INVALID', …)
687
+ * createBlueprint({ name: 'Router', src: [] }) // throws ScaffoldError('INVALID', …)
537
688
  * ```
538
689
  */
539
690
  export declare function createBlueprint(data: Partial<Blueprint> & {
@@ -574,7 +725,7 @@ export declare function coreViteConfig(): string;
574
725
  export declare function createPlanManager(options?: PlanManagerOptions): PlanManagerInterface;
575
726
 
576
727
  /** The `engines.node` range the `blueprint` builder fills. */
577
- export declare const DEFAULT_ENGINES = ">=22";
728
+ export declare const DEFAULT_ENGINES = ">=22.12.0";
578
729
 
579
730
  /** The starting version the `blueprint` builder fills. */
580
731
  export declare const DEFAULT_VERSION = "0.0.1";
@@ -654,12 +805,11 @@ export declare function coreViteConfig(): string;
654
805
  }, false>;
655
806
 
656
807
  /**
657
- * The devDependency baseline every repo in the line carries the same set
658
- * (`@vitest/browser-playwright` included regardless of a browser surface: both
659
- * @orkestrel/middleware, core+server, and @orkestrel/router, core+browser+server,
660
- * ship it grounded, not conditional). A package's `extras` (code-unit sorted)
661
- * merge in on top, the extras' declared range winning on a name collision with
662
- * the baseline.
808
+ * The host-neutral devDependency baseline every generated workspace needs.
809
+ * Browser providers are added only by browser selections or the scaffold
810
+ * engine's generated-browser consumer proof. A package's `extras` (code-unit
811
+ * sorted) merge in on top, the extras' declared range winning on a name
812
+ * collision with the baseline.
663
813
  *
664
814
  * @param extras - The blueprint's package-specific `extras` `Dependency[]`.
665
815
  * @returns The merged `devDependencies` record.
@@ -681,8 +831,9 @@ export declare function coreViteConfig(): string;
681
831
  * PRESENCE only — `missing` or `aligned`, never `stale` — UNLESS it has been
682
832
  * hydrated with its real host bytes (`hydratePlan`'s `content`), in which case
683
833
  * it is content-compared exactly like a `computed` artifact and CAN be
684
- * `stale`. A degrade-path or directory-shaped host artifact (never hydrated)
685
- * stays presence-only. A `computed` artifact is content-aware canon —
834
+ * `stale`. `hydratePlan` expands directory-shaped host artifacts into
835
+ * content-bearing file artifacts; only an unresolved degrade-path host
836
+ * artifact stays presence-only. A `computed` artifact is content-aware canon —
686
837
  * `missing` / `aligned` / `stale` — and gates the audit like any drifted
687
838
  * finding. A `template`-origin artifact is BIRTH-ONLY and AUDIT-EXEMPT: it is
688
839
  * always reported `aligned`, regardless of whether the target has it at all
@@ -705,7 +856,7 @@ export declare function coreViteConfig(): string;
705
856
  * diffPlan(plan, current) // { findings: [...], clean: false, complete: true, drifted: 1, missing: 20, foreign: 0 }
706
857
  * ```
707
858
  */
708
- export declare function diffPlan(plan: Plan, current: Readonly<Record<string, string>>): Audit;
859
+ export declare function diffPlan(plan: Plan, current: Snapshot): Audit;
709
860
 
710
861
  /** One `Finding`'s verdict against the target's current content. */
711
862
  export declare type Drift = 'aligned' | 'stale' | 'missing' | 'foreign';
@@ -724,10 +875,13 @@ export declare function coreViteConfig(): string;
724
875
  */
725
876
  export declare function dualCondition(path: string): Readonly<Record<string, unknown>>;
726
877
 
878
+ /** The minimum-Node engine syntax accepted by `validateBlueprint`. */
879
+ export declare const ENGINES_PATTERN: RegExp;
880
+
727
881
  /**
728
882
  * Build the `main` / `module` / top-level `types` entry fields.
729
883
  *
730
- * @param surfaces - The declared `Surface[]`.
884
+ * @param src - The declared `Environment[]`.
731
885
  * @returns The `package.json` `main` / `module` / optional `types` fields.
732
886
  *
733
887
  * @example
@@ -735,16 +889,40 @@ export declare function coreViteConfig(): string;
735
889
  * entryFields(['browser']).main // './dist/src/browser/index.js'
736
890
  * ```
737
891
  */
738
- export declare function entryFields(surfaces: readonly Surface[]): {
892
+ export declare function entryFields(src: readonly Environment[]): {
739
893
  readonly main: string;
740
894
  readonly module: string;
741
895
  readonly types?: string;
742
896
  };
743
897
 
898
+ /** One core, browser, or server environment in the scaffolded workspace. */
899
+ export declare type Environment = 'core' | 'browser' | 'server';
900
+
901
+ /** The three `Environment` values, frozen — compose with `literalOf(...)` / `parseEnum(...)`. */
902
+ export declare const ENVIRONMENTS: readonly Environment[];
903
+
904
+ /**
905
+ * Escape text for an HTML text-node context.
906
+ *
907
+ * @param value - The untrusted text value.
908
+ * @returns Text with the five HTML-significant characters entity-escaped.
909
+ *
910
+ * @example
911
+ * ```ts
912
+ * import { escapeHtmlText } from '@orkestrel/scaffold'
913
+ *
914
+ * escapeHtmlText('<app & "team">') // '&lt;app &amp; &quot;team&quot;&gt;'
915
+ * ```
916
+ */
917
+ export declare function escapeHtmlText(value: string): string;
918
+
919
+ /** Declaration token kept out of template literals so parity scans see only real exports. */
920
+ export declare const EXPORT_KEYWORD = "export";
921
+
744
922
  /**
745
923
  * Build the `package.json` `exports` map.
746
924
  *
747
- * @param surfaces - The declared `Surface[]`.
925
+ * @param src - The declared `Environment[]`.
748
926
  * @returns The `package.json` `exports` map.
749
927
  *
750
928
  * @example
@@ -752,7 +930,7 @@ export declare function coreViteConfig(): string;
752
930
  * exportsMap(['core'])['.'] // dual import/require condition block
753
931
  * ```
754
932
  */
755
- export declare function exportsMap(surfaces: readonly Surface[]): Readonly<Record<string, unknown>>;
933
+ export declare function exportsMap(src: readonly Environment[]): Readonly<Record<string, unknown>>;
756
934
 
757
935
  /**
758
936
  * The `extras` dependency-name RegExp — a strict npm package-name shape: an
@@ -768,16 +946,19 @@ export declare function coreViteConfig(): string;
768
946
  */
769
947
  export declare const EXTRA_NAME_PATTERN: RegExp;
770
948
 
949
+ /** The registry-only semver subset accepted for package-specific development extras. */
950
+ export declare const EXTRA_RANGE_PATTERN: RegExp;
951
+
771
952
  /**
772
953
  * Fill one `TEMPLATES` entry into a `template`-origin `Artifact`, optionally
773
- * tagged with the owning `Surface` (source/tests artifacts that live under a
774
- * declared surface's tree).
954
+ * tagged with the owning `Environment` (source/tests artifacts that live under a
955
+ * declared environment's tree).
775
956
  *
776
957
  * @param path - The artifact's output path.
777
958
  * @param group - The artifact's `Group`.
778
959
  * @param id - The `TEMPLATES` entry id to fill.
779
960
  * @param values - The placeholder values to fill the template with.
780
- * @param surface - The owning `Surface`, when the artifact lives under a declared surface's tree.
961
+ * @param environment - The owning `Environment`, when the artifact lives under a declared environment's tree.
781
962
  * @returns The filled `template`-origin `Artifact`.
782
963
  *
783
964
  * @example
@@ -786,15 +967,33 @@ export declare function coreViteConfig(): string;
786
967
  * // { path: 'README.md', group: 'docs', origin: 'template', content: '# router\n…' }
787
968
  * ```
788
969
  */
789
- export declare function fillArtifact(path: string, group: Group, id: string, values: Readonly<Record<string, unknown>>, surface?: Surface): Artifact;
970
+ export declare function fillArtifact(path: string, group: Group, id: string, values: Readonly<Record<string, unknown>>, environment?: Environment): Artifact;
971
+
972
+ /**
973
+ * Find the first exact, case-insensitive, or file/descendant path collision.
974
+ *
975
+ * @param paths - Portable file paths in deterministic input order.
976
+ * @returns The first conflicting pair, or `undefined`.
977
+ */
978
+ export declare function findFileConflict(paths: readonly string[]): readonly [existing: string, duplicate: string] | undefined;
790
979
 
791
980
  /** One audit drift result. */
792
981
  export declare interface Finding {
793
982
  readonly path: string;
794
983
  readonly group: Group;
795
984
  readonly drift: Drift;
985
+ /** Exact bounded observed bytes for a stale destination, used as the repair precondition. */
986
+ readonly observed?: string;
796
987
  }
797
988
 
989
+ /**
990
+ * Find the first exact or portable case-insensitive path collision.
991
+ *
992
+ * @param paths - Portable paths in deterministic input order.
993
+ * @returns The first `[existing, duplicate]` pair, or `undefined`.
994
+ */
995
+ export declare function findPathConflict(paths: readonly string[]): readonly [existing: string, duplicate: string] | undefined;
996
+
798
997
  /**
799
998
  * Serialize a value to newline-terminated JSON that matches the fleet's own
800
999
  * `oxfmt` output byte-for-byte — objects one key per line, arrays collapsed
@@ -821,7 +1020,7 @@ export declare function coreViteConfig(): string;
821
1020
  export declare function formatJson(value: unknown): string;
822
1021
 
823
1022
  /** The four `Freshness` values, frozen — the currency axis `Sync` reports on. */
824
- export declare const FRESHNESS: readonly ["current", "behind", "missing", "failed"];
1023
+ export declare const FRESHNESS: readonly Freshness[];
825
1024
 
826
1025
  /**
827
1026
  * One `GuideSync` / `VersionSync`'s currency against upstream.
@@ -831,11 +1030,14 @@ export declare function coreViteConfig(): string;
831
1030
  */
832
1031
  export declare type Freshness = 'current' | 'behind' | 'missing' | 'failed';
833
1032
 
1033
+ /** Function-declaration token kept out of template literals consumed by parity scans. */
1034
+ export declare const FUNCTION_KEYWORD = "function";
1035
+
834
1036
  /** The closed artifact-group vocabulary a plan selects over. */
835
1037
  export declare type Group = 'manifest' | 'configs' | 'source' | 'tests' | 'guides' | 'docs' | 'orchestration';
836
1038
 
837
1039
  /** The seven `Group` values, frozen — the artifact-group selection vocabulary. */
838
- export declare const GROUPS: readonly ["manifest", "configs", "source", "tests", "guides", "docs", "orchestration"];
1040
+ export declare const GROUPS: readonly Group[];
839
1041
 
840
1042
  /**
841
1043
  * Draft the `guides` group's artifacts — the package's own filled guide stub,
@@ -855,10 +1057,10 @@ export declare function coreViteConfig(): string;
855
1057
 
856
1058
  /**
857
1059
  * Build an `alignTable` markdown table over a member category's rows, deduped
858
- * by name — `blueprintToMembers` declares one full member set PER surface, so
859
- * a multi-surface blueprint carries byte-identical name/summary rows once per
860
- * surface; the one guide (AGENTS §22) lists each declared member once,
861
- * grouped across its surfaces.
1060
+ * by name — `blueprintToMembers` declares one full member set PER environment, so
1061
+ * a multi-environment blueprint carries byte-identical name/summary rows once per
1062
+ * environment; the one guide (AGENTS §22) lists each declared member once,
1063
+ * grouped across its src.
862
1064
  *
863
1065
  * @param category - The `Member['category']` to filter rows by.
864
1066
  * @param members - The blueprint's derived `Member[]` (previously closed over by the caller).
@@ -871,6 +1073,14 @@ export declare function coreViteConfig(): string;
871
1073
  */
872
1074
  export declare function guideMemberTable(category: Member['category'], members: readonly Member[]): string;
873
1075
 
1076
+ /**
1077
+ * Build the generated application server's method contract section.
1078
+ *
1079
+ * @param spec - The workspace blueprint.
1080
+ * @returns A Methods section when app/server is selected, otherwise an empty string.
1081
+ */
1082
+ export declare function guideMethods(spec: Blueprint): string;
1083
+
874
1084
  /**
875
1085
  * One dependency guide fetched from upstream at its `path`, plus its
876
1086
  * `freshness` verdict against the local mirror.
@@ -888,20 +1098,105 @@ export declare function coreViteConfig(): string;
888
1098
  readonly content: string;
889
1099
  readonly freshness: Freshness;
890
1100
  readonly note?: string;
1101
+ /** SHA-256 of the observed local mirror, or `absent`; omitted outside target-aware pulls. */
1102
+ readonly baseline?: string;
891
1103
  }
892
1104
 
1105
+ /**
1106
+ * Build links to every generated source and application test file.
1107
+ *
1108
+ * @param spec - The workspace blueprint.
1109
+ * @param pascal - The source entity name.
1110
+ * @returns A newline-separated Markdown test inventory.
1111
+ */
1112
+ export declare function guideTests(spec: Blueprint, pascal: string): string;
1113
+
1114
+ /**
1115
+ * Build complete guide examples for every generated public function.
1116
+ *
1117
+ * @param spec - The workspace blueprint.
1118
+ * @param pascal - The source entity name.
1119
+ * @returns TypeScript fences covering each selected source and app environment.
1120
+ */
1121
+ export declare function guideUsage(spec: Blueprint, pascal: string): string;
1122
+
1123
+ /**
1124
+ * Whether a structurally valid blueprint selects at least one source or app environment.
1125
+ *
1126
+ * @param blueprint - The structurally valid blueprint to inspect.
1127
+ * @returns `true` when `src` or `app` is non-empty.
1128
+ */
1129
+ export declare function hasBlueprintEnvironment(blueprint: Blueprint): boolean;
1130
+
1131
+ /**
1132
+ * Determine whether a structured boundary contains data properties only.
1133
+ *
1134
+ * @param value - The candidate record/array graph.
1135
+ * @returns `true` when copying the graph cannot invoke a user-defined accessor.
1136
+ */
1137
+ export declare function hasOnlyDataProperties(value: unknown): boolean;
1138
+
1139
+ /** Determine whether one artifact fits the public physical-byte limit. */
1140
+ export declare function hasValidArtifactBytes(artifact: Artifact): boolean;
1141
+
1142
+ /**
1143
+ * Apply the semantic lowercase byte-pair law to an artifact's optional hex.
1144
+ *
1145
+ * @param artifact - The structurally valid artifact to inspect.
1146
+ * @returns `true` when `hex` is absent or encodes whole lowercase bytes.
1147
+ */
1148
+ export declare function hasValidArtifactHex(artifact: Artifact): boolean;
1149
+
1150
+ /** Determine whether an audit snapshot fits the aggregate retained-byte limit. */
1151
+ export declare function hasValidAuditBytes(audit: Audit): boolean;
1152
+
1153
+ /** Determine whether blueprint-authored text fits the per-item and aggregate byte limits. */
1154
+ export declare function hasValidBlueprintBytes(blueprint: Blueprint): boolean;
1155
+
1156
+ /** Determine whether one override fits the public UTF-8 artifact byte limit. */
1157
+ export declare function hasValidOverrideBytes(override: Override): boolean;
1158
+
1159
+ /** Determine whether a plan fits the aggregate retained-artifact byte limit. */
1160
+ export declare function hasValidPlanBytes(plan: Plan): boolean;
1161
+
1162
+ /**
1163
+ * Apply the artifact byte law to every nested artifact in a `Plan`.
1164
+ *
1165
+ * @param plan - The structurally valid plan to inspect.
1166
+ * @returns `true` when every artifact has absent or valid lowercase byte hex.
1167
+ */
1168
+ export declare function hasValidPlanHex(plan: Plan): boolean;
1169
+
1170
+ /** Determine whether a target snapshot is a bounded exact-byte record. */
1171
+ export declare function hasValidSnapshotBytes(snapshot: Snapshot): boolean;
1172
+
1173
+ /** Determine whether every guide body fits the public UTF-8 artifact byte limit. */
1174
+ export declare function hasValidSyncReportBytes(report: SyncReport): boolean;
1175
+
1176
+ /** Exact lowercase hexadecimal bytes: two digits per byte, including empty content. */
1177
+ export declare const HEX_PATTERN: RegExp;
1178
+
893
1179
  /**
894
1180
  * The byte-copied host artifact paths, frozen.
895
1181
  *
896
1182
  * @remarks
897
- * The root docs (`AGENTS.md` / `CLAUDE.md`), `LICENSE`, `.claude`, the three
898
- * SessionStart hook scripts (`scripts/deps.sh` / `scripts/cursor.sh` /
899
- * `scripts/ollama.sh`), the line's seven byte-identical root dotfiles,
900
- * `.github/workflows/ci.yml`, and the two guides-grouped mirrors every repo
901
- * carries: the line-wide dev-tooling guide (`guides/src/guide.md`) and the
1183
+ * The root docs (`AGENTS.md` / `CLAUDE.md`), `LICENSE`, `.agents`, `.claude`, `.codex`,
1184
+ * the four SessionStart hook scripts (`scripts/deps.sh` / `scripts/cursor.sh` /
1185
+ * `scripts/codex.sh` / `scripts/ollama.sh`), the repository coding-law policy module,
1186
+ * the line's seven byte-identical root dotfiles, and the two guides-grouped mirrors every repo carries: the line-wide
1187
+ * dev-tooling guide (`guides/src/guide.md`) and the
902
1188
  * scaffold engine's own self-guide (`guides/src/scaffold.md`).
903
1189
  */
904
- export declare const HOST_PATHS: readonly ["AGENTS.md", "CLAUDE.md", "LICENSE", ".claude", "scripts/deps.sh", "scripts/cursor.sh", "scripts/ollama.sh", ".editorconfig", ".gitattributes", ".gitignore", ".oxfmtrc.json", ".oxlintrc.json", ".oxlintignore", ".prettierignore", ".github/workflows/ci.yml", "guides/src/guide.md", "guides/src/scaffold.md"];
1190
+ export declare const HOST_PATHS: readonly string[];
1191
+
1192
+ /** A byte-copied host artifact; `source` falls back to `path` when absent. */
1193
+ export declare interface HostArtifact extends ArtifactBase {
1194
+ readonly origin: 'host';
1195
+ /** Exact lowercase hexadecimal bytes used for byte-safe host auditing. */
1196
+ readonly hex?: string;
1197
+ readonly source?: string;
1198
+ readonly content?: never;
1199
+ }
905
1200
 
906
1201
  /**
907
1202
  * Resolve the `Group` a byte-copied `HOST_PATHS` entry belongs to.
@@ -912,20 +1207,25 @@ export declare function coreViteConfig(): string;
912
1207
  * @example
913
1208
  * ```ts
914
1209
  * hostGroup('AGENTS.md') // 'docs'
1210
+ * hostGroup('.agents') // 'orchestration'
915
1211
  * hostGroup('.claude') // 'orchestration'
1212
+ * hostGroup('.codex') // 'orchestration'
916
1213
  * ```
917
1214
  */
918
1215
  export declare function hostGroup(path: string): Group;
919
1216
 
1217
+ /** Import token kept out of template literals consumed by parity scans. */
1218
+ export declare const IMPORT_KEYWORD = "import";
1219
+
920
1220
  /**
921
1221
  * Infer a foreign path's `Group` from its leading path segment.
922
1222
  *
923
1223
  * @param path - The target-relative path to classify.
924
1224
  * @remarks
925
1225
  * Ordered prefix match — `src/`, `tests/`, `guides/`, `docs/`, `configs/`,
926
- * then `.github/` / `scripts/` as `'orchestration'`, then the two manifest
927
- * files by exact name. Anything else (a root-level, prefix-less file) falls
928
- * through to `'configs'`.
1226
+ * then `.agents/`, `.claude/`, `.codex/`, `.github/`, and `scripts/` as
1227
+ * `'orchestration'`, then the two manifest files by exact name. Anything else
1228
+ * (a root-level, prefix-less file) falls through to `'configs'`.
929
1229
  * @returns The inferred `Group` for `path`.
930
1230
  *
931
1231
  * @example
@@ -938,12 +1238,15 @@ export declare function coreViteConfig(): string;
938
1238
  */
939
1239
  export declare function inferGroup(path: string): Group;
940
1240
 
1241
+ /** Visible characters forbidden by portable paths and Markdown path cells. */
1242
+ export declare const INVALID_PATH_CHARACTER_PATTERN: RegExp;
1243
+
941
1244
  /**
942
- * Narrow a value to an `Artifact` — `group` / `origin` on-vocabulary.
1245
+ * Narrow a value to an origin-discriminated `Artifact`.
943
1246
  *
944
1247
  * @remarks
945
- * Compiled from {@link artifactShape} via `createContract` (AGENTS §14) — a
946
- * total `Guard`, adversarial input returns `false`, never throws.
1248
+ * Compiled from {@link artifactShape} and refined by
1249
+ * {@link hasValidArtifactHex}; total for adversarial input.
947
1250
  */
948
1251
  export declare const isArtifact: Guard<Artifact>;
949
1252
 
@@ -964,17 +1267,28 @@ export declare function coreViteConfig(): string;
964
1267
  export declare function isBehind(freshness: Freshness): boolean;
965
1268
 
966
1269
  /**
967
- * Narrow a value to a `Blueprint` `surfaces` on-vocabulary and non-empty,
968
- * `name` a non-empty string.
1270
+ * Narrow a value to a `Blueprint` with at least one source or application environment.
969
1271
  *
970
1272
  * @remarks
971
- * Compiled from {@link blueprintShape} via `createContract` (AGENTS §14)
972
- * the `NAME_PATTERN` law is the semantic pass's (`validateBlueprint`), not
973
- * this shape's; a total `Guard`, adversarial input returns `false`, never
974
- * throws.
1273
+ * Compiled from {@link blueprintShape} via `createContract` and refined by
1274
+ * {@link hasBlueprintEnvironment}. The `NAME_PATTERN` law remains in the semantic
1275
+ * pass; this total guard returns `false` for adversarial input and never throws.
975
1276
  */
976
1277
  export declare const isBlueprint: Guard<Blueprint>;
977
1278
 
1279
+ /** Narrow an exact initial-listener record for `Compiler`. */
1280
+ export declare function isCompilerEventHooks(value: unknown): value is EmitterHooks<CompilerEventMap>;
1281
+
1282
+ /**
1283
+ * Narrow a value to a bounded dense array with index data properties only.
1284
+ *
1285
+ * @param value - The candidate array.
1286
+ * @param limit - Maximum item count.
1287
+ * @param guard - The item contract.
1288
+ * @returns `true` only when no custom iterator, method, symbol, accessor, or sparse index exists.
1289
+ */
1290
+ export declare function isDenseDataArray<T>(value: unknown, limit: number, guard: Guard<T>): value is readonly T[];
1291
+
978
1292
  /**
979
1293
  * Narrow a value to a `Dependency` — `name` and `range` non-empty strings.
980
1294
  *
@@ -984,8 +1298,11 @@ export declare function coreViteConfig(): string;
984
1298
  */
985
1299
  export declare const isDependency: Guard<Dependency>;
986
1300
 
1301
+ /** Narrow a listener-error handler accepted by the shared emitter. */
1302
+ export declare function isEmitterErrorHandler(value: unknown): value is EmitterErrorHandler;
1303
+
987
1304
  /**
988
- * Narrow a value to a `Member` — `category` and `surface` on-vocabulary.
1305
+ * Narrow a value to a `Member` — `category` and `environment` on-vocabulary.
989
1306
  *
990
1307
  * @remarks
991
1308
  * Compiled from {@link memberShape} via `createContract` (AGENTS §14) — a
@@ -1012,22 +1329,8 @@ export declare function coreViteConfig(): string;
1012
1329
  */
1013
1330
  export declare const isPlan: Guard<Plan>;
1014
1331
 
1015
- /**
1016
- * Narrow an unknown value to a plain (non-array, non-null) JSON object.
1017
- *
1018
- * @param value - The value to narrow.
1019
- * @returns `true` iff `value` is a non-null, non-array object.
1020
- *
1021
- * @example
1022
- * ```ts
1023
- * import { isRecord } from '@orkestrel/scaffold'
1024
- *
1025
- * isRecord({ a: 1 }) // true
1026
- * isRecord([1, 2]) // false
1027
- * isRecord(null) // false
1028
- * ```
1029
- */
1030
- export declare function isRecord(value: unknown): value is Record<string, unknown>;
1332
+ /** Narrow an exact initial-listener record for `PlanManager`. */
1333
+ export declare function isPlanManagerEventHooks(value: unknown): value is EmitterHooks<PlanManagerEventMap>;
1031
1334
 
1032
1335
  /**
1033
1336
  * Narrow a caught value to a `ScaffoldError`.
@@ -1049,11 +1352,19 @@ export declare function coreViteConfig(): string;
1049
1352
  * `guide` / `version` sections composed.
1050
1353
  *
1051
1354
  * @remarks
1052
- * Compiled from {@link syncReportShape} via `createContract` (AGENTS §14) — a
1053
- * total `Guard`, adversarial input returns `false`, never throws.
1355
+ * Compiled from {@link syncReportShape} via `createContract` and refined by
1356
+ * {@link hasValidSyncReportBytes}; total for adversarial input.
1054
1357
  */
1055
1358
  export declare const isSyncReport: Guard<SyncReport>;
1056
1359
 
1360
+ /**
1361
+ * Narrow a value to the bounded bare name accepted by a workspace blueprint.
1362
+ *
1363
+ * @param value - The candidate workspace name.
1364
+ * @returns `true` only for a `NAME_PATTERN` string no longer than `MAX_NAME_LENGTH`.
1365
+ */
1366
+ export declare function isWorkspaceName(value: unknown): value is string;
1367
+
1057
1368
  /** The fleet's `.oxfmtrc.json` `printWidth` — `formatJson`'s array-collapse threshold. */
1058
1369
  export declare const JSON_PRINT_WIDTH = 100;
1059
1370
 
@@ -1081,12 +1392,53 @@ export declare function coreViteConfig(): string;
1081
1392
  */
1082
1393
  export declare function manifestToDependencies(manifestText: string): readonly Dependency[];
1083
1394
 
1395
+ /** Maximum byte size accepted for one scaffold artifact. */
1396
+ export declare const MAX_ARTIFACT_BYTES = 5242880;
1397
+
1398
+ /** Maximum hexadecimal string length representing one scaffold artifact. */
1399
+ export declare const MAX_ARTIFACT_HEX_LENGTH: number;
1400
+
1401
+ /** Maximum items accepted by one public package collection. */
1402
+ export declare const MAX_COLLECTION_ITEMS = 1000;
1403
+
1404
+ /** Maximum own keys inspected across one untrusted data-only graph boundary. */
1405
+ export declare const MAX_DATA_GRAPH_KEYS: number;
1406
+
1407
+ /** Maximum distinct records or arrays traversed at one untrusted data-only graph boundary. */
1408
+ export declare const MAX_DATA_GRAPH_NODES: number;
1409
+
1410
+ /** Maximum dependency package name length, including the canonical scope. */
1411
+ export declare const MAX_DEPENDENCY_NAME_LENGTH = 214;
1412
+
1413
+ /** Maximum UTF-8 bytes accepted for one package or host manifest. */
1414
+ export declare const MAX_MANIFEST_BYTES = 1048576;
1415
+
1416
+ /** Maximum bare workspace name length beneath the generated `@orkestrel/` scope. */
1417
+ export declare const MAX_NAME_LENGTH = 203;
1418
+
1419
+ /** Maximum general path length accepted at serialized package boundaries. */
1420
+ export declare const MAX_PATH_LENGTH = 32767;
1421
+
1422
+ /** Maximum package range or endpoint-sized token length. */
1423
+ export declare const MAX_RANGE_LENGTH = 2048;
1424
+
1425
+ /**
1426
+ * Maximum UTF-8 bytes accepted by a public serialized JSON parser.
1427
+ *
1428
+ * Four aggregate artifact budgets admit the hexadecimal and metadata overhead
1429
+ * of the largest supported contracts while bounding allocation before JSON parsing.
1430
+ */
1431
+ export declare const MAX_SERIALIZED_INPUT_BYTES: number;
1432
+
1433
+ /** Maximum aggregate bytes retained by one blueprint, plan, audit, or sync report. */
1434
+ export declare const MAX_TOTAL_ARTIFACT_BYTES = 104857600;
1435
+
1084
1436
  /** One declared public export of the scaffolded package; derived by `blueprintToMembers`, never authored. */
1085
1437
  export declare interface Member {
1086
1438
  readonly name: string;
1087
1439
  readonly category: Category;
1088
1440
  readonly summary: string;
1089
- readonly surface: Surface;
1441
+ readonly environment: Environment;
1090
1442
  }
1091
1443
 
1092
1444
  /**
@@ -1095,30 +1447,33 @@ export declare function coreViteConfig(): string;
1095
1447
  * @param name - The declared export name.
1096
1448
  * @param category - The `Member`'s `Category`.
1097
1449
  * @param summary - A one-line description.
1098
- * @param surface - The owning `Surface`; defaults `'core'`.
1450
+ * @param environment - The owning `Environment`; defaults `'core'`.
1099
1451
  * @returns A `Member` with every field set.
1100
1452
  *
1101
1453
  * @example
1102
1454
  * ```ts
1103
1455
  * import { member } from '@orkestrel/scaffold'
1104
1456
  *
1105
- * member('RouterOptions', 'type', 'Options for creating a Router.') // surface: 'core'
1457
+ * member('RouterOptions', 'type', 'Options for creating a Router.') // environment: 'core'
1106
1458
  * ```
1107
1459
  */
1108
- export declare function member(name: string, category: Category, summary: string, surface?: Surface): Member;
1460
+ export declare function member(name: string, category: Category, summary: string, environment?: Environment): Member;
1109
1461
 
1110
1462
  /**
1111
1463
  * Build the `Member` object shape.
1112
1464
  *
1113
- * @returns A fresh `ContractShape` describing `{ name, category, summary, surface }`.
1465
+ * @returns A fresh `ContractShape` describing `{ name, category, summary, environment }`.
1114
1466
  */
1115
1467
  export declare function memberShape(): ObjectShape<{
1116
1468
  name: StringShape;
1117
- category: LiteralShape<readonly ["type", "constant", "factory", "entity"]>;
1469
+ category: LiteralShape<readonly Category[]>;
1118
1470
  summary: StringShape;
1119
- surface: LiteralShape<readonly ["core", "browser", "server"]>;
1471
+ environment: LiteralShape<readonly Environment[]>;
1120
1472
  }, false>;
1121
1473
 
1474
+ /** The oldest Node version supported by the generated Vite toolchain. */
1475
+ export declare const MINIMUM_NODE_VERSION = "22.12.0";
1476
+
1122
1477
  /** The package-name RegExp — lowercase alphanumeric-with-hyphens, letter-first. */
1123
1478
  export declare const NAME_PATTERN: RegExp;
1124
1479
 
@@ -1131,7 +1486,10 @@ export declare function coreViteConfig(): string;
1131
1486
  export declare type Origin = 'host' | 'template' | 'computed';
1132
1487
 
1133
1488
  /** The three `Origin` values, frozen. */
1134
- export declare const ORIGINS: readonly ["host", "template", "computed"];
1489
+ export declare const ORIGINS: readonly Origin[];
1490
+
1491
+ /** The exact caret-pinned pre-1.0 range accepted for Orkestrel runtime dependencies. */
1492
+ export declare const ORKESTREL_RANGE_PATTERN: RegExp;
1135
1493
 
1136
1494
  /**
1137
1495
  * One caller template override.
@@ -1172,9 +1530,27 @@ export declare function coreViteConfig(): string;
1172
1530
  content: StringShape;
1173
1531
  }, false>;
1174
1532
 
1533
+ /**
1534
+ * Read one own data property without traversing a prototype or invoking an accessor.
1535
+ *
1536
+ * @param value - The candidate record.
1537
+ * @param key - The own property name to read.
1538
+ * @returns The data property's value, or `undefined` when it is absent, accessor-backed,
1539
+ * non-record, or cannot be inspected.
1540
+ *
1541
+ * @example
1542
+ * ```ts
1543
+ * import { ownDataValue } from '@orkestrel/scaffold'
1544
+ *
1545
+ * ownDataValue({ name: 'router' }, 'name') // 'router'
1546
+ * ownDataValue(Object.create({ name: 'inherited' }), 'name') // undefined
1547
+ * ```
1548
+ */
1549
+ export declare function ownDataValue(value: unknown, key: string): unknown;
1550
+
1175
1551
  /**
1176
1552
  * Compute the `package.json` artifact's `content`, applying the manifest and
1177
- * exports combination rules over a blueprint's surfaces — grounded against the
1553
+ * exports combination rules over a blueprint's src — grounded against the
1178
1554
  * live @orkestrel/middleware (core+server) and @orkestrel/router
1179
1555
  * (core+browser+server) exemplars.
1180
1556
  *
@@ -1211,12 +1587,12 @@ export declare function coreViteConfig(): string;
1211
1587
  /**
1212
1588
  * Build the computed `SELF_SPECIFIERS` / `SPECIFIER_MODULES` / `exportsFor`
1213
1589
  * block the `parityTest` template's `{{specifiers}}` placeholder fills —
1214
- * ONE shape for every surface count (grounded against the live single-surface
1215
- * websocket/indexeddb and multi-surface router/middleware exemplars, which
1590
+ * ONE shape for every environment count (grounded against the live single-environment
1591
+ * websocket/indexeddb and multi-environment router/middleware exemplars, which
1216
1592
  * both resolve a fence's specifier through a `SPECIFIER_MODULES` map rather
1217
1593
  * than a single-module lookup). The bare `@orkestrel/<name>` specifier
1218
- * resolves to the PRIMARY surface — `core` when declared, else the sole
1219
- * declared surface.
1594
+ * resolves to the PRIMARY environment — `core` when declared, else the sole
1595
+ * declared environment.
1220
1596
  *
1221
1597
  * @param spec - The `Blueprint` to derive the parity specifiers block from.
1222
1598
  * @returns The computed `parityTest` `{{specifiers}}` block content.
@@ -1240,7 +1616,34 @@ export declare function coreViteConfig(): string;
1240
1616
  * @param input - The value (or JSON string) to parse.
1241
1617
  * @returns A `Blueprint`, else `undefined`.
1242
1618
  */
1243
- export declare const parseBlueprint: (input: unknown) => Blueprint | undefined;
1619
+ export declare function parseBlueprint(input: unknown): Blueprint | undefined;
1620
+
1621
+ /**
1622
+ * Parse JSON only when its UTF-8 representation fits an explicit allocation budget.
1623
+ *
1624
+ * @param input - Serialized JSON text.
1625
+ * @param guard - Contract guard for the parsed value.
1626
+ * @param maximum - Maximum serialized UTF-8 bytes; defaults to the public input ceiling.
1627
+ * @returns The guarded value, or `undefined` when malformed, over budget, or off-contract.
1628
+ *
1629
+ * @example
1630
+ * ```ts
1631
+ * import { parseBoundedJSON } from '@orkestrel/scaffold'
1632
+ *
1633
+ * parseBoundedJSON('"ready"', (value): value is string => typeof value === 'string', 7)
1634
+ * // 'ready'
1635
+ * ```
1636
+ */
1637
+ export declare function parseBoundedJSON<T>(input: string, guard: Guard<T>, maximum?: number): T | undefined;
1638
+
1639
+ /**
1640
+ * Parse and own the exact `Compiler` constructor boundary before emitter allocation.
1641
+ *
1642
+ * @param input - Caller-supplied options.
1643
+ * @returns Fresh immutable options containing owned listener hooks.
1644
+ * @throws ScaffoldError with code INVALID for unknown keys, accessors, symbols, or hostile traps.
1645
+ */
1646
+ export declare function parseCompilerOptions(input: unknown): CompilerOptions;
1244
1647
 
1245
1648
  /**
1246
1649
  * Parse a `Plan` from `unknown` (or a JSON string), else `undefined`.
@@ -1254,7 +1657,34 @@ export declare function coreViteConfig(): string;
1254
1657
  * @param input - The value (or JSON string) to parse.
1255
1658
  * @returns A `Plan`, else `undefined`.
1256
1659
  */
1257
- export declare const parsePlan: (input: unknown) => Plan | undefined;
1660
+ export declare function parsePlan(input: unknown): Plan | undefined;
1661
+
1662
+ /**
1663
+ * Snapshot a bounded dense array of unique plan ids without invoking its iterator.
1664
+ *
1665
+ * @param input - The untrusted batch-removal boundary.
1666
+ * @returns A frozen id array, or `undefined` for accessors, symbols, holes,
1667
+ * duplicates, non-string values, excessive length, or hostile proxy traps.
1668
+ *
1669
+ * @example
1670
+ * ```ts
1671
+ * import { parsePlanIds } from '@orkestrel/scaffold'
1672
+ *
1673
+ * parsePlanIds(['a', 'b']) // ['a', 'b']
1674
+ * parsePlanIds(['a', 'a']) // undefined
1675
+ * ```
1676
+ */
1677
+ export declare function parsePlanIds(input: unknown): readonly string[] | undefined;
1678
+
1679
+ /**
1680
+ * Parse and own the exact `PlanManager` constructor boundary before resource allocation.
1681
+ *
1682
+ * @param input - Caller-supplied options.
1683
+ * @returns Fresh options containing immutable plan snapshots and own listener hooks.
1684
+ * @throws ScaffoldError with code INVALID for unknown keys, accessors, symbols,
1685
+ * hostile traps, malformed hooks, or malformed/unbounded seed plans.
1686
+ */
1687
+ export declare function parsePlanManagerOptions(input: unknown): PlanManagerOptions;
1258
1688
 
1259
1689
  /**
1260
1690
  * Parse a `SyncReport` from `unknown` (or a JSON string), else `undefined`.
@@ -1268,7 +1698,7 @@ export declare function coreViteConfig(): string;
1268
1698
  * @param input - The value (or JSON string) to parse.
1269
1699
  * @returns A `SyncReport`, else `undefined`.
1270
1700
  */
1271
- export declare const parseSyncReport: (input: unknown) => SyncReport | undefined;
1701
+ export declare function parseSyncReport(input: unknown): SyncReport | undefined;
1272
1702
 
1273
1703
  /**
1274
1704
  * Derive the PascalCase entity name from a lowercase-hyphen package name.
@@ -1293,19 +1723,26 @@ export declare function coreViteConfig(): string;
1293
1723
  * `hash` is a canonical `computeHash` digest of the plan's
1294
1724
  * blueprint/groups/artifacts, serialized through `stableStringify` —
1295
1725
  * deterministic, no clocks or randomness. `trace` is a one-line derivation
1296
- * summary built from the plan's own `PlanSummary`.
1726
+ * summary built from the plan's own `PlanSummary`; its explicit `src:` and
1727
+ * `app:` fields use `none` when that independent axis is empty.
1297
1728
  * @returns The plan with `trace` and `hash` filled.
1298
1729
  *
1299
1730
  * @example
1300
1731
  * ```ts
1301
1732
  * import { pinPlan } from '@orkestrel/scaffold'
1302
1733
  *
1303
- * pinPlan(plan).trace // 'router · core+browser · groups:7 · artifacts:21'
1734
+ * pinPlan(plan).trace // 'router · src:core+browser · app:none · groups:7 · artifacts:21'
1304
1735
  * ```
1305
1736
  */
1306
1737
  export declare function pinPlan(plan: Plan): Plan;
1307
1738
 
1308
- /** The compiled, ordered artifact list plus the selection it covers; `trace` / `hash` filled by the pin. */
1739
+ /**
1740
+ * The compiled, ordered artifact list plus the independent source/application selection it covers.
1741
+ *
1742
+ * @remarks
1743
+ * `pinPlan` fills `trace` with explicit `src:` and `app:` axes and fills
1744
+ * `hash` from the plan's identity payload.
1745
+ */
1309
1746
  export declare interface Plan {
1310
1747
  readonly blueprint: Blueprint;
1311
1748
  readonly groups: readonly Group[];
@@ -1322,17 +1759,20 @@ export declare function coreViteConfig(): string;
1322
1759
  * `hash` — deterministic, no randomness. Re-adding a plan whose content is
1323
1760
  * unchanged resolves to the SAME id and returns the existing record
1324
1761
  * untouched (`version` stays put); a plan whose content differs mints a
1325
- * fresh id at `version: 1`. The array overload of `remove` is declared FIRST
1326
- * (AGENTS §9.2) so an id list resolves to the batch form; the batch form is
1327
- * ALL-OR-NOTHING. After `destroy()` every method but the getters and
1328
- * `destroy` itself throws `ScaffoldError('DESTROYED', …)`.
1762
+ * fresh id at `version: 1`, while a distinct canonical payload with the same
1763
+ * digest throws `INVALID`. Every stored plan and returned record is a detached,
1764
+ * recursively frozen snapshot. The array overload of `remove` is declared
1765
+ * FIRST (AGENTS §9.2) so an id list resolves to the batch form; the batch form
1766
+ * is ALL-OR-NOTHING and commits every deletion before emitting. After
1767
+ * `destroy()` every method but the getters and `destroy` itself throws
1768
+ * `ScaffoldError('DESTROYED', …)`.
1329
1769
  *
1330
1770
  * @example
1331
1771
  * ```ts
1332
1772
  * import { blueprint, blueprintToPlan, PlanManager } from '@src/core'
1333
1773
  *
1334
1774
  * const plans = new PlanManager()
1335
- * const record = plans.add(blueprintToPlan(blueprint('budget', { surfaces: ['core'] })))
1775
+ * const record = plans.add(blueprintToPlan(blueprint('budget', { src: ['core'] })))
1336
1776
  * record.id === record.hash // true — id minted from content
1337
1777
  * plans.destroy()
1338
1778
  * ```
@@ -1371,7 +1811,7 @@ export declare function coreViteConfig(): string;
1371
1811
  *
1372
1812
  * @example
1373
1813
  * ```ts
1374
- * const record = plans.add(blueprintToPlan(blueprint('budget', { surfaces: ['core'] })))
1814
+ * const record = plans.add(blueprintToPlan(blueprint('budget', { src: ['core'] })))
1375
1815
  * record.version // 1
1376
1816
  * ```
1377
1817
  */
@@ -1386,7 +1826,8 @@ export declare function coreViteConfig(): string;
1386
1826
  * `remove(id)` removes one plan, emitting `remove` and returning `true`
1387
1827
  * when it existed, `false` otherwise. `remove(ids)` is ALL-OR-NOTHING: if
1388
1828
  * any listed id is unregistered, the collection is left untouched and
1389
- * `false` is returned.
1829
+ * `false` is returned. Successful batch and remove-all calls commit every
1830
+ * deletion before the first stable-order event.
1390
1831
  *
1391
1832
  * @param target - Omit to remove all, a single id, or a list of ids.
1392
1833
  * @returns `boolean` for the single-id / list-of-ids forms; `void` for the remove-all form.
@@ -1398,7 +1839,7 @@ export declare function coreViteConfig(): string;
1398
1839
  destroy(): void;
1399
1840
  }
1400
1841
 
1401
- /** `PlanManager`'s push observation surface (AGENTS §13). */
1842
+ /** `PlanManager`'s push observation channel (AGENTS §13). */
1402
1843
  export declare type PlanManagerEventMap = {
1403
1844
  readonly add: readonly [id: string];
1404
1845
  readonly remove: readonly [id: string];
@@ -1426,6 +1867,21 @@ export declare function coreViteConfig(): string;
1426
1867
  readonly error?: EmitterErrorHandler;
1427
1868
  }
1428
1869
 
1870
+ /**
1871
+ * Serialize exactly the content that establishes a plan's identity.
1872
+ *
1873
+ * @param plan - The plan whose identity payload to serialize.
1874
+ * @returns The canonical blueprint, group, and artifact payload.
1875
+ *
1876
+ * @example
1877
+ * ```ts
1878
+ * import { planPayload } from '@orkestrel/scaffold'
1879
+ *
1880
+ * planPayload(plan) === planPayload({ ...plan, trace: 'different' }) // true
1881
+ * ```
1882
+ */
1883
+ export declare function planPayload(plan: Plan): string;
1884
+
1429
1885
  /** A versioned, content-hashed `Plan` inside a `PlanManager`. */
1430
1886
  export declare interface PlanRecord {
1431
1887
  readonly id: string;
@@ -1448,7 +1904,8 @@ export declare function coreViteConfig(): string;
1448
1904
  name: StringShape;
1449
1905
  description: OptionalShape<StringShape>;
1450
1906
  keywords: ArrayShape<StringShape>;
1451
- surfaces: ArrayShape<LiteralShape<readonly ["core", "browser", "server"]>>;
1907
+ src: ArrayShape<LiteralShape<readonly Environment[]>>;
1908
+ app: ArrayShape<LiteralShape<readonly Environment[]>>;
1452
1909
  dependencies: ArrayShape<ObjectShape<{
1453
1910
  name: StringShape;
1454
1911
  range: StringShape;
@@ -1470,24 +1927,32 @@ export declare function coreViteConfig(): string;
1470
1927
  path: StringShape;
1471
1928
  content: StringShape;
1472
1929
  }, false>>;
1930
+ engine: BooleanShape;
1473
1931
  }, false>;
1474
- groups: ArrayShape<LiteralShape<readonly ["manifest", "configs", "source", "tests", "guides", "docs", "orchestration"]>>;
1475
- artifacts: ArrayShape<ObjectShape<{
1932
+ groups: ArrayShape<LiteralShape<readonly Group[]>>;
1933
+ artifacts: ArrayShape<UnionShape<[ ObjectShape<{
1476
1934
  path: StringShape;
1477
- group: LiteralShape<readonly ["manifest", "configs", "source", "tests", "guides", "docs", "orchestration"]>;
1478
- origin: LiteralShape<readonly ["host", "template", "computed"]>;
1479
- surface: OptionalShape<LiteralShape<readonly ["core", "browser", "server"]>>;
1480
- content: OptionalShape<StringShape>;
1935
+ group: LiteralShape<readonly Group[]>;
1936
+ origin: LiteralShape<readonly ["host"]>;
1937
+ environment: OptionalShape<LiteralShape<readonly Environment[]>>;
1938
+ hex: OptionalShape<StringShape>;
1481
1939
  source: OptionalShape<StringShape>;
1482
- }, false>>;
1940
+ }, false>, ObjectShape<{
1941
+ path: StringShape;
1942
+ group: LiteralShape<readonly Group[]>;
1943
+ origin: LiteralShape<readonly ["template", "computed"]>;
1944
+ environment: OptionalShape<LiteralShape<readonly Environment[]>>;
1945
+ content: StringShape;
1946
+ }, false>]>>;
1483
1947
  trace: OptionalShape<StringShape>;
1484
1948
  hash: OptionalShape<StringShape>;
1485
1949
  }, false>;
1486
1950
 
1487
- /** The dry-run tally. */
1951
+ /** The dry-run tally, including the independent source and application environment selections. */
1488
1952
  export declare interface PlanSummary {
1489
1953
  readonly name: string;
1490
- readonly surfaces: readonly Surface[];
1954
+ readonly src: readonly Environment[];
1955
+ readonly app: readonly Environment[];
1491
1956
  readonly groups: readonly Group[];
1492
1957
  readonly artifacts: number;
1493
1958
  readonly host: number;
@@ -1514,7 +1979,7 @@ export declare function coreViteConfig(): string;
1514
1979
  * Project a `Plan` into a `PlanSummary`.
1515
1980
  *
1516
1981
  * @param plan - The plan to summarize.
1517
- * @returns The artifact tally by `origin`, the surfaces, and the covered groups.
1982
+ * @returns The artifact tally by `origin`, both environment axes, and the covered groups.
1518
1983
  *
1519
1984
  * @example
1520
1985
  * ```ts
@@ -1525,6 +1990,9 @@ export declare function coreViteConfig(): string;
1525
1990
  */
1526
1991
  export declare function planToSummary(plan: Plan): PlanSummary;
1527
1992
 
1993
+ /** Build the dedicated Node-only repository policy Vitest project. */
1994
+ export declare function policyViteProject(): string;
1995
+
1528
1996
  /**
1529
1997
  * One validation issue.
1530
1998
  *
@@ -1617,10 +2085,11 @@ export declare function coreViteConfig(): string;
1617
2085
  export declare function renderValue(entry: unknown, indent: string, prefix: string, suffix: string): string;
1618
2086
 
1619
2087
  /**
1620
- * The root `tsconfig.json` — one `@src/<surface>` path alias per declared
1621
- * surface, in declared order.
2088
+ * The root `tsconfig.json` — one `@src/<environment>` path alias per declared
2089
+ * environment, in declared order.
1622
2090
  *
1623
- * @param surfaces - The declared `Surface[]`.
2091
+ * @param src - The declared `Environment[]`.
2092
+ * @param app - The declared application environments, defaulting to none.
1624
2093
  * @returns The root `tsconfig.json` file content, newline-terminated.
1625
2094
  *
1626
2095
  * @example
@@ -1628,26 +2097,30 @@ export declare function coreViteConfig(): string;
1628
2097
  * rootTsconfig(['core']) // '{\n\t"compilerOptions": {…}\n}\n'
1629
2098
  * ```
1630
2099
  */
1631
- export declare function rootTsconfig(surfaces: readonly Surface[]): string;
2100
+ export declare function rootTsconfig(src: readonly Environment[], app?: readonly Environment[]): string;
1632
2101
 
1633
2102
  /**
1634
2103
  * The root `vite.config.ts` — three grounded shapes, chosen by a blueprint's
1635
- * `surfaces`:
2104
+ * `src`:
1636
2105
  * 1. `core`-only — `srcCore` + `guides`, no Playwright at all (the live
1637
2106
  * timeout exemplar: no browser project exists anywhere in the file).
1638
- * 2. Multi-surface (2+ surfaces, always including `core` per the live
2107
+ * 2. Multi-environment (2+ src, always including `core` per the live
1639
2108
  * middleware/router exemplars) — `srcCore` is the shared base;
1640
2109
  * `srcBrowser` / `srcServer` extend it and externalize `@src/core` to
1641
2110
  * the sibling build. Playwright ships UNCONDITIONALLY (middleware
1642
- * carries it with no browser surface — grounded, not conditional).
1643
- * 3. A single non-`core` surface (`browser`-only / `server`-only) — the
1644
- * surface factory itself IS the base (no `srcCore` to extend, so no
2111
+ * carries it with no browser environment — grounded, not conditional).
2112
+ * 3. A single non-`core` environment (`browser`-only / `server`-only) — the
2113
+ * environment factory itself IS the base (no `srcCore` to extend, so no
1645
2114
  * dead `@src/core` externalize/remap either — there is no sibling
1646
2115
  * core build), per the live sqlite (server-only) / indexeddb
1647
2116
  * (browser-only) exemplars. Playwright ships only when the sole
1648
- * surface is `browser` (it must run its own tests in a real browser).
2117
+ * environment is `browser` (it must run its own tests in a real browser).
1649
2118
  *
1650
- * @param surfaces - The declared `Surface[]`.
2119
+ * @param src - The declared `Environment[]`.
2120
+ * @param engine - Structural: `true` appends the `srcBin` project (an
2121
+ * executable build target, never a barrel) after the other declared
2122
+ * projects — the self-hosting tax, grounded against this very repo's own
2123
+ * checked-in `vite.config.ts`.
1651
2124
  * @returns The root `vite.config.ts` file content, newline-terminated.
1652
2125
  *
1653
2126
  * @example
@@ -1655,7 +2128,7 @@ export declare function coreViteConfig(): string;
1655
2128
  * rootViteConfig(['core']).includes('srcCore') // true
1656
2129
  * ```
1657
2130
  */
1658
- export declare function rootViteConfig(surfaces: readonly Surface[]): string;
2131
+ export declare function rootViteConfig(src: readonly Environment[], engine?: boolean): string;
1659
2132
 
1660
2133
  /** The devDependency range generated packages pin `@orkestrel/scaffold` at. */
1661
2134
  export declare const SCAFFOLD_RANGE = "^0.0.2";
@@ -1666,7 +2139,7 @@ export declare function coreViteConfig(): string;
1666
2139
  * @remarks
1667
2140
  * Throws are reserved for caller misuse: `createBlueprint` on off-contract
1668
2141
  * data throws `INVALID`, any method after `destroy()` throws `DESTROYED`, and
1669
- * on the server surface a non-vacant target throws `TARGET` while a failed
2142
+ * in the server environment a non-vacant target throws `TARGET` while a failed
1670
2143
  * write throws `WRITE`. A failing gate is NOT an error — it fails closed into
1671
2144
  * an incomplete `Scaffolding` whose `failures` carry a `BLOCKED` marker.
1672
2145
  *
@@ -1702,28 +2175,78 @@ export declare function coreViteConfig(): string;
1702
2175
  }
1703
2176
 
1704
2177
  /**
1705
- * The single non-`core` surface's factory IS the base (Shape 3 of
1706
- * `rootViteConfig`) — the surface's own `viteHeader` (Playwright only when
1707
- * `surface === 'browser'`, per the live sqlite/indexeddb exemplars) prefixes
1708
- * the surface-specific `srcBrowser` / `srcServer` + `guides` projects export.
2178
+ * Serialize text as a single-quoted TypeScript string literal.
2179
+ *
2180
+ * @param value - The untrusted text value.
2181
+ * @returns A source literal preserving every UTF-16 code unit.
2182
+ *
2183
+ * @example
2184
+ * ```ts
2185
+ * import { serializeTypeScriptString } from '@orkestrel/scaffold'
2186
+ *
2187
+ * serializeTypeScriptString("app's") // "'app\\'s'"
2188
+ * ```
2189
+ */
2190
+ export declare function serializeTypeScriptString(value: string): string;
2191
+
2192
+ /** Immutable official actions/setup-node v6.4.0 commit used by generated CI. */
2193
+ export declare const SETUP_NODE_ACTION_SHA = "48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e";
2194
+
2195
+ /**
2196
+ * The single non-`core` environment's factory IS the base (Shape 3 of
2197
+ * `rootViteConfig`) — the environment's own `viteHeader` (Playwright only when
2198
+ * `environment === 'browser'`, per the live sqlite/indexeddb exemplars) prefixes
2199
+ * the environment-specific `srcBrowser` / `srcServer` + `guides` projects export.
1709
2200
  *
1710
- * @param surface - The sole declared non-`core` surface.
1711
- * @returns The root `vite.config.ts` file content for a single non-`core` surface, newline-terminated.
2201
+ * @param environment - The sole declared non-`core` environment.
2202
+ * @returns The root `vite.config.ts` file content for a single non-`core` environment, newline-terminated.
1712
2203
  *
1713
2204
  * @example
1714
2205
  * ```ts
1715
- * singleSurfaceViteConfig('server').includes('srcServer') // true
2206
+ * singleSrcViteConfig('server').includes('srcServer') // true
1716
2207
  * ```
1717
2208
  */
1718
- export declare function singleSurfaceViteConfig(surface: 'browser' | 'server'): string;
2209
+ export declare function singleSrcViteConfig(environment: 'browser' | 'server'): string;
2210
+
2211
+ /** Exact lowercase hexadecimal target bytes keyed by artifact-relative path. */
2212
+ export declare type Snapshot = Readonly<Record<string, string>>;
2213
+
2214
+ /**
2215
+ * Build an exact-byte snapshot from text content keyed by artifact path.
2216
+ *
2217
+ * @param current - Text content keyed by artifact path.
2218
+ * @returns The same keys with UTF-8 bytes encoded as lowercase hexadecimal.
2219
+ */
2220
+ export declare function snapshotOf(current: Readonly<Record<string, string>>): Snapshot;
2221
+
2222
+ /**
2223
+ * Clone and recursively freeze a plan into an immutable owned snapshot.
2224
+ *
2225
+ * @param input - The untrusted plan boundary to snapshot.
2226
+ * @returns A detached, recursively frozen plan.
2227
+ * @throws ScaffoldError with code INVALID when the input is off-contract,
2228
+ * accessor-backed, uncloneable, or cannot be frozen.
2229
+ *
2230
+ * @example
2231
+ * ```ts
2232
+ * import { snapshotPlan } from '@orkestrel/scaffold'
2233
+ *
2234
+ * const snapshot = snapshotPlan(plan)
2235
+ * Object.isFrozen(snapshot.blueprint) // true
2236
+ * ```
2237
+ */
2238
+ export declare function snapshotPlan(input: unknown): Plan;
2239
+
2240
+ /** Additional development dependency required by a published browser source environment. */
2241
+ export declare const SOURCE_BROWSER_DEV_DEPENDENCIES: Readonly<Record<string, string>>;
1719
2242
 
1720
2243
  /**
1721
2244
  * Draft the `source` group's `template` artifacts — the generated-minimal
1722
- * `src/<surface>/*` stubs, one full {types, <Pascal>, factories, index} set
1723
- * PER declared surface (never assuming `core`), filled from `TEMPLATES` with
2245
+ * `src/<environment>/*` stubs, one full {types, <Pascal>, factories, index} set
2246
+ * PER declared environment (never assuming `core`), filled from `TEMPLATES` with
1724
2247
  * `missing: 'error'`. `blueprintToMembers` already declares a full entity +
1725
- * factory per surface (AGENTS §5's per-surface centralized-file pattern), so
1726
- * every surface gets the same uniform stub shape.
2248
+ * factory per environment (AGENTS §5's per-environment centralized-file pattern), so
2249
+ * every environment gets the same uniform stub shape.
1727
2250
  *
1728
2251
  * @param spec - The `Blueprint` to derive source stubs from.
1729
2252
  * @param pascal - The package's PascalCase entity name.
@@ -1756,100 +2279,86 @@ export declare function coreViteConfig(): string;
1756
2279
  export declare function splitTableRow(line: string): readonly string[];
1757
2280
 
1758
2281
  /**
1759
- * Serialize a value to a canonical, key-order-INDEPENDENT JSON-like string.
1760
- *
1761
- * @param value - The value to stringify.
1762
- * @remarks
1763
- * Object keys sort code-unit; array order is preserved. So two
1764
- * logically-equal blueprints built with their fields in a different
1765
- * construction order still hash identically once fed through `computeHash`.
1766
- * @returns The canonical string form of `value`.
1767
- *
1768
- * @example
1769
- * ```ts
1770
- * import { stableStringify } from '@orkestrel/scaffold'
1771
- *
1772
- * stableStringify({ b: 1, a: 2 }) // '{"a":2,"b":1}'
1773
- * ```
1774
- */
1775
- export declare function stableStringify(value: unknown): string;
1776
-
1777
- /** The environment surface an artifact or member belongs to (the SCAFFOLDED package's faces, not scaffold's own). */
1778
- export declare type Surface = 'core' | 'browser' | 'server';
1779
-
1780
- /**
1781
- * The per-surface variant matrix as data: per `Surface`, its `configs/src`
2282
+ * The per-environment variant matrix as data: per `Environment`, its `configs/src`
1782
2283
  * files, Vitest project label, `exports` subpath, and build formats — the
1783
- * per-surface layer `blueprintToPlan` reads BENEATH the manifest/exports
2284
+ * per-environment layer `blueprintToPlan` reads BENEATH the manifest/exports
1784
2285
  * combination rules it applies on top.
1785
2286
  */
1786
- export declare const SURFACE_MATRIX: Readonly<{
1787
- readonly core: Readonly<{
1788
- configs: readonly ["configs/src/vite.core.config.ts", "configs/src/tsconfig.core.json"];
1789
- project: "src:core";
1790
- path: ".";
1791
- formats: readonly ["es", "cjs"];
1792
- }>;
1793
- readonly browser: Readonly<{
1794
- configs: readonly ["configs/src/vite.browser.config.ts", "configs/src/tsconfig.browser.json"];
1795
- project: "src:browser";
1796
- path: "./browser";
1797
- formats: readonly ["es"];
1798
- }>;
1799
- readonly server: Readonly<{
1800
- configs: readonly ["configs/src/vite.server.config.ts", "configs/src/tsconfig.server.json"];
1801
- project: "src:server";
1802
- path: "./server";
1803
- formats: readonly ["es", "cjs"];
1804
- }>;
1805
- }>;
1806
-
1807
- /** The three `Surface` values, frozen — compose with `literalOf(...)` / `parseEnum(...)`. */
1808
- export declare const SURFACES: readonly ["core", "browser", "server"];
2287
+ export declare const SRC_MATRIX: Readonly<Record<Environment, SrcDefinition>>;
2288
+
2289
+ /** The deterministic build and export settings for one source environment. */
2290
+ export declare interface SrcDefinition {
2291
+ readonly configs: readonly string[];
2292
+ readonly project: string;
2293
+ readonly path: string;
2294
+ readonly formats: readonly BuildFormat[];
2295
+ }
1809
2296
 
1810
2297
  /**
1811
2298
  * `configs/src/tsconfig.<browser|server>.json` — `rootDir`/`outDir` point at
1812
- * the whole `src`/`dist/src` tree (not a per-surface subfolder), per the live
2299
+ * the whole `src`/`dist/src` tree (not a per-environment subfolder), per the live
1813
2300
  * middleware/router exemplars.
1814
2301
  *
1815
- * @param surface - The non-`core` surface to derive the `tsconfig` for.
1816
- * @returns The surface `tsconfig` file content, newline-terminated.
2302
+ * @param environment - The non-`core` environment to derive the `tsconfig` for.
2303
+ * @returns The environment `tsconfig` file content, newline-terminated.
1817
2304
  *
1818
2305
  * @example
1819
2306
  * ```ts
1820
- * surfaceTsconfig('server').includes('"rootDir": "../../src"') // true
2307
+ * srcTsconfig('server').includes('"rootDir": "../../src"') // true
1821
2308
  * ```
1822
2309
  */
1823
- export declare function surfaceTsconfig(surface: 'browser' | 'server'): string;
2310
+ export declare function srcTsconfig(environment: 'browser' | 'server'): string;
1824
2311
 
1825
2312
  /**
1826
- * Classify a blueprint's surfaces into the manifest/exports variant class.
2313
+ * Classify a blueprint's src into the manifest/exports variant class.
1827
2314
  *
1828
- * @param surfaces - The declared `Surface[]`.
1829
- * @returns The sole declared `Surface`, or `'multi'` when two or more are declared.
2315
+ * @param src - The declared `Environment[]`.
2316
+ * @returns The sole declared `Environment`, or `'multi'` when two or more are declared.
1830
2317
  *
1831
2318
  * @example
1832
2319
  * ```ts
1833
- * surfaceVariant(['core']) // 'core'
1834
- * surfaceVariant(['core', 'server']) // 'multi'
2320
+ * srcVariant(['core']) // 'core'
2321
+ * srcVariant(['core', 'server']) // 'multi'
1835
2322
  * ```
1836
2323
  */
1837
- export declare function surfaceVariant(surfaces: readonly Surface[]): Surface | 'multi';
2324
+ export declare function srcVariant(src: readonly Environment[]): Environment | 'multi';
1838
2325
 
1839
2326
  /**
1840
2327
  * `configs/src/vite.<browser|server>.config.ts` — a thin `dts`-only wrapper;
1841
2328
  * `build.lib` / externals live in the root `srcBrowser` / `srcServer` export
1842
2329
  * instead (per the live exemplars).
1843
2330
  *
1844
- * @param surface - The non-`core` surface to derive the `vite.config.ts` for.
1845
- * @returns The surface `vite.config.ts` file content, newline-terminated.
2331
+ * @param environment - The non-`core` environment to derive the `vite.config.ts` for.
2332
+ * @returns The environment `vite.config.ts` file content, newline-terminated.
1846
2333
  *
1847
2334
  * @example
1848
2335
  * ```ts
1849
- * surfaceViteConfig('browser').includes('srcBrowser') // true
2336
+ * srcViteConfig('browser').includes('srcBrowser') // true
1850
2337
  * ```
1851
2338
  */
1852
- export declare function surfaceViteConfig(surface: 'browser' | 'server'): string;
2339
+ export declare function srcViteConfig(environment: 'browser' | 'server'): string;
2340
+
2341
+ /**
2342
+ * Serialize a value to a canonical, key-order-INDEPENDENT JSON-like string.
2343
+ *
2344
+ * @param value - The value to stringify.
2345
+ * @remarks
2346
+ * Object keys sort code-unit; array order is preserved. So two
2347
+ * logically-equal blueprints built with their fields in a different
2348
+ * construction order still hash identically once fed through `computeHash`.
2349
+ * @returns The canonical string form of `value`.
2350
+ *
2351
+ * @example
2352
+ * ```ts
2353
+ * import { stableStringify } from '@orkestrel/scaffold'
2354
+ *
2355
+ * stableStringify({ b: 1, a: 2 }) // '{"a":2,"b":1}'
2356
+ * ```
2357
+ */
2358
+ export declare function stableStringify(value: unknown): string;
2359
+
2360
+ /** Target-aware guide baseline: an absence marker or exact SHA-256 digest. */
2361
+ export declare const SYNC_BASELINE_PATTERN: RegExp;
1853
2362
 
1854
2363
  /**
1855
2364
  * The whole outcome of a `Sync.pull`.
@@ -1882,14 +2391,15 @@ export declare function coreViteConfig(): string;
1882
2391
  name: StringShape;
1883
2392
  path: StringShape;
1884
2393
  content: StringShape;
1885
- freshness: LiteralShape<readonly ["current", "behind", "missing", "failed"]>;
2394
+ freshness: LiteralShape<readonly Freshness[]>;
1886
2395
  note: OptionalShape<StringShape>;
2396
+ baseline: OptionalShape<StringShape>;
1887
2397
  }, boolean | ContractShape>>;
1888
2398
  versions: ArrayShape<ObjectShape<{
1889
2399
  name: StringShape;
1890
2400
  range: StringShape;
1891
2401
  latest: StringShape;
1892
- freshness: LiteralShape<readonly ["current", "behind", "missing", "failed"]>;
2402
+ freshness: LiteralShape<readonly Freshness[]>;
1893
2403
  note: OptionalShape<StringShape>;
1894
2404
  }, boolean | ContractShape>>;
1895
2405
  clean: BooleanShape;
@@ -1916,7 +2426,7 @@ export declare function coreViteConfig(): string;
1916
2426
  * `template`-origin artifact `blueprintToPlan` renders.
1917
2427
  *
1918
2428
  * @remarks
1919
- * The generated-minimal stub prose/source, expressed as `{{name}}` /
2429
+ * The generated-minimal starter prose/source, expressed as `{{name}}` /
1920
2430
  * `{{pascal}}` `{{token}}` placeholders for `@orkestrel/template`'s pure
1921
2431
  * `fillTemplate` LEAF. Only genuinely templated PROSE / source artifacts live
1922
2432
  * here — the token-collision boundary (AGENTS §14, this guide's Contract
@@ -1930,10 +2440,10 @@ export declare function coreViteConfig(): string;
1930
2440
 
1931
2441
  /**
1932
2442
  * Draft the `tests` group's `template` artifacts — the shared recorder
1933
- * setup, one environment-specific setup file per non-`core` surface
2443
+ * setup, one environment-specific setup file per non-`core` environment
1934
2444
  * (`setupServer.ts` / `setupBrowser.ts`, grounded against the live
1935
2445
  * exemplars' setup-file naming), the generated-minimal entity / factory test
1936
- * stubs PER declared surface, and the surface-aware guides-parity drop-in.
2446
+ * stubs PER declared environment, and the environment-aware guides-parity drop-in.
1937
2447
  *
1938
2448
  * @param spec - The `Blueprint` to derive test stubs from.
1939
2449
  * @param pascal - The package's PascalCase entity name.
@@ -1946,21 +2456,23 @@ export declare function coreViteConfig(): string;
1946
2456
  */
1947
2457
  export declare function testArtifacts(spec: Blueprint, pascal: string): readonly Artifact[];
1948
2458
 
2459
+ /** TypeScript module extensions every generated scoped configuration checks. */
2460
+ export declare const TYPESCRIPT_EXTENSIONS: readonly string[];
2461
+
1949
2462
  /**
1950
2463
  * The semantic pass over a blueprint.
1951
2464
  *
1952
2465
  * @param spec - The blueprint to validate.
1953
2466
  * @remarks
1954
- * Checks the name against `NAME_PATTERN`, non-empty on-vocabulary `surfaces`
1955
- * with no repeats (a repeat would produce duplicate members); a single
1956
- * surface `core`-only, `server`-only, `browser`-only is a fully
1957
- * first-class declaration (`rootViteConfig` retargets the root export and
1958
- * runs the surface's own factory as the base, no `core` involved), but a
1959
- * `browser`+`server` declaration with no `core` has no defined configuration
1960
- * class `rootViteConfig` / `singleSurfaceViteConfig` can shape that ONE
1961
- * exemplar-less combination is a blocking question (without this gate it
1962
- * would silently drop a surface at `rootViteConfig`'s dispatch while the
1963
- * manifest still references it). And well-formed `dependencies` / `peers` /
2467
+ * Checks the name against `NAME_PATTERN` and `MAX_NAME_LENGTH`, requires at
2468
+ * least one selected environment across the published `src` and private `app`
2469
+ * axes, and keeps both axes on-vocabulary with no repeats (a repeat would
2470
+ * produce duplicate members). A single environment `core`-only, `server`-only, or
2471
+ * `browser`-only is first-class on either axis, but a `browser`+`server`
2472
+ * declaration with no `core` in the same axis has no defined shared
2473
+ * configuration class. That ONE exemplar-less combination is a blocking
2474
+ * question; without the gate dispatch would silently drop an environment. Also checks
2475
+ * well-formed `dependencies` / `peers` /
1964
2476
  * `extras` (non-empty name/range, no duplicate names within an array):
1965
2477
  * `dependencies` and `peers` names are shaped `DEPENDENCY_NAME_PATTERN`
1966
2478
  * (closed to `@orkestrel/*`) — a NAME-shaped law at the gate that closes the
@@ -2012,6 +2524,25 @@ export declare function coreViteConfig(): string;
2012
2524
  readonly seen: ReadonlySet<string>;
2013
2525
  };
2014
2526
 
2527
+ /**
2528
+ * Validate both a plan's blueprint semantics and every override against the
2529
+ * exact artifact set the plan would materialize.
2530
+ *
2531
+ * @param plan - The structurally valid plan to validate before mutation.
2532
+ * @returns A total validation whose blocking questions include missing,
2533
+ * host-owned, and publication-boundary override targets.
2534
+ *
2535
+ * @example
2536
+ * ```ts
2537
+ * import { blueprint, blueprintToPlan, validatePlan } from '@orkestrel/scaffold'
2538
+ *
2539
+ * const plan = blueprintToPlan(blueprint('router', { src: ['core'] }))
2540
+ *
2541
+ * validatePlan(plan).valid // true
2542
+ * ```
2543
+ */
2544
+ export declare function validatePlan(plan: Plan): Validation;
2545
+
2015
2546
  /** The semantic pass over a blueprint; returns, never throws. */
2016
2547
  export declare interface Validation {
2017
2548
  readonly valid: boolean;
@@ -2019,6 +2550,9 @@ export declare function coreViteConfig(): string;
2019
2550
  readonly warnings: readonly string[];
2020
2551
  }
2021
2552
 
2553
+ /** The exact three-component version syntax accepted by `validateBlueprint`. */
2554
+ export declare const VERSION_PATTERN: RegExp;
2555
+
2022
2556
  /**
2023
2557
  * One dependency's declared `range` against the registry `latest`, plus its
2024
2558
  * `freshness` verdict.
@@ -2036,13 +2570,14 @@ export declare function coreViteConfig(): string;
2036
2570
 
2037
2571
  /**
2038
2572
  * The rendered import / `resolve` header block every `rootViteConfig` shape
2039
- * prefixes — the Playwright import lines + `createBrowserProvider` appear
2040
- * only when `needsPlaywright`, per the three grounded `rootViteConfig`
2041
- * shapes: unconditional for a multi-surface blueprint, conditional on the
2042
- * sole surface being `'browser'` for a single non-`core` surface, absent for
2573
+ * prefixes — the official Playwright provider import appears only when
2574
+ * `needsPlaywright`, per the three grounded `rootViteConfig`
2575
+ * shapes: unconditional for a multi-environment blueprint, conditional on the
2576
+ * sole environment being `'browser'` for a single non-`core` environment, absent for
2043
2577
  * `core`-only.
2044
2578
  *
2045
2579
  * @param needsPlaywright - Whether this shape ships a browser test project (and so needs Playwright).
2580
+ * @param needsVue - Whether the generated root imports the Vue Vite plugin.
2046
2581
  * @returns The rendered header block, newline-terminated.
2047
2582
  *
2048
2583
  * @example
@@ -2051,6 +2586,6 @@ export declare function coreViteConfig(): string;
2051
2586
  * viteHeader(true).includes('@vitest/browser-playwright') // true
2052
2587
  * ```
2053
2588
  */
2054
- export declare function viteHeader(needsPlaywright: boolean): string;
2589
+ export declare function viteHeader(needsPlaywright: boolean, needsVue?: boolean): string;
2055
2590
 
2056
2591
  export { }