@haiyangbg/buildbeat 2.0.2 → 3.0.1

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.
Files changed (113) hide show
  1. package/CHANGELOG.md +25 -301
  2. package/README.en.md +9 -22
  3. package/README.md +6 -19
  4. package/SKILL.md +169 -220
  5. package/bin/buildbeat.js +14 -2
  6. package/docs/CAPABILITY-MATRIX.md +13 -55
  7. package/docs/README.md +13 -14
  8. package/docs/RELEASING.md +10 -9
  9. package/docs/v2/RFC-0001-product-definition.md +2 -0
  10. package/docs/v2/RFC-0003-workflow-policy.md +2 -0
  11. package/docs/v2/guide/00-how-to-talk.md +3 -3
  12. package/docs/v2/guide/01-quickstart.en.md +163 -0
  13. package/docs/v2/guide/01-quickstart.md +15 -13
  14. package/docs/v2/guide/03-policy-guide.md +1 -1
  15. package/docs/v2/guide/06-evidence-guide.en.md +51 -0
  16. package/docs/v2/guide/06-evidence-guide.md +5 -3
  17. package/docs/v2/guide/07-approval-guide.en.md +115 -0
  18. package/docs/v2/guide/07-approval-guide.md +12 -10
  19. package/docs/v2/guide/10-recovery.en.md +83 -0
  20. package/docs/v2/guide/10-recovery.md +8 -6
  21. package/docs/v2/guide/11-session-handoff.en.md +2 -2
  22. package/docs/v2/guide/11-session-handoff.md +2 -2
  23. package/docs/v2/guide/README.md +4 -10
  24. package/example/.buildbeat/notify.yaml +13 -0
  25. package/example/.buildbeat/observe.yaml +31 -0
  26. package/example/AGENTS.md +67 -13
  27. package/example/BUILDBEAT.md +8 -11
  28. package/example/CLAUDE.md +1 -1
  29. package/example/README.md +17 -67
  30. package/example/delivery/envelope/prompts/builder.md +10 -0
  31. package/example/delivery/envelope/prompts/fixer.md +10 -0
  32. package/example/delivery/envelope/prompts/reviewer.md +13 -0
  33. package/example/delivery/envelope/worker.sh +70 -0
  34. package/example/delivery/work/WORK-EXPORT-DATE-FILTER/decisions.jsonl +3 -0
  35. package/example/delivery/work/WORK-EXPORT-DATE-FILTER/intent.md +24 -0
  36. package/example/delivery/work/WORK-EXPORT-DATE-FILTER/plan.md +20 -0
  37. package/example/delivery/work/WORK-EXPORT-DATE-FILTER/run-config.yaml +66 -0
  38. package/example/delivery/work/WORK-EXPORT-DATE-FILTER/runs/RUN-EXPORT-01/run-record.json +108 -0
  39. package/example/delivery/work/WORK-EXPORT-DATE-FILTER/workflow.yaml +44 -0
  40. package/example/gitignore.template +20 -0
  41. package/example/package.json +13 -0
  42. package/example/pm/decisions.md +3 -15
  43. package/example/src/export.js +25 -0
  44. package/example/src/ledger.js +16 -0
  45. package/example/tests/export.test.js +35 -0
  46. package/example//346/214/207/346/214/245/345/217/260.md +40 -0
  47. package/lessons.md +52 -71
  48. package/package.json +3 -7
  49. package/src/v2/cli/run.js +33 -23
  50. package/src/v2/engine/risk-preset.js +1 -1
  51. package/src/v2/runtime/notify.js +5 -5
  52. package/src/v2/runtime/overview.js +7 -7
  53. package/templates/ARCHITECTURE.md +1 -1
  54. package/templates/contracts/PROTOCOL.md +2 -10
  55. package/templates/gitignore.template +0 -3
  56. package/templates/pm/adr/README.md +1 -1
  57. package/templates/pm/decisions.md +4 -5
  58. package/templates/standards/CODE.md +1 -1
  59. package/templates/standards/DESIGN.md +1 -1
  60. package/templates/standards/REVIEW.md +2 -2
  61. package/templates/standards/STACK.md +2 -8
  62. package/templates/v2/AGENTS.md +18 -18
  63. package/templates/v2/BUILDBEAT.md +2 -3
  64. package/templates/v2/CLAUDE.md +1 -1
  65. package/templates/v2/run-config.example.yaml +1 -1
  66. package/templates/v2//346/214/207/346/214/245/345/217/260.md +6 -6
  67. package/bin/buildbeat-v2.js +0 -18
  68. package/bin/solobaton.js +0 -6
  69. package/docs/CHECKS.md +0 -326
  70. package/docs/CLI.md +0 -245
  71. package/docs/LEGACY-V1.16-MIGRATION.md +0 -54
  72. package/docs/v2/guide/08-migration-v1.md +0 -72
  73. package/example/.buildbeat/manifest.json +0 -45
  74. package/example/ARCHITECTURE.md +0 -39
  75. package/example/contracts/PROTOCOL.md +0 -38
  76. package/example/pm/NOW.md +0 -22
  77. package/example/pm/adr/ADR-0001-local-first-sqlite.md +0 -25
  78. package/example/pm/adr/README.md +0 -7
  79. package/example/pm/archive//344/270/200/346/234/237/evidence/gate1.md +0 -5
  80. package/example/pm/archive//344/270/200/346/234/237/evidence/gate2.md +0 -5
  81. package/example/pm/archive//344/270/200/346/234/237/evidence/gate3.md +0 -5
  82. package/example/pm/archive//344/270/200/346/234/237/evidence/gate4.md +0 -5
  83. package/example/pm/archive//344/270/200/346/234/237/evidence/implementation.md +0 -5
  84. package/example/pm/status//344/272/247/345/223/201.md +0 -20
  85. package/example/pm/status//345/205/250/346/240/210.md +0 -15
  86. package/example/pm/status//346/265/213/350/257/225.md +0 -15
  87. package/example/pm//344/270/200/346/234/237-/347/234/213/346/235/277.md +0 -97
  88. package/example/standards/CODE.md +0 -18
  89. package/example/standards/DESIGN.md +0 -34
  90. package/example/standards/REVIEW.md +0 -16
  91. package/example/standards/STACK.md +0 -31
  92. package/src/cli.js +0 -323
  93. package/src/constants.js +0 -202
  94. package/src/doctor.js +0 -267
  95. package/src/planner.js +0 -251
  96. package/src/project.js +0 -844
  97. package/src/upgrader.js +0 -1249
  98. package/src/v2/presets/risk/legacy-four-gates.yaml +0 -44
  99. package/src/writer.js +0 -534
  100. package/templates/.claude/agents/reviewer.md +0 -62
  101. package/templates/AGENTS.md +0 -85
  102. package/templates/BUILDBEAT.md +0 -13
  103. package/templates/CLAUDE.md +0 -7
  104. package/templates/pm/NOW.md +0 -26
  105. package/templates/pm/changes/README.md +0 -44
  106. package/templates/pm/status/README.md +0 -32
  107. package/templates/pm//345/275/223/346/234/237/347/234/213/346/235/277.md +0 -62
  108. package/templates/scripts/bus-check.sh +0 -1875
  109. package/templates/scripts/design-preview.sh +0 -44
  110. package/templates/scripts/drift-check.sh +0 -112
  111. package/templates/scripts/pre-commit.sh +0 -74
  112. package/templates/scripts/verify-status.sh +0 -105
  113. package/templates//346/214/207/346/214/245/345/217/260.md +0 -58
package/example/AGENTS.md CHANGED
@@ -1,19 +1,73 @@
1
- # AGENTS.md — 简账 工作区 · 工作包路由 + 协作总线
1
+ # AGENTS.md — 简账 工作区 · BuildBeat 协作契约
2
2
 
3
- > 沙盘说明:真项目此文件是完整版(路由表 + §1.5 审美红线 + 十条规则 + 红线,见 [templates/AGENTS.md](../templates/AGENTS.md));沙盘只展示**填好占位符的路由表**,其余段落与模板一致、此处从略。简账的同一 Builder 端到端拥有一期工作包,产品/全栈/测试只是 AI 视角。
4
- > 根上另有一份 `CLAUDE.md`,只是指向本文件的一行指针(见 [templates/CLAUDE.md](../templates/CLAUDE.md))。
3
+ > 本文件走开放标准 `AGENTS.md`,由工作区下的会话按各工具自己的方式装载(Claude Code / Codex / Cursor / Gemini CLI / Aider / Zed 等多数会自动读根目录 `AGENTS.md` 或 `CLAUDE.md`;不自动读的工具由人开场贴给会话——用哪个工具就按它的文档核对一次,不要假设)。目的:每个会话开工即知道「当前工作在哪 / 我是什么视角 / 读哪 / 写哪 / 该调哪条命令」,不靠人转述上下文。
4
+ > **层叠规则**(标准语义):会话从被编辑文件所在目录向上收集沿途所有 `AGENTS.md` 合并,**离得越近优先级越高**。本文件只写全局的(路由 / 协作规则 / 红线),各代码子仓的局部细节写进**该仓自己的 `AGENTS.md`**。
5
+ > 根目录 `CLAUDE.md` 只是一行指针(兼容只认该文件名的工具),内容单点在本文件。单仓项目,没有 `ARCHITECTURE.md` 与 `contracts/`。
6
+ > **本仓运行 BuildBeat**(运行时 `@haiyangbg/buildbeat@3.0.0`,`buildbeat` 由会话调用,人不必手敲)。
5
7
 
6
- ## 1. 工作包路由 —— Builder 端到端负责,会话按 AI 视角隔离
8
+ ## 0. 工作怎么发生(一页流程)
7
9
 
8
- | AI 视角 | cwd | 可写(拥有) | 只读 | 开工先读 | 状态写回 |
9
- |---|---|---|---|---|---|
10
- | **产品**(规格/编排) | `pm/` | `pm/**` | 全仓 | `pm/NOW.md` | 当期看板 + `pm/status/产品.md` |
11
- | **全栈**(实现,含运维) | 工作区根(同持 jz-web、jz-api 两仓) | `jz-web/**` + `jz-api/**`(**按仓分别 stage,不 `git add -A`**) | `pm/*` 当期文件、契约 | 各代码仓自己的 `AGENTS.md` + `pm/NOW.md` | `pm/status/全栈.md`(带 hash)+ 各仓 `CHANGELOG.md` + `contracts/PROTOCOL.md` |
12
- | **测试**(E2E·走查) | `jz-web/` | `tests/**` · 视觉基线 · 走查报告 | 实现 + spec + 设计稿 + 契约 | `pm/NOW.md` + `tests/README.md` | `pm/status/测试.md` + 核查门证据(E2E 报告/视觉 diff/对比图,**落 `pm/archive/<期>/evidence/`,换期零搬运**) |
10
+ 1. **工作项**:每件事一个 `delivery/work/<WORK-ID>/`(`intent.md` 为什么做 + **止损线**(最多几个 Run / 几轮 review / 几小时,越线先问所有者"继续还是砍")+ `plan.md` 怎么做,可选 `env-facts.md` 记踩出来的环境事实);被 digest 绑定接受(`buildbeat accept`)前只是草稿、不产生义务。`overview` 的 `cost:` 行就是止损线的读数。
11
+ 2. **代码工作跑 Run**:`buildbeat start --config <run-config.yaml> --attempt new` → 隔离 worktree 内 Build→Verify→Fix→Review 自动闭环 → **停在合并决定**。push、合并、部署永远是人批之后的人类动作。
12
+ 3. **人怎么知道该做什么**:`buildbeat overview --repo .` 回答「每件事走到哪、下一步该谁」;`inbox` 只列等人批的 Run,每条后面附可复制的下一句命令;`status --run <RUN>` 回答「还在动吗、动了多久、卡没卡」。
13
+ 4. **上线**:生产动作是人的;`release-readback` 预设 + `release` 风险预设把「做之前回读 → 人做 → 做之后回读 → 观察 → 人关窗」记成 L4 证据,任一步失败即停人批。
14
+ 5. **observe 盯生产**:`buildbeat observe run --config .buildbeat/observe.yaml` 一次=一轮只读体检;异常分层(落账→只读诊断→intent 草稿入队 `delivery/observe/intents/`),草稿**绝不自动执行**,人用 `observe triage` 分诊。
15
+ 6. **拍板台账**:平台级真实决策包一行进 `pm/decisions.md`(从 `templates/pm/decisions.md` 拷,`pm/` 下只有这一个文件与可选的 `adr/`);Run 级批准落各 Work 的 `decisions.jsonl`;finding 裁决落 `review-findings.jsonl`。单仓项目没有 `contracts/`。
16
+ 7. **通知**:`.buildbeat/notify.yaml` 配一条通道(URL 只能来自环境变量),Run 停在人批 / 终态 / 疑似卡住会来找人。
17
+ 8. **打扫**:终态 Run 留下的工作树用 `buildbeat gc --repo .` 清(默认只出计划)。工作树在仓内 `.buildbeat/worktrees/`:`.gitignore` 排除 `.buildbeat/runtime/` 与 `.buildbeat/worktrees/`,测试框架的收集范围也要排除 `**/.buildbeat/**`(vitest `exclude`、jest `testPathIgnorePatterns`、pytest `norecursedirs`),否则主干测试会把旧候选的用例一起跑。
18
+ 9. **worker 信封**:`delivery/envelope/`(从 `templates/v2/envelope/` 拷)放 `worker.sh` 与 builder / reviewer / fixer 的 prompt,run 配置 `envelope.prompts` 指向它;换工具只改 run 配置里 `--` 后的命令。**worker 环境事实(写进 prompt)**:worker 的沙箱通常**不能监听端口**,需要起服务或绑定 loopback 的集成测试交给 verify 步,worker 只跑单测与静态检查,不要反复尝试;PATH 只认 POSIX 工具(`grep -E` 不用 `rg`,`find` 不用 `fd`)或在 `requires:` 里声明;verify / 包装脚本发现环境不满足(命令不在 PATH、端口被占、后端 404)就 `exit 75`,内核会当基础设施故障停人、不派 fixer、不扣预算。
13
19
 
14
- > 🔴 同一 Builder 合并多视角的补偿控制:一期候选满足 review-ready(两仓 `HEAD=candidate`、工作树干净、L3/渲染证据绿、无待修)后由 reviewer 全核一次 + 测试视角独立核两端;首次 milestone 前写者自发现问题先自行收敛,只有修改冻结对外语义/不可逆副作用才提前 `risk-delta`。写者≠审者不变,但不边改边审。
15
- > 开工/收工护栏:任意会话开工先跑 `bash scripts/bus-check.sh` + 各仓 `git pull`;收工前回写证据/状态并再跑 `bus-check --strict`,warning/unverified 仍需说明。
20
+ ## 1. 工作包路由 —— Builder 端到端负责,会话按 AI 视角隔离
16
21
 
17
- ## 1.5 UI 规范摘要 / 2. 十条规则 / 2.5 任务包与人批节奏 / 3. 红线
22
+ > 协作单元是需求/功能工作包(= Work)。一个 Builder 对工作包的产品判断、实现、测试、合并与发布证据端到端负责;下表是可调用的 AI 专业视角和文件写边界,不是人类岗位或固定交接流水线。共享事实走 Git(`delivery/` 与 Run 台账)。
18
23
 
19
- (与 [templates/AGENTS.md](../templates/AGENTS.md) 一致,沙盘从略。完整 UI 规范单点见 `standards/DESIGN.md`;规则⑥采用「机器闸常驻 + review-ready 后一次 milestone + P0/P1 合并 closure」;§2.5 规定会话按用户级工作包持续推进,审批分 `STOP_NOW / BATCH_AT_GATE / NO_APPROVAL`,不因每个小任务交还接力棒。)
24
+ | AI 视角 | cwd | 可写(拥有) | 只读 | 开工先读 |
25
+ |---|---|---|---|---|
26
+ | **产品**(规格/编排) | 仓根 | `delivery/**`、`pm/decisions.md` | 全仓 | `buildbeat overview --repo .` |
27
+ | **全栈**(实现) | 仓根 | `src/**`、`tests/**`(Run 内受 `allowedPaths` 机器约束) | `delivery/*` | 所属 Work 的 intent/plan + `run-config.yaml` |
28
+ | **测试**(独立核验) | 仓根 | `tests/**`、独立核验报告(落所属 Work 目录) | 实现 + 规格 | 所属 Work |
29
+
30
+ > 🔴 **边界**:新地盘 `src/export.js` 与 `tests/`;`src/ledger.js` 是记账核心,只维护、改动一律先问人;不得借道写入 `delivery/work/*/runs/`(内核写)。
31
+ > 🔴 **写者≠审者的机器化**:Run 内置 fresh-context 只读 reviewer(快照强制,写入即失败落账);merge 门绑定 candidate + plan + 证据 digest,过期即 stale。
32
+ > **开工/收工护栏**:任意会话开工先各仓 `git pull`,再 `buildbeat overview --repo .`(活动 Work、等人的 Run、成本);收工前再跑一次 `overview` 并把 warning / unverified 原样写进收口。生产状态问 `observe status`,不猜。
33
+
34
+ ## 1.5 UI 规范摘要(非 UI 项目可删)
35
+
36
+ - 延用既定设计语言与 token;每个可见界面处理加载 / 空 / 错误 / 移动端四态。
37
+ - **界面零元注释**:上线的可见界面不得出现给"做的人"看的文字;每次上线核查门必查。
38
+ - UI 交付的拍板对象必须含可渲染证据(真渲染入口 + 截图 digest);静态描述不构成拍板对象。
39
+
40
+ ## 2. 协作规则
41
+
42
+ **① 唯一入口** —— 活动工作看 `delivery/`(`overview` / `inbox`);不另建进度文件、状态文件或看板,进度由内核从台账与 Git 回读。
43
+ **② 接口先落盘再动手** —— 单仓项目没有跨边界契约;对外导出格式(CSV 列序、日期格式)的变化先写进所属 Work 的 plan 并被接受,再动代码。
44
+ **③ 交接靠 candidate hash + 台账** —— Run 停在合并决定时 candidate 已由 Git 回读固定;跨会话接力读 `delivery/work/<id>/` 即知全部事实,hash 不得编造。
45
+ **④ 护栏与不可逆动作** —— 开工 `overview`;部署/改契约/migration 等不可逆动作前再核一次并走人批;exit 0 不消除 `warning/unverified`。
46
+ **⑤ 风险分轨** —— Risk Preset:`fast`(仅 merge 人批)/ `standard`(plan+merge,默认)/ `controlled`(intent+plan+merge+release)/ `release`(上线回读车道)。
47
+ **⑥ 核查门** —— Run 内 reviewer 只读、结构化 findings;`reviewTriage: required` 时 P0/P1 先过人分诊再派 fixer;review 每 Run 默认 2 轮封顶。**完成 = hash + 可核验证据**;标准轨最低 L3,上线必须 L4。`UNVERIFIED` 永不当作通过。
48
+ **⑦ 状态单点** —— 事实进 Run 证据与 Work 记录;进度看 `overview`,度量看 `metrics`(本地只读)。
49
+ **⑧ 视觉问题带图对比** —— 提 UI bug 必附『实现截图 ⟷ 设计稿截图』并排 + 标注差异点。
50
+ **⑨ 单点事实** —— 线上版本只信实查(`observe status` / 部署平台);任何文档不写「当前线上 vX」;每个收敛后的真实决策包只在 `pm/decisions.md` 记一行;历史台账不回改。
51
+ **⑩ 真渲染拍板** —— 有 UI 的拍板对象必须是真渲染证据。
52
+ **⑪ 所有者可见命名进决策卡** —— 域名、服务名、环境名、自停时长、窗口时长等**所有者以后要看见或要念出来的名字与参数**,不由 worker 顺手定:进 intent 或门前决策卡(`BATCH_AT_GATE`),给推荐值和理由(用业务上听得懂的名字,不用内部术语)。
53
+
54
+ ## 2.5 任务包与人批节奏
55
+
56
+ **任务包信封** —— 开工时从用户目标与活动 Work 明确 `objective / in_scope / terminal_condition`(即 Work 的 intent/plan)。默认一个工作包覆盖多个子项;每个会话同时只认领一个。只要仍有安全、可逆、在范围内且能推进目标的工作,会话就继续做,不因子产物完成交还接力棒。
57
+
58
+ **域回复格式** —— 面向用户收口、交接或回复明确检查点时,统一写「已做 → 未做 → 下一步」;已做/未做默认各总结成一句,不习惯性 1234 分条;只有事项性质差异大时才列举,每条仍是"结果+证据"。
59
+
60
+ **审批三级**:`STOP_NOW`(跨发布门 / 扩范围 / 改冻结契约 / 不可逆外部动作 / 接受风险);`BATCH_AT_GATE`(冻结前可逆取舍、默认值、阈值、可见命名——攒到门前一次批 2~5 个);`NO_APPROVAL`(能实查的事实、派生约束、文档归档、普通 P2)。
61
+
62
+ **人批预算** —— 每个工作包、每道门默认 1 个 `BATCH_AT_GATE` 请求;待批项必须带 findings 摘要与风险声明。
63
+
64
+ > **元原则:能实查的不问人** —— 查代码 / 配置 / 部署平台 / `overview` / `status` / `observe status` 能得到的事实,不拿去问用户、不信文档、不信上游转述。
65
+
66
+ ## 3. 红线(每个会话受约束)
67
+
68
+ 1. **凭据不入 git、不出本机**:文档只标位置不写值;本地 .env gitignore + 600;机器闸 = gitleaks pre-commit;Worker 默认 env 白名单;通知 URL 只能来自环境变量。
69
+ 2. **不 `git add -A`**:只 stage 当前工作包拥有的具体文件;各仓分别提交。
70
+ 3. **不未授权部署**、不 force-push、不 `--amend` 已推送历史、不 `--no-verify`。Run 的合并决定只表示候选具备合并条件(`SUCCEEDED` ≠ 已合并),合并/push/发布是其后的人类动作、逐项授权。
71
+ 4. **每次部署完必更对应仓 `CHANGELOG.md`**;部署后 `observe run` 一轮。
72
+ 5. **写者≠审者**:Run 内置只读 reviewer 机器强制;写者转述不构成证据。
73
+ 6. **事实分层**:代码已确认事实 / 运行时待核事实 / 拟议需求 / 已实现行为,四类严格分开;未实查一律写「待核」。
@@ -1,17 +1,14 @@
1
- # BUILDBEAT.md — 本项目的协作骨架版本标记
1
+ # BUILDBEAT.md — 本项目的 BuildBeat 标记
2
2
 
3
- **本项目使用 BuildBeat `v1.21`**(2026-06-10 初次拷入;2026-08-22 升级;2026-08-25 scoped 分发迁移与域回复格式升级;2026-08-28 起随 v2 beta 包分发,v1 脚手架冻结于 v1.21,沙盘示意)
4
- **协调层布局:`默认`**(脚本在 `scripts/`;简账是从零起的项目,根上本来没别的东西 —— 接管存量项目才用紧凑布局)
5
- 来源:<https://github.com/HaiYangBG1/BuildBeat>
3
+ **本项目运行 BuildBeat**:运行时 `@haiyangbg/buildbeat@3.0.0`(2026-09-09 首次接入;查看本机版本 `npm ls -g @haiyangbg/buildbeat`,查看最新 `npm view @haiyangbg/buildbeat@latest version`)
4
+ **装载方式**:会话读根目录 `AGENTS.md`(`CLAUDE.md` 是一行指针);驾驶手册在 BuildBeat Skill `SKILL.md` §0.5
5
+ **活动工作**:`delivery/work/<WORK-ID>/`(intent / plan / run-config / decisions.jsonl / runs/);信封与 worker 包装在 `delivery/envelope/`
6
+ 来源:<https://github.com/HaiYangBG1/BuildBeat>
6
7
 
7
8
  ## 升级
8
9
 
9
- 对照上游 [CHANGELOG.md](https://github.com/HaiYangBG1/BuildBeat/blob/main/CHANGELOG.md),从本文件记录的版本**往后**逐版看「拷出项目升级」标注的文件,同步后更新上面的版本行。拿不准就让 AI 会话对比上游 `templates/` 与本项目对应文件的差异。
10
+ 运行时升级只是 `npm install --global @haiyangbg/buildbeat@latest`,对项目文件零改动;升级后更新上面的版本行。模板(`AGENTS.md` / `指挥台.md` / `delivery/envelope/`)对照上游 [CHANGELOG.md](https://github.com/HaiYangBG1/BuildBeat/blob/main/CHANGELOG.md) 中「模板」条目手工同步,拿不准就让会话对比上游 `templates/v2/` 与本项目对应文件。事件 schema 只增不改,旧 Run 台账不需要迁移。
10
11
 
11
- ## 教学 manifest
12
+ ## 回灌(比升级更重要)
12
13
 
13
- `.buildbeat/manifest.json` 是为本仓文档回归维护的 schema 2 合成快照,它的 hash 锁定当前示例字节。它不证明 npm artifact 或真实 CLI 完成过写入,不是真实项目的安装证据,也不得作为 legacy 项目的复制/重命名来源。真实迁移见 [v1.16 legacy 迁移指南](../docs/LEGACY-V1.16-MIGRATION.md)。
14
-
15
- ## 回灌(比升级更重要)
16
-
17
- 本项目踩到 BuildBeat **没覆盖的新坑** → 回上游 `lessons.md` 登记一条(症状→根因→解药)。换期压缩仪式 checklist 里有"回灌一问",别跳过。
14
+ 本项目踩到 BuildBeat **没覆盖的新坑**(新反模式 / 机制漏洞)→ 回上游 `lessons.md` 登记一条(症状 → 根因 → 解药),提 issue / PR 或直接改上游仓。只回灌真实事故,不回灌猜想。
package/example/CLAUDE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # CLAUDE.md — 指针(🔴 勿在此处写内容)
2
2
 
3
- 本工作区的会话路由、协作总线十条规则、红线,**单点在同目录的 [`AGENTS.md`](AGENTS.md)** —— 请立即读取那份。
3
+ 本工作区的会话路由、协作规则、红线,**单点在同目录的 [`AGENTS.md`](AGENTS.md)** —— 请立即读取那份。
4
4
 
5
5
  > 本文件只为兼容「只认 `CLAUDE.md` 这个文件名的工具」而存在,**永远保持这几行**。
6
6
  > 往这里复制任何规则 = 两份文档必然漂移(上游 `lessons.md` 第 1 条:SSOT 腐烂)。
package/example/README.md CHANGED
@@ -1,75 +1,25 @@
1
- # example/ —— 教学沙盘:虚构项目「简账」跑完一期的快照
1
+ # example/ —— 可直接拷的示例:虚构项目「简账」跑完一个 Work 的快照
2
2
 
3
- > 这里的协议骨架文件展示 `templates/` 对应模板**填好项目事实之后的样子**,status/evidence 则是虚构一期的教学产物;沙盘也刻意启用了可选 standards 与一个 ADR,用来展示“默认不生成、选择后由项目拥有”的完成态。
4
- > 🔴 项目、数据、人物、决策全部虚构(已脱敏);commit hash 均为示意值——真项目里 hash 必须真实可查(`git cat-file -t <hash>`,见 [lessons.md](../lessons.md) 第 11 条)。
5
- > [`.buildbeat/manifest.json`](.buildbeat/manifest.json) 是 schema 2 的**合成教学快照**:其 baseline hash 会由本仓机器检查锁定到当前示例字节,但它不证明 npm artifact 或真实 CLI 写过这些文件,也不是可复制到真实项目的受管基线。
3
+ > 这是一个**单仓、无 UI、一个 Builder 端到端**的最小项目,展示 `templates/` 填好项目事实之后长什么样,以及一个 Work 从立项、接受、Run、合并决定到合并之后,仓库里留下哪些文件。项目、人物、决策全部虚构。
6
4
 
7
- ## 沙盘设定
5
+ ## 里面是什么
8
6
 
9
- - **项目**:「简账」—— 网页记账应用(就是主 README §2 举例的那个)
10
- - **仓**:`jz-web`(前端 React)+ `jz-api`(后端 Node + SQLite),各自独立 git
11
- - **工作包所有权**:同一 Builder 端到端负责;产品 / 全栈 / 测试是 AI 专业视角;**轨道**:标准轨;**部署**:示例 PaaS(沙盘不接真平台)
12
- - **进度**:一期(记账主流程 + 月度报表)已跑完 Gate1→Gate4 上线,尚未换期
7
+ | 路径 | 是什么 | 来源 |
8
+ |---|---|---|
9
+ | `AGENTS.md` / `CLAUDE.md` / `指挥台.md` / `BUILDBEAT.md` | 会话装载入口、一行指针、给人看的操作卡、运行时版本标记 | `templates/v2/` 填好项目名、边界、视角路由 |
10
+ | `gitignore.template` | 拷入后改名 `.gitignore`(npm 包不带点文件,所以这里不带点) | `templates/gitignore.template` |
11
+ | `pm/decisions.md` | 平台级拍板台账:接入时的【BOOTSTRAP】决策包和本 Work 的【EXPORT-1】决策包各一行 | `templates/pm/decisions.md` |
12
+ | `.buildbeat/notify.yaml` / `observe.yaml` | 通知通道(URL 只走环境变量)与只读体检配置的样例 | 按 [Approval 指南](../docs/v2/guide/07-approval-guide.md) / [Evidence 指南](../docs/v2/guide/06-evidence-guide.md) |
13
+ | `delivery/envelope/` | worker 包装脚本 + builder / reviewer / fixer 三份 prompt,末尾补了本项目的环境事实 | `templates/v2/envelope/` |
14
+ | `delivery/work/WORK-EXPORT-DATE-FILTER/` | 一个完整的 Work:`intent.md`(为什么 + 止损线)、`plan.md`、`run-config.yaml`、`workflow.yaml`(官方预设的逐字副本)、`decisions.jsonl`、`runs/RUN-EXPORT-01/run-record.json` | 前四份人写;后两份是运行时产出(见下) |
15
+ | `src/` / `tests/` / `package.json` | 应用本体:`ledger.js` 是"老地盘"(只维护),`export.js` 是本 Work 加了日期筛选之后的样子,`npm test` 是 verify 步跑的真实命令 | 虚构 |
13
16
 
14
- ## 怎么读(建议顺序)
17
+ ## 快照的时点与哪些是机器写的
15
18
 
16
- 1. [pm/NOW.md](pm/NOW.md) —— 任何会话开工第一眼:当前期是什么、去看哪些文件
17
- 2. [pm/一期-看板.md](pm/一期-看板.md) —— 当前工作包如何覆盖多个子项、决策收件箱如何批量收敛,以及阶段门/分工/挂账
18
- 3. [pm/decisions.md](pm/decisions.md) —— 拍板台账:收敛后的真实决策包 + BuildBeat 升级记录(注意部分回答不单独记行)
19
- 4. [pm/status/](pm/status/) —— 三个 AI 视角各写各的状态:带 hash、带证据指针,按工作包/里程碑更新而非每个子任务一条
20
- 5. [pm/archive/一期/evidence/](pm/archive/一期/evidence/) —— 完成工作包和 Gate 令牌引用的可核验证据落点
21
- 6. [contracts/PROTOCOL.md](contracts/PROTOCOL.md) —— 跨仓契约:快照 + 关键对齐点 + 变更记录(含"独立核查"列)
22
- 7. [AGENTS.md](AGENTS.md) / [ARCHITECTURE.md](ARCHITECTURE.md) —— 路由表和全栈总图填好后的样子(根上另有 [CLAUDE.md](CLAUDE.md),只是指向 `AGENTS.md` 的一行指针)
23
- 8. [standards/](standards/) —— 已确认的 STACK/CODE/REVIEW/DESIGN;普通项目可以完全没有此目录
24
- 9. [pm/adr/](pm/adr/) —— 长期技术决定与替代链;普通拍板仍只进 decisions.md
25
- 10. [.buildbeat/manifest.json](.buildbeat/manifest.json) —— schema 2 字段、所有权策略与 baseline hash 的教学快照
19
+ 快照 = **所有者批准合并决定并合并候选之后**的仓库。`decisions.jsonl` 里的三条(接受 intent、接受 plan、合并决定)和 `runs/RUN-EXPORT-01/run-record.json` 不是手写的:它们是把本目录放进一个一次性 Git 仓库、用脚本 worker 代替 `codex exec` 真跑一遍 `accept → doctor → start → approve` 得到的原始输出,只在拷出时去掉了本机路径(运行时本来就不输出绝对路径)。因此 run-record 里的 `candidate` / `base` 两个 commit 指向那个一次性仓库,在你拷出的仓库里查不到——真项目里它们必须可以 `git cat-file -t` 查到。review 的那条 P2 finding 也是脚本 worker 按 reviewer 合同返回的样例。
26
20
 
27
- ## Gate 四态怎么写
21
+ `tests/example-firstrun.test.js` 锁住两件事:这些工件彼此一致(plan 的 digest 与批准对象一致、无绝对路径),以及把本目录原样拷进一个新仓库后,用脚本 worker 能再起一个 Run(`RUN-EXPORT-02`)跑到合并决定,verify 步跑的是本项目真实的 `npm test`。它不证明某个真实模型能完成任务。
28
22
 
29
- `pm/一期-看板.md` 是已完成一期的 live 快照,因此四行都是 `passed`。下面只是语法对照,不要再追加到同一份看板:
23
+ ## 怎么用它起自己的项目
30
24
 
31
- ```md
32
- - Gate1: pending
33
- - Gate2: passed | 决策: `pm/decisions.md:16` | 证据: `pm/archive/一期/evidence/gate2.md`
34
- - Gate3: blocked | 理由: `实现候选尚有 P1 待修`
35
- - Gate4: n/a | 理由: `本工作包无部署或生产发布交付`
36
- ```
37
-
38
- `n/a` 必须同行带非占位的 `理由:`;`passed` 应同行指向已存在的决策表行或归档证据。`blocked` 也应说明真实阻塞,不把“还没做”包装成审批。
39
-
40
- ## 域回复示例
41
-
42
- 下面展示一期实现候选形成时,全栈视角如何面向人收口。这是回复格式示例,status 和证据文件仍是持久事实。
43
-
44
- ```md
45
- ## 全栈视角|✅ 已完成
46
-
47
- ### 已做
48
-
49
- 1. 记账主流程和月度报表已形成可验收候选。
50
- - 证据:`pm/archive/一期/evidence/implementation.md`
51
-
52
- ### 未做
53
-
54
- 1. 黑盒 E2E 和带图走查。
55
- - 原因:需要测试视角独立验收当前候选。
56
-
57
- ### 下一步
58
-
59
- - **本域已完成:** 下一棒是测试视角,负责黑盒 E2E 和带图走查。
60
- ```
61
-
62
- ## Manifest 的教学边界
63
-
64
- - `files` 只记录这份合成快照声明的 8 个基线路径;当前文档字节与 `baselineSha256` 一致,是为了防止教材漂移,不是为 legacy 项目追认历史所有权。
65
- - 可选 `standards/`、`pm/adr/`、业务 status 与 evidence 是基线后的 project-owned 教学内容,不进 manifest。
66
- - 为避免复制可执行 SSOT,沙盘仍从上游引用 scripts/指挥台/Hook;所以这不是可用 `doctor` 证明健康的完整 CLI 安装。
67
- - 真实 v1.16 拷出项目必须按 [legacy 迁移指南](../docs/LEGACY-V1.16-MIGRATION.md) 处理;不得复制本 manifest、重命名 `.solobaton` 文件,或把当前已改过的文件 hash 伪装成安装基线。
68
-
69
- ## 拿它练手(公司内训用法)
70
-
71
- 开一个 AI 会话,把本目录当项目根,说「你是当前工作包的产品视角,开工」——看它能否从 NOW 顺藤摸瓜讲清当前状态;再说「换期到二期」,对照 NOW.md 底部的压缩仪式 checklist,检查它做没做全。
72
-
73
- 若把模板脚本复制进本目录运行 `bus-check --strict`,示意 commit 会按设计触发 `sync.ghost_hash`:这是给教学沙盘保留的负例,不是可发布候选的绿灯。真项目必须换成仓库中可解析的真实 hash;删除或豁免检查都不算修复。
74
-
75
- > scripts/ 不在沙盘里:开工护栏等脚本直接用 [templates/scripts/](../templates/scripts/);指挥台操作卡见 [templates/指挥台.md](../templates/指挥台.md)。
25
+ 不要整目录照抄——项目名、边界、视角、验证命令都是简账的。按 [SKILL.md](../SKILL.md) §8 的"自查 → 少量提问 → 一屏确认 → 生成"走,让会话从 `templates/` 生成;本目录只用来对照"填好之后应该长什么样"。想手动核对命令,按 [快速开始](../docs/v2/guide/01-quickstart.md):把 `run-config.yaml` 里 `--` 后面的 `codex exec …` 换成你实际用的工具,`accept` 之后 `doctor`,再 `start --attempt new`。
@@ -0,0 +1,10 @@
1
+ 你是本 Run 的 builder,在一个隔离的 git worktree 里工作(当前目录)。
2
+
3
+ 1. 读环境变量 `BUILDBEAT_INPUT`(JSON):`workId` / `runId` / `step` / `attempt`。目标与计划在 `delivery/work/<workId>/intent.md` 与 `plan.md`——只做 plan 里写的,plan 没写的记到 `delivery/work/<workId>/notes.md` 交给人,不要顺手做。
4
+ 2. 只改 run 配置 `allowedPaths` 列出的目录(通常是 `src` 与 `tests`);越界改动不会成为候选。
5
+ 3. 不要 `git commit`、不要 `git push`、不要改分支:提交由包装脚本机械完成,push 已被封禁。
6
+ 4. 沙箱通常不能监听端口:需要起服务的集成测试交给 verify 步,你只跑单测与静态检查;PATH 只认 POSIX 工具(`grep -E` 不用 `rg`)。
7
+ 5. 所有者以后要看见或念出来的名字与参数(域名、服务名、环境名、时长)不由你定:写进 `delivery/work/<workId>/notes.md` 给推荐值与理由,等人批。
8
+ 6. 改完自检一次能跑的测试;把做了什么、没做什么、下一步各一句写到 stdout 末尾。
9
+
10
+ 本项目(简账)的环境事实:Node ≥ 20,测试命令 `npm test`(`node --test tests/*.test.js`),零依赖、不用装包;沙箱不能监听端口,本项目也没有需要端口的测试;`src/ledger.js` 是老地盘,只维护、不重构;PATH 只认 POSIX 工具。
@@ -0,0 +1,10 @@
1
+ 你是本 Run 的 fixer,在隔离的 git worktree 里工作(当前目录)。你只修被指出的问题,不做别的。
2
+
3
+ 1. 读环境变量 `BUILDBEAT_INPUT`(JSON):
4
+ - 有 `findings[]`:这是上一轮 review 的结论及裁决状态,**只修 `adjudication` 为 `accepted` 或 `open` 的条目**,`dismissed` 的不碰;
5
+ - 没有 `findings`:说明是 verify 失败进来的。失败日志在主仓 `.buildbeat/runtime/runs/<runId>/logs/verify-<n>.log`(`<n>` 是最近一次 verify 的 attempt;从 worktree 找主仓:`cd "$(git rev-parse --git-common-dir)/.."`),里面有命令、退出码、stdout / stderr。先读日志,再改代码。
6
+ 2. 只改 run 配置 `allowedPaths` 列出的目录;不要 `git commit` / `git push`(提交由包装脚本完成,push 已封禁)。
7
+ 3. 修不了或问题不在代码(环境缺工具、端口被占、后端 404):不要绕,`exit 75`,内核会当基础设施故障停人。
8
+ 4. 改完跑一次相关测试;把修了哪条、没修哪条及原因各一句写到 stdout 末尾。
9
+
10
+ 本项目(简账)的环境事实:Node ≥ 20,测试命令 `npm test`(`node --test tests/*.test.js`),零依赖、不用装包;沙箱不能监听端口,本项目也没有需要端口的测试;`src/ledger.js` 是老地盘,只维护、不重构;PATH 只认 POSIX 工具。
@@ -0,0 +1,13 @@
1
+ 你是本 Run 的 reviewer,只读:不要改任何文件、不要跑会写盘的命令(写入会被快照比对捕获并按失败落账)。
2
+
3
+ 1. 读环境变量 `BUILDBEAT_INPUT`(JSON)。若有 `lastReviewed.range`,只审 `git diff <range>` 的增量;否则审本分支相对 base 的全部改动(`git log --oneline` 与 `git diff HEAD~1` 起步,按需扩大)。
4
+ 2. `BUILDBEAT_INPUT.anchor` 是历史 finding 与人的裁决:**已裁决(accepted / dismissed)的结论不得翻案**;同一问题不要换措辞重提。
5
+ 3. 对照 `delivery/work/<workId>/plan.md`:做了 plan 没写的事、引入了未经批准的可见命名(域名 / 服务名 / 环境名)→ 记 P2。
6
+ 4. 严重度:P0 数据丢失 / 安全 / 不可逆;P1 功能错误或测试未覆盖计划要求的行为;P2 可维护性、命名、边界;P3 建议。只有 P0 / P1 会阻断。
7
+ 5. **最后只输出一个 JSON 对象,不要别的文字**(可以裹一层 ```json 代码栏):
8
+
9
+ ```json
10
+ {"status": "succeeded", "findings": [{"severity": "P1", "summary": "一句话,稳定、可复述、不带时间戳"}]}
11
+ ```
12
+
13
+ 没有问题就 `"findings": []`。每条必须有 `severity`(P0–P3)和 `summary`;缺字段或不是 JSON 会被当成 worker 故障停人,而不是候选缺陷。
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env bash
2
+ # BuildBeat v2 worker 包装:把任意 CLI Agent 接进 Runner 的信封合同。
3
+ #
4
+ # bash delivery/envelope/worker.sh <role> -- <tool command...>
5
+ # role: builder | fixer | planner(写入步) reviewer(只读步)
6
+ #
7
+ # 做的事(每一条都对应 docs/v2/guide/05-worker-contract.md 的一条合同):
8
+ # 1. 工具不在 PATH → exit 75(EX_TEMPFAIL):内核判基础设施故障停人,不派 fixer、不扣预算;
9
+ # 2. 有 $BUILDBEAT_PROMPT 就把 prompt 文本作为最后一个参数追加给工具(codex exec / claude -p 都吃位置参数);
10
+ # 3. 写入步:工具返回后若工作树有改动,机械地 git add -A && git commit(提交动作不交给模型);
11
+ # 4. 只读步:工具的 stdout 落到 $BUILDBEAT_OUTPUT(工具自己写了该文件则不覆盖);不 commit;
12
+ # 5. 工具退出码原样透传;本脚本自己不判断候选好坏——那是 verify 与 review 的事。
13
+ # cwd 已由内核设为该步的隔离 worktree;不要 cd。
14
+ set -uo pipefail
15
+
16
+ role="${1:-}"
17
+ shift || true
18
+ if [ "${1:-}" = "--" ]; then
19
+ shift
20
+ fi
21
+ if [ -z "$role" ] || [ "$#" -eq 0 ]; then
22
+ echo "usage: worker.sh <builder|fixer|planner|reviewer> -- <tool command...>" >&2
23
+ exit 64
24
+ fi
25
+
26
+ tool="$1"
27
+ if ! command -v "$tool" >/dev/null 2>&1; then
28
+ echo "worker.sh: tool not found in PATH: $tool (exit 75 = infrastructure, not a candidate defect)" >&2
29
+ exit 75
30
+ fi
31
+
32
+ input="${BUILDBEAT_INPUT:-{}}"
33
+ run_id="$(printf '%s' "$input" | sed -n 's/.*"runId":"\([^"]*\)".*/\1/p')"
34
+ attempt="$(printf '%s' "$input" | sed -n 's/.*"attempt":\([0-9]*\).*/\1/p')"
35
+
36
+ args=("$@")
37
+ if [ -n "${BUILDBEAT_PROMPT:-}" ] && [ -f "$BUILDBEAT_PROMPT" ]; then
38
+ args+=("$(cat "$BUILDBEAT_PROMPT")")
39
+ fi
40
+
41
+ case "$role" in
42
+ builder|fixer|planner)
43
+ "${args[@]}"
44
+ status=$?
45
+ if [ -n "$(git status --porcelain 2>/dev/null)" ]; then
46
+ git add -A
47
+ git -c user.name="${GIT_AUTHOR_NAME:-buildbeat-worker}" -c user.email="${GIT_AUTHOR_EMAIL:-worker@buildbeat.local}" \
48
+ commit -q -m "${role}: ${run_id:-run} attempt ${attempt:-?}" || status=$?
49
+ fi
50
+ exit "$status"
51
+ ;;
52
+ reviewer)
53
+ if [ -n "${BUILDBEAT_OUTPUT:-}" ]; then
54
+ captured="$(mktemp "${TMPDIR:-/tmp}/bb-review.XXXXXX")"
55
+ "${args[@]}" | tee "$captured"
56
+ status=${PIPESTATUS[0]}
57
+ if [ ! -s "$BUILDBEAT_OUTPUT" ]; then
58
+ cp "$captured" "$BUILDBEAT_OUTPUT"
59
+ fi
60
+ rm -f "$captured"
61
+ exit "$status"
62
+ fi
63
+ "${args[@]}"
64
+ exit $?
65
+ ;;
66
+ *)
67
+ echo "worker.sh: unknown role: $role" >&2
68
+ exit 64
69
+ ;;
70
+ esac
@@ -0,0 +1,3 @@
1
+ {"ts":"2026-09-09T15:09:50.301Z","decisionRef":"A-WORK-EXPORT-DATE-FILTER-1","decision":"approved","transition":"accept-intent","subject":{"artifact":"intent","digest":"sha256:4e0d96de3ff7c5a1fffc8af268ce91784a515ebcc92e6d5ea035d67ef118da92"},"by":"小周"}
2
+ {"ts":"2026-09-09T15:09:50.350Z","decisionRef":"A-WORK-EXPORT-DATE-FILTER-2","decision":"approved","transition":"accept-plan","subject":{"artifact":"plan","digest":"sha256:4f770dd7b20f14c3e64371ec475ea18f0b82e052fba1f3b8649b04d3ac7ec07a"},"by":"小周"}
3
+ {"ts":"2026-09-09T15:09:51.628Z","run":"RUN-EXPORT-01","decisionRef":"D-RUN-EXPORT-01-1","decision":"approved","transition":"enter-wait-merge","subject":{"candidate":"be7e4f9c4d3d5dcd26132f98f660f9e217c47a97","planDigest":"sha256:4f770dd7b20f14c3e64371ec475ea18f0b82e052fba1f3b8649b04d3ac7ec07a","evidenceDigest":"sha256:7c00d8d23d7d1b3f56006f4686a99bd8b3cc0839f105b524cabadd50dfa04f67"},"by":"小周"}
@@ -0,0 +1,24 @@
1
+ # Intent:导出加日期筛选(WORK-EXPORT-DATE-FILTER)
2
+
3
+ ## 为什么做
4
+
5
+ 月底对账只想看当月流水,现在的 CSV 导出是全量的,用户得在表格里再筛一遍。
6
+
7
+ ## 目标
8
+
9
+ `exportCsv(ledger, { from, to })` 支持含端点的日期区间,两端都可以省略;导出格式(列序、金额两位小数)不变。
10
+
11
+ ## 非目标
12
+
13
+ - 不动 `src/ledger.js`(老地盘);
14
+ - 不做界面,没有 UI 交付;
15
+ - 不改 CSV 的列和编码。
16
+
17
+ ## 止损线
18
+
19
+ 最多 2 个 Run、3 轮 review、总计 1 小时 worker 时间;越线先问所有者"继续还是砍"。
20
+
21
+ ## 验收条件
22
+
23
+ - `npm test` 全绿,且新增用例覆盖:无边界、单边界、双边界、区间外为空、坏格式、from>to;
24
+ - review 无 P0/P1。
@@ -0,0 +1,20 @@
1
+ # Plan:导出加日期筛选(WORK-EXPORT-DATE-FILTER)
2
+
3
+ ## 修改范围
4
+
5
+ `src/export.js`、`tests/export.test.js`(allowedPaths:`src`、`tests`)。
6
+
7
+ ## 实现顺序
8
+
9
+ 1. `exportCsv` 增加第二个参数 `options = {}`,读 `from` / `to`;
10
+ 2. 两个边界都按 `YYYY-MM-DD` 校验,坏格式抛 `bad date bound`,`from > to` 抛 `is after`(【EXPORT-1】拍板:不静默);
11
+ 3. 用字符串比较做含端点筛选(ISO 日期字符串可直接比大小);
12
+ 4. `tests/export.test.js` 补:无边界、单边界、双边界、区间外为空、坏格式、from>to。
13
+
14
+ ## 测试方法
15
+
16
+ verify 步跑 `npm test`(`node --test tests/*.test.js`),退出码回读为证据。
17
+
18
+ ## 风险与回滚
19
+
20
+ 只加参数、默认行为不变,老调用方不受影响;候选不合并即无影响,Run 的工作树可整体 `gc`。
@@ -0,0 +1,66 @@
1
+ # 简账 · WORK-EXPORT-DATE-FILTER 的 run 配置。路径相对本文件解析。
2
+ # 起跑前:buildbeat doctor --config <本文件>;起跑:buildbeat start --config <本文件> --attempt new
3
+ repo: ../../..
4
+ work: WORK-EXPORT-DATE-FILTER
5
+ run: RUN-EXPORT
6
+ # 从 $(npm root -g)/@haiyangbg/buildbeat/src/v2/presets/software-delivery.yaml 复制到本目录
7
+ workflow: workflow.yaml
8
+ riskPreset: standard
9
+ entry: build
10
+ allowedPaths:
11
+ - src
12
+ - tests
13
+ reviewTriage: required
14
+ # 对应 intent 的止损线:3 轮 review
15
+ budgets:
16
+ maxAttempts:
17
+ review: 2
18
+ reviewRoundsPerWork: 3
19
+ cache:
20
+ verify: tree
21
+ envelope:
22
+ prompts: ../../envelope/prompts
23
+ vars:
24
+ component: export
25
+ redact:
26
+ - "(token|secret|password|TOKEN|SECRET|PASSWORD)=\\S+"
27
+ requires:
28
+ - command: node
29
+ min: "20"
30
+ # 换工具只改 -- 后面的命令
31
+ workers:
32
+ builder:
33
+ command: bash
34
+ args:
35
+ - delivery/envelope/worker.sh
36
+ - builder
37
+ - --
38
+ - codex
39
+ - exec
40
+ - -s
41
+ - workspace-write
42
+ verifier:
43
+ command: bash
44
+ args:
45
+ - -lc
46
+ - npm test
47
+ reviewer:
48
+ command: bash
49
+ args:
50
+ - delivery/envelope/worker.sh
51
+ - reviewer
52
+ - --
53
+ - codex
54
+ - exec
55
+ - -s
56
+ - read-only
57
+ fixer:
58
+ command: bash
59
+ args:
60
+ - delivery/envelope/worker.sh
61
+ - fixer
62
+ - --
63
+ - codex
64
+ - exec
65
+ - -s
66
+ - workspace-write
@@ -0,0 +1,108 @@
1
+ {
2
+ "run": "RUN-EXPORT-01",
3
+ "work": "WORK-EXPORT-DATE-FILTER",
4
+ "workflow": "software-delivery",
5
+ "terminal": {
6
+ "status": "SUCCEEDED",
7
+ "reason": "final decision approved; the external action (merge) stays manual"
8
+ },
9
+ "events": {
10
+ "from": 1,
11
+ "to": 31,
12
+ "lastDigest": "sha256:fb0aad2e3f356dd8cdd3d12c70421536c9033b6bfdac80808023a49df4509dc8"
13
+ },
14
+ "startedAt": "2026-09-09T15:09:50.530Z",
15
+ "finishedAt": "2026-09-09T15:09:51.628Z",
16
+ "attempts": {
17
+ "build": 1,
18
+ "verify": 1,
19
+ "review": 1
20
+ },
21
+ "budgets": {
22
+ "attempts": {
23
+ "consumed": 3,
24
+ "remaining": 1
25
+ }
26
+ },
27
+ "cost": {
28
+ "reviewRounds": 1,
29
+ "humanWaits": 1,
30
+ "infraFailures": 0,
31
+ "workerMs": 853
32
+ },
33
+ "workspaces": {
34
+ "RUN-EXPORT-01": {
35
+ "repo": ".",
36
+ "branch": "run/RUN-EXPORT-01",
37
+ "worktreePath": ".buildbeat/worktrees/RUN-EXPORT-01",
38
+ "base": "8f4ef5d4a4bd75c7765fbec860c3f5cbf1e0d02f",
39
+ "candidate": "be7e4f9c4d3d5dcd26132f98f660f9e217c47a97"
40
+ }
41
+ },
42
+ "evidence": [
43
+ {
44
+ "ref": ".buildbeat/runtime/runs/RUN-EXPORT-01/logs/build-1.log",
45
+ "kind": "command",
46
+ "subject": "be7e4f9c4d3d5dcd26132f98f660f9e217c47a97",
47
+ "digest": "sha256:1192f1c2a9a09f23c69d2c3935d2f7a0b3945f2b8aab979f811dd508183755c2",
48
+ "status": "passed",
49
+ "grade": "L2"
50
+ },
51
+ {
52
+ "ref": ".buildbeat/runtime/runs/RUN-EXPORT-01/logs/verify-1.log",
53
+ "kind": "command",
54
+ "subject": "be7e4f9c4d3d5dcd26132f98f660f9e217c47a97",
55
+ "digest": "sha256:603a7dd74be408af1575dca2c5a79bc5b211b9de3366812fb70603aa6121fc99",
56
+ "status": "passed",
57
+ "grade": "L2",
58
+ "cacheKey": "sha256:4425cad04706cc2c7f45e5306c573bf756d39d7aa0815d46406810331592e0ea"
59
+ },
60
+ {
61
+ "ref": ".buildbeat/runtime/runs/RUN-EXPORT-01/logs/review-1.log",
62
+ "kind": "command",
63
+ "subject": "be7e4f9c4d3d5dcd26132f98f660f9e217c47a97",
64
+ "digest": "sha256:65b9474c69d677a43341ee0af9f6865ca66a6c620d0ca71e7c1d61e6b806913e",
65
+ "status": "passed",
66
+ "grade": "L2"
67
+ },
68
+ {
69
+ "ref": ".buildbeat/runtime/runs/RUN-EXPORT-01/outputs/review-1.json",
70
+ "kind": "review",
71
+ "subject": "be7e4f9c4d3d5dcd26132f98f660f9e217c47a97",
72
+ "digest": "sha256:7c00d8d23d7d1b3f56006f4686a99bd8b3cc0839f105b524cabadd50dfa04f67",
73
+ "status": "passed",
74
+ "grade": "L2",
75
+ "findings": [
76
+ {
77
+ "severity": "P2",
78
+ "summary": "日期区间用字符串比较依赖 YYYY-MM-DD 格式,已有校验兜底,但可以在 export.js 顶部注释里写明这个前提"
79
+ }
80
+ ]
81
+ }
82
+ ],
83
+ "decisions": [
84
+ {
85
+ "decision": "approved",
86
+ "transition": "enter-wait-merge",
87
+ "subject": {
88
+ "candidate": "be7e4f9c4d3d5dcd26132f98f660f9e217c47a97",
89
+ "planDigest": "sha256:4f770dd7b20f14c3e64371ec475ea18f0b82e052fba1f3b8649b04d3ac7ec07a",
90
+ "evidenceDigest": "sha256:7c00d8d23d7d1b3f56006f4686a99bd8b3cc0839f105b524cabadd50dfa04f67"
91
+ },
92
+ "decisionRef": "D-RUN-EXPORT-01-1"
93
+ }
94
+ ],
95
+ "approvals": [
96
+ {
97
+ "decisionRef": "D-RUN-EXPORT-01-1",
98
+ "transition": "enter-wait-merge",
99
+ "subject": {
100
+ "candidate": "be7e4f9c4d3d5dcd26132f98f660f9e217c47a97",
101
+ "planDigest": "sha256:4f770dd7b20f14c3e64371ec475ea18f0b82e052fba1f3b8649b04d3ac7ec07a",
102
+ "evidenceDigest": "sha256:7c00d8d23d7d1b3f56006f4686a99bd8b3cc0839f105b524cabadd50dfa04f67"
103
+ },
104
+ "stale": false
105
+ }
106
+ ],
107
+ "unverified": []
108
+ }
@@ -0,0 +1,44 @@
1
+ # Official software-delivery preset per docs/v2/RFC-0003-workflow-policy.md §2.
2
+ # Step order defines the happy path (each step chains to the next on
3
+ # "succeeded"); fix sits off-path at the end and is reached only via the
4
+ # explicit failure/findings transitions.
5
+ kind: workflow
6
+ version: 1
7
+ name: software-delivery
8
+ entry: intent
9
+ steps:
10
+ - id: intent
11
+ worker: planner
12
+ - id: spec
13
+ worker: planner
14
+ optional: true
15
+ requiredWhen: ui-delivery
16
+ - id: plan
17
+ worker: planner
18
+ - id: build
19
+ worker: builder
20
+ - id: verify
21
+ worker: verifier
22
+ - id: review
23
+ worker: reviewer
24
+ readonly: true
25
+ - id: wait-merge
26
+ - id: fix
27
+ worker: fixer
28
+ transitions:
29
+ - from: verify
30
+ on: failed
31
+ to: fix
32
+ - from: fix
33
+ on: succeeded
34
+ to: verify
35
+ - from: review
36
+ on: findings-blocking
37
+ to: fix
38
+ terminal:
39
+ - wait-merge
40
+ # Review rounds are capped by default (deploy-campaign charter: two review
41
+ # rounds per run, then a human). Override per project via budgets.maxAttempts.
42
+ budgets:
43
+ maxAttempts:
44
+ review: 2