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
+54 -40
View File
@@ -189,23 +189,23 @@ def verify_git_common_directory_membership(
real_common = os.path.realpath(common_dir)
canonical_git = os.path.realpath(os.path.join(real_root, ".git"))
if real_common in (canonical_git, real_root) or os.path.dirname(real_common) == real_root:
if real_common in (canonical_git, real_root):
return True, None
return (
False,
f"workspace '{real_ws}' git common directory '{real_common}' does not match "
f"canonical repository root '{real_root}' (.git at '{canonical_git}')"
)
except Exception:
pass
if amw.is_path_under_branches(real_ws, real_root):
return True, None
return (
False,
f"workspace '{real_ws}' does not belong to canonical repository root '{real_root}'"
)
else:
return (
False,
f"workspace '{real_ws}' is not a valid git repository or git rev-parse failed"
)
except Exception as exc:
return (
False,
f"failed to inspect git common directory for workspace '{real_ws}': {exc}"
)
def resolve_namespace_mutation_context(
@@ -313,6 +313,8 @@ def resolve_namespace_mutation_context(
"canonical_repo_root": canonical_root,
"roots_aligned": roots_aligned,
"canonical_root_assessment": crr_assessment,
"expected_slug": expected_slug,
"remote": remote,
}
if durable is not None:
result["author_worktree_resolution"] = durable
@@ -324,6 +326,15 @@ def resolve_namespace_mutation_context(
result["author_worktree_reasons"] = list(durable.get("reasons") or [])
result["author_worktree_blocker_kind"] = durable.get("blocker_kind")
result["operator_recovery"] = durable.get("operator_recovery")
else:
path_exists = os.path.exists(workspace)
result["path_exists"] = path_exists
result["in_git_worktree_list"] = (
amw.path_in_git_worktree_list(workspace, canonical_root)
if path_exists
else False
)
result["bound_worktree_missing"] = not path_exists
return result
@@ -456,8 +467,8 @@ def format_namespace_workspace_binding_error(
def assess_namespace_mutation_workspace(
*,
role_kind: str,
worktree_path: str | None,
worktree: str | None,
worktree_path: str | None = None,
worktree: str | None = None,
process_project_root: str,
env: dict[str, str] | os._Environ | None = None,
session_lease_worktree: str | None = None,
@@ -509,14 +520,16 @@ def assess_namespace_mutation_workspace(
if crr_reasons:
reasons.extend(crr_reasons)
if not ctx.get("roots_aligned"):
if not crr_reasons:
reasons.append(
f"unsafe_process_root_workspace_alignment: process root '{process_root}' "
f"and canonical root '{ctx['canonical_repo_root']}' disagree"
)
path_exists = ctx.get("path_exists")
if path_exists is None:
path_exists = os.path.exists(mutation_workspace)
if os.path.exists(mutation_workspace):
if not path_exists:
if role != "author":
reasons.append(
f"{role} mutation blocked: configured workspace directory '{mutation_workspace}' does not exist (nonexistent worktree)"
)
else:
valid_common, common_err = verify_git_common_directory_membership(
mutation_workspace, ctx["canonical_repo_root"]
)
@@ -539,26 +552,27 @@ def assess_namespace_mutation_workspace(
)
if branches["block"]:
reasons.extend(branches["reasons"])
elif (
role == "reviewer"
and mutation_workspace == process_root
and not amw.is_path_under_branches(mutation_workspace, ctx["canonical_repo_root"])
):
reasons.append(
f"{role} mutation blocked: workspace is the stable control checkout; "
f"create or reconnect to a session-owned worktree under branches/ "
f"or set {ROLE_WORKTREE_ENVS.get(role, ACTIVE_WORKTREE_ENV)} / "
f"{ACTIVE_WORKTREE_ENV}"
)
elif (
role in {"reviewer", "merger"}
and mutation_workspace != process_root
and not amw.is_path_under_branches(mutation_workspace, ctx["canonical_repo_root"])
):
reasons.append(
f"{role} mutation blocked: workspace '{mutation_workspace}' is not under "
f"'{ctx['canonical_repo_root']}/branches/'"
)
elif role in {"reviewer", "merger"}:
if mutation_workspace == process_root and not amw.is_path_under_branches(mutation_workspace, ctx["canonical_repo_root"]):
reasons.append(
f"{role} mutation blocked: workspace is the stable control checkout; "
f"create or reconnect to a session-owned worktree under branches/ "
f"or set {ROLE_WORKTREE_ENVS.get(role, ACTIVE_WORKTREE_ENV)} / "
f"{ACTIVE_WORKTREE_ENV}"
)
elif mutation_workspace != process_root and not amw.is_path_under_branches(mutation_workspace, ctx["canonical_repo_root"]):
reasons.append(
f"{role} mutation blocked: workspace '{mutation_workspace}' is not under "
f"'{ctx['canonical_repo_root']}/branches/'"
)
if path_exists and amw.is_path_under_branches(mutation_workspace, ctx["canonical_repo_root"]):
in_list = ctx.get("in_git_worktree_list")
if in_list is False:
reasons.append(
f"{role} mutation blocked: workspace '{mutation_workspace}' is under branches/ "
f"but is not registered in git worktree list for '{ctx['canonical_repo_root']}'"
)
block = bool(reasons)
return {