Skip to content

feat(code-review): synchronous GitHub-mode verifier dispatch + loud missing-verifier signal (FEA-3154) - #180

Merged
peterulsteen merged 3 commits into
mainfrom
fix/code-review-verifier-github-sync
Jul 16, 2026
Merged

feat(code-review): synchronous GitHub-mode verifier dispatch + loud missing-verifier signal (FEA-3154)#180
peterulsteen merged 3 commits into
mainfrom
fix/code-review-verifier-github-sync

Conversation

@peterulsteen

Copy link
Copy Markdown
Contributor

Summary

Applies the merged v3.6.0 reviewer-fleet hardening (#179 / FEA-3085) to the verifier fleet (stage_23_verify_findings). Bumps code-review 3.6.0 → 3.7.0. Implements PLN-1334 (approved).

stage_23 (skill code-review:verify-findings) spawned every verifier with run_in_background: true + blocking TaskOutput in both modes — the exact pattern v3.6.0 proved unsafe under headless claude -p, where the orchestrator can end its turn before issuing the blocking collection, so the process exits (terminal_reason: "completed") and verifier verdicts never land. This is worse for verifiers than reviewers: stage_23 is on_failure: continue, so a missing output degrades silently to pending_verification[], which _compute_canonical_verdict does not read — a BLOCKING finding whose verifier died could ship APPROVED.

Changes:

  • skills/verify-findings/SKILL.md — MODE branch: github mode dispatches verifiers synchronously one-at-a-time (run_in_background: false, wait for each Task response before the next), local mode keeps parallel background + blocking TaskOutput; adds a headless-mode warning. Synchronous dispatch keeps the headless turn alive by construction (each Task is itself the pending call).
  • commands/start.md — stage_23 stage-note sync clause + a Verifier Fleet walker guard mirroring the stage_20 guard (bans watcher files / sleep loops / polling loops / turn-ending waits).
  • cmd_verify_consolidate — defense-in-depth: in github mode, when ≥1 BLOCKING/HIGH finding has no verifier output, emit one aggregate coverage:verifier-missing-output coverage-gap finding (severity: HIGH, required: false) → _compute_canonical_verdict escalates to NEEDS_ATTENTION (mirrors the existing "verifier uncertain → human triages, not silent approval" semantics). New _make_unverified_findings_gap helper; new optional --mode on verify-consolidate, wired at stage_24a_verify_consolidate (same {mode} token finalize-result already uses). Gap id continues past any pre-existing coverage_gaps.json entries (no collision with stage_20b's coverage-verifier_f*).
  • TestsTestFEA3154VerifierDispatchContracts prose-contract class (mirrors FEA-2162) + behavioral cmd_verify_consolidate/cmd_finalize_result cases (github HIGH emits gap + end-to-end finalize asserts validation_errors == [] and NEEDS_ATTENTION; local/MEDIUM/deferred-budget negatives; count aggregation; index continuation). Regenerated the 3 declarative-config snapshots (only the --mode addition).

Net-new github-synchronous verifier behavior — not a revert (pre-v3.5.0 verifiers were background in both modes).

Reviewed pre-PR by an adversarial Codex deep review (multi-worker: verdict/schema/prose/id-index lanes) and a /code-review --depth deep pass — both APPROVED with no BLOCKING/HIGH/MEDIUM findings. Their two test-depth suggestions (count aggregation, index continuation) are included.

CHANGELOG note: the v3.7.0 entry was hand-reconciled to the /update-documentation generator's format (version heading matches plugin.json, newest-first, single root CHANGELOG.md) because this branch was authored from a headless session that can't invoke the plugin slash command — same approach accepted on #179. Happy to regenerate via /update-documentation before merge if preferred.

Feature Flags

N/A — plugin behavior change, no runtime flag. --mode on verify-consolidate is optional and back-compatible (omitted → mode=None → no signal, prior behavior).

Breaking changes

None. Omitting --mode preserves prior behavior. Trade-offs: github verifier stage wall-clock becomes sum-of-verifiers (was slowest-of, but that path was unreliable); a missing github verifier for a BLOCKING/HIGH finding now escalates the verdict to NEEDS_ATTENTION instead of a possible silent APPROVED.

Test plan

  • uv run --frozen --group dev pytest plugins/code-review/tools/python/test_code_review_helpers.py1177 passed
  • uv run ruff check . → clean
  • uv run pyright → 0 errors, 0 warnings
  • Regenerated config snapshots verified diff = only the --mode addition
  • Codex deep review + /code-review --depth deep subagent → both APPROVED

🤖 Generated with Claude Code

peterulsteen and others added 2 commits July 15, 2026 11:50
…issing-verifier signal (FEA-3154)

Applies the v3.6.0 reviewer hardening to the stage_23 verifier fleet.
Bumps code-review 3.6.0 -> 3.7.0.

stage_23 (skill code-review:verify-findings) spawned every verifier with
run_in_background: true + blocking TaskOutput in BOTH modes — the pattern
v3.6.0 proved unsafe under headless claude -p (the turn can end before the
blocking collection is issued, so the process exits and verdicts never
land). Worse for verifiers: stage_23 is on_failure: continue, so a missing
output degrades SILENTLY to pending_verification[], which
_compute_canonical_verdict does not read — a BLOCKING finding whose
verifier died could ship APPROVED.

- verify-findings/SKILL.md: MODE branch — github synchronous one-at-a-time,
  local parallel background + blocking TaskOutput; headless warning.
- commands/start.md: stage_23 note + Verifier Fleet walker guard mirroring
  stage_20 (ban watcher/sleep/polling/turn-end substitutes).
- cmd_verify_consolidate: in github mode, emit ONE aggregate
  coverage:verifier-missing-output gap (HIGH, required: false ->
  NEEDS_ATTENTION) when a BLOCKING/HIGH finding has no verifier output.
  New optional --mode on verify-consolidate, wired at stage_24a.
- Tests: TestFEA3154VerifierDispatchContracts prose-contract class +
  behavioral cmd_verify_consolidate/cmd_finalize_result cases; regenerated
  the 3 declarative-config snapshots (only the --mode addition).

Full code-review suite green (1175 passed), ruff + pyright clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ier-github-sync

# Conflicts:
#	CHANGELOG.md
#	plugins/code-review/.claude-plugin/plugin.json

@mikeangstadt mikeangstadt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solid. The synchronous-primary + coverage-gap-defense split is the right shape, and I traced the loud path end to end: gap lands in coverage_gaps.json, finalize reads it, Rule 3 escalates the HIGH gap to NEEDS_ATTENTION so a dead-verifier BLOCKING/HIGH can't ship APPROVED. Contracts are all in sync (skill, start.md, cli.json, stages.json wired at stage_24a, snapshots, version bump). One tiny doc nit inline, not blocking.

Comment thread plugins/code-review/tools/python/code_review_helpers.py
…producer (FEA-3154 review)

Address review: _append_to_coverage_gaps docstring listed only
arbitrate-budget and derive-spawn-spec; verify-consolidate (stage_24a)
is now a third writer. Doc-only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@peterulsteen
peterulsteen merged commit 5c6b6ab into main Jul 16, 2026
5 checks passed
@peterulsteen
peterulsteen deleted the fix/code-review-verifier-github-sync branch July 16, 2026 15:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants