Get Started
Guide

Refine

Let a local model fix findings, retest each one, and repeat until the backlog is clear

thespider-agent refine picks actionable findings, has a local model write a fix, records the commits as a proposed fix, then runs a retest. It repeats until that backlog is empty or --max-iterations is hit.

Refine itself never writes fixed or still_vulnerable. Only a finished retest does.

Refine asks the agent to list actionable findings from TheSpider Cloud, run an agentic fix in a local worktree, record the commits as needs_retest, then retest. Only a finished retest marks a finding fixed or still vulnerable. The loop repeats until the backlog is clear.

You
thespider-agent
Model CLI
TheSpider Cloud
refine --min-severity high
list actionable findings
backlog
agentic fix in a worktreecommit, never push
needs_retest + commit SHAsproposed, not fixed
create retest campaign
audit slices on the fixed tree
stdout
results
fixed or still_vulnerable

Repeat until the selected backlog is empty, or `--max-iterations` is hit.

Refine never writes `fixed`. A completed retest is the only thing that does.

One iteration

  1. Select. status=actionable, filtered by --min-severity (a floor: high means critical and high), --branch, and --profile. Sorted by severity, capped at 100. A truncated list is disclosed, never called "clear". Empty list exits 0.
  2. Fix. Re-fetch each finding (skip it if a human already triaged it). Render the finding packet into a fix prompt. Run the fix binding in agentic mode in the worktree. The prompt asks for a small targeted fix, cheap tests, a commit, and no push.
  3. Validate. Counts only if the model exited 0, the tree is clean, and at least one new commit has the pre-fix HEAD as an ancestor. Otherwise that finding is a no-op.
  4. Record. needs_retest plus the commit list. The server stores a proposed fix row and sets fixed_at_commit to the last SHA. The finding stays actionable.
  5. Retest. Create a retest campaign at the post-fix HEAD, run its slices with the retest binding, wait until it finishes. Failed slices mark the run degraded; the finding stays needs_retest and comes back next iteration.
  6. Re-list. fixed drops out of actionable. still_vulnerable stays in.

An iteration that made zero new commits and worked zero campaigns stops early.

Retest slices go through the same runner as run and daemon, so each one leaves a per-lease run log you can follow with thespider-agent log. The fix runs in step 2 use a different runner and are not logged that way.

Flags

thespider-agent refine [--max-iterations N] [--min-severity SEV] [--branch NAME] [--list]
                       [--model CODE] [--retest-model CODE] [--fix-timeout SECS] [--retest-timeout SECS]
                       [--in-place] [--profile security|bugs] [--redact] [--json]
FlagDefaultMeaning
--max-iterations3Stop after N loops. 1 is fix once and verify.
--min-severitynoneA floor, not a set. high expands to critical,high.
--branchnoneFilter and guardrail: the checkout must already be on this branch.
--listoffDry run. Print the selection, write nothing. Exit 0 if empty, 1 if work remains.
--modelfirst project bindingThe models.dev code that fixes.
--retest-modelsame as --modelThe models.dev code that retests. Required when the fixer is a freeform command.
--fix-timeoutbinding timeoutSeconds for one agentic fix.
--retest-timeout1800Seconds to wait for each retest campaign.
--in-placeoffFix in the parent checkout. Needs a clean tree. No merge copy at the end.
--profilerepo configsecurity or bugs. all is rejected.
--redactoffSame client-side stdout scrub as run --redact.
--jsonoffVersioned envelope. See Agent CLI contracts.
thespider-agent refine --min-severity high --max-iterations 2

Exit codes

CodeNameMeaning
0OKSelected backlog is empty.
1FINDINGSWork remains after --max-iterations.
3TIMEOUTA retest wait exceeded --retest-timeout.
4DEGRADEDA retest finished with failed slices, or with no conclusion.
5USAGEBad flags, --profile all, unbound models, or a 409 commit_mismatch.
6OPERATIONALTransport, auth, or missing worktree tooling.
7INTERRUPTEDSIGINT/SIGTERM. The worktree is left in place with resume hints.

When several apply: 7 > 3 > 4 > 1 > 0.

Worktree

By default refine works in a throwaway git worktree, so your checkout is not the fix agent's working directory:

git worktree add <tmp> -b thespider/refine/<project-slug>-<utc-ts> <parent HEAD>
  • The worktree is removed on a normal exit. The branch is kept.
  • Merge instructions print at the end (worktree mode only).
  • A failing pre-push hook is installed in the worktree, so the agent cannot git push. Commits are authored as thespider-agent <refine@thespider.local>.
  • Campaigns record your original checkout branch, not the worktree branch name.

--in-place skips the worktree. The tree must be clean before each fix.

Before you point it at a repo

Finding text is model-derived. The packet renderer strips heading forgeries and control characters, but the fix agent is a writer: your credentials, your network, your host. A worktree keeps its commits off your branch. It is not a sandbox.

A freeform command runs exactly what you wrote. Built-in agentic modes (acceptEdits, workspace-write) auto-approve edits and can still hang on other prompts. --fix-timeout bounds that.

The push blocker is a git hook, not a network control. It stops git push. It does not stop anything that talks to the remote another way.

Metering

Every retest slice is a billable slice_claim at claim time (first claim per slice; retries do not double-count). Retest ingest may also meter ai_dedupe_call. Refine prints the campaign id, slice count, and that note as each campaign is created. Plan limits: Pricing.

Proposed vs fixed

  • needs_retest + commits writes a proposed fix row. The finding stays actionable.
  • A retest that does not see it again concludes fixed and marks that row verified.
  • A retest that sees it again concludes still_vulnerable. The proposed row stays proposed for the next fix.

If refine crashes mid-run, the next run re-selects the same finding. Expect history to cycle needs_reteststill_vulnerableneeds_retest until a fix verifies. That trail is the point.

Interrupt

On interrupt, refine leaves the worktree and prints its path, branch, in-flight campaign ids, and:

thespider-agent run --campaign <id> --once

A later refine run warns about non-terminal retest campaigns and prints the same hint.

Next

Copyright © 2026