@orkestrel/scaffold 0.0.49 → 0.0.51

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.
@@ -12,8 +12,8 @@ does not work. Scaffold makes the shared set data — a vendored data root shipp
12
12
  — and gives it verbs: create a workspace from it, report how a workspace differs from it, and
13
13
  write the difference back.
14
14
 
15
- Every code fence below is illustrative. [`tests/guides.test.ts`](../tests/guides.test.ts) keeps the
16
- command reference aligned with the executable and transcribes the pure blueprint-default,
15
+ Every following code fence is illustrative. [`tests/guides.test.ts`](../tests/guides.test.ts)
16
+ keeps the command reference aligned with the executable and transcribes the pure blueprint-default,
17
17
  compile-refusal, and error-narrowing fences. A trailing comment in another fence is this guide's
18
18
  claim rather than a measured answer; the driven examples are the ones the shipped declarations
19
19
  print. Limits states what that leaves unproven and what covers it instead.
@@ -59,27 +59,31 @@ Exported from `@orkestrel/scaffold`, and reachable from
59
59
 
60
60
  #### Interfaces
61
61
 
62
- | Name | Kind | Summary |
63
- | ------------------- | --------- | --------------------------------------------------------------------------------------- |
64
- | `AppDefinition` | interface | The configuration and runtime-entry settings one private `app` environment contributes. |
65
- | `ArtifactBase` | interface | The fields every planned file carries. |
66
- | `Audit` | interface | The whole comparison of a plan against a target's current content. |
67
- | `Blueprint` | interface | The closed, JSON-serializable workspace specification. |
68
- | `CompileFailure` | interface | The coded reason one compile stage failed. |
69
- | `CompileRecord` | interface | The input and output snapshot of one compile stage. |
70
- | `CompilerInterface` | interface | The compilation contract: pure, synchronous, and host-independent. |
71
- | `CompilerOptions` | interface | Options for the compiler. |
72
- | `ContentArtifact` | interface | A text file produced by the template or computed compilation path. |
73
- | `Dependency` | interface | One runtime `@orkestrel/*` dependency of a generated workspace. |
74
- | `HostArtifact` | interface | A file byte-copied from the vendored data root, planned before its bytes are read. |
75
- | `HydratedArtifact` | interface | A vendored file whose exact bytes have been read, so its content can be compared. |
76
- | `Override` | interface | One artifact override. |
77
- | `Plan` | interface | The compiled, ordered artifact list and the selection it covers. |
78
- | `PlanSummary` | interface | The tally of one plan by artifact origin. |
79
- | `Question` | interface | One validation issue raised against a blueprint or a plan. |
80
- | `Scaffolding` | interface | The replayable outcome of one compile. |
81
- | `SrcDefinition` | interface | The build and export settings one published `src` environment contributes. |
82
- | `ViteMachinery` | interface | Which host-specific pipelines a generated root Vite configuration carries. |
62
+ | Name | Kind | Summary |
63
+ | ----------------------- | --------- | --------------------------------------------------------------------------------------- |
64
+ | `AppDefinition` | interface | The configuration and runtime-entry settings one private `app` environment contributes. |
65
+ | `ArtifactBase` | interface | The fields every planned file carries. |
66
+ | `Audit` | interface | The whole comparison of a plan against a target's current content. |
67
+ | `Blueprint` | interface | The closed, JSON-serializable workspace specification. |
68
+ | `CompileFailure` | interface | The coded reason one compile stage failed. |
69
+ | `CompileRecord` | interface | The input and output snapshot of one compile stage. |
70
+ | `CompilerInterface` | interface | The compilation contract: pure, synchronous, and host-independent. |
71
+ | `CompilerOptions` | interface | Options for the compiler. |
72
+ | `ContentArtifact` | interface | A text file produced by the template or computed compilation path. |
73
+ | `Dependency` | interface | One runtime `@orkestrel/*` dependency of a generated workspace. |
74
+ | `DependencyPinSet` | interface | The runtime and development dependency sections a range writer may change. |
75
+ | `HostArtifact` | interface | A file byte-copied from the vendored data root, planned before its bytes are read. |
76
+ | `HydratedArtifact` | interface | A vendored file whose exact bytes have been read, so its content can be compared. |
77
+ | `ManifestDependencySet` | interface | The runtime, development, and peer declarations read from an existing manifest. |
78
+ | `ManifestRegionSet` | interface | The manifest regions a writing operation may change. |
79
+ | `ManifestScript` | interface | One manifest script a region-writing operation may replace. |
80
+ | `Override` | interface | One artifact override. |
81
+ | `Plan` | interface | The compiled, ordered artifact list and the selection it covers. |
82
+ | `PlanSummary` | interface | The tally of one plan by artifact origin. |
83
+ | `Question` | interface | One validation issue raised against a blueprint or a plan. |
84
+ | `Scaffolding` | interface | The replayable outcome of one compile. |
85
+ | `SrcDefinition` | interface | The build and export settings one published `src` environment contributes. |
86
+ | `ViteMachinery` | interface | Which host-specific pipelines a generated root Vite configuration carries. |
83
87
 
84
88
  #### Constants
85
89
 
@@ -101,7 +105,7 @@ Exported from `@orkestrel/scaffold`, and reachable from
101
105
  | `DEFAULT_ENGINES` | const | The `engines.node` range a workspace starts with. |
102
106
  | `DEFAULT_VERSION` | const | The version a workspace starts at. |
103
107
  | `DEPENDENCY_NAME_PATTERN` | const | The runtime dependency name syntax: the `@orkestrel` scope and a bare name. |
104
- | `DISTRIBUTION_TEST_PATH` | const | The packed-package proof whose presence makes a workspace `distribution`. |
108
+ | `DISTRIBUTION_TEST_PATH` | const | The generated packed-package proof every publishing workspace is planned at. |
105
109
  | `ENGINES_PATTERN` | const | The minimum-Node engine syntax a blueprint declares. |
106
110
  | `ENVIRONMENTS` | const | The `Environment` values, frozen. |
107
111
  | `EXECUTABLE_PATHS` | const | The vendored paths a target receives with its executable bit set, frozen. |
@@ -116,6 +120,7 @@ Exported from `@orkestrel/scaffold`, and reachable from
116
120
  | `HOST_INVENTORY_PATH` | const | The repository-relative path where the committed vendored-file inventory is served. |
117
121
  | `INTEGRATION_TEST_PATH` | const | The cross-environment composition proof whose presence makes a workspace `integration`. |
118
122
  | `INVALID_PATH_CHARACTER_PATTERN` | const | Visible characters a target-relative path and a Markdown path cell both forbid. |
123
+ | `MANIFEST_PATH` | const | The manifest path every compiler plan emits with birth ownership. |
119
124
  | `MAX_ARTIFACT_BYTES` | const | Maximum bytes accepted for one artifact. |
120
125
  | `MAX_ARTIFACT_HEX_LENGTH` | const | Maximum length of the hexadecimal string carrying one artifact's bytes. |
121
126
  | `MAX_AUDIT_FINDINGS` | const | Maximum findings one audit can produce from a bounded plan and snapshot. |
@@ -126,6 +131,7 @@ Exported from `@orkestrel/scaffold`, and reachable from
126
131
  | `MAX_PATH_LENGTH` | const | Maximum length of one path, matching the longest a supported filesystem accepts. |
127
132
  | `MAX_RANGE_LENGTH` | const | Maximum length of one declared package range. |
128
133
  | `MAX_REGISTRY_BYTES` | const | Maximum decoded bytes accepted from one registry response. |
134
+ | `MAX_SCRIPT_LENGTH` | const | Maximum length of one manifest script name or command. |
129
135
  | `MAX_TOTAL_ARTIFACT_BYTES` | const | Maximum bytes retained across one whole plan or audit. |
130
136
  | `MAX_TOTAL_REGISTRY_BYTES` | const | Maximum decoded bytes accepted across one registry-reading call. |
131
137
  | `MINIMUM_NODE_VERSION` | const | The oldest Node version the generated toolchain supports. |
@@ -134,6 +140,7 @@ Exported from `@orkestrel/scaffold`, and reachable from
134
140
  | `ORCHESTRATION_PATH_PREFIXES` | const | The path prefixes whose contents instruct or wire an agent, frozen. |
135
141
  | `ORKESTREL_RANGE_PATTERN` | const | The exact caret-pinned pre-1.0 range accepted for an `@orkestrel/*` runtime dependency. |
136
142
  | `PRINT_WIDTH` | const | Columns one emitted line may occupy, matching `printWidth` in `.oxfmtrc.json`. |
143
+ | `RELEASE_PROOF_COMMAND` | const | The `prepublishOnly` row that runs the packed-package proof against a real registry. |
137
144
  | `SERVICE_SCRIPT_PATH` | const | The provisioner skeleton a workspace with declared service vendors is given once. |
138
145
  | `SERVICE_SETUP_PATH` | const | The live-service readiness module whose presence makes a workspace `service`. |
139
146
  | `SERVICE_TEST_INCLUDE` | const | The include the live-service project covers, which is a directory rather than one proof. |
@@ -164,6 +171,7 @@ Exported from `@orkestrel/scaffold`, and reachable from
164
171
  | `isGroup` | const | Narrow a value to one `Group` a plan selects over. |
165
172
  | `isGroups` | const | Narrow a value to a bounded group selection. |
166
173
  | `isHex` | const | Narrow a value to exact lowercase hexadecimal bytes within one artifact's limit. |
174
+ | `isManifestScript` | const | Narrow a value to a `ManifestScript`. |
167
175
  | `isMirror` | const | Narrow a value to a `Mirror`. |
168
176
  | `isOverride` | const | Narrow a value to an `Override`. |
169
177
  | `isPath` | function | Narrow a value to a logical target-relative path. |
@@ -198,7 +206,7 @@ Exported from `@orkestrel/scaffold`, and reachable from
198
206
  | `inferDrift` | function | Infer how one target path compares to the artifact planned for it. |
199
207
  | `inferGroup` | function | Infer the `Group` a path belongs to. |
200
208
  | `isDeferredPath` | function | Test whether another surface owns the vendored bytes at a path. |
201
- | `manifestToDependencies` | function | Project a package manifest's text to the `@orkestrel/*` packages it declares. |
209
+ | `manifestToDependencies` | function | Project a manifest's `@orkestrel/*` declarations into separate section lists. |
202
210
  | `manifestToName` | function | Project a package manifest's text to its own name. |
203
211
  | `matchesDriftReachability` | function | Test whether `inferDrift` could have produced a finding for an ownership. |
204
212
  | `matchesEngines` | function | Test whether a declared engines floor is at or above the supported minimum. |
@@ -232,14 +240,16 @@ Exported from `@orkestrel/scaffold`, and reachable from
232
240
  | `blueprintToScripts` | function | Project a blueprint into the scripts its manifest declares. |
233
241
  | `blueprintToSourceArtifacts` | function | Compile every artifact in the `source` group. |
234
242
  | `blueprintToTestArtifacts` | function | Compile every artifact in the `tests` group that is not vendored from the host. |
243
+ | `blueprintToWritableScripts` | function | Project a blueprint into the manifest scripts a region write may replace. |
235
244
  | `dependenciesToQuestions` | function | Measure one declared package list against the name and range syntax it accepts. |
236
245
  | `nameToHostArtifacts` | function | Compile the vendored host artifacts a named workspace plans. |
237
246
  | `overridesToQuestions` | function | Measure a blueprint's overrides against the artifacts drafted for it. |
238
247
  | `pathToCondition` | function | Build one `exports` condition block for a built environment. |
239
248
  | `planToFindings` | function | Compare a plan against a target's current content. |
240
249
  | `planToHash` | function | Compute a plan's content identity. |
241
- | `replaceManifestRanges` | function | Replace declared dependency ranges in package manifest text. |
242
- | `replacePlanRanges` | function | Replace dependency ranges in a plan's manifest and recompute its identity. |
250
+ | `replaceManifestRanges` | function | Replace runtime and development ranges without reading or writing peer fields. |
251
+ | `replaceManifestScripts` | function | Replace named script values, refusing a value the region does not accept. |
252
+ | `replacePlanRanges` | function | Replace writable ranges in a plan's manifest and recompute its identity. |
243
253
  | `srcToEntry` | function | Project a published selection into the manifest's entry fields. |
244
254
  | `srcToExports` | function | Project a published selection into the manifest's `exports` map. |
245
255
  | `srcToRoot` | function | Select the single published environment a package root points at. |
@@ -321,6 +331,7 @@ Exported from `@orkestrel/scaffold/server`, and reachable from
321
331
  | `isHostManifest` | const | Narrow a value to one `HostManifest`. |
322
332
  | `isInventory` | function | Narrow a value to a working-tree inventory within the limit one target may report. |
323
333
  | `isManifestEntry` | const | Narrow a value to one `ManifestEntry`. |
334
+ | `isManifestRegionSet` | const | Narrow a value to one `ManifestRegionSet`. |
324
335
  | `isMaterializerHooks` | const | Narrow a value to the materializer's initial listener record. |
325
336
  | `isMaterializerOptions` | const | Narrow a value to `MaterializerOptions`. |
326
337
  | `isMirrors` | const | Narrow a value to a bounded list of fetched guide mirrors. |
@@ -380,8 +391,8 @@ Exported from `@orkestrel/scaffold/server`, and reachable from
380
391
 
381
392
  `Compiler` implements `CompilerInterface`, `Materializer` implements `MaterializerInterface`, and
382
393
  `Upstream` implements `UpstreamInterface`. Each class exposes exactly its interface's members and
383
- nothing more, so the interface tables below describe the classes too. `WriteTransaction` publishes
384
- no interface and is documented directly.
394
+ nothing more, so the following interface tables describe the classes too. `WriteTransaction`
395
+ publishes no interface and is documented directly.
385
396
 
386
397
  #### `CompilerInterface`
387
398
 
@@ -400,7 +411,7 @@ no interface and is documented directly.
400
411
  | `repair` | Write a plan into an existing target, guided by an audit of it. |
401
412
  | `mirror` | Write fetched dependency guides to their local mirrors. |
402
413
  | `catalog` | Rewrite the marker-bounded package table in the target's catalog agent file. |
403
- | `declare` | Rewrite the `@orkestrel/*` range set in the target's manifest. |
414
+ | `declare` | Rewrite the manifest regions the caller names: the ranges and the scripts. |
404
415
  | `remove` | Re-derive and delete the tracked files the plan does not own. |
405
416
  | `destroy` | Tear the materializer down. Every later call throws, and teardown is idempotent. |
406
417
 
@@ -430,13 +441,13 @@ no interface and is documented directly.
430
441
  Authority is the verb's: every verb except `audit` writes when it is typed, and no
431
442
  option grants a write.
432
443
 
433
- | Verb | Writes |
434
- | ----------- | ------------------------------------------------------------------------------- |
435
- | `new` | A whole workspace, into a target that holds nothing the plan would collide with |
436
- | `audit` | Nothing |
437
- | `repair` | Each planned path the target is missing or has let drift, and the ranges |
438
- | `catalog` | The package table, the guide mirrors, and the ranges |
439
- | `overwrite` | Everything `repair` and `catalog` write, plus deletions |
444
+ | Verb | Writes |
445
+ | ----------- | ------------------------------------------------------------------------------------------ |
446
+ | `new` | A whole workspace, into a target that holds nothing the plan would collide with |
447
+ | `audit` | Nothing |
448
+ | `repair` | Each planned path the target is missing or has let drift, and the range and script regions |
449
+ | `catalog` | The package table, the guide mirrors, and the range region |
450
+ | `overwrite` | Everything `repair` and `catalog` write, plus deletions |
440
451
 
441
452
  ### Baselines
442
453
 
@@ -517,14 +528,17 @@ answers a read and grant no verb write authority that it did not already have.
517
528
 
518
529
  `new --bin` creates the executable entry, its test, and its scoped Vite and TypeScript wrappers. The
519
530
  other structural facts do not need creation flags. Add a root `tests/setup*.test.ts` proof for
520
- `setup`, `tests/guides.test.ts` for `guides`,
521
- `tests/distribution.test.ts` for `distribution`, `tests/integration.test.ts` for `integration`,
531
+ `setup`, `tests/guides.test.ts` for `guides`, `tests/integration.test.ts` for `integration`,
522
532
  `tests/conformance.test.ts` for `conformance`, `tests/setupService.ts` for `service`,
523
533
  `tests/setupGlobal.ts` for `global`, and `configs/app/vite.showcase.config.ts` for `showcase`;
524
534
  reading verbs detect each exact-case file and register its fixed machinery. Add `scripts/service.sh`
525
535
  for `vendors`. Reading verbs preserve and protect that birth-owned script, but do not infer its
526
536
  vendor list from edited text.
527
537
 
538
+ `distribution` is not on that list. Publishing at least one `src` environment is its whole
539
+ condition, and scaffold writes `tests/distribution.test.ts` itself rather than waiting for you to.
540
+ Limits states what makes that one proof generable when the others are not.
541
+
528
542
  ### Reading a target
529
543
 
530
544
  `audit`, `repair`, `catalog`, and `overwrite` derive the blueprint from the target itself. The name
@@ -532,11 +546,11 @@ and the declared `@orkestrel/*` packages come from `package.json`. The environme
532
546
  from the directories the target actually ships, because a directory is the fact and a declaration
533
547
  beside it could disagree. The remaining facts come from exact-case files: `src/bin/main.ts` selects
534
548
  `bin`, each root `tests/setup*.test.ts` match selects `setup`, `tests/guides.test.ts` selects
535
- `guides`, `tests/distribution.test.ts` selects `distribution`,
536
- `tests/integration.test.ts` selects `integration`, `tests/conformance.test.ts` selects
549
+ `guides`, `tests/integration.test.ts` selects `integration`, `tests/conformance.test.ts` selects
537
550
  `conformance`, `tests/setupService.ts` selects `service`, `tests/setupGlobal.ts` selects `global`,
538
551
  and `configs/app/vite.showcase.config.ts` selects `showcase`. A containing directory does not select
539
- the fact by itself.
552
+ the fact by itself. `tests/distribution.test.ts` selects nothing: the published `src` axis the
553
+ target ships already decides the `distribution` project, and the file is planned from that.
540
554
 
541
555
  `vendors` is not reconstructed. Its only artifact, `scripts/service.sh`, is birth-owned, so edited
542
556
  script text is not a trustworthy declaration of a vendor list. A present script remains in the
@@ -552,9 +566,9 @@ carries the fact and the vendor list keeps its own separate job.
552
566
  The root Vite configuration defines and registers the fixed `guides` project only when the derived
553
567
  blueprint carries `guides`. Reading verbs set that fact only when `tests/guides.test.ts` is a
554
568
  physical file with that exact path case. A directory or a case-folded spelling does not select it. A
555
- fresh workspace therefore carries no guides project or script. A developer who adds the proof must
556
- also add the exact `test:guides` script line that the plan reports; the manifest remains
557
- birth-owned.
569
+ fresh workspace therefore carries no guides project or script. When a developer adds the proof,
570
+ `audit` reports the exact `test:guides` script line until `repair` or `overwrite` appends it through
571
+ the writable script region. The rest of the manifest remains birth-owned.
558
572
 
559
573
  The plan-reading verbs compare the Vitest project set named by the target manifest with the
560
574
  project set the planned root configuration registers. Every planned proof project must also be
@@ -568,16 +582,39 @@ question instead of licensing a write. The classifier is deliberately bounded to
568
582
  text that names `vitest`; an external wrapper whose name does not identify its runner supplies no
569
583
  static Vitest fact to infer.
570
584
 
571
- `audit` still completes the comparison and reports one non-blocking `projects` question. For a
585
+ `audit` still completes the comparison and reports one non-blocking `projects` question when its
586
+ selection includes `configs`. A scoped audit that excludes `configs` omits that question. For a
572
587
  literal absent project, its advisory tells the developer to register the project or remove the
573
- script. For a planned project absent from the gate chains, the advisory checks the direct
574
- `test:<project>` script. When the script is absent, the advisory gives the exact line to add to
575
- `package.json`. When the script is declared but ungated, the advisory names the script and the gate
576
- chain that must invoke it, without repeating a script line. `repair` and `overwrite` refuse either
577
- mismatch and do not write the manifest or configuration. Their absent-project refusal tells the
578
- developer to remove the script or not use scaffold writing verbs for a workspace that needs custom
579
- Vitest projects. It does not recommend editing the content-owned configuration that the refusing
580
- verb would restore. An advisory alone does not make an aligned target drift.
588
+ script. For a planned project absent from the gate chains, the advisory reads the manifest after a
589
+ writable script projection. The `scripts` question owns an absent direct `test:<project>` line. The
590
+ `projects` question names the direct script and the gate chain that must invoke it when the projected
591
+ region still leaves the project ungated. When `configs` is selected, `repair` and `overwrite` refuse
592
+ an unregistered or ungated project before writing. Their refusal names the `configs` group, the
593
+ manifest and planned `vite.config.ts` conflict, and the option to exclude `configs` from `--groups`.
594
+ A selection that excludes `configs` proceeds. An advisory alone does not make an aligned target
595
+ drift.
596
+
597
+ Scaffold writes one part of the manifest rather than advising on it: the writable script region.
598
+ `repair` and `overwrite` write every direct `test:<project>` script the blueprint computes,
599
+ `test:probe`, and `test:bench`. A publishing workspace also receives `test:distribution`, `prepack`,
600
+ and `prepublishOnly`. The `test`, `check`, `build`, `dev`, `serve`, `show`, `format`, `lint`, `clean`,
601
+ and `copy` gate chains stay maintainer-owned. A declared value is overwritten only when it is already
602
+ the value being written or is a recognized generated predecessor. The overwrite happens in place,
603
+ so every byte outside the replaced ranges survives. A target's descriptions, keywords, extra
604
+ scripts, and manifest key order survive byte-for-byte. A script the manifest does not declare is
605
+ appended after the last declared one, copying that section's indentation. `catalog` writes no script
606
+ region; it names the ranges alone.
607
+
608
+ A value matching neither is a script the workspace author wrote. The region writer retains that
609
+ value byte-for-byte and reports its name, declared value, and planned value. Each other planned
610
+ script is decided independently: an absent script appends, the planned value stands, and an accepted
611
+ predecessor upgrades in place. Extra scripts remain byte-identical. A planned key holding a
612
+ non-string value or a `scripts` field that is not an object still refuses the whole region with no
613
+ script byte moving. `audit` reports absent and differing scripts separately in its non-blocking
614
+ `scripts` question, and the terminal audit in `repair` and `overwrite` keeps every retained
615
+ difference visible. Other selected writes still proceed. The `projects` question reports only a
616
+ direct script the manifest declares but the maintainer-owned gate chain does not invoke after
617
+ projection.
581
618
 
582
619
  The same plan-reading verbs compare the tooling set the derived blueprint plans against
583
620
  `dependencies` and `devDependencies` together. A missing planned package produces one non-blocking
@@ -585,9 +622,43 @@ The same plan-reading verbs compare the tooling set the derived blueprint plans
585
622
  order. The comparison measures membership: a workspace-owned extra is outside it, a planned tool may
586
623
  live in either section, and how current a declared range is belongs to the registry evidence
587
624
  Dependency floors describes rather than to this question. A present section that is not an object
588
- produces a question instead of a crash. `audit` reports the question without changing its exit
589
- semantics. `repair` and `overwrite` refuse before writing configuration, and no verb edits the
590
- birth-owned `package.json`.
625
+ produces a question instead of a crash. This question belongs to `configs` and `tests`. `audit`
626
+ reports it only when its selection includes either group, without changing its exit semantics.
627
+ `repair` and `overwrite` refuse before writing a selected `configs` or `tests` group. A selection
628
+ that excludes those groups proceeds, and no verb adds the declaration for you: `package.json` is
629
+ birth-owned, and the range and script regions are the only parts of it a verb rewrites.
630
+
631
+ `audit` reports one further non-blocking question, on the `setup` field, and it alone reports it.
632
+ The question fires when the target carries a filled root `tests/setup*.ts` module that is neither a
633
+ proof itself nor one of the vendored modules every target receives, while no proof of the same stem
634
+ covers it. A module counts as filled when its text differs from the seed this blueprint plans at
635
+ that same path.
636
+
637
+ The comparison reads the module and the seed trimmed, so surrounding whitespace decides nothing: a
638
+ trailing newline is not authorship, and a module holding whitespace alone reads as empty rather than
639
+ as filled. It is seed-relative rather than a test for emptiness, because the seeds differ by path:
640
+ `tests/setup.ts` is seeded with the empty string and `tests/setupGlobal.ts` is seeded with a `setup`
641
+ function body. A test for emptiness therefore raises the question against a freshly materialized
642
+ workspace. Holding each module to the seed the same blueprint plans at its own path reports what a
643
+ maintainer wrote rather than what scaffold seeded.
644
+
645
+ That reading carries a release-skew limit. A seeded setup module is birth-owned, so `repair` reports
646
+ it aligned and never rewrites it. A target keeps the seed of the release that materialized it. When
647
+ a release moves a planned seed, scaffold raises the question on every target materialized before it,
648
+ against a module scaffold wrote and no maintainer touched. `audit` compares each setup module only
649
+ with the seed the installed release plans, and it retains no earlier seed bytes.
650
+ `tests/setupGlobal.ts` is the module that can meet it, because it is the one seeded with more than
651
+ the empty string. A maintainer meeting that question closes it by writing the proof it asks for, or
652
+ by taking the seed the installed release plans.
653
+
654
+ Coverage is read per module: `tests/<name>.ts` is covered by `tests/<name>.test.ts` and by nothing
655
+ else, which is the pairing the vendored policy proof resolves. Writing one proof retires that module
656
+ and leaves every other uncovered module named, and the message pairs each module it names with the
657
+ proof that module wants. The question belongs to the `tests` group, so a scoped audit that excludes
658
+ `tests` omits it. Scaffold does not write the proof it asks for, and no writing verb raises the
659
+ question: a writing verb refuses the advisories it reports, and refusing `repair` over this one
660
+ would block every write on a gap no write can close. Run across a fleet, the question is the list of
661
+ packages carrying a filled setup module that no proof covers.
591
662
 
592
663
  ### Exit codes
593
664
 
@@ -676,12 +747,12 @@ One published environment owns the package root directly. Several published envi
676
747
  never runs. The gate reports that as a non-blocking `src` question rather than refusing the compile,
677
748
  because the shape is chosen once and read afterwards: `new` refuses the advisory, while `audit` and
678
749
  `repair` need the plan to describe and restore a target that already has that shape. A library
679
- caller creating a workspace holds the same refusal, and the Compile section below states it.
750
+ caller creating a workspace holds the same refusal, and the Compile section states it.
680
751
 
681
- `bin`, `setup`, `guides`, `distribution`, `integration`, `conformance`, `service`, `vendors`,
682
- `global`, and `showcase` are structural facts. Each is set only when the workspace physically ships
683
- the directory or exact-case file that defines it, never because of the workspace's name and never
684
- because a sibling fact is set.
752
+ `bin`, `setup`, `guides`, `integration`, `conformance`, `service`, `vendors`, `global`, and
753
+ `showcase` are structural facts. Each is set only when the workspace physically ships the directory
754
+ or exact-case file that defines it, never because of the workspace's name and never because a
755
+ sibling fact is set.
685
756
 
686
757
  `setup` registers every root `tests/setup*.test.ts` proof in one Node project that loads
687
758
  `tests/setup.ts`. A nested or wrong-case match does not set the fact. The generated manifest emits
@@ -693,18 +764,19 @@ generated before that file existed and still registers no `integration` project,
693
764
  fails with `integration has no project factory or configuration` until a plan-writing verb
694
765
  regenerates it.
695
766
 
696
- `repair` alone does not close that, and refusing is correct rather than a gap. `package.json` is
697
- birth-owned, so the verb cannot add the project's script, and it will not register a project the
698
- manifest reaches from no gate. It exits 1 naming the target and writes nothing.
767
+ `repair` closes the direct-script half through the writable manifest region. It still refuses to
768
+ register a project that the maintainer-owned gate chains do not reach.
699
769
 
700
- Adding a structural proof is therefore these steps, in order: write the file; declare its
701
- `test:<project>` script and invoke that script from a gate chain; then run `repair`, which
702
- regenerates the root configuration and registers the project. `audit` reports whichever piece is
703
- still outstanding at each step.
770
+ When you add a structural proof, write the file and invoke its planned `test:<project>` script from
771
+ a gate chain. Then run `repair`; it appends the direct script, regenerates the root configuration,
772
+ and registers the project. `audit` reports whichever piece is still outstanding at each step.
704
773
 
705
- `distribution` projects only when the workspace also publishes at least one `src` environment. It
706
- packs and installs the published artifact, so without that axis there is nothing to pack, and the
707
- declared flag alone adds no project, no `test:distribution` script, and no gate entry.
774
+ `distribution` is not a field at all. A published `src` environment is its whole condition, read
775
+ from the `src` axis the blueprint already carries. The proof packs and installs the published
776
+ artifact, so a workspace publishing none has nothing for it to read and gets no project, no
777
+ `test:distribution` script, and no gate entry. A workspace publishing any gets the project, the
778
+ script, the `prepublishOnly` entry, and `tests/distribution.test.ts` itself. Limits states why this
779
+ is the one proof scaffold generates from the workspace's own shape.
708
780
 
709
781
  `service` says the workspace runs a live-service Vitest project over `tests/service`, and it alone
710
782
  registers that project, its `test:service` script, and the `tests/setupService.ts` readiness module
@@ -786,7 +858,8 @@ place, and the caller that picked the shape is the one holding it.
786
858
  Off-contract input is different. A value that is not the exact shape raises `ScaffoldError` coded
787
859
  `INVALID`, because it is not a question anyone can answer. Each entry point snapshots the caller's
788
860
  value first and then guards the snapshot, so a property backed by an accessor is refused rather than
789
- read.
861
+ read. `isPlan` refuses an artifact at `package.json` unless it carries `birth` ownership, because a
862
+ plan claiming `content` or `presence` there contradicts the compiler-produced plan.
790
863
 
791
864
  Overrides replace a drafted artifact's content whole. The gate checks each override against the
792
865
  blueprint's full draft before a group selection narrows the returned plan, so an override outside a
@@ -828,10 +901,23 @@ content is produced. `Ownership` says what scaffold claims at the path.
828
901
 
829
902
  Presence ownership has separate mechanisms, and a reader needs to know which applies:
830
903
 
831
- | Mechanism | Paths | Bytes belong to | Cost |
832
- | --------------- | ------------------------------------------------- | --------------------- | ------------------------------------------------------- |
833
- | Verb-owned | `CATALOG_AGENT_PATH` and dependency guide mirrors | `catalog` or `mirror` | The owning verb is the only route for a later update. |
834
- | Workspace-owned | `WORKSPACE_OWNED_PATHS`, which holds `.gitignore` | The target workspace | Present bytes receive no later canonical ignore update. |
904
+ | Mechanism | Paths | Bytes belong to | Cost |
905
+ | --------------- | ------------------------------------------------- | -------------------------------------------- | ----------------------------------------------------------- |
906
+ | Verb-owned | `CATALOG_AGENT_PATH` and dependency guide mirrors | `catalog` or `mirror` | The owning verb is the only route for a later update. |
907
+ | Workspace-owned | `WORKSPACE_OWNED_PATHS`, which holds `.gitignore` | The target workspace | Present bytes receive no later canonical ignore update. |
908
+ | Plan-owned | `DISTRIBUTION_TEST_PATH` | The plan, until the workspace writes its own | A deleted file is restored from the plan on the next write. |
909
+ | Unhydrated | Every vendored path a core-compiled plan carries | Scaffold, after a hydrating face reads them | Hydration restores the byte claim the core plan omits. |
910
+
911
+ The unhydrated row is the one a core-only caller meets most, and reading it as a claim about the
912
+ path is the mistake it invites. `Compiler` runs in the pure core face, which cannot read the
913
+ vendored data root, so every host artifact it plans carries `presence`: a claim over bytes nobody
914
+ has read is a claim no comparison could check. A `src: ['core']` plan therefore reports `presence`
915
+ for `AGENTS.md`, `.claude/settings.json`, `tests/policy.test.ts`, and every other vendored path, and
916
+ a consumer concluding from that reading that scaffold never replaces those bytes is wrong.
917
+ `Materializer` hydrates the plan before it audits or writes: hydration reads the vendored root and
918
+ turns each path scaffold owns the bytes of into a content-owned artifact, leaving `presence` on the
919
+ workspace-owned paths and the mirror pointers the preceding rows name. What a verb claims at a
920
+ vendored path is the hydrated ownership, and `HostArtifact` carries the same narrowing on the type.
835
921
 
836
922
  Birth ownership is what makes a generated workspace the consumer's. `materialize` writes a
837
923
  birth-owned path into a vacant target. A later `repair` or `overwrite` call treats that path as
@@ -842,16 +928,29 @@ You own `tests/setup.ts`, the selected `tests/setupBrowser.ts`, `tests/setupServ
842
928
  `tests/setupService.ts`, and `tests/setupGlobal.ts` modules, each root `tests/setup*.test.ts` proof,
843
929
  the selected environment entry tests under `tests/src` and `tests/app`, the
844
930
  `tests/src/bin/main.test.ts` file, and the `tests/integration.test.ts` seed. Scaffold writes those
845
- planned files only during materialize and leaves later edits or deletions alone. You also own the `tests/guides.test.ts`,
846
- `tests/distribution.test.ts`, `tests/conformance.test.ts`, and `tests/service/**/*.test.ts` proof
847
- files that you add to select their projects. Scaffold content-owns `tests/setupPolicy.ts`,
931
+ planned files only during materialize and leaves later edits or deletions alone. You also own the
932
+ `tests/guides.test.ts`, `tests/conformance.test.ts`, and `tests/service/**/*.test.ts` proof files,
933
+ each of which selects its project by being written. Scaffold content-owns `tests/setupPolicy.ts`,
848
934
  `tests/policy.test.ts`, and `tests/config.test.ts`; `repair` and `overwrite` restore those files when
849
935
  their bytes drift or the files are missing.
850
936
 
851
- Content ownership does not preserve an arbitrary custom Vitest project. Fixed optional proofs are
852
- selected by their defining paths, as `guides`, `distribution`, `integration`, `conformance`, and
853
- `service` are. A workspace that needs other local configuration must keep those edits outside a
854
- content-owned file; `repair` restores that file to the canonical project set.
937
+ `tests/distribution.test.ts` is the one proof scaffold generates, and the one test artifact it
938
+ claims by presence. Generation is the line, not writing: scaffold writes the vendored
939
+ `tests/policy.test.ts` and `tests/config.test.ts` proofs too, and restores them, but those are the
940
+ shared file set's own bytes copied into the target. The distribution proof is derived from the
941
+ workspace's own shape instead, which is why it is the one proof a generated file can be. A
942
+ publishing workspace missing that file reports `missing` drift, and `repair` or `overwrite` writes
943
+ the generated proof there. A workspace that replaced the generated proof with a better one keeps its
944
+ own bytes exactly: presence compares existence, so no verb reads what is already at the path, none
945
+ replaces it, and none ever reports it stale. Deleting the file is how you ask for the generated
946
+ proof back; editing it is how you keep your own. Limits states what makes this proof generable when
947
+ the others are not.
948
+
949
+ Content ownership does not preserve an arbitrary custom Vitest project. The optional proof projects
950
+ are fixed: `guides`, `integration`, `conformance`, and `service` are selected by their defining
951
+ paths, and `distribution` by a published `src` environment. A workspace that needs other local
952
+ configuration must keep those edits outside a content-owned file; `repair` restores that file to the
953
+ canonical project set.
855
954
 
856
955
  An audit reports one `Finding` per planned path, followed by any foreign path beneath the groups
857
956
  the plan covers. Every planned finding carries its artifact's `ownership`. A foreign finding has
@@ -938,12 +1037,18 @@ lookup verdict records why the registry row could not enter a layer.
938
1037
 
939
1038
  ## Dependency floors
940
1039
 
941
- Every scaffold-owned range from its dependency tables is a floor: a caret over a whole
1040
+ Every scaffold-owned runtime or development range is a floor: a caret over a whole
942
1041
  `major.minor.patch` version. The triple is the newest release the registry served when that floor
943
1042
  was last raised, so a workspace generated with no network still receives the latest floor scaffold
944
- knew rather than a bare `major.0.0`. Caller extras and peers pass through unchanged. Extras follow
945
- `EXTRA_RANGE_PATTERN`; fleet peers follow `ORKESTREL_RANGE_PATTERN`; foreign peers follow
946
- `FLOOR_RANGE_PATTERN`.
1043
+ knew rather than a bare `major.0.0`. A `Blueprint.peers` row is written during creation into a
1044
+ vacant target. After creation, peer declarations and `peerDependenciesMeta` are caller-owned:
1045
+ `audit`, `repair`, `catalog`, and `overwrite` do not invent, rewrite, insert, or remove them. Caller
1046
+ extras also pass through unchanged. Extras follow `EXTRA_RANGE_PATTERN`; fleet peers follow
1047
+ `ORKESTREL_RANGE_PATTERN`; foreign peers follow `FLOOR_RANGE_PATTERN`.
1048
+
1049
+ The distribution project packs a caller-owned peer beside a co-peer witness that requires an exact
1050
+ version. The real npm resolver accepts the preserved range. Its narrowed-range control reports
1051
+ `ERESOLVE`.
947
1052
 
948
1053
  The floors live in scaffold's own `package.json`. `BASE_DEV_DEPENDENCIES` and the tables beside it
949
1054
  derive each row scaffold installs from that manifest, and the self-pin from its `version` field, so
@@ -1083,9 +1188,9 @@ A workspace's file set is a function of its axes plus its structural facts. Noth
1083
1188
  except the manifest.
1084
1189
 
1085
1190
  - One computed artifact: `package.json`, with the entry points, `exports` map, scripts, and
1086
- development dependencies its selection implies. A publishing manifest carries
1087
- `"prepack": "npm run build"` so a publish rebuilds `dist/` and cannot ship a stale artifact;
1088
- the hook is publish-time only, and every generated distribution proof passes
1191
+ development dependencies its selection implies. In publishing workspaces, the emitted `prepack`
1192
+ script runs `npm run build` so a publish rebuilds `dist/` and cannot ship a stale artifact; the
1193
+ hook is publish-time only, and every generated distribution proof passes
1089
1194
  `--ignore-scripts` to `npm pack` so a suite never re-runs the build it already gates.
1090
1195
  - One template artifact per configuration file the selection needs: the root `tsconfig.json` and
1091
1196
  `vite.config.ts`, plus a Vite config and a scoped TypeScript config per selected environment and
@@ -1107,6 +1212,12 @@ except the manifest.
1107
1212
  integration selection also emits a birth-owned `tests/integration.test.ts` seed that imports each
1108
1213
  selected public barrel and records its initial empty exports for the consumer to replace with an
1109
1214
  observable cross-environment flow.
1215
+ - One template artifact, `tests/distribution.test.ts`, for a workspace publishing any `src`
1216
+ environment. It is the packed-package proof, and it is claimed by presence rather than birth, so a
1217
+ workspace that replaces it keeps its replacement. A published browser environment adds the
1218
+ real-browser stage to it: the stage bundles the installed package with the workspace's own
1219
+ `configs/browsers.ts` resolution, serves the bundle over a loopback server, and drives it in
1220
+ Playwright Chromium.
1110
1221
  - One template artifact each for `README.md` and `guides/README.md`.
1111
1222
  - One host artifact per vendored path the workspace selects. A vendored directory is one planned
1112
1223
  path that expands into the files the data root stores beneath it.
@@ -1317,32 +1428,157 @@ nothing. This is deliberate: a generated sample entity is repeatedly mistaken fo
1317
1428
  implementation. What a consumer does first is write the module's `types.ts`, then the
1318
1429
  implementation that conforms to it, then export both from the barrel — the order `AGENTS.md` fixes.
1319
1430
 
1320
- **A selected distribution, conformance, or live-service proof is registered, but none is written for
1321
- you.** Scaffold registers `conformance` and `service` when their structural facts are set, and
1322
- registers `distribution` only when the workspace also publishes `src`. In a publishing workspace,
1323
- `distribution` and `service` run from `prepublishOnly` and `conformance` stays in `test`. In a
1324
- `private: true` workspace, `distribution` is absent, `service` runs from `test`, and there is no
1325
- `prepublishOnly` at all. Scaffold emits no proof into any registered project, because each names
1326
- something only the package knows: the behavior its own packed artifact must hold after it is
1327
- installed, the official artifact a conformance check measures against, and the service a live proof
1328
- drives. A generated placeholder would read as a proof while measuring nothing, so the file a
1329
- consumer writes is the file that selects the project.
1330
-
1331
- A distribution proof carries one contract scaffold does enforce from the outside. The generated
1332
- `prepublishOnly` invokes it as `npm run test:distribution -- --mode release`, and a proof that reads
1333
- `import.meta.env.MODE === 'release'` must **fail** on an unreachable registry rather than skip. An
1334
- ordinary local run may skip that case, because a developer offline is not a defect; a release run
1335
- may not, because skipping there passes the publish gate without ever proving the artifact installs.
1336
- Scaffold writes no proof, so honouring the flag is the consumer's, and a proof that ignores it
1337
- reports green on exactly the runs that matter.
1338
-
1339
- The consequence is one empty-project case per registered proof. A publishing blueprint carrying
1340
- `distribution` with no `tests/distribution.test.ts`, or any blueprint carrying `conformance` with no
1341
- `tests/conformance.test.ts`, registers a project whose include resolves to nothing, and Vitest exits
1342
- non-zero on it. A blueprint carrying `service` gets `tests/setupService.ts` the root configuration
1343
- names that module by path, so an absent one fails the project's load rather than its run — and still
1344
- no suite beneath `tests/service`, so `test:service` reports no test files until the consumer writes
1345
- the first one. Every case is visible the first time the script runs, which is why none is silent.
1431
+ **Scaffold generates the distribution proof and refuses to generate every other one.** The subject
1432
+ is what separates them, and it is the whole rule. Generating a file is not the same as writing one:
1433
+ scaffold also writes `tests/policy.test.ts` and `tests/config.test.ts` into a target, byte for byte
1434
+ from the shared file set, and the distribution proof is the one it derives from the workspace it is
1435
+ writing into.
1436
+
1437
+ A distribution proof's every assertion derives from the artifact the workspace installs: the
1438
+ `exports` map the packed tarball declares, the built declarations beside it, and the module objects
1439
+ a Node import, a CommonJS require, and a real browser hand back from that installed tree. Nothing
1440
+ there has to be named, so one generated file measures every publishing workspace, and it stays true
1441
+ as that workspace's published surface moves.
1442
+
1443
+ A guide, conformance, live-service, or setup proof asserts something scaffold cannot read: the API a
1444
+ guide fence claims, the official runner a conformance check measures against, the service a live
1445
+ proof drives, and what a setup module does. That subject is what no generated file can reach, and
1446
+ the claim here is about the subject rather than about every property those files have. A structural
1447
+ property of the same files can be derivable whether each root `tests/setup*.ts` module is
1448
+ reachable from the root configuration is one — and a file asserting it would still leave the
1449
+ module's behavior unmeasured. A generated file there would read as a proof while measuring nothing,
1450
+ which is worse than an absent one. So the file a consumer writes is what selects each of those
1451
+ projects, and `tests/distribution.test.ts` is the one proof scaffold generates for you.
1452
+
1453
+ Registration follows the same split. Scaffold registers `conformance` and `service` when their
1454
+ structural facts are set, and registers `distribution` whenever the workspace publishes at least one
1455
+ `src` environment. In a publishing workspace, `distribution` and `service` run from `prepublishOnly`
1456
+ and `conformance` stays in `test`. In a `private: true` workspace, `distribution` is absent,
1457
+ `service` runs from `test`, and there is no `prepublishOnly` at all. One gap the project set cannot
1458
+ show, `audit` reports directly: a filled `tests/setup*.ts` module that no `tests/setup*.test.ts`
1459
+ proof covers raises the non-blocking `setup` question, which names the modules and the proof to add.
1460
+ Scaffold generates nothing there either, because what that proof asserts is those modules' own
1461
+ behavior, which only the workspace that wrote them can state.
1462
+
1463
+ The generated proof partitions the installed `exports` map rather than sampling it. Every published
1464
+ subpath lands in exactly one of driven, undeclared, or excluded, and a totality assertion holds that
1465
+ partition against the map's own subpath list, so a subpath the proof classifies into none of them
1466
+ reddens instead of disappearing. Another assertion beside it names every driven subpath whose entry
1467
+ resolves no Node target and no browser target: each drive retires itself for such a subpath, so
1468
+ membership of the partition alone would leave one measured by nothing. Together they hold that every
1469
+ published subpath is driven, or is named where the proof cannot drive it.
1470
+
1471
+ A subpath is driven when its entry resolves a declaration, and each measurement resolves that entry
1472
+ under the conditions of the driver taking it rather than under one shared set. The Node ESM runtime
1473
+ resolves `node-addons`, `node`, `import`, and `module-sync`; the Node CommonJS runtime resolves
1474
+ `node-addons`, `node`, `require`, and `module-sync`; Vite's production client build resolves
1475
+ `module`, `browser`, `production`, and `import`. A subpath whose Vite resolution lands under
1476
+ `dist/src/browser/` is driven in a real browser and the Node drives retire for it; every other
1477
+ subpath is imported where the Node ESM set resolves a target and required where the Node CommonJS
1478
+ set resolves one.
1479
+
1480
+ The CommonJS compile probe resolves the declaration under `types`, `node`, and `require`, then reads
1481
+ that declaration's format. TypeScript accepts an existing declaration target directly. Otherwise it
1482
+ substitutes beside the resolved JavaScript target: `.cjs` maps to `.d.cts`, `.mjs` maps to `.d.mts`,
1483
+ and `.js` maps to `.d.ts`. A missing target under `types` leaves that condition unresolved, so the
1484
+ walk continues through the remaining conditions or fallback members. A `.d.cts` declaration admits
1485
+ the subpath. A `.d.mts` declaration refuses it. A `.d.ts` declaration takes the nearest enclosing
1486
+ physical `package.json` file from its own directory: a `"type": "module"` field refuses, while
1487
+ `"type": "commonjs"`, an omitted field, or a manifest that cannot supply a readable field admits.
1488
+ A directory named `package.json` starts no scope, so the walk continues outward. The runtime target
1489
+ does not decide compile membership. The runtime drive separately resolves under `node-addons`,
1490
+ `node`, `require`, and `module-sync`, then loads the subpath whatever declaration format the compile
1491
+ probe found. An invalid non-list target beside a valid CommonJS declaration therefore reaches Node's
1492
+ `ERR_INVALID_PACKAGE_TARGET` failure instead of being dropped during classification.
1493
+
1494
+ The mirror assertion reports a CommonJS typing defect only when the entry's own mapping declares an
1495
+ explicit `require` condition, the Node `require` resolver reaches the entry, and the selected
1496
+ declaration refuses a CommonJS consumer. A `default` branch that merely resolves under the require
1497
+ condition set makes no CommonJS claim.
1498
+
1499
+ Each drive compares against the declaration its own consumer reads, resolved under the conditions
1500
+ TypeScript applies for that resolution and importing format: `types` first and the format's own
1501
+ condition after it, with `node` between them for the `node16` and `nodenext` resolutions and left
1502
+ out for `bundler`, which is the set the browser drive compares against. The import declaration and
1503
+ the require declaration are resolved independently and kept separately on the entry, so a dual
1504
+ subpath is compiled against the declaration each consumer format reads rather than against whichever
1505
+ one answered first. That is what drives a `require`-only subpath declaring its types inside
1506
+ `require`, and what admits a conventional subpath that publishes no `types` condition but ships the
1507
+ adjacent declaration TypeScript substitutes from its runtime target.
1508
+
1509
+ A subpath is undeclared when it resolves no declaration and names a runtime target, which is a
1510
+ defect, because a consumer importing it compiles against nothing under `node16`. A target is a
1511
+ runtime target when its own file name carries no extension at all, or carries `.js`, `.mjs`,
1512
+ `.cjs`, or `.node`. An extensionless target loads, because `require` reads such a file through its
1513
+ JavaScript handler; a `.wasm` target does not, because it carries an extension that is not a
1514
+ JavaScript one. A
1515
+ `.node` target is named beside them because `require` loads a native addon through its own handler
1516
+ rather than the JavaScript one, and the addon publishes names to whatever loads it. The test is the
1517
+ extension the name carries rather than a denylist of asset extensions. Reading the
1518
+ file name rather than the whole path is load-bearing: `./dist/bundle.js/feature` and
1519
+ `./dist/v1.2/index` are modules, and reading the path gets each of them wrong. What the rule
1520
+ excludes is stated where the proof is emitted: an extensionless file published for a reader, such as
1521
+ a `LICENSE` at a subpath, reports undeclared until it is given an extension or a declaration. That
1522
+ is the safe direction: the proof names a subpath it cannot vouch for rather than passing one it
1523
+ never measured.
1524
+
1525
+ A subpath is excluded when it resolves no declaration and names no runtime target: the
1526
+ `./package.json` pointer, a published stylesheet, and a WebAssembly binary are read rather than
1527
+ imported, and the proof names them where it excludes them.
1528
+
1529
+ Classification reads every target the entry names under every condition, and the members of a
1530
+ fallback list with them: Node reads an array in an exports entry as a list of fallbacks, and a
1531
+ reader taking a later member takes a file the installed tree still owes. Node's package-target rules
1532
+ apply inside that list, so a member naming a path outside the package or carrying a `.`, `..`, or
1533
+ `node_modules` segment is skipped rather than resolved or collected: Node falls through to the next
1534
+ member, and no reader can take the one it passed. A standalone target Node rejects the same way is
1535
+ still read and reported, because Node throws on one rather than falling through to anything. So a
1536
+ `require`-only CommonJS subpath carrying no declaration reddens too, and a `.d.ts` or `.d.cts`
1537
+ target never satisfies the runtime-target test, so a types-only condition cannot stand in for a
1538
+ missing declaration.
1539
+
1540
+ A `./*` subpath pattern is read as an ordinary subpath, with no expansion of the `*`, so a pattern
1541
+ naming a runtime target reddens rather than landing in excluded. That is deliberate: excluding the
1542
+ pattern would account for a whole family of published subpaths and measure none of them, which is
1543
+ the silence this partition exists to close. Measuring the family means expanding the pattern against
1544
+ the installed tree and driving each match, which this proof does not do. A maintainer meeting that
1545
+ red is reading the honest answer — the proof does not measure that family — rather than a defect in
1546
+ the proof.
1547
+
1548
+ The proof generated for a workspace publishing no browser face asserts that no browser face exists.
1549
+ That variant drives a Node import and a Node require and carries no browser branch, because the
1550
+ branch follows a published browser face on the `src` axis: the browser drive measures the packed
1551
+ artifact, and only a published face is packed. A workspace that selects `browser` on its `app` axis
1552
+ alone declares `playwright` and `@vitest/browser-playwright` and gets `configs/browsers.ts` emitted,
1553
+ and its proof still carries no branch: the selector reads the `src` axis, and a generated manifest
1554
+ packs `dist/src`, so an application face is neither selected nor packed. The imports the branch
1555
+ needs are declared by either axis, so they do not select the branch. The `vite` import selects
1556
+ nothing either: every workspace declares `vite`, whatever it publishes. In a core-only workspace,
1557
+ those imports resolve to nothing, and emitting the branch there would fail its own `check` and
1558
+ `lint:check` gates. Its Node cases retire themselves for a browser face, so a face published after
1559
+ the file was written would leave nothing measuring it. The assertion reddens instead, and names the
1560
+ subpath a browser branch is owed for. The remedy it carries is to delete the file and run `repair`,
1561
+ which writes the variant that carries the branch — the same route presence ownership already gives
1562
+ you for asking for the generated proof back.
1563
+
1564
+ The generated distribution proof takes its release contract from the outside. The generated
1565
+ `prepublishOnly` invokes it as `npm run test:distribution -- --mode release`, and the proof reads
1566
+ `import.meta.env.MODE === 'release'` and **fails** on an unreachable registry rather than skipping.
1567
+ An ordinary local run skips that case, because a developer offline is not a defect; a release run
1568
+ does not, because skipping there passes the publish gate without ever proving the artifact installs.
1569
+ A workspace that replaces the generated proof takes that contract with it: presence ownership leaves
1570
+ a replacement alone, so a replacement that ignores the flag reports green on exactly the runs that
1571
+ matter.
1572
+
1573
+ The consequence is one empty-project case per refused proof. A blueprint carrying `conformance` with
1574
+ no `tests/conformance.test.ts` registers a project whose include resolves to nothing, and Vitest
1575
+ exits non-zero on it. A blueprint carrying `service` gets `tests/setupService.ts` — the root
1576
+ configuration names that module by path, so an absent one fails the project's load rather than its
1577
+ run — and still no suite beneath `tests/service`, so `test:service` reports no test files until the
1578
+ consumer writes the first one. The `distribution` project no longer has that case: `new` writes the
1579
+ proof into the workspace it registers the project in, and a target that later lost the file reports
1580
+ drift that `repair` closes. Every remaining case is visible the first time the script runs, which is
1581
+ why none is silent.
1346
1582
 
1347
1583
  None of those folds into `integration`, which measures a different axis rather than a smaller
1348
1584
  one: the workspace's selected environments compose through their public barrels. The generated seed