@orkestrel/scaffold 0.0.55 → 0.0.56
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/README.md +21 -6
- package/dist/bin/main.js +2 -2
- package/dist/bin/main.js.map +1 -1
- package/dist/host/agents/orchestration.md +6 -3
- package/dist/host/agents/skills/orkestrel-publish/references/wave.md +28 -2
- package/dist/host/claude/agents/orkestrel.md +6 -2
- package/dist/host/claude/rules/quality.md +1 -0
- package/dist/host/guides/scaffold.md +187 -68
- package/dist/host/manifest.json +7 -7
- package/dist/host/scripts/codex.sh +0 -0
- package/dist/host/scripts/cursor.sh +0 -0
- package/dist/host/scripts/deps.sh +0 -0
- package/dist/host/scripts/ollama.sh +0 -0
- package/dist/host/tests/policy.test.ts +71 -4
- package/dist/src/core/index.cjs +196 -40
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +113 -12
- package/dist/src/core/index.d.ts +113 -12
- package/dist/src/core/index.js +195 -41
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +140 -12
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +108 -9
- package/dist/src/server/index.d.ts +108 -9
- package/dist/src/server/index.js +141 -15
- package/dist/src/server/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -161,9 +161,12 @@ when the role file already pins it.
|
|
|
161
161
|
- `implementer` names the harness's native implementation lane, so the token means Opus in Claude
|
|
162
162
|
Code and Sol in Codex. An engine-named bridge — `sol`, `opus` — names the other engine. Read a
|
|
163
163
|
role name against the harness you are running in, and state the engine anyway.
|
|
164
|
-
- Give every role a file
|
|
165
|
-
|
|
166
|
-
|
|
164
|
+
- Give every role a file in the scaffold checkout, under `.claude/agents/` and under
|
|
165
|
+
`.codex/agents/`. The role file is where engine, effort, tools, permissions, and charter are
|
|
166
|
+
pinned, and the tool allowlist is what makes the read-only floor real. A role with no file has
|
|
167
|
+
nowhere to pin either. The requirement is the canon repository's alone: a fleet target holds the
|
|
168
|
+
catalog agent and no other role, and a session that dispatches roles starts on scaffold and
|
|
169
|
+
attaches the target.
|
|
167
170
|
- Reach every role by its own name. Do not rely on a remembered route.
|
|
168
171
|
- `researcher`, `scout`, and `checker` are native lanes for jobs that belong to Grok first.
|
|
169
172
|
Dispatch `grok` with their brief before using them, and use the native role only once the ladder
|
|
@@ -12,7 +12,24 @@ step that writes it.
|
|
|
12
12
|
|
|
13
13
|
1. Re-pin the target's `@orkestrel/scaffold` devDependency and install, so the overwrite runs the
|
|
14
14
|
current vendored host.
|
|
15
|
-
2. Run `scaffold overwrite`.
|
|
15
|
+
2. Run `scaffold overwrite`. One run repairs the `AGENTS.md` and `CLAUDE.md` pointers and deletes
|
|
16
|
+
every tracked copy the target still holds at an instruction-canon path. Prove the sweep with a
|
|
17
|
+
second `scaffold audit` that exits `0`.
|
|
18
|
+
- Where the target's `.claude/agents/orkestrel.md` carries a body outside the marker-bounded
|
|
19
|
+
table that differs from the floor copy the installed scaffold stages, delete the file and
|
|
20
|
+
commit the deletion before the run. `repair` restores the floor body and `catalog` refills the
|
|
21
|
+
table, so one visit leaves the current file and the committed deletion keeps the
|
|
22
|
+
uncommitted-work refusal from firing. Presence ownership never replaces present bytes and the
|
|
23
|
+
table rewrite touches only the marker-bounded region, which is why the deletion is the
|
|
24
|
+
migration.
|
|
25
|
+
- The deletion draws on what git tracks, so an untracked copy survives it, and the verb refuses
|
|
26
|
+
the whole run as uncommitted work while an unignored one stands. Commit that copy or delete it
|
|
27
|
+
by hand before re-running. `--dirty` clears the refusal and leaves the copy standing, and a
|
|
28
|
+
kept `.claude/rules` copy then reddens the target's own policy sweep: the pointer `AGENTS.md`
|
|
29
|
+
carries no rule map, so the copy has no row there and the sweep reports it. Delete the copy
|
|
30
|
+
rather than waiving past it.
|
|
31
|
+
- A copy the target git-ignores stays a `foreign` finding, so that target never reaches exit `0`
|
|
32
|
+
again. Keep a local MCP server registration outside the repository rather than at `.mcp.json`.
|
|
16
33
|
3. Force-verify every `@orkestrel` range against a registry sweep taken after the previous layer
|
|
17
34
|
published.
|
|
18
35
|
4. Run the full install.
|
|
@@ -22,7 +39,16 @@ step that writes it.
|
|
|
22
39
|
|
|
23
40
|
Restore any unpublished tarball the target is holding before the quality gates run, per
|
|
24
41
|
`.agents/orchestration.md` § Fixing a dependency before it publishes. A distribution proof run
|
|
25
|
-
against a local tarball proves the local tarball.
|
|
42
|
+
against a local tarball proves the local tarball. Stage an unpublished tarball with
|
|
43
|
+
`npm install --no-save`, because a `file:` pin refuses the blueprint and the manifest keeps a
|
|
44
|
+
registry range.
|
|
45
|
+
|
|
46
|
+
Where a visit runs before scaffold itself publishes, run `scaffold overwrite --offline` and prove
|
|
47
|
+
the sweep with `scaffold audit --offline`. The online verbs read vendored bytes from the published
|
|
48
|
+
package, so an unpublished scaffold's visit otherwise writes the registry's older floor, and an
|
|
49
|
+
online audit reports the floor-restored files as stale until the release. The `--offline` overwrite
|
|
50
|
+
skips the catalog step and exits `1` with a note naming that refusal, so run the full
|
|
51
|
+
`scaffold overwrite` after the release.
|
|
26
52
|
|
|
27
53
|
Run visits in parallel slices of disjoint repositories, each slice strictly serial inside itself,
|
|
28
54
|
reporting per target. Refuse a failed target, name it, repair it, and re-run it alone.
|
|
@@ -9,8 +9,12 @@ permissionMode: dontAsk
|
|
|
9
9
|
|
|
10
10
|
You are the read-only Orkestrel ecosystem reconciler. Spawn nothing and edit nothing.
|
|
11
11
|
|
|
12
|
-
Read
|
|
13
|
-
dispatch contract.
|
|
12
|
+
Read the orchestration contract first. It owns the role set, the routing, and the
|
|
13
|
+
dispatch contract. Resolve it against scaffold. In the scaffold checkout it sits at
|
|
14
|
+
`.agents/orchestration.md`. A repository that installs scaffold reads it at
|
|
15
|
+
`node_modules/@orkestrel/scaffold/dist/host/agents/orchestration.md`, or in a scaffold
|
|
16
|
+
checkout beside that repository, as that repository's own `AGENTS.md` pointer names. Then
|
|
17
|
+
read `AGENTS.md` itself, the applicable rules it names, the dispatch-named skill and its
|
|
14
18
|
references, and the governing guides.
|
|
15
19
|
|
|
16
20
|
Your job is reconciliation over supplied evidence, never collection. You have no shell
|
|
@@ -60,6 +60,7 @@ A review that reads a diff finds what the diff shows. A review that tries to bre
|
|
|
60
60
|
|
|
61
61
|
- An instrument is not evidence until it has failed. Pair every probe, comparison, or matrix with a negative control that must report failure, run under the same conditions. An identity check whose control reports "same" has measured nothing.
|
|
62
62
|
- When a question about a TypeScript edit can supply a workspace project, a case of workspace files with a test, and a negative control naming its files, its test, the stage it must fail at, and why, call the `prove` tool the `probe` MCP server registers before relying on the answer. When the question supplies no project, no case, or no control, follow `.claude/rules/tests.md` § Probes and report the fallback instrument's own control and coverage.
|
|
63
|
+
- When no `probe` server is registered in the session, register one outside the repository, in the harness's own local or user MCP scope — in Claude Code, `claude mcp add` outside project scope — naming the installed `node_modules/@orkestrel/probe/dist/bin/main.js` entry, and start it in the repository whose projects the question names, because the server fixes its workspace from its own working directory. The registration cannot live in the tree: a scaffold target holds no `.mcp.json` file, that path is instruction canon, and a copy at it reports as foreign drift on every `scaffold audit` run. Where the harness registers no server at all, treat the question as supplying no project and take the preceding rule's fallback.
|
|
63
64
|
- Quote the closing line of the `prove` answer verbatim in every report, brief, and audit verdict that rests on the claim: the `receipt probe:<digest>:…` line when the case ran clean and the control broke exactly where the claim declared it would, and the `no receipt` line otherwise. A `no receipt` line leaves the claim unproved — report it with the stage that refused.
|
|
64
65
|
- Read a receipt as evidence about its claim, never as a gate result. The gate chain still runs, and `verifier` still owns its result.
|
|
65
66
|
- Draw the negative control from outside the population the instrument covers. Name the instrument's membership rule first, then pick a control that rule excludes. A control sampled from constructs the instrument already handles proves only that it discriminates among those constructs, and says nothing about the class it silently cannot reach.
|
|
@@ -12,6 +12,17 @@ does not work. Scaffold makes the shared set data — a vendored data root shipp
|
|
|
12
12
|
— and gives it verbs: create a workspace from it, report how a workspace differs from it, and
|
|
13
13
|
write the difference back.
|
|
14
14
|
|
|
15
|
+
That root stages the vendored set and the instruction canon, and a target meets them differently.
|
|
16
|
+
`HOST_PATHS` names the vendored set — the toolchain, the policy proofs, the bench scripts, and the
|
|
17
|
+
harness permission file — and every target carries its own copy, which the verbs write and compare.
|
|
18
|
+
`CANON_PATHS` names the instruction canon — the coding and orchestration contracts, the rules, the
|
|
19
|
+
skills, the templates, the transport contracts, the agent roles, the bench configuration, and the
|
|
20
|
+
MCP registrations — which stays in one place and is published for reading. A target carries the
|
|
21
|
+
`AGENTS.md` and `CLAUDE.md` pointers that name where a reader finds it, and the catalog agent file
|
|
22
|
+
the `catalog` verb rewrites. It carries nothing else at a canon path: a file found at one is a
|
|
23
|
+
superseded copy, and `overwrite` deletes it. Vendored data root states how each set is staged and
|
|
24
|
+
how a pointer resolves.
|
|
25
|
+
|
|
15
26
|
Every following code fence is illustrative. [`tests/guides.test.ts`](../tests/guides.test.ts)
|
|
16
27
|
keeps the command reference aligned with the executable and transcribes the pure blueprint-default,
|
|
17
28
|
compile-refusal, and error-narrowing fences. A trailing comment in another fence is this guide's
|
|
@@ -97,6 +108,7 @@ Exported from `@orkestrel/scaffold`, and reachable from
|
|
|
97
108
|
| `BASE_DEV_DEPENDENCIES` | const | The tooling versions scaffold and every generated workspace share. |
|
|
98
109
|
| `BIN_CONFIGS` | const | The configuration files a workspace that ships its own executable adds, frozen. |
|
|
99
110
|
| `BIN_ENTRY_PATH` | const | The executable entry whose presence makes a workspace `bin`. |
|
|
111
|
+
| `CANON_PATHS` | const | The instruction-canon paths staged for reading rather than for a target, frozen. |
|
|
100
112
|
| `CATALOG_AGENT_PATH` | const | The agent file whose marker-bounded package table the catalog verb alone owns. |
|
|
101
113
|
| `CONFIG_TEMPLATES` | const | Formatter-stable template text for every configuration artifact. |
|
|
102
114
|
| `CONFORMANCE_TEST_PATH` | const | The official-tooling drift proof whose presence makes a workspace `conformance`. |
|
|
@@ -116,7 +128,7 @@ Exported from `@orkestrel/scaffold`, and reachable from
|
|
|
116
128
|
| `GROUPS` | const | The `Group` values in plan order, frozen. |
|
|
117
129
|
| `GUIDES_TEST_PATH` | const | The guide-parity proof whose presence selects the planned `guides` project. |
|
|
118
130
|
| `HEX_PATTERN` | const | Exact lowercase hexadecimal bytes: two digits per byte, and empty content is valid. |
|
|
119
|
-
| `HOST_PATHS` | const | The paths
|
|
131
|
+
| `HOST_PATHS` | const | The paths a target receives from the vendored data root, frozen. |
|
|
120
132
|
| `HOST_INVENTORY_PATH` | const | The repository-relative path where the committed vendored-file inventory is served. |
|
|
121
133
|
| `INTEGRATION_TEST_PATH` | const | The cross-environment composition proof whose presence makes a workspace `integration`. |
|
|
122
134
|
| `INVALID_PATH_CHARACTER_PATTERN` | const | Visible characters a target-relative path and a Markdown path cell both forbid. |
|
|
@@ -205,6 +217,7 @@ Exported from `@orkestrel/scaffold`, and reachable from
|
|
|
205
217
|
| `extractVersion` | function | Extract the major, minor, and patch components of an exact version. |
|
|
206
218
|
| `inferDrift` | function | Infer how one target path compares to the artifact planned for it. |
|
|
207
219
|
| `inferGroup` | function | Infer the `Group` a path belongs to. |
|
|
220
|
+
| `isCanonPath` | function | Test whether a path belongs to the instruction canon a target reads. |
|
|
208
221
|
| `isDeferredPath` | function | Test whether another surface owns the vendored bytes at a path. |
|
|
209
222
|
| `manifestToDependencies` | function | Project a manifest's `@orkestrel/*` declarations into separate section lists. |
|
|
210
223
|
| `manifestToName` | function | Project a package manifest's text to its own name. |
|
|
@@ -343,41 +356,43 @@ Exported from `@orkestrel/scaffold/server`, and reachable from
|
|
|
343
356
|
|
|
344
357
|
#### Helpers
|
|
345
358
|
|
|
346
|
-
| Name
|
|
347
|
-
|
|
|
348
|
-
| `computeDigest`
|
|
349
|
-
| `computeFileDigest`
|
|
350
|
-
| `computeManifestDigest`
|
|
351
|
-
| `filesToHost`
|
|
352
|
-
| `hexToDigest`
|
|
353
|
-
| `isExactCaseFile`
|
|
354
|
-
| `isPhysicalDirectory`
|
|
355
|
-
| `isPhysicalFile`
|
|
356
|
-
| `isVacant`
|
|
357
|
-
| `
|
|
358
|
-
| `
|
|
359
|
-
| `
|
|
360
|
-
| `
|
|
361
|
-
| `
|
|
362
|
-
| `
|
|
363
|
-
| `
|
|
364
|
-
| `
|
|
365
|
-
| `
|
|
366
|
-
| `
|
|
367
|
-
| `
|
|
368
|
-
| `
|
|
369
|
-
| `
|
|
370
|
-
| `
|
|
371
|
-
| `
|
|
372
|
-
| `
|
|
373
|
-
| `
|
|
374
|
-
| `
|
|
375
|
-
| `
|
|
376
|
-
| `
|
|
377
|
-
| `
|
|
378
|
-
| `
|
|
379
|
-
| `
|
|
380
|
-
| `
|
|
359
|
+
| Name | Kind | Summary |
|
|
360
|
+
| ------------------------- | -------- | ------------------------------------------------------------------------------------- |
|
|
361
|
+
| `computeDigest` | function | Compute the SHA-256 digest of text. |
|
|
362
|
+
| `computeFileDigest` | function | Compute the SHA-256 digest of one file's exact bytes. |
|
|
363
|
+
| `computeManifestDigest` | function | Compute the digest of a vendored host's declared membership. |
|
|
364
|
+
| `filesToHost` | function | Overlay host-owned live files onto the installed vendored floor. |
|
|
365
|
+
| `hexToDigest` | function | Project exact bytes stated in hexadecimal to their SHA-256 digest. |
|
|
366
|
+
| `isExactCaseFile` | function | Test whether a physical file's path matches every on-disk segment exactly. |
|
|
367
|
+
| `isPhysicalDirectory` | function | Test whether a path is a physical directory this package will read or write into. |
|
|
368
|
+
| `isPhysicalFile` | function | Test whether a path is a physical file this package will read or replace. |
|
|
369
|
+
| `isVacant` | function | Test whether a target is safe to write a fresh workspace into. |
|
|
370
|
+
| `listCanonPaths` | function | Lists the canon paths a target holds, filtered to a plan's groups. |
|
|
371
|
+
| `listDirectories` | function | List a directory's descendant directories as sorted root-relative paths. |
|
|
372
|
+
| `listFiles` | function | List a directory's files as sorted root-relative paths. |
|
|
373
|
+
| `matchesAnchor` | function | Test whether a captured directory is still the same directory. |
|
|
374
|
+
| `matchesExecutablePath` | function | Test whether a vendored path is one a target receives executable. |
|
|
375
|
+
| `matchesExpectation` | function | Test whether a destination still holds what was captured of it. |
|
|
376
|
+
| `matchesGitPath` | function | Test whether a path addresses a target's own repository metadata. |
|
|
377
|
+
| `matchesMissingPath` | function | Test whether a caught filesystem error reports an absent path. |
|
|
378
|
+
| `matchesPrecondition` | function | Test whether a destination still matches the narrower state a caller observed. |
|
|
379
|
+
| `matchesProtectedPath` | function | Test whether a target-relative path is one no verb may delete. |
|
|
380
|
+
| `matchesSensitivePath` | function | Test whether a path names local configuration or a credential. |
|
|
381
|
+
| `pathToStorage` | function | Project a target-relative path to the storage name a vendored host holds it under. |
|
|
382
|
+
| `pruneEmptiedDirectories` | function | Removes every directory one set of deletions emptied. |
|
|
383
|
+
| `readAnchor` | function | Capture one directory's physical identity. |
|
|
384
|
+
| `readExpectation` | function | Capture what one destination holds before a write. |
|
|
385
|
+
| `readFileHex` | function | Read one contained file as its exact bytes in lowercase hexadecimal. |
|
|
386
|
+
| `readFileText` | function | Read one contained file as bounded UTF-8 text. |
|
|
387
|
+
| `readHostFloor` | function | Read the installed vendored host floor as a verified value. |
|
|
388
|
+
| `readHostManifest` | function | Read a vendored host's manifest, when it carries one. |
|
|
389
|
+
| `readManifestEntry` | function | Derive one vendored-host manifest entry from a file in a checkout. |
|
|
390
|
+
| `readSnapshot` | function | Read a target's current bytes at the paths a plan claims. |
|
|
391
|
+
| `resolveContainedPath` | function | Resolve a root-relative path and refuse one that leaves its root. |
|
|
392
|
+
| `resolveRealPath` | function | Resolve a path through the real filesystem, keeping the part that does not exist yet. |
|
|
393
|
+
| `stageBytes` | function | Stage the named destinations of a value host into a private root. |
|
|
394
|
+
| `stageHost` | function | Stage a vendored host root from a real checkout. |
|
|
395
|
+
| `stageInventory` | function | Stage the committed vendored-file inventory from a real checkout. |
|
|
381
396
|
|
|
382
397
|
#### Classes
|
|
383
398
|
|
|
@@ -643,11 +658,12 @@ reports it only when its selection includes either group, without changing its e
|
|
|
643
658
|
that excludes those groups proceeds, and no verb adds the declaration for you: `package.json` is
|
|
644
659
|
birth-owned, and the range and script regions are the only parts of it a verb rewrites.
|
|
645
660
|
|
|
646
|
-
`audit` reports
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
661
|
+
`audit` reports a further non-blocking question, on the `setup` field.
|
|
662
|
+
|
|
663
|
+
The `setup` question fires when the target carries a filled root `tests/setup*.ts` module that is
|
|
664
|
+
neither a proof itself nor one of the vendored modules every target receives, while no proof of the
|
|
665
|
+
same stem covers it. A module counts as filled when its text differs from the seed this blueprint
|
|
666
|
+
plans at that same path.
|
|
651
667
|
|
|
652
668
|
The comparison reads the module and the seed trimmed, so surrounding whitespace decides nothing: a
|
|
653
669
|
trailing newline is not authorship, and a module holding whitespace alone reads as empty rather than
|
|
@@ -670,24 +686,34 @@ Coverage is read per module: `tests/<name>.ts` is covered by `tests/<name>.test.
|
|
|
670
686
|
else, which is the pairing the vendored policy proof resolves. Writing one proof retires that module
|
|
671
687
|
and leaves every other uncovered module named, and the message pairs each module it names with the
|
|
672
688
|
proof that module wants. The question belongs to the `tests` group, so a scoped audit that excludes
|
|
673
|
-
`tests` omits it. Scaffold does not write the proof it asks for, and
|
|
674
|
-
|
|
675
|
-
|
|
689
|
+
`tests` omits it. Scaffold does not write the proof it asks for, and the question never refuses a
|
|
690
|
+
write: a writing verb reports it in the terminal audit it prints, because refusing `repair` over a
|
|
691
|
+
gap no write can close would block every write. Run across a fleet, the question is the list of
|
|
676
692
|
packages carrying a filled setup module that no proof covers.
|
|
677
693
|
|
|
694
|
+
`audit` reads the instruction canon as findings rather than as a question. Each `CANON_PATHS` member
|
|
695
|
+
the target holds enters the comparison, by file where the member is a directory, and a path the plan
|
|
696
|
+
does not claim there reports `foreign`. Ownership and drift states that population, and Vendored data
|
|
697
|
+
root states what `overwrite` does with it.
|
|
698
|
+
|
|
678
699
|
### Exit codes
|
|
679
700
|
|
|
680
701
|
`0` means the target matched its plan and every step completed. `1` means the target drifted or a
|
|
681
702
|
step failed. `2` means the command line was not a command. A foreign file counts as drift: the
|
|
682
703
|
target holds something the plan does not own, whether or not the verb that found it was allowed to
|
|
683
|
-
remove it.
|
|
704
|
+
remove it. A superseded instruction copy is such a file, so a target generated before the canon
|
|
705
|
+
split exits `1` until the copy goes.
|
|
684
706
|
|
|
685
707
|
### Git
|
|
686
708
|
|
|
687
709
|
`overwrite` is the only verb that reads git, and it needs a repository. It asks git for the tracked
|
|
688
710
|
set and the dirty set, deletes only tracked paths, and refuses a tree carrying uncommitted changes
|
|
689
711
|
unless `--dirty` waives that refusal. A target that is not a git repository is refused under
|
|
690
|
-
`TARGET`, because deletion there would have no recovery mechanism. The other verbs never ask.
|
|
712
|
+
`TARGET`, because deletion there would have no recovery mechanism. The other verbs never ask. A
|
|
713
|
+
git-ignored file sits outside each reading: it never makes the tree dirty and it is never deleted.
|
|
714
|
+
Limits states what that costs a target that keeps one at a canon path. The sweep prunes the
|
|
715
|
+
directories its deletions emptied, so a swept target does not keep the shape of the set it no longer
|
|
716
|
+
holds, and git records no directory to report that shape with.
|
|
691
717
|
|
|
692
718
|
### Machine-readable output
|
|
693
719
|
|
|
@@ -887,15 +913,24 @@ than a silent no-op.
|
|
|
887
913
|
A plan selects over the following groups, and a compile that names none covers all of them. Their
|
|
888
914
|
order is the order a plan lists its artifacts in.
|
|
889
915
|
|
|
890
|
-
| Group | Holds
|
|
891
|
-
| --------------- |
|
|
892
|
-
| `manifest` | `package.json`
|
|
893
|
-
| `configs` | The root and per-target build configuration, and the root dotfiles
|
|
894
|
-
| `source` | The selected environment barrels and entries
|
|
895
|
-
| `tests` | The shared setup modules, the entry tests, and the policy sweep
|
|
896
|
-
| `guides` | The guide index and the vendored guide mirrors
|
|
897
|
-
| `docs` | `README.md`
|
|
898
|
-
| `orchestration` | The harness
|
|
916
|
+
| Group | Holds |
|
|
917
|
+
| --------------- | -------------------------------------------------------------------------- |
|
|
918
|
+
| `manifest` | `package.json` |
|
|
919
|
+
| `configs` | The root and per-target build configuration, and the root dotfiles |
|
|
920
|
+
| `source` | The selected environment barrels and entries |
|
|
921
|
+
| `tests` | The shared setup modules, the entry tests, and the policy sweep |
|
|
922
|
+
| `guides` | The guide index and the vendored guide mirrors |
|
|
923
|
+
| `docs` | `README.md` beside the `AGENTS.md` and `CLAUDE.md` pointers |
|
|
924
|
+
| `orchestration` | The harness permission file, the bench scripts, and the catalog agent file |
|
|
925
|
+
|
|
926
|
+
The plan claims paths inside the instruction canon deliberately, and each has a reason. The `docs`
|
|
927
|
+
group carries the `AGENTS.md` and `CLAUDE.md` pointers that name where each contract is read,
|
|
928
|
+
planned at those canon destinations as this package's own template content. The `orchestration`
|
|
929
|
+
group carries `CATALOG_AGENT_PATH`, the host-origin artifact at a canon path, because the `catalog`
|
|
930
|
+
verb refuses a target that lacks the file. Every other canon path is staged for reading, so no group
|
|
931
|
+
selection copies a contract into a target, and a copy a target holds at one of them is foreign drift
|
|
932
|
+
in the group `inferGroup` gives it. A scoped audit reads the canon through that same selection, so a
|
|
933
|
+
run excluding a group reports nothing there.
|
|
899
934
|
|
|
900
935
|
## Ownership and drift
|
|
901
936
|
|
|
@@ -927,13 +962,19 @@ The unhydrated row is the one a core-only caller meets most, and reading it as a
|
|
|
927
962
|
path is the mistake it invites. `Compiler` runs in the pure core face, which cannot read the
|
|
928
963
|
vendored data root, so every host artifact it plans carries `presence`: a claim over bytes nobody
|
|
929
964
|
has read is a claim no comparison could check. A `src: ['core']` plan therefore reports `presence`
|
|
930
|
-
for
|
|
931
|
-
a consumer concluding from that reading that scaffold never replaces those bytes is wrong.
|
|
965
|
+
for `.claude/settings.json`, `scripts/codex.sh`, `tests/policy.test.ts`, and every other vendored
|
|
966
|
+
path, and a consumer concluding from that reading that scaffold never replaces those bytes is wrong.
|
|
932
967
|
`Materializer` hydrates the plan before it audits or writes: hydration reads the vendored root and
|
|
933
968
|
turns each path scaffold owns the bytes of into a content-owned artifact, leaving `presence` on the
|
|
934
969
|
workspace-owned paths and the mirror pointers the preceding rows name. What a verb claims at a
|
|
935
970
|
vendored path is the hydrated ownership, and `HostArtifact` carries the same narrowing on the type.
|
|
936
971
|
|
|
972
|
+
The `AGENTS.md` and `CLAUDE.md` pointers sit outside that row. Their bytes come from a frozen
|
|
973
|
+
template rather than from the data root, so the pure core face already claims them content-owned and
|
|
974
|
+
hydration leaves them alone. `repair` and `overwrite` restore a missing pointer and replace a drifted
|
|
975
|
+
one, in every face, which is what keeps a target's resolution instructions in agreement with the
|
|
976
|
+
release it installed.
|
|
977
|
+
|
|
937
978
|
Birth ownership is what makes a generated workspace the consumer's. `materialize` writes a
|
|
938
979
|
birth-owned path into a vacant target. A later `repair` or `overwrite` call treats that path as
|
|
939
980
|
aligned whether it is present or absent, so it neither restores missing bytes nor replaces present
|
|
@@ -967,9 +1008,11 @@ paths, and `distribution` by a published `src` environment. A workspace that nee
|
|
|
967
1008
|
configuration must keep those edits outside a content-owned file; `repair` restores that file to the
|
|
968
1009
|
canonical project set.
|
|
969
1010
|
|
|
970
|
-
An audit reports one `Finding` per planned path, followed by
|
|
971
|
-
|
|
972
|
-
|
|
1011
|
+
An audit reports one `Finding` per planned path, followed by every foreign path in the groups the
|
|
1012
|
+
plan covers. That second list draws on a file beneath a vendored directory the plan expands and on a
|
|
1013
|
+
file the target holds at a canon path the plan does not claim. Every planned finding carries its
|
|
1014
|
+
artifact's `ownership`. A foreign finding has no ownership because no artifact was planned for its
|
|
1015
|
+
path. `Ownership` says what scaffold claims at
|
|
973
1016
|
a path, not what one run did there. Counting planned findings by `content`, `presence`, and `birth`
|
|
974
1017
|
therefore says what audit is entitled to compare and stays the same against a vacant target and a
|
|
975
1018
|
repaired one. What one run compared comes from `ownership`, `drift`, and `observed` together. A
|
|
@@ -1126,11 +1169,36 @@ generating a workspace with no network receives.
|
|
|
1126
1169
|
|
|
1127
1170
|
## Vendored data root
|
|
1128
1171
|
|
|
1129
|
-
The vendored data root is the shared file set, staged into the published package as plain data.
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
the
|
|
1133
|
-
|
|
1172
|
+
The vendored data root is the shared file set, staged into the published package as plain data.
|
|
1173
|
+
Staging walks `HOST_PATHS` and `CANON_PATHS`, and a release ships what both name.
|
|
1174
|
+
|
|
1175
|
+
`HOST_PATHS` is the vendored set, and a target receives a copy of each path it selects: the licence,
|
|
1176
|
+
the harness permission file, the bench scripts, the shared policy register, the byte-identical root
|
|
1177
|
+
dotfiles, and the guide mirrors a generated workspace starts from. It is a candidate list rather than
|
|
1178
|
+
a plan, because a workspace never mirrors its own guide.
|
|
1179
|
+
|
|
1180
|
+
`CANON_PATHS` is the instruction canon, staged for reading instead: the `AGENTS.md` coding contract,
|
|
1181
|
+
the `CLAUDE.md` harness bridge, the `.agents/orchestration.md` agent-operation contract, the rules
|
|
1182
|
+
under `.claude/rules/` and `.cursor/rules/`, the skills under `.agents/skills/` and `.claude/skills/`,
|
|
1183
|
+
the templates under `.agents/templates/`, the transport contracts under `.agents/transports/`, the
|
|
1184
|
+
agent roles under `.claude/agents/` and `.codex/agents/`, the `.codex/config.toml` bench
|
|
1185
|
+
configuration, and the `.mcp.json` and `.cursor/mcp.json` server registrations. A release stages
|
|
1186
|
+
every one of them, and a target receives a copy only where the plan claims the path. At the
|
|
1187
|
+
`AGENTS.md` and `CLAUDE.md` destinations it receives the pointers: different content at the same
|
|
1188
|
+
paths, planned as this package's own template content. At `CATALOG_AGENT_PATH` it receives the staged
|
|
1189
|
+
bytes themselves, because the `catalog` verb refuses a target that lacks the file. Everywhere else in
|
|
1190
|
+
the canon a target holds nothing, and a reader reaches the contracts from a scaffold checkout sitting
|
|
1191
|
+
beside the repository, or from the `node_modules/@orkestrel/scaffold/dist/host/` root inside the
|
|
1192
|
+
installed package, which is what the `AGENTS.md` pointer scaffold plans into a target names.
|
|
1193
|
+
|
|
1194
|
+
`HOST_PATHS` and `CANON_PATHS` are disjoint by prefix in either direction: no member of one equals or
|
|
1195
|
+
sits beneath a member of the other. Staging depends on that, because the walk covers the union and a
|
|
1196
|
+
path it discovers twice claims one storage name twice, which refuses the stage. `isCanonPath` is the
|
|
1197
|
+
one reading of canon membership, matching a member and anything beneath a member that is a directory,
|
|
1198
|
+
so staging, the live overlay, and the executable's fetch list never disagree about what a path is.
|
|
1199
|
+
Membership says where a path's bytes are staged, not whether a plan claims it: `nameToHostArtifacts`
|
|
1200
|
+
appends `CATALOG_AGENT_PATH` to what `HOST_PATHS` selects rather than listing it there, which is what
|
|
1201
|
+
keeps the file planned without putting a canon path in the vendored list.
|
|
1134
1202
|
|
|
1135
1203
|
The `host.json` file at the repository root is the committed live inventory. Each entry carries the
|
|
1136
1204
|
SHA-256 digest of its file content, and the inventory carries a membership digest over its declared
|
|
@@ -1143,12 +1211,29 @@ those paths; it can neither introduce a path nor delete one. A path added upstre
|
|
|
1143
1211
|
until a release adds it to the installed manifest. Remove a vendored path in the same change that
|
|
1144
1212
|
ships the release which removes it from that manifest.
|
|
1145
1213
|
|
|
1214
|
+
Moving a path from `HOST_PATHS` to `CANON_PATHS` is not that removal. The path stays staged, stays in
|
|
1215
|
+
the installed manifest, and keeps being published; what changes is that no host artifact claims it. A
|
|
1216
|
+
target generated before the move still holds the copy it received, and that copy sits at a path the
|
|
1217
|
+
plan does not own, so `audit` reports it `foreign` and exits `1`. `overwrite` deletes it in the run
|
|
1218
|
+
that repairs the pointers — one candidate list and one transaction, whether the file is a stray
|
|
1219
|
+
beneath a vendored directory or a superseded copy inside the canon. Membership decides that, never
|
|
1220
|
+
byte identity: a copy a release behind no longer matches the bytes the canon stages, and matching
|
|
1221
|
+
bytes is exactly how such a copy would be spared.
|
|
1222
|
+
|
|
1146
1223
|
At the default `UpstreamOptions.retries` value, an aligned target spends one request on `host.json`,
|
|
1147
1224
|
and each installed path whose live digest differs from the target adds one request for its bytes. A
|
|
1148
1225
|
positive `retries` value can repeat a request after a transport fault. Raw-host propagation lag after
|
|
1149
1226
|
a commit is a property of the content host. Scaffold neither creates that lag nor presents a stale
|
|
1150
1227
|
response as fresher than the host served it.
|
|
1151
1228
|
|
|
1229
|
+
A canon destination costs no request. The fetch list drops every canon destination and `filesToHost`
|
|
1230
|
+
keeps the installed floor bytes for each one, claimed or not. The rule covers the destinations a plan
|
|
1231
|
+
does claim as well: the `AGENTS.md` and `CLAUDE.md` pointers are written from this package's own
|
|
1232
|
+
templates, and the catalog agent file is claimed by presence, so no byte a target holds is taken from
|
|
1233
|
+
a fetched canon path. A fill carrying no row for a canon path is complete rather than spoiled, which
|
|
1234
|
+
is what lets one `Host` carry live bytes beside floor bytes without mixing baselines within a
|
|
1235
|
+
surface.
|
|
1236
|
+
|
|
1152
1237
|
`.claude/settings.json` is in that set, and the artifact planned for it is content-owned. `repair`
|
|
1153
1238
|
and `overwrite` restore its bytes, so an edit made to it inside a target is reverted at the next
|
|
1154
1239
|
visit and reported as drift until then. Put an operator grant in `.claude/settings.local.json`
|
|
@@ -1164,7 +1249,7 @@ import { stageHost } from '@orkestrel/scaffold/server'
|
|
|
1164
1249
|
stageHost(process.cwd(), 'dist/host') // one ManifestEntry per file staged
|
|
1165
1250
|
```
|
|
1166
1251
|
|
|
1167
|
-
Each
|
|
1252
|
+
Each staged path is copied to a storage name, and every dot that opens a segment comes off,
|
|
1168
1253
|
because npm's own ignore rules would drop a leading-dot entry from the tarball. A dotted file at the
|
|
1169
1254
|
root moves under `dotfiles/` so it cannot collide with an undotted sibling. `manifest.json` is
|
|
1170
1255
|
written last and declares the whole membership: one entry per file with a digest computed from the
|
|
@@ -1172,7 +1257,15 @@ staged destination after its copy, the sorted directory inventory, and a SHA-256
|
|
|
1172
1257
|
The membership digest detects an edit that did not update the manifest, and the directory inventory
|
|
1173
1258
|
makes a declared empty directory survive a file walk.
|
|
1174
1259
|
|
|
1175
|
-
|
|
1260
|
+
The pointer reads that spelling back. The installed branch of a target's `AGENTS.md` names the
|
|
1261
|
+
`node_modules/@orkestrel/scaffold/dist/host/AGENTS.md` file, the
|
|
1262
|
+
`node_modules/@orkestrel/scaffold/dist/host/agents/orchestration.md` file, and the
|
|
1263
|
+
`node_modules/@orkestrel/scaffold/dist/host/claude/rules/` directory, which are where the dot-stripped
|
|
1264
|
+
storage names of `AGENTS.md`, `.agents/orchestration.md`, and `.claude/rules/` land. A reader
|
|
1265
|
+
following a canon path through the installed package types the storage spelling, not the repository
|
|
1266
|
+
one.
|
|
1267
|
+
|
|
1268
|
+
A missing staged path is refused rather than staged around, and the refusal names every missing
|
|
1176
1269
|
path at once. That is why `guides/scaffold.md` — this file — must exist before `npm run build`
|
|
1177
1270
|
completes.
|
|
1178
1271
|
|
|
@@ -1234,6 +1327,12 @@ except the manifest.
|
|
|
1234
1327
|
`configs/browsers.ts` resolution, serves the bundle over a loopback server, and drives it in
|
|
1235
1328
|
Playwright Chromium.
|
|
1236
1329
|
- One template artifact each for `README.md` and `guides/README.md`.
|
|
1330
|
+
- One template artifact each for `AGENTS.md` and `CLAUDE.md`. They are pointers rather than contracts:
|
|
1331
|
+
`AGENTS.md` names the coding contract, the orchestration contract, the rules, and the skills, and
|
|
1332
|
+
resolves each against a sibling scaffold checkout or the installed package; `CLAUDE.md` names the
|
|
1333
|
+
`AGENTS.md` file beside it and imports nothing, because an `@path` import inlines the imported file
|
|
1334
|
+
into every context that loads it. Scaffold owns their bytes, so a release that moves the wording
|
|
1335
|
+
moves every target's copy at its next `repair`.
|
|
1237
1336
|
- One host artifact per vendored path the workspace selects. A vendored directory is one planned
|
|
1238
1337
|
path that expands into the files the data root stores beneath it.
|
|
1239
1338
|
|
|
@@ -1413,6 +1512,26 @@ drivers is separate test capability rather than name-resolution parity.
|
|
|
1413
1512
|
question, and `materialize` writes any plan into any vacant target. The Compile section states the
|
|
1414
1513
|
rule a library caller applies in its place.
|
|
1415
1514
|
|
|
1515
|
+
**A file a target keeps at a canon path never reports clean.** `overwrite` deletes a superseded
|
|
1516
|
+
instruction copy in the run that repairs the pointers, and it deletes only what git tracks, from a
|
|
1517
|
+
tree carrying no uncommitted work. An untracked copy is left standing, and a git-ignored one sits
|
|
1518
|
+
outside the dirty reading as well, so a target can carry its own file at a canon path through every
|
|
1519
|
+
visit. The audit reads canon membership by path, so such a copy stays a `foreign` finding and that
|
|
1520
|
+
target exits `1` on every run. `repair` never closes it either: that verb writes the planned paths a
|
|
1521
|
+
target is missing or has let drift and deletes nothing, so it restores the `AGENTS.md` and
|
|
1522
|
+
`CLAUDE.md` pointers and leaves every other copy where it is. A maintainer who wants a local MCP
|
|
1523
|
+
server registration keeps it outside the repository, in the harness's own local or user scope, rather
|
|
1524
|
+
than at `.mcp.json`, where the file is drift whoever wrote it.
|
|
1525
|
+
|
|
1526
|
+
**A target holds no dispatchable role beyond the catalog agent.** The canon is staged for reading, so
|
|
1527
|
+
a target receives the `AGENTS.md` and `CLAUDE.md` pointers and `.claude/agents/orkestrel.md`, and
|
|
1528
|
+
nothing else a harness reads: no other agent role, no bench configuration, and no MCP registration. A
|
|
1529
|
+
harness running in a target loads none of those from `node_modules` either, so a role, a bench, or a
|
|
1530
|
+
server that target needs is defined in the harness's own local or user scope — the seam the preceding
|
|
1531
|
+
registration entry already names. Fleet targets are not orchestration hosts. A session that
|
|
1532
|
+
dispatches roles starts on scaffold, where `.agents/orchestration.md` and the role files sit, and
|
|
1533
|
+
attaches the target it is working on.
|
|
1534
|
+
|
|
1416
1535
|
**`isPath` does not prove host portability.** It proves bounded target-relative syntax and rejects
|
|
1417
1536
|
traversal, separators, controls, and reserved syntax characters. It deliberately admits host-specific
|
|
1418
1537
|
segment spellings such as a Windows device name, a trailing dot or space, and a segment beyond a
|
|
@@ -1648,4 +1767,4 @@ port, so the run drives nothing external and stays in `test`.
|
|
|
1648
1767
|
|
|
1649
1768
|
- [`guides/README.md`](README.md) — the concept and directory index.
|
|
1650
1769
|
- [`README.md`](../README.md) — the package front page.
|
|
1651
|
-
- [`AGENTS.md`](../AGENTS.md) — the coding contract every generated workspace
|
|
1770
|
+
- [`AGENTS.md`](../AGENTS.md) — the coding contract every generated workspace points at.
|
package/dist/host/manifest.json
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"storage": "agents/orchestration.md",
|
|
23
23
|
"destination": ".agents/orchestration.md",
|
|
24
24
|
"executable": false,
|
|
25
|
-
"digest": "
|
|
25
|
+
"digest": "601036308ef2144a5e6e0aeb9af58127c43b25a007d194a1cfbc501f9fade1d7"
|
|
26
26
|
},
|
|
27
27
|
{
|
|
28
28
|
"storage": "agents/skills/enterprise-bootstrap/SKILL.md",
|
|
@@ -244,7 +244,7 @@
|
|
|
244
244
|
"storage": "agents/skills/orkestrel-publish/references/wave.md",
|
|
245
245
|
"destination": ".agents/skills/orkestrel-publish/references/wave.md",
|
|
246
246
|
"executable": false,
|
|
247
|
-
"digest": "
|
|
247
|
+
"digest": "9f8dbb293bccffbc87751d70b828a8a7e6e6f09fb60ae9fc9f66aeb9f135e906"
|
|
248
248
|
},
|
|
249
249
|
{
|
|
250
250
|
"storage": "agents/skills/orkestrel-publish/references/window.md",
|
|
@@ -310,7 +310,7 @@
|
|
|
310
310
|
"storage": "claude/agents/orkestrel.md",
|
|
311
311
|
"destination": ".claude/agents/orkestrel.md",
|
|
312
312
|
"executable": false,
|
|
313
|
-
"digest": "
|
|
313
|
+
"digest": "c48480a671f6288d9acf70366804f2386540bc16d711cf8cc29b67a3947bcfe5"
|
|
314
314
|
},
|
|
315
315
|
{
|
|
316
316
|
"storage": "claude/agents/planner.md",
|
|
@@ -394,7 +394,7 @@
|
|
|
394
394
|
"storage": "claude/rules/quality.md",
|
|
395
395
|
"destination": ".claude/rules/quality.md",
|
|
396
396
|
"executable": false,
|
|
397
|
-
"digest": "
|
|
397
|
+
"digest": "bed49d37c2f97cb1b1640ee36e45a1c2a79a95fd7263513369ee53b999aa0d85"
|
|
398
398
|
},
|
|
399
399
|
{
|
|
400
400
|
"storage": "claude/rules/styles.md",
|
|
@@ -652,7 +652,7 @@
|
|
|
652
652
|
"storage": "guides/scaffold.md",
|
|
653
653
|
"destination": "guides/scaffold.md",
|
|
654
654
|
"executable": false,
|
|
655
|
-
"digest": "
|
|
655
|
+
"digest": "168273a80a9bd44046d1afe472c238858b92deae528e46d73b8ff4b4b4fe73bd"
|
|
656
656
|
},
|
|
657
657
|
{
|
|
658
658
|
"storage": "scripts/codex.sh",
|
|
@@ -688,7 +688,7 @@
|
|
|
688
688
|
"storage": "tests/policy.test.ts",
|
|
689
689
|
"destination": "tests/policy.test.ts",
|
|
690
690
|
"executable": false,
|
|
691
|
-
"digest": "
|
|
691
|
+
"digest": "f1f9ad779a090e9921695c743068025c387ccd610a09fee411eda809475a7367"
|
|
692
692
|
},
|
|
693
693
|
{
|
|
694
694
|
"storage": "tests/setupPolicy.ts",
|
|
@@ -742,5 +742,5 @@
|
|
|
742
742
|
".codex/agents",
|
|
743
743
|
".cursor/rules"
|
|
744
744
|
],
|
|
745
|
-
"digest": "
|
|
745
|
+
"digest": "260052484e5203b91bc8542fc49870dde886f789dc4f3f2a4e48f50f4f16afb3"
|
|
746
746
|
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|