@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/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 scorers = basePool.filter((a) => isAvailable(a));
4930
- if (scorers.length === 0)
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 = scorers.filter((a) => working !== "" && isHeterogeneous(a, working));
4933
- const sameVendor = scorers.filter((a) => working === "" || !isHeterogeneous(a, working));
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 existsSync64, readFileSync as readFileSync60 } from "node:fs";
231364
- import { basename as basename14, dirname as dirname32, extname, join as join66, relative as relative5, resolve as resolve5, sep as sep4 } from "node:path";
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, dirname32(tsconfigPath));
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 = join66(root, "tsconfig.json");
231490
- if (existsSync64(direct))
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) => join66(root, candidate)).filter((path) => existsSync64(path));
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 (!existsSync64(fileName))
231506
+ if (!existsSync65(fileName))
231501
231507
  return void 0;
231502
- return ts.ScriptSnapshot.fromString(readFileSync60(fileName, "utf8"));
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(dirname32(containingFile), specifier);
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 (existsSync64(candidate))
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 = join66(root, file);
231846
- if (existsSync64(path) && readFileSync60(path, "utf8").includes(name))
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
- if (candidates.length === 0) {
235451
- deps.event({ type: "pair:none-available", cycleId, stage: scoreStage, reason: "no scorer available to spawn a fresh review session", ts: deps.now() });
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 allowedSet = selectionAllowedAgents === void 0 ? void 0 : new Set([...selectionAllowedAgents].map(canonicalAgentName));
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 lines2 = stdout.split(/\r?\n/);
235531
- const scoreLines = lines2.map((line, index) => ({ index, match: /^\s*SCORE:\s*(\d{1,2})\s*$/i.exec(line) })).filter((entry) => entry.match !== null);
235532
- const verdictLines = lines2.map((line, index) => ({ index, match: /^\s*VERDICT:\s*(good|ok|regression)\s*$/i.exec(line) })).filter((entry) => entry.match !== null);
235533
- const rationaleLines = lines2.map((line, index) => ({ index, match: /^\s*RATIONALE:\s*(.+)$/i.exec(line) })).filter((entry) => entry.match !== null);
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(stdout);
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 existsSync47, mkdirSync as mkdirSync25, readFileSync as readFileSync44, statSync as statSync15, writeFileSync as writeFileSync24 } from "node:fs";
246270
- import { dirname as dirname27, join as join50 } from "node:path";
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 readFileSync44(absPath, "utf8");
247516
+ return readFileSync45(absPath, "utf8");
247422
247517
  } catch {
247423
247518
  return "";
247424
247519
  }
247425
247520
  },
247426
247521
  writeText(absPath, text2) {
247427
- mkdirSync25(dirname27(absPath), { recursive: true });
247428
- writeFileSync24(absPath, text2, "utf8");
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 = join50(projectPath3, ".roll");
247456
- if (!existsSync47(rollDir))
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 = join50(projectPath3, ".roll", "backlog.md");
247555
- const backlog = existsSync47(backlogPath) ? parseBacklog(readFileSync44(backlogPath, "utf8")).map((it) => ({ id: it.id, status: it.status, dependsOn: depsOf(it.desc) })) : [];
247556
- const agentsPath = join50(projectPath3, ".roll", "agents.yaml");
247557
- const routeConfigErrors = existsSync47(agentsPath) ? normalizeAgentConfig(readFileSync44(agentsPath, "utf8")).errors : [];
247558
- const eventsPath2 = join50(projectPath3, ".roll", "loop", "events.ndjson");
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 (existsSync47(eventsPath2))
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: join50(projectPath3, ".roll", "loop", "events.ndjson"),
247642
- peerDir: join50(projectPath3, ".roll", "loop", "peer"),
247643
- cycleLogDir: join50(projectPath3, ".roll", "loop", "cycle-logs")
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 = join50(projectPath3, ".roll", "loop", "events.ndjson");
247851
+ const eventsPath2 = join51(projectPath3, ".roll", "loop", "events.ndjson");
247754
247852
  try {
247755
- if (existsSync47(eventsPath2))
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 existsSync49, readFileSync as readFileSync46 } from "node:fs";
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 existsSync48, mkdirSync as mkdirSync26, readFileSync as readFileSync45, renameSync as renameSync10, realpathSync as realpathSync7, writeFileSync as writeFileSync25 } from "node:fs";
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 dirname28, join as join51 } from "node:path";
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 join51(registryHome(home), ".roll", "projects.json");
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 = readFileSync45(projectsRegistryPath(home), "utf8");
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
- mkdirSync26(dirname28(path), { recursive: true });
248090
+ mkdirSync27(dirname29(path), { recursive: true });
247993
248091
  const tmp = `${path}.${process.pid}.tmp`;
247994
- writeFileSync25(tmp, serializeProjectsRegistry(merged), "utf8");
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 = existsSync49) {
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 = readFileSync46(projectsRegistryPath(), "utf8");
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 existsSync50, readFileSync as readFileSync47, readdirSync as readdirSync17 } from "node:fs";
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 join52 } from "node:path";
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 join52(envRt, "runs.jsonl");
248129
- const sharedDefault = join52(sharedRoot(), "loop", "runs.jsonl");
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 join52(proj, ".roll", "loop", "runs.jsonl");
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(join52(d, "runs.jsonl"));
248364
+ candidates.push(join53(d, "runs.jsonl"));
248267
248365
  } else if ((process.env["ROLL_PROJECT_RUNTIME_DIR"] ?? "").trim()) {
248268
- candidates.push(join52(process.env["ROLL_PROJECT_RUNTIME_DIR"].trim(), "runs.jsonl"));
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() || join52(homedir17(), "Library", "LaunchAgents");
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 = readFileSync47(join52(laDir, pl), "utf8");
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(join52(m7[1], ".roll", "loop", "runs.jsonl"));
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 (!existsSync50(f) || readFileSync47(f, "utf8").trim() === "")
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(readFileSync47(f, "utf8")));
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 (!existsSync50(src)) {
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(readFileSync47(src, "utf8"));
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 (!existsSync50(src) || readFileSync47(src, "utf8").trim() === "") {
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(readFileSync47(src, "utf8")).filter((r) => str3(r["project"]) === slug2);
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 = join52(proj, ".roll", "backlog.md");
248404
- if (existsSync50(blPath)) {
248501
+ const blPath = join53(proj, ".roll", "backlog.md");
248502
+ if (existsSync51(blPath)) {
248405
248503
  try {
248406
- backlogText = readFileSync47(blPath, "utf8");
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 existsSync51, mkdirSync as mkdirSync27, readFileSync as readFileSync48, writeFileSync as writeFileSync26 } from "node:fs";
248420
- import { dirname as dirname29, join as join53 } from "node:path";
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 (!existsSync51(runsSrc) || readFileSync48(runsSrc, "utf8").trim() === "") {
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 readFileSync48(runsSrc, "utf8").split("\n")) {
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() || join53(projectPath3, ".roll", "loop");
248472
- const seenFile = join53(rtDir, `signals-seen-${slug2}`);
248473
- const candFile = join53(projectPath3, ".roll", "signals", "candidates.md");
248474
- mkdirSync27(rtDir, { recursive: true });
248475
- mkdirSync27(dirname29(candFile), { recursive: true });
248476
- if (!existsSync51(seenFile))
248477
- writeFileSync26(seenFile, "");
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 (existsSync51(candFile)) {
248480
- for (const m7 of readFileSync48(candFile, "utf8").matchAll(/CAND-(\d+)/g)) {
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(existsSync51(seenFile) ? readFileSync48(seenFile, "utf8").split("\n").filter((l) => l !== "") : []);
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 existsSync52, readFileSync as readFileSync49, readdirSync as readdirSync18 } from "node:fs";
248534
- import { basename as basename12, join as join54 } from "node:path";
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 = readFileSync49(file, "utf8");
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 = join54(projectPath(), ".roll", "cycle-logs");
248663
+ const logsDir = join55(projectPath(), ".roll", "cycle-logs");
248566
248664
  const all = logFiles(logsDir);
248567
- if (!existsSync52(logsDir) || all.length === 0) {
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(join54(logsDir, latest));
248678
+ showLog(join55(logsDir, latest));
248581
248679
  return 0;
248582
248680
  }
248583
- const exact = join54(logsDir, `${query}.log`);
248584
- if (existsSync52(exact)) {
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(join54(logsDir, matches[0]));
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 existsSync53, readFileSync as readFileSync50 } from "node:fs";
248607
- import { join as join55 } from "node:path";
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 join55(projectPath3, ".roll", "loop", "goal.yaml");
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 (!existsSync53(path)) {
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(readFileSync50(path, "utf8"))));
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 existsSync55, mkdirSync as mkdirSync29, readFileSync as readFileSync52, renameSync as renameSync12, statSync as statSync17, writeFileSync as writeFileSync28 } from "node:fs";
248693
- import { dirname as dirname31, join as join57 } from "node:path";
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 existsSync54, mkdirSync as mkdirSync28, mkdtempSync as mkdtempSync3, readFileSync as readFileSync51, readdirSync as readdirSync19, readSync, renameSync as renameSync11, rmSync as rmSync12, statSync as statSync16, writeFileSync as writeFileSync27 } from "node:fs";
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 dirname30, join as join56 } from "node:path";
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: existsSync54,
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 = join56(dir, bin);
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 = join56(mkdtempSync3(join56(tmpdir5(), "roll-screen-probe-")), "probe.png");
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(dirname30(tmp), { recursive: true, force: true });
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() || join56(deps.home, ".roll");
249001
- return join56(rollHome4, "cache", "terminal-screen-recording.json");
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(readFileSync51(path, "utf8"));
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
- mkdirSync28(dirname30(path), { recursive: true });
249020
- writeFileSync27(tmpPath, JSON.stringify({
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(join56(cache, "chromium"));
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 join56(deps.home, "Library", "Caches", "ms-playwright");
249157
+ return join57(deps.home, "Library", "Caches", "ms-playwright");
249060
249158
  if (deps.platform === "win32")
249061
- return join56(deps.env["LOCALAPPDATA"] ?? join56(deps.home, "AppData", "Local"), "ms-playwright");
249062
- return join56(deps.home, ".cache", "ms-playwright");
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 readFileSync52(absPath, "utf8");
249276
+ return readFileSync53(absPath, "utf8");
249179
249277
  } catch {
249180
249278
  return "";
249181
249279
  }
249182
249280
  },
249183
249281
  writeText(absPath, text2) {
249184
- mkdirSync29(dirname31(absPath), { recursive: true });
249185
- writeFileSync28(absPath, text2, "utf8");
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 join57(projectPath3, ".roll", "loop");
249364
+ return join58(projectPath3, ".roll", "loop");
249267
249365
  }
249268
249366
  function goalPath2(projectPath3) {
249269
- return join57(runtimeDir5(projectPath3), "goal.yaml");
249367
+ return join58(runtimeDir5(projectPath3), "goal.yaml");
249270
249368
  }
249271
249369
  function goLockPath(projectPath3) {
249272
- return join57(runtimeDir5(projectPath3), "go.lock");
249370
+ return join58(runtimeDir5(projectPath3), "go.lock");
249273
249371
  }
249274
249372
  function pauseMarkerPath2(projectPath3, slug2) {
249275
- return join57(runtimeDir5(projectPath3), `PAUSE-${slug2}`);
249373
+ return join58(runtimeDir5(projectPath3), `PAUSE-${slug2}`);
249276
249374
  }
249277
249375
  function eventsPath(projectPath3) {
249278
- return join57(runtimeDir5(projectPath3), "events.ndjson");
249376
+ return join58(runtimeDir5(projectPath3), "events.ndjson");
249279
249377
  }
249280
249378
  function runsPath2(projectPath3) {
249281
- return join57(runtimeDir5(projectPath3), "runs.jsonl");
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
- mkdirSync29(dirname31(path), { recursive: true });
249653
+ mkdirSync30(dirname32(path), { recursive: true });
249556
249654
  const tmp = `${path}.tmp-${process.pid}`;
249557
- writeFileSync28(tmp, renderGoalYaml(goal), "utf8");
249655
+ writeFileSync29(tmp, renderGoalYaml(goal), "utf8");
249558
249656
  renameSync12(tmp, path);
249559
249657
  }
249560
249658
  function readGoal(path) {
249561
- if (!existsSync55(path))
249659
+ if (!existsSync56(path))
249562
249660
  return void 0;
249563
- return parseGoalYaml(readFileSync52(path, "utf8"));
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 = readFileSync52(path, "utf8");
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(readFileSync52(join57(projectPath3, ".roll", "backlog.md"), "utf8")).map((row2) => ({
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(readFileSync52(join57(projectPath3, ".roll", "index.json"), "utf8"));
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 = join57(projectPath3, ".roll", "loop", "runs.jsonl");
249756
+ const runsPath3 = join58(projectPath3, ".roll", "loop", "runs.jsonl");
249659
249757
  let content = "";
249660
249758
  try {
249661
- content = readFileSync52(runsPath3, "utf8");
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 join57(runtimeDir5(projectPath3), `ALERT-${slug2}.md`);
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
- mkdirSync29(dirname31(path), { recursive: true });
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
- mkdirSync29(dirname31(path), { recursive: true });
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
- mkdirSync29(dirname31(path), { recursive: true });
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 (!existsSync55(path))
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 existsSync55(join57(projectPath3, ".roll", "backlog.md"));
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 = join57(cardArchiveDir(projectPath3, row2.id), "notes");
249906
- mkdirSync29(notesDir, { recursive: true });
249907
- writeFileSync28(join57(notesDir, fileName), body, "utf8");
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 = readFileSync52(path, "utf8");
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 (!existsSync55(path) || statSync17(path).mtimeMs / 1e3 < sinceSec)
250259
+ if (!existsSync56(path) || statSync17(path).mtimeMs / 1e3 < sinceSec)
250162
250260
  return void 0;
250163
- const lines2 = readFileSync52(path, "utf8").split("\n").map((line2) => line2.trim()).filter((line2) => line2 !== "");
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 = join57(runtimeDir5(projectPath3), "inner.lock");
250275
+ const path = join58(runtimeDir5(projectPath3), "inner.lock");
250178
250276
  try {
250179
- if (!existsSync55(path))
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
- mkdirSync29(rt, { recursive: true });
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 (existsSync55(pauseMarkerPath2(id.path, id.slug))) {
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 (existsSync55(pauseMarkerPath2(id.path, id.slug)))
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 (existsSync55(pauseMarkerPath2(id.path, id.slug))) {
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 existsSync56, readFileSync as readFileSync53 } from "node:fs";
250479
- import { join as join58 } from "node:path";
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 = join58(sharedRoot(), "loop", `events-${slug2}.ndjson`);
250487
- if (!existsSync56(evfile)) {
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 = readFileSync53(evfile, "utf8").split("\n").filter((l) => l !== "");
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 existsSync61, mkdtempSync as mkdtempSync5, readFileSync as readFileSync58, readdirSync as readdirSync24, statSync as statSync21, writeFileSync as writeFileSync30 } from "node:fs";
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 join63 } from "node:path";
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 existsSync59, mkdtempSync as mkdtempSync4, readFileSync as readFileSync56, readdirSync as readdirSync22, statSync as statSync19, writeFileSync as writeFileSync29 } from "node:fs";
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 join61 } from "node:path";
250640
+ import { join as join62 } from "node:path";
250543
250641
 
250544
250642
  // packages/cli/dist/lib/skills-panel.js
250545
- import { existsSync as existsSync58, readFileSync as readFileSync55, readdirSync as readdirSync21, statSync as statSync18 } from "node:fs";
250546
- import { join as join60 } from "node:path";
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 existsSync57, readFileSync as readFileSync54, readdirSync as readdirSync20 } from "node:fs";
250550
- import { join as join59, relative as relative4, sep as sep3 } from "node:path";
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 (!existsSync57(dir))
250696
+ if (!existsSync58(dir))
250599
250697
  return [];
250600
250698
  return readdirSync20(dir, { withFileTypes: true }).flatMap((entry) => {
250601
- const full = join59(dir, entry.name);
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(join59(skillDir, dirName)).map((file) => toPosix(relative4(skillDir, file))));
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 = readFileSync54(file, "utf8");
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 = readFileSync54(file, "utf8");
250757
+ const text2 = readFileSync55(file, "utf8");
250660
250758
  const { fields: fields2, body, ok: ok12 } = parseFrontmatter(text2);
250661
- const skillDir = join59(file, "..");
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) => existsSync57(join59(skillDir, 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 (!existsSync57(skillsDir2))
250784
+ if (!existsSync58(skillsDir2))
250687
250785
  return [];
250688
- return readdirSync20(skillsDir2, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join59(skillsDir2, entry.name, "SKILL.md")).filter((file) => existsSync57(file)).sort();
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 (!existsSync57(routeFile))
250789
+ if (!existsSync58(routeFile))
250692
250790
  return { skills: {} };
250693
250791
  try {
250694
- return JSON.parse(readFileSync54(routeFile, "utf8"));
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 ?? join59(options.skillsDir, "route-cases", "skills.json");
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 = join60(projectPath3, "skills");
250751
- if (!existsSync58(skillsDir2))
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 readFileSync55(path, "utf8").split("\n").length;
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 = join60(dir, e.name);
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 = join60(sub, f);
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(join60(dir, e.name)), dir: false });
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 (!existsSync58(skillsRoot))
250926
+ if (!existsSync59(skillsRoot))
250829
250927
  return [];
250830
250928
  try {
250831
- return readdirSync21(skillsRoot, { withFileTypes: true }).filter((e) => e.isDirectory() && existsSync58(join60(skillsRoot, e.name, "SKILL.md"))).map((e) => e.name).sort((a, b) => a.localeCompare(b));
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 = join60(projectPath3, "skills");
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 = join60(skillsRoot, name);
250846
- const hubPath = join60(dir, "SKILL.md");
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: existsSync58(hubPath) ? readFileSync55(hubPath, "utf8") : ""
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 join61(pkgDir(), "guide", "skills.md");
250984
+ return join62(pkgDir(), "guide", "skills.md");
250887
250985
  }
250888
250986
  function isInstallTree() {
250889
- return !existsSync59(join61(pkgDir(), "guide"));
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 join61(pkgDir(), "skills");
250994
+ return join62(pkgDir(), "skills");
250897
250995
  }
250898
250996
  function frontmatterField(file, field2) {
250899
- const lines2 = readFileSync56(file, "utf8").split("\n");
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 = join61(dir, name);
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 = join61(skillDir, "SKILL.md");
250967
- if (!existsSync59(skillMd))
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
- writeFileSync29(target, generateCatalog());
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 (!existsSync59(target)) {
251146
+ if (!existsSync60(target)) {
251049
251147
  err8(t(v2Catalog, lang11, "skills.check_missing", target));
251050
251148
  return 1;
251051
251149
  }
251052
- const fresh = join61(mkdtempSync4(join61(tmpdir6(), "roll-skills-")), "skills.md");
251053
- writeFileSync29(fresh, generateCatalog());
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
- writeFileSync29(target, generateCatalog());
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 existsSync60, lstatSync as lstatSync2, readFileSync as readFileSync57, readdirSync as readdirSync23, statSync as statSync20 } from "node:fs";
251177
- import { basename as basename13, join as join62 } from "node:path";
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 = readFileSync57(fullPath, "utf8");
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 = join62(projectDir, ".roll", "backlog.md");
251235
- if (existsSync60(backlogPath)) {
251236
- const content = readFileSync57(backlogPath, "utf8");
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 (!existsSync60(projectDir)) {
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 = join62(dir, entry);
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 = join62(dir, entry);
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"] ?? join63(homedir19(), ".roll");
251359
- return join63(rollHome4, "config.yaml");
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(join63(dir, bin));
251496
+ const st = statSync21(join64(dir, bin));
251399
251497
  if (!st.isFile())
251400
251498
  continue;
251401
- accessSync3(join63(dir, bin), constants3.X_OK);
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 (!existsSync61(cfg))
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 = readFileSync58(cfg, "utf8");
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 existsSync61(join63(".github", "workflows", "pr-review-event.yml")) ? "present" : "absent";
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 = join63(pkgDir2(), "skills");
251676
+ const skillsDir2 = join64(pkgDir2(), "skills");
251579
251677
  if (!safeIsDir(skillsDir2))
251580
251678
  return;
251581
- const target = join63(pkgDir2(), "guide", "skills.md");
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 (!existsSync61(target)) {
251684
+ if (!existsSync62(target)) {
251587
251685
  drift = true;
251588
251686
  } else {
251589
- const fresh = join63(mkdtempSync5(join63(tmpdir7(), "roll-doctor-")), "skills.md");
251590
- writeFileSync30(fresh, generateCatalog());
251591
- drift = readFileSync58(target, "utf8") !== readFileSync58(fresh, "utf8");
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"] ?? join63(homedir19(), "Library", "LaunchAgents");
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(join63(dir, name));
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"] ?? join63(homedir19(), "Library", "LaunchAgents");
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 = join63(dir, name);
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 = readFileSync58(plist, "utf8");
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 existsSync65, appendFileSync as appendFileSync12, mkdirSync as mkdirSync30, readFileSync as readFileSync61, renameSync as renameSync13, unlinkSync as unlinkSync3, writeFileSync as writeFileSync31 } from "node:fs";
251819
- import { join as join67 } from "node:path";
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 existsSync62, readFileSync as readFileSync59 } from "node:fs";
251921
+ import { existsSync as existsSync63, readFileSync as readFileSync60 } from "node:fs";
251824
251922
  import { homedir as homedir20 } from "node:os";
251825
- import { join as join64 } from "node:path";
251923
+ import { join as join65 } from "node:path";
251826
251924
  function readSkillBody(projectPath3, opts) {
251827
251925
  const candidates = [
251828
251926
  opts.envOverride ?? "",
251829
- join64(projectPath3, ".roll", "skills", opts.skillName, "SKILL.md"),
251830
- join64(projectPath3, "skills", opts.skillName, "SKILL.md"),
251831
- join64(homedir20(), ".roll", "skills", opts.skillName, "SKILL.md")
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 (!existsSync62(p))
251932
+ if (!existsSync63(p))
251835
251933
  continue;
251836
251934
  let raw = "";
251837
251935
  try {
251838
- raw = readFileSync59(p, "utf8");
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 existsSync63, readdirSync as readdirSync25, rmSync as rmSync13, statSync as statSync22 } from "node:fs";
251852
- import { join as join65 } from "node:path";
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(join65(dir, e.name)).mtimeMs / 1e3) });
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 = join65(projectPath3, ".roll", "features");
251875
- if (existsSync63(featuresRoot)) {
251972
+ const featuresRoot = join66(projectPath3, ".roll", "features");
251973
+ if (existsSync64(featuresRoot)) {
251876
251974
  for (const epic of safeDirs(featuresRoot)) {
251877
- const epicDir = join65(featuresRoot, epic);
251975
+ const epicDir = join66(featuresRoot, epic);
251878
251976
  for (const story of safeDirs(epicDir)) {
251879
- const dir = join65(epicDir, story);
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 = join65(projectPath3, ".roll", "verification");
251887
- if (existsSync63(verRoot)) {
251984
+ const verRoot = join66(projectPath3, ".roll", "verification");
251985
+ if (existsSync64(verRoot)) {
251888
251986
  for (const story of safeDirs(verRoot)) {
251889
- const dir = join65(verRoot, story);
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(join65(sa.dir, runId), { recursive: true, force: true });
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 (!existsSync65(dormant))
252073
+ if (!existsSync66(dormant))
251976
252074
  return { rearmed: false };
251977
- const scanPath = join67(projectPath3, ".roll", "dream", "structure-scan.json");
251978
- if (!existsSync65(scanPath))
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 = readFileSync61(scanPath, "utf8");
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(join67(projectPath3, ".roll", "backlog.md"));
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 = join67(projectPath3, ".roll", "loop");
251999
- const launchdDir = join67(homedir21(), "Library", "LaunchAgents");
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: join67(projectPath3, ".roll", "backlog.md"),
252006
- eventsPath: join67(loopDir, "events.ndjson"),
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) => existsSync65(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: join67(launchdDir, `${label4}.plist`)
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 = join67(id.path, ".roll", "dream");
252026
- const log = join67(dreamDir, "cron.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
- mkdirSync30(dreamDir, { recursive: true });
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
- writeFileSync31(join67(dreamDir, "structure-scan.json"), `${JSON.stringify(preScan.json, null, 2)}
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 existsSync66, mkdirSync as mkdirSync31, writeFileSync as writeFileSync32 } from "node:fs";
252142
- import { join as join68 } from "node:path";
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 (!existsSync66(BACKLOG_PATH2)) {
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 = join68(projectPath3, ".roll", "features", epic, plan.id);
252310
+ const cardDir = join69(projectPath3, ".roll", "features", epic, plan.id);
252213
252311
  try {
252214
- if (existsSync66(join68(cardDir, "spec.md"))) {
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
- mkdirSync31(cardDir, { recursive: true });
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
- writeFileSync32(join68(cardDir, "spec.md"), renderSpecMd(card), "utf8");
252227
- writeFileSync32(join68(cardDir, "index.html"), renderStoryPage(card), "utf8");
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 existsSync75, readFileSync as readFileSync69, readdirSync as readdirSync29, statSync as statSync24, writeFileSync as writeFileSync33 } from "node:fs";
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 join78 } from "node:path";
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 existsSync67 } from "node:fs";
253473
- import { join as join69 } from "node:path";
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 existsSync67(join69(cwd, rel));
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 existsSync68, readFileSync as readFileSync62 } from "node:fs";
253619
- import { join as join70 } from "node:path";
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 = join70(cwd, "conventions", "config.yaml");
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 = join70(cwd, rel);
253653
- if (!existsSync68(abs))
253750
+ const abs = join71(cwd, rel);
253751
+ if (!existsSync69(abs))
253654
253752
  return void 0;
253655
253753
  try {
253656
- return readFileSync62(abs, "utf8");
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 existsSync70, readFileSync as readFileSync64 } from "node:fs";
253707
- import { join as join72 } from "node:path";
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 existsSync69, lstatSync as lstatSync3, readdirSync as readdirSync26, readFileSync as readFileSync63, realpathSync as realpathSync8, statSync as statSync23 } from "node:fs";
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 dirname33, join as join71 } from "node:path";
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"] ?? join71(homedir22(), ".roll");
253826
+ return process.env["ROLL_HOME"] ?? join72(homedir22(), ".roll");
253729
253827
  }
253730
- var globalDir = () => join71(rollHome2(), "conventions", "global");
253731
- var templatesDir = () => join71(rollHome2(), "conventions", "templates");
253732
- var configPath = () => join71(rollHome2(), "config.yaml");
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, existsSync69(join71(globalDir(), 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 (!existsSync69(cfg))
253853
+ if (!existsSync70(cfg))
253756
253854
  return [];
253757
253855
  const entries = [];
253758
- for (const line of readFileSync63(cfg, "utf8").split("\n")) {
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(dirname33(aiDir)).replace(/^\.+/, "");
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 = join71(e.ai_dir, e.cfg_file);
253779
- const rollMd = join71(e.ai_dir, "roll.md");
253780
- const src = join71(globalDir(), e.src_file);
253781
- if (!existsSync69(cfgFile))
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 (!existsSync69(rollMd))
253881
+ if (!existsSync70(rollMd))
253784
253882
  return "out-of-sync";
253785
253883
  try {
253786
- if (existsSync69(src) && !readFileSync63(rollMd).equals(readFileSync63(src)))
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 (!readFileSync63(cfgFile, "utf8").includes("@roll.md"))
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 = join71(e.ai_dir, "skills");
253801
- if (!existsSync69(skillsDir2))
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 = join71(skillsDir2, name);
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 = join71(dir, name);
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 = join71(templatesDir(), tpl);
253832
- if (!existsSync69(d))
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 = join71(rollHome2(), "skills");
253842
- if (!existsSync69(sd))
253939
+ const sd = join72(rollHome2(), "skills");
253940
+ if (!existsSync70(sd))
253843
253941
  return 0;
253844
253942
  try {
253845
- return readdirSync26(sd).filter((n) => statSync23(join71(sd, n)).isDirectory()).length;
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 = join71(homedir22(), "Library", "LaunchAgents", `${label4}.plist`);
253853
- if (!existsSync69(plist))
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: join71(e.ai_dir, e.cfg_file).replaceAll(home, "~"),
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 (existsSync69(featDir)) {
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: existsSync69("AGENTS.md"),
254005
- project_has_backlog: existsSync69(".roll/backlog.md"),
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 = join72(projectPath3, ".roll", "loop", "runs.jsonl");
254200
- if (!existsSync70(path))
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 = readFileSync64(path, "utf8");
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: join72(entry.ai_dir, entry.cfg_file),
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 existsSync72, readFileSync as readFileSync66, readdirSync as readdirSync27 } from "node:fs";
254274
- import { join as join74 } from "node:path";
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 existsSync71, readFileSync as readFileSync65 } from "node:fs";
254280
- import { join as join73 } from "node:path";
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(readFileSync65(join73(projectPath3, "package.json"), "utf8"));
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 = readFileSync65(join73(projectPath3, "CHANGELOG.md"), "utf8");
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 = join73(projectPath3, ".roll", "loop", "events.ndjson");
254368
- if (!existsSync71(path))
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 readFileSync65(path, "utf8").split("\n")) {
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 = join74(projectPath3, ".roll", "reports", "consistency");
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(readFileSync66(join74(dir, latest), "utf8"));
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 = join74(projectPath3, ".roll", "loop", "events.ndjson");
254435
- if (existsSync72(path)) {
254532
+ const path = join75(projectPath3, ".roll", "loop", "events.ndjson");
254533
+ if (existsSync73(path)) {
254436
254534
  const tags = [];
254437
- for (const line of readFileSync66(path, "utf8").split("\n")) {
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 existsSync73, readFileSync as readFileSync67 } from "node:fs";
254456
- import { join as join75 } from "node:path";
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 = join75(projectPath3, ".roll", "loop", "events.ndjson");
254469
- if (!existsSync73(path))
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 readFileSync67(path, "utf8").split("\n")) {
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 = join75(projectPath3, "CHANGELOG.md");
254580
- if (!existsSync73(path))
254677
+ const path = join76(projectPath3, "CHANGELOG.md");
254678
+ if (!existsSync74(path))
254581
254679
  return [];
254582
254680
  let text2 = "";
254583
254681
  try {
254584
- text2 = readFileSync67(path, "utf8");
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 = join75(projectPath3, ".roll", "loop", "events.ndjson");
254591
- if (existsSync73(ev)) {
254592
- for (const line of readFileSync67(ev, "utf8").split("\n")) {
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 existsSync74, readFileSync as readFileSync68 } from "node:fs";
254952
- import { join as join76 } from "node:path";
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 = join76(projectPath3, ".roll", "loop", file);
255059
+ const path = join77(projectPath3, ".roll", "loop", file);
254962
255060
  try {
254963
- const lines2 = readFileSync68(path, "utf8").trim().split("\n");
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 = join76(launchAgentsDir3, `com.roll.${svc}.${slug2}.plist`);
255085
+ const p = join77(launchAgentsDir3, `com.roll.${svc}.${slug2}.plist`);
254988
255086
  try {
254989
- return existsSync74(p) ? readFileSync68(p, "utf8") : null;
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 readFileSync68(join76(projectPath3, ".roll", "loop", "goal.yaml"), "utf8");
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 readFileSync68(join76(projectPath3, ".roll", "loop", "events.ndjson"), "utf8");
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 join77, resolve as resolve6 } from "node:path";
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 === "" ? join77(projectPath3, ".git", "hooks") : isAbsolute(gitPath) ? gitPath : resolve6(projectPath3, 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) => join77(resolved.displayPath, 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 = join78(cwd, ".roll", "loop");
255334
- if (!existsSync75(loopDir))
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
- writeFileSync33(join78(loopDir, `cycle-${row2.cycleId}.signals.jsonl`), signals.map((sig) => JSON.stringify(sig)).join("\n") + "\n", "utf8");
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 = join78(projectPath3, ".roll", "reports", "consistency");
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(readFileSync69(join78(dir, latest), "utf8"));
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 (!existsSync75(join78(projectPath3, ".roll", "loop", "runs.jsonl")))
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 = join78(projectPath3, ".roll", "loop", "events.ndjson");
255507
+ const path = join79(projectPath3, ".roll", "loop", "events.ndjson");
255410
255508
  let content = "";
255411
255509
  try {
255412
- content = readFileSync69(path, "utf8");
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 : join78(projectPath3, ".roll", "loop");
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 = join78(runtimeDir6(projectPath3), "live.log");
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 (!existsSync75(livePath)) {
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 = readFileSync69(livePath, "utf8");
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: join78(runtimeDir6(cwd), "live.log"),
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 = join78(storyDir, "spec.md");
255579
- if (!existsSync75(specPath))
255676
+ const specPath = join79(storyDir, "spec.md");
255677
+ if (!existsSync76(specPath))
255580
255678
  return null;
255581
255679
  let md;
255582
255680
  try {
255583
- md = readFileSync69(specPath, "utf8");
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 (existsSync75(join78(cwd, ".roll", "features"))) {
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 = join78(cwd, ".roll", "features");
255656
- if (!existsSync75(featuresDir))
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
- writeFileSync33(join78(featuresDir, "truth.json"), snapshotJson2, "utf8");
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
- writeFileSync33(join78(featuresDir, "index.html"), renderTruthConsole({
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
- writeFileSync33(join78(featuresDir, "agents.html"), renderAgentsMachinePage({ ...machineBar, agents: collectAgentPanel(cwd), externalTools: collectExternalTools() }), "utf8");
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
- writeFileSync33(join78(featuresDir, file), html, "utf8");
255896
+ writeFileSync34(join79(featuresDir, file), html, "utf8");
255799
255897
  pages += 1;
255800
255898
  } catch {
255801
255899
  }
255802
255900
  }
255803
255901
  try {
255804
- writeFileSync33(join78(featuresDir, "tools.html"), renderToolsPage({ ...machineBar, tools: collectToolPanel() }), "utf8");
255902
+ writeFileSync34(join79(featuresDir, "tools.html"), renderToolsPage({ ...machineBar, tools: collectToolPanel() }), "utf8");
255805
255903
  pages += 1;
255806
255904
  } catch {
255807
255905
  }
255808
255906
  try {
255809
- writeFileSync33(join78(featuresDir, "conventions.html"), renderConventionsPage({ ...machineBar, vm: collectConventions(defaultConventionsDeps(cwd, agentRows, renderMarkdown)) }), "utf8");
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
- writeFileSync33(join78(featuresDir, "about.html"), renderAboutPage({ ...machineBar, vm: collectAbout(defaultAboutDeps(cwd)) }), "utf8");
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
- writeFileSync33(join78(featuresDir, epic.name, "index.html"), renderEpicPage(epic), "utf8");
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 = join78(featuresDir, epic.name, story.id);
255925
+ const storyDir = join79(featuresDir, epic.name, story.id);
255828
255926
  try {
255829
- const storyIndex = join78(storyDir, "index.html");
255830
- if (rebuild || !existsSync75(storyIndex)) {
255831
- writeFileSync33(storyIndex, renderStoryDossier(inputs.get(`${epic.name}/${story.id}`) ?? collectStoryDossierInput(cwd, story, runCache)), "utf8");
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
- writeFileSync33(join78(storyDir, "spec.html"), specHtml, "utf8");
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 existsSync76, mkdirSync as mkdirSync32, writeFileSync as writeFileSync34 } from "node:fs";
255862
- import { join as join79 } from "node:path";
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 = join79(cwd, ".roll", "features", epic, id);
255896
- if (existsSync76(join79(dir, "spec.md"))) {
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
- mkdirSync32(dir, { recursive: true });
255910
- writeFileSync34(join79(dir, "spec.md"), renderSpecMd(meta8), "utf8");
255911
- writeFileSync34(join79(dir, "index.html"), renderStoryPage(meta8), "utf8");
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 = join79(cwd, ".roll", "backlog.md");
255915
- if (existsSync76(backlogPath)) {
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 readFileSync70 } from "node:fs";
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 = readFileSync70(spec, "utf8");
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 existsSync82, mkdtempSync as mkdtempSync6, mkdirSync as mkdirSync34, readSync as readSync4, readFileSync as readFileSync75, readdirSync as readdirSync30, realpathSync as realpathSync10, renameSync as renameSync14, rmSync as rmSync14, statSync as statSync28, writeFileSync as writeFileSync36 } from "node:fs";
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 dirname35, join as join85 } from "node:path";
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 existsSync77, opendirSync, readFileSync as readFileSync71, realpathSync as realpathSync9, statSync as statSync25 } from "node:fs";
256042
- import { join as join80 } from "node:path";
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(join80(root, rel)) : existsSync77(join80(root, rel))).sort();
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 = existsSync77(join80(projectDir, ".git"));
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 = join80(dir, entry);
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 = join80(projectDir, rel);
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 = readFileSync71(path, "utf8");
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(join80(projectDir, rel)).toLowerCase();
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 = join80(projectDir, dir);
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(join80(dir, entry));
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(join80(projectDir, ".roll"));
256394
+ const dotRoll = isDir3(join81(projectDir, ".roll"));
256297
256395
  let dotRollMarker = dotRoll;
256298
256396
  if (dotRoll && deps.ignoreOnboardArtifacts === true) {
256299
- const listed = sortedDirectoryEntries(join80(projectDir, ".roll"), MAX_SOURCE_DIR_ENTRIES);
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(join80(projectDir, ".roll", "backlog.md")),
256305
- features: isDir3(join80(projectDir, ".roll", "features")),
256306
- agentsDoc: isFile(join80(projectDir, "AGENTS.md")),
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: existsSync77(join80(projectDir, ".git")), commits: 0 },
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(join80(projectDir, dir), 4, MAX_SOURCE_FILES - sourceFileCount);
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 existsSync78 } from "node:fs";
256436
- import { join as join81 } from "node:path";
256533
+ import { existsSync as existsSync79 } from "node:fs";
256534
+ import { join as join82 } from "node:path";
256437
256535
  function existsProjectPath(projectDir, rel) {
256438
- return existsSync78(join81(projectDir, rel.replace(/\/$/, "")));
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 existsSync79, mkdirSync as mkdirSync33, readFileSync as readFileSync72, statSync as statSync26, writeFileSync as writeFileSync35 } from "node:fs";
256491
- import { dirname as dirname34, join as join82 } from "node:path";
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 = join82(projectDir, rel);
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 = readFileSync72(path, "utf8").slice(0, MAX_SOURCE_BYTES);
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 = join82(projectDir, ".roll", "brief.md");
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: !existsSync79(briefPath),
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
- mkdirSync33(dirname34(briefPath), { recursive: true });
256560
- writeFileSync35(briefPath, sourcePath !== void 0 ? renderPrdBrief(projectDir, sourcePath) : renderEmptyBrief(options.emptyDescription));
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 existsSync80, readFileSync as readFileSync73 } from "node:fs";
256567
- import { join as join83 } from "node:path";
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(join83(projectDir, ".roll", "init-diagnosis.yaml"));
256659
- const hasApplyMetadata = existsSync80(join83(projectDir, ".roll", "onboard-changeset.yaml"));
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 (!existsSync80(path))
256771
+ if (!existsSync81(path))
256674
256772
  return null;
256675
- const match = /^factsHash:\s*"?([^"\n]+)"?/m.exec(readFileSync73(path, "utf8"));
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 existsSync80(join83(projectDir, target.replace(/\/$/, "")));
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 = join83(projectDir, target);
256711
- const exists = existsSync80(path);
256712
- const hasEntry = exists && readFileSync73(path, "utf8").split("\n").includes(".roll/");
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 existsSync81, readFileSync as readFileSync74, readSync as readSync2, statSync as statSync27 } from "node:fs";
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 join84 } from "node:path";
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 = join84(dir, bin);
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) => existsSync81(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 (!existsSync81(cfg))
256908
+ if (!existsSync82(cfg))
256811
256909
  return { installed, missing };
256812
256910
  const env = agentEnv ?? realAgentEnv();
256813
- for (const line of readFileSync74(cfg, "utf8").split("\n")) {
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 (!existsSync81(cfg))
256928
+ if (!existsSync82(cfg))
256831
256929
  return null;
256832
- for (const line of readFileSync74(cfg, "utf8").split("\n")) {
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 = join84(rollPkgDir(), "skills", skillName, "SKILL.md");
256844
- if (!existsSync81(skillFile))
256941
+ const skillFile = join85(rollPkgDir(), "skills", skillName, "SKILL.md");
256942
+ if (!existsSync82(skillFile))
256845
256943
  return null;
256846
- return readFileSync74(skillFile, "utf8").replace(/^---\n[\s\S]*?\n---\n?/, "").trim();
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"] ?? join85(homedir24(), ".roll");
257166
+ return process.env["ROLL_HOME"] ?? join86(homedir24(), ".roll");
257069
257167
  }
257070
257168
  function rollGlobal2() {
257071
- return join85(rollHome3(), "conventions", "global");
257169
+ return join86(rollHome3(), "conventions", "global");
257072
257170
  }
257073
257171
  function rollTemplates2() {
257074
- return join85(rollHome3(), "conventions", "templates");
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 = join85(dir, "package.json");
257178
+ const pkg = join86(dir, "package.json");
257081
257179
  const readPkg = () => {
257082
257180
  try {
257083
- return readFileSync75(pkg, "utf8");
257181
+ return readFileSync76(pkg, "utf8");
257084
257182
  } catch {
257085
257183
  return "";
257086
257184
  }
257087
257185
  };
257088
- if (existsSync82(pkg)) {
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) => existsSync82(join85(dir, d))))
257190
+ if (["src", "app", "pages", "components"].some((d) => existsSync83(join86(dir, d))))
257093
257191
  hasFrontend = true;
257094
- if (["server", "api", "backend"].some((d) => existsSync82(join85(dir, 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) => existsSync82(join85(dir, 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 (existsSync82(pkg)) {
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 (existsSync82(join85(dir, "prisma", "schema.prisma")))
257200
+ if (existsSync83(join86(dir, "prisma", "schema.prisma")))
257103
257201
  hasBackend = true;
257104
- if (existsSync82(join85(dir, "bin")) || existsSync82(join85(dir, "cmd")))
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 = join85(rollGlobal2(), "AGENTS.md");
257141
- const dst = join85(projectDir, "AGENTS.md");
257142
- if (!existsSync82(src)) {
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 = readFileSync75(src, "utf8");
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 (!existsSync82(dst)) {
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 = readFileSync75(dst, "utf8");
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 = join85(rollTemplates2(), projectType, "CLAUDE.md");
257225
- if (!existsSync82(tplFile))
257322
+ const tplFile = join86(rollTemplates2(), projectType, "CLAUDE.md");
257323
+ if (!existsSync83(tplFile))
257226
257324
  return;
257227
- const claudeDir = join85(projectDir, ".claude");
257228
- const outFile = join85(claudeDir, "CLAUDE.md");
257229
- mkdirSync34(claudeDir, { recursive: true });
257230
- if (!existsSync82(outFile)) {
257231
- writeFileAtomic(outFile, readFileSync75(tplFile, "utf8"));
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 = readFileSync75(tplFile, "utf8");
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 = readFileSync75(outFile, "utf8");
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 (existsSync82(path)) {
257379
+ if (existsSync83(path)) {
257282
257380
  summary.push("unchanged|.roll/backlog.md");
257283
257381
  return;
257284
257382
  }
257285
- mkdirSync34(dirname35(path), { recursive: true });
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 (existsSync82(path) && statSync28(path).isDirectory()) {
257388
+ if (existsSync83(path) && statSync28(path).isDirectory()) {
257291
257389
  summary.push("unchanged|.roll/features/");
257292
257390
  return;
257293
257391
  }
257294
- mkdirSync34(path, { recursive: true });
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 (existsSync82(path)) {
257406
+ if (existsSync83(path)) {
257309
257407
  summary.push("unchanged|.roll/features.md");
257310
257408
  return;
257311
257409
  }
257312
- mkdirSync34(dirname35(path), { recursive: true });
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 = join85(projectDir, ".roll", "agents.yaml");
257336
- if (existsSync82(dest)) {
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
- mkdirSync34(dirname35(dest), { recursive: true });
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 = join85(projectDir, ".roll", ".version");
257347
- if (existsSync82(stampPath)) {
257444
+ const stampPath = join86(projectDir, ".roll", ".version");
257445
+ if (existsSync83(stampPath)) {
257348
257446
  summary.push("unchanged|.roll/.version");
257349
257447
  return;
257350
257448
  }
257351
- mkdirSync34(join85(projectDir, ".roll"), { recursive: true });
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
- writeFileSync36(tmp, text2);
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 join85(projectDir, ".roll", "onboard-changeset.yaml");
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
- mkdirSync34(dirname35(path), { recursive: true });
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 (!existsSync82(path))
257523
+ if (!existsSync83(path))
257426
257524
  return parsed;
257427
257525
  let current = null;
257428
- for (const rawLine of readFileSync75(path, "utf8").split("\n")) {
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 (!existsSync82(backlog))
257685
+ if (!existsSync83(backlog))
257588
257686
  return false;
257589
- const text2 = readFileSync75(backlog, "utf8");
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 = join85(rollPkgDir(), "lib", "roll-onboard-render.py");
257637
- if (!existsSync82(renderer))
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) => existsSync82(join85(projectDir, 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 = join85(projectDir, ".roll", "backlog.md");
257768
+ const backlog = join86(projectDir, ".roll", "backlog.md");
257671
257769
  if (seedIds.length > 0) {
257672
- if (!existsSync82(backlog))
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 (!existsSync82(backlog))
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 = join85(projectDir, ".gitignore");
257700
- const current = existsSync82(gi) ? readFileSync75(gi, "utf8") : "";
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 existsSync82(join85(rollTemplates2(), projectType, "CLAUDE.md"));
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 && existsSync82(join85(projectDir, rel)))
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 && existsSync82(join85(projectDir, rel)))
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 = join85(projectDir, ".roll", "features");
257824
- if (existsSync82(featuresDir) && !statSync28(featuresDir).isDirectory()) {
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 (!existsSync82(rollTemplates2())) {
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 = join85(projectDir, ".roll", "backlog.md");
257860
- const backlogExisted = existsSync82(backlog);
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 = join85(projectDir, ".roll", "features");
257864
- const featuresDirExisted = existsSync82(featuresDir);
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 = join85(projectDir, ".roll", "features.md");
257868
- const featuresMdExisted = existsSync82(featuresMd);
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 = join85(projectDir, ".roll", ".version");
257872
- const stampExisted = existsSync82(stamp);
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 = join85(projectDir, ".roll", "onboard-plan.yaml");
257881
- const validator = join85(rollPkgDir(), "lib", "roll-plan-validate.py");
257882
- if (!existsSync82(plan)) {
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 (!existsSync82(validator)) {
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 = join85(projectDir, ".roll", ".version");
257936
- const stampExisted = existsSync82(stamp);
258033
+ const stamp = join86(projectDir, ".roll", ".version");
258034
+ const stampExisted = existsSync83(stamp);
257937
258035
  writeVersionStamp(projectDir, summary);
257938
- if (!stampExisted && existsSync82(stamp))
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 = join85(projectDir, ".roll", "backlog.md");
257943
- const existed = existsSync82(backlogPath);
258040
+ const backlogPath = join86(projectDir, ".roll", "backlog.md");
258041
+ const existed = existsSync83(backlogPath);
257944
258042
  writeBacklog(backlogPath, summary);
257945
- if (!existed && existsSync82(backlogPath))
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 = join85(projectDir, ".roll", "agents.yaml");
257951
- const existed = existsSync82(routesPath);
257952
- if (initSeedProjectAgents(projectDir, summary) === 0 && !existed && existsSync82(routesPath)) {
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 = join85(projectDir, ".roll", "features");
257958
- const featuresMd = join85(projectDir, ".roll", "features.md");
257959
- const dirExisted = existsSync82(featuresDir);
257960
- const mdExisted = existsSync82(featuresMd);
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 && existsSync82(featuresDir))
258061
+ if (!dirExisted && existsSync83(featuresDir))
257964
258062
  recordChangeset(projectDir, changeset, "dirs_created", ".roll/features");
257965
- if (!mdExisted && existsSync82(featuresMd))
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 = join85(projectDir, ".roll", "domain");
257970
- const existed = existsSync82(path);
257971
- mkdirSync34(path, { recursive: true });
257972
- if (!existed && existsSync82(path))
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 = join85(projectDir, ".roll", "briefs");
257977
- const existed = existsSync82(path);
257978
- mkdirSync34(path, { recursive: true });
257979
- if (!existed && existsSync82(path))
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("/") ? join85(projectDir, rel.slice(0, -1)) : join85(projectDir, rel);
258292
- if (existsSync82(path))
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(join85(tmpdir8(), "roll-init-attest-prd-only-")));
258398
+ const workspace = realpathSync10(mkdtempSync6(join86(tmpdir8(), "roll-init-attest-prd-only-")));
258301
258399
  let status2 = 1;
258302
258400
  try {
258303
- const smokeHome = join85(workspace, ".roll-home");
258304
- mkdirSync34(smokeHome, { recursive: true });
258305
- cpSync(join85(rollPkgDir(), "conventions"), join85(smokeHome, "conventions"), { recursive: true });
258306
- writeFileSync36(join85(smokeHome, "config.yaml"), "# Roll config\nlang: en\n");
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
- mkdirSync34(join85(workspace, "docs"), { recursive: true });
258309
- writeFileSync36(join85(workspace, "docs", "intel-radar-PRD.md"), "# Intel Radar PRD\n\nBuild a radar for intelligence signals with source ranking and daily review.\n");
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: ${existsSync82(workspace) ? "failed" : "removed"} ${workspace}
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
- writeFileSync36(join85(workspace, "README.md"), "# Existing App\n\nA service with real source and tests.\n");
258332
- writeFileSync36(join85(workspace, "package.json"), '{"scripts":{"test":"vitest"}}\n');
258333
- mkdirSync34(join85(workspace, "src"), { recursive: true });
258334
- writeFileSync36(join85(workspace, "src", "index.ts"), "export const value = 1;\n");
258335
- mkdirSync34(join85(workspace, "tests"), { recursive: true });
258336
- writeFileSync36(join85(workspace, "tests", "index.test.ts"), "import { expect, it } from 'vitest';\nit('works', () => expect(1).toBe(1));\n");
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}: ${existsSync82(join85(projectDir, rel)) ? "present" : "missing"}
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 = existsSync82(join85(workspace, ".gitignore")) ? readFileSync75(join85(workspace, ".gitignore"), "utf8") : "";
258370
- const changeset = existsSync82(join85(workspace, ".roll", "onboard-changeset.yaml")) ? readFileSync75(join85(workspace, ".roll", "onboard-changeset.yaml"), "utf8") : "";
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(join85(tmpdir8(), "roll-init-attest-existing-codebase-")));
258393
- const emptyBin = realpathSync10(mkdtempSync6(join85(tmpdir8(), "roll-init-attest-empty-bin-")));
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: ${existsSync82(workspace) ? "failed" : "removed"} ${workspace}
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(join85(tmpdir8(), "roll-init-invalid-plan-")));
258567
+ const workspace = realpathSync10(mkdtempSync6(join86(tmpdir8(), "roll-init-invalid-plan-")));
258470
258568
  const staleHash = "sha256:dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd";
258471
258569
  try {
258472
- const smokeHome = join85(workspace, ".roll-home");
258473
- mkdirSync34(smokeHome, { recursive: true });
258474
- cpSync(join85(rollPkgDir(), "conventions"), join85(smokeHome, "conventions"), { recursive: true });
258475
- writeFileSync36(join85(smokeHome, "config.yaml"), "# Roll config\nlang: en\n");
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
- mkdirSync34(join85(workspace, ".roll"), { recursive: true });
258479
- writeFileSync36(join85(workspace, ".roll", "init-diagnosis.yaml"), onboardDiagnosisFixture(staleHash));
258480
- writeFileSync36(join85(workspace, ".roll", "onboard-plan.yaml"), onboardPlanFixture(staleHash));
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: ${existsSync82(join85(workspace, "AGENTS.md")) ? "present" : "missing"}
258589
+ process.stdout.write(` AGENTS.md: ${existsSync83(join86(workspace, "AGENTS.md")) ? "present" : "missing"}
258492
258590
  `);
258493
- process.stdout.write(` .roll/backlog.md: ${existsSync82(join85(workspace, ".roll", "backlog.md")) ? "present" : "missing"}
258591
+ process.stdout.write(` .roll/backlog.md: ${existsSync83(join86(workspace, ".roll", "backlog.md")) ? "present" : "missing"}
258494
258592
  `);
258495
- process.stdout.write(` .gitignore: ${existsSync82(join85(workspace, ".gitignore")) ? "present" : "missing"}
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: ${existsSync82(workspace) ? "failed" : "removed"} ${workspace}
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(join85(tmpdir8(), "roll-init-review-")));
258610
+ const workspace = realpathSync10(mkdtempSync6(join86(tmpdir8(), "roll-init-review-")));
258513
258611
  try {
258514
- const smokeHome = join85(workspace, ".roll-home");
258515
- mkdirSync34(smokeHome, { recursive: true });
258516
- cpSync(join85(rollPkgDir(), "conventions"), join85(smokeHome, "conventions"), { recursive: true });
258517
- writeFileSync36(join85(smokeHome, "config.yaml"), "# Roll config\nlang: en\n");
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
- mkdirSync34(join85(workspace, ".roll"), { recursive: true });
258522
- writeFileSync36(join85(workspace, ".roll", "init-diagnosis.yaml"), onboardDiagnosisFixture(factsHash));
258523
- writeFileSync36(join85(workspace, ".roll", "onboard-plan.yaml"), onboardPlanFixture(factsHash));
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: ${existsSync82(join85(workspace, "AGENTS.md")) ? "present" : "missing"}
258632
+ process.stdout.write(` AGENTS.md: ${existsSync83(join86(workspace, "AGENTS.md")) ? "present" : "missing"}
258535
258633
  `);
258536
- process.stdout.write(` .roll/backlog.md: ${existsSync82(join85(workspace, ".roll", "backlog.md")) ? "present" : "missing"}
258634
+ process.stdout.write(` .roll/backlog.md: ${existsSync83(join86(workspace, ".roll", "backlog.md")) ? "present" : "missing"}
258537
258635
  `);
258538
- process.stdout.write(` .gitignore: ${existsSync82(join85(workspace, ".gitignore")) ? "present" : "missing"}
258636
+ process.stdout.write(` .gitignore: ${existsSync83(join86(workspace, ".gitignore")) ? "present" : "missing"}
258539
258637
  `);
258540
- return code === 1 && !existsSync82(join85(workspace, "AGENTS.md")) && !existsSync82(join85(workspace, ".roll", "backlog.md")) ? 0 : 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: ${existsSync82(workspace) ? "failed" : "removed"} ${workspace}
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
- mkdirSync34(join85(workspace, ".roll"), { recursive: true });
258555
- writeFileSync36(join85(workspace, ".roll", "init-diagnosis.yaml"), onboardDiagnosisFixture(factsHash));
258556
- writeFileSync36(join85(workspace, ".roll", "onboard-plan.yaml"), onboardPlanFixture(factsHash));
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(join85(tmpdir8(), "roll-init-existing-codebase-")));
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 = existsSync82(workspace) ? "failed" : "removed";
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("/") ? join85(projectDir, rel.slice(0, -1)) : join85(projectDir, rel);
258637
- process.stdout.write(` ${rel}: ${existsSync82(path) ? "present" : "missing"}
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(join85(tmpdir8(), "roll-init-partial-legacy-")));
258742
+ const workspace = realpathSync10(mkdtempSync6(join86(tmpdir8(), "roll-init-partial-legacy-")));
258645
258743
  let okSmoke = true;
258646
258744
  try {
258647
- const smokeHome = join85(workspace, ".roll-home");
258648
- mkdirSync34(smokeHome, { recursive: true });
258649
- cpSync(join85(rollPkgDir(), "conventions"), join85(smokeHome, "conventions"), { recursive: true });
258650
- writeFileSync36(join85(smokeHome, "config.yaml"), "# Roll config\nlang: en\n");
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 = join85(workspace, "partial-roll");
258653
- mkdirSync34(join85(partial, ".roll"), { recursive: true });
258654
- writeFileSync36(join85(partial, "AGENTS.md"), "# Owner Guide\n\nKeep this owner text.\n");
258655
- writeFileSync36(join85(partial, ".roll", "backlog.md"), "# Owner Backlog\n\nKeep this backlog.\n");
258656
- writeFileSync36(join85(partial, "BACKLOG.md"), "# Old Roll backlog\n");
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 = join85(workspace, "legacy-roll");
258674
- mkdirSync34(join85(legacy, "docs", "features"), { recursive: true });
258675
- writeFileSync36(join85(legacy, "BACKLOG.md"), "# Old Roll backlog\n");
258676
- writeFileSync36(join85(legacy, "docs", "features", "feature.md"), "# Old feature\n");
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: ${existsSync82(join85(legacy, "AGENTS.md")) ? "present" : "missing"}
258781
+ process.stdout.write(` AGENTS.md: ${existsSync83(join86(legacy, "AGENTS.md")) ? "present" : "missing"}
258684
258782
  `);
258685
- process.stdout.write(` .roll/: ${existsSync82(join85(legacy, ".roll")) ? "present" : "missing"}
258783
+ process.stdout.write(` .roll/: ${existsSync83(join86(legacy, ".roll")) ? "present" : "missing"}
258686
258784
  `);
258687
- okSmoke = okSmoke && legacyDiagnosis === 0 && !existsSync82(join85(legacy, "AGENTS.md")) && !existsSync82(join85(legacy, ".roll"));
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: ${existsSync82(workspace) ? "failed" : "removed"} ${workspace}
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 (!existsSync82(rollTemplates2())) {
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 (!existsSync82(rollTemplates2())) {
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 (existsSync82(join85(projectDir, "AGENTS.md"))) {
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(join85(projectDir, ".roll", "backlog.md"), summary);
258806
- ensureFeaturesDir(join85(projectDir, ".roll", "features"), summary);
258807
- writeFeaturesMd(join85(projectDir, ".roll", "features.md"), summary);
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 existsSync83, mkdtempSync as mkdtempSync7, mkdirSync as mkdirSync35, readFileSync as readFileSync76, realpathSync as realpathSync11, rmSync as rmSync15, writeFileSync as writeFileSync37 } from "node:fs";
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 dirname36, join as join86 } from "node:path";
258929
+ import { dirname as dirname37, join as join87 } from "node:path";
258832
258930
  function safeRead(path) {
258833
258931
  try {
258834
- return readFileSync76(path, "utf8");
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 existsSync83(path);
258939
+ return existsSync84(path);
258842
258940
  } catch {
258843
258941
  return false;
258844
258942
  }
258845
258943
  }
258846
258944
  function hasPendingOnboardPlan(projectDir) {
258847
- return existsFile(join86(projectDir, ".roll", "onboard-plan.yaml")) && !existsFile(join86(projectDir, ".roll", "onboard-changeset.yaml"));
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(join86(projectDir, ".roll", "brief.md")) ? "roll design --from-file .roll/brief.md" : null;
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 = join86(projectDir, ".roll", "backlog.md");
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 = join86(root, rel);
258939
- mkdirSync35(dirname36(path), { recursive: true });
258940
- writeFileSync37(path, text2);
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
- mkdirSync35(join86(root, rel), { recursive: true });
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(join86(tmpdir9(), "roll-next-journey-")));
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: join86(workspace, "prd-only") };
258960
- const codebaseOnboard = { label: "codebase-onboard", dir: join86(workspace, "codebase-onboard") };
258961
- const partialRoll = { label: "partial-roll", dir: join86(workspace, "partial-roll") };
258962
- const oldRollLayout = { label: "old-roll-layout", dir: join86(workspace, "old-roll-layout") };
258963
- const rollReady = { label: "roll-ready", dir: join86(workspace, "roll-ready") };
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 existsSync84, readFileSync as readFileSync77, statSync as statSync29 } from "node:fs";
259020
- import { join as join87, resolve as resolve7 } from "node:path";
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 existsSync84(join87(cwd, ".roll"));
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 = join87(cwd, ".roll", "backlog.md");
259183
+ const bp = join88(cwd, ".roll", "backlog.md");
259086
259184
  try {
259087
- const content = readFileSync77(bp, "utf8");
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 existsSync85, readFileSync as readFileSync78 } from "node:fs";
259219
- import { join as join88 } from "node:path";
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 : join88(projectPath3, ".roll", "loop");
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) => existsSync85(p),
259464
+ exists: (p) => existsSync86(p),
259367
259465
  readText: (p) => {
259368
259466
  try {
259369
- return readFileSync78(p, "utf8");
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 = join88(rt, opts.events || opts.rawEvents ? "events.ndjson" : "live.log");
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 = join88(rt, "events.ndjson");
259491
- const runsPath3 = join88(rt, "runs.jsonl");
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 mkdirSync37 } from "node:fs";
259514
- import { dirname as dirname38, join as join90 } from "node:path";
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 existsSync86, mkdirSync as mkdirSync36, readFileSync as readFileSync79, readdirSync as readdirSync31 } from "node:fs";
259521
- import { dirname as dirname37, join as join89 } from "node:path";
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) => join89(project, ".roll", "features");
259639
+ var FEATURES = (project) => join90(project, ".roll", "features");
259542
259640
  function findCardEpic(project, id) {
259543
259641
  const base = FEATURES(project);
259544
- if (!existsSync86(base))
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 (existsSync86(join89(base, epic.name, id, "spec.md")))
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 = readFileSync79(join89(FEATURES(project), epic, id, "spec.md"), "utf8");
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(readFileSync79(join89(FEATURES(project), epic, id, "spec.md"), "utf8"));
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 = join89(project, ".roll", "backlog.md");
259590
- const rt = (process.env["ROLL_PROJECT_RUNTIME_DIR"] ?? "").trim() || join89(project, ".roll", "loop");
259591
- const eventsPath2 = join89(rt, "events.ndjson");
259592
- const alertsPath = (process.env["ROLL_LOOP_ALERT"] ?? "").trim() || join89(rt, `ALERT-${(process.env["ROLL_MAIN_SLUG"] ?? "").trim() || projectSlug2(project)}.md`);
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
- mkdirSync36(dirname37(alertsPath), { recursive: true });
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() || join90(projectPath3, ".roll", "loop");
259735
- const alertsPath = (process.env["ROLL_LOOP_ALERT"] ?? "").trim() || join90(rt, `ALERT-${projectSlug2(projectPath3)}.md`);
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
- mkdirSync37(dirname38(alertsPath), { recursive: true });
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() || join90(project, ".roll", "loop");
259755
- const eventsPath2 = join90(rt, "events.ndjson");
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 existsSync87, readFileSync as readFileSync80, mkdirSync as mkdirSync38, writeFileSync as writeFileSync38 } from "node:fs";
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 = readFileSync80(eventsPath2, "utf-8");
259954
+ raw = readFileSync81(eventsPath2, "utf-8");
259857
259955
  } catch {
259858
259956
  return;
259859
259957
  }
259860
259958
  const outDir = `${cycleLogDir}/${cycleId}`;
259861
- if (!existsSync87(outDir)) {
259862
- mkdirSync38(outDir, { recursive: true });
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
- writeFileSync38(`${outDir}/summary.json`, JSON.stringify(summary, null, 2), "utf-8");
259880
- writeFileSync38(`${outDir}/summary.md`, renderCycleRoleSummaryMarkdown(summary), "utf-8");
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 existsSync88, readFileSync as readFileSync81, writeFileSync as writeFileSync39 } from "node:fs";
259979
- import { join as join91 } from "node:path";
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 join91(runtimeDir9, "skip-cards.json");
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 (!existsSync88(path))
260084
+ if (!existsSync89(path))
259987
260085
  return { fails: {}, skip: [] };
259988
- const o = JSON.parse(readFileSync81(path, "utf8"));
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
- writeFileSync39(skipFile(runtimeDir9), JSON.stringify(s, null, 2), "utf8");
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 out3 = lines2.map((line) => {
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
- return line.replace(/\s*[✅✔]\s*$/, "");
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
- return "**Status**: \u{1F4CB} Todo";
262525
+ out3.push("**Status**: \u{1F4CB} Todo");
262526
+ continue;
262447
262527
  }
262448
262528
  if (/^(\s*[-*]\s+)\[[xX]\]/.test(line)) {
262449
262529
  changed = true;
262450
- return line.replace(/^(\s*[-*]\s+)\[[xX]\]/, "$1[ ]");
262530
+ out3.push(line.replace(/^(\s*[-*]\s+)\[[xX]\]/, "$1[ ]"));
262531
+ continue;
262451
262532
  }
262452
- return line;
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 { text: text2, changed } = resetSpecTruthText(before);
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 renameSync15, rmSync as rmSync17, writeFileSync as writeFileSync49 } from "node:fs";
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
- renameSync15(tmp, path);
264994
+ renameSync16(tmp, path);
264841
264995
  } catch (error) {
264842
264996
  rmSync17(tmp, { force: true });
264843
264997
  throw error;