@orkestrel/scaffold 0.0.81 → 0.0.82

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 (35) hide show
  1. package/dist/bin/main.js +167 -13
  2. package/dist/bin/main.js.map +1 -1
  3. package/dist/host/AGENTS.md +5 -3
  4. package/dist/host/agents/skills/orkestrel-harden/references/centralization.md +2 -2
  5. package/dist/host/agents/skills/orkestrel-journey/SKILL.md +41 -38
  6. package/dist/host/agents/skills/orkestrel-journey/references/captures.md +3 -3
  7. package/dist/host/agents/skills/orkestrel-journey/references/decide.md +3 -3
  8. package/dist/host/agents/skills/orkestrel-journey/references/layer.md +5 -5
  9. package/dist/host/agents/skills/orkestrel-journey/references/statechart.md +3 -3
  10. package/dist/host/agents/skills/orkestrel-journey/references/styles.md +9 -9
  11. package/dist/host/claude/rules/application.md +20 -6
  12. package/dist/host/claude/rules/architecture.md +2 -2
  13. package/dist/host/claude/rules/browser.md +9 -0
  14. package/dist/host/claude/rules/documentation.md +2 -1
  15. package/dist/host/claude/rules/styles.md +35 -12
  16. package/dist/host/claude/rules/tests.md +15 -10
  17. package/dist/host/claude/rules/workspace.md +128 -98
  18. package/dist/host/claude/skills/orkestrel-journey/SKILL.md +1 -1
  19. package/dist/host/configs/helpers.ts +157 -9
  20. package/dist/host/configs/policy.ts +64 -61
  21. package/dist/host/dotfiles/oxlintrc.json +132 -16
  22. package/dist/host/dotfiles/prettierignore +1 -1
  23. package/dist/host/guides/README.md +9 -5
  24. package/dist/host/guides/scaffold.md +475 -115
  25. package/dist/host/manifest.json +26 -26
  26. package/dist/host/tests/config.test.ts +996 -39
  27. package/dist/host/tests/policy.test.ts +11 -0
  28. package/dist/host/tests/setupPolicy.ts +396 -22
  29. package/dist/src/core/index.cjs +1261 -159
  30. package/dist/src/core/index.cjs.map +1 -1
  31. package/dist/src/core/index.d.cts +297 -35
  32. package/dist/src/core/index.d.ts +297 -35
  33. package/dist/src/core/index.js +1241 -160
  34. package/dist/src/core/index.js.map +1 -1
  35. package/package.json +1 -1
@@ -31,7 +31,8 @@ data root states how each set is staged and how a pointer resolves.
31
31
 
32
32
  Every following code fence is illustrative. [`tests/guides.test.ts`](../tests/guides.test.ts)
33
33
  keeps the command reference aligned with the executable and transcribes the pure blueprint-default,
34
- compile-refusal, and error-narrowing fences. A trailing comment in another fence is this guide's
34
+ compile-refusal, error-narrowing, extension-parsing, and export-map fences. A trailing comment in
35
+ another fence is this guide's
35
36
  claim rather than a measured answer; the driven examples are the ones the shipped declarations
36
37
  print. Limits states what that leaves unproven and what covers it instead.
37
38
 
@@ -57,6 +58,7 @@ Exported from `@orkestrel/scaffold`, and reachable from
57
58
  | Name | Kind | Summary |
58
59
  | ------------------- | ---- | ----------------------------------------------------------------------------------------------------------- |
59
60
  | `Artifact` | type | Represents one file in a plan, discriminated by how its content is produced and what scaffold claims of it. |
61
+ | `Axis` | type | Names the workspace axis an extension occupies. |
60
62
  | `BuildFormat` | type | Names one module format a published library environment builds. |
61
63
  | `CatalogEntry` | type | Represents one package row of the fleet catalog. |
62
64
  | `CompileStage` | type | Names the compile phases, in the order they run. |
@@ -64,7 +66,9 @@ Exported from `@orkestrel/scaffold`, and reachable from
64
66
  | `HostFile` | type | Represents one vendored file read from the repository, beside the target bytes it answers for. |
65
67
  | `Drift` | type | Names how one target path compares to the artifact planned for it. |
66
68
  | `Environment` | type | Names one environment a generated workspace selects on its `src` or `app` axis. |
69
+ | `Extension` | type | Represents an extension discriminated by its surface. |
67
70
  | `Finding` | type | Represents one drift verdict against a target path. |
71
+ | `Framework` | type | Names a supported browser framework. |
68
72
  | `Group` | type | Names the artifact group a plan selects over. |
69
73
  | `Lookup` | type | Names how an upstream lookup resolved: found, missing, unmatched, or failed. |
70
74
  | `Mirror` | type | Represents one dependency guide fetched from upstream, beside the local mirror it answers for. |
@@ -74,6 +78,7 @@ Exported from `@orkestrel/scaffold`, and reachable from
74
78
  | `ScaffoldErrorCode` | type | Names the coded reasons a scaffold error is raised. |
75
79
  | `SetupRuntime` | type | Names the runtime a root setup proof requires. |
76
80
  | `Snapshot` | type | Holds exact lowercase hexadecimal target bytes keyed by artifact-relative path. |
81
+ | `Surface` | type | Names the surface an extension extends. |
77
82
 
78
83
  #### Interfaces
79
84
 
@@ -83,6 +88,7 @@ Exported from `@orkestrel/scaffold`, and reachable from
83
88
  | `ArtifactBase` | interface | Describes the fields every planned file carries. |
84
89
  | `Audit` | interface | Represents the whole comparison of a plan against a target's current content. |
85
90
  | `Blueprint` | interface | Represents the closed, JSON-serializable workspace specification. |
91
+ | `BrowserExtension` | interface | Represents a browser framework and its physically occupied axes. |
86
92
  | `CompileFailure` | interface | Represents the coded reason one compile stage failed. |
87
93
  | `CompileRecord` | interface | Holds the input and output snapshot of one compile stage. |
88
94
  | `CompilerInterface` | interface | Describes the compilation contract: pure, synchronous, and host-independent. |
@@ -90,6 +96,7 @@ Exported from `@orkestrel/scaffold`, and reachable from
90
96
  | `ContentArtifact` | interface | Represents a text file produced by the template or computed compilation path. |
91
97
  | `Dependency` | interface | Represents one runtime `@orkestrel/*` dependency of a generated workspace. |
92
98
  | `DependencyPinSet` | interface | Describes the runtime and development sections a range-writing operation may change. |
99
+ | `FrameworkDefinition` | interface | Describes the tooling and package boundaries a browser framework contributes. |
93
100
  | `HostArtifact` | interface | Represents a file byte-copied from the vendored data root, planned before its bytes are read. |
94
101
  | `HydratedArtifact` | interface | Represents a vendored file whose exact bytes have been read, so its content can be compared. |
95
102
  | `ManifestDependencySet` | interface | Describes the runtime, development, and peer sections read from an existing package manifest. |
@@ -101,17 +108,19 @@ Exported from `@orkestrel/scaffold`, and reachable from
101
108
  | `Question` | interface | Represents one validation issue raised against a blueprint or a plan. |
102
109
  | `Scaffolding` | interface | Represents the replayable outcome of one compile. |
103
110
  | `SrcDefinition` | interface | Describes the build and export settings one published `src` environment contributes. |
111
+ | `StylesExtension` | interface | Represents a named sheet face under `src/<name>`. |
104
112
  | `ViteMachinery` | interface | Names which host-specific pipelines a generated root Vite configuration carries. |
105
113
 
106
114
  #### Constants
107
115
 
108
116
  | Name | Kind | Summary |
109
117
  | --------------------------------- | ----- | ------------------------------------------------------------------------------------------------------ |
110
- | `APP_BROWSER_DEV_DEPENDENCIES` | const | Lists the development dependencies a private Vue browser application adds. |
118
+ | `APP_BROWSER_DEV_DEPENDENCIES` | const | Lists the development dependencies a private browser application adds. |
111
119
  | `APP_DEV_DEPENDENCIES` | const | Names the development dependency every private `app` environment adds. |
112
120
  | `APP_MATRIX` | const | Holds the configuration and runtime-entry settings each private `app` environment contributes, frozen. |
113
121
  | `APP_SERVER_DEV_DEPENDENCIES` | const | Lists the development dependencies a private server application adds. |
114
122
  | `ARTIFACT_TEMPLATES` | const | Holds formatter-stable template text for source, test, document, guide, and service artifacts. |
123
+ | `AXES` | const | Lists the axes a browser extension may occupy, frozen. |
115
124
  | `BASE_DEV_DEPENDENCIES` | const | Holds the tooling versions scaffold and every generated workspace share. |
116
125
  | `BIN_CONFIGS` | const | Lists the configuration files a workspace that ships its own executable adds, frozen. |
117
126
  | `BIN_ENTRY_PATH` | const | Names the executable entry whose presence makes a workspace `bin`. |
@@ -133,6 +142,8 @@ Exported from `@orkestrel/scaffold`, and reachable from
133
142
  | `EXTRA_RANGE_PATTERN` | const | Matches the registry-only semver subset accepted for a development extra's range. |
134
143
  | `FLOOR_RANGE_PATTERN` | const | Matches the exact `major.minor.patch` floor accepted for a foreign peer's range. |
135
144
  | `FOREIGN_NAME_PATTERN` | const | Matches the package name syntax for a dependency this package does not publish. |
145
+ | `FRAMEWORKS` | const | Lists the supported browser frameworks, frozen. |
146
+ | `FRAMEWORK_MATRIX` | const | Describes the tooling and package boundaries of each browser framework, frozen. |
136
147
  | `GLOBAL_SETUP_PATH` | const | Names the shared Vitest global-setup module whose presence makes a workspace `global`. |
137
148
  | `GROUPS` | const | Lists the `Group` values in plan order, frozen. |
138
149
  | `GUIDES_TEST_PATH` | const | Names the package-owned guide-parity entry used by `test:guides` and to select the `guides` project. |
@@ -165,57 +176,71 @@ Exported from `@orkestrel/scaffold`, and reachable from
165
176
  | `PRINT_WIDTH` | const | Caps the columns one emitted line may occupy, matching `printWidth` in `.oxfmtrc.json`. |
166
177
  | `REFERENCE_PATHS` | const | Lists the reference paths staged for offline reading, frozen. |
167
178
  | `RELEASE_PROOF_COMMAND` | const | Names the `prepublishOnly` row that runs the packed-package proof against a real registry. |
179
+ | `RESERVED_SHEET_NAMES` | const | Lists the names a styles extension cannot occupy, frozen. |
168
180
  | `SEED_GUIDE_PATHS` | const | Lists the guide paths a generated workspace starts with, frozen. |
169
181
  | `SERVICE_SCRIPT_PATH` | const | Names the inventory skeleton a workspace with declared service vendors is given once. |
170
182
  | `SERVICE_SETUP_PATH` | const | Names the live-service readiness module whose presence makes a workspace `service`. |
171
183
  | `SERVICE_TEST_INCLUDE` | const | Names the include the live-service project covers, which is a directory rather than one proof. |
184
+ | `SHEET_ENTRY_NAME` | const | Names the build entry beside each stylesheet marker. |
172
185
  | `SHOWCASE_CONFIG_PATH` | const | Names the Vite wrapper whose presence makes a workspace `showcase`. |
173
186
  | `SHOWCASE_DEV_DEPENDENCIES` | const | Names the development dependency used only by the optional single-file showcase build. |
187
+ | `SHOWCASE_PAGES_PATH` | const | Names the physical showcase output directory. |
174
188
  | `SKILLS_CONFIG_PATH` | const | Names the TypeScript wrapper whose presence makes a workspace `skills`. |
175
189
  | `SOURCE_BROWSER_DEV_DEPENDENCIES` | const | Lists the development dependencies a published browser `src` environment adds. |
176
190
  | `SRC_MATRIX` | const | Holds the build and export settings each published `src` environment contributes, frozen. |
191
+ | `STYLES_DEV_DEPENDENCIES` | const | Lists the development dependencies the styles surface adds, frozen. |
192
+ | `STYLES_ENTRY_PATH` | const | Names the base stylesheet marker. |
193
+ | `SURFACES` | const | Lists the surfaces an extension may extend, frozen. |
177
194
  | `TAB_WIDTH` | const | Sets the columns one tab occupies when the formatter measures a line, matching `tabWidth`. |
178
195
  | `TARGET_SKILL_NAMES` | const | Lists the package-facing skills a target receives pointers for, frozen and alphabetical. |
196
+ | `THEMES_BARREL_PATH` | const | Names the themes stylesheet marker. |
197
+ | `THEMES_ENTRY_PATH` | const | Names the themes build entry marker. |
179
198
  | `VERSION_PATTERN` | const | Matches the exact `major.minor.patch` version syntax a blueprint declares. |
180
199
  | `WORKSPACE_DEV_ENGINES` | const | Holds the `devEngines` record every generated manifest carries. |
181
200
  | `WORKSPACE_OWNED_PATHS` | const | Lists the vendored paths whose present bytes belong to each workspace, frozen. |
182
201
 
183
202
  #### Guards
184
203
 
185
- | Name | Kind | Summary |
186
- | ------------------- | -------- | --------------------------------------------------------------------------------- |
187
- | `isArtifact` | const | Narrows a value to an `Artifact`. |
188
- | `isAudit` | const | Narrows a value to an `Audit`. |
189
- | `isBlueprint` | const | Narrows a value to a `Blueprint`. |
190
- | `isCatalogEntry` | const | Narrows a value to a `CatalogEntry`. |
191
- | `isCollection` | function | Narrows a value to an array within the limit one public collection accepts. |
192
- | `isCompilerHooks` | const | Narrows a value to the compiler's initial listener record. |
193
- | `isCompilerOptions` | const | Narrows a value to `CompilerOptions`. |
194
- | `isContent` | const | Narrows a value to text this package will accept as one artifact's content. |
195
- | `isDependency` | const | Narrows a value to a `Dependency`. |
196
- | `isDependencyName` | const | Narrows a value to the scoped package name a runtime dependency carries. |
197
- | `isEnvironment` | const | Narrows a value to one `Environment` a workspace may select. |
198
- | `isFinding` | const | Narrows a value to a `Finding`. |
199
- | `isGroup` | const | Narrows a value to one `Group` a plan selects over. |
200
- | `isGroups` | const | Narrows a value to a bounded group selection. |
201
- | `isHex` | const | Narrows a value to exact lowercase hexadecimal bytes within one artifact's limit. |
202
- | `isManifestScript` | const | Narrows a value to a `ManifestScript`. |
203
- | `isMirror` | const | Narrows a value to a `Mirror`. |
204
- | `isOverride` | const | Narrows a value to an `Override`. |
205
- | `isPath` | function | Narrows a value to a logical target-relative path. |
206
- | `isPlan` | const | Narrows a value to a `Plan`. |
207
- | `isQuestion` | const | Narrows a value to a `Question`. |
208
- | `isScaffoldError` | function | Narrows a caught value to a `ScaffoldError`. |
209
- | `isSnapshot` | function | Narrows a value to a `Snapshot`. |
204
+ | Name | Kind | Summary |
205
+ | -------------------- | -------- | --------------------------------------------------------------------------------- |
206
+ | `isArtifact` | const | Narrows a value to an `Artifact`. |
207
+ | `isAudit` | const | Narrows a value to an `Audit`. |
208
+ | `isBlueprint` | const | Narrows a value to a `Blueprint`. |
209
+ | `isBrowserExtension` | const | Narrows a value to a supported browser framework with distinct occupied axes. |
210
+ | `isCatalogEntry` | const | Narrows a value to a `CatalogEntry`. |
211
+ | `isCollection` | function | Narrows a value to an array within the limit one public collection accepts. |
212
+ | `isCompilerHooks` | const | Narrows a value to the compiler's initial listener record. |
213
+ | `isCompilerOptions` | const | Narrows a value to `CompilerOptions`. |
214
+ | `isContent` | const | Narrows a value to text this package will accept as one artifact's content. |
215
+ | `isDependency` | const | Narrows a value to a `Dependency`. |
216
+ | `isDependencyName` | const | Narrows a value to the scoped package name a runtime dependency carries. |
217
+ | `isEnvironment` | const | Narrows a value to one `Environment` a workspace may select. |
218
+ | `isExtension` | const | Narrows a value to an extension of a supported surface. |
219
+ | `isFinding` | const | Narrows a value to a `Finding`. |
220
+ | `isGroup` | const | Narrows a value to one `Group` a plan selects over. |
221
+ | `isGroups` | const | Narrows a value to a bounded group selection. |
222
+ | `isHex` | const | Narrows a value to exact lowercase hexadecimal bytes within one artifact's limit. |
223
+ | `isManifestScript` | const | Narrows a value to a `ManifestScript`. |
224
+ | `isMirror` | const | Narrows a value to a `Mirror`. |
225
+ | `isOverride` | const | Narrows a value to an `Override`. |
226
+ | `isPath` | function | Narrows a value to a logical target-relative path. |
227
+ | `isPlan` | const | Narrows a value to a `Plan`. |
228
+ | `isQuestion` | const | Narrows a value to a `Question`. |
229
+ | `isScaffoldError` | function | Narrows a caught value to a `ScaffoldError`. |
230
+ | `isSheetName` | function | Narrows a value to a non-reserved sheet face name. |
231
+ | `isSnapshot` | function | Narrows a value to a `Snapshot`. |
232
+ | `isStylesExtension` | const | Narrows a value to a named non-reserved stylesheet face. |
233
+ | `isSurface` | const | Narrows a value to a surface an extension can extend. |
210
234
 
211
235
  #### Parsers
212
236
 
213
- | Name | Kind | Summary |
214
- | ---------------------- | -------- | ------------------------------------------------ |
215
- | `parseBlueprint` | function | Coerces an untrusted value to a `Blueprint`. |
216
- | `parseCompilerOptions` | function | Coerces an untrusted value to `CompilerOptions`. |
217
- | `parseGroups` | function | Coerces an untrusted value to a group selection. |
218
- | `parseSnapshot` | function | Coerces an untrusted value to a `Snapshot`. |
237
+ | Name | Kind | Summary |
238
+ | ---------------------- | -------- | --------------------------------------------------------------------------- |
239
+ | `parseBlueprint` | function | Coerces an untrusted value to a `Blueprint`. |
240
+ | `parseCompilerOptions` | function | Coerces an untrusted value to `CompilerOptions`. |
241
+ | `parseExtension` | function | Coerces an extension value or a `surface:name` selection into an extension. |
242
+ | `parseGroups` | function | Coerces an untrusted value to a group selection. |
243
+ | `parseSnapshot` | function | Coerces an untrusted value to a `Snapshot`. |
219
244
 
220
245
  #### Helpers
221
246
 
@@ -262,6 +287,8 @@ Exported from `@orkestrel/scaffold`, and reachable from
262
287
  | `blueprintToConfigArtifacts` | function | Compiles every artifact in the `configs` group. |
263
288
  | `blueprintToDevDependencies` | function | Projects a blueprint into the development dependencies its manifest declares. |
264
289
  | `blueprintToDocumentArtifacts` | function | Compiles the generated workspace's root documentation. |
290
+ | `blueprintToExports` | function | Projects published environments and sheets into the manifest export map. |
291
+ | `blueprintToFaces` | function | Projects a blueprint into browser extensions restricted to occupied browser axes. |
265
292
  | `blueprintToGuideArtifacts` | function | Compiles the generated workspace's guide index. |
266
293
  | `blueprintToHostArtifacts` | function | Compiles the vendored host artifacts a workspace plans. |
267
294
  | `blueprintToMachinery` | function | Derives the host-specific machinery a generated root Vite configuration carries. |
@@ -269,8 +296,10 @@ Exported from `@orkestrel/scaffold`, and reachable from
269
296
  | `blueprintToOrchestrationArtifacts` | function | Compiles the blueprint-dependent orchestration artifacts. |
270
297
  | `blueprintToQuestions` | function | Measures a blueprint against every law its own fields decide. |
271
298
  | `blueprintToRootTsconfig` | function | Compiles the root TypeScript configuration for a blueprint. |
299
+ | `blueprintToProjects` | function | Projects a blueprint into the project labels its root Vitest configuration registers. |
272
300
  | `blueprintToRootVite` | function | Compiles the root Vite and Vitest configuration for a blueprint. |
273
301
  | `blueprintToScripts` | function | Projects a blueprint into the scripts its manifest declares. |
302
+ | `blueprintToSheets` | function | Projects a blueprint into its validated sheet-face names in stable order. |
274
303
  | `blueprintToSourceArtifacts` | function | Compiles every artifact in the `source` group. |
275
304
  | `blueprintToTestArtifacts` | function | Compiles every artifact in the `tests` group that is not vendored from the host. |
276
305
  | `blueprintToWritableScripts` | function | Projects a blueprint into the manifest scripts a region write may replace. |
@@ -549,7 +578,7 @@ a local path.
549
578
  ```text
550
579
  scaffold <verb> [options]
551
580
 
552
- scaffold new <name> [--src <list>] [--app <list>] [--bin] [--deps <list>] [--offline] [--from <path>] [--target <path>] [--json]
581
+ scaffold new <name> [--src <list>] [--app <list>] [--bin] [--styles] [--themes] [--showcase] [--extend <list>] [--deps <list>] [--offline] [--from <path>] [--target <path>] [--json]
553
582
  scaffold a workspace
554
583
  scaffold audit [--groups <list>] [--offline] [--from <path>] [--target <path>] [--json]
555
584
  report how the target compares to its plan, writing nothing
@@ -564,6 +593,10 @@ options
564
593
  --src <list> the published library environments to build: core, browser, server
565
594
  --app <list> the private application environments to build: core, browser, server
566
595
  --bin scaffold a command-line executable at src/bin/main.ts
596
+ --styles select the base styles surface
597
+ --themes select themes; requires --styles
598
+ --showcase select the showcase; requires --app browser
599
+ --extend <list> select surface:name extensions on the selected surfaces
567
600
  --deps <list> the @orkestrel/* packages the workspace depends on
568
601
  --groups <list> the artifact groups to cover; every group when absent
569
602
  --all fetch a guide for every package the organization publishes, not the declared ones alone
@@ -599,35 +632,37 @@ answers a read and grant no verb write authority that it did not already have.
599
632
  `new --app browser` command selects the journey axis, creates its birth-owned wrapper, defines
600
633
  `appJourney` in the root configuration, and excludes the browser integration suite from
601
634
  `app:browser`. Its manifest declares `test:journey` and invokes it after `npm run test:app` in
602
- `test`. A selection without a browser application emits no journey axis. Creation leaves `setup`
603
- empty. The other structural facts do not need creation flags. Add a root `tests/setup*.test.ts` proof for
604
- `setup`, `tests/guides.test.ts` for `guides`, `tests/integration.test.ts` for `integration`,
635
+ `test`. A selection without a browser application emits no journey axis. `--styles`, `--themes`,
636
+ `--showcase`, and `--extend` select the structural facts and the extensions, and Surfaces and extensions
637
+ states what each emits and what each refuses. Creation leaves `setup` empty, and the remaining
638
+ structural facts take no creation option. Add a root `tests/setup*.test.ts` proof for `setup`,
639
+ `tests/guides.test.ts` for `guides`, `tests/integration.test.ts` for `integration`,
605
640
  `tests/conformance.test.ts` for `conformance`, `tests/setupService.ts` for `service`,
606
- `tests/setupGlobal.ts` for `global`, `configs/app/vite.showcase.config.ts` for `showcase`,
607
- `configs/app/vite.journey.config.ts` for `journey`, and `configs/agents/tsconfig.skills.json` for
608
- `skills`;
609
- reading verbs detect each exact-case file and register its fixed machinery. An explicitly supplied
641
+ `tests/setupGlobal.ts` for `global`, `configs/app/vite.journey.config.ts` for `journey`, and
642
+ `configs/agents/tsconfig.skills.json` for `skills`; reading verbs detect each exact-case file and
643
+ register its fixed machinery. An explicitly supplied
610
644
  plan with `vendors` owns and protects the birth-owned `scripts/service.sh` inventory skeleton.
611
645
  Reading verbs do not infer its vendor list from edited text and cannot preserve an arbitrary present
612
646
  script on that basis.
613
647
 
614
- `distribution` is not on that list. Publishing at least one `src` environment is its whole
615
- condition, and scaffold writes `tests/distribution.test.ts` itself rather than waiting for you to.
616
- Limits states what makes that one proof generable when the others are not.
648
+ `distribution` is not on that list. Publishing at least one `src` environment or one sheet face is
649
+ its whole condition, and scaffold writes `tests/distribution.test.ts` itself rather than waiting for
650
+ you to. Limits states what makes that one proof generable when the others are not.
617
651
 
618
652
  ### Reading a target
619
653
 
620
654
  `audit`, `repair`, `catalog`, and `overwrite` derive the blueprint from the target itself. The name
621
655
  and the declared `@orkestrel/*` packages come from `package.json`. The environment axes come from
622
656
  the directories the target actually ships, because a directory is the fact and a declaration beside
623
- it could disagree. The remaining facts come from exact-case files: `src/bin/main.ts` selects `bin`,
624
- each root `tests/setup*.test.ts` match selects `setup`, `tests/guides.test.ts` selects `guides`,
625
- `tests/integration.test.ts` selects `integration`, `tests/conformance.test.ts` selects
626
- `conformance`, `tests/setupService.ts` selects `service`, `tests/setupGlobal.ts` selects `global`,
627
- `configs/app/vite.showcase.config.ts` selects `showcase`, `configs/app/vite.journey.config.ts`
628
- selects `journey`, and `configs/agents/tsconfig.skills.json` selects `skills`. A containing
629
- directory does not select the fact by itself. `tests/distribution.test.ts` selects nothing: the
630
- published `src` axis the target ships already decides the `distribution` project, and the file is
657
+ it could disagree. The styles surface, its themes target, the showcase, and every extension are
658
+ read from the markers Surfaces and extensions lists. The remaining facts come from exact-case
659
+ files: `src/bin/main.ts` selects `bin`, each root `tests/setup*.test.ts` match selects `setup`,
660
+ `tests/guides.test.ts` selects `guides`, `tests/integration.test.ts` selects `integration`,
661
+ `tests/conformance.test.ts` selects `conformance`, `tests/setupService.ts` selects `service`,
662
+ `tests/setupGlobal.ts` selects `global`, `configs/app/vite.journey.config.ts` selects `journey`,
663
+ and `configs/agents/tsconfig.skills.json` selects `skills`. A containing directory does not select
664
+ any of those facts by itself. `tests/distribution.test.ts` selects nothing: the published `src`
665
+ axis and the sheet faces the target ships already decide the `distribution` project, and the file is
631
666
  planned from that.
632
667
 
633
668
  `vendors` is not reconstructed. Its artifact, `scripts/service.sh`, is a birth-owned inventory
@@ -704,11 +739,19 @@ manifest and planned `vite.config.ts` conflict, and the option to exclude `confi
704
739
  A selection that excludes `configs` proceeds. An advisory alone does not make an aligned target
705
740
  drift.
706
741
 
742
+ A gate chain also reaches a sheet or framework face through `vitest run --config <wrapper>` when
743
+ the wrapper path belongs to that face in the planned configuration; a build invocation does not.
744
+
707
745
  Scaffold writes one part of the manifest rather than advising on it: the writable script region.
708
746
  `repair` and `overwrite` write every direct `test:<project>` script the blueprint computes,
709
747
  `test:probe`, and `test:bench`. A publishing workspace also receives `test:distribution`, `prepack`,
710
- and `prepublishOnly`. The `test` chain joins the region only as a generated predecessor: when it
711
- runs fewer steps than the planned chain and every step it runs is a planned step in the planned
748
+ and `prepublishOnly`. Each sheet face adds its `check:src:<face>` and `build:src:<face>` scripts.
749
+ Each occupied framework face adds `check:<axis>:vue` and `build:<axis>:vue`; the application face also adds `dev:vue`.
750
+ Selected showcase pages add `showcase`, `showcase:<framework>`, `build:showcase`, and `build:showcase:<framework>`; application journeys add `test:journey:<framework>`.
751
+ Its `test:src:<face>` script accepts, as its generated predecessor, the command that ran the project
752
+ without building the face first, and `build:src:styles` accepts the styles-only build as the
753
+ predecessor of the chain that builds themes after it. The `test` chain joins the region only as a
754
+ generated predecessor: when it runs fewer steps than the planned chain and every step it runs is a planned step in the planned
712
755
  order, `repair` and `overwrite` write the planned chain in its place. That write lands only when
713
756
  every step the planned chain adds runs a script the manifest declares or the region writes. The
714
757
  `test:src` and `test:app` aggregates sit outside the region, so a chain whose planned form adds an
@@ -716,7 +759,7 @@ aggregate the manifest lacks stays with the package, and the `projects` question
716
759
  `audit` reports this chain write only through the `projects` question, so a planned step that
717
760
  registers no Vitest project, such as `npm run test:guides`, lands on the next `repair` without an
718
761
  earlier advisory. A `test` chain running any other step or order stays maintainer-owned, as do the
719
- `check`, `build`, `dev`, `serve`, `show`, `format`, `lint`, `clean`, and `copy` gate chains. A
762
+ `check`, `build`, `dev`, `serve`, `format`, `lint`, `clean`, and `copy` gate chains. A
720
763
  declared value is overwritten only when it is already the value being written or is a recognized
721
764
  generated predecessor. The overwrite happens in place,
722
765
  so every byte outside the replaced ranges survives. A target's descriptions, keywords, extra
@@ -759,27 +802,32 @@ birth-owned, and the range and script regions are the only parts of it a verb re
759
802
 
760
803
  `audit` reports a further non-blocking question, on the `setup` field.
761
804
 
762
- The `setup` question fires when the target carries a filled root `tests/setup*.ts` module that is
805
+ The `setup` question fires when the target carries a filled, exporting root `tests/setup*.ts` module that is
763
806
  neither a proof itself nor one of the vendored modules every target receives, while no proof of the
764
807
  same stem covers it. A module counts as filled when its text differs from the seed this blueprint
765
808
  plans at that same path.
809
+ The export check matches a line beginning with `export `, as the policy sweep does; a hook-only
810
+ or augmentation-only module with no such line raises no question.
766
811
 
767
812
  The comparison reads the module and the seed trimmed, so surrounding whitespace decides nothing: a
768
813
  trailing newline is not authorship, and a module holding whitespace alone reads as empty rather than
769
814
  as filled. It is seed-relative rather than a test for emptiness, because the seeds differ by path:
770
- `tests/setup.ts` is seeded with the empty string and `tests/setupGlobal.ts` is seeded with a `setup`
771
- function body. A test for emptiness therefore raises the question against a freshly materialized
815
+ `tests/setup.ts` is seeded with the empty string, `tests/setupGlobal.ts` with a `setup` function
816
+ body, and a journey workspace's `tests/setupBrowser.ts` with a type augmentation and no sibling
817
+ proof. A test for emptiness therefore raises the question against a freshly materialized journey
772
818
  workspace. Holding each module to the seed the same blueprint plans at its own path reports what a
773
819
  maintainer wrote rather than what scaffold seeded.
774
820
 
775
821
  That reading carries a release-skew limit. A seeded setup module is birth-owned, so `repair` reports
776
822
  it aligned and never rewrites it. A target keeps the seed of the release that materialized it. When
777
- a release moves a planned seed, scaffold raises the question on every target materialized before it,
823
+ a release moves a planned seed, scaffold raises the question on an exporting module retained from that release,
778
824
  against a module scaffold wrote and no maintainer touched. `audit` compares each setup module only
779
- with the seed the installed release plans, and it retains no earlier seed bytes.
780
- `tests/setupGlobal.ts` is the module that can meet it, because it is the one seeded with more than
781
- the empty string. A maintainer meeting that question closes it by writing the proof it asks for, or
782
- by taking the seed the installed release plans.
825
+ with the seed the installed release plans, and it retains no earlier seed bytes. The limit reaches an
826
+ exporting module seeded with more than the empty string that no proof covers. Scaffold seeds
827
+ `tests/setupGlobal.test.ts` beside `tests/setupGlobal.ts` and `tests/setupStyles.test.ts` beside
828
+ `tests/setupStyles.ts`, so an exporting seeded module whose proof was deleted meets it.
829
+ A maintainer meeting that question closes it by writing the
830
+ proof it asks for, or by taking the seed the installed release plans.
783
831
 
784
832
  Coverage is read per module: `tests/<name>.ts` is covered by `tests/<name>.test.ts` and by nothing
785
833
  else, which is the pairing the vendored policy proof resolves. Writing one proof retires that module
@@ -788,7 +836,7 @@ proof that module wants. The question belongs to the `tests` group, so a scoped
788
836
  `tests` omits it. Scaffold does not write the proof it asks for, and the question never refuses a
789
837
  write: a writing verb reports it in the terminal audit it prints, because refusing `repair` over a
790
838
  gap no write can close would block every write. Run across a fleet, the question is the list of
791
- packages carrying a filled setup module that no proof covers.
839
+ packages carrying a filled, exporting setup module that no proof covers.
792
840
 
793
841
  `audit` reads the instruction canon as findings rather than as a question. Each `CANON_PATHS` member
794
842
  the target holds enters the comparison, by file where the member is a directory, and a path the plan
@@ -929,31 +977,36 @@ because the shape is chosen once and read afterwards: `new` refuses the advisory
929
977
  `repair` need the plan to describe and restore a target that already has that shape. A library
930
978
  caller creating a workspace holds the same refusal, and the Compile section states it.
931
979
 
932
- `bin`, `setup`, `guides`, `integration`, `conformance`, `service`, `vendors`, `global`, `showcase`,
933
- `journey`, and `skills` are structural facts. Reading verbs set each only when the workspace physically ships the directory
934
- or exact-case file that defines it, never because of the workspace's name and never because a
935
- sibling fact is set.
980
+ `bin`, `setup`, `guides`, `integration`, `conformance`, `service`, `vendors`, `global`, `styles`,
981
+ `themes`, `showcase`, `journey`, and `skills` are structural facts, and `extensions` lists the
982
+ extension faces. Reading verbs set each fact and list each extension only when the workspace
983
+ physically ships the directory or exact-case file that defines it, never because of the workspace's
984
+ name and never because a sibling fact is set.
936
985
 
937
986
  The `setup` member is a `readonly SetupRuntime[]`, empty by default. Target inference adds
938
- `browser` for the exact-case `tests/setupBrowser.test.ts` proof and `node` for every other root
939
- `tests/setup*.test.ts` match, including `tests/setup.test.ts` and `tests/setupServer.test.ts`.
940
- A nested or wrong-case match adds no runtime.
987
+ `browser` for the exact-case `tests/setupBrowser.test.ts` and `tests/setupStyles.test.ts` proofs and
988
+ `node` for every other root `tests/setup*.test.ts` match, including `tests/setup.test.ts` and
989
+ `tests/setupServer.test.ts`. A nested or wrong-case match adds no runtime.
941
990
 
942
991
  The `node` runtime registers the Node `setup` project, which loads `tests/setup.ts` and excludes
943
- `tests/setupBrowser.test.ts`. The `browser` runtime registers `setup:browser`, which collects
944
- only that browser proof and loads `tests/setup.ts` and `tests/setupBrowser.ts` through Playwright
945
- Chromium. The generated manifest emits the selected `test:setup` and `test:setup:browser` scripts
946
- and invokes them from `test`. Scaffold generates no setup proof for an empty setup seed.
992
+ both browser proofs. The `browser` runtime registers `setup:browser`, which collects only the two
993
+ browser proofs and loads `tests/setup.ts` and `tests/setupBrowser.ts` through Playwright Chromium. A
994
+ sheet face registers `setup:browser` as well, because scaffold plans `tests/setupStyles.test.ts`
995
+ beside every sheet face. The generated manifest emits the selected `test:setup` and
996
+ `test:setup:browser` scripts and invokes them from `test`. Scaffold generates no setup proof for an
997
+ empty setup seed.
947
998
 
948
999
  A `global` workspace gives `setup:browser` the `tests/setupGlobal.ts` module as its Vitest global
949
1000
  setup, as it gives `src:browser` and `integration`. A browser proof cannot start a Node fixture from
950
1001
  inside the browser, so it reads what that module provides through the Vitest `inject` function.
951
1002
  The Node `setup` project takes no global setup.
952
1003
 
953
- When the `app` axis selects `browser`, the browser setup project also applies the Vue
954
- single-file-component transform. Your `tests/setupBrowser.ts` module and its paired proof can
955
- import and render application Vue components. A browser setup proof without `app/browser` keeps
956
- the non-Vue pipeline; selecting `src/browser` alone adds no Vue plugin or dependency.
1004
+ The browser setup project applies the Vue single-file-component transform only when the workspace
1005
+ carries the `vue` browser extension on an axis whose selection includes `browser`, and then adds
1006
+ `vue` to its `optimizeDeps.include`, so your `tests/setupBrowser.ts` module and its paired proof
1007
+ can import and render the extension's components. A browser application without that
1008
+ extension keeps the non-Vue pipeline, and a `src/browser` selection adds no Vue plugin or
1009
+ dependency.
957
1010
 
958
1011
  A structural fact is read when a verb runs, not when the file appears. Writing
959
1012
  `tests/integration.test.ts` into a workspace sets the fact, but the root configuration on disk was
@@ -971,8 +1024,9 @@ direct script, regenerates the root configuration, and registers the project. Ov
971
1024
  predecessor `test` chain, write the file and run `repair`. `audit` reports whichever piece is still
972
1025
  outstanding at each step.
973
1026
 
974
- `distribution` is not a field at all. A published `src` environment is its whole condition, read
975
- from the `src` axis the blueprint already carries. The proof packs and installs the published
1027
+ `distribution` is not a field at all. A published `src` environment or a sheet face is its whole
1028
+ condition, read from the `src` axis and the styles surface the blueprint already carries. The proof
1029
+ packs and installs the published
976
1030
  artifact, so a workspace publishing none has nothing for it to read and gets no project, no
977
1031
  `test:distribution` script, and no gate entry. A workspace publishing any gets the project, the
978
1032
  script, the `prepublishOnly` entry, and `tests/distribution.test.ts` itself. Limits states why this
@@ -1003,9 +1057,9 @@ that field so the caller who set it learns it emitted nothing.
1003
1057
  The library's `journey` flag defaults to `false`; `new` sets it when its `app` selection includes
1004
1058
  `browser`. Reading verbs infer it from the wrapper's presence. The flag requires a browser application. Without that
1005
1059
  application, it emits no journey configuration or script and raises a non-blocking `journey`
1006
- question. With that application, the content-owned root configuration defines
1007
- `appJourney(variant, variants)` and excludes `tests/app/browser/integration.test.ts` from the
1008
- ordinary `app:browser` project.
1060
+ question. With that application, the content-owned root configuration defines the `appJourney`
1061
+ factory and excludes `tests/app/browser/integration.test.ts` from the ordinary `app:browser`
1062
+ project. Surfaces and extensions states the journey of each further application mode.
1009
1063
 
1010
1064
  Edit the variant list in `configs/app/vite.journey.config.ts`. This wrapper is birth-owned:
1011
1065
  scaffold creates it when absent and preserves your edits during `repair`. It imports
@@ -1014,7 +1068,8 @@ at 1280 × 800 and `compact` at 390 × 844 without a theme. Rename and extend th
1014
1068
  your application; apply themes through the application's interface in your tests.
1015
1069
 
1016
1070
  The wrapper registers `journey:<name>` for each variant through the root factory. Each project
1017
- collects the browser integration suite alone, sets the variant viewport, and provides `variant`
1071
+ collects the integration suite of the application the Vite mode selects, sets the variant
1072
+ viewport, and provides `variant`
1018
1073
  as its name, `variants` as the declared list, and `capture` as a boolean. The root configuration
1019
1074
  reads `process.env.CAPTURE === '1'` for that boolean. The generated `test:journey` script runs
1020
1075
  `vitest run --config configs/app/vite.journey.config.ts --no-cache --reporter=dot`, and the generated
@@ -1028,6 +1083,276 @@ block states the condition that reopens engine selection, and is that condition'
1028
1083
  axis combination one this package can generate are the gate's laws, and the gate answers them with
1029
1084
  questions. A blueprint the gate will refuse is still constructible, so one law lives in one place.
1030
1085
 
1086
+ ## Surfaces and extensions
1087
+
1088
+ A surface is a part of a workspace that an extension extends, and `Surface` names the two the
1089
+ generator plans. The browser surface is the `browser` environment on the `src` and `app` axes,
1090
+ together with the journey and the showcase of the browser application. The styles surface is the
1091
+ base sheet face at `src/styles`, together with its optional themes target at `src/styles/themes`.
1092
+ An extension adds one face to one surface, and `Blueprint.extensions` lists every extension a
1093
+ workspace carries:
1094
+
1095
+ | Surface | Extension | Face |
1096
+ | --------- | ------------ | ------------------------------------------------------------ |
1097
+ | `browser` | `vue` | `src/vue` on the `src` axis, and `app/vue` on the `app` axis |
1098
+ | `styles` | a sheet name | `src/<name>`, a named sheet face beside `src/styles` |
1099
+
1100
+ `BrowserExtension.axes` lists the axes a browser extension physically occupies, so a target holding
1101
+ `app/vue` and no `src/vue` carries `axes: ['app']`. `FRAMEWORKS` holds `vue` alone. A
1102
+ `StylesExtension` name passes `isSheetName`: it matches `NAME_PATTERN` and is none of the
1103
+ `RESERVED_SHEET_NAMES` values, which are `core`, `browser`, `server`, `bin`, `styles`, `themes`, and
1104
+ `vue`.
1105
+
1106
+ `parseExtension` reads one `surface:name` entry, and `isSurface` decides whether its surface is
1107
+ one the generator plans, so `styles:print` parses and `themes:print` does not. Browser text carries
1108
+ empty axes, because the creating command supplies the browser axes it selected:
1109
+
1110
+ ```ts
1111
+ import { parseExtension } from '@orkestrel/scaffold'
1112
+
1113
+ parseExtension('browser:vue') // { surface: 'browser', name: 'vue', axes: [] }
1114
+ parseExtension('styles:print') // { surface: 'styles', name: 'print' }
1115
+ parseExtension('styles:themes') // undefined
1116
+ parseExtension('browser:react') // undefined
1117
+ ```
1118
+
1119
+ ### Select at creation
1120
+
1121
+ `new` selects each surface and each extension with its own option, as the following command shows:
1122
+
1123
+ ```sh
1124
+ npx @orkestrel/scaffold new paper --src core,browser --app core,browser --styles --themes --showcase --extend browser:vue,styles:print
1125
+ ```
1126
+
1127
+ Each option selects one part:
1128
+
1129
+ - `--styles` selects the styles surface, and `--themes` selects its themes target.
1130
+ - `--showcase` selects the showcase of the browser application.
1131
+ - `--app browser` selects the journey, and no option selects it alone.
1132
+ - `--extend` takes one comma-separated list of `surface:name` entries. A `browser:vue` entry
1133
+ occupies every axis whose selection includes `browser`, so the preceding command plans both
1134
+ `src/vue` and `app/vue`.
1135
+
1136
+ `new` refuses each of the following command lines with exit code `2` before it writes a file:
1137
+
1138
+ | Command line | Refused because |
1139
+ | -------------------------------------------------- | ---------------------------------------------------- |
1140
+ | `--themes` without `--styles` | the themes target belongs to the styles surface |
1141
+ | `--showcase` without `--app browser` | the showcase projects the browser application |
1142
+ | `--extend styles:print` without `--styles` | a named sheet extends the styles surface |
1143
+ | `--extend browser:vue` with no `browser` selection | a browser extension occupies a selected browser axis |
1144
+ | `--extend browser:react` | `vue` is the one supported framework |
1145
+ | `--extend styles:themes` | `themes` is a reserved sheet name |
1146
+ | `--extend browser:vue,browser:vue` | an entry repeats |
1147
+ | `--extend browser:vue --extend styles:print` | `--extend` takes one list |
1148
+ | `--surfaces browser` | `--surfaces` is not an option |
1149
+
1150
+ A library caller can declare an extension the workspace does not place. `blueprintToQuestions`
1151
+ raises one `extensions` question for each such entry, with the following messages:
1152
+
1153
+ - A repeated `surface:name` entry blocks the compile: `styles:print is declared more than once on extensions.`
1154
+ - A browser extension with empty `axes` raises the non-blocking `browser:vue occupies no axis.`
1155
+ - A browser extension on an axis whose selection lacks `browser` raises the non-blocking `browser:vue occupies app, whose selection lacks browser.`
1156
+ - A styles extension without the styles surface raises the non-blocking `styles:print extends a styles surface this workspace does not declare.`
1157
+
1158
+ A browser extension that occupies no axis whose selection includes `browser` adds no framework
1159
+ dependency and no framework machinery.
1160
+
1161
+ ### Read the markers
1162
+
1163
+ Every reading verb derives the structural facts and the extensions from the tree on each run, and
1164
+ no selection is stored anywhere. Each fact and each extension has its own marker:
1165
+
1166
+ | Fact or extension | Marker |
1167
+ | ------------------ | ------------------------------------------------------------------------------------------- |
1168
+ | `styles` | The exact-case `STYLES_ENTRY_PATH` file, `src/styles/index.scss` |
1169
+ | `themes` | The exact-case `THEMES_BARREL_PATH` and `THEMES_ENTRY_PATH` files under `src/styles/themes` |
1170
+ | `showcase` | The exact-case `configs/app/vite.showcase.config.ts` wrapper, or a `showcase` directory |
1171
+ | `journey` | The exact-case `configs/app/vite.journey.config.ts` wrapper |
1172
+ | `vue` | A `src/vue` or `app/vue` directory, and `axes` lists each one present |
1173
+ | A styles extension | A direct `src/<name>` directory holding the exact-case `index.scss` and `sheet.ts` files |
1174
+
1175
+ A reserved directory name is skipped, so a `src/core` directory holding both sheet files reads as no
1176
+ extension. The styles extensions follow the browser extensions, sorted by code unit. A directory
1177
+ holding both sheet files under a name `isSheetName` refuses, and two such directories whose names
1178
+ differ only by case, refuse the target with a `TARGET` error. A face missing one of its markers
1179
+ reads as absent, and Limits states what that costs.
1180
+
1181
+ ### What the styles surface emits
1182
+
1183
+ The styles surface and each styles extension are sheet faces, and every sheet face receives the
1184
+ same seed. In the following table, `<face>` is `styles` or the extension's name:
1185
+
1186
+ | Path | Ownership |
1187
+ | ----------------------------------------------------------------------------------- | ---------- |
1188
+ | `src/<face>/index.scss`, `_tokens.scss`, `_mixins.scss`, `sheet.ts`, and `index.ts` | `birth` |
1189
+ | `_index.scss` in each of `src/<face>/elements`, `components`, and `utilities` | `birth` |
1190
+ | `src/styles/themes/index.scss`, `_default.scss`, and `sheet.ts` | `birth` |
1191
+ | `tests/src/<face>/index.test.ts` and `tests/src/styles/themes/index.test.ts` | `birth` |
1192
+ | `tests/setupStyles.ts` and `tests/setupStyles.test.ts` | `birth` |
1193
+ | `configs/src/vite.<face>.config.ts` and `configs/src/tsconfig.<face>.json` | `content` |
1194
+ | `configs/src/vite.themes.config.ts` | `content` |
1195
+ | `tests/distribution.test.ts` | `presence` |
1196
+
1197
+ `sheet.ts` imports `./index.scss` and nothing else, and `index.ts` star-exports `./sheet.js`.
1198
+ `index.scss` loads `tokens` and then the `elements`, `components`, and `utilities` folder barrels
1199
+ with `@use`, and each `_index.scss` folder barrel starts empty. `_tokens.scss` holds the
1200
+ `@layer theme, reset, base, elements, components, utilities;` order statement. The themes barrel
1201
+ loads `../tokens` and then `_default.scss` with `@use`, so its first emitted rule is the order statement. The
1202
+ themes rows plan only with `themes`, and the themes target takes no TypeScript wrapper of its own.
1203
+
1204
+ Every sheet face publishes. The manifest exports `./<face>` as the compiled `index.css` and
1205
+ `./<face>/scss` as the authored `index.scss`, and themes adds `./styles/themes` and
1206
+ `./styles/themes/scss`. `files` packs the SCSS sources and leaves out each face's JavaScript build
1207
+ stub, and `sideEffects` names every CSS and SCSS file. A styles-only workspace publishes those
1208
+ subpaths and declares no `main`, `module`, or `types` field:
1209
+
1210
+ ```ts
1211
+ import { blueprintToExports, createBlueprint } from '@orkestrel/scaffold'
1212
+
1213
+ const exports = blueprintToExports(createBlueprint('paper', { styles: true, themes: true }))
1214
+
1215
+ Object.keys(exports) // ['./styles', './styles/scss', './styles/themes', './styles/themes/scss', './package.json']
1216
+ ```
1217
+
1218
+ Each sheet face adds its `check:src:<face>`, `build:src:<face>`, and `test:src:<face>` scripts, and
1219
+ `test:src:<face>` builds the face before it runs the face's project. With themes, `build:src:styles`
1220
+ builds the themes target after the base face. The root configuration registers each face's project
1221
+ by its wrapper, and the wrapper composes it through the root `sheetProject` factory, which runs it
1222
+ in Playwright Chromium with `isolate: false` and loads `tests/setup.ts`, `tests/setupBrowser.ts`,
1223
+ and `tests/setupStyles.ts`. The manifest declares `sass` from `STYLES_DEV_DEPENDENCIES` beside the
1224
+ Playwright pair, and the root `tsconfig.json` aliases `@src/<face>` to the face's `index.ts`.
1225
+
1226
+ ### The browser surface
1227
+
1228
+ The base browser application is framework-free. A browser application without the `vue` extension
1229
+ declares no Vue package and loads no Vue plugin, and its `app/browser/main.ts` seed renders the
1230
+ workspace name as a level-1 heading. The `vue` extension adds the `FRAMEWORK_MATRIX.vue`
1231
+ development dependencies, `@vitejs/plugin-vue`, `vue`, and `vue-tsc`, while it occupies an axis
1232
+ whose selection includes `browser`.
1233
+
1234
+ The `vue` extension gives each axis it occupies a face of its own:
1235
+
1236
+ - On the `src` axis it adds the published `src/vue` face: a barrel holding one comment line and no
1237
+ export, the `tests/src/vue/index.test.ts` entry proof, the content-owned
1238
+ `configs/src/vite.vue.config.ts` and `configs/src/tsconfig.vue.json` wrappers, the `@src/vue`
1239
+ alias, and the `./vue` ES export. The wrapper's declaration roll-up rewrites the core and browser
1240
+ specifiers to their published subpaths, so the manifest keeps a `./browser` subpath beside a
1241
+ browser root export. `check:src:vue` checks through `tsc`, `build:src:vue` builds the face, and
1242
+ `test:src:vue` runs its project.
1243
+ - On the `app` axis it adds the `app/vue` application: an empty `index.ts`, a `main.ts` that mounts
1244
+ `App.vue`, an `App.vue` arrival component that renders the same level-1 heading, `index.html`,
1245
+ the `tests/app/vue/index.test.ts` entry proof, the content-owned `configs/app/vite.vue.config.ts`
1246
+ and `configs/app/tsconfig.vue.json` wrappers, the `@app/vue` alias, `check:app:vue` through
1247
+ `vue-tsc`, `build:app:vue`, `dev:vue`, and `test:app:vue`. While `app/vue` is occupied, the root
1248
+ `check` script typechecks the whole tree through `vue-tsc` in place of `tsc`.
1249
+
1250
+ The vendored `.oxlintrc.json` holds each face to the import direction `AGENTS.md` § Project model
1251
+ fixes, and the vendored `tests/config.test.ts` drives those directions through Oxlint.
1252
+
1253
+ Every published face's build decides its externals through `resolveExternal` from the vendored
1254
+ `configs/helpers.ts`. Node builtins, `@orkestrel/*` packages, declared peers with their subpaths,
1255
+ and the sibling entries a face names stay external. The helper bundles an `@src/` or `@app/` alias
1256
+ even where it names a sibling, so the browser and server builds keep `@src/core` external ahead of
1257
+ it and name the core entry as their sibling. The `./vue` build passes `FRAMEWORK_MATRIX.vue.refused`,
1258
+ which holds `vue` and the `@vue/` scope, and the helper refuses that build with one of two messages:
1259
+
1260
+ - An import inside the refused scope reads `The import @vue/runtime-core is refused; import from vue instead of the @vue/ implementation scope.`
1261
+ for `@vue/runtime-core`, even where the manifest declares that package as a peer.
1262
+ - A refused package with no admitting peer reads `The import vue is refused; declare its public package in peerDependencies with peerDependenciesMeta marking it optional.`
1263
+ for `vue`.
1264
+
1265
+ Declare `vue` as an optional peer, and the `./vue` build leaves `vue` and its subpaths external.
1266
+
1267
+ The showcase builds one page per application mode. The base mode reads `app/browser`, and each
1268
+ app-side browser extension adds the mode of its own name. The content-owned
1269
+ `configs/app/vite.showcase.config.ts` wrapper passes the Vite mode to the root
1270
+ `appShowcase(mode, override?)` factory, which selects the application through `resolveApplication`
1271
+ from the vendored `configs/helpers.ts`. No mode, `development`, `production`, and `test` select `browser`, the
1272
+ name of a declared application selects that application, and every other mode throws before the
1273
+ build starts.
1274
+
1275
+ The factory builds into the root `showcase/` directory without emptying it, so one mode's build
1276
+ leaves every sibling page in place. It stamps the final inlined page through `stampPage` and names
1277
+ the page `showcase/<application>.html`. The manifest declares `showcase` and `build:showcase` for
1278
+ the base mode and `showcase:<framework>` and `build:showcase:<framework>` for each extension mode,
1279
+ and a publishing workspace rebuilds every page from `prepublishOnly` after `npm run build` and
1280
+ before `npm test`. The vendored `.prettierignore` lists `showcase/`, so formatting never rewrites a
1281
+ committed page.
1282
+
1283
+ `stampPage` writes one `<meta name="build-id" content="DIGEST" />` line before the line that closes
1284
+ the head, where `DIGEST` is what `computeStamp` returns for the page without that line: its SHA-256
1285
+ digest in lowercase hexadecimal. Stamping a stamped page returns it unchanged. `stampPage` refuses a
1286
+ page carrying a repeated or malformed stamp, and a page whose head does not close on its own line.
1287
+
1288
+ The journey follows the same modes. The birth-owned `configs/app/vite.journey.config.ts` wrapper
1289
+ keeps your variant list and passes the Vite mode to the root `appJourney(variant, variants, mode?)`
1290
+ factory, which selects the application through `resolveApplication` as well. Each variant project
1291
+ collects `tests/app/<application>/integration.test.ts` alone, sets the variant viewport, and
1292
+ provides `variant`, `variants`, and `capture`. The manifest runs `test:journey` for the base
1293
+ application and `test:journey:<framework>`, the same command with `--mode <framework>`, for each
1294
+ app-side browser extension, after `npm run test:app` in `test`.
1295
+
1296
+ Scaffold seeds one birth-owned arrival journey per application at
1297
+ `tests/app/<application>/integration.test.ts`. The base journey imports `app/browser/main.ts`, and
1298
+ the Vue journey mounts `App.vue`. Each resolves the level-1 heading by its role and the workspace
1299
+ name, then proves the Journey, Refusal, and Matrix families the `orkestrel-journey` skill names,
1300
+ and proves Capture as well when `CAPTURE=1` sets the `capture` value. The seeded wrapper declares
1301
+ two variants, which is what makes the journey owe Matrix. A journey workspace's
1302
+ `tests/setupBrowser.ts` seed carries the `ProvidedContext` augmentation that types the three
1303
+ provided values.
1304
+
1305
+ ### Vendored files and their refresh
1306
+
1307
+ The configuration a surface reaches is compiled or vendored, and no package-owned file sits beside
1308
+ it. `tsconfig.json`, `vite.config.ts`, every wrapper under `configs/src`, and
1309
+ `configs/app/vite.showcase.config.ts` are content-owned template artifacts, so `repair` restores a
1310
+ deleted one and replaces a stale one. `configs/app/vite.journey.config.ts` is birth-owned and keeps
1311
+ your variant list. `configs/helpers.ts`, `.oxlintrc.json`, `.prettierignore`, and
1312
+ `tests/config.test.ts` are `HOST_PATHS` members: hydration claims their bytes, so the next
1313
+ release's `repair` refreshes them, and `overwrite` adds deletions rather than a forced refresh.
1314
+ Ownership and drift states the hydration.
1315
+
1316
+ The vendored `tests/config.test.ts` proves those files in each target that holds them. It
1317
+ enumerates the sheet faces and the framework faces from the target's tree rather than from the
1318
+ emitted wrappers, requires a non-empty population only where a marker exists, loads every selected
1319
+ wrapper, and pairs each behaviour with a mutation control in a scratch copy: a deleted wrapper, a
1320
+ removed `tests/setupStyles.ts` entry, a reversed themes build order, a disabled Vue import
1321
+ restriction, and disabled declaration rewrites each fail it. Scaffold's own release gate adds a
1322
+ scratch adopter: `tests/distribution.test.ts` generates the complete selection through the packed
1323
+ executable, installs it, runs its checks, builds, projects, journey modes, showcase builds, and CSS
1324
+ export consumption, and proves that `repair` restores a deleted wrapper byte for byte and that
1325
+ `audit` reports a stale one.
1326
+
1327
+ ### The migration guard
1328
+
1329
+ Vue code belongs to the `vue` extension's faces. `repair` and `overwrite` refuse a target whose
1330
+ `app/browser` directory holds a `.vue` file with a `TARGET` error, before either writes, and the
1331
+ message names the move:
1332
+ `Move Vue components from app/browser to app/vue before regenerating this workspace.` Move the
1333
+ components to `app/vue`, then run `repair`. An `audit` that covers every group reports the same
1334
+ sentence as a non-blocking `extensions` question and keeps the exit code its findings decide, so an
1335
+ otherwise aligned target exits `0`. An `audit` scoped by `--groups` omits the question. Limits
1336
+ names the fleet targets that meet the refusal.
1337
+
1338
+ ### Root setup mirror
1339
+
1340
+ Scaffold plans each setup seed that declares an export beside its sibling proof, so the module and
1341
+ its proof arrive together under the mirror `.claude/rules/tests.md` states:
1342
+
1343
+ - `tests/setupStyles.ts` exports the CSSOM instruments every sheet proof reads and arrives with
1344
+ `tests/setupStyles.test.ts`. The emitted sheet proofs import `adoptSheet` and `readLayerNames`
1345
+ from that module, and the sibling proof drives both against sheets it builds from text.
1346
+ - `tests/setupGlobal.ts` exports the Vitest global `setup` function and arrives with
1347
+ `tests/setupGlobal.test.ts`, which imports `setup` and runs in the Node `setup` project that
1348
+ `test:setup` invokes from `test`.
1349
+
1350
+ A journey workspace's `tests/setupBrowser.ts` seed declares no top-level export, so it arrives
1351
+ without a proof. The vendored policy sweep in `tests/setupPolicy.ts` reads the same mirror in both
1352
+ directions: a root `tests/setup<Name>.test.ts` without its `tests/setup<Name>.ts` module fails
1353
+ `test:policy`, as does a root module that declares an export with neither its sibling proof nor an
1354
+ import from `tests/setup.test.ts`. A module `HOST_PATHS` vendors sits outside that population.
1355
+
1031
1356
  ## Compile
1032
1357
 
1033
1358
  The compiler is pure, synchronous, and host-independent. It runs its stages in order.
@@ -1101,7 +1426,7 @@ order is the order a plan lists its artifacts in.
1101
1426
  | --------------- | ------------------------------------------------------------------------------------------------- |
1102
1427
  | `manifest` | `package.json` |
1103
1428
  | `configs` | The root and per-target build configuration, and the root dotfiles |
1104
- | `source` | The selected environment barrels and entries |
1429
+ | `source` | The selected environment barrels and entries, and each sheet face's seed |
1105
1430
  | `tests` | The shared setup modules, the entry tests, and the policy sweep |
1106
1431
  | `guides` | The guide index and the vendored guide mirrors |
1107
1432
  | `docs` | `README.md` beside the `AGENTS.md` pointer |
@@ -1174,9 +1499,10 @@ aligned whether it is present or absent, so it neither restores missing bytes no
1174
1499
  bytes.
1175
1500
 
1176
1501
  You own `tests/setup.ts`, the selected `tests/setupBrowser.ts`, `tests/setupServer.ts`,
1177
- `tests/setupService.ts`, and `tests/setupGlobal.ts` modules, each root `tests/setup*.test.ts` proof,
1178
- the selected environment entry tests under `tests/src` and `tests/app`, the
1179
- `tests/src/bin/main.test.ts` file, and the `tests/integration.test.ts` seed. Scaffold writes those
1502
+ `tests/setupService.ts`, `tests/setupStyles.ts`, and `tests/setupGlobal.ts` modules, each root
1503
+ `tests/setup*.test.ts` proof, the selected environment and sheet-face entry tests under `tests/src`
1504
+ and `tests/app`, the `tests/src/bin/main.test.ts` file, and the `tests/integration.test.ts` seed.
1505
+ Every sheet face's seed under `src` is yours on the same terms. Scaffold writes those
1180
1506
  planned files only during materialize and leaves later edits or deletions alone. You also own the
1181
1507
  `tests/guides.test.ts`, `tests/conformance.test.ts`, and `tests/service/**/*.test.ts` proof files,
1182
1508
  each of which selects its project by being written. Scaffold content-owns `tests/setupPolicy.ts`,
@@ -1186,7 +1512,10 @@ their bytes drift or the files are missing.
1186
1512
  `tests/policy.test.ts` proves the path- and text-shaped laws, and the vendored oxlint plugin
1187
1513
  `configs/policy.ts` carries the syntax-shaped ones: `policy/no-malformed-summary` reads the doc
1188
1514
  block preceding each export, and `policy/no-banned-term` reads every comment for a term
1189
- `.claude/rules/writing.md` § Substitutions bans unconditionally. The prose sweep in
1515
+ `.claude/rules/writing.md` § Substitutions bans unconditionally. `policy/no-nested-functions`
1516
+ enforces the nested-function law of `.claude/rules/architecture.md` § Functions and orchestration,
1517
+ its callback admission included: an event map passed as an option from inside a function body
1518
+ passes the rule, and a function bound to a local name fails it. The prose sweep in
1190
1519
  `tests/setupPolicy.ts` reads every authored Markdown file for the same terms through the
1191
1520
  `POLICY_BANNED_TERMS` denylist the rule and the sweep share, and `tests/policy.test.ts` proves that
1192
1521
  denylist against the table wherever the workspace authors it. The sweep skips a top-level guide the
@@ -1433,7 +1762,9 @@ not install are seeds — `@vitejs/plugin-vue`, `vue`, `vue-tsc`, `vite-plugin-s
1433
1762
  application-server fleet packages — and each carries the newest triple its supported major served
1434
1763
  when it was written.
1435
1764
  [`tests/src/core/constants.test.ts`](../tests/src/core/constants.test.ts) names that seeded set, so a
1436
- row entering or leaving the manifest moves a test rather than passing unnoticed.
1765
+ row entering or leaving the manifest moves a test rather than passing unnoticed. `sass`, the one row
1766
+ of `STYLES_DEV_DEPENDENCIES`, is a seed as well: it carries the `^1.105.1` range the
1767
+ `@orkestrel/veneer` checkout declared on 2026-09-30, and that test names it in the seeded set.
1437
1768
 
1438
1769
  A newer major is never crossed for you. `audit` reports one as a non-blocking `dependencies`
1439
1770
  question, and a person decides whether the generated toolchain supports it. Inside the declared
@@ -1703,8 +2034,8 @@ read or write that file.
1703
2034
 
1704
2035
  ## Generated workspace
1705
2036
 
1706
- A workspace's file set is a function of its axes plus its structural facts. Nothing is fixed
1707
- except the manifest.
2037
+ A workspace's file set is a function of its axes, its structural facts, and its extensions.
2038
+ Nothing is fixed except the manifest.
1708
2039
 
1709
2040
  - One computed artifact: `package.json`, with the entry points, `exports` map, scripts, and
1710
2041
  development dependencies its selection implies. In publishing workspaces, the emitted `prepack`
@@ -1739,9 +2070,15 @@ except the manifest.
1739
2070
  integration selection also emits a birth-owned `tests/integration.test.ts` seed that imports each
1740
2071
  selected public barrel and records its initial empty exports for the consumer to replace with an
1741
2072
  observable cross-environment flow.
2073
+ - One set of template artifacts per sheet face, and one for the themes target: the birth-owned
2074
+ seed, the content-owned wrappers, and the birth-owned entry proof, beside the birth-owned
2075
+ `tests/setupStyles.ts` module and its proof. Surfaces and extensions lists each path.
2076
+ - One set of template artifacts per axis the `vue` extension occupies, and one birth-owned arrival
2077
+ journey per application of a journey workspace. Surfaces and extensions lists each face.
1742
2078
  - One template artifact, `tests/distribution.test.ts`, for a workspace publishing any `src`
1743
- environment. It is the packed-package proof, and it is claimed by presence rather than birth, so a
1744
- workspace that replaces it keeps its replacement. A published browser environment adds the
2079
+ environment or sheet face. It is the packed-package proof, and it is claimed by presence rather
2080
+ than birth, so a workspace that replaces it keeps its replacement. A published browser environment
2081
+ adds the
1745
2082
  real-browser stage to it: the stage bundles the installed package with the workspace's own
1746
2083
  `configs/browsers.ts` resolution, serves the bundle over a loopback server, and drives it in
1747
2084
  Playwright Chromium.
@@ -1962,7 +2299,12 @@ the Surface tables match the core and server barrels in each direction, the meth
1962
2299
  behavioral declarations, relative links resolve, and named imports in TypeScript fences resolve. It
1963
2300
  does not resolve arbitrary backticked prose spans or typecheck a whole fence. The same suite keeps
1964
2301
  the command reference aligned with the executable and executes the transcribed pure examples for
1965
- blueprint defaults, compile refusal, and error-code narrowing. Other trailing comments remain guide
2302
+ blueprint defaults, compile refusal, error-code narrowing, extension parsing, and the styles-only
2303
+ export map. It also drives the marker, creation, advisory, styles-surface, Vue-face, showcase,
2304
+ stamp, journey, setup-seed, external-resolution, and migration-guard claims of Surfaces and
2305
+ extensions through the compilers, the vendored `configs/helpers.ts`, scratch trees, and the
2306
+ executable. The page stamp is driven on page text, so no showcase build runs there; the scratch
2307
+ adopter in `tests/distribution.test.ts` runs the builds. Other trailing comments remain guide
1966
2308
  claims rather than build answers. The verdicts that are measured are the ones a consumer hovers:
1967
2309
  [`tests/distribution.test.ts`](../tests/distribution.test.ts) drives every `@example` the built
1968
2310
  declarations print against the installed package, scores each verdict it can read as a value, and
@@ -2011,10 +2353,18 @@ filename that legally contains a backslash — `weird\..\name` — is therefore
2011
2353
  segments rather than admitted as one name. That is one separator law with a conservative side, not a
2012
2354
  host-dependent second one.
2013
2355
 
2014
- **Scaffold emits no styles axis.** `SRC_MATRIX` is exactly `core`, `browser`, and `server`, and
2015
- `Blueprint` carries no styles field. A workspace that needs `src/styles/` adds the directory, its
2016
- configuration, and its Vitest project by hand. `.claude/rules/workspace.md` describes styles as an
2017
- environment because the fleet has one; scaffold does not generate it.
2356
+ **A face missing one of its markers reads as absent.** Derivation reads a sheet face only from its
2357
+ complete marker set: `src/styles/index.scss` for the base face, both themes files for the themes
2358
+ target, and both `index.scss` and `sheet.ts` for a styles extension. A face that lost one of them
2359
+ reads as no face at all, so the plan carries none of its artifacts, `repair` restores none of them,
2360
+ and the regenerated root configuration registers no project for it. Restore the missing marker by
2361
+ hand, then run `repair`.
2362
+
2363
+ **A fleet target holding Vue code under `app/browser` cannot repair.** On 2026-09-30 the
2364
+ `elements`, `mailbox`, `roughnotes`, and `supervisor` checkouts each held `.vue` files under
2365
+ `app/browser`, read by a recursive count in each local checkout. The migration guard refuses
2366
+ `repair` and `overwrite` in each of them until its components move to `app/vue`, so each moves them
2367
+ in its own change before it adopts the release that carries the guard.
2018
2368
 
2019
2369
  **No host path is normalized before it is guarded.** `isFilesystemPath` refuses an empty segment, so
2020
2370
  `packages//router` is off contract. A trailing separator does not produce one: it terminates a
@@ -2033,7 +2383,10 @@ implementation that conforms to it, then export both from the barrel — the ord
2033
2383
  is what separates them, and it is the whole rule. Generating a file is not the same as writing one:
2034
2384
  scaffold also writes `tests/policy.test.ts` and `tests/config.test.ts` into a target, byte for byte
2035
2385
  from the shared file set, and the distribution proof is the one it derives from the workspace it is
2036
- writing into.
2386
+ writing into. A seed is not generation either: scaffold writes `tests/setupStyles.test.ts`,
2387
+ `tests/setupGlobal.test.ts`, and each arrival journey at creation, as birth-owned template bytes
2388
+ that prove the modules and applications it seeds beside them. After creation those files are the
2389
+ workspace's, so no verb compares or restores them.
2037
2390
 
2038
2391
  A distribution proof's every assertion derives from the artifact the workspace installs: the
2039
2392
  `exports` map the packed tarball declares, the built declarations beside it, and the module objects
@@ -2041,7 +2394,7 @@ a Node import, a CommonJS require, and a real browser hand back from that instal
2041
2394
  there has to be named, so one generated file measures every publishing workspace, and it stays true
2042
2395
  as that workspace's published surface moves.
2043
2396
 
2044
- A guide, conformance, live-service, or setup proof asserts something scaffold cannot read: the API a
2397
+ A guide, conformance, live-service, or authored setup proof asserts something scaffold cannot read: the API a
2045
2398
  guide fence claims, the official runner a conformance check measures against, the service a live
2046
2399
  proof drives, and what a setup module does. That subject is what no generated file can reach, and
2047
2400
  the claim here is about the subject rather than about every property those files have. A structural
@@ -2049,17 +2402,16 @@ property of the same files can be derivable — whether each root `tests/setup*.
2049
2402
  reachable from the root configuration is one — and a file asserting it would still leave the
2050
2403
  module's behavior unmeasured. A generated file there would read as a proof while measuring nothing,
2051
2404
  which is worse than an absent one. So the file a consumer writes is what selects each of those
2052
- projects, and `tests/distribution.test.ts` is the one proof scaffold generates for you.
2405
+ projects. Scaffold also seeds proofs for its own setup modules, as Root setup mirror describes.
2053
2406
 
2054
2407
  Registration follows the same split. Scaffold registers `conformance` and `service` when their
2055
2408
  structural facts are set, and registers `distribution` whenever the workspace publishes at least one
2056
- `src` environment. In a publishing workspace, `distribution` and `service` run from `prepublishOnly`
2409
+ `src` environment or sheet face. In a publishing workspace, `distribution` and `service` run from `prepublishOnly`
2057
2410
  and `conformance` stays in `test`. In a `private: true` workspace, `distribution` is absent,
2058
- `service` runs from `test`, and there is no `prepublishOnly` at all. One gap the project set cannot
2059
- show, `audit` reports directly: a filled `tests/setup*.ts` module that no `tests/setup*.test.ts`
2060
- proof covers raises the non-blocking `setup` question, which names the modules and the proof to add.
2061
- Scaffold generates nothing there either, because what that proof asserts is those modules' own
2062
- behavior, which only the workspace that wrote them can state.
2411
+ `service` runs from `test`, and there is no `prepublishOnly` at all. The `policy` project reports an exporting root setup module that lacks its sibling proof or an import from `tests/setup.test.ts`.
2412
+ Separately, a filled, exporting `tests/setup*.ts` module that no `tests/setup*.test.ts`
2413
+ proof covers raises the non-blocking `setup` question in `audit`, which names the modules and the proof to add.
2414
+ For setup modules the workspace authors, the workspace supplies the behavior proof; the setup modules scaffold seeds arrive with their sibling proofs.
2063
2415
 
2064
2416
  The generated proof partitions the installed `exports` map rather than sampling it. Every published
2065
2417
  subpath lands in exactly one of driven, undeclared, or excluded, and a totality assertion holds that
@@ -2178,7 +2530,8 @@ The generated distribution proof takes its release contract from the outside. Th
2178
2530
  The project factories the root configuration registers receive the invocation record, and each of
2179
2531
  their projects runs in the invocation's mode. Vitest runs a project whose factory returns no mode in
2180
2532
  Vitest's own `test` mode, where the proof skips. A journey project is such a project: its
2181
- birth-owned wrapper drops the record, so it runs in `test` whatever mode the run names.
2533
+ birth-owned wrapper reads the run's mode only to select the application, and the factory it hands
2534
+ each project takes no record, so the project runs in `test` whatever mode the run names.
2182
2535
  An ordinary local run skips that case, because a developer offline is not a defect; a release run
2183
2536
  does not, because skipping there passes the publish gate without ever proving the artifact installs.
2184
2537
  A workspace that replaces the generated proof takes that contract with it: presence ownership leaves
@@ -2208,6 +2561,8 @@ port, so the run drives nothing external and stays in `test`.
2208
2561
 
2209
2562
  ## Tests
2210
2563
 
2564
+ The generated guide index lists each occupied Vue face with its source, tests, and directory entry, and each selected showcase page.
2565
+
2211
2566
  - [`tests/src/core/Compiler.test.ts`](../tests/src/core/Compiler.test.ts) — the compile stages, the
2212
2567
  fail-closed rule, off-contract input, and teardown.
2213
2568
  - [`tests/src/core/compilers.test.ts`](../tests/src/core/compilers.test.ts) — every projection from
@@ -2241,13 +2596,18 @@ port, so the run drives nothing external and stays in `test`.
2241
2596
  rendering, and the failure envelope.
2242
2597
  - [`tests/src/bin/main.test.ts`](../tests/src/bin/main.test.ts) — the process entry point.
2243
2598
  - [`tests/policy.test.ts`](../tests/policy.test.ts) — the path- and text-shaped policy laws:
2244
- mirrors, suppressions, the rule map, filenames, manifest scripts, skills, bridges, and the prose
2245
- sweep over every authored Markdown file. The syntax-shaped laws are the rules of the vendored
2246
- oxlint plugin `configs/policy.ts`, proven in `tests/config.test.ts`.
2599
+ mirrors, the root setup mirror, suppressions, the rule map, filenames, manifest scripts, skills,
2600
+ bridges, and the prose sweep over every authored Markdown file. The syntax-shaped laws are the
2601
+ rules of the vendored oxlint plugin `configs/policy.ts`, proven in `tests/config.test.ts`.
2247
2602
  - [`tests/config.test.ts`](../tests/config.test.ts) — the root configuration's aliases, projects,
2248
2603
  and outputs, every plugin rule against a case pair drawn from inside and outside its membership
2249
- boundary, and the declaration roll-up over a real face.
2250
- - [`tests/guides.test.ts`](../tests/guides.test.ts) — this guide's bijection with the barrels.
2604
+ boundary, the declaration roll-up over a real face, and the sheet and framework faces enumerated
2605
+ from the tree with a mutation control per behaviour.
2606
+ - [`tests/distribution.test.ts`](../tests/distribution.test.ts) — the packed package installed and
2607
+ resolved through its public exports, and the scratch adopter that generates, installs, builds,
2608
+ and repairs the complete selection.
2609
+ - [`tests/guides.test.ts`](../tests/guides.test.ts) — this guide's bijection with the barrels, its
2610
+ transcribed fences, and the executed behaviour behind its prose claims.
2251
2611
 
2252
2612
  ## See also
2253
2613