axstack 0.11.6 → 0.12.0
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/package.json
CHANGED
|
@@ -11,7 +11,7 @@ Pair A/B is retired for this contract; its artefacts remain untouched.
|
|
|
11
11
|
|
|
12
12
|
- **driver** — every 15 minutes, fresh Opus session in the host's `root`
|
|
13
13
|
folder workspace, which is not a git repository and belongs to no project. It discovers GitHub work, binds the persistent Orca
|
|
14
|
-
Run,
|
|
14
|
+
Run, checks each selected PR's head out into a free project-local slot, dispatches the
|
|
15
15
|
matching Axstack agent, reconciles completions and decisions, then exits. The
|
|
16
16
|
driver is the automation session itself, with no `axstack-monitor` or
|
|
17
17
|
`axstack-owner` role row. It never performs review or repair in its own
|
|
@@ -97,8 +97,8 @@ The driver performs this order and exits:
|
|
|
97
97
|
inbox. For a `worker_done` matching a live marker, verify the review id at
|
|
98
98
|
the bound head, push range, or opened token. Release the worker; once its
|
|
99
99
|
release receipt is settled and the process has exited, run the cleanup
|
|
100
|
-
under "Run directory" below, which proves the
|
|
101
|
-
|
|
100
|
+
under "Run directory" below, which proves the slot disposable before
|
|
101
|
+
resetting it; then clear the marker. Unverifiable delivery stays in
|
|
102
102
|
`pending_settlement[]` and blocks only that PR.
|
|
103
103
|
3. Consume decisions as their sole consumer under "Decision tokens" below.
|
|
104
104
|
4. Reconcile every marker older than 3 h. A live worker gets `worker-stop`; an
|
|
@@ -124,6 +124,36 @@ The driver performs this order and exits:
|
|
|
124
124
|
|
|
125
125
|
## Dispatch and repair selection
|
|
126
126
|
|
|
127
|
+
Claude Code trusts a folder per git toplevel and stops at its "Quick safety
|
|
128
|
+
check" dialog otherwise, and the driver never answers that dialog for a
|
|
129
|
+
worker. So workers run in a fixed pool: every allowlisted project has
|
|
130
|
+
exactly two slot worktrees, `slot-1` and `slot-2`, its Orca child worktrees
|
|
131
|
+
created once, parented to the project's primary worktree, and trusted once
|
|
132
|
+
by the user through that dialog. The driver never creates or removes a
|
|
133
|
+
worktree and never writes `~/.claude.json`. A slot is free when no live
|
|
134
|
+
dispatch marker names it, it is not in `retained_slots[]`, no terminal is
|
|
135
|
+
listed in it, and its tree is clean; no free slot in the project defers the
|
|
136
|
+
PR to `deferred[]` like a budget, not a hold. Taking a slot fetches the head into the project clone,
|
|
137
|
+
checks the slot out detached at the pinned head, and verifies HEAD equals
|
|
138
|
+
it; the marker's worktree is the slot path. Trusting a folder activates the
|
|
139
|
+
full project surface: its `.claude/settings.json` and the hooks it defines,
|
|
140
|
+
its `.mcp.json` servers, marketplace plugin auto-install, and `CLAUDE.md`;
|
|
141
|
+
a hostile branch's hooks or MCP servers would run the moment the folder
|
|
142
|
+
opens. So the worker is launched in Claude Code's own isolation mode,
|
|
143
|
+
`--safe-mode`, through `terminal create` and `worker-start --terminal`,
|
|
144
|
+
since `worker-start` cannot pass argv. Safe mode is the binary's sanctioned
|
|
145
|
+
"all customizations disabled" path: no `CLAUDE.md`, skills, plugins, hooks,
|
|
146
|
+
MCP servers, custom commands or agents load from anywhere, project or user;
|
|
147
|
+
built-in tools and authentication are untouched, and the brief loads the
|
|
148
|
+
skill files it needs by path. The driver confirms readiness from the
|
|
149
|
+
rendered frame — `wait.satisfied`, the prompt marker present, the dialog
|
|
150
|
+
absent — before dispatching; a dialog on a slot means the slot is not
|
|
151
|
+
trusted: the slot is named in a health line, the PR is deferred, nothing is
|
|
152
|
+
dispatched. What remains live is the repository's files as data the worker
|
|
153
|
+
reads and the commands the worker itself chooses to run, which it already
|
|
154
|
+
runs today; nothing from the branch loads, executes, or is offered for
|
|
155
|
+
invocation on its own.
|
|
156
|
+
|
|
127
157
|
Every selected PR receives one dispatch marker with task id, dispatch id,
|
|
128
158
|
worktree, head, `started_at`, reservation (`verdict` or `repair`), and trigger:
|
|
129
159
|
`{kind: check, name, app_id}` or `{kind: review, review_id, digest}`. There is at
|
|
@@ -147,10 +177,10 @@ An own PR needs repair when either trigger applies:
|
|
|
147
177
|
triggers again subject to the 24 h cap.
|
|
148
178
|
|
|
149
179
|
Repair also requires no deploy-on-push head branch, no live repair cap, and
|
|
150
|
-
selection of the lowest own PR in its stack that needs repair.
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
dispatch one `axstack-watch` agent in authored repair mode. Its
|
|
180
|
+
selection of the lowest own PR in its stack that needs repair. Take a free
|
|
181
|
+
slot of that project (its slots are parented to that project's primary
|
|
182
|
+
worktree, so the work appears under the project it serves) at the exact
|
|
183
|
+
head, and dispatch one `axstack-watch` agent in authored repair mode. Its
|
|
154
184
|
brief contains only the triggering checks or review findings. Each open
|
|
155
185
|
descendant records one user-owned `pending restack` hold until it stops needing
|
|
156
186
|
repair. The 24 h cap starts at dispatch and an abandon does not refund it.
|
|
@@ -172,8 +202,8 @@ and head. Budget exhaustion records the count and is not a hold.
|
|
|
172
202
|
|
|
173
203
|
## Agents and verdicts
|
|
174
204
|
|
|
175
|
-
Every agent works in
|
|
176
|
-
head and reports only through the Orca worker protocol.
|
|
205
|
+
Every agent works in a project-local slot worktree checked out detached at
|
|
206
|
+
the exact head and reports only through the Orca worker protocol.
|
|
177
207
|
|
|
178
208
|
Peer review runs the two isolated configured reviewers on the identical brief,
|
|
179
209
|
then the Luna gate. `APPROVE` requires complete exact-head/base reviews, gate
|
|
@@ -312,12 +342,12 @@ is no gate for health findings.
|
|
|
312
342
|
## Run directory
|
|
313
343
|
|
|
314
344
|
The driver and watchdog run from the host's `root` folder workspace, not a
|
|
315
|
-
project worktree: no project owns the automation, and every
|
|
345
|
+
project worktree: no project owns the automation, and every slot worktree
|
|
316
346
|
belongs to the project it serves. That workspace is not a git repository, so
|
|
317
347
|
the run directory is private host state, one
|
|
318
348
|
`~/.local/share/axstack/runs/<run id>/` directory. Settlement leaves nothing
|
|
319
349
|
behind, but never destroys work. Before any destructive step the driver
|
|
320
|
-
proves the
|
|
350
|
+
proves the slot is disposable: the worker is settled — on the release path
|
|
321
351
|
a settled release receipt, on the abandon path an accepted abandon receipt,
|
|
322
352
|
either with proven process exit; pending or unknown stops here — the
|
|
323
353
|
worktree's HEAD is either the pinned head or a candidate that is durably
|
|
@@ -327,21 +357,27 @@ targeted fetch of that exact remote branch into a per-dispatch ref, never
|
|
|
327
357
|
shared clone can fake durability, a failed fetch retaining the worktree — or held by a
|
|
328
358
|
`refs/axstack/decisions/<token>` ref in the project clone; and, on the
|
|
329
359
|
abandon path, the worktree has no uncommitted changes.
|
|
330
|
-
Only then it closes any terminal tab still listed,
|
|
331
|
-
|
|
332
|
-
|
|
360
|
+
Only then it closes any terminal tab still listed, resets the slot to the
|
|
361
|
+
pinned head, clears untracked artefacts, and verifies the slot is clean, so
|
|
362
|
+
it is back in the pool. On the settled path
|
|
333
363
|
the worker has finished, so untracked files are artefacts by definition and
|
|
334
|
-
are cleared; a candidate there is already pushed or token-held.
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
364
|
+
are cleared; a candidate there is already pushed or token-held. A slot
|
|
365
|
+
whose release is settled but whose HEAD cannot be proven disposable, and an
|
|
366
|
+
abandoned slot that is dirty or holds an unproven candidate, are both
|
|
367
|
+
**retained**: named in one `health[]` line with path and SHA, and blocking
|
|
368
|
+
only that PR with the user as owner. Retention is mechanical on both paths:
|
|
369
|
+
the driver appends `retained_slots[]` `{slot, pr, head, reason}`, which the
|
|
370
|
+
free predicate excludes for every PR — a clean, terminal-less slot holding
|
|
371
|
+
an unpushed candidate would otherwise look free — and an entry is cleared
|
|
372
|
+
only by the user after reconciling the candidate. A dirty slot or a terminal that
|
|
373
|
+
outlives its dispatch without such a retention record is a health finding. The run directory contains:
|
|
339
374
|
|
|
340
375
|
- `cursor.json` — driver only, with these exact keys: `fingerprint`,
|
|
341
376
|
`tick_started_at`, `tick_done_at`, `tick_outcome`, `prs{url: {head, base,
|
|
342
377
|
draft, checks, reviews, last_self_review}}`, `dispatch_markers[]` (`pr`,
|
|
343
378
|
`task_id`, `dispatch_id`, `worktree`, `head`, `started_at`, `reservation`,
|
|
344
379
|
`trigger`), `deferred[]`, `pending_settlement[]`,
|
|
380
|
+
`retained_slots[]` (`slot`, `pr`, `head`, `reason`),
|
|
345
381
|
`repair_caps{url: {expires_at}}`, `abandon_count{head: n}`,
|
|
346
382
|
`processed_reviews[]` (`review_id`, `pr`, `head`, `digest`),
|
|
347
383
|
`deploy_on_push{repo: [branches]}`,
|
|
@@ -383,12 +419,12 @@ delivery uses [axstack-relay](../../axstack-relay/SKILL.md).
|
|
|
383
419
|
`runtime_refusal {code, first_seen, last_seen}`; the same code keeps the
|
|
384
420
|
hold and updates `last_seen` without a new health line, a different code is
|
|
385
421
|
a new finding. Prose is never the key. When `worker-start` itself is
|
|
386
|
-
refused after the
|
|
422
|
+
refused after the slot was checked out, there is no worker, so the
|
|
387
423
|
settlement proof does not apply; the driver reads the receipt's `failedStage`
|
|
388
424
|
and `residualResources` first. With no Dispatch and no residual resources
|
|
389
425
|
the no-worker branch applies: the worktree's HEAD must equal the pinned
|
|
390
|
-
head and `git status --porcelain` must be empty, and
|
|
391
|
-
|
|
426
|
+
head and `git status --porcelain` must be empty, and then the slot is simply
|
|
427
|
+
free again in the same tick; there is nothing to remove.
|
|
392
428
|
With a Dispatch or any residual resource the failed start owns runtime
|
|
393
429
|
state, and retaining alone is not recovery: the driver follows the
|
|
394
430
|
runtime's recovery guide. With a Dispatch: `worker-list` for that run, and
|