@seanyao/roll 3.611.3 → 3.612.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/README.md +1 -1
- package/dist/roll.mjs +555 -235
- package/package.json +2 -1
package/dist/roll.mjs
CHANGED
|
@@ -1528,12 +1528,12 @@ function appendRowsToTable(content, rows) {
|
|
|
1528
1528
|
}
|
|
1529
1529
|
}
|
|
1530
1530
|
if (sepIdx === -1) {
|
|
1531
|
-
const
|
|
1531
|
+
const tail2 = rows.join("\n");
|
|
1532
1532
|
if (content !== "" && !content.endsWith("\n"))
|
|
1533
1533
|
return `${content}
|
|
1534
|
-
${
|
|
1534
|
+
${tail2}
|
|
1535
1535
|
`;
|
|
1536
|
-
return `${content}${
|
|
1536
|
+
return `${content}${tail2}
|
|
1537
1537
|
`;
|
|
1538
1538
|
}
|
|
1539
1539
|
let insertAt = sepIdx + 1;
|
|
@@ -4575,14 +4575,14 @@ function appendBacklogRow(content, row2) {
|
|
|
4575
4575
|
}
|
|
4576
4576
|
const at = anchor !== -1 ? anchor : lastTableRow;
|
|
4577
4577
|
if (at === -1) {
|
|
4578
|
-
const
|
|
4578
|
+
const tail2 = `
|
|
4579
4579
|
## Epic: ${row2.epic}
|
|
4580
4580
|
|
|
4581
4581
|
| ID | Description | Status |
|
|
4582
4582
|
|----|----|----|
|
|
4583
4583
|
${line}
|
|
4584
4584
|
`;
|
|
4585
|
-
return { content: content.replace(/\n*$/, "\n") +
|
|
4585
|
+
return { content: content.replace(/\n*$/, "\n") + tail2, appended: true };
|
|
4586
4586
|
}
|
|
4587
4587
|
lines2.splice(at + 1, 0, line);
|
|
4588
4588
|
return { content: lines2.join("\n"), appended: true };
|
|
@@ -5136,8 +5136,8 @@ function parseAlertLogTail(body, n) {
|
|
|
5136
5136
|
continue;
|
|
5137
5137
|
}
|
|
5138
5138
|
}
|
|
5139
|
-
const
|
|
5140
|
-
return
|
|
5139
|
+
const tail2 = n >= rows.length ? rows : rows.slice(rows.length - n);
|
|
5140
|
+
return tail2.reverse();
|
|
5141
5141
|
}
|
|
5142
5142
|
|
|
5143
5143
|
// packages/core/dist/loop/ci-loop.js
|
|
@@ -5650,12 +5650,12 @@ function renderRebaseAttempts(timestamps) {
|
|
|
5650
5650
|
var DEAD_TICK_NOTES = /* @__PURE__ */ new Set(["gh_error", "lock_fail"]);
|
|
5651
5651
|
function deadTickVerdict(input) {
|
|
5652
5652
|
const n = input.threshold ?? 5;
|
|
5653
|
-
const
|
|
5653
|
+
const tail2 = input.recentNotes.slice(-n);
|
|
5654
5654
|
const last = input.recentNotes[input.recentNotes.length - 1];
|
|
5655
5655
|
const lastAbnormal = last !== void 0 && DEAD_TICK_NOTES.has(last);
|
|
5656
5656
|
if (input.alreadyAlerted)
|
|
5657
5657
|
return lastAbnormal ? null : "recovered";
|
|
5658
|
-
if (
|
|
5658
|
+
if (tail2.length >= n && tail2.every((t2) => DEAD_TICK_NOTES.has(t2)))
|
|
5659
5659
|
return "alert";
|
|
5660
5660
|
return null;
|
|
5661
5661
|
}
|
|
@@ -6310,15 +6310,15 @@ function boundTranscript(raw, opts = {}) {
|
|
|
6310
6310
|
return { text: raw, truncated: false, totalLen, shownLen: totalLen };
|
|
6311
6311
|
}
|
|
6312
6312
|
const head = raw.slice(0, headLen);
|
|
6313
|
-
const
|
|
6314
|
-
const elided = totalLen - head.length -
|
|
6313
|
+
const tail2 = raw.slice(totalLen - tailLen);
|
|
6314
|
+
const elided = totalLen - head.length - tail2.length;
|
|
6315
6315
|
const marker = `
|
|
6316
6316
|
|
|
6317
6317
|
\u2026 \u4E2D\u95F4\u7701\u7565 ${elided} \u5B57\u7B26 / ${elided} chars elided\uFF08\u5B8C\u6574\u539F\u4EF6\u89C1\u4E0B\u65B9\u7D22\u5F15 \xB7 full log at the indexed path\uFF09\u2026
|
|
6318
6318
|
|
|
6319
6319
|
`;
|
|
6320
|
-
const text = head + marker +
|
|
6321
|
-
return { text, truncated: true, totalLen, shownLen: head.length +
|
|
6320
|
+
const text = head + marker + tail2;
|
|
6321
|
+
return { text, truncated: true, totalLen, shownLen: head.length + tail2.length };
|
|
6322
6322
|
}
|
|
6323
6323
|
|
|
6324
6324
|
// packages/core/dist/policy/engine.js
|
|
@@ -7048,6 +7048,7 @@ function planShip(facts) {
|
|
|
7048
7048
|
var HEADING = /^(#{2,3})\s+(.*)$/;
|
|
7049
7049
|
var STORY_ID = /\b((?:US|FIX|REFACTOR)-[A-Z0-9]+(?:-[A-Z0-9]+)*?-?\d+[a-z]?)\b/;
|
|
7050
7050
|
var AC_OPEN = /^\*\*AC:\*\*\s*$/;
|
|
7051
|
+
var AC_HEADING = /^#{2,4}\s+(?:Acceptance Criteria|验收标准)\s*$/i;
|
|
7051
7052
|
var ITEM = /^- \[([ xX])\]\s?(.*)$/;
|
|
7052
7053
|
var CONTINUATION = /^\s{2,}(\S.*)$/;
|
|
7053
7054
|
function parseAcBlocks(markdown) {
|
|
@@ -7065,6 +7066,11 @@ function parseAcBlocks(markdown) {
|
|
|
7065
7066
|
};
|
|
7066
7067
|
for (const raw of lines2) {
|
|
7067
7068
|
const line = raw.replace(/\r$/, "");
|
|
7069
|
+
if (AC_HEADING.test(line)) {
|
|
7070
|
+
closeBlock();
|
|
7071
|
+
block = [];
|
|
7072
|
+
continue;
|
|
7073
|
+
}
|
|
7068
7074
|
const h = HEADING.exec(line);
|
|
7069
7075
|
if (h) {
|
|
7070
7076
|
closeBlock();
|
|
@@ -7423,6 +7429,17 @@ function selfCaptureBlock(refs) {
|
|
|
7423
7429
|
${figs}
|
|
7424
7430
|
</section>`;
|
|
7425
7431
|
}
|
|
7432
|
+
function captureSkipBlock(skips) {
|
|
7433
|
+
if (skips === void 0 || skips.length === 0)
|
|
7434
|
+
return "";
|
|
7435
|
+
const rows = skips.map((s) => {
|
|
7436
|
+
const json = JSON.stringify({ kind: s.kind, out: s.out, taken: false, skipped: s.skipped }, null, 2);
|
|
7437
|
+
return `<details class="capture-skip"><summary>${bi("Capture skip", "\u622A\u56FE\u8DF3\u8FC7")} \xB7 ${esc(s.kind)}</summary><pre data-machine-capture-skip="true">${esc(json)}</pre></details>`;
|
|
7438
|
+
}).join("\n");
|
|
7439
|
+
return `<section class="capture-skips"><h2>${bi("Capture skip", "\u622A\u56FE\u8DF3\u8FC7")}</h2>
|
|
7440
|
+
${rows}
|
|
7441
|
+
</section>`;
|
|
7442
|
+
}
|
|
7426
7443
|
function evidenceIndexBlock(items, beforeAfter, selfCaptures) {
|
|
7427
7444
|
const rows = [];
|
|
7428
7445
|
const row2 = (ref) => {
|
|
@@ -7597,6 +7614,9 @@ details.selfscore ul { margin:8px 0 4px; padding-left:18px; }
|
|
|
7597
7614
|
.selfscore-badge { display:inline-block; border:1px solid var(--line); border-radius:999px; padding:1px 8px; font-size:12px; font-weight:600; }
|
|
7598
7615
|
.selfscore-good { color:var(--pass); } .selfscore-ok { color:var(--warn); } .selfscore-regression { color:var(--fail); }
|
|
7599
7616
|
.selfscore-dims, .selfscore-trend { color:var(--muted); font-size:12.5px; margin-top:4px; }
|
|
7617
|
+
.capture-skip { margin:8px 0; border:1px solid var(--line); border-radius:6px; padding:6px 12px; background:rgba(127,110,70,.04); }
|
|
7618
|
+
.capture-skip summary { cursor:pointer; color:var(--muted); font-size:12.5px; font-weight:600; }
|
|
7619
|
+
.capture-skip pre { white-space:pre-wrap; font-size:12px; }
|
|
7600
7620
|
details.tech { margin:8px 0 2px; border:1px solid var(--line); border-radius:6px; padding:6px 12px; background:rgba(127,110,70,.04); }
|
|
7601
7621
|
details.tech summary { cursor:pointer; color:var(--muted); font-size:12.5px; font-weight:600; }
|
|
7602
7622
|
details.tech[open] summary { margin-bottom:6px; }
|
|
@@ -7640,6 +7660,7 @@ ${cardContextBlock(input.context)}
|
|
|
7640
7660
|
${items.map(acSection).join("\n")}
|
|
7641
7661
|
${beforeAfterBlock(input.beforeAfter)}
|
|
7642
7662
|
${selfCaptureBlock(input.selfCaptures)}
|
|
7663
|
+
${captureSkipBlock(input.captureSkips)}
|
|
7643
7664
|
${processTraceBlock(input.process)}
|
|
7644
7665
|
${closing}
|
|
7645
7666
|
<footer>Roll \xB7 ${bi("Acceptance Evidence", "\u9A8C\u6536\u8BC1\u636E")} \xB7 <code>${esc(input.storyId)}</code></footer>
|
|
@@ -7769,6 +7790,8 @@ function runConsistencyAudit(s) {
|
|
|
7769
7790
|
}
|
|
7770
7791
|
if (!probe.report) {
|
|
7771
7792
|
add("done-missing-attest", "fail", row2.id, `Done without an acceptance report${probe.acMap ? "" : " (no ac-map either)"} \u2014 attest_evidence anchor`);
|
|
7793
|
+
} else if (probe.acMap && !(probe.visualEvidence ?? false) && !(probe.machineSkip ?? false)) {
|
|
7794
|
+
add("done-attest-no-visual", "warn", row2.id, "Done acceptance evidence has a report/ac-map but no screenshot and no machine-generated capture skip \u2014 visual evidence floor (FIX-258)");
|
|
7772
7795
|
}
|
|
7773
7796
|
}
|
|
7774
7797
|
for (const row2 of s.runs) {
|
|
@@ -9024,7 +9047,9 @@ async function collectEvidence(opts) {
|
|
|
9024
9047
|
deploy,
|
|
9025
9048
|
test_pass: testPass,
|
|
9026
9049
|
screenshots: listDir("screenshots", /\.png$/i),
|
|
9027
|
-
texts: listDir("evidence", /\.(txt|log)$/i)
|
|
9050
|
+
texts: listDir("evidence", /\.(txt|log)$/i),
|
|
9051
|
+
captures: [...opts.captures ?? []],
|
|
9052
|
+
capture_command: opts.captureCommand ?? null
|
|
9028
9053
|
};
|
|
9029
9054
|
}
|
|
9030
9055
|
function writeEvidenceJson(manifest, runDir) {
|
|
@@ -9035,7 +9060,7 @@ function writeEvidenceJson(manifest, runDir) {
|
|
|
9035
9060
|
}
|
|
9036
9061
|
|
|
9037
9062
|
// packages/infra/dist/screenshot.js
|
|
9038
|
-
import { existsSync as existsSync10, mkdirSync as mkdirSync7, statSync as statSync5 } from "node:fs";
|
|
9063
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync7, rmSync as rmSync4, statSync as statSync5 } from "node:fs";
|
|
9039
9064
|
import { execFile as execFile6 } from "node:child_process";
|
|
9040
9065
|
import { promisify as promisify6 } from "node:util";
|
|
9041
9066
|
import { join as join6 } from "node:path";
|
|
@@ -9105,6 +9130,8 @@ function fileNonEmpty(p) {
|
|
|
9105
9130
|
}
|
|
9106
9131
|
}
|
|
9107
9132
|
var DEFAULT_REGION = "0,0,1280,800";
|
|
9133
|
+
var TERMINAL_DONE_TIMEOUT_MS = 12e4;
|
|
9134
|
+
var TERMINAL_DONE_POLL_MS = 100;
|
|
9108
9135
|
function parseCaptureMarker(line) {
|
|
9109
9136
|
const m7 = /^::roll-capture\s+(before|after|gate)\s+(web|mobile-ios|mobile-android|terminal)\s+([A-Za-z0-9_.-]+)(?:\s+(.+))?\s*$/.exec(line.trim());
|
|
9110
9137
|
if (m7 === null)
|
|
@@ -9147,19 +9174,66 @@ function parseRegion(region) {
|
|
|
9147
9174
|
return null;
|
|
9148
9175
|
return { x, y, w, h };
|
|
9149
9176
|
}
|
|
9150
|
-
function terminalOpenScript(line, r) {
|
|
9151
|
-
const esc6 = line
|
|
9177
|
+
function terminalOpenScript(line, r, title) {
|
|
9178
|
+
const esc6 = appleScriptString(line);
|
|
9179
|
+
const setTitle = title === void 0 ? [] : [` set custom title of front window to "${appleScriptString(title)}"`];
|
|
9152
9180
|
return [
|
|
9153
9181
|
'tell application "Terminal"',
|
|
9154
9182
|
" activate",
|
|
9155
9183
|
` do script "${esc6}"`,
|
|
9184
|
+
...setTitle,
|
|
9156
9185
|
" delay 1.5",
|
|
9157
9186
|
` set bounds of front window to {${r.x}, ${r.y}, ${r.x + r.w}, ${r.y + r.h}}`,
|
|
9158
9187
|
"end tell"
|
|
9159
9188
|
].join("\n");
|
|
9160
9189
|
}
|
|
9161
|
-
function terminalCloseScript() {
|
|
9162
|
-
|
|
9190
|
+
function terminalCloseScript(title) {
|
|
9191
|
+
if (title === void 0)
|
|
9192
|
+
return 'tell application "Terminal" to close front window saving no';
|
|
9193
|
+
const esc6 = appleScriptString(title);
|
|
9194
|
+
return [
|
|
9195
|
+
'tell application "Terminal"',
|
|
9196
|
+
" repeat with w in windows",
|
|
9197
|
+
` if custom title of w is "${esc6}" then`,
|
|
9198
|
+
" close w saving no",
|
|
9199
|
+
" exit repeat",
|
|
9200
|
+
" end if",
|
|
9201
|
+
" end repeat",
|
|
9202
|
+
"end tell"
|
|
9203
|
+
].join("\n");
|
|
9204
|
+
}
|
|
9205
|
+
function shellQuote(value) {
|
|
9206
|
+
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
9207
|
+
}
|
|
9208
|
+
function appleScriptString(value) {
|
|
9209
|
+
return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
9210
|
+
}
|
|
9211
|
+
function terminalWindowTitle(out3) {
|
|
9212
|
+
const safe = out3.replace(/[^A-Za-z0-9_.-]+/g, "-");
|
|
9213
|
+
return `roll-attest-${safe.slice(Math.max(0, safe.length - 80))}`;
|
|
9214
|
+
}
|
|
9215
|
+
function terminalCommandWithDoneFile(line, doneFile) {
|
|
9216
|
+
const done = shellQuote(doneFile);
|
|
9217
|
+
return [
|
|
9218
|
+
`(${line})`,
|
|
9219
|
+
"__roll_status=$?",
|
|
9220
|
+
`printf '%s' "$__roll_status" > ${done}`,
|
|
9221
|
+
'exit "$__roll_status"'
|
|
9222
|
+
].join("; ");
|
|
9223
|
+
}
|
|
9224
|
+
function terminalDoneWaitScript(doneFile) {
|
|
9225
|
+
const attempts = Math.ceil(TERMINAL_DONE_TIMEOUT_MS / TERMINAL_DONE_POLL_MS);
|
|
9226
|
+
const sleepSeconds = String(TERMINAL_DONE_POLL_MS / 1e3);
|
|
9227
|
+
const done = shellQuote(doneFile);
|
|
9228
|
+
return `i=0; while [ ! -f ${done} ]; do if [ "$i" -ge ${attempts} ]; then exit 1; fi; i=$((i + 1)); sleep ${sleepSeconds}; done`;
|
|
9229
|
+
}
|
|
9230
|
+
async function waitForTerminalCommandExit(doneFile, run) {
|
|
9231
|
+
const waited = await run("sh", ["-lc", terminalDoneWaitScript(doneFile)]);
|
|
9232
|
+
try {
|
|
9233
|
+
rmSync4(doneFile, { force: true });
|
|
9234
|
+
} catch {
|
|
9235
|
+
}
|
|
9236
|
+
return waited.code === 0;
|
|
9163
9237
|
}
|
|
9164
9238
|
async function captureScreenshot(req, deps = {}) {
|
|
9165
9239
|
const run = deps.run ?? defaultRun2;
|
|
@@ -9197,8 +9271,8 @@ async function captureScreenshot(req, deps = {}) {
|
|
|
9197
9271
|
return skip("ROLL_ATTEST_NO_TERMINAL=1");
|
|
9198
9272
|
if (platform3 !== "darwin")
|
|
9199
9273
|
return skip("not macOS");
|
|
9200
|
-
const
|
|
9201
|
-
if (containsSecret(
|
|
9274
|
+
const rawLine = req.tmux !== void 0 && req.tmux !== "" ? `tmux attach -t ${req.tmux}` : req.command ?? "";
|
|
9275
|
+
if (containsSecret(rawLine))
|
|
9202
9276
|
return skip("secret in capture command \u2014 redact & reshoot");
|
|
9203
9277
|
const gui = await run("launchctl", ["managername"]);
|
|
9204
9278
|
if (gui.code !== 0 || !gui.stdout.includes("Aqua"))
|
|
@@ -9206,15 +9280,34 @@ async function captureScreenshot(req, deps = {}) {
|
|
|
9206
9280
|
const rect = parseRegion(req.region ?? DEFAULT_REGION);
|
|
9207
9281
|
if (rect === null)
|
|
9208
9282
|
return skip("bad region");
|
|
9209
|
-
const
|
|
9283
|
+
const commandDoneFile = req.tmux === void 0 && req.command !== void 0 && req.command !== "" ? `${req.out}.done` : void 0;
|
|
9284
|
+
if (commandDoneFile !== void 0) {
|
|
9285
|
+
try {
|
|
9286
|
+
rmSync4(commandDoneFile, { force: true });
|
|
9287
|
+
} catch {
|
|
9288
|
+
}
|
|
9289
|
+
}
|
|
9290
|
+
const line = commandDoneFile !== void 0 ? terminalCommandWithDoneFile(rawLine, commandDoneFile) : rawLine;
|
|
9291
|
+
const windowTitle = terminalWindowTitle(req.out);
|
|
9292
|
+
const opened = await run("osascript", ["-e", terminalOpenScript(line, rect, windowTitle)]);
|
|
9210
9293
|
if (opened.code !== 0)
|
|
9211
9294
|
return skip("osascript Terminal open failed");
|
|
9212
9295
|
const shot = await run("screencapture", ["-x", "-R", req.region ?? DEFAULT_REGION, req.out]);
|
|
9213
9296
|
if (shot.code !== 0) {
|
|
9214
|
-
await
|
|
9297
|
+
if (commandDoneFile !== void 0 && !await waitForTerminalCommandExit(commandDoneFile, run)) {
|
|
9298
|
+
return skip("terminal command still running; window left open to avoid macOS termination prompt");
|
|
9299
|
+
}
|
|
9300
|
+
const closed2 = await run("osascript", ["-e", terminalCloseScript(windowTitle)]);
|
|
9301
|
+
if (closed2.code !== 0)
|
|
9302
|
+
return skip("screencapture failed; Terminal close failed");
|
|
9215
9303
|
return skip("screencapture failed (screen-recording permission?)");
|
|
9216
9304
|
}
|
|
9217
|
-
await
|
|
9305
|
+
if (commandDoneFile !== void 0 && !await waitForTerminalCommandExit(commandDoneFile, run)) {
|
|
9306
|
+
return skip("terminal command still running; window left open to avoid macOS termination prompt");
|
|
9307
|
+
}
|
|
9308
|
+
const closed = await run("osascript", ["-e", terminalCloseScript(windowTitle)]);
|
|
9309
|
+
if (closed.code !== 0)
|
|
9310
|
+
return skip("Terminal close failed after capture");
|
|
9218
9311
|
}
|
|
9219
9312
|
} catch {
|
|
9220
9313
|
return skip("capture errored");
|
|
@@ -10330,18 +10423,18 @@ function pyLjust(s, w) {
|
|
|
10330
10423
|
function agentSummaryLine(records, windowCycles = 50, minSample = 5) {
|
|
10331
10424
|
if (records.length === 0 || windowCycles <= 0)
|
|
10332
10425
|
return "";
|
|
10333
|
-
const
|
|
10426
|
+
const tail2 = [];
|
|
10334
10427
|
for (const rec of records.slice(-windowCycles)) {
|
|
10335
10428
|
const agent = (rec ?? {}).agent ?? "";
|
|
10336
10429
|
if (!agent)
|
|
10337
10430
|
continue;
|
|
10338
|
-
|
|
10431
|
+
tail2.push(rec);
|
|
10339
10432
|
}
|
|
10340
|
-
if (
|
|
10433
|
+
if (tail2.length === 0)
|
|
10341
10434
|
return "";
|
|
10342
10435
|
const counts = /* @__PURE__ */ new Map();
|
|
10343
10436
|
const order = [];
|
|
10344
|
-
for (const rec of
|
|
10437
|
+
for (const rec of tail2) {
|
|
10345
10438
|
const agent = rec.agent ?? "";
|
|
10346
10439
|
if (!agent)
|
|
10347
10440
|
continue;
|
|
@@ -11388,7 +11481,7 @@ import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync10, readFileSy
|
|
|
11388
11481
|
import { dirname as dirname9, join as join10 } from "node:path";
|
|
11389
11482
|
|
|
11390
11483
|
// packages/cli/dist/commands/setup-shared.js
|
|
11391
|
-
import { copyFileSync, existsSync as existsSync13, lstatSync, mkdirSync as mkdirSync9, readFileSync as readFileSync10, readdirSync as readdirSync4, readlinkSync, realpathSync as realpathSync2, rmSync as
|
|
11484
|
+
import { copyFileSync, existsSync as existsSync13, lstatSync, mkdirSync as mkdirSync9, readFileSync as readFileSync10, readdirSync as readdirSync4, readlinkSync, realpathSync as realpathSync2, rmSync as rmSync5, statSync as statSync7, symlinkSync, writeFileSync as writeFileSync8 } from "node:fs";
|
|
11392
11485
|
import { homedir as homedir4 } from "node:os";
|
|
11393
11486
|
import { basename as basename4, dirname as dirname8, join as join9 } from "node:path";
|
|
11394
11487
|
function rollHome() {
|
|
@@ -11535,7 +11628,7 @@ function pruneDir(installedDir, sourceDir) {
|
|
|
11535
11628
|
if (!isFile)
|
|
11536
11629
|
continue;
|
|
11537
11630
|
if (!existsSync13(join9(sourceDir, name)))
|
|
11538
|
-
|
|
11631
|
+
rmSync5(installedF, { force: true });
|
|
11539
11632
|
}
|
|
11540
11633
|
}
|
|
11541
11634
|
function safeCopy(src, dst, force) {
|
|
@@ -11613,7 +11706,7 @@ function syncSkillTree(sourceDir, destDir) {
|
|
|
11613
11706
|
const sourceNames = new Set(listDirEntries(sourceDir));
|
|
11614
11707
|
for (const name of listDirEntries(destDir)) {
|
|
11615
11708
|
if (!sourceNames.has(name))
|
|
11616
|
-
|
|
11709
|
+
rmSync5(join9(destDir, name), { recursive: true, force: true });
|
|
11617
11710
|
}
|
|
11618
11711
|
for (const name of sourceNames) {
|
|
11619
11712
|
const src = join9(sourceDir, name);
|
|
@@ -11626,11 +11719,11 @@ function syncSkillTree(sourceDir, destDir) {
|
|
|
11626
11719
|
}
|
|
11627
11720
|
if (st.isDirectory()) {
|
|
11628
11721
|
if (lstatType(dst) !== "dir" && lstatType(dst) !== "none")
|
|
11629
|
-
|
|
11722
|
+
rmSync5(dst, { recursive: true, force: true });
|
|
11630
11723
|
syncSkillTree(src, dst);
|
|
11631
11724
|
} else if (st.isFile()) {
|
|
11632
11725
|
if (lstatType(dst) === "dir")
|
|
11633
|
-
|
|
11726
|
+
rmSync5(dst, { recursive: true, force: true });
|
|
11634
11727
|
if (!sameFile(src, dst))
|
|
11635
11728
|
copyFileSync(src, dst);
|
|
11636
11729
|
}
|
|
@@ -11662,7 +11755,7 @@ function pullSkills() {
|
|
|
11662
11755
|
continue;
|
|
11663
11756
|
}
|
|
11664
11757
|
if (!existsSync13(join9(pkgSkills, installedName))) {
|
|
11665
|
-
|
|
11758
|
+
rmSync5(installedDir, { recursive: true, force: true });
|
|
11666
11759
|
}
|
|
11667
11760
|
}
|
|
11668
11761
|
}
|
|
@@ -11772,7 +11865,7 @@ function installLocal(force) {
|
|
|
11772
11865
|
const cfg = rollConfig();
|
|
11773
11866
|
if (existsSync13(cfg) && !/^ai_[a-z]+:/m.test(readFileSync10(cfg, "utf8"))) {
|
|
11774
11867
|
copyFileSync(cfg, `${cfg}.bak`);
|
|
11775
|
-
|
|
11868
|
+
rmSync5(cfg, { force: true });
|
|
11776
11869
|
}
|
|
11777
11870
|
if (!existsSync13(cfg)) {
|
|
11778
11871
|
writeFileSync8(cfg, DEFAULT_CONFIG);
|
|
@@ -11851,7 +11944,7 @@ function linkSkills() {
|
|
|
11851
11944
|
if (skillsReal !== null && skillsReal === rollSkillsReal)
|
|
11852
11945
|
continue;
|
|
11853
11946
|
if (skillsReal === null) {
|
|
11854
|
-
|
|
11947
|
+
rmSync5(skillsDir2, { force: true });
|
|
11855
11948
|
} else {
|
|
11856
11949
|
void target;
|
|
11857
11950
|
continue;
|
|
@@ -11876,7 +11969,7 @@ function linkSkills() {
|
|
|
11876
11969
|
target = "";
|
|
11877
11970
|
}
|
|
11878
11971
|
if (target.startsWith(homeSkillsPrefix) && !existsSync13(link)) {
|
|
11879
|
-
|
|
11972
|
+
rmSync5(link, { force: true });
|
|
11880
11973
|
}
|
|
11881
11974
|
}
|
|
11882
11975
|
const homeSkills = join9(rollHome(), "skills");
|
|
@@ -11898,7 +11991,7 @@ function linkSkills() {
|
|
|
11898
11991
|
current = "";
|
|
11899
11992
|
}
|
|
11900
11993
|
if (current !== skillDir) {
|
|
11901
|
-
|
|
11994
|
+
rmSync5(skillLink, { force: true });
|
|
11902
11995
|
symlinkSync(skillDir, skillLink);
|
|
11903
11996
|
}
|
|
11904
11997
|
} else if (t2 === "none") {
|
|
@@ -12278,7 +12371,7 @@ duration: ${facts.durationMs}ms
|
|
|
12278
12371
|
}
|
|
12279
12372
|
|
|
12280
12373
|
// packages/cli/dist/commands/alert.js
|
|
12281
|
-
import { appendFileSync as appendFileSync3, existsSync as existsSync14, mkdirSync as mkdirSync11, readFileSync as readFileSync12, rmSync as
|
|
12374
|
+
import { appendFileSync as appendFileSync3, existsSync as existsSync14, mkdirSync as mkdirSync11, readFileSync as readFileSync12, rmSync as rmSync6, statSync as statSync8 } from "node:fs";
|
|
12282
12375
|
import { homedir as homedir5 } from "node:os";
|
|
12283
12376
|
import { join as join11 } from "node:path";
|
|
12284
12377
|
function palette() {
|
|
@@ -12385,11 +12478,11 @@ function alertCommand(args) {
|
|
|
12385
12478
|
out3.push("");
|
|
12386
12479
|
process.stdout.write(out3.join("\n") + "\n");
|
|
12387
12480
|
process.stdout.write(action.contents);
|
|
12388
|
-
const
|
|
12389
|
-
|
|
12390
|
-
|
|
12391
|
-
|
|
12392
|
-
process.stdout.write(
|
|
12481
|
+
const tail2 = [];
|
|
12482
|
+
tail2.push("");
|
|
12483
|
+
tail2.push(` Run '${p.CYAN}roll loop alert ack${p.NC}' to acknowledge, '${p.CYAN}roll loop alert resolve${p.NC}' to clear.`);
|
|
12484
|
+
tail2.push(t(v2Catalog, lang9, "alert.run_roll_alert_ack_to_acknowledge"));
|
|
12485
|
+
process.stdout.write(tail2.join("\n") + "\n");
|
|
12393
12486
|
return 0;
|
|
12394
12487
|
}
|
|
12395
12488
|
case "ack_none":
|
|
@@ -12403,7 +12496,7 @@ function alertCommand(args) {
|
|
|
12403
12496
|
return 0;
|
|
12404
12497
|
}
|
|
12405
12498
|
case "remove":
|
|
12406
|
-
|
|
12499
|
+
rmSync6(file, { force: true });
|
|
12407
12500
|
ok2(t(v2Catalog, lang9, "alert.alert_resolved_and_cleared"), p);
|
|
12408
12501
|
return 0;
|
|
12409
12502
|
case "log":
|
|
@@ -12430,9 +12523,10 @@ function ackMessage(lang9, ts) {
|
|
|
12430
12523
|
}
|
|
12431
12524
|
|
|
12432
12525
|
// packages/cli/dist/commands/attest.js
|
|
12433
|
-
import { existsSync as existsSync20, mkdirSync as mkdirSync14, readFileSync as readFileSync18, readdirSync as readdirSync9, realpathSync as realpathSync3, rmSync as
|
|
12434
|
-
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
12526
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync14, readFileSync as readFileSync18, readdirSync as readdirSync9, realpathSync as realpathSync3, rmSync as rmSync7, statSync as statSync11, symlinkSync as symlinkSync2, writeFileSync as writeFileSync13 } from "node:fs";
|
|
12527
|
+
import { execFile as execFile7, execFileSync as execFileSync4 } from "node:child_process";
|
|
12435
12528
|
import { basename as basename7, join as join16, relative as relative2 } from "node:path";
|
|
12529
|
+
import { promisify as promisify7 } from "node:util";
|
|
12436
12530
|
|
|
12437
12531
|
// packages/cli/dist/lib/story-page.js
|
|
12438
12532
|
var STORY_ID_RE = /^(FIX|US|IDEA|REFACTOR)-/;
|
|
@@ -15143,10 +15237,47 @@ function buildProcessArchive(storyId, readers) {
|
|
|
15143
15237
|
return archive;
|
|
15144
15238
|
}
|
|
15145
15239
|
var STATUSES = ["pass", "readonly", "partial", "fail", "blocked", "claimed", "missing"];
|
|
15240
|
+
var execFileAsync7 = promisify7(execFile7);
|
|
15146
15241
|
function warn2(msg6) {
|
|
15147
15242
|
process.stderr.write(`[roll] attest WARN: ${msg6}
|
|
15148
15243
|
`);
|
|
15149
15244
|
}
|
|
15245
|
+
function shellQuote2(value) {
|
|
15246
|
+
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
15247
|
+
}
|
|
15248
|
+
function commandInProject(projectPath3, command) {
|
|
15249
|
+
return `cd ${shellQuote2(projectPath3)} && ${command}`;
|
|
15250
|
+
}
|
|
15251
|
+
function tail(text, max = 4e3) {
|
|
15252
|
+
return text.length <= max ? text : text.slice(text.length - max);
|
|
15253
|
+
}
|
|
15254
|
+
async function runShell(line, deps) {
|
|
15255
|
+
const injected = deps?.run;
|
|
15256
|
+
if (injected !== void 0)
|
|
15257
|
+
return injected("sh", ["-lc", line]);
|
|
15258
|
+
try {
|
|
15259
|
+
const { stdout, stderr } = await execFileAsync7("sh", ["-lc", line], {
|
|
15260
|
+
encoding: "utf8",
|
|
15261
|
+
maxBuffer: 4 * 1024 * 1024,
|
|
15262
|
+
timeout: 12e4
|
|
15263
|
+
});
|
|
15264
|
+
return { code: 0, stdout, stderr };
|
|
15265
|
+
} catch (e) {
|
|
15266
|
+
const err17 = e;
|
|
15267
|
+
return { code: typeof err17.code === "number" ? err17.code : 1, stdout: err17.stdout ?? "", stderr: err17.stderr ?? "" };
|
|
15268
|
+
}
|
|
15269
|
+
}
|
|
15270
|
+
async function captureCommandFact(projectPath3, command, deps) {
|
|
15271
|
+
const wrappedCommand = commandInProject(projectPath3, command);
|
|
15272
|
+
const r = await runShell(wrappedCommand, deps);
|
|
15273
|
+
return {
|
|
15274
|
+
command,
|
|
15275
|
+
wrappedCommand,
|
|
15276
|
+
exitCode: r.code,
|
|
15277
|
+
stdoutTail: tail(r.stdout),
|
|
15278
|
+
stderrTail: tail(r.stderr)
|
|
15279
|
+
};
|
|
15280
|
+
}
|
|
15150
15281
|
var DOC_ALIGNMENT_PATTERNS = [
|
|
15151
15282
|
/^README(?:_[A-Z]+)?\.md$/,
|
|
15152
15283
|
/^AGENTS\.md$/,
|
|
@@ -15603,7 +15734,7 @@ async function attestCommand(args, deps = {}) {
|
|
|
15603
15734
|
}
|
|
15604
15735
|
const acItems = resolveStoryAcItems(projectPath3, storyId);
|
|
15605
15736
|
if (acItems.length === 0)
|
|
15606
|
-
warn2(`no
|
|
15737
|
+
warn2(`no AC block for ${storyId} \u2014 report will carry facts only`);
|
|
15607
15738
|
const now = (deps.now ?? (() => /* @__PURE__ */ new Date()))();
|
|
15608
15739
|
const p2 = (n) => String(n).padStart(2, "0");
|
|
15609
15740
|
const generatedRunId = `${now.getFullYear()}-${p2(now.getMonth() + 1)}-${p2(now.getDate())}T${p2(now.getHours())}-${p2(now.getMinutes())}-${p2(now.getSeconds())}`;
|
|
@@ -15611,15 +15742,27 @@ async function attestCommand(args, deps = {}) {
|
|
|
15611
15742
|
const runDir = providedRunDir ?? join16(storyDir, generatedRunId);
|
|
15612
15743
|
openEvidenceFrame({ runDir });
|
|
15613
15744
|
let selfCaptures = [];
|
|
15745
|
+
const captureFacts = [];
|
|
15746
|
+
let commandFact = null;
|
|
15614
15747
|
if (captureTerminal) {
|
|
15615
15748
|
mkdirSync14(join16(runDir, "screenshots"), { recursive: true });
|
|
15616
|
-
const
|
|
15749
|
+
const out3 = join16(runDir, "screenshots", "terminal.png");
|
|
15750
|
+
if (captureCommand !== void 0) {
|
|
15751
|
+
commandFact = await captureCommandFact(projectPath3, captureCommand, deps.capture);
|
|
15752
|
+
}
|
|
15753
|
+
const shot = commandFact !== null && commandFact.exitCode !== 0 ? { kind: "terminal", out: out3, taken: false, skipped: `capture command exited ${commandFact.exitCode}` } : await captureScreenshot({
|
|
15617
15754
|
kind: "terminal",
|
|
15618
|
-
out:
|
|
15755
|
+
out: out3,
|
|
15619
15756
|
...captureTmux !== void 0 ? { tmux: captureTmux } : {},
|
|
15620
|
-
...captureCommand !== void 0 ? { command: captureCommand } : {},
|
|
15757
|
+
...captureCommand !== void 0 ? { command: commandInProject(projectPath3, captureCommand) } : {},
|
|
15621
15758
|
...captureRegion !== void 0 ? { region: captureRegion } : {}
|
|
15622
15759
|
}, deps.capture ?? {});
|
|
15760
|
+
captureFacts.push({
|
|
15761
|
+
kind: shot.kind,
|
|
15762
|
+
out: shot.out,
|
|
15763
|
+
taken: shot.taken,
|
|
15764
|
+
...shot.skipped !== void 0 ? { skipped: shot.skipped } : {}
|
|
15765
|
+
});
|
|
15623
15766
|
const ref = screenshotEvidenceRef(shot, "screenshots/terminal.png");
|
|
15624
15767
|
if (ref !== null)
|
|
15625
15768
|
selfCaptures = [ref];
|
|
@@ -15633,7 +15776,9 @@ async function attestCommand(args, deps = {}) {
|
|
|
15633
15776
|
...deployUrl !== void 0 ? { deployUrl } : {},
|
|
15634
15777
|
now: () => now.toISOString(),
|
|
15635
15778
|
...deps.run !== void 0 ? { run: deps.run } : {},
|
|
15636
|
-
...deps.ghProbe !== void 0 ? { ghProbe: deps.ghProbe } : {}
|
|
15779
|
+
...deps.ghProbe !== void 0 ? { ghProbe: deps.ghProbe } : {},
|
|
15780
|
+
captures: captureFacts,
|
|
15781
|
+
captureCommand: commandFact
|
|
15637
15782
|
});
|
|
15638
15783
|
writeEvidenceJson(manifest, runDir);
|
|
15639
15784
|
const acMap = readAcMap(storyDir) ?? readAcMap(join16(projectPath3, ".roll", "verification", storyId));
|
|
@@ -15676,13 +15821,14 @@ async function attestCommand(args, deps = {}) {
|
|
|
15676
15821
|
...docGap !== void 0 ? { docGap } : {},
|
|
15677
15822
|
...selfScores.length > 0 ? { selfScores } : {},
|
|
15678
15823
|
...selfScoreTrend !== void 0 ? { selfScoreTrend } : {},
|
|
15679
|
-
...selfCaptures.length > 0 ? { selfCaptures } : {}
|
|
15824
|
+
...selfCaptures.length > 0 ? { selfCaptures } : {},
|
|
15825
|
+
...captureFacts.some((x) => !x.taken && x.skipped !== void 0) ? { captureSkips: captureFacts.filter((x) => !x.taken && x.skipped !== void 0).map((x) => ({ kind: x.kind, out: x.out, skipped: x.skipped ?? "" })) } : {}
|
|
15680
15826
|
});
|
|
15681
15827
|
const reportPath = join16(runDir, reportFileName(storyId));
|
|
15682
15828
|
writeFileSync13(reportPath, html);
|
|
15683
15829
|
const latest = join16(storyDir, "latest");
|
|
15684
15830
|
try {
|
|
15685
|
-
|
|
15831
|
+
rmSync7(latest, { force: true });
|
|
15686
15832
|
symlinkSync2(relativeFromPhysical(storyDir, runDir), latest);
|
|
15687
15833
|
} catch {
|
|
15688
15834
|
warn2("latest symlink update failed (report still written)");
|
|
@@ -15715,6 +15861,10 @@ async function attestCommand(args, deps = {}) {
|
|
|
15715
15861
|
warn2(`render smoke: ${p}`);
|
|
15716
15862
|
return 2;
|
|
15717
15863
|
}
|
|
15864
|
+
if (commandFact !== null && commandFact.exitCode !== 0) {
|
|
15865
|
+
warn2(`capture command failed with exit ${commandFact.exitCode}`);
|
|
15866
|
+
return 3;
|
|
15867
|
+
}
|
|
15718
15868
|
return 0;
|
|
15719
15869
|
}
|
|
15720
15870
|
|
|
@@ -17720,17 +17870,17 @@ function configCommand(args) {
|
|
|
17720
17870
|
}
|
|
17721
17871
|
|
|
17722
17872
|
// packages/cli/dist/commands/consistency.js
|
|
17723
|
-
import { existsSync as existsSync29, readFileSync as readFileSync27, readdirSync as
|
|
17873
|
+
import { existsSync as existsSync29, readFileSync as readFileSync27, readdirSync as readdirSync11, statSync as statSync12 } from "node:fs";
|
|
17724
17874
|
import { join as join24 } from "node:path";
|
|
17725
17875
|
|
|
17726
17876
|
// packages/cli/dist/commands/consistency-audit.js
|
|
17727
|
-
import { execFile as
|
|
17728
|
-
import { existsSync as existsSync28, mkdirSync as mkdirSync19, readFileSync as readFileSync26, writeFileSync as writeFileSync19 } from "node:fs";
|
|
17729
|
-
import { join as join23 } from "node:path";
|
|
17730
|
-
import { promisify as
|
|
17877
|
+
import { execFile as execFile8 } from "node:child_process";
|
|
17878
|
+
import { existsSync as existsSync28, mkdirSync as mkdirSync19, readFileSync as readFileSync26, readdirSync as readdirSync10, writeFileSync as writeFileSync19 } from "node:fs";
|
|
17879
|
+
import { dirname as dirname16, join as join23 } from "node:path";
|
|
17880
|
+
import { promisify as promisify8 } from "node:util";
|
|
17731
17881
|
var PROBE_CAP = 20;
|
|
17732
17882
|
var COUNT_WINDOW_SEC = 72 * 3600;
|
|
17733
|
-
var
|
|
17883
|
+
var execFileAsync8 = promisify8(execFile8);
|
|
17734
17884
|
function readJsonl2(path) {
|
|
17735
17885
|
if (!existsSync28(path))
|
|
17736
17886
|
return [];
|
|
@@ -17747,9 +17897,58 @@ function readJsonl2(path) {
|
|
|
17747
17897
|
}
|
|
17748
17898
|
return out3;
|
|
17749
17899
|
}
|
|
17900
|
+
function readJson(path) {
|
|
17901
|
+
if (!existsSync28(path))
|
|
17902
|
+
return null;
|
|
17903
|
+
try {
|
|
17904
|
+
const parsed = JSON.parse(readFileSync26(path, "utf8"));
|
|
17905
|
+
return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : null;
|
|
17906
|
+
} catch {
|
|
17907
|
+
return null;
|
|
17908
|
+
}
|
|
17909
|
+
}
|
|
17910
|
+
function hasScreenshotArtifact(reportPath) {
|
|
17911
|
+
const runDir = dirname16(reportPath);
|
|
17912
|
+
const manifest = readJson(join23(runDir, "evidence.json"));
|
|
17913
|
+
if (manifest !== null) {
|
|
17914
|
+
const screenshots = manifest["screenshots"];
|
|
17915
|
+
if (Array.isArray(screenshots) && screenshots.some((x) => typeof x === "string" && x !== ""))
|
|
17916
|
+
return true;
|
|
17917
|
+
const captures = manifest["captures"];
|
|
17918
|
+
if (Array.isArray(captures)) {
|
|
17919
|
+
if (captures.some((raw) => {
|
|
17920
|
+
if (typeof raw !== "object" || raw === null)
|
|
17921
|
+
return false;
|
|
17922
|
+
return raw["taken"] === true;
|
|
17923
|
+
})) {
|
|
17924
|
+
return true;
|
|
17925
|
+
}
|
|
17926
|
+
}
|
|
17927
|
+
}
|
|
17928
|
+
const dir = join23(runDir, "screenshots");
|
|
17929
|
+
if (!existsSync28(dir))
|
|
17930
|
+
return false;
|
|
17931
|
+
try {
|
|
17932
|
+
return readdirSync10(dir).some((name) => /\.png$/i.test(name));
|
|
17933
|
+
} catch {
|
|
17934
|
+
return false;
|
|
17935
|
+
}
|
|
17936
|
+
}
|
|
17937
|
+
function hasMachineCaptureSkip(reportPath) {
|
|
17938
|
+
const manifest = readJson(join23(dirname16(reportPath), "evidence.json"));
|
|
17939
|
+
const captures = manifest?.["captures"];
|
|
17940
|
+
if (!Array.isArray(captures))
|
|
17941
|
+
return false;
|
|
17942
|
+
return captures.some((raw) => {
|
|
17943
|
+
if (typeof raw !== "object" || raw === null)
|
|
17944
|
+
return false;
|
|
17945
|
+
const row2 = raw;
|
|
17946
|
+
return row2["taken"] === false && typeof row2["skipped"] === "string" && row2["skipped"] !== "";
|
|
17947
|
+
});
|
|
17948
|
+
}
|
|
17750
17949
|
async function gitLocalMainAhead(projectPath3) {
|
|
17751
17950
|
try {
|
|
17752
|
-
const { stdout } = await
|
|
17951
|
+
const { stdout } = await execFileAsync8("git", ["rev-list", "--count", "origin/main..main"], {
|
|
17753
17952
|
cwd: projectPath3,
|
|
17754
17953
|
encoding: "utf8"
|
|
17755
17954
|
});
|
|
@@ -17798,9 +17997,12 @@ async function gatherAuditSnapshot(projectPath3, runtimeDir6, deps = {}) {
|
|
|
17798
17997
|
const card = cardArchiveDir(projectPath3, row2.id);
|
|
17799
17998
|
if (!existsSync28(card))
|
|
17800
17999
|
continue;
|
|
18000
|
+
const reportPath = join23(card, "latest", reportFileName(row2.id));
|
|
17801
18001
|
snapshot.attest[row2.id] = {
|
|
17802
|
-
report: existsSync28(
|
|
17803
|
-
acMap: existsSync28(join23(card, "ac-map.json"))
|
|
18002
|
+
report: existsSync28(reportPath),
|
|
18003
|
+
acMap: existsSync28(join23(card, "ac-map.json")),
|
|
18004
|
+
visualEvidence: existsSync28(reportPath) ? hasScreenshotArtifact(reportPath) : false,
|
|
18005
|
+
machineSkip: existsSync28(reportPath) ? hasMachineCaptureSkip(reportPath) : false
|
|
17804
18006
|
};
|
|
17805
18007
|
}
|
|
17806
18008
|
const slug = deps.slug ?? ghRepoSlug(await remoteUrl(projectPath3));
|
|
@@ -17962,7 +18164,7 @@ function walkTextFiles(projectDir, relDir, extensions) {
|
|
|
17962
18164
|
const dirAbs = join24(projectDir, dirRel);
|
|
17963
18165
|
let entries;
|
|
17964
18166
|
try {
|
|
17965
|
-
entries =
|
|
18167
|
+
entries = readdirSync11(dirAbs, { withFileTypes: true });
|
|
17966
18168
|
} catch {
|
|
17967
18169
|
return;
|
|
17968
18170
|
}
|
|
@@ -18070,10 +18272,10 @@ function checkCards(projectDir) {
|
|
|
18070
18272
|
return { status: "pass", gaps: [] };
|
|
18071
18273
|
const cardEpic = /* @__PURE__ */ new Map();
|
|
18072
18274
|
try {
|
|
18073
|
-
for (const epic of
|
|
18275
|
+
for (const epic of readdirSync11(featuresDir, { withFileTypes: true })) {
|
|
18074
18276
|
if (!epic.isDirectory())
|
|
18075
18277
|
continue;
|
|
18076
|
-
for (const card of
|
|
18278
|
+
for (const card of readdirSync11(join24(featuresDir, epic.name), { withFileTypes: true })) {
|
|
18077
18279
|
if (!card.isDirectory())
|
|
18078
18280
|
continue;
|
|
18079
18281
|
if (existsSync29(join24(featuresDir, epic.name, card.name, "spec.md")) && !cardEpic.has(card.name)) {
|
|
@@ -18239,7 +18441,7 @@ function checkSite(projectDir) {
|
|
|
18239
18441
|
}
|
|
18240
18442
|
function listFiles2(dir) {
|
|
18241
18443
|
try {
|
|
18242
|
-
return
|
|
18444
|
+
return readdirSync11(dir).filter((n) => {
|
|
18243
18445
|
try {
|
|
18244
18446
|
return statSync12(join24(dir, n)).isFile();
|
|
18245
18447
|
} catch {
|
|
@@ -18270,7 +18472,7 @@ function checkI18n(projectDir) {
|
|
|
18270
18472
|
const keysZh = /* @__PURE__ */ new Set();
|
|
18271
18473
|
let shFiles = [];
|
|
18272
18474
|
try {
|
|
18273
|
-
shFiles =
|
|
18475
|
+
shFiles = readdirSync11(i18nDir).filter((n) => n.endsWith(".sh")).sort();
|
|
18274
18476
|
} catch {
|
|
18275
18477
|
shFiles = [];
|
|
18276
18478
|
}
|
|
@@ -18310,7 +18512,7 @@ function rglobBats(dir) {
|
|
|
18310
18512
|
const walk2 = (d) => {
|
|
18311
18513
|
let entries = [];
|
|
18312
18514
|
try {
|
|
18313
|
-
entries =
|
|
18515
|
+
entries = readdirSync11(d);
|
|
18314
18516
|
} catch {
|
|
18315
18517
|
return;
|
|
18316
18518
|
}
|
|
@@ -18517,7 +18719,7 @@ function consistencyCommand(args, command = "roll consistency") {
|
|
|
18517
18719
|
}
|
|
18518
18720
|
|
|
18519
18721
|
// packages/cli/dist/commands/loop-runs.js
|
|
18520
|
-
import { existsSync as existsSync30, readFileSync as readFileSync28, readdirSync as
|
|
18722
|
+
import { existsSync as existsSync30, readFileSync as readFileSync28, readdirSync as readdirSync12 } from "node:fs";
|
|
18521
18723
|
import { homedir as homedir9, platform as platform2 } from "node:os";
|
|
18522
18724
|
import { basename as basename8, join as join25 } from "node:path";
|
|
18523
18725
|
function lang3() {
|
|
@@ -18678,7 +18880,7 @@ function aggregateAllFiles() {
|
|
|
18678
18880
|
const laDir = (process.env["_LAUNCHD_DIR"] ?? "").trim() || join25(homedir9(), "Library", "LaunchAgents");
|
|
18679
18881
|
let plists = [];
|
|
18680
18882
|
try {
|
|
18681
|
-
plists =
|
|
18883
|
+
plists = readdirSync12(laDir).filter((f) => f.startsWith("com.roll.loop.") && f.endsWith(".plist"));
|
|
18682
18884
|
} catch {
|
|
18683
18885
|
plists = [];
|
|
18684
18886
|
}
|
|
@@ -18823,7 +19025,7 @@ function loopRunsCommand(argv) {
|
|
|
18823
19025
|
|
|
18824
19026
|
// packages/cli/dist/commands/loop-signals.js
|
|
18825
19027
|
import { appendFileSync as appendFileSync7, existsSync as existsSync31, mkdirSync as mkdirSync20, readFileSync as readFileSync29, writeFileSync as writeFileSync20 } from "node:fs";
|
|
18826
|
-
import { dirname as
|
|
19028
|
+
import { dirname as dirname17, join as join26 } from "node:path";
|
|
18827
19029
|
function lang4() {
|
|
18828
19030
|
return resolveLang({ rollLang: process.env["ROLL_LANG"], lcAll: process.env["LC_ALL"], lang: process.env["LANG"] });
|
|
18829
19031
|
}
|
|
@@ -18878,7 +19080,7 @@ function loopSignalsCommand(argv) {
|
|
|
18878
19080
|
const seenFile = join26(rtDir, `signals-seen-${slug}`);
|
|
18879
19081
|
const candFile = join26(projectPath3, ".roll", "signals", "candidates.md");
|
|
18880
19082
|
mkdirSync20(rtDir, { recursive: true });
|
|
18881
|
-
mkdirSync20(
|
|
19083
|
+
mkdirSync20(dirname17(candFile), { recursive: true });
|
|
18882
19084
|
if (!existsSync31(seenFile))
|
|
18883
19085
|
writeFileSync20(seenFile, "");
|
|
18884
19086
|
let lastId = 0;
|
|
@@ -18935,7 +19137,7 @@ Options:
|
|
|
18935
19137
|
`;
|
|
18936
19138
|
|
|
18937
19139
|
// packages/cli/dist/commands/loop-log.js
|
|
18938
|
-
import { existsSync as existsSync32, readFileSync as readFileSync30, readdirSync as
|
|
19140
|
+
import { existsSync as existsSync32, readFileSync as readFileSync30, readdirSync as readdirSync13 } from "node:fs";
|
|
18939
19141
|
import { basename as basename9, join as join27 } from "node:path";
|
|
18940
19142
|
function lang5() {
|
|
18941
19143
|
return resolveLang({ rollLang: process.env["ROLL_LANG"], lcAll: process.env["LC_ALL"], lang: process.env["LANG"] });
|
|
@@ -18961,7 +19163,7 @@ ${body}`);
|
|
|
18961
19163
|
}
|
|
18962
19164
|
function logFiles(logsDir) {
|
|
18963
19165
|
try {
|
|
18964
|
-
return
|
|
19166
|
+
return readdirSync13(logsDir).filter((n) => n.endsWith(".log"));
|
|
18965
19167
|
} catch {
|
|
18966
19168
|
return [];
|
|
18967
19169
|
}
|
|
@@ -19092,8 +19294,8 @@ async function loopGoalCommand(args, deps = realDeps2()) {
|
|
|
19092
19294
|
|
|
19093
19295
|
// packages/cli/dist/commands/loop-go.js
|
|
19094
19296
|
import { spawn as spawn2, spawnSync as spawnSync3 } from "node:child_process";
|
|
19095
|
-
import { appendFileSync as appendFileSync8, createReadStream, existsSync as existsSync34, mkdirSync as mkdirSync21, readFileSync as readFileSync32, renameSync as renameSync4, writeFileSync as writeFileSync21 } from "node:fs";
|
|
19096
|
-
import { dirname as
|
|
19297
|
+
import { appendFileSync as appendFileSync8, createReadStream, existsSync as existsSync34, mkdirSync as mkdirSync21, readFileSync as readFileSync32, renameSync as renameSync4, statSync as statSync13, writeFileSync as writeFileSync21 } from "node:fs";
|
|
19298
|
+
import { dirname as dirname18, join as join29 } from "node:path";
|
|
19097
19299
|
import { createInterface } from "node:readline";
|
|
19098
19300
|
|
|
19099
19301
|
// packages/cli/dist/lib/goal-progress.js
|
|
@@ -19349,6 +19551,7 @@ function parseOptions2(args) {
|
|
|
19349
19551
|
let worker = false;
|
|
19350
19552
|
let noTmux = false;
|
|
19351
19553
|
let noWait = false;
|
|
19554
|
+
let scopeSpecified = false;
|
|
19352
19555
|
let reviewMode = "auto";
|
|
19353
19556
|
let reviewModeSpecified = false;
|
|
19354
19557
|
for (let i = 0; i < args.length; i += 1) {
|
|
@@ -19367,15 +19570,19 @@ function parseOptions2(args) {
|
|
|
19367
19570
|
}
|
|
19368
19571
|
if (arg === "--epic") {
|
|
19369
19572
|
const epic = args[i + 1]?.trim() ?? "";
|
|
19370
|
-
if (epic !== "")
|
|
19573
|
+
if (epic !== "") {
|
|
19371
19574
|
scope = { kind: "epic", epic };
|
|
19575
|
+
scopeSpecified = true;
|
|
19576
|
+
}
|
|
19372
19577
|
i += 1;
|
|
19373
19578
|
continue;
|
|
19374
19579
|
}
|
|
19375
19580
|
if (arg.startsWith("--epic=")) {
|
|
19376
19581
|
const epic = arg.slice("--epic=".length).trim();
|
|
19377
|
-
if (epic !== "")
|
|
19582
|
+
if (epic !== "") {
|
|
19378
19583
|
scope = { kind: "epic", epic };
|
|
19584
|
+
scopeSpecified = true;
|
|
19585
|
+
}
|
|
19379
19586
|
continue;
|
|
19380
19587
|
}
|
|
19381
19588
|
if (arg === "--budget") {
|
|
@@ -19437,13 +19644,16 @@ function parseOptions2(args) {
|
|
|
19437
19644
|
if (!arg.startsWith("-"))
|
|
19438
19645
|
cards.push(...parseCards(arg));
|
|
19439
19646
|
}
|
|
19440
|
-
if (cards.length > 0)
|
|
19647
|
+
if (cards.length > 0) {
|
|
19441
19648
|
scope = { kind: "cards", cards };
|
|
19649
|
+
scopeSpecified = true;
|
|
19650
|
+
}
|
|
19442
19651
|
return {
|
|
19443
19652
|
worker,
|
|
19444
19653
|
noTmux,
|
|
19445
19654
|
noWait,
|
|
19446
19655
|
scope,
|
|
19656
|
+
scopeSpecified,
|
|
19447
19657
|
reviewMode,
|
|
19448
19658
|
reviewModeSpecified,
|
|
19449
19659
|
usageThreshold,
|
|
@@ -19548,7 +19758,7 @@ function parseRequiredDurationSeconds(value, flag2) {
|
|
|
19548
19758
|
function parseCards(value) {
|
|
19549
19759
|
return (value ?? "").split(",").map((s) => s.trim()).filter((s) => s !== "");
|
|
19550
19760
|
}
|
|
19551
|
-
function
|
|
19761
|
+
function shellQuote3(value) {
|
|
19552
19762
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
19553
19763
|
}
|
|
19554
19764
|
function rollBin() {
|
|
@@ -19557,13 +19767,13 @@ function rollBin() {
|
|
|
19557
19767
|
function startGoTmux(input) {
|
|
19558
19768
|
const session = `roll-loop-${input.slug}`;
|
|
19559
19769
|
const rt = runtimeDir2(input.projectPath);
|
|
19560
|
-
const workerArgs = input.args.filter((arg) => arg !== "--worker" && arg !== "--no-tmux").concat("--worker").map(
|
|
19561
|
-
const watch = `printf 'roll goal \xB7 ${input.slug}\\n'; tail -n +1 -F ${
|
|
19770
|
+
const workerArgs = input.args.filter((arg) => arg !== "--worker" && arg !== "--no-tmux").concat("--worker").map(shellQuote3).join(" ");
|
|
19771
|
+
const watch = `printf 'roll goal \xB7 ${input.slug}\\n'; tail -n +1 -F ${shellQuote3(join29(rt, "live.log"))} | ${shellQuote3(input.rollBin)} loop fmt`;
|
|
19562
19772
|
try {
|
|
19563
19773
|
if (spawnSync3("tmux", ["has-session", "-t", session], { stdio: "ignore" }).status !== 0) {
|
|
19564
19774
|
spawnSync3("tmux", ["new-session", "-d", "-s", session, "-x", "200", "-y", "50", "-n", "watch", watch], { stdio: "ignore" });
|
|
19565
19775
|
}
|
|
19566
|
-
const command = `cd ${
|
|
19776
|
+
const command = `cd ${shellQuote3(input.projectPath)} && ROLL_LOOP_GO_WORKER=1 ROLL_LOOP_NO_TMUX=1 ROLL_BIN=${shellQuote3(input.rollBin)} ${shellQuote3(input.rollBin)} loop go ${workerArgs}`;
|
|
19567
19777
|
return spawnSync3("tmux", ["new-window", "-d", "-t", session, "-n", "go", command], { stdio: "ignore" }).status === 0;
|
|
19568
19778
|
} catch {
|
|
19569
19779
|
return false;
|
|
@@ -19589,7 +19799,7 @@ function realRunOnce(input) {
|
|
|
19589
19799
|
});
|
|
19590
19800
|
}
|
|
19591
19801
|
function writeGoal(path, goal) {
|
|
19592
|
-
mkdirSync21(
|
|
19802
|
+
mkdirSync21(dirname18(path), { recursive: true });
|
|
19593
19803
|
const tmp = `${path}.tmp-${process.pid}`;
|
|
19594
19804
|
writeFileSync21(tmp, renderGoalYaml(goal), "utf8");
|
|
19595
19805
|
renameSync4(tmp, path);
|
|
@@ -19700,7 +19910,7 @@ function alertPath(projectPath3, slug) {
|
|
|
19700
19910
|
}
|
|
19701
19911
|
function appendGoalAlert(projectPath3, slug, storyId, cycleId, at) {
|
|
19702
19912
|
const path = alertPath(projectPath3, slug);
|
|
19703
|
-
mkdirSync21(
|
|
19913
|
+
mkdirSync21(dirname18(path), { recursive: true });
|
|
19704
19914
|
const cycleLine = cycleId === void 0 ? "" : ` cycle=${cycleId}`;
|
|
19705
19915
|
appendFileSync8(path, `[${at}] goal card skipped: ${storyId}${cycleLine} reason=zero delivery streak
|
|
19706
19916
|
`, "utf8");
|
|
@@ -20083,6 +20293,7 @@ function applyRunOptions(goal, opts, at) {
|
|
|
20083
20293
|
const maxHours = opts.forSeconds !== void 0 ? opts.forSeconds / 3600 : goal.limits.maxHours;
|
|
20084
20294
|
return {
|
|
20085
20295
|
...goal,
|
|
20296
|
+
scope: opts.scopeSpecified ? opts.scope : goal.scope,
|
|
20086
20297
|
...opts.budgetUsd !== void 0 ? { budgetUsd: opts.budgetUsd } : {},
|
|
20087
20298
|
review: opts.reviewModeSpecified ? { mode: opts.reviewMode } : goal.review,
|
|
20088
20299
|
limits: {
|
|
@@ -20093,6 +20304,24 @@ function applyRunOptions(goal, opts, at) {
|
|
|
20093
20304
|
updatedAt: at
|
|
20094
20305
|
};
|
|
20095
20306
|
}
|
|
20307
|
+
function latestAlertSummary(projectPath3, slug, sinceSec) {
|
|
20308
|
+
const path = alertPath(projectPath3, slug);
|
|
20309
|
+
try {
|
|
20310
|
+
if (!existsSync34(path) || statSync13(path).mtimeMs / 1e3 < sinceSec)
|
|
20311
|
+
return void 0;
|
|
20312
|
+
const lines2 = readFileSync32(path, "utf8").split("\n").map((line2) => line2.trim()).filter((line2) => line2 !== "");
|
|
20313
|
+
const line = [...lines2].reverse().find((candidate) => /\b(ALERT|WARN|BLOCKED|refused|failed)\b/i.test(candidate));
|
|
20314
|
+
if (line === void 0)
|
|
20315
|
+
return void 0;
|
|
20316
|
+
return line.replace(/\s+/g, " ").slice(0, 220);
|
|
20317
|
+
} catch {
|
|
20318
|
+
return void 0;
|
|
20319
|
+
}
|
|
20320
|
+
}
|
|
20321
|
+
function noCycleTerminalReason(projectPath3, slug, sinceSec) {
|
|
20322
|
+
const alert = latestAlertSummary(projectPath3, slug, sinceSec);
|
|
20323
|
+
return alert === void 0 ? "no_cycle_terminal" : `no_cycle_terminal: ${alert}`;
|
|
20324
|
+
}
|
|
20096
20325
|
function applyBudgetGate(projectPath3, bus, session, goal, deps) {
|
|
20097
20326
|
const budgetUsd = goal.budgetUsd;
|
|
20098
20327
|
if (budgetUsd === void 0)
|
|
@@ -20354,7 +20583,7 @@ async function runGoWorker(id, opts, deps) {
|
|
|
20354
20583
|
break;
|
|
20355
20584
|
}
|
|
20356
20585
|
if (after.summary.cycles <= before.summary.cycles) {
|
|
20357
|
-
stopReason =
|
|
20586
|
+
stopReason = noCycleTerminalReason(id.path, id.slug, startedSec);
|
|
20358
20587
|
break;
|
|
20359
20588
|
}
|
|
20360
20589
|
}
|
|
@@ -20430,13 +20659,13 @@ function loopBranchesRetired() {
|
|
|
20430
20659
|
|
|
20431
20660
|
// packages/cli/dist/commands/doctor.js
|
|
20432
20661
|
import { execFileSync as execFileSync11 } from "node:child_process";
|
|
20433
|
-
import { accessSync as accessSync2, constants as constants2, existsSync as existsSync37, mkdtempSync as mkdtempSync3, readFileSync as readFileSync35, readdirSync as
|
|
20662
|
+
import { accessSync as accessSync2, constants as constants2, existsSync as existsSync37, mkdtempSync as mkdtempSync3, readFileSync as readFileSync35, readdirSync as readdirSync15, statSync as statSync15, writeFileSync as writeFileSync23 } from "node:fs";
|
|
20434
20663
|
import { homedir as homedir10, tmpdir as tmpdir4 } from "node:os";
|
|
20435
20664
|
import { delimiter as delimiter2, join as join32 } from "node:path";
|
|
20436
20665
|
|
|
20437
20666
|
// packages/cli/dist/commands/skills.js
|
|
20438
20667
|
import { execFileSync as execFileSync10 } from "node:child_process";
|
|
20439
|
-
import { existsSync as existsSync36, mkdtempSync as mkdtempSync2, readFileSync as readFileSync34, readdirSync as
|
|
20668
|
+
import { existsSync as existsSync36, mkdtempSync as mkdtempSync2, readFileSync as readFileSync34, readdirSync as readdirSync14, statSync as statSync14, writeFileSync as writeFileSync22 } from "node:fs";
|
|
20440
20669
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
20441
20670
|
import { join as join31 } from "node:path";
|
|
20442
20671
|
function pkgDir() {
|
|
@@ -20504,14 +20733,14 @@ function generateCatalog() {
|
|
|
20504
20733
|
const dir = skillsDir();
|
|
20505
20734
|
let entries = [];
|
|
20506
20735
|
try {
|
|
20507
|
-
entries =
|
|
20736
|
+
entries = readdirSync14(dir).sort();
|
|
20508
20737
|
} catch {
|
|
20509
20738
|
entries = [];
|
|
20510
20739
|
}
|
|
20511
20740
|
for (const name of entries) {
|
|
20512
20741
|
const skillDir = join31(dir, name);
|
|
20513
20742
|
try {
|
|
20514
|
-
if (!
|
|
20743
|
+
if (!statSync14(skillDir).isDirectory())
|
|
20515
20744
|
continue;
|
|
20516
20745
|
} catch {
|
|
20517
20746
|
continue;
|
|
@@ -20644,7 +20873,7 @@ function commandOnPath2(bin) {
|
|
|
20644
20873
|
if (dir === "")
|
|
20645
20874
|
continue;
|
|
20646
20875
|
try {
|
|
20647
|
-
const st =
|
|
20876
|
+
const st = statSync15(join32(dir, bin));
|
|
20648
20877
|
if (!st.isFile())
|
|
20649
20878
|
continue;
|
|
20650
20879
|
accessSync2(join32(dir, bin), constants2.X_OK);
|
|
@@ -20663,7 +20892,7 @@ function agentInstalledByName4(agent, dir) {
|
|
|
20663
20892
|
const p = join32(home, ".opencode", "bin", "opencode");
|
|
20664
20893
|
try {
|
|
20665
20894
|
accessSync2(p, constants2.X_OK);
|
|
20666
|
-
return
|
|
20895
|
+
return statSync15(p).isFile();
|
|
20667
20896
|
} catch {
|
|
20668
20897
|
return false;
|
|
20669
20898
|
}
|
|
@@ -20682,7 +20911,7 @@ function agentInstalledByName4(agent, dir) {
|
|
|
20682
20911
|
}
|
|
20683
20912
|
function safeIsDir(p) {
|
|
20684
20913
|
try {
|
|
20685
|
-
return
|
|
20914
|
+
return statSync15(p).isDirectory();
|
|
20686
20915
|
} catch {
|
|
20687
20916
|
return false;
|
|
20688
20917
|
}
|
|
@@ -20856,7 +21085,7 @@ function lanesSection(lang9, probe) {
|
|
|
20856
21085
|
return lines2;
|
|
20857
21086
|
let plists = [];
|
|
20858
21087
|
try {
|
|
20859
|
-
plists =
|
|
21088
|
+
plists = readdirSync15(dir).filter((n) => n.startsWith("com.roll.") && n.endsWith(".plist")).sort();
|
|
20860
21089
|
} catch {
|
|
20861
21090
|
return lines2;
|
|
20862
21091
|
}
|
|
@@ -20887,7 +21116,7 @@ function launchdStaleSection(lang9) {
|
|
|
20887
21116
|
let found = false;
|
|
20888
21117
|
let plists = [];
|
|
20889
21118
|
try {
|
|
20890
|
-
plists =
|
|
21119
|
+
plists = readdirSync15(dir).filter((n) => n.startsWith("com.roll.") && n.endsWith(".plist")).sort();
|
|
20891
21120
|
} catch {
|
|
20892
21121
|
plists = [];
|
|
20893
21122
|
}
|
|
@@ -21231,14 +21460,14 @@ function readSkillBody(projectPath3, opts) {
|
|
|
21231
21460
|
}
|
|
21232
21461
|
|
|
21233
21462
|
// packages/cli/dist/commands/gc.js
|
|
21234
|
-
import { existsSync as existsSync39, readdirSync as
|
|
21463
|
+
import { existsSync as existsSync39, readdirSync as readdirSync16, rmSync as rmSync8, statSync as statSync16 } from "node:fs";
|
|
21235
21464
|
import { join as join35 } from "node:path";
|
|
21236
21465
|
var RUN_ID_RE = /^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}$/;
|
|
21237
21466
|
function runsInDir(dir) {
|
|
21238
21467
|
const out3 = [];
|
|
21239
21468
|
let entries = [];
|
|
21240
21469
|
try {
|
|
21241
|
-
entries =
|
|
21470
|
+
entries = readdirSync16(dir, { withFileTypes: true });
|
|
21242
21471
|
} catch {
|
|
21243
21472
|
return out3;
|
|
21244
21473
|
}
|
|
@@ -21246,7 +21475,7 @@ function runsInDir(dir) {
|
|
|
21246
21475
|
if (!e.isDirectory() || !RUN_ID_RE.test(e.name))
|
|
21247
21476
|
continue;
|
|
21248
21477
|
try {
|
|
21249
|
-
out3.push({ runId: e.name, mtimeSec: Math.floor(
|
|
21478
|
+
out3.push({ runId: e.name, mtimeSec: Math.floor(statSync16(join35(dir, e.name)).mtimeMs / 1e3) });
|
|
21250
21479
|
} catch {
|
|
21251
21480
|
}
|
|
21252
21481
|
}
|
|
@@ -21279,7 +21508,7 @@ function collectStoryArchives(projectPath3) {
|
|
|
21279
21508
|
}
|
|
21280
21509
|
function safeDirs(root) {
|
|
21281
21510
|
try {
|
|
21282
|
-
return
|
|
21511
|
+
return readdirSync16(root, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
21283
21512
|
} catch {
|
|
21284
21513
|
return [];
|
|
21285
21514
|
}
|
|
@@ -21321,7 +21550,7 @@ function gcCommand(args, deps = {}) {
|
|
|
21321
21550
|
lines2.push(` ${dryRun ? "would delete" : "deleted"}: ${sa.storyId}/${runId}`);
|
|
21322
21551
|
if (!dryRun) {
|
|
21323
21552
|
try {
|
|
21324
|
-
|
|
21553
|
+
rmSync8(join35(sa.dir, runId), { recursive: true, force: true });
|
|
21325
21554
|
} catch {
|
|
21326
21555
|
}
|
|
21327
21556
|
}
|
|
@@ -21639,9 +21868,9 @@ ${rowNote}`);
|
|
|
21639
21868
|
|
|
21640
21869
|
// packages/cli/dist/commands/init.js
|
|
21641
21870
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
21642
|
-
import { copyFileSync as copyFileSync2, existsSync as existsSync42, mkdirSync as mkdirSync25, readSync, readFileSync as readFileSync38, readdirSync as
|
|
21871
|
+
import { copyFileSync as copyFileSync2, existsSync as existsSync42, mkdirSync as mkdirSync25, readSync, readFileSync as readFileSync38, readdirSync as readdirSync17, realpathSync as realpathSync4, statSync as statSync17, writeFileSync as writeFileSync26 } from "node:fs";
|
|
21643
21872
|
import { homedir as homedir12 } from "node:os";
|
|
21644
|
-
import { dirname as
|
|
21873
|
+
import { dirname as dirname19, join as join40 } from "node:path";
|
|
21645
21874
|
function err10(line) {
|
|
21646
21875
|
const { RED, NC } = pal3();
|
|
21647
21876
|
process.stderr.write(`${RED}[roll]${NC} ${line}
|
|
@@ -21744,7 +21973,7 @@ function countNonEmptyFiles(dir) {
|
|
|
21744
21973
|
function isLegacyProject(projectDir) {
|
|
21745
21974
|
for (const dir of ["src", "app", "lib", "pkg", "cmd"]) {
|
|
21746
21975
|
const p = join40(projectDir, dir);
|
|
21747
|
-
if (existsSync42(p) &&
|
|
21976
|
+
if (existsSync42(p) && statSync17(p).isDirectory()) {
|
|
21748
21977
|
if (countNonEmptyFiles(p) >= 10)
|
|
21749
21978
|
return true;
|
|
21750
21979
|
}
|
|
@@ -21790,7 +22019,7 @@ function legacyFileSummary(projectDir) {
|
|
|
21790
22019
|
const parts = [];
|
|
21791
22020
|
for (const dir of ["src", "app", "lib", "pkg", "cmd"]) {
|
|
21792
22021
|
const p = join40(projectDir, dir);
|
|
21793
|
-
if (existsSync42(p) &&
|
|
22022
|
+
if (existsSync42(p) && statSync17(p).isDirectory()) {
|
|
21794
22023
|
const count = countNonEmptyFiles(p);
|
|
21795
22024
|
if (count >= 10)
|
|
21796
22025
|
parts.push(`${count} files in ${dir}/`);
|
|
@@ -21827,7 +22056,7 @@ function legacyFileSummary(projectDir) {
|
|
|
21827
22056
|
}
|
|
21828
22057
|
}
|
|
21829
22058
|
try {
|
|
21830
|
-
if (
|
|
22059
|
+
if (readdirSync17(projectDir).some((name) => name.endsWith(".tf")))
|
|
21831
22060
|
parts.push("Terraform .tf files");
|
|
21832
22061
|
} catch {
|
|
21833
22062
|
}
|
|
@@ -22186,12 +22415,12 @@ function writeBacklog(path, summary) {
|
|
|
22186
22415
|
summary.push("unchanged|.roll/backlog.md");
|
|
22187
22416
|
return;
|
|
22188
22417
|
}
|
|
22189
|
-
mkdirSync25(
|
|
22418
|
+
mkdirSync25(dirname19(path), { recursive: true });
|
|
22190
22419
|
writeFileSync26(path, BACKLOG_TEMPLATE);
|
|
22191
22420
|
summary.push("created|.roll/backlog.md");
|
|
22192
22421
|
}
|
|
22193
22422
|
function ensureFeaturesDir(path, summary) {
|
|
22194
|
-
if (existsSync42(path) &&
|
|
22423
|
+
if (existsSync42(path) && statSync17(path).isDirectory()) {
|
|
22195
22424
|
summary.push("unchanged|.roll/features/");
|
|
22196
22425
|
return;
|
|
22197
22426
|
}
|
|
@@ -22213,7 +22442,7 @@ function writeFeaturesMd(path, summary) {
|
|
|
22213
22442
|
summary.push("unchanged|.roll/features.md");
|
|
22214
22443
|
return;
|
|
22215
22444
|
}
|
|
22216
|
-
mkdirSync25(
|
|
22445
|
+
mkdirSync25(dirname19(path), { recursive: true });
|
|
22217
22446
|
writeFileSync26(path, FEATURES_TEMPLATE);
|
|
22218
22447
|
summary.push("created|.roll/features.md");
|
|
22219
22448
|
}
|
|
@@ -22227,7 +22456,7 @@ function initSeedAgentRoutes(templateName, projectDir, summary) {
|
|
|
22227
22456
|
if (!existsSync42(src)) {
|
|
22228
22457
|
return 1;
|
|
22229
22458
|
}
|
|
22230
|
-
mkdirSync25(
|
|
22459
|
+
mkdirSync25(dirname19(dest), { recursive: true });
|
|
22231
22460
|
copyFileSync2(src, dest);
|
|
22232
22461
|
summary.push("created|.roll/agent-routes.yaml");
|
|
22233
22462
|
return 0;
|
|
@@ -22254,7 +22483,7 @@ function scaffoldPairing(projectDir, summary) {
|
|
|
22254
22483
|
summary.push("unchanged|.roll/pairing.yaml");
|
|
22255
22484
|
return;
|
|
22256
22485
|
}
|
|
22257
|
-
mkdirSync25(
|
|
22486
|
+
mkdirSync25(dirname19(path), { recursive: true });
|
|
22258
22487
|
writeFileSync26(path, renderPairingConfig(defaultPairingConfig(agentsInstalled(realAgentEnv()))));
|
|
22259
22488
|
summary.push("created|.roll/pairing.yaml");
|
|
22260
22489
|
}
|
|
@@ -22289,7 +22518,7 @@ roll_version: "${changeset.rollVersion}"
|
|
|
22289
22518
|
}
|
|
22290
22519
|
function writeChangeset(projectDir, changeset) {
|
|
22291
22520
|
const path = changesetPath(projectDir);
|
|
22292
|
-
mkdirSync25(
|
|
22521
|
+
mkdirSync25(dirname19(path), { recursive: true });
|
|
22293
22522
|
writeFileSync26(path, renderChangeset(changeset));
|
|
22294
22523
|
}
|
|
22295
22524
|
function beginChangeset(projectDir) {
|
|
@@ -22803,16 +23032,16 @@ async function loopFmtCommand(args) {
|
|
|
22803
23032
|
|
|
22804
23033
|
// packages/cli/dist/commands/loop-maint.js
|
|
22805
23034
|
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
22806
|
-
import { existsSync as existsSync44, mkdirSync as mkdirSync27, readFileSync as readFileSync40, readdirSync as
|
|
23035
|
+
import { existsSync as existsSync44, mkdirSync as mkdirSync27, readFileSync as readFileSync40, readdirSync as readdirSync19, renameSync as renameSync6, rmSync as rmSync10, statSync as statSync18, writeFileSync as writeFileSync28 } from "node:fs";
|
|
22807
23036
|
import { homedir as homedir14 } from "node:os";
|
|
22808
|
-
import { basename as basename10, dirname as
|
|
23037
|
+
import { basename as basename10, dirname as dirname21, join as join42 } from "node:path";
|
|
22809
23038
|
|
|
22810
23039
|
// packages/cli/dist/commands/loop-sched.js
|
|
22811
23040
|
import { createHash as createHash4 } from "node:crypto";
|
|
22812
23041
|
import { spawn as spawn4, spawnSync as spawnSync5 } from "node:child_process";
|
|
22813
|
-
import { existsSync as existsSync43, mkdirSync as mkdirSync26, readFileSync as readFileSync39, renameSync as renameSync5, rmSync as
|
|
23042
|
+
import { existsSync as existsSync43, mkdirSync as mkdirSync26, readFileSync as readFileSync39, renameSync as renameSync5, rmSync as rmSync9, writeFileSync as writeFileSync27, readdirSync as readdirSync18 } from "node:fs";
|
|
22814
23043
|
import { homedir as homedir13 } from "node:os";
|
|
22815
|
-
import { dirname as
|
|
23044
|
+
import { dirname as dirname20, join as join41 } from "node:path";
|
|
22816
23045
|
function realDeps5() {
|
|
22817
23046
|
return {
|
|
22818
23047
|
identity: () => projectIdentity(),
|
|
@@ -22839,12 +23068,12 @@ function realDeps5() {
|
|
|
22839
23068
|
// the inner lock; Ctrl-C stops the TAIL only (the cycle lives in tmux).
|
|
22840
23069
|
observe: (rt) => new Promise((resolve4) => {
|
|
22841
23070
|
const lock = join41(rt, "inner.lock");
|
|
22842
|
-
const
|
|
23071
|
+
const tail2 = spawn4("tail", ["-n", "+1", "-F", join41(rt, "live.log")], { stdio: "inherit" });
|
|
22843
23072
|
let sawLock = false;
|
|
22844
23073
|
const t0 = Date.now();
|
|
22845
23074
|
const finish = () => {
|
|
22846
23075
|
try {
|
|
22847
|
-
|
|
23076
|
+
tail2.kill("SIGTERM");
|
|
22848
23077
|
} catch {
|
|
22849
23078
|
}
|
|
22850
23079
|
process.removeListener("SIGINT", finish);
|
|
@@ -23073,7 +23302,7 @@ function pathValue() {
|
|
|
23073
23302
|
].join(":");
|
|
23074
23303
|
}
|
|
23075
23304
|
function writeExecutable(path, content) {
|
|
23076
|
-
mkdirSync26(
|
|
23305
|
+
mkdirSync26(dirname20(path), { recursive: true });
|
|
23077
23306
|
writeFileSync27(path, content, { mode: 493 });
|
|
23078
23307
|
}
|
|
23079
23308
|
function pauseMarkerPath2(projectPath3, slug) {
|
|
@@ -23223,7 +23452,7 @@ async function loopOffCommand(_args, deps = realDeps5()) {
|
|
|
23223
23452
|
continue;
|
|
23224
23453
|
await deps.launchd.uninstall(uid, label4);
|
|
23225
23454
|
try {
|
|
23226
|
-
|
|
23455
|
+
rmSync9(join41(launchAgentsDir2(), `${label4}.plist`), { force: true });
|
|
23227
23456
|
} catch {
|
|
23228
23457
|
}
|
|
23229
23458
|
process.stdout.write(` swept zombie lane: ${label4}
|
|
@@ -23239,7 +23468,7 @@ function launchAgentsDir2() {
|
|
|
23239
23468
|
}
|
|
23240
23469
|
function listRollLaneLabels(slug) {
|
|
23241
23470
|
try {
|
|
23242
|
-
return
|
|
23471
|
+
return readdirSync18(launchAgentsDir2()).filter((n) => n.startsWith("com.roll.") && n.endsWith(`.${slug}.plist`)).map((n) => n.replace(/\.plist$/, "")).sort();
|
|
23243
23472
|
} catch {
|
|
23244
23473
|
return [];
|
|
23245
23474
|
}
|
|
@@ -23247,7 +23476,7 @@ function listRollLaneLabels(slug) {
|
|
|
23247
23476
|
async function loopPauseCommand(_args, deps = realDeps5()) {
|
|
23248
23477
|
const id = await deps.identity();
|
|
23249
23478
|
const marker = pauseMarkerPath2(id.path, id.slug);
|
|
23250
|
-
mkdirSync26(
|
|
23479
|
+
mkdirSync26(dirname20(marker), { recursive: true });
|
|
23251
23480
|
const already = existsSync43(marker);
|
|
23252
23481
|
if (!already)
|
|
23253
23482
|
writeFileSync27(marker, `${(/* @__PURE__ */ new Date()).toISOString()}
|
|
@@ -23264,7 +23493,7 @@ async function loopResumeCommand(_args, deps = realDeps5()) {
|
|
|
23264
23493
|
const id = await deps.identity();
|
|
23265
23494
|
const marker = pauseMarkerPath2(id.path, id.slug);
|
|
23266
23495
|
const existed = existsSync43(marker);
|
|
23267
|
-
|
|
23496
|
+
rmSync9(marker, { force: true });
|
|
23268
23497
|
const rt = join41(id.path, ".roll", "loop");
|
|
23269
23498
|
const counterFile = join41(rt, "consecutive-fails");
|
|
23270
23499
|
if (existsSync43(counterFile)) {
|
|
@@ -23284,7 +23513,7 @@ async function loopResumeCommand(_args, deps = realDeps5()) {
|
|
|
23284
23513
|
}
|
|
23285
23514
|
const healDir2 = join41((process.env["ROLL_LOOP_DIR"] ?? "").trim() || join41(homedir13(), ".shared", "roll", "loop"), "heal");
|
|
23286
23515
|
try {
|
|
23287
|
-
|
|
23516
|
+
rmSync9(healDir2, { recursive: true, force: true });
|
|
23288
23517
|
} catch {
|
|
23289
23518
|
}
|
|
23290
23519
|
if (existed) {
|
|
@@ -23404,25 +23633,25 @@ function loopResetCommand(_args = []) {
|
|
|
23404
23633
|
const slug = projectSlug2();
|
|
23405
23634
|
const state = stateFile(slug);
|
|
23406
23635
|
if (existsSync44(state)) {
|
|
23407
|
-
|
|
23636
|
+
rmSync10(state, { force: true });
|
|
23408
23637
|
ok6(msg5("loop.loop_state_cleared_will_start_fresh"));
|
|
23409
23638
|
} else {
|
|
23410
23639
|
info4(msg5("loop.no_loop_state_to_clear"));
|
|
23411
23640
|
}
|
|
23412
|
-
|
|
23641
|
+
rmSync10(healDir(), { recursive: true, force: true });
|
|
23413
23642
|
return 0;
|
|
23414
23643
|
}
|
|
23415
23644
|
function loopMuteCommand(_args = []) {
|
|
23416
23645
|
const slug = projectSlug2();
|
|
23417
23646
|
const file = muteFile(slug);
|
|
23418
|
-
mkdirSync27(
|
|
23647
|
+
mkdirSync27(dirname21(file), { recursive: true });
|
|
23419
23648
|
writeFileSync28(file, "");
|
|
23420
23649
|
ok6(msg5("loop.muted_auto_attach_disabled"));
|
|
23421
23650
|
return 0;
|
|
23422
23651
|
}
|
|
23423
23652
|
function loopUnmuteCommand(_args = []) {
|
|
23424
23653
|
const slug = projectSlug2();
|
|
23425
|
-
|
|
23654
|
+
rmSync10(muteFile(slug), { force: true });
|
|
23426
23655
|
ok6(msg5("loop.unmuted_auto_attach_live"));
|
|
23427
23656
|
return 0;
|
|
23428
23657
|
}
|
|
@@ -23438,7 +23667,7 @@ function realGcDeps() {
|
|
|
23438
23667
|
}
|
|
23439
23668
|
function fileMtimeSec(f) {
|
|
23440
23669
|
try {
|
|
23441
|
-
return Math.floor(
|
|
23670
|
+
return Math.floor(statSync18(f).mtimeMs / 1e3);
|
|
23442
23671
|
} catch {
|
|
23443
23672
|
return 0;
|
|
23444
23673
|
}
|
|
@@ -23453,7 +23682,7 @@ function plistWorkingDir(plistPath) {
|
|
|
23453
23682
|
}
|
|
23454
23683
|
function isDir2(p) {
|
|
23455
23684
|
try {
|
|
23456
|
-
return
|
|
23685
|
+
return statSync18(p).isDirectory();
|
|
23457
23686
|
} catch {
|
|
23458
23687
|
return false;
|
|
23459
23688
|
}
|
|
@@ -23464,7 +23693,7 @@ function gcStamp(d) {
|
|
|
23464
23693
|
}
|
|
23465
23694
|
function loopDirEntries(loopDir) {
|
|
23466
23695
|
try {
|
|
23467
|
-
return
|
|
23696
|
+
return readdirSync19(loopDir);
|
|
23468
23697
|
} catch {
|
|
23469
23698
|
return [];
|
|
23470
23699
|
}
|
|
@@ -23538,7 +23767,7 @@ function loopGcCommand(args = [], deps = realGcDeps()) {
|
|
|
23538
23767
|
`events-${slug}.ndjson`,
|
|
23539
23768
|
`cron-${slug}.log`
|
|
23540
23769
|
]) {
|
|
23541
|
-
|
|
23770
|
+
rmSync10(join42(loopDir, rel), { force: true });
|
|
23542
23771
|
}
|
|
23543
23772
|
gcCount++;
|
|
23544
23773
|
}
|
|
@@ -23554,7 +23783,7 @@ function loopGcCommand(args = [], deps = realGcDeps()) {
|
|
|
23554
23783
|
process.stdout.write(`[DRY-RUN] tmp debris: ${basename10(f)}
|
|
23555
23784
|
`);
|
|
23556
23785
|
else
|
|
23557
|
-
|
|
23786
|
+
rmSync10(f, { force: true });
|
|
23558
23787
|
gcCount++;
|
|
23559
23788
|
continue;
|
|
23560
23789
|
}
|
|
@@ -23564,7 +23793,7 @@ function loopGcCommand(args = [], deps = realGcDeps()) {
|
|
|
23564
23793
|
process.stdout.write(`[DRY-RUN] old backup: ${basename10(f)}
|
|
23565
23794
|
`);
|
|
23566
23795
|
else
|
|
23567
|
-
|
|
23796
|
+
rmSync10(f, { force: true });
|
|
23568
23797
|
gcCount++;
|
|
23569
23798
|
}
|
|
23570
23799
|
continue;
|
|
@@ -23575,7 +23804,7 @@ function loopGcCommand(args = [], deps = realGcDeps()) {
|
|
|
23575
23804
|
process.stdout.write(`[DRY-RUN] old migrated: ${basename10(f)}
|
|
23576
23805
|
`);
|
|
23577
23806
|
else
|
|
23578
|
-
|
|
23807
|
+
rmSync10(f, { force: true });
|
|
23579
23808
|
gcCount++;
|
|
23580
23809
|
}
|
|
23581
23810
|
continue;
|
|
@@ -23586,7 +23815,7 @@ function loopGcCommand(args = [], deps = realGcDeps()) {
|
|
|
23586
23815
|
process.stdout.write(`[DRY-RUN] old .bak: ${basename10(f)}
|
|
23587
23816
|
`);
|
|
23588
23817
|
else
|
|
23589
|
-
|
|
23818
|
+
rmSync10(f, { force: true });
|
|
23590
23819
|
gcCount++;
|
|
23591
23820
|
}
|
|
23592
23821
|
}
|
|
@@ -23598,7 +23827,7 @@ function loopGcCommand(args = [], deps = realGcDeps()) {
|
|
|
23598
23827
|
}
|
|
23599
23828
|
function statSafeIsFile(f) {
|
|
23600
23829
|
try {
|
|
23601
|
-
return
|
|
23830
|
+
return statSync18(f).isFile();
|
|
23602
23831
|
} catch {
|
|
23603
23832
|
return false;
|
|
23604
23833
|
}
|
|
@@ -23645,7 +23874,7 @@ function loopTestCommand(args = [], deps = realTestDeps()) {
|
|
|
23645
23874
|
if (cmd === "")
|
|
23646
23875
|
cmd = defaultSmokeCmd(agent);
|
|
23647
23876
|
const testRunner = join42(loopDir, `run-${slug}-test.sh`);
|
|
23648
|
-
mkdirSync27(
|
|
23877
|
+
mkdirSync27(dirname21(testRunner), { recursive: true });
|
|
23649
23878
|
writeFileSync28(testRunner, buildLoopTestRunnerScript({ projectPath: projectPath3, slug, cmd }), { mode: 493 });
|
|
23650
23879
|
info4(msg5("loop.generating_test_runner_agent", agent));
|
|
23651
23880
|
info4(msg5("loop.starting_smoke_test_agent", agent));
|
|
@@ -23663,14 +23892,14 @@ function loopTestCommand(args = [], deps = realTestDeps()) {
|
|
|
23663
23892
|
}
|
|
23664
23893
|
|
|
23665
23894
|
// packages/cli/dist/commands/loop-pr-inbox.js
|
|
23666
|
-
import { appendFileSync as appendFileSync11, mkdirSync as mkdirSync29, readFileSync as readFileSync42, writeFileSync as writeFileSync30, existsSync as existsSync46, rmSync as
|
|
23667
|
-
import { dirname as
|
|
23895
|
+
import { appendFileSync as appendFileSync11, mkdirSync as mkdirSync29, readFileSync as readFileSync42, writeFileSync as writeFileSync30, existsSync as existsSync46, rmSync as rmSync12 } from "node:fs";
|
|
23896
|
+
import { dirname as dirname23, join as join44 } from "node:path";
|
|
23668
23897
|
|
|
23669
23898
|
// packages/cli/dist/commands/loop-pr-heal.js
|
|
23670
23899
|
import { execFileSync as execFileSync12, spawn as spawn5 } from "node:child_process";
|
|
23671
|
-
import { appendFileSync as appendFileSync10, existsSync as existsSync45, mkdirSync as mkdirSync28, mkdtempSync as mkdtempSync4, readFileSync as readFileSync41, rmSync as
|
|
23900
|
+
import { appendFileSync as appendFileSync10, existsSync as existsSync45, mkdirSync as mkdirSync28, mkdtempSync as mkdtempSync4, readFileSync as readFileSync41, rmSync as rmSync11, writeFileSync as writeFileSync29 } from "node:fs";
|
|
23672
23901
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
23673
|
-
import { dirname as
|
|
23902
|
+
import { dirname as dirname22, join as join43 } from "node:path";
|
|
23674
23903
|
function runtimeDir3() {
|
|
23675
23904
|
const o = (process.env["ROLL_PROJECT_RUNTIME_DIR"] ?? "").trim();
|
|
23676
23905
|
return o !== "" ? o : join43(process.cwd(), ".roll", "loop");
|
|
@@ -23703,7 +23932,7 @@ function realHealDeps() {
|
|
|
23703
23932
|
healMax: () => resolveHealMax(process.env["ROLL_LOOP_NO_HEAL"], process.env["ROLL_LOOP_HEAL_MAX"]),
|
|
23704
23933
|
prHealCount: (num4) => parseInt(stateGet(readState(), `heal_count.pr:${num4}`) || "0", 10) || 0,
|
|
23705
23934
|
setPrHealCount: (num4, n) => {
|
|
23706
|
-
mkdirSync28(
|
|
23935
|
+
mkdirSync28(dirname22(statePath()), { recursive: true });
|
|
23707
23936
|
writeFileSync29(statePath(), stateUpsert(readState(), `heal_count.pr:${num4}`, n));
|
|
23708
23937
|
},
|
|
23709
23938
|
lock: (num4) => {
|
|
@@ -23726,7 +23955,7 @@ function realHealDeps() {
|
|
|
23726
23955
|
}
|
|
23727
23956
|
return { lockPresent: true, lockPidAlive: alive };
|
|
23728
23957
|
},
|
|
23729
|
-
reclaimLock: (num4) =>
|
|
23958
|
+
reclaimLock: (num4) => rmSync11(lockPath(num4), { force: true }),
|
|
23730
23959
|
writeLock: (num4) => {
|
|
23731
23960
|
mkdirSync28(healDir(), { recursive: true });
|
|
23732
23961
|
writeFileSync29(lockPath(num4), String(process.pid));
|
|
@@ -23739,7 +23968,7 @@ function realHealDeps() {
|
|
|
23739
23968
|
}
|
|
23740
23969
|
},
|
|
23741
23970
|
appendAlert: (line) => {
|
|
23742
|
-
mkdirSync28(
|
|
23971
|
+
mkdirSync28(dirname22(alertPath2()), { recursive: true });
|
|
23743
23972
|
appendFileSync10(alertPath2(), line + "\n");
|
|
23744
23973
|
},
|
|
23745
23974
|
now: nowIso,
|
|
@@ -23819,7 +24048,7 @@ ${gh2(["-R", repo, "run", "view", runId, "--log-failed"]).split("\n").slice(-200
|
|
|
23819
24048
|
execFileSync12("git", ["fetch", "origin", headRef], { stdio: "ignore" });
|
|
23820
24049
|
execFileSync12("git", ["worktree", "add", wt, `origin/${headRef}`], { stdio: "ignore" });
|
|
23821
24050
|
} catch {
|
|
23822
|
-
|
|
24051
|
+
rmSync11(tmpRoot, { recursive: true, force: true });
|
|
23823
24052
|
return 1;
|
|
23824
24053
|
}
|
|
23825
24054
|
const agent = projectAgent() || "claude";
|
|
@@ -23841,7 +24070,7 @@ ${gh2(["-R", repo, "run", "view", runId, "--log-failed"]).split("\n").slice(-200
|
|
|
23841
24070
|
execFileSync12("git", ["worktree", "remove", "--force", wt], { stdio: "ignore" });
|
|
23842
24071
|
} catch {
|
|
23843
24072
|
}
|
|
23844
|
-
|
|
24073
|
+
rmSync11(tmpRoot, { recursive: true, force: true });
|
|
23845
24074
|
return 0;
|
|
23846
24075
|
}
|
|
23847
24076
|
function realRebaseDeps() {
|
|
@@ -23901,7 +24130,7 @@ function realRebaseDeps() {
|
|
|
23901
24130
|
}
|
|
23902
24131
|
},
|
|
23903
24132
|
appendAlert: (line) => {
|
|
23904
|
-
mkdirSync28(
|
|
24133
|
+
mkdirSync28(dirname22(alertPath2()), { recursive: true });
|
|
23905
24134
|
appendFileSync10(alertPath2(), line + "\n");
|
|
23906
24135
|
},
|
|
23907
24136
|
now: () => (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z")
|
|
@@ -24051,7 +24280,7 @@ function nowSec() {
|
|
|
24051
24280
|
}
|
|
24052
24281
|
function writeTickFile(tick) {
|
|
24053
24282
|
const file = tickPath();
|
|
24054
|
-
mkdirSync29(
|
|
24283
|
+
mkdirSync29(dirname23(file), { recursive: true });
|
|
24055
24284
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
24056
24285
|
appendFileSync11(file, `${JSON.stringify({ ts, ...tick })}
|
|
24057
24286
|
`);
|
|
@@ -24093,14 +24322,14 @@ function checkDeadTickStreak(file, alert, markerPath = deadTickMarkerPath()) {
|
|
|
24093
24322
|
} else if (verdict === "recovered") {
|
|
24094
24323
|
alert("pr-loop recovered: healthy tick after an alerted dead-tick streak (FIX-233)");
|
|
24095
24324
|
try {
|
|
24096
|
-
|
|
24325
|
+
rmSync12(markerPath, { force: true });
|
|
24097
24326
|
} catch {
|
|
24098
24327
|
}
|
|
24099
24328
|
}
|
|
24100
24329
|
}
|
|
24101
24330
|
function appendAlert(line) {
|
|
24102
24331
|
const file = alertPath3();
|
|
24103
|
-
mkdirSync29(
|
|
24332
|
+
mkdirSync29(dirname23(file), { recursive: true });
|
|
24104
24333
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
24105
24334
|
appendFileSync11(file, `[${ts}] ${line}
|
|
24106
24335
|
`);
|
|
@@ -24116,7 +24345,7 @@ function rebaseCircuitAllowed(num4) {
|
|
|
24116
24345
|
writeRebaseAttempts(state, num4, verdict.freshTimestamps);
|
|
24117
24346
|
if (!verdict.allowed) {
|
|
24118
24347
|
const file = alertPath3();
|
|
24119
|
-
mkdirSync29(
|
|
24348
|
+
mkdirSync29(dirname23(file), { recursive: true });
|
|
24120
24349
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().slice(0, 16).replace("T", " ");
|
|
24121
24350
|
writeFileSync30(file, [
|
|
24122
24351
|
`# ALERT \u2014 PR rebase circuit breaker tripped`,
|
|
@@ -24172,7 +24401,7 @@ function upsertRebaseAttempts(stateBody, pr, value) {
|
|
|
24172
24401
|
`;
|
|
24173
24402
|
}
|
|
24174
24403
|
function writeRebaseAttempts(state, pr, timestamps) {
|
|
24175
|
-
mkdirSync29(
|
|
24404
|
+
mkdirSync29(dirname23(state), { recursive: true });
|
|
24176
24405
|
let body = "";
|
|
24177
24406
|
try {
|
|
24178
24407
|
body = readFileSync42(state, "utf8");
|
|
@@ -24255,20 +24484,20 @@ async function loopPrInboxCommand(_args, deps = realDeps6()) {
|
|
|
24255
24484
|
|
|
24256
24485
|
// packages/cli/dist/commands/loop-run-once.js
|
|
24257
24486
|
import { appendFileSync as appendFileSync15, existsSync as existsSync55, mkdirSync as mkdirSync34, readFileSync as readFileSync51, writeFileSync as writeFileSync36 } from "node:fs";
|
|
24258
|
-
import { dirname as
|
|
24487
|
+
import { dirname as dirname28, join as join54 } from "node:path";
|
|
24259
24488
|
|
|
24260
24489
|
// packages/cli/dist/runner/executor.js
|
|
24261
|
-
import { execFile as
|
|
24262
|
-
import { appendFileSync as appendFileSync13, existsSync as existsSync53, lstatSync as lstatSync2, mkdirSync as mkdirSync32, readdirSync as
|
|
24263
|
-
import { dirname as
|
|
24264
|
-
import { promisify as
|
|
24490
|
+
import { execFile as execFile10 } from "node:child_process";
|
|
24491
|
+
import { appendFileSync as appendFileSync13, existsSync as existsSync53, lstatSync as lstatSync2, mkdirSync as mkdirSync32, readdirSync as readdirSync24, readFileSync as readFileSync48, realpathSync as realpathSync5, rmSync as rmSync13, symlinkSync as symlinkSync3, unlinkSync, writeFileSync as writeFileSync33 } from "node:fs";
|
|
24492
|
+
import { dirname as dirname26, join as join52 } from "node:path";
|
|
24493
|
+
import { promisify as promisify10 } from "node:util";
|
|
24265
24494
|
|
|
24266
24495
|
// packages/cli/dist/runner/peer-gate.js
|
|
24267
|
-
import { execFile as
|
|
24268
|
-
import { existsSync as existsSync47, readdirSync as
|
|
24496
|
+
import { execFile as execFile9 } from "node:child_process";
|
|
24497
|
+
import { existsSync as existsSync47, readdirSync as readdirSync20 } from "node:fs";
|
|
24269
24498
|
import { join as join45 } from "node:path";
|
|
24270
|
-
import { promisify as
|
|
24271
|
-
var
|
|
24499
|
+
import { promisify as promisify9 } from "node:util";
|
|
24500
|
+
var execFileAsync9 = promisify9(execFile9);
|
|
24272
24501
|
var HIGH_RISK = [/^\.github\/workflows\//, /^packages\/infra\/src\/(git|github|process)\.ts$/];
|
|
24273
24502
|
function assessComplexity(files) {
|
|
24274
24503
|
const reasons = [];
|
|
@@ -24289,7 +24518,7 @@ function assessComplexity(files) {
|
|
|
24289
24518
|
}
|
|
24290
24519
|
async function cycleChangedFiles(worktreeCwd) {
|
|
24291
24520
|
try {
|
|
24292
|
-
const { stdout } = await
|
|
24521
|
+
const { stdout } = await execFileAsync9("git", ["diff", "--name-only", "origin/main...HEAD"], { cwd: worktreeCwd, encoding: "utf8" });
|
|
24293
24522
|
return stdout.split("\n").map((l) => l.trim()).filter((l) => l !== "");
|
|
24294
24523
|
} catch {
|
|
24295
24524
|
return [];
|
|
@@ -24300,7 +24529,7 @@ function peerEvidencePresent(runtimeDir6, cycleId) {
|
|
|
24300
24529
|
if (!existsSync47(dir))
|
|
24301
24530
|
return false;
|
|
24302
24531
|
try {
|
|
24303
|
-
return
|
|
24532
|
+
return readdirSync20(dir).some((f) => f.startsWith(`cycle-${cycleId}.`));
|
|
24304
24533
|
} catch {
|
|
24305
24534
|
return false;
|
|
24306
24535
|
}
|
|
@@ -24324,8 +24553,8 @@ async function runPeerGate(worktreeCwd, runtimeDir6, cycleId, sinks) {
|
|
|
24324
24553
|
}
|
|
24325
24554
|
|
|
24326
24555
|
// packages/cli/dist/runner/attest-gate.js
|
|
24327
|
-
import { existsSync as existsSync48, readFileSync as readFileSync43, readdirSync as
|
|
24328
|
-
import { join as join46 } from "node:path";
|
|
24556
|
+
import { existsSync as existsSync48, readFileSync as readFileSync43, readdirSync as readdirSync21, statSync as statSync19 } from "node:fs";
|
|
24557
|
+
import { dirname as dirname24, join as join46 } from "node:path";
|
|
24329
24558
|
function reportCandidates(worktreeCwd, storyId) {
|
|
24330
24559
|
return [join46(cardArchiveDir(worktreeCwd, storyId), "latest", reportFileName(storyId))];
|
|
24331
24560
|
}
|
|
@@ -24335,7 +24564,7 @@ function acMapCandidates(worktreeCwd, storyId) {
|
|
|
24335
24564
|
function storySpecPath(worktreeCwd, storyId) {
|
|
24336
24565
|
const featuresDir = join46(worktreeCwd, ".roll", "features");
|
|
24337
24566
|
try {
|
|
24338
|
-
for (const epic of
|
|
24567
|
+
for (const epic of readdirSync21(featuresDir, { withFileTypes: true })) {
|
|
24339
24568
|
if (!epic.isDirectory())
|
|
24340
24569
|
continue;
|
|
24341
24570
|
const spec = join46(featuresDir, epic.name, storyId, "spec.md");
|
|
@@ -24355,7 +24584,7 @@ function storyHasAcBlock(worktreeCwd, storyId) {
|
|
|
24355
24584
|
if (spec === null)
|
|
24356
24585
|
return null;
|
|
24357
24586
|
try {
|
|
24358
|
-
return
|
|
24587
|
+
return acForStory(readFileSync43(spec, "utf8"), storyId, { fileOwned: true }).length > 0;
|
|
24359
24588
|
} catch {
|
|
24360
24589
|
return null;
|
|
24361
24590
|
}
|
|
@@ -24370,13 +24599,64 @@ function storyRequiresScreenshot(worktreeCwd, storyId) {
|
|
|
24370
24599
|
return false;
|
|
24371
24600
|
}
|
|
24372
24601
|
}
|
|
24602
|
+
function readAcMapEntries(worktreeCwd, storyId) {
|
|
24603
|
+
const path = acMapCandidates(worktreeCwd, storyId)[0];
|
|
24604
|
+
if (path === void 0 || !existsSync48(path))
|
|
24605
|
+
return null;
|
|
24606
|
+
try {
|
|
24607
|
+
const parsed = JSON.parse(readFileSync43(path, "utf8"));
|
|
24608
|
+
return Array.isArray(parsed) ? parsed.filter((x) => typeof x === "object" && x !== null) : null;
|
|
24609
|
+
} catch {
|
|
24610
|
+
return null;
|
|
24611
|
+
}
|
|
24612
|
+
}
|
|
24613
|
+
function evidenceManifest(worktreeCwd, storyId) {
|
|
24614
|
+
const report = existingReport(worktreeCwd, storyId);
|
|
24615
|
+
if (report === null)
|
|
24616
|
+
return null;
|
|
24617
|
+
const path = join46(dirname24(report), "evidence.json");
|
|
24618
|
+
if (!existsSync48(path))
|
|
24619
|
+
return null;
|
|
24620
|
+
try {
|
|
24621
|
+
const parsed = JSON.parse(readFileSync43(path, "utf8"));
|
|
24622
|
+
return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : null;
|
|
24623
|
+
} catch {
|
|
24624
|
+
return null;
|
|
24625
|
+
}
|
|
24626
|
+
}
|
|
24627
|
+
function hasMachineCaptureSkip2(worktreeCwd, storyId) {
|
|
24628
|
+
const manifest = evidenceManifest(worktreeCwd, storyId);
|
|
24629
|
+
if (manifest === null || !Array.isArray(manifest.captures))
|
|
24630
|
+
return false;
|
|
24631
|
+
return manifest.captures.some((raw) => {
|
|
24632
|
+
if (typeof raw !== "object" || raw === null)
|
|
24633
|
+
return false;
|
|
24634
|
+
const row2 = raw;
|
|
24635
|
+
return row2["taken"] === false && typeof row2["skipped"] === "string" && row2["skipped"] !== "";
|
|
24636
|
+
});
|
|
24637
|
+
}
|
|
24638
|
+
function passAcVisualFloor(worktreeCwd, storyId) {
|
|
24639
|
+
const entries = readAcMapEntries(worktreeCwd, storyId);
|
|
24640
|
+
if (entries === null)
|
|
24641
|
+
return { ok: true };
|
|
24642
|
+
const pass = entries.filter((e) => e.status === "pass");
|
|
24643
|
+
if (pass.length === 0)
|
|
24644
|
+
return { ok: true };
|
|
24645
|
+
const missing = pass.filter((e) => !(e.evidence ?? []).some((ev) => ev.kind === "screenshot" && typeof ev.href === "string" && ev.href !== ""));
|
|
24646
|
+
if (missing.length === 0)
|
|
24647
|
+
return { ok: true };
|
|
24648
|
+
if (hasMachineCaptureSkip2(worktreeCwd, storyId))
|
|
24649
|
+
return { ok: true, reason: "machine capture skip present" };
|
|
24650
|
+
const ids = missing.map((e) => e.ac ?? "?").join(", ");
|
|
24651
|
+
return { ok: false, reason: `pass AC(s) lack screenshot evidence or machine capture skip: ${ids}` };
|
|
24652
|
+
}
|
|
24373
24653
|
function verificationReportPath(worktreeCwd, storyId) {
|
|
24374
24654
|
return reportCandidates(worktreeCwd, storyId)[0];
|
|
24375
24655
|
}
|
|
24376
24656
|
function existingReport(worktreeCwd, storyId) {
|
|
24377
24657
|
for (const p of reportCandidates(worktreeCwd, storyId)) {
|
|
24378
24658
|
try {
|
|
24379
|
-
if (
|
|
24659
|
+
if (statSync19(p).isFile())
|
|
24380
24660
|
return p;
|
|
24381
24661
|
} catch {
|
|
24382
24662
|
}
|
|
@@ -24390,7 +24670,7 @@ function verificationReportFresh(worktreeCwd, storyId, sinceSec) {
|
|
|
24390
24670
|
if (p === null)
|
|
24391
24671
|
return false;
|
|
24392
24672
|
try {
|
|
24393
|
-
const st =
|
|
24673
|
+
const st = statSync19(p);
|
|
24394
24674
|
if (sinceSec === void 0)
|
|
24395
24675
|
return true;
|
|
24396
24676
|
return st.mtimeMs / 1e3 >= sinceSec;
|
|
@@ -24424,8 +24704,10 @@ function verificationReportHasContent(worktreeCwd, storyId) {
|
|
|
24424
24704
|
}
|
|
24425
24705
|
if (positiveWithEvidence === 0)
|
|
24426
24706
|
return false;
|
|
24707
|
+
if (!passAcVisualFloor(worktreeCwd, storyId).ok)
|
|
24708
|
+
return false;
|
|
24427
24709
|
if (storyRequiresScreenshot(worktreeCwd, storyId)) {
|
|
24428
|
-
return /<figure class="shot\b|href="screenshots\/|src="screenshots
|
|
24710
|
+
return /<figure class="shot\b|href="screenshots\/|src="screenshots\//i.test(html) || hasMachineCaptureSkip2(worktreeCwd, storyId);
|
|
24429
24711
|
}
|
|
24430
24712
|
return true;
|
|
24431
24713
|
} catch {
|
|
@@ -24453,7 +24735,8 @@ function runAttestGate(worktreeCwd, storyId, cycleId, mode, sinceSec, sinks) {
|
|
|
24453
24735
|
if (fresh && verificationReportHasContent(worktreeCwd, storyId)) {
|
|
24454
24736
|
const score = evaluateSelfScoreGate(worktreeCwd, storyId);
|
|
24455
24737
|
if (score.status === "pass") {
|
|
24456
|
-
const
|
|
24738
|
+
const visual = passAcVisualFloor(worktreeCwd, storyId);
|
|
24739
|
+
const reasons3 = ["fresh acceptance report present", score.reason, ...visual.reason !== void 0 ? [visual.reason] : []];
|
|
24457
24740
|
sinks.event({ cycleId, verdict: "produced", reasons: reasons3 });
|
|
24458
24741
|
return { verdict: "produced", mode, reasons: reasons3, blocked: false };
|
|
24459
24742
|
}
|
|
@@ -24477,7 +24760,7 @@ function runAttestGate(worktreeCwd, storyId, cycleId, mode, sinceSec, sinks) {
|
|
|
24477
24760
|
}
|
|
24478
24761
|
|
|
24479
24762
|
// packages/cli/dist/runner/usage-recovery.js
|
|
24480
|
-
import { readFileSync as readFileSync44, readdirSync as
|
|
24763
|
+
import { readFileSync as readFileSync44, readdirSync as readdirSync22, statSync as statSync20 } from "node:fs";
|
|
24481
24764
|
import { homedir as homedir15 } from "node:os";
|
|
24482
24765
|
import { join as join47 } from "node:path";
|
|
24483
24766
|
function defaultPiSessionsRoot() {
|
|
@@ -24490,7 +24773,7 @@ function recoverPiUsage(worktreeCwd, sinceSec, sessionsRoot = defaultPiSessionsR
|
|
|
24490
24773
|
const dir = piSessionsDirFor(sessionsRoot, worktreeCwd);
|
|
24491
24774
|
let files;
|
|
24492
24775
|
try {
|
|
24493
|
-
files =
|
|
24776
|
+
files = readdirSync22(dir).filter((f) => f.endsWith(".jsonl"));
|
|
24494
24777
|
} catch {
|
|
24495
24778
|
return null;
|
|
24496
24779
|
}
|
|
@@ -24498,7 +24781,7 @@ function recoverPiUsage(worktreeCwd, sinceSec, sessionsRoot = defaultPiSessionsR
|
|
|
24498
24781
|
for (const f of files) {
|
|
24499
24782
|
const p = join47(dir, f);
|
|
24500
24783
|
try {
|
|
24501
|
-
if (sinceSec !== void 0 &&
|
|
24784
|
+
if (sinceSec !== void 0 && statSync20(p).mtimeMs / 1e3 < sinceSec)
|
|
24502
24785
|
continue;
|
|
24503
24786
|
summaries.push(sumPiSession(readFileSync44(p, "utf8").split("\n")));
|
|
24504
24787
|
} catch {
|
|
@@ -24620,8 +24903,8 @@ function buildAcMapRemediationPrompt(worktreeCwd, storyId, runDir) {
|
|
|
24620
24903
|
}
|
|
24621
24904
|
|
|
24622
24905
|
// packages/cli/dist/runner/correction-actuator.js
|
|
24623
|
-
import { appendFileSync as appendFileSync12, existsSync as existsSync51, mkdirSync as mkdirSync30, readFileSync as readFileSync46, readdirSync as
|
|
24624
|
-
import { dirname as
|
|
24906
|
+
import { appendFileSync as appendFileSync12, existsSync as existsSync51, mkdirSync as mkdirSync30, readFileSync as readFileSync46, readdirSync as readdirSync23, writeFileSync as writeFileSync31 } from "node:fs";
|
|
24907
|
+
import { dirname as dirname25, join as join50 } from "node:path";
|
|
24625
24908
|
function readMode(projectPath3) {
|
|
24626
24909
|
try {
|
|
24627
24910
|
const path = join50(projectPath3, ".roll", "policy.yaml");
|
|
@@ -24641,7 +24924,7 @@ function readEvents2(eventsPath4) {
|
|
|
24641
24924
|
}
|
|
24642
24925
|
function appendEvent(eventsPath4, event) {
|
|
24643
24926
|
try {
|
|
24644
|
-
mkdirSync30(
|
|
24927
|
+
mkdirSync30(dirname25(eventsPath4), { recursive: true });
|
|
24645
24928
|
appendFileSync12(eventsPath4, `${JSON.stringify(event)}
|
|
24646
24929
|
`, "utf8");
|
|
24647
24930
|
} catch {
|
|
@@ -24649,7 +24932,7 @@ function appendEvent(eventsPath4, event) {
|
|
|
24649
24932
|
}
|
|
24650
24933
|
function appendAlert2(alertsPath, msg6) {
|
|
24651
24934
|
try {
|
|
24652
|
-
mkdirSync30(
|
|
24935
|
+
mkdirSync30(dirname25(alertsPath), { recursive: true });
|
|
24653
24936
|
appendFileSync12(alertsPath, `${msg6}
|
|
24654
24937
|
`, "utf8");
|
|
24655
24938
|
} catch {
|
|
@@ -24681,7 +24964,7 @@ function storyEpic(projectPath3, storyId) {
|
|
|
24681
24964
|
}
|
|
24682
24965
|
try {
|
|
24683
24966
|
const features = join50(projectPath3, ".roll", "features");
|
|
24684
|
-
for (const d of
|
|
24967
|
+
for (const d of readdirSync23(features, { withFileTypes: true })) {
|
|
24685
24968
|
if (!d.isDirectory())
|
|
24686
24969
|
continue;
|
|
24687
24970
|
if (existsSync51(join50(features, d.name, storyId)))
|
|
@@ -24881,14 +25164,14 @@ async function runPairing(projectDir, worktreeCwd, runtimeDir6, cycleId, working
|
|
|
24881
25164
|
}
|
|
24882
25165
|
|
|
24883
25166
|
// packages/cli/dist/runner/executor.js
|
|
24884
|
-
var
|
|
25167
|
+
var execFileAsync10 = promisify10(execFile10);
|
|
24885
25168
|
function createCaptureMarkerSink(runDir, capture) {
|
|
24886
25169
|
let buf = "";
|
|
24887
25170
|
const pending = [];
|
|
24888
25171
|
const logPath = join52(runDir, "evidence", "capture-markers.log");
|
|
24889
25172
|
const record2 = (marker, result) => {
|
|
24890
25173
|
try {
|
|
24891
|
-
mkdirSync32(
|
|
25174
|
+
mkdirSync32(dirname26(logPath), { recursive: true });
|
|
24892
25175
|
appendFileSync13(logPath, JSON.stringify({ marker, result }) + "\n", "utf8");
|
|
24893
25176
|
} catch {
|
|
24894
25177
|
}
|
|
@@ -25008,7 +25291,7 @@ async function executeCommand(cmd, ports, ctx) {
|
|
|
25008
25291
|
// execute: spawn the agent (TCR commits happen inside the worktree). The
|
|
25009
25292
|
// exit code + timeout feed back as agent_exited; usage is captured for cost.
|
|
25010
25293
|
case "spawn_agent": {
|
|
25011
|
-
const livePath = join52(
|
|
25294
|
+
const livePath = join52(dirname26(ports.paths.eventsPath), "live.log");
|
|
25012
25295
|
try {
|
|
25013
25296
|
writeFileSync33(livePath, `\u2500\u2500 cycle ${ctx.cycleId ?? "?"} \xB7 ${ctx.storyId ?? "?"} \xB7 agent ${cmd.agent} \u2500\u2500
|
|
25014
25297
|
`);
|
|
@@ -25038,7 +25321,7 @@ async function executeCommand(cmd, ports, ctx) {
|
|
|
25038
25321
|
await captureSink?.flush();
|
|
25039
25322
|
persistWorktreeAlerts(ports.paths.worktreePath, ports.paths.alertsPath, ports.events);
|
|
25040
25323
|
try {
|
|
25041
|
-
const logDir = join52(
|
|
25324
|
+
const logDir = join52(dirname26(ports.paths.eventsPath), "cycle-logs");
|
|
25042
25325
|
mkdirSync32(logDir, { recursive: true });
|
|
25043
25326
|
writeFileSync33(join52(logDir, `${ctx.cycleId ?? "cycle"}.agent.log`), `# exit=${res.exitCode} timedOut=${res.timedOut}
|
|
25044
25327
|
--- stdout ---
|
|
@@ -25100,7 +25383,7 @@ ${res.stderr}
|
|
|
25100
25383
|
tcrCount = await ports.git.tcrCount(ports.paths.worktreePath);
|
|
25101
25384
|
} catch {
|
|
25102
25385
|
}
|
|
25103
|
-
await runPeerGate(ports.paths.worktreePath,
|
|
25386
|
+
await runPeerGate(ports.paths.worktreePath, dirname26(ports.paths.eventsPath), ctx.cycleId ?? "", {
|
|
25104
25387
|
alert: (m7) => ports.events.appendAlert(ports.paths.alertsPath, m7),
|
|
25105
25388
|
event: (p) => ports.events.appendEvent(ports.paths.eventsPath, {
|
|
25106
25389
|
type: "peer:gate",
|
|
@@ -25155,7 +25438,7 @@ DIFF:
|
|
|
25155
25438
|
changedFiles: cycleChangedFiles,
|
|
25156
25439
|
diff: async (cwd) => {
|
|
25157
25440
|
try {
|
|
25158
|
-
const { stdout } = await
|
|
25441
|
+
const { stdout } = await execFileAsync10("git", ["diff", "origin/main...HEAD"], { cwd, encoding: "utf8" });
|
|
25159
25442
|
return stdout.slice(0, 6e4);
|
|
25160
25443
|
} catch {
|
|
25161
25444
|
return "";
|
|
@@ -25165,7 +25448,7 @@ DIFF:
|
|
|
25165
25448
|
now: () => ports.clock()
|
|
25166
25449
|
};
|
|
25167
25450
|
for (const stage of enabledPairingStages(ports.repoCwd)) {
|
|
25168
|
-
await runPairing(ports.repoCwd, ports.paths.worktreePath,
|
|
25451
|
+
await runPairing(ports.repoCwd, ports.paths.worktreePath, dirname26(ports.paths.eventsPath), ctx.cycleId ?? "", ctx.agent ?? "", stage, pairingDeps);
|
|
25169
25452
|
}
|
|
25170
25453
|
}
|
|
25171
25454
|
const storyId = ctx.storyId ?? "";
|
|
@@ -25489,13 +25772,13 @@ function agentWritableRoots(repoCwd, alertsPath) {
|
|
|
25489
25772
|
const rollDir = join52(repoCwd, ".roll");
|
|
25490
25773
|
if (existsSync53(rollDir))
|
|
25491
25774
|
add(rollDir);
|
|
25492
|
-
add(
|
|
25775
|
+
add(dirname26(alertsPath));
|
|
25493
25776
|
return roots;
|
|
25494
25777
|
}
|
|
25495
25778
|
function persistWorktreeAlerts(worktreePath, alertsPath, events) {
|
|
25496
25779
|
let names;
|
|
25497
25780
|
try {
|
|
25498
|
-
names =
|
|
25781
|
+
names = readdirSync24(worktreePath).filter((n) => /^ALERT.*\.md$/i.test(n));
|
|
25499
25782
|
} catch {
|
|
25500
25783
|
return;
|
|
25501
25784
|
}
|
|
@@ -25527,16 +25810,16 @@ async function linkRollIntoWorktree(repoCwd, worktreePath) {
|
|
|
25527
25810
|
const incompleteFossil = existsSync53(join52(src, "backlog.md")) && !existsSync53(join52(dst, "backlog.md"));
|
|
25528
25811
|
if (!incompleteFossil)
|
|
25529
25812
|
return;
|
|
25530
|
-
|
|
25813
|
+
rmSync13(dst, { recursive: true, force: true });
|
|
25531
25814
|
}
|
|
25532
25815
|
symlinkSync3(src, dst);
|
|
25533
|
-
const common = (await
|
|
25816
|
+
const common = (await execFileAsync10("git", ["-C", repoCwd, "rev-parse", "--path-format=absolute", "--git-common-dir"])).stdout.trim();
|
|
25534
25817
|
if (common === "")
|
|
25535
25818
|
return;
|
|
25536
25819
|
const exclude = join52(common, "info", "exclude");
|
|
25537
25820
|
const cur = existsSync53(exclude) ? readFileSync48(exclude, "utf8") : "";
|
|
25538
25821
|
if (!/^\.roll$/m.test(cur)) {
|
|
25539
|
-
mkdirSync32(
|
|
25822
|
+
mkdirSync32(dirname26(exclude), { recursive: true });
|
|
25540
25823
|
appendFileSync13(exclude, `${cur === "" || cur.endsWith("\n") ? "" : "\n"}.roll
|
|
25541
25824
|
`, "utf8");
|
|
25542
25825
|
}
|
|
@@ -25567,7 +25850,7 @@ function nodePorts(opts) {
|
|
|
25567
25850
|
return push(repoCwd, branch);
|
|
25568
25851
|
},
|
|
25569
25852
|
async commitsAhead(worktreeCwd) {
|
|
25570
|
-
const r = await
|
|
25853
|
+
const r = await execFileAsync10("git", ["rev-list", "--count", "origin/main..HEAD"], {
|
|
25571
25854
|
cwd: worktreeCwd,
|
|
25572
25855
|
encoding: "utf8"
|
|
25573
25856
|
}).catch(() => ({ stdout: "0" }));
|
|
@@ -25575,7 +25858,7 @@ function nodePorts(opts) {
|
|
|
25575
25858
|
return Number.isFinite(n) ? n : 0;
|
|
25576
25859
|
},
|
|
25577
25860
|
async mainAhead(repoCwd) {
|
|
25578
|
-
const r = await
|
|
25861
|
+
const r = await execFileAsync10("git", ["rev-list", "--count", "origin/main..main"], {
|
|
25579
25862
|
cwd: repoCwd,
|
|
25580
25863
|
encoding: "utf8"
|
|
25581
25864
|
}).catch(() => ({ stdout: "0" }));
|
|
@@ -25583,7 +25866,7 @@ function nodePorts(opts) {
|
|
|
25583
25866
|
return Number.isFinite(n) ? n : 0;
|
|
25584
25867
|
},
|
|
25585
25868
|
async tcrCount(worktreeCwd) {
|
|
25586
|
-
const r = await
|
|
25869
|
+
const r = await execFileAsync10("git", ["log", "--oneline", "origin/main..HEAD"], {
|
|
25587
25870
|
cwd: worktreeCwd,
|
|
25588
25871
|
encoding: "utf8"
|
|
25589
25872
|
}).catch(() => ({ stdout: "" }));
|
|
@@ -25688,7 +25971,7 @@ function nodePorts(opts) {
|
|
|
25688
25971
|
};
|
|
25689
25972
|
}
|
|
25690
25973
|
function appendAlertLine(alertsPath, message) {
|
|
25691
|
-
mkdirSync32(
|
|
25974
|
+
mkdirSync32(dirname26(alertsPath), { recursive: true });
|
|
25692
25975
|
appendFileSync13(alertsPath, `${message}
|
|
25693
25976
|
`, "utf8");
|
|
25694
25977
|
}
|
|
@@ -25866,7 +26149,7 @@ function describeCommand(cmd) {
|
|
|
25866
26149
|
|
|
25867
26150
|
// packages/cli/dist/runner/correction-circuit.js
|
|
25868
26151
|
import { appendFileSync as appendFileSync14, existsSync as existsSync54, mkdirSync as mkdirSync33, readFileSync as readFileSync49, writeFileSync as writeFileSync34 } from "node:fs";
|
|
25869
|
-
import { dirname as
|
|
26152
|
+
import { dirname as dirname27, join as join53 } from "node:path";
|
|
25870
26153
|
function readLoopSafety(projectPath3) {
|
|
25871
26154
|
try {
|
|
25872
26155
|
const path = join53(projectPath3, ".roll", "policy.yaml");
|
|
@@ -25888,7 +26171,7 @@ function alreadyTripped(events, verdict) {
|
|
|
25888
26171
|
return events.some((ev) => ev.type === "correction:circuit_breaker" && ev.signal === verdict.signal && ev.threshold === verdict.threshold && (ev.storyId ?? "") === (verdict.storyId ?? ""));
|
|
25889
26172
|
}
|
|
25890
26173
|
function appendEvent2(eventsPath4, event) {
|
|
25891
|
-
mkdirSync33(
|
|
26174
|
+
mkdirSync33(dirname27(eventsPath4), { recursive: true });
|
|
25892
26175
|
appendFileSync14(eventsPath4, `${JSON.stringify(event)}
|
|
25893
26176
|
`, "utf8");
|
|
25894
26177
|
}
|
|
@@ -25911,10 +26194,10 @@ function applyCorrectionCircuitBreaker(projectPath3, slug, eventsPath4, alertsPa
|
|
|
25911
26194
|
` : "") + `**Action**: loop paused to prevent unattended correction oscillation. Resume manually with \`roll loop resume\`.
|
|
25912
26195
|
`;
|
|
25913
26196
|
try {
|
|
25914
|
-
mkdirSync33(
|
|
26197
|
+
mkdirSync33(dirname27(pauseMarker), { recursive: true });
|
|
25915
26198
|
if (pauseWritten)
|
|
25916
26199
|
writeFileSync34(pauseMarker, alertMsg, "utf8");
|
|
25917
|
-
mkdirSync33(
|
|
26200
|
+
mkdirSync33(dirname27(alertsPath), { recursive: true });
|
|
25918
26201
|
appendFileSync14(alertsPath, `${alertMsg}
|
|
25919
26202
|
`, "utf8");
|
|
25920
26203
|
appendEvent2(eventsPath4, {
|
|
@@ -26004,6 +26287,7 @@ async function backfillMergedRuns(projectPath3, runsPath3, deps = {}) {
|
|
|
26004
26287
|
// packages/cli/dist/commands/loop-run-once.js
|
|
26005
26288
|
import { execFileSync as execFileSync13, spawn as spawn6 } from "node:child_process";
|
|
26006
26289
|
import { lookup } from "node:dns/promises";
|
|
26290
|
+
import { createConnection } from "node:net";
|
|
26007
26291
|
function announceReport(projectPath3, slug, storyId, opener = (p) => {
|
|
26008
26292
|
try {
|
|
26009
26293
|
spawn6("open", [p], { stdio: "ignore", detached: true }).unref();
|
|
@@ -26256,7 +26540,7 @@ async function loopRunOnceCommand(args) {
|
|
|
26256
26540
|
}
|
|
26257
26541
|
const rt = runtimeDir5(id.path);
|
|
26258
26542
|
const alertsPath = join54(rt, `ALERT-${id.slug}.md`);
|
|
26259
|
-
mkdirSync34(
|
|
26543
|
+
mkdirSync34(dirname28(alertsPath), { recursive: true });
|
|
26260
26544
|
const paths = {
|
|
26261
26545
|
eventsPath: join54(rt, "events.ndjson"),
|
|
26262
26546
|
runsPath: join54(rt, "runs.jsonl"),
|
|
@@ -26411,17 +26695,34 @@ async function isOffline(resolve4 = (h) => lookup(h)) {
|
|
|
26411
26695
|
return true;
|
|
26412
26696
|
}
|
|
26413
26697
|
}
|
|
26414
|
-
|
|
26698
|
+
function tcpConnect(host, port, timeoutMs) {
|
|
26699
|
+
return new Promise((resolve4, reject) => {
|
|
26700
|
+
const socket = createConnection({ host, port });
|
|
26701
|
+
let settled = false;
|
|
26702
|
+
const done = (err17) => {
|
|
26703
|
+
if (settled)
|
|
26704
|
+
return;
|
|
26705
|
+
settled = true;
|
|
26706
|
+
socket.removeAllListeners();
|
|
26707
|
+
socket.destroy();
|
|
26708
|
+
if (err17)
|
|
26709
|
+
reject(err17);
|
|
26710
|
+
else
|
|
26711
|
+
resolve4();
|
|
26712
|
+
};
|
|
26713
|
+
socket.setTimeout(timeoutMs, () => done(new Error("tcp timeout")));
|
|
26714
|
+
socket.once("connect", () => done());
|
|
26715
|
+
socket.once("error", done);
|
|
26716
|
+
});
|
|
26717
|
+
}
|
|
26718
|
+
async function egressBlocked(resolve4 = (h) => lookup(h), tcpProbe2 = () => tcpConnect("github.com", 443, 3e3)) {
|
|
26415
26719
|
if (process.platform !== "darwin")
|
|
26416
26720
|
return false;
|
|
26417
26721
|
const offline = await isOffline(resolve4);
|
|
26418
26722
|
if (offline)
|
|
26419
26723
|
return false;
|
|
26420
26724
|
try {
|
|
26421
|
-
|
|
26422
|
-
const { promisify: promisify10 } = await import("node:util");
|
|
26423
|
-
const execFileAsync10 = promisify10(execFile10);
|
|
26424
|
-
await execFileAsync10("bash", ["-c", "timeout 3 bash -c 'echo >/dev/tcp/github.com/443' 2>/dev/null"], { timeout: 5e3 });
|
|
26725
|
+
await tcpProbe2();
|
|
26425
26726
|
return false;
|
|
26426
26727
|
} catch {
|
|
26427
26728
|
return true;
|
|
@@ -26430,7 +26731,7 @@ async function egressBlocked(resolve4 = (h) => lookup(h)) {
|
|
|
26430
26731
|
|
|
26431
26732
|
// packages/cli/dist/commands/offboard.js
|
|
26432
26733
|
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
26433
|
-
import { existsSync as existsSync56, readFileSync as readFileSync52, realpathSync as realpathSync6, rmSync as
|
|
26734
|
+
import { existsSync as existsSync56, readFileSync as readFileSync52, realpathSync as realpathSync6, rmSync as rmSync14, writeFileSync as writeFileSync37 } from "node:fs";
|
|
26434
26735
|
import { homedir as homedir16 } from "node:os";
|
|
26435
26736
|
import { join as join55, resolve as resolve2 } from "node:path";
|
|
26436
26737
|
function pal5() {
|
|
@@ -26634,7 +26935,7 @@ function offboardCommand(args) {
|
|
|
26634
26935
|
process.stdout.write(m4("offboard.applying_offboard") + "\n");
|
|
26635
26936
|
for (const item of files) {
|
|
26636
26937
|
try {
|
|
26637
|
-
|
|
26938
|
+
rmSync14(join55(projectDir, item), { force: true });
|
|
26638
26939
|
if (!existsSync56(join55(projectDir, item)))
|
|
26639
26940
|
process.stdout.write(` removed file ${item}
|
|
26640
26941
|
`);
|
|
@@ -26643,7 +26944,7 @@ function offboardCommand(args) {
|
|
|
26643
26944
|
}
|
|
26644
26945
|
for (const item of dirs) {
|
|
26645
26946
|
try {
|
|
26646
|
-
|
|
26947
|
+
rmSync14(join55(projectDir, item), { recursive: true, force: true });
|
|
26647
26948
|
process.stdout.write(` removed dir ${item}
|
|
26648
26949
|
`);
|
|
26649
26950
|
} catch {
|
|
@@ -26667,19 +26968,19 @@ function offboardCommand(args) {
|
|
|
26667
26968
|
if (r === 0)
|
|
26668
26969
|
process.stdout.write(` unloaded ${item}
|
|
26669
26970
|
`);
|
|
26670
|
-
|
|
26971
|
+
rmSync14(plistPath, { force: true });
|
|
26671
26972
|
}
|
|
26672
|
-
|
|
26973
|
+
rmSync14(changeset, { force: true });
|
|
26673
26974
|
ok7(m4("offboard.offboard_complete_offboard"));
|
|
26674
26975
|
return 0;
|
|
26675
26976
|
}
|
|
26676
26977
|
|
|
26677
26978
|
// packages/cli/dist/commands/prices.js
|
|
26678
|
-
import { existsSync as existsSync58, readdirSync as
|
|
26979
|
+
import { existsSync as existsSync58, readdirSync as readdirSync26, readFileSync as readFileSync54 } from "node:fs";
|
|
26679
26980
|
import { join as join57 } from "node:path";
|
|
26680
26981
|
|
|
26681
26982
|
// packages/cli/dist/commands/prices-refresh.js
|
|
26682
|
-
import { existsSync as existsSync57, mkdirSync as mkdirSync35, readdirSync as
|
|
26983
|
+
import { existsSync as existsSync57, mkdirSync as mkdirSync35, readdirSync as readdirSync25, readFileSync as readFileSync53, writeFileSync as writeFileSync38 } from "node:fs";
|
|
26683
26984
|
import { join as join56 } from "node:path";
|
|
26684
26985
|
var FetchError = class extends Error {
|
|
26685
26986
|
constructor(message) {
|
|
@@ -26903,7 +27204,7 @@ function vendorFromSnapshotName(name) {
|
|
|
26903
27204
|
function latestSnapshotPath(snapshotDir, vendor) {
|
|
26904
27205
|
if (!existsSync57(snapshotDir))
|
|
26905
27206
|
return null;
|
|
26906
|
-
const snaps =
|
|
27207
|
+
const snaps = readdirSync25(snapshotDir).filter((name) => SNAPSHOT_RE.test(name) && vendorFromSnapshotName(name) === vendor).sort().map((name) => join56(snapshotDir, name));
|
|
26907
27208
|
return snaps[snaps.length - 1] ?? null;
|
|
26908
27209
|
}
|
|
26909
27210
|
function readPrices(path) {
|
|
@@ -27113,7 +27414,7 @@ function loadSnapshots() {
|
|
|
27113
27414
|
if (!existsSync58(dir)) {
|
|
27114
27415
|
throw new Error(`no price snapshots found in ${dir}; run \`roll prices refresh\``);
|
|
27115
27416
|
}
|
|
27116
|
-
const files =
|
|
27417
|
+
const files = readdirSync26(dir).filter((n) => n.startsWith("snapshot-") && n.endsWith(".json")).sort();
|
|
27117
27418
|
return files.map((name) => {
|
|
27118
27419
|
const data = JSON.parse(readFileSync54(join57(dir, name), "utf8"));
|
|
27119
27420
|
for (const key of ["version", "effective_at", "source_url", "prices"]) {
|
|
@@ -27602,7 +27903,7 @@ function releaseWaiverCommand(args, deps = {}) {
|
|
|
27602
27903
|
|
|
27603
27904
|
// packages/cli/dist/commands/setup.js
|
|
27604
27905
|
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
27605
|
-
import { existsSync as existsSync60, lstatSync as lstatSync3, mkdirSync as mkdirSync36, readFileSync as readFileSync57, readdirSync as
|
|
27906
|
+
import { existsSync as existsSync60, lstatSync as lstatSync3, mkdirSync as mkdirSync36, readFileSync as readFileSync57, readdirSync as readdirSync27, readlinkSync as readlinkSync2, statSync as statSync21 } from "node:fs";
|
|
27606
27907
|
import { join as join61 } from "node:path";
|
|
27607
27908
|
function err14(line) {
|
|
27608
27909
|
const noColor2 = (process.env["NO_COLOR"] ?? "") !== "";
|
|
@@ -27628,7 +27929,7 @@ function setupSnapshot(watch) {
|
|
|
27628
27929
|
continue;
|
|
27629
27930
|
let isDir3 = false;
|
|
27630
27931
|
try {
|
|
27631
|
-
isDir3 =
|
|
27932
|
+
isDir3 = statSync21(d).isDirectory();
|
|
27632
27933
|
} catch {
|
|
27633
27934
|
isDir3 = false;
|
|
27634
27935
|
}
|
|
@@ -27641,7 +27942,7 @@ function setupSnapshot(watch) {
|
|
|
27641
27942
|
function walk(dir, lines2) {
|
|
27642
27943
|
let names;
|
|
27643
27944
|
try {
|
|
27644
|
-
names =
|
|
27945
|
+
names = readdirSync27(dir);
|
|
27645
27946
|
} catch {
|
|
27646
27947
|
return;
|
|
27647
27948
|
}
|
|
@@ -27662,7 +27963,7 @@ function walk(dir, lines2) {
|
|
|
27662
27963
|
}
|
|
27663
27964
|
let st;
|
|
27664
27965
|
try {
|
|
27665
|
-
st =
|
|
27966
|
+
st = statSync21(p);
|
|
27666
27967
|
} catch {
|
|
27667
27968
|
continue;
|
|
27668
27969
|
}
|
|
@@ -27720,7 +28021,7 @@ function submoduleGuard() {
|
|
|
27720
28021
|
const hasMods = existsSync60(join61(pkg, ".gitmodules"));
|
|
27721
28022
|
let empty = true;
|
|
27722
28023
|
try {
|
|
27723
|
-
empty =
|
|
28024
|
+
empty = readdirSync27(skills).length === 0;
|
|
27724
28025
|
} catch {
|
|
27725
28026
|
empty = true;
|
|
27726
28027
|
}
|
|
@@ -27868,9 +28169,9 @@ function setupCommand(args) {
|
|
|
27868
28169
|
// packages/cli/dist/commands/status.js
|
|
27869
28170
|
import { execFileSync as execFileSync16 } from "node:child_process";
|
|
27870
28171
|
import { createHash as createHash5 } from "node:crypto";
|
|
27871
|
-
import { existsSync as existsSync61, lstatSync as lstatSync4, readdirSync as
|
|
28172
|
+
import { existsSync as existsSync61, lstatSync as lstatSync4, readdirSync as readdirSync28, readFileSync as readFileSync58, realpathSync as realpathSync7, statSync as statSync22 } from "node:fs";
|
|
27872
28173
|
import { homedir as homedir17 } from "node:os";
|
|
27873
|
-
import { basename as basename11, dirname as
|
|
28174
|
+
import { basename as basename11, dirname as dirname29, join as join62 } from "node:path";
|
|
27874
28175
|
function rollHome3() {
|
|
27875
28176
|
return process.env["ROLL_HOME"] ?? join62(homedir17(), ".roll");
|
|
27876
28177
|
}
|
|
@@ -27915,7 +28216,7 @@ function parseAiEntries() {
|
|
|
27915
28216
|
const srcFile = (parts[2] ?? "").trim();
|
|
27916
28217
|
let name = basename11(aiDir).replace(/^\.+/, "");
|
|
27917
28218
|
if (name === "workspace" || name === "agent") {
|
|
27918
|
-
name = basename11(
|
|
28219
|
+
name = basename11(dirname29(aiDir)).replace(/^\.+/, "");
|
|
27919
28220
|
}
|
|
27920
28221
|
entries.push({ name, ai_dir: aiDir, cfg_file: cfgFile, src_file: srcFile });
|
|
27921
28222
|
}
|
|
@@ -27949,7 +28250,7 @@ function aiSkillCount(e) {
|
|
|
27949
28250
|
return 0;
|
|
27950
28251
|
try {
|
|
27951
28252
|
let n = 0;
|
|
27952
|
-
for (const name of
|
|
28253
|
+
for (const name of readdirSync28(skillsDir2)) {
|
|
27953
28254
|
if (!name.startsWith("roll-"))
|
|
27954
28255
|
continue;
|
|
27955
28256
|
const p = join62(skillsDir2, name);
|
|
@@ -27964,9 +28265,9 @@ function aiSkillCount(e) {
|
|
|
27964
28265
|
}
|
|
27965
28266
|
function countFilesRecursive(dir) {
|
|
27966
28267
|
let n = 0;
|
|
27967
|
-
for (const name of
|
|
28268
|
+
for (const name of readdirSync28(dir)) {
|
|
27968
28269
|
const p = join62(dir, name);
|
|
27969
|
-
const st =
|
|
28270
|
+
const st = statSync22(p);
|
|
27970
28271
|
if (st.isDirectory())
|
|
27971
28272
|
n += countFilesRecursive(p);
|
|
27972
28273
|
else if (st.isFile())
|
|
@@ -27989,7 +28290,7 @@ function skillsInstalled() {
|
|
|
27989
28290
|
if (!existsSync61(sd))
|
|
27990
28291
|
return 0;
|
|
27991
28292
|
try {
|
|
27992
|
-
return
|
|
28293
|
+
return readdirSync28(sd).filter((n) => statSync22(join62(sd, n)).isDirectory()).length;
|
|
27993
28294
|
} catch {
|
|
27994
28295
|
return 0;
|
|
27995
28296
|
}
|
|
@@ -28142,7 +28443,7 @@ function liveData() {
|
|
|
28142
28443
|
const featDir = ".roll/features";
|
|
28143
28444
|
let featCount = 0;
|
|
28144
28445
|
if (existsSync61(featDir)) {
|
|
28145
|
-
featCount =
|
|
28446
|
+
featCount = readdirSync28(featDir).filter((n) => n.endsWith(".md")).length;
|
|
28146
28447
|
}
|
|
28147
28448
|
return {
|
|
28148
28449
|
conventions: globalConventions(),
|
|
@@ -28174,8 +28475,8 @@ function statusCommand(args) {
|
|
|
28174
28475
|
|
|
28175
28476
|
// packages/cli/dist/commands/test.js
|
|
28176
28477
|
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
28177
|
-
import { appendFileSync as appendFileSync16, existsSync as existsSync62, mkdirSync as mkdirSync37, readFileSync as readFileSync59, rmSync as
|
|
28178
|
-
import { dirname as
|
|
28478
|
+
import { appendFileSync as appendFileSync16, existsSync as existsSync62, mkdirSync as mkdirSync37, readFileSync as readFileSync59, rmSync as rmSync15, writeFileSync as writeFileSync39 } from "node:fs";
|
|
28479
|
+
import { dirname as dirname30, join as join63, resolve as resolve3 } from "node:path";
|
|
28179
28480
|
function pal7() {
|
|
28180
28481
|
const noColor2 = (process.env["NO_COLOR"] ?? "") !== "";
|
|
28181
28482
|
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" };
|
|
@@ -28311,13 +28612,13 @@ function resetAcquireLock() {
|
|
|
28311
28612
|
const lock = resetLockPath();
|
|
28312
28613
|
if (existsSync62(lock))
|
|
28313
28614
|
return false;
|
|
28314
|
-
mkdirSync37(
|
|
28615
|
+
mkdirSync37(dirname30(lock), { recursive: true });
|
|
28315
28616
|
writeFileSync39(lock, `${process.pid}
|
|
28316
28617
|
`);
|
|
28317
28618
|
return true;
|
|
28318
28619
|
}
|
|
28319
28620
|
function resetReleaseLock() {
|
|
28320
|
-
|
|
28621
|
+
rmSync15(resetLockPath(), { force: true });
|
|
28321
28622
|
}
|
|
28322
28623
|
function runForward(cmd, argv) {
|
|
28323
28624
|
const frame = currentEvidenceFrame();
|
|
@@ -28333,6 +28634,23 @@ function runForward(cmd, argv) {
|
|
|
28333
28634
|
appendRollTestEvidence(frame, cmd, argv, status2, stdout, stderr);
|
|
28334
28635
|
return status2;
|
|
28335
28636
|
}
|
|
28637
|
+
function ensureSkillsSubmoduleReady() {
|
|
28638
|
+
const pkg = rollPkgDir();
|
|
28639
|
+
const required2 = join63(pkg, "skills", "roll-onboard", "SKILL.md");
|
|
28640
|
+
if (existsSync62(required2))
|
|
28641
|
+
return true;
|
|
28642
|
+
if (existsSync62(join63(pkg, ".git")) && existsSync62(join63(pkg, ".gitmodules"))) {
|
|
28643
|
+
spawnSync9("git", ["submodule", "update", "--init", "--recursive", "--quiet", "skills"], {
|
|
28644
|
+
cwd: pkg,
|
|
28645
|
+
stdio: "ignore"
|
|
28646
|
+
});
|
|
28647
|
+
if (existsSync62(required2))
|
|
28648
|
+
return true;
|
|
28649
|
+
}
|
|
28650
|
+
err15("roll test: skills submodule is empty");
|
|
28651
|
+
process.stderr.write(" run: git submodule update --init --recursive skills\n");
|
|
28652
|
+
return false;
|
|
28653
|
+
}
|
|
28336
28654
|
function isolationDispatch(method, args) {
|
|
28337
28655
|
const type = isolationGetType();
|
|
28338
28656
|
if (type === "none" && !existsSync62(join63(process.cwd(), ".roll", "local.yaml"))) {
|
|
@@ -28424,6 +28742,8 @@ function testCommand(args) {
|
|
|
28424
28742
|
let npmArgs = argv;
|
|
28425
28743
|
if (npmArgs.length === 0)
|
|
28426
28744
|
npmArgs = ["--affected"];
|
|
28745
|
+
if (!ensureSkillsSubmoduleReady())
|
|
28746
|
+
return 1;
|
|
28427
28747
|
return isolationDispatch("exec", ["npm", "test", "--", ...npmArgs]);
|
|
28428
28748
|
}
|
|
28429
28749
|
|
|
@@ -28612,7 +28932,7 @@ function tuneCommand(argv) {
|
|
|
28612
28932
|
|
|
28613
28933
|
// packages/cli/dist/commands/update.js
|
|
28614
28934
|
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
28615
|
-
import { existsSync as existsSync64, mkdtempSync as mkdtempSync5, readFileSync as readFileSync61, rmSync as
|
|
28935
|
+
import { existsSync as existsSync64, mkdtempSync as mkdtempSync5, readFileSync as readFileSync61, rmSync as rmSync16 } from "node:fs";
|
|
28616
28936
|
import { tmpdir as tmpdir6 } from "node:os";
|
|
28617
28937
|
import { join as join65 } from "node:path";
|
|
28618
28938
|
function pal8() {
|
|
@@ -28702,7 +29022,7 @@ function downloadAndInstallCurl(tag) {
|
|
|
28702
29022
|
}
|
|
28703
29023
|
return { ok: true, newVersion: treeVersion(extractDir) };
|
|
28704
29024
|
} finally {
|
|
28705
|
-
|
|
29025
|
+
rmSync16(tmpDir, { recursive: true, force: true });
|
|
28706
29026
|
}
|
|
28707
29027
|
}
|
|
28708
29028
|
function checkInstalledVersionOrRetry() {
|
|
@@ -28722,7 +29042,7 @@ function checkInstalledVersionOrRetry() {
|
|
|
28722
29042
|
}
|
|
28723
29043
|
}
|
|
28724
29044
|
function invalidateUpdateCache() {
|
|
28725
|
-
|
|
29045
|
+
rmSync16(join65(rollHome(), ".update-check"), { force: true });
|
|
28726
29046
|
}
|
|
28727
29047
|
function showChangelog() {
|
|
28728
29048
|
const changelog = join65(rollPkgDir(), "CHANGELOG.md");
|