Verdict
Architecture·6 layers · 3 MCP tools · 1 verdict

How Verdict works

Each layer is a Bob custom mode that emits structured JSON. The next layer reads it. The synthesis at the end calls a deterministic MCP tool to find the cross-layer match — guaranteeing the killer line fires when it should.

6
Pipeline layers
3
MCP tools
5
Bob skills
The pipeline

Six sequential layers

01

Semantic Diff

What changed in meaning. Function signatures, return types, invariants, lifecycle. Ignores whitespace, formatting, and renames.

modeverdict-semantic
skillsemantic-diff
// output schema
{
"mode_name": "semantic",
"findings": "[changes]",
"next_mode_input": "{...}",
}
02

Blast Radius

What else in the full repository depends on what changed. Uses @file references to read every potentially affected file.

modeverdict-blast
skillblast-radius
// output schema
{
"mode_name": "blast",
"findings": "[callers]",
"next_mode_input": "{...}",
}
03

Mutation Audit

Which surviving mutations represent real bugs. Classifies by type and severity. CRITICAL = auth, payment, data integrity.

modeverdict-mutation
skillmutation-audit
mcpuvx mutmut-mcp
// output schema
{
"mode_name": "mutation",
"findings": "[survivors]",
"next_mode_input": "{...}",
}
04

Incident Mining

What broke here before. Parses INCIDENTS.md and git log for fix:, hotfix:, revert:, rollback:, INC- commits.

modeverdict-incident
skillincident-mining
mcpfind_incident_commits
// output schema
{
"mode_name": "incident",
"findings": "[incidents]",
"next_mode_input": "{...}",
}
05

Reviewer Questions

Exactly three specific risk questions. Each must reference a finding from a prior layer. No style, no 'have you considered'.

modeverdict-questions
skillpr-synthesis
// output schema
{
"mode_name": "questions",
"findings": "[Q1, Q2, Q3]",
"next_mode_input": "{...}",
}
06

Synthesis

Killer line fires here

One GitHub comment. TL;DR + Verdict + 5 sections. If cross-layer match exists, TL;DR sentence 1 is the killer line — non-negotiable.

modeverdict-synthesis
skillpr-synthesis
mcpfind_cross_layer_match
// output schema
{
"mode_name": "synthesis",
"findings": "<full PR VERDICT comment>",
"next_mode_input": "{}",
}
MCP server

Three tools, one moment.

The verdict-tools MCP server is FastMCP-based and exposes 3 tools to Bob. The third is the one that fires the killer line.

get_git_history
get_git_history(file_path, since_days=90)
Retrieves git commit history for a specific file. Returns a list of commits with sha, date, and message.
find_incident_commits
find_incident_commits(file_paths)
Mines INCIDENTS.md and git log for past incidents involving the changed files. Extracts incident IDs, line ranges, root causes.
find_cross_layer_match
find_cross_layer_match(mutations, incidents)
Matches mutations to incidents by file path + line distance (≤5 lines). When a match exists, it returns the killer_line string.
.bob/mcp.json
{
  "mcpServers": {
    "verdict-tools": {
      "command": "python",
      "args": ["packages/mcp-server/server.py"]
    },
    "mutmut": {
      "command": "uvx",
      "args": ["mutmut-mcp"]
    }
  }
}
Why this architecture

Each layer is just JSON in, JSON out.

The 6-layer split means every step is independently testable, swappable, and observable. The Python harness orchestrates Bob Shell calls; the MCP server provides deterministic tools; the cross-layer match is computed in Python before synthesis — so the killer line cannot be hallucinated.

Bob plans the pipeline. Bob runs the pipeline. The pipeline produces the killer line.

See it fire.

Run the demo