@haiyangbg/buildbeat 2.0.0-beta.5 → 2.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.
- package/CHANGELOG.md +30 -1
- package/README.en.md +100 -224
- package/README.md +100 -222
- package/SKILL.md +95 -27
- package/docs/CAPABILITY-MATRIX.md +37 -6
- package/docs/CLI.md +14 -3
- package/docs/README.md +37 -0
- package/docs/RELEASING.md +27 -3
- package/docs/V2-PLAN.md +2 -0
- package/docs/V2.0.0-BETA.5-RELEASE-EVIDENCE-2026-09-05.md +10 -0
- package/docs/V2.0.0-RELEASE-EVIDENCE-2026-09-05.md +11 -0
- package/docs/v2/RFC-0001-product-definition.md +2 -0
- package/docs/v2/guide/00-how-to-talk.md +3 -1
- package/docs/v2/guide/01-quickstart.md +92 -29
- package/docs/v2/guide/02-workflow-guide.md +4 -2
- package/docs/v2/guide/04-adapter-guide.md +17 -2
- package/docs/v2/guide/05-worker-contract.md +17 -6
- package/docs/v2/guide/06-evidence-guide.md +2 -1
- package/docs/v2/guide/07-approval-guide.md +22 -7
- package/docs/v2/guide/08-migration-v1.md +8 -4
- package/docs/v2/guide/09-security-boundaries.md +22 -11
- package/docs/v2/guide/10-recovery.md +4 -2
- package/docs/v2/guide/11-session-handoff.en.md +84 -0
- package/docs/v2/guide/11-session-handoff.md +84 -0
- package/docs/v2/guide/README.md +40 -21
- package/example/.buildbeat/manifest.json +1 -1
- package/package.json +10 -8
- package/src/v2/cli/run.js +26 -0
- package/templates/v2/AGENTS.md +6 -6
- package/templates/v2/BUILDBEAT.md +15 -0
- package/templates/v2/CLAUDE.md +7 -0
- package/templates/v2/envelope/prompts/builder.md +8 -0
- package/templates/v2/envelope/prompts/fixer.md +8 -0
- package/templates/v2/envelope/prompts/reviewer.md +13 -0
- package/templates/v2/envelope/worker.sh +70 -0
- package/templates/v2/run-config.example.yaml +74 -0
- package/templates/v2//346/214/207/346/214/245/345/217/260.md +7 -3
|
@@ -1,95 +1,158 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 快速开始:第一个 Run
|
|
2
2
|
|
|
3
|
-
目标:在一个真实 Git 仓库里,让 v2 Runner 驱动 Build→Verify→Review
|
|
3
|
+
目标:在一个真实 Git 仓库里,让 v2 Runner 驱动 Build→Verify→Review 自动跑完,**停在合并决定**,由你带着证据拍板。下面的顺序是固定的:安装 → 准备工作项 → 写 run 配置 → 接受计划 → doctor → start → 看证据、拍板。每一步都写了"成功是什么样"。耗时取决于你的 worker 与任务,本文不给承诺数字。
|
|
4
|
+
|
|
5
|
+
> 在 AI 会话里用 BuildBeat 的人不需要手敲这些命令:`SKILL.md` §0.5 是给会话读的驾驶手册,你说「开工 / 当前进度 / 批准」即可。本文给的是会话背后跑的东西,方便你核对。
|
|
4
6
|
|
|
5
7
|
## 0. 安装
|
|
6
8
|
|
|
7
9
|
```bash
|
|
8
|
-
npm install
|
|
10
|
+
npm install --global @haiyangbg/buildbeat@latest
|
|
11
|
+
buildbeat-v2 | head -3 # 打印 "BuildBeat v2 runtime" 与用法即安装成功
|
|
9
12
|
```
|
|
10
13
|
|
|
11
|
-
|
|
14
|
+
2.0.0 起 `@latest` 就是 v2;同一个包同时给出 `buildbeat`(v1 生命周期命令:doctor / init / adopt / upgrade)和 `buildbeat-v2`(本文用的运行时)。预发布才用 `@next`。要求 Node ≥ 20、Git、bash,零运行时依赖。
|
|
15
|
+
|
|
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` 更新。
|
|
12
17
|
|
|
13
18
|
## 1. 准备工作项(Git 面)
|
|
14
19
|
|
|
15
|
-
在目标仓库建工作项目录并写下意图与计划(它们的 digest
|
|
20
|
+
在目标仓库建工作项目录并写下意图与计划(它们的 digest 会绑进批准对象),把官方 workflow 预设复制到工作项旁边(复制而不是引用安装目录:workflow 文件的 digest 会记进 Run,随项目一起进 Git),再把信封模板(worker 包装脚本 + 三份 prompt)拷到仓级 `delivery/envelope/`:
|
|
16
21
|
|
|
17
22
|
```bash
|
|
23
|
+
BB="$(npm root -g)/@haiyangbg/buildbeat"
|
|
18
24
|
mkdir -p delivery/work/WORK-DEMO-1
|
|
19
|
-
printf "# 意图\n
|
|
20
|
-
printf "# 计划\n1.
|
|
25
|
+
printf "# 意图\n给 CSV 导出加日期筛选。\n止损线:最多 3 个 Run、4 轮 review。\n" > delivery/work/WORK-DEMO-1/intent.md
|
|
26
|
+
printf "# 计划\n1. 在 src/export.js 加 from/to 参数;2. tests/ 补边界用例。\n" > delivery/work/WORK-DEMO-1/plan.md
|
|
27
|
+
cp "$BB/src/v2/presets/software-delivery.yaml" delivery/work/WORK-DEMO-1/workflow.yaml
|
|
28
|
+
cp -R "$BB/templates/v2/envelope" delivery/envelope
|
|
29
|
+
git add delivery && git commit -qm "buildbeat: work WORK-DEMO-1 + envelope"
|
|
21
30
|
```
|
|
22
31
|
|
|
32
|
+
信封要进 Git:worker 在隔离 worktree 里运行,只看得到已提交的文件。`delivery/envelope/worker.sh <角色> -- <工具命令…>` 负责"工具不在 PATH 就 exit 75、把 prompt 追加为最后一个参数、写入步机械 commit、只读步把 stdout 落成信封",三份 prompt 按项目补环境事实即可([Worker 合同](05-worker-contract.md))。
|
|
33
|
+
|
|
23
34
|
## 2. 写 run 配置
|
|
24
35
|
|
|
25
|
-
`delivery/work/WORK-DEMO-1/run-config.yaml
|
|
36
|
+
`delivery/work/WORK-DEMO-1/run-config.yaml`。路径相对**本文件**解析;YAML 是严格子集:只有块列表与块映射,没有行内 `[]` / `{}`、没有锚点、注释必须独占一行。下面这份可以原样解析(机器验证在 `tests/v2-templates-firstrun.test.js`);完整样板与信封模板在 [`templates/v2/`](../../../templates/v2/run-config.example.yaml)。
|
|
26
37
|
|
|
27
38
|
```yaml
|
|
28
39
|
repo: ../../..
|
|
29
40
|
work: WORK-DEMO-1
|
|
30
|
-
run: RUN-DEMO
|
|
31
|
-
workflow:
|
|
41
|
+
run: RUN-DEMO
|
|
42
|
+
workflow: workflow.yaml
|
|
32
43
|
riskPreset: standard
|
|
33
44
|
entry: build
|
|
34
45
|
allowedPaths:
|
|
35
46
|
- src
|
|
36
47
|
- tests
|
|
48
|
+
reviewTriage: required
|
|
49
|
+
envelope:
|
|
50
|
+
prompts: ../../envelope/prompts
|
|
37
51
|
workers:
|
|
38
52
|
builder:
|
|
39
|
-
command:
|
|
53
|
+
command: bash
|
|
40
54
|
args:
|
|
55
|
+
- delivery/envelope/worker.sh
|
|
56
|
+
- builder
|
|
57
|
+
- --
|
|
58
|
+
- codex
|
|
41
59
|
- exec
|
|
42
60
|
- -s
|
|
43
61
|
- workspace-write
|
|
44
|
-
- 按 delivery/work/WORK-DEMO-1/plan.md 实施,改动后 git commit
|
|
45
62
|
verifier:
|
|
46
63
|
command: bash
|
|
47
64
|
args:
|
|
48
65
|
- -lc
|
|
49
66
|
- npm test
|
|
50
67
|
reviewer:
|
|
51
|
-
command:
|
|
68
|
+
command: bash
|
|
52
69
|
args:
|
|
70
|
+
- delivery/envelope/worker.sh
|
|
71
|
+
- reviewer
|
|
72
|
+
- --
|
|
73
|
+
- codex
|
|
53
74
|
- exec
|
|
54
75
|
- -s
|
|
55
76
|
- read-only
|
|
56
|
-
|
|
77
|
+
fixer:
|
|
78
|
+
command: bash
|
|
79
|
+
args:
|
|
80
|
+
- delivery/envelope/worker.sh
|
|
81
|
+
- fixer
|
|
82
|
+
- --
|
|
83
|
+
- codex
|
|
84
|
+
- exec
|
|
85
|
+
- -s
|
|
86
|
+
- workspace-write
|
|
57
87
|
```
|
|
58
88
|
|
|
59
|
-
|
|
89
|
+
- `workers.<角色>` 是任意 CLI:换工具只改 `--` 后面的命令(`claude -p`、任意脚本都行),见 [Adapter 指南](04-adapter-guide.md);reviewer 的输出格式见 [Worker 合同](05-worker-contract.md),prompt 模板已写明。
|
|
90
|
+
- **`fixer` 不是可选项**:没配它,verify 失败或 review 阻断时 Run 会停 `WAITING_HUMAN`(理由 `no adapter configured for worker fixer`)等你手修,不会自动修。
|
|
91
|
+
- worker 子进程默认只拿到 `PATH HOME LANG LC_ALL TMPDIR TERM USER SHELL`;需要别的变量用 `env:` 点名注入([Adapter 指南](04-adapter-guide.md))。
|
|
92
|
+
- `reviewTriage: required` 让 P0/P1 finding 先过你的手再派 fixer;不想要就删掉这行。
|
|
93
|
+
|
|
94
|
+
## 3. 接受计划
|
|
60
95
|
|
|
61
|
-
|
|
96
|
+
`standard` 预设在 build 前要求 plan 是已接受工件(`controlled` 还要求 intent)。接受是 digest 绑定的:接受后改了 plan,接受自动过期,`doctor` 会报 `stale`。
|
|
62
97
|
|
|
63
98
|
```bash
|
|
64
|
-
buildbeat-v2
|
|
99
|
+
buildbeat-v2 accept --repo . --work WORK-DEMO-1 --artifact plan --by <你的名字>
|
|
65
100
|
```
|
|
66
101
|
|
|
67
|
-
|
|
102
|
+
成功:打印 `accepted plan as A-WORK-DEMO-1-<n>` 与 `digest: sha256:…`。
|
|
103
|
+
|
|
104
|
+
## 4. doctor:起跑前把 start 会读的事实读一遍
|
|
68
105
|
|
|
69
106
|
```bash
|
|
70
|
-
buildbeat-v2
|
|
107
|
+
buildbeat-v2 doctor --config delivery/work/WORK-DEMO-1/run-config.yaml
|
|
71
108
|
```
|
|
72
109
|
|
|
73
|
-
|
|
110
|
+
逐段核对:`policies` 每条的 declared 与 actual 强制等级;`worker isolation` 每个 worker 是 `env allowlist` 还是 `WARNING inherit`;`push protection`;每步预算;`work artifacts` 里 intent / plan 是否存在、是否已接受、是否 stale,以及"start 会停在哪一步"的预告。有 `WARNING` 不代表不能跑,但要知道它意味着什么;退出码 0 不等于全部就绪。
|
|
111
|
+
|
|
112
|
+
## 5. 起 Run,停在人批
|
|
74
113
|
|
|
75
114
|
```bash
|
|
76
|
-
buildbeat-v2
|
|
77
|
-
buildbeat-v2 status --repo . --run RUN-DEMO-1
|
|
78
|
-
buildbeat-v2 approve --repo . --run RUN-DEMO-1 --transition enter-wait-merge --by <你的名字> --config delivery/work/WORK-DEMO-1/run-config.yaml
|
|
115
|
+
buildbeat-v2 start --config delivery/work/WORK-DEMO-1/run-config.yaml --attempt new
|
|
79
116
|
```
|
|
80
117
|
|
|
81
|
-
|
|
118
|
+
`--attempt new` 自动编号 `RUN-DEMO-01/02…`,并作废同一 Work 下仍在等人的旧 Run。Runner 会:开隔离 worktree(分支 `run/RUN-DEMO-01`,对配置 remote 的 push 已被封禁)→ builder 产出提交并固定 candidate → verifier 真实跑测试(退出码回读为证据)→ reviewer 只读出结构化 findings → 到达 `WAITING_HUMAN`。
|
|
119
|
+
|
|
120
|
+
从 AI 会话里启动时要脱离启动(`nohup` / `setsid`),否则宿主会话超时会把 Run 杀掉。
|
|
121
|
+
|
|
122
|
+
**成功是什么样**:输出末尾 `status: WAITING_HUMAN`,`waiting on human:` 后面是 `enter-wait-merge`(合并决定)或 `enter-fix`(分诊)。**停在 `infra` 是环境问题不是代码问题**:超时、崩溃、非 JSON 信封、退出码 75 都算,修好 worker / 环境后 `approve --transition resume-<step>` 续跑,预算不扣。
|
|
123
|
+
|
|
124
|
+
## 6. 看证据、拍板
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
buildbeat-v2 overview --repo . # 每个 Work 走到哪、下一步该谁、花了多少
|
|
128
|
+
buildbeat-v2 inbox --repo . # 等你批的 Run,每条附可复制的下一句命令
|
|
129
|
+
buildbeat-v2 status --repo . --run RUN-DEMO-01 # 步、耗时、证据、findings、待批理由
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
批之前先看:候选 SHA、verify 的退出码与日志、review 的每条 finding。然后按 `inbox` 给出的那一句执行,通常是:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
buildbeat-v2 approve --repo . --run RUN-DEMO-01 --transition enter-wait-merge --by <你的名字> --config delivery/work/WORK-DEMO-1/run-config.yaml
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**批的是哪一步要分清**([Approval 指南](07-approval-guide.md)):`enter-wait-merge` 是合并决定,Run 进终态 `SUCCEEDED`,表示候选具备合并条件——真正的合并、push、发布永远是你在 Runner 之外的动作;`enter-fix` / `resume-<step>` 是非终态转换,批准后要 `resume --config …` 让它续跑。被 findings 阻断时会自动路由 fix→verify→review 重走,超预算或失败指纹重复则停下交还给你([Recovery](10-recovery.md))。
|
|
139
|
+
|
|
140
|
+
## 7. 走一次失败分支
|
|
82
141
|
|
|
83
|
-
|
|
142
|
+
想看自动修复闭环,把一条会失败的用例提交进 `tests/`,再 `start --attempt new`:verify 失败 → fixer 带着失败摘要修 → verify 重跑 → review。`status` 会显示 `step fix: SUCCEEDED` 与第二次 `verify`。想让 finding 先过你的手:`reviewTriage: required` 配套 `findings list` / `findings adjudicate` 逐指纹裁决,dismiss 后同指纹不再阻断。
|
|
84
143
|
|
|
85
|
-
|
|
144
|
+
## 8. 恢复、通知、打扫
|
|
86
145
|
|
|
87
|
-
|
|
146
|
+
- 进程被杀 / 机器重启:`resume --config <run-config.yaml>`,见 [故障恢复](10-recovery.md)。
|
|
147
|
+
- 自己在 worktree 里把问题修好并提交了:`resume --config … --adopt <sha> --by <名字>` 跳过 fixer 从 verify 续跑。
|
|
148
|
+
- 不想一直盯着:`.buildbeat/notify.yaml` 配一条钉钉 / webhook 通道(URL 只能来自环境变量),Run 停下会来找你([Approval 指南](07-approval-guide.md))。
|
|
149
|
+
- 终态 Run 留下的工作树:`gc --repo .` 先出计划,`--apply true` 再清。
|
|
150
|
+
- 正式起 Run 前想干跑单步:`preflight --step <id>`(主 checkout、分钟级、不产证据);信封的环境依赖用 `requires:` 声明,启动前 fail-closed 核验([Workflow 指南](02-workflow-guide.md))。
|
|
88
151
|
|
|
89
|
-
##
|
|
152
|
+
## 9. observe:让系统盯生产(v0)
|
|
90
153
|
|
|
91
154
|
```bash
|
|
92
|
-
cp
|
|
155
|
+
cp "$(npm root -g)/@haiyangbg/buildbeat/src/v2/presets/observe.yaml" .buildbeat/observe.yaml # 改成项目真实探针
|
|
93
156
|
buildbeat-v2 observe run --config .buildbeat/observe.yaml # 一次=一个周期;周期化交给 cron
|
|
94
157
|
buildbeat-v2 observe status --repo .
|
|
95
158
|
buildbeat-v2 observe triage --repo . --intent delivery/observe/intents/INTENT-<fp>.md --action fix_now --by <你>
|
|
@@ -70,8 +70,9 @@ budgets:
|
|
|
70
70
|
|
|
71
71
|
**按 Work 累计的 review 轮数(迭代 09)**:每 Run 的预算挡不住"每轮一个新 Run"——试点一个 Work 跑了 21 个 Run、9 轮 review,2 轮封顶从未触发。`budgets.reviewRoundsPerWork: N` 让内核在 review 步起跑前统计本 Work **所有** Run(含已作废、含已压成 run-record 的)的 review 轮数,达到 N 即停 `WAITING_HUMAN`(kind `work-review-cap`,transition `enter-review`):批准即再审一轮(台账 `BUDGET_EXTENDED scope=work`),拒绝则按手头证据合并或关闭。`overview` 每个 Work 多一行 `cost: review rounds · findings · human waits · worker 时长`,run-record 也带 `cost` 块——"继续还是砍"之前先看这一行;intent 里的止损线(最多几个 Run / 几轮 review / 几小时)就对着它核。
|
|
72
72
|
|
|
73
|
-
## 工作树在仓内:把 `.buildbeat/`
|
|
73
|
+
## 工作树在仓内:把 `.buildbeat/` 排除出测试收集
|
|
74
74
|
|
|
75
|
+
> 自 2.0.0-beta.5(迭代 09)起。
|
|
75
76
|
Run 的隔离工作树在 `<repo>/.buildbeat/worktrees/<RUN>/`,运行时台账在 `<repo>/.buildbeat/runtime/`。两者都不入 git(模板 `.gitignore` 已排除;尊重 `.gitignore` 的工具如 `rg`、`gitleaks` 随之不再走进去),但**测试框架按文件系统收集用例**:试点合并后的主干 vitest 把残留工作树里旧候选的用例一起跑了,噪声直到 `gc` 才消失。在项目里加:
|
|
76
77
|
|
|
77
78
|
- vitest:`test.exclude: ['**/node_modules/**', '**/.buildbeat/**']`
|
|
@@ -81,8 +82,9 @@ Run 的隔离工作树在 `<repo>/.buildbeat/worktrees/<RUN>/`,运行时台账
|
|
|
81
82
|
|
|
82
83
|
`start` 被「another run is active」挡住时,CLI 现在打印持锁的 Run、它在哪一步、最后一次事件多久前,以及可复制的 `status` 命令;仓级单活动 Run 锁本身没放开——工作树已隔离,锁只剩台账与合并安全的意义,等真出现第二次多小时排队再动。
|
|
83
84
|
|
|
84
|
-
##
|
|
85
|
+
## 基础设施故障与候选缺陷分开算
|
|
85
86
|
|
|
87
|
+
> 自 2.0.0-beta.5(迭代 09)起。
|
|
86
88
|
worker 的超时、崩溃、非信封输出,以及 worker 主动以退出码 **75** 结束(约定:verify / 包装脚本发现环境不满足——命令不在 PATH、端口被占、后端 404、沙箱禁止监听——就 `exit 75`),内核一律判 `infra`:`STEP_FINISHED.data.infra = true`,不记失败指纹、不派 fixer、该步预算不扣(`steps[step].infraAttempts` 抵回),停 `WAITING_HUMAN`(kind `infra`)。人批准 `resume-<step>` 重跑,拒绝结束。其余非零退出仍是候选失败,走 `on: failed` 边。
|
|
87
89
|
|
|
88
90
|
没有转移边的失败结果(预设里 build、review、fix 的 `failed`)也不再终态,停 `resume-<step>` 交人决定。终态 FAILED 只剩 policy `BLOCK`。
|
|
@@ -24,7 +24,21 @@ workers:
|
|
|
24
24
|
|
|
25
25
|
## env 白名单(默认,能力移除的一部分)
|
|
26
26
|
|
|
27
|
-
Worker 子进程默认**只**拿到 `PATH HOME LANG LC_ALL TMPDIR TERM USER SHELL`——宿主 shell 里的云凭据、token
|
|
27
|
+
Worker 子进程默认**只**拿到 `PATH HOME LANG LC_ALL TMPDIR TERM USER SHELL`——宿主 shell 里的云凭据、token **环境变量**到不了 Worker(注意 `HOME` 在白名单里,凭据**文件**不在此边界之内,见 [安全边界](09-security-boundaries.md))。`inheritEnv: true` 可显式打开(doctor 会把它标为仅 ADVISORY 隔离);单个变量可用 `env:` 白名单式注入:
|
|
28
|
+
|
|
29
|
+
```yaml
|
|
30
|
+
workers:
|
|
31
|
+
verifier:
|
|
32
|
+
command: bash
|
|
33
|
+
env:
|
|
34
|
+
DATABASE_URL: postgres://localhost/app_test
|
|
35
|
+
CI: "1"
|
|
36
|
+
args:
|
|
37
|
+
- -lc
|
|
38
|
+
- npm test
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
`env:` 的值必须是标量(写进子进程前转成字符串),变量名须合法(字母、数字、下划线);不合法时 `doctor` / `start` 在加载配置时直接报错。**2.0.0 及更早的 CLI 加载路径会丢掉这两个字段**(doctor 报告了姿态,start 却按默认白名单跑,`env:` 的变量到不了 worker);2.0.1 起透传,并有 CLI 端到端回归(`tests/v2-run-cli.test.js`)。直接调用 `createShellAdapter` 的 API 用户不受此影响。
|
|
28
42
|
|
|
29
43
|
## 输入输出
|
|
30
44
|
|
|
@@ -44,6 +58,7 @@ Adapter 只报告事实:exitCode / signal / timedOut / spawnError / stdout / s
|
|
|
44
58
|
|
|
45
59
|
只有当 Shell 表达不了(需要流式交互、会话保持)才写专用 Adapter;按 M3 裁决,先用 Shell 接一切,等真实试点证明不够再说。
|
|
46
60
|
|
|
47
|
-
##
|
|
61
|
+
## 实时输出
|
|
48
62
|
|
|
63
|
+
> 自 2.0.0-beta.4(迭代 08)起。
|
|
49
64
|
编排器给 Shell Adapter 传 `liveDir` 时,子进程的 stdout/stderr 直接写到 `<liveDir>/<step>-<attempt>.{stdout,stderr}.live`(fd 直连,不经父进程缓冲),并写 `live.json`(`step / attempt / worker / command / startedAt`)。步返回后 Adapter 读回两份流作为 `stdout` / `stderr`,删掉实时文件——结果形状不变,证据收集器照旧。自写 Adapter 若想被 `status` 的"最后输出距今"识别,产出同名文件即可;不产出则 `status` 只显示已用时间。
|
|
@@ -5,15 +5,21 @@
|
|
|
5
5
|
## 通用合同
|
|
6
6
|
|
|
7
7
|
- **输入**:环境变量 `BUILDBEAT_INPUT`(JSON):step、worker、run/work id、candidate(如已固定)、允许范围;
|
|
8
|
-
- **输出**:需要结构化结论的步把 JSON 信封写到 `BUILDBEAT_OUTPUT`
|
|
8
|
+
- **输出**:需要结构化结论的步把 JSON 信封写到 `BUILDBEAT_OUTPUT` 指向的文件。最小合法示例(与 `src/v2/runtime/orchestrator.js` 的解析器一致,回归测试 `tests/v2-review-loop.test.js`):
|
|
9
9
|
|
|
10
10
|
```json
|
|
11
|
-
{
|
|
11
|
+
{
|
|
12
|
+
"status": "succeeded",
|
|
13
|
+
"findings": [
|
|
14
|
+
{"severity": "P1", "summary": "日期筛选未覆盖结束日期边界,导致当天记录被遗漏。"}
|
|
15
|
+
]
|
|
16
|
+
}
|
|
12
17
|
```
|
|
13
18
|
|
|
14
19
|
- `status`: `succeeded` | `failed` | `blocked`;
|
|
15
|
-
- `findings[]
|
|
16
|
-
-
|
|
20
|
+
- `findings[]`(可省,省略等于空数组):每条**必须**有 `severity`(`P0` | `P1` | `P2` | `P3`)和字符串 `summary`;其他字段被忽略、不落账。finding 指纹 = 严重度 + `summary` 规范化 hash,所以 `summary` 要稳定、可复述,不要带时间戳或随机 id;
|
|
21
|
+
- **阻断语义**:`P0` / `P1` 阻断——`findings-blocking` 路由进 fix(`reviewTriage: required` 时先停人分诊);`P2` / `P3` 只落 Evidence,不阻断、不派 fixer;已 `dismiss` 的同指纹不再阻断([Approval 指南](07-approval-guide.md));
|
|
22
|
+
- **格式错误不是候选缺陷**:信封外多裹一层 markdown 代码栏(```json … ```)可容忍;其余任何格式(非 JSON、不是对象、finding 缺 `summary`、severity 不在 P0–P3)= `invalid-output`,2.0.0-beta.5 起内核判为 worker 基础设施故障(kind `infra`):不派 fixer、不记失败指纹、不扣预算,停 `WAITING_HUMAN`;人修好 worker 或环境后 `approve --transition resume-<step>` 续跑;
|
|
17
23
|
- **Worker 说的不算证据**:Runner 只相信自己回读的事实(退出码、日志、git 状态);见 [Evidence 指南](06-evidence-guide.md)。
|
|
18
24
|
|
|
19
25
|
## 各角色纪律
|
|
@@ -23,15 +29,19 @@
|
|
|
23
29
|
| planner | 工作项目录 | 产出 intent/plan 草稿;接受与否是人的 digest 绑定动作 |
|
|
24
30
|
| builder | 隔离 worktree(`allowedPaths` 内) | 改动必须落成 git 提交;越界写入 = Run BLOCK,不固定 candidate |
|
|
25
31
|
| verifier | 只跑命令 | 跑真实测试;退出码就是结论,不写信封 |
|
|
26
|
-
| fixer | 同 builder |
|
|
32
|
+
| fixer | 同 builder | 输入是上一轮 review 的 `findings[]`(含指纹与裁决状态,只修 accepted / open);verify 失败进来时输入里**没有**失败摘要,失败命令 / 退出码 / stdout / stderr 在主仓 `.buildbeat/runtime/runs/<RUN>/logs/verify-<attempt>.log`,prompt 要写明去读([模板](../../../templates/v2/envelope/prompts/fixer.md));不接受泛化的"再检查一下" |
|
|
27
33
|
| reviewer | **无**(`readonly: true`) | fresh-context 只读;产出结构化 findings;任何工作树写入由快照比对捕获并按失败落账(不变量 9) |
|
|
28
34
|
|
|
29
35
|
## 失败与预算
|
|
30
36
|
|
|
31
37
|
同一步失败会带着**失败指纹**(命令+退出码+错误摘要+diff digest)重试;连续同指纹或超 `maxAttemptsPerStep`/预算即停,转人工。Worker 不需要(也不能)自己决定"再试一次"。
|
|
32
38
|
|
|
39
|
+
**没配 fixer 不等于自动修复**:run 配置 `workers:` 里缺某个角色(常见是 `fixer`),Run 走到该步时不会报错也不会跳过,而是停 `WAITING_HUMAN`(`enter-fix`,理由 `no adapter configured for worker fixer; attended handoff`)等人接手。想要"测试失败后自动修",必须配置 `fixer`(通常与 builder 同一条命令,prompt 从 `BUILDBEAT_INPUT` 读失败摘要),见 [快速开始](01-quickstart.md)。
|
|
40
|
+
|
|
33
41
|
## 实践提示
|
|
34
42
|
|
|
43
|
+
- 现成的包装脚本与三份 prompt 在 [`templates/v2/envelope/`](../../../templates/v2/envelope/worker.sh):`worker.sh <role> -- <工具命令…>` 负责"工具不在 PATH 就 exit 75、把 `$BUILDBEAT_PROMPT` 追加为最后一个参数、写入步机械 commit、只读步把 stdout 落到 `$BUILDBEAT_OUTPUT`",换工具只改 `--` 后面的命令;确定性首跑回归见 `tests/v2-templates-firstrun.test.js`。
|
|
44
|
+
|
|
35
45
|
- prompt 里明确引用 `delivery/work/<id>/plan.md`,让 Worker 的目标与被批准的 digest 是同一份文件;
|
|
36
46
|
- builder 的提交动作可以由包装脚本机械执行(M4 试点即如此:codex 只改文件,`git commit` 在包装层);
|
|
37
47
|
- reviewer 的 prompt 要求"只输出信封 JSON",并用 `-o`/重定向落到 `$BUILDBEAT_OUTPUT`。
|
|
@@ -42,6 +52,7 @@
|
|
|
42
52
|
- `input.lastReviewed`(仅 readonly 步):`{candidate, run, evidenceRef, range}`——上一次 review 看过的候选与到当前候选的 `range`;reviewer 可只审增量,但**已裁决结论不得翻案**(`anchor` 仍在)。
|
|
43
53
|
- `input.findings`(写入步)与 `input.anchor`(readonly 步)不变。
|
|
44
54
|
|
|
45
|
-
## 所有者可见命名不由 worker
|
|
55
|
+
## 所有者可见命名不由 worker 决定
|
|
46
56
|
|
|
57
|
+
> 自 2.0.0-beta.4(迭代 08)起。
|
|
47
58
|
builder / planner 在实现中会顺手起名:域名、服务名、环境名、自停时长、窗口时长。**凡所有者以后要看见或念出来的名字与参数,不是实现细节,是门前决策项**:写进 intent,或攒进门前决策卡给推荐值与理由,人批后再落地。真实事故:一个按内部术语起的服务名让所有者连问四轮才改成他听得懂的业务名。prompt 里写明这条,reviewer 清单里把"引入了未经批准的可见命名"记为 P2。
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
|
|
44
44
|
`buildbeat-v2 metrics` 输出证据完整率(有证据的步/应有证据的步);M4/M5 退出线 ≥95%,试点实测 100%。
|
|
45
45
|
|
|
46
|
-
## 运行中的读数 ≠
|
|
46
|
+
## 运行中的读数 ≠ 证据
|
|
47
47
|
|
|
48
|
+
> 自 2.0.0-beta.4(迭代 08)起。
|
|
48
49
|
Shell Adapter 在步运行期间把 worker 的 stdout/stderr 实时流到 `.buildbeat/runtime/runs/<RUN>/<step>-<n>.{stdout,stderr}.live`,并留 `live.json`(命令、开始时间)。它们是**读数**:`status` 拿来回答"还在动吗、动了多久、最后一次输出是什么时候",步一结束就收回;证据日志仍由回读生成、digest 仍绑最终日志。耗时同理——每步耗时、同仓历史中位数(`metrics` 的 `typical step duration`)都从台账时间戳推导,不进台账、不进 run-record。
|
|
@@ -25,16 +25,27 @@ buildbeat-v2 accept --repo . --work WORK-X --artifact plan --by <名字> #
|
|
|
25
25
|
3. **transition 门在盖章瞬间 re-check**:merge-evidence-floor / ui-render-gate 等此刻不 PASS → 拒绝;
|
|
26
26
|
4. 终局决定(final-decision 类待批)批准即 `RUN_TERMINAL SUCCEEDED` + 压实 run-record 进 Git 面。
|
|
27
27
|
|
|
28
|
-
##
|
|
28
|
+
## 五个词各指什么(批准 ≠ 执行)
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
会话与文档里"接受 / 批准 / 恢复 / 成功 / 合并"混用过,统一如下:
|
|
31
|
+
|
|
32
|
+
| 词 | 命令 | 含义 | 不等于 |
|
|
33
|
+
|---|---|---|---|
|
|
34
|
+
| **接受**(accept) | `accept --artifact intent\|plan` | 一份工件的 digest 被人认可;改过即 `stale` | 开工;不产生任何 Run |
|
|
35
|
+
| **批准某转换**(approve) | `approve --transition <t>` | 允许 Run 走**这一条** transition:`enter-fix`(放行分诊后的 fixer)、`resume-<step>`(预算耗尽 / infra 停人后再跑一次,会落 `BUDGET_EXTENDED`)、`enter-review`(Work 级 review 上限后再审一轮)、`enter-apply-readback`(上线车道"我做完了") | 批准了别的转换;非终态转换批准后 Run **不会自己动**,要 `resume --config <run-config>` 续跑(`approve` 输出的 `next:` 行会写明) |
|
|
36
|
+
| **合并决定**(最终批准) | `approve --transition enter-wait-merge` | 候选已具备合并条件:candidate + planDigest + evidenceDigest 此刻全部成立;Run 进终态 `SUCCEEDED`,run-record 压进 Git 面 | 代码已合并、已 push、已部署——这三件永远是你在 Runner 之外的动作 |
|
|
37
|
+
| **Run SUCCEEDED** | — | Run 停在了它该停的地方,证据齐 | Work 完成。`overview` 只有回读到候选在当前分支上才显示 `MERGED` |
|
|
38
|
+
| **拒绝**(reject) | `reject --reason` | Run 终止(`FAILED`,理由入账) | 工件失效;intent/plan 的接受状态不变 |
|
|
39
|
+
|
|
40
|
+
同理 observe 草稿的 `fix_now` 只是接受,Run 由人发起。保护动作见 [安全边界](09-security-boundaries.md)。
|
|
31
41
|
|
|
32
42
|
## 人批点由 Risk Preset 决定
|
|
33
43
|
|
|
34
44
|
`fast` 仅 Merge;`standard` Plan+Merge;`controlled` Intent+Plan+Merge+Release;`legacy-four-gates` 为 v1 四 Gate 完整形态(迁移期用,见 [迁移指南](08-migration-v1.md))。待批项强制携带 findings 摘要与理由——防"秒批"退化;人批等待时长进 `metrics`。
|
|
35
45
|
|
|
36
|
-
##
|
|
46
|
+
## 发现分诊门与锚定审查
|
|
37
47
|
|
|
48
|
+
> 自 2.0.0-beta.3(beta.3)起。
|
|
38
49
|
来自三十轮部署战役最大的结构性教训:**finding 是处方不是事实**,无记忆 fresh reviewer 会开出互斥处方并翻案早已接受的设计,自动路由 fixer 让振荡直接烧钱。两个机制配套:
|
|
39
50
|
|
|
40
51
|
1. **分诊门**:run 配置 `reviewTriage: required` 后,review 产出 P0/P1 finding 不再自动派 fixer,而是停 `WAITING_HUMAN`(kind `finding-triage`),待批理由逐条列出 finding 指纹。人先裁决、再 `approve --transition enter-fix` 放行(或 `reject` 终止 Run)。
|
|
@@ -50,8 +61,9 @@ merge 批准只表示 **merge-ready**:真正的合并、push、发布是你在
|
|
|
50
61
|
|
|
51
62
|
裁决记忆在 Git 面,删 runtime 不丢(不变量 23 同款测试覆盖)。
|
|
52
63
|
|
|
53
|
-
##
|
|
64
|
+
## 等待要能找到人
|
|
54
65
|
|
|
66
|
+
> 自 2.0.0-beta.4(迭代 08)起。
|
|
55
67
|
试点工作区 58 个 Run 里 32 个被取消,多数是在 `WAITING_HUMAN` 挂满一天后批量清掉;人批平均等 7~12 小时。原因不是人慢,是**没人知道有东西等他**。三件事配套:
|
|
56
68
|
|
|
57
69
|
1. **下一句该说什么**:`status` 与 `inbox` 在每个等待后面直接给出可复制的命令(`approve` / `reject`,分诊时加 `findings list|adjudicate`);`inbox` 按 Work 分组并显示已等待时长。输出里的 `--repo` 只在项目内给相对路径,项目外给 `<repo-path>` 占位——本机绝对路径永不进输出。
|
|
@@ -75,14 +87,16 @@ merge 批准只表示 **merge-ready**:真正的合并、push、发布是你在
|
|
|
75
87
|
|
|
76
88
|
通知不是审批通道:拍板仍只能在 CLI 完成,digest 绑定不变。
|
|
77
89
|
|
|
78
|
-
## 从「等我批」到「到哪了」:overview
|
|
90
|
+
## 从「等我批」到「到哪了」:overview
|
|
79
91
|
|
|
92
|
+
> 自 2.0.0-beta.4(迭代 08)起。
|
|
80
93
|
`inbox` 只知道哪个 Run 在等人;`buildbeat-v2 overview --repo .` 按 Work 回答「走到哪、下一步该谁」——intent/plan 是否被接受(接受后改过即 `stale`)、最新 Run 状态与候选、候选是否已合入当前分支、未裁决 P0/P1 数、是否有 `env-facts.md`,每行附下一句命令。运行时被删后由 Git 面 run-record 补足。会话开场先跑它,再回答用户「当前进度」。
|
|
81
94
|
|
|
82
95
|
**阶段判定的真相修正(迭代 09)**:候选只要合入了当前分支,Work 就是 `MERGED`,哪怕最新 Run 是 CANCELLED(试点一条应用登录 Run 因预算问题被取消,候选却已在生产,overview 曾报 `STOPPED_CANCELLED` 并催重试);`release-readback` 车道成功关窗的 Work 显示 `RELEASED`,不再说 "nothing to merge";已合并 / 已发布 / 已关闭的 Work 不再提示未裁决 finding 数。`overview` 每个 Work 还多一行 `cost:`(见 [Workflow 指南](02-workflow-guide.md) 的 Work 级预算)。
|
|
83
96
|
|
|
84
|
-
## 你自己改好了:`resume --adopt
|
|
97
|
+
## 你自己改好了:`resume --adopt`
|
|
85
98
|
|
|
99
|
+
> 自 2.0.0-beta.5(迭代 09)起。
|
|
86
100
|
Run 停在 `enter-fix` / `resume-fix` 时,驾驶会话或人常常已经在 Run 的 worktree 里把问题修掉并提交了。此时再 `approve` 会派一个无事可做的 fixer,再多跑一次 verify(试点一条前端 Run 因此跑到 verify 第 5 次、fix 第 3 次)。改用:
|
|
87
101
|
|
|
88
102
|
```bash
|
|
@@ -93,6 +107,7 @@ buildbeat-v2 resume --config <run-config.yaml> --adopt <sha> --by <名字>
|
|
|
93
107
|
|
|
94
108
|
`doctor` 现在还打印本仓 `delivery/work/<ID>/` 里 intent / plan 的存在与接受状态,并对每条要求 `artifact.accepted` 的 policy 预告"start 会停在哪一步"——此前两次 doctor 通过、start 却被"plan 未镜像到子仓"挡住。
|
|
95
109
|
|
|
96
|
-
##
|
|
110
|
+
## 可见命名是门前决策项
|
|
97
111
|
|
|
112
|
+
> 自 2.0.0-beta.4(迭代 08)起。
|
|
98
113
|
审批三级里 `BATCH_AT_GATE` 明确包含:域名、服务名、环境名、自停时长、窗口时长等**所有者以后要看见或念出来的名字与参数**。worker 顺手定的名字进不了台账;planner 在 intent 里列出并给推荐值,人一次批。
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
# v1 → v2
|
|
1
|
+
# v1 → v2 迁移指南(手工 runbook)
|
|
2
2
|
|
|
3
|
-
按收尾修正三:装机量 N=1,**不做 importer
|
|
3
|
+
按收尾修正三:装机量 N=1,**不做 importer 工具**,人工走完。各步括号里的耗时是作者一次迁移的估算,不是承诺。
|
|
4
|
+
|
|
5
|
+
先分清两件事:**升级 CLI** 与 **迁移项目状态**。`npm install --global @haiyangbg/buildbeat@latest` 只是前者——它把 `buildbeat-v2` 装到机器上,对项目文件零改动;v1 的 `buildbeat doctor / init / adopt / upgrade` 原样保留,schema 仍是 2,`buildbeat upgrade` 对 1.21 骨架报 up-to-date。后者才是本文:把"哪些工作在途"从 v1 看板搬进 `delivery/work/`,并冻结旧入口。三条铁律全程有效:
|
|
4
6
|
|
|
5
7
|
1. **不猜旧状态有效性**——v1 看板/状态文件里没有证据支撑的行,一律当"待人工确认",不自动翻译成 v2 状态;
|
|
6
8
|
2. **单向迁移**——v1 只冻结不删除,历史归档可查;
|
|
@@ -8,7 +10,7 @@
|
|
|
8
10
|
|
|
9
11
|
## 前提(约 30 分钟)
|
|
10
12
|
|
|
11
|
-
- [ ]
|
|
13
|
+
- [ ] 安装稳定版(`npm install --global @haiyangbg/buildbeat@latest`,2.0.0 起 `latest` 即 v2;`buildbeat-v2` 无参运行能打印用法);
|
|
12
14
|
- [ ] 读完 [快速开始](01-quickstart.md) 与 [Approval 指南](07-approval-guide.md);
|
|
13
15
|
- [ ] 目标仓库工作树干净、基线已提交。
|
|
14
16
|
|
|
@@ -65,4 +67,6 @@ v1 脚本本体不用改——它们的权威边界(各查什么、不证什
|
|
|
65
67
|
- 至少一个真实 Run 走完 Build→Verify→Review→人批闭环;
|
|
66
68
|
- 三栏清单与拍板结果留档(就是迁移的证据)。
|
|
67
69
|
|
|
68
|
-
|
|
70
|
+
迁移前后可核对的目录:迁移前 `pm/NOW.md`、`pm/status/*`、`pm/changes/*` 可写;迁移后它们只读并带冻结声明,`delivery/work/<ID>/` 每个在途事项一个目录,`buildbeat-v2 overview --repo .` 能列出全部活动 Work 且没有重复。旧文件不删,任何时候可读;不要为旧 Run 伪造 run-record 或 manifest。
|
|
71
|
+
|
|
72
|
+
回退:v1 全部原样在 Git 里,去掉冻结声明即可回去——但双写永远禁止,回去就是整个回去。已经跑出的 v2 Run 台账保留在 `delivery/work/*/runs/`,回退不需要删它。
|
|
@@ -2,22 +2,33 @@
|
|
|
2
2
|
|
|
3
3
|
权威:[`RFC-0001 §保护动作`](../RFC-0001-product-definition.md)、[`V2-PLAN.md`](../../V2-PLAN.md) §9 不变量。设计哲学:**保护动作 = 能力移除**——不是"请 Agent 别做",而是让它做不到。
|
|
4
4
|
|
|
5
|
-
## Runner
|
|
5
|
+
## Runner 侧的本地边界(LOCAL_ENFORCED,均有测试)
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|---|---|
|
|
9
|
-
| push 封禁 | worktree 级 `remote.pushurl=protected://push-blocked-by-buildbeat`——Worker 在工作区内 `git push` 无处可推(真实 remote 上实测) |
|
|
10
|
-
| 写范围 | `allowedPaths` 越界写入 → 不固定 candidate、`workspace.scope` BLOCK 落账、Run 停 |
|
|
11
|
-
| Reviewer 只读 | 步级前后快照比对,任何写入按失败落账(不变量 9) |
|
|
12
|
-
| 凭据隔离 | Worker env 白名单默认仅 `PATH HOME LANG LC_ALL TMPDIR TERM USER SHELL`;宿主云凭据/token 到不了子进程(`inheritEnv` 显式打开会被 doctor 降级标注) |
|
|
13
|
-
| 单活动 Run | 仓库级锁,一仓同时只有一个活动 Run |
|
|
14
|
-
| 控制文件 | workflow/policy/run 配置在主检出,不在 Worker 的 worktree 写范围内 |
|
|
7
|
+
下表每行分两栏:**内核实际做到的**,与**不能由此推出的**。前者有回归测试;后者要靠宿主沙箱 / 容器 / 服务端,Runner 不冒充。
|
|
15
8
|
|
|
16
|
-
|
|
9
|
+
| 边界 | 内核实际做到的(检测或移除) | 不能由此推出 |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| push 封禁 | worktree 级 `remote.pushurl=protected://push-blocked-by-buildbeat`——Worker 在工作区内对配置的 remote `git push` 无处可推(真实 remote 上实测) | Worker 不能 `git remote add` 另一个远端、不能发起任何网络请求 |
|
|
12
|
+
| 写范围 | `allowedPaths` 越界写入 → 不固定 candidate、`workspace.scope` BLOCK 落账、Run 停——越界改动**不可能**成为合格候选 | Worker 进程无法触碰 worktree 之外的宿主目录 |
|
|
13
|
+
| Reviewer 只读 | 步级前后快照比对,任何工作树写入按失败落账(不变量 9)——这是**事后检测并阻断结果**,不是操作系统级禁写 | 写入在发生那一刻就被拦下 |
|
|
14
|
+
| 凭据隔离 | Worker env 默认白名单仅 `PATH HOME LANG LC_ALL TMPDIR TERM USER SHELL`;宿主 shell 里的云凭据 / token **环境变量**不进子进程;`inheritEnv: true` 显式打开会被 doctor 标为 ADVISORY;`env:` 只注入你点名的变量(CLI 加载路径 2.0.1 起真正透传,2.0.0 及更早 doctor 与 start 姿态不一致,见 [Adapter 指南](04-adapter-guide.md)) | Worker 读不到 `$HOME` 下的凭据文件、keychain、ssh key 等宿主资源(`HOME` 在白名单里) |
|
|
15
|
+
| 单活动 Run | 仓库级锁,一仓同时只有一个活动 Run | 多仓 / 多机并发有协调 |
|
|
16
|
+
| 控制文件 | workflow / policy / run 配置在主检出,不在 Worker 的 worktree 写范围内 | Worker 无法通过其他途径读到它们 |
|
|
17
|
+
| 内核无外部动作 | merge、push、部署、发布在 Runner **没有调用路径**(不变量 20,doctor 打印);Runner 至多把"候选具备合并条件"放进 inbox | 你配置的任意外部 Worker 命令在全部宿主环境下都做不了这些动作 |
|
|
18
|
+
|
|
19
|
+
一句话:**内核保证的是"越界的结果进不了台账、成不了候选、盖不了章"**;"Worker 一开始就做不到"要靠宿主给它的沙箱(工具白名单、出网限制、无生产凭据)。
|
|
17
20
|
|
|
18
21
|
## 无人值守的前置条件(MVP 起强制的立场)
|
|
19
22
|
|
|
20
|
-
prompt injection 是一等攻击面:无人值守 Worker 会消费仓库内任意文件。unattended run
|
|
23
|
+
prompt injection 是一等攻击面:无人值守 Worker 会消费仓库内任意文件。unattended run 必须同时满足三层,缺一层就降级 attended(人在环):
|
|
24
|
+
|
|
25
|
+
| 层 | 谁保证 | 内容 |
|
|
26
|
+
|---|---|---|
|
|
27
|
+
| 内核 | Runner(本表上节) | push 封禁、写范围、只读 reviewer、env 白名单、无外部动作调用路径 |
|
|
28
|
+
| 宿主 | 你的 worker 沙箱 / 容器 / 工具本身的权限模式(如 `codex exec -s read-only`) | 工具白名单、出网限制、**无生产凭据**——内核不检查也检查不了这层,doctor 只报告 env 姿态 |
|
|
29
|
+
| 服务端 | 代码托管 / CI / 部署平台 | 分支保护、必需 CI、部署审批(下节) |
|
|
30
|
+
|
|
31
|
+
observe 的 diagnose 命令同理只读、同 env 白名单纪律。
|
|
21
32
|
|
|
22
33
|
## SERVER_ENFORCED 是诚实声明
|
|
23
34
|
|
|
@@ -57,8 +57,9 @@ rm -rf .buildbeat/runtime/
|
|
|
57
57
|
|
|
58
58
|
`buildbeat-v2 doctor --config <run-config>`:配置可解析、workflow 无出口环、adapter env 姿态、digest 可算、supersede 与 stall 阈值、通知通道与环境变量是否就位。`events`/`replay`/`metrics` 全部只读,可随时跑。
|
|
59
59
|
|
|
60
|
-
## "是不是卡住了"
|
|
60
|
+
## "是不是卡住了"
|
|
61
61
|
|
|
62
|
+
> 自 2.0.0-beta.4(迭代 08)起。
|
|
62
63
|
先看 `buildbeat-v2 status --repo . --run <RUN>`:在飞步骤有已用时间、同仓历史中位数、worker 命令、最后一次输出距今多久与末三行输出。无输出超过阈值(默认 15 分钟,`--stall-after <分钟>` 或 run 配置 `stallAfterMs`)标 `STALLED`——**只标不杀**。判断口径:
|
|
63
64
|
|
|
64
65
|
- 有输出在持续 → 等(对照 `typical` 看是否已远超中位数);
|
|
@@ -67,8 +68,9 @@ rm -rf .buildbeat/runtime/
|
|
|
67
68
|
|
|
68
69
|
想不盯屏就订阅 `STALLED` 通知([Approval 指南](07-approval-guide.md))。`watch --repo . --run <RUN> --once true` 可手工探测一次。
|
|
69
70
|
|
|
70
|
-
## 打扫卫生:gc
|
|
71
|
+
## 打扫卫生:gc
|
|
71
72
|
|
|
73
|
+
> 自 2.0.0-beta.4(迭代 08)起。
|
|
72
74
|
终态 Run 会留下工作树、`run/*` 分支和偶尔的锁。`buildbeat-v2 gc --repo .` 默认只出计划,`--apply true` 执行:
|
|
73
75
|
|
|
74
76
|
- 只动**终态且已压成 run-record** 的 Run(Git 面有账才动运行时面);
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Session handoffs: close the chat, keep the work
|
|
2
|
+
|
|
3
|
+
[简体中文](11-session-handoff.md) | **English**
|
|
4
|
+
|
|
5
|
+
BuildBeat uses project files, Git, and run ledgers to continue work. A fresh session reads those facts to decide whether to proceed, recover an interrupted Run, handle a pending decision, or prepare the next Run for the same Work. The person taking over can be you or another teammate. The handoff does not need the old chat transcript, and it does not automatically save discussion that exists only in that chat.
|
|
6
|
+
|
|
7
|
+
## Before closing the old session
|
|
8
|
+
|
|
9
|
+
Tell the current session:
|
|
10
|
+
|
|
11
|
+
> I am switching sessions. Save context needed to continue that is still only in this chat. Check the current Work, candidate, unverified items, pending decisions, and run state.
|
|
12
|
+
|
|
13
|
+
The session should check that:
|
|
14
|
+
|
|
15
|
+
- Goals, scope, acceptance criteria, and decisions have a clear home in project files. Recording facts must not rewrite approvals or turn an unaccepted idea into an accepted plan.
|
|
16
|
+
- Candidate commits, uncommitted changes, verification evidence, and the next step are identifiable. Save necessary environment facts in the Work's `env-facts.md`; reference the source of secrets without copying their values into project records.
|
|
17
|
+
- `overview`, `inbox`, and `status` reflect the actual state. If a Run is active, explain whether its process is detached from the driving session. State uncertainty when this cannot be confirmed.
|
|
18
|
+
- Project records and candidate branches are committed and synchronized under existing authorization when another machine or collaborator needs them. Saved to disk does not mean committed or pushed.
|
|
19
|
+
|
|
20
|
+
When these facts are already saved, each handoff does not need another long report. Removing a chat should retain the project directory, run ledger, and worktree. Some tools also remove temporary workspaces when deleting a task; check what the operation actually removes.
|
|
21
|
+
|
|
22
|
+
## Taking over in a new session
|
|
23
|
+
|
|
24
|
+
Open a fresh session in the **same project directory**. Load the BuildBeat Skill and the project's `AGENTS.md` using the target tool's supported mechanism, then say:
|
|
25
|
+
|
|
26
|
+
> Continue this project. Read its BuildBeat entry point and active work first. Check Git, progress, verification results, and pending decisions, then proceed within existing authorization.
|
|
27
|
+
|
|
28
|
+
The session reads current facts first:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
buildbeat-v2 overview --repo .
|
|
32
|
+
buildbeat-v2 inbox --repo .
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
It then reads the goal, plan, decisions, and configuration under the relevant `delivery/work/<ID>/`. For active Run details, use `status --repo . --run <RUN-ID>`. Read IDs from actual output rather than guessing from a conversation.
|
|
36
|
+
|
|
37
|
+
| Observed state | Next action |
|
|
38
|
+
|---|---|
|
|
39
|
+
| A Run is executing normally | Observe it; avoid starting a duplicate or modifying its worktree |
|
|
40
|
+
| A Run awaits a human decision | Show the current subject and evidence; a new session does not create a missing approval or renew a stale one |
|
|
41
|
+
| The Runner was interrupted; its ledger and worktree remain | Inspect the state and follow recovery guidance, then `resume --config <configuration-path>`; the interrupted step may run again |
|
|
42
|
+
| Dirty worktree, changed configuration, stale approval, or missing state | Explain the specific difference and follow the runtime's handling; do not claim lossless recovery |
|
|
43
|
+
| A Run is terminal, but its Work needs another execution | Prepare the next Run from existing artifacts and the candidate; terminal Runs do not reopen |
|
|
44
|
+
| The work is already merged or released | Read back Git or release facts; do not repeat work because an earlier Run was canceled |
|
|
45
|
+
|
|
46
|
+
Recovery approval and the final merge decision are distinct actions. See [approvals](07-approval-guide.md) and [run recovery](10-recovery.md) (Chinese).
|
|
47
|
+
|
|
48
|
+
## Another teammate takes over
|
|
49
|
+
|
|
50
|
+
The person handing over saves shared goals, plans, decisions, acceptance records, and the next step in project files, synchronizes them with the shared repository under existing authorization, and makes candidate commits reachable. Record who will carry the Work forward, whether its original Run is still active, and where it is executing. Actual readback remains authoritative for run state.
|
|
51
|
+
|
|
52
|
+
Once granted project access, the next teammate syncs the relevant files and candidate branches, loads the project entry point, and uses their own AI tool to inspect scope, evidence, pending decisions, and environment. Existing valid decisions remain in effect. Taking over does not automatically grant someone else's merge, release, or credential permissions.
|
|
53
|
+
|
|
54
|
+
If the original Run is not terminal, check its execution environment first. An empty `overview` or `inbox` on a new machine does not show that the old machine has no active Run. Local locks do not coordinate different machines or Git clones; do not start duplicate work on that basis. Before executing in a new environment, settle how the original Run will be handled, then prepare subsequent execution from synchronized artifacts and candidates.
|
|
55
|
+
|
|
56
|
+
Teammates can own separate end-to-end work packages or hand over the same package. Product, full-stack, and testing are AI perspectives each teammate may use (review is the Run's built-in read-only reviewer, not a session perspective); both the person and the perspective can change. Access control relies on existing repository hosting, execution platforms, and team authorization agreements. BuildBeat does not add a member account or permission system.
|
|
57
|
+
|
|
58
|
+
## Changing tools, models, and perspectives
|
|
59
|
+
|
|
60
|
+
Project artifacts are readable files that different tools can consume. The new tool needs the entry point, access to the same project, and suitable permissions. Execution Workers also need a compatible command, authentication, and output contract. The external AI tool selects the model.
|
|
61
|
+
|
|
62
|
+
The product, full-stack, and testing perspectives read the same Work's goal, constraints, and evidence, and follow their own write boundaries; review is carried out by the Run's built-in read-only reviewer. Changing perspective does not change accepted scope or require duplicating progress documents. The current runtime supports one active Run per repository.
|
|
63
|
+
|
|
64
|
+
This explains protocol continuity, not proof that every tool combination has passed a real handoff. See the [capability matrix](../../CAPABILITY-MATRIX.md) for existing evidence and the [adapter guide](04-adapter-guide.md) for integration requirements (Chinese).
|
|
65
|
+
|
|
66
|
+
## Moving machines versus recovering a Run
|
|
67
|
+
|
|
68
|
+
| Retained or synchronized content | What it supports | What it does not establish |
|
|
69
|
+
|---|---|---|
|
|
70
|
+
| Committed Work artifacts, decisions, standards, and terminal records | Reading durable project facts on another machine | Raw execution logs and active checkpoints were also synchronized |
|
|
71
|
+
| Candidate branches and their commits | Reading candidate code, diffs, and merge status | An ordinary clone fetched a branch that exists only on the old machine |
|
|
72
|
+
| Local runtime and the matching worktree | Inspecting and recovering an active Run in its original environment | Copying files to another path migrates an executing process |
|
|
73
|
+
|
|
74
|
+
`.buildbeat/runtime/` contains active ledgers and raw logs; `.buildbeat/worktrees/` contains working trees. Both are normally excluded from Git. After runtime cleanup, Git-managed facts can support further project work, but exact active-Run recovery and raw logs are no longer assured. A terminal record's log digest cannot reconstruct the log text.
|
|
75
|
+
|
|
76
|
+
To take over elsewhere, synchronize project facts and candidates, prepare tools and environment, and decide where execution should resume. BuildBeat does not currently automate active-Run migration between machines.
|
|
77
|
+
|
|
78
|
+
## Verifying a real handoff
|
|
79
|
+
|
|
80
|
+
Choose a small task with an existing verification command. Session A saves a goal and plan, then executes to an identifiable state. Record the Work, candidate, verification result, and pending decision. Close the chat. Give a fresh session B only the project location and a request to continue, without the old conversation history. For a team handoff, have another authorized teammate sync the files and candidate, then perform this step using their own tool.
|
|
81
|
+
|
|
82
|
+
Check whether B reads the same goal, state, and next step from project files and tools, then continues within existing authorization. Record tool and model versions, files read, actual commands, and the outcome. Verify combinations of tools, teammates, and machines individually. An illustrative conversation is not that evidence.
|
|
83
|
+
|
|
84
|
+
Existing `tests/v2-resume.test.js`, `tests/v2-approval.test.js`, and `tests/v2-overview-stages.test.js` cover recovery and state mechanisms. They do not constitute model-behavior acceptance for a real fresh-session handoff.
|