@seanyao/roll 4.630.1 → 4.630.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/README.md +1 -0
- package/dist/roll.mjs +902 -748
- package/package.json +1 -1
package/dist/roll.mjs
CHANGED
|
@@ -4926,11 +4926,12 @@ function selectPairingCandidates(input) {
|
|
|
4926
4926
|
const allowedSet = input.allowedAgents === void 0 ? void 0 : new Set([...input.allowedAgents].map(canonicalAgentName));
|
|
4927
4927
|
const basePool = installed.map(canonicalAgentName).filter((a, i, arr2) => arr2.indexOf(a) === i).filter((a) => agentIsKnown(a)).filter((a) => allowedSet === void 0 || allowedSet.has(a)).sort((x, y) => (order.get(x) ?? 999) - (order.get(y) ?? 999));
|
|
4928
4928
|
if (stage === "score") {
|
|
4929
|
-
const
|
|
4930
|
-
|
|
4929
|
+
const builderIsSoleInstalledAgent = working !== "" && basePool.every((a) => a === working);
|
|
4930
|
+
const eligible = basePool.filter((a) => isAvailable(a) && (builderIsSoleInstalledAgent || a !== working));
|
|
4931
|
+
if (eligible.length === 0)
|
|
4931
4932
|
return [];
|
|
4932
|
-
const hetero =
|
|
4933
|
-
const sameVendor =
|
|
4933
|
+
const hetero = eligible.filter((a) => working !== "" && isHeterogeneous(a, working));
|
|
4934
|
+
const sameVendor = eligible.filter((a) => working === "" || !isHeterogeneous(a, working));
|
|
4934
4935
|
const rotate = (pool) => {
|
|
4935
4936
|
if (pool.length === 0)
|
|
4936
4937
|
return pool;
|
|
@@ -9179,7 +9180,8 @@ function blockingDetails(input) {
|
|
|
9179
9180
|
return {
|
|
9180
9181
|
deliveredSet: buildDoneSet(input),
|
|
9181
9182
|
openPrSet: new Set(input.openPrStories),
|
|
9182
|
-
stuckSet: new Set(input.recentFailures.filter((f) => f.consecutiveFailures >= 2).map((f) => f.storyId))
|
|
9183
|
+
stuckSet: new Set(input.recentFailures.filter((f) => f.consecutiveFailures >= 2).map((f) => f.storyId)),
|
|
9184
|
+
pendingPublishSet: new Set(input.pendingPublish ?? [])
|
|
9183
9185
|
};
|
|
9184
9186
|
}
|
|
9185
9187
|
function buildSupervisorRunbookState(input) {
|
|
@@ -9189,7 +9191,7 @@ function buildSupervisorRunbookState(input) {
|
|
|
9189
9191
|
const blockedCards = [];
|
|
9190
9192
|
const manualMergeGates = input.manualMergeGates ?? [];
|
|
9191
9193
|
const structuralFailures = input.structuralFailures ?? [];
|
|
9192
|
-
const { deliveredSet, openPrSet, stuckSet } = blockingDetails(input);
|
|
9194
|
+
const { deliveredSet, openPrSet, stuckSet, pendingPublishSet } = blockingDetails(input);
|
|
9193
9195
|
const confirmedDelivered = new Set(input.delivered);
|
|
9194
9196
|
const truthDrift = input.backlog.filter((row2) => statusOf(row2.status) === "done" && !confirmedDelivered.has(row2.id)).map((row2) => row2.id);
|
|
9195
9197
|
const liveScopeIds = /* @__PURE__ */ new Set();
|
|
@@ -9326,6 +9328,10 @@ function buildSupervisorRunbookState(input) {
|
|
|
9326
9328
|
blockedCards.push(blocker(row2.id, "repeated_failure", "repeated failure must be diagnosed before retry"));
|
|
9327
9329
|
continue;
|
|
9328
9330
|
}
|
|
9331
|
+
if (pendingPublishSet.has(row2.id)) {
|
|
9332
|
+
blockedCards.push(blocker(row2.id, "pending_publish", "locally-committed work failed to publish; clear the publish blocker or run a scoped retry"));
|
|
9333
|
+
continue;
|
|
9334
|
+
}
|
|
9329
9335
|
return {
|
|
9330
9336
|
scope: { label: "live non-Hold FIX/US/REFACTOR", families: SUPERVISOR_FAMILIES, remainingByFamily, todoByFamily, excluded },
|
|
9331
9337
|
truth: {
|
|
@@ -231360,8 +231366,8 @@ __export(structure_scan_exports, {
|
|
|
231360
231366
|
scanDreamStructure: () => scanDreamStructure
|
|
231361
231367
|
});
|
|
231362
231368
|
import { createHash as createHash5 } from "node:crypto";
|
|
231363
|
-
import { existsSync as
|
|
231364
|
-
import { basename as basename14, dirname as
|
|
231369
|
+
import { existsSync as existsSync65, readFileSync as readFileSync61 } from "node:fs";
|
|
231370
|
+
import { basename as basename14, dirname as dirname33, extname, join as join67, relative as relative5, resolve as resolve5, sep as sep4 } from "node:path";
|
|
231365
231371
|
function buildStaticProjectGraph(input) {
|
|
231366
231372
|
const root = resolve5(input.root);
|
|
231367
231373
|
const tsconfigPaths = input.tsconfigPath ? [resolve5(root, input.tsconfigPath)] : findTsconfigs(root);
|
|
@@ -231377,7 +231383,7 @@ function buildStaticProjectGraph(input) {
|
|
|
231377
231383
|
diagnostics.push(flattenDiagnostic(config.error));
|
|
231378
231384
|
continue;
|
|
231379
231385
|
}
|
|
231380
|
-
const parsed = ts.parseJsonConfigFileContent(config.config, ts.sys,
|
|
231386
|
+
const parsed = ts.parseJsonConfigFileContent(config.config, ts.sys, dirname33(tsconfigPath));
|
|
231381
231387
|
diagnostics.push(...parsed.errors.map(flattenDiagnostic));
|
|
231382
231388
|
compilerOptions = { ...compilerOptions, ...parsed.options };
|
|
231383
231389
|
for (const fileName of parsed.fileNames)
|
|
@@ -231486,10 +231492,10 @@ function emptyGraph(root, error) {
|
|
|
231486
231492
|
};
|
|
231487
231493
|
}
|
|
231488
231494
|
function findTsconfigs(root) {
|
|
231489
|
-
const direct =
|
|
231490
|
-
if (
|
|
231495
|
+
const direct = join67(root, "tsconfig.json");
|
|
231496
|
+
if (existsSync65(direct))
|
|
231491
231497
|
return [direct];
|
|
231492
|
-
return ["packages/spec/tsconfig.json", "packages/core/tsconfig.json", "packages/infra/tsconfig.json", "packages/cli/tsconfig.json"].map((candidate) =>
|
|
231498
|
+
return ["packages/spec/tsconfig.json", "packages/core/tsconfig.json", "packages/infra/tsconfig.json", "packages/cli/tsconfig.json"].map((candidate) => join67(root, candidate)).filter((path) => existsSync65(path));
|
|
231493
231499
|
}
|
|
231494
231500
|
function createLanguageServiceHost(fileNames, options) {
|
|
231495
231501
|
return {
|
|
@@ -231497,9 +231503,9 @@ function createLanguageServiceHost(fileNames, options) {
|
|
|
231497
231503
|
getScriptFileNames: () => [...fileNames],
|
|
231498
231504
|
getScriptVersion: () => "0",
|
|
231499
231505
|
getScriptSnapshot: (fileName) => {
|
|
231500
|
-
if (!
|
|
231506
|
+
if (!existsSync65(fileName))
|
|
231501
231507
|
return void 0;
|
|
231502
|
-
return ts.ScriptSnapshot.fromString(
|
|
231508
|
+
return ts.ScriptSnapshot.fromString(readFileSync61(fileName, "utf8"));
|
|
231503
231509
|
},
|
|
231504
231510
|
getCurrentDirectory: () => process.cwd(),
|
|
231505
231511
|
getDefaultLibFileName: (opts) => ts.getDefaultLibFilePath(opts),
|
|
@@ -231625,10 +231631,10 @@ function importEdges(root, sourceFile) {
|
|
|
231625
231631
|
function resolveModulePath(root, containingFile, specifier) {
|
|
231626
231632
|
if (!specifier.startsWith("."))
|
|
231627
231633
|
return void 0;
|
|
231628
|
-
const base = resolve5(
|
|
231634
|
+
const base = resolve5(dirname33(containingFile), specifier);
|
|
231629
231635
|
for (const suffix of [".ts", ".tsx", ".mts", ".cts", "/index.ts"]) {
|
|
231630
231636
|
const candidate = `${base}${suffix}`;
|
|
231631
|
-
if (
|
|
231637
|
+
if (existsSync65(candidate))
|
|
231632
231638
|
return normalizePath(root, candidate);
|
|
231633
231639
|
}
|
|
231634
231640
|
return void 0;
|
|
@@ -231842,8 +231848,8 @@ function isProcessEnvExpression(node) {
|
|
|
231842
231848
|
}
|
|
231843
231849
|
function isEnvDocumented(root, name) {
|
|
231844
231850
|
for (const file of ["README.md", "docs/README.md", "docs/architecture.md"]) {
|
|
231845
|
-
const path =
|
|
231846
|
-
if (
|
|
231851
|
+
const path = join67(root, file);
|
|
231852
|
+
if (existsSync65(path) && readFileSync61(path, "utf8").includes(name))
|
|
231847
231853
|
return true;
|
|
231848
231854
|
}
|
|
231849
231855
|
return false;
|
|
@@ -235447,8 +235453,11 @@ async function runScorePairing(projectDir, runtimeDir9, cycleId, workingAgent, s
|
|
|
235447
235453
|
// FIX-935: respect project-config agent allowlist.
|
|
235448
235454
|
...selectionAllowedAgents !== void 0 ? { allowedAgents: selectionAllowedAgents } : {}
|
|
235449
235455
|
});
|
|
235450
|
-
|
|
235451
|
-
|
|
235456
|
+
const builderCanonical = canonicalAgentName(workingAgent);
|
|
235457
|
+
const escalationAllowedSet = selectionAllowedAgents === void 0 ? void 0 : new Set([...selectionAllowedAgents].map(canonicalAgentName));
|
|
235458
|
+
const escalationUniverse = deps.installed.map(canonicalAgentName).filter((a, i, arr2) => arr2.indexOf(a) === i).filter((a) => agentIsKnown(a)).filter((a) => escalationAllowedSet === void 0 || escalationAllowedSet.has(a)).filter((a) => workingAgent.trim() === "" || a !== builderCanonical);
|
|
235459
|
+
if (candidates.length === 0 && escalationUniverse.length === 0) {
|
|
235460
|
+
deps.event({ type: "pair:none-available", cycleId, stage: scoreStage, reason: "no independent scorer available to spawn a fresh review session", ts: deps.now() });
|
|
235452
235461
|
return { status: "none-available" };
|
|
235453
235462
|
}
|
|
235454
235463
|
const timeoutMs = deps.timeoutMs ?? SCORE_TIMEOUT_MS;
|
|
@@ -235484,9 +235493,7 @@ async function runScorePairing(projectDir, runtimeDir9, cycleId, workingAgent, s
|
|
|
235484
235493
|
winner = await runRound(sameVendorPool, false);
|
|
235485
235494
|
if (winner === null) {
|
|
235486
235495
|
const triedPeers = new Set([...heteroPool, ...sameVendorPool].map(canonicalAgentName));
|
|
235487
|
-
const
|
|
235488
|
-
const allKnown = deps.installed.map(canonicalAgentName).filter((a, i, arr2) => arr2.indexOf(a) === i).filter((a) => agentIsKnown(a)).filter((a) => allowedSet === void 0 || allowedSet.has(a));
|
|
235489
|
-
const escalationPool = allKnown.filter((a) => !triedPeers.has(a));
|
|
235496
|
+
const escalationPool = escalationUniverse.filter((a) => !triedPeers.has(a));
|
|
235490
235497
|
if (escalationPool.length > 0) {
|
|
235491
235498
|
const ESCALATION_MAX_ROUNDS = 2;
|
|
235492
235499
|
const rounds = Math.min(ESCALATION_MAX_ROUNDS, escalationPool.length);
|
|
@@ -235526,11 +235533,50 @@ async function runScorePairing(projectDir, runtimeDir9, cycleId, workingAgent, s
|
|
|
235526
235533
|
return { status: "error" };
|
|
235527
235534
|
}
|
|
235528
235535
|
}
|
|
235536
|
+
var SCORE_ANSI_RE = /[\u001b\u009b][[\]()#;?]*(?:(?:(?:[a-zA-Z\d]*(?:;[a-zA-Z\d]*)*)?\u0007)|(?:(?:\d{1,4}(?:;\d{0,4})*)?[\dA-PR-TZcf-nq-uy=><~]))/g;
|
|
235537
|
+
function applyBackspaces(text2) {
|
|
235538
|
+
if (!text2.includes("\b"))
|
|
235539
|
+
return text2;
|
|
235540
|
+
const out3 = [];
|
|
235541
|
+
for (const ch of text2) {
|
|
235542
|
+
if (ch === "\b") {
|
|
235543
|
+
const last = out3[out3.length - 1];
|
|
235544
|
+
if (last !== void 0 && last !== "\n" && last !== "\r")
|
|
235545
|
+
out3.pop();
|
|
235546
|
+
} else {
|
|
235547
|
+
out3.push(ch);
|
|
235548
|
+
}
|
|
235549
|
+
}
|
|
235550
|
+
return out3.join("");
|
|
235551
|
+
}
|
|
235552
|
+
function unwrapJsonlResult(stdout) {
|
|
235553
|
+
let payload = null;
|
|
235554
|
+
for (const line of stdout.split(/\r?\n/)) {
|
|
235555
|
+
const t2 = line.trim();
|
|
235556
|
+
if (t2 === "" || t2[0] !== "{")
|
|
235557
|
+
continue;
|
|
235558
|
+
try {
|
|
235559
|
+
const obj = JSON.parse(t2);
|
|
235560
|
+
if (typeof obj.result === "string")
|
|
235561
|
+
payload = obj.result;
|
|
235562
|
+
} catch {
|
|
235563
|
+
}
|
|
235564
|
+
}
|
|
235565
|
+
return payload;
|
|
235566
|
+
}
|
|
235567
|
+
function normalizeScoreStdout(stdout) {
|
|
235568
|
+
const text2 = unwrapJsonlResult(stdout) ?? stdout;
|
|
235569
|
+
return applyBackspaces(text2).replace(SCORE_ANSI_RE, "").replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/g, "");
|
|
235570
|
+
}
|
|
235571
|
+
function stripScoreLineDecoration(line) {
|
|
235572
|
+
return line.replace(/^[\s>*#•‣◦⁃·▪⁃-]+/, "").replace(/[\s*]+$/, "");
|
|
235573
|
+
}
|
|
235529
235574
|
function parsePairScoreOutput(stdout) {
|
|
235530
|
-
const
|
|
235531
|
-
const
|
|
235532
|
-
const
|
|
235533
|
-
const
|
|
235575
|
+
const normalized = normalizeScoreStdout(stdout);
|
|
235576
|
+
const lines2 = normalized.split(/\r?\n/).map(stripScoreLineDecoration);
|
|
235577
|
+
const scoreLines = lines2.map((line, index) => ({ index, match: /^SCORE:\s*(\d{1,2})$/i.exec(line) })).filter((entry) => entry.match !== null);
|
|
235578
|
+
const verdictLines = lines2.map((line, index) => ({ index, match: /^VERDICT:\s*(good|ok|regression)$/i.exec(line) })).filter((entry) => entry.match !== null);
|
|
235579
|
+
const rationaleLines = lines2.map((line, index) => ({ index, match: /^RATIONALE:\s*(.+)$/i.exec(line) })).filter((entry) => entry.match !== null);
|
|
235534
235580
|
if (scoreLines.length !== 1 || verdictLines.length !== 1 || rationaleLines.length !== 1)
|
|
235535
235581
|
return null;
|
|
235536
235582
|
const sm = scoreLines[0];
|
|
@@ -235543,7 +235589,7 @@ function parsePairScoreOutput(stdout) {
|
|
|
235543
235589
|
const score = Number(sm.match[1]);
|
|
235544
235590
|
if (!Number.isInteger(score) || score < 1 || score > 10)
|
|
235545
235591
|
return null;
|
|
235546
|
-
const resize = parseResizeSignal(
|
|
235592
|
+
const resize = parseResizeSignal(normalized);
|
|
235547
235593
|
return {
|
|
235548
235594
|
score,
|
|
235549
235595
|
verdict: vm.match[1].toLowerCase(),
|
|
@@ -246266,8 +246312,8 @@ ${CYCLE_USAGE}
|
|
|
246266
246312
|
// packages/cli/dist/commands/supervisor.js
|
|
246267
246313
|
init_dist2();
|
|
246268
246314
|
import { execFileSync as execFileSync12 } from "node:child_process";
|
|
246269
|
-
import { existsSync as
|
|
246270
|
-
import { dirname as
|
|
246315
|
+
import { existsSync as existsSync48, mkdirSync as mkdirSync26, readFileSync as readFileSync45, statSync as statSync15, writeFileSync as writeFileSync25 } from "node:fs";
|
|
246316
|
+
import { dirname as dirname28, join as join51 } from "node:path";
|
|
246271
246317
|
|
|
246272
246318
|
// packages/cli/dist/lib/operating-mode.js
|
|
246273
246319
|
init_dist3();
|
|
@@ -247393,6 +247439,55 @@ async function loopPrInboxCommand(_args, deps = realDeps3()) {
|
|
|
247393
247439
|
return 0;
|
|
247394
247440
|
}
|
|
247395
247441
|
|
|
247442
|
+
// packages/cli/dist/runner/pending-publish.js
|
|
247443
|
+
import { existsSync as existsSync47, mkdirSync as mkdirSync25, readFileSync as readFileSync44, writeFileSync as writeFileSync24 } from "node:fs";
|
|
247444
|
+
import { dirname as dirname27, join as join50 } from "node:path";
|
|
247445
|
+
var FILENAME = "pending-publish.json";
|
|
247446
|
+
function pathFor(runtimeDir9) {
|
|
247447
|
+
return join50(runtimeDir9, FILENAME);
|
|
247448
|
+
}
|
|
247449
|
+
function readSet(runtimeDir9) {
|
|
247450
|
+
const path = pathFor(runtimeDir9);
|
|
247451
|
+
if (!existsSync47(path))
|
|
247452
|
+
return /* @__PURE__ */ new Set();
|
|
247453
|
+
try {
|
|
247454
|
+
const raw = JSON.parse(readFileSync44(path, "utf8"));
|
|
247455
|
+
if (Array.isArray(raw))
|
|
247456
|
+
return new Set(raw.filter((v) => typeof v === "string"));
|
|
247457
|
+
} catch {
|
|
247458
|
+
}
|
|
247459
|
+
return /* @__PURE__ */ new Set();
|
|
247460
|
+
}
|
|
247461
|
+
function writeSet(runtimeDir9, set) {
|
|
247462
|
+
const path = pathFor(runtimeDir9);
|
|
247463
|
+
mkdirSync25(dirname27(path), { recursive: true });
|
|
247464
|
+
const tmp = `${path}.tmp-${process.pid}`;
|
|
247465
|
+
writeFileSync24(tmp, JSON.stringify([...set].sort(), null, 2), "utf8");
|
|
247466
|
+
writeFileSync24(path, readFileSync44(tmp, "utf8"), "utf8");
|
|
247467
|
+
try {
|
|
247468
|
+
const { rmSync: rmSync21 } = __require("node:fs");
|
|
247469
|
+
rmSync21(tmp, { force: true });
|
|
247470
|
+
} catch {
|
|
247471
|
+
}
|
|
247472
|
+
}
|
|
247473
|
+
function readPendingPublish(runtimeDir9) {
|
|
247474
|
+
return readSet(runtimeDir9);
|
|
247475
|
+
}
|
|
247476
|
+
function addPendingPublish(runtimeDir9, storyId) {
|
|
247477
|
+
const set = readSet(runtimeDir9);
|
|
247478
|
+
if (set.has(storyId))
|
|
247479
|
+
return;
|
|
247480
|
+
set.add(storyId);
|
|
247481
|
+
writeSet(runtimeDir9, set);
|
|
247482
|
+
}
|
|
247483
|
+
function removePendingPublish(runtimeDir9, storyId) {
|
|
247484
|
+
const set = readSet(runtimeDir9);
|
|
247485
|
+
if (!set.has(storyId))
|
|
247486
|
+
return;
|
|
247487
|
+
set.delete(storyId);
|
|
247488
|
+
writeSet(runtimeDir9, set);
|
|
247489
|
+
}
|
|
247490
|
+
|
|
247396
247491
|
// packages/cli/dist/commands/supervisor.js
|
|
247397
247492
|
var EXEC_MAX_BUFFER_BYTES2 = 64 * 1024 * 1024;
|
|
247398
247493
|
var SUPERVISOR_USAGE = [
|
|
@@ -247418,14 +247513,14 @@ var nodeFreshnessPort = {
|
|
|
247418
247513
|
},
|
|
247419
247514
|
readText(absPath) {
|
|
247420
247515
|
try {
|
|
247421
|
-
return
|
|
247516
|
+
return readFileSync45(absPath, "utf8");
|
|
247422
247517
|
} catch {
|
|
247423
247518
|
return "";
|
|
247424
247519
|
}
|
|
247425
247520
|
},
|
|
247426
247521
|
writeText(absPath, text2) {
|
|
247427
|
-
|
|
247428
|
-
|
|
247522
|
+
mkdirSync26(dirname28(absPath), { recursive: true });
|
|
247523
|
+
writeFileSync25(absPath, text2, "utf8");
|
|
247429
247524
|
}
|
|
247430
247525
|
};
|
|
247431
247526
|
var quietExecPort = {
|
|
@@ -247452,8 +247547,8 @@ function summarizeList(items, limit = 5) {
|
|
|
247452
247547
|
return remaining > 0 ? `${shown}, \u2026 +${remaining} more` : shown;
|
|
247453
247548
|
}
|
|
247454
247549
|
function readRollMetaState(projectPath3) {
|
|
247455
|
-
const rollDir =
|
|
247456
|
-
if (!
|
|
247550
|
+
const rollDir = join51(projectPath3, ".roll");
|
|
247551
|
+
if (!existsSync48(rollDir))
|
|
247457
247552
|
return { state: "unknown", detail: ".roll directory is missing" };
|
|
247458
247553
|
const res = quietExecPort.run("git", ["-C", rollDir, "status", "--short"]);
|
|
247459
247554
|
if (res.code !== 0)
|
|
@@ -247551,14 +247646,14 @@ function readManualMergeGates(projectPath3, events, port = quietExecPort, knownS
|
|
|
247551
247646
|
return gates;
|
|
247552
247647
|
}
|
|
247553
247648
|
function gatherSupervisorInput(projectPath3) {
|
|
247554
|
-
const backlogPath =
|
|
247555
|
-
const backlog =
|
|
247556
|
-
const agentsPath =
|
|
247557
|
-
const routeConfigErrors =
|
|
247558
|
-
const eventsPath2 =
|
|
247649
|
+
const backlogPath = join51(projectPath3, ".roll", "backlog.md");
|
|
247650
|
+
const backlog = existsSync48(backlogPath) ? parseBacklog(readFileSync45(backlogPath, "utf8")).map((it) => ({ id: it.id, status: it.status, dependsOn: depsOf(it.desc) })) : [];
|
|
247651
|
+
const agentsPath = join51(projectPath3, ".roll", "agents.yaml");
|
|
247652
|
+
const routeConfigErrors = existsSync48(agentsPath) ? normalizeAgentConfig(readFileSync45(agentsPath, "utf8")).errors : [];
|
|
247653
|
+
const eventsPath2 = join51(projectPath3, ".roll", "loop", "events.ndjson");
|
|
247559
247654
|
let events = [];
|
|
247560
247655
|
try {
|
|
247561
|
-
if (
|
|
247656
|
+
if (existsSync48(eventsPath2))
|
|
247562
247657
|
events = new EventBus().readEvents(eventsPath2);
|
|
247563
247658
|
} catch {
|
|
247564
247659
|
events = [];
|
|
@@ -247620,7 +247715,10 @@ function gatherSupervisorInput(projectPath3) {
|
|
|
247620
247715
|
releaseBlockers: [],
|
|
247621
247716
|
rollMeta: readRollMetaState(projectPath3),
|
|
247622
247717
|
manualMergeGates: readManualMergeGates(projectPath3, events, quietExecPort, backlog.map((row2) => row2.id)),
|
|
247623
|
-
structuralFailures: [...structuralFailures.values()]
|
|
247718
|
+
structuralFailures: [...structuralFailures.values()],
|
|
247719
|
+
// FIX-1043 — surface the runner's pending-publish hold so supervisor
|
|
247720
|
+
// next/why agree with the picker's `all_pending_publish` idle.
|
|
247721
|
+
pendingPublish: [...readPendingPublish(join51(projectPath3, ".roll", "loop"))]
|
|
247624
247722
|
};
|
|
247625
247723
|
}
|
|
247626
247724
|
function remainingLine(input) {
|
|
@@ -247638,9 +247736,9 @@ function latestExecutionCast(projectPath3, events) {
|
|
|
247638
247736
|
return buildCycleRoleSummary({
|
|
247639
247737
|
cycleId: latest.cycleId,
|
|
247640
247738
|
events,
|
|
247641
|
-
eventsPath:
|
|
247642
|
-
peerDir:
|
|
247643
|
-
cycleLogDir:
|
|
247739
|
+
eventsPath: join51(projectPath3, ".roll", "loop", "events.ndjson"),
|
|
247740
|
+
peerDir: join51(projectPath3, ".roll", "loop", "peer"),
|
|
247741
|
+
cycleLogDir: join51(projectPath3, ".roll", "loop", "cycle-logs")
|
|
247644
247742
|
});
|
|
247645
247743
|
}
|
|
247646
247744
|
function latestCastSummary(events) {
|
|
@@ -247750,9 +247848,9 @@ function runbookWhy(state, facts) {
|
|
|
247750
247848
|
return state.next.reason;
|
|
247751
247849
|
}
|
|
247752
247850
|
function readSupervisorEvents(projectPath3) {
|
|
247753
|
-
const eventsPath2 =
|
|
247851
|
+
const eventsPath2 = join51(projectPath3, ".roll", "loop", "events.ndjson");
|
|
247754
247852
|
try {
|
|
247755
|
-
if (
|
|
247853
|
+
if (existsSync48(eventsPath2))
|
|
247756
247854
|
return new EventBus().readEvents(eventsPath2);
|
|
247757
247855
|
} catch {
|
|
247758
247856
|
return [];
|
|
@@ -247871,19 +247969,19 @@ function supervisorCommand(args) {
|
|
|
247871
247969
|
|
|
247872
247970
|
// packages/cli/dist/commands/ls.js
|
|
247873
247971
|
init_dist();
|
|
247874
|
-
import { existsSync as
|
|
247972
|
+
import { existsSync as existsSync50, readFileSync as readFileSync47 } from "node:fs";
|
|
247875
247973
|
|
|
247876
247974
|
// packages/cli/dist/lib/projects-registry.js
|
|
247877
247975
|
init_dist2();
|
|
247878
247976
|
import { execFileSync as execFileSync13 } from "node:child_process";
|
|
247879
|
-
import { existsSync as
|
|
247977
|
+
import { existsSync as existsSync49, mkdirSync as mkdirSync27, readFileSync as readFileSync46, renameSync as renameSync10, realpathSync as realpathSync7, writeFileSync as writeFileSync26 } from "node:fs";
|
|
247880
247978
|
import { homedir as homedir16 } from "node:os";
|
|
247881
|
-
import { basename as basename10, dirname as
|
|
247979
|
+
import { basename as basename10, dirname as dirname29, join as join52 } from "node:path";
|
|
247882
247980
|
function registryHome(home) {
|
|
247883
247981
|
return home ?? process.env["ROLL_HOME"] ?? homedir16();
|
|
247884
247982
|
}
|
|
247885
247983
|
function projectsRegistryPath(home) {
|
|
247886
|
-
return
|
|
247984
|
+
return join52(registryHome(home), ".roll", "projects.json");
|
|
247887
247985
|
}
|
|
247888
247986
|
function parseProjectsRegistry(text2) {
|
|
247889
247987
|
let raw;
|
|
@@ -247915,7 +248013,7 @@ function parseProjectsRegistry(text2) {
|
|
|
247915
248013
|
function collectProjectsRegistry(home) {
|
|
247916
248014
|
let text2;
|
|
247917
248015
|
try {
|
|
247918
|
-
text2 =
|
|
248016
|
+
text2 = readFileSync46(projectsRegistryPath(home), "utf8");
|
|
247919
248017
|
} catch {
|
|
247920
248018
|
return [];
|
|
247921
248019
|
}
|
|
@@ -247989,9 +248087,9 @@ function writeProjectRow(entry, home) {
|
|
|
247989
248087
|
const existing = collectProjectsRegistry(home);
|
|
247990
248088
|
const merged = upsertProjectRow(existing, entry);
|
|
247991
248089
|
try {
|
|
247992
|
-
|
|
248090
|
+
mkdirSync27(dirname29(path), { recursive: true });
|
|
247993
248091
|
const tmp = `${path}.${process.pid}.tmp`;
|
|
247994
|
-
|
|
248092
|
+
writeFileSync26(tmp, serializeProjectsRegistry(merged), "utf8");
|
|
247995
248093
|
renameSync10(tmp, path);
|
|
247996
248094
|
return merged;
|
|
247997
248095
|
} catch {
|
|
@@ -248019,7 +248117,7 @@ function statusLabel(status2, lang11) {
|
|
|
248019
248117
|
return lang11 === "zh" ? "\u7F3A\u5931" : "missing";
|
|
248020
248118
|
return lang11 === "zh" ? "\u8FC7\u671F" : "stale";
|
|
248021
248119
|
}
|
|
248022
|
-
function renderProjectsTable(rows, lang11, nowMs, staleMs, pathExists =
|
|
248120
|
+
function renderProjectsTable(rows, lang11, nowMs, staleMs, pathExists = existsSync50) {
|
|
248023
248121
|
if (rows.length === 0) {
|
|
248024
248122
|
return lang11 === "zh" ? "\u6CE8\u518C\u8868\u4E3A\u7A7A\uFF08\u8FD8\u6CA1\u6709\u9879\u76EE\u8DD1\u8FC7 roll index\uFF09\n\u2192 \u5728\u67D0\u4E2A\u9879\u76EE\u91CC\u8DD1 roll index \u4EE5\u767B\u8BB0\u5B83\n" : "registry is empty (no project has run roll index yet)\n\u2192 run roll index in a project to register it\n";
|
|
248025
248123
|
}
|
|
@@ -248094,7 +248192,7 @@ ${LS_USAGE}
|
|
|
248094
248192
|
if (args.includes("--json")) {
|
|
248095
248193
|
let text2;
|
|
248096
248194
|
try {
|
|
248097
|
-
text2 =
|
|
248195
|
+
text2 = readFileSync47(projectsRegistryPath(), "utf8");
|
|
248098
248196
|
} catch {
|
|
248099
248197
|
text2 = "[]\n";
|
|
248100
248198
|
}
|
|
@@ -248109,9 +248207,9 @@ ${LS_USAGE}
|
|
|
248109
248207
|
|
|
248110
248208
|
// packages/cli/dist/commands/loop-runs.js
|
|
248111
248209
|
init_dist();
|
|
248112
|
-
import { existsSync as
|
|
248210
|
+
import { existsSync as existsSync51, readFileSync as readFileSync48, readdirSync as readdirSync17 } from "node:fs";
|
|
248113
248211
|
import { homedir as homedir17, platform as platform2 } from "node:os";
|
|
248114
|
-
import { basename as basename11, join as
|
|
248212
|
+
import { basename as basename11, join as join53 } from "node:path";
|
|
248115
248213
|
function lang4() {
|
|
248116
248214
|
return resolveLang({
|
|
248117
248215
|
rollLang: process.env["ROLL_LANG"],
|
|
@@ -248125,13 +248223,13 @@ function msg4(key, ...args) {
|
|
|
248125
248223
|
function runsFile() {
|
|
248126
248224
|
const envRt = (process.env["ROLL_PROJECT_RUNTIME_DIR"] ?? "").trim();
|
|
248127
248225
|
if (envRt)
|
|
248128
|
-
return
|
|
248129
|
-
const sharedDefault =
|
|
248226
|
+
return join53(envRt, "runs.jsonl");
|
|
248227
|
+
const sharedDefault = join53(sharedRoot(), "loop", "runs.jsonl");
|
|
248130
248228
|
const override = (process.env["_LOOP_RUNS"] ?? "").trim();
|
|
248131
248229
|
if (override && override !== sharedDefault)
|
|
248132
248230
|
return override;
|
|
248133
248231
|
const proj = (process.env["ROLL_MAIN_PROJECT"] ?? "").trim() || process.cwd();
|
|
248134
|
-
return
|
|
248232
|
+
return join53(proj, ".roll", "loop", "runs.jsonl");
|
|
248135
248233
|
}
|
|
248136
248234
|
function parseRows(text2) {
|
|
248137
248235
|
const out3 = [];
|
|
@@ -248263,11 +248361,11 @@ function aggregateAllFiles() {
|
|
|
248263
248361
|
if (allDirs) {
|
|
248264
248362
|
for (const d of allDirs.split(":"))
|
|
248265
248363
|
if (d)
|
|
248266
|
-
candidates.push(
|
|
248364
|
+
candidates.push(join53(d, "runs.jsonl"));
|
|
248267
248365
|
} else if ((process.env["ROLL_PROJECT_RUNTIME_DIR"] ?? "").trim()) {
|
|
248268
|
-
candidates.push(
|
|
248366
|
+
candidates.push(join53(process.env["ROLL_PROJECT_RUNTIME_DIR"].trim(), "runs.jsonl"));
|
|
248269
248367
|
} else if (platform2() === "darwin") {
|
|
248270
|
-
const laDir = (process.env["_LAUNCHD_DIR"] ?? "").trim() ||
|
|
248368
|
+
const laDir = (process.env["_LAUNCHD_DIR"] ?? "").trim() || join53(homedir17(), "Library", "LaunchAgents");
|
|
248271
248369
|
let plists = [];
|
|
248272
248370
|
try {
|
|
248273
248371
|
plists = readdirSync17(laDir).filter((f) => f.startsWith("com.roll.loop.") && f.endsWith(".plist"));
|
|
@@ -248277,13 +248375,13 @@ function aggregateAllFiles() {
|
|
|
248277
248375
|
for (const pl of plists) {
|
|
248278
248376
|
let content;
|
|
248279
248377
|
try {
|
|
248280
|
-
content =
|
|
248378
|
+
content = readFileSync48(join53(laDir, pl), "utf8");
|
|
248281
248379
|
} catch {
|
|
248282
248380
|
continue;
|
|
248283
248381
|
}
|
|
248284
248382
|
const m7 = /<key>WorkingDirectory<\/key>\s*<string>([^<]*)<\/string>/.exec(content);
|
|
248285
248383
|
if (m7 && m7[1])
|
|
248286
|
-
candidates.push(
|
|
248384
|
+
candidates.push(join53(m7[1], ".roll", "loop", "runs.jsonl"));
|
|
248287
248385
|
}
|
|
248288
248386
|
}
|
|
248289
248387
|
candidates.push(runsFile());
|
|
@@ -248293,7 +248391,7 @@ function aggregateAllFiles() {
|
|
|
248293
248391
|
if (!f || seen.has(f))
|
|
248294
248392
|
continue;
|
|
248295
248393
|
try {
|
|
248296
|
-
if (!
|
|
248394
|
+
if (!existsSync51(f) || readFileSync48(f, "utf8").trim() === "")
|
|
248297
248395
|
continue;
|
|
248298
248396
|
} catch {
|
|
248299
248397
|
continue;
|
|
@@ -248307,7 +248405,7 @@ function aggregateAllRows() {
|
|
|
248307
248405
|
const rows = [];
|
|
248308
248406
|
for (const f of aggregateAllFiles()) {
|
|
248309
248407
|
try {
|
|
248310
|
-
rows.push(...parseRows(
|
|
248408
|
+
rows.push(...parseRows(readFileSync48(f, "utf8")));
|
|
248311
248409
|
} catch {
|
|
248312
248410
|
}
|
|
248313
248411
|
}
|
|
@@ -248323,13 +248421,13 @@ function aggregateAllRows() {
|
|
|
248323
248421
|
}
|
|
248324
248422
|
function runsDetail(cycleId) {
|
|
248325
248423
|
const src = runsFile();
|
|
248326
|
-
if (!
|
|
248424
|
+
if (!existsSync51(src)) {
|
|
248327
248425
|
process.stdout.write(msg4("loop.no_runs_jsonl_yet") + "\n");
|
|
248328
248426
|
return 0;
|
|
248329
248427
|
}
|
|
248330
248428
|
let rows;
|
|
248331
248429
|
try {
|
|
248332
|
-
rows = parseRows(
|
|
248430
|
+
rows = parseRows(readFileSync48(src, "utf8"));
|
|
248333
248431
|
} catch {
|
|
248334
248432
|
rows = [];
|
|
248335
248433
|
}
|
|
@@ -248386,12 +248484,12 @@ function loopRunsCommand(argv) {
|
|
|
248386
248484
|
rows = aggregateAllRows();
|
|
248387
248485
|
} else {
|
|
248388
248486
|
const src = runsFile();
|
|
248389
|
-
if (!
|
|
248487
|
+
if (!existsSync51(src) || readFileSync48(src, "utf8").trim() === "") {
|
|
248390
248488
|
process.stdout.write(msg4("loop.no_loop_runs_yet") + "\n");
|
|
248391
248489
|
return 0;
|
|
248392
248490
|
}
|
|
248393
248491
|
const slug2 = projectSlug2();
|
|
248394
|
-
rows = parseRows(
|
|
248492
|
+
rows = parseRows(readFileSync48(src, "utf8")).filter((r) => str3(r["project"]) === slug2);
|
|
248395
248493
|
}
|
|
248396
248494
|
if (rows.length === 0) {
|
|
248397
248495
|
process.stdout.write(msg4("loop.no_loop_runs_for_current_project") + "\n");
|
|
@@ -248400,10 +248498,10 @@ function loopRunsCommand(argv) {
|
|
|
248400
248498
|
const recent = [...rows].reverse().slice(0, n);
|
|
248401
248499
|
const proj = (process.env["ROLL_MAIN_PROJECT"] ?? "").trim() || process.cwd();
|
|
248402
248500
|
let backlogText = "";
|
|
248403
|
-
const blPath =
|
|
248404
|
-
if (
|
|
248501
|
+
const blPath = join53(proj, ".roll", "backlog.md");
|
|
248502
|
+
if (existsSync51(blPath)) {
|
|
248405
248503
|
try {
|
|
248406
|
-
backlogText =
|
|
248504
|
+
backlogText = readFileSync48(blPath, "utf8");
|
|
248407
248505
|
} catch {
|
|
248408
248506
|
backlogText = "";
|
|
248409
248507
|
}
|
|
@@ -248416,8 +248514,8 @@ function loopRunsCommand(argv) {
|
|
|
248416
248514
|
// packages/cli/dist/commands/loop-signals.js
|
|
248417
248515
|
init_dist2();
|
|
248418
248516
|
init_dist();
|
|
248419
|
-
import { appendFileSync as appendFileSync10, existsSync as
|
|
248420
|
-
import { dirname as
|
|
248517
|
+
import { appendFileSync as appendFileSync10, existsSync as existsSync52, mkdirSync as mkdirSync28, readFileSync as readFileSync49, writeFileSync as writeFileSync27 } from "node:fs";
|
|
248518
|
+
import { dirname as dirname30, join as join54 } from "node:path";
|
|
248421
248519
|
function lang5() {
|
|
248422
248520
|
return resolveLang({ rollLang: process.env["ROLL_LANG"], lcAll: process.env["LC_ALL"], lang: process.env["LANG"] });
|
|
248423
248521
|
}
|
|
@@ -248449,14 +248547,14 @@ function loopSignalsCommand(argv) {
|
|
|
248449
248547
|
process.stdout.write(s + "\n");
|
|
248450
248548
|
};
|
|
248451
248549
|
const runsSrc = runsFile();
|
|
248452
|
-
if (!
|
|
248550
|
+
if (!existsSync52(runsSrc) || readFileSync49(runsSrc, "utf8").trim() === "") {
|
|
248453
248551
|
say(t(v2Catalog, lang5(), "loop.no_loop_runs_yet"));
|
|
248454
248552
|
return 0;
|
|
248455
248553
|
}
|
|
248456
248554
|
const projectPath3 = (process.env["ROLL_MAIN_PROJECT"] ?? "").trim() || process.cwd();
|
|
248457
248555
|
const slug2 = projectSlug2();
|
|
248458
248556
|
const records = [];
|
|
248459
|
-
for (const line of
|
|
248557
|
+
for (const line of readFileSync49(runsSrc, "utf8").split("\n")) {
|
|
248460
248558
|
if (line.trim() === "")
|
|
248461
248559
|
continue;
|
|
248462
248560
|
try {
|
|
@@ -248468,22 +248566,22 @@ function loopSignalsCommand(argv) {
|
|
|
248468
248566
|
}
|
|
248469
248567
|
}
|
|
248470
248568
|
const signals = detectSignals(records, streak);
|
|
248471
|
-
const rtDir = (process.env["_LOOP_RT_DIR"] ?? "").trim() ||
|
|
248472
|
-
const seenFile =
|
|
248473
|
-
const candFile =
|
|
248474
|
-
|
|
248475
|
-
|
|
248476
|
-
if (!
|
|
248477
|
-
|
|
248569
|
+
const rtDir = (process.env["_LOOP_RT_DIR"] ?? "").trim() || join54(projectPath3, ".roll", "loop");
|
|
248570
|
+
const seenFile = join54(rtDir, `signals-seen-${slug2}`);
|
|
248571
|
+
const candFile = join54(projectPath3, ".roll", "signals", "candidates.md");
|
|
248572
|
+
mkdirSync28(rtDir, { recursive: true });
|
|
248573
|
+
mkdirSync28(dirname30(candFile), { recursive: true });
|
|
248574
|
+
if (!existsSync52(seenFile))
|
|
248575
|
+
writeFileSync27(seenFile, "");
|
|
248478
248576
|
let lastId = 0;
|
|
248479
|
-
if (
|
|
248480
|
-
for (const m7 of
|
|
248577
|
+
if (existsSync52(candFile)) {
|
|
248578
|
+
for (const m7 of readFileSync49(candFile, "utf8").matchAll(/CAND-(\d+)/g)) {
|
|
248481
248579
|
const n = parseInt(m7[1] ?? "0", 10);
|
|
248482
248580
|
if (n > lastId)
|
|
248483
248581
|
lastId = n;
|
|
248484
248582
|
}
|
|
248485
248583
|
}
|
|
248486
|
-
const seen = new Set(
|
|
248584
|
+
const seen = new Set(existsSync52(seenFile) ? readFileSync49(seenFile, "utf8").split("\n").filter((l) => l !== "") : []);
|
|
248487
248585
|
let newCount = 0;
|
|
248488
248586
|
for (const sig of signals) {
|
|
248489
248587
|
if (seen.has(sig.key))
|
|
@@ -248530,8 +248628,8 @@ Options:
|
|
|
248530
248628
|
|
|
248531
248629
|
// packages/cli/dist/commands/loop-log.js
|
|
248532
248630
|
init_dist();
|
|
248533
|
-
import { existsSync as
|
|
248534
|
-
import { basename as basename12, join as
|
|
248631
|
+
import { existsSync as existsSync53, readFileSync as readFileSync50, readdirSync as readdirSync18 } from "node:fs";
|
|
248632
|
+
import { basename as basename12, join as join55 } from "node:path";
|
|
248535
248633
|
function lang6() {
|
|
248536
248634
|
return resolveLang({ rollLang: process.env["ROLL_LANG"], lcAll: process.env["LC_ALL"], lang: process.env["LANG"] });
|
|
248537
248635
|
}
|
|
@@ -248547,7 +248645,7 @@ function showLog(file) {
|
|
|
248547
248645
|
const ts2 = m7 ? `${m7[1]}-${m7[2]}-${m7[3]} ${m7[4]}:${m7[5]}` : id;
|
|
248548
248646
|
let body = "";
|
|
248549
248647
|
try {
|
|
248550
|
-
body =
|
|
248648
|
+
body = readFileSync50(file, "utf8");
|
|
248551
248649
|
} catch {
|
|
248552
248650
|
body = "";
|
|
248553
248651
|
}
|
|
@@ -248562,9 +248660,9 @@ function logFiles(logsDir) {
|
|
|
248562
248660
|
}
|
|
248563
248661
|
}
|
|
248564
248662
|
function loopLogCommand(argv) {
|
|
248565
|
-
const logsDir =
|
|
248663
|
+
const logsDir = join55(projectPath(), ".roll", "cycle-logs");
|
|
248566
248664
|
const all = logFiles(logsDir);
|
|
248567
|
-
if (!
|
|
248665
|
+
if (!existsSync53(logsDir) || all.length === 0) {
|
|
248568
248666
|
process.stdout.write(msg5("loop.no_cycle_logs_found_run_roll") + "\n");
|
|
248569
248667
|
return 0;
|
|
248570
248668
|
}
|
|
@@ -248577,11 +248675,11 @@ function loopLogCommand(argv) {
|
|
|
248577
248675
|
process.stdout.write(msg5("loop.no_cycle_logs_found_run_roll_2") + "\n");
|
|
248578
248676
|
return 0;
|
|
248579
248677
|
}
|
|
248580
|
-
showLog(
|
|
248678
|
+
showLog(join55(logsDir, latest));
|
|
248581
248679
|
return 0;
|
|
248582
248680
|
}
|
|
248583
|
-
const exact =
|
|
248584
|
-
if (
|
|
248681
|
+
const exact = join55(logsDir, `${query}.log`);
|
|
248682
|
+
if (existsSync53(exact)) {
|
|
248585
248683
|
showLog(exact);
|
|
248586
248684
|
return 0;
|
|
248587
248685
|
}
|
|
@@ -248591,7 +248689,7 @@ function loopLogCommand(argv) {
|
|
|
248591
248689
|
return 1;
|
|
248592
248690
|
}
|
|
248593
248691
|
if (matches.length === 1) {
|
|
248594
|
-
showLog(
|
|
248692
|
+
showLog(join55(logsDir, matches[0]));
|
|
248595
248693
|
return 0;
|
|
248596
248694
|
}
|
|
248597
248695
|
process.stdout.write(msg5("loop.ambiguous_prefix_matches_logs", query, matches.length) + "\n");
|
|
@@ -248603,13 +248701,13 @@ function loopLogCommand(argv) {
|
|
|
248603
248701
|
|
|
248604
248702
|
// packages/cli/dist/commands/loop-goal.js
|
|
248605
248703
|
init_dist();
|
|
248606
|
-
import { existsSync as
|
|
248607
|
-
import { join as
|
|
248704
|
+
import { existsSync as existsSync54, readFileSync as readFileSync51 } from "node:fs";
|
|
248705
|
+
import { join as join56 } from "node:path";
|
|
248608
248706
|
function realDeps4() {
|
|
248609
248707
|
return { projectPath: () => process.cwd() };
|
|
248610
248708
|
}
|
|
248611
248709
|
function goalPath(projectPath3) {
|
|
248612
|
-
return
|
|
248710
|
+
return join56(projectPath3, ".roll", "loop", "goal.yaml");
|
|
248613
248711
|
}
|
|
248614
248712
|
function scopeLabel(scope) {
|
|
248615
248713
|
if (scope.kind === "all")
|
|
@@ -248668,14 +248766,14 @@ async function loopGoalCommand(args, deps = realDeps4()) {
|
|
|
248668
248766
|
}
|
|
248669
248767
|
const project = deps.projectPath();
|
|
248670
248768
|
const path = goalPath(project);
|
|
248671
|
-
if (!
|
|
248769
|
+
if (!existsSync54(path)) {
|
|
248672
248770
|
process.stdout.write(`No active goal \u2014 .roll/loop/goal.yaml not found
|
|
248673
248771
|
\u5F53\u524D\u6CA1\u6709 goal \u2014 \u672A\u627E\u5230 .roll/loop/goal.yaml
|
|
248674
248772
|
`);
|
|
248675
248773
|
return 0;
|
|
248676
248774
|
}
|
|
248677
248775
|
try {
|
|
248678
|
-
process.stdout.write(renderGoal(parseGoalYaml(
|
|
248776
|
+
process.stdout.write(renderGoal(parseGoalYaml(readFileSync51(path, "utf8"))));
|
|
248679
248777
|
return 0;
|
|
248680
248778
|
} catch (e) {
|
|
248681
248779
|
process.stderr.write(`[roll] goal.yaml invalid: ${e.message}
|
|
@@ -248689,8 +248787,8 @@ init_dist2();
|
|
|
248689
248787
|
init_dist();
|
|
248690
248788
|
init_dist3();
|
|
248691
248789
|
import { spawn as spawn7, spawnSync as spawnSync7 } from "node:child_process";
|
|
248692
|
-
import { appendFileSync as appendFileSync11, createReadStream, existsSync as
|
|
248693
|
-
import { dirname as
|
|
248790
|
+
import { appendFileSync as appendFileSync11, createReadStream, existsSync as existsSync56, mkdirSync as mkdirSync30, readFileSync as readFileSync53, renameSync as renameSync12, statSync as statSync17, writeFileSync as writeFileSync29 } from "node:fs";
|
|
248791
|
+
import { dirname as dirname32, join as join58 } from "node:path";
|
|
248694
248792
|
import { createInterface as createInterface3 } from "node:readline";
|
|
248695
248793
|
|
|
248696
248794
|
// packages/cli/dist/lib/goal-progress.js
|
|
@@ -248766,9 +248864,9 @@ function numberField(row2, field2) {
|
|
|
248766
248864
|
// packages/cli/dist/lib/external-tools.js
|
|
248767
248865
|
init_dist3();
|
|
248768
248866
|
import { execFileSync as execFileSync14, spawnSync as spawnSync6 } from "node:child_process";
|
|
248769
|
-
import { accessSync as accessSync2, constants as constants2, existsSync as
|
|
248867
|
+
import { accessSync as accessSync2, constants as constants2, existsSync as existsSync55, mkdirSync as mkdirSync29, mkdtempSync as mkdtempSync3, readFileSync as readFileSync52, readdirSync as readdirSync19, readSync, renameSync as renameSync11, rmSync as rmSync12, statSync as statSync16, writeFileSync as writeFileSync28 } from "node:fs";
|
|
248770
248868
|
import { homedir as homedir18, tmpdir as tmpdir5 } from "node:os";
|
|
248771
|
-
import { delimiter as delimiter2, dirname as
|
|
248869
|
+
import { delimiter as delimiter2, dirname as dirname31, join as join57 } from "node:path";
|
|
248772
248870
|
var EXTERNAL_REQUIREMENT_DECLARATIONS = [
|
|
248773
248871
|
{
|
|
248774
248872
|
id: "screencapture",
|
|
@@ -248813,7 +248911,7 @@ function defaultExternalToolDeps() {
|
|
|
248813
248911
|
return [];
|
|
248814
248912
|
}
|
|
248815
248913
|
},
|
|
248816
|
-
exists:
|
|
248914
|
+
exists: existsSync55,
|
|
248817
248915
|
...platform3 === "darwin" && interactive && process.env["ROLL_NO_SCREENCAP"] !== "1" ? { hasAquaGUI: macosHasAquaGUI(execFile13) } : {},
|
|
248818
248916
|
cacheScreenRecording: true
|
|
248819
248917
|
};
|
|
@@ -248832,7 +248930,7 @@ function commandOnPath2(bin) {
|
|
|
248832
248930
|
for (const dir of (process.env["PATH"] ?? "").split(delimiter2)) {
|
|
248833
248931
|
if (dir === "")
|
|
248834
248932
|
continue;
|
|
248835
|
-
const p =
|
|
248933
|
+
const p = join57(dir, bin);
|
|
248836
248934
|
try {
|
|
248837
248935
|
accessSync2(p, constants2.X_OK);
|
|
248838
248936
|
return true;
|
|
@@ -248933,12 +249031,12 @@ function screenRecordingPreflight(deps = defaultExternalToolDeps()) {
|
|
|
248933
249031
|
cached: false
|
|
248934
249032
|
};
|
|
248935
249033
|
}
|
|
248936
|
-
const tmp =
|
|
249034
|
+
const tmp = join57(mkdtempSync3(join57(tmpdir5(), "roll-screen-probe-")), "probe.png");
|
|
248937
249035
|
const r = deps.execFile("screencapture", ["-x", "-R", "0,0,1,1", tmp]);
|
|
248938
249036
|
const capturedPixels = fileNonEmpty2(tmp);
|
|
248939
249037
|
try {
|
|
248940
249038
|
rmSync12(tmp, { force: true });
|
|
248941
|
-
rmSync12(
|
|
249039
|
+
rmSync12(dirname31(tmp), { recursive: true, force: true });
|
|
248942
249040
|
} catch {
|
|
248943
249041
|
}
|
|
248944
249042
|
if (r.code === 0 && capturedPixels) {
|
|
@@ -248997,13 +249095,13 @@ function fileNonEmpty2(path) {
|
|
|
248997
249095
|
}
|
|
248998
249096
|
}
|
|
248999
249097
|
function screenRecordingCachePath(deps) {
|
|
249000
|
-
const rollHome4 = (deps.env["ROLL_HOME"] ?? "").trim() ||
|
|
249001
|
-
return
|
|
249098
|
+
const rollHome4 = (deps.env["ROLL_HOME"] ?? "").trim() || join57(deps.home, ".roll");
|
|
249099
|
+
return join57(rollHome4, "cache", "terminal-screen-recording.json");
|
|
249002
249100
|
}
|
|
249003
249101
|
function readScreenRecordingCache(deps) {
|
|
249004
249102
|
const path = screenRecordingCachePath(deps);
|
|
249005
249103
|
try {
|
|
249006
|
-
const parsed = JSON.parse(
|
|
249104
|
+
const parsed = JSON.parse(readFileSync52(path, "utf8"));
|
|
249007
249105
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed))
|
|
249008
249106
|
return false;
|
|
249009
249107
|
const row2 = parsed;
|
|
@@ -249016,8 +249114,8 @@ function writeScreenRecordingCache(deps) {
|
|
|
249016
249114
|
const path = screenRecordingCachePath(deps);
|
|
249017
249115
|
const tmpPath = `${path}.${process.pid}.${Date.now()}.tmp`;
|
|
249018
249116
|
try {
|
|
249019
|
-
|
|
249020
|
-
|
|
249117
|
+
mkdirSync29(dirname31(path), { recursive: true });
|
|
249118
|
+
writeFileSync28(tmpPath, JSON.stringify({
|
|
249021
249119
|
version: 1,
|
|
249022
249120
|
platform: "darwin",
|
|
249023
249121
|
app: "Terminal.app",
|
|
@@ -249043,7 +249141,7 @@ function playwrightChromiumResolution(requirement, deps) {
|
|
|
249043
249141
|
}
|
|
249044
249142
|
const cache = deps.env["PLAYWRIGHT_BROWSERS_PATH"] ?? defaultPlaywrightBrowsersPath(deps);
|
|
249045
249143
|
const entries = deps.readDir(cache);
|
|
249046
|
-
const hasChromium = entries.some((name) => /^chromium(-|_headless_shell-|$)/.test(name) || /^chromium_headless_shell-/.test(name)) || deps.exists(
|
|
249144
|
+
const hasChromium = entries.some((name) => /^chromium(-|_headless_shell-|$)/.test(name) || /^chromium_headless_shell-/.test(name)) || deps.exists(join57(cache, "chromium"));
|
|
249047
249145
|
if (hasChromium) {
|
|
249048
249146
|
return { requirement, status: "ok", detail: `Chromium browser files found in ${cache} (playwright pinned v${PLAYWRIGHT_VERSION}).` };
|
|
249049
249147
|
}
|
|
@@ -249056,10 +249154,10 @@ function playwrightChromiumResolution(requirement, deps) {
|
|
|
249056
249154
|
}
|
|
249057
249155
|
function defaultPlaywrightBrowsersPath(deps) {
|
|
249058
249156
|
if (deps.platform === "darwin")
|
|
249059
|
-
return
|
|
249157
|
+
return join57(deps.home, "Library", "Caches", "ms-playwright");
|
|
249060
249158
|
if (deps.platform === "win32")
|
|
249061
|
-
return
|
|
249062
|
-
return
|
|
249159
|
+
return join57(deps.env["LOCALAPPDATA"] ?? join57(deps.home, "AppData", "Local"), "ms-playwright");
|
|
249160
|
+
return join57(deps.home, ".cache", "ms-playwright");
|
|
249063
249161
|
}
|
|
249064
249162
|
function renderExternalRequirementDoctorSection(states) {
|
|
249065
249163
|
const lines2 = ["", "External requirements", "\u5916\u90E8\u4F9D\u8D56", ""];
|
|
@@ -249175,14 +249273,14 @@ var nodeFreshnessPort2 = {
|
|
|
249175
249273
|
},
|
|
249176
249274
|
readText(absPath) {
|
|
249177
249275
|
try {
|
|
249178
|
-
return
|
|
249276
|
+
return readFileSync53(absPath, "utf8");
|
|
249179
249277
|
} catch {
|
|
249180
249278
|
return "";
|
|
249181
249279
|
}
|
|
249182
249280
|
},
|
|
249183
249281
|
writeText(absPath, text2) {
|
|
249184
|
-
|
|
249185
|
-
|
|
249282
|
+
mkdirSync30(dirname32(absPath), { recursive: true });
|
|
249283
|
+
writeFileSync29(absPath, text2, "utf8");
|
|
249186
249284
|
}
|
|
249187
249285
|
};
|
|
249188
249286
|
var GO_LOCK_STALE_SEC = 21600;
|
|
@@ -249263,22 +249361,22 @@ async function defaultPrEvidence(projectPath3, _storyId, backlogStatus) {
|
|
|
249263
249361
|
}
|
|
249264
249362
|
}
|
|
249265
249363
|
function runtimeDir5(projectPath3) {
|
|
249266
|
-
return
|
|
249364
|
+
return join58(projectPath3, ".roll", "loop");
|
|
249267
249365
|
}
|
|
249268
249366
|
function goalPath2(projectPath3) {
|
|
249269
|
-
return
|
|
249367
|
+
return join58(runtimeDir5(projectPath3), "goal.yaml");
|
|
249270
249368
|
}
|
|
249271
249369
|
function goLockPath(projectPath3) {
|
|
249272
|
-
return
|
|
249370
|
+
return join58(runtimeDir5(projectPath3), "go.lock");
|
|
249273
249371
|
}
|
|
249274
249372
|
function pauseMarkerPath2(projectPath3, slug2) {
|
|
249275
|
-
return
|
|
249373
|
+
return join58(runtimeDir5(projectPath3), `PAUSE-${slug2}`);
|
|
249276
249374
|
}
|
|
249277
249375
|
function eventsPath(projectPath3) {
|
|
249278
|
-
return
|
|
249376
|
+
return join58(runtimeDir5(projectPath3), "events.ndjson");
|
|
249279
249377
|
}
|
|
249280
249378
|
function runsPath2(projectPath3) {
|
|
249281
|
-
return
|
|
249379
|
+
return join58(runtimeDir5(projectPath3), "runs.jsonl");
|
|
249282
249380
|
}
|
|
249283
249381
|
function parseOptions2(args) {
|
|
249284
249382
|
let scope = { kind: "all" };
|
|
@@ -249552,15 +249650,15 @@ function realRunOnce(input) {
|
|
|
249552
249650
|
});
|
|
249553
249651
|
}
|
|
249554
249652
|
function writeGoal(path, goal) {
|
|
249555
|
-
|
|
249653
|
+
mkdirSync30(dirname32(path), { recursive: true });
|
|
249556
249654
|
const tmp = `${path}.tmp-${process.pid}`;
|
|
249557
|
-
|
|
249655
|
+
writeFileSync29(tmp, renderGoalYaml(goal), "utf8");
|
|
249558
249656
|
renameSync12(tmp, path);
|
|
249559
249657
|
}
|
|
249560
249658
|
function readGoal(path) {
|
|
249561
|
-
if (!
|
|
249659
|
+
if (!existsSync56(path))
|
|
249562
249660
|
return void 0;
|
|
249563
|
-
return parseGoalYaml(
|
|
249661
|
+
return parseGoalYaml(readFileSync53(path, "utf8"));
|
|
249564
249662
|
}
|
|
249565
249663
|
function createGoal(opts, at) {
|
|
249566
249664
|
return {
|
|
@@ -249583,7 +249681,7 @@ function summarizeRuns(path) {
|
|
|
249583
249681
|
function readRunSnapshot(path) {
|
|
249584
249682
|
let text2 = "";
|
|
249585
249683
|
try {
|
|
249586
|
-
text2 =
|
|
249684
|
+
text2 = readFileSync53(path, "utf8");
|
|
249587
249685
|
} catch {
|
|
249588
249686
|
return { rows: [], summary: { cycles: 0, costUsd: 0 } };
|
|
249589
249687
|
}
|
|
@@ -249612,7 +249710,7 @@ function readRunSnapshot(path) {
|
|
|
249612
249710
|
}
|
|
249613
249711
|
function readBacklogRows(projectPath3) {
|
|
249614
249712
|
try {
|
|
249615
|
-
return parseBacklog(
|
|
249713
|
+
return parseBacklog(readFileSync53(join58(projectPath3, ".roll", "backlog.md"), "utf8")).map((row2) => ({
|
|
249616
249714
|
id: row2.id,
|
|
249617
249715
|
status: row2.status
|
|
249618
249716
|
}));
|
|
@@ -249622,7 +249720,7 @@ function readBacklogRows(projectPath3) {
|
|
|
249622
249720
|
}
|
|
249623
249721
|
function readStoryIndex(projectPath3) {
|
|
249624
249722
|
try {
|
|
249625
|
-
const obj = JSON.parse(
|
|
249723
|
+
const obj = JSON.parse(readFileSync53(join58(projectPath3, ".roll", "index.json"), "utf8"));
|
|
249626
249724
|
if (typeof obj.stories !== "object" || obj.stories === null || Array.isArray(obj.stories))
|
|
249627
249725
|
return {};
|
|
249628
249726
|
const out3 = {};
|
|
@@ -249655,10 +249753,10 @@ function allScopeCardsSkipped(projectPath3, goal, progress) {
|
|
|
249655
249753
|
return rows.length > 0 && rows.every((row2) => progress.skippedCards.has(row2.id));
|
|
249656
249754
|
}
|
|
249657
249755
|
function readRunRows2(projectPath3) {
|
|
249658
|
-
const runsPath3 =
|
|
249756
|
+
const runsPath3 = join58(projectPath3, ".roll", "loop", "runs.jsonl");
|
|
249659
249757
|
let content = "";
|
|
249660
249758
|
try {
|
|
249661
|
-
content =
|
|
249759
|
+
content = readFileSync53(runsPath3, "utf8");
|
|
249662
249760
|
} catch {
|
|
249663
249761
|
return [];
|
|
249664
249762
|
}
|
|
@@ -249691,11 +249789,11 @@ function allScopeCardsSettled(projectPath3, goal, progress) {
|
|
|
249691
249789
|
return rows.every((row2) => progress.skippedCards.has(row2.id) || progress.deliveredCards.has(row2.id));
|
|
249692
249790
|
}
|
|
249693
249791
|
function alertPath3(projectPath3, slug2) {
|
|
249694
|
-
return
|
|
249792
|
+
return join58(runtimeDir5(projectPath3), `ALERT-${slug2}.md`);
|
|
249695
249793
|
}
|
|
249696
249794
|
function appendGoalAlert(projectPath3, slug2, storyId, cycleId, streak, at) {
|
|
249697
249795
|
const path = alertPath3(projectPath3, slug2);
|
|
249698
|
-
|
|
249796
|
+
mkdirSync30(dirname32(path), { recursive: true });
|
|
249699
249797
|
const cycleLine = cycleId === void 0 ? "" : ` cycle=${cycleId}`;
|
|
249700
249798
|
const verb = streak >= CARD_NO_PROGRESS_SKIP ? "skipped (no-progress streak)" : "no progress";
|
|
249701
249799
|
appendFileSync11(path, `[${at}] ALERT goal card ${verb}: ${storyId}${cycleLine} no_progress_cycles=${streak}
|
|
@@ -249703,13 +249801,13 @@ function appendGoalAlert(projectPath3, slug2, storyId, cycleId, streak, at) {
|
|
|
249703
249801
|
}
|
|
249704
249802
|
function appendBreakerAlert(projectPath3, slug2, cycles, at) {
|
|
249705
249803
|
const path = alertPath3(projectPath3, slug2);
|
|
249706
|
-
|
|
249804
|
+
mkdirSync30(dirname32(path), { recursive: true });
|
|
249707
249805
|
appendFileSync11(path, `[${at}] ALERT goal STOPPED: ${cycles} consecutive no-progress cycles (dead-loop breaker). Remediation: a card cannot be delivered by re-running \u2014 check the spec/dependencies, split or hold the card, then resume.
|
|
249708
249806
|
`, "utf8");
|
|
249709
249807
|
}
|
|
249710
249808
|
function appendReviewAlert(projectPath3, slug2, session, reason, at) {
|
|
249711
249809
|
const path = alertPath3(projectPath3, slug2);
|
|
249712
|
-
|
|
249810
|
+
mkdirSync30(dirname32(path), { recursive: true });
|
|
249713
249811
|
appendFileSync11(path, `[${at}] ALERT goal final review failed: session=${session} reason=${reason.replace(/\s+/g, " ").slice(0, 200)}
|
|
249714
249812
|
`, "utf8");
|
|
249715
249813
|
}
|
|
@@ -249798,7 +249896,7 @@ async function workerAgentsForSession(projectPath3, session) {
|
|
|
249798
249896
|
const out3 = [];
|
|
249799
249897
|
let inSession = false;
|
|
249800
249898
|
const path = eventsPath(projectPath3);
|
|
249801
|
-
if (!
|
|
249899
|
+
if (!existsSync56(path))
|
|
249802
249900
|
return out3;
|
|
249803
249901
|
const lines2 = createInterface3({ input: createReadStream(path, { encoding: "utf8" }), crlfDelay: Infinity });
|
|
249804
249902
|
try {
|
|
@@ -249867,7 +249965,7 @@ async function defaultFinalReview(input) {
|
|
|
249867
249965
|
};
|
|
249868
249966
|
}
|
|
249869
249967
|
function backlogExists(projectPath3) {
|
|
249870
|
-
return
|
|
249968
|
+
return existsSync56(join58(projectPath3, ".roll", "backlog.md"));
|
|
249871
249969
|
}
|
|
249872
249970
|
function reviewBlockReason(verdict, reason) {
|
|
249873
249971
|
return `final_review:${verdict.toLowerCase()}:${reason}`;
|
|
@@ -249902,9 +250000,9 @@ function writeFinalReviewNotes(projectPath3, goal, session, review, at) {
|
|
|
249902
250000
|
const fileName = `final-review-${safeNotePart(session)}.md`;
|
|
249903
250001
|
const body = finalReviewNoteBody(session, review, at);
|
|
249904
250002
|
for (const row2 of rowsForScope(projectPath3, goal.scope)) {
|
|
249905
|
-
const notesDir =
|
|
249906
|
-
|
|
249907
|
-
|
|
250003
|
+
const notesDir = join58(cardArchiveDir(projectPath3, row2.id), "notes");
|
|
250004
|
+
mkdirSync30(notesDir, { recursive: true });
|
|
250005
|
+
writeFileSync29(join58(notesDir, fileName), body, "utf8");
|
|
249908
250006
|
}
|
|
249909
250007
|
}
|
|
249910
250008
|
async function runFinalReviewGate(projectPath3, slug2, goal, evaluation, deps, session, workerAgents, bus) {
|
|
@@ -250041,7 +250139,7 @@ async function evaluateGoal(projectPath3, slug2, goal, deps, session, workerAgen
|
|
|
250041
250139
|
function hasSafetyPauseSince(path, since) {
|
|
250042
250140
|
let text2 = "";
|
|
250043
250141
|
try {
|
|
250044
|
-
text2 =
|
|
250142
|
+
text2 = readFileSync53(path, "utf8");
|
|
250045
250143
|
} catch {
|
|
250046
250144
|
return false;
|
|
250047
250145
|
}
|
|
@@ -250158,9 +250256,9 @@ function applyRunOptions(goal, opts, at) {
|
|
|
250158
250256
|
function latestAlertSummary(projectPath3, slug2, sinceSec) {
|
|
250159
250257
|
const path = alertPath3(projectPath3, slug2);
|
|
250160
250258
|
try {
|
|
250161
|
-
if (!
|
|
250259
|
+
if (!existsSync56(path) || statSync17(path).mtimeMs / 1e3 < sinceSec)
|
|
250162
250260
|
return void 0;
|
|
250163
|
-
const lines2 =
|
|
250261
|
+
const lines2 = readFileSync53(path, "utf8").split("\n").map((line2) => line2.trim()).filter((line2) => line2 !== "");
|
|
250164
250262
|
const line = [...lines2].reverse().find((candidate) => /\b(ALERT|WARN|BLOCKED|refused|failed)\b/i.test(candidate));
|
|
250165
250263
|
if (line === void 0)
|
|
250166
250264
|
return void 0;
|
|
@@ -250174,9 +250272,9 @@ function noCycleTerminalReason(projectPath3, slug2, sinceSec) {
|
|
|
250174
250272
|
return alert === void 0 ? "no_cycle_terminal" : `no_cycle_terminal: ${alert}`;
|
|
250175
250273
|
}
|
|
250176
250274
|
function innerLockHolder(projectPath3, nowSec2) {
|
|
250177
|
-
const path =
|
|
250275
|
+
const path = join58(runtimeDir5(projectPath3), "inner.lock");
|
|
250178
250276
|
try {
|
|
250179
|
-
if (!
|
|
250277
|
+
if (!existsSync56(path))
|
|
250180
250278
|
return void 0;
|
|
250181
250279
|
const owner = readLockOwner(path);
|
|
250182
250280
|
return isOwnerHeld(owner, nowSec2, INNER_LOCK_STALE_SEC) ? owner?.pid : void 0;
|
|
@@ -250296,7 +250394,7 @@ async function loopGoCommand(args, deps = realDeps5()) {
|
|
|
250296
250394
|
}
|
|
250297
250395
|
async function runGoWorker(id, opts, deps) {
|
|
250298
250396
|
const rt = runtimeDir5(id.path);
|
|
250299
|
-
|
|
250397
|
+
mkdirSync30(rt, { recursive: true });
|
|
250300
250398
|
const bus = new EventBus();
|
|
250301
250399
|
const evPath = eventsPath(id.path);
|
|
250302
250400
|
const lockPath2 = goLockPath(id.path);
|
|
@@ -250361,7 +250459,7 @@ async function runGoWorker(id, opts, deps) {
|
|
|
250361
250459
|
while (true) {
|
|
250362
250460
|
if (stopRequested)
|
|
250363
250461
|
break;
|
|
250364
|
-
if (
|
|
250462
|
+
if (existsSync56(pauseMarkerPath2(id.path, id.slug))) {
|
|
250365
250463
|
stopReason = "pause_marker";
|
|
250366
250464
|
break;
|
|
250367
250465
|
}
|
|
@@ -250393,7 +250491,7 @@ async function runGoWorker(id, opts, deps) {
|
|
|
250393
250491
|
}
|
|
250394
250492
|
if (stopRequested)
|
|
250395
250493
|
break;
|
|
250396
|
-
if (
|
|
250494
|
+
if (existsSync56(pauseMarkerPath2(id.path, id.slug)))
|
|
250397
250495
|
continue;
|
|
250398
250496
|
const before = readRunSnapshot(runsPath2(id.path));
|
|
250399
250497
|
await deps.runOnce({ projectPath: id.path, allowedCards });
|
|
@@ -250446,7 +250544,7 @@ async function runGoWorker(id, opts, deps) {
|
|
|
250446
250544
|
stopReason = "safety_pause";
|
|
250447
250545
|
break;
|
|
250448
250546
|
}
|
|
250449
|
-
if (
|
|
250547
|
+
if (existsSync56(pauseMarkerPath2(id.path, id.slug))) {
|
|
250450
250548
|
stopReason = "pause_marker";
|
|
250451
250549
|
break;
|
|
250452
250550
|
}
|
|
@@ -250475,23 +250573,23 @@ async function runGoWorker(id, opts, deps) {
|
|
|
250475
250573
|
}
|
|
250476
250574
|
|
|
250477
250575
|
// packages/cli/dist/commands/loop-events.js
|
|
250478
|
-
import { existsSync as
|
|
250479
|
-
import { join as
|
|
250576
|
+
import { existsSync as existsSync57, readFileSync as readFileSync54 } from "node:fs";
|
|
250577
|
+
import { join as join59 } from "node:path";
|
|
250480
250578
|
function str4(v) {
|
|
250481
250579
|
return typeof v === "string" ? v : v === void 0 || v === null ? "" : String(v);
|
|
250482
250580
|
}
|
|
250483
250581
|
function loopEventsCommand(argv) {
|
|
250484
250582
|
const n = argv[0] !== void 0 && /^\d+$/.test(argv[0]) ? parseInt(argv[0], 10) : 20;
|
|
250485
250583
|
const slug2 = projectSlug2();
|
|
250486
|
-
const evfile =
|
|
250487
|
-
if (!
|
|
250584
|
+
const evfile = join59(sharedRoot(), "loop", `events-${slug2}.ndjson`);
|
|
250585
|
+
if (!existsSync57(evfile)) {
|
|
250488
250586
|
process.stdout.write(`[monitor] No event log found for project: ${slug2}
|
|
250489
250587
|
`);
|
|
250490
250588
|
return 1;
|
|
250491
250589
|
}
|
|
250492
250590
|
let lines2;
|
|
250493
250591
|
try {
|
|
250494
|
-
lines2 =
|
|
250592
|
+
lines2 = readFileSync54(evfile, "utf8").split("\n").filter((l) => l !== "");
|
|
250495
250593
|
} catch {
|
|
250496
250594
|
lines2 = [];
|
|
250497
250595
|
}
|
|
@@ -250530,24 +250628,24 @@ function loopBranchesRetired() {
|
|
|
250530
250628
|
init_dist2();
|
|
250531
250629
|
init_dist();
|
|
250532
250630
|
import { execFileSync as execFileSync16 } from "node:child_process";
|
|
250533
|
-
import { accessSync as accessSync3, constants as constants3, existsSync as
|
|
250631
|
+
import { accessSync as accessSync3, constants as constants3, existsSync as existsSync62, mkdtempSync as mkdtempSync5, readFileSync as readFileSync59, readdirSync as readdirSync24, statSync as statSync21, writeFileSync as writeFileSync31 } from "node:fs";
|
|
250534
250632
|
import { homedir as homedir19, tmpdir as tmpdir7 } from "node:os";
|
|
250535
|
-
import { delimiter as delimiter3, join as
|
|
250633
|
+
import { delimiter as delimiter3, join as join64 } from "node:path";
|
|
250536
250634
|
|
|
250537
250635
|
// packages/cli/dist/commands/skills.js
|
|
250538
250636
|
init_dist();
|
|
250539
250637
|
import { execFileSync as execFileSync15 } from "node:child_process";
|
|
250540
|
-
import { existsSync as
|
|
250638
|
+
import { existsSync as existsSync60, mkdtempSync as mkdtempSync4, readFileSync as readFileSync57, readdirSync as readdirSync22, statSync as statSync19, writeFileSync as writeFileSync30 } from "node:fs";
|
|
250541
250639
|
import { tmpdir as tmpdir6 } from "node:os";
|
|
250542
|
-
import { join as
|
|
250640
|
+
import { join as join62 } from "node:path";
|
|
250543
250641
|
|
|
250544
250642
|
// packages/cli/dist/lib/skills-panel.js
|
|
250545
|
-
import { existsSync as
|
|
250546
|
-
import { join as
|
|
250643
|
+
import { existsSync as existsSync59, readFileSync as readFileSync56, readdirSync as readdirSync21, statSync as statSync18 } from "node:fs";
|
|
250644
|
+
import { join as join61 } from "node:path";
|
|
250547
250645
|
|
|
250548
250646
|
// packages/cli/dist/lib/skills-audit.js
|
|
250549
|
-
import { existsSync as
|
|
250550
|
-
import { join as
|
|
250647
|
+
import { existsSync as existsSync58, readFileSync as readFileSync55, readdirSync as readdirSync20 } from "node:fs";
|
|
250648
|
+
import { join as join60, relative as relative4, sep as sep3 } from "node:path";
|
|
250551
250649
|
function stripYamlQuotes(value) {
|
|
250552
250650
|
const trimmed = value.trim();
|
|
250553
250651
|
if (trimmed.startsWith('"') && trimmed.endsWith('"') || trimmed.startsWith("'") && trimmed.endsWith("'")) {
|
|
@@ -250595,10 +250693,10 @@ function wordCount(text2) {
|
|
|
250595
250693
|
return text2.trim().split(/\s+/).filter(Boolean).length;
|
|
250596
250694
|
}
|
|
250597
250695
|
function walkFiles(dir) {
|
|
250598
|
-
if (!
|
|
250696
|
+
if (!existsSync58(dir))
|
|
250599
250697
|
return [];
|
|
250600
250698
|
return readdirSync20(dir, { withFileTypes: true }).flatMap((entry) => {
|
|
250601
|
-
const full =
|
|
250699
|
+
const full = join60(dir, entry.name);
|
|
250602
250700
|
if (entry.isDirectory())
|
|
250603
250701
|
return walkFiles(full);
|
|
250604
250702
|
if (entry.isFile())
|
|
@@ -250611,7 +250709,7 @@ function toPosix(relativePath2) {
|
|
|
250611
250709
|
}
|
|
250612
250710
|
var SPOKE_DIRS = ["references", "assets", "scripts"];
|
|
250613
250711
|
function collectSpokeFiles(skillDir) {
|
|
250614
|
-
return SPOKE_DIRS.flatMap((dirName) => walkFiles(
|
|
250712
|
+
return SPOKE_DIRS.flatMap((dirName) => walkFiles(join60(skillDir, dirName)).map((file) => toPosix(relative4(skillDir, file))));
|
|
250615
250713
|
}
|
|
250616
250714
|
function findDeadBashRefs(text2) {
|
|
250617
250715
|
const refs = [];
|
|
@@ -250633,7 +250731,7 @@ function collectDeadBashRefs(skillDir) {
|
|
|
250633
250731
|
const all = /* @__PURE__ */ new Set();
|
|
250634
250732
|
for (const file of walkFiles(skillDir).filter((f) => f.endsWith(".md"))) {
|
|
250635
250733
|
try {
|
|
250636
|
-
const text2 =
|
|
250734
|
+
const text2 = readFileSync55(file, "utf8");
|
|
250637
250735
|
for (const ref of findDeadBashRefs(text2))
|
|
250638
250736
|
all.add(ref);
|
|
250639
250737
|
} catch {
|
|
@@ -250656,9 +250754,9 @@ function collectReferencedSpokes(body) {
|
|
|
250656
250754
|
return [...refs].sort();
|
|
250657
250755
|
}
|
|
250658
250756
|
function parseSkillFile(file) {
|
|
250659
|
-
const text2 =
|
|
250757
|
+
const text2 = readFileSync55(file, "utf8");
|
|
250660
250758
|
const { fields: fields2, body, ok: ok12 } = parseFrontmatter(text2);
|
|
250661
|
-
const skillDir =
|
|
250759
|
+
const skillDir = join60(file, "..");
|
|
250662
250760
|
const description = fields2["description"] ?? "";
|
|
250663
250761
|
const spokeFiles = collectSpokeFiles(skillDir);
|
|
250664
250762
|
const referencedSpokes = collectReferencedSpokes(body);
|
|
@@ -250674,7 +250772,7 @@ function parseSkillFile(file) {
|
|
|
250674
250772
|
hasWhenNotToUse: /^##\s+When Not to Use\b/im.test(body),
|
|
250675
250773
|
hasGotchas: /^##\s+(Gotchas|Known Failure Modes)\b/im.test(body),
|
|
250676
250774
|
hasReviewedWaiver: /Reviewed Waiver:/i.test(body),
|
|
250677
|
-
auxiliaryDirs: SPOKE_DIRS.filter((dirName) =>
|
|
250775
|
+
auxiliaryDirs: SPOKE_DIRS.filter((dirName) => existsSync58(join60(skillDir, dirName))),
|
|
250678
250776
|
spokeFiles,
|
|
250679
250777
|
referencedSpokes,
|
|
250680
250778
|
missingSpokeRefs: referencedSpokes.filter((ref) => !spokeFiles.includes(ref)),
|
|
@@ -250683,15 +250781,15 @@ function parseSkillFile(file) {
|
|
|
250683
250781
|
};
|
|
250684
250782
|
}
|
|
250685
250783
|
function findSkillFiles(skillsDir2) {
|
|
250686
|
-
if (!
|
|
250784
|
+
if (!existsSync58(skillsDir2))
|
|
250687
250785
|
return [];
|
|
250688
|
-
return readdirSync20(skillsDir2, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) =>
|
|
250786
|
+
return readdirSync20(skillsDir2, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join60(skillsDir2, entry.name, "SKILL.md")).filter((file) => existsSync58(file)).sort();
|
|
250689
250787
|
}
|
|
250690
250788
|
function loadRouteCases(routeFile) {
|
|
250691
|
-
if (!
|
|
250789
|
+
if (!existsSync58(routeFile))
|
|
250692
250790
|
return { skills: {} };
|
|
250693
250791
|
try {
|
|
250694
|
-
return JSON.parse(
|
|
250792
|
+
return JSON.parse(readFileSync55(routeFile, "utf8"));
|
|
250695
250793
|
} catch {
|
|
250696
250794
|
return { skills: {} };
|
|
250697
250795
|
}
|
|
@@ -250725,7 +250823,7 @@ function violationsFor(skill, route) {
|
|
|
250725
250823
|
return violations;
|
|
250726
250824
|
}
|
|
250727
250825
|
function auditSkills(options) {
|
|
250728
|
-
const routeFile = options.routeFile ??
|
|
250826
|
+
const routeFile = options.routeFile ?? join60(options.skillsDir, "route-cases", "skills.json");
|
|
250729
250827
|
const routes = loadRouteCases(routeFile);
|
|
250730
250828
|
const skills = findSkillFiles(options.skillsDir).map((file) => {
|
|
250731
250829
|
const parsed = parseSkillFile(file);
|
|
@@ -250747,8 +250845,8 @@ function auditSkills(options) {
|
|
|
250747
250845
|
function defaultSkillsPanelDeps(projectPath3) {
|
|
250748
250846
|
return {
|
|
250749
250847
|
audit: () => {
|
|
250750
|
-
const skillsDir2 =
|
|
250751
|
-
if (!
|
|
250848
|
+
const skillsDir2 = join61(projectPath3, "skills");
|
|
250849
|
+
if (!existsSync59(skillsDir2))
|
|
250752
250850
|
return null;
|
|
250753
250851
|
try {
|
|
250754
250852
|
return auditSkills({ skillsDir: skillsDir2 });
|
|
@@ -250795,7 +250893,7 @@ function skillGroupOf(name) {
|
|
|
250795
250893
|
}
|
|
250796
250894
|
function lineCount(path) {
|
|
250797
250895
|
try {
|
|
250798
|
-
return
|
|
250896
|
+
return readFileSync56(path, "utf8").split("\n").length;
|
|
250799
250897
|
} catch {
|
|
250800
250898
|
return 0;
|
|
250801
250899
|
}
|
|
@@ -250805,18 +250903,18 @@ function skillFiles(dir) {
|
|
|
250805
250903
|
try {
|
|
250806
250904
|
for (const e of readdirSync21(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
250807
250905
|
if (e.isDirectory()) {
|
|
250808
|
-
const sub =
|
|
250906
|
+
const sub = join61(dir, e.name);
|
|
250809
250907
|
out3.push({ path: `${e.name}/`, lines: 0, dir: true });
|
|
250810
250908
|
try {
|
|
250811
250909
|
for (const f of readdirSync21(sub).sort()) {
|
|
250812
|
-
const p =
|
|
250910
|
+
const p = join61(sub, f);
|
|
250813
250911
|
if (statSync18(p).isFile())
|
|
250814
250912
|
out3.push({ path: `${e.name}/${f}`, lines: lineCount(p), dir: false });
|
|
250815
250913
|
}
|
|
250816
250914
|
} catch {
|
|
250817
250915
|
}
|
|
250818
250916
|
} else if (e.isFile()) {
|
|
250819
|
-
out3.push({ path: e.name, lines: lineCount(
|
|
250917
|
+
out3.push({ path: e.name, lines: lineCount(join61(dir, e.name)), dir: false });
|
|
250820
250918
|
}
|
|
250821
250919
|
}
|
|
250822
250920
|
} catch {
|
|
@@ -250825,10 +250923,10 @@ function skillFiles(dir) {
|
|
|
250825
250923
|
}
|
|
250826
250924
|
var GROUP_ORDER = ["delivery", "quality", "observe", "lifecycle"];
|
|
250827
250925
|
function skillsOnDisk(skillsRoot) {
|
|
250828
|
-
if (!
|
|
250926
|
+
if (!existsSync59(skillsRoot))
|
|
250829
250927
|
return [];
|
|
250830
250928
|
try {
|
|
250831
|
-
return readdirSync21(skillsRoot, { withFileTypes: true }).filter((e) => e.isDirectory() &&
|
|
250929
|
+
return readdirSync21(skillsRoot, { withFileTypes: true }).filter((e) => e.isDirectory() && existsSync59(join61(skillsRoot, e.name, "SKILL.md"))).map((e) => e.name).sort((a, b) => a.localeCompare(b));
|
|
250832
250930
|
} catch {
|
|
250833
250931
|
return [];
|
|
250834
250932
|
}
|
|
@@ -250837,13 +250935,13 @@ function collectSkillsPanel(projectPath3, deps = defaultSkillsPanelDeps(projectP
|
|
|
250837
250935
|
const audit = deps.audit();
|
|
250838
250936
|
const auditRan = audit !== null;
|
|
250839
250937
|
const usage5 = deps.usageCounts();
|
|
250840
|
-
const skillsRoot =
|
|
250938
|
+
const skillsRoot = join61(projectPath3, "skills");
|
|
250841
250939
|
const byName = /* @__PURE__ */ new Map();
|
|
250842
250940
|
for (const a of audit?.skills ?? [])
|
|
250843
250941
|
byName.set(a.name, a);
|
|
250844
250942
|
const rows = skillsOnDisk(skillsRoot).map((name) => {
|
|
250845
|
-
const dir =
|
|
250846
|
-
const hubPath =
|
|
250943
|
+
const dir = join61(skillsRoot, name);
|
|
250944
|
+
const hubPath = join61(dir, "SKILL.md");
|
|
250847
250945
|
const a = byName.get(name);
|
|
250848
250946
|
const known = auditRan && a !== void 0;
|
|
250849
250947
|
return {
|
|
@@ -250859,7 +250957,7 @@ function collectSkillsPanel(projectPath3, deps = defaultSkillsPanelDeps(projectP
|
|
|
250859
250957
|
usage: usage5[name] ?? 0,
|
|
250860
250958
|
files: skillFiles(dir),
|
|
250861
250959
|
dirPath: dir,
|
|
250862
|
-
hubText:
|
|
250960
|
+
hubText: existsSync59(hubPath) ? readFileSync56(hubPath, "utf8") : ""
|
|
250863
250961
|
};
|
|
250864
250962
|
});
|
|
250865
250963
|
const hubLines = rows.reduce((acc, r) => acc + r.hubLines, 0);
|
|
@@ -250883,20 +250981,20 @@ function pkgDir() {
|
|
|
250883
250981
|
return process.env["ROLL_PKG_DIR"] ?? repoRoot2();
|
|
250884
250982
|
}
|
|
250885
250983
|
function catalogPath() {
|
|
250886
|
-
return
|
|
250984
|
+
return join62(pkgDir(), "guide", "skills.md");
|
|
250887
250985
|
}
|
|
250888
250986
|
function isInstallTree() {
|
|
250889
|
-
return !
|
|
250987
|
+
return !existsSync60(join62(pkgDir(), "guide"));
|
|
250890
250988
|
}
|
|
250891
250989
|
function installSkipNotice() {
|
|
250892
250990
|
info2("skills catalog lives in the source repo \u2014 nothing to maintain on an installed roll");
|
|
250893
250991
|
info2("\u6280\u80FD\u76EE\u5F55\u6E05\u5355\u5728\u6E90\u7801\u4ED3\u7EF4\u62A4\u2014\u2014\u5B89\u88C5\u73AF\u5883\u65E0\u9700\u751F\u6210");
|
|
250894
250992
|
}
|
|
250895
250993
|
function skillsDir() {
|
|
250896
|
-
return
|
|
250994
|
+
return join62(pkgDir(), "skills");
|
|
250897
250995
|
}
|
|
250898
250996
|
function frontmatterField(file, field2) {
|
|
250899
|
-
const lines2 =
|
|
250997
|
+
const lines2 = readFileSync57(file, "utf8").split("\n");
|
|
250900
250998
|
if (lines2.length === 0 || lines2[0] !== "---")
|
|
250901
250999
|
return "";
|
|
250902
251000
|
let collecting = false;
|
|
@@ -250956,15 +251054,15 @@ function generateCatalog() {
|
|
|
250956
251054
|
entries = [];
|
|
250957
251055
|
}
|
|
250958
251056
|
for (const name of entries) {
|
|
250959
|
-
const skillDir =
|
|
251057
|
+
const skillDir = join62(dir, name);
|
|
250960
251058
|
try {
|
|
250961
251059
|
if (!statSync19(skillDir).isDirectory())
|
|
250962
251060
|
continue;
|
|
250963
251061
|
} catch {
|
|
250964
251062
|
continue;
|
|
250965
251063
|
}
|
|
250966
|
-
const skillMd =
|
|
250967
|
-
if (!
|
|
251064
|
+
const skillMd = join62(skillDir, "SKILL.md");
|
|
251065
|
+
if (!existsSync60(skillMd))
|
|
250968
251066
|
continue;
|
|
250969
251067
|
let nm = frontmatterField(skillMd, "name");
|
|
250970
251068
|
if (nm === "")
|
|
@@ -251039,18 +251137,18 @@ function skillsCommand(args) {
|
|
|
251039
251137
|
return 0;
|
|
251040
251138
|
}
|
|
251041
251139
|
const target = catalogPath();
|
|
251042
|
-
|
|
251140
|
+
writeFileSync30(target, generateCatalog());
|
|
251043
251141
|
info2(t(v2Catalog, lang11, "skills.generated", target));
|
|
251044
251142
|
return 0;
|
|
251045
251143
|
}
|
|
251046
251144
|
if (sub === "check") {
|
|
251047
251145
|
const target = catalogPath();
|
|
251048
|
-
if (!
|
|
251146
|
+
if (!existsSync60(target)) {
|
|
251049
251147
|
err8(t(v2Catalog, lang11, "skills.check_missing", target));
|
|
251050
251148
|
return 1;
|
|
251051
251149
|
}
|
|
251052
|
-
const fresh =
|
|
251053
|
-
|
|
251150
|
+
const fresh = join62(mkdtempSync4(join62(tmpdir6(), "roll-skills-")), "skills.md");
|
|
251151
|
+
writeFileSync30(fresh, generateCatalog());
|
|
251054
251152
|
let diffOut = "";
|
|
251055
251153
|
let identical = true;
|
|
251056
251154
|
try {
|
|
@@ -251073,7 +251171,7 @@ function skillsCommand(args) {
|
|
|
251073
251171
|
return 0;
|
|
251074
251172
|
}
|
|
251075
251173
|
const target = catalogPath();
|
|
251076
|
-
|
|
251174
|
+
writeFileSync30(target, generateCatalog());
|
|
251077
251175
|
if (lang11 === "zh") {
|
|
251078
251176
|
info2(`\u5DF2\u540C\u6B65\u6280\u80FD\u76EE\u5F55\uFF1A${target}`);
|
|
251079
251177
|
} else {
|
|
@@ -251173,8 +251271,8 @@ function statusMarker(status2) {
|
|
|
251173
251271
|
// packages/cli/dist/lib/onboard-nudge.js
|
|
251174
251272
|
init_dist2();
|
|
251175
251273
|
init_dist();
|
|
251176
|
-
import { existsSync as
|
|
251177
|
-
import { basename as basename13, join as
|
|
251274
|
+
import { existsSync as existsSync61, lstatSync as lstatSync2, readFileSync as readFileSync58, readdirSync as readdirSync23, statSync as statSync20 } from "node:fs";
|
|
251275
|
+
import { basename as basename13, join as join63 } from "node:path";
|
|
251178
251276
|
var DOC_EXTENSIONS = /* @__PURE__ */ new Set([".md", ".markdown", ".txt", ".rst", ".pdf", ".doc", ".docx"]);
|
|
251179
251277
|
var MATERIAL_NAME_RE = /(prd|spec|requirement|design|rfc|需求|产品|需求文档)/i;
|
|
251180
251278
|
var EXCLUDED_NAMES = /* @__PURE__ */ new Set([
|
|
@@ -251222,7 +251320,7 @@ function isNonEmpty(fullPath, isText) {
|
|
|
251222
251320
|
return false;
|
|
251223
251321
|
if (!isText)
|
|
251224
251322
|
return s.size > 0;
|
|
251225
|
-
const content =
|
|
251323
|
+
const content = readFileSync58(fullPath, "utf8");
|
|
251226
251324
|
return content.replace(/\s/g, "").length > 0;
|
|
251227
251325
|
} catch {
|
|
251228
251326
|
return false;
|
|
@@ -251231,9 +251329,9 @@ function isNonEmpty(fullPath, isText) {
|
|
|
251231
251329
|
function detectDesignHandoff(projectDir) {
|
|
251232
251330
|
let backlogEmpty = true;
|
|
251233
251331
|
try {
|
|
251234
|
-
const backlogPath =
|
|
251235
|
-
if (
|
|
251236
|
-
const content =
|
|
251332
|
+
const backlogPath = join63(projectDir, ".roll", "backlog.md");
|
|
251333
|
+
if (existsSync61(backlogPath)) {
|
|
251334
|
+
const content = readFileSync58(backlogPath, "utf8");
|
|
251237
251335
|
const items = parseBacklog(content);
|
|
251238
251336
|
backlogEmpty = items.length === 0;
|
|
251239
251337
|
}
|
|
@@ -251242,7 +251340,7 @@ function detectDesignHandoff(projectDir) {
|
|
|
251242
251340
|
}
|
|
251243
251341
|
let materialPresent = false;
|
|
251244
251342
|
try {
|
|
251245
|
-
if (!
|
|
251343
|
+
if (!existsSync61(projectDir)) {
|
|
251246
251344
|
return { materialPresent: false, backlogEmpty, shouldNudge: false };
|
|
251247
251345
|
}
|
|
251248
251346
|
materialPresent = scanForMaterials(projectDir, 0);
|
|
@@ -251265,7 +251363,7 @@ function scanForMaterials(dir, depth) {
|
|
|
251265
251363
|
return false;
|
|
251266
251364
|
}
|
|
251267
251365
|
for (const entry of entries) {
|
|
251268
|
-
const fullPath =
|
|
251366
|
+
const fullPath = join63(dir, entry);
|
|
251269
251367
|
let lst;
|
|
251270
251368
|
try {
|
|
251271
251369
|
lst = lstatSync2(fullPath);
|
|
@@ -251317,7 +251415,7 @@ function hasMaterialFileInside(dir, depth) {
|
|
|
251317
251415
|
return false;
|
|
251318
251416
|
}
|
|
251319
251417
|
for (const entry of entries) {
|
|
251320
|
-
const fullPath =
|
|
251418
|
+
const fullPath = join63(dir, entry);
|
|
251321
251419
|
let lst;
|
|
251322
251420
|
try {
|
|
251323
251421
|
lst = lstatSync2(fullPath);
|
|
@@ -251355,8 +251453,8 @@ function palette3() {
|
|
|
251355
251453
|
return noColor2 ? { GREEN: "", YELLOW: "", CYAN: "", RED: "", NC: "" } : { GREEN: "\x1B[0;32m", YELLOW: "\x1B[0;33m", CYAN: "\x1B[0;36m", RED: "\x1B[0;31m", NC: "\x1B[0m" };
|
|
251356
251454
|
}
|
|
251357
251455
|
function rollConfigPath4() {
|
|
251358
|
-
const rollHome4 = process.env["ROLL_HOME"] ??
|
|
251359
|
-
return
|
|
251456
|
+
const rollHome4 = process.env["ROLL_HOME"] ?? join64(homedir19(), ".roll");
|
|
251457
|
+
return join64(rollHome4, "config.yaml");
|
|
251360
251458
|
}
|
|
251361
251459
|
function pkgDir2() {
|
|
251362
251460
|
return process.env["ROLL_PKG_DIR"] ?? repoRoot2();
|
|
@@ -251395,10 +251493,10 @@ function commandOnPath3(bin) {
|
|
|
251395
251493
|
if (dir === "")
|
|
251396
251494
|
continue;
|
|
251397
251495
|
try {
|
|
251398
|
-
const st = statSync21(
|
|
251496
|
+
const st = statSync21(join64(dir, bin));
|
|
251399
251497
|
if (!st.isFile())
|
|
251400
251498
|
continue;
|
|
251401
|
-
accessSync3(
|
|
251499
|
+
accessSync3(join64(dir, bin), constants3.X_OK);
|
|
251402
251500
|
return true;
|
|
251403
251501
|
} catch {
|
|
251404
251502
|
}
|
|
@@ -251434,13 +251532,13 @@ var padEnd = (s, w) => {
|
|
|
251434
251532
|
};
|
|
251435
251533
|
function agentSection(p) {
|
|
251436
251534
|
const cfg = rollConfigPath4();
|
|
251437
|
-
if (!
|
|
251535
|
+
if (!existsSync62(cfg))
|
|
251438
251536
|
return;
|
|
251439
251537
|
emit3("");
|
|
251440
251538
|
for (const l of bilingual("doctor.agent_detection"))
|
|
251441
251539
|
emit3(l);
|
|
251442
251540
|
emit3("");
|
|
251443
|
-
const text2 =
|
|
251541
|
+
const text2 = readFileSync59(cfg, "utf8");
|
|
251444
251542
|
let primary = "";
|
|
251445
251543
|
for (const line of text2.split("\n")) {
|
|
251446
251544
|
const m7 = /^primary_agent:\s*(.*)$/.exec(line);
|
|
@@ -251501,7 +251599,7 @@ function branchProtectionState() {
|
|
|
251501
251599
|
return Number(required2) >= 1 ? "enabled" : "disabled";
|
|
251502
251600
|
}
|
|
251503
251601
|
function eventWorkflowState() {
|
|
251504
|
-
return
|
|
251602
|
+
return existsSync62(join64(".github", "workflows", "pr-review-event.yml")) ? "present" : "absent";
|
|
251505
251603
|
}
|
|
251506
251604
|
function insideGitWorkTree() {
|
|
251507
251605
|
try {
|
|
@@ -251575,20 +251673,20 @@ function prSection(lang11) {
|
|
|
251575
251673
|
}
|
|
251576
251674
|
}
|
|
251577
251675
|
function skillsCatalogSection(lang11) {
|
|
251578
|
-
const skillsDir2 =
|
|
251676
|
+
const skillsDir2 = join64(pkgDir2(), "skills");
|
|
251579
251677
|
if (!safeIsDir(skillsDir2))
|
|
251580
251678
|
return;
|
|
251581
|
-
const target =
|
|
251679
|
+
const target = join64(pkgDir2(), "guide", "skills.md");
|
|
251582
251680
|
emit3("");
|
|
251583
251681
|
for (const l of bilingual("skills.doctor_heading"))
|
|
251584
251682
|
emit3(l);
|
|
251585
251683
|
let drift;
|
|
251586
|
-
if (!
|
|
251684
|
+
if (!existsSync62(target)) {
|
|
251587
251685
|
drift = true;
|
|
251588
251686
|
} else {
|
|
251589
|
-
const fresh =
|
|
251590
|
-
|
|
251591
|
-
drift =
|
|
251687
|
+
const fresh = join64(mkdtempSync5(join64(tmpdir7(), "roll-doctor-")), "skills.md");
|
|
251688
|
+
writeFileSync31(fresh, generateCatalog());
|
|
251689
|
+
drift = readFileSync59(target, "utf8") !== readFileSync59(fresh, "utf8");
|
|
251592
251690
|
}
|
|
251593
251691
|
emit3(` ${t(v2Catalog, lang11, drift ? "skills.doctor_drift" : "skills.doctor_ok")}`);
|
|
251594
251692
|
}
|
|
@@ -251596,7 +251694,7 @@ function lanesSection(lang11, probe) {
|
|
|
251596
251694
|
const lines2 = [];
|
|
251597
251695
|
if (process.platform !== "darwin")
|
|
251598
251696
|
return lines2;
|
|
251599
|
-
const dir = process.env["_LAUNCHD_DIR"] ??
|
|
251697
|
+
const dir = process.env["_LAUNCHD_DIR"] ?? join64(homedir19(), "Library", "LaunchAgents");
|
|
251600
251698
|
if (!safeIsDir(dir))
|
|
251601
251699
|
return lines2;
|
|
251602
251700
|
let plists = [];
|
|
@@ -251612,7 +251710,7 @@ function lanesSection(lang11, probe) {
|
|
|
251612
251710
|
lines2.push("");
|
|
251613
251711
|
for (const name of plists) {
|
|
251614
251712
|
const label4 = name.replace(/\.plist$/, "");
|
|
251615
|
-
const wd = readWorkingDirectory(
|
|
251713
|
+
const wd = readWorkingDirectory(join64(dir, name));
|
|
251616
251714
|
const stale = wd !== "" && !safeIsDir(wd);
|
|
251617
251715
|
const exit = probe?.lastExit(label4);
|
|
251618
251716
|
const state = exit === void 0 ? "" : exit === null ? lang11 === "zh" ? " \xB7 \u672A\u52A0\u8F7D" : " \xB7 not loaded" : ` \xB7 last exit ${exit}`;
|
|
@@ -251626,7 +251724,7 @@ function lanesSection(lang11, probe) {
|
|
|
251626
251724
|
function launchdStaleSection(lang11) {
|
|
251627
251725
|
if (process.platform !== "darwin")
|
|
251628
251726
|
return;
|
|
251629
|
-
const dir = process.env["_LAUNCHD_DIR"] ??
|
|
251727
|
+
const dir = process.env["_LAUNCHD_DIR"] ?? join64(homedir19(), "Library", "LaunchAgents");
|
|
251630
251728
|
if (!safeIsDir(dir))
|
|
251631
251729
|
return;
|
|
251632
251730
|
let found = false;
|
|
@@ -251637,7 +251735,7 @@ function launchdStaleSection(lang11) {
|
|
|
251637
251735
|
plists = [];
|
|
251638
251736
|
}
|
|
251639
251737
|
for (const name of plists) {
|
|
251640
|
-
const plist =
|
|
251738
|
+
const plist = join64(dir, name);
|
|
251641
251739
|
const wd = readWorkingDirectory(plist);
|
|
251642
251740
|
if (wd === "")
|
|
251643
251741
|
continue;
|
|
@@ -251757,7 +251855,7 @@ function launchdProxySection(lang11) {
|
|
|
251757
251855
|
function readWorkingDirectory(plist) {
|
|
251758
251856
|
let body;
|
|
251759
251857
|
try {
|
|
251760
|
-
body =
|
|
251858
|
+
body = readFileSync59(plist, "utf8");
|
|
251761
251859
|
} catch {
|
|
251762
251860
|
return "";
|
|
251763
251861
|
}
|
|
@@ -251815,27 +251913,27 @@ function doctorCommand(args, deps = {}) {
|
|
|
251815
251913
|
// packages/cli/dist/commands/dream-run-once.js
|
|
251816
251914
|
init_dist3();
|
|
251817
251915
|
init_dist2();
|
|
251818
|
-
import { existsSync as
|
|
251819
|
-
import { join as
|
|
251916
|
+
import { existsSync as existsSync66, appendFileSync as appendFileSync12, mkdirSync as mkdirSync31, readFileSync as readFileSync62, renameSync as renameSync13, unlinkSync as unlinkSync3, writeFileSync as writeFileSync32 } from "node:fs";
|
|
251917
|
+
import { join as join68 } from "node:path";
|
|
251820
251918
|
import { homedir as homedir21 } from "node:os";
|
|
251821
251919
|
|
|
251822
251920
|
// packages/cli/dist/runner/skill-body.js
|
|
251823
|
-
import { existsSync as
|
|
251921
|
+
import { existsSync as existsSync63, readFileSync as readFileSync60 } from "node:fs";
|
|
251824
251922
|
import { homedir as homedir20 } from "node:os";
|
|
251825
|
-
import { join as
|
|
251923
|
+
import { join as join65 } from "node:path";
|
|
251826
251924
|
function readSkillBody(projectPath3, opts) {
|
|
251827
251925
|
const candidates = [
|
|
251828
251926
|
opts.envOverride ?? "",
|
|
251829
|
-
|
|
251830
|
-
|
|
251831
|
-
|
|
251927
|
+
join65(projectPath3, ".roll", "skills", opts.skillName, "SKILL.md"),
|
|
251928
|
+
join65(projectPath3, "skills", opts.skillName, "SKILL.md"),
|
|
251929
|
+
join65(homedir20(), ".roll", "skills", opts.skillName, "SKILL.md")
|
|
251832
251930
|
].filter((p) => p !== "");
|
|
251833
251931
|
for (const p of candidates) {
|
|
251834
|
-
if (!
|
|
251932
|
+
if (!existsSync63(p))
|
|
251835
251933
|
continue;
|
|
251836
251934
|
let raw = "";
|
|
251837
251935
|
try {
|
|
251838
|
-
raw =
|
|
251936
|
+
raw = readFileSync60(p, "utf8");
|
|
251839
251937
|
} catch {
|
|
251840
251938
|
continue;
|
|
251841
251939
|
}
|
|
@@ -251848,8 +251946,8 @@ function readSkillBody(projectPath3, opts) {
|
|
|
251848
251946
|
|
|
251849
251947
|
// packages/cli/dist/commands/gc.js
|
|
251850
251948
|
init_dist2();
|
|
251851
|
-
import { existsSync as
|
|
251852
|
-
import { join as
|
|
251949
|
+
import { existsSync as existsSync64, readdirSync as readdirSync25, rmSync as rmSync13, statSync as statSync22 } from "node:fs";
|
|
251950
|
+
import { join as join66 } from "node:path";
|
|
251853
251951
|
var RUN_ID_RE = /^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}$/;
|
|
251854
251952
|
function runsInDir(dir) {
|
|
251855
251953
|
const out3 = [];
|
|
@@ -251863,7 +251961,7 @@ function runsInDir(dir) {
|
|
|
251863
251961
|
if (!e.isDirectory() || !RUN_ID_RE.test(e.name))
|
|
251864
251962
|
continue;
|
|
251865
251963
|
try {
|
|
251866
|
-
out3.push({ runId: e.name, mtimeSec: Math.floor(statSync22(
|
|
251964
|
+
out3.push({ runId: e.name, mtimeSec: Math.floor(statSync22(join66(dir, e.name)).mtimeMs / 1e3) });
|
|
251867
251965
|
} catch {
|
|
251868
251966
|
}
|
|
251869
251967
|
}
|
|
@@ -251871,22 +251969,22 @@ function runsInDir(dir) {
|
|
|
251871
251969
|
}
|
|
251872
251970
|
function collectStoryArchives(projectPath3) {
|
|
251873
251971
|
const out3 = [];
|
|
251874
|
-
const featuresRoot =
|
|
251875
|
-
if (
|
|
251972
|
+
const featuresRoot = join66(projectPath3, ".roll", "features");
|
|
251973
|
+
if (existsSync64(featuresRoot)) {
|
|
251876
251974
|
for (const epic of safeDirs(featuresRoot)) {
|
|
251877
|
-
const epicDir =
|
|
251975
|
+
const epicDir = join66(featuresRoot, epic);
|
|
251878
251976
|
for (const story of safeDirs(epicDir)) {
|
|
251879
|
-
const dir =
|
|
251977
|
+
const dir = join66(epicDir, story);
|
|
251880
251978
|
const runs = runsInDir(dir);
|
|
251881
251979
|
if (runs.length > 0)
|
|
251882
251980
|
out3.push({ storyId: story, dir, runs });
|
|
251883
251981
|
}
|
|
251884
251982
|
}
|
|
251885
251983
|
}
|
|
251886
|
-
const verRoot =
|
|
251887
|
-
if (
|
|
251984
|
+
const verRoot = join66(projectPath3, ".roll", "verification");
|
|
251985
|
+
if (existsSync64(verRoot)) {
|
|
251888
251986
|
for (const story of safeDirs(verRoot)) {
|
|
251889
|
-
const dir =
|
|
251987
|
+
const dir = join66(verRoot, story);
|
|
251890
251988
|
const runs = runsInDir(dir);
|
|
251891
251989
|
if (runs.length > 0)
|
|
251892
251990
|
out3.push({ storyId: story, dir, runs });
|
|
@@ -251938,7 +252036,7 @@ function gcCommand(args, deps = {}) {
|
|
|
251938
252036
|
lines2.push(` ${dryRun ? "would delete" : "deleted"}: ${sa.storyId}/${runId}`);
|
|
251939
252037
|
if (!dryRun) {
|
|
251940
252038
|
try {
|
|
251941
|
-
rmSync13(
|
|
252039
|
+
rmSync13(join66(sa.dir, runId), { recursive: true, force: true });
|
|
251942
252040
|
} catch {
|
|
251943
252041
|
}
|
|
251944
252042
|
}
|
|
@@ -251972,14 +252070,14 @@ function realDeps6() {
|
|
|
251972
252070
|
},
|
|
251973
252071
|
dreamReArm: async (projectPath3, slug2) => {
|
|
251974
252072
|
const dormant = dormantMarkerPath(projectPath3, slug2);
|
|
251975
|
-
if (!
|
|
252073
|
+
if (!existsSync66(dormant))
|
|
251976
252074
|
return { rearmed: false };
|
|
251977
|
-
const scanPath =
|
|
251978
|
-
if (!
|
|
252075
|
+
const scanPath = join68(projectPath3, ".roll", "dream", "structure-scan.json");
|
|
252076
|
+
if (!existsSync66(scanPath))
|
|
251979
252077
|
return { rearmed: false };
|
|
251980
252078
|
let hasFindings = false;
|
|
251981
252079
|
try {
|
|
251982
|
-
const raw =
|
|
252080
|
+
const raw = readFileSync62(scanPath, "utf8");
|
|
251983
252081
|
const parsed = JSON.parse(raw);
|
|
251984
252082
|
hasFindings = (parsed.findings?.length ?? 0) > 0;
|
|
251985
252083
|
} catch {
|
|
@@ -251988,29 +252086,29 @@ function realDeps6() {
|
|
|
251988
252086
|
if (!hasFindings)
|
|
251989
252087
|
return { rearmed: false };
|
|
251990
252088
|
const store = new BacklogStore();
|
|
251991
|
-
const snap = store.readBacklog(
|
|
252089
|
+
const snap = store.readBacklog(join68(projectPath3, ".roll", "backlog.md"));
|
|
251992
252090
|
const isDone = buildDoneIndex(snap.items);
|
|
251993
252091
|
for (const item of snap.items) {
|
|
251994
252092
|
if (!item.id.startsWith("REFACTOR-DREAM-"))
|
|
251995
252093
|
continue;
|
|
251996
252094
|
if (isEligible(item, isDone)) {
|
|
251997
252095
|
const scheduler = createScheduler(process.platform, { uid: process.getuid?.() ?? 501 });
|
|
251998
|
-
const loopDir =
|
|
251999
|
-
const launchdDir =
|
|
252096
|
+
const loopDir = join68(projectPath3, ".roll", "loop");
|
|
252097
|
+
const launchdDir = join68(homedir21(), "Library", "LaunchAgents");
|
|
252000
252098
|
const label4 = `com.roll.loop.${slug2}`;
|
|
252001
252099
|
const wakeDeps2 = {
|
|
252002
252100
|
projectPath: projectPath3,
|
|
252003
252101
|
slug: slug2,
|
|
252004
252102
|
scheduler,
|
|
252005
|
-
backlogPath:
|
|
252006
|
-
eventsPath:
|
|
252103
|
+
backlogPath: join68(projectPath3, ".roll", "backlog.md"),
|
|
252104
|
+
eventsPath: join68(loopDir, "events.ndjson"),
|
|
252007
252105
|
eventBus: new EventBus(),
|
|
252008
252106
|
readBacklog: (p) => new BacklogStore().readBacklog(p),
|
|
252009
|
-
probe: (p) =>
|
|
252107
|
+
probe: (p) => existsSync66(p),
|
|
252010
252108
|
rename: (from, to) => renameSync13(from, to),
|
|
252011
252109
|
unlink: (p) => unlinkSync3(p),
|
|
252012
252110
|
nowSec: () => Math.floor(Date.now() / 1e3),
|
|
252013
|
-
loopPlistPath:
|
|
252111
|
+
loopPlistPath: join68(launchdDir, `${label4}.plist`)
|
|
252014
252112
|
};
|
|
252015
252113
|
await rearmLoop("dream", wakeDeps2, item.id);
|
|
252016
252114
|
return { rearmed: true, picked: item.id };
|
|
@@ -252022,8 +252120,8 @@ function realDeps6() {
|
|
|
252022
252120
|
}
|
|
252023
252121
|
async function dreamRunOnceCommand(_args, deps = realDeps6()) {
|
|
252024
252122
|
const id = await deps.identity();
|
|
252025
|
-
const dreamDir =
|
|
252026
|
-
const log =
|
|
252123
|
+
const dreamDir = join68(id.path, ".roll", "dream");
|
|
252124
|
+
const log = join68(dreamDir, "cron.log");
|
|
252027
252125
|
const body = deps.skillBody(id.path);
|
|
252028
252126
|
if (body === null) {
|
|
252029
252127
|
process.stderr.write(`dream run-once: roll-.dream SKILL.md not found \u2014 refusing to spawn a blind agent
|
|
@@ -252031,7 +252129,7 @@ dream run-once: \u627E\u4E0D\u5230 roll-.dream SKILL.md \u2014 \u62D2\u7EDD\u76F
|
|
|
252031
252129
|
`);
|
|
252032
252130
|
return 1;
|
|
252033
252131
|
}
|
|
252034
|
-
|
|
252132
|
+
mkdirSync31(dreamDir, { recursive: true });
|
|
252035
252133
|
const stamp = () => deps.now().toISOString();
|
|
252036
252134
|
const append = (line) => {
|
|
252037
252135
|
try {
|
|
@@ -252047,7 +252145,7 @@ dream run-once: \u627E\u4E0D\u5230 roll-.dream SKILL.md \u2014 \u62D2\u7EDD\u76F
|
|
|
252047
252145
|
append(`[${stamp()}] dream structure pre-scan start
|
|
252048
252146
|
`);
|
|
252049
252147
|
const preScan = await deps.structureScan(id.path, deps.now().toISOString());
|
|
252050
|
-
|
|
252148
|
+
writeFileSync32(join68(dreamDir, "structure-scan.json"), `${JSON.stringify(preScan.json, null, 2)}
|
|
252051
252149
|
`, "utf8");
|
|
252052
252150
|
append(preScan.log);
|
|
252053
252151
|
append(`[${stamp()}] dream structure pre-scan end findings=${preScan.json.findings.length}
|
|
@@ -252138,8 +252236,8 @@ Usage: roll dream run-once
|
|
|
252138
252236
|
// packages/cli/dist/commands/idea.js
|
|
252139
252237
|
init_dist2();
|
|
252140
252238
|
init_dist();
|
|
252141
|
-
import { existsSync as
|
|
252142
|
-
import { join as
|
|
252239
|
+
import { existsSync as existsSync67, mkdirSync as mkdirSync32, writeFileSync as writeFileSync33 } from "node:fs";
|
|
252240
|
+
import { join as join69 } from "node:path";
|
|
252143
252241
|
init_render();
|
|
252144
252242
|
var BACKLOG_PATH2 = ".roll/backlog.md";
|
|
252145
252243
|
function label(lang11, key, ...args) {
|
|
@@ -252169,7 +252267,7 @@ ${label(lang11, "ideav3.usage")}
|
|
|
252169
252267
|
}
|
|
252170
252268
|
const RED = noColor2 ? "" : "\x1B[0;31m";
|
|
252171
252269
|
const NC = noColor2 ? "" : "\x1B[0m";
|
|
252172
|
-
if (!
|
|
252270
|
+
if (!existsSync67(BACKLOG_PATH2)) {
|
|
252173
252271
|
process.stderr.write(`${RED}[roll]${NC} ${t(v2Catalog, lang11, "backlog.roll_backlog_md_not_found_run")}
|
|
252174
252272
|
`);
|
|
252175
252273
|
return 1;
|
|
@@ -252209,13 +252307,13 @@ ${c("green", "\u{1F4DD} " + label(lang11, "ideav3.recorded", plan.id))}
|
|
|
252209
252307
|
`);
|
|
252210
252308
|
const epic = inferEpic(text2) ?? UNCATEGORIZED;
|
|
252211
252309
|
const projectPath3 = process.cwd();
|
|
252212
|
-
const cardDir =
|
|
252310
|
+
const cardDir = join69(projectPath3, ".roll", "features", epic, plan.id);
|
|
252213
252311
|
try {
|
|
252214
|
-
if (
|
|
252312
|
+
if (existsSync67(join69(cardDir, "spec.md"))) {
|
|
252215
252313
|
process.stdout.write(`${c("dim", label(lang11, "ideav3.card_exists", epic, plan.id))}
|
|
252216
252314
|
`);
|
|
252217
252315
|
} else {
|
|
252218
|
-
|
|
252316
|
+
mkdirSync32(cardDir, { recursive: true });
|
|
252219
252317
|
const card = {
|
|
252220
252318
|
id: plan.id,
|
|
252221
252319
|
title: text2,
|
|
@@ -252223,8 +252321,8 @@ ${c("green", "\u{1F4DD} " + label(lang11, "ideav3.recorded", plan.id))}
|
|
|
252223
252321
|
epic: epic !== UNCATEGORIZED ? epic : void 0,
|
|
252224
252322
|
created: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10)
|
|
252225
252323
|
};
|
|
252226
|
-
|
|
252227
|
-
|
|
252324
|
+
writeFileSync33(join69(cardDir, "spec.md"), renderSpecMd(card), "utf8");
|
|
252325
|
+
writeFileSync33(join69(cardDir, "index.html"), renderStoryPage(card), "utf8");
|
|
252228
252326
|
process.stdout.write(` ${c("dim", label(lang11, "ideav3.card_created", epic))}
|
|
252229
252327
|
`);
|
|
252230
252328
|
}
|
|
@@ -252242,9 +252340,9 @@ init_dist2();
|
|
|
252242
252340
|
init_dist();
|
|
252243
252341
|
init_dist2();
|
|
252244
252342
|
init_dist();
|
|
252245
|
-
import { existsSync as
|
|
252343
|
+
import { existsSync as existsSync76, readFileSync as readFileSync70, readdirSync as readdirSync29, statSync as statSync24, writeFileSync as writeFileSync34 } from "node:fs";
|
|
252246
252344
|
import { execFileSync as execFileSync21 } from "node:child_process";
|
|
252247
|
-
import { join as
|
|
252345
|
+
import { join as join79 } from "node:path";
|
|
252248
252346
|
|
|
252249
252347
|
// packages/cli/dist/lib/truth-console.js
|
|
252250
252348
|
init_dist2();
|
|
@@ -253469,8 +253567,8 @@ ${CONSOLE_SCRIPT}
|
|
|
253469
253567
|
|
|
253470
253568
|
// packages/cli/dist/lib/page-about.js
|
|
253471
253569
|
init_dist2();
|
|
253472
|
-
import { existsSync as
|
|
253473
|
-
import { join as
|
|
253570
|
+
import { existsSync as existsSync68 } from "node:fs";
|
|
253571
|
+
import { join as join70 } from "node:path";
|
|
253474
253572
|
var ROLL_CREED = {
|
|
253475
253573
|
en: "Treat the model as a black box; drive its output toward reliability with a feedback loop \u2014 a harness that is observable, trustworthy, self-evaluating, and able to stop itself.",
|
|
253476
253574
|
zh: "\u628A AI \u5F53\u9ED1\u76D2\uFF0C\u7528\u53CD\u9988\u95ED\u73AF\u628A\u5B83\u7684\u4EA7\u51FA\u903C\u5411\u53EF\u9760\uFF1B\u8BA9\u8FD9\u53F0 harness \u81EA\u5DF1\u53EF\u89C2\u6D4B\u3001\u53EF\u4FE1\u8D56\u3001\u80FD\u81EA\u8BC4\u3001\u8FD8\u62E6\u5F97\u4F4F\u81EA\u5DF1\u3002"
|
|
@@ -253555,7 +253653,7 @@ function defaultAboutDeps(cwd) {
|
|
|
253555
253653
|
return {
|
|
253556
253654
|
docExists: (rel) => {
|
|
253557
253655
|
try {
|
|
253558
|
-
return
|
|
253656
|
+
return existsSync68(join70(cwd, rel));
|
|
253559
253657
|
} catch {
|
|
253560
253658
|
return false;
|
|
253561
253659
|
}
|
|
@@ -253615,8 +253713,8 @@ function renderAboutPage(input) {
|
|
|
253615
253713
|
// packages/cli/dist/lib/page-conventions.js
|
|
253616
253714
|
init_dist3();
|
|
253617
253715
|
init_dist2();
|
|
253618
|
-
import { existsSync as
|
|
253619
|
-
import { join as
|
|
253716
|
+
import { existsSync as existsSync69, readFileSync as readFileSync63 } from "node:fs";
|
|
253717
|
+
import { join as join71 } from "node:path";
|
|
253620
253718
|
var SYNC_KEYS = [
|
|
253621
253719
|
{ key: "sync_claude", agent: "claude" },
|
|
253622
253720
|
{ key: "sync_kimi", agent: "kimi" },
|
|
@@ -253644,16 +253742,16 @@ function collectConventions(deps) {
|
|
|
253644
253742
|
};
|
|
253645
253743
|
}
|
|
253646
253744
|
function defaultConventionsDeps(cwd, agents, render2) {
|
|
253647
|
-
const configPath2 =
|
|
253745
|
+
const configPath2 = join71(cwd, "conventions", "config.yaml");
|
|
253648
253746
|
return {
|
|
253649
253747
|
readConfig: (key) => yamlReadFlat(configPath2, key),
|
|
253650
253748
|
agents,
|
|
253651
253749
|
readDoc: (rel) => {
|
|
253652
|
-
const abs =
|
|
253653
|
-
if (!
|
|
253750
|
+
const abs = join71(cwd, rel);
|
|
253751
|
+
if (!existsSync69(abs))
|
|
253654
253752
|
return void 0;
|
|
253655
253753
|
try {
|
|
253656
|
-
return
|
|
253754
|
+
return readFileSync63(abs, "utf8");
|
|
253657
253755
|
} catch {
|
|
253658
253756
|
return void 0;
|
|
253659
253757
|
}
|
|
@@ -253703,17 +253801,17 @@ function renderConventionsPage(input) {
|
|
|
253703
253801
|
|
|
253704
253802
|
// packages/cli/dist/lib/agent-panel.js
|
|
253705
253803
|
init_dist2();
|
|
253706
|
-
import { existsSync as
|
|
253707
|
-
import { join as
|
|
253804
|
+
import { existsSync as existsSync71, readFileSync as readFileSync65 } from "node:fs";
|
|
253805
|
+
import { join as join73 } from "node:path";
|
|
253708
253806
|
|
|
253709
253807
|
// packages/cli/dist/commands/status.js
|
|
253710
253808
|
init_dist();
|
|
253711
253809
|
init_render();
|
|
253712
253810
|
import { execFileSync as execFileSync17 } from "node:child_process";
|
|
253713
253811
|
import { createHash as createHash6 } from "node:crypto";
|
|
253714
|
-
import { existsSync as
|
|
253812
|
+
import { existsSync as existsSync70, lstatSync as lstatSync3, readdirSync as readdirSync26, readFileSync as readFileSync64, realpathSync as realpathSync8, statSync as statSync23 } from "node:fs";
|
|
253715
253813
|
import { homedir as homedir22 } from "node:os";
|
|
253716
|
-
import { basename as basename15, dirname as
|
|
253814
|
+
import { basename as basename15, dirname as dirname34, join as join72 } from "node:path";
|
|
253717
253815
|
function cycleSnapshotCostStr(cyc) {
|
|
253718
253816
|
const byCur = cyc.costByCurrency3d;
|
|
253719
253817
|
if (byCur !== void 0 && Object.keys(byCur).length > 0) {
|
|
@@ -253725,11 +253823,11 @@ function cycleSnapshotCostStr(cyc) {
|
|
|
253725
253823
|
return `$${cyc.costUsd3d.toFixed(2)}`;
|
|
253726
253824
|
}
|
|
253727
253825
|
function rollHome2() {
|
|
253728
|
-
return process.env["ROLL_HOME"] ??
|
|
253826
|
+
return process.env["ROLL_HOME"] ?? join72(homedir22(), ".roll");
|
|
253729
253827
|
}
|
|
253730
|
-
var globalDir = () =>
|
|
253731
|
-
var templatesDir = () =>
|
|
253732
|
-
var configPath = () =>
|
|
253828
|
+
var globalDir = () => join72(rollHome2(), "conventions", "global");
|
|
253829
|
+
var templatesDir = () => join72(rollHome2(), "conventions", "templates");
|
|
253830
|
+
var configPath = () => join72(rollHome2(), "config.yaml");
|
|
253733
253831
|
function projectSlugPy() {
|
|
253734
253832
|
let path = realpathSync8(process.cwd());
|
|
253735
253833
|
try {
|
|
@@ -253748,14 +253846,14 @@ function projectSlugPy() {
|
|
|
253748
253846
|
var CONVENTION_FILES = ["AGENTS.md", "CLAUDE.md", ".cursor-rules", "project_rules.md"];
|
|
253749
253847
|
var TEMPLATES = ["fullstack", "frontend-only", "backend-service", "cli"];
|
|
253750
253848
|
function globalConventions() {
|
|
253751
|
-
return CONVENTION_FILES.map((f) => [f,
|
|
253849
|
+
return CONVENTION_FILES.map((f) => [f, existsSync70(join72(globalDir(), f))]);
|
|
253752
253850
|
}
|
|
253753
253851
|
function parseAiEntries() {
|
|
253754
253852
|
const cfg = configPath();
|
|
253755
|
-
if (!
|
|
253853
|
+
if (!existsSync70(cfg))
|
|
253756
253854
|
return [];
|
|
253757
253855
|
const entries = [];
|
|
253758
|
-
for (const line of
|
|
253856
|
+
for (const line of readFileSync64(cfg, "utf8").split("\n")) {
|
|
253759
253857
|
const m7 = /^ai_[a-z]+:\s*(.+)/.exec(line);
|
|
253760
253858
|
if (m7 === null)
|
|
253761
253859
|
continue;
|
|
@@ -253768,28 +253866,28 @@ function parseAiEntries() {
|
|
|
253768
253866
|
const srcFile = (parts[2] ?? "").trim();
|
|
253769
253867
|
let name = basename15(aiDir).replace(/^\.+/, "");
|
|
253770
253868
|
if (name === "workspace" || name === "agent") {
|
|
253771
|
-
name = basename15(
|
|
253869
|
+
name = basename15(dirname34(aiDir)).replace(/^\.+/, "");
|
|
253772
253870
|
}
|
|
253773
253871
|
entries.push({ name, ai_dir: aiDir, cfg_file: cfgFile, src_file: srcFile });
|
|
253774
253872
|
}
|
|
253775
253873
|
return entries;
|
|
253776
253874
|
}
|
|
253777
253875
|
function aiSyncStatus(e) {
|
|
253778
|
-
const cfgFile =
|
|
253779
|
-
const rollMd =
|
|
253780
|
-
const src =
|
|
253781
|
-
if (!
|
|
253876
|
+
const cfgFile = join72(e.ai_dir, e.cfg_file);
|
|
253877
|
+
const rollMd = join72(e.ai_dir, "roll.md");
|
|
253878
|
+
const src = join72(globalDir(), e.src_file);
|
|
253879
|
+
if (!existsSync70(cfgFile))
|
|
253782
253880
|
return "missing";
|
|
253783
|
-
if (!
|
|
253881
|
+
if (!existsSync70(rollMd))
|
|
253784
253882
|
return "out-of-sync";
|
|
253785
253883
|
try {
|
|
253786
|
-
if (
|
|
253884
|
+
if (existsSync70(src) && !readFileSync64(rollMd).equals(readFileSync64(src)))
|
|
253787
253885
|
return "out-of-sync";
|
|
253788
253886
|
} catch {
|
|
253789
253887
|
return "out-of-sync";
|
|
253790
253888
|
}
|
|
253791
253889
|
try {
|
|
253792
|
-
if (!
|
|
253890
|
+
if (!readFileSync64(cfgFile, "utf8").includes("@roll.md"))
|
|
253793
253891
|
return "out-of-sync";
|
|
253794
253892
|
} catch {
|
|
253795
253893
|
return "out-of-sync";
|
|
@@ -253797,15 +253895,15 @@ function aiSyncStatus(e) {
|
|
|
253797
253895
|
return "sync";
|
|
253798
253896
|
}
|
|
253799
253897
|
function aiSkillCount(e) {
|
|
253800
|
-
const skillsDir2 =
|
|
253801
|
-
if (!
|
|
253898
|
+
const skillsDir2 = join72(e.ai_dir, "skills");
|
|
253899
|
+
if (!existsSync70(skillsDir2))
|
|
253802
253900
|
return 0;
|
|
253803
253901
|
try {
|
|
253804
253902
|
let n = 0;
|
|
253805
253903
|
for (const name of readdirSync26(skillsDir2)) {
|
|
253806
253904
|
if (!name.startsWith("roll-"))
|
|
253807
253905
|
continue;
|
|
253808
|
-
const p =
|
|
253906
|
+
const p = join72(skillsDir2, name);
|
|
253809
253907
|
const st = lstatSync3(p);
|
|
253810
253908
|
if (st.isSymbolicLink() || st.isDirectory())
|
|
253811
253909
|
n++;
|
|
@@ -253818,7 +253916,7 @@ function aiSkillCount(e) {
|
|
|
253818
253916
|
function countFilesRecursive(dir) {
|
|
253819
253917
|
let n = 0;
|
|
253820
253918
|
for (const name of readdirSync26(dir)) {
|
|
253821
|
-
const p =
|
|
253919
|
+
const p = join72(dir, name);
|
|
253822
253920
|
const st = statSync23(p);
|
|
253823
253921
|
if (st.isDirectory())
|
|
253824
253922
|
n += countFilesRecursive(p);
|
|
@@ -253828,8 +253926,8 @@ function countFilesRecursive(dir) {
|
|
|
253828
253926
|
return n;
|
|
253829
253927
|
}
|
|
253830
253928
|
function templateCount(tpl) {
|
|
253831
|
-
const d =
|
|
253832
|
-
if (!
|
|
253929
|
+
const d = join72(templatesDir(), tpl);
|
|
253930
|
+
if (!existsSync70(d))
|
|
253833
253931
|
return 0;
|
|
253834
253932
|
try {
|
|
253835
253933
|
return countFilesRecursive(d);
|
|
@@ -253838,19 +253936,19 @@ function templateCount(tpl) {
|
|
|
253838
253936
|
}
|
|
253839
253937
|
}
|
|
253840
253938
|
function skillsInstalled() {
|
|
253841
|
-
const sd =
|
|
253842
|
-
if (!
|
|
253939
|
+
const sd = join72(rollHome2(), "skills");
|
|
253940
|
+
if (!existsSync70(sd))
|
|
253843
253941
|
return 0;
|
|
253844
253942
|
try {
|
|
253845
|
-
return readdirSync26(sd).filter((n) => statSync23(
|
|
253943
|
+
return readdirSync26(sd).filter((n) => statSync23(join72(sd, n)).isDirectory()).length;
|
|
253846
253944
|
} catch {
|
|
253847
253945
|
return 0;
|
|
253848
253946
|
}
|
|
253849
253947
|
}
|
|
253850
253948
|
function launchdState(service, slug2) {
|
|
253851
253949
|
const label4 = `com.roll.${service}.${slug2}`;
|
|
253852
|
-
const plist =
|
|
253853
|
-
if (!
|
|
253950
|
+
const plist = join72(homedir22(), "Library", "LaunchAgents", `${label4}.plist`);
|
|
253951
|
+
if (!existsSync70(plist))
|
|
253854
253952
|
return "not-installed";
|
|
253855
253953
|
try {
|
|
253856
253954
|
const out3 = execFileSync17("launchctl", ["list", label4], {
|
|
@@ -253987,13 +254085,13 @@ function liveData() {
|
|
|
253987
254085
|
const aiClients = parseAiEntries().map((e) => ({
|
|
253988
254086
|
name: e.name,
|
|
253989
254087
|
cfg_file: e.cfg_file,
|
|
253990
|
-
path:
|
|
254088
|
+
path: join72(e.ai_dir, e.cfg_file).replaceAll(home, "~"),
|
|
253991
254089
|
sync: aiSyncStatus(e),
|
|
253992
254090
|
skills: aiSkillCount(e)
|
|
253993
254091
|
}));
|
|
253994
254092
|
const featDir = ".roll/features";
|
|
253995
254093
|
let featCount = 0;
|
|
253996
|
-
if (
|
|
254094
|
+
if (existsSync70(featDir)) {
|
|
253997
254095
|
featCount = readdirSync26(featDir).filter((n) => n.endsWith(".md")).length;
|
|
253998
254096
|
}
|
|
253999
254097
|
return {
|
|
@@ -254001,8 +254099,8 @@ function liveData() {
|
|
|
254001
254099
|
ai_clients: aiClients,
|
|
254002
254100
|
templates: TEMPLATES.map((t2) => [t2, templateCount(t2)]),
|
|
254003
254101
|
skills_installed: skillsInstalled(),
|
|
254004
|
-
project_has_agents:
|
|
254005
|
-
project_has_backlog:
|
|
254102
|
+
project_has_agents: existsSync70("AGENTS.md"),
|
|
254103
|
+
project_has_backlog: existsSync70(".roll/backlog.md"),
|
|
254006
254104
|
project_features_count: featCount,
|
|
254007
254105
|
loop_state: launchdState("loop", slug2),
|
|
254008
254106
|
dream_state: launchdState("dream", slug2)
|
|
@@ -254196,12 +254294,12 @@ function defaultAgentPanelDeps() {
|
|
|
254196
254294
|
}
|
|
254197
254295
|
function spend72h(projectPath3, nowSec2) {
|
|
254198
254296
|
const out3 = /* @__PURE__ */ new Map();
|
|
254199
|
-
const path =
|
|
254200
|
-
if (!
|
|
254297
|
+
const path = join73(projectPath3, ".roll", "loop", "runs.jsonl");
|
|
254298
|
+
if (!existsSync71(path))
|
|
254201
254299
|
return out3;
|
|
254202
254300
|
let content = "";
|
|
254203
254301
|
try {
|
|
254204
|
-
content =
|
|
254302
|
+
content = readFileSync65(path, "utf8");
|
|
254205
254303
|
} catch {
|
|
254206
254304
|
return out3;
|
|
254207
254305
|
}
|
|
@@ -254243,7 +254341,7 @@ function collectAgentPanel(projectPath3, deps = defaultAgentPanelDeps()) {
|
|
|
254243
254341
|
if (entry !== void 0) {
|
|
254244
254342
|
const sync = aiSyncStatus(entry);
|
|
254245
254343
|
files.push({
|
|
254246
|
-
path:
|
|
254344
|
+
path: join73(entry.ai_dir, entry.cfg_file),
|
|
254247
254345
|
kind: entry.cfg_file,
|
|
254248
254346
|
state: sync === "sync" ? "sync" : sync === "missing" ? "missing" : "stale"
|
|
254249
254347
|
});
|
|
@@ -254270,14 +254368,14 @@ function collectAgentPanel(projectPath3, deps = defaultAgentPanelDeps()) {
|
|
|
254270
254368
|
// packages/cli/dist/lib/release-panel.js
|
|
254271
254369
|
init_dist2();
|
|
254272
254370
|
init_dist();
|
|
254273
|
-
import { existsSync as
|
|
254274
|
-
import { join as
|
|
254371
|
+
import { existsSync as existsSync73, readFileSync as readFileSync67, readdirSync as readdirSync27 } from "node:fs";
|
|
254372
|
+
import { join as join75 } from "node:path";
|
|
254275
254373
|
|
|
254276
254374
|
// packages/cli/dist/lib/release-truth.js
|
|
254277
254375
|
init_dist2();
|
|
254278
254376
|
import { execFileSync as execFileSync18 } from "node:child_process";
|
|
254279
|
-
import { existsSync as
|
|
254280
|
-
import { join as
|
|
254377
|
+
import { existsSync as existsSync72, readFileSync as readFileSync66 } from "node:fs";
|
|
254378
|
+
import { join as join74 } from "node:path";
|
|
254281
254379
|
function bareVersion(tag) {
|
|
254282
254380
|
return tag.replace(/^[vV]/, "");
|
|
254283
254381
|
}
|
|
@@ -254344,7 +254442,7 @@ function readGitTags(projectPath3) {
|
|
|
254344
254442
|
}
|
|
254345
254443
|
function readPackageVersion(projectPath3) {
|
|
254346
254444
|
try {
|
|
254347
|
-
const obj = JSON.parse(
|
|
254445
|
+
const obj = JSON.parse(readFileSync66(join74(projectPath3, "package.json"), "utf8"));
|
|
254348
254446
|
return typeof obj.version === "string" && obj.version.trim() !== "" ? obj.version.trim() : void 0;
|
|
254349
254447
|
} catch {
|
|
254350
254448
|
return void 0;
|
|
@@ -254353,7 +254451,7 @@ function readPackageVersion(projectPath3) {
|
|
|
254353
254451
|
function readChangelogTags(projectPath3) {
|
|
254354
254452
|
const out3 = [];
|
|
254355
254453
|
try {
|
|
254356
|
-
const text2 =
|
|
254454
|
+
const text2 = readFileSync66(join74(projectPath3, "CHANGELOG.md"), "utf8");
|
|
254357
254455
|
for (const line of text2.split("\n")) {
|
|
254358
254456
|
const m7 = /^## (v\S+)\s+—\s+\S+/.exec(line);
|
|
254359
254457
|
if (m7 !== null && m7[1] !== void 0)
|
|
@@ -254364,12 +254462,12 @@ function readChangelogTags(projectPath3) {
|
|
|
254364
254462
|
return out3;
|
|
254365
254463
|
}
|
|
254366
254464
|
function readGateTag(projectPath3) {
|
|
254367
|
-
const path =
|
|
254368
|
-
if (!
|
|
254465
|
+
const path = join74(projectPath3, ".roll", "loop", "events.ndjson");
|
|
254466
|
+
if (!existsSync72(path))
|
|
254369
254467
|
return void 0;
|
|
254370
254468
|
let last;
|
|
254371
254469
|
try {
|
|
254372
|
-
for (const line of
|
|
254470
|
+
for (const line of readFileSync66(path, "utf8").split("\n")) {
|
|
254373
254471
|
if (!line.includes('"type":"release:gate"'))
|
|
254374
254472
|
continue;
|
|
254375
254473
|
const m7 = /"tag":"(v[^"]+)"/.exec(line);
|
|
@@ -254407,11 +254505,11 @@ function collectReleasePanel(projectPath3, releaseReader) {
|
|
|
254407
254505
|
tally: { fail: 0, warn: 0, unknown: 0, subjects: [] }
|
|
254408
254506
|
}));
|
|
254409
254507
|
const out3 = { dims: dimsEmpty, total: { fail: 0, warn: 0, unknown: 0 }, blocking: false };
|
|
254410
|
-
const dir =
|
|
254508
|
+
const dir = join75(projectPath3, ".roll", "reports", "consistency");
|
|
254411
254509
|
try {
|
|
254412
254510
|
const latest = readdirSync27(dir).filter((f) => f.endsWith(".json")).sort().at(-1);
|
|
254413
254511
|
if (latest !== void 0) {
|
|
254414
|
-
const obj = JSON.parse(
|
|
254512
|
+
const obj = JSON.parse(readFileSync67(join75(dir, latest), "utf8"));
|
|
254415
254513
|
const findings = Array.isArray(obj.findings) ? obj.findings : [];
|
|
254416
254514
|
const tallies = tallyByDimension(findings);
|
|
254417
254515
|
out3.dims = CONSISTENCY_DIMENSIONS.map((key) => ({ key, tally: tallies[key] }));
|
|
@@ -254431,10 +254529,10 @@ function collectReleasePanel(projectPath3, releaseReader) {
|
|
|
254431
254529
|
out3.prevTag = reconciled.prevTag;
|
|
254432
254530
|
} else {
|
|
254433
254531
|
try {
|
|
254434
|
-
const path =
|
|
254435
|
-
if (
|
|
254532
|
+
const path = join75(projectPath3, ".roll", "loop", "events.ndjson");
|
|
254533
|
+
if (existsSync73(path)) {
|
|
254436
254534
|
const tags = [];
|
|
254437
|
-
for (const line of
|
|
254535
|
+
for (const line of readFileSync67(path, "utf8").split("\n")) {
|
|
254438
254536
|
const e = parseEventLine(line);
|
|
254439
254537
|
if (e !== null && e.type === "release:gate" && typeof e.tag === "string" && e.tag !== "" && tags.at(-1) !== e.tag) {
|
|
254440
254538
|
tags.push(e.tag);
|
|
@@ -254452,8 +254550,8 @@ function collectReleasePanel(projectPath3, releaseReader) {
|
|
|
254452
254550
|
// packages/cli/dist/lib/release-scope.js
|
|
254453
254551
|
init_dist();
|
|
254454
254552
|
import { execFileSync as execFileSync19 } from "node:child_process";
|
|
254455
|
-
import { existsSync as
|
|
254456
|
-
import { join as
|
|
254553
|
+
import { existsSync as existsSync74, readFileSync as readFileSync68 } from "node:fs";
|
|
254554
|
+
import { join as join76 } from "node:path";
|
|
254457
254555
|
function groupByEpic(items) {
|
|
254458
254556
|
const map = /* @__PURE__ */ new Map();
|
|
254459
254557
|
for (const it of items) {
|
|
@@ -254465,11 +254563,11 @@ function groupByEpic(items) {
|
|
|
254465
254563
|
}
|
|
254466
254564
|
function mergesFromEvents(projectPath3) {
|
|
254467
254565
|
const out3 = /* @__PURE__ */ new Map();
|
|
254468
|
-
const path =
|
|
254469
|
-
if (!
|
|
254566
|
+
const path = join76(projectPath3, ".roll", "loop", "events.ndjson");
|
|
254567
|
+
if (!existsSync74(path))
|
|
254470
254568
|
return out3;
|
|
254471
254569
|
try {
|
|
254472
|
-
for (const line of
|
|
254570
|
+
for (const line of readFileSync68(path, "utf8").split("\n")) {
|
|
254473
254571
|
const e = parseEventLine(line);
|
|
254474
254572
|
if (e !== null && e.type === "pr:merge") {
|
|
254475
254573
|
const prev = out3.get(e.storyId);
|
|
@@ -254576,20 +254674,20 @@ function collectReleaseScope(projectPath3, stories, facts) {
|
|
|
254576
254674
|
};
|
|
254577
254675
|
}
|
|
254578
254676
|
function collectHistory(projectPath3) {
|
|
254579
|
-
const path =
|
|
254580
|
-
if (!
|
|
254677
|
+
const path = join76(projectPath3, "CHANGELOG.md");
|
|
254678
|
+
if (!existsSync74(path))
|
|
254581
254679
|
return [];
|
|
254582
254680
|
let text2 = "";
|
|
254583
254681
|
try {
|
|
254584
|
-
text2 =
|
|
254682
|
+
text2 = readFileSync68(path, "utf8");
|
|
254585
254683
|
} catch {
|
|
254586
254684
|
return [];
|
|
254587
254685
|
}
|
|
254588
254686
|
const waivedTags = /* @__PURE__ */ new Set();
|
|
254589
254687
|
try {
|
|
254590
|
-
const ev =
|
|
254591
|
-
if (
|
|
254592
|
-
for (const line of
|
|
254688
|
+
const ev = join76(projectPath3, ".roll", "loop", "events.ndjson");
|
|
254689
|
+
if (existsSync74(ev)) {
|
|
254690
|
+
for (const line of readFileSync68(ev, "utf8").split("\n")) {
|
|
254593
254691
|
const e = parseEventLine(line);
|
|
254594
254692
|
if (e !== null && e.type === "release:gate" && Array.isArray(e.waivedRules) && e.waivedRules.length > 0) {
|
|
254595
254693
|
waivedTags.add(e.tag);
|
|
@@ -254948,8 +255046,8 @@ function requirementLabel(requirement) {
|
|
|
254948
255046
|
|
|
254949
255047
|
// packages/cli/dist/lib/loop-heartbeat.js
|
|
254950
255048
|
init_dist();
|
|
254951
|
-
import { existsSync as
|
|
254952
|
-
import { join as
|
|
255049
|
+
import { existsSync as existsSync75, readFileSync as readFileSync69 } from "node:fs";
|
|
255050
|
+
import { join as join77 } from "node:path";
|
|
254953
255051
|
var LAUNCHD_LANES = [
|
|
254954
255052
|
{ svc: "loop", name: "backlog loop", mode: "backlog" },
|
|
254955
255053
|
{ svc: "pr", name: "PR loop", mode: "pr" },
|
|
@@ -254958,9 +255056,9 @@ var LAUNCHD_LANES = [
|
|
|
254958
255056
|
function defaultHeartbeatDeps(projectPath3, slug2, launchAgentsDir3) {
|
|
254959
255057
|
const lastRunAt = (svc) => {
|
|
254960
255058
|
const file = svc === "pr" ? "pr.log" : svc === "dream" ? "dream.log" : "runs.jsonl";
|
|
254961
|
-
const path =
|
|
255059
|
+
const path = join77(projectPath3, ".roll", "loop", file);
|
|
254962
255060
|
try {
|
|
254963
|
-
const lines2 =
|
|
255061
|
+
const lines2 = readFileSync69(path, "utf8").trim().split("\n");
|
|
254964
255062
|
for (let i = lines2.length - 1; i >= 0; i--) {
|
|
254965
255063
|
const line = lines2[i] ?? "";
|
|
254966
255064
|
if (line.trim() === "")
|
|
@@ -254984,9 +255082,9 @@ function defaultHeartbeatDeps(projectPath3, slug2, launchAgentsDir3) {
|
|
|
254984
255082
|
};
|
|
254985
255083
|
return {
|
|
254986
255084
|
plistText: (svc) => {
|
|
254987
|
-
const p =
|
|
255085
|
+
const p = join77(launchAgentsDir3, `com.roll.${svc}.${slug2}.plist`);
|
|
254988
255086
|
try {
|
|
254989
|
-
return
|
|
255087
|
+
return existsSync75(p) ? readFileSync69(p, "utf8") : null;
|
|
254990
255088
|
} catch {
|
|
254991
255089
|
return null;
|
|
254992
255090
|
}
|
|
@@ -254994,14 +255092,14 @@ function defaultHeartbeatDeps(projectPath3, slug2, launchAgentsDir3) {
|
|
|
254994
255092
|
lastRunAt,
|
|
254995
255093
|
goalText: () => {
|
|
254996
255094
|
try {
|
|
254997
|
-
return
|
|
255095
|
+
return readFileSync69(join77(projectPath3, ".roll", "loop", "goal.yaml"), "utf8");
|
|
254998
255096
|
} catch {
|
|
254999
255097
|
return null;
|
|
255000
255098
|
}
|
|
255001
255099
|
},
|
|
255002
255100
|
eventsText: () => {
|
|
255003
255101
|
try {
|
|
255004
|
-
return
|
|
255102
|
+
return readFileSync69(join77(projectPath3, ".roll", "loop", "events.ndjson"), "utf8");
|
|
255005
255103
|
} catch {
|
|
255006
255104
|
return null;
|
|
255007
255105
|
}
|
|
@@ -255129,7 +255227,7 @@ function collectLoopHeartbeat(deps) {
|
|
|
255129
255227
|
// packages/cli/dist/lib/git-hooks.js
|
|
255130
255228
|
import { execFileSync as execFileSync20 } from "node:child_process";
|
|
255131
255229
|
import { readdirSync as readdirSync28 } from "node:fs";
|
|
255132
|
-
import { isAbsolute, join as
|
|
255230
|
+
import { isAbsolute, join as join78, resolve as resolve6 } from "node:path";
|
|
255133
255231
|
var HOOK_DESCRIPTIONS = {
|
|
255134
255232
|
"pre-commit": {
|
|
255135
255233
|
en: "TCR proof gate before commit",
|
|
@@ -255195,7 +255293,7 @@ function resolveHooksPath(projectPath3) {
|
|
|
255195
255293
|
};
|
|
255196
255294
|
}
|
|
255197
255295
|
const gitPath = gitOutput3(projectPath3, ["rev-parse", "--git-path", "hooks"]);
|
|
255198
|
-
const fsPath = gitPath === "" ?
|
|
255296
|
+
const fsPath = gitPath === "" ? join78(projectPath3, ".git", "hooks") : isAbsolute(gitPath) ? gitPath : resolve6(projectPath3, gitPath);
|
|
255199
255297
|
return {
|
|
255200
255298
|
displayPath: configured === "" ? ".git/hooks" : configured,
|
|
255201
255299
|
fsPath
|
|
@@ -255206,7 +255304,7 @@ function defaultGitHooksDeps(projectPath3) {
|
|
|
255206
255304
|
return {
|
|
255207
255305
|
hooksPath: resolved.displayPath,
|
|
255208
255306
|
listHookFiles: () => readdirSync28(resolved.fsPath, { withFileTypes: true }).filter((d) => d.isFile()).map((d) => d.name),
|
|
255209
|
-
hookPath: (name) =>
|
|
255307
|
+
hookPath: (name) => join78(resolved.displayPath, name)
|
|
255210
255308
|
};
|
|
255211
255309
|
}
|
|
255212
255310
|
|
|
@@ -255330,14 +255428,14 @@ function iso2(sec) {
|
|
|
255330
255428
|
return new Date(sec * 1e3).toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
255331
255429
|
}
|
|
255332
255430
|
function writeCycleSignalFiles(cwd, rows) {
|
|
255333
|
-
const loopDir =
|
|
255334
|
-
if (!
|
|
255431
|
+
const loopDir = join79(cwd, ".roll", "loop");
|
|
255432
|
+
if (!existsSync76(loopDir))
|
|
255335
255433
|
return;
|
|
255336
255434
|
for (const row2 of rows) {
|
|
255337
255435
|
const signals = row2.signals ?? [];
|
|
255338
255436
|
if (signals.length === 0)
|
|
255339
255437
|
continue;
|
|
255340
|
-
|
|
255438
|
+
writeFileSync34(join79(loopDir, `cycle-${row2.cycleId}.signals.jsonl`), signals.map((sig) => JSON.stringify(sig)).join("\n") + "\n", "utf8");
|
|
255341
255439
|
}
|
|
255342
255440
|
}
|
|
255343
255441
|
function renderNowSec2() {
|
|
@@ -255356,7 +255454,7 @@ function str5(v) {
|
|
|
255356
255454
|
return typeof v === "string" && v !== "" ? v : void 0;
|
|
255357
255455
|
}
|
|
255358
255456
|
function latestConsistencyAudit(projectPath3) {
|
|
255359
|
-
const dir =
|
|
255457
|
+
const dir = join79(projectPath3, ".roll", "reports", "consistency");
|
|
255360
255458
|
let files;
|
|
255361
255459
|
try {
|
|
255362
255460
|
files = readdirSync29(dir).filter((f) => f.endsWith(".json")).sort();
|
|
@@ -255367,7 +255465,7 @@ function latestConsistencyAudit(projectPath3) {
|
|
|
255367
255465
|
if (latest === void 0)
|
|
255368
255466
|
return void 0;
|
|
255369
255467
|
try {
|
|
255370
|
-
const obj = JSON.parse(
|
|
255468
|
+
const obj = JSON.parse(readFileSync70(join79(dir, latest), "utf8"));
|
|
255371
255469
|
const summary = obj["summary"];
|
|
255372
255470
|
if (typeof summary !== "object" || summary === null || Array.isArray(summary))
|
|
255373
255471
|
return void 0;
|
|
@@ -255384,7 +255482,7 @@ function latestConsistencyAudit(projectPath3) {
|
|
|
255384
255482
|
}
|
|
255385
255483
|
}
|
|
255386
255484
|
function cycleTruthBoard(projectPath3, cycleRows, nowSec2) {
|
|
255387
|
-
if (!
|
|
255485
|
+
if (!existsSync76(join79(projectPath3, ".roll", "loop", "runs.jsonl")))
|
|
255388
255486
|
return void 0;
|
|
255389
255487
|
const board = cyclesCycleBoard([...cycleRows], nowSec2);
|
|
255390
255488
|
return {
|
|
@@ -255406,10 +255504,10 @@ function releaseVerdict(v) {
|
|
|
255406
255504
|
}
|
|
255407
255505
|
function releaseTruthBoard(projectPath3, nowSec2) {
|
|
255408
255506
|
const reconciled = reconcileReleaseForProject(projectPath3);
|
|
255409
|
-
const path =
|
|
255507
|
+
const path = join79(projectPath3, ".roll", "loop", "events.ndjson");
|
|
255410
255508
|
let content = "";
|
|
255411
255509
|
try {
|
|
255412
|
-
content =
|
|
255510
|
+
content = readFileSync70(path, "utf8");
|
|
255413
255511
|
} catch {
|
|
255414
255512
|
}
|
|
255415
255513
|
let latestGate;
|
|
@@ -255459,7 +255557,7 @@ function maxCollectedAt2(parts) {
|
|
|
255459
255557
|
}
|
|
255460
255558
|
function runtimeDir6(projectPath3) {
|
|
255461
255559
|
const env = (process.env["ROLL_PROJECT_RUNTIME_DIR"] ?? "").trim();
|
|
255462
|
-
return env !== "" ? env :
|
|
255560
|
+
return env !== "" ? env : join79(projectPath3, ".roll", "loop");
|
|
255463
255561
|
}
|
|
255464
255562
|
function tailNonEmptyLines(text2, limit) {
|
|
255465
255563
|
const lines2 = text2.split(/\r?\n/).filter((line) => line.trim() !== "");
|
|
@@ -255467,7 +255565,7 @@ function tailNonEmptyLines(text2, limit) {
|
|
|
255467
255565
|
}
|
|
255468
255566
|
var LIVE_FEED_FRESH_SEC = 300;
|
|
255469
255567
|
function collectLoopLiveFeed(projectPath3, nowSec2 = renderNowSec2()) {
|
|
255470
|
-
const livePath =
|
|
255568
|
+
const livePath = join79(runtimeDir6(projectPath3), "live.log");
|
|
255471
255569
|
const agent = (process.env["ROLL_LOOP_AGENT"] ?? "claude").trim() || "claude";
|
|
255472
255570
|
const generatedAt = iso2(nowSec2);
|
|
255473
255571
|
const base = {
|
|
@@ -255476,7 +255574,7 @@ function collectLoopLiveFeed(projectPath3, nowSec2 = renderNowSec2()) {
|
|
|
255476
255574
|
agent,
|
|
255477
255575
|
generatedAt
|
|
255478
255576
|
};
|
|
255479
|
-
if (!
|
|
255577
|
+
if (!existsSync76(livePath)) {
|
|
255480
255578
|
return {
|
|
255481
255579
|
...base,
|
|
255482
255580
|
status: "idle",
|
|
@@ -255489,7 +255587,7 @@ function collectLoopLiveFeed(projectPath3, nowSec2 = renderNowSec2()) {
|
|
|
255489
255587
|
let updatedAt = generatedAt;
|
|
255490
255588
|
let mtimeMs = nowSec2 * 1e3;
|
|
255491
255589
|
try {
|
|
255492
|
-
raw =
|
|
255590
|
+
raw = readFileSync70(livePath, "utf8");
|
|
255493
255591
|
const st = statSync24(livePath);
|
|
255494
255592
|
updatedAt = st.mtime.toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
255495
255593
|
mtimeMs = st.mtimeMs;
|
|
@@ -255564,7 +255662,7 @@ function emptyGitHooksPanel(cwd) {
|
|
|
255564
255662
|
function pausedLiveFeed(cwd, nowSec2) {
|
|
255565
255663
|
const generatedAt = iso2(nowSec2);
|
|
255566
255664
|
return {
|
|
255567
|
-
sourcePath:
|
|
255665
|
+
sourcePath: join79(runtimeDir6(cwd), "live.log"),
|
|
255568
255666
|
relativeHref: "../loop/live.log",
|
|
255569
255667
|
agent: (process.env["ROLL_LOOP_AGENT"] ?? "claude").trim() || "claude",
|
|
255570
255668
|
status: "paused",
|
|
@@ -255575,12 +255673,12 @@ function pausedLiveFeed(cwd, nowSec2) {
|
|
|
255575
255673
|
};
|
|
255576
255674
|
}
|
|
255577
255675
|
function renderSpecHtml(storyDir, id) {
|
|
255578
|
-
const specPath =
|
|
255579
|
-
if (!
|
|
255676
|
+
const specPath = join79(storyDir, "spec.md");
|
|
255677
|
+
if (!existsSync76(specPath))
|
|
255580
255678
|
return null;
|
|
255581
255679
|
let md;
|
|
255582
255680
|
try {
|
|
255583
|
-
md =
|
|
255681
|
+
md = readFileSync70(specPath, "utf8");
|
|
255584
255682
|
} catch {
|
|
255585
255683
|
return null;
|
|
255586
255684
|
}
|
|
@@ -255618,7 +255716,7 @@ function indexCommand(args) {
|
|
|
255618
255716
|
\u7D22\u5F15\u5DF2\u91CD\u5EFA
|
|
255619
255717
|
${n} stories mapped to epics (.roll/index.json)
|
|
255620
255718
|
`);
|
|
255621
|
-
if (
|
|
255719
|
+
if (existsSync76(join79(cwd, ".roll", "features"))) {
|
|
255622
255720
|
const pages = generateDossierPages(cwd, rebuild);
|
|
255623
255721
|
process.stdout.write(`Static archive regenerated (${pages} pages)
|
|
255624
255722
|
\u9759\u6001\u5F52\u6863\u5DF2\u91CD\u5EFA\uFF08${pages} \u9875\uFF09
|
|
@@ -255652,8 +255750,8 @@ function backlogViewModel(epics) {
|
|
|
255652
255750
|
return { shipping, settled };
|
|
255653
255751
|
}
|
|
255654
255752
|
function generateDossierPages(cwd, rebuild) {
|
|
255655
|
-
const featuresDir =
|
|
255656
|
-
if (!
|
|
255753
|
+
const featuresDir = join79(cwd, ".roll", "features");
|
|
255754
|
+
if (!existsSync76(featuresDir))
|
|
255657
255755
|
return 0;
|
|
255658
255756
|
refreshDossierMergeBaseline(cwd);
|
|
255659
255757
|
const runCache = buildDossierRunCache(cwd);
|
|
@@ -255707,7 +255805,7 @@ function generateDossierPages(cwd, rebuild) {
|
|
|
255707
255805
|
};
|
|
255708
255806
|
const snapshot = collectDossierState(cwd, { deps: cliDeps });
|
|
255709
255807
|
const snapshotJson2 = serializeTruthSnapshot(snapshot);
|
|
255710
|
-
|
|
255808
|
+
writeFileSync34(join79(featuresDir, "truth.json"), snapshotJson2, "utf8");
|
|
255711
255809
|
const projectName = resolveProjectName(cwd);
|
|
255712
255810
|
try {
|
|
255713
255811
|
if (shouldSelfRegister(cwd)) {
|
|
@@ -255724,7 +255822,7 @@ function generateDossierPages(cwd, rebuild) {
|
|
|
255724
255822
|
} catch {
|
|
255725
255823
|
}
|
|
255726
255824
|
const agentRows = collectAgentPanel(cwd);
|
|
255727
|
-
|
|
255825
|
+
writeFileSync34(join79(featuresDir, "index.html"), renderTruthConsole({
|
|
255728
255826
|
snapshot,
|
|
255729
255827
|
snapshotJson: snapshotJson2,
|
|
255730
255828
|
brand: {
|
|
@@ -255785,7 +255883,7 @@ function generateDossierPages(cwd, rebuild) {
|
|
|
255785
255883
|
currentSlug: projectSlug2(cwd)
|
|
255786
255884
|
};
|
|
255787
255885
|
try {
|
|
255788
|
-
|
|
255886
|
+
writeFileSync34(join79(featuresDir, "agents.html"), renderAgentsMachinePage({ ...machineBar, agents: collectAgentPanel(cwd), externalTools: collectExternalTools() }), "utf8");
|
|
255789
255887
|
pages += 1;
|
|
255790
255888
|
} catch {
|
|
255791
255889
|
}
|
|
@@ -255795,23 +255893,23 @@ function generateDossierPages(cwd, rebuild) {
|
|
|
255795
255893
|
for (const [page, file] of MACHINE_PAGES) {
|
|
255796
255894
|
try {
|
|
255797
255895
|
const html = page === "skills" ? renderSkillsPage({ ...machineBar, skills: collectSkillsPanel(cwd) }) : renderMachineStubPage({ ...machineBar, page });
|
|
255798
|
-
|
|
255896
|
+
writeFileSync34(join79(featuresDir, file), html, "utf8");
|
|
255799
255897
|
pages += 1;
|
|
255800
255898
|
} catch {
|
|
255801
255899
|
}
|
|
255802
255900
|
}
|
|
255803
255901
|
try {
|
|
255804
|
-
|
|
255902
|
+
writeFileSync34(join79(featuresDir, "tools.html"), renderToolsPage({ ...machineBar, tools: collectToolPanel() }), "utf8");
|
|
255805
255903
|
pages += 1;
|
|
255806
255904
|
} catch {
|
|
255807
255905
|
}
|
|
255808
255906
|
try {
|
|
255809
|
-
|
|
255907
|
+
writeFileSync34(join79(featuresDir, "conventions.html"), renderConventionsPage({ ...machineBar, vm: collectConventions(defaultConventionsDeps(cwd, agentRows, renderMarkdown)) }), "utf8");
|
|
255810
255908
|
pages += 1;
|
|
255811
255909
|
} catch {
|
|
255812
255910
|
}
|
|
255813
255911
|
try {
|
|
255814
|
-
|
|
255912
|
+
writeFileSync34(join79(featuresDir, "about.html"), renderAboutPage({ ...machineBar, vm: collectAbout(defaultAboutDeps(cwd)) }), "utf8");
|
|
255815
255913
|
pages += 1;
|
|
255816
255914
|
} catch {
|
|
255817
255915
|
}
|
|
@@ -255819,21 +255917,21 @@ function generateDossierPages(cwd, rebuild) {
|
|
|
255819
255917
|
}
|
|
255820
255918
|
for (const epic of epics) {
|
|
255821
255919
|
try {
|
|
255822
|
-
|
|
255920
|
+
writeFileSync34(join79(featuresDir, epic.name, "index.html"), renderEpicPage(epic), "utf8");
|
|
255823
255921
|
pages += 1;
|
|
255824
255922
|
} catch {
|
|
255825
255923
|
}
|
|
255826
255924
|
for (const story of epic.stories) {
|
|
255827
|
-
const storyDir =
|
|
255925
|
+
const storyDir = join79(featuresDir, epic.name, story.id);
|
|
255828
255926
|
try {
|
|
255829
|
-
const storyIndex =
|
|
255830
|
-
if (rebuild || !
|
|
255831
|
-
|
|
255927
|
+
const storyIndex = join79(storyDir, "index.html");
|
|
255928
|
+
if (rebuild || !existsSync76(storyIndex)) {
|
|
255929
|
+
writeFileSync34(storyIndex, renderStoryDossier(inputs.get(`${epic.name}/${story.id}`) ?? collectStoryDossierInput(cwd, story, runCache)), "utf8");
|
|
255832
255930
|
pages += 1;
|
|
255833
255931
|
}
|
|
255834
255932
|
const specHtml = renderSpecHtml(storyDir, story.id);
|
|
255835
255933
|
if (specHtml !== null) {
|
|
255836
|
-
|
|
255934
|
+
writeFileSync34(join79(storyDir, "spec.html"), specHtml, "utf8");
|
|
255837
255935
|
pages += 1;
|
|
255838
255936
|
}
|
|
255839
255937
|
} catch {
|
|
@@ -255858,8 +255956,8 @@ function refreshDossierMergeBaseline(cwd) {
|
|
|
255858
255956
|
}
|
|
255859
255957
|
|
|
255860
255958
|
// packages/cli/dist/commands/story-new.js
|
|
255861
|
-
import { existsSync as
|
|
255862
|
-
import { join as
|
|
255959
|
+
import { existsSync as existsSync77, mkdirSync as mkdirSync33, writeFileSync as writeFileSync35 } from "node:fs";
|
|
255960
|
+
import { join as join80 } from "node:path";
|
|
255863
255961
|
init_dist2();
|
|
255864
255962
|
function todayYmd() {
|
|
255865
255963
|
const d = /* @__PURE__ */ new Date();
|
|
@@ -255892,8 +255990,8 @@ story new: '${id}' \u4E0D\u662F\u5408\u6CD5\u6545\u4E8B ID
|
|
|
255892
255990
|
const epic = flagValue2(args, "--epic") ?? UNCATEGORIZED;
|
|
255893
255991
|
const note = flagValue2(args, "--note");
|
|
255894
255992
|
const cwd = process.cwd();
|
|
255895
|
-
const dir =
|
|
255896
|
-
if (
|
|
255993
|
+
const dir = join80(cwd, ".roll", "features", epic, id);
|
|
255994
|
+
if (existsSync77(join80(dir, "spec.md"))) {
|
|
255897
255995
|
process.stderr.write(`story new: ${epic}/${id}/spec.md already exists \u2014 cards are born once
|
|
255898
255996
|
story new: \u5361\u5DF2\u5B58\u5728\uFF0C\u4E0D\u53EF\u8986\u76D6
|
|
255899
255997
|
`);
|
|
@@ -255906,13 +256004,13 @@ story new: \u5361\u5DF2\u5B58\u5728\uFF0C\u4E0D\u53EF\u8986\u76D6
|
|
|
255906
256004
|
...epic !== UNCATEGORIZED ? { epic } : {},
|
|
255907
256005
|
...note !== void 0 && note !== "" ? { note } : {}
|
|
255908
256006
|
};
|
|
255909
|
-
|
|
255910
|
-
|
|
255911
|
-
|
|
256007
|
+
mkdirSync33(dir, { recursive: true });
|
|
256008
|
+
writeFileSync35(join80(dir, "spec.md"), renderSpecMd(meta8), "utf8");
|
|
256009
|
+
writeFileSync35(join80(dir, "index.html"), renderStoryPage(meta8), "utf8");
|
|
255912
256010
|
let rowNote = "";
|
|
255913
256011
|
try {
|
|
255914
|
-
const backlogPath =
|
|
255915
|
-
if (
|
|
256012
|
+
const backlogPath = join80(cwd, ".roll", "backlog.md");
|
|
256013
|
+
if (existsSync77(backlogPath)) {
|
|
255916
256014
|
const store = new BacklogStore();
|
|
255917
256015
|
const before = store.readBacklog(backlogPath);
|
|
255918
256016
|
let appended = false;
|
|
@@ -255946,7 +256044,7 @@ ${rowNote}`);
|
|
|
255946
256044
|
|
|
255947
256045
|
// packages/cli/dist/commands/story-validate.js
|
|
255948
256046
|
init_render();
|
|
255949
|
-
import { readFileSync as
|
|
256047
|
+
import { readFileSync as readFileSync71 } from "node:fs";
|
|
255950
256048
|
var green = (s) => c("green", s);
|
|
255951
256049
|
var red = (s) => c("red", s);
|
|
255952
256050
|
var STORY_VALIDATE_USAGE = "Usage: roll story validate <ID>\n Self-check a card's spec against the visual-evidence contract (FIX-339):\n must-declare a deliverable surface (deliverable_url / deliverable_cmd /\n screenshot_exempt) AND carry a visual-evidence AC. Exit 0 = ok, non-zero = not ok.\n \u81EA\u68C0\u5361\u7247\u662F\u5426\u6EE1\u8DB3\u53EF\u89C6\u8BC1\u636E\u5951\u7EA6:\u5FC5\u987B\u58F0\u660E\u4EA4\u4ED8\u9762 + \u5E26\u53EF\u89C6\u8BC1\u636E AC;\u5408\u683C\u9000\u51FA 0,\u4E0D\u5408\u683C\u975E 0\u3002\n";
|
|
@@ -255986,7 +256084,7 @@ story validate: \u627E\u4E0D\u5230 ${id} \u7684 spec
|
|
|
255986
256084
|
}
|
|
255987
256085
|
let specText;
|
|
255988
256086
|
try {
|
|
255989
|
-
specText =
|
|
256087
|
+
specText = readFileSync71(spec, "utf8");
|
|
255990
256088
|
} catch (e) {
|
|
255991
256089
|
process.stderr.write(`story validate: cannot read ${spec} (${e instanceof Error ? e.message : "?"})
|
|
255992
256090
|
`);
|
|
@@ -256032,14 +256130,14 @@ init_dist2();
|
|
|
256032
256130
|
init_dist();
|
|
256033
256131
|
init_render();
|
|
256034
256132
|
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
256035
|
-
import { cpSync, existsSync as
|
|
256133
|
+
import { cpSync, existsSync as existsSync83, mkdtempSync as mkdtempSync6, mkdirSync as mkdirSync35, readSync as readSync4, readFileSync as readFileSync76, readdirSync as readdirSync30, realpathSync as realpathSync10, renameSync as renameSync14, rmSync as rmSync14, statSync as statSync28, writeFileSync as writeFileSync37 } from "node:fs";
|
|
256036
256134
|
import { homedir as homedir24, tmpdir as tmpdir8 } from "node:os";
|
|
256037
|
-
import { dirname as
|
|
256135
|
+
import { dirname as dirname36, join as join86 } from "node:path";
|
|
256038
256136
|
|
|
256039
256137
|
// packages/cli/dist/lib/init-diagnosis.js
|
|
256040
256138
|
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
256041
|
-
import { existsSync as
|
|
256042
|
-
import { join as
|
|
256139
|
+
import { existsSync as existsSync78, opendirSync, readFileSync as readFileSync72, realpathSync as realpathSync9, statSync as statSync25 } from "node:fs";
|
|
256140
|
+
import { join as join81 } from "node:path";
|
|
256043
256141
|
|
|
256044
256142
|
// packages/cli/dist/lib/init-diagnosis-render.js
|
|
256045
256143
|
function label2(en, zh, lang11) {
|
|
@@ -256125,7 +256223,7 @@ function isFile(path) {
|
|
|
256125
256223
|
}
|
|
256126
256224
|
}
|
|
256127
256225
|
function sortedExisting(paths, root, dirsOnly = false) {
|
|
256128
|
-
return paths.filter((rel) => dirsOnly || rel.endsWith("/") ? isDir3(
|
|
256226
|
+
return paths.filter((rel) => dirsOnly || rel.endsWith("/") ? isDir3(join81(root, rel)) : existsSync78(join81(root, rel))).sort();
|
|
256129
256227
|
}
|
|
256130
256228
|
function sortedDirectoryEntries(dir, cap) {
|
|
256131
256229
|
let handle;
|
|
@@ -256148,7 +256246,7 @@ function sortedDirectoryEntries(dir, cap) {
|
|
|
256148
256246
|
}
|
|
256149
256247
|
}
|
|
256150
256248
|
function gitFacts(projectDir) {
|
|
256151
|
-
const present2 =
|
|
256249
|
+
const present2 = existsSync78(join81(projectDir, ".git"));
|
|
256152
256250
|
if (!present2)
|
|
256153
256251
|
return { present: false, commits: 0 };
|
|
256154
256252
|
const count = spawnSync8("git", ["rev-list", "--count", "HEAD"], { cwd: projectDir, encoding: "utf8" });
|
|
@@ -256177,7 +256275,7 @@ function countFiles(root, remainingDepth, cap) {
|
|
|
256177
256275
|
fileCapped = true;
|
|
256178
256276
|
return;
|
|
256179
256277
|
}
|
|
256180
|
-
const path =
|
|
256278
|
+
const path = join81(dir, entry);
|
|
256181
256279
|
let st;
|
|
256182
256280
|
try {
|
|
256183
256281
|
st = statSync25(path);
|
|
@@ -256208,7 +256306,7 @@ function addDocSignal(projectDir, rel, docs, ambiguityReasons) {
|
|
|
256208
256306
|
ambiguityReasons.push("document scan capped at 16 files");
|
|
256209
256307
|
return;
|
|
256210
256308
|
}
|
|
256211
|
-
const path =
|
|
256309
|
+
const path = join81(projectDir, rel);
|
|
256212
256310
|
if (!isFile(path))
|
|
256213
256311
|
return;
|
|
256214
256312
|
let st;
|
|
@@ -256225,7 +256323,7 @@ function addDocSignal(projectDir, rel, docs, ambiguityReasons) {
|
|
|
256225
256323
|
}
|
|
256226
256324
|
let text2 = "";
|
|
256227
256325
|
try {
|
|
256228
|
-
text2 =
|
|
256326
|
+
text2 = readFileSync72(path, "utf8");
|
|
256229
256327
|
} catch {
|
|
256230
256328
|
ambiguityReasons.push(`unreadable document: ${rel}`);
|
|
256231
256329
|
return;
|
|
@@ -256251,7 +256349,7 @@ function collectDocs(projectDir, ambiguityReasons) {
|
|
|
256251
256349
|
const seen = /* @__PURE__ */ new Set();
|
|
256252
256350
|
const add = (rel) => {
|
|
256253
256351
|
try {
|
|
256254
|
-
const real = realpathSync9(
|
|
256352
|
+
const real = realpathSync9(join81(projectDir, rel)).toLowerCase();
|
|
256255
256353
|
if (seen.has(real))
|
|
256256
256354
|
return;
|
|
256257
256355
|
seen.add(real);
|
|
@@ -256263,7 +256361,7 @@ function collectDocs(projectDir, ambiguityReasons) {
|
|
|
256263
256361
|
for (const rel of DOC_ROOTS)
|
|
256264
256362
|
add(rel);
|
|
256265
256363
|
for (const dir of DOC_DIRS) {
|
|
256266
|
-
const root =
|
|
256364
|
+
const root = join81(projectDir, dir);
|
|
256267
256365
|
if (!isDir3(root))
|
|
256268
256366
|
continue;
|
|
256269
256367
|
const listed = sortedDirectoryEntries(root, MAX_DOC_CANDIDATES);
|
|
@@ -256276,7 +256374,7 @@ function collectDocs(projectDir, ambiguityReasons) {
|
|
|
256276
256374
|
for (const entry of listed.entries) {
|
|
256277
256375
|
if (!/\.(md|mdx|txt)$/i.test(entry))
|
|
256278
256376
|
continue;
|
|
256279
|
-
add(
|
|
256377
|
+
add(join81(dir, entry));
|
|
256280
256378
|
}
|
|
256281
256379
|
}
|
|
256282
256380
|
docs.prdFiles.sort();
|
|
@@ -256293,23 +256391,23 @@ function defaultContentScan(projectDir) {
|
|
|
256293
256391
|
}
|
|
256294
256392
|
function collectInitFacts(projectDir, deps = {}) {
|
|
256295
256393
|
const ambiguityReasons = [];
|
|
256296
|
-
const dotRoll = isDir3(
|
|
256394
|
+
const dotRoll = isDir3(join81(projectDir, ".roll"));
|
|
256297
256395
|
let dotRollMarker = dotRoll;
|
|
256298
256396
|
if (dotRoll && deps.ignoreOnboardArtifacts === true) {
|
|
256299
|
-
const listed = sortedDirectoryEntries(
|
|
256397
|
+
const listed = sortedDirectoryEntries(join81(projectDir, ".roll"), MAX_SOURCE_DIR_ENTRIES);
|
|
256300
256398
|
dotRollMarker = listed.unreadable || listed.capped || listed.entries.some((entry) => !ONBOARD_ONLY_DOT_ROLL_ENTRIES.has(entry));
|
|
256301
256399
|
}
|
|
256302
256400
|
const roll = {
|
|
256303
256401
|
dotRoll: dotRollMarker,
|
|
256304
|
-
backlog: isFile(
|
|
256305
|
-
features: isDir3(
|
|
256306
|
-
agentsDoc: isFile(
|
|
256402
|
+
backlog: isFile(join81(projectDir, ".roll", "backlog.md")),
|
|
256403
|
+
features: isDir3(join81(projectDir, ".roll", "features")),
|
|
256404
|
+
agentsDoc: isFile(join81(projectDir, "AGENTS.md")),
|
|
256307
256405
|
oldMarkers: sortedExisting(OLD_ROLL_MARKERS, projectDir)
|
|
256308
256406
|
};
|
|
256309
256407
|
if (roll.dotRoll || roll.backlog || roll.features || roll.agentsDoc || roll.oldMarkers.length > 0) {
|
|
256310
256408
|
return {
|
|
256311
256409
|
root: projectDir,
|
|
256312
|
-
git: { present:
|
|
256410
|
+
git: { present: existsSync78(join81(projectDir, ".git")), commits: 0 },
|
|
256313
256411
|
roll,
|
|
256314
256412
|
codebase: { manifests: [], sourceDirs: [], testDirs: [], sourceFileCount: 0 },
|
|
256315
256413
|
docs: { hasContent: false, prdFiles: [], readmeFiles: [], designDocs: [], extractedSignals: [] },
|
|
@@ -256319,7 +256417,7 @@ function collectInitFacts(projectDir, deps = {}) {
|
|
|
256319
256417
|
const sourceDirs = sortedExisting(SOURCE_DIRS, projectDir, true);
|
|
256320
256418
|
let sourceFileCount = 0;
|
|
256321
256419
|
for (const dir of sourceDirs) {
|
|
256322
|
-
const counted = countFiles(
|
|
256420
|
+
const counted = countFiles(join81(projectDir, dir), 4, MAX_SOURCE_FILES - sourceFileCount);
|
|
256323
256421
|
sourceFileCount += counted.count;
|
|
256324
256422
|
if (counted.entryCapped)
|
|
256325
256423
|
ambiguityReasons.push(`source directory scan capped at ${MAX_SOURCE_DIR_ENTRIES} entries: ${dir}/`);
|
|
@@ -256432,10 +256530,10 @@ function renderStateMatrixFixture(lang11) {
|
|
|
256432
256530
|
}
|
|
256433
256531
|
|
|
256434
256532
|
// packages/cli/dist/lib/init-repair.js
|
|
256435
|
-
import { existsSync as
|
|
256436
|
-
import { join as
|
|
256533
|
+
import { existsSync as existsSync79 } from "node:fs";
|
|
256534
|
+
import { join as join82 } from "node:path";
|
|
256437
256535
|
function existsProjectPath(projectDir, rel) {
|
|
256438
|
-
return
|
|
256536
|
+
return existsSync79(join82(projectDir, rel.replace(/\/$/, "")));
|
|
256439
256537
|
}
|
|
256440
256538
|
function createOrKeep(projectDir, target, kind) {
|
|
256441
256539
|
const exists = existsProjectPath(projectDir, target);
|
|
@@ -256487,19 +256585,19 @@ function buildInitRepairPlan(projectDir, facts) {
|
|
|
256487
256585
|
}
|
|
256488
256586
|
|
|
256489
256587
|
// packages/cli/dist/lib/init-brief.js
|
|
256490
|
-
import { existsSync as
|
|
256491
|
-
import { dirname as
|
|
256588
|
+
import { existsSync as existsSync80, mkdirSync as mkdirSync34, readFileSync as readFileSync73, statSync as statSync26, writeFileSync as writeFileSync36 } from "node:fs";
|
|
256589
|
+
import { dirname as dirname35, join as join83 } from "node:path";
|
|
256492
256590
|
var MAX_SOURCE_BYTES = 24e3;
|
|
256493
256591
|
function firstBriefSource(facts) {
|
|
256494
256592
|
return facts.docs.prdFiles[0] ?? facts.docs.extractedSignals[0] ?? facts.docs.designDocs[0] ?? facts.docs.readmeFiles[0];
|
|
256495
256593
|
}
|
|
256496
256594
|
function readSourceExcerpt(projectDir, rel) {
|
|
256497
|
-
const path =
|
|
256595
|
+
const path = join83(projectDir, rel);
|
|
256498
256596
|
try {
|
|
256499
256597
|
const st = statSync26(path);
|
|
256500
256598
|
if (!st.isFile() || st.size <= 0)
|
|
256501
256599
|
return "";
|
|
256502
|
-
const text2 =
|
|
256600
|
+
const text2 = readFileSync73(path, "utf8").slice(0, MAX_SOURCE_BYTES);
|
|
256503
256601
|
return text2.trim();
|
|
256504
256602
|
} catch {
|
|
256505
256603
|
return "";
|
|
@@ -256546,25 +256644,25 @@ function initDesignNextCommand(kind, facts) {
|
|
|
256546
256644
|
function writeInitBrief(projectDir, kind, facts, options = {}) {
|
|
256547
256645
|
if (kind !== "prd-only" && kind !== "empty")
|
|
256548
256646
|
return null;
|
|
256549
|
-
const briefPath =
|
|
256647
|
+
const briefPath = join83(projectDir, ".roll", "brief.md");
|
|
256550
256648
|
const sourcePath = kind === "prd-only" ? firstBriefSource(facts) : void 0;
|
|
256551
256649
|
const result = {
|
|
256552
256650
|
relPath: ".roll/brief.md",
|
|
256553
|
-
created: !
|
|
256651
|
+
created: !existsSync80(briefPath),
|
|
256554
256652
|
nextCommand: initDesignNextCommand(kind, facts),
|
|
256555
256653
|
...sourcePath !== void 0 ? { sourcePath } : {}
|
|
256556
256654
|
};
|
|
256557
256655
|
if (!result.created)
|
|
256558
256656
|
return result;
|
|
256559
|
-
|
|
256560
|
-
|
|
256657
|
+
mkdirSync34(dirname35(briefPath), { recursive: true });
|
|
256658
|
+
writeFileSync36(briefPath, sourcePath !== void 0 ? renderPrdBrief(projectDir, sourcePath) : renderEmptyBrief(options.emptyDescription));
|
|
256561
256659
|
return result;
|
|
256562
256660
|
}
|
|
256563
256661
|
|
|
256564
256662
|
// packages/cli/dist/lib/onboard-apply.js
|
|
256565
256663
|
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
256566
|
-
import { existsSync as
|
|
256567
|
-
import { join as
|
|
256664
|
+
import { existsSync as existsSync81, readFileSync as readFileSync74 } from "node:fs";
|
|
256665
|
+
import { join as join84 } from "node:path";
|
|
256568
256666
|
|
|
256569
256667
|
// packages/cli/dist/lib/onboard-plan.js
|
|
256570
256668
|
import { createHash as createHash7 } from "node:crypto";
|
|
@@ -256655,8 +256753,8 @@ function validateOnboardApplyPreflight(projectDir, planPath, deps = {}) {
|
|
|
256655
256753
|
if (planFactsHash === null)
|
|
256656
256754
|
errors.push("could not read factsHash from .roll/onboard-plan.yaml");
|
|
256657
256755
|
else if (planFactsHash !== currentFactsHash) {
|
|
256658
|
-
const diagnosisFactsHash = readDiagnosisFactsHash(
|
|
256659
|
-
const hasApplyMetadata =
|
|
256756
|
+
const diagnosisFactsHash = readDiagnosisFactsHash(join84(projectDir, ".roll", "init-diagnosis.yaml"));
|
|
256757
|
+
const hasApplyMetadata = existsSync81(join84(projectDir, ".roll", "onboard-changeset.yaml"));
|
|
256660
256758
|
if (hasApplyMetadata && diagnosisFactsHash === planFactsHash) {
|
|
256661
256759
|
return { ok: true, errors: [], currentFactsHash, planFactsHash };
|
|
256662
256760
|
}
|
|
@@ -256670,13 +256768,13 @@ function validateOnboardApplyPreflight(projectDir, planPath, deps = {}) {
|
|
|
256670
256768
|
};
|
|
256671
256769
|
}
|
|
256672
256770
|
function readDiagnosisFactsHash(path) {
|
|
256673
|
-
if (!
|
|
256771
|
+
if (!existsSync81(path))
|
|
256674
256772
|
return null;
|
|
256675
|
-
const match = /^factsHash:\s*"?([^"\n]+)"?/m.exec(
|
|
256773
|
+
const match = /^factsHash:\s*"?([^"\n]+)"?/m.exec(readFileSync74(path, "utf8"));
|
|
256676
256774
|
return match?.[1] ?? null;
|
|
256677
256775
|
}
|
|
256678
256776
|
function existsProjectPath2(projectDir, target) {
|
|
256679
|
-
return
|
|
256777
|
+
return existsSync81(join84(projectDir, target.replace(/\/$/, "")));
|
|
256680
256778
|
}
|
|
256681
256779
|
function createIfMissing(projectDir, target) {
|
|
256682
256780
|
const exists = existsProjectPath2(projectDir, target);
|
|
@@ -256707,9 +256805,9 @@ function mergeSections(projectDir, target) {
|
|
|
256707
256805
|
}
|
|
256708
256806
|
function gitignoreOperation(projectDir) {
|
|
256709
256807
|
const target = ".gitignore";
|
|
256710
|
-
const path =
|
|
256711
|
-
const exists =
|
|
256712
|
-
const hasEntry = exists &&
|
|
256808
|
+
const path = join84(projectDir, target);
|
|
256809
|
+
const exists = existsSync81(path);
|
|
256810
|
+
const hasEntry = exists && readFileSync74(path, "utf8").split("\n").includes(".roll/");
|
|
256713
256811
|
return {
|
|
256714
256812
|
action: hasEntry ? "keep" : "append",
|
|
256715
256813
|
target,
|
|
@@ -256764,9 +256862,9 @@ function renderOnboardApplyReview(operations, labels = DEFAULT_ONBOARD_APPLY_REV
|
|
|
256764
256862
|
// packages/cli/dist/lib/interactive-agent.js
|
|
256765
256863
|
init_dist2();
|
|
256766
256864
|
init_dist();
|
|
256767
|
-
import { accessSync as accessSync4, constants as constants4, existsSync as
|
|
256865
|
+
import { accessSync as accessSync4, constants as constants4, existsSync as existsSync82, readFileSync as readFileSync75, readSync as readSync2, statSync as statSync27 } from "node:fs";
|
|
256768
256866
|
import { homedir as homedir23 } from "node:os";
|
|
256769
|
-
import { delimiter as delimiter4, join as
|
|
256867
|
+
import { delimiter as delimiter4, join as join85 } from "node:path";
|
|
256770
256868
|
function expandHome(path) {
|
|
256771
256869
|
const home = process.env["HOME"] ?? homedir23();
|
|
256772
256870
|
return path.replace(/^~/, home);
|
|
@@ -256777,7 +256875,7 @@ function agentEnvFromEnv(envDict) {
|
|
|
256777
256875
|
for (const dir of pathEnv.split(delimiter4)) {
|
|
256778
256876
|
if (dir === "")
|
|
256779
256877
|
continue;
|
|
256780
|
-
const p =
|
|
256878
|
+
const p = join85(dir, bin);
|
|
256781
256879
|
try {
|
|
256782
256880
|
const st = statSync27(p);
|
|
256783
256881
|
if (!st.isFile())
|
|
@@ -256792,7 +256890,7 @@ function agentEnvFromEnv(envDict) {
|
|
|
256792
256890
|
return {
|
|
256793
256891
|
home: envDict["HOME"] ?? homedir23(),
|
|
256794
256892
|
commandOnPath: commandOnPath4,
|
|
256795
|
-
dirExists: (p) =>
|
|
256893
|
+
dirExists: (p) => existsSync82(p),
|
|
256796
256894
|
fileExecutable: (p) => {
|
|
256797
256895
|
try {
|
|
256798
256896
|
accessSync4(p, constants4.X_OK);
|
|
@@ -256807,10 +256905,10 @@ function discoverInteractiveAgents(agentEnv) {
|
|
|
256807
256905
|
const installed = [];
|
|
256808
256906
|
const missing = [];
|
|
256809
256907
|
const cfg = rollConfig();
|
|
256810
|
-
if (!
|
|
256908
|
+
if (!existsSync82(cfg))
|
|
256811
256909
|
return { installed, missing };
|
|
256812
256910
|
const env = agentEnv ?? realAgentEnv();
|
|
256813
|
-
for (const line of
|
|
256911
|
+
for (const line of readFileSync75(cfg, "utf8").split("\n")) {
|
|
256814
256912
|
const match = /^(ai_[^:]+):\s*(.*)$/.exec(line);
|
|
256815
256913
|
if (match === null)
|
|
256816
256914
|
continue;
|
|
@@ -256827,9 +256925,9 @@ function discoverInteractiveAgents(agentEnv) {
|
|
|
256827
256925
|
}
|
|
256828
256926
|
function readPrimaryAgent() {
|
|
256829
256927
|
const cfg = rollConfig();
|
|
256830
|
-
if (!
|
|
256928
|
+
if (!existsSync82(cfg))
|
|
256831
256929
|
return null;
|
|
256832
|
-
for (const line of
|
|
256930
|
+
for (const line of readFileSync75(cfg, "utf8").split("\n")) {
|
|
256833
256931
|
const m7 = /^primary_agent:\s*(.*)$/.exec(line);
|
|
256834
256932
|
if (m7 !== null) {
|
|
256835
256933
|
const v = (m7[1] ?? "").replace(/\s*#.*$/, "").trim();
|
|
@@ -256840,10 +256938,10 @@ function readPrimaryAgent() {
|
|
|
256840
256938
|
return null;
|
|
256841
256939
|
}
|
|
256842
256940
|
function readSkillBody2(skillName) {
|
|
256843
|
-
const skillFile =
|
|
256844
|
-
if (!
|
|
256941
|
+
const skillFile = join85(rollPkgDir(), "skills", skillName, "SKILL.md");
|
|
256942
|
+
if (!existsSync82(skillFile))
|
|
256845
256943
|
return null;
|
|
256846
|
-
return
|
|
256944
|
+
return readFileSync75(skillFile, "utf8").replace(/^---\n[\s\S]*?\n---\n?/, "").trim();
|
|
256847
256945
|
}
|
|
256848
256946
|
function kimiBin() {
|
|
256849
256947
|
if (onPath("kimi-code"))
|
|
@@ -257065,43 +257163,43 @@ function initMergeSummaryTitle() {
|
|
|
257065
257163
|
return msgLang6() === "zh" ? "Roll \u7EA6\u5B9A\u540C\u6B65\u6458\u8981" : "Roll convention sync summary";
|
|
257066
257164
|
}
|
|
257067
257165
|
function rollHome3() {
|
|
257068
|
-
return process.env["ROLL_HOME"] ??
|
|
257166
|
+
return process.env["ROLL_HOME"] ?? join86(homedir24(), ".roll");
|
|
257069
257167
|
}
|
|
257070
257168
|
function rollGlobal2() {
|
|
257071
|
-
return
|
|
257169
|
+
return join86(rollHome3(), "conventions", "global");
|
|
257072
257170
|
}
|
|
257073
257171
|
function rollTemplates2() {
|
|
257074
|
-
return
|
|
257172
|
+
return join86(rollHome3(), "conventions", "templates");
|
|
257075
257173
|
}
|
|
257076
257174
|
function scanProjectType(dir) {
|
|
257077
257175
|
let hasFrontend = false;
|
|
257078
257176
|
let hasBackend = false;
|
|
257079
257177
|
let hasCli = false;
|
|
257080
|
-
const pkg =
|
|
257178
|
+
const pkg = join86(dir, "package.json");
|
|
257081
257179
|
const readPkg = () => {
|
|
257082
257180
|
try {
|
|
257083
|
-
return
|
|
257181
|
+
return readFileSync76(pkg, "utf8");
|
|
257084
257182
|
} catch {
|
|
257085
257183
|
return "";
|
|
257086
257184
|
}
|
|
257087
257185
|
};
|
|
257088
|
-
if (
|
|
257186
|
+
if (existsSync83(pkg)) {
|
|
257089
257187
|
if (/"react"|"vue"|"next"|"nuxt"|"vite"|"svelte"/i.test(readPkg()))
|
|
257090
257188
|
hasFrontend = true;
|
|
257091
257189
|
}
|
|
257092
|
-
if (["src", "app", "pages", "components"].some((d) =>
|
|
257190
|
+
if (["src", "app", "pages", "components"].some((d) => existsSync83(join86(dir, d))))
|
|
257093
257191
|
hasFrontend = true;
|
|
257094
|
-
if (["server", "api", "backend"].some((d) =>
|
|
257192
|
+
if (["server", "api", "backend"].some((d) => existsSync83(join86(dir, d))))
|
|
257095
257193
|
hasBackend = true;
|
|
257096
|
-
if (["go.mod", "main.go", "main.py", "app.py", "Cargo.toml", "requirements.txt", "pyproject.toml"].some((f) =>
|
|
257194
|
+
if (["go.mod", "main.go", "main.py", "app.py", "Cargo.toml", "requirements.txt", "pyproject.toml"].some((f) => existsSync83(join86(dir, f))))
|
|
257097
257195
|
hasBackend = true;
|
|
257098
|
-
if (
|
|
257196
|
+
if (existsSync83(pkg)) {
|
|
257099
257197
|
if (/"prisma"|"@prisma\/client"|"typeorm"|"sequelize"|"mongoose"|"drizzle-orm"|"@neondatabase\/serverless"|"pg"|"mysql2"|"mongodb"|"redis"|"ioredis"|"express"|"fastify"|"koa"|"hapi"|"@hapi\/hapi"|"apollo-server"|"graphql-yoga"|"trpc"/i.test(readPkg()))
|
|
257100
257198
|
hasBackend = true;
|
|
257101
257199
|
}
|
|
257102
|
-
if (
|
|
257200
|
+
if (existsSync83(join86(dir, "prisma", "schema.prisma")))
|
|
257103
257201
|
hasBackend = true;
|
|
257104
|
-
if (
|
|
257202
|
+
if (existsSync83(join86(dir, "bin")) || existsSync83(join86(dir, "cmd")))
|
|
257105
257203
|
hasCli = true;
|
|
257106
257204
|
if (hasFrontend && hasBackend)
|
|
257107
257205
|
return "fullstack";
|
|
@@ -257137,18 +257235,18 @@ function readLineFromStdin2() {
|
|
|
257137
257235
|
return Buffer.from(chunks).toString("utf8");
|
|
257138
257236
|
}
|
|
257139
257237
|
function mergeGlobalToProject(projectDir, summary) {
|
|
257140
|
-
const src =
|
|
257141
|
-
const dst =
|
|
257142
|
-
if (!
|
|
257238
|
+
const src = join86(rollGlobal2(), "AGENTS.md");
|
|
257239
|
+
const dst = join86(projectDir, "AGENTS.md");
|
|
257240
|
+
if (!existsSync83(src)) {
|
|
257143
257241
|
return;
|
|
257144
257242
|
}
|
|
257145
257243
|
const projectType = scanProjectType(projectDir);
|
|
257146
257244
|
const skipFrontend = ["cli", "backend-service", "unknown"].includes(projectType);
|
|
257147
257245
|
const FRONTEND_HEAD = "## 7. Frontend Default Stack";
|
|
257148
|
-
const srcText =
|
|
257246
|
+
const srcText = readFileSync76(src, "utf8");
|
|
257149
257247
|
const srcLines = srcText.split("\n");
|
|
257150
257248
|
const lines2 = srcText.endsWith("\n") ? srcLines.slice(0, -1) : srcLines;
|
|
257151
|
-
if (!
|
|
257249
|
+
if (!existsSync83(dst)) {
|
|
257152
257250
|
let out3 = "";
|
|
257153
257251
|
let fcH = "";
|
|
257154
257252
|
let fcB = "";
|
|
@@ -257181,7 +257279,7 @@ ${fcB}`;
|
|
|
257181
257279
|
summary.push("created|AGENTS.md");
|
|
257182
257280
|
return;
|
|
257183
257281
|
}
|
|
257184
|
-
const dstText =
|
|
257282
|
+
const dstText = readFileSync76(dst, "utf8");
|
|
257185
257283
|
let added = 0;
|
|
257186
257284
|
let curH = "";
|
|
257187
257285
|
let curB = "";
|
|
@@ -257221,20 +257319,20 @@ ${curB}`;
|
|
|
257221
257319
|
}
|
|
257222
257320
|
function mergeClaudeToProject(projectDir, summary) {
|
|
257223
257321
|
const projectType = scanProjectType(projectDir);
|
|
257224
|
-
const tplFile =
|
|
257225
|
-
if (!
|
|
257322
|
+
const tplFile = join86(rollTemplates2(), projectType, "CLAUDE.md");
|
|
257323
|
+
if (!existsSync83(tplFile))
|
|
257226
257324
|
return;
|
|
257227
|
-
const claudeDir =
|
|
257228
|
-
const outFile =
|
|
257229
|
-
|
|
257230
|
-
if (!
|
|
257231
|
-
writeFileAtomic(outFile,
|
|
257325
|
+
const claudeDir = join86(projectDir, ".claude");
|
|
257326
|
+
const outFile = join86(claudeDir, "CLAUDE.md");
|
|
257327
|
+
mkdirSync35(claudeDir, { recursive: true });
|
|
257328
|
+
if (!existsSync83(outFile)) {
|
|
257329
|
+
writeFileAtomic(outFile, readFileSync76(tplFile, "utf8"));
|
|
257232
257330
|
summary.push("created|.claude/CLAUDE.md");
|
|
257233
257331
|
return;
|
|
257234
257332
|
}
|
|
257235
|
-
const tplText =
|
|
257333
|
+
const tplText = readFileSync76(tplFile, "utf8");
|
|
257236
257334
|
const lines2 = tplText.endsWith("\n") ? tplText.split("\n").slice(0, -1) : tplText.split("\n");
|
|
257237
|
-
const outText =
|
|
257335
|
+
const outText = readFileSync76(outFile, "utf8");
|
|
257238
257336
|
let added = 0;
|
|
257239
257337
|
let curH = "";
|
|
257240
257338
|
let curB = "";
|
|
@@ -257278,20 +257376,20 @@ var BACKLOG_TEMPLATE = `# Project Backlog
|
|
|
257278
257376
|
|----|---------|--------|
|
|
257279
257377
|
`;
|
|
257280
257378
|
function writeBacklog(path, summary) {
|
|
257281
|
-
if (
|
|
257379
|
+
if (existsSync83(path)) {
|
|
257282
257380
|
summary.push("unchanged|.roll/backlog.md");
|
|
257283
257381
|
return;
|
|
257284
257382
|
}
|
|
257285
|
-
|
|
257383
|
+
mkdirSync35(dirname36(path), { recursive: true });
|
|
257286
257384
|
writeFileAtomic(path, BACKLOG_TEMPLATE);
|
|
257287
257385
|
summary.push("created|.roll/backlog.md");
|
|
257288
257386
|
}
|
|
257289
257387
|
function ensureFeaturesDir(path, summary) {
|
|
257290
|
-
if (
|
|
257388
|
+
if (existsSync83(path) && statSync28(path).isDirectory()) {
|
|
257291
257389
|
summary.push("unchanged|.roll/features/");
|
|
257292
257390
|
return;
|
|
257293
257391
|
}
|
|
257294
|
-
|
|
257392
|
+
mkdirSync35(path, { recursive: true });
|
|
257295
257393
|
summary.push("created|.roll/features/");
|
|
257296
257394
|
}
|
|
257297
257395
|
var FEATURES_TEMPLATE = `# Features
|
|
@@ -257305,11 +257403,11 @@ var FEATURES_TEMPLATE = `# Features
|
|
|
257305
257403
|
<!-- Add feature entries here as epics are completed -->
|
|
257306
257404
|
`;
|
|
257307
257405
|
function writeFeaturesMd(path, summary) {
|
|
257308
|
-
if (
|
|
257406
|
+
if (existsSync83(path)) {
|
|
257309
257407
|
summary.push("unchanged|.roll/features.md");
|
|
257310
257408
|
return;
|
|
257311
257409
|
}
|
|
257312
|
-
|
|
257410
|
+
mkdirSync35(dirname36(path), { recursive: true });
|
|
257313
257411
|
writeFileAtomic(path, FEATURES_TEMPLATE);
|
|
257314
257412
|
summary.push("created|.roll/features.md");
|
|
257315
257413
|
}
|
|
@@ -257332,23 +257430,23 @@ defaults:
|
|
|
257332
257430
|
strategy: seeded-random
|
|
257333
257431
|
`;
|
|
257334
257432
|
function initSeedProjectAgents(projectDir, summary) {
|
|
257335
|
-
const dest =
|
|
257336
|
-
if (
|
|
257433
|
+
const dest = join86(projectDir, ".roll", "agents.yaml");
|
|
257434
|
+
if (existsSync83(dest)) {
|
|
257337
257435
|
summary.push("unchanged|.roll/agents.yaml");
|
|
257338
257436
|
return 0;
|
|
257339
257437
|
}
|
|
257340
|
-
|
|
257438
|
+
mkdirSync35(dirname36(dest), { recursive: true });
|
|
257341
257439
|
writeFileAtomic(dest, PROJECT_AGENTS_TEMPLATE);
|
|
257342
257440
|
summary.push("created|.roll/agents.yaml");
|
|
257343
257441
|
return 0;
|
|
257344
257442
|
}
|
|
257345
257443
|
function writeVersionStamp(projectDir, summary) {
|
|
257346
|
-
const stampPath =
|
|
257347
|
-
if (
|
|
257444
|
+
const stampPath = join86(projectDir, ".roll", ".version");
|
|
257445
|
+
if (existsSync83(stampPath)) {
|
|
257348
257446
|
summary.push("unchanged|.roll/.version");
|
|
257349
257447
|
return;
|
|
257350
257448
|
}
|
|
257351
|
-
|
|
257449
|
+
mkdirSync35(join86(projectDir, ".roll"), { recursive: true });
|
|
257352
257450
|
const installedAt = (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
257353
257451
|
writeFileAtomic(stampPath, `# Roll project version stamp \u2014 written by \`roll init\` (US-ONBOARD-019).
|
|
257354
257452
|
# Used by \`_check_structure\` to recognise a previously-onboarded Roll project
|
|
@@ -257371,7 +257469,7 @@ var ROLL_MERGE_END = "<!-- roll:onboard:end -->";
|
|
|
257371
257469
|
function writeFileAtomic(path, text2) {
|
|
257372
257470
|
const tmp = `${path}.tmp-${process.pid}-${Date.now()}`;
|
|
257373
257471
|
try {
|
|
257374
|
-
|
|
257472
|
+
writeFileSync37(tmp, text2);
|
|
257375
257473
|
renameSync14(tmp, path);
|
|
257376
257474
|
} catch (error) {
|
|
257377
257475
|
rmSync14(tmp, { force: true });
|
|
@@ -257384,7 +257482,7 @@ ${text2.replace(/^\n+/, "")}${ROLL_MERGE_END}
|
|
|
257384
257482
|
`;
|
|
257385
257483
|
}
|
|
257386
257484
|
function changesetPath(projectDir) {
|
|
257387
|
-
return
|
|
257485
|
+
return join86(projectDir, ".roll", "onboard-changeset.yaml");
|
|
257388
257486
|
}
|
|
257389
257487
|
function isoNow() {
|
|
257390
257488
|
return (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
@@ -257406,7 +257504,7 @@ roll_version: "${changeset.rollVersion}"
|
|
|
257406
257504
|
}
|
|
257407
257505
|
function writeChangeset(projectDir, changeset) {
|
|
257408
257506
|
const path = changesetPath(projectDir);
|
|
257409
|
-
|
|
257507
|
+
mkdirSync35(dirname36(path), { recursive: true });
|
|
257410
257508
|
writeFileAtomic(path, renderChangeset(changeset));
|
|
257411
257509
|
}
|
|
257412
257510
|
function emptyChangesetLists() {
|
|
@@ -257422,10 +257520,10 @@ function emptyChangesetLists() {
|
|
|
257422
257520
|
function readExistingChangeset(projectDir) {
|
|
257423
257521
|
const path = changesetPath(projectDir);
|
|
257424
257522
|
const parsed = emptyChangesetLists();
|
|
257425
|
-
if (!
|
|
257523
|
+
if (!existsSync83(path))
|
|
257426
257524
|
return parsed;
|
|
257427
257525
|
let current = null;
|
|
257428
|
-
for (const rawLine of
|
|
257526
|
+
for (const rawLine of readFileSync76(path, "utf8").split("\n")) {
|
|
257429
257527
|
const itemMatch = /^\s+-\s+(.*)$/.exec(rawLine);
|
|
257430
257528
|
if (itemMatch && current !== null) {
|
|
257431
257529
|
let value = (itemMatch[1] ?? "").trim();
|
|
@@ -257584,9 +257682,9 @@ function maybeFailApplyAfter(label4) {
|
|
|
257584
257682
|
}
|
|
257585
257683
|
}
|
|
257586
257684
|
function seedBacklogRow(backlog, heading, row2, id) {
|
|
257587
|
-
if (!
|
|
257685
|
+
if (!existsSync83(backlog))
|
|
257588
257686
|
return false;
|
|
257589
|
-
const text2 =
|
|
257687
|
+
const text2 = readFileSync76(backlog, "utf8");
|
|
257590
257688
|
if (text2.includes(`| ${id} |`))
|
|
257591
257689
|
return false;
|
|
257592
257690
|
const lines2 = text2.split("\n");
|
|
@@ -257633,11 +257731,11 @@ function confirmSeed(count, noun, ids, titles) {
|
|
|
257633
257731
|
return reply === "y" || reply === "Y" || reply === "yes" || reply === "YES";
|
|
257634
257732
|
}
|
|
257635
257733
|
function renderAndSeed(projectDir, plan, changeset) {
|
|
257636
|
-
const renderer =
|
|
257637
|
-
if (!
|
|
257734
|
+
const renderer = join86(rollPkgDir(), "lib", "roll-onboard-render.py");
|
|
257735
|
+
if (!existsSync83(renderer))
|
|
257638
257736
|
return;
|
|
257639
257737
|
const knownRenderedFiles = [".roll/domain/context-map.md", ".roll/tech-analysis.md", ".roll/test-assessment.md"];
|
|
257640
|
-
const existedBefore = new Set(knownRenderedFiles.filter((file) =>
|
|
257738
|
+
const existedBefore = new Set(knownRenderedFiles.filter((file) => existsSync83(join86(projectDir, file))));
|
|
257641
257739
|
const r = spawnSync10("python3", [renderer, plan, projectDir], { encoding: "utf8" });
|
|
257642
257740
|
if (r.status === 2)
|
|
257643
257741
|
return;
|
|
@@ -257667,9 +257765,9 @@ function renderAndSeed(projectDir, plan, changeset) {
|
|
|
257667
257765
|
fixTitles.push(b);
|
|
257668
257766
|
}
|
|
257669
257767
|
}
|
|
257670
|
-
const backlog =
|
|
257768
|
+
const backlog = join86(projectDir, ".roll", "backlog.md");
|
|
257671
257769
|
if (seedIds.length > 0) {
|
|
257672
|
-
if (!
|
|
257770
|
+
if (!existsSync83(backlog))
|
|
257673
257771
|
info3(m3("init.onboard_seed_no_backlog"));
|
|
257674
257772
|
else if (confirmSeed(seedIds.length, "story", seedIds, seedTitles)) {
|
|
257675
257773
|
let seeded = 0;
|
|
@@ -257682,7 +257780,7 @@ function renderAndSeed(projectDir, plan, changeset) {
|
|
|
257682
257780
|
info3(m3("init.onboard_seed_cancelled"));
|
|
257683
257781
|
}
|
|
257684
257782
|
if (fixIds.length > 0) {
|
|
257685
|
-
if (!
|
|
257783
|
+
if (!existsSync83(backlog))
|
|
257686
257784
|
info3(m3("init.onboard_seed_no_backlog"));
|
|
257687
257785
|
else if (confirmSeed(fixIds.length, "fix", fixIds, fixTitles)) {
|
|
257688
257786
|
let seeded = 0;
|
|
@@ -257696,8 +257794,8 @@ function renderAndSeed(projectDir, plan, changeset) {
|
|
|
257696
257794
|
}
|
|
257697
257795
|
}
|
|
257698
257796
|
function addRollToGitignore(projectDir, changeset) {
|
|
257699
|
-
const gi =
|
|
257700
|
-
const current =
|
|
257797
|
+
const gi = join86(projectDir, ".gitignore");
|
|
257798
|
+
const current = existsSync83(gi) ? readFileSync76(gi, "utf8") : "";
|
|
257701
257799
|
if (current.split("\n").includes(".roll/"))
|
|
257702
257800
|
return;
|
|
257703
257801
|
writeFileAtomic(gi, current + (current === "" || current.endsWith("\n") ? "" : "\n") + ".roll/\n");
|
|
@@ -257709,7 +257807,7 @@ function applyIsInteractive(opts) {
|
|
|
257709
257807
|
}
|
|
257710
257808
|
function claudeTemplateAvailable(projectDir) {
|
|
257711
257809
|
const projectType = scanProjectType(projectDir);
|
|
257712
|
-
return
|
|
257810
|
+
return existsSync83(join86(rollTemplates2(), projectType, "CLAUDE.md"));
|
|
257713
257811
|
}
|
|
257714
257812
|
function projectAgentsConfigEnabled(templateName) {
|
|
257715
257813
|
return templateName !== "skip";
|
|
@@ -257812,16 +257910,16 @@ function confirmRepair(operations, opts) {
|
|
|
257812
257910
|
return confirmed;
|
|
257813
257911
|
}
|
|
257814
257912
|
function recordCreatedFileIfNeeded(projectDir, changeset, rel, existed) {
|
|
257815
|
-
if (!existed &&
|
|
257913
|
+
if (!existed && existsSync83(join86(projectDir, rel)))
|
|
257816
257914
|
recordChangeset(projectDir, changeset, "files_created", rel);
|
|
257817
257915
|
}
|
|
257818
257916
|
function recordCreatedDirIfNeeded(projectDir, changeset, rel, existed) {
|
|
257819
|
-
if (!existed &&
|
|
257917
|
+
if (!existed && existsSync83(join86(projectDir, rel)))
|
|
257820
257918
|
recordChangeset(projectDir, changeset, "dirs_created", rel);
|
|
257821
257919
|
}
|
|
257822
257920
|
function repairBlocker(projectDir) {
|
|
257823
|
-
const featuresDir =
|
|
257824
|
-
if (
|
|
257921
|
+
const featuresDir = join86(projectDir, ".roll", "features");
|
|
257922
|
+
if (existsSync83(featuresDir) && !statSync28(featuresDir).isDirectory()) {
|
|
257825
257923
|
return ".roll/features exists but is not a directory. Move or rename it, then rerun `roll init --repair --auto`.";
|
|
257826
257924
|
}
|
|
257827
257925
|
return null;
|
|
@@ -257846,7 +257944,7 @@ function initRepair(projectDir, facts, diagnosis2, opts = {}) {
|
|
|
257846
257944
|
err9(blocker2);
|
|
257847
257945
|
return 1;
|
|
257848
257946
|
}
|
|
257849
|
-
if (!
|
|
257947
|
+
if (!existsSync83(rollTemplates2())) {
|
|
257850
257948
|
err9(m3("init.no_templates_found_run_roll_setup_2"));
|
|
257851
257949
|
return 1;
|
|
257852
257950
|
}
|
|
@@ -257856,20 +257954,20 @@ function initRepair(projectDir, facts, diagnosis2, opts = {}) {
|
|
|
257856
257954
|
process.stdout.write("\nREPAIR \xB7 Partial Roll repair\n");
|
|
257857
257955
|
mergeGlobalToProject(projectDir, summary);
|
|
257858
257956
|
recordSummaryOwnership(projectDir, changeset, summary, "AGENTS.md");
|
|
257859
|
-
const backlog =
|
|
257860
|
-
const backlogExisted =
|
|
257957
|
+
const backlog = join86(projectDir, ".roll", "backlog.md");
|
|
257958
|
+
const backlogExisted = existsSync83(backlog);
|
|
257861
257959
|
writeBacklog(backlog, summary);
|
|
257862
257960
|
recordCreatedFileIfNeeded(projectDir, changeset, ".roll/backlog.md", backlogExisted);
|
|
257863
|
-
const featuresDir =
|
|
257864
|
-
const featuresDirExisted =
|
|
257961
|
+
const featuresDir = join86(projectDir, ".roll", "features");
|
|
257962
|
+
const featuresDirExisted = existsSync83(featuresDir);
|
|
257865
257963
|
ensureFeaturesDir(featuresDir, summary);
|
|
257866
257964
|
recordCreatedDirIfNeeded(projectDir, changeset, ".roll/features", featuresDirExisted);
|
|
257867
|
-
const featuresMd =
|
|
257868
|
-
const featuresMdExisted =
|
|
257965
|
+
const featuresMd = join86(projectDir, ".roll", "features.md");
|
|
257966
|
+
const featuresMdExisted = existsSync83(featuresMd);
|
|
257869
257967
|
writeFeaturesMd(featuresMd, summary);
|
|
257870
257968
|
recordCreatedFileIfNeeded(projectDir, changeset, ".roll/features.md", featuresMdExisted);
|
|
257871
|
-
const stamp =
|
|
257872
|
-
const stampExisted =
|
|
257969
|
+
const stamp = join86(projectDir, ".roll", ".version");
|
|
257970
|
+
const stampExisted = existsSync83(stamp);
|
|
257873
257971
|
writeVersionStamp(projectDir, summary);
|
|
257874
257972
|
recordCreatedFileIfNeeded(projectDir, changeset, ".roll/.version", stampExisted);
|
|
257875
257973
|
printMergeSummary(summary);
|
|
@@ -257877,9 +257975,9 @@ function initRepair(projectDir, facts, diagnosis2, opts = {}) {
|
|
|
257877
257975
|
return 0;
|
|
257878
257976
|
}
|
|
257879
257977
|
function initApply(projectDir, opts = {}) {
|
|
257880
|
-
const plan =
|
|
257881
|
-
const validator =
|
|
257882
|
-
if (!
|
|
257978
|
+
const plan = join86(projectDir, ".roll", "onboard-plan.yaml");
|
|
257979
|
+
const validator = join86(rollPkgDir(), "lib", "roll-plan-validate.py");
|
|
257980
|
+
if (!existsSync83(plan)) {
|
|
257883
257981
|
err9(m3("init.no_onboard_plan_found_at_roll"));
|
|
257884
257982
|
process.stderr.write("\n");
|
|
257885
257983
|
process.stderr.write(" Run $roll-onboard in your AI agent first to generate the plan.\n");
|
|
@@ -257887,7 +257985,7 @@ function initApply(projectDir, opts = {}) {
|
|
|
257887
257985
|
`);
|
|
257888
257986
|
return 1;
|
|
257889
257987
|
}
|
|
257890
|
-
if (!
|
|
257988
|
+
if (!existsSync83(validator)) {
|
|
257891
257989
|
err9(m3("init.plan_validator_missing", validator));
|
|
257892
257990
|
return 1;
|
|
257893
257991
|
}
|
|
@@ -257932,51 +258030,51 @@ function initApply(projectDir, opts = {}) {
|
|
|
257932
258030
|
recordSummaryOwnership(projectDir, changeset, summary, "AGENTS.md");
|
|
257933
258031
|
mergeClaudeToProject(projectDir, summary);
|
|
257934
258032
|
recordSummaryOwnership(projectDir, changeset, summary, ".claude/CLAUDE.md");
|
|
257935
|
-
const stamp =
|
|
257936
|
-
const stampExisted =
|
|
258033
|
+
const stamp = join86(projectDir, ".roll", ".version");
|
|
258034
|
+
const stampExisted = existsSync83(stamp);
|
|
257937
258035
|
writeVersionStamp(projectDir, summary);
|
|
257938
|
-
if (!stampExisted &&
|
|
258036
|
+
if (!stampExisted && existsSync83(stamp))
|
|
257939
258037
|
recordChangeset(projectDir, changeset, "files_created", ".roll/.version");
|
|
257940
258038
|
const approved = new Set(fields2.approved);
|
|
257941
258039
|
if (approved.has("backlog")) {
|
|
257942
|
-
const backlogPath =
|
|
257943
|
-
const existed =
|
|
258040
|
+
const backlogPath = join86(projectDir, ".roll", "backlog.md");
|
|
258041
|
+
const existed = existsSync83(backlogPath);
|
|
257944
258042
|
writeBacklog(backlogPath, summary);
|
|
257945
|
-
if (!existed &&
|
|
258043
|
+
if (!existed && existsSync83(backlogPath))
|
|
257946
258044
|
recordChangeset(projectDir, changeset, "files_created", ".roll/backlog.md");
|
|
257947
258045
|
maybeFailApplyAfter("backlog");
|
|
257948
258046
|
}
|
|
257949
258047
|
if (routesTemplate !== "skip") {
|
|
257950
|
-
const routesPath =
|
|
257951
|
-
const existed =
|
|
257952
|
-
if (initSeedProjectAgents(projectDir, summary) === 0 && !existed &&
|
|
258048
|
+
const routesPath = join86(projectDir, ".roll", "agents.yaml");
|
|
258049
|
+
const existed = existsSync83(routesPath);
|
|
258050
|
+
if (initSeedProjectAgents(projectDir, summary) === 0 && !existed && existsSync83(routesPath)) {
|
|
257953
258051
|
recordChangeset(projectDir, changeset, "files_created", ".roll/agents.yaml");
|
|
257954
258052
|
}
|
|
257955
258053
|
}
|
|
257956
258054
|
if (approved.has("features")) {
|
|
257957
|
-
const featuresDir =
|
|
257958
|
-
const featuresMd =
|
|
257959
|
-
const dirExisted =
|
|
257960
|
-
const mdExisted =
|
|
258055
|
+
const featuresDir = join86(projectDir, ".roll", "features");
|
|
258056
|
+
const featuresMd = join86(projectDir, ".roll", "features.md");
|
|
258057
|
+
const dirExisted = existsSync83(featuresDir);
|
|
258058
|
+
const mdExisted = existsSync83(featuresMd);
|
|
257961
258059
|
ensureFeaturesDir(featuresDir, summary);
|
|
257962
258060
|
writeFeaturesMd(featuresMd, summary);
|
|
257963
|
-
if (!dirExisted &&
|
|
258061
|
+
if (!dirExisted && existsSync83(featuresDir))
|
|
257964
258062
|
recordChangeset(projectDir, changeset, "dirs_created", ".roll/features");
|
|
257965
|
-
if (!mdExisted &&
|
|
258063
|
+
if (!mdExisted && existsSync83(featuresMd))
|
|
257966
258064
|
recordChangeset(projectDir, changeset, "files_created", ".roll/features.md");
|
|
257967
258065
|
}
|
|
257968
258066
|
if (approved.has("domain")) {
|
|
257969
|
-
const path =
|
|
257970
|
-
const existed =
|
|
257971
|
-
|
|
257972
|
-
if (!existed &&
|
|
258067
|
+
const path = join86(projectDir, ".roll", "domain");
|
|
258068
|
+
const existed = existsSync83(path);
|
|
258069
|
+
mkdirSync35(path, { recursive: true });
|
|
258070
|
+
if (!existed && existsSync83(path))
|
|
257973
258071
|
recordChangeset(projectDir, changeset, "dirs_created", ".roll/domain");
|
|
257974
258072
|
}
|
|
257975
258073
|
if (approved.has("briefs")) {
|
|
257976
|
-
const path =
|
|
257977
|
-
const existed =
|
|
257978
|
-
|
|
257979
|
-
if (!existed &&
|
|
258074
|
+
const path = join86(projectDir, ".roll", "briefs");
|
|
258075
|
+
const existed = existsSync83(path);
|
|
258076
|
+
mkdirSync35(path, { recursive: true });
|
|
258077
|
+
if (!existed && existsSync83(path))
|
|
257980
258078
|
recordChangeset(projectDir, changeset, "dirs_created", ".roll/briefs");
|
|
257981
258079
|
}
|
|
257982
258080
|
renderAndSeed(projectDir, plan, changeset);
|
|
@@ -258288,8 +258386,8 @@ var PRD_ONLY_SMOKE_FILES = [
|
|
|
258288
258386
|
function printSmokeCreatedFiles(projectDir) {
|
|
258289
258387
|
process.stdout.write("\nCreated files:\n");
|
|
258290
258388
|
for (const rel of PRD_ONLY_SMOKE_FILES) {
|
|
258291
|
-
const path = rel.endsWith("/") ?
|
|
258292
|
-
if (
|
|
258389
|
+
const path = rel.endsWith("/") ? join86(projectDir, rel.slice(0, -1)) : join86(projectDir, rel);
|
|
258390
|
+
if (existsSync83(path))
|
|
258293
258391
|
process.stdout.write(` - ${rel}
|
|
258294
258392
|
`);
|
|
258295
258393
|
}
|
|
@@ -258297,16 +258395,16 @@ function printSmokeCreatedFiles(projectDir) {
|
|
|
258297
258395
|
function runPrdOnlyAttestSmoke() {
|
|
258298
258396
|
const originalCwd = process.cwd();
|
|
258299
258397
|
const originalRollHome = process.env["ROLL_HOME"];
|
|
258300
|
-
const workspace = realpathSync10(mkdtempSync6(
|
|
258398
|
+
const workspace = realpathSync10(mkdtempSync6(join86(tmpdir8(), "roll-init-attest-prd-only-")));
|
|
258301
258399
|
let status2 = 1;
|
|
258302
258400
|
try {
|
|
258303
|
-
const smokeHome =
|
|
258304
|
-
|
|
258305
|
-
cpSync(
|
|
258306
|
-
|
|
258401
|
+
const smokeHome = join86(workspace, ".roll-home");
|
|
258402
|
+
mkdirSync35(smokeHome, { recursive: true });
|
|
258403
|
+
cpSync(join86(rollPkgDir(), "conventions"), join86(smokeHome, "conventions"), { recursive: true });
|
|
258404
|
+
writeFileSync37(join86(smokeHome, "config.yaml"), "# Roll config\nlang: en\n");
|
|
258307
258405
|
process.env["ROLL_HOME"] = smokeHome;
|
|
258308
|
-
|
|
258309
|
-
|
|
258406
|
+
mkdirSync35(join86(workspace, "docs"), { recursive: true });
|
|
258407
|
+
writeFileSync37(join86(workspace, "docs", "intel-radar-PRD.md"), "# Intel Radar PRD\n\nBuild a radar for intelligence signals with source ranking and daily review.\n");
|
|
258310
258408
|
process.stdout.write("roll init attest smoke: prd-only\n");
|
|
258311
258409
|
process.stdout.write(`workspace: ${workspace}
|
|
258312
258410
|
`);
|
|
@@ -258322,18 +258420,18 @@ function runPrdOnlyAttestSmoke() {
|
|
|
258322
258420
|
else
|
|
258323
258421
|
process.env["ROLL_HOME"] = originalRollHome;
|
|
258324
258422
|
rmSync14(workspace, { recursive: true, force: true });
|
|
258325
|
-
process.stdout.write(`cleanup: ${
|
|
258423
|
+
process.stdout.write(`cleanup: ${existsSync83(workspace) ? "failed" : "removed"} ${workspace}
|
|
258326
258424
|
`);
|
|
258327
258425
|
}
|
|
258328
258426
|
}
|
|
258329
258427
|
var EXISTING_CODEBASE_SMOKE_FILES = ["README.md", "package.json", "src/index.ts", "tests/index.test.ts"];
|
|
258330
258428
|
function writeExistingCodebaseSmokeFixture(workspace) {
|
|
258331
|
-
|
|
258332
|
-
|
|
258333
|
-
|
|
258334
|
-
|
|
258335
|
-
|
|
258336
|
-
|
|
258429
|
+
writeFileSync37(join86(workspace, "README.md"), "# Existing App\n\nA service with real source and tests.\n");
|
|
258430
|
+
writeFileSync37(join86(workspace, "package.json"), '{"scripts":{"test":"vitest"}}\n');
|
|
258431
|
+
mkdirSync35(join86(workspace, "src"), { recursive: true });
|
|
258432
|
+
writeFileSync37(join86(workspace, "src", "index.ts"), "export const value = 1;\n");
|
|
258433
|
+
mkdirSync35(join86(workspace, "tests"), { recursive: true });
|
|
258434
|
+
writeFileSync37(join86(workspace, "tests", "index.test.ts"), "import { expect, it } from 'vitest';\nit('works', () => expect(1).toBe(1));\n");
|
|
258337
258435
|
}
|
|
258338
258436
|
function printExistingCodebaseSmokeTree(title = "Fixture tree") {
|
|
258339
258437
|
process.stdout.write(`
|
|
@@ -258358,7 +258456,7 @@ function printExistingCodebaseRollState(projectDir, title) {
|
|
|
258358
258456
|
${title}:
|
|
258359
258457
|
`);
|
|
258360
258458
|
for (const rel of EXISTING_CODEBASE_ROLL_SMOKE_FILES) {
|
|
258361
|
-
process.stdout.write(` ${rel}: ${
|
|
258459
|
+
process.stdout.write(` ${rel}: ${existsSync83(join86(projectDir, rel)) ? "present" : "missing"}
|
|
258362
258460
|
`);
|
|
258363
258461
|
}
|
|
258364
258462
|
}
|
|
@@ -258366,8 +258464,8 @@ function countText(text2, needle) {
|
|
|
258366
258464
|
return text2.split(needle).length - 1;
|
|
258367
258465
|
}
|
|
258368
258466
|
function runExistingCodebaseIdempotencyChecks(workspace) {
|
|
258369
|
-
const gitignore =
|
|
258370
|
-
const changeset =
|
|
258467
|
+
const gitignore = existsSync83(join86(workspace, ".gitignore")) ? readFileSync76(join86(workspace, ".gitignore"), "utf8") : "";
|
|
258468
|
+
const changeset = existsSync83(join86(workspace, ".roll", "onboard-changeset.yaml")) ? readFileSync76(join86(workspace, ".roll", "onboard-changeset.yaml"), "utf8") : "";
|
|
258371
258469
|
const gitignoreRollEntries = gitignore.split("\n").filter((line) => line === ".roll/").length;
|
|
258372
258470
|
const agentsEntries = countText(changeset, ' - "AGENTS.md"');
|
|
258373
258471
|
const claudeEntries = countText(changeset, ' - ".claude/CLAUDE.md"');
|
|
@@ -258389,8 +258487,8 @@ function runExistingCodebaseIdempotencyChecks(workspace) {
|
|
|
258389
258487
|
function runExistingCodebaseDiagnoseAttestSmoke() {
|
|
258390
258488
|
const originalCwd = process.cwd();
|
|
258391
258489
|
const originalPath = process.env["PATH"];
|
|
258392
|
-
const workspace = realpathSync10(mkdtempSync6(
|
|
258393
|
-
const emptyBin = realpathSync10(mkdtempSync6(
|
|
258490
|
+
const workspace = realpathSync10(mkdtempSync6(join86(tmpdir8(), "roll-init-attest-existing-codebase-")));
|
|
258491
|
+
const emptyBin = realpathSync10(mkdtempSync6(join86(tmpdir8(), "roll-init-attest-empty-bin-")));
|
|
258394
258492
|
let status2 = 1;
|
|
258395
258493
|
try {
|
|
258396
258494
|
writeExistingCodebaseSmokeFixture(workspace);
|
|
@@ -258411,7 +258509,7 @@ function runExistingCodebaseDiagnoseAttestSmoke() {
|
|
|
258411
258509
|
process.env["PATH"] = originalPath;
|
|
258412
258510
|
rmSync14(workspace, { recursive: true, force: true });
|
|
258413
258511
|
rmSync14(emptyBin, { recursive: true, force: true });
|
|
258414
|
-
process.stdout.write(`cleanup: ${
|
|
258512
|
+
process.stdout.write(`cleanup: ${existsSync83(workspace) ? "failed" : "removed"} ${workspace}
|
|
258415
258513
|
`);
|
|
258416
258514
|
}
|
|
258417
258515
|
}
|
|
@@ -258466,18 +258564,18 @@ agent:
|
|
|
258466
258564
|
function runExistingCodebaseInvalidPlanAttestSmoke() {
|
|
258467
258565
|
const originalCwd = process.cwd();
|
|
258468
258566
|
const originalRollHome = process.env["ROLL_HOME"];
|
|
258469
|
-
const workspace = realpathSync10(mkdtempSync6(
|
|
258567
|
+
const workspace = realpathSync10(mkdtempSync6(join86(tmpdir8(), "roll-init-invalid-plan-")));
|
|
258470
258568
|
const staleHash = "sha256:dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd";
|
|
258471
258569
|
try {
|
|
258472
|
-
const smokeHome =
|
|
258473
|
-
|
|
258474
|
-
cpSync(
|
|
258475
|
-
|
|
258570
|
+
const smokeHome = join86(workspace, ".roll-home");
|
|
258571
|
+
mkdirSync35(smokeHome, { recursive: true });
|
|
258572
|
+
cpSync(join86(rollPkgDir(), "conventions"), join86(smokeHome, "conventions"), { recursive: true });
|
|
258573
|
+
writeFileSync37(join86(smokeHome, "config.yaml"), "# Roll config\nlang: en\n");
|
|
258476
258574
|
process.env["ROLL_HOME"] = smokeHome;
|
|
258477
258575
|
writeExistingCodebaseSmokeFixture(workspace);
|
|
258478
|
-
|
|
258479
|
-
|
|
258480
|
-
|
|
258576
|
+
mkdirSync35(join86(workspace, ".roll"), { recursive: true });
|
|
258577
|
+
writeFileSync37(join86(workspace, ".roll", "init-diagnosis.yaml"), onboardDiagnosisFixture(staleHash));
|
|
258578
|
+
writeFileSync37(join86(workspace, ".roll", "onboard-plan.yaml"), onboardPlanFixture(staleHash));
|
|
258481
258579
|
process.stdout.write("roll init attest smoke: existing-codebase-invalid-plan\n");
|
|
258482
258580
|
process.stdout.write(`workspace: ${workspace}
|
|
258483
258581
|
`);
|
|
@@ -258488,11 +258586,11 @@ function runExistingCodebaseInvalidPlanAttestSmoke() {
|
|
|
258488
258586
|
const code = initCommand(["--apply", "--auto"]);
|
|
258489
258587
|
process.chdir(originalCwd);
|
|
258490
258588
|
process.stdout.write("\nPost-apply mutation check:\n");
|
|
258491
|
-
process.stdout.write(` AGENTS.md: ${
|
|
258589
|
+
process.stdout.write(` AGENTS.md: ${existsSync83(join86(workspace, "AGENTS.md")) ? "present" : "missing"}
|
|
258492
258590
|
`);
|
|
258493
|
-
process.stdout.write(` .roll/backlog.md: ${
|
|
258591
|
+
process.stdout.write(` .roll/backlog.md: ${existsSync83(join86(workspace, ".roll", "backlog.md")) ? "present" : "missing"}
|
|
258494
258592
|
`);
|
|
258495
|
-
process.stdout.write(` .gitignore: ${
|
|
258593
|
+
process.stdout.write(` .gitignore: ${existsSync83(join86(workspace, ".gitignore")) ? "present" : "missing"}
|
|
258496
258594
|
`);
|
|
258497
258595
|
return code === 0 ? 1 : 0;
|
|
258498
258596
|
} finally {
|
|
@@ -258502,25 +258600,25 @@ function runExistingCodebaseInvalidPlanAttestSmoke() {
|
|
|
258502
258600
|
else
|
|
258503
258601
|
process.env["ROLL_HOME"] = originalRollHome;
|
|
258504
258602
|
rmSync14(workspace, { recursive: true, force: true });
|
|
258505
|
-
process.stdout.write(`cleanup: ${
|
|
258603
|
+
process.stdout.write(`cleanup: ${existsSync83(workspace) ? "failed" : "removed"} ${workspace}
|
|
258506
258604
|
`);
|
|
258507
258605
|
}
|
|
258508
258606
|
}
|
|
258509
258607
|
function runExistingCodebaseReviewAttestSmoke() {
|
|
258510
258608
|
const originalCwd = process.cwd();
|
|
258511
258609
|
const originalRollHome = process.env["ROLL_HOME"];
|
|
258512
|
-
const workspace = realpathSync10(mkdtempSync6(
|
|
258610
|
+
const workspace = realpathSync10(mkdtempSync6(join86(tmpdir8(), "roll-init-review-")));
|
|
258513
258611
|
try {
|
|
258514
|
-
const smokeHome =
|
|
258515
|
-
|
|
258516
|
-
cpSync(
|
|
258517
|
-
|
|
258612
|
+
const smokeHome = join86(workspace, ".roll-home");
|
|
258613
|
+
mkdirSync35(smokeHome, { recursive: true });
|
|
258614
|
+
cpSync(join86(rollPkgDir(), "conventions"), join86(smokeHome, "conventions"), { recursive: true });
|
|
258615
|
+
writeFileSync37(join86(smokeHome, "config.yaml"), "# Roll config\nlang: en\n");
|
|
258518
258616
|
process.env["ROLL_HOME"] = smokeHome;
|
|
258519
258617
|
writeExistingCodebaseSmokeFixture(workspace);
|
|
258520
258618
|
const factsHash = computeInitFactsHash(collectInitFacts(workspace));
|
|
258521
|
-
|
|
258522
|
-
|
|
258523
|
-
|
|
258619
|
+
mkdirSync35(join86(workspace, ".roll"), { recursive: true });
|
|
258620
|
+
writeFileSync37(join86(workspace, ".roll", "init-diagnosis.yaml"), onboardDiagnosisFixture(factsHash));
|
|
258621
|
+
writeFileSync37(join86(workspace, ".roll", "onboard-plan.yaml"), onboardPlanFixture(factsHash));
|
|
258524
258622
|
process.stdout.write("roll init attest smoke: existing-codebase-review\n");
|
|
258525
258623
|
process.stdout.write(`workspace: ${workspace}
|
|
258526
258624
|
`);
|
|
@@ -258531,13 +258629,13 @@ function runExistingCodebaseReviewAttestSmoke() {
|
|
|
258531
258629
|
const code = initCommand(["--apply"], { forceInteractive: true, readLine: () => "n" });
|
|
258532
258630
|
process.chdir(originalCwd);
|
|
258533
258631
|
process.stdout.write("\nPost-review mutation check:\n");
|
|
258534
|
-
process.stdout.write(` AGENTS.md: ${
|
|
258632
|
+
process.stdout.write(` AGENTS.md: ${existsSync83(join86(workspace, "AGENTS.md")) ? "present" : "missing"}
|
|
258535
258633
|
`);
|
|
258536
|
-
process.stdout.write(` .roll/backlog.md: ${
|
|
258634
|
+
process.stdout.write(` .roll/backlog.md: ${existsSync83(join86(workspace, ".roll", "backlog.md")) ? "present" : "missing"}
|
|
258537
258635
|
`);
|
|
258538
|
-
process.stdout.write(` .gitignore: ${
|
|
258636
|
+
process.stdout.write(` .gitignore: ${existsSync83(join86(workspace, ".gitignore")) ? "present" : "missing"}
|
|
258539
258637
|
`);
|
|
258540
|
-
return code === 1 && !
|
|
258638
|
+
return code === 1 && !existsSync83(join86(workspace, "AGENTS.md")) && !existsSync83(join86(workspace, ".roll", "backlog.md")) ? 0 : 1;
|
|
258541
258639
|
} finally {
|
|
258542
258640
|
process.chdir(originalCwd);
|
|
258543
258641
|
if (originalRollHome === void 0)
|
|
@@ -258545,15 +258643,15 @@ function runExistingCodebaseReviewAttestSmoke() {
|
|
|
258545
258643
|
else
|
|
258546
258644
|
process.env["ROLL_HOME"] = originalRollHome;
|
|
258547
258645
|
rmSync14(workspace, { recursive: true, force: true });
|
|
258548
|
-
process.stdout.write(`cleanup: ${
|
|
258646
|
+
process.stdout.write(`cleanup: ${existsSync83(workspace) ? "failed" : "removed"} ${workspace}
|
|
258549
258647
|
`);
|
|
258550
258648
|
}
|
|
258551
258649
|
}
|
|
258552
258650
|
function writeExistingCodebaseOnboardArtifacts(workspace) {
|
|
258553
258651
|
const factsHash = computeInitFactsHash(collectInitFacts(workspace));
|
|
258554
|
-
|
|
258555
|
-
|
|
258556
|
-
|
|
258652
|
+
mkdirSync35(join86(workspace, ".roll"), { recursive: true });
|
|
258653
|
+
writeFileSync37(join86(workspace, ".roll", "init-diagnosis.yaml"), onboardDiagnosisFixture(factsHash));
|
|
258654
|
+
writeFileSync37(join86(workspace, ".roll", "onboard-plan.yaml"), onboardPlanFixture(factsHash));
|
|
258557
258655
|
}
|
|
258558
258656
|
function printExistingCodebaseSmokeSummary(summary) {
|
|
258559
258657
|
process.stdout.write("\nSmoke summary:\n");
|
|
@@ -258572,7 +258670,7 @@ function printExistingCodebaseSmokeSummary(summary) {
|
|
|
258572
258670
|
}
|
|
258573
258671
|
function runExistingCodebaseAttestSmoke() {
|
|
258574
258672
|
const originalCwd = process.cwd();
|
|
258575
|
-
const workspace = realpathSync10(mkdtempSync6(
|
|
258673
|
+
const workspace = realpathSync10(mkdtempSync6(join86(tmpdir8(), "roll-init-existing-codebase-")));
|
|
258576
258674
|
const summary = {
|
|
258577
258675
|
diagnosis: "not run",
|
|
258578
258676
|
reviewCheckpoint: false,
|
|
@@ -258622,7 +258720,7 @@ Idempotent re-apply result: ${reapplyCode === 0 ? "pass" : "fail"} (exit ${reapp
|
|
|
258622
258720
|
} finally {
|
|
258623
258721
|
process.chdir(originalCwd);
|
|
258624
258722
|
rmSync14(workspace, { recursive: true, force: true });
|
|
258625
|
-
summary.cleanup =
|
|
258723
|
+
summary.cleanup = existsSync83(workspace) ? "failed" : "removed";
|
|
258626
258724
|
process.stdout.write(`cleanup: ${summary.cleanup} ${workspace}
|
|
258627
258725
|
`);
|
|
258628
258726
|
printExistingCodebaseSmokeSummary(summary);
|
|
@@ -258633,27 +258731,27 @@ function printPartialRollState(projectDir, title) {
|
|
|
258633
258731
|
${title}:
|
|
258634
258732
|
`);
|
|
258635
258733
|
for (const rel of ["AGENTS.md", ".roll/backlog.md", ".roll/features/", ".roll/features.md", ".roll/.version", ".roll/onboard-changeset.yaml"]) {
|
|
258636
|
-
const path = rel.endsWith("/") ?
|
|
258637
|
-
process.stdout.write(` ${rel}: ${
|
|
258734
|
+
const path = rel.endsWith("/") ? join86(projectDir, rel.slice(0, -1)) : join86(projectDir, rel);
|
|
258735
|
+
process.stdout.write(` ${rel}: ${existsSync83(path) ? "present" : "missing"}
|
|
258638
258736
|
`);
|
|
258639
258737
|
}
|
|
258640
258738
|
}
|
|
258641
258739
|
function runPartialAndLegacyAttestSmoke() {
|
|
258642
258740
|
const originalCwd = process.cwd();
|
|
258643
258741
|
const originalRollHome = process.env["ROLL_HOME"];
|
|
258644
|
-
const workspace = realpathSync10(mkdtempSync6(
|
|
258742
|
+
const workspace = realpathSync10(mkdtempSync6(join86(tmpdir8(), "roll-init-partial-legacy-")));
|
|
258645
258743
|
let okSmoke = true;
|
|
258646
258744
|
try {
|
|
258647
|
-
const smokeHome =
|
|
258648
|
-
|
|
258649
|
-
cpSync(
|
|
258650
|
-
|
|
258745
|
+
const smokeHome = join86(workspace, ".roll-home");
|
|
258746
|
+
mkdirSync35(smokeHome, { recursive: true });
|
|
258747
|
+
cpSync(join86(rollPkgDir(), "conventions"), join86(smokeHome, "conventions"), { recursive: true });
|
|
258748
|
+
writeFileSync37(join86(smokeHome, "config.yaml"), "# Roll config\nlang: en\n");
|
|
258651
258749
|
process.env["ROLL_HOME"] = smokeHome;
|
|
258652
|
-
const partial =
|
|
258653
|
-
|
|
258654
|
-
|
|
258655
|
-
|
|
258656
|
-
|
|
258750
|
+
const partial = join86(workspace, "partial-roll");
|
|
258751
|
+
mkdirSync35(join86(partial, ".roll"), { recursive: true });
|
|
258752
|
+
writeFileSync37(join86(partial, "AGENTS.md"), "# Owner Guide\n\nKeep this owner text.\n");
|
|
258753
|
+
writeFileSync37(join86(partial, ".roll", "backlog.md"), "# Owner Backlog\n\nKeep this backlog.\n");
|
|
258754
|
+
writeFileSync37(join86(partial, "BACKLOG.md"), "# Old Roll backlog\n");
|
|
258657
258755
|
process.stdout.write("roll init attest smoke: partial-and-roll-legacy\n");
|
|
258658
258756
|
process.stdout.write(`workspace: ${workspace}
|
|
258659
258757
|
`);
|
|
@@ -258670,21 +258768,21 @@ Partial repair result: ${repair === 0 ? "pass" : "fail"} (exit ${repair})
|
|
|
258670
258768
|
`);
|
|
258671
258769
|
printPartialRollState(partial, "Partial repair state");
|
|
258672
258770
|
okSmoke = okSmoke && partialDiagnosis === 0 && repair === 0 && repairAgain === 0;
|
|
258673
|
-
const legacy =
|
|
258674
|
-
|
|
258675
|
-
|
|
258676
|
-
|
|
258771
|
+
const legacy = join86(workspace, "legacy-roll");
|
|
258772
|
+
mkdirSync35(join86(legacy, "docs", "features"), { recursive: true });
|
|
258773
|
+
writeFileSync37(join86(legacy, "BACKLOG.md"), "# Old Roll backlog\n");
|
|
258774
|
+
writeFileSync37(join86(legacy, "docs", "features", "feature.md"), "# Old feature\n");
|
|
258677
258775
|
writeExistingCodebaseSmokeFixture(legacy);
|
|
258678
258776
|
process.stdout.write("\nLegacy Roll diagnosis:\n");
|
|
258679
258777
|
process.chdir(legacy);
|
|
258680
258778
|
const legacyDiagnosis = initCommand([]);
|
|
258681
258779
|
process.chdir(originalCwd);
|
|
258682
258780
|
process.stdout.write("\nLegacy mutation check:\n");
|
|
258683
|
-
process.stdout.write(` AGENTS.md: ${
|
|
258781
|
+
process.stdout.write(` AGENTS.md: ${existsSync83(join86(legacy, "AGENTS.md")) ? "present" : "missing"}
|
|
258684
258782
|
`);
|
|
258685
|
-
process.stdout.write(` .roll/: ${
|
|
258783
|
+
process.stdout.write(` .roll/: ${existsSync83(join86(legacy, ".roll")) ? "present" : "missing"}
|
|
258686
258784
|
`);
|
|
258687
|
-
okSmoke = okSmoke && legacyDiagnosis === 0 && !
|
|
258785
|
+
okSmoke = okSmoke && legacyDiagnosis === 0 && !existsSync83(join86(legacy, "AGENTS.md")) && !existsSync83(join86(legacy, ".roll"));
|
|
258688
258786
|
return okSmoke ? 0 : 1;
|
|
258689
258787
|
} finally {
|
|
258690
258788
|
process.chdir(originalCwd);
|
|
@@ -258693,7 +258791,7 @@ Partial repair result: ${repair === 0 ? "pass" : "fail"} (exit ${repair})
|
|
|
258693
258791
|
else
|
|
258694
258792
|
process.env["ROLL_HOME"] = originalRollHome;
|
|
258695
258793
|
rmSync14(workspace, { recursive: true, force: true });
|
|
258696
|
-
process.stdout.write(`cleanup: ${
|
|
258794
|
+
process.stdout.write(`cleanup: ${existsSync83(workspace) ? "failed" : "removed"} ${workspace}
|
|
258697
258795
|
`);
|
|
258698
258796
|
}
|
|
258699
258797
|
}
|
|
@@ -258728,7 +258826,7 @@ function initCommand(args, deps = {}) {
|
|
|
258728
258826
|
err9(`${m3("init.unknown_flag_1")}${applyUnknownFlag}`);
|
|
258729
258827
|
return 1;
|
|
258730
258828
|
}
|
|
258731
|
-
if (!
|
|
258829
|
+
if (!existsSync83(rollTemplates2())) {
|
|
258732
258830
|
err9(m3("init.no_templates_found_run_roll_setup"));
|
|
258733
258831
|
return 1;
|
|
258734
258832
|
}
|
|
@@ -258782,7 +258880,7 @@ function initCommand(args, deps = {}) {
|
|
|
258782
258880
|
`);
|
|
258783
258881
|
return 0;
|
|
258784
258882
|
}
|
|
258785
|
-
if (!
|
|
258883
|
+
if (!existsSync83(rollTemplates2())) {
|
|
258786
258884
|
err9(m3("init.no_templates_found_run_roll_setup_2"));
|
|
258787
258885
|
return 1;
|
|
258788
258886
|
}
|
|
@@ -258793,7 +258891,7 @@ function initCommand(args, deps = {}) {
|
|
|
258793
258891
|
let hasAgents = false;
|
|
258794
258892
|
let emptyDescription;
|
|
258795
258893
|
const summary = [];
|
|
258796
|
-
if (
|
|
258894
|
+
if (existsSync83(join86(projectDir, "AGENTS.md"))) {
|
|
258797
258895
|
hasAgents = true;
|
|
258798
258896
|
} else if (emptyInteractive) {
|
|
258799
258897
|
emptyDescription = promptEmptyProjectBrief(deps.readLine);
|
|
@@ -258802,9 +258900,9 @@ function initCommand(args, deps = {}) {
|
|
|
258802
258900
|
}
|
|
258803
258901
|
mergeGlobalToProject(projectDir, summary);
|
|
258804
258902
|
mergeClaudeToProject(projectDir, summary);
|
|
258805
|
-
writeBacklog(
|
|
258806
|
-
ensureFeaturesDir(
|
|
258807
|
-
writeFeaturesMd(
|
|
258903
|
+
writeBacklog(join86(projectDir, ".roll", "backlog.md"), summary);
|
|
258904
|
+
ensureFeaturesDir(join86(projectDir, ".roll", "features"), summary);
|
|
258905
|
+
writeFeaturesMd(join86(projectDir, ".roll", "features.md"), summary);
|
|
258808
258906
|
const routesTemplate = process.env["ROLL_AGENT_ROUTES_TEMPLATE"] ?? "default";
|
|
258809
258907
|
if (routesTemplate !== "skip")
|
|
258810
258908
|
initSeedProjectAgents(projectDir, summary);
|
|
@@ -258826,28 +258924,28 @@ function initCommand(args, deps = {}) {
|
|
|
258826
258924
|
// packages/cli/dist/lib/init-journey.js
|
|
258827
258925
|
init_dist2();
|
|
258828
258926
|
init_dist();
|
|
258829
|
-
import { existsSync as
|
|
258927
|
+
import { existsSync as existsSync84, mkdtempSync as mkdtempSync7, mkdirSync as mkdirSync36, readFileSync as readFileSync77, realpathSync as realpathSync11, rmSync as rmSync15, writeFileSync as writeFileSync38 } from "node:fs";
|
|
258830
258928
|
import { tmpdir as tmpdir9 } from "node:os";
|
|
258831
|
-
import { dirname as
|
|
258929
|
+
import { dirname as dirname37, join as join87 } from "node:path";
|
|
258832
258930
|
function safeRead(path) {
|
|
258833
258931
|
try {
|
|
258834
|
-
return
|
|
258932
|
+
return readFileSync77(path, "utf8");
|
|
258835
258933
|
} catch {
|
|
258836
258934
|
return "";
|
|
258837
258935
|
}
|
|
258838
258936
|
}
|
|
258839
258937
|
function existsFile(path) {
|
|
258840
258938
|
try {
|
|
258841
|
-
return
|
|
258939
|
+
return existsSync84(path);
|
|
258842
258940
|
} catch {
|
|
258843
258941
|
return false;
|
|
258844
258942
|
}
|
|
258845
258943
|
}
|
|
258846
258944
|
function hasPendingOnboardPlan(projectDir) {
|
|
258847
|
-
return existsFile(
|
|
258945
|
+
return existsFile(join87(projectDir, ".roll", "onboard-plan.yaml")) && !existsFile(join87(projectDir, ".roll", "onboard-changeset.yaml"));
|
|
258848
258946
|
}
|
|
258849
258947
|
function briefDesignCommand(projectDir) {
|
|
258850
|
-
return existsFile(
|
|
258948
|
+
return existsFile(join87(projectDir, ".roll", "brief.md")) ? "roll design --from-file .roll/brief.md" : null;
|
|
258851
258949
|
}
|
|
258852
258950
|
function firstSentence(text2) {
|
|
258853
258951
|
return text2.trim().replace(/\s+/g, " ");
|
|
@@ -258856,7 +258954,7 @@ function renderReason(diagnosis2) {
|
|
|
258856
258954
|
return firstSentence(diagnosis2.reasons[0] ?? "Current project state determines the next action.");
|
|
258857
258955
|
}
|
|
258858
258956
|
function rollReadyRecommendation(projectDir) {
|
|
258859
|
-
const backlogPath =
|
|
258957
|
+
const backlogPath = join87(projectDir, ".roll", "backlog.md");
|
|
258860
258958
|
const items = parseBacklog(safeRead(backlogPath));
|
|
258861
258959
|
const todo = items.find((item) => classifyStatus(item.status) === "todo");
|
|
258862
258960
|
if (todo !== void 0) {
|
|
@@ -258935,12 +259033,12 @@ function renderNextRecommendation(input) {
|
|
|
258935
259033
|
`;
|
|
258936
259034
|
}
|
|
258937
259035
|
function write(root, rel, text2) {
|
|
258938
|
-
const path =
|
|
258939
|
-
|
|
258940
|
-
|
|
259036
|
+
const path = join87(root, rel);
|
|
259037
|
+
mkdirSync36(dirname37(path), { recursive: true });
|
|
259038
|
+
writeFileSync38(path, text2);
|
|
258941
259039
|
}
|
|
258942
259040
|
function mkdir2(root, rel) {
|
|
258943
|
-
|
|
259041
|
+
mkdirSync36(join87(root, rel), { recursive: true });
|
|
258944
259042
|
}
|
|
258945
259043
|
function writeReady(root) {
|
|
258946
259044
|
write(root, "AGENTS.md", "# Agents\n");
|
|
@@ -258953,14 +259051,14 @@ function writeReady(root) {
|
|
|
258953
259051
|
}
|
|
258954
259052
|
function renderInitJourneyAttestSmoke() {
|
|
258955
259053
|
const original = process.cwd();
|
|
258956
|
-
const workspace = realpathSync11(mkdtempSync7(
|
|
259054
|
+
const workspace = realpathSync11(mkdtempSync7(join87(tmpdir9(), "roll-next-journey-")));
|
|
258957
259055
|
const lines2 = ["roll next attest smoke: init-journey", `workspace: ${workspace}`, ""];
|
|
258958
259056
|
try {
|
|
258959
|
-
const prdOnly = { label: "prd-only", dir:
|
|
258960
|
-
const codebaseOnboard = { label: "codebase-onboard", dir:
|
|
258961
|
-
const partialRoll = { label: "partial-roll", dir:
|
|
258962
|
-
const oldRollLayout = { label: "old-roll-layout", dir:
|
|
258963
|
-
const rollReady = { label: "roll-ready", dir:
|
|
259057
|
+
const prdOnly = { label: "prd-only", dir: join87(workspace, "prd-only") };
|
|
259058
|
+
const codebaseOnboard = { label: "codebase-onboard", dir: join87(workspace, "codebase-onboard") };
|
|
259059
|
+
const partialRoll = { label: "partial-roll", dir: join87(workspace, "partial-roll") };
|
|
259060
|
+
const oldRollLayout = { label: "old-roll-layout", dir: join87(workspace, "old-roll-layout") };
|
|
259061
|
+
const rollReady = { label: "roll-ready", dir: join87(workspace, "roll-ready") };
|
|
258964
259062
|
const fixtures = [prdOnly, codebaseOnboard, partialRoll, oldRollLayout, rollReady];
|
|
258965
259063
|
write(prdOnly.dir, "docs/PRD.md", "# Radar\n\nA product requirements document for an app.\n");
|
|
258966
259064
|
mkdir2(codebaseOnboard.dir, ".roll");
|
|
@@ -259016,8 +259114,8 @@ function nextCommand(args) {
|
|
|
259016
259114
|
init_dist();
|
|
259017
259115
|
init_dist2();
|
|
259018
259116
|
import { spawnSync as spawnSync11 } from "node:child_process";
|
|
259019
|
-
import { existsSync as
|
|
259020
|
-
import { join as
|
|
259117
|
+
import { existsSync as existsSync85, readFileSync as readFileSync78, statSync as statSync29 } from "node:fs";
|
|
259118
|
+
import { join as join88, resolve as resolve7 } from "node:path";
|
|
259021
259119
|
function lang9() {
|
|
259022
259120
|
return currentLang();
|
|
259023
259121
|
}
|
|
@@ -259072,7 +259170,7 @@ function parseDesignFlags(args) {
|
|
|
259072
259170
|
return { agent, fromFile, rest, error: null };
|
|
259073
259171
|
}
|
|
259074
259172
|
function isRollProject(cwd) {
|
|
259075
|
-
return
|
|
259173
|
+
return existsSync85(join88(cwd, ".roll"));
|
|
259076
259174
|
}
|
|
259077
259175
|
function isRegularFile(path) {
|
|
259078
259176
|
try {
|
|
@@ -259082,9 +259180,9 @@ function isRegularFile(path) {
|
|
|
259082
259180
|
}
|
|
259083
259181
|
}
|
|
259084
259182
|
function hasNonEmptyBacklog(cwd) {
|
|
259085
|
-
const bp =
|
|
259183
|
+
const bp = join88(cwd, ".roll", "backlog.md");
|
|
259086
259184
|
try {
|
|
259087
|
-
const content =
|
|
259185
|
+
const content = readFileSync78(bp, "utf8");
|
|
259088
259186
|
return parseBacklog(content).length > 0;
|
|
259089
259187
|
} catch {
|
|
259090
259188
|
return false;
|
|
@@ -259215,12 +259313,12 @@ init_dist2();
|
|
|
259215
259313
|
init_dist3();
|
|
259216
259314
|
init_render();
|
|
259217
259315
|
import { spawn as spawn8, spawnSync as spawnSync12 } from "node:child_process";
|
|
259218
|
-
import { existsSync as
|
|
259219
|
-
import { join as
|
|
259316
|
+
import { existsSync as existsSync86, readFileSync as readFileSync79 } from "node:fs";
|
|
259317
|
+
import { join as join89 } from "node:path";
|
|
259220
259318
|
import { createInterface as createInterface4 } from "node:readline";
|
|
259221
259319
|
function runtimeDir7(projectPath3) {
|
|
259222
259320
|
const env = (process.env["ROLL_PROJECT_RUNTIME_DIR"] ?? "").trim();
|
|
259223
|
-
return env !== "" ? env :
|
|
259321
|
+
return env !== "" ? env : join89(projectPath3, ".roll", "loop");
|
|
259224
259322
|
}
|
|
259225
259323
|
function rollBin2() {
|
|
259226
259324
|
return (process.env["ROLL_BIN"] ?? "").trim() || process.argv[1] || "roll";
|
|
@@ -259363,10 +259461,10 @@ function realDeps7() {
|
|
|
259363
259461
|
const id = await projectIdentity();
|
|
259364
259462
|
return { path: id.path, slug: id.slug };
|
|
259365
259463
|
},
|
|
259366
|
-
exists: (p) =>
|
|
259464
|
+
exists: (p) => existsSync86(p),
|
|
259367
259465
|
readText: (p) => {
|
|
259368
259466
|
try {
|
|
259369
|
-
return
|
|
259467
|
+
return readFileSync79(p, "utf8");
|
|
259370
259468
|
} catch {
|
|
259371
259469
|
return null;
|
|
259372
259470
|
}
|
|
@@ -259473,7 +259571,7 @@ async function loopWatchCommand(args, deps = realDeps7()) {
|
|
|
259473
259571
|
if (opts.attach)
|
|
259474
259572
|
return attachToWatchWindow(id.path, id.slug, deps);
|
|
259475
259573
|
const rt = runtimeDir7(id.path);
|
|
259476
|
-
const watchPath =
|
|
259574
|
+
const watchPath = join89(rt, opts.events || opts.rawEvents ? "events.ndjson" : "live.log");
|
|
259477
259575
|
if (!deps.exists(watchPath)) {
|
|
259478
259576
|
if (opts.events || opts.rawEvents) {
|
|
259479
259577
|
deps.emit(`roll loop watch: no event stream at ${watchPath} yet \u2014 the loop has not written events in this project.`);
|
|
@@ -259487,8 +259585,8 @@ async function loopWatchCommand(args, deps = realDeps7()) {
|
|
|
259487
259585
|
return 1;
|
|
259488
259586
|
}
|
|
259489
259587
|
const agent = (process.env["ROLL_LOOP_AGENT"] ?? "claude").trim() || "claude";
|
|
259490
|
-
const eventsPath2 =
|
|
259491
|
-
const runsPath3 =
|
|
259588
|
+
const eventsPath2 = join89(rt, "events.ndjson");
|
|
259589
|
+
const runsPath3 = join89(rt, "runs.jsonl");
|
|
259492
259590
|
const durableLookup = buildDurableLookup(runsPath3, deps);
|
|
259493
259591
|
const status2 = !opts.events && !opts.rawEvents ? () => statusSnapshot(eventsPath2, deps, durableLookup) : void 0;
|
|
259494
259592
|
if (status2 !== void 0)
|
|
@@ -259510,15 +259608,15 @@ async function loopWatchCommand(args, deps = realDeps7()) {
|
|
|
259510
259608
|
|
|
259511
259609
|
// packages/cli/dist/commands/loop-review-resize.js
|
|
259512
259610
|
init_dist2();
|
|
259513
|
-
import { appendFileSync as appendFileSync14, mkdirSync as
|
|
259514
|
-
import { dirname as
|
|
259611
|
+
import { appendFileSync as appendFileSync14, mkdirSync as mkdirSync38 } from "node:fs";
|
|
259612
|
+
import { dirname as dirname39, join as join91 } from "node:path";
|
|
259515
259613
|
init_dist2();
|
|
259516
259614
|
|
|
259517
259615
|
// packages/cli/dist/commands/loop-self-downgrade.js
|
|
259518
259616
|
init_dist2();
|
|
259519
259617
|
init_dist3();
|
|
259520
|
-
import { appendFileSync as appendFileSync13, existsSync as
|
|
259521
|
-
import { dirname as
|
|
259618
|
+
import { appendFileSync as appendFileSync13, existsSync as existsSync87, mkdirSync as mkdirSync37, readFileSync as readFileSync80, readdirSync as readdirSync31 } from "node:fs";
|
|
259619
|
+
import { dirname as dirname38, join as join90 } from "node:path";
|
|
259522
259620
|
function realSelfDowngradeDeps() {
|
|
259523
259621
|
return {
|
|
259524
259622
|
now: () => Date.now(),
|
|
@@ -259538,22 +259636,22 @@ function realSelfDowngradeDeps() {
|
|
|
259538
259636
|
}
|
|
259539
259637
|
};
|
|
259540
259638
|
}
|
|
259541
|
-
var FEATURES = (project) =>
|
|
259639
|
+
var FEATURES = (project) => join90(project, ".roll", "features");
|
|
259542
259640
|
function findCardEpic(project, id) {
|
|
259543
259641
|
const base = FEATURES(project);
|
|
259544
|
-
if (!
|
|
259642
|
+
if (!existsSync87(base))
|
|
259545
259643
|
return void 0;
|
|
259546
259644
|
for (const epic of readdirSync31(base, { withFileTypes: true })) {
|
|
259547
259645
|
if (!epic.isDirectory())
|
|
259548
259646
|
continue;
|
|
259549
|
-
if (
|
|
259647
|
+
if (existsSync87(join90(base, epic.name, id, "spec.md")))
|
|
259550
259648
|
return epic.name;
|
|
259551
259649
|
}
|
|
259552
259650
|
return void 0;
|
|
259553
259651
|
}
|
|
259554
259652
|
function readCardTitle(project, epic, id) {
|
|
259555
259653
|
try {
|
|
259556
|
-
const text2 =
|
|
259654
|
+
const text2 = readFileSync80(join90(FEATURES(project), epic, id, "spec.md"), "utf8");
|
|
259557
259655
|
const fm = /^---\n([\s\S]*?)\n---/.exec(text2);
|
|
259558
259656
|
const m7 = fm !== null ? /^title:\s*(.+)$/m.exec(fm[1] ?? "") : null;
|
|
259559
259657
|
const title = (m7?.[1] ?? "").trim().replace(/^["']|["']$/g, "");
|
|
@@ -259567,7 +259665,7 @@ function readSpecChainDepth(project, id) {
|
|
|
259567
259665
|
if (epic === void 0)
|
|
259568
259666
|
return 0;
|
|
259569
259667
|
try {
|
|
259570
|
-
return parseChainDepth(
|
|
259668
|
+
return parseChainDepth(readFileSync80(join90(FEATURES(project), epic, id, "spec.md"), "utf8"));
|
|
259571
259669
|
} catch {
|
|
259572
259670
|
return 0;
|
|
259573
259671
|
}
|
|
@@ -259586,10 +259684,10 @@ async function loopSelfDowngradeCommand(argv, deps = realSelfDowngradeDeps()) {
|
|
|
259586
259684
|
if (parentId === "" || reason === "")
|
|
259587
259685
|
return usage2();
|
|
259588
259686
|
const project = (process.env["ROLL_MAIN_PROJECT"] ?? "").trim() || process.cwd();
|
|
259589
|
-
const backlogPath =
|
|
259590
|
-
const rt = (process.env["ROLL_PROJECT_RUNTIME_DIR"] ?? "").trim() ||
|
|
259591
|
-
const eventsPath2 =
|
|
259592
|
-
const alertsPath = (process.env["ROLL_LOOP_ALERT"] ?? "").trim() ||
|
|
259687
|
+
const backlogPath = join90(project, ".roll", "backlog.md");
|
|
259688
|
+
const rt = (process.env["ROLL_PROJECT_RUNTIME_DIR"] ?? "").trim() || join90(project, ".roll", "loop");
|
|
259689
|
+
const eventsPath2 = join90(rt, "events.ndjson");
|
|
259690
|
+
const alertsPath = (process.env["ROLL_LOOP_ALERT"] ?? "").trim() || join90(rt, `ALERT-${(process.env["ROLL_MAIN_SLUG"] ?? "").trim() || projectSlug2(project)}.md`);
|
|
259593
259691
|
const store = new BacklogStore();
|
|
259594
259692
|
let snap;
|
|
259595
259693
|
try {
|
|
@@ -259631,7 +259729,7 @@ async function loopSelfDowngradeCommand(argv, deps = realSelfDowngradeDeps()) {
|
|
|
259631
259729
|
if (plan.kind === "cap-hit") {
|
|
259632
259730
|
const headline = plan.capReason === "chain-cap" ? `${parentId} hit the self-downgrade chain cap (chain_depth=${plan.chainDepth} \u2265 ${CHAIN_DEPTH_CAP}) \u2014 held for human triage` : `${parentId} could not be split into \u22652 sub-stories (irreducible) \u2014 held for human triage`;
|
|
259633
259731
|
try {
|
|
259634
|
-
|
|
259732
|
+
mkdirSync37(dirname38(alertsPath), { recursive: true });
|
|
259635
259733
|
appendFileSync13(alertsPath, `[${isoUtc(ts2)}] ALERT ${headline}
|
|
259636
259734
|
`, "utf8");
|
|
259637
259735
|
} catch {
|
|
@@ -259731,10 +259829,10 @@ For each sub-story create its .roll/features/<epic>/<id>/spec.md. Do NOT edit th
|
|
|
259731
259829
|
},
|
|
259732
259830
|
selfDowngrade: (storyId, reason, subIds) => loopSelfDowngradeCommand([storyId, reason, subIds.join(",")]),
|
|
259733
259831
|
alert: (projectPath3, message, ts2) => {
|
|
259734
|
-
const rt = (process.env["ROLL_PROJECT_RUNTIME_DIR"] ?? "").trim() ||
|
|
259735
|
-
const alertsPath = (process.env["ROLL_LOOP_ALERT"] ?? "").trim() ||
|
|
259832
|
+
const rt = (process.env["ROLL_PROJECT_RUNTIME_DIR"] ?? "").trim() || join91(projectPath3, ".roll", "loop");
|
|
259833
|
+
const alertsPath = (process.env["ROLL_LOOP_ALERT"] ?? "").trim() || join91(rt, `ALERT-${projectSlug2(projectPath3)}.md`);
|
|
259736
259834
|
try {
|
|
259737
|
-
|
|
259835
|
+
mkdirSync38(dirname39(alertsPath), { recursive: true });
|
|
259738
259836
|
appendFileSync14(alertsPath, `[${new Date(ts2).toISOString()}] ALERT ${message}
|
|
259739
259837
|
`, "utf8");
|
|
259740
259838
|
} catch {
|
|
@@ -259751,8 +259849,8 @@ async function loopReviewResizeCommand(argv, deps = realReviewResizeDeps()) {
|
|
|
259751
259849
|
if (storyId === "")
|
|
259752
259850
|
return usage3();
|
|
259753
259851
|
const project = (process.env["ROLL_MAIN_PROJECT"] ?? "").trim() || process.cwd();
|
|
259754
|
-
const rt = (process.env["ROLL_PROJECT_RUNTIME_DIR"] ?? "").trim() ||
|
|
259755
|
-
const eventsPath2 =
|
|
259852
|
+
const rt = (process.env["ROLL_PROJECT_RUNTIME_DIR"] ?? "").trim() || join91(project, ".roll", "loop");
|
|
259853
|
+
const eventsPath2 = join91(rt, "events.ndjson");
|
|
259756
259854
|
const bus = new EventBus();
|
|
259757
259855
|
const ts2 = deps.now();
|
|
259758
259856
|
const latest = deps.readResize(project, storyId);
|
|
@@ -259846,20 +259944,20 @@ init_dist3();
|
|
|
259846
259944
|
// packages/cli/dist/runner/cycle-role-artifact-writer.js
|
|
259847
259945
|
init_dist();
|
|
259848
259946
|
init_dist2();
|
|
259849
|
-
import { existsSync as
|
|
259947
|
+
import { existsSync as existsSync88, readFileSync as readFileSync81, mkdirSync as mkdirSync39, writeFileSync as writeFileSync39 } from "node:fs";
|
|
259850
259948
|
function writeCycleRoleSummaryBestEffort(cycleId, eventsPath2, cycleLogDir) {
|
|
259851
259949
|
try {
|
|
259852
259950
|
if (!cycleId)
|
|
259853
259951
|
return;
|
|
259854
259952
|
let raw;
|
|
259855
259953
|
try {
|
|
259856
|
-
raw =
|
|
259954
|
+
raw = readFileSync81(eventsPath2, "utf-8");
|
|
259857
259955
|
} catch {
|
|
259858
259956
|
return;
|
|
259859
259957
|
}
|
|
259860
259958
|
const outDir = `${cycleLogDir}/${cycleId}`;
|
|
259861
|
-
if (!
|
|
259862
|
-
|
|
259959
|
+
if (!existsSync88(outDir)) {
|
|
259960
|
+
mkdirSync39(outDir, { recursive: true });
|
|
259863
259961
|
}
|
|
259864
259962
|
const lines2 = raw.split("\n").filter((l) => l.trim() !== "");
|
|
259865
259963
|
const events = [];
|
|
@@ -259876,15 +259974,15 @@ function writeCycleRoleSummaryBestEffort(cycleId, eventsPath2, cycleLogDir) {
|
|
|
259876
259974
|
cycleLogDir
|
|
259877
259975
|
};
|
|
259878
259976
|
const summary = buildCycleRoleSummary(input);
|
|
259879
|
-
|
|
259880
|
-
|
|
259977
|
+
writeFileSync39(`${outDir}/summary.json`, JSON.stringify(summary, null, 2), "utf-8");
|
|
259978
|
+
writeFileSync39(`${outDir}/summary.md`, renderCycleRoleSummaryMarkdown(summary), "utf-8");
|
|
259881
259979
|
} catch {
|
|
259882
259980
|
}
|
|
259883
259981
|
}
|
|
259884
259982
|
|
|
259885
259983
|
// packages/cli/dist/runner/executor.js
|
|
259886
259984
|
import { execFile as execFile10, execFileSync as execFileSync22 } from "node:child_process";
|
|
259887
|
-
import { appendFileSync as appendFileSync16, existsSync as existsSync93, lstatSync as lstatSync4, mkdirSync as mkdirSync42, readdirSync as readdirSync34, readFileSync as readFileSync87, realpathSync as realpathSync12, rmSync as rmSync16, statSync as statSync31, symlinkSync as symlinkSync3, unlinkSync as unlinkSync4, writeFileSync as writeFileSync44 } from "node:fs";
|
|
259985
|
+
import { appendFileSync as appendFileSync16, existsSync as existsSync93, lstatSync as lstatSync4, mkdirSync as mkdirSync42, readdirSync as readdirSync34, readFileSync as readFileSync87, realpathSync as realpathSync12, renameSync as renameSync15, rmSync as rmSync16, statSync as statSync31, symlinkSync as symlinkSync3, unlinkSync as unlinkSync4, writeFileSync as writeFileSync44 } from "node:fs";
|
|
259888
259986
|
import { homedir as homedir26 } from "node:os";
|
|
259889
259987
|
import { dirname as dirname41, join as join97 } from "node:path";
|
|
259890
259988
|
import { promisify as promisify10 } from "node:util";
|
|
@@ -259975,17 +260073,17 @@ function firstLine(s) {
|
|
|
259975
260073
|
}
|
|
259976
260074
|
|
|
259977
260075
|
// packages/cli/dist/runner/skip-cards.js
|
|
259978
|
-
import { existsSync as
|
|
259979
|
-
import { join as
|
|
260076
|
+
import { existsSync as existsSync89, readFileSync as readFileSync82, writeFileSync as writeFileSync40 } from "node:fs";
|
|
260077
|
+
import { join as join92 } from "node:path";
|
|
259980
260078
|
function skipFile(runtimeDir9) {
|
|
259981
|
-
return
|
|
260079
|
+
return join92(runtimeDir9, "skip-cards.json");
|
|
259982
260080
|
}
|
|
259983
260081
|
function read(runtimeDir9) {
|
|
259984
260082
|
try {
|
|
259985
260083
|
const path = skipFile(runtimeDir9);
|
|
259986
|
-
if (!
|
|
260084
|
+
if (!existsSync89(path))
|
|
259987
260085
|
return { fails: {}, skip: [] };
|
|
259988
|
-
const o = JSON.parse(
|
|
260086
|
+
const o = JSON.parse(readFileSync82(path, "utf8"));
|
|
259989
260087
|
return {
|
|
259990
260088
|
fails: o.fails !== void 0 && typeof o.fails === "object" ? o.fails : {},
|
|
259991
260089
|
skip: Array.isArray(o.skip) ? o.skip.filter((s) => typeof s === "string") : []
|
|
@@ -259996,7 +260094,7 @@ function read(runtimeDir9) {
|
|
|
259996
260094
|
}
|
|
259997
260095
|
function write2(runtimeDir9, s) {
|
|
259998
260096
|
try {
|
|
259999
|
-
|
|
260097
|
+
writeFileSync40(skipFile(runtimeDir9), JSON.stringify(s, null, 2), "utf8");
|
|
260000
260098
|
} catch {
|
|
260001
260099
|
}
|
|
260002
260100
|
}
|
|
@@ -260028,55 +260126,6 @@ function clearCardFailure(runtimeDir9, storyId) {
|
|
|
260028
260126
|
write2(runtimeDir9, s);
|
|
260029
260127
|
}
|
|
260030
260128
|
|
|
260031
|
-
// packages/cli/dist/runner/pending-publish.js
|
|
260032
|
-
import { existsSync as existsSync89, mkdirSync as mkdirSync39, readFileSync as readFileSync82, writeFileSync as writeFileSync40 } from "node:fs";
|
|
260033
|
-
import { dirname as dirname39, join as join92 } from "node:path";
|
|
260034
|
-
var FILENAME = "pending-publish.json";
|
|
260035
|
-
function pathFor(runtimeDir9) {
|
|
260036
|
-
return join92(runtimeDir9, FILENAME);
|
|
260037
|
-
}
|
|
260038
|
-
function readSet(runtimeDir9) {
|
|
260039
|
-
const path = pathFor(runtimeDir9);
|
|
260040
|
-
if (!existsSync89(path))
|
|
260041
|
-
return /* @__PURE__ */ new Set();
|
|
260042
|
-
try {
|
|
260043
|
-
const raw = JSON.parse(readFileSync82(path, "utf8"));
|
|
260044
|
-
if (Array.isArray(raw))
|
|
260045
|
-
return new Set(raw.filter((v) => typeof v === "string"));
|
|
260046
|
-
} catch {
|
|
260047
|
-
}
|
|
260048
|
-
return /* @__PURE__ */ new Set();
|
|
260049
|
-
}
|
|
260050
|
-
function writeSet(runtimeDir9, set) {
|
|
260051
|
-
const path = pathFor(runtimeDir9);
|
|
260052
|
-
mkdirSync39(dirname39(path), { recursive: true });
|
|
260053
|
-
const tmp = `${path}.tmp-${process.pid}`;
|
|
260054
|
-
writeFileSync40(tmp, JSON.stringify([...set].sort(), null, 2), "utf8");
|
|
260055
|
-
writeFileSync40(path, readFileSync82(tmp, "utf8"), "utf8");
|
|
260056
|
-
try {
|
|
260057
|
-
const { rmSync: rmSync21 } = __require("node:fs");
|
|
260058
|
-
rmSync21(tmp, { force: true });
|
|
260059
|
-
} catch {
|
|
260060
|
-
}
|
|
260061
|
-
}
|
|
260062
|
-
function readPendingPublish(runtimeDir9) {
|
|
260063
|
-
return readSet(runtimeDir9);
|
|
260064
|
-
}
|
|
260065
|
-
function addPendingPublish(runtimeDir9, storyId) {
|
|
260066
|
-
const set = readSet(runtimeDir9);
|
|
260067
|
-
if (set.has(storyId))
|
|
260068
|
-
return;
|
|
260069
|
-
set.add(storyId);
|
|
260070
|
-
writeSet(runtimeDir9, set);
|
|
260071
|
-
}
|
|
260072
|
-
function removePendingPublish(runtimeDir9, storyId) {
|
|
260073
|
-
const set = readSet(runtimeDir9);
|
|
260074
|
-
if (!set.has(storyId))
|
|
260075
|
-
return;
|
|
260076
|
-
set.delete(storyId);
|
|
260077
|
-
writeSet(runtimeDir9, set);
|
|
260078
|
-
}
|
|
260079
|
-
|
|
260080
260129
|
// packages/cli/dist/runner/selfheal-budget.js
|
|
260081
260130
|
import { existsSync as existsSync90, readFileSync as readFileSync83, writeFileSync as writeFileSync41 } from "node:fs";
|
|
260082
260131
|
import { join as join93 } from "node:path";
|
|
@@ -262184,6 +262233,7 @@ ${diffStat}`;
|
|
|
262184
262233
|
}
|
|
262185
262234
|
if (!terminalMerged && terminalStoryId !== "") {
|
|
262186
262235
|
resetStaleSpecTruth(ports, terminalStoryId);
|
|
262236
|
+
cleanStaleEvidence(ports.repoCwd, terminalStoryId, ctx.cycleId ?? "");
|
|
262187
262237
|
}
|
|
262188
262238
|
await commitRollMetadata(ports, ctx);
|
|
262189
262239
|
if (ctx.cycleId !== void 0) {
|
|
@@ -262433,33 +262483,96 @@ function revertPrematureDone(ports, storyId, preCycleStatus) {
|
|
|
262433
262483
|
} catch {
|
|
262434
262484
|
}
|
|
262435
262485
|
}
|
|
262436
|
-
function resetSpecTruthText(text2) {
|
|
262486
|
+
function resetSpecTruthText(text2, baseline) {
|
|
262437
262487
|
let changed = false;
|
|
262438
262488
|
const lines2 = text2.split("\n");
|
|
262439
|
-
const
|
|
262489
|
+
const deliveryStampRe = /^(?:\s*>\s*)?(?:\*\*(?:Fixed|Delivery(?:\s+notes)?)\b[^*]*\*\*|##\s+Delivery\s+notes\b)/i;
|
|
262490
|
+
const narrativeLabelRe = /^(?:\s*>\s*)?(?:\*\*|##\s+)(Problem|Root Cause|Solution)\b/i;
|
|
262491
|
+
const baselineNarrativeLabels = collectNarrativeLabels(baseline, narrativeLabelRe);
|
|
262492
|
+
const boundaryRe = /^(?:\s*>\s*)?(?:\*\*[^*]+(?:\*\*\s*[::]|:\*\*)|#{1,2}\s)/;
|
|
262493
|
+
let inRemovableSection = false;
|
|
262494
|
+
const out3 = [];
|
|
262495
|
+
for (const line of lines2) {
|
|
262496
|
+
if (inRemovableSection) {
|
|
262497
|
+
if (boundaryRe.test(line)) {
|
|
262498
|
+
inRemovableSection = false;
|
|
262499
|
+
} else {
|
|
262500
|
+
changed = true;
|
|
262501
|
+
continue;
|
|
262502
|
+
}
|
|
262503
|
+
}
|
|
262504
|
+
if (deliveryStampRe.test(line)) {
|
|
262505
|
+
inRemovableSection = true;
|
|
262506
|
+
changed = true;
|
|
262507
|
+
continue;
|
|
262508
|
+
}
|
|
262509
|
+
const narrativeMatch = narrativeLabelRe.exec(line);
|
|
262510
|
+
if (narrativeMatch !== null && narrativeMatch[1] !== void 0) {
|
|
262511
|
+
const label4 = narrativeMatch[1].toLowerCase();
|
|
262512
|
+
if (baseline !== void 0 && !baselineNarrativeLabels.has(label4)) {
|
|
262513
|
+
inRemovableSection = true;
|
|
262514
|
+
changed = true;
|
|
262515
|
+
continue;
|
|
262516
|
+
}
|
|
262517
|
+
}
|
|
262440
262518
|
if (/^#\s/.test(line) && /[✅✔]\s*$/.test(line)) {
|
|
262441
262519
|
changed = true;
|
|
262442
|
-
|
|
262520
|
+
out3.push(line.replace(/\s*[✅✔]\s*$/, ""));
|
|
262521
|
+
continue;
|
|
262443
262522
|
}
|
|
262444
262523
|
if (/^\*\*Status\*\*\s*:/.test(line) && /[✅✔]\s*(Done|Fixed|Fix)\b/i.test(line)) {
|
|
262445
262524
|
changed = true;
|
|
262446
|
-
|
|
262525
|
+
out3.push("**Status**: \u{1F4CB} Todo");
|
|
262526
|
+
continue;
|
|
262447
262527
|
}
|
|
262448
262528
|
if (/^(\s*[-*]\s+)\[[xX]\]/.test(line)) {
|
|
262449
262529
|
changed = true;
|
|
262450
|
-
|
|
262530
|
+
out3.push(line.replace(/^(\s*[-*]\s+)\[[xX]\]/, "$1[ ]"));
|
|
262531
|
+
continue;
|
|
262451
262532
|
}
|
|
262452
|
-
|
|
262453
|
-
}
|
|
262533
|
+
out3.push(line);
|
|
262534
|
+
}
|
|
262454
262535
|
return { text: out3.join("\n"), changed };
|
|
262455
262536
|
}
|
|
262537
|
+
function collectNarrativeLabels(baseline, labelRe) {
|
|
262538
|
+
const labels = /* @__PURE__ */ new Set();
|
|
262539
|
+
if (baseline === void 0)
|
|
262540
|
+
return labels;
|
|
262541
|
+
for (const line of baseline.split("\n")) {
|
|
262542
|
+
const m7 = labelRe.exec(line);
|
|
262543
|
+
if (m7 !== null && m7[1] !== void 0)
|
|
262544
|
+
labels.add(m7[1].toLowerCase());
|
|
262545
|
+
}
|
|
262546
|
+
return labels;
|
|
262547
|
+
}
|
|
262548
|
+
function readSpecBaseline(specPath) {
|
|
262549
|
+
try {
|
|
262550
|
+
const dir = dirname41(specPath);
|
|
262551
|
+
const top = execFileSync22("git", ["-C", dir, "rev-parse", "--show-toplevel"], {
|
|
262552
|
+
encoding: "utf8",
|
|
262553
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
262554
|
+
}).trim();
|
|
262555
|
+
if (top === "")
|
|
262556
|
+
return void 0;
|
|
262557
|
+
let rel = specPath.startsWith(top) ? specPath.slice(top.length) : specPath;
|
|
262558
|
+
rel = rel.replace(/^[/\\]+/, "");
|
|
262559
|
+
const out3 = execFileSync22("git", ["-C", top, "show", `HEAD:${rel}`], {
|
|
262560
|
+
encoding: "utf8",
|
|
262561
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
262562
|
+
});
|
|
262563
|
+
return out3;
|
|
262564
|
+
} catch {
|
|
262565
|
+
return void 0;
|
|
262566
|
+
}
|
|
262567
|
+
}
|
|
262456
262568
|
function resetStaleSpecTruth(ports, storyId) {
|
|
262457
262569
|
try {
|
|
262458
262570
|
const specPath = join97(cardArchiveDir(ports.repoCwd, storyId), "spec.md");
|
|
262459
262571
|
if (!existsSync93(specPath))
|
|
262460
262572
|
return;
|
|
262461
262573
|
const before = readFileSync87(specPath, "utf8");
|
|
262462
|
-
const
|
|
262574
|
+
const baseline = readSpecBaseline(specPath);
|
|
262575
|
+
const { text: text2, changed } = resetSpecTruthText(before, baseline);
|
|
262463
262576
|
if (!changed)
|
|
262464
262577
|
return;
|
|
262465
262578
|
writeFileSync44(specPath, text2);
|
|
@@ -262467,6 +262580,42 @@ function resetStaleSpecTruth(ports, storyId) {
|
|
|
262467
262580
|
} catch {
|
|
262468
262581
|
}
|
|
262469
262582
|
}
|
|
262583
|
+
function cleanStaleEvidence(projectCwd, storyId, cycleId) {
|
|
262584
|
+
try {
|
|
262585
|
+
const cardDir = cardArchiveDir(projectCwd, storyId);
|
|
262586
|
+
if (!existsSync93(cardDir))
|
|
262587
|
+
return;
|
|
262588
|
+
const diagDir = join97(cardDir, "failed-diagnostics");
|
|
262589
|
+
mkdirSync42(diagDir, { recursive: true });
|
|
262590
|
+
const reportName = reportFileName(storyId);
|
|
262591
|
+
const latestReport = join97(cardDir, "latest", reportName);
|
|
262592
|
+
if (existsSync93(latestReport)) {
|
|
262593
|
+
renameSync15(latestReport, join97(diagDir, reportName));
|
|
262594
|
+
}
|
|
262595
|
+
const acMap = join97(cardDir, "ac-map.json");
|
|
262596
|
+
if (existsSync93(acMap)) {
|
|
262597
|
+
renameSync15(acMap, join97(diagDir, "ac-map.json"));
|
|
262598
|
+
}
|
|
262599
|
+
const latestLink = join97(cardDir, "latest");
|
|
262600
|
+
if (existsSync93(latestLink)) {
|
|
262601
|
+
const st = lstatSync4(latestLink);
|
|
262602
|
+
if (st.isSymbolicLink() || st.isDirectory()) {
|
|
262603
|
+
rmSync16(latestLink, { recursive: true, force: true });
|
|
262604
|
+
}
|
|
262605
|
+
}
|
|
262606
|
+
const readme = join97(diagDir, "README.md");
|
|
262607
|
+
if (!existsSync93(readme)) {
|
|
262608
|
+
writeFileSync44(readme, `# Failed-cycle diagnostics
|
|
262609
|
+
|
|
262610
|
+
Artifacts in this directory were produced by a cycle that did NOT merge to main. They are retained for debugging only and MUST NOT be treated as delivery evidence.
|
|
262611
|
+
|
|
262612
|
+
- cycle: ${cycleId}
|
|
262613
|
+
- story: ${storyId}
|
|
262614
|
+
`, "utf8");
|
|
262615
|
+
}
|
|
262616
|
+
} catch {
|
|
262617
|
+
}
|
|
262618
|
+
}
|
|
262470
262619
|
function runVisualEvidencePreflight(ports, storyId, cycleId) {
|
|
262471
262620
|
try {
|
|
262472
262621
|
const specPath = join97(cardArchiveDir(ports.repoCwd, storyId), "spec.md");
|
|
@@ -264358,6 +264507,11 @@ async function loopRunOnceCommand(args) {
|
|
|
264358
264507
|
return 0;
|
|
264359
264508
|
}
|
|
264360
264509
|
}
|
|
264510
|
+
if (allowedCards !== void 0) {
|
|
264511
|
+
for (const storyId of allowedCards) {
|
|
264512
|
+
removePendingPublish(rt, storyId);
|
|
264513
|
+
}
|
|
264514
|
+
}
|
|
264361
264515
|
if (isLoopPaused(id.path, id.slug)) {
|
|
264362
264516
|
const lang11 = resolveLang({
|
|
264363
264517
|
rollLang: process.env["ROLL_LANG"],
|
|
@@ -264738,7 +264892,7 @@ function writeRepoAlert(alertsPath, eventsPath2, cycleId, result) {
|
|
|
264738
264892
|
// packages/cli/dist/commands/offboard.js
|
|
264739
264893
|
init_dist();
|
|
264740
264894
|
import { spawnSync as spawnSync14 } from "node:child_process";
|
|
264741
|
-
import { existsSync as existsSync98, readFileSync as readFileSync92, realpathSync as realpathSync13, renameSync as
|
|
264895
|
+
import { existsSync as existsSync98, readFileSync as readFileSync92, realpathSync as realpathSync13, renameSync as renameSync16, rmSync as rmSync17, writeFileSync as writeFileSync49 } from "node:fs";
|
|
264742
264896
|
import { homedir as homedir27 } from "node:os";
|
|
264743
264897
|
import { join as join102, resolve as resolve8 } from "node:path";
|
|
264744
264898
|
function pal5() {
|
|
@@ -264837,7 +264991,7 @@ function writeFileAtomic2(path, text2) {
|
|
|
264837
264991
|
const tmp = `${path}.tmp-${process.pid}-${Date.now()}`;
|
|
264838
264992
|
try {
|
|
264839
264993
|
writeFileSync49(tmp, text2);
|
|
264840
|
-
|
|
264994
|
+
renameSync16(tmp, path);
|
|
264841
264995
|
} catch (error) {
|
|
264842
264996
|
rmSync17(tmp, { force: true });
|
|
264843
264997
|
throw error;
|