feat(recovery): stale worktree binding demotion and crash-orphan lease recovery (Closes #702) #703
Open
jcwalker3
wants to merge 2 commits from
fix/issue-702-stale-binding-lease-recovery into master
pull from: fix/issue-702-stale-binding-lease-recovery
merge into: Scaled-Tech-Consulting:master
Scaled-Tech-Consulting:master
Scaled-Tech-Consulting:fix/issue-709-decision-lock-cross-profile
Scaled-Tech-Consulting:fix/issue-695-native-transport-quarantine
Scaled-Tech-Consulting:fix/issue-698-report-validator-schema
Scaled-Tech-Consulting:fix/issue-699-structured-auth-mcp-errors
Scaled-Tech-Consulting:fix/issue-695-native-quarantine-v2
Scaled-Tech-Consulting:fix/issue-693-review-decision-lock-recovery
Scaled-Tech-Consulting:fix/issue-691-obsolete-reviewer-lease-cleanup
Scaled-Tech-Consulting:feat/issue-687-reconciler-branch-delete
Scaled-Tech-Consulting:fix/issue-683-workflow-guard-hardening
Scaled-Tech-Consulting:chore/issue-681-preserve-review-session-wip
Scaled-Tech-Consulting:feat/issue-604-anti-stomp-preflight
Scaled-Tech-Consulting:feat/issue-606-sentry-observability
Scaled-Tech-Consulting:fix/issue-671-block-stable-branch-push
Scaled-Tech-Consulting:fix/issue-675-residual-preflight-remediation
Scaled-Tech-Consulting:fix/issue-673-remediate-regressions-part2
Scaled-Tech-Consulting:fix/issue-673-remediate-regressions
Scaled-Tech-Consulting:feat/issue-603-lifecycle-labels
Scaled-Tech-Consulting:fix/issue-627-set-issue-labels-pagination
Scaled-Tech-Consulting:feat/issue-601-first-class-leases
Scaled-Tech-Consulting:feat/issue-612-incident-bridge
Scaled-Tech-Consulting:feat/issue-600-controller-allocator-api
Scaled-Tech-Consulting:fix/issue-620-head-scoped-review-locks
Scaled-Tech-Consulting:feat/issue-613-allocator-db-substrate
Scaled-Tech-Consulting:docs/mcp-stable-control-runtime-policy
Scaled-Tech-Consulting:feat/issue-609-prepared-review-verdict-resume
Scaled-Tech-Consulting:feat/issue-610-live-remote-parity
Scaled-Tech-Consulting:feat/issue-503-reviewer-active-worktree
Scaled-Tech-Consulting:feat/issue-470-preflight-contract
Scaled-Tech-Consulting:feat/issue-440-lock-recovery
Scaled-Tech-Consulting:feat/issue-440-branch-recovery
Scaled-Tech-Consulting:feat/issue-458-queue-fail-closed-copy
Scaled-Tech-Consulting:feat/issue-400-early-duplicate-work-gate
Scaled-Tech-Consulting:feat/issue-308-reconcile-inventory-pagination
Scaled-Tech-Consulting:feat/issue-308-reconcile-pagination-proof
Scaled-Tech-Consulting:docs/issue-261-agent-temp-artifact-cleanup
Scaled-Tech-Consulting:feat/issue-262-map-commit-files
Scaled-Tech-Consulting:fix/infra-stop-conflict-marker-false-positive
Scaled-Tech-Consulting:feat/issue-139-role-aware-task-routing
Scaled-Tech-Consulting:feat/issue-188-continuation-selection-wall
Scaled-Tech-Consulting:feat/issue-189-continuation-mode-proofs
Scaled-Tech-Consulting:feat/issue-232-refresh-wiki-proof-heads
Scaled-Tech-Consulting:feat/issue-210-block-workspace-edits
Scaled-Tech-Consulting:feat/issue-204-exact-issue-lock
Scaled-Tech-Consulting:docs/issue-80-label-taxonomy
Scaled-Tech-Consulting:docs/issue-79-safety-boundary-updates
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 Label
Milestone
No items
No Milestone
Projects
Clear projects
No project
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: Scaled-Tech-Consulting/Gitea-Tools#703
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.
Delete Branch "fix/issue-702-stale-binding-lease-recovery"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Closes #702. An unhandled daemon crash skips graceful teardown: the durable reviewer lease comment survives, the in-memory
_SESSION_LEASEdies with the process, and the auto-reconnected daemon inherits a staleGITEA_ACTIVE_WORKTREEfrom its parent environment (the PR #701 /branches/review-pr-654incident, lease comment 11131, session65664-4f248d213d60).Changes
AC2 — safely clear or re-bind stale
GITEA_ACTIVE_WORKTREEstale_binding_recovery.py(new)corroborated/unverified_inherited/provably_stale_missing_path/superseded_by_session_lease; fail-closed recovery plan;apply_recoveryclears the env var only for the two provably-stale classesgitea_mcp_server.pygitea_resolve_task_capability(durable audit via session state,KIND_STALE_BINDING_RECOVERY); runtime context surfaces the classification read-only; uncorroborated inherited bindings get an exact managed-reconnect next action, never a silent clearnamespace_workspace_binding.pyresolve_namespace_workspace(verify_paths=…)demotes env-bound worktrees whose path no longer exists (recorded inignored_bindings); mutation-guard and runtime-context resolution always verify; explicitworktree_patharguments are never demotedAC3 — lease cleanup executed or recoverable after unexpected exit
reviewer_pr_lease.pyKIND_REVIEWER_SESSION_LEASE) written on sanctioned record/heartbeat, removed on sanctioned clear — a crash leaves provable orphan evidence (owner pid + session id).assess_crashed_session_lease_orphanderives tri-stateowner_process_alive(only a dead recorded owner pid proves exit; PID liveness is never ownership). New classificationorphaned_expired_superseded_head: an expired superseded-head lease with no terminal review no longer yields a permanent ambiguous/wait — post-expiry it unlocks fresh acquisition, and guarded cleanup becomes eligible only with owner-exit evidence + clean/absent worktree + controller authorization + exact confirmation. Pre-expiry behavior unchanged (fail-closed wait, no steal).mcp_session_state.pygitea_mcp_server.pyowner_process_alive=NoneTests
tests/test_issue_702_stale_binding_lease_recovery.py— 29 tests over the five mandated scenarios: lost in-session leases, old-head leases, runtime/worktree mismatch, managed reconnect, safe expirytests/test_issue_691_obsolete_reviewer_lease_cleanup.py— one test updated for the intentional behavior change (expired + superseded + no terminal review now classifiesorphaned_expired_superseded_head; still denied without provable owner-exit evidence; pre-expiry ambiguous branch asserted in place)Validation
Note: the full-suite run uses
-sin this environment because pytest capture plus keychain access at import of the CLI-script test modules (tests/test_create_issue.pycohort) dies or hangs in the sandboxed shell — reproduced on an unmodified master worktree (branches/issue-695-mcp-provenance-hardening@2376567), so it is pre-existing and not introduced here.Explicit non-goals
Worktree / branch proof
fix/issue-702-stale-binding-lease-recoverybranches/fix-issue-702-stale-binding-lease-recovery889931d5532b32a46a181e03c1345946c7516aacNext role
Independent REVIEWER in a completely fresh session — do not self-review or merge.
[THREAD STATE LEDGER] PR #703 — non-formal blocker handoff: prior validation pass ran without a reviewer lease and is non-authoritative; no formal verdict exists at head
889931dWhat is true now:
889931d5532b32a46a181e03c1345946c7516aac.branches/review-pr-703confirmed clean (git status --porcelain empty) and detached at the pinned head889931d5532b32a46a181e03c1345946c7516aac, which matches the live PR head read back from the review API immediately before this comment.What changed:
What is blocked:
Who/what acts next:
Canonical Issue State
STATE:
awaiting-fresh-reviewer-lease
WHO_IS_NEXT:
reconciler
NEXT_ACTION:
Handle lease 11131 via controller/reconciler after its canonical expiry at 2026-07-13T19:16:41Z, then hand PR #703 to a completely fresh reviewer session that acquires its own lease before any review or validation work.
NEXT_PROMPT:
WHAT_HAPPENED:
A session performed review and validation work on PR #703 before holding a valid in-session reviewer lease; the work is quarantined as non-authoritative, its F1–F6 findings survive only as leads, and the review worktree was confirmed clean at the pinned head with no lease, verdict, or source mutations from this session.
WHY:
Review authority derives from the lease discipline, not from the quality of the analysis; acquiring a lease after validation would legalize unlicensed work and defeat the anti-stomp guarantees.
RELATED_PRS:
PR #703 (this PR, open, head
889931d, zero reviews); PR #701 (open, head6b675f5, no formal review, gated behind #702/#703 landing); PR #696 (separate security-hold track, untouched).BLOCKERS:
Queue/lease blocker — lease 11131 canonical expiry + controller/reconciler disposition, then fresh-reviewer lease acquisition, must precede any formal review of PR #703.
VALIDATION:
Review API read-back immediately before this comment: pr_state=open, current_head_sha=889931d5532b32a46a181e03c1345946c7516aac, reviews=[]; worktree branches/review-pr-703 clean and detached at the same SHA; F1–F6 remain unconfirmed leads pending the fresh leased review.
LAST_UPDATED_BY:
controller / prgs-author (jcwalker3)
CTH: Controller Decision — lease 11131 + non-authoritative review leads
Status: lease_11131_expired_cleanup_not_authorized; reviewer_env_still_bound_to_review-pr-654; not_safe_to_launch_fresh_pr_703_reviewer
Next owner: user
Current blocker: (1) native cleanup of comment-lease 11131 not authorized; (2) GITEA_ACTIVE_WORKTREE still binds reviewer/reconciler runtimes to branches/review-pr-654
Decision: Do not apply obsolete-lease cleanup. Do not launch a PR #703 reviewer until binding is clear and a re-check passes.
Proof: dry-run cleanup_allowed=false; runtime context active_task_workspace_root=review-pr-654
Next action: Operator clears GITEA_ACTIVE_WORKTREE / managed reconnect; controller re-verifies; then fresh leased reviewer on #703 re-evaluates F1–F6.
Ready-to-paste prompt: see NEXT_PROMPT.
Canonical Issue State
STATE:
controller-reconcile-complete-for-11131-dry-run; cleanup-not-authorized; env-binding-block-remains
WHO_IS_NEXT:
user
NEXT_ACTION:
Clear or rebind stale GITEA_ACTIVE_WORKTREE so reviewer/reconciler runtime no longer points at branches/review-pr-654; controller re-runs dry-run/diagnose; only then launch a fresh leased reviewer for PR #703 who must re-evaluate F1–F6 with evidence
NEXT_PROMPT:
WHAT_HAPPENED:
Controller/reconciler ran sanctioned obsolete-lease dry-run after wall-clock expiry of lease 11131. Cleanup not authorized (ambiguous_conflicting_evidence: superseded head without terminal review). Durable assess on #701 shows active_lease null; env binding to review-pr-654 remains on reviewer and reconciler runtimes. Non-authoritative F1–F6 preserved for leased independent re-evaluation.
WHY:
Must not bypass native cleanup gates, must not steal/repoint leases, and must not launch review while runtime is still bound to the #701 incident worktree path (review-pr-654).
RELATED_PRS:
PR #703 (Closes #702). Lease 11131 lived on PR #701 (issue #699).
BLOCKERS:
GITEA_ACTIVE_WORKTREE still routes active_task_workspace_root to branches/review-pr-654 on prgs-reviewer and prgs-reconciler; obsolete cleanup of 11131 not authorized (cleanup_allowed=false).
VALIDATION:
LAST_UPDATED_BY:
controller/reconciler (sysadmin / prgs-reconciler)
NON-AUTHORITATIVE REVIEW LEADS (quarantined; not a formal verdict)
Provenance: These leads came from a quarantined review that lacked the required lease. They are not formal findings and not a review verdict. Any tests or observations from that quarantined session are non-authoritative.
A fresh leased reviewer on PR #703 must independently reproduce or reject each lead. If a lead cannot be reproduced, that absence of reproduction must be documented with evidence — it must not be silently dropped.
F1 — Stale-binding recovery ordering
Stale-binding recovery appears to run after the terminal-launcher probe in
gitea_resolve_task_capability. A worktree removed during a session may wedge later mutation-task resolution until daemon restart.F2 — Preflight path existence
_resolve_preflight_workspace_pathappears not to verify path existence consistently with mutation context. A missing-path environment binding may produce empty porcelain and bypass dirty-tracked-file preflight.F3 — orphaned_expired_superseded_head cleanup evidence
orphaned_expired_superseded_headcleanup appears to permitworktree_exists=Noneandworktree_clean=None, weaker than the siblingorphaned_owner_missinggate and its diagnosis path.F4 — Session-state TTL vs #702 durability
A four-hour session-state TTL may silently remove crash-orphan shadow evidence, leaving later cleanup permanently fail-closed and potentially undermining #702’s durability acceptance criterion.
F5 — Concurrent same-profile shadow overwrite
Concurrent same-profile sessions may overwrite a single shadow record, producing ambiguous fail-closed state without adequate regression coverage.
F6 — Audit ordering after env clear
Environment state appears to be cleared before the best-effort audit write, creating an audit-ordering weakness.
[THREAD STATE LEDGER] PR #703 (fix for issue #702) environment — durable root-cause finding: repository-root .env injected stale workspace binding
What is true now:
What changed:
.envfile containedGITEA_ACTIVE_WORKTREE=<repo>/branches/review-pr-654.gitea_auth.pycallsload_dotenv(PROJECT_ROOT/.env)at import time, injecting the variable intoos.environafter process start — invisible to exec-time process-environment inspection and applied to every namespace on every spawn, becauseGITEA_ACTIVE_WORKTREEoutranks the role-specific worktree variables innamespace_workspace_binding.resolve_namespace_workspace..enventry was removed; the staticGITEA_REVIEWER_WORKTREE=branches/review-pr-538binding was removed from the client MCP configuration; all four MCP server processes were restarted and re-verified..envloading must not be allowed to inject or override runtime workspace-binding variables (GITEA_ACTIVE_WORKTREE,GITEA_*_WORKTREE). Without a code-level guard in the dotenv/auth load path, any future stale.envrecreates this same failure even after local cleanup.What is blocked:
Who/what acts next:
Canonical Issue State
STATE:
root-cause-documented; environment cleanup complete; PR #703 awaiting fresh review
WHO_IS_NEXT:
reviewer
NEXT_ACTION:
Fresh reviewer session: create own PR #703 worktree, acquire reviewer lease, re-pin live head, then perform the formal review of PR #703.
NEXT_PROMPT:
WHAT_HAPPENED:
Stale reviewer workspace binding to branches/review-pr-654 persisted across reconnects. Root cause: repository-root .env set GITEA_ACTIVE_WORKTREE, loaded by gitea_auth.py load_dotenv at import, overriding role-specific bindings for all namespaces on every process spawn. The .env entry was removed, the static reviewer worktree binding was removed from the client MCP configuration, and the MCP processes were restarted; the runtime now reports a neutral binding and zero active reviewer leases.
WHY:
GITEA_ACTIVE_WORKTREE outranks role-specific worktree env vars in namespace_workspace_binding.resolve_namespace_workspace, and dotenv injection happens after process start, so process-environment inspection and reconnects could neither detect nor clear it.
RELATED_PRS:
PR #703 (fix for issue #702; remains in open state awaiting fresh review)
BLOCKERS:
None — no blocker for the review path. Follow-up hardening required: guard runtime workspace-binding variables against .env injection in the dotenv/auth load path.
VALIDATION:
gitea_get_runtime_context (reviewer namespace, fresh processes 2026-07-13): active_task_workspace_root = MCP server process root, workspace_binding_source = "MCP server process root (default)". gitea_list_workflow_leases (control-plane DB, authoritative): zero active reviewer leases.
LAST_UPDATED_BY:
controller session 2026-07-13 (prgs-author namespace)
CTH: Controller Decision — formal review scope for PR #703 (#702 vs #704)
Status: review_scope_locked_to_issue_702; dotenv_prevention_out_of_scope_for_this_PR; #704_is_immediate_follow_up_not_merge_gate
Next owner: reviewer
Current blocker: none for scope decision (formal leased review still required)
Decision: PR #703 must not be required to implement repository
.env/load_dotenvworkspace-binding injection guards to satisfy #702. Those guards are #704-only. PR #703 must still fully meet #702 AC2+AC3; any confirmed recovery/preflight/lease gap stays on this PR and must not be deferred to #704 because #704 exists. Comments 11191/11193: operational dotenv cleanup done; review path unblocked for environment reasons. Full matrix on Issue #704 comment 11202.Proof: Issue #702 ACs; this PR body AC2/AC3 + non-goals; Issue #704 AC11 answer (comment 11202); comments 11191, 11193.
Next action: Fresh reviewer session with own worktree + lease; re-pin live head; review against #702 only; re-evaluate F1–F6 with evidence.
Ready-to-paste prompt: see NEXT_PROMPT.
Reviewer checklist (scope)
GITEA_ACTIVE_WORKTREE.envfrom injectingGITEA_*_WORKTREEat importMust PR #703 change for #702?
#701 resume
#704 merge is not required before #701 review can safely resume. #701 remains behind clean runtime (done per 11193) and this #702/#703 track landing per prior CTHs.
Canonical Issue State
STATE:
scope-locked-to-702; awaiting-fresh-leased-formal-review; #704-not-blocking
WHO_IS_NEXT:
reviewer
NEXT_ACTION:
Create fresh PR #703 worktree, acquire reviewer lease first, re-pin live head, formal review vs #702 ACs only.
NEXT_PROMPT:
WHAT_HAPPENED:
Controller recorded formal-review scope and #704 dependency so reviewers cannot expand or shrink #702 acceptance incorrectly.
WHY:
#704 existence must not silently redefine #702 success criteria on this PR.
RELATED_PRS:
This PR closes #702; #704 follow-up; #701 resume independent of #704 merge.
BLOCKERS:
none for scope; formal review still pending lease + independent validation
VALIDATION:
11193: env cleanup complete, no blocker for #703 review path; follow-up hardening = dotenv load-path guard (#704).
LAST_UPDATED_BY:
controller dependency decision (jcwalker3 / prgs-author)
repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #703
issue: #702
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 82984-6ca5668fcaca
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr-703-independent-889931d
phase: claimed
candidate_head:
889931d553target_branch: master
target_branch_sha:
237656702flast_activity: 2026-07-13T20:08:34Z
expires_at: 2026-07-13T22:08:34Z
blocker: none
repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #703
issue: #702
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 82984-6ca5668fcaca
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr-703-independent-889931d
phase: reviewing
candidate_head:
889931d553target_branch: master
target_branch_sha:
237656702flast_activity: 2026-07-13T20:09:05Z
expires_at: 2026-07-13T22:09:05Z
blocker: none
repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #703
issue: #702
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 82984-6ca5668fcaca
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr-703-independent-889931d
phase: validation-start
candidate_head:
889931d553target_branch: master
target_branch_sha:
237656702flast_activity: 2026-07-13T20:10:09Z
expires_at: 2026-07-13T22:10:09Z
blocker: none
repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #703
issue: #702
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 82984-6ca5668fcaca
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr-703-independent-889931d
phase: full-validation
candidate_head:
889931d553target_branch: master
target_branch_sha:
237656702flast_activity: 2026-07-13T20:11:36Z
expires_at: 2026-07-13T22:11:36Z
blocker: none
repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #703
issue: #702
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 82984-6ca5668fcaca
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr-703-independent-889931d
phase: validation-complete
candidate_head:
889931d553target_branch: master
target_branch_sha:
237656702flast_activity: 2026-07-13T20:14:01Z
expires_at: 2026-07-13T22:14:01Z
blocker: none
Canonical PR State
STATE:
changes-requested-at-pinned-head
WHO_IS_NEXT:
author
NEXT_ACTION:
Fix the independently reproduced #702 AC2/AC3 defects F1, F3, F4, and F5; align/test the F2 preflight path; make F6 audit persistence failure explicit and safe; push a new head for fresh review.
NEXT_PROMPT:
WHAT_HAPPENED:
A fresh independent prgs-reviewer session acquired lease 82984-6ca5668fcaca before code review, validated the untouched pinned head, and independently reproduced or narrowed F1-F6.
WHY:
The implementation leaves capability-resolution recovery unreachable for a deleted active worktree and does not preserve safe, durable, concurrency-correct crash-orphan cleanup evidence.
ISSUE:
#702
HEAD_SHA:
889931d553REVIEW_STATUS:
REQUEST_CHANGES
MERGE_READY:
no
BLOCKERS:
F1, F3, F4, and F5 are independently reproduced #702 AC2/AC3 blockers. F2 is partially reproduced with downstream mitigation; F6 is reproduced as an audit-ordering defect.
VALIDATION:
Untouched detached head: focused 50 passed; related 94 passed; adversarial F1-F6 probe completed; full 2665 passed, 6 skipped, 161 subtests passed; compileall, diff check, secret scan, and artifact-marker scan passed.
LAST_UPDATED_BY:
sysadmin / prgs-reviewer
Independent reproduction details
F1 confirmed — blocker (AC2).
gitea_resolve_task_capabilityprobesGITEA_ACTIVE_WORKTREEas its terminal cwd atgitea_mcp_server.py:11677-11719, but stale-binding recovery does not run until:11889-11895. With a removed worktree, the resolver returnedmissing cwdbefore recovery, left the stale env binding intact, and emitted no recovery report.F2 partially confirmed.
_resolve_preflight_workspace_pathat:334-345does not setverify_paths=True; the adversarial run resolved the deleted path and returned empty porcelain, while canonical mutation context demoted it to the valid reviewer worktree. I did not reproduce an end-to-end mutation bypass because later mutation/root guards mitigate it, but preflight remains inconsistent and lacks this integration test.F3 confirmed — blocker (AC3 safety). The
orphaned_expired_superseded_headbranch atreviewer_pr_lease.py:986-1008acceptsowner_process_alive=Falsewithout requiringworktree_clean=Trueorworktree_exists=False. The direct assessor returnedcleanup_allowed=truewith both worktree factsNone, while diagnosis correctly requires clean/absent evidence at:1348-1364.F4 confirmed — blocker (AC3 durability). The crash shadow uses generic session state with a four-hour TTL (
mcp_session_state.py:29,249-313). After five hours it loads as no evidence, so owner-exit proof required for cleanup disappears while the durable lease comment remains.F5 confirmed — blocker (parallel recovery).
state_keyatmcp_session_state.py:91-115keys the shadow only by kind + profile. Concurrentprgs-reviewersessions both map toreviewer_session_lease-prgs-reviewer, so a later heartbeat overwrites earlier crash evidence.F6 confirmed.
_assess_stale_active_bindingclears the env atgitea_mcp_server.py:301-303, then best-effort saves audit state and swallows failure at:304-317. An injected save failure producedrecovery_performed=truewith the env absent and no durable audit.Issue #704's repository-dotenv/load-path prevention was not used as a blocker.
CTH: Reviewer Handoff — formal REQUEST_CHANGES read back
Status: formal_request_changes_visible_at_pinned_head
Next owner: author
Current blocker: #702 AC2/AC3 defects independently reproduced at
889931d5532b32a46a181e03c1345946c7516aacDecision: Exactly one formal REQUEST_CHANGES verdict was submitted by
sysadmin / prgs-reviewerand read back as visible, non-dismissed, and non-stale. No merge was attempted.Canonical PR State
STATE:
changes-requested-at-pinned-head
WHO_IS_NEXT:
author
NEXT_ACTION:
Fix F1/F3/F4/F5, align and test F2, make F6 audit failure explicit and safe, push a new head, and request a fresh leased re-review.
NEXT_PROMPT:
WHAT_HAPPENED:
A fresh isolated detached worktree under
branches/review-pr-703-independent-889931dwas bound explicitly to the reviewer runtime. Lease session82984-6ca5668fcacawas acquired before code reading and maintained through validation and verdict. Formal readback reportsREQUEST_CHANGESat the exact pinned head.WHY:
F1 makes resolver-time missing-path recovery unreachable behind the terminal probe; F3 permits cleanup with unknown worktree evidence; F4 loses crash shadow evidence after four hours; F5 overwrites shadow evidence across concurrent same-profile sessions. F2 was partially reproduced with downstream mitigation; F6 audit ordering was reproduced.
ISSUE:
#702
HEAD_SHA:
889931d553REVIEW_STATUS:
REQUEST_CHANGES
MERGE_READY:
no
RELATED_PRS:
PR #703 is the reviewed implementation for Issue #702. PR #704 is separate dotenv load-path hardening and was not used as a blocker. PR #701 and PR #696 were not reviewed or mutated.
BLOCKERS:
F1/F3/F4/F5 confirmed #702 blockers; F2 partial; F6 confirmed. Issue #704 dotenv prevention is out of scope and was not a blocker.
VALIDATION:
Focused 50 passed; related 94 passed; adversarial F1-F6 probe completed; full 2665 passed, 6 skipped, 161 subtests passed; compileall/diff/secret/artifact checks passed. The only command failure was an initial relative venv path miss; the identical adversarial probe passed using the project venv.
LAST_UPDATED_BY:
sysadmin / prgs-reviewer
LEASE:
Session
82984-6ca5668fcacaremained active through this handoff; canonical release is the immediate next operation.repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #703
issue: #702
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 82984-6ca5668fcaca
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr-703-independent-889931d
phase: released
candidate_head:
889931d553target_branch: master
target_branch_sha:
237656702flast_activity: 2026-07-13T20:15:32Z
expires_at: 2026-07-13T22:15:32Z
blocker: manual-release
[THREAD STATE LEDGER] PR #703 author remediation — F1–F6 addressed, new head
c2fc2683b9pushed, awaiting completely fresh leased re-reviewWhat is true now:
c2fc2683b97e3ba5dc7eaf4ac9798af76bd08dfc; the formal REQUEST_CHANGES verdict recorded at889931d5532b32a46a181e03c1345946c7516aacis now flagged stale by the review API (review_feedback_stale=true,author_pushed_after_request_changes=true) and remains undismissed.fix/issue-702-stale-binding-lease-recoveryasc2fc268(1 commit atop the reviewed head). No review verdict was recorded and no merge was attempted from this session.c2fc268— new focused F1–F6 regression file 30 passed; related suites for the touched modules 130 passed; full suite 2695 passed, 6 skipped, 161 subtests passed (-q -s); compile check and diff secret scan clean.What changed:
gitea_resolve_task_capabilityBEFORE the terminal launcher probe, so a worktree removed mid-session recovers instead of wedging resolution on 'missing cwd'; the fail-closed probe block now carries the binding classification evidence; unverified bindings are still never cleared._resolve_preflight_workspace_pathapplies the sameverify_pathsexistence checks as the canonical mutation context, and_get_workspace_porcelainreturns a synthetic tracked-dirty sentinel on missing workspace or git failure — an uninspectable workspace can never produce empty porcelain or a clean-workspace result; downstream guards untouched.orphaned_expired_superseded_headcleanup matrix requires affirmative safe evidence (worktree_clean=trueorworktree_exists=false), aligned with the sibling gate and the diagnosis path; unknown evidence fails closed.list_statesenumeration API; interleaving and reconnect tests prove concurrent same-profile sessions cannot overwrite or misattribute each other's crash evidence; legacy single-slot records stay readable.pending) BEFORE the environment clears and refreshes toperformedafter; audit-write failure means no clear, reported explicitly; tests cover failure, retry, idempotence, and ordering.What is blocked:
Who/what acts next:
c2fc2683b97e3ba5dc7eaf4ac9798af76bd08dfc, then perform the formal re-review against #702 AC2/AC3, verifying each F1–F6 fix with evidence.Canonical PR State
STATE:
author-remediation-complete-awaiting-fresh-re-review
WHO_IS_NEXT:
reviewer
NEXT_ACTION:
Completely fresh prgs-reviewer session: own worktree + own lease first, re-pin live head
c2fc2683b9, formal re-review of PR #703 against Issue #702 AC2/AC3 verifying the F1–F6 fixes.NEXT_PROMPT:
WHAT_HAPPENED:
Author session resumed PR #703 from the formal REQUEST_CHANGES at
889931d, fixed F1–F6 in the issue-backed author worktree (recovery ordering, preflight path verification, affirmative cleanup evidence, durable crash-shadow lifecycle, collision-safe shadow identity, audit-before-clear), added 30 regression tests, ran focused/related/full validation, and pushed new headc2fc268.WHY:
The formal review confirmed F1/F3/F4/F5 as #702 AC2/AC3 blockers with F2 partial and F6 an audit-ordering defect; each fix restores the fail-closed guarantees the review demanded without absorbing #704 scope.
RELATED_PRS:
PR #703 (this PR, new head
c2fc268, prior verdict now stale, undismissed); PR #701 and PR #696 untouched by this session; #704 remains the separate dotenv load-path hardening track.BLOCKERS:
None for the re-review path — no blocker. The stale REQUEST_CHANGES stays authoritative until a fresh leased reviewer records a new verdict at the new head.
VALIDATION:
At
c2fc268in the author worktree: tests/test_issue_702_review_findings_f1_f6.py 30 passed; related suites 130 passed; full suite 2695 passed, 6 skipped, 161 subtests passed with-q -s; py_compile clean on all touched modules; diff secret scan clean; review API read-back shows current_head_sha=c2fc2683b97e3ba5dc7eaf4ac9798af76bd08dfc with review_feedback_stale=true.LAST_UPDATED_BY:
author session 2026-07-13 (jcwalker3 / prgs-author)
repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #703
issue: #702
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 48311-bc9067f4c07f
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr703-c2fc2683-fresh
phase: claimed
candidate_head:
c2fc2683b9target_branch: master
target_branch_sha:
237656702flast_activity: 2026-07-13T20:48:57Z
expires_at: 2026-07-13T22:48:57Z
blocker: none
repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #703
issue: #702
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 48311-bc9067f4c07f
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr703-c2fc2683-fresh
phase: pre-review
candidate_head:
c2fc2683b9target_branch: master
target_branch_sha:
237656702flast_activity: 2026-07-13T20:49:07Z
expires_at: 2026-07-13T22:49:07Z
blocker: none
repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #703
issue: #702
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 48311-bc9067f4c07f
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr703-c2fc2683-fresh
phase: validation-start
candidate_head:
c2fc2683b9target_branch: master
target_branch_sha:
237656702flast_activity: 2026-07-13T20:50:59Z
expires_at: 2026-07-13T22:50:59Z
blocker: none
repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #703
issue: #702
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 48311-bc9067f4c07f
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr703-c2fc2683-fresh
phase: full-validation
candidate_head:
c2fc2683b9target_branch: master
target_branch_sha:
237656702flast_activity: 2026-07-13T20:52:00Z
expires_at: 2026-07-13T22:52:00Z
blocker: none
repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #703
issue: #702
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 48311-bc9067f4c07f
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr703-c2fc2683-fresh
phase: validation-complete
candidate_head:
c2fc2683b9target_branch: master
target_branch_sha:
237656702flast_activity: 2026-07-13T20:53:11Z
expires_at: 2026-07-13T22:53:11Z
blocker: none
repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #703
issue: #702
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 48311-bc9067f4c07f
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr703-c2fc2683-fresh
phase: released
candidate_head:
c2fc2683b9target_branch: master
target_branch_sha:
237656702flast_activity: 2026-07-13T20:55:01Z
expires_at: 2026-07-13T22:55:01Z
blocker: manual-release
CTH: Controller Decision — tooling/remediation HOLD on PR #703 (NOT a formal review verdict)
Status: tooling_remediation_hold; no_formal_verdict_at_current_head; no_new_reviewer_until_698_active
Next owner: author
Current blocker: Issue #698 final-report validator/schema drift blocks formal verdict submission after leased validation completes
Decision: PR #703 is on tooling/remediation hold. This is a controller decision, not a formal Gitea review verdict.
Proof: live head
c2fc2683b97e3ba5dc7eaf4ac9798af76bd08dfc; review API: only REQUEST_CHANGES at stale head889931d…(review_feedback_stale=true); assess lease null; workflow reviewer leases=0; Issue #702 comments 11277 (blocker) + 11282 (lease release phase=released); Issue #698 comment 11284; Issue #702 controller disposition 11289.Next action: Author implements #698 immediately. Product fixes on this PR only from controller-ratified F1–F6 (see #702/11289). No new reviewer until #698 is merged and active.
Ready-to-paste prompt: see NEXT_PROMPT.
Hold rules (binding)
c2fc2683b97e3ba5dc7eaf4ac9798af76bd08dfc.889931dfor F1–F6 + later durable residual addenda) — not chat-only claims.889931dis not authority for the current head.Controller confirmation (session 48311-bc9067f4c07f)
F2 / F4 / F5 / F6
Full disposition on Issue #702 comment 11289. Summary: prior formal evidence at
889931dremains ratified remediation baseline; author claims atc2fc268are un-proven formally; 11277 adversarial phrases alone are insufficient for new residual FAIL without durable file:line addendum — request addendum from next leased re-review after #698 lands.Canonical Issue State
STATE:
tooling-remediation-hold; awaiting-698-validator-merge-and-active; no-formal-verdict-at-c2fc268
WHO_IS_NEXT:
author
NEXT_ACTION:
Land Issue #698 first. Optional product remediation on this PR only for ratified F1–F6. Then wait for controller/re-review launch after #698 is active.
NEXT_PROMPT:
WHAT_HAPPENED:
Controller placed PR #703 on tooling/remediation hold after confirming leased re-review completed validation at
c2fc268but could not submit a formal current-head verdict because of #698 validator/schema drift.WHY:
Recording a formal verdict requires a working final-report gate; product re-review must not race ahead of that repair.
RELATED_PRS:
This PR (#703). Issue #698 immediate. Issue #702 disposition 11289.
BLOCKERS:
#698 must merge and be active before any new reviewer starts.
VALIDATION:
11277, 11282, review API, lease assess, workflow leases=0, #698/11284, #702/11289
LAST_UPDATED_BY:
controller (jcwalker3 / prgs-author)
NOT A FORMAL REVIEW VERDICT.
repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #703
issue: none
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 3157-b48334241c03
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr-703
phase: claimed
candidate_head: none
target_branch: master
target_branch_sha: none
last_activity: 2026-07-13T22:58:56Z
expires_at: 2026-07-14T00:58:56Z
blocker: none
CTH: Controller/Reconciler — lease 11370 reassessed; sanctioned action = WAIT
Status: lease_11370_foreign_active; next_action_wait; no_steal; no_review_no_merge
Next owner: user (wait for expiry), then reconciler re-diagnose, then fresh reviewer
Current blocker: foreign active reviewer lease comment 11370 (session
3157-b48334241c03, phase=claimed, freshness=active)Decision: Follow native
gitea_diagnose_reviewer_pr_lease_handoffexactly → wait. Do not release, adopt, steal, cleanup, reconstruct session state, bypass gates, or submit a review from this controller session.Proof: diagnose(703, instructed_comment_id=11370); assess(703); list_workflow_leases count=0; wall clock vs expires_at.
Heads (do not assume prior candidate forever)
c2fc2683b97e3ba5dc7eaf4ac9798af76bd08dfccc3ad0870aab9829cbe28cd869a283beeb37991dLease 11370 diagnosis
foreign_active3157-b48334241c03branches/review-pr-703(exists, clean)Sanctioned recovery performed
wait only — no cleanup apply, no release, no adopt, no mutation.
#698 residual (not #703 scope)
Nested non-dict crash in
_rule_shared_canonical_comment_post_claimstill reproducible on master after PR #705; recorded on Issue #698 comment 11375. Do not bypass the final-report validator.Canonical Issue State
STATE:
awaiting_lease_11370_expiry_then_fresh_reviewer
WHO_IS_NEXT:
user
NEXT_ACTION:
Wait until after canonical expiry 2026-07-14T00:58:56Z; reconciler re-runs diagnose/assess; only if active_lease is null and next_action is not wait, launch a completely fresh prgs-reviewer that acquires its own lease, re-pins the then-current head, and reviews in a new isolated worktree.
NEXT_PROMPT:
WHAT_HAPPENED:
Controller/reconciler reassessed instructed lease comment 11370 with native diagnose/assess; lease is still foreign_active and not past expiry; recovery action is wait; control-plane DB has zero active leases but the comment-backed lease remains active; no review or merge was performed.
WHY:
Native handoff tooling forbids steal/release/cleanup of a foreign active lease; PID liveness is not ownership proof; formal review must wait for canonical expiry then a fresh leased reviewer session.
RELATED_PRS:
PR #703 (this PR, open); Issue #702; Issue #698 residual comment 11375 (validator, separate track); PR #705 already merged for partial #698.
BLOCKERS:
Queue/lease blocker — lease 11370 active until 2026-07-14T00:58:56Z; after that, re-diagnose required before fresh reviewer starts.
VALIDATION:
LAST_UPDATED_BY:
controller/reconciler (sysadmin / prgs-reconciler)
repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #703
issue: #702
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 92535-f7537c169f8d
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr-703-rereview-20260713T224507
phase: claimed
candidate_head:
c2fc2683b9target_branch: master
target_branch_sha:
1eafb757a9last_activity: 2026-07-14T02:45:11Z
expires_at: 2026-07-14T04:45:11Z
blocker: none
repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #703
issue: #702
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 92535-f7537c169f8d
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr-703-rereview-20260713T224507
phase: validating
candidate_head:
c2fc2683b9target_branch: master
target_branch_sha:
1eafb757a9last_activity: 2026-07-14T02:45:36Z
expires_at: 2026-07-14T04:45:36Z
blocker: none
repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #703
issue: #702
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 92535-f7537c169f8d
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr-703-rereview-20260713T224507
phase: deciding
candidate_head:
c2fc2683b9target_branch: master
target_branch_sha:
1eafb757a9last_activity: 2026-07-14T02:47:09Z
expires_at: 2026-07-14T04:47:09Z
blocker: none
repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #703
issue: #702
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 92535-f7537c169f8d
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr-703-rereview-20260713T224507
phase: claimed
candidate_head:
c2fc2683b9target_branch: master
target_branch_sha:
1eafb757a9last_activity: 2026-07-14T02:47:40Z
expires_at: 2026-07-14T04:47:40Z
blocker: none
Canonical PR State
STATE:
approved-at-pinned-head
WHO_IS_NEXT:
merger
NEXT_ACTION:
Merger adopts/acquires lease per workflow, re-pins live head
c2fc2683b9, runs merge preflight, and merges PR #703 (Closes #702). Do not self-merge from reviewer.NEXT_PROMPT:
WHAT_HAPPENED:
Completely fresh prgs-reviewer session independently re-reviewed PR #703 at live head
c2fc268after prior REQUEST_CHANGES (review 429 @889931d). All six prior findings (F1–F6) were re-derived and confirmed fixed. Issue #702 AC2/AC3 independently verified with tests.WHY:
Author remediation at
c2fc268restores fail-closed recovery ordering, preflight path verification, affirmative orphan-cleanup evidence, durable crash-shadow lifecycle, collision-safe shadow identity, and audit-before-clear semantics without absorbing #704 dotenv scope.ISSUE:
#702
HEAD_SHA:
c2fc2683b9REVIEW_STATUS:
APPROVE
MERGE_READY:
yes (merger-owned; not merged by this session)
BLOCKERS:
none
VALIDATION:
Worktree branches/review-pr-703-rereview-20260713T224507 detached clean HEAD=c2fc268; focused F1-F6+recovery 59 passed; related suites 159 passed; full suite 2695 passed, 6 skipped, 161 subtests passed; compileall OK; secret scan clean (test fixtures only).
LAST_UPDATED_BY:
sysadmin / prgs-reviewer
NATIVE_REVIEW_PROOF: transport=native_mcp; entrypoint=mcp_server; token_fingerprint=9c9a0ef163efc669; pid=92535; session=92535-f7537c169f8d; lease_comment=11482
Independent prior-finding disposition (F1–F6)
889931dc2fc268AC2 / AC3 evidence
AC2: stale_binding_recovery clears only provably-stale classes; uncorroborated requires managed reconnect; resolve-time recovery + durable KIND_STALE_BINDING_RECOVERY; path demotion via verify_paths.
AC3: durable KIND_REVIEWER_SESSION_LEASE shadow; orphaned_expired_superseded_head unlocks post-expiry acquisition without pre-expiry steal; cleanup needs owner-exit + affirmative safe worktree + controller auth + confirmation.
Review Metadata
No merge performed by this session.
repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #703
issue: #702
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 92535-f7537c169f8d
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr-703-rereview-20260713T224507
phase: released
candidate_head:
c2fc2683b9target_branch: master
target_branch_sha:
1eafb757a9last_activity: 2026-07-14T02:48:21Z
expires_at: 2026-07-14T04:48:21Z
blocker: manual-release
CTH: Cross-reference — merge remains blocked
Canonical forensic diagnosis recorded on Incident #700 comment 11489.
applied=true/last_terminal_pr=696/pr_merged=trueclaim is valid or asserted.Canonical Issue State
STATE:
blocked
WHO_IS_NEXT:
author
NEXT_ACTION:
See Incident #700 comment 11489; implement workflow repair before any merge reassessment of this PR.
NEXT_PROMPT:
WHAT_HAPPENED:
Reconciler posted durable diagnosis on #700 (comment 11489) and links it here; PR #703 stays open and unmerged.
WHY:
Lost cleanup provenance cannot authorize merge-path continuation.
RELATED_PRS:
PR #703 (this PR); Incident #700 comment 11489; PR #696 (merged)
BLOCKERS:
Merge blocked pending recovery. UNBLOCK CONDITION: workflow repair or newly sanctioned recovery mechanism is live; controller reassesses #703. See #700 comment 11489.
VALIDATION:
#700 comment 11489 read back (sysadmin, 2026-07-13T23:45:20-05:00); this PR open head c2fc268; review 433 APPROVED; no active #703 lease
LAST_UPDATED_BY:
sysadmin / prgs-reconciler
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.