Skip to content

feat(execution): add Run-owned command runtime - #110

Merged
Qiyuanqiii merged 9 commits into
mainfrom
codex/issue-100-command-runtime
Aug 18, 2026
Merged

Qiyuanqiii merged 9 commits into
mainfrom
codex/issue-100-command-runtime

Conversation

@Qiyuanqiii

@Qiyuanqiii Qiyuanqiii commented Aug 18, 2026 •

Copy link
Copy Markdown
Member

摘要

  • 新增严格版本化的 command-runtime.v2:支持 1–4 条有序前台命令和 Run-owned 后台 Job;提供固定 PowerShell/Bash profile 与绝对路径原生进程 profile,并完整约束 argv、Workspace 相对 cwd、受限环境变量、stdin、timeout、输出、网络、凭据及 fail_fast|continue 批次语义。
  • command_runtime 仅向 Code/Local/Deliver 的 root Supervisor 暴露,并要求当前 full_access 权限快照、有效 execution generation、进程内 permission-control + danger-full-access 启动能力、普通 Policy 审计以及真实 runtime adapter 同时成立。
  • 新增 stdout/stderr 混合单调 cursor、有限等待、stdin 写入、取消/强杀、UTF-8/终端控制序列/敏感信息清洗、明确截断证据,以及带 SHA-256 的终态 Artifact。
  • 使用独立的进程 owner generation/heartbeat 跨 turn 持有后台 Job:Windows 在创建时绑定 kill-on-close Job Object;POSIX 使用 owned process group + guardian,Linux 额外使用 parent-death signal。崩溃或重启只收敛为 interrupted,绝不重放持久化 intent,也不按数据库中的旧 PID 发信号。
  • 已接入 CLI、API、Desktop、严格 OpenAPI/Bootstrap capability、独立设置项和 schema v116;中英文使用/架构/安全文档及 ADR 0117 同步更新。

Closes #100.

协议与命令边界

command-runtime.v2 按 action 使用互斥的严格对象结构;未知字段、缺失字段、null 和跨 action 字段均 fail closed。

  • run 接受 1–4 条完整命令,先对整个批次做预检和 Policy 审计,再顺序启动;前台批次总时限固定为 25 秒。
  • start 只启动一个后台 Job;list、read、wait、write_stdin、cancel、kill 必须属于同一 Run,并重新验证当前授权绑定。
  • PowerShell 固定使用 -NoLogo -NoProfile -NonInteractive -Command;Bash 固定使用 --noprofile --norc -c。
  • 原生进程 profile 只接受 Workspace 外的绝对 PE/ELF/Mach-O 可执行文件与字面 argv;拒绝 Shell、脚本解释器和提权解释器。
  • Workspace root 与 cwd 经 symlink/reparse 解析后规范化、哈希并限制在已注册根目录内;启动前再次校验。
  • 可执行文件在持久化 intent 前计算 SHA-256,启动时重新校验;env/argv/script/purpose/stdin/limit/output policy 全部有界并规范化。
  • 前台与后台共用同一启动路径。命令非零退出是可审计的终态 Job 结果,不会伪装成工具协议失败,因此 continue 可返回完整批次,fail_fast 可确定性停止。

流式输出、stdin 与 Artifact

  • stdout/stderr 共用一个单调全局 cursor;每个 frame 保留 stream、时间、cursor 范围、文本、终端状态、退出码和截断信息。
  • 内联 ring 同时受字节数和 4,096 frame 限制;base_cursor 与 dropped 明确表示淘汰,最小 4 字节读取保证跨 UTF-8 分片仍可前进。
  • 状态化 collector 在持久化前修复损坏/分片 UTF-8,移除 ANSI CSI/OSC/DCS/SOS/PM/APC、C1、不安全 C0、Unicode format control、CR 效果、疑似 secret 行、PEM 块与超限片段;Gateway 对返回模型的内容再次清洗。
  • 每个终态 stream 保存 observed bytes、有界清洗文本、SHA-256 和 inline_window|artifact_limit 原因;溢出内容走既有 Run Artifact 路径,工具 metadata 只保存 Artifact ID/hash。
  • stdin 写入有长度上限、secret 检测、串行化、context 取消和 operation-key 幂等;部分写入视为不确定状态,绝不自动重放。
  • 初始 stdin 不阻塞 timeout:先启动 wait/timeout monitor,再异步执行串行初始写入。

所有权、恢复与持久化

Supervisor turn lease 只 fence 启动前的 write-ahead intent。后台进程由独立随机 owner、正数 generation 和 15 秒可续租 heartbeat 持有,因此同一 API/Desktop 进程中的后续 turn 可以继续读取或写 stdin。

  • 其他进程可以查看持久审计记录,但在 owner heartbeat 有效时不能收养 live Job、取得 handle、发送 stdin 或发信号。
  • root/mode/profile/permission/Workspace-root 漂移、owner 续租失败、timeout、cancel、kill 和应用关闭都收敛到 owned process-tree 清理路径。
  • 重启先等待仍有效的 heartbeat 过期,再写入 interrupted;不会重执行 intent,也不会向可能已复用的持久 PID/process group 发信号。
  • Windows 以 suspended 创建进程,并在同一次 CreateProcess 中绑定 kill-on-close Job Object,仅继承明确 allowlist 中的 handle。
  • POSIX 使用 owned process group 与 parent-pipe guardian;Linux 额外设置 Pdeathsig。
  • POSIX 进程主动新建 session 并脱离 inherited process group 仍可能逃逸;文档将其明确列为非沙箱 full_access 残余风险,不把它描述成可安全收养的 Job。
  • 全进程和单 Run 的活动 Job 上限均为 32;SQLite 还独立约束单 Run 上限、不可变字段及版本化状态转换。

schema v116 保存启动绑定、规范化 intent、可执行文件/env/root 指纹、owner lease、有界清洗输出和终态结果;同时在保留 schema v115 workspace-tool authority JSON 与全部既有调用的前提下,把 command_runtime 加入持久 Supervisor 调用账本。

安全与兼容边界

  • Plan、Cyber、Specialist、approval、debug、过期绑定、缺少 adapter 等上下文完全看不到该工具;Provider 伪造调用会在 Gateway 前再次被拒绝。
  • 每次启动和 lifecycle action 都重新加载并校验 Run/Mission/Session/Workspace/root、当前 mode/profile/permission、精确 Supervisor generation、进程内 capability 与普通 Policy。
  • 批次中每条命令都必须先产生可审计 Policy 决策;任一 denial 或需逐条审批的命令都会阻止整个批次部分启动。
  • 协议只允许 network=disabled 与 credentials=none;显式网络程序/标记及 Policy 判定需审阅的命令会被拒绝。
  • 清除或拒绝 HOME/USERPROFILE、SSH agent/askpass、Shell startup、loader、proxy、credential、cloud/profile、Git config/helper/hook/fsmonitor/external-diff/editor/pager/prompt 等控制路径。
  • Go、Cargo、npm、pip、uv 注入不可变 offline 默认;Git 仅允许 file transport,并关闭交互凭据路径。
  • 这不是 packet-level sandbox,也不替代宿主 OS user token。full_access 仍是非沙箱宿主执行,无法证明本机凭据文件不可读;需要网络/凭据的操作必须使用独立精确审阅路径,要求隔离证据时应使用 Docker network none。
  • 用户终端、Debug terminal、审批 one-shot、普通 Run-owned runtime 与 Docker Sandbox 保持独立 session、owner、UI 标签、审计 metadata 和 capability。

API、Desktop、UI 与 CLI

  • API/Desktop 仅在 Run execution 与完整 permission-control/danger-full-access 能力链同时开启时安装 runtime adapter。
  • 长生命周期 API/Desktop host 每 500 ms 协调 owner heartbeat 与绑定漂移,并在关闭时执行有界 manager shutdown。
  • CLI run step、run execute 与 wake consumption 需显式启用两项启动 flag;CLI 进程退出时会终止其拥有的后台 Job。
  • 不新增直接 HTTP shell/argv/stdin/Job mutation endpoint;HTTP 只投影独立的 command_runtime_enabled,实际执行仍由认证 Run execution 所有。
  • Desktop bootstrap 与 HTTP capability 严格绑定 command_runtime_enabled = run_execution_enabled && danger_full_access_enabled;process/shell 兼容字段与真实可用性保持一致。
  • React connection state 与 Settings 使用独立“命令运行时 / Command runtime”能力项,不与用户终端、Debug 输入、审批提案或 Docker 混合。

主线合并说明

本分支已合并当前 main(cc6fd76,包含 PR #109 的模型工作区工具):

  • PR feat(agent-tools): add model-callable workspace workflow #109 保持 schema v115 与 ADR 0116;本 PR 的命令运行时顺延为 schema v116 与 ADR 0117,不改写已经进入主线的历史版本。
  • v116 从 v115 的 Supervisor 表结构迁移,保留 authority_json 和全部 workspace_* 调用,同时加入 authority 必须为空的 command_runtime。
  • 新增直接迁移测试,验证 v115 workspace authority 精确保留,并验证 v116 能持久化/读取 command-runtime 调用。
  • root 系统策略同时描述 agent-code-tools.v1 与 command_runtime:前者是有界 Workspace 工具,后者是禁网、无凭据、Run-owned 的普通执行;两者不能互相扩大权限。
  • OpenAPI、TypeScript、Desktop bootstrap、Run Detail capability 和设置页面同时保留两组独立能力。

验证

  • go test -timeout 20m -count=1 ./...:全仓通过;internal/application 405.305s、internal/httpapi 171.263s、internal/store 完整 v1–v116 迁移/恢复矩阵 821.790s。
  • v115→v116 定向迁移:workspace authority 原样保留,command_runtime 以空 authority 加入共享账本。
  • go test -race 定向覆盖 command runtime、runner、Supervisor、agent-code 合并边界、store 与 gateway。
  • go test -tags "desktop,wv2runtime.error" -count=1 ./cmd/cyberagent-desktop ./internal/desktop ./internal/webui。
  • Windows 真实 smoke:Windows PowerShell 5、Git for Windows Bash、平台 shell、cursor 输出和完整进程树 cancel/reap;本机固定受信任路径未安装 PS7,按稳定诊断跳过。
  • WSL2 临时 Linux 自举 smoke:快速进程退出后读取输出连续 100 次通过;临时测试文件未进入提交。
  • Linux amd64 与 macOS amd64/CGO-off 的 runner 测试二进制交叉编译。
  • go mod verify、go mod tidy -diff、go vet ./...。
  • correctness-focused staticcheck -checks='SA*,S1*,QF*' 覆盖受影响 Go 包;internal/runner 与 internal/outputsafe 在当前扫描器下无告警。
  • npm run check:api、完整 npm test(60 files / 246 tests)、npm run typecheck、npm run build。
  • npm audit:0 vulnerabilities。
  • git diff --check、schema/ADR 旧引用扫描、冲突标记扫描和隔离 worktree 清洁检查。
  • GitHub Actions CI #362 与 Desktop release #24 均通过:Ubuntu Go 1.25.13 下完整测试、go vet、govulncheck(No vulnerabilities found),Windows/macOS Desktop shell,Rust/TypeScript,以及 release 依赖/许可证和可复现 Portable ZIP 全部成功;PR 场景的 publish 按预期跳过。

审计

  • 未提交凭据、本地数据库、构建输出、原始终端字节、临时可执行文件或原工作区的无关修改。
  • 已审查批次预检、Policy 审计、exe/cwd/env pinning、双 generation、崩溃/重启、stdin 不确定性、输出清洗、Artifact 上限、活动 Job 上限及 permission/root 漂移。
  • README、usage、architecture、Desktop/API 指南、迁移账本、OpenAPI 和中英双语 ADR 0117 同时描述保证与宿主残余风险。
  • 既有用户终端、Debug terminal、one-shot、Docker、schema v114 context continuity、schema v115 agent-code tools 与 Supervisor 历史调用保持数据和权限兼容。

仍需人工证据

PR 暂时保持 Draft,仅剩 reviewer-facing Desktop 交互证据:

  • 远端平台证据已闭环:Ubuntu 全量 Go/runner,macOS POSIX shell 与 guardian/process-group 回收,Windows 平台 shell、进程树 cancel/reap、PowerShell 7 与 Git Bash 均通过。GitHub Windows service session 对 PS5 命中已识别的 0xffff0000 + System.Management.Automation.Utils 启动失败,只有该精确签名稳定 skip;本机真实 Windows PowerShell 5 smoke 通过。
  • 仍需人工确认 Desktop 独立“Command runtime”标签,并确认普通执行不会出现在 Plan/Cyber/Debug-only 配置中。

@Qiyuanqiii
Qiyuanqiii marked this pull request as ready for review August 18, 2026 21:29
@Qiyuanqiii
Qiyuanqiii merged commit 1c8761a into main Aug 18, 2026
8 checks passed
@Qiyuanqiii
Qiyuanqiii deleted the codex/issue-100-command-runtime branch August 18, 2026 21:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(execution): 普通模式真实命令闭环、流式输出与后台 Job

1 participant