Skip to content

Add stage checkpoints and resume to SourceHuntRunner - #129

Draft
jorge-garcia-le wants to merge 1 commit into
mainfrom
worktree-stage-checkpoints
Draft

Add stage checkpoints and resume to SourceHuntRunner#129
jorge-garcia-le wants to merge 1 commit into
mainfrom
worktree-stage-checkpoints

Conversation

@jorge-garcia-le

Copy link
Copy Markdown
Contributor

Summary

Adds per-stage checkpoints and a resume capability to a single SourceHuntRunner run. Today, if a run crashes partway through, everything is lost — the hunt runs entirely in memory and findings.json/SARIF/report.md are written only once at the end. This change writes a lossless findings snapshot at each natural pipeline phase boundary so a crashed run can resume from the last completed phase.

Two goals:

  • (a) Eval transparency — a physical, json.load-simple artifact per phase showing how findings evolve across hunt → verify → exploit.
  • (b) Resume — re-run a crashed session from the last completed phase instead of from scratch, carrying budget forward.

Scope is deliberately coarse (three phase-level checkpoints, not the ~10 internal sub-stages). Mid-hunt/per-file resume, the proof flow, and changes to existing artifacts are out of scope.

What it does

Three checkpoints under <output_dir>/<session_id>/checkpoints/:

File Written Payload
hunt.json after per-file hunt + static-merge + subsystem hunt findings
verify.json after verify + stability findings + verified + rejected
exploit.json after exploit findings + verified + rejected + exploited

Each file is a superset of findings.json. Serialization is lossless (dataclasses.asdict, not the pool's lossy discovery-time subset); reload uses the tolerant __dataclass_fields__ filter.

Resume via a new resume_session parameter (accepts a bare sh-<uuid> name or a path to a session dir):

  • Highest checkpoint present wins (exploit > verify > hunt).
  • Re-runs preprocess (rebuilds repo checkout / callgraph / sandbox that verify+exploit need); skips rank — its priority fields are only consumed by the hunt phase.
  • Guards each completed phase and its enrichment/side-effect sub-stages so only work after the last checkpoint executes.
  • Report always re-runs (cheap; regenerates findings.json/SARIF/report.md).
  • Deliberate exit: a session dir with no checkpoint raises rather than silently starting over.

Budget carries forward: the prior run's settled spend is summed from the existing spend-ledger.jsonl and seeded into a new SpendLedger via a new initial_spent_usd kwarg, so a resumed run honors the original dollar cap.

Existing artifacts (findings.json, findings_pool.jsonl, etc.) are untouched — only new checkpoint files are added.

Changes

  • New clearwing/sourcehunt/checkpoints.py — standalone checkpoint read/write (atomic mkstemp + os.replace), latest_checkpoint, sum_prior_spend, resolve_session_dir.
  • clearwing/llm/budget.py — new initial_spent_usd kwarg on SpendLedger (validated finite/≥0), recorded as carried_forward_usd in the run_started event.
  • clearwing/sourcehunt/runner.pyresume_session param; adopts the resumed session id before instrumentation; seeds the ledger on resume; preflight skips models for skipped phases; arun writes the three checkpoints and guards completed phases on resume.
  • tests/test_sourcehunt_checkpoints.py — 27 tests covering lossless round-trip, priority ordering, spend reconstruction, budget seeding, deliberate exit, and end-to-end resume (hunt+verify skipped, report re-runs, budget carried).

Eval passthrough

No call-site change needed in agent_eval.pyresume_session flows through the existing **extra/--runner-arg resume_session=<name> passthrough.

Verification

  • 27/27 new tests pass; 35/35 existing budget + runner regression tests pass.
  • ruff check clean on all touched files.

Write a lossless findings snapshot at each natural pipeline phase
boundary (end of hunt, verify, exploit) under
<session>/checkpoints/<stage>.json. Each file is a json.load-simple
superset of findings.json, so it doubles as an eval artifact showing how
findings evolve across phases.

These checkpoints back a new resume_session parameter: a crashed or
errored run resumes from the last completed phase instead of re-hunting
from scratch. Resume re-runs preprocess (rebuilds repo/callgraph/sandbox)
but skips rank (its priority fields are only consumed by the hunt phase),
seeds the finding lists from the checkpoint, and guards each completed
phase and its enrichment/side-effect sub-stages so only work after the
last checkpoint executes. Report always re-runs.

Budget carries forward: the prior run's settled spend is summed from the
existing spend-ledger.jsonl and seeded into a new SpendLedger via a new
initial_spent_usd kwarg, so a resumed run honors the original dollar cap.

Resume is deliberate — a session dir with no checkpoint raises rather
than silently starting over. Existing artifacts are untouched; only new
checkpoint files are added.

Adds tests for the checkpoint module, budget carry-forward, deliberate
exit, and end-to-end resume (hunt+verify skipped, report re-runs, budget
carried).
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.

1 participant