workspace-cli AINative 研发平台技术实现方案
本文描述 AI Native Core CLI、daemon、MCP 和 Worker 实现;后续 Web 服务、内嵌 SPA、认证、REST/SSE 和主 Agent Web Chat 见 AI Native Web 技术实现方案。
1. 技术目标
AINative 研发平台在现有 workspace-cli 架构上增量实现。底层仍使用 Go、Cobra、SQLite、Git worktree 和本机 provider CLI;新增本地 daemon、SQLite job queue、Agent provider runner、MCP server、artifact 管理和更细的 workflow 状态。
当前交付和验收覆盖 Codex 与 Claude Code provider。两者使用同一 job/run/MCP 状态边界,并分别验证命令协议、主 Agent 会话和 Worker 输出解析;真实 smoke 按本机 CLI 可用性执行。
核心原则:
- 复用现有
internal/workspace中 repo、requirement、finish、reopen、release integrate、release publish 语义。 - 新增 AINative 状态不得破坏旧库和旧命令。
- Agent 只能通过 service 层和 MCP 工具操作状态,不直接写 SQLite。
- Worker 的每次执行都必须可追踪、可重试、可诊断。
- release 分支继续保持可重建和不可直接修复。
2. 总体架构
flowchart TD
User["用户"] --> MainAgent["主 Agent\nCodex CLI 交互会话"]
MainAgent --> MCP["workspace mcp serve\n结构化控制面"]
MCP --> Service["workspace service 层"]
CLI["workspace CLI"] --> Service
Daemon["workspace agent daemon"] --> Queue["SQLite job queue"]
Daemon --> CoordLane["Coordinator lane\nmain Agent non-interactive"]
Daemon --> WorkerA["Analysis Worker"]
Daemon --> WorkerC["Coding Worker"]
Daemon --> WorkerT["Testing Worker"]
CoordLane --> ProviderM["Codex provider"]
WorkerA --> ProviderA["Codex provider"]
WorkerC --> ProviderC["Codex provider"]
WorkerT --> ProviderT["Codex provider"]
ProviderM --> MCP
ProviderA --> MCP
ProviderC --> MCP
ProviderT --> MCP
Service --> DB["workspace.db"]
Service --> Artifacts["work/artifacts"]
Service --> Git["bare repos + worktrees"]
本地进程分工:
workspace ai start:启动主 Agent 交互会话。主 Agent 获得 workspace-cli MCP 工具,可与用户聊天并协调流程。workspace agent daemon start:启动 coordinator daemon。daemon 负责监听 workflow 状态、创建系统 job、claim worker job、用默认主 Agent 执行 coordinator job、启动 provider 子进程、回收 worker、处理 lease 超时。workspace mcp serve:stdio MCP server。提供需求、artifact、job、release、bug 工具。- provider 子进程:当前为 Codex。每个 job 对应一次 provider run,默认非交互执行。
3. 运行目录
现有目录保持不变,新增 artifacts 和 runtime 目录:
~/.workspace-cli/
config.yaml
workspace.db
work/
repos/
<repo>.git
requirements/
<req-slug>/
<repo>/
releases/
<release-slug>/
<repo>/
.publish/
<repo>/
artifacts/
requirements/
<req-slug>/
analysis/
development/
testing/
bugs/
releases/
<release-slug>/
test-runs/
<test-run-id>/
runtime/
mcp/
jobs/
logs/
artifact 文件使用 Markdown 或 JSON:
- 面向用户阅读的方案、报告、Review 使用
.md。 - provider 原始 JSONL 输出和结构化摘要使用
.jsonl或.json。 - DB 保存 artifact path、type、version、sha256、final 标记和创建 run。
4. 配置结构
扩展 config.Config:
type Config struct {
Home string
DBPath string
WorkDir string
ReposDir string
ReqDir string
ReleaseDir string
ArtifactDir string
RuntimeDir string
Tools Tools
Agent AgentConfig
}
type AgentConfig struct {
DefaultReviewPolicy string
DefaultMainAgent string
DefaultTestCommand string
CoordinatorWatchIntervalMs int
}
config.yaml 新增:
artifacts_dir: "~/.workspace-cli/work/artifacts"
runtime_dir: "~/.workspace-cli/work/runtime"
agent_default_review_policy: "no_high_risk"
agent_default_main_agent: "main-codex"
agent_default_test_command: ""
agent_coordinator_watch_interval_ms: 2000
已有简单 YAML parser 只能解析平铺 key。为控制变更范围,V1 继续使用平铺 key,不引入嵌套 agent: 配置。
5. SQLite 迁移
AINative 基础表使用 migration 0003_ai_native_workflow;后续兼容迁移依次为 0004_ai_native_atomic_hardening 和 0005_ai_native_hardening。0005 为 requirements 增加 acceptance_criteria、priority、analysis_review_policy_id、development_review_policy_id,旧记录使用 priority 100,策略为空时回退到全局默认策略。
5.1 扩展 requirements
新增列:
description TEXTworkflow_status TEXT NOT NULL DEFAULT 'manual_active'analysis_agent_id INTEGERcoding_agent_id INTEGERtest_agent_id INTEGERanalysis_final_artifact_id INTEGERtechnical_final_artifact_id INTEGER
manual_active 表示旧命令创建的需求,不进入 AINative 自动流程。通过 req submit 创建的需求默认 pending_acceptance。
SQLite 不能可靠地通过 ALTER TABLE ADD COLUMN 为旧表新增外键约束;这些新增 ID 字段由 service 层校验引用存在、角色匹配和状态转换合法性,并新增普通索引用于查询。
5.2 扩展 releases
新增列:
workflow_status TEXT NOT NULL DEFAULT 'manual_release'test_agent_id INTEGERactive_test_run_id INTEGERdefault_test_command TEXT
这些新增 ID 字段同样由 service 层校验;旧 release 默认 manual_release,不自动进入 AINative 测试/发布状态机。AINative release 的 workflow_status 取值为 pending_testing、testing、testing_completed、pending_release、releasing、released、stale、publish_in_progress。default_test_command 来自 workspace release create --test-command,可为空。
5.3 新表 agents
CREATE TABLE agents (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL UNIQUE,
provider TEXT NOT NULL,
role TEXT NOT NULL,
model TEXT,
system_prompt TEXT,
system_prompt_path TEXT,
command TEXT,
sandbox TEXT,
approval_policy TEXT,
enabled INTEGER NOT NULL DEFAULT 1,
health_status TEXT NOT NULL DEFAULT 'unknown',
health_message TEXT,
metadata_json TEXT,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
Provider 取值:codex、claude。Role 取值:coordinator、analysis、coding、testing。
5.4 新表 worker_pools
CREATE TABLE worker_pools (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL UNIQUE,
role TEXT NOT NULL,
agent_id INTEGER NOT NULL,
parallelism INTEGER NOT NULL DEFAULT 1,
max_workers INTEGER NOT NULL DEFAULT 1,
poll_interval_ms INTEGER NOT NULL DEFAULT 2000,
lease_seconds INTEGER NOT NULL DEFAULT 300,
enabled INTEGER NOT NULL DEFAULT 1,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY(agent_id) REFERENCES agents(id)
);
5.5 新表 worker_instances
CREATE TABLE worker_instances (
id INTEGER PRIMARY KEY AUTOINCREMENT,
pool_id INTEGER NOT NULL,
worker_key TEXT NOT NULL UNIQUE,
pid INTEGER,
status TEXT NOT NULL,
current_job_id INTEGER,
heartbeat_at TIMESTAMP,
started_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
stopped_at TIMESTAMP,
message TEXT,
FOREIGN KEY(pool_id) REFERENCES worker_pools(id)
);
worker_instances.status 取值为 starting、idle、running、stopping、stopped、lost。parallelism 限制同一 pool 同时处于 leased/running 的 job 数;max_workers 限制同一 pool 存活 worker instance 数,存活状态包括 starting、idle、running、stopping。daemon 每轮调度先清理过期 heartbeat 的 instance 为 lost,再按 min(parallelism - active_jobs, max_workers - live_instances) 计算可启动槽位。
一次调度先串行完成 capacity、worker 和 job claim,随后为每个 claimed worker slot 启动独立 goroutine 并发运行 provider,等待本轮全部 outcome 后再生成 RunOnceResult。SQLite 状态读写使用单一共享连接串行短事务,provider 进程和文件系统工作仍并行执行,不能让数据库 transaction 跨越 provider 运行时间。claim query 对带 requirement_id 的 job 排除相同 requirement 的 leased/running job;只有不带 requirement 的 release-workspace job 才按 release_id 互斥。这样可以保护同一 workspace,同时允许同一 release 内不同 requirement 的 bugfix 并行。
5.6 新表 review_policies
CREATE TABLE review_policies (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL UNIQUE,
stage TEXT NOT NULL,
max_review_rounds INTEGER NOT NULL,
pass_condition TEXT NOT NULL,
max_allowed_severity TEXT NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
默认插入:
analysis-strict:stageanalysis,max 5,pass_conditionno_findings。analysis-no-high-risk:stageanalysis,max 5,pass_conditionmax_severity,max severitymedium。development-no-high-risk:stagedevelopment,max 3,max severitymedium。testing-no-open-bugs:stagetesting,max 3,pass_conditionno_open_bugs。
5.7 新表 artifacts
CREATE TABLE artifacts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
entity_type TEXT NOT NULL,
entity_id INTEGER NOT NULL,
job_id INTEGER,
run_id INTEGER,
artifact_type TEXT NOT NULL,
stage TEXT NOT NULL,
version INTEGER NOT NULL,
title TEXT NOT NULL,
path TEXT NOT NULL,
sha256 TEXT NOT NULL,
is_final INTEGER NOT NULL DEFAULT 0,
created_by TEXT NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
entity_type 取值为 requirement、release、release_test_run,entity_id 按类型指向对应业务对象。需求设计、技术方案、开发报告和 bugfix 报告使用 entity_type=requirement;release 级说明使用 entity_type=release;测试报告使用 entity_type=release_test_run。job_id、run_id 指向 Agent 执行记录;多态 entity、artifact、job、run 的归属由 service 层校验,并在查询侧建立普通索引。
索引:
CREATE UNIQUE INDEX artifacts_version_unique
ON artifacts(entity_type, entity_id, artifact_type, version);
CREATE UNIQUE INDEX artifacts_one_final
ON artifacts(entity_type, entity_id, artifact_type)
WHERE is_final = 1;
5.8 新表 requirement_status_events
CREATE TABLE requirement_status_events (
id INTEGER PRIMARY KEY AUTOINCREMENT,
requirement_id INTEGER NOT NULL,
old_status TEXT,
new_status TEXT NOT NULL,
actor TEXT NOT NULL,
reason TEXT,
job_id INTEGER,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY(requirement_id) REFERENCES requirements(id)
);
5.8.1 新表 release_status_events
CREATE TABLE release_status_events (
id INTEGER PRIMARY KEY AUTOINCREMENT,
release_id INTEGER NOT NULL,
old_status TEXT,
new_status TEXT NOT NULL,
actor TEXT NOT NULL,
reason TEXT,
test_run_id INTEGER,
job_id INTEGER,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY(release_id) REFERENCES releases(id)
);
test_run_id 和 job_id 由 service 层校验归属。release test start、test pass/fail、scope stale、publish confirmation reject、publish start、publish-in-progress 和 publish success 都必须写入该表,供 release watch、release status 和主 Agent 展示。
所有改变 AINative workflow 的 production store API 必须把状态更新和 status event 放在同一个 transaction 中。requirement submit 还要把 requirement row、repo bindings 和初始 event 一起提交;Agent assignment 与状态推进、analysis final -> pending development、daemon requirement/release transitions 都使用带 actor、reason、job/test-run scope 的 transactional operation。测试专用 raw setter 不进入 production 调用路径。
5.9 新表 agent_jobs
CREATE TABLE agent_jobs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
job_key TEXT NOT NULL UNIQUE,
role TEXT NOT NULL,
job_type TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'queued',
priority INTEGER NOT NULL DEFAULT 100,
requirement_id INTEGER,
release_id INTEGER,
bug_id INTEGER,
agent_id INTEGER,
worker_pool_id INTEGER,
input_json TEXT NOT NULL,
result_json TEXT,
attempts INTEGER NOT NULL DEFAULT 0,
max_attempts INTEGER NOT NULL DEFAULT 3,
lease_owner TEXT,
lease_expires_at TIMESTAMP,
not_before TIMESTAMP,
started_at TIMESTAMP,
completed_at TIMESTAMP,
failed_at TIMESTAMP,
last_error TEXT,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY(requirement_id) REFERENCES requirements(id),
FOREIGN KEY(release_id) REFERENCES releases(id),
FOREIGN KEY(agent_id) REFERENCES agents(id),
FOREIGN KEY(worker_pool_id) REFERENCES worker_pools(id)
);
状态:queued、leased、running、succeeded、failed、blocked、waiting_user_input、cancelled。
bug_id 指向 requirement_bugs.id,由 service 层校验;只有 job_type=bugfix 的 job 可以设置。
5.10 新表 agent_runs
CREATE TABLE agent_runs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
job_id INTEGER NOT NULL,
attempt INTEGER NOT NULL,
provider TEXT NOT NULL,
agent_id INTEGER NOT NULL,
worker_key TEXT,
command TEXT NOT NULL,
cwd TEXT NOT NULL,
stdout_path TEXT,
stderr_path TEXT,
output_json_path TEXT,
exit_code INTEGER,
status TEXT NOT NULL,
started_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
completed_at TIMESTAMP,
error TEXT,
FOREIGN KEY(job_id) REFERENCES agent_jobs(id),
FOREIGN KEY(agent_id) REFERENCES agents(id)
);
5.11 新表 agent_run_events
CREATE TABLE agent_run_events (
id INTEGER PRIMARY KEY AUTOINCREMENT,
run_id INTEGER NOT NULL,
job_id INTEGER NOT NULL,
requirement_id INTEGER,
release_id INTEGER,
event_seq INTEGER NOT NULL,
event_type TEXT NOT NULL,
visibility TEXT NOT NULL DEFAULT 'user',
severity TEXT NOT NULL DEFAULT 'info',
message TEXT NOT NULL,
payload_json TEXT,
artifact_id INTEGER,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY(run_id) REFERENCES agent_runs(id),
FOREIGN KEY(job_id) REFERENCES agent_jobs(id),
FOREIGN KEY(requirement_id) REFERENCES requirements(id),
FOREIGN KEY(release_id) REFERENCES releases(id)
);
索引:
CREATE UNIQUE INDEX agent_run_events_seq_unique
ON agent_run_events(run_id, event_seq);
CREATE INDEX agent_run_events_job_created
ON agent_run_events(job_id, created_at, id);
事件类型至少包含:run_started、provider_output、tool_call、artifact_created、review_result、test_output、approval_requested、blocked、run_completed。visibility=debug 的事件只在 --verbose 或显式 tail 时展示;token、API key、环境变量 secret 不写入事件。
event_seq 只能由 AppendAgentRunEvent service 方法生成,调用方不传入序号。该方法使用 BEGIN IMMEDIATE 或等价写锁事务读取同一 run_id 当前最大 event_seq,插入 max + 1,并返回插入后的事件;runner 的 stdout、stderr、tool call 和 approval 事件必须串行经过这个方法,避免并发写入重复序号。artifact_id 如果不为空,service 必须校验 artifact 存在且属于同一 requirement/release/test-run 上下文;V1 不增加 DB 外键,保持和 artifacts.job_id/run_id 一致的 service 校验策略。
5.12 新表 human_approval_requests
CREATE TABLE human_approval_requests (
id INTEGER PRIMARY KEY AUTOINCREMENT,
approval_key TEXT NOT NULL UNIQUE,
requirement_id INTEGER,
release_id INTEGER,
release_test_run_id INTEGER,
job_id INTEGER,
run_id INTEGER,
approval_type TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'pending',
title TEXT NOT NULL,
prompt TEXT NOT NULL,
payload_json TEXT,
options_json TEXT,
default_option TEXT,
response_json TEXT,
requested_by TEXT NOT NULL,
responded_by TEXT,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
responded_at TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY(requirement_id) REFERENCES requirements(id),
FOREIGN KEY(release_id) REFERENCES releases(id),
FOREIGN KEY(release_test_run_id) REFERENCES release_test_runs(id),
FOREIGN KEY(job_id) REFERENCES agent_jobs(id),
FOREIGN KEY(run_id) REFERENCES agent_runs(id)
);
状态:pending、approved、rejected、cancelled。类型至少包含:requirement_clarification、artifact_finalization、implementation_blocker、test_command_missing、publish_confirmation、provider_permission。
同一业务 scope 内,同一 approval_type 只能存在一个 pending request;重复触发时更新原 request 的 updated_at 和提示摘要,不创建重复确认项。scope 按类型固定:需求澄清、方案定稿和实现阻塞使用 requirement_id,测试命令缺失使用 release_test_run_id,发布确认使用 release_id + release_test_run_id,provider 权限使用 job_id/run_id。如果 scope 字段缺失,service 必须拒绝创建 approval。
payload_json 和 response_json 必须按 approval_type 使用稳定结构:
- 所有 response 都包含
choice、message、submitted_by、submitted_at;submitted_by和submitted_at由 service 根据 CLI 用户或 coordinator relay 填充,调用方不能覆盖。 requirement_clarification:payload 包含缺失字段列表;response 可包含description、acceptance_criteria、repo、priority的更新值。artifact_finalization:payload 包含可选的requirement_design_artifact_ids和technical_design_artifact_ids;response 必须包含final_requirement_design_artifact_id和final_technical_design_artifact_id。service 校验两份 artifact 同属该需求,关闭 approval 后在同一事务里 finalize 两类 artifact。implementation_blocker:response 的choice只能是continue、replan、block;replan创建新的 analysis job,block保持 job blocked。test_command_missing:payload 必须包含release_test_run_id、已尝试的test_command_sources和失败原因;response 必须包含test_command或choice=block。用户补充命令后,service 更新对应release_test_runs.test_command/test_command_source并把该 test run 恢复为queued;不允许用空命令把 release 标记为测试通过。publish_confirmation:payload 必须包含release_id、release_test_run_id、待发布 requirements、test run 的 requirement+repo+commit 快照摘要、目标默认分支、最近一次 test run 和 dirty/external commit 检查摘要;response 必须包含confirm=true|false。只有confirm=true的 approved approval 才允许调用 publish。provider_permission:payload 必须包含requested_scope、requested_sandbox、requested_approval_policy和reason;response 必须包含approved、scope、expires_at、sandbox、approval_policy。service 只允许把 response 中的 sandbox/approval policy 限制在 payload 请求的权限内;拒绝时 job 保持 blocked 或 failed。
5.12.1 新表 provider_permission_grants
CREATE TABLE provider_permission_grants (
id INTEGER PRIMARY KEY AUTOINCREMENT,
approval_id INTEGER NOT NULL,
job_id INTEGER NOT NULL,
run_id INTEGER,
scope TEXT NOT NULL,
sandbox TEXT NOT NULL,
approval_policy TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'active',
expires_at TIMESTAMP NOT NULL,
used_at TIMESTAMP,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY(approval_id) REFERENCES human_approval_requests(id),
FOREIGN KEY(job_id) REFERENCES agent_jobs(id)
);
状态:active、used、expired、revoked。用户 approve provider_permission 后,service 创建 grant,把关联 job 恢复为 queued;grant 必须保存非空 sandbox 和 approval_policy,且二者来自用户 response。下一次 runner 启动前读取同一 job 的 active grant,校验未过期、scope 覆盖本次请求、sandbox 和 approval_policy 都存在后,才把 grant 应用到 provider 命令。grant 使用后写 used_at/status=used;过期 grant 或缺少授权参数时不得继续使用。用户 reject 时不创建 grant,job 保持 blocked 或标记 failed。
5.13 新表 requirement_bugs
CREATE TABLE requirement_bugs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
requirement_id INTEGER NOT NULL,
release_id INTEGER,
test_run_id INTEGER,
title TEXT NOT NULL,
description TEXT NOT NULL,
severity TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'open',
repo_id INTEGER,
file_path TEXT,
reproduction TEXT,
created_by_job_id INTEGER,
fixed_by_job_id INTEGER,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
closed_at TIMESTAMP,
FOREIGN KEY(requirement_id) REFERENCES requirements(id),
FOREIGN KEY(release_id) REFERENCES releases(id),
FOREIGN KEY(repo_id) REFERENCES repos(id)
);
test_run_id、created_by_job_id、fixed_by_job_id 由 service 层校验存在性和归属,避免循环外键让 migration 顺序变脆。
5.14 新表 release_test_runs
CREATE TABLE release_test_runs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
release_id INTEGER NOT NULL,
test_agent_id INTEGER,
status TEXT NOT NULL DEFAULT 'queued',
test_command TEXT,
test_command_source TEXT NOT NULL DEFAULT 'explicit',
working_dir TEXT,
summary_artifact_id INTEGER,
started_at TIMESTAMP,
completed_at TIMESTAMP,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY(release_id) REFERENCES releases(id),
FOREIGN KEY(test_agent_id) REFERENCES agents(id)
);
summary_artifact_id 指向 entity_type=release_test_run、entity_id=<release_test_run_id>、artifact_type=test_report 的 artifact,由 service 层校验。release_test_runs.status 取值为 queued、running、waiting_user_input、passed、failed、blocked、cancelled;waiting_user_input 只用于等待 test_command_missing 等人工确认,用户补充命令后回到 queued,用户选择 block 后进入 blocked。
test_command_source 由 service 层校验稳定取值,V1 不加 DB CHECK 约束:
explicit:来自release_test_start --test-command。release_default:来自releases.default_test_command。agent_default:来自agent_default_test_command。inferred:测试 Agent 根据仓库推断并实际执行。user_supplied:用户响应test_command_missingapproval 后补充。
5.15 新表 release_test_run_requirements
CREATE TABLE release_test_run_requirements (
id INTEGER PRIMARY KEY AUTOINCREMENT,
release_test_run_id INTEGER NOT NULL,
release_id INTEGER NOT NULL,
requirement_id INTEGER NOT NULL,
repo_id INTEGER,
repo_name TEXT NOT NULL,
requirement_workflow_status TEXT NOT NULL,
feature_branch TEXT,
feature_commit_sha TEXT,
release_commit_sha TEXT,
included_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY(release_test_run_id) REFERENCES release_test_runs(id),
FOREIGN KEY(release_id) REFERENCES releases(id),
FOREIGN KEY(requirement_id) REFERENCES requirements(id),
FOREIGN KEY(repo_id) REFERENCES repos(id)
);
CREATE UNIQUE INDEX release_test_run_requirements_unique
ON release_test_run_requirements(release_test_run_id, requirement_id, repo_name);
创建 test run 时,service 必须把当前 active release scope 按 requirement + repo 写入快照;同一需求覆盖多个 repo 时写多行。repo_id 可为空以兼容尚未落库的 repo 绑定或历史测试数据,repo_name 必填并参与唯一约束。feature_commit_sha 记录该需求在该 repo 的 feature 分支提交,release_commit_sha 记录 release worktree 中该 repo 的集成提交,二者都不是需求全局字段。发布前必须比较当前 active release 的 requirement 集合、repo 集合和每个 requirement + repo 的 feature/release commit 与当前 passed test run 快照;任一集合或提交不一致时,旧 test run 失效,release 进入 stale 或 pending_testing,并要求重新 integrate/test。
6. Go 包边界
新增或扩展包:
internal/agentProviderRunnerinterface。CodexRunner和ClaudeRunner。- health check 和 command builder。
internal/coordinator- daemon 主循环。
- Worker pool 调度。
- coordinator lane:用
agent_default_main_agent串行执行role=coordinatorjob,不通过普通 worker pool 配置。 - job lease、heartbeat、retry、cancel。
internal/mcp- stdio MCP server。
- tool registry。
- capability token 校验。
internal/artifact- artifact path、version、sha256、finalize。
- Markdown 模板。
internal/workspace- AINative service 方法,继续封装业务规则。
internal/store- migration 0003。
- Agent、Worker、Job、Run、RunEvent、Approval、Artifact、Bug、TestRun CRUD。
internal/cli- 新增 agent、worker、ai、job、mcp、artifact、req analysis/artifact/bug、release test 命令。
7. Provider runner
7.1 Interface
type ProviderRunner interface {
Health(ctx context.Context, agent store.Agent) agent.HealthResult
Run(ctx context.Context, run agent.RunRequest) agent.RunResult
}
type RunRequest struct {
WorkspaceHome string
RuntimeDir string
JobKey string
JobID int64
JobToken string
Attempt int
Provider string
Model string
AgentID int64
WorkerKey string
CWD string
Prompt string
PermissionScope string
Sandbox string
ApprovalPolicy string
MCPServerCommand string
}
ToolConfigPath 表示 provider 专用工具配置文件:Codex 生成 job/session scoped 的 config.toml 作为审计和等价配置来源,同时通过 -c mcp_servers.workspace_cli.* 注入当前进程,避免覆盖用户已有 CODEX_HOME 中的登录态;Claude 使用 --mcp-config 指向的 JSON 文件。CodexHome 在实现中表示 Codex runtime 配置目录,不应强制写入 provider 环境变量。
7.2 Codex 默认命令
codex exec
--model <configured-model-if-present>
--json
--cd <cwd>
--skip-git-repo-check
--sandbox workspace-write
-c approval_policy="never"
-c mcp_servers.workspace_cli.command="<workspace-binary>"
-c mcp_servers.workspace_cli.args=["mcp", "serve", "--home", "<workspace-home>", "--capability-token", "<job-token>"]
--output-last-message <job-runtime>/output.json
<prompt>
Codex runner 在启动前必须创建 work/runtime/mcp/<job-key>/codex/config.toml,配置内容只暴露一个 stdio MCP server:
[mcp_servers.workspace_cli]
command = "<workspace-binary>"
args = ["mcp", "serve", "--home", "<workspace-home>", "--capability-token", "<job-token>"]
不要为 Codex 使用 --mcp-config;该参数属于 Claude Code。Codex Worker 和主 Agent 都不应把 CODEX_HOME 改到临时目录,否则真实 Codex 会丢失用户登录态并出现 401。实际启动命令使用 -c mcp_servers.workspace_cli.command=... 和 -c mcp_servers.workspace_cli.args=[...] 注入同一 MCP server;生成的 config.toml 用于审计、session 记录和排障。主 Agent 的交互式 Codex 会话沿用用户默认 CODEX_HOME,通过 -c 注入 coordinator token,并保留 --ask-for-approval on-request。
如果 job 只读,例如分析或测试 Review,可以使用 --sandbox read-only,但分析阶段需要写 artifact 时由 MCP 工具写入,不要求文件系统写权限。
daemon 构造 worker RunRequest 时读取绑定 Agent 配置。model 非空时分别传给 Codex/Claude 的 --model。内联 system_prompt 和 system_prompt_path 文件内容按此顺序拼接,再以 Agent system instructions 与 Job input 两段组成最终 prompt;两者都为空时保持原始 job input,兼容既有作业。prompt 文件读取失败时在 provider 进程启动前终止本次执行,不能静默忽略配置;worker/coordinator job 使用相同 retry/max-attempts 状态机保存 path-specific error,普通 worker instance 返回 idle,达到最大次数的 pre-run failure 必须显式进入 failed。终态写入成功后 scheduler 将该 job 视为已处理,不把原错误上抛为 daemon fatal error。
provider 工作目录与控制面 home 必须分离。带 workspace_path 的 Coding/testing job 使用该路径作为 CWD,并在启动前校验 workspace 和 artifact 目录存在且为目录;不带 workspace_path 的 analysis/coordinator job 使用 work/runtime/agent-workspaces/job-<id>/attempt-<n>。交互式主 Agent 使用 work/runtime/main-agent/<agent>/<session>/workspace。MCP config 和 WORKSPACE_CLI_HOME 仍指向真实 workspace home,但 Codex --cd、CommandSpec.Dir 和 Claude process CWD 不得指向包含 workspace.db 的 home 根目录。
如果 job 曾因权限不足创建 provider_permission approval,runner 重试前必须读取同一 job 的 active provider_permission_grants。只有 grant 未过期、scope 覆盖本次请求、且规范化 workspace_policy 和 approval_policy 都存在时,才能扩大当前登记代码 worktree 内的权限;原始 sandbox 只用于审计,不能直接决定执行参数。否则继续保持 job blocked 或重新请求用户确认。
7.3 Claude 默认命令
claude -p
--model <configured-model-if-present>
--output-format stream-json
--mcp-config <mcp-config.json>
--permission-mode acceptEdits
--system-prompt-file <prompt-file>
<prompt>
Claude provider 的 --mcp-config 使用 job-scoped 配置文件,只暴露 workspace-cli MCP server。
7.4 输出采集
每次 run 写入:
work/runtime/jobs/<job-key>/<attempt>/
prompt.md
stdout.jsonl
stderr.log
result.json
runner 必须边读取 provider stdout/stderr 边写 agent_run_events,让 job watch 和主 Agent 可以实时展示执行过程。原始输出仍写入 stdout.jsonl 和 stderr.log;DB event 保存摘要、事件类型、关联对象和输出文件路径/offset,摘要写入前必须做 secret redaction。单条 provider output 超过摘要上限时,DB 只保存“输出已省略”的摘要、原始字节数和 raw 文件路径,完整内容只能从 runtime 文件读取。runner 完成后解析 provider 最后一条 assistant 消息,写入 agent_runs,并把结构化 artifact 创建交给 MCP 工具或 service 层。
当 provider 输出表示需要用户澄清或确认时,runner 不继续猜测:通过 service 创建 human_approval_requests,写入 approval_requested event,并把 job 标记为 waiting_user_input。
8. Job 调度
8.1 Claim 规则
daemon 对每个 enabled worker pool 执行事务,worker pool 只处理 analysis、coding、testing 三类 job。claim 前必须计算当前 pool 的 active job 数和 live worker instance 数;当 active job 数已达到 parallelism,或 live worker instance 数已达到 max_workers 且没有 idle instance 可复用时,本轮不得 claim 新 job:
UPDATE agent_jobs
SET status = 'leased',
lease_owner = ?,
lease_expires_at = datetime('now', '+' || ? || ' seconds'),
attempts = attempts + 1,
updated_at = CURRENT_TIMESTAMP
WHERE id = (
SELECT id FROM agent_jobs
WHERE status = 'queued'
AND role = ?
AND (not_before IS NULL OR not_before <= CURRENT_TIMESTAMP)
AND attempts < max_attempts
ORDER BY priority ASC, created_at ASC, id ASC
LIMIT 1
)
RETURNING *;
如果 SQLite driver 不支持 RETURNING 的目标环境出现问题,改成 BEGIN IMMEDIATE、SELECT、UPDATE、COMMIT。
claim 成功后,daemon 优先复用该 pool 的 idle instance;没有 idle instance 且 live instance 数小于 max_workers 时创建 starting instance 并启动 provider runner;runner 开始执行时 instance 变为 running 并写 current_job_id,job 完成后 instance 回到 idle 或在 daemon 停止时进入 stopping/stopped。任何路径都不得让 live instance 数超过 max_workers,也不得让 active job 数超过 parallelism。
daemon-generated worker key 使用 <lease-owner>-pool-<pool-id>-<sequence>,sequence 必须跳过该 pool 所有 retained worker rows,不按 live count 回退。若另一 daemon 在 create 窗口抢先占用候选 key,当前 daemon 识别已存在 key 并尝试下一 sequence;单 daemon lost/stopped replacement 绝不能触发 unique constraint。
同一轮 claim 完成后,各 worker slot 的 provider runner 必须并发启动;RunOnce 等待本轮所有 runner 完成并汇总 completed/failed/retried 计数。带 requirement 的 job 以 requirement workspace 为互斥 scope;release-only job 以 release workspace 为互斥 scope。相同 scope 的 queued job 必须等待当前 leased/running job 退出 active 状态后才能 claim。
role=coordinator 的 job 不由 worker pool claim。daemon 使用 agent_default_main_agent 建立固定并行度为 1 的 coordinator lane,复用同样的 lease、run 记录和 retry 逻辑,避免多个主 Agent 同时为同一需求做相互冲突的分配决策。
8.2 Heartbeat
Worker instance 每 10 秒更新:
worker_instances.heartbeat_atagent_jobs.lease_expires_at
daemon 启动时把过期的 leased 或 running job 恢复为 queued,除非 attempts >= max_attempts,这种情况标记为 failed。
8.3 Retry
provider 退出非零时:
- 如果
attempts < max_attempts,写last_error,状态回queued,not_before延迟 30 秒。 - 否则标记
failed。 - 如果错误是业务阻塞,例如方案不可实施、测试需要人工确认,标记
blocked。 - 如果错误是等待用户输入,创建 pending approval request,标记
waiting_user_input,不消耗自动 retry。
8.4 Workflow watch loop
daemon 每 agent_coordinator_watch_interval_ms 扫描 workflow 状态,并用幂等 service 方法补齐缺失 job:
pending_acceptance且存在默认主 Agent 时,创建role=coordinator、job_type=coordinator_decidejob;该 job 由 coordinator lane 执行,可以按默认规则调用req_assign_agents,也可以把需求保持待采纳并写阻塞说明。- coordinator lane 还监听
analysis_completed、development_completed、open test bug、releasestale、releasepublish_in_progress和非 coordinator blocked job。需求/release 使用最新匹配当前状态的 status event ID 构造 job key;bug 使用 bug ID;blocked job 使用 source job ID + current attempt。这样相同快照重复 tick 保持幂等,但方案定稿响应、同状态诊断或 retry 后再次 blocked 仍可形成新的协调代次。没有 status event 的历史数据使用实体+状态 fallback key。 - coordinator job input 包含 trigger type、requirement/release/bug/source-job scope、status event actor/reason、last error 和显式 coordination request。
publish_in_progress先写幂等 manual-recovery diagnostic 再扫描;所有 coordinator job 继续由固定并行度 1 的 lane 执行。扫描 blocked job 时排除role=coordinator,防止协调任务失败后递归派生。 pending_analysis且无 active analysis job 时,创建analysis_generatejob。analysis_completed不自动进入开发;必须等用户通过artifact_finalizationapproval 或显式 CLI 操作 finalize 两类 artifact 后,主 Agent 才能调用req advance <req> pending_development。pending_development且终稿齐全时,先调用PrepareRequirementWorkspace,成功后推进到developing并创建implementation_planjob。development_completed加入 release 后,由 release integrate 成功路径推进到pending_testing。- release test 产生 open bug 时,为对应需求创建
bugfixjob;已存在同一 open bug 的 active bugfix job 时不重复创建。 - release 从
testing_completed进入pending_release时,读取releases.active_test_run_id指向的当前 passed test run,创建 release/test-run scopedpublish_confirmationapproval,同步把 active requirements 从testing_completed推进到pending_release,并写release_status_events;用户拒绝后 release 和 requirements 保持pending_release,并且 daemon 不自动重建同一 release/test run 的确认。只有用户再次请求发布、release 重新测试生成新的 test run,或 release scope 变化后,才创建新的发布确认。 publish-in-progress、stale、blocked job 只写诊断和 next action,不自动绕过用户确认。
8.5 实时 watch 和人工确认流程
实时 watch 使用 SQLite 事件流,不引入远程服务:
workspace job watch <job-key> --follow轮询agent_run_events,按event_seq展示新增事件;无新增事件时展示 heartbeat 和当前 job 状态。workspace req watch <req> --follow聚合当前需求的 workflow 状态、active jobs、最近 run events、pending approvals 和最新 artifact。workspace release watch <release> --follow聚合 release workflow 状态、release_status_events、测试 run、requirement+repo+commit 快照、open bugs、关联需求状态、pending approvals、最近 run events 和 test_report artifact id/path。workspace run tail <run-id> --follow展示某次 run 的 event,并可在--raw时读取 stdout/stderr 文件尾部;--raw默认仍做 redaction,只有本地 CLI 的--unsafe-unredacted才允许读取未脱敏尾部,MCP 不提供未脱敏 raw tail。- 主 Agent 通过 MCP 的
req_watch、release_watch、job_watch、run_tail、approval_list、approval_respond工具获得相同信息。
人工确认流程:
- Agent、daemon 或 service 发现需要用户判断,调用
CreateHumanApprovalRequest。 - service 写
human_approval_requests,同时写agent_run_events.event_type=approval_requested和 requirement/release 状态事件,保证 watch 能立即显示。 - 关联 job 进入
waiting_user_input或blocked;业务workflow_status保持当前阶段。 - 用户通过主 Agent 或 CLI respond。
- service 写响应、关闭 approval,并根据响应把 job 恢复为
queued、取消 job,或创建新的 coordinator/analysis/coding/testing job。 artifact_finalization被 approve 时,service 在关闭 approval 的同一事务中 finalize 需求设计和技术方案两类 artifact;任一 artifact 不存在、类型不匹配或不属于该需求时拒绝响应并保持 approval pending。publish_confirmation被 reject 时,service 保持 releasepending_release并写release_status_eventsnext action;被 approve 且confirm=true时,只记录确认。publish 由后续release_publish单独触发,且仍要重新检查 dirty guard、external commit、release test run 的 requirement+repo+commit 快照和测试状态。provider_permission被 approve 时,service 校验 response 包含scope、expires_at、sandbox和approval_policy,再创建provider_permission_grants并把 job 恢复为queued;被 reject 时保持blocked或标记failed。- 每次响应都写 requirement/release status event 和 run event,保证审计可追踪。
9. 状态机
需求状态只允许通过 service 方法推进。
允许转换:
pending_acceptance -> pending_analysis
pending_analysis -> analyzing
analyzing -> analysis_completed
analysis_completed -> pending_development
pending_development -> developing
developing -> development_completed
development_completed -> pending_testing
pending_testing -> testing
testing -> pending_development # bugfix reopen
testing -> testing_completed
testing_completed -> pending_release
pending_release -> releasing
releasing -> released
特殊规则:
analysis_completed -> pending_development必须存在 final 的requirement_design和technical_design。pending_development -> developing前必须完成PrepareRequirementWorkspace。testing -> pending_development必须存在 open bug。developing -> development_completed必须底层需求 stage 为ready。releasing -> released必须 release status 为published。- 旧命令创建的
manual_active需求不自动进入 AINative 状态机。
每次需求转换写入 requirement_status_events。
release 状态只允许通过 service 方法推进。允许转换:
manual_release -> pending_testing
pending_testing -> testing
testing -> testing_completed
testing -> stale
stale -> pending_testing
testing_completed -> pending_release
testing_completed -> stale
pending_release -> stale
pending_release -> releasing
releasing -> publish_in_progress
publish_in_progress -> released
releasing -> released
特殊规则:
testing -> testing_completed必须存在当前 release scope 的 passedrelease_test_run。testing_completed -> pending_release必须写入active_test_run_id。pending_release -> releasing必须存在同一 release 和当前 passed test run 的 approvedpublish_confirmation。releasing -> publish_in_progress表示现有 publish 流程已经进入部分完成状态,禁止变更 release scope 或 reopen 相关需求。publish_in_progress -> released或releasing -> released必须 release status 为published且目标默认分支包含 release 代码。- release scope 变化、target branch 外部 commit、测试通过后发生 bugfix、或当前 passed test run 的
requirement + repo + commit快照与 active release 不一致时,旧 test run 失效,release 从testing、testing_completed或pending_release进入stale,重新 integrate 后回到pending_testing。
每次 release 转换写入 release_status_events。
9.1 PrepareRequirementWorkspace
新增 service 方法:
func (s *Service) PrepareRequirementWorkspace(ctx context.Context, keyOrSlug string) (PrepareRequirementWorkspaceResult, error)
语义:
- 只处理已存在 requirement,不 insert 新 requirement row。
- requirement 必须已有至少一个 repo 绑定;否则返回 blocked error,状态保持不变。
- 对每个绑定 repo 执行 fetch,计算 worktree path 为
<requirements>/<req-slug>/<repo-name>,feature branch 使用现有FeatureBranch(req.Slug)。 - worktree 不存在时创建 worktree 并写/更新 requirement repo relation。
- worktree 已存在且是对应 feature branch、无未提交改动时复用。
- worktree 已存在但不是 Git worktree、脏、分支不匹配、feature branch 被其它 worktree 占用时返回可恢复错误,不删除用户内容。
- 任一 repo 创建失败时清理本次新创建的 worktree 和 relation,保留进入方法前已有的 worktree 和状态。
- 成功后由调用方先把
pending_development推进到developing,再创建 development job;该方法本身不推进业务状态。
10. Artifact 管理
artifact 类型:
requirement_designtechnical_designanalysis_reviewimplementation_planimplementation_step_reviewimplementation_reportimplementation_reviewtest_reportbug_reportbugfix_report
版本规则:
- 同一
entity_type + entity_id + artifact_type从 1 自增。 - finalize 使用事务:先清同一 entity 和 artifact type 的 final,再设置目标 artifact final。
- 需求进入
pending_development前必须有requirement_design和technical_design两类 final;analysis_completed只表示 Agent 分析和 Review 达到门槛。
文件命名:
<artifact-type>-v<version>.md
<artifact-type>-final-v<version>.md
用户编辑 artifact 时创建新版本,created_by=user。
CLI 入口为 workspace req artifact create <req> --type <artifact-type> --content-file <path>,也支持 --content <text>;新版本创建后默认不自动 final,用户需要通过 req artifact finalize 或 artifact_finalization approval 选择终稿。
11. MCP server
11.1 Transport
V1 实现 stdio MCP:
workspace mcp serve --home <home> --capability-token <token>
主 Agent 可以用长期 coordinator token;Worker 使用 job-scoped token。
本地健康检查使用:
workspace mcp health --home <home>
health command 生成短期 coordinator capability,通过同一个 Server.Serve stdio JSON-RPC 边界发送 tools/list,要求无 RPC error 且 tools 非空。输出 status=available、transport=stdio、tool count 和 tool names;它不复用用户或 job token,也不执行任何业务 tool call。
stdio scanner 必须设置明确的有界 request limit。V1 上限为 4 MiB,覆盖 artifact/approval 等结构化 payload,同时避免无界内存增长;超过上限时返回 scanner error,不进入 tool dispatch。
11.2 Tool 权限
权限矩阵:
| Tool | coordinator | analysis | coding | testing |
|---|---|---|---|---|
req_submit |
yes | no | no | no |
req_list / req_show |
yes | scoped | scoped | scoped |
req_watch |
yes | scoped | scoped | scoped |
req_assign_agents |
yes | no | no | no |
req_update_workflow_status |
yes | scoped | scoped | scoped |
req_prepare_workspace |
yes | no | scoped | no |
artifact_create |
yes | scoped entity | scoped entity | scoped entity |
artifact_list / artifact_show |
yes | scoped entity | scoped entity | scoped entity |
artifact_finalize |
yes | no | no | no |
job_create |
yes | scoped review | scoped fix | scoped bug |
job_list / job_show |
yes | scoped | scoped | scoped |
job_update |
yes | no | no | no |
job_watch / run_tail |
yes | scoped | scoped | scoped |
approval_list / approval_show |
yes | scoped | scoped | scoped |
approval_respond |
yes | no | no | no |
bug_create |
yes | no | no | scoped |
bug_list / bug_update |
yes | no | no | scoped |
release_create |
yes | no | no | no |
release_test_start / release_test_status |
yes | no | no | scoped |
release_status / release_watch |
yes | scoped | scoped | scoped |
release_integrate |
yes | no | no | scoped |
release_publish |
yes with confirmation | no | no | no |
approval_respond 的 MCP 权限只给 coordinator,worker token 不能代表用户确认。CLI workspace approval respond 不走 MCP 权限矩阵,直接以本地用户身份调用 service;主 Agent 通过 MCP respond 时必须传入“用户在聊天中明确选择”的 structured response,service 将审计字段写成 coordinator relay,而不是 worker 自动决策。
job_update 是 coordinator 管理工具,worker token 不允许自行修改 job 状态,只能通过 runner/service 的受控完成、失败、阻塞和等待用户输入路径推进。bug_update 是 MCP/service 工具,用于测试 Agent 或 coordinator 在 scoped release/requirement 范围内关闭或更新测试 bug;V1 CLI 只提供 workspace req bugs list 和 workspace release bugs list 查询入口,不新增通用 workspace bug update 命令。
release_test_start 对应 CLI workspace release test start <release> [--agent <name>] [--test-command <cmd>],负责通过同一 service 方法创建或排队 release test run。release_test_status 对应 CLI workspace release test status <release>,返回当前或最近 test run、status、test_report artifact id/path、test_command_source 和 pending approval 摘要。release_status 保持 release workflow 总览,不替代 release test 专用状态。
11.3 Tool 输入输出
所有 MCP tools 返回 JSON object,包含:
okdataerrornext_actions
工具失败不 panic,返回可读错误并写 operation log 或 job error。
Artifact tools 使用同一套多态 entity schema:artifact_create、artifact_list、artifact_show、artifact_finalize 的输入必须包含 entity_type=requirement|release|release_test_run 和 entity_id;artifact_show 还必须包含 artifact_id,并校验 artifact 的 entity 与输入一致。Capability token 不只校验 tool 名,还必须按 entity_type 校验 scope:analysis/coding token 只能访问本需求 artifact,testing token 只能访问 scoped requirement、release 或 release_test_run artifact,coordinator token 可以访问所有 entity。testing token 访问 requirement artifact 时,release_test_run_id scope 优先使用 immutable test snapshot membership;没有 test-run scope 时才使用 active release membership。testing token 访问 entity_type=release_test_run 的 artifact、watch 或 status 时,必须校验 token 的 release_test_run_id 匹配,或该 test run 属于 token 的 release_id。输出至少包含 artifact_id、entity_type、entity_id、artifact_type、version、path、sha256、is_final 和 created_by。workspace req artifact ... 只是 entity_type=requirement 的便捷包装,底层仍调用通用 artifact service。
bug_create 在 MCP 和 service 两层校验 requirement membership。带 test-run scope 时 requirement 必须在 release_test_run_requirements snapshot 中;只有 release scope 时 requirement 必须是 active release_requirements membership。相同优先级用于 bug_list、bug_update 和 bug-scoped job_create:只要 token 有 release_test_run_id,bug 的 test_run_id 和 requirement snapshot 都必须匹配,不能先用 release_id 放宽。MCP 省略 test_run_id 时把 capability release_test_run_id 写入请求,显式指定不同 run 时在 service 之前拒绝;同 release 不能替代同 test-run。MCP 未显式提供 created_by_job_id 时使用 capability job_id,service 接受 requirement-scoped job,或 release 和 input release_test_run_id 都匹配的 release_test job,并把该 job id 写入 bug 和 requirement status event。
release-test daemon 解析 provider bug 输出时也必须先做 snapshot resolution:显式 requirement ID/key 与 repo ID/name 均只能解析到当前 release_test_run_requirements 行,不能直接信任正整数 ID,也不能在名称未命中时回退到唯一需求。service 再执行相同 membership guard 作为写入边界。store 在一个 transaction 中创建 bug、推进 requirement workflow、写 requirement status event,并在提供 run ID 时校验 run/job 关系后写 bug_created run event。
当 capability 带 release_test_run_id 时,MCP auth helper 使用 test-run-first 规则:requirement 以 immutable snapshot 判定;job 以 input release_test_run_id 或 bound bug 判定;approval 以 approval test-run 或 scoped job 判定;release-test artifact 只接受 exact run。job_create 对 input scope 执行 default-and-reject。requirement/release watch 在返回前过滤其他周期的 jobs、approvals、bugs、events、test runs 和 active membership;run-scoped token 的 release_test_start 与 release_integrate 被拒绝。只有不带 test-run scope 的 release capability 才能使用 active release fallback。
job_create 的空 input 先规范化为 JSON {},再注入 test-run scope。requirement_status_events V1 没有 test_run_id 列,因此 MCP run-scoped view 通过 event job_id -> agent_jobs.input_json.release_test_run_id/bound bug 归属过滤;不能证明归属的 event fail closed。该过滤同时应用于 req list、show 和 watch,不影响 coordinator 完整审计。
publish_confirmation response 由 service 先规范化和校验:choice=confirm 生成 approved + confirm=true,其他 approved response 必须从最终 response JSON 读到 true confirmation,否则保持 pending。store transaction 再更新 approval,并在 commit 前写 release status event;approval 带 run scope 时同时写 approval_responded run event。approve/cancel 使用标准 <approval_type> approval <status> reason,reject 保留 release 当前状态与 next action 的专用诊断。任何 event insert 失败都回滚 approval response。
缺测试命令的新 test cycle 使用 CreateReleaseTestRunAwaitingCommand:同一 transaction 写 release_test_runs、从 active release scope 复制 release_test_run_requirements、创建 scoped test_command_missing approval,并写 approval-request release status event。daemon 不再先创建 run 后补 approval;对历史 waiting_user_input run 仍幂等执行 approval ensure 以自愈旧数据。
有测试命令的新 cycle 使用 CreateReleaseTestRunWithSnapshots,并与 awaiting-command 路径共享 createReleaseTestRunWithSnapshotsTx。daemon 在 queued/waiting run 上比较 snapshot 的 requirement/repo 集合、repo name、feature branch/SHA 和 release SHA;缺失、部分或不匹配时通过 test-run/status-event transaction 阻塞旧 cycle,不能创建 provider job。
invalid failed-output 使用 BlockInvalidReleaseTestOutput transaction,同时写 blocked test run、release_test_output_blocked run event、failed agent run、blocked job 和 release status diagnostic。service CreateBug 对 test-run scope 的空 repo 执行唯一 repo resolution,因此 daemon 和 MCP 共用同一个 concrete repo invariant。publish-confirmation specialized store responder重复校验 approved response JSON,generic responder 检测该 approval type 后委托 specialized path。
CreateHumanApprovalRequest 对 publish_confirmation 强制 initial status 为 pending,封闭 create-time terminal bypass。MCP test-run bug_create 通过 GetRunningAgentRunForJob 取得 capability job 的 active attempt,并把 run ID 传入 CreateRequirementBug transaction;没有 active run 时 fail closed。release worktree dirty 与 invalid-output 最终都调用 BlockReleaseTestExecution:它原子写 test-run block、可选 run event/run failure、job block 和 release event,适配 provider 启动前无 run 与结束后有 run 两种时序。
test-run-scoped MCP bug_create 先把 created-by job 绑定为 capability job,显式不同值 forbidden;canAccessBugCreate 重复校验。service 要求 TestRunID 同时携带 job/run 并验证归属,store 在 transaction 前重复 required-field guard。completeReleaseTest 对 parseReleaseTestOutput 的所有错误统一调用 BlockInvalidReleaseTestOutput,不再把 malformed output 送入普通 post-run retry。
release test completion 只接受 workflow_status=testing 且该 release 最新的 passed test run;同一 testing_completed + active_test_run_id 调用直接返回且不写重复 event。release scope、requirement reopen、feature/base/release branch 或 snapshot 变化进入 stale 时,AINative 路径在同一事务写 legacy status、workflow status 和 release event,manual release 继续保留 legacy workflow。stale 写入失败必须原样传播,不能只返回语义 stale error。bugfix 后的 re-integrate/retest 扫描 workflow_status=stale,并兼容历史 workflow_status=testing + status=stale 数据。
12. CLI 命令面
新增命令:
workspace agent add <name> --provider codex|claude --role coordinator|analysis|coding|testing
workspace agent list
workspace agent show <name>
workspace agent update <name>
workspace agent health <name>
workspace agent remove <name>
workspace worker add <name> --role analysis|coding|testing --agent <agent>
workspace worker list
workspace worker update <name> --parallelism <n> --max-workers <n>
workspace worker enable <name>
workspace worker disable <name>
workspace ai start [--agent <name>]
workspace agent daemon start
workspace agent daemon status
workspace agent daemon stop
workspace mcp serve
workspace job list [--status queued|running|failed|waiting_user_input|blocked]
workspace job show <job-key>
workspace job watch <job-key> [--follow]
workspace job retry <job-key>
workspace job cancel <job-key>
workspace run tail <run-id> [--follow] [--raw] [--unsafe-unredacted]
workspace req submit <title> [--description <text>] [--repo <name>]
workspace req watch <req> [--follow]
workspace req assign-agents <req> --analysis-agent <name> --coding-agent <name> --test-agent <name>
workspace req prepare-workspace <req>
workspace req artifact create <req> --type <artifact-type> [--stage analysis] [--title <title>] [--content <text>|--content-file <path>]
workspace req artifact list <req>
workspace req artifact show <req> <artifact-id>
workspace req artifact finalize <req> <artifact-id>
workspace req advance <req> <workflow-status>
workspace req bugs list <req> [--status open|fixed]
workspace artifact list --entity-type <requirement|release|release_test_run> --entity-id <id>
workspace artifact show <artifact-id>
workspace release create <title> --req <key> [--req <key>] [--key <slug>] [--test-command <cmd>]
workspace release test start <release> [--agent <name>] [--test-command <cmd>]
workspace release test status <release>
workspace release status <release>
workspace release watch <release> [--follow]
workspace release bugs list <release> [--status open|fixed]
workspace approval list [--status pending]
workspace approval show <approval-key>
workspace approval respond <approval-key> --choice <choice> [--message <text>] [--response-json <json>]
workspace approval respond <approval-key> --choice approve --final-requirement-design-artifact <id> --final-technical-design-artifact <id>
workspace approval respond <approval-key> --choice approve --test-command <cmd>
workspace approval respond <approval-key> --choice approve --confirm
workspace approval respond <approval-key> --choice approve --scope <scope> --expires-at <time> --sandbox <mode> --approval-policy <policy>
旧命令继续可用。README 和帮助文本必须明确 AINative 命令是高级协作模式。
13. 阶段 Loop 算法
13.1 分析 Loop
create analysis_generate job
for round in 1..max_review_rounds:
analysis agent writes requirement_design and technical_design artifacts
create analysis_review job
review result = read review artifact
if policy passes:
mark analysis_completed
stop
create analysis_revise job with review artifact as input
mark blocked if max rounds exhausted
13.2 开发 Loop
ensure final requirement_design and technical_design exist
call PrepareRequirementWorkspace
mark developing
derive development cycle from final technical_design artifact
create implementation_plan job for the cycle
for each step:
create cycle-scoped implementation_step job
run coding agent in requirement workspace
if result contains implementation_blocker.reason:
create implementation_blocker artifact
atomically create continue/replan/block approval and block source job
stop the development loop pending user decision
create cycle-scoped implementation_step_review job
if review passes:
continue
create cycle-scoped implementation_step_fix job
after all steps:
create implementation_report job from current-cycle steps and reviews only
call FinishRequirement
if requirement stage ready:
mark development_completed
首个开发周期保留既有不带 cycle suffix 的 job key;后续周期的 plan key 绑定新的终稿 technical_design artifact,step、Review、fix 和 report key 使用新 implementation_plan artifact ID 作为 suffix。Review 轮次和报告聚合都必须按 implementation_plan_artifact_id 过滤,旧周期作业无论成功、失败或仍排队,都不能影响当前周期。
调度器在 queued stale job 清理、claim 后、provider 启动前和 provider 运行期间执行 current-cycle check。运行中的 development provider 使用可取消 context;requirement 离开 pending_development|developing,或 source plan job 绑定的 technical design 不再是当前终稿时,daemon 取消 provider 和 job,恢复 worker idle,并且不进入失败重试或 success post-processing。
implementation_step 和 implementation_step_fix job input 的 result_contract.blocked 声明 implementation_blocker 对象,至少要求非空 reason,可选 title、Markdown content 和用户决策 prompt。同一次 run 的 post-processing retry 复用同一个 blocker artifact 和 pending approval;新的 run 再次阻塞时创建新 artifact version 和 run-scoped approval key。同一 requirement 的不同 source job 不能复用 pending blocker approval。approval、approval_requested 实时事件和 source job blocked 状态在同一 SQLite 事务内提交。
13.3 测试和 bugfix Loop
release integrate
create release_test_run with resolved test_command
verify every release repo worktree is clean
if any worktree is dirty:
block release_test job and test run
write release diagnostic event
stop before provider starts
run testing agent in release workspace
verify every release repo worktree is still clean
if testing agent changed a worktree:
reject provider result
mark provider run failed
block release_test job and test run
write release_workspace_modified run/release events
wait for explicit cleanup and retry
if no command can run:
create test_command_missing approval
mark test_run waiting_user_input
if user provides test_command:
save supplied command
mark test_run queued
return to release test claim
if user chooses block:
mark test_run blocked
stop
if bugs found:
for each bug:
in one store transaction:
create requirement_bug
set requirement pending_development
append requirement status event with actor/reason/source job
rollback bug and workflow if event write fails
create bugfix job for coding agent
req reopen
coding agent fixes feature branch
req finish
release integrate again
rerun test
else:
mark requirements testing_completed
mark release testing_completed with active_test_run_id
create publish_confirmation approval for active_test_run_id
mark release pending_release
mark requirements pending_release
14. 安全与恢复
- Worker 默认不使用 danger-full-access。
- workspace-write provider 不以包含
workspace.db的 workspace home 作为 CWD;无业务 workspace 的 job/main session 使用 runtime scoped 隔离目录,业务 workspace 和 artifact 目录在 provider 启动前完成显式 preflight。 - Provider API key 不进入 workspace-cli DB。
- MCP capability 使用 256-bit 随机 opaque token,数据库只保存 SHA-256 hash、scope、过期时间和撤销状态;不再把可签发新权限的共享 secret 放入 config。token 不写入 artifact、
agent_runs.command或 provider events;provider 执行前保留真实参数,持久化 command/event 使用 exact-token[REDACTED],通用 redactor 识别 JSON argv 和 standalone capability,以保护 MCP 默认 raw tail。主 Agent session 结束时撤销该 session 的全部 token,每次 MCP 调用都重新查询 token 状态。 - daemon 持有 Provider control-plane Unix socket 和 SQLite 连接。Worker 内的 MCP stdio 进程仅使用 job token 代理 socket 请求,不读取 workspace DB;Codex 强制使用原生 filesystem sandbox,Claude 使用外层 OS allow-list sandbox。隔离后端不可用时必须 fail closed。
- Worker token 绑定 job 并按 lease 设置短期过期时间;成功、失败、取消或等待人工输入后统一撤销。main Agent token 轮换成功后立即撤销旧 token。
- Provider 终态优先级固定为进程失败/取消、协议错误、合法 approval、成功结果;approval 不得覆盖非零退出或协议错误,多个 approval 必须失败。
- Job 的实际 CWD 只能从数据库登记的 requirement feature worktree、release worktree 或 job-attempt runtime 派生。
input_json.workspace_path是只读诊断字段,Worker 不得提交,coordinator/历史值必须与派生路径 canonical-equal;workspace home、DB parent、runtime root、其他 worktree 和 symlink escape 全部拒绝。 - Provider permission 只调整 code-workspace policy;
danger-full-access被规范化为当前登记 worktree 内的workspace-write,永远不能解除 control-plane envelope。 - Worker capability 在 run 启动后绑定 run ID;heartbeat 只有在 job lease 尚未过期、lease owner 和 Worker current job 都匹配时,才能原子续期 lease 和仍未过期的 run-bound token。lease 一旦到期不可复活,只能由 reconciliation 收敛后重新 claim。job/run 终态原子撤销 token;lease recovery 同时收敛 job、run、worker、event 和 capability,并保证每个 job 最多一个 running run。
- migration 0010 修复历史 permission workspace policy,并在建立 running-run 唯一索引前收敛 queued、blocked、waiting、terminal 和 lease-expired job 的 orphan run。Block、Cancel、resume、retry、approval resume 和新 run 创建都执行同一单 job reconciliation,终态事件使用每个 run 的下一个
event_seq。 - migration 0011 继续收敛没有 running run 但仍被 Worker 引用或持有未撤销 token 的 queued/terminal Job,并清理引用不存在 Job 的 Worker、run 和 capability。daemon recovery 使用同一 residual reconciliation。
- Worker capability 只能通过 lease-bound transaction 签发:Job 必须 active、owner 必须匹配、lease 必须严格未过期、同一 Job 不得已有 active token,token expiry 必须等于数据库 lease expiry。不存在
now + 固定时长fallback。 - Retry、Requeue 和 Resume 必须在同一事务断言不存在有效 lease 或 running run;live Job 返回 ownership conflict。daemon 在普通失败重排队前先把 active Job 原子终结,ownership-lost 只进入 reconciliation。
- heartbeat 必须恰好续期一个当前 run-bound token;Provider 尚未创建 run 时只允许唯一 unbound token。token 数量为零或大于一时整个 heartbeat 事务回滚。
- active job/run 聚合必须同时验证 Job active 状态和未过期 lease。succeeded run 的 reconciliation 不写
error,原因只保留在 terminal event。 - Worker sandbox 的执行值只允许
read-only或workspace-write。Agent 配置、permission grant 或调用方传入的danger-full-access只保留审计值,daemon 与 CodexRunner 都必须防御性规范化为当前登记 worktree 的workspace-write;该限制不改变用户主动启动主 Agent 的独立交互权限模型。 - Provider workspace 的每个路径组件都必须通过
Lstat;macOS 仅允许/var -> /private/var、/tmp -> /private/tmp、/etc -> /private/etc固定系统别名,任何业务父级或最终节点 symlink 都拒绝。Provider 启动请求在签发 capability 前再次检查路径组件。 - job-scoped token 到期后不可继续调用工具。
- provider permission grant 到期或 scope 不匹配时不可提升 sandbox/approval policy。
- release test provider 前后都必须校验每个 release repo worktree clean;发现修改时只阻塞并保留现场,不执行自动 reset/clean。
- daemon 重启后可根据 job lease 恢复。
- provider 输出过大时只保留文件路径和摘要,避免 DB 膨胀。
- release publish 前仍必须通过现有 dirty guard 和 external commit 检查。
release_publish必须校验同一 release 和当前通过的 release test run 已存在 approved 且confirm=true的publish_confirmation,并校验当前 active release 的 requirement 集合、repo 集合和每个 requirement+repo 的提交与该 test run 的release_test_run_requirements快照一致;没有确认、用户拒绝或快照不一致时返回可读错误并保持pending_release或转入stale,但已处于publish_in_progress的 release 只能返回 manual handling,不能自动降级为stale。- release publish 成功必须复用现有语义把 release 代码合并到目标默认分支
main或master,然后才能把 AINative requirement 标记为released。 - publish-in-progress 优先级保持高于 stale。
15. 测试策略
- Store 单元测试:migration、默认 review policy、artifact final partial unique、job lease、requirement/release status event、release test run scope、provider permission grant。
- CLI 单元测试:agent/worker/job/req artifact/release test 命令面。
- Provider 测试:fake runner 覆盖成功、失败、超时、JSONL 解析。
- Run event 测试:fake runner 输出多条事件时,
agent_run_events按顺序保存,watch API 只返回新增事件。 - Coordinator 测试:parallelism、max_workers、lease 过期恢复、retry 上限。
- MCP 测试:tools/list、tool call 成功、capability token 越权拒绝。
- Approval 测试:需求澄清创建 pending request,用户 respond 后 job 恢复或取消;方案定稿 approval respond 后两类 artifact 在同一事务中 finalize;
test_command_missingapproval 绑定release_test_run_id,用户补充命令后同一 test run 恢复 queued;publish_confirmationreject 保持pending_release,confirm=true 且 test run 的 requirement+repo+commit 快照一致后才允许 publish。 - Provider 配置测试:Codex runner 生成 job-scoped
config.toml、通过-c mcp_servers.workspace_cli.*注入workspace mcp serve且不覆盖CODEX_HOME;Claude runner 使用--mcp-config。 - 集成测试:临时 bare repo 跑完整
submit -> clarification approval -> analysis -> artifact_finalization approval -> pending_development -> developing -> coding -> req finish -> release integrate -> test_command_missing approval -> test bug -> reopen -> publish_confirmation approval -> publish。 - 回归测试:现有
go test -count=1 ./...必须继续通过。
16. Review 加固实现
- Review policy 通过 store/service/CLI/MCP 管理,
no_findings在持久化前规范化为max_allowed_severity=none;需求绑定时校验阶段匹配。 requirement_clarification响应可原子替换 description、acceptance criteria、priority 和 repo bindings,并与 approval、job 恢复、审计事件一起提交或回滚。- 生产 daemon 将 provider job 异步执行,调度 tick 继续按最短 pool interval 运行;claim 容量为
min(parallelism,max_workers)-active_jobs。 - provider 启动成功后才消耗一次性权限 grant;启动后的输出、协议或持久化错误必须终止进程并收敛 run/job 状态。
- capability 必须带非零到期时间。配置、数据库、token 配置、runtime 日志和 provider 输出使用 owner-only 权限;raw tail 每次读取严格受
max_bytes限制。 - migration 0006 保存 daemon 单实例 lease、PID、heartbeat 和停止状态;后台 daemon 只回收本实例 worker。主 Agent MCP 使用 0600 capability file 定时轮换,并通过 session 状态即时撤销。
- requirement job priority 使用
requirement_priority * 1000 + stage_priority,既保证跨需求优先级,也保持同一需求逐步实施和 Review 顺序。