@seanyao/roll 3.614.3 → 3.614.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/dist/roll.mjs +1266 -842
- package/package.json +1 -1
package/dist/roll.mjs
CHANGED
|
@@ -4978,6 +4978,532 @@ var init_bus = __esm({
|
|
|
4978
4978
|
}
|
|
4979
4979
|
});
|
|
4980
4980
|
|
|
4981
|
+
// packages/core/dist/loop/signals.js
|
|
4982
|
+
function signalKindForMarker(marker) {
|
|
4983
|
+
if (marker === "tcr")
|
|
4984
|
+
return "tcr";
|
|
4985
|
+
if (marker === "skill" || marker === "story")
|
|
4986
|
+
return "skill";
|
|
4987
|
+
if (marker.startsWith("ci:"))
|
|
4988
|
+
return "ci";
|
|
4989
|
+
if (marker === "peer:gate" || marker === "peer")
|
|
4990
|
+
return "peer";
|
|
4991
|
+
if (marker === "attest:gate" || marker === "evidence:frame-opened" || marker === "attest")
|
|
4992
|
+
return "attest";
|
|
4993
|
+
if (marker.startsWith("pr:"))
|
|
4994
|
+
return "pr";
|
|
4995
|
+
if (marker === "alert" || marker === "error")
|
|
4996
|
+
return "alert";
|
|
4997
|
+
return null;
|
|
4998
|
+
}
|
|
4999
|
+
var init_signals = __esm({
|
|
5000
|
+
"packages/core/dist/loop/signals.js"() {
|
|
5001
|
+
"use strict";
|
|
5002
|
+
}
|
|
5003
|
+
});
|
|
5004
|
+
|
|
5005
|
+
// packages/core/dist/loop/activity-signal.js
|
|
5006
|
+
function newNormalizerState() {
|
|
5007
|
+
return {
|
|
5008
|
+
cycleId: "",
|
|
5009
|
+
seg: "cycle",
|
|
5010
|
+
pendingCommit: false,
|
|
5011
|
+
pendingPr: false,
|
|
5012
|
+
pendingCi: false,
|
|
5013
|
+
pendingStory: false,
|
|
5014
|
+
lastBashCmd: "",
|
|
5015
|
+
tcrCount: 0,
|
|
5016
|
+
editStreakFile: null,
|
|
5017
|
+
lastActionTs: 0,
|
|
5018
|
+
lastSummary: "",
|
|
5019
|
+
lastHeartbeatTs: 0
|
|
5020
|
+
};
|
|
5021
|
+
}
|
|
5022
|
+
function clip(s, n = 60) {
|
|
5023
|
+
const flat = s.replace(/\s+/g, " ").trim();
|
|
5024
|
+
return flat.length > n ? `${flat.slice(0, n - 1)}\u2026` : flat;
|
|
5025
|
+
}
|
|
5026
|
+
function basename2(p) {
|
|
5027
|
+
const trimmed = p.replace(/\/+$/, "");
|
|
5028
|
+
const i = trimmed.lastIndexOf("/");
|
|
5029
|
+
return i >= 0 ? trimmed.slice(i + 1) : trimmed;
|
|
5030
|
+
}
|
|
5031
|
+
function emit(st, nowMs, fields) {
|
|
5032
|
+
let tier = fields.tier ?? KIND_TIER[fields.kind];
|
|
5033
|
+
if (fields.kind === "test" && fields.result === "fail")
|
|
5034
|
+
tier = "A";
|
|
5035
|
+
const sig = {
|
|
5036
|
+
ts: nowMs,
|
|
5037
|
+
cycleId: st.cycleId,
|
|
5038
|
+
seg: fields.seg ?? st.seg,
|
|
5039
|
+
kind: fields.kind,
|
|
5040
|
+
tier,
|
|
5041
|
+
summary: fields.summary
|
|
5042
|
+
};
|
|
5043
|
+
if (fields.result !== void 0)
|
|
5044
|
+
sig.result = fields.result;
|
|
5045
|
+
if (fields.ref !== void 0 && fields.ref !== "")
|
|
5046
|
+
sig.ref = fields.ref;
|
|
5047
|
+
if (fields.detail !== void 0 && fields.detail !== "")
|
|
5048
|
+
sig.detail = fields.detail;
|
|
5049
|
+
if (fields.marker !== void 0) {
|
|
5050
|
+
const sk = signalKindForMarker(fields.marker);
|
|
5051
|
+
if (sk !== null)
|
|
5052
|
+
sig.signalKind = sk;
|
|
5053
|
+
}
|
|
5054
|
+
if (fields.kind !== "heartbeat") {
|
|
5055
|
+
st.lastActionTs = nowMs;
|
|
5056
|
+
st.lastSummary = fields.summary;
|
|
5057
|
+
}
|
|
5058
|
+
return sig;
|
|
5059
|
+
}
|
|
5060
|
+
function clearPending(st) {
|
|
5061
|
+
st.pendingCommit = false;
|
|
5062
|
+
st.pendingPr = false;
|
|
5063
|
+
st.pendingCi = false;
|
|
5064
|
+
st.pendingStory = false;
|
|
5065
|
+
}
|
|
5066
|
+
function resetState(st) {
|
|
5067
|
+
clearPending(st);
|
|
5068
|
+
st.tcrCount = 0;
|
|
5069
|
+
st.editStreakFile = null;
|
|
5070
|
+
st.seg = "cycle";
|
|
5071
|
+
}
|
|
5072
|
+
function matchBanner(line) {
|
|
5073
|
+
const header = /^──\s*cycle\s+(.+?)\s*──\s*$/.exec(line);
|
|
5074
|
+
if (header) {
|
|
5075
|
+
const inner = header[1];
|
|
5076
|
+
const id = /([0-9]{6,8}-\d+)/.exec(inner);
|
|
5077
|
+
return { label: clip(inner, 80), cycleId: id ? id[1] : inner.split(/\s+/)[0] ?? "" };
|
|
5078
|
+
}
|
|
5079
|
+
const m7 = /\[loop\]\s+cycle\s+(\d+)/.exec(line);
|
|
5080
|
+
if (m7)
|
|
5081
|
+
return { label: `cycle #${m7[1]}`, cycleId: m7[1] };
|
|
5082
|
+
return null;
|
|
5083
|
+
}
|
|
5084
|
+
function fmtElapsed(ms) {
|
|
5085
|
+
const s = Math.round(ms / 1e3);
|
|
5086
|
+
if (s < 60)
|
|
5087
|
+
return `${s}s`;
|
|
5088
|
+
return `${Math.floor(s / 60)}m ${s % 60}s`;
|
|
5089
|
+
}
|
|
5090
|
+
function maybeHeartbeat(st, nowMs, gapMs = DEFAULT_HEARTBEAT_GAP_MS) {
|
|
5091
|
+
const baseline = st.lastActionTs || st.lastHeartbeatTs;
|
|
5092
|
+
if (baseline === 0)
|
|
5093
|
+
return [];
|
|
5094
|
+
const since = Math.max(st.lastActionTs, st.lastHeartbeatTs);
|
|
5095
|
+
if (nowMs - since < gapMs)
|
|
5096
|
+
return [];
|
|
5097
|
+
st.lastHeartbeatTs = nowMs;
|
|
5098
|
+
const elapsed = fmtElapsed(nowMs - st.lastActionTs);
|
|
5099
|
+
const last = st.lastSummary !== "" ? ` \xB7 last: ${st.lastSummary}` : "";
|
|
5100
|
+
return [
|
|
5101
|
+
{
|
|
5102
|
+
ts: nowMs,
|
|
5103
|
+
cycleId: st.cycleId,
|
|
5104
|
+
seg: st.seg,
|
|
5105
|
+
kind: "heartbeat",
|
|
5106
|
+
tier: "A",
|
|
5107
|
+
summary: `\u2026still in ${st.seg} \xB7 ${elapsed}${last}`
|
|
5108
|
+
}
|
|
5109
|
+
];
|
|
5110
|
+
}
|
|
5111
|
+
function claudeText(text, st, nowMs) {
|
|
5112
|
+
const t2 = text.trim();
|
|
5113
|
+
if (t2 === "")
|
|
5114
|
+
return [];
|
|
5115
|
+
for (const v of PEER_VERDICTS) {
|
|
5116
|
+
if (t2.includes(v)) {
|
|
5117
|
+
const rm = /round\s+(\d+)[/\\](\d+)/i.exec(t2);
|
|
5118
|
+
const round = rm ? `round ${rm[1]}/${rm[2]}` : "round ?";
|
|
5119
|
+
const am = /(\w+)\s*→\s*(\w+)/.exec(t2);
|
|
5120
|
+
const agents = am ? `${am[1]} \u2192 ${am[2]}` : "peer";
|
|
5121
|
+
st.editStreakFile = null;
|
|
5122
|
+
st.seg = "peer";
|
|
5123
|
+
return [emit(st, nowMs, {
|
|
5124
|
+
seg: "peer",
|
|
5125
|
+
kind: "gate",
|
|
5126
|
+
summary: agents,
|
|
5127
|
+
detail: `${round} \xB7 ${v}`,
|
|
5128
|
+
ref: agents,
|
|
5129
|
+
marker: "peer"
|
|
5130
|
+
})];
|
|
5131
|
+
}
|
|
5132
|
+
}
|
|
5133
|
+
return [emit(st, nowMs, { kind: "say", summary: clip(t2, 80) })];
|
|
5134
|
+
}
|
|
5135
|
+
function claudeToolUse(blk, st, nowMs) {
|
|
5136
|
+
const name = typeof blk["name"] === "string" ? blk["name"] : "";
|
|
5137
|
+
const input = blk["input"] ?? {};
|
|
5138
|
+
if (SUPPRESS_TOOLS.has(name))
|
|
5139
|
+
return [];
|
|
5140
|
+
if (name === "Edit" || name === "Write") {
|
|
5141
|
+
const path = typeof input["file_path"] === "string" && input["file_path"] || typeof input["path"] === "string" && input["path"] || "";
|
|
5142
|
+
if (path === st.editStreakFile)
|
|
5143
|
+
return [];
|
|
5144
|
+
st.editStreakFile = path;
|
|
5145
|
+
st.seg = "build";
|
|
5146
|
+
return [emit(st, nowMs, {
|
|
5147
|
+
seg: "build",
|
|
5148
|
+
kind: "edit",
|
|
5149
|
+
summary: basename2(path),
|
|
5150
|
+
ref: path
|
|
5151
|
+
})];
|
|
5152
|
+
}
|
|
5153
|
+
st.editStreakFile = null;
|
|
5154
|
+
if (name === "Bash") {
|
|
5155
|
+
const cmd = typeof input["command"] === "string" ? input["command"] : "";
|
|
5156
|
+
const first = cmd.split("\n").map((l) => l.trim()).find((l) => l !== "") ?? cmd;
|
|
5157
|
+
st.lastBashCmd = first;
|
|
5158
|
+
if (/git\s+commit[\s\S]*tcr:/.test(cmd)) {
|
|
5159
|
+
st.pendingCommit = true;
|
|
5160
|
+
return [];
|
|
5161
|
+
}
|
|
5162
|
+
if (/gh\s+pr\s+(create|merge)/.test(cmd)) {
|
|
5163
|
+
st.pendingPr = true;
|
|
5164
|
+
st.seg = "pr";
|
|
5165
|
+
return [];
|
|
5166
|
+
}
|
|
5167
|
+
if (/(roll\s+ci|npm\s+run\s+ci|_ci_wait|ci:local)/.test(cmd)) {
|
|
5168
|
+
st.pendingCi = true;
|
|
5169
|
+
st.seg = "ci";
|
|
5170
|
+
return [];
|
|
5171
|
+
}
|
|
5172
|
+
return [emit(st, nowMs, { kind: "tool", summary: clip(first, 60), ref: "bash" })];
|
|
5173
|
+
}
|
|
5174
|
+
if (name === "Skill") {
|
|
5175
|
+
const skill = typeof input["skill"] === "string" ? input["skill"] : "";
|
|
5176
|
+
if (skill === "roll-build" || skill === "roll-fix") {
|
|
5177
|
+
const args = (typeof input["args"] === "string" ? input["args"] : "").trim();
|
|
5178
|
+
const usId = args.split(/\s+/)[0] || "?";
|
|
5179
|
+
st.pendingStory = true;
|
|
5180
|
+
st.seg = "story";
|
|
5181
|
+
return [emit(st, nowMs, {
|
|
5182
|
+
seg: "story",
|
|
5183
|
+
kind: "lifecycle",
|
|
5184
|
+
summary: usId,
|
|
5185
|
+
detail: clip(args, 60),
|
|
5186
|
+
ref: usId,
|
|
5187
|
+
marker: "skill"
|
|
5188
|
+
})];
|
|
5189
|
+
}
|
|
5190
|
+
return [];
|
|
5191
|
+
}
|
|
5192
|
+
return [];
|
|
5193
|
+
}
|
|
5194
|
+
function extractResultText(content) {
|
|
5195
|
+
if (typeof content === "string")
|
|
5196
|
+
return content;
|
|
5197
|
+
if (Array.isArray(content)) {
|
|
5198
|
+
return content.filter((c2) => typeof c2 === "object" && c2 !== null && c2["type"] === "text").map((c2) => typeof c2["text"] === "string" ? c2["text"] : "").join("\n");
|
|
5199
|
+
}
|
|
5200
|
+
return content == null ? "" : String(content);
|
|
5201
|
+
}
|
|
5202
|
+
function claudeAssistant(ev, st, nowMs) {
|
|
5203
|
+
const msg6 = ev["message"] ?? {};
|
|
5204
|
+
const content = Array.isArray(msg6["content"]) ? msg6["content"] : [];
|
|
5205
|
+
const out3 = [];
|
|
5206
|
+
for (const blkRaw of content) {
|
|
5207
|
+
if (typeof blkRaw !== "object" || blkRaw === null)
|
|
5208
|
+
continue;
|
|
5209
|
+
const blk = blkRaw;
|
|
5210
|
+
const bt = blk["type"];
|
|
5211
|
+
if (bt === "thinking")
|
|
5212
|
+
continue;
|
|
5213
|
+
if (bt === "text")
|
|
5214
|
+
out3.push(...claudeText(typeof blk["text"] === "string" ? blk["text"] : "", st, nowMs));
|
|
5215
|
+
else if (bt === "tool_use")
|
|
5216
|
+
out3.push(...claudeToolUse(blk, st, nowMs));
|
|
5217
|
+
}
|
|
5218
|
+
return out3;
|
|
5219
|
+
}
|
|
5220
|
+
function claudeUser(ev, st, nowMs) {
|
|
5221
|
+
const msg6 = ev["message"] ?? {};
|
|
5222
|
+
const content = Array.isArray(msg6["content"]) ? msg6["content"] : [];
|
|
5223
|
+
const out3 = [];
|
|
5224
|
+
for (const blkRaw of content) {
|
|
5225
|
+
if (typeof blkRaw !== "object" || blkRaw === null)
|
|
5226
|
+
continue;
|
|
5227
|
+
const blk = blkRaw;
|
|
5228
|
+
if (blk["type"] !== "tool_result")
|
|
5229
|
+
continue;
|
|
5230
|
+
const text = extractResultText(blk["content"]);
|
|
5231
|
+
if (blk["is_error"] === true) {
|
|
5232
|
+
st.editStreakFile = null;
|
|
5233
|
+
const lines2 = text.split("\n").filter((l) => l.trim() !== "").slice(0, 3);
|
|
5234
|
+
clearPending(st);
|
|
5235
|
+
out3.push(emit(st, nowMs, {
|
|
5236
|
+
kind: "alert",
|
|
5237
|
+
summary: "tool",
|
|
5238
|
+
detail: clip(lines2.join(" | "), 80),
|
|
5239
|
+
result: "fail",
|
|
5240
|
+
marker: "alert"
|
|
5241
|
+
}));
|
|
5242
|
+
continue;
|
|
5243
|
+
}
|
|
5244
|
+
if (st.pendingCommit) {
|
|
5245
|
+
st.pendingCommit = false;
|
|
5246
|
+
const m7 = /\[[\w/-]+ ([0-9a-f]{7,})\]\s*tcr:\s*(.+)/.exec(text);
|
|
5247
|
+
if (m7) {
|
|
5248
|
+
st.tcrCount += 1;
|
|
5249
|
+
out3.push(emit(st, nowMs, {
|
|
5250
|
+
kind: "tcr",
|
|
5251
|
+
summary: m7[1].slice(0, 7),
|
|
5252
|
+
detail: clip(m7[2].trim(), 60),
|
|
5253
|
+
ref: m7[1].slice(0, 7),
|
|
5254
|
+
result: "pass",
|
|
5255
|
+
marker: "tcr"
|
|
5256
|
+
}));
|
|
5257
|
+
}
|
|
5258
|
+
continue;
|
|
5259
|
+
}
|
|
5260
|
+
if (st.pendingStory) {
|
|
5261
|
+
st.pendingStory = false;
|
|
5262
|
+
continue;
|
|
5263
|
+
}
|
|
5264
|
+
if (st.pendingPr) {
|
|
5265
|
+
st.pendingPr = false;
|
|
5266
|
+
const m7 = /#(\d+)/.exec(text);
|
|
5267
|
+
if (m7) {
|
|
5268
|
+
const branch = /loop\/[\w-]+/.exec(st.lastBashCmd);
|
|
5269
|
+
out3.push(emit(st, nowMs, {
|
|
5270
|
+
seg: "pr",
|
|
5271
|
+
kind: "pr",
|
|
5272
|
+
summary: `#${m7[1]}`,
|
|
5273
|
+
ref: `#${m7[1]}`,
|
|
5274
|
+
detail: branch ? `merged \xB7 ${branch[0]}` : "merged",
|
|
5275
|
+
result: "pass",
|
|
5276
|
+
marker: "pr:merge"
|
|
5277
|
+
}));
|
|
5278
|
+
}
|
|
5279
|
+
continue;
|
|
5280
|
+
}
|
|
5281
|
+
if (st.pendingCi) {
|
|
5282
|
+
st.pendingCi = false;
|
|
5283
|
+
const green = /(green|pass|success|all tests)/i.test(text);
|
|
5284
|
+
const red = /(red|fail|error)/i.test(text);
|
|
5285
|
+
const dur = /(\d+(?:\.\d+)?)\s*s\b/.exec(text);
|
|
5286
|
+
const tests = /(\d+)\s+tests?/.exec(text);
|
|
5287
|
+
const detail = [dur ? `${dur[1]}s` : "", tests ? `${tests[1]} tests` : ""].filter(Boolean).join(" \xB7 ");
|
|
5288
|
+
const ok8 = green && !red;
|
|
5289
|
+
out3.push(emit(st, nowMs, {
|
|
5290
|
+
seg: "ci",
|
|
5291
|
+
kind: "gate",
|
|
5292
|
+
summary: ok8 ? "green" : "red",
|
|
5293
|
+
result: ok8 ? "pass" : "fail",
|
|
5294
|
+
detail,
|
|
5295
|
+
marker: ok8 ? "ci:pass" : "ci:fail"
|
|
5296
|
+
}));
|
|
5297
|
+
continue;
|
|
5298
|
+
}
|
|
5299
|
+
}
|
|
5300
|
+
return out3;
|
|
5301
|
+
}
|
|
5302
|
+
function claudeResult(ev, st, nowMs) {
|
|
5303
|
+
st.editStreakFile = null;
|
|
5304
|
+
st.seg = "end";
|
|
5305
|
+
const durMs = typeof ev["duration_ms"] === "number" ? ev["duration_ms"] : 0;
|
|
5306
|
+
const cost = typeof ev["total_cost_usd"] === "number" ? ev["total_cost_usd"] : 0;
|
|
5307
|
+
const durS = Math.round(durMs / 1e3);
|
|
5308
|
+
if (ev["subtype"] === "error_max_turns") {
|
|
5309
|
+
return [emit(st, nowMs, { seg: "end", kind: "alert", summary: "max-turns", detail: `${durS}s`, result: "fail", marker: "alert" })];
|
|
5310
|
+
}
|
|
5311
|
+
const parts = [
|
|
5312
|
+
st.tcrCount > 0 ? `${st.tcrCount} tcr` : "",
|
|
5313
|
+
`${durS}s`,
|
|
5314
|
+
cost > 0 ? `$${cost.toFixed(2)}` : ""
|
|
5315
|
+
].filter(Boolean);
|
|
5316
|
+
return [emit(st, nowMs, { seg: "end", kind: "lifecycle", summary: "cycle done", detail: parts.join(" \xB7 ") })];
|
|
5317
|
+
}
|
|
5318
|
+
function codexJsonl(line) {
|
|
5319
|
+
if (!/^\s*\{/.test(line))
|
|
5320
|
+
return null;
|
|
5321
|
+
try {
|
|
5322
|
+
const o = JSON.parse(line);
|
|
5323
|
+
const text = typeof o["text"] === "string" && o["text"] || typeof o["message"] === "string" && o["message"] || typeof o["content"] === "string" && o["content"] || typeof o["delta"] === "string" && o["delta"] || "";
|
|
5324
|
+
const kind = typeof o["type"] === "string" ? o["type"] : typeof o["role"] === "string" ? o["role"] : void 0;
|
|
5325
|
+
const r = {};
|
|
5326
|
+
if (kind !== void 0)
|
|
5327
|
+
r.kind = kind;
|
|
5328
|
+
if (typeof text === "string" && text !== "")
|
|
5329
|
+
r.text = text;
|
|
5330
|
+
return r;
|
|
5331
|
+
} catch {
|
|
5332
|
+
return null;
|
|
5333
|
+
}
|
|
5334
|
+
}
|
|
5335
|
+
function normalizerFor(agent) {
|
|
5336
|
+
const a = (agent ?? "").trim().toLowerCase();
|
|
5337
|
+
if (a === "claude")
|
|
5338
|
+
return claudeNormalizer;
|
|
5339
|
+
if (a === "codex")
|
|
5340
|
+
return codexNormalizer;
|
|
5341
|
+
return genericNormalizer;
|
|
5342
|
+
}
|
|
5343
|
+
var KIND_TIER, DEFAULT_HEARTBEAT_GAP_MS, SUPPRESS_TOOLS, PEER_VERDICTS, claudeNormalizer, VITEST_FAIL_RE, VITEST_PASS_RE, TEST_FILE_RE, DIFF_FILE_RE, UNIFIED_DIFF_RE, CMD_RE, codexNormalizer, genericNormalizer;
|
|
5344
|
+
var init_activity_signal = __esm({
|
|
5345
|
+
"packages/core/dist/loop/activity-signal.js"() {
|
|
5346
|
+
"use strict";
|
|
5347
|
+
init_signals();
|
|
5348
|
+
KIND_TIER = {
|
|
5349
|
+
lifecycle: "A",
|
|
5350
|
+
tcr: "A",
|
|
5351
|
+
commit: "A",
|
|
5352
|
+
pr: "A",
|
|
5353
|
+
gate: "A",
|
|
5354
|
+
alert: "A",
|
|
5355
|
+
heartbeat: "A",
|
|
5356
|
+
test: "B",
|
|
5357
|
+
// pass → B; a FAIL is promoted to A at emit time
|
|
5358
|
+
edit: "B",
|
|
5359
|
+
tool: "B",
|
|
5360
|
+
say: "C"
|
|
5361
|
+
};
|
|
5362
|
+
DEFAULT_HEARTBEAT_GAP_MS = 45e3;
|
|
5363
|
+
SUPPRESS_TOOLS = /* @__PURE__ */ new Set([
|
|
5364
|
+
"Read",
|
|
5365
|
+
"Glob",
|
|
5366
|
+
"Grep",
|
|
5367
|
+
"ReadMcpResourceTool",
|
|
5368
|
+
"ListMcpResourcesTool",
|
|
5369
|
+
"WebFetch",
|
|
5370
|
+
"WebSearch",
|
|
5371
|
+
"TaskCreate",
|
|
5372
|
+
"TaskGet",
|
|
5373
|
+
"TaskList",
|
|
5374
|
+
"TaskUpdate",
|
|
5375
|
+
"TaskOutput",
|
|
5376
|
+
"TaskStop"
|
|
5377
|
+
]);
|
|
5378
|
+
PEER_VERDICTS = ["AGREE", "REFINE", "OBJECT", "ESCALATE"];
|
|
5379
|
+
claudeNormalizer = {
|
|
5380
|
+
agent: "claude",
|
|
5381
|
+
reset: resetState,
|
|
5382
|
+
normalize(raw, st, nowMs) {
|
|
5383
|
+
const line = raw.replace(/\s+$/, "");
|
|
5384
|
+
if (line.trim() === "")
|
|
5385
|
+
return [];
|
|
5386
|
+
const banner = matchBanner(line);
|
|
5387
|
+
if (banner) {
|
|
5388
|
+
resetState(st);
|
|
5389
|
+
st.cycleId = banner.cycleId;
|
|
5390
|
+
return [emit(st, nowMs, { seg: "cycle", kind: "lifecycle", summary: banner.label })];
|
|
5391
|
+
}
|
|
5392
|
+
let ev;
|
|
5393
|
+
try {
|
|
5394
|
+
ev = JSON.parse(line);
|
|
5395
|
+
} catch {
|
|
5396
|
+
return [];
|
|
5397
|
+
}
|
|
5398
|
+
if (typeof ev !== "object" || ev === null)
|
|
5399
|
+
return [];
|
|
5400
|
+
const type = ev.type;
|
|
5401
|
+
if (type === "system")
|
|
5402
|
+
return [];
|
|
5403
|
+
if (type === "assistant")
|
|
5404
|
+
return claudeAssistant(ev, st, nowMs);
|
|
5405
|
+
if (type === "user")
|
|
5406
|
+
return claudeUser(ev, st, nowMs);
|
|
5407
|
+
if (type === "result")
|
|
5408
|
+
return claudeResult(ev, st, nowMs);
|
|
5409
|
+
return [];
|
|
5410
|
+
}
|
|
5411
|
+
};
|
|
5412
|
+
VITEST_FAIL_RE = /(\d+)\s+failed|FAIL\b|✗|✘|✖|tests?\s+failed|failed\s+\(\d+\)/i;
|
|
5413
|
+
VITEST_PASS_RE = /\b(\d+)\s+passed\b|✓\s+\d+|all tests pass|tests?\s+passed/i;
|
|
5414
|
+
TEST_FILE_RE = /([\w./-]+\.(?:test|spec)\.[jt]sx?)(?::(\d+))?/;
|
|
5415
|
+
DIFF_FILE_RE = /(?:^|\s)(?:✎|✏|edit(?:ing)?|writing|modified|patch(?:ing)?)\s+([\w./-]+)/i;
|
|
5416
|
+
UNIFIED_DIFF_RE = /^\s*(?:\+\+\+|---)\s+[ab]\/([\w./-]+)/;
|
|
5417
|
+
CMD_RE = /^\s*(?:\$|>|Running:|Exec:|Command:|\+\s)\s*(.+)$/;
|
|
5418
|
+
codexNormalizer = {
|
|
5419
|
+
agent: "codex",
|
|
5420
|
+
reset: resetState,
|
|
5421
|
+
normalize(raw, st, nowMs) {
|
|
5422
|
+
const line = raw.replace(/\s+$/, "");
|
|
5423
|
+
if (line.trim() === "")
|
|
5424
|
+
return [];
|
|
5425
|
+
const banner = matchBanner(line);
|
|
5426
|
+
if (banner) {
|
|
5427
|
+
resetState(st);
|
|
5428
|
+
st.cycleId = banner.cycleId;
|
|
5429
|
+
return [emit(st, nowMs, { seg: "cycle", kind: "lifecycle", summary: banner.label })];
|
|
5430
|
+
}
|
|
5431
|
+
let text = line;
|
|
5432
|
+
const j = codexJsonl(line);
|
|
5433
|
+
if (j !== null) {
|
|
5434
|
+
if (j.text === void 0)
|
|
5435
|
+
return [];
|
|
5436
|
+
text = j.text;
|
|
5437
|
+
}
|
|
5438
|
+
const t2 = text.trim();
|
|
5439
|
+
if (t2 === "")
|
|
5440
|
+
return [];
|
|
5441
|
+
const fileM = TEST_FILE_RE.exec(t2);
|
|
5442
|
+
if (VITEST_FAIL_RE.test(t2)) {
|
|
5443
|
+
st.seg = "ci";
|
|
5444
|
+
st.editStreakFile = null;
|
|
5445
|
+
const ref = fileM ? fileM[1] + (fileM[2] ? `:${fileM[2]}` : "") : "";
|
|
5446
|
+
return [emit(st, nowMs, { seg: "ci", kind: "test", summary: clip(t2, 60), result: "fail", ref, marker: "ci:fail" })];
|
|
5447
|
+
}
|
|
5448
|
+
if (VITEST_PASS_RE.test(t2)) {
|
|
5449
|
+
st.seg = "ci";
|
|
5450
|
+
st.editStreakFile = null;
|
|
5451
|
+
const ref = fileM ? fileM[1] + (fileM[2] ? `:${fileM[2]}` : "") : "";
|
|
5452
|
+
return [emit(st, nowMs, { seg: "ci", kind: "test", summary: clip(t2, 60), result: "pass", ref, marker: "ci:pass" })];
|
|
5453
|
+
}
|
|
5454
|
+
const tcrM = /\[[\w/-]+\s+([0-9a-f]{7,})\]\s*tcr:\s*(.+)/.exec(t2);
|
|
5455
|
+
if (tcrM) {
|
|
5456
|
+
st.tcrCount += 1;
|
|
5457
|
+
st.editStreakFile = null;
|
|
5458
|
+
return [emit(st, nowMs, { kind: "tcr", summary: tcrM[1].slice(0, 7), detail: clip(tcrM[2].trim(), 60), ref: tcrM[1].slice(0, 7), result: "pass", marker: "tcr" })];
|
|
5459
|
+
}
|
|
5460
|
+
const prM = /(?:Merged|merge[ds]?)\b[^#]*#(\d+)/.exec(t2);
|
|
5461
|
+
if (prM) {
|
|
5462
|
+
st.seg = "pr";
|
|
5463
|
+
st.editStreakFile = null;
|
|
5464
|
+
return [emit(st, nowMs, { seg: "pr", kind: "pr", summary: `#${prM[1]}`, ref: `#${prM[1]}`, detail: "merged", result: "pass", marker: "pr:merge" })];
|
|
5465
|
+
}
|
|
5466
|
+
const diffM = DIFF_FILE_RE.exec(t2) ?? UNIFIED_DIFF_RE.exec(t2);
|
|
5467
|
+
if (diffM) {
|
|
5468
|
+
const path = diffM[1];
|
|
5469
|
+
if (path === st.editStreakFile)
|
|
5470
|
+
return [];
|
|
5471
|
+
st.editStreakFile = path;
|
|
5472
|
+
st.seg = "build";
|
|
5473
|
+
return [emit(st, nowMs, { seg: "build", kind: "edit", summary: basename2(path), ref: path })];
|
|
5474
|
+
}
|
|
5475
|
+
const cmdM = CMD_RE.exec(t2);
|
|
5476
|
+
if (cmdM) {
|
|
5477
|
+
st.editStreakFile = null;
|
|
5478
|
+
const cmd = cmdM[1].trim();
|
|
5479
|
+
if (/git\s+commit/.test(cmd) || /gh\s+pr\s+(create|merge)/.test(cmd))
|
|
5480
|
+
st.seg = "pr";
|
|
5481
|
+
else if (/test|vitest|pnpm\s+-r/.test(cmd))
|
|
5482
|
+
st.seg = "ci";
|
|
5483
|
+
return [emit(st, nowMs, { kind: "tool", summary: clip(cmd, 60), ref: "cmd" })];
|
|
5484
|
+
}
|
|
5485
|
+
return [emit(st, nowMs, { kind: "say", summary: clip(t2, 80) })];
|
|
5486
|
+
}
|
|
5487
|
+
};
|
|
5488
|
+
genericNormalizer = {
|
|
5489
|
+
agent: "generic",
|
|
5490
|
+
reset: resetState,
|
|
5491
|
+
normalize(raw, st, nowMs) {
|
|
5492
|
+
const line = raw.replace(/\s+$/, "");
|
|
5493
|
+
if (line.trim() === "")
|
|
5494
|
+
return [];
|
|
5495
|
+
const banner = matchBanner(line);
|
|
5496
|
+
if (banner) {
|
|
5497
|
+
resetState(st);
|
|
5498
|
+
st.cycleId = banner.cycleId;
|
|
5499
|
+
return [emit(st, nowMs, { seg: "cycle", kind: "lifecycle", summary: banner.label })];
|
|
5500
|
+
}
|
|
5501
|
+
return [emit(st, nowMs, { kind: "say", summary: clip(line, 100) })];
|
|
5502
|
+
}
|
|
5503
|
+
};
|
|
5504
|
+
}
|
|
5505
|
+
});
|
|
5506
|
+
|
|
4981
5507
|
// packages/core/dist/loop/alert-loop.js
|
|
4982
5508
|
function alertFileName(slug) {
|
|
4983
5509
|
return `ALERT-${slug}.md`;
|
|
@@ -5207,14 +5733,14 @@ function classifyAttribution(storyId, reasons) {
|
|
|
5207
5733
|
}
|
|
5208
5734
|
};
|
|
5209
5735
|
}
|
|
5210
|
-
function priorCorrectionCount(events, storyId,
|
|
5736
|
+
function priorCorrectionCount(events, storyId, signal) {
|
|
5211
5737
|
let n = 0;
|
|
5212
5738
|
for (const ev of events) {
|
|
5213
5739
|
if (ev.type !== "correction:action")
|
|
5214
5740
|
continue;
|
|
5215
5741
|
if (ev.storyId !== storyId)
|
|
5216
5742
|
continue;
|
|
5217
|
-
if (ev.signal !==
|
|
5743
|
+
if (ev.signal !== signal)
|
|
5218
5744
|
continue;
|
|
5219
5745
|
n += 1;
|
|
5220
5746
|
}
|
|
@@ -5245,8 +5771,8 @@ var init_correction_actuator = __esm({
|
|
|
5245
5771
|
});
|
|
5246
5772
|
|
|
5247
5773
|
// packages/core/dist/loop/correction-safety.js
|
|
5248
|
-
function normalizeSignal(
|
|
5249
|
-
return
|
|
5774
|
+
function normalizeSignal(signal) {
|
|
5775
|
+
return signal.trim().toLowerCase().replace(/\s+/g, " ").slice(0, 160);
|
|
5250
5776
|
}
|
|
5251
5777
|
function cycleStoryMap(events) {
|
|
5252
5778
|
const out3 = /* @__PURE__ */ new Map();
|
|
@@ -5261,26 +5787,26 @@ function correctionSignals(events) {
|
|
|
5261
5787
|
const out3 = [];
|
|
5262
5788
|
for (const ev of events) {
|
|
5263
5789
|
if (ev.type === "correction:action") {
|
|
5264
|
-
const
|
|
5265
|
-
if (
|
|
5790
|
+
const signal = normalizeSignal(ev.signal);
|
|
5791
|
+
if (signal === "")
|
|
5266
5792
|
continue;
|
|
5267
5793
|
out3.push({
|
|
5268
5794
|
storyId: ev.storyId,
|
|
5269
5795
|
...ev.cycleId !== void 0 ? { cycleId: ev.cycleId } : {},
|
|
5270
|
-
signal
|
|
5796
|
+
signal,
|
|
5271
5797
|
action: ev.action,
|
|
5272
5798
|
ts: ev.ts,
|
|
5273
5799
|
source: "correction"
|
|
5274
5800
|
});
|
|
5275
5801
|
} else if (ev.type === "attest:gate" && ev.verdict === "skipped") {
|
|
5276
|
-
const
|
|
5277
|
-
if (
|
|
5802
|
+
const signal = normalizeSignal(ev.reasons[0] ?? "attest gate skipped");
|
|
5803
|
+
if (signal === "")
|
|
5278
5804
|
continue;
|
|
5279
5805
|
const storyId = stories.get(ev.cycleId);
|
|
5280
5806
|
out3.push({
|
|
5281
5807
|
...storyId !== void 0 ? { storyId } : {},
|
|
5282
5808
|
cycleId: ev.cycleId,
|
|
5283
|
-
signal
|
|
5809
|
+
signal,
|
|
5284
5810
|
action: "attest_skipped",
|
|
5285
5811
|
ts: ev.ts,
|
|
5286
5812
|
source: "attest"
|
|
@@ -5328,7 +5854,7 @@ function correctionSignalVerdict(events, safety, nowSec2) {
|
|
|
5328
5854
|
for (const sig of inWindow) {
|
|
5329
5855
|
bySignal.set(sig.signal, [...bySignal.get(sig.signal) ?? [], sig]);
|
|
5330
5856
|
}
|
|
5331
|
-
for (const [
|
|
5857
|
+
for (const [signal, hits] of [...bySignal.entries()].sort((a, b) => b[1].length - a[1].length || a[0].localeCompare(b[0]))) {
|
|
5332
5858
|
if (hits.length < threshold)
|
|
5333
5859
|
continue;
|
|
5334
5860
|
const knownStories = new Set(hits.map((h) => h.storyId).filter((s) => s !== void 0 && s !== ""));
|
|
@@ -5338,10 +5864,10 @@ function correctionSignalVerdict(events, safety, nowSec2) {
|
|
|
5338
5864
|
action: "pause_and_notify",
|
|
5339
5865
|
kind: "signal_repeat",
|
|
5340
5866
|
...knownStories.size > 0 ? { storyId: [...knownStories].sort().join(",") } : {},
|
|
5341
|
-
signal
|
|
5867
|
+
signal,
|
|
5342
5868
|
count: hits.length,
|
|
5343
5869
|
threshold,
|
|
5344
|
-
reason: `failure signal repeated: "${
|
|
5870
|
+
reason: `failure signal repeated: "${signal}" ${hits.length} times in ${windowSec}s >= ${threshold}`
|
|
5345
5871
|
};
|
|
5346
5872
|
}
|
|
5347
5873
|
return { action: "continue" };
|
|
@@ -5806,389 +6332,120 @@ function cycleStep(state, event) {
|
|
|
5806
6332
|
}
|
|
5807
6333
|
case "facts_captured": {
|
|
5808
6334
|
const status2 = classifyCaptured(event.facts);
|
|
5809
|
-
const next = { ...state, phase: "reconcile", captured: event.facts };
|
|
5810
|
-
if (status2 !== "built") {
|
|
5811
|
-
const extra = status2 === "idle" || status2 === "published" ? [{ kind: "cleanup_worktree", branch: state.ctx.branch }] : status2 === "failed" && (event.facts.mainAhead ?? 0) > 0 ? [
|
|
5812
|
-
{
|
|
5813
|
-
kind: "append_alert",
|
|
5814
|
-
message: `cycle ${state.ctx.cycleId}: local main is ahead of origin/main by ${event.facts.mainAhead} commit(s) while cycle branch has ${event.facts.commitsAhead} commit(s); leaving state untouched for rescue (FIX-252)`
|
|
5815
|
-
}
|
|
5816
|
-
] : status2 === "failed" && event.facts.commitsAhead > 0 ? [
|
|
5817
|
-
{ kind: "push_orphan", branch: state.ctx.branch },
|
|
5818
|
-
{
|
|
5819
|
-
kind: "append_alert",
|
|
5820
|
-
message: `cycle ${state.ctx.cycleId}: gate-killed with ${event.facts.commitsAhead} commit(s) \u2014 branch ${state.ctx.branch} pushed for audit/rescue; next cycle starts fresh by design (FIX-247)`
|
|
5821
|
-
}
|
|
5822
|
-
] : [];
|
|
5823
|
-
return terminate(next, status2, extra);
|
|
5824
|
-
}
|
|
5825
|
-
return {
|
|
5826
|
-
state: { ...next, phase: "publish" },
|
|
5827
|
-
commands: [{ kind: "publish_pr", branch: state.ctx.branch, docOnly: false }]
|
|
5828
|
-
};
|
|
5829
|
-
}
|
|
5830
|
-
case "published": {
|
|
5831
|
-
const status2 = classifyPublish(event.result);
|
|
5832
|
-
if (status2 === "published" || status2 === "done") {
|
|
5833
|
-
return terminate({ ...state, phase: "cleanup" }, status2, [
|
|
5834
|
-
{ kind: "cleanup_worktree", branch: state.ctx.branch }
|
|
5835
|
-
]);
|
|
5836
|
-
}
|
|
5837
|
-
if (status2 === "orphan") {
|
|
5838
|
-
return terminate({ ...state, phase: "cleanup" }, "orphan", [
|
|
5839
|
-
{ kind: "cleanup_worktree", branch: state.ctx.branch },
|
|
5840
|
-
{ kind: "append_alert", message: `cycle ${state.ctx.cycleId}: publish failed; orphan branch+tag pushed; worktree cleaned` }
|
|
5841
|
-
]);
|
|
5842
|
-
}
|
|
5843
|
-
return terminate({ ...state, phase: "publish" }, "failed", [
|
|
5844
|
-
{ kind: "append_alert", message: `cycle ${state.ctx.cycleId}: publish failed; worktree preserved at branch ${state.ctx.branch}` }
|
|
5845
|
-
]);
|
|
5846
|
-
}
|
|
5847
|
-
case "merge_polled": {
|
|
5848
|
-
const action = nextWaitAction(event.state, event.elapsedSec);
|
|
5849
|
-
if (action.kind === "wait") {
|
|
5850
|
-
return {
|
|
5851
|
-
state: { ...state, phase: "merge-wait" },
|
|
5852
|
-
commands: [{ kind: "wait_merge", branch: state.ctx.branch, elapsedSec: event.elapsedSec + action.sleepSeconds }]
|
|
5853
|
-
};
|
|
5854
|
-
}
|
|
5855
|
-
if (action.kind === "merged") {
|
|
5856
|
-
return terminate({ ...state, phase: "reconcile" }, "done", [
|
|
5857
|
-
{ kind: "reconcile" },
|
|
5858
|
-
{ kind: "cleanup_worktree", branch: state.ctx.branch }
|
|
5859
|
-
]);
|
|
5860
|
-
}
|
|
5861
|
-
return terminate({ ...state, phase: "merge-wait" }, "orphan", [
|
|
5862
|
-
{ kind: "push_orphan", branch: state.ctx.branch }
|
|
5863
|
-
]);
|
|
5864
|
-
}
|
|
5865
|
-
default:
|
|
5866
|
-
return { state, commands: [] };
|
|
5867
|
-
}
|
|
5868
|
-
}
|
|
5869
|
-
function cycleStartEvent(ctx, ts = 0) {
|
|
5870
|
-
return {
|
|
5871
|
-
type: "cycle:start",
|
|
5872
|
-
cycleId: ctx.cycleId,
|
|
5873
|
-
storyId: ctx.storyId ?? "",
|
|
5874
|
-
agent: ctx.agent ?? "",
|
|
5875
|
-
model: ctx.model ?? "",
|
|
5876
|
-
ts
|
|
5877
|
-
};
|
|
5878
|
-
}
|
|
5879
|
-
function initialCycleState(ctx) {
|
|
5880
|
-
return { phase: "pick", ctx, attempt: 0, done: false };
|
|
5881
|
-
}
|
|
5882
|
-
var CYCLE_TIMEOUT_SEC, WATCHDOG_KILL_GRACE_SEC, MAX_AGENT_ATTEMPTS, RETRY_BASE_BACKOFF_SEC, EVENT_VALID_PHASES;
|
|
5883
|
-
var init_orchestrator = __esm({
|
|
5884
|
-
"packages/core/dist/loop/orchestrator.js"() {
|
|
5885
|
-
"use strict";
|
|
5886
|
-
init_pr();
|
|
5887
|
-
CYCLE_TIMEOUT_SEC = 2700;
|
|
5888
|
-
WATCHDOG_KILL_GRACE_SEC = 5;
|
|
5889
|
-
MAX_AGENT_ATTEMPTS = 3;
|
|
5890
|
-
RETRY_BASE_BACKOFF_SEC = 30;
|
|
5891
|
-
EVENT_VALID_PHASES = {
|
|
5892
|
-
preflight_done: ["pick"],
|
|
5893
|
-
worktree_created: ["worktree"],
|
|
5894
|
-
worktree_failed: ["worktree"],
|
|
5895
|
-
story_picked: ["pick"],
|
|
5896
|
-
no_story: ["pick"],
|
|
5897
|
-
route_resolved: ["route"],
|
|
5898
|
-
budget_ok: ["route"],
|
|
5899
|
-
budget_halt: ["route"],
|
|
5900
|
-
agent_exited: ["execute"],
|
|
5901
|
-
facts_captured: ["reconcile"],
|
|
5902
|
-
published: ["publish"],
|
|
5903
|
-
merge_polled: ["merge-wait", "publish"],
|
|
5904
|
-
reconciled: ["reconcile"],
|
|
5905
|
-
cleaned: ["cleanup"]
|
|
5906
|
-
};
|
|
5907
|
-
}
|
|
5908
|
-
});
|
|
5909
|
-
|
|
5910
|
-
// packages/core/dist/loop/recovery.js
|
|
5911
|
-
function resolveKeepDays(envDays, yamlDays) {
|
|
5912
|
-
if (envDays !== void 0 && /^\d+$/.test(envDays.trim()))
|
|
5913
|
-
return Number(envDays.trim());
|
|
5914
|
-
if (yamlDays !== void 0 && Number.isFinite(yamlDays) && yamlDays >= 0)
|
|
5915
|
-
return Math.trunc(yamlDays);
|
|
5916
|
-
return GC_DEFAULT_KEEP_DAYS;
|
|
5917
|
-
}
|
|
5918
|
-
var GC_DEFAULT_KEEP_DAYS;
|
|
5919
|
-
var init_recovery = __esm({
|
|
5920
|
-
"packages/core/dist/loop/recovery.js"() {
|
|
5921
|
-
"use strict";
|
|
5922
|
-
GC_DEFAULT_KEEP_DAYS = 30;
|
|
5923
|
-
}
|
|
5924
|
-
});
|
|
5925
|
-
|
|
5926
|
-
// packages/core/dist/loop/signals.js
|
|
5927
|
-
function signalKindForMarker(marker) {
|
|
5928
|
-
if (marker === "tcr")
|
|
5929
|
-
return "tcr";
|
|
5930
|
-
if (marker === "skill" || marker === "story")
|
|
5931
|
-
return "skill";
|
|
5932
|
-
if (marker.startsWith("ci:"))
|
|
5933
|
-
return "ci";
|
|
5934
|
-
if (marker === "peer:gate" || marker === "peer")
|
|
5935
|
-
return "peer";
|
|
5936
|
-
if (marker === "attest:gate" || marker === "evidence:frame-opened" || marker === "attest")
|
|
5937
|
-
return "attest";
|
|
5938
|
-
if (marker.startsWith("pr:"))
|
|
5939
|
-
return "pr";
|
|
5940
|
-
if (marker === "alert" || marker === "error")
|
|
5941
|
-
return "alert";
|
|
5942
|
-
return null;
|
|
5943
|
-
}
|
|
5944
|
-
var init_signals = __esm({
|
|
5945
|
-
"packages/core/dist/loop/signals.js"() {
|
|
5946
|
-
"use strict";
|
|
5947
|
-
}
|
|
5948
|
-
});
|
|
5949
|
-
|
|
5950
|
-
// packages/core/dist/loop/loop-fmt.js
|
|
5951
|
-
function newFmtState() {
|
|
5952
|
-
return {
|
|
5953
|
-
pendingCommit: false,
|
|
5954
|
-
pendingPr: false,
|
|
5955
|
-
pendingCi: false,
|
|
5956
|
-
pendingStory: false,
|
|
5957
|
-
lastBashCmd: "",
|
|
5958
|
-
tcrCount: 0,
|
|
5959
|
-
editStreakFile: null
|
|
5960
|
-
};
|
|
5961
|
-
}
|
|
5962
|
-
function clip(s, n = 60) {
|
|
5963
|
-
const flat = s.replace(/\s+/g, " ").trim();
|
|
5964
|
-
return flat.length > n ? `${flat.slice(0, n - 1)}\u2026` : flat;
|
|
5965
|
-
}
|
|
5966
|
-
function basename2(p) {
|
|
5967
|
-
const trimmed = p.replace(/\/+$/, "");
|
|
5968
|
-
const i = trimmed.lastIndexOf("/");
|
|
5969
|
-
return i >= 0 ? trimmed.slice(i + 1) : trimmed;
|
|
5970
|
-
}
|
|
5971
|
-
function clearPending(st) {
|
|
5972
|
-
st.pendingCommit = false;
|
|
5973
|
-
st.pendingPr = false;
|
|
5974
|
-
st.pendingCi = false;
|
|
5975
|
-
st.pendingStory = false;
|
|
5976
|
-
}
|
|
5977
|
-
function signal(marker, category, label4, detail, ok8 = true) {
|
|
5978
|
-
const kind = signalKindForMarker(marker);
|
|
5979
|
-
const line = { tier: "signal", category, label: label4, ok: ok8 };
|
|
5980
|
-
if (kind !== null)
|
|
5981
|
-
line.kind = kind;
|
|
5982
|
-
if (detail !== void 0 && detail !== "")
|
|
5983
|
-
line.detail = detail;
|
|
5984
|
-
return line;
|
|
5985
|
-
}
|
|
5986
|
-
function formatLine(raw, st) {
|
|
5987
|
-
const line = raw.replace(/\s+$/, "");
|
|
5988
|
-
if (line.trim() === "")
|
|
5989
|
-
return [];
|
|
5990
|
-
const header = /^──\s*cycle\s+(.+?)\s*──\s*$/.exec(line);
|
|
5991
|
-
if (header) {
|
|
5992
|
-
clearPending(st);
|
|
5993
|
-
st.tcrCount = 0;
|
|
5994
|
-
st.editStreakFile = null;
|
|
5995
|
-
return [{ tier: "banner", category: "cycle", label: clip(header[1], 80) }];
|
|
5996
|
-
}
|
|
5997
|
-
let ev;
|
|
5998
|
-
try {
|
|
5999
|
-
ev = JSON.parse(line);
|
|
6000
|
-
} catch {
|
|
6001
|
-
const m7 = /\[loop\]\s+cycle\s+(\d+)/.exec(line);
|
|
6002
|
-
if (m7) {
|
|
6003
|
-
clearPending(st);
|
|
6004
|
-
st.tcrCount = 0;
|
|
6005
|
-
return [{ tier: "banner", category: "cycle", label: `cycle #${m7[1]}` }];
|
|
6006
|
-
}
|
|
6007
|
-
return [];
|
|
6008
|
-
}
|
|
6009
|
-
if (typeof ev !== "object" || ev === null)
|
|
6010
|
-
return [];
|
|
6011
|
-
const type = ev.type;
|
|
6012
|
-
if (type === "system")
|
|
6013
|
-
return [];
|
|
6014
|
-
if (type === "assistant")
|
|
6015
|
-
return handleAssistant(ev, st);
|
|
6016
|
-
if (type === "user")
|
|
6017
|
-
return handleUser(ev, st);
|
|
6018
|
-
if (type === "result")
|
|
6019
|
-
return handleResult(ev, st);
|
|
6020
|
-
return [];
|
|
6021
|
-
}
|
|
6022
|
-
function handleAssistant(ev, st) {
|
|
6023
|
-
const msg6 = ev["message"] ?? {};
|
|
6024
|
-
const content = Array.isArray(msg6["content"]) ? msg6["content"] : [];
|
|
6025
|
-
const out3 = [];
|
|
6026
|
-
for (const blkRaw of content) {
|
|
6027
|
-
if (typeof blkRaw !== "object" || blkRaw === null)
|
|
6028
|
-
continue;
|
|
6029
|
-
const blk = blkRaw;
|
|
6030
|
-
const bt = blk["type"];
|
|
6031
|
-
if (bt === "thinking")
|
|
6032
|
-
continue;
|
|
6033
|
-
if (bt === "text") {
|
|
6034
|
-
out3.push(...handleText(typeof blk["text"] === "string" ? blk["text"] : "", st));
|
|
6035
|
-
} else if (bt === "tool_use") {
|
|
6036
|
-
out3.push(...handleToolUse(blk, st));
|
|
6037
|
-
}
|
|
6038
|
-
}
|
|
6039
|
-
return out3;
|
|
6040
|
-
}
|
|
6041
|
-
function handleText(text, st) {
|
|
6042
|
-
const t2 = text.trim();
|
|
6043
|
-
if (t2 === "")
|
|
6044
|
-
return [];
|
|
6045
|
-
for (const v of PEER_VERDICTS) {
|
|
6046
|
-
if (t2.includes(v)) {
|
|
6047
|
-
const rm = /round\s+(\d+)[/\\](\d+)/i.exec(t2);
|
|
6048
|
-
const round = rm ? `round ${rm[1]}/${rm[2]}` : "round ?";
|
|
6049
|
-
const am = /(\w+)\s*→\s*(\w+)/.exec(t2);
|
|
6050
|
-
const agents = am ? `${am[1]} \u2192 ${am[2]}` : "peer";
|
|
6051
|
-
st.editStreakFile = null;
|
|
6052
|
-
return [signal("peer", "peer", agents, `${round} \xB7 ${v}`)];
|
|
6053
|
-
}
|
|
6054
|
-
}
|
|
6055
|
-
return [];
|
|
6056
|
-
}
|
|
6057
|
-
function handleToolUse(blk, st) {
|
|
6058
|
-
const name = typeof blk["name"] === "string" ? blk["name"] : "";
|
|
6059
|
-
const input = blk["input"] ?? {};
|
|
6060
|
-
if (SUPPRESS_TOOLS.has(name))
|
|
6061
|
-
return [];
|
|
6062
|
-
if (name === "Edit" || name === "Write") {
|
|
6063
|
-
const path = typeof input["file_path"] === "string" && input["file_path"] || typeof input["path"] === "string" && input["path"] || "";
|
|
6064
|
-
if (path === st.editStreakFile)
|
|
6065
|
-
return [];
|
|
6066
|
-
st.editStreakFile = path;
|
|
6067
|
-
return [{ tier: "muted", category: "\u270F", label: `\u270F ${basename2(path)}` }];
|
|
6068
|
-
}
|
|
6069
|
-
st.editStreakFile = null;
|
|
6070
|
-
if (name === "Bash") {
|
|
6071
|
-
const cmd = typeof input["command"] === "string" ? input["command"] : "";
|
|
6072
|
-
const first = cmd.split("\n").map((l) => l.trim()).find((l) => l !== "") ?? cmd;
|
|
6073
|
-
st.lastBashCmd = first;
|
|
6074
|
-
if (/git\s+commit[\s\S]*tcr:/.test(cmd))
|
|
6075
|
-
st.pendingCommit = true;
|
|
6076
|
-
else if (/gh\s+pr\s+(create|merge)/.test(cmd))
|
|
6077
|
-
st.pendingPr = true;
|
|
6078
|
-
else if (/(roll\s+ci|npm\s+run\s+ci|_ci_wait|ci:local)/.test(cmd))
|
|
6079
|
-
st.pendingCi = true;
|
|
6080
|
-
return [];
|
|
6081
|
-
}
|
|
6082
|
-
if (name === "Skill") {
|
|
6083
|
-
const skill = typeof input["skill"] === "string" ? input["skill"] : "";
|
|
6084
|
-
if (skill === "roll-build" || skill === "roll-fix") {
|
|
6085
|
-
const args = (typeof input["args"] === "string" ? input["args"] : "").trim();
|
|
6086
|
-
const usId = args.split(/\s+/)[0] || "?";
|
|
6087
|
-
st.pendingStory = true;
|
|
6088
|
-
return [signal("skill", "story", usId, clip(args, 60))];
|
|
6089
|
-
}
|
|
6090
|
-
return [];
|
|
6091
|
-
}
|
|
6092
|
-
return [];
|
|
6093
|
-
}
|
|
6094
|
-
function extractResultText(content) {
|
|
6095
|
-
if (typeof content === "string")
|
|
6096
|
-
return content;
|
|
6097
|
-
if (Array.isArray(content)) {
|
|
6098
|
-
return content.filter((c2) => typeof c2 === "object" && c2 !== null && c2["type"] === "text").map((c2) => typeof c2["text"] === "string" ? c2["text"] : "").join("\n");
|
|
6099
|
-
}
|
|
6100
|
-
return content == null ? "" : String(content);
|
|
6101
|
-
}
|
|
6102
|
-
function handleUser(ev, st) {
|
|
6103
|
-
const msg6 = ev["message"] ?? {};
|
|
6104
|
-
const content = Array.isArray(msg6["content"]) ? msg6["content"] : [];
|
|
6105
|
-
const out3 = [];
|
|
6106
|
-
for (const blkRaw of content) {
|
|
6107
|
-
if (typeof blkRaw !== "object" || blkRaw === null)
|
|
6108
|
-
continue;
|
|
6109
|
-
const blk = blkRaw;
|
|
6110
|
-
if (blk["type"] !== "tool_result")
|
|
6111
|
-
continue;
|
|
6112
|
-
const text = extractResultText(blk["content"]);
|
|
6113
|
-
if (blk["is_error"] === true) {
|
|
6114
|
-
st.editStreakFile = null;
|
|
6115
|
-
const lines2 = text.split("\n").filter((l) => l.trim() !== "").slice(0, 3);
|
|
6116
|
-
clearPending(st);
|
|
6117
|
-
out3.push(signal("error", "error", "tool", clip(lines2.join(" | "), 80), false));
|
|
6118
|
-
continue;
|
|
6119
|
-
}
|
|
6120
|
-
if (st.pendingCommit) {
|
|
6121
|
-
st.pendingCommit = false;
|
|
6122
|
-
const m7 = /\[[\w/-]+ ([0-9a-f]{7,})\]\s*tcr:\s*(.+)/.exec(text);
|
|
6123
|
-
if (m7) {
|
|
6124
|
-
st.tcrCount += 1;
|
|
6125
|
-
out3.push(signal("tcr", "tcr", m7[1].slice(0, 7), clip(m7[2].trim(), 60)));
|
|
6335
|
+
const next = { ...state, phase: "reconcile", captured: event.facts };
|
|
6336
|
+
if (status2 !== "built") {
|
|
6337
|
+
const extra = status2 === "idle" || status2 === "published" ? [{ kind: "cleanup_worktree", branch: state.ctx.branch }] : status2 === "failed" && (event.facts.mainAhead ?? 0) > 0 ? [
|
|
6338
|
+
{
|
|
6339
|
+
kind: "append_alert",
|
|
6340
|
+
message: `cycle ${state.ctx.cycleId}: local main is ahead of origin/main by ${event.facts.mainAhead} commit(s) while cycle branch has ${event.facts.commitsAhead} commit(s); leaving state untouched for rescue (FIX-252)`
|
|
6341
|
+
}
|
|
6342
|
+
] : status2 === "failed" && event.facts.commitsAhead > 0 ? [
|
|
6343
|
+
{ kind: "push_orphan", branch: state.ctx.branch },
|
|
6344
|
+
{
|
|
6345
|
+
kind: "append_alert",
|
|
6346
|
+
message: `cycle ${state.ctx.cycleId}: gate-killed with ${event.facts.commitsAhead} commit(s) \u2014 branch ${state.ctx.branch} pushed for audit/rescue; next cycle starts fresh by design (FIX-247)`
|
|
6347
|
+
}
|
|
6348
|
+
] : [];
|
|
6349
|
+
return terminate(next, status2, extra);
|
|
6126
6350
|
}
|
|
6127
|
-
|
|
6128
|
-
|
|
6129
|
-
|
|
6130
|
-
|
|
6131
|
-
continue;
|
|
6351
|
+
return {
|
|
6352
|
+
state: { ...next, phase: "publish" },
|
|
6353
|
+
commands: [{ kind: "publish_pr", branch: state.ctx.branch, docOnly: false }]
|
|
6354
|
+
};
|
|
6132
6355
|
}
|
|
6133
|
-
|
|
6134
|
-
|
|
6135
|
-
|
|
6136
|
-
|
|
6137
|
-
|
|
6138
|
-
|
|
6356
|
+
case "published": {
|
|
6357
|
+
const status2 = classifyPublish(event.result);
|
|
6358
|
+
if (status2 === "published" || status2 === "done") {
|
|
6359
|
+
return terminate({ ...state, phase: "cleanup" }, status2, [
|
|
6360
|
+
{ kind: "cleanup_worktree", branch: state.ctx.branch }
|
|
6361
|
+
]);
|
|
6139
6362
|
}
|
|
6140
|
-
|
|
6363
|
+
if (status2 === "orphan") {
|
|
6364
|
+
return terminate({ ...state, phase: "cleanup" }, "orphan", [
|
|
6365
|
+
{ kind: "cleanup_worktree", branch: state.ctx.branch },
|
|
6366
|
+
{ kind: "append_alert", message: `cycle ${state.ctx.cycleId}: publish failed; orphan branch+tag pushed; worktree cleaned` }
|
|
6367
|
+
]);
|
|
6368
|
+
}
|
|
6369
|
+
return terminate({ ...state, phase: "publish" }, "failed", [
|
|
6370
|
+
{ kind: "append_alert", message: `cycle ${state.ctx.cycleId}: publish failed; worktree preserved at branch ${state.ctx.branch}` }
|
|
6371
|
+
]);
|
|
6141
6372
|
}
|
|
6142
|
-
|
|
6143
|
-
|
|
6144
|
-
|
|
6145
|
-
|
|
6146
|
-
|
|
6147
|
-
|
|
6148
|
-
|
|
6149
|
-
|
|
6150
|
-
|
|
6151
|
-
|
|
6373
|
+
case "merge_polled": {
|
|
6374
|
+
const action = nextWaitAction(event.state, event.elapsedSec);
|
|
6375
|
+
if (action.kind === "wait") {
|
|
6376
|
+
return {
|
|
6377
|
+
state: { ...state, phase: "merge-wait" },
|
|
6378
|
+
commands: [{ kind: "wait_merge", branch: state.ctx.branch, elapsedSec: event.elapsedSec + action.sleepSeconds }]
|
|
6379
|
+
};
|
|
6380
|
+
}
|
|
6381
|
+
if (action.kind === "merged") {
|
|
6382
|
+
return terminate({ ...state, phase: "reconcile" }, "done", [
|
|
6383
|
+
{ kind: "reconcile" },
|
|
6384
|
+
{ kind: "cleanup_worktree", branch: state.ctx.branch }
|
|
6385
|
+
]);
|
|
6386
|
+
}
|
|
6387
|
+
return terminate({ ...state, phase: "merge-wait" }, "orphan", [
|
|
6388
|
+
{ kind: "push_orphan", branch: state.ctx.branch }
|
|
6389
|
+
]);
|
|
6152
6390
|
}
|
|
6391
|
+
default:
|
|
6392
|
+
return { state, commands: [] };
|
|
6153
6393
|
}
|
|
6154
|
-
return out3;
|
|
6155
6394
|
}
|
|
6156
|
-
function
|
|
6157
|
-
|
|
6158
|
-
|
|
6159
|
-
|
|
6160
|
-
|
|
6161
|
-
|
|
6162
|
-
|
|
6395
|
+
function cycleStartEvent(ctx, ts = 0) {
|
|
6396
|
+
return {
|
|
6397
|
+
type: "cycle:start",
|
|
6398
|
+
cycleId: ctx.cycleId,
|
|
6399
|
+
storyId: ctx.storyId ?? "",
|
|
6400
|
+
agent: ctx.agent ?? "",
|
|
6401
|
+
model: ctx.model ?? "",
|
|
6402
|
+
ts
|
|
6403
|
+
};
|
|
6404
|
+
}
|
|
6405
|
+
function initialCycleState(ctx) {
|
|
6406
|
+
return { phase: "pick", ctx, attempt: 0, done: false };
|
|
6407
|
+
}
|
|
6408
|
+
var CYCLE_TIMEOUT_SEC, WATCHDOG_KILL_GRACE_SEC, MAX_AGENT_ATTEMPTS, RETRY_BASE_BACKOFF_SEC, EVENT_VALID_PHASES;
|
|
6409
|
+
var init_orchestrator = __esm({
|
|
6410
|
+
"packages/core/dist/loop/orchestrator.js"() {
|
|
6411
|
+
"use strict";
|
|
6412
|
+
init_pr();
|
|
6413
|
+
CYCLE_TIMEOUT_SEC = 2700;
|
|
6414
|
+
WATCHDOG_KILL_GRACE_SEC = 5;
|
|
6415
|
+
MAX_AGENT_ATTEMPTS = 3;
|
|
6416
|
+
RETRY_BASE_BACKOFF_SEC = 30;
|
|
6417
|
+
EVENT_VALID_PHASES = {
|
|
6418
|
+
preflight_done: ["pick"],
|
|
6419
|
+
worktree_created: ["worktree"],
|
|
6420
|
+
worktree_failed: ["worktree"],
|
|
6421
|
+
story_picked: ["pick"],
|
|
6422
|
+
no_story: ["pick"],
|
|
6423
|
+
route_resolved: ["route"],
|
|
6424
|
+
budget_ok: ["route"],
|
|
6425
|
+
budget_halt: ["route"],
|
|
6426
|
+
agent_exited: ["execute"],
|
|
6427
|
+
facts_captured: ["reconcile"],
|
|
6428
|
+
published: ["publish"],
|
|
6429
|
+
merge_polled: ["merge-wait", "publish"],
|
|
6430
|
+
reconciled: ["reconcile"],
|
|
6431
|
+
cleaned: ["cleanup"]
|
|
6432
|
+
};
|
|
6163
6433
|
}
|
|
6164
|
-
|
|
6165
|
-
|
|
6166
|
-
|
|
6167
|
-
|
|
6168
|
-
|
|
6169
|
-
|
|
6434
|
+
});
|
|
6435
|
+
|
|
6436
|
+
// packages/core/dist/loop/recovery.js
|
|
6437
|
+
function resolveKeepDays(envDays, yamlDays) {
|
|
6438
|
+
if (envDays !== void 0 && /^\d+$/.test(envDays.trim()))
|
|
6439
|
+
return Number(envDays.trim());
|
|
6440
|
+
if (yamlDays !== void 0 && Number.isFinite(yamlDays) && yamlDays >= 0)
|
|
6441
|
+
return Math.trunc(yamlDays);
|
|
6442
|
+
return GC_DEFAULT_KEEP_DAYS;
|
|
6170
6443
|
}
|
|
6171
|
-
var
|
|
6172
|
-
var
|
|
6173
|
-
"packages/core/dist/loop/
|
|
6444
|
+
var GC_DEFAULT_KEEP_DAYS;
|
|
6445
|
+
var init_recovery = __esm({
|
|
6446
|
+
"packages/core/dist/loop/recovery.js"() {
|
|
6174
6447
|
"use strict";
|
|
6175
|
-
|
|
6176
|
-
SUPPRESS_TOOLS = /* @__PURE__ */ new Set([
|
|
6177
|
-
"Read",
|
|
6178
|
-
"Glob",
|
|
6179
|
-
"Grep",
|
|
6180
|
-
"ReadMcpResourceTool",
|
|
6181
|
-
"ListMcpResourcesTool",
|
|
6182
|
-
"WebFetch",
|
|
6183
|
-
"WebSearch",
|
|
6184
|
-
"TaskCreate",
|
|
6185
|
-
"TaskGet",
|
|
6186
|
-
"TaskList",
|
|
6187
|
-
"TaskUpdate",
|
|
6188
|
-
"TaskOutput",
|
|
6189
|
-
"TaskStop"
|
|
6190
|
-
]);
|
|
6191
|
-
PEER_VERDICTS = ["AGREE", "REFINE", "OBJECT", "ESCALATE"];
|
|
6448
|
+
GC_DEFAULT_KEEP_DAYS = 30;
|
|
6192
6449
|
}
|
|
6193
6450
|
});
|
|
6194
6451
|
|
|
@@ -6484,7 +6741,8 @@ function parseLoopSafety(lines2, start) {
|
|
|
6484
6741
|
correctionSignalWindowSec: numOr(flat["correction_signal_window_sec"], DEFAULT_CORRECTION_SIGNAL_WINDOW_SEC),
|
|
6485
6742
|
correctionActuator: flat["correction_actuator"] === "auto" ? "auto" : DEFAULT_CORRECTION_ACTUATOR,
|
|
6486
6743
|
...budget ? { budget } : {},
|
|
6487
|
-
...flat["attest_gate"] === "hard" || flat["attest_gate"] === "soft" ? { attestGate: flat["attest_gate"] } : {}
|
|
6744
|
+
...flat["attest_gate"] === "hard" || flat["attest_gate"] === "soft" ? { attestGate: flat["attest_gate"] } : {},
|
|
6745
|
+
...flat["peer_gate"] === "hard" || flat["peer_gate"] === "soft" ? { peerGate: flat["peer_gate"] } : {}
|
|
6488
6746
|
};
|
|
6489
6747
|
return [i, cfg];
|
|
6490
6748
|
}
|
|
@@ -6731,47 +6989,47 @@ function routeProposals(input, minSamples) {
|
|
|
6731
6989
|
}
|
|
6732
6990
|
function rubricProposals(input, minSamples) {
|
|
6733
6991
|
const out3 = [];
|
|
6734
|
-
for (const
|
|
6735
|
-
if (
|
|
6992
|
+
for (const signal of input.rubricSignals) {
|
|
6993
|
+
if (signal.samples < minSamples)
|
|
6736
6994
|
continue;
|
|
6737
|
-
const current = input.current.rubricWeights?.[
|
|
6738
|
-
if (
|
|
6995
|
+
const current = input.current.rubricWeights?.[signal.dimension] ?? DEFAULT_RUBRIC_WEIGHT;
|
|
6996
|
+
if (signal.reworkCorrelation >= 0.6 && signal.noise <= 0.4) {
|
|
6739
6997
|
const next = round1(clamp(current + 0.2, 0.2, 3));
|
|
6740
6998
|
if (next === current)
|
|
6741
6999
|
continue;
|
|
6742
7000
|
out3.push({
|
|
6743
7001
|
kind: "rubric_weight",
|
|
6744
|
-
target: `rubric.${
|
|
7002
|
+
target: `rubric.${signal.dimension}.weight`,
|
|
6745
7003
|
action: "raise_weight",
|
|
6746
7004
|
from: current,
|
|
6747
7005
|
to: next,
|
|
6748
7006
|
rationale: "\u8BE5 rubric \u7EF4\u5EA6\u4E0E\u771F\u5B9E\u8FD4\u5DE5\u5F3A\u76F8\u5173\uFF0C\u6743\u91CD\u5C0F\u5E45\u4E0A\u8C03\u3002",
|
|
6749
7007
|
evidence: [
|
|
6750
|
-
`dimension=${
|
|
6751
|
-
`samples=${
|
|
6752
|
-
`rework_correlation=${fmtRate(
|
|
6753
|
-
`noise=${fmtRate(
|
|
7008
|
+
`dimension=${signal.dimension}`,
|
|
7009
|
+
`samples=${signal.samples}`,
|
|
7010
|
+
`rework_correlation=${fmtRate(signal.reworkCorrelation)}`,
|
|
7011
|
+
`noise=${fmtRate(signal.noise)}`
|
|
6754
7012
|
],
|
|
6755
|
-
rollback: reset(`rubric.${
|
|
7013
|
+
rollback: reset(`rubric.${signal.dimension}.weight`, DEFAULT_RUBRIC_WEIGHT)
|
|
6756
7014
|
});
|
|
6757
|
-
} else if (
|
|
7015
|
+
} else if (signal.noise >= 0.6 && signal.reworkCorrelation <= 0.3) {
|
|
6758
7016
|
const next = round1(clamp(current - 0.2, 0.2, 3));
|
|
6759
7017
|
if (next === current)
|
|
6760
7018
|
continue;
|
|
6761
7019
|
out3.push({
|
|
6762
7020
|
kind: "rubric_weight",
|
|
6763
|
-
target: `rubric.${
|
|
7021
|
+
target: `rubric.${signal.dimension}.weight`,
|
|
6764
7022
|
action: "lower_weight",
|
|
6765
7023
|
from: current,
|
|
6766
7024
|
to: next,
|
|
6767
7025
|
rationale: "\u8BE5 rubric \u7EF4\u5EA6\u566A\u58F0\u9AD8\u4E14\u4E0E\u771F\u5B9E\u8FD4\u5DE5\u5F31\u76F8\u5173\uFF0C\u6743\u91CD\u5C0F\u5E45\u4E0B\u8C03\u3002",
|
|
6768
7026
|
evidence: [
|
|
6769
|
-
`dimension=${
|
|
6770
|
-
`samples=${
|
|
6771
|
-
`rework_correlation=${fmtRate(
|
|
6772
|
-
`noise=${fmtRate(
|
|
7027
|
+
`dimension=${signal.dimension}`,
|
|
7028
|
+
`samples=${signal.samples}`,
|
|
7029
|
+
`rework_correlation=${fmtRate(signal.reworkCorrelation)}`,
|
|
7030
|
+
`noise=${fmtRate(signal.noise)}`
|
|
6773
7031
|
],
|
|
6774
|
-
rollback: reset(`rubric.${
|
|
7032
|
+
rollback: reset(`rubric.${signal.dimension}.weight`, DEFAULT_RUBRIC_WEIGHT)
|
|
6775
7033
|
});
|
|
6776
7034
|
}
|
|
6777
7035
|
}
|
|
@@ -8086,6 +8344,7 @@ var init_dist2 = __esm({
|
|
|
8086
8344
|
init_score();
|
|
8087
8345
|
init_bus();
|
|
8088
8346
|
init_infra_default3();
|
|
8347
|
+
init_activity_signal();
|
|
8089
8348
|
init_alert_loop();
|
|
8090
8349
|
init_ci_loop();
|
|
8091
8350
|
init_correction_actuator();
|
|
@@ -8095,7 +8354,6 @@ var init_dist2 = __esm({
|
|
|
8095
8354
|
init_quality_gate();
|
|
8096
8355
|
init_orchestrator();
|
|
8097
8356
|
init_recovery();
|
|
8098
|
-
init_loop_fmt();
|
|
8099
8357
|
init_sentinel();
|
|
8100
8358
|
init_signals();
|
|
8101
8359
|
init_transcript();
|
|
@@ -8117,7 +8375,7 @@ var init_dist2 = __esm({
|
|
|
8117
8375
|
});
|
|
8118
8376
|
|
|
8119
8377
|
// packages/infra/dist/config.js
|
|
8120
|
-
import { existsSync as existsSync12, mkdirSync as mkdirSync8, readFileSync as
|
|
8378
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync8, readFileSync as readFileSync14, writeFileSync as writeFileSync9 } from "node:fs";
|
|
8121
8379
|
import { homedir as homedir3 } from "node:os";
|
|
8122
8380
|
import { dirname as dirname7, join as join12 } from "node:path";
|
|
8123
8381
|
function expandLeadingTilde(val, home = homedir3()) {
|
|
@@ -8133,7 +8391,7 @@ function yamlReadNested(file, parent, child) {
|
|
|
8133
8391
|
const parentRe = new RegExp(`^${parent}:`);
|
|
8134
8392
|
const childRe = new RegExp(`^[ \\t]+${child}:`);
|
|
8135
8393
|
let found = false;
|
|
8136
|
-
const text =
|
|
8394
|
+
const text = readFileSync14(file, "utf8");
|
|
8137
8395
|
const lines2 = text.length === 0 ? [] : text.replace(/\n$/, "").split("\n");
|
|
8138
8396
|
for (const line of lines2) {
|
|
8139
8397
|
if (!found) {
|
|
@@ -8153,7 +8411,7 @@ function yamlReadFlat(file, key) {
|
|
|
8153
8411
|
if (!existsSync12(file))
|
|
8154
8412
|
return "";
|
|
8155
8413
|
const re = new RegExp(`^${escapeRegExp(key)}:`);
|
|
8156
|
-
for (const line of
|
|
8414
|
+
for (const line of readFileSync14(file, "utf8").split("\n")) {
|
|
8157
8415
|
if (re.test(line)) {
|
|
8158
8416
|
return line.replace(/^[^:]*:[ \t]*/, "").replace(/[ \t]*#.*$/, "").replace(/[ \t]*$/, "");
|
|
8159
8417
|
}
|
|
@@ -8308,7 +8566,7 @@ function applyConfigSet(text, key, value) {
|
|
|
8308
8566
|
}
|
|
8309
8567
|
function configSet(key, value, file) {
|
|
8310
8568
|
mkdirSync8(dirname7(file), { recursive: true });
|
|
8311
|
-
const text = existsSync12(file) ?
|
|
8569
|
+
const text = existsSync12(file) ? readFileSync14(file, "utf8") : "";
|
|
8312
8570
|
writeFileSync9(file, applyConfigSet(text, key, value));
|
|
8313
8571
|
}
|
|
8314
8572
|
var CONFIG_KEYS;
|
|
@@ -8825,7 +9083,7 @@ var init_github = __esm({
|
|
|
8825
9083
|
});
|
|
8826
9084
|
|
|
8827
9085
|
// packages/infra/dist/process.js
|
|
8828
|
-
import { existsSync as existsSync14, mkdirSync as mkdirSync10, readFileSync as
|
|
9086
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync10, readFileSync as readFileSync15, rmSync as rmSync4, statSync as statSync5, writeFileSync as writeFileSync10 } from "node:fs";
|
|
8829
9087
|
import { dirname as dirname9 } from "node:path";
|
|
8830
9088
|
function parseLock(raw) {
|
|
8831
9089
|
const firstLine = raw.split("\n", 1)[0] ?? "";
|
|
@@ -8853,7 +9111,7 @@ function acquireLock(lockPath2, pid = process.pid, opts = {}) {
|
|
|
8853
9111
|
const pidAlive = opts.pidAlive ?? systemPidAlive;
|
|
8854
9112
|
mkdirSync10(dirname9(lockPath2), { recursive: true });
|
|
8855
9113
|
if (existsSync14(lockPath2)) {
|
|
8856
|
-
const contents = parseLock(
|
|
9114
|
+
const contents = parseLock(readFileSync15(lockPath2, "utf8"));
|
|
8857
9115
|
if (isLockHeld(contents, now, staleSec, pidAlive)) {
|
|
8858
9116
|
return { acquired: false, heldByPid: contents.pid };
|
|
8859
9117
|
}
|
|
@@ -8873,7 +9131,7 @@ function writeHeartbeat(heartbeatPath, now = systemClock) {
|
|
|
8873
9131
|
function heartbeatAge(heartbeatPath, now = systemClock) {
|
|
8874
9132
|
let ts = 0;
|
|
8875
9133
|
if (existsSync14(heartbeatPath)) {
|
|
8876
|
-
const raw =
|
|
9134
|
+
const raw = readFileSync15(heartbeatPath, "utf8").trim();
|
|
8877
9135
|
ts = /^\d+$/.test(raw) ? Number(raw) : 0;
|
|
8878
9136
|
}
|
|
8879
9137
|
return now() - ts;
|
|
@@ -8902,10 +9160,10 @@ function installExitHooks(final, target = process) {
|
|
|
8902
9160
|
const onExit = () => {
|
|
8903
9161
|
runOnce();
|
|
8904
9162
|
};
|
|
8905
|
-
const onSignal = (
|
|
9163
|
+
const onSignal = (signal) => {
|
|
8906
9164
|
runOnce();
|
|
8907
|
-
target.removeListener(
|
|
8908
|
-
target.kill(target.pid,
|
|
9165
|
+
target.removeListener(signal, onSignal);
|
|
9166
|
+
target.kill(target.pid, signal);
|
|
8909
9167
|
};
|
|
8910
9168
|
target.on("exit", onExit);
|
|
8911
9169
|
target.on("SIGTERM", onSignal);
|
|
@@ -10048,10 +10306,12 @@ var init_showcase = __esm({
|
|
|
10048
10306
|
var showcase_exports = {};
|
|
10049
10307
|
__export(showcase_exports, {
|
|
10050
10308
|
SHOWCASE_USAGE: () => SHOWCASE_USAGE,
|
|
10309
|
+
probeMissingAgents: () => probeMissingAgents,
|
|
10310
|
+
resetSandbox: () => resetSandbox,
|
|
10051
10311
|
showcaseCommand: () => showcaseCommand
|
|
10052
10312
|
});
|
|
10053
10313
|
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
10054
|
-
import { cpSync, existsSync as existsSync73, mkdirSync as mkdirSync38, mkdtempSync as mkdtempSync5, readdirSync as readdirSync32, readFileSync as
|
|
10314
|
+
import { cpSync, existsSync as existsSync73, mkdirSync as mkdirSync38, mkdtempSync as mkdtempSync5, readdirSync as readdirSync32, readFileSync as readFileSync69, rmSync as rmSync15, statSync as statSync24, writeFileSync as writeFileSync40 } from "node:fs";
|
|
10055
10315
|
import { tmpdir as tmpdir7 } from "node:os";
|
|
10056
10316
|
import { dirname as dirname31, join as join72 } from "node:path";
|
|
10057
10317
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
@@ -10106,14 +10366,17 @@ function packageRoot() {
|
|
|
10106
10366
|
function rollBin2() {
|
|
10107
10367
|
return join72(packageRoot(), "packages", "cli", "bin", "roll.js");
|
|
10108
10368
|
}
|
|
10109
|
-
function runRoll(sandbox, rollHome4, args,
|
|
10369
|
+
function runRoll(sandbox, rollHome4, args, opts = {}) {
|
|
10110
10370
|
const env = {
|
|
10111
10371
|
...process.env,
|
|
10112
|
-
ROLL_HOME: rollHome4,
|
|
10113
10372
|
ROLL_LANG: process.env["ROLL_LANG"] ?? "en",
|
|
10114
10373
|
GIT_TERMINAL_PROMPT: "0",
|
|
10115
|
-
...extraEnv
|
|
10374
|
+
...opts.extraEnv
|
|
10116
10375
|
};
|
|
10376
|
+
if (opts.realHome === true) {
|
|
10377
|
+
} else {
|
|
10378
|
+
env.ROLL_HOME = rollHome4;
|
|
10379
|
+
}
|
|
10117
10380
|
const r = spawnSync8(process.execPath, [rollBin2(), ...args], {
|
|
10118
10381
|
cwd: sandbox,
|
|
10119
10382
|
env,
|
|
@@ -10176,9 +10439,13 @@ function findCardSpec(sandbox, card) {
|
|
|
10176
10439
|
function resetSandbox(sandbox, card) {
|
|
10177
10440
|
const notes = [];
|
|
10178
10441
|
let reset2 = false;
|
|
10442
|
+
let ok8 = false;
|
|
10179
10443
|
const backlogPath = join72(sandbox, ".roll", "backlog.md");
|
|
10180
10444
|
if (existsSync73(backlogPath)) {
|
|
10181
|
-
const before =
|
|
10445
|
+
const before = readFileSync69(backlogPath, "utf8");
|
|
10446
|
+
const cardRow = before.split("\n").find((line) => line.startsWith("|") && line.includes(card));
|
|
10447
|
+
const hadStatusToken = cardRow !== void 0 && /(✅ *Done|🚧 *WIP|🔄 *In Progress|⏳ *Hold|📋 *Todo|✔️ *Done)/.test(cardRow);
|
|
10448
|
+
const alreadyTodo = cardRow !== void 0 && /📋 *Todo/.test(cardRow);
|
|
10182
10449
|
const lines2 = before.split("\n").map((line) => {
|
|
10183
10450
|
if (!line.includes(card) || !line.startsWith("|"))
|
|
10184
10451
|
return line;
|
|
@@ -10188,9 +10455,16 @@ function resetSandbox(sandbox, card) {
|
|
|
10188
10455
|
if (after !== before) {
|
|
10189
10456
|
writeFileSync40(backlogPath, after, "utf8");
|
|
10190
10457
|
reset2 = true;
|
|
10458
|
+
ok8 = true;
|
|
10191
10459
|
notes.push(`backlog: ${card} \u2192 Todo`);
|
|
10460
|
+
} else if (alreadyTodo) {
|
|
10461
|
+
ok8 = true;
|
|
10462
|
+
notes.push(`backlog: ${card} already Todo (no-op)`);
|
|
10463
|
+
} else if (!hadStatusToken) {
|
|
10464
|
+
notes.push(`backlog: ${card} has no status token`);
|
|
10192
10465
|
} else {
|
|
10193
|
-
|
|
10466
|
+
ok8 = true;
|
|
10467
|
+
notes.push(`backlog: ${card} already Todo`);
|
|
10194
10468
|
}
|
|
10195
10469
|
} else {
|
|
10196
10470
|
notes.push("backlog: .roll/backlog.md absent");
|
|
@@ -10200,7 +10474,7 @@ function resetSandbox(sandbox, card) {
|
|
|
10200
10474
|
rmSync15(pulseCmd, { force: true });
|
|
10201
10475
|
notes.push("removed prior pulse.ts surface");
|
|
10202
10476
|
}
|
|
10203
|
-
return { reset: reset2, notes };
|
|
10477
|
+
return { ok: ok8, reset: reset2, notes };
|
|
10204
10478
|
}
|
|
10205
10479
|
function writeCasting(sandbox, casting) {
|
|
10206
10480
|
const agentsPath2 = join72(sandbox, ".roll", "agents.yaml");
|
|
@@ -10243,7 +10517,7 @@ function readBacklogStatus(sandbox, card) {
|
|
|
10243
10517
|
const backlogPath = join72(sandbox, ".roll", "backlog.md");
|
|
10244
10518
|
if (!existsSync73(backlogPath))
|
|
10245
10519
|
return void 0;
|
|
10246
|
-
for (const line of
|
|
10520
|
+
for (const line of readFileSync69(backlogPath, "utf8").split("\n")) {
|
|
10247
10521
|
if (line.startsWith("|") && line.includes(card)) {
|
|
10248
10522
|
const m7 = /(✅ *Done|🚧 *WIP|🔄 *In Progress|⏳ *Hold|📋 *Todo|✔️ *Done)/.exec(line);
|
|
10249
10523
|
if (m7 !== null && m7[1] !== void 0)
|
|
@@ -10257,7 +10531,7 @@ function readTruthLadder(sandbox, card) {
|
|
|
10257
10531
|
if (!existsSync73(truthPath))
|
|
10258
10532
|
return void 0;
|
|
10259
10533
|
try {
|
|
10260
|
-
const snap = JSON.parse(
|
|
10534
|
+
const snap = JSON.parse(readFileSync69(truthPath, "utf8"));
|
|
10261
10535
|
const row2 = (snap.stories ?? []).find((s) => s.id === card);
|
|
10262
10536
|
return row2?.ladder;
|
|
10263
10537
|
} catch {
|
|
@@ -10270,7 +10544,7 @@ function readTcrCommits(sandbox) {
|
|
|
10270
10544
|
return [];
|
|
10271
10545
|
const out3 = [];
|
|
10272
10546
|
try {
|
|
10273
|
-
const lines2 =
|
|
10547
|
+
const lines2 = readFileSync69(runsPath3, "utf8").trim().split("\n").filter(Boolean);
|
|
10274
10548
|
const last = lines2[lines2.length - 1];
|
|
10275
10549
|
if (last === void 0)
|
|
10276
10550
|
return [];
|
|
@@ -10315,7 +10589,7 @@ ${msg6}
|
|
|
10315
10589
|
const sourceProject = process.cwd();
|
|
10316
10590
|
const { sandbox, rollHome: rollHome4 } = makeSandbox(sourceProject);
|
|
10317
10591
|
const steps = [];
|
|
10318
|
-
const
|
|
10592
|
+
const emit4 = (id, ok8, detail) => {
|
|
10319
10593
|
steps.push({ id, ok: ok8, detail });
|
|
10320
10594
|
if (!json)
|
|
10321
10595
|
process.stdout.write(`${ok8 ? "\u2713" : "\u2717"} ${id.padEnd(18)} ${detail}
|
|
@@ -10324,28 +10598,28 @@ ${msg6}
|
|
|
10324
10598
|
try {
|
|
10325
10599
|
const spec = findCardSpec(sandbox, card);
|
|
10326
10600
|
if (spec === void 0) {
|
|
10327
|
-
|
|
10601
|
+
emit4("sandbox", false, `target card ${card} not found in the sandbox \u2014 nothing to deliver`);
|
|
10328
10602
|
throw new ShowcaseAbort(`card ${card} absent`);
|
|
10329
10603
|
}
|
|
10330
10604
|
const reset2 = resetSandbox(sandbox, card);
|
|
10331
|
-
|
|
10605
|
+
emit4("reset", reset2.ok, reset2.notes.join("; "));
|
|
10332
10606
|
writeCasting(sandbox, casting);
|
|
10333
|
-
|
|
10607
|
+
emit4("casting", true, `builder=${casting.builder} reviewer=${casting.reviewer} scorer=${casting.scorer} (heterogeneous)`);
|
|
10334
10608
|
const missing = probeMissingAgents(sandbox, rollHome4, casting);
|
|
10335
10609
|
if (missing.length > 0) {
|
|
10336
|
-
|
|
10610
|
+
emit4("agents", false, `unavailable real agent(s): ${missing.join(", ")} \u2014 cannot run the real loop`);
|
|
10337
10611
|
throw new ShowcaseAbort(`agents unavailable: ${missing.join(", ")}`);
|
|
10338
10612
|
}
|
|
10339
|
-
|
|
10613
|
+
emit4("agents", true, `all cast agents available: ${casting.builder}, ${casting.reviewer}, ${casting.scorer}`);
|
|
10340
10614
|
const go = runRoll(sandbox, rollHome4, ["loop", "go", "--cards", card, "--no-tmux", "--no-wait"]);
|
|
10341
|
-
|
|
10615
|
+
emit4("loop-go", go.code === 0, go.code === 0 ? "loop cycle completed" : `loop go exited ${go.code}: ${tail2(go.stderr || go.stdout)}`);
|
|
10342
10616
|
runRoll(sandbox, rollHome4, ["index", "--rebuild"]);
|
|
10343
10617
|
const attest = runRoll(sandbox, rollHome4, ["attest", card]);
|
|
10344
10618
|
const screenshots = await captureScreenshots(sandbox, card);
|
|
10345
10619
|
const cliShot = screenshots.find((s) => s.surface === "cli");
|
|
10346
10620
|
const webShot = screenshots.find((s) => s.surface === "web");
|
|
10347
|
-
|
|
10348
|
-
|
|
10621
|
+
emit4("capture-cli", cliShot?.present === true, cliShot?.present === true ? cliShot.path : `skip: ${cliShot?.skipped ?? "none"}`);
|
|
10622
|
+
emit4("capture-web", webShot?.present === true, webShot?.present === true ? webShot.path : `skip: ${webShot?.skipped ?? "none"}`);
|
|
10349
10623
|
const backlogStatus = readBacklogStatus(sandbox, card);
|
|
10350
10624
|
const truthLadder = readTruthLadder(sandbox, card);
|
|
10351
10625
|
const tcrCommits = readTcrCommits(sandbox);
|
|
@@ -10413,9 +10687,9 @@ ROLL_HOME: ${rollHome4}
|
|
|
10413
10687
|
}
|
|
10414
10688
|
}
|
|
10415
10689
|
}
|
|
10416
|
-
function probeMissingAgents(sandbox, rollHome4, casting) {
|
|
10690
|
+
function probeMissingAgents(sandbox, rollHome4, casting, runner = runRoll) {
|
|
10417
10691
|
const wanted = [.../* @__PURE__ */ new Set([casting.builder, casting.reviewer, casting.scorer])];
|
|
10418
|
-
const r =
|
|
10692
|
+
const r = runner(sandbox, rollHome4, ["agent", "list"], { realHome: true });
|
|
10419
10693
|
if (r.code !== 0 && r.stdout.trim() === "")
|
|
10420
10694
|
return wanted;
|
|
10421
10695
|
const listed = r.stdout.toLowerCase();
|
|
@@ -11437,12 +11711,12 @@ function agentCommand(args, deps = {}) {
|
|
|
11437
11711
|
init_dist2();
|
|
11438
11712
|
init_dist();
|
|
11439
11713
|
init_dist2();
|
|
11440
|
-
import { appendFileSync as appendFileSync3, existsSync as existsSync18, mkdirSync as mkdirSync13, readFileSync as
|
|
11714
|
+
import { appendFileSync as appendFileSync3, existsSync as existsSync18, mkdirSync as mkdirSync13, readFileSync as readFileSync17, writeFileSync as writeFileSync12 } from "node:fs";
|
|
11441
11715
|
import { dirname as dirname10, join as join16, relative as relative2 } from "node:path";
|
|
11442
11716
|
|
|
11443
11717
|
// packages/cli/dist/runner/pairing-gate.js
|
|
11444
11718
|
init_dist2();
|
|
11445
|
-
import { existsSync as existsSync10, mkdirSync as mkdirSync5, readFileSync as
|
|
11719
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync5, readFileSync as readFileSync11, writeFileSync as writeFileSync6 } from "node:fs";
|
|
11446
11720
|
import { join as join9 } from "node:path";
|
|
11447
11721
|
|
|
11448
11722
|
// packages/cli/dist/lib/self-score.js
|
|
@@ -12195,8 +12469,9 @@ function evaluateSelfScoreGate(projectPath3, storyId) {
|
|
|
12195
12469
|
}
|
|
12196
12470
|
|
|
12197
12471
|
// packages/cli/dist/runner/peer-gate.js
|
|
12472
|
+
init_dist2();
|
|
12198
12473
|
import { execFile } from "node:child_process";
|
|
12199
|
-
import { existsSync as existsSync9, readdirSync as readdirSync4 } from "node:fs";
|
|
12474
|
+
import { existsSync as existsSync9, readFileSync as readFileSync10, readdirSync as readdirSync4 } from "node:fs";
|
|
12200
12475
|
import { join as join8 } from "node:path";
|
|
12201
12476
|
import { promisify } from "node:util";
|
|
12202
12477
|
var execFileAsync = promisify(execFile);
|
|
@@ -12236,21 +12511,32 @@ function peerEvidencePresent(runtimeDir6, cycleId) {
|
|
|
12236
12511
|
return false;
|
|
12237
12512
|
}
|
|
12238
12513
|
}
|
|
12239
|
-
|
|
12514
|
+
function readPeerGateMode(repoCwd) {
|
|
12515
|
+
try {
|
|
12516
|
+
const p = join8(repoCwd, ".roll", "policy.yaml");
|
|
12517
|
+
if (!existsSync9(p))
|
|
12518
|
+
return "hard";
|
|
12519
|
+
return parsePolicy(readFileSync10(p, "utf8")).loopSafety.peerGate === "soft" ? "soft" : "hard";
|
|
12520
|
+
} catch {
|
|
12521
|
+
return "hard";
|
|
12522
|
+
}
|
|
12523
|
+
}
|
|
12524
|
+
async function runPeerGate(worktreeCwd, runtimeDir6, cycleId, mode, sinks) {
|
|
12240
12525
|
try {
|
|
12241
12526
|
const files = await cycleChangedFiles(worktreeCwd);
|
|
12242
12527
|
const cx = assessComplexity(files);
|
|
12243
12528
|
if (!cx.high)
|
|
12244
|
-
return { verdict: "not-required", reasons: [] };
|
|
12529
|
+
return { verdict: "not-required", mode, reasons: [], blocked: false };
|
|
12245
12530
|
if (peerEvidencePresent(runtimeDir6, cycleId)) {
|
|
12246
12531
|
sinks.event({ cycleId, verdict: "consulted", reasons: cx.reasons });
|
|
12247
|
-
return { verdict: "consulted", reasons: cx.reasons };
|
|
12532
|
+
return { verdict: "consulted", mode, reasons: cx.reasons, blocked: false };
|
|
12248
12533
|
}
|
|
12249
|
-
|
|
12534
|
+
const blocked = mode === "hard";
|
|
12535
|
+
sinks.alert(`peer gate (${mode}): high-complexity work without peer review (${cx.reasons.join("; ")}) \u2014 cycle ${cycleId}` + (blocked ? " \u2014 retrying the consult; story not marked Done unless peer evidence is produced" : ""));
|
|
12250
12536
|
sinks.event({ cycleId, verdict: "skipped", reasons: cx.reasons });
|
|
12251
|
-
return { verdict: "skipped", reasons: cx.reasons };
|
|
12537
|
+
return { verdict: "skipped", mode, reasons: cx.reasons, blocked };
|
|
12252
12538
|
} catch {
|
|
12253
|
-
return { verdict: "not-required", reasons: [] };
|
|
12539
|
+
return { verdict: "not-required", mode, reasons: [], blocked: false };
|
|
12254
12540
|
}
|
|
12255
12541
|
}
|
|
12256
12542
|
|
|
@@ -12260,7 +12546,7 @@ function enabledPairingStages(projectDir) {
|
|
|
12260
12546
|
const cfgPath = join9(projectDir, ".roll", "pairing.yaml");
|
|
12261
12547
|
if (!existsSync10(cfgPath))
|
|
12262
12548
|
return [];
|
|
12263
|
-
const cfg = parsePairingConfig(
|
|
12549
|
+
const cfg = parsePairingConfig(readFileSync11(cfgPath, "utf8"));
|
|
12264
12550
|
if (!cfg.enabled)
|
|
12265
12551
|
return [];
|
|
12266
12552
|
return cfg.stages.filter((s, i, arr2) => arr2.indexOf(s) === i && s !== "score");
|
|
@@ -12281,7 +12567,7 @@ async function runPairing(projectDir, worktreeCwd, runtimeDir6, cycleId, working
|
|
|
12281
12567
|
const cfgPath = join9(projectDir, ".roll", "pairing.yaml");
|
|
12282
12568
|
if (!existsSync10(cfgPath))
|
|
12283
12569
|
return { status: "off" };
|
|
12284
|
-
const cfg = parsePairingConfig(
|
|
12570
|
+
const cfg = parsePairingConfig(readFileSync11(cfgPath, "utf8"));
|
|
12285
12571
|
if (!cfg.enabled || !cfg.stages.includes(stage))
|
|
12286
12572
|
return { status: "off" };
|
|
12287
12573
|
const files = await deps.changedFiles(worktreeCwd);
|
|
@@ -12324,7 +12610,7 @@ async function runScorePairing(projectDir, runtimeDir6, cycleId, workingAgent, s
|
|
|
12324
12610
|
const cfgPath = join9(projectDir, ".roll", "pairing.yaml");
|
|
12325
12611
|
if (!existsSync10(cfgPath))
|
|
12326
12612
|
return { status: "off" };
|
|
12327
|
-
const cfg = parsePairingConfig(
|
|
12613
|
+
const cfg = parsePairingConfig(readFileSync11(cfgPath, "utf8"));
|
|
12328
12614
|
if (!cfg.enabled || !cfg.stages.includes("score"))
|
|
12329
12615
|
return { status: "off" };
|
|
12330
12616
|
const candidates = selectPairingCandidates({
|
|
@@ -12378,6 +12664,33 @@ function parsePairScoreOutput(stdout) {
|
|
|
12378
12664
|
return null;
|
|
12379
12665
|
return { score, verdict: vm[1].toLowerCase(), rationale: rm[1].trim() };
|
|
12380
12666
|
}
|
|
12667
|
+
async function retryPeerConsult(worktreeCwd, runtimeDir6, cycleId, deps) {
|
|
12668
|
+
try {
|
|
12669
|
+
const working = canonicalAgentName(deps.workingAgent);
|
|
12670
|
+
const distinct = deps.installed.map(canonicalAgentName).filter((a, i, arr2) => arr2.indexOf(a) === i);
|
|
12671
|
+
const heterogeneous = distinct.filter((a) => a !== working && isHeterogeneous(a, working))[0];
|
|
12672
|
+
const peer = heterogeneous ?? working;
|
|
12673
|
+
const sameTypeFallback = heterogeneous === void 0;
|
|
12674
|
+
if (peer === "") {
|
|
12675
|
+
deps.event({ type: "pair:none-available", cycleId, stage: "code", reason: "peer-gate retry: no peer could be consulted (no agent to spawn a separate-session review)", ts: deps.now() });
|
|
12676
|
+
return { status: "none-available" };
|
|
12677
|
+
}
|
|
12678
|
+
const diff = await deps.diff(worktreeCwd);
|
|
12679
|
+
if (diff.trim() === "")
|
|
12680
|
+
return { status: "empty" };
|
|
12681
|
+
deps.event({ type: "pair:selected", cycleId, workingAgent: working, peer, stage: "code", ts: deps.now() });
|
|
12682
|
+
const review = await deps.reviewPeer(peer, diff, deps.timeoutMs ?? DEFAULT_TIMEOUT_MS);
|
|
12683
|
+
if (review === null)
|
|
12684
|
+
return { status: "timeout", peer, sameTypeFallback };
|
|
12685
|
+
const path = evidencePath(runtimeDir6, cycleId, "code");
|
|
12686
|
+
mkdirSync5(join9(runtimeDir6, "peer"), { recursive: true });
|
|
12687
|
+
writeFileSync6(path, JSON.stringify({ cycleId, workingAgent: working, peer, stage: "code", sameTypeFallback, ...review }, null, 2), "utf8");
|
|
12688
|
+
deps.event({ type: "pair:verdict", cycleId, peer, verdict: review.verdict, findings: review.findings.length, cost: review.cost, stage: "code", ts: deps.now() });
|
|
12689
|
+
return { status: "reviewed", peer, sameTypeFallback };
|
|
12690
|
+
} catch {
|
|
12691
|
+
return { status: "error" };
|
|
12692
|
+
}
|
|
12693
|
+
}
|
|
12381
12694
|
function buildPairScorePrompt(summary) {
|
|
12382
12695
|
return `You are a heterogeneous PAIRING scorer. A different agent delivered the cycle below; grade the delivery quality honestly (root-cause depth, test coverage, scope discipline, evidence). Reply with exactly one "SCORE: <integer 1..10>" line, one "VERDICT: good|ok|regression" line, and one "RATIONALE: <one sentence>" line.
|
|
12383
12696
|
|
|
@@ -12388,11 +12701,11 @@ DELIVERY:
|
|
|
12388
12701
|
// packages/cli/dist/commands/peer.js
|
|
12389
12702
|
init_dist2();
|
|
12390
12703
|
import { spawn } from "node:child_process";
|
|
12391
|
-
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync7, readFileSync as
|
|
12704
|
+
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync7, readFileSync as readFileSync13, writeFileSync as writeFileSync8 } from "node:fs";
|
|
12392
12705
|
import { dirname as dirname6, join as join11 } from "node:path";
|
|
12393
12706
|
|
|
12394
12707
|
// packages/cli/dist/commands/setup-shared.js
|
|
12395
|
-
import { copyFileSync, existsSync as existsSync11, lstatSync, mkdirSync as mkdirSync6, readFileSync as
|
|
12708
|
+
import { copyFileSync, existsSync as existsSync11, lstatSync, mkdirSync as mkdirSync6, readFileSync as readFileSync12, readdirSync as readdirSync5, readlinkSync, realpathSync, rmSync as rmSync2, statSync as statSync4, symlinkSync, writeFileSync as writeFileSync7 } from "node:fs";
|
|
12396
12709
|
import { homedir as homedir2 } from "node:os";
|
|
12397
12710
|
import { basename as basename5, dirname as dirname5, join as join10 } from "node:path";
|
|
12398
12711
|
function rollHome() {
|
|
@@ -12421,7 +12734,7 @@ function getAiTools() {
|
|
|
12421
12734
|
if (!existsSync11(cfg))
|
|
12422
12735
|
return [];
|
|
12423
12736
|
const out3 = [];
|
|
12424
|
-
for (const line of
|
|
12737
|
+
for (const line of readFileSync12(cfg, "utf8").split("\n")) {
|
|
12425
12738
|
if (/^ai_[a-z]+:/.test(line)) {
|
|
12426
12739
|
let entry = line.replace(/^[^:]*:[ \t]*/, "");
|
|
12427
12740
|
entry = entry.replace(/^~/, homedir2());
|
|
@@ -12554,7 +12867,7 @@ function safeCopy(src, dst, force) {
|
|
|
12554
12867
|
}
|
|
12555
12868
|
function sameFile(a, b) {
|
|
12556
12869
|
try {
|
|
12557
|
-
return
|
|
12870
|
+
return readFileSync12(a).equals(readFileSync12(b));
|
|
12558
12871
|
} catch {
|
|
12559
12872
|
return false;
|
|
12560
12873
|
}
|
|
@@ -12688,7 +13001,7 @@ function ensureConfigEntries() {
|
|
|
12688
13001
|
const cfg = rollConfig();
|
|
12689
13002
|
if (!existsSync11(cfg))
|
|
12690
13003
|
return;
|
|
12691
|
-
const original =
|
|
13004
|
+
const original = readFileSync12(cfg, "utf8");
|
|
12692
13005
|
let lines2 = original.split("\n");
|
|
12693
13006
|
let added = 0;
|
|
12694
13007
|
for (const [key, val] of DEFAULT_AI_KEYS) {
|
|
@@ -12764,7 +13077,7 @@ function replacePrimaryAgent(newAgent) {
|
|
|
12764
13077
|
const cfg = rollConfig();
|
|
12765
13078
|
if (!existsSync11(cfg) || newAgent === "")
|
|
12766
13079
|
return;
|
|
12767
|
-
const lines2 =
|
|
13080
|
+
const lines2 = readFileSync12(cfg, "utf8").split("\n");
|
|
12768
13081
|
const out3 = lines2.map((l) => /^primary_agent:/.test(l) ? `primary_agent: ${newAgent}` : l);
|
|
12769
13082
|
writeFileSync7(cfg, out3.join("\n"));
|
|
12770
13083
|
}
|
|
@@ -12774,7 +13087,7 @@ function installLocal(force) {
|
|
|
12774
13087
|
pullConventions(force);
|
|
12775
13088
|
pullSkills();
|
|
12776
13089
|
const cfg = rollConfig();
|
|
12777
|
-
if (existsSync11(cfg) && !/^ai_[a-z]+:/m.test(
|
|
13090
|
+
if (existsSync11(cfg) && !/^ai_[a-z]+:/m.test(readFileSync12(cfg, "utf8"))) {
|
|
12778
13091
|
copyFileSync(cfg, `${cfg}.bak`);
|
|
12779
13092
|
rmSync2(cfg, { force: true });
|
|
12780
13093
|
}
|
|
@@ -12800,8 +13113,8 @@ function syncConventionForTool(src, mainDst, force) {
|
|
|
12800
13113
|
copyFileSync(src, wkFile);
|
|
12801
13114
|
if (!existsSync11(mainDst)) {
|
|
12802
13115
|
writeFileSync7(mainDst, "@roll.md\n");
|
|
12803
|
-
} else if (!
|
|
12804
|
-
writeFileSync7(mainDst,
|
|
13116
|
+
} else if (!readFileSync12(mainDst, "utf8").includes("@roll.md")) {
|
|
13117
|
+
writeFileSync7(mainDst, readFileSync12(mainDst, "utf8") + "\n@roll.md\n");
|
|
12805
13118
|
}
|
|
12806
13119
|
}
|
|
12807
13120
|
function syncConventions(force) {
|
|
@@ -12940,7 +13253,7 @@ function textAgentArgv(agent, prompt) {
|
|
|
12940
13253
|
case "gemini":
|
|
12941
13254
|
case "agy":
|
|
12942
13255
|
case "antigravity":
|
|
12943
|
-
return { bin: "agy", args: ["
|
|
13256
|
+
return { bin: "agy", args: ["--dangerously-skip-permissions", "-p", prompt] };
|
|
12944
13257
|
default:
|
|
12945
13258
|
return null;
|
|
12946
13259
|
}
|
|
@@ -12991,15 +13304,15 @@ function boundedAppend(current, chunk) {
|
|
|
12991
13304
|
const next = current + chunk.toString("utf8");
|
|
12992
13305
|
return next.length > 1e5 ? next.slice(-1e5) : next;
|
|
12993
13306
|
}
|
|
12994
|
-
function killChild(child,
|
|
13307
|
+
function killChild(child, signal) {
|
|
12995
13308
|
if (child.pid !== void 0) {
|
|
12996
13309
|
try {
|
|
12997
|
-
process.kill(-child.pid,
|
|
13310
|
+
process.kill(-child.pid, signal);
|
|
12998
13311
|
return true;
|
|
12999
13312
|
} catch {
|
|
13000
13313
|
}
|
|
13001
13314
|
}
|
|
13002
|
-
return child.kill(
|
|
13315
|
+
return child.kill(signal);
|
|
13003
13316
|
}
|
|
13004
13317
|
function releaseChild(child) {
|
|
13005
13318
|
child.stdout?.destroy();
|
|
@@ -13044,14 +13357,14 @@ function spawnPeerReviewAgent(input) {
|
|
|
13044
13357
|
stderr = boundedAppend(stderr, chunk);
|
|
13045
13358
|
});
|
|
13046
13359
|
child.on("error", (error) => finish({ status: "error", reason: error.message, stdout }));
|
|
13047
|
-
child.on("exit", (code,
|
|
13360
|
+
child.on("exit", (code, signal) => {
|
|
13048
13361
|
setImmediate(() => {
|
|
13049
13362
|
if (timedOut)
|
|
13050
13363
|
finish({ status: "timeout", stdout });
|
|
13051
13364
|
else if (code === 0)
|
|
13052
13365
|
finish({ status: "ok", stdout });
|
|
13053
13366
|
else
|
|
13054
|
-
finish({ status: "error", reason: `exit_${code ??
|
|
13367
|
+
finish({ status: "error", reason: `exit_${code ?? signal ?? "signal"}:${stderr.trim().slice(0, 200)}`, stdout });
|
|
13055
13368
|
});
|
|
13056
13369
|
});
|
|
13057
13370
|
child.on("close", (code) => {
|
|
@@ -13234,7 +13547,7 @@ function readPrompt(opts) {
|
|
|
13234
13547
|
if (opts.prompt !== void 0)
|
|
13235
13548
|
return opts.prompt;
|
|
13236
13549
|
if (opts.file !== void 0)
|
|
13237
|
-
return
|
|
13550
|
+
return readFileSync13(opts.file, "utf8");
|
|
13238
13551
|
throw new Error("roll peer: --prompt or --file is required");
|
|
13239
13552
|
}
|
|
13240
13553
|
async function peerCommand(args, deps = realDeps()) {
|
|
@@ -13284,7 +13597,7 @@ duration: ${facts.durationMs}ms
|
|
|
13284
13597
|
// packages/cli/dist/commands/dashboard.js
|
|
13285
13598
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
13286
13599
|
import { createHash as createHash3 } from "node:crypto";
|
|
13287
|
-
import { existsSync as existsSync17, readFileSync as
|
|
13600
|
+
import { existsSync as existsSync17, readFileSync as readFileSync16, readdirSync as readdirSync7, realpathSync as realpathSync2, statSync as statSync8 } from "node:fs";
|
|
13288
13601
|
import { homedir as homedir4, platform } from "node:os";
|
|
13289
13602
|
import { basename as basename6, join as join15 } from "node:path";
|
|
13290
13603
|
init_dist3();
|
|
@@ -13396,7 +13709,7 @@ function resolveProjectPath(slug) {
|
|
|
13396
13709
|
const plist = join15(homedir4(), "Library", "LaunchAgents", `com.roll.loop.${slug}.plist`);
|
|
13397
13710
|
if (existsSync17(plist)) {
|
|
13398
13711
|
try {
|
|
13399
|
-
const text =
|
|
13712
|
+
const text = readFileSync16(plist, "utf8");
|
|
13400
13713
|
const m7 = /<key>WorkingDirectory<\/key>\s*<string>([^<]+)<\/string>/.exec(text);
|
|
13401
13714
|
if (m7 && m7[1] !== void 0 && isDir(m7[1]))
|
|
13402
13715
|
return m7[1];
|
|
@@ -13421,7 +13734,7 @@ function resolveProjectPath(slug) {
|
|
|
13421
13734
|
const innerScript = join15(sharedRoot(), "loop", `run-${slug}-inner.sh`);
|
|
13422
13735
|
if (existsSync17(innerScript)) {
|
|
13423
13736
|
try {
|
|
13424
|
-
const text =
|
|
13737
|
+
const text = readFileSync16(innerScript, "utf8");
|
|
13425
13738
|
const m7 = /export ROLL_MAIN_PROJECT="([^"]+)"/.exec(text);
|
|
13426
13739
|
if (m7 && m7[1] !== void 0 && isDir(m7[1]))
|
|
13427
13740
|
return m7[1];
|
|
@@ -13505,7 +13818,7 @@ function loadEvents(slug, days) {
|
|
|
13505
13818
|
for (const p of existing) {
|
|
13506
13819
|
let content;
|
|
13507
13820
|
try {
|
|
13508
|
-
content =
|
|
13821
|
+
content = readFileSync16(p, "utf8");
|
|
13509
13822
|
} catch {
|
|
13510
13823
|
continue;
|
|
13511
13824
|
}
|
|
@@ -13543,7 +13856,7 @@ function loadCronLog(slug) {
|
|
|
13543
13856
|
const out3 = [];
|
|
13544
13857
|
let content;
|
|
13545
13858
|
try {
|
|
13546
|
-
content =
|
|
13859
|
+
content = readFileSync16(path, "utf8");
|
|
13547
13860
|
} catch {
|
|
13548
13861
|
return [];
|
|
13549
13862
|
}
|
|
@@ -13573,7 +13886,7 @@ function loadState(slug) {
|
|
|
13573
13886
|
const out3 = {};
|
|
13574
13887
|
let content;
|
|
13575
13888
|
try {
|
|
13576
|
-
content =
|
|
13889
|
+
content = readFileSync16(path, "utf8");
|
|
13577
13890
|
} catch {
|
|
13578
13891
|
return {};
|
|
13579
13892
|
}
|
|
@@ -13595,7 +13908,7 @@ function loadBacklog(projectRoot2) {
|
|
|
13595
13908
|
const pat = /^\|\s*(?:\[)?([A-Z]+-\d+)(?:\]\([^)]+\))?\s*\|\s*([^|]+?)\s*\|/;
|
|
13596
13909
|
let content;
|
|
13597
13910
|
try {
|
|
13598
|
-
content =
|
|
13911
|
+
content = readFileSync16(path, "utf8");
|
|
13599
13912
|
} catch {
|
|
13600
13913
|
return {};
|
|
13601
13914
|
}
|
|
@@ -13746,7 +14059,7 @@ function detectLiveCycle(rtDir, cycles, now, pidAlive = systemPidAlive) {
|
|
|
13746
14059
|
const nowSec2 = Math.floor(now.getTime() / 1e3);
|
|
13747
14060
|
let lockRaw;
|
|
13748
14061
|
try {
|
|
13749
|
-
lockRaw =
|
|
14062
|
+
lockRaw = readFileSync16(lockPath2, "utf8");
|
|
13750
14063
|
} catch {
|
|
13751
14064
|
return dead;
|
|
13752
14065
|
}
|
|
@@ -13779,7 +14092,7 @@ function loadRuns(slug) {
|
|
|
13779
14092
|
const out3 = {};
|
|
13780
14093
|
let content;
|
|
13781
14094
|
try {
|
|
13782
|
-
content =
|
|
14095
|
+
content = readFileSync16(path, "utf8");
|
|
13783
14096
|
} catch {
|
|
13784
14097
|
return {};
|
|
13785
14098
|
}
|
|
@@ -13997,7 +14310,7 @@ function loadClaudeSessionUsage(label4, slug) {
|
|
|
13997
14310
|
let durationMs = null;
|
|
13998
14311
|
let content;
|
|
13999
14312
|
try {
|
|
14000
|
-
content =
|
|
14313
|
+
content = readFileSync16(path, "utf8");
|
|
14001
14314
|
} catch {
|
|
14002
14315
|
return null;
|
|
14003
14316
|
}
|
|
@@ -14173,7 +14486,7 @@ function selfScoreSummaryLine(notesDir = ".roll/notes", windowN = 14, featuresDi
|
|
|
14173
14486
|
let verdict = null;
|
|
14174
14487
|
let content;
|
|
14175
14488
|
try {
|
|
14176
|
-
content =
|
|
14489
|
+
content = readFileSync16(f.path, "utf8");
|
|
14177
14490
|
} catch {
|
|
14178
14491
|
content = "";
|
|
14179
14492
|
}
|
|
@@ -14403,7 +14716,7 @@ function readDailyPlistSchedule(svc) {
|
|
|
14403
14716
|
return null;
|
|
14404
14717
|
let text;
|
|
14405
14718
|
try {
|
|
14406
|
-
text =
|
|
14719
|
+
text = readFileSync16(plist, "utf8");
|
|
14407
14720
|
} catch {
|
|
14408
14721
|
return null;
|
|
14409
14722
|
}
|
|
@@ -14456,7 +14769,7 @@ function tickAgeLine(loopType, now) {
|
|
|
14456
14769
|
return null;
|
|
14457
14770
|
let lastLine;
|
|
14458
14771
|
try {
|
|
14459
|
-
const lines2 =
|
|
14772
|
+
const lines2 = readFileSync16(tickFile, "utf8").trim().split("\n");
|
|
14460
14773
|
lastLine = lines2[lines2.length - 1] ?? "";
|
|
14461
14774
|
if (lastLine === "")
|
|
14462
14775
|
return null;
|
|
@@ -14488,7 +14801,7 @@ function readLoopPlistSchedule() {
|
|
|
14488
14801
|
return null;
|
|
14489
14802
|
let text;
|
|
14490
14803
|
try {
|
|
14491
|
-
text =
|
|
14804
|
+
text = readFileSync16(plist, "utf8");
|
|
14492
14805
|
} catch {
|
|
14493
14806
|
return null;
|
|
14494
14807
|
}
|
|
@@ -14511,7 +14824,7 @@ function lastLoopFireEpochSec() {
|
|
|
14511
14824
|
if (!existsSync17(cronLog))
|
|
14512
14825
|
return null;
|
|
14513
14826
|
try {
|
|
14514
|
-
const lines2 =
|
|
14827
|
+
const lines2 = readFileSync16(cronLog, "utf8").trim().split("\n").reverse();
|
|
14515
14828
|
for (const line of lines2) {
|
|
14516
14829
|
if (!line.includes("cycle start"))
|
|
14517
14830
|
continue;
|
|
@@ -15317,7 +15630,7 @@ function pairStatus(rest) {
|
|
|
15317
15630
|
const NC = noColor2 ? "" : "\x1B[0m";
|
|
15318
15631
|
let view;
|
|
15319
15632
|
try {
|
|
15320
|
-
view = pairingPoolView(agentsInstalled(realAgentEnv()), parsePairingConfig(
|
|
15633
|
+
view = pairingPoolView(agentsInstalled(realAgentEnv()), parsePairingConfig(readFileSync17(path, "utf8")));
|
|
15321
15634
|
} catch (e) {
|
|
15322
15635
|
process.stderr.write(`[roll] pairing.yaml invalid: ${e.message}
|
|
15323
15636
|
`);
|
|
@@ -15359,7 +15672,7 @@ function pairingActivitySummary() {
|
|
|
15359
15672
|
for (const p of pairingEventFiles()) {
|
|
15360
15673
|
let content;
|
|
15361
15674
|
try {
|
|
15362
|
-
content =
|
|
15675
|
+
content = readFileSync17(p, "utf8");
|
|
15363
15676
|
} catch {
|
|
15364
15677
|
continue;
|
|
15365
15678
|
}
|
|
@@ -15413,13 +15726,13 @@ function resolveSummary(storyId, summaryFlag, fileFlag) {
|
|
|
15413
15726
|
return summaryFlag.trim();
|
|
15414
15727
|
if (fileFlag !== void 0) {
|
|
15415
15728
|
try {
|
|
15416
|
-
return
|
|
15729
|
+
return readFileSync17(fileFlag, "utf8").trim() || null;
|
|
15417
15730
|
} catch {
|
|
15418
15731
|
return null;
|
|
15419
15732
|
}
|
|
15420
15733
|
}
|
|
15421
15734
|
try {
|
|
15422
|
-
const backlog =
|
|
15735
|
+
const backlog = readFileSync17(join16(process.cwd(), ".roll", "backlog.md"), "utf8");
|
|
15423
15736
|
const idRe = new RegExp(`${storyId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(?![A-Za-z0-9])`);
|
|
15424
15737
|
const row2 = backlog.split("\n").find((l) => idRe.test(l));
|
|
15425
15738
|
return row2 !== void 0 ? `Story ${storyId} \u2014 backlog row:
|
|
@@ -15510,7 +15823,7 @@ ${HELP}`);
|
|
|
15510
15823
|
// packages/cli/dist/commands/alert.js
|
|
15511
15824
|
init_dist2();
|
|
15512
15825
|
init_dist();
|
|
15513
|
-
import { appendFileSync as appendFileSync4, existsSync as existsSync19, mkdirSync as mkdirSync14, readFileSync as
|
|
15826
|
+
import { appendFileSync as appendFileSync4, existsSync as existsSync19, mkdirSync as mkdirSync14, readFileSync as readFileSync18, rmSync as rmSync6, statSync as statSync9 } from "node:fs";
|
|
15514
15827
|
import { homedir as homedir5 } from "node:os";
|
|
15515
15828
|
import { join as join17 } from "node:path";
|
|
15516
15829
|
function palette() {
|
|
@@ -15573,7 +15886,7 @@ function renderLog(n, p, lang9) {
|
|
|
15573
15886
|
let body = "";
|
|
15574
15887
|
try {
|
|
15575
15888
|
if (existsSync19(file) && statSync9(file).size > 0)
|
|
15576
|
-
body =
|
|
15889
|
+
body = readFileSync18(file, "utf8");
|
|
15577
15890
|
} catch {
|
|
15578
15891
|
body = "";
|
|
15579
15892
|
}
|
|
@@ -15604,7 +15917,7 @@ function alertCommand(args) {
|
|
|
15604
15917
|
const rest = args.slice(1);
|
|
15605
15918
|
const file = loopAlertPath();
|
|
15606
15919
|
const fileExists = existsSync19(file);
|
|
15607
|
-
const contents = fileExists ?
|
|
15920
|
+
const contents = fileExists ? readFileSync18(file, "utf8") : "";
|
|
15608
15921
|
const ts = nowStamp();
|
|
15609
15922
|
const action = alertConsumeAction(subcmd, fileExists, contents, ts, rest[0]);
|
|
15610
15923
|
switch (action.kind) {
|
|
@@ -15665,7 +15978,7 @@ function ackMessage(lang9, ts) {
|
|
|
15665
15978
|
init_dist2();
|
|
15666
15979
|
init_dist();
|
|
15667
15980
|
init_dist3();
|
|
15668
|
-
import { existsSync as existsSync36, mkdirSync as mkdirSync17, readFileSync as
|
|
15981
|
+
import { existsSync as existsSync36, mkdirSync as mkdirSync17, readFileSync as readFileSync34, readdirSync as readdirSync16, realpathSync as realpathSync5, rmSync as rmSync8, statSync as statSync14, symlinkSync as symlinkSync2, writeFileSync as writeFileSync16 } from "node:fs";
|
|
15669
15982
|
import { execFile as execFile8, execFileSync as execFileSync5 } from "node:child_process";
|
|
15670
15983
|
import { basename as basename8, join as join33, relative as relative4 } from "node:path";
|
|
15671
15984
|
import { promisify as promisify8 } from "node:util";
|
|
@@ -15675,7 +15988,7 @@ init_dist2();
|
|
|
15675
15988
|
init_dist();
|
|
15676
15989
|
init_dist2();
|
|
15677
15990
|
init_dist();
|
|
15678
|
-
import { existsSync as existsSync35, readFileSync as
|
|
15991
|
+
import { existsSync as existsSync35, readFileSync as readFileSync33, readdirSync as readdirSync15, writeFileSync as writeFileSync15 } from "node:fs";
|
|
15679
15992
|
import { join as join32 } from "node:path";
|
|
15680
15993
|
|
|
15681
15994
|
// packages/cli/dist/lib/dossier-index.js
|
|
@@ -16159,7 +16472,7 @@ function copyChip(cmd) {
|
|
|
16159
16472
|
}
|
|
16160
16473
|
function cycleRow2(cy) {
|
|
16161
16474
|
const color = VERDICT_COLORS[cy.verdict] ?? C.slate;
|
|
16162
|
-
const n = cy.cycleId
|
|
16475
|
+
const n = cycleHandle(cy.cycleId);
|
|
16163
16476
|
return `<details class="cy-row" data-ts="${cy.tsSec}" data-verdict="${cy.verdict}" data-open-key="cy:${esc2(cy.cycleId)}" style="border-top:1px solid ${C.hair};"><summary style="display:grid;grid-template-columns:14px 70px 1fr auto;align-items:center;gap:14px;padding:12px 18px;cursor:pointer;list-style:none;"><span title="${cy.verdict}" style="width:10px;height:10px;border-radius:50%;background:${color};flex:none;"></span><span style="${MONO}font-size:13px;font-weight:600;color:${C.ink};">${esc2(n)}</span><div style="min-width:0;display:flex;align-items:center;gap:10px;"><span style="${MONO}font-size:10px;letter-spacing:.05em;text-transform:uppercase;font-weight:600;padding:2px 8px;border-radius:999px;border:1px solid ${color}44;color:${color};flex:none;">${bi(cy.verdict, VERDICT_ZH[cy.verdict] ?? cy.verdict)}</span><span style="${MONO}font-size:12px;color:${C.blue};font-weight:600;flex:none;">${esc2(cy.storyId || "\u2014")}</span></div><div style="display:flex;align-items:center;gap:14px;${MONO}font-size:11.5px;color:${C.dim};flex:none;"><span style="color:#5b6478;">${esc2(cy.model)}</span><span title="tokens in/out">${esc2(cy.tokens)}</span><span style="color:#5b6478;">${esc2(cy.cost)}</span><span>${esc2(cy.duration)}</span><span class="bl-caret" style="color:${C.faint};transition:transform .18s;font-size:10px;">\u25B6</span></div></summary><div style="padding:6px 18px 18px 60px;background:#fbfcfe;border-top:1px solid #f1f4f8;"><div style="display:flex;flex-wrap:nowrap;overflow-x:auto;gap:0;margin:12px 0 4px;padding-bottom:4px;">` + cy.tape.map((s, i) => tapeSegment(s, i === cy.tape.length - 1)).join("") + `</div><div style="display:flex;flex-wrap:wrap;gap:8px;margin-top:14px;">` + cy.evidence.map((e) => `<a href="${esc2(e.href)}" style="${MONO}font-size:11px;padding:4px 10px;border-radius:6px;border:1px solid ${C.line};color:${C.blue};text-decoration:none;background:${C.card};">${esc2(e.label)}</a>`).join("") + // US-DOSSIER-018: the web teaches the CLI — this command really exists (US-CLI-013).
|
|
16164
16477
|
copyChip(`roll cycle ${cycleHandle(cy.cycleId)}`) + `</div></div></details>`;
|
|
16165
16478
|
}
|
|
@@ -16195,6 +16508,7 @@ function hooksPanel(input) {
|
|
|
16195
16508
|
}
|
|
16196
16509
|
function loopTab(input) {
|
|
16197
16510
|
const ranges = [
|
|
16511
|
+
["recent", "Recent", "\u8FD1\u671F"],
|
|
16198
16512
|
["1", "Today", "\u4ECA\u5929"],
|
|
16199
16513
|
["3", "3 days", "\u4E09\u5929"],
|
|
16200
16514
|
["7", "7 days", "\u4E03\u5929"],
|
|
@@ -16204,7 +16518,7 @@ function loopTab(input) {
|
|
|
16204
16518
|
// project-scoped commit-hooks panel + the Cycle ledger. The inline agents
|
|
16205
16519
|
// panel (now the machine Agents page) and the inline casting ladder (now its
|
|
16206
16520
|
// own Casting tab) are NOT rendered here.
|
|
16207
|
-
hooksPanel(input) + `<div style="display:flex;align-items:center;gap:12px;margin:24px 0 12px;flex-wrap:wrap;"><span style="${MONO}font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:${C.sub};font-weight:600;">${bi("Cycle ledger", "\u5468\u671F\u8D26\u672C")}</span><span style="${MONO}font-size:11.5px;color:${C.faint};">${bi("what it actually did while you were away", "\u4F60\u4E0D\u5728\u7684\u65F6\u5019\u5B83\u5230\u5E95\u5E72\u4E86\u4EC0\u4E48")}</span><span style="flex:1;height:1px;background:#dfe4ec;min-width:16px;"></span><div style="display:flex;border:1px solid #dfe4ec;border-radius:999px;overflow:hidden;background:${C.card};">` + ranges.map(([key, en, zh]) => `<button type="button" class="cy-range${key === "
|
|
16521
|
+
hooksPanel(input) + `<div style="display:flex;align-items:center;gap:12px;margin:24px 0 12px;flex-wrap:wrap;"><span style="${MONO}font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:${C.sub};font-weight:600;">${bi("Cycle ledger", "\u5468\u671F\u8D26\u672C")}</span><span style="${MONO}font-size:11.5px;color:${C.faint};">${bi("what it actually did while you were away", "\u4F60\u4E0D\u5728\u7684\u65F6\u5019\u5B83\u5230\u5E95\u5E72\u4E86\u4EC0\u4E48")}</span><span style="flex:1;height:1px;background:#dfe4ec;min-width:16px;"></span><div style="display:flex;border:1px solid #dfe4ec;border-radius:999px;overflow:hidden;background:${C.card};">` + ranges.map(([key, en, zh]) => `<button type="button" class="cy-range${key === "recent" ? " on" : ""}" data-range="${key}" style="appearance:none;border:0;background:transparent;${MONO}font-size:11px;padding:6px 13px;cursor:pointer;color:${C.sub};">${bi(en, zh)}</button>`).join("") + `</div><span style="${MONO}font-size:11.5px;color:${C.dim};white-space:nowrap;"><span id="cy-count">\u2014</span> ${bi("shown", "\u663E\u793A")} <span style="color:${C.faint};">\xB7</span> <b id="cy-failed" style="color:#d23b3b;font-weight:600;">\u2014</b> ${bi("failed (all)", "\u5931\u8D25\uFF08\u5168\u90E8\uFF09")}</span></div><section id="cy-ledger" style="border:1px solid ${C.line};border-radius:14px;background:${C.card};overflow:hidden;box-shadow:0 1px 2px rgba(17,26,69,.05);">` + (input.cycles.length > 0 ? input.cycles.map(cycleRow2).join("") : `<div style="padding:16px 18px;font-size:12.5px;color:${C.faint};font-style:italic;">${bi("no cycles recorded yet", "\u5C1A\u65E0\u5468\u671F\u8BB0\u5F55")}</div>`) + `</section>`;
|
|
16208
16522
|
}
|
|
16209
16523
|
var TYPE_COLORS = { US: C.blue, FIX: C.red, REFACTOR: C.purple, IDEA: C.amber };
|
|
16210
16524
|
function typeBadge(type) {
|
|
@@ -16496,26 +16810,38 @@ var CONSOLE_SCRIPT = `<script>
|
|
|
16496
16810
|
chips[c].classList.toggle("on", !!active[chips[c].getAttribute("data-filter")]);
|
|
16497
16811
|
}
|
|
16498
16812
|
}
|
|
16499
|
-
// US-DOSSIER-013: cycle ledger range filter
|
|
16813
|
+
// US-DOSSIER-013 / FIX-297: cycle ledger range filter. Rows render newest-first.
|
|
16814
|
+
// The default "recent" window count-caps the view to the newest RECENT_CAP cycles
|
|
16815
|
+
// (the loop runs hundreds a week, so showing all history overwhelms the page).
|
|
16816
|
+
// Two invariants hold for EVERY range, including "recent":
|
|
16817
|
+
// 1. A failed/reverted/blocked cycle is NEVER hidden by the window \u2014 failures
|
|
16818
|
+
// are first-class, always in view however narrow the window.
|
|
16819
|
+
// 2. The "failed" tally counts the FULL ledger, not just what's visible, so it
|
|
16820
|
+
// stays accurate no matter which range is active.
|
|
16821
|
+
var RECENT_CAP = 50;
|
|
16500
16822
|
function applyRange(range) {
|
|
16501
16823
|
var rows = document.querySelectorAll(".cy-row");
|
|
16502
16824
|
var nowSec = Math.floor(Date.now() / 1000);
|
|
16503
|
-
var horizon = range === "all" ? Infinity : Number(range) * 86400;
|
|
16504
|
-
var
|
|
16825
|
+
var horizon = range === "all" || range === "recent" ? Infinity : Number(range) * 86400;
|
|
16826
|
+
var shown = 0, failedAll = 0, kept = 0;
|
|
16505
16827
|
for (var i = 0; i < rows.length; i++) {
|
|
16828
|
+
var v = rows[i].getAttribute("data-verdict");
|
|
16829
|
+
var isFail = v === "failed" || v === "reverted" || v === "blocked";
|
|
16830
|
+
if (isFail) failedAll++; // full-ledger tally, independent of the window
|
|
16506
16831
|
var ts = Number(rows[i].getAttribute("data-ts")) || 0;
|
|
16507
|
-
var
|
|
16832
|
+
var inWindow = range === "all" ? true
|
|
16833
|
+
: range === "recent" ? kept < RECENT_CAP
|
|
16834
|
+
: nowSec - ts <= horizon;
|
|
16835
|
+
// Failures are always shown; otherwise honor the window.
|
|
16836
|
+
var show = isFail || inWindow;
|
|
16508
16837
|
rows[i].style.display = show ? "" : "none";
|
|
16509
|
-
if (show)
|
|
16510
|
-
|
|
16511
|
-
var v = rows[i].getAttribute("data-verdict");
|
|
16512
|
-
if (v === "failed" || v === "reverted" || v === "blocked") failed++;
|
|
16513
|
-
}
|
|
16838
|
+
if (show) shown++;
|
|
16839
|
+
if (inWindow) kept++; // the cap counts non-fail slots; failures are bonus
|
|
16514
16840
|
}
|
|
16515
16841
|
var c = document.getElementById("cy-count");
|
|
16516
16842
|
var f = document.getElementById("cy-failed");
|
|
16517
|
-
if (c) c.textContent = String(
|
|
16518
|
-
if (f) f.textContent = String(
|
|
16843
|
+
if (c) c.textContent = String(shown);
|
|
16844
|
+
if (f) f.textContent = String(failedAll);
|
|
16519
16845
|
var btns = document.querySelectorAll(".cy-range");
|
|
16520
16846
|
for (var b = 0; b < btns.length; b++) btns[b].classList.toggle("on", btns[b].getAttribute("data-range") === range);
|
|
16521
16847
|
}
|
|
@@ -16617,7 +16943,7 @@ var CONSOLE_SCRIPT = `<script>
|
|
|
16617
16943
|
for (var rb = 0; rb < rbs.length; rb++) {
|
|
16618
16944
|
rbs[rb].addEventListener("click", function () { applyRange(this.getAttribute("data-range")); });
|
|
16619
16945
|
}
|
|
16620
|
-
applyRange("
|
|
16946
|
+
applyRange("recent");
|
|
16621
16947
|
applyFreshness();
|
|
16622
16948
|
tickCountdown();
|
|
16623
16949
|
setInterval(tickCountdown, 30000);
|
|
@@ -16794,7 +17120,7 @@ ${CONSOLE_SCRIPT}
|
|
|
16794
17120
|
}
|
|
16795
17121
|
|
|
16796
17122
|
// packages/cli/dist/lib/page-charter.js
|
|
16797
|
-
import { existsSync as existsSync20, readFileSync as
|
|
17123
|
+
import { existsSync as existsSync20, readFileSync as readFileSync19, readdirSync as readdirSync8, statSync as statSync10 } from "node:fs";
|
|
16798
17124
|
import { join as join18 } from "node:path";
|
|
16799
17125
|
function docTitle(src, path) {
|
|
16800
17126
|
for (const raw of src.split("\n")) {
|
|
@@ -16863,7 +17189,7 @@ function defaultCharterDeps(cwd, render2) {
|
|
|
16863
17189
|
if (!existsSync20(abs))
|
|
16864
17190
|
return void 0;
|
|
16865
17191
|
try {
|
|
16866
|
-
return
|
|
17192
|
+
return readFileSync19(abs, "utf8");
|
|
16867
17193
|
} catch {
|
|
16868
17194
|
return void 0;
|
|
16869
17195
|
}
|
|
@@ -17049,7 +17375,7 @@ function renderAboutPage(input) {
|
|
|
17049
17375
|
// packages/cli/dist/lib/page-conventions.js
|
|
17050
17376
|
init_dist3();
|
|
17051
17377
|
init_dist2();
|
|
17052
|
-
import { existsSync as existsSync22, readFileSync as
|
|
17378
|
+
import { existsSync as existsSync22, readFileSync as readFileSync20 } from "node:fs";
|
|
17053
17379
|
import { join as join20 } from "node:path";
|
|
17054
17380
|
var SYNC_KEYS = [
|
|
17055
17381
|
{ key: "sync_claude", agent: "claude" },
|
|
@@ -17087,7 +17413,7 @@ function defaultConventionsDeps(cwd, agents, render2) {
|
|
|
17087
17413
|
if (!existsSync22(abs))
|
|
17088
17414
|
return void 0;
|
|
17089
17415
|
try {
|
|
17090
|
-
return
|
|
17416
|
+
return readFileSync20(abs, "utf8");
|
|
17091
17417
|
} catch {
|
|
17092
17418
|
return void 0;
|
|
17093
17419
|
}
|
|
@@ -17132,7 +17458,7 @@ function renderConventionsPage(input) {
|
|
|
17132
17458
|
}
|
|
17133
17459
|
|
|
17134
17460
|
// packages/cli/dist/lib/projects-registry.js
|
|
17135
|
-
import { existsSync as existsSync23, mkdirSync as mkdirSync15, readFileSync as
|
|
17461
|
+
import { existsSync as existsSync23, mkdirSync as mkdirSync15, readFileSync as readFileSync21, renameSync as renameSync4, realpathSync as realpathSync3, writeFileSync as writeFileSync13 } from "node:fs";
|
|
17136
17462
|
import { homedir as homedir6, tmpdir } from "node:os";
|
|
17137
17463
|
import { dirname as dirname11, join as join21, sep } from "node:path";
|
|
17138
17464
|
function registryHome(home) {
|
|
@@ -17171,7 +17497,7 @@ function parseProjectsRegistry(text) {
|
|
|
17171
17497
|
function collectProjectsRegistry(home) {
|
|
17172
17498
|
let text;
|
|
17173
17499
|
try {
|
|
17174
|
-
text =
|
|
17500
|
+
text = readFileSync21(projectsRegistryPath(home), "utf8");
|
|
17175
17501
|
} catch {
|
|
17176
17502
|
return [];
|
|
17177
17503
|
}
|
|
@@ -17222,7 +17548,7 @@ function writeProjectRow(entry, home) {
|
|
|
17222
17548
|
|
|
17223
17549
|
// packages/cli/dist/lib/cycle-ledger.js
|
|
17224
17550
|
init_dist();
|
|
17225
|
-
import { existsSync as existsSync24, readFileSync as
|
|
17551
|
+
import { existsSync as existsSync24, readFileSync as readFileSync22 } from "node:fs";
|
|
17226
17552
|
import { join as join22 } from "node:path";
|
|
17227
17553
|
function ledgerVerdict(status2, outcome) {
|
|
17228
17554
|
if (status2 === "reverted")
|
|
@@ -17241,6 +17567,20 @@ function ledgerVerdict(status2, outcome) {
|
|
|
17241
17567
|
function ledgerFailedCount(rows) {
|
|
17242
17568
|
return rows.filter((r) => r.verdict === "failed" || r.verdict === "reverted" || r.verdict === "blocked").length;
|
|
17243
17569
|
}
|
|
17570
|
+
function isIdleHeartbeat(row2, verdict) {
|
|
17571
|
+
if (verdict !== "idle")
|
|
17572
|
+
return false;
|
|
17573
|
+
const storyId = typeof row2["story_id"] === "string" ? row2["story_id"] : "";
|
|
17574
|
+
if (storyId !== "")
|
|
17575
|
+
return false;
|
|
17576
|
+
const tcr = typeof row2["tcr_count"] === "number" ? row2["tcr_count"] : 0;
|
|
17577
|
+
if (tcr > 0)
|
|
17578
|
+
return false;
|
|
17579
|
+
const built = row2["built"];
|
|
17580
|
+
if (Array.isArray(built) && built.length > 0)
|
|
17581
|
+
return false;
|
|
17582
|
+
return true;
|
|
17583
|
+
}
|
|
17244
17584
|
function fmtTokens2(tin, tout, usageUnknown) {
|
|
17245
17585
|
if (usageUnknown)
|
|
17246
17586
|
return "?";
|
|
@@ -17267,7 +17607,7 @@ function readEventFacts(projectPath3) {
|
|
|
17267
17607
|
return { byCycle, prMergedBy, prOpenBy };
|
|
17268
17608
|
let content = "";
|
|
17269
17609
|
try {
|
|
17270
|
-
content =
|
|
17610
|
+
content = readFileSync22(path, "utf8");
|
|
17271
17611
|
} catch {
|
|
17272
17612
|
return { byCycle, prMergedBy, prOpenBy };
|
|
17273
17613
|
}
|
|
@@ -17322,7 +17662,7 @@ function collectCycleLedger(projectPath3) {
|
|
|
17322
17662
|
return [];
|
|
17323
17663
|
let content = "";
|
|
17324
17664
|
try {
|
|
17325
|
-
content =
|
|
17665
|
+
content = readFileSync22(runsPath3, "utf8");
|
|
17326
17666
|
} catch {
|
|
17327
17667
|
return [];
|
|
17328
17668
|
}
|
|
@@ -17343,6 +17683,8 @@ function collectCycleLedger(projectPath3) {
|
|
|
17343
17683
|
const status2 = String(row2["status"] ?? "");
|
|
17344
17684
|
const outcome = String(row2["outcome"] ?? "");
|
|
17345
17685
|
const verdict = ledgerVerdict(status2, outcome);
|
|
17686
|
+
if (isIdleHeartbeat(row2, verdict))
|
|
17687
|
+
continue;
|
|
17346
17688
|
const storyId = typeof row2["story_id"] === "string" ? row2["story_id"] : "";
|
|
17347
17689
|
const rawTs = row2["ts"];
|
|
17348
17690
|
const ts = typeof rawTs === "string" ? Date.parse(rawTs) : typeof rawTs === "number" ? rawTs > 1e10 ? rawTs : rawTs * 1e3 : Number.NaN;
|
|
@@ -17378,14 +17720,14 @@ function collectCycleLedger(projectPath3) {
|
|
|
17378
17720
|
|
|
17379
17721
|
// packages/cli/dist/lib/agent-panel.js
|
|
17380
17722
|
init_dist2();
|
|
17381
|
-
import { existsSync as existsSync26, readFileSync as
|
|
17723
|
+
import { existsSync as existsSync26, readFileSync as readFileSync24 } from "node:fs";
|
|
17382
17724
|
import { join as join24 } from "node:path";
|
|
17383
17725
|
|
|
17384
17726
|
// packages/cli/dist/commands/status.js
|
|
17385
17727
|
init_dist();
|
|
17386
17728
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
17387
17729
|
import { createHash as createHash4 } from "node:crypto";
|
|
17388
|
-
import { existsSync as existsSync25, lstatSync as lstatSync2, readdirSync as readdirSync9, readFileSync as
|
|
17730
|
+
import { existsSync as existsSync25, lstatSync as lstatSync2, readdirSync as readdirSync9, readFileSync as readFileSync23, realpathSync as realpathSync4, statSync as statSync11 } from "node:fs";
|
|
17389
17731
|
import { homedir as homedir7 } from "node:os";
|
|
17390
17732
|
import { basename as basename7, dirname as dirname12, join as join23 } from "node:path";
|
|
17391
17733
|
function rollHome2() {
|
|
@@ -17419,7 +17761,7 @@ function parseAiEntries() {
|
|
|
17419
17761
|
if (!existsSync25(cfg))
|
|
17420
17762
|
return [];
|
|
17421
17763
|
const entries = [];
|
|
17422
|
-
for (const line of
|
|
17764
|
+
for (const line of readFileSync23(cfg, "utf8").split("\n")) {
|
|
17423
17765
|
const m7 = /^ai_[a-z]+:\s*(.+)/.exec(line);
|
|
17424
17766
|
if (m7 === null)
|
|
17425
17767
|
continue;
|
|
@@ -17447,13 +17789,13 @@ function aiSyncStatus(e) {
|
|
|
17447
17789
|
if (!existsSync25(rollMd))
|
|
17448
17790
|
return "out-of-sync";
|
|
17449
17791
|
try {
|
|
17450
|
-
if (existsSync25(src) && !
|
|
17792
|
+
if (existsSync25(src) && !readFileSync23(rollMd).equals(readFileSync23(src)))
|
|
17451
17793
|
return "out-of-sync";
|
|
17452
17794
|
} catch {
|
|
17453
17795
|
return "out-of-sync";
|
|
17454
17796
|
}
|
|
17455
17797
|
try {
|
|
17456
|
-
if (!
|
|
17798
|
+
if (!readFileSync23(cfgFile, "utf8").includes("@roll.md"))
|
|
17457
17799
|
return "out-of-sync";
|
|
17458
17800
|
} catch {
|
|
17459
17801
|
return "out-of-sync";
|
|
@@ -17862,7 +18204,7 @@ function spend72h(projectPath3, nowSec2) {
|
|
|
17862
18204
|
return out3;
|
|
17863
18205
|
let content = "";
|
|
17864
18206
|
try {
|
|
17865
|
-
content =
|
|
18207
|
+
content = readFileSync24(path, "utf8");
|
|
17866
18208
|
} catch {
|
|
17867
18209
|
return out3;
|
|
17868
18210
|
}
|
|
@@ -17931,7 +18273,7 @@ function collectAgentPanel(projectPath3, deps = defaultAgentPanelDeps()) {
|
|
|
17931
18273
|
// packages/cli/dist/lib/release-panel.js
|
|
17932
18274
|
init_dist2();
|
|
17933
18275
|
init_dist();
|
|
17934
|
-
import { existsSync as existsSync27, readFileSync as
|
|
18276
|
+
import { existsSync as existsSync27, readFileSync as readFileSync25, readdirSync as readdirSync10 } from "node:fs";
|
|
17935
18277
|
import { join as join25 } from "node:path";
|
|
17936
18278
|
function collectReleasePanel(projectPath3) {
|
|
17937
18279
|
const dimsEmpty = CONSISTENCY_DIMENSIONS.map((key) => ({
|
|
@@ -17943,7 +18285,7 @@ function collectReleasePanel(projectPath3) {
|
|
|
17943
18285
|
try {
|
|
17944
18286
|
const latest = readdirSync10(dir).filter((f) => f.endsWith(".json")).sort().at(-1);
|
|
17945
18287
|
if (latest !== void 0) {
|
|
17946
|
-
const obj = JSON.parse(
|
|
18288
|
+
const obj = JSON.parse(readFileSync25(join25(dir, latest), "utf8"));
|
|
17947
18289
|
const findings = Array.isArray(obj.findings) ? obj.findings : [];
|
|
17948
18290
|
const tallies = tallyByDimension(findings);
|
|
17949
18291
|
out3.dims = CONSISTENCY_DIMENSIONS.map((key) => ({ key, tally: tallies[key] }));
|
|
@@ -17962,7 +18304,7 @@ function collectReleasePanel(projectPath3) {
|
|
|
17962
18304
|
const path = join25(projectPath3, ".roll", "loop", "events.ndjson");
|
|
17963
18305
|
if (existsSync27(path)) {
|
|
17964
18306
|
const tags = [];
|
|
17965
|
-
for (const line of
|
|
18307
|
+
for (const line of readFileSync25(path, "utf8").split("\n")) {
|
|
17966
18308
|
const e = parseEventLine(line);
|
|
17967
18309
|
if (e !== null && e.type === "release:gate" && typeof e.tag === "string" && e.tag !== "" && tags.at(-1) !== e.tag) {
|
|
17968
18310
|
tags.push(e.tag);
|
|
@@ -17978,7 +18320,7 @@ function collectReleasePanel(projectPath3) {
|
|
|
17978
18320
|
|
|
17979
18321
|
// packages/cli/dist/lib/release-scope.js
|
|
17980
18322
|
init_dist();
|
|
17981
|
-
import { existsSync as existsSync28, readFileSync as
|
|
18323
|
+
import { existsSync as existsSync28, readFileSync as readFileSync26 } from "node:fs";
|
|
17982
18324
|
import { join as join26 } from "node:path";
|
|
17983
18325
|
function groupByEpic(items) {
|
|
17984
18326
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -17995,7 +18337,7 @@ function prFromEvents(projectPath3) {
|
|
|
17995
18337
|
if (!existsSync28(path))
|
|
17996
18338
|
return out3;
|
|
17997
18339
|
try {
|
|
17998
|
-
for (const line of
|
|
18340
|
+
for (const line of readFileSync26(path, "utf8").split("\n")) {
|
|
17999
18341
|
const e = parseEventLine(line);
|
|
18000
18342
|
if (e !== null && e.type === "pr:merge")
|
|
18001
18343
|
out3.set(e.storyId, e.prNumber);
|
|
@@ -18032,7 +18374,7 @@ function collectHistory(projectPath3) {
|
|
|
18032
18374
|
return [];
|
|
18033
18375
|
let text = "";
|
|
18034
18376
|
try {
|
|
18035
|
-
text =
|
|
18377
|
+
text = readFileSync26(path, "utf8");
|
|
18036
18378
|
} catch {
|
|
18037
18379
|
return [];
|
|
18038
18380
|
}
|
|
@@ -18040,7 +18382,7 @@ function collectHistory(projectPath3) {
|
|
|
18040
18382
|
try {
|
|
18041
18383
|
const ev = join26(projectPath3, ".roll", "loop", "events.ndjson");
|
|
18042
18384
|
if (existsSync28(ev)) {
|
|
18043
|
-
for (const line of
|
|
18385
|
+
for (const line of readFileSync26(ev, "utf8").split("\n")) {
|
|
18044
18386
|
const e = parseEventLine(line);
|
|
18045
18387
|
if (e !== null && e.type === "release:gate" && Array.isArray(e.waivedRules) && e.waivedRules.length > 0) {
|
|
18046
18388
|
waivedTags.add(e.tag);
|
|
@@ -18073,11 +18415,11 @@ function collectHistory(projectPath3) {
|
|
|
18073
18415
|
}
|
|
18074
18416
|
|
|
18075
18417
|
// packages/cli/dist/lib/skills-panel.js
|
|
18076
|
-
import { existsSync as existsSync30, readFileSync as
|
|
18418
|
+
import { existsSync as existsSync30, readFileSync as readFileSync28, readdirSync as readdirSync12, statSync as statSync12 } from "node:fs";
|
|
18077
18419
|
import { join as join28 } from "node:path";
|
|
18078
18420
|
|
|
18079
18421
|
// packages/cli/dist/lib/skills-audit.js
|
|
18080
|
-
import { existsSync as existsSync29, readFileSync as
|
|
18422
|
+
import { existsSync as existsSync29, readFileSync as readFileSync27, readdirSync as readdirSync11 } from "node:fs";
|
|
18081
18423
|
import { join as join27, relative as relative3, sep as sep2 } from "node:path";
|
|
18082
18424
|
function stripYamlQuotes(value) {
|
|
18083
18425
|
const trimmed = value.trim();
|
|
@@ -18159,7 +18501,7 @@ function collectReferencedSpokes(body) {
|
|
|
18159
18501
|
return [...refs].sort();
|
|
18160
18502
|
}
|
|
18161
18503
|
function parseSkillFile(file) {
|
|
18162
|
-
const text =
|
|
18504
|
+
const text = readFileSync27(file, "utf8");
|
|
18163
18505
|
const { fields, body, ok: ok8 } = parseFrontmatter(text);
|
|
18164
18506
|
const skillDir = join27(file, "..");
|
|
18165
18507
|
const description = fields["description"] ?? "";
|
|
@@ -18192,7 +18534,7 @@ function loadRouteCases(routeFile) {
|
|
|
18192
18534
|
if (!existsSync29(routeFile))
|
|
18193
18535
|
return { skills: {} };
|
|
18194
18536
|
try {
|
|
18195
|
-
return JSON.parse(
|
|
18537
|
+
return JSON.parse(readFileSync27(routeFile, "utf8"));
|
|
18196
18538
|
} catch {
|
|
18197
18539
|
return { skills: {} };
|
|
18198
18540
|
}
|
|
@@ -18296,7 +18638,7 @@ function skillGroupOf(name) {
|
|
|
18296
18638
|
}
|
|
18297
18639
|
function lineCount(path) {
|
|
18298
18640
|
try {
|
|
18299
|
-
return
|
|
18641
|
+
return readFileSync28(path, "utf8").split("\n").length;
|
|
18300
18642
|
} catch {
|
|
18301
18643
|
return 0;
|
|
18302
18644
|
}
|
|
@@ -18360,7 +18702,7 @@ function collectSkillsPanel(projectPath3, deps = defaultSkillsPanelDeps(projectP
|
|
|
18360
18702
|
usage: usage2[name] ?? 0,
|
|
18361
18703
|
files: skillFiles(dir),
|
|
18362
18704
|
dirPath: dir,
|
|
18363
|
-
hubText: existsSync30(hubPath) ?
|
|
18705
|
+
hubText: existsSync30(hubPath) ? readFileSync28(hubPath, "utf8") : ""
|
|
18364
18706
|
};
|
|
18365
18707
|
});
|
|
18366
18708
|
const hubLines = rows.reduce((acc, r) => acc + r.hubLines, 0);
|
|
@@ -18533,7 +18875,7 @@ function renderSkillsPage(input) {
|
|
|
18533
18875
|
}
|
|
18534
18876
|
|
|
18535
18877
|
// packages/cli/dist/lib/loop-heartbeat.js
|
|
18536
|
-
import { existsSync as existsSync31, readFileSync as
|
|
18878
|
+
import { existsSync as existsSync31, readFileSync as readFileSync29 } from "node:fs";
|
|
18537
18879
|
import { join as join29 } from "node:path";
|
|
18538
18880
|
var LANES = ["loop", "dream"];
|
|
18539
18881
|
function defaultHeartbeatDeps(projectPath3, slug, launchAgentsDir3) {
|
|
@@ -18541,14 +18883,14 @@ function defaultHeartbeatDeps(projectPath3, slug, launchAgentsDir3) {
|
|
|
18541
18883
|
plistText: (svc) => {
|
|
18542
18884
|
const p = join29(launchAgentsDir3, `com.roll.${svc}.${slug}.plist`);
|
|
18543
18885
|
try {
|
|
18544
|
-
return existsSync31(p) ?
|
|
18886
|
+
return existsSync31(p) ? readFileSync29(p, "utf8") : null;
|
|
18545
18887
|
} catch {
|
|
18546
18888
|
return null;
|
|
18547
18889
|
}
|
|
18548
18890
|
},
|
|
18549
18891
|
lastRunAt: () => {
|
|
18550
18892
|
try {
|
|
18551
|
-
const lines2 =
|
|
18893
|
+
const lines2 = readFileSync29(join29(projectPath3, ".roll", "loop", "runs.jsonl"), "utf8").trim().split("\n");
|
|
18552
18894
|
for (let i = lines2.length - 1; i >= 0; i--) {
|
|
18553
18895
|
const line = lines2[i] ?? "";
|
|
18554
18896
|
if (line.trim() === "")
|
|
@@ -18605,7 +18947,7 @@ function collectLoopHeartbeat(deps) {
|
|
|
18605
18947
|
|
|
18606
18948
|
// packages/cli/dist/lib/casting.js
|
|
18607
18949
|
init_dist2();
|
|
18608
|
-
import { existsSync as existsSync32, readFileSync as
|
|
18950
|
+
import { existsSync as existsSync32, readFileSync as readFileSync30 } from "node:fs";
|
|
18609
18951
|
import { join as join30 } from "node:path";
|
|
18610
18952
|
var EM_DASH = "\u2014";
|
|
18611
18953
|
function slotRow(key, roleEn, roleZh, deps) {
|
|
@@ -18694,7 +19036,7 @@ function defaultCastingDeps(projectPath3) {
|
|
|
18694
19036
|
const agentsPath2 = process.env["ROLL_AGENTS_CONFIG"] ?? join30(projectPath3, ".roll", "agents.yaml");
|
|
18695
19037
|
try {
|
|
18696
19038
|
if (existsSync32(agentsPath2))
|
|
18697
|
-
agentsText =
|
|
19039
|
+
agentsText = readFileSync30(agentsPath2, "utf8");
|
|
18698
19040
|
} catch {
|
|
18699
19041
|
agentsText = null;
|
|
18700
19042
|
}
|
|
@@ -18702,7 +19044,7 @@ function defaultCastingDeps(projectPath3) {
|
|
|
18702
19044
|
try {
|
|
18703
19045
|
const evPath = join30(projectPath3, ".roll", "loop", "events.ndjson");
|
|
18704
19046
|
if (existsSync32(evPath)) {
|
|
18705
|
-
const content =
|
|
19047
|
+
const content = readFileSync30(evPath, "utf8");
|
|
18706
19048
|
for (const line of content.split("\n")) {
|
|
18707
19049
|
const t2 = line.trim();
|
|
18708
19050
|
if (t2 === "" || !t2.includes("route:resolve"))
|
|
@@ -18741,7 +19083,7 @@ init_dist2();
|
|
|
18741
19083
|
init_dist();
|
|
18742
19084
|
import { createHash as createHash5 } from "node:crypto";
|
|
18743
19085
|
import { spawn as spawn2, spawnSync } from "node:child_process";
|
|
18744
|
-
import { existsSync as existsSync33, mkdirSync as mkdirSync16, readFileSync as
|
|
19086
|
+
import { existsSync as existsSync33, mkdirSync as mkdirSync16, readFileSync as readFileSync31, renameSync as renameSync5, rmSync as rmSync7, writeFileSync as writeFileSync14, readdirSync as readdirSync13 } from "node:fs";
|
|
18745
19087
|
import { homedir as homedir8 } from "node:os";
|
|
18746
19088
|
import { dirname as dirname13, join as join31 } from "node:path";
|
|
18747
19089
|
function realDeps2() {
|
|
@@ -19016,7 +19358,7 @@ function syncGoalPaused(projectPath3, reason) {
|
|
|
19016
19358
|
if (!existsSync33(path))
|
|
19017
19359
|
return;
|
|
19018
19360
|
try {
|
|
19019
|
-
const before = parseGoalYaml(
|
|
19361
|
+
const before = parseGoalYaml(readFileSync31(path, "utf8"));
|
|
19020
19362
|
if (before.status === "paused" || before.status === "complete")
|
|
19021
19363
|
return;
|
|
19022
19364
|
const at = (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
@@ -19058,7 +19400,7 @@ async function loopOnCommand(_args, deps = realDeps2()) {
|
|
|
19058
19400
|
const localYaml = join31(id.path, ".roll", "local.yaml");
|
|
19059
19401
|
if (existsSync33(localYaml)) {
|
|
19060
19402
|
try {
|
|
19061
|
-
period = parseLoopPeriodMinutes(
|
|
19403
|
+
period = parseLoopPeriodMinutes(readFileSync31(localYaml, "utf8"));
|
|
19062
19404
|
} catch {
|
|
19063
19405
|
}
|
|
19064
19406
|
}
|
|
@@ -19207,7 +19549,7 @@ async function loopResumeCommand(_args, deps = realDeps2()) {
|
|
|
19207
19549
|
const stateFile2 = join31(rt, `state-${id.slug}.yaml`);
|
|
19208
19550
|
if (existsSync33(stateFile2)) {
|
|
19209
19551
|
try {
|
|
19210
|
-
const body =
|
|
19552
|
+
const body = readFileSync31(stateFile2, "utf8");
|
|
19211
19553
|
const lines2 = body.split("\n").filter((l) => /^(?!heal_count_head_)/.test(l));
|
|
19212
19554
|
writeFileSync14(stateFile2, lines2.join("\n"), "utf8");
|
|
19213
19555
|
} catch {
|
|
@@ -19250,7 +19592,7 @@ async function loopNowCommand(_args, deps = realDeps2()) {
|
|
|
19250
19592
|
let legacy = false;
|
|
19251
19593
|
if (existsSync33(runner)) {
|
|
19252
19594
|
try {
|
|
19253
|
-
legacy = isLegacyRunner(
|
|
19595
|
+
legacy = isLegacyRunner(readFileSync31(runner, "utf8"));
|
|
19254
19596
|
} catch {
|
|
19255
19597
|
legacy = true;
|
|
19256
19598
|
}
|
|
@@ -19410,7 +19752,7 @@ ${CHROME_CONTROLS}
|
|
|
19410
19752
|
init_dist2();
|
|
19411
19753
|
init_dist();
|
|
19412
19754
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
19413
|
-
import { existsSync as existsSync34, readdirSync as readdirSync14, readFileSync as
|
|
19755
|
+
import { existsSync as existsSync34, readdirSync as readdirSync14, readFileSync as readFileSync32, statSync as statSync13 } from "node:fs";
|
|
19414
19756
|
import { join as joinPath2 } from "node:path";
|
|
19415
19757
|
var esc6 = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
19416
19758
|
function storyDeliveryState(d) {
|
|
@@ -20803,7 +21145,7 @@ function rebaseAcEvidenceToStoryRoot(ev) {
|
|
|
20803
21145
|
return ev.map((e) => e.href !== void 0 ? { ...e, href: rebaseEvidenceHrefToStoryRoot(e.href) } : e);
|
|
20804
21146
|
}
|
|
20805
21147
|
function readFile(p) {
|
|
20806
|
-
return
|
|
21148
|
+
return readFileSync32(p, "utf8");
|
|
20807
21149
|
}
|
|
20808
21150
|
function statDir(p) {
|
|
20809
21151
|
return statSync13(p).isFile();
|
|
@@ -20828,7 +21170,7 @@ function renderNowSec() {
|
|
|
20828
21170
|
function readJsonl(path) {
|
|
20829
21171
|
let content;
|
|
20830
21172
|
try {
|
|
20831
|
-
content =
|
|
21173
|
+
content = readFileSync33(path, "utf8");
|
|
20832
21174
|
} catch {
|
|
20833
21175
|
return void 0;
|
|
20834
21176
|
}
|
|
@@ -20871,7 +21213,7 @@ function latestConsistencyAudit(projectPath3) {
|
|
|
20871
21213
|
if (latest === void 0)
|
|
20872
21214
|
return void 0;
|
|
20873
21215
|
try {
|
|
20874
|
-
const obj = JSON.parse(
|
|
21216
|
+
const obj = JSON.parse(readFileSync33(join32(dir, latest), "utf8"));
|
|
20875
21217
|
const summary = obj["summary"];
|
|
20876
21218
|
if (typeof summary !== "object" || summary === null || Array.isArray(summary))
|
|
20877
21219
|
return void 0;
|
|
@@ -20928,7 +21270,7 @@ function releaseTruthBoard(projectPath3, nowSec2) {
|
|
|
20928
21270
|
const path = join32(projectPath3, ".roll", "loop", "events.ndjson");
|
|
20929
21271
|
let content;
|
|
20930
21272
|
try {
|
|
20931
|
-
content =
|
|
21273
|
+
content = readFileSync33(path, "utf8");
|
|
20932
21274
|
} catch {
|
|
20933
21275
|
return void 0;
|
|
20934
21276
|
}
|
|
@@ -20994,7 +21336,7 @@ function renderSpecHtml(storyDir, id) {
|
|
|
20994
21336
|
return null;
|
|
20995
21337
|
let md;
|
|
20996
21338
|
try {
|
|
20997
|
-
md =
|
|
21339
|
+
md = readFileSync33(specPath, "utf8");
|
|
20998
21340
|
} catch {
|
|
20999
21341
|
return null;
|
|
21000
21342
|
}
|
|
@@ -21255,7 +21597,7 @@ function defaultProcessReaders(projectPath3, env) {
|
|
|
21255
21597
|
if (!existsSync36(p))
|
|
21256
21598
|
return null;
|
|
21257
21599
|
try {
|
|
21258
|
-
return
|
|
21600
|
+
return readFileSync34(p, "utf8");
|
|
21259
21601
|
} catch {
|
|
21260
21602
|
return null;
|
|
21261
21603
|
}
|
|
@@ -21482,7 +21824,7 @@ function readAcMap(storyDir) {
|
|
|
21482
21824
|
if (!existsSync36(p))
|
|
21483
21825
|
return null;
|
|
21484
21826
|
try {
|
|
21485
|
-
const arr2 = JSON.parse(
|
|
21827
|
+
const arr2 = JSON.parse(readFileSync34(p, "utf8"));
|
|
21486
21828
|
if (!Array.isArray(arr2))
|
|
21487
21829
|
return null;
|
|
21488
21830
|
const m7 = /* @__PURE__ */ new Map();
|
|
@@ -21503,7 +21845,7 @@ function toRef(runDir, e) {
|
|
|
21503
21845
|
if (!existsSync36(p))
|
|
21504
21846
|
return null;
|
|
21505
21847
|
try {
|
|
21506
|
-
const { redacted, hits } = redactSecrets(
|
|
21848
|
+
const { redacted, hits } = redactSecrets(readFileSync34(p, "utf8"));
|
|
21507
21849
|
if (hits.length > 0)
|
|
21508
21850
|
warn2(`redacted secret(s) in ${e.textFile}: ${hits.join(", ")}`);
|
|
21509
21851
|
return { kind, label: label4, inlineHtml: ansiPre(redacted) };
|
|
@@ -21522,7 +21864,7 @@ function toRef(runDir, e) {
|
|
|
21522
21864
|
return null;
|
|
21523
21865
|
}
|
|
21524
21866
|
if (kind === "cast") {
|
|
21525
|
-
const { redacted, hits } = redactSecrets(
|
|
21867
|
+
const { redacted, hits } = redactSecrets(readFileSync34(p, "utf8"));
|
|
21526
21868
|
if (hits.length > 0)
|
|
21527
21869
|
warn2(`redacted secret(s) in ${e.href}: ${hits.join(", ")}`);
|
|
21528
21870
|
const bounded = boundTranscript(redacted);
|
|
@@ -21562,7 +21904,7 @@ function readBacklogRow(projectPath3, storyId) {
|
|
|
21562
21904
|
return {};
|
|
21563
21905
|
let text;
|
|
21564
21906
|
try {
|
|
21565
|
-
text =
|
|
21907
|
+
text = readFileSync34(p, "utf8");
|
|
21566
21908
|
} catch {
|
|
21567
21909
|
return {};
|
|
21568
21910
|
}
|
|
@@ -21600,7 +21942,7 @@ function buildCardContext(projectPath3, featureFile, storyId, env) {
|
|
|
21600
21942
|
const oneLiner = row2.description !== void 0 ? row2.description.replace(/\s*depends-on:\S+/gi, "").trim() : void 0;
|
|
21601
21943
|
let summary;
|
|
21602
21944
|
try {
|
|
21603
|
-
summary = extractSummary(
|
|
21945
|
+
summary = extractSummary(readFileSync34(featureFile, "utf8"));
|
|
21604
21946
|
} catch {
|
|
21605
21947
|
}
|
|
21606
21948
|
const epic = epicFromFeaturePath(featureFile);
|
|
@@ -21719,7 +22061,7 @@ function ensurePreEvidenceMarker(storyId, runDir) {
|
|
|
21719
22061
|
function resolveStoryAcItems(projectPath3, storyId) {
|
|
21720
22062
|
for (const cand of findFeatureFiles(projectPath3, storyId)) {
|
|
21721
22063
|
try {
|
|
21722
|
-
const items = acForStory(
|
|
22064
|
+
const items = acForStory(readFileSync34(cand, "utf8"), storyId, {
|
|
21723
22065
|
fileOwned: basename8(cand) === `${storyId}.md`
|
|
21724
22066
|
});
|
|
21725
22067
|
if (items.length > 0)
|
|
@@ -21760,7 +22102,7 @@ async function attestBackfillCommand(args, deps) {
|
|
|
21760
22102
|
return 1;
|
|
21761
22103
|
}
|
|
21762
22104
|
const stats = { scanned: 0, backfilled: 0, skippedExisting: 0, skippedMissingCard: 0, failed: 0 };
|
|
21763
|
-
const items = parseBacklog(
|
|
22105
|
+
const items = parseBacklog(readFileSync34(backlogPath, "utf8")).filter((item) => classifyStatus(item.status) === "done");
|
|
21764
22106
|
for (const item of items) {
|
|
21765
22107
|
stats.scanned += 1;
|
|
21766
22108
|
const featureFile = findFeatureFile(projectPath3, item.id);
|
|
@@ -21949,7 +22291,7 @@ async function attestCommand(args, deps = {}) {
|
|
|
21949
22291
|
const deliveryHtml = `<p><a href="${reportRel}">${bi("Attestation report", "\u9A8C\u6536\u62A5\u544A")}</a></p>
|
|
21950
22292
|
` + dossierVisualsHtml(runRel, beforeAfter, afterOnly) + `<p class="muted">${bi("Delivered", "\u4EA4\u4ED8\u4E8E")} ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}</p>
|
|
21951
22293
|
`;
|
|
21952
|
-
const idx = markPhaseDone(
|
|
22294
|
+
const idx = markPhaseDone(readFileSync34(indexPath, "utf8"), "delivery", deliveryHtml);
|
|
21953
22295
|
writeFileSync16(indexPath, idx, "utf8");
|
|
21954
22296
|
} catch {
|
|
21955
22297
|
}
|
|
@@ -21978,12 +22320,12 @@ async function attestCommand(args, deps = {}) {
|
|
|
21978
22320
|
|
|
21979
22321
|
// packages/cli/dist/commands/backlog.js
|
|
21980
22322
|
init_dist();
|
|
21981
|
-
import { existsSync as existsSync37, readFileSync as
|
|
22323
|
+
import { existsSync as existsSync37, readFileSync as readFileSync35 } from "node:fs";
|
|
21982
22324
|
var ID_RE = /\[([^\]]+)\]\([^)]+\)/;
|
|
21983
22325
|
var REASON_RE = /\[([^\]]+)\]/;
|
|
21984
22326
|
function parseBacklog2(path) {
|
|
21985
22327
|
const items = [];
|
|
21986
|
-
for (const raw of
|
|
22328
|
+
for (const raw of readFileSync35(path, "utf8").split("\n")) {
|
|
21987
22329
|
const line = raw.replace(/\n$/, "");
|
|
21988
22330
|
if (!line.startsWith("|"))
|
|
21989
22331
|
continue;
|
|
@@ -22105,7 +22447,7 @@ function backlogCommand(args) {
|
|
|
22105
22447
|
// packages/cli/dist/commands/backlog-mgmt.js
|
|
22106
22448
|
init_dist2();
|
|
22107
22449
|
init_dist();
|
|
22108
|
-
import { appendFileSync as appendFileSync5, existsSync as existsSync38, mkdirSync as mkdirSync18, readFileSync as
|
|
22450
|
+
import { appendFileSync as appendFileSync5, existsSync as existsSync38, mkdirSync as mkdirSync18, readFileSync as readFileSync36, writeFileSync as writeFileSync17 } from "node:fs";
|
|
22109
22451
|
import { dirname as dirname14, join as join34 } from "node:path";
|
|
22110
22452
|
var BACKLOG_PATH = ".roll/backlog.md";
|
|
22111
22453
|
function lang() {
|
|
@@ -22226,8 +22568,8 @@ function backlogUnstickCommand(args, deps = realUnstickDeps()) {
|
|
|
22226
22568
|
const slug = deps.slug();
|
|
22227
22569
|
const loopDir = join34(deps.sharedRoot(), "loop");
|
|
22228
22570
|
const eventsPath2 = join34(loopDir, `events-${slug}.ndjson`);
|
|
22229
|
-
const events = existsSync38(eventsPath2) ? parseUnstickEvents(
|
|
22230
|
-
const content =
|
|
22571
|
+
const events = existsSync38(eventsPath2) ? parseUnstickEvents(readFileSync36(eventsPath2, "utf8")) : [];
|
|
22572
|
+
const content = readFileSync36(backlog, "utf8");
|
|
22231
22573
|
const nowMs = deps.nowMs();
|
|
22232
22574
|
const candidates = reconcileStuckBacklog(content, events, nowMs, ttlHours);
|
|
22233
22575
|
if (candidates.length === 0)
|
|
@@ -22288,7 +22630,7 @@ function backlogLintCommand(args) {
|
|
|
22288
22630
|
errLine(`[roll] backlog not found: ${backlog}`);
|
|
22289
22631
|
return 1;
|
|
22290
22632
|
}
|
|
22291
|
-
const findings = lintBacklogContent(
|
|
22633
|
+
const findings = lintBacklogContent(readFileSync36(backlog, "utf8"));
|
|
22292
22634
|
for (const f of findings) {
|
|
22293
22635
|
out(`${backlog}:${f.lineno}: ${f.sid} \u2014 ${f.issues}`);
|
|
22294
22636
|
out(` ${f.desc}`);
|
|
@@ -22310,7 +22652,7 @@ function backlogLintCommand(args) {
|
|
|
22310
22652
|
// packages/cli/dist/commands/backlog-sync.js
|
|
22311
22653
|
init_dist2();
|
|
22312
22654
|
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
22313
|
-
import { appendFileSync as appendFileSync6, existsSync as existsSync39, mkdirSync as mkdirSync19, readFileSync as
|
|
22655
|
+
import { appendFileSync as appendFileSync6, existsSync as existsSync39, mkdirSync as mkdirSync19, readFileSync as readFileSync37, writeFileSync as writeFileSync18 } from "node:fs";
|
|
22314
22656
|
import { dirname as dirname15, join as join35 } from "node:path";
|
|
22315
22657
|
var API_ROOT = "https://api.github.com";
|
|
22316
22658
|
var RATE_LIMIT_FLOOR = 5;
|
|
@@ -22405,7 +22747,7 @@ function realSyncDeps() {
|
|
|
22405
22747
|
loadIssues: async (owner, repo) => {
|
|
22406
22748
|
const fixture = (process.env["ROLL_SYNC_FIXTURE"] ?? "").trim();
|
|
22407
22749
|
if (fixture)
|
|
22408
|
-
return JSON.parse(
|
|
22750
|
+
return JSON.parse(readFileSync37(fixture, "utf8"));
|
|
22409
22751
|
return fetchIssues(owner, repo, { state: "open" });
|
|
22410
22752
|
},
|
|
22411
22753
|
nowIso: () => (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z")
|
|
@@ -22419,7 +22761,7 @@ async function backlogSyncCommand(args, deps = realSyncDeps()) {
|
|
|
22419
22761
|
const backlog = flagValue(args, "--backlog") ?? ".roll/backlog.md";
|
|
22420
22762
|
const featuresDir = flagValue(args, "--features") ?? ".roll/features";
|
|
22421
22763
|
const localYaml = flagValue(args, "--local-yaml") ?? ".roll/local.yaml";
|
|
22422
|
-
const cfg = existsSync39(localYaml) ? readSyncConfig(
|
|
22764
|
+
const cfg = existsSync39(localYaml) ? readSyncConfig(readFileSync37(localYaml, "utf8")) : {};
|
|
22423
22765
|
const repoArg = flagValue(args, "--repo") ?? cfg.repo ?? "";
|
|
22424
22766
|
if (!repoArg) {
|
|
22425
22767
|
process.stderr.write("usage: roll backlog sync --repo <owner/repo> [--backlog <path>] [--features <dir>] [--label <a,b>] [--dry-run]\n \u9996\u6B21 sync \u5FC5\u987B\u663E\u5F0F --repo\uFF08local.yaml \u4E2D\u5C1A\u65E0 backlog_sync.repo\uFF09\u3002\n");
|
|
@@ -22462,7 +22804,7 @@ async function backlogSyncCommand(args, deps = realSyncDeps()) {
|
|
|
22462
22804
|
`);
|
|
22463
22805
|
return 1;
|
|
22464
22806
|
}
|
|
22465
|
-
const content =
|
|
22807
|
+
const content = readFileSync37(backlog, "utf8");
|
|
22466
22808
|
if (dryRun) {
|
|
22467
22809
|
const preview = dryRunPreview(issues, content);
|
|
22468
22810
|
for (const line of preview.lines)
|
|
@@ -22488,7 +22830,7 @@ async function backlogSyncCommand(args, deps = realSyncDeps()) {
|
|
|
22488
22830
|
process.stdout.write(`added: ${result.added}, skipped: ${result.skipped}, total issues: ${result.total}
|
|
22489
22831
|
`);
|
|
22490
22832
|
const block = renderSyncBlock(repoArg, wanted, deps.nowIso());
|
|
22491
|
-
const original = existsSync39(localYaml) ?
|
|
22833
|
+
const original = existsSync39(localYaml) ? readFileSync37(localYaml, "utf8") : "";
|
|
22492
22834
|
mkdirSync19(dirname15(localYaml) || ".", { recursive: true });
|
|
22493
22835
|
writeFileSync18(localYaml, original === "" ? block + "\n" : writeSyncBlock(original, block));
|
|
22494
22836
|
return 0;
|
|
@@ -22499,7 +22841,7 @@ function writeFeatureStub(issue, featuresDir, epic = "backlog-lifecycle") {
|
|
|
22499
22841
|
const path = join35(epicDir, `${ghId(issue)}.md`);
|
|
22500
22842
|
const ac = renderAcSection(issue);
|
|
22501
22843
|
if (existsSync39(path)) {
|
|
22502
|
-
const existing =
|
|
22844
|
+
const existing = readFileSync37(path, "utf8");
|
|
22503
22845
|
const block = ac ? ac + "\n" : "";
|
|
22504
22846
|
const sep3 = existing.endsWith("\n") || existing === "" ? "" : "\n";
|
|
22505
22847
|
if (block)
|
|
@@ -22515,7 +22857,7 @@ init_dist2();
|
|
|
22515
22857
|
init_dist3();
|
|
22516
22858
|
init_dist();
|
|
22517
22859
|
import { execFileSync as execFileSync7, spawnSync as spawnSync2 } from "node:child_process";
|
|
22518
|
-
import { existsSync as existsSync40, mkdirSync as mkdirSync20, readFileSync as
|
|
22860
|
+
import { existsSync as existsSync40, mkdirSync as mkdirSync20, readFileSync as readFileSync38, writeFileSync as writeFileSync19 } from "node:fs";
|
|
22519
22861
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
22520
22862
|
import { dirname as dirname16, join as join36 } from "node:path";
|
|
22521
22863
|
function lang2() {
|
|
@@ -22615,7 +22957,7 @@ function loopEnforceTcrCommand(args, deps = realEnforceTcrDeps()) {
|
|
|
22615
22957
|
return 0;
|
|
22616
22958
|
const backlog = join36(".roll", "backlog.md");
|
|
22617
22959
|
if (existsSync40(backlog)) {
|
|
22618
|
-
writeFileSync19(backlog, revertStoryDone(
|
|
22960
|
+
writeFileSync19(backlog, revertStoryDone(readFileSync38(backlog, "utf8"), storyId));
|
|
22619
22961
|
}
|
|
22620
22962
|
const alert = alertFile();
|
|
22621
22963
|
mkdirSync20(dirname16(alert), { recursive: true });
|
|
@@ -22673,7 +23015,7 @@ function loopPrecheckCiCommand(args, deps = realPrecheckDeps()) {
|
|
|
22673
23015
|
const sha8 = commit2.slice(0, 8);
|
|
22674
23016
|
const healKey = `heal_count_head_${sha8}`;
|
|
22675
23017
|
const state = stateFilePath();
|
|
22676
|
-
const body = existsSync40(state) ?
|
|
23018
|
+
const body = existsSync40(state) ? readFileSync38(state, "utf8") : "";
|
|
22677
23019
|
const headHealCount = parseInt(stateGet(body, healKey) || "0", 10) || 0;
|
|
22678
23020
|
const verdict = precheckCiVerdict({ ghAndCommitOk: true, runs, healMax, headHealCount });
|
|
22679
23021
|
if (verdict.exit === 2) {
|
|
@@ -22785,7 +23127,7 @@ function loopUnknownSubcommand(sub) {
|
|
|
22785
23127
|
// packages/cli/dist/commands/brief.js
|
|
22786
23128
|
init_dist2();
|
|
22787
23129
|
init_dist();
|
|
22788
|
-
import { existsSync as existsSync41, readFileSync as
|
|
23130
|
+
import { existsSync as existsSync41, readFileSync as readFileSync39 } from "node:fs";
|
|
22789
23131
|
import { homedir as homedir9 } from "node:os";
|
|
22790
23132
|
import { join as join37 } from "node:path";
|
|
22791
23133
|
var BACKLOG_PATH2 = ".roll/backlog.md";
|
|
@@ -22877,7 +23219,7 @@ function briefCommand(args) {
|
|
|
22877
23219
|
`);
|
|
22878
23220
|
return 1;
|
|
22879
23221
|
}
|
|
22880
|
-
const items = parseBacklog(
|
|
23222
|
+
const items = parseBacklog(readFileSync39(BACKLOG_PATH2, "utf8"));
|
|
22881
23223
|
const model = composeBrief(items, activeAlerts());
|
|
22882
23224
|
const dateStr = formatNow(/* @__PURE__ */ new Date());
|
|
22883
23225
|
process.stdout.write(renderBrief(model, lang9, { full }, dateStr).join("\n") + "\n");
|
|
@@ -22950,7 +23292,7 @@ init_dist();
|
|
|
22950
23292
|
// packages/cli/dist/commands/lang.js
|
|
22951
23293
|
init_dist();
|
|
22952
23294
|
import { execFileSync as execFileSync8 } from "node:child_process";
|
|
22953
|
-
import { existsSync as existsSync42, mkdirSync as mkdirSync21, mkdtempSync, readFileSync as
|
|
23295
|
+
import { existsSync as existsSync42, mkdirSync as mkdirSync21, mkdtempSync, readFileSync as readFileSync40, renameSync as renameSync6, writeFileSync as writeFileSync20 } from "node:fs";
|
|
22954
23296
|
import { homedir as homedir10, tmpdir as tmpdir3 } from "node:os";
|
|
22955
23297
|
import { dirname as dirname17, join as join38 } from "node:path";
|
|
22956
23298
|
function rollConfigPath2() {
|
|
@@ -22961,7 +23303,7 @@ function configLang2() {
|
|
|
22961
23303
|
const cfg = rollConfigPath2();
|
|
22962
23304
|
if (!existsSync42(cfg))
|
|
22963
23305
|
return void 0;
|
|
22964
|
-
for (const line of
|
|
23306
|
+
for (const line of readFileSync40(cfg, "utf8").split("\n")) {
|
|
22965
23307
|
const m7 = /^lang:\s*(.*)$/.exec(line);
|
|
22966
23308
|
if (m7 !== null) {
|
|
22967
23309
|
const v = (m7[1] ?? "").replace(/\s*#.*$/, "").trim();
|
|
@@ -22975,7 +23317,7 @@ function configHasLangLine() {
|
|
|
22975
23317
|
const cfg = rollConfigPath2();
|
|
22976
23318
|
if (!existsSync42(cfg))
|
|
22977
23319
|
return false;
|
|
22978
|
-
return
|
|
23320
|
+
return readFileSync40(cfg, "utf8").split("\n").some((l) => /^lang:/.test(l));
|
|
22979
23321
|
}
|
|
22980
23322
|
function appleLang2() {
|
|
22981
23323
|
if (process.platform !== "darwin")
|
|
@@ -23018,7 +23360,7 @@ function resolveSource() {
|
|
|
23018
23360
|
function writeLang(value) {
|
|
23019
23361
|
const cfg = rollConfigPath2();
|
|
23020
23362
|
mkdirSync21(dirname17(cfg), { recursive: true });
|
|
23021
|
-
const existing = existsSync42(cfg) ?
|
|
23363
|
+
const existing = existsSync42(cfg) ? readFileSync40(cfg, "utf8") : "";
|
|
23022
23364
|
const kept = existing === "" ? [] : existing.split("\n").filter((l) => !/^lang:/.test(l));
|
|
23023
23365
|
if (kept.length > 0 && kept[kept.length - 1] === "")
|
|
23024
23366
|
kept.pop();
|
|
@@ -23032,7 +23374,7 @@ function clearLang() {
|
|
|
23032
23374
|
const cfg = rollConfigPath2();
|
|
23033
23375
|
if (!existsSync42(cfg))
|
|
23034
23376
|
return;
|
|
23035
|
-
const existing =
|
|
23377
|
+
const existing = readFileSync40(cfg, "utf8");
|
|
23036
23378
|
const kept = existing.split("\n").filter((l) => !/^lang:/.test(l));
|
|
23037
23379
|
if (kept.length > 0 && kept[kept.length - 1] === "")
|
|
23038
23380
|
kept.pop();
|
|
@@ -23939,7 +24281,7 @@ ${CYCLE_USAGE}
|
|
|
23939
24281
|
|
|
23940
24282
|
// packages/cli/dist/commands/ls.js
|
|
23941
24283
|
init_dist();
|
|
23942
|
-
import { existsSync as existsSync43, readFileSync as
|
|
24284
|
+
import { existsSync as existsSync43, readFileSync as readFileSync41 } from "node:fs";
|
|
23943
24285
|
var LS_USAGE = "Usage: roll ls [--json] [--stale-days <n>]\n List the cross-project registry (~/.roll/projects.json): name \xB7 tag \xB7 verdict \xB7 path.\n Missing paths and stale entries are flagged, never dropped. --json echoes the file verbatim.\n\u5217\u51FA\u8DE8\u9879\u76EE\u6CE8\u518C\u8868\uFF08~/.roll/projects.json\uFF09\uFF1A\u540D\u79F0 \xB7 \u7248\u672C \xB7 \u5224\u5B9A \xB7 \u8DEF\u5F84\u3002\n\u7F3A\u5931\u8DEF\u5F84\u4E0E\u8FC7\u671F\u6761\u76EE\u4F1A\u88AB\u6807\u6CE8\uFF0C\u7EDD\u4E0D\u4E22\u5F03\u3002--json \u9010\u5B57\u8F93\u51FA\u6587\u4EF6\u672C\u8EAB\u3002";
|
|
23944
24286
|
var DEFAULT_STALE_DAYS = 14;
|
|
23945
24287
|
function projectStatus(entry, nowMs, staleMs, pathExists) {
|
|
@@ -24033,7 +24375,7 @@ ${LS_USAGE}
|
|
|
24033
24375
|
if (args.includes("--json")) {
|
|
24034
24376
|
let text;
|
|
24035
24377
|
try {
|
|
24036
|
-
text =
|
|
24378
|
+
text = readFileSync41(projectsRegistryPath(), "utf8");
|
|
24037
24379
|
} catch {
|
|
24038
24380
|
text = "[]\n";
|
|
24039
24381
|
}
|
|
@@ -24048,7 +24390,7 @@ ${LS_USAGE}
|
|
|
24048
24390
|
|
|
24049
24391
|
// packages/cli/dist/commands/loop-runs.js
|
|
24050
24392
|
init_dist();
|
|
24051
|
-
import { existsSync as existsSync44, readFileSync as
|
|
24393
|
+
import { existsSync as existsSync44, readFileSync as readFileSync42, readdirSync as readdirSync17 } from "node:fs";
|
|
24052
24394
|
import { homedir as homedir12, platform as platform2 } from "node:os";
|
|
24053
24395
|
import { basename as basename9, join as join40 } from "node:path";
|
|
24054
24396
|
function lang3() {
|
|
@@ -24156,7 +24498,7 @@ function backlogDesc(backlogText, id) {
|
|
|
24156
24498
|
}
|
|
24157
24499
|
return "";
|
|
24158
24500
|
}
|
|
24159
|
-
function
|
|
24501
|
+
function formatLine(row2, showProject, backlogText) {
|
|
24160
24502
|
const ts = str3(row2["ts"]);
|
|
24161
24503
|
const status2 = str3(row2["status"]);
|
|
24162
24504
|
const project = str3(row2["project"]);
|
|
@@ -24216,7 +24558,7 @@ function aggregateAllFiles() {
|
|
|
24216
24558
|
for (const pl of plists) {
|
|
24217
24559
|
let content;
|
|
24218
24560
|
try {
|
|
24219
|
-
content =
|
|
24561
|
+
content = readFileSync42(join40(laDir, pl), "utf8");
|
|
24220
24562
|
} catch {
|
|
24221
24563
|
continue;
|
|
24222
24564
|
}
|
|
@@ -24232,7 +24574,7 @@ function aggregateAllFiles() {
|
|
|
24232
24574
|
if (!f || seen.has(f))
|
|
24233
24575
|
continue;
|
|
24234
24576
|
try {
|
|
24235
|
-
if (!existsSync44(f) ||
|
|
24577
|
+
if (!existsSync44(f) || readFileSync42(f, "utf8").trim() === "")
|
|
24236
24578
|
continue;
|
|
24237
24579
|
} catch {
|
|
24238
24580
|
continue;
|
|
@@ -24246,7 +24588,7 @@ function aggregateAllRows() {
|
|
|
24246
24588
|
const rows = [];
|
|
24247
24589
|
for (const f of aggregateAllFiles()) {
|
|
24248
24590
|
try {
|
|
24249
|
-
rows.push(...parseRows(
|
|
24591
|
+
rows.push(...parseRows(readFileSync42(f, "utf8")));
|
|
24250
24592
|
} catch {
|
|
24251
24593
|
}
|
|
24252
24594
|
}
|
|
@@ -24268,7 +24610,7 @@ function runsDetail(cycleId) {
|
|
|
24268
24610
|
}
|
|
24269
24611
|
let rows;
|
|
24270
24612
|
try {
|
|
24271
|
-
rows = parseRows(
|
|
24613
|
+
rows = parseRows(readFileSync42(src, "utf8"));
|
|
24272
24614
|
} catch {
|
|
24273
24615
|
rows = [];
|
|
24274
24616
|
}
|
|
@@ -24325,12 +24667,12 @@ function loopRunsCommand(argv) {
|
|
|
24325
24667
|
rows = aggregateAllRows();
|
|
24326
24668
|
} else {
|
|
24327
24669
|
const src = runsFile();
|
|
24328
|
-
if (!existsSync44(src) ||
|
|
24670
|
+
if (!existsSync44(src) || readFileSync42(src, "utf8").trim() === "") {
|
|
24329
24671
|
process.stdout.write(msg3("loop.no_loop_runs_yet") + "\n");
|
|
24330
24672
|
return 0;
|
|
24331
24673
|
}
|
|
24332
24674
|
const slug = projectSlug2();
|
|
24333
|
-
rows = parseRows(
|
|
24675
|
+
rows = parseRows(readFileSync42(src, "utf8")).filter((r) => str3(r["project"]) === slug);
|
|
24334
24676
|
}
|
|
24335
24677
|
if (rows.length === 0) {
|
|
24336
24678
|
process.stdout.write(msg3("loop.no_loop_runs_for_current_project") + "\n");
|
|
@@ -24342,12 +24684,12 @@ function loopRunsCommand(argv) {
|
|
|
24342
24684
|
const blPath = join40(proj, ".roll", "backlog.md");
|
|
24343
24685
|
if (existsSync44(blPath)) {
|
|
24344
24686
|
try {
|
|
24345
|
-
backlogText =
|
|
24687
|
+
backlogText = readFileSync42(blPath, "utf8");
|
|
24346
24688
|
} catch {
|
|
24347
24689
|
backlogText = "";
|
|
24348
24690
|
}
|
|
24349
24691
|
}
|
|
24350
|
-
const out3 = recent.map((r) =>
|
|
24692
|
+
const out3 = recent.map((r) => formatLine(r, allFlag, backlogText));
|
|
24351
24693
|
process.stdout.write(out3.join("\n") + "\n");
|
|
24352
24694
|
return 0;
|
|
24353
24695
|
}
|
|
@@ -24355,7 +24697,7 @@ function loopRunsCommand(argv) {
|
|
|
24355
24697
|
// packages/cli/dist/commands/loop-signals.js
|
|
24356
24698
|
init_dist2();
|
|
24357
24699
|
init_dist();
|
|
24358
|
-
import { appendFileSync as appendFileSync7, existsSync as existsSync45, mkdirSync as mkdirSync22, readFileSync as
|
|
24700
|
+
import { appendFileSync as appendFileSync7, existsSync as existsSync45, mkdirSync as mkdirSync22, readFileSync as readFileSync43, writeFileSync as writeFileSync21 } from "node:fs";
|
|
24359
24701
|
import { dirname as dirname18, join as join41 } from "node:path";
|
|
24360
24702
|
function lang4() {
|
|
24361
24703
|
return resolveLang({ rollLang: process.env["ROLL_LANG"], lcAll: process.env["LC_ALL"], lang: process.env["LANG"] });
|
|
@@ -24388,14 +24730,14 @@ function loopSignalsCommand(argv) {
|
|
|
24388
24730
|
process.stdout.write(s + "\n");
|
|
24389
24731
|
};
|
|
24390
24732
|
const runsSrc = runsFile();
|
|
24391
|
-
if (!existsSync45(runsSrc) ||
|
|
24733
|
+
if (!existsSync45(runsSrc) || readFileSync43(runsSrc, "utf8").trim() === "") {
|
|
24392
24734
|
say(t(v2Catalog, lang4(), "loop.no_loop_runs_yet"));
|
|
24393
24735
|
return 0;
|
|
24394
24736
|
}
|
|
24395
24737
|
const projectPath3 = (process.env["ROLL_MAIN_PROJECT"] ?? "").trim() || process.cwd();
|
|
24396
24738
|
const slug = projectSlug2();
|
|
24397
24739
|
const records = [];
|
|
24398
|
-
for (const line of
|
|
24740
|
+
for (const line of readFileSync43(runsSrc, "utf8").split("\n")) {
|
|
24399
24741
|
if (line.trim() === "")
|
|
24400
24742
|
continue;
|
|
24401
24743
|
try {
|
|
@@ -24416,13 +24758,13 @@ function loopSignalsCommand(argv) {
|
|
|
24416
24758
|
writeFileSync21(seenFile, "");
|
|
24417
24759
|
let lastId = 0;
|
|
24418
24760
|
if (existsSync45(candFile)) {
|
|
24419
|
-
for (const m7 of
|
|
24761
|
+
for (const m7 of readFileSync43(candFile, "utf8").matchAll(/CAND-(\d+)/g)) {
|
|
24420
24762
|
const n = parseInt(m7[1] ?? "0", 10);
|
|
24421
24763
|
if (n > lastId)
|
|
24422
24764
|
lastId = n;
|
|
24423
24765
|
}
|
|
24424
24766
|
}
|
|
24425
|
-
const seen = new Set(existsSync45(seenFile) ?
|
|
24767
|
+
const seen = new Set(existsSync45(seenFile) ? readFileSync43(seenFile, "utf8").split("\n").filter((l) => l !== "") : []);
|
|
24426
24768
|
let newCount = 0;
|
|
24427
24769
|
for (const sig of signals) {
|
|
24428
24770
|
if (seen.has(sig.key))
|
|
@@ -24469,7 +24811,7 @@ Options:
|
|
|
24469
24811
|
|
|
24470
24812
|
// packages/cli/dist/commands/loop-log.js
|
|
24471
24813
|
init_dist();
|
|
24472
|
-
import { existsSync as existsSync46, readFileSync as
|
|
24814
|
+
import { existsSync as existsSync46, readFileSync as readFileSync44, readdirSync as readdirSync18 } from "node:fs";
|
|
24473
24815
|
import { basename as basename10, join as join42 } from "node:path";
|
|
24474
24816
|
function lang5() {
|
|
24475
24817
|
return resolveLang({ rollLang: process.env["ROLL_LANG"], lcAll: process.env["LC_ALL"], lang: process.env["LANG"] });
|
|
@@ -24486,7 +24828,7 @@ function showLog(file) {
|
|
|
24486
24828
|
const ts = m7 ? `${m7[1]}-${m7[2]}-${m7[3]} ${m7[4]}:${m7[5]}` : id;
|
|
24487
24829
|
let body = "";
|
|
24488
24830
|
try {
|
|
24489
|
-
body =
|
|
24831
|
+
body = readFileSync44(file, "utf8");
|
|
24490
24832
|
} catch {
|
|
24491
24833
|
body = "";
|
|
24492
24834
|
}
|
|
@@ -24542,7 +24884,7 @@ function loopLogCommand(argv) {
|
|
|
24542
24884
|
|
|
24543
24885
|
// packages/cli/dist/commands/loop-goal.js
|
|
24544
24886
|
init_dist();
|
|
24545
|
-
import { existsSync as existsSync47, readFileSync as
|
|
24887
|
+
import { existsSync as existsSync47, readFileSync as readFileSync45 } from "node:fs";
|
|
24546
24888
|
import { join as join43 } from "node:path";
|
|
24547
24889
|
function realDeps3() {
|
|
24548
24890
|
return { projectPath: () => process.cwd() };
|
|
@@ -24616,7 +24958,7 @@ async function loopGoalCommand(args, deps = realDeps3()) {
|
|
|
24616
24958
|
return 0;
|
|
24617
24959
|
}
|
|
24618
24960
|
try {
|
|
24619
|
-
process.stdout.write(renderGoal(parseGoalYaml(
|
|
24961
|
+
process.stdout.write(renderGoal(parseGoalYaml(readFileSync45(path, "utf8"))));
|
|
24620
24962
|
return 0;
|
|
24621
24963
|
} catch (e) {
|
|
24622
24964
|
process.stderr.write(`[roll] goal.yaml invalid: ${e.message}
|
|
@@ -24630,7 +24972,7 @@ init_dist2();
|
|
|
24630
24972
|
init_dist();
|
|
24631
24973
|
init_dist3();
|
|
24632
24974
|
import { spawn as spawn3, spawnSync as spawnSync4 } from "node:child_process";
|
|
24633
|
-
import { appendFileSync as appendFileSync8, createReadStream, existsSync as existsSync48, mkdirSync as mkdirSync23, readFileSync as
|
|
24975
|
+
import { appendFileSync as appendFileSync8, createReadStream, existsSync as existsSync48, mkdirSync as mkdirSync23, readFileSync as readFileSync46, renameSync as renameSync7, statSync as statSync15, writeFileSync as writeFileSync22 } from "node:fs";
|
|
24634
24976
|
import { dirname as dirname19, join as join44 } from "node:path";
|
|
24635
24977
|
import { createInterface } from "node:readline";
|
|
24636
24978
|
|
|
@@ -25215,7 +25557,7 @@ function writeGoal(path, goal) {
|
|
|
25215
25557
|
function readGoal(path) {
|
|
25216
25558
|
if (!existsSync48(path))
|
|
25217
25559
|
return void 0;
|
|
25218
|
-
return parseGoalYaml(
|
|
25560
|
+
return parseGoalYaml(readFileSync46(path, "utf8"));
|
|
25219
25561
|
}
|
|
25220
25562
|
function createGoal(opts, at) {
|
|
25221
25563
|
return {
|
|
@@ -25249,7 +25591,7 @@ function rowSpentZeroNoExecution(row2) {
|
|
|
25249
25591
|
function readRunSnapshot(path) {
|
|
25250
25592
|
let text = "";
|
|
25251
25593
|
try {
|
|
25252
|
-
text =
|
|
25594
|
+
text = readFileSync46(path, "utf8");
|
|
25253
25595
|
} catch {
|
|
25254
25596
|
return { rows: [], summary: { cycles: 0, costUsd: 0, costUnknownRows: 0 } };
|
|
25255
25597
|
}
|
|
@@ -25282,7 +25624,7 @@ function readRunSnapshot(path) {
|
|
|
25282
25624
|
}
|
|
25283
25625
|
function readBacklogRows(projectPath3) {
|
|
25284
25626
|
try {
|
|
25285
|
-
return parseBacklog(
|
|
25627
|
+
return parseBacklog(readFileSync46(join44(projectPath3, ".roll", "backlog.md"), "utf8")).map((row2) => ({
|
|
25286
25628
|
id: row2.id,
|
|
25287
25629
|
status: row2.status
|
|
25288
25630
|
}));
|
|
@@ -25292,7 +25634,7 @@ function readBacklogRows(projectPath3) {
|
|
|
25292
25634
|
}
|
|
25293
25635
|
function readStoryIndex(projectPath3) {
|
|
25294
25636
|
try {
|
|
25295
|
-
const obj = JSON.parse(
|
|
25637
|
+
const obj = JSON.parse(readFileSync46(join44(projectPath3, ".roll", "index.json"), "utf8"));
|
|
25296
25638
|
if (typeof obj.stories !== "object" || obj.stories === null || Array.isArray(obj.stories))
|
|
25297
25639
|
return {};
|
|
25298
25640
|
const out3 = {};
|
|
@@ -25629,7 +25971,7 @@ async function evaluateGoal(projectPath3, slug, goal, deps, session, workerAgent
|
|
|
25629
25971
|
function hasSafetyPauseSince(path, since) {
|
|
25630
25972
|
let text = "";
|
|
25631
25973
|
try {
|
|
25632
|
-
text =
|
|
25974
|
+
text = readFileSync46(path, "utf8");
|
|
25633
25975
|
} catch {
|
|
25634
25976
|
return false;
|
|
25635
25977
|
}
|
|
@@ -25759,7 +26101,7 @@ function latestAlertSummary(projectPath3, slug, sinceSec) {
|
|
|
25759
26101
|
try {
|
|
25760
26102
|
if (!existsSync48(path) || statSync15(path).mtimeMs / 1e3 < sinceSec)
|
|
25761
26103
|
return void 0;
|
|
25762
|
-
const lines2 =
|
|
26104
|
+
const lines2 = readFileSync46(path, "utf8").split("\n").map((line2) => line2.trim()).filter((line2) => line2 !== "");
|
|
25763
26105
|
const line = [...lines2].reverse().find((candidate) => /\b(ALERT|WARN|BLOCKED|refused|failed)\b/i.test(candidate));
|
|
25764
26106
|
if (line === void 0)
|
|
25765
26107
|
return void 0;
|
|
@@ -25777,7 +26119,7 @@ function innerLockHolder(projectPath3, nowSec2) {
|
|
|
25777
26119
|
try {
|
|
25778
26120
|
if (!existsSync48(path))
|
|
25779
26121
|
return void 0;
|
|
25780
|
-
const contents = parseLock(
|
|
26122
|
+
const contents = parseLock(readFileSync46(path, "utf8"));
|
|
25781
26123
|
return isLockHeld(contents, nowSec2, INNER_LOCK_STALE_SEC) ? contents.pid : void 0;
|
|
25782
26124
|
} catch {
|
|
25783
26125
|
return void 0;
|
|
@@ -25918,14 +26260,14 @@ function applyTimeboxGate(projectPath3, bus, session, goal, deps, deadlineSec) {
|
|
|
25918
26260
|
}
|
|
25919
26261
|
function installStopHandlers(onStop) {
|
|
25920
26262
|
const signals = ["SIGINT", "SIGTERM", "SIGHUP"];
|
|
25921
|
-
const handlers = signals.map((
|
|
25922
|
-
const handler = () => onStop(
|
|
25923
|
-
process.on(
|
|
25924
|
-
return { signal
|
|
26263
|
+
const handlers = signals.map((signal) => {
|
|
26264
|
+
const handler = () => onStop(signal);
|
|
26265
|
+
process.on(signal, handler);
|
|
26266
|
+
return { signal, handler };
|
|
25925
26267
|
});
|
|
25926
26268
|
return () => {
|
|
25927
|
-
for (const { signal
|
|
25928
|
-
process.off(
|
|
26269
|
+
for (const { signal, handler } of handlers)
|
|
26270
|
+
process.off(signal, handler);
|
|
25929
26271
|
};
|
|
25930
26272
|
}
|
|
25931
26273
|
function describeScope(scope) {
|
|
@@ -25998,9 +26340,9 @@ async function runGoWorker(id, opts, deps) {
|
|
|
25998
26340
|
let stopReason;
|
|
25999
26341
|
let stopRequested = false;
|
|
26000
26342
|
let workerAgents = [];
|
|
26001
|
-
const disposeSignals = installStopHandlers((
|
|
26343
|
+
const disposeSignals = installStopHandlers((signal) => {
|
|
26002
26344
|
stopRequested = true;
|
|
26003
|
-
stopReason = `signal_${
|
|
26345
|
+
stopReason = `signal_${signal}`;
|
|
26004
26346
|
});
|
|
26005
26347
|
try {
|
|
26006
26348
|
const gPath = goalPath2(id.path);
|
|
@@ -26140,7 +26482,7 @@ async function runGoWorker(id, opts, deps) {
|
|
|
26140
26482
|
}
|
|
26141
26483
|
|
|
26142
26484
|
// packages/cli/dist/commands/loop-events.js
|
|
26143
|
-
import { existsSync as existsSync49, readFileSync as
|
|
26485
|
+
import { existsSync as existsSync49, readFileSync as readFileSync47 } from "node:fs";
|
|
26144
26486
|
import { join as join45 } from "node:path";
|
|
26145
26487
|
function str4(v) {
|
|
26146
26488
|
return typeof v === "string" ? v : v === void 0 || v === null ? "" : String(v);
|
|
@@ -26156,7 +26498,7 @@ function loopEventsCommand(argv) {
|
|
|
26156
26498
|
}
|
|
26157
26499
|
let lines2;
|
|
26158
26500
|
try {
|
|
26159
|
-
lines2 =
|
|
26501
|
+
lines2 = readFileSync47(evfile, "utf8").split("\n").filter((l) => l !== "");
|
|
26160
26502
|
} catch {
|
|
26161
26503
|
lines2 = [];
|
|
26162
26504
|
}
|
|
@@ -26194,14 +26536,14 @@ function loopBranchesRetired() {
|
|
|
26194
26536
|
// packages/cli/dist/commands/doctor.js
|
|
26195
26537
|
init_dist();
|
|
26196
26538
|
import { execFileSync as execFileSync11 } from "node:child_process";
|
|
26197
|
-
import { accessSync as accessSync2, constants as constants2, existsSync as existsSync51, mkdtempSync as mkdtempSync3, readFileSync as
|
|
26539
|
+
import { accessSync as accessSync2, constants as constants2, existsSync as existsSync51, mkdtempSync as mkdtempSync3, readFileSync as readFileSync49, readdirSync as readdirSync20, statSync as statSync17, writeFileSync as writeFileSync24 } from "node:fs";
|
|
26198
26540
|
import { homedir as homedir13, tmpdir as tmpdir5 } from "node:os";
|
|
26199
26541
|
import { delimiter as delimiter2, join as join47 } from "node:path";
|
|
26200
26542
|
|
|
26201
26543
|
// packages/cli/dist/commands/skills.js
|
|
26202
26544
|
init_dist();
|
|
26203
26545
|
import { execFileSync as execFileSync10 } from "node:child_process";
|
|
26204
|
-
import { existsSync as existsSync50, mkdtempSync as mkdtempSync2, readFileSync as
|
|
26546
|
+
import { existsSync as existsSync50, mkdtempSync as mkdtempSync2, readFileSync as readFileSync48, readdirSync as readdirSync19, statSync as statSync16, writeFileSync as writeFileSync23 } from "node:fs";
|
|
26205
26547
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
26206
26548
|
import { join as join46 } from "node:path";
|
|
26207
26549
|
function pkgDir() {
|
|
@@ -26221,7 +26563,7 @@ function skillsDir() {
|
|
|
26221
26563
|
return join46(pkgDir(), "skills");
|
|
26222
26564
|
}
|
|
26223
26565
|
function frontmatterField(file, field2) {
|
|
26224
|
-
const lines2 =
|
|
26566
|
+
const lines2 = readFileSync48(file, "utf8").split("\n");
|
|
26225
26567
|
if (lines2.length === 0 || lines2[0] !== "---")
|
|
26226
26568
|
return "";
|
|
26227
26569
|
let collecting = false;
|
|
@@ -26466,7 +26808,7 @@ function bilingual(key) {
|
|
|
26466
26808
|
return [t(v2Catalog, "en", key), t(v2Catalog, "zh", key)];
|
|
26467
26809
|
}
|
|
26468
26810
|
var out2 = { lines: [] };
|
|
26469
|
-
function
|
|
26811
|
+
function emit2(line) {
|
|
26470
26812
|
out2.lines.push(line);
|
|
26471
26813
|
}
|
|
26472
26814
|
function agentBinNames4(agent) {
|
|
@@ -26547,11 +26889,11 @@ function agentSection(p) {
|
|
|
26547
26889
|
const cfg = rollConfigPath4();
|
|
26548
26890
|
if (!existsSync51(cfg))
|
|
26549
26891
|
return;
|
|
26550
|
-
|
|
26892
|
+
emit2("");
|
|
26551
26893
|
for (const l of bilingual("doctor.agent_detection"))
|
|
26552
|
-
|
|
26553
|
-
|
|
26554
|
-
const text =
|
|
26894
|
+
emit2(l);
|
|
26895
|
+
emit2("");
|
|
26896
|
+
const text = readFileSync49(cfg, "utf8");
|
|
26555
26897
|
let primary = "";
|
|
26556
26898
|
for (const line of text.split("\n")) {
|
|
26557
26899
|
const m7 = /^primary_agent:\s*(.*)$/.exec(line);
|
|
@@ -26577,7 +26919,7 @@ function agentSection(p) {
|
|
|
26577
26919
|
const installed = agentInstalledByName4(name, dir) ? t(v2Catalog, msgLang5(), "doctor.agent_installed") : t(v2Catalog, msgLang5(), "doctor.agent_missing");
|
|
26578
26920
|
const dirExists = safeIsDir(dir) ? t(v2Catalog, msgLang5(), "doctor.agent_dir_exists") : t(v2Catalog, msgLang5(), "doctor.agent_dir_missing");
|
|
26579
26921
|
const tag = name === primary ? ` (${t(v2Catalog, msgLang5(), "doctor.agent_primary_label")})` : "";
|
|
26580
|
-
|
|
26922
|
+
emit2(` ${padEnd(name, 10)} ${padEnd(installed, 14)} ${dirExists}${tag}`);
|
|
26581
26923
|
}
|
|
26582
26924
|
}
|
|
26583
26925
|
function ghAvailable3() {
|
|
@@ -26657,28 +26999,28 @@ function prEventHint(lang9) {
|
|
|
26657
26999
|
function prSection(lang9) {
|
|
26658
27000
|
if (!insideGitWorkTree())
|
|
26659
27001
|
return;
|
|
26660
|
-
|
|
27002
|
+
emit2("");
|
|
26661
27003
|
for (const l of bilingual("doctor.pr_review_extras"))
|
|
26662
|
-
|
|
26663
|
-
|
|
27004
|
+
emit2(l);
|
|
27005
|
+
emit2("");
|
|
26664
27006
|
const protection = branchProtectionState();
|
|
26665
27007
|
if (protection === "enabled") {
|
|
26666
|
-
|
|
27008
|
+
emit2(` ${t(v2Catalog, lang9, "doctor.pr_double_gate_enabled")}`);
|
|
26667
27009
|
} else if (protection === "disabled") {
|
|
26668
|
-
|
|
27010
|
+
emit2(` ${t(v2Catalog, lang9, "doctor.pr_double_gate_disabled")}`);
|
|
26669
27011
|
for (const l of prPipelineHint())
|
|
26670
|
-
|
|
27012
|
+
emit2(l);
|
|
26671
27013
|
} else {
|
|
26672
|
-
|
|
27014
|
+
emit2(` ${t(v2Catalog, lang9, "doctor.pr_double_gate_unknown")}`);
|
|
26673
27015
|
for (const l of prPipelineHint())
|
|
26674
|
-
|
|
27016
|
+
emit2(l);
|
|
26675
27017
|
}
|
|
26676
27018
|
if (eventWorkflowState() === "present") {
|
|
26677
|
-
|
|
27019
|
+
emit2(` ${t(v2Catalog, lang9, "doctor.pr_event_enabled")}`);
|
|
26678
27020
|
} else {
|
|
26679
|
-
|
|
27021
|
+
emit2(` ${t(v2Catalog, lang9, "doctor.pr_event_disabled")}`);
|
|
26680
27022
|
for (const l of prEventHint(lang9))
|
|
26681
|
-
|
|
27023
|
+
emit2(l);
|
|
26682
27024
|
}
|
|
26683
27025
|
}
|
|
26684
27026
|
function skillsCatalogSection(lang9) {
|
|
@@ -26686,18 +27028,18 @@ function skillsCatalogSection(lang9) {
|
|
|
26686
27028
|
if (!safeIsDir(skillsDir2))
|
|
26687
27029
|
return;
|
|
26688
27030
|
const target = join47(pkgDir2(), "guide", "skills.md");
|
|
26689
|
-
|
|
27031
|
+
emit2("");
|
|
26690
27032
|
for (const l of bilingual("skills.doctor_heading"))
|
|
26691
|
-
|
|
27033
|
+
emit2(l);
|
|
26692
27034
|
let drift;
|
|
26693
27035
|
if (!existsSync51(target)) {
|
|
26694
27036
|
drift = true;
|
|
26695
27037
|
} else {
|
|
26696
27038
|
const fresh = join47(mkdtempSync3(join47(tmpdir5(), "roll-doctor-")), "skills.md");
|
|
26697
27039
|
writeFileSync24(fresh, generateCatalog());
|
|
26698
|
-
drift =
|
|
27040
|
+
drift = readFileSync49(target, "utf8") !== readFileSync49(fresh, "utf8");
|
|
26699
27041
|
}
|
|
26700
|
-
|
|
27042
|
+
emit2(` ${t(v2Catalog, lang9, drift ? "skills.doctor_drift" : "skills.doctor_ok")}`);
|
|
26701
27043
|
}
|
|
26702
27044
|
function lanesSection(lang9, probe) {
|
|
26703
27045
|
const lines2 = [];
|
|
@@ -26727,7 +27069,7 @@ function lanesSection(lang9, probe) {
|
|
|
26727
27069
|
lines2.push(` \u2192 ${wd === "" ? "(no WorkingDirectory)" : wd}${stale ? lang9 === "zh" ? " [\u76EE\u5F55\u5DF2\u4E0D\u5B58\u5728\u2014\u2014\u9648\u65E7 lane]" : " [missing \u2014 STALE lane]" : ""}`);
|
|
26728
27070
|
}
|
|
26729
27071
|
for (const l of lines2)
|
|
26730
|
-
|
|
27072
|
+
emit2(l);
|
|
26731
27073
|
return lines2;
|
|
26732
27074
|
}
|
|
26733
27075
|
function launchdStaleSection(lang9) {
|
|
@@ -26751,15 +27093,15 @@ function launchdStaleSection(lang9) {
|
|
|
26751
27093
|
if (safeIsDir(wd))
|
|
26752
27094
|
continue;
|
|
26753
27095
|
if (!found) {
|
|
26754
|
-
|
|
26755
|
-
|
|
26756
|
-
|
|
27096
|
+
emit2("");
|
|
27097
|
+
emit2(t(v2Catalog, lang9, "doctor.stale_plists"));
|
|
27098
|
+
emit2("");
|
|
26757
27099
|
found = true;
|
|
26758
27100
|
}
|
|
26759
27101
|
const label4 = name.replace(/\.plist$/, "");
|
|
26760
|
-
|
|
26761
|
-
|
|
26762
|
-
|
|
27102
|
+
emit2(` \u26A0 ${label4}`);
|
|
27103
|
+
emit2(` WorkingDirectory missing: ${wd}`);
|
|
27104
|
+
emit2(` ${t(v2Catalog, lang9, "doctor.stale_plists_cleanup")}: launchctl bootout gui/${process.getuid?.() ?? 0}/${label4}; rm '${plist}'`);
|
|
26763
27105
|
}
|
|
26764
27106
|
}
|
|
26765
27107
|
function realLaneProbe() {
|
|
@@ -26848,23 +27190,23 @@ function launchdProxySection(lang9) {
|
|
|
26848
27190
|
}
|
|
26849
27191
|
if (stale.length === 0)
|
|
26850
27192
|
return;
|
|
26851
|
-
|
|
26852
|
-
|
|
26853
|
-
|
|
26854
|
-
|
|
27193
|
+
emit2("");
|
|
27194
|
+
emit2(t(v3Catalog, "en", "doctor.proxy_env_warning"));
|
|
27195
|
+
emit2(t(v3Catalog, "zh", "doctor.proxy_env_warning"));
|
|
27196
|
+
emit2("");
|
|
26855
27197
|
for (const { name, target } of stale) {
|
|
26856
|
-
|
|
27198
|
+
emit2(` \u26A0 ${name}=${target}`);
|
|
26857
27199
|
}
|
|
26858
|
-
|
|
26859
|
-
|
|
27200
|
+
emit2("");
|
|
27201
|
+
emit2(` ${t(v3Catalog, lang9, "doctor.proxy_env_hint")}`);
|
|
26860
27202
|
for (const { name } of stale) {
|
|
26861
|
-
|
|
27203
|
+
emit2(` launchctl unsetenv ${name}`);
|
|
26862
27204
|
}
|
|
26863
27205
|
}
|
|
26864
27206
|
function readWorkingDirectory(plist) {
|
|
26865
27207
|
let body;
|
|
26866
27208
|
try {
|
|
26867
|
-
body =
|
|
27209
|
+
body = readFileSync49(plist, "utf8");
|
|
26868
27210
|
} catch {
|
|
26869
27211
|
return "";
|
|
26870
27212
|
}
|
|
@@ -26900,11 +27242,11 @@ import { join as join51 } from "node:path";
|
|
|
26900
27242
|
import { spawn as spawn4 } from "node:child_process";
|
|
26901
27243
|
import { join as join48 } from "node:path";
|
|
26902
27244
|
var liveAgents = /* @__PURE__ */ new Set();
|
|
26903
|
-
function killLiveAgents(
|
|
27245
|
+
function killLiveAgents(signal = "SIGKILL") {
|
|
26904
27246
|
let n = 0;
|
|
26905
27247
|
for (const c2 of liveAgents) {
|
|
26906
27248
|
try {
|
|
26907
|
-
if (killHard(c2,
|
|
27249
|
+
if (killHard(c2, signal))
|
|
26908
27250
|
n += 1;
|
|
26909
27251
|
} catch {
|
|
26910
27252
|
}
|
|
@@ -26912,15 +27254,15 @@ function killLiveAgents(signal2 = "SIGKILL") {
|
|
|
26912
27254
|
liveAgents.clear();
|
|
26913
27255
|
return n;
|
|
26914
27256
|
}
|
|
26915
|
-
function killHard(c2,
|
|
27257
|
+
function killHard(c2, signal) {
|
|
26916
27258
|
if (c2.pid !== void 0) {
|
|
26917
27259
|
try {
|
|
26918
|
-
process.kill(-c2.pid,
|
|
27260
|
+
process.kill(-c2.pid, signal);
|
|
26919
27261
|
return true;
|
|
26920
27262
|
} catch {
|
|
26921
27263
|
}
|
|
26922
27264
|
}
|
|
26923
|
-
return c2.kill(
|
|
27265
|
+
return c2.kill(signal);
|
|
26924
27266
|
}
|
|
26925
27267
|
var AUTORUN_DIRECTIVE = "[roll \u81EA\u4E3B\u6A21\u5F0F] \u4F60\u6B63\u5728\u65E0\u4EBA\u503C\u5B88\u7684\u81EA\u52A8\u5316\u5FAA\u73AF\u4E2D\u8FD0\u884C,\u8FD9\u4E0D\u662F\u5BF9\u8BDD\u3002\u8BF7\u7ACB\u5373\u3001\u5B8C\u6574\u5730\u6267\u884C\u4E0B\u9762\u8FD9\u4EFD\u6280\u80FD\u6587\u6863\u63CF\u8FF0\u7684\u5DE5\u4F5C\u6D41,\u76F4\u5230\u5B8C\u6210\u4EA4\u4ED8\u6216\u5199\u51FA ALERT \u4E3A\u6B62;\u4E25\u7981\u53CD\u95EE\u3001\u4E25\u7981\u7B49\u5F85\u786E\u8BA4\u3001\u4E25\u7981\u53EA\u590D\u8FF0\u6216\u603B\u7ED3\u800C\u4E0D\u52A8\u624B\u3002\u6280\u80FD\u6587\u6863\u5982\u4E0B: ";
|
|
26926
27268
|
var AGENT_ARGV_TODO = {
|
|
@@ -26977,7 +27319,7 @@ function buildSpawnCommand(agent, opts) {
|
|
|
26977
27319
|
return { bin: opts.bin ?? "qwen", args: [prompt] };
|
|
26978
27320
|
}
|
|
26979
27321
|
if (agent === "agy" || agent === "gemini" || agent === "antigravity") {
|
|
26980
|
-
return { bin: opts.bin ?? "agy", args: ["
|
|
27322
|
+
return { bin: opts.bin ?? "agy", args: ["--dangerously-skip-permissions", "-p", prompt] };
|
|
26981
27323
|
}
|
|
26982
27324
|
const hint = AGENT_ARGV_TODO[agent] ?? "unknown agent";
|
|
26983
27325
|
throw new Error(`runner: agent '${agent}' argv not yet ported. v2 shape: ${hint}`);
|
|
@@ -27043,8 +27385,8 @@ function spawnAndWait(bin, args, opts, pty = false) {
|
|
|
27043
27385
|
settle({ stdout, stderr: `${stderr}${String(e)}
|
|
27044
27386
|
`, exitCode: 127, timedOut });
|
|
27045
27387
|
});
|
|
27046
|
-
child.on("exit", (code,
|
|
27047
|
-
setImmediate(() => settle({ stdout, stderr, exitCode: code ?? (
|
|
27388
|
+
child.on("exit", (code, signal) => {
|
|
27389
|
+
setImmediate(() => settle({ stdout, stderr, exitCode: code ?? (signal !== null ? 137 : 1), timedOut }));
|
|
27048
27390
|
});
|
|
27049
27391
|
child.on("close", (code) => {
|
|
27050
27392
|
settle({ stdout, stderr, exitCode: code ?? 1, timedOut });
|
|
@@ -27057,7 +27399,7 @@ var realAgentSpawn = (agent, opts) => {
|
|
|
27057
27399
|
};
|
|
27058
27400
|
|
|
27059
27401
|
// packages/cli/dist/runner/skill-body.js
|
|
27060
|
-
import { existsSync as existsSync52, readFileSync as
|
|
27402
|
+
import { existsSync as existsSync52, readFileSync as readFileSync50 } from "node:fs";
|
|
27061
27403
|
import { homedir as homedir14 } from "node:os";
|
|
27062
27404
|
import { join as join49 } from "node:path";
|
|
27063
27405
|
function readSkillBody(projectPath3, opts) {
|
|
@@ -27072,7 +27414,7 @@ function readSkillBody(projectPath3, opts) {
|
|
|
27072
27414
|
continue;
|
|
27073
27415
|
let raw = "";
|
|
27074
27416
|
try {
|
|
27075
|
-
raw =
|
|
27417
|
+
raw = readFileSync50(p, "utf8");
|
|
27076
27418
|
} catch {
|
|
27077
27419
|
continue;
|
|
27078
27420
|
}
|
|
@@ -27474,7 +27816,7 @@ ${rowNote}`);
|
|
|
27474
27816
|
init_dist2();
|
|
27475
27817
|
init_dist();
|
|
27476
27818
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
27477
|
-
import { copyFileSync as copyFileSync2, existsSync as existsSync56, mkdirSync as mkdirSync27, readSync, readFileSync as
|
|
27819
|
+
import { copyFileSync as copyFileSync2, existsSync as existsSync56, mkdirSync as mkdirSync27, readSync, readFileSync as readFileSync51, readdirSync as readdirSync22, realpathSync as realpathSync6, statSync as statSync19, writeFileSync as writeFileSync27 } from "node:fs";
|
|
27478
27820
|
import { homedir as homedir15 } from "node:os";
|
|
27479
27821
|
import { dirname as dirname20, join as join54 } from "node:path";
|
|
27480
27822
|
function registerProject(projectDir) {
|
|
@@ -27550,7 +27892,7 @@ function scanProjectType(dir) {
|
|
|
27550
27892
|
const pkg = join54(dir, "package.json");
|
|
27551
27893
|
const readPkg = () => {
|
|
27552
27894
|
try {
|
|
27553
|
-
return
|
|
27895
|
+
return readFileSync51(pkg, "utf8");
|
|
27554
27896
|
} catch {
|
|
27555
27897
|
return "";
|
|
27556
27898
|
}
|
|
@@ -27695,7 +28037,7 @@ function discoverOnboardAgents() {
|
|
|
27695
28037
|
if (!existsSync56(cfg))
|
|
27696
28038
|
return { installed, missing };
|
|
27697
28039
|
const env = realAgentEnv();
|
|
27698
|
-
for (const line of
|
|
28040
|
+
for (const line of readFileSync51(cfg, "utf8").split("\n")) {
|
|
27699
28041
|
const match = /^(ai_[^:]+):\s*(.*)$/.exec(line);
|
|
27700
28042
|
if (match === null)
|
|
27701
28043
|
continue;
|
|
@@ -27766,7 +28108,7 @@ function readOnboardPrompt() {
|
|
|
27766
28108
|
err8(`Skill file missing: ${skillFile}`);
|
|
27767
28109
|
return null;
|
|
27768
28110
|
}
|
|
27769
|
-
const body =
|
|
28111
|
+
const body = readFileSync51(skillFile, "utf8").replace(/^---\n[\s\S]*?\n---\n?/, "").trim();
|
|
27770
28112
|
return `Run the $roll-onboard skill below for this project. Follow it end-to-end and write .roll/onboard-plan.yaml when done.
|
|
27771
28113
|
|
|
27772
28114
|
${body}`;
|
|
@@ -27901,7 +28243,7 @@ function mergeGlobalToProject(projectDir, summary) {
|
|
|
27901
28243
|
const projectType = scanProjectType(projectDir);
|
|
27902
28244
|
const skipFrontend = ["cli", "backend-service", "unknown"].includes(projectType);
|
|
27903
28245
|
const FRONTEND_HEAD = "## 7. Frontend Default Stack";
|
|
27904
|
-
const srcText =
|
|
28246
|
+
const srcText = readFileSync51(src, "utf8");
|
|
27905
28247
|
const srcLines = srcText.split("\n");
|
|
27906
28248
|
const lines2 = srcText.endsWith("\n") ? srcLines.slice(0, -1) : srcLines;
|
|
27907
28249
|
if (!existsSync56(dst)) {
|
|
@@ -27937,7 +28279,7 @@ ${fcB}`;
|
|
|
27937
28279
|
summary.push("created|AGENTS.md");
|
|
27938
28280
|
return;
|
|
27939
28281
|
}
|
|
27940
|
-
const dstText =
|
|
28282
|
+
const dstText = readFileSync51(dst, "utf8");
|
|
27941
28283
|
let added = 0;
|
|
27942
28284
|
let curH = "";
|
|
27943
28285
|
let curB = "";
|
|
@@ -27986,9 +28328,9 @@ function mergeClaudeToProject(projectDir, summary) {
|
|
|
27986
28328
|
summary.push("created|.claude/CLAUDE.md");
|
|
27987
28329
|
return;
|
|
27988
28330
|
}
|
|
27989
|
-
const tplText =
|
|
28331
|
+
const tplText = readFileSync51(tplFile, "utf8");
|
|
27990
28332
|
const lines2 = tplText.endsWith("\n") ? tplText.split("\n").slice(0, -1) : tplText.split("\n");
|
|
27991
|
-
const outText =
|
|
28333
|
+
const outText = readFileSync51(outFile, "utf8");
|
|
27992
28334
|
let added = 0;
|
|
27993
28335
|
let curH = "";
|
|
27994
28336
|
let curB = "";
|
|
@@ -28222,7 +28564,7 @@ function printMergeSummary(summary) {
|
|
|
28222
28564
|
function seedBacklogRow(backlog, heading, row2, id) {
|
|
28223
28565
|
if (!existsSync56(backlog))
|
|
28224
28566
|
return false;
|
|
28225
|
-
const text =
|
|
28567
|
+
const text = readFileSync51(backlog, "utf8");
|
|
28226
28568
|
if (text.includes(`| ${id} |`))
|
|
28227
28569
|
return false;
|
|
28228
28570
|
const lines2 = text.split("\n");
|
|
@@ -28330,7 +28672,7 @@ function renderAndSeed(projectDir, plan, changeset) {
|
|
|
28330
28672
|
}
|
|
28331
28673
|
function addRollToGitignore(projectDir, changeset) {
|
|
28332
28674
|
const gi = join54(projectDir, ".gitignore");
|
|
28333
|
-
const current = existsSync56(gi) ?
|
|
28675
|
+
const current = existsSync56(gi) ? readFileSync51(gi, "utf8") : "";
|
|
28334
28676
|
if (current.split("\n").includes(".roll/"))
|
|
28335
28677
|
return;
|
|
28336
28678
|
writeFileSync27(gi, current + (current === "" || current.endsWith("\n") ? "" : "\n") + ".roll/\n");
|
|
@@ -28586,28 +28928,52 @@ function initCommand(args) {
|
|
|
28586
28928
|
init_dist2();
|
|
28587
28929
|
import { createInterface as createInterface2 } from "node:readline";
|
|
28588
28930
|
var KIND_COLOR = {
|
|
28931
|
+
lifecycle: "dim",
|
|
28932
|
+
edit: "muted",
|
|
28933
|
+
test: "green",
|
|
28934
|
+
tool: "muted",
|
|
28935
|
+
say: "dim",
|
|
28589
28936
|
tcr: "green",
|
|
28590
|
-
|
|
28591
|
-
ci: "green",
|
|
28592
|
-
peer: "purple",
|
|
28593
|
-
attest: "blue",
|
|
28937
|
+
commit: "green",
|
|
28594
28938
|
pr: "green",
|
|
28939
|
+
gate: "purple",
|
|
28940
|
+
heartbeat: "amber",
|
|
28595
28941
|
alert: "red"
|
|
28596
28942
|
};
|
|
28597
|
-
|
|
28943
|
+
var KIND_CAT = {
|
|
28944
|
+
lifecycle: "\xB7",
|
|
28945
|
+
edit: "\u270F",
|
|
28946
|
+
test: "test",
|
|
28947
|
+
tool: "\u203A",
|
|
28948
|
+
say: "\xB7",
|
|
28949
|
+
tcr: "tcr",
|
|
28950
|
+
commit: "commit",
|
|
28951
|
+
pr: "pr",
|
|
28952
|
+
gate: "gate",
|
|
28953
|
+
heartbeat: "\u2665",
|
|
28954
|
+
alert: "error"
|
|
28955
|
+
};
|
|
28956
|
+
function tierVisible(tier, verbose) {
|
|
28957
|
+
if (verbose)
|
|
28958
|
+
return true;
|
|
28959
|
+
return tier === "A" || tier === "B";
|
|
28960
|
+
}
|
|
28961
|
+
function renderSignal(sig, opts = {}) {
|
|
28598
28962
|
const ts = opts.ts !== void 0 && opts.ts !== "" ? c("muted", opts.ts) + " " : "";
|
|
28599
|
-
if (
|
|
28600
|
-
const detail2 =
|
|
28601
|
-
return `${ts}${c("dim",
|
|
28602
|
-
}
|
|
28603
|
-
if (
|
|
28604
|
-
|
|
28605
|
-
|
|
28606
|
-
|
|
28607
|
-
const
|
|
28608
|
-
const
|
|
28609
|
-
const
|
|
28610
|
-
const
|
|
28963
|
+
if (sig.kind === "lifecycle") {
|
|
28964
|
+
const detail2 = sig.detail !== void 0 && sig.detail !== "" ? c("muted", ` \u2014 ${sig.detail}`) : "";
|
|
28965
|
+
return `${ts}${c("dim", sig.summary)}${detail2}`;
|
|
28966
|
+
}
|
|
28967
|
+
if (sig.kind === "edit" || sig.kind === "tool" || sig.kind === "say") {
|
|
28968
|
+
const cat2 = KIND_CAT[sig.kind];
|
|
28969
|
+
return `${ts}${c("muted", `${cat2} ${sig.summary}`)}`;
|
|
28970
|
+
}
|
|
28971
|
+
const isFail = sig.result === "fail" || sig.kind === "alert";
|
|
28972
|
+
const color = isFail ? "red" : KIND_COLOR[sig.kind];
|
|
28973
|
+
const arrow = sig.kind === "heartbeat" ? c("amber", "\u2665") : c("faint", "\u2192");
|
|
28974
|
+
const cat = c("blue", KIND_CAT[sig.kind].padEnd(6));
|
|
28975
|
+
const label4 = c(color, sig.summary.padEnd(14), { bold: true });
|
|
28976
|
+
const detail = sig.detail !== void 0 && sig.detail !== "" ? " " + c("muted", sig.detail) : "";
|
|
28611
28977
|
return `${ts}${arrow} ${cat} ${label4}${detail}`;
|
|
28612
28978
|
}
|
|
28613
28979
|
function hms() {
|
|
@@ -28615,14 +28981,24 @@ function hms() {
|
|
|
28615
28981
|
const p = (n) => String(n).padStart(2, "0");
|
|
28616
28982
|
return `${p(d.getHours())}:${p(d.getMinutes())}:${p(d.getSeconds())}`;
|
|
28617
28983
|
}
|
|
28618
|
-
var HELP3 = `Usage: roll loop fmt
|
|
28984
|
+
var HELP3 = `Usage: roll loop fmt [--verbose] [--no-color]
|
|
28619
28985
|
|
|
28620
|
-
Reads the agent's raw stream
|
|
28621
|
-
transcript to stdout (the loop observation window).
|
|
28622
|
-
|
|
28623
|
-
|
|
28986
|
+
Reads the running agent's raw stream on stdin and writes a formatted, tiered
|
|
28987
|
+
transcript to stdout (the loop observation window). It selects a per-agent
|
|
28988
|
+
normalizer (claude stream-json \xB7 codex text/jsonl \xB7 generic passthrough),
|
|
28989
|
+
folds each line into a standard activity signal, and renders by tier:
|
|
28990
|
+
surfaces turning points (story / tcr / test / ci / pr / gate / error), folds
|
|
28991
|
+
edits + tools, and beats a heartbeat when the agent goes quiet so the window
|
|
28992
|
+
never looks frozen.
|
|
28993
|
+
\u8BFB\u53D6\u8FD0\u884C\u4E2D agent \u7684\u539F\u59CB\u6D41\uFF0C\u5F52\u4E00\u4E3A\u6807\u51C6\u6D3B\u52A8\u4FE1\u53F7\u540E\u5206\u5C42\u8F93\u51FA\uFF08\u89C2\u6D4B\u7A97\uFF09\u3002
|
|
28994
|
+
\u4EFB\u4F55 agent\uFF08claude/codex/kimi/pi\u2026\uFF09\u90FD\u663E\u793A\u771F\u5B9E\u6D3B\u52A8\uFF0C\u9759\u9ED8\u65F6\u5FC3\u8DF3\u4FDD\u6D3B\u3002
|
|
28624
28995
|
|
|
28625
|
-
|
|
28996
|
+
--verbose, --raw also show tier-C lines (assistant prose / passthrough say)
|
|
28997
|
+
--no-color plain text (also auto-off when stdout is not a TTY)
|
|
28998
|
+
|
|
28999
|
+
The agent is read from $ROLL_LOOP_AGENT (default: claude \u2192 claude normalizer;
|
|
29000
|
+
unknown \u2192 generic). Intended to sit in the watch pipe:
|
|
29001
|
+
tail -F live.log | roll loop fmt
|
|
28626
29002
|
`;
|
|
28627
29003
|
async function loopFmtCommand(args) {
|
|
28628
29004
|
if (args.includes("--help") || args.includes("-h")) {
|
|
@@ -28631,23 +29007,28 @@ async function loopFmtCommand(args) {
|
|
|
28631
29007
|
}
|
|
28632
29008
|
const noColor2 = args.includes("--no-color") || !process.stdout.isTTY || (process.env["NO_COLOR"] ?? "") !== "";
|
|
28633
29009
|
renderState.useColor = !noColor2;
|
|
28634
|
-
const
|
|
28635
|
-
|
|
28636
|
-
|
|
28637
|
-
|
|
28638
|
-
|
|
28639
|
-
|
|
28640
|
-
|
|
29010
|
+
const verbose = args.includes("--verbose") || args.includes("--raw");
|
|
29011
|
+
const agent = (process.env["ROLL_LOOP_AGENT"] ?? "claude").trim() || "claude";
|
|
29012
|
+
const norm = normalizerFor(agent);
|
|
29013
|
+
const st = newNormalizerState();
|
|
29014
|
+
const rl = createInterface2({ input: process.stdin, crlfDelay: Infinity });
|
|
29015
|
+
const gapMs = DEFAULT_HEARTBEAT_GAP_MS;
|
|
29016
|
+
const beat = setInterval(() => {
|
|
29017
|
+
for (const sig of maybeHeartbeat(st, Date.now(), gapMs)) {
|
|
29018
|
+
if (tierVisible(sig.tier, verbose))
|
|
29019
|
+
process.stdout.write(renderSignal(sig, { ts: hms() }) + "\n");
|
|
29020
|
+
}
|
|
29021
|
+
}, Math.min(gapMs, 15e3));
|
|
29022
|
+
beat.unref?.();
|
|
29023
|
+
try {
|
|
29024
|
+
for await (const raw of rl) {
|
|
29025
|
+
for (const sig of norm.normalize(raw, st, Date.now())) {
|
|
29026
|
+
if (tierVisible(sig.tier, verbose))
|
|
29027
|
+
process.stdout.write(renderSignal(sig, { ts: hms() }) + "\n");
|
|
28641
29028
|
}
|
|
28642
29029
|
}
|
|
28643
|
-
|
|
28644
|
-
|
|
28645
|
-
const rl = createInterface2({ input: process.stdin, crlfDelay: Infinity });
|
|
28646
|
-
for await (const raw of rl) {
|
|
28647
|
-
if (raw.trim() === "")
|
|
28648
|
-
continue;
|
|
28649
|
-
process.stdout.write(`${c("muted", hms())} ${c("dim", raw)}
|
|
28650
|
-
`);
|
|
29030
|
+
} finally {
|
|
29031
|
+
clearInterval(beat);
|
|
28651
29032
|
}
|
|
28652
29033
|
return 0;
|
|
28653
29034
|
}
|
|
@@ -28656,7 +29037,7 @@ async function loopFmtCommand(args) {
|
|
|
28656
29037
|
init_dist3();
|
|
28657
29038
|
init_dist();
|
|
28658
29039
|
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
28659
|
-
import { existsSync as existsSync57, mkdirSync as mkdirSync28, readFileSync as
|
|
29040
|
+
import { existsSync as existsSync57, mkdirSync as mkdirSync28, readFileSync as readFileSync52, readdirSync as readdirSync23, renameSync as renameSync8, rmSync as rmSync10, statSync as statSync20, writeFileSync as writeFileSync28 } from "node:fs";
|
|
28660
29041
|
import { homedir as homedir16 } from "node:os";
|
|
28661
29042
|
import { basename as basename11, dirname as dirname21, join as join55 } from "node:path";
|
|
28662
29043
|
function palette3() {
|
|
@@ -28742,7 +29123,7 @@ function fileMtimeSec(f) {
|
|
|
28742
29123
|
}
|
|
28743
29124
|
function plistWorkingDir(plistPath) {
|
|
28744
29125
|
try {
|
|
28745
|
-
const m7 = /<key>WorkingDirectory<\/key>\s*<string>([^<]*)<\/string>/.exec(
|
|
29126
|
+
const m7 = /<key>WorkingDirectory<\/key>\s*<string>([^<]*)<\/string>/.exec(readFileSync52(plistPath, "utf8"));
|
|
28746
29127
|
return m7?.[1] ?? "";
|
|
28747
29128
|
} catch {
|
|
28748
29129
|
return "";
|
|
@@ -28962,14 +29343,14 @@ function loopTestCommand(args = [], deps = realTestDeps()) {
|
|
|
28962
29343
|
// packages/cli/dist/commands/loop-pr-inbox.js
|
|
28963
29344
|
init_dist2();
|
|
28964
29345
|
init_dist3();
|
|
28965
|
-
import { appendFileSync as appendFileSync11, mkdirSync as mkdirSync30, readFileSync as
|
|
29346
|
+
import { appendFileSync as appendFileSync11, mkdirSync as mkdirSync30, readFileSync as readFileSync54, writeFileSync as writeFileSync30, existsSync as existsSync59, rmSync as rmSync12 } from "node:fs";
|
|
28966
29347
|
import { dirname as dirname23, join as join57 } from "node:path";
|
|
28967
29348
|
|
|
28968
29349
|
// packages/cli/dist/commands/loop-pr-heal.js
|
|
28969
29350
|
init_dist2();
|
|
28970
29351
|
init_dist3();
|
|
28971
29352
|
import { execFileSync as execFileSync12, spawn as spawn5 } from "node:child_process";
|
|
28972
|
-
import { appendFileSync as appendFileSync10, existsSync as existsSync58, mkdirSync as mkdirSync29, mkdtempSync as mkdtempSync4, readFileSync as
|
|
29353
|
+
import { appendFileSync as appendFileSync10, existsSync as existsSync58, mkdirSync as mkdirSync29, mkdtempSync as mkdtempSync4, readFileSync as readFileSync53, rmSync as rmSync11, writeFileSync as writeFileSync29 } from "node:fs";
|
|
28973
29354
|
import { tmpdir as tmpdir6 } from "node:os";
|
|
28974
29355
|
import { dirname as dirname22, join as join56 } from "node:path";
|
|
28975
29356
|
function runtimeDir3() {
|
|
@@ -28995,7 +29376,7 @@ function nowIso() {
|
|
|
28995
29376
|
function realHealDeps() {
|
|
28996
29377
|
const readState = () => {
|
|
28997
29378
|
try {
|
|
28998
|
-
return
|
|
29379
|
+
return readFileSync53(statePath(), "utf8");
|
|
28999
29380
|
} catch {
|
|
29000
29381
|
return "";
|
|
29001
29382
|
}
|
|
@@ -29013,7 +29394,7 @@ function realHealDeps() {
|
|
|
29013
29394
|
return { lockPresent: false, lockPidAlive: void 0 };
|
|
29014
29395
|
let alive;
|
|
29015
29396
|
try {
|
|
29016
|
-
const pid = parseInt(
|
|
29397
|
+
const pid = parseInt(readFileSync53(p, "utf8").trim(), 10);
|
|
29017
29398
|
alive = Number.isFinite(pid) ? (() => {
|
|
29018
29399
|
try {
|
|
29019
29400
|
process.kill(pid, 0);
|
|
@@ -29034,7 +29415,7 @@ function realHealDeps() {
|
|
|
29034
29415
|
},
|
|
29035
29416
|
alertHasKey: (key) => {
|
|
29036
29417
|
try {
|
|
29037
|
-
return
|
|
29418
|
+
return readFileSync53(alertPath2(), "utf8").includes(key);
|
|
29038
29419
|
} catch {
|
|
29039
29420
|
return false;
|
|
29040
29421
|
}
|
|
@@ -29252,10 +29633,10 @@ function reducePrView(raw) {
|
|
|
29252
29633
|
}
|
|
29253
29634
|
async function runPrInbox(deps) {
|
|
29254
29635
|
if (!await deps.ghAvailable())
|
|
29255
|
-
return
|
|
29636
|
+
return emit3(deps, prIdleTick("gh_unavailable"));
|
|
29256
29637
|
const slug = await deps.resolveSlug();
|
|
29257
29638
|
if (slug === void 0 || slug === "")
|
|
29258
|
-
return
|
|
29639
|
+
return emit3(deps, prIdleTick("gh_unavailable"));
|
|
29259
29640
|
const list2 = await deps.listOpenPrs(slug);
|
|
29260
29641
|
const stdout = (list2.stdout ?? "").trim();
|
|
29261
29642
|
let openCount = 0;
|
|
@@ -29275,7 +29656,7 @@ async function runPrInbox(deps) {
|
|
|
29275
29656
|
...list2.stderr !== void 0 ? { listStderr: list2.stderr } : {}
|
|
29276
29657
|
});
|
|
29277
29658
|
if (gate !== void 0)
|
|
29278
|
-
return
|
|
29659
|
+
return emit3(deps, gate);
|
|
29279
29660
|
const prs = JSON.parse(stdout);
|
|
29280
29661
|
for (const pr of prs) {
|
|
29281
29662
|
const num4 = String(pr.number ?? "");
|
|
@@ -29311,9 +29692,9 @@ async function runPrInbox(deps) {
|
|
|
29311
29692
|
break;
|
|
29312
29693
|
}
|
|
29313
29694
|
}
|
|
29314
|
-
return
|
|
29695
|
+
return emit3(deps, prActedTick());
|
|
29315
29696
|
}
|
|
29316
|
-
function
|
|
29697
|
+
function emit3(deps, tick) {
|
|
29317
29698
|
deps.writeTick(tick);
|
|
29318
29699
|
return tick;
|
|
29319
29700
|
}
|
|
@@ -29357,7 +29738,7 @@ function writeTickFile(tick) {
|
|
|
29357
29738
|
appendFileSync11(file, `${JSON.stringify({ ts, ...tick })}
|
|
29358
29739
|
`);
|
|
29359
29740
|
try {
|
|
29360
|
-
const lines2 =
|
|
29741
|
+
const lines2 = readFileSync54(file, "utf8").split("\n").filter((l) => l !== "");
|
|
29361
29742
|
if (lines2.length > 500)
|
|
29362
29743
|
writeFileSync30(file, `${lines2.slice(-500).join("\n")}
|
|
29363
29744
|
`);
|
|
@@ -29374,7 +29755,7 @@ function deadTickMarkerPath() {
|
|
|
29374
29755
|
function checkDeadTickStreak(file, alert, markerPath = deadTickMarkerPath()) {
|
|
29375
29756
|
let rows = [];
|
|
29376
29757
|
try {
|
|
29377
|
-
rows =
|
|
29758
|
+
rows = readFileSync54(file, "utf8").split("\n").filter((l) => l.trim() !== "").map((l) => JSON.parse(l));
|
|
29378
29759
|
} catch {
|
|
29379
29760
|
return;
|
|
29380
29761
|
}
|
|
@@ -29410,7 +29791,7 @@ function rebaseCircuitAllowed(num4) {
|
|
|
29410
29791
|
const state = statePath2();
|
|
29411
29792
|
let body = "";
|
|
29412
29793
|
try {
|
|
29413
|
-
body =
|
|
29794
|
+
body = readFileSync54(state, "utf8");
|
|
29414
29795
|
} catch {
|
|
29415
29796
|
}
|
|
29416
29797
|
const verdict = rebaseCircuitVerdict(parseRebaseAttempts(body, num4), nowSec());
|
|
@@ -29476,7 +29857,7 @@ function writeRebaseAttempts(state, pr, timestamps) {
|
|
|
29476
29857
|
mkdirSync30(dirname23(state), { recursive: true });
|
|
29477
29858
|
let body = "";
|
|
29478
29859
|
try {
|
|
29479
|
-
body =
|
|
29860
|
+
body = readFileSync54(state, "utf8");
|
|
29480
29861
|
} catch {
|
|
29481
29862
|
}
|
|
29482
29863
|
writeFileSync30(state, upsertRebaseAttempts(body, pr, renderRebaseAttempts(timestamps)));
|
|
@@ -29558,7 +29939,7 @@ async function loopPrInboxCommand(_args, deps = realDeps6()) {
|
|
|
29558
29939
|
init_dist2();
|
|
29559
29940
|
init_dist();
|
|
29560
29941
|
init_dist3();
|
|
29561
|
-
import { appendFileSync as appendFileSync16, existsSync as existsSync67, mkdirSync as mkdirSync35, readFileSync as
|
|
29942
|
+
import { appendFileSync as appendFileSync16, existsSync as existsSync67, mkdirSync as mkdirSync35, readFileSync as readFileSync63, writeFileSync as writeFileSync36 } from "node:fs";
|
|
29562
29943
|
import { dirname as dirname29, join as join66 } from "node:path";
|
|
29563
29944
|
|
|
29564
29945
|
// packages/cli/dist/runner/executor.js
|
|
@@ -29566,13 +29947,13 @@ init_dist2();
|
|
|
29566
29947
|
init_dist();
|
|
29567
29948
|
init_dist3();
|
|
29568
29949
|
import { execFile as execFile9 } from "node:child_process";
|
|
29569
|
-
import { appendFileSync as appendFileSync13, existsSync as existsSync64, lstatSync as lstatSync3, mkdirSync as mkdirSync32, readdirSync as readdirSync27, readFileSync as
|
|
29950
|
+
import { appendFileSync as appendFileSync13, existsSync as existsSync64, lstatSync as lstatSync3, mkdirSync as mkdirSync32, readdirSync as readdirSync27, readFileSync as readFileSync59, realpathSync as realpathSync7, rmSync as rmSync13, symlinkSync as symlinkSync3, unlinkSync, writeFileSync as writeFileSync32 } from "node:fs";
|
|
29570
29951
|
import { dirname as dirname26, join as join63 } from "node:path";
|
|
29571
29952
|
import { promisify as promisify9 } from "node:util";
|
|
29572
29953
|
|
|
29573
29954
|
// packages/cli/dist/runner/attest-gate.js
|
|
29574
29955
|
init_dist2();
|
|
29575
|
-
import { existsSync as existsSync60, readFileSync as
|
|
29956
|
+
import { existsSync as existsSync60, readFileSync as readFileSync55, readdirSync as readdirSync24, statSync as statSync21 } from "node:fs";
|
|
29576
29957
|
import { dirname as dirname24, join as join58 } from "node:path";
|
|
29577
29958
|
function reportCandidates(worktreeCwd, storyId) {
|
|
29578
29959
|
return [join58(cardArchiveDir(worktreeCwd, storyId), "latest", reportFileName(storyId))];
|
|
@@ -29603,7 +29984,7 @@ function storyHasAcBlock(worktreeCwd, storyId) {
|
|
|
29603
29984
|
if (spec === null)
|
|
29604
29985
|
return null;
|
|
29605
29986
|
try {
|
|
29606
|
-
return acForStory(
|
|
29987
|
+
return acForStory(readFileSync55(spec, "utf8"), storyId, { fileOwned: true }).length > 0;
|
|
29607
29988
|
} catch {
|
|
29608
29989
|
return null;
|
|
29609
29990
|
}
|
|
@@ -29613,7 +29994,7 @@ function storyRequiresScreenshot(worktreeCwd, storyId) {
|
|
|
29613
29994
|
if (spec === null)
|
|
29614
29995
|
return false;
|
|
29615
29996
|
try {
|
|
29616
|
-
return /\b(CLI|web|UI|TUI)\b|界面|交互|截屏|截图|screenshot/i.test(
|
|
29997
|
+
return /\b(CLI|web|UI|TUI)\b|界面|交互|截屏|截图|screenshot/i.test(readFileSync55(spec, "utf8"));
|
|
29617
29998
|
} catch {
|
|
29618
29999
|
return false;
|
|
29619
30000
|
}
|
|
@@ -29623,7 +30004,7 @@ function readAcMapEntries(worktreeCwd, storyId) {
|
|
|
29623
30004
|
if (path === void 0 || !existsSync60(path))
|
|
29624
30005
|
return null;
|
|
29625
30006
|
try {
|
|
29626
|
-
const parsed = JSON.parse(
|
|
30007
|
+
const parsed = JSON.parse(readFileSync55(path, "utf8"));
|
|
29627
30008
|
return Array.isArray(parsed) ? parsed.filter((x) => typeof x === "object" && x !== null) : null;
|
|
29628
30009
|
} catch {
|
|
29629
30010
|
return null;
|
|
@@ -29637,7 +30018,7 @@ function evidenceManifest(worktreeCwd, storyId) {
|
|
|
29637
30018
|
if (!existsSync60(path))
|
|
29638
30019
|
return null;
|
|
29639
30020
|
try {
|
|
29640
|
-
const parsed = JSON.parse(
|
|
30021
|
+
const parsed = JSON.parse(readFileSync55(path, "utf8"));
|
|
29641
30022
|
return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : null;
|
|
29642
30023
|
} catch {
|
|
29643
30024
|
return null;
|
|
@@ -29669,6 +30050,12 @@ function passAcVisualFloor(worktreeCwd, storyId) {
|
|
|
29669
30050
|
const ids = missing.map((e) => e.ac ?? "?").join(", ");
|
|
29670
30051
|
return { ok: false, reason: `pass AC(s) lack screenshot evidence or machine capture skip: ${ids}` };
|
|
29671
30052
|
}
|
|
30053
|
+
function redAcFailures(worktreeCwd, storyId) {
|
|
30054
|
+
const entries = readAcMapEntries(worktreeCwd, storyId);
|
|
30055
|
+
if (entries === null)
|
|
30056
|
+
return [];
|
|
30057
|
+
return entries.filter((e) => e.status === "fail").map((e) => e.ac ?? "?");
|
|
30058
|
+
}
|
|
29672
30059
|
function verificationReportPath(worktreeCwd, storyId) {
|
|
29673
30060
|
return reportCandidates(worktreeCwd, storyId)[0];
|
|
29674
30061
|
}
|
|
@@ -29704,7 +30091,7 @@ function verificationReportHasContent(worktreeCwd, storyId) {
|
|
|
29704
30091
|
if (p === null)
|
|
29705
30092
|
return false;
|
|
29706
30093
|
try {
|
|
29707
|
-
const html =
|
|
30094
|
+
const html = readFileSync55(p, "utf8");
|
|
29708
30095
|
const hasMap = acMapCandidates(worktreeCwd, storyId).some((m7) => existsSync60(m7));
|
|
29709
30096
|
if (!hasMap)
|
|
29710
30097
|
return false;
|
|
@@ -29738,7 +30125,7 @@ function readAttestGateMode(repoCwd) {
|
|
|
29738
30125
|
const p = join58(repoCwd, ".roll", "policy.yaml");
|
|
29739
30126
|
if (!existsSync60(p))
|
|
29740
30127
|
return "hard";
|
|
29741
|
-
return parsePolicy(
|
|
30128
|
+
return parsePolicy(readFileSync55(p, "utf8")).loopSafety.attestGate === "hard" ? "hard" : "soft";
|
|
29742
30129
|
} catch {
|
|
29743
30130
|
return "hard";
|
|
29744
30131
|
}
|
|
@@ -29750,6 +30137,16 @@ function runAttestGate(worktreeCwd, storyId, cycleId, mode, sinceSec, sinks) {
|
|
|
29750
30137
|
sinks.event({ cycleId, verdict: "produced", reasons: reasons2 });
|
|
29751
30138
|
return { verdict: "produced", mode, reasons: reasons2, blocked: false };
|
|
29752
30139
|
}
|
|
30140
|
+
const redAcs = redAcFailures(worktreeCwd, storyId);
|
|
30141
|
+
if (redAcs.length > 0) {
|
|
30142
|
+
const reasons2 = [
|
|
30143
|
+
`acceptance check failed for ${storyId}: ${redAcs.join(", ")} went red \u2014 a failing check is a regression, not an environment issue, so it cannot be waived`
|
|
30144
|
+
];
|
|
30145
|
+
const blocked2 = mode === "hard";
|
|
30146
|
+
sinks.alert(`attest gate (${mode}): acceptance check failed (${storyId}) \u2014 ${redAcs.join(", ")} went red; a red check is a regression and is never waived as environmental \u2014 cycle ${cycleId}` + (blocked2 ? " \u2014 BLOCKED (hard mode); story not marked Done" : ""));
|
|
30147
|
+
sinks.event({ cycleId, verdict: "skipped", reasons: reasons2 });
|
|
30148
|
+
return { verdict: "skipped", mode, reasons: reasons2, blocked: blocked2 };
|
|
30149
|
+
}
|
|
29753
30150
|
const fresh = verificationReportFresh(worktreeCwd, storyId, sinceSec);
|
|
29754
30151
|
if (fresh && verificationReportHasContent(worktreeCwd, storyId)) {
|
|
29755
30152
|
const score = evaluateSelfScoreGate(worktreeCwd, storyId);
|
|
@@ -29780,7 +30177,7 @@ function runAttestGate(worktreeCwd, storyId, cycleId, mode, sinceSec, sinks) {
|
|
|
29780
30177
|
|
|
29781
30178
|
// packages/cli/dist/runner/usage-recovery.js
|
|
29782
30179
|
init_dist2();
|
|
29783
|
-
import { readFileSync as
|
|
30180
|
+
import { readFileSync as readFileSync56, readdirSync as readdirSync25, statSync as statSync22 } from "node:fs";
|
|
29784
30181
|
import { homedir as homedir17 } from "node:os";
|
|
29785
30182
|
import { join as join59 } from "node:path";
|
|
29786
30183
|
function defaultPiSessionsRoot() {
|
|
@@ -29803,7 +30200,7 @@ function recoverPiUsage(worktreeCwd, sinceSec, sessionsRoot = defaultPiSessionsR
|
|
|
29803
30200
|
try {
|
|
29804
30201
|
if (sinceSec !== void 0 && statSync22(p).mtimeMs / 1e3 < sinceSec)
|
|
29805
30202
|
continue;
|
|
29806
|
-
summaries.push(sumPiSession(
|
|
30203
|
+
summaries.push(sumPiSession(readFileSync56(p, "utf8").split("\n")));
|
|
29807
30204
|
} catch {
|
|
29808
30205
|
}
|
|
29809
30206
|
}
|
|
@@ -29824,14 +30221,14 @@ function recoverPiUsage(worktreeCwd, sinceSec, sessionsRoot = defaultPiSessionsR
|
|
|
29824
30221
|
|
|
29825
30222
|
// packages/cli/dist/runner/budget-check.js
|
|
29826
30223
|
init_dist2();
|
|
29827
|
-
import { existsSync as existsSync61, readFileSync as
|
|
30224
|
+
import { existsSync as existsSync61, readFileSync as readFileSync57 } from "node:fs";
|
|
29828
30225
|
import { join as join60 } from "node:path";
|
|
29829
30226
|
function readBudgetPolicy(repoCwd) {
|
|
29830
30227
|
try {
|
|
29831
30228
|
const p = join60(repoCwd, ".roll", "policy.yaml");
|
|
29832
30229
|
if (!existsSync61(p))
|
|
29833
30230
|
return void 0;
|
|
29834
|
-
return parsePolicy(
|
|
30231
|
+
return parsePolicy(readFileSync57(p, "utf8")).loopSafety.budget;
|
|
29835
30232
|
} catch {
|
|
29836
30233
|
return void 0;
|
|
29837
30234
|
}
|
|
@@ -29840,7 +30237,7 @@ function ledgerFromRuns(runsPath3) {
|
|
|
29840
30237
|
const ledger = new BudgetLedger();
|
|
29841
30238
|
let body;
|
|
29842
30239
|
try {
|
|
29843
|
-
body =
|
|
30240
|
+
body = readFileSync57(runsPath3, "utf8");
|
|
29844
30241
|
} catch {
|
|
29845
30242
|
return ledger;
|
|
29846
30243
|
}
|
|
@@ -29926,21 +30323,21 @@ function buildAcMapRemediationPrompt(worktreeCwd, storyId, runDir) {
|
|
|
29926
30323
|
// packages/cli/dist/runner/correction-actuator.js
|
|
29927
30324
|
init_dist2();
|
|
29928
30325
|
init_dist();
|
|
29929
|
-
import { appendFileSync as appendFileSync12, existsSync as existsSync63, mkdirSync as mkdirSync31, readFileSync as
|
|
30326
|
+
import { appendFileSync as appendFileSync12, existsSync as existsSync63, mkdirSync as mkdirSync31, readFileSync as readFileSync58, readdirSync as readdirSync26, writeFileSync as writeFileSync31 } from "node:fs";
|
|
29930
30327
|
import { dirname as dirname25, join as join62 } from "node:path";
|
|
29931
30328
|
function readMode(projectPath3) {
|
|
29932
30329
|
try {
|
|
29933
30330
|
const path = join62(projectPath3, ".roll", "policy.yaml");
|
|
29934
30331
|
if (!existsSync63(path))
|
|
29935
30332
|
return "conservative";
|
|
29936
|
-
return parsePolicy(
|
|
30333
|
+
return parsePolicy(readFileSync58(path, "utf8")).loopSafety.correctionActuator;
|
|
29937
30334
|
} catch {
|
|
29938
30335
|
return "conservative";
|
|
29939
30336
|
}
|
|
29940
30337
|
}
|
|
29941
30338
|
function readEvents(eventsPath2) {
|
|
29942
30339
|
try {
|
|
29943
|
-
return
|
|
30340
|
+
return readFileSync58(eventsPath2, "utf8").split("\n").map(parseEventLine).filter((ev) => ev !== null);
|
|
29944
30341
|
} catch {
|
|
29945
30342
|
return [];
|
|
29946
30343
|
}
|
|
@@ -29979,7 +30376,7 @@ function markStoryTodo(projectPath3, storyId) {
|
|
|
29979
30376
|
}
|
|
29980
30377
|
function storyEpic(projectPath3, storyId) {
|
|
29981
30378
|
try {
|
|
29982
|
-
const idx = JSON.parse(
|
|
30379
|
+
const idx = JSON.parse(readFileSync58(join62(projectPath3, ".roll", "index.json"), "utf8"));
|
|
29983
30380
|
const epic = idx[storyId];
|
|
29984
30381
|
if (typeof epic === "string" && epic.trim() !== "")
|
|
29985
30382
|
return epic;
|
|
@@ -29997,7 +30394,7 @@ function storyEpic(projectPath3, storyId) {
|
|
|
29997
30394
|
}
|
|
29998
30395
|
return "uncategorized";
|
|
29999
30396
|
}
|
|
30000
|
-
function existingFixId(projectPath3, storyId,
|
|
30397
|
+
function existingFixId(projectPath3, storyId, signal) {
|
|
30001
30398
|
try {
|
|
30002
30399
|
const snap = new BacklogStore().readBacklog(join62(projectPath3, ".roll", "backlog.md"));
|
|
30003
30400
|
return snap.items.find((it) => {
|
|
@@ -30008,7 +30405,7 @@ function existingFixId(projectPath3, storyId, signal2) {
|
|
|
30008
30405
|
return false;
|
|
30009
30406
|
if (!desc.includes(`fixes:${storyId.toLowerCase()}`))
|
|
30010
30407
|
return false;
|
|
30011
|
-
if (!desc.includes(`signal:${
|
|
30408
|
+
if (!desc.includes(`signal:${signal.toLowerCase()}`))
|
|
30012
30409
|
return false;
|
|
30013
30410
|
return classifyStatus(it.status) !== "done";
|
|
30014
30411
|
})?.id;
|
|
@@ -30016,8 +30413,8 @@ function existingFixId(projectPath3, storyId, signal2) {
|
|
|
30016
30413
|
return void 0;
|
|
30017
30414
|
}
|
|
30018
30415
|
}
|
|
30019
|
-
function fixDescription(storyId,
|
|
30020
|
-
return `autofix [roll:manual-merge] fixes:${storyId} signal:${
|
|
30416
|
+
function fixDescription(storyId, signal) {
|
|
30417
|
+
return `autofix [roll:manual-merge] fixes:${storyId} signal:${signal} evidence correction`;
|
|
30021
30418
|
}
|
|
30022
30419
|
function writeFixSpec(projectPath3, epic, fixId, decision) {
|
|
30023
30420
|
try {
|
|
@@ -30344,7 +30741,45 @@ ${res.stderr}
|
|
|
30344
30741
|
tcrCount = await ports.git.tcrCount(ports.paths.worktreePath);
|
|
30345
30742
|
} catch {
|
|
30346
30743
|
}
|
|
30347
|
-
|
|
30744
|
+
const reviewPeer = async (peer, diff, timeoutMs) => {
|
|
30745
|
+
const prompt = `You are a heterogeneous PAIRING reviewer. A different agent wrote the diff below; give it a terse second-pair-of-eyes review (correctness, edge cases, quality). End with exactly one line "VERDICT: agree|refine|object" and one "FINDING: <issue>" line per concrete issue.
|
|
30746
|
+
|
|
30747
|
+
DIFF:
|
|
30748
|
+
` + diff;
|
|
30749
|
+
let res;
|
|
30750
|
+
try {
|
|
30751
|
+
res = await Promise.race([
|
|
30752
|
+
ports.agentSpawn(peer, {
|
|
30753
|
+
cwd: ports.paths.worktreePath,
|
|
30754
|
+
skillBody: prompt,
|
|
30755
|
+
timeoutMs,
|
|
30756
|
+
...ctx.evidenceRunDir !== void 0 ? { runDir: ctx.evidenceRunDir } : {}
|
|
30757
|
+
}),
|
|
30758
|
+
new Promise((resolve5) => setTimeout(() => resolve5(null), timeoutMs).unref())
|
|
30759
|
+
]);
|
|
30760
|
+
} catch {
|
|
30761
|
+
return null;
|
|
30762
|
+
}
|
|
30763
|
+
if (res === null || res.timedOut || res.exitCode !== 0)
|
|
30764
|
+
return null;
|
|
30765
|
+
const vm = /VERDICT:\s*(agree|refine|object)/i.exec(res.stdout);
|
|
30766
|
+
const verdict = vm?.[1]?.toLowerCase() ?? "agree";
|
|
30767
|
+
const findings = [...res.stdout.matchAll(/^\s*FINDING:\s*(.+)$/gim)].map((m7) => (m7[1] ?? "").trim());
|
|
30768
|
+
const cost = peerReviewCost(peer, res.stdout);
|
|
30769
|
+
return { verdict, findings, cost };
|
|
30770
|
+
};
|
|
30771
|
+
const cycleDiff = async (cwd) => {
|
|
30772
|
+
try {
|
|
30773
|
+
const { stdout } = await execFileAsync9("git", ["diff", "origin/main...HEAD"], { cwd, encoding: "utf8" });
|
|
30774
|
+
return stdout.slice(0, 6e4);
|
|
30775
|
+
} catch {
|
|
30776
|
+
return "";
|
|
30777
|
+
}
|
|
30778
|
+
};
|
|
30779
|
+
const peerGateMode = readPeerGateMode(ports.repoCwd);
|
|
30780
|
+
const runtimeDir6 = dirname26(ports.paths.eventsPath);
|
|
30781
|
+
const cycleIdStr = ctx.cycleId ?? "";
|
|
30782
|
+
const peerGateSinks = {
|
|
30348
30783
|
alert: (m7) => ports.events.appendAlert(ports.paths.alertsPath, m7),
|
|
30349
30784
|
event: (p) => ports.events.appendEvent(ports.paths.eventsPath, {
|
|
30350
30785
|
type: "peer:gate",
|
|
@@ -30353,58 +30788,44 @@ ${res.stderr}
|
|
|
30353
30788
|
reasons: p.reasons,
|
|
30354
30789
|
ts: ports.clock()
|
|
30355
30790
|
})
|
|
30356
|
-
}
|
|
30791
|
+
};
|
|
30792
|
+
let peerGate = await runPeerGate(ports.paths.worktreePath, runtimeDir6, cycleIdStr, peerGateMode, peerGateSinks);
|
|
30793
|
+
let peerBlocked = peerGate.blocked;
|
|
30794
|
+
if (peerGate.blocked) {
|
|
30795
|
+
const retry = await retryPeerConsult(ports.paths.worktreePath, runtimeDir6, cycleIdStr, {
|
|
30796
|
+
installed: ports.installedAgents?.() ?? agentsInstalled(realAgentEnv()),
|
|
30797
|
+
workingAgent: ctx.agent ?? "claude",
|
|
30798
|
+
reviewPeer,
|
|
30799
|
+
diff: cycleDiff,
|
|
30800
|
+
event: (e) => ports.events.appendEvent(ports.paths.eventsPath, e),
|
|
30801
|
+
now: () => ports.clock()
|
|
30802
|
+
});
|
|
30803
|
+
if (retry.status === "reviewed" && peerEvidencePresent(runtimeDir6, cycleIdStr)) {
|
|
30804
|
+
peerGate = await runPeerGate(ports.paths.worktreePath, runtimeDir6, cycleIdStr, peerGateMode, peerGateSinks);
|
|
30805
|
+
peerBlocked = peerGate.blocked;
|
|
30806
|
+
}
|
|
30807
|
+
if (peerBlocked) {
|
|
30808
|
+
const how = retry.sameTypeFallback === true ? "same-type separate-session review" : "peer review";
|
|
30809
|
+
ports.events.appendAlert(ports.paths.alertsPath, `peer gate (hard): high-complexity work still without peer evidence after one retry \u2014 the ${how} produced no evidence (${retry.status}) \u2014 cycle ${cycleIdStr} BLOCKED; story not marked Done`);
|
|
30810
|
+
}
|
|
30811
|
+
}
|
|
30357
30812
|
{
|
|
30358
|
-
const reviewPeer = async (peer, diff, timeoutMs) => {
|
|
30359
|
-
const prompt = `You are a heterogeneous PAIRING reviewer. A different agent wrote the diff below; give it a terse second-pair-of-eyes review (correctness, edge cases, quality). End with exactly one line "VERDICT: agree|refine|object" and one "FINDING: <issue>" line per concrete issue.
|
|
30360
|
-
|
|
30361
|
-
DIFF:
|
|
30362
|
-
` + diff;
|
|
30363
|
-
let res;
|
|
30364
|
-
try {
|
|
30365
|
-
res = await Promise.race([
|
|
30366
|
-
ports.agentSpawn(peer, {
|
|
30367
|
-
cwd: ports.paths.worktreePath,
|
|
30368
|
-
skillBody: prompt,
|
|
30369
|
-
timeoutMs,
|
|
30370
|
-
...ctx.evidenceRunDir !== void 0 ? { runDir: ctx.evidenceRunDir } : {}
|
|
30371
|
-
}),
|
|
30372
|
-
new Promise((resolve5) => setTimeout(() => resolve5(null), timeoutMs).unref())
|
|
30373
|
-
]);
|
|
30374
|
-
} catch {
|
|
30375
|
-
return null;
|
|
30376
|
-
}
|
|
30377
|
-
if (res === null || res.timedOut || res.exitCode !== 0)
|
|
30378
|
-
return null;
|
|
30379
|
-
const vm = /VERDICT:\s*(agree|refine|object)/i.exec(res.stdout);
|
|
30380
|
-
const verdict = vm?.[1]?.toLowerCase() ?? "agree";
|
|
30381
|
-
const findings = [...res.stdout.matchAll(/^\s*FINDING:\s*(.+)$/gim)].map((m7) => (m7[1] ?? "").trim());
|
|
30382
|
-
const cost = peerReviewCost(peer, res.stdout);
|
|
30383
|
-
return { verdict, findings, cost };
|
|
30384
|
-
};
|
|
30385
30813
|
let pairHistory;
|
|
30386
30814
|
try {
|
|
30387
30815
|
if (existsSync64(ports.paths.eventsPath)) {
|
|
30388
|
-
const events =
|
|
30816
|
+
const events = readFileSync59(ports.paths.eventsPath, "utf8").split("\n").map(parseEventLine).filter((e) => e !== null);
|
|
30389
30817
|
pairHistory = pairingHistory(events);
|
|
30390
30818
|
}
|
|
30391
30819
|
} catch {
|
|
30392
30820
|
}
|
|
30393
30821
|
const pairingDeps = {
|
|
30394
|
-
installed: agentsInstalled(realAgentEnv()),
|
|
30822
|
+
installed: ports.installedAgents?.() ?? agentsInstalled(realAgentEnv()),
|
|
30395
30823
|
isAvailable: () => true,
|
|
30396
30824
|
// MVP: `installed` is the hard gate; a dead peer → reviewPeer null (non-blocking). Real probe is a refinement.
|
|
30397
30825
|
reviewPeer,
|
|
30398
30826
|
...pairHistory !== void 0 ? { history: pairHistory } : {},
|
|
30399
30827
|
changedFiles: cycleChangedFiles,
|
|
30400
|
-
diff:
|
|
30401
|
-
try {
|
|
30402
|
-
const { stdout } = await execFileAsync9("git", ["diff", "origin/main...HEAD"], { cwd, encoding: "utf8" });
|
|
30403
|
-
return stdout.slice(0, 6e4);
|
|
30404
|
-
} catch {
|
|
30405
|
-
return "";
|
|
30406
|
-
}
|
|
30407
|
-
},
|
|
30828
|
+
diff: cycleDiff,
|
|
30408
30829
|
event: (e) => ports.events.appendEvent(ports.paths.eventsPath, e),
|
|
30409
30830
|
now: () => ports.clock()
|
|
30410
30831
|
};
|
|
@@ -30517,10 +30938,13 @@ ${diffStat}`;
|
|
|
30517
30938
|
}
|
|
30518
30939
|
const facts = {
|
|
30519
30940
|
usedWorktree: true,
|
|
30520
|
-
// accept-path reaches capture at exit 0; a HARD attest block fails
|
|
30521
|
-
// capture (classifyCaptured: exit ≠ 0 → failed) so Done is withheld
|
|
30522
|
-
//
|
|
30523
|
-
|
|
30941
|
+
// accept-path reaches capture at exit 0; a HARD attest OR peer block fails
|
|
30942
|
+
// the capture (classifyCaptured: exit ≠ 0 → failed) so Done is withheld.
|
|
30943
|
+
// FIX-293: a high-complexity delivery with no peer review (even after the
|
|
30944
|
+
// one retry) is peerBlocked → it MUST NOT self-score / flip Done. The
|
|
30945
|
+
// FIX-244 PR-state "published" reclassification stays scoped to the attest
|
|
30946
|
+
// block (a peer-blocked cycle still owes peer review; Done≡merged anyway).
|
|
30947
|
+
agentExit: attestBlocked || peerBlocked ? 1 : 0,
|
|
30524
30948
|
timedOut: false,
|
|
30525
30949
|
commitsAhead,
|
|
30526
30950
|
...mainAhead > 0 ? { mainAhead } : {},
|
|
@@ -30732,7 +31156,7 @@ function readRunsRows(runsPath3) {
|
|
|
30732
31156
|
try {
|
|
30733
31157
|
if (!existsSync64(runsPath3))
|
|
30734
31158
|
return [];
|
|
30735
|
-
return
|
|
31159
|
+
return readFileSync59(runsPath3, "utf8").split("\n").filter((l) => l.trim() !== "").map((l) => {
|
|
30736
31160
|
try {
|
|
30737
31161
|
return JSON.parse(l);
|
|
30738
31162
|
} catch {
|
|
@@ -30755,14 +31179,14 @@ function storyRequiresManualMerge(repoCwd, storyId) {
|
|
|
30755
31179
|
return needles.some((n) => lower.includes(n));
|
|
30756
31180
|
};
|
|
30757
31181
|
try {
|
|
30758
|
-
const backlog =
|
|
31182
|
+
const backlog = readFileSync59(join63(repoCwd, ".roll", "backlog.md"), "utf8");
|
|
30759
31183
|
const row2 = parseBacklog(backlog).find((it) => it.id === storyId);
|
|
30760
31184
|
if (row2 !== void 0 && containsMarker(row2.desc))
|
|
30761
31185
|
return true;
|
|
30762
31186
|
} catch {
|
|
30763
31187
|
}
|
|
30764
31188
|
try {
|
|
30765
|
-
return containsMarker(
|
|
31189
|
+
return containsMarker(readFileSync59(join63(cardArchiveDir(repoCwd, storyId), "spec.md"), "utf8"));
|
|
30766
31190
|
} catch {
|
|
30767
31191
|
return false;
|
|
30768
31192
|
}
|
|
@@ -30801,7 +31225,7 @@ function persistWorktreeAlerts(worktreePath, alertsPath, events) {
|
|
|
30801
31225
|
const path = join63(worktreePath, name);
|
|
30802
31226
|
if (!lstatSync3(path).isFile())
|
|
30803
31227
|
continue;
|
|
30804
|
-
const body =
|
|
31228
|
+
const body = readFileSync59(path, "utf8").trim();
|
|
30805
31229
|
if (body === "")
|
|
30806
31230
|
continue;
|
|
30807
31231
|
events.appendAlert(alertsPath, `# worktree alert persisted: ${name}
|
|
@@ -30831,7 +31255,7 @@ async function linkRollIntoWorktree(repoCwd, worktreePath) {
|
|
|
30831
31255
|
if (common === "")
|
|
30832
31256
|
return;
|
|
30833
31257
|
const exclude = join63(common, "info", "exclude");
|
|
30834
|
-
const cur = existsSync64(exclude) ?
|
|
31258
|
+
const cur = existsSync64(exclude) ? readFileSync59(exclude, "utf8") : "";
|
|
30835
31259
|
if (!/^\.roll$/m.test(cur)) {
|
|
30836
31260
|
mkdirSync32(dirname26(exclude), { recursive: true });
|
|
30837
31261
|
appendFileSync13(exclude, `${cur === "" || cur.endsWith("\n") ? "" : "\n"}.roll
|
|
@@ -30955,7 +31379,7 @@ function nodePorts(opts) {
|
|
|
30955
31379
|
const p = join63(projectCwd, ".roll", "backlog.md");
|
|
30956
31380
|
if (!existsSync64(p))
|
|
30957
31381
|
return [];
|
|
30958
|
-
return parseBacklog(
|
|
31382
|
+
return parseBacklog(readFileSync59(p, "utf8"));
|
|
30959
31383
|
},
|
|
30960
31384
|
// FIX-198: the production binding was MISSING entirely (the optional
|
|
30961
31385
|
// chain made every In-Progress claim a silent no-op). ID-anchored mark
|
|
@@ -31188,21 +31612,21 @@ function describeCommand(cmd) {
|
|
|
31188
31612
|
// packages/cli/dist/runner/correction-circuit.js
|
|
31189
31613
|
init_dist2();
|
|
31190
31614
|
init_dist();
|
|
31191
|
-
import { appendFileSync as appendFileSync14, existsSync as existsSync65, mkdirSync as mkdirSync33, readFileSync as
|
|
31615
|
+
import { appendFileSync as appendFileSync14, existsSync as existsSync65, mkdirSync as mkdirSync33, readFileSync as readFileSync60, writeFileSync as writeFileSync33 } from "node:fs";
|
|
31192
31616
|
import { dirname as dirname27, join as join64 } from "node:path";
|
|
31193
31617
|
function readLoopSafety(projectPath3) {
|
|
31194
31618
|
try {
|
|
31195
31619
|
const path = join64(projectPath3, ".roll", "policy.yaml");
|
|
31196
31620
|
if (!existsSync65(path))
|
|
31197
31621
|
return parsePolicy("").loopSafety;
|
|
31198
|
-
return parsePolicy(
|
|
31622
|
+
return parsePolicy(readFileSync60(path, "utf8")).loopSafety;
|
|
31199
31623
|
} catch {
|
|
31200
31624
|
return parsePolicy("").loopSafety;
|
|
31201
31625
|
}
|
|
31202
31626
|
}
|
|
31203
31627
|
function readEvents2(eventsPath2) {
|
|
31204
31628
|
try {
|
|
31205
|
-
return
|
|
31629
|
+
return readFileSync60(eventsPath2, "utf8").split("\n").map(parseEventLine).filter((ev) => ev !== null);
|
|
31206
31630
|
} catch {
|
|
31207
31631
|
return [];
|
|
31208
31632
|
}
|
|
@@ -31259,7 +31683,7 @@ function applyCorrectionCircuitBreaker(projectPath3, slug, eventsPath2, alertsPa
|
|
|
31259
31683
|
// packages/cli/dist/lib/morning-report.js
|
|
31260
31684
|
init_dist2();
|
|
31261
31685
|
init_dist();
|
|
31262
|
-
import { appendFileSync as appendFileSync15, existsSync as existsSync66, mkdirSync as mkdirSync34, readFileSync as
|
|
31686
|
+
import { appendFileSync as appendFileSync15, existsSync as existsSync66, mkdirSync as mkdirSync34, readFileSync as readFileSync61, writeFileSync as writeFileSync34 } from "node:fs";
|
|
31263
31687
|
import { dirname as dirname28, join as join65 } from "node:path";
|
|
31264
31688
|
var esc7 = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
31265
31689
|
function iso2(sec) {
|
|
@@ -31267,14 +31691,14 @@ function iso2(sec) {
|
|
|
31267
31691
|
}
|
|
31268
31692
|
function readEvents3(path) {
|
|
31269
31693
|
try {
|
|
31270
|
-
return
|
|
31694
|
+
return readFileSync61(path, "utf8").split("\n").map(parseEventLine).filter((ev) => ev !== null);
|
|
31271
31695
|
} catch {
|
|
31272
31696
|
return [];
|
|
31273
31697
|
}
|
|
31274
31698
|
}
|
|
31275
31699
|
function readRuns(path) {
|
|
31276
31700
|
try {
|
|
31277
|
-
return
|
|
31701
|
+
return readFileSync61(path, "utf8").split("\n").map((line) => line.trim()).filter((line) => line !== "").map((line) => JSON.parse(line));
|
|
31278
31702
|
} catch {
|
|
31279
31703
|
return [];
|
|
31280
31704
|
}
|
|
@@ -31346,7 +31770,7 @@ function writeLatestMorningReport(projectPath3, eventsPath2, runsPath3, nowSec2
|
|
|
31346
31770
|
// packages/cli/dist/lib/runs-backfill.js
|
|
31347
31771
|
init_dist2();
|
|
31348
31772
|
init_dist3();
|
|
31349
|
-
import { readFileSync as
|
|
31773
|
+
import { readFileSync as readFileSync62, writeFileSync as writeFileSync35 } from "node:fs";
|
|
31350
31774
|
var BACKFILL_PROBE_CAP = 20;
|
|
31351
31775
|
function parseLine(raw) {
|
|
31352
31776
|
if (raw.trim() === "")
|
|
@@ -31368,7 +31792,7 @@ function isCandidate(row2) {
|
|
|
31368
31792
|
async function backfillMergedRuns(projectPath3, runsPath3, deps = {}) {
|
|
31369
31793
|
let body;
|
|
31370
31794
|
try {
|
|
31371
|
-
body =
|
|
31795
|
+
body = readFileSync62(runsPath3, "utf8");
|
|
31372
31796
|
} catch {
|
|
31373
31797
|
return [];
|
|
31374
31798
|
}
|
|
@@ -31456,7 +31880,7 @@ function cycleSignalTeardown(paths, cycleId, branch, sig, deps = {}) {
|
|
|
31456
31880
|
}
|
|
31457
31881
|
let owned = false;
|
|
31458
31882
|
try {
|
|
31459
|
-
owned = existsSync67(paths.lockPath) && parseLock(
|
|
31883
|
+
owned = existsSync67(paths.lockPath) && parseLock(readFileSync63(paths.lockPath, "utf8")).pid === pid;
|
|
31460
31884
|
} catch {
|
|
31461
31885
|
owned = false;
|
|
31462
31886
|
}
|
|
@@ -31541,7 +31965,7 @@ function incrementConsecutiveFails(projectPath3, slug, alertsPath, eventsPath2,
|
|
|
31541
31965
|
let count = 0;
|
|
31542
31966
|
try {
|
|
31543
31967
|
if (existsSync67(counterFile)) {
|
|
31544
|
-
count = parseInt(
|
|
31968
|
+
count = parseInt(readFileSync63(counterFile, "utf8").trim(), 10) || 0;
|
|
31545
31969
|
}
|
|
31546
31970
|
} catch {
|
|
31547
31971
|
}
|
|
@@ -31593,7 +32017,7 @@ function readFailurePauseThreshold(projectPath3) {
|
|
|
31593
32017
|
const policy = join66(projectPath3, ".roll", "policy.yaml");
|
|
31594
32018
|
if (!existsSync67(policy))
|
|
31595
32019
|
return PAUSE_THRESHOLD;
|
|
31596
|
-
return parsePolicy(
|
|
32020
|
+
return parsePolicy(readFileSync63(policy, "utf8")).loopSafety.maxConsecutiveFailures;
|
|
31597
32021
|
} catch {
|
|
31598
32022
|
return PAUSE_THRESHOLD;
|
|
31599
32023
|
}
|
|
@@ -31618,7 +32042,7 @@ function buildLoopRouteDeps(projectPath3) {
|
|
|
31618
32042
|
function readSlot(slot) {
|
|
31619
32043
|
const agentsYaml = join66(projectPath3, ".roll", "agents.yaml");
|
|
31620
32044
|
try {
|
|
31621
|
-
return readSlotFromText(
|
|
32045
|
+
return readSlotFromText(readFileSync63(agentsYaml, "utf8"), slot);
|
|
31622
32046
|
} catch {
|
|
31623
32047
|
return void 0;
|
|
31624
32048
|
}
|
|
@@ -31633,7 +32057,7 @@ function buildLoopRouteDeps(projectPath3) {
|
|
|
31633
32057
|
}
|
|
31634
32058
|
function readField(path, re) {
|
|
31635
32059
|
try {
|
|
31636
|
-
const text =
|
|
32060
|
+
const text = readFileSync63(path, "utf8");
|
|
31637
32061
|
for (const line of text.split("\n")) {
|
|
31638
32062
|
const m7 = line.match(re);
|
|
31639
32063
|
if (m7 !== null) {
|
|
@@ -31862,7 +32286,7 @@ async function egressBlocked(resolve5 = (h) => lookup(h), tcpProbe2 = () => tcpC
|
|
|
31862
32286
|
// packages/cli/dist/commands/offboard.js
|
|
31863
32287
|
init_dist();
|
|
31864
32288
|
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
31865
|
-
import { existsSync as existsSync68, readFileSync as
|
|
32289
|
+
import { existsSync as existsSync68, readFileSync as readFileSync64, realpathSync as realpathSync8, rmSync as rmSync14, writeFileSync as writeFileSync37 } from "node:fs";
|
|
31866
32290
|
import { homedir as homedir18 } from "node:os";
|
|
31867
32291
|
import { join as join67, resolve as resolve3 } from "node:path";
|
|
31868
32292
|
function pal5() {
|
|
@@ -31990,7 +32414,7 @@ function offboardCommand(args) {
|
|
|
31990
32414
|
`);
|
|
31991
32415
|
return 1;
|
|
31992
32416
|
}
|
|
31993
|
-
const parsed = parseChangeset(
|
|
32417
|
+
const parsed = parseChangeset(readFileSync64(changeset, "utf8"));
|
|
31994
32418
|
if (!parsed.ok) {
|
|
31995
32419
|
err10(m4("offboard.failed_to_parse_changeset"));
|
|
31996
32420
|
return 1;
|
|
@@ -32084,7 +32508,7 @@ function offboardCommand(args) {
|
|
|
32084
32508
|
for (const item of giEntries) {
|
|
32085
32509
|
const gi = join67(projectDir, ".gitignore");
|
|
32086
32510
|
if (existsSync68(gi)) {
|
|
32087
|
-
const lines2 =
|
|
32511
|
+
const lines2 = readFileSync64(gi, "utf8").split("\n");
|
|
32088
32512
|
if (lines2.includes(item)) {
|
|
32089
32513
|
const kept = lines2.filter((l) => l !== item);
|
|
32090
32514
|
writeFileSync37(gi, kept.join("\n"));
|
|
@@ -32108,12 +32532,12 @@ function offboardCommand(args) {
|
|
|
32108
32532
|
|
|
32109
32533
|
// packages/cli/dist/commands/prices.js
|
|
32110
32534
|
init_dist();
|
|
32111
|
-
import { existsSync as existsSync70, readdirSync as readdirSync29, readFileSync as
|
|
32535
|
+
import { existsSync as existsSync70, readdirSync as readdirSync29, readFileSync as readFileSync66 } from "node:fs";
|
|
32112
32536
|
import { join as join69 } from "node:path";
|
|
32113
32537
|
|
|
32114
32538
|
// packages/cli/dist/commands/prices-refresh.js
|
|
32115
32539
|
init_dist();
|
|
32116
|
-
import { existsSync as existsSync69, mkdirSync as mkdirSync36, readdirSync as readdirSync28, readFileSync as
|
|
32540
|
+
import { existsSync as existsSync69, mkdirSync as mkdirSync36, readdirSync as readdirSync28, readFileSync as readFileSync65, writeFileSync as writeFileSync38 } from "node:fs";
|
|
32117
32541
|
import { join as join68 } from "node:path";
|
|
32118
32542
|
var FetchError = class extends Error {
|
|
32119
32543
|
constructor(message) {
|
|
@@ -32341,7 +32765,7 @@ function latestSnapshotPath(snapshotDir, vendor) {
|
|
|
32341
32765
|
return snaps[snaps.length - 1] ?? null;
|
|
32342
32766
|
}
|
|
32343
32767
|
function readPrices(path) {
|
|
32344
|
-
const data = JSON.parse(
|
|
32768
|
+
const data = JSON.parse(readFileSync65(path, "utf8"));
|
|
32345
32769
|
return data.prices ?? {};
|
|
32346
32770
|
}
|
|
32347
32771
|
function diffPrices(oldPrices, newPrices) {
|
|
@@ -32549,7 +32973,7 @@ function loadSnapshots() {
|
|
|
32549
32973
|
}
|
|
32550
32974
|
const files = readdirSync29(dir).filter((n) => n.startsWith("snapshot-") && n.endsWith(".json")).sort();
|
|
32551
32975
|
return files.map((name) => {
|
|
32552
|
-
const data = JSON.parse(
|
|
32976
|
+
const data = JSON.parse(readFileSync66(join69(dir, name), "utf8"));
|
|
32553
32977
|
for (const key of ["version", "effective_at", "source_url", "prices"]) {
|
|
32554
32978
|
if (data[key] === void 0)
|
|
32555
32979
|
throw new Error(`snapshot ${name} missing required key ${key}`);
|
|
@@ -32645,13 +33069,13 @@ function pricesCommand(args, deps = {}) {
|
|
|
32645
33069
|
init_dist2();
|
|
32646
33070
|
init_dist();
|
|
32647
33071
|
import { execFileSync as execFileSync14 } from "node:child_process";
|
|
32648
|
-
import { readFileSync as
|
|
33072
|
+
import { readFileSync as readFileSync70, writeFileSync as writeFileSync41, existsSync as existsSync74 } from "node:fs";
|
|
32649
33073
|
import { join as join73 } from "node:path";
|
|
32650
33074
|
|
|
32651
33075
|
// packages/cli/dist/lib/release-consistency.js
|
|
32652
33076
|
init_dist2();
|
|
32653
33077
|
init_dist();
|
|
32654
|
-
import { existsSync as existsSync72, readFileSync as
|
|
33078
|
+
import { existsSync as existsSync72, readFileSync as readFileSync68, readdirSync as readdirSync31, statSync as statSync23 } from "node:fs";
|
|
32655
33079
|
import { join as join71 } from "node:path";
|
|
32656
33080
|
|
|
32657
33081
|
// packages/cli/dist/lib/consistency-audit.js
|
|
@@ -32659,7 +33083,7 @@ init_dist2();
|
|
|
32659
33083
|
init_dist3();
|
|
32660
33084
|
init_dist();
|
|
32661
33085
|
import { execFile as execFile10 } from "node:child_process";
|
|
32662
|
-
import { existsSync as existsSync71, mkdirSync as mkdirSync37, readFileSync as
|
|
33086
|
+
import { existsSync as existsSync71, mkdirSync as mkdirSync37, readFileSync as readFileSync67, readdirSync as readdirSync30, writeFileSync as writeFileSync39 } from "node:fs";
|
|
32663
33087
|
import { dirname as dirname30, join as join70 } from "node:path";
|
|
32664
33088
|
import { promisify as promisify10 } from "node:util";
|
|
32665
33089
|
init_dist();
|
|
@@ -32671,7 +33095,7 @@ function readJsonl2(path) {
|
|
|
32671
33095
|
if (!existsSync71(path))
|
|
32672
33096
|
return [];
|
|
32673
33097
|
const out3 = [];
|
|
32674
|
-
for (const line of
|
|
33098
|
+
for (const line of readFileSync67(path, "utf8").split("\n")) {
|
|
32675
33099
|
if (line.trim() === "")
|
|
32676
33100
|
continue;
|
|
32677
33101
|
try {
|
|
@@ -32687,7 +33111,7 @@ function readJson(path) {
|
|
|
32687
33111
|
if (!existsSync71(path))
|
|
32688
33112
|
return null;
|
|
32689
33113
|
try {
|
|
32690
|
-
const parsed = JSON.parse(
|
|
33114
|
+
const parsed = JSON.parse(readFileSync67(path, "utf8"));
|
|
32691
33115
|
return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : null;
|
|
32692
33116
|
} catch {
|
|
32693
33117
|
return null;
|
|
@@ -32750,7 +33174,7 @@ async function gatherAuditSnapshot(projectPath3, runtimeDir6, deps = {}) {
|
|
|
32750
33174
|
const skipped = [];
|
|
32751
33175
|
const backlogPath = join70(projectPath3, ".roll", "backlog.md");
|
|
32752
33176
|
if (existsSync71(backlogPath)) {
|
|
32753
|
-
snapshot.backlog = parseBacklog(
|
|
33177
|
+
snapshot.backlog = parseBacklog(readFileSync67(backlogPath, "utf8")).map((r) => ({ id: r.id, status: r.status }));
|
|
32754
33178
|
}
|
|
32755
33179
|
snapshot.index = readIndex(projectPath3);
|
|
32756
33180
|
snapshot.localMainAhead = deps.localMainAhead !== void 0 ? await deps.localMainAhead() : await gitLocalMainAhead(projectPath3);
|
|
@@ -32759,7 +33183,7 @@ async function gatherAuditSnapshot(projectPath3, runtimeDir6, deps = {}) {
|
|
|
32759
33183
|
const terminal = [];
|
|
32760
33184
|
const eventsPath2 = join70(runtimeDir6, "events.ndjson");
|
|
32761
33185
|
if (existsSync71(eventsPath2)) {
|
|
32762
|
-
for (const line of
|
|
33186
|
+
for (const line of readFileSync67(eventsPath2, "utf8").split("\n")) {
|
|
32763
33187
|
const e = parseEventLine(line);
|
|
32764
33188
|
if (e === null)
|
|
32765
33189
|
continue;
|
|
@@ -32924,7 +33348,7 @@ function escapeRegExp3(s) {
|
|
|
32924
33348
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
32925
33349
|
}
|
|
32926
33350
|
function readText(p) {
|
|
32927
|
-
return
|
|
33351
|
+
return readFileSync68(p, "utf8");
|
|
32928
33352
|
}
|
|
32929
33353
|
var COMMAND_SURFACE_REPLACEMENTS = /* @__PURE__ */ new Map([
|
|
32930
33354
|
["migrate", "npx @seanyao/roll@2 migrate"],
|
|
@@ -33659,7 +34083,7 @@ function realReleaseDeps() {
|
|
|
33659
34083
|
return {
|
|
33660
34084
|
version: (cwd) => {
|
|
33661
34085
|
try {
|
|
33662
|
-
const pkg = JSON.parse(
|
|
34086
|
+
const pkg = JSON.parse(readFileSync70(join73(cwd, "package.json"), "utf8"));
|
|
33663
34087
|
return typeof pkg.version === "string" ? pkg.version : "";
|
|
33664
34088
|
} catch {
|
|
33665
34089
|
return "";
|
|
@@ -33694,11 +34118,11 @@ function realReleaseDeps() {
|
|
|
33694
34118
|
return true;
|
|
33695
34119
|
}
|
|
33696
34120
|
},
|
|
33697
|
-
readChangelog: (cwd) =>
|
|
34121
|
+
readChangelog: (cwd) => readFileSync70(join73(cwd, "CHANGELOG.md"), "utf8"),
|
|
33698
34122
|
writeChangelog: (cwd, text) => writeFileSync41(join73(cwd, "CHANGELOG.md"), text, "utf8"),
|
|
33699
34123
|
bumpVersion: (cwd, version) => {
|
|
33700
34124
|
const path = join73(cwd, "package.json");
|
|
33701
|
-
const pkg = JSON.parse(
|
|
34125
|
+
const pkg = JSON.parse(readFileSync70(path, "utf8"));
|
|
33702
34126
|
pkg["version"] = version;
|
|
33703
34127
|
writeFileSync41(path, `${JSON.stringify(pkg, null, 2)}
|
|
33704
34128
|
`, "utf8");
|
|
@@ -34006,7 +34430,7 @@ async function selfScoreCommand(args) {
|
|
|
34006
34430
|
// packages/cli/dist/commands/setup.js
|
|
34007
34431
|
init_dist();
|
|
34008
34432
|
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
34009
|
-
import { existsSync as existsSync75, lstatSync as lstatSync4, mkdirSync as mkdirSync39, readFileSync as
|
|
34433
|
+
import { existsSync as existsSync75, lstatSync as lstatSync4, mkdirSync as mkdirSync39, readFileSync as readFileSync71, readdirSync as readdirSync33, readlinkSync as readlinkSync2, statSync as statSync25 } from "node:fs";
|
|
34010
34434
|
import { join as join74 } from "node:path";
|
|
34011
34435
|
function err13(line) {
|
|
34012
34436
|
const noColor2 = (process.env["NO_COLOR"] ?? "") !== "";
|
|
@@ -34080,7 +34504,7 @@ function walk(dir, lines2) {
|
|
|
34080
34504
|
}
|
|
34081
34505
|
function fileFingerprint(p) {
|
|
34082
34506
|
try {
|
|
34083
|
-
const buf =
|
|
34507
|
+
const buf = readFileSync71(p);
|
|
34084
34508
|
let sum = 0;
|
|
34085
34509
|
for (let i = 0; i < buf.length; i++)
|
|
34086
34510
|
sum = sum * 31 + (buf[i] ?? 0) >>> 0;
|
|
@@ -34274,7 +34698,7 @@ init_showcase2();
|
|
|
34274
34698
|
|
|
34275
34699
|
// packages/cli/dist/commands/test.js
|
|
34276
34700
|
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
34277
|
-
import { appendFileSync as appendFileSync17, existsSync as existsSync76, mkdirSync as mkdirSync40, readFileSync as
|
|
34701
|
+
import { appendFileSync as appendFileSync17, existsSync as existsSync76, mkdirSync as mkdirSync40, readFileSync as readFileSync72, rmSync as rmSync16, writeFileSync as writeFileSync42 } from "node:fs";
|
|
34278
34702
|
import { dirname as dirname32, join as join75, resolve as resolve4 } from "node:path";
|
|
34279
34703
|
function pal7() {
|
|
34280
34704
|
const noColor2 = (process.env["NO_COLOR"] ?? "") !== "";
|
|
@@ -34357,7 +34781,7 @@ function isolationGetType() {
|
|
|
34357
34781
|
return "none";
|
|
34358
34782
|
let text;
|
|
34359
34783
|
try {
|
|
34360
|
-
text =
|
|
34784
|
+
text = readFileSync72(file, "utf8");
|
|
34361
34785
|
} catch {
|
|
34362
34786
|
return "none";
|
|
34363
34787
|
}
|
|
@@ -34548,7 +34972,7 @@ function testCommand(args) {
|
|
|
34548
34972
|
|
|
34549
34973
|
// packages/cli/dist/commands/tune.js
|
|
34550
34974
|
init_dist2();
|
|
34551
|
-
import { existsSync as existsSync77, readFileSync as
|
|
34975
|
+
import { existsSync as existsSync77, readFileSync as readFileSync73 } from "node:fs";
|
|
34552
34976
|
import { join as join76 } from "node:path";
|
|
34553
34977
|
function projectPath2() {
|
|
34554
34978
|
return (process.env["ROLL_MAIN_PROJECT"] ?? "").trim() || process.cwd();
|
|
@@ -34561,7 +34985,7 @@ function parseJsonl(path) {
|
|
|
34561
34985
|
return [];
|
|
34562
34986
|
let text;
|
|
34563
34987
|
try {
|
|
34564
|
-
text =
|
|
34988
|
+
text = readFileSync73(path, "utf8");
|
|
34565
34989
|
} catch {
|
|
34566
34990
|
return [];
|
|
34567
34991
|
}
|
|
@@ -34733,7 +35157,7 @@ function tuneCommand(argv) {
|
|
|
34733
35157
|
// packages/cli/dist/commands/update.js
|
|
34734
35158
|
init_dist();
|
|
34735
35159
|
import { spawnSync as spawnSync11 } from "node:child_process";
|
|
34736
|
-
import { existsSync as existsSync78, mkdtempSync as mkdtempSync6, readFileSync as
|
|
35160
|
+
import { existsSync as existsSync78, mkdtempSync as mkdtempSync6, readFileSync as readFileSync74, rmSync as rmSync17 } from "node:fs";
|
|
34737
35161
|
import { tmpdir as tmpdir8 } from "node:os";
|
|
34738
35162
|
import { join as join77 } from "node:path";
|
|
34739
35163
|
function pal8() {
|
|
@@ -34854,7 +35278,7 @@ function showChangelog() {
|
|
|
34854
35278
|
`);
|
|
34855
35279
|
let count = 0;
|
|
34856
35280
|
let inSection = false;
|
|
34857
|
-
for (const line of
|
|
35281
|
+
for (const line of readFileSync74(changelog, "utf8").split("\n")) {
|
|
34858
35282
|
if (/^## /.test(line)) {
|
|
34859
35283
|
count += 1;
|
|
34860
35284
|
if (count > 3)
|
|
@@ -34879,7 +35303,7 @@ function updateCommand(args) {
|
|
|
34879
35303
|
let installMethod = "npm";
|
|
34880
35304
|
const methodFile = join77(rollPkgDir(), ".install-method");
|
|
34881
35305
|
if (existsSync78(methodFile)) {
|
|
34882
|
-
installMethod =
|
|
35306
|
+
installMethod = readFileSync74(methodFile, "utf8").trim() || "npm";
|
|
34883
35307
|
}
|
|
34884
35308
|
if (installMethod === "curl") {
|
|
34885
35309
|
info5(m6("update.upgrading_via_curl"));
|