feat: add host commander skeleton

This commit is contained in:
Codex
2026-05-21 12:28:13 +00:00
parent 9f166d0580
commit 67f6d0e820
16 changed files with 1187 additions and 277 deletions
+39 -208
View File
@@ -1,42 +1,15 @@
# Host Codex Commander Contract
# Host Codex Commander Skeleton
本文定义第一阶段的 host Codex 指挥官正规化设计。当前阶段只建立 source/contract、CLI dry-run stub、状态模型和安全边界;不部署、不重启、不上线 production,也不实现会实际执行后台动作的守护进程
本文定义 host Codex 指挥官的本地 skeleton 阶段。当前只提供 `/health``/api/commander/contract``.state/commander/` 状态读写、trace summary dry-run 聚合和 approval draft preview;不接 live bridge,不发送 ClaudeQQ,不接管人工指挥官
## 目标边界
## 边界
host Codex 指挥官是独立用户服务/基础设施:在 master server host 上保留一个常驻 Codex 指挥会话,由未来的直管微服务负责保活、prompt 注入、trace 采集和高风险动作请示。它不替代 Code Queue runner,也不让 Code Queue 自己上线自己
- `host-codex-commander` 是独立的本地 skeleton,不是运行中的 live daemon
- 只允许本地文件状态、trace 摘要和审批草案预览。
- 所有输出必须 redaction token/secret/URL credential。
- 不得重启或接管 Code Queue backend,不得 cancel/interrupt 运行任务,不得打印 token 明文。
服务边界固定为三层:
- host Codex 进程:运行在 master server host 的常驻 Codex 指挥会话,只负责监督、派单、审阅和恢复计划。
- 直管控制微服务:运行在 host 侧或能直接接入 host TTY/stdio 的受控位置,负责发现/启动计划、SSH/PTY/stdio bridge、事件持久化、prompt plan、trace summary 和审批状态。
- UniDesk/Code Queue/ClaudeQQCode Queue 继续作为任务执行面,GitHub issue 继续作为长期记录,ClaudeQQ 作为高风险动作请示入口。
第一阶段只允许这些产物:
- `docs/reference/host-codex-commander.md` 长期 contract
- `bun scripts/cli.ts commander contract``commander plan --dry-run` 这类只读/dry-run 输出;
- contract test 证明 CLI 不执行 live operation
- 后续任务拆分。
## 非目标
当前阶段明确不做:
- 不启动、停止或重启任何常驻 commander daemon
- 不打开真实 PTY、stdio 或 SSH bridge
- 不向 host Codex 注入真实 prompt
- 不发送 ClaudeQQ 消息;
- 不部署、不重启、不上线 prod
- 不直接重启 Code Queue backend,不重建 Code Queue backend 容器,不重启 Code Queue 执行面;
- 不 cancel 或 interrupt 运行中的 Code Queue task
- 不读取、打印或持久化 token 明文。
这些动作即使未来实现,也必须先通过本文的审批和安全边界。
## CLI Contract
统一入口:
## CLI
```bash
bun scripts/cli.ts commander contract
@@ -44,188 +17,46 @@ bun scripts/cli.ts commander plan --dry-run [--session-id primary]
bun scripts/cli.ts commander approval request --action <action> --dry-run [--reason text] [--task-id id]
```
所有命令默认输出 JSON,失败也必须有结构化 stdout 和非零退出码。`plan` `approval request` 在第一阶段必须要求 `--dry-run`;没有 `--dry-run` 时必须返回 `ok=false``error=dry-run-required`,不能降级成真实执行
`plan` `approval request` 必须显式使用 `--dry-run`,缺失时返回 `error=dry-run-required`
`commander contract` 必须暴露:
## HTTP
- `phase=source-contract`
- `serviceId=host-codex-commander`
- `daemonImplemented=false`
- `liveOperationsImplemented=false`
- 需要的 host Codex 发现/启动计划、SSH/PTY/stdio bridge、prompt guidance、trace summary、#20/#46 issue 入口、ClaudeQQ 审批入口;
- `safetyBoundary`
| Method | Path | 说明 |
| --- | --- | --- |
| GET | `/health` | 返回 service id、启动时间、state root 和日志文件 |
| GET | `/api/commander/contract` | 返回机器可读 contract |
| GET | `/api/commander/sessions` | 读取本地 session 摘要 |
| POST | `/api/commander/state` | 写入本地 session state |
| GET | `/api/commander/trace-summary` | 对 mock trace JSONL 做 dry-run 摘要 |
| POST | `/api/commander/trace-summary` | 读取 mock trace JSONL 并更新本地 session 状态 |
| POST | `/api/commander/approvals` | 生成 approval draft preview 并落盘 |
`commander plan --dry-run` 必须输出:
## State
- process discovery signal 列表;
- host Codex start command shape,但 `enabled=false`
- SSH/PTY/stdio bridge 设计和 guardrail
- prompt guidance pipeline
- trace summary sources 和 summary shape
- #20/#46 read/write 入口;
- ClaudeQQ high-risk approval command shape
- `mutation=false`
状态根目录固定为 `.state/commander/`,至少包含:
`commander approval request --dry-run` 只生成审批草案。允许的 `--action` 固定为:
- `sessions/<sessionId>.json`
- `events/<sessionId>.jsonl`
- `approvals/<approvalId>.json`
- `logs/commander.jsonl`
- `code-queue-backend-restart`
- `code-queue-backend-rebuild`
- `code-queue-execution-plane-restart`
- `code-queue-task-interrupt`
- `code-queue-task-cancel`
- `prod-runtime-mutation`
session 状态只保留 `unknown``discovered``planned``starting``running``attention_required``stopping``stopped``degraded`
输出中 `claudeqq.mutation=false``sendImplemented=false`。真实发送和审批消费属于后续阶段。
## Trace summary
## Future API Contract
trace summary 输入 mock Code Queue trace JSONL 和可选 task summary,输出:
后续微服务 API 以 REST 为主,所有写入口默认异步、有 request id、有事件序列、有 redaction 结果:
- `taskId`
- `sessionId`
- `lastSeq`
- `status`
- `keyEvents`
- `openQuestions`
- `recommendedNextActions`
- `redactionsApplied`
| Method | Path | 用途 | 第一阶段状态 |
| --- | --- | --- | --- |
| GET | `/health` | 服务健康、版本、日志路径、state root | contract only |
| GET | `/api/commander/contract` | 返回本文对应机器可读 contract | contract only |
| GET | `/api/commander/sessions` | 列出 host Codex session 摘要 | contract only |
| POST | `/api/commander/sessions/:sessionId/plan-start` | 生成发现/启动计划 | contract only |
| POST | `/api/commander/sessions/:sessionId/prompt-plan` | 生成 prompt 注入计划 | contract only |
| GET | `/api/commander/trace-summary` | 读取有界 trace summary | contract only |
| POST | `/api/commander/issues/:issueNumber/write-plan` | 生成 #20/#46 写入计划 | contract only |
| POST | `/api/commander/approvals` | 创建 ClaudeQQ 高风险请示草案 | contract only |
输出只做摘要,不返回 live transcript。
后续实现不得绕过现有 CLI/服务边界。GitHub issue 写入仍使用 `bun scripts/cli.ts gh issue ... --body-file`、dry-run-first 和并发 guardCode Queue 读写仍优先使用 `codex task/tasks/steer/read` 等正式入口。
## Approval draft
## State Model
状态根目录规划为 `.state/commander/`。后续服务至少拆成这些文件或等价表:
- `sessions/<sessionId>.json`host Codex session 摘要、pid/cwd 指纹、bridge 状态、lastSeq、heartbeat
- `events/<sessionId>.jsonl`prompt、trace、approval、bridge lifecycle 事件;
- `approvals/<approvalId>.json`:ClaudeQQ 请示草案、状态、授权绑定动作、过期时间;
- `locks/<name>.lock.d/`:启动、prompt injection、issue write、approval consume 的互斥锁;
- `redactions/<eventId>.json`:脱敏摘要,不保存明文 secret。
session 状态:
| State | 含义 |
| --- | --- |
| `unknown` | 没有足够信号判断 host Codex 是否存在 |
| `discovered` | 通过 state/process/bridge heartbeat 找到候选会话 |
| `planned` | 只生成启动或接管计划,尚未执行 |
| `starting` | 后续 live executor 正在启动或 attach |
| `running` | heartbeat 和 trace 新鲜 |
| `attention_required` | 需要人工判断或审批 |
| `stopping` | 后续 live executor 正在退出 |
| `stopped` | 会话已终止 |
| `degraded` | bridge、trace 或状态持久化部分失败 |
prompt 状态:`draft``planned``queued_for_injection``injected``rejected``failed`
approval 状态:`draft``requested``approved``rejected``expired``consumed`。审批只能绑定一个具体 action、taskId 或 target,不得作为泛授权复用。
## Bridge Contract
SSH bridge 只复用现有 UniDesk Host SSH / WSL SSH 维护桥。它用于 provider 只读诊断、受控维护命令和未来已审批恢复动作;不得作为 provider-gateway 自重建通道,也不得绕过 provider.upgrade 调度规则。
PTY bridge 用于 host Codex 交互会话保活和窗口化 transcript 采集。后续实现必须:
- 有 heartbeat
- stdout/stderr 分流或标注;
- 按 seq 写入事件;
- 默认有 byte/line 上限;
- prompt 注入前先落 plan 和 redaction summary
- 注入失败必须可见,不得静默重试。
stdio bridge 用于非交互 Codex 或 helper subprocess。它必须有 argv 记录、cwd、env key allowlist、exit code、timeout 和 bounded output。env 只能记录 key 存在性或来源,不能记录值。
## Prompt Guidance
prompt 注入前必须按顺序执行:
1. 分类意图和风险;
2. 汇总当前 #20/#46/task/queue 的有界上下文;
3. 运行 forbidden-action guard
4. 对 prompt 和上下文做 secret-like redaction
5. 持久化 prompt plan
6. 后续 live executor 仅在 policy pass 后注入。
遇到 Code Queue backend 重启/重建、执行面重启、task interrupt/cancel、prod mutation、token 访问、破坏性 Git 操作时,必须转入 ClaudeQQ 审批草案,而不是注入执行 prompt。
## Trace Summary
trace summary 不是 raw transcript dump。默认输出应包含:
- `taskId``sessionId``lastSeq`
- 当前状态和 freshness
- 最近关键事件;
- open questions
- recommended next actions
- redactionsApplied
- drill-down 命令。
原始 transcript 必须分页读取,默认不在 summary 中展开。summary 可以引用 Code Queue `codex task --trace``codex output`、host Codex event JSONL 和 approval event,但不能把任一路径失败升级为全局故障,仍需遵守 `docs/reference/code-queue-supervision.md` 的多信号裁决规则。
## Issue Entrypoints
#20 是 Code Queue 总看板入口。读取优先:
```bash
bun scripts/cli.ts gh issue board-audit --board-issue 20 --dry-run
bun scripts/cli.ts gh issue board-row list --board-issue 20
```
写入必须先 dry-run,再带 body SHA 或 updatedAt
```bash
bun scripts/cli.ts gh issue board-row update <issueNumber> --board-issue 20 --field progress --value <text> --expect-body-sha <sha>
```
#46 是每日指挥简报入口。读取:
```bash
bun scripts/cli.ts gh issue read 46 --json body,title,state,updatedAt
```
写入:
```bash
bun scripts/cli.ts gh issue update 46 --body-profile commander-brief --body-file <file> --expect-updated-at <ts>
```
所有 Markdown 正文必须来自 `--body-file`,禁止把正文拼入 shell 参数。任何 issue 写入都不能自动触发 ClaudeQQ,除非该动作本身是高风险请示或用户通知策略明确要求。
## Safety Boundary
第一阶段所有 commander CLI 输出都必须是 `mutation=false`
未来 live executor 在没有用户明确同意前也不得执行:
- 重启或重建 Code Queue backend
- 重启 Code Queue 执行面;
- interrupt 或 cancel 运行任务;
- 修改 production runtime
- 读取或输出 token 明文;
- 直写 PostgreSQL 修补任务状态;
- 破坏性 Git 操作;
- 绕过 GitHub issue body-file 和并发 guard。
高风险动作流程固定为:
1. 生成 ClaudeQQ 请示草案,说明原因、影响范围、拟执行动作和可回滚性;
2. 发送给配置的主用户私聊入口;
3. 等待明确批准;
4. 将批准绑定到唯一 action 和 target
5. 执行前再次校验审批未过期且未被消费;
6. 执行后写入 #46 或对应 issue 的结果摘要。
ClaudeQQ 不可达时,不得把请求视为已批准;只能记录通知失败和继续只读诊断。
## Next Stage Tasks
可派单的下一阶段任务:
- 实现 `src/components/microservices/host-codex-commander` 服务骨架,提供 `/health``/api/commander/contract`,仍不启动 live bridge。
- 增加 `.state/commander/` 文件状态读写模块和 redaction 单元测试。
- 实现只读 host Codex process discovery,输出候选 pid/cwd/age,不 attach、不 kill。
- 实现 trace summary 聚合器,读取 mock event JSONL 和 Code Queue bounded trace。
- 实现 ClaudeQQ approval draft service,不发送消息,只落审批草案和 preview。
- 设计第二阶段 live PTY/stdio bridge 的权限、日志、锁和超时测试。
高风险动作只生成 approval draft JSON / Markdown preview。preview 必须显示 redaction 结果,并明确 `sendImplemented=false`