feat(mcp): use a 10-minute sliding TTL for reviewer and merger PR leases (Closes #747) #748

Merged
sysadmin merged 1 commits from feat/issue-747-sliding-lease-ttl into master 2026-07-18 13:16:24 -05:00
Owner

Closes #747.

Head: 277ec5269d
Base: master @ b05075fd25

Problem

Reviewer and merger PR leases minted a fixed 120-minute expiry (#407 AC6/AC7) and derived staleness from two further activity bands — stale at 30 minutes, reclaimable at 60. A session that died (daemon crash, transport flap, client restart) kept a PR blocked for an hour before anyone could reclaim it, and two hours before manual cleanup was sanctioned. #718 records the resulting deadlock: a merge stalled behind a reviewer lease that had stopped being live long before it stopped being authoritative.

The flaw was using a long fixed expiry as a proxy for "the owner is probably still alive" instead of making the owner continuously prove liveness.

What changed

Sliding window. LEASE_TTL_MINUTES = 10 governs acquisition, and every write of the lease marker re-derives expires_at from the moment of the write, so each heartbeat slides the window forward. An actively heartbeating session is never evicted and has no maximum lifetime; a dead one releases its hold within one TTL.

Renewal has a seam. LEASE_RENEWAL_MINUTES is named separately from the acquisition TTL. Previously the heartbeat slid the expiry only as a side effect of re-defaulting the acquisition constant, so the two durations could not be tuned or reasoned about independently. format_lease_body now accepts an explicit ttl_minutes, and the heartbeat passes the renewal window.

Merger parity. Merger acquisition funnels through the same lease-body formatter, so it inherits the identical window by construction rather than through a parallel constant.

Reclaim tier removed. classify_lease_freshness no longer returns reclaimable. Beyond being an extra waiting tier, that band is unreachable under a sliding TTL: a heartbeat stamps last_activity and expires_at together, so a lease idle for a full TTL is necessarily already expired. Expiry becomes the only takeover gate. STALE_WARNING_MINUTES drops to 5 — half the window — so the warning still fires while the owner can heartbeat and recover.

Diagnostics. Adds lease_seconds_remaining; the heartbeat tool now returns ttl_minutes, expires_at, and seconds_remaining, so an operator can distinguish "held and live" from "held and dying". Additive only — no existing key changed.

Duplicate constant removed. pr_work_lease.DEFAULT_REVIEWER_LEASE_TTL_MINUTES had no readers anywhere in the tree and could only drift.

Reviewer notes

Two points deserve scrutiny:

  1. No reclaim path is lost by retiring reclaimable. find_active_reviewer_lease already skips expired markers, so an expired foreign lease never gated acquisition in the first place. The foreign_expired classification carries the NEXT_ACTION_RELEASE_EXPIRED_LEASE next-action that foreign_reclaimable used to carry. The two updated tests in test_reviewer_pr_lease.py are written to demonstrate exactly this: the classification label changes, the sanctioned next action does not.

  2. One now-unreachable branch was deliberately left in place. assess_acquire_lease still has an elif ... freshness == "reclaimable" arm that fails closed. It can no longer fire. I left it rather than widening the diff, since it is fail-closed and harmless; say the word if you would rather it be deleted.

Legacy markers minted under the old 120-minute TTL still parse and are judged against their own recorded expires_at, so nothing is retroactively expired (AC9).

Acceptance criteria

AC Status
AC1 reviewer acquire = now + 10m covered — TestAcquisitionTTL
AC2 merger acquire = now + 10m covered — TestAcquisitionTTL
AC3 heartbeat slides expiry covered — TestHeartbeatSlides
AC4 heartbeat cannot resurrect an expired lease pre-existing behaviour — the heartbeat fails closed when no in-session lease matches the PR, with a structured reason rather than internal_error
AC5 expired is immediately reclaimable, tiers removed covered — TestFreshnessBands, TestExpiredLeaseIsImmediatelyReclaimable
AC6 single named constant per lease kind covered — TestSlidingTTLConstant; duplicate removed
AC7 diagnostics report TTL and remaining time covered — TestRemainingTimeReporting
AC8 regression tests covered — 17 new tests
AC9 legacy rows still evaluate covered — TestLegacyLeaseRows

Verification

Full suite: 3425 passed, 6 skipped, 2 failed, 365 subtests passed.

Both failures — test_issue_702_review_findings_f1_f6::test_removed_worktree_recovers_before_probe and test_reconciler_supersession_close::test_tool_posts_comment_and_closes_superseded_pr_issue — were re-run on a clean master worktree at b05075fd25 and fail identically there. They are pre-existing and untouched by this change.

Lease suites specifically (reviewer, merger acquire/adoption/finalization, obsolete-lease cleanup, post-merge moot, lifecycle, work-lease, queue inventory, plus the new file): 203 passed, 42 subtests passed.

Runner used: /opt/homebrew/bin/python3 -m pytest (Python 3.14, pytest 9.0.3). The runner ambiguity this exposes is tracked separately in #738.

Closes #747. Head: 277ec5269d039899a9d6eb77c5612b9cff9e71a7 Base: master @ b05075fd25ea ## Problem Reviewer and merger PR leases minted a fixed 120-minute expiry (#407 AC6/AC7) and derived staleness from two further activity bands — stale at 30 minutes, reclaimable at 60. A session that died (daemon crash, transport flap, client restart) kept a PR blocked for an hour before anyone could reclaim it, and two hours before manual cleanup was sanctioned. #718 records the resulting deadlock: a merge stalled behind a reviewer lease that had stopped being live long before it stopped being authoritative. The flaw was using a long fixed expiry as a proxy for "the owner is probably still alive" instead of making the owner continuously prove liveness. ## What changed **Sliding window.** `LEASE_TTL_MINUTES = 10` governs acquisition, and every write of the lease marker re-derives `expires_at` from the moment of the write, so each heartbeat slides the window forward. An actively heartbeating session is never evicted and has no maximum lifetime; a dead one releases its hold within one TTL. **Renewal has a seam.** `LEASE_RENEWAL_MINUTES` is named separately from the acquisition TTL. Previously the heartbeat slid the expiry only as a side effect of re-defaulting the acquisition constant, so the two durations could not be tuned or reasoned about independently. `format_lease_body` now accepts an explicit `ttl_minutes`, and the heartbeat passes the renewal window. **Merger parity.** Merger acquisition funnels through the same lease-body formatter, so it inherits the identical window by construction rather than through a parallel constant. **Reclaim tier removed.** `classify_lease_freshness` no longer returns `reclaimable`. Beyond being an extra waiting tier, that band is unreachable under a sliding TTL: a heartbeat stamps `last_activity` and `expires_at` together, so a lease idle for a full TTL is necessarily already expired. Expiry becomes the only takeover gate. `STALE_WARNING_MINUTES` drops to 5 — half the window — so the warning still fires while the owner can heartbeat and recover. **Diagnostics.** Adds `lease_seconds_remaining`; the heartbeat tool now returns `ttl_minutes`, `expires_at`, and `seconds_remaining`, so an operator can distinguish "held and live" from "held and dying". Additive only — no existing key changed. **Duplicate constant removed.** `pr_work_lease.DEFAULT_REVIEWER_LEASE_TTL_MINUTES` had no readers anywhere in the tree and could only drift. ## Reviewer notes Two points deserve scrutiny: 1. **No reclaim path is lost by retiring `reclaimable`.** `find_active_reviewer_lease` already skips expired markers, so an expired foreign lease never gated acquisition in the first place. The `foreign_expired` classification carries the `NEXT_ACTION_RELEASE_EXPIRED_LEASE` next-action that `foreign_reclaimable` used to carry. The two updated tests in `test_reviewer_pr_lease.py` are written to demonstrate exactly this: the classification label changes, the sanctioned next action does not. 2. **One now-unreachable branch was deliberately left in place.** `assess_acquire_lease` still has an `elif ... freshness == "reclaimable"` arm that fails closed. It can no longer fire. I left it rather than widening the diff, since it is fail-closed and harmless; say the word if you would rather it be deleted. Legacy markers minted under the old 120-minute TTL still parse and are judged against their own recorded `expires_at`, so nothing is retroactively expired (AC9). ## Acceptance criteria | AC | Status | |---|---| | AC1 reviewer acquire = now + 10m | covered — `TestAcquisitionTTL` | | AC2 merger acquire = now + 10m | covered — `TestAcquisitionTTL` | | AC3 heartbeat slides expiry | covered — `TestHeartbeatSlides` | | AC4 heartbeat cannot resurrect an expired lease | pre-existing behaviour — the heartbeat fails closed when no in-session lease matches the PR, with a structured reason rather than `internal_error` | | AC5 expired is immediately reclaimable, tiers removed | covered — `TestFreshnessBands`, `TestExpiredLeaseIsImmediatelyReclaimable` | | AC6 single named constant per lease kind | covered — `TestSlidingTTLConstant`; duplicate removed | | AC7 diagnostics report TTL and remaining time | covered — `TestRemainingTimeReporting` | | AC8 regression tests | covered — 17 new tests | | AC9 legacy rows still evaluate | covered — `TestLegacyLeaseRows` | ## Verification Full suite: **3425 passed, 6 skipped, 2 failed**, 365 subtests passed. Both failures — `test_issue_702_review_findings_f1_f6::test_removed_worktree_recovers_before_probe` and `test_reconciler_supersession_close::test_tool_posts_comment_and_closes_superseded_pr_issue` — were re-run on a clean master worktree at b05075fd25ea and fail identically there. They are pre-existing and untouched by this change. Lease suites specifically (reviewer, merger acquire/adoption/finalization, obsolete-lease cleanup, post-merge moot, lifecycle, work-lease, queue inventory, plus the new file): 203 passed, 42 subtests passed. Runner used: `/opt/homebrew/bin/python3 -m pytest` (Python 3.14, pytest 9.0.3). The runner ambiguity this exposes is tracked separately in #738.
jcwalker3 added 1 commit 2026-07-18 12:57:10 -05:00
Reviewer and merger PR leases minted a fixed 120-minute expiry (#407 AC6/AC7)
and derived staleness from two further activity bands: stale at 30 minutes,
reclaimable at 60. A session that died — daemon crash, transport flap, client
restart — therefore kept a PR blocked for an hour before anyone could reclaim
it, and two hours before manual cleanup was sanctioned. #718 records the
resulting deadlock: a merge stalled behind a reviewer lease that had stopped
being live long before it stopped being authoritative.

The flaw was using a long fixed expiry as a proxy for "the owner is probably
still alive" instead of making the owner continuously prove liveness.

Sliding window
--------------
`LEASE_TTL_MINUTES = 10` now governs acquisition, and every write of the lease
marker re-derives `expires_at` from the moment of the write, so each heartbeat
slides the window forward. An actively heartbeating session is never evicted
and has no maximum lifetime; a dead one releases its hold within one TTL.

`LEASE_RENEWAL_MINUTES` is named separately from the acquisition TTL. Renewal
previously had no seam at all: the heartbeat slid the expiry only as a side
effect of re-defaulting the acquisition constant, so the two durations could
not be reasoned about or tuned independently. `format_lease_body` now takes an
explicit `ttl_minutes`, and the heartbeat passes the renewal window rather than
relying on that default.

Merger leases acquire through the same lease-body formatter, so they inherit
the identical window by construction rather than by a parallel constant.

Removal of the reclaim tier
---------------------------
`classify_lease_freshness` no longer returns `reclaimable`. Beyond being an
extra waiting tier, that band is unreachable under a sliding TTL: a heartbeat
stamps `last_activity` and `expires_at` together, so a lease idle for a full
TTL is necessarily already expired. Expiry is now the only takeover gate.

No reclaim path is lost. `find_active_reviewer_lease` already ignores expired
markers, so an expired foreign lease never gated acquisition; and the
`foreign_expired` classification carries the same
`NEXT_ACTION_RELEASE_EXPIRED_LEASE` the retired `foreign_reclaimable` did. The
two updated tests in `test_reviewer_pr_lease.py` assert exactly that: the
classification label changes, the sanctioned next action does not.

`STALE_WARNING_MINUTES` drops to 5 — half the window — so the warning still
fires while the owner can heartbeat and recover.

Diagnostics
-----------
Adds `lease_seconds_remaining`, and the heartbeat tool now returns
`ttl_minutes`, `expires_at`, and `seconds_remaining`, so an operator can
distinguish "held and live" from "held and dying" instead of only seeing that
a lease exists. All additions are additive; no existing key changed.

Also removes `pr_work_lease.DEFAULT_REVIEWER_LEASE_TTL_MINUTES`, a duplicate of
the reviewer TTL with no readers anywhere in the tree, which could only drift.

Legacy markers minted under the old 120-minute TTL still parse and are judged
against their own recorded `expires_at`, so no lease is retroactively expired
by this change.

Full suite: 3425 passed, 6 skipped, 2 failed. Both failures
(`test_issue_702_review_findings_f1_f6`, `test_reconciler_supersession_close`)
reproduce identically on clean master b05075fd25 and are pre-existing.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01QxXHZ7rqXtLgTusngaWgKZ
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #748
issue: #747
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 71946-8e6386fa879b
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-feat-issue-747-sliding-lease-ttl
phase: claimed
candidate_head: 277ec5269d
target_branch: master
target_branch_sha: b05075fd25
last_activity: 2026-07-18T18:08:15Z
expires_at: 2026-07-18T20:08:15Z
blocker: none

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #748 issue: #747 reviewer_identity: sysadmin profile: prgs-reviewer session_id: 71946-8e6386fa879b worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-feat-issue-747-sliding-lease-ttl phase: claimed candidate_head: 277ec5269d039899a9d6eb77c5612b9cff9e71a7 target_branch: master target_branch_sha: b05075fd25ea7f3ac2e86d68f18a1a14c803962e last_activity: 2026-07-18T18:08:15Z expires_at: 2026-07-18T20:08:15Z blocker: none
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #748
issue: #747
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 71946-8e6386fa879b
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-feat-issue-747-sliding-lease-ttl
phase: validating
candidate_head: 277ec5269d
target_branch: master
target_branch_sha: b05075fd25
last_activity: 2026-07-18T18:09:27Z
expires_at: 2026-07-18T20:09:27Z
blocker: none

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #748 issue: #747 reviewer_identity: sysadmin profile: prgs-reviewer session_id: 71946-8e6386fa879b worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-feat-issue-747-sliding-lease-ttl phase: validating candidate_head: 277ec5269d039899a9d6eb77c5612b9cff9e71a7 target_branch: master target_branch_sha: b05075fd25ea7f3ac2e86d68f18a1a14c803962e last_activity: 2026-07-18T18:09:27Z expires_at: 2026-07-18T20:09:27Z blocker: none
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #748
issue: #747
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 71946-8e6386fa879b
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-feat-issue-747-sliding-lease-ttl
phase: submitting_review
candidate_head: 277ec5269d
target_branch: master
target_branch_sha: b05075fd25
last_activity: 2026-07-18T18:10:59Z
expires_at: 2026-07-18T20:10:59Z
blocker: none

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #748 issue: #747 reviewer_identity: sysadmin profile: prgs-reviewer session_id: 71946-8e6386fa879b worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-feat-issue-747-sliding-lease-ttl phase: submitting_review candidate_head: 277ec5269d039899a9d6eb77c5612b9cff9e71a7 target_branch: master target_branch_sha: b05075fd25ea7f3ac2e86d68f18a1a14c803962e last_activity: 2026-07-18T18:10:59Z expires_at: 2026-07-18T20:10:59Z blocker: none
sysadmin approved these changes 2026-07-18 13:12:51 -05:00
sysadmin left a comment
Owner

Canonical PR State

STATE: approved
WHO_IS_NEXT: merger
NEXT_ACTION: separate merger session re-validates head 277ec5269d then merges; do not merge from this reviewer session
NEXT_PROMPT:

Merge PR #748 for issue #747 only if still open at head 277ec5269d039899a9d6eb77c5612b9cff9e71a7 base master@b05075fd25ea7f3ac2e86d68f18a1a14c803962e. Use merger namespace/profile. Do not touch PR #746. Do not implement #749.

WHAT_HAPPENED: Independent reviewer validated full diff, 10-minute sliding TTL policy, reclaimable removal, and full test suite; approving at pinned head.
WHY: Sliding 10-minute TTL is correct; reclaimable tier is proven unreachable for production markers; foreign_expired preserves NEXT_ACTION_RELEASE_EXPIRED_LEASE; issue locks and control-plane DB TTLs unchanged.
ISSUE: #747
HEAD_SHA: 277ec5269d
REVIEW_STATUS: APPROVED by sysadmin via gitea_submit_pr_review at 277ec5269d
MERGE_READY: true after separate merger gates only
BLOCKERS: none
VALIDATION: new TTL suite 17 passed; lease suites 185 passed; full suite 3425 passed / 6 skipped / 2 failed (both fail identically on clean master b05075fd25); git diff --check clean
NATIVE_REVIEW_PROOF: transport=native_mcp; tool=gitea_submit_pr_review; namespace=gitea-reviewer; profile=prgs-reviewer; identity=sysadmin; action=approve; pr=748; head=277ec5269d039899a9d6eb77c5612b9cff9e71a7; session=71946-8e6386fa879b
LAST_UPDATED_BY: sysadmin (prgs-reviewer)

Independent reviewer APPROVE — PR #748 / issue #747

Pinned head: 277ec5269d039899a9d6eb77c5612b9cff9e71a7
Base: master @ b05075fd25ea7f3ac2e86d68f18a1a14c803962e
Author: jcwalker3 (reviewer identity sysadmin — not self-review)
Worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-feat-issue-747-sliding-lease-ttl (detached, clean)

Ten-minute policy

  • LEASE_TTL_MINUTES / LEASE_RENEWAL_MINUTES = 10 (600s)
  • Acquire, heartbeat, merger acquire, adoption share format_lease_body
  • Heartbeat renews with server UTC now + 600s
  • Issue locks and control-plane DB leases unchanged
  • Legacy expires_at honored (AC9)

Reclaimable removal

Author claim holds: production markers write last_activity and expires_at together; expiry is checked first so reclaimable is unreachable. foreign_expired keeps NEXT_ACTION_RELEASE_EXPIRED_LEASE. Non-blocking: delete dead reclaimable arms in assess/inventory/handoff/release.

Tests

Full suite 3425 passed / 6 skipped / 2 failed; failures reproduced on clean master b05075f (pre-existing).

Decision

APPROVE. Do not merge from this reviewer session.

Review Metadata:

  • LLM-Agent-SHA: llm-a7c3e91f2b04
  • LLM-Role: reviewer
  • Authenticated-Gitea-User: sysadmin
  • MCP-Profile: prgs-reviewer
  • Eligibility: passed
## Canonical PR State STATE: approved WHO_IS_NEXT: merger NEXT_ACTION: separate merger session re-validates head 277ec5269d039899a9d6eb77c5612b9cff9e71a7 then merges; do not merge from this reviewer session NEXT_PROMPT: ```text Merge PR #748 for issue #747 only if still open at head 277ec5269d039899a9d6eb77c5612b9cff9e71a7 base master@b05075fd25ea7f3ac2e86d68f18a1a14c803962e. Use merger namespace/profile. Do not touch PR #746. Do not implement #749. ``` WHAT_HAPPENED: Independent reviewer validated full diff, 10-minute sliding TTL policy, reclaimable removal, and full test suite; approving at pinned head. WHY: Sliding 10-minute TTL is correct; reclaimable tier is proven unreachable for production markers; foreign_expired preserves NEXT_ACTION_RELEASE_EXPIRED_LEASE; issue locks and control-plane DB TTLs unchanged. ISSUE: #747 HEAD_SHA: 277ec5269d039899a9d6eb77c5612b9cff9e71a7 REVIEW_STATUS: APPROVED by sysadmin via gitea_submit_pr_review at 277ec5269d039899a9d6eb77c5612b9cff9e71a7 MERGE_READY: true after separate merger gates only BLOCKERS: none VALIDATION: new TTL suite 17 passed; lease suites 185 passed; full suite 3425 passed / 6 skipped / 2 failed (both fail identically on clean master b05075fd25ea7f3ac2e86d68f18a1a14c803962e); git diff --check clean NATIVE_REVIEW_PROOF: transport=native_mcp; tool=gitea_submit_pr_review; namespace=gitea-reviewer; profile=prgs-reviewer; identity=sysadmin; action=approve; pr=748; head=277ec5269d039899a9d6eb77c5612b9cff9e71a7; session=71946-8e6386fa879b LAST_UPDATED_BY: sysadmin (prgs-reviewer) ## Independent reviewer APPROVE — PR #748 / issue #747 **Pinned head:** `277ec5269d039899a9d6eb77c5612b9cff9e71a7` **Base:** `master @ b05075fd25ea7f3ac2e86d68f18a1a14c803962e` **Author:** jcwalker3 (reviewer identity sysadmin — not self-review) **Worktree:** `/Users/jasonwalker/Development/Gitea-Tools/branches/review-feat-issue-747-sliding-lease-ttl` (detached, clean) ### Ten-minute policy - LEASE_TTL_MINUTES / LEASE_RENEWAL_MINUTES = 10 (600s) - Acquire, heartbeat, merger acquire, adoption share format_lease_body - Heartbeat renews with server UTC now + 600s - Issue locks and control-plane DB leases unchanged - Legacy expires_at honored (AC9) ### Reclaimable removal Author claim holds: production markers write last_activity and expires_at together; expiry is checked first so reclaimable is unreachable. foreign_expired keeps NEXT_ACTION_RELEASE_EXPIRED_LEASE. Non-blocking: delete dead reclaimable arms in assess/inventory/handoff/release. ### Tests Full suite 3425 passed / 6 skipped / 2 failed; failures reproduced on clean master b05075f (pre-existing). ### Decision **APPROVE**. Do not merge from this reviewer session. Review Metadata: - LLM-Agent-SHA: llm-a7c3e91f2b04 - LLM-Role: reviewer - Authenticated-Gitea-User: sysadmin - MCP-Profile: prgs-reviewer - Eligibility: passed
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #748
issue: #747
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 71946-8e6386fa879b
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-feat-issue-747-sliding-lease-ttl
phase: released
candidate_head: 277ec5269d
target_branch: master
target_branch_sha: b05075fd25
last_activity: 2026-07-18T18:12:57Z
expires_at: 2026-07-18T20:12:57Z
blocker: manual-release

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #748 issue: #747 reviewer_identity: sysadmin profile: prgs-reviewer session_id: 71946-8e6386fa879b worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-feat-issue-747-sliding-lease-ttl phase: released candidate_head: 277ec5269d039899a9d6eb77c5612b9cff9e71a7 target_branch: master target_branch_sha: b05075fd25ea7f3ac2e86d68f18a1a14c803962e last_activity: 2026-07-18T18:12:57Z expires_at: 2026-07-18T20:12:57Z blocker: manual-release
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #748
issue: #747
reviewer_identity: sysadmin
profile: prgs-merger
session_id: 80867-c576f546e587
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/merge-pr-748-277ec52-20260718T181603
phase: claimed
candidate_head: 277ec5269d
target_branch: master
target_branch_sha: b05075fd25
last_activity: 2026-07-18T18:16:08Z
expires_at: 2026-07-18T20:16:08Z
blocker: none

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #748 issue: #747 reviewer_identity: sysadmin profile: prgs-merger session_id: 80867-c576f546e587 worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/merge-pr-748-277ec52-20260718T181603 phase: claimed candidate_head: 277ec5269d039899a9d6eb77c5612b9cff9e71a7 target_branch: master target_branch_sha: b05075fd25ea7f3ac2e86d68f18a1a14c803962e last_activity: 2026-07-18T18:16:08Z expires_at: 2026-07-18T20:16:08Z blocker: none
sysadmin merged commit fdab6b6c69 into master 2026-07-18 13:16:24 -05:00
Owner

Stale #332 review-decision lock cleanup (#594)

Status: APPLIED

Manual deletion of session-state files is not the workflow.
This path only clears a lock when the referenced PR is merged/closed.

## Stale #332 review-decision lock cleanup (#594) Status: **APPLIED** - actor: `sysadmin` - profile: `prgs-merger` - timestamp: `2026-07-18T18:16:25.107777+00:00` - last terminal: `approve` on PR #748 - PR state: `closed` (merged=True) - merge_commit_sha: `fdab6b6c69717d32a0d50e233413cf09be83f6e8` - prior live_mutations_count: `1` - prior profile_identity: `prgs-reviewer` Manual deletion of session-state files is **not** the workflow. This path only clears a lock when the referenced PR is merged/closed.
Sign in to join this conversation.
No Reviewers
No labels
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

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