Skip to content

fix(sourcehunt): bound persisted trace-step payloads - #205

Open
tsunoda-kazuya wants to merge 3 commits into
Lazarus-AI:mainfrom
tsunoda-kazuya:fix/sourcehunt-trace-step-bound
Open

fix(sourcehunt): bound persisted trace-step payloads#205
tsunoda-kazuya wants to merge 3 commits into
Lazarus-AI:mainfrom
tsunoda-kazuya:fix/sourcehunt-trace-step-bound

Conversation

@tsunoda-kazuya

Copy link
Copy Markdown
Contributor

Summary

  • Cap code_snippet and note recorded by record_trace_step at trace_step_max_chars (default 4096) and mark truncated steps with truncated: bool and original_chars: int.
  • The cap is also applied to inline trace steps passed via record_finding(trace={"steps": [...]}), which chatty local models use in place of streaming record_trace_step.
  • Read the limit from HuntTuning.trace_step_max_chars; --full-trace sets it to 0 (disabled).
  • Complements fix(sourcehunt): bound machine-mode result payload #194, which bounds the machine-mode result payload; this bounds what is persisted to ctx.trace_steps and flows into Finding.vulnerability_trace and the written artifacts.

Problem

record_trace_step appends model-supplied text to ctx.trace_steps without a size limit. Those steps travel into finding evidence and the written artifacts, so a long hunt on a large repository can produce artifacts far larger than the findings they describe. The machine-mode projection bounds what is returned to a caller, not what is stored.

Fix

  • New _cap_trace_strings helper truncates code_snippet and note at ctx.trace_step_max_chars; attaches truncated=True and original_chars=<combined pre-truncation char count> when it clips.
  • record_trace_step (streaming path) applies the cap before constructing TraceStep.
  • record_finding's compatibility path for inline trace={"steps": [...]} routes each step through _build_capped_trace_step so the two entry points behave identically.
  • HuntTuning.trace_step_max_chars (default 4096); HuntPoolConfig and SourceHuntRunner thread it to HunterContext. --full-trace sets the value to 0, which the helper treats as unlimited.

Validation

  • uv run --frozen --extra dev pytest -q tests/test_hunt_reporting_tools.py tests/test_sourcehunt_hunter.py tests/test_sourcehunt_trace_cap_config.py — 102 passed; new regressions: below-cap preserved byte-identically; above-cap truncated with original_chars set; inline record_finding path capped identically; --full-trace (cap=0) leaves 1 MB inputs untouched; config default 4096; pool sets ctx.trace_step_max_chars from config.
  • uv run --frozen --extra dev ruff check clearwing/agent/tools/hunt/reporting.py clearwing/agent/tools/hunt/sandbox.py clearwing/findings/types.py clearwing/sourcehunt/config.py clearwing/sourcehunt/pool.py clearwing/sourcehunt/runner.py clearwing/ui/commands/sourcehunt.py
  • git diff --check

Backward compatibility

Steps under 4096 characters are unchanged. Consumers see two new optional keys only on truncated steps (both default to False/0). --full-trace restores the previous unlimited behaviour.

Independent of the other 4 PRs in this batch; trivial rebase if any lands first.

record_trace_step accepted arbitrarily large code_snippet and note strings
and appended them straight onto ctx.trace_steps. Those strings flow through
finding evidence into artifacts, so on large repos with chatty hunters they
bloated reports and slowed downstream processing.

Cap code_snippet and note at HunterContext.trace_step_max_chars (default
4096). When truncation occurs, mark the TraceStep with truncated=True and
record original_chars so downstream can tell that content was clipped.
Setting trace_step_max_chars <= 0 disables the cap entirely.

The knob currently lives on HunterContext only; wiring it through
SourceHuntConfig and the CLI is left for a follow-up to keep the surface
change minimal (HunterContext has 9 constructor sites).
The streaming record_trace_step path caps code_snippet and note via
_cap_trace_strings, but the inline compat path in record_finding
(trace={"steps": [...]}) built TraceStep directly from the dict and
bypassed the cap. Chatty local models prefer the inline path, so the
bounded-evidence promise was broken on exactly the callers that motivate
this change. Route inline steps through the same helper and mark
truncated/original_chars accordingly.

Also drop the getattr fallback for ctx.trace_step_max_chars now that
HunterContext declares the field.
… --full-trace

Adds HuntTuning.trace_step_max_chars (default 4096) so the trace-step cap
is configurable through SourceHuntConfig. SourceHuntRunner accepts a
trace_step_max_chars kwarg that reaches the hunt pool and the verifier
HunterContext; HuntPoolConfig propagates it to each per-file hunter via
_configure_hunter_context. The CLI gains --full-trace, which sets the cap
to 0 to retain the full snippet on record_finding trace steps.
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