#!/usr/bin/env python3 """Launch an ACK worker from a validated, structured profile. Public commands: profile-hash Print the canonical hash for one configured profile. plan Validate and print the exact launch plan without creating a terminal. launch Create an Orca terminal through a fixed bootstrap command. The private ``_bootstrap`` command accepts only an opaque hexadecimal launch ID. It re-reads the authoritative task board, revalidates the profile and worktree, then starts the Agent CLI with an argv array and ``shell=False``. """ from __future__ import annotations import argparse import fcntl import hashlib import hmac import json import os import pwd import re import secrets import select import shlex import stat import subprocess import sys import time from contextlib import contextmanager from datetime import datetime, timedelta, timezone from pathlib import Path from typing import Iterator SCRIPT_DIR = Path(__file__).resolve().parent if str(SCRIPT_DIR) not in sys.path: sys.path.insert(0, str(SCRIPT_DIR)) 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, ) PROTOCOL_VERSION = LAUNCH_PROTOCOL_VERSION RECEIPT_VERSION = 1 TASKS_RELATIVE_PATH = Path("docs/ack/tasks.yaml") MAX_CONTROL_OUTPUT = 1024 * 1024 MAX_RECORD_SIZE = 256 * 1024 LAUNCH_TTL_SECONDS = 120 BOOTSTRAP_READY_TIMEOUT_SECONDS = 10 CONTROL_TIMEOUT_SECONDS = 30 LAUNCH_ID_RE = re.compile(r"^[0-9a-f]{64}$") PROFILE_ID_RE = re.compile(r"^[a-z][a-z0-9-]{1,63}$") TASK_ID_RE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$") SHA256_RE = re.compile(r"^sha256:[0-9a-f]{64}$") CONTROL_ENVIRONMENT_NAMES = { "COLORTERM", "LANG", "LC_ALL", "NO_COLOR", "TERM", "TZ", } WORKER_ENVIRONMENT_NAMES = CONTROL_ENVIRONMENT_NAMES | { "HTTPS_PROXY", "HTTP_PROXY", "SSL_CERT_DIR", "SSL_CERT_FILE", "https_proxy", "http_proxy", "no_proxy", "NO_PROXY", } 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_", ) class LaunchError(RuntimeError): """A deterministic launch validation or runtime error.""" class IndeterminateLaunch(LaunchError): """Orca may have created a terminal, but no safe identity was obtained.""" def utc_now() -> datetime: return datetime.now(timezone.utc) def format_timestamp(value: datetime) -> str: return value.astimezone(timezone.utc).isoformat().replace("+00:00", "Z") def parse_timestamp(value: object, label: str) -> datetime: if not isinstance(value, str) or not value: raise LaunchError(f"{label} 必须是 RFC3339 时间字符串") normalized = value[:-1] + "+00:00" if value.endswith("Z") else value try: parsed = datetime.fromisoformat(normalized) except ValueError as exc: raise LaunchError(f"{label} 不是合法 RFC3339 时间") from exc if parsed.tzinfo is None: raise LaunchError(f"{label} 必须包含时区") return parsed.astimezone(timezone.utc) def safe_identity_text(value: object, label: str, *, max_length: int = 512) -> str: if ( not isinstance(value, str) or not value.strip() or value != value.strip() or len(value) > max_length or any(character in value for character in ("\0", "\n", "\r")) ): raise LaunchError(f"{label} 必须是安全的单行非空字符串") return value def account_identity() -> tuple[Path, str]: account = pwd.getpwuid(os.getuid()) home = Path(account.pw_dir).resolve(strict=True) if not home.is_dir(): raise LaunchError("当前用户 home 不是可访问目录") return home, account.pw_name def trusted_path_entries() -> list[Path]: home, _ = account_identity() candidates = [ home / ".local" / "bin", home / ".local" / "share" / "mise" / "shims", home / ".cargo" / "bin", Path("/home/linuxbrew/.linuxbrew/bin"), Path("/usr/local/go/bin"), Path("/usr/local/bin"), Path("/usr/bin"), Path("/bin"), ] result: list[Path] = [] for candidate in candidates: try: resolved = candidate.resolve(strict=True) except OSError: continue if resolved.is_dir() and resolved not in result: result.append(resolved) return result def _sanitized_environment(allowed_names: frozenset[str] | set[str]) -> dict[str, str]: """Build an environment from exact names plus locale categories.""" home, username = account_identity() result = { "HOME": str(home), "LOGNAME": username, "PATH": os.pathsep.join(str(path) for path in trusted_path_entries()), "USER": username, } for name, value in os.environ.items(): if name in allowed_names or any( name.startswith(prefix) for prefix in INHERITED_ENVIRONMENT_PREFIXES ): if "\0" not in value: result[name] = value return result def control_environment() -> dict[str, str]: """Return a credential-free environment for Git, Orca, and CLI probes.""" return _sanitized_environment(CONTROL_ENVIRONMENT_NAMES) def worker_environment(cli: str, role: str | None = None) -> 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 ) def reject_duplicate_or_separator_args(argv: list[str]) -> None: seen: set[str] = set() for token in argv: if token == "--": raise LaunchError("不接受 -- 分隔符或额外位置参数") if not token.startswith("--"): continue name = token.split("=", 1)[0] if name in seen: raise LaunchError(f"命令行参数不能重复: {name}") seen.add(name) def _path_has_parent_reference(value: str) -> bool: return ".." in Path(value).parts def _assert_no_symlink_components(path: Path, label: str) -> None: if not path.is_absolute(): raise LaunchError(f"{label}必须是绝对路径: {path}") current = Path(path.anchor) for part in path.parts[1:]: current /= part try: metadata = os.lstat(current) except OSError as exc: raise LaunchError(f"{label}不存在或不可访问: {current}") from exc if stat.S_ISLNK(metadata.st_mode): raise LaunchError(f"{label}不能包含 symlink: {current}") def canonical_directory(value: str, label: str) -> Path: if not value or _path_has_parent_reference(value): raise LaunchError(f"{label}必须是无 '..' 的绝对目录") raw = Path(value) _assert_no_symlink_components(raw, label) try: resolved = raw.resolve(strict=True) except OSError as exc: raise LaunchError(f"{label}不存在: {raw}") from exc if resolved != raw: raise LaunchError(f"{label}必须使用规范绝对路径: {resolved}") if not resolved.is_dir(): raise LaunchError(f"{label}不是目录: {resolved}") return resolved def authoritative_tasks_path(project_root: Path) -> Path: tasks_path = project_root / TASKS_RELATIVE_PATH _assert_no_symlink_components(tasks_path, "任务板路径") metadata = tasks_path.stat() if not stat.S_ISREG(metadata.st_mode): raise LaunchError(f"任务板必须是普通文件: {tasks_path}") if metadata.st_size > MAX_RECORD_SIZE: raise LaunchError(f"任务板超过 {MAX_RECORD_SIZE} 字节上限") return tasks_path def load_authoritative_board(project_root_value: str) -> tuple[Path, dict]: project_root = canonical_directory(project_root_value, "项目根目录") tasks_path = authoritative_tasks_path(project_root) board = load_document(tasks_path) errors = validate_builtin(board) errors.extend(validate_routing_document(board)) if errors: formatted = "\n".join(f" - {error}" for error in dict.fromkeys(errors)) raise LaunchError(f"任务板未通过 worker 路由校验:\n{formatted}") project = board.get("project") repo_path = project.get("repoPath") if isinstance(project, dict) else None if not isinstance(repo_path, str): raise LaunchError("project.repoPath 必须配置为项目根绝对路径") configured_root = canonical_directory(repo_path, "project.repoPath") if configured_root != project_root: raise LaunchError( f"project.repoPath 与 --project-root 不一致: {configured_root}" ) return project_root, board def resolve_executable(name: str) -> Path: supported = {"codex", "cursor-agent", "git", "orca"} if name not in supported: raise LaunchError(f"不支持的可执行文件: {name}") search_paths = trusted_path_entries() if name == "git": search_paths = [ path for path in search_paths if str(path) in {"/usr/local/bin", "/usr/bin", "/bin"} ] for directory in search_paths: candidate = directory / name try: candidate_metadata = os.lstat(candidate) resolved = candidate.resolve(strict=True) metadata = resolved.stat() except OSError: continue if not ( stat.S_ISREG(candidate_metadata.st_mode) or stat.S_ISLNK(candidate_metadata.st_mode) ): continue if not stat.S_ISREG(metadata.st_mode) or not os.access(resolved, os.X_OK): continue if metadata.st_uid not in {0, os.getuid()}: continue if stat.S_IMODE(metadata.st_mode) & 0o022: continue if resolved.name != name: continue return resolved raise LaunchError( f"找不到可信 {name};只搜索固定用户工具目录和系统目录,不读取 PATH" ) def run_process( argv: list[str], *, timeout: int = CONTROL_TIMEOUT_SECONDS, indeterminate_on_timeout: bool = False, ) -> subprocess.CompletedProcess[str]: try: return subprocess.run( argv, shell=False, check=False, capture_output=True, text=True, timeout=timeout, env=control_environment(), ) except subprocess.TimeoutExpired as exc: error_type = IndeterminateLaunch if indeterminate_on_timeout else LaunchError raise error_type(f"命令超时: {argv[0]}") from exc def run_text(argv: list[str], label: str) -> str: completed = run_process(argv) if completed.returncode != 0: detail = (completed.stderr or completed.stdout).strip()[:2000] raise LaunchError(f"{label}失败(exit {completed.returncode}): {detail}") output = completed.stdout.strip() if not output: raise LaunchError(f"{label}没有输出") if len(output.encode("utf-8")) > MAX_CONTROL_OUTPUT: raise LaunchError(f"{label}输出超过安全上限") return output def parse_json_output(output: str, label: str) -> dict: if len(output.encode("utf-8")) > MAX_CONTROL_OUTPUT: raise LaunchError(f"{label} JSON 超过安全上限") def reject_duplicate(pairs: list[tuple[str, object]]) -> dict: result: dict = {} for key, value in pairs: if key in result: raise LaunchError(f"{label} JSON 存在重复键: {key}") result[key] = value return result try: value = json.loads(output, object_pairs_hook=reject_duplicate) except (json.JSONDecodeError, UnicodeDecodeError) as exc: raise LaunchError(f"{label} 返回畸形 JSON") from exc if not isinstance(value, dict): raise LaunchError(f"{label} JSON 顶层必须是对象") if value.get("ok") is False: raise LaunchError(f"{label} 返回 ok=false") return value def run_json(argv: list[str], label: str) -> dict: response = parse_json_output(run_text(argv, label), label) if response.get("ok") is not True: raise LaunchError(f"{label} 未明确返回 ok=true") return response def run_orca_create(argv: list[str]) -> tuple[dict, str]: """Run Orca's mutating create once and obtain a safe terminal identity. Once the mutating call is attempted, any timeout, transport/decode error, interruption, non-zero exit, malformed response, or response without a handle is indeterminate: Orca may already have created a terminal, so callers must not retry automatically. """ label = "orca terminal create" try: completed = run_process(argv, indeterminate_on_timeout=True) if completed.returncode != 0: detail = (completed.stderr or completed.stdout).strip()[:2000] raise IndeterminateLaunch( f"{label} 返回 exit {completed.returncode},可能已创建终端: {detail}" ) output = completed.stdout.strip() if not output: raise IndeterminateLaunch(f"{label} 无响应,可能已创建终端") response = parse_json_output(output, label) if response.get("ok") is not True: raise IndeterminateLaunch( f"{label} 未明确返回 ok=true,可能已创建终端" ) handle = terminal_handle_from_create(response) if not handle: raise IndeterminateLaunch(f"{label} 响应缺少 handle,可能已创建终端") return response, handle except IndeterminateLaunch: raise except BaseException as exc: detail = str(exc).strip() or type(exc).__name__ raise IndeterminateLaunch( f"{label} 调用或响应处理异常,可能已创建终端: " f"{type(exc).__name__}: {detail[:2000]}" ) from exc def terminal_metadata(response: dict, expected_handle: str) -> dict | None: """Read only Orca's documented result.terminal/result handle shapes.""" result = response.get("result") if not isinstance(result, dict): return None terminal = result.get("terminal") candidates = [ candidate for candidate in (terminal, result) if isinstance(candidate, dict) and candidate.get("handle") == expected_handle ] if len(candidates) != 1: return None return candidates[0] def terminal_handle_from_create(response: dict) -> str | None: result = response.get("result") if not isinstance(result, dict): return None terminal = result.get("terminal") values = [ candidate.get("handle") for candidate in (terminal, result) if isinstance(candidate, dict) and isinstance(candidate.get("handle"), str) and candidate.get("handle") ] unique = set(values) if len(values) != 1 or len(unique) != 1: return None try: return safe_identity_text(values[0], "Orca terminal handle") except LaunchError: return None def git_output(git: Path, directory: Path, *args: str) -> str: return run_text( [str(git), "-C", str(directory), *args], f"git {' '.join(args)}", ).splitlines()[0] def git_common_directory(git: Path, worktree: Path) -> Path: raw = git_output(git, worktree, "rev-parse", "--git-common-dir") candidate = Path(raw) if not candidate.is_absolute(): candidate = worktree / candidate try: return candidate.resolve(strict=True) except OSError as exc: raise LaunchError(f"无法解析 Git common-dir: {candidate}") from exc def registered_git_worktrees(git: Path, project_root: Path) -> set[Path]: output = run_text( [ str(git), "-C", str(project_root), "worktree", "list", "--porcelain", "-z", ], "git worktree list", ) paths: set[Path] = set() for record in output.split("\0\0"): if not record: continue fields = record.split("\0") if not fields or not fields[0].startswith("worktree "): raise LaunchError("git worktree list 返回畸形 porcelain 记录") raw_path = fields[0][len("worktree ") :] path = Path(raw_path) if ( not path.is_absolute() or _path_has_parent_reference(raw_path) or os.path.normpath(raw_path) != raw_path ): raise LaunchError("git worktree list 返回非规范绝对路径") if path in paths: raise LaunchError(f"git worktree list 返回重复路径: {path}") paths.add(path) if not paths: raise LaunchError("git worktree list 未返回任何注册 worktree") return paths def assert_git_control_entry(worktree: Path) -> None: control_path = worktree / ".git" try: metadata = os.lstat(control_path) except OSError as exc: raise LaunchError(f"worktree 缺少 .git 控制入口: {worktree}") from exc if stat.S_ISLNK(metadata.st_mode): raise LaunchError(f"worktree .git 不能是 symlink: {control_path}") if not (stat.S_ISDIR(metadata.st_mode) or stat.S_ISREG(metadata.st_mode)): raise LaunchError(f"worktree .git 必须是目录或普通 gitfile: {control_path}") def capture_worktree_identity( project_root: Path, worktree_value: str, allowed_worktrees: object, ) -> dict: if not isinstance(allowed_worktrees, list): raise LaunchError("project.orchestration.allowedWorktrees 必须是列表") worktree = canonical_directory(worktree_value, "worker worktree") configured_paths: list[Path] = [] for index, configured in enumerate(allowed_worktrees): if not isinstance(configured, str): raise LaunchError(f"allowedWorktrees[{index}] 必须是字符串") configured_paths.append( canonical_directory(configured, f"allowedWorktrees[{index}]") ) if worktree not in configured_paths: raise LaunchError(f"worker worktree 不在 allowedWorktrees 中: {worktree}") git = resolve_executable("git") assert_git_control_entry(project_root) assert_git_control_entry(worktree) top_level = canonical_directory( git_output(git, worktree, "rev-parse", "--show-toplevel"), "Git worktree top-level", ) if top_level != worktree: raise LaunchError("worker worktree 必须是 Git worktree 根目录,不能是子目录") project_top = canonical_directory( git_output(git, project_root, "rev-parse", "--show-toplevel"), "项目 Git top-level", ) if project_top != project_root: raise LaunchError("--project-root 必须是 Git worktree 根目录") registered = registered_git_worktrees(git, project_root) if project_root not in registered: raise LaunchError("项目根目录不在 git worktree 注册表中") if worktree not in registered: raise LaunchError("worker worktree 未出现在 git worktree list 中") common = git_common_directory(git, worktree) project_common = git_common_directory(git, project_root) common_stat = common.stat() project_common_stat = project_common.stat() if ( common_stat.st_dev, common_stat.st_ino, ) != ( project_common_stat.st_dev, project_common_stat.st_ino, ): raise LaunchError("worker worktree 不属于项目的 Git common-dir") worktree_stat = worktree.stat() return { "path": str(worktree), "device": worktree_stat.st_dev, "inode": worktree_stat.st_ino, "gitCommonDir": str(common), "gitCommonDevice": common_stat.st_dev, "gitCommonInode": common_stat.st_ino, } def assert_identity_current(identity: dict, label: str) -> None: path = canonical_directory(str(identity.get("path", "")), label) metadata = path.stat() if ( metadata.st_dev, metadata.st_ino, ) != ( identity.get("device"), identity.get("inode"), ): raise LaunchError(f"{label} inode 已变化: {path}") common = canonical_directory( str(identity.get("gitCommonDir", "")), f"{label} Git common-dir", ) common_metadata = common.stat() if ( common_metadata.st_dev, common_metadata.st_ino, ) != ( identity.get("gitCommonDevice"), identity.get("gitCommonInode"), ): raise LaunchError(f"{label} Git common-dir identity 已变化") def find_task(board: dict, task_id: str) -> dict: tasks = board.get("tasks") if not isinstance(tasks, list): raise LaunchError("tasks 必须是列表") matches = [ task for task in tasks if isinstance(task, dict) and task.get("id") == task_id ] if len(matches) != 1: raise LaunchError(f"任务必须唯一存在: {task_id}") return matches[0] def build_plan( *, project_root_value: str, task_id: str, attempt_id: str, role: str, profile_id: str, worktree_value: str, slot: int, ) -> dict: if not TASK_ID_RE.fullmatch(task_id): 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 必须精确为 -A1..A3") if role not in {"developer", "test", "operator"}: raise LaunchError("role 必须是 developer、test 或 operator") 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 执行") project = board["project"] orchestration = project.get("orchestration") if not isinstance(orchestration, dict): raise LaunchError("旧任务板缺少 project.orchestration,只能使用手动模式") if orchestration.get("mode") != "orca": raise LaunchError("project.orchestration.mode 不是 orca,拒绝自动创建 worker") profiles = orchestration.get("profiles") profile = profiles.get(profile_id) if isinstance(profiles, dict) else None if not isinstance(profile, dict): raise LaunchError(f"找不到结构化 profile: {profile_id}") if profile.get("role") != role: raise LaunchError( f"profile {profile_id} 的角色是 {profile.get('role')!r},不是 {role}" ) worktree = capture_worktree_identity( project_root, worktree_value, orchestration.get("allowedWorktrees"), ) executable = resolve_executable(str(profile["cli"])) executable_stat = executable.stat() cli_version = run_text([str(executable), "--version"], "读取 Agent CLI 版本") if len(cli_version) > 256 or any(ord(char) < 32 for char in cli_version): raise LaunchError("Agent CLI 版本输出包含控制字符或过长") argv = render_worker_argv(profile, str(executable), worktree["path"]) requested = { "cli": profile["cli"], "tier": profile["tier"], "model": profile["model"], "reasoningEffort": profile["reasoningEffort"], "permissionMode": profile["permissionMode"], "executable": str(executable), "executableDevice": executable_stat.st_dev, "executableInode": executable_stat.st_ino, "cliVersion": cli_version, "argv": argv, "argvHash": canonical_sha256(argv), "environmentPolicy": environment_policy_for_role(role), } current_profile_hash = profile_hash( profile, profile_version=orchestration["profileVersion"], ) created_for = { "taskId": task_id, "attemptId": attempt_id, "role": role, } launch_fingerprint = canonical_sha256( { "protocolVersion": PROTOCOL_VERSION, "backend": "orca", "profileId": profile_id, "profileHash": current_profile_hash, "createdFor": created_for, "worktree": worktree, "requested": requested, "slot": slot, } ) cli_label = "CODEX" if profile["cli"] == "codex" else "CURSOR" role_label = { "developer": "DEV", "test": "TEST", "operator": "OP", }[role] digest_short = launch_fingerprint.split(":", 1)[-1][:10] title = ( f"ACK-{role_label}-{cli_label}-{str(profile['tier']).upper()}-" f"{digest_short}-{slot}" ) return { "protocolVersion": PROTOCOL_VERSION, "backend": "orca", "projectRoot": str(project_root), "taskId": task_id, "attemptId": attempt_id, "role": role, "profileId": profile_id, "profileHash": current_profile_hash, "launchFingerprint": launch_fingerprint, "worktree": worktree, "requested": requested, "slot": slot, "title": title, } def record_directory() -> Path: root = Path("/tmp") / f"ack-worker-launch-{os.getuid()}" try: os.mkdir(root, 0o700) except FileExistsError: pass metadata = os.lstat(root) if not stat.S_ISDIR(metadata.st_mode) or stat.S_ISLNK(metadata.st_mode): raise LaunchError(f"启动记录目录不是普通目录: {root}") if metadata.st_uid != os.getuid() or stat.S_IMODE(metadata.st_mode) != 0o700: raise LaunchError(f"启动记录目录必须由当前用户拥有且权限为 0700: {root}") return root def record_path(launch_id: str) -> Path: if not LAUNCH_ID_RE.fullmatch(launch_id): raise LaunchError("launch-id 必须是 64 位小写十六进制") return record_directory() / f"{launch_id}.json" def _read_record_file(path: Path) -> dict: file_descriptor = os.open(path, os.O_RDONLY | os.O_NOFOLLOW) try: metadata = os.fstat(file_descriptor) _assert_private_file(metadata, "启动记录") if metadata.st_size > MAX_RECORD_SIZE: raise LaunchError("启动记录超过安全上限") chunks: list[bytes] = [] remaining = MAX_RECORD_SIZE + 1 while remaining: chunk = os.read(file_descriptor, min(65536, remaining)) if not chunk: break chunks.append(chunk) remaining -= len(chunk) content_bytes = b"".join(chunks) if len(content_bytes) > MAX_RECORD_SIZE: raise LaunchError("启动记录超过安全上限") try: content = content_bytes.decode("utf-8") except UnicodeDecodeError as exc: raise LaunchError("启动记录不是 UTF-8") from exc finally: os.close(file_descriptor) value = parse_json_output(content, "启动记录") if value.get("launchId") != path.stem: raise LaunchError("启动记录 launchId 与文件名不一致") return value def _assert_private_file(metadata: os.stat_result, label: str) -> None: if not stat.S_ISREG(metadata.st_mode): raise LaunchError(f"{label}必须是普通文件") if metadata.st_uid != os.getuid(): raise LaunchError(f"{label}必须由当前用户拥有") if stat.S_IMODE(metadata.st_mode) != 0o600: raise LaunchError(f"{label}权限必须精确为 0600") if metadata.st_nlink != 1: raise LaunchError(f"{label}不能有额外 hard link") def _write_record_file(path: Path, value: dict, *, exclusive: bool) -> None: payload = ( json.dumps( value, sort_keys=True, separators=(",", ":"), ensure_ascii=False, allow_nan=False, ) + "\n" ).encode("utf-8") if len(payload) > MAX_RECORD_SIZE: raise LaunchError("启动记录超过安全上限") if exclusive: flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW file_descriptor = os.open(path, flags, 0o600) with os.fdopen(file_descriptor, "wb") as output: output.write(payload) output.flush() os.fsync(output.fileno()) else: temporary = path.with_name(f".{path.name}.{secrets.token_hex(8)}.tmp") flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW file_descriptor = os.open(temporary, flags, 0o600) try: with os.fdopen(file_descriptor, "wb") as output: output.write(payload) output.flush() os.fsync(output.fileno()) os.replace(temporary, path) finally: try: os.unlink(temporary) except FileNotFoundError: pass directory_fd = os.open(path.parent, os.O_RDONLY | os.O_DIRECTORY) try: os.fsync(directory_fd) finally: os.close(directory_fd) def create_record(value: dict) -> Path: path = record_path(str(value.get("launchId", ""))) _write_record_file(path, value, exclusive=True) return path @contextmanager def locked_record(launch_id: str) -> Iterator[dict]: path = record_path(launch_id) lock_path = path.with_suffix(".lock") lock_fd = os.open( lock_path, os.O_RDWR | os.O_CREAT | os.O_NOFOLLOW, 0o600, ) try: _assert_private_file(os.fstat(lock_fd), "启动记录锁") fcntl.flock(lock_fd, fcntl.LOCK_EX) value = _read_record_file(path) yield value _write_record_file(path, value, exclusive=False) finally: fcntl.flock(lock_fd, fcntl.LOCK_UN) os.close(lock_fd) def read_record(launch_id: str) -> dict: with locked_record(launch_id) as value: return json.loads(json.dumps(value)) def update_record( launch_id: str, *, preserve_cleanup_state: bool = False, **changes: object, ) -> dict: with locked_record(launch_id) as value: if preserve_cleanup_state and isinstance(value.get("cleanup"), dict): return json.loads(json.dumps(value)) value.update(changes) return json.loads(json.dumps(value)) def try_update_record(launch_id: str, **changes: object) -> str | None: """Attempt an exception-path record update without changing control flow.""" try: update_record(launch_id, **changes) except BaseException as exc: detail = str(exc).strip() or type(exc).__name__ return f"{type(exc).__name__}: {detail[:2000]}" return None def build_bootstrap_command(launch_id: str) -> str: if not LAUNCH_ID_RE.fullmatch(launch_id): raise LaunchError("launch-id 格式非法") python = Path(sys.executable).resolve(strict=True) script = Path(__file__).resolve(strict=True) argv = [ str(python), "-I", str(script), "_bootstrap", "--launch-id", launch_id, ] return "exec " + shlex.join(argv) def bootstrap_authorization_hash( launch_id: str, launch_fingerprint: str, nonce: str, ) -> str: if not LAUNCH_ID_RE.fullmatch(launch_id): raise LaunchError("launch-id 格式非法") if not SHA256_RE.fullmatch(launch_fingerprint): raise LaunchError("launch fingerprint 格式非法") if not LAUNCH_ID_RE.fullmatch(nonce): raise LaunchError("bootstrap nonce 格式非法") return canonical_sha256( { "protocolVersion": PROTOCOL_VERSION, "launchId": launch_id, "launchFingerprint": launch_fingerprint, "nonce": nonce, } ) def bootstrap_ready_proof( launch_id: str, launch_fingerprint: str, nonce: str, ) -> str: bootstrap_authorization_hash(launch_id, launch_fingerprint, nonce) message = ( f"ack-bootstrap-ready-v{PROTOCOL_VERSION}:" f"{launch_id}:{launch_fingerprint}" ).encode("utf-8") digest = hmac.new(bytes.fromhex(nonce), message, hashlib.sha256).hexdigest() return f"sha256:{digest}" def runtime_id_from_response(response: dict) -> str: metadata = response.get("_meta") runtime_id = metadata.get("runtimeId") if isinstance(metadata, dict) else None return safe_identity_text(runtime_id, "Orca runtimeId") def run_orca_close( orca: Path, handle: str, expected_runtime_id: str, ) -> dict[str, str]: """Durably close the created tab and require a bound JSON confirmation.""" label = "orca terminal close --tab" try: completed = run_process( [ str(orca), "terminal", "close", "--terminal", handle, "--tab", "--json", ], timeout=10, indeterminate_on_timeout=True, ) except (LaunchError, OSError) as exc: raise IndeterminateLaunch( f"{label} 未获得确认,reconcile required: {exc}" ) from exc if completed.returncode != 0: detail = (completed.stderr or completed.stdout).strip()[:2000] raise IndeterminateLaunch( f"{label} 返回 exit {completed.returncode},reconcile required: {detail}" ) output = completed.stdout.strip() if not output: raise IndeterminateLaunch(f"{label} 无响应,reconcile required") try: response = parse_json_output(output, label) if response.get("ok") is not True: raise LaunchError(f"{label} 未明确返回 ok=true") runtime_id = runtime_id_from_response(response) if runtime_id != expected_runtime_id: raise LaunchError( f"{label} runtimeId 不匹配: {runtime_id} != {expected_runtime_id}" ) result = response.get("result") close = result.get("close") if isinstance(result, dict) else None if not isinstance(close, dict): raise LaunchError(f"{label} 缺少 result.close") closed_handle = safe_identity_text(close.get("handle"), "close handle") tab_id = safe_identity_text(close.get("tabId"), "close tabId") if closed_handle != handle: raise LaunchError( f"{label} handle 不匹配: {closed_handle} != {handle}" ) if close.get("closeMode") != "tab": raise LaunchError(f"{label} 未确认整 tab 持久关闭") except (LaunchError, OSError, ValueError, KeyError) as exc: raise IndeterminateLaunch( f"{label} 回执无法确认,reconcile required: {exc}" ) from exc return { "runtimeId": runtime_id, "handle": closed_handle, "tabId": tab_id, "closeMode": "tab", } def wait_for_bootstrap(launch_id: str, expected_proof: str) -> dict: deadline = time.monotonic() + BOOTSTRAP_READY_TIMEOUT_SECONDS while time.monotonic() < deadline: value = read_record(launch_id) state = value.get("state") if state in {"bootstrap-ready", "ready"}: if not hmac.compare_digest( str(value.get("bootstrapProof", "")), expected_proof, ): raise LaunchError("worker bootstrap ready proof 不匹配") return value if state in {"failed", "closed", "indeterminate"}: raise LaunchError( f"worker bootstrap 未就绪: state={state}, error={value.get('error')}" ) time.sleep(0.1) raise LaunchError("worker bootstrap ready handshake 超时") def validate_terminal_binding(plan: dict, metadata: dict) -> dict[str, str]: handle = safe_identity_text(metadata.get("handle"), "terminal show handle") incarnation_id = safe_identity_text( metadata.get("incarnationId"), "terminal show incarnationId", ) connected = metadata.get("connected") writable = metadata.get("writable") if connected is not True or writable is not True: raise LaunchError("新 worker terminal 必须 connected=true 且 writable=true") observed_worktree = metadata.get("worktreePath") if not isinstance(observed_worktree, str) or not observed_worktree: raise LaunchError("terminal show 缺少可核对的 worktreePath") observed_path = canonical_directory( observed_worktree, "Orca observed worktreePath", ) if str(observed_path) != plan["worktree"]["path"]: raise LaunchError( "Orca observed worktreePath 与请求不一致: " f"{observed_path} != {plan['worktree']['path']}" ) return { "handle": handle, "incarnationId": incarnation_id, "observedWorktreePath": str(observed_path), } def build_receipt( launch_id: str, plan: dict, runtime_id: str, metadata: dict, created_at: str, ) -> dict: observed = validate_terminal_binding(plan, metadata) receipt = { "receiptVersion": RECEIPT_VERSION, "id": f"WR-{launch_id}", "launchId": launch_id, "profileId": plan["profileId"], "profileHash": plan["profileHash"], "launchFingerprint": plan["launchFingerprint"], "slot": plan["slot"], "createdFor": { "taskId": plan["taskId"], "attemptId": plan["attemptId"], "role": plan["role"], }, "worktree": plan["worktree"], "requested": plan["requested"], "binding": { "orchestrator": "orca", "runtimeId": runtime_id, "handle": observed["handle"], "incarnationId": observed["incarnationId"], "observedWorktreePath": observed["observedWorktreePath"], "connected": True, "writable": True, "boundAt": format_timestamp(utc_now()), }, "createdAt": created_at, } receipt["receiptHash"] = canonical_sha256(receipt) return receipt def launch_with_orca(plan: dict) -> dict: launch_id = secrets.token_hex(32) authorization_nonce = secrets.token_hex(32) created_at_dt = utc_now() created_at = format_timestamp(created_at_dt) record = { "recordVersion": 1, "launchId": launch_id, "state": "prepared", "createdAt": created_at, "expiresAt": format_timestamp( created_at_dt + timedelta(seconds=LAUNCH_TTL_SECONDS) ), "plan": plan, "runtime": None, "receipt": None, "authorizationHash": bootstrap_authorization_hash( launch_id, plan["launchFingerprint"], authorization_nonce, ), "bootstrapProof": None, "error": None, } record_path_value = create_record(record) orca: Path | None = None handle: str | None = None runtime_id: str | None = None try: orca = resolve_executable("orca") status_response = run_json([str(orca), "status", "--json"], "orca status") runtime_id = runtime_id_from_response(status_response) bootstrap_command = build_bootstrap_command(launch_id) create_argv = [ str(orca), "terminal", "create", "--worktree", f"path:{plan['worktree']['path']}", "--command", bootstrap_command, "--title", plan["title"], "--json", ] assert_identity_current(plan["worktree"], "worker worktree") create_response, handle = run_orca_create(create_argv) create_runtime_id = runtime_id_from_response(create_response) if create_runtime_id != runtime_id: raise LaunchError("Orca runtimeId 在 terminal create 期间变化") initial_show = run_json( [ str(orca), "terminal", "show", "--terminal", handle, "--json", ], "orca terminal show (pre-authorization)", ) if runtime_id_from_response(initial_show) != runtime_id: raise LaunchError("Orca runtimeId 在 terminal create 期间变化") initial_metadata = terminal_metadata(initial_show, handle) if initial_metadata is None: raise LaunchError("terminal show 无法绑定刚创建的 handle") initial_binding = validate_terminal_binding(plan, initial_metadata) update_record( launch_id, runtime={ "runtimeId": runtime_id, "handle": handle, "incarnationId": initial_binding["incarnationId"], }, ) send_response = run_json( [ str(orca), "terminal", "send", "--terminal", handle, "--text", authorization_nonce, "--enter", "--json", ], "orca terminal send bootstrap authorization", ) if runtime_id_from_response(send_response) != runtime_id: raise LaunchError("Orca runtimeId 在 bootstrap 授权期间变化") expected_proof = bootstrap_ready_proof( launch_id, plan["launchFingerprint"], authorization_nonce, ) wait_for_bootstrap(launch_id, expected_proof) show_response = run_json( [ str(orca), "terminal", "show", "--terminal", handle, "--json", ], "orca terminal show", ) if runtime_id_from_response(show_response) != runtime_id: raise LaunchError("Orca runtimeId 在 terminal show 期间变化") metadata = terminal_metadata(show_response, handle) if metadata is None: raise LaunchError("terminal show 无法绑定刚创建的 handle") final_binding = validate_terminal_binding(plan, metadata) if final_binding["incarnationId"] != initial_binding["incarnationId"]: raise LaunchError("Orca terminal incarnation 在 bootstrap 期间变化") assert_identity_current(plan["worktree"], "worker worktree") receipt = build_receipt( launch_id, plan, runtime_id, metadata, created_at, ) update_record( launch_id, state="ready", runtime={ "runtimeId": runtime_id, "handle": handle, "incarnationId": receipt["binding"]["incarnationId"], }, receipt=receipt, error=None, ) return receipt except BaseException as exc: original_error = str(exc) or type(exc).__name__ if isinstance(exc, IndeterminateLaunch) and not handle: detail = ( f"launchId={launch_id}; record={record_path_value}; " f"{original_error}; reconcile required" ) record_error = try_update_record( launch_id, state="indeterminate", error=detail, ) if record_error is not None: detail += f"; record update failed: {record_error}" raise IndeterminateLaunch(detail) from exc if not handle: record_error = try_update_record( launch_id, state="failed", error=original_error, ) if record_error is not None: detail = ( f"launchId={launch_id}; record={record_path_value}; " f"pre-handle failure: {original_error}; " f"record update failed: {record_error}" ) raise LaunchError(detail) from exc raise pending_detail = ( f"launchId={launch_id}; record={record_path_value}; " f"post-handle failure: {original_error}; cleanup pending; " "reconcile required" ) pending_record_error = try_update_record( launch_id, state="indeterminate", error=pending_detail, cleanup={ "method": "terminal.closeTab", "runtimeId": runtime_id, "handle": handle, "confirmed": False, "reconcileRequired": True, }, ) try: if orca is None or runtime_id is None: raise IndeterminateLaunch( "缺少 Orca runtime identity,无法确认关闭" ) close_confirmation = run_orca_close(orca, handle, runtime_id) except BaseException as close_exc: close_error = str(close_exc) or type(close_exc).__name__ detail = ( f"launchId={launch_id}; record={record_path_value}; " f"post-handle failure: {original_error}; " f"close confirmation failed: {close_error}; reconcile required" ) if pending_record_error is not None: detail += ( "; pending record update failed: " f"{pending_record_error}" ) reconcile_record_error = try_update_record( launch_id, state="indeterminate", error=detail, cleanup={ "method": "terminal.closeTab", "runtimeId": runtime_id, "handle": handle, "confirmed": False, "reconcileRequired": True, "error": close_error, }, ) if reconcile_record_error is not None: detail += ( "; reconcile record update failed: " f"{reconcile_record_error}" ) raise IndeterminateLaunch(detail) from close_exc final_record_error = try_update_record( launch_id, state="failed", error=original_error, cleanup={ "method": "terminal.closeTab", **close_confirmation, "confirmed": True, "reconcileRequired": False, }, ) if final_record_error is not None: detail = ( f"launchId={launch_id}; record={record_path_value}; " f"post-handle failure: {original_error}; close confirmed; " "failed state persistence could not be confirmed: " f"{final_record_error}; reconcile required" ) if pending_record_error is not None: detail += ( "; pending record update failed: " f"{pending_record_error}" ) raise IndeterminateLaunch(detail) from exc raise def bootstrap_worker(launch_id: str) -> int: try: with locked_record(launch_id) as record: if record.get("state") != "prepared": raise LaunchError( f"启动记录不能重复消费: state={record.get('state')}" ) expires_at = parse_timestamp(record.get("expiresAt"), "expiresAt") if utc_now() >= expires_at: raise LaunchError("启动记录已过期") record["state"] = "bootstrapping" plan_snapshot = record.get("plan") if not isinstance(plan_snapshot, dict): raise LaunchError("启动记录缺少 plan") authorization_hash = record.get("authorizationHash") if not isinstance(authorization_hash, str) or not SHA256_RE.fullmatch( authorization_hash ): raise LaunchError("启动记录缺少 bootstrap authorization hash") rebuilt = build_plan( project_root_value=str(plan_snapshot.get("projectRoot", "")), task_id=str(plan_snapshot.get("taskId", "")), attempt_id=str(plan_snapshot.get("attemptId", "")), role=str(plan_snapshot.get("role", "")), profile_id=str(plan_snapshot.get("profileId", "")), worktree_value=str( (plan_snapshot.get("worktree") or {}).get("path", "") ), slot=plan_snapshot.get("slot", 0), ) if rebuilt != plan_snapshot: raise LaunchError("bootstrap 重读后的 launch plan 与已审阅快照不一致") if Path.cwd().resolve(strict=True) != Path(rebuilt["worktree"]["path"]): raise LaunchError("bootstrap cwd 与已验证 worktree 不一致") assert_identity_current(rebuilt["worktree"], "bootstrap worktree") executable = Path(rebuilt["requested"]["executable"]) executable_metadata = executable.stat() if ( executable_metadata.st_dev, executable_metadata.st_ino, ) != ( rebuilt["requested"]["executableDevice"], rebuilt["requested"]["executableInode"], ): raise LaunchError("Agent CLI executable identity 已变化") awaiting_record = update_record( launch_id, preserve_cleanup_state=True, state="awaiting-authorization", error=None, ) if ( awaiting_record.get("state") != "awaiting-authorization" or isinstance(awaiting_record.get("cleanup"), dict) ): raise LaunchError("bootstrap 已被父进程取消,拒绝等待授权") readable, _, _ = select.select( [sys.stdin], [], [], BOOTSTRAP_READY_TIMEOUT_SECONDS, ) if not readable: raise LaunchError("bootstrap authorization 输入超时") nonce_line = sys.stdin.readline(130) nonce = nonce_line.rstrip("\r\n") if not LAUNCH_ID_RE.fullmatch(nonce) or nonce_line not in { nonce + "\n", nonce + "\r\n", }: raise LaunchError("bootstrap authorization nonce 格式非法") expected_authorization = bootstrap_authorization_hash( launch_id, rebuilt["launchFingerprint"], nonce, ) if not hmac.compare_digest(authorization_hash, expected_authorization): raise LaunchError("bootstrap authorization hash 不匹配") ready_proof = bootstrap_ready_proof( launch_id, rebuilt["launchFingerprint"], nonce, ) with locked_record(launch_id) as current_record: if ( current_record.get("state") != "awaiting-authorization" or isinstance(current_record.get("cleanup"), dict) ): raise LaunchError("bootstrap 已被父进程取消,拒绝启动 Agent") if not hmac.compare_digest( str(current_record.get("authorizationHash", "")), authorization_hash, ): raise LaunchError("bootstrap authorization record 已漂移") process = subprocess.Popen( rebuilt["requested"]["argv"], shell=False, cwd=rebuilt["worktree"]["path"], env=worker_environment( str(rebuilt["requested"]["cli"]), str(rebuilt["role"]), ), ) current_record.update( state="bootstrap-ready", childPid=process.pid, bootstrapProof=ready_proof, error=None, ) return_code = process.wait() update_record( launch_id, preserve_cleanup_state=True, state="closed" if return_code == 0 else "failed", childExitCode=return_code, error=None if return_code == 0 else f"Agent CLI exit {return_code}", ) return return_code except BaseException as exc: try: update_record( launch_id, preserve_cleanup_state=True, state="failed", error=str(exc), ) except BaseException: pass sys.stderr.write(f"ACK worker bootstrap 失败: {exc}\n") return 1 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("--profile-id", required=True) parser.add_argument("--worktree", required=True) parser.add_argument("--slot", type=int, default=1) def build_parser() -> argparse.ArgumentParser: parser = argparse.ArgumentParser( description="按 ACK 结构化 profile 规划或启动 worker", allow_abbrev=False, ) subparsers = parser.add_subparsers(dest="action", required=True) profile_parser = subparsers.add_parser( "profile-hash", help="输出一个 profile 的规范化 SHA-256", allow_abbrev=False, ) profile_parser.add_argument("--project-root", required=True) profile_parser.add_argument("--profile-id", required=True) plan_parser = subparsers.add_parser( "plan", help="只校验并输出启动计划,不创建终端", allow_abbrev=False, ) add_launch_arguments(plan_parser) launch_parser = subparsers.add_parser( "launch", help="通过 Orca 固定 bootstrap 创建 worker", allow_abbrev=False, ) add_launch_arguments(launch_parser) launch_parser.add_argument( "--expected-launch-fingerprint", required=True, help="必须与刚审阅的 plan.launchFingerprint 精确一致", ) bootstrap_parser = subparsers.add_parser( "_bootstrap", help=argparse.SUPPRESS, allow_abbrev=False, ) bootstrap_parser.add_argument("--launch-id", required=True) return parser def profile_hash_command(project_root_value: str, profile_id: str) -> dict: if not PROFILE_ID_RE.fullmatch(profile_id): raise LaunchError("profile-id 格式非法") _, board = load_authoritative_board(project_root_value) orchestration = board["project"].get("orchestration") profiles = orchestration.get("profiles") if isinstance(orchestration, dict) else None profile = profiles.get(profile_id) if isinstance(profiles, dict) else None if not isinstance(profile, dict): raise LaunchError(f"找不到 profile: {profile_id}") return { "profileVersion": orchestration["profileVersion"], "profileId": profile_id, "profileHash": profile_hash( profile, profile_version=orchestration["profileVersion"], ), "profile": profile, } def main(argv: list[str] | None = None) -> int: arguments = list(sys.argv[1:] if argv is None else argv) try: reject_duplicate_or_separator_args(arguments) except LaunchError as exc: sys.stderr.write(f"{exc}\n") return 2 parser = build_parser() try: args = parser.parse_args(arguments) except SystemExit as exc: return int(exc.code) if args.action == "_bootstrap": if not LAUNCH_ID_RE.fullmatch(args.launch_id): sys.stderr.write("launch-id 必须是 64 位小写十六进制\n") return 2 return bootstrap_worker(args.launch_id) try: if args.action == "profile-hash": output = profile_hash_command(args.project_root, args.profile_id) else: plan = build_plan( project_root_value=args.project_root, task_id=args.task_id, attempt_id=args.attempt_id, role=args.role, profile_id=args.profile_id, worktree_value=args.worktree, slot=args.slot, ) if args.action == "plan": output = {"mode": "plan", "plan": plan} else: if not SHA256_RE.fullmatch(args.expected_launch_fingerprint): raise LaunchError( "expected-launch-fingerprint 必须是规范 sha256 值" ) if not hmac.compare_digest( args.expected_launch_fingerprint, plan["launchFingerprint"], ): raise LaunchError( "当前 launch plan 与已审阅 fingerprint 不一致;" "请重新执行 plan 并审阅" ) output = { "mode": "launched", "receipt": launch_with_orca(plan), } except IndeterminateLaunch as exc: sys.stderr.write( "worker 创建结果不确定;不要直接重试,请先按外部 launch record " f"reconcile: {exc}\n" ) return 1 except (LaunchError, OSError, ValueError, KeyError) as exc: sys.stderr.write(f"worker 启动拒绝: {exc}\n") return 1 sys.stdout.write( json.dumps( output, sort_keys=True, ensure_ascii=False, separators=(",", ":"), allow_nan=False, ) + "\n" ) return 0 if __name__ == "__main__": raise SystemExit(main())