fix(mcp): enforce role capability invariants #766

Merged
sysadmin merged 1 commits from fix/issue-723-role-stamp-invariants into master 2026-07-19 23:38:50 -05:00
Owner

Summary

  • centralize the complete current role-exclusive task set in task_capability_map.ROLE_EXCLUSIVE_TASKS
  • prevent denied or failed capability resolution from recording/stale-preserving a role stamp
  • return structured workspace_role_binding failures from review submission and merger-lease adoption
  • make runtime capability reporting truthful with explicit role_filtered and permission_only views
  • keep configured-profile matching aligned with declared roles

Closes #723

Files changed

  • task_capability_map.py
  • gitea_mcp_server.py
  • tests/test_issue_723_role_stamp_and_submission.py
  • tests/test_task_capability_role_invariants.py
  • tests/test_resolve_task_capability.py

Validation

  • master red proof: 7 intended #723 failures plus missing shared-constant collection failure
  • focused #723/resolver/invariant: 47 passed, 78 subtests passed
  • review submission and merger lease: 270 passed
  • runtime/profile/workspace/repository/preflight regressions: 418 passed, 119 subtests passed
  • expanded focused/lease rerun: 81 passed, 78 subtests passed
  • git diff --check: passed
  • python3 -m py_compile for every changed Python file: passed
  • full suite: 3711 passed, 6 skipped, 491 subtests passed; 2 failures reproduced identically on pristine detached base fcf6981b1ba4d8d5072357ba13be0fdb6baa07ff

Known baseline failures

  • TestF1RecoveryBeforeTerminalProbe.test_removed_worktree_recovers_before_probe
  • TestReconcilerSupersessionMcpTool.test_tool_posts_comment_and_closes_superseded_pr_issue

Both signatures match the pristine detached base and are outside the #723 diff.

Risk

The changes affect capability preflight state and role-filtered reporting. Coverage pins allowed/denied stamp behavior, unknown-task and lease aliases, structured verifier failures, profile-role matching, current-master role-exclusive completeness, and adjacent workspace/preflight invariants.

Worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/fix-issue-723-role-stamp-invariants
Branch: fix/issue-723-role-stamp-invariants
Commit: 4b8a9219d85bc99b6abeebb4dc9db3e344bc27e5

## Summary - centralize the complete current role-exclusive task set in `task_capability_map.ROLE_EXCLUSIVE_TASKS` - prevent denied or failed capability resolution from recording/stale-preserving a role stamp - return structured `workspace_role_binding` failures from review submission and merger-lease adoption - make runtime capability reporting truthful with explicit `role_filtered` and `permission_only` views - keep configured-profile matching aligned with declared roles Closes #723 ## Files changed - `task_capability_map.py` - `gitea_mcp_server.py` - `tests/test_issue_723_role_stamp_and_submission.py` - `tests/test_task_capability_role_invariants.py` - `tests/test_resolve_task_capability.py` ## Validation - master red proof: 7 intended #723 failures plus missing shared-constant collection failure - focused #723/resolver/invariant: 47 passed, 78 subtests passed - review submission and merger lease: 270 passed - runtime/profile/workspace/repository/preflight regressions: 418 passed, 119 subtests passed - expanded focused/lease rerun: 81 passed, 78 subtests passed - `git diff --check`: passed - `python3 -m py_compile` for every changed Python file: passed - full suite: 3711 passed, 6 skipped, 491 subtests passed; 2 failures reproduced identically on pristine detached base `fcf6981b1ba4d8d5072357ba13be0fdb6baa07ff` ## Known baseline failures - `TestF1RecoveryBeforeTerminalProbe.test_removed_worktree_recovers_before_probe` - `TestReconcilerSupersessionMcpTool.test_tool_posts_comment_and_closes_superseded_pr_issue` Both signatures match the pristine detached base and are outside the #723 diff. ## Risk The changes affect capability preflight state and role-filtered reporting. Coverage pins allowed/denied stamp behavior, unknown-task and lease aliases, structured verifier failures, profile-role matching, current-master role-exclusive completeness, and adjacent workspace/preflight invariants. Worktree: `/Users/jasonwalker/Development/Gitea-Tools/branches/fix-issue-723-role-stamp-invariants` Branch: `fix/issue-723-role-stamp-invariants` Commit: `4b8a9219d85bc99b6abeebb4dc9db3e344bc27e5`
jcwalker3 added 1 commit 2026-07-19 22:22:47 -05:00
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #766
issue: #723
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 9625-79d38f65031d
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr-766-4b8a921
phase: claimed
candidate_head: 4b8a9219d8
target_branch: master
target_branch_sha: fcf6981b1b
last_activity: 2026-07-20T04:17:24Z
expires_at: 2026-07-20T04:27:24Z
blocker: none

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #766 issue: #723 reviewer_identity: sysadmin profile: prgs-reviewer session_id: 9625-79d38f65031d worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr-766-4b8a921 phase: claimed candidate_head: 4b8a9219d85bc99b6abeebb4dc9db3e344bc27e5 target_branch: master target_branch_sha: fcf6981b1ba4d8d5072357ba13be0fdb6baa07ff last_activity: 2026-07-20T04:17:24Z expires_at: 2026-07-20T04:27:24Z blocker: none
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #766
issue: #723
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 9625-79d38f65031d
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr-766-4b8a921
phase: claimed
candidate_head: 4b8a9219d8
target_branch: master
target_branch_sha: fcf6981b1b
last_activity: 2026-07-20T04:28:54Z
expires_at: 2026-07-20T04:38:54Z
blocker: none

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #766 issue: #723 reviewer_identity: sysadmin profile: prgs-reviewer session_id: 9625-79d38f65031d worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr-766-4b8a921 phase: claimed candidate_head: 4b8a9219d85bc99b6abeebb4dc9db3e344bc27e5 target_branch: master target_branch_sha: fcf6981b1ba4d8d5072357ba13be0fdb6baa07ff last_activity: 2026-07-20T04:28:54Z expires_at: 2026-07-20T04:38:54Z blocker: none
sysadmin approved these changes 2026-07-19 23:29:58 -05:00
sysadmin left a comment
Owner

Independent reviewer verdict: APPROVE at head 4b8a9219d85bc99b6abeebb4dc9db3e344bc27e5.

Reviewer sysadmin / prgs-reviewer is distinct from PR author jcwalker3. Review performed in a detached reviewer worktree at the exact PR head (branches/review-pr-766-4b8a921), independent of the author worktree.

Acceptance criteria (issue #723)

  • AC1 — role-exclusive tasks have a satisfying profile. TestRoleExclusiveSetIntegrity.test_every_role_exclusive_task_has_a_satisfying_profile derives the required role per task and asserts the canonical role-profile shape satisfies both permission and role. test_every_role_exclusive_task_exists_in_capability_map pins the set against TASK_CAPABILITY_MAP. Verified independently: both are derived checks, not literal comparisons.
  • AC2 — map to router agreement. Existing REVIEWER_TASKS/MERGER_TASKS role-agreement tests remain, and test_formal_review_tasks_are_role_exclusive adds the containment invariant.
  • AC3 — denied resolve must not stamp a role. _clear_resolved_capability_stamp() runs at resolver entry before any fallible work; the mid-resolver call is now record_preflight_check("capability") with no role/task, and the authority stamp is recorded only in the final else branch when neither stop_required nor restart_required holds. I traced lines 17386-17843: every return between the entry clear and the final stamp is a denial path, and the allow path has a single exit. Confirmed record_preflight_check only assigns _preflight_resolved_role/_task when the arguments are truthy, so the entry clear is what actually removes stale authority. Confirmed _effective_workspace_role() falls back to the permission-derived role when the stamp is None, so clearing degrades to the true session role rather than to an unguarded state, and preflight_task_matches(None, ...) returns False.
  • AC4 — structured failure instead of a generic internal error. _evaluate_pr_review_submission and gitea_adopt_merger_pr_lease now catch RuntimeError from _verify_role_mutation_workspace and return blocker_kind="workspace_role_binding" with redacted reasons. I enumerated the raise sites in _verify_role_mutation_workspace plus _enforce_canonical_repository_root: all are RuntimeError, so the guarded blocks are fully covered. The early-return result shape is identical to the existing workflow_blockers early return (performed=False, would_perform=False, non-empty reasons), and both callers return it unchanged, so no caller reinterprets it as success. _redact(...) is applied to the exception text.
  • AC5 — runtime capability view consistent with the resolver. _build_runtime_task_capabilities now takes active_role_kind from _profile_role_kind(profile) — the same source the resolver uses — and applies role_exclusive and active_role_kind == required_role_kind, which is semantically identical to the resolver's role_matches_current_session. Entries carry role_exclusive and an explicit capability_view of role_filtered or permission_only, so a caller that omits the role gets a labeled weaker view rather than an implied stronger authority.

Independent validation

All commands run by the reviewer in branches/review-pr-766-4b8a921 at 4b8a9219d85bc99b6abeebb4dc9db3e344bc27e5; worktree verified clean before and after.

  • Red proof (proof source: command). Master sources gitea_mcp_server.py and task_capability_map.py restored from fcf6981b1ba4d8d5072357ba13be0fdb6baa07ff into the reviewer worktree: tests/test_task_capability_role_invariants.py fails collection with ImportError: cannot import name 'ROLE_EXCLUSIVE_TASKS', and tests/test_issue_723_role_stamp_and_submission.py gives 7 failed / 4 passed. This reproduces the author's stated red proof exactly. Reviewer worktree restored to the PR head afterward and re-verified clean.
  • Focused (proof source: command): tests/test_issue_723_role_stamp_and_submission.py tests/test_task_capability_role_invariants.py tests/test_resolve_task_capability.py gives 48 passed, 78 subtests passed.
  • Adjacent regressions (proof source: command): -k "runtime_context or preflight or capability or role or submit or submission or merger_lease or reviewer_lease or profile" gives 769 passed, 241 subtests passed, 0 failed.
  • Full suite (proof source: command): 3711 passed, 6 skipped, 491 subtests passed, 2 failed.
  • Baseline failure confirmation (proof source: command): the 2 failures — TestF1RecoveryBeforeTerminalProbe.test_removed_worktree_recovers_before_probe and TestReconcilerSupersessionMcpTool.test_tool_posts_comment_and_closes_superseded_pr_issue — were re-run in a separate detached worktree at pristine base fcf6981b1ba4d8d5072357ba13be0fdb6baa07ff and fail identically there. They are pre-existing on master and outside this diff. That temporary baseline worktree was removed after use.

Sync state at verdict time: head 4b8a9219d85bc99b6abeebb4dc9db3e344bc27e5, base head fcf6981b1ba4d8d5072357ba13be0fdb6baa07ff, commits_behind=0, mergeable=true, has_conflicts=false, checks not required by live branch protection.

Non-blocking observations (no change requested)

  1. test_complete_current_role_exclusive_set compares ROLE_EXCLUSIVE_TASKS against an identical literal in the test file. It is a change detector rather than a derived invariant, so it cannot detect a task that should be role-exclusive but was never in either copy. The derived tests alongside it carry the real invariant weight, so this is acceptable as an intentional pin against silent shrinkage.
  2. The runtime role filter intentionally does not replicate the resolver's cross-host, identity-mismatch, and context-drift blocks. The role_filtered label claims role filtering only and does not claim resolver equivalence, so this is honest; a future change that markets the runtime view as resolver-equivalent would need those blocks too.
  3. Catching RuntimeError broadly in the two submission paths could also classify an unrelated internal RuntimeError as workspace_role_binding. It still fails closed and includes the original message, which is strictly better than the previous opaque failure mode, and test_unexpected_verifier_failure_remains_fail_closed pins that non-RuntimeError exceptions still propagate.

No blocking defects found. Scope is confined to issue #723; no unrelated behavior changes appear in the diff.

Canonical PR State

STATE:
approved

WHO_IS_NEXT:
merger

NEXT_ACTION:
An independent merger session using prgs-merger/sysadmin should acquire a merger PR lease, re-verify this approval at head 4b8a9219d8, and merge PR 766.

NEXT_PROMPT:
Run one bounded merger phase for PR #766 in Scaled-Tech-Consulting/Gitea-Tools using prgs-merger/sysadmin. Verify identity, repository binding, namespace health, and master/runtime parity. Acquire the merger PR lease, pin head 4b8a9219d8, confirm the APPROVE review at that exact head is visible and undismissed with no blocking change requests, re-assess checks, commits behind, conflicts, and mergeability, then merge only through gitea_merge_pr with confirmation "MERGE PR 766". Post the canonical merger handoff and stop. Do not review, do not edit the branch, and do not delete branches or worktrees.

WHAT_HAPPENED:
An independent reviewer validated PR 766 against the acceptance criteria of issue #723, reproduced the master red proof, ran focused, adjacent, and full-suite validation, confirmed the two remaining suite failures are pre-existing on the base commit, and posted an APPROVE verdict at the exact current head.

WHY:
All five acceptance criteria of issue #723 are implemented and covered by derived regression tests; the capability stamp is cleared at resolver entry and recorded only on the final allow decision, guarded workspace/role rejections now return structured fail-closed results instead of raising, and the runtime capability view applies the same role filter as the resolver or labels itself permission-only.

ISSUE:
#723

BASE:
master

HEAD:
fix/issue-723-role-stamp-invariants

HEAD_SHA:
4b8a9219d8

REVIEW_STATUS:
approved

VALIDATION:
Red proof reproduced on master sources (7 failures plus a collection ImportError); focused 48 passed with 78 subtests; adjacent 769 passed with 241 subtests; full suite 3711 passed, 6 skipped, 491 subtests, 2 failures proven pre-existing at base fcf6981b1b.

BLOCKERS:
none

SUPERSEDES:
none

SUPERSEDED_BY:
none

MERGE_READY:
yes — commits_behind is 0, mergeable is true, no conflicts, checks are not required by live branch protection, and this APPROVE is recorded at the exact current head.

LAST_UPDATED_BY:
sysadmin / prgs-reviewer / 2026-07-20

NATIVE_REVIEW_PROOF: transport=native_mcp; tool=gitea_submit_pr_review; namespace=gitea-reviewer; profile=prgs-reviewer; identity=sysadmin; pinned_head=4b8a9219d85bc99b6abeebb4dc9db3e344bc27e5; reviewer_lease_comment_id=13068

[THREAD STATE LEDGER]

What is true now:
PR 766 is open at head 4b8a9219d8, base master at fcf6981b1b, 0 commits behind, mergeable with no conflicts, and status checks are not required by live branch protection. A reviewer PR lease is held by session 9625-79d38f65031d (current lease comment 13068; the first lease comment 13066 expired under the 10-minute sliding TTL while the full suite ran and was re-acquired by the same session). Server-side decision state: no server-side review decision existed on this PR before this submission; this comment is the approved review posted to Gitea. Local verdict/state: approve verdict prepared locally from an independent reviewer worktree at the pinned head, then submitted natively.

What changed:
Server-side mutation ledger: two reviewer PR lease comments by the same reviewer session (ids 13066 and 13068) and one native approved review posted to Gitea at head 4b8a9219d8. Server-side state changed by exactly those three reviewer mutations. An earlier submit attempt returned performed=false with reason "no active reviewer lease found on PR #766" and made no server-side change. Merge not performed. No branch, tag, label, issue-state, or file mutation was made by the reviewer. Local: a detached reviewer worktree was created at the PR head and a temporary detached baseline worktree at fcf6981b1b was created and then removed; the control checkout stayed on master and clean.

What is blocked:
Blocker classification: none. No blocking change requests, no conflicts, no failing in-scope tests, and no unresolved acceptance criteria. The 2 remaining full-suite failures are pre-existing on the base commit and outside this diff, so they do not gate this PR.

Who/what acts next:
Next actor: merger. Required action: an independent prgs-merger/sysadmin session acquires the merger PR lease, re-verifies this approved review at the exact head 4b8a9219d8, reassesses mergeability, and merges PR 766 via gitea_merge_pr with confirmation "MERGE PR 766". Merge not performed by this reviewer session; a reviewer approval is not merge authorization.

Independent reviewer verdict: **APPROVE** at head `4b8a9219d85bc99b6abeebb4dc9db3e344bc27e5`. Reviewer `sysadmin` / `prgs-reviewer` is distinct from PR author `jcwalker3`. Review performed in a detached reviewer worktree at the exact PR head (`branches/review-pr-766-4b8a921`), independent of the author worktree. ## Acceptance criteria (issue #723) - **AC1 — role-exclusive tasks have a satisfying profile.** `TestRoleExclusiveSetIntegrity.test_every_role_exclusive_task_has_a_satisfying_profile` derives the required role per task and asserts the canonical role-profile shape satisfies both permission and role. `test_every_role_exclusive_task_exists_in_capability_map` pins the set against `TASK_CAPABILITY_MAP`. Verified independently: both are derived checks, not literal comparisons. - **AC2 — map to router agreement.** Existing `REVIEWER_TASKS`/`MERGER_TASKS` role-agreement tests remain, and `test_formal_review_tasks_are_role_exclusive` adds the containment invariant. - **AC3 — denied resolve must not stamp a role.** `_clear_resolved_capability_stamp()` runs at resolver entry before any fallible work; the mid-resolver call is now `record_preflight_check("capability")` with no role/task, and the authority stamp is recorded only in the final `else` branch when neither `stop_required` nor `restart_required` holds. I traced lines 17386-17843: every return between the entry clear and the final stamp is a denial path, and the allow path has a single exit. Confirmed `record_preflight_check` only assigns `_preflight_resolved_role`/`_task` when the arguments are truthy, so the entry clear is what actually removes stale authority. Confirmed `_effective_workspace_role()` falls back to the permission-derived role when the stamp is `None`, so clearing degrades to the true session role rather than to an unguarded state, and `preflight_task_matches(None, ...)` returns `False`. - **AC4 — structured failure instead of a generic internal error.** `_evaluate_pr_review_submission` and `gitea_adopt_merger_pr_lease` now catch `RuntimeError` from `_verify_role_mutation_workspace` and return `blocker_kind="workspace_role_binding"` with redacted reasons. I enumerated the raise sites in `_verify_role_mutation_workspace` plus `_enforce_canonical_repository_root`: all are `RuntimeError`, so the guarded blocks are fully covered. The early-return result shape is identical to the existing `workflow_blockers` early return (`performed=False`, `would_perform=False`, non-empty `reasons`), and both callers return it unchanged, so no caller reinterprets it as success. `_redact(...)` is applied to the exception text. - **AC5 — runtime capability view consistent with the resolver.** `_build_runtime_task_capabilities` now takes `active_role_kind` from `_profile_role_kind(profile)` — the same source the resolver uses — and applies `role_exclusive and active_role_kind == required_role_kind`, which is semantically identical to the resolver's `role_matches_current_session`. Entries carry `role_exclusive` and an explicit `capability_view` of `role_filtered` or `permission_only`, so a caller that omits the role gets a labeled weaker view rather than an implied stronger authority. ## Independent validation All commands run by the reviewer in `branches/review-pr-766-4b8a921` at `4b8a9219d85bc99b6abeebb4dc9db3e344bc27e5`; worktree verified clean before and after. - Red proof (proof source: command). Master sources `gitea_mcp_server.py` and `task_capability_map.py` restored from `fcf6981b1ba4d8d5072357ba13be0fdb6baa07ff` into the reviewer worktree: `tests/test_task_capability_role_invariants.py` fails collection with `ImportError: cannot import name 'ROLE_EXCLUSIVE_TASKS'`, and `tests/test_issue_723_role_stamp_and_submission.py` gives 7 failed / 4 passed. This reproduces the author's stated red proof exactly. Reviewer worktree restored to the PR head afterward and re-verified clean. - Focused (proof source: command): `tests/test_issue_723_role_stamp_and_submission.py tests/test_task_capability_role_invariants.py tests/test_resolve_task_capability.py` gives 48 passed, 78 subtests passed. - Adjacent regressions (proof source: command): `-k "runtime_context or preflight or capability or role or submit or submission or merger_lease or reviewer_lease or profile"` gives 769 passed, 241 subtests passed, 0 failed. - Full suite (proof source: command): 3711 passed, 6 skipped, 491 subtests passed, 2 failed. - Baseline failure confirmation (proof source: command): the 2 failures — `TestF1RecoveryBeforeTerminalProbe.test_removed_worktree_recovers_before_probe` and `TestReconcilerSupersessionMcpTool.test_tool_posts_comment_and_closes_superseded_pr_issue` — were re-run in a separate detached worktree at pristine base `fcf6981b1ba4d8d5072357ba13be0fdb6baa07ff` and fail identically there. They are pre-existing on master and outside this diff. That temporary baseline worktree was removed after use. Sync state at verdict time: head `4b8a9219d85bc99b6abeebb4dc9db3e344bc27e5`, base head `fcf6981b1ba4d8d5072357ba13be0fdb6baa07ff`, `commits_behind=0`, `mergeable=true`, `has_conflicts=false`, checks not required by live branch protection. ## Non-blocking observations (no change requested) 1. `test_complete_current_role_exclusive_set` compares `ROLE_EXCLUSIVE_TASKS` against an identical literal in the test file. It is a change detector rather than a derived invariant, so it cannot detect a task that should be role-exclusive but was never in either copy. The derived tests alongside it carry the real invariant weight, so this is acceptable as an intentional pin against silent shrinkage. 2. The runtime role filter intentionally does not replicate the resolver's cross-host, identity-mismatch, and context-drift blocks. The `role_filtered` label claims role filtering only and does not claim resolver equivalence, so this is honest; a future change that markets the runtime view as resolver-equivalent would need those blocks too. 3. Catching `RuntimeError` broadly in the two submission paths could also classify an unrelated internal `RuntimeError` as `workspace_role_binding`. It still fails closed and includes the original message, which is strictly better than the previous opaque failure mode, and `test_unexpected_verifier_failure_remains_fail_closed` pins that non-`RuntimeError` exceptions still propagate. No blocking defects found. Scope is confined to issue #723; no unrelated behavior changes appear in the diff. ## Canonical PR State STATE: approved WHO_IS_NEXT: merger NEXT_ACTION: An independent merger session using prgs-merger/sysadmin should acquire a merger PR lease, re-verify this approval at head 4b8a9219d85bc99b6abeebb4dc9db3e344bc27e5, and merge PR 766. NEXT_PROMPT: Run one bounded merger phase for PR #766 in Scaled-Tech-Consulting/Gitea-Tools using prgs-merger/sysadmin. Verify identity, repository binding, namespace health, and master/runtime parity. Acquire the merger PR lease, pin head 4b8a9219d85bc99b6abeebb4dc9db3e344bc27e5, confirm the APPROVE review at that exact head is visible and undismissed with no blocking change requests, re-assess checks, commits behind, conflicts, and mergeability, then merge only through gitea_merge_pr with confirmation "MERGE PR 766". Post the canonical merger handoff and stop. Do not review, do not edit the branch, and do not delete branches or worktrees. WHAT_HAPPENED: An independent reviewer validated PR 766 against the acceptance criteria of issue #723, reproduced the master red proof, ran focused, adjacent, and full-suite validation, confirmed the two remaining suite failures are pre-existing on the base commit, and posted an APPROVE verdict at the exact current head. WHY: All five acceptance criteria of issue #723 are implemented and covered by derived regression tests; the capability stamp is cleared at resolver entry and recorded only on the final allow decision, guarded workspace/role rejections now return structured fail-closed results instead of raising, and the runtime capability view applies the same role filter as the resolver or labels itself permission-only. ISSUE: #723 BASE: master HEAD: fix/issue-723-role-stamp-invariants HEAD_SHA: 4b8a9219d85bc99b6abeebb4dc9db3e344bc27e5 REVIEW_STATUS: approved VALIDATION: Red proof reproduced on master sources (7 failures plus a collection ImportError); focused 48 passed with 78 subtests; adjacent 769 passed with 241 subtests; full suite 3711 passed, 6 skipped, 491 subtests, 2 failures proven pre-existing at base fcf6981b1ba4d8d5072357ba13be0fdb6baa07ff. BLOCKERS: none SUPERSEDES: none SUPERSEDED_BY: none MERGE_READY: yes — commits_behind is 0, mergeable is true, no conflicts, checks are not required by live branch protection, and this APPROVE is recorded at the exact current head. LAST_UPDATED_BY: sysadmin / prgs-reviewer / 2026-07-20 NATIVE_REVIEW_PROOF: transport=native_mcp; tool=gitea_submit_pr_review; namespace=gitea-reviewer; profile=prgs-reviewer; identity=sysadmin; pinned_head=4b8a9219d85bc99b6abeebb4dc9db3e344bc27e5; reviewer_lease_comment_id=13068 [THREAD STATE LEDGER] What is true now: PR 766 is open at head 4b8a9219d85bc99b6abeebb4dc9db3e344bc27e5, base master at fcf6981b1ba4d8d5072357ba13be0fdb6baa07ff, 0 commits behind, mergeable with no conflicts, and status checks are not required by live branch protection. A reviewer PR lease is held by session 9625-79d38f65031d (current lease comment 13068; the first lease comment 13066 expired under the 10-minute sliding TTL while the full suite ran and was re-acquired by the same session). Server-side decision state: no server-side review decision existed on this PR before this submission; this comment is the approved review posted to Gitea. Local verdict/state: approve verdict prepared locally from an independent reviewer worktree at the pinned head, then submitted natively. What changed: Server-side mutation ledger: two reviewer PR lease comments by the same reviewer session (ids 13066 and 13068) and one native approved review posted to Gitea at head 4b8a9219d85bc99b6abeebb4dc9db3e344bc27e5. Server-side state changed by exactly those three reviewer mutations. An earlier submit attempt returned performed=false with reason "no active reviewer lease found on PR #766" and made no server-side change. Merge not performed. No branch, tag, label, issue-state, or file mutation was made by the reviewer. Local: a detached reviewer worktree was created at the PR head and a temporary detached baseline worktree at fcf6981b1ba4d8d5072357ba13be0fdb6baa07ff was created and then removed; the control checkout stayed on master and clean. What is blocked: Blocker classification: none. No blocking change requests, no conflicts, no failing in-scope tests, and no unresolved acceptance criteria. The 2 remaining full-suite failures are pre-existing on the base commit and outside this diff, so they do not gate this PR. Who/what acts next: Next actor: merger. Required action: an independent prgs-merger/sysadmin session acquires the merger PR lease, re-verifies this approved review at the exact head 4b8a9219d85bc99b6abeebb4dc9db3e344bc27e5, reassesses mergeability, and merges PR 766 via gitea_merge_pr with confirmation "MERGE PR 766". Merge not performed by this reviewer session; a reviewer approval is not merge authorization.
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #766
issue: #723
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 9625-79d38f65031d
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr-766-4b8a921
phase: released
candidate_head: 4b8a9219d8
target_branch: master
target_branch_sha: fcf6981b1b
last_activity: 2026-07-20T04:30:44Z
expires_at: 2026-07-20T04:40:44Z
blocker: manual-release

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #766 issue: #723 reviewer_identity: sysadmin profile: prgs-reviewer session_id: 9625-79d38f65031d worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr-766-4b8a921 phase: released candidate_head: 4b8a9219d85bc99b6abeebb4dc9db3e344bc27e5 target_branch: master target_branch_sha: fcf6981b1ba4d8d5072357ba13be0fdb6baa07ff last_activity: 2026-07-20T04:30:44Z expires_at: 2026-07-20T04:40:44Z blocker: manual-release
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #766
issue: #723
reviewer_identity: sysadmin
profile: prgs-merger
session_id: 52960-cfa84f3dee63
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/merge-pr-766-4b8a921
phase: claimed
candidate_head: 4b8a9219d8
target_branch: master
target_branch_sha: fcf6981b1b
last_activity: 2026-07-20T04:38:01Z
expires_at: 2026-07-20T04:48:01Z
blocker: none

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #766 issue: #723 reviewer_identity: sysadmin profile: prgs-merger session_id: 52960-cfa84f3dee63 worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/merge-pr-766-4b8a921 phase: claimed candidate_head: 4b8a9219d85bc99b6abeebb4dc9db3e344bc27e5 target_branch: master target_branch_sha: fcf6981b1ba4d8d5072357ba13be0fdb6baa07ff last_activity: 2026-07-20T04:38:01Z expires_at: 2026-07-20T04:48:01Z blocker: none
sysadmin merged commit d12adabeb1 into master 2026-07-19 23:38:50 -05:00
Owner

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

Status: APPLIED

  • actor: sysadmin
  • profile: prgs-merger
  • timestamp: 2026-07-20T04:38:50.978412+00:00
  • last terminal: approve on PR fix(mcp): enforce role capability invariants (#766)
  • PR state: closed (merged=True)
  • merge_commit_sha: d12adabeb1cf7810b1286ca8871a9b680646021c
  • 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.

## Stale #332 review-decision lock cleanup (#594) Status: **APPLIED** - actor: `sysadmin` - profile: `prgs-merger` - timestamp: `2026-07-20T04:38:50.978412+00:00` - last terminal: `approve` on PR #766 - PR state: `closed` (merged=True) - merge_commit_sha: `d12adabeb1cf7810b1286ca8871a9b680646021c` - 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.
Owner

Merger closeout for PR #766 by an independent prgs-merger / sysadmin session. Merge performed natively; no review, no author remediation, no branch or worktree deletion, no control-checkout update.

Canonical Issue State

STATE:
merged

WHO_IS_NEXT:
reconciler

NEXT_ACTION:
All MCP namespaces (gitea-tools, gitea-reviewer, gitea-merger, gitea-reconciler) must be restarted or reconnected at master d12adabeb1 before any further mutation, because every running daemon started at fcf6981b1b and is now stale. After that restart, a prgs-reconciler session may perform scoped terminal cleanup for this landed PR: remove the stale status:pr-open label from issue #723, clean moot leases for PR #766, and remove the merged branch and its worktrees through sanctioned tools only.

NEXT_PROMPT:

Run one bounded reconciler phase for landed PR #766 in Scaled-Tech-Consulting/Gitea-Tools using prgs-reconciler/sysadmin, only after every MCP namespace has been restarted or reconnected at master d12adabeb1cf7810b1286ca8871a9b680646021c. Verify terminal state (PR #766 closed with merge commit d12adabeb1cf7810b1286ca8871a9b680646021c, issue #723 closed), preview cleanup before applying it, then scope cleanup to exactly these targets: the stale status:pr-open label on issue #723, moot leases for PR #766, the merged remote branch fix/issue-723-role-stamp-invariants, and the local worktrees branches/fix-issue-723-role-stamp-invariants, branches/review-pr-766-4b8a921, and branches/merge-pr-766-4b8a921. Refuse the batch if any unrelated target appears. Post the canonical reconciliation handoff and stop.

WHAT_HAPPENED:
An independent merger session re-ran the full merger gate sequence against fresh live state and merged PR #766. Verified before merge: OS identity jasonwalker/502 non-root; identity sysadmin with profile prgs-merger and identity_match true, auto_profile_substitution false; repository binding Scaled-Tech-Consulting/Gitea-Tools on remote prgs with canonical root /Users/jasonwalker/Development/Gitea-Tools and workspace roots aligned; namespace gitea-merger healthy with ide_namespace_proven true and blocks_merge_workflow false; runtime parity in_parity true, restart_required false, startup and current head both fcf6981b1ba4d8d5072357ba13be0fdb6baa07ff; workflow proof loaded from skills/llm-project-workflow/workflows/review-merge-pr.md at hash 263d0a6cb8a6; router route_result allowed_current_session; capability merge_pr allowed with stop_required false. Approval freshness: review 478 by sysadmin/prgs-reviewer, verdict APPROVED at exact head 4b8a9219d8, dismissed false, stale false, quarantined false, approval_at_current_head true, has_blocking_change_requests false, author jcwalker3 distinct from merger sysadmin. Sync reassessment: commits_behind 0, mergeable true, has_conflicts false, checks not required by live branch protection, recommended_next_action merge_now. A merger PR lease was acquired natively (lease comment 13074, session 52960-cfa84f3dee63) in a dedicated detached merger worktree, live state was re-read after acquisition and was unchanged, and the merge was then executed with the pinned head and confirmation.

WHY:
Every merger gate passed against freshly read live state, the approval was visible and undismissed at the exact pinned head with no blocking change requests, and the operator explicitly authorized the merge of this PR.

RELATED_PRS:
PR #766 (this PR, closed with merge commit d12adabeb1, implements issue #723). No other open PR is linked to issue #723, and this merger session touched no other PR.

ISSUE:
#723

BASE:
master

HEAD:
fix/issue-723-role-stamp-invariants

HEAD_SHA:
4b8a9219d8

REVIEW_STATUS:
approved

VALIDATION:
No new validation was run by this merger session, by design. The merger phase does not re-review. Validation of record is reviewer review 478 at head 4b8a9219d8: red proof reproduced on master sources, focused 48 passed with 78 subtests, adjacent 769 passed with 241 subtests, full suite 3711 passed with 6 skipped and 491 subtests, and 2 failures proven pre-existing at base fcf6981b1b.

BLOCKERS:
none

SUPERSEDES:
none

SUPERSEDED_BY:
none

MERGE_READY:
merged — PR #766 state closed, merged_at 2026-07-19T23:38:50-05:00, merge commit d12adabeb1, live prgs/master advanced from fcf6981b1b to d12adabeb1, issue #723 auto-closed.

LAST_UPDATED_BY:
sysadmin / prgs-merger / 2026-07-20

NATIVE_MERGE_PROOF: transport=native_mcp; tool=gitea_merge_pr; namespace=gitea-merger; profile=prgs-merger; identity=sysadmin; pinned_head=4b8a9219d85bc99b6abeebb4dc9db3e344bc27e5; merge_method=merge; merge_commit=d12adabeb1cf7810b1286ca8871a9b680646021c; merger_lease_comment_id=13074; lease_proof_kind=sanctioned_acquire_merger

[THREAD STATE LEDGER]

What is true now:
PR #766 is closed with merge commit d12adabeb1 recorded at 2026-07-19T23:38:50-05:00. Live prgs/master is d12adabeb1. Issue #723 is closed. Server-side decision state: reviewer review 478 is the approval of record at head 4b8a9219d8, undismissed, non-stale, non-quarantined; the prgs-reviewer review-decision lock for this PR was cleared by the merge tool after the merge with audit comment id 13078; the merger PR lease from session 52960-cfa84f3dee63 (lease comment 13074) is now moot. Local verdict/state: this merger session prepared no verdict and holds no local decision state; it inspected live state only and executed the merge from a detached merger worktree at branches/merge-pr-766-4b8a921 pinned to head 4b8a9219d8. Every MCP namespace daemon is running code from startup head fcf6981b1b and is therefore stale relative to live master. The control checkout at /Users/jasonwalker/Development/Gitea-Tools remains on master at fcf6981b1b and is clean; the merger phase does not advance it.

What changed:
Server-side mutation ledger for this merger session, exactly four mutations: one merger PR lease comment id 13074; one native merge of PR #766 via gitea_merge_pr producing merge commit d12adabeb1cf7810b1286ca8871a9b680646021c; one post-merge review-decision-lock clearance for profile prgs-reviewer with audit comment id 13078; and this handoff comment. Issue #723 was closed by Gitea as a side effect of the merge, not by a direct issue mutation from this session. No formal review verdict was posted to Gitea by this session, no branch was pushed or deleted, no worktree was deleted, no label was changed, and no file was modified. Local: one detached merger worktree was created at branches/merge-pr-766-4b8a921 at the pinned head, and git fetch --prune prgs was run twice. The control checkout was not modified.

What is blocked:

  • Blocker classification: no blocker

PR #766 reached its terminal merged state with no blocking change requests, no conflicts, no failing in-scope tests, and no unresolved acceptance criteria. Two follow-on conditions are recorded here as preconditions for later phases rather than as blockers on this PR. First, every MCP namespace daemon is stale at fcf6981b1b and must be restarted or reconnected at d12adabeb1 before any further mutation, because the loaded capability-gate code predates this merge. Second, residual hygiene items remain for a reconciler and are out of scope for a merger: the stale status:pr-open label on closed issue #723, the moot merger lease for PR #766, the merged remote branch fix/issue-723-role-stamp-invariants, and the three local worktrees created for this PR (author, reviewer, merger).

Do not do:
Do not re-review PR #766 or replay any approve or merge command; the PR is terminal. Do not run any mutation through a stale namespace before the restart or reconnect at d12adabeb1. Do not advance the control checkout as part of a merger phase. Do not delete branches, worktrees, or lock files by hand, and do not batch the residual cleanup together with unrelated targets. Do not treat this merger handoff as authorization for any new author work.

Who/what acts next:
Next actor: the operator, then a reconciler. Required action: the operator restarts or reconnects all four MCP namespaces (gitea-tools, gitea-reviewer, gitea-merger, gitea-reconciler) at master d12adabeb1 and advances the control checkout to that SHA outside the merger phase; only after that may a prgs-reconciler session perform the scoped terminal cleanup listed above through sanctioned tools. This merger session performs no further mutation and stops here.

Merger closeout for PR #766 by an independent `prgs-merger` / `sysadmin` session. Merge performed natively; no review, no author remediation, no branch or worktree deletion, no control-checkout update. ## Canonical Issue State STATE: merged WHO_IS_NEXT: reconciler NEXT_ACTION: All MCP namespaces (gitea-tools, gitea-reviewer, gitea-merger, gitea-reconciler) must be restarted or reconnected at master d12adabeb1cf7810b1286ca8871a9b680646021c before any further mutation, because every running daemon started at fcf6981b1ba4d8d5072357ba13be0fdb6baa07ff and is now stale. After that restart, a `prgs-reconciler` session may perform scoped terminal cleanup for this landed PR: remove the stale `status:pr-open` label from issue #723, clean moot leases for PR #766, and remove the merged branch and its worktrees through sanctioned tools only. NEXT_PROMPT: ```text Run one bounded reconciler phase for landed PR #766 in Scaled-Tech-Consulting/Gitea-Tools using prgs-reconciler/sysadmin, only after every MCP namespace has been restarted or reconnected at master d12adabeb1cf7810b1286ca8871a9b680646021c. Verify terminal state (PR #766 closed with merge commit d12adabeb1cf7810b1286ca8871a9b680646021c, issue #723 closed), preview cleanup before applying it, then scope cleanup to exactly these targets: the stale status:pr-open label on issue #723, moot leases for PR #766, the merged remote branch fix/issue-723-role-stamp-invariants, and the local worktrees branches/fix-issue-723-role-stamp-invariants, branches/review-pr-766-4b8a921, and branches/merge-pr-766-4b8a921. Refuse the batch if any unrelated target appears. Post the canonical reconciliation handoff and stop. ``` WHAT_HAPPENED: An independent merger session re-ran the full merger gate sequence against fresh live state and merged PR #766. Verified before merge: OS identity jasonwalker/502 non-root; identity sysadmin with profile prgs-merger and identity_match true, auto_profile_substitution false; repository binding Scaled-Tech-Consulting/Gitea-Tools on remote prgs with canonical root /Users/jasonwalker/Development/Gitea-Tools and workspace roots aligned; namespace gitea-merger healthy with ide_namespace_proven true and blocks_merge_workflow false; runtime parity in_parity true, restart_required false, startup and current head both fcf6981b1ba4d8d5072357ba13be0fdb6baa07ff; workflow proof loaded from skills/llm-project-workflow/workflows/review-merge-pr.md at hash 263d0a6cb8a6; router route_result allowed_current_session; capability merge_pr allowed with stop_required false. Approval freshness: review 478 by sysadmin/prgs-reviewer, verdict APPROVED at exact head 4b8a9219d85bc99b6abeebb4dc9db3e344bc27e5, dismissed false, stale false, quarantined false, approval_at_current_head true, has_blocking_change_requests false, author jcwalker3 distinct from merger sysadmin. Sync reassessment: commits_behind 0, mergeable true, has_conflicts false, checks not required by live branch protection, recommended_next_action merge_now. A merger PR lease was acquired natively (lease comment 13074, session 52960-cfa84f3dee63) in a dedicated detached merger worktree, live state was re-read after acquisition and was unchanged, and the merge was then executed with the pinned head and confirmation. WHY: Every merger gate passed against freshly read live state, the approval was visible and undismissed at the exact pinned head with no blocking change requests, and the operator explicitly authorized the merge of this PR. RELATED_PRS: PR #766 (this PR, closed with merge commit d12adabeb1cf7810b1286ca8871a9b680646021c, implements issue #723). No other open PR is linked to issue #723, and this merger session touched no other PR. ISSUE: #723 BASE: master HEAD: fix/issue-723-role-stamp-invariants HEAD_SHA: 4b8a9219d85bc99b6abeebb4dc9db3e344bc27e5 REVIEW_STATUS: approved VALIDATION: No new validation was run by this merger session, by design. The merger phase does not re-review. Validation of record is reviewer review 478 at head 4b8a9219d85bc99b6abeebb4dc9db3e344bc27e5: red proof reproduced on master sources, focused 48 passed with 78 subtests, adjacent 769 passed with 241 subtests, full suite 3711 passed with 6 skipped and 491 subtests, and 2 failures proven pre-existing at base fcf6981b1ba4d8d5072357ba13be0fdb6baa07ff. BLOCKERS: none SUPERSEDES: none SUPERSEDED_BY: none MERGE_READY: merged — PR #766 state closed, merged_at 2026-07-19T23:38:50-05:00, merge commit d12adabeb1cf7810b1286ca8871a9b680646021c, live prgs/master advanced from fcf6981b1ba4d8d5072357ba13be0fdb6baa07ff to d12adabeb1cf7810b1286ca8871a9b680646021c, issue #723 auto-closed. LAST_UPDATED_BY: sysadmin / prgs-merger / 2026-07-20 NATIVE_MERGE_PROOF: transport=native_mcp; tool=gitea_merge_pr; namespace=gitea-merger; profile=prgs-merger; identity=sysadmin; pinned_head=4b8a9219d85bc99b6abeebb4dc9db3e344bc27e5; merge_method=merge; merge_commit=d12adabeb1cf7810b1286ca8871a9b680646021c; merger_lease_comment_id=13074; lease_proof_kind=sanctioned_acquire_merger [THREAD STATE LEDGER] What is true now: PR #766 is closed with merge commit d12adabeb1cf7810b1286ca8871a9b680646021c recorded at 2026-07-19T23:38:50-05:00. Live prgs/master is d12adabeb1cf7810b1286ca8871a9b680646021c. Issue #723 is closed. Server-side decision state: reviewer review 478 is the approval of record at head 4b8a9219d85bc99b6abeebb4dc9db3e344bc27e5, undismissed, non-stale, non-quarantined; the prgs-reviewer review-decision lock for this PR was cleared by the merge tool after the merge with audit comment id 13078; the merger PR lease from session 52960-cfa84f3dee63 (lease comment 13074) is now moot. Local verdict/state: this merger session prepared no verdict and holds no local decision state; it inspected live state only and executed the merge from a detached merger worktree at branches/merge-pr-766-4b8a921 pinned to head 4b8a9219d85bc99b6abeebb4dc9db3e344bc27e5. Every MCP namespace daemon is running code from startup head fcf6981b1ba4d8d5072357ba13be0fdb6baa07ff and is therefore stale relative to live master. The control checkout at /Users/jasonwalker/Development/Gitea-Tools remains on master at fcf6981b1ba4d8d5072357ba13be0fdb6baa07ff and is clean; the merger phase does not advance it. What changed: Server-side mutation ledger for this merger session, exactly four mutations: one merger PR lease comment id 13074; one native merge of PR #766 via gitea_merge_pr producing merge commit d12adabeb1cf7810b1286ca8871a9b680646021c; one post-merge review-decision-lock clearance for profile prgs-reviewer with audit comment id 13078; and this handoff comment. Issue #723 was closed by Gitea as a side effect of the merge, not by a direct issue mutation from this session. No formal review verdict was posted to Gitea by this session, no branch was pushed or deleted, no worktree was deleted, no label was changed, and no file was modified. Local: one detached merger worktree was created at branches/merge-pr-766-4b8a921 at the pinned head, and git fetch --prune prgs was run twice. The control checkout was not modified. What is blocked: - Blocker classification: no blocker PR #766 reached its terminal merged state with no blocking change requests, no conflicts, no failing in-scope tests, and no unresolved acceptance criteria. Two follow-on conditions are recorded here as preconditions for later phases rather than as blockers on this PR. First, every MCP namespace daemon is stale at fcf6981b1ba4d8d5072357ba13be0fdb6baa07ff and must be restarted or reconnected at d12adabeb1cf7810b1286ca8871a9b680646021c before any further mutation, because the loaded capability-gate code predates this merge. Second, residual hygiene items remain for a reconciler and are out of scope for a merger: the stale `status:pr-open` label on closed issue #723, the moot merger lease for PR #766, the merged remote branch `fix/issue-723-role-stamp-invariants`, and the three local worktrees created for this PR (author, reviewer, merger). Do not do: Do not re-review PR #766 or replay any approve or merge command; the PR is terminal. Do not run any mutation through a stale namespace before the restart or reconnect at d12adabeb1cf7810b1286ca8871a9b680646021c. Do not advance the control checkout as part of a merger phase. Do not delete branches, worktrees, or lock files by hand, and do not batch the residual cleanup together with unrelated targets. Do not treat this merger handoff as authorization for any new author work. Who/what acts next: Next actor: the operator, then a reconciler. Required action: the operator restarts or reconnects all four MCP namespaces (gitea-tools, gitea-reviewer, gitea-merger, gitea-reconciler) at master d12adabeb1cf7810b1286ca8871a9b680646021c and advances the control checkout to that SHA outside the merger phase; only after that may a prgs-reconciler session perform the scoped terminal cleanup listed above through sanctioned tools. This merger session performs no further mutation and stops here.
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#766