@haiyangbg/buildbeat 3.1.0 → 3.2.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 +31 -10
- package/README.en.md +3 -3
- package/SKILL.md +19 -299
- package/docs/CAPABILITY-MATRIX.md +1 -1
- package/docs/README.md +6 -5
- package/docs/RELEASING.md +5 -5
- package/docs/v2/RFC-0001-product-definition.md +5 -5
- package/docs/v2/RFC-0002-domain-model.md +2 -2
- package/docs/v2/RFC-0003-workflow-policy.md +3 -3
- package/docs/v2/SPEC-0001-events-v1.md +2 -2
- package/docs/v2/guide/00-how-to-talk.en.md +61 -0
- package/docs/v2/guide/00-how-to-talk.md +2 -0
- package/docs/v2/guide/02-workflow-guide.en.md +125 -0
- package/docs/v2/guide/02-workflow-guide.md +7 -1
- package/docs/v2/guide/03-policy-guide.en.md +55 -0
- package/docs/v2/guide/03-policy-guide.md +2 -0
- package/docs/v2/guide/04-adapter-guide.en.md +66 -0
- package/docs/v2/guide/04-adapter-guide.md +2 -0
- package/docs/v2/guide/05-worker-contract.en.md +60 -0
- package/docs/v2/guide/05-worker-contract.md +2 -0
- package/docs/v2/guide/09-security-boundaries.en.md +41 -0
- package/docs/v2/guide/09-security-boundaries.md +4 -2
- package/docs/v2/guide/10-recovery.en.md +1 -1
- package/docs/v2/guide/10-recovery.md +1 -1
- package/docs/v2/guide/README.en.md +36 -0
- package/docs/v2/guide/README.md +8 -6
- package/docs/v2/skill/01-principles.md +26 -0
- package/docs/v2/skill/02-project-layout.md +31 -0
- package/docs/v2/skill/03-collaboration-rules.md +45 -0
- package/docs/v2/skill/04-rhythm-and-rituals.md +102 -0
- package/docs/v2/skill/05-red-lines.md +13 -0
- package/docs/v2/skill/06-bootstrap-and-takeover.md +84 -0
- package/docs/v2/skill/07-templates-and-lessons.md +24 -0
- package/package.json +7 -16
- package/src/v2/cli/run-config-check.js +10 -4
- package/src/v2/cli/run.js +35 -11
- package/src/v2/engine/yaml-subset.js +17 -11
- package/src/v2/presets/policies/ui-render-gate.yaml +1 -1
- package/src/v2/runtime/decisions.js +1 -1
- package/src/v2/runtime/gc.js +41 -25
- package/src/v2/runtime/metrics.js +3 -2
- package/src/v2/runtime/orchestrator.js +542 -412
- package/src/v2/workspace/workspace-manager.js +62 -3
- package/templates/v2/CLAUDE.md +1 -1
- package/templates/v2/run-config.example.yaml +2 -0
|
@@ -214,19 +214,78 @@ export function acquireLock(repoRoot, runId) {
|
|
|
214
214
|
return lockPath;
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
-
//
|
|
218
|
-
//
|
|
217
|
+
// Locks that belong to no single run: the repository-wide active-run lock,
|
|
218
|
+
// and names starting with "@" (per-work, parallel-run marker, repo-git),
|
|
219
|
+
// which no run id can contain.
|
|
220
|
+
export function isRunLockName(name) {
|
|
221
|
+
return name !== "active-run" && !name.startsWith("@");
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Run ids currently holding a lock in this repository: who a blocked
|
|
225
|
+
// `start` is queued behind.
|
|
219
226
|
export function listHeldRunLocks(repoRoot) {
|
|
220
227
|
const lockDir = join(repoRoot, ".buildbeat", "runtime", "locks");
|
|
221
228
|
if (!existsSync(lockDir)) {
|
|
222
229
|
return [];
|
|
223
230
|
}
|
|
224
231
|
return readdirSync(lockDir)
|
|
225
|
-
.filter((entry) => entry.endsWith(".lock")
|
|
232
|
+
.filter((entry) => entry.endsWith(".lock"))
|
|
226
233
|
.map((entry) => entry.slice(0, -".lock".length))
|
|
234
|
+
.filter(isRunLockName)
|
|
227
235
|
.sort();
|
|
228
236
|
}
|
|
229
237
|
|
|
238
|
+
// Parallel-run markers (@parallel.<RUN>) whose owner is alive or cannot be
|
|
239
|
+
// judged; markers of dead owners are reclaimed on the way and not returned.
|
|
240
|
+
export function liveParallelMarkers(repoRoot) {
|
|
241
|
+
const lockDir = join(repoRoot, ".buildbeat", "runtime", "locks");
|
|
242
|
+
if (!existsSync(lockDir)) {
|
|
243
|
+
return [];
|
|
244
|
+
}
|
|
245
|
+
const live = [];
|
|
246
|
+
for (const entry of readdirSync(lockDir).sort()) {
|
|
247
|
+
if (!entry.startsWith("@parallel.") || !entry.endsWith(".lock")) {
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
const lockPath = join(lockDir, entry);
|
|
251
|
+
const seen = inspectLock(lockPath);
|
|
252
|
+
if (seen.state === "dead" && reclaimStaleLock(lockPath, seen.owner)) {
|
|
253
|
+
rmSync(lockPath, { recursive: true, force: true });
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
live.push({ run: entry.slice("@parallel.".length, -".lock".length), ...seen });
|
|
257
|
+
}
|
|
258
|
+
return live;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function pause(ms) {
|
|
262
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Writes to the repository's shared git state (worktree add/remove, branch
|
|
266
|
+
// create/delete, .git/config) are serialised: with parallel runs two drivers
|
|
267
|
+
// could otherwise race on .git/config.lock or index.lock. Held for
|
|
268
|
+
// milliseconds, so a busy lock is waited for (bounded), not reported.
|
|
269
|
+
export function withRepoGitLock(repoRoot, fn, { waitMs = 10_000 } = {}) {
|
|
270
|
+
const deadline = Date.now() + waitMs;
|
|
271
|
+
for (;;) {
|
|
272
|
+
try {
|
|
273
|
+
acquireLock(repoRoot, "@repo-git");
|
|
274
|
+
break;
|
|
275
|
+
} catch (error) {
|
|
276
|
+
if (!error.lock || Date.now() >= deadline) {
|
|
277
|
+
throw error;
|
|
278
|
+
}
|
|
279
|
+
pause(100);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
try {
|
|
283
|
+
return fn();
|
|
284
|
+
} finally {
|
|
285
|
+
releaseLock(repoRoot, "@repo-git");
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
230
289
|
export function releaseLock(repoRoot, runId) {
|
|
231
290
|
rmSync(lockPathFor(repoRoot, runId), { recursive: true, force: true });
|
|
232
291
|
}
|
package/templates/v2/CLAUDE.md
CHANGED
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
本工作区的会话路由、协作规则、红线,**单点在同目录的 [`AGENTS.md`](AGENTS.md)** —— 请立即读取那份。
|
|
4
4
|
|
|
5
5
|
> 本文件只为兼容「只认 `CLAUDE.md` 这个文件名的工具」而存在,**永远保持这几行**。
|
|
6
|
-
> 往这里复制任何规则 = 两份文档必然漂移(上游 `lessons.md
|
|
6
|
+
> 往这里复制任何规则 = 两份文档必然漂移(上游 `lessons.md`「SSOT 腐烂)。
|
|
7
7
|
> 也不要改成符号链接:Windows 上 git 默认 `core.symlinks=false`,clone 出来会静默退化成一个内容是路径字符串的普通文件,装载即失效。
|