Add anti-stomp preflight gate before every mutation tool #604

Open
opened 2026-07-09 16:06:52 -05:00 by jcwalker3 · 6 comments
Owner

Context

Part of the LLM coordination failure series (sessions stepping on each other). This is a focused implementation issue, not an umbrella.

Related siblings: #600 (allocator), #601 (leases), #602 (terminal lock early check), #603 (lifecycle labels).

Problem

Even with leases, mutation tools need a shared preflight that prevents stale sessions, wrong worktrees, wrong repos, old prompts, terminal locks, foreign leases, contaminated approvals, and root-checkout mutations from slipping through.

Required behavior

Before create issue/comment, acquire lease, submit review, approve, request changes, merge, cleanup, or label mutation, run a common anti-stomp preflight:

  • repo/org verification
  • profile/role verification
  • root checkout clean and not used for mutation
  • worktree under branches when required
  • active lease ownership
  • terminal lock status
  • expected head SHA
  • stale runtime status
  • workflow hash
  • source contamination status
  • no manual state/mtime/source-file bypass

Acceptance criteria

  1. All mutation tools call the common preflight.
  2. Failure returns a typed blocker and exact next action.
  3. Tests cover wrong repo defaulting to Timesheet, stale runtime, wrong worktree, foreign lease, terminal lock, and contaminated approval.
  4. No mutation can proceed using stale prompt data if live state disagrees.
  5. Existing successful paths continue to work.

Implementation notes

  • Centralize in one module/function invoked from MCP mutation entrypoints.
  • Keep fail-closed semantics; do not add bypass flags for agents.
  • Preserve existing successful author/reviewer/merger happy paths.
## Context Part of the LLM coordination failure series (sessions stepping on each other). This is a focused implementation issue, not an umbrella. Related siblings: #600 (allocator), #601 (leases), #602 (terminal lock early check), #603 (lifecycle labels). ## Problem Even with leases, mutation tools need a shared preflight that prevents stale sessions, wrong worktrees, wrong repos, old prompts, terminal locks, foreign leases, contaminated approvals, and root-checkout mutations from slipping through. ## Required behavior Before create issue/comment, acquire lease, submit review, approve, request changes, merge, cleanup, or label mutation, run a common anti-stomp preflight: * repo/org verification * profile/role verification * root checkout clean and not used for mutation * worktree under branches when required * active lease ownership * terminal lock status * expected head SHA * stale runtime status * workflow hash * source contamination status * no manual state/mtime/source-file bypass ## Acceptance criteria 1. All mutation tools call the common preflight. 2. Failure returns a typed blocker and exact next action. 3. Tests cover wrong repo defaulting to Timesheet, stale runtime, wrong worktree, foreign lease, terminal lock, and contaminated approval. 4. No mutation can proceed using stale prompt data if live state disagrees. 5. Existing successful paths continue to work. ## Implementation notes * Centralize in one module/function invoked from MCP mutation entrypoints. * Keep fail-closed semantics; do not add bypass flags for agents. * Preserve existing successful author/reviewer/merger happy paths.
Author
Owner

Canonical Issue State

STATE: ready for independent implementation
WHO_IS_NEXT: author
NEXT_ACTION: claim this issue and add a shared anti-stomp preflight before every mutation tool
NEXT_PROMPT:

Implement #604 on Scaled-Tech-Consulting/Gitea-Tools: common anti-stomp preflight for all mutation tools covering repo/role/worktree/lease/terminal-lock/head-SHA/stale-runtime/contamination checks. Return typed blocker + next action. Keep existing happy paths green.

WHAT_HAPPENED: Filed as focused coordination issue #604. Series siblings: #600 allocator, #601 leases, #602 terminal-lock early check, #603 lifecycle labels, #605 dashboard.
WHY: Mutation tools still allow stale/wrong-worktree/foreign-lease/terminal-lock failures to slip through without a shared gate.
RELATED_PRS: none yet
BLOCKERS: none
VALIDATION: issue created with type:guardrail status:ready and labels workflow-hardening,anti-stomp,preflight,safety
LAST_UPDATED_BY: jcwalker3 (prgs-author)

## Canonical Issue State STATE: ready for independent implementation WHO_IS_NEXT: author NEXT_ACTION: claim this issue and add a shared anti-stomp preflight before every mutation tool NEXT_PROMPT: ```text Implement #604 on Scaled-Tech-Consulting/Gitea-Tools: common anti-stomp preflight for all mutation tools covering repo/role/worktree/lease/terminal-lock/head-SHA/stale-runtime/contamination checks. Return typed blocker + next action. Keep existing happy paths green. ``` WHAT_HAPPENED: Filed as focused coordination issue #604. Series siblings: #600 allocator, #601 leases, #602 terminal-lock early check, #603 lifecycle labels, #605 dashboard. WHY: Mutation tools still allow stale/wrong-worktree/foreign-lease/terminal-lock failures to slip through without a shared gate. RELATED_PRS: none yet BLOCKERS: none VALIDATION: issue created with type:guardrail status:ready and labels workflow-hardening,anti-stomp,preflight,safety LAST_UPDATED_BY: jcwalker3 (prgs-author)
jcwalker3 added status:in-progress and removed status:ready labels 2026-07-12 04:04:40 -05:00
Author
Owner

Issue claim heartbeat

<!-- gitea-issue-claim-heartbeat:v1 --> **Issue claim heartbeat** - kind: claim - issue: #604 - branch: feat/issue-604-anti-stomp-preflight - phase: claimed - profile: prgs-author - pr: none - blocker: none - next_action: create worktree and begin implementation
jcwalker3 added status:pr-open and removed status:in-progress labels 2026-07-12 04:11:03 -05:00
Author
Owner

Canonical Issue State

STATE: implementation complete — PR open for review
WHO_IS_NEXT: reviewer
NEXT_ACTION: independent review of PR #680 against issue #604 acceptance criteria; do not self-merge
NEXT_PROMPT:

Role: REVIEWER
Repo: prgs / Scaled-Tech-Consulting / Gitea-Tools
Assignment: Review PR #680 (Closes #604) — common anti-stomp preflight for mutation tools.

Verify identity as prgs-reviewer, master parity, workflow skill, and an isolated branches/ worktree. Reconcile live PR #680 state (open, head SHA ea8e186549d4a21e7e3e8f41261ff527b6a60e97, base master). Validate independently:
1. All mutation entry paths call the shared anti-stomp preflight.
2. Failures return typed blocker + exact next action; no agent bypass flags.
3. Regression coverage for wrong-repo Timesheet default, stale runtime, wrong worktree, foreign lease, terminal lock, contaminated approval, and stale head SHA.
4. Happy paths remain green (full suite was 2627 passed / 6 skipped).
5. Scope limited to #604 only (not #606/#607).

Post REQUEST_CHANGES or APPROVE with pinned expected_head_sha. Do not merge unless operator-authorized after approval from a distinct merger identity.

WHAT_HAPPENED: Claimed #604 as prgs-author (jcwalker3). Implemented pure anti_stomp_preflight.py + wired _run_anti_stomp_preflight into verify_preflight_purity and live review/merge paths. Pushed feat/issue-604-anti-stomp-preflight @ ea8e186. Opened PR #680 with Closes #604.
WHY: Mutation tools still allowed stale/wrong-worktree/foreign-lease/terminal-lock/contamination failures without a shared typed gate.
RELATED_PRS: #680
BLOCKERS: none
VALIDATION: pytest tests/test_anti_stomp_preflight.py → 31 passed; full suite → 2627 passed, 6 skipped
LAST_UPDATED_BY: jcwalker3 (prgs-author)

Implementation state

  • Complete for #604 only
  • Commit: ea8e186549d4a21e7e3e8f41261ff527b6a60e97
  • Branch: feat/issue-604-anti-stomp-preflight
  • PR: #680master
  • Worktree: branches/issue-604-anti-stomp-preflight

Remaining risks

  • MCP daemons must reload after merge to enforce the new gate in process memory
  • Live anti-stomp under pytest is opt-in (GITEA_TEST_FORCE_ANTI_STOMP); production paths always enforce for named mutation tasks

Next role

reviewer (not author; no self-review/self-merge)

## Canonical Issue State STATE: implementation complete — PR open for review WHO_IS_NEXT: reviewer NEXT_ACTION: independent review of PR #680 against issue #604 acceptance criteria; do not self-merge NEXT_PROMPT: ```text Role: REVIEWER Repo: prgs / Scaled-Tech-Consulting / Gitea-Tools Assignment: Review PR #680 (Closes #604) — common anti-stomp preflight for mutation tools. Verify identity as prgs-reviewer, master parity, workflow skill, and an isolated branches/ worktree. Reconcile live PR #680 state (open, head SHA ea8e186549d4a21e7e3e8f41261ff527b6a60e97, base master). Validate independently: 1. All mutation entry paths call the shared anti-stomp preflight. 2. Failures return typed blocker + exact next action; no agent bypass flags. 3. Regression coverage for wrong-repo Timesheet default, stale runtime, wrong worktree, foreign lease, terminal lock, contaminated approval, and stale head SHA. 4. Happy paths remain green (full suite was 2627 passed / 6 skipped). 5. Scope limited to #604 only (not #606/#607). Post REQUEST_CHANGES or APPROVE with pinned expected_head_sha. Do not merge unless operator-authorized after approval from a distinct merger identity. ``` WHAT_HAPPENED: Claimed #604 as prgs-author (jcwalker3). Implemented pure `anti_stomp_preflight.py` + wired `_run_anti_stomp_preflight` into `verify_preflight_purity` and live review/merge paths. Pushed `feat/issue-604-anti-stomp-preflight` @ ea8e186. Opened PR #680 with Closes #604. WHY: Mutation tools still allowed stale/wrong-worktree/foreign-lease/terminal-lock/contamination failures without a shared typed gate. RELATED_PRS: #680 BLOCKERS: none VALIDATION: pytest tests/test_anti_stomp_preflight.py → 31 passed; full suite → 2627 passed, 6 skipped LAST_UPDATED_BY: jcwalker3 (prgs-author) ### Implementation state - Complete for #604 only - Commit: `ea8e186549d4a21e7e3e8f41261ff527b6a60e97` - Branch: `feat/issue-604-anti-stomp-preflight` - PR: #680 → `master` - Worktree: `branches/issue-604-anti-stomp-preflight` ### Remaining risks - MCP daemons must reload after merge to enforce the new gate in process memory - Live anti-stomp under pytest is opt-in (`GITEA_TEST_FORCE_ANTI_STOMP`); production paths always enforce for named mutation tasks ### Next role **reviewer** (not author; no self-review/self-merge)
Owner

Canonical Issue State

STATE: changes requested
WHO_IS_NEXT: author
NEXT_ACTION: Fix the critical anti-stomp role regression (reviewer/merger WRONG_ROLE-blocked on issue-comment-class tasks), then address the two coverage/test findings, repin head, and hand back to a distinct reviewer.
NEXT_PROMPT:

Role: AUTHOR
Repo: prgs / Scaled-Tech-Consulting / Gitea-Tools
Fix PR #680 (Closes #604) per reviewer REQUEST_CHANGES at head ea8e186549d4a21e7e3e8f41261ff527b6a60e97.
1. CRITICAL: the anti-stomp role check WRONG_ROLE-blocks reviewer/merger on comment_issue/mark_issue/set_issue_labels/lock_issue (task role "author") even though those profiles hold gitea.issue.comment. Gate on the required permission, not the nominal task role; add a test that a reviewer and a merger pass the preflight for comment_issue.
2. Reconcile anti_stomp_preflight.MUTATION_TASKS with real wiring (wire or de-scope mark_final_review_decision / save_review_draft / resume_review_draft).
3. Replace the set-membership inventory test with a real wiring assertion; add a behavioral test that a mutation entrypoint aborts before its Gitea API call when the assessor blocks.
4. Re-run the full suite; keep 2627 passed / 6 skipped. Repin head and hand back to a distinct reviewer.

WHAT_HAPPENED: Independent review of PR #680 at head ea8e186 posted a REQUEST_CHANGES verdict to Gitea. Diff scope matches #604 (anti_stomp_preflight.py, gitea_mcp_server.py, tests/test_anti_stomp_preflight.py). Focused 31 passed and full suite 2627 passed / 6 skipped, reproduced independently.
WHY: The shared anti-stomp assessor is pure and fail-closed, but a role-check design flaw breaks reviewer/merger issue comments (AC5), the declared mutation set overstates wiring (AC1), and the enforcement path lacks behavioral proof (AC4) because the gate is inert under pytest.
RELATED_PRS: #680 (Closes #604)
BLOCKERS: (1) anti-stomp role check WRONG_ROLE-blocks reviewer/merger on issue-comment-class tasks; (2) MUTATION_TASKS over-declares vs wiring; (3) inadequate wiring/ordering regression proof
VALIDATION: pytest tests/test_anti_stomp_preflight.py -> 31 passed; assessor gate suites -> 93 passed; capability/lease/merge/reconciler/review suites -> 133 passed; full suite -> 2627 passed, 6 skipped; py_compile OK; direct assessor repro of the role regression against PR code
LAST_UPDATED_BY: sysadmin (prgs-reviewer)

[THREAD STATE LEDGER]

What is true now: PR #680 (Closes #604) received an independent REQUEST_CHANGES review at head ea8e186549. The shared anti-stomp assessor is pure and fail-closed; the full suite is 2627 passing with 6 skipped.

What changed: A formal request_changes review verdict was posted to Gitea on PR #680, head-pinned. A supplementary critical-regression note was posted to the PR thread. No merge performed.

What is blocked: Merging PR #680 is held pending author fix.

  • Blocker classification: process/rule blocker
  • Server-side decision state: request_changes review posted to Gitea on PR #680 (head-pinned)
  • Local verdict/state: independent review complete; verdict request_changes
  • Next actor: author (jcwalker3)
  • Required action: fix the anti-stomp role regression plus the coverage/test findings, repin head, hand back to a distinct reviewer
  • Do not do: do not merge PR #680, do not self-review, do not weaken the fail-closed gate to pass tests

Who/what acts next: author addresses the three findings; then a distinct reviewer re-reviews at the new head (no self-review, no self-merge).

## Canonical Issue State STATE: changes requested WHO_IS_NEXT: author NEXT_ACTION: Fix the critical anti-stomp role regression (reviewer/merger WRONG_ROLE-blocked on issue-comment-class tasks), then address the two coverage/test findings, repin head, and hand back to a distinct reviewer. NEXT_PROMPT: ```text Role: AUTHOR Repo: prgs / Scaled-Tech-Consulting / Gitea-Tools Fix PR #680 (Closes #604) per reviewer REQUEST_CHANGES at head ea8e186549d4a21e7e3e8f41261ff527b6a60e97. 1. CRITICAL: the anti-stomp role check WRONG_ROLE-blocks reviewer/merger on comment_issue/mark_issue/set_issue_labels/lock_issue (task role "author") even though those profiles hold gitea.issue.comment. Gate on the required permission, not the nominal task role; add a test that a reviewer and a merger pass the preflight for comment_issue. 2. Reconcile anti_stomp_preflight.MUTATION_TASKS with real wiring (wire or de-scope mark_final_review_decision / save_review_draft / resume_review_draft). 3. Replace the set-membership inventory test with a real wiring assertion; add a behavioral test that a mutation entrypoint aborts before its Gitea API call when the assessor blocks. 4. Re-run the full suite; keep 2627 passed / 6 skipped. Repin head and hand back to a distinct reviewer. ``` WHAT_HAPPENED: Independent review of PR #680 at head ea8e186 posted a REQUEST_CHANGES verdict to Gitea. Diff scope matches #604 (anti_stomp_preflight.py, gitea_mcp_server.py, tests/test_anti_stomp_preflight.py). Focused 31 passed and full suite 2627 passed / 6 skipped, reproduced independently. WHY: The shared anti-stomp assessor is pure and fail-closed, but a role-check design flaw breaks reviewer/merger issue comments (AC5), the declared mutation set overstates wiring (AC1), and the enforcement path lacks behavioral proof (AC4) because the gate is inert under pytest. RELATED_PRS: #680 (Closes #604) BLOCKERS: (1) anti-stomp role check WRONG_ROLE-blocks reviewer/merger on issue-comment-class tasks; (2) MUTATION_TASKS over-declares vs wiring; (3) inadequate wiring/ordering regression proof VALIDATION: pytest tests/test_anti_stomp_preflight.py -> 31 passed; assessor gate suites -> 93 passed; capability/lease/merge/reconciler/review suites -> 133 passed; full suite -> 2627 passed, 6 skipped; py_compile OK; direct assessor repro of the role regression against PR code LAST_UPDATED_BY: sysadmin (prgs-reviewer) [THREAD STATE LEDGER] **What is true now:** PR #680 (Closes #604) received an independent REQUEST_CHANGES review at head ea8e186549d4a21e7e3e8f41261ff527b6a60e97. The shared anti-stomp assessor is pure and fail-closed; the full suite is 2627 passing with 6 skipped. **What changed:** A formal request_changes review verdict was posted to Gitea on PR #680, head-pinned. A supplementary critical-regression note was posted to the PR thread. No merge performed. **What is blocked:** Merging PR #680 is held pending author fix. - Blocker classification: process/rule blocker - Server-side decision state: request_changes review posted to Gitea on PR #680 (head-pinned) - Local verdict/state: independent review complete; verdict request_changes - Next actor: author (jcwalker3) - Required action: fix the anti-stomp role regression plus the coverage/test findings, repin head, hand back to a distinct reviewer - Do not do: do not merge PR #680, do not self-review, do not weaken the fail-closed gate to pass tests **Who/what acts next:** author addresses the three findings; then a distinct reviewer re-reviews at the new head (no self-review, no self-merge).
Author
Owner

Canonical Issue State

STATE: author rework complete — PR #680 ready for independent re-review
WHO_IS_NEXT: reviewer
NEXT_ACTION: independent re-review of PR #680 at head 3fd02a3c633fb539850ce202c68b2043cbf7e4ca
NEXT_PROMPT:

Role: REVIEWER
Repo: prgs / Scaled-Tech-Consulting / Gitea-Tools
Re-review PR #680 (Closes #604) at head 3fd02a3c633fb539850ce202c68b2043cbf7e4ca.
Verify Blocker A (capability-authorized reviewer/merger issue comments), Blocker B (MUTATION_TASKS↔wiring + dedicated-gate classifications), Blocker C (entrypoint side-effect ordering). Full suite was 2639 passed / 6 skipped. No self-merge.

WHAT_HAPPENED: Author fixed REQUEST_CHANGES from review comments 10479/10481. New commit 3fd02a3 on feat/issue-604-anti-stomp-preflight. Worktree: branches/issue-604-anti-stomp-preflight (clean). Control-checkout dirt documented as #681 — not absorbed into #604.
WHY: Shared anti-stomp role check blocked legitimate reviewer/merger issue handoffs; inventory overstated wiring; suite lacked behavioral proof that the gate aborts before side effects.
RELATED_PRS: #680
BLOCKERS: none for #604 rework; unrelated root dirt tracked in #681
VALIDATION: focused anti-stomp 43 passed; related suites 216 passed; full suite 2639 passed / 6 skipped; py_compile OK
LAST_UPDATED_BY: jcwalker3 (prgs-author)

Classification of disputed mutation tasks

  • Shared anti-stomp: edit_pr (non-closing gitea_edit_pr), acquire_reviewer_pr_lease, plus existing wired mutation set.
  • Dedicated gate (excluded from MUTATION_TASKS with rationale): mark_final_review_decision, save_review_draft, resume_review_draft, cleanup_stale_review_decision_lock, lease heartbeat/release helpers.

Next role

reviewer — distinct from author; pin head SHA; no self-merge.

## Canonical Issue State STATE: author rework complete — PR #680 ready for independent re-review WHO_IS_NEXT: reviewer NEXT_ACTION: independent re-review of PR #680 at head `3fd02a3c633fb539850ce202c68b2043cbf7e4ca` NEXT_PROMPT: ```text Role: REVIEWER Repo: prgs / Scaled-Tech-Consulting / Gitea-Tools Re-review PR #680 (Closes #604) at head 3fd02a3c633fb539850ce202c68b2043cbf7e4ca. Verify Blocker A (capability-authorized reviewer/merger issue comments), Blocker B (MUTATION_TASKS↔wiring + dedicated-gate classifications), Blocker C (entrypoint side-effect ordering). Full suite was 2639 passed / 6 skipped. No self-merge. ``` WHAT_HAPPENED: Author fixed REQUEST_CHANGES from review comments 10479/10481. New commit `3fd02a3` on `feat/issue-604-anti-stomp-preflight`. Worktree: `branches/issue-604-anti-stomp-preflight` (clean). Control-checkout dirt documented as #681 — not absorbed into #604. WHY: Shared anti-stomp role check blocked legitimate reviewer/merger issue handoffs; inventory overstated wiring; suite lacked behavioral proof that the gate aborts before side effects. RELATED_PRS: #680 BLOCKERS: none for #604 rework; unrelated root dirt tracked in #681 VALIDATION: focused anti-stomp 43 passed; related suites 216 passed; full suite 2639 passed / 6 skipped; py_compile OK LAST_UPDATED_BY: jcwalker3 (prgs-author) ### Classification of disputed mutation tasks - **Shared anti-stomp:** `edit_pr` (non-closing `gitea_edit_pr`), `acquire_reviewer_pr_lease`, plus existing wired mutation set. - **Dedicated gate (excluded from MUTATION_TASKS with rationale):** `mark_final_review_decision`, `save_review_draft`, `resume_review_draft`, `cleanup_stale_review_decision_lock`, lease heartbeat/release helpers. ### Next role **reviewer** — distinct from author; pin head SHA; no self-merge.
Owner

Canonical Issue State

STATE: approved on PR #680 — awaiting distinct merger
WHO_IS_NEXT: merger
NEXT_ACTION: merge PR #680 at head 3fd02a3c63 with operator confirmation MERGE PR 680
NEXT_PROMPT:

Role: MERGER
Repo: prgs / Scaled-Tech-Consulting / Gitea-Tools
Merge PR #680 (Closes #604) only if live head still 3fd02a3c633fb539850ce202c68b2043cbf7e4ca and approval_at_current_head is true. Reviewer was sysadmin; author jcwalker3. Do not absorb #681 dirt.

WHAT_HAPPENED: After transport-EOF recovery, independent re-review APPROVED PR #680 at 3fd02a3. Prior REQUEST_CHANGES findings A/B/C confirmed fixed. Canonical Gitea feedback: APPROVED at current head.
WHY: Shared anti-stomp preflight ready for merge after review rework.
RELATED_PRS: #680
BLOCKERS: none on implementation; control-plane #584/#672; root #681 unrelated
VALIDATION: 43 focused anti-stomp passed at head; approval_visible + approval_at_current_head on Gitea
LAST_UPDATED_BY: sysadmin (prgs-reviewer)

## Canonical Issue State STATE: approved on PR #680 — awaiting distinct merger WHO_IS_NEXT: merger NEXT_ACTION: merge PR #680 at head 3fd02a3c633fb539850ce202c68b2043cbf7e4ca with operator confirmation MERGE PR 680 NEXT_PROMPT: ```text Role: MERGER Repo: prgs / Scaled-Tech-Consulting / Gitea-Tools Merge PR #680 (Closes #604) only if live head still 3fd02a3c633fb539850ce202c68b2043cbf7e4ca and approval_at_current_head is true. Reviewer was sysadmin; author jcwalker3. Do not absorb #681 dirt. ``` WHAT_HAPPENED: After transport-EOF recovery, independent re-review APPROVED PR #680 at 3fd02a3. Prior REQUEST_CHANGES findings A/B/C confirmed fixed. Canonical Gitea feedback: APPROVED at current head. WHY: Shared anti-stomp preflight ready for merge after review rework. RELATED_PRS: #680 BLOCKERS: none on implementation; control-plane #584/#672; root #681 unrelated VALIDATION: 43 focused anti-stomp passed at head; approval_visible + approval_at_current_head on Gitea LAST_UPDATED_BY: sysadmin (prgs-reviewer)
Sign in to join this conversation.
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Scaled-Tech-Consulting/Gitea-Tools#604