revert(ack): restore three-role collaboration scope

This reverts commit a0f1c15b85.
This commit is contained in:
2026-08-01 17:48:33 +08:00
parent a0f1c15b85
commit f02a34e751
21 changed files with 58 additions and 871 deletions
+10 -45
View File
@@ -41,7 +41,6 @@ from validate_tasks import load_document, validate_builtin # noqa: E402
from worker_profiles import ( # noqa: E402
LAUNCH_PROTOCOL_VERSION,
canonical_sha256,
environment_policy_for_role,
profile_hash,
render_worker_argv,
validate_routing_document,
@@ -49,6 +48,7 @@ from worker_profiles import ( # noqa: E402
PROTOCOL_VERSION = LAUNCH_PROTOCOL_VERSION
RECEIPT_VERSION = 1
ENVIRONMENT_POLICY = "per-cli-allowlist-v1"
TASKS_RELATIVE_PATH = Path("docs/ack/tasks.yaml")
MAX_CONTROL_OUTPUT = 1024 * 1024
MAX_RECORD_SIZE = 256 * 1024
@@ -82,15 +82,6 @@ WORKER_CREDENTIAL_NAMES = {
"codex": frozenset({"AZURE_OPENAI_API_KEY", "OPENAI_API_KEY"}),
"cursor-agent": frozenset({"CURSOR_API_KEY"}),
}
OPERATOR_CREDENTIAL_NAMES = frozenset(
{
"DEB_REPOSITORY",
"DEB_SERVER_URL",
"DEB_TOKEN",
"DEB_UPLOAD_PATH",
"SSH_AUTH_SOCK",
}
)
INHERITED_ENVIRONMENT_PREFIXES = (
"LC_",
)
@@ -193,23 +184,13 @@ def control_environment() -> dict[str, str]:
return _sanitized_environment(CONTROL_ENVIRONMENT_NAMES)
def worker_environment(cli: str, role: str | None = None) -> dict[str, str]:
def worker_environment(cli: str) -> dict[str, str]:
"""Return only the supported CLI's own credentials and common runtime data."""
credential_names = WORKER_CREDENTIAL_NAMES.get(cli)
if credential_names is None:
raise LaunchError(f"不支持的 worker CLI 环境: {cli}")
if role is not None:
try:
environment_policy_for_role(role)
except ValueError as exc:
raise LaunchError(f"不支持的 worker role 环境: {role}") from exc
role_credentials = (
OPERATOR_CREDENTIAL_NAMES if role == "operator" else frozenset()
)
return _sanitized_environment(
WORKER_ENVIRONMENT_NAMES | credential_names | role_credentials
)
return _sanitized_environment(WORKER_ENVIRONMENT_NAMES | credential_names)
def reject_duplicate_or_separator_args(argv: list[str]) -> None:
@@ -652,20 +633,15 @@ def build_plan(
raise LaunchError("task-id 只允许字母、数字、点、下划线和连字符")
if attempt_id not in {f"{task_id}-A1", f"{task_id}-A2", f"{task_id}-A3"}:
raise LaunchError("attempt-id 必须精确为 <task-id>-A1..A3")
if role not in {"developer", "test", "operator"}:
raise LaunchError("role 必须是 developer、test 或 operator")
if role not in {"developer", "test"}:
raise LaunchError("role 必须是 developer 或 test")
if not PROFILE_ID_RE.fullmatch(profile_id):
raise LaunchError("profile-id 格式非法")
if not isinstance(slot, int) or isinstance(slot, bool) or not 1 <= slot <= 99:
raise LaunchError("slot 必须是 1..99 的整数")
project_root, board = load_authoritative_board(project_root_value)
task = find_task(board, task_id)
is_delivery_operation = task.get("type") == "delivery-operation"
if role == "operator" and not is_delivery_operation:
raise LaunchError("operator 只能用于 delivery-operation 任务")
if role != "operator" and is_delivery_operation:
raise LaunchError("delivery-operation 任务只能由 operator 执行")
find_task(board, task_id)
project = board["project"]
orchestration = project.get("orchestration")
if not isinstance(orchestration, dict):
@@ -705,7 +681,7 @@ def build_plan(
"cliVersion": cli_version,
"argv": argv,
"argvHash": canonical_sha256(argv),
"environmentPolicy": environment_policy_for_role(role),
"environmentPolicy": ENVIRONMENT_POLICY,
}
current_profile_hash = profile_hash(
profile,
@@ -729,11 +705,7 @@ def build_plan(
}
)
cli_label = "CODEX" if profile["cli"] == "codex" else "CURSOR"
role_label = {
"developer": "DEV",
"test": "TEST",
"operator": "OP",
}[role]
role_label = "DEV" if role == "developer" else "TEST"
digest_short = launch_fingerprint.split(":", 1)[-1][:10]
title = (
f"ACK-{role_label}-{cli_label}-{str(profile['tier']).upper()}-"
@@ -1481,10 +1453,7 @@ def bootstrap_worker(launch_id: str) -> int:
rebuilt["requested"]["argv"],
shell=False,
cwd=rebuilt["worktree"]["path"],
env=worker_environment(
str(rebuilt["requested"]["cli"]),
str(rebuilt["role"]),
),
env=worker_environment(str(rebuilt["requested"]["cli"])),
)
current_record.update(
state="bootstrap-ready",
@@ -1519,11 +1488,7 @@ def add_launch_arguments(parser: argparse.ArgumentParser) -> None:
parser.add_argument("--project-root", required=True)
parser.add_argument("--task-id", required=True)
parser.add_argument("--attempt-id", required=True)
parser.add_argument(
"--role",
required=True,
choices=("developer", "test", "operator"),
)
parser.add_argument("--role", required=True, choices=("developer", "test"))
parser.add_argument("--profile-id", required=True)
parser.add_argument("--worktree", required=True)
parser.add_argument("--slot", type=int, default=1)