feat: add own-branch lock adoption recovery to gitea_lock_issue (Closes #442) #461
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#461
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 #442. Adds a non-destructive own-branch adoption path to
gitea_lock_issueso an issue's exact pushed branch can be reacquired after in-memory lock loss (e.g. MCP restart) without treating it as #400 duplicate competing work.Changes
issue_lock_adoption.py— pure adoption decision (assess_own_branch_adoption): ADOPT exact branch, BLOCK competing same-issue branches, NO_MATCH for normal lock pathgitea_mcp_server.py— wire adoption intogitea_lock_issuewith open-PR, competing-lock, capability, and worktree safety gates; return adoption proof fieldstests/test_issue_lock_adoption.py— 8 unit cases for adoption outcomes and prooftests/test_mcp_server.py— MCP-level adoption, blockers, and post-adoptiongitea_create_preligibilityBehavior
branch_nameexactly matches the only remote branch carryingissue-<n>Verification
Worktree
branches/issue-442-lock-adoption@f64fa70REQUEST CHANGES — reviewer sysadmin/prgs-reviewer (not author). Reviewed head
f64fa70in isolated worktreebranches/review-pr461(clean before + after; no local edits). Tests green:tests/test_issue_lock_adoption.py+tests/test_mcp_server.py→ 200 passed.The core adoption logic is correct (exact-branch ADOPT, fail-closed BLOCK on competing, NO_MATCH passthrough) and well-tested. One blocking correctness defect:
Substring-collision false-block in
assess_own_branch_adoption(issue_lock_adoption.py).marker = f"issue-{issue_number}"; if marker in namematches by raw substring, so a lower-numbered issue whose marker is a numeric prefix of a higher-numbered issue's branch is mis-classified as competing.Reproduced against this head:
Expected: ADOPT #42's own branch. Instead the unrelated #420 branch leaks in via substring and false-blocks a legitimate own-branch lock/recovery — defeating the PR's recovery purpose. Real collisions in this repo: #40↔#400–409, #42↔#420–429, #43↔#430–436, #46↔#460.
This also directly violates AC6 of the umbrella #440 ("Duplicate branch detection must not rely only on broad substring matching like
issue-420; use structured issue/branch ownership evidence"). Since this PR rewrites exactly that detection block, the fix belongs here.Suggested fix (small): require a word boundary after the number, e.g. match
rf"(?:^|/)issue-{issue_number}(?![0-9])"against the branch name (or parse the structured issue number from the branch and compare equality). Add a regression test for the #42-vs-#420 collision (both BLOCK and ADOPT paths).Everything else looks good; re-request review after the matcher is boundary-safe. Not merging.
f64fa703c2to04a2bf406304a2bf4063toab4af23afdrepo: Scaled-Tech-Consulting/Gitea-Tools
pr: #461
issue: none
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 41033-97b298b26d57
worktree: branches/review-feat-issue-442-lock-adoption
phase: claimed
candidate_head:
ab4af23afdtarget_branch: master
target_branch_sha: none
last_activity: 2026-07-07T21:53:00Z
expires_at: 2026-07-07T23:53:00Z
blocker: none
Independent audit — REQUEST CHANGES (rebase required)
Auditor:
sysadmin/prgs-reviewer(not PR authorjcwalker3).Pinned HEAD:
ab4af23afd51f392b3c7e72d9a62a08ec017501dWorktree + Cleanliness
git statusclean before and after running tests.Findings
assess_own_branch_adoptionand added unit tests.f061fee).pytest) reveals 3 regression failures intests/test_commit_files_gate.pydue to refactoring mismatches with master.Required Action
Please rebase this PR branch onto the current master (post-PR #449 / post-PR #462) to align the test harnesses and verify that the full test suite passes cleanly.
repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #461
issue: #442
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 41033-97b298b26d57
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr461
phase: claimed
candidate_head:
ab4af23afdtarget_branch: master
target_branch_sha:
f51dc95153last_activity: 2026-07-07T21:57:25Z
expires_at: 2026-07-07T23:57:25Z
blocker: none
APPROVE — re-review at head
ab4af23(fresh detached worktree, clean before/after).Prior REQUEST_CHANGES (substring collision) is RESOLVED.
issue_lock_adoption.py::_branch_carries_issue_markernow uses a boundary-aware regex(?:^|/)issue-{n}(?![0-9]). Verified against exact cases:Adoption behavior preserved and fail-closed: ADOPT only the exact requested branch; BLOCK_COMPETING when any non-requested same-issue branch exists (ownership ambiguous); NO_MATCH → normal lock path. Matcher is stricter than before, so lock safety is not weakened.
No unsafe additions: diff scan found no branch deletion, force-push recovery, raw POST/DELETE API fallback, or manual lock-file seeding. Adoption wiring gates on open-PR + competing-lock + capability + worktree checks and records adoption proof.
Validation at
ab4af23:Scope matches #442 (issue_lock_adoption.py +156, gitea_mcp_server.py +53, tests). No scope creep beyond adoption + tests.
Note: PR is behind current master but Gitea reports mergeable=true (no conflicts). A merge session must re-pin the head and confirm mergeable at merge time. Land in child-stack order relative to #465 (#443) per current dependency reality.
repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #461
issue: #442
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 41033-97b298b26d57
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr461
phase: claimed
candidate_head:
ab4af23afdtarget_branch: master
target_branch_sha:
f51dc95153last_activity: 2026-07-07T21:57:59Z
expires_at: 2026-07-07T23:57:59Z
blocker: none
APPROVE — re-review after substring-collision fix (sysadmin/prgs-reviewer, not author).
Pinned head:
ab4af23afd51f392b3c7e72d9a62a08ec017501d(unchanged through validation). Prior REQUEST_CHANGES atf64fa70is superseded.Substring-collision verdict: FIXED.
_branch_carries_issue_markernow uses(?:^|/)issue-{n}(?![0-9]). Repro from prior review (#42 vs #420) now ADOPTs correctly; unrelated higher-number branches are ignored. Hermetic tests added:test_higher_issue_number_branch_does_not_block_lower_issue_adoption,test_unrelated_higher_number_branch_is_ignored_without_own_branch.Safety unchanged: exact-branch ADOPT only; competing same-issue branches still fail-closed; no branch deletion/force-push/manual lock seeding introduced.
Validated in
branches/review-pr461@ab4af23(clean before/after). Not merging.repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #461
issue: none
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 41033-97b298b26d57
worktree: branches/review-feat-issue-442-lock-adoption
phase: claimed
candidate_head:
ab4af23afdtarget_branch: master
target_branch_sha: none
last_activity: 2026-07-07T22:01:17Z
expires_at: 2026-07-08T00:01:17Z
blocker: none
Independent audit — APPROVE
Auditor:
sysadmin/prgs-reviewer(not PR authorjcwalker3).Pinned HEAD:
ab4af23afd51f392b3c7e72d9a62a08ec017501dWorktree + Cleanliness
git statusclean before and after running tests.Verification & Tests
pytest tests/test_issue_lock_adoption.py -q-> 9 passed.pytest tests/test_issue_lock_worktree.py -q-> 12 passed.git diff --checkpassed against master.Findings
assess_own_branch_adoptionand added unit tests.repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #461
issue: none
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 41033-97b298b26d57
worktree: branches/review-feat-issue-442-lock-adoption
phase: claimed
candidate_head:
ab4af23afdtarget_branch: master
target_branch_sha: none
last_activity: 2026-07-07T22:01:49Z
expires_at: 2026-07-08T00:01:49Z
blocker: none
ab4af23afdto85532059e2APPROVE — reviewer sysadmin/prgs-reviewer (not author jcwalker3). Fresh review at pinned head
85532059(rebased onto post-#465 master54a75153), in isolated worktreebranches/review-pr461-fresh(clean before + after; no local edits). Supersedes the staleab4af23approvals.Residual diff vs master (post-#465):
issue_lock_adoption.py(+48),tests/test_issue_lock_adoption.py(+72) — the bulk of adoption landed with #465; #461 now adds only the boundary-safe matcher + tests. Scope matches #442.Substring-collision blocker: FIXED.
_branch_carries_issue_markerusesrf"(?:^|/)issue-{int(issue_number)}(?![0-9])"(anchored at start//, digit-terminated). Verified:issue-442matchesfeat/issue-442-lock-adoptionandfeat/issue-442; does NOT matchissue-44,issue-1442,issue-4420; reverse#44does not matchfeat/issue-442-*. The original #42-vs-#420 false-block is resolved.Safety preserved (stricter, not weaker): ADOPT only the exact requested branch; BLOCK_COMPETING fail-closed on any non-requested same-issue branch (ownership ambiguous); NO_MATCH → normal lock path. Diff scan found no branch deletion, force-push, raw POST/DELETE API fallback, or manual lock-file seeding.
Validation at
85532059:On current master, mergeable=true, no unresolved REQUEST_CHANGES. Ready. Not merging (separate merge session must re-pin
85532059and confirm this approval binds to it).repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #461
issue: #442
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 41033-97b298b26d57
worktree: branches/review-pr461-issue-442-lock-adoption
phase: claimed
candidate_head:
85532059e2target_branch: master
target_branch_sha:
54a75153a9last_activity: 2026-07-07T22:15:45Z
expires_at: 2026-07-08T00:15:45Z
blocker: none
Fresh review at rebased head
85532059e277c397feddee8dc959693fddf60a02Stale prior approval at
ab4af23superseded by rebase onto master (54a7515, #465/#443 keyed lock store landed).Preflight
master@54a7515(matchesprgs/master)sysadmin/prgs-reviewer(gitea_whoami)review_prallowed (gitea.pr.review)jcwalker3)85532059e277c397feddee8dc959693fddf60a02— exact matchScope reviewed (2 files vs master)
issue_lock_adoption.pytests/test_issue_lock_adoption.pySubstring-collision verdict
_branch_carries_issue_markerreplaces naiveissue-<n> in namewith boundary-aware regex(?:^|/)issue-<n>(?![0-9]).Verified:
feat/issue-442-*issue-44,issue-1442, orissue-4420issue-442branchesAdoption outcomes preserved: ADOPT exact own branch, BLOCK competing, NO_MATCH unrelated.
Safety / compatibility
gitea_lock_issuestill uses keyedbind_session_lock(#443 foundation); adoption decision remains pure/side-effect-freeTests
pytest tests/test_issue_lock_adoption.py tests/test_issue_lock_worktree.py -q→ 21 passedpytest tests/test_mcp_server.py -k "adopt or lock_issue"→ 8 passedgit diff --check→ cleanDecision: APPROVE — rebase preserves own-branch adoption behavior and fixes issue-number substring collisions without regressing lock safety.
Merge session may proceed at head
85532059e277c397feddee8dc959693fddf60a02.repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #461
issue: none
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 41033-97b298b26d57
worktree: branches/review-feat-issue-442-lock-adoption
phase: claimed
candidate_head:
85532059e2target_branch: master
target_branch_sha: none
last_activity: 2026-07-07T22:16:30Z
expires_at: 2026-07-08T00:16:30Z
blocker: none