@haiyangbg/buildbeat 3.0.0 → 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 (39) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.en.md +4 -4
  3. package/README.md +1 -1
  4. package/SKILL.md +1 -1
  5. package/docs/README.md +3 -2
  6. package/docs/RELEASING.md +3 -1
  7. package/docs/v2/guide/01-quickstart.en.md +163 -0
  8. package/docs/v2/guide/01-quickstart.md +4 -2
  9. package/docs/v2/guide/06-evidence-guide.en.md +51 -0
  10. package/docs/v2/guide/06-evidence-guide.md +2 -0
  11. package/docs/v2/guide/07-approval-guide.en.md +115 -0
  12. package/docs/v2/guide/07-approval-guide.md +2 -0
  13. package/docs/v2/guide/10-recovery.en.md +83 -0
  14. package/docs/v2/guide/10-recovery.md +2 -0
  15. package/docs/v2/guide/README.md +4 -4
  16. package/example/.buildbeat/notify.yaml +13 -0
  17. package/example/.buildbeat/observe.yaml +31 -0
  18. package/example/AGENTS.md +73 -0
  19. package/example/BUILDBEAT.md +14 -0
  20. package/example/CLAUDE.md +7 -0
  21. package/example/README.md +25 -0
  22. package/example/delivery/envelope/prompts/builder.md +10 -0
  23. package/example/delivery/envelope/prompts/fixer.md +10 -0
  24. package/example/delivery/envelope/prompts/reviewer.md +13 -0
  25. package/example/delivery/envelope/worker.sh +70 -0
  26. package/example/delivery/work/WORK-EXPORT-DATE-FILTER/decisions.jsonl +3 -0
  27. package/example/delivery/work/WORK-EXPORT-DATE-FILTER/intent.md +24 -0
  28. package/example/delivery/work/WORK-EXPORT-DATE-FILTER/plan.md +20 -0
  29. package/example/delivery/work/WORK-EXPORT-DATE-FILTER/run-config.yaml +66 -0
  30. package/example/delivery/work/WORK-EXPORT-DATE-FILTER/runs/RUN-EXPORT-01/run-record.json +108 -0
  31. package/example/delivery/work/WORK-EXPORT-DATE-FILTER/workflow.yaml +44 -0
  32. package/example/gitignore.template +20 -0
  33. package/example/package.json +13 -0
  34. package/example/pm/decisions.md +8 -0
  35. package/example/src/export.js +25 -0
  36. package/example/src/ledger.js +16 -0
  37. package/example/tests/export.test.js +35 -0
  38. package/example//346/214/207/346/214/245/345/217/260.md +40 -0
  39. package/package.json +2 -1
package/CHANGELOG.md CHANGED
@@ -2,8 +2,15 @@
2
2
 
3
3
  > 本项目吃自己的狗粮(红线④:必更 CHANGELOG)。格式循 Keep a Changelog,倒序。
4
4
 
5
+ ## v3.0.1 — 2026-09-09(补丁:示例项目、英文指南)
6
+
7
+ - **英文指南补齐四篇**:快速开始、Human Approval、Evidence、故障恢复各加 `.en.md`(与中文逐节对应,互相加语言切换行);指南索引、docs 总入口、英文 README 指向英文版。快速开始安装注释里的 `BuildBeat v2 runtime` 改为 3.0.0 实际打印的 `BuildBeat runtime`,信封存在性说明去掉版本号。
8
+ - **示例项目回来了**:`example/` 现在是虚构单仓项目「简账」跑完一个 Work 的快照——填好的 `AGENTS.md` / `指挥台.md` / `BUILDBEAT.md` / `pm/decisions.md`、通知与 observe 配置样例、带项目环境事实的信封、完整的 `delivery/work/WORK-EXPORT-DATE-FILTER/`(intent / plan / run-config / workflow 副本)以及运行时真跑一遍得到的 `decisions.jsonl` 与 `run-record.json`,外加应用本体与真实 `npm test`。随 npm 包与 Claude 插件分发;`tests/example-firstrun.test.js` 锁住工件一致性并把原样拷贝再跑到合并决定。README、docs 索引、SKILL §8.3 指向它。
9
+
5
10
  ## v3.0.0 — 2026-09-09(大版本:只剩一个产品,v1 移除)
6
11
 
12
+ > **发布状态**:`@haiyangbg/buildbeat@3.0.0` 已于 2026-09-09 从 `main`(PR #37,merge commit `0289415`,tag `v3.0.0`)经 OIDC Trusted Publishing 发布到 dist-tag **`latest`**(run 34362068004;publish 一次成功,verify 因 npm 异步处理约 6 分钟才可见而首次超时、版本可见后重跑成功;所有者授权「合并,然后发 3.0.0」)。独立回读(直连 npmjs.org):`latest` = 3.0.0、integrity 与本地 dry-run 一致、attestation、隔离安装只有 `buildbeat` 一个可执行文件、裸调用零写入、包内无 v1 面全过,GitHub Release v3.0.0 标 Latest,证据见 [`docs/V3.0.0-RELEASE-EVIDENCE-2026-09-09.md`](docs/V3.0.0-RELEASE-EVIDENCE-2026-09-09.md)。
13
+
7
14
  > **3.0.0(破坏性变更)**:v1 已移除。需要 v1 文件总线或 `buildbeat doctor/init/adopt/upgrade` 的项目请停留在 2.0.2;3.0.0 起仓库与包只描述一个产品。
8
15
 
9
16
  - **可执行文件只剩 `buildbeat`**:它就是运行时(原 `buildbeat-v2`);`buildbeat-v2` 与 `solobaton` 两个入口删除。新增 `buildbeat --version`。所有文档、模板、信封、`overview` / `inbox` / 通知里可复制的下一句命令统一改名。
package/README.en.md CHANGED
@@ -7,7 +7,7 @@ Context in files. Collaboration through Git. Work keeps moving.
7
7
 
8
8
  BuildBeat is a Git-based AI delivery workflow for humans and AI sessions. Goals, plans, decisions, and delivery records stay in the project, providing a basis for continuing when models, tools, sessions, or the person doing the work change. A build, verify, review, and fix loop moves execution forward; progress and evidence are read back by the kernel from Git and real commands, never taken from a session's own account; key decisions remain human.
9
9
 
10
- [User guides (Chinese)](docs/v2/guide/README.md) · [Session handoffs](docs/v2/guide/11-session-handoff.en.md) · [npm](https://www.npmjs.com/package/@haiyangbg/buildbeat) · [CI](https://github.com/HaiYangBG1/BuildBeat/actions/workflows/ci.yml) · [MIT](LICENSE)
10
+ [Quickstart](docs/v2/guide/01-quickstart.en.md) · [Session handoffs](docs/v2/guide/11-session-handoff.en.md) · [npm](https://www.npmjs.com/package/@haiyangbg/buildbeat) · [CI](https://github.com/HaiYangBG1/BuildBeat/actions/workflows/ci.yml) · [MIT](LICENSE)
11
11
 
12
12
  ## Let go of that irreplaceable chat
13
13
 
@@ -37,7 +37,7 @@ Git manages project facts that need to last. Local files hold execution state. B
37
37
  | `.buildbeat/runtime/` | In-flight events, checkpoints, locks, and raw logs | Local and excluded from Git; needed to recover an active Run |
38
38
  | `.buildbeat/worktrees/` | Each Run's isolated working tree | Preserves candidate code and the working state; keep it when clearing chats |
39
39
 
40
- Filesystem storage does not mean every file belongs in Git. Secrets stay in a protected local environment. Terminal records retain evidence digests and references; retain raw logs separately when the project requires them. See the [evidence guide (Chinese)](docs/v2/guide/06-evidence-guide.md).
40
+ Filesystem storage does not mean every file belongs in Git. Secrets stay in a protected local environment. Terminal records retain evidence digests and references; retain raw logs separately when the project requires them. See the [evidence guide](docs/v2/guide/06-evidence-guide.en.md).
41
41
 
42
42
  ## Different ways to continue the same work
43
43
 
@@ -105,7 +105,7 @@ npm install --global @haiyangbg/buildbeat@latest
105
105
 
106
106
  > Set up BuildBeat for this project. Inspect the code and existing constraints first, then prepare context and execution configuration for the first piece of work.
107
107
 
108
- The session inspects the project and prepares a goal, plan, verification commands, and Worker configuration. Execution starts after your acceptance. See the [quickstart](docs/v2/guide/01-quickstart.md) (Chinese).
108
+ The session inspects the project and prepares a goal, plan, verification commands, and Worker configuration. Execution starts after your acceptance. See the [quickstart](docs/v2/guide/01-quickstart.en.md) and the [example project](example/README.md) (Chinese).
109
109
 
110
110
  **3. Try a handoff.** Once work records are saved, close the old session and open one without its chat history. Or synchronize the records and candidate so another authorized teammate can take over with their own tool:
111
111
 
@@ -148,6 +148,6 @@ Teams collaborate through a shared Git repository and project agreements. BuildB
148
148
 
149
149
  - [Documentation index](docs/README.md): current guides, specifications, and historical records (Chinese).
150
150
  - [Capability matrix](docs/CAPABILITY-MATRIX.md): manual protocol, runtime, plugin, and verification scope (Chinese).
151
- - [Session handoffs](docs/v2/guide/11-session-handoff.en.md) · [Run recovery](docs/v2/guide/10-recovery.md) · [Approval and triage](docs/v2/guide/07-approval-guide.md) (last two in Chinese).
151
+ - [Session handoffs](docs/v2/guide/11-session-handoff.en.md) · [Run recovery](docs/v2/guide/10-recovery.en.md) · [Approval and triage](docs/v2/guide/07-approval-guide.en.md) · [Evidence](docs/v2/guide/06-evidence-guide.en.md).
152
152
  - [Skill](SKILL.md): how a session uses BuildBeat; [lessons](lessons.md): the real incidents behind its mechanisms (Chinese).
153
153
  - [CHANGELOG](CHANGELOG.md) (Chinese) · [Contributing](CONTRIBUTING.md) · [MIT license](LICENSE).
package/README.md CHANGED
@@ -105,7 +105,7 @@ npm install --global @haiyangbg/buildbeat@latest
105
105
 
106
106
  > 用 BuildBeat 接管这个项目。先检查代码和现有约束,为第一项工作准备上下文与运行配置。
107
107
 
108
- 会话先检查项目,补齐目标、计划、验证命令和执行配置;你接受后再启动。完整步骤见 [快速开始](docs/v2/guide/01-quickstart.md)。
108
+ 会话先检查项目,补齐目标、计划、验证命令和执行配置;你接受后再启动。完整步骤见 [快速开始](docs/v2/guide/01-quickstart.md);填好之后长什么样,看 [示例项目](example/README.md)。
109
109
 
110
110
  **3. 试一次接力。** 在工作记录落盘后关闭旧会话,打开一个没有旧聊天历史的新会话;也可以同步记录与候选,让另一位有权限的成员用自己的工具接手:
111
111
 
package/SKILL.md CHANGED
@@ -390,7 +390,7 @@ worker prompt 里要写清三条环境事实(模板 AGENTS 第 ⑨ 条):沙箱
390
390
  - [ ] 8. 收尾一屏:生成了什么 / 默认拿主意的项 / 首跑停在哪、证据在哪 / 下一步由谁做(合并是人的动作)
391
391
  ```
392
392
 
393
- > 可核对的样例:`tests/v2-templates-firstrun.test.js` 用脚本 worker 代替真实模型,从上面的模板走到合并决定(含一次 verify 失败→fixer→重验)。它证明包内路径、配置、信封、提交机制、reviewer 信封连得上;不证明某个真实模型能完成业务任务。
393
+ > 各文件「填好之后长什么样」,参照 [example/](example/README.md)(虚构「简账」项目跑完一个 Work 的快照)。可核对的样例:`tests/v2-templates-firstrun.test.js` 与 `tests/example-firstrun.test.js` 用脚本 worker 代替真实模型,从上面的模板走到合并决定(含一次 verify 失败→fixer→重验)。它证明包内路径、配置、信封、提交机制、reviewer 信封连得上;不证明某个真实模型能完成业务任务。
394
394
 
395
395
  ## 8.5 接管存量项目(10→N 入口:先摸底、划边界、补验证)
396
396
 
package/docs/README.md CHANGED
@@ -7,11 +7,12 @@
7
7
  | 你要做什么 | 读 |
8
8
  |---|---|
9
9
  | 第一次用,在 AI 会话里 | [`v2/guide/00-how-to-talk.md`](v2/guide/00-how-to-talk.md) → 会话读 [`SKILL.md`](../SKILL.md) §0.5 |
10
- | 第一次用,自己敲命令核对 | [`v2/guide/01-quickstart.md`](v2/guide/01-quickstart.md) |
10
+ | 第一次用,自己敲命令核对 | [`v2/guide/01-quickstart.md`](v2/guide/01-quickstart.md) · [English](v2/guide/01-quickstart.en.md) |
11
11
  | 指南索引(日常 / 配置) | [`v2/guide/README.md`](v2/guide/README.md) |
12
12
  | 关闭旧会话后继续,或由其他成员/工具接手 | [`跨会话接续`](v2/guide/11-session-handoff.md) · [English](v2/guide/11-session-handoff.en.md) |
13
13
  | 三个可用面各能做什么(Skill-only / 运行时 / 插件) | [`CAPABILITY-MATRIX.md`](CAPABILITY-MATRIX.md) |
14
14
  | 项目装载入口与信封模板 | [`../templates/v2/`](../templates/v2/AGENTS.md) |
15
+ | 填好之后长什么样:一个 Work 跑到合并决定的快照 | [`../example/`](../example/README.md) |
15
16
 
16
17
  ## 现行:规范与维护
17
18
 
@@ -26,7 +27,7 @@
26
27
 
27
28
  | 类别 | 文件 |
28
29
  |---|---|
29
- | 发布证据 | `V2.0.2-RELEASE-EVIDENCE-2026-09-09.md`(当前 `latest`)、`V2.0.1-RELEASE-EVIDENCE-2026-09-06.md`、`V2.0.0-RELEASE-EVIDENCE-2026-09-05.md`、`V2.0.0-BETA.1~5-RELEASE-EVIDENCE-*.md`、`V1.21-RELEASE-EVIDENCE-2026-08-25.md`、`WP4.3-RELEASE-EVIDENCE-2026-08-25.md` |
30
+ | 发布证据 | `V3.0.0-RELEASE-EVIDENCE-2026-09-09.md`(当前 `latest`)、`V2.0.2-RELEASE-EVIDENCE-2026-09-09.md`、`V2.0.1-RELEASE-EVIDENCE-2026-09-06.md`、`V2.0.0-RELEASE-EVIDENCE-2026-09-05.md`、`V2.0.0-BETA.1~5-RELEASE-EVIDENCE-*.md`、`V1.21-RELEASE-EVIDENCE-2026-08-25.md`、`WP4.3-RELEASE-EVIDENCE-2026-08-25.md` |
30
31
  | 规划与决策(2026-08) | [`V2-PLAN.md`](V2-PLAN.md)(执行基线,已交付)、[`V2-PROPOSAL.md`](V2-PROPOSAL.md)、[`V2-DECISIONS.md`](V2-DECISIONS.md)、[`V2-D2-DECISION-CARD.md`](V2-D2-DECISION-CARD.md)、[《BuildBeat v2:AI 原生软件交付控制平面》](BuildBeat%20v2%EF%BC%9AAI%20%E5%8E%9F%E7%94%9F%E8%BD%AF%E4%BB%B6%E4%BA%A4%E4%BB%98%E6%8E%A7%E5%88%B6%E5%B9%B3%E9%9D%A2.md) |
31
32
  | 迭代与里程碑记录 | `V2-ITERATION-01~08.md`、[`v2/`](v2/) 下的 M1/M2/M4 验收与试点记录 |
32
33
  | 早期版本史 | [`../CHANGELOG-v1.md`](../CHANGELOG-v1.md)(2026-06 ~ 2026-08 的条目原文;当前条目在根 [`CHANGELOG.md`](../CHANGELOG.md)) |
package/docs/RELEASING.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  This runbook governs BuildBeat's public npm distribution. The canonical package is `@haiyangbg/buildbeat` in `HaiYangBG1/BuildBeat`; the only executable is `buildbeat`. No other package name or executable alias receives publications.
4
4
 
5
- Release evidence at source package version `@haiyangbg/buildbeat@3.0.0`; latest independently verified BuildBeat npm distribution `@haiyangbg/buildbeat@2.0.2` (dist-tag `latest`; `next` stays `2.0.0-beta.5`), anchored by annotated tag `v2.0.2` at commit `a077367`, workflow run [34351668694](https://github.com/HaiYangBG1/BuildBeat/actions/runs/34351668694), and archived in [`V2.0.2-RELEASE-EVIDENCE-2026-09-09.md`](V2.0.2-RELEASE-EVIDENCE-2026-09-09.md). The 2.0.1 chain (`latest` from 2026-09-06 until 2.0.2 took over on 2026-09-09) stays archived in [`V2.0.1-RELEASE-EVIDENCE-2026-09-06.md`](V2.0.1-RELEASE-EVIDENCE-2026-09-06.md). The 2.0.0 chain (`latest` from 2026-09-05 until 2.0.1 took over on 2026-09-06) stays archived in [`V2.0.0-RELEASE-EVIDENCE-2026-09-05.md`](V2.0.0-RELEASE-EVIDENCE-2026-09-05.md). The beta.5 chain stays archived in [`V2.0.0-BETA.5-RELEASE-EVIDENCE-2026-09-05.md`](V2.0.0-BETA.5-RELEASE-EVIDENCE-2026-09-05.md). The beta.4 chain stays archived in [`V2.0.0-BETA.4-RELEASE-EVIDENCE-2026-09-03.md`](V2.0.0-BETA.4-RELEASE-EVIDENCE-2026-09-03.md); the beta.3 chain in [`V2.0.0-BETA.3-RELEASE-EVIDENCE-2026-09-01.md`](V2.0.0-BETA.3-RELEASE-EVIDENCE-2026-09-01.md). The beta.2 chain stays archived in [`V2.0.0-BETA.2-RELEASE-EVIDENCE-2026-08-28.md`](V2.0.0-BETA.2-RELEASE-EVIDENCE-2026-08-28.md); the beta.1 chain stays archived in [`V2.0.0-BETA.1-RELEASE-EVIDENCE-2026-08-28.md`](V2.0.0-BETA.1-RELEASE-EVIDENCE-2026-08-28.md). Earlier distributions and the retired legacy package name are archived in the dated evidence files under `docs/`.
5
+ Release evidence at source package version `@haiyangbg/buildbeat@3.0.1`; latest independently verified BuildBeat npm distribution `@haiyangbg/buildbeat@3.0.0` (dist-tag `latest`; `next` stays `2.0.0-beta.5`), anchored by annotated tag `v3.0.0` at commit `0289415`, workflow run [34362068004](https://github.com/HaiYangBG1/BuildBeat/actions/runs/34362068004), and archived in [`V3.0.0-RELEASE-EVIDENCE-2026-09-09.md`](V3.0.0-RELEASE-EVIDENCE-2026-09-09.md). The 2.0.2 chain (`latest` from 2026-09-09 until 3.0.0 took over the same day; the last version carrying the removed generation) stays archived in [`V2.0.2-RELEASE-EVIDENCE-2026-09-09.md`](V2.0.2-RELEASE-EVIDENCE-2026-09-09.md). The 2.0.1 chain (`latest` from 2026-09-06 until 2.0.2 took over on 2026-09-09) stays archived in [`V2.0.1-RELEASE-EVIDENCE-2026-09-06.md`](V2.0.1-RELEASE-EVIDENCE-2026-09-06.md). The 2.0.0 chain (`latest` from 2026-09-05 until 2.0.1 took over on 2026-09-06) stays archived in [`V2.0.0-RELEASE-EVIDENCE-2026-09-05.md`](V2.0.0-RELEASE-EVIDENCE-2026-09-05.md). The beta.5 chain stays archived in [`V2.0.0-BETA.5-RELEASE-EVIDENCE-2026-09-05.md`](V2.0.0-BETA.5-RELEASE-EVIDENCE-2026-09-05.md). The beta.4 chain stays archived in [`V2.0.0-BETA.4-RELEASE-EVIDENCE-2026-09-03.md`](V2.0.0-BETA.4-RELEASE-EVIDENCE-2026-09-03.md); the beta.3 chain in [`V2.0.0-BETA.3-RELEASE-EVIDENCE-2026-09-01.md`](V2.0.0-BETA.3-RELEASE-EVIDENCE-2026-09-01.md). The beta.2 chain stays archived in [`V2.0.0-BETA.2-RELEASE-EVIDENCE-2026-08-28.md`](V2.0.0-BETA.2-RELEASE-EVIDENCE-2026-08-28.md); the beta.1 chain stays archived in [`V2.0.0-BETA.1-RELEASE-EVIDENCE-2026-08-28.md`](V2.0.0-BETA.1-RELEASE-EVIDENCE-2026-08-28.md). Earlier distributions and the retired legacy package name are archived in the dated evidence files under `docs/`.
6
6
 
7
7
  ## Channels and branches
8
8
 
@@ -118,6 +118,8 @@ gh workflow run publish.yml --ref main -f tag=vX.Y.Z
118
118
  gh run watch --exit-status
119
119
  ```
120
120
 
121
+ npm now processes a publish asynchronously (`npm publish` prints "being processed and may take a few minutes"); the verify job waits up to ten minutes for the exact version, the dist-tag and the provenance to read back. If it still fails **only** on readback, wait for `npm view` to show the version and re-run the failed job (`gh run rerun <run-id> --failed`); never publish again. Real incident: 3.0.0 became readable about six minutes after `npm publish` returned.
122
+
121
123
  The workflow waits for exact registry-version readback, requires `dist.attestations` to expose an npm attestation URL with the SLSA v1 provenance predicate, installs the public package into a clean temporary prefix, checks its executable version, and runs `npm audit signatures`. The release operator must still repeat the isolated-install and read-only `doctor` check independently before publishing the matching GitHub Release. Never use `workflow_dispatch` to bypass the repository's human merge or tag Gate.
122
124
 
123
125
  Trusted Publishing removes the long-lived write token and automatically emits provenance for supported public GitHub repositories. Configure the exact owner, repository, workflow filename, allowed `npm publish` action, and the exact `npm-publish` environment on npmjs.com. A GitHub Environment without the matching npm-side environment binding is not sufficient evidence. See npm's [Trusted Publishing](https://docs.npmjs.com/trusted-publishers/) and [provenance](https://docs.npmjs.com/generating-provenance-statements/) documentation.
@@ -0,0 +1,163 @@
1
+ # Quickstart: your first Run
2
+
3
+ [简体中文](01-quickstart.md) | **English**
4
+
5
+ Goal: in a real Git repository, let the Runner drive Build → Verify → Review to completion and **stop at the merge decision**, which you make with the evidence in front of you. The order is fixed: install → prepare the Work → write the run config → accept the plan → doctor → start → read the evidence and decide. Every step says what success looks like. How long it takes depends on your workers and the task; this page promises no numbers.
6
+
7
+ > People who use BuildBeat inside an AI session never type these commands: `SKILL.md` §0.5 is the driving manual the session reads, and you just say "start", "where are we", "approve". This page shows what runs behind the session so you can check it.
8
+
9
+ ## 0. Install
10
+
11
+ ```bash
12
+ npm install --global @haiyangbg/buildbeat@latest
13
+ buildbeat | head -3 # printing "BuildBeat runtime" plus the usage means the install worked
14
+ ```
15
+
16
+ Stable releases live on `@latest`; there is exactly one executable, `buildbeat` (the runtime this page uses). `@next` is only for pre-releases. Requirements: Node ≥ 20, Git, bash, zero runtime dependencies.
17
+
18
+ > Before continuing, confirm that `$(npm root -g)/@haiyangbg/buildbeat/templates/v2/envelope/` exists. If it does not, reinstall with `npm install --global @haiyangbg/buildbeat@latest`.
19
+
20
+ ## 1. Prepare the Work (Git plane)
21
+
22
+ In the target repository, create the Work directory and write the intent and the plan (their digests get bound into the approval subject), copy the official workflow preset next to the Work (copy, do not reference the install directory: the workflow file's digest is recorded in the Run and travels with the project in Git), then copy the envelope templates (worker wrapper script plus three prompts) into the repository-level `delivery/envelope/`:
23
+
24
+ ```bash
25
+ BB="$(npm root -g)/@haiyangbg/buildbeat"
26
+ mkdir -p delivery/work/WORK-DEMO-1
27
+ printf "# Intent\nAdd date filtering to the CSV export.\nStop-loss: at most 3 Runs, 4 review rounds.\n" > delivery/work/WORK-DEMO-1/intent.md
28
+ printf "# Plan\n1. Add from/to parameters in src/export.js; 2. add boundary cases under tests/.\n" > delivery/work/WORK-DEMO-1/plan.md
29
+ cp "$BB/src/v2/presets/software-delivery.yaml" delivery/work/WORK-DEMO-1/workflow.yaml
30
+ cp -R "$BB/templates/v2/envelope" delivery/envelope
31
+ git add delivery && git commit -qm "buildbeat: work WORK-DEMO-1 + envelope"
32
+ ```
33
+
34
+ The envelope must be committed: workers run in an isolated worktree and only see committed files. `delivery/envelope/worker.sh <role> -- <tool command…>` takes care of "exit 75 when the tool is not on PATH, append the prompt as the last argument, commit mechanically after a writing step, capture stdout as the envelope for a read-only step"; the three prompts only need the project's environment facts added ([Worker contract](05-worker-contract.md), Chinese).
35
+
36
+ ## 2. Write the run config
37
+
38
+ `delivery/work/WORK-DEMO-1/run-config.yaml`. Paths resolve relative to **this file**; the YAML is a strict subset: block lists and block maps only, no inline `[]` / `{}`, no anchors, comments on their own line. The config below parses as-is (machine-checked by `tests/v2-templates-firstrun.test.js`); the full sample and the envelope templates are in [`templates/v2/`](../../../templates/v2/run-config.example.yaml).
39
+
40
+ ```yaml
41
+ repo: ../../..
42
+ work: WORK-DEMO-1
43
+ run: RUN-DEMO
44
+ workflow: workflow.yaml
45
+ riskPreset: standard
46
+ entry: build
47
+ allowedPaths:
48
+ - src
49
+ - tests
50
+ reviewTriage: required
51
+ envelope:
52
+ prompts: ../../envelope/prompts
53
+ workers:
54
+ builder:
55
+ command: bash
56
+ args:
57
+ - delivery/envelope/worker.sh
58
+ - builder
59
+ - --
60
+ - codex
61
+ - exec
62
+ - -s
63
+ - workspace-write
64
+ verifier:
65
+ command: bash
66
+ args:
67
+ - -lc
68
+ - npm test
69
+ reviewer:
70
+ command: bash
71
+ args:
72
+ - delivery/envelope/worker.sh
73
+ - reviewer
74
+ - --
75
+ - codex
76
+ - exec
77
+ - -s
78
+ - read-only
79
+ fixer:
80
+ command: bash
81
+ args:
82
+ - delivery/envelope/worker.sh
83
+ - fixer
84
+ - --
85
+ - codex
86
+ - exec
87
+ - -s
88
+ - workspace-write
89
+ ```
90
+
91
+ - `workers.<role>` is any CLI: to switch tools, change only what follows `--` (`claude -p`, any script), see the [Adapter guide](04-adapter-guide.md) (Chinese); the reviewer's output format is in the [Worker contract](05-worker-contract.md) (Chinese) and already spelled out in the prompt template.
92
+ - **`fixer` is not optional**: without it, a failed verify or a blocking review stops the Run at `WAITING_HUMAN` (reason `no adapter configured for worker fixer`) waiting for you to fix by hand; nothing gets fixed automatically.
93
+ - Worker subprocesses receive only `PATH HOME LANG LC_ALL TMPDIR TERM USER SHELL` by default; inject anything else by name with `env:` ([Adapter guide](04-adapter-guide.md), Chinese).
94
+ - `reviewTriage: required` routes P0/P1 findings through you before a fixer is dispatched; delete the line if you do not want that.
95
+
96
+ ## 3. Accept the plan
97
+
98
+ The `standard` preset requires the plan to be an accepted artifact before build (`controlled` also requires the intent). Acceptance is digest-bound: edit the plan after accepting it and the acceptance expires on its own; `doctor` reports `stale`.
99
+
100
+ ```bash
101
+ buildbeat accept --repo . --work WORK-DEMO-1 --artifact plan --by <your name>
102
+ ```
103
+
104
+ Success: it prints `accepted plan as A-WORK-DEMO-1-<n>` and `digest: sha256:…`.
105
+
106
+ ## 4. doctor: read what start will read, before starting
107
+
108
+ ```bash
109
+ buildbeat doctor --config delivery/work/WORK-DEMO-1/run-config.yaml
110
+ ```
111
+
112
+ Check section by section: declared versus actual enforcement for each entry under `policies`; whether each worker under `worker isolation` is `env allowlist` or `WARNING inherit`; `push protection`; the per-step budgets; under `work artifacts`, whether intent and plan exist, are accepted, are stale, and the preview of where `start` will stop. A `WARNING` does not mean you cannot run, but you should know what it means; exit code 0 does not mean everything is ready.
113
+
114
+ ## 5. Start the Run; it stops for a human
115
+
116
+ ```bash
117
+ buildbeat start --config delivery/work/WORK-DEMO-1/run-config.yaml --attempt new
118
+ ```
119
+
120
+ `--attempt new` numbers the run automatically (`RUN-DEMO-01/02…`) and supersedes older Runs of the same Work that are still waiting for a human. The Runner will: open an isolated worktree (branch `run/RUN-DEMO-01`, pushing to the configured remote is blocked) → the builder produces a commit and the candidate is pinned → the verifier really runs the tests (the exit code is read back as evidence) → the reviewer produces structured findings read-only → the Run reaches `WAITING_HUMAN`.
121
+
122
+ When starting from inside an AI session, detach the process (`nohup` / `setsid`); otherwise the host session's timeout kills the Run.
123
+
124
+ **What success looks like**: the output ends with `status: WAITING_HUMAN`, and `waiting on human:` is followed by `enter-wait-merge` (the merge decision) or `enter-fix` (triage). **Stopping with `infra` is an environment problem, not a code problem**: timeouts, crashes, non-JSON envelopes and exit code 75 all count; fix the worker or the environment, then `approve --transition resume-<step>` to continue. No budget is consumed.
125
+
126
+ ## 6. Read the evidence, decide
127
+
128
+ ```bash
129
+ buildbeat overview --repo . # where each Work is, whose move is next, what it has cost
130
+ buildbeat inbox --repo . # Runs waiting for you, each with the copyable next command
131
+ buildbeat status --repo . --run RUN-DEMO-01 # steps, durations, evidence, findings, the reason it waits
132
+ ```
133
+
134
+ Before approving, look at: the candidate SHA, the verify exit code and log, every review finding. Then run the line `inbox` gives you, usually:
135
+
136
+ ```bash
137
+ buildbeat approve --repo . --run RUN-DEMO-01 --transition enter-wait-merge --by <your name> --config delivery/work/WORK-DEMO-1/run-config.yaml
138
+ ```
139
+
140
+ **Be clear about which step you are approving** ([Approval guide](07-approval-guide.en.md)): `enter-wait-merge` is the merge decision; the Run reaches the terminal state `SUCCEEDED`, meaning the candidate is fit to merge. The actual merge, push and release are always your actions outside the Runner. `enter-fix` / `resume-<step>` are non-terminal transitions: after approving them, `resume --config …` lets the Run continue. When findings block, the Run routes fix → verify → review on its own; when the budget is exhausted or a failure fingerprint repeats, it stops and hands back to you ([Recovery](10-recovery.en.md)).
141
+
142
+ ## 7. Walk the failure branch once
143
+
144
+ To see the automatic repair loop, commit a failing test case under `tests/` and `start --attempt new` again: verify fails → the fixer repairs with the failure summary → verify reruns → review. `status` shows `step fix: SUCCEEDED` and a second `verify`. To route findings through your hands first: `reviewTriage: required` together with `findings list` / `findings adjudicate` adjudicates fingerprint by fingerprint; a dismissed fingerprint no longer blocks.
145
+
146
+ ## 8. Recovery, notifications, cleanup
147
+
148
+ - Process killed / machine rebooted: `resume --config <run-config.yaml>`, see [Recovery](10-recovery.en.md).
149
+ - You fixed the problem yourself in the worktree and committed it: `resume --config … --adopt <sha> --by <name>` skips the fixer and continues from verify.
150
+ - Not watching the screen: configure one DingTalk / webhook channel in `.buildbeat/notify.yaml` (the URL comes only from an environment variable) and the Run finds you when it stops ([Approval guide](07-approval-guide.en.md)).
151
+ - Worktrees left by terminal Runs: `gc --repo .` prints the plan first, `--apply true` cleans.
152
+ - To dry-run a single step before a real Run: `preflight --step <id>` (main checkout, minute-scale, produces no evidence); declare the envelope's environment dependencies with `requires:` so they are checked fail-closed before start ([Workflow guide](02-workflow-guide.md), Chinese).
153
+
154
+ ## 9. observe: let the system watch production (v0)
155
+
156
+ ```bash
157
+ cp "$(npm root -g)/@haiyangbg/buildbeat/src/v2/presets/observe.yaml" .buildbeat/observe.yaml # replace with the project's real probes
158
+ buildbeat observe run --config .buildbeat/observe.yaml # one invocation = one cycle; leave scheduling to cron
159
+ buildbeat observe status --repo .
160
+ buildbeat observe triage --repo . --intent delivery/observe/intents/INTENT-<fp>.md --action fix_now --by <you>
161
+ ```
162
+
163
+ A probe fails or cannot collect → evidence `failed` / `unverified` → bands escalate (record → read-only diagnosis → Intent draft queued). Drafts are **never executed automatically**; `dismiss` feeds the threshold back so the same fingerprint stays quiet until its severity rises. Details in the [Evidence guide](06-evidence-guide.en.md) §observe.
@@ -1,5 +1,7 @@
1
1
  # 快速开始:第一个 Run
2
2
 
3
+ **简体中文** | [English](01-quickstart.en.md)
4
+
3
5
  目标:在一个真实 Git 仓库里,让 v2 Runner 驱动 Build→Verify→Review 自动跑完,**停在合并决定**,由你带着证据拍板。下面的顺序是固定的:安装 → 准备工作项 → 写 run 配置 → 接受计划 → doctor → start → 看证据、拍板。每一步都写了"成功是什么样"。耗时取决于你的 worker 与任务,本文不给承诺数字。
4
6
 
5
7
  > 在 AI 会话里用 BuildBeat 的人不需要手敲这些命令:`SKILL.md` §0.5 是给会话读的驾驶手册,你说「开工 / 当前进度 / 批准」即可。本文给的是会话背后跑的东西,方便你核对。
@@ -8,12 +10,12 @@
8
10
 
9
11
  ```bash
10
12
  npm install --global @haiyangbg/buildbeat@latest
11
- buildbeat | head -3 # 打印 "BuildBeat v2 runtime" 与用法即安装成功
13
+ buildbeat | head -3 # 打印 "BuildBeat runtime" 与用法即安装成功
12
14
  ```
13
15
 
14
16
  稳定版走 `@latest`,可执行文件只有一个:`buildbeat`(本文用的运行时)。预发布才用 `@next`。要求 Node ≥ 20、Git、bash,零运行时依赖。
15
17
 
16
- > 下文用到的 `templates/v2/envelope/` 与 run 配置 `env:` 透传修复自 2.0.1 起随包分发。装好后确认 `$(npm root -g)/@haiyangbg/buildbeat/templates/v2/envelope/` 存在再继续;不存在说明装到的是 2.0.0,先 `npm install --global @haiyangbg/buildbeat@latest` 更新。
18
+ > 继续之前确认 `$(npm root -g)/@haiyangbg/buildbeat/templates/v2/envelope/` 存在;不存在就重新 `npm install --global @haiyangbg/buildbeat@latest`。
17
19
 
18
20
  ## 1. 准备工作项(Git 面)
19
21
 
@@ -0,0 +1,51 @@
1
+ # Evidence guide
2
+
3
+ [简体中文](06-evidence-guide.md) | **English**
4
+
5
+ Authority: [`RFC-0002 §4`](../RFC-0002-domain-model.md) (Chinese); implementation: `src/v2/evidence/collector.js`, `src/v2/observe/`. Core idea: **evidence is a fact the Runner read back, not a worker's account of itself**.
6
+
7
+ ## The shape of an evidence record
8
+
9
+ Every piece of evidence enters the event ledger (`EVIDENCE_RECORDED`) with: `kind` (command / screenshot / drift / runtime-health / diagnosis / …), `subject` (candidate SHA or deployment unit), `digest` (sha256 of the raw log; the runtime may be deleted, the digest lives on), `status`, `grade`, producer, start and end times. Raw logs land in the runtime plane, `.buildbeat/runtime/`; the ledger and the compacted record reference only digests.
10
+
11
+ ## Status: three values, fail-closed
12
+
13
+ | status | Meaning |
14
+ |---|---|
15
+ | `passed` | Zero exit code, no timeout, not killed by a signal |
16
+ | `failed` | Non-zero exit / timeout / signal |
17
+ | `unverified` | **Could not collect**: failed to start, data missing. Never means "no problem" |
18
+
19
+ `unverified` is never treated as a pass by any gate (three-valued logic, [Policy guide](03-policy-guide.md), Chinese). Fail-closed is kernel semantics, not a convention.
20
+
21
+ ## Grades L0–L4
22
+
23
+ `L0` self-report → `L1` static check → `L2` real local execution (the default grade for command readback) → `L3` post-deployment verification → `L4` production readback. Gates state their requirement with `minGrade` (for example a merge floor of L2; closing a production switch needs L4).
24
+
25
+ **Verification pyramid warning (the most expensive lesson of the thirty-round campaign)**: the marginal value of polishing a lower layer toward theoretical completeness is far below moving one layer closer to the real machine one step earlier. In practice a 7,400-line L3 suite was polished to its limit, while the four real release blockers (systemd parsing behaviour, deployment/service identity split, probe budgets calibrated against a stand-in, TLS ref format) **were all structurally invisible to L3** and were found in one evening at L4. Rule of thumb: **move up a layer as soon as the simulated layer has zero real defect classes left; do not chase theoretical completeness**. Similarly, re-running the full verify when the candidate touched only a part is pure repetition; caching or trimming by content hash belongs to the envelope layer (the campaign measured 25 → 13 minutes) and the kernel does not do it for you: cache correctness depends on assumptions about a stable environment, which the envelope owner carries.
26
+
27
+ ## Preflight is not evidence
28
+
29
+ `buildbeat preflight --config <run-config> --step <id>` dry-runs one step's worker command directly in the main checkout: no worktree, no ledger, no evidence of any kind (the output carries a `PREFLIGHT (dry signal, never evidence)` banner and the environment variable `BUILDBEAT_PREFLIGHT=1`). Its purpose is a minute-scale loop that reaches the first failure boundary before entering a Run (in the campaign every harness defect cost a whole Run round; preflight mode dismantled them in one evening). **Anything preflight finds counts only once a Run reproduces it.**
30
+
31
+ ## Candidate scope
32
+
33
+ Evidence is bound to the candidate through `subject`: the merge gate counts only the current candidate's evidence; records from old candidates or old review rounds are not mixed in (a real-incident regression, see the `fix-loop` eval).
34
+
35
+ ## observe: production joins the evidence plane (v0)
36
+
37
+ Frozen in [`RFC-0003 §8`](../RFC-0003-workflow-policy.md) (Chinese), implemented in M5 (`src/v2/observe/`):
38
+
39
+ - **Providers** (project probes such as drift checks and live status) produce records under the same Evidence Contract into a separate observe ledger (same chain verification, `.buildbeat/runtime/observe/`); a broken probe is `unverified` (default severity warn), never silent;
40
+ - **Three bands** (thresholds configurable, order fixed): `log` records only → `diagnose` triggers a read-only diagnostic command and produces `diagnosis` evidence → `intent` writes an Intent **draft** into the Git plane at `delivery/observe/intents/` (never executed automatically);
41
+ - **Human triage**: `observe triage --action fix_now|schedule|dismiss`. After `fix_now` a human carries it into a software-delivery Run and the loop closes; `dismiss` feeds the bands back so the same fingerprint is not queued again until its severity rises (alert-fatigue protection); the triage outcome is written into the draft file itself and survives deleting the runtime (invariant 23);
42
+ - **Scheduling boundary in v0**: the `schedule` field is parsed and recorded but there is no built-in scheduler; periodic runs are the host's cron calling `observe run` repeatedly.
43
+
44
+ ## Completeness
45
+
46
+ `buildbeat metrics` prints evidence completeness (steps with evidence / steps that should have it); the M4/M5 exit line is ≥ 95%, the pilots measured 100%.
47
+
48
+ ## Live readings are not evidence
49
+
50
+ > Since 2.0.0-beta.4 (iteration 08).
51
+ While a step runs, the Shell Adapter streams the worker's stdout/stderr to `.buildbeat/runtime/runs/<RUN>/<step>-<n>.{stdout,stderr}.live` and keeps a `live.json` (command, start time). These are **readings**: `status` uses them to answer "is it still moving, for how long, when was the last output", and they are reclaimed as soon as the step ends; the evidence log is still produced by readback, and the digest still binds the final log. Durations likewise: per-step elapsed time and the repository's historical median (`typical step duration` in `metrics`) are derived from ledger timestamps and enter neither the ledger nor the run-record.
@@ -1,5 +1,7 @@
1
1
  # Evidence 指南
2
2
 
3
+ **简体中文** | [English](06-evidence-guide.en.md)
4
+
3
5
  权威:[`RFC-0002 §4`](../RFC-0002-domain-model.md);实现:`src/v2/evidence/collector.js`、`src/v2/observe/`。核心:**证据是 Runner 回读到的事实,不是 Worker 的自述**。
4
6
 
5
7
  ## 证据记录的形状
@@ -0,0 +1,115 @@
1
+ # Human approval guide
2
+
3
+ [简体中文](07-approval-guide.md) | **English**
4
+
5
+ Authority: [`RFC-0003 §5`](../RFC-0003-workflow-policy.md) (Chinese); implementation: `src/v2/runtime/decisions.js`. Principle: **a human approves a digest-bound subject, not a sentence that says "fine"**.
6
+
7
+ ## What an approval binds
8
+
9
+ One approval = the quadruple `transition + candidate + planDigest + evidenceDigest`. If any of the four changes afterwards, the approval becomes `APPROVAL_STALE` on its own and the Run returns to `WAITING_HUMAN`: an old stamp never covers a new subject (zero reuse of stale approvals is an exit metric; the pilots measured zero).
10
+
11
+ ## Daily commands
12
+
13
+ ```bash
14
+ buildbeat inbox --repo . # every Run waiting for a human: transition, candidate, digest, reason
15
+ buildbeat status --repo . --run RUN-X # the full derived view of one Run (steps, evidence, findings)
16
+ buildbeat approve --repo . --run RUN-X --transition enter-wait-merge --by <name> --config <run-config>
17
+ buildbeat reject --repo . --run RUN-X --reason "<why>" --by <name>
18
+ buildbeat accept --repo . --work WORK-X --artifact plan --by <name> # artifact acceptance (digest-bound)
19
+ ```
20
+
21
+ Decisions land in the Git plane at `delivery/work/<id>/decisions.jsonl`; the event ledger records `DECISION_RECORDED` at the same time.
22
+
23
+ ## The safety semantics of approve (all tested)
24
+
25
+ 1. **The transition must match** the pending request;
26
+ 2. **Reality is re-read before stamping**: if the pending snapshot and reality disagree (the candidate moved, the plan changed), the approval is refused and a refresh is required; nothing is stamped;
27
+ 3. **Transition gates are re-checked at the instant of stamping**: if merge-evidence-floor / ui-render-gate do not PASS right then, the approval is refused;
28
+ 4. Approving a final decision (a pending request of the final-decision kind) means `RUN_TERMINAL SUCCEEDED` plus compacting the run-record into the Git plane.
29
+
30
+ ## Five words and what each means (approving is not executing)
31
+
32
+ Sessions and documents used to mix "accept / approve / resume / succeeded / merged". The vocabulary is fixed as follows:
33
+
34
+ | Word | Command | Meaning | Is not |
35
+ |---|---|---|---|
36
+ | **Accept** | `accept --artifact intent\|plan` | A human endorses one artifact's digest; editing it makes the acceptance `stale` | Starting work; it creates no Run |
37
+ | **Approve a transition** | `approve --transition <t>` | Lets the Run take **this one** transition: `enter-fix` (release the fixer after triage), `resume-<step>` (run the step once more after a budget or infra stop; records `BUDGET_EXTENDED`), `enter-review` (one more review round after the Work-level cap), `enter-apply-readback` ("I have done it" on the release lane) | Approving any other transition; after a non-terminal transition is approved the Run **does not move by itself**: `resume --config <run-config>` continues it (the `next:` line printed by `approve` says so) |
38
+ | **Merge decision** (final approval) | `approve --transition enter-wait-merge` | The candidate is fit to merge: candidate + planDigest + evidenceDigest all hold at this instant; the Run reaches the terminal state `SUCCEEDED` and the run-record is compacted into the Git plane | Code merged, pushed or deployed: those three remain your actions outside the Runner, always |
39
+ | **Run SUCCEEDED** | — | The Run stopped where it should and the evidence is complete | The Work is finished. `overview` shows `MERGED` only after reading back that the candidate is on the current branch |
40
+ | **Reject** | `reject --reason` | The Run ends (`FAILED`, reason recorded) | The artifacts are invalidated; the acceptance state of intent/plan does not change |
41
+
42
+ Likewise, `fix_now` on an observe draft is only acceptance; a human starts the Run. Protected actions are listed under [Security boundaries](09-security-boundaries.md) (Chinese).
43
+
44
+ ## Risk presets decide where humans approve
45
+
46
+ `fast`: Merge only; `standard`: Plan + Merge; `controlled`: Intent + Plan + Merge + Release. A pending request must carry the findings summary and the reason, which prevents the "rubber stamp" decay; human waiting time goes into `metrics`.
47
+
48
+ ## The finding triage gate and anchored review
49
+
50
+ > Since 2.0.0-beta.3.
51
+ The biggest structural lesson of the thirty-round deployment campaign: **a finding is a prescription, not a fact**. A memoryless fresh reviewer writes contradictory prescriptions and overturns designs that were accepted long ago; routing a fixer automatically turns that oscillation straight into cost. Two mechanisms work together:
52
+
53
+ 1. **The triage gate**: with `reviewTriage: required` in the run config, P0/P1 findings from review no longer dispatch a fixer automatically; the Run stops at `WAITING_HUMAN` (kind `finding-triage`) and the pending reason lists every finding fingerprint. A human adjudicates first, then `approve --transition enter-fix` releases the fixer (or `reject` ends the Run).
54
+ 2. **The adjudication ledger**: every finding lands in the Git plane at `delivery/work/<id>/review-findings.jsonl` (fingerprint = hash of severity plus normalized text):
55
+
56
+ ```bash
57
+ buildbeat findings list --repo . --work WORK-X
58
+ buildbeat findings adjudicate --repo . --work WORK-X --fingerprint <fp> --action dismiss --by <name> --note "<why>"
59
+ ```
60
+
61
+ After `dismiss`, the same fingerprint no longer blocks (raising it again is recorded visibly as `RE-RAISED`, but does not restart the loop); **a severity upgrade is a new fingerprint and blocks again on its own**: noise is suppressed, real signal is not, the same principle as observe's dismiss feedback.
62
+ 3. **Anchor injection**: the reviewer (a readonly step) receives `anchor` in `BUILDBEAT_INPUT`, the full table of past findings and adjudications, and the envelope prompt should tell the reviewer that adjudicated conclusions must not be overturned; writing steps such as the fixer receive `findings` (last round's findings with their adjudication state), and the fixer repairs only accepted/open ones instead of guessing.
63
+
64
+ Adjudication memory lives in the Git plane; deleting the runtime does not lose it (covered by the same tests as invariant 23).
65
+
66
+ ## Waiting must be able to find a person
67
+
68
+ > Since 2.0.0-beta.4 (iteration 08).
69
+ In the pilot workspace, 32 of 58 Runs were cancelled, most of them after hanging in `WAITING_HUMAN` for a full day; the average human wait was 7 to 12 hours. The cause was not slow people but **nobody knowing something was waiting for them**. Three things go together:
70
+
71
+ 1. **What to say next**: `status` and `inbox` print the copyable command right after each wait (`approve` / `reject`, plus `findings list|adjudicate` during triage); `inbox` groups by Work and shows how long each has waited. The `--repo` in that output is a relative path inside the project and the placeholder `<repo-path>` outside it: a machine-local absolute path never enters the output.
72
+ 2. **A new Run of the same Work supersedes the old wait**: on `start`, older Runs of the same Work that are still waiting are recorded as `SUPERSEDED` (terminal, compacted into a run-record), and the new Run's `RUN_CREATED.data.supersedes` records the lineage; the inbox keeps only live waits. Write `supersede: off` in the run config if you do not want this. RUNNING Runs are unaffected (active lock); old Runs locked by another process are skipped and reported.
73
+ 3. **Outbound notifications**: `.buildbeat/notify.yaml` in the Git plane:
74
+
75
+ ```yaml
76
+ kind: notify
77
+ version: 1
78
+ channels:
79
+ - id: owner
80
+ type: dingtalk # or webhook
81
+ urlEnv: BUILDBEAT_NOTIFY_URL # the URL comes only from an environment variable; a literal url is refused
82
+ events:
83
+ - HUMAN_REQUESTED
84
+ - RUN_TERMINAL
85
+ - STALLED
86
+ ```
87
+
88
+ The CLI sends when a Run stops for a human or reaches a terminal state; subscribing to `STALLED` makes `start`/`resume` spawn a detached `watch` process that watches for silent worker output (threshold `stallAfterMs`, default 15 minutes). A failed send is only logged to `runs/<RUN>/notify.log` and the screen and **never affects the Run**; the payload carries identifiers, the reason, the candidate SHA and the next command, with zero logs and zero candidate content. A DingTalk custom robot needs its keyword configured (default `BuildBeat`). `doctor` reports whether the channel and its environment variable are in place.
89
+
90
+ Notification is not an approval channel: decisions are still made only through the CLI, with digest binding unchanged.
91
+
92
+ ## From "waiting for me" to "where are we": overview
93
+
94
+ > Since 2.0.0-beta.4 (iteration 08).
95
+ `inbox` only knows which Run waits for a human; `buildbeat overview --repo .` answers per Work "how far, whose move next": whether intent/plan are accepted (edited after acceptance means `stale`), the latest Run's state and candidate, whether the candidate is merged into the current branch, the number of unadjudicated P0/P1 findings, whether `env-facts.md` exists, each row with its next command. After the runtime is deleted, the Git-plane run-records fill in. A session runs it first, then answers "where are we".
96
+
97
+ **Stage truth corrections (iteration 09)**: once a candidate is merged into the current branch the Work is `MERGED`, even if the latest Run is CANCELLED (a pilot login Run was cancelled over a budget problem while its candidate was already in production, and overview reported `STOPPED_CANCELLED` and urged a retry); a Work whose `release-readback` lane closed successfully shows `RELEASED` instead of "nothing to merge"; merged / released / closed Works no longer report unadjudicated finding counts. Each Work in `overview` also carries a `cost:` line (see the Work-level budgets in the [Workflow guide](02-workflow-guide.md), Chinese).
98
+
99
+ ## You fixed it yourself: `resume --adopt`
100
+
101
+ > Since 2.0.0-beta.5 (iteration 09).
102
+ When a Run stops at `enter-fix` / `resume-fix`, the driving session or a person has often already fixed the problem in the Run's worktree and committed it. Approving at that point dispatches a fixer with nothing to do and runs verify once more (a pilot frontend Run reached its 5th verify and 3rd fix this way). Use instead:
103
+
104
+ ```bash
105
+ buildbeat resume --config <run-config.yaml> --adopt <sha> --by <name>
106
+ ```
107
+
108
+ The kernel reads the worktree back: the tree must be clean and HEAD must be exactly `<sha>` (7-character prefix or longer), otherwise it refuses; then it records `CANDIDATE_PINNED` with a human actor (`adopted: true`), records `DECISION_RECORDED` with that commit as subject (`adopted`, `resumeAt`), and continues from verify (the step after a successful fix in the preset). The ledger shows who supplied this candidate. Adoption is not accepted at the merge decision.
109
+
110
+ `doctor` now also prints whether intent / plan exist and are accepted in this repository's `delivery/work/<ID>/`, and for every policy requiring `artifact.accepted` it previews where `start` will stop; before that, doctor passed twice while start was blocked by "plan not mirrored into the sub-repository".
111
+
112
+ ## Visible names are gate decisions
113
+
114
+ > Since 2.0.0-beta.4 (iteration 08).
115
+ The `BATCH_AT_GATE` tier of the three approval tiers explicitly includes domain names, service names, environment names, auto-stop durations, window durations: **names and parameters the owner will later see or say out loud**. Names a worker picks in passing never reach the ledger; the planner lists them in the intent with recommended values, and the human approves them in one go.
@@ -1,5 +1,7 @@
1
1
  # Human Approval 指南
2
2
 
3
+ **简体中文** | [English](07-approval-guide.en.md)
4
+
3
5
  权威:[`RFC-0003 §5`](../RFC-0003-workflow-policy.md);实现:`src/v2/runtime/decisions.js`。原则:**人批的是一个 digest 绑定的对象,不是一句"可以了"**。
4
6
 
5
7
  ## 批准绑定什么
@@ -0,0 +1,83 @@
1
+ # Recovery handbook
2
+
3
+ [简体中文](10-recovery.md) | **English**
4
+
5
+ Design premise (invariant 23 in [`V2-PLAN.md`](../../V2-PLAN.md), Chinese): **the whole `.buildbeat/runtime/` directory can be deleted at any time**. Accepted artifacts, decisions, Intent drafts with their triage, and the compacted records of finished Runs all live in the Git plane. "Delete and rebuild" is the default troubleshooting move, not the last resort.
6
+
7
+ ## Symptom → action
8
+
9
+ ### The ledger reports corrupted
10
+
11
+ `status`/`inbox` shows `LEDGER CORRUPTED after seq=N (<reason>)`: the ledger truncates its view at the last valid event and **refuses to append**; recovery is a human decision, nothing is repaired silently.
12
+
13
+ 1. `buildbeat events --repo . --run RUN-X` shows the valid prefix; `replay` verifies the reduction;
14
+ 2. If the broken Run is in flight: usually abandon it (the candidate in the worktree is still readable on its branch) and start a new Run;
15
+ 3. If someone edited the ledger file by hand: rebuild the judgement from Git-plane facts; do not patch event lines by hand.
16
+
17
+ ### The Run process was killed / the machine rebooted
18
+
19
+ ```bash
20
+ buildbeat resume --config <run-config.yaml>
21
+ ```
22
+
23
+ The in-flight step is closed as `crashed` (the fact is recorded), then **the step itself is rerun** (changed in beta.3): a dead process says nothing about the candidate; the lost attempt still counts against the step's budget, and an exhausted budget stops for a human. The earlier semantics treated a crash as a step failure and followed the failure edge; real incident (deploy-18): the host tool's timeout killed the verify worker, the crash was routed to fix, and the fixer burned a round facing zero verifier evidence. A dirty worktree still stops for a human first. Resuming with approvals re-checks candidate/plan freshness and turns `APPROVAL_STALE` over to a human if anything changed. If it cannot be recovered, delete the runtime and rerun: the candidate branch and the Git-plane records are not lost.
24
+
25
+ **Launch discipline** (the other half of the same incident): a Run longer than minutes must be launched in a way that escapes the host tool's timeout (`nohup`/`setsid`); `start` prints this reminder in an interactive shell.
26
+
27
+ ### A stuck lock ("another run is active")
28
+
29
+ A Run that exited abnormally may leave the repository lock behind. Once you have confirmed that no Run is really active:
30
+
31
+ ```bash
32
+ buildbeat stop --repo . --run RUN-X --reason "crashed; releasing lock"
33
+ ```
34
+
35
+ `stop` records the terminal state and the reason; for a mere leftover lock you may also delete `.buildbeat/runtime/` and start over.
36
+
37
+ ### Abnormal worker behaviour
38
+
39
+ - **Worker infrastructure failure (iteration 09)**: a timeout, a crash, output that is not an envelope (`invalid-output`), or the worker ending itself with exit code **75** (`EX_TEMPFAIL`, "environment unavailable"): the kernel classifies it as `infra`: no failure fingerprint is recorded, no fixer is dispatched, **the step's budget is not consumed**, the Run stops at `WAITING_HUMAN` (kind `infra`, transition `resume-<step>`), notifications go out as usual. Once the backend is back, `approve --transition resume-<step>` reruns the step; `reject` ends the Run. Real incidents: a worker backend returning 404 and non-JSON output killed five Runs in two days while the driving session hand-wrote a probe every two minutes; a missing rg on PATH, a port collision and a host load of 280 each dispatched a fixer.
40
+ - **A failure with no transition edge** (such as `failed` on build / review / fix in the preset) no longer ends in FAILED; it stops at `resume-<step>` as well, and a human decides whether to rerun or end.
41
+ - Out-of-scope writes → the Run BLOCKs and no candidate is pinned: check `allowedPaths` and the scope declared in the worker prompt;
42
+ - Timeouts → first check whether it is the environment (`infra` already stopped for you), then adjust `timeoutMs`; an exhausted budget is a brake, not a fault: approve `resume-<step>` to grant one more attempt, or narrow the scope.
43
+
44
+ ### The observe plane
45
+
46
+ - A probe stays `unverified`: fix the probe's reachability first; unverified means "could not collect", not "no problem";
47
+ - False alarms flooding: `observe triage --action dismiss`; the same fingerprint stays out of the queue until its severity rises;
48
+ - Observe cycle counts reset to zero after the runtime was deleted: normal; triage memory lives in the Git-plane drafts, and suppression keeps working (tested).
49
+
50
+ ### Everything is a mess
51
+
52
+ ```bash
53
+ rm -rf .buildbeat/runtime/
54
+ ```
55
+
56
+ Then start again from the Git plane. Any phenomenon where a long-term metric or a terminal-state explanation depends on the runtime is a bug; please report it.
57
+
58
+ ## Diagnostic entry point
59
+
60
+ `buildbeat doctor --config <run-config>`: the config parses, the workflow has no exit loop, adapter env posture, digests can be computed, supersede and stall thresholds, whether the notification channel and its environment variable are in place. `events`/`replay`/`metrics` are all read-only and can run at any time.
61
+
62
+ ## "Is it stuck?"
63
+
64
+ > Since 2.0.0-beta.4 (iteration 08).
65
+ Look at `buildbeat status --repo . --run <RUN>` first: the step in flight shows elapsed time, the repository's historical median, the worker command, how long ago the last output was and its last three lines. No output beyond the threshold (default 15 minutes, `--stall-after <minutes>` or `stallAfterMs` in the run config) marks `STALLED`: **marked, never killed**. How to judge:
66
+
67
+ - Output keeps coming → wait (compare against `typical` to see whether it is far beyond the median);
68
+ - STALLED and the worker is an agent CLI → most likely a long reasoning stretch or waiting for an interaction that never comes; `stop --reason`, then rerun by the crash recovery path (the interrupted step reruns itself);
69
+ - STALLED and the worker is a script → read the last three lines; usually it waits on an external resource (port, lock, network).
70
+
71
+ To avoid watching the screen, subscribe to `STALLED` notifications ([Approval guide](07-approval-guide.en.md)). `watch --repo . --run <RUN> --once true` probes once by hand.
72
+
73
+ ## Cleanup: gc
74
+
75
+ > Since 2.0.0-beta.4 (iteration 08).
76
+ Terminal Runs leave worktrees, `run/*` branches and the occasional lock. `buildbeat gc --repo .` prints the plan by default, `--apply true` executes it:
77
+
78
+ - It touches only Runs that are **terminal and already compacted into a run-record** (the Git plane must have the record before the runtime plane is touched);
79
+ - Worktrees may be deleted (the commits are on the branch); a dirty worktree is left alone without `--force true`;
80
+ - A branch is deleted only when the candidate **is reachable from another ref** (merged / tagged / on the remote) or the Run produced no candidate; otherwise it reports "reachable only from this branch, kept": that branch is the last thread to the evidence;
81
+ - Leftover `locks/<RUN>.lock` of terminal Runs are cleaned; the `active-run` lock is still handled by hand as above.
82
+
83
+ gc never writes to the ledger (after the terminal state only `RUN_COMPACTED` is allowed), so it can run at any time and repeatedly.
@@ -1,5 +1,7 @@
1
1
  # 故障恢复手册
2
2
 
3
+ **简体中文** | [English](10-recovery.en.md)
4
+
3
5
  设计前提([`V2-PLAN.md`](../../V2-PLAN.md) 不变量 23):**`.buildbeat/runtime/` 整个目录随时可删**——已接受工件、Decision、Intent 草稿与分诊、已终结 Run 的压实记录全部活在 Git 面。"删了重建"是默认排障手段,不是最后手段。
4
6
 
5
7
  ## 症状 → 处置