fix(session): keep KIND_DECISION_LOCK durable past generic 4h TTL (Closes #720) #721
Merged
sysadmin
merged 1 commits from 2026-07-16 19:48:07 -05:00
fix/issue-720-expired-decision-lock into master
Labels
Clear labels
allocator
anti-stomp
architecture
bug
chore
codex
concurrency
contamination
control-plane
dashboard
database
design
documentation
enhancement
gitea
glitchtip
important
incident
incident-bridge
integration
jenkins
labels
leases
mcp
mcp-health
mcp-menu
multi-project
mutating
nice-to-have
observability
portability
preflight
protected-branch
queue
read-only
reconnect
recovery
refactor
release
reliability
resumable-review
reviewer
roadmap
safety
security
self-hosted
sentry
stale-runtime
status:blocked
status:in-progress
status:pr-open
status:ready
terminal-lock
testing
tracker
type:bug
type:feature
type:feature
type:guardrail
visibility
workflow
workflow-hardening
workflow-hardening
Controller-owned work allocator
Prevent concurrent LLM session stomping
Architecture / structural design
OpenAI Codex client / workflow session surface
Concurrent session safety
Workflow or session contamination incident
MCP control-plane coordination and allocation authority
MCP operational dashboard/queue view
Internal coordination storage (SQLite/Postgres)
Design / investigation, no implementation
Docs / runbooks
New feature or improvement
Gitea MCP workflow
GlitchTip integration
Operational or process incident requiring durable audit trail
Sentry-to-Gitea incident bridging
Integration testing
Jenkins integration
Label taxonomy management
Lease adopt/release/expire lifecycle
MCP server / tooling
MCP namespace and runtime health
MCP menu surface
Work spanning multiple monitoring projects or Gitea repos
Mutating action; requires gating
Observability, metrics, traces, error reporting
Cross-platform / portability
Shared preflight gates before mutation
Protected branch / stable-branch policy concern
Work queue visibility and allocation
Read-only, no mutation
MCP client reconnect/reload recovery path
Recovery paths for stale/foreign leases
Code refactor / restructure
Release / versioning
Reliability / failure handling
Persist and resume prepared review verdicts across sessions
Reviewer workflow tooling
Roadmap / umbrella issue
Safety rails and fail-closed mutation guards
Security / trust boundary
Self-hosted infrastructure integration
Sentry error monitoring integration
Stale backend daemon / runtime-vs-master parity failures
Issue is blocked
Issue is being worked on
Issue has an open pull request
Issue is ready for work
Terminal review lock (#332) path
Tests / test coverage
Issue tracker hygiene / meta
Bug or defect
Feature or enhancement
Feature or enhancement
Safety gate or guardrail
Workflow state visibility for LLMs/operators
Cross-tool workflow
LLM workflow coordination hardening
LLM workflow coordination hardening
No labels
Milestone
No items
No Milestone
Projects
Clear projects
No projects
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: Scaled-Tech-Consulting/Gitea-Tools#721
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Closes #720.
Root cause
KIND_DECISION_LOCKwas treated as ordinary session state under the generic four-hour TTL. After age expiry, durable load /gitea_mark_final_review_decisionfailed withsession state expired after 4hbefore head-scoped#620logic (fresh_review_on_current_head_allowed) could allow an independent formal review at a newer open-PR head. Moot cleanup (#594) is correctly forbidden while the PR is open, and irrecoverable recovery (#709) is not an ordinary-profile path — so affected open PRs had no reachable sanctioned recovery.Concrete reproduction: PR #616, review 443
REQUEST_CHANGESat old heada0fffae…, remediated heada6a2243…, independent re-review green, prepared APPROVE blocked by TTL.State-machine correction
KIND_DECISION_LOCKas recovery-critical (with archive/recovery kinds). Terminal review provenance is not disposable cache; other kinds (workflow load, drafts, etc.) remain TTL-bound.kind+recovery_criticalon decision-lock save for compatibility and flag-based readers.inspect_state_envelopeso assessment can report on-disk present / age / TTL-exempt status instead of silent "no lock".disk_inspectwhen normal load is empty but a file remains.Existing on-disk ledgers become loadable after deploy without hand-editing session-state files (kind membership is enough).
Compatibility
kind: review_decision_lockload after >4h.#709authorization; no grant ofgitea.decision_lock.irrecoverable_recoveryto author/reviewer/merger/general reconciler profiles.Security invariants
REQUEST_CHANGESnever counts as approval.internal_error).Tests
tests/test_issue_720_expired_decision_lock.py(14):Validation
Explicit non-goals
chore/preserve-local-master-54753d4Next role
Independent REVIEWER — do not self-review or merge.
repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #721
issue: #720
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 74516-b6720915604a
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr-721-80f59b3
phase: claimed
candidate_head:
80f59b334etarget_branch: master
target_branch_sha:
293808b42dlast_activity: 2026-07-16T21:56:45Z
expires_at: 2026-07-16T23:56:45Z
blocker: none
repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #721
issue: #720
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 74516-b6720915604a
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr-721-80f59b3
phase: released
candidate_head:
80f59b334etarget_branch: master
target_branch_sha:
293808b42dlast_activity: 2026-07-16T22:01:03Z
expires_at: 2026-07-17T00:01:03Z
blocker: manual-release
Canonical Issue State
STATE: blocked_formal_review_submit
WHO_IS_NEXT: controller
NEXT_ACTION: Fix master task_capability_map so review_pr and approve_pr use role=reviewer (matching prgs-reviewer), restart gitea-reviewer MCP with in_parity, then independent reviewer posts one formal APPROVE at head
80f59b3NEXT_PROMPT:
WHAT_HAPPENED: Independent code review of PR #721 completed as APPROVE-worthy (Issue #720 ACs pass; 14/228/2898 tests; clean merge onto
293808b4). Formal submit blocked: master970e68bremapped review_pr to role=merger while prgs-merger forbids approve/review and prgs-reviewer is role=reviewer. Lease acquired and released (11891/11893). mark_final succeeded earlier; no formal Gitea review object. No merge.WHY: Runtime master role map catch-22 prevents resolve(review_pr) on prgs-reviewer. Orthogonal to PR #721 three-dot scope.
RELATED_PRS: #721, #720, master
970e68b,293808b4BLOCKERS: Unblock when master maps review_pr/approve_pr to role=reviewer matching prgs-reviewer permissions and gitea-reviewer MCP is restarted with in_parity such that resolve(review_pr) returns allowed_in_current_session=true
VALIDATION: 14 focused + 228 aggregate + 2898 full suite passed (6 skipped, 1 warning, 173 subtests); clean merge sim; checkouts clean
LAST_UPDATED_BY: sysadmin / prgs-reviewer
repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #721
issue: #720
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 14647-427dc88f7b0b
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr-721-80f59b3
phase: claimed
candidate_head:
80f59b334etarget_branch: master
target_branch_sha:
ba7915452elast_activity: 2026-07-17T00:06:18Z
expires_at: 2026-07-17T02:06:18Z
blocker: none
APPROVE — independent formal review of PR #721 at head
80f59b334e(Closes-#720 scope), recorded after the incident #722 capability repair.Technical basis (validated at this exact head; see PR comments 11891–11895): KIND_DECISION_LOCK correctly classified recovery-critical with archive/recovery kinds;
recovery_critical+kindstamped on save for legacy envelopes;inspect_state_envelopereports on-disk presence/age/TTL-exempt status; stale-lock assessment surfacesdisk_inspect; #332 same-head, #620 new-head, #594 moot-cleanup, and #709 authorization boundaries all preserved; no ordinary-profile recovery permission expansion. Test evidence at this head: 14 focused, 228 aggregate, 2898 full-suite passing (6 skipped, 1 known warning). Base master has since advanced293808b4→ba79154(capability-map role restoration + invariant tests only — no file overlap with this PR's diff; merge simulation remains clean).Canonical PR State
STATE: formal_approve_verdict_recorded
ISSUE: #720
HEAD_SHA:
80f59b334eREVIEW_STATUS: APPROVE verdict recorded via the native review API at head
80f59b3by prgs-reviewer / sysadminNATIVE_REVIEW_PROOF: this verdict is recorded by the live native gitea-reviewer MCP daemon (native_mcp transport, daemon pid 14647, reviewer lease session 14647-427dc88f7b0b, lease comment 11925) through gitea_submit_pr_review with final_review_decision_ready consuming the durable decision lock; no offline, import, or script fallback path was used
MERGE_READY: eligible for independent merger adoption; merger must re-verify head, gates, and authorization before any merge
WHO_IS_NEXT: merger
NEXT_ACTION: Independent merger session adopts the PR lease and merges PR #721 only under separate explicit authorization
NEXT_PROMPT:
WHAT_HAPPENED: The prepared APPROVE decision for PR #721, stranded by the #722 capability regression, is now recorded as a formal native review after the operator-authorized master repair (
ba79154) and reviewer-namespace restart.WHY: Prior independent review at this exact head found Issue #720 acceptance criteria satisfied; the formal verdict was stranded by the #722 capability regression, which is now repaired at master
ba79154with resolve(review_pr) allowing prgs-reviewer again.RELATED_PRS: #721, #720, #722, #723
BLOCKERS: none for this review verdict; merge requires a separate operator authorization
VALIDATION: at head
80f59b3— 14 focused, 228 aggregate, 2898 full-suite tests passing (6 skipped, 1 known warning); clean merge simulation; capability-repair suite 2900 passing at masterba79154LAST_UPDATED_BY: prgs-reviewer / sysadmin (native gitea-reviewer namespace)
[THREAD STATE LEDGER]
what is true now: PR #721 remains in open state at head 80f59b3; this submission records the APPROVE verdict via the native review API; master carries the #722 capability repair at
ba79154.what changed: the formal verdict is now recorded on Gitea; previously only a durable local prepared-APPROVE decision lock existed with no review object.
what is blocked: the merge, pending separate operator authorization and an independent merger session.
who/what acts next: a merger session adopts the PR lease and merges under explicit authorization; the controller completes the incident #722 audit trail.
Server-side decision state: APPROVE review recorded at head 80f59b3; PR #721 in open state awaiting merger.
Local verdict/state: durable decision lock consumed by this submission; reviewer lease 11925 active and released immediately after this verdict.
Next actor: merger (separate session, separate authorization).
Required action: merger adoption and merge of PR #721, then Issue #720 closure through the merge.
Blocker classification: no blocker
Do not do: no self-merge from this reviewer session; no additional review mutations for PR #721 in this run.
adopted_at: 2026-07-17T00:44:39Z
adopted_by_identity: sysadmin
adopted_by_profile: prgs-merger
adopted_from_session_id: 14647-427dc88f7b0b
adopted_from_profile: prgs-reviewer
adopted_from_reviewer_identity: sysadmin
adopted_from_comment_id: 11925
adoption_reason: merger-handoff-approved-head
repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #721
issue: #720
reviewer_identity: sysadmin
profile: prgs-merger
session_id: 60151-ffe26336620a
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr-721-80f59b3
phase: adopted
candidate_head:
80f59b334etarget_branch: master
target_branch_sha:
ba7915452elast_activity: 2026-07-17T00:44:39Z
expires_at: 2026-07-17T02:44:39Z
blocker: none
Stale #332 review-decision lock cleanup (#594)
Status: APPLIED
sysadminprgs-reviewer2026-07-17T02:05:12.947396+00:00approveon PR fix(session): keep KIND_DECISION_LOCK durable past generic 4h TTL (Closes #720) (#721)closed(merged=True)67e4a2b5e96b680a1dcb90a20c2ebf87357a3b1f1prgs-reviewerManual deletion of session-state files is not the workflow.
This path only clears a lock when the referenced PR is merged/closed.