Hand off findings
A review workflow’s real output is its consensus: a ranked, cross-checked list of findings. nax parses that consensus into a structured findings.json artifact and can route selected findings to where work happens: GitHub issues, one advisory pull request review, or beads.
Declare where findings come from
A workflow opts in with a top-level findings key naming the step whose result holds the consensus, and the adapter that understands its shape:
id: review
findings:
step: synthesize
adapter: review-consensus
steps:
# ...- The bundled
reviewworkflow declares this already. stepmust be an agent step (not a human-review gate), andadaptermust be a registered adapter.nax lintreportsinvalid_findings_sourceotherwise.- There is no guessing: a workflow without
findingsproduces no findings. - Available adapters:
review-consensus(the## 2. Structured ConsensusJSON from the review synthesize prompt).
findings.json
When a run reaches a terminal state (completed, completed with failures, or failed with results), nax writes .nax/workflows/<run-id>/artifacts/findings.json. It is derived purely from the saved run, so older runs get the same data computed on demand; reads never write.
{
"schemaVersion": 1,
"runId": "2026-09-25T16-02-11-000Z-review",
"flowId": "review",
"adapter": "review-consensus",
"source": { "stepId": "synthesize", "instanceId": "codex:auto:auto" },
"target": { "branch": "fix/auth", "sha": "abc123…", "pullRequest": { "number": 123 } },
"findings": [
{
"key": "2026-09-25T16-02-11-000Z-review/synthesize/S1",
"localId": "S1",
"rank": 1,
"bucket": "consensus",
"title": "Token refresh races with logout",
"severity": "high",
"status": "open",
"file": "src/auth/session.ts",
"line": 88,
"claim": "…",
"suggestedFix": "…",
"agents": ["claude", "gemini"]
}
],
"diagnostics": []
}rankfollows the consensus order; contested and merge-dependent items have their ownbucketand no rank.severityis one ofcritical,high,medium,low,info(P0–P3map to the first four; unknown values becomeinfowithseverityRaw).agentslists which agents’ findings the consensus item merges.- Agent output that deviates from the schema becomes a
diagnosticsentry naming the step and instance; it never fails the run. keyis stable per run, step and finding, and is what every handoff target uses to avoid duplicates.
Print findings
nax handoff --findings # latest run that has findings
nax handoff <run-id> --findings
nax handoff --findings --json # the findings.json artifactSend findings to a target
nax handoff --to github-issues # interactive picker
nax handoff --to github-issues --limit 5 --force # top five, no prompts
nax handoff --to github-issues --select S1,S3 --dry # preview only
nax handoff --to pr-review --force
nax handoff --to beads --min-severity high --limit 10 --forceSelecting findings:
- In a terminal without
--selector--limit, a picker preselects the top five ranked consensus findings. --select S1,S3picks exact ids;--limit Ntakes the top N ranked candidates.- Candidates are consensus findings at or above
--min-severity(defaultlow), excludingrejectedanddroppedones. Add--include-contestedor--include-rejectedto widen. - Without a terminal,
--selector--limitis required, and applying requires--force.--dryalways previews without creating anything. --jsonprints{ target, planned, applied, skipped }.
Every target plans first and is idempotent: rerunning the same command after a success creates nothing new and reports what was skipped.
GitHub issues
- One issue per finding, titled with the finding title, labeled
nax-findingandseverity:<level>plus any--labelvalues. Missing labels are created; if a label cannot be created, the issue is created without it and a warning is printed. - The body links the file at the run’s commit and ends with a hidden
<!-- nax-finding:<key> -->marker. - Before creating,
naxscans up to 1000nax-findingissues for markers. Removing thenax-findinglabel from an issue defeats this check. - Issues are created one at a time; a failure stops the batch and reports what was created, and a rerun finishes the rest.
--repo owner/nametargets another repository (default: the currentghrepository).
PR review
- Posts one review with event
COMMENT, neverREQUEST_CHANGES: nax stays advisory. - The pull request comes from the run (when started with
--branch '#123'), then--pr <number>, then the open PR for the run’s branch. - Findings become inline comments only on lines that are in the PR diff; everything else is listed under “Outside this diff”.
- If the PR head moved since the run, the review is pinned to the run’s commit when that commit is in the PR history, otherwise it is posted as a summary without inline comments.
- A hidden
<!-- nax-review:<run-id> -->marker refuses posting the same run twice;--forceposts another review (it never edits the old one).
Beads
- Requires
bron yourPATHand a.beadsworkspace in the project; otherwise the command stops with guidance. - One bead per finding:
bugfor defects, otherwisetask; priority from severity (critical0 …info4); labelsnax-findingandseverity:<level>. - Each bead carries external ref
nax:<key>; existing refs are skipped.
From the dashboard and MCP
- The dashboard’s run details show a collapsible Findings table with a copy button per finding.
- MCP
run_getincludes a findings summary (count, severity histogram, top ten) in thedetailsview, andview: "findings"returns the full artifact. The resourcenax://scopes/{scope_id}/runs/{run_id}/findingsexposes the same data. MCP has no mutation tools for handoff targets.