feat(ack): enforce worker launch policy
This commit is contained in:
+12
-4
@@ -107,15 +107,23 @@ ln -s <此框架绝对路径> <project>/docs/ack/kit
|
|||||||
```text
|
```text
|
||||||
我要做一个新需求:<一句话需求>。你作为 ack 的 Coordinator(PM),按 docs/ack/kit/core 规范:
|
我要做一个新需求:<一句话需求>。你作为 ack 的 Coordinator(PM),按 docs/ack/kit/core 规范:
|
||||||
先读 project.md 与 core/*;写产品文档到 docs/ 并把需求拆成带可观测验收信号的任务写进 docs/ack/tasks.yaml;
|
先读 project.md 与 core/*;写产品文档到 docs/ 并把需求拆成带可观测验收信号的任务写进 docs/ack/tasks.yaml;
|
||||||
先给我确认产品文档+任务拆分,再按闭环起 DEV/TEST worker(cursor-agent --model auto)循环派发/复测/终检;
|
先给我确认产品文档+任务拆分,再按 project.md 校验并启动 DEV/TEST worker,核对实际模型后循环派发/复测/终检;
|
||||||
每个任务最多三轮,三轮不过记 leftover。
|
每个任务最多三轮,三轮不过记 leftover。
|
||||||
```
|
```
|
||||||
|
|
||||||
### 起 worker(模型固定为 auto)
|
### 校验并启动 worker
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
orca terminal create --worktree active --command "cursor-agent --model auto" --title "DEV" --json
|
DEV_CMD='codex --dangerously-bypass-approvals-and-sandbox -m gpt-5.6-terra -c model_reasoning_effort=medium'
|
||||||
orca terminal create --worktree active --command "cursor-agent --model auto" --title "TEST" --json
|
TEST_CMD='codex --dangerously-bypass-approvals-and-sandbox -m gpt-5.6-luna -c model_reasoning_effort=low'
|
||||||
|
python3 docs/ack/validate_worker_command.py --role developer --command "$DEV_CMD"
|
||||||
|
python3 docs/ack/validate_worker_command.py --role test --command "$TEST_CMD"
|
||||||
|
orca terminal create --worktree active --command "$DEV_CMD" --title "DEV" --json
|
||||||
|
orca terminal create --worktree active --command "$TEST_CMD" --title "TEST" --json
|
||||||
|
|
||||||
|
# Cursor worker 使用同一项目校验器
|
||||||
|
CURSOR_CMD='cursor-agent --yolo --model auto'
|
||||||
|
python3 docs/ack/validate_worker_command.py --role developer --command "$CURSOR_CMD"
|
||||||
```
|
```
|
||||||
|
|
||||||
需要隔离/并行时先建 worktree:`orca worktree create --name <feature> --base-branch <base> --json`(选择依据见 `core/closed-loop.md`)。
|
需要隔离/并行时先建 worktree:`orca worktree create --name <feature> --base-branch <base> --json`(选择依据见 `core/closed-loop.md`)。
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
Coordinator 发现或读取 open 任务
|
Coordinator 发现或读取 open 任务
|
||||||
-> prepare:写/补全 tasks.yaml 验收信号
|
-> prepare:写/补全 tasks.yaml 验收信号
|
||||||
-> 决定 worktree:当前 worktree 起子 agent,还是新建隔离 worktree(见下节「子任务放哪」)
|
-> 决定 worktree:当前 worktree 起子 agent,还是新建隔离 worktree(见下节「子任务放哪」)
|
||||||
-> 起 worker:按档位建 worker 终端(如 cursor-agent --model auto,见 model-routing.md)
|
-> 起 worker:先按项目覆盖层校验命令,再按档位和执行模式建 worker 终端(见 model-routing.md)
|
||||||
-> dispatch 给 Developer(--to <worker handle>)
|
-> dispatch 给 Developer(--to <worker handle>)
|
||||||
-> wait:Developer 的 worker_done / escalation
|
-> wait:Developer 的 worker_done / escalation
|
||||||
-> writeback fixed_by_dev
|
-> writeback fixed_by_dev
|
||||||
@@ -54,7 +54,7 @@ Coordinator 派发前先决定 Developer/Test 在哪工作。两种方式:
|
|||||||
**方式 1:当前 worktree 起子 agent(终端)**
|
**方式 1:当前 worktree 起子 agent(终端)**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
orca terminal create --worktree active --command "cursor-agent --model auto" --json
|
orca terminal create --worktree active --command "cursor-agent --yolo --model auto" --json
|
||||||
```
|
```
|
||||||
|
|
||||||
- 适合:串行闭环、一次一个 Developer 任务、小改动、Test 要复测的正是 Developer 改的那棵树。
|
- 适合:串行闭环、一次一个 Developer 任务、小改动、Test 要复测的正是 Developer 改的那棵树。
|
||||||
@@ -65,7 +65,7 @@ orca terminal create --worktree active --command "cursor-agent --model auto" --j
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
orca worktree create --name <feature> --base-branch <base> --json
|
orca worktree create --name <feature> --base-branch <base> --json
|
||||||
# 然后在新 worktree 内 orca terminal create --worktree path:<new> --command "cursor-agent --model auto"
|
# 然后在新 worktree 内 orca terminal create --worktree path:<new> --command "cursor-agent --yolo --model auto"
|
||||||
```
|
```
|
||||||
|
|
||||||
- 适合:并行多个互不依赖的子任务、大/高风险/实验性改动、要保持基线分支干净(如 prod 不动、feature 走独立分支)、要独立 build 或跑独立服务实例、best-of-N 尝试。
|
- 适合:并行多个互不依赖的子任务、大/高风险/实验性改动、要保持基线分支干净(如 prod 不动、feature 走独立分支)、要独立 build 或跑独立服务实例、best-of-N 尝试。
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
## 前提:谁是 Coordinator
|
## 前提:谁是 Coordinator
|
||||||
|
|
||||||
**你(发起编排的强模型会话)就是 Coordinator (PM) / 产品。** 你负责写文档、拆任务、编排、终检,**不亲自写代码、不亲自跑测试**。开发和测试是另起的 worker agent(`cursor-agent --model auto`)。
|
**你(发起编排的强模型会话)就是 Coordinator (PM) / 产品。** 你负责写文档、拆任务、编排、终检,**不亲自写代码、不亲自跑测试**。开发和测试是另起的 worker agent;具体 CLI、模型、reasoning effort 和执行模式必须先读项目覆盖层 `docs/ack/project.md`,禁止照抄未核对的默认命令。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
2. 写产品文档到 docs/(PRD / 交互 / 验收),把需求拆成任务,每个任务的验收写成可观测信号(可见文本 / API 结果 / 交互结果)。
|
2. 写产品文档到 docs/(PRD / 交互 / 验收),把需求拆成任务,每个任务的验收写成可观测信号(可见文本 / API 结果 / 交互结果)。
|
||||||
3. 把任务写进 docs/ack/tasks.yaml(只有你写),跑 validate 校验结构。
|
3. 把任务写进 docs/ack/tasks.yaml(只有你写),跑 validate 校验结构。
|
||||||
4. 先把「产品文档 + 任务拆分 + 验收信号」给我确认,不要急着派发。
|
4. 先把「产品文档 + 任务拆分 + 验收信号」给我确认,不要急着派发。
|
||||||
5. 我确认后,按 ack 闭环循环:为任务起 Developer/Test worker(cursor-agent --model auto),
|
5. 我确认后,按 ack 闭环循环:先按 docs/ack/project.md 校验 Developer/Test worker 启动命令,
|
||||||
dispatch 开发 → worker_done → dispatch 测试独立复测 → 你读证据终检 → 回写 tasks.yaml;
|
dispatch 开发 → worker_done → dispatch 测试独立复测 → 你读证据终检 → 回写 tasks.yaml;
|
||||||
每个任务最多三轮,三轮不过记 leftover 并升级我复盘。
|
每个任务最多三轮,三轮不过记 leftover 并升级我复盘。
|
||||||
```
|
```
|
||||||
@@ -50,14 +50,26 @@ python3 docs/ack/kit/scripts/validate_tasks.py docs/ack/tasks.yaml
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 第 3 步:起 worker(模型固定 auto)
|
## 第 3 步:校验并启动 worker
|
||||||
|
|
||||||
|
先读 `docs/ack/project.md` 的项目覆盖规则。如果项目提供 `validate_worker_command.py`,校验未通过时不得创建终端。
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
orca terminal create --worktree active --command "cursor-agent --model auto" --title "DEV" --json
|
# Codex 示例(模型与执行模式以项目覆盖层为准)
|
||||||
orca terminal create --worktree active --command "cursor-agent --model auto" --title "TEST" --json
|
DEV_CMD='codex --dangerously-bypass-approvals-and-sandbox -m gpt-5.6-terra -c model_reasoning_effort=medium'
|
||||||
|
TEST_CMD='codex --dangerously-bypass-approvals-and-sandbox -m gpt-5.6-luna -c model_reasoning_effort=low'
|
||||||
|
python3 docs/ack/validate_worker_command.py --role developer --command "$DEV_CMD"
|
||||||
|
python3 docs/ack/validate_worker_command.py --role test --command "$TEST_CMD"
|
||||||
|
orca terminal create --worktree active --command "$DEV_CMD" --title "DEV" --json
|
||||||
|
orca terminal create --worktree active --command "$TEST_CMD" --title "TEST" --json
|
||||||
|
|
||||||
|
# Cursor 示例
|
||||||
|
CURSOR_CMD='cursor-agent --yolo --model auto'
|
||||||
|
python3 docs/ack/validate_worker_command.py --role developer --command "$CURSOR_CMD"
|
||||||
|
orca terminal create --worktree active --command "$CURSOR_CMD" --title "DEV" --json
|
||||||
```
|
```
|
||||||
|
|
||||||
新 worktree 时先 `orca worktree create --name <feature> --base-branch <base>`,再在其中起终端。选型与升级见 `model-routing.md`。
|
新 worktree 时先 `orca worktree create --name <feature> --base-branch <base>`,再在其中起终端。选型与升级见 `model-routing.md`。终端启动后、dispatch 前必须读取启动信息,确认实际 CLI、模型和 reasoning effort。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -82,4 +94,4 @@ task-create → dispatch 给 DEV → 等 worker_done
|
|||||||
|
|
||||||
## 一句话
|
## 一句话
|
||||||
|
|
||||||
产品文档 + 验收信号写在前(你,强模型)→ DEV/TEST 用 `--model auto` 起 worker → dispatch / 复测 / 终检循环 → 结论只落 `tasks.yaml`。
|
产品文档 + 验收信号写在前(你,强模型)→ 按项目覆盖层校验并启动 DEV/TEST → 核对实际模型 → dispatch / 复测 / 终检循环 → 结论只落 `tasks.yaml`。
|
||||||
|
|||||||
@@ -69,7 +69,9 @@
|
|||||||
| Codex (`codex`) | `codex -m <model> -c model_reasoning_effort=<effort>` |
|
| Codex (`codex`) | `codex -m <model> -c model_reasoning_effort=<effort>` |
|
||||||
| 其它(opencode 等) | 用各自 CLI 的模型参数或配置 |
|
| 其它(opencode 等) | 用各自 CLI 的模型参数或配置 |
|
||||||
|
|
||||||
**本 kit 对 Cursor 的默认建议**:Test 与 Developer worker 用 `cursor-agent --model auto`(自动选型,天然偏向高效模型,符合"中低档位"意图);需要更强时改成具体强模型(如 `--model claude-opus-4-8-thinking-high`)。Coordinator 作为强模型脑,通常就是发起编排的那个会话本身。
|
执行模式也必须在创建 worker 时固定,并服从项目覆盖层或用户的明确要求。Cursor 的 YOLO 参数是 `--yolo`;Codex 的等价参数是 `--dangerously-bypass-approvals-and-sandbox`。不要把 Cursor 的 `--yolo` 原样传给 Codex,也不要把裸启动 `codex` 当作“自动选择了正确角色模型”。如果项目提供 worker 命令校验脚本,校验通过是 `terminal create` 的前置条件。
|
||||||
|
|
||||||
|
**本 kit 对 Cursor 的默认建议**:Test 与 Developer worker 用 `cursor-agent --yolo --model auto`(自动选型,天然偏向高效模型,符合"中低档位"意图,并按当前项目授权启用 YOLO);需要更强时改成具体强模型并保留 `--yolo`。Coordinator 作为强模型脑,通常就是发起编排的那个会话本身。
|
||||||
|
|
||||||
### Codex 默认映射
|
### Codex 默认映射
|
||||||
|
|
||||||
@@ -82,6 +84,28 @@
|
|||||||
|
|
||||||
Codex worker 应明确指定模型和 reasoning effort,不把“未指定模型”当作 Cursor `auto` 的等价物。Codex 未指定模型时使用产品推荐模型,但推荐值可能随版本更新,也不保证符合 Test / Developer 的成本档位。具体模型若失效或被弃用,应保持上面的角色档位不变,只更新本映射;项目也可在 overlay 中覆盖映射。
|
Codex worker 应明确指定模型和 reasoning effort,不把“未指定模型”当作 Cursor `auto` 的等价物。Codex 未指定模型时使用产品推荐模型,但推荐值可能随版本更新,也不保证符合 Test / Developer 的成本档位。具体模型若失效或被弃用,应保持上面的角色档位不变,只更新本映射;项目也可在 overlay 中覆盖映射。
|
||||||
|
|
||||||
|
### Worker 固定启动命令
|
||||||
|
|
||||||
|
以下是 core 的默认完整命令。Developer/Test worker 禁止裸启动;必须同时固定 Agent CLI、角色模型和执行模式。
|
||||||
|
|
||||||
|
| Agent CLI | 角色 | 完整启动命令 |
|
||||||
|
|-----------|------|--------------|
|
||||||
|
| Codex | Developer | `codex --dangerously-bypass-approvals-and-sandbox -m gpt-5.6-terra -c model_reasoning_effort=medium` |
|
||||||
|
| Codex | Test | `codex --dangerously-bypass-approvals-and-sandbox -m gpt-5.6-luna -c model_reasoning_effort=low` |
|
||||||
|
| Codex | Developer 升级 | `codex --dangerously-bypass-approvals-and-sandbox -m gpt-5.6-sol -c model_reasoning_effort=high` |
|
||||||
|
| Cursor | Developer / Test | `cursor-agent --yolo --model auto` |
|
||||||
|
|
||||||
|
硬规则:
|
||||||
|
|
||||||
|
1. Codex worker 必须带 `--dangerously-bypass-approvals-and-sandbox`;Cursor worker 必须带 `--yolo`。
|
||||||
|
2. 禁止用裸 `codex`、裸 `cursor-agent` 或只指定 CLI 而不指定角色模型。
|
||||||
|
3. 创建终端前先运行项目提供的 worker 命令校验器;校验失败时不得执行 `orca terminal create`。
|
||||||
|
4. 创建终端后、dispatch 前读取启动信息,确认实际 CLI、模型和 reasoning effort 与命令一致。
|
||||||
|
5. Developer 升级到强模型必须由 Coordinator 记录原因;Test 不得复用 Developer 的强模型终端。
|
||||||
|
6. YOLO 会跳过确认和沙箱,只能在用户已明确授权、外层运行环境受控时启用;项目覆盖层可以收紧执行模式,不能静默放宽。
|
||||||
|
|
||||||
|
项目可以覆盖模型名称或收紧权限,但必须在 `project.md` 中写出完整替代命令,不能只写“auto”“默认模型”或依赖当前 CLI 的隐式默认值。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 成本原则
|
## 成本原则
|
||||||
|
|||||||
@@ -34,27 +34,27 @@ orca orchestration inbox --limit 20 --json
|
|||||||
默认沿用 Coordinator 当前所在的 Agent CLI:Cursor Coordinator 创建 Cursor worker,Codex Coordinator 创建 Codex worker。不要通过询问模型来猜运行环境;以当前 CLI / 终端环境为准。除非项目 overlay 或用户明确指定,否则不跨 Agent CLI 创建 worker。
|
默认沿用 Coordinator 当前所在的 Agent CLI:Cursor Coordinator 创建 Cursor worker,Codex Coordinator 创建 Codex worker。不要通过询问模型来猜运行环境;以当前 CLI / 终端环境为准。除非项目 overlay 或用户明确指定,否则不跨 Agent CLI 创建 worker。
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Cursor:Test / Developer worker 用 auto 模型(自动选型)
|
# Cursor:Test / Developer worker 用 auto 模型,并按项目要求启用 YOLO
|
||||||
orca terminal create --worktree path:<dev_worktree> \
|
orca terminal create --worktree path:<dev_worktree> \
|
||||||
--command "cursor-agent --model auto" --title "DEV" --json
|
--command "cursor-agent --yolo --model auto" --title "DEV" --json
|
||||||
|
|
||||||
# 需要更强模型时改成具体模型
|
# 需要更强模型时改成具体模型
|
||||||
orca terminal create --worktree path:<dev_worktree> \
|
orca terminal create --worktree path:<dev_worktree> \
|
||||||
--command "cursor-agent --model claude-opus-4-8-thinking-high" --title "DEV" --json
|
--command "cursor-agent --yolo --model claude-opus-4-8-thinking-high" --title "DEV" --json
|
||||||
|
|
||||||
# Codex:Developer worker
|
# Codex:Developer worker
|
||||||
orca terminal create --worktree path:<dev_worktree> \
|
orca terminal create --worktree path:<dev_worktree> \
|
||||||
--command "codex -m gpt-5.6-terra -c model_reasoning_effort=medium" \
|
--command "codex --dangerously-bypass-approvals-and-sandbox -m gpt-5.6-terra -c model_reasoning_effort=medium" \
|
||||||
--title "DEV" --json
|
--title "DEV" --json
|
||||||
|
|
||||||
# Codex:Test worker
|
# Codex:Test worker
|
||||||
orca terminal create --worktree path:<test_worktree> \
|
orca terminal create --worktree path:<test_worktree> \
|
||||||
--command "codex -m gpt-5.6-luna -c model_reasoning_effort=low" \
|
--command "codex --dangerously-bypass-approvals-and-sandbox -m gpt-5.6-luna -c model_reasoning_effort=low" \
|
||||||
--title "TEST" --json
|
--title "TEST" --json
|
||||||
|
|
||||||
# Codex:复杂 Developer 任务升级
|
# Codex:复杂 Developer 任务升级
|
||||||
orca terminal create --worktree path:<dev_worktree> \
|
orca terminal create --worktree path:<dev_worktree> \
|
||||||
--command "codex -m gpt-5.6-sol -c model_reasoning_effort=high" \
|
--command "codex --dangerously-bypass-approvals-and-sandbox -m gpt-5.6-sol -c model_reasoning_effort=high" \
|
||||||
--title "DEV-STRONG" --json
|
--title "DEV-STRONG" --json
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -64,11 +64,12 @@ orca terminal create --worktree path:<dev_worktree> \
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
orca worktree create --name <feature> --base-branch <base> --json
|
orca worktree create --name <feature> --base-branch <base> --json
|
||||||
orca terminal create --worktree path:<new_worktree> --command "cursor-agent --model auto" --json
|
orca terminal create --worktree path:<new_worktree> --command "cursor-agent --yolo --model auto" --json
|
||||||
```
|
```
|
||||||
|
|
||||||
- `cursor-agent --list-models` 可列出合法模型;`auto` 表示由 Cursor 自动选型。
|
- `cursor-agent --list-models` 可列出合法模型;`auto` 表示由 Cursor 自动选型。
|
||||||
- Codex 用 `-m / --model` 指定模型,用 `-c model_reasoning_effort=<effort>` 固定推理档位;不要把省略 `-m` 当作 Cursor `auto` 的等价物。
|
- Codex 用 `-m / --model` 指定模型,用 `-c model_reasoning_effort=<effort>` 固定推理档位;不要把省略 `-m` 当作 Cursor `auto` 的等价物。
|
||||||
|
- 本项目要求 Cursor worker 带 `--yolo`,Codex worker 带 `--dangerously-bypass-approvals-and-sandbox`;创建前先运行项目覆盖层指定的校验器。
|
||||||
- 其它 CLI(opencode 等)用各自的模型参数或配置,`--command` 相应替换。
|
- 其它 CLI(opencode 等)用各自的模型参数或配置,`--command` 相应替换。
|
||||||
- 若 worker 是已在跑的会话(用 `--inject` 投递),模型已由该会话启动时决定,无法在 dispatch 时改;要换模型需新建终端。
|
- 若 worker 是已在跑的会话(用 `--inject` 投递),模型已由该会话启动时决定,无法在 dispatch 时改;要换模型需新建终端。
|
||||||
|
|
||||||
|
|||||||
Executable
+172
@@ -0,0 +1,172 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""校验 Music Pilot 的 Developer/Test worker 启动命令。
|
||||||
|
|
||||||
|
用法:
|
||||||
|
python3 validate_worker_command.py --role developer --command '<command>'
|
||||||
|
python3 validate_worker_command.py --role test --command '<command>'
|
||||||
|
python3 validate_worker_command.py --role developer --upgraded --command '<command>'
|
||||||
|
python3 validate_worker_command.py --self-test
|
||||||
|
|
||||||
|
退出码:0 通过 / 1 规则不通过 / 2 用法或命令解析错误。
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import shlex
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
CODEX_YOLO = "--dangerously-bypass-approvals-and-sandbox"
|
||||||
|
CURSOR_YOLO = "--yolo"
|
||||||
|
|
||||||
|
|
||||||
|
def option_value(tokens: list[str], *names: str) -> str | None:
|
||||||
|
for index, token in enumerate(tokens):
|
||||||
|
for name in names:
|
||||||
|
if token == name and index + 1 < len(tokens):
|
||||||
|
return tokens[index + 1]
|
||||||
|
prefix = f"{name}="
|
||||||
|
if token.startswith(prefix):
|
||||||
|
return token[len(prefix) :]
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def codex_effort(tokens: list[str]) -> str | None:
|
||||||
|
configs: list[str] = []
|
||||||
|
for index, token in enumerate(tokens):
|
||||||
|
if token in {"-c", "--config"} and index + 1 < len(tokens):
|
||||||
|
configs.append(tokens[index + 1])
|
||||||
|
elif token.startswith("--config="):
|
||||||
|
configs.append(token.split("=", 1)[1])
|
||||||
|
for config in configs:
|
||||||
|
if config.startswith("model_reasoning_effort="):
|
||||||
|
return config.split("=", 1)[1].strip('"\'')
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def validate(role: str, command: str, upgraded: bool = False) -> list[str]:
|
||||||
|
try:
|
||||||
|
tokens = shlex.split(command)
|
||||||
|
except ValueError as exc:
|
||||||
|
return [f"命令无法解析:{exc}"]
|
||||||
|
if not tokens:
|
||||||
|
return ["启动命令不能为空"]
|
||||||
|
|
||||||
|
executable = Path(tokens[0]).name
|
||||||
|
errors: list[str] = []
|
||||||
|
|
||||||
|
if upgraded and role != "developer":
|
||||||
|
errors.append("只有 Developer 可以使用 --upgraded")
|
||||||
|
|
||||||
|
if executable == "codex":
|
||||||
|
if CODEX_YOLO not in tokens:
|
||||||
|
errors.append(f"Codex worker 必须包含 {CODEX_YOLO}")
|
||||||
|
|
||||||
|
model = option_value(tokens, "-m", "--model")
|
||||||
|
effort = codex_effort(tokens)
|
||||||
|
if upgraded:
|
||||||
|
expected_model = "gpt-5.6-sol"
|
||||||
|
allowed_efforts = {"high", "xhigh"}
|
||||||
|
elif role == "developer":
|
||||||
|
expected_model = "gpt-5.6-terra"
|
||||||
|
allowed_efforts = {"medium"}
|
||||||
|
else:
|
||||||
|
expected_model = "gpt-5.6-luna"
|
||||||
|
allowed_efforts = {"low"}
|
||||||
|
|
||||||
|
if model != expected_model:
|
||||||
|
errors.append(
|
||||||
|
f"Codex {role} 模型应为 {expected_model},实际为 {model or '未指定'}"
|
||||||
|
)
|
||||||
|
if effort not in allowed_efforts:
|
||||||
|
expected = "/".join(sorted(allowed_efforts))
|
||||||
|
errors.append(
|
||||||
|
f"Codex {role} reasoning effort 应为 {expected},实际为 {effort or '未指定'}"
|
||||||
|
)
|
||||||
|
elif executable == "cursor-agent":
|
||||||
|
if upgraded:
|
||||||
|
errors.append("Cursor worker 不使用 Codex --upgraded 映射")
|
||||||
|
if CURSOR_YOLO not in tokens:
|
||||||
|
errors.append(f"Cursor worker 必须显式包含 {CURSOR_YOLO}")
|
||||||
|
model = option_value(tokens, "--model")
|
||||||
|
if model != "auto":
|
||||||
|
errors.append(f"Cursor {role} 模型应为 auto,实际为 {model or '未指定'}")
|
||||||
|
else:
|
||||||
|
errors.append(f"不支持的 worker CLI:{executable};只允许 codex 或 cursor-agent")
|
||||||
|
|
||||||
|
return errors
|
||||||
|
|
||||||
|
|
||||||
|
def run_self_test() -> int:
|
||||||
|
cases = [
|
||||||
|
(
|
||||||
|
"codex developer",
|
||||||
|
"developer",
|
||||||
|
f"codex {CODEX_YOLO} -m gpt-5.6-terra -c model_reasoning_effort=medium",
|
||||||
|
False,
|
||||||
|
True,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"codex test",
|
||||||
|
"test",
|
||||||
|
f"codex {CODEX_YOLO} -m gpt-5.6-luna -c model_reasoning_effort=low",
|
||||||
|
False,
|
||||||
|
True,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"codex upgraded developer",
|
||||||
|
"developer",
|
||||||
|
f"codex {CODEX_YOLO} -m gpt-5.6-sol -c model_reasoning_effort=high",
|
||||||
|
True,
|
||||||
|
True,
|
||||||
|
),
|
||||||
|
("cursor worker", "test", "cursor-agent --yolo --model auto", False, True),
|
||||||
|
("naked codex", "developer", "codex", False, False),
|
||||||
|
(
|
||||||
|
"wrong codex role model",
|
||||||
|
"test",
|
||||||
|
f"codex {CODEX_YOLO} -m gpt-5.6-terra -c model_reasoning_effort=medium",
|
||||||
|
False,
|
||||||
|
False,
|
||||||
|
),
|
||||||
|
("cursor without yolo", "developer", "cursor-agent --model auto", False, False),
|
||||||
|
]
|
||||||
|
failures: list[str] = []
|
||||||
|
for name, role, command, upgraded, expected_pass in cases:
|
||||||
|
passed = not validate(role, command, upgraded)
|
||||||
|
if passed != expected_pass:
|
||||||
|
failures.append(name)
|
||||||
|
if failures:
|
||||||
|
sys.stderr.write("worker 命令校验器自测失败:" + ", ".join(failures) + "\n")
|
||||||
|
return 1
|
||||||
|
print(f"worker 命令校验器自测通过:{len(cases)} 项")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def main(argv: list[str] | None = None) -> int:
|
||||||
|
parser = argparse.ArgumentParser(description="校验 Developer/Test worker 启动命令")
|
||||||
|
parser.add_argument("--role", choices=("developer", "test"))
|
||||||
|
parser.add_argument("--command")
|
||||||
|
parser.add_argument("--upgraded", action="store_true", help="校验升级后的 Codex Developer")
|
||||||
|
parser.add_argument("--self-test", action="store_true")
|
||||||
|
args = parser.parse_args(argv)
|
||||||
|
|
||||||
|
if args.self_test:
|
||||||
|
return run_self_test()
|
||||||
|
if not args.role or not args.command:
|
||||||
|
parser.error("非自测模式必须同时提供 --role 和 --command")
|
||||||
|
|
||||||
|
errors = validate(args.role, args.command, args.upgraded)
|
||||||
|
if errors:
|
||||||
|
sys.stderr.write("worker 启动命令校验失败:\n")
|
||||||
|
for error in errors:
|
||||||
|
sys.stderr.write(f" - {error}\n")
|
||||||
|
return 1
|
||||||
|
print(f"worker 启动命令校验通过:role={args.role}")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
Reference in New Issue
Block a user