Track Issues & Regressions

Navigate runs, issues, and regressions in the validation tracker.

Overview

The UluOps Validation Tracker automatically correlates issues across runs using SHA-256 fingerprinting. Every finding gets a stable fingerprint based on its file, location, and failure type — so the same issue is tracked across runs even as line numbers shift.

This guide covers how to query, manage, and analyze issues using the ops MCP server in Claude Code, with SDK alternatives for programmatic access.

Viewing Runs

Get the Latest Run

text
get_latest_run({ project: "my-project" })

This returns the most recent validation run with all agent scores, the overall decision, and correlation data showing what changed since the previous run.

Compare Two Runs

text
diff_runs({
  project: "my-project",
  base_run: 3,
  compare_run: 5
})

The diff shows which issues were fixed, which are new, which remain unchanged, and how agent scores changed between runs. Useful for verifying that a fix round actually resolved the targeted issues.

Note

SDK alternative:

typescript
const latest = await client.runs.getLatest({ project: 'my-project' });
const diff = await client.runs.diff({
  project: 'my-project',
  baseRun: 3,
  compareRun: 5,
});

Querying Issues

By Status

text
# All open issues
query_issues({ project: "my-project", status: "open" })

# Only critical priority
query_issues({ project: "my-project", status: "open", priority: "critical" })

By Agent

text
query_issues({ project: "my-project", agent: "code-validator" })

By Failure Domain

Filter by the failure taxonomy to focus on specific issue types:

text
# All open epistemic issues (assumptions, evidence gaps)
query_issues({ project: "my-project", failure_domain: "EPI" })

# Structural issues from a specific agent
query_issues({ project: "my-project", failure_domain: "STR", agent: "public-interface-validator" })

Domains: STR (structural), SEM (semantic), PRA (pragmatic), EPI (epistemic).

text
search_issues({ query: "error handling", projects: ["my-project"] })

Search works across projects and supports filtering by status, priority, severity, agents, and failure domains.

Example Response

Each issue in the query response includes an id you'll use for updates, along with the finding details:

json
{
  "id": "a1b2c3d4-...",
  "title": "Missing null check on .find() result",
  "status": "open",
  "priority": "suggested",
  "severity": "medium",
  "agent": "code-validator",
  "filePath": "src/services/auth.ts",
  "lineNumber": 23,
  "failureCode": "SEM-COM/M",
  "failureDomain": "SEM",
  "failureMode": "COM",
  "fingerprint": "9f21dc...",
  "timesSeen": 3,
  "firstSeenRunId": "...",
  "lastSeenRunId": "..."
}

The timesSeen field shows how many runs have flagged this issue — useful for identifying persistent problems.

Note

SDK alternative:

typescript
const open = await client.issues.query({
  project: 'my-project',
  status: 'open',
  priority: 'critical',
});

const results = await client.issues.search({
  query: 'error handling',
  projects: ['my-project'],
});

Managing Issue Lifecycle

Issues move through these statuses:

StatusMeaningWhen to Use
openActive, needs attentionDefault for new findings
completedGenuine defect, fixedThe fix has been verified
wontfixCorrect observation, not worth acting onValid finding but doesn't warrant a change (lifecycle mismatch)
false-positiveAgent was factually wrongThe agent misread the code — this isn't actually an issue
observationValid observation, tracked separatelyFor analyst/forecaster findings that aren't defects
deferredAcknowledged, will address laterGenuine issue but not the right time to fix
mergedMerged into another issueDuplicate finding consolidated into a target issue
💡
Tip

Your labeling matters. The distinction between wontfix (correct finding, not actionable) and false-positive (agent was wrong) is what drives the Recursive Appreciation feedback loop. Accurate labeling helps the system distinguish accuracy failures from lifecycle mismatches — and the difference is significant (6.4% FP rate vs 18.0% combined rejection rate across the ecosystem).

Update Status

You can identify issues by id (preferred), fingerprint, or file_path + title:

text
update_status({
  project: "my-project",
  updates: [
    { id: "a1b2c3d4-...", status: "completed", reason: "Fixed in PR #42" },
    { id: "e5f6g7h8-...", status: "deferred", reason: "Waiting on v2 migration" }
  ]
})

For bulk updates across many issues at once (up to 100):

text
bulk_update_status({
  project: "my-project",
  updates: [
    { id: "a1b2c3d4-...", status: "completed", reason: "Resolved in refactoring sprint" },
    { id: "e5f6g7h8-...", status: "completed", reason: "Resolved in refactoring sprint" },
    { id: "i9j0k1l2-...", status: "wontfix", reason: "Intentional pattern" }
  ]
})

Undo a Status Change

Accidentally marked something completed? Undo the last status change:

text
undo_issue_status({ issue_id: "a1b2c3d4-..." })

This reverts to the previous status and preserves the full status history.

Add Notes

Attach context to issues without changing their status:

text
add_issue_note({
  issue_id: "a1b2c3d4-...",
  note_type: "context",
  content: "Caused by the legacy API adapter — will fix when we migrate to v2"
})

Note types: context (background info), resolution (how it was fixed), blocker (what's preventing a fix).

Note

SDK alternative:

typescript
await client.issues.updateStatus({
  project: 'my-project',
  updates: [
    { id: issueId, status: 'completed', reason: 'Fixed in PR #42' },
  ],
});

await client.issues.addNote({
  issueId: issue.id,
  noteType: 'context',
  content: 'Caused by the legacy API adapter',
});

Detecting Regressions

Regressions are automatically detected when a previously resolved fingerprint reappears in a new run. The tracker flags these in the correlation summary after each run is saved.

Check for Regressions

When you save a run (see Run a Validation), the response includes correlation data:

text
# Response from save_run includes:
#   correlation.newIssues: 2
#   correlation.recurring: 5
#   correlation.regressions: 1  <- previously fixed issue came back
#   correlation.resolved: 3

Respond to Regressions

When regressions appear:

  1. Investigate the diff — use diff_runs to see exactly which resolved issues reappeared
  2. Check if the fix was reverted — a merge conflict or rebase may have dropped the fix
  3. Re-run the specific agent — confirm the regression is real, not a false positive from changed context
  4. If the issue is real, fix it again and add a note explaining what caused the regression

Investigate Recurring Issues

Find issues that keep appearing across runs:

text
query_issues({ project: "my-project", min_times_seen: 3, status: "open" })

Recurring issues often indicate a systemic pattern rather than a one-off bug. Consider whether the codebase needs an architectural fix or whether the agent criteria need adjustment. See Improve Your Agents for how to iterate on criteria.

Analytics

The tracker provides several analytics tools to help you understand trends beyond individual issues.

Project Summary

Get a high-level overview with issue counts, agent stats, and trends:

text
get_project_summary({ project: "my-project" })

Burndown

Track open issue count over time by failure domain:

text
get_burndown({ project: "my-project", days: 30 })

A downward trend with stable scores means the team is resolving real issues, not just lowering the bar.

Velocity

See which failure modes are being resolved fastest and which are stalling:

text
get_velocity({ project: "my-project", days: 30 })

Agent Reliability

Not all agents are equally reliable. Track false-positive rates and resolution rates per agent:

text
get_agent_reliability({ project: "my-project" })

Low-reliability agents are candidates for recursive improvement — their ADL definitions need refinement.

Coverage Matrix

Identify blind spots in your agent ecosystem:

text
get_agent_matrix({ project: "my-project" })

This shows which failure domains have no agent coverage (blind spots), which have only one agent (single points of failure), and which have 3+ agents detecting the same mode (overlap).

Note

SDK alternative:

typescript
const summary = await client.projects.getSummary({ project: 'my-project' });
const burndown = await client.analytics.getBurndown({ project: 'my-project', days: 30 });
const reliability = await client.analytics.getAgentReliability({ project: 'my-project' });
const matrix = await client.analytics.getAgentMatrix({ project: 'my-project' });

Automatic Resolution Detection

The /commit-push workflow in Claude Code automatically checks for resolved issues before committing:

  1. Queries open issues for the current project
  2. Matches modified files against issue file_path values
  3. Prompts you to mark matching issues as completed
  4. Updates the tracker with the commit SHA as the resolution reason

This closes the loop between fixing code and updating the tracker without manual bookkeeping.

Next Steps