fix(gate): stop classifying stale-runtime blocks as permission denials (Closes #897) #901

Open
jcwalker3 wants to merge 1 commits from fix/issue-897-permission-stale-runtime-classification into master
Owner

Summary

Closes #897.

Stale-runtime and runtime-mode mutation refusals were returned as permission denials: permission_report named a permission the active profile already held and recommended gitea_activate_profile / session switch. That diagnosis is wrong and the recovery is hazardous (#685 reconnect-only; #690/#714 no mid-session role switch).

Changes

  • Typed gate refusals via _build_operation_gate_refusal:
    • blocker_kind=runtime_reconnect_required for master parity staleness (parity heads + reconnect-only action; no permission_report)
    • blocker_kind=runtime_mode_blocked for stable-control runtime blocks (no permission_report)
    • blocker_kind=permission_denied for true profile denials (permission_report retained)
    • Mixed stale + permission: both classes reported under separate fields; still no fabricated missing permission
  • _profile_operation_gate collects all refusal classes (no short-circuit)
  • _profile_permission_block uses the typed builder (covers mark/create/mutation paths)
  • _permission_block_report fails closed as diagnostic_defect when the active profile already holds the op
  • Selected direct gate returns (lease acquire, pr.close, branch.push) updated to the same builder

Tests

pytest tests/test_issue_897_permission_stale_runtime_classification.py tests/test_permission_reports.py -q
# 23 passed, 12 subtests passed

Role matrix: author / reviewer / merger / reconciler — stale+permitted, fresh+forbidden, stale+forbidden, create_issue regression.

Head

  • Branch: fix/issue-897-permission-stale-runtime-classification
  • Commit: 6e6ca9433873056c7a84d2a1ef3590323ea5a636
  • Worktree: branches/issue-897-permission-stale-runtime

Canonical PR state

STATE: author-complete
WHO_IS_NEXT: reviewer
NEXT_ACTION: formal review of head 6e6ca9433873056c7a84d2a1ef3590323ea5a636
## Summary Closes #897. Stale-runtime and runtime-mode mutation refusals were returned as permission denials: `permission_report` named a permission the active profile already held and recommended `gitea_activate_profile` / session switch. That diagnosis is wrong and the recovery is hazardous (#685 reconnect-only; #690/#714 no mid-session role switch). ## Changes - Typed gate refusals via `_build_operation_gate_refusal`: - `blocker_kind=runtime_reconnect_required` for master parity staleness (parity heads + reconnect-only action; **no** `permission_report`) - `blocker_kind=runtime_mode_blocked` for stable-control runtime blocks (**no** `permission_report`) - `blocker_kind=permission_denied` for true profile denials (`permission_report` retained) - Mixed stale + permission: both classes reported under separate fields; still no fabricated missing permission - `_profile_operation_gate` collects all refusal classes (no short-circuit) - `_profile_permission_block` uses the typed builder (covers mark/create/mutation paths) - `_permission_block_report` fails closed as `diagnostic_defect` when the active profile already holds the op - Selected direct gate returns (lease acquire, pr.close, branch.push) updated to the same builder ## Tests ```text pytest tests/test_issue_897_permission_stale_runtime_classification.py tests/test_permission_reports.py -q # 23 passed, 12 subtests passed ``` Role matrix: author / reviewer / merger / reconciler — stale+permitted, fresh+forbidden, stale+forbidden, create_issue regression. ## Head - Branch: `fix/issue-897-permission-stale-runtime-classification` - Commit: `6e6ca9433873056c7a84d2a1ef3590323ea5a636` - Worktree: `branches/issue-897-permission-stale-runtime` ## Canonical PR state ```text STATE: author-complete WHO_IS_NEXT: reviewer NEXT_ACTION: formal review of head 6e6ca9433873056c7a84d2a1ef3590323ea5a636 ```
jcwalker3 added 1 commit 2026-07-25 00:49:06 -05:00
Stale-runtime and runtime-mode mutation refusals previously shared the
permission-denial channel, so permission_report claimed a missing op the
active profile already held and recommended gitea_activate_profile.
Typed blocker_kind payloads report reconnect-only recovery for staleness,
omit permission_report for non-permission gates, and fail closed when a
permission_report would invent a missing permission the profile holds.
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #901
issue: none
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 19262-c1d8c36e6171
worktree: branches/issue-897-permission-stale-runtime
phase: claimed
candidate_head: none
target_branch: master
target_branch_sha: none
last_activity: 2026-07-25T06:04:24Z
expires_at: 2026-07-25T06:14:24Z
blocker: none

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #901 issue: none reviewer_identity: sysadmin profile: prgs-reviewer session_id: 19262-c1d8c36e6171 worktree: branches/issue-897-permission-stale-runtime phase: claimed candidate_head: none target_branch: master target_branch_sha: none last_activity: 2026-07-25T06:04:24Z expires_at: 2026-07-25T06:14:24Z blocker: none
sysadmin approved these changes 2026-07-25 01:09:16 -05:00
sysadmin left a comment
Owner

Canonical PR State

STATE: reviewer-approved
WHO_IS_NEXT: merger
NEXT_ACTION: merge PR 901 at head 6e6ca94338
NEXT_PROMPT:

Execute sanctioned gitea-merger workflow for PR #901 at head 6e6ca9433873056c7a84d2a1ef3590323ea5a636.

WHAT_HAPPENED: Formal review completed by sysadmin under prgs-reviewer profile. PR #901 correctly addresses #897 by stopping misclassification of stale-runtime and runtime-mode refusals as permission denials.
WHY: All acceptance criteria A-H verified in code and tests. Focused test suite passed cleanly (23 tests).
ISSUE: #897
HEAD_SHA: 6e6ca94338
REVIEW_STATUS: APPROVED
MERGE_READY: true
BLOCKERS: none
VALIDATION: pytest tests/test_issue_897_permission_stale_runtime_classification.py tests/test_permission_reports.py (23 passed)
LAST_UPDATED_BY: sysadmin

NATIVE_REVIEW_PROOF: transport=native_mcp; entrypoint=mcp_server; token_fingerprint=4539170d8551c07a


Detailed Review Summary

PR #901 addresses issue #897 by ensuring stale-runtime and runtime-mode refusals are properly classified as system/runtime gate failures rather than profile permission denials.

Key verifications:

  1. Typed blockers: Stale-runtime refusals use blocker_kind=runtime_reconnect_required, runtime-mode refusals use blocker_kind=runtime_mode_blocked, and true profile denials use blocker_kind=permission_denied.
  2. No fabricated permission_report: Stale and runtime-mode refusals do not attach permission_report or claim missing permissions that the active profile already holds.
  3. Sanctioned recovery: Staleness recovery explicitly points to IDE/client session reconnect instead of profile switching.
  4. _permission_block_report integrity: Flags diagnostic_defect: True when active profile holds operation.
  5. Gate collection & cause separation: Stale and permission causes reported distinctly under stale_runtime_reasons and permission_block_reasons.
  6. Regression & Scope: Scoped to gitea_mcp_server.py and tests/test_issue_897_permission_stale_runtime_classification.py. All 23 tests pass cleanly.
## Canonical PR State STATE: reviewer-approved WHO_IS_NEXT: merger NEXT_ACTION: merge PR 901 at head 6e6ca9433873056c7a84d2a1ef3590323ea5a636 NEXT_PROMPT: ```text Execute sanctioned gitea-merger workflow for PR #901 at head 6e6ca9433873056c7a84d2a1ef3590323ea5a636. ``` WHAT_HAPPENED: Formal review completed by sysadmin under prgs-reviewer profile. PR #901 correctly addresses #897 by stopping misclassification of stale-runtime and runtime-mode refusals as permission denials. WHY: All acceptance criteria A-H verified in code and tests. Focused test suite passed cleanly (23 tests). ISSUE: #897 HEAD_SHA: 6e6ca9433873056c7a84d2a1ef3590323ea5a636 REVIEW_STATUS: APPROVED MERGE_READY: true BLOCKERS: none VALIDATION: pytest tests/test_issue_897_permission_stale_runtime_classification.py tests/test_permission_reports.py (23 passed) LAST_UPDATED_BY: sysadmin NATIVE_REVIEW_PROOF: transport=native_mcp; entrypoint=mcp_server; token_fingerprint=4539170d8551c07a --- ## Detailed Review Summary PR #901 addresses issue #897 by ensuring stale-runtime and runtime-mode refusals are properly classified as system/runtime gate failures rather than profile permission denials. Key verifications: 1. **Typed blockers**: Stale-runtime refusals use `blocker_kind=runtime_reconnect_required`, runtime-mode refusals use `blocker_kind=runtime_mode_blocked`, and true profile denials use `blocker_kind=permission_denied`. 2. **No fabricated `permission_report`**: Stale and runtime-mode refusals do not attach `permission_report` or claim missing permissions that the active profile already holds. 3. **Sanctioned recovery**: Staleness recovery explicitly points to IDE/client session reconnect instead of profile switching. 4. **`_permission_block_report` integrity**: Flags `diagnostic_defect: True` when active profile holds operation. 5. **Gate collection & cause separation**: Stale and permission causes reported distinctly under `stale_runtime_reasons` and `permission_block_reasons`. 6. **Regression & Scope**: Scoped to `gitea_mcp_server.py` and `tests/test_issue_897_permission_stale_runtime_classification.py`. All 23 tests pass cleanly.
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #901
issue: none
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 19262-c1d8c36e6171
worktree: branches/issue-897-permission-stale-runtime
phase: released
candidate_head: none
target_branch: master
target_branch_sha: none
last_activity: 2026-07-25T06:09:38Z
expires_at: 2026-07-25T06:19:38Z
blocker: manual-release

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #901 issue: none reviewer_identity: sysadmin profile: prgs-reviewer session_id: 19262-c1d8c36e6171 worktree: branches/issue-897-permission-stale-runtime phase: released candidate_head: none target_branch: master target_branch_sha: none last_activity: 2026-07-25T06:09:38Z expires_at: 2026-07-25T06:19:38Z blocker: manual-release
You are not authorized to merge this pull request.
This pull request can be merged automatically.
This branch is out-of-date with the base branch
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin fix/issue-897-permission-stale-runtime-classification:fix/issue-897-permission-stale-runtime-classification
git checkout fix/issue-897-permission-stale-runtime-classification
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#901