ai-delivery-workflow 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/docs/FILE-REFERENCE.zh-CN.md +16 -35
- package/docs/PROJECT-MANUAL.zh-CN.md +14 -13
- package/docs/STATE-CLI-MAINTENANCE.zh-CN.md +2 -2
- package/docs/STATE-CLI-USER-GUIDE.zh-CN.md +3 -3
- package/docs/agents/workflow-manager-current-state.md +7 -6
- package/lib/delivery-state.mjs +130 -12
- package/lib/project-installer.mjs +15 -4
- package/lib/workspace.mjs +4 -1
- package/package.json +1 -1
- package/skills/ai-delivery-close-version/SKILL.md +9 -4
- package/skills/ai-delivery-close-version/assets/version-closeout-readiness.yaml +15 -0
- package/skills/ai-delivery-close-version/references/version-closeout-contract.md +3 -1
- package/skills/ai-delivery-orchestrate/SKILL.md +3 -2
- package/skills/ai-delivery-orchestrate/assets/project-template/AGENTS.md +1 -1
- package/skills/ai-delivery-orchestrate/references/communication-confirmation-contract.md +1 -1
- package/skills/ai-delivery-orchestrate/references/formal-state-contract.md +5 -3
- package/skills/ai-delivery-orchestrate/references/workflow-model.md +2 -2
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
- [正式状态 CLI 维护指南](docs/STATE-CLI-MAINTENANCE.zh-CN.md)
|
|
23
23
|
- [npm 版本与发布管理规范](docs/NPM-RELEASE-MANAGEMENT.zh-CN.md)
|
|
24
24
|
- [维护仓库验证工具:发布预检、成本基准与可信平台证明](docs/MAINTENANCE-VERIFICATION.zh-CN.md)
|
|
25
|
-
- [
|
|
25
|
+
- [审计物料:保留样例、历史清理和五版本发布列车](audit/README.md)
|
|
26
26
|
- [审计物料逐文件用途](audit/FILE-GUIDE.zh-CN.md)
|
|
27
27
|
- [永久验证源码说明](verification/README.zh-CN.md)
|
|
28
28
|
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
| --- | --- |
|
|
24
24
|
| 发行源码 | npm 包实际发布并用于安装目标项目的 `bin/`、`lib/`、`skills/` 和 `docs/`。 |
|
|
25
25
|
| 永久验证 | 根配置和 `verification/` 中的通用测试与审计校验器,用于维护本发行仓库。 |
|
|
26
|
-
| 审计物料 | `audit/`
|
|
26
|
+
| 审计物料 | `audit/` 中保留的发布、双仓、演化和自主恢复样例,纳入 Git,但不会安装到目标项目;历史清理清单位于 `.scratch/`。 |
|
|
27
27
|
| 可版本化设计原型 | `prototypes/` 中已确认的 Workflow Manager 原型及其业务页面夹具,纳入 Git,但不进入 npm 包或安装目标。 |
|
|
28
28
|
| 临时物料 | `.tmp/` 中的测试工作区、缓存、日志、报告、临时仓库、打包文件和单次场景脚本,整体忽略且可丢弃。 |
|
|
29
29
|
|
|
@@ -130,7 +130,7 @@
|
|
|
130
130
|
| `verification/documentation.test.mjs` | 手册存在、README 链接、25 个 Skill 名称、主要文件域、YAML 解析、仓库内容边界和 npm `docs` 发布白名单。 |
|
|
131
131
|
| `verification/skill-validation.test.mjs` | 验证当前 25 个 Skill 通过校验、无效 fixture 被拒绝、`skills:validate` 命令在 npm 包内可达且维护文档完整。 |
|
|
132
132
|
| `verification/release-planner.test.mjs` | 连续版本闭包、同版本重发、倒退、断链、stale、缺 Tag 和 Git 血缘。 |
|
|
133
|
-
| `verification/audit-workflow.test.mjs` |
|
|
133
|
+
| `verification/audit-workflow.test.mjs` | 运行审计总验证器,要求保留样例和历史清理清单通过,并检查 checksum 格式和未发布版本数。 |
|
|
134
134
|
| `verification/autonomous-guidance-evidence.test.mjs` | 验证自主引导证据可离线复算,并拒绝不完整清单、错误 commit tree、被篡改的快照/运行日志和符号链接逃逸。 |
|
|
135
135
|
| `verification/release-check.test.mjs` | 验证发布预检的本地通过、结构化失败和 Tag/提交绑定。 |
|
|
136
136
|
| `verification/autonomy-cost-benchmark.test.mjs` | 验证成本基准的迭代参数、上下文代理和重复恢复零持久增长。 |
|
|
@@ -139,7 +139,7 @@
|
|
|
139
139
|
| `verification/checkpoint-task-state.test.mjs` | 独立验证 checkpoint、任务依赖、恢复顺序、共享发布和版本归档。 |
|
|
140
140
|
| `verification/version-archive-references.test.mjs` | 隔离验证版本归档以 checksum 引用 task summary、attempt receipt、scope、candidate、Gate 和 history anchor。 |
|
|
141
141
|
| `verification/evolution.test.mjs` | 验证反馈脱敏与幂等、证据门槛、风险抬升、checksum 批准、Hook、冲突、trial 晋升与回退。 |
|
|
142
|
-
| `verification/audit/verify-audit.mjs` |
|
|
142
|
+
| `verification/audit/verify-audit.mjs` | 一键检查保留审计样例、清理清单、checksum、发布列车、双仓、演化和自主引导证据一致性。 |
|
|
143
143
|
| `verification/audit/verify-autonomous-guidance.mjs` | 复算自主引导结果/运行日志、Git 证据和任务语义;缺省保留平台未认证声明,也可用外部受信 Ed25519 公钥验证平台签名。 |
|
|
144
144
|
| `verification/audit/verify-autonomy-cost.mjs` | 校验正式成本基线至少包含三次恢复样本,且持久 checksum、文件数、字节数和语义上下文均稳定。 |
|
|
145
145
|
|
|
@@ -410,7 +410,7 @@
|
|
|
410
410
|
|
|
411
411
|
| 路径 | 作用 |
|
|
412
412
|
| --- | --- |
|
|
413
|
-
| `skills/ai-delivery-close-version/` |
|
|
413
|
+
| `skills/ai-delivery-close-version/` | 先通过 `VERSION-CLOSEOUT-READINESS` 人工 Gate 规划并确认收尾,再关闭已验证计划版本,生成版本 Manifest、血缘、version-ready Tag 与累计研发线推进记录,并在 release-ready 时归档任务。 |
|
|
414
414
|
| `skills/ai-delivery-orchestrate-release/` | 只在用户明确发布时编排 R00 至 R10,固定请求时 main 快照、目标版本选择、精确候选晋级和 release-fix 回写;R10 使用产品线级候选库存及不可变 successor。 |
|
|
415
415
|
| `skills/ai-delivery-assemble-release/` | 使用 `scripts/plan-release.mjs` 计算连续闭包并校验 Git/Tag,输出版本纳入表、main-first Git 计划和发布候选模板。 |
|
|
416
416
|
|
|
@@ -465,39 +465,20 @@
|
|
|
465
465
|
|
|
466
466
|
## 14. 审计物料目录
|
|
467
467
|
|
|
468
|
-
`audit/`
|
|
468
|
+
`audit/` 只保留仍有验证价值的发布、双仓、演化和自主恢复样例。每个具体文件的用途由 [../audit/FILE-GUIDE.zh-CN.md](../audit/FILE-GUIDE.zh-CN.md) 维护;清理清单由 `.scratch/historical-node-cleanup/audit-cleanup-manifest.json` 维护。整个目录只属于维护仓库审计资产,不随 `init` 安装。
|
|
469
469
|
|
|
470
470
|
| 目录 | 作用 |
|
|
471
471
|
| --- | --- |
|
|
472
|
-
| `audit/
|
|
473
|
-
| `audit/
|
|
474
|
-
| `audit/
|
|
475
|
-
| `audit/
|
|
476
|
-
| `audit/
|
|
477
|
-
| `audit/
|
|
478
|
-
| `audit/
|
|
479
|
-
| `audit/
|
|
480
|
-
| `audit/
|
|
481
|
-
| `audit/
|
|
482
|
-
| `audit/10-change-review/` | 独立审查报告、发现和决定。 |
|
|
483
|
-
| `audit/11-candidate-verification/` | 风险测试包、证据、覆盖、缺陷、候选决定和验证工具。 |
|
|
484
|
-
| `audit/12-release-preparation/` | 完整变更覆盖、上线交付清单、发布清单和回滚就绪。 |
|
|
485
|
-
| `audit/13-production-approval/` | 绑定精确发布包的模拟人工审批。 |
|
|
486
|
-
| `audit/14-production-deployment/` | 独立部署计划、记录、证据和部署副本。 |
|
|
487
|
-
| `audit/15-production-verification/` | 生产烟雾脚本、证据、报告和发布决定。 |
|
|
488
|
-
| `audit/16-version-archive/` | ITER-V1 的 15 个任务、checkpoint、事件、恢复摘要和版本索引。 |
|
|
489
|
-
| `audit/ITER-V2/` | 当前契约下的第二次迭代,交付“完成任务”,包含可运行低保真与正式 UI、三道人工 Gate、调整记录、产品核对、体验变更追踪、上下游接收凭据、TDD、发布、部署、验证和版本归档。 |
|
|
490
|
-
| `audit/RELEASE-TRAIN-DEMO/` | 当前双状态机契约示例:五个累计版本、VER-02 至 VER-05 的多版本发布、完整 R00-R10 物料和同版本重发。 |
|
|
491
|
-
|
|
492
|
-
`audit/` 根文件:
|
|
493
|
-
|
|
494
|
-
| 文件 | 作用 |
|
|
495
|
-
| --- | --- |
|
|
496
|
-
| `audit/README.md` | TaskLite 示例边界、阅读顺序和运行命令。 |
|
|
497
|
-
| `audit/FILE-GUIDE.zh-CN.md` | 审计目录全部 628 个文件及同构归档路径的权威说明。 |
|
|
498
|
-
| `audit/REVIEW-CHECKLIST.md` | 人工审阅全流程完整性的清单。 |
|
|
499
|
-
| `audit/V1-CONTRACT-COMPATIBILITY.md` | 解释历史 V1 能证明什么、缺少哪些当前强制物料,以及为何不能原地补写。 |
|
|
500
|
-
| `audit/generate-v2.mjs` | 从 V1 基线可重复生成并执行 ITER-V2,包含真实 TDD、确定性候选打包、部署、生产烟雾和版本归档。 |
|
|
472
|
+
| `audit/RELEASE-TRAIN-DEMO/` | 五个递进版本、跨版本发布、同版本重发和 R00-R10 发布闭包。 |
|
|
473
|
+
| `audit/DUAL-REPO-FULL-FLOW/` | 双仓工作区、七节点研发、收尾前人工 Gate、双 Tag、release-fix、候选库存和回滚证据。 |
|
|
474
|
+
| `audit/EVOLUTION-CONTROL-LOOP/` | 脱敏反馈、自动 trial、人工批准和自动回退。 |
|
|
475
|
+
| `audit/AUTONOMOUS-GUIDANCE/` | 零命令自主引导的离线可复算证据和声明等级。 |
|
|
476
|
+
| `audit/AUTONOMY-COST/` | 重复只读恢复的成本基线和持久状态零增长不变量。 |
|
|
477
|
+
| `audit/README.md` | 保留样例、当前研发/发布路线、历史清理和验证命令。 |
|
|
478
|
+
| `audit/FILE-GUIDE.zh-CN.md` | 保留审计文件的用途和路径模式。 |
|
|
479
|
+
| `audit/REVIEW-CHECKLIST.md` | 当前研发、人工 Gate、发布、归档和清理结果的人工清单。 |
|
|
480
|
+
| `audit/generate-all.mjs` | 只调用双仓全流程生成器。 |
|
|
481
|
+
| `audit/generate-dual-repo.mjs` | 在 `.tmp/dual-repo-e2e/` 建立临时双 Git 工作区并生成不含 `.git` 的持久样例。 |
|
|
501
482
|
|
|
502
483
|
## 15. 安装后生成而非发行的文件
|
|
503
484
|
|
|
@@ -559,7 +540,7 @@
|
|
|
559
540
|
| Hook 事件 | 只能作为审计和心跳,不推进正式节点。 |
|
|
560
541
|
| runtime 当前任务 | 通过 `task-state.mjs` 原子写入,不手工拼接。 |
|
|
561
542
|
| 已归档版本 | 不原地修改。 |
|
|
562
|
-
| `audit/`
|
|
543
|
+
| `audit/` 保留样例 | 只更新生成器和可重建结果;历史删除内容从清单备份恢复,不在现行审计树中原地补写。 |
|
|
563
544
|
| 规范 | 通过 `$ai-delivery-manage-standards` 提案、人工批准和版本化。 |
|
|
564
545
|
|
|
565
546
|
当仓库文件发生变化时,应先更新本文件的对应章节,再运行文档一致性测试和 `npm pack --dry-run`。
|
|
@@ -23,7 +23,7 @@ workspace/code/.git 代码 Git
|
|
|
23
23
|
> 文件级索引:[FILE-REFERENCE.zh-CN.md](FILE-REFERENCE.zh-CN.md)
|
|
24
24
|
> CodeGraph 可选集成:[CODEGRAPH-INTEGRATION.zh-CN.md](CODEGRAPH-INTEGRATION.zh-CN.md)
|
|
25
25
|
> Microcks Mock System:[MOCK-SYSTEM.zh-CN.md](MOCK-SYSTEM.zh-CN.md)
|
|
26
|
-
>
|
|
26
|
+
> 全流程审计物料(保留样例与历史清理记录):[../audit/README.md](../audit/README.md)
|
|
27
27
|
> 正式状态命令:[STATE-CLI-USER-GUIDE.zh-CN.md](STATE-CLI-USER-GUIDE.zh-CN.md)
|
|
28
28
|
|
|
29
29
|
## 1. 项目是什么
|
|
@@ -107,7 +107,7 @@ AI Delivery Workflow 是一套安装在单个代码仓库内的 AI 研发流程
|
|
|
107
107
|
| CLI | `bin/ai-delivery.mjs` | 安装、检查、引导和诊断目标项目。 |
|
|
108
108
|
| 安装与引导库 | `lib/` | 合并项目配置、识别项目状态、生成存量代码上下文。 |
|
|
109
109
|
| 项目 skills | `skills/ai-delivery-*` | 定义各研发节点的输入、过程、输出、Gate 和失败路由。 |
|
|
110
|
-
| 审计与验证 | `audit/`、`verification/` |
|
|
110
|
+
| 审计与验证 | `audit/`、`verification/` | 保留发布、双仓、演化和自主恢复样例,并用通用测试验证安装、引导、收尾 Gate 和发布交接;两者均不随 `init` 安装。 |
|
|
111
111
|
| 可版本化设计原型 | `prototypes/` | 保存 Workflow Manager 原型及其业务页面夹具;纳入 Git,不进入 npm 包或安装目标。 |
|
|
112
112
|
| 临时运行物料 | `.tmp/` | 保存测试工作区、缓存、日志、报告、临时 Git 仓库、打包文件和单次场景脚本,整体忽略且可随时删除。 |
|
|
113
113
|
|
|
@@ -420,6 +420,7 @@ flowchart LR
|
|
|
420
420
|
| `UX-UI` | 应用选定系统后的可运行正式 UI 是否通过 | AI 保持已确认交互,记录所有修订,直到最新轮次批准且评论全部终结。 |
|
|
421
421
|
| 生产部署审批 | 是否允许把精确 package hash 部署到指定环境 | AI 必须先列出完整变更和回滚条件。 |
|
|
422
422
|
| 规范治理 | 新增、修改、废弃或例外是否生效 | AI 起草版本化规范,批准后注册并固定版本。 |
|
|
423
|
+
| `VERSION-CLOSEOUT-READINESS` | 候选测试完成后,收尾任务是否已规划、相关问题是否已确认、是否允许进入 `06-version-closeout` | AI 先登记完整 queued 任务计划并整理确认摘要;人工批准后才可启动 06。 |
|
|
423
424
|
|
|
424
425
|
除上述 Gate 外,中间交付默认由下游按契约验证,不要求额外人工确认。
|
|
425
426
|
|
|
@@ -630,7 +631,7 @@ node .workflow/tools/state/state.mjs verify
|
|
|
630
631
|
|
|
631
632
|
状态 CLI 根据流程图元数据校验前置依赖,不采用简单的相邻编号规则。`03-delivery-readiness` 内的平台准备可与计划和测试设计并行;Product Shaping 和 Solution Design 可因原型校正带原因重开;后续迭代可用已登记且 identity/checksum 精确匹配的成功冻结基线满足未受影响的前置条件。节点完成证据必须处于允许的成功状态,并完成当前节点尝试的强制 Gate。生产审批 Gate ID 固定为 `PRODUCTION-APPROVAL`,不能标记为 `not-required`。
|
|
632
633
|
|
|
633
|
-
Delivery Readiness 通过 `scope freeze` 将 Slice、需求、验收、任务和物料冻结为带 revision/checksum 的 manifest,并启用 `scope_contract_version: 1`。冻结后,只有明确人工批准的 `scope amend` 可以通过 `--supersedes` 创建下一 revision;`scope warn` 只写入 `warn-only` 和 `reslice_performed: false
|
|
634
|
+
Delivery Readiness 通过 `scope freeze` 将 Slice、需求、验收、任务和物料冻结为带 revision/checksum 的 manifest,并启用 `scope_contract_version: 1`。冻结后,只有明确人工批准的 `scope amend` 可以通过 `--supersedes` 创建下一 revision;`scope warn` 只写入 `warn-only` 和 `reslice_performed: false`,预算超限不会自动重新切片、重排计划或改变验收。候选测试完成后,进入 `06-version-closeout` 前必须先完成收尾任务规划、确认摘要和 `VERSION-CLOSEOUT-READINESS` 人工 Gate。
|
|
634
635
|
|
|
635
636
|
`inspect.derived_node_states` 根据 task、最新 blocking finding、Gate、artifact、immutable candidate、当前 manifest 与 completion receipt 联合投影正式节点状态,而不是由单个子任务状态直接决定。可能状态为 `pending`、`active`、`waiting`、`blocked`、`ready-to-complete` 和 `completed`。新契约节点只有达到 `ready-to-complete` 才能完成;CLI 随后生成绑定 manifest、任务/物料事实、Gate、candidate、blocking defect、evidence 和 checksum 的不可变 completion receipt。完整 `scope freeze`、`scope amend`、`scope warn` 命令见正式状态指南。
|
|
636
637
|
|
|
@@ -893,32 +894,32 @@ R00 同时固定当时 `main` 的 commit。R04 通过 `release-git.mjs create-ca
|
|
|
893
894
|
|
|
894
895
|
## 18. 全流程审计物料
|
|
895
896
|
|
|
896
|
-
`audit/` 使用最小前后端系统 TaskLite
|
|
897
|
+
`audit/` 使用最小前后端系统 TaskLite 保存仍有验证价值的发布与治理证据。它只属于本维护仓库,不随 `init` 安装到业务项目:
|
|
897
898
|
|
|
898
899
|
- Node.js HTTP 服务;
|
|
899
900
|
- 原生浏览器 Web 前端;
|
|
900
901
|
- 任务创建和列表 API;
|
|
901
|
-
-
|
|
902
|
-
- `audit/ITER-V2/` 是当前契约示例:在 V1 不可变基线上交付“完成任务”,补齐最新原型管理、上下游接收凭据和当前验证规则;
|
|
902
|
+
- `audit/DUAL-REPO-FULL-FLOW/` 是当前双仓全流程示例:研发按七节点路线执行,`06-version-closeout` 前有 `VERSION-CLOSEOUT-READINESS` 人工确认,发布按 R00-R10 独立闭包;
|
|
903
903
|
- `audit/RELEASE-TRAIN-DEMO/` 演示五个严格递进版本、生产停在 VER-02、统一发布至 VER-05,以及同版本重新发布。
|
|
904
|
+
- `audit/EVOLUTION-CONTROL-LOOP/` 演示脱敏反馈、自动 trial、人工批准和自动回退。
|
|
904
905
|
- `audit/AUTONOMOUS-GUIDANCE/` 保存零命令引导黑盒证据;远程 commit/tree 与四个关键 Git blob 的路径归属可离线复算,`fork_turns`、输入边界和未要求命令等平台行为在没有可信平台签名时明确保持 `unattested`。
|
|
906
|
+
- `audit/AUTONOMY-COST/` 保存重复只读恢复成本基线,并证明持久工作流状态零增长。
|
|
905
907
|
|
|
906
|
-
|
|
908
|
+
旧的 V1、ITER-V2、STATE-CLI-DEMO 和双仓 VER-01/VER-02 证据树已清理;逐文件 checksum、原因和可恢复备份路径见 `.scratch/historical-node-cleanup/audit-cleanup-manifest.json`。当前规范来源始终是 `skills/**/SKILL.md`、对应 `references/` 和 `assets/`。
|
|
907
909
|
|
|
908
910
|
推荐阅读:
|
|
909
911
|
|
|
910
912
|
1. [../audit/README.md](../audit/README.md):示例入口和运行方式;
|
|
911
913
|
2. [../audit/FILE-GUIDE.zh-CN.md](../audit/FILE-GUIDE.zh-CN.md):`audit/` 中每个文件的用途;
|
|
912
914
|
3. [../audit/REVIEW-CHECKLIST.md](../audit/REVIEW-CHECKLIST.md):人工审阅清单;
|
|
913
|
-
4.
|
|
914
|
-
5. `audit/
|
|
915
|
-
6.
|
|
916
|
-
7.
|
|
917
|
-
8. 最后运行 `npm run audit:verify`。
|
|
915
|
+
4. `../.scratch/historical-node-cleanup/audit-cleanup-manifest.json`:历史文件清理清单和恢复路径;
|
|
916
|
+
5. 按 `audit/DUAL-REPO-FULL-FLOW/` 审阅双仓身份、收尾 Gate、发布和归档;
|
|
917
|
+
6. 按 `audit/RELEASE-TRAIN-DEMO/` 审阅跨版本发布与同版本重发;
|
|
918
|
+
7. 最后运行 `npm run audit:verify`。
|
|
918
919
|
|
|
919
920
|
自主引导专项校验也可单独运行 `node verification/audit/verify-autonomous-guidance.mjs`。该命令验证仓库快照、摘要、Git blob OID 和任务语义,但不会把维护者记录的平台运行声明当作独立认证事实。
|
|
920
921
|
|
|
921
|
-
|
|
922
|
+
审计目录中的保留样例和清理清单都应保持可解释、可重建。历史备份位于被忽略的 `.tmp/`,不属于 Git 或 npm 发行物料。
|
|
922
923
|
|
|
923
924
|
## 19. 本仓库开发与验证
|
|
924
925
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
当前生产图是 `development-seven-node`:`00-bootstrap -> 01-product-shaping -> 02-solution-design -> 03-delivery-readiness -> 04-implementation -> 05-candidate-assurance -> 06-version-closeout`。`R00-release-request` 至 `R10-release-archive` 继续允许写入。
|
|
4
4
|
|
|
5
|
-
正式状态写入会先完整暂存权威事件分片、当前视图和 JSONL 事件索引,持久化 prepared journal,再提交各目标并写入 committed marker;同步异常时恢复原文件,进程中断后由下一次受锁 mutation 或 `rebuild` 幂等恢复。`inspect`、`verify`、Bootstrap 诊断与 Workflow Manager 正式状态读取期间获取与 mutation 共用的 formal-state lock
|
|
5
|
+
正式状态写入会先完整暂存权威事件分片、当前视图和 JSONL 事件索引,持久化 prepared journal,再提交各目标并写入 committed marker;同步异常时恢复原文件,进程中断后由下一次受锁 mutation 或 `rebuild` 幂等恢复。`inspect`、`verify`、Bootstrap 诊断与 Workflow Manager 正式状态读取期间获取与 mutation 共用的 formal-state lock;只读调用方只对能够解析且确认 `pid` 仍存活的活动 writer 做有限等待,以避免并发读取观察到混合 revision;未知格式锁、失联 writer、其他 reader 或未恢复 journal 均立即 fail-closed。只读调用方不得接管死锁或执行事务恢复。日常 `verify` 不遍历历史分片,只校验当前视图、JSONL 索引、物料和状态不变量;显式 `verify --history` 还检查全部事件分片的连续性、元数据、记录 checksum、schema 2 checksum 链以及最新 replay 结果与全局视图的一致性。`rebuild` 按 revision replay 每个 stream,并按确定顺序重建 JSONL 索引。
|
|
6
6
|
|
|
7
7
|
## 1. 权威源码与安装结果
|
|
8
8
|
|
|
@@ -135,7 +135,7 @@ npm run audit:verify
|
|
|
135
135
|
|
|
136
136
|
`workflow-state.yaml` 当前 schema 为 2。修改状态实现时必须分别验证 `development_state` 与 `release_state` 的 scope、局部 revision、节点集合、Gate 集合和节点尝试。流程图不能退化为简单“上一编号节点”判断:平台准备允许并行,体验与产品允许带原因重开,后续迭代允许用成功的冻结基线物料满足未受影响的前置条件。
|
|
137
137
|
|
|
138
|
-
独立 aggregate 的 writer 仍通过共享提交区串行更新 JSONL 和全局视图,但使用各自的 aggregate revision:最多等待可识别的活动事务 30 秒,获取锁后重新读取并可分别成功。同一 aggregate 的 writer 在等待后必须因 revision conflict fail-closed
|
|
138
|
+
独立 aggregate 的 writer 仍通过共享提交区串行更新 JSONL 和全局视图,但使用各自的 aggregate revision:最多等待可识别的活动事务 30 秒,获取锁后重新读取并可分别成功。同一 aggregate 的 writer 在等待后必须因 revision conflict fail-closed。只读入口仅等待可证明仍存活的活动 writer;未知格式锁、失联 writer 和 journal 均不等待、不恢复,立即 fail-closed。
|
|
139
139
|
|
|
140
140
|
安装诊断不得从项目内可编辑 manifest 推导可信 Skill 集合。固定 Skill 清单、Skill 目录摘要、Hook 摘要和状态运行时摘要以发行包为准;manifest 必须与发行包一致。`doctor` 还必须运行安装后状态 CLI 的 `inspect` 与 `verify`,并校验 JSON 输出语义。
|
|
141
141
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
## 可重建视图
|
|
6
6
|
|
|
7
|
-
正式状态 mutation 会生成 `.workflow/control/events/<stream>/<revision>-<event-id>.yaml` 权威事件分片,并与 `workflow-state.yaml` 或 `artifact-registry.yaml` 当前视图及 `state-events.jsonl` 索引作为一组提交。workflow 与 artifact mutation 都使用 schema 2 增量事务:事件只保存顶层元数据和受影响的 scope 或物料,不再嵌入完整视图;scope start 同时固化项目身份。带已登记 evidence 的 transition/Gate 会在同一事务中同时生成 workflow delta 和 artifact handoff delta,并向 registry 顶层 `handoffs` 追加独立关系;已登记 artifact revision 的字段保持不变。提交前会在 `.workflow/delivery/runtime/formal-state-locks/` 写入恢复 journal;`inspect`、`verify`、Bootstrap 诊断及 Workflow Manager 正式状态读取期间持有同一把 formal-state lock
|
|
7
|
+
正式状态 mutation 会生成 `.workflow/control/events/<stream>/<revision>-<event-id>.yaml` 权威事件分片,并与 `workflow-state.yaml` 或 `artifact-registry.yaml` 当前视图及 `state-events.jsonl` 索引作为一组提交。workflow 与 artifact mutation 都使用 schema 2 增量事务:事件只保存顶层元数据和受影响的 scope 或物料,不再嵌入完整视图;scope start 同时固化项目身份。带已登记 evidence 的 transition/Gate 会在同一事务中同时生成 workflow delta 和 artifact handoff delta,并向 registry 顶层 `handoffs` 追加独立关系;已登记 artifact revision 的字段保持不变。提交前会在 `.workflow/delivery/runtime/formal-state-locks/` 写入恢复 journal;`inspect`、`verify`、Bootstrap 诊断及 Workflow Manager 正式状态读取期间持有同一把 formal-state lock,仅对可解析且确认 writer `pid` 仍存活的活动 mutation 做有界等待,不会返回混合 revision。未知格式锁、失联 writer、其他 reader 或未恢复 journal 均立即 fail-closed。mutation writer 最多等待可识别的活动提交 30 秒,获取锁后重新读取并校验自己的 aggregate revision。下一次 mutation 或 `rebuild` 根据 commit marker 回滚 prepared 事务或清理 committed 事务。视图丢失或损坏时执行:
|
|
8
8
|
|
|
9
9
|
```powershell
|
|
10
10
|
node .workflow/tools/state/state.mjs rebuild
|
|
@@ -245,8 +245,8 @@ node .workflow/tools/state/state.mjs gate decide \
|
|
|
245
245
|
|
|
246
246
|
研发与发布使用两个独立状态域:`development_state.scope_id` 由 `iteration-started` 建立,`release_state.scope_id` 由用户明确发布后执行 `release-started` 建立。两者分别保存局部 revision、活动/阻塞/完成节点、Gate、节点尝试次数和选定物料;局部 revision 用于 workflow 乐观并发,顶层 `workflow_state.revision` 只负责审计串行化。
|
|
247
247
|
|
|
248
|
-
`node-started` 会验证流程图前置条件。当前迭代未执行的前置节点,可以用来自该节点且处于成功状态的已登记基线物料作为 evidence;这用于后续迭代只重访受影响基线。重新打开已完成节点必须提供 `--reason`,并产生新的节点尝试,旧 Gate
|
|
248
|
+
`node-started` 会验证流程图前置条件。当前迭代未执行的前置节点,可以用来自该节点且处于成功状态的已登记基线物料作为 evidence;这用于后续迭代只重访受影响基线。重新打开已完成节点必须提供 `--reason`,并产生新的节点尝试,旧 Gate 决定不能批准新一轮输出。`06-version-closeout` 还有一个前置人工 Gate:先登记收尾任务计划和确认摘要,再在 `05-candidate-assurance` 完成后申请 `VERSION-CLOSEOUT-READINESS`;未获批准时不能启动 06。
|
|
249
249
|
|
|
250
|
-
`node-completed` 只接受成功状态物料,并检查当前尝试的必需 Gate:`GATE-A`、`GATE-B`、`UX-VS`、`UX-UI` 和 `PRODUCTION-APPROVAL`。只有确实无视觉交互的体验范围可以依据产品终端证据把活动 UX Gate 决定为 `not-required`;Gate A、Gate B 和生产审批必须为 `approved`。
|
|
250
|
+
`node-completed` 只接受成功状态物料,并检查当前尝试的必需 Gate:`GATE-A`、`GATE-B`、`UX-VS`、`UX-UI`、`VERSION-CLOSEOUT-READINESS` 和 `PRODUCTION-APPROVAL`。只有确实无视觉交互的体验范围可以依据产品终端证据把活动 UX Gate 决定为 `not-required`;Gate A、Gate B 和生产审批必须为 `approved`。
|
|
251
251
|
|
|
252
252
|
每个节点交接、生产审批和部署前运行日常 `verify`;版本收尾和发布归档还必须运行 `verify --history`。新研发流程使用 `06-version-closeout` 和 `release-ready`;完成该节点后通过 `version-closed` 记录累计研发版本,但不得创建任何 R 节点。独立发布使用 `R00-release-request` 至 `R10-release-archive`;启动 R00 时必须提供节点为 R00、状态成功且 `artifact_type: release-request` 的显式用户请求物料,并固定请求时 `main` 的 `expected_main`。R04 必须以 `release-git.mjs create-candidate` 的 `--expected-main`、精确 `--source-tag/--source-commit`、`--receipt` 和 `--apply` 从该快照创建 release 分支。增量发布只以 `--no-ff` 合入一个精确不可变 `version-ready` Tag;同版本重发在目标 Tag 已包含于快照时不新增合并,候选就是该快照。候选、审批和部署都绑定该精确候选提交。R09 成功结论先写入带 `operation: production-verification-decision` 的机器 JSON,再通过 `release-git.mjs promote --production-verification <R09-json>` 触发受控的精确 `main` 快进;R10 在归档前准备 schema 2 的产品线级 `candidate-inventory.json`,其根部固定 `scope: product-line`、`product_id`、`line_branch` 和 active candidate,每项候选保留自己的 `release_id`、commit/status。以 `sync-release-fix --expected-line --production-verification <R09-json> --candidate-inventory <predecessor-R10-json> --successor-candidate-inventory <new-R10-json> --receipt --apply` 受控同步每个成功的 release-fix 到 `line/<product-id>`;脚本只写入新的不可变 successor 库存,在回执中绑定前代/后代库存,并派生、登记带 release ID 的 `stale_candidate_ids` 与 `candidate_status_updates`。main 漂移、候选不一致或遗漏已成功 fix 都使候选 stale。R10 完成并登记 `released` 归档物料后,才通过 `release-archived` 正式回写生产版本和 release ID。生产审批只发生在 R07,并绑定精确 release ID、main 基线、source Tag/commit、候选 commit/Tag、包 checksum、镜像 digest、配置、迁移、环境和回滚镜像;任一项变化均创建新发布候选并重新审批。
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# 工作流与工作流管理器阶段现状
|
|
2
2
|
|
|
3
|
-
更新时间:2026-08-
|
|
3
|
+
更新时间:2026-08-23
|
|
4
4
|
|
|
5
5
|
本文是继续设计、实现或审核 Workflow Manager 时的阶段入口。它区分已经进入正式工作流源码的能力、已经接受但尚未实现的产品决策、仅在隔离原型中验证的交互,以及仍未完成的事项。领域术语以根目录 `CONTEXT.md` 为准,不以本文替代 ADR、正式状态契约或 Issue。
|
|
6
6
|
|
|
7
7
|
## 1. 当前基线
|
|
8
8
|
|
|
9
9
|
- 当前仓库是 `ai-delivery-workflow` 的维护与发行源码仓库,不是安装了工作流的业务项目。
|
|
10
|
-
-
|
|
10
|
+
- 当前维护基线的包版本为 `0.8.0`,本轮维护提交按 breaking cleanup 的 Minor 版本规则准备发行;对应发行提交、Git tag `v0.8.0` 和 npm 包身份须由发布预检与发布后验证固定。`0.4.0`、`0.5.0`、`0.5.1`、`0.6.0`、`0.7.0` 和 `0.7.1` 的提交、Git tag、npm 包身份及校验和/生命周期证据均属于历史记录,仍保存在 `audit/` 中且不可改写;候选包和展开验证工作区保留在被忽略的 `.tmp/`。
|
|
11
11
|
- 正式维护源码位于 `bin/`、`lib/`、`skills/`、`docs/`、`verification/` 和 `audit/`。
|
|
12
12
|
- Workflow Manager 设计原型位于 `prototypes/workflow-manager/`,业务项目原型夹具位于 `prototypes/order-ops-business/`。两者是可版本化设计资产,不进入发行包,也不等于正式前端已经实现;运行时依赖、构建产物和一次性验证工作区仍放在 `.tmp/`。
|
|
13
13
|
|
|
@@ -56,6 +56,7 @@
|
|
|
56
56
|
### 2.4 原型优先 UI 治理
|
|
57
57
|
|
|
58
58
|
- `UX-VS` 负责视觉规范确认,`UX-UI` 负责正式原型审核,两者归入 `02-solution-design`。
|
|
59
|
+
- `06-version-closeout` 不能在候选测试完成后直接启动;必须先规划并登记收尾任务、清空并确认收尾问题,再通过 `VERSION-CLOSEOUT-READINESS` 人工 Gate。
|
|
59
60
|
- 所有用户可见 UI 修改都遵守“先修改隔离 Prototype -> 用户确认 -> 再修改正式前端”,不存在小改、紧急修复或业务逻辑调整例外。
|
|
60
61
|
- 一个项目只有一个逻辑 Prototype。Page 是稳定路由页面,Review Scene 是 Page 的可审核状态;原型必须列出错误、空态、权限、恢复等正式系统中只在条件满足时出现的状态。
|
|
61
62
|
- 页面级 Prototype 审核、Revision/checksum 绑定、Review Shell、Page Receipt、正式前端守卫和 Candidate Assurance UI Acceptance 已进入维护源码。
|
|
@@ -156,17 +157,17 @@ Workflow Manager 从一开始就是人和 AI 共同使用的控制面。UI 与 W
|
|
|
156
157
|
|
|
157
158
|
当前正式浏览器测试遍历全部 19 个 Page,验证 P12 筛选、P13 Scene/Ctrl+V/保存、P14/P15 深链、P14 -> P13 Source Inspection Snapshot、P08 双 Tab/计划节点、P02 列头以及 `1280x720`、`1440x900` 无横向溢出或关键面板重叠;应用控制台无 error/warn。Manager 定向套件 97/97 通过,最终 `index.html` 引用的哈希资源已登记到 Git 索引。
|
|
158
159
|
|
|
159
|
-
### 4.1 `0.4.0` 候选验证
|
|
160
|
+
### 4.1 历史 `0.4.0` 候选验证
|
|
160
161
|
|
|
161
162
|
- 当前 P0/P1/P2 候选包的精确路径、SHA-256、文件数和生命周期报告由维护仓库的 `audit/WORKFLOW-MANAGER-P0-P1-P2-CLOSURE.md` 固定登记。审计记录不在 npm 包范围内,因此不会导致候选包自引用;实际 tarball 和展开验证工作区仍保留在 `.tmp/`。
|
|
162
163
|
- 隔离新安装的 Doctor 除可选 CodeGraph 提示外全部通过;安装后 Manager 的主页、健康检查、`workflow-manager.v1` Schema、19 个 Page、七节点投影、25 个可发现受控动作和 r33 Prototype 投影均已实测。
|
|
163
164
|
|
|
164
|
-
### 4.2 v2 Prototype catalog Candidate Assurance
|
|
165
|
+
### 4.2 历史 v2 Prototype catalog Candidate Assurance
|
|
165
166
|
|
|
166
167
|
- 新安装交付把 v2 Prototype Revision 的运行时、Manager、Agent Interface、Experience Skill 和全部必需 catalog 模板列为包表面。`doctor` 在包表面缺失时立即失败,不再继续计算会因缺失运行时而崩溃的受管资产摘要。
|
|
167
168
|
- 新的生产路径只接受 `prototype-revision-catalog.v2`。Experience Skill、Project Template、安装后的 Manager 与 Candidate Assurance 都从同一 Revision/checksum 读取事实;缺少任一必需 catalog 时由 CLI、HTTP 和 UI 确定性拒绝。
|
|
168
169
|
- `verification/workflow-manager.test.mjs` 的隔离 Candidate Assurance 用当前工作树实际执行 `npm pack`,在 `.tmp/` 的独立 consumer 安装 tarball,并由安装后的 `ai-delivery init` 与 `doctor` 建立项目。它用多 Logical Terminal 的 v2 fixture 证明安装后的 Manager CLI、HTTP 和 P07/P11-P17 浏览器 UI 读取同一 Prototype Revision 身份和 checksum:每个 Web UI 请求和返回都显式为 `TERM-WEB`,P12 的 `TERM-ADMIN` 路由实际显示 Admin 目标而不回退到 Web。Component Candidate 通过 P11 提交 `candidate -> under-review`、已安装 CLI 提交 `under-review -> registered`、HTTP 提交 `registered -> modified`;每次 apply 均产生 Receipt/Event,CLI 与 HTTP 均重放同一幂等键。初始 CLI/HTTP 计划仍返回相同 plan/successor;删除 v2 `components` catalog 后,三种入口返回相同受控拒绝。测试覆盖 `1280x720` 与 `1440x900` 桌面视口,且有效 Revision 路径没有浏览器 console error/warn。
|
|
169
|
-
- 可重建证据和边界记录在 `audit/WORKFLOW-MANAGER-V2-CANDIDATE-ASSURANCE.md`。它不替代 `audit/WORKFLOW-MANAGER-P0-P1-P2-CLOSURE.md`
|
|
170
|
+
- 可重建证据和边界记录在 `audit/WORKFLOW-MANAGER-V2-CANDIDATE-ASSURANCE.md`。它不替代 `audit/WORKFLOW-MANAGER-P0-P1-P2-CLOSURE.md` 的历史候选身份;其中记录的 `0.5.0` 发布闭环属于历史证据,不代表当前 HEAD 已执行发布。生成的 tarball、consumer、缓存和浏览器临时文件都留在被忽略的 `.tmp/` 并在测试结束后删除。
|
|
170
171
|
|
|
171
172
|
## 5. 开放事项
|
|
172
173
|
|
|
@@ -189,7 +190,7 @@ Workflow Manager 从一开始就是人和 AI 共同使用的控制面。UI 与 W
|
|
|
189
190
|
|
|
190
191
|
1. P0/P1/P2 及 Prototype 治理 01–07 已完成;实现提交为 `ae70304`,后续 v2 Candidate Assurance 收尾提交为 `db8abfb`,候选验证与 11 个 Gitee Issue 收尾均已完成。
|
|
191
192
|
2. 后续变更继续沿当前 `.workflow/`、schema 2 与 v2 Prototype Revision 契约推进。
|
|
192
|
-
3. r33
|
|
193
|
+
3. r33 晋级改变了当时的源码候选内容,历史 `0.4.0` r8 候选证据仍不可变且不能复用;该变更当时已在 `0.5.0` 中完成发布闭环。`0.7.1` 维护提交已完成历史记录;本轮 `0.8.0` 清理提交需在账号/2FA、Git 同步和发布后验证完成后才可宣称发行,后续发布仍需从干净且同步的 `main` 重新生成候选。
|
|
193
194
|
|
|
194
195
|
## 6. 继续工作时必须读取的来源
|
|
195
196
|
|
package/lib/delivery-state.mjs
CHANGED
|
@@ -64,6 +64,7 @@ const GATE_DECISIONS = new Set(["approved", "rejected", "blocked", "not-required
|
|
|
64
64
|
const UX_GATE_IDS = new Set(["UX-VS", "UX-UI"]);
|
|
65
65
|
const UX_GATE_NODES = new Set(["02-solution-design"]);
|
|
66
66
|
const PRODUCT_TERMINAL_NODES = new Set(["01-product-shaping"]);
|
|
67
|
+
const VERSION_CLOSEOUT_READINESS_GATE_ID = "VERSION-CLOSEOUT-READINESS";
|
|
67
68
|
const SUCCESSFUL_ARTIFACT_STATUSES = new Set([
|
|
68
69
|
"approved", "valid", "frozen", "immutable", "passed", "deployed", "released",
|
|
69
70
|
"release-ready", "included-in-release", "archived",
|
|
@@ -75,7 +76,11 @@ const NODE_RULES = new Map([
|
|
|
75
76
|
["03-delivery-readiness", { scope: "development", prerequisites: ["02-solution-design"], gates: [] }],
|
|
76
77
|
["04-implementation", { scope: "development", prerequisites: ["03-delivery-readiness"], gates: [] }],
|
|
77
78
|
["05-candidate-assurance", { scope: "development", prerequisites: ["04-implementation"], gates: [] }],
|
|
78
|
-
["06-version-closeout", {
|
|
79
|
+
["06-version-closeout", {
|
|
80
|
+
scope: "development",
|
|
81
|
+
prerequisites: ["05-candidate-assurance"],
|
|
82
|
+
gates: [VERSION_CLOSEOUT_READINESS_GATE_ID],
|
|
83
|
+
}],
|
|
79
84
|
["R00-release-request", { scope: "release", prerequisites: [], gates: [] }],
|
|
80
85
|
["R01-version-selection", { scope: "release", prerequisites: ["R00-release-request"], gates: [] }],
|
|
81
86
|
["R02-release-eligibility", { scope: "release", prerequisites: ["R01-version-selection"], gates: [] }],
|
|
@@ -330,6 +335,7 @@ function pauseForLockRetry() {
|
|
|
330
335
|
function withLock(files, stream, action, lockOptions = {}) {
|
|
331
336
|
const recover = lockOptions.recover !== false;
|
|
332
337
|
const waitForActive = lockOptions.waitForActive === true;
|
|
338
|
+
let waitNotified = false;
|
|
333
339
|
const maximumAttempts = waitForActive ? Number.POSITIVE_INFINITY : 3;
|
|
334
340
|
const waitDeadline = waitForActive
|
|
335
341
|
? Date.now() + (lockOptions.waitTimeoutMs ?? ACTIVE_LOCK_WAIT_TIMEOUT_MS)
|
|
@@ -351,10 +357,20 @@ function withLock(files, stream, action, lockOptions = {}) {
|
|
|
351
357
|
} catch (error) {
|
|
352
358
|
if (error.code !== "EEXIST") throw error;
|
|
353
359
|
if (recover && removeAbandonedLock(lockFile)) continue;
|
|
354
|
-
if (waitForActive
|
|
360
|
+
if (waitForActive
|
|
361
|
+
&& isWaitableFormalLock(lockFile, { allowInitializing: stream !== "formal-state-read" })
|
|
362
|
+
&& Date.now() < waitDeadline) {
|
|
363
|
+
if (!waitNotified && typeof lockOptions.onWait === "function") {
|
|
364
|
+
waitNotified = true;
|
|
365
|
+
lockOptions.onWait({ lockFile, stream });
|
|
366
|
+
}
|
|
355
367
|
pauseForLockRetry();
|
|
356
368
|
continue;
|
|
357
369
|
}
|
|
370
|
+
// A live writer can release the lock between the failed open and metadata
|
|
371
|
+
// inspection. Retry that narrow race; an existing malformed/orphaned lock
|
|
372
|
+
// still falls through to the fail-closed error below.
|
|
373
|
+
if (waitForActive && !fs.existsSync(lockFile) && Date.now() < waitDeadline) continue;
|
|
358
374
|
throw new Error(`Formal state is locked while updating: ${stream}`);
|
|
359
375
|
}
|
|
360
376
|
}
|
|
@@ -371,19 +387,28 @@ function withLock(files, stream, action, lockOptions = {}) {
|
|
|
371
387
|
}
|
|
372
388
|
}
|
|
373
389
|
|
|
374
|
-
function isWaitableFormalLock(lockFile) {
|
|
390
|
+
function isWaitableFormalLock(lockFile, { allowInitializing = false } = {}) {
|
|
375
391
|
try {
|
|
376
392
|
const content = fs.readFileSync(lockFile, "utf8");
|
|
377
393
|
try {
|
|
378
394
|
const owner = JSON.parse(content);
|
|
379
|
-
|
|
395
|
+
if (typeof owner.stream !== "string" || owner.stream.length === 0
|
|
396
|
+
|| owner.stream === "formal-state-read"
|
|
397
|
+
|| !Number.isInteger(owner.pid) || owner.pid <= 0) return false;
|
|
398
|
+
try {
|
|
399
|
+
process.kill(owner.pid, 0);
|
|
400
|
+
return true;
|
|
401
|
+
} catch (error) {
|
|
402
|
+
return error.code === "EPERM";
|
|
403
|
+
}
|
|
380
404
|
} catch {
|
|
405
|
+
if (!allowInitializing) return false;
|
|
381
406
|
const ageMs = Date.now() - fs.statSync(lockFile).mtimeMs;
|
|
382
407
|
return ageMs >= 0 && ageMs < LOCK_METADATA_INITIALIZATION_TIMEOUT_MS;
|
|
383
408
|
}
|
|
384
409
|
} catch (error) {
|
|
385
410
|
// The owner may release the lock between our failed open and metadata read.
|
|
386
|
-
return
|
|
411
|
+
return false;
|
|
387
412
|
}
|
|
388
413
|
}
|
|
389
414
|
|
|
@@ -618,6 +643,60 @@ function artifactFileIntegrity(files, artifact) {
|
|
|
618
643
|
}
|
|
619
644
|
}
|
|
620
645
|
|
|
646
|
+
function validateVersionCloseoutReadinessEvidence(files, artifacts, iterationId, candidateId, options) {
|
|
647
|
+
const readiness = artifacts.find((artifact) =>
|
|
648
|
+
artifact.artifact_type === "version-closeout-readiness"
|
|
649
|
+
&& ["submitted", "pending-approval"].includes(artifact.status),
|
|
650
|
+
);
|
|
651
|
+
if (!readiness) {
|
|
652
|
+
throw new Error(
|
|
653
|
+
"VERSION-CLOSEOUT-READINESS requires a submitted version-closeout-readiness artifact.",
|
|
654
|
+
);
|
|
655
|
+
}
|
|
656
|
+
const integrity = artifactFileIntegrity(files, readiness);
|
|
657
|
+
if (!integrity.valid) {
|
|
658
|
+
throw new Error(
|
|
659
|
+
`Version closeout readiness evidence failed integrity: ${integrity.code}.`,
|
|
660
|
+
);
|
|
661
|
+
}
|
|
662
|
+
const readinessPath = path.resolve(files.root, readiness.path);
|
|
663
|
+
const document = readYaml(readinessPath, options.yaml, "version closeout readiness");
|
|
664
|
+
if (document.schema_version !== 1 || document.artifact_type !== "version-closeout-readiness") {
|
|
665
|
+
throw new Error("Version closeout readiness evidence must use schema 1.");
|
|
666
|
+
}
|
|
667
|
+
if (document.iteration_id !== iterationId) {
|
|
668
|
+
throw new Error("Version closeout readiness evidence iteration does not match the Gate.");
|
|
669
|
+
}
|
|
670
|
+
if (document.candidate_id !== candidateId) {
|
|
671
|
+
throw new Error("Version closeout readiness evidence candidate does not match the selected candidate.");
|
|
672
|
+
}
|
|
673
|
+
const taskPlan = document.task_plan;
|
|
674
|
+
if (!taskPlan || !Array.isArray(taskPlan.task_ids) || taskPlan.task_ids.length === 0
|
|
675
|
+
|| typeof taskPlan.ref !== "string" || typeof taskPlan.checksum !== "string") {
|
|
676
|
+
throw new Error("Version closeout readiness evidence must include a checksummed task plan.");
|
|
677
|
+
}
|
|
678
|
+
const confirmation = document.confirmation_summary;
|
|
679
|
+
if (!confirmation || typeof confirmation.ref !== "string"
|
|
680
|
+
|| typeof confirmation.checksum !== "string" || confirmation.shared_understanding !== true
|
|
681
|
+
|| (Array.isArray(confirmation.unresolved_decisions) && confirmation.unresolved_decisions.length > 0)) {
|
|
682
|
+
throw new Error(
|
|
683
|
+
"Version closeout readiness evidence must include a confirmed, unresolved-free confirmation summary.",
|
|
684
|
+
);
|
|
685
|
+
}
|
|
686
|
+
for (const reference of [taskPlan, confirmation]) {
|
|
687
|
+
const referencedPath = path.resolve(files.root, reference.ref);
|
|
688
|
+
if (!isInside(referencedPath, files.workflow)
|
|
689
|
+
|| !fs.existsSync(referencedPath)
|
|
690
|
+
|| !fs.statSync(referencedPath).isFile()) {
|
|
691
|
+
throw new Error(`Version closeout readiness reference is missing or outside .workflow: ${reference.ref}`);
|
|
692
|
+
}
|
|
693
|
+
if (sha256(fs.readFileSync(referencedPath)) !== reference.checksum) {
|
|
694
|
+
throw new Error(`Version closeout readiness reference checksum mismatch: ${reference.ref}`);
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
return readiness;
|
|
698
|
+
}
|
|
699
|
+
|
|
621
700
|
function latestGateDecisions(scope, node) {
|
|
622
701
|
const attempt = Number(scope.node_attempts[node] || 1);
|
|
623
702
|
const decisions = new Map();
|
|
@@ -935,8 +1014,12 @@ function assertNoPendingTransaction(files) {
|
|
|
935
1014
|
}
|
|
936
1015
|
}
|
|
937
1016
|
|
|
938
|
-
function withReadableFormalState(files, action) {
|
|
939
|
-
return withLock(files, "formal-state-read", action, {
|
|
1017
|
+
function withReadableFormalState(files, action, lockOptions = {}) {
|
|
1018
|
+
return withLock(files, "formal-state-read", action, {
|
|
1019
|
+
recover: false,
|
|
1020
|
+
waitForActive: true,
|
|
1021
|
+
onWait: lockOptions.onWait,
|
|
1022
|
+
});
|
|
940
1023
|
}
|
|
941
1024
|
|
|
942
1025
|
function withZeroWriteFormalState(files, action) {
|
|
@@ -2449,6 +2532,18 @@ function transitionWorkflow(files, flags, options) {
|
|
|
2449
2532
|
bound_at: timestamp,
|
|
2450
2533
|
};
|
|
2451
2534
|
}
|
|
2535
|
+
if (node === "06-version-closeout") {
|
|
2536
|
+
const readiness = [...scope.gate_decisions].reverse().find((decision) =>
|
|
2537
|
+
decision?.node === node
|
|
2538
|
+
&& decision.gate_id === VERSION_CLOSEOUT_READINESS_GATE_ID
|
|
2539
|
+
&& Number(decision.node_attempt || nextAttempt) === nextAttempt,
|
|
2540
|
+
);
|
|
2541
|
+
if (readiness?.decision !== "approved") {
|
|
2542
|
+
throw new Error(
|
|
2543
|
+
"06-version-closeout requires an approved VERSION-CLOSEOUT-READINESS Gate before start.",
|
|
2544
|
+
);
|
|
2545
|
+
}
|
|
2546
|
+
}
|
|
2452
2547
|
scope.active_nodes = [...scope.active_nodes, node];
|
|
2453
2548
|
scope.node_attempts[node] = nextAttempt;
|
|
2454
2549
|
} else if (event === "node-completed") {
|
|
@@ -2533,7 +2628,10 @@ function transitionWorkflow(files, flags, options) {
|
|
|
2533
2628
|
});
|
|
2534
2629
|
if (completionReceipt) result.completion_receipt = completionReceipt;
|
|
2535
2630
|
return result;
|
|
2536
|
-
}, {
|
|
2631
|
+
}, {
|
|
2632
|
+
waitForActive: flags.has("--expected-scope-revision"),
|
|
2633
|
+
onWait: options.onLockWait,
|
|
2634
|
+
});
|
|
2537
2635
|
}
|
|
2538
2636
|
|
|
2539
2637
|
function registeredEvidence(files, evidence, options, node = null) {
|
|
@@ -2569,12 +2667,29 @@ function requestGate(files, flags, options) {
|
|
|
2569
2667
|
if (scope.scope_id !== iterationId) {
|
|
2570
2668
|
throw new Error(`Iteration mismatch for ${scopeName} scope: state is ${scope.scope_id}, command is ${iterationId}.`);
|
|
2571
2669
|
}
|
|
2572
|
-
|
|
2670
|
+
const preNodeCloseoutGate = gateId === VERSION_CLOSEOUT_READINESS_GATE_ID
|
|
2671
|
+
&& node === "06-version-closeout";
|
|
2672
|
+
if (!scope.active_nodes.includes(node)) {
|
|
2673
|
+
if (!preNodeCloseoutGate
|
|
2674
|
+
|| scope.completed_nodes.includes(node)
|
|
2675
|
+
|| !scope.completed_nodes.includes("05-candidate-assurance")) {
|
|
2676
|
+
throw new Error(`Gate node is not active: ${node}`);
|
|
2677
|
+
}
|
|
2678
|
+
}
|
|
2573
2679
|
const pending = scope.pending_gates.map((gate) =>
|
|
2574
2680
|
typeof gate === "string" ? { gate_id: gate, node: null } : gate);
|
|
2575
2681
|
if (pending.some((gate) => gate?.gate_id === gateId)) throw new Error(`Gate is already pending: ${gateId}`);
|
|
2576
2682
|
const evidence = repeatedFlag(flags, "--evidence");
|
|
2577
|
-
registeredEvidence(files, evidence, options, node);
|
|
2683
|
+
const evidenceArtifacts = registeredEvidence(files, evidence, options, node);
|
|
2684
|
+
if (preNodeCloseoutGate) {
|
|
2685
|
+
validateVersionCloseoutReadinessEvidence(
|
|
2686
|
+
files,
|
|
2687
|
+
evidenceArtifacts,
|
|
2688
|
+
iterationId,
|
|
2689
|
+
scope.latest_candidate_id,
|
|
2690
|
+
options,
|
|
2691
|
+
);
|
|
2692
|
+
}
|
|
2578
2693
|
|
|
2579
2694
|
const timestamp = (options.now || (() => new Date().toISOString()))();
|
|
2580
2695
|
const request = {
|
|
@@ -2582,7 +2697,9 @@ function requestGate(files, flags, options) {
|
|
|
2582
2697
|
node,
|
|
2583
2698
|
iteration_id: iterationId,
|
|
2584
2699
|
scope: scopeName,
|
|
2585
|
-
node_attempt:
|
|
2700
|
+
node_attempt: preNodeCloseoutGate
|
|
2701
|
+
? Number(scope.node_attempts[node] || 0) + 1
|
|
2702
|
+
: Number(scope.node_attempts[node] || 1),
|
|
2586
2703
|
evidence,
|
|
2587
2704
|
requested_at: timestamp,
|
|
2588
2705
|
};
|
|
@@ -3208,6 +3325,7 @@ export function executeDeliveryStateCommand(argv, options = {}) {
|
|
|
3208
3325
|
history: flags.has("--history"),
|
|
3209
3326
|
sinceAnchor: flags.has("--since-anchor"),
|
|
3210
3327
|
}),
|
|
3328
|
+
{ onWait: options.onLockWait },
|
|
3211
3329
|
);
|
|
3212
3330
|
} else if (command === "snapshot" && positional[1] === "create") {
|
|
3213
3331
|
result = createFormalSnapshot(files, flags, options);
|
|
@@ -3234,7 +3352,7 @@ export function executeDeliveryStateCommand(argv, options = {}) {
|
|
|
3234
3352
|
scope_manifest: currentScopeManifest(workflowState.development_state),
|
|
3235
3353
|
derived_node_states: deriveNodeStates(files, workflowState, artifactRegistry, options),
|
|
3236
3354
|
};
|
|
3237
|
-
});
|
|
3355
|
+
}, { onWait: options.onLockWait });
|
|
3238
3356
|
} else {
|
|
3239
3357
|
throw new Error(
|
|
3240
3358
|
"Use inspect, verify, rebuild, snapshot create, artifact register/prune, scope freeze/amend/warn, "
|
|
@@ -243,8 +243,13 @@ function managedFilesEqual(left, right) {
|
|
|
243
243
|
|
|
244
244
|
function directoryDigest(root) {
|
|
245
245
|
const hash = crypto.createHash("sha256");
|
|
246
|
-
|
|
247
|
-
|
|
246
|
+
const entries = filesUnder(root)
|
|
247
|
+
.map((file) => ({
|
|
248
|
+
file,
|
|
249
|
+
relative: path.relative(root, file).replaceAll("\\", "/"),
|
|
250
|
+
}))
|
|
251
|
+
.sort((left, right) => left.relative.localeCompare(right.relative));
|
|
252
|
+
for (const { file, relative } of entries) {
|
|
248
253
|
hash.update(relative);
|
|
249
254
|
hash.update("\0");
|
|
250
255
|
hash.update(normalizedManagedContent(file));
|
|
@@ -292,8 +297,14 @@ function exactPathDigest(target) {
|
|
|
292
297
|
|
|
293
298
|
function sourceSetDigest(sources) {
|
|
294
299
|
const hash = crypto.createHash("sha256");
|
|
295
|
-
|
|
296
|
-
|
|
300
|
+
const entries = [...sources]
|
|
301
|
+
.map((item) => ({
|
|
302
|
+
item,
|
|
303
|
+
relative: item.relative.replaceAll("\\", "/"),
|
|
304
|
+
}))
|
|
305
|
+
.sort((left, right) => left.relative.localeCompare(right.relative));
|
|
306
|
+
for (const { item, relative } of entries) {
|
|
307
|
+
hash.update(relative);
|
|
297
308
|
hash.update("\0");
|
|
298
309
|
hash.update(normalizedManagedContent(item.source));
|
|
299
310
|
hash.update("\0");
|
package/lib/workspace.mjs
CHANGED
|
@@ -113,7 +113,10 @@ function initializeWorkflowRepository(workspaceRoot, branch, remote, heads, acti
|
|
|
113
113
|
const current = gitBranch(workspaceRoot);
|
|
114
114
|
if (current !== branch) {
|
|
115
115
|
if (gitHasCommit(workspaceRoot)) {
|
|
116
|
-
throw new Error(
|
|
116
|
+
throw new Error(
|
|
117
|
+
`Existing workflow repository must already use ${branch}; automatic branch changes are not supported. `
|
|
118
|
+
+ `Create or switch to the required branch with 'git switch -c ${branch}' and rerun init.`,
|
|
119
|
+
);
|
|
117
120
|
}
|
|
118
121
|
if (!dryRun) runGit(workspaceRoot, ["symbolic-ref", "HEAD", `refs/heads/${branch}`]);
|
|
119
122
|
}
|
package/package.json
CHANGED
|
@@ -1,20 +1,25 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ai-delivery-close-version
|
|
3
|
-
description: Close an independently verified planned version without publishing it by freezing its candidate, recording cumulative lineage, creating an immutable version-ready tag, advancing the product development line, marking artifacts release-ready, and archiving closed task context. Use after iteration candidate verification passes or when resuming an interrupted version-closeout node.
|
|
3
|
+
description: Close an independently verified planned version without publishing it by first obtaining human closeout-readiness confirmation, planning and registering closeout tasks, freezing its candidate, recording cumulative lineage, creating an immutable version-ready tag, advancing the product development line, marking artifacts release-ready, and archiving closed task context. Use after iteration candidate verification passes or when resuming an interrupted version-closeout node.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Close Planned Version
|
|
7
7
|
|
|
8
|
+
Before starting `06-version-closeout`, obtain the human `VERSION-CLOSEOUT-READINESS` Gate. The Gate is a pre-node decision: it is requested only after the closeout task plan is registered and the current confirmation frontier is empty. Do not activate or mutate the closeout task while this Gate is pending or missing.
|
|
9
|
+
|
|
8
10
|
When closeout finds an unresolved decision or exception, validate the current `confirmation-summary.yaml` through `../ai-delivery-orchestrate/scripts/confirmation-state.mjs`; link confirmed decisions to closeout evidence and keep release intent separate.
|
|
9
11
|
|
|
10
12
|
Finish one planned version and stop before release. Never start a release from this skill.
|
|
11
13
|
|
|
12
14
|
## Preflight
|
|
13
15
|
|
|
14
|
-
1. Recover or
|
|
16
|
+
1. Recover or inspect the completed `05-candidate-assurance` task and read its immutable candidate and completion receipt.
|
|
15
17
|
2. Run `node .workflow/tools/state/state.mjs verify --history`.
|
|
16
18
|
3. Require a passing immutable candidate, a completed Candidate Assurance receipt for that same candidate, a resolved or superseded product impact assessment bound to the candidate, closed version tasks, complete requirement/test/material traceability, and no unresolved blocking defect.
|
|
17
|
-
4.
|
|
19
|
+
4. Create `.workflow/iterations/<version-id>/06-version-closeout/closeout-plan.yaml` with stable closeout task IDs, dependencies, scopes, acceptance criteria, responsibilities, and next actions. Register every known closeout task as `queued` through `$ai-delivery-checkpoint-task` before any closeout task is activated.
|
|
20
|
+
5. Read and validate the node `confirmation-summary.yaml`. Ask the user one frontier question at a time; confirm release-readiness, archive exceptions, and any remaining risk or documentation acceptance. Continue only when `shared_understanding: true` and there are no unresolved decisions.
|
|
21
|
+
6. Write and register `.workflow/iterations/<version-id>/06-version-closeout/closeout-readiness.yaml` as `version-closeout-readiness` with the checksummed task plan and confirmation summary references. Request `VERSION-CLOSEOUT-READINESS` while `05-candidate-assurance` is complete, then stop for the human decision. The state CLI refuses `06-version-closeout` `node-started` until this Gate is approved.
|
|
22
|
+
7. After approval, activate the planned closeout task and continue. Read the preceding version lineage and Git policy. Require the candidate to descend from the current `line/<product-id>` head, except for the first version.
|
|
18
23
|
|
|
19
24
|
## Close The Version
|
|
20
25
|
|
|
@@ -36,4 +41,4 @@ Report the release-ready version, code Tag, workflow Tag, manifest checksum, cum
|
|
|
36
41
|
|
|
37
42
|
Read [version-closeout-contract.md](references/version-closeout-contract.md) before writing outputs.
|
|
38
43
|
|
|
39
|
-
Before closeout, validate the confirmation summary and ensure confirmed product, architecture, standard, and risk decisions have authority references and matching checksums. Deferred or open decisions remain visible in closeout evidence. Closing a version does not imply release intent.
|
|
44
|
+
Before closeout, validate the confirmation summary and ensure confirmed product, architecture, standard, and risk decisions have authority references and matching checksums. The pre-node readiness artifact must reference the queued closeout task plan and a confirmed, unresolved-free summary. Deferred or open decisions block the readiness Gate and remain visible in closeout evidence. Closing a version does not imply release intent.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
artifact_type: version-closeout-readiness
|
|
2
|
+
schema_version: 1
|
|
3
|
+
iteration_id: ITER-0001
|
|
4
|
+
candidate_id: CAND-0001
|
|
5
|
+
task_plan:
|
|
6
|
+
ref: .workflow/iterations/ITER-0001/06-version-closeout/closeout-plan.yaml
|
|
7
|
+
checksum: sha256
|
|
8
|
+
task_ids:
|
|
9
|
+
- TASK-CLOSEOUT-0001
|
|
10
|
+
confirmation_summary:
|
|
11
|
+
ref: .workflow/iterations/ITER-0001/06-version-closeout/confirmation-summary.yaml
|
|
12
|
+
checksum: sha256
|
|
13
|
+
shared_understanding: true
|
|
14
|
+
unresolved_decisions: []
|
|
15
|
+
readiness: pending-human-gate
|
|
@@ -14,7 +14,9 @@
|
|
|
14
14
|
|
|
15
15
|
All outputs live under `.workflow/iterations/<version-id>/06-version-closeout/`, use stable IDs, and are registered through the formal state CLI. A version is `release-ready` only when every checksum resolves and the line fast-forward is proven.
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
Before `06-version-closeout` starts, create and register a checksummed `closeout-readiness.yaml` artifact. It must reference a queued closeout task plan, the exact selected candidate, and a confirmation summary with `shared_understanding: true` and no unresolved decisions. Request the pre-node `VERSION-CLOSEOUT-READINESS` Gate while `05-candidate-assurance` is complete and stop at the human decision boundary. The state CLI rejects `06-version-closeout` `node-started` until that Gate is approved for the next closeout attempt.
|
|
18
|
+
|
|
19
|
+
After the readiness Gate is approved and Candidate Assurance has completed for the same immutable candidate, the `release-ready` closeout revision is registered, `06-version-closeout` is completed, and both immutable Tags are verified, run the formal `version-closed` transition with that artifact ID. This audited event is the only writer of `workflow-state.yaml.latest_line_version_id`. Then create the version-boundary history anchor and archive version tasks to `.workflow/control/archives/versions/<version-id>/`. Verify that the manifest references checksummed task summaries, attempt receipts, scope, candidate, Gate decisions, and that anchor, and that active task/checkpoint shards were removed. The task archive is a separate checkpoint operation and does not replace this formal transition.
|
|
18
20
|
|
|
19
21
|
## Failure rules
|
|
20
22
|
|
|
@@ -73,8 +73,9 @@ Use this producer order:
|
|
|
73
73
|
4. `03-delivery-readiness`: `$ai-delivery-prepare-platform`, `$ai-delivery-plan-iteration`, and `$ai-delivery-design-tests` converge on one approved Slice, dependency, acceptance, task, artifact, environment, and public-test contract; then freeze it with `scope freeze`.
|
|
74
74
|
5. `04-implementation`: `$ai-delivery-develop-iteration` coordinates stable logical-task attempts for implementation, package review, triage, repair, and developer tests. It completes only after selecting and retaining one immutable candidate as evidence.
|
|
75
75
|
6. `05-candidate-assurance`: `$ai-delivery-review-change` and `$ai-delivery-verify-candidate` collect review feedback and independently verify the candidate bound when the node attempt starts. Findings are applied only as an approved `change_set_id`; any candidate-changing repair returns through `04-implementation` and creates a new candidate and assurance attempt.
|
|
76
|
-
7. `06-version-closeout
|
|
77
|
-
8.
|
|
76
|
+
7. Before `06-version-closeout`, `$ai-delivery-close-version` must plan and queue all closeout tasks, resolve the confirmation frontier, and obtain the human `VERSION-CLOSEOUT-READINESS` Gate. The formal state CLI refuses to start `06-version-closeout` without that approval.
|
|
77
|
+
8. `06-version-closeout`: `$ai-delivery-close-version` creates the immutable `version-ready` tag, advances `line/<product-id>`, marks the version `release-ready`, archives closed task/checkpoint shards, and removes them from active recovery collections.
|
|
78
|
+
9. Stop. Continue the next cumulative planned version from the latest line head, or wait for explicit user intent.
|
|
78
79
|
|
|
79
80
|
At every task and version safe point, route eligible feedback and trial observations through `$ai-delivery-evolve-workflow`. Extension behavior begins with the next task or version and never mutates an in-progress execution.
|
|
80
81
|
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
14. Hook 日志只用于脱敏审计和心跳,不得作为任务完成、Gate 批准或正式交付物的替代品,也不得修改正式或 runtime 状态。
|
|
54
54
|
14.1 任何正式前端修改必须先更新隔离 Prototype 并取得用户 Page approval,再冻结 checksummed `frontend-change-scope.yaml` 与 UI Mapping。首次写入每个 UI 路径前运行 `ai-delivery frontend-guard check-file <workspace> --path <path>`;合并、Candidate Assurance 和正式交接前从固定 refs 运行 `ai-delivery frontend-guard verify-diff <workspace> --base <base> --head <head>`,由 independent Git diff 复核。Hook 只做前置防误改,不能替代后者。文案、样式、响应式、无障碍、Page/route 增删和缺陷修复均无例外。
|
|
55
55
|
14.2 UI-bearing candidate 必须在 `05-candidate-assurance` 内运行 `ai-delivery ui-acceptance plan` 和 `verify`,绑定 active attempt、immutable candidate、Prototype revision、Visual Standard、Page receipts、UI Mapping、Scenario Pack 与 pinned Playwright environment。UI Acceptance 不是新节点。Product Backend Mock 不得充当真实后端验收;candidate checksum 改变时返回 `04-implementation` 并创建新 attempt。
|
|
56
|
-
15. 当前研发生产路线在 `06-version-closeout`
|
|
56
|
+
15. 当前研发生产路线在 `06-version-closeout` 结束。进入 `06-version-closeout` 前,必须先规划并登记全部收尾任务为 `queued`,确认版本收尾 `confirmation-summary.yaml` 的问题已清空并由用户确认,然后用 `VERSION-CLOSEOUT-READINESS` 前置 Gate 获得人工批准;正式状态 CLI 在该 Gate 批准前拒绝启动 06。登记 `release-ready` 收尾物料、完成节点并验证不可变身份后,必须通过正式状态 CLI 的 `version-closed` 事件更新累计研发版本,再归档任务上下文;不得直接编辑状态文件,也不得因为版本完成而自动发布。
|
|
57
57
|
16. `product-id` 是首次 bootstrap 时冻结的稳定产品研发线身份,不是仓库、版本或 release 名称。该产品首次开始计划版本时,从当时 `main` 创建一次 `line/<product-id>`;后续计划版本必须从最新 line 开始,不能在每次迭代或发布时重新从 `main` 拉线。`main` 始终表示当前生产验证成功历史。
|
|
58
58
|
17. 只有用户明确提出发布并选择截止版本时,才使用 `$ai-delivery-orchestrate-release`。R00 必须同时记录当时受保护 `main` 的精确 `expected_main`,系统必须计算从当前生产版本到目标版本的连续闭包。增量发布要求该快照仍是 main 且为目标 `version-ready` Tag 的祖先;同版本重发要求目标 Tag 已经可由该快照到达。
|
|
59
59
|
18. R04 只能通过包内 `.agents/skills/ai-delivery-manage-git/scripts/release-git.mjs create-candidate --release-id <id> --release-branch <branch> --expected-main <r00-sha> --source-tag <tag> --source-commit <tag-sha> --receipt <path> --apply` 从该快照创建 release 分支。增量发布以 `--no-ff` 合入一个目标 Tag,结果 `candidate_commit` 是唯一可验证、审批、部署和冻结 release Tag 的身份;同版本重发不新增合并,候选就是 `expected_main`。中间版本 Tag 仅用于闭包和物料追溯。main 漂移或候选不一致时必须标为 `stale`、保留证据并创建新 R00 请求,不得调整旧候选基线。
|
|
@@ -49,7 +49,7 @@ Every formal development and release node uses this same protocol when a user or
|
|
|
49
49
|
| `03-delivery-readiness` | Slice boundaries, dependencies, environments, test policy, budget exceptions | scope manifest, test/platform contracts, or scope amend |
|
|
50
50
|
| `04-implementation` | behavior ambiguity, implementation constraints, risk acceptance, allowed-file changes | task evidence, approved change set, or owning-node return |
|
|
51
51
|
| `05-candidate-assurance` | exceptions, residual risk, test gaps, candidate acceptance | review/verification evidence or producer return |
|
|
52
|
-
| `06-version-closeout` |
|
|
52
|
+
| `06-version-closeout` | closeout task plan, release readiness, unresolved decisions, archive exceptions | `VERSION-CLOSEOUT-READINESS`, version manifest/closeout; release intent remains separate |
|
|
53
53
|
| `R00`-`R10` release | release intent, target selection, eligibility exceptions, production approval, deployment/rollback decisions | release artifacts, `PRODUCTION-APPROVAL`, production evidence |
|
|
54
54
|
|
|
55
55
|
At node entry, read the current summary before asking a question. After each answer, append or supersede the record, recompute the frontier, and link the decision to its authority artifact before advancing. A node may continue without a question only when its evidence proves the decision is agent-verifiable or an approved baseline is unchanged.
|
|
@@ -47,6 +47,8 @@ node .workflow/tools/state/state.mjs gate request --expected-scope-revision <rev
|
|
|
47
47
|
node .workflow/tools/state/state.mjs gate decide --expected-scope-revision <revision> --gate-id <gate-id> --decision <decision> --actor <actor-id> --rationale <text> --evidence <artifact-id>
|
|
48
48
|
```
|
|
49
49
|
|
|
50
|
+
For `06-version-closeout`, request `VERSION-CLOSEOUT-READINESS` after `05-candidate-assurance` is complete but before starting the closeout node. Its evidence must be a submitted `version-closeout-readiness` artifact that binds the queued closeout task plan and a confirmed, unresolved-free confirmation summary. The Gate must be approved by a human before `node-started` is legal.
|
|
51
|
+
|
|
50
52
|
Repeat `--evidence` for multiple evidence IDs. Use `iteration-started` only for development and `release-started` only after explicit user release intent. Other events are `node-started`, `node-completed`, `node-blocked`, `node-unblocked`, `candidate-selected`, `release-selected`, `version-closed`, and `release-archived`.
|
|
51
53
|
|
|
52
54
|
`workflow-state.yaml` schema 2 owns independent `development_state` and `release_state` objects. Each has its own scope ID, revision, node collections, Gate collections, node attempts, and selected identities. Use the owning scope revision for workflow optimistic concurrency. The top-level revision is the serialized audit-stream revision; mutations use the owning scope revision. A release may advance while later cumulative development is active; neither scope resets the other.
|
|
@@ -55,7 +57,7 @@ Repeat `--evidence` for multiple evidence IDs. Use `iteration-started` only for
|
|
|
55
57
|
|
|
56
58
|
## Producer And Release Contracts
|
|
57
59
|
|
|
58
|
-
The installed producer graph is `development-seven-node`: `00-bootstrap -> 01-product-shaping -> 02-solution-design -> 03-delivery-readiness -> 04-implementation -> 05-candidate-assurance -> 06-version-closeout`. Product Shaping owns `GATE-A` and `GATE-B`; Solution Design owns `UX-VS` and `UX-UI
|
|
60
|
+
The installed producer graph is `development-seven-node`: `00-bootstrap -> 01-product-shaping -> 02-solution-design -> 03-delivery-readiness -> 04-implementation -> 05-candidate-assurance -> 06-version-closeout`. Product Shaping owns `GATE-A` and `GATE-B`; Solution Design owns `UX-VS` and `UX-UI`; `06-version-closeout` requires the pre-node `VERSION-CLOSEOUT-READINESS` human Gate. Independent release work uses `R00-release-request` through `R10-release-archive`. Use artifact statuses `release-ready` for a closed unpublished version and `included-in-release` when a specific release has consumed that immutable version manifest.
|
|
59
61
|
|
|
60
62
|
## Artifact Lifecycle And Retention
|
|
61
63
|
|
|
@@ -95,6 +97,6 @@ Trusted formal-state snapshots live under `.workflow/control/snapshots/formal-st
|
|
|
95
97
|
|
|
96
98
|
`snapshot references` is the single trusted projection used by `archive-version`. It validates the latest pointer, anchor, exact snapshots, target scope manifest, and selected immutable candidate under the formal read lock, then returns relative JSON Pointer references and checksums for scope, candidate, every Gate decision, and the history anchor. An optional requested candidate ID is only a consistency assertion and must equal the candidate selected in the anchored workflow state. Missing or mismatched formal evidence fails before task archive files are written; task-state code must not reimplement anchor validation or emit nullable formal references.
|
|
97
99
|
|
|
98
|
-
Formal approval is never inferred. A Gate decision requires an explicit actor, rationale, and registered evidence. A Hook event, chat message, file timestamp, UI state, or successful command alone is not approval.
|
|
100
|
+
Formal approval is never inferred. A Gate decision requires an explicit actor, rationale, and registered evidence. A Hook event, chat message, file timestamp, UI state, or successful command alone is not approval. The closeout readiness evidence must also bind the queued task plan and the confirmed confirmation summary before the pre-node Gate can be requested.
|
|
99
101
|
|
|
100
|
-
Version completion never implies release intent. Registering a `release-ready` artifact or completing `06-version-closeout` must not create an R-node transition. `R00-release-request` requires successful evidence registered on R00 with `artifact_type: release-request`. Mandatory active Gate IDs are `GATE-A`, `GATE-B`, `UX-VS`, `UX-UI`, and `PRODUCTION-APPROVAL`. Only a genuinely non-visual experience scope may use `not-required` for an active UX Gate; the decision must retain its experience evidence and add successful product-terminal evidence from `01-product-shaping` whose artifact type contains `terminal` (the canonical type is `product-terminal-scope`). Gate A, Gate B, and production approval require `approved`.
|
|
102
|
+
Version completion never implies release intent. Registering a `release-ready` artifact or completing `06-version-closeout` must not create an R-node transition. `R00-release-request` requires successful evidence registered on R00 with `artifact_type: release-request`. Mandatory active Gate IDs are `GATE-A`, `GATE-B`, `UX-VS`, `UX-UI`, `VERSION-CLOSEOUT-READINESS`, and `PRODUCTION-APPROVAL`. Only a genuinely non-visual experience scope may use `not-required` for an active UX Gate; the decision must retain its experience evidence and add successful product-terminal evidence from `01-product-shaping` whose artifact type contains `terminal` (the canonical type is `product-terminal-scope`). Gate A, Gate B, and production approval require `approved`.
|
|
@@ -8,7 +8,7 @@ Formal state schema 2 separates `development_state` from `release_state`. The tw
|
|
|
8
8
|
|
|
9
9
|
## Development State Machine
|
|
10
10
|
|
|
11
|
-
`00-bootstrap -> 01-product-shaping(GATE-A -> GATE-B) -> 02-solution-design(UX-VS -> UX-UI) -> 03-delivery-readiness -> 04-implementation -> 05-candidate-assurance -> 06-version-closeout -> release-ready`
|
|
11
|
+
`00-bootstrap -> 01-product-shaping(GATE-A -> GATE-B) -> 02-solution-design(UX-VS -> UX-UI) -> 03-delivery-readiness -> 04-implementation -> 05-candidate-assurance -> VERSION-CLOSEOUT-READINESS (human) -> 06-version-closeout -> release-ready`
|
|
12
12
|
|
|
13
13
|
This is the installed `development-seven-node` producer route. New producer tasks, artifacts, and requested formal transitions use these node IDs. Release nodes `R00-release-request` through `R10-release-archive` remain writable.
|
|
14
14
|
|
|
@@ -24,6 +24,6 @@ Only explicit user release intent may create R00. The user selects a cumulative
|
|
|
24
24
|
|
|
25
25
|
## Gates And Transition Rules
|
|
26
26
|
|
|
27
|
-
Retain discovery Gate A, product Gate B, major architecture decisions, prototype tool selection, mandatory human `UX-VS`/`UX-UI`, standard governance, and exact-package production approval. Product reconciliation after all prototype candidates must be `valid/aligned`; intermediate handoffs use downstream contract validation.
|
|
27
|
+
Retain discovery Gate A, product Gate B, major architecture decisions, prototype tool selection, mandatory human `UX-VS`/`UX-UI`, the pre-node human `VERSION-CLOSEOUT-READINESS` Gate, standard governance, and exact-package production approval. Product reconciliation after all prototype candidates must be `valid/aligned`; intermediate handoffs use downstream contract validation.
|
|
28
28
|
|
|
29
29
|
Advance only from immutable referenced inputs. Mark dependents stale after upstream change. Preserve failed candidates, releases, Tags, and deployment records. Treat image rollback as deployment state, never Git state. On restart reconcile workspace, Git, artifacts, and external systems; never automatically replay production actions.
|