feat(ack): add grok workers and allow --always-approve

Grok is a first-class worker CLI. Launcher argv includes --always-approve so
unattended tool calls are not blocked; sandbox stays required.
This commit is contained in:
2026-08-23 19:08:54 +08:00
parent c113f68bf4
commit 7dfdf80e9e
28 changed files with 679 additions and 78 deletions
+50 -2
View File
@@ -39,8 +39,10 @@ if str(SCRIPT_DIR) not in sys.path:
from validate_tasks import load_document, validate_builtin # noqa: E402
from worker_profiles import ( # noqa: E402
GROK_EXECUTABLE_NAME_RE,
LAUNCH_PROTOCOL_VERSION,
canonical_sha256,
executable_basename_matches_cli,
profile_hash,
render_worker_argv,
validate_routing_document,
@@ -81,6 +83,12 @@ WORKER_ENVIRONMENT_NAMES = CONTROL_ENVIRONMENT_NAMES | {
WORKER_CREDENTIAL_NAMES = {
"codex": frozenset({"AZURE_OPENAI_API_KEY", "OPENAI_API_KEY"}),
"cursor-agent": frozenset({"CURSOR_API_KEY"}),
"grok": frozenset({"XAI_API_KEY"}),
}
CLI_TITLE_LABELS = {
"codex": "CODEX",
"cursor-agent": "CURSOR",
"grok": "GROK",
}
INHERITED_ENVIRONMENT_PREFIXES = (
"LC_",
@@ -263,8 +271,41 @@ def load_authoritative_board(project_root_value: str) -> tuple[Path, dict]:
return project_root, board
def _is_under_real_grok_home(resolved: Path) -> bool:
"""Return True when ``resolved`` is under a non-symlink ``$HOME/.grok``."""
home, _ = account_identity()
grok_root = home / ".grok"
try:
root_metadata = os.lstat(grok_root)
if stat.S_ISLNK(root_metadata.st_mode) or not stat.S_ISDIR(root_metadata.st_mode):
return False
grok_root.resolve(strict=True)
resolved.relative_to(grok_root.resolve(strict=True))
except (OSError, ValueError):
return False
return True
def _is_trusted_grok_executable(resolved: Path, metadata: os.stat_result) -> bool:
"""Accept Grok's vendor artifact names under ``~/.grok``, or a 0755 ``grok``."""
if GROK_EXECUTABLE_NAME_RE.fullmatch(resolved.name) is None:
return False
if not executable_basename_matches_cli(str(resolved), "grok"):
return False
mode = stat.S_IMODE(metadata.st_mode)
if mode & 0o002:
return False
if resolved.name == "grok" and not (mode & 0o020):
return True
if not _is_under_real_grok_home(resolved):
return False
return metadata.st_uid == os.getuid() and metadata.st_gid == os.getgid()
def resolve_executable(name: str) -> Path:
supported = {"codex", "cursor-agent", "git", "orca"}
supported = {"codex", "cursor-agent", "grok", "git", "orca"}
if name not in supported:
raise LaunchError(f"不支持的可执行文件: {name}")
search_paths = trusted_path_entries()
@@ -289,6 +330,10 @@ def resolve_executable(name: str) -> Path:
continue
if metadata.st_uid not in {0, os.getuid()}:
continue
if name == "grok":
if _is_trusted_grok_executable(resolved, metadata):
return resolved
continue
if stat.S_IMODE(metadata.st_mode) & 0o022:
continue
if resolved.name != name:
@@ -697,7 +742,10 @@ def build_plan(
"slot": slot,
}
)
cli_label = "CODEX" if profile["cli"] == "codex" else "CURSOR"
try:
cli_label = CLI_TITLE_LABELS[str(profile["cli"])]
except KeyError as exc:
raise LaunchError(f"不支持的 worker CLI: {profile['cli']}") from exc
role_label = "DEV" if role == "developer" else "TEST"
digest_short = launch_fingerprint.split(":", 1)[-1][:10]
title = (
+39
View File
@@ -43,6 +43,7 @@ TOP_LEVEL_FIELDS = {
"project",
"enabled",
"defaultProfile",
"intents",
"entrypoints",
"artifacts",
"destinations",
@@ -99,6 +100,11 @@ CHANNELS = {"preview", "staging", "stable"}
ENVIRONMENT_TYPES = {"ssh-host", "docker-compose", "kubernetes", "custom"}
CLASSIFICATIONS = {"development", "staging", "production"}
STOP_POINTS = {"verified", "validation_ready", "review_ready", "released"}
INTENT_FIELDS = {"testEnvironment", "release"}
INTENT_STOP_AT = {
"testEnvironment": "validation_ready",
"release": "released",
}
ACTIONS = {
"verify",
"pull-request",
@@ -675,6 +681,38 @@ def _validate_profiles(
errors.append(f"{where}: defaultProfile 不能部署 production 环境")
def _validate_intents(
values: Any,
profiles: dict[str, Any],
errors: list[str],
) -> None:
if values is None:
return
if not _mapping(values):
errors.append("intents: 必须是对象")
return
_reject_unknown(values, INTENT_FIELDS, "intents", errors)
for field in sorted(INTENT_FIELDS):
if field not in values:
errors.append(f"intents.{field}: 必填")
continue
profile_id = values[field]
if profile_id is None:
continue
if not isinstance(profile_id, str) or ID_RE.fullmatch(profile_id) is None:
errors.append(f"intents.{field}: 必须是 null 或小写连字符 profile ID")
continue
profile = profiles.get(profile_id)
if profile is None:
errors.append(f"intents.{field}: 未定义 profile {profile_id!r}")
continue
expected_stop = INTENT_STOP_AT[field]
if _mapping(profile) and profile.get("stopAt") != expected_stop:
errors.append(
f"intents.{field}: profile {profile_id!r} 必须 stopAt {expected_stop}"
)
def validate_builtin(data: dict[str, Any], project_root: Path | None = None) -> list[str]:
errors: list[str] = []
_reject_unknown(data, TOP_LEVEL_FIELDS, "<root>", errors)
@@ -720,6 +758,7 @@ def validate_builtin(data: dict[str, Any], project_root: Path | None = None) ->
environments=environments,
errors=errors,
)
_validate_intents(data.get("intents"), profiles, errors)
if enabled:
if default_profile not in profiles:
+18 -4
View File
@@ -103,6 +103,8 @@ DELIVERY_RUN_FIELDS = {
"evidence",
"updatedAt",
}
DELIVERY_RUN_OPTIONAL_FIELDS = {"intent"}
DELIVERY_RUN_INTENTS = {"testEnvironment", "release"}
DELIVERY_STATUSES = {
"planned",
"running",
@@ -481,7 +483,9 @@ def validate_delivery_runs(
if not isinstance(run, dict):
errors.append(f"{where}: 必须是对象")
continue
reject_unknown_fields(run, DELIVERY_RUN_FIELDS, where, errors)
reject_unknown_fields(
run, DELIVERY_RUN_FIELDS | DELIVERY_RUN_OPTIONAL_FIELDS, where, errors
)
missing = sorted(DELIVERY_RUN_FIELDS - set(run))
for field in missing:
errors.append(f"{where}.{field}: 必填")
@@ -501,13 +505,23 @@ def validate_delivery_runs(
if status not in DELIVERY_STATUSES:
errors.append(f"{where}.status: 必须是 {sorted(DELIVERY_STATUSES)}")
intent = run.get("intent")
if "intent" in run and intent not in DELIVERY_RUN_INTENTS:
errors.append(
f"{where}.intent: 必须是 {sorted(DELIVERY_RUN_INTENTS)}"
)
task_ids = run.get("taskIds")
allow_empty_tasks = intent in DELIVERY_RUN_INTENTS
if (
not isinstance(task_ids, list)
or not task_ids
or any(not _nonempty_string(task_id) for task_id in task_ids)
or (not task_ids and not allow_empty_tasks)
or any(not _nonempty_string(task_id) for task_id in (task_ids or []))
):
errors.append(f"{where}.taskIds: 必须是非空任务 ID 列表")
errors.append(
f"{where}.taskIds: 必须是任务 ID 列表"
if allow_empty_tasks
else f"{where}.taskIds: 必须是非空任务 ID 列表"
)
task_ids = []
elif len(task_ids) != len(set(task_ids)):
errors.append(f"{where}.taskIds: 不能包含重复值")
+73 -19
View File
@@ -24,12 +24,27 @@ LAUNCH_PROTOCOL_VERSION = 1
MAX_ROUNDS = 3
ROLES = frozenset({"developer", "test"})
CLIS = frozenset({"codex", "cursor-agent"})
CLIS = frozenset({"codex", "cursor-agent", "grok"})
TIERS = frozenset({"standard", "strong"})
REASONING_EFFORTS = frozenset({"low", "medium", "high", "xhigh"})
PERMISSION_MODES = frozenset({"read-only", "workspace-write"})
ORCHESTRATION_MODES = frozenset({"orca", "manual"})
DEFAULT_KEYS = frozenset({"developer", "test", "developerUpgraded"})
CLI_REQUIRES_REASONING_EFFORT = frozenset({"codex", "grok"})
CLI_REQUIRES_NULL_REASONING_EFFORT = frozenset({"cursor-agent"})
def _cli_choice_text() -> str:
return "/".join(sorted(CLIS))
def executable_basename_matches_cli(executable: str, cli: str) -> bool:
"""Return whether a resolved executable basename is valid for ``cli``."""
name = Path(executable).name
if name == cli:
return True
return cli == "grok" and GROK_EXECUTABLE_NAME_RE.fullmatch(name) is not None
ORCHESTRATION_FIELDS = frozenset(
{
@@ -114,6 +129,9 @@ ROLE_DISPATCH_FIELDS = frozenset(
PROFILE_ID_RE = re.compile(r"^[a-z][a-z0-9-]{1,63}$")
MODEL_ID_RE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._:/+@-]{0,127}$")
GROK_EXECUTABLE_NAME_RE = re.compile(
r"^grok(?:-(?:linux|darwin|windows)-(?:x86_64|aarch64|arm64))?$"
)
RECEIPT_ID_RE = re.compile(r"^WR-[0-9a-f]{64}$")
LAUNCH_ID_RE = re.compile(r"^[0-9a-f]{64}$")
TASK_ID_RE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$")
@@ -214,7 +232,7 @@ def validate_profile(profile: Any, *, where: str = "profile") -> list[str]:
if not isinstance(role, str) or role not in ROLES:
errors.append(f"{where}.role: must be developer/test")
if not isinstance(cli, str) or cli not in CLIS:
errors.append(f"{where}.cli: must be codex/cursor-agent")
errors.append(f"{where}.cli: must be {_cli_choice_text()}")
if not isinstance(tier, str) or tier not in TIERS:
errors.append(f"{where}.tier: must be standard/strong")
if not isinstance(model, str) or MODEL_ID_RE.fullmatch(model) is None:
@@ -223,12 +241,17 @@ def validate_profile(profile: Any, *, where: str = "profile") -> list[str]:
errors.append(
f"{where}.permissionMode: must be read-only/workspace-write"
)
if cli == "codex":
if isinstance(cli, str) and cli in CLI_REQUIRES_REASONING_EFFORT:
if not isinstance(effort, str) or effort not in REASONING_EFFORTS:
label = "Codex" if cli == "codex" else "Grok"
errors.append(
f"{where}.reasoningEffort: Codex requires low/medium/high/xhigh"
f"{where}.reasoningEffort: {label} requires low/medium/high/xhigh"
)
elif cli == "cursor-agent" and effort is not None:
elif (
isinstance(cli, str)
and cli in CLI_REQUIRES_NULL_REASONING_EFFORT
and effort is not None
):
errors.append(f"{where}.reasoningEffort: Cursor requires null")
if role == "test" and tier != "standard":
@@ -446,14 +469,15 @@ def render_worker_argv(
raise ValueError("invalid profile: " + "; ".join(errors))
if not _is_absolute_safe_path(executable):
raise ValueError("executable must be a safe absolute path other than root")
if Path(executable).name != profile["cli"]:
if not executable_basename_matches_cli(executable, profile["cli"]):
raise ValueError("executable basename must match profile.cli")
if not _is_absolute_safe_path(worktree):
raise ValueError("worktree must be a safe absolute path other than root")
model = profile["model"]
permission = profile["permissionMode"]
if profile["cli"] == "codex":
cli = profile["cli"]
if cli == "codex":
return [
executable,
"--strict-config",
@@ -469,13 +493,33 @@ def render_worker_argv(
worktree,
]
argv = [executable, "--model", model]
if permission == "read-only":
argv.extend(["--mode", "plan"])
else:
argv.append("--auto-review")
argv.extend(["--sandbox", "enabled", "--workspace", worktree])
return argv
if cli == "cursor-agent":
argv = [executable, "--model", model]
if permission == "read-only":
argv.extend(["--mode", "plan"])
else:
argv.append("--auto-review")
argv.extend(["--sandbox", "enabled", "--workspace", worktree])
return argv
if cli != "grok":
raise ValueError(f"unsupported cli: {cli}")
grok_permission = "plan" if permission == "read-only" else "acceptEdits"
grok_sandbox = "read-only" if permission == "read-only" else "workspace"
return [
executable,
"--model",
model,
"--reasoning-effort",
profile["reasoningEffort"],
"--permission-mode",
grok_permission,
"--always-approve",
"--sandbox",
grok_sandbox,
"--cwd",
worktree,
]
def receipt_hash(receipt: dict[str, Any]) -> str:
@@ -532,25 +576,34 @@ def _validate_requested(value: Any, where: str) -> list[str]:
tier = value.get("tier")
permission = value.get("permissionMode")
if not isinstance(cli, str) or cli not in CLIS:
errors.append(f"{where}.cli: must be codex/cursor-agent")
errors.append(f"{where}.cli: must be {_cli_choice_text()}")
if not isinstance(tier, str) or tier not in TIERS:
errors.append(f"{where}.tier: must be standard/strong")
model = value.get("model")
if not isinstance(model, str) or MODEL_ID_RE.fullmatch(model) is None:
errors.append(f"{where}.model: must be a safe model ID")
effort = value.get("reasoningEffort")
if cli == "codex" and (
if isinstance(cli, str) and cli in CLI_REQUIRES_REASONING_EFFORT and (
not isinstance(effort, str) or effort not in REASONING_EFFORTS
):
errors.append(f"{where}.reasoningEffort: invalid Codex effort")
if cli == "cursor-agent" and effort is not None:
label = "Codex" if cli == "codex" else "Grok"
errors.append(f"{where}.reasoningEffort: invalid {label} effort")
if (
isinstance(cli, str)
and cli in CLI_REQUIRES_NULL_REASONING_EFFORT
and effort is not None
):
errors.append(f"{where}.reasoningEffort: Cursor requires null")
if not isinstance(permission, str) or permission not in PERMISSION_MODES:
errors.append(f"{where}.permissionMode: must be read-only/workspace-write")
executable = value.get("executable")
if not _is_absolute_safe_path(executable):
errors.append(f"{where}.executable: must be a safe absolute path")
elif isinstance(cli, str) and cli in CLIS and Path(executable).name != cli:
elif (
isinstance(cli, str)
and cli in CLIS
and not executable_basename_matches_cli(str(executable), cli)
):
errors.append(f"{where}.executable: basename must match cli")
if not _is_nonnegative_int(value.get("executableDevice")):
errors.append(f"{where}.executableDevice: must be a non-negative integer")
@@ -995,6 +1048,7 @@ __all__ = [
"profile_hash",
"receipt_hash",
"render_worker_argv",
"executable_basename_matches_cli",
"validate_profile",
"validate_orchestration",
"validate_worker_receipt",