@orkestrel/scaffold 0.0.21 → 0.0.22
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 +371 -140
- package/dist/bin/scaffold.js.map +1 -1
- package/dist/host/AGENTS.md +61 -42
- package/dist/host/CLAUDE.md +39 -408
- package/dist/host/agents/orchestration.md +454 -0
- package/dist/host/agents/skills/enterprise-bootstrap/SKILL.md +25 -7
- package/dist/host/agents/skills/orkestrel-align-packages/SKILL.md +2 -2
- package/dist/host/agents/skills/orkestrel-build-application/SKILL.md +42 -31
- package/dist/host/agents/skills/orkestrel-build-application/references/application.md +129 -0
- package/dist/host/agents/skills/orkestrel-debrief/SKILL.md +3 -3
- package/dist/host/agents/skills/orkestrel-debrief/references/field-testing.md +2 -2
- package/dist/host/agents/skills/orkestrel-falsify/SKILL.md +167 -0
- package/dist/host/agents/skills/orkestrel-falsify/references/brief.md +98 -0
- package/dist/host/agents/skills/orkestrel-falsify/references/reconcile.md +148 -0
- package/dist/host/agents/skills/orkestrel-harden-package/SKILL.md +4 -2
- package/dist/host/agents/skills/orkestrel-harden-package/references/centralization.md +5 -5
- package/dist/host/agents/skills/orkestrel-harden-package/references/research.md +2 -0
- package/dist/host/agents/skills/orkestrel-polish-surface/SKILL.md +11 -6
- package/dist/host/claude/agents/analyst.md +59 -0
- package/dist/host/claude/agents/application.md +1 -1
- package/dist/host/claude/agents/builder.md +1 -1
- package/dist/host/claude/agents/checker.md +5 -1
- package/dist/host/claude/agents/codex.md +120 -94
- package/dist/host/claude/agents/grok.md +44 -32
- package/dist/host/claude/agents/implementer.md +1 -1
- package/dist/host/claude/agents/orkestrel.md +1 -1
- package/dist/host/claude/agents/planner.md +9 -3
- package/dist/host/claude/agents/researcher.md +6 -5
- package/dist/host/claude/agents/reviewer.md +12 -6
- package/dist/host/claude/agents/scout.md +7 -4
- package/dist/host/claude/agents/verifier.md +1 -1
- package/dist/host/claude/rules/application.md +17 -16
- package/dist/host/claude/rules/architecture.md +41 -22
- package/dist/host/claude/rules/documentation.md +2 -1
- package/dist/host/claude/rules/names.md +7 -6
- package/dist/host/claude/rules/quality.md +65 -18
- package/dist/host/claude/rules/styles.md +1 -1
- package/dist/host/claude/rules/tests.md +12 -6
- package/dist/host/claude/rules/typescript.md +1 -1
- package/dist/host/claude/rules/workspace.md +6 -3
- package/dist/host/claude/settings.json +2 -0
- package/dist/host/claude/skills/orkestrel-falsify/SKILL.md +10 -0
- package/dist/host/codex/agents/analyst.toml +13 -4
- package/dist/host/codex/agents/checker.toml +1 -1
- package/dist/host/codex/agents/grok.toml +2 -1
- package/dist/host/codex/agents/opus.toml +1 -1
- package/dist/host/codex/agents/planner.toml +1 -1
- package/dist/host/codex/agents/researcher.toml +2 -2
- package/dist/host/codex/agents/reviewer.toml +1 -1
- package/dist/host/codex/agents/scout.toml +2 -2
- package/dist/host/codex/config.toml +23 -70
- package/dist/host/cursor/rules/orchestration.mdc +33 -0
- package/dist/host/guides/src/scaffold.md +301 -123
- package/dist/host/manifest.json +47 -1
- package/dist/host/tests/setupPolicy.ts +83 -3
- package/dist/src/core/index.cjs +404 -63
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +119 -41
- package/dist/src/core/index.d.ts +119 -41
- package/dist/src/core/index.js +401 -64
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +83 -33
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +32 -16
- package/dist/src/server/index.d.ts +32 -16
- package/dist/src/server/index.js +84 -35
- package/dist/src/server/index.js.map +1 -1
- package/package.json +4 -4
|
@@ -226,7 +226,8 @@ application-browser projection. The root machinery selection never attaches a
|
|
|
226
226
|
compilers section sets out.
|
|
227
227
|
|
|
228
228
|
`ViteFacts` is the optional structural-fact slice shared by every root Vite compiler:
|
|
229
|
-
`bin
|
|
229
|
+
`bin` and `integration` each select their matching standalone project when `true`, while `services`
|
|
230
|
+
selects one standalone project for every listed vendor;
|
|
230
231
|
`global` records the exact-case consumer-owned global-setup module and wires it into each eligible
|
|
231
232
|
project; `showcase` records the exact-case consumer-owned showcase wrapper and selects only its
|
|
232
233
|
generated browser machinery.
|
|
@@ -252,7 +253,7 @@ interface Blueprint {
|
|
|
252
253
|
readonly overrides: readonly Override[]
|
|
253
254
|
readonly bin: boolean
|
|
254
255
|
readonly integration: boolean
|
|
255
|
-
readonly
|
|
256
|
+
readonly services: readonly string[]
|
|
256
257
|
readonly global: boolean
|
|
257
258
|
readonly showcase: boolean
|
|
258
259
|
}
|
|
@@ -265,9 +266,10 @@ packages — a peer flagged `optional` also gets a `peerDependenciesMeta` entry.
|
|
|
265
266
|
package-specific development dependencies merged over the generated baseline, and may carry any
|
|
266
267
|
valid npm package name.
|
|
267
268
|
|
|
268
|
-
`bin`, `integration`, `
|
|
269
|
-
each is `true
|
|
270
|
-
defines it — never because of the workspace's name, and
|
|
269
|
+
`bin`, `integration`, `services`, `global`, and `showcase` are structural project facts. They obey
|
|
270
|
+
one law: each boolean is `true`, and each service name is present, only when the workspace physically
|
|
271
|
+
ships the directory or exact-case file that defines it — never because of the workspace's name, and
|
|
272
|
+
never because a sibling fact is set.
|
|
271
273
|
`deriveBlueprint` probes those paths, so a fresh compile and an audit of a mature repository agree
|
|
272
274
|
on what the workspace is.
|
|
273
275
|
|
|
@@ -279,10 +281,11 @@ on what the workspace is.
|
|
|
279
281
|
workspace's own built output, outside the default run: the generated root configuration registers
|
|
280
282
|
a standalone `integration` project including `tests/integration/**/*.test.ts`, and the manifest
|
|
281
283
|
emits `test:integration`.
|
|
282
|
-
- **`
|
|
283
|
-
|
|
284
|
-
`
|
|
285
|
-
isolated `test:service
|
|
284
|
+
- **`services`** — each direct `tests/service/<vendor>/` directory that contains a `*.test.ts` at
|
|
285
|
+
any depth contributes its directory name to the sorted list. Each vendor gets a slow, opt-in
|
|
286
|
+
`service:<vendor>` proof project against its foreign process, including
|
|
287
|
+
`tests/service/<vendor>/**/*.test.ts`, and an isolated `test:service:<vendor>` script. The
|
|
288
|
+
aggregate `test:service` runs all vendor projects in one invocation.
|
|
286
289
|
- **`global`** — the physical, exact-case `tests/setupGlobal.ts` file exists. It is the single
|
|
287
290
|
governing setup-presence fact. A declared `src/browser` project runs that consumer-owned module
|
|
288
291
|
as `globalSetup`; integration runs it only when `bin` and `integration` are also true.
|
|
@@ -293,12 +296,20 @@ on what the workspace is.
|
|
|
293
296
|
consumer-only `vite-plugin-singlefile` development dependency. A directory, link, wrong-case
|
|
294
297
|
name, absent wrapper, demo HTML, script, or installed dependency never implies this fact.
|
|
295
298
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
299
|
+
Each service vendor owes `tests/service/<vendor>/setup.ts`, whose module-load readiness check probes
|
|
300
|
+
and warms only that vendor. A service workspace also owes the shared `scripts/service.sh`
|
|
301
|
+
provisioner. Derivation fails with a coded `INVALID` question when a vendor's readiness module is
|
|
302
|
+
missing, when a vendor directory contains no test, or when a test uses the former flat
|
|
303
|
+
`tests/service/*.test.ts` layout. An absent shared provisioner is instead a repairable missing
|
|
304
|
+
artifact, so declaring the vendor directory does not deadlock the tool that supplies the skeleton.
|
|
305
|
+
The migration is to move each flat test into `tests/service/<vendor>/`, add that vendor's `setup.ts`,
|
|
306
|
+
and customize the repaired provisioner skeleton. Nothing here is inferred from a source or
|
|
307
|
+
application axis: a vendor serves both.
|
|
308
|
+
|
|
309
|
+
This is a published breaking change: `Blueprint.service` and `ViteFacts.service` were replaced by
|
|
310
|
+
their sorted `services` collections, the single `service` project became one project per vendor,
|
|
311
|
+
and the global `tests/setupService.ts` readiness seam was removed. There is no compatibility
|
|
312
|
+
boolean or declaration file.
|
|
302
313
|
|
|
303
314
|
`Override` replaces a rendered artifact's content at a path, never partially merges it. `Member` is
|
|
304
315
|
one declared public export of the scaffolded workspace, derived rather than authored.
|
|
@@ -316,7 +327,8 @@ by artifact-relative path.
|
|
|
316
327
|
self-describing. `PlanSummary` is the dry-run tally by origin and carries both selections. `Finding` is one
|
|
317
328
|
drift verdict with an optional bounded `observed` byte hex for a stale destination, and `Audit` is
|
|
318
329
|
the whole diff plus its `clean` and `complete` flags, `questions`, and `drifted` / `missing` /
|
|
319
|
-
`foreign` counts.
|
|
330
|
+
`foreign` counts.
|
|
331
|
+
`Question` is one validation issue; `blocking: true` fails the gate closed while
|
|
320
332
|
`false` rides a complete result as an advisory. `Validation` is the semantic pass result and never
|
|
321
333
|
throws.
|
|
322
334
|
|
|
@@ -374,8 +386,11 @@ instead of through the manifest.
|
|
|
374
386
|
|
|
375
387
|
`ManifestEntry` is one vendored-host file record — its un-dotted `storage` name, its `destination`
|
|
376
388
|
relative to a target, and an `executable` bit. `HostManifest` pairs the sorted file `entries` with
|
|
377
|
-
the complete sorted directory `roots` inventory
|
|
378
|
-
|
|
389
|
+
the complete sorted directory `roots` inventory and a SHA-256 `digest` of that exact membership.
|
|
390
|
+
The independently persisted digest detects an entry/root membership edit that did not update the
|
|
391
|
+
digest, while roots distinguish a declared-empty directory. A self-consistent replacement manifest
|
|
392
|
+
remains structurally valid and defines its own smaller membership; authenticity of that complete
|
|
393
|
+
membership is outside the digest's checksum-only contract.
|
|
379
394
|
|
|
380
395
|
The write-transaction shapes are the fail-closed mutation vocabulary. `WriteExpectation` is one
|
|
381
396
|
destination snapshot captured before mutation (`absent`, `file`, or `directory`, with device,
|
|
@@ -410,9 +425,12 @@ From [`constants.ts`](../../src/core/constants.ts).
|
|
|
410
425
|
| `BIN_CONFIGS` | const |
|
|
411
426
|
| `APP_MATRIX` | const |
|
|
412
427
|
| `HOST_PATHS` | const |
|
|
428
|
+
| `ORCHESTRATION_PATH_PREFIXES` | const |
|
|
429
|
+
| `ORCHESTRATION_PATH_NAMES` | const |
|
|
413
430
|
| `SERVICE_SCRIPT_PATH` | const |
|
|
414
431
|
| `GLOBAL_SETUP_PATH` | const |
|
|
415
432
|
| `SHOWCASE_CONFIG_PATH` | const |
|
|
433
|
+
| `CATALOG_AGENT_PATH` | const |
|
|
416
434
|
| `NAME_PATTERN` | const |
|
|
417
435
|
| `MAX_NAME_LENGTH` | const |
|
|
418
436
|
| `MAX_DEPENDENCY_NAME_LENGTH` | const |
|
|
@@ -464,10 +482,38 @@ produces one (`app/browser/index.html`, `app/server/main.ts`). `BIN_CONFIGS` is
|
|
|
464
482
|
axis's computed `tsconfig` and Vite wrapper pair. `HOST_PATHS` is the ordered list of byte-copied
|
|
465
483
|
host artifacts, and it is the staging manifest rather than the per-plan carried set:
|
|
466
484
|
`stageHost` vendors every path on it, while each plan carries the subset `selectHostPaths` selects
|
|
467
|
-
for that one workspace. `
|
|
468
|
-
|
|
485
|
+
for that one workspace. `ORCHESTRATION_PATH_PREFIXES` and `ORCHESTRATION_PATH_NAMES` are the one
|
|
486
|
+
membership rule behind both group classifiers: `inferGroup` reads them for a foreign target path and
|
|
487
|
+
`hostGroup` for a `HOST_PATHS` entry, so a new harness directory is admitted once rather than twice.
|
|
488
|
+
`SERVICE_SCRIPT_PATH` names the generated provisioner skeleton a service
|
|
489
|
+
workspace must replace with its idempotent vendor provisioning. It is birth-only while present and
|
|
490
|
+
repairable while absent. `GLOBAL_SETUP_PATH` names the consumer-owned Vitest global-setup
|
|
469
491
|
module that independently selected projects can load. `SHOWCASE_CONFIG_PATH` names the sole
|
|
470
492
|
consumer-owned regular file whose exact physical presence enables the optional app showcase.
|
|
493
|
+
`CATALOG_AGENT_PATH` names the one artifact `diffPlan` compares by presence even after hydration,
|
|
494
|
+
so a consumer can name the file the catalog operation owns rather than rediscovering it from a
|
|
495
|
+
finding:
|
|
496
|
+
|
|
497
|
+
```ts
|
|
498
|
+
import type { Plan } from '@orkestrel/scaffold'
|
|
499
|
+
import { blueprint, CATALOG_AGENT_PATH, contentToHex, diffPlan } from '@orkestrel/scaffold'
|
|
500
|
+
|
|
501
|
+
const plan: Plan = {
|
|
502
|
+
blueprint: blueprint('router', { src: ['core'] }),
|
|
503
|
+
groups: ['orchestration'],
|
|
504
|
+
artifacts: [
|
|
505
|
+
{
|
|
506
|
+
path: CATALOG_AGENT_PATH,
|
|
507
|
+
group: 'orchestration',
|
|
508
|
+
origin: 'host',
|
|
509
|
+
hex: contentToHex('vendored catalog\n'),
|
|
510
|
+
},
|
|
511
|
+
],
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
diffPlan(plan, { [CATALOG_AGENT_PATH]: contentToHex('a newer fleet table\n') }).clean // true
|
|
515
|
+
diffPlan(plan, {}).missing // 1 — restorable while absent, never replaced while present
|
|
516
|
+
```
|
|
471
517
|
|
|
472
518
|
The bounds are public because they are part of the contract, not implementation trivia.
|
|
473
519
|
`MAX_ARTIFACT_BYTES` caps one artifact at 5 MiB and `MAX_TOTAL_ARTIFACT_BYTES` caps one blueprint,
|
|
@@ -548,6 +594,14 @@ From [`constants.ts`](../../src/server/constants.ts).
|
|
|
548
594
|
`PRUNE_DIRECTORIES` is the closed set of prune-owned directories — `.claude/agents`,
|
|
549
595
|
`.codex/agents`, and `scripts`. Nothing outside those roots is ever a deletion candidate, which is
|
|
550
596
|
why project-owned skills under `.agents/skills` and `.claude/skills` are structurally safe.
|
|
597
|
+
`.cursor/rules` is vendored but deliberately not pruned, for the same reason: a workspace owns
|
|
598
|
+
project-specific Cursor rules beside the vendored bridge, and pruning would delete them. That
|
|
599
|
+
choice has a cost, and it is accepted rather than avoided: a rule file dropped from `HOST_PATHS`
|
|
600
|
+
stays in every consumer that already received it, no `audit` run reports it — the executable audit
|
|
601
|
+
reads only planned paths, and nothing outside `PRUNE_DIRECTORIES` is ever a `foreign` finding — and
|
|
602
|
+
a Cursor rule carrying `alwaysApply: true` keeps instructing agents there indefinitely. Retiring a
|
|
603
|
+
vendored rule therefore needs a deliberate consumer-side removal, not a scaffold run.
|
|
604
|
+
`.claude/rules` and `.claude/skills` carry the identical exposure for the identical reason.
|
|
551
605
|
`HOST_MANIFEST_PATH` is the reserved `manifest.json` written at the root of every staged host.
|
|
552
606
|
`SENSITIVE_HOST_PATH_PATTERN` rejects credential-like, key-store, certificate-key, and
|
|
553
607
|
local-configuration paths at the staging boundary. `RESERVED_TARGET_PATH_PATTERN` protects `.git`
|
|
@@ -838,6 +892,7 @@ From [`helpers.ts`](../../src/core/helpers.ts).
|
|
|
838
892
|
| `syncToReview` | function |
|
|
839
893
|
| `catalogToBlock` | function |
|
|
840
894
|
| `inferGroup` | function |
|
|
895
|
+
| `matchesOrchestrationPath` | function |
|
|
841
896
|
| `diffPlan` | function |
|
|
842
897
|
| `bytesToHex` | function |
|
|
843
898
|
| `contentCodePoint` | function |
|
|
@@ -899,6 +954,14 @@ that block enters agent instruction context. `isBehind` is the shared freshness
|
|
|
899
954
|
report projections count with.
|
|
900
955
|
|
|
901
956
|
`diffPlan` is the audit engine, and `inferGroup` classifies a target file the plan does not own.
|
|
957
|
+
`matchesOrchestrationPath` is the shared membership test both classifiers use to decide whether a
|
|
958
|
+
path instructs or wires an agent rather than configuring the toolchain.
|
|
959
|
+
A host artifact without canonical `hex` is presence-owned: present is `aligned`, absent is
|
|
960
|
+
`missing`. The server face attaches `hex` to every readable vendored source before executable
|
|
961
|
+
audits, except the dependency-guide pointers hydration deliberately marks presence-owned. The
|
|
962
|
+
hydrated `CATALOG_AGENT_PATH` artifact remains presence-owned even with vendored bytes because
|
|
963
|
+
`catalog` owns its bounded marker region. The same engine governs `Materializer.repair`'s preview
|
|
964
|
+
recheck and direct library consumers without a call-site plan rewrite.
|
|
902
965
|
`snapshotOf`, `contentToHex`, `contentToBytes`, `contentByteLength`, `contentCodePoint`, and
|
|
903
966
|
`bytesToHex` are the host-independent byte leaves that make exact comparison possible without a
|
|
904
967
|
host encoder or buffer; an unpaired surrogate encodes as `U+FFFD` rather than throwing.
|
|
@@ -946,6 +1009,7 @@ From [`helpers.ts`](../../src/server/helpers.ts).
|
|
|
946
1009
|
| `digestFile` | function |
|
|
947
1010
|
| `digestHex` | function |
|
|
948
1011
|
| `digestText` | function |
|
|
1012
|
+
| `digestHostManifest` | function |
|
|
949
1013
|
| `guideStub` | function |
|
|
950
1014
|
| `packageShortName` | function |
|
|
951
1015
|
| `readGuideReferences` | function |
|
|
@@ -998,7 +1062,9 @@ directory. All three reject malformed paths before filesystem access. Containmen
|
|
|
998
1062
|
realpath-aware rather than merely lexical, so a symlinked subdirectory planted inside an otherwise
|
|
999
1063
|
legitimate root cannot smuggle a write or a read outside it.
|
|
1000
1064
|
|
|
1001
|
-
`digestFile`, `digestHex`, and `digestText` are the
|
|
1065
|
+
`digestFile`, `digestHex`, and `digestText` are the byte and text SHA-256 leaves;
|
|
1066
|
+
`digestHostManifest` hashes the canonical entry/root membership independently of the stored digest
|
|
1067
|
+
field. The file digest is
|
|
1002
1068
|
bounded-memory and revalidates device, inode, size, and modification time before and after reading,
|
|
1003
1069
|
so a file swapped mid-read is a failure rather than a silent wrong digest. `readFileHex` and
|
|
1004
1070
|
`readFileText` read one contained file under the same revalidation, and the text reader decodes
|
|
@@ -1030,8 +1096,9 @@ existing workspace so a mature package is diffed against its own would-be scaffo
|
|
|
1030
1096
|
dependency-less stand-in. Environments come from `src/<environment>/` and `app/<environment>/`, the
|
|
1031
1097
|
three directory-shaped structural project facts from their directory probes, `global` from the
|
|
1032
1098
|
physical exact-case `tests/setupGlobal.ts` file, and `showcase` from the physical exact-case regular
|
|
1033
|
-
file `configs/app/vite.showcase.config.ts`;
|
|
1034
|
-
|
|
1099
|
+
file `configs/app/vite.showcase.config.ts`; service names come from the direct vendor directories
|
|
1100
|
+
under `tests/service/`, subject to the companion law in the blueprint section. Every fact is a
|
|
1101
|
+
reading of the filesystem, never of the package name. Dependencies and peers come
|
|
1035
1102
|
from the manifest's scoped entries, with an optional peer recovered from
|
|
1036
1103
|
`peerDependenciesMeta`; and `extras` is every development dependency minus the complete set
|
|
1037
1104
|
`devDependenciesFor` emits for those environments and structural axes, and minus anything already
|
|
@@ -1045,7 +1112,8 @@ repository forking the file.
|
|
|
1045
1112
|
`hydratePlan` are the vendored-host path. `storagePath` maps a repo-relative path to its un-dotted
|
|
1046
1113
|
storage name, `stageHost` copies the vendored set into an output directory behind a full preflight
|
|
1047
1114
|
and an atomic swap, and `readHostManifest` reads and validates the resulting `manifest.json`,
|
|
1048
|
-
returning `undefined` when a host has none —
|
|
1115
|
+
including its independently stored membership digest, returning `undefined` when a host has none —
|
|
1116
|
+
the raw-repository-root fallback that maps sources 1:1.
|
|
1049
1117
|
`locateHostSource` resolves one source to its storage file, `remapArtifactPath` maps a manifest
|
|
1050
1118
|
destination back onto an artifact's target prefix, and `hydratePlan` rehydrates a plan's host
|
|
1051
1119
|
artifacts with their exact bytes, expanding a directory-shaped host artifact into one artifact per
|
|
@@ -1182,10 +1250,11 @@ formatter's 100-column fixed point: a complete registration-array line, includin
|
|
|
1182
1250
|
its trailing comma, stays collapsed when it fits and expands one entry per line otherwise.
|
|
1183
1251
|
`viteProjectRegistrations` is the one registration derivation every root shape consumes: it derives
|
|
1184
1252
|
the selected source and application projects from the canonical environment order, then appends
|
|
1185
|
-
`policy`, `config`, `guides`,
|
|
1253
|
+
`policy`, `config`, `guides`, the optional `srcBin` and `integration` projects, and one
|
|
1254
|
+
`service<Vendor>` project for every selected service.
|
|
1186
1255
|
`viteProjectDefinitions` renders the standalone proof and structural-fact definitions in that same
|
|
1187
1256
|
order with one blank line between declarations. Both consume `ViteFacts`, so each optional project
|
|
1188
|
-
is controlled only by its matching `bin`, `integration`, or `
|
|
1257
|
+
is controlled only by its matching `bin`, `integration`, or `services` blueprint fact; the same
|
|
1189
1258
|
slice carries `global` to integration and the source-browser compiler, and `showcase` to the
|
|
1190
1259
|
application-browser compiler, without adding another test project.
|
|
1191
1260
|
|
|
@@ -1200,11 +1269,12 @@ single non-core `src` environment, and application-bearing workspace respectivel
|
|
|
1200
1269
|
executable-project emitter. A
|
|
1201
1270
|
proof project is structurally derived from the directory holding its tests and never wraps a source
|
|
1202
1271
|
or application environment project. The guides project therefore uses only `tests/setup.ts`, never
|
|
1203
|
-
`setupServer.ts`, `setupBrowser.ts`, or
|
|
1272
|
+
`setupServer.ts`, `setupBrowser.ts`, or a vendor readiness module; and its `tests/src/**/*.test.ts` and
|
|
1204
1273
|
`tests/app/**/*.test.ts` exclude rows are uniform across all root shapes by design, including
|
|
1205
1274
|
core-only workspaces where one row cannot currently match. Integration and service use 120-second
|
|
1206
|
-
test and hook timeouts with file parallelism disabled
|
|
1207
|
-
`tests/
|
|
1275
|
+
test and hook timeouts with file parallelism disabled. Each service project layers
|
|
1276
|
+
`tests/setupServer.ts` and `tests/service/<vendor>/setup.ts` onto the shared setup, carries the
|
|
1277
|
+
server environment boundary, and may exercise either the `src` or `app` axis. The integration project wires
|
|
1208
1278
|
`tests/setupGlobal.ts` for the shared template-registry harness exactly when `bin`, `integration`,
|
|
1209
1279
|
and `global` are all true. Independently, a `global` source-browser project places
|
|
1210
1280
|
`globalSetup: ['./tests/setupGlobal.ts']` immediately before its ordinary `setupFiles` row (and
|
|
@@ -1221,7 +1291,9 @@ generated parity suite resolves fence imports through. `guideMemberTable`, `guid
|
|
|
1221
1291
|
`guideMethods`, and `guideTests` render the generated guide's member tables, usage examples, method
|
|
1222
1292
|
contract, and test inventory. `fillArtifact` fills one template entry into a `template`-origin
|
|
1223
1293
|
artifact with missing placeholders treated as an error, and `hostGroup` resolves which group a
|
|
1224
|
-
byte-copied host path belongs to
|
|
1294
|
+
byte-copied host path belongs to — splitting by what a path governs rather than where it sits, so
|
|
1295
|
+
that both MCP registrations (`.mcp.json` and `.cursor/mcp.json`) group with the harness bridges as
|
|
1296
|
+
`orchestration` rather than with the root dotfiles they sit beside. `applyOverrides` replaces a matching artifact's content in place
|
|
1225
1297
|
and deliberately leaves an unmatched, host-owned, or `package.json` override unapplied, because the
|
|
1226
1298
|
gate reports it as a blocking question. `ciWorkflow` renders the generated workflow.
|
|
1227
1299
|
|
|
@@ -1317,7 +1389,10 @@ The public methods of each behavioral interface, one table per type.
|
|
|
1317
1389
|
`audit(blueprint, current, groups?)` compiles and then diffs the resulting plan against the
|
|
1318
1390
|
caller-supplied current content; a gated blueprint returns `complete: false` with the gate's
|
|
1319
1391
|
blocking questions and zero findings, and a complete one carries the gate's advisories on that same
|
|
1320
|
-
`questions` field.
|
|
1392
|
+
`questions` field. Because this core-only method performs no host I/O, its compiled host artifacts
|
|
1393
|
+
have no `hex` and are audited by presence. Callers that need host-byte verdicts hydrate the compiled
|
|
1394
|
+
plan through the server face and call `diffPlan`, which is the path every executable audit uses.
|
|
1395
|
+
`destroy()` is idempotent teardown. The interface also exposes the readonly
|
|
1321
1396
|
`emitter`.
|
|
1322
1397
|
|
|
1323
1398
|
#### `PlanManagerInterface`
|
|
@@ -1347,13 +1422,14 @@ interface also exposes the readonly `emitter` and `size` properties.
|
|
|
1347
1422
|
| `destroy` | `void` |
|
|
1348
1423
|
|
|
1349
1424
|
`materialize(plan, target)` is green-field: it refuses any target `isVacant` rejects, then copies
|
|
1350
|
-
each host artifact and writes each template and computed artifact. `repair(plan, audit, target
|
|
1351
|
-
into-existing: it skips the vacancy check, re-verifies that the target still matches
|
|
1352
|
-
preview, and writes
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1425
|
+
each host artifact and writes each template and computed artifact. `repair(plan, audit, target,
|
|
1426
|
+
replace?)` is into-existing: it skips the vacancy check, re-verifies that the target still matches
|
|
1427
|
+
the audit preview, and writes missing artifacts. Stale artifacts are report-only and returned as
|
|
1428
|
+
`skipped` by default; passing `true` for `replace` explicitly replaces their bytes and discards their
|
|
1429
|
+
local changes. Aligned artifacts are always `skipped`. `prune(target, expected)` deletes exactly the
|
|
1430
|
+
unexpected files the vendored host no longer declares under the prune directories, and only after
|
|
1431
|
+
the observed bytes still match the `expected` snapshot it was previewed with. `destroy()` is
|
|
1432
|
+
idempotent teardown. The interface also exposes the readonly `emitter`.
|
|
1357
1433
|
|
|
1358
1434
|
#### `SyncInterface`
|
|
1359
1435
|
|
|
@@ -1424,10 +1500,11 @@ produce the same digest — and a `PlanManager` id is that digest.
|
|
|
1424
1500
|
how it is audited, and whether it may ever be overwritten.
|
|
1425
1501
|
|
|
1426
1502
|
- **`host`** — byte-copied from the vendored data root. These are the shared files a whole fleet
|
|
1427
|
-
keeps identical: the root instruction documents and licence, the
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1503
|
+
keeps identical: the root instruction documents and licence, the canonical orchestration contract
|
|
1504
|
+
and the three harness bridges that point at it, the agent, rule, and skill directories, the
|
|
1505
|
+
session scripts, the repository coding-law policy module, the byte-identical root dotfiles, and
|
|
1506
|
+
the two line guide mirrors a workspace carries for contracts other than its own. `HOST_PATHS` is
|
|
1507
|
+
the exact vendored list; what a given plan carries is `selectHostPaths` of it.
|
|
1431
1508
|
- **`template`** — filled from a frozen template definition by a pure fill engine. These are
|
|
1432
1509
|
starter files: source stubs, test stubs, the starter guide, the README.
|
|
1433
1510
|
- **`computed`** — derived by this package's own combination logic. These are the structural files:
|
|
@@ -1443,19 +1520,32 @@ Audit semantics follow directly from that.
|
|
|
1443
1520
|
missing, or clean tallies.
|
|
1444
1521
|
- A **computed** artifact is content-aware canon: `missing`, `aligned`, or `stale`, and it gates the
|
|
1445
1522
|
audit like any other drift.
|
|
1446
|
-
- A **host** artifact
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1523
|
+
- A **host** artifact with canonical `hex` is content-compared exactly like a computed artifact and
|
|
1524
|
+
can be `stale`. Without `hex`, it is presence-owned: present is `aligned`, absent is `missing`.
|
|
1525
|
+
The catalog agent is explicitly presence-owned because `catalog` is its sole content writer.
|
|
1526
|
+
Hydration expands a directory-shaped host artifact into one artifact per declared file and verifies
|
|
1527
|
+
that the manifest digest matches the manifest's current membership before expansion. That detects
|
|
1528
|
+
stale-digest truncation; a self-consistently rewritten manifest defines a smaller valid inventory,
|
|
1529
|
+
so the digest alone cannot authenticate omitted membership.
|
|
1530
|
+
- In a caller-supplied snapshot, a path the plan does not own is `foreign`, and `inferGroup`
|
|
1531
|
+
classifies it by its leading path segment. The executable supplies unexpected paths only from
|
|
1532
|
+
`.claude/agents`, `.codex/agents`, and `scripts`, because those prune-owned directories are the
|
|
1533
|
+
only regions scaffold has authority to delete from; unplanned files elsewhere are not reported
|
|
1534
|
+
as foreign.
|
|
1452
1535
|
|
|
1453
1536
|
The same ownership boundary is what makes mutation safe. **`fleet` and default `repair` both scope
|
|
1454
|
-
the compiled plan to host origin before hydrating, diffing, or applying.**
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1537
|
+
the compiled plan to host origin before hydrating, diffing, or applying.** Missing files in that
|
|
1538
|
+
scope are restored, but stale files are report-only unless `--replace` explicitly authorizes byte
|
|
1539
|
+
replacement. `--generated` widens the selected ownership scope to generated canon. It keeps the
|
|
1540
|
+
`package.json` publication boundary protected except for the generated service-script keys needed
|
|
1541
|
+
when the derived service set changes; it composes with `--replace` and does not itself authorize
|
|
1542
|
+
replacement. Template
|
|
1543
|
+
artifacts remain birth-only in either scope, except that an absent service provisioner and absent
|
|
1544
|
+
service conformance test are promoted to missing-file repair artifacts. A present customized copy
|
|
1545
|
+
is never compared or replaced. A mature workspace's hand-written source, tests, and guides are
|
|
1546
|
+
therefore never overwritten with a stub. The generated
|
|
1547
|
+
`.github/workflows/ci.yml` is a **computed** artifact, so user-owned CI stands by default and is
|
|
1548
|
+
restored only when both `--generated` and `--replace` are passed.
|
|
1459
1549
|
Audit always compares it because computed artifacts are content-aware canon. A legitimate
|
|
1460
1550
|
difference that the blueprint cannot express is a canon gap: add the missing blueprint axis rather
|
|
1461
1551
|
than forking the computed file in one repository.
|
|
@@ -1477,8 +1567,11 @@ owner: a dependency this package vendors a byte-identical mirror for gets a real
|
|
|
1477
1567
|
dependency, so a package depending on `@orkestrel/guide` plans one `guides/src/guide.md` rather than
|
|
1478
1568
|
two. Any other dependency gets a host-origin _pointer_ artifact plus a non-blocking question, never
|
|
1479
1569
|
a fabricated mirror; on materialization that pointer degrades to a short stub, and `scaffold pull`
|
|
1480
|
-
fetches the real thing.
|
|
1481
|
-
|
|
1570
|
+
fetches the real thing. Hydration marks that permanent pointer state presence-owned, so both the
|
|
1571
|
+
birth stub and a later pulled guide audit clean while present; `pull` refreshes content but is not a
|
|
1572
|
+
remedy for an audit state. That degrade is scoped exactly to guide pointers. A manifest whose
|
|
1573
|
+
membership changes without a matching digest is rejected, while any other undeclared or unreadable
|
|
1574
|
+
source is rejected with a coded `TARGET` failure. Selection is the law and
|
|
1482
1575
|
`findFileConflict` is its backstop: two artifacts at one path refuse the plan rather than racing to
|
|
1483
1576
|
be the last writer.
|
|
1484
1577
|
|
|
@@ -1489,23 +1582,63 @@ checks one. `readTarget` supplies the snapshot as exact bytes; `diffPlan` return
|
|
|
1489
1582
|
`auditToReview` renders them for a human. Nothing in that path writes.
|
|
1490
1583
|
|
|
1491
1584
|
The executable's physical unexpected-file scan treats exactly `scripts/service.sh` as an expected
|
|
1492
|
-
|
|
1493
|
-
because
|
|
1494
|
-
|
|
1495
|
-
provisioner. A non-service workspace still reports the same path as foreign.
|
|
1585
|
+
workspace-owned seam when the derived blueprint has at least one service. That exclusion is
|
|
1586
|
+
warranted because the promoted plan reports an absent file as missing while a present file is
|
|
1587
|
+
consumer-owned. A workspace with no services still reports the same path as foreign.
|
|
1496
1588
|
|
|
1497
1589
|
`repair` turns those findings back into the narrowest possible write. It re-reads the target,
|
|
1498
1590
|
re-diffs it, and refuses to proceed if the findings changed since the preview it was given — a
|
|
1499
1591
|
target that moved under the caller is a `TARGET` failure, not a race to win. It then derives a write
|
|
1500
1592
|
precondition per artifact from the audit itself: a `missing` finding requires the destination to
|
|
1501
|
-
still be absent
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1593
|
+
still be absent. A `stale` finding remains untouched and is reported as skipped unless the caller
|
|
1594
|
+
passes `replace`; an authorized stale replacement requires the destination to still carry exactly
|
|
1595
|
+
the bytes that were observed. Those preconditions are checked again inside the write transaction
|
|
1596
|
+
before any promotion. A skipped stale path keeps the executable at exit `1`, because the selected
|
|
1597
|
+
workspace remains drifted; a clean run and a run that fully applies its findings exit `0`. An
|
|
1598
|
+
interactive audit repair hand-off forwards both `--generated` and `--replace` when those flags were
|
|
1599
|
+
present on `audit`.
|
|
1600
|
+
|
|
1601
|
+
That boundary governs the executable's words too. Every drift line states what a command will do
|
|
1602
|
+
rather than how a file came to differ: the executable cannot know whether a generated file was
|
|
1603
|
+
hand-edited, and a consumer whose blueprint cannot yet express what it needs legitimately edits one.
|
|
1604
|
+
Every cost is stated where it can still be declined, and nowhere else: a run with nothing to write
|
|
1605
|
+
states no boundary it is not about to act on, because a warning attached to a no-op only trains
|
|
1606
|
+
operators to ignore warnings. `repair` states its scope when the audit found something to repair;
|
|
1607
|
+
`fleet` states its scope, its repository count, and the same replacement cost once `--apply` has
|
|
1608
|
+
authorized a write; neither states it over a dry run. Each run closes on the tally of what it did,
|
|
1609
|
+
including a run that writes nothing — and a drifted file left alone is counted apart from an
|
|
1610
|
+
aligned one, because `unchanged` is already the audit table's word for a file that matches canon.
|
|
1611
|
+
|
|
1612
|
+
**Four paths discard content a consumer may own, and each names its cost before it acts.**
|
|
1613
|
+
|
|
1614
|
+
| Path | What it discards | Ownership boundary |
|
|
1615
|
+
| --------------------------------- | -------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
|
|
1616
|
+
| `--replace` on repair or fleet | The local bytes of a drifted file the report named | Host-owned artifacts, widened to generated canon by `--generated`; never a present starter, never `package.json` |
|
|
1617
|
+
| `--prune --apply` | Whole unexpected files, quarantined first and reported by exact path | Only `.claude/agents`, `.codex/agents`, and `scripts`, and only paths the vendored host does not declare |
|
|
1618
|
+
| `catalog --apply` | Everything between the two catalog markers, local additions included | Exactly the one bounded marker region of `CATALOG_AGENT_PATH`; the rest of that file is never touched |
|
|
1619
|
+
| `pull --apply` / `mirror --apply` | A locally edited vendored guide mirror, which reads as `behind` | Only `guides/src/<name>.md` mirrors of other packages; never the guide this workspace owns |
|
|
1620
|
+
|
|
1621
|
+
`--replace` is the only one of the four that is an opt-in modifier rather than a verb, so it is the
|
|
1622
|
+
one whose cost is repeated in every line that offers it: the scope line, the repair verdict, the
|
|
1623
|
+
audit's drift guidance, and the hand-off question itself. `--apply` authorizes all four and nothing
|
|
1624
|
+
else does — `--yes` only skips a confirmation it can no longer stand in for, and an unexpected-file
|
|
1625
|
+
hint that recommended `repair --prune` without it would name a command that deletes nothing. `new`
|
|
1626
|
+
is absent from the table on purpose: it refuses any target `isVacant` rejects, so it has no local
|
|
1627
|
+
content to discard.
|
|
1628
|
+
|
|
1629
|
+
The catalog agent has a narrower ownership exception in `diffPlan` itself.
|
|
1630
|
+
`CATALOG_AGENT_PATH` remains presence-owned after host hydration: repair can restore the
|
|
1631
|
+
absent file, but audit, repair, fleet, and direct library consumers never compare or replace its
|
|
1632
|
+
existing bytes, even under `--replace`. `catalog` is the sole content writer and continues to
|
|
1633
|
+
replace only the uniquely bounded marker region. Thus
|
|
1634
|
+
`repair` → `catalog` → `repair` converges without restoring a stale embedded catalog snapshot over
|
|
1635
|
+
the current fleet table.
|
|
1505
1636
|
|
|
1506
1637
|
`prune` is the deletion arm, and it is deliberately narrow. Its candidate set comes from
|
|
1507
|
-
`pruneTargets`, which is also what the executable's
|
|
1508
|
-
|
|
1638
|
+
`pruneTargets`, which is also what the executable's merged report and preview read. Repair's
|
|
1639
|
+
optimistic-concurrency recheck receives the raw plan audit, while the separate foreign findings
|
|
1640
|
+
remain attached to reporting and exit status; after that recheck succeeds, the same preview snapshot
|
|
1641
|
+
drives deletion. Only the three prune directories are in scope; the allowlist must be
|
|
1509
1642
|
positively established from the vendored host, or the call fails closed rather than treating an
|
|
1510
1643
|
unresolved host as "vendors nothing" and proposing to delete everything. Each candidate is verified
|
|
1511
1644
|
as a plain physical file whose bytes still match the preview, moved into a private quarantine rather
|
|
@@ -1574,11 +1707,14 @@ fleet refresh is never partial. Files outside the discovered guide set remain un
|
|
|
1574
1707
|
|
|
1575
1708
|
A generated workspace is not a folder of suggestions; it is a working, gated project.
|
|
1576
1709
|
|
|
1577
|
-
**Manifest and scripts.** A published workspace is scoped
|
|
1578
|
-
|
|
1579
|
-
`
|
|
1580
|
-
|
|
1581
|
-
|
|
1710
|
+
**Manifest and scripts.** A published workspace is scoped, carries the Orkestrel GitHub homepage,
|
|
1711
|
+
issues, and repository identity, carries an `exports` map and publish configuration, and ships
|
|
1712
|
+
`dist/src` plus its README. An application-only workspace is unscoped and `private: true`, with no
|
|
1713
|
+
export map, publish configuration, or invented GitHub identity, and ships `dist/app`. Both carry
|
|
1714
|
+
`license: "MIT"` because every generated workspace receives the same host-owned MIT `LICENSE`.
|
|
1715
|
+
A workspace that builds its own executable additionally ships `dist/bin` and `dist/host`. Scripts
|
|
1716
|
+
are emitted in a fixed, interleaved order so aggregates sit immediately before their per-environment
|
|
1717
|
+
members:
|
|
1582
1718
|
|
|
1583
1719
|
- `clean`, `copy`, `scaffold`, `lint`
|
|
1584
1720
|
- `check`, then `check:src` with one `check:src:<environment>` per published environment, then
|
|
@@ -1586,7 +1722,8 @@ a fixed, interleaved order so aggregates sit immediately before their per-enviro
|
|
|
1586
1722
|
Vue typechecker, every other scope uses plain `tsc`
|
|
1587
1723
|
- `format`, `format:check`, `lint:check`
|
|
1588
1724
|
- `test`, then `test:src` and its per-environment scopes, the optional `test:integration`,
|
|
1589
|
-
`test:equivalence`, and `test:service`
|
|
1725
|
+
`test:equivalence`, and `test:service` aggregate followed by its sorted per-vendor proofs,
|
|
1726
|
+
`test:app` and its per-environment scopes, then
|
|
1590
1727
|
`test:policy`, `test:config`, and `test:guides`
|
|
1591
1728
|
- `build`, then `build:src` and its per-environment targets, `build:app` and its runtime targets, and
|
|
1592
1729
|
`build:host` for a bin workspace
|
|
@@ -1595,24 +1732,24 @@ a fixed, interleaved order so aggregates sit immediately before their per-enviro
|
|
|
1595
1732
|
- `showcase`, `build:showcase`, and `show` only when the physical showcase wrapper is present;
|
|
1596
1733
|
`show` formats, then builds, then copies `dist/showcase/index.html` to `demo/showcase.html`
|
|
1597
1734
|
- `prepublishOnly` chaining `format:check → lint:check → check → build → test`, followed by
|
|
1598
|
-
`test:integration` when
|
|
1735
|
+
`test:integration` when selected and finally `test:service` when any service is selected
|
|
1599
1736
|
|
|
1600
1737
|
**Proof gating.** The opt-in proofs are predictable from the axes alone. `test:integration` rides
|
|
1601
|
-
the `integration` axis and `test:service`
|
|
1738
|
+
the `integration` axis and `test:service` a nonempty `services` axis, while `test:equivalence` is emitted
|
|
1602
1739
|
only where `bin` and `integration` are both set:
|
|
1603
1740
|
|
|
1604
|
-
| Proof | `npm test` | `prepublishOnly`
|
|
1605
|
-
| ------------------ | ---------- |
|
|
1606
|
-
| `test:integration` | no | yes,
|
|
1607
|
-
| `test:equivalence` | no | no
|
|
1608
|
-
| `test:service` | no |
|
|
1741
|
+
| Proof | `npm test` | `prepublishOnly` | CI |
|
|
1742
|
+
| ------------------ | ---------- | ------------------- | -------------------------- |
|
|
1743
|
+
| `test:integration` | no | yes, before service | after the standard gates |
|
|
1744
|
+
| `test:equivalence` | no | no | no |
|
|
1745
|
+
| `test:service` | no | yes, last | after `scripts/service.sh` |
|
|
1609
1746
|
|
|
1610
1747
|
No opt-in proof joins the default chain: `npm test` runs the source, application, policy,
|
|
1611
1748
|
configuration, and guide projects, and nothing there needs a build artifact or a foreign process.
|
|
1612
|
-
Publication is the one
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1749
|
+
Publication is the one asymmetry: `prepublishOnly` appends integration and then service proofs.
|
|
1750
|
+
A package that claims to drive a vendor has not proved that claim unless publishing runs against
|
|
1751
|
+
it, despite the provisioning cost. Neither default testing nor publication starts a foreign
|
|
1752
|
+
process; publication requires the caller to provision one first.
|
|
1616
1753
|
The showcase is likewise outside `build`, `test`, and `prepublishOnly`; it is an explicit projection
|
|
1617
1754
|
of `app/browser`, not an environment, test-project row, or source/demo artifact.
|
|
1618
1755
|
Its copied `demo/showcase.html` is generated and minified, so the mirrored `.prettierignore` keeps it
|
|
@@ -1630,22 +1767,29 @@ The equivalence proof is a dual-path re-run rather than a separate suite. Run
|
|
|
1630
1767
|
integration project in dual-path mode and proves each programmatic driver verdict against the
|
|
1631
1768
|
spawned npm-script reference. Ordinary integration runs keep the faster driver-only path.
|
|
1632
1769
|
|
|
1633
|
-
**Consumer-owned service seams.**
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1770
|
+
**Consumer-owned service seams.** Each vendor owns its readiness module at
|
|
1771
|
+
`tests/service/<vendor>/setup.ts`. It probes and warms that vendor at module load, throwing a clear
|
|
1772
|
+
error when unavailable so only that vendor project fails readiness. The scaffold never generates
|
|
1773
|
+
these modules because an inert readiness check would be a false proof.
|
|
1774
|
+
|
|
1775
|
+
`scripts/service.sh`, named once by `SERVICE_SCRIPT_PATH`, is shared provisioning for every vendor.
|
|
1776
|
+
The scaffold emits a template skeleton that exits nonzero until the workspace replaces it with
|
|
1777
|
+
idempotent provisioning; an already-provisioned vendor must be a no-op, and any vendor that cannot
|
|
1778
|
+
be prepared must make the script fail. The skeleton is written at birth when services are already
|
|
1779
|
+
declared, or by repair when a post-birth vendor declaration makes it newly absent. Once present it
|
|
1780
|
+
is consumer-owned and never replaced. CI invokes it once before the aggregate project run.
|
|
1781
|
+
|
|
1782
|
+
The configuration conformance test lives in the ordinary `config` project, so `npm test` checks the
|
|
1783
|
+
directory names, readiness files, project declarations, scripts, default-test omission, and
|
|
1784
|
+
publication suffix without contacting a vendor. Like the provisioner it is repaired only when
|
|
1785
|
+
absent, then remains workspace-owned and audit-exempt. Service adoption under `--generated`
|
|
1786
|
+
regenerates the Vite and CI canon and merges only `test:service`, the per-vendor service scripts,
|
|
1787
|
+
and the `prepublishOnly` service suffix into `package.json`; publication metadata and unrelated
|
|
1788
|
+
scripts retain their existing values.
|
|
1645
1789
|
|
|
1646
1790
|
The audit expects the script rather than reporting it foreign, on the derive-time warrant the audit
|
|
1647
1791
|
section gives. Repair pruning applies the same exclusion, so it never proposes or removes that
|
|
1648
|
-
required
|
|
1792
|
+
required workspace-owned provisioner.
|
|
1649
1793
|
|
|
1650
1794
|
**Environment isolation.** Scoped TypeScript projects remove the wrong host's globals from each
|
|
1651
1795
|
environment: core scopes carry the WHATWG web-interop surface and no host at all — no DOM, no Node,
|
|
@@ -1881,8 +2025,13 @@ the proof-gating table gives them.
|
|
|
1881
2025
|
dependency, model, and external-tool readiness scripts at session start. The **`Stop` hook runs only
|
|
1882
2026
|
`git diff --check`** — a whitespace and conflict-marker check over the working tree, nothing more.
|
|
1883
2027
|
Bash invocation and sensitive reads are controlled by the **settings permission list, not by a guard
|
|
1884
|
-
script
|
|
1885
|
-
|
|
2028
|
+
script**. The allow list is closed and holds exactly two entries — `Bash(codex --version)` and
|
|
2029
|
+
`Bash(codex login *)` — because the orchestration contract requires a bench-liveness probe and a
|
|
2030
|
+
device-login recovery at session start, and prompting for those would stall every session before
|
|
2031
|
+
planning. Every other Bash command requires explicit approval, including commands Claude Code
|
|
2032
|
+
otherwise classifies as read-only. That list is inherited by every workspace in the line, so a
|
|
2033
|
+
machine-local grant belongs in `settings.local.json`, which `SENSITIVE_HOST_PATH_PATTERN` keeps out
|
|
2034
|
+
of every vendored host. Read-only reviewer, checker, and ecosystem roles carry no Bash tool; the
|
|
1886
2035
|
orchestrator supplies their diff and status evidence. Bridge, writer, and verifier roles request
|
|
1887
2036
|
approval when their bounded shell work is needed. Read patterns covering environment files,
|
|
1888
2037
|
package-manager credentials, credential stores, private keys, key stores, SSH, cloud credentials,
|
|
@@ -1905,7 +2054,7 @@ no module API of its own. Seven verbs:
|
|
|
1905
2054
|
| `pull` | refresh vendored guides and versions, report drift |
|
|
1906
2055
|
| `mirror` | refresh every published Orkestrel package guide |
|
|
1907
2056
|
| `audit` | whole-plan conformance report |
|
|
1908
|
-
| `repair` | restore
|
|
2057
|
+
| `repair` | restore missing canon; optionally replace drifted bytes |
|
|
1909
2058
|
| `fleet` | audit or repair every workspace under the cwd's children |
|
|
1910
2059
|
| `catalog` | regenerate the fleet package-catalog table |
|
|
1911
2060
|
|
|
@@ -1919,8 +2068,10 @@ Orkestrel short name. Other npm packages are not a creation-time flag — add th
|
|
|
1919
2068
|
manifest's development dependencies afterwards, and they round-trip through `deriveBlueprint`'s
|
|
1920
2069
|
extras so the workspace stays audit-clean.
|
|
1921
2070
|
|
|
1922
|
-
**Other flags.** `--target <path>` selects the directory a verb operates on
|
|
1923
|
-
|
|
2071
|
+
**Other flags.** `--target <path>` selects the directory a single-workspace verb operates on;
|
|
2072
|
+
`fleet --target` is a usage error because fleet's root is always the current directory.
|
|
2073
|
+
`--from <path>` points at a local template source instead of the bundled one and may be passed once
|
|
2074
|
+
to those verbs. It is repeatable only for `catalog`, where each occurrence adds one catalog source.
|
|
1924
2075
|
On `pull`, `--deps x,y` limits refresh to those declared Orkestrel dependencies; without it, every
|
|
1925
2076
|
declared dependency mirror is considered.
|
|
1926
2077
|
`mirror` accepts no dependency selection: its exact npm organization discovery is the operation's
|
|
@@ -1928,25 +2079,34 @@ scope, and it fetches guides without registry version or packument requests.
|
|
|
1928
2079
|
`--groups a,b` scopes an audit to artifact groups. `--live` adds an upstream freshness check to an
|
|
1929
2080
|
audit. `--strict` makes a pull or mirror throw on a network fault. `--offline` restricts a catalog to local
|
|
1930
2081
|
sources. `--prune` opts a repair or fleet run into deleting unexpected files under the three prune
|
|
1931
|
-
directories. `--generated` opts a repair or fleet run into
|
|
1932
|
-
`package.json
|
|
2082
|
+
directories. `--generated` opts a repair or fleet run into including generated canon while
|
|
2083
|
+
protecting `package.json` outside its generated service-script keys; on `audit`, it is inherited if
|
|
2084
|
+
the interactive repair hand-off is accepted.
|
|
2085
|
+
`--replace` authorizes repair to discard local changes in the drifted files named by its report; it
|
|
2086
|
+
composes with `--generated`, and is likewise inherited by an accepted audit hand-off.
|
|
1933
2087
|
`--json` emits one machine-readable value. `--apply` writes, `--yes` skips the confirmation, and
|
|
1934
2088
|
`-h` or `--help` prints usage.
|
|
1935
2089
|
|
|
1936
|
-
**Safety model.** Every verb is a dry run by default.
|
|
1937
|
-
|
|
2090
|
+
**Safety model.** Every verb is a dry run by default. `--apply` is the sole write authorization;
|
|
2091
|
+
`--yes` only skips a confirmation and never authorizes a write or deletion by itself. On a terminal
|
|
2092
|
+
an authorized write asks for confirmation first, defaulting to no; scripts do not prompt. Every write is
|
|
1938
2093
|
confined to the working directory, so the instruction is to change into it first rather than to pass
|
|
1939
2094
|
a root. `repair` asks a second, separately defaulted question before deleting anything, and a
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
2095
|
+
session without `--apply` skips pruning regardless of `--yes`. `fleet` operates on the immediate
|
|
2096
|
+
children of the working directory and never on the directory itself. It has no root flag at all:
|
|
2097
|
+
passing `--target` is rejected with exit `2` instead of being silently ignored. `repair` is the
|
|
2098
|
+
single-workspace tool.
|
|
2099
|
+
|
|
2100
|
+
`fleet` and default `repair` are scoped to host-origin artifacts plus absent service-owned starter
|
|
2101
|
+
seams. Both state that selected scope in the output before they act — `repair` once its audit found
|
|
2102
|
+
something to repair, `fleet` once `--apply` authorized a write, naming the number of repositories
|
|
2103
|
+
that write covers. `--generated` widens both verbs to generated
|
|
2104
|
+
files and the manifest's generated service-script keys while still excluding present starter files
|
|
2105
|
+
and package publication metadata. Within either scope, missing files are safe to restore, stale
|
|
2106
|
+
files are report-only by default, and `--replace` is the explicit destructive opt-in.
|
|
1947
2107
|
|
|
1948
2108
|
**Catalog markers.** `catalog` rewrites the block between `<!-- catalog:start -->` and
|
|
1949
|
-
`<!-- catalog:end -->` in `.
|
|
2109
|
+
`<!-- catalog:end -->` in `CATALOG_AGENT_PATH`. **Ambiguous markers fail before any
|
|
1950
2110
|
mutation**: the file must contain exactly one ordered pair. A missing marker, a reversed pair, or a
|
|
1951
2111
|
repeated marker of either kind is a coded `TARGET` failure raised before the file is touched, and
|
|
1952
2112
|
the run reports the drift and any row-count shrink rather than rewriting a file it cannot bound.
|
|
@@ -1958,10 +2118,16 @@ The check is a feature detection: **earlier supported Node 22 releases simply us
|
|
|
1958
2118
|
roots**. It only ever adds trusted issuers — nothing disables verification — and a failure is a
|
|
1959
2119
|
silent no-op rather than a crash. Custom PEMs are added through the standard environment variable.
|
|
1960
2120
|
|
|
1961
|
-
**Exit codes.** `0` is clean or successful, `1` is drift or failure, `2` is a usage error.
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
2121
|
+
**Exit codes.** `0` is clean or successful, `1` is drift or failure, `2` is a usage error. Repair
|
|
2122
|
+
and fleet use the same dirty-repository predicate: selected-scope drift or any full-plan finding
|
|
2123
|
+
outside that scope keeps exit `1`. A repair that skips stale files therefore exits `1`; a repair
|
|
2124
|
+
exits `0` only when its selected audit and its reported outside scope are both clean. An audit exits
|
|
2125
|
+
non-zero on any drift, foreign files included, which makes it usable directly as a CI gate.
|
|
2126
|
+
`repair --json` carries that same terminal audit after any authorized write, while its `result`
|
|
2127
|
+
records the files the write copied, wrote, skipped, and removed. A pull exits non-zero on any drift
|
|
2128
|
+
or failure whether or not `--strict` was passed, including when
|
|
2129
|
+
other entries were applied successfully; `--strict` additionally throws on a network fault. Every
|
|
2130
|
+
unknown verb is a usage error and gets a nearest-match
|
|
1965
2131
|
suggestion when one is sufficiently close.
|
|
1966
2132
|
|
|
1967
2133
|
## Package contents
|
|
@@ -1972,7 +2138,8 @@ files, plus `./package.json`. The `scaffold` binary maps to the built executable
|
|
|
1972
2138
|
|
|
1973
2139
|
The published file set is exactly `dist/src`, `dist/bin`, `dist/host`, and `README.md`. `dist/host`
|
|
1974
2140
|
is the vendored data root: the byte-preserved host files plus the `manifest.json` recording their
|
|
1975
|
-
storage names, destinations,
|
|
2141
|
+
storage names, destinations, executable bits, directory roots, and membership digest. Storage names
|
|
2142
|
+
are un-dotted, because a leading dot
|
|
1976
2143
|
does not survive packaging intact; the manifest is what maps a storage name back to its real
|
|
1977
2144
|
destination. That is also why the default host is resolved from the installed module's own
|
|
1978
2145
|
location — the package carries its host data with itself, and a caller-supplied raw repository root
|
|
@@ -2368,10 +2535,14 @@ configViteProject()
|
|
|
2368
2535
|
guidesViteProject()
|
|
2369
2536
|
binViteProject()
|
|
2370
2537
|
integrationViteProject({ bin: true, integration: true, global: true })
|
|
2371
|
-
serviceViteProject()
|
|
2372
|
-
viteProjectDefinitions({ integration: true }).includes(
|
|
2373
|
-
|
|
2374
|
-
//
|
|
2538
|
+
serviceViteProject('claude')
|
|
2539
|
+
viteProjectDefinitions({ integration: true, services: ['claude'] }).includes(
|
|
2540
|
+
'export const serviceClaude =',
|
|
2541
|
+
) // true
|
|
2542
|
+
viteProjectRegistrations(['core'], [], { integration: true, services: ['claude'] }).map(
|
|
2543
|
+
({ project }) => project,
|
|
2544
|
+
)
|
|
2545
|
+
// ['srcCore', 'policy', 'config', 'guides', 'integration', 'serviceClaude']
|
|
2375
2546
|
|
|
2376
2547
|
rootViteConfig(['core', 'server'], { bin: true })
|
|
2377
2548
|
singleSrcViteConfig('server').includes('srcServer') // true
|
|
@@ -2411,6 +2582,7 @@ syncReportOf('./packages/router', [], []) // { clean: true, failed: 0, … }
|
|
|
2411
2582
|
import { blueprint, blueprintToPlan, diffPlan } from '@orkestrel/scaffold'
|
|
2412
2583
|
import {
|
|
2413
2584
|
createMaterializer,
|
|
2585
|
+
digestHostManifest,
|
|
2414
2586
|
hostRoot,
|
|
2415
2587
|
hydratePlan,
|
|
2416
2588
|
isVacant,
|
|
@@ -2424,6 +2596,7 @@ import {
|
|
|
2424
2596
|
} from '@orkestrel/scaffold/server'
|
|
2425
2597
|
|
|
2426
2598
|
const host = hostRoot()
|
|
2599
|
+
digestHostManifest([], []) // exact empty manifest membership digest
|
|
2427
2600
|
readHostManifest(host) // the vendored manifest, or undefined for a raw root
|
|
2428
2601
|
storagePath('.claude/agents/reviewer.md') // 'claude/agents/reviewer.md'
|
|
2429
2602
|
locateHostSource(undefined, 'package.json', host)
|
|
@@ -2443,7 +2616,8 @@ const current = readTarget(
|
|
|
2443
2616
|
'./packages/router',
|
|
2444
2617
|
plan.artifacts.map((artifact) => artifact.path),
|
|
2445
2618
|
)
|
|
2446
|
-
materializer.repair(plan, diffPlan(plan, current), './packages/router')
|
|
2619
|
+
materializer.repair(plan, diffPlan(plan, current), './packages/router') // missing only; stale is skipped
|
|
2620
|
+
materializer.repair(plan, diffPlan(plan, current), './packages/router', true) // replace stale bytes
|
|
2447
2621
|
materializer.prune('./packages/router', {})
|
|
2448
2622
|
materializer.destroy()
|
|
2449
2623
|
|
|
@@ -2638,7 +2812,11 @@ hasOnlyDataProperties({ a: 1 }) // true
|
|
|
2638
2812
|
isDenseDataArray(['a'], 10, isPortablePath) // true
|
|
2639
2813
|
isWritePrecondition({ path: 'package.json', shape: 'absent' }) // true
|
|
2640
2814
|
isManifestEntry({ storage: 'AGENTS.md', destination: 'AGENTS.md', executable: false }) // true
|
|
2641
|
-
isHostManifest({
|
|
2815
|
+
isHostManifest({
|
|
2816
|
+
entries: [],
|
|
2817
|
+
roots: [],
|
|
2818
|
+
digest: 'f98e1531d9fd8fab7e301d1cc944249913d93f48c918a11a753048b877211679',
|
|
2819
|
+
}) // true
|
|
2642
2820
|
isSyncEventHooks({ done: () => undefined }) // true
|
|
2643
2821
|
isMaterializerEventHooks({ done: () => undefined }) // true
|
|
2644
2822
|
isEmitterErrorHandler(() => undefined) // true
|