@seanyao/roll 4.702.2 → 4.702.4
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 +15 -0
- package/README.md +6 -2
- package/dist/roll.mjs +563 -190
- package/guide/en/loop.md +8 -0
- package/guide/en/project-setup.md +7 -0
- package/guide/zh/loop.md +6 -0
- package/guide/zh/project-setup.md +6 -0
- package/package.json +1 -1
package/dist/roll.mjs
CHANGED
|
@@ -2240,8 +2240,8 @@ var init_catalog_v3 = __esm({
|
|
|
2240
2240
|
// `design.*` — explicit `roll design` entry point (US-ONBOARD-NUDGE-004 / FIX-1055).
|
|
2241
2241
|
// Thin wrapper that launches the existing $roll-design skill interactively.
|
|
2242
2242
|
"design.usage": {
|
|
2243
|
-
en: 'Usage: roll design [--from-file <path> | "<requirement>"] [--agent <name>] [--verbose|--raw]\n Launch the $roll-design skill in an interactive agent conversation.\n `--from-file` binds a PRD/brief file as the design input.\n `"<requirement>"` binds a free-text design target; it cannot be combined with `--from-file`.\n `--agent` and `ROLL_DESIGN_AGENT` override only this design session; scoped roles live in ~/.roll/agents.yaml and .roll/agents.yaml.\n `--verbose`
|
|
2244
|
-
zh: '\u7528\u6CD5\uFF1Aroll design [--from-file <path> | "<requirement>"] [--agent <name>] [--verbose|--raw]\n \u5728\u4EA4\u4E92\u5F0F agent \u5BF9\u8BDD\u4E2D\u542F\u52A8 $roll-design skill\u3002\n `--from-file` \u4F1A\u628A PRD/brief \u6587\u4EF6\u7ED1\u5B9A\u4E3A\u8BBE\u8BA1\u8F93\u5165\u3002\n `"<requirement>"` \u4F1A\u7ED1\u5B9A\u81EA\u7531\u6587\u672C\u8BBE\u8BA1\u76EE\u6807\uFF1B\u4E0D\u80FD\u4E0E `--from-file` \u6DF7\u7528\u3002\n `--agent` \u4E0E `ROLL_DESIGN_AGENT` \u53EA\u8986\u76D6\u672C\u6B21 design session\uFF1Bscoped roles \u4F4D\u4E8E ~/.roll/agents.yaml \u548C .roll/agents.yaml\u3002\n `--verbose` \u663E\u793A
|
|
2243
|
+
en: 'Usage: roll design [--from-file <path> | "<requirement>"] [--agent <name>] [--verbose|--raw]\n Launch the $roll-design skill in an interactive agent conversation.\n Default output streams bounded live progress, card-created events, quiet heartbeats, and the final handoff while preserving the raw transcript.\n `--from-file` binds a PRD/brief file as the design input.\n `"<requirement>"` binds a free-text design target; it cannot be combined with `--from-file`.\n `--agent` and `ROLL_DESIGN_AGENT` override only this design session; scoped roles live in ~/.roll/agents.yaml and .roll/agents.yaml.\n `--verbose` streams lower-priority normalized activity; `--raw` streams the raw child output live.\n Unlike `roll init`, this command runs an LLM \u2014 run it only when you want to design.',
|
|
2244
|
+
zh: '\u7528\u6CD5\uFF1Aroll design [--from-file <path> | "<requirement>"] [--agent <name>] [--verbose|--raw]\n \u5728\u4EA4\u4E92\u5F0F agent \u5BF9\u8BDD\u4E2D\u542F\u52A8 $roll-design skill\u3002\n \u9ED8\u8BA4\u8F93\u51FA\u4F1A\u5B9E\u65F6\u663E\u793A\u6709\u754C\u8FDB\u5C55\u3001\u5EFA\u5361\u4E8B\u4EF6\u3001\u9759\u9ED8\u5FC3\u8DF3\u548C\u6700\u7EC8\u4EA4\u4ED8\uFF0C\u540C\u65F6\u4FDD\u7559\u5B8C\u6574\u539F\u59CB\u8BB0\u5F55\u3002\n `--from-file` \u4F1A\u628A PRD/brief \u6587\u4EF6\u7ED1\u5B9A\u4E3A\u8BBE\u8BA1\u8F93\u5165\u3002\n `"<requirement>"` \u4F1A\u7ED1\u5B9A\u81EA\u7531\u6587\u672C\u8BBE\u8BA1\u76EE\u6807\uFF1B\u4E0D\u80FD\u4E0E `--from-file` \u6DF7\u7528\u3002\n `--agent` \u4E0E `ROLL_DESIGN_AGENT` \u53EA\u8986\u76D6\u672C\u6B21 design session\uFF1Bscoped roles \u4F4D\u4E8E ~/.roll/agents.yaml \u548C .roll/agents.yaml\u3002\n `--verbose` \u5B9E\u65F6\u663E\u793A\u8F83\u4F4E\u4F18\u5148\u7EA7\u7684\u89C4\u8303\u5316\u6D3B\u52A8\uFF1B`--raw` \u5B9E\u65F6\u8F93\u51FA\u5B50\u8FDB\u7A0B\u539F\u59CB\u6D41\u3002\n \u4E0E `roll init` \u4E0D\u540C\uFF0C\u672C\u547D\u4EE4\u4F1A\u8FD0\u884C LLM\u2014\u2014\u53EA\u5728\u9700\u8981\u8BBE\u8BA1\u65F6\u6267\u884C\u3002'
|
|
2245
2245
|
},
|
|
2246
2246
|
"design.not_roll_project": {
|
|
2247
2247
|
en: "This directory is not a Roll project (no .roll/). Run `roll init` first.",
|
|
@@ -12475,6 +12475,12 @@ function signalLabel(ev) {
|
|
|
12475
12475
|
return `pair ${clean2(ev.peer)} ${ev.cause}`;
|
|
12476
12476
|
case "pair:excluded":
|
|
12477
12477
|
return `pair ${clean2(ev.agent)} excluded ${ev.cause} (${ev.failures})`;
|
|
12478
|
+
case "agent:retry":
|
|
12479
|
+
return `retry ${clean2(ev.fromAgent)} \u2192 ${clean2(ev.toAgent)} (${clean2(ev.reason)})`;
|
|
12480
|
+
case "goal:gate_tripped":
|
|
12481
|
+
return `paused ${clean2(ev.reason)} (${ev.gate})`;
|
|
12482
|
+
case "goal:state":
|
|
12483
|
+
return `goal ${clean2(ev.to)} ${clean2(ev.reason)}`;
|
|
12478
12484
|
default:
|
|
12479
12485
|
return void 0;
|
|
12480
12486
|
}
|
|
@@ -12486,6 +12492,20 @@ function summarizeWatchEvents(lines3, durableLookup, nowMs) {
|
|
|
12486
12492
|
const summary = { tcrCount: 0, hasEnd: false };
|
|
12487
12493
|
const events = [];
|
|
12488
12494
|
let seen = false;
|
|
12495
|
+
const resetCycleScope = (cycleId) => {
|
|
12496
|
+
if (summary.cycleId === cycleId)
|
|
12497
|
+
return;
|
|
12498
|
+
summary.cycleId = cycleId;
|
|
12499
|
+
summary.storyId = void 0;
|
|
12500
|
+
summary.agent = void 0;
|
|
12501
|
+
summary.phase = void 0;
|
|
12502
|
+
summary.tcrCount = 0;
|
|
12503
|
+
summary.outcome = void 0;
|
|
12504
|
+
summary.hasEnd = false;
|
|
12505
|
+
summary.acceptedScore = void 0;
|
|
12506
|
+
summary.attest = void 0;
|
|
12507
|
+
summary.lastPr = void 0;
|
|
12508
|
+
};
|
|
12489
12509
|
for (const line of lines3) {
|
|
12490
12510
|
const ev = parseEventLine(line);
|
|
12491
12511
|
if (ev === null)
|
|
@@ -12493,26 +12513,26 @@ function summarizeWatchEvents(lines3, durableLookup, nowMs) {
|
|
|
12493
12513
|
events.push(ev);
|
|
12494
12514
|
seen = true;
|
|
12495
12515
|
if (ev.type === "cycle:start") {
|
|
12496
|
-
|
|
12516
|
+
resetCycleScope(ev.cycleId);
|
|
12497
12517
|
summary.storyId = ev.storyId;
|
|
12498
12518
|
summary.agent = ev.agent;
|
|
12499
|
-
summary.phase = void 0;
|
|
12500
|
-
summary.tcrCount = 0;
|
|
12501
|
-
summary.outcome = void 0;
|
|
12502
|
-
summary.hasEnd = false;
|
|
12503
|
-
summary.acceptedScore = void 0;
|
|
12504
|
-
summary.attest = void 0;
|
|
12505
|
-
summary.lastPr = void 0;
|
|
12506
12519
|
} else if (ev.type === "cycle:phase") {
|
|
12507
|
-
|
|
12520
|
+
resetCycleScope(ev.cycleId);
|
|
12508
12521
|
summary.phase = ev.phase;
|
|
12509
12522
|
} else if (ev.type === "cycle:tcr") {
|
|
12510
|
-
|
|
12523
|
+
resetCycleScope(ev.cycleId);
|
|
12511
12524
|
summary.tcrCount += 1;
|
|
12512
|
-
} else if (ev.type === "cycle:end"
|
|
12513
|
-
|
|
12525
|
+
} else if (ev.type === "cycle:end") {
|
|
12526
|
+
resetCycleScope(ev.cycleId);
|
|
12527
|
+
summary.outcome = ev.outcome;
|
|
12528
|
+
summary.hasEnd = true;
|
|
12529
|
+
} else if (ev.type === "cycle:terminal") {
|
|
12530
|
+
resetCycleScope(ev.cycleId);
|
|
12531
|
+
summary.storyId = ev.storyId;
|
|
12532
|
+
summary.agent = ev.agent;
|
|
12514
12533
|
summary.outcome = ev.outcome;
|
|
12515
12534
|
summary.hasEnd = true;
|
|
12535
|
+
summary.tcrCount = ev.tcr.present ? ev.tcr.value : 0;
|
|
12516
12536
|
}
|
|
12517
12537
|
if (ev.type === "pair:score") {
|
|
12518
12538
|
summary.acceptedScore = { peer: ev.peer, score: ev.score, verdict: ev.verdict };
|
|
@@ -12584,7 +12604,7 @@ function renderWatchStatusSummary(summary, nowMs) {
|
|
|
12584
12604
|
const story = summary.storyId !== void 0 && summary.storyId !== "" ? summary.storyId : "story unknown";
|
|
12585
12605
|
const agent = summary.agent !== void 0 && summary.agent !== "" ? summary.agent : "agent unknown";
|
|
12586
12606
|
const phase = summary.phase !== void 0 ? `phase ${summary.phase}` : "phase unknown";
|
|
12587
|
-
const classification = summary.classification !== void 0 ? summary.classification : "active";
|
|
12607
|
+
const classification = summary.classification !== void 0 ? summary.classification : summary.hasEnd ? "ended" : "active";
|
|
12588
12608
|
const tcr = `${summary.tcrCount} TCR`;
|
|
12589
12609
|
const parts = [`status ${phase}`, classification, quietText(summary, nowMs), story, agent, cycle];
|
|
12590
12610
|
if (summary.microStep !== void 0) {
|
|
@@ -12656,11 +12676,18 @@ function previousTransitionLine(previous) {
|
|
|
12656
12676
|
return ` previous: ${parts.join(" \xB7 ")}`;
|
|
12657
12677
|
}
|
|
12658
12678
|
function nextTransitionLine(current, ctx) {
|
|
12679
|
+
if (current.storyId === void 0 || current.storyId === "") {
|
|
12680
|
+
const outcome = current.hasEnd ? current.outcome ?? "unknown" : "no active story";
|
|
12681
|
+
return ` next: no runnable work \xB7 ${outcome}`;
|
|
12682
|
+
}
|
|
12659
12683
|
const story = current.storyId !== void 0 && current.storyId !== "" ? current.storyId : "story unknown";
|
|
12660
12684
|
const brief = current.storyId !== void 0 && current.storyId !== "" ? ctx?.storyBrief?.(current.storyId) ?? "brief unavailable" : "brief unavailable";
|
|
12661
12685
|
return ` next: ${story} \xB7 ${brief}`;
|
|
12662
12686
|
}
|
|
12663
12687
|
function builderTransitionLine(current, ctx) {
|
|
12688
|
+
if (current.storyId === void 0 || current.storyId === "") {
|
|
12689
|
+
return " builder: none \xB7 no story/agent selected";
|
|
12690
|
+
}
|
|
12664
12691
|
const route = current.storyId !== void 0 && current.storyId !== "" ? ctx?.routeReason?.(current.storyId) : void 0;
|
|
12665
12692
|
if (route !== void 0) {
|
|
12666
12693
|
return ` builder: ${route.agent} \xB7 selected by ${route.reason}`;
|
|
@@ -18793,16 +18820,16 @@ async function crontabRead() {
|
|
|
18793
18820
|
}
|
|
18794
18821
|
}
|
|
18795
18822
|
async function crontabWrite(text2) {
|
|
18796
|
-
return new Promise((
|
|
18823
|
+
return new Promise((resolve12, reject) => {
|
|
18797
18824
|
const child = execFile4("crontab", ["-"], (err16) => {
|
|
18798
18825
|
if (err16 === null) {
|
|
18799
|
-
|
|
18826
|
+
resolve12(0);
|
|
18800
18827
|
} else if (typeof err16.code === "number") {
|
|
18801
|
-
|
|
18828
|
+
resolve12(err16.code);
|
|
18802
18829
|
} else if (err16.code === "ENOENT") {
|
|
18803
18830
|
reject(err16);
|
|
18804
18831
|
} else {
|
|
18805
|
-
|
|
18832
|
+
resolve12(1);
|
|
18806
18833
|
}
|
|
18807
18834
|
});
|
|
18808
18835
|
child.stdin?.end(text2);
|
|
@@ -20846,14 +20873,14 @@ var init_mcp = __esm({
|
|
|
20846
20873
|
child.on("exit", () => this.rejectAll(new Error("MCP server exited")));
|
|
20847
20874
|
}
|
|
20848
20875
|
static async open(child) {
|
|
20849
|
-
await new Promise((
|
|
20876
|
+
await new Promise((resolve12, reject) => {
|
|
20850
20877
|
const onError = (cause) => {
|
|
20851
20878
|
child.off("spawn", onSpawn);
|
|
20852
20879
|
reject(cause);
|
|
20853
20880
|
};
|
|
20854
20881
|
const onSpawn = () => {
|
|
20855
20882
|
child.off("error", onError);
|
|
20856
|
-
|
|
20883
|
+
resolve12();
|
|
20857
20884
|
};
|
|
20858
20885
|
child.once("error", onError);
|
|
20859
20886
|
child.once("spawn", onSpawn);
|
|
@@ -20882,8 +20909,8 @@ var init_mcp = __esm({
|
|
|
20882
20909
|
const id = this.nextId;
|
|
20883
20910
|
this.nextId += 1;
|
|
20884
20911
|
const message = { jsonrpc: "2.0", id, method, params };
|
|
20885
|
-
return new Promise((
|
|
20886
|
-
this.pending.set(id, { resolve:
|
|
20912
|
+
return new Promise((resolve12, reject) => {
|
|
20913
|
+
this.pending.set(id, { resolve: resolve12, reject });
|
|
20887
20914
|
this.write(message);
|
|
20888
20915
|
});
|
|
20889
20916
|
}
|
|
@@ -20978,7 +21005,7 @@ async function requestWithRedirects(url, input, deps, timeoutMs, redirects, star
|
|
|
20978
21005
|
return response;
|
|
20979
21006
|
}
|
|
20980
21007
|
function requestOnce(url, input, deps, timeoutMs, startedAt) {
|
|
20981
|
-
return new Promise((
|
|
21008
|
+
return new Promise((resolve12, reject) => {
|
|
20982
21009
|
const proxy = proxyFor(url);
|
|
20983
21010
|
const viaProxy = proxy !== void 0;
|
|
20984
21011
|
const requestUrl = viaProxy ? proxy : url;
|
|
@@ -21000,7 +21027,7 @@ function requestOnce(url, input, deps, timeoutMs, startedAt) {
|
|
|
21000
21027
|
});
|
|
21001
21028
|
res.on("end", () => {
|
|
21002
21029
|
clearTimeout(timer);
|
|
21003
|
-
|
|
21030
|
+
resolve12({
|
|
21004
21031
|
statusCode: res.statusCode ?? 0,
|
|
21005
21032
|
headers: normalizeHeaders(res.headers),
|
|
21006
21033
|
body: deps.redact(Buffer.concat(chunks).toString("utf8")),
|
|
@@ -21054,7 +21081,7 @@ function isTimeout(cause) {
|
|
|
21054
21081
|
function delay(ms) {
|
|
21055
21082
|
if (ms <= 0)
|
|
21056
21083
|
return Promise.resolve();
|
|
21057
|
-
return new Promise((
|
|
21084
|
+
return new Promise((resolve12) => setTimeout(resolve12, ms));
|
|
21058
21085
|
}
|
|
21059
21086
|
function failure5(invocation, startedAt, endedAt, code, message, retryable, detail, attempt) {
|
|
21060
21087
|
return {
|
|
@@ -145685,7 +145712,7 @@ ${lanes.join("\n")}
|
|
|
145685
145712
|
}
|
|
145686
145713
|
}
|
|
145687
145714
|
function createImportCallExpressionAMD(arg, containsLexicalThis) {
|
|
145688
|
-
const
|
|
145715
|
+
const resolve12 = factory2.createUniqueName("resolve");
|
|
145689
145716
|
const reject = factory2.createUniqueName("reject");
|
|
145690
145717
|
const parameters = [
|
|
145691
145718
|
factory2.createParameterDeclaration(
|
|
@@ -145694,7 +145721,7 @@ ${lanes.join("\n")}
|
|
|
145694
145721
|
/*dotDotDotToken*/
|
|
145695
145722
|
void 0,
|
|
145696
145723
|
/*name*/
|
|
145697
|
-
|
|
145724
|
+
resolve12
|
|
145698
145725
|
),
|
|
145699
145726
|
factory2.createParameterDeclaration(
|
|
145700
145727
|
/*modifiers*/
|
|
@@ -145711,7 +145738,7 @@ ${lanes.join("\n")}
|
|
|
145711
145738
|
factory2.createIdentifier("require"),
|
|
145712
145739
|
/*typeArguments*/
|
|
145713
145740
|
void 0,
|
|
145714
|
-
[factory2.createArrayLiteralExpression([arg || factory2.createOmittedExpression()]),
|
|
145741
|
+
[factory2.createArrayLiteralExpression([arg || factory2.createOmittedExpression()]), resolve12, reject]
|
|
145715
145742
|
)
|
|
145716
145743
|
)
|
|
145717
145744
|
]);
|
|
@@ -232642,8 +232669,8 @@ Additional information: BADCLIENT: Bad error code, ${badCode} not found in range
|
|
|
232642
232669
|
installPackage(options) {
|
|
232643
232670
|
this.packageInstallId++;
|
|
232644
232671
|
const request = { kind: "installPackage", ...options, id: this.packageInstallId };
|
|
232645
|
-
const promise = new Promise((
|
|
232646
|
-
(this.packageInstalledPromise ?? (this.packageInstalledPromise = /* @__PURE__ */ new Map())).set(this.packageInstallId, { resolve:
|
|
232672
|
+
const promise = new Promise((resolve12, reject) => {
|
|
232673
|
+
(this.packageInstalledPromise ?? (this.packageInstalledPromise = /* @__PURE__ */ new Map())).set(this.packageInstallId, { resolve: resolve12, reject });
|
|
232647
232674
|
});
|
|
232648
232675
|
this.installer.send(request);
|
|
232649
232676
|
return promise;
|
|
@@ -232936,10 +232963,10 @@ __export(structure_scan_exports, {
|
|
|
232936
232963
|
});
|
|
232937
232964
|
import { createHash as createHash5 } from "node:crypto";
|
|
232938
232965
|
import { existsSync as existsSync63, readFileSync as readFileSync59 } from "node:fs";
|
|
232939
|
-
import { basename as basename13, dirname as dirname32, extname, join as join65, relative as relative5, resolve as
|
|
232966
|
+
import { basename as basename13, dirname as dirname32, extname, join as join65, relative as relative5, resolve as resolve7, sep as sep4 } from "node:path";
|
|
232940
232967
|
function buildStaticProjectGraph(input) {
|
|
232941
|
-
const root =
|
|
232942
|
-
const tsconfigPaths = input.tsconfigPath ? [
|
|
232968
|
+
const root = resolve7(input.root);
|
|
232969
|
+
const tsconfigPaths = input.tsconfigPath ? [resolve7(root, input.tsconfigPath)] : findTsconfigs(root);
|
|
232943
232970
|
if (tsconfigPaths.length === 0) {
|
|
232944
232971
|
return emptyGraph(root, "No tsconfig.json found for Dream structure scan");
|
|
232945
232972
|
}
|
|
@@ -233086,7 +233113,7 @@ function createLanguageServiceHost(fileNames, options) {
|
|
|
233086
233113
|
};
|
|
233087
233114
|
}
|
|
233088
233115
|
function normalizePath(root, path) {
|
|
233089
|
-
return relative5(root,
|
|
233116
|
+
return relative5(root, resolve7(path)).split(sep4).join("/");
|
|
233090
233117
|
}
|
|
233091
233118
|
function isExcluded(root, path) {
|
|
233092
233119
|
const rel = normalizePath(root, path);
|
|
@@ -233200,7 +233227,7 @@ function importEdges(root, sourceFile) {
|
|
|
233200
233227
|
function resolveModulePath(root, containingFile, specifier) {
|
|
233201
233228
|
if (!specifier.startsWith("."))
|
|
233202
233229
|
return void 0;
|
|
233203
|
-
const base =
|
|
233230
|
+
const base = resolve7(dirname32(containingFile), specifier);
|
|
233204
233231
|
for (const suffix of [".ts", ".tsx", ".mts", ".cts", "/index.ts"]) {
|
|
233205
233232
|
const candidate = `${base}${suffix}`;
|
|
233206
233233
|
if (existsSync63(candidate))
|
|
@@ -233623,7 +233650,7 @@ __export(showcase_exports, {
|
|
|
233623
233650
|
resetSandbox: () => resetSandbox,
|
|
233624
233651
|
showcaseCommand: () => showcaseCommand
|
|
233625
233652
|
});
|
|
233626
|
-
import { spawnSync as
|
|
233653
|
+
import { spawnSync as spawnSync15 } from "node:child_process";
|
|
233627
233654
|
import { cpSync as cpSync2, existsSync as existsSync105, mkdirSync as mkdirSync51, mkdtempSync as mkdtempSync8, readdirSync as readdirSync41, readFileSync as readFileSync99, rmSync as rmSync18, statSync as statSync35, writeFileSync as writeFileSync54 } from "node:fs";
|
|
233628
233655
|
import { tmpdir as tmpdir10 } from "node:os";
|
|
233629
233656
|
import { dirname as dirname49, join as join109 } from "node:path";
|
|
@@ -233695,7 +233722,7 @@ function runRoll(sandbox, rollHome4, args, opts = {}) {
|
|
|
233695
233722
|
}
|
|
233696
233723
|
const bin = rollBin3();
|
|
233697
233724
|
const [cmd, cmdArgs] = bin === "roll" ? [bin, args] : [process.execPath, [bin, ...args]];
|
|
233698
|
-
const r =
|
|
233725
|
+
const r = spawnSync15(cmd, cmdArgs, {
|
|
233699
233726
|
cwd: sandbox,
|
|
233700
233727
|
env,
|
|
233701
233728
|
encoding: "utf8",
|
|
@@ -234138,7 +234165,7 @@ function networkNeeds(command, args) {
|
|
|
234138
234165
|
}
|
|
234139
234166
|
}
|
|
234140
234167
|
function tcpConnect(host, port, timeoutMs) {
|
|
234141
|
-
return new Promise((
|
|
234168
|
+
return new Promise((resolve12, reject) => {
|
|
234142
234169
|
const socket = createConnection({ host, port });
|
|
234143
234170
|
let settled = false;
|
|
234144
234171
|
const done = (err16) => {
|
|
@@ -234150,7 +234177,7 @@ function tcpConnect(host, port, timeoutMs) {
|
|
|
234150
234177
|
if (err16)
|
|
234151
234178
|
reject(err16);
|
|
234152
234179
|
else
|
|
234153
|
-
|
|
234180
|
+
resolve12();
|
|
234154
234181
|
};
|
|
234155
234182
|
socket.setTimeout(timeoutMs, () => done(new Error("tcp timeout")));
|
|
234156
234183
|
socket.once("connect", () => done());
|
|
@@ -234162,11 +234189,11 @@ async function networkReachable(probes = {}) {
|
|
|
234162
234189
|
host: PROBE_HOST,
|
|
234163
234190
|
port: PROBE_PORT
|
|
234164
234191
|
};
|
|
234165
|
-
const
|
|
234192
|
+
const resolve12 = probes.resolve ?? ((h) => lookup(h));
|
|
234166
234193
|
const tcpProbe2 = probes.tcpProbe ?? (() => tcpConnect(target.host, target.port, TCP_TIMEOUT_MS));
|
|
234167
234194
|
try {
|
|
234168
234195
|
await Promise.race([
|
|
234169
|
-
|
|
234196
|
+
resolve12(target.host),
|
|
234170
234197
|
new Promise((_, rej) => {
|
|
234171
234198
|
const timer = setTimeout(() => rej(new Error("dns timeout")), DNS_TIMEOUT_MS);
|
|
234172
234199
|
if (typeof timer === "object")
|
|
@@ -234473,7 +234500,7 @@ init_dist2();
|
|
|
234473
234500
|
import { spawn as spawn2 } from "node:child_process";
|
|
234474
234501
|
import { existsSync as existsSync15, readFileSync as readFileSync12, realpathSync as realpathSync2, unlinkSync, writeFileSync as writeFileSync6 } from "node:fs";
|
|
234475
234502
|
import { homedir as homedir4 } from "node:os";
|
|
234476
|
-
import { join as join18 } from "node:path";
|
|
234503
|
+
import { join as join18, resolve as resolve5 } from "node:path";
|
|
234477
234504
|
var liveAgents = /* @__PURE__ */ new Set();
|
|
234478
234505
|
function killLiveAgents(signal = "SIGKILL") {
|
|
234479
234506
|
let n = 0;
|
|
@@ -234799,12 +234826,28 @@ function evidenceFrameEnv(runDir) {
|
|
|
234799
234826
|
};
|
|
234800
234827
|
}
|
|
234801
234828
|
var INHERITED_GIT_ENV_KEYS = ["GIT_DIR", "GIT_WORK_TREE", "GIT_COMMON_DIR", "GIT_INDEX_FILE"];
|
|
234829
|
+
function worktreeGitEnv(cwd) {
|
|
234830
|
+
const gitPath = join18(cwd, ".git");
|
|
234831
|
+
if (!existsSync15(gitPath))
|
|
234832
|
+
return {};
|
|
234833
|
+
try {
|
|
234834
|
+
const text2 = readFileSync12(gitPath, "utf8");
|
|
234835
|
+
const match = /^gitdir:\s*(.+)\s*$/m.exec(text2);
|
|
234836
|
+
if (match?.[1] !== void 0 && match[1].trim() !== "") {
|
|
234837
|
+
return { GIT_DIR: resolve5(cwd, match[1].trim()), GIT_WORK_TREE: cwd };
|
|
234838
|
+
}
|
|
234839
|
+
} catch {
|
|
234840
|
+
return { GIT_DIR: gitPath, GIT_WORK_TREE: cwd };
|
|
234841
|
+
}
|
|
234842
|
+
return {};
|
|
234843
|
+
}
|
|
234802
234844
|
function childEnv(opts) {
|
|
234803
234845
|
const env = { ...opts.env ?? process.env };
|
|
234804
234846
|
for (const key of INHERITED_GIT_ENV_KEYS)
|
|
234805
234847
|
delete env[key];
|
|
234806
234848
|
env.PWD = opts.cwd;
|
|
234807
234849
|
delete env.OLDPWD;
|
|
234850
|
+
Object.assign(env, worktreeGitEnv(opts.cwd));
|
|
234808
234851
|
return opts.runDir !== void 0 && opts.runDir !== "" ? { ...env, ...evidenceFrameEnv(opts.runDir) } : env;
|
|
234809
234852
|
}
|
|
234810
234853
|
function withAgentProfileEnv(agent, opts) {
|
|
@@ -234820,7 +234863,7 @@ function withAgentProfileEnv(agent, opts) {
|
|
|
234820
234863
|
function spawnAndWait(bin, args, opts, pty = false) {
|
|
234821
234864
|
process.stderr.write(`[runner] spawn ${bin} argv=${JSON.stringify(args.map((a) => a.length > 80 ? `${a.slice(0, 77)}...` : a))}
|
|
234822
234865
|
`);
|
|
234823
|
-
return new Promise((
|
|
234866
|
+
return new Promise((resolve12) => {
|
|
234824
234867
|
const child = spawn2(bin, args, {
|
|
234825
234868
|
cwd: opts.cwd,
|
|
234826
234869
|
env: childEnv(opts),
|
|
@@ -234863,7 +234906,7 @@ function spawnAndWait(bin, args, opts, pty = false) {
|
|
|
234863
234906
|
opts.cleanup?.();
|
|
234864
234907
|
} catch {
|
|
234865
234908
|
}
|
|
234866
|
-
|
|
234909
|
+
resolve12(result);
|
|
234867
234910
|
};
|
|
234868
234911
|
child.on("error", (e) => {
|
|
234869
234912
|
settle({ stdout, stderr: `${stderr}${String(e)}
|
|
@@ -234890,13 +234933,13 @@ function realDeps() {
|
|
|
234890
234933
|
sharedRoot: () => process.env["ROLL_SHARED_ROOT"] || join19(homedir5(), ".shared", "roll"),
|
|
234891
234934
|
launchdDir: () => join19(homedir5(), "Library", "LaunchAgents"),
|
|
234892
234935
|
scheduler: createScheduler(process.platform, { uid: process.getuid?.() ?? 501 }),
|
|
234893
|
-
execRunner: (runner) => new Promise((
|
|
234936
|
+
execRunner: (runner) => new Promise((resolve12) => {
|
|
234894
234937
|
const child = spawn3("bash", [runner], {
|
|
234895
234938
|
stdio: "inherit",
|
|
234896
234939
|
env: { ...process.env, ROLL_LOOP_FORCE: "1" }
|
|
234897
234940
|
});
|
|
234898
|
-
child.on("exit", (code) =>
|
|
234899
|
-
child.on("error", () =>
|
|
234941
|
+
child.on("exit", (code) => resolve12(code ?? 1));
|
|
234942
|
+
child.on("error", () => resolve12(1));
|
|
234900
234943
|
}),
|
|
234901
234944
|
hasTmux: () => {
|
|
234902
234945
|
try {
|
|
@@ -234907,7 +234950,7 @@ function realDeps() {
|
|
|
234907
234950
|
},
|
|
234908
234951
|
// The `loop now` inline observation: tail live.log while the cycle holds
|
|
234909
234952
|
// the inner lock; Ctrl-C stops the TAIL only (the cycle lives in tmux).
|
|
234910
|
-
observe: (rt) => new Promise((
|
|
234953
|
+
observe: (rt) => new Promise((resolve12) => {
|
|
234911
234954
|
const lock = join19(rt, "inner.lock");
|
|
234912
234955
|
const tail3 = spawn3("tail", ["-n", "+1", "-F", join19(rt, "live.log")], { stdio: "inherit" });
|
|
234913
234956
|
let sawLock = false;
|
|
@@ -234918,7 +234961,7 @@ function realDeps() {
|
|
|
234918
234961
|
} catch {
|
|
234919
234962
|
}
|
|
234920
234963
|
process.removeListener("SIGINT", finish);
|
|
234921
|
-
|
|
234964
|
+
resolve12();
|
|
234922
234965
|
};
|
|
234923
234966
|
const timer = setInterval(() => {
|
|
234924
234967
|
if (existsSync16(lock))
|
|
@@ -249779,13 +249822,13 @@ function followSupervisorCollabStream(projectPath3, noColor2) {
|
|
|
249779
249822
|
const tickLimit = envOptionalPositiveInt("ROLL_SUPERVISOR_COLLAB_WATCH_TICKS");
|
|
249780
249823
|
let renderedCycles = 0;
|
|
249781
249824
|
let ticks = 0;
|
|
249782
|
-
return new Promise((
|
|
249825
|
+
return new Promise((resolve12) => {
|
|
249783
249826
|
let timer;
|
|
249784
249827
|
const stop = (code) => {
|
|
249785
249828
|
if (timer !== void 0)
|
|
249786
249829
|
clearInterval(timer);
|
|
249787
249830
|
process.removeListener("SIGINT", onSigint);
|
|
249788
|
-
|
|
249831
|
+
resolve12(code);
|
|
249789
249832
|
};
|
|
249790
249833
|
const onSigint = () => stop(130);
|
|
249791
249834
|
const tick = () => {
|
|
@@ -249876,7 +249919,7 @@ function unknownSupervisorLiveFlag(args) {
|
|
|
249876
249919
|
function followSupervisorLiveBoard(projectPath3, intervalMs) {
|
|
249877
249920
|
const tickLimit = envOptionalPositiveInt("ROLL_SUPERVISOR_LIVE_WATCH_TICKS");
|
|
249878
249921
|
let ticks = 0;
|
|
249879
|
-
return new Promise((
|
|
249922
|
+
return new Promise((resolve12) => {
|
|
249880
249923
|
let timer;
|
|
249881
249924
|
let stopped = false;
|
|
249882
249925
|
const stop = (code) => {
|
|
@@ -249887,7 +249930,7 @@ function followSupervisorLiveBoard(projectPath3, intervalMs) {
|
|
|
249887
249930
|
clearInterval(timer);
|
|
249888
249931
|
process.removeListener("SIGINT", onSigint);
|
|
249889
249932
|
process.stdout.write("\x1B[?25h");
|
|
249890
|
-
|
|
249933
|
+
resolve12(code);
|
|
249891
249934
|
};
|
|
249892
249935
|
const onSigint = () => stop(130);
|
|
249893
249936
|
const tick = () => {
|
|
@@ -251053,7 +251096,7 @@ function spawnPeerReviewAgent(input) {
|
|
|
251053
251096
|
const cmd = textAgentArgv(input.agent, input.prompt);
|
|
251054
251097
|
if (cmd === null)
|
|
251055
251098
|
return Promise.resolve({ status: "error", reason: "unsupported_reviewer", stdout: "" });
|
|
251056
|
-
return new Promise((
|
|
251099
|
+
return new Promise((resolve12) => {
|
|
251057
251100
|
let stdout = "";
|
|
251058
251101
|
let stderr = "";
|
|
251059
251102
|
let timedOut = false;
|
|
@@ -251071,7 +251114,7 @@ function spawnPeerReviewAgent(input) {
|
|
|
251071
251114
|
settled = true;
|
|
251072
251115
|
if (timer !== void 0)
|
|
251073
251116
|
clearTimeout(timer);
|
|
251074
|
-
|
|
251117
|
+
resolve12(result);
|
|
251075
251118
|
};
|
|
251076
251119
|
timer = setTimeout(() => {
|
|
251077
251120
|
timedOut = true;
|
|
@@ -251681,7 +251724,7 @@ function realDeps5() {
|
|
|
251681
251724
|
startTmux: startGoTmux,
|
|
251682
251725
|
followFeed: followGoLiveFeed,
|
|
251683
251726
|
runOnce: realRunOnce,
|
|
251684
|
-
sleep: (ms) => new Promise((
|
|
251727
|
+
sleep: (ms) => new Promise((resolve12) => setTimeout(resolve12, ms)),
|
|
251685
251728
|
externalTools: guideExternalToolSetup,
|
|
251686
251729
|
preinstallChromium: () => {
|
|
251687
251730
|
silentPreinstallChromium();
|
|
@@ -251726,6 +251769,59 @@ function eventsPath(projectPath3) {
|
|
|
251726
251769
|
function runsPath2(projectPath3) {
|
|
251727
251770
|
return join55(runtimeDir5(projectPath3), "runs.jsonl");
|
|
251728
251771
|
}
|
|
251772
|
+
function parsePorcelainPath(line) {
|
|
251773
|
+
const raw = line.length > 3 ? line.slice(3).trim() : line.trim();
|
|
251774
|
+
const target = raw.includes(" -> ") ? raw.split(" -> ").at(-1) ?? raw : raw;
|
|
251775
|
+
return target.replace(/^"|"$/g, "").replace(/\/$/, "");
|
|
251776
|
+
}
|
|
251777
|
+
function gitDirtyPaths(projectPath3) {
|
|
251778
|
+
const result = spawnSync8("git", ["status", "--porcelain", "--untracked-files=all"], {
|
|
251779
|
+
cwd: projectPath3,
|
|
251780
|
+
encoding: "utf8",
|
|
251781
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
251782
|
+
});
|
|
251783
|
+
if (result.status !== 0)
|
|
251784
|
+
return [];
|
|
251785
|
+
return String(result.stdout ?? "").split("\n").map((line) => line.trimEnd()).filter((line) => line.trim() !== "").map(parsePorcelainPath).filter((path) => path !== ".roll/loop" && !path.startsWith(".roll/loop/")).slice(0, 50);
|
|
251786
|
+
}
|
|
251787
|
+
function isBootstrapArtifactPath(path) {
|
|
251788
|
+
if (path === "AGENTS.md" || path === "CLAUDE.md" || path === ".cursor-rules" || path === "project_rules.md")
|
|
251789
|
+
return true;
|
|
251790
|
+
if (path === ".roll" || path.startsWith(".roll/"))
|
|
251791
|
+
return true;
|
|
251792
|
+
if (path === ".claude" || path.startsWith(".claude/"))
|
|
251793
|
+
return true;
|
|
251794
|
+
return false;
|
|
251795
|
+
}
|
|
251796
|
+
function classifyBootstrapArtifacts(paths) {
|
|
251797
|
+
const files = paths.filter((path) => path.trim() !== "");
|
|
251798
|
+
if (files.length === 0)
|
|
251799
|
+
return { kind: "none", files: [] };
|
|
251800
|
+
return files.every(isBootstrapArtifactPath) ? { kind: "bootstrap_only", files } : { kind: "mixed", files };
|
|
251801
|
+
}
|
|
251802
|
+
function bootstrapArtifactsMessage(files) {
|
|
251803
|
+
const shown = files.slice(0, 12).join(", ");
|
|
251804
|
+
const more = files.length > 12 ? `, ... +${files.length - 12} more` : "";
|
|
251805
|
+
return [
|
|
251806
|
+
"roll loop go: bootstrap_artifacts_unconfirmed",
|
|
251807
|
+
` files: ${shown}${more}`,
|
|
251808
|
+
" These files define project conventions/backlog metadata. Confirm their ownership before running builders:",
|
|
251809
|
+
" - commit them to the product repo if they are product truth",
|
|
251810
|
+
" - commit private Roll metadata inside .roll/roll-meta when applicable",
|
|
251811
|
+
" - ignore/externalize them by project policy",
|
|
251812
|
+
" - or clean them up and re-run init/design",
|
|
251813
|
+
" Then rerun: roll loop go",
|
|
251814
|
+
"",
|
|
251815
|
+
"roll loop go: bootstrap_artifacts_unconfirmed",
|
|
251816
|
+
" \u8FD9\u4E9B\u6587\u4EF6\u5B9A\u4E49\u9879\u76EE\u7EA6\u5B9A/backlog \u5143\u6570\u636E\u3002\u5148\u786E\u8BA4\u5F52\u5C5E\uFF0C\u518D\u542F\u52A8 builder\uFF1A",
|
|
251817
|
+
" - \u5C5E\u4E8E\u4EA7\u54C1\u4E8B\u5B9E\u5C31\u63D0\u4EA4\u5230\u4EA7\u54C1\u4ED3",
|
|
251818
|
+
" - \u5C5E\u4E8E\u79C1\u6709 Roll \u5143\u6570\u636E\u5C31\u63D0\u4EA4\u5230 .roll/roll-meta",
|
|
251819
|
+
" - \u6309\u9879\u76EE\u7EA6\u5B9A ignore/\u5916\u7F6E",
|
|
251820
|
+
" - \u6216\u6E05\u7406\u540E\u91CD\u8DD1 init/design",
|
|
251821
|
+
" \u7136\u540E\u518D\u8FD0\u884C\uFF1Aroll loop go",
|
|
251822
|
+
""
|
|
251823
|
+
].join("\n");
|
|
251824
|
+
}
|
|
251729
251825
|
function parseOptions(args) {
|
|
251730
251826
|
let scope = { kind: "all" };
|
|
251731
251827
|
let maxCycles;
|
|
@@ -251958,7 +252054,7 @@ function startGoTmux(input) {
|
|
|
251958
252054
|
}
|
|
251959
252055
|
}
|
|
251960
252056
|
function followGoLiveFeed(projectPath3, rollBin4) {
|
|
251961
|
-
return new Promise((
|
|
252057
|
+
return new Promise((resolve12) => {
|
|
251962
252058
|
const cmd = rollBin4.endsWith(".js") || rollBin4.endsWith(".mjs") ? process.execPath : rollBin4;
|
|
251963
252059
|
const args = rollBin4.endsWith(".js") || rollBin4.endsWith(".mjs") ? [rollBin4, "loop", "watch", "--since", "all"] : ["loop", "watch", "--since", "all"];
|
|
251964
252060
|
const watch = spawn7(cmd, args, { cwd: projectPath3, stdio: ["ignore", "inherit", "inherit"] });
|
|
@@ -251968,7 +252064,7 @@ function followGoLiveFeed(projectPath3, rollBin4) {
|
|
|
251968
252064
|
} catch {
|
|
251969
252065
|
}
|
|
251970
252066
|
process.removeListener("SIGINT", finish);
|
|
251971
|
-
|
|
252067
|
+
resolve12();
|
|
251972
252068
|
};
|
|
251973
252069
|
process.on("SIGINT", finish);
|
|
251974
252070
|
watch.on("exit", finish);
|
|
@@ -251979,7 +252075,7 @@ function realRunOnce(input) {
|
|
|
251979
252075
|
const bin = rollBin();
|
|
251980
252076
|
const cmd = bin.endsWith(".js") || bin.endsWith(".mjs") ? process.execPath : bin;
|
|
251981
252077
|
const args = cmd === process.execPath ? [bin, "loop", "run-once"] : ["loop", "run-once"];
|
|
251982
|
-
return new Promise((
|
|
252078
|
+
return new Promise((resolve12) => {
|
|
251983
252079
|
const child = spawn7(cmd, args, {
|
|
251984
252080
|
cwd: input.projectPath,
|
|
251985
252081
|
detached: true,
|
|
@@ -251993,8 +252089,8 @@ function realRunOnce(input) {
|
|
|
251993
252089
|
},
|
|
251994
252090
|
stdio: "inherit"
|
|
251995
252091
|
});
|
|
251996
|
-
child.on("exit", (code) =>
|
|
251997
|
-
child.on("error", () =>
|
|
252092
|
+
child.on("exit", (code) => resolve12(code ?? 1));
|
|
252093
|
+
child.on("error", () => resolve12(1));
|
|
251998
252094
|
});
|
|
251999
252095
|
}
|
|
252000
252096
|
function writeGoal(path, goal) {
|
|
@@ -252822,6 +252918,14 @@ async function runGoWorker(id, opts, deps) {
|
|
|
252822
252918
|
stopReason2 = preProgressGate.reason;
|
|
252823
252919
|
break;
|
|
252824
252920
|
}
|
|
252921
|
+
const bootstrap = classifyBootstrapArtifacts(gitDirtyPaths(id.path));
|
|
252922
|
+
if (bootstrap.kind === "bootstrap_only") {
|
|
252923
|
+
stopReason2 = "bootstrap_artifacts_unconfirmed";
|
|
252924
|
+
appendGoalGate(bus, evPath, sid, "progress", "paused", stopReason2, { files: bootstrap.files.join(", "), count: bootstrap.files.length }, deps.nowSec());
|
|
252925
|
+
process.stdout.write(bootstrapArtifactsMessage(bootstrap.files));
|
|
252926
|
+
goal = pauseGoal(id.path, bus, stopReason2, deps.nowIso(), deps.nowSec()) ?? goal;
|
|
252927
|
+
break;
|
|
252928
|
+
}
|
|
252825
252929
|
const allowedCards = allowedCardsForScope(id.path, goal, progress);
|
|
252826
252930
|
if (allScopeCardsSkipped(id.path, goal, progress)) {
|
|
252827
252931
|
stopReason2 = "no_progress_on_all_cards";
|
|
@@ -253975,7 +254079,7 @@ function renderDesignNudge(lang10) {
|
|
|
253975
254079
|
init_dist2();
|
|
253976
254080
|
init_dist();
|
|
253977
254081
|
import { existsSync as existsSync59, readdirSync as readdirSync24, readFileSync as readFileSync56, statSync as statSync22 } from "node:fs";
|
|
253978
|
-
import { relative as relative4, resolve as
|
|
254082
|
+
import { relative as relative4, resolve as resolve6 } from "node:path";
|
|
253979
254083
|
var IGNORE_DIRS = /* @__PURE__ */ new Set([
|
|
253980
254084
|
".git",
|
|
253981
254085
|
"node_modules",
|
|
@@ -253997,23 +254101,23 @@ function walkMarkdownFiles(dir, out3, includeGenerated) {
|
|
|
253997
254101
|
continue;
|
|
253998
254102
|
if (!includeGenerated && (entry.name === ".roll" || entry.name === "archive"))
|
|
253999
254103
|
continue;
|
|
254000
|
-
walkMarkdownFiles(
|
|
254104
|
+
walkMarkdownFiles(resolve6(dir, entry.name), out3, includeGenerated);
|
|
254001
254105
|
} else if (entry.isFile() && isMarkdownFile(entry.name)) {
|
|
254002
|
-
out3.push(
|
|
254106
|
+
out3.push(resolve6(dir, entry.name));
|
|
254003
254107
|
}
|
|
254004
254108
|
}
|
|
254005
254109
|
}
|
|
254006
254110
|
function defaultScanRoots(root, includeGenerated) {
|
|
254007
254111
|
const roots = [];
|
|
254008
254112
|
for (const rel of ["AGENTS.md", "roll.md", "conventions", "skills", "guide"]) {
|
|
254009
|
-
const abs =
|
|
254113
|
+
const abs = resolve6(root, rel);
|
|
254010
254114
|
if (!existsSync59(abs))
|
|
254011
254115
|
continue;
|
|
254012
254116
|
roots.push(abs);
|
|
254013
254117
|
}
|
|
254014
254118
|
if (includeGenerated) {
|
|
254015
254119
|
for (const rel of [".roll", "archive"]) {
|
|
254016
|
-
const abs =
|
|
254120
|
+
const abs = resolve6(root, rel);
|
|
254017
254121
|
if (existsSync59(abs))
|
|
254018
254122
|
roots.push(abs);
|
|
254019
254123
|
}
|
|
@@ -256854,7 +256958,7 @@ function renderAiClients(out3, clients) {
|
|
|
256854
256958
|
}
|
|
256855
256959
|
out3.push(" " + pad(nameCol, 14) + pad(c("dim", cl.cfg_file), 14) + pad(syncCol, 14) + c("dim", String(cl.skills)));
|
|
256856
256960
|
if (cl.sync === "out-of-sync" || cl.sync === "missing") {
|
|
256857
|
-
out3.push(" " + c("dim", "fix: ") + c("blue",
|
|
256961
|
+
out3.push(" " + c("dim", "fix: ") + c("blue", "roll setup -f"));
|
|
256858
256962
|
}
|
|
256859
256963
|
}
|
|
256860
256964
|
out3.push("", hr(), "");
|
|
@@ -257180,7 +257284,7 @@ function collectAgentPanel(projectPath3, deps = defaultAgentPanelDeps()) {
|
|
|
257180
257284
|
costUsd72h: Number(s.cost.toFixed(4)),
|
|
257181
257285
|
files,
|
|
257182
257286
|
syncStale: isInstalled && stale,
|
|
257183
|
-
...isInstalled && stale ? { setupCmd:
|
|
257287
|
+
...isInstalled && stale ? { setupCmd: "roll setup -f" } : {}
|
|
257184
257288
|
});
|
|
257185
257289
|
}
|
|
257186
257290
|
rows.sort((a, b) => Number(b.installed) - Number(a.installed) || b.cycles72h - a.cycles72h || a.name.localeCompare(b.name));
|
|
@@ -258049,7 +258153,7 @@ function collectLoopHeartbeat(deps) {
|
|
|
258049
258153
|
// packages/cli/dist/lib/git-hooks.js
|
|
258050
258154
|
import { execFileSync as execFileSync20 } from "node:child_process";
|
|
258051
258155
|
import { readdirSync as readdirSync29 } from "node:fs";
|
|
258052
|
-
import { isAbsolute, join as join77, resolve as
|
|
258156
|
+
import { isAbsolute, join as join77, resolve as resolve8 } from "node:path";
|
|
258053
258157
|
var HOOK_DESCRIPTIONS = {
|
|
258054
258158
|
"pre-commit": {
|
|
258055
258159
|
en: "TCR proof gate before commit",
|
|
@@ -258111,11 +258215,11 @@ function resolveHooksPath(projectPath3) {
|
|
|
258111
258215
|
if (configured !== "" && configured !== ".git/hooks") {
|
|
258112
258216
|
return {
|
|
258113
258217
|
displayPath: configured,
|
|
258114
|
-
fsPath: isAbsolute(configured) ? configured :
|
|
258218
|
+
fsPath: isAbsolute(configured) ? configured : resolve8(projectPath3, configured)
|
|
258115
258219
|
};
|
|
258116
258220
|
}
|
|
258117
258221
|
const gitPath = gitOutput3(projectPath3, ["rev-parse", "--git-path", "hooks"]);
|
|
258118
|
-
const fsPath = gitPath === "" ? join77(projectPath3, ".git", "hooks") : isAbsolute(gitPath) ? gitPath :
|
|
258222
|
+
const fsPath = gitPath === "" ? join77(projectPath3, ".git", "hooks") : isAbsolute(gitPath) ? gitPath : resolve8(projectPath3, gitPath);
|
|
258119
258223
|
return {
|
|
258120
258224
|
displayPath: configured === "" ? ".git/hooks" : configured,
|
|
258121
258225
|
fsPath
|
|
@@ -260053,6 +260157,91 @@ function registerProject(projectDir) {
|
|
|
260053
260157
|
} catch {
|
|
260054
260158
|
}
|
|
260055
260159
|
}
|
|
260160
|
+
var ROLL_OWNED_GIT_PATHS = [
|
|
260161
|
+
"AGENTS.md",
|
|
260162
|
+
".claude/CLAUDE.md",
|
|
260163
|
+
".roll/.version",
|
|
260164
|
+
".roll/agents.yaml",
|
|
260165
|
+
".roll/backlog.md",
|
|
260166
|
+
".roll/brief.md",
|
|
260167
|
+
".roll/briefs",
|
|
260168
|
+
".roll/domain",
|
|
260169
|
+
".roll/domain/context-map.md",
|
|
260170
|
+
".roll/features",
|
|
260171
|
+
".roll/features.md",
|
|
260172
|
+
".roll/init-diagnosis.yaml",
|
|
260173
|
+
".roll/onboard-changeset.yaml",
|
|
260174
|
+
".roll/onboard-plan.yaml",
|
|
260175
|
+
".roll/tech-analysis.md",
|
|
260176
|
+
".roll/test-assessment.md",
|
|
260177
|
+
".gitignore"
|
|
260178
|
+
];
|
|
260179
|
+
function runGit(projectDir, args) {
|
|
260180
|
+
const result = spawnSync11("git", args, {
|
|
260181
|
+
cwd: projectDir,
|
|
260182
|
+
encoding: "utf8",
|
|
260183
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
260184
|
+
});
|
|
260185
|
+
return {
|
|
260186
|
+
ok: result.status === 0,
|
|
260187
|
+
stdout: String(result.stdout ?? ""),
|
|
260188
|
+
stderr: String(result.stderr ?? "")
|
|
260189
|
+
};
|
|
260190
|
+
}
|
|
260191
|
+
function existingRollOwnedPaths(projectDir) {
|
|
260192
|
+
return ROLL_OWNED_GIT_PATHS.filter((rel) => existsSync83(join86(projectDir, rel.replace(/\/$/, ""))));
|
|
260193
|
+
}
|
|
260194
|
+
function printGitFinalizeManual(reason, command) {
|
|
260195
|
+
warn4(`Roll meta git finalize needs manual follow-up: ${reason}`);
|
|
260196
|
+
process.stderr.write(` ${command}
|
|
260197
|
+
`);
|
|
260198
|
+
}
|
|
260199
|
+
function finalizeRollOwnedGit(projectDir) {
|
|
260200
|
+
if (!runGit(projectDir, ["rev-parse", "--is-inside-work-tree"]).ok)
|
|
260201
|
+
return;
|
|
260202
|
+
const topLevel = runGit(projectDir, ["rev-parse", "--show-toplevel"]);
|
|
260203
|
+
if (!topLevel.ok)
|
|
260204
|
+
return;
|
|
260205
|
+
if (realpathSync11(projectDir) !== realpathSync11(topLevel.stdout.trim()))
|
|
260206
|
+
return;
|
|
260207
|
+
const paths = existingRollOwnedPaths(projectDir);
|
|
260208
|
+
if (paths.length === 0)
|
|
260209
|
+
return;
|
|
260210
|
+
if (!runGit(projectDir, ["diff", "--cached", "--quiet"]).ok) {
|
|
260211
|
+
printGitFinalizeManual("existing staged changes; auto commit skipped", `git add -A -f -- ${paths.join(" ")} && git commit -m 'roll init: commit Roll-owned meta files'`);
|
|
260212
|
+
return;
|
|
260213
|
+
}
|
|
260214
|
+
const add = runGit(projectDir, ["add", "-A", "-f", "--", ...paths]);
|
|
260215
|
+
if (!add.ok) {
|
|
260216
|
+
printGitFinalizeManual("git add failed", `git add -A -f -- ${paths.join(" ")}`);
|
|
260217
|
+
return;
|
|
260218
|
+
}
|
|
260219
|
+
if (runGit(projectDir, ["diff", "--cached", "--quiet", "--", ...paths]).ok)
|
|
260220
|
+
return;
|
|
260221
|
+
const commit2 = runGit(projectDir, ["commit", "-m", "roll init: commit Roll-owned meta files"]);
|
|
260222
|
+
if (!commit2.ok) {
|
|
260223
|
+
printGitFinalizeManual("git commit failed", "git commit -m 'roll init: commit Roll-owned meta files' -- AGENTS.md .roll .claude .gitignore");
|
|
260224
|
+
return;
|
|
260225
|
+
}
|
|
260226
|
+
const sha = runGit(projectDir, ["rev-parse", "--short", "HEAD"]).stdout.trim();
|
|
260227
|
+
ok10(`Roll meta committed${sha !== "" ? `: ${sha}` : ""}`);
|
|
260228
|
+
const branch = runGit(projectDir, ["rev-parse", "--abbrev-ref", "HEAD"]).stdout.trim();
|
|
260229
|
+
if (branch === "" || branch === "HEAD") {
|
|
260230
|
+
printGitFinalizeManual("detached HEAD; push skipped", "git push origin HEAD");
|
|
260231
|
+
return;
|
|
260232
|
+
}
|
|
260233
|
+
const remotes = runGit(projectDir, ["remote"]).stdout.split("\n").filter((line) => line.trim() !== "");
|
|
260234
|
+
if (!remotes.includes("origin")) {
|
|
260235
|
+
printGitFinalizeManual("origin remote is not configured; push skipped", `git push -u origin ${branch}`);
|
|
260236
|
+
return;
|
|
260237
|
+
}
|
|
260238
|
+
const push2 = runGit(projectDir, ["push", "-u", "origin", branch]);
|
|
260239
|
+
if (!push2.ok) {
|
|
260240
|
+
printGitFinalizeManual("git push failed", `git push -u origin ${branch}`);
|
|
260241
|
+
return;
|
|
260242
|
+
}
|
|
260243
|
+
ok10(`Roll meta pushed: origin/${branch}`);
|
|
260244
|
+
}
|
|
260056
260245
|
function err9(line) {
|
|
260057
260246
|
const { RED, NC } = pal4();
|
|
260058
260247
|
process.stderr.write(`${RED}[roll]${NC} ${line}
|
|
@@ -260914,6 +261103,7 @@ function initRepair(projectDir, facts, diagnosis2, opts = {}) {
|
|
|
260914
261103
|
recordCreatedFileIfNeeded(projectDir, changeset, ".roll/.version", stampExisted);
|
|
260915
261104
|
printMergeSummary(summary);
|
|
260916
261105
|
ok10("Repair complete.");
|
|
261106
|
+
finalizeRollOwnedGit(projectDir);
|
|
260917
261107
|
return 0;
|
|
260918
261108
|
}
|
|
260919
261109
|
function initApply(projectDir, opts = {}) {
|
|
@@ -261029,6 +261219,7 @@ function initApply(projectDir, opts = {}) {
|
|
|
261029
261219
|
registerProject(projectDir);
|
|
261030
261220
|
process.stdout.write("\n");
|
|
261031
261221
|
ok10(m3("init.onboard_apply_complete_onboard"));
|
|
261222
|
+
finalizeRollOwnedGit(projectDir);
|
|
261032
261223
|
return 0;
|
|
261033
261224
|
} catch (error) {
|
|
261034
261225
|
err9(m32("init.onboard_apply_failed"));
|
|
@@ -261859,6 +262050,7 @@ function initCommand(args, deps = {}) {
|
|
|
261859
262050
|
registerProject(projectDir);
|
|
261860
262051
|
const shouldNudge = detectDesignHandoff(projectDir).shouldNudge;
|
|
261861
262052
|
emitInitUi(projectDir, hasAgents, syncStatus, summary, shouldNudge, repairMode ? "repair" : void 0, conciergeNextItems(brief, initDiagnosis));
|
|
262053
|
+
finalizeRollOwnedGit(projectDir);
|
|
261862
262054
|
void err9;
|
|
261863
262055
|
return 0;
|
|
261864
262056
|
}
|
|
@@ -262055,9 +262247,9 @@ function nextCommand(args) {
|
|
|
262055
262247
|
// packages/cli/dist/commands/design.js
|
|
262056
262248
|
init_dist();
|
|
262057
262249
|
init_dist2();
|
|
262058
|
-
import {
|
|
262059
|
-
import { existsSync as existsSync85, mkdirSync as mkdirSync37, readFileSync as readFileSync78, renameSync as renameSync16, statSync as statSync31, writeFileSync as writeFileSync39 } from "node:fs";
|
|
262060
|
-
import { dirname as dirname39, join as join88, relative as relative6, resolve as
|
|
262250
|
+
import { spawn as spawnChild } from "node:child_process";
|
|
262251
|
+
import { appendFileSync as appendFileSync13, existsSync as existsSync85, mkdirSync as mkdirSync37, readFileSync as readFileSync78, renameSync as renameSync16, statSync as statSync31, writeFileSync as writeFileSync39 } from "node:fs";
|
|
262252
|
+
import { dirname as dirname39, join as join88, relative as relative6, resolve as resolve9 } from "node:path";
|
|
262061
262253
|
|
|
262062
262254
|
// packages/cli/dist/lib/review-page.js
|
|
262063
262255
|
init_dist2();
|
|
@@ -262443,7 +262635,7 @@ function lookupEpic(target, cwd) {
|
|
|
262443
262635
|
function readBacklogItems(cwd) {
|
|
262444
262636
|
try {
|
|
262445
262637
|
const content = readFileSync78(join88(cwd, ".roll", "backlog.md"), "utf8");
|
|
262446
|
-
return parseBacklog(content).map((row2) => ({ id: row2.id }));
|
|
262638
|
+
return parseBacklog(content).map((row2) => ({ id: row2.id, desc: row2.desc }));
|
|
262447
262639
|
} catch {
|
|
262448
262640
|
return [];
|
|
262449
262641
|
}
|
|
@@ -262466,7 +262658,7 @@ function renderDesignReviewPageForTarget(ctx, cardsCreated) {
|
|
|
262466
262658
|
return;
|
|
262467
262659
|
const base = join88(".roll", "features", epic, ctx.target);
|
|
262468
262660
|
const md = join88(base, "spec.md");
|
|
262469
|
-
const absMd =
|
|
262661
|
+
const absMd = resolve9(ctx.cwd, md);
|
|
262470
262662
|
if (!existsSync85(absMd) || !hasDetailedDesign(absMd))
|
|
262471
262663
|
return;
|
|
262472
262664
|
const markdown = readFileSync78(absMd, "utf8");
|
|
@@ -262481,7 +262673,7 @@ function renderDesignReviewPageForTarget(ctx, cardsCreated) {
|
|
|
262481
262673
|
markdown,
|
|
262482
262674
|
lang: ctx.lang
|
|
262483
262675
|
});
|
|
262484
|
-
const out3 =
|
|
262676
|
+
const out3 = resolve9(ctx.cwd, base, "design-review.html");
|
|
262485
262677
|
mkdirSync37(dirname39(out3), { recursive: true });
|
|
262486
262678
|
const tmp = `${out3}.tmp`;
|
|
262487
262679
|
writeFileSync39(tmp, html, "utf8");
|
|
@@ -262499,37 +262691,203 @@ function formatSignal(sig) {
|
|
|
262499
262691
|
const detail = sig.detail !== void 0 && sig.detail !== "" ? ` ${sig.detail}` : "";
|
|
262500
262692
|
return `${fmtHhmmss(sig.ts)} ${sig.summary}${detail}`.trimEnd();
|
|
262501
262693
|
}
|
|
262502
|
-
function
|
|
262503
|
-
|
|
262694
|
+
function isPromiseLike(value) {
|
|
262695
|
+
return typeof value.then === "function";
|
|
262696
|
+
}
|
|
262697
|
+
function isDesignNoise(text2) {
|
|
262698
|
+
const s = text2.trim();
|
|
262699
|
+
if (s === "")
|
|
262700
|
+
return true;
|
|
262701
|
+
if (/^\?\?\s/.test(s))
|
|
262702
|
+
return true;
|
|
262703
|
+
if (/^\s*-\s*\[\s*\]\s+/.test(s))
|
|
262704
|
+
return true;
|
|
262705
|
+
return /\$roll-design|roll-design contract|ID generation algorithm|Who writes the data|encrypted reasoning/i.test(s);
|
|
262706
|
+
}
|
|
262707
|
+
function isMeaningfulDesignSay(summary) {
|
|
262708
|
+
return /\b(reading|planning|designing|writing|validating|recovering|handoff|backlog|spec|artifact|context|contexts|created|card)\b/i.test(summary);
|
|
262709
|
+
}
|
|
262710
|
+
function shouldShowSignal(sig, verbose) {
|
|
262711
|
+
const joined = `${sig.summary} ${sig.detail ?? ""}`;
|
|
262712
|
+
if (isDesignNoise(joined))
|
|
262713
|
+
return false;
|
|
262714
|
+
if (verbose)
|
|
262715
|
+
return true;
|
|
262716
|
+
if (sig.tier === "A" || sig.tier === "B")
|
|
262717
|
+
return true;
|
|
262718
|
+
if (sig.kind === "say" && isMeaningfulDesignSay(sig.summary))
|
|
262719
|
+
return true;
|
|
262720
|
+
return sig.kind === "say" && isQuestionLike(sig.summary);
|
|
262721
|
+
}
|
|
262722
|
+
function formatDuration(ms) {
|
|
262723
|
+
const total = Math.max(0, Math.round(ms / 1e3));
|
|
262724
|
+
const m7 = Math.floor(total / 60);
|
|
262725
|
+
const s = total % 60;
|
|
262726
|
+
if (m7 === 0)
|
|
262727
|
+
return `${s}s`;
|
|
262728
|
+
return `${m7}m ${String(s).padStart(2, "0")}s`;
|
|
262729
|
+
}
|
|
262730
|
+
function formatBytes(bytes) {
|
|
262731
|
+
if (bytes < 1024)
|
|
262732
|
+
return `${bytes} B`;
|
|
262733
|
+
if (bytes < 1024 * 1024)
|
|
262734
|
+
return `${Math.round(bytes / 1024)} KB`;
|
|
262735
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
262736
|
+
}
|
|
262737
|
+
function transcriptSize(path) {
|
|
262738
|
+
try {
|
|
262739
|
+
return statSync31(path).size;
|
|
262740
|
+
} catch {
|
|
262741
|
+
return 0;
|
|
262742
|
+
}
|
|
262743
|
+
}
|
|
262744
|
+
function splitCardDescription(desc) {
|
|
262745
|
+
const clean3 = desc.replace(/\s+/g, " ").trim();
|
|
262746
|
+
const solves = /\s+·\s+solves\s+/i.exec(clean3);
|
|
262747
|
+
if (solves !== null) {
|
|
262748
|
+
const title = clean3.slice(0, solves.index).trim();
|
|
262749
|
+
const problem = clean3.slice(solves.index + solves[0].length).trim();
|
|
262750
|
+
return { title: title || clean3, problem: problem || title || clean3 };
|
|
262751
|
+
}
|
|
262752
|
+
return { title: clean3 || "Untitled card", problem: clean3 || "the design gap" };
|
|
262753
|
+
}
|
|
262754
|
+
function createLiveProgress(ctx, deps, opts) {
|
|
262755
|
+
const normalizer = normalizerFor(ctx.agent);
|
|
262504
262756
|
const state = newNormalizerState();
|
|
262505
|
-
const
|
|
262506
|
-
const
|
|
262507
|
-
|
|
262508
|
-
|
|
262509
|
-
|
|
262510
|
-
|
|
262757
|
+
const emittedCards = /* @__PURE__ */ new Set();
|
|
262758
|
+
const knownBefore = new Set(ctx.beforeBacklog.map((row2) => row2.id));
|
|
262759
|
+
let stdoutBuffer = "";
|
|
262760
|
+
let stderrBuffer = "";
|
|
262761
|
+
let rawTranscript = "";
|
|
262762
|
+
let sawLiveOutput = false;
|
|
262763
|
+
let lastPrintedTs = ctx.startTs;
|
|
262764
|
+
let heartbeat;
|
|
262765
|
+
const scanCards = () => {
|
|
262766
|
+
if (opts.raw)
|
|
262767
|
+
return;
|
|
262768
|
+
for (const item of readBacklogItems(ctx.cwd)) {
|
|
262769
|
+
if (knownBefore.has(item.id) || emittedCards.has(item.id))
|
|
262770
|
+
continue;
|
|
262771
|
+
emittedCards.add(item.id);
|
|
262772
|
+
const { title, problem } = splitCardDescription(item.desc);
|
|
262773
|
+
const ts2 = deps.now();
|
|
262774
|
+
lastPrintedTs = ts2;
|
|
262775
|
+
emit4(`${fmtHhmmss(ts2)} card created: ${item.id} \u2014 ${title} \xB7 solves ${problem}`);
|
|
262776
|
+
}
|
|
262777
|
+
};
|
|
262778
|
+
const processLine = (line) => {
|
|
262779
|
+
if (opts.raw)
|
|
262780
|
+
return;
|
|
262781
|
+
const ts2 = deps.now();
|
|
262782
|
+
const signals = normalizer.normalize(line, state, ts2);
|
|
262511
262783
|
for (const sig of signals) {
|
|
262512
|
-
|
|
262513
|
-
|
|
262514
|
-
|
|
262784
|
+
if (!shouldShowSignal(sig, opts.verbose))
|
|
262785
|
+
continue;
|
|
262786
|
+
lastPrintedTs = sig.ts;
|
|
262787
|
+
emit4(formatSignal(sig));
|
|
262788
|
+
}
|
|
262789
|
+
};
|
|
262790
|
+
const ingest = (chunk, stream) => {
|
|
262791
|
+
if (chunk === "")
|
|
262792
|
+
return;
|
|
262793
|
+
sawLiveOutput = true;
|
|
262794
|
+
rawTranscript += chunk;
|
|
262795
|
+
appendFileSync13(ctx.transcriptPath, chunk, "utf8");
|
|
262796
|
+
if (opts.raw) {
|
|
262797
|
+
process.stderr.write(chunk);
|
|
262798
|
+
return;
|
|
262799
|
+
}
|
|
262800
|
+
const next = (stream === "stdout" ? stdoutBuffer : stderrBuffer) + chunk;
|
|
262801
|
+
const parts = next.split(/\n/);
|
|
262802
|
+
const complete = parts.slice(0, -1);
|
|
262803
|
+
for (const line of complete)
|
|
262804
|
+
processLine(line);
|
|
262805
|
+
if (stream === "stdout")
|
|
262806
|
+
stdoutBuffer = parts[parts.length - 1] ?? "";
|
|
262807
|
+
else
|
|
262808
|
+
stderrBuffer = parts[parts.length - 1] ?? "";
|
|
262809
|
+
scanCards();
|
|
262810
|
+
};
|
|
262811
|
+
const emitHeartbeat = () => {
|
|
262812
|
+
if (opts.raw)
|
|
262813
|
+
return;
|
|
262814
|
+
const ts2 = deps.now();
|
|
262815
|
+
if (ts2 - lastPrintedTs < deps.heartbeatMs)
|
|
262816
|
+
return;
|
|
262817
|
+
lastPrintedTs = ts2;
|
|
262818
|
+
emit4(`${fmtHhmmss(ts2)} heartbeat: still designing \xB7 elapsed ${formatDuration(ts2 - ctx.startTs)} \xB7 transcript ${formatBytes(transcriptSize(ctx.transcriptPath))} \xB7 cards observed ${emittedCards.size}`);
|
|
262819
|
+
};
|
|
262820
|
+
return {
|
|
262821
|
+
get sawLiveOutput() {
|
|
262822
|
+
return sawLiveOutput;
|
|
262823
|
+
},
|
|
262824
|
+
get rawTranscript() {
|
|
262825
|
+
return rawTranscript;
|
|
262826
|
+
},
|
|
262827
|
+
startHeartbeat: () => {
|
|
262828
|
+
if (opts.raw)
|
|
262829
|
+
return;
|
|
262830
|
+
heartbeat = setInterval(emitHeartbeat, deps.heartbeatMs);
|
|
262831
|
+
heartbeat.unref?.();
|
|
262832
|
+
},
|
|
262833
|
+
stopHeartbeat: () => {
|
|
262834
|
+
if (heartbeat !== void 0)
|
|
262835
|
+
clearInterval(heartbeat);
|
|
262836
|
+
},
|
|
262837
|
+
ingestStdout: (chunk) => ingest(chunk, "stdout"),
|
|
262838
|
+
ingestStderr: (chunk) => ingest(chunk, "stderr"),
|
|
262839
|
+
flush: () => {
|
|
262840
|
+
if (stdoutBuffer !== "") {
|
|
262841
|
+
processLine(stdoutBuffer);
|
|
262842
|
+
stdoutBuffer = "";
|
|
262515
262843
|
}
|
|
262844
|
+
if (stderrBuffer !== "") {
|
|
262845
|
+
processLine(stderrBuffer);
|
|
262846
|
+
stderrBuffer = "";
|
|
262847
|
+
}
|
|
262848
|
+
scanCards();
|
|
262516
262849
|
}
|
|
262517
|
-
}
|
|
262518
|
-
return out3;
|
|
262850
|
+
};
|
|
262519
262851
|
}
|
|
262520
262852
|
var defaultDeps = {
|
|
262521
262853
|
cwd: process.cwd(),
|
|
262522
262854
|
env: process.env,
|
|
262523
262855
|
readLine: readLineFromStdin,
|
|
262524
262856
|
now: () => Date.now(),
|
|
262525
|
-
|
|
262526
|
-
|
|
262527
|
-
return {
|
|
262528
|
-
|
|
262529
|
-
|
|
262530
|
-
|
|
262531
|
-
|
|
262532
|
-
|
|
262857
|
+
heartbeatMs: 6e4,
|
|
262858
|
+
spawn: (bin, args, opts, live) => {
|
|
262859
|
+
return new Promise((resolveSpawn) => {
|
|
262860
|
+
const child = spawnChild(bin, args, { ...opts, stdio: ["inherit", "pipe", "pipe"] });
|
|
262861
|
+
let stdout = "";
|
|
262862
|
+
let stderr = "";
|
|
262863
|
+
let settled = false;
|
|
262864
|
+
const finish = (result) => {
|
|
262865
|
+
if (settled)
|
|
262866
|
+
return;
|
|
262867
|
+
settled = true;
|
|
262868
|
+
resolveSpawn(result);
|
|
262869
|
+
};
|
|
262870
|
+
child.stdout?.setEncoding("utf8");
|
|
262871
|
+
child.stderr?.setEncoding("utf8");
|
|
262872
|
+
child.stdout?.on("data", (chunk) => {
|
|
262873
|
+
stdout += chunk;
|
|
262874
|
+
live?.onStdout(chunk);
|
|
262875
|
+
});
|
|
262876
|
+
child.stderr?.on("data", (chunk) => {
|
|
262877
|
+
stderr += chunk;
|
|
262878
|
+
live?.onStderr(chunk);
|
|
262879
|
+
});
|
|
262880
|
+
child.on("error", (err16) => {
|
|
262881
|
+
const message = `${err16 instanceof Error ? err16.message : String(err16)}
|
|
262882
|
+
`;
|
|
262883
|
+
stderr += message;
|
|
262884
|
+
live?.onStderr(message);
|
|
262885
|
+
finish({ status: 1, signal: null, stdout, stderr });
|
|
262886
|
+
});
|
|
262887
|
+
child.on("close", (code, signal) => {
|
|
262888
|
+
finish({ status: code, signal, stdout, stderr });
|
|
262889
|
+
});
|
|
262890
|
+
});
|
|
262533
262891
|
}
|
|
262534
262892
|
};
|
|
262535
262893
|
function selectAgent(installed, forced, envAgent, primary, readLine) {
|
|
@@ -262594,12 +262952,12 @@ function printHandoff(ctx, statusCode, rawTranscript) {
|
|
|
262594
262952
|
const md = join88(base, "spec.md");
|
|
262595
262953
|
const reviewHtml = join88(base, "design-review.html");
|
|
262596
262954
|
const html = join88(base, "spec.html");
|
|
262597
|
-
if (existsSync85(
|
|
262598
|
-
designPath = hasDetailedDesign(
|
|
262955
|
+
if (existsSync85(resolve9(ctx.cwd, md))) {
|
|
262956
|
+
designPath = hasDetailedDesign(resolve9(ctx.cwd, md)) ? `${md}#detailed-design` : md;
|
|
262599
262957
|
}
|
|
262600
|
-
if (existsSync85(
|
|
262958
|
+
if (existsSync85(resolve9(ctx.cwd, reviewHtml)))
|
|
262601
262959
|
reviewPagePath = reviewHtml;
|
|
262602
|
-
else if (existsSync85(
|
|
262960
|
+
else if (existsSync85(resolve9(ctx.cwd, html)))
|
|
262603
262961
|
reviewPagePath = html;
|
|
262604
262962
|
}
|
|
262605
262963
|
let status2;
|
|
@@ -262664,7 +263022,7 @@ function designCommand(args, deps = {}) {
|
|
|
262664
263022
|
emit4(t(v3Catalog, l, "design.not_roll_project"));
|
|
262665
263023
|
return 1;
|
|
262666
263024
|
}
|
|
262667
|
-
if (fromFile !== void 0 && !isRegularFile(
|
|
263025
|
+
if (fromFile !== void 0 && !isRegularFile(resolve9(d.cwd, fromFile))) {
|
|
262668
263026
|
emit4(t(v3Catalog, l, "design.from_file_not_found", fromFile));
|
|
262669
263027
|
return 1;
|
|
262670
263028
|
}
|
|
@@ -262717,20 +263075,35 @@ function designCommand(args, deps = {}) {
|
|
|
262717
263075
|
beforeBacklog: readBacklogItems(d.cwd)
|
|
262718
263076
|
};
|
|
262719
263077
|
printStartBlock(ctx);
|
|
262720
|
-
const
|
|
262721
|
-
|
|
262722
|
-
|
|
262723
|
-
|
|
262724
|
-
|
|
262725
|
-
|
|
262726
|
-
|
|
262727
|
-
|
|
262728
|
-
|
|
262729
|
-
|
|
263078
|
+
const live = createLiveProgress(ctx, d, { raw: rawMode, verbose });
|
|
263079
|
+
live.startHeartbeat();
|
|
263080
|
+
const finish = (result) => {
|
|
263081
|
+
if (!live.sawLiveOutput) {
|
|
263082
|
+
live.ingestStdout(result.stdout ?? "");
|
|
263083
|
+
live.ingestStderr(result.stderr ?? "");
|
|
263084
|
+
} else {
|
|
263085
|
+
const stdout = result.stdout ?? "";
|
|
263086
|
+
const stderr = result.stderr ?? "";
|
|
263087
|
+
if (stdout !== "" && !live.rawTranscript.includes(stdout))
|
|
263088
|
+
live.ingestStdout(stdout);
|
|
263089
|
+
if (stderr !== "" && !live.rawTranscript.includes(stderr))
|
|
263090
|
+
live.ingestStderr(stderr);
|
|
263091
|
+
}
|
|
263092
|
+
live.stopHeartbeat();
|
|
263093
|
+
live.flush();
|
|
263094
|
+
const statusCode = result.status ?? (result.signal === null ? 1 : 130);
|
|
263095
|
+
printHandoff(ctx, statusCode, live.rawTranscript);
|
|
263096
|
+
return statusCode;
|
|
263097
|
+
};
|
|
263098
|
+
const spawned = d.spawn(cmd.bin, cmd.args, { cwd: d.cwd, env: d.env }, { onStdout: live.ingestStdout, onStderr: live.ingestStderr });
|
|
263099
|
+
if (isPromiseLike(spawned)) {
|
|
263100
|
+
return spawned.then(finish, (err16) => {
|
|
263101
|
+
live.ingestStderr(`${err16 instanceof Error ? err16.message : String(err16)}
|
|
263102
|
+
`);
|
|
263103
|
+
return finish({ status: 1, signal: null });
|
|
263104
|
+
});
|
|
262730
263105
|
}
|
|
262731
|
-
|
|
262732
|
-
printHandoff(ctx, statusCode, rawTranscript);
|
|
262733
|
-
return statusCode;
|
|
263106
|
+
return finish(spawned);
|
|
262734
263107
|
}
|
|
262735
263108
|
|
|
262736
263109
|
// packages/cli/dist/commands/loop-watch.js
|
|
@@ -262738,7 +263111,7 @@ init_dist();
|
|
|
262738
263111
|
init_dist2();
|
|
262739
263112
|
init_dist3();
|
|
262740
263113
|
init_render();
|
|
262741
|
-
import { spawn as spawn8, spawnSync as
|
|
263114
|
+
import { spawn as spawn8, spawnSync as spawnSync12 } from "node:child_process";
|
|
262742
263115
|
import { existsSync as existsSync86, readFileSync as readFileSync79 } from "node:fs";
|
|
262743
263116
|
import { join as join89 } from "node:path";
|
|
262744
263117
|
import { createInterface as createInterface4 } from "node:readline";
|
|
@@ -262899,13 +263272,13 @@ function realDeps7() {
|
|
|
262899
263272
|
render: (input, opts) => streamThroughRenderer(input, process.stdout, opts),
|
|
262900
263273
|
renderEvents: streamEvents,
|
|
262901
263274
|
tmuxState: probeWatchTmuxState,
|
|
262902
|
-
tmuxRun: (argv) =>
|
|
263275
|
+
tmuxRun: (argv) => spawnSync12("tmux", argv, { stdio: "ignore" }).status === 0,
|
|
262903
263276
|
tmuxAttach: (session) => {
|
|
262904
|
-
|
|
263277
|
+
spawnSync12("tmux", ["attach-session", "-r", "-t", session], { stdio: "inherit" });
|
|
262905
263278
|
},
|
|
262906
263279
|
hasTmux: () => {
|
|
262907
263280
|
try {
|
|
262908
|
-
return
|
|
263281
|
+
return spawnSync12("tmux", ["-V"], { stdio: "ignore" }).status === 0;
|
|
262909
263282
|
} catch {
|
|
262910
263283
|
return false;
|
|
262911
263284
|
}
|
|
@@ -262916,10 +263289,10 @@ function realDeps7() {
|
|
|
262916
263289
|
}
|
|
262917
263290
|
function probeWatchTmuxState(slug3) {
|
|
262918
263291
|
const session = watchSessionName(slug3);
|
|
262919
|
-
const sessionExists =
|
|
263292
|
+
const sessionExists = spawnSync12("tmux", ["has-session", "-t", session], { stdio: "ignore" }).status === 0;
|
|
262920
263293
|
if (!sessionExists)
|
|
262921
263294
|
return { sessionExists: false, watchWindowExists: false };
|
|
262922
|
-
const listed =
|
|
263295
|
+
const listed = spawnSync12("tmux", ["list-windows", "-t", session, "-F", "#{window_name}"], { encoding: "utf8" });
|
|
262923
263296
|
const windows = listed.status === 0 ? String(listed.stdout ?? "").split("\n").map((w) => w.trim()) : [];
|
|
262924
263297
|
return { sessionExists: true, watchWindowExists: windows.includes("watch") };
|
|
262925
263298
|
}
|
|
@@ -263296,14 +263669,14 @@ ${RECONCILE_PENDING_USAGE}
|
|
|
263296
263669
|
|
|
263297
263670
|
// packages/cli/dist/commands/loop-review-resize.js
|
|
263298
263671
|
init_dist2();
|
|
263299
|
-
import { appendFileSync as
|
|
263672
|
+
import { appendFileSync as appendFileSync15, mkdirSync as mkdirSync39 } from "node:fs";
|
|
263300
263673
|
import { dirname as dirname41, join as join92 } from "node:path";
|
|
263301
263674
|
init_dist2();
|
|
263302
263675
|
|
|
263303
263676
|
// packages/cli/dist/commands/loop-self-downgrade.js
|
|
263304
263677
|
init_dist2();
|
|
263305
263678
|
init_dist3();
|
|
263306
|
-
import { appendFileSync as
|
|
263679
|
+
import { appendFileSync as appendFileSync14, existsSync as existsSync87, mkdirSync as mkdirSync38, readFileSync as readFileSync80, readdirSync as readdirSync32 } from "node:fs";
|
|
263307
263680
|
import { dirname as dirname40, join as join91 } from "node:path";
|
|
263308
263681
|
function realSelfDowngradeDeps() {
|
|
263309
263682
|
return {
|
|
@@ -263418,7 +263791,7 @@ async function loopSelfDowngradeCommand(argv, deps = realSelfDowngradeDeps()) {
|
|
|
263418
263791
|
const headline = plan.capReason === "chain-cap" ? `${parentId} hit the self-downgrade chain cap (chain_depth=${plan.chainDepth} \u2265 ${CHAIN_DEPTH_CAP}) \u2014 held for human triage` : `${parentId} could not be split into \u22652 sub-stories (irreducible) \u2014 held for human triage`;
|
|
263419
263792
|
try {
|
|
263420
263793
|
mkdirSync38(dirname40(alertsPath), { recursive: true });
|
|
263421
|
-
|
|
263794
|
+
appendFileSync14(alertsPath, `[${isoUtc(ts2)}] ALERT ${headline}
|
|
263422
263795
|
`, "utf8");
|
|
263423
263796
|
} catch {
|
|
263424
263797
|
}
|
|
@@ -263521,7 +263894,7 @@ For each sub-story create its .roll/features/<epic>/<id>/spec.md. Do NOT edit th
|
|
|
263521
263894
|
const alertsPath = (process.env["ROLL_LOOP_ALERT"] ?? "").trim() || join92(rt, `ALERT-${projectSlug3(projectPath3)}.md`);
|
|
263522
263895
|
try {
|
|
263523
263896
|
mkdirSync39(dirname41(alertsPath), { recursive: true });
|
|
263524
|
-
|
|
263897
|
+
appendFileSync15(alertsPath, `[${new Date(ts2).toISOString()}] ALERT ${message}
|
|
263525
263898
|
`, "utf8");
|
|
263526
263899
|
} catch {
|
|
263527
263900
|
}
|
|
@@ -263621,7 +263994,7 @@ async function loopExhaustionSplitCommand(argv, deps = realExhaustionSplitDeps()
|
|
|
263621
263994
|
init_dist2();
|
|
263622
263995
|
init_dist();
|
|
263623
263996
|
init_dist3();
|
|
263624
|
-
import { appendFileSync as
|
|
263997
|
+
import { appendFileSync as appendFileSync19, existsSync as existsSync99, mkdirSync as mkdirSync47, readFileSync as readFileSync93, writeFileSync as writeFileSync49 } from "node:fs";
|
|
263625
263998
|
import { dirname as dirname46, join as join103 } from "node:path";
|
|
263626
263999
|
|
|
263627
264000
|
// packages/cli/dist/runner/executor.js
|
|
@@ -263670,7 +264043,7 @@ function writeCycleRoleSummaryBestEffort(cycleId, eventsPath3, cycleLogDir) {
|
|
|
263670
264043
|
|
|
263671
264044
|
// packages/cli/dist/runner/executor.js
|
|
263672
264045
|
import { execFile as execFile10, execFileSync as execFileSync22 } from "node:child_process";
|
|
263673
|
-
import { appendFileSync as
|
|
264046
|
+
import { appendFileSync as appendFileSync17, existsSync as existsSync95, lstatSync as lstatSync5, mkdirSync as mkdirSync44, readdirSync as readdirSync36, readFileSync as readFileSync89, realpathSync as realpathSync13, renameSync as renameSync17, rmSync as rmSync16, statSync as statSync33, symlinkSync as symlinkSync3, unlinkSync as unlinkSync4, writeFileSync as writeFileSync46 } from "node:fs";
|
|
263674
264047
|
import { homedir as homedir27 } from "node:os";
|
|
263675
264048
|
import { dirname as dirname43, join as join100 } from "node:path";
|
|
263676
264049
|
import { promisify as promisify10 } from "node:util";
|
|
@@ -263734,8 +264107,8 @@ async function probeAgentReachable(agent, spawn10, opts = {}) {
|
|
|
263734
264107
|
try {
|
|
263735
264108
|
res = await Promise.race([
|
|
263736
264109
|
spawn10(agent, { cwd, skillBody: `Reply with exactly: ${token}`, timeoutMs, bare: true }),
|
|
263737
|
-
new Promise((
|
|
263738
|
-
setTimeout(() =>
|
|
264110
|
+
new Promise((resolve12) => {
|
|
264111
|
+
setTimeout(() => resolve12(null), timeoutMs).unref();
|
|
263739
264112
|
})
|
|
263740
264113
|
]);
|
|
263741
264114
|
} catch (e) {
|
|
@@ -264323,7 +264696,7 @@ function autoAttachScreenshotToAcMap(worktreeCwd, storyId, runDir) {
|
|
|
264323
264696
|
// packages/cli/dist/runner/correction-actuator.js
|
|
264324
264697
|
init_dist2();
|
|
264325
264698
|
init_dist();
|
|
264326
|
-
import { appendFileSync as
|
|
264699
|
+
import { appendFileSync as appendFileSync16, existsSync as existsSync93, mkdirSync as mkdirSync42, readFileSync as readFileSync87, readdirSync as readdirSync35, writeFileSync as writeFileSync44 } from "node:fs";
|
|
264327
264700
|
import { dirname as dirname42, join as join98 } from "node:path";
|
|
264328
264701
|
function readMode(projectPath3) {
|
|
264329
264702
|
try {
|
|
@@ -264345,7 +264718,7 @@ function readEvents4(eventsPath3) {
|
|
|
264345
264718
|
function appendEvent(eventsPath3, event) {
|
|
264346
264719
|
try {
|
|
264347
264720
|
mkdirSync42(dirname42(eventsPath3), { recursive: true });
|
|
264348
|
-
|
|
264721
|
+
appendFileSync16(eventsPath3, `${JSON.stringify(event)}
|
|
264349
264722
|
`, "utf8");
|
|
264350
264723
|
} catch {
|
|
264351
264724
|
}
|
|
@@ -264353,7 +264726,7 @@ function appendEvent(eventsPath3, event) {
|
|
|
264353
264726
|
function appendAlert2(alertsPath, msg6) {
|
|
264354
264727
|
try {
|
|
264355
264728
|
mkdirSync42(dirname42(alertsPath), { recursive: true });
|
|
264356
|
-
|
|
264729
|
+
appendFileSync16(alertsPath, `${msg6}
|
|
264357
264730
|
`, "utf8");
|
|
264358
264731
|
} catch {
|
|
264359
264732
|
}
|
|
@@ -264621,7 +264994,7 @@ function reviewTimeoutMs(diffChars) {
|
|
|
264621
264994
|
async function firstValid(promises) {
|
|
264622
264995
|
if (promises.length === 0)
|
|
264623
264996
|
return null;
|
|
264624
|
-
return new Promise((
|
|
264997
|
+
return new Promise((resolve12, reject) => {
|
|
264625
264998
|
let pending = promises.length;
|
|
264626
264999
|
let settled = false;
|
|
264627
265000
|
let lastError;
|
|
@@ -264633,7 +265006,7 @@ async function firstValid(promises) {
|
|
|
264633
265006
|
if (threw)
|
|
264634
265007
|
reject(lastError);
|
|
264635
265008
|
else
|
|
264636
|
-
|
|
265009
|
+
resolve12(null);
|
|
264637
265010
|
}
|
|
264638
265011
|
};
|
|
264639
265012
|
for (const p of promises) {
|
|
@@ -264642,7 +265015,7 @@ async function firstValid(promises) {
|
|
|
264642
265015
|
return;
|
|
264643
265016
|
if (value !== null) {
|
|
264644
265017
|
settled = true;
|
|
264645
|
-
|
|
265018
|
+
resolve12(value);
|
|
264646
265019
|
return;
|
|
264647
265020
|
}
|
|
264648
265021
|
onNonResult();
|
|
@@ -265025,7 +265398,7 @@ DIFF:
|
|
|
265025
265398
|
|
|
265026
265399
|
// packages/cli/dist/runner/executor.js
|
|
265027
265400
|
var execFileAsync10 = promisify10(execFile10);
|
|
265028
|
-
function
|
|
265401
|
+
function parsePorcelainPath2(line) {
|
|
265029
265402
|
const raw = line.length > 3 ? line.slice(3).trim() : line.trim();
|
|
265030
265403
|
const target = raw.includes(" -> ") ? raw.split(" -> ").at(-1) ?? raw : raw;
|
|
265031
265404
|
return target.replace(/^"|"$/g, "");
|
|
@@ -265036,7 +265409,7 @@ async function checkMainDirty(repoCwd) {
|
|
|
265036
265409
|
cwd: repoCwd,
|
|
265037
265410
|
encoding: "utf8"
|
|
265038
265411
|
});
|
|
265039
|
-
return stdout.split("\n").map((line) => line.trimEnd()).filter((line) => line.trim() !== "").map(
|
|
265412
|
+
return stdout.split("\n").map((line) => line.trimEnd()).filter((line) => line.trim() !== "").map(parsePorcelainPath2).filter((path) => path !== ".roll" && !path.startsWith(".roll/")).slice(0, 50);
|
|
265040
265413
|
} catch {
|
|
265041
265414
|
return [];
|
|
265042
265415
|
}
|
|
@@ -265141,7 +265514,7 @@ var ActivitySignalRecorder = class {
|
|
|
265141
265514
|
}
|
|
265142
265515
|
append(signals) {
|
|
265143
265516
|
try {
|
|
265144
|
-
|
|
265517
|
+
appendFileSync17(this.signalPath, signals.map((sig) => JSON.stringify(sig)).join("\n") + "\n", "utf8");
|
|
265145
265518
|
} catch {
|
|
265146
265519
|
}
|
|
265147
265520
|
}
|
|
@@ -265510,7 +265883,7 @@ function createCaptureMarkerSink(runDir, capture) {
|
|
|
265510
265883
|
const record = (marker, result) => {
|
|
265511
265884
|
try {
|
|
265512
265885
|
mkdirSync44(dirname43(logPath), { recursive: true });
|
|
265513
|
-
|
|
265886
|
+
appendFileSync17(logPath, JSON.stringify({ marker, result }) + "\n", "utf8");
|
|
265514
265887
|
} catch {
|
|
265515
265888
|
}
|
|
265516
265889
|
};
|
|
@@ -265756,7 +266129,7 @@ ${skillBodyForSpawn}` : skillBodyForSpawn;
|
|
|
265756
266129
|
stallDetector.markProgress();
|
|
265757
266130
|
captureSink?.onChunk(d);
|
|
265758
266131
|
try {
|
|
265759
|
-
|
|
266132
|
+
appendFileSync17(livePath, d);
|
|
265760
266133
|
} catch {
|
|
265761
266134
|
}
|
|
265762
266135
|
signalRecorder.accept(d);
|
|
@@ -265995,7 +266368,7 @@ ${stderr}
|
|
|
265995
266368
|
// FIX-319: review-only framing, no worker autorun directive
|
|
265996
266369
|
...ctx.evidenceRunDir !== void 0 ? { runDir: ctx.evidenceRunDir } : {}
|
|
265997
266370
|
}),
|
|
265998
|
-
new Promise((
|
|
266371
|
+
new Promise((resolve12) => setTimeout(() => resolve12(null), timeoutMs).unref())
|
|
265999
266372
|
]);
|
|
266000
266373
|
} catch (e) {
|
|
266001
266374
|
const detail = e instanceof Error ? e.message : String(e);
|
|
@@ -266135,7 +266508,7 @@ ${res.stderr}`;
|
|
|
266135
266508
|
timeoutMs,
|
|
266136
266509
|
...ctx.evidenceRunDir !== void 0 ? { runDir: ctx.evidenceRunDir } : {}
|
|
266137
266510
|
}),
|
|
266138
|
-
new Promise((
|
|
266511
|
+
new Promise((resolve12) => setTimeout(() => resolve12(null), timeoutMs).unref())
|
|
266139
266512
|
]);
|
|
266140
266513
|
} catch (e) {
|
|
266141
266514
|
const detail = e instanceof Error ? e.message : String(e);
|
|
@@ -267354,7 +267727,7 @@ async function linkRollIntoWorktree(repoCwd, worktreePath) {
|
|
|
267354
267727
|
const cur = existsSync95(exclude) ? readFileSync89(exclude, "utf8") : "";
|
|
267355
267728
|
if (!/^\.roll$/m.test(cur)) {
|
|
267356
267729
|
mkdirSync44(dirname43(exclude), { recursive: true });
|
|
267357
|
-
|
|
267730
|
+
appendFileSync17(exclude, `${cur === "" || cur.endsWith("\n") ? "" : "\n"}.roll
|
|
267358
267731
|
`, "utf8");
|
|
267359
267732
|
}
|
|
267360
267733
|
} catch {
|
|
@@ -267928,7 +268301,7 @@ function nodePorts(opts) {
|
|
|
267928
268301
|
}
|
|
267929
268302
|
function appendAlertLine(alertsPath, message) {
|
|
267930
268303
|
mkdirSync44(dirname43(alertsPath), { recursive: true });
|
|
267931
|
-
|
|
268304
|
+
appendFileSync17(alertsPath, `${message}
|
|
267932
268305
|
`, "utf8");
|
|
267933
268306
|
}
|
|
267934
268307
|
|
|
@@ -268271,7 +268644,7 @@ async function warnIfBinaryStale(rollHomeDir2, runningVersion, appendAlert3) {
|
|
|
268271
268644
|
// packages/cli/dist/runner/correction-circuit.js
|
|
268272
268645
|
init_dist2();
|
|
268273
268646
|
init_dist();
|
|
268274
|
-
import { appendFileSync as
|
|
268647
|
+
import { appendFileSync as appendFileSync18, existsSync as existsSync98, mkdirSync as mkdirSync46, readFileSync as readFileSync92, writeFileSync as writeFileSync48 } from "node:fs";
|
|
268275
268648
|
import { dirname as dirname45, join as join102 } from "node:path";
|
|
268276
268649
|
function readLoopSafety(projectPath3) {
|
|
268277
268650
|
try {
|
|
@@ -268295,7 +268668,7 @@ function alreadyTripped(events, verdict) {
|
|
|
268295
268668
|
}
|
|
268296
268669
|
function appendEvent2(eventsPath3, event) {
|
|
268297
268670
|
mkdirSync46(dirname45(eventsPath3), { recursive: true });
|
|
268298
|
-
|
|
268671
|
+
appendFileSync18(eventsPath3, `${JSON.stringify(event)}
|
|
268299
268672
|
`, "utf8");
|
|
268300
268673
|
}
|
|
268301
268674
|
function applyCorrectionCircuitBreaker(projectPath3, slug3, eventsPath3, alertsPath, nowSec2 = Math.floor(Date.now() / 1e3)) {
|
|
@@ -268321,7 +268694,7 @@ function applyCorrectionCircuitBreaker(projectPath3, slug3, eventsPath3, alertsP
|
|
|
268321
268694
|
if (pauseWritten)
|
|
268322
268695
|
writeFileSync48(pauseMarker, alertMsg, "utf8");
|
|
268323
268696
|
mkdirSync46(dirname45(alertsPath), { recursive: true });
|
|
268324
|
-
|
|
268697
|
+
appendFileSync18(alertsPath, `${alertMsg}
|
|
268325
268698
|
`, "utf8");
|
|
268326
268699
|
appendEvent2(eventsPath3, {
|
|
268327
268700
|
type: "correction:circuit_breaker",
|
|
@@ -268341,7 +268714,7 @@ function applyCorrectionCircuitBreaker(projectPath3, slug3, eventsPath3, alertsP
|
|
|
268341
268714
|
|
|
268342
268715
|
// packages/cli/dist/commands/loop-run-once.js
|
|
268343
268716
|
init_dist();
|
|
268344
|
-
import { execFileSync as execFileSync23, spawn as spawn9, spawnSync as
|
|
268717
|
+
import { execFileSync as execFileSync23, spawn as spawn9, spawnSync as spawnSync13 } from "node:child_process";
|
|
268345
268718
|
import { lookup as lookup2 } from "node:dns/promises";
|
|
268346
268719
|
function announceReport(projectPath3, slug3, storyId, opener = (p) => {
|
|
268347
268720
|
try {
|
|
@@ -268487,7 +268860,7 @@ function writeCardSkipAlert(alertsPath, eventsPath3, cycleId, storyId, count) {
|
|
|
268487
268860
|
**Action**: investigate ${storyId} (it likely needs a smaller split, a spec fix, or manual delivery). Once addressed, remove it from \`.roll/loop/skip-cards.json\` (or just fix the card) to re-arm it.
|
|
268488
268861
|
`;
|
|
268489
268862
|
try {
|
|
268490
|
-
|
|
268863
|
+
appendFileSync19(alertsPath, `${msg6}
|
|
268491
268864
|
`, "utf8");
|
|
268492
268865
|
} catch {
|
|
268493
268866
|
}
|
|
@@ -268534,7 +268907,7 @@ function incrementConsecutiveFails(projectPath3, slug3, alertsPath, eventsPath3,
|
|
|
268534
268907
|
`;
|
|
268535
268908
|
try {
|
|
268536
268909
|
writeFileSync49(pauseMarker, alertMsg, "utf8");
|
|
268537
|
-
|
|
268910
|
+
appendFileSync19(alertsPath, `${alertMsg}
|
|
268538
268911
|
`, "utf8");
|
|
268539
268912
|
const ts2 = Date.now();
|
|
268540
268913
|
const bus = new EventBus();
|
|
@@ -268701,7 +269074,7 @@ function writeReviewerBlockedAlert(projectPath3, slug3, alertsPath, eventsPath3,
|
|
|
268701
269074
|
` : "") + `**Action**: ${fix}
|
|
268702
269075
|
`;
|
|
268703
269076
|
try {
|
|
268704
|
-
|
|
269077
|
+
appendFileSync19(alertsPath, `${msg6}
|
|
268705
269078
|
`, "utf8");
|
|
268706
269079
|
} catch {
|
|
268707
269080
|
}
|
|
@@ -268852,10 +269225,10 @@ async function loopRunOnceCommand(args) {
|
|
|
268852
269225
|
const headline = t(v3Catalog, lang10, "loop.egress_blocked", cycleId);
|
|
268853
269226
|
try {
|
|
268854
269227
|
const ts2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
268855
|
-
|
|
269228
|
+
appendFileSync19(alertsPath, `[${ts2}] ALERT ${headline}
|
|
268856
269229
|
`, "utf8");
|
|
268857
269230
|
for (const line of guardLines)
|
|
268858
|
-
|
|
269231
|
+
appendFileSync19(alertsPath, `[${ts2}] ALERT ${line}
|
|
268859
269232
|
`, "utf8");
|
|
268860
269233
|
} catch {
|
|
268861
269234
|
}
|
|
@@ -268880,7 +269253,7 @@ loop run-once: ${repoCheck.detail !== "" ? `(${repoCheck.detail})` : ""}
|
|
|
268880
269253
|
if (skillBody === null) {
|
|
268881
269254
|
const msg6 = `[${(/* @__PURE__ */ new Date()).toISOString()}] ALERT loop run-once: roll-loop SKILL.md not found (checked ROLL_LOOP_SKILL, .roll/skills/, skills/) \u2014 cycle ${cycleId} refused to start`;
|
|
268882
269255
|
try {
|
|
268883
|
-
|
|
269256
|
+
appendFileSync19(alertsPath, `${msg6}
|
|
268884
269257
|
`, "utf8");
|
|
268885
269258
|
} catch {
|
|
268886
269259
|
}
|
|
@@ -268914,7 +269287,7 @@ loop run-once: \u627E\u4E0D\u5230 roll-loop SKILL.md \u2014 \u62D2\u7EDD\u76F2\u
|
|
|
268914
269287
|
try {
|
|
268915
269288
|
await warnIfBinaryStale(rollHome(), rollVersion(), (msg6) => {
|
|
268916
269289
|
try {
|
|
268917
|
-
|
|
269290
|
+
appendFileSync19(alertsPath, `${msg6}
|
|
268918
269291
|
`, "utf8");
|
|
268919
269292
|
} catch {
|
|
268920
269293
|
}
|
|
@@ -269132,10 +269505,10 @@ function autoGc(projectPath3) {
|
|
|
269132
269505
|
}
|
|
269133
269506
|
}
|
|
269134
269507
|
}
|
|
269135
|
-
async function isOffline(
|
|
269508
|
+
async function isOffline(resolve12 = (h) => lookup2(h)) {
|
|
269136
269509
|
try {
|
|
269137
269510
|
await Promise.race([
|
|
269138
|
-
|
|
269511
|
+
resolve12("github.com"),
|
|
269139
269512
|
new Promise((_, rej) => {
|
|
269140
269513
|
const t2 = setTimeout(() => rej(new Error("dns timeout")), 1500);
|
|
269141
269514
|
if (typeof t2 === "object")
|
|
@@ -269152,7 +269525,7 @@ function isLoopPaused(projectPath3, slug3) {
|
|
|
269152
269525
|
}
|
|
269153
269526
|
function checkRepoPushable(projectPath3) {
|
|
269154
269527
|
const git4 = (args) => {
|
|
269155
|
-
const r =
|
|
269528
|
+
const r = spawnSync13("git", args, { cwd: projectPath3, encoding: "utf8" });
|
|
269156
269529
|
return { code: r.status ?? 1, stderr: r.stderr ?? "" };
|
|
269157
269530
|
};
|
|
269158
269531
|
const inside = git4(["rev-parse", "--git-dir"]);
|
|
@@ -269184,7 +269557,7 @@ function writeRepoAlert(alertsPath, eventsPath3, cycleId, result) {
|
|
|
269184
269557
|
**Action**: ${t(v3Catalog, lang10, "loop.no_remote")}
|
|
269185
269558
|
`;
|
|
269186
269559
|
try {
|
|
269187
|
-
|
|
269560
|
+
appendFileSync19(alertsPath, `${msg6}
|
|
269188
269561
|
`, "utf8");
|
|
269189
269562
|
} catch {
|
|
269190
269563
|
}
|
|
@@ -269201,10 +269574,10 @@ function writeRepoAlert(alertsPath, eventsPath3, cycleId, result) {
|
|
|
269201
269574
|
|
|
269202
269575
|
// packages/cli/dist/commands/offboard.js
|
|
269203
269576
|
init_dist();
|
|
269204
|
-
import { spawnSync as
|
|
269577
|
+
import { spawnSync as spawnSync14 } from "node:child_process";
|
|
269205
269578
|
import { existsSync as existsSync100, readFileSync as readFileSync94, realpathSync as realpathSync14, renameSync as renameSync18, rmSync as rmSync17, writeFileSync as writeFileSync50 } from "node:fs";
|
|
269206
269579
|
import { homedir as homedir28 } from "node:os";
|
|
269207
|
-
import { join as join104, resolve as
|
|
269580
|
+
import { join as join104, resolve as resolve10 } from "node:path";
|
|
269208
269581
|
function pal5() {
|
|
269209
269582
|
const noColor2 = (process.env["NO_COLOR"] ?? "") !== "";
|
|
269210
269583
|
return noColor2 ? { RED: "", GREEN: "", YELLOW: "", CYAN: "", BOLD: "", NC: "" } : {
|
|
@@ -269250,13 +269623,13 @@ function loopInCycle2() {
|
|
|
269250
269623
|
function runLaunchctl(args) {
|
|
269251
269624
|
const readOnly = /* @__PURE__ */ new Set(["print", "print-disabled", "list", "version", "dumpstate", "examine"]);
|
|
269252
269625
|
if (args[0] !== void 0 && readOnly.has(args[0])) {
|
|
269253
|
-
return
|
|
269626
|
+
return spawnSync14("launchctl", args, { stdio: "inherit" }).status ?? 1;
|
|
269254
269627
|
}
|
|
269255
269628
|
const canonical = join104(homedir28(), "Library", "LaunchAgents");
|
|
269256
269629
|
const launchdDir = process.env["_LAUNCHD_DIR"] ?? canonical;
|
|
269257
269630
|
if (launchdDir !== canonical)
|
|
269258
269631
|
return 0;
|
|
269259
|
-
return
|
|
269632
|
+
return spawnSync14("launchctl", args, { stdio: "inherit" }).status ?? 1;
|
|
269260
269633
|
}
|
|
269261
269634
|
var SECTIONS = ["files_merged", "files_created", "dirs_created", "gitignore_entries_added", "launchd_plists_installed"];
|
|
269262
269635
|
function parseChangeset(text2) {
|
|
@@ -269308,7 +269681,7 @@ function writeFileAtomic2(path, text2) {
|
|
|
269308
269681
|
}
|
|
269309
269682
|
}
|
|
269310
269683
|
function resolveChangesetItem(projectDir, item) {
|
|
269311
|
-
return item.startsWith("/") ?
|
|
269684
|
+
return item.startsWith("/") ? resolve10(item) : resolve10(projectDir, item);
|
|
269312
269685
|
}
|
|
269313
269686
|
var HELP3 = `Usage: roll offboard [--confirm]
|
|
269314
269687
|
Preview (default) or apply (--confirm) the removal of every
|
|
@@ -269329,7 +269702,7 @@ function offboardCommand(args) {
|
|
|
269329
269702
|
}
|
|
269330
269703
|
let projectDir;
|
|
269331
269704
|
try {
|
|
269332
|
-
projectDir = realpathSync14(
|
|
269705
|
+
projectDir = realpathSync14(resolve10(process.cwd()));
|
|
269333
269706
|
} catch {
|
|
269334
269707
|
projectDir = process.cwd();
|
|
269335
269708
|
}
|
|
@@ -271799,7 +272172,7 @@ ${c("dim", "\u2192 Running the golden-path showcase (real models; its verdict do
|
|
|
271799
272172
|
// packages/cli/dist/commands/setup.js
|
|
271800
272173
|
init_dist();
|
|
271801
272174
|
init_render();
|
|
271802
|
-
import { spawnSync as
|
|
272175
|
+
import { spawnSync as spawnSync16 } from "node:child_process";
|
|
271803
272176
|
import { existsSync as existsSync107, lstatSync as lstatSync6, mkdirSync as mkdirSync52, readFileSync as readFileSync101, readdirSync as readdirSync42, readlinkSync as readlinkSync3, statSync as statSync36 } from "node:fs";
|
|
271804
272177
|
import { join as join111 } from "node:path";
|
|
271805
272178
|
function err13(line) {
|
|
@@ -271906,13 +272279,13 @@ function runSetupStep(watch, fn) {
|
|
|
271906
272279
|
return before === after ? "unchanged" : "changed";
|
|
271907
272280
|
}
|
|
271908
272281
|
function ensureHooksPath(repoPath) {
|
|
271909
|
-
const inRepo =
|
|
272282
|
+
const inRepo = spawnSync16("git", ["-C", repoPath, "rev-parse", "--git-dir"], { stdio: "ignore" }).status === 0;
|
|
271910
272283
|
if (!inRepo)
|
|
271911
272284
|
return;
|
|
271912
|
-
const cur =
|
|
272285
|
+
const cur = spawnSync16("git", ["-C", repoPath, "config", "core.hooksPath"], { encoding: "utf8" });
|
|
271913
272286
|
const current = cur.status === 0 ? (cur.stdout ?? "").trim() : "";
|
|
271914
272287
|
if (current === "" || current === ".git/hooks") {
|
|
271915
|
-
|
|
272288
|
+
spawnSync16("git", ["-C", repoPath, "config", "core.hooksPath", "hooks"], { stdio: "ignore" });
|
|
271916
272289
|
}
|
|
271917
272290
|
}
|
|
271918
272291
|
function peerEnsureStateDir() {
|
|
@@ -271935,7 +272308,7 @@ function submoduleGuard() {
|
|
|
271935
272308
|
empty = true;
|
|
271936
272309
|
}
|
|
271937
272310
|
if (hasGit && hasMods && empty) {
|
|
271938
|
-
|
|
272311
|
+
spawnSync16("git", ["submodule", "update", "--init", "--recursive", "--quiet"], {
|
|
271939
272312
|
cwd: pkg,
|
|
271940
272313
|
stdio: "ignore"
|
|
271941
272314
|
});
|
|
@@ -272116,9 +272489,9 @@ function setupCommand(args) {
|
|
|
272116
272489
|
init_showcase2();
|
|
272117
272490
|
|
|
272118
272491
|
// packages/cli/dist/commands/test.js
|
|
272119
|
-
import { spawnSync as
|
|
272120
|
-
import { appendFileSync as
|
|
272121
|
-
import { dirname as dirname50, join as join112, resolve as
|
|
272492
|
+
import { spawnSync as spawnSync17 } from "node:child_process";
|
|
272493
|
+
import { appendFileSync as appendFileSync20, existsSync as existsSync108, mkdirSync as mkdirSync53, readFileSync as readFileSync102, rmSync as rmSync19, writeFileSync as writeFileSync56 } from "node:fs";
|
|
272494
|
+
import { dirname as dirname50, join as join112, resolve as resolve11 } from "node:path";
|
|
272122
272495
|
function pal7() {
|
|
272123
272496
|
const noColor2 = (process.env["NO_COLOR"] ?? "") !== "";
|
|
272124
272497
|
return noColor2 ? { CYAN: "", GREEN: "", YELLOW: "", RED: "", NC: "" } : { CYAN: "\x1B[0;36m", GREEN: "\x1B[0;32m", YELLOW: "\x1B[0;33m", RED: "\x1B[0;31m", NC: "\x1B[0m" };
|
|
@@ -272138,7 +272511,7 @@ function currentEvidenceFrame() {
|
|
|
272138
272511
|
const raw = (process.env["ROLL_RUN_DIR"] ?? "").trim();
|
|
272139
272512
|
if (raw === "")
|
|
272140
272513
|
return null;
|
|
272141
|
-
const runDir =
|
|
272514
|
+
const runDir = resolve11(raw);
|
|
272142
272515
|
if (!existsSync108(runDir))
|
|
272143
272516
|
return null;
|
|
272144
272517
|
const frame = {
|
|
@@ -272175,7 +272548,7 @@ function appendRollTestEvidence(frame, cmd, argv, status2, stdout, stderr) {
|
|
|
272175
272548
|
try {
|
|
272176
272549
|
const ts2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
272177
272550
|
const command = [cmd, ...argv];
|
|
272178
|
-
|
|
272551
|
+
appendFileSync20(join112(frame.evidenceDir, "roll-test-output.log"), [
|
|
272179
272552
|
`===== roll test ${ts2} exit=${status2} =====`,
|
|
272180
272553
|
`$ ${command.join(" ")}`,
|
|
272181
272554
|
"--- stdout ---",
|
|
@@ -272184,7 +272557,7 @@ function appendRollTestEvidence(frame, cmd, argv, status2, stdout, stderr) {
|
|
|
272184
272557
|
stderr,
|
|
272185
272558
|
""
|
|
272186
272559
|
].join("\n"), "utf8");
|
|
272187
|
-
|
|
272560
|
+
appendFileSync20(join112(frame.evidenceDir, "roll-test-summary.txt"), JSON.stringify({
|
|
272188
272561
|
ts: ts2,
|
|
272189
272562
|
command,
|
|
272190
272563
|
exitCode: status2,
|
|
@@ -272264,7 +272637,7 @@ function resetReleaseLock() {
|
|
|
272264
272637
|
}
|
|
272265
272638
|
function runForward(cmd, argv) {
|
|
272266
272639
|
const frame = currentEvidenceFrame();
|
|
272267
|
-
const r =
|
|
272640
|
+
const r = spawnSync17(cmd, argv, { encoding: "utf8", env: childEnvForEvidence(frame) });
|
|
272268
272641
|
const stdout = typeof r.stdout === "string" ? r.stdout : "";
|
|
272269
272642
|
const stderr = typeof r.stderr === "string" ? r.stderr : "";
|
|
272270
272643
|
const status2 = r.status ?? 1;
|
|
@@ -272282,7 +272655,7 @@ function ensureSkillsSubmoduleReady() {
|
|
|
272282
272655
|
if (existsSync108(required2))
|
|
272283
272656
|
return true;
|
|
272284
272657
|
if (existsSync108(join112(pkg, ".git")) && existsSync108(join112(pkg, ".gitmodules"))) {
|
|
272285
|
-
|
|
272658
|
+
spawnSync17("git", ["submodule", "update", "--init", "--recursive", "--quiet", "skills"], {
|
|
272286
272659
|
cwd: pkg,
|
|
272287
272660
|
stdio: "ignore"
|
|
272288
272661
|
});
|
|
@@ -272788,7 +273161,7 @@ function tuneCommand(argv) {
|
|
|
272788
273161
|
|
|
272789
273162
|
// packages/cli/dist/commands/update.js
|
|
272790
273163
|
init_dist();
|
|
272791
|
-
import { spawnSync as
|
|
273164
|
+
import { spawnSync as spawnSync18 } from "node:child_process";
|
|
272792
273165
|
import { existsSync as existsSync111, mkdtempSync as mkdtempSync9, readFileSync as readFileSync105, rmSync as rmSync20 } from "node:fs";
|
|
272793
273166
|
import { tmpdir as tmpdir11 } from "node:os";
|
|
272794
273167
|
import { join as join116 } from "node:path";
|
|
@@ -272829,7 +273202,7 @@ function m6(key, ...args) {
|
|
|
272829
273202
|
return t(v2Catalog, msgLang10(), key, ...args);
|
|
272830
273203
|
}
|
|
272831
273204
|
function runForward2(cmd, argv) {
|
|
272832
|
-
const r =
|
|
273205
|
+
const r = spawnSync18(cmd, argv, { encoding: "utf8" });
|
|
272833
273206
|
if (typeof r.stdout === "string" && r.stdout !== "")
|
|
272834
273207
|
process.stdout.write(r.stdout);
|
|
272835
273208
|
if (typeof r.stderr === "string" && r.stderr !== "")
|
|
@@ -272840,7 +273213,7 @@ function resolveRemoteVersion() {
|
|
|
272840
273213
|
const pinned = process.env["ROLL_VERSION"];
|
|
272841
273214
|
if (pinned !== void 0 && pinned !== "")
|
|
272842
273215
|
return pinned;
|
|
272843
|
-
const r =
|
|
273216
|
+
const r = spawnSync18("curl", ["-fsSL", "-H", "Accept: application/vnd.github+json", "https://api.github.com/repos/seanyao/roll/releases/latest"], { encoding: "utf8" });
|
|
272844
273217
|
let latest = "";
|
|
272845
273218
|
if (r.status === 0 && typeof r.stdout === "string") {
|
|
272846
273219
|
const mm = /"tag_name"\s*:\s*"([^"]*)"/.exec(r.stdout);
|
|
@@ -272865,7 +273238,7 @@ function downloadAndInstallCurl(tag) {
|
|
|
272865
273238
|
}
|
|
272866
273239
|
info5("[roll] Extracting ...");
|
|
272867
273240
|
const extractDir = join116(tmpDir, "extract");
|
|
272868
|
-
|
|
273241
|
+
spawnSync18("mkdir", ["-p", extractDir], { stdio: "ignore" });
|
|
272869
273242
|
const ex = runForward2("tar", [
|
|
272870
273243
|
"-xzf",
|
|
272871
273244
|
join116(tmpDir, "roll.tar.gz"),
|
|
@@ -272883,16 +273256,16 @@ function downloadAndInstallCurl(tag) {
|
|
|
272883
273256
|
}
|
|
272884
273257
|
}
|
|
272885
273258
|
function checkInstalledVersionOrRetry() {
|
|
272886
|
-
const expected = (
|
|
272887
|
-
const pkgRoot = (
|
|
273259
|
+
const expected = (spawnSync18("npm", ["view", "@seanyao/roll", "version"], { encoding: "utf8" }).stdout ?? "").trim();
|
|
273260
|
+
const pkgRoot = (spawnSync18("npm", ["root", "-g"], { encoding: "utf8" }).stdout ?? "").trim();
|
|
272888
273261
|
const installedTree = join116(pkgRoot, "@seanyao", "roll");
|
|
272889
273262
|
const installed = treeVersion(installedTree);
|
|
272890
273263
|
if (expected === "" || installed === "")
|
|
272891
273264
|
return;
|
|
272892
273265
|
if (installed !== expected) {
|
|
272893
273266
|
warn5(m6("update.version_mismatch", installed, expected));
|
|
272894
|
-
|
|
272895
|
-
|
|
273267
|
+
spawnSync18("npm", ["cache", "clean", "--force"], { stdio: "ignore" });
|
|
273268
|
+
spawnSync18("npm", ["install", "-g", "@seanyao/roll@latest"], { stdio: "ignore" });
|
|
272896
273269
|
const after = treeVersion(installedTree);
|
|
272897
273270
|
if (after !== "" && after !== expected)
|
|
272898
273271
|
warn5(m6("update.still_mismatch", after));
|
|
@@ -273102,7 +273475,7 @@ function registerAll() {
|
|
|
273102
273475
|
});
|
|
273103
273476
|
registerPorted("init", initCommand, { help: "Usage: roll init [--auto|--repair|--apply]\n Diagnose this project and route to scaffold, PRD design, existing-codebase onboard, repair, migration, or roll status.\n --auto: apply deterministic fresh-project scaffolding in non-interactive runs.\n --repair: repair partial Roll markers only.\n --apply: validate and apply a reviewed existing-codebase onboard plan.\n\u8BCA\u65AD\u9879\u76EE\u5E76\u8DEF\u7531\u5230\u9AA8\u67B6\u3001PRD \u8BBE\u8BA1\u3001\u5DF2\u6709\u4EE3\u7801\u5E93\u63A5\u5165\u3001\u4FEE\u590D\u3001\u8FC1\u79FB\u6216 roll status\u3002\n --apply\uFF1A\u6821\u9A8C\u5E76\u5E94\u7528\u5DF2\u5BA1\u9605\u7684\u5DF2\u6709\u4EE3\u7801\u5E93\u63A5\u5165\u8BA1\u5212\u3002" });
|
|
273104
273477
|
registerPorted("next", nextCommand, { help: NEXT_USAGE });
|
|
273105
|
-
registerPorted("design", designCommand, { help: 'Usage: roll design [--from-file <path> | "<requirement>"] [--agent <name>] [--verbose|--raw]\n Launch $roll-design interactively
|
|
273478
|
+
registerPorted("design", designCommand, { help: 'Usage: roll design [--from-file <path> | "<requirement>"] [--agent <name>] [--verbose|--raw]\n Launch $roll-design interactively with bounded live progress, card-created events, quiet heartbeats, and final handoff; --verbose streams lower-priority normalized activity; --raw streams raw child output live.\n\u4EA4\u4E92\u5F0F\u542F\u52A8 $roll-design\uFF1B\u9ED8\u8BA4\u5B9E\u65F6\u663E\u793A\u6709\u754C\u8FDB\u5C55\u3001\u5EFA\u5361\u4E8B\u4EF6\u3001\u9759\u9ED8\u5FC3\u8DF3\u548C\u6700\u7EC8\u4EA4\u4ED8\uFF1B--verbose \u663E\u793A\u66F4\u591A\u89C4\u8303\u5316\u6D3B\u52A8\uFF1B--raw \u5B9E\u65F6\u8F93\u51FA\u539F\u59CB\u6D41\u3002' });
|
|
273106
273479
|
registerPorted("offboard", removedTopLevel("offboard"));
|
|
273107
273480
|
registerPorted("setup", (args) => {
|
|
273108
273481
|
if (args[0] === "skills") {
|
|
@@ -273114,7 +273487,7 @@ function registerAll() {
|
|
|
273114
273487
|
if (args[0] === "offboard")
|
|
273115
273488
|
return offboardCommand(args.slice(1));
|
|
273116
273489
|
return setupCommand(args);
|
|
273117
|
-
}, { help: "Usage: roll setup [skills
|
|
273490
|
+
}, { help: "Usage: roll setup [-f|--force] [--reselect]\n roll setup skills [args...]\n roll setup offboard [args...]\n Install or re-sync Roll conventions/templates for this machine; use -f to force refresh.\n\u672C\u673A\u5B89\u88C5\u6216\u91CD\u65B0\u540C\u6B65 Roll \u6A21\u677F\u4E0E\u7EA6\u5B9A\uFF1B-f \u5F3A\u5236\u5237\u65B0\u3002" });
|
|
273118
273491
|
registerPorted("ci", (args) => {
|
|
273119
273492
|
if (args.includes("--wait"))
|
|
273120
273493
|
return ciWaitCommand(args);
|