fix(bootstrap): allow author worktree bootstrap from clean control checkout (Closes #892) #926
Merged
sysadmin
merged 1 commits from 2026-07-26 03:25:34 -05:00
fix/issue-892-author-bootstrap-deadlock 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#926
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
Breaks the author worktree bootstrap deadlock (#892) so an author session starting from a clean control checkout can obtain a usable
branches/worktree through the sanctioned MCP path.Root cause
assess_author_issue_bootstrapreturnedallowed/provenfor a clean control checkout, but the shared predicatebootstrap_permits_control_checkoutonly accepted create_issue assessments (task_scope=create_issue_only, emptyreasons, full base-tip field set). Author assessments never satisfied the predicate, so#274/#604guards kept the ordinary control-checkout block on everygitea_bootstrap_author_issue_worktreecall.Fix
author_issue_bootstrap.assess_author_issue_bootstrap— emit create_issue-compatible proof fields (task_scope=author_issue_bootstrap, emptyreasonswhen allowed,base_tips_verified, binding paths, strict tip proof).create_issue_bootstrap.bootstrap_permits_control_checkout— accepttask_scope=author_issue_bootstrapfor author bootstrap tasks (still fail-closed for cross-scope smuggling).tests/test_issue_892_author_bootstrap_deadlock.py.Files
author_issue_bootstrap.pycreate_issue_bootstrap.pytests/test_issue_892_author_bootstrap_deadlock.pyValidation
Worktree / proof
branches/fix-issue-892-author-bootstrap-deadlockfix/issue-892-author-bootstrap-deadlock2066623986df9a05c0f24bb760d7c0abb5bf0d9ejcwalker3/prgs-authorgitea_bootstrap_author_issue_worktreeis the primary path.Risk
Low — narrow waiver remains fail-closed (clean base, tip proof, binding match, empty refusal reasons). Does not widen create_issue scope.
Closes #892
Handoff
WHO_IS_NEXT: reviewer — independent review of PR; do not self-merge.
repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #926
issue: #892
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 45657-6b1b84aba2e2
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr926-issue-892-bootstrap
phase: claimed
candidate_head:
2066623986target_branch: master
target_branch_sha:
2b4e43042alast_activity: 2026-07-25T23:32:03Z
expires_at: 2026-07-25T23:42:03Z
blocker: none
repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #926
issue: #892
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 52497-a4b43ab643a5
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr926-issue-892-bootstrap
phase: claimed
candidate_head:
2066623986target_branch: master
target_branch_sha:
6a56260768last_activity: 2026-07-26T08:05:18Z
expires_at: 2026-07-26T08:15:18Z
blocker: none
repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #926
issue: #892
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 52497-df4ee80a7322
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr926-issue-892-bootstrap
phase: claimed
candidate_head:
2066623986target_branch: master
target_branch_sha:
6a56260768last_activity: 2026-07-26T08:16:07Z
expires_at: 2026-07-26T08:26:07Z
blocker: none
Canonical PR State
STATE: reviewed-approved
WHO_IS_NEXT: merger
NEXT_ACTION: Merge PR #926 into master from an independent prgs-merger session, then advance the control checkout and restart the MCP fleet.
NEXT_PROMPT:
WHAT_HAPPENED: Performed an independent review of PR #926 at head
2066623986in the bound review worktree branches/review-pr926-issue-892-bootstrap. Read issue #892, the complete three-file change set, the surrounding guard source, and the new tests. Confirmed the #892 deadlock is present at the base revision and resolved at this head, with every fail-closed protection preserved.WHY: The scope proof in create_issue_bootstrap.bootstrap_permits_control_checkout accepted only task_scope create_issue_only, while assess_author_issue_bootstrap emitted no task_scope key at all. The predicate therefore could never return True for an author bootstrap, even though the task gate above it already admitted the author task. This change completes that half-applied fix without widening any other proof obligation.
ISSUE: 892
HEAD_SHA:
2066623986REVIEW_STATUS: APPROVE
MERGE_READY: yes
BLOCKERS: none
VALIDATION: Focused suites at head (test_issue_892_author_bootstrap_deadlock.py, test_create_issue_bootstrap.py, test_issue_757_bootstrap_guard_agreement.py, test_author_issue_bootstrap.py) = 105 passed, 31 subtests. Broad regression over 33 bootstrap/worktree/guard/preflight suites, identical set at both revisions: base
2b4e430= 10 failed / 599 passed / 96 subtests; head2066623= 10 failed / 613 passed / 96 subtests. Delta is +14 passed, equal to the 14 new tests; zero new failures. The 10 failures share identical test IDs at both revisions, are pre-existing, and each passes when run alone.LAST_UPDATED_BY: sysadmin / prgs-reviewer
NATIVE_REVIEW_PROOF: transport=native_mcp; entrypoint=mcp_server; token_fingerprint=cb971ff277593f1b
Independence
Reviewer identity
sysadminon profileprgs-reviewer; PR author isjcwalker3. Distinct accounts, no self-review. Base branchmasterat6a56260768ad2f69b773a8b7ab8d460ce821c914; merge base2b4e43042a34f4e29617378ae79a7f5a3d312688.Scope
Exactly three files, merge base to head:
author_issue_bootstrap.py(+157 / −46)create_issue_bootstrap.py(+18 / −6)tests/test_issue_892_author_bootstrap_deadlock.py(+215, new)Both production modules are byte-identical between the merge base and the current
mastertip, so this analysis holds againstmasterand the merge is clean on the touched files. Nothing in the change touches role permissions, credential resolution, or process launching, and it adds no manual worktree or branch-creation bypass.Deadlock present at base, resolved at head
A single scenario matrix was evaluated read-only in the review worktree against both revisions.
2b4e4302066623FalseTrueTrueTrueFalseFalseFalseFalseFalseFalseFalseFalseFalseFalseFalseFalseFalseFalseFalseFalsebranches/worktreeFalseFalseFalseFalsecommit_files)FalseFalseFalseFalseFalseFalseallowed=Trueover a dirty treeFalseFalsebase_tips_verifiedover mismatched tipsFalseFalseExactly one behavior delta, A1. Every denial and every cross-scope or hand-built assertion is refused identically at both revisions.
Fix assessment
bootstrap_permits_control_checkoutnow applies the scope proof per task branch rather than as a widened disjunction: a create_issue task still requirescreate_issue_only, an author bootstrap task requiresauthor_issue_bootstrap, and a finalelsecloses unknown tasks. Both directions of cross-scope reuse fail closed (S1, S2). Every other obligation is unchanged and still applies to both branches —bootstrap_pathmust beclean_canonical_control_checkout,reasonsmust be empty,dirty_filesmust be empty,under_branchesmust be exactlyFalse, tip equality is re-derived rather than trusted from the assessment's own flag, and the assessment must bind to the exact workspace and canonical root.Ordinary author mutations stay blocked from the control checkout: the task gate admits only
bootstrap_author_issue_worktreeandgitea_bootstrap_author_issue_worktree, so every other author task leaves the ordinary block in force (D11).assess_author_issue_bootstrapnow produces the full predicate-compatible field set through one constructor.provenandbase_tips_verifiedare derived inside that constructor rather than accepted from callers, andtask_scopeis fixed toauthor_issue_bootstrap, so it cannot mint a create_issue-scoped assessment.The allowed path is strictly tighter than before. The prior logic compared tips only when both were present, so a missing local HEAD or a missing remote tip left
reasonsempty and yieldedallowed=Truewith no base-equivalence proof. The new logic fails closed on an unknown local HEAD, on a resolver error, and on a missing remote tip (D5, D6, D7), closing a pre-existing fail-open.The
under_branchesresult changed fromallowed=Truetonot_applicable=True. This is operationally inert: when the workspace is a validbranches/worktree the ordinary guard does not block and returns before the bootstrap assessment is consulted, and on the durable-block path the predicate refused it at both revisions, since the prior dict carried nounder_brancheskey and theis not Falsecheck rejected the resultingNone. The new shape simply states the intent correctly.Two-guard agreement from #757 is preserved:
anti_stomp_preflight.py:599routes the same threaded assessment through the same predicate under the same task name, so the #274 and #604 guards cannot diverge. The waiver stays narrow — only the wrong-worktree verdict is waived, while root-checkout, repo, role, stale-runtime and lease checks are each still evaluated.The #892 criterion that a refusal must name the missing precondition and the sanctioned call is met:
format_create_issue_bootstrap_erroratcreate_issue_bootstrap.py:322-330surfacesexact_next_action, and author block assessments populate it throughEXACT_NEXT_ACTION_AUTHOR_BOOTSTRAP.Non-blocking findings
tests/test_issue_892_author_bootstrap_deadlock.py:151-211—TestAuthorBootstrapPreflightIntegration.test_enforce_branches_only_allows_clean_control_for_bootstrapis described as exercising the real enforcer wiring and binds the server module assrvat line 156, but never callssrv._enforce_branches_only_author_mutation. Thedurable_blockdict built at line 192 is passed to nothing, and the assertion at line 211 holds by construction. The branch at lines 200-208 reduces to the assertion already made at line 113. The net effect is a duplicate unit assertion under an integration name, and no test drives_enforce_branches_only_author_mutationwith an author bootstrap task —test_issue_757_bootstrap_guard_agreement.py:349reaches the real enforcer but only for create_issue tasks. A follow-up should cover that path end to end. Not a blocker here: the enforcer-to-predicate wiring is pre-existing and untouched by this change, and the predicate behavior is established above.tests/test_issue_892_author_bootstrap_deadlock.py:19— theunittest.mockbinding is unused, as is the server-module binding at line 156.create_issue_bootstrap.py:328— author bootstrap refusals carry the prefixCreate-issue bootstrap guard (#749):even when the task is the author bootstrap. The text is correct and actionable; only the guard named in the label is wrong.None of these changes production behavior or the correctness of the fix.
Note for the merger
This branch trails
master, but neither production module it edits has changed onmastersince the merge base, and Gitea reportsmergeable: true. After the merge, advance the control checkout and restart the MCP fleet so the daemons load this fix before the author bootstrap path is exercised. Issue #931 remains unclaimed and can be re-allocated once that is done.repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #926
issue: #892
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 52497-df4ee80a7322
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr926-issue-892-bootstrap
phase: released
candidate_head:
2066623986target_branch: master
target_branch_sha:
6a56260768last_activity: 2026-07-26T08:19:56Z
expires_at: 2026-07-26T08:29:56Z
blocker: manual-release
repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #926
issue: #892
reviewer_identity: sysadmin
profile: prgs-merger
session_id: 52586-294892e2f1d7
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr926-issue-892-bootstrap
phase: claimed
candidate_head:
2066623986target_branch: master
target_branch_sha:
6a56260768last_activity: 2026-07-26T08:24:54Z
expires_at: 2026-07-26T08:34:54Z
blocker: none
Stale #332 review-decision lock cleanup (#594)
Status: APPLIED
sysadminprgs-merger2026-07-26T08:25:36.220396+00:00approveon PR fix(bootstrap): allow author worktree bootstrap from clean control checkout (Closes #892) (#926)closed(merged=True)8c1d22a658ecb5715e3f4db6eb7ebb408830c1011prgs-reviewerManual deletion of session-state files is not the workflow.
This path only clears a lock when the referenced PR is merged/closed.
finalized_at: 2026-07-26T08:26:31Z
finalized_by_identity: sysadmin
finalized_by_profile: prgs-merger
finalized_by_session_id: 52586-294892e2f1d7
finalization_outcome: released
finalization_reason: PR #926 merged successfully at 2066623986df9a05c0f24bb760d7c0abb5bf0d9e; merge commit
8c1d22a658finalized_lease_comment_id: 17362
repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #926
issue: #892
reviewer_identity: sysadmin
profile: prgs-merger
session_id: 52586-294892e2f1d7
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr926-issue-892-bootstrap
phase: released
candidate_head:
2066623986target_branch: master
target_branch_sha:
6a56260768last_activity: 2026-07-26T08:26:31Z
expires_at: 2026-07-26T08:36:31Z
blocker: PR #926 merged successfully at 2066623986df9a05c0f24bb760d7c0abb5bf0d9e; merge commit
8c1d22a658