Skip to content

fix(stella-cli): resume a crash that recorded an error at boot (#1696) - #1939

Merged
macanderson merged 8 commits into
mainfrom
worktree-fix-batch-1653-1698
Aug 7, 2026
Merged

fix(stella-cli): resume a crash that recorded an error at boot (#1696)#1939
macanderson merged 8 commits into
mainfrom
worktree-fix-batch-1653-1698

Conversation

@macanderson

@macanderson macanderson commented Aug 7, 2026

Copy link
Copy Markdown
Owner

What this delivers now

#1696 only. While this batch sat, main independently landed the rest of it:

The merge takes main's shipped implementations for all of those, and rebuilds the one unshipped fix on top of them.

The remaining fix (#1696)

boot::decide used to skip every terminal status, Error included — a compromise forced by #1653's ambiguity, at the honest cost of stranding a crash that lived just long enough to record Error. With #1653 landed, a policy stop records Stopped, so Error means only "it fell over", and this lets it fall through to the resume-point check.

Safe twice over, both checked rather than assumed:

Witness

a_crash_that_recorded_itself_is_continued_but_a_policy_stop_is_not fails on main (where decide skips every terminal status) and passes here. The exhaustive property nothing_is_ever_continued_without_a_resume_point is widened to pin the new rule: only live statuses and Error are ever continued.

Verified locally: cargo test -p stella-cli daemon suite (75 passed), cargo clippy -p stella-cli --all-targets -- -D warnings clean.

Closes #1696
Refs #1653, #1690, #1698 — shipped on main by #1878, #1723, #1920 respectively.

Stella Test added 4 commits August 5, 2026 20:04
…mentations

The #1616 approval-deadline work landed twice, from two PRs that chose
different names and different mechanisms, and the merge kept half of each.
main does not compile.

Four residues, all one collision:

- `SidecarApprovalGate` carries `deadline`/`with_deadline` while the park
  loop and two tests reference `self.wait`/`with_wait`, and the loop passes
  a `parked_at` it never binds. Reconciled onto `deadline`, keeping the
  `next_poll` mechanism: it clips the sleep by what is left of the deadline,
  so a one-second wait is honoured to the second rather than to the 250ms
  poll, and it factors the arithmetic out for a test that need not sleep
  through it. The redundant top-of-loop expiry check is dropped — one
  definition of "expired", which is the thing this file just paid for.
- `ConsoleGuard::drain_shared` is called from `main` and from the panic hook
  but was authored into `impl Drainable`, which is `#[cfg(unix)]`. Moved to
  `impl ConsoleGuard`, where its two callers already look for it.
- `arm_panic_drain` is the stranded parent of `install_panic_drain` and
  orders the hook chain the opposite way. `install_panic_drain` is the wired
  one and its reasoning is the stronger of the two (release builds are
  `panic = "abort"`, so there is no unwind back to main's own drain).
  Removed, with the doc reference repointed.
- `park_deadline` duplicates `AgentEngineConfig::approval_wait` exactly and
  had no caller, so `approval_wait_secs` was dead config: #1616's feature was
  unwired on main. Removed; its documentation of the `0` convention moves to
  the surviving definition, and its test now reads through it.

Also drops the weaker of the two duplicated deadline witnesses — the
survivor asserts the same property with an outer timeout for teeth and
checks the transport cleanup.
…1653)

#1620 and #1637 made the exit code honest — an `AbortKind::DeliberateStop`
(stuck-loop escalation, the step cap, an enforced budget, a scope review the
user ended) exits 3 and a crash exits 1. The session registry still collapsed
the two: both writers reduced the outcome to a bool one line before the write,
and `outcome_status(false, None)` mapped to `SessionStatus::Error`. So
`stella daemon list` and the deck SESSIONS view painted a run that stopped by
policy identically to one that fell over.

The design call the issue asked for: a deliberate stop reuses
`SessionStatus::Cancelled` rather than earning a variant. The two endings are
one fact to every reader — the work was ended, not broken — and it is already
what `outcome_status` writes for a signal. A new variant would also have
forced lines into `command_deck.rs` and `views/session.rs`, both grandfathered
god files closed to growth, for no information a reader gains.

What that buys is the load-bearing half: `Error` now means only "it fell
over", which is the predicate a boot-time resume sweep needs to tell a
resumable crash from a run it must never restart (#1696).

- `CliFailure::is_deliberate_stop` exposes the bit `exit_code` already turns
  into 3.
- `outcome_status` takes `Option<&CliFailure>` — the terminal answer itself —
  instead of a bool, so both writers can record what actually happened.
- Both call sites updated: `main`'s Err arm passes the failure it already
  holds, and the resume driver passes `result.as_ref().err()`.

Witness: `a_deliberate_stop_is_not_recorded_as_a_crash` asserts the two
endings store different statuses, where today both store `Error`.

Refs #1637, #1620, #1586
Closes #1653
Neither of these compiles on main; both are the cfg(test) half of the
collisions the previous commit reconciled in the shipping code.

- `daemon/console/tests.rs` builds a `ConsoleGuard { streams: … }`, the
  struct shape from before the pumps moved behind `Arc<Drainable>`.
- `fleet_claims.rs` matches `cli.command` as a bare `Command` where it is an
  `Option<Command>`, and formats `Command` with `{:?}` where it derives no
  `Debug`. The mismatch arm now states what was expected instead of printing
  what arrived, which is the half a reader of the failure needs anyway.
…ehind a parked one (#1696, #1698)

Three changes to the resume-at-boot sweep, plus the pid rung `daemon`
verbs were missing.

**#1696 — an `Error` is continued.** `decide` skipped every terminal status,
`Error` included. That was the price of #1653's ambiguity: a policy stop and
a crash both recorded `Error`, so continuing one risked restarting, unattended
and at the operator's expense, work the operator ended on purpose. The cost
was a real crash that managed to write `Error` before dying being stranded.

#1653 removed the ambiguity — a policy stop records `Cancelled` with every
other deliberate ending — so `Error` now means only "it fell over". No new
`BootCandidate` field: the stored status *is* the distinction, and a second
copy of it would be a second thing to keep true.

Two facts make the widening safe rather than merely intended, and both are
asserted: a deliberate stop retracts its checkpoint on the way out
(`discard_checkpoint` runs on every terminal path in the driver, abort
included), so even a pre-#1653 row that really was a policy stop is filtered
by `NoResumePoint` without this module trusting its status; and the
`MAX_BOOT_ATTEMPTS` bound still applies to whatever it continues.

**#1698 — a parked run no longer blocks the sweep.** A run interrupted while
parked on a scope review left its `approval-request.json` behind, and resuming
it at boot re-parked it immediately with no terminal and nobody to answer.
Because the sweep is sequential, that run blocked every remaining id forever
and the service console showed it as continued and then went quiet — work
stranded silently, which is the shape this module exists to prevent.

Option (1) of the three the issue offered: a `parked_on_approval` fact on
`BootCandidate`, probed from the sidecar, and its own `SkipReason::NeedsInput`
naming `daemon attach` as the way through. Read from the sidecar rather than
inferred from `NeedsInput`, because a run killed the instant after its review
was answered carries that status too and has nothing left to ask.

This bounds the park the sweep can see, not a resumed turn that parks on a
*new* review; that needs a per-resume wall-clock ceiling and is filed
separately rather than guessed at.

**#1690 — `daemon` verbs take a pid.** `resolve` accepted an exact id or a
unique prefix. A pid is what `ps`, `top`, Activity Monitor and an OOM-killer
log hand you, and it was a dead end: you had to eyeball `daemon list` to
translate it first. An all-digits argument is now matched against
`SessionRecord::pid`, with the same ambiguity rule as a prefix — a reused pid
is refused, not guessed at. The forms cannot collide: a session id is
`ses-<millis>-<pid>` and never parses as digits alone.

Witnesses: `a_crash_that_recorded_itself_is_continued_but_a_policy_stop_is_not`,
`a_parked_run_is_skipped_and_does_not_strand_the_runs_behind_it` (which
asserts the run *behind* the parked one is still decided — the half that
matters), `an_answered_review_leaves_the_run_resumable`, and
`a_pid_resolves_to_its_run_and_an_ambiguous_one_is_refused`.

`nothing_is_ever_continued_without_a_resume_point` grows the parked dimension
and drops the `is_live()` clause that was the old selection rule restated;
the invariant its name promises is unchanged and still asserted.

Refs #1627, #1653, #1586, #1585, #1607, #1594
Closes #1696
Closes #1698
Closes #1690

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @macanderson, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@vercel

vercel Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
stella-cli-docs Ignored Ignored Preview Aug 7, 2026 12:57am

@macanderson
macanderson enabled auto-merge (squash) August 7, 2026 00:25
@sourcery-ai

sourcery-ai Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Boot-time resume logic is updated to (1) distinguish crashes from deliberate stops and continue crashed runs with resume points, (2) avoid re-parking runs stuck on scope reviews and instead skip them with an explicit NeedsInput reason, and (3) allow daemon commands to resolve runs by pid as well as id, with stronger status semantics and supporting tests/docs.

Flow diagram for updated boot-time decide logic (resume vs skip)

flowchart TD
    A[BootCandidate] --> B{lock_held?}
    B -- yes --> R1[Skip StillRunning]
    B -- no --> C{stored_status is_live or Error?}
    C -- no
      --> R2[Skip EndedDeliberately]
    C -- yes --> D{parked_on_approval?}
    D -- yes --> R3[Skip NeedsInput]
    D -- no --> E{has_resume_point?}
    E -- no --> R4[Skip NoResumePoint]
    E -- yes --> F{workspace_exists?}
    F -- no --> R5[Skip WorkspaceGone]
    F -- yes --> G{attempts < MAX_BOOT_ATTEMPTS?}
    G -- no --> R6[Skip AttemptsExhausted]
    G -- yes --> R7[Resume]

    %% Key fields / values
    subgraph BootCandidate
      A1[stored_status]
      A2[lock_held]
      A3[parked_on_approval]
      A4[has_resume_point]
      A5[workspace_exists]
      A6[attempts]
    end
Loading

File-Level Changes

Change Details Files
BootCandidate and boot-time decision logic now detect parked scope reviews and treat them as skip-with-NeedsInput instead of resumable, while tightening invariants around what is actually continued.
  • Add parked_on_approval field to BootCandidate, populated by presence of approval-request.json in the sidecar.
  • Introduce SkipReason::NeedsInput and hook it into decide() before resume-point checks for parked runs.
  • Adjust decide() to treat SessionStatus::Error as resumable when a resume point exists, while other terminal statuses map to EndedDeliberately.
  • Extend nothing_is_ever_continued_without_a_resume_point test to cover parked_on_approval and refined status invariants.
  • Add boot tests covering crash-vs-policy-stop, parked run skipping without stranding later candidates, and answered reviews remaining resumable.
crates/stella-cli/src/daemon/boot.rs
crates/stella-cli/src/daemon/boot/tests.rs
Outcome recording for supervised runs now receives structured failures, distinguishes deliberate policy stops from crashes, and records appropriate terminal SessionStatus values.
  • Change outcome_status signature from (ok: bool) to (failure: Option<&CliFailure>) and update logic to return Cancelled for signals and deliberate stops, Error only for genuine failures, Complete for success.
  • Update record_outcome_if_supervised and all call sites (main and agent resume) to pass CliFailure or None rather than booleans.
  • Add CliFailure::is_deliberate_stop accessor to expose the deliberate_stop bit.
  • Revise tests to assert deliberate stops are not recorded as crashes and to read approval_wait via AgentEngineConfig instead of a standalone helper.
crates/stella-cli/src/daemon.rs
crates/stella-cli/src/main.rs
crates/stella-cli/src/agent/resume.rs
crates/stella-cli/src/failure.rs
crates/stella-cli/src/settings.rs
crates/stella-cli/src/daemon/tests.rs
Session resolution and CLI/docs are extended so daemon verbs can target runs by pid as well as id, with ambiguity detection and documentation updates.
  • Extend resolve() to treat all-digit arguments as pids, select matching supervised SessionRecord, and error on reused/ambiguous pids.
  • Add tests verifying pid resolution, ambiguity refusal, and non-collision with id prefix resolution.
  • Update daemon attach documentation to mention pid support.
crates/stella-cli/src/daemon.rs
crates/stella-cli/src/daemon/tests.rs
website/content/docs/commands/daemon.mdx
Scope-review approval gating and console draining are refactored for single-source deadline semantics and platform-agnostic drain_shared behavior.
  • Refactor SidecarApprovalGate to use deadline instead of wait, centralizing deadline expiry in next_poll and simplifying the review loop.
  • Remove the park_deadline helper in favor of AgentEngineConfig::approval_wait, and update tests accordingly.
  • Rename and relocate drain_shared from unix-only Drainable to ConsoleGuard, keeping pump-thread skip semantics but making main/platform usage uniform.
  • Adjust console and approval tests to the new APIs and types.
  • Clarify comments around panic drain installation and fleet claims CLI parsing expectations.
crates/stella-cli/src/daemon/approval.rs
crates/stella-cli/src/daemon/console.rs
crates/stella-cli/src/daemon/console/tests.rs
crates/stella-cli/src/fleet_claims.rs
SessionStatus::Cancelled semantics and boot/website docs are updated to reflect the new distinction between ended-on-purpose runs and crashed runs, including parked-on-approval behavior.
  • Document SessionStatus::Cancelled as covering both user interruptions and policy stops, with Error reserved for genuine crashes.
  • Revise boot.rs module docs to explain Error continuation safety, parked-run skipping behavior, and attempt bounds.
  • Update website boot sweep docs to describe what is continued, what is never resumed, and how parked scope reviews are handled.
  • Update SkipReason display strings and related messaging to match new semantics.
crates/stella-store/src/sessions.rs
crates/stella-cli/src/daemon/boot.rs
website/content/docs/commands/daemon.mdx

Assessment against linked issues

Issue Objective Addressed Explanation
#1653 Represent deliberate policy stops distinctly in the session registry, either by reusing SessionStatus::Cancelled or adding a new variant, and update all consumers (SessionStatus docs/ALL, deck SESSIONS view, stella daemon list) accordingly.
#1653 Widen outcome_status beyond a bool to accept the terminal answer (e.g., Option<&CliFailure>), add a deliberate-stop accessor on CliFailure, and use this to distinguish policy stops from crashes when writing session status.
#1653 Update record_outcome_if_supervised and its callers (including main.rs and resume paths) to pass the richer terminal outcome so deliberate stops are recorded with the correct SessionStatus, and add a witness test verifying deliberate stops and crashes store different statuses.
#1690 Update daemon::resolve to accept an all-digits argument as a pid, matching against SessionRecord::pid alongside exact-id and unique-prefix matching, preserving existing ambiguity rules.
#1690 Add a test in crates/stella-cli/src/daemon/tests.rs that exercises resolve-by-pid (including ambiguity and miss cases), failing on the old behavior.
#1690 Update daemon attach documentation (website/content/docs/commands/daemon.mdx) to state that the id can be a unique prefix or a pid.
#1696 Add a mechanism in the boot sweep (originally specified as a new field on BootCandidate) to distinguish runs ended by policy/operator from runs ended on a genuine error/crash.
#1696 Widen the boot-time decision logic so that a genuine crash recorded as SessionStatus::Error with a resume point is continued, while policy stops remain skipped and SkipReason is split to report these cases distinctly.
#1696 Update documentation in boot.rs and the website daemon command docs (resume-all section) to reflect the new, non-ambiguous behavior instead of the old conservative rule.
#1698 Modify the boot-time resume sweep so that runs parked on a scope review (with a pending approval-request.json) are not resumed at boot and do not block the sweep from reaching subsequent runs, including adding tests in boot/tests.rs to prove this behavior.
#1698 Update the daemon documentation (daemon.mdx, resume-all section) to describe the chosen behavior for boot-time handling of parked runs (scope reviews) and how the sweep treats them.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Resolves the conflicts in favour of the implementations that already
shipped on main where the two sides fixed the same issue independently:

- #1653 (deliberate stop vs crash): main's SessionStatus::Stopped design
  and Result-shaped outcome_status/record_outcome_if_supervised (#1828,
  #1878) over this branch's Cancelled-collapsing Option shape.
- #1690 (pid addressing): main's resolve() with the shared only() helper
  and its error wording (#1723).
- #1616 drain residue: main's arm_panic_drain + pump_thread self-join
  guard; this branch's unwired drain_shared duplicate is dropped.
- fleet claims parse test: main moved it to stella-cli/src/tests.rs;
  the copy this branch kept in fleet_claims.rs would have duplicated it.
… a recorded-error crash at boot (#1696)

Main independently landed the rest of this batch while it sat: the
deliberate-stop status (#1653 via SessionStatus::Stopped, #1828/#1878),
pid addressing (#1690 via #1723), the parked-run boot skip (#1698 via
#1920), and the #1616 drain/panic-hook machinery. Those files are taken
from main wholesale; the duplicated pid test, the stale-signature
outcome_status test, and the unwired drain_shared duplicate go with
them.

What remains is #1696, rebuilt on main's design: boot::decide lets
`Error` fall through to the resume-point check, because since #1653 a
policy stop records `Stopped` and `Error` means only 'it fell over'.
Safe twice over — a deliberate stop retracts its checkpoint on every
terminal path, so a pre-#1653 row is filtered by NoResumePoint anyway,
and the boot attempt ledger still bounds an Error that resumes into
another Error.

Closes #1696
@macanderson macanderson changed the title Boot sweep: resume crashes, skip parks, resolve pids (#1690, #1696, #1698) fix(stella-cli): resume a crash that recorded an error at boot (#1696) Aug 7, 2026
@macanderson
macanderson disabled auto-merge August 7, 2026 00:57
@macanderson
macanderson merged commit a280624 into main Aug 7, 2026
10 of 11 checks passed
@macanderson
macanderson deleted the worktree-fix-batch-1653-1698 branch August 7, 2026 00:57
macanderson added a commit that referenced this pull request Aug 7, 2026
…mon::boot (#1970)

## What & why

`main`'s workspace doc gate is red:
`crates/stella-cli/src/daemon/boot.rs`'s module doc intra-doc-links
`SkipReason::NoResumePoint`, but `daemon::boot` is a **private** module
and `SkipReason` is `pub(super)`, so rustdoc resolves nothing and
`rustdoc::broken_intra_doc_links` fails under `-D warnings`.

The link landed in #1939 and was invisible until now, which is the part
worth recording: `cargo doc` bails on the first crate that fails, so
`stella-store`'s private-link error (fixed in #1965) masked this one
entirely. Fixing one rustdoc break surfaces the next one down — expect
to iterate, not to assume the first fix was the last.

The fix is the same shape as #1965's: name the item in prose rather than
link something rustdoc cannot see, with a parenthetical saying why.

## The witness

- [ ] No witness needed (docs) — because: this is a doc-comment-only
change, and the gate itself is the check. `RUSTDOCFLAGS="-D warnings"
cargo doc --workspace --no-deps` exits **101** on `main` and **0** with
this change, verified by exit code rather than by reading output.

## The gate

- [x] `cargo doc --workspace --no-deps` under `-D warnings` (exit 0, the
whole workspace — re-run after the fix to confirm nothing further was
masked)
- [x] `cargo fmt --check`
- [x] CLA signed

Refs #1939, #1965.

## Summary by Sourcery

Documentation:
- Clarify daemon boot module documentation by naming
SkipReason::NoResumePoint in text instead of using an intra-doc link
that rustdoc cannot resolve.
macanderson added a commit that referenced this pull request Aug 7, 2026
…ead's tasks rows (#1708) (#1967)

## What

A sub-session worker's closeout wrote **its own** private task board
into the shared `tasks` table under the **lead's** `session_id`
(`crates/stella-cli/src/subsession.rs`, `run_worker`). At the table's
`UNIQUE(session_id, task_id)` key that write was pure corruption, twice
over:

1. **Ordinal collision** — a worker board numbers from "1" in its own
namespace, so its task "1" upserted over the lead's unrelated task "1".
2. **`/clear` seal bypass (#1692)** — the seal that quarantines
pre-clear workers lives on the driver (`SubSessions::seal_task_board` →
`session_clear::settle_worker_task`); this write ran on the worker's own
thread where no seal can reach, so a pre-clear worker repopulated the
mirror the user destroyed.

## The decision (of the three shapes in #1708)

**Drop the write** — the shape #1708's investigation identified as the
only one that fixes both defects alone:

- The write's stated purpose ("so `tasks` queries see sub-agent boards
too") is unachievable at this key — neither reader
(`Store::list_session_tasks`, the Observatory's sessions query) can
distinguish a worker row from a lead row.
- The delegation outcome the session cares about is the **lead's** board
row, which the driver already mirrors at both of its own write sites
(the lead's turn end in `command_deck.rs`, worker settlement in
`session_clear::settle_worker_task`).
- Namespacing fixes only defect 1; routing through the driver fixes only
defect 2. Dropping fixes both, with no migration and no cross-thread
plumbing — and it makes the `/clear` seal airtight rather than advisory,
because the driver becomes the session mirror's *sole* writer.

## The witness seam (the part #1708's investigation could not find)

The worker's store closeout moves to a new sibling module,
`crates/stella-cli/src/subsession/closeout.rs` — required anyway, since
`subsession.rs` sits 24 lines under the file-size gate's 1500-line
ceiling and could not absorb tests. `close_worker_execution` is the
exact production path `run_worker` calls, and its signature takes **no
session id**, so the closeout structurally cannot address session-keyed
rows.

Two witness tests drive that seam against a real in-memory store:

- `a_workers_private_board_never_lands_in_the_sessions_tasks_rows` — the
lead's mirror survives a worker closeout byte-identical, the table row
**count** is pinned too (so a NULL-session append can't hide), and the
execution row still closes (so "fixed by deleting the closeout" can't
pass).
- `a_pre_clear_workers_closeout_cannot_repopulate_a_cleared_mirror` —
after `clear_session_tasks` (the persisted half of `/clear`), a worker
closeout leaves the mirror exactly as empty as the user made it.

**Fail→pass flip, demonstrated:** the seam is new, so `git stash` alone
can't show the flip. Instead the pre-#1708 board mirror was temporarily
grafted back into `close_worker_execution` (same write, keyed to the
lead's session exactly as `run_worker` was) — both witnesses **fail**
against the graft with the exact corruption #1708 describes ("the lead's
mirror survives a worker closeout untouched" assertion trips), and
**pass** with it removed. The graft was reverted before shipping.

## Verification

Measured on this branch **with current `main` merged in** (head
`73f99926`):

- `cargo test -p stella-cli` — **1456 pass**, 0 fail, including both new
witnesses
- `cargo clippy -p stella-cli --all-targets -- -D warnings` — clean
- `cargo fmt --check` — clean
- `make guards-fast` (all 25 guards) — clean; `file-size` reports
**"none grew"** against main's regenerated baseline

## CI is red for reasons outside this diff

`fmt + clippy + test` fails on **five breaks inherited from `main`**,
none in a file this PR touches (the diff is 3 files, all `stella-cli`):

| Break | Crate | Already covered by |
|---|---|---|
| `unresolved link to SkipReason::NoResumePoint` (`daemon/boot.rs:59`,
added by `a2806246` / #1939) | stella-cli | **#1970** |
| `too many arguments (8/7)` (clippy) | stella-pipeline | **#1971** |
| `PassingShell` not found | stella-pipeline | **#1971** |
| `shell_call_result` not found | stella-pipeline | **#1971** |
| non-exhaustive match: `ModelCallRole::Research` not covered |
stella-pipeline | **#1971** |

The last one is the root cause of three of these: `main` added a
`Research` variant to `stella_protocol::ModelCallRole` without updating
downstream exhaustive matches. This branch point has no `Research`
variant at all, which is why the break is provably inherited rather than
caused.

No competing unbreak is included here deliberately — duplicate PRs
racing the same seam is how `main` gets re-broken. This PR should go
green once #1970 and #1971 land; it is already merged up to current
`main` and conflict-free.

No migration: the corrupted rows self-heal — the driver's next
lead-board mirror upserts the colliding ordinals back to the lead's
state, and `/clear` deletes the rest; stray rows beyond the lead's
ordinal range in existing databases are dead rows in a table whose only
production readers are per-session queries the driver now exclusively
feeds.

Exemplar for the shape: the pipeline's witness stage gives authored
witnesses exactly this lifetime — scaffolding for one run, discarded
with it — which is the model applied to a worker's private board here.

## Filed, not fixed

- **#1968** — this PR deliberately closes the door on persisting
sub-agent boards. If they are wanted, it takes a `lane` column +
migration, routing through the driver, *and* a lane-aware reader, all
three together; the issue scopes each and says why any one alone
reintroduces a defect.
- **#1969** — existing databases already hold corrupt rows from this
bug, and they are **indistinguishable by construction** (that is #1708's
whole complaint), so no migration can repair them. They render in the
Observatory's Sessions tab. Needs a maintainer's call between accept /
caveat / document.

Refs #1692, #1631.

Closes #1708
macanderson added a commit that referenced this pull request Aug 7, 2026
…a dangling boot.rs doc link (#1985)

## What & why

`main`'s required `fmt + clippy + test` job has been **red since #1951**
(five
consecutive merges), so every open PR inherits a red gate. Four distinct
errors
are involved. This PR fixes the two that **no open PR covers**.

### 1. `cargo clippy -D warnings` — `plan_stage` has 8 arguments (limit
7)

`crates/stella-pipeline/src/pipeline.rs`. #1953 added a `research`
parameter,
pushing `plan_stage` over `clippy::too_many_arguments`.

`Spend<'_>` (`crates/stella-pipeline/src/pipeline/stage_budget.rs`)
already
groups the `budget`/`total` pair, and **seven** sibling stage methods
take it;
`plan_stage` was the last one carrying the two loose. Adopting it takes
the
count to 7.

This is the right fix rather than `#[allow(clippy::too_many_arguments)]`
because there is no argument that the lint is wrong *here* — the
grouping type
the lint is asking for already exists — and because `pipeline.rs` is a
grandfathered god file closed to growth, which this change **shrinks**.

### 2. `cargo doc -D warnings` — unresolved link in `boot.rs`

`crates/stella-cli/src/daemon/boot.rs`. #1939 left
``[`SkipReason::NoResumePoint`]`` in the module doc unresolvable
(`no item named `SkipReason` in scope`), which fails
`rustdoc::broken_intra_doc_links`.

Qualified to the full path — the same remedy #1927 applied to *this same
file*
for *this same reason* after #1920. That recurrence is filed as #1986.

## What this PR deliberately does NOT fix

The other two errors belong to the open PR **#1964**:

- `flip_halt_arming.rs` references `PassingShell` / `shell_call_result`,
test
  helpers #1945 landed the test file without.
- `crates/stella-pipeline/src/management_prompt/tests.rs`'s exhaustive
match
  omits `ModelCallRole::Research`, which #1953 added.

Duplicating them here is how two parallel unbreak PRs collide, so they
are left
to #1964.

**`main` needs both PRs.** This one alone leaves `cargo test` red; #1964
alone
leaves clippy and rustdoc red (verified: #1964's own CI still fails
both, and
its clippy failure is the identical `plan_stage` error). Neither is
sufficient
on its own, and the merge order does not matter.

Because of that, **this PR's own `cargo clippy` and `cargo test` steps
will
stay red until #1964 merges** — clippy `--all-targets` reaches the
missing test
helpers once the lib error is gone. That is expected, not a regression.

## The witness

- [x] No witness test needed — a lint fix and a doc-link fix, neither a
      behavior change. Verified the artisanal way:
- `RUSTDOCFLAGS="-D warnings" cargo doc -p stella-cli --no-deps` fails
on
    `main` and **exits 0** with this change.
- `cargo check -p stella-pipeline --all-targets` reports **only** the
three
#1964-owned errors; the `plan_stage` arg-count error is gone and both
call sites (`pipeline/scope_stage.rs`,
`pipeline/tests/management_accounting.rs`)
    compile.
  - `cargo fmt --check -p stella-pipeline -p stella-cli` exits 0.

## The gate

- [x] `check-file-size.sh` and `check-god-files.sh` pass; `pipeline.rs`
shrinks,
      so no baseline change is needed.
- [x] No behavior change, no new flags, no docs pages affected.
- [x] No new dependencies.

## Nothing left behind

- **#1986** — `boot.rs`'s module doc has now broken `main`'s rustdoc
twice in
two days by the same mechanism (#1920#1927, then #1939 → this PR),
because
  `ci.yml` does not run on a push to `main`. Filed as a handoff.
- **#1974** — `CandidateState` is hand-built at two sites, which is how
#1951's
field addition silently broke PR #1962 at merge time. Noticed in the
same
  investigation.

Refs #1953, #1939, #1964
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Widen resume-at-boot to genuine crashes once #1653 separates a policy stop from an error

1 participant