Already-landed open PRs block the review queue: the already-landed gate
correctly stops approval/merge, but no task path could close the
redundant PR. Add the reconciler close path:
- task_capability_map: new reconcile_close_landed_pr (gitea.pr.close)
and reconcile_close_landed_issue (gitea.issue.close) tasks under a
dedicated "reconciler" role. Exact close capabilities only — the
role grants no review, approve, request-changes, or merge authority,
and normal reviewer profiles keep no broad PR-close authority.
- role_session_router: reconciler tasks route wrong_role_stop in
author/reviewer sessions with a dedicated recovery message; matching
reconciler sessions route allowed_current_session.
- review_proofs.assess_reconciler_close_gate: PR close allowed only
when every proof passes — PR live-verified open, candidate head SHA
pinned and matching the live head, target branch freshly fetched
with a full SHA, head an ancestor of the target, exact
gitea.pr.close proven. Non-landed PRs return
NOT_LANDED_CLOSE_BLOCKED; missing close capability returns
RECOVERY_HANDOFF_REQUIRED; incomplete proof fails closed as
GATE_NOT_PROVEN. Linked-issue close is skipped when the issue is
already closed and allowed only for an open issue resolved by the
landed commits with exact gitea.issue.close capability. The gate
also returns the required final-report field list.
17 new tests cover the capability map, wrong-role routing, and every
gate path (landed close, non-landed block, stale target, changed head,
missing capabilities, linked-issue variants, review-mutation denial).
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Approving a PR whose full test suite fails is now gated behind complete
baseline proof. New assess_full_suite_failure_approval_gate:
- Full-suite pass: approval allowed, no baseline required.
- Full-suite failure: default action is REQUEST_CHANGES; approval is
blocked unless the #325 baseline validation proof passes (branches/
worktree, pinned baseline/PR SHAs, matching failure signatures,
clean before/after) and the proof also carries the PR and baseline
full-suite commands, evidence that new/changed tests passed, and a
non-empty explanation of why the failures are unrelated to the PR.
- Unknown/unproven full-suite result blocks approval.
- Main-checkout baseline comparison is rejected.
- Vague "same as master" claims without proof are rejected via the
existing pre-existing-failure claim detection.
- Non-approve decisions are never blocked; the gate only reports the
request-changes default.
Tests cover matching baseline failures, mismatched signatures,
incomplete proof (missing commands, new-test evidence, explanation),
main-checkout baseline, unknown suite result, vague claims, and
full-suite pass.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Add assess_linked_issue_consistency to review_proofs: reviewer final
reports must report a "Linked issue status" that matches the issue(s)
the selected PR was live-verified to link this session. Without live
proof the field may only say "not verified in this session"; with
proof, every linked issue must be named, and any other "Issue #N"
mention anywhere in the report fails as stale leakage from a previous
PR (the PR #280 / Issue #260-vs-#275 incident). Missing field fails
closed. Tests cover correct linked issue, stale previous issue in both
the status field and diagnostics, missing proof, unverified wording,
multiple linked issues, and PR-number mentions not being mistaken for
issue mentions.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Merge prgs/master into feat/issue-330-proof-wording-enforcement and keep
both assess_proof_wording (#330) and git ref mutation reporting (#297).
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Add assess_prior_blocker_skip_proof to validate reviewer reports document
live REQUEST_CHANGES blocker proof for skipped earlier open PRs, reject
stale-memory skips when head changed after blocker, and require
BLOCKER_STATUS_UNVERIFIED when review feedback cannot be fetched.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Reviewer controller handoffs must now report the precise mutation
categories (File edits by reviewer, Worktree/index mutations, Git ref
mutations, MCP/Gitea mutations, Review mutations, Merge mutations,
Cleanup mutations, External-state mutations, Read-only diagnostics)
instead of the ambiguous legacy "Workspace mutations" field.
- assess_controller_handoff(role="review") no longer requires
"Workspace mutations" and fails closed when any legacy
"Workspace mutations:" line is present, regardless of value.
- New HANDOFF_REVIEW_MUTATION_FIELDS makes the nine precise categories
required fields for review-role handoffs, matching the canonical
schemas/review-merge-final-report.md field set.
- Tests cover approval, request-changes, merge, worktree cleanup,
fetch-only, and blocked handoffs, plus rejection of
"Workspace mutations: none" and non-none values.
- Author/create-issue/inventory roles keep their existing contracts.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Add assess_workspace_mutation_consistency to review_proofs: final
reports fail validation when they claim "Workspace mutations: none"
while worktree mutations (reset --hard, checkout, clean, worktree
add/remove, stash, merge, rebase, ...) occurred — either observed in
the workflow command log or self-reported in the report's own
"Worktree mutations" field. Observed worktree and git ref mutations
must be reported under their precise category fields; reports pass
when they say "File edits by reviewer: none" alongside a non-none
"Worktree mutations" entry. Tests cover reset, checkout, worktree add,
clean, fetch-only, and no-op cases.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Add assess_non_mergeable_skip_proof to validate reviewer reports document
head SHA, mergeability result, conflict proof command, conflicting files,
and head-change status for each skipped non-mergeable PR, or classify
MERGEABILITY_UNVERIFIED when proof cannot be retrieved.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Add assess_reviewer_baseline_validation_proof to block test-suite runs in
the main checkout and require complete baseline worktree proof when reports
claim pre-existing master failures.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Add assess_queue_status_report and assess_proof_wording to reject
contradictory queue-status-only reports: passed gates without a selected
PR, prior diagnostic conflict proof, pagination assumptions, and
blocker contradictions. Wire into build_final_report and document the
queue-status-only schema path.
Closes#339
Add assess_proof_wording to reject unsupported phrases such as
inventory complete, live proof, same as master, and file edits none
unless matching evidence is present. Wire into build_final_report and
add doc-contract tests.
Closes#330
Resolve task_capability_map.py conflict by keeping all three capability
entries: commit_files and gitea_commit_files (gitea.repo.commit, #262,
from master) and reconcile_merged_cleanups (gitea.read, #269, this
branch). Capability boundaries unchanged — reconciliation reporting stays
read-only; no close/merge capability broadened.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
route_task_session now calls assess_infra_stop() live instead of
check_mid_merge(). Update TestMCPHealth.test_route_task_session_blocks_during_merge
to mock the infra-stop assessment path and assert infra_stop_assessment
is returned when blocked.
Part of #285 / PR #286 review fix.
Extends the single-terminal-decision machinery (#211) to session-level
hard-stop semantics:
- terminal_review_hard_stop_reasons: after a live terminal verdict, only
the merge sequence for the same approved PR may continue; REQUEST_CHANGES
stops the run; operator-approved corrections re-open the review path
only, never a cross-PR merge.
- gitea_merge_pr: new Gate 2b consults the hard-stop before any API call,
so a run can never verdict one PR and merge another.
- gitea_mark_final_review_decision: hard-stop check with explicit stop
guidance naming the consumed terminal mutation; plus duplicate
REQUEST_CHANGES suppression — an unresolved request-changes at the
current head SHA refuses a second request-changes (fail closed when
feedback cannot be verified).
- tests/test_terminal_review_hard_stop.py: 13 tests covering the
acceptance criteria; existing TestSubmitPrReview setups stub the new
feedback fetch.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>