@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.
@@ -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 on both sides. The role file is where engine, effort, tools, permissions,
165
- and charter are pinned, and the tool allowlist is what makes the read-only floor real. A role
166
- with no file has nowhere to pin either.
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. **Spend the window.** Follow [window.md](references/window.md). Open the layer with one
54
- package, confirm its upload from the registry, then chase the remaining uploads back-to-back.
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
- The npm approval is the user's click, and the window it opens is five minutes long. Reach that
4
- click with a live chain, and spend the window without losing it.
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 opening the window. A stored credential expires
23
- mid-session, so a session-start answer does not hold.
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
- - Launch the login chain only when the user has signalled they are at the keyboard and will click
34
- within ten minutes. An approval URL expires unclicked in about ten to fifteen minutes, and an
35
- overnight gap expires the session credential with it.
36
- - Expect an approval for each stage. The `npmjs.com/login/cli/<id>` URL authenticates the session;
37
- the `npmjs.com/auth/cli/<id>` URL authorizes the publish and opens the five-minute window. Tell
38
- the user both are coming, or the second link reads as the first having failed.
39
- - Say that approving the publish one opens a five-minute window covering the rest of the layer.
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 usually still alive on a
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 live attempt
64
- the current poll fails `403 Forbidden - GET /-/v1/done` mid-flight. After any such 403,
65
- confirm no publish process is live, then mint one fresh attempt.
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. The abandoned poll then reports
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 the third attempt and on a later pass with no new
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 `.agents/orchestration.md` first. It owns the role set, the routing, and the
13
- dispatch contract. Then read `AGENTS.md`, applicable rules, the dispatch-named skill and
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.