@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.
- package/CHANGELOG.md +7 -0
- package/README.en.md +4 -4
- package/README.md +1 -1
- package/SKILL.md +1 -1
- package/docs/README.md +3 -2
- package/docs/RELEASING.md +3 -1
- package/docs/v2/guide/01-quickstart.en.md +163 -0
- package/docs/v2/guide/01-quickstart.md +4 -2
- package/docs/v2/guide/06-evidence-guide.en.md +51 -0
- package/docs/v2/guide/06-evidence-guide.md +2 -0
- package/docs/v2/guide/07-approval-guide.en.md +115 -0
- package/docs/v2/guide/07-approval-guide.md +2 -0
- package/docs/v2/guide/10-recovery.en.md +83 -0
- package/docs/v2/guide/10-recovery.md +2 -0
- package/docs/v2/guide/README.md +4 -4
- package/example/.buildbeat/notify.yaml +13 -0
- package/example/.buildbeat/observe.yaml +31 -0
- package/example/AGENTS.md +73 -0
- package/example/BUILDBEAT.md +14 -0
- package/example/CLAUDE.md +7 -0
- package/example/README.md +25 -0
- package/example/delivery/envelope/prompts/builder.md +10 -0
- package/example/delivery/envelope/prompts/fixer.md +10 -0
- package/example/delivery/envelope/prompts/reviewer.md +13 -0
- package/example/delivery/envelope/worker.sh +70 -0
- package/example/delivery/work/WORK-EXPORT-DATE-FILTER/decisions.jsonl +3 -0
- package/example/delivery/work/WORK-EXPORT-DATE-FILTER/intent.md +24 -0
- package/example/delivery/work/WORK-EXPORT-DATE-FILTER/plan.md +20 -0
- package/example/delivery/work/WORK-EXPORT-DATE-FILTER/run-config.yaml +66 -0
- package/example/delivery/work/WORK-EXPORT-DATE-FILTER/runs/RUN-EXPORT-01/run-record.json +108 -0
- package/example/delivery/work/WORK-EXPORT-DATE-FILTER/workflow.yaml +44 -0
- package/example/gitignore.template +20 -0
- package/example/package.json +13 -0
- package/example/pm/decisions.md +8 -0
- package/example/src/export.js +25 -0
- package/example/src/ledger.js +16 -0
- package/example/tests/export.test.js +35 -0
- package/example//346/214/207/346/214/245/345/217/260.md +40 -0
- package/package.json +2 -1
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// CSV 导出(新地盘)。WORK-EXPORT-DATE-FILTER 给它加了 from / to 日期筛选。
|
|
2
|
+
|
|
3
|
+
const HEADER = "date,category,amount,note";
|
|
4
|
+
|
|
5
|
+
function escapeCell(value) {
|
|
6
|
+
const text = String(value ?? "");
|
|
7
|
+
return /[",\n]/.test(text) ? `"${text.replace(/"/g, '""')}"` : text;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// options.from / options.to 都是含端点的 "YYYY-MM-DD";省略一端表示不限。
|
|
11
|
+
export function exportCsv(ledger, options = {}) {
|
|
12
|
+
const { from, to } = options;
|
|
13
|
+
for (const bound of [from, to]) {
|
|
14
|
+
if (bound !== undefined && !/^\d{4}-\d{2}-\d{2}$/.test(bound)) {
|
|
15
|
+
throw new Error(`bad date bound: ${bound}`);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
if (from && to && from > to) {
|
|
19
|
+
throw new Error(`from ${from} is after to ${to}`);
|
|
20
|
+
}
|
|
21
|
+
const rows = ledger
|
|
22
|
+
.filter((entry) => (from === undefined || entry.date >= from) && (to === undefined || entry.date <= to))
|
|
23
|
+
.map((entry) => [entry.date, entry.category, (entry.amount / 100).toFixed(2), entry.note].map(escapeCell).join(","));
|
|
24
|
+
return [HEADER, ...rows].join("\n") + "\n";
|
|
25
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// 记账核心(老地盘:只维护,改动一律先问人)。
|
|
2
|
+
// 一条流水 = { date: "YYYY-MM-DD", category, amount, note };金额以分为单位的整数。
|
|
3
|
+
|
|
4
|
+
export function addEntry(ledger, entry) {
|
|
5
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(entry.date)) {
|
|
6
|
+
throw new Error(`bad date: ${entry.date}`);
|
|
7
|
+
}
|
|
8
|
+
if (!Number.isInteger(entry.amount)) {
|
|
9
|
+
throw new Error("amount must be an integer number of cents");
|
|
10
|
+
}
|
|
11
|
+
return [...ledger, { note: "", ...entry }];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function total(ledger) {
|
|
15
|
+
return ledger.reduce((sum, entry) => sum + entry.amount, 0);
|
|
16
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
|
|
4
|
+
import { exportCsv } from "../src/export.js";
|
|
5
|
+
import { addEntry } from "../src/ledger.js";
|
|
6
|
+
|
|
7
|
+
const ledger = [
|
|
8
|
+
{ date: "2026-08-30", category: "餐饮", amount: 3550, note: "" },
|
|
9
|
+
{ date: "2026-09-01", category: "交通", amount: 1200, note: "地铁, 两程" },
|
|
10
|
+
{ date: "2026-09-15", category: "房租", amount: 250000, note: "" },
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
test("exports every row with a header when no bounds are given", () => {
|
|
14
|
+
const csv = exportCsv(ledger);
|
|
15
|
+
const lines = csv.trimEnd().split("\n");
|
|
16
|
+
assert.equal(lines[0], "date,category,amount,note");
|
|
17
|
+
assert.equal(lines.length, 4);
|
|
18
|
+
assert.equal(lines[2], '2026-09-01,交通,12.00,"地铁, 两程"');
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test("from / to bounds are inclusive and each side is optional", () => {
|
|
22
|
+
assert.equal(exportCsv(ledger, { from: "2026-09-01" }).trimEnd().split("\n").length, 3);
|
|
23
|
+
assert.equal(exportCsv(ledger, { to: "2026-09-01" }).trimEnd().split("\n").length, 3);
|
|
24
|
+
assert.equal(exportCsv(ledger, { from: "2026-09-01", to: "2026-09-01" }).trimEnd().split("\n").length, 2);
|
|
25
|
+
assert.equal(exportCsv(ledger, { from: "2026-10-01" }), "date,category,amount,note\n");
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test("malformed or inverted bounds are rejected, not silently ignored", () => {
|
|
29
|
+
assert.throws(() => exportCsv(ledger, { from: "2026/09/01" }), /bad date bound/);
|
|
30
|
+
assert.throws(() => exportCsv(ledger, { from: "2026-09-02", to: "2026-09-01" }), /is after/);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test("ledger entries still validate their own date", () => {
|
|
34
|
+
assert.throws(() => addEntry([], { date: "bad", category: "x", amount: 1 }), /bad date/);
|
|
35
|
+
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# 指挥台 — 简账:Builder 怎么驱动工作(忘了怎么开场就看这页)
|
|
2
|
+
|
|
3
|
+
> 本仓运行 BuildBeat。会话按所用工具的方式装载 `AGENTS.md`(多数工具自动读根目录 `AGENTS.md` / `CLAUDE.md`;不自动读的,开场把它贴给会话);活动工作在 `delivery/`。你基本只需说下面这几句话,命令由会话调、不用你手敲。
|
|
4
|
+
|
|
5
|
+
## 日常六句话
|
|
6
|
+
|
|
7
|
+
| 你想干什么 | 说什么 | 会话背后调什么 |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| 看现在到哪了、该谁动 | 「当前进度」/「待办是什么」 | `buildbeat overview --repo .`(每个 Work 的阶段 + 下一步)+ `observe status` |
|
|
10
|
+
| 看有什么等我批 | 「有什么要我拍板」 | `buildbeat inbox --repo .`(每条附可复制的下一句) |
|
|
11
|
+
| 立一件新事 | 「开个 Work:〔一句话目标〕」→ 看完说「接受」 | 建 `delivery/work/<ID>/intent.md + plan.md` → `accept`(digest 绑定) |
|
|
12
|
+
| 让它干活 | 「开工」/「再来一轮」 | 先 `buildbeat doctor --config …`(配置、intent/plan 接受状态、env 姿态、预算),再 `start --config … --attempt new`(自动编号、自动作废旧等待,停在合并决定) |
|
|
13
|
+
| 它是不是卡了 | 「怎么样了」/「卡住了吗」 | `buildbeat status --repo . --run <RUN>`(耗时、历史中位数、最后输出、STALLED) |
|
|
14
|
+
| 拍板 | 「批准 / 拒绝〔RUN-ID〕」;分诊时「这条接受,那条不算」 | `approve` / `reject` / `findings adjudicate`;会话说清批的是哪一步(放行 fixer / 再跑一次 / 合并决定),非终态批准后 `resume` 续跑;合并决定只表示候选够格合并,合并/push/部署逐项另说 |
|
|
15
|
+
|
|
16
|
+
其他:生产报警看 `delivery/observe/intents/` 草稿 → 「fix_now / schedule / dismiss」;上线用 `release-readback` 预设开一个 Run,「我做完了」就是批准 `enter-apply-readback`;「打扫卫生」= `gc --repo .`(先看计划再 `--apply true`)。
|
|
17
|
+
|
|
18
|
+
## 新开一个 Work 时会话要动的文件
|
|
19
|
+
|
|
20
|
+
`delivery/work/<WORK-ID>/`:`intent.md`(为什么 + 止损线)、`plan.md`(怎么做)、`run-config.yaml`(从 `templates/v2/run-config.example.yaml` 改 work / run / allowedPaths / workers)、`workflow.yaml`(从 `$(npm root -g)/@haiyangbg/buildbeat/src/v2/presets/software-delivery.yaml` 复制)。信封与 worker 包装在仓级 `delivery/envelope/`,不用每个 Work 重写。
|
|
21
|
+
|
|
22
|
+
## 视角开场白
|
|
23
|
+
|
|
24
|
+
| AI 视角 | 在哪开(cwd) | 你的一句话 |
|
|
25
|
+
|---|---|---|
|
|
26
|
+
| **产品** | 工作区根 | 「把当前目标收成一个 Work」/「验收」——定 intent/plan、维护决策收件箱、按决策包记 `pm/decisions.md` |
|
|
27
|
+
| **全栈** | `<代码仓>/` | 「〔WORK-ID〕该你了,开工」——授权范围内实现,Run 停在合并决定回人批 |
|
|
28
|
+
| **测试** | 工作区根 | 「验〔RUN-ID〕候选」——对精确 candidate 独立核验,报告落所属 Work 目录 |
|
|
29
|
+
|
|
30
|
+
## 域回复怎么写
|
|
31
|
+
|
|
32
|
+
面向你收口统一「已做 → 未做 → 下一步」,各一句;证据紧跟事项。下一步只写一条:下一棒是谁、需要你确认什么、或「我继续做,暂不交棒」。
|
|
33
|
+
|
|
34
|
+
## 按项目阶段的完整问法
|
|
35
|
+
|
|
36
|
+
未开始 → 立项定方案 → 准备执行 → 执行推进 → 验收合并 → 上线 → 完结换期复盘,每阶段说什么、会话做什么、你得到什么:见 BuildBeat 指南第 0 篇 `docs/v2/guide/00-how-to-talk.md`(Skill 装载目录下同路径)。
|
|
37
|
+
|
|
38
|
+
## 红线、写边界、审批三级、可见命名进决策卡
|
|
39
|
+
|
|
40
|
+
全在 `AGENTS.md`,本页不复制。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@haiyangbg/buildbeat",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"description": "BuildBeat: Git-based AI delivery across models, tools, sessions, and people, with context in project files, build-test-review-fix loops, and human decisions.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"!docs/PHASE*.md",
|
|
23
23
|
"!docs/CLI-STRATEGY-2026-08.md",
|
|
24
24
|
"!docs/CLI-PILOT-2026-08-23.md",
|
|
25
|
+
"example/",
|
|
25
26
|
"src/",
|
|
26
27
|
"templates/",
|
|
27
28
|
"CHANGELOG.md",
|