fix(mcp): forward explicit org/repo into lease/review anti-stomp

_verify_role_mutation_workspace dropped org/repo, so anti-stomp resolved bare
remote=prgs to Timesheet and failed closed wrong_repo on Gitea-Tools. Forward
explicit org/repo for merger/reviewer lease acquire, adopt, review, merge, and
lease release. Add regression for merger acquire forwarding.

Fixes #718
Refs #723
This commit is contained in:
2026-07-17 13:30:52 -04:00
parent 29c2cf2ef6
commit 83bc7246ff
2 changed files with 76 additions and 7 deletions
+45 -7
View File
@@ -1282,12 +1282,18 @@ def _verify_role_mutation_workspace(
worktree_path: str | None = None,
worktree: str | None = None,
task: str | None = None,
org: str | None = None,
repo: str | None = None,
) -> str:
"""Bind reviewer/merger mutations to the active namespace workspace (#510).
#683: must NOT early-return solely because pytest/unittest is loaded.
Production workspace binding always runs; test isolation uses explicit
env fixtures / force-on flags, never a production short-circuit here.
org/repo are forwarded into anti-stomp (#604) so callers that pass explicit
repository targets (e.g. prgs + Gitea-Tools when REMOTES defaults to
Timesheet) do not fail closed with wrong_repo after a successful resolve.
"""
# Check running runtimes to prevent stale mutations
@@ -1350,7 +1356,13 @@ def _verify_role_mutation_workspace(
)
)
resolved = assessment["mutation_workspace"]
verify_preflight_purity(remote, worktree_path=resolved, task=task)
verify_preflight_purity(
remote,
worktree_path=resolved,
task=task,
org=org,
repo=repo,
)
return resolved
@@ -4521,7 +4533,11 @@ def _evaluate_pr_review_submission(
) -> dict:
"""Shared gate chain for live submit and dry-run review tools."""
_verify_role_mutation_workspace(
remote, worktree_path=worktree_path, task="review_pr"
remote,
worktree_path=worktree_path,
task="review_pr",
org=org,
repo=repo,
)
action = (action or "").strip().lower()
workflow_blockers = _review_workflow_load_gate_reasons() if live else []
@@ -7619,7 +7635,11 @@ def gitea_merge_pr(
available. Never secrets.
"""
_verify_role_mutation_workspace(
remote, worktree_path=worktree_path, task="merge_pr"
remote,
worktree_path=worktree_path,
task="merge_pr",
org=org,
repo=repo,
)
allowed = get_profile()["allowed_operations"]
forbidden = get_profile()["forbidden_operations"]
@@ -10652,8 +10672,14 @@ def gitea_acquire_reviewer_pr_lease(
# task=acquire_reviewer_pr_lease so verify_preflight_purity runs shared #604
# anti-stomp for the declared lease-acquire mutation inventory entry.
# Forward explicit org/repo so anti-stomp does not default bare remote=prgs
# to Timesheet when the local git remote is Gitea-Tools (#604 wrong_repo).
_verify_role_mutation_workspace(
remote, worktree=worktree, task="acquire_reviewer_pr_lease"
remote,
worktree=worktree,
task="acquire_reviewer_pr_lease",
org=org,
repo=repo,
)
h, o, r = _resolve(remote, host, org, repo)
auth = _auth(h)
@@ -10794,7 +10820,11 @@ def gitea_acquire_merger_pr_lease(
try:
_verify_role_mutation_workspace(
remote, worktree=worktree, task="acquire_merger_pr_lease"
remote,
worktree=worktree,
task="acquire_merger_pr_lease",
org=org,
repo=repo,
)
except RuntimeError as e:
return {
@@ -10987,7 +11017,11 @@ def gitea_adopt_merger_pr_lease(
# task=adopt_merger_pr_lease so verify_preflight_purity runs shared #604 anti-stomp.
_verify_role_mutation_workspace(
remote, worktree=worktree, task="adopt_merger_pr_lease"
remote,
worktree=worktree,
task="adopt_merger_pr_lease",
org=org,
repo=repo,
)
h, o, r = _resolve(remote, host, org, repo)
auth = _auth(h)
@@ -11709,7 +11743,11 @@ def gitea_release_reviewer_pr_lease(
dict reporting release status.
"""
_verify_role_mutation_workspace(
remote, worktree=worktree, task="review_pr"
remote,
worktree=worktree,
task="review_pr",
org=org,
repo=repo,
)
h, o, r = _resolve(remote, host, org, repo)
auth = _auth(h)