fix: authoritative cross-role generic queue allocation (Closes #840)
Add controller-owned cross_role allocation mode that inspects the full queue and returns one selection with required role/profile/action and lease evidence. Document process_work_queue routing, normalize controller role metadata, and keep the dashboard explanatory only. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
@@ -24,7 +24,12 @@ ROLE_WORKTREE_ENVS: dict[str, str] = {
|
||||
"reconciler": RECONCILER_WORKTREE_ENV,
|
||||
}
|
||||
|
||||
NON_AUTHOR_ROLES = frozenset({"reviewer", "merger", "reconciler"})
|
||||
# Controller has no task worktree env — it routes only (#840).
|
||||
KNOWN_ROLE_KINDS = frozenset(
|
||||
{"author", "reviewer", "merger", "reconciler", "controller"}
|
||||
)
|
||||
|
||||
NON_AUTHOR_ROLES = frozenset({"reviewer", "merger", "reconciler", "controller"})
|
||||
|
||||
|
||||
def normalize_role_kind(
|
||||
@@ -37,8 +42,12 @@ def normalize_role_kind(
|
||||
profile = (profile_name or "").strip().lower()
|
||||
if role == "reviewer" and "merger" in profile:
|
||||
return "merger"
|
||||
if "controller" in profile or role == "controller":
|
||||
return "controller"
|
||||
if role in ROLE_WORKTREE_ENVS:
|
||||
return role
|
||||
if role in KNOWN_ROLE_KINDS:
|
||||
return role
|
||||
return "author"
|
||||
|
||||
|
||||
@@ -80,7 +89,7 @@ def resolve_namespace_workspace(
|
||||
"""
|
||||
env_map = env if env is not None else os.environ
|
||||
role = normalize_role_kind(role_kind, profile_name=profile_name)
|
||||
role_env_key = ROLE_WORKTREE_ENVS[role]
|
||||
role_env_key = ROLE_WORKTREE_ENVS.get(role)
|
||||
|
||||
# #618: durable author resolution — no silent control/master fallback.
|
||||
if role == "author" and verify_paths:
|
||||
@@ -108,13 +117,17 @@ def resolve_namespace_workspace(
|
||||
)
|
||||
return workspace, source
|
||||
|
||||
role_env_candidate = (
|
||||
(_env_value(env_map, role_env_key), f"{role_env_key} environment variable", True)
|
||||
if role_env_key
|
||||
else (None, "no role worktree env", True)
|
||||
)
|
||||
for candidate, source, env_sourced in (
|
||||
(worktree_path, "worktree_path argument", False),
|
||||
(worktree, "worktree argument", False),
|
||||
(_env_value(env_map, ACTIVE_WORKTREE_ENV),
|
||||
f"{ACTIVE_WORKTREE_ENV} environment variable", True),
|
||||
(_env_value(env_map, role_env_key),
|
||||
f"{role_env_key} environment variable", True),
|
||||
role_env_candidate,
|
||||
(session_lease_worktree if role in {"reviewer", "merger"} else None,
|
||||
"reviewer PR lease worktree", False),
|
||||
# Author lock derivation is handled by the durable path above when
|
||||
@@ -433,7 +446,8 @@ def assess_namespace_mutation_workspace(
|
||||
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[role]} / {ACTIVE_WORKTREE_ENV}"
|
||||
f"or set {ROLE_WORKTREE_ENVS.get(role, ACTIVE_WORKTREE_ENV)} / "
|
||||
f"{ACTIVE_WORKTREE_ENV}"
|
||||
)
|
||||
elif (
|
||||
role in {"reviewer", "merger"}
|
||||
|
||||
Reference in New Issue
Block a user