@dongfanglin/openspec-agentic
v0.4.0
Published
OpenSpec agentic workflow extension: schema, role models, installation and migration.
Maintainers
Readme
agentic 扩展(@dongfanglin/openspec-agentic)
本扩展是 OpenSpec 的 agentic 工作流扩展。
标准流程(proposal → specs/design → plan → tasks → apply → verification → archive)
仍由 OpenSpec 执行;本扩展负责安装与升级、agentic schema、角色模型解析、E2E 留证与流程结构检查。
流程结构检查:openspec-agentic workflow check --change <name> --stage plan|premerge|final|archive --json。计划阶段会检查 Main E2E 决策、依赖声明审查(开工前门禁)和项目配置;premerge 在候选提交上核对固定基线、Verify、独立 review、worktree 交接与 premerge 历史;final 再逐交付单元核对 premerge PASS,最终阶段只接受显式 --stage final 的 E2E 执行记录。配置错误直接阻断检查。
关键分支可从 assets/openspec/schemas/agentic/ci/github-premerge.yml 安装 PR 检查,并将 agentic-premerge 设为受保护分支的必需状态,同时要求合入前同步目标分支;PR 正文用 Agentic-Change: <name> 指定变更。归档前仍须运行 --stage archive 并复核语义验收。直接执行的 Git 合入或上游归档命令不受本包拦截。
它只读核对意图基线、需求覆盖引用、唯一门禁任务,以及最终目标、契约和证据摘要。
新 E2E 记录绑定规划契约,修改需求或计划后不能直接沿用旧记录。字段、兼容性和受控入口接法见
检查协议,填写方式见
完整变更示例。机械 PASS 不替代语义验收,
也不会自动拦截上游合并/归档;需要强制执行时由项目受控入口或 CI 调用。
安装
新项目一条命令:
npx @dongfanglin/openspec-agentic@latest init . --tools codex已经装过旧版 FluentSpec 的项目,一条命令完成迁移:
npx @dongfanglin/openspec-agentic@latest update .init 会依次完成:
- 校验 Node / npm;
- 把
@fission-ai/openspec(精确1.13.0)与本扩展作为项目本地 devDependencies 安装; - 调用
openspec init; - 安装
agenticschema; - 合并
openspec/config.yaml(引擎读的schema/context/operations,不含扩展配置); - 按
assets/openspec/agentic.yaml模板创建openspec/agentic.yaml:8 个常设角色初始化为@current,并写入dispatch.pool与e2e默认值; - 安装
.agents/skills/agentic-verify; - 合并
AGENTS.md; - 写
openspec/.agentic-install.json; - 安装后校验。
任一步失败会回滚本次写入,不留下半成品。
init / update 的选项:
npx @dongfanglin/openspec-agentic@latest update . --prefer openspec # 新旧配置冲突时的显式裁决(update)
npx @dongfanglin/openspec-agentic@latest init . --force # 覆盖被本地修改过的受管文件
npx @dongfanglin/openspec-agentic@latest init . --no-install # 离线:假定两个依赖已在项目本地
npx @dongfanglin/openspec-agentic@latest init . --dry-run # 只报告将要执行的动作--tools <host,...> 透传给 openspec init(缺省为 none,不生成任何宿主专属文件)。
日常使用
宿主入口由 OpenSpec 提供,本扩展不新增入口:
/opsx:propose/opsx:apply/opsx:verify/opsx:archive
/opsx:apply 的合入默认发生在本地主分支:候选验证通过后无需逐单元人工批准,合入后完成本地
主分支检查。远端推送是独立操作,只有明确要求并授权时才执行;即使计划远端交付,也先完成本地合入。
终端里统一使用项目本地 OpenSpec(init 已把它装为项目本地依赖,因此不需要联网,也不会用到全局版本):
npx --quiet --no-install openspec status --change add-export
npx --quiet --no-install openspec instructions apply --change add-export --json
npx --quiet --no-install openspec validate add-export --strict项目适配上下文
openspec/config.yaml 的 context 是稳定的项目画像,而不只是 agentic 配置说明。模板按
Repository Structure、Standard Commands、Engineering Constraints、Runtime Environment
组织待适配项;新项目不应把“未配置”当作事实或自行猜测,可先让隔离的 scout/recon
只读采集,再由 main 确认并写入。某次变更的文件范围、提交、工作包、临时资源和检查结果仍分别写入
plan.md、tasks.md、verification.md,不进入全局 context。
init / update 只补缺失配置并保留项目已有 context;通用工作流正文留在 schema,all_done 和
归档兜底留在 operations.*.guidance(属于引擎的 openspec/config.yaml),
扩展自己的配置——角色模型、并发派发、E2E 开关——全部住在 openspec/agentic.yaml。
E2E 校验开关
init 会在 openspec/agentic.yaml 写入项目级开关 e2e,默认开启;存量项目执行一次
update 也会迁移/补上该键。
e2e:
enabled: true # true:每次变更的 Main E2E mode 必须为 required
command: "" # 可选:项目真实 E2E 命令或入口
maxAttempts: 3 # 同一变更连续失败的 E2E 重试上限;达到后停止自动重跑,须用户介入maxAttempts(默认 3)限制“E2E 失败 → 修复 → 重跑”的循环:同一变更连续失败达到该值后,e2e run拒绝再开自动尝试并返回退出码2,e2e check判BLOCKED,任务保持待办、 阻断验收与归档;此时必须把问题、已尝试方案和证据交用户决策(提高上限或调整方案), 不得删除或改写记录绕过。候选与最终阶段的失败尝试共同计数;人工记录(--manual)不执行命令,不计入。- 开启(含缺省)时,agentic 变更的计划必须把 Main E2E 判为
required;只有用户显式批准降级, 才能在plan.md的downgrade_approval记录批准原话、时间与来源后写not-applicable。 缺少该记录时计划无效,最终验收判 FAIL 并要求回写为required。 - 关闭后,变更按原有判据自行选择 mode;
not-applicable仍需理由、依据和通过的非空替代检查。 - 读取当前开关(每次从磁盘读取,不缓存):
npx --quiet --no-install openspec-agentic e2e
npx --quiet --no-install openspec-agentic e2e --json一致性检查(比对开关与每个已完成变更 plan.md 的 Main E2E 判据,并核对 required 变更是否已有成功执行记录):
npx --quiet --no-install openspec-agentic e2e check --change add-export # 只查一个变更
npx --quiet --no-install openspec-agentic e2e check --json # 查全部未归档变更结论为 PASS / FAIL / BLOCKED;查全部模式下 IN_PROGRESS(任务未全部完成)与 SKIPPED(非 agentic
变更)不参与判定、不阻断,指定 --change 时未完成的变更判 BLOCKED(仅扩展拥有的最终 E2E 行与正在
执行的最终验收行 [final-verification] 允许保持待办)——单变更检查是 E2E 任务的完成
条件,不能让未完成状态被平凡判为 PASS;非 PASS 时命令以非零状态退出。它只做结构比对,不读
verification.md,不证明测试真实性;它自身不调用 archive,但判 PASS 时按 [e2e-owned] 回写的任务框会让
openspec archive 的"未完成任务阻断"生效。要防伪造仍需在 CI 或分支保护里重跑真实 E2E。
未指定 --change 时每个变更需要一次引擎调用,耗时随变更数增长。
只读核查(用户只要求检查、不更新进度)用 --no-write:检查照常判定但不回写 [e2e-owned] 行。
--run-if-missing 把检查升级为“确保执行”:required 变更没有新鲜成功记录时,先真实执行
e2e.command 并写记录,再给出判定(执行输出走 stderr,--json 的 stdout 仍是纯 JSON)。
需与 --change 连用;执行成功后若仍有除最终 E2E 行与最终验收行外的任务未勾完,判 BLOCKED,勾完复查才 PASS。
npx --quiet --no-install openspec-agentic e2e check --change add-export --run-if-missing流程内执行 E2E(这是 apply 阶段的 E2E 任务,与编码、代码检视同属一个阶段,不需要等 CI 或归档):
npx --quiet --no-install openspec-agentic e2e run --change add-export # 用 e2e.command
npx --quiet --no-install openspec-agentic e2e run --change add-export --stage final # 最终主分支完整 E2E
npx --quiet --no-install openspec-agentic e2e run --change add-export --command "npm run e2e -- --grep @final"
npx --quiet --no-install openspec-agentic e2e run --change add-export --planning-root ..\main-repo # 测试 worktree 中写回权威规划根
npx --quiet --no-install openspec-agentic e2e run --change add-export --manual --by tester-A --evidence reports/manual.md --result pass --cases E1,E2规划根与代码目录分离:--planning-root <路径> 指定权威规划目录(存放 openspec/changes 的仓库/store),
命令仍在当前目录(代码 worktree)执行,记录统一写回权威变更目录。在独立测试 worktree 中执行时必须
显式传入主仓库的规划根,不要用当前目录推断变更位置,否则会解析到 worktree 中的非权威副本,
变更未提交时甚至找不到。--planning-root 同样作用于 e2e check,使检查与回写都针对权威规划。
命令在当前项目根执行,输出实时透传;退出码 0 通过、1 E2E 失败、2 无法执行(缺命令/缺变更/参数不完整,或已达连续失败重试上限)。
无论通过还是失败,都会在变更目录下写一条机器记录(openspec/changes/<变更>/e2e/run-*.json,含命令、
退出码、提交、阶段与输出片段;人工路径记录执行人、证据引用、结果与用例范围),随变更一起归档。
执行前若变更目录之外的已跟踪文件存在未提交改动,e2e run 直接以退出码 2 拒绝执行:未提交内容无法绑定到
提交,记录会失效;e2e check 也会把“执行时产品已脏”或“记录之后又出现未提交改动”的记录判为失效。
--stage candidate|final
标注记录属于候选还是最终阶段,候选记录不满足最终门;本流程只在最终阶段产生记录,候选标记仅用于项目自有 CI。人工路径用 --result pass|fail|blocked 与 --cases <范围>
显式记录结果与用例范围;人工记录不参与自动重试失败计数,一条人工 pass 不能隐式解除自动失败上限。
required 的变更若没有成功记录、
或者只有人工记录而项目已配置 e2e.command、或者成功记录的命令与配置不一致、
或者最近一次相关尝试失败(更新的失败不会被更早的 pass 掩盖)、或者只有候选阶段记录、
或者记录停在旧提交之后又改了代码,e2e check 都会判 FAIL。
e2e check --change <变更> 是 最终 E2E 门禁行的完成条件:它要求其余任务已完成,但允许扩展拥有的该行
与正在执行的最终验收行([final-verification])保持待办,避免二者互相死锁;判 PASS 时它自动勾选带 [e2e-owned] 标记的该行
(行级单一所有者:该行归扩展,其余任务行归主 Agent);非 PASS 时该行由扩展回退(若原为已勾选)或保持待办,
两种 mode 都保留该行:required 时它是最终主分支完整 E2E 的门禁检查行;not-applicable 时它只确认
“不适用判据已按计划固化”,实际替代验证另列为主 Agent 拥有的任务(未完成时检查判 BLOCKED,不会被误勾)。
按"未完成任务阻断验收"的既有规则在 apply 内拦下,不在归档阶段补做。没有现成记录时先用
--run-if-missing 在流程内真实执行一次再判定。
这条自动回写给的是“流程阻断与默认确认提示”,不是不可绕过的 CLI 硬门:没跑 E2E/替代验证没做完时该框保持待办,
openspec archive 会据此提示并默认要求确认;但固定版本的上游引擎在确认后仍可用 archive --yes 带未完成任务继续,
本仓库的引擎契约测试也验证了该路径。因此复选框只是宿主流程义务,需要真正强制时使用受控归档入口、CI 或分支保护。
标记由任务模板生成;多条 [e2e-owned] 会使检查判 BLOCKED,不猜测。
开关是流程义务,不是 CLI 门禁:扩展只读取并校验配置、只读地核对计划与执行记录,不判断测试真实性,也不阻止归档;
判据正文见 agentic schema 的 plan/apply instruction 与 procedures/acceptance.md。
最终验收(tasks 的 [final-verification])沿用 OpenSpec 的“复选框 + 提示词”模型:不勾选会被
openspec archive 的未完成任务门拦下,但扩展不对该标记做存在性/唯一性机器校验,也不校验验收结论的真实性,
与上游 /opsx:verify 同级;需要不可绕过的强制时同样落到 CI 或分支保护。
并发编码(流水线与调用窗口)
用只读调度状态视图查看池占用、逐包状态、阻塞原因、待确认条件、接收/心跳诊断及下一步建议:
npx --quiet --no-install openspec-agentic workflow status --change add-export
npx --quiet --no-install openspec-agentic workflow status --change add-export --json
# 在代码 worktree 中读取独立的权威规划根
npx --quiet --no-install openspec-agentic workflow status --change add-export --planning-root ..\main-repo --json优先准备队列按未完成的 code/contract 传递下游数量、最长依赖链、计划顺序排序,受池容量和
已知独占资源冲突约束。它是准备/派发建议,不是耗时预测或开工授权;实际开工前仍核实基线、
冻结契约、资源和 worktree。视图识别已接收的同单元集成基线:核对本轮交付、Verify、独立 review、
规划摘要、报告哈希及提交包含关系后,下游可提前准备开工。缺结构化证据时 main 仍按原规则核实,
跨单元 code 依赖仍要求上游合入。plan 门禁非 PASS 时无首次开工建议;视图不写任务、台账或证据。
JSON 的 result 表示视图所核对的规划/配置结论,recommended 是本轮优先准备 ID,
rankedPending 是全部 pending 包的依赖优先顺序,packages 保留逐包阻塞和待确认条件。
integrationBaselines 列出基线有效性与失效原因;mergeQueue 按完整单元列出候选准备状态,
recommendedMerge 每次只列一个优先候选验证单元。它要求本轮源交付、Verify/最新独立 review 有效,
不等于 premerge PASS 或允许立即合入。计划 Order 全为整数时遵守顺序组,同值按可解锁 code 下游数、
传递下游数、最长链、表序排序;全部留空时视为同组,文字或混合顺序保守沿用表序。
基线由 merger 返回可选 integration_baseline,main 确认后 workflow record 登记接收;
基线同时绑定 contractDigest 与包含冻结契约内容的 planningDigest;集成交付索引的后续失败或失效撤销解锁。
结构和示例见 角色共用报告契约。旧报告不要求迁移。
退出码 0 表示规划/配置 PASS,1 表示不一致,2 表示材料/解析不可用;无可准备包不等于检查失败。
并行不再按“批次一起出发、整批到齐才进下一批”,而是按流水线 + 叫号窗口:谁空谁接下一个能开工的工作包,
避免快任务干等慢任务。计划里的 ## Execution Waves 仍用于静态登记每个工作包的最早可开工层级与
Serialization Reason(无理由串行会被判不合格),但运行期不再按批次互等,而是按依赖就绪逐个开工。
项目配置(openspec/agentic.yaml):
dispatch:
pool:
coding: 3 # 编程流水线数量(默认 3)
testing: 2 # 测试流水线数量(默认 2)- 不再有
mode与maxConcurrency,也不再声明宿主并发能力:默认宿主支持并发, 没有“宿主不支持并发所以串行”的退路。 - 池子大小是上限不是目标:有几个能开工就开几个,空窗口不补; 台账在开工时按角色统计占用,达到上限就拒绝新的开工(等窗口释放)。
dispatch.pool限制的是并发工作包数量,不是全部子 Agent:只统计 coder/tester 工作包, 工作包处于编码中/检视中/修复中都占一个窗口,进入待合入/已合入/受阻/退役后释放(reviewer 在同一窗口内接替作者)。- 辅助角色(merger、validator、scout、provisioner)不计入该上限,因此同一时刻实际运行的子 Agent 数
可能超过
coding + testing。若要限制实际 Agent 总数,需在宿主/项目层另设总上限,本包不提供。 - 池按计划
Role列的车道统计:只有Role: tester(或 Owner 含test)走 testing 车道,其余归 coding 车道; 旧键pool.coders/pool.testers仍兼容,新键优先;两者同时出现且取值不同会报错。
能开工(Ready)的四个条件
- 依赖就绪:同一交付单元内
code:依赖的上游已进入已验收集成基线;跨交付单元的code:依赖要求上游 已合入主分支(不是“编码写完了”)。已验收集成基线 = 固定提交 + 包含上游交付提交 + 必要的 Project Verify 与独立 review 已通过 + 主 Agent 已接收;仅 merger 建了个集成提交不算; - 依赖接口已冻结且可读;
- 需要的运行态资源空闲;
- 该工作包状态为“未开工”。
上游工作包“已验收”不等于“交付单元已合入”:不得为启动同单元下游而提前把上游台账标为 merged。
主 Agent 是唯一调度台(单线程,无锁):流程开始时算一次,之后每有一个工作包合入就重算,
有空窗口就补人。工作包之间的依赖写在单个 WP 上并标注 code: / contract: / resource:,
不写“整批依赖整批”。
文件与资源的区别
| 重叠类型 | 性质 | 处理 | | --- | --- | --- | | 文件写入范围 | 软冲突:worktree 能并行写,冲突在合入时出现 | 登记合并负责人与合入顺序,后合入方重验;不作为串行理由 | | 运行态资源 | 硬互斥:worktree 隔不了端口、数据库、缓存、外部服务 | 必须隔离,隔离不了就排队独占 |
计划的最低机械保证
Main E2E: required时,Work Packages 至少有一个Role: tester的测试工作包(TP);- 每个工作包的
Reviewer非空且不得等于Owner(不得自审); - tasks 里每个工作包都有一条引用它的独立 review 任务(带
[CR…]或“检视/复核/review”); - plan 必须有
## Independent Validation表(Task / Target Revision / Assignment / Pass Condition / Report Path 字段不得为空), tasks 里必须有唯一一条[validation]任务;validator 是常设角色,没有“不适用”取值。
状态落盘,防止重复开工
每个工作包一张状态表,必须落盘(会话中断或压缩后要靠它接着数):
未开工 → 编码中 → 检视中 → 待合入 → 已合入
↘ ↘ ↘
修复中(未交付/打回/回归失败) → 检视中
任意非终态 → 受阻(blocked,释放窗口,可恢复)
任意非终态 → 已退役(superseded,终态;计划演进时退役旧 WP)核心不变式:每个工作包在任意时刻最多一个实例。同一状态再派一个属于错误;
未交付崩溃(编码中)、检视打回、候选验证失败、合入后回归失败、上游变化或从受阻恢复时,
都可用 --reopen --reason <原因> 打回“修复中”,由新的实现实例重做;--retry-kind 区分
implementation / contract / environment / runtime,每类上限 3,Attempt 持续递增;旧无类型调用仍计实现额度。
blocked(受阻)会释放窗口、可恢复;计划拆包/删包/改 ID 时,三处必须一起改:plan.md 的 Work Packages 与
Execution Waves 行、tasks.md 里该 WP 的 [wp:…] 派发任务行,以及台账。旧工作包用
--state superseded --reason <原因> [--superseded-by <新WP,...>] 退役(拆分可写多个后继),不能直接抹掉台账;
历史产物(verification 的对账/检视行)引用已退役工作包会被放行。
流水线内的角色流转
- coder 交付 → 立即销毁 → 在同一窗口创建 reviewer,不等待、不并行保留;
- reviewer 是全新实例:只读、固定提交、不继承 coder 上下文、不得与作者同一实例;
- 检视通过 → 释放窗口,工作包进入“待合入”;
- 检视不通过 → 工作包进入“修复中”,主 Agent 起新的修复实例(原 coder 已销毁,天然是新上下文), 输入必须包含原提交与 diff、review 报告、契约与允许写入范围;修复后再换一个全新 reviewer 复核;
- 子 Agent 之间不直接对话,所有传递由主 Agent 转交固定产物(提交、diff、review 报告), 保证可审计且不破坏检视独立性。
测试流水线同样拆成两个事件:tester 写完用例并交出基础检查与 handoff、主 Agent 确认可读且交接完整后
即释放实例(不等待 review PASS);阶段完成在非用例作者的 reviewer 报告落盘并被主 Agent 接收后判定。
execute / retest 每轮独立派发都新建实例(不是每条用例都新建),从当前最终主分支、用例/产物版本、
本轮 E2E ID 与资源恢复上下文,retest 另附原问题 ID、失败证据、修复提交与 review 结论;
每轮只允许一次聚合 E2E 入口调用。测试工作包(TP)按功能域/用户路径划分,不按 WP 划分。
任务勾选只能由主 Agent 在 review 通过之后执行;子 Agent 不修改计划、任务与验收记录。
检视与合入
- coder 一交付即并行检视;合入前只审 rebase 新产生的冲突解决与新增交互,不重审整份改动。
- 逐包流水线:各 WP/TP 交付后立即独立启动自己的 reviewer,不等待同层所有 coder/tester 完成。 apply 只为当前依赖满足且有流水线容量的包准备 worktree 和必要依赖,逐包就绪即派发。 契约阻断项集中修订后复审;仅记录格式错误由 main 修正并重跑机械检查,PASS 的非阻断建议不要求清零。 报告随交付即时保存、登记;未实际派发的修复不能提前登记 fixing。完整规则见 调度与返工。
- 逐包流水线:各 WP/TP 交付后立即独立启动自己的 reviewer,不等待同层所有 coder/tester 完成。 apply 只为当前依赖满足且有流水线容量的包准备 worktree 和必要依赖,逐包就绪即派发。 契约阻断项集中修订后复审;仅记录格式错误由 main 修正并重跑机械检查,PASS 的非阻断建议不要求清零。 报告随交付即时保存、登记;未实际派发的修复不能提前登记 fixing。完整规则见 调度与返工。
- rebase 干净且改动内容指纹未变 → 复用原检视结论,只记录复用依据与原报告编号。
- 候选必须建在最新主分支上;先写入
agentic-premerge块并运行workflow check --stage premerge, 非 PASS 不得合入;PASS 之后才把该块持久化为版本化 receipt,并由主 Agent 校验 merger 返回的 结构化记录后在## Premerge History记一行(子角色不直接写权威 verification.md)。 final 会逐行读取 receipt,核对它是合法agentic-premerge块且 candidate/target/contract_digest/delivery_unit/证据摘要与行一致。 - propose 完成门禁:规划文件生成后,
plan.md的Dependency Declaration Review由独立 reviewer 以phase: plan、stage: plan核实(目标为当前 planningDigest,不针对代码 diff),结果落在verification.md的## Dependency Declaration Review(Reviewer 独立、Review ID + Round、Result PASS、Plan Revision绑定当前契约摘要、报告可读);随后运行workflow check --stage plan,两者对当前版本均 PASS 才报告 propose 完成。verification.md从 propose 的审查开始记录,apply 先确认门禁仍有效再准备执行 worktree;摘要未变就复用有效 PASS, planningDigest 变化后重新派发审查。旧变更缺少门禁时先补齐再执行,旧 contractDigest 审查仍按全文摘要核对。 新语义摘要忽略执行者、worktree/报告路径与后填用例表;contractDigest 仍用于完整契约与最终证据。 - 证据与影响分析:
workflow record --change <name> --input <报告路径> [--dry-run]从原始结构化报告 自动登记适用索引和哈希,幂等且冲突整次拒绝;workflow reconcile刷新台账对账。 plan PASS 后用workflow snapshot --change <name> --output <快照.json>保存不可覆盖的已批准基线, 改动后用workflow impact --change <name> --baseline <快照.json>定位受影响包及传递下游。 只有 canContinue 中已开工且自身仍就绪的包继续编码/编写;合入与最终验收仍要求完整当前门禁。 - 派发接收与测试交付:新派发使用
--require-ack,作者及接管 reviewer 各自以实际 ID 使用--ack; 持续执行可报告--heartbeat,main 用dispatch --change <name> --diagnose --idle-minutes 10查看未接收或停滞。 确认是执行者报告,不证明当前进程存活;旧台账明确为 LEGACY_UNVERIFIED,不自动结束实例。 测试设计只登记 DESIGN;新计划 staged-v2 的测试包必须交可运行用例/脚本或明确人工方案与基础检查, 不把设计文档当作编写完成,也不要求提前填写运行 Executor 与分片版本。 - worktree 交接留证:provisioner 创建/回收 worktree,并按
(WP, Attempt)返回结构化交接记录; 主 Agent 校验后写入## Worktree Handoff(worktree、基线提交、本轮认领执行者、开工前接收时间)。 Received At 不得晚于该轮首次执行事件(首次 coding、重开 fixing);Executor 绑定本轮实现者/测试作者, 不随 reviewer/merger 接管变动;交付证据在 Handoff Index 按Work Package绑定到具体工作包(同一执行者跨多个 WP 时不能串用);Provisioner 必须来自 Handoff Index 的 provisioner 交接行,且该行报告被引用。 - 合入永久串行:每个目标分支只有一个合入执行者(merger)、一条队列;把互不相关的工作包打包成一个候选 一起合入可以减少排队。合入后在主分支做回归核对。
- 逐工作包 review 记录:每个工作包的独立检视结果必须落在
verification.md的## Review Findings(Work Package列非空、Reviewer 不得是该 WP 的Owner、CRITICAL/MAJOR 必须有 Resolution);premerge/final 机械核对。 - 状态台账:开工与流转用
openspec-agentic dispatch --change <变更> --wp <WP> --executor <ID> --role coder|tester(首次开工)与openspec-agentic dispatch --change <变更> --wp <WP> --state <coding|reviewing|ready-to-merge|merged>(交付/检视/合入); 打回重做用--reopen(进入 fixing,轮次 +1,新的实现实例)。台账写在变更目录的dispatch-queue.jsonl,同一工作包已有主人时会被拒绝;dispatch --wp省略--role时会按计划Role列(缺列则按Owner规范化)推断, 避免漏传把 tester 记成 coder(仍建议显式写--role tester);openspec-agentic dispatch --change <变更>可查看当前状态。 - 派发留痕:每批还可运行
openspec-agentic dispatch --change <变更> --wave <W> --wps <WP,...> --executors <ID,...> --start <ISO> --end <ISO> --windows "<ID>=<start>~<end>,..."; 存在可并发层级(同层同角色 >=2 且对应池容量 >=2)时,台账里这些已开工工作包的占用窗口至少有一对真实重叠,否则premerge/final判不合格(时间戳由 dispatch 的开工/交付自动写入)。- 这是单侧负向探针:重叠 1 秒即通过,价值是“防止随手串行”,不是并行证明;
dispatch.pool把角色容量设为 1 时探针直接跳过——等于项目级声明该角色串行,是有意保留的口子;- 时间戳仍是主体自报(伪造成本高于手写窗口,但不是进程级观测)。
--windows/dispatch-records.jsonl是可选审计产物,不作判定依据;一旦写入,workflow check会校验它自洽(executors 不重复、wps 存在、start≤end、window ⊆ executors)。verification.md的## Dispatch Reconciliation逐工作包与台账、Handoff Index对账(Attempt / Executor / State / Evidence 都要对得上), 作为偏离探测而非并行证明。
验证证据复用
验证结果绑定改动内容指纹(改了哪些文件、各文件内容哈希),不再绑定提交号;指纹由检查工具自己 从 git 计算,不接受自报。只有干净 rebase 且上游未触及本工作包写入范围时才能复用,并记录原候选、 新候选、指纹未变与复用依据。只对 Verify 与 review 开放;E2E 一律重跑。 这是合入串行能站得住的前提。
E2E 分档
| 阶段 | 范围 | 时机 | | --- | --- | --- | | 最终 | 全量,覆盖所有需求 | 所有单元合入后只跑一次,单入口内部并行 |
测试的设计与编码并行(只依赖契约),只有执行需要等代码与资源;执行阶段的并行度由隔离资源决定, 与 tester 数量无关,最终 E2E 的分片并行在项目命令内部完成。
明确不解决
- 真正的依赖链:最慢的工作包决定整体时间,没有别的活可填窗口就只能等;
- 主 Agent 是单点且不占池:调度台、verification 维护、最终验收、合并协调都在它身上, 池子再大也不会让它变快;它是整套流程的吞吐上限;
- 合入天然串行,池子只把它变薄;
- 语义冲突(文件没变但与上游组合坏了)内容指纹看不出来,靠 review 抓;
- 运行态资源仍需隔离。
E2E 并行执行
最终 Main E2E 的并行只在 e2e.command 内部发生,流程层仍是一个入口:
# 每轮只调用一次;分片由命令内部并发
npx --quiet --no-install openspec-agentic e2e run --change add-export --stage final- 把并发逻辑封进项目聚合入口(如
node scripts/e2e-parallel.mjs),由它内部派发分片并汇总退出码: 任一分片失败或约定用例零执行即非零退出;各分片写独立报告供verification.md引用。 - 不要按分片多次调用
e2e run --stage final:e2e check只认最近一条 final 记录,多分会掩盖失败分片; 且记录命令必须与e2e.command逐字一致,加分片参数会直接判 FAIL。 - 本流程只在最终阶段执行 E2E,不产生候选 E2E 记录,
premerge也不核对任何候选 E2E;如需额外中间测试,由项目自有 CI 定义其性质与责任人,其记录不参与合入或验收判据。not-applicable时每个替代检查 ID 必须在任务中以[ID]声明,并在## Checks表有一行 PASS 与可读证据;e2e check只认 mode 与批准字段,逐项结果由workflow check --stage final与最终验收核对。 - 分片必须隔离资源(数据库/schema、端口、账号、可写目录、外部服务);无法隔离时串行或独占排队。
判据正文在 openspec/schemas/agentic/ 的 plan/apply instruction 与 E2E 并行执行(单入口) 小节。
角色模型
只有修改模型时才需要扩展命令:
npx openspec-agentic roles # 读取并校验当前映射
npx openspec-agentic roles set reviewer provider/review-model # 设置单个角色
npx openspec-agentic roles unset reviewer # 删除该角色条目同样可以走项目本地解析:
npx --quiet --no-install openspec-agentic roles set reviewer provider/review-model
npx --quiet --no-install openspec-agentic roles unset reviewer角色模型配置只有一份,位于扩展独占的 openspec/agentic.yaml(与引擎的 config.yaml 同目录,分成两个文件),便于模型经常变动时与流程配置分开维护:
roles:
main: "@current"
coder: provider/fast-model
reviewer: provider/review-model该文件是否纳入版本库由使用它的项目自行决定;扩展不写入 .gitignore。
8 个常设角色:main、coder、tester、reviewer、validator、merger、scout、provisioner。
@current 是扩展保留值,表示继承主会话当前模型;它不是宿主模型名,不会作为模型名传给宿主。
主流程在每次启用或派发其他角色前重新读取该映射,不缓存,也不生成宿主专用 agent 文件。
按档位推荐模型
判断与把关的岗位保持高档,实现、测试、合入等执行岗位用中档,侦察与资源类杂务用低档。
下例以 deepseek-v4 系列的 id 命名(该系列只有 pro 与 flash 两个型号),实际可用 id 由宿主决定;
下表是选型建议,不会写入配置;init / update 只在缺失时补上模型值本身。
| 档位 | 建议模型 | 角色 | 理由 |
| --- | --- | --- | --- |
| 高档 | deepseek-v4-pro | main、reviewer | 主流程协调、契约收敛与最终判断;独立检视与阻断判断,不能随实现档位下沉 |
| 中档 | deepseek-v4-flash | coder、merger、tester、validator | 实现与修复、合入排队与主分支回归、测试设计/编写/执行、独立验证,按标准能力即可 |
| 低档 | deepseek-v4-flash | scout、provisioner | 仓库/版本等事实侦察及 worktree 与运行资源准备、就绪检查和清理,流程固定、判断量低;该系列没有更低型号,沿用 flash 即可 |
三档描述的是岗位所需能力,不是型号数量:判断与把关用 pro,执行与环境类用 flash。
按上表写入 openspec/agentic.yaml:
roles:
main: deepseek-v4-pro
coder: deepseek-v4-flash
tester: deepseek-v4-flash
reviewer: deepseek-v4-pro
validator: deepseek-v4-flash
merger: deepseek-v4-flash
scout: deepseek-v4-flash
provisioner: deepseek-v4-flash任务下放与上下文隔离
scout 使用 scout 角色指令 的 recon phase 只读采集
仓库与目标引用、工具版本、命令入口、资源状态等机械事实;provisioner 使用
provisioner 角色指令 的 runtime phase 创建/回收
worktree、准备/隔离/启动运行资源、检查就绪并清理。两者权限模型相反(只读事实 vs 可写资源),
因此不共用一个角色。每次派发使用新的任务级最小上下文;宿主支持时设置
fork_turns="none",不传完整主对话、实现推理/自评、其他角色私有对话或全局证据汇总。
coder 在实现期间可延续同一工作包的必要上下文,但交付后即销毁;修复由新的实现实例承担
(携带原提交与 diff、review 报告),不继承旧上下文。reviewer 每轮新建隔离上下文;tester 的
execute / retest 每轮独立派发都新建实例(不是每条用例都新建),从当前最终主分支、用例/产物版本、
本轮 E2E ID 与资源恢复上下文,retest 另附原问题 ID、失败证据、修复提交与 review 结论;
merger 可延续本单元集成上下文并绑定目标分支;validator 同一验证任务可延续。
main 的调度状态以台账与 verification.md 为准,不依赖会话记忆:中断恢复先读目标、台账、
Handoff Index 与未闭环项。provisioner 按资源操作/租约管理,跨 WP 共享资源的归属落在资源表与
交接记录里,不只存在会话中。各角色在来源处整理自身 handoff,权威 plan.md、tasks.md、
verification.md 和跨报告判断仍由 main 单点维护,避免用另一个读取全部报告的 Agent 形成第二份全局上下文。
只想换个别角色时用 roles set 覆盖即可,其余保持 @current 继承主会话模型:
npx --quiet --no-install openspec-agentic roles set reviewer deepseek-v4-pro
npx --quiet --no-install openspec-agentic roles set provisioner deepseek-v4-flashinit / update 只写模型值,不注入注释;用户已写的行尾注释在 update 与 roles set 时保留。
模型是否生效由宿主决定:宿主必须把解析结果传入当次调用的原生 model 参数; 宿主无法指定模型时,必须报告该能力限制,不得声称配置已生效。
目录结构
openspec/
config.yaml # 引擎的项目配置(schema、context、operations)
agentic.yaml # 扩展的项目配置(roles、dispatch、e2e)
.agentic-install.json # 安装清单:扩展与引擎版本、受管文件哈希(doctor/update 据此判断漂移)
schemas/agentic/ # 工作流定义
specs/ # 主规范
changes/ # 变更(归档后位于 changes/archive/)
.agents/skills/agentic-verify/
AGENTS.md
package.jsonopenspec/changes/** 与 openspec/specs/** 是项目自己的资产,扩展安装/升级/迁移时只读写受管文件。
运行期唯一例外是 E2E:扩展在变更目录下写自己的 e2e/run-*.json 记录,并只按 [e2e-owned] 标记回写最终
E2E 任务行(行级单一所有者)。
不再有 fluentspec/ 目录,也不再有第二套配置;扩展自己的键不再写进引擎的 config.yaml。
旧项目迁移
update 会先识别四种状态:纯旧版、已完成迁移、新旧混合、用户改过受管 schema。迁移内容:
fluentspec/config.yaml的roles:与旧版openspec/roles.yaml的roles、旧版config.yaml的x-agentic.roles→openspec/agentic.yaml的roles;- 旧版
config.yaml的x-agentic.e2e/x-agentic.dispatch→openspec/agentic.yaml的同名段,x-agentic段整体从config.yaml移除; - 旧配置的
context/operations合并到openspec/config.yaml; - 旧版
x-agentic.configVersion直接丢弃:受管配置形态版本只由openspec/.agentic-install.json承载; - 迁移完成后就地删除旧版
openspec/roles.yaml; fluentspec/schemas/agentic→openspec/schemas/agentic。
冲突不静默覆盖,用 --prefer openspec 或 --prefer legacy 显式裁决。
旧配置保留为 fluentspec/config.yaml.migrated,目录不立即删除。
安装/升级/迁移不改写 openspec/changes/** 与 openspec/specs/**。
源码布局
assets/openspec/schemas/agentic/:流程定义(schema.yaml、templates、roles、procedures、tests)assets/openspec/config.yaml:引擎侧项目配置片段(schema/context/operations)assets/openspec/agentic.yaml:扩展侧项目配置模板(roles/dispatch/e2e,新项目播种与update补齐的唯一来源)assets/AGENTS.md:安装时写入目标项目根AGENTS.md的指引片段assets/skills/agentic-verify/SKILL.md:安装时写入目标项目.agents/skills/agentic-verify/的验收 skillsrc/:install、migrate、roles、e2e、e2e-check、manifest、project、clibin/openspec-agentic.mjs:CLI 入口test/、scripts/
全部安装模板都位于 assets/ 下;仓库根的 AGENTS.md 只写本仓库的开发与发布规则。
本仓库不包含 openspec/:它是包,不是使用本扩展的项目,因此 agentic 门禁(派发台账、e2e check、
workflow check、verification.md)不适用于本仓库的开发改动;试跑完整流程见文末「试跑完整流程」。
引擎兼容
依赖精确锁定 @fission-ai/openspec 1.13.0(同时出现在 peerDependencies 与 devDependencies),
Node >=20.19.0。本扩展不把引擎当库 import,只消费它的 CLI 与 JSON 契约。
升级引擎是刻意变更:改锁定版本 → npm ci → 通过下面的发布门禁。
发布门禁
npm test # 单元与契约测试(test/*.test.mjs)
npm run test:workflow # PowerShell 回归套件
npm run test:pack # 真实 tarball 全流程
npm run verify # 上述三者串行prepublishOnly 绑定 npm run verify。npm run test:workflow 需要 Windows PowerShell 或 pwsh;
非 Windows 环境缺少 pwsh 时 verify 会失败(脚本会给出明确提示),请在 CI 中预装或单独拆分门禁。
试跑完整流程
npm run test:pack 会用真实 npm pack 产物在临时项目里跑完整流程(安装 → 逐阶段 instructions → 归档 →
旧项目迁移);也可以在任意空项目里直接初始化:
npx --quiet --no-install openspec --version # 仓库内解析的是固定版本引擎
npx @dongfanglin/openspec-agentic@latest init . --tools codex