fix(author bootstrap): restore missing runtime identity and session helpers (Closes #943) #944

Merged
sysadmin merged 2 commits from fix/issue-943-runtime-context-helpers into master 2026-07-27 20:03:09 -05:00
Owner

Closes #943

Diagnosis

gitea_bootstrap_author_issue_worktree referenced four module globals that commit a942afe ("Implement native author issue worktree bootstrap", #850) introduced without ever defining:

Name References Definitions
_active_username 1 0
_active_profile_name 1 0
_current_session_id 1 0
_author_mutation_block 1 0

The first three are evaluated as call arguments at gitea_mcp_server.py:10235-10237, so every invocation raised

success=false
reason_code=internal_error
exception_class=builtins.NameError
detail=name '_active_username' is not defined

before author_issue_bootstrap.bootstrap_author_issue_worktree was entered. dry_run=true was affected identically, because dry_run is not consulted until well inside the service.

_author_mutation_block was not in the #943 report. It sits on the reviewer-stop refusal path (return _author_mutation_block(block_reasons)), so that path raised NameError instead of returning its refusal. The generalised regression test found it, not the original triage.

Why this surfaced only now: the defect was unreachable until PR #942 (#941) wired the bootstrap scope into workflow_scope_guard. Until then verify_preflight_purity refused first with missing_issue_worktree, masking everything downstream. Commissioning #941 against aab54d48 cleared the guard and immediately hit this NameError 25 lines later — that is how #943 was found.

Implementation

Each helper delegates to the source the codebase already treats as authoritative. Nothing is duplicated, inferred, or weakened.

  • _active_username reads the immutable #714 session context that gitea_whoami seeds — the identity pin every other mutation gate already consults. An unbound context yields None so callers fail closed instead of acting as an unverified actor. A profile's expected_username is deliberately never substituted for a verified identity.
  • _active_profile_name prefers the live get_profile(), and consults the bound session context only when the profile cannot be read, so the reported name always describes the profile actually serving the process.
  • _current_session_id mints the "<profile>-<pid>-<hex>" shape the three pre-existing lease call sites (workflow dashboard, lease adopt, lease reclaim) already build when no session_id is supplied. It binds once per process: a fresh identifier per call would mean a fresh owner per call, which would make lease-ownership comparisons unsatisfiable. None is never memoised.
  • _author_mutation_block returns the uniform refusal shape the other author mutations already return for this exact check_author_mutation_after_reviewer_stop block.

Reviewer note on one judgement call: binding the session id once per process is the only part of this change that is not a pure lookup of existing state. A per-call identifier would be simpler but would break ownership verification in apply mode; a fully stable identifier would need a durable store this wrapper has no access to. Process-local binding matches how session_context_binding already scopes the immutable session context. Worth a look.

No guard, signature, permission, or role change. +534 / −0 — nothing removed.

Enforcement preserved

The helpers only supply values the service then validates fail-closed. Verified by test, not by inspection:

Condition Reason code
identity absent/blank missing_active_identity
profile absent/blank missing_active_profile
session absent missing_owner_session
base SHA drift stale_concurrency_pin

Wrong-role, wrong-profile, wrong-identity, stale-runtime, expected-base and workflow-scope enforcement are all unchanged, as are the #274 / #604 / #618 / #683 protections.

Tests

tests/test_issue_943_runtime_context_helpers.py — 27 tests, 12 subtests.

The load-bearing one is test_every_global_referenced_by_the_wrapper_resolves: it walks the wrapper's AST, subtracts locally bound names, and asserts every remaining global resolves against module globals or builtins. Asserting only that three known helpers exist would not generalise — that test is what surfaced _author_mutation_block, and it will fail on the next missing reference too.

Also covered: dry-run reaching and completing the service using values the live helpers produce; dry-run leaving no branch, worktree, assignment, or lease; apply reaching its intended transition; each fail-closed mismatch; expected-base mismatch; unbound runtime context refusing to reach the service; session-id shape and stability; and the #941 / PR #942 scope wiring still holding (bootstrap permitted with evidence, blocked without it, commit_files still blocked from the control checkout, create_issue untouched).

# new suite, against unmodified aab54d48 (base gitea_mcp_server.py, new tests)
20 failed, 13 passed

# new suite, with this change
27 passed, 12 subtests passed

# targeted bootstrap + guard suites (943, 941, 892, author_issue_bootstrap,
# create_issue_bootstrap, 683, 757, anti_stomp_preflight, root_checkout_guard, 618)
245 passed, 59 subtests passed

# full suite, run from the branches/ worktree
28 failed, 5552 passed, 6 skipped, 1006 subtests passed in 151.72s

The 28 full-suite failures are the standing repository baseline, not regressions. Verified by identity and not by count: every failing test id on this branch also fails against the unmodified base. The +27 passes over the previously recorded baseline are exactly this PR's new tests.

Scope

  • Files: gitea_mcp_server.py, tests/test_issue_943_runtime_context_helpers.py
  • Diff: 2 files, +534 / −0
  • Branch: fix/issue-943-runtime-context-helpers
  • Base: master at aab54d4825270f5a5c6f9c1abc1ab09eb4f3e218
  • Head: f49e781102b9f363834c28c055f69639d16290c9
  • Commit parent verified as the base SHA
  • Worktree: branches/issue-943-runtime-context-helpers
  • Issue lock: author_issue_work-d1a91a7d2c7d43df, owner pid 18161

Author worktree provenance

The canonical gitea_bootstrap_author_issue_worktree is the very capability this PR repairs, so it could not create its own worktree — the defect blocks its own fix, exactly as #941 did. Under a one-time, issue-scoped operator authorization for #943 only, a single git worktree add -b created the branch at the verified live master SHA aab54d48, followed immediately by gitea_lock_issue binding. The known-broken bootstrap capability was not called. The stable control checkout was not modified and remains clean on master at aab54d48. Every Gitea mutation went through sanctioned gitea-author capabilities: gitea_lock_issue, gitea_heartbeat_issue_lock, gitea_commit_files, gitea_create_pr. No tea, no curl, no raw API, no direct database access, no manual push.

Commissioning requirements after merge

This fix cannot be proven live until the deployed runtime executes it. The running daemons still execute the pre-fix code, so the capability stays broken in production until:

  1. This PR is independently reviewed and merged.
  2. The control checkout is fast-forwarded to the new master tip.
  3. All five MCP servers are restarted or reconnected, in one atomic operator window — a restart before the checkout advance is a no-op that looks like success.
  4. Parity is re-verified across all five namespaces: startup_head, daemon_start_head, local_head, live_remote_head in agreement with live_stale:false, restart_required:false, mutation_safe:true.
  5. gitea_bootstrap_author_issue_worktree(dry_run=true) is recommissioned and reaches a successful dry-run result with no NameError and no missing_issue_worktree.

Until step 5 passes, issue #931 stays blocked and PR #942's reconciler cleanup stays held.

Untouched

Issue #931 received nothing — no assignment, lease, branch, worktree, commit, or PR. Issue #941 was not reopened or edited. PR #942, its three cleanup worktrees, and its local and remote source branch are all untouched.

Handoff

WHO_IS_NEXT: reviewer — independent review against the #943 acceptance criteria, pinned to head f49e781102b9f363834c28c055f69639d16290c9. Do not self-review and do not self-merge.

Closes #943 ## Diagnosis `gitea_bootstrap_author_issue_worktree` referenced four module globals that commit `a942afe` ("Implement native author issue worktree bootstrap", #850) introduced without ever defining: | Name | References | Definitions | | ---- | ---------: | ----------: | | `_active_username` | 1 | 0 | | `_active_profile_name` | 1 | 0 | | `_current_session_id` | 1 | 0 | | `_author_mutation_block` | 1 | 0 | The first three are evaluated as call arguments at `gitea_mcp_server.py:10235-10237`, so every invocation raised ```text success=false reason_code=internal_error exception_class=builtins.NameError detail=name '_active_username' is not defined ``` before `author_issue_bootstrap.bootstrap_author_issue_worktree` was entered. `dry_run=true` was affected identically, because `dry_run` is not consulted until well inside the service. `_author_mutation_block` was **not** in the #943 report. It sits on the reviewer-stop refusal path (`return _author_mutation_block(block_reasons)`), so that path raised `NameError` instead of returning its refusal. The generalised regression test found it, not the original triage. Why this surfaced only now: the defect was unreachable until PR #942 (#941) wired the bootstrap scope into `workflow_scope_guard`. Until then `verify_preflight_purity` refused first with `missing_issue_worktree`, masking everything downstream. Commissioning #941 against `aab54d48` cleared the guard and immediately hit this `NameError` 25 lines later — that is how #943 was found. ## Implementation Each helper delegates to the source the codebase already treats as authoritative. Nothing is duplicated, inferred, or weakened. * **`_active_username`** reads the immutable #714 session context that `gitea_whoami` seeds — the identity pin every other mutation gate already consults. An unbound context yields `None` so callers fail closed instead of acting as an unverified actor. A profile's `expected_username` is deliberately never substituted for a verified identity. * **`_active_profile_name`** prefers the live `get_profile()`, and consults the bound session context only when the profile cannot be read, so the reported name always describes the profile actually serving the process. * **`_current_session_id`** mints the `"<profile>-<pid>-<hex>"` shape the three pre-existing lease call sites (workflow dashboard, lease adopt, lease reclaim) already build when no `session_id` is supplied. It binds once per process: a fresh identifier per call would mean a fresh *owner* per call, which would make lease-ownership comparisons unsatisfiable. `None` is never memoised. * **`_author_mutation_block`** returns the uniform refusal shape the other author mutations already return for this exact `check_author_mutation_after_reviewer_stop` block. **Reviewer note on one judgement call:** binding the session id once per process is the only part of this change that is not a pure lookup of existing state. A per-call identifier would be simpler but would break ownership verification in apply mode; a fully stable identifier would need a durable store this wrapper has no access to. Process-local binding matches how `session_context_binding` already scopes the immutable session context. Worth a look. No guard, signature, permission, or role change. `+534 / −0` — nothing removed. ## Enforcement preserved The helpers only supply values the service then validates fail-closed. Verified by test, not by inspection: | Condition | Reason code | | --------- | ----------- | | identity absent/blank | `missing_active_identity` | | profile absent/blank | `missing_active_profile` | | session absent | `missing_owner_session` | | base SHA drift | `stale_concurrency_pin` | Wrong-role, wrong-profile, wrong-identity, stale-runtime, expected-base and workflow-scope enforcement are all unchanged, as are the #274 / #604 / #618 / #683 protections. ## Tests `tests/test_issue_943_runtime_context_helpers.py` — 27 tests, 12 subtests. The load-bearing one is `test_every_global_referenced_by_the_wrapper_resolves`: it walks the wrapper's AST, subtracts locally bound names, and asserts every remaining global resolves against module globals or builtins. Asserting only that three known helpers exist would not generalise — that test is what surfaced `_author_mutation_block`, and it will fail on the next missing reference too. Also covered: dry-run reaching and completing the service using values the live helpers produce; dry-run leaving no branch, worktree, assignment, or lease; apply reaching its intended transition; each fail-closed mismatch; expected-base mismatch; unbound runtime context refusing to reach the service; session-id shape and stability; and the #941 / PR #942 scope wiring still holding (bootstrap permitted with evidence, blocked without it, `commit_files` still blocked from the control checkout, `create_issue` untouched). ```text # new suite, against unmodified aab54d48 (base gitea_mcp_server.py, new tests) 20 failed, 13 passed # new suite, with this change 27 passed, 12 subtests passed # targeted bootstrap + guard suites (943, 941, 892, author_issue_bootstrap, # create_issue_bootstrap, 683, 757, anti_stomp_preflight, root_checkout_guard, 618) 245 passed, 59 subtests passed # full suite, run from the branches/ worktree 28 failed, 5552 passed, 6 skipped, 1006 subtests passed in 151.72s ``` The 28 full-suite failures are the standing repository baseline, not regressions. Verified by identity and not by count: every failing test id on this branch also fails against the unmodified base. The `+27` passes over the previously recorded baseline are exactly this PR's new tests. ## Scope * Files: `gitea_mcp_server.py`, `tests/test_issue_943_runtime_context_helpers.py` * Diff: 2 files, +534 / −0 * Branch: `fix/issue-943-runtime-context-helpers` * Base: `master` at `aab54d4825270f5a5c6f9c1abc1ab09eb4f3e218` * Head: `f49e781102b9f363834c28c055f69639d16290c9` * Commit parent verified as the base SHA * Worktree: `branches/issue-943-runtime-context-helpers` * Issue lock: `author_issue_work-d1a91a7d2c7d43df`, owner pid 18161 ## Author worktree provenance The canonical `gitea_bootstrap_author_issue_worktree` is the very capability this PR repairs, so it could not create its own worktree — the defect blocks its own fix, exactly as #941 did. Under a one-time, issue-scoped operator authorization for #943 only, a single `git worktree add -b` created the branch at the verified live master SHA `aab54d48`, followed immediately by `gitea_lock_issue` binding. The known-broken bootstrap capability was not called. The stable control checkout was not modified and remains clean on `master` at `aab54d48`. Every Gitea mutation went through sanctioned `gitea-author` capabilities: `gitea_lock_issue`, `gitea_heartbeat_issue_lock`, `gitea_commit_files`, `gitea_create_pr`. No `tea`, no `curl`, no raw API, no direct database access, no manual push. ## Commissioning requirements after merge This fix cannot be proven live until the deployed runtime executes it. The running daemons still execute the pre-fix code, so the capability stays broken in production until: 1. This PR is independently reviewed and merged. 2. The control checkout is fast-forwarded to the new master tip. 3. All five MCP servers are restarted or reconnected, in one atomic operator window — a restart before the checkout advance is a no-op that looks like success. 4. Parity is re-verified across all five namespaces: `startup_head`, `daemon_start_head`, `local_head`, `live_remote_head` in agreement with `live_stale:false`, `restart_required:false`, `mutation_safe:true`. 5. `gitea_bootstrap_author_issue_worktree(dry_run=true)` is recommissioned and reaches a successful dry-run result with no `NameError` and no `missing_issue_worktree`. Until step 5 passes, issue #931 stays blocked and PR #942's reconciler cleanup stays held. ## Untouched Issue #931 received nothing — no assignment, lease, branch, worktree, commit, or PR. Issue #941 was not reopened or edited. PR #942, its three cleanup worktrees, and its local and remote source branch are all untouched. ## Handoff **WHO_IS_NEXT: reviewer** — independent review against the #943 acceptance criteria, pinned to head `f49e781102b9f363834c28c055f69639d16290c9`. Do not self-review and do not self-merge.
jcwalker3 added 1 commit 2026-07-26 07:59:35 -05:00
gitea_bootstrap_author_issue_worktree referenced four globals that commit
a942afe (#850) introduced without ever defining:

    _active_username        1 reference, 0 definitions
    _active_profile_name    1 reference, 0 definitions
    _current_session_id     1 reference, 0 definitions
    _author_mutation_block  1 reference, 0 definitions

Evaluating the call arguments therefore raised

    NameError: name '_active_username' is not defined

before author_issue_bootstrap.bootstrap_author_issue_worktree was entered, so
the capability was unusable for every caller including dry_run=true. The fourth
name, _author_mutation_block, sits on the reviewer-stop refusal path and was
found by the generalised regression test rather than by the original report.

The defect was unreachable until PR #942 (#941) wired the bootstrap scope into
workflow_scope_guard: before that, verify_preflight_purity refused first with
missing_issue_worktree, masking it.

Changes:

* _active_username reads the immutable #714 session context that gitea_whoami
  seeds — the identity pin every other mutation gate already consults. An
  unbound context returns None so callers fail closed rather than acting as an
  unverified actor; a profile's expected_username is never substituted.
* _active_profile_name prefers the live get_profile() and falls back to the
  bound session context only when the profile cannot be read.
* _current_session_id mints the same "<profile>-<pid>-<hex>" shape as the three
  pre-existing lease call sites, bound once per process so repeated calls
  describe one session instead of a fresh owner per call, which would make
  lease-ownership comparisons unsatisfiable. None is never memoised.
* _author_mutation_block returns the uniform refusal shape the other author
  mutations already return for the same check_author_mutation_after_reviewer_stop
  block.

No guard, signature, or permission changes. Wrong-role, wrong-profile,
wrong-identity, stale-runtime, expected-base and workflow-scope enforcement all
still gate the call; the helpers only supply values the service then validates
fail-closed (missing_active_identity / missing_active_profile /
missing_owner_session / stale_concurrency_pin).

Regression: tests/test_issue_943_runtime_context_helpers.py (27 tests). The
generalised test resolves every global the wrapper's body references against
module globals and builtins, so the next missing reference fails too rather
than only the three named here — that test is what found
_author_mutation_block. Coverage also coversdry-run reaching and completing the
service with helper-produced bindings, dry-run leaving no branch, worktree,
assignment or lease, apply reaching its intended transition, each fail-closed
mismatch, expected-base mismatch, and the #941/PR #942 scope wiring.

Pre-fix 20 failed / 13 passed against unmodified aab54d48; post-fix 27 passed.
Targeted bootstrap and guard suites: 245 passed, 59 subtests.
Full suite: 28 failed, 5552 passed, 6 skipped, 1006 subtests — the 28 are the
standing baseline, every one of which also fails on the unmodified base.

Closes #943

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_013ygVZQLbbhJTChuVuLaJWb
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #944
issue: #943
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 18216-99c21d36dc2b
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr944-head
phase: claimed
candidate_head: f49e781102
target_branch: master
target_branch_sha: aab54d4825
last_activity: 2026-07-26T13:39:45Z
expires_at: 2026-07-26T13:49:45Z
blocker: none

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #944 issue: #943 reviewer_identity: sysadmin profile: prgs-reviewer session_id: 18216-99c21d36dc2b worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr944-head phase: claimed candidate_head: f49e781102b9f363834c28c055f69639d16290c9 target_branch: master target_branch_sha: aab54d4825270f5a5c6f9c1abc1ab09eb4f3e218 last_activity: 2026-07-26T13:39:45Z expires_at: 2026-07-26T13:49:45Z blocker: none
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #944
issue: #943
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 18216-99c21d36dc2b
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr944-head
phase: claimed
candidate_head: f49e781102
target_branch: master
target_branch_sha: aab54d4825
last_activity: 2026-07-26T13:42:50Z
expires_at: 2026-07-26T13:52:50Z
blocker: none

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #944 issue: #943 reviewer_identity: sysadmin profile: prgs-reviewer session_id: 18216-99c21d36dc2b worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr944-head phase: claimed candidate_head: f49e781102b9f363834c28c055f69639d16290c9 target_branch: master target_branch_sha: aab54d4825270f5a5c6f9c1abc1ab09eb4f3e218 last_activity: 2026-07-26T13:42:50Z expires_at: 2026-07-26T13:52:50Z blocker: none
sysadmin requested changes 2026-07-26 08:46:26 -05:00
Dismissed
sysadmin left a comment
Owner

REQUEST_CHANGES — PR #944 at head f49e781102b9f363834c28c055f69639d16290c9

Reviewed independently at base aab54d4825270f5a5c6f9c1abc1ab09eb4f3e218 (live master, unmoved — no base drift affects this review). Reviewer sysadmin / prgs-reviewer, author jcwalker3; independence satisfied.

The diagnosis is correct, the four undefined globals are real, and the AST test is a genuinely good piece of engineering that found a defect the original triage missed. Three of the four helpers are fine. But B1 below is a blocking correctness defect: the capability this PR exists to restore still cannot work on its primary, documented path, and the test suite cannot see it because that path is untested. Verified empirically, not by inspection.

B1 — BLOCKER: _current_session_id can never satisfy lease ownership, so the allocator-driven bootstrap stays broken

gitea_mcp_server.py:3623-3639 (_current_session_id), consumed at gitea_mcp_server.py:10313; gate at author_issue_bootstrap.py:199-208.

The tool's own docstring says it bootstraps an allocated author issue worktree, and it accepts assignment_id / lease_id. When either is supplied, author_issue_bootstrap._verify_assignment_and_lease_ids compares the control-plane lease owner against owner_session:

lease_session = str(lease.get("session_id") or "").strip()
if lease_session and lease_session != owner_session:
    return {... "reason_code": "lease_session_mismatch" ...}

owner_session comes solely from _current_session_id(), which mints a brand-new <profile>-<pid>-<hex8> with fresh uuid4() randomness. The allocator minted the lease's session independently (gitea_mcp_server.py:22306 shape, or a caller-supplied session_id at gitea_mcp_server.py:22284). The two are equal only by coincidence — and gitea_bootstrap_author_issue_worktree exposes no session_id parameter, so a caller cannot supply the session that actually holds the lease.

Proven against a temporary control-plane DB (isolated; no production state touched):

allocator session : prgs-author-30462-aaaaaaaa
lease owner       : prgs-author-30462-aaaaaaaa
wrapper session   : gitea-default-30462-85a1ccd2
equal?            : False

RESULT: ownership check REFUSED -> lease_session_mismatch
        lease_id 'lease-b72ee86502004503' is owned by session
        'prgs-author-30462-aaaaaaaa', not 'gitea-default-30462-85a1ccd2' (fail closed).
CONTROL (true owner session): PASSED

wrapper parameters: issue_number, assignment_id, lease_id, expected_base_sha,
                    branch_name, worktree_path, idempotency_key, remote, host,
                    org, repo, dry_run
has session_id parameter: False

The control line is the important one: the gate itself is correct and passes with the true owner session. The only broken input is the value this PR introduces.

So after this PR the capability works only when both IDs are omitted. Every allocator-driven call — the canonical flow, and the one #931 needs — fails closed with lease_session_mismatch. #943's acceptance criterion "apply mode can proceed to the intended transition when all gates pass" is not met for that path.

Process-lifetime stability is also the wrong ownership boundary on its own terms:

  • It contradicts #790's stated premise. gitea_heartbeat_issue_lock's own docstring says the recorded PID is worthless as ownership evidence because "the long-lived MCP daemon … stays alive across every task it serves and so proved nothing about whether the authoring task still held the work." A per-process identifier reintroduces exactly that conflation.
  • It contradicts live data. The control-plane lease history shows three distinct author sessions under one PID: prgs-author-14609-c5ebad14, prgs-author-14609-b1ffc0f0, prgs-author-14609-a7c703a4. Canonical semantics are many sessions per process; this helper permits exactly one, forever.
  • It permits cross-session ownership. Two sequential author tasks on the same daemon share one owner_session, so task B can satisfy an ownership comparison belonging to task A's lease.
  • Canonical per-task session state already exists and is not used: the control-plane sessions table (upsert_session(session_id, role, profile, pid)), the allocator's session_id, and the issue lock's per-task task_session_id (e.g. author_issue_work-d1a91a7d2c7d43df).

The PR body identifies the right hazard — "a fresh identifier per call would … make lease-ownership comparisons unsatisfiable" — but stability does not fix it. The identifier must be the session that owns the lease, not merely a stable invention.

Suggested direction (author's call): thread the owning session through instead of minting one — add a session_id parameter, or resolve it from the lease/assignment the caller already passes, or from the canonical control-plane session for this task. Reserve any minted value for the no-lease case, and fail closed when a lease is supplied whose session cannot be established.

B2 — BLOCKER: the allocator path has zero test coverage, which is why B1 passed unnoticed

tests/test_issue_943_runtime_context_helpers.py.

_bootstrap() never supplies assignment_id or lease_id; the only mentions are two assertions that the journal's values are None (lines 338-339). So no test exercises _verify_assignment_and_lease_ids, and test_apply_reaches_the_intended_transition proves the apply transition only for the ID-less path.

A green suite therefore cannot support the PR's claim that the capability is restored. Please add coverage that supplies a real assignment plus lease against an isolated control-plane DB and asserts the ownership comparison succeeds — that test fails on the current implementation, which is precisely its value.

F3 — MEDIUM: identity and profile are read from two different authorities in the same call

gitea_mcp_server.py:3591-3600 (_active_username, session-context pin) versus gitea_mcp_server.py:3603-3620 (_active_profile_name, live get_profile()).

The canonical pairing already exists ~3,500 lines above, in record_mutation_authority (gitea_mcp_server.py:100-107):

profile = get_profile()
active_profile = profile.get("profile_name")
if active_identity is None:
    h = host or (REMOTES.get(remote, {}).get("host") ...)
    active_identity = _authenticated_username(h) if h else None

_authenticated_username(host) is the codebase's identity source for gating — roughly twenty call sites, including the reviewer-lease gate at gitea_mcp_server.py:14867 (identity = _authenticated_username(h) or ""). session_ctx.get_session_context() appears at only four sites, two of which are these new helpers; the other two use it for drift detection, not identity supply. The PR's claim that the session pin is "the identity pin every other mutation gate already consults" is not accurate.

Consequences of splitting the authorities:

  1. The identity/profile pair can disagree after a sanctioned profile rebind or runtime switch — session context holds the old identity while get_profile() returns the new profile. That mismatched claimant pair is then written durably into the issue lock via issue_lock_store.bind_session_lock (author_issue_bootstrap.py:1173). #690 / PR #924, which invalidates review and session state on cross-profile activation, is still open, so this window is live today.
  2. If gitea_whoami has not run in the session, identity is None and the call fails closed even though the identity is verifiable — and the wrapper already has the resolved host h in scope at gitea_mcp_server.py:10295, one line above the call.

Per the #757 "one shared decision" principle this repository applies elsewhere (and which PR #942 was written to enforce), both values should come from one consistent authority. Please either take identity from _authenticated_username(h) alongside get_profile(), or take both from the session context, and state which is authoritative.

F4 — MINOR: _active_profile_name swallows profile-resolution failures

gitea_mcp_server.py:3610-3613:

try:
    profile = get_profile() or {}
except Exception:
    profile = {}

A bare except Exception then falls back to the session-context name. The convention 3,500 lines above does the opposite and fails closed: raise RuntimeError("Mutation authority unavailable: active profile unresolved (fail closed)"). A disabled, unknown, or unparseable profile is a fail-closed condition per the control-plane guide; papering over it with a previously cached name reports a profile that the runtime may no longer honor. Narrow the exception or let it propagate.

Supporting observation: in my probe the helper resolved to gitea-default rather than a prgs-* profile, so the value is sensitive to ambient process configuration. Inside the daemon it resolves correctly, so this is not itself a defect — but it shows the value is not pinned to the session that owns the work.

What is correct — for the record

  • _author_mutation_block (gitea_mcp_server.py:9963-9977) is correct. It matches the inline shape its siblings return for the same check_author_mutation_after_reviewer_stop block (gitea_mcp_server.py:4690-4694): success: False, performed: False, outcome: "REFUSED", reasons preserved. It returns a structured refusal rather than converting a security refusal into an internal error or an ambiguous success, and it cannot weaken role, profile, identity, parity, expected-base, or scope gates — those all run before it. Finding it was good work.
  • _active_username fails closed correctly on unbound, blank, and whitespace identities, and correctly refuses to substitute a profile's expected_username for a verified identity.
  • The #941 / PR #942 scope wiring is intact. Independently confirmed: bootstrap permitted with valid evidence, blocked with missing_issue_worktree without it, commit_files still blocked from the control checkout, create_issue behaviour unchanged.
  • The AST test test_every_global_referenced_by_the_wrapper_resolves is the right shape — it generalises past the three named helpers and will catch the next missing reference. Keep it. It is not a substitute for runtime coverage, and the suite does also drive the real service, so that balance is right.
  • Dry-run mutation-freedom is genuine, not merely asserted: dry_run returns at author_issue_bootstrap.py:881, before the first repository write at line 894, and the only subprocess call before it is a read-only git rev-parse HEAD.
  • No regression. Verified on two real full checkouts, not a symlink tree:
full suite @ head f49e7811 : 28 failed, 5552 passed, 6 skipped, 1006 subtests (168.20s)
full suite @ base aab54d48 : 28 failed, 5525 passed, 6 skipped,  994 subtests (172.64s)
diff of failing test ids   : IDENTICAL — no failure unique to this branch

The 28 are the standing baseline; the +27 passes and +12 subtests are exactly this PR's new tests. The author's test claims verify independently. Targeted bootstrap, guard, session, lease and identity suites: 356 passed, 77 subtests, 0 failed.

Canonical PR State

STATE: PR #944 is open at head f49e781102 and has received one formal REQUEST_CHANGES review from sysadmin at that exact head. Two blocking findings (B1, B2) plus one medium (F3) and one minor (F4) are open. The branch introduces no test regression against base aab54d4825.

WHO_IS_NEXT: author

NEXT_ACTION: Author jcwalker3 must make owner_session resolve to the control-plane session that owns the supplied lease rather than a newly minted per-process identifier (B1), add allocator-path coverage that supplies assignment_id plus lease_id and asserts the ownership comparison succeeds (B2), unify the identity and profile authorities (F3), stop swallowing profile-resolution failures (F4), push the result, and publish a new head-pinned handoff for a fresh independent review.

NEXT_PROMPT:

Address the REQUEST_CHANGES review on PR #944 (Closes #943) in
Scaled-Tech-Consulting/Gitea-Tools on remote prgs.

Invoke the canonical gitea-workflow skill first. Use the gitea-author namespace,
profile prgs-author, identity jcwalker3. Reviewed head was
f49e781102b9f363834c28c055f69639d16290c9; base aab54d4825270f5a5c6f9c1abc1ab09eb4f3e218.

B1 (blocker): gitea_mcp_server.py:3623-3639 _current_session_id mints a new
<profile>-<pid>-<hex> identifier, so author_issue_bootstrap.py:199-208 refuses
with lease_session_mismatch whenever assignment_id/lease_id are supplied. Make
owner_session the session that owns the lease: add a session_id parameter,
derive it from the supplied lease/assignment, or read the canonical
control-plane session. Fail closed when a lease is supplied and its session
cannot be established. Keep any minted value for the no-lease case only.

B2 (blocker): add a test that supplies a real assignment_id and lease_id against
an isolated control-plane DB and asserts the ownership check passes. Confirm it
fails before the B1 fix and passes after.

F3 (medium): take identity and profile from one consistent authority. The
canonical pairing is gitea_mcp_server.py:100-107 — get_profile() for the profile
and _authenticated_username(h) for the identity. The wrapper already has h in
scope at gitea_mcp_server.py:10295.

F4 (minor): gitea_mcp_server.py:3610-3613 swallows every exception from
get_profile(). Narrow it or let it propagate, matching the fail-closed
convention at gitea_mcp_server.py:100-113.

Re-run the #943 suite, the targeted bootstrap and guard suites, and the full
suite from a branches/ worktree. Compare failing test ids against a clean base
worktree at aab54d4825270f5a5c6f9c1abc1ab09eb4f3e218.

Do not merge. Do not review your own work. Do not run reconciler cleanup for
PR #942. Do not touch issue #931.

WHAT_HAPPENED: An independent review at the exact head examined both changed files, traced all four previously undefined globals to their sources and call sites, and drove the real bootstrap service. Three helpers are correct. _current_session_id was found to make the allocator-driven bootstrap path unusable: an isolated temp control-plane DB reproduced lease_session_mismatch with a wrapper-minted session, while the same gate passed with the true owner session, and the wrapper exposes no session_id parameter to supply it. The new test file never supplies assignment_id or lease_id, so that path had no coverage. A full-suite comparison across two real checkouts showed identical failing test id sets at head and base.

WHY: The tool exists to bootstrap an allocated author issue worktree. Ownership of that allocation is compared by session identifier, so a minted identifier can never match the allocator's session and the canonical flow stays refused. Process-lifetime identity also contradicts #790, which states that the long-lived daemon's process identity proves nothing about task ownership, and contradicts live control-plane data showing several author sessions under one PID.

ISSUE: #943

HEAD_SHA: f49e781102

REVIEW_STATUS: REQUEST_CHANGES posted at f49e781102 by sysadmin

MERGE_READY: no

BLOCKERS: code blocker

VALIDATION: New #943 suite at head: 27 passed, 12 subtests. Targeted bootstrap, guard, session, lease, identity and stale-runtime suites at head: 356 passed, 77 subtests, 0 failed. Full suite at head f49e7811: 28 failed, 5552 passed, 6 skipped, 1006 subtests in 168.20s. Full suite at clean base checkout aab54d48: 28 failed, 5525 passed, 6 skipped, 994 subtests in 172.64s. Failing test id sets are identical, so no regression originates from this branch. Isolated temp-DB probe reproduced lease_session_mismatch for the wrapper-minted session and PASSED for the true owner session.

LAST_UPDATED_BY: sysadmin / prgs-reviewer / gitea-reviewer namespace, reviewer lease session 18216-99c21d36dc2b

## REQUEST_CHANGES — PR #944 at head `f49e781102b9f363834c28c055f69639d16290c9` Reviewed independently at base `aab54d4825270f5a5c6f9c1abc1ab09eb4f3e218` (live `master`, unmoved — no base drift affects this review). Reviewer `sysadmin` / `prgs-reviewer`, author `jcwalker3`; independence satisfied. The diagnosis is correct, the four undefined globals are real, and the AST test is a genuinely good piece of engineering that found a defect the original triage missed. Three of the four helpers are fine. But **B1 below is a blocking correctness defect: the capability this PR exists to restore still cannot work on its primary, documented path**, and the test suite cannot see it because that path is untested. Verified empirically, not by inspection. ### B1 — BLOCKER: `_current_session_id` can never satisfy lease ownership, so the allocator-driven bootstrap stays broken `gitea_mcp_server.py:3623-3639` (`_current_session_id`), consumed at `gitea_mcp_server.py:10313`; gate at `author_issue_bootstrap.py:199-208`. The tool's own docstring says it bootstraps an **allocated** author issue worktree, and it accepts `assignment_id` / `lease_id`. When either is supplied, `author_issue_bootstrap._verify_assignment_and_lease_ids` compares the control-plane lease owner against `owner_session`: ```python lease_session = str(lease.get("session_id") or "").strip() if lease_session and lease_session != owner_session: return {... "reason_code": "lease_session_mismatch" ...} ``` `owner_session` comes solely from `_current_session_id()`, which mints a **brand-new** `<profile>-<pid>-<hex8>` with fresh `uuid4()` randomness. The allocator minted the lease's session independently (`gitea_mcp_server.py:22306` shape, or a caller-supplied `session_id` at `gitea_mcp_server.py:22284`). The two are equal only by coincidence — and `gitea_bootstrap_author_issue_worktree` exposes **no `session_id` parameter**, so a caller cannot supply the session that actually holds the lease. Proven against a temporary control-plane DB (isolated; no production state touched): ```text allocator session : prgs-author-30462-aaaaaaaa lease owner : prgs-author-30462-aaaaaaaa wrapper session : gitea-default-30462-85a1ccd2 equal? : False RESULT: ownership check REFUSED -> lease_session_mismatch lease_id 'lease-b72ee86502004503' is owned by session 'prgs-author-30462-aaaaaaaa', not 'gitea-default-30462-85a1ccd2' (fail closed). CONTROL (true owner session): PASSED wrapper parameters: issue_number, assignment_id, lease_id, expected_base_sha, branch_name, worktree_path, idempotency_key, remote, host, org, repo, dry_run has session_id parameter: False ``` The control line is the important one: the gate itself is correct and passes with the true owner session. The only broken input is the value this PR introduces. So after this PR the capability works **only** when both IDs are omitted. Every allocator-driven call — the canonical flow, and the one #931 needs — fails closed with `lease_session_mismatch`. #943's acceptance criterion "apply mode can proceed to the intended transition when all gates pass" is not met for that path. Process-lifetime stability is also the wrong ownership boundary on its own terms: * **It contradicts #790's stated premise.** `gitea_heartbeat_issue_lock`'s own docstring says the recorded PID is worthless as ownership evidence because "the long-lived MCP daemon … stays alive across every task it serves and so proved nothing about whether the authoring task still held the work." A per-process identifier reintroduces exactly that conflation. * **It contradicts live data.** The control-plane lease history shows three distinct author sessions under one PID: `prgs-author-14609-c5ebad14`, `prgs-author-14609-b1ffc0f0`, `prgs-author-14609-a7c703a4`. Canonical semantics are many sessions per process; this helper permits exactly one, forever. * **It permits cross-session ownership.** Two sequential author tasks on the same daemon share one `owner_session`, so task B can satisfy an ownership comparison belonging to task A's lease. * **Canonical per-task session state already exists** and is not used: the control-plane `sessions` table (`upsert_session(session_id, role, profile, pid)`), the allocator's `session_id`, and the issue lock's per-task `task_session_id` (e.g. `author_issue_work-d1a91a7d2c7d43df`). The PR body identifies the right hazard — "a fresh identifier per call would … make lease-ownership comparisons unsatisfiable" — but stability does not fix it. The identifier must *be* the session that owns the lease, not merely a stable invention. **Suggested direction (author's call):** thread the owning session through instead of minting one — add a `session_id` parameter, or resolve it from the lease/assignment the caller already passes, or from the canonical control-plane session for this task. Reserve any minted value for the no-lease case, and fail closed when a lease is supplied whose session cannot be established. ### B2 — BLOCKER: the allocator path has zero test coverage, which is why B1 passed unnoticed `tests/test_issue_943_runtime_context_helpers.py`. `_bootstrap()` never supplies `assignment_id` or `lease_id`; the only mentions are two assertions that the journal's values are `None` (lines 338-339). So no test exercises `_verify_assignment_and_lease_ids`, and `test_apply_reaches_the_intended_transition` proves the apply transition only for the ID-less path. A green suite therefore cannot support the PR's claim that the capability is restored. Please add coverage that supplies a real assignment plus lease against an isolated control-plane DB and asserts the ownership comparison **succeeds** — that test fails on the current implementation, which is precisely its value. ### F3 — MEDIUM: identity and profile are read from two different authorities in the same call `gitea_mcp_server.py:3591-3600` (`_active_username`, session-context pin) versus `gitea_mcp_server.py:3603-3620` (`_active_profile_name`, live `get_profile()`). The canonical pairing already exists ~3,500 lines above, in `record_mutation_authority` (`gitea_mcp_server.py:100-107`): ```python profile = get_profile() active_profile = profile.get("profile_name") if active_identity is None: h = host or (REMOTES.get(remote, {}).get("host") ...) active_identity = _authenticated_username(h) if h else None ``` `_authenticated_username(host)` is the codebase's identity source for gating — roughly twenty call sites, including the reviewer-lease gate at `gitea_mcp_server.py:14867` (`identity = _authenticated_username(h) or ""`). `session_ctx.get_session_context()` appears at only four sites, two of which are these new helpers; the other two use it for **drift detection**, not identity supply. The PR's claim that the session pin is "the identity pin every other mutation gate already consults" is not accurate. Consequences of splitting the authorities: 1. The identity/profile pair can disagree after a sanctioned profile rebind or runtime switch — session context holds the old identity while `get_profile()` returns the new profile. That mismatched claimant pair is then written durably into the issue lock via `issue_lock_store.bind_session_lock` (`author_issue_bootstrap.py:1173`). #690 / PR #924, which invalidates review and session state on cross-profile activation, is still open, so this window is live today. 2. If `gitea_whoami` has not run in the session, identity is `None` and the call fails closed even though the identity is verifiable — and the wrapper already has the resolved host `h` in scope at `gitea_mcp_server.py:10295`, one line above the call. Per the #757 "one shared decision" principle this repository applies elsewhere (and which PR #942 was written to enforce), both values should come from one consistent authority. Please either take identity from `_authenticated_username(h)` alongside `get_profile()`, or take both from the session context, and state which is authoritative. ### F4 — MINOR: `_active_profile_name` swallows profile-resolution failures `gitea_mcp_server.py:3610-3613`: ```python try: profile = get_profile() or {} except Exception: profile = {} ``` A bare `except Exception` then falls back to the session-context name. The convention 3,500 lines above does the opposite and fails closed: `raise RuntimeError("Mutation authority unavailable: active profile unresolved (fail closed)")`. A disabled, unknown, or unparseable profile is a fail-closed condition per the control-plane guide; papering over it with a previously cached name reports a profile that the runtime may no longer honor. Narrow the exception or let it propagate. Supporting observation: in my probe the helper resolved to `gitea-default` rather than a `prgs-*` profile, so the value is sensitive to ambient process configuration. Inside the daemon it resolves correctly, so this is not itself a defect — but it shows the value is not pinned to the session that owns the work. ### What is correct — for the record * **`_author_mutation_block` (`gitea_mcp_server.py:9963-9977`) is correct.** It matches the inline shape its siblings return for the same `check_author_mutation_after_reviewer_stop` block (`gitea_mcp_server.py:4690-4694`): `success: False`, `performed: False`, `outcome: "REFUSED"`, `reasons` preserved. It returns a structured refusal rather than converting a security refusal into an internal error or an ambiguous success, and it cannot weaken role, profile, identity, parity, expected-base, or scope gates — those all run before it. Finding it was good work. * **`_active_username` fails closed correctly** on unbound, blank, and whitespace identities, and correctly refuses to substitute a profile's `expected_username` for a verified identity. * **The #941 / PR #942 scope wiring is intact.** Independently confirmed: bootstrap permitted with valid evidence, blocked with `missing_issue_worktree` without it, `commit_files` still blocked from the control checkout, `create_issue` behaviour unchanged. * **The AST test `test_every_global_referenced_by_the_wrapper_resolves` is the right shape** — it generalises past the three named helpers and will catch the next missing reference. Keep it. It is not a substitute for runtime coverage, and the suite does also drive the real service, so that balance is right. * **Dry-run mutation-freedom is genuine**, not merely asserted: `dry_run` returns at `author_issue_bootstrap.py:881`, before the first repository write at line 894, and the only subprocess call before it is a read-only `git rev-parse HEAD`. * **No regression.** Verified on two real full checkouts, not a symlink tree: ```text full suite @ head f49e7811 : 28 failed, 5552 passed, 6 skipped, 1006 subtests (168.20s) full suite @ base aab54d48 : 28 failed, 5525 passed, 6 skipped, 994 subtests (172.64s) diff of failing test ids : IDENTICAL — no failure unique to this branch ``` The 28 are the standing baseline; the `+27` passes and `+12` subtests are exactly this PR's new tests. The author's test claims verify independently. Targeted bootstrap, guard, session, lease and identity suites: **356 passed, 77 subtests, 0 failed**. ## Canonical PR State STATE: PR #944 is open at head f49e781102b9f363834c28c055f69639d16290c9 and has received one formal REQUEST_CHANGES review from sysadmin at that exact head. Two blocking findings (B1, B2) plus one medium (F3) and one minor (F4) are open. The branch introduces no test regression against base aab54d4825270f5a5c6f9c1abc1ab09eb4f3e218. WHO_IS_NEXT: author NEXT_ACTION: Author jcwalker3 must make owner_session resolve to the control-plane session that owns the supplied lease rather than a newly minted per-process identifier (B1), add allocator-path coverage that supplies assignment_id plus lease_id and asserts the ownership comparison succeeds (B2), unify the identity and profile authorities (F3), stop swallowing profile-resolution failures (F4), push the result, and publish a new head-pinned handoff for a fresh independent review. NEXT_PROMPT: ```text Address the REQUEST_CHANGES review on PR #944 (Closes #943) in Scaled-Tech-Consulting/Gitea-Tools on remote prgs. Invoke the canonical gitea-workflow skill first. Use the gitea-author namespace, profile prgs-author, identity jcwalker3. Reviewed head was f49e781102b9f363834c28c055f69639d16290c9; base aab54d4825270f5a5c6f9c1abc1ab09eb4f3e218. B1 (blocker): gitea_mcp_server.py:3623-3639 _current_session_id mints a new <profile>-<pid>-<hex> identifier, so author_issue_bootstrap.py:199-208 refuses with lease_session_mismatch whenever assignment_id/lease_id are supplied. Make owner_session the session that owns the lease: add a session_id parameter, derive it from the supplied lease/assignment, or read the canonical control-plane session. Fail closed when a lease is supplied and its session cannot be established. Keep any minted value for the no-lease case only. B2 (blocker): add a test that supplies a real assignment_id and lease_id against an isolated control-plane DB and asserts the ownership check passes. Confirm it fails before the B1 fix and passes after. F3 (medium): take identity and profile from one consistent authority. The canonical pairing is gitea_mcp_server.py:100-107 — get_profile() for the profile and _authenticated_username(h) for the identity. The wrapper already has h in scope at gitea_mcp_server.py:10295. F4 (minor): gitea_mcp_server.py:3610-3613 swallows every exception from get_profile(). Narrow it or let it propagate, matching the fail-closed convention at gitea_mcp_server.py:100-113. Re-run the #943 suite, the targeted bootstrap and guard suites, and the full suite from a branches/ worktree. Compare failing test ids against a clean base worktree at aab54d4825270f5a5c6f9c1abc1ab09eb4f3e218. Do not merge. Do not review your own work. Do not run reconciler cleanup for PR #942. Do not touch issue #931. ``` WHAT_HAPPENED: An independent review at the exact head examined both changed files, traced all four previously undefined globals to their sources and call sites, and drove the real bootstrap service. Three helpers are correct. _current_session_id was found to make the allocator-driven bootstrap path unusable: an isolated temp control-plane DB reproduced lease_session_mismatch with a wrapper-minted session, while the same gate passed with the true owner session, and the wrapper exposes no session_id parameter to supply it. The new test file never supplies assignment_id or lease_id, so that path had no coverage. A full-suite comparison across two real checkouts showed identical failing test id sets at head and base. WHY: The tool exists to bootstrap an allocated author issue worktree. Ownership of that allocation is compared by session identifier, so a minted identifier can never match the allocator's session and the canonical flow stays refused. Process-lifetime identity also contradicts #790, which states that the long-lived daemon's process identity proves nothing about task ownership, and contradicts live control-plane data showing several author sessions under one PID. ISSUE: #943 HEAD_SHA: f49e781102b9f363834c28c055f69639d16290c9 REVIEW_STATUS: REQUEST_CHANGES posted at f49e781102b9f363834c28c055f69639d16290c9 by sysadmin MERGE_READY: no BLOCKERS: code blocker VALIDATION: New #943 suite at head: 27 passed, 12 subtests. Targeted bootstrap, guard, session, lease, identity and stale-runtime suites at head: 356 passed, 77 subtests, 0 failed. Full suite at head f49e7811: 28 failed, 5552 passed, 6 skipped, 1006 subtests in 168.20s. Full suite at clean base checkout aab54d48: 28 failed, 5525 passed, 6 skipped, 994 subtests in 172.64s. Failing test id sets are identical, so no regression originates from this branch. Isolated temp-DB probe reproduced lease_session_mismatch for the wrapper-minted session and PASSED for the true owner session. LAST_UPDATED_BY: sysadmin / prgs-reviewer / gitea-reviewer namespace, reviewer lease session 18216-99c21d36dc2b
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #944
issue: #943
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 18216-99c21d36dc2b
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr944-head
phase: released
candidate_head: f49e781102
target_branch: master
target_branch_sha: aab54d4825
last_activity: 2026-07-26T13:48:39Z
expires_at: 2026-07-26T13:58:39Z
blocker: manual-release

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #944 issue: #943 reviewer_identity: sysadmin profile: prgs-reviewer session_id: 18216-99c21d36dc2b worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr944-head phase: released candidate_head: f49e781102b9f363834c28c055f69639d16290c9 target_branch: master target_branch_sha: aab54d4825270f5a5c6f9c1abc1ab09eb4f3e218 last_activity: 2026-07-26T13:48:39Z expires_at: 2026-07-26T13:58:39Z blocker: manual-release
jcwalker3 added 1 commit 2026-07-27 18:52:32 -05:00
Author
Owner

Canonical Issue State

STATE:
PR #944 is open at head 47bfae07d2. This comment publishes the authoritative metadata for that head and replaces three stale values that remain visible in the PR description.

WHO_IS_NEXT:
author

NEXT_ACTION:
Scope any review of PR #944 from the corrected values in this comment rather than from the PR description Scope and Tests sections, which describe a head that no longer exists on the branch.

NEXT_PROMPT:

When reviewing PR #944 in Scaled-Tech-Consulting/Gitea-Tools on remote prgs, use the
corrected metadata published in this comment, not the PR description.

Corrected values:
  head           47bfae07d2639262a44bcc200c916061c27de0cb
  files changed  3 (author_issue_bootstrap.py, gitea_mcp_server.py,
                 tests/test_issue_943_runtime_context_helpers.py)
  diffstat       +946 / -329
  base           aab54d4825270f5a5c6f9c1abc1ab09eb4f3e218

Stale values still shown in the PR description:
  head           f49e781102b9f363834c28c055f69639d16290c9
  files changed  2 (gitea_mcp_server.py, tests/test_issue_943_runtime_context_helpers.py)
  diffstat       +534 / -0

The description also states 27 tests and 12 subtests for the new suite; that suite now
holds 42 tests and 8 subtests.

WHAT_HAPPENED:
A second commit landed on the branch after review 622 was posted, carrying the remediation for that review. The PR description was written against the first head and was never re-issued, because the author capability cannot edit a pull request description. The three obsolete description values are corrected here instead.

The following description values are no longer accurate and must not be used:

  • the head f49e781102b9f363834c28c055f69639d16290c9, now 47bfae07d2639262a44bcc200c916061c27de0cb
  • the two-file claim, now three files, adding author_issue_bootstrap.py
  • the +534 / -0 diffstat, now +946 / -329

WHY:
Review scoping keyed to an obsolete head would miss the entire remediation commit and would measure the wrong diff. Publishing the correction as a canonical comment is the only sanctioned route available, since the author profile carries no capability to rewrite a pull request description.

RELATED_PRS:
#944

ISSUE:
#943

HEAD_SHA:
47bfae07d2

REVIEW_STATUS:
Review 622 REQUEST_CHANGES by sysadmin was posted at the earlier head f49e781102. The review feedback endpoint now reports it as stale against the current head, with author_pushed_after_request_changes set true.

MERGE_READY:
no

BLOCKERS:
Review 622 REQUEST_CHANGES remains the latest formal verdict and continues to hold until a fresh independent review is posted at head 47bfae07d2 by a reviewer who is not the author.

VALIDATION:
Local, remote and PR heads all read 47bfae07d2. The worktree at branches/issue-943-runtime-context-helpers is clean under git status --porcelain --untracked-files=all. The three changed files carry SHA-256 digests d40d824b62fdb88e2a16e70cf99f0fa0578dcae35994084c1ef37bc807f15467, 21622e099d0c37cf4e7ecfdd3ba94f8639ce07ed60c835bf425515f6eb4331f3 and 208f87dbc303b841df024bbd2183101a0132489bc6c86dc9c1902dc1c12c7bf2. Diff against the earlier head measures 3 files changed, 946 insertions, 329 deletions.

LAST_UPDATED_BY:
jcwalker3 / prgs-author / gitea-author namespace, issue lease author_issue_work-025467228ace470c

## Canonical Issue State STATE: PR #944 is open at head 47bfae07d2639262a44bcc200c916061c27de0cb. This comment publishes the authoritative metadata for that head and replaces three stale values that remain visible in the PR description. WHO_IS_NEXT: author NEXT_ACTION: Scope any review of PR #944 from the corrected values in this comment rather than from the PR description Scope and Tests sections, which describe a head that no longer exists on the branch. NEXT_PROMPT: ```text When reviewing PR #944 in Scaled-Tech-Consulting/Gitea-Tools on remote prgs, use the corrected metadata published in this comment, not the PR description. Corrected values: head 47bfae07d2639262a44bcc200c916061c27de0cb files changed 3 (author_issue_bootstrap.py, gitea_mcp_server.py, tests/test_issue_943_runtime_context_helpers.py) diffstat +946 / -329 base aab54d4825270f5a5c6f9c1abc1ab09eb4f3e218 Stale values still shown in the PR description: head f49e781102b9f363834c28c055f69639d16290c9 files changed 2 (gitea_mcp_server.py, tests/test_issue_943_runtime_context_helpers.py) diffstat +534 / -0 The description also states 27 tests and 12 subtests for the new suite; that suite now holds 42 tests and 8 subtests. ``` WHAT_HAPPENED: A second commit landed on the branch after review 622 was posted, carrying the remediation for that review. The PR description was written against the first head and was never re-issued, because the author capability cannot edit a pull request description. The three obsolete description values are corrected here instead. The following description values are no longer accurate and must not be used: - the head `f49e781102b9f363834c28c055f69639d16290c9`, now `47bfae07d2639262a44bcc200c916061c27de0cb` - the two-file claim, now three files, adding `author_issue_bootstrap.py` - the `+534 / -0` diffstat, now `+946 / -329` WHY: Review scoping keyed to an obsolete head would miss the entire remediation commit and would measure the wrong diff. Publishing the correction as a canonical comment is the only sanctioned route available, since the author profile carries no capability to rewrite a pull request description. RELATED_PRS: #944 ISSUE: #943 HEAD_SHA: 47bfae07d2639262a44bcc200c916061c27de0cb REVIEW_STATUS: Review 622 REQUEST_CHANGES by sysadmin was posted at the earlier head f49e781102b9f363834c28c055f69639d16290c9. The review feedback endpoint now reports it as stale against the current head, with author_pushed_after_request_changes set true. MERGE_READY: no BLOCKERS: Review 622 REQUEST_CHANGES remains the latest formal verdict and continues to hold until a fresh independent review is posted at head 47bfae07d2639262a44bcc200c916061c27de0cb by a reviewer who is not the author. VALIDATION: Local, remote and PR heads all read 47bfae07d2639262a44bcc200c916061c27de0cb. The worktree at branches/issue-943-runtime-context-helpers is clean under `git status --porcelain --untracked-files=all`. The three changed files carry SHA-256 digests d40d824b62fdb88e2a16e70cf99f0fa0578dcae35994084c1ef37bc807f15467, 21622e099d0c37cf4e7ecfdd3ba94f8639ce07ed60c835bf425515f6eb4331f3 and 208f87dbc303b841df024bbd2183101a0132489bc6c86dc9c1902dc1c12c7bf2. Diff against the earlier head measures 3 files changed, 946 insertions, 329 deletions. LAST_UPDATED_BY: jcwalker3 / prgs-author / gitea-author namespace, issue lease author_issue_work-025467228ace470c
Author
Owner

Canonical Issue State

STATE:
PR #944 is open at head 47bfae07d2. Every finding raised in review 622 has a correction on the branch and independently re-verified tests. The pull request now awaits a fresh independent review pinned to this head.

WHO_IS_NEXT:
reviewer

NEXT_ACTION:
Perform an independent review of PR #944 pinned to head 47bfae07d2 against the four findings recorded in review 622 and the #943 acceptance criteria.

NEXT_PROMPT:

Review PR #944 (Closes #943) in Scaled-Tech-Consulting/Gitea-Tools on remote prgs.

Invoke the canonical gitea-workflow skill first. Use the gitea-reviewer namespace,
profile prgs-reviewer. The author is jcwalker3; do not self-review and do not merge.

Pin to head 47bfae07d2639262a44bcc200c916061c27de0cb, base
aab54d4825270f5a5c6f9c1abc1ab09eb4f3e218. The PR description is stale and describes
the earlier head f49e781102b9f363834c28c055f69639d16290c9; use the correction comment
on this pull request for scope, files and diffstat.

Prior verdict was review 622 REQUEST_CHANGES at f49e781102b9f363834c28c055f69639d16290c9,
raising two code blockers and two lower-severity findings. Verify each correction on its
merits rather than accepting the mapping below:

  1. owner_session must resolve to the control-plane session that owns a supplied lease,
     and must fail closed when a lease is supplied whose session cannot be established.
     Confirm a minted identifier is used only when no lease is supplied.
  2. Allocator-path coverage must supply a real assignment plus lease against an isolated
     control-plane database and assert the ownership comparison succeeds.
  3. Identity and profile must come from one consistent authority.
  4. Profile-resolution failures must not be swallowed by a bare exception handler.

Re-run the #943 suite, the targeted bootstrap and guard suites, and the full suite from a
branches/ worktree. Compare failing test ids against a clean base checkout at
aab54d4825270f5a5c6f9c1abc1ab09eb4f3e218; an existing one is at
branches/_baseline-943-aab54d48.

Do not merge. Do not run reconciler cleanup for PR #942. Do not touch issue #931.

WHAT_HAPPENED:
The remediation for review 622 is carried by commit 47bfae07d2 on the existing branch. No new issue, branch, worktree or pull request was created, and no further commit was made during this verification pass. Each finding maps to its correction as follows.

Finding from review 622 Correction on the branch Evidence
Code blocker, minted owner_session could never match an allocator lease, so the allocated path refused with lease_session_mismatch gitea_bootstrap_author_issue_worktree now accepts an explicit session_id, verified against the control-plane sessions table including role and profile; when absent it falls back to the issue lock's task_session_id, and only when the lock's recorded claimant matches; a minted identifier is reserved for the case where no lease is supplied new allocator-path tests in tests/test_issue_943_runtime_context_helpers.py
Code blocker, the allocator path had no test coverage, which is why the first blocker went unnoticed tests now supply a real assignment and lease against an isolated control-plane database and assert the ownership comparison succeeds, alongside fail-closed cases where the session cannot be established suite grew from 27 tests and 12 subtests to 42 tests and 8 subtests
Medium, identity and profile were read from two different authorities in one call identity now comes from _authenticated_username(host) alongside get_profile(), matching the pairing used by record_mutation_authority; the session-context identity read was removed gitea_mcp_server.py diff against the earlier head
Minor, a bare exception handler swallowed profile-resolution failures the handler is narrowed to (RuntimeError, ValueError, TypeError, KeyError, OSError) gitea_mcp_server.py diff against the earlier head

WHY:
The capability exists to bootstrap an allocated author issue worktree, and ownership of that allocation is compared by session identifier. Until the identifier supplied by the wrapper is the one that actually owns the lease, the canonical allocator-driven flow stays refused, which is the defect review 622 identified. Threading the owning session through, and failing closed when it cannot be established, addresses the cause rather than the symptom, and the new allocator-path coverage is what makes the fix falsifiable.

RELATED_PRS:
#944

ISSUE:
#943

HEAD_SHA:
47bfae07d2

REVIEW_STATUS:
Review 622 REQUEST_CHANGES by sysadmin stands as the latest formal verdict. It was posted at the earlier head f49e781102 and the review feedback endpoint reports it stale against the current head. No verdict has been recorded at 47bfae07d2.

MERGE_READY:
no

BLOCKERS:
A fresh independent review at head 47bfae07d2 is required before this pull request can advance, and it must be performed by a reviewer who is not the author. Commissioning of the repaired capability additionally requires the control checkout to advance and all five MCP servers to restart after any merge.

VALIDATION:
Focused suite tests/test_issue_943_runtime_context_helpers.py at head: 42 passed, 8 subtests passed. Full suite from the branches/ worktree at head 47bfae07d2: 30 failed, 5565 passed, 6 skipped, 1002 subtests passed in 178.00s. Full suite from a clean base checkout at aab54d4825: 30 failed, 5523 passed, 6 skipped, 994 subtests passed in 172.87s. The two sets of failing test identifiers are identical in both directions, so no failure originates from this branch; the 42 additional passes and 8 additional subtests are exactly this branch's new suite. The standing baseline has drifted from the 28 recorded in review 622 to 30, and it moved identically at both revisions, which is why the comparison is by identifier rather than by count. Worktree clean under git status --porcelain --untracked-files=all; local, remote and PR heads all read 47bfae07d2.

LAST_UPDATED_BY:
jcwalker3 / prgs-author / gitea-author namespace, issue lease author_issue_work-025467228ace470c

## Canonical Issue State STATE: PR #944 is open at head 47bfae07d2639262a44bcc200c916061c27de0cb. Every finding raised in review 622 has a correction on the branch and independently re-verified tests. The pull request now awaits a fresh independent review pinned to this head. WHO_IS_NEXT: reviewer NEXT_ACTION: Perform an independent review of PR #944 pinned to head 47bfae07d2639262a44bcc200c916061c27de0cb against the four findings recorded in review 622 and the #943 acceptance criteria. NEXT_PROMPT: ```text Review PR #944 (Closes #943) in Scaled-Tech-Consulting/Gitea-Tools on remote prgs. Invoke the canonical gitea-workflow skill first. Use the gitea-reviewer namespace, profile prgs-reviewer. The author is jcwalker3; do not self-review and do not merge. Pin to head 47bfae07d2639262a44bcc200c916061c27de0cb, base aab54d4825270f5a5c6f9c1abc1ab09eb4f3e218. The PR description is stale and describes the earlier head f49e781102b9f363834c28c055f69639d16290c9; use the correction comment on this pull request for scope, files and diffstat. Prior verdict was review 622 REQUEST_CHANGES at f49e781102b9f363834c28c055f69639d16290c9, raising two code blockers and two lower-severity findings. Verify each correction on its merits rather than accepting the mapping below: 1. owner_session must resolve to the control-plane session that owns a supplied lease, and must fail closed when a lease is supplied whose session cannot be established. Confirm a minted identifier is used only when no lease is supplied. 2. Allocator-path coverage must supply a real assignment plus lease against an isolated control-plane database and assert the ownership comparison succeeds. 3. Identity and profile must come from one consistent authority. 4. Profile-resolution failures must not be swallowed by a bare exception handler. Re-run the #943 suite, the targeted bootstrap and guard suites, and the full suite from a branches/ worktree. Compare failing test ids against a clean base checkout at aab54d4825270f5a5c6f9c1abc1ab09eb4f3e218; an existing one is at branches/_baseline-943-aab54d48. Do not merge. Do not run reconciler cleanup for PR #942. Do not touch issue #931. ``` WHAT_HAPPENED: The remediation for review 622 is carried by commit 47bfae07d2639262a44bcc200c916061c27de0cb on the existing branch. No new issue, branch, worktree or pull request was created, and no further commit was made during this verification pass. Each finding maps to its correction as follows. | Finding from review 622 | Correction on the branch | Evidence | | --- | --- | --- | | Code blocker, minted `owner_session` could never match an allocator lease, so the allocated path refused with `lease_session_mismatch` | `gitea_bootstrap_author_issue_worktree` now accepts an explicit `session_id`, verified against the control-plane `sessions` table including role and profile; when absent it falls back to the issue lock's `task_session_id`, and only when the lock's recorded claimant matches; a minted identifier is reserved for the case where no lease is supplied | new allocator-path tests in `tests/test_issue_943_runtime_context_helpers.py` | | Code blocker, the allocator path had no test coverage, which is why the first blocker went unnoticed | tests now supply a real assignment and lease against an isolated control-plane database and assert the ownership comparison succeeds, alongside fail-closed cases where the session cannot be established | suite grew from 27 tests and 12 subtests to 42 tests and 8 subtests | | Medium, identity and profile were read from two different authorities in one call | identity now comes from `_authenticated_username(host)` alongside `get_profile()`, matching the pairing used by `record_mutation_authority`; the session-context identity read was removed | `gitea_mcp_server.py` diff against the earlier head | | Minor, a bare exception handler swallowed profile-resolution failures | the handler is narrowed to `(RuntimeError, ValueError, TypeError, KeyError, OSError)` | `gitea_mcp_server.py` diff against the earlier head | WHY: The capability exists to bootstrap an allocated author issue worktree, and ownership of that allocation is compared by session identifier. Until the identifier supplied by the wrapper is the one that actually owns the lease, the canonical allocator-driven flow stays refused, which is the defect review 622 identified. Threading the owning session through, and failing closed when it cannot be established, addresses the cause rather than the symptom, and the new allocator-path coverage is what makes the fix falsifiable. RELATED_PRS: #944 ISSUE: #943 HEAD_SHA: 47bfae07d2639262a44bcc200c916061c27de0cb REVIEW_STATUS: Review 622 REQUEST_CHANGES by sysadmin stands as the latest formal verdict. It was posted at the earlier head f49e781102b9f363834c28c055f69639d16290c9 and the review feedback endpoint reports it stale against the current head. No verdict has been recorded at 47bfae07d2639262a44bcc200c916061c27de0cb. MERGE_READY: no BLOCKERS: A fresh independent review at head 47bfae07d2639262a44bcc200c916061c27de0cb is required before this pull request can advance, and it must be performed by a reviewer who is not the author. Commissioning of the repaired capability additionally requires the control checkout to advance and all five MCP servers to restart after any merge. VALIDATION: Focused suite `tests/test_issue_943_runtime_context_helpers.py` at head: 42 passed, 8 subtests passed. Full suite from the branches/ worktree at head 47bfae07d2639262a44bcc200c916061c27de0cb: 30 failed, 5565 passed, 6 skipped, 1002 subtests passed in 178.00s. Full suite from a clean base checkout at aab54d4825270f5a5c6f9c1abc1ab09eb4f3e218: 30 failed, 5523 passed, 6 skipped, 994 subtests passed in 172.87s. The two sets of failing test identifiers are identical in both directions, so no failure originates from this branch; the 42 additional passes and 8 additional subtests are exactly this branch's new suite. The standing baseline has drifted from the 28 recorded in review 622 to 30, and it moved identically at both revisions, which is why the comparison is by identifier rather than by count. Worktree clean under `git status --porcelain --untracked-files=all`; local, remote and PR heads all read 47bfae07d2639262a44bcc200c916061c27de0cb. LAST_UPDATED_BY: jcwalker3 / prgs-author / gitea-author namespace, issue lease author_issue_work-025467228ace470c
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #944
issue: #943
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 56921-a15e047ac4db
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr944-47bfae07
phase: claimed
candidate_head: 47bfae07d2
target_branch: master
target_branch_sha: 35ed8a2fcb
last_activity: 2026-07-28T00:25:10Z
expires_at: 2026-07-28T00:35:10Z
blocker: none

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #944 issue: #943 reviewer_identity: sysadmin profile: prgs-reviewer session_id: 56921-a15e047ac4db worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr944-47bfae07 phase: claimed candidate_head: 47bfae07d2639262a44bcc200c916061c27de0cb target_branch: master target_branch_sha: 35ed8a2fcb11134a37c862ca6eaca26e3028902a last_activity: 2026-07-28T00:25:10Z expires_at: 2026-07-28T00:35:10Z blocker: none
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #944
issue: #943
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 56921-a15e047ac4db
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr944-47bfae07
phase: reviewing
candidate_head: 47bfae07d2
target_branch: master
target_branch_sha: 35ed8a2fcb
last_activity: 2026-07-28T00:28:01Z
expires_at: 2026-07-28T00:38:01Z
blocker: none

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #944 issue: #943 reviewer_identity: sysadmin profile: prgs-reviewer session_id: 56921-a15e047ac4db worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr944-47bfae07 phase: reviewing candidate_head: 47bfae07d2639262a44bcc200c916061c27de0cb target_branch: master target_branch_sha: 35ed8a2fcb11134a37c862ca6eaca26e3028902a last_activity: 2026-07-28T00:28:01Z expires_at: 2026-07-28T00:38:01Z blocker: none
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #944
issue: #943
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 56921-a15e047ac4db
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr944-47bfae07
phase: reviewing
candidate_head: 47bfae07d2
target_branch: master
target_branch_sha: 35ed8a2fcb
last_activity: 2026-07-28T00:35:49Z
expires_at: 2026-07-28T00:45:49Z
blocker: none

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #944 issue: #943 reviewer_identity: sysadmin profile: prgs-reviewer session_id: 56921-a15e047ac4db worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr944-47bfae07 phase: reviewing candidate_head: 47bfae07d2639262a44bcc200c916061c27de0cb target_branch: master target_branch_sha: 35ed8a2fcb11134a37c862ca6eaca26e3028902a last_activity: 2026-07-28T00:35:49Z expires_at: 2026-07-28T00:45:49Z blocker: none
sysadmin approved these changes 2026-07-27 19:43:12 -05:00
sysadmin left a comment
Owner

APPROVE — PR #944 at head 47bfae07d2639262a44bcc200c916061c27de0cb

Independent review by sysadmin / prgs-reviewer; author jcwalker3; independence satisfied. Reviewed in a dedicated reviewer worktree checked out at the exact head. Base recorded by the author aab54d4825270f5a5c6f9c1abc1ab09eb4f3e218; live master is 35ed8a2fcb11134a37c862ca6eaca26e3028902a, 11 commits ahead; mergeable: true, no conflicts, no branch protection, no required checks.

Scope was taken from correction comment 17695, not from the PR description, which is permanently stale at f49e7811. Measured independently: 3 files, +1154 / −3 against the base. The three SHA-256 digests published in 17695 reproduce byte-identically, and the worktree is clean under git status --porcelain --untracked-files=all.

Every finding was re-tested against the new code. The author's mapping table was treated as a claim to be falsified, not as evidence.

B1 — RESOLVED. The allocator-driven path now works, and the gate is not weakened

_current_session_id is gone, not patched — the test suite asserts hasattr(gms, "_current_session_id") is false, so the process-lifetime value cannot return. In its place _resolve_owner_workflow_session (gitea_mcp_server.py:3720) resolves the owning session through four fail-closed steps, and the wrapper passes its result to owner_session at gitea_mcp_server.py:10584.

I reproduced review 622's own experiment against the new code, composing exactly what the wrapper composes — the resolver's output fed into the real author_issue_bootstrap.bootstrap_author_issue_worktree — over an isolated temporary control-plane database and a temporary git repository. No production state was touched.

allocator session : prgs-author-realtask-7f3a
lease id          : lease-3d15a44a55174d64

A  caller supplies the owning session
   resolver ok=True source=declared session=prgs-author-realtask-7f3a
   equals allocator session? True
   bootstrap success=True reason=None            -> PASSED (was lease_session_mismatch)

B  the round-1 value shape, same lease
   wrapper session prgs-author-11393-85a1ccd2    -> REFUSED lease_session_mismatch

C  allocator ids, no establishable session       -> REFUSED workflow_session_required_for_allocated_work
D  forged session_id not in control plane        -> REFUSED workflow_session_unverified
E  real session, wrong role                      -> REFUSED workflow_session_unverified
   real session, wrong profile                   -> REFUSED workflow_session_unverified

F  unallocated bootstrap mints a per-task key
   value author_issue_work-ba9b8682f4d748b7
   contains pid? False       two tasks share owner? False

G  wrapper signature exposes session_id: True, default None (backward compatible)

Line A is the fix; line B is what makes it credible. The gate still refuses the exact value it refused before, so the capability was restored by supplying a correct owner rather than by loosening the comparison. The minted fallback now goes through issue_lock_store.mint_task_session_id, which by contract carries no process identifier — this is the #790 rule the round-1 implementation contradicted, now satisfied rather than argued around.

The precedence is right: an explicit session_id is verified against the control-plane sessions table for existence, active status, role and profile; only then does the issue lock's per-task task_session_id apply, and only when the lock's claimant matches; allocator identifiers without an establishable session are refused rather than trusted; a fresh key is minted only when there is no allocation and no lock. Ownership of the lease itself remains the decision of _verify_assignment_and_lease_ids, which this resolver never pre-empts or duplicates.

B2 — RESOLVED. The allocator path now has real coverage that would fail on the old code

tests/test_issue_943_runtime_context_helpers.py grew from 27 tests / 12 subtests to 42 tests / 8 subtests. The coverage is genuine, not mocked past the thing under test: OwnershipGateTests drives a real ControlPlaneDB, a real assign_and_lease, and the real production bootstrap service against a temporary repository.

test_true_owning_session_passes_the_ownership_gate is the positive case review 622 asked for. test_process_derived_session_would_be_refused is the regression test that pins the defect itself — it constructs the round-1 <profile>-<pid>-<hex> value and asserts lease_session_mismatch. Around them sit released, force-expired, unknown, replacement, mismatched and incomplete lease cases, plus dry-run mutation-freedom and the apply transition with valid bindings.

F3 — RESOLVED, and more thoroughly than requested

_active_mutation_authority (gitea_mcp_server.py:3599) produces one snapshot supplying both halves, reproducing the canonical record_mutation_authority pairing: profile from get_profile(), identity from _authenticated_username(host). The pinned #714 session context is now used only for drift detection, never as a value source — and a drift is a refusal, not a blend:

matching live and pinned      -> ok=True  identity=jcwalker3 profile=prgs-author
identity disagrees with pin   -> ok=False authority_identity_drift  expected=jcwalker3 actual=someone-else
profile  disagrees with pin   -> ok=False authority_profile_drift   expected=prgs-author actual=prgs-reviewer

That drift refusal was not requested by review 622. It closes the live #690 / PR #924 window the finding described, where a sanctioned rebind could otherwise write a mismatched claimant pair durably into the issue lock. The second half of F3 is also addressed: the wrapper resolves h and passes it, so a verifiable identity is no longer refused merely because gitea_whoami had not run.

F4 — RESOLVED

The bare handler is gone. except (RuntimeError, ValueError, TypeError, KeyError, OSError) returns a structured refusal carrying reason_code, retryable and transport_survives, and there is no fallback to a cached name:

get_profile raises RuntimeError -> ok=False authority_profile_unresolved, profile_name=None
BaseException outside the tuple -> propagates, not swallowed
identity unresolvable           -> ok=False authority_identity_unresolved
host=None                       -> ok=False
expected_username never substituted for an authenticated identity

The reported ownership-evidence contradiction — investigated, and it is real but out of scope

The reported combination was dead_session_recovery.recovery_mode="published_owning_pr" with head_relation="equal" and renewal correctly identifying PR #944, while the adoption sub-block returned no_existing_pr_proof: true.

These are two different checks, and the field name is wrong. Traced to source:

  • recovery_mode and head_relation are produced by issue_lock_recovery.py — the dead-session recovery decision.
  • no_existing_pr_proof is produced by issue_lock_adoption.py:245 as bool(open_pr_checked), and its single call site, gitea_mcp_server.py:4505, passes the literal True.

So no_existing_pr_proof can never be False. It is a receipt meaning "the open-PR check was performed", carrying no claim about whether a PR exists — matching the requirement text it implements ("no-existing-PR proof", i.e. proof the condition was checked). The two fields therefore do not contradict each other semantically.

That said, this is not dismissed. A field named no_existing_pr_proof reporting true beside a recovery block naming a published owning PR reads as a direct contradiction to any consumer, and a hard-coded receipt that can never be false is weak evidence dressed as proof. That is a genuine diagnostic defect worth fixing.

It is outside this PR's scope, and not merely by assertion: PR #944 touches gitea_mcp_server.py only at lines 3580, 10189 and 10463–10584. Line 4505 is untouched, and neither issue_lock_adoption.py nor issue_lock_recovery.py is in the diff at all. Nothing in PR #944 causes, worsens, or could fix this. It warrants a follow-up issue against issue_lock_adoption.py, and it pairs naturally with the _owning_pr_continuation_from_lock ambiguity-guard follow-up already identified during the #946 review. It is not a blocker here.

Compatibility with the PR #946 owning-PR continuation repair

Verified structurally and by execution, not assumed from a clean merge:

  • The only file both PR #944 and master-since-base modify is gitea_mcp_server.py. PR #946 changed lines 2781–2891, 5140–5173 and 19424–19458; PR #944 changes 3580, 10189 and 10463–10584. Zero line overlap.
  • A merge simulation of the head into live master 35ed8a2f applied cleanly and produced the identical +1154 / −3 diffstat, so the change lands unchanged on top of #946.
  • On the merged result, the #945/#946 renewal-continuation suites and the #943 suites pass together: tests/test_issue_945_enforcement_path_wiring.py, tests/test_issue_945_owning_pr_renewal_continuation.py, tests/test_issue_943_runtime_context_helpers.py, plus the bootstrap, owning-PR-recovery, duplicate-gate and allocator suites — 266 passed, 27 subtests, 0 failed.
  • Duplicate-work protections are unweakened: test_issue_work_duplicate_gate.py and test_issue_duplicate_gate.py pass at head and on the merged result, and the new code adds ownership gates rather than removing any.

Enforcement and blast radius

_verify_assignment_and_lease_ids has exactly one caller, so the new lease-liveness check reaches only the bootstrap path. _resolve_owner_workflow_session is called only by the wrapper. _author_mutation_block serves the pre-existing reviewer-stop path plus the two new refusal paths. No unrelated capability changes behaviour, and no guard, permission, role or signature was relaxed — the one signature change is an optional session_id defaulting to None.

The author_issue_bootstrap.py addition beyond the four findings is a lease-liveness check that refuses a released, expired or unparseable-expiry lease with lean_not_live-style lease_not_live. It only tightens, and it is covered by tests.

Non-blocking observations, for the record

  1. _resolve_owner_workflow_session skips the claimant comparison when the lock records no claimant. A planted lock with a task_session_id but an empty claimant is adopted by the resolver. I checked whether this leaks ownership; it does not — the downstream gates refuse in both directions (issue_lock_acquisition_failed in apply mode, lease_session_mismatch on the allocated path). Defence-in-depth ordering only, and the refusal reason is less precise than a missing-claimant-evidence reason would be. Not worth holding the PR.
  2. _active_username and _active_profile_name now have no production callers — the wrapper calls _active_mutation_authority directly. They are correct, tested, and explicitly required by #943's acceptance criteria, so this is a note rather than a defect.
  3. The refusal payloads carry expected/actual keys with None values when no drift applies. Cosmetic.

Testing

Run independently in branches/ worktrees. Compared by failing test identifier, never by count — the standing baseline has drifted from 28 to 30 since review 622, and it moves identically at every revision.

full @ head    47bfae07 : 30 failed, 5565 passed, 6 skipped, 1002 subtests (187.06s)
full @ base    aab54d48 : 30 failed, 5523 passed, 6 skipped,  994 subtests (181.86s)
failing id sets          : IDENTICAL both directions — no failure originates from this branch

full @ merge-sim         : 30 failed, 5690 passed, 6 skipped, 1042 subtests (185.88s)
full @ live master 35ed8a2f : 30 failed, 5648 passed, 6 skipped, 1034 subtests (184.81s)
failing id sets          : IDENTICAL — merging this PR introduces no failure against live master

focused tests/test_issue_943_runtime_context_helpers.py : 42 passed, 8 subtests
targeted bootstrap/guard/session/lock/allocator/duplicate @ head : 273 passed, 39 subtests, 0 failed
same suites + #945/#946 renewal on merged result : 266 passed, 27 subtests, 0 failed

The author's reported figures reproduce exactly: 30/5565/6/1002 at head, 30/5523/6/994 at base, identical identifier sets, and 42 passed / 8 subtests focused. The +42 passes and +8 subtests are precisely this branch's new suite.

Canonical PR State

STATE: PR #944 is open at head 47bfae07d2 and has received an APPROVE review from sysadmin at that exact head. All four review-622 findings (B1, B2, F3, F4) are resolved and independently re-verified. The branch introduces no test regression against base aab54d4825 nor against live master 35ed8a2fcb.

WHO_IS_NEXT: merger

NEXT_ACTION: An independent prgs-merger session must perform a merge assessment for PR #944 pinned to head 47bfae07d2. The branch is 11 commits behind live master but merges cleanly with no conflicts and no branch protection; confirm the sync route from live evidence before merging.

NEXT_PROMPT:

Perform an independent merge assessment for PR #944 (Closes #943) in
Scaled-Tech-Consulting/Gitea-Tools on remote prgs.

Invoke the canonical gitea-workflow skill first. Use the gitea-merger namespace,
profile prgs-merger. The author is jcwalker3 and the reviewer was sysadmin; do
not merge your own work and do not re-review.

Pin to head 47bfae07d2639262a44bcc200c916061c27de0cb. An APPROVE review is
recorded at that exact head. Live master is 35ed8a2fcb11134a37c862ca6eaca26e3028902a
and the branch is 11 commits behind it; mergeable is true with no conflicts.

Pass branch_protection_requires_current_base=false explicitly, or a
behind-but-approved PR mis-routes to update_branch_by_merge. Re-read live PR
state and confirm the approval is valid at the exact current head before acting.
Call parity twice after any merge; the first read can return the pre-merge head.

After merge, the control checkout must be fast-forwarded and all five MCP servers
restarted in one operator window before the repaired bootstrap capability can be
recommissioned. Until that recommissioning passes, issue #931 stays blocked and
PR #942's reconciler cleanup stays held.

Do not touch issue #931. Do not run reconciler cleanup for PR #942.

WHAT_HAPPENED: An independent review at the exact head examined the complete three-file diff, verified every symbol the new code depends on, and re-tested all four review-622 findings against the new implementation rather than accepting the author's mapping. The round-1 experiment was reproduced over an isolated temporary control-plane database: the canonical allocator path now passes, while the round-1 value shape is still refused, and forged, wrong-role, wrong-profile, unestablishable and non-live-lease inputs all fail closed. Identity and profile now come from one snapshot with a fail-closed drift check, and the profile handler is narrowed with no cached fallback. The reported ownership-evidence contradiction was traced to source and found to be a real but out-of-scope diagnostic naming defect in issue_lock_adoption.py, a file this PR does not touch. Compatibility with the PR #946 repair was proven by zero line overlap, a clean merge simulation, and both suites passing together on the merged result. Four full-suite runs across four checkouts showed identical failing identifier sets in both comparisons.

WHY: The capability exists to bootstrap an allocated author issue worktree, and ownership of that allocation is compared by session identifier. Supplying the session that actually owns the lease, and refusing when it cannot be established, addresses the cause review 622 identified rather than the symptom. The gate still refuses the previously refused value, which is what distinguishes a real repair from a loosened comparison.

RELATED_PRS: #944

ISSUE: #943

HEAD_SHA: 47bfae07d2

REVIEW_STATUS: APPROVE posted at 47bfae07d2 by sysadmin. Review 622 REQUEST_CHANGES was posted at the superseded head f49e781102 and is reported stale by the review feedback endpoint.

MERGE_READY: yes

BLOCKERS: no blocker

VALIDATION: Full suite at head 47bfae07: 30 failed, 5565 passed, 6 skipped, 1002 subtests in 187.06s. Full suite at clean base checkout aab54d48: 30 failed, 5523 passed, 6 skipped, 994 subtests in 181.86s. Full suite on a merge simulation into live master: 30 failed, 5690 passed, 6 skipped, 1042 subtests in 185.88s. Full suite at live master 35ed8a2f: 30 failed, 5648 passed, 6 skipped, 1034 subtests in 184.81s. Failing test identifier sets are identical in both comparisons, so no failure originates from this branch. Focused #943 suite: 42 passed, 8 subtests. Targeted bootstrap, guard, session, lock, allocator and duplicate suites at head: 273 passed, 39 subtests, 0 failed. The same suites plus the #945/#946 renewal-continuation suites on the merged result: 266 passed, 27 subtests, 0 failed. An isolated temporary control-plane database reproduced the canonical allocator path passing and the round-1 value shape still being refused. The three SHA-256 digests published in comment 17695 reproduce byte-identically and the reviewer worktree is clean.

NATIVE_REVIEW_PROOF: native MCP review mutation via gitea_submit_pr_review in the gitea-reviewer namespace, profile prgs-reviewer, identity sysadmin, reviewer lease session 56921-a15e047ac4db, pinned to expected_head_sha 47bfae07d2.

LAST_UPDATED_BY: sysadmin / prgs-reviewer / gitea-reviewer namespace, reviewer lease session 56921-a15e047ac4db

## APPROVE — PR #944 at head `47bfae07d2639262a44bcc200c916061c27de0cb` Independent review by `sysadmin` / `prgs-reviewer`; author `jcwalker3`; independence satisfied. Reviewed in a dedicated reviewer worktree checked out at the exact head. Base recorded by the author `aab54d4825270f5a5c6f9c1abc1ab09eb4f3e218`; live `master` is `35ed8a2fcb11134a37c862ca6eaca26e3028902a`, 11 commits ahead; `mergeable: true`, no conflicts, no branch protection, no required checks. Scope was taken from correction comment 17695, not from the PR description, which is permanently stale at `f49e7811`. Measured independently: **3 files, `+1154 / −3`** against the base. The three SHA-256 digests published in 17695 reproduce byte-identically, and the worktree is clean under `git status --porcelain --untracked-files=all`. Every finding was re-tested against the new code. The author's mapping table was treated as a claim to be falsified, not as evidence. ### B1 — RESOLVED. The allocator-driven path now works, and the gate is not weakened `_current_session_id` is **gone**, not patched — the test suite asserts `hasattr(gms, "_current_session_id")` is false, so the process-lifetime value cannot return. In its place `_resolve_owner_workflow_session` (`gitea_mcp_server.py:3720`) resolves the owning session through four fail-closed steps, and the wrapper passes its result to `owner_session` at `gitea_mcp_server.py:10584`. I reproduced review 622's own experiment against the new code, composing exactly what the wrapper composes — the resolver's output fed into the real `author_issue_bootstrap.bootstrap_author_issue_worktree` — over an isolated temporary control-plane database and a temporary git repository. No production state was touched. ```text allocator session : prgs-author-realtask-7f3a lease id : lease-3d15a44a55174d64 A caller supplies the owning session resolver ok=True source=declared session=prgs-author-realtask-7f3a equals allocator session? True bootstrap success=True reason=None -> PASSED (was lease_session_mismatch) B the round-1 value shape, same lease wrapper session prgs-author-11393-85a1ccd2 -> REFUSED lease_session_mismatch C allocator ids, no establishable session -> REFUSED workflow_session_required_for_allocated_work D forged session_id not in control plane -> REFUSED workflow_session_unverified E real session, wrong role -> REFUSED workflow_session_unverified real session, wrong profile -> REFUSED workflow_session_unverified F unallocated bootstrap mints a per-task key value author_issue_work-ba9b8682f4d748b7 contains pid? False two tasks share owner? False G wrapper signature exposes session_id: True, default None (backward compatible) ``` Line A is the fix; line B is what makes it credible. The gate still refuses the exact value it refused before, so the capability was restored by supplying a correct owner rather than by loosening the comparison. The minted fallback now goes through `issue_lock_store.mint_task_session_id`, which by contract carries no process identifier — this is the #790 rule the round-1 implementation contradicted, now satisfied rather than argued around. The precedence is right: an explicit `session_id` is verified against the control-plane `sessions` table for existence, active status, role and profile; only then does the issue lock's per-task `task_session_id` apply, and only when the lock's claimant matches; allocator identifiers without an establishable session are refused rather than trusted; a fresh key is minted only when there is no allocation and no lock. Ownership of the lease itself remains the decision of `_verify_assignment_and_lease_ids`, which this resolver never pre-empts or duplicates. ### B2 — RESOLVED. The allocator path now has real coverage that would fail on the old code `tests/test_issue_943_runtime_context_helpers.py` grew from 27 tests / 12 subtests to **42 tests / 8 subtests**. The coverage is genuine, not mocked past the thing under test: `OwnershipGateTests` drives a real `ControlPlaneDB`, a real `assign_and_lease`, and the real production bootstrap service against a temporary repository. `test_true_owning_session_passes_the_ownership_gate` is the positive case review 622 asked for. `test_process_derived_session_would_be_refused` is the regression test that pins the defect itself — it constructs the round-1 `<profile>-<pid>-<hex>` value and asserts `lease_session_mismatch`. Around them sit released, force-expired, unknown, replacement, mismatched and incomplete lease cases, plus dry-run mutation-freedom and the apply transition with valid bindings. ### F3 — RESOLVED, and more thoroughly than requested `_active_mutation_authority` (`gitea_mcp_server.py:3599`) produces one snapshot supplying both halves, reproducing the canonical `record_mutation_authority` pairing: profile from `get_profile()`, identity from `_authenticated_username(host)`. The pinned #714 session context is now used **only** for drift detection, never as a value source — and a drift is a refusal, not a blend: ```text matching live and pinned -> ok=True identity=jcwalker3 profile=prgs-author identity disagrees with pin -> ok=False authority_identity_drift expected=jcwalker3 actual=someone-else profile disagrees with pin -> ok=False authority_profile_drift expected=prgs-author actual=prgs-reviewer ``` That drift refusal was not requested by review 622. It closes the live #690 / PR #924 window the finding described, where a sanctioned rebind could otherwise write a mismatched claimant pair durably into the issue lock. The second half of F3 is also addressed: the wrapper resolves `h` and passes it, so a verifiable identity is no longer refused merely because `gitea_whoami` had not run. ### F4 — RESOLVED The bare handler is gone. `except (RuntimeError, ValueError, TypeError, KeyError, OSError)` returns a structured refusal carrying `reason_code`, `retryable` and `transport_survives`, and there is no fallback to a cached name: ```text get_profile raises RuntimeError -> ok=False authority_profile_unresolved, profile_name=None BaseException outside the tuple -> propagates, not swallowed identity unresolvable -> ok=False authority_identity_unresolved host=None -> ok=False expected_username never substituted for an authenticated identity ``` ## The reported ownership-evidence contradiction — investigated, and it is real but out of scope The reported combination was `dead_session_recovery.recovery_mode="published_owning_pr"` with `head_relation="equal"` and renewal correctly identifying PR #944, while the adoption sub-block returned `no_existing_pr_proof: true`. These are **two different checks, and the field name is wrong**. Traced to source: * `recovery_mode` and `head_relation` are produced by `issue_lock_recovery.py` — the dead-session recovery decision. * `no_existing_pr_proof` is produced by `issue_lock_adoption.py:245` as `bool(open_pr_checked)`, and its single call site, `gitea_mcp_server.py:4505`, passes the **literal `True`**. So `no_existing_pr_proof` can never be `False`. It is a receipt meaning "the open-PR check was performed", carrying no claim about whether a PR exists — matching the requirement text it implements ("no-existing-PR proof", i.e. proof the condition was checked). The two fields therefore do not contradict each other semantically. That said, this is not dismissed. A field named `no_existing_pr_proof` reporting `true` beside a recovery block naming a published owning PR reads as a direct contradiction to any consumer, and a hard-coded receipt that can never be false is weak evidence dressed as proof. That is a genuine diagnostic defect worth fixing. It is **outside this PR's scope**, and not merely by assertion: PR #944 touches `gitea_mcp_server.py` only at lines 3580, 10189 and 10463–10584. Line 4505 is untouched, and neither `issue_lock_adoption.py` nor `issue_lock_recovery.py` is in the diff at all. Nothing in PR #944 causes, worsens, or could fix this. It warrants a follow-up issue against `issue_lock_adoption.py`, and it pairs naturally with the `_owning_pr_continuation_from_lock` ambiguity-guard follow-up already identified during the #946 review. It is not a blocker here. ## Compatibility with the PR #946 owning-PR continuation repair Verified structurally and by execution, not assumed from a clean merge: * The only file both PR #944 and `master`-since-base modify is `gitea_mcp_server.py`. PR #946 changed lines 2781–2891, 5140–5173 and 19424–19458; PR #944 changes 3580, 10189 and 10463–10584. **Zero line overlap.** * A merge simulation of the head into live `master` `35ed8a2f` applied cleanly and produced the identical `+1154 / −3` diffstat, so the change lands unchanged on top of #946. * On the merged result, the #945/#946 renewal-continuation suites and the #943 suites pass **together**: `tests/test_issue_945_enforcement_path_wiring.py`, `tests/test_issue_945_owning_pr_renewal_continuation.py`, `tests/test_issue_943_runtime_context_helpers.py`, plus the bootstrap, owning-PR-recovery, duplicate-gate and allocator suites — 266 passed, 27 subtests, 0 failed. * Duplicate-work protections are unweakened: `test_issue_work_duplicate_gate.py` and `test_issue_duplicate_gate.py` pass at head and on the merged result, and the new code adds ownership gates rather than removing any. ## Enforcement and blast radius `_verify_assignment_and_lease_ids` has exactly one caller, so the new lease-liveness check reaches only the bootstrap path. `_resolve_owner_workflow_session` is called only by the wrapper. `_author_mutation_block` serves the pre-existing reviewer-stop path plus the two new refusal paths. No unrelated capability changes behaviour, and no guard, permission, role or signature was relaxed — the one signature change is an optional `session_id` defaulting to `None`. The `author_issue_bootstrap.py` addition beyond the four findings is a lease-liveness check that refuses a released, expired or unparseable-expiry lease with `lean_not_live`-style `lease_not_live`. It only tightens, and it is covered by tests. ## Non-blocking observations, for the record 1. **`_resolve_owner_workflow_session` skips the claimant comparison when the lock records no claimant.** A planted lock with a `task_session_id` but an empty `claimant` is adopted by the resolver. I checked whether this leaks ownership; it does not — the downstream gates refuse in both directions (`issue_lock_acquisition_failed` in apply mode, `lease_session_mismatch` on the allocated path). Defence-in-depth ordering only, and the refusal reason is less precise than a missing-claimant-evidence reason would be. Not worth holding the PR. 2. **`_active_username` and `_active_profile_name` now have no production callers** — the wrapper calls `_active_mutation_authority` directly. They are correct, tested, and explicitly required by #943's acceptance criteria, so this is a note rather than a defect. 3. The refusal payloads carry `expected`/`actual` keys with `None` values when no drift applies. Cosmetic. ## Testing Run independently in `branches/` worktrees. Compared by failing test identifier, never by count — the standing baseline has drifted from 28 to 30 since review 622, and it moves identically at every revision. ```text full @ head 47bfae07 : 30 failed, 5565 passed, 6 skipped, 1002 subtests (187.06s) full @ base aab54d48 : 30 failed, 5523 passed, 6 skipped, 994 subtests (181.86s) failing id sets : IDENTICAL both directions — no failure originates from this branch full @ merge-sim : 30 failed, 5690 passed, 6 skipped, 1042 subtests (185.88s) full @ live master 35ed8a2f : 30 failed, 5648 passed, 6 skipped, 1034 subtests (184.81s) failing id sets : IDENTICAL — merging this PR introduces no failure against live master focused tests/test_issue_943_runtime_context_helpers.py : 42 passed, 8 subtests targeted bootstrap/guard/session/lock/allocator/duplicate @ head : 273 passed, 39 subtests, 0 failed same suites + #945/#946 renewal on merged result : 266 passed, 27 subtests, 0 failed ``` The author's reported figures reproduce exactly: 30/5565/6/1002 at head, 30/5523/6/994 at base, identical identifier sets, and 42 passed / 8 subtests focused. The `+42` passes and `+8` subtests are precisely this branch's new suite. ## Canonical PR State STATE: PR #944 is open at head 47bfae07d2639262a44bcc200c916061c27de0cb and has received an APPROVE review from sysadmin at that exact head. All four review-622 findings (B1, B2, F3, F4) are resolved and independently re-verified. The branch introduces no test regression against base aab54d4825270f5a5c6f9c1abc1ab09eb4f3e218 nor against live master 35ed8a2fcb11134a37c862ca6eaca26e3028902a. WHO_IS_NEXT: merger NEXT_ACTION: An independent prgs-merger session must perform a merge assessment for PR #944 pinned to head 47bfae07d2639262a44bcc200c916061c27de0cb. The branch is 11 commits behind live master but merges cleanly with no conflicts and no branch protection; confirm the sync route from live evidence before merging. NEXT_PROMPT: ```text Perform an independent merge assessment for PR #944 (Closes #943) in Scaled-Tech-Consulting/Gitea-Tools on remote prgs. Invoke the canonical gitea-workflow skill first. Use the gitea-merger namespace, profile prgs-merger. The author is jcwalker3 and the reviewer was sysadmin; do not merge your own work and do not re-review. Pin to head 47bfae07d2639262a44bcc200c916061c27de0cb. An APPROVE review is recorded at that exact head. Live master is 35ed8a2fcb11134a37c862ca6eaca26e3028902a and the branch is 11 commits behind it; mergeable is true with no conflicts. Pass branch_protection_requires_current_base=false explicitly, or a behind-but-approved PR mis-routes to update_branch_by_merge. Re-read live PR state and confirm the approval is valid at the exact current head before acting. Call parity twice after any merge; the first read can return the pre-merge head. After merge, the control checkout must be fast-forwarded and all five MCP servers restarted in one operator window before the repaired bootstrap capability can be recommissioned. Until that recommissioning passes, issue #931 stays blocked and PR #942's reconciler cleanup stays held. Do not touch issue #931. Do not run reconciler cleanup for PR #942. ``` WHAT_HAPPENED: An independent review at the exact head examined the complete three-file diff, verified every symbol the new code depends on, and re-tested all four review-622 findings against the new implementation rather than accepting the author's mapping. The round-1 experiment was reproduced over an isolated temporary control-plane database: the canonical allocator path now passes, while the round-1 value shape is still refused, and forged, wrong-role, wrong-profile, unestablishable and non-live-lease inputs all fail closed. Identity and profile now come from one snapshot with a fail-closed drift check, and the profile handler is narrowed with no cached fallback. The reported ownership-evidence contradiction was traced to source and found to be a real but out-of-scope diagnostic naming defect in issue_lock_adoption.py, a file this PR does not touch. Compatibility with the PR #946 repair was proven by zero line overlap, a clean merge simulation, and both suites passing together on the merged result. Four full-suite runs across four checkouts showed identical failing identifier sets in both comparisons. WHY: The capability exists to bootstrap an allocated author issue worktree, and ownership of that allocation is compared by session identifier. Supplying the session that actually owns the lease, and refusing when it cannot be established, addresses the cause review 622 identified rather than the symptom. The gate still refuses the previously refused value, which is what distinguishes a real repair from a loosened comparison. RELATED_PRS: #944 ISSUE: #943 HEAD_SHA: 47bfae07d2639262a44bcc200c916061c27de0cb REVIEW_STATUS: APPROVE posted at 47bfae07d2639262a44bcc200c916061c27de0cb by sysadmin. Review 622 REQUEST_CHANGES was posted at the superseded head f49e781102b9f363834c28c055f69639d16290c9 and is reported stale by the review feedback endpoint. MERGE_READY: yes BLOCKERS: no blocker VALIDATION: Full suite at head 47bfae07: 30 failed, 5565 passed, 6 skipped, 1002 subtests in 187.06s. Full suite at clean base checkout aab54d48: 30 failed, 5523 passed, 6 skipped, 994 subtests in 181.86s. Full suite on a merge simulation into live master: 30 failed, 5690 passed, 6 skipped, 1042 subtests in 185.88s. Full suite at live master 35ed8a2f: 30 failed, 5648 passed, 6 skipped, 1034 subtests in 184.81s. Failing test identifier sets are identical in both comparisons, so no failure originates from this branch. Focused #943 suite: 42 passed, 8 subtests. Targeted bootstrap, guard, session, lock, allocator and duplicate suites at head: 273 passed, 39 subtests, 0 failed. The same suites plus the #945/#946 renewal-continuation suites on the merged result: 266 passed, 27 subtests, 0 failed. An isolated temporary control-plane database reproduced the canonical allocator path passing and the round-1 value shape still being refused. The three SHA-256 digests published in comment 17695 reproduce byte-identically and the reviewer worktree is clean. NATIVE_REVIEW_PROOF: native MCP review mutation via gitea_submit_pr_review in the gitea-reviewer namespace, profile prgs-reviewer, identity sysadmin, reviewer lease session 56921-a15e047ac4db, pinned to expected_head_sha 47bfae07d2639262a44bcc200c916061c27de0cb. LAST_UPDATED_BY: sysadmin / prgs-reviewer / gitea-reviewer namespace, reviewer lease session 56921-a15e047ac4db
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #944
issue: #943
reviewer_identity: sysadmin
profile: prgs-merger
session_id: 56965-a9fbecb42673
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr944-47bfae07
phase: claimed
candidate_head: 47bfae07d2
target_branch: master
target_branch_sha: 35ed8a2fcb
last_activity: 2026-07-28T01:02:28Z
expires_at: 2026-07-28T01:12:28Z
blocker: none

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #944 issue: #943 reviewer_identity: sysadmin profile: prgs-merger session_id: 56965-a9fbecb42673 worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr944-47bfae07 phase: claimed candidate_head: 47bfae07d2639262a44bcc200c916061c27de0cb target_branch: master target_branch_sha: 35ed8a2fcb11134a37c862ca6eaca26e3028902a last_activity: 2026-07-28T01:02:28Z expires_at: 2026-07-28T01:12:28Z blocker: none
sysadmin merged commit 82d71b7702 into master 2026-07-27 20:03:09 -05:00
Owner

Stale #332 review-decision lock cleanup (#594)

Status: APPLIED

Manual deletion of session-state files is not the workflow.
This path only clears a lock when the referenced PR is merged/closed.

## Stale #332 review-decision lock cleanup (#594) Status: **APPLIED** - actor: `sysadmin` - profile: `prgs-merger` - timestamp: `2026-07-28T01:03:14.856874+00:00` - last terminal: `approve` on PR #944 - PR state: `closed` (merged=True) - merge_commit_sha: `82d71b77028a7abd4f8ab4a4e4d89658a187f73d` - prior live_mutations_count: `1` - prior profile_identity: `prgs-reviewer` Manual deletion of session-state files is **not** the workflow. This path only clears a lock when the referenced PR is merged/closed.
Sign in to join this conversation.
No Reviewers
No labels
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

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