Skip to content

fix(stella-pipeline): bound the oracle trace at the verifier-prompt ingress (#1787) - #2002

Merged
macanderson merged 6 commits into
mainfrom
land-1787-oracle-trace-bound-on-main
Aug 7, 2026
Merged

fix(stella-pipeline): bound the oracle trace at the verifier-prompt ingress (#1787)#2002
macanderson merged 6 commits into
mainfrom
land-1787-oracle-trace-bound-on-main

Conversation

@macanderson

@macanderson macanderson commented Aug 7, 2026

Copy link
Copy Markdown
Owner

Why this PR exists

#1787's fix is not in main. PR #1982 carried it, but its base was the topic branch unbreak-main-pipeline, whose own PR (#1975) was closed, not merged. #1982 then merged into that dead branch, so the oracle-trace bound landed nowhere main can see, and nothing is carrying that branch forward.

It also merged in a broken state. While the base was being reconciled with main, git's auto-merge of the two independently-written unbreaks concatenated both sides, leaving:

  • struct PassingShell and fn shell_call_result defined twice
  • async fn a_revision_halts_at_the_step_where_the_tracked_test_flips defined twice
  • a duplicate ModelCallRole::Research match arm (unreachable pattern)

None of that compiles. unbreak-main-pipeline currently holds it; main is unaffected.

This PR is the clean landing: main plus evidence.rs, and nothing else.

What it does (#1787)

Bounds the oracle trace at the verifier-prompt ingress. The trace grows once per verification round and the repair gate can keep granting rounds while a measured budget affords them — so unlike the diff, which rides under a token budget, this channel had no ceiling at all.

  • MAX_ORACLE_TRACE_OBSERVATIONS = 24 — sized far above a normal run (baseline plus a handful of rounds) so the bound only bites a pathological loop.
  • bounded_oracle_trace keeps the newest observations and states the drop in-band (…N earlier observation(s) omitted → …), so the verifier reads "earlier observations exist" rather than a trace that silently starts mid-run.
  • The stored snapshot keeps the full trace; only the prompt ingress is clipped — the structural-bound rule from fix(stella-pipeline): bound the verdict reasoning at the point it is constructed (#1787) #1932.

Witnesses

  • a_pathological_oracle_trace_is_clipped_with_the_drop_stated — a 100-observation trace renders clipped to the newest 24 with the omission counted in-band.
  • an_ordinary_oracle_trace_renders_unchanged — the bound does not touch a normal run, so this cannot ship as "always clip".

Observations alternate pass/fail in the fixture so a clipped render is distinguishable from a repeated one.

Verification

  • cargo test -p stella-pipeline585 pass, 0 fail, including both witnesses above
  • cargo fmt --check -p stella-pipeline — clean
  • Diff vs main is exactly one file: crates/stella-pipeline/src/pipeline/evidence.rs (+74/−2)

CI is red on main's breaks, not this diff

This branch is merged up to current main. Every failing step fails in a file this PR does not touch, and each already has a dedicated unbreak in flight:

Failing step Where Covered by
check-file-size scripts/file-size-baseline.txt (parallel-merge skew) #2003, #2008
cargo fmt --check not this crate's file #2005
clippy: unused spend / unused mut pipeline/scope_stage.rs:34 — a dead local #1985 left behind #2000
rustdoc: unresolved CompactionRewrite stella-protocol #2010

The clippy one is worth naming precisely, since it is stella-pipeline: main's scope_stage.rs binds let mut spend = Spend { budget, total }; and then never uses it — the loop constructs a fresh Spend inline per iteration. spend occurs exactly once in the file. That is main's dead local, untouched by this PR.

No competing unbreak is included here on purpose — six are already open against main, and duplicating one is how main gets re-broken.

Note on the dead branch

unbreak-main-pipeline still holds the duplicate-definition breakage and the only copy of #1982's merge. It is not reachable from main and its PR is closed, so nothing needs to be reverted — but it should not be revived without first taking main's copies of flip_halt_arming.rs, management_prompt/tests.rs and scope_stage.rs, which is what this PR does. Filed as #2001.

Closes #1787

…an uncovered ModelCallRole

main was red at 43402ae: stella-pipeline's lib test build failed with
three compile errors, so every PR against it inherits a red gate.

Two independent parallel-merge collisions, neither visible to the CI of
the PR that caused it:

1. #1951 rewrote tests/verification_hardening.rs from a pre-#1945 base,
   deleting the PassingShell double, shell_call_result, and the
   configured-command witness, while leaving the 'mod flip_halt_arming;'
   #1945 had added — so the child module referenced two symbols that no
   longer existed. Restored into flip_halt_arming.rs itself rather than
   the parent: verification_hardening.rs is 1434 lines against a 1500
   ceiling and cannot hold them, and the child is their only user. Both
   #1793 witnesses now sit in one module.

2. #1778 added ModelCallRole::Research; management_prompt/tests.rs holds
   a deliberately exhaustive match over the enum, which #1778's own CI
   never compiled against. Research runs as an engine sub-agent turn, so
   its system prompt rides its SubAgentSpec and it joins the
   never-dispatched-through-the-chokepoint arm — the same grouping, with
   the same reasoning, that raw_usage.rs already gives it. Added to
   ALL_ROLES too, since that array is 'every role the crate can dispatch'.

No behavior change: test-only code plus one test-only match arm.
… the research stage

Third break on main from the same round of parallel merges: #1778 added
'research: &[ResearchFinding]' to plan_stage, taking it to 8 arguments
against clippy's limit of 7. The gate runs clippy at -D warnings, so
stella-pipeline could not pass it.

Fixed structurally, not with an #[allow]: budget and total are exactly
the pair the crate's own Spend envelope bundles (stage_budget.rs), and
they travel together everywhere else — verifier() already took this
shape in #1951. plan_stage takes Spend, plan_with_review builds one
before its re-plan loop and reborrows it per iteration, and neither
uses the two for anything else. 8 arguments become 7 and the meaning
is unchanged.

No behavior change.
…ngress

The trusted evidence summary rode into the verdict prompt with no length
bound on its one growing channel: oracle_trace gains an observation per
verification round, and the repair gate can keep granting rounds as long
as a measured budget affords them — the diff has a token budget, the
trusted zone had none (#1787's folded-in item).

Bounded where the prompt value is constructed (the #1932 rule), to the
newest 24 observations with the drop stated in-band, so a verifier reads
'earlier observations exist' rather than a trace that silently starts
mid-run. The stored ladder snapshot keeps the full trace; provenance
rendering is deliberately untouched.

Refs #1787
…-bound

# Conflicts:
#	crates/stella-pipeline/src/management_prompt/tests.rs
#	crates/stella-pipeline/src/pipeline/scope_stage.rs
#	crates/stella-pipeline/src/pipeline/tests/verification_hardening/flip_halt_arming.rs
…es this branch does not own

The merge of main into this branch collided on three files that the closed
base branch (unbreak-main-pipeline, PR #1975) had fixed independently of the
unbreaks that actually landed (#1970, #1971). Git's auto-merge concatenated
both sides, leaving duplicate PassingShell / shell_call_result definitions
and a duplicate ModelCallRole::Research match arm — neither of which compiles.

This branch owns only pipeline/evidence.rs (#1787's oracle-trace bound), so
the other files take main's shipped, reviewed copies verbatim. The branch is
now exactly main plus evidence.rs.

@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.

Project Deployment Actions Updated (UTC)
stella-cli-docs Ready Ready Preview Aug 7, 2026 3:03am

@sourcery-ai

sourcery-ai Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Bounds the oracle trace rendered in verifier prompts, adds a helper to cap the number of observations shown while preserving the full stored trace, and introduces tests that ensure pathological traces are clipped with an in-band omission notice while normal traces remain unchanged.

File-Level Changes

Change Details Files
Introduce a bounded oracle trace renderer for verifier prompts and apply it where the oracle trace is appended to the evidence summary.
  • Add MAX_ORACLE_TRACE_OBSERVATIONS constant to cap rendered observations for verifier prompts
  • Implement bounded_oracle_trace helper that keeps the newest observations and prepends an in-band omission message when clipping occurs
  • Use bounded_oracle_trace instead of direct render_oracle_trace when adding oracle_trace to the evidence_summary string
crates/stella-pipeline/src/pipeline/evidence.rs
Add unit tests and helpers to validate the new oracle trace bounding behavior for pathological and ordinary runs.
  • Extend test module imports to include new constants and types used by the bounding logic
  • Add trace_of helper to generate alternating pass/fail oracle observation sequences
  • Add test ensuring long traces are clipped to the configured maximum with the omission count stated in-band and the newest observations preserved
  • Add test ensuring short, ordinary traces render identically to the unbounded render function
crates/stella-pipeline/src/pipeline/evidence.rs

Assessment against linked issues

Issue Objective Addressed Explanation
#1787 Introduce a structured/JSON verdict output path for the verifier (instead of relying on the first-non-empty-line token protocol), with provider-parity-aware configuration and tests. The PR only changes crates/stella-pipeline/src/pipeline/evidence.rs to bound and render the oracle trace; it does not modify verify.rs or verifier_stage.rs, nor does it introduce any structured/JSON verdict protocol or provider-specific posture configuration.
#1787 Impose a structural length bound on Verdict::reasoning so that verifier responses cannot flow unbounded into the worker revision prompt and verdict cache. The diff contains no changes to how Verdict::reasoning is captured, stored, or injected into prompts; it only bounds the oracle trace length at prompt ingress. There is no cap introduced on the size of the reasoning text.
#1787 Add a length bound to the trusted evidence summary’s oracle trace (rendered into verifier prompts), clipping it structurally while preserving the full stored snapshot.

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

@macanderson
macanderson merged commit d891167 into main Aug 7, 2026
13 of 15 checks passed
@macanderson
macanderson deleted the land-1787-oracle-trace-bound-on-main branch August 7, 2026 03:42
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.

Verdict output contract is fragile: no structured-output path, unbounded reasoning, degradations warned once per run across a fan-out

1 participant