Skip to content

Verify Stage

VerifyStage determines whether deduplicated bugs are reproducible, reachable, or otherwise supported by evidence. It produces a vega.verification_results artifact used by PatchStage.

Location

src/stages/verify/stage.py

Stage declaration

class VerifyStage(BaseStage[StageInput, StageOutput]):
    name = StageName.VERIFY
    required_artifacts = ("source_snapshot",)
    produced_artifacts = ("verification_evidence",)

Input

VerifyPatchTransition builds the stage input from PipelineState:

StageInput(
    repo_id=state.repo_id,
    run_id=state.run_id,
    source_snapshot=state.source_snapshot,
    plan_artifact=state.plan_artifact,
    data={
        "bugs": state.deduplicated_bugs,
        "selected_plugin": ...,  # plugin id/version metadata
    },
)

data["bugs"] is the deduplicated_bugs tuple from SharedTriageService.

What it does

For each deduplicated bug:

  1. Loads the bug record from input.data["bugs"].
  2. Reads the relevant source files from the source snapshot.
  3. Optionally simplifies the threat model if a plan_artifact is present (using stages/verify/prompts/threat_model_simplify.txt).
  4. Runs an agent task (purpose="verify.finding") per bug in parallel using the default verification prompt (stages/verify/prompts/default.txt).
  5. Validates the agent output against stages/verify/schemas/results.json.
  6. Emits a finding_verified domain event for each result.
  7. Writes all verification results as the vega.verification_results artifact.
  8. Emits verification_evidence_created.

Threat model contract

Before verifying individual bugs, VerifyStage optionally runs a separate agent call (purpose="verify.threat_model_simplify") to condense the full threat model into a compact "contract" relevant to the bugs being verified. This is only done when a threat model artifact is present and avoids flooding the verification prompt with an entire large threat model document.

Verification result schema

Each result in vega.verification_results follows this shape:

{
  "finding_id": "bug_1",
  "status": "verified",
  "triggerable": true,
  "bug_description": "Bug overview and affected behavior.",
  "root_cause": "Root cause and reproducibility explanation.",
  "strategy": "agent_verification",
  "evidence": ["relevant source path or evidence string"],
  "confidence": "high",
  "metadata": {}
}

Possible status values:

Status Meaning
"verified" Bug is reproducible / reachable — eligible for patch
"not_verified" Agent could not reproduce or reach the bug
"insufficient_evidence" Insufficient data to determine

Domain events

Event kind When emitted
finding_verified Each individual verification result
verification_evidence_created Artifact written

finding_verified payload

{
  "finding_id": "bug_1",
  "status": "verified",
  "triggerable": true,
  "verification_evidence": {"uri": "...", "kind": "verification_evidence", ...}
}

The root_cause and confidence fields are present inside the vega.verification_results artifact per-result entry, not in the event payload.

Backend updates finding verification status from this event.

Parallelism

Verification runs with RunPolicy.max_workers_per_runner worker threads, matching audit parallelism. Each bug is processed independently.

Cancellation

VerifyStage calls context.checkpoint(StageName.VERIFY, progress) between bugs. Cancellation terminates in-flight agent calls and emits stage_cancelled.

Error handling

Condition Behavior
Agent failure for one bug Bug marked not_verified; verification continues
Agent output schema invalid Bug marked insufficient_evidence
All bugs fail to verify Stage still completes; PatchStage will skip unverified bugs