Already-landed PR reconciliation could prove a PR should be closed but
stop silently when gitea.pr.close was unavailable, even with comment
capability present. Adopt Option B (comment-then-stop) as the durable
policy and enforce it:
- resolve_partial_reconciliation_plan maps proven capabilities to one
of four outcomes: FULL_RECONCILE_CLOSE_ALLOWED (close_pr proven),
PARTIAL_RECONCILE_COMMENT_THEN_STOP (comment_pr proven, close_pr
missing; one reconciliation comment with PR head SHA, target branch
SHA, ancestor proof, linked issue status, and the missing capability,
then stop), RECOVERY_HANDOFF_ONLY (no comment capability; no Gitea
mutation), and GATE_NOT_PROVEN (no ancestry proof; no mutation
regardless of capability). Missing capability dicts fail closed.
- assess_partial_reconciliation_report requires final reports to
explain why the comment was or was not posted, name the missing
capability, and state the close result or that no mutation ran.
- workflows/reconcile-landed-pr.md gains section 12A documenting the
policy; the workflow contract test locks the new markers.
Tests cover close capability present, close missing with comment
allowed, comment capability missing, all capabilities missing,
unproven ancestry, fail-closed capability dict, and report checks for
each outcome.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Add assess_reconciliation_handoff to review_proofs: already-landed PR
reconciliation runs must emit a dedicated handoff schema (selected PR,
live state, candidate head SHA, target branch + SHA, ancestor proof,
linked issue + live status, eligibility class
ALREADY_LANDED_RECONCILE_REQUIRED, capability proofs, per-category
mutation ledger, blocker, safe next action, no-review/merge
confirmation) instead of author or reviewer fields. Stale fields (PR
number opened, Pinned reviewed head, Scratch worktree used, Workspace
mutations, Issue lock proof, Claim/comment status) fail validation, a
wrong eligibility class fails, and an observed git fetch/pull must be
reported under Git ref mutations rather than claimed none. Fails
closed on a missing Controller Handoff section. Tests cover blocked
reconciliation, successful PR close, comment-only, no-op
already-closed, missing linked-issue proof, wrong eligibility class,
each stale field, and unreported observed fetch.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Add assess_reconcile_linked_issue_report verifier to block open/closed/resolved
linked issue status claims without gitea_view_issue proof in the current session,
require not-verified wording when the issue is missing, and gate recommended
issue close/reopen/comment actions on exact capability proof. Wire into
build_final_report and export from review_proofs.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Structured claim/progress heartbeats post on issue claim and via
gitea_post_heartbeat. Read-only gitea_reconcile_issue_claims inventories
active, stale, phantom, and PR-backed claims; gitea_cleanup_stale_claims
supports dry-run cleanup of reclaimable labels.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Add assess_inventory_worktree_report verifier to reject partial PR inventory
claims, exactly-full first pages without finality proof, legacy scratch-worktree
flags that contradict branches/ review worktrees, and contradictory checkout
wording. Wire into build_final_report and export from review_proofs.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Add assess_already_landed_report_wording to review_proofs: when the
already-landed gate fires, final reports and controller handoffs must
use the reconciliation wording (Oldest open PR requiring action,
Eligibility class: ALREADY_LANDED_RECONCILE_REQUIRED, Candidate head
SHA, Reviewed head SHA: none, Review worktree used: false) and must not
use the legacy fields (oldest/next eligible PR, Pinned reviewed head,
Scratch worktree used) or claim a reviewed head SHA. In
non-already-landed reports, a populated Pinned reviewed head or
Reviewed head SHA fails unless validation and diff review actually
passed this session. Fails closed. Tests cover the correct
reconciliation wording, each forbidden legacy field, missing required
fields, populated reviewed SHA, normal reviewed reports, blocked-infra
reports, and validation-failed reports.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
A reviewer workflow approved and attempted to merge PR #278 although its
head commit was already an ancestor of master, ending in a Gitea 405 and
manual reconciliation. Add the missing pre-mutation gate:
- assess_already_landed_review_gate classifies the pinned candidate
head against the fetched target branch: NORMAL_REVIEW_CANDIDATE,
ALREADY_LANDED_RECONCILE_REQUIRED, or GATE_NOT_PROVEN (fail closed).
Already-landed PRs block approval and the merge API, allow
request-changes only for a real blocker, and require a reconciliation
handoff (PR number/title, candidate head SHA, target branch + SHA,
ancestor proof, linked issue status, recommended action, capability
proof for close/comment mutations). Unchecked ancestry, invalid or
missing SHAs, and a head changed since pinning all fail closed.
Mergeability stays a separate gate.
- assess_already_landed_report_state rejects APPROVED / MERGED /
READY_TO_MERGE wording and missing ALREADY_LANDED_RECONCILE_REQUIRED
state when the session's gate fired, complementing the text-marker
rules from #327 which need the report to admit the landed state.
Tests cover already-landed, normal, non-mergeable, changed-head,
unchecked-ancestry, and invalid-SHA gate paths plus all report-state
verdicts.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>