@seanyao/roll 3.614.2 → 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/dist/roll.mjs
CHANGED
|
@@ -2324,6 +2324,7 @@ function buildTerminalEvent(input) {
|
|
|
2324
2324
|
cycleId: input.cycleId,
|
|
2325
2325
|
storyId: input.storyId,
|
|
2326
2326
|
agent: input.agent,
|
|
2327
|
+
model: input.model ?? "",
|
|
2327
2328
|
startedAt: input.startedAt,
|
|
2328
2329
|
endedAt: input.endedAt,
|
|
2329
2330
|
outcome: input.outcome,
|
|
@@ -2412,6 +2413,10 @@ var init_truth_registry = __esm({
|
|
|
2412
2413
|
{ field: "cycleId", surface: "event:cycle:terminal", anchor: "cycle_outcome", writer: "buildTerminalEvent", kind: "authoritative" },
|
|
2413
2414
|
{ field: "storyId", surface: "event:cycle:terminal", anchor: "cycle_outcome", writer: "buildTerminalEvent", kind: "authoritative" },
|
|
2414
2415
|
{ field: "agent", surface: "event:cycle:terminal", anchor: "cycle_outcome", writer: "buildTerminalEvent", kind: "authoritative" },
|
|
2416
|
+
// FIX-294: routed model is a dispatch-time fact (like agent) — authoritative,
|
|
2417
|
+
// ALWAYS present even when usage couldn't be parsed; the `usage` fact below
|
|
2418
|
+
// still owns the present-or-reasoned token/cost truth.
|
|
2419
|
+
{ field: "model", surface: "event:cycle:terminal", anchor: "cycle_outcome", writer: "buildTerminalEvent", kind: "authoritative" },
|
|
2415
2420
|
{ field: "startedAt", surface: "event:cycle:terminal", anchor: "cycle_outcome", writer: "buildTerminalEvent", kind: "authoritative" },
|
|
2416
2421
|
{ field: "endedAt", surface: "event:cycle:terminal", anchor: "cycle_outcome", writer: "buildTerminalEvent", kind: "authoritative" },
|
|
2417
2422
|
{ field: "outcome", surface: "event:cycle:terminal", anchor: "cycle_outcome", writer: "buildTerminalEvent", kind: "authoritative" },
|
|
@@ -4973,6 +4978,532 @@ var init_bus = __esm({
|
|
|
4973
4978
|
}
|
|
4974
4979
|
});
|
|
4975
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
|
+
|
|
4976
5507
|
// packages/core/dist/loop/alert-loop.js
|
|
4977
5508
|
function alertFileName(slug) {
|
|
4978
5509
|
return `ALERT-${slug}.md`;
|
|
@@ -5202,14 +5733,14 @@ function classifyAttribution(storyId, reasons) {
|
|
|
5202
5733
|
}
|
|
5203
5734
|
};
|
|
5204
5735
|
}
|
|
5205
|
-
function priorCorrectionCount(events, storyId,
|
|
5736
|
+
function priorCorrectionCount(events, storyId, signal) {
|
|
5206
5737
|
let n = 0;
|
|
5207
5738
|
for (const ev of events) {
|
|
5208
5739
|
if (ev.type !== "correction:action")
|
|
5209
5740
|
continue;
|
|
5210
5741
|
if (ev.storyId !== storyId)
|
|
5211
5742
|
continue;
|
|
5212
|
-
if (ev.signal !==
|
|
5743
|
+
if (ev.signal !== signal)
|
|
5213
5744
|
continue;
|
|
5214
5745
|
n += 1;
|
|
5215
5746
|
}
|
|
@@ -5240,8 +5771,8 @@ var init_correction_actuator = __esm({
|
|
|
5240
5771
|
});
|
|
5241
5772
|
|
|
5242
5773
|
// packages/core/dist/loop/correction-safety.js
|
|
5243
|
-
function normalizeSignal(
|
|
5244
|
-
return
|
|
5774
|
+
function normalizeSignal(signal) {
|
|
5775
|
+
return signal.trim().toLowerCase().replace(/\s+/g, " ").slice(0, 160);
|
|
5245
5776
|
}
|
|
5246
5777
|
function cycleStoryMap(events) {
|
|
5247
5778
|
const out3 = /* @__PURE__ */ new Map();
|
|
@@ -5256,26 +5787,26 @@ function correctionSignals(events) {
|
|
|
5256
5787
|
const out3 = [];
|
|
5257
5788
|
for (const ev of events) {
|
|
5258
5789
|
if (ev.type === "correction:action") {
|
|
5259
|
-
const
|
|
5260
|
-
if (
|
|
5790
|
+
const signal = normalizeSignal(ev.signal);
|
|
5791
|
+
if (signal === "")
|
|
5261
5792
|
continue;
|
|
5262
5793
|
out3.push({
|
|
5263
5794
|
storyId: ev.storyId,
|
|
5264
5795
|
...ev.cycleId !== void 0 ? { cycleId: ev.cycleId } : {},
|
|
5265
|
-
signal
|
|
5796
|
+
signal,
|
|
5266
5797
|
action: ev.action,
|
|
5267
5798
|
ts: ev.ts,
|
|
5268
5799
|
source: "correction"
|
|
5269
5800
|
});
|
|
5270
5801
|
} else if (ev.type === "attest:gate" && ev.verdict === "skipped") {
|
|
5271
|
-
const
|
|
5272
|
-
if (
|
|
5802
|
+
const signal = normalizeSignal(ev.reasons[0] ?? "attest gate skipped");
|
|
5803
|
+
if (signal === "")
|
|
5273
5804
|
continue;
|
|
5274
5805
|
const storyId = stories.get(ev.cycleId);
|
|
5275
5806
|
out3.push({
|
|
5276
5807
|
...storyId !== void 0 ? { storyId } : {},
|
|
5277
5808
|
cycleId: ev.cycleId,
|
|
5278
|
-
signal
|
|
5809
|
+
signal,
|
|
5279
5810
|
action: "attest_skipped",
|
|
5280
5811
|
ts: ev.ts,
|
|
5281
5812
|
source: "attest"
|
|
@@ -5323,7 +5854,7 @@ function correctionSignalVerdict(events, safety, nowSec2) {
|
|
|
5323
5854
|
for (const sig of inWindow) {
|
|
5324
5855
|
bySignal.set(sig.signal, [...bySignal.get(sig.signal) ?? [], sig]);
|
|
5325
5856
|
}
|
|
5326
|
-
for (const [
|
|
5857
|
+
for (const [signal, hits] of [...bySignal.entries()].sort((a, b) => b[1].length - a[1].length || a[0].localeCompare(b[0]))) {
|
|
5327
5858
|
if (hits.length < threshold)
|
|
5328
5859
|
continue;
|
|
5329
5860
|
const knownStories = new Set(hits.map((h) => h.storyId).filter((s) => s !== void 0 && s !== ""));
|
|
@@ -5333,10 +5864,10 @@ function correctionSignalVerdict(events, safety, nowSec2) {
|
|
|
5333
5864
|
action: "pause_and_notify",
|
|
5334
5865
|
kind: "signal_repeat",
|
|
5335
5866
|
...knownStories.size > 0 ? { storyId: [...knownStories].sort().join(",") } : {},
|
|
5336
|
-
signal
|
|
5867
|
+
signal,
|
|
5337
5868
|
count: hits.length,
|
|
5338
5869
|
threshold,
|
|
5339
|
-
reason: `failure signal repeated: "${
|
|
5870
|
+
reason: `failure signal repeated: "${signal}" ${hits.length} times in ${windowSec}s >= ${threshold}`
|
|
5340
5871
|
};
|
|
5341
5872
|
}
|
|
5342
5873
|
return { action: "continue" };
|
|
@@ -5802,388 +6333,119 @@ function cycleStep(state, event) {
|
|
|
5802
6333
|
case "facts_captured": {
|
|
5803
6334
|
const status2 = classifyCaptured(event.facts);
|
|
5804
6335
|
const next = { ...state, phase: "reconcile", captured: event.facts };
|
|
5805
|
-
if (status2 !== "built") {
|
|
5806
|
-
const extra = status2 === "idle" || status2 === "published" ? [{ kind: "cleanup_worktree", branch: state.ctx.branch }] : status2 === "failed" && (event.facts.mainAhead ?? 0) > 0 ? [
|
|
5807
|
-
{
|
|
5808
|
-
kind: "append_alert",
|
|
5809
|
-
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)`
|
|
5810
|
-
}
|
|
5811
|
-
] : status2 === "failed" && event.facts.commitsAhead > 0 ? [
|
|
5812
|
-
{ kind: "push_orphan", branch: state.ctx.branch },
|
|
5813
|
-
{
|
|
5814
|
-
kind: "append_alert",
|
|
5815
|
-
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)`
|
|
5816
|
-
}
|
|
5817
|
-
] : [];
|
|
5818
|
-
return terminate(next, status2, extra);
|
|
5819
|
-
}
|
|
5820
|
-
return {
|
|
5821
|
-
state: { ...next, phase: "publish" },
|
|
5822
|
-
commands: [{ kind: "publish_pr", branch: state.ctx.branch, docOnly: false }]
|
|
5823
|
-
};
|
|
5824
|
-
}
|
|
5825
|
-
case "published": {
|
|
5826
|
-
const status2 = classifyPublish(event.result);
|
|
5827
|
-
if (status2 === "published" || status2 === "done") {
|
|
5828
|
-
return terminate({ ...state, phase: "cleanup" }, status2, [
|
|
5829
|
-
{ kind: "cleanup_worktree", branch: state.ctx.branch }
|
|
5830
|
-
]);
|
|
5831
|
-
}
|
|
5832
|
-
if (status2 === "orphan") {
|
|
5833
|
-
return terminate({ ...state, phase: "cleanup" }, "orphan", [
|
|
5834
|
-
{ kind: "cleanup_worktree", branch: state.ctx.branch },
|
|
5835
|
-
{ kind: "append_alert", message: `cycle ${state.ctx.cycleId}: publish failed; orphan branch+tag pushed; worktree cleaned` }
|
|
5836
|
-
]);
|
|
5837
|
-
}
|
|
5838
|
-
return terminate({ ...state, phase: "publish" }, "failed", [
|
|
5839
|
-
{ kind: "append_alert", message: `cycle ${state.ctx.cycleId}: publish failed; worktree preserved at branch ${state.ctx.branch}` }
|
|
5840
|
-
]);
|
|
5841
|
-
}
|
|
5842
|
-
case "merge_polled": {
|
|
5843
|
-
const action = nextWaitAction(event.state, event.elapsedSec);
|
|
5844
|
-
if (action.kind === "wait") {
|
|
5845
|
-
return {
|
|
5846
|
-
state: { ...state, phase: "merge-wait" },
|
|
5847
|
-
commands: [{ kind: "wait_merge", branch: state.ctx.branch, elapsedSec: event.elapsedSec + action.sleepSeconds }]
|
|
5848
|
-
};
|
|
5849
|
-
}
|
|
5850
|
-
if (action.kind === "merged") {
|
|
5851
|
-
return terminate({ ...state, phase: "reconcile" }, "done", [
|
|
5852
|
-
{ kind: "reconcile" },
|
|
5853
|
-
{ kind: "cleanup_worktree", branch: state.ctx.branch }
|
|
5854
|
-
]);
|
|
5855
|
-
}
|
|
5856
|
-
return terminate({ ...state, phase: "merge-wait" }, "orphan", [
|
|
5857
|
-
{ kind: "push_orphan", branch: state.ctx.branch }
|
|
5858
|
-
]);
|
|
5859
|
-
}
|
|
5860
|
-
default:
|
|
5861
|
-
return { state, commands: [] };
|
|
5862
|
-
}
|
|
5863
|
-
}
|
|
5864
|
-
function cycleStartEvent(ctx, ts = 0) {
|
|
5865
|
-
return {
|
|
5866
|
-
type: "cycle:start",
|
|
5867
|
-
cycleId: ctx.cycleId,
|
|
5868
|
-
storyId: ctx.storyId ?? "",
|
|
5869
|
-
agent: ctx.agent ?? "",
|
|
5870
|
-
model: ctx.model ?? "",
|
|
5871
|
-
ts
|
|
5872
|
-
};
|
|
5873
|
-
}
|
|
5874
|
-
function initialCycleState(ctx) {
|
|
5875
|
-
return { phase: "pick", ctx, attempt: 0, done: false };
|
|
5876
|
-
}
|
|
5877
|
-
var CYCLE_TIMEOUT_SEC, WATCHDOG_KILL_GRACE_SEC, MAX_AGENT_ATTEMPTS, RETRY_BASE_BACKOFF_SEC, EVENT_VALID_PHASES;
|
|
5878
|
-
var init_orchestrator = __esm({
|
|
5879
|
-
"packages/core/dist/loop/orchestrator.js"() {
|
|
5880
|
-
"use strict";
|
|
5881
|
-
init_pr();
|
|
5882
|
-
CYCLE_TIMEOUT_SEC = 2700;
|
|
5883
|
-
WATCHDOG_KILL_GRACE_SEC = 5;
|
|
5884
|
-
MAX_AGENT_ATTEMPTS = 3;
|
|
5885
|
-
RETRY_BASE_BACKOFF_SEC = 30;
|
|
5886
|
-
EVENT_VALID_PHASES = {
|
|
5887
|
-
preflight_done: ["pick"],
|
|
5888
|
-
worktree_created: ["worktree"],
|
|
5889
|
-
worktree_failed: ["worktree"],
|
|
5890
|
-
story_picked: ["pick"],
|
|
5891
|
-
no_story: ["pick"],
|
|
5892
|
-
route_resolved: ["route"],
|
|
5893
|
-
budget_ok: ["route"],
|
|
5894
|
-
budget_halt: ["route"],
|
|
5895
|
-
agent_exited: ["execute"],
|
|
5896
|
-
facts_captured: ["reconcile"],
|
|
5897
|
-
published: ["publish"],
|
|
5898
|
-
merge_polled: ["merge-wait", "publish"],
|
|
5899
|
-
reconciled: ["reconcile"],
|
|
5900
|
-
cleaned: ["cleanup"]
|
|
5901
|
-
};
|
|
5902
|
-
}
|
|
5903
|
-
});
|
|
5904
|
-
|
|
5905
|
-
// packages/core/dist/loop/recovery.js
|
|
5906
|
-
function resolveKeepDays(envDays, yamlDays) {
|
|
5907
|
-
if (envDays !== void 0 && /^\d+$/.test(envDays.trim()))
|
|
5908
|
-
return Number(envDays.trim());
|
|
5909
|
-
if (yamlDays !== void 0 && Number.isFinite(yamlDays) && yamlDays >= 0)
|
|
5910
|
-
return Math.trunc(yamlDays);
|
|
5911
|
-
return GC_DEFAULT_KEEP_DAYS;
|
|
5912
|
-
}
|
|
5913
|
-
var GC_DEFAULT_KEEP_DAYS;
|
|
5914
|
-
var init_recovery = __esm({
|
|
5915
|
-
"packages/core/dist/loop/recovery.js"() {
|
|
5916
|
-
"use strict";
|
|
5917
|
-
GC_DEFAULT_KEEP_DAYS = 30;
|
|
5918
|
-
}
|
|
5919
|
-
});
|
|
5920
|
-
|
|
5921
|
-
// packages/core/dist/loop/signals.js
|
|
5922
|
-
function signalKindForMarker(marker) {
|
|
5923
|
-
if (marker === "tcr")
|
|
5924
|
-
return "tcr";
|
|
5925
|
-
if (marker === "skill" || marker === "story")
|
|
5926
|
-
return "skill";
|
|
5927
|
-
if (marker.startsWith("ci:"))
|
|
5928
|
-
return "ci";
|
|
5929
|
-
if (marker === "peer:gate" || marker === "peer")
|
|
5930
|
-
return "peer";
|
|
5931
|
-
if (marker === "attest:gate" || marker === "evidence:frame-opened" || marker === "attest")
|
|
5932
|
-
return "attest";
|
|
5933
|
-
if (marker.startsWith("pr:"))
|
|
5934
|
-
return "pr";
|
|
5935
|
-
if (marker === "alert" || marker === "error")
|
|
5936
|
-
return "alert";
|
|
5937
|
-
return null;
|
|
5938
|
-
}
|
|
5939
|
-
var init_signals = __esm({
|
|
5940
|
-
"packages/core/dist/loop/signals.js"() {
|
|
5941
|
-
"use strict";
|
|
5942
|
-
}
|
|
5943
|
-
});
|
|
5944
|
-
|
|
5945
|
-
// packages/core/dist/loop/loop-fmt.js
|
|
5946
|
-
function newFmtState() {
|
|
5947
|
-
return {
|
|
5948
|
-
pendingCommit: false,
|
|
5949
|
-
pendingPr: false,
|
|
5950
|
-
pendingCi: false,
|
|
5951
|
-
pendingStory: false,
|
|
5952
|
-
lastBashCmd: "",
|
|
5953
|
-
tcrCount: 0,
|
|
5954
|
-
editStreakFile: null
|
|
5955
|
-
};
|
|
5956
|
-
}
|
|
5957
|
-
function clip(s, n = 60) {
|
|
5958
|
-
const flat = s.replace(/\s+/g, " ").trim();
|
|
5959
|
-
return flat.length > n ? `${flat.slice(0, n - 1)}\u2026` : flat;
|
|
5960
|
-
}
|
|
5961
|
-
function basename2(p) {
|
|
5962
|
-
const trimmed = p.replace(/\/+$/, "");
|
|
5963
|
-
const i = trimmed.lastIndexOf("/");
|
|
5964
|
-
return i >= 0 ? trimmed.slice(i + 1) : trimmed;
|
|
5965
|
-
}
|
|
5966
|
-
function clearPending(st) {
|
|
5967
|
-
st.pendingCommit = false;
|
|
5968
|
-
st.pendingPr = false;
|
|
5969
|
-
st.pendingCi = false;
|
|
5970
|
-
st.pendingStory = false;
|
|
5971
|
-
}
|
|
5972
|
-
function signal(marker, category, label4, detail, ok8 = true) {
|
|
5973
|
-
const kind = signalKindForMarker(marker);
|
|
5974
|
-
const line = { tier: "signal", category, label: label4, ok: ok8 };
|
|
5975
|
-
if (kind !== null)
|
|
5976
|
-
line.kind = kind;
|
|
5977
|
-
if (detail !== void 0 && detail !== "")
|
|
5978
|
-
line.detail = detail;
|
|
5979
|
-
return line;
|
|
5980
|
-
}
|
|
5981
|
-
function formatLine(raw, st) {
|
|
5982
|
-
const line = raw.replace(/\s+$/, "");
|
|
5983
|
-
if (line.trim() === "")
|
|
5984
|
-
return [];
|
|
5985
|
-
const header = /^──\s*cycle\s+(.+?)\s*──\s*$/.exec(line);
|
|
5986
|
-
if (header) {
|
|
5987
|
-
clearPending(st);
|
|
5988
|
-
st.tcrCount = 0;
|
|
5989
|
-
st.editStreakFile = null;
|
|
5990
|
-
return [{ tier: "banner", category: "cycle", label: clip(header[1], 80) }];
|
|
5991
|
-
}
|
|
5992
|
-
let ev;
|
|
5993
|
-
try {
|
|
5994
|
-
ev = JSON.parse(line);
|
|
5995
|
-
} catch {
|
|
5996
|
-
const m7 = /\[loop\]\s+cycle\s+(\d+)/.exec(line);
|
|
5997
|
-
if (m7) {
|
|
5998
|
-
clearPending(st);
|
|
5999
|
-
st.tcrCount = 0;
|
|
6000
|
-
return [{ tier: "banner", category: "cycle", label: `cycle #${m7[1]}` }];
|
|
6001
|
-
}
|
|
6002
|
-
return [];
|
|
6003
|
-
}
|
|
6004
|
-
if (typeof ev !== "object" || ev === null)
|
|
6005
|
-
return [];
|
|
6006
|
-
const type = ev.type;
|
|
6007
|
-
if (type === "system")
|
|
6008
|
-
return [];
|
|
6009
|
-
if (type === "assistant")
|
|
6010
|
-
return handleAssistant(ev, st);
|
|
6011
|
-
if (type === "user")
|
|
6012
|
-
return handleUser(ev, st);
|
|
6013
|
-
if (type === "result")
|
|
6014
|
-
return handleResult(ev, st);
|
|
6015
|
-
return [];
|
|
6016
|
-
}
|
|
6017
|
-
function handleAssistant(ev, st) {
|
|
6018
|
-
const msg6 = ev["message"] ?? {};
|
|
6019
|
-
const content = Array.isArray(msg6["content"]) ? msg6["content"] : [];
|
|
6020
|
-
const out3 = [];
|
|
6021
|
-
for (const blkRaw of content) {
|
|
6022
|
-
if (typeof blkRaw !== "object" || blkRaw === null)
|
|
6023
|
-
continue;
|
|
6024
|
-
const blk = blkRaw;
|
|
6025
|
-
const bt = blk["type"];
|
|
6026
|
-
if (bt === "thinking")
|
|
6027
|
-
continue;
|
|
6028
|
-
if (bt === "text") {
|
|
6029
|
-
out3.push(...handleText(typeof blk["text"] === "string" ? blk["text"] : "", st));
|
|
6030
|
-
} else if (bt === "tool_use") {
|
|
6031
|
-
out3.push(...handleToolUse(blk, st));
|
|
6032
|
-
}
|
|
6033
|
-
}
|
|
6034
|
-
return out3;
|
|
6035
|
-
}
|
|
6036
|
-
function handleText(text, st) {
|
|
6037
|
-
const t2 = text.trim();
|
|
6038
|
-
if (t2 === "")
|
|
6039
|
-
return [];
|
|
6040
|
-
for (const v of PEER_VERDICTS) {
|
|
6041
|
-
if (t2.includes(v)) {
|
|
6042
|
-
const rm = /round\s+(\d+)[/\\](\d+)/i.exec(t2);
|
|
6043
|
-
const round = rm ? `round ${rm[1]}/${rm[2]}` : "round ?";
|
|
6044
|
-
const am = /(\w+)\s*→\s*(\w+)/.exec(t2);
|
|
6045
|
-
const agents = am ? `${am[1]} \u2192 ${am[2]}` : "peer";
|
|
6046
|
-
st.editStreakFile = null;
|
|
6047
|
-
return [signal("peer", "peer", agents, `${round} \xB7 ${v}`)];
|
|
6048
|
-
}
|
|
6049
|
-
}
|
|
6050
|
-
return [];
|
|
6051
|
-
}
|
|
6052
|
-
function handleToolUse(blk, st) {
|
|
6053
|
-
const name = typeof blk["name"] === "string" ? blk["name"] : "";
|
|
6054
|
-
const input = blk["input"] ?? {};
|
|
6055
|
-
if (SUPPRESS_TOOLS.has(name))
|
|
6056
|
-
return [];
|
|
6057
|
-
if (name === "Edit" || name === "Write") {
|
|
6058
|
-
const path = typeof input["file_path"] === "string" && input["file_path"] || typeof input["path"] === "string" && input["path"] || "";
|
|
6059
|
-
if (path === st.editStreakFile)
|
|
6060
|
-
return [];
|
|
6061
|
-
st.editStreakFile = path;
|
|
6062
|
-
return [{ tier: "muted", category: "\u270F", label: `\u270F ${basename2(path)}` }];
|
|
6063
|
-
}
|
|
6064
|
-
st.editStreakFile = null;
|
|
6065
|
-
if (name === "Bash") {
|
|
6066
|
-
const cmd = typeof input["command"] === "string" ? input["command"] : "";
|
|
6067
|
-
const first = cmd.split("\n").map((l) => l.trim()).find((l) => l !== "") ?? cmd;
|
|
6068
|
-
st.lastBashCmd = first;
|
|
6069
|
-
if (/git\s+commit[\s\S]*tcr:/.test(cmd))
|
|
6070
|
-
st.pendingCommit = true;
|
|
6071
|
-
else if (/gh\s+pr\s+(create|merge)/.test(cmd))
|
|
6072
|
-
st.pendingPr = true;
|
|
6073
|
-
else if (/(roll\s+ci|npm\s+run\s+ci|_ci_wait|ci:local)/.test(cmd))
|
|
6074
|
-
st.pendingCi = true;
|
|
6075
|
-
return [];
|
|
6076
|
-
}
|
|
6077
|
-
if (name === "Skill") {
|
|
6078
|
-
const skill = typeof input["skill"] === "string" ? input["skill"] : "";
|
|
6079
|
-
if (skill === "roll-build" || skill === "roll-fix") {
|
|
6080
|
-
const args = (typeof input["args"] === "string" ? input["args"] : "").trim();
|
|
6081
|
-
const usId = args.split(/\s+/)[0] || "?";
|
|
6082
|
-
st.pendingStory = true;
|
|
6083
|
-
return [signal("skill", "story", usId, clip(args, 60))];
|
|
6084
|
-
}
|
|
6085
|
-
return [];
|
|
6086
|
-
}
|
|
6087
|
-
return [];
|
|
6088
|
-
}
|
|
6089
|
-
function extractResultText(content) {
|
|
6090
|
-
if (typeof content === "string")
|
|
6091
|
-
return content;
|
|
6092
|
-
if (Array.isArray(content)) {
|
|
6093
|
-
return content.filter((c2) => typeof c2 === "object" && c2 !== null && c2["type"] === "text").map((c2) => typeof c2["text"] === "string" ? c2["text"] : "").join("\n");
|
|
6094
|
-
}
|
|
6095
|
-
return content == null ? "" : String(content);
|
|
6096
|
-
}
|
|
6097
|
-
function handleUser(ev, st) {
|
|
6098
|
-
const msg6 = ev["message"] ?? {};
|
|
6099
|
-
const content = Array.isArray(msg6["content"]) ? msg6["content"] : [];
|
|
6100
|
-
const out3 = [];
|
|
6101
|
-
for (const blkRaw of content) {
|
|
6102
|
-
if (typeof blkRaw !== "object" || blkRaw === null)
|
|
6103
|
-
continue;
|
|
6104
|
-
const blk = blkRaw;
|
|
6105
|
-
if (blk["type"] !== "tool_result")
|
|
6106
|
-
continue;
|
|
6107
|
-
const text = extractResultText(blk["content"]);
|
|
6108
|
-
if (blk["is_error"] === true) {
|
|
6109
|
-
st.editStreakFile = null;
|
|
6110
|
-
const lines2 = text.split("\n").filter((l) => l.trim() !== "").slice(0, 3);
|
|
6111
|
-
clearPending(st);
|
|
6112
|
-
out3.push(signal("error", "error", "tool", clip(lines2.join(" | "), 80), false));
|
|
6113
|
-
continue;
|
|
6114
|
-
}
|
|
6115
|
-
if (st.pendingCommit) {
|
|
6116
|
-
st.pendingCommit = false;
|
|
6117
|
-
const m7 = /\[[\w/-]+ ([0-9a-f]{7,})\]\s*tcr:\s*(.+)/.exec(text);
|
|
6118
|
-
if (m7) {
|
|
6119
|
-
st.tcrCount += 1;
|
|
6120
|
-
out3.push(signal("tcr", "tcr", m7[1].slice(0, 7), clip(m7[2].trim(), 60)));
|
|
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);
|
|
6121
6350
|
}
|
|
6122
|
-
|
|
6123
|
-
|
|
6124
|
-
|
|
6125
|
-
|
|
6126
|
-
continue;
|
|
6351
|
+
return {
|
|
6352
|
+
state: { ...next, phase: "publish" },
|
|
6353
|
+
commands: [{ kind: "publish_pr", branch: state.ctx.branch, docOnly: false }]
|
|
6354
|
+
};
|
|
6127
6355
|
}
|
|
6128
|
-
|
|
6129
|
-
|
|
6130
|
-
|
|
6131
|
-
|
|
6132
|
-
|
|
6133
|
-
|
|
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
|
+
]);
|
|
6134
6362
|
}
|
|
6135
|
-
|
|
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
|
+
]);
|
|
6136
6372
|
}
|
|
6137
|
-
|
|
6138
|
-
|
|
6139
|
-
|
|
6140
|
-
|
|
6141
|
-
|
|
6142
|
-
|
|
6143
|
-
|
|
6144
|
-
|
|
6145
|
-
|
|
6146
|
-
|
|
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
|
+
]);
|
|
6147
6390
|
}
|
|
6391
|
+
default:
|
|
6392
|
+
return { state, commands: [] };
|
|
6148
6393
|
}
|
|
6149
|
-
return out3;
|
|
6150
6394
|
}
|
|
6151
|
-
function
|
|
6152
|
-
|
|
6153
|
-
|
|
6154
|
-
|
|
6155
|
-
|
|
6156
|
-
|
|
6157
|
-
|
|
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
|
+
};
|
|
6158
6433
|
}
|
|
6159
|
-
|
|
6160
|
-
|
|
6161
|
-
|
|
6162
|
-
|
|
6163
|
-
|
|
6164
|
-
|
|
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;
|
|
6165
6443
|
}
|
|
6166
|
-
var
|
|
6167
|
-
var
|
|
6168
|
-
"packages/core/dist/loop/
|
|
6444
|
+
var GC_DEFAULT_KEEP_DAYS;
|
|
6445
|
+
var init_recovery = __esm({
|
|
6446
|
+
"packages/core/dist/loop/recovery.js"() {
|
|
6169
6447
|
"use strict";
|
|
6170
|
-
|
|
6171
|
-
SUPPRESS_TOOLS = /* @__PURE__ */ new Set([
|
|
6172
|
-
"Read",
|
|
6173
|
-
"Glob",
|
|
6174
|
-
"Grep",
|
|
6175
|
-
"ReadMcpResourceTool",
|
|
6176
|
-
"ListMcpResourcesTool",
|
|
6177
|
-
"WebFetch",
|
|
6178
|
-
"WebSearch",
|
|
6179
|
-
"TaskCreate",
|
|
6180
|
-
"TaskGet",
|
|
6181
|
-
"TaskList",
|
|
6182
|
-
"TaskUpdate",
|
|
6183
|
-
"TaskOutput",
|
|
6184
|
-
"TaskStop"
|
|
6185
|
-
]);
|
|
6186
|
-
PEER_VERDICTS = ["AGREE", "REFINE", "OBJECT", "ESCALATE"];
|
|
6448
|
+
GC_DEFAULT_KEEP_DAYS = 30;
|
|
6187
6449
|
}
|
|
6188
6450
|
});
|
|
6189
6451
|
|
|
@@ -6479,7 +6741,8 @@ function parseLoopSafety(lines2, start) {
|
|
|
6479
6741
|
correctionSignalWindowSec: numOr(flat["correction_signal_window_sec"], DEFAULT_CORRECTION_SIGNAL_WINDOW_SEC),
|
|
6480
6742
|
correctionActuator: flat["correction_actuator"] === "auto" ? "auto" : DEFAULT_CORRECTION_ACTUATOR,
|
|
6481
6743
|
...budget ? { budget } : {},
|
|
6482
|
-
...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"] } : {}
|
|
6483
6746
|
};
|
|
6484
6747
|
return [i, cfg];
|
|
6485
6748
|
}
|
|
@@ -6726,47 +6989,47 @@ function routeProposals(input, minSamples) {
|
|
|
6726
6989
|
}
|
|
6727
6990
|
function rubricProposals(input, minSamples) {
|
|
6728
6991
|
const out3 = [];
|
|
6729
|
-
for (const
|
|
6730
|
-
if (
|
|
6992
|
+
for (const signal of input.rubricSignals) {
|
|
6993
|
+
if (signal.samples < minSamples)
|
|
6731
6994
|
continue;
|
|
6732
|
-
const current = input.current.rubricWeights?.[
|
|
6733
|
-
if (
|
|
6995
|
+
const current = input.current.rubricWeights?.[signal.dimension] ?? DEFAULT_RUBRIC_WEIGHT;
|
|
6996
|
+
if (signal.reworkCorrelation >= 0.6 && signal.noise <= 0.4) {
|
|
6734
6997
|
const next = round1(clamp(current + 0.2, 0.2, 3));
|
|
6735
6998
|
if (next === current)
|
|
6736
6999
|
continue;
|
|
6737
7000
|
out3.push({
|
|
6738
7001
|
kind: "rubric_weight",
|
|
6739
|
-
target: `rubric.${
|
|
7002
|
+
target: `rubric.${signal.dimension}.weight`,
|
|
6740
7003
|
action: "raise_weight",
|
|
6741
7004
|
from: current,
|
|
6742
7005
|
to: next,
|
|
6743
7006
|
rationale: "\u8BE5 rubric \u7EF4\u5EA6\u4E0E\u771F\u5B9E\u8FD4\u5DE5\u5F3A\u76F8\u5173\uFF0C\u6743\u91CD\u5C0F\u5E45\u4E0A\u8C03\u3002",
|
|
6744
7007
|
evidence: [
|
|
6745
|
-
`dimension=${
|
|
6746
|
-
`samples=${
|
|
6747
|
-
`rework_correlation=${fmtRate(
|
|
6748
|
-
`noise=${fmtRate(
|
|
7008
|
+
`dimension=${signal.dimension}`,
|
|
7009
|
+
`samples=${signal.samples}`,
|
|
7010
|
+
`rework_correlation=${fmtRate(signal.reworkCorrelation)}`,
|
|
7011
|
+
`noise=${fmtRate(signal.noise)}`
|
|
6749
7012
|
],
|
|
6750
|
-
rollback: reset(`rubric.${
|
|
7013
|
+
rollback: reset(`rubric.${signal.dimension}.weight`, DEFAULT_RUBRIC_WEIGHT)
|
|
6751
7014
|
});
|
|
6752
|
-
} else if (
|
|
7015
|
+
} else if (signal.noise >= 0.6 && signal.reworkCorrelation <= 0.3) {
|
|
6753
7016
|
const next = round1(clamp(current - 0.2, 0.2, 3));
|
|
6754
7017
|
if (next === current)
|
|
6755
7018
|
continue;
|
|
6756
7019
|
out3.push({
|
|
6757
7020
|
kind: "rubric_weight",
|
|
6758
|
-
target: `rubric.${
|
|
7021
|
+
target: `rubric.${signal.dimension}.weight`,
|
|
6759
7022
|
action: "lower_weight",
|
|
6760
7023
|
from: current,
|
|
6761
7024
|
to: next,
|
|
6762
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",
|
|
6763
7026
|
evidence: [
|
|
6764
|
-
`dimension=${
|
|
6765
|
-
`samples=${
|
|
6766
|
-
`rework_correlation=${fmtRate(
|
|
6767
|
-
`noise=${fmtRate(
|
|
7027
|
+
`dimension=${signal.dimension}`,
|
|
7028
|
+
`samples=${signal.samples}`,
|
|
7029
|
+
`rework_correlation=${fmtRate(signal.reworkCorrelation)}`,
|
|
7030
|
+
`noise=${fmtRate(signal.noise)}`
|
|
6768
7031
|
],
|
|
6769
|
-
rollback: reset(`rubric.${
|
|
7032
|
+
rollback: reset(`rubric.${signal.dimension}.weight`, DEFAULT_RUBRIC_WEIGHT)
|
|
6770
7033
|
});
|
|
6771
7034
|
}
|
|
6772
7035
|
}
|
|
@@ -8081,6 +8344,7 @@ var init_dist2 = __esm({
|
|
|
8081
8344
|
init_score();
|
|
8082
8345
|
init_bus();
|
|
8083
8346
|
init_infra_default3();
|
|
8347
|
+
init_activity_signal();
|
|
8084
8348
|
init_alert_loop();
|
|
8085
8349
|
init_ci_loop();
|
|
8086
8350
|
init_correction_actuator();
|
|
@@ -8090,7 +8354,6 @@ var init_dist2 = __esm({
|
|
|
8090
8354
|
init_quality_gate();
|
|
8091
8355
|
init_orchestrator();
|
|
8092
8356
|
init_recovery();
|
|
8093
|
-
init_loop_fmt();
|
|
8094
8357
|
init_sentinel();
|
|
8095
8358
|
init_signals();
|
|
8096
8359
|
init_transcript();
|
|
@@ -8112,7 +8375,7 @@ var init_dist2 = __esm({
|
|
|
8112
8375
|
});
|
|
8113
8376
|
|
|
8114
8377
|
// packages/infra/dist/config.js
|
|
8115
|
-
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";
|
|
8116
8379
|
import { homedir as homedir3 } from "node:os";
|
|
8117
8380
|
import { dirname as dirname7, join as join12 } from "node:path";
|
|
8118
8381
|
function expandLeadingTilde(val, home = homedir3()) {
|
|
@@ -8128,7 +8391,7 @@ function yamlReadNested(file, parent, child) {
|
|
|
8128
8391
|
const parentRe = new RegExp(`^${parent}:`);
|
|
8129
8392
|
const childRe = new RegExp(`^[ \\t]+${child}:`);
|
|
8130
8393
|
let found = false;
|
|
8131
|
-
const text =
|
|
8394
|
+
const text = readFileSync14(file, "utf8");
|
|
8132
8395
|
const lines2 = text.length === 0 ? [] : text.replace(/\n$/, "").split("\n");
|
|
8133
8396
|
for (const line of lines2) {
|
|
8134
8397
|
if (!found) {
|
|
@@ -8148,7 +8411,7 @@ function yamlReadFlat(file, key) {
|
|
|
8148
8411
|
if (!existsSync12(file))
|
|
8149
8412
|
return "";
|
|
8150
8413
|
const re = new RegExp(`^${escapeRegExp(key)}:`);
|
|
8151
|
-
for (const line of
|
|
8414
|
+
for (const line of readFileSync14(file, "utf8").split("\n")) {
|
|
8152
8415
|
if (re.test(line)) {
|
|
8153
8416
|
return line.replace(/^[^:]*:[ \t]*/, "").replace(/[ \t]*#.*$/, "").replace(/[ \t]*$/, "");
|
|
8154
8417
|
}
|
|
@@ -8303,7 +8566,7 @@ function applyConfigSet(text, key, value) {
|
|
|
8303
8566
|
}
|
|
8304
8567
|
function configSet(key, value, file) {
|
|
8305
8568
|
mkdirSync8(dirname7(file), { recursive: true });
|
|
8306
|
-
const text = existsSync12(file) ?
|
|
8569
|
+
const text = existsSync12(file) ? readFileSync14(file, "utf8") : "";
|
|
8307
8570
|
writeFileSync9(file, applyConfigSet(text, key, value));
|
|
8308
8571
|
}
|
|
8309
8572
|
var CONFIG_KEYS;
|
|
@@ -8820,7 +9083,7 @@ var init_github = __esm({
|
|
|
8820
9083
|
});
|
|
8821
9084
|
|
|
8822
9085
|
// packages/infra/dist/process.js
|
|
8823
|
-
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";
|
|
8824
9087
|
import { dirname as dirname9 } from "node:path";
|
|
8825
9088
|
function parseLock(raw) {
|
|
8826
9089
|
const firstLine = raw.split("\n", 1)[0] ?? "";
|
|
@@ -8848,7 +9111,7 @@ function acquireLock(lockPath2, pid = process.pid, opts = {}) {
|
|
|
8848
9111
|
const pidAlive = opts.pidAlive ?? systemPidAlive;
|
|
8849
9112
|
mkdirSync10(dirname9(lockPath2), { recursive: true });
|
|
8850
9113
|
if (existsSync14(lockPath2)) {
|
|
8851
|
-
const contents = parseLock(
|
|
9114
|
+
const contents = parseLock(readFileSync15(lockPath2, "utf8"));
|
|
8852
9115
|
if (isLockHeld(contents, now, staleSec, pidAlive)) {
|
|
8853
9116
|
return { acquired: false, heldByPid: contents.pid };
|
|
8854
9117
|
}
|
|
@@ -8868,7 +9131,7 @@ function writeHeartbeat(heartbeatPath, now = systemClock) {
|
|
|
8868
9131
|
function heartbeatAge(heartbeatPath, now = systemClock) {
|
|
8869
9132
|
let ts = 0;
|
|
8870
9133
|
if (existsSync14(heartbeatPath)) {
|
|
8871
|
-
const raw =
|
|
9134
|
+
const raw = readFileSync15(heartbeatPath, "utf8").trim();
|
|
8872
9135
|
ts = /^\d+$/.test(raw) ? Number(raw) : 0;
|
|
8873
9136
|
}
|
|
8874
9137
|
return now() - ts;
|
|
@@ -8897,10 +9160,10 @@ function installExitHooks(final, target = process) {
|
|
|
8897
9160
|
const onExit = () => {
|
|
8898
9161
|
runOnce();
|
|
8899
9162
|
};
|
|
8900
|
-
const onSignal = (
|
|
9163
|
+
const onSignal = (signal) => {
|
|
8901
9164
|
runOnce();
|
|
8902
|
-
target.removeListener(
|
|
8903
|
-
target.kill(target.pid,
|
|
9165
|
+
target.removeListener(signal, onSignal);
|
|
9166
|
+
target.kill(target.pid, signal);
|
|
8904
9167
|
};
|
|
8905
9168
|
target.on("exit", onExit);
|
|
8906
9169
|
target.on("SIGTERM", onSignal);
|
|
@@ -10043,10 +10306,12 @@ var init_showcase = __esm({
|
|
|
10043
10306
|
var showcase_exports = {};
|
|
10044
10307
|
__export(showcase_exports, {
|
|
10045
10308
|
SHOWCASE_USAGE: () => SHOWCASE_USAGE,
|
|
10309
|
+
probeMissingAgents: () => probeMissingAgents,
|
|
10310
|
+
resetSandbox: () => resetSandbox,
|
|
10046
10311
|
showcaseCommand: () => showcaseCommand
|
|
10047
10312
|
});
|
|
10048
10313
|
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
10049
|
-
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";
|
|
10050
10315
|
import { tmpdir as tmpdir7 } from "node:os";
|
|
10051
10316
|
import { dirname as dirname31, join as join72 } from "node:path";
|
|
10052
10317
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
@@ -10101,14 +10366,17 @@ function packageRoot() {
|
|
|
10101
10366
|
function rollBin2() {
|
|
10102
10367
|
return join72(packageRoot(), "packages", "cli", "bin", "roll.js");
|
|
10103
10368
|
}
|
|
10104
|
-
function runRoll(sandbox, rollHome4, args,
|
|
10369
|
+
function runRoll(sandbox, rollHome4, args, opts = {}) {
|
|
10105
10370
|
const env = {
|
|
10106
10371
|
...process.env,
|
|
10107
|
-
ROLL_HOME: rollHome4,
|
|
10108
10372
|
ROLL_LANG: process.env["ROLL_LANG"] ?? "en",
|
|
10109
10373
|
GIT_TERMINAL_PROMPT: "0",
|
|
10110
|
-
...extraEnv
|
|
10374
|
+
...opts.extraEnv
|
|
10111
10375
|
};
|
|
10376
|
+
if (opts.realHome === true) {
|
|
10377
|
+
} else {
|
|
10378
|
+
env.ROLL_HOME = rollHome4;
|
|
10379
|
+
}
|
|
10112
10380
|
const r = spawnSync8(process.execPath, [rollBin2(), ...args], {
|
|
10113
10381
|
cwd: sandbox,
|
|
10114
10382
|
env,
|
|
@@ -10171,9 +10439,13 @@ function findCardSpec(sandbox, card) {
|
|
|
10171
10439
|
function resetSandbox(sandbox, card) {
|
|
10172
10440
|
const notes = [];
|
|
10173
10441
|
let reset2 = false;
|
|
10442
|
+
let ok8 = false;
|
|
10174
10443
|
const backlogPath = join72(sandbox, ".roll", "backlog.md");
|
|
10175
10444
|
if (existsSync73(backlogPath)) {
|
|
10176
|
-
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);
|
|
10177
10449
|
const lines2 = before.split("\n").map((line) => {
|
|
10178
10450
|
if (!line.includes(card) || !line.startsWith("|"))
|
|
10179
10451
|
return line;
|
|
@@ -10183,9 +10455,16 @@ function resetSandbox(sandbox, card) {
|
|
|
10183
10455
|
if (after !== before) {
|
|
10184
10456
|
writeFileSync40(backlogPath, after, "utf8");
|
|
10185
10457
|
reset2 = true;
|
|
10458
|
+
ok8 = true;
|
|
10186
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`);
|
|
10187
10465
|
} else {
|
|
10188
|
-
|
|
10466
|
+
ok8 = true;
|
|
10467
|
+
notes.push(`backlog: ${card} already Todo`);
|
|
10189
10468
|
}
|
|
10190
10469
|
} else {
|
|
10191
10470
|
notes.push("backlog: .roll/backlog.md absent");
|
|
@@ -10195,7 +10474,7 @@ function resetSandbox(sandbox, card) {
|
|
|
10195
10474
|
rmSync15(pulseCmd, { force: true });
|
|
10196
10475
|
notes.push("removed prior pulse.ts surface");
|
|
10197
10476
|
}
|
|
10198
|
-
return { reset: reset2, notes };
|
|
10477
|
+
return { ok: ok8, reset: reset2, notes };
|
|
10199
10478
|
}
|
|
10200
10479
|
function writeCasting(sandbox, casting) {
|
|
10201
10480
|
const agentsPath2 = join72(sandbox, ".roll", "agents.yaml");
|
|
@@ -10238,7 +10517,7 @@ function readBacklogStatus(sandbox, card) {
|
|
|
10238
10517
|
const backlogPath = join72(sandbox, ".roll", "backlog.md");
|
|
10239
10518
|
if (!existsSync73(backlogPath))
|
|
10240
10519
|
return void 0;
|
|
10241
|
-
for (const line of
|
|
10520
|
+
for (const line of readFileSync69(backlogPath, "utf8").split("\n")) {
|
|
10242
10521
|
if (line.startsWith("|") && line.includes(card)) {
|
|
10243
10522
|
const m7 = /(✅ *Done|🚧 *WIP|🔄 *In Progress|⏳ *Hold|📋 *Todo|✔️ *Done)/.exec(line);
|
|
10244
10523
|
if (m7 !== null && m7[1] !== void 0)
|
|
@@ -10252,7 +10531,7 @@ function readTruthLadder(sandbox, card) {
|
|
|
10252
10531
|
if (!existsSync73(truthPath))
|
|
10253
10532
|
return void 0;
|
|
10254
10533
|
try {
|
|
10255
|
-
const snap = JSON.parse(
|
|
10534
|
+
const snap = JSON.parse(readFileSync69(truthPath, "utf8"));
|
|
10256
10535
|
const row2 = (snap.stories ?? []).find((s) => s.id === card);
|
|
10257
10536
|
return row2?.ladder;
|
|
10258
10537
|
} catch {
|
|
@@ -10265,7 +10544,7 @@ function readTcrCommits(sandbox) {
|
|
|
10265
10544
|
return [];
|
|
10266
10545
|
const out3 = [];
|
|
10267
10546
|
try {
|
|
10268
|
-
const lines2 =
|
|
10547
|
+
const lines2 = readFileSync69(runsPath3, "utf8").trim().split("\n").filter(Boolean);
|
|
10269
10548
|
const last = lines2[lines2.length - 1];
|
|
10270
10549
|
if (last === void 0)
|
|
10271
10550
|
return [];
|
|
@@ -10310,7 +10589,7 @@ ${msg6}
|
|
|
10310
10589
|
const sourceProject = process.cwd();
|
|
10311
10590
|
const { sandbox, rollHome: rollHome4 } = makeSandbox(sourceProject);
|
|
10312
10591
|
const steps = [];
|
|
10313
|
-
const
|
|
10592
|
+
const emit4 = (id, ok8, detail) => {
|
|
10314
10593
|
steps.push({ id, ok: ok8, detail });
|
|
10315
10594
|
if (!json)
|
|
10316
10595
|
process.stdout.write(`${ok8 ? "\u2713" : "\u2717"} ${id.padEnd(18)} ${detail}
|
|
@@ -10319,28 +10598,28 @@ ${msg6}
|
|
|
10319
10598
|
try {
|
|
10320
10599
|
const spec = findCardSpec(sandbox, card);
|
|
10321
10600
|
if (spec === void 0) {
|
|
10322
|
-
|
|
10601
|
+
emit4("sandbox", false, `target card ${card} not found in the sandbox \u2014 nothing to deliver`);
|
|
10323
10602
|
throw new ShowcaseAbort(`card ${card} absent`);
|
|
10324
10603
|
}
|
|
10325
10604
|
const reset2 = resetSandbox(sandbox, card);
|
|
10326
|
-
|
|
10605
|
+
emit4("reset", reset2.ok, reset2.notes.join("; "));
|
|
10327
10606
|
writeCasting(sandbox, casting);
|
|
10328
|
-
|
|
10607
|
+
emit4("casting", true, `builder=${casting.builder} reviewer=${casting.reviewer} scorer=${casting.scorer} (heterogeneous)`);
|
|
10329
10608
|
const missing = probeMissingAgents(sandbox, rollHome4, casting);
|
|
10330
10609
|
if (missing.length > 0) {
|
|
10331
|
-
|
|
10610
|
+
emit4("agents", false, `unavailable real agent(s): ${missing.join(", ")} \u2014 cannot run the real loop`);
|
|
10332
10611
|
throw new ShowcaseAbort(`agents unavailable: ${missing.join(", ")}`);
|
|
10333
10612
|
}
|
|
10334
|
-
|
|
10613
|
+
emit4("agents", true, `all cast agents available: ${casting.builder}, ${casting.reviewer}, ${casting.scorer}`);
|
|
10335
10614
|
const go = runRoll(sandbox, rollHome4, ["loop", "go", "--cards", card, "--no-tmux", "--no-wait"]);
|
|
10336
|
-
|
|
10615
|
+
emit4("loop-go", go.code === 0, go.code === 0 ? "loop cycle completed" : `loop go exited ${go.code}: ${tail2(go.stderr || go.stdout)}`);
|
|
10337
10616
|
runRoll(sandbox, rollHome4, ["index", "--rebuild"]);
|
|
10338
10617
|
const attest = runRoll(sandbox, rollHome4, ["attest", card]);
|
|
10339
10618
|
const screenshots = await captureScreenshots(sandbox, card);
|
|
10340
10619
|
const cliShot = screenshots.find((s) => s.surface === "cli");
|
|
10341
10620
|
const webShot = screenshots.find((s) => s.surface === "web");
|
|
10342
|
-
|
|
10343
|
-
|
|
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"}`);
|
|
10344
10623
|
const backlogStatus = readBacklogStatus(sandbox, card);
|
|
10345
10624
|
const truthLadder = readTruthLadder(sandbox, card);
|
|
10346
10625
|
const tcrCommits = readTcrCommits(sandbox);
|
|
@@ -10408,9 +10687,9 @@ ROLL_HOME: ${rollHome4}
|
|
|
10408
10687
|
}
|
|
10409
10688
|
}
|
|
10410
10689
|
}
|
|
10411
|
-
function probeMissingAgents(sandbox, rollHome4, casting) {
|
|
10690
|
+
function probeMissingAgents(sandbox, rollHome4, casting, runner = runRoll) {
|
|
10412
10691
|
const wanted = [.../* @__PURE__ */ new Set([casting.builder, casting.reviewer, casting.scorer])];
|
|
10413
|
-
const r =
|
|
10692
|
+
const r = runner(sandbox, rollHome4, ["agent", "list"], { realHome: true });
|
|
10414
10693
|
if (r.code !== 0 && r.stdout.trim() === "")
|
|
10415
10694
|
return wanted;
|
|
10416
10695
|
const listed = r.stdout.toLowerCase();
|
|
@@ -11432,12 +11711,12 @@ function agentCommand(args, deps = {}) {
|
|
|
11432
11711
|
init_dist2();
|
|
11433
11712
|
init_dist();
|
|
11434
11713
|
init_dist2();
|
|
11435
|
-
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";
|
|
11436
11715
|
import { dirname as dirname10, join as join16, relative as relative2 } from "node:path";
|
|
11437
11716
|
|
|
11438
11717
|
// packages/cli/dist/runner/pairing-gate.js
|
|
11439
11718
|
init_dist2();
|
|
11440
|
-
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";
|
|
11441
11720
|
import { join as join9 } from "node:path";
|
|
11442
11721
|
|
|
11443
11722
|
// packages/cli/dist/lib/self-score.js
|
|
@@ -12190,8 +12469,9 @@ function evaluateSelfScoreGate(projectPath3, storyId) {
|
|
|
12190
12469
|
}
|
|
12191
12470
|
|
|
12192
12471
|
// packages/cli/dist/runner/peer-gate.js
|
|
12472
|
+
init_dist2();
|
|
12193
12473
|
import { execFile } from "node:child_process";
|
|
12194
|
-
import { existsSync as existsSync9, readdirSync as readdirSync4 } from "node:fs";
|
|
12474
|
+
import { existsSync as existsSync9, readFileSync as readFileSync10, readdirSync as readdirSync4 } from "node:fs";
|
|
12195
12475
|
import { join as join8 } from "node:path";
|
|
12196
12476
|
import { promisify } from "node:util";
|
|
12197
12477
|
var execFileAsync = promisify(execFile);
|
|
@@ -12231,21 +12511,32 @@ function peerEvidencePresent(runtimeDir6, cycleId) {
|
|
|
12231
12511
|
return false;
|
|
12232
12512
|
}
|
|
12233
12513
|
}
|
|
12234
|
-
|
|
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) {
|
|
12235
12525
|
try {
|
|
12236
12526
|
const files = await cycleChangedFiles(worktreeCwd);
|
|
12237
12527
|
const cx = assessComplexity(files);
|
|
12238
12528
|
if (!cx.high)
|
|
12239
|
-
return { verdict: "not-required", reasons: [] };
|
|
12529
|
+
return { verdict: "not-required", mode, reasons: [], blocked: false };
|
|
12240
12530
|
if (peerEvidencePresent(runtimeDir6, cycleId)) {
|
|
12241
12531
|
sinks.event({ cycleId, verdict: "consulted", reasons: cx.reasons });
|
|
12242
|
-
return { verdict: "consulted", reasons: cx.reasons };
|
|
12532
|
+
return { verdict: "consulted", mode, reasons: cx.reasons, blocked: false };
|
|
12243
12533
|
}
|
|
12244
|
-
|
|
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" : ""));
|
|
12245
12536
|
sinks.event({ cycleId, verdict: "skipped", reasons: cx.reasons });
|
|
12246
|
-
return { verdict: "skipped", reasons: cx.reasons };
|
|
12537
|
+
return { verdict: "skipped", mode, reasons: cx.reasons, blocked };
|
|
12247
12538
|
} catch {
|
|
12248
|
-
return { verdict: "not-required", reasons: [] };
|
|
12539
|
+
return { verdict: "not-required", mode, reasons: [], blocked: false };
|
|
12249
12540
|
}
|
|
12250
12541
|
}
|
|
12251
12542
|
|
|
@@ -12255,7 +12546,7 @@ function enabledPairingStages(projectDir) {
|
|
|
12255
12546
|
const cfgPath = join9(projectDir, ".roll", "pairing.yaml");
|
|
12256
12547
|
if (!existsSync10(cfgPath))
|
|
12257
12548
|
return [];
|
|
12258
|
-
const cfg = parsePairingConfig(
|
|
12549
|
+
const cfg = parsePairingConfig(readFileSync11(cfgPath, "utf8"));
|
|
12259
12550
|
if (!cfg.enabled)
|
|
12260
12551
|
return [];
|
|
12261
12552
|
return cfg.stages.filter((s, i, arr2) => arr2.indexOf(s) === i && s !== "score");
|
|
@@ -12276,7 +12567,7 @@ async function runPairing(projectDir, worktreeCwd, runtimeDir6, cycleId, working
|
|
|
12276
12567
|
const cfgPath = join9(projectDir, ".roll", "pairing.yaml");
|
|
12277
12568
|
if (!existsSync10(cfgPath))
|
|
12278
12569
|
return { status: "off" };
|
|
12279
|
-
const cfg = parsePairingConfig(
|
|
12570
|
+
const cfg = parsePairingConfig(readFileSync11(cfgPath, "utf8"));
|
|
12280
12571
|
if (!cfg.enabled || !cfg.stages.includes(stage))
|
|
12281
12572
|
return { status: "off" };
|
|
12282
12573
|
const files = await deps.changedFiles(worktreeCwd);
|
|
@@ -12319,7 +12610,7 @@ async function runScorePairing(projectDir, runtimeDir6, cycleId, workingAgent, s
|
|
|
12319
12610
|
const cfgPath = join9(projectDir, ".roll", "pairing.yaml");
|
|
12320
12611
|
if (!existsSync10(cfgPath))
|
|
12321
12612
|
return { status: "off" };
|
|
12322
|
-
const cfg = parsePairingConfig(
|
|
12613
|
+
const cfg = parsePairingConfig(readFileSync11(cfgPath, "utf8"));
|
|
12323
12614
|
if (!cfg.enabled || !cfg.stages.includes("score"))
|
|
12324
12615
|
return { status: "off" };
|
|
12325
12616
|
const candidates = selectPairingCandidates({
|
|
@@ -12373,6 +12664,33 @@ function parsePairScoreOutput(stdout) {
|
|
|
12373
12664
|
return null;
|
|
12374
12665
|
return { score, verdict: vm[1].toLowerCase(), rationale: rm[1].trim() };
|
|
12375
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
|
+
}
|
|
12376
12694
|
function buildPairScorePrompt(summary) {
|
|
12377
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.
|
|
12378
12696
|
|
|
@@ -12383,11 +12701,11 @@ DELIVERY:
|
|
|
12383
12701
|
// packages/cli/dist/commands/peer.js
|
|
12384
12702
|
init_dist2();
|
|
12385
12703
|
import { spawn } from "node:child_process";
|
|
12386
|
-
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";
|
|
12387
12705
|
import { dirname as dirname6, join as join11 } from "node:path";
|
|
12388
12706
|
|
|
12389
12707
|
// packages/cli/dist/commands/setup-shared.js
|
|
12390
|
-
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";
|
|
12391
12709
|
import { homedir as homedir2 } from "node:os";
|
|
12392
12710
|
import { basename as basename5, dirname as dirname5, join as join10 } from "node:path";
|
|
12393
12711
|
function rollHome() {
|
|
@@ -12416,7 +12734,7 @@ function getAiTools() {
|
|
|
12416
12734
|
if (!existsSync11(cfg))
|
|
12417
12735
|
return [];
|
|
12418
12736
|
const out3 = [];
|
|
12419
|
-
for (const line of
|
|
12737
|
+
for (const line of readFileSync12(cfg, "utf8").split("\n")) {
|
|
12420
12738
|
if (/^ai_[a-z]+:/.test(line)) {
|
|
12421
12739
|
let entry = line.replace(/^[^:]*:[ \t]*/, "");
|
|
12422
12740
|
entry = entry.replace(/^~/, homedir2());
|
|
@@ -12549,7 +12867,7 @@ function safeCopy(src, dst, force) {
|
|
|
12549
12867
|
}
|
|
12550
12868
|
function sameFile(a, b) {
|
|
12551
12869
|
try {
|
|
12552
|
-
return
|
|
12870
|
+
return readFileSync12(a).equals(readFileSync12(b));
|
|
12553
12871
|
} catch {
|
|
12554
12872
|
return false;
|
|
12555
12873
|
}
|
|
@@ -12683,7 +13001,7 @@ function ensureConfigEntries() {
|
|
|
12683
13001
|
const cfg = rollConfig();
|
|
12684
13002
|
if (!existsSync11(cfg))
|
|
12685
13003
|
return;
|
|
12686
|
-
const original =
|
|
13004
|
+
const original = readFileSync12(cfg, "utf8");
|
|
12687
13005
|
let lines2 = original.split("\n");
|
|
12688
13006
|
let added = 0;
|
|
12689
13007
|
for (const [key, val] of DEFAULT_AI_KEYS) {
|
|
@@ -12759,7 +13077,7 @@ function replacePrimaryAgent(newAgent) {
|
|
|
12759
13077
|
const cfg = rollConfig();
|
|
12760
13078
|
if (!existsSync11(cfg) || newAgent === "")
|
|
12761
13079
|
return;
|
|
12762
|
-
const lines2 =
|
|
13080
|
+
const lines2 = readFileSync12(cfg, "utf8").split("\n");
|
|
12763
13081
|
const out3 = lines2.map((l) => /^primary_agent:/.test(l) ? `primary_agent: ${newAgent}` : l);
|
|
12764
13082
|
writeFileSync7(cfg, out3.join("\n"));
|
|
12765
13083
|
}
|
|
@@ -12769,7 +13087,7 @@ function installLocal(force) {
|
|
|
12769
13087
|
pullConventions(force);
|
|
12770
13088
|
pullSkills();
|
|
12771
13089
|
const cfg = rollConfig();
|
|
12772
|
-
if (existsSync11(cfg) && !/^ai_[a-z]+:/m.test(
|
|
13090
|
+
if (existsSync11(cfg) && !/^ai_[a-z]+:/m.test(readFileSync12(cfg, "utf8"))) {
|
|
12773
13091
|
copyFileSync(cfg, `${cfg}.bak`);
|
|
12774
13092
|
rmSync2(cfg, { force: true });
|
|
12775
13093
|
}
|
|
@@ -12795,8 +13113,8 @@ function syncConventionForTool(src, mainDst, force) {
|
|
|
12795
13113
|
copyFileSync(src, wkFile);
|
|
12796
13114
|
if (!existsSync11(mainDst)) {
|
|
12797
13115
|
writeFileSync7(mainDst, "@roll.md\n");
|
|
12798
|
-
} else if (!
|
|
12799
|
-
writeFileSync7(mainDst,
|
|
13116
|
+
} else if (!readFileSync12(mainDst, "utf8").includes("@roll.md")) {
|
|
13117
|
+
writeFileSync7(mainDst, readFileSync12(mainDst, "utf8") + "\n@roll.md\n");
|
|
12800
13118
|
}
|
|
12801
13119
|
}
|
|
12802
13120
|
function syncConventions(force) {
|
|
@@ -12935,7 +13253,7 @@ function textAgentArgv(agent, prompt) {
|
|
|
12935
13253
|
case "gemini":
|
|
12936
13254
|
case "agy":
|
|
12937
13255
|
case "antigravity":
|
|
12938
|
-
return { bin: "agy", args: ["
|
|
13256
|
+
return { bin: "agy", args: ["--dangerously-skip-permissions", "-p", prompt] };
|
|
12939
13257
|
default:
|
|
12940
13258
|
return null;
|
|
12941
13259
|
}
|
|
@@ -12986,15 +13304,15 @@ function boundedAppend(current, chunk) {
|
|
|
12986
13304
|
const next = current + chunk.toString("utf8");
|
|
12987
13305
|
return next.length > 1e5 ? next.slice(-1e5) : next;
|
|
12988
13306
|
}
|
|
12989
|
-
function killChild(child,
|
|
13307
|
+
function killChild(child, signal) {
|
|
12990
13308
|
if (child.pid !== void 0) {
|
|
12991
13309
|
try {
|
|
12992
|
-
process.kill(-child.pid,
|
|
13310
|
+
process.kill(-child.pid, signal);
|
|
12993
13311
|
return true;
|
|
12994
13312
|
} catch {
|
|
12995
13313
|
}
|
|
12996
13314
|
}
|
|
12997
|
-
return child.kill(
|
|
13315
|
+
return child.kill(signal);
|
|
12998
13316
|
}
|
|
12999
13317
|
function releaseChild(child) {
|
|
13000
13318
|
child.stdout?.destroy();
|
|
@@ -13039,14 +13357,14 @@ function spawnPeerReviewAgent(input) {
|
|
|
13039
13357
|
stderr = boundedAppend(stderr, chunk);
|
|
13040
13358
|
});
|
|
13041
13359
|
child.on("error", (error) => finish({ status: "error", reason: error.message, stdout }));
|
|
13042
|
-
child.on("exit", (code,
|
|
13360
|
+
child.on("exit", (code, signal) => {
|
|
13043
13361
|
setImmediate(() => {
|
|
13044
13362
|
if (timedOut)
|
|
13045
13363
|
finish({ status: "timeout", stdout });
|
|
13046
13364
|
else if (code === 0)
|
|
13047
13365
|
finish({ status: "ok", stdout });
|
|
13048
13366
|
else
|
|
13049
|
-
finish({ status: "error", reason: `exit_${code ??
|
|
13367
|
+
finish({ status: "error", reason: `exit_${code ?? signal ?? "signal"}:${stderr.trim().slice(0, 200)}`, stdout });
|
|
13050
13368
|
});
|
|
13051
13369
|
});
|
|
13052
13370
|
child.on("close", (code) => {
|
|
@@ -13229,7 +13547,7 @@ function readPrompt(opts) {
|
|
|
13229
13547
|
if (opts.prompt !== void 0)
|
|
13230
13548
|
return opts.prompt;
|
|
13231
13549
|
if (opts.file !== void 0)
|
|
13232
|
-
return
|
|
13550
|
+
return readFileSync13(opts.file, "utf8");
|
|
13233
13551
|
throw new Error("roll peer: --prompt or --file is required");
|
|
13234
13552
|
}
|
|
13235
13553
|
async function peerCommand(args, deps = realDeps()) {
|
|
@@ -13279,7 +13597,7 @@ duration: ${facts.durationMs}ms
|
|
|
13279
13597
|
// packages/cli/dist/commands/dashboard.js
|
|
13280
13598
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
13281
13599
|
import { createHash as createHash3 } from "node:crypto";
|
|
13282
|
-
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";
|
|
13283
13601
|
import { homedir as homedir4, platform } from "node:os";
|
|
13284
13602
|
import { basename as basename6, join as join15 } from "node:path";
|
|
13285
13603
|
init_dist3();
|
|
@@ -13391,7 +13709,7 @@ function resolveProjectPath(slug) {
|
|
|
13391
13709
|
const plist = join15(homedir4(), "Library", "LaunchAgents", `com.roll.loop.${slug}.plist`);
|
|
13392
13710
|
if (existsSync17(plist)) {
|
|
13393
13711
|
try {
|
|
13394
|
-
const text =
|
|
13712
|
+
const text = readFileSync16(plist, "utf8");
|
|
13395
13713
|
const m7 = /<key>WorkingDirectory<\/key>\s*<string>([^<]+)<\/string>/.exec(text);
|
|
13396
13714
|
if (m7 && m7[1] !== void 0 && isDir(m7[1]))
|
|
13397
13715
|
return m7[1];
|
|
@@ -13416,7 +13734,7 @@ function resolveProjectPath(slug) {
|
|
|
13416
13734
|
const innerScript = join15(sharedRoot(), "loop", `run-${slug}-inner.sh`);
|
|
13417
13735
|
if (existsSync17(innerScript)) {
|
|
13418
13736
|
try {
|
|
13419
|
-
const text =
|
|
13737
|
+
const text = readFileSync16(innerScript, "utf8");
|
|
13420
13738
|
const m7 = /export ROLL_MAIN_PROJECT="([^"]+)"/.exec(text);
|
|
13421
13739
|
if (m7 && m7[1] !== void 0 && isDir(m7[1]))
|
|
13422
13740
|
return m7[1];
|
|
@@ -13500,7 +13818,7 @@ function loadEvents(slug, days) {
|
|
|
13500
13818
|
for (const p of existing) {
|
|
13501
13819
|
let content;
|
|
13502
13820
|
try {
|
|
13503
|
-
content =
|
|
13821
|
+
content = readFileSync16(p, "utf8");
|
|
13504
13822
|
} catch {
|
|
13505
13823
|
continue;
|
|
13506
13824
|
}
|
|
@@ -13538,7 +13856,7 @@ function loadCronLog(slug) {
|
|
|
13538
13856
|
const out3 = [];
|
|
13539
13857
|
let content;
|
|
13540
13858
|
try {
|
|
13541
|
-
content =
|
|
13859
|
+
content = readFileSync16(path, "utf8");
|
|
13542
13860
|
} catch {
|
|
13543
13861
|
return [];
|
|
13544
13862
|
}
|
|
@@ -13568,7 +13886,7 @@ function loadState(slug) {
|
|
|
13568
13886
|
const out3 = {};
|
|
13569
13887
|
let content;
|
|
13570
13888
|
try {
|
|
13571
|
-
content =
|
|
13889
|
+
content = readFileSync16(path, "utf8");
|
|
13572
13890
|
} catch {
|
|
13573
13891
|
return {};
|
|
13574
13892
|
}
|
|
@@ -13590,7 +13908,7 @@ function loadBacklog(projectRoot2) {
|
|
|
13590
13908
|
const pat = /^\|\s*(?:\[)?([A-Z]+-\d+)(?:\]\([^)]+\))?\s*\|\s*([^|]+?)\s*\|/;
|
|
13591
13909
|
let content;
|
|
13592
13910
|
try {
|
|
13593
|
-
content =
|
|
13911
|
+
content = readFileSync16(path, "utf8");
|
|
13594
13912
|
} catch {
|
|
13595
13913
|
return {};
|
|
13596
13914
|
}
|
|
@@ -13741,7 +14059,7 @@ function detectLiveCycle(rtDir, cycles, now, pidAlive = systemPidAlive) {
|
|
|
13741
14059
|
const nowSec2 = Math.floor(now.getTime() / 1e3);
|
|
13742
14060
|
let lockRaw;
|
|
13743
14061
|
try {
|
|
13744
|
-
lockRaw =
|
|
14062
|
+
lockRaw = readFileSync16(lockPath2, "utf8");
|
|
13745
14063
|
} catch {
|
|
13746
14064
|
return dead;
|
|
13747
14065
|
}
|
|
@@ -13774,7 +14092,7 @@ function loadRuns(slug) {
|
|
|
13774
14092
|
const out3 = {};
|
|
13775
14093
|
let content;
|
|
13776
14094
|
try {
|
|
13777
|
-
content =
|
|
14095
|
+
content = readFileSync16(path, "utf8");
|
|
13778
14096
|
} catch {
|
|
13779
14097
|
return {};
|
|
13780
14098
|
}
|
|
@@ -13992,7 +14310,7 @@ function loadClaudeSessionUsage(label4, slug) {
|
|
|
13992
14310
|
let durationMs = null;
|
|
13993
14311
|
let content;
|
|
13994
14312
|
try {
|
|
13995
|
-
content =
|
|
14313
|
+
content = readFileSync16(path, "utf8");
|
|
13996
14314
|
} catch {
|
|
13997
14315
|
return null;
|
|
13998
14316
|
}
|
|
@@ -14168,7 +14486,7 @@ function selfScoreSummaryLine(notesDir = ".roll/notes", windowN = 14, featuresDi
|
|
|
14168
14486
|
let verdict = null;
|
|
14169
14487
|
let content;
|
|
14170
14488
|
try {
|
|
14171
|
-
content =
|
|
14489
|
+
content = readFileSync16(f.path, "utf8");
|
|
14172
14490
|
} catch {
|
|
14173
14491
|
content = "";
|
|
14174
14492
|
}
|
|
@@ -14398,7 +14716,7 @@ function readDailyPlistSchedule(svc) {
|
|
|
14398
14716
|
return null;
|
|
14399
14717
|
let text;
|
|
14400
14718
|
try {
|
|
14401
|
-
text =
|
|
14719
|
+
text = readFileSync16(plist, "utf8");
|
|
14402
14720
|
} catch {
|
|
14403
14721
|
return null;
|
|
14404
14722
|
}
|
|
@@ -14451,7 +14769,7 @@ function tickAgeLine(loopType, now) {
|
|
|
14451
14769
|
return null;
|
|
14452
14770
|
let lastLine;
|
|
14453
14771
|
try {
|
|
14454
|
-
const lines2 =
|
|
14772
|
+
const lines2 = readFileSync16(tickFile, "utf8").trim().split("\n");
|
|
14455
14773
|
lastLine = lines2[lines2.length - 1] ?? "";
|
|
14456
14774
|
if (lastLine === "")
|
|
14457
14775
|
return null;
|
|
@@ -14483,7 +14801,7 @@ function readLoopPlistSchedule() {
|
|
|
14483
14801
|
return null;
|
|
14484
14802
|
let text;
|
|
14485
14803
|
try {
|
|
14486
|
-
text =
|
|
14804
|
+
text = readFileSync16(plist, "utf8");
|
|
14487
14805
|
} catch {
|
|
14488
14806
|
return null;
|
|
14489
14807
|
}
|
|
@@ -14506,7 +14824,7 @@ function lastLoopFireEpochSec() {
|
|
|
14506
14824
|
if (!existsSync17(cronLog))
|
|
14507
14825
|
return null;
|
|
14508
14826
|
try {
|
|
14509
|
-
const lines2 =
|
|
14827
|
+
const lines2 = readFileSync16(cronLog, "utf8").trim().split("\n").reverse();
|
|
14510
14828
|
for (const line of lines2) {
|
|
14511
14829
|
if (!line.includes("cycle start"))
|
|
14512
14830
|
continue;
|
|
@@ -15312,7 +15630,7 @@ function pairStatus(rest) {
|
|
|
15312
15630
|
const NC = noColor2 ? "" : "\x1B[0m";
|
|
15313
15631
|
let view;
|
|
15314
15632
|
try {
|
|
15315
|
-
view = pairingPoolView(agentsInstalled(realAgentEnv()), parsePairingConfig(
|
|
15633
|
+
view = pairingPoolView(agentsInstalled(realAgentEnv()), parsePairingConfig(readFileSync17(path, "utf8")));
|
|
15316
15634
|
} catch (e) {
|
|
15317
15635
|
process.stderr.write(`[roll] pairing.yaml invalid: ${e.message}
|
|
15318
15636
|
`);
|
|
@@ -15354,7 +15672,7 @@ function pairingActivitySummary() {
|
|
|
15354
15672
|
for (const p of pairingEventFiles()) {
|
|
15355
15673
|
let content;
|
|
15356
15674
|
try {
|
|
15357
|
-
content =
|
|
15675
|
+
content = readFileSync17(p, "utf8");
|
|
15358
15676
|
} catch {
|
|
15359
15677
|
continue;
|
|
15360
15678
|
}
|
|
@@ -15408,13 +15726,13 @@ function resolveSummary(storyId, summaryFlag, fileFlag) {
|
|
|
15408
15726
|
return summaryFlag.trim();
|
|
15409
15727
|
if (fileFlag !== void 0) {
|
|
15410
15728
|
try {
|
|
15411
|
-
return
|
|
15729
|
+
return readFileSync17(fileFlag, "utf8").trim() || null;
|
|
15412
15730
|
} catch {
|
|
15413
15731
|
return null;
|
|
15414
15732
|
}
|
|
15415
15733
|
}
|
|
15416
15734
|
try {
|
|
15417
|
-
const backlog =
|
|
15735
|
+
const backlog = readFileSync17(join16(process.cwd(), ".roll", "backlog.md"), "utf8");
|
|
15418
15736
|
const idRe = new RegExp(`${storyId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(?![A-Za-z0-9])`);
|
|
15419
15737
|
const row2 = backlog.split("\n").find((l) => idRe.test(l));
|
|
15420
15738
|
return row2 !== void 0 ? `Story ${storyId} \u2014 backlog row:
|
|
@@ -15505,7 +15823,7 @@ ${HELP}`);
|
|
|
15505
15823
|
// packages/cli/dist/commands/alert.js
|
|
15506
15824
|
init_dist2();
|
|
15507
15825
|
init_dist();
|
|
15508
|
-
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";
|
|
15509
15827
|
import { homedir as homedir5 } from "node:os";
|
|
15510
15828
|
import { join as join17 } from "node:path";
|
|
15511
15829
|
function palette() {
|
|
@@ -15568,7 +15886,7 @@ function renderLog(n, p, lang9) {
|
|
|
15568
15886
|
let body = "";
|
|
15569
15887
|
try {
|
|
15570
15888
|
if (existsSync19(file) && statSync9(file).size > 0)
|
|
15571
|
-
body =
|
|
15889
|
+
body = readFileSync18(file, "utf8");
|
|
15572
15890
|
} catch {
|
|
15573
15891
|
body = "";
|
|
15574
15892
|
}
|
|
@@ -15599,7 +15917,7 @@ function alertCommand(args) {
|
|
|
15599
15917
|
const rest = args.slice(1);
|
|
15600
15918
|
const file = loopAlertPath();
|
|
15601
15919
|
const fileExists = existsSync19(file);
|
|
15602
|
-
const contents = fileExists ?
|
|
15920
|
+
const contents = fileExists ? readFileSync18(file, "utf8") : "";
|
|
15603
15921
|
const ts = nowStamp();
|
|
15604
15922
|
const action = alertConsumeAction(subcmd, fileExists, contents, ts, rest[0]);
|
|
15605
15923
|
switch (action.kind) {
|
|
@@ -15660,7 +15978,7 @@ function ackMessage(lang9, ts) {
|
|
|
15660
15978
|
init_dist2();
|
|
15661
15979
|
init_dist();
|
|
15662
15980
|
init_dist3();
|
|
15663
|
-
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";
|
|
15664
15982
|
import { execFile as execFile8, execFileSync as execFileSync5 } from "node:child_process";
|
|
15665
15983
|
import { basename as basename8, join as join33, relative as relative4 } from "node:path";
|
|
15666
15984
|
import { promisify as promisify8 } from "node:util";
|
|
@@ -15670,7 +15988,7 @@ init_dist2();
|
|
|
15670
15988
|
init_dist();
|
|
15671
15989
|
init_dist2();
|
|
15672
15990
|
init_dist();
|
|
15673
|
-
import { existsSync as existsSync35, readFileSync as
|
|
15991
|
+
import { existsSync as existsSync35, readFileSync as readFileSync33, readdirSync as readdirSync15, writeFileSync as writeFileSync15 } from "node:fs";
|
|
15674
15992
|
import { join as join32 } from "node:path";
|
|
15675
15993
|
|
|
15676
15994
|
// packages/cli/dist/lib/dossier-index.js
|
|
@@ -16154,7 +16472,7 @@ function copyChip(cmd) {
|
|
|
16154
16472
|
}
|
|
16155
16473
|
function cycleRow2(cy) {
|
|
16156
16474
|
const color = VERDICT_COLORS[cy.verdict] ?? C.slate;
|
|
16157
|
-
const n = cy.cycleId
|
|
16475
|
+
const n = cycleHandle(cy.cycleId);
|
|
16158
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).
|
|
16159
16477
|
copyChip(`roll cycle ${cycleHandle(cy.cycleId)}`) + `</div></div></details>`;
|
|
16160
16478
|
}
|
|
@@ -16190,6 +16508,7 @@ function hooksPanel(input) {
|
|
|
16190
16508
|
}
|
|
16191
16509
|
function loopTab(input) {
|
|
16192
16510
|
const ranges = [
|
|
16511
|
+
["recent", "Recent", "\u8FD1\u671F"],
|
|
16193
16512
|
["1", "Today", "\u4ECA\u5929"],
|
|
16194
16513
|
["3", "3 days", "\u4E09\u5929"],
|
|
16195
16514
|
["7", "7 days", "\u4E03\u5929"],
|
|
@@ -16199,7 +16518,7 @@ function loopTab(input) {
|
|
|
16199
16518
|
// project-scoped commit-hooks panel + the Cycle ledger. The inline agents
|
|
16200
16519
|
// panel (now the machine Agents page) and the inline casting ladder (now its
|
|
16201
16520
|
// own Casting tab) are NOT rendered here.
|
|
16202
|
-
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>`;
|
|
16203
16522
|
}
|
|
16204
16523
|
var TYPE_COLORS = { US: C.blue, FIX: C.red, REFACTOR: C.purple, IDEA: C.amber };
|
|
16205
16524
|
function typeBadge(type) {
|
|
@@ -16491,26 +16810,38 @@ var CONSOLE_SCRIPT = `<script>
|
|
|
16491
16810
|
chips[c].classList.toggle("on", !!active[chips[c].getAttribute("data-filter")]);
|
|
16492
16811
|
}
|
|
16493
16812
|
}
|
|
16494
|
-
// 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;
|
|
16495
16822
|
function applyRange(range) {
|
|
16496
16823
|
var rows = document.querySelectorAll(".cy-row");
|
|
16497
16824
|
var nowSec = Math.floor(Date.now() / 1000);
|
|
16498
|
-
var horizon = range === "all" ? Infinity : Number(range) * 86400;
|
|
16499
|
-
var
|
|
16825
|
+
var horizon = range === "all" || range === "recent" ? Infinity : Number(range) * 86400;
|
|
16826
|
+
var shown = 0, failedAll = 0, kept = 0;
|
|
16500
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
|
|
16501
16831
|
var ts = Number(rows[i].getAttribute("data-ts")) || 0;
|
|
16502
|
-
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;
|
|
16503
16837
|
rows[i].style.display = show ? "" : "none";
|
|
16504
|
-
if (show)
|
|
16505
|
-
|
|
16506
|
-
var v = rows[i].getAttribute("data-verdict");
|
|
16507
|
-
if (v === "failed" || v === "reverted" || v === "blocked") failed++;
|
|
16508
|
-
}
|
|
16838
|
+
if (show) shown++;
|
|
16839
|
+
if (inWindow) kept++; // the cap counts non-fail slots; failures are bonus
|
|
16509
16840
|
}
|
|
16510
16841
|
var c = document.getElementById("cy-count");
|
|
16511
16842
|
var f = document.getElementById("cy-failed");
|
|
16512
|
-
if (c) c.textContent = String(
|
|
16513
|
-
if (f) f.textContent = String(
|
|
16843
|
+
if (c) c.textContent = String(shown);
|
|
16844
|
+
if (f) f.textContent = String(failedAll);
|
|
16514
16845
|
var btns = document.querySelectorAll(".cy-range");
|
|
16515
16846
|
for (var b = 0; b < btns.length; b++) btns[b].classList.toggle("on", btns[b].getAttribute("data-range") === range);
|
|
16516
16847
|
}
|
|
@@ -16612,7 +16943,7 @@ var CONSOLE_SCRIPT = `<script>
|
|
|
16612
16943
|
for (var rb = 0; rb < rbs.length; rb++) {
|
|
16613
16944
|
rbs[rb].addEventListener("click", function () { applyRange(this.getAttribute("data-range")); });
|
|
16614
16945
|
}
|
|
16615
|
-
applyRange("
|
|
16946
|
+
applyRange("recent");
|
|
16616
16947
|
applyFreshness();
|
|
16617
16948
|
tickCountdown();
|
|
16618
16949
|
setInterval(tickCountdown, 30000);
|
|
@@ -16789,7 +17120,7 @@ ${CONSOLE_SCRIPT}
|
|
|
16789
17120
|
}
|
|
16790
17121
|
|
|
16791
17122
|
// packages/cli/dist/lib/page-charter.js
|
|
16792
|
-
import { existsSync as existsSync20, readFileSync as
|
|
17123
|
+
import { existsSync as existsSync20, readFileSync as readFileSync19, readdirSync as readdirSync8, statSync as statSync10 } from "node:fs";
|
|
16793
17124
|
import { join as join18 } from "node:path";
|
|
16794
17125
|
function docTitle(src, path) {
|
|
16795
17126
|
for (const raw of src.split("\n")) {
|
|
@@ -16858,7 +17189,7 @@ function defaultCharterDeps(cwd, render2) {
|
|
|
16858
17189
|
if (!existsSync20(abs))
|
|
16859
17190
|
return void 0;
|
|
16860
17191
|
try {
|
|
16861
|
-
return
|
|
17192
|
+
return readFileSync19(abs, "utf8");
|
|
16862
17193
|
} catch {
|
|
16863
17194
|
return void 0;
|
|
16864
17195
|
}
|
|
@@ -17044,7 +17375,7 @@ function renderAboutPage(input) {
|
|
|
17044
17375
|
// packages/cli/dist/lib/page-conventions.js
|
|
17045
17376
|
init_dist3();
|
|
17046
17377
|
init_dist2();
|
|
17047
|
-
import { existsSync as existsSync22, readFileSync as
|
|
17378
|
+
import { existsSync as existsSync22, readFileSync as readFileSync20 } from "node:fs";
|
|
17048
17379
|
import { join as join20 } from "node:path";
|
|
17049
17380
|
var SYNC_KEYS = [
|
|
17050
17381
|
{ key: "sync_claude", agent: "claude" },
|
|
@@ -17082,7 +17413,7 @@ function defaultConventionsDeps(cwd, agents, render2) {
|
|
|
17082
17413
|
if (!existsSync22(abs))
|
|
17083
17414
|
return void 0;
|
|
17084
17415
|
try {
|
|
17085
|
-
return
|
|
17416
|
+
return readFileSync20(abs, "utf8");
|
|
17086
17417
|
} catch {
|
|
17087
17418
|
return void 0;
|
|
17088
17419
|
}
|
|
@@ -17127,7 +17458,7 @@ function renderConventionsPage(input) {
|
|
|
17127
17458
|
}
|
|
17128
17459
|
|
|
17129
17460
|
// packages/cli/dist/lib/projects-registry.js
|
|
17130
|
-
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";
|
|
17131
17462
|
import { homedir as homedir6, tmpdir } from "node:os";
|
|
17132
17463
|
import { dirname as dirname11, join as join21, sep } from "node:path";
|
|
17133
17464
|
function registryHome(home) {
|
|
@@ -17166,7 +17497,7 @@ function parseProjectsRegistry(text) {
|
|
|
17166
17497
|
function collectProjectsRegistry(home) {
|
|
17167
17498
|
let text;
|
|
17168
17499
|
try {
|
|
17169
|
-
text =
|
|
17500
|
+
text = readFileSync21(projectsRegistryPath(home), "utf8");
|
|
17170
17501
|
} catch {
|
|
17171
17502
|
return [];
|
|
17172
17503
|
}
|
|
@@ -17217,7 +17548,7 @@ function writeProjectRow(entry, home) {
|
|
|
17217
17548
|
|
|
17218
17549
|
// packages/cli/dist/lib/cycle-ledger.js
|
|
17219
17550
|
init_dist();
|
|
17220
|
-
import { existsSync as existsSync24, readFileSync as
|
|
17551
|
+
import { existsSync as existsSync24, readFileSync as readFileSync22 } from "node:fs";
|
|
17221
17552
|
import { join as join22 } from "node:path";
|
|
17222
17553
|
function ledgerVerdict(status2, outcome) {
|
|
17223
17554
|
if (status2 === "reverted")
|
|
@@ -17236,6 +17567,20 @@ function ledgerVerdict(status2, outcome) {
|
|
|
17236
17567
|
function ledgerFailedCount(rows) {
|
|
17237
17568
|
return rows.filter((r) => r.verdict === "failed" || r.verdict === "reverted" || r.verdict === "blocked").length;
|
|
17238
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
|
+
}
|
|
17239
17584
|
function fmtTokens2(tin, tout, usageUnknown) {
|
|
17240
17585
|
if (usageUnknown)
|
|
17241
17586
|
return "?";
|
|
@@ -17262,7 +17607,7 @@ function readEventFacts(projectPath3) {
|
|
|
17262
17607
|
return { byCycle, prMergedBy, prOpenBy };
|
|
17263
17608
|
let content = "";
|
|
17264
17609
|
try {
|
|
17265
|
-
content =
|
|
17610
|
+
content = readFileSync22(path, "utf8");
|
|
17266
17611
|
} catch {
|
|
17267
17612
|
return { byCycle, prMergedBy, prOpenBy };
|
|
17268
17613
|
}
|
|
@@ -17317,7 +17662,7 @@ function collectCycleLedger(projectPath3) {
|
|
|
17317
17662
|
return [];
|
|
17318
17663
|
let content = "";
|
|
17319
17664
|
try {
|
|
17320
|
-
content =
|
|
17665
|
+
content = readFileSync22(runsPath3, "utf8");
|
|
17321
17666
|
} catch {
|
|
17322
17667
|
return [];
|
|
17323
17668
|
}
|
|
@@ -17338,6 +17683,8 @@ function collectCycleLedger(projectPath3) {
|
|
|
17338
17683
|
const status2 = String(row2["status"] ?? "");
|
|
17339
17684
|
const outcome = String(row2["outcome"] ?? "");
|
|
17340
17685
|
const verdict = ledgerVerdict(status2, outcome);
|
|
17686
|
+
if (isIdleHeartbeat(row2, verdict))
|
|
17687
|
+
continue;
|
|
17341
17688
|
const storyId = typeof row2["story_id"] === "string" ? row2["story_id"] : "";
|
|
17342
17689
|
const rawTs = row2["ts"];
|
|
17343
17690
|
const ts = typeof rawTs === "string" ? Date.parse(rawTs) : typeof rawTs === "number" ? rawTs > 1e10 ? rawTs : rawTs * 1e3 : Number.NaN;
|
|
@@ -17373,14 +17720,14 @@ function collectCycleLedger(projectPath3) {
|
|
|
17373
17720
|
|
|
17374
17721
|
// packages/cli/dist/lib/agent-panel.js
|
|
17375
17722
|
init_dist2();
|
|
17376
|
-
import { existsSync as existsSync26, readFileSync as
|
|
17723
|
+
import { existsSync as existsSync26, readFileSync as readFileSync24 } from "node:fs";
|
|
17377
17724
|
import { join as join24 } from "node:path";
|
|
17378
17725
|
|
|
17379
17726
|
// packages/cli/dist/commands/status.js
|
|
17380
17727
|
init_dist();
|
|
17381
17728
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
17382
17729
|
import { createHash as createHash4 } from "node:crypto";
|
|
17383
|
-
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";
|
|
17384
17731
|
import { homedir as homedir7 } from "node:os";
|
|
17385
17732
|
import { basename as basename7, dirname as dirname12, join as join23 } from "node:path";
|
|
17386
17733
|
function rollHome2() {
|
|
@@ -17414,7 +17761,7 @@ function parseAiEntries() {
|
|
|
17414
17761
|
if (!existsSync25(cfg))
|
|
17415
17762
|
return [];
|
|
17416
17763
|
const entries = [];
|
|
17417
|
-
for (const line of
|
|
17764
|
+
for (const line of readFileSync23(cfg, "utf8").split("\n")) {
|
|
17418
17765
|
const m7 = /^ai_[a-z]+:\s*(.+)/.exec(line);
|
|
17419
17766
|
if (m7 === null)
|
|
17420
17767
|
continue;
|
|
@@ -17442,13 +17789,13 @@ function aiSyncStatus(e) {
|
|
|
17442
17789
|
if (!existsSync25(rollMd))
|
|
17443
17790
|
return "out-of-sync";
|
|
17444
17791
|
try {
|
|
17445
|
-
if (existsSync25(src) && !
|
|
17792
|
+
if (existsSync25(src) && !readFileSync23(rollMd).equals(readFileSync23(src)))
|
|
17446
17793
|
return "out-of-sync";
|
|
17447
17794
|
} catch {
|
|
17448
17795
|
return "out-of-sync";
|
|
17449
17796
|
}
|
|
17450
17797
|
try {
|
|
17451
|
-
if (!
|
|
17798
|
+
if (!readFileSync23(cfgFile, "utf8").includes("@roll.md"))
|
|
17452
17799
|
return "out-of-sync";
|
|
17453
17800
|
} catch {
|
|
17454
17801
|
return "out-of-sync";
|
|
@@ -17857,7 +18204,7 @@ function spend72h(projectPath3, nowSec2) {
|
|
|
17857
18204
|
return out3;
|
|
17858
18205
|
let content = "";
|
|
17859
18206
|
try {
|
|
17860
|
-
content =
|
|
18207
|
+
content = readFileSync24(path, "utf8");
|
|
17861
18208
|
} catch {
|
|
17862
18209
|
return out3;
|
|
17863
18210
|
}
|
|
@@ -17926,7 +18273,7 @@ function collectAgentPanel(projectPath3, deps = defaultAgentPanelDeps()) {
|
|
|
17926
18273
|
// packages/cli/dist/lib/release-panel.js
|
|
17927
18274
|
init_dist2();
|
|
17928
18275
|
init_dist();
|
|
17929
|
-
import { existsSync as existsSync27, readFileSync as
|
|
18276
|
+
import { existsSync as existsSync27, readFileSync as readFileSync25, readdirSync as readdirSync10 } from "node:fs";
|
|
17930
18277
|
import { join as join25 } from "node:path";
|
|
17931
18278
|
function collectReleasePanel(projectPath3) {
|
|
17932
18279
|
const dimsEmpty = CONSISTENCY_DIMENSIONS.map((key) => ({
|
|
@@ -17938,7 +18285,7 @@ function collectReleasePanel(projectPath3) {
|
|
|
17938
18285
|
try {
|
|
17939
18286
|
const latest = readdirSync10(dir).filter((f) => f.endsWith(".json")).sort().at(-1);
|
|
17940
18287
|
if (latest !== void 0) {
|
|
17941
|
-
const obj = JSON.parse(
|
|
18288
|
+
const obj = JSON.parse(readFileSync25(join25(dir, latest), "utf8"));
|
|
17942
18289
|
const findings = Array.isArray(obj.findings) ? obj.findings : [];
|
|
17943
18290
|
const tallies = tallyByDimension(findings);
|
|
17944
18291
|
out3.dims = CONSISTENCY_DIMENSIONS.map((key) => ({ key, tally: tallies[key] }));
|
|
@@ -17957,7 +18304,7 @@ function collectReleasePanel(projectPath3) {
|
|
|
17957
18304
|
const path = join25(projectPath3, ".roll", "loop", "events.ndjson");
|
|
17958
18305
|
if (existsSync27(path)) {
|
|
17959
18306
|
const tags = [];
|
|
17960
|
-
for (const line of
|
|
18307
|
+
for (const line of readFileSync25(path, "utf8").split("\n")) {
|
|
17961
18308
|
const e = parseEventLine(line);
|
|
17962
18309
|
if (e !== null && e.type === "release:gate" && typeof e.tag === "string" && e.tag !== "" && tags.at(-1) !== e.tag) {
|
|
17963
18310
|
tags.push(e.tag);
|
|
@@ -17973,7 +18320,7 @@ function collectReleasePanel(projectPath3) {
|
|
|
17973
18320
|
|
|
17974
18321
|
// packages/cli/dist/lib/release-scope.js
|
|
17975
18322
|
init_dist();
|
|
17976
|
-
import { existsSync as existsSync28, readFileSync as
|
|
18323
|
+
import { existsSync as existsSync28, readFileSync as readFileSync26 } from "node:fs";
|
|
17977
18324
|
import { join as join26 } from "node:path";
|
|
17978
18325
|
function groupByEpic(items) {
|
|
17979
18326
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -17990,7 +18337,7 @@ function prFromEvents(projectPath3) {
|
|
|
17990
18337
|
if (!existsSync28(path))
|
|
17991
18338
|
return out3;
|
|
17992
18339
|
try {
|
|
17993
|
-
for (const line of
|
|
18340
|
+
for (const line of readFileSync26(path, "utf8").split("\n")) {
|
|
17994
18341
|
const e = parseEventLine(line);
|
|
17995
18342
|
if (e !== null && e.type === "pr:merge")
|
|
17996
18343
|
out3.set(e.storyId, e.prNumber);
|
|
@@ -18027,7 +18374,7 @@ function collectHistory(projectPath3) {
|
|
|
18027
18374
|
return [];
|
|
18028
18375
|
let text = "";
|
|
18029
18376
|
try {
|
|
18030
|
-
text =
|
|
18377
|
+
text = readFileSync26(path, "utf8");
|
|
18031
18378
|
} catch {
|
|
18032
18379
|
return [];
|
|
18033
18380
|
}
|
|
@@ -18035,7 +18382,7 @@ function collectHistory(projectPath3) {
|
|
|
18035
18382
|
try {
|
|
18036
18383
|
const ev = join26(projectPath3, ".roll", "loop", "events.ndjson");
|
|
18037
18384
|
if (existsSync28(ev)) {
|
|
18038
|
-
for (const line of
|
|
18385
|
+
for (const line of readFileSync26(ev, "utf8").split("\n")) {
|
|
18039
18386
|
const e = parseEventLine(line);
|
|
18040
18387
|
if (e !== null && e.type === "release:gate" && Array.isArray(e.waivedRules) && e.waivedRules.length > 0) {
|
|
18041
18388
|
waivedTags.add(e.tag);
|
|
@@ -18068,11 +18415,11 @@ function collectHistory(projectPath3) {
|
|
|
18068
18415
|
}
|
|
18069
18416
|
|
|
18070
18417
|
// packages/cli/dist/lib/skills-panel.js
|
|
18071
|
-
import { existsSync as existsSync30, readFileSync as
|
|
18418
|
+
import { existsSync as existsSync30, readFileSync as readFileSync28, readdirSync as readdirSync12, statSync as statSync12 } from "node:fs";
|
|
18072
18419
|
import { join as join28 } from "node:path";
|
|
18073
18420
|
|
|
18074
18421
|
// packages/cli/dist/lib/skills-audit.js
|
|
18075
|
-
import { existsSync as existsSync29, readFileSync as
|
|
18422
|
+
import { existsSync as existsSync29, readFileSync as readFileSync27, readdirSync as readdirSync11 } from "node:fs";
|
|
18076
18423
|
import { join as join27, relative as relative3, sep as sep2 } from "node:path";
|
|
18077
18424
|
function stripYamlQuotes(value) {
|
|
18078
18425
|
const trimmed = value.trim();
|
|
@@ -18154,7 +18501,7 @@ function collectReferencedSpokes(body) {
|
|
|
18154
18501
|
return [...refs].sort();
|
|
18155
18502
|
}
|
|
18156
18503
|
function parseSkillFile(file) {
|
|
18157
|
-
const text =
|
|
18504
|
+
const text = readFileSync27(file, "utf8");
|
|
18158
18505
|
const { fields, body, ok: ok8 } = parseFrontmatter(text);
|
|
18159
18506
|
const skillDir = join27(file, "..");
|
|
18160
18507
|
const description = fields["description"] ?? "";
|
|
@@ -18187,7 +18534,7 @@ function loadRouteCases(routeFile) {
|
|
|
18187
18534
|
if (!existsSync29(routeFile))
|
|
18188
18535
|
return { skills: {} };
|
|
18189
18536
|
try {
|
|
18190
|
-
return JSON.parse(
|
|
18537
|
+
return JSON.parse(readFileSync27(routeFile, "utf8"));
|
|
18191
18538
|
} catch {
|
|
18192
18539
|
return { skills: {} };
|
|
18193
18540
|
}
|
|
@@ -18291,7 +18638,7 @@ function skillGroupOf(name) {
|
|
|
18291
18638
|
}
|
|
18292
18639
|
function lineCount(path) {
|
|
18293
18640
|
try {
|
|
18294
|
-
return
|
|
18641
|
+
return readFileSync28(path, "utf8").split("\n").length;
|
|
18295
18642
|
} catch {
|
|
18296
18643
|
return 0;
|
|
18297
18644
|
}
|
|
@@ -18355,7 +18702,7 @@ function collectSkillsPanel(projectPath3, deps = defaultSkillsPanelDeps(projectP
|
|
|
18355
18702
|
usage: usage2[name] ?? 0,
|
|
18356
18703
|
files: skillFiles(dir),
|
|
18357
18704
|
dirPath: dir,
|
|
18358
|
-
hubText: existsSync30(hubPath) ?
|
|
18705
|
+
hubText: existsSync30(hubPath) ? readFileSync28(hubPath, "utf8") : ""
|
|
18359
18706
|
};
|
|
18360
18707
|
});
|
|
18361
18708
|
const hubLines = rows.reduce((acc, r) => acc + r.hubLines, 0);
|
|
@@ -18528,7 +18875,7 @@ function renderSkillsPage(input) {
|
|
|
18528
18875
|
}
|
|
18529
18876
|
|
|
18530
18877
|
// packages/cli/dist/lib/loop-heartbeat.js
|
|
18531
|
-
import { existsSync as existsSync31, readFileSync as
|
|
18878
|
+
import { existsSync as existsSync31, readFileSync as readFileSync29 } from "node:fs";
|
|
18532
18879
|
import { join as join29 } from "node:path";
|
|
18533
18880
|
var LANES = ["loop", "dream"];
|
|
18534
18881
|
function defaultHeartbeatDeps(projectPath3, slug, launchAgentsDir3) {
|
|
@@ -18536,14 +18883,14 @@ function defaultHeartbeatDeps(projectPath3, slug, launchAgentsDir3) {
|
|
|
18536
18883
|
plistText: (svc) => {
|
|
18537
18884
|
const p = join29(launchAgentsDir3, `com.roll.${svc}.${slug}.plist`);
|
|
18538
18885
|
try {
|
|
18539
|
-
return existsSync31(p) ?
|
|
18886
|
+
return existsSync31(p) ? readFileSync29(p, "utf8") : null;
|
|
18540
18887
|
} catch {
|
|
18541
18888
|
return null;
|
|
18542
18889
|
}
|
|
18543
18890
|
},
|
|
18544
18891
|
lastRunAt: () => {
|
|
18545
18892
|
try {
|
|
18546
|
-
const lines2 =
|
|
18893
|
+
const lines2 = readFileSync29(join29(projectPath3, ".roll", "loop", "runs.jsonl"), "utf8").trim().split("\n");
|
|
18547
18894
|
for (let i = lines2.length - 1; i >= 0; i--) {
|
|
18548
18895
|
const line = lines2[i] ?? "";
|
|
18549
18896
|
if (line.trim() === "")
|
|
@@ -18600,7 +18947,7 @@ function collectLoopHeartbeat(deps) {
|
|
|
18600
18947
|
|
|
18601
18948
|
// packages/cli/dist/lib/casting.js
|
|
18602
18949
|
init_dist2();
|
|
18603
|
-
import { existsSync as existsSync32, readFileSync as
|
|
18950
|
+
import { existsSync as existsSync32, readFileSync as readFileSync30 } from "node:fs";
|
|
18604
18951
|
import { join as join30 } from "node:path";
|
|
18605
18952
|
var EM_DASH = "\u2014";
|
|
18606
18953
|
function slotRow(key, roleEn, roleZh, deps) {
|
|
@@ -18689,7 +19036,7 @@ function defaultCastingDeps(projectPath3) {
|
|
|
18689
19036
|
const agentsPath2 = process.env["ROLL_AGENTS_CONFIG"] ?? join30(projectPath3, ".roll", "agents.yaml");
|
|
18690
19037
|
try {
|
|
18691
19038
|
if (existsSync32(agentsPath2))
|
|
18692
|
-
agentsText =
|
|
19039
|
+
agentsText = readFileSync30(agentsPath2, "utf8");
|
|
18693
19040
|
} catch {
|
|
18694
19041
|
agentsText = null;
|
|
18695
19042
|
}
|
|
@@ -18697,7 +19044,7 @@ function defaultCastingDeps(projectPath3) {
|
|
|
18697
19044
|
try {
|
|
18698
19045
|
const evPath = join30(projectPath3, ".roll", "loop", "events.ndjson");
|
|
18699
19046
|
if (existsSync32(evPath)) {
|
|
18700
|
-
const content =
|
|
19047
|
+
const content = readFileSync30(evPath, "utf8");
|
|
18701
19048
|
for (const line of content.split("\n")) {
|
|
18702
19049
|
const t2 = line.trim();
|
|
18703
19050
|
if (t2 === "" || !t2.includes("route:resolve"))
|
|
@@ -18736,7 +19083,7 @@ init_dist2();
|
|
|
18736
19083
|
init_dist();
|
|
18737
19084
|
import { createHash as createHash5 } from "node:crypto";
|
|
18738
19085
|
import { spawn as spawn2, spawnSync } from "node:child_process";
|
|
18739
|
-
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";
|
|
18740
19087
|
import { homedir as homedir8 } from "node:os";
|
|
18741
19088
|
import { dirname as dirname13, join as join31 } from "node:path";
|
|
18742
19089
|
function realDeps2() {
|
|
@@ -19011,7 +19358,7 @@ function syncGoalPaused(projectPath3, reason) {
|
|
|
19011
19358
|
if (!existsSync33(path))
|
|
19012
19359
|
return;
|
|
19013
19360
|
try {
|
|
19014
|
-
const before = parseGoalYaml(
|
|
19361
|
+
const before = parseGoalYaml(readFileSync31(path, "utf8"));
|
|
19015
19362
|
if (before.status === "paused" || before.status === "complete")
|
|
19016
19363
|
return;
|
|
19017
19364
|
const at = (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
@@ -19053,7 +19400,7 @@ async function loopOnCommand(_args, deps = realDeps2()) {
|
|
|
19053
19400
|
const localYaml = join31(id.path, ".roll", "local.yaml");
|
|
19054
19401
|
if (existsSync33(localYaml)) {
|
|
19055
19402
|
try {
|
|
19056
|
-
period = parseLoopPeriodMinutes(
|
|
19403
|
+
period = parseLoopPeriodMinutes(readFileSync31(localYaml, "utf8"));
|
|
19057
19404
|
} catch {
|
|
19058
19405
|
}
|
|
19059
19406
|
}
|
|
@@ -19202,7 +19549,7 @@ async function loopResumeCommand(_args, deps = realDeps2()) {
|
|
|
19202
19549
|
const stateFile2 = join31(rt, `state-${id.slug}.yaml`);
|
|
19203
19550
|
if (existsSync33(stateFile2)) {
|
|
19204
19551
|
try {
|
|
19205
|
-
const body =
|
|
19552
|
+
const body = readFileSync31(stateFile2, "utf8");
|
|
19206
19553
|
const lines2 = body.split("\n").filter((l) => /^(?!heal_count_head_)/.test(l));
|
|
19207
19554
|
writeFileSync14(stateFile2, lines2.join("\n"), "utf8");
|
|
19208
19555
|
} catch {
|
|
@@ -19245,7 +19592,7 @@ async function loopNowCommand(_args, deps = realDeps2()) {
|
|
|
19245
19592
|
let legacy = false;
|
|
19246
19593
|
if (existsSync33(runner)) {
|
|
19247
19594
|
try {
|
|
19248
|
-
legacy = isLegacyRunner(
|
|
19595
|
+
legacy = isLegacyRunner(readFileSync31(runner, "utf8"));
|
|
19249
19596
|
} catch {
|
|
19250
19597
|
legacy = true;
|
|
19251
19598
|
}
|
|
@@ -19405,7 +19752,7 @@ ${CHROME_CONTROLS}
|
|
|
19405
19752
|
init_dist2();
|
|
19406
19753
|
init_dist();
|
|
19407
19754
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
19408
|
-
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";
|
|
19409
19756
|
import { join as joinPath2 } from "node:path";
|
|
19410
19757
|
var esc6 = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
19411
19758
|
function storyDeliveryState(d) {
|
|
@@ -20798,7 +21145,7 @@ function rebaseAcEvidenceToStoryRoot(ev) {
|
|
|
20798
21145
|
return ev.map((e) => e.href !== void 0 ? { ...e, href: rebaseEvidenceHrefToStoryRoot(e.href) } : e);
|
|
20799
21146
|
}
|
|
20800
21147
|
function readFile(p) {
|
|
20801
|
-
return
|
|
21148
|
+
return readFileSync32(p, "utf8");
|
|
20802
21149
|
}
|
|
20803
21150
|
function statDir(p) {
|
|
20804
21151
|
return statSync13(p).isFile();
|
|
@@ -20823,7 +21170,7 @@ function renderNowSec() {
|
|
|
20823
21170
|
function readJsonl(path) {
|
|
20824
21171
|
let content;
|
|
20825
21172
|
try {
|
|
20826
|
-
content =
|
|
21173
|
+
content = readFileSync33(path, "utf8");
|
|
20827
21174
|
} catch {
|
|
20828
21175
|
return void 0;
|
|
20829
21176
|
}
|
|
@@ -20866,7 +21213,7 @@ function latestConsistencyAudit(projectPath3) {
|
|
|
20866
21213
|
if (latest === void 0)
|
|
20867
21214
|
return void 0;
|
|
20868
21215
|
try {
|
|
20869
|
-
const obj = JSON.parse(
|
|
21216
|
+
const obj = JSON.parse(readFileSync33(join32(dir, latest), "utf8"));
|
|
20870
21217
|
const summary = obj["summary"];
|
|
20871
21218
|
if (typeof summary !== "object" || summary === null || Array.isArray(summary))
|
|
20872
21219
|
return void 0;
|
|
@@ -20923,7 +21270,7 @@ function releaseTruthBoard(projectPath3, nowSec2) {
|
|
|
20923
21270
|
const path = join32(projectPath3, ".roll", "loop", "events.ndjson");
|
|
20924
21271
|
let content;
|
|
20925
21272
|
try {
|
|
20926
|
-
content =
|
|
21273
|
+
content = readFileSync33(path, "utf8");
|
|
20927
21274
|
} catch {
|
|
20928
21275
|
return void 0;
|
|
20929
21276
|
}
|
|
@@ -20989,7 +21336,7 @@ function renderSpecHtml(storyDir, id) {
|
|
|
20989
21336
|
return null;
|
|
20990
21337
|
let md;
|
|
20991
21338
|
try {
|
|
20992
|
-
md =
|
|
21339
|
+
md = readFileSync33(specPath, "utf8");
|
|
20993
21340
|
} catch {
|
|
20994
21341
|
return null;
|
|
20995
21342
|
}
|
|
@@ -21250,7 +21597,7 @@ function defaultProcessReaders(projectPath3, env) {
|
|
|
21250
21597
|
if (!existsSync36(p))
|
|
21251
21598
|
return null;
|
|
21252
21599
|
try {
|
|
21253
|
-
return
|
|
21600
|
+
return readFileSync34(p, "utf8");
|
|
21254
21601
|
} catch {
|
|
21255
21602
|
return null;
|
|
21256
21603
|
}
|
|
@@ -21477,7 +21824,7 @@ function readAcMap(storyDir) {
|
|
|
21477
21824
|
if (!existsSync36(p))
|
|
21478
21825
|
return null;
|
|
21479
21826
|
try {
|
|
21480
|
-
const arr2 = JSON.parse(
|
|
21827
|
+
const arr2 = JSON.parse(readFileSync34(p, "utf8"));
|
|
21481
21828
|
if (!Array.isArray(arr2))
|
|
21482
21829
|
return null;
|
|
21483
21830
|
const m7 = /* @__PURE__ */ new Map();
|
|
@@ -21498,7 +21845,7 @@ function toRef(runDir, e) {
|
|
|
21498
21845
|
if (!existsSync36(p))
|
|
21499
21846
|
return null;
|
|
21500
21847
|
try {
|
|
21501
|
-
const { redacted, hits } = redactSecrets(
|
|
21848
|
+
const { redacted, hits } = redactSecrets(readFileSync34(p, "utf8"));
|
|
21502
21849
|
if (hits.length > 0)
|
|
21503
21850
|
warn2(`redacted secret(s) in ${e.textFile}: ${hits.join(", ")}`);
|
|
21504
21851
|
return { kind, label: label4, inlineHtml: ansiPre(redacted) };
|
|
@@ -21517,7 +21864,7 @@ function toRef(runDir, e) {
|
|
|
21517
21864
|
return null;
|
|
21518
21865
|
}
|
|
21519
21866
|
if (kind === "cast") {
|
|
21520
|
-
const { redacted, hits } = redactSecrets(
|
|
21867
|
+
const { redacted, hits } = redactSecrets(readFileSync34(p, "utf8"));
|
|
21521
21868
|
if (hits.length > 0)
|
|
21522
21869
|
warn2(`redacted secret(s) in ${e.href}: ${hits.join(", ")}`);
|
|
21523
21870
|
const bounded = boundTranscript(redacted);
|
|
@@ -21557,7 +21904,7 @@ function readBacklogRow(projectPath3, storyId) {
|
|
|
21557
21904
|
return {};
|
|
21558
21905
|
let text;
|
|
21559
21906
|
try {
|
|
21560
|
-
text =
|
|
21907
|
+
text = readFileSync34(p, "utf8");
|
|
21561
21908
|
} catch {
|
|
21562
21909
|
return {};
|
|
21563
21910
|
}
|
|
@@ -21595,7 +21942,7 @@ function buildCardContext(projectPath3, featureFile, storyId, env) {
|
|
|
21595
21942
|
const oneLiner = row2.description !== void 0 ? row2.description.replace(/\s*depends-on:\S+/gi, "").trim() : void 0;
|
|
21596
21943
|
let summary;
|
|
21597
21944
|
try {
|
|
21598
|
-
summary = extractSummary(
|
|
21945
|
+
summary = extractSummary(readFileSync34(featureFile, "utf8"));
|
|
21599
21946
|
} catch {
|
|
21600
21947
|
}
|
|
21601
21948
|
const epic = epicFromFeaturePath(featureFile);
|
|
@@ -21714,7 +22061,7 @@ function ensurePreEvidenceMarker(storyId, runDir) {
|
|
|
21714
22061
|
function resolveStoryAcItems(projectPath3, storyId) {
|
|
21715
22062
|
for (const cand of findFeatureFiles(projectPath3, storyId)) {
|
|
21716
22063
|
try {
|
|
21717
|
-
const items = acForStory(
|
|
22064
|
+
const items = acForStory(readFileSync34(cand, "utf8"), storyId, {
|
|
21718
22065
|
fileOwned: basename8(cand) === `${storyId}.md`
|
|
21719
22066
|
});
|
|
21720
22067
|
if (items.length > 0)
|
|
@@ -21755,7 +22102,7 @@ async function attestBackfillCommand(args, deps) {
|
|
|
21755
22102
|
return 1;
|
|
21756
22103
|
}
|
|
21757
22104
|
const stats = { scanned: 0, backfilled: 0, skippedExisting: 0, skippedMissingCard: 0, failed: 0 };
|
|
21758
|
-
const items = parseBacklog(
|
|
22105
|
+
const items = parseBacklog(readFileSync34(backlogPath, "utf8")).filter((item) => classifyStatus(item.status) === "done");
|
|
21759
22106
|
for (const item of items) {
|
|
21760
22107
|
stats.scanned += 1;
|
|
21761
22108
|
const featureFile = findFeatureFile(projectPath3, item.id);
|
|
@@ -21944,7 +22291,7 @@ async function attestCommand(args, deps = {}) {
|
|
|
21944
22291
|
const deliveryHtml = `<p><a href="${reportRel}">${bi("Attestation report", "\u9A8C\u6536\u62A5\u544A")}</a></p>
|
|
21945
22292
|
` + dossierVisualsHtml(runRel, beforeAfter, afterOnly) + `<p class="muted">${bi("Delivered", "\u4EA4\u4ED8\u4E8E")} ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}</p>
|
|
21946
22293
|
`;
|
|
21947
|
-
const idx = markPhaseDone(
|
|
22294
|
+
const idx = markPhaseDone(readFileSync34(indexPath, "utf8"), "delivery", deliveryHtml);
|
|
21948
22295
|
writeFileSync16(indexPath, idx, "utf8");
|
|
21949
22296
|
} catch {
|
|
21950
22297
|
}
|
|
@@ -21973,12 +22320,12 @@ async function attestCommand(args, deps = {}) {
|
|
|
21973
22320
|
|
|
21974
22321
|
// packages/cli/dist/commands/backlog.js
|
|
21975
22322
|
init_dist();
|
|
21976
|
-
import { existsSync as existsSync37, readFileSync as
|
|
22323
|
+
import { existsSync as existsSync37, readFileSync as readFileSync35 } from "node:fs";
|
|
21977
22324
|
var ID_RE = /\[([^\]]+)\]\([^)]+\)/;
|
|
21978
22325
|
var REASON_RE = /\[([^\]]+)\]/;
|
|
21979
22326
|
function parseBacklog2(path) {
|
|
21980
22327
|
const items = [];
|
|
21981
|
-
for (const raw of
|
|
22328
|
+
for (const raw of readFileSync35(path, "utf8").split("\n")) {
|
|
21982
22329
|
const line = raw.replace(/\n$/, "");
|
|
21983
22330
|
if (!line.startsWith("|"))
|
|
21984
22331
|
continue;
|
|
@@ -22100,7 +22447,7 @@ function backlogCommand(args) {
|
|
|
22100
22447
|
// packages/cli/dist/commands/backlog-mgmt.js
|
|
22101
22448
|
init_dist2();
|
|
22102
22449
|
init_dist();
|
|
22103
|
-
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";
|
|
22104
22451
|
import { dirname as dirname14, join as join34 } from "node:path";
|
|
22105
22452
|
var BACKLOG_PATH = ".roll/backlog.md";
|
|
22106
22453
|
function lang() {
|
|
@@ -22221,8 +22568,8 @@ function backlogUnstickCommand(args, deps = realUnstickDeps()) {
|
|
|
22221
22568
|
const slug = deps.slug();
|
|
22222
22569
|
const loopDir = join34(deps.sharedRoot(), "loop");
|
|
22223
22570
|
const eventsPath2 = join34(loopDir, `events-${slug}.ndjson`);
|
|
22224
|
-
const events = existsSync38(eventsPath2) ? parseUnstickEvents(
|
|
22225
|
-
const content =
|
|
22571
|
+
const events = existsSync38(eventsPath2) ? parseUnstickEvents(readFileSync36(eventsPath2, "utf8")) : [];
|
|
22572
|
+
const content = readFileSync36(backlog, "utf8");
|
|
22226
22573
|
const nowMs = deps.nowMs();
|
|
22227
22574
|
const candidates = reconcileStuckBacklog(content, events, nowMs, ttlHours);
|
|
22228
22575
|
if (candidates.length === 0)
|
|
@@ -22283,7 +22630,7 @@ function backlogLintCommand(args) {
|
|
|
22283
22630
|
errLine(`[roll] backlog not found: ${backlog}`);
|
|
22284
22631
|
return 1;
|
|
22285
22632
|
}
|
|
22286
|
-
const findings = lintBacklogContent(
|
|
22633
|
+
const findings = lintBacklogContent(readFileSync36(backlog, "utf8"));
|
|
22287
22634
|
for (const f of findings) {
|
|
22288
22635
|
out(`${backlog}:${f.lineno}: ${f.sid} \u2014 ${f.issues}`);
|
|
22289
22636
|
out(` ${f.desc}`);
|
|
@@ -22305,7 +22652,7 @@ function backlogLintCommand(args) {
|
|
|
22305
22652
|
// packages/cli/dist/commands/backlog-sync.js
|
|
22306
22653
|
init_dist2();
|
|
22307
22654
|
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
22308
|
-
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";
|
|
22309
22656
|
import { dirname as dirname15, join as join35 } from "node:path";
|
|
22310
22657
|
var API_ROOT = "https://api.github.com";
|
|
22311
22658
|
var RATE_LIMIT_FLOOR = 5;
|
|
@@ -22400,7 +22747,7 @@ function realSyncDeps() {
|
|
|
22400
22747
|
loadIssues: async (owner, repo) => {
|
|
22401
22748
|
const fixture = (process.env["ROLL_SYNC_FIXTURE"] ?? "").trim();
|
|
22402
22749
|
if (fixture)
|
|
22403
|
-
return JSON.parse(
|
|
22750
|
+
return JSON.parse(readFileSync37(fixture, "utf8"));
|
|
22404
22751
|
return fetchIssues(owner, repo, { state: "open" });
|
|
22405
22752
|
},
|
|
22406
22753
|
nowIso: () => (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z")
|
|
@@ -22414,7 +22761,7 @@ async function backlogSyncCommand(args, deps = realSyncDeps()) {
|
|
|
22414
22761
|
const backlog = flagValue(args, "--backlog") ?? ".roll/backlog.md";
|
|
22415
22762
|
const featuresDir = flagValue(args, "--features") ?? ".roll/features";
|
|
22416
22763
|
const localYaml = flagValue(args, "--local-yaml") ?? ".roll/local.yaml";
|
|
22417
|
-
const cfg = existsSync39(localYaml) ? readSyncConfig(
|
|
22764
|
+
const cfg = existsSync39(localYaml) ? readSyncConfig(readFileSync37(localYaml, "utf8")) : {};
|
|
22418
22765
|
const repoArg = flagValue(args, "--repo") ?? cfg.repo ?? "";
|
|
22419
22766
|
if (!repoArg) {
|
|
22420
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");
|
|
@@ -22457,7 +22804,7 @@ async function backlogSyncCommand(args, deps = realSyncDeps()) {
|
|
|
22457
22804
|
`);
|
|
22458
22805
|
return 1;
|
|
22459
22806
|
}
|
|
22460
|
-
const content =
|
|
22807
|
+
const content = readFileSync37(backlog, "utf8");
|
|
22461
22808
|
if (dryRun) {
|
|
22462
22809
|
const preview = dryRunPreview(issues, content);
|
|
22463
22810
|
for (const line of preview.lines)
|
|
@@ -22483,7 +22830,7 @@ async function backlogSyncCommand(args, deps = realSyncDeps()) {
|
|
|
22483
22830
|
process.stdout.write(`added: ${result.added}, skipped: ${result.skipped}, total issues: ${result.total}
|
|
22484
22831
|
`);
|
|
22485
22832
|
const block = renderSyncBlock(repoArg, wanted, deps.nowIso());
|
|
22486
|
-
const original = existsSync39(localYaml) ?
|
|
22833
|
+
const original = existsSync39(localYaml) ? readFileSync37(localYaml, "utf8") : "";
|
|
22487
22834
|
mkdirSync19(dirname15(localYaml) || ".", { recursive: true });
|
|
22488
22835
|
writeFileSync18(localYaml, original === "" ? block + "\n" : writeSyncBlock(original, block));
|
|
22489
22836
|
return 0;
|
|
@@ -22494,7 +22841,7 @@ function writeFeatureStub(issue, featuresDir, epic = "backlog-lifecycle") {
|
|
|
22494
22841
|
const path = join35(epicDir, `${ghId(issue)}.md`);
|
|
22495
22842
|
const ac = renderAcSection(issue);
|
|
22496
22843
|
if (existsSync39(path)) {
|
|
22497
|
-
const existing =
|
|
22844
|
+
const existing = readFileSync37(path, "utf8");
|
|
22498
22845
|
const block = ac ? ac + "\n" : "";
|
|
22499
22846
|
const sep3 = existing.endsWith("\n") || existing === "" ? "" : "\n";
|
|
22500
22847
|
if (block)
|
|
@@ -22510,7 +22857,7 @@ init_dist2();
|
|
|
22510
22857
|
init_dist3();
|
|
22511
22858
|
init_dist();
|
|
22512
22859
|
import { execFileSync as execFileSync7, spawnSync as spawnSync2 } from "node:child_process";
|
|
22513
|
-
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";
|
|
22514
22861
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
22515
22862
|
import { dirname as dirname16, join as join36 } from "node:path";
|
|
22516
22863
|
function lang2() {
|
|
@@ -22610,7 +22957,7 @@ function loopEnforceTcrCommand(args, deps = realEnforceTcrDeps()) {
|
|
|
22610
22957
|
return 0;
|
|
22611
22958
|
const backlog = join36(".roll", "backlog.md");
|
|
22612
22959
|
if (existsSync40(backlog)) {
|
|
22613
|
-
writeFileSync19(backlog, revertStoryDone(
|
|
22960
|
+
writeFileSync19(backlog, revertStoryDone(readFileSync38(backlog, "utf8"), storyId));
|
|
22614
22961
|
}
|
|
22615
22962
|
const alert = alertFile();
|
|
22616
22963
|
mkdirSync20(dirname16(alert), { recursive: true });
|
|
@@ -22668,7 +23015,7 @@ function loopPrecheckCiCommand(args, deps = realPrecheckDeps()) {
|
|
|
22668
23015
|
const sha8 = commit2.slice(0, 8);
|
|
22669
23016
|
const healKey = `heal_count_head_${sha8}`;
|
|
22670
23017
|
const state = stateFilePath();
|
|
22671
|
-
const body = existsSync40(state) ?
|
|
23018
|
+
const body = existsSync40(state) ? readFileSync38(state, "utf8") : "";
|
|
22672
23019
|
const headHealCount = parseInt(stateGet(body, healKey) || "0", 10) || 0;
|
|
22673
23020
|
const verdict = precheckCiVerdict({ ghAndCommitOk: true, runs, healMax, headHealCount });
|
|
22674
23021
|
if (verdict.exit === 2) {
|
|
@@ -22780,7 +23127,7 @@ function loopUnknownSubcommand(sub) {
|
|
|
22780
23127
|
// packages/cli/dist/commands/brief.js
|
|
22781
23128
|
init_dist2();
|
|
22782
23129
|
init_dist();
|
|
22783
|
-
import { existsSync as existsSync41, readFileSync as
|
|
23130
|
+
import { existsSync as existsSync41, readFileSync as readFileSync39 } from "node:fs";
|
|
22784
23131
|
import { homedir as homedir9 } from "node:os";
|
|
22785
23132
|
import { join as join37 } from "node:path";
|
|
22786
23133
|
var BACKLOG_PATH2 = ".roll/backlog.md";
|
|
@@ -22872,7 +23219,7 @@ function briefCommand(args) {
|
|
|
22872
23219
|
`);
|
|
22873
23220
|
return 1;
|
|
22874
23221
|
}
|
|
22875
|
-
const items = parseBacklog(
|
|
23222
|
+
const items = parseBacklog(readFileSync39(BACKLOG_PATH2, "utf8"));
|
|
22876
23223
|
const model = composeBrief(items, activeAlerts());
|
|
22877
23224
|
const dateStr = formatNow(/* @__PURE__ */ new Date());
|
|
22878
23225
|
process.stdout.write(renderBrief(model, lang9, { full }, dateStr).join("\n") + "\n");
|
|
@@ -22945,7 +23292,7 @@ init_dist();
|
|
|
22945
23292
|
// packages/cli/dist/commands/lang.js
|
|
22946
23293
|
init_dist();
|
|
22947
23294
|
import { execFileSync as execFileSync8 } from "node:child_process";
|
|
22948
|
-
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";
|
|
22949
23296
|
import { homedir as homedir10, tmpdir as tmpdir3 } from "node:os";
|
|
22950
23297
|
import { dirname as dirname17, join as join38 } from "node:path";
|
|
22951
23298
|
function rollConfigPath2() {
|
|
@@ -22956,7 +23303,7 @@ function configLang2() {
|
|
|
22956
23303
|
const cfg = rollConfigPath2();
|
|
22957
23304
|
if (!existsSync42(cfg))
|
|
22958
23305
|
return void 0;
|
|
22959
|
-
for (const line of
|
|
23306
|
+
for (const line of readFileSync40(cfg, "utf8").split("\n")) {
|
|
22960
23307
|
const m7 = /^lang:\s*(.*)$/.exec(line);
|
|
22961
23308
|
if (m7 !== null) {
|
|
22962
23309
|
const v = (m7[1] ?? "").replace(/\s*#.*$/, "").trim();
|
|
@@ -22970,7 +23317,7 @@ function configHasLangLine() {
|
|
|
22970
23317
|
const cfg = rollConfigPath2();
|
|
22971
23318
|
if (!existsSync42(cfg))
|
|
22972
23319
|
return false;
|
|
22973
|
-
return
|
|
23320
|
+
return readFileSync40(cfg, "utf8").split("\n").some((l) => /^lang:/.test(l));
|
|
22974
23321
|
}
|
|
22975
23322
|
function appleLang2() {
|
|
22976
23323
|
if (process.platform !== "darwin")
|
|
@@ -23013,7 +23360,7 @@ function resolveSource() {
|
|
|
23013
23360
|
function writeLang(value) {
|
|
23014
23361
|
const cfg = rollConfigPath2();
|
|
23015
23362
|
mkdirSync21(dirname17(cfg), { recursive: true });
|
|
23016
|
-
const existing = existsSync42(cfg) ?
|
|
23363
|
+
const existing = existsSync42(cfg) ? readFileSync40(cfg, "utf8") : "";
|
|
23017
23364
|
const kept = existing === "" ? [] : existing.split("\n").filter((l) => !/^lang:/.test(l));
|
|
23018
23365
|
if (kept.length > 0 && kept[kept.length - 1] === "")
|
|
23019
23366
|
kept.pop();
|
|
@@ -23027,7 +23374,7 @@ function clearLang() {
|
|
|
23027
23374
|
const cfg = rollConfigPath2();
|
|
23028
23375
|
if (!existsSync42(cfg))
|
|
23029
23376
|
return;
|
|
23030
|
-
const existing =
|
|
23377
|
+
const existing = readFileSync40(cfg, "utf8");
|
|
23031
23378
|
const kept = existing.split("\n").filter((l) => !/^lang:/.test(l));
|
|
23032
23379
|
if (kept.length > 0 && kept[kept.length - 1] === "")
|
|
23033
23380
|
kept.pop();
|
|
@@ -23934,7 +24281,7 @@ ${CYCLE_USAGE}
|
|
|
23934
24281
|
|
|
23935
24282
|
// packages/cli/dist/commands/ls.js
|
|
23936
24283
|
init_dist();
|
|
23937
|
-
import { existsSync as existsSync43, readFileSync as
|
|
24284
|
+
import { existsSync as existsSync43, readFileSync as readFileSync41 } from "node:fs";
|
|
23938
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";
|
|
23939
24286
|
var DEFAULT_STALE_DAYS = 14;
|
|
23940
24287
|
function projectStatus(entry, nowMs, staleMs, pathExists) {
|
|
@@ -24028,7 +24375,7 @@ ${LS_USAGE}
|
|
|
24028
24375
|
if (args.includes("--json")) {
|
|
24029
24376
|
let text;
|
|
24030
24377
|
try {
|
|
24031
|
-
text =
|
|
24378
|
+
text = readFileSync41(projectsRegistryPath(), "utf8");
|
|
24032
24379
|
} catch {
|
|
24033
24380
|
text = "[]\n";
|
|
24034
24381
|
}
|
|
@@ -24043,7 +24390,7 @@ ${LS_USAGE}
|
|
|
24043
24390
|
|
|
24044
24391
|
// packages/cli/dist/commands/loop-runs.js
|
|
24045
24392
|
init_dist();
|
|
24046
|
-
import { existsSync as existsSync44, readFileSync as
|
|
24393
|
+
import { existsSync as existsSync44, readFileSync as readFileSync42, readdirSync as readdirSync17 } from "node:fs";
|
|
24047
24394
|
import { homedir as homedir12, platform as platform2 } from "node:os";
|
|
24048
24395
|
import { basename as basename9, join as join40 } from "node:path";
|
|
24049
24396
|
function lang3() {
|
|
@@ -24151,7 +24498,7 @@ function backlogDesc(backlogText, id) {
|
|
|
24151
24498
|
}
|
|
24152
24499
|
return "";
|
|
24153
24500
|
}
|
|
24154
|
-
function
|
|
24501
|
+
function formatLine(row2, showProject, backlogText) {
|
|
24155
24502
|
const ts = str3(row2["ts"]);
|
|
24156
24503
|
const status2 = str3(row2["status"]);
|
|
24157
24504
|
const project = str3(row2["project"]);
|
|
@@ -24211,7 +24558,7 @@ function aggregateAllFiles() {
|
|
|
24211
24558
|
for (const pl of plists) {
|
|
24212
24559
|
let content;
|
|
24213
24560
|
try {
|
|
24214
|
-
content =
|
|
24561
|
+
content = readFileSync42(join40(laDir, pl), "utf8");
|
|
24215
24562
|
} catch {
|
|
24216
24563
|
continue;
|
|
24217
24564
|
}
|
|
@@ -24227,7 +24574,7 @@ function aggregateAllFiles() {
|
|
|
24227
24574
|
if (!f || seen.has(f))
|
|
24228
24575
|
continue;
|
|
24229
24576
|
try {
|
|
24230
|
-
if (!existsSync44(f) ||
|
|
24577
|
+
if (!existsSync44(f) || readFileSync42(f, "utf8").trim() === "")
|
|
24231
24578
|
continue;
|
|
24232
24579
|
} catch {
|
|
24233
24580
|
continue;
|
|
@@ -24241,7 +24588,7 @@ function aggregateAllRows() {
|
|
|
24241
24588
|
const rows = [];
|
|
24242
24589
|
for (const f of aggregateAllFiles()) {
|
|
24243
24590
|
try {
|
|
24244
|
-
rows.push(...parseRows(
|
|
24591
|
+
rows.push(...parseRows(readFileSync42(f, "utf8")));
|
|
24245
24592
|
} catch {
|
|
24246
24593
|
}
|
|
24247
24594
|
}
|
|
@@ -24263,7 +24610,7 @@ function runsDetail(cycleId) {
|
|
|
24263
24610
|
}
|
|
24264
24611
|
let rows;
|
|
24265
24612
|
try {
|
|
24266
|
-
rows = parseRows(
|
|
24613
|
+
rows = parseRows(readFileSync42(src, "utf8"));
|
|
24267
24614
|
} catch {
|
|
24268
24615
|
rows = [];
|
|
24269
24616
|
}
|
|
@@ -24320,12 +24667,12 @@ function loopRunsCommand(argv) {
|
|
|
24320
24667
|
rows = aggregateAllRows();
|
|
24321
24668
|
} else {
|
|
24322
24669
|
const src = runsFile();
|
|
24323
|
-
if (!existsSync44(src) ||
|
|
24670
|
+
if (!existsSync44(src) || readFileSync42(src, "utf8").trim() === "") {
|
|
24324
24671
|
process.stdout.write(msg3("loop.no_loop_runs_yet") + "\n");
|
|
24325
24672
|
return 0;
|
|
24326
24673
|
}
|
|
24327
24674
|
const slug = projectSlug2();
|
|
24328
|
-
rows = parseRows(
|
|
24675
|
+
rows = parseRows(readFileSync42(src, "utf8")).filter((r) => str3(r["project"]) === slug);
|
|
24329
24676
|
}
|
|
24330
24677
|
if (rows.length === 0) {
|
|
24331
24678
|
process.stdout.write(msg3("loop.no_loop_runs_for_current_project") + "\n");
|
|
@@ -24337,12 +24684,12 @@ function loopRunsCommand(argv) {
|
|
|
24337
24684
|
const blPath = join40(proj, ".roll", "backlog.md");
|
|
24338
24685
|
if (existsSync44(blPath)) {
|
|
24339
24686
|
try {
|
|
24340
|
-
backlogText =
|
|
24687
|
+
backlogText = readFileSync42(blPath, "utf8");
|
|
24341
24688
|
} catch {
|
|
24342
24689
|
backlogText = "";
|
|
24343
24690
|
}
|
|
24344
24691
|
}
|
|
24345
|
-
const out3 = recent.map((r) =>
|
|
24692
|
+
const out3 = recent.map((r) => formatLine(r, allFlag, backlogText));
|
|
24346
24693
|
process.stdout.write(out3.join("\n") + "\n");
|
|
24347
24694
|
return 0;
|
|
24348
24695
|
}
|
|
@@ -24350,7 +24697,7 @@ function loopRunsCommand(argv) {
|
|
|
24350
24697
|
// packages/cli/dist/commands/loop-signals.js
|
|
24351
24698
|
init_dist2();
|
|
24352
24699
|
init_dist();
|
|
24353
|
-
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";
|
|
24354
24701
|
import { dirname as dirname18, join as join41 } from "node:path";
|
|
24355
24702
|
function lang4() {
|
|
24356
24703
|
return resolveLang({ rollLang: process.env["ROLL_LANG"], lcAll: process.env["LC_ALL"], lang: process.env["LANG"] });
|
|
@@ -24383,14 +24730,14 @@ function loopSignalsCommand(argv) {
|
|
|
24383
24730
|
process.stdout.write(s + "\n");
|
|
24384
24731
|
};
|
|
24385
24732
|
const runsSrc = runsFile();
|
|
24386
|
-
if (!existsSync45(runsSrc) ||
|
|
24733
|
+
if (!existsSync45(runsSrc) || readFileSync43(runsSrc, "utf8").trim() === "") {
|
|
24387
24734
|
say(t(v2Catalog, lang4(), "loop.no_loop_runs_yet"));
|
|
24388
24735
|
return 0;
|
|
24389
24736
|
}
|
|
24390
24737
|
const projectPath3 = (process.env["ROLL_MAIN_PROJECT"] ?? "").trim() || process.cwd();
|
|
24391
24738
|
const slug = projectSlug2();
|
|
24392
24739
|
const records = [];
|
|
24393
|
-
for (const line of
|
|
24740
|
+
for (const line of readFileSync43(runsSrc, "utf8").split("\n")) {
|
|
24394
24741
|
if (line.trim() === "")
|
|
24395
24742
|
continue;
|
|
24396
24743
|
try {
|
|
@@ -24411,13 +24758,13 @@ function loopSignalsCommand(argv) {
|
|
|
24411
24758
|
writeFileSync21(seenFile, "");
|
|
24412
24759
|
let lastId = 0;
|
|
24413
24760
|
if (existsSync45(candFile)) {
|
|
24414
|
-
for (const m7 of
|
|
24761
|
+
for (const m7 of readFileSync43(candFile, "utf8").matchAll(/CAND-(\d+)/g)) {
|
|
24415
24762
|
const n = parseInt(m7[1] ?? "0", 10);
|
|
24416
24763
|
if (n > lastId)
|
|
24417
24764
|
lastId = n;
|
|
24418
24765
|
}
|
|
24419
24766
|
}
|
|
24420
|
-
const seen = new Set(existsSync45(seenFile) ?
|
|
24767
|
+
const seen = new Set(existsSync45(seenFile) ? readFileSync43(seenFile, "utf8").split("\n").filter((l) => l !== "") : []);
|
|
24421
24768
|
let newCount = 0;
|
|
24422
24769
|
for (const sig of signals) {
|
|
24423
24770
|
if (seen.has(sig.key))
|
|
@@ -24464,7 +24811,7 @@ Options:
|
|
|
24464
24811
|
|
|
24465
24812
|
// packages/cli/dist/commands/loop-log.js
|
|
24466
24813
|
init_dist();
|
|
24467
|
-
import { existsSync as existsSync46, readFileSync as
|
|
24814
|
+
import { existsSync as existsSync46, readFileSync as readFileSync44, readdirSync as readdirSync18 } from "node:fs";
|
|
24468
24815
|
import { basename as basename10, join as join42 } from "node:path";
|
|
24469
24816
|
function lang5() {
|
|
24470
24817
|
return resolveLang({ rollLang: process.env["ROLL_LANG"], lcAll: process.env["LC_ALL"], lang: process.env["LANG"] });
|
|
@@ -24481,7 +24828,7 @@ function showLog(file) {
|
|
|
24481
24828
|
const ts = m7 ? `${m7[1]}-${m7[2]}-${m7[3]} ${m7[4]}:${m7[5]}` : id;
|
|
24482
24829
|
let body = "";
|
|
24483
24830
|
try {
|
|
24484
|
-
body =
|
|
24831
|
+
body = readFileSync44(file, "utf8");
|
|
24485
24832
|
} catch {
|
|
24486
24833
|
body = "";
|
|
24487
24834
|
}
|
|
@@ -24537,7 +24884,7 @@ function loopLogCommand(argv) {
|
|
|
24537
24884
|
|
|
24538
24885
|
// packages/cli/dist/commands/loop-goal.js
|
|
24539
24886
|
init_dist();
|
|
24540
|
-
import { existsSync as existsSync47, readFileSync as
|
|
24887
|
+
import { existsSync as existsSync47, readFileSync as readFileSync45 } from "node:fs";
|
|
24541
24888
|
import { join as join43 } from "node:path";
|
|
24542
24889
|
function realDeps3() {
|
|
24543
24890
|
return { projectPath: () => process.cwd() };
|
|
@@ -24611,7 +24958,7 @@ async function loopGoalCommand(args, deps = realDeps3()) {
|
|
|
24611
24958
|
return 0;
|
|
24612
24959
|
}
|
|
24613
24960
|
try {
|
|
24614
|
-
process.stdout.write(renderGoal(parseGoalYaml(
|
|
24961
|
+
process.stdout.write(renderGoal(parseGoalYaml(readFileSync45(path, "utf8"))));
|
|
24615
24962
|
return 0;
|
|
24616
24963
|
} catch (e) {
|
|
24617
24964
|
process.stderr.write(`[roll] goal.yaml invalid: ${e.message}
|
|
@@ -24625,7 +24972,7 @@ init_dist2();
|
|
|
24625
24972
|
init_dist();
|
|
24626
24973
|
init_dist3();
|
|
24627
24974
|
import { spawn as spawn3, spawnSync as spawnSync4 } from "node:child_process";
|
|
24628
|
-
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";
|
|
24629
24976
|
import { dirname as dirname19, join as join44 } from "node:path";
|
|
24630
24977
|
import { createInterface } from "node:readline";
|
|
24631
24978
|
|
|
@@ -25210,7 +25557,7 @@ function writeGoal(path, goal) {
|
|
|
25210
25557
|
function readGoal(path) {
|
|
25211
25558
|
if (!existsSync48(path))
|
|
25212
25559
|
return void 0;
|
|
25213
|
-
return parseGoalYaml(
|
|
25560
|
+
return parseGoalYaml(readFileSync46(path, "utf8"));
|
|
25214
25561
|
}
|
|
25215
25562
|
function createGoal(opts, at) {
|
|
25216
25563
|
return {
|
|
@@ -25244,7 +25591,7 @@ function rowSpentZeroNoExecution(row2) {
|
|
|
25244
25591
|
function readRunSnapshot(path) {
|
|
25245
25592
|
let text = "";
|
|
25246
25593
|
try {
|
|
25247
|
-
text =
|
|
25594
|
+
text = readFileSync46(path, "utf8");
|
|
25248
25595
|
} catch {
|
|
25249
25596
|
return { rows: [], summary: { cycles: 0, costUsd: 0, costUnknownRows: 0 } };
|
|
25250
25597
|
}
|
|
@@ -25277,7 +25624,7 @@ function readRunSnapshot(path) {
|
|
|
25277
25624
|
}
|
|
25278
25625
|
function readBacklogRows(projectPath3) {
|
|
25279
25626
|
try {
|
|
25280
|
-
return parseBacklog(
|
|
25627
|
+
return parseBacklog(readFileSync46(join44(projectPath3, ".roll", "backlog.md"), "utf8")).map((row2) => ({
|
|
25281
25628
|
id: row2.id,
|
|
25282
25629
|
status: row2.status
|
|
25283
25630
|
}));
|
|
@@ -25287,7 +25634,7 @@ function readBacklogRows(projectPath3) {
|
|
|
25287
25634
|
}
|
|
25288
25635
|
function readStoryIndex(projectPath3) {
|
|
25289
25636
|
try {
|
|
25290
|
-
const obj = JSON.parse(
|
|
25637
|
+
const obj = JSON.parse(readFileSync46(join44(projectPath3, ".roll", "index.json"), "utf8"));
|
|
25291
25638
|
if (typeof obj.stories !== "object" || obj.stories === null || Array.isArray(obj.stories))
|
|
25292
25639
|
return {};
|
|
25293
25640
|
const out3 = {};
|
|
@@ -25624,7 +25971,7 @@ async function evaluateGoal(projectPath3, slug, goal, deps, session, workerAgent
|
|
|
25624
25971
|
function hasSafetyPauseSince(path, since) {
|
|
25625
25972
|
let text = "";
|
|
25626
25973
|
try {
|
|
25627
|
-
text =
|
|
25974
|
+
text = readFileSync46(path, "utf8");
|
|
25628
25975
|
} catch {
|
|
25629
25976
|
return false;
|
|
25630
25977
|
}
|
|
@@ -25754,7 +26101,7 @@ function latestAlertSummary(projectPath3, slug, sinceSec) {
|
|
|
25754
26101
|
try {
|
|
25755
26102
|
if (!existsSync48(path) || statSync15(path).mtimeMs / 1e3 < sinceSec)
|
|
25756
26103
|
return void 0;
|
|
25757
|
-
const lines2 =
|
|
26104
|
+
const lines2 = readFileSync46(path, "utf8").split("\n").map((line2) => line2.trim()).filter((line2) => line2 !== "");
|
|
25758
26105
|
const line = [...lines2].reverse().find((candidate) => /\b(ALERT|WARN|BLOCKED|refused|failed)\b/i.test(candidate));
|
|
25759
26106
|
if (line === void 0)
|
|
25760
26107
|
return void 0;
|
|
@@ -25772,7 +26119,7 @@ function innerLockHolder(projectPath3, nowSec2) {
|
|
|
25772
26119
|
try {
|
|
25773
26120
|
if (!existsSync48(path))
|
|
25774
26121
|
return void 0;
|
|
25775
|
-
const contents = parseLock(
|
|
26122
|
+
const contents = parseLock(readFileSync46(path, "utf8"));
|
|
25776
26123
|
return isLockHeld(contents, nowSec2, INNER_LOCK_STALE_SEC) ? contents.pid : void 0;
|
|
25777
26124
|
} catch {
|
|
25778
26125
|
return void 0;
|
|
@@ -25913,14 +26260,14 @@ function applyTimeboxGate(projectPath3, bus, session, goal, deps, deadlineSec) {
|
|
|
25913
26260
|
}
|
|
25914
26261
|
function installStopHandlers(onStop) {
|
|
25915
26262
|
const signals = ["SIGINT", "SIGTERM", "SIGHUP"];
|
|
25916
|
-
const handlers = signals.map((
|
|
25917
|
-
const handler = () => onStop(
|
|
25918
|
-
process.on(
|
|
25919
|
-
return { signal
|
|
26263
|
+
const handlers = signals.map((signal) => {
|
|
26264
|
+
const handler = () => onStop(signal);
|
|
26265
|
+
process.on(signal, handler);
|
|
26266
|
+
return { signal, handler };
|
|
25920
26267
|
});
|
|
25921
26268
|
return () => {
|
|
25922
|
-
for (const { signal
|
|
25923
|
-
process.off(
|
|
26269
|
+
for (const { signal, handler } of handlers)
|
|
26270
|
+
process.off(signal, handler);
|
|
25924
26271
|
};
|
|
25925
26272
|
}
|
|
25926
26273
|
function describeScope(scope) {
|
|
@@ -25993,9 +26340,9 @@ async function runGoWorker(id, opts, deps) {
|
|
|
25993
26340
|
let stopReason;
|
|
25994
26341
|
let stopRequested = false;
|
|
25995
26342
|
let workerAgents = [];
|
|
25996
|
-
const disposeSignals = installStopHandlers((
|
|
26343
|
+
const disposeSignals = installStopHandlers((signal) => {
|
|
25997
26344
|
stopRequested = true;
|
|
25998
|
-
stopReason = `signal_${
|
|
26345
|
+
stopReason = `signal_${signal}`;
|
|
25999
26346
|
});
|
|
26000
26347
|
try {
|
|
26001
26348
|
const gPath = goalPath2(id.path);
|
|
@@ -26135,7 +26482,7 @@ async function runGoWorker(id, opts, deps) {
|
|
|
26135
26482
|
}
|
|
26136
26483
|
|
|
26137
26484
|
// packages/cli/dist/commands/loop-events.js
|
|
26138
|
-
import { existsSync as existsSync49, readFileSync as
|
|
26485
|
+
import { existsSync as existsSync49, readFileSync as readFileSync47 } from "node:fs";
|
|
26139
26486
|
import { join as join45 } from "node:path";
|
|
26140
26487
|
function str4(v) {
|
|
26141
26488
|
return typeof v === "string" ? v : v === void 0 || v === null ? "" : String(v);
|
|
@@ -26151,7 +26498,7 @@ function loopEventsCommand(argv) {
|
|
|
26151
26498
|
}
|
|
26152
26499
|
let lines2;
|
|
26153
26500
|
try {
|
|
26154
|
-
lines2 =
|
|
26501
|
+
lines2 = readFileSync47(evfile, "utf8").split("\n").filter((l) => l !== "");
|
|
26155
26502
|
} catch {
|
|
26156
26503
|
lines2 = [];
|
|
26157
26504
|
}
|
|
@@ -26189,14 +26536,14 @@ function loopBranchesRetired() {
|
|
|
26189
26536
|
// packages/cli/dist/commands/doctor.js
|
|
26190
26537
|
init_dist();
|
|
26191
26538
|
import { execFileSync as execFileSync11 } from "node:child_process";
|
|
26192
|
-
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";
|
|
26193
26540
|
import { homedir as homedir13, tmpdir as tmpdir5 } from "node:os";
|
|
26194
26541
|
import { delimiter as delimiter2, join as join47 } from "node:path";
|
|
26195
26542
|
|
|
26196
26543
|
// packages/cli/dist/commands/skills.js
|
|
26197
26544
|
init_dist();
|
|
26198
26545
|
import { execFileSync as execFileSync10 } from "node:child_process";
|
|
26199
|
-
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";
|
|
26200
26547
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
26201
26548
|
import { join as join46 } from "node:path";
|
|
26202
26549
|
function pkgDir() {
|
|
@@ -26216,7 +26563,7 @@ function skillsDir() {
|
|
|
26216
26563
|
return join46(pkgDir(), "skills");
|
|
26217
26564
|
}
|
|
26218
26565
|
function frontmatterField(file, field2) {
|
|
26219
|
-
const lines2 =
|
|
26566
|
+
const lines2 = readFileSync48(file, "utf8").split("\n");
|
|
26220
26567
|
if (lines2.length === 0 || lines2[0] !== "---")
|
|
26221
26568
|
return "";
|
|
26222
26569
|
let collecting = false;
|
|
@@ -26461,7 +26808,7 @@ function bilingual(key) {
|
|
|
26461
26808
|
return [t(v2Catalog, "en", key), t(v2Catalog, "zh", key)];
|
|
26462
26809
|
}
|
|
26463
26810
|
var out2 = { lines: [] };
|
|
26464
|
-
function
|
|
26811
|
+
function emit2(line) {
|
|
26465
26812
|
out2.lines.push(line);
|
|
26466
26813
|
}
|
|
26467
26814
|
function agentBinNames4(agent) {
|
|
@@ -26542,11 +26889,11 @@ function agentSection(p) {
|
|
|
26542
26889
|
const cfg = rollConfigPath4();
|
|
26543
26890
|
if (!existsSync51(cfg))
|
|
26544
26891
|
return;
|
|
26545
|
-
|
|
26892
|
+
emit2("");
|
|
26546
26893
|
for (const l of bilingual("doctor.agent_detection"))
|
|
26547
|
-
|
|
26548
|
-
|
|
26549
|
-
const text =
|
|
26894
|
+
emit2(l);
|
|
26895
|
+
emit2("");
|
|
26896
|
+
const text = readFileSync49(cfg, "utf8");
|
|
26550
26897
|
let primary = "";
|
|
26551
26898
|
for (const line of text.split("\n")) {
|
|
26552
26899
|
const m7 = /^primary_agent:\s*(.*)$/.exec(line);
|
|
@@ -26572,7 +26919,7 @@ function agentSection(p) {
|
|
|
26572
26919
|
const installed = agentInstalledByName4(name, dir) ? t(v2Catalog, msgLang5(), "doctor.agent_installed") : t(v2Catalog, msgLang5(), "doctor.agent_missing");
|
|
26573
26920
|
const dirExists = safeIsDir(dir) ? t(v2Catalog, msgLang5(), "doctor.agent_dir_exists") : t(v2Catalog, msgLang5(), "doctor.agent_dir_missing");
|
|
26574
26921
|
const tag = name === primary ? ` (${t(v2Catalog, msgLang5(), "doctor.agent_primary_label")})` : "";
|
|
26575
|
-
|
|
26922
|
+
emit2(` ${padEnd(name, 10)} ${padEnd(installed, 14)} ${dirExists}${tag}`);
|
|
26576
26923
|
}
|
|
26577
26924
|
}
|
|
26578
26925
|
function ghAvailable3() {
|
|
@@ -26652,28 +26999,28 @@ function prEventHint(lang9) {
|
|
|
26652
26999
|
function prSection(lang9) {
|
|
26653
27000
|
if (!insideGitWorkTree())
|
|
26654
27001
|
return;
|
|
26655
|
-
|
|
27002
|
+
emit2("");
|
|
26656
27003
|
for (const l of bilingual("doctor.pr_review_extras"))
|
|
26657
|
-
|
|
26658
|
-
|
|
27004
|
+
emit2(l);
|
|
27005
|
+
emit2("");
|
|
26659
27006
|
const protection = branchProtectionState();
|
|
26660
27007
|
if (protection === "enabled") {
|
|
26661
|
-
|
|
27008
|
+
emit2(` ${t(v2Catalog, lang9, "doctor.pr_double_gate_enabled")}`);
|
|
26662
27009
|
} else if (protection === "disabled") {
|
|
26663
|
-
|
|
27010
|
+
emit2(` ${t(v2Catalog, lang9, "doctor.pr_double_gate_disabled")}`);
|
|
26664
27011
|
for (const l of prPipelineHint())
|
|
26665
|
-
|
|
27012
|
+
emit2(l);
|
|
26666
27013
|
} else {
|
|
26667
|
-
|
|
27014
|
+
emit2(` ${t(v2Catalog, lang9, "doctor.pr_double_gate_unknown")}`);
|
|
26668
27015
|
for (const l of prPipelineHint())
|
|
26669
|
-
|
|
27016
|
+
emit2(l);
|
|
26670
27017
|
}
|
|
26671
27018
|
if (eventWorkflowState() === "present") {
|
|
26672
|
-
|
|
27019
|
+
emit2(` ${t(v2Catalog, lang9, "doctor.pr_event_enabled")}`);
|
|
26673
27020
|
} else {
|
|
26674
|
-
|
|
27021
|
+
emit2(` ${t(v2Catalog, lang9, "doctor.pr_event_disabled")}`);
|
|
26675
27022
|
for (const l of prEventHint(lang9))
|
|
26676
|
-
|
|
27023
|
+
emit2(l);
|
|
26677
27024
|
}
|
|
26678
27025
|
}
|
|
26679
27026
|
function skillsCatalogSection(lang9) {
|
|
@@ -26681,18 +27028,18 @@ function skillsCatalogSection(lang9) {
|
|
|
26681
27028
|
if (!safeIsDir(skillsDir2))
|
|
26682
27029
|
return;
|
|
26683
27030
|
const target = join47(pkgDir2(), "guide", "skills.md");
|
|
26684
|
-
|
|
27031
|
+
emit2("");
|
|
26685
27032
|
for (const l of bilingual("skills.doctor_heading"))
|
|
26686
|
-
|
|
27033
|
+
emit2(l);
|
|
26687
27034
|
let drift;
|
|
26688
27035
|
if (!existsSync51(target)) {
|
|
26689
27036
|
drift = true;
|
|
26690
27037
|
} else {
|
|
26691
27038
|
const fresh = join47(mkdtempSync3(join47(tmpdir5(), "roll-doctor-")), "skills.md");
|
|
26692
27039
|
writeFileSync24(fresh, generateCatalog());
|
|
26693
|
-
drift =
|
|
27040
|
+
drift = readFileSync49(target, "utf8") !== readFileSync49(fresh, "utf8");
|
|
26694
27041
|
}
|
|
26695
|
-
|
|
27042
|
+
emit2(` ${t(v2Catalog, lang9, drift ? "skills.doctor_drift" : "skills.doctor_ok")}`);
|
|
26696
27043
|
}
|
|
26697
27044
|
function lanesSection(lang9, probe) {
|
|
26698
27045
|
const lines2 = [];
|
|
@@ -26722,7 +27069,7 @@ function lanesSection(lang9, probe) {
|
|
|
26722
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]" : ""}`);
|
|
26723
27070
|
}
|
|
26724
27071
|
for (const l of lines2)
|
|
26725
|
-
|
|
27072
|
+
emit2(l);
|
|
26726
27073
|
return lines2;
|
|
26727
27074
|
}
|
|
26728
27075
|
function launchdStaleSection(lang9) {
|
|
@@ -26746,15 +27093,15 @@ function launchdStaleSection(lang9) {
|
|
|
26746
27093
|
if (safeIsDir(wd))
|
|
26747
27094
|
continue;
|
|
26748
27095
|
if (!found) {
|
|
26749
|
-
|
|
26750
|
-
|
|
26751
|
-
|
|
27096
|
+
emit2("");
|
|
27097
|
+
emit2(t(v2Catalog, lang9, "doctor.stale_plists"));
|
|
27098
|
+
emit2("");
|
|
26752
27099
|
found = true;
|
|
26753
27100
|
}
|
|
26754
27101
|
const label4 = name.replace(/\.plist$/, "");
|
|
26755
|
-
|
|
26756
|
-
|
|
26757
|
-
|
|
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}'`);
|
|
26758
27105
|
}
|
|
26759
27106
|
}
|
|
26760
27107
|
function realLaneProbe() {
|
|
@@ -26843,23 +27190,23 @@ function launchdProxySection(lang9) {
|
|
|
26843
27190
|
}
|
|
26844
27191
|
if (stale.length === 0)
|
|
26845
27192
|
return;
|
|
26846
|
-
|
|
26847
|
-
|
|
26848
|
-
|
|
26849
|
-
|
|
27193
|
+
emit2("");
|
|
27194
|
+
emit2(t(v3Catalog, "en", "doctor.proxy_env_warning"));
|
|
27195
|
+
emit2(t(v3Catalog, "zh", "doctor.proxy_env_warning"));
|
|
27196
|
+
emit2("");
|
|
26850
27197
|
for (const { name, target } of stale) {
|
|
26851
|
-
|
|
27198
|
+
emit2(` \u26A0 ${name}=${target}`);
|
|
26852
27199
|
}
|
|
26853
|
-
|
|
26854
|
-
|
|
27200
|
+
emit2("");
|
|
27201
|
+
emit2(` ${t(v3Catalog, lang9, "doctor.proxy_env_hint")}`);
|
|
26855
27202
|
for (const { name } of stale) {
|
|
26856
|
-
|
|
27203
|
+
emit2(` launchctl unsetenv ${name}`);
|
|
26857
27204
|
}
|
|
26858
27205
|
}
|
|
26859
27206
|
function readWorkingDirectory(plist) {
|
|
26860
27207
|
let body;
|
|
26861
27208
|
try {
|
|
26862
|
-
body =
|
|
27209
|
+
body = readFileSync49(plist, "utf8");
|
|
26863
27210
|
} catch {
|
|
26864
27211
|
return "";
|
|
26865
27212
|
}
|
|
@@ -26895,11 +27242,11 @@ import { join as join51 } from "node:path";
|
|
|
26895
27242
|
import { spawn as spawn4 } from "node:child_process";
|
|
26896
27243
|
import { join as join48 } from "node:path";
|
|
26897
27244
|
var liveAgents = /* @__PURE__ */ new Set();
|
|
26898
|
-
function killLiveAgents(
|
|
27245
|
+
function killLiveAgents(signal = "SIGKILL") {
|
|
26899
27246
|
let n = 0;
|
|
26900
27247
|
for (const c2 of liveAgents) {
|
|
26901
27248
|
try {
|
|
26902
|
-
if (killHard(c2,
|
|
27249
|
+
if (killHard(c2, signal))
|
|
26903
27250
|
n += 1;
|
|
26904
27251
|
} catch {
|
|
26905
27252
|
}
|
|
@@ -26907,15 +27254,15 @@ function killLiveAgents(signal2 = "SIGKILL") {
|
|
|
26907
27254
|
liveAgents.clear();
|
|
26908
27255
|
return n;
|
|
26909
27256
|
}
|
|
26910
|
-
function killHard(c2,
|
|
27257
|
+
function killHard(c2, signal) {
|
|
26911
27258
|
if (c2.pid !== void 0) {
|
|
26912
27259
|
try {
|
|
26913
|
-
process.kill(-c2.pid,
|
|
27260
|
+
process.kill(-c2.pid, signal);
|
|
26914
27261
|
return true;
|
|
26915
27262
|
} catch {
|
|
26916
27263
|
}
|
|
26917
27264
|
}
|
|
26918
|
-
return c2.kill(
|
|
27265
|
+
return c2.kill(signal);
|
|
26919
27266
|
}
|
|
26920
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: ";
|
|
26921
27268
|
var AGENT_ARGV_TODO = {
|
|
@@ -26972,7 +27319,7 @@ function buildSpawnCommand(agent, opts) {
|
|
|
26972
27319
|
return { bin: opts.bin ?? "qwen", args: [prompt] };
|
|
26973
27320
|
}
|
|
26974
27321
|
if (agent === "agy" || agent === "gemini" || agent === "antigravity") {
|
|
26975
|
-
return { bin: opts.bin ?? "agy", args: ["
|
|
27322
|
+
return { bin: opts.bin ?? "agy", args: ["--dangerously-skip-permissions", "-p", prompt] };
|
|
26976
27323
|
}
|
|
26977
27324
|
const hint = AGENT_ARGV_TODO[agent] ?? "unknown agent";
|
|
26978
27325
|
throw new Error(`runner: agent '${agent}' argv not yet ported. v2 shape: ${hint}`);
|
|
@@ -27038,8 +27385,8 @@ function spawnAndWait(bin, args, opts, pty = false) {
|
|
|
27038
27385
|
settle({ stdout, stderr: `${stderr}${String(e)}
|
|
27039
27386
|
`, exitCode: 127, timedOut });
|
|
27040
27387
|
});
|
|
27041
|
-
child.on("exit", (code,
|
|
27042
|
-
setImmediate(() => settle({ stdout, stderr, exitCode: code ?? (
|
|
27388
|
+
child.on("exit", (code, signal) => {
|
|
27389
|
+
setImmediate(() => settle({ stdout, stderr, exitCode: code ?? (signal !== null ? 137 : 1), timedOut }));
|
|
27043
27390
|
});
|
|
27044
27391
|
child.on("close", (code) => {
|
|
27045
27392
|
settle({ stdout, stderr, exitCode: code ?? 1, timedOut });
|
|
@@ -27052,7 +27399,7 @@ var realAgentSpawn = (agent, opts) => {
|
|
|
27052
27399
|
};
|
|
27053
27400
|
|
|
27054
27401
|
// packages/cli/dist/runner/skill-body.js
|
|
27055
|
-
import { existsSync as existsSync52, readFileSync as
|
|
27402
|
+
import { existsSync as existsSync52, readFileSync as readFileSync50 } from "node:fs";
|
|
27056
27403
|
import { homedir as homedir14 } from "node:os";
|
|
27057
27404
|
import { join as join49 } from "node:path";
|
|
27058
27405
|
function readSkillBody(projectPath3, opts) {
|
|
@@ -27067,7 +27414,7 @@ function readSkillBody(projectPath3, opts) {
|
|
|
27067
27414
|
continue;
|
|
27068
27415
|
let raw = "";
|
|
27069
27416
|
try {
|
|
27070
|
-
raw =
|
|
27417
|
+
raw = readFileSync50(p, "utf8");
|
|
27071
27418
|
} catch {
|
|
27072
27419
|
continue;
|
|
27073
27420
|
}
|
|
@@ -27469,7 +27816,7 @@ ${rowNote}`);
|
|
|
27469
27816
|
init_dist2();
|
|
27470
27817
|
init_dist();
|
|
27471
27818
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
27472
|
-
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";
|
|
27473
27820
|
import { homedir as homedir15 } from "node:os";
|
|
27474
27821
|
import { dirname as dirname20, join as join54 } from "node:path";
|
|
27475
27822
|
function registerProject(projectDir) {
|
|
@@ -27545,7 +27892,7 @@ function scanProjectType(dir) {
|
|
|
27545
27892
|
const pkg = join54(dir, "package.json");
|
|
27546
27893
|
const readPkg = () => {
|
|
27547
27894
|
try {
|
|
27548
|
-
return
|
|
27895
|
+
return readFileSync51(pkg, "utf8");
|
|
27549
27896
|
} catch {
|
|
27550
27897
|
return "";
|
|
27551
27898
|
}
|
|
@@ -27690,7 +28037,7 @@ function discoverOnboardAgents() {
|
|
|
27690
28037
|
if (!existsSync56(cfg))
|
|
27691
28038
|
return { installed, missing };
|
|
27692
28039
|
const env = realAgentEnv();
|
|
27693
|
-
for (const line of
|
|
28040
|
+
for (const line of readFileSync51(cfg, "utf8").split("\n")) {
|
|
27694
28041
|
const match = /^(ai_[^:]+):\s*(.*)$/.exec(line);
|
|
27695
28042
|
if (match === null)
|
|
27696
28043
|
continue;
|
|
@@ -27761,7 +28108,7 @@ function readOnboardPrompt() {
|
|
|
27761
28108
|
err8(`Skill file missing: ${skillFile}`);
|
|
27762
28109
|
return null;
|
|
27763
28110
|
}
|
|
27764
|
-
const body =
|
|
28111
|
+
const body = readFileSync51(skillFile, "utf8").replace(/^---\n[\s\S]*?\n---\n?/, "").trim();
|
|
27765
28112
|
return `Run the $roll-onboard skill below for this project. Follow it end-to-end and write .roll/onboard-plan.yaml when done.
|
|
27766
28113
|
|
|
27767
28114
|
${body}`;
|
|
@@ -27896,7 +28243,7 @@ function mergeGlobalToProject(projectDir, summary) {
|
|
|
27896
28243
|
const projectType = scanProjectType(projectDir);
|
|
27897
28244
|
const skipFrontend = ["cli", "backend-service", "unknown"].includes(projectType);
|
|
27898
28245
|
const FRONTEND_HEAD = "## 7. Frontend Default Stack";
|
|
27899
|
-
const srcText =
|
|
28246
|
+
const srcText = readFileSync51(src, "utf8");
|
|
27900
28247
|
const srcLines = srcText.split("\n");
|
|
27901
28248
|
const lines2 = srcText.endsWith("\n") ? srcLines.slice(0, -1) : srcLines;
|
|
27902
28249
|
if (!existsSync56(dst)) {
|
|
@@ -27932,7 +28279,7 @@ ${fcB}`;
|
|
|
27932
28279
|
summary.push("created|AGENTS.md");
|
|
27933
28280
|
return;
|
|
27934
28281
|
}
|
|
27935
|
-
const dstText =
|
|
28282
|
+
const dstText = readFileSync51(dst, "utf8");
|
|
27936
28283
|
let added = 0;
|
|
27937
28284
|
let curH = "";
|
|
27938
28285
|
let curB = "";
|
|
@@ -27981,9 +28328,9 @@ function mergeClaudeToProject(projectDir, summary) {
|
|
|
27981
28328
|
summary.push("created|.claude/CLAUDE.md");
|
|
27982
28329
|
return;
|
|
27983
28330
|
}
|
|
27984
|
-
const tplText =
|
|
28331
|
+
const tplText = readFileSync51(tplFile, "utf8");
|
|
27985
28332
|
const lines2 = tplText.endsWith("\n") ? tplText.split("\n").slice(0, -1) : tplText.split("\n");
|
|
27986
|
-
const outText =
|
|
28333
|
+
const outText = readFileSync51(outFile, "utf8");
|
|
27987
28334
|
let added = 0;
|
|
27988
28335
|
let curH = "";
|
|
27989
28336
|
let curB = "";
|
|
@@ -28217,7 +28564,7 @@ function printMergeSummary(summary) {
|
|
|
28217
28564
|
function seedBacklogRow(backlog, heading, row2, id) {
|
|
28218
28565
|
if (!existsSync56(backlog))
|
|
28219
28566
|
return false;
|
|
28220
|
-
const text =
|
|
28567
|
+
const text = readFileSync51(backlog, "utf8");
|
|
28221
28568
|
if (text.includes(`| ${id} |`))
|
|
28222
28569
|
return false;
|
|
28223
28570
|
const lines2 = text.split("\n");
|
|
@@ -28325,7 +28672,7 @@ function renderAndSeed(projectDir, plan, changeset) {
|
|
|
28325
28672
|
}
|
|
28326
28673
|
function addRollToGitignore(projectDir, changeset) {
|
|
28327
28674
|
const gi = join54(projectDir, ".gitignore");
|
|
28328
|
-
const current = existsSync56(gi) ?
|
|
28675
|
+
const current = existsSync56(gi) ? readFileSync51(gi, "utf8") : "";
|
|
28329
28676
|
if (current.split("\n").includes(".roll/"))
|
|
28330
28677
|
return;
|
|
28331
28678
|
writeFileSync27(gi, current + (current === "" || current.endsWith("\n") ? "" : "\n") + ".roll/\n");
|
|
@@ -28581,28 +28928,52 @@ function initCommand(args) {
|
|
|
28581
28928
|
init_dist2();
|
|
28582
28929
|
import { createInterface as createInterface2 } from "node:readline";
|
|
28583
28930
|
var KIND_COLOR = {
|
|
28931
|
+
lifecycle: "dim",
|
|
28932
|
+
edit: "muted",
|
|
28933
|
+
test: "green",
|
|
28934
|
+
tool: "muted",
|
|
28935
|
+
say: "dim",
|
|
28584
28936
|
tcr: "green",
|
|
28585
|
-
|
|
28586
|
-
ci: "green",
|
|
28587
|
-
peer: "purple",
|
|
28588
|
-
attest: "blue",
|
|
28937
|
+
commit: "green",
|
|
28589
28938
|
pr: "green",
|
|
28939
|
+
gate: "purple",
|
|
28940
|
+
heartbeat: "amber",
|
|
28590
28941
|
alert: "red"
|
|
28591
28942
|
};
|
|
28592
|
-
|
|
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 = {}) {
|
|
28593
28962
|
const ts = opts.ts !== void 0 && opts.ts !== "" ? c("muted", opts.ts) + " " : "";
|
|
28594
|
-
if (
|
|
28595
|
-
const detail2 =
|
|
28596
|
-
return `${ts}${c("dim",
|
|
28597
|
-
}
|
|
28598
|
-
if (
|
|
28599
|
-
|
|
28600
|
-
|
|
28601
|
-
|
|
28602
|
-
const
|
|
28603
|
-
const
|
|
28604
|
-
const
|
|
28605
|
-
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) : "";
|
|
28606
28977
|
return `${ts}${arrow} ${cat} ${label4}${detail}`;
|
|
28607
28978
|
}
|
|
28608
28979
|
function hms() {
|
|
@@ -28610,14 +28981,24 @@ function hms() {
|
|
|
28610
28981
|
const p = (n) => String(n).padStart(2, "0");
|
|
28611
28982
|
return `${p(d.getHours())}:${p(d.getMinutes())}:${p(d.getSeconds())}`;
|
|
28612
28983
|
}
|
|
28613
|
-
var HELP3 = `Usage: roll loop fmt
|
|
28984
|
+
var HELP3 = `Usage: roll loop fmt [--verbose] [--no-color]
|
|
28985
|
+
|
|
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
|
|
28614
28995
|
|
|
28615
|
-
|
|
28616
|
-
|
|
28617
|
-
edits, and surfaces signals (tcr / story / ci / peer / pr / error).
|
|
28618
|
-
\u8BFB\u53D6 agent \u7684 stream-json\uFF0C\u8F93\u51FA\u4E09\u5C42\u5173\u952E\u8282\u70B9\u8F6C\u5F55\uFF08\u89C2\u6D4B\u7A97\uFF09\u3002
|
|
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)
|
|
28619
28998
|
|
|
28620
|
-
|
|
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
|
|
28621
29002
|
`;
|
|
28622
29003
|
async function loopFmtCommand(args) {
|
|
28623
29004
|
if (args.includes("--help") || args.includes("-h")) {
|
|
@@ -28626,23 +29007,28 @@ async function loopFmtCommand(args) {
|
|
|
28626
29007
|
}
|
|
28627
29008
|
const noColor2 = args.includes("--no-color") || !process.stdout.isTTY || (process.env["NO_COLOR"] ?? "") !== "";
|
|
28628
29009
|
renderState.useColor = !noColor2;
|
|
28629
|
-
const
|
|
28630
|
-
|
|
28631
|
-
|
|
28632
|
-
|
|
28633
|
-
|
|
28634
|
-
|
|
28635
|
-
|
|
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");
|
|
28636
29028
|
}
|
|
28637
29029
|
}
|
|
28638
|
-
|
|
28639
|
-
|
|
28640
|
-
const rl = createInterface2({ input: process.stdin, crlfDelay: Infinity });
|
|
28641
|
-
for await (const raw of rl) {
|
|
28642
|
-
if (raw.trim() === "")
|
|
28643
|
-
continue;
|
|
28644
|
-
process.stdout.write(`${c("muted", hms())} ${c("dim", raw)}
|
|
28645
|
-
`);
|
|
29030
|
+
} finally {
|
|
29031
|
+
clearInterval(beat);
|
|
28646
29032
|
}
|
|
28647
29033
|
return 0;
|
|
28648
29034
|
}
|
|
@@ -28651,7 +29037,7 @@ async function loopFmtCommand(args) {
|
|
|
28651
29037
|
init_dist3();
|
|
28652
29038
|
init_dist();
|
|
28653
29039
|
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
28654
|
-
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";
|
|
28655
29041
|
import { homedir as homedir16 } from "node:os";
|
|
28656
29042
|
import { basename as basename11, dirname as dirname21, join as join55 } from "node:path";
|
|
28657
29043
|
function palette3() {
|
|
@@ -28737,7 +29123,7 @@ function fileMtimeSec(f) {
|
|
|
28737
29123
|
}
|
|
28738
29124
|
function plistWorkingDir(plistPath) {
|
|
28739
29125
|
try {
|
|
28740
|
-
const m7 = /<key>WorkingDirectory<\/key>\s*<string>([^<]*)<\/string>/.exec(
|
|
29126
|
+
const m7 = /<key>WorkingDirectory<\/key>\s*<string>([^<]*)<\/string>/.exec(readFileSync52(plistPath, "utf8"));
|
|
28741
29127
|
return m7?.[1] ?? "";
|
|
28742
29128
|
} catch {
|
|
28743
29129
|
return "";
|
|
@@ -28957,14 +29343,14 @@ function loopTestCommand(args = [], deps = realTestDeps()) {
|
|
|
28957
29343
|
// packages/cli/dist/commands/loop-pr-inbox.js
|
|
28958
29344
|
init_dist2();
|
|
28959
29345
|
init_dist3();
|
|
28960
|
-
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";
|
|
28961
29347
|
import { dirname as dirname23, join as join57 } from "node:path";
|
|
28962
29348
|
|
|
28963
29349
|
// packages/cli/dist/commands/loop-pr-heal.js
|
|
28964
29350
|
init_dist2();
|
|
28965
29351
|
init_dist3();
|
|
28966
29352
|
import { execFileSync as execFileSync12, spawn as spawn5 } from "node:child_process";
|
|
28967
|
-
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";
|
|
28968
29354
|
import { tmpdir as tmpdir6 } from "node:os";
|
|
28969
29355
|
import { dirname as dirname22, join as join56 } from "node:path";
|
|
28970
29356
|
function runtimeDir3() {
|
|
@@ -28990,7 +29376,7 @@ function nowIso() {
|
|
|
28990
29376
|
function realHealDeps() {
|
|
28991
29377
|
const readState = () => {
|
|
28992
29378
|
try {
|
|
28993
|
-
return
|
|
29379
|
+
return readFileSync53(statePath(), "utf8");
|
|
28994
29380
|
} catch {
|
|
28995
29381
|
return "";
|
|
28996
29382
|
}
|
|
@@ -29008,7 +29394,7 @@ function realHealDeps() {
|
|
|
29008
29394
|
return { lockPresent: false, lockPidAlive: void 0 };
|
|
29009
29395
|
let alive;
|
|
29010
29396
|
try {
|
|
29011
|
-
const pid = parseInt(
|
|
29397
|
+
const pid = parseInt(readFileSync53(p, "utf8").trim(), 10);
|
|
29012
29398
|
alive = Number.isFinite(pid) ? (() => {
|
|
29013
29399
|
try {
|
|
29014
29400
|
process.kill(pid, 0);
|
|
@@ -29029,7 +29415,7 @@ function realHealDeps() {
|
|
|
29029
29415
|
},
|
|
29030
29416
|
alertHasKey: (key) => {
|
|
29031
29417
|
try {
|
|
29032
|
-
return
|
|
29418
|
+
return readFileSync53(alertPath2(), "utf8").includes(key);
|
|
29033
29419
|
} catch {
|
|
29034
29420
|
return false;
|
|
29035
29421
|
}
|
|
@@ -29247,10 +29633,10 @@ function reducePrView(raw) {
|
|
|
29247
29633
|
}
|
|
29248
29634
|
async function runPrInbox(deps) {
|
|
29249
29635
|
if (!await deps.ghAvailable())
|
|
29250
|
-
return
|
|
29636
|
+
return emit3(deps, prIdleTick("gh_unavailable"));
|
|
29251
29637
|
const slug = await deps.resolveSlug();
|
|
29252
29638
|
if (slug === void 0 || slug === "")
|
|
29253
|
-
return
|
|
29639
|
+
return emit3(deps, prIdleTick("gh_unavailable"));
|
|
29254
29640
|
const list2 = await deps.listOpenPrs(slug);
|
|
29255
29641
|
const stdout = (list2.stdout ?? "").trim();
|
|
29256
29642
|
let openCount = 0;
|
|
@@ -29270,7 +29656,7 @@ async function runPrInbox(deps) {
|
|
|
29270
29656
|
...list2.stderr !== void 0 ? { listStderr: list2.stderr } : {}
|
|
29271
29657
|
});
|
|
29272
29658
|
if (gate !== void 0)
|
|
29273
|
-
return
|
|
29659
|
+
return emit3(deps, gate);
|
|
29274
29660
|
const prs = JSON.parse(stdout);
|
|
29275
29661
|
for (const pr of prs) {
|
|
29276
29662
|
const num4 = String(pr.number ?? "");
|
|
@@ -29306,9 +29692,9 @@ async function runPrInbox(deps) {
|
|
|
29306
29692
|
break;
|
|
29307
29693
|
}
|
|
29308
29694
|
}
|
|
29309
|
-
return
|
|
29695
|
+
return emit3(deps, prActedTick());
|
|
29310
29696
|
}
|
|
29311
|
-
function
|
|
29697
|
+
function emit3(deps, tick) {
|
|
29312
29698
|
deps.writeTick(tick);
|
|
29313
29699
|
return tick;
|
|
29314
29700
|
}
|
|
@@ -29352,7 +29738,7 @@ function writeTickFile(tick) {
|
|
|
29352
29738
|
appendFileSync11(file, `${JSON.stringify({ ts, ...tick })}
|
|
29353
29739
|
`);
|
|
29354
29740
|
try {
|
|
29355
|
-
const lines2 =
|
|
29741
|
+
const lines2 = readFileSync54(file, "utf8").split("\n").filter((l) => l !== "");
|
|
29356
29742
|
if (lines2.length > 500)
|
|
29357
29743
|
writeFileSync30(file, `${lines2.slice(-500).join("\n")}
|
|
29358
29744
|
`);
|
|
@@ -29369,7 +29755,7 @@ function deadTickMarkerPath() {
|
|
|
29369
29755
|
function checkDeadTickStreak(file, alert, markerPath = deadTickMarkerPath()) {
|
|
29370
29756
|
let rows = [];
|
|
29371
29757
|
try {
|
|
29372
|
-
rows =
|
|
29758
|
+
rows = readFileSync54(file, "utf8").split("\n").filter((l) => l.trim() !== "").map((l) => JSON.parse(l));
|
|
29373
29759
|
} catch {
|
|
29374
29760
|
return;
|
|
29375
29761
|
}
|
|
@@ -29405,7 +29791,7 @@ function rebaseCircuitAllowed(num4) {
|
|
|
29405
29791
|
const state = statePath2();
|
|
29406
29792
|
let body = "";
|
|
29407
29793
|
try {
|
|
29408
|
-
body =
|
|
29794
|
+
body = readFileSync54(state, "utf8");
|
|
29409
29795
|
} catch {
|
|
29410
29796
|
}
|
|
29411
29797
|
const verdict = rebaseCircuitVerdict(parseRebaseAttempts(body, num4), nowSec());
|
|
@@ -29471,7 +29857,7 @@ function writeRebaseAttempts(state, pr, timestamps) {
|
|
|
29471
29857
|
mkdirSync30(dirname23(state), { recursive: true });
|
|
29472
29858
|
let body = "";
|
|
29473
29859
|
try {
|
|
29474
|
-
body =
|
|
29860
|
+
body = readFileSync54(state, "utf8");
|
|
29475
29861
|
} catch {
|
|
29476
29862
|
}
|
|
29477
29863
|
writeFileSync30(state, upsertRebaseAttempts(body, pr, renderRebaseAttempts(timestamps)));
|
|
@@ -29553,7 +29939,7 @@ async function loopPrInboxCommand(_args, deps = realDeps6()) {
|
|
|
29553
29939
|
init_dist2();
|
|
29554
29940
|
init_dist();
|
|
29555
29941
|
init_dist3();
|
|
29556
|
-
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";
|
|
29557
29943
|
import { dirname as dirname29, join as join66 } from "node:path";
|
|
29558
29944
|
|
|
29559
29945
|
// packages/cli/dist/runner/executor.js
|
|
@@ -29561,13 +29947,13 @@ init_dist2();
|
|
|
29561
29947
|
init_dist();
|
|
29562
29948
|
init_dist3();
|
|
29563
29949
|
import { execFile as execFile9 } from "node:child_process";
|
|
29564
|
-
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";
|
|
29565
29951
|
import { dirname as dirname26, join as join63 } from "node:path";
|
|
29566
29952
|
import { promisify as promisify9 } from "node:util";
|
|
29567
29953
|
|
|
29568
29954
|
// packages/cli/dist/runner/attest-gate.js
|
|
29569
29955
|
init_dist2();
|
|
29570
|
-
import { existsSync as existsSync60, readFileSync as
|
|
29956
|
+
import { existsSync as existsSync60, readFileSync as readFileSync55, readdirSync as readdirSync24, statSync as statSync21 } from "node:fs";
|
|
29571
29957
|
import { dirname as dirname24, join as join58 } from "node:path";
|
|
29572
29958
|
function reportCandidates(worktreeCwd, storyId) {
|
|
29573
29959
|
return [join58(cardArchiveDir(worktreeCwd, storyId), "latest", reportFileName(storyId))];
|
|
@@ -29598,7 +29984,7 @@ function storyHasAcBlock(worktreeCwd, storyId) {
|
|
|
29598
29984
|
if (spec === null)
|
|
29599
29985
|
return null;
|
|
29600
29986
|
try {
|
|
29601
|
-
return acForStory(
|
|
29987
|
+
return acForStory(readFileSync55(spec, "utf8"), storyId, { fileOwned: true }).length > 0;
|
|
29602
29988
|
} catch {
|
|
29603
29989
|
return null;
|
|
29604
29990
|
}
|
|
@@ -29608,7 +29994,7 @@ function storyRequiresScreenshot(worktreeCwd, storyId) {
|
|
|
29608
29994
|
if (spec === null)
|
|
29609
29995
|
return false;
|
|
29610
29996
|
try {
|
|
29611
|
-
return /\b(CLI|web|UI|TUI)\b|界面|交互|截屏|截图|screenshot/i.test(
|
|
29997
|
+
return /\b(CLI|web|UI|TUI)\b|界面|交互|截屏|截图|screenshot/i.test(readFileSync55(spec, "utf8"));
|
|
29612
29998
|
} catch {
|
|
29613
29999
|
return false;
|
|
29614
30000
|
}
|
|
@@ -29618,7 +30004,7 @@ function readAcMapEntries(worktreeCwd, storyId) {
|
|
|
29618
30004
|
if (path === void 0 || !existsSync60(path))
|
|
29619
30005
|
return null;
|
|
29620
30006
|
try {
|
|
29621
|
-
const parsed = JSON.parse(
|
|
30007
|
+
const parsed = JSON.parse(readFileSync55(path, "utf8"));
|
|
29622
30008
|
return Array.isArray(parsed) ? parsed.filter((x) => typeof x === "object" && x !== null) : null;
|
|
29623
30009
|
} catch {
|
|
29624
30010
|
return null;
|
|
@@ -29632,7 +30018,7 @@ function evidenceManifest(worktreeCwd, storyId) {
|
|
|
29632
30018
|
if (!existsSync60(path))
|
|
29633
30019
|
return null;
|
|
29634
30020
|
try {
|
|
29635
|
-
const parsed = JSON.parse(
|
|
30021
|
+
const parsed = JSON.parse(readFileSync55(path, "utf8"));
|
|
29636
30022
|
return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : null;
|
|
29637
30023
|
} catch {
|
|
29638
30024
|
return null;
|
|
@@ -29664,6 +30050,12 @@ function passAcVisualFloor(worktreeCwd, storyId) {
|
|
|
29664
30050
|
const ids = missing.map((e) => e.ac ?? "?").join(", ");
|
|
29665
30051
|
return { ok: false, reason: `pass AC(s) lack screenshot evidence or machine capture skip: ${ids}` };
|
|
29666
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
|
+
}
|
|
29667
30059
|
function verificationReportPath(worktreeCwd, storyId) {
|
|
29668
30060
|
return reportCandidates(worktreeCwd, storyId)[0];
|
|
29669
30061
|
}
|
|
@@ -29699,7 +30091,7 @@ function verificationReportHasContent(worktreeCwd, storyId) {
|
|
|
29699
30091
|
if (p === null)
|
|
29700
30092
|
return false;
|
|
29701
30093
|
try {
|
|
29702
|
-
const html =
|
|
30094
|
+
const html = readFileSync55(p, "utf8");
|
|
29703
30095
|
const hasMap = acMapCandidates(worktreeCwd, storyId).some((m7) => existsSync60(m7));
|
|
29704
30096
|
if (!hasMap)
|
|
29705
30097
|
return false;
|
|
@@ -29733,7 +30125,7 @@ function readAttestGateMode(repoCwd) {
|
|
|
29733
30125
|
const p = join58(repoCwd, ".roll", "policy.yaml");
|
|
29734
30126
|
if (!existsSync60(p))
|
|
29735
30127
|
return "hard";
|
|
29736
|
-
return parsePolicy(
|
|
30128
|
+
return parsePolicy(readFileSync55(p, "utf8")).loopSafety.attestGate === "hard" ? "hard" : "soft";
|
|
29737
30129
|
} catch {
|
|
29738
30130
|
return "hard";
|
|
29739
30131
|
}
|
|
@@ -29745,6 +30137,16 @@ function runAttestGate(worktreeCwd, storyId, cycleId, mode, sinceSec, sinks) {
|
|
|
29745
30137
|
sinks.event({ cycleId, verdict: "produced", reasons: reasons2 });
|
|
29746
30138
|
return { verdict: "produced", mode, reasons: reasons2, blocked: false };
|
|
29747
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
|
+
}
|
|
29748
30150
|
const fresh = verificationReportFresh(worktreeCwd, storyId, sinceSec);
|
|
29749
30151
|
if (fresh && verificationReportHasContent(worktreeCwd, storyId)) {
|
|
29750
30152
|
const score = evaluateSelfScoreGate(worktreeCwd, storyId);
|
|
@@ -29775,7 +30177,7 @@ function runAttestGate(worktreeCwd, storyId, cycleId, mode, sinceSec, sinks) {
|
|
|
29775
30177
|
|
|
29776
30178
|
// packages/cli/dist/runner/usage-recovery.js
|
|
29777
30179
|
init_dist2();
|
|
29778
|
-
import { readFileSync as
|
|
30180
|
+
import { readFileSync as readFileSync56, readdirSync as readdirSync25, statSync as statSync22 } from "node:fs";
|
|
29779
30181
|
import { homedir as homedir17 } from "node:os";
|
|
29780
30182
|
import { join as join59 } from "node:path";
|
|
29781
30183
|
function defaultPiSessionsRoot() {
|
|
@@ -29798,7 +30200,7 @@ function recoverPiUsage(worktreeCwd, sinceSec, sessionsRoot = defaultPiSessionsR
|
|
|
29798
30200
|
try {
|
|
29799
30201
|
if (sinceSec !== void 0 && statSync22(p).mtimeMs / 1e3 < sinceSec)
|
|
29800
30202
|
continue;
|
|
29801
|
-
summaries.push(sumPiSession(
|
|
30203
|
+
summaries.push(sumPiSession(readFileSync56(p, "utf8").split("\n")));
|
|
29802
30204
|
} catch {
|
|
29803
30205
|
}
|
|
29804
30206
|
}
|
|
@@ -29819,14 +30221,14 @@ function recoverPiUsage(worktreeCwd, sinceSec, sessionsRoot = defaultPiSessionsR
|
|
|
29819
30221
|
|
|
29820
30222
|
// packages/cli/dist/runner/budget-check.js
|
|
29821
30223
|
init_dist2();
|
|
29822
|
-
import { existsSync as existsSync61, readFileSync as
|
|
30224
|
+
import { existsSync as existsSync61, readFileSync as readFileSync57 } from "node:fs";
|
|
29823
30225
|
import { join as join60 } from "node:path";
|
|
29824
30226
|
function readBudgetPolicy(repoCwd) {
|
|
29825
30227
|
try {
|
|
29826
30228
|
const p = join60(repoCwd, ".roll", "policy.yaml");
|
|
29827
30229
|
if (!existsSync61(p))
|
|
29828
30230
|
return void 0;
|
|
29829
|
-
return parsePolicy(
|
|
30231
|
+
return parsePolicy(readFileSync57(p, "utf8")).loopSafety.budget;
|
|
29830
30232
|
} catch {
|
|
29831
30233
|
return void 0;
|
|
29832
30234
|
}
|
|
@@ -29835,7 +30237,7 @@ function ledgerFromRuns(runsPath3) {
|
|
|
29835
30237
|
const ledger = new BudgetLedger();
|
|
29836
30238
|
let body;
|
|
29837
30239
|
try {
|
|
29838
|
-
body =
|
|
30240
|
+
body = readFileSync57(runsPath3, "utf8");
|
|
29839
30241
|
} catch {
|
|
29840
30242
|
return ledger;
|
|
29841
30243
|
}
|
|
@@ -29921,21 +30323,21 @@ function buildAcMapRemediationPrompt(worktreeCwd, storyId, runDir) {
|
|
|
29921
30323
|
// packages/cli/dist/runner/correction-actuator.js
|
|
29922
30324
|
init_dist2();
|
|
29923
30325
|
init_dist();
|
|
29924
|
-
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";
|
|
29925
30327
|
import { dirname as dirname25, join as join62 } from "node:path";
|
|
29926
30328
|
function readMode(projectPath3) {
|
|
29927
30329
|
try {
|
|
29928
30330
|
const path = join62(projectPath3, ".roll", "policy.yaml");
|
|
29929
30331
|
if (!existsSync63(path))
|
|
29930
30332
|
return "conservative";
|
|
29931
|
-
return parsePolicy(
|
|
30333
|
+
return parsePolicy(readFileSync58(path, "utf8")).loopSafety.correctionActuator;
|
|
29932
30334
|
} catch {
|
|
29933
30335
|
return "conservative";
|
|
29934
30336
|
}
|
|
29935
30337
|
}
|
|
29936
30338
|
function readEvents(eventsPath2) {
|
|
29937
30339
|
try {
|
|
29938
|
-
return
|
|
30340
|
+
return readFileSync58(eventsPath2, "utf8").split("\n").map(parseEventLine).filter((ev) => ev !== null);
|
|
29939
30341
|
} catch {
|
|
29940
30342
|
return [];
|
|
29941
30343
|
}
|
|
@@ -29974,7 +30376,7 @@ function markStoryTodo(projectPath3, storyId) {
|
|
|
29974
30376
|
}
|
|
29975
30377
|
function storyEpic(projectPath3, storyId) {
|
|
29976
30378
|
try {
|
|
29977
|
-
const idx = JSON.parse(
|
|
30379
|
+
const idx = JSON.parse(readFileSync58(join62(projectPath3, ".roll", "index.json"), "utf8"));
|
|
29978
30380
|
const epic = idx[storyId];
|
|
29979
30381
|
if (typeof epic === "string" && epic.trim() !== "")
|
|
29980
30382
|
return epic;
|
|
@@ -29992,7 +30394,7 @@ function storyEpic(projectPath3, storyId) {
|
|
|
29992
30394
|
}
|
|
29993
30395
|
return "uncategorized";
|
|
29994
30396
|
}
|
|
29995
|
-
function existingFixId(projectPath3, storyId,
|
|
30397
|
+
function existingFixId(projectPath3, storyId, signal) {
|
|
29996
30398
|
try {
|
|
29997
30399
|
const snap = new BacklogStore().readBacklog(join62(projectPath3, ".roll", "backlog.md"));
|
|
29998
30400
|
return snap.items.find((it) => {
|
|
@@ -30003,7 +30405,7 @@ function existingFixId(projectPath3, storyId, signal2) {
|
|
|
30003
30405
|
return false;
|
|
30004
30406
|
if (!desc.includes(`fixes:${storyId.toLowerCase()}`))
|
|
30005
30407
|
return false;
|
|
30006
|
-
if (!desc.includes(`signal:${
|
|
30408
|
+
if (!desc.includes(`signal:${signal.toLowerCase()}`))
|
|
30007
30409
|
return false;
|
|
30008
30410
|
return classifyStatus(it.status) !== "done";
|
|
30009
30411
|
})?.id;
|
|
@@ -30011,8 +30413,8 @@ function existingFixId(projectPath3, storyId, signal2) {
|
|
|
30011
30413
|
return void 0;
|
|
30012
30414
|
}
|
|
30013
30415
|
}
|
|
30014
|
-
function fixDescription(storyId,
|
|
30015
|
-
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`;
|
|
30016
30418
|
}
|
|
30017
30419
|
function writeFixSpec(projectPath3, epic, fixId, decision) {
|
|
30018
30420
|
try {
|
|
@@ -30339,7 +30741,45 @@ ${res.stderr}
|
|
|
30339
30741
|
tcrCount = await ports.git.tcrCount(ports.paths.worktreePath);
|
|
30340
30742
|
} catch {
|
|
30341
30743
|
}
|
|
30342
|
-
|
|
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 = {
|
|
30343
30783
|
alert: (m7) => ports.events.appendAlert(ports.paths.alertsPath, m7),
|
|
30344
30784
|
event: (p) => ports.events.appendEvent(ports.paths.eventsPath, {
|
|
30345
30785
|
type: "peer:gate",
|
|
@@ -30348,58 +30788,44 @@ ${res.stderr}
|
|
|
30348
30788
|
reasons: p.reasons,
|
|
30349
30789
|
ts: ports.clock()
|
|
30350
30790
|
})
|
|
30351
|
-
}
|
|
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
|
+
}
|
|
30352
30812
|
{
|
|
30353
|
-
const reviewPeer = async (peer, diff, timeoutMs) => {
|
|
30354
|
-
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.
|
|
30355
|
-
|
|
30356
|
-
DIFF:
|
|
30357
|
-
` + diff;
|
|
30358
|
-
let res;
|
|
30359
|
-
try {
|
|
30360
|
-
res = await Promise.race([
|
|
30361
|
-
ports.agentSpawn(peer, {
|
|
30362
|
-
cwd: ports.paths.worktreePath,
|
|
30363
|
-
skillBody: prompt,
|
|
30364
|
-
timeoutMs,
|
|
30365
|
-
...ctx.evidenceRunDir !== void 0 ? { runDir: ctx.evidenceRunDir } : {}
|
|
30366
|
-
}),
|
|
30367
|
-
new Promise((resolve5) => setTimeout(() => resolve5(null), timeoutMs).unref())
|
|
30368
|
-
]);
|
|
30369
|
-
} catch {
|
|
30370
|
-
return null;
|
|
30371
|
-
}
|
|
30372
|
-
if (res === null || res.timedOut || res.exitCode !== 0)
|
|
30373
|
-
return null;
|
|
30374
|
-
const vm = /VERDICT:\s*(agree|refine|object)/i.exec(res.stdout);
|
|
30375
|
-
const verdict = vm?.[1]?.toLowerCase() ?? "agree";
|
|
30376
|
-
const findings = [...res.stdout.matchAll(/^\s*FINDING:\s*(.+)$/gim)].map((m7) => (m7[1] ?? "").trim());
|
|
30377
|
-
const cost = peerReviewCost(peer, res.stdout);
|
|
30378
|
-
return { verdict, findings, cost };
|
|
30379
|
-
};
|
|
30380
30813
|
let pairHistory;
|
|
30381
30814
|
try {
|
|
30382
30815
|
if (existsSync64(ports.paths.eventsPath)) {
|
|
30383
|
-
const events =
|
|
30816
|
+
const events = readFileSync59(ports.paths.eventsPath, "utf8").split("\n").map(parseEventLine).filter((e) => e !== null);
|
|
30384
30817
|
pairHistory = pairingHistory(events);
|
|
30385
30818
|
}
|
|
30386
30819
|
} catch {
|
|
30387
30820
|
}
|
|
30388
30821
|
const pairingDeps = {
|
|
30389
|
-
installed: agentsInstalled(realAgentEnv()),
|
|
30822
|
+
installed: ports.installedAgents?.() ?? agentsInstalled(realAgentEnv()),
|
|
30390
30823
|
isAvailable: () => true,
|
|
30391
30824
|
// MVP: `installed` is the hard gate; a dead peer → reviewPeer null (non-blocking). Real probe is a refinement.
|
|
30392
30825
|
reviewPeer,
|
|
30393
30826
|
...pairHistory !== void 0 ? { history: pairHistory } : {},
|
|
30394
30827
|
changedFiles: cycleChangedFiles,
|
|
30395
|
-
diff:
|
|
30396
|
-
try {
|
|
30397
|
-
const { stdout } = await execFileAsync9("git", ["diff", "origin/main...HEAD"], { cwd, encoding: "utf8" });
|
|
30398
|
-
return stdout.slice(0, 6e4);
|
|
30399
|
-
} catch {
|
|
30400
|
-
return "";
|
|
30401
|
-
}
|
|
30402
|
-
},
|
|
30828
|
+
diff: cycleDiff,
|
|
30403
30829
|
event: (e) => ports.events.appendEvent(ports.paths.eventsPath, e),
|
|
30404
30830
|
now: () => ports.clock()
|
|
30405
30831
|
};
|
|
@@ -30512,10 +30938,13 @@ ${diffStat}`;
|
|
|
30512
30938
|
}
|
|
30513
30939
|
const facts = {
|
|
30514
30940
|
usedWorktree: true,
|
|
30515
|
-
// accept-path reaches capture at exit 0; a HARD attest block fails
|
|
30516
|
-
// capture (classifyCaptured: exit ≠ 0 → failed) so Done is withheld
|
|
30517
|
-
//
|
|
30518
|
-
|
|
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,
|
|
30519
30948
|
timedOut: false,
|
|
30520
30949
|
commitsAhead,
|
|
30521
30950
|
...mainAhead > 0 ? { mainAhead } : {},
|
|
@@ -30703,10 +31132,13 @@ function buildTerminalRecord(cmd, ctx, worktreePath, nowSec2) {
|
|
|
30703
31132
|
} else {
|
|
30704
31133
|
usage2 = absent("no_parseable_usage");
|
|
30705
31134
|
}
|
|
31135
|
+
const routedModel = (ctx.model ?? "").trim() !== "" ? ctx.model : ctx.agent ?? "";
|
|
31136
|
+
const model = ctx.cost !== void 0 && ctx.cost.model !== "" ? ctx.cost.model : routedModel;
|
|
30706
31137
|
return buildTerminalEvent({
|
|
30707
31138
|
cycleId: cmd.cycleId,
|
|
30708
31139
|
storyId,
|
|
30709
31140
|
agent: ctx.agent ?? "",
|
|
31141
|
+
model,
|
|
30710
31142
|
startedAt: ctx.startSec ?? nowSec2,
|
|
30711
31143
|
endedAt: nowSec2,
|
|
30712
31144
|
outcome: OUTCOME[cmd.status] ?? "unknown",
|
|
@@ -30724,7 +31156,7 @@ function readRunsRows(runsPath3) {
|
|
|
30724
31156
|
try {
|
|
30725
31157
|
if (!existsSync64(runsPath3))
|
|
30726
31158
|
return [];
|
|
30727
|
-
return
|
|
31159
|
+
return readFileSync59(runsPath3, "utf8").split("\n").filter((l) => l.trim() !== "").map((l) => {
|
|
30728
31160
|
try {
|
|
30729
31161
|
return JSON.parse(l);
|
|
30730
31162
|
} catch {
|
|
@@ -30747,14 +31179,14 @@ function storyRequiresManualMerge(repoCwd, storyId) {
|
|
|
30747
31179
|
return needles.some((n) => lower.includes(n));
|
|
30748
31180
|
};
|
|
30749
31181
|
try {
|
|
30750
|
-
const backlog =
|
|
31182
|
+
const backlog = readFileSync59(join63(repoCwd, ".roll", "backlog.md"), "utf8");
|
|
30751
31183
|
const row2 = parseBacklog(backlog).find((it) => it.id === storyId);
|
|
30752
31184
|
if (row2 !== void 0 && containsMarker(row2.desc))
|
|
30753
31185
|
return true;
|
|
30754
31186
|
} catch {
|
|
30755
31187
|
}
|
|
30756
31188
|
try {
|
|
30757
|
-
return containsMarker(
|
|
31189
|
+
return containsMarker(readFileSync59(join63(cardArchiveDir(repoCwd, storyId), "spec.md"), "utf8"));
|
|
30758
31190
|
} catch {
|
|
30759
31191
|
return false;
|
|
30760
31192
|
}
|
|
@@ -30793,7 +31225,7 @@ function persistWorktreeAlerts(worktreePath, alertsPath, events) {
|
|
|
30793
31225
|
const path = join63(worktreePath, name);
|
|
30794
31226
|
if (!lstatSync3(path).isFile())
|
|
30795
31227
|
continue;
|
|
30796
|
-
const body =
|
|
31228
|
+
const body = readFileSync59(path, "utf8").trim();
|
|
30797
31229
|
if (body === "")
|
|
30798
31230
|
continue;
|
|
30799
31231
|
events.appendAlert(alertsPath, `# worktree alert persisted: ${name}
|
|
@@ -30823,7 +31255,7 @@ async function linkRollIntoWorktree(repoCwd, worktreePath) {
|
|
|
30823
31255
|
if (common === "")
|
|
30824
31256
|
return;
|
|
30825
31257
|
const exclude = join63(common, "info", "exclude");
|
|
30826
|
-
const cur = existsSync64(exclude) ?
|
|
31258
|
+
const cur = existsSync64(exclude) ? readFileSync59(exclude, "utf8") : "";
|
|
30827
31259
|
if (!/^\.roll$/m.test(cur)) {
|
|
30828
31260
|
mkdirSync32(dirname26(exclude), { recursive: true });
|
|
30829
31261
|
appendFileSync13(exclude, `${cur === "" || cur.endsWith("\n") ? "" : "\n"}.roll
|
|
@@ -30947,7 +31379,7 @@ function nodePorts(opts) {
|
|
|
30947
31379
|
const p = join63(projectCwd, ".roll", "backlog.md");
|
|
30948
31380
|
if (!existsSync64(p))
|
|
30949
31381
|
return [];
|
|
30950
|
-
return parseBacklog(
|
|
31382
|
+
return parseBacklog(readFileSync59(p, "utf8"));
|
|
30951
31383
|
},
|
|
30952
31384
|
// FIX-198: the production binding was MISSING entirely (the optional
|
|
30953
31385
|
// chain made every In-Progress claim a silent no-op). ID-anchored mark
|
|
@@ -31180,21 +31612,21 @@ function describeCommand(cmd) {
|
|
|
31180
31612
|
// packages/cli/dist/runner/correction-circuit.js
|
|
31181
31613
|
init_dist2();
|
|
31182
31614
|
init_dist();
|
|
31183
|
-
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";
|
|
31184
31616
|
import { dirname as dirname27, join as join64 } from "node:path";
|
|
31185
31617
|
function readLoopSafety(projectPath3) {
|
|
31186
31618
|
try {
|
|
31187
31619
|
const path = join64(projectPath3, ".roll", "policy.yaml");
|
|
31188
31620
|
if (!existsSync65(path))
|
|
31189
31621
|
return parsePolicy("").loopSafety;
|
|
31190
|
-
return parsePolicy(
|
|
31622
|
+
return parsePolicy(readFileSync60(path, "utf8")).loopSafety;
|
|
31191
31623
|
} catch {
|
|
31192
31624
|
return parsePolicy("").loopSafety;
|
|
31193
31625
|
}
|
|
31194
31626
|
}
|
|
31195
31627
|
function readEvents2(eventsPath2) {
|
|
31196
31628
|
try {
|
|
31197
|
-
return
|
|
31629
|
+
return readFileSync60(eventsPath2, "utf8").split("\n").map(parseEventLine).filter((ev) => ev !== null);
|
|
31198
31630
|
} catch {
|
|
31199
31631
|
return [];
|
|
31200
31632
|
}
|
|
@@ -31251,7 +31683,7 @@ function applyCorrectionCircuitBreaker(projectPath3, slug, eventsPath2, alertsPa
|
|
|
31251
31683
|
// packages/cli/dist/lib/morning-report.js
|
|
31252
31684
|
init_dist2();
|
|
31253
31685
|
init_dist();
|
|
31254
|
-
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";
|
|
31255
31687
|
import { dirname as dirname28, join as join65 } from "node:path";
|
|
31256
31688
|
var esc7 = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
31257
31689
|
function iso2(sec) {
|
|
@@ -31259,14 +31691,14 @@ function iso2(sec) {
|
|
|
31259
31691
|
}
|
|
31260
31692
|
function readEvents3(path) {
|
|
31261
31693
|
try {
|
|
31262
|
-
return
|
|
31694
|
+
return readFileSync61(path, "utf8").split("\n").map(parseEventLine).filter((ev) => ev !== null);
|
|
31263
31695
|
} catch {
|
|
31264
31696
|
return [];
|
|
31265
31697
|
}
|
|
31266
31698
|
}
|
|
31267
31699
|
function readRuns(path) {
|
|
31268
31700
|
try {
|
|
31269
|
-
return
|
|
31701
|
+
return readFileSync61(path, "utf8").split("\n").map((line) => line.trim()).filter((line) => line !== "").map((line) => JSON.parse(line));
|
|
31270
31702
|
} catch {
|
|
31271
31703
|
return [];
|
|
31272
31704
|
}
|
|
@@ -31338,7 +31770,7 @@ function writeLatestMorningReport(projectPath3, eventsPath2, runsPath3, nowSec2
|
|
|
31338
31770
|
// packages/cli/dist/lib/runs-backfill.js
|
|
31339
31771
|
init_dist2();
|
|
31340
31772
|
init_dist3();
|
|
31341
|
-
import { readFileSync as
|
|
31773
|
+
import { readFileSync as readFileSync62, writeFileSync as writeFileSync35 } from "node:fs";
|
|
31342
31774
|
var BACKFILL_PROBE_CAP = 20;
|
|
31343
31775
|
function parseLine(raw) {
|
|
31344
31776
|
if (raw.trim() === "")
|
|
@@ -31360,7 +31792,7 @@ function isCandidate(row2) {
|
|
|
31360
31792
|
async function backfillMergedRuns(projectPath3, runsPath3, deps = {}) {
|
|
31361
31793
|
let body;
|
|
31362
31794
|
try {
|
|
31363
|
-
body =
|
|
31795
|
+
body = readFileSync62(runsPath3, "utf8");
|
|
31364
31796
|
} catch {
|
|
31365
31797
|
return [];
|
|
31366
31798
|
}
|
|
@@ -31448,7 +31880,7 @@ function cycleSignalTeardown(paths, cycleId, branch, sig, deps = {}) {
|
|
|
31448
31880
|
}
|
|
31449
31881
|
let owned = false;
|
|
31450
31882
|
try {
|
|
31451
|
-
owned = existsSync67(paths.lockPath) && parseLock(
|
|
31883
|
+
owned = existsSync67(paths.lockPath) && parseLock(readFileSync63(paths.lockPath, "utf8")).pid === pid;
|
|
31452
31884
|
} catch {
|
|
31453
31885
|
owned = false;
|
|
31454
31886
|
}
|
|
@@ -31533,7 +31965,7 @@ function incrementConsecutiveFails(projectPath3, slug, alertsPath, eventsPath2,
|
|
|
31533
31965
|
let count = 0;
|
|
31534
31966
|
try {
|
|
31535
31967
|
if (existsSync67(counterFile)) {
|
|
31536
|
-
count = parseInt(
|
|
31968
|
+
count = parseInt(readFileSync63(counterFile, "utf8").trim(), 10) || 0;
|
|
31537
31969
|
}
|
|
31538
31970
|
} catch {
|
|
31539
31971
|
}
|
|
@@ -31585,7 +32017,7 @@ function readFailurePauseThreshold(projectPath3) {
|
|
|
31585
32017
|
const policy = join66(projectPath3, ".roll", "policy.yaml");
|
|
31586
32018
|
if (!existsSync67(policy))
|
|
31587
32019
|
return PAUSE_THRESHOLD;
|
|
31588
|
-
return parsePolicy(
|
|
32020
|
+
return parsePolicy(readFileSync63(policy, "utf8")).loopSafety.maxConsecutiveFailures;
|
|
31589
32021
|
} catch {
|
|
31590
32022
|
return PAUSE_THRESHOLD;
|
|
31591
32023
|
}
|
|
@@ -31610,7 +32042,7 @@ function buildLoopRouteDeps(projectPath3) {
|
|
|
31610
32042
|
function readSlot(slot) {
|
|
31611
32043
|
const agentsYaml = join66(projectPath3, ".roll", "agents.yaml");
|
|
31612
32044
|
try {
|
|
31613
|
-
return readSlotFromText(
|
|
32045
|
+
return readSlotFromText(readFileSync63(agentsYaml, "utf8"), slot);
|
|
31614
32046
|
} catch {
|
|
31615
32047
|
return void 0;
|
|
31616
32048
|
}
|
|
@@ -31625,7 +32057,7 @@ function buildLoopRouteDeps(projectPath3) {
|
|
|
31625
32057
|
}
|
|
31626
32058
|
function readField(path, re) {
|
|
31627
32059
|
try {
|
|
31628
|
-
const text =
|
|
32060
|
+
const text = readFileSync63(path, "utf8");
|
|
31629
32061
|
for (const line of text.split("\n")) {
|
|
31630
32062
|
const m7 = line.match(re);
|
|
31631
32063
|
if (m7 !== null) {
|
|
@@ -31854,7 +32286,7 @@ async function egressBlocked(resolve5 = (h) => lookup(h), tcpProbe2 = () => tcpC
|
|
|
31854
32286
|
// packages/cli/dist/commands/offboard.js
|
|
31855
32287
|
init_dist();
|
|
31856
32288
|
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
31857
|
-
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";
|
|
31858
32290
|
import { homedir as homedir18 } from "node:os";
|
|
31859
32291
|
import { join as join67, resolve as resolve3 } from "node:path";
|
|
31860
32292
|
function pal5() {
|
|
@@ -31982,7 +32414,7 @@ function offboardCommand(args) {
|
|
|
31982
32414
|
`);
|
|
31983
32415
|
return 1;
|
|
31984
32416
|
}
|
|
31985
|
-
const parsed = parseChangeset(
|
|
32417
|
+
const parsed = parseChangeset(readFileSync64(changeset, "utf8"));
|
|
31986
32418
|
if (!parsed.ok) {
|
|
31987
32419
|
err10(m4("offboard.failed_to_parse_changeset"));
|
|
31988
32420
|
return 1;
|
|
@@ -32076,7 +32508,7 @@ function offboardCommand(args) {
|
|
|
32076
32508
|
for (const item of giEntries) {
|
|
32077
32509
|
const gi = join67(projectDir, ".gitignore");
|
|
32078
32510
|
if (existsSync68(gi)) {
|
|
32079
|
-
const lines2 =
|
|
32511
|
+
const lines2 = readFileSync64(gi, "utf8").split("\n");
|
|
32080
32512
|
if (lines2.includes(item)) {
|
|
32081
32513
|
const kept = lines2.filter((l) => l !== item);
|
|
32082
32514
|
writeFileSync37(gi, kept.join("\n"));
|
|
@@ -32100,12 +32532,12 @@ function offboardCommand(args) {
|
|
|
32100
32532
|
|
|
32101
32533
|
// packages/cli/dist/commands/prices.js
|
|
32102
32534
|
init_dist();
|
|
32103
|
-
import { existsSync as existsSync70, readdirSync as readdirSync29, readFileSync as
|
|
32535
|
+
import { existsSync as existsSync70, readdirSync as readdirSync29, readFileSync as readFileSync66 } from "node:fs";
|
|
32104
32536
|
import { join as join69 } from "node:path";
|
|
32105
32537
|
|
|
32106
32538
|
// packages/cli/dist/commands/prices-refresh.js
|
|
32107
32539
|
init_dist();
|
|
32108
|
-
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";
|
|
32109
32541
|
import { join as join68 } from "node:path";
|
|
32110
32542
|
var FetchError = class extends Error {
|
|
32111
32543
|
constructor(message) {
|
|
@@ -32333,7 +32765,7 @@ function latestSnapshotPath(snapshotDir, vendor) {
|
|
|
32333
32765
|
return snaps[snaps.length - 1] ?? null;
|
|
32334
32766
|
}
|
|
32335
32767
|
function readPrices(path) {
|
|
32336
|
-
const data = JSON.parse(
|
|
32768
|
+
const data = JSON.parse(readFileSync65(path, "utf8"));
|
|
32337
32769
|
return data.prices ?? {};
|
|
32338
32770
|
}
|
|
32339
32771
|
function diffPrices(oldPrices, newPrices) {
|
|
@@ -32541,7 +32973,7 @@ function loadSnapshots() {
|
|
|
32541
32973
|
}
|
|
32542
32974
|
const files = readdirSync29(dir).filter((n) => n.startsWith("snapshot-") && n.endsWith(".json")).sort();
|
|
32543
32975
|
return files.map((name) => {
|
|
32544
|
-
const data = JSON.parse(
|
|
32976
|
+
const data = JSON.parse(readFileSync66(join69(dir, name), "utf8"));
|
|
32545
32977
|
for (const key of ["version", "effective_at", "source_url", "prices"]) {
|
|
32546
32978
|
if (data[key] === void 0)
|
|
32547
32979
|
throw new Error(`snapshot ${name} missing required key ${key}`);
|
|
@@ -32637,13 +33069,13 @@ function pricesCommand(args, deps = {}) {
|
|
|
32637
33069
|
init_dist2();
|
|
32638
33070
|
init_dist();
|
|
32639
33071
|
import { execFileSync as execFileSync14 } from "node:child_process";
|
|
32640
|
-
import { readFileSync as
|
|
33072
|
+
import { readFileSync as readFileSync70, writeFileSync as writeFileSync41, existsSync as existsSync74 } from "node:fs";
|
|
32641
33073
|
import { join as join73 } from "node:path";
|
|
32642
33074
|
|
|
32643
33075
|
// packages/cli/dist/lib/release-consistency.js
|
|
32644
33076
|
init_dist2();
|
|
32645
33077
|
init_dist();
|
|
32646
|
-
import { existsSync as existsSync72, readFileSync as
|
|
33078
|
+
import { existsSync as existsSync72, readFileSync as readFileSync68, readdirSync as readdirSync31, statSync as statSync23 } from "node:fs";
|
|
32647
33079
|
import { join as join71 } from "node:path";
|
|
32648
33080
|
|
|
32649
33081
|
// packages/cli/dist/lib/consistency-audit.js
|
|
@@ -32651,7 +33083,7 @@ init_dist2();
|
|
|
32651
33083
|
init_dist3();
|
|
32652
33084
|
init_dist();
|
|
32653
33085
|
import { execFile as execFile10 } from "node:child_process";
|
|
32654
|
-
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";
|
|
32655
33087
|
import { dirname as dirname30, join as join70 } from "node:path";
|
|
32656
33088
|
import { promisify as promisify10 } from "node:util";
|
|
32657
33089
|
init_dist();
|
|
@@ -32663,7 +33095,7 @@ function readJsonl2(path) {
|
|
|
32663
33095
|
if (!existsSync71(path))
|
|
32664
33096
|
return [];
|
|
32665
33097
|
const out3 = [];
|
|
32666
|
-
for (const line of
|
|
33098
|
+
for (const line of readFileSync67(path, "utf8").split("\n")) {
|
|
32667
33099
|
if (line.trim() === "")
|
|
32668
33100
|
continue;
|
|
32669
33101
|
try {
|
|
@@ -32679,7 +33111,7 @@ function readJson(path) {
|
|
|
32679
33111
|
if (!existsSync71(path))
|
|
32680
33112
|
return null;
|
|
32681
33113
|
try {
|
|
32682
|
-
const parsed = JSON.parse(
|
|
33114
|
+
const parsed = JSON.parse(readFileSync67(path, "utf8"));
|
|
32683
33115
|
return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : null;
|
|
32684
33116
|
} catch {
|
|
32685
33117
|
return null;
|
|
@@ -32742,7 +33174,7 @@ async function gatherAuditSnapshot(projectPath3, runtimeDir6, deps = {}) {
|
|
|
32742
33174
|
const skipped = [];
|
|
32743
33175
|
const backlogPath = join70(projectPath3, ".roll", "backlog.md");
|
|
32744
33176
|
if (existsSync71(backlogPath)) {
|
|
32745
|
-
snapshot.backlog = parseBacklog(
|
|
33177
|
+
snapshot.backlog = parseBacklog(readFileSync67(backlogPath, "utf8")).map((r) => ({ id: r.id, status: r.status }));
|
|
32746
33178
|
}
|
|
32747
33179
|
snapshot.index = readIndex(projectPath3);
|
|
32748
33180
|
snapshot.localMainAhead = deps.localMainAhead !== void 0 ? await deps.localMainAhead() : await gitLocalMainAhead(projectPath3);
|
|
@@ -32751,7 +33183,7 @@ async function gatherAuditSnapshot(projectPath3, runtimeDir6, deps = {}) {
|
|
|
32751
33183
|
const terminal = [];
|
|
32752
33184
|
const eventsPath2 = join70(runtimeDir6, "events.ndjson");
|
|
32753
33185
|
if (existsSync71(eventsPath2)) {
|
|
32754
|
-
for (const line of
|
|
33186
|
+
for (const line of readFileSync67(eventsPath2, "utf8").split("\n")) {
|
|
32755
33187
|
const e = parseEventLine(line);
|
|
32756
33188
|
if (e === null)
|
|
32757
33189
|
continue;
|
|
@@ -32916,7 +33348,7 @@ function escapeRegExp3(s) {
|
|
|
32916
33348
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
32917
33349
|
}
|
|
32918
33350
|
function readText(p) {
|
|
32919
|
-
return
|
|
33351
|
+
return readFileSync68(p, "utf8");
|
|
32920
33352
|
}
|
|
32921
33353
|
var COMMAND_SURFACE_REPLACEMENTS = /* @__PURE__ */ new Map([
|
|
32922
33354
|
["migrate", "npx @seanyao/roll@2 migrate"],
|
|
@@ -33651,7 +34083,7 @@ function realReleaseDeps() {
|
|
|
33651
34083
|
return {
|
|
33652
34084
|
version: (cwd) => {
|
|
33653
34085
|
try {
|
|
33654
|
-
const pkg = JSON.parse(
|
|
34086
|
+
const pkg = JSON.parse(readFileSync70(join73(cwd, "package.json"), "utf8"));
|
|
33655
34087
|
return typeof pkg.version === "string" ? pkg.version : "";
|
|
33656
34088
|
} catch {
|
|
33657
34089
|
return "";
|
|
@@ -33686,11 +34118,11 @@ function realReleaseDeps() {
|
|
|
33686
34118
|
return true;
|
|
33687
34119
|
}
|
|
33688
34120
|
},
|
|
33689
|
-
readChangelog: (cwd) =>
|
|
34121
|
+
readChangelog: (cwd) => readFileSync70(join73(cwd, "CHANGELOG.md"), "utf8"),
|
|
33690
34122
|
writeChangelog: (cwd, text) => writeFileSync41(join73(cwd, "CHANGELOG.md"), text, "utf8"),
|
|
33691
34123
|
bumpVersion: (cwd, version) => {
|
|
33692
34124
|
const path = join73(cwd, "package.json");
|
|
33693
|
-
const pkg = JSON.parse(
|
|
34125
|
+
const pkg = JSON.parse(readFileSync70(path, "utf8"));
|
|
33694
34126
|
pkg["version"] = version;
|
|
33695
34127
|
writeFileSync41(path, `${JSON.stringify(pkg, null, 2)}
|
|
33696
34128
|
`, "utf8");
|
|
@@ -33998,7 +34430,7 @@ async function selfScoreCommand(args) {
|
|
|
33998
34430
|
// packages/cli/dist/commands/setup.js
|
|
33999
34431
|
init_dist();
|
|
34000
34432
|
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
34001
|
-
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";
|
|
34002
34434
|
import { join as join74 } from "node:path";
|
|
34003
34435
|
function err13(line) {
|
|
34004
34436
|
const noColor2 = (process.env["NO_COLOR"] ?? "") !== "";
|
|
@@ -34072,7 +34504,7 @@ function walk(dir, lines2) {
|
|
|
34072
34504
|
}
|
|
34073
34505
|
function fileFingerprint(p) {
|
|
34074
34506
|
try {
|
|
34075
|
-
const buf =
|
|
34507
|
+
const buf = readFileSync71(p);
|
|
34076
34508
|
let sum = 0;
|
|
34077
34509
|
for (let i = 0; i < buf.length; i++)
|
|
34078
34510
|
sum = sum * 31 + (buf[i] ?? 0) >>> 0;
|
|
@@ -34266,7 +34698,7 @@ init_showcase2();
|
|
|
34266
34698
|
|
|
34267
34699
|
// packages/cli/dist/commands/test.js
|
|
34268
34700
|
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
34269
|
-
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";
|
|
34270
34702
|
import { dirname as dirname32, join as join75, resolve as resolve4 } from "node:path";
|
|
34271
34703
|
function pal7() {
|
|
34272
34704
|
const noColor2 = (process.env["NO_COLOR"] ?? "") !== "";
|
|
@@ -34349,7 +34781,7 @@ function isolationGetType() {
|
|
|
34349
34781
|
return "none";
|
|
34350
34782
|
let text;
|
|
34351
34783
|
try {
|
|
34352
|
-
text =
|
|
34784
|
+
text = readFileSync72(file, "utf8");
|
|
34353
34785
|
} catch {
|
|
34354
34786
|
return "none";
|
|
34355
34787
|
}
|
|
@@ -34540,7 +34972,7 @@ function testCommand(args) {
|
|
|
34540
34972
|
|
|
34541
34973
|
// packages/cli/dist/commands/tune.js
|
|
34542
34974
|
init_dist2();
|
|
34543
|
-
import { existsSync as existsSync77, readFileSync as
|
|
34975
|
+
import { existsSync as existsSync77, readFileSync as readFileSync73 } from "node:fs";
|
|
34544
34976
|
import { join as join76 } from "node:path";
|
|
34545
34977
|
function projectPath2() {
|
|
34546
34978
|
return (process.env["ROLL_MAIN_PROJECT"] ?? "").trim() || process.cwd();
|
|
@@ -34553,7 +34985,7 @@ function parseJsonl(path) {
|
|
|
34553
34985
|
return [];
|
|
34554
34986
|
let text;
|
|
34555
34987
|
try {
|
|
34556
|
-
text =
|
|
34988
|
+
text = readFileSync73(path, "utf8");
|
|
34557
34989
|
} catch {
|
|
34558
34990
|
return [];
|
|
34559
34991
|
}
|
|
@@ -34725,7 +35157,7 @@ function tuneCommand(argv) {
|
|
|
34725
35157
|
// packages/cli/dist/commands/update.js
|
|
34726
35158
|
init_dist();
|
|
34727
35159
|
import { spawnSync as spawnSync11 } from "node:child_process";
|
|
34728
|
-
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";
|
|
34729
35161
|
import { tmpdir as tmpdir8 } from "node:os";
|
|
34730
35162
|
import { join as join77 } from "node:path";
|
|
34731
35163
|
function pal8() {
|
|
@@ -34846,7 +35278,7 @@ function showChangelog() {
|
|
|
34846
35278
|
`);
|
|
34847
35279
|
let count = 0;
|
|
34848
35280
|
let inSection = false;
|
|
34849
|
-
for (const line of
|
|
35281
|
+
for (const line of readFileSync74(changelog, "utf8").split("\n")) {
|
|
34850
35282
|
if (/^## /.test(line)) {
|
|
34851
35283
|
count += 1;
|
|
34852
35284
|
if (count > 3)
|
|
@@ -34871,7 +35303,7 @@ function updateCommand(args) {
|
|
|
34871
35303
|
let installMethod = "npm";
|
|
34872
35304
|
const methodFile = join77(rollPkgDir(), ".install-method");
|
|
34873
35305
|
if (existsSync78(methodFile)) {
|
|
34874
|
-
installMethod =
|
|
35306
|
+
installMethod = readFileSync74(methodFile, "utf8").trim() || "npm";
|
|
34875
35307
|
}
|
|
34876
35308
|
if (installMethod === "curl") {
|
|
34877
35309
|
info5(m6("update.upgrading_via_curl"));
|