Fix review 646 blockers B1-B7 for cross-repo canonical roots (#973)

This commit is contained in:
2026-07-29 14:01:17 -04:00
parent 6a53308473
commit 7978008709
4 changed files with 380 additions and 80 deletions
+51 -11
View File
@@ -500,10 +500,38 @@ def _resolve_preflight_workspace_path(worktree_path: str | None = None) -> str:
return workspace
def _resolve_namespace_mutation_context(worktree_path: str | None = None) -> dict:
def _resolve_expected_repository_slug(
remote: str | None = None,
org: str | None = None,
repo: str | None = None,
) -> str | None:
"""Resolve expected repository slug from parameters, session context, or remote URL."""
if org and repo:
return session_ctx.format_repository_slug(org, repo)
bound = session_ctx.get_session_context() or {}
b_org = bound.get("org")
b_repo = bound.get("repository")
if b_org and b_repo:
return session_ctx.format_repository_slug(b_org, b_repo)
eff_remote = remote or bound.get("remote") or _effective_remote()
parsed = remote_repo_guard.parse_org_repo_from_remote_url(
_local_git_remote_url(eff_remote)
)
if parsed:
return session_ctx.format_repository_slug(parsed[0], parsed[1])
return None
def _resolve_namespace_mutation_context(
worktree_path: str | None = None,
remote: str | None = None,
) -> dict:
"""Canonical namespace workspace + repository root for guards (#460/#510/#706/#618)."""
role = _effective_workspace_role()
configured_root, _source = _configured_canonical_root()
bound = session_ctx.get_session_context() or {}
eff_remote = remote or bound.get("remote") or _effective_remote()
expected_slug = _resolve_expected_repository_slug(eff_remote)
return nwb.resolve_namespace_mutation_context(
role_kind=role,
worktree_path=worktree_path,
@@ -516,9 +544,12 @@ def _resolve_namespace_mutation_context(worktree_path: str | None = None) -> dic
),
profile_name=get_profile().get("profile_name"),
configured_canonical_root=configured_root,
expected_slug=expected_slug,
remote=eff_remote,
)
def _resolve_author_mutation_context(worktree_path: str | None = None) -> dict:
"""Backward-compatible alias for namespace workspace context."""
return _resolve_namespace_mutation_context(worktree_path)
@@ -620,6 +651,9 @@ def _preflight_workspace_details(worktree_path: str | None, dirty_files: list[st
inspected_root = _get_git_root(workspace)
process_root = ctx["process_project_root"]
canonical_root = ctx["canonical_repo_root"]
crr_assessment = ctx.get("canonical_root_assessment") or {}
resolved_slug = crr_assessment.get("resolved_slug")
expected_slug = ctx.get("expected_slug")
active_root = os.path.realpath(inspected_root or workspace)
if active_root == canonical_root:
dirty_scope = "control checkout"
@@ -649,6 +683,10 @@ def _preflight_workspace_details(worktree_path: str | None, dirty_files: list[st
"workspace_healthy": not bool(
ctx.get("bound_worktree_missing") or ctx.get("author_worktree_block")
),
"canonical_root_assessment": crr_assessment,
"expected_repository_slug": expected_slug,
"observed_repository_identity": resolved_slug,
"worktree_registration_result": ctx.get("in_git_worktree_list"),
}
if not ctx["roots_aligned"]:
details["workspace_root_mismatch"] = (
@@ -658,6 +696,7 @@ def _preflight_workspace_details(worktree_path: str | None, dirty_files: list[st
return details
def _format_preflight_workspace_details(details: dict) -> str:
parts = [
f"MCP server process root: {details.get('mcp_server_process_root')}",
@@ -1866,6 +1905,9 @@ def _verify_role_mutation_workspace(
# back to the install checkout and validated Gitea-Tools/branches/ instead
# of the target repository the namespace is actually bound to.
_configured_root, _configured_source = _configured_canonical_root()
bound = session_ctx.get_session_context() or {}
eff_remote = remote or bound.get("remote") or _effective_remote()
expected_slug = _resolve_expected_repository_slug(eff_remote, org=org, repo=repo)
assessment = nwb.assess_namespace_mutation_workspace(
role_kind=role,
worktree_path=worktree_path,
@@ -1880,6 +1922,8 @@ def _verify_role_mutation_workspace(
profile_name=get_profile().get("profile_name"),
current_branch=git_state.get("current_branch"),
configured_canonical_root=_configured_root,
expected_slug=expected_slug,
remote=eff_remote,
)
if assessment["block"]:
raise RuntimeError(
@@ -3414,7 +3458,7 @@ def cleanup_in_progress_for_pr(
# ── Helpers ───────────────────────────────────────────────────────────────────
def _effective_remote(remote: str) -> str:
def _effective_remote(remote: str = "dadeschools") -> str:
"""If remote is the default ('dadeschools') but the active profile base_url maps to a known remote, use that remote instead."""
try:
profile = get_profile()
@@ -15277,22 +15321,17 @@ def _current_runtime_mode_report(refresh: bool = False) -> dict:
workspace_root = None
aligned = None
canonical_root = None
resolved_slug = None
try:
ctx = _resolve_namespace_mutation_context(None)
workspace_root = ctx.get("workspace_path")
canonical_root = ctx.get("canonical_repo_root")
# Alignment keeps its established repository-level meaning (#615 F1):
# does this namespace target the repository the process is installed in,
# i.e. canonical_repo_root == process_project_root. It is deliberately
# NOT path equality between the task workspace and the process root --
# the global worktree rule requires task work to live in a branches/
# worktree, so that comparison would classify every correctly bound
# author, reviewer, and merger session as unsafe.
aligned = ctx.get("roots_aligned")
crr_assessment = ctx.get("canonical_root_assessment") or {}
resolved_slug = crr_assessment.get("resolved_slug")
except Exception:
# An unresolvable binding is reported as unknown alignment, never as
# proof of alignment.
aligned = None
resolved_slug = None
try:
profile_name = get_profile()["profile_name"]
except Exception:
@@ -15305,6 +15344,7 @@ def _current_runtime_mode_report(refresh: bool = False) -> dict:
dirty_files=dirty_files,
active_task_workspace=workspace_root,
canonical_repository_root=canonical_root,
repository_slug=resolved_slug,
workspace_roots_aligned=aligned,
profile=profile_name,
declared_mode=stable_control_runtime.declared_runtime_mode(),