Context
The claim ledger's soft-claim/duplicate-winner election (src/miner/soft-claim.ts) establishes intent at claim time, but the create/iterate loop that follows can run long — especially once it involves multiple candidate attempts per worktree — and nothing re-checks the target repo's live state immediately before the miner actually writes anything. The Miner-Local Governor is the mandatory fail-closed chokepoint every write passes through (packages/gittensory-engine/src/governor, governor-ledger.ts), and open_pr is the specific local-write action that creates external, irreversible state (src/mcp/local-write-tools.ts, under the LOCAL_WRITE_BOUNDARY spec-builder-not-actuator contract). A claim made at the start of a long loop can go stale: the issue may have been closed, fixed by another contributor or miner, or reassigned in the interim, and the miner would still submit a now-duplicate or now-irrelevant PR purely because its claim-time check was correct at the time.
Goal
Add a final freshness check against the target repo's live state immediately before the open_pr local-write action fires, as a complement to the existing claim-time check, not a replacement for it.
Requirements
- Insert the freshness check between candidate selection and the open_pr spec construction in src/mcp/local-write-tools.ts's call path, so it runs once per submission attempt, not once per claimed issue.
- Check at minimum: issue state (open/closed), whether the issue already has a merged or open PR referencing it from another author, and whether the claim ledger entry is still the miner's own live claim (not superseded or expired).
- On any staleness signal, abort the open_pr action before the Governor chokepoint is invoked for it — a stale submission should never reach the Governor as a live write attempt.
- Route the abort through the existing graceful silent disengagement behavior (no PR, no noisy failure surfaced to the target repo) rather than a new error path.
- Log the abort reason (closed / already-fixed / claim-superseded) to the miner's own event ledger for later fleet-level analysis, distinct from a rejection outcome.
- Keep this check read-only against the target repo — it must not itself count as or trigger a write.
Deliverables
Expected outcomes
- Elimination of duplicate/stale-submission PRs caused by long-running create/iterate loops, measured against current duplicate-submission incident count
- No additional Governor-chokepoint invocations for attempts that are aborted pre-open_pr
Context
The claim ledger's soft-claim/duplicate-winner election (src/miner/soft-claim.ts) establishes intent at claim time, but the create/iterate loop that follows can run long — especially once it involves multiple candidate attempts per worktree — and nothing re-checks the target repo's live state immediately before the miner actually writes anything. The Miner-Local Governor is the mandatory fail-closed chokepoint every write passes through (packages/gittensory-engine/src/governor, governor-ledger.ts), and open_pr is the specific local-write action that creates external, irreversible state (src/mcp/local-write-tools.ts, under the LOCAL_WRITE_BOUNDARY spec-builder-not-actuator contract). A claim made at the start of a long loop can go stale: the issue may have been closed, fixed by another contributor or miner, or reassigned in the interim, and the miner would still submit a now-duplicate or now-irrelevant PR purely because its claim-time check was correct at the time.
Goal
Add a final freshness check against the target repo's live state immediately before the open_pr local-write action fires, as a complement to the existing claim-time check, not a replacement for it.
Requirements
Deliverables
Expected outcomes