@orkestrel/scaffold 0.0.5 → 0.0.7
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.
- package/dist/bin/scaffold.js +57 -22
- package/dist/bin/scaffold.js.map +1 -1
- package/dist/host/CLAUDE.md +64 -24
- package/dist/host/claude/rules/workspace.md +8 -8
- package/dist/host/guides/src/scaffold.md +178 -94
- package/dist/host/scripts/codex.sh +5 -0
- package/dist/host/tests/setupPolicy.ts +179 -4
- package/dist/src/core/index.cjs +289 -69
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +74 -13
- package/dist/src/core/index.d.ts +74 -13
- package/dist/src/core/index.js +287 -70
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +11 -5
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +4 -2
- package/dist/src/server/index.d.ts +4 -2
- package/dist/src/server/index.js +12 -6
- package/dist/src/server/index.js.map +1 -1
- package/package.json +12 -11
|
@@ -29,7 +29,7 @@ that projection, expressed as data. Rendered defaults ship as versioned package
|
|
|
29
29
|
here rather than a hand edit in every workspace.
|
|
30
30
|
|
|
31
31
|
The module is mechanism, never product policy. The judgment calls — the name, the description, the
|
|
32
|
-
keywords, which src and app environments, which dependencies, any
|
|
32
|
+
keywords, which src and app environments, which dependencies, any artifact override —
|
|
33
33
|
belong to the caller. What this module supplies is the closed vocabularies, the variant matrix as
|
|
34
34
|
data, exact-record validation, a fail-closed gate, a deterministic pin, and lossless projections.
|
|
35
35
|
|
|
@@ -127,49 +127,50 @@ plan.artifacts.some((artifact) => artifact.path === 'app/server/main.ts') // tru
|
|
|
127
127
|
|
|
128
128
|
From [`types.ts`](../../src/core/types.ts).
|
|
129
129
|
|
|
130
|
-
| Name
|
|
131
|
-
|
|
|
132
|
-
| `Environment`
|
|
133
|
-
| `BuildFormat`
|
|
134
|
-
| `SrcDefinition`
|
|
135
|
-
| `AppDefinition`
|
|
136
|
-
| `ViteMachinery`
|
|
137
|
-
| `
|
|
138
|
-
| `
|
|
139
|
-
| `
|
|
140
|
-
| `
|
|
141
|
-
| `
|
|
142
|
-
| `
|
|
143
|
-
| `
|
|
144
|
-
| `
|
|
145
|
-
| `
|
|
146
|
-
| `
|
|
147
|
-
| `
|
|
148
|
-
| `
|
|
149
|
-
| `
|
|
150
|
-
| `
|
|
151
|
-
| `
|
|
152
|
-
| `
|
|
153
|
-
| `
|
|
154
|
-
| `
|
|
155
|
-
| `
|
|
156
|
-
| `
|
|
157
|
-
| `
|
|
158
|
-
| `
|
|
159
|
-
| `
|
|
160
|
-
| `
|
|
161
|
-
| `
|
|
162
|
-
| `
|
|
163
|
-
| `
|
|
164
|
-
| `
|
|
165
|
-
| `
|
|
166
|
-
| `
|
|
167
|
-
| `
|
|
168
|
-
| `
|
|
169
|
-
| `
|
|
170
|
-
| `
|
|
171
|
-
| `
|
|
172
|
-
| `
|
|
130
|
+
| Name | Kind |
|
|
131
|
+
| ------------------------- | --------- |
|
|
132
|
+
| `Environment` | type |
|
|
133
|
+
| `BuildFormat` | type |
|
|
134
|
+
| `SrcDefinition` | interface |
|
|
135
|
+
| `AppDefinition` | interface |
|
|
136
|
+
| `ViteMachinery` | interface |
|
|
137
|
+
| `ViteProjectRegistration` | interface |
|
|
138
|
+
| `Origin` | type |
|
|
139
|
+
| `Group` | type |
|
|
140
|
+
| `Category` | type |
|
|
141
|
+
| `CatalogEntry` | interface |
|
|
142
|
+
| `Drift` | type |
|
|
143
|
+
| `Freshness` | type |
|
|
144
|
+
| `CompileStage` | type |
|
|
145
|
+
| `ScaffoldErrorCode` | type |
|
|
146
|
+
| `Dependency` | interface |
|
|
147
|
+
| `Override` | interface |
|
|
148
|
+
| `Blueprint` | interface |
|
|
149
|
+
| `Member` | interface |
|
|
150
|
+
| `ArtifactBase` | interface |
|
|
151
|
+
| `HostArtifact` | interface |
|
|
152
|
+
| `ContentArtifact` | interface |
|
|
153
|
+
| `Artifact` | type |
|
|
154
|
+
| `Snapshot` | type |
|
|
155
|
+
| `Plan` | interface |
|
|
156
|
+
| `Finding` | interface |
|
|
157
|
+
| `Audit` | interface |
|
|
158
|
+
| `Question` | interface |
|
|
159
|
+
| `Validation` | interface |
|
|
160
|
+
| `GuideSync` | interface |
|
|
161
|
+
| `VersionSync` | interface |
|
|
162
|
+
| `SyncReport` | interface |
|
|
163
|
+
| `PlanSummary` | interface |
|
|
164
|
+
| `CompileRecord` | interface |
|
|
165
|
+
| `CompileFailure` | interface |
|
|
166
|
+
| `Scaffolding` | interface |
|
|
167
|
+
| `PlanRecord` | interface |
|
|
168
|
+
| `CompilerEventMap` | type |
|
|
169
|
+
| `CompilerOptions` | interface |
|
|
170
|
+
| `CompilerInterface` | interface |
|
|
171
|
+
| `PlanManagerEventMap` | type |
|
|
172
|
+
| `PlanManagerOptions` | interface |
|
|
173
|
+
| `PlanManagerInterface` | interface |
|
|
173
174
|
|
|
174
175
|
The closed vocabularies are small and total. `Environment` is `'core' | 'browser' | 'server'`.
|
|
175
176
|
`BuildFormat` is `'es' | 'cjs'`. `Origin` is `'host' | 'template' | 'computed'`. `Group` is
|
|
@@ -190,6 +191,10 @@ single-file-component, HTML, and development-server machinery an application bro
|
|
|
190
191
|
needs, and `output` for build-output containment. It never selects a boundary guarantee — those ship
|
|
191
192
|
in every shape, as the compilers section sets out.
|
|
192
193
|
|
|
194
|
+
`ViteProjectRegistration` carries one generated project factory identifier and its optional browser
|
|
195
|
+
label. Root configuration renderers preserve that browser ownership as data through registration
|
|
196
|
+
instead of inferring it from a project identifier.
|
|
197
|
+
|
|
193
198
|
`Blueprint` is the closed input spec:
|
|
194
199
|
|
|
195
200
|
```ts
|
|
@@ -370,7 +375,9 @@ value lists behind their literal unions. `SRC_MATRIX` is the `src` environment m
|
|
|
370
375
|
data — each environment's `configs/src` files, test-project label, `exports` subpath, and build
|
|
371
376
|
formats. `APP_MATRIX` is its application sibling, adding the runtime entry where an environment produces
|
|
372
377
|
one (`app/browser/index.html`, `app/server/main.ts`). `HOST_PATHS` is the ordered list of
|
|
373
|
-
byte-copied host artifacts
|
|
378
|
+
byte-copied host artifacts, and it is the staging manifest rather than the per-plan carried set:
|
|
379
|
+
`stageHost` vendors every path on it, while each plan carries the subset `selectHostPaths` selects
|
|
380
|
+
for that one workspace.
|
|
374
381
|
|
|
375
382
|
The bounds are public because they are part of the contract, not implementation trivia.
|
|
376
383
|
`MAX_ARTIFACT_BYTES` caps one artifact at 5 MiB and `MAX_TOTAL_ARTIFACT_BYTES` caps one blueprint,
|
|
@@ -544,7 +551,8 @@ entity allocation.
|
|
|
544
551
|
then checks every override against the exact artifact set the plan would write. An override whose
|
|
545
552
|
`path` matches no planned artifact, targets a `host`-origin artifact, or targets the
|
|
546
553
|
blueprint-owned `package.json` publication boundary is a blocking question rather than a silent
|
|
547
|
-
no-op.
|
|
554
|
+
no-op. An override that clears all three lands a `warnings` entry naming the path it replaces — the
|
|
555
|
+
declaration is accepted, and it is never accepted silently.
|
|
548
556
|
|
|
549
557
|
### Validators — server
|
|
550
558
|
|
|
@@ -736,11 +744,13 @@ From [`helpers.ts`](../../src/core/helpers.ts).
|
|
|
736
744
|
| `contentByteLength` | function |
|
|
737
745
|
| `contentToHex` | function |
|
|
738
746
|
| `snapshotOf` | function |
|
|
747
|
+
| `selectHostPaths` | function |
|
|
739
748
|
| `findPathConflict` | function |
|
|
740
749
|
| `findFileConflict` | function |
|
|
741
750
|
| `validateDependencyArray` | function |
|
|
742
751
|
| `validateBlueprint` | function |
|
|
743
752
|
| `manifestToDependencies` | function |
|
|
753
|
+
| `manifestToName` | function |
|
|
744
754
|
| `rangeToFreshness` | function |
|
|
745
755
|
| `computeHash` | function |
|
|
746
756
|
| `stableStringify` | function |
|
|
@@ -786,14 +796,20 @@ report projections count with.
|
|
|
786
796
|
`snapshotOf`, `contentToHex`, `contentToBytes`, `contentByteLength`, `contentCodePoint`, and
|
|
787
797
|
`bytesToHex` are the host-independent byte leaves that make exact comparison possible without a
|
|
788
798
|
host encoder or buffer; an unpaired surrogate encodes as `U+FFFD` rather than throwing.
|
|
789
|
-
`
|
|
790
|
-
|
|
799
|
+
`selectHostPaths` is the one-owner filter plan assembly applies before it carries anything: it
|
|
800
|
+
returns the host paths in input order minus `guides/src/<name>.md`, so a workspace never plans a
|
|
801
|
+
vendored mirror of the guide it writes itself. `findPathConflict` finds the first exact or
|
|
802
|
+
case-insensitive collision in a path list, and `findFileConflict` additionally rejects a file that
|
|
803
|
+
would sit inside another planned path — the loud backstop behind that selection.
|
|
791
804
|
|
|
792
805
|
`validateBlueprint` and `validateDependencyArray` are the semantic pass. The array validator is
|
|
793
806
|
pure — it returns its questions and the set of names it saw, so the caller can apply the
|
|
794
807
|
cross-array overlap rules on top. `manifestToDependencies` reads a manifest's `dependencies`,
|
|
795
808
|
`devDependencies`, and `peerDependencies` in that order, keeps only own data sections and scoped
|
|
796
|
-
names, deduplicates, and never throws. `
|
|
809
|
+
names, deduplicates, and never throws. `manifestToName` is its self-reading sibling over the same
|
|
810
|
+
text: the manifest's own string `name`, or `undefined` when the text is oversized, malformed,
|
|
811
|
+
rootless, or nameless — the projection that lets a target recognize itself in its own declared
|
|
812
|
+
dependencies. `rangeToFreshness` applies the exact-pin comparison; the `missing` and `failed`
|
|
797
813
|
verdicts come from the fetch layer, never from this pure comparison.
|
|
798
814
|
|
|
799
815
|
`computeHash` is a deterministic FNV-1a digest and `stableStringify` a key-order-independent
|
|
@@ -904,7 +920,9 @@ dependency-less stand-in. Environments come from `src/<environment>/` and `app/<
|
|
|
904
920
|
scoped entries, with an optional peer recovered from `peerDependenciesMeta`; and `extras` is every
|
|
905
921
|
development dependency minus the generated baseline and minus anything already declared as a
|
|
906
922
|
dependency or peer, so a hand-added development dependency round-trips and stays audit-clean.
|
|
907
|
-
`overrides
|
|
923
|
+
Derivation yields no `overrides`: they are caller-time inputs, not repository state. A computed
|
|
924
|
+
artifact that must differ reveals a gap in the canon; the blueprint grows an axis for that
|
|
925
|
+
distinction rather than the repository forking the file.
|
|
908
926
|
|
|
909
927
|
`storagePath`, `stageHost`, `readHostManifest`, `locateHostSource`, `remapArtifactPath`, and
|
|
910
928
|
`hydratePlan` are the vendored-host path. `storagePath` maps a repo-relative path to its un-dotted
|
|
@@ -926,7 +944,9 @@ anything.
|
|
|
926
944
|
`consumeCatalogAllowance` decrements the single shared entry allowance and throws `TARGET` before an
|
|
927
945
|
over-budget traversal continues. `discoverPackages` requires a real, unlinked root and lists its
|
|
928
946
|
immediate child directories whose bounded manifest names a scoped package, skipping anything else
|
|
929
|
-
silently.
|
|
947
|
+
silently. A control-bearing child directory fails closed before its manifest is read and the
|
|
948
|
+
untrusted name is never reflected in the diagnostic. `catalogPackages` applies one allowance across
|
|
949
|
+
every root and directory rather than
|
|
930
950
|
resetting a per-root budget, then draws each description from the first paragraph of the first
|
|
931
951
|
blockquote of that package's own bounded guide via `guideToDescription`; a missing guide, an
|
|
932
952
|
unreadable or oversized one, or one with no blockquote yields an empty description rather than an
|
|
@@ -954,6 +974,7 @@ From [`compilers.ts`](../../src/core/compilers.ts).
|
|
|
954
974
|
| `packageManifest` | function |
|
|
955
975
|
| `rootTsconfig` | function |
|
|
956
976
|
| `viteMachinery` | function |
|
|
977
|
+
| `renderViteTest` | function |
|
|
957
978
|
| `viteHeader` | function |
|
|
958
979
|
| `policyViteProject` | function |
|
|
959
980
|
| `singleSrcViteConfig` | function |
|
|
@@ -994,7 +1015,13 @@ optional metadata, and engines.
|
|
|
994
1015
|
|
|
995
1016
|
`rootTsconfig` emits the root compiler options and one path alias per declared environment;
|
|
996
1017
|
`coreTsconfig`, `srcTsconfig`, and `appTsconfig` emit the scoped configurations that remove the
|
|
997
|
-
wrong host's globals from each environment.
|
|
1018
|
+
wrong host's globals from each environment. A core scope is the interesting one: `lib` is
|
|
1019
|
+
`["ESNext", "WebWorker"]` and `types` stays `[]`, which declares the WHATWG surface that is
|
|
1020
|
+
identical across Node, browsers, and workers — `fetch` and its request/response/header types,
|
|
1021
|
+
streams, `URL`, `AbortController`, the text encoders, `crypto`, timers, `console`, `DOMException`,
|
|
1022
|
+
`structuredClone` — while leaving `document`, `window`, and every `node:*` type unresolvable. That
|
|
1023
|
+
is one declaration set for a host-independent module, not a host. `viteHeader` renders the shared
|
|
1024
|
+
header — the alias block
|
|
998
1025
|
derived from the tsconfig paths, plus the environment-boundary plugin — and `viteMachinery` is the
|
|
999
1026
|
one place the header's axes are derived, read by `rootViteConfig`, `singleSrcViteConfig`,
|
|
1000
1027
|
`applicationViteConfig`, and `configArtifacts` alike so no caller can invent a fourth answer.
|
|
@@ -1006,7 +1033,8 @@ emits `environmentBoundary`, its `resolveId` / `load` / `buildEnd` walks, the mo
|
|
|
1006
1033
|
plus its `environmentPathError` / `environmentSourceError` clauses). Those enforce owner-independent
|
|
1007
1034
|
laws: core stays host-independent whatever else the workspace declares, a server module never
|
|
1008
1035
|
imports a stylesheet, and a `@vite-ignore` dynamic import — which `resolveId` never sees and the
|
|
1009
|
-
module graph never records — has no other enforcement point
|
|
1036
|
+
module graph never records — has no other enforcement point in workspace-owned source. Dependency
|
|
1037
|
+
and toolchain modules are outside that ownership boundary. Only host-specific pipelines vary,
|
|
1010
1038
|
along the three `ViteMachinery` axes:
|
|
1011
1039
|
|
|
1012
1040
|
| Machinery | Emitted when |
|
|
@@ -1019,6 +1047,10 @@ along the three `ViteMachinery` axes:
|
|
|
1019
1047
|
An application of `app/core` alone is the sole shape that builds nothing, so it is the sole shape
|
|
1020
1048
|
without output containment — and it still carries every boundary guarantee above.
|
|
1021
1049
|
|
|
1050
|
+
`renderViteTest` is the single root-project renderer. It consumes ordered
|
|
1051
|
+
`ViteProjectRegistration` data and emits either the plain project list or the browser gate, keeping
|
|
1052
|
+
source and application root configurations byte-consistent without reconstructing browser ownership.
|
|
1053
|
+
|
|
1022
1054
|
`coreViteConfig`, `srcViteConfig`, and `appViteConfig` emit the thin per-target wrappers;
|
|
1023
1055
|
`rootViteConfig`, `singleSrcViteConfig`, and `applicationViteConfig` emit the root configuration for
|
|
1024
1056
|
a library-only, single non-core `src` environment, and application-bearing workspace respectively;
|
|
@@ -1125,8 +1157,9 @@ The public methods of each behavioral interface, one table per type.
|
|
|
1125
1157
|
`Scaffolding`; the optional group selection scopes the plan to those artifact groups.
|
|
1126
1158
|
`audit(blueprint, current, groups?)` compiles and then diffs the resulting plan against the
|
|
1127
1159
|
caller-supplied current content; a gated blueprint returns `complete: false` with the gate's
|
|
1128
|
-
blocking questions and zero findings
|
|
1129
|
-
exposes the readonly
|
|
1160
|
+
blocking questions and zero findings, and a complete one carries the gate's advisories on that same
|
|
1161
|
+
`questions` field. `destroy()` is idempotent teardown. The interface also exposes the readonly
|
|
1162
|
+
`emitter`.
|
|
1130
1163
|
|
|
1131
1164
|
#### `PlanManagerInterface`
|
|
1132
1165
|
|
|
@@ -1190,12 +1223,14 @@ in-flight request. The interface also exposes the readonly `emitter`.
|
|
|
1190
1223
|
`compile` runs three stages in fixed order and records each as a `CompileRecord` carrying its input,
|
|
1191
1224
|
its output, whether it failed, and any error text.
|
|
1192
1225
|
|
|
1193
|
-
1. **draft** — `blueprintToPlan` selects the covered groups, drafts each group's artifacts,
|
|
1194
|
-
the host set
|
|
1226
|
+
1. **draft** — `blueprintToPlan` selects the covered groups, drafts each group's artifacts, carries
|
|
1227
|
+
the selected host set — every vendored host path except the workspace's own guide — applies
|
|
1228
|
+
overrides, and pins the draft. A throw here records a `draft` failure coded
|
|
1195
1229
|
`INVALID`, emits `error`, marks the remaining two stages skipped, and returns incomplete.
|
|
1196
1230
|
2. **gate** — `validatePlan` runs the semantic pass over the blueprint and checks every override
|
|
1197
|
-
against the drafted artifact set. Blocking questions fail the stage;
|
|
1198
|
-
vendored guide set
|
|
1231
|
+
against the drafted artifact set. Blocking questions fail the stage; an accepted override and a
|
|
1232
|
+
dependency outside the vendored guide set each contribute a non-blocking advisory question
|
|
1233
|
+
instead.
|
|
1199
1234
|
3. **pin** — a host-origin pointer artifact is appended for each non-vendored dependency, and
|
|
1200
1235
|
`pinPlan` fills `trace` and `hash` from the plan's own content.
|
|
1201
1236
|
|
|
@@ -1227,7 +1262,8 @@ how it is audited, and whether it may ever be overwritten.
|
|
|
1227
1262
|
- **`host`** — byte-copied from the vendored data root. These are the shared files a whole fleet
|
|
1228
1263
|
keeps identical: the root instruction documents and licence, the agent, rule, and skill
|
|
1229
1264
|
directories, the session scripts, the repository coding-law policy module, the byte-identical root
|
|
1230
|
-
dotfiles, and the two guide mirrors
|
|
1265
|
+
dotfiles, and the two line guide mirrors a workspace carries for contracts other than its own.
|
|
1266
|
+
`HOST_PATHS` is the exact vendored list; what a given plan carries is `selectHostPaths` of it.
|
|
1231
1267
|
- **`template`** — filled from a frozen template definition by a pure fill engine. These are
|
|
1232
1268
|
starter files: source stubs, test stubs, the starter guide, the README.
|
|
1233
1269
|
- **`computed`** — derived by this package's own combination logic. These are the structural files:
|
|
@@ -1256,18 +1292,31 @@ anything, so a mature workspace's hand-written source, tests, guides, and manife
|
|
|
1256
1292
|
overwritten with a stub. A consequence worth stating plainly: the generated
|
|
1257
1293
|
`.github/workflows/ci.yml` is a **computed** artifact, so **user-owned CI is never repaired**. Once
|
|
1258
1294
|
a workspace has its own workflow, that copy stands, and any change to it is an ordinary edit in that
|
|
1259
|
-
workspace.
|
|
1295
|
+
workspace. Audit still compares it because computed artifacts are content-aware canon. A legitimate
|
|
1296
|
+
difference that the blueprint cannot express is a canon gap: add the missing blueprint axis rather
|
|
1297
|
+
than forking the computed file in one repository.
|
|
1260
1298
|
|
|
1261
1299
|
Overrides respect the same boundary from the other direction. `applyOverrides` never replaces a
|
|
1262
1300
|
host-origin artifact and never replaces `package.json`; the gate turns either attempt — and an
|
|
1263
1301
|
override matching no planned artifact at all — into a blocking question rather than a silent no-op.
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1302
|
+
What survives those three refusals is applied and announced: the gate carries a non-blocking
|
|
1303
|
+
advisory naming each replaced path, and that advisory rides the `Scaffolding` and the `Audit` all
|
|
1304
|
+
the way through the library result.
|
|
1305
|
+
|
|
1306
|
+
Guide mirrors are the one place ownership is conditional, and the law is one owner per guide path.
|
|
1307
|
+
**A workspace mirrors every line guide except its own.** When the name matches — the guide package
|
|
1308
|
+
on `guides/src/guide.md`, this package on `guides/src/scaffold.md` — the workspace itself is the
|
|
1309
|
+
owner, keeping that path as its **template**-origin starter guide, and `selectHostPaths` drops the
|
|
1310
|
+
vendored mirror so the path is contributed exactly once. For every other contract the mirror is the
|
|
1311
|
+
owner: a dependency this package vendors a byte-identical mirror for gets a real host-origin copy of
|
|
1312
|
+
`guides/src/<short>.md`, contributed once whether it arrives through the host set or through the
|
|
1313
|
+
dependency, so a package depending on `@orkestrel/guide` plans one `guides/src/guide.md` rather than
|
|
1314
|
+
two. Any other dependency gets a host-origin _pointer_ artifact plus a non-blocking question, never
|
|
1315
|
+
a fabricated mirror; on materialization that pointer degrades to a short stub, and `scaffold pull`
|
|
1316
|
+
fetches the real thing. That degrade is scoped exactly to guide pointers: any other missing manifest
|
|
1317
|
+
entry means a corrupt or truncated vendored manifest, and fails closed. Selection is the law and
|
|
1318
|
+
`findFileConflict` is its backstop: two artifacts at one path refuse the plan rather than racing to
|
|
1319
|
+
be the last writer.
|
|
1271
1320
|
|
|
1272
1321
|
## Audit, repair, and prune
|
|
1273
1322
|
|
|
@@ -1317,10 +1366,15 @@ because there is nothing to explain.
|
|
|
1317
1366
|
`pull` is the target-aware composition. It reads the target's declared scoped dependencies from its
|
|
1318
1367
|
manifest, rejects any explicit selection the target does not declare, builds the reference map from
|
|
1319
1368
|
the target's own `guides/src/<short>.md` mirrors, fetches guides and versions under one shared
|
|
1320
|
-
allowance, and assembles a report whose `clean` flag requires both no drift and no failures.
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1369
|
+
allowance, and assembles a report whose `clean` flag requires both no drift and no failures. A
|
|
1370
|
+
target that declares itself is the one asymmetry, and it follows the same single-owner law: the
|
|
1371
|
+
guide pass drops the self dependency, so `pull` never fetches or writes a workspace's own contract
|
|
1372
|
+
guide over the copy that workspace owns, while the version pass keeps it and still reports its
|
|
1373
|
+
freshness. A `--live` audit reads upstream through the same two passes and applies the same
|
|
1374
|
+
self-exclusion, so the freshness a workspace reports about itself never depends on which verb asked.
|
|
1375
|
+
`write` then commits only the `behind` guides — never `current`, `missing`, or `failed`,
|
|
1376
|
+
none of which carry trustworthy content — under the same containment and precondition law
|
|
1377
|
+
`Materializer` enforces, including a baseline digest check against what is actually on disk.
|
|
1324
1378
|
|
|
1325
1379
|
`catalog` builds the fleet package catalog from three reads per entry. The registry's exact
|
|
1326
1380
|
organization package list is authoritative and unconditionally required. Each package's own registry
|
|
@@ -1353,7 +1407,7 @@ a fixed, interleaved order so aggregates sit immediately before their per-enviro
|
|
|
1353
1407
|
Vue typechecker, every other scope uses plain `tsc`
|
|
1354
1408
|
- `test`, then `test:src` and its per-environment scopes, `test:app` and its per-environment scopes,
|
|
1355
1409
|
`test:policy`, and `test:guides`; an engine also receives the deliberately non-default
|
|
1356
|
-
`test:integration` live installed-consumer gate
|
|
1410
|
+
`test:integration` live installed-consumer gate and `test:equivalence` driver-reference proof
|
|
1357
1411
|
- `build`, then `build:src` and its per-environment targets, `build:app` and its runtime targets, and
|
|
1358
1412
|
`build:host` for an engine workspace
|
|
1359
1413
|
- `dev` when a browser application is selected; `serve` and `serve:build` when a server application
|
|
@@ -1361,11 +1415,25 @@ a fixed, interleaved order so aggregates sit immediately before their per-enviro
|
|
|
1361
1415
|
- `prepublishOnly` chaining `format:check → lint:check → check → build → test`, followed by the
|
|
1362
1416
|
live generated-consumer integration gate for the scaffold engine itself
|
|
1363
1417
|
|
|
1418
|
+
Run `npm run test:equivalence` after changing the persistent boundary build driver. It reruns the
|
|
1419
|
+
integration project in dual-path mode and proves each programmatic driver verdict against the
|
|
1420
|
+
spawned npm-script reference; ordinary integration runs keep the faster driver-only path.
|
|
1421
|
+
|
|
1364
1422
|
**Environment isolation.** Scoped TypeScript projects remove the wrong host's globals from each
|
|
1365
|
-
environment: core scopes carry
|
|
1366
|
-
and no Node; server scopes carry Node and no DOM.
|
|
1367
|
-
|
|
1368
|
-
|
|
1423
|
+
environment: core scopes carry the WHATWG web-interop surface and no host at all — no DOM, no Node,
|
|
1424
|
+
no `vite/client`; browser scopes carry DOM and no Node; server scopes carry Node and no DOM. The
|
|
1425
|
+
worker-only globals the `WebWorker` declarations would otherwise admit — `name`, `onrtctransform`,
|
|
1426
|
+
`close`, `postMessage`, `dispatchEvent`, `location`, `onerror`, `onlanguagechange`, `onoffline`,
|
|
1427
|
+
`ononline`, `onrejectionhandled`, `onunhandledrejection`, `self`, `importScripts`, `fonts`, `caches`,
|
|
1428
|
+
`crossOriginIsolated`, `indexedDB`, `isSecureContext`, `origin`, `scheduler`, `createImageBitmap`,
|
|
1429
|
+
`reportError`, `cancelAnimationFrame`, `requestAnimationFrame`, `onmessage`, `onmessageerror`,
|
|
1430
|
+
`addEventListener`, and `removeEventListener` — are fenced out of `src/core` and `app/core` sources
|
|
1431
|
+
by the policy suite, so the declarations widen what a host-independent module may call without
|
|
1432
|
+
widening where it may run. On every TypeScript bump, derive this list from the module-scope
|
|
1433
|
+
global-object `declare var` and `declare function` declarations in the installed
|
|
1434
|
+
`lib.webworker.d.ts`, then subtract values supplied by `lib.esnext*` or current Node globals. Lint
|
|
1435
|
+
restricts declared package, alias, and conventional relative imports in the same directions.
|
|
1436
|
+
Neither replaces the other, and neither replaces the build.
|
|
1369
1437
|
|
|
1370
1438
|
**The generated build boundary.** The emitted configuration carries an environment-boundary plugin
|
|
1371
1439
|
that resolves the real module graph rather than re-implementing a parser. **TypeScript and
|
|
@@ -1398,10 +1466,10 @@ application's module graph through `import.meta.env` instead.
|
|
|
1398
1466
|
Asset URLs that force `?inline` are rejected before Vite can read them outside that auditable output
|
|
1399
1467
|
graph. Dynamic imports must use a static quoted string or expression-free template string; even
|
|
1400
1468
|
`/* @vite-ignore */` static values repeat the same environment and containment checks inside the
|
|
1401
|
-
transform boundary, including inline HTML proxy modules
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1469
|
+
transform boundary, including inline HTML proxy modules. The transform, load, resolution, emitted
|
|
1470
|
+
asset, and finished-module-graph passes apply that law only to workspace-owned `src/*` and `app/*`
|
|
1471
|
+
modules. Resolved ids under any `node_modules` segment, Vite/Vitest virtual ids, and tooling client
|
|
1472
|
+
injections remain owned by their toolchain and are exempt.
|
|
1405
1473
|
|
|
1406
1474
|
Browser application scripts are modules. Vite's parsed HTML asset callback rejects a classic
|
|
1407
1475
|
external `<script src>` before resolution and directs the author to `type="module"`. A module
|
|
@@ -1416,9 +1484,9 @@ path remains Vite-owned and passes through the environment resolver, which rejec
|
|
|
1416
1484
|
ASCII control range and every non-Node URL scheme before loading or output. No second HTML parser or global
|
|
1417
1485
|
reference rewrite is involved, so comments, text, non-script attributes, and entity-spelled asset
|
|
1418
1486
|
filenames retain Vite's native parsing and resolution behavior.
|
|
1419
|
-
The resolver leaves NUL-prefixed Rolldown/Vite
|
|
1420
|
-
|
|
1421
|
-
|
|
1487
|
+
The resolver leaves NUL-prefixed and `virtual:` Rolldown/Vite module IDs, tooling client injections,
|
|
1488
|
+
and every resolved `node_modules` module to the tool that owns that namespace; author module and
|
|
1489
|
+
asset URLs are extracted and validated before they reach those resolver exceptions.
|
|
1422
1490
|
SVG script `href` and `xlink:href` attributes are parsed too and rejected as classic script loads.
|
|
1423
1491
|
Inline module scripts enter Vite's HTML proxy graph and receive the same Oxc boundary analysis as
|
|
1424
1492
|
module files. Classic inline scripts cannot enter that graph, so the required security prologue places
|
|
@@ -1458,11 +1526,7 @@ What it rejects is equally deliberate:
|
|
|
1458
1526
|
browser or server package subpath;
|
|
1459
1527
|
- a browser module reaching a Node builtin or a server subpath;
|
|
1460
1528
|
- a server module reaching a stylesheet, Vue, or a browser subpath;
|
|
1461
|
-
- a workspace-relative import that resolves outside the workspace
|
|
1462
|
-
escapes the exact physical package root established by the nearest bounded, unlinked
|
|
1463
|
-
`package.json` whose own `name` exactly matches the resolved dependency;
|
|
1464
|
-
- a package `#imports` mapping that resolves outside both the declaring package and another exact
|
|
1465
|
-
physical package root;
|
|
1529
|
+
- a workspace-relative import that resolves outside the workspace;
|
|
1466
1530
|
- an HTML reference carrying `vite-ignore` that violates the same environment or containment law
|
|
1467
1531
|
as an ordinary reference, a Vite `%ENV%` HTML substitution, a classic external script, or a
|
|
1468
1532
|
computed dynamic import in the module graph that would bypass graph resolution;
|
|
@@ -1485,7 +1549,8 @@ cannot express — that a centralized module exports every top-level declaration
|
|
|
1485
1549
|
implementation files hold one class and no stray module-scope declaration, that no function is
|
|
1486
1550
|
declared inside another function outside a directly-passed callback, that interface properties are
|
|
1487
1551
|
readonly, that privacy is a runtime `#` field rather than a TypeScript modifier, that a barrel
|
|
1488
|
-
re-exports only through `export *`,
|
|
1552
|
+
re-exports only through `export *`, that a core source never names a worker-only global the
|
|
1553
|
+
`WebWorker` declarations expose, and that a computed dynamic import cannot smuggle a
|
|
1489
1554
|
cross-environment dependency past the declared import rules. Vue components are inspected for the
|
|
1490
1555
|
same evasions. It is a complement to lint and typecheck, never a second type system, and it is not a
|
|
1491
1556
|
general-purpose source analyzer. Generated workspaces receive the same exported policy module as a
|
|
@@ -1495,7 +1560,14 @@ host-origin file and run it as a dedicated Node-only `policy` test project over
|
|
|
1495
1560
|
**Real browser capability.** Browser test projects are gated on the real executable: the generated
|
|
1496
1561
|
configuration and the generated policy test both probe `existsSync(chromium.executablePath())`. A
|
|
1497
1562
|
browser suite runs when a real Chromium is installed and is skipped honestly when it is not, rather
|
|
1498
|
-
than being faked.
|
|
1563
|
+
than being faked. The gate is applied at registration, not inside the real browser project: without
|
|
1564
|
+
Chromium, each browser factory is replaced by a same-label Node/no-test placeholder, so generated
|
|
1565
|
+
`--project <label>` and `--project=<label>` filters still resolve while no browser code runs. The
|
|
1566
|
+
root permits an empty run only when every recognized exact project filter names one of those gated
|
|
1567
|
+
placeholders; an unreadable or mixed filter keeps the ordinary no-test failure semantics for its
|
|
1568
|
+
Node projects. One printed warning names every gated project label. A machine with a browser
|
|
1569
|
+
registers and runs the real browser suites unchanged; a machine without one runs the remaining
|
|
1570
|
+
projects and says so.
|
|
1499
1571
|
|
|
1500
1572
|
**Continuous integration.** The generated workflow runs on push and pull request, on
|
|
1501
1573
|
`ubuntu-latest`, with read-only contents permission, a 60-minute timeout, and a matrix that **tests
|
|
@@ -1903,6 +1975,7 @@ import {
|
|
|
1903
1975
|
hostGroup,
|
|
1904
1976
|
packageManifest,
|
|
1905
1977
|
paritySpecifiers,
|
|
1978
|
+
selectHostPaths,
|
|
1906
1979
|
sourceArtifacts,
|
|
1907
1980
|
srcVariant,
|
|
1908
1981
|
testArtifacts,
|
|
@@ -1912,6 +1985,7 @@ const spec = blueprint('router', { src: ['core'], app: ['core', 'server'] })
|
|
|
1912
1985
|
const members = blueprintToMembers(spec)
|
|
1913
1986
|
|
|
1914
1987
|
hostGroup('AGENTS.md') // 'docs'
|
|
1988
|
+
selectHostPaths(['guides/src/router.md', 'LICENSE'], spec.name) // ['LICENSE'] — never its own guide
|
|
1915
1989
|
srcVariant(['core', 'server']) // 'multi'
|
|
1916
1990
|
entryFields(['browser']).main // './dist/src/browser/index.js'
|
|
1917
1991
|
dualCondition('./dist/src/core/index')
|
|
@@ -1949,6 +2023,7 @@ import {
|
|
|
1949
2023
|
coreTsconfig,
|
|
1950
2024
|
coreViteConfig,
|
|
1951
2025
|
policyViteProject,
|
|
2026
|
+
renderViteTest,
|
|
1952
2027
|
rootTsconfig,
|
|
1953
2028
|
rootViteConfig,
|
|
1954
2029
|
singleSrcViteConfig,
|
|
@@ -1965,6 +2040,7 @@ appTsconfig('browser', true)
|
|
|
1965
2040
|
|
|
1966
2041
|
viteMachinery(['core']) // { browser: false, vue: false, output: true }
|
|
1967
2042
|
viteMachinery([], ['core', 'browser']) // { browser: true, vue: true, output: true }
|
|
2043
|
+
renderViteTest([{ project: 'srcCore' }], false).includes('projects: [srcCore]') // true
|
|
1968
2044
|
viteHeader(viteMachinery([], ['core', 'browser'])) // the shared header, with browser and Vue support
|
|
1969
2045
|
coreViteConfig()
|
|
1970
2046
|
srcViteConfig('browser')
|
|
@@ -1979,7 +2055,12 @@ applicationViteConfig([], ['core', 'server']).includes('appServer') // true
|
|
|
1979
2055
|
### Reading declared dependencies and comparing freshness
|
|
1980
2056
|
|
|
1981
2057
|
```ts
|
|
1982
|
-
import {
|
|
2058
|
+
import {
|
|
2059
|
+
isBehind,
|
|
2060
|
+
manifestToDependencies,
|
|
2061
|
+
manifestToName,
|
|
2062
|
+
rangeToFreshness,
|
|
2063
|
+
} from '@orkestrel/scaffold'
|
|
1983
2064
|
import {
|
|
1984
2065
|
guideStub,
|
|
1985
2066
|
packageShortName,
|
|
@@ -1988,6 +2069,7 @@ import {
|
|
|
1988
2069
|
} from '@orkestrel/scaffold/server'
|
|
1989
2070
|
|
|
1990
2071
|
manifestToDependencies('{"dependencies":{"@orkestrel/contract":"^0.0.7"}}')
|
|
2072
|
+
manifestToName('{"name":"@orkestrel/router"}') // '@orkestrel/router' — the target's own name
|
|
1991
2073
|
rangeToFreshness('^0.0.7', '0.0.7') // 'current'
|
|
1992
2074
|
isBehind(rangeToFreshness('^0.0.7', '0.0.9')) // true
|
|
1993
2075
|
|
|
@@ -2220,7 +2302,8 @@ isMissingPathError(caught) // true only for an ENOENT error
|
|
|
2220
2302
|
## Tests
|
|
2221
2303
|
|
|
2222
2304
|
- [`tests/src/core/helpers.test.ts`](../../tests/src/core/helpers.test.ts) — the pure leaves: table
|
|
2223
|
-
alignment, byte encoding, snapshots, conflicts, projections, hashing, and
|
|
2305
|
+
alignment, byte encoding, snapshots, host selection, conflicts, projections, hashing, and
|
|
2306
|
+
format-stable JSON.
|
|
2224
2307
|
- [`tests/src/core/builders.test.ts`](../../tests/src/core/builders.test.ts) — the blueprint,
|
|
2225
2308
|
dependency, override, and member builders, including optional-field omission.
|
|
2226
2309
|
- [`tests/src/core/validators.test.ts`](../../tests/src/core/validators.test.ts) — every guard and
|
|
@@ -2228,7 +2311,8 @@ isMissingPathError(caught) // true only for an ENOENT error
|
|
|
2228
2311
|
- [`tests/src/core/shapers.test.ts`](../../tests/src/core/shapers.test.ts) — per-shape guard
|
|
2229
2312
|
exactness, schema essentials, seeded generation, and parse round-trips.
|
|
2230
2313
|
- [`tests/src/core/compilers.test.ts`](../../tests/src/core/compilers.test.ts) — every drafted
|
|
2231
|
-
group, the manifest and exports combination rules,
|
|
2314
|
+
group, the manifest and exports combination rules, the one-owner guide law for a workspace that
|
|
2315
|
+
names a line guide, and the emitted configuration text.
|
|
2232
2316
|
- [`tests/src/core/Compiler.test.ts`](../../tests/src/core/Compiler.test.ts) — the three-stage
|
|
2233
2317
|
pipeline, the fail-closed gate, the emission sequences, and post-destroy behavior.
|
|
2234
2318
|
- [`tests/src/core/PlanManager.test.ts`](../../tests/src/core/PlanManager.test.ts) — content-hash
|
|
@@ -32,8 +32,10 @@ valid_effort() {
|
|
|
32
32
|
|
|
33
33
|
if codex login status >/dev/null 2>&1; then
|
|
34
34
|
auth="authentication ready"
|
|
35
|
+
recovery=""
|
|
35
36
|
else
|
|
36
37
|
auth="authentication unavailable"
|
|
38
|
+
recovery='codex login --device-auth'
|
|
37
39
|
fi
|
|
38
40
|
|
|
39
41
|
if valid_model "$analyst_model" &&
|
|
@@ -46,4 +48,7 @@ else
|
|
|
46
48
|
fi
|
|
47
49
|
|
|
48
50
|
echo "codex.sh: bench detected; ${auth}; ${routes}."
|
|
51
|
+
if [ -n "$recovery" ]; then
|
|
52
|
+
echo "codex.sh: to recover, run \`${recovery}\`."
|
|
53
|
+
fi
|
|
49
54
|
exit 0
|