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:
- Loads the bug record from
input.data["bugs"]. - Reads the relevant source files from the source snapshot.
- Optionally simplifies the threat model if a
plan_artifactis present (usingstages/verify/prompts/threat_model_simplify.txt). - Runs an agent task (
purpose="verify.finding") per bug in parallel using the default verification prompt (stages/verify/prompts/default.txt). - Validates the agent output against
stages/verify/schemas/results.json. - Emits a
finding_verifieddomain event for each result. - Writes all verification results as the
vega.verification_resultsartifact. - 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 |