From 20c6e2aa22d09ef3ccd5075ec260d346b571f6ad Mon Sep 17 00:00:00 2001 From: Mac Anderson Date: Thu, 6 Aug 2026 19:53:09 -0700 Subject: [PATCH 1/4] =?UTF-8?q?fix(stella-pipeline):=20unbreak=20main=20?= =?UTF-8?q?=E2=80=94=20two=20unbreak=20PRs=20fixed=20the=20same=20three=20?= =?UTF-8?q?things=20and=20the=20merge=20kept=20both?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #1985 and #1971/#1995 independently repaired the breaks #1953 left, converged on the same designs, and landed within minutes of each other. Git merged the two additively rather than conflicting, so `main` at e0fbbe02 carries each fix twice and fails `cargo clippy -p stella-pipeline --all-targets -- -D warnings` three ways: 1. `management_prompt/tests.rs` — `ModelCallRole::Research` appears twice in the same or-pattern (`unreachable_patterns`). Kept one. 2. `pipeline/scope_stage.rs` — both PRs bundled `plan_stage`'s budget+total into `Spend`, but the call site kept #1985's per-iteration reborrow AND the other's hoisted `let mut spend`, now unused (`unused_variables` + `unused_mut`). Kept #1985's: the loop replans after a rejected scope card, and only a reborrow per attempt survives that. 3. `tests/verification_hardening.rs` — both restored `PassingShell` and `shell_call_result` after #1951 deleted them, one into this file and one into its `flip_halt_arming` child, leaving the parent's pair dead (`dead_code` ×3, counting `SHELL_TOOL`). For (3) the two copies were not equivalent, so this is not an arbitrary pick: #1985's are better documented — they name `SHELL_TOOL` as a const distinct from `WRITING_TOOL` and say why the `[exit code: 0]` marker is load-bearing (without it the halt never latches and the arming test passes for no reason). Those are the ones kept. They move to the child, which is where both #1793 witnesses now live, because co-location is what makes the next wholesale rewrite of the parent a merge conflict instead of the silent deletion that started this (#1997). The parent's now-stale `mod` doc is corrected in place rather than left describing a layout that no longer holds. `cargo clippy -p stella-pipeline --all-targets -- -D warnings`: clean. --- .../src/management_prompt/tests.rs | 3 +- .../src/pipeline/scope_stage.rs | 1 - .../pipeline/tests/verification_hardening.rs | 59 ++----------- .../flip_halt_arming.rs | 85 +++++++++++-------- 4 files changed, 57 insertions(+), 91 deletions(-) diff --git a/crates/stella-pipeline/src/management_prompt/tests.rs b/crates/stella-pipeline/src/management_prompt/tests.rs index 4af33f99..dc6513c7 100644 --- a/crates/stella-pipeline/src/management_prompt/tests.rs +++ b/crates/stella-pipeline/src/management_prompt/tests.rs @@ -94,8 +94,7 @@ fn management_system_block(role: ModelCallRole) -> Option { | ModelCallRole::SkillAuthor | ModelCallRole::DomainInference | ModelCallRole::Reflection - | ModelCallRole::Summarization - | ModelCallRole::Research => None, + | ModelCallRole::Summarization => None, } } diff --git a/crates/stella-pipeline/src/pipeline/scope_stage.rs b/crates/stella-pipeline/src/pipeline/scope_stage.rs index 77fc84ab..6e97ab9c 100644 --- a/crates/stella-pipeline/src/pipeline/scope_stage.rs +++ b/crates/stella-pipeline/src/pipeline/scope_stage.rs @@ -31,7 +31,6 @@ impl Pipeline<'_> { let repo_structure = self.repo.structure_summary().await; let mut revision: Option = None; let mut spent_revisions = 0usize; - let mut spend = Spend { budget, total }; loop { let plan = match self diff --git a/crates/stella-pipeline/src/pipeline/tests/verification_hardening.rs b/crates/stella-pipeline/src/pipeline/tests/verification_hardening.rs index aaf9990a..27674234 100644 --- a/crates/stella-pipeline/src/pipeline/tests/verification_hardening.rs +++ b/crates/stella-pipeline/src/pipeline/tests/verification_hardening.rs @@ -7,59 +7,14 @@ use super::*; use crate::LineMutation; -/// The shell tool `flip_halt_arming` scripts its revision against. +/// Both arming paths of the mid-turn flip halt (#1793), and the two doubles +/// they share. A child rather than a sibling module so it still reaches this +/// file's scripted ports through `use super::*`, and so the already-oversized +/// `tests.rs` does not grow another module declaration. /// -/// A distinct name from [`WRITING_TOOL`] because the two fakes answer -/// differently and a flip must be attributable: only this one emits the exit -/// marker [`crate::flip_halt::exit_status`] reads. -const SHELL_TOOL: &str = "bash"; - -/// One model turn that runs `command` through the shell tool. -/// -/// The `command` key is what [`crate::flip_halt::command_of`] looks for, so a -/// call built any other way would be invisible to the halt and the test would -/// pass for the wrong reason. -fn shell_call_result(command: &str) -> CompletionResult { - CompletionResult { - tool_calls: vec![ToolCall { - call_id: "call-shell".into(), - name: SHELL_TOOL.into(), - input: serde_json::json!({ "command": command }), - }], - ..text_result("") - } -} - -/// A shell whose every command succeeds, reported the way the real bash tool -/// reports it — the trailing `[exit code: 0]` marker. -/// -/// That marker is the whole point: [`crate::flip_halt::FlipHalt::observe`] -/// latches only on a tracked command that exited zero, and output without a -/// marker can never stop a turn. A fake returning bare prose would leave the -/// halt unlatched and the arming test green for no reason. -struct PassingShell; -#[async_trait] -impl ToolExecutor for PassingShell { - fn schemas(&self) -> Vec { - vec![ToolSchema { - name: SHELL_TOOL.into(), - description: "run a shell command".into(), - input_schema: serde_json::json!({ "type": "object" }), - read_only: false, - speculation_safe: false, - }] - } - async fn execute(&self, _name: &str, _input: &Value) -> ToolOutput { - ToolOutput::Ok { - content: "ok\n[exit code: 0]".into(), - } - } -} - -/// The authored-witness arming of the mid-turn flip halt (#1793) — a child -/// rather than a sibling module so it reaches the shared fakes through this -/// file's own `use super::*`, and so the already-oversized `tests.rs` does -/// not grow another module declaration. +/// The doubles live in the child with their only users, not here: when they +/// sat in this file, a wholesale rewrite of it took them and the +/// configured-command witness with them, and no gate objected (#1997). mod flip_halt_arming; /// #860 acceptance: a baseline that TIMES OUT observed no failing assertion, diff --git a/crates/stella-pipeline/src/pipeline/tests/verification_hardening/flip_halt_arming.rs b/crates/stella-pipeline/src/pipeline/tests/verification_hardening/flip_halt_arming.rs index 5d5c21cb..887230fb 100644 --- a/crates/stella-pipeline/src/pipeline/tests/verification_hardening/flip_halt_arming.rs +++ b/crates/stella-pipeline/src/pipeline/tests/verification_hardening/flip_halt_arming.rs @@ -20,6 +20,55 @@ use super::*; +/// The shell tool both witnesses script their revision against. +/// +/// A distinct name from [`WRITING_TOOL`] because the two fakes answer +/// differently and a flip must be attributable: only this one emits the exit +/// marker [`crate::flip_halt::exit_status`] reads. +const SHELL_TOOL: &str = "bash"; + +/// One model turn that runs `command` through the shell tool. +/// +/// The `command` key is what [`crate::flip_halt::command_of`] looks for, so a +/// call built any other way would be invisible to the halt and the test would +/// pass for the wrong reason. +fn shell_call_result(command: &str) -> CompletionResult { + CompletionResult { + tool_calls: vec![ToolCall { + call_id: "call-shell".into(), + name: SHELL_TOOL.into(), + input: serde_json::json!({ "command": command }), + }], + ..text_result("") + } +} + +/// A shell whose every command succeeds, reported the way the real bash tool +/// reports it — the trailing `[exit code: 0]` marker. +/// +/// That marker is the whole point: [`crate::flip_halt::FlipHalt::observe`] +/// latches only on a tracked command that exited zero, and output without a +/// marker can never stop a turn. A fake returning bare prose would leave the +/// halt unlatched and the arming test green for no reason. +struct PassingShell; +#[async_trait] +impl ToolExecutor for PassingShell { + fn schemas(&self) -> Vec { + vec![ToolSchema { + name: SHELL_TOOL.into(), + description: "run a shell command".into(), + input_schema: serde_json::json!({ "type": "object" }), + read_only: false, + speculation_safe: false, + }] + } + async fn execute(&self, _name: &str, _input: &Value) -> ToolOutput { + ToolOutput::Ok { + content: "ok\n[exit code: 0]".into(), + } + } +} + /// #1793 witness (authored side): after `witness_on_demand` seeds a failing /// witness, a revision that observes the witness command pass halts at that /// step boundary. As in the configured-command twin, the provider is @@ -114,42 +163,6 @@ async fn an_authored_witness_arms_the_revision_flip_halt() { flipped, not spend the scripted steps beyond it" ); } -/// A shell double whose every command "passes": the output carries the -/// trailing exit-0 marker [`crate::flip_halt::exit_status`] parses. What -/// [`EmptyTools`] can never express — a worker *observing* the tracked test -/// succeed through a tool result. -struct PassingShell; -#[async_trait] -impl ToolExecutor for PassingShell { - fn schemas(&self) -> Vec { - vec![ToolSchema { - name: "bash".into(), - description: "run a shell command".into(), - input_schema: serde_json::json!({ "type": "object" }), - read_only: false, - speculation_safe: false, - }] - } - async fn execute(&self, _name: &str, _input: &Value) -> ToolOutput { - ToolOutput::Ok { - content: "1 passed\n[exit code: 0]".into(), - } - } -} - -/// A completion that runs `command` through the shell — the observation the -/// flip halt correlates by `call_id` and scores against the tracked test. -fn shell_call_result(command: &str) -> CompletionResult { - CompletionResult { - tool_calls: vec![ToolCall { - call_id: format!("call-shell-{command}"), - name: "bash".into(), - input: serde_json::json!({ "command": command }), - }], - ..text_result("") - } -} - /// #1793 witness (configured-command side): a revision that observes the /// tracked test go fail→pass halts at that step boundary instead of running /// on. The provider is scripted with steps BEYOND the flip; consuming them From 234cfe308c09632abe1d3cea48129d08cc95549d Mon Sep 17 00:00:00 2001 From: Mac Anderson Date: Thu, 6 Aug 2026 19:59:28 -0700 Subject: [PATCH 2/4] fix(stella-pipeline,scripts): also unbreak the file-size ratchet main merged past MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A fourth break on `main` at e0fbbe02, independent of the three duplicate-fix collisions in the parent commit and of anything either unbreak PR wrote: two grandfathered files sit one line over their recorded ceiling. crates/stella-core/src/driver.rs 2572 vs 2571 (+1) crates/stella-pipeline/src/pipeline/tests.rs 2537 vs 2536 (+1) Both are `main`'s own state — this branch touches neither file — from PRs (#1979, #1962) that grew them without regenerating the baseline in the same commit. It fails `file size ratchet` on every open PR, mine and #2000 alike, so nothing can land until someone absorbs it. Regenerated with `make file-size-update`, never hand-edited. **Saying the unflattering half out loud, per CLAUDE.md.** Two ceilings go UP by one line each. A raised ceiling to turn a gate green is normally a defect against the PR that raises it — the difference here is that these lines are already merged and shipping, so the choice is not "grow or don't" but "record what merged, or leave `main` red for everyone". I am recording it and naming it rather than letting it pass as routine. The two lines are somebody's to reclaim; neither is mine to judge irreducible. The same regeneration also TIGHTENS `crates/stella-pipeline/src/pipeline.rs` from 3451 to 3181 — 270 lines of headroom that had gone stale and is now closed off, which is the ratchet working as intended and more than offsets the two. `make guards-fast`: green. `cargo test -p stella-pipeline --lib`: 596 passed, 0 failed, both #1793 witnesses among them. --- scripts/file-size-baseline.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/file-size-baseline.txt b/scripts/file-size-baseline.txt index 960881fe..1196660a 100644 --- a/scripts/file-size-baseline.txt +++ b/scripts/file-size-baseline.txt @@ -20,14 +20,14 @@ 4621 crates/stella-cli/src/command_deck.rs 1507 crates/stella-cli/src/fleet_cmd.rs 2126 crates/stella-core/src/bus.rs -2571 crates/stella-core/src/driver.rs +2572 crates/stella-core/src/driver.rs 3681 crates/stella-core/src/driver/tests.rs 1781 crates/stella-model/src/anthropic/tests.rs 2093 crates/stella-model/src/openai.rs 1565 crates/stella-model/src/zai.rs 1895 crates/stella-model/src/zai/tests.rs -3451 crates/stella-pipeline/src/pipeline.rs -2536 crates/stella-pipeline/src/pipeline/tests.rs +3181 crates/stella-pipeline/src/pipeline.rs +2537 crates/stella-pipeline/src/pipeline/tests.rs 1996 crates/stella-store/src/lib.rs 2266 crates/stella-store/src/tests.rs 1916 crates/stella-store/src/usage.rs From 926380548ec742f31dc6c1e586470318dfdd5217 Mon Sep 17 00:00:00 2001 From: Mac Anderson Date: Thu, 6 Aug 2026 20:13:04 -0700 Subject: [PATCH 3/4] style(stella-protocol): restore the trailing newline #1994 dropped MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A fifth break on `main`, landed by #1994 (6c345532) minutes ago and unrelated to everything else in this PR: `crates/stella-protocol/src/event/tests.rs` ends without the blank line after `mod tag_table;` that rustfmt emits, so `cargo fmt --all --check` fails and takes the `fmt + clippy + test` job with it — on every open PR, not just this one. Applied with `cargo fmt --all`; the whole diff is one newline. Folded in here rather than filed because this PR already exists to make `main` build, and a one-newline fix in its own PR would spend more review attention than it costs to read. --- crates/stella-protocol/src/event/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/stella-protocol/src/event/tests.rs b/crates/stella-protocol/src/event/tests.rs index 30d80d2d..72cfda5e 100644 --- a/crates/stella-protocol/src/event/tests.rs +++ b/crates/stella-protocol/src/event/tests.rs @@ -1486,4 +1486,4 @@ fn a_known_event_wire_format_is_unchanged_by_the_fallback() { assert!(matches!(back, AgentEvent::Text { text } if text == "hello")); } -mod tag_table; \ No newline at end of file +mod tag_table; From 64742daddc8e6d7ba458178d461e980e55f21f55 Mon Sep 17 00:00:00 2001 From: Mac Anderson Date: Thu, 6 Aug 2026 20:38:08 -0700 Subject: [PATCH 4/4] fix(stella-protocol): resolve the CompactionRewrite doc link #1979 left dangling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A sixth break on `main`, from #1979 (#1667) and unrelated to the rest of this PR: `event.rs`'s `Compaction` variant documents its `rewrites` field with [`CompactionRewrite`], but that name is not in scope in `event.rs` — the field itself spells the fully-qualified `crate::CompactionRewrite`, and the type is only re-exported at the crate root from `compaction_rewrite.rs`. So `RUSTDOCFLAGS="-D warnings" cargo doc` fails the whole `fmt + clippy + test` job, on every open PR. The link now matches the path the field already uses — the same repair #1985 applied to `boot.rs`'s `SkipReason::NoResumePoint`, which is the second time this exact shape has broken `main` in a day. Caught only in CI, not locally, because `make guards-fast` runs no rustdoc and clippy does not check doc links: `doc-warnings` is a `make check`/`make gate` tier. Verified here with `make doc-warnings` over the whole workspace, which is now clean — worth doing directly, because each fix of this kind only lets rustdoc reach the next dangling link rather than proving there are none left. --- crates/stella-protocol/src/event.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/stella-protocol/src/event.rs b/crates/stella-protocol/src/event.rs index 13deb1aa..d91b0bda 100644 --- a/crates/stella-protocol/src/event.rs +++ b/crates/stella-protocol/src/event.rs @@ -542,7 +542,7 @@ pub enum AgentEvent { /// The replacement bytes each in-place rewrite left behind, one entry /// per digest — what lets reconstruction resolve a compacted block to /// the bytes the model received rather than the pre-compaction output - /// under the same `call_id` (#1667); see [`CompactionRewrite`]. + /// under the same `call_id` (#1667); see [`crate::CompactionRewrite`]. /// `serde(default)` — absent on journals written before rewrites were /// journaled, whose compacted blocks surface as digest mismatches. #[serde(default, skip_serializing_if = "Vec::is_empty")]