fix(author): prevent bootstrap lock-provenance dead ends before PR creation #953

Closed
opened 2026-07-27 22:48:51 -05:00 by jcwalker3 · 2 comments
Owner

Related: #850, #887, #890, #891, #892, #442, #447, #760, #790, #947

Problem

gitea_bootstrap_author_issue_worktree creates an issue lock whose schema no downstream author operation accepts, and the shape cannot be upgraded once the author follows the tool's own reported next action. A sanctioned author cycle that starts with bootstrap therefore reaches a state where the pull request can never be created and no sanctioned recovery path is eligible.

Only gitea_lock_issue writes the canonical lock fields. Bootstrap writes a different, thinner record and then directs the author straight to implementation.

Trigger

Observed during the sanctioned implementation of issue #949:

  1. gitea_bootstrap_author_issue_worktree created the issue branch, the registered worktree, and the lock, reporting branch_created: true, worktree_registered: true, lock_created: true.
  2. The resulting lock recorded:
    • claimant at the top level (username, profile)
    • lease_id: null
    • no canonical work_lease
    • no acceptable lock_provenance
    • no usable expires_at
  3. Bootstrap's reported exact_next_action directed the author to call gitea_whoami, then gitea_resolve_task_capability(task='work_issue'), and "proceed with author implementation in the bootstrapped worktree". It did not direct the author to call gitea_lock_issue.
  4. The author implemented, committed, and pushed the branch.
  5. gitea_create_pr then rejected the lock:
Issue lock provenance guard (#447): issue lock file lacks sanctioned lock_provenance;
manual seeding is not a normal recovery path — call gitea_lock_issue or use #442
adoption (fail closed)

Unrecoverable state

Every sanctioned recovery path was then simultaneously unavailable. Each gate is individually correct; the combination is the defect.

Path Refusal Cause
gitea_heartbeat_issue_lock lock does not record both a claimant username and profile reads the claimant from work_lease.claimant; bootstrap wrote it at the lock top level
gitea_lock_issue issue lock worktree must be base-equivalent to one of dev/main/master before implementation work correct: the branch now carries the committed work
Exact-owner renewal (#760) not evaluated requires an expired lease; the waiver that exists precisely for a branch carrying commits never engages
Expiration contract is_lease_expired returns False when no expires_at is recorded, so a bootstrap lock is treated as never expiring and therefore never renewable
gitea_create_pr #447 provenance guard requires lock_provenance and work_lease

Net effect: the lock cannot be heartbeated, renewed, re-locked, upgraded, or accepted by create_pr.

No workaround was applied. The lock file was not hand-edited, the branch pointer was not moved or rewound to satisfy base-equivalence, and no fallback transport was used.

Current reproduction

Dimension Value
Issue #949
Branch feat/issue-949-native-fleet-inventory (published)
Registered worktree branches/issue-949-fleet-inventory
Head 92615f474bf6652d4e9ea59af7fd0dba03b56544
Base master at 82d71b77028a7abd4f8ab4a4e4d89658a187f73d
Bootstrap owner session author_issue_work-9713b9c3ed2c4a48
Lock generation 1
Claimant jcwalker3 / prgs-author
Lease ID null
Worktree state clean, on the branch, local head equals remote head
Pull request not created
Failure gitea_create_pr fail-closed on the issue-lock provenance guard

The #949 implementation itself is complete and published; only the pull request is blocked. Treat source line numbers observed during diagnosis as provisional and re-verify them during implementation.

Required behavior

Bootstrap and ordinary lock acquisition must produce one compatible canonical lock contract.

A successful bootstrap must either:

  1. Create a lock immediately usable by heartbeat, renewal, commit/push, and create_pr; or
  2. Require and advertise a sanctioned lock-finalization step before implementation begins.

It must never direct an author to make commits when following that direction will make every sanctioned recovery path ineligible.

The fix must also provide a safe, sanctioned recovery path for existing incomplete bootstrap locks whose branches already contain legitimate pushed commits.

Acceptance criteria

  1. Bootstrap-created locks use the canonical claimant, work_lease, provenance, generation, and expiration schema required by downstream operations.
  2. A freshly bootstrapped lock can be heartbeated immediately.
  3. The exact owner can renew it both before and after the issue branch contains commits.
  4. create_pr accepts valid bootstrap provenance after sanctioned commit and push operations.
  5. Bootstrap's exact_next_action is executable under the state bootstrap actually returned.
  6. No successful bootstrap returns lease_id=null when the canonical workflow requires a workflow lease.
  7. Partial lock creation fails closed before implementation begins and names the missing fields.
  8. Existing incomplete bootstrap locks can be inspected and upgraded or recovered through a target-specific sanctioned operation.
  9. Recovery works when the branch already contains legitimate commits, and must not require rewinding it to the base revision.
  10. Recovery verifies repository, issue, claimant, profile, identity, session ownership, branch, worktree, and head before changing lock state.
  11. Recovery cannot take over a healthy foreign-owned lock.
  12. Missing expiration is represented explicitly; it cannot make a malformed lock permanently non-expiring and non-renewable.
  13. Heartbeat, renewal, lock acquisition, bootstrap, and create_pr consume compatible claimant and provenance shapes.
  14. Legacy lock compatibility is explicit and tested.
  15. A failed bootstrap cannot strand a branch or worktree without a structured recovery recommendation.
  16. Read-only inspection performs no lock, lease, branch, worktree, issue, or PR mutation.
  17. Tests reproduce the exact #949 sequence: bootstrap → implement → commit → push → create PR.
  18. The regression test proves that sequence completes without manual lock edits or fallback transport.
  19. Tests cover malformed, partial, expired, healthy same-owner, healthy foreign-owner, committed-branch, and legacy bootstrap locks.
  20. Canonical workflow documentation defines the required ordering and the recovery path.

Safety requirements

  • Do not weaken the #447 create-PR provenance guard.
  • Do not allow caller-supplied provenance to bypass validation.
  • Do not treat a matching username alone as proof of lock ownership.
  • Do not permit foreign-lock takeover through the legacy recovery path.
  • Do not move or reset a committed branch merely to satisfy base-equivalence.
  • Preserve auditable generation and ownership transitions.
  • Recovery must affect only the exact target lock.
  • Do not automatically create a pull request as part of lock repair.
  • Keep issues #950, #951, and #952 outside this issue's implementation scope.

Non-goals

  • Implementing issue #949.
  • Altering the code already pushed for #949.
  • Creating the #949 pull request as part of this issue.
  • Weakening workflow ownership or provenance enforcement.
  • General stale-lease cleanup.
  • Fleet inventory, restart receipts, role alignment, or lease-dashboard consistency.
  • Restarting or reconciling the MCP fleet.

Duplicate verdict

NOT a duplicate. Searched all 400 open and closed issue titles for lock, lease, bootstrap, provenance, claimant, worktree, author, renew, heartbeat, adopt, recover, expire, and create-PR terms, yielding 169 title candidates, and read the bodies of the closest.

Issue State Why it does not cover this
#850 closed Added the bootstrap tool. Its AC1 targets an "issue-lock-ready state", i.e. a worktree eligible for a later gitea_lock_issue call. It does not specify the lock record bootstrap itself writes, and nothing in it addresses the downstream provenance, heartbeat, or renewal contracts.
#892 closed Bootstrap could not produce a worktree at all (the #618 wall). This issue is the opposite failure: bootstrap succeeds and produces an unusable lock.
#890 open Unifies competing ownership stores that contradict each other, plus a fenced recover_author_ownership entry point. Here the stores do not disagree; a single lock is well-formed for its writer and malformed for every reader. Does not name lock_provenance, work_lease, or the create_pr guard.
#891 open Atomic finalization transaction over publish, PR creation, handoff, and lease retirement. It notes that the base-equivalent lock cannot be reused after the branch advances, but assumes a valid lock produced by gitea_lock_issue. It neither corrects the bootstrap lock schema nor recovers already-created incomplete bootstrap locks.
#887 open Parent epic for author transactionality. This is a concrete, reproducible child defect with its own acceptance criteria, not the epic.
#947 open Same shape — a sanctioned capability succeeds and the next gate refuses for want of evidence — but scoped to gitea_rebind_dirty_same_claimant_author_session and dirty-worktree owning-PR continuation. Its non-goals explicitly preserve the clean-worktree requirements of renewal and dead-session recovery. Never mentions bootstrap, provenance, or the create-PR guard.
#440 closed Recovery after a lock was lost (server restart wiped it) with the branch already pushed. Here the lock is present and malformed, which is a different root cause and reaches a different guard.
#442 / #447 / #760 closed The own-branch adoption path, the provenance guard, and exact-owner renewal respectively. Each is a component this defect traverses; none covers their interaction with a bootstrap-written lock.
#792 / #793 open Terminal lease retirement and lease fencing slices of #790. Neither concerns the lock schema bootstrap writes nor create-PR eligibility.

No single existing issue covers both future bootstrap correctness and recovery of already-created incomplete bootstrap locks.

Canonical issue state

STATE: ready-for-author
WHO_IS_NEXT: author
NEXT_ACTION: Unify the bootstrap and lock_issue lock contracts, add a sanctioned upgrade or recovery operation for existing incomplete bootstrap locks whose branches already carry pushed commits, and add the end-to-end regression that reproduces the #949 bootstrap-to-create-PR sequence
NEXT_PROMPT:
Role: AUTHOR
Repo: prgs / Scaled-Tech-Consulting / Gitea-Tools
Issue: this issue

1. Native MCP only; gitea_whoami + gitea_resolve_task_capability(work_issue) on prgs-author; bind an issue-backed worktree under branches/ and finalize the lock before writing any implementation bytes.
2. Make gitea_bootstrap_author_issue_worktree and gitea_lock_issue produce one canonical lock contract covering claimant shape, work_lease, lock_provenance, generation, and expiration.
3. Either have bootstrap emit an immediately usable lock, or have it fail closed and advertise the required lock-finalization call before implementation begins.
4. Add a sanctioned inspection and upgrade or recovery operation for existing incomplete bootstrap locks, including the case where the branch already carries legitimate pushed commits, without rewinding the branch.
5. Add regression coverage for the exact bootstrap to implement to commit to push to create-PR sequence, plus malformed, partial, expired, same-owner, foreign-owner, committed-branch, and legacy lock cases.
6. Update the canonical workflow documentation with the required ordering and the recovery path.
7. Open one PR with Closes; stop; hand off to an independent reviewer.
Related: #850, #887, #890, #891, #892, #442, #447, #760, #790, #947 ## Problem `gitea_bootstrap_author_issue_worktree` creates an issue lock whose schema no downstream author operation accepts, and the shape cannot be upgraded once the author follows the tool's own reported next action. A sanctioned author cycle that starts with bootstrap therefore reaches a state where the pull request can never be created and no sanctioned recovery path is eligible. Only `gitea_lock_issue` writes the canonical lock fields. Bootstrap writes a different, thinner record and then directs the author straight to implementation. ## Trigger Observed during the sanctioned implementation of issue #949: 1. `gitea_bootstrap_author_issue_worktree` created the issue branch, the registered worktree, and the lock, reporting `branch_created: true`, `worktree_registered: true`, `lock_created: true`. 2. The resulting lock recorded: * `claimant` at the **top level** (`username`, `profile`) * `lease_id: null` * **no** canonical `work_lease` * **no** acceptable `lock_provenance` * **no** usable `expires_at` 3. Bootstrap's reported `exact_next_action` directed the author to call `gitea_whoami`, then `gitea_resolve_task_capability(task='work_issue')`, and "proceed with author implementation in the bootstrapped worktree". It did not direct the author to call `gitea_lock_issue`. 4. The author implemented, committed, and pushed the branch. 5. `gitea_create_pr` then rejected the lock: ```text Issue lock provenance guard (#447): issue lock file lacks sanctioned lock_provenance; manual seeding is not a normal recovery path — call gitea_lock_issue or use #442 adoption (fail closed) ``` ## Unrecoverable state Every sanctioned recovery path was then simultaneously unavailable. Each gate is individually correct; the combination is the defect. | Path | Refusal | Cause | | --- | --- | --- | | `gitea_heartbeat_issue_lock` | `lock does not record both a claimant username and profile` | reads the claimant from `work_lease.claimant`; bootstrap wrote it at the lock top level | | `gitea_lock_issue` | `issue lock worktree must be base-equivalent to one of dev/main/master before implementation work` | correct: the branch now carries the committed work | | Exact-owner renewal (#760) | not evaluated | requires an **expired** lease; the waiver that exists precisely for a branch carrying commits never engages | | Expiration contract | — | `is_lease_expired` returns `False` when no `expires_at` is recorded, so a bootstrap lock is treated as **never expiring** and therefore never renewable | | `gitea_create_pr` | #447 provenance guard | requires `lock_provenance` **and** `work_lease` | Net effect: the lock cannot be heartbeated, renewed, re-locked, upgraded, or accepted by `create_pr`. No workaround was applied. The lock file was not hand-edited, the branch pointer was not moved or rewound to satisfy base-equivalence, and no fallback transport was used. ## Current reproduction | Dimension | Value | | --- | --- | | Issue | #949 | | Branch | `feat/issue-949-native-fleet-inventory` (published) | | Registered worktree | `branches/issue-949-fleet-inventory` | | Head | `92615f474bf6652d4e9ea59af7fd0dba03b56544` | | Base | `master` at `82d71b77028a7abd4f8ab4a4e4d89658a187f73d` | | Bootstrap owner session | `author_issue_work-9713b9c3ed2c4a48` | | Lock generation | `1` | | Claimant | `jcwalker3` / `prgs-author` | | Lease ID | `null` | | Worktree state | clean, on the branch, local head equals remote head | | Pull request | not created | | Failure | `gitea_create_pr` fail-closed on the issue-lock provenance guard | The #949 implementation itself is complete and published; only the pull request is blocked. Treat source line numbers observed during diagnosis as provisional and re-verify them during implementation. ## Required behavior Bootstrap and ordinary lock acquisition must produce **one compatible canonical lock contract**. A successful bootstrap must either: 1. Create a lock immediately usable by heartbeat, renewal, commit/push, and `create_pr`; or 2. Require and advertise a sanctioned lock-finalization step **before** implementation begins. It must never direct an author to make commits when following that direction will make every sanctioned recovery path ineligible. The fix must also provide a safe, sanctioned recovery path for **existing** incomplete bootstrap locks whose branches already contain legitimate pushed commits. ## Acceptance criteria 1. Bootstrap-created locks use the canonical claimant, `work_lease`, provenance, generation, and expiration schema required by downstream operations. 2. A freshly bootstrapped lock can be heartbeated immediately. 3. The exact owner can renew it both before and after the issue branch contains commits. 4. `create_pr` accepts valid bootstrap provenance after sanctioned commit and push operations. 5. Bootstrap's `exact_next_action` is executable under the state bootstrap actually returned. 6. No successful bootstrap returns `lease_id=null` when the canonical workflow requires a workflow lease. 7. Partial lock creation fails closed **before** implementation begins and names the missing fields. 8. Existing incomplete bootstrap locks can be inspected and upgraded or recovered through a target-specific sanctioned operation. 9. Recovery works when the branch already contains legitimate commits, and must not require rewinding it to the base revision. 10. Recovery verifies repository, issue, claimant, profile, identity, session ownership, branch, worktree, and head before changing lock state. 11. Recovery cannot take over a healthy foreign-owned lock. 12. Missing expiration is represented explicitly; it cannot make a malformed lock permanently non-expiring and non-renewable. 13. Heartbeat, renewal, lock acquisition, bootstrap, and `create_pr` consume compatible claimant and provenance shapes. 14. Legacy lock compatibility is explicit and tested. 15. A failed bootstrap cannot strand a branch or worktree without a structured recovery recommendation. 16. Read-only inspection performs no lock, lease, branch, worktree, issue, or PR mutation. 17. Tests reproduce the exact #949 sequence: bootstrap → implement → commit → push → create PR. 18. The regression test proves that sequence completes without manual lock edits or fallback transport. 19. Tests cover malformed, partial, expired, healthy same-owner, healthy foreign-owner, committed-branch, and legacy bootstrap locks. 20. Canonical workflow documentation defines the required ordering and the recovery path. ## Safety requirements * Do not weaken the #447 create-PR provenance guard. * Do not allow caller-supplied provenance to bypass validation. * Do not treat a matching username alone as proof of lock ownership. * Do not permit foreign-lock takeover through the legacy recovery path. * Do not move or reset a committed branch merely to satisfy base-equivalence. * Preserve auditable generation and ownership transitions. * Recovery must affect only the exact target lock. * Do not automatically create a pull request as part of lock repair. * Keep issues #950, #951, and #952 outside this issue's implementation scope. ## Non-goals * Implementing issue #949. * Altering the code already pushed for #949. * Creating the #949 pull request as part of this issue. * Weakening workflow ownership or provenance enforcement. * General stale-lease cleanup. * Fleet inventory, restart receipts, role alignment, or lease-dashboard consistency. * Restarting or reconciling the MCP fleet. ## Duplicate verdict NOT a duplicate. Searched all 400 open and closed issue titles for lock, lease, bootstrap, provenance, claimant, worktree, author, renew, heartbeat, adopt, recover, expire, and create-PR terms, yielding 169 title candidates, and read the bodies of the closest. | Issue | State | Why it does not cover this | | --- | --- | --- | | #850 | closed | Added the bootstrap tool. Its AC1 targets an "issue-lock-ready state", i.e. a worktree eligible for a later `gitea_lock_issue` call. It does not specify the lock record bootstrap itself writes, and nothing in it addresses the downstream provenance, heartbeat, or renewal contracts. | | #892 | closed | Bootstrap could not produce a worktree **at all** (the #618 wall). This issue is the opposite failure: bootstrap **succeeds** and produces an unusable lock. | | #890 | open | Unifies competing ownership **stores** that contradict each other, plus a fenced `recover_author_ownership` entry point. Here the stores do not disagree; a single lock is well-formed for its writer and malformed for every reader. Does not name `lock_provenance`, `work_lease`, or the `create_pr` guard. | | #891 | open | Atomic finalization transaction over publish, PR creation, handoff, and lease retirement. It notes that the base-equivalent lock cannot be reused after the branch advances, but assumes a **valid** lock produced by `gitea_lock_issue`. It neither corrects the bootstrap lock schema nor recovers already-created incomplete bootstrap locks. | | #887 | open | Parent epic for author transactionality. This is a concrete, reproducible child defect with its own acceptance criteria, not the epic. | | #947 | open | Same *shape* — a sanctioned capability succeeds and the next gate refuses for want of evidence — but scoped to `gitea_rebind_dirty_same_claimant_author_session` and dirty-worktree owning-PR continuation. Its non-goals explicitly preserve the clean-worktree requirements of renewal and dead-session recovery. Never mentions bootstrap, provenance, or the create-PR guard. | | #440 | closed | Recovery after a lock was **lost** (server restart wiped it) with the branch already pushed. Here the lock is **present and malformed**, which is a different root cause and reaches a different guard. | | #442 / #447 / #760 | closed | The own-branch adoption path, the provenance guard, and exact-owner renewal respectively. Each is a component this defect traverses; none covers their interaction with a bootstrap-written lock. | | #792 / #793 | open | Terminal lease retirement and lease fencing slices of #790. Neither concerns the lock schema bootstrap writes nor create-PR eligibility. | No single existing issue covers both future bootstrap correctness and recovery of already-created incomplete bootstrap locks. ## Canonical issue state ```text STATE: ready-for-author WHO_IS_NEXT: author NEXT_ACTION: Unify the bootstrap and lock_issue lock contracts, add a sanctioned upgrade or recovery operation for existing incomplete bootstrap locks whose branches already carry pushed commits, and add the end-to-end regression that reproduces the #949 bootstrap-to-create-PR sequence NEXT_PROMPT: Role: AUTHOR Repo: prgs / Scaled-Tech-Consulting / Gitea-Tools Issue: this issue 1. Native MCP only; gitea_whoami + gitea_resolve_task_capability(work_issue) on prgs-author; bind an issue-backed worktree under branches/ and finalize the lock before writing any implementation bytes. 2. Make gitea_bootstrap_author_issue_worktree and gitea_lock_issue produce one canonical lock contract covering claimant shape, work_lease, lock_provenance, generation, and expiration. 3. Either have bootstrap emit an immediately usable lock, or have it fail closed and advertise the required lock-finalization call before implementation begins. 4. Add a sanctioned inspection and upgrade or recovery operation for existing incomplete bootstrap locks, including the case where the branch already carries legitimate pushed commits, without rewinding the branch. 5. Add regression coverage for the exact bootstrap to implement to commit to push to create-PR sequence, plus malformed, partial, expired, same-owner, foreign-owner, committed-branch, and legacy lock cases. 6. Update the canonical workflow documentation with the required ordering and the recovery path. 7. Open one PR with Closes; stop; hand off to an independent reviewer. ```
Author
Owner

[THREAD STATE LEDGER] Issue #953 — author implementation plan published; lock finalized before divergence

What is true now:

  • Issue state: open and claimed by this author session
  • Branch: fix/issue-953-bootstrap-lock-provenance
  • Worktree: branches/issue-953-bootstrap-lock-provenance
  • Pinned base SHA: 82d71b7702
  • Server-side decision state: no review or merge decision exists; no pull request has been created for this issue
  • Local verdict/state: canonical author issue lock held at generation 3, heartbeat verified, implementation not yet written
  • Latest known validation: bootstrap lock read back as incomplete, then finalized and heartbeated successfully

What changed:

  • Bootstrap created the issue branch, the registered worktree, and an incomplete lock
  • gitea_lock_issue finalized that same lock to the canonical contract before any implementation byte was written
  • gitea_heartbeat_issue_lock succeeded against that exact lock with no ownership change and no second lock

What is blocked:

  • Blocker classification: no blocker

Who/what acts next:

  • Next actor: author
  • Required action: implement the canonical bootstrap and lock contract, add target-specific recovery and read-only inspection, add the regression suite against isolated fixtures, update the author workflow documentation, then open exactly one pull request
  • Do not do: do not recover, heartbeat, renew, or retry issue #949, do not modify issues #950 through #952, do not modify the PR #906 lease, do not review or merge the pull request this issue produces
  • Resume from: this plan comment and the canonical lock for issue #953

Author implementation plan

Ownership was established without reproducing the dead end. Bootstrap ran, then the lock was finalized by gitea_lock_issue before any implementation bytes were written, which is the ordering this issue's own NEXT_PROMPT step 1 prescribes.

Dimension Value
Branch fix/issue-953-bootstrap-lock-provenance
Worktree branches/issue-953-bootstrap-lock-provenance
Pinned base 82d71b7702
Lock generation 1 at bootstrap, then 2 at gitea_lock_issue, then 3 at heartbeat
Task session author_issue_work-af66d20143e04ee5

Defect verified against the pinned base rather than the issue's line numbers

  1. author_issue_bootstrap.py:1203-1220 writes claimant at the lock top level with lease_id null and no work_lease, lock_provenance, or expires_at.
  2. gitea_mcp_server.py:4683-4701 is the only canonical writer: work_lease via _build_author_issue_work_lease plus lock_provenance via build_sanctioned_lock_provenance.
  3. issue_lock_store.py:302-308, the ownership check used by heartbeat and legacy rebind, reads the claimant only from work_lease.claimant, so a bootstrap lock is refused for not recording both a claimant username and profile. issue_lock_store.py:1115, issue_lock_renewal.py:68, and issue_lock_recovery.py:118 already tolerate both shapes, so three readers disagree.
  4. issue_lock_store.py:690-703 reads expiry only from work_lease.expires_at, so a bootstrap lock yields none, is never expired, and #760 exact-owner renewal never engages.
  5. issue_lock_store.py:858-879 classifies a lock with no work_lease as legacy with no recorded expiry, and for the #949 shape no pid, so freshness returns live permanently.
  6. issue_lock_provenance.py:128-160, the #447 guard, requires both lock_provenance and work_lease. It is correct and is preserved unchanged.
  7. author_issue_bootstrap.py:1265 directs the author to implement rather than to finalize the lock.

Acceptance-criterion map

AC Code location Behavior Test Interface Compatibility
1, 6, 13 new author_lock_contract.py, author_issue_bootstrap.py, gitea_mcp_server.py one canonical builder emits claimant, work_lease, provenance, generation, and expiration, consumed by both writers test_issue_953_bootstrap_lock_contract.py bootstrap and gitea_lock_issue provenance source stays sanctioned
2 issue_lock_store ownership check claimant read tolerates both shapes through one shared reader same gitea_heartbeat_issue_lock legacy top-level claimant still accepted
3 issue_lock_renewal exact-owner renewal before and after commits same gitea_lock_issue #760 waiver unchanged
4 issue_lock_provenance unchanged valid bootstrap provenance passes the #447 guard same gitea_create_pr guard not weakened
5, 15 author_issue_bootstrap reported next action matches the returned state, and failure returns structured recovery same bootstrap none
7 new contract validator partial lock fails closed before implementation and names the missing fields same bootstrap none
8, 9, 10, 11 new target-specific recovery tool authenticated upgrade with no branch rewind, verifying repository, issue, claimant, profile, identity, session, branch, worktree, and head, refusing healthy foreign locks same new tool affects only the exact target lock
12 issue_lock_store freshness missing expiration represented explicitly, never non-expiring and non-renewable at the same time same inspection and renewal legacy absolute expiry preserved
14 shared claimant reader legacy shapes explicit and tested same all consumers none
16 new read-only inspection performs no lock, lease, branch, worktree, issue, or pull request mutation same new tool none
17, 18, 19 tests full bootstrap, implement, commit, push, create pull request regression plus malformed, partial, expired, same-owner, foreign-owner, committed-branch, and legacy locks same none isolated fixtures only
20 author workflow documentation required ordering and the recovery path documentation assertion none none

Preserved state

Issue #949 is untouched and stays deferred. Branch feat/issue-949-native-fleet-inventory remains at 92615f474b, its worktree and malformed lock are not modified, and its pull request is not retried. The #949-shaped regression uses isolated fixtures only. Issues #950 through #952 and the PR #906 lease are out of scope and unmodified.

Canonical Issue State

STATE: in-progress
WHO_IS_NEXT: author
NEXT_ACTION: Implement the canonical bootstrap and lock contract, add the target-specific recovery and read-only inspection surfaces, add the #949-shaped regression against isolated fixtures, update the author workflow documentation, then open exactly one pull request and hand off to an independent reviewer.
NEXT_PROMPT:

Role: AUTHOR
Repo: prgs / Scaled-Tech-Consulting / Gitea-Tools
Issue: 953
Branch: fix/issue-953-bootstrap-lock-provenance
Worktree: branches/issue-953-bootstrap-lock-provenance
Base: 82d71b77028a7abd4f8ab4a4e4d89658a187f73d

1. Heartbeat the issue-953 lock, then implement the canonical lock contract shared by bootstrap and gitea_lock_issue.
2. Add the target-specific authenticated recovery for existing incomplete bootstrap locks whose branches already carry pushed commits, without rewinding the branch.
3. Add read-only lock contract inspection that mutates nothing.
4. Add regression coverage for bootstrap to implement to commit to push to create pull request, plus malformed, partial, expired, same-owner, foreign-owner, committed-branch, and legacy locks, using isolated fixtures only.
5. Update the author workflow documentation with the required ordering and the recovery path.
6. Open exactly one pull request with the closing reference for issue 953, publish the author handoff pinned to the pushed head, then stop.

WHAT_HAPPENED: Native preflight verified profile prgs-author, identity jcwalker3, role author, repository binding Scaled-Tech-Consulting/Gitea-Tools, and full parity at 82d71b7702 with in_parity true, live_stale false, restart_required false, and mutation_safe true. Every required capability resolved before invocation. The existing-work search found no pull request, branch, worktree, lease, assignee, or comment for this issue. Bootstrap created the branch and registered worktree and wrote the incomplete lock exactly as reported, so gitea_lock_issue finalized it to the canonical contract before any implementation byte was written, and the pre-edit heartbeat then succeeded against that exact lock.
WHY: Bootstrap and ordinary lock acquisition write two different lock shapes, so heartbeat, renewal, and the create-PR provenance guard all refuse a lock that bootstrap reported as created. Finalizing the lock before divergence avoids the unrecoverable state while the fix is implemented.
RELATED_PRS: none yet for this issue; exactly one pull request will be opened from branch fix/issue-953-bootstrap-lock-provenance.
BLOCKERS: None. The lock is canonical and heartbeatable at generation 3, so implementation may proceed.
VALIDATION: The bootstrap lock read back with a top-level claimant, lease_id null, and no work_lease, lock_provenance, or expires_at. After gitea_lock_issue the same lock file records work_lease with claimant, created_at, expires_at, task_session_id, and lifecycle_version heartbeat-v1, plus lock_provenance with source gitea_lock_issue, at lock_generation 2. gitea_heartbeat_issue_lock then succeeded and advanced to generation 3 with no ownership change and no second lock. Full test evidence will accompany the pull request.
LAST_UPDATED_BY: prgs-author / jcwalker3

[THREAD STATE LEDGER] Issue #953 — author implementation plan published; lock finalized before divergence What is true now: - Issue state: open and claimed by this author session - Branch: `fix/issue-953-bootstrap-lock-provenance` - Worktree: `branches/issue-953-bootstrap-lock-provenance` - Pinned base SHA: 82d71b77028a7abd4f8ab4a4e4d89658a187f73d - Server-side decision state: no review or merge decision exists; no pull request has been created for this issue - Local verdict/state: canonical author issue lock held at generation 3, heartbeat verified, implementation not yet written - Latest known validation: bootstrap lock read back as incomplete, then finalized and heartbeated successfully What changed: - Bootstrap created the issue branch, the registered worktree, and an incomplete lock - `gitea_lock_issue` finalized that same lock to the canonical contract before any implementation byte was written - `gitea_heartbeat_issue_lock` succeeded against that exact lock with no ownership change and no second lock What is blocked: - Blocker classification: no blocker Who/what acts next: - Next actor: author - Required action: implement the canonical bootstrap and lock contract, add target-specific recovery and read-only inspection, add the regression suite against isolated fixtures, update the author workflow documentation, then open exactly one pull request - Do not do: do not recover, heartbeat, renew, or retry issue #949, do not modify issues #950 through #952, do not modify the PR #906 lease, do not review or merge the pull request this issue produces - Resume from: this plan comment and the canonical lock for issue #953 ## Author implementation plan Ownership was established without reproducing the dead end. Bootstrap ran, then the lock was finalized by `gitea_lock_issue` before any implementation bytes were written, which is the ordering this issue's own NEXT_PROMPT step 1 prescribes. | Dimension | Value | | --- | --- | | Branch | `fix/issue-953-bootstrap-lock-provenance` | | Worktree | `branches/issue-953-bootstrap-lock-provenance` | | Pinned base | 82d71b77028a7abd4f8ab4a4e4d89658a187f73d | | Lock generation | 1 at bootstrap, then 2 at `gitea_lock_issue`, then 3 at heartbeat | | Task session | `author_issue_work-af66d20143e04ee5` | ### Defect verified against the pinned base rather than the issue's line numbers 1. `author_issue_bootstrap.py:1203-1220` writes `claimant` at the lock top level with `lease_id` null and no `work_lease`, `lock_provenance`, or `expires_at`. 2. `gitea_mcp_server.py:4683-4701` is the only canonical writer: `work_lease` via `_build_author_issue_work_lease` plus `lock_provenance` via `build_sanctioned_lock_provenance`. 3. `issue_lock_store.py:302-308`, the ownership check used by heartbeat and legacy rebind, reads the claimant only from `work_lease.claimant`, so a bootstrap lock is refused for not recording both a claimant username and profile. `issue_lock_store.py:1115`, `issue_lock_renewal.py:68`, and `issue_lock_recovery.py:118` already tolerate both shapes, so three readers disagree. 4. `issue_lock_store.py:690-703` reads expiry only from `work_lease.expires_at`, so a bootstrap lock yields none, is never expired, and #760 exact-owner renewal never engages. 5. `issue_lock_store.py:858-879` classifies a lock with no `work_lease` as legacy with no recorded expiry, and for the #949 shape no pid, so freshness returns live permanently. 6. `issue_lock_provenance.py:128-160`, the #447 guard, requires both `lock_provenance` and `work_lease`. It is correct and is preserved unchanged. 7. `author_issue_bootstrap.py:1265` directs the author to implement rather than to finalize the lock. ### Acceptance-criterion map | AC | Code location | Behavior | Test | Interface | Compatibility | | --- | --- | --- | --- | --- | --- | | 1, 6, 13 | new `author_lock_contract.py`, `author_issue_bootstrap.py`, `gitea_mcp_server.py` | one canonical builder emits claimant, `work_lease`, provenance, generation, and expiration, consumed by both writers | `test_issue_953_bootstrap_lock_contract.py` | bootstrap and `gitea_lock_issue` | provenance source stays sanctioned | | 2 | `issue_lock_store` ownership check | claimant read tolerates both shapes through one shared reader | same | `gitea_heartbeat_issue_lock` | legacy top-level claimant still accepted | | 3 | `issue_lock_renewal` | exact-owner renewal before and after commits | same | `gitea_lock_issue` | #760 waiver unchanged | | 4 | `issue_lock_provenance` unchanged | valid bootstrap provenance passes the #447 guard | same | `gitea_create_pr` | guard not weakened | | 5, 15 | `author_issue_bootstrap` | reported next action matches the returned state, and failure returns structured recovery | same | bootstrap | none | | 7 | new contract validator | partial lock fails closed before implementation and names the missing fields | same | bootstrap | none | | 8, 9, 10, 11 | new target-specific recovery tool | authenticated upgrade with no branch rewind, verifying repository, issue, claimant, profile, identity, session, branch, worktree, and head, refusing healthy foreign locks | same | new tool | affects only the exact target lock | | 12 | `issue_lock_store` freshness | missing expiration represented explicitly, never non-expiring and non-renewable at the same time | same | inspection and renewal | legacy absolute expiry preserved | | 14 | shared claimant reader | legacy shapes explicit and tested | same | all consumers | none | | 16 | new read-only inspection | performs no lock, lease, branch, worktree, issue, or pull request mutation | same | new tool | none | | 17, 18, 19 | tests | full bootstrap, implement, commit, push, create pull request regression plus malformed, partial, expired, same-owner, foreign-owner, committed-branch, and legacy locks | same | none | isolated fixtures only | | 20 | author workflow documentation | required ordering and the recovery path | documentation assertion | none | none | ### Preserved state Issue #949 is untouched and stays deferred. Branch `feat/issue-949-native-fleet-inventory` remains at 92615f474bf6652d4e9ea59af7fd0dba03b56544, its worktree and malformed lock are not modified, and its pull request is not retried. The #949-shaped regression uses isolated fixtures only. Issues #950 through #952 and the PR #906 lease are out of scope and unmodified. ## Canonical Issue State STATE: in-progress WHO_IS_NEXT: author NEXT_ACTION: Implement the canonical bootstrap and lock contract, add the target-specific recovery and read-only inspection surfaces, add the #949-shaped regression against isolated fixtures, update the author workflow documentation, then open exactly one pull request and hand off to an independent reviewer. NEXT_PROMPT: ```text Role: AUTHOR Repo: prgs / Scaled-Tech-Consulting / Gitea-Tools Issue: 953 Branch: fix/issue-953-bootstrap-lock-provenance Worktree: branches/issue-953-bootstrap-lock-provenance Base: 82d71b77028a7abd4f8ab4a4e4d89658a187f73d 1. Heartbeat the issue-953 lock, then implement the canonical lock contract shared by bootstrap and gitea_lock_issue. 2. Add the target-specific authenticated recovery for existing incomplete bootstrap locks whose branches already carry pushed commits, without rewinding the branch. 3. Add read-only lock contract inspection that mutates nothing. 4. Add regression coverage for bootstrap to implement to commit to push to create pull request, plus malformed, partial, expired, same-owner, foreign-owner, committed-branch, and legacy locks, using isolated fixtures only. 5. Update the author workflow documentation with the required ordering and the recovery path. 6. Open exactly one pull request with the closing reference for issue 953, publish the author handoff pinned to the pushed head, then stop. ``` WHAT_HAPPENED: Native preflight verified profile prgs-author, identity jcwalker3, role author, repository binding Scaled-Tech-Consulting/Gitea-Tools, and full parity at 82d71b77028a7abd4f8ab4a4e4d89658a187f73d with in_parity true, live_stale false, restart_required false, and mutation_safe true. Every required capability resolved before invocation. The existing-work search found no pull request, branch, worktree, lease, assignee, or comment for this issue. Bootstrap created the branch and registered worktree and wrote the incomplete lock exactly as reported, so gitea_lock_issue finalized it to the canonical contract before any implementation byte was written, and the pre-edit heartbeat then succeeded against that exact lock. WHY: Bootstrap and ordinary lock acquisition write two different lock shapes, so heartbeat, renewal, and the create-PR provenance guard all refuse a lock that bootstrap reported as created. Finalizing the lock before divergence avoids the unrecoverable state while the fix is implemented. RELATED_PRS: none yet for this issue; exactly one pull request will be opened from branch fix/issue-953-bootstrap-lock-provenance. BLOCKERS: None. The lock is canonical and heartbeatable at generation 3, so implementation may proceed. VALIDATION: The bootstrap lock read back with a top-level claimant, lease_id null, and no work_lease, lock_provenance, or expires_at. After gitea_lock_issue the same lock file records work_lease with claimant, created_at, expires_at, task_session_id, and lifecycle_version heartbeat-v1, plus lock_provenance with source gitea_lock_issue, at lock_generation 2. gitea_heartbeat_issue_lock then succeeded and advanced to generation 3 with no ownership change and no second lock. Full test evidence will accompany the pull request. LAST_UPDATED_BY: prgs-author / jcwalker3
jcwalker3 added status:pr-open and removed status:ready labels 2026-07-27 23:38:11 -05:00
Author
Owner

[THREAD STATE LEDGER] Issue #953 — PR #954 published at cdf0dae; author handoff to independent reviewer

What is true now:

  • Issue state: open, labelled status:pr-open
  • Pull request: #954, open, base master, head branch fix/issue-953-bootstrap-lock-provenance
  • Pinned head SHA: cdf0daefa9 (local head, remote head, and PR head_sha all agree)
  • Base: master at 82d71b7702
  • Mergeable: true
  • Server-side decision state: no review or merge decision exists; no verdict has been recorded on PR #954
  • Local verdict/state: implementation complete, committed, published, and pull request created and read back natively
  • Latest known validation: full suite at head 28 failed / 5753 passed / 6 skipped / 1042 subtests; full suite at base 28 failed / 5692 passed / 6 skipped / 1042 subtests; failing test-ID sets identical

What changed:

  • Added author_lock_contract.py as the single canonical lock definition, consumed by both gitea_lock_issue and gitea_bootstrap_author_issue_worktree
  • Promoted issue_lock_store.lock_claimant to the one shared claimant reader and used it in the ownership check
  • Represented missing expiration explicitly so a malformed lock is no longer permanently non-expiring and permanently unrenewable at once
  • Bootstrap now reads its lock back, verifies it structurally, fails closed before implementation on a partial lock, and reports a next action derived from the state it actually returned
  • Added gitea_recover_incomplete_bootstrap_lock and the read-only gitea_inspect_issue_lock_contract
  • Added docs/author-issue-lock-contract.md and 61 new test cases
  • Published branch at cdf0dae and opened pull request #954

What is blocked:

  • Blocker classification: no blocker

Who/what acts next:

  • Next actor: reviewer
  • Required action: independent formal review of pull request #954 against the twenty acceptance criteria of this issue, focusing on ownership proof, provenance minting, recovery evidence, and foreign-lock safety
  • Do not do: do not recover, heartbeat, renew, or retry issue #949; do not modify issues #950 through #952; do not modify the PR #906 lease; the author must not review or merge pull request #954
  • Resume from: pull request #954 at head cdf0daefa9

Canonical Issue State

STATE: in-review
WHO_IS_NEXT: reviewer
NEXT_ACTION: Perform an independent formal review of pull request #954 at head cdf0daefa9 against the twenty acceptance criteria and the safety requirements of this issue, then record a formal verdict.
NEXT_PROMPT:

Role: REVIEWER
Repo: prgs / Scaled-Tech-Consulting / Gitea-Tools
PR: 954
Issue: 953
Head: cdf0daefa91f891186bfad0513816ec2ddc90e7c
Base: master at 82d71b77028a7abd4f8ab4a4e4d89658a187f73d

1. Native preflight on prgs-reviewer, load the review workflow, resolve review_pr, acquire the reviewer lease, and pin the live head.
2. Verify each of the twenty acceptance criteria against the diff and the new test suite.
3. Focus on: whether tolerating the legacy claimant placement widens where the claimant is read from without widening whether ownership is proven; that SANCTIONED_LOCK_SOURCES is untouched and no path accepts caller-supplied provenance; that the recovery assessor trusts only server-resolved identity and locally observed head; that a healthy foreign-owned lock and a matching-username-with-different-profile caller are both refused; and whether leaving is_lease_expired and assess_lock_freshness unchanged is the correct conservatism.
4. Confirm the branch was never rewound and that issue #949 was not touched.
5. Record a formal verdict. Do not merge without explicit operator approval.

WHAT_HAPPENED: Bootstrap created the branch, the registered worktree, and an incomplete lock exactly as this issue reports. The lock was finalized by gitea_lock_issue to the canonical contract before any implementation byte was written, and heartbeated throughout, ending at generation 10 with no ownership change and no second lock. The implementation unified the bootstrap and lock acquisition contracts, added the target-specific recovery and read-only inspection surfaces, added sixty-one test cases including the full bootstrap to implement to commit to push to create pull request regression against isolated fixtures, and documented the required ordering. The branch was published natively at cdf0dae and pull request #954 was created and read back.
WHY: Bootstrap and ordinary lock acquisition wrote two different lock shapes, so heartbeat, renewal, re-lock, and the create-PR provenance guard all refused a lock that bootstrap reported as created, leaving no eligible recovery path once the branch carried commits. One shared contract removes the disagreement, and the new recovery operation repairs locks already written by the old code without rewinding their committed work.
RELATED_PRS: #954 is the only pull request for this issue.
BLOCKERS: None. Pull request #954 is open and mergeable, and awaits an independent reviewer verdict.
VALIDATION: New suite tests/test_issue_953_bootstrap_lock_contract.py 61 passed, exit 0. Adjacent lock, bootstrap, lease, renewal, recovery, heartbeat, and capability suites 283 passed with 92 subtests, exit 0. Full suite at head cdf0dae 28 failed, 5753 passed, 6 skipped, 1042 subtests. Full suite at base 82d71b77 28 failed, 5692 passed, 6 skipped, 1042 subtests. The failing test-ID sets are identical, so zero regressions; the plus sixty-one passes are this issue's new suite. All twenty-eight failures were reproduced at the pinned base, and four that looked like plausible candidates for being caused by this change were re-run individually at base and also fail there. The live create-PR provenance guard accepted the canonical lock, which is an end-to-end proof of the fix.
LAST_UPDATED_BY: prgs-author / jcwalker3

Preserved state

Issue #949 remains open and unmodified. Branch feat/issue-949-native-fleet-inventory is still at 92615f474b on both the remote and its worktree, its worktree and malformed lock were not modified, and its pull request was not retried. Issues #950 through #952 and the PR #906 lease were not modified. The control checkout remained clean and on master throughout.

[THREAD STATE LEDGER] Issue #953 — PR #954 published at cdf0dae; author handoff to independent reviewer What is true now: - Issue state: open, labelled `status:pr-open` - Pull request: #954, open, base `master`, head branch `fix/issue-953-bootstrap-lock-provenance` - Pinned head SHA: cdf0daefa91f891186bfad0513816ec2ddc90e7c (local head, remote head, and PR `head_sha` all agree) - Base: `master` at 82d71b77028a7abd4f8ab4a4e4d89658a187f73d - Mergeable: true - Server-side decision state: no review or merge decision exists; no verdict has been recorded on PR #954 - Local verdict/state: implementation complete, committed, published, and pull request created and read back natively - Latest known validation: full suite at head 28 failed / 5753 passed / 6 skipped / 1042 subtests; full suite at base 28 failed / 5692 passed / 6 skipped / 1042 subtests; failing test-ID sets identical What changed: - Added `author_lock_contract.py` as the single canonical lock definition, consumed by both `gitea_lock_issue` and `gitea_bootstrap_author_issue_worktree` - Promoted `issue_lock_store.lock_claimant` to the one shared claimant reader and used it in the ownership check - Represented missing expiration explicitly so a malformed lock is no longer permanently non-expiring and permanently unrenewable at once - Bootstrap now reads its lock back, verifies it structurally, fails closed before implementation on a partial lock, and reports a next action derived from the state it actually returned - Added `gitea_recover_incomplete_bootstrap_lock` and the read-only `gitea_inspect_issue_lock_contract` - Added `docs/author-issue-lock-contract.md` and 61 new test cases - Published branch at cdf0dae and opened pull request #954 What is blocked: - Blocker classification: no blocker Who/what acts next: - Next actor: reviewer - Required action: independent formal review of pull request #954 against the twenty acceptance criteria of this issue, focusing on ownership proof, provenance minting, recovery evidence, and foreign-lock safety - Do not do: do not recover, heartbeat, renew, or retry issue #949; do not modify issues #950 through #952; do not modify the PR #906 lease; the author must not review or merge pull request #954 - Resume from: pull request #954 at head cdf0daefa91f891186bfad0513816ec2ddc90e7c ## Canonical Issue State STATE: in-review WHO_IS_NEXT: reviewer NEXT_ACTION: Perform an independent formal review of pull request #954 at head cdf0daefa91f891186bfad0513816ec2ddc90e7c against the twenty acceptance criteria and the safety requirements of this issue, then record a formal verdict. NEXT_PROMPT: ```text Role: REVIEWER Repo: prgs / Scaled-Tech-Consulting / Gitea-Tools PR: 954 Issue: 953 Head: cdf0daefa91f891186bfad0513816ec2ddc90e7c Base: master at 82d71b77028a7abd4f8ab4a4e4d89658a187f73d 1. Native preflight on prgs-reviewer, load the review workflow, resolve review_pr, acquire the reviewer lease, and pin the live head. 2. Verify each of the twenty acceptance criteria against the diff and the new test suite. 3. Focus on: whether tolerating the legacy claimant placement widens where the claimant is read from without widening whether ownership is proven; that SANCTIONED_LOCK_SOURCES is untouched and no path accepts caller-supplied provenance; that the recovery assessor trusts only server-resolved identity and locally observed head; that a healthy foreign-owned lock and a matching-username-with-different-profile caller are both refused; and whether leaving is_lease_expired and assess_lock_freshness unchanged is the correct conservatism. 4. Confirm the branch was never rewound and that issue #949 was not touched. 5. Record a formal verdict. Do not merge without explicit operator approval. ``` WHAT_HAPPENED: Bootstrap created the branch, the registered worktree, and an incomplete lock exactly as this issue reports. The lock was finalized by gitea_lock_issue to the canonical contract before any implementation byte was written, and heartbeated throughout, ending at generation 10 with no ownership change and no second lock. The implementation unified the bootstrap and lock acquisition contracts, added the target-specific recovery and read-only inspection surfaces, added sixty-one test cases including the full bootstrap to implement to commit to push to create pull request regression against isolated fixtures, and documented the required ordering. The branch was published natively at cdf0dae and pull request #954 was created and read back. WHY: Bootstrap and ordinary lock acquisition wrote two different lock shapes, so heartbeat, renewal, re-lock, and the create-PR provenance guard all refused a lock that bootstrap reported as created, leaving no eligible recovery path once the branch carried commits. One shared contract removes the disagreement, and the new recovery operation repairs locks already written by the old code without rewinding their committed work. RELATED_PRS: #954 is the only pull request for this issue. BLOCKERS: None. Pull request #954 is open and mergeable, and awaits an independent reviewer verdict. VALIDATION: New suite `tests/test_issue_953_bootstrap_lock_contract.py` 61 passed, exit 0. Adjacent lock, bootstrap, lease, renewal, recovery, heartbeat, and capability suites 283 passed with 92 subtests, exit 0. Full suite at head cdf0dae 28 failed, 5753 passed, 6 skipped, 1042 subtests. Full suite at base 82d71b77 28 failed, 5692 passed, 6 skipped, 1042 subtests. The failing test-ID sets are identical, so zero regressions; the plus sixty-one passes are this issue's new suite. All twenty-eight failures were reproduced at the pinned base, and four that looked like plausible candidates for being caused by this change were re-run individually at base and also fail there. The live create-PR provenance guard accepted the canonical lock, which is an end-to-end proof of the fix. LAST_UPDATED_BY: prgs-author / jcwalker3 ### Preserved state Issue #949 remains open and unmodified. Branch `feat/issue-949-native-fleet-inventory` is still at 92615f474bf6652d4e9ea59af7fd0dba03b56544 on both the remote and its worktree, its worktree and malformed lock were not modified, and its pull request was not retried. Issues #950 through #952 and the PR #906 lease were not modified. The control checkout remained clean and on `master` throughout.
sysadmin removed the status:pr-open label 2026-07-28 02:21:14 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

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