The canonical PR review/merge workflow already lives in
skills/llm-project-workflow/workflows/review-merge-pr.md and is exposed
through mcp_list_project_skills / mcp_get_skill_guide (#333-#335), and
its final-report schema already demands a workflow version. What was
missing is enforcement: add compute_workflow_hash (short sha256
version hash of workflow text) and assess_review_workflow_source to
review_proofs. Review reports must cite the canonical workflow file
and carry a populated Workflow version field; when the current
canonical hash is supplied, a mismatched citation fails as a stale
workflow copy, directing the agent to reload via mcp_get_skill_guide.
Fails closed. Tests cover hash determinism and content sensitivity,
matching-hash pass, missing citation, missing version field, stale
hash, version none, and offline validation without a canonical hash.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
gitea_lock_issue is profile-gated via task_capability_map
(gitea.issue.comment); without GITEA_ALLOWED_OPERATIONS the call
fail-closes before the artifact-warning logic runs, so the test
asserted success on a permission block. Seed the environment in
setUp/tearDown exactly like tests/test_mcp_server.py::TestIssueLocking
and complete the mocked git state with base_equivalent,
inspected_git_root, and base_branch so the newer lock-worktree
base-equivalence gate passes. The test still verifies the artifact
warning fires for '?? _emit_payload.py'. Full suite now passes with
zero failures.
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]>