@orkestrel/scaffold 0.0.55 → 0.0.57
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/SKILL.md +4 -2
- package/dist/host/agents/skills/orkestrel-publish/references/wave.md +28 -2
- package/dist/host/agents/skills/orkestrel-publish/references/window.md +73 -19
- 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 +9 -9
- 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
|
|
@@ -50,8 +50,10 @@ following the skill.
|
|
|
50
50
|
happens outside the window.
|
|
51
51
|
6. **Reach the approval.** Follow [window.md](references/window.md), and launch the login chain
|
|
52
52
|
only after the user signals they are at the keyboard.
|
|
53
|
-
7. **
|
|
54
|
-
|
|
53
|
+
7. **Authorize and upload.** Follow [window.md](references/window.md). Take the account's one-time
|
|
54
|
+
code where it has one, because that path opens no window. Where the account answers with no
|
|
55
|
+
code, the browser authorization opens the five-minute window: open the layer with one package,
|
|
56
|
+
confirm its upload from the registry, then chase the remaining uploads back-to-back.
|
|
55
57
|
8. **Close the layer from the registry, then prepare the next.** A dependent's new pin cannot
|
|
56
58
|
install until the version it names exists, so preparation and publication interleave and cannot
|
|
57
59
|
be batched ahead.
|
|
@@ -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.
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
# The approval and the upload window
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
A release needs the user at the keyboard to authenticate the session, and again to authorize each
|
|
4
|
+
upload. An approval URL dies unclicked in under a minute, so mint one only in a
|
|
5
|
+
moment the user can click, and relay it byte for byte. Where the account answers with a one-time
|
|
6
|
+
code, take that code for the upload — it needs no browser authorization and opens no window to
|
|
7
|
+
lose. Where the account has no code, the browser authorization opens a five-minute window, and the
|
|
8
|
+
rest of the layer either fits inside it or takes another approval.
|
|
5
9
|
|
|
6
10
|
## Arm the terminal
|
|
7
11
|
|
|
@@ -19,8 +23,8 @@ click with a live chain, and spend the window without losing it.
|
|
|
19
23
|
missing credential.
|
|
20
24
|
- Confirm authentication with `npm whoami`, never with an exit code. The legacy fallthrough exits
|
|
21
25
|
zero.
|
|
22
|
-
- Re-probe `whoami` immediately before
|
|
23
|
-
|
|
26
|
+
- Re-probe `whoami` immediately before the first upload. A stored credential expires mid-session
|
|
27
|
+
and an overnight gap expires it, so a session-start answer does not hold.
|
|
24
28
|
- Read a login log that shows the spinner and then a legacy `Username:` prompt as an expired
|
|
25
29
|
attempt rather than as a prompt to answer. Kill it by process id and mint a fresh flow.
|
|
26
30
|
- On a Windows host, Git Bash ships no `script` binary, so the upload step is operator-driven:
|
|
@@ -30,13 +34,30 @@ click with a live chain, and spend the window without losing it.
|
|
|
30
34
|
|
|
31
35
|
## Reach the approval
|
|
32
36
|
|
|
33
|
-
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
- Mint an approval only when the user is at the keyboard in that moment and can click immediately.
|
|
38
|
+
A URL minted while the user is still on their way is dead before they arrive.
|
|
39
|
+
- Put the URL on the first line of the message, with nothing before it. A reader who must read
|
|
40
|
+
anything before clicking arrives after the session is gone.
|
|
41
|
+
- Relay the URL exactly as the journal holds it. The `npm login --browser=false` command prints
|
|
42
|
+
`https://www.npmjs.com/login?next=/login/cli/<id>`, and the `npm publish --browser=false` command
|
|
43
|
+
prints `https://www.npmjs.com/auth/cli/<id>`.
|
|
44
|
+
- Never shorten, redirect-strip, or otherwise improve a minted URL. The bare
|
|
45
|
+
`https://www.npmjs.com/login/cli/<id>` target the login URL names is not a page: opened in a
|
|
46
|
+
browser it answers `{"message":"Unauthorized"}`. The user then reads a broken chain where the
|
|
47
|
+
chain is healthy, and the operator diagnoses the wrong failure.
|
|
48
|
+
- Expect an unclicked session to die about 45 seconds after it is minted. Measured on 2026-08-27
|
|
49
|
+
against `registry.npmjs.org` with `npm` 10.9.7 and `node` 22.22.2: npm polls `GET /-/v1/done`
|
|
50
|
+
every few seconds and takes `202` while the session waits, and the registry answers `403` at
|
|
51
|
+
about 45 seconds. Whether the registry fixes that abandon by elapsed time or by poll count is
|
|
52
|
+
unmeasured, so plan against the duration.
|
|
53
|
+
- Recognise the abandon on each side. The `npm login` command reads the `403` as web login being
|
|
54
|
+
unsupported and drops to its legacy `Username:` prompt. The `npm publish` command exits `E403`
|
|
55
|
+
naming `GET /-/v1/done?authId=`.
|
|
56
|
+
- Never keep a link alive by re-minting on a loop. Each mint invalidates the URL before it, so a
|
|
57
|
+
supervisor that re-mints on expiry makes the link a moving target and every relayed URL is dead
|
|
58
|
+
on arrival. Mint once per human moment, and mint again only when the user asks.
|
|
59
|
+
- Name the login approval and the upload authorization to the user before either arrives, or the
|
|
60
|
+
authorization link reads as the login having failed.
|
|
40
61
|
- Surface each approval URL the moment it appears in the log, and take the **last** one in log
|
|
41
62
|
order. npm mints a new URL whenever an attempt starts again, and the log accumulates every one,
|
|
42
63
|
so a URL chosen by sorting rather than by position is already dead when the user opens it.
|
|
@@ -45,13 +66,33 @@ click with a live chain, and spend the window without losing it.
|
|
|
45
66
|
has not reached the URL yet.
|
|
46
67
|
- Relay the URL as plain text. A decorated link did not render for the operator, who then had
|
|
47
68
|
nothing to click while the window ran down.
|
|
48
|
-
- Re-read the log before treating an approval as failed. The chain is
|
|
69
|
+
- Re-read the log before treating an approval as failed. The chain is sometimes still alive on a
|
|
49
70
|
later URL, so surface that one rather than starting the chain again.
|
|
50
71
|
- Read a `404` on an approval URL as a publish that already succeeded and consumed it. Read the
|
|
51
72
|
registry before calling it a failure.
|
|
52
73
|
|
|
74
|
+
## Authorize the upload
|
|
75
|
+
|
|
76
|
+
- Take the account's one-time code where the account has one. The
|
|
77
|
+
`npm publish --ignore-scripts --otp=<code>` command uploads with no browser authorization and no
|
|
78
|
+
poll, so it carries neither a window nor a race. In the `@orkestrel/scaffold` 0.0.56 run on
|
|
79
|
+
2026-08-27 the browser authorization failed on the 45-second abandon and the one-time code
|
|
80
|
+
uploaded the package with no retry.
|
|
81
|
+
- Ask for the code at the moment of the upload, and run the upload inside that code's own life. A
|
|
82
|
+
code read minutes earlier is already spent.
|
|
83
|
+
- Ask for the code and nothing else. Never ask for a password, an access token, or an auth file.
|
|
84
|
+
`.agents/orchestration.md` § Publishing the fleet owns that law.
|
|
85
|
+
- Arm a one-time-code upload the way § Arm the terminal arms every other publish.
|
|
86
|
+
- Fall back to the browser authorization where the account answers with no code. That path mints
|
|
87
|
+
the `auth/cli/<id>` URL, needs the click inside the session's life, and opens the five-minute
|
|
88
|
+
window.
|
|
89
|
+
- Tell the user that approving an `auth/cli/<id>` URL opens a five-minute window covering the rest
|
|
90
|
+
of the layer.
|
|
91
|
+
|
|
53
92
|
## Spend the window
|
|
54
93
|
|
|
94
|
+
- Everything under this heading is the browser-authorization path. A one-time-code upload opens no
|
|
95
|
+
window, so none of it binds that path.
|
|
55
96
|
- The window opens when the user approves, not when the first publish starts.
|
|
56
97
|
- Open each layer with one package: publish it alone, surface its approval URL the moment the
|
|
57
98
|
journal shows it, and confirm the upload from the registry before starting the rest.
|
|
@@ -60,18 +101,16 @@ click with a live chain, and spend the window without losing it.
|
|
|
60
101
|
its own URL.
|
|
61
102
|
- Relay every new URL to the user the moment it appears, through a journal watcher, and never
|
|
62
103
|
pause the chain to wait for a click: a poll outlives the relay.
|
|
63
|
-
- Tell the user to click only the URL last in log order. A click on a superseded URL poisons the
|
|
64
|
-
|
|
65
|
-
|
|
104
|
+
- Tell the user to click only the URL last in log order. A click on a superseded URL poisons the
|
|
105
|
+
live attempt, and the current poll then fails `403 Forbidden - GET /-/v1/done` mid-flight.
|
|
106
|
+
§ Read a `403` on the poll owns the recovery.
|
|
66
107
|
- **Never retry a publish that is still waiting for its authorization.** Each `npm publish`
|
|
67
108
|
attempt mints a new `authId` and invalidates the previous one, so a retry loop makes the URL a
|
|
68
|
-
moving target the user cannot approve in time.
|
|
69
|
-
`403 Forbidden - GET /-/v1/done?authId=…`, which reads as a permissions problem and is the
|
|
70
|
-
abandoned attempt colliding with the live one. Publish the first package of a layer with exactly
|
|
109
|
+
moving target the user cannot approve in time. Publish a layer's opening package with exactly
|
|
71
110
|
one attempt.
|
|
72
111
|
- Retry only an upload that failed **inside** an already-open window. `EOTP` there is intermittent
|
|
73
112
|
contention rather than the window closing: retry about three times, and retry a failed set after
|
|
74
|
-
the layer ends. Packages have landed on
|
|
113
|
+
the layer ends. Packages have landed on a third attempt and on a later pass with no new
|
|
75
114
|
approval. These are different failures wearing similar codes; a retry fixes in-window contention
|
|
76
115
|
and causes the moving approval target.
|
|
77
116
|
- Expect a large layer to outlast one window. Size batches to what uploads in five minutes and
|
|
@@ -79,6 +118,21 @@ click with a live chain, and spend the window without losing it.
|
|
|
79
118
|
- The contract's serialization law binds every upload in the window, and
|
|
80
119
|
`.agents/orchestration.md` § Long-running commands binds the chain that runs them.
|
|
81
120
|
|
|
121
|
+
## Read a `403` on the poll
|
|
122
|
+
|
|
123
|
+
`403 Forbidden - GET /-/v1/done` carries more than one cause, and each takes a different reading of
|
|
124
|
+
the same status. Rule from the evidence, never from which cause reads likelier.
|
|
125
|
+
|
|
126
|
+
- Nobody clicked inside the session's life. The poll ran out its 45 seconds against a URL no one
|
|
127
|
+
opened, and the registry closed the session.
|
|
128
|
+
- The user clicked a superseded URL and poisoned the live attempt. The poll fails mid-flight while
|
|
129
|
+
the user is looking at a page that reports success.
|
|
130
|
+
- Tell those causes apart from the log and the user, never from the status alone. A single minted
|
|
131
|
+
URL that nobody opened in time is the abandon. A log carrying a URL the running attempt
|
|
132
|
+
superseded, with the user reporting a click, is the poisoned attempt.
|
|
133
|
+
- Recover the same way whichever it was: read the registry for the version, confirm no publish
|
|
134
|
+
process is live, then mint exactly one fresh attempt with the user at the keyboard.
|
|
135
|
+
|
|
82
136
|
## Read the verdict from the registry
|
|
83
137
|
|
|
84
138
|
- Read the result from the registry, not from an exit code. A piped `npm publish` reports the exit
|
|
@@ -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.
|