@seanyao/roll 3.625.1 → 3.625.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.
Files changed (3) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/roll.mjs +1114 -669
  3. package/package.json +1 -1
package/dist/roll.mjs CHANGED
@@ -3435,6 +3435,24 @@ function resolveRoute(tier, deps, nudge) {
3435
3435
  out3.warning = warning;
3436
3436
  return out3;
3437
3437
  }
3438
+ function resolveRouteExcluding(tier, deps, excluded) {
3439
+ const ex = new Set(excluded.filter((a) => a !== ""));
3440
+ const chain = tier === "default" ? ["default", "fallback"] : [tier, "default", "fallback"];
3441
+ for (const slot of chain) {
3442
+ const s = deps.readSlot(slot);
3443
+ if (s?.agent !== void 0 && s.agent !== "" && !ex.has(s.agent)) {
3444
+ const out3 = { agent: s.agent, tier };
3445
+ if (s.model !== void 0 && s.model !== "")
3446
+ out3.model = s.model;
3447
+ return out3;
3448
+ }
3449
+ }
3450
+ const first = deps.firstInstalled();
3451
+ if (first !== void 0 && first !== "" && !ex.has(first)) {
3452
+ return { agent: first, tier, warning: `agents.yaml: tier '${tier}' chain exhausted by exclusions; using first installed '${first}'` };
3453
+ }
3454
+ return null;
3455
+ }
3438
3456
  var EASY_MAX_MIN, HARD_MIN_MIN, SAMPLE_FLOOR;
3439
3457
  var init_router = __esm({
3440
3458
  "packages/core/dist/agent/router.js"() {
@@ -3813,26 +3831,26 @@ function floatOr(v) {
3813
3831
  const n = typeof v === "number" ? v : typeof v === "string" ? Number(v) : 0;
3814
3832
  return Number.isFinite(n) ? n : 0;
3815
3833
  }
3816
- function toCycleCost(usage4, facts) {
3834
+ function toCycleCost(usage5, facts) {
3817
3835
  const tokens = {
3818
- input_tokens: usage4.input_tokens,
3819
- output_tokens: usage4.output_tokens,
3820
- cache_creation_tokens: usage4.cache_creation_tokens ?? 0,
3821
- cache_read_tokens: usage4.cache_read_tokens ?? 0
3836
+ input_tokens: usage5.input_tokens,
3837
+ output_tokens: usage5.output_tokens,
3838
+ cache_creation_tokens: usage5.cache_creation_tokens ?? 0,
3839
+ cache_read_tokens: usage5.cache_read_tokens ?? 0
3822
3840
  };
3823
- const estimatedCost = usage4.cost_list_usd ?? computeListCost(usage4.model, tokens);
3841
+ const estimatedCost = usage5.cost_list_usd ?? computeListCost(usage5.model, tokens);
3824
3842
  const reverts = Math.max(0, Math.trunc(facts.revertCount));
3825
3843
  const effectiveCost = estimatedCost * (reverts + 1);
3826
- const cur = cycleCurrency(usage4.model);
3844
+ const cur = cycleCurrency(usage5.model);
3827
3845
  return {
3828
3846
  cycleId: facts.cycleId,
3829
3847
  agent: facts.agent,
3830
- model: usage4.model,
3831
- tokensIn: usage4.input_tokens,
3832
- tokensOut: usage4.output_tokens,
3848
+ model: usage5.model,
3849
+ tokensIn: usage5.input_tokens,
3850
+ tokensOut: usage5.output_tokens,
3833
3851
  // FIX-249: keep the cache split when the adapter reported one (absent ≠ 0).
3834
- ...usage4.cache_read_tokens !== void 0 ? { cacheRead: usage4.cache_read_tokens } : {},
3835
- ...usage4.cache_creation_tokens !== void 0 ? { cacheWrite: usage4.cache_creation_tokens } : {},
3852
+ ...usage5.cache_read_tokens !== void 0 ? { cacheRead: usage5.cache_read_tokens } : {},
3853
+ ...usage5.cache_creation_tokens !== void 0 ? { cacheWrite: usage5.cache_creation_tokens } : {},
3836
3854
  estimatedCost,
3837
3855
  revertCount: reverts,
3838
3856
  effectiveCost,
@@ -4004,12 +4022,12 @@ function peerReviewCost(peer, stdout) {
4004
4022
  try {
4005
4023
  const canon = canonicalAgentName(peer);
4006
4024
  const lines2 = stdout.split("\n");
4007
- const usage4 = extractUsage(canon, lines2);
4008
- if (usage4 === null)
4025
+ const usage5 = extractUsage(canon, lines2);
4026
+ if (usage5 === null)
4009
4027
  return 0;
4010
- if ((usage4.input_tokens ?? 0) === 0 && (usage4.output_tokens ?? 0) === 0)
4028
+ if ((usage5.input_tokens ?? 0) === 0 && (usage5.output_tokens ?? 0) === 0)
4011
4029
  return 0;
4012
- const { estimatedCost } = toCycleCost(usage4, { cycleId: "pair", agent: canon, revertCount: 0 });
4030
+ const { estimatedCost } = toCycleCost(usage5, { cycleId: "pair", agent: canon, revertCount: 0 });
4013
4031
  return Number.isFinite(estimatedCost) && estimatedCost > 0 ? estimatedCost : 0;
4014
4032
  } catch {
4015
4033
  return 0;
@@ -7704,6 +7722,19 @@ function cycleTimeoutVerdict(input) {
7704
7722
  const idleRemain = idle > 0 ? idle - input.idleSec : Number.POSITIVE_INFINITY;
7705
7723
  return { timedOut: false, remainingSec: Math.min(wallRemain, idleRemain) };
7706
7724
  }
7725
+ function stallVerdict(input) {
7726
+ const threshold = input.stallThresholdSec ?? CYCLE_STALL_THRESHOLD_SEC;
7727
+ const grace = input.startupGraceSec ?? STALL_STARTUP_GRACE_SEC;
7728
+ if (threshold <= 0)
7729
+ return { stalled: false };
7730
+ if (input.alreadyFired)
7731
+ return { stalled: false };
7732
+ if (input.elapsedSec < grace)
7733
+ return { stalled: false };
7734
+ if (input.idleSec < threshold)
7735
+ return { stalled: false };
7736
+ return { stalled: true, idleSec: input.idleSec, thresholdSec: threshold };
7737
+ }
7707
7738
  function retryPlan(input) {
7708
7739
  const max = input.maxAttempts ?? MAX_AGENT_ATTEMPTS;
7709
7740
  const base = input.baseBackoffSec ?? RETRY_BASE_BACKOFF_SEC;
@@ -7945,7 +7976,7 @@ function cycleStartEvent(ctx, ts2 = 0) {
7945
7976
  function initialCycleState(ctx) {
7946
7977
  return { phase: "pick", ctx, attempt: 0, done: false };
7947
7978
  }
7948
- var CYCLE_TIMEOUT_SEC, WATCHDOG_KILL_GRACE_SEC, CYCLE_WALL_TIMEOUT_SEC, CYCLE_NO_PROGRESS_SEC, MAX_AGENT_ATTEMPTS, RETRY_BASE_BACKOFF_SEC, EVENT_VALID_PHASES;
7979
+ var CYCLE_TIMEOUT_SEC, WATCHDOG_KILL_GRACE_SEC, CYCLE_WALL_TIMEOUT_SEC, CYCLE_NO_PROGRESS_SEC, CYCLE_STALL_THRESHOLD_SEC, STALL_STARTUP_GRACE_SEC, MAX_AGENT_ATTEMPTS, RETRY_BASE_BACKOFF_SEC, EVENT_VALID_PHASES;
7949
7980
  var init_orchestrator = __esm({
7950
7981
  "packages/core/dist/loop/orchestrator.js"() {
7951
7982
  "use strict";
@@ -7955,6 +7986,8 @@ var init_orchestrator = __esm({
7955
7986
  WATCHDOG_KILL_GRACE_SEC = 5;
7956
7987
  CYCLE_WALL_TIMEOUT_SEC = 2700;
7957
7988
  CYCLE_NO_PROGRESS_SEC = 900;
7989
+ CYCLE_STALL_THRESHOLD_SEC = 600;
7990
+ STALL_STARTUP_GRACE_SEC = 120;
7958
7991
  MAX_AGENT_ATTEMPTS = 3;
7959
7992
  RETRY_BASE_BACKOFF_SEC = 30;
7960
7993
  EVENT_VALID_PHASES = {
@@ -8306,6 +8339,73 @@ function watchRenderEventFromRollEvent(ev, mode = "events") {
8306
8339
  detail: [ev.path, ev.paused ? "paused" : ""].filter((v) => v !== "").join(" \xB7 "),
8307
8340
  severity: "muted"
8308
8341
  };
8342
+ // ── FIX-934: pair:* event rendering ────────────────────────────────────
8343
+ case "pair:selected":
8344
+ return {
8345
+ kind: "gate",
8346
+ observedAt: eventTs(ev),
8347
+ cycleId: ev.cycleId,
8348
+ summary: "pair:selected",
8349
+ detail: `${text(ev.workingAgent)} \u2192 ${text(ev.peer)} (${text(ev.stage)})`,
8350
+ severity: "normal"
8351
+ };
8352
+ case "pair:verdict":
8353
+ return {
8354
+ kind: "gate",
8355
+ observedAt: eventTs(ev),
8356
+ cycleId: ev.cycleId,
8357
+ summary: "pair:verdict",
8358
+ detail: [ev.peer, ev.verdict, `${ev.findings} finding${ev.findings === 1 ? "" : "s"}`, ev.stage !== void 0 ? ev.stage : ""].filter((v) => v !== "").join(" \xB7 "),
8359
+ severity: ev.verdict === "agree" ? "good" : ev.verdict === "object" ? "warn" : "normal"
8360
+ };
8361
+ case "pair:score":
8362
+ return {
8363
+ kind: "gate",
8364
+ observedAt: eventTs(ev),
8365
+ cycleId: ev.cycleId,
8366
+ summary: "pair:score",
8367
+ detail: [ev.peer, String(ev.score), ev.verdict].join(" \xB7 "),
8368
+ severity: ev.verdict === "good" ? "good" : ev.verdict === "regression" ? "bad" : "warn"
8369
+ };
8370
+ case "pair:consult": {
8371
+ const durSec = (ev.durationMs / 1e3).toFixed(1);
8372
+ const causeTag = ev.cause !== void 0 ? ` (${ev.cause})` : "";
8373
+ return {
8374
+ kind: "raw",
8375
+ observedAt: eventTs(ev),
8376
+ cycleId: ev.cycleId,
8377
+ summary: "pair:consult",
8378
+ detail: `${text(ev.peer)} \xB7 ${ev.outcome} \xB7 ${durSec}s${causeTag}`,
8379
+ severity: ev.outcome === "reviewed" ? "good" : ev.outcome === "timeout" ? "warn" : "bad"
8380
+ };
8381
+ }
8382
+ case "pair:none-available":
8383
+ return {
8384
+ kind: "gate",
8385
+ observedAt: eventTs(ev),
8386
+ cycleId: ev.cycleId,
8387
+ summary: "pair:none-available",
8388
+ detail: `${text(ev.stage)} \xB7 ${text(ev.reason)}`,
8389
+ severity: "warn"
8390
+ };
8391
+ case "pair:score-failure":
8392
+ return {
8393
+ kind: "gate",
8394
+ observedAt: eventTs(ev),
8395
+ cycleId: ev.cycleId,
8396
+ summary: "pair:score-failure",
8397
+ detail: [ev.peer, ev.cause, ev.detail !== void 0 ? ev.detail : ""].filter((v) => v !== "").join(" \xB7 "),
8398
+ severity: "bad"
8399
+ };
8400
+ case "pair:excluded":
8401
+ return {
8402
+ kind: "gate",
8403
+ observedAt: eventTs(ev),
8404
+ cycleId: ev.cycleId,
8405
+ summary: "pair:excluded",
8406
+ detail: `${text(ev.agent)} \xB7 ${ev.cause} \xB7 ${ev.failures} failure${ev.failures === 1 ? "" : "s"}`,
8407
+ severity: "warn"
8408
+ };
8309
8409
  default:
8310
8410
  return mode === "status" ? null : eventFromUnknown(ev);
8311
8411
  }
@@ -8399,6 +8499,24 @@ function signalLabel(ev) {
8399
8499
  return `${ev.type} #${ev.prNumber}`;
8400
8500
  case "alert:notify":
8401
8501
  return `alert ${clean2(ev.message)}`;
8502
+ // ── FIX-934: pair:* signal labels ─────────────────────────────────────
8503
+ case "pair:selected":
8504
+ return `pair ${clean2(ev.workingAgent)} \u2192 ${clean2(ev.peer)} (${clean2(ev.stage)})`;
8505
+ case "pair:verdict":
8506
+ return `pair ${clean2(ev.peer)} ${ev.verdict} (${ev.findings} finding${ev.findings === 1 ? "" : "s"})`;
8507
+ case "pair:score":
8508
+ return `pair ${clean2(ev.peer)} ${ev.score} ${ev.verdict}`;
8509
+ case "pair:consult": {
8510
+ const durSec = (ev.durationMs / 1e3).toFixed(1);
8511
+ const causeTag = ev.cause !== void 0 ? ` (${ev.cause})` : "";
8512
+ return `pair ${clean2(ev.peer)} ${ev.outcome} ${durSec}s${causeTag}`;
8513
+ }
8514
+ case "pair:none-available":
8515
+ return `pair ${clean2(ev.stage)} none-available`;
8516
+ case "pair:score-failure":
8517
+ return `pair ${clean2(ev.peer)} ${ev.cause}`;
8518
+ case "pair:excluded":
8519
+ return `pair ${clean2(ev.agent)} excluded ${ev.cause} (${ev.failures})`;
8402
8520
  default:
8403
8521
  return void 0;
8404
8522
  }
@@ -37442,7 +37560,7 @@ ${lanes.join("\n")}
37442
37560
  updateLineCountAndPosFor(s);
37443
37561
  }
37444
37562
  }
37445
- function write2(s) {
37563
+ function write3(s) {
37446
37564
  if (s) hasTrailingComment = false;
37447
37565
  writeText(s);
37448
37566
  }
@@ -37467,7 +37585,7 @@ ${lanes.join("\n")}
37467
37585
  }
37468
37586
  function writeLiteral(s) {
37469
37587
  if (s && s.length) {
37470
- write2(s);
37588
+ write3(s);
37471
37589
  }
37472
37590
  }
37473
37591
  function writeLine(force) {
@@ -37481,7 +37599,7 @@ ${lanes.join("\n")}
37481
37599
  }
37482
37600
  reset22();
37483
37601
  return {
37484
- write: write2,
37602
+ write: write3,
37485
37603
  rawWrite,
37486
37604
  writeLiteral,
37487
37605
  writeLine,
@@ -37500,15 +37618,15 @@ ${lanes.join("\n")}
37500
37618
  hasTrailingComment: () => hasTrailingComment,
37501
37619
  hasTrailingWhitespace: () => !!output.length && isWhiteSpaceLike(output.charCodeAt(output.length - 1)),
37502
37620
  clear: reset22,
37503
- writeKeyword: write2,
37504
- writeOperator: write2,
37505
- writeParameter: write2,
37506
- writeProperty: write2,
37507
- writePunctuation: write2,
37508
- writeSpace: write2,
37509
- writeStringLiteral: write2,
37510
- writeSymbol: (s, _) => write2(s),
37511
- writeTrailingSemicolon: write2,
37621
+ writeKeyword: write3,
37622
+ writeOperator: write3,
37623
+ writeParameter: write3,
37624
+ writeProperty: write3,
37625
+ writePunctuation: write3,
37626
+ writeSpace: write3,
37627
+ writeStringLiteral: write3,
37628
+ writeSymbol: (s, _) => write3(s),
37629
+ writeTrailingSemicolon: write3,
37512
37630
  writeComment
37513
37631
  };
37514
37632
  }
@@ -39738,34 +39856,34 @@ ${lanes.join("\n")}
39738
39856
  directories: directoriesMatcher,
39739
39857
  exclude: excludeMatcher
39740
39858
  };
39741
- function getRegularExpressionForWildcard(specs, basePath, usage4) {
39742
- const patterns = getRegularExpressionsForWildcards(specs, basePath, usage4);
39859
+ function getRegularExpressionForWildcard(specs, basePath, usage5) {
39860
+ const patterns = getRegularExpressionsForWildcards(specs, basePath, usage5);
39743
39861
  if (!patterns || !patterns.length) {
39744
39862
  return void 0;
39745
39863
  }
39746
39864
  const pattern = patterns.map((pattern2) => `(?:${pattern2})`).join("|");
39747
- const terminator = usage4 === "exclude" ? "(?:$|/)" : "$";
39865
+ const terminator = usage5 === "exclude" ? "(?:$|/)" : "$";
39748
39866
  return `^(?:${pattern})${terminator}`;
39749
39867
  }
39750
- function getRegularExpressionsForWildcards(specs, basePath, usage4) {
39868
+ function getRegularExpressionsForWildcards(specs, basePath, usage5) {
39751
39869
  if (specs === void 0 || specs.length === 0) {
39752
39870
  return void 0;
39753
39871
  }
39754
- return flatMap(specs, (spec) => spec && getSubPatternFromSpec(spec, basePath, usage4, wildcardMatchers[usage4]));
39872
+ return flatMap(specs, (spec) => spec && getSubPatternFromSpec(spec, basePath, usage5, wildcardMatchers[usage5]));
39755
39873
  }
39756
39874
  function isImplicitGlob(lastPathComponent) {
39757
39875
  return !/[.*?]/.test(lastPathComponent);
39758
39876
  }
39759
- function getPatternFromSpec(spec, basePath, usage4) {
39760
- const pattern = spec && getSubPatternFromSpec(spec, basePath, usage4, wildcardMatchers[usage4]);
39761
- return pattern && `^(?:${pattern})${usage4 === "exclude" ? "(?:$|/)" : "$"}`;
39877
+ function getPatternFromSpec(spec, basePath, usage5) {
39878
+ const pattern = spec && getSubPatternFromSpec(spec, basePath, usage5, wildcardMatchers[usage5]);
39879
+ return pattern && `^(?:${pattern})${usage5 === "exclude" ? "(?:$|/)" : "$"}`;
39762
39880
  }
39763
- function getSubPatternFromSpec(spec, basePath, usage4, { singleAsteriskRegexFragment, doubleAsteriskRegexFragment, replaceWildcardCharacter: replaceWildcardCharacter2 } = wildcardMatchers[usage4]) {
39881
+ function getSubPatternFromSpec(spec, basePath, usage5, { singleAsteriskRegexFragment, doubleAsteriskRegexFragment, replaceWildcardCharacter: replaceWildcardCharacter2 } = wildcardMatchers[usage5]) {
39764
39882
  let subpattern = "";
39765
39883
  let hasWrittenComponent = false;
39766
39884
  const components = getNormalizedPathComponents(spec, basePath);
39767
39885
  const lastComponent = last(components);
39768
- if (usage4 !== "exclude" && lastComponent === "**") {
39886
+ if (usage5 !== "exclude" && lastComponent === "**") {
39769
39887
  return void 0;
39770
39888
  }
39771
39889
  components[0] = removeTrailingDirectorySeparator(components[0]);
@@ -39777,14 +39895,14 @@ ${lanes.join("\n")}
39777
39895
  if (component === "**") {
39778
39896
  subpattern += doubleAsteriskRegexFragment;
39779
39897
  } else {
39780
- if (usage4 === "directories") {
39898
+ if (usage5 === "directories") {
39781
39899
  subpattern += "(?:";
39782
39900
  optionalCount++;
39783
39901
  }
39784
39902
  if (hasWrittenComponent) {
39785
39903
  subpattern += directorySeparator;
39786
39904
  }
39787
- if (usage4 !== "exclude") {
39905
+ if (usage5 !== "exclude") {
39788
39906
  let componentPattern = "";
39789
39907
  if (component.charCodeAt(0) === 42) {
39790
39908
  componentPattern += "(?:[^./]" + singleAsteriskRegexFragment + ")?";
@@ -73082,27 +73200,27 @@ ${lanes.join("\n")}
73082
73200
  }
73083
73201
  return Debug.fail("There should exist two symbols, one as property declaration and one as parameter declaration");
73084
73202
  }
73085
- function isBlockScopedNameDeclaredBeforeUse(declaration, usage4) {
73203
+ function isBlockScopedNameDeclaredBeforeUse(declaration, usage5) {
73086
73204
  const declarationFile = getSourceFileOfNode(declaration);
73087
- const useFile = getSourceFileOfNode(usage4);
73205
+ const useFile = getSourceFileOfNode(usage5);
73088
73206
  const declContainer = getEnclosingBlockScopeContainer(declaration);
73089
73207
  if (declarationFile !== useFile) {
73090
- if (moduleKind && (declarationFile.externalModuleIndicator || useFile.externalModuleIndicator) || !compilerOptions.outFile || isInTypeQuery(usage4) || declaration.flags & 33554432) {
73208
+ if (moduleKind && (declarationFile.externalModuleIndicator || useFile.externalModuleIndicator) || !compilerOptions.outFile || isInTypeQuery(usage5) || declaration.flags & 33554432) {
73091
73209
  return true;
73092
73210
  }
73093
- if (isUsedInFunctionOrInstanceProperty(usage4, declaration)) {
73211
+ if (isUsedInFunctionOrInstanceProperty(usage5, declaration)) {
73094
73212
  return true;
73095
73213
  }
73096
73214
  const sourceFiles = host.getSourceFiles();
73097
73215
  return sourceFiles.indexOf(declarationFile) <= sourceFiles.indexOf(useFile);
73098
73216
  }
73099
- if (!!(usage4.flags & 16777216) || isInTypeQuery(usage4) || isInAmbientOrTypeNode(usage4)) {
73217
+ if (!!(usage5.flags & 16777216) || isInTypeQuery(usage5) || isInAmbientOrTypeNode(usage5)) {
73100
73218
  return true;
73101
73219
  }
73102
- if (declaration.pos <= usage4.pos && !(isPropertyDeclaration(declaration) && isThisProperty(usage4.parent) && !declaration.initializer && !declaration.exclamationToken)) {
73220
+ if (declaration.pos <= usage5.pos && !(isPropertyDeclaration(declaration) && isThisProperty(usage5.parent) && !declaration.initializer && !declaration.exclamationToken)) {
73103
73221
  if (declaration.kind === 209) {
73104
73222
  const errorBindingElement = getAncestor(
73105
- usage4,
73223
+ usage5,
73106
73224
  209
73107
73225
  /* BindingElement */
73108
73226
  );
@@ -73113,41 +73231,41 @@ ${lanes.join("\n")}
73113
73231
  declaration,
73114
73232
  261
73115
73233
  /* VariableDeclaration */
73116
- ), usage4);
73234
+ ), usage5);
73117
73235
  } else if (declaration.kind === 261) {
73118
- return !isImmediatelyUsedInInitializerOfBlockScopedVariable(declaration, usage4);
73236
+ return !isImmediatelyUsedInInitializerOfBlockScopedVariable(declaration, usage5);
73119
73237
  } else if (isClassLike(declaration)) {
73120
- const container = findAncestor(usage4, (n) => n === declaration ? "quit" : isComputedPropertyName(n) ? n.parent.parent === declaration : !legacyDecorators && isDecorator(n) && (n.parent === declaration || isMethodDeclaration(n.parent) && n.parent.parent === declaration || isGetOrSetAccessorDeclaration(n.parent) && n.parent.parent === declaration || isPropertyDeclaration(n.parent) && n.parent.parent === declaration || isParameter(n.parent) && n.parent.parent.parent === declaration));
73238
+ const container = findAncestor(usage5, (n) => n === declaration ? "quit" : isComputedPropertyName(n) ? n.parent.parent === declaration : !legacyDecorators && isDecorator(n) && (n.parent === declaration || isMethodDeclaration(n.parent) && n.parent.parent === declaration || isGetOrSetAccessorDeclaration(n.parent) && n.parent.parent === declaration || isPropertyDeclaration(n.parent) && n.parent.parent === declaration || isParameter(n.parent) && n.parent.parent.parent === declaration));
73121
73239
  if (!container) {
73122
73240
  return true;
73123
73241
  }
73124
73242
  if (!legacyDecorators && isDecorator(container)) {
73125
- return !!findAncestor(usage4, (n) => n === container ? "quit" : isFunctionLike2(n) && !getImmediatelyInvokedFunctionExpression(n));
73243
+ return !!findAncestor(usage5, (n) => n === container ? "quit" : isFunctionLike2(n) && !getImmediatelyInvokedFunctionExpression(n));
73126
73244
  }
73127
73245
  return false;
73128
73246
  } else if (isPropertyDeclaration(declaration)) {
73129
73247
  return !isPropertyImmediatelyReferencedWithinDeclaration(
73130
73248
  declaration,
73131
- usage4,
73249
+ usage5,
73132
73250
  /*stopAtAnyPropertyDeclaration*/
73133
73251
  false
73134
73252
  );
73135
73253
  } else if (isParameterPropertyDeclaration(declaration, declaration.parent)) {
73136
- return !(emitStandardClassFields && getContainingClass(declaration) === getContainingClass(usage4) && isUsedInFunctionOrInstanceProperty(usage4, declaration));
73254
+ return !(emitStandardClassFields && getContainingClass(declaration) === getContainingClass(usage5) && isUsedInFunctionOrInstanceProperty(usage5, declaration));
73137
73255
  }
73138
73256
  return true;
73139
73257
  }
73140
- if (usage4.parent.kind === 282 || usage4.parent.kind === 278 && usage4.parent.isExportEquals) {
73258
+ if (usage5.parent.kind === 282 || usage5.parent.kind === 278 && usage5.parent.isExportEquals) {
73141
73259
  return true;
73142
73260
  }
73143
- if (usage4.kind === 278 && usage4.isExportEquals) {
73261
+ if (usage5.kind === 278 && usage5.isExportEquals) {
73144
73262
  return true;
73145
73263
  }
73146
- if (isUsedInFunctionOrInstanceProperty(usage4, declaration)) {
73264
+ if (isUsedInFunctionOrInstanceProperty(usage5, declaration)) {
73147
73265
  if (emitStandardClassFields && getContainingClass(declaration) && (isPropertyDeclaration(declaration) || isParameterPropertyDeclaration(declaration, declaration.parent))) {
73148
73266
  return !isPropertyImmediatelyReferencedWithinDeclaration(
73149
73267
  declaration,
73150
- usage4,
73268
+ usage5,
73151
73269
  /*stopAtAnyPropertyDeclaration*/
73152
73270
  true
73153
73271
  );
@@ -73753,19 +73871,19 @@ ${lanes.join("\n")}
73753
73871
  /* Default */
73754
73872
  ) || isExportSpecifier(node) || isNamespaceExport(node);
73755
73873
  }
73756
- function getEmitSyntaxForModuleSpecifierExpression(usage4) {
73757
- return isStringLiteralLike(usage4) ? host.getEmitSyntaxForUsageLocation(getSourceFileOfNode(usage4), usage4) : void 0;
73874
+ function getEmitSyntaxForModuleSpecifierExpression(usage5) {
73875
+ return isStringLiteralLike(usage5) ? host.getEmitSyntaxForUsageLocation(getSourceFileOfNode(usage5), usage5) : void 0;
73758
73876
  }
73759
73877
  function isESMFormatImportImportingCommonjsFormatFile(usageMode, targetMode) {
73760
73878
  return usageMode === 99 && targetMode === 1;
73761
73879
  }
73762
- function isOnlyImportableAsDefault(usage4, resolvedModule) {
73880
+ function isOnlyImportableAsDefault(usage5, resolvedModule) {
73763
73881
  if (100 <= moduleKind && moduleKind <= 199) {
73764
- const usageMode = getEmitSyntaxForModuleSpecifierExpression(usage4);
73882
+ const usageMode = getEmitSyntaxForModuleSpecifierExpression(usage5);
73765
73883
  if (usageMode === 99) {
73766
73884
  resolvedModule ?? (resolvedModule = resolveExternalModuleName(
73767
- usage4,
73768
- usage4,
73885
+ usage5,
73886
+ usage5,
73769
73887
  /*ignoreErrors*/
73770
73888
  true
73771
73889
  ));
@@ -73775,8 +73893,8 @@ ${lanes.join("\n")}
73775
73893
  }
73776
73894
  return false;
73777
73895
  }
73778
- function canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias, usage4) {
73779
- const usageMode = file && getEmitSyntaxForModuleSpecifierExpression(usage4);
73896
+ function canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias, usage5) {
73897
+ const usageMode = file && getEmitSyntaxForModuleSpecifierExpression(usage5);
73780
73898
  if (file && usageMode !== void 0) {
73781
73899
  const targetMode = host.getImpliedNodeFormatForEmit(file);
73782
73900
  if (usageMode === 99 && targetMode === 1 && 100 <= moduleKind && moduleKind <= 199) {
@@ -147375,7 +147493,7 @@ ${lanes.join("\n")}
147375
147493
  var nextListElementPos;
147376
147494
  var writer;
147377
147495
  var ownWriter;
147378
- var write2 = writeBase;
147496
+ var write3 = writeBase;
147379
147497
  var isOwnFileEmit;
147380
147498
  var sourceMapsDisabled = true;
147381
147499
  var sourceMapGenerator;
@@ -148233,7 +148351,7 @@ ${lanes.join("\n")}
148233
148351
  nonEscapingWrite(`$${snippet.order}`);
148234
148352
  }
148235
148353
  function emitIdentifier(node) {
148236
- const writeText = node.symbol ? writeSymbol : write2;
148354
+ const writeText = node.symbol ? writeSymbol : write3;
148237
148355
  writeText(getTextOfNode2(
148238
148356
  node,
148239
148357
  /*includeTrivia*/
@@ -148247,7 +148365,7 @@ ${lanes.join("\n")}
148247
148365
  );
148248
148366
  }
148249
148367
  function emitPrivateIdentifier(node) {
148250
- write2(getTextOfNode2(
148368
+ write3(getTextOfNode2(
148251
148369
  node,
148252
148370
  /*includeTrivia*/
148253
148371
  false
@@ -150108,7 +150226,7 @@ ${lanes.join("\n")}
150108
150226
  emitInitializer(node.initializer, node.name.end, node, parenthesizer.parenthesizeExpressionForDisallowedComma);
150109
150227
  }
150110
150228
  function emitJSDoc(node) {
150111
- write2("/**");
150229
+ write3("/**");
150112
150230
  if (node.comment) {
150113
150231
  const text2 = getTextOfJSDocComment(node.comment);
150114
150232
  if (text2) {
@@ -150118,7 +150236,7 @@ ${lanes.join("\n")}
150118
150236
  writeSpace();
150119
150237
  writePunctuation("*");
150120
150238
  writeSpace();
150121
- write2(line);
150239
+ write3(line);
150122
150240
  }
150123
150241
  }
150124
150242
  }
@@ -150136,7 +150254,7 @@ ${lanes.join("\n")}
150136
150254
  }
150137
150255
  }
150138
150256
  writeSpace();
150139
- write2("*/");
150257
+ write3("*/");
150140
150258
  }
150141
150259
  function emitJSDocSimpleTypedTag(tag) {
150142
150260
  emitJSDocTagName(tag.tagName);
@@ -150197,7 +150315,7 @@ ${lanes.join("\n")}
150197
150315
  } else {
150198
150316
  writeSpace();
150199
150317
  writePunctuation("{");
150200
- write2("Object");
150318
+ write3("Object");
150201
150319
  if (tag.typeExpression.isArrayType) {
150202
150320
  writePunctuation("[");
150203
150321
  writePunctuation("]");
@@ -150285,7 +150403,7 @@ ${lanes.join("\n")}
150285
150403
  const text2 = getTextOfJSDocComment(comment);
150286
150404
  if (text2) {
150287
150405
  writeSpace();
150288
- write2(text2);
150406
+ write3(text2);
150289
150407
  }
150290
150408
  }
150291
150409
  function emitJSDocTypeExpression(typeExpression) {
@@ -150427,10 +150545,10 @@ ${lanes.join("\n")}
150427
150545
  }
150428
150546
  function emitNodeWithWriter(node, writer2) {
150429
150547
  if (!node) return;
150430
- const savedWrite = write2;
150431
- write2 = writer2;
150548
+ const savedWrite = write3;
150549
+ write3 = writer2;
150432
150550
  emit4(node);
150433
- write2 = savedWrite;
150551
+ write3 = savedWrite;
150434
150552
  }
150435
150553
  function emitDecoratorsAndModifiers(node, modifiers, allowDecorators) {
150436
150554
  if (modifiers == null ? void 0 : modifiers.length) {
@@ -150864,7 +150982,7 @@ ${lanes.join("\n")}
150864
150982
  const line = indentation ? lineText.slice(indentation) : lineText;
150865
150983
  if (line.length) {
150866
150984
  writeLine();
150867
- write2(line);
150985
+ write3(line);
150868
150986
  }
150869
150987
  }
150870
150988
  }
@@ -152985,43 +153103,43 @@ ${lanes.join("\n")}
152985
153103
  }
152986
153104
  return false;
152987
153105
  }
152988
- function getModeForUsageLocation(file, usage4, compilerOptions) {
152989
- return getModeForUsageLocationWorker(file, usage4, compilerOptions);
153106
+ function getModeForUsageLocation(file, usage5, compilerOptions) {
153107
+ return getModeForUsageLocationWorker(file, usage5, compilerOptions);
152990
153108
  }
152991
- function getModeForUsageLocationWorker(file, usage4, compilerOptions) {
152992
- if (isImportDeclaration2(usage4.parent) || isExportDeclaration2(usage4.parent) || isJSDocImportTag(usage4.parent)) {
152993
- const isTypeOnly = isExclusivelyTypeOnlyImportOrExport(usage4.parent);
153109
+ function getModeForUsageLocationWorker(file, usage5, compilerOptions) {
153110
+ if (isImportDeclaration2(usage5.parent) || isExportDeclaration2(usage5.parent) || isJSDocImportTag(usage5.parent)) {
153111
+ const isTypeOnly = isExclusivelyTypeOnlyImportOrExport(usage5.parent);
152994
153112
  if (isTypeOnly) {
152995
- const override = getResolutionModeOverride(usage4.parent.attributes);
153113
+ const override = getResolutionModeOverride(usage5.parent.attributes);
152996
153114
  if (override) {
152997
153115
  return override;
152998
153116
  }
152999
153117
  }
153000
153118
  }
153001
- if (usage4.parent.parent && isImportTypeNode(usage4.parent.parent)) {
153002
- const override = getResolutionModeOverride(usage4.parent.parent.attributes);
153119
+ if (usage5.parent.parent && isImportTypeNode(usage5.parent.parent)) {
153120
+ const override = getResolutionModeOverride(usage5.parent.parent.attributes);
153003
153121
  if (override) {
153004
153122
  return override;
153005
153123
  }
153006
153124
  }
153007
153125
  if (compilerOptions && importSyntaxAffectsModuleResolution(compilerOptions)) {
153008
- return getEmitSyntaxForUsageLocationWorker(file, usage4, compilerOptions);
153126
+ return getEmitSyntaxForUsageLocationWorker(file, usage5, compilerOptions);
153009
153127
  }
153010
153128
  }
153011
- function getEmitSyntaxForUsageLocationWorker(file, usage4, compilerOptions) {
153129
+ function getEmitSyntaxForUsageLocationWorker(file, usage5, compilerOptions) {
153012
153130
  var _a;
153013
153131
  if (!compilerOptions) {
153014
153132
  return void 0;
153015
153133
  }
153016
- const exprParentParent = (_a = walkUpParenthesizedExpressions(usage4.parent)) == null ? void 0 : _a.parent;
153134
+ const exprParentParent = (_a = walkUpParenthesizedExpressions(usage5.parent)) == null ? void 0 : _a.parent;
153017
153135
  if (exprParentParent && isImportEqualsDeclaration(exprParentParent) || isRequireCall(
153018
- usage4.parent,
153136
+ usage5.parent,
153019
153137
  /*requireStringLiteralLikeArgument*/
153020
153138
  false
153021
153139
  )) {
153022
153140
  return 1;
153023
153141
  }
153024
- if (isImportCall(walkUpParenthesizedExpressions(usage4.parent))) {
153142
+ if (isImportCall(walkUpParenthesizedExpressions(usage5.parent))) {
153025
153143
  return shouldTransformImportCallWorker(file, compilerOptions) ? 1 : 99;
153026
153144
  }
153027
153145
  const fileEmitMode = getEmitModuleFormatOfFileWorker(file, compilerOptions);
@@ -156253,11 +156371,11 @@ ${lanes.join("\n")}
156253
156371
  }
156254
156372
  return symlinks;
156255
156373
  }
156256
- function getModeForUsageLocation2(file, usage4) {
156257
- return getModeForUsageLocationWorker(file, usage4, getCompilerOptionsForFile(file));
156374
+ function getModeForUsageLocation2(file, usage5) {
156375
+ return getModeForUsageLocationWorker(file, usage5, getCompilerOptionsForFile(file));
156258
156376
  }
156259
- function getEmitSyntaxForUsageLocation(file, usage4) {
156260
- return getEmitSyntaxForUsageLocationWorker(file, usage4, getCompilerOptionsForFile(file));
156377
+ function getEmitSyntaxForUsageLocation(file, usage5) {
156378
+ return getEmitSyntaxForUsageLocationWorker(file, usage5, getCompilerOptionsForFile(file));
156261
156379
  }
156262
156380
  function getModeForResolutionAtIndex2(file, index) {
156263
156381
  return getModeForUsageLocation2(file, getModuleNameStringLiteralAt(file, index));
@@ -160100,24 +160218,24 @@ ${lanes.join("\n")}
160100
160218
  function isBuilderProgram(program) {
160101
160219
  return !!program.state;
160102
160220
  }
160103
- function listFiles3(program, write2) {
160221
+ function listFiles3(program, write3) {
160104
160222
  const options = program.getCompilerOptions();
160105
160223
  if (options.explainFiles) {
160106
- explainFiles(isBuilderProgram(program) ? program.getProgram() : program, write2);
160224
+ explainFiles(isBuilderProgram(program) ? program.getProgram() : program, write3);
160107
160225
  } else if (options.listFiles || options.listFilesOnly) {
160108
160226
  forEach(program.getSourceFiles(), (file) => {
160109
- write2(file.fileName);
160227
+ write3(file.fileName);
160110
160228
  });
160111
160229
  }
160112
160230
  }
160113
- function explainFiles(program, write2) {
160231
+ function explainFiles(program, write3) {
160114
160232
  var _a, _b;
160115
160233
  const reasons = program.getFileIncludeReasons();
160116
160234
  const relativeFileName = (fileName) => convertToRelativePath(fileName, program.getCurrentDirectory(), program.getCanonicalFileName);
160117
160235
  for (const file of program.getSourceFiles()) {
160118
- write2(`${toFileName(file, relativeFileName)}`);
160119
- (_a = reasons.get(file.path)) == null ? void 0 : _a.forEach((reason) => write2(` ${fileIncludeReasonToDiagnostics(program, reason, relativeFileName).messageText}`));
160120
- (_b = explainIfFileIsRedirectAndImpliedFormat(file, program.getCompilerOptionsForFile(file), relativeFileName)) == null ? void 0 : _b.forEach((d) => write2(` ${d.messageText}`));
160236
+ write3(`${toFileName(file, relativeFileName)}`);
160237
+ (_a = reasons.get(file.path)) == null ? void 0 : _a.forEach((reason) => write3(` ${fileIncludeReasonToDiagnostics(program, reason, relativeFileName).messageText}`));
160238
+ (_b = explainIfFileIsRedirectAndImpliedFormat(file, program.getCompilerOptionsForFile(file), relativeFileName)) == null ? void 0 : _b.forEach((d) => write3(` ${d.messageText}`));
160121
160239
  }
160122
160240
  }
160123
160241
  function explainIfFileIsRedirectAndImpliedFormat(file, options, fileNameConvertor) {
@@ -160315,7 +160433,7 @@ ${lanes.join("\n")}
160315
160433
  const fileName = isString(file) ? file : file.fileName;
160316
160434
  return fileNameConvertor ? fileNameConvertor(fileName) : fileName;
160317
160435
  }
160318
- function emitFilesAndReportErrors(program, reportDiagnostic, write2, reportSummary, writeFile22, cancellationToken, emitOnlyDtsFiles, customTransformers) {
160436
+ function emitFilesAndReportErrors(program, reportDiagnostic, write3, reportSummary, writeFile22, cancellationToken, emitOnlyDtsFiles, customTransformers) {
160319
160437
  const options = program.getCompilerOptions();
160320
160438
  const allDiagnostics = program.getConfigFileParsingDiagnostics().slice();
160321
160439
  const configFileParsingDiagnosticsLength = allDiagnostics.length;
@@ -160355,13 +160473,13 @@ ${lanes.join("\n")}
160355
160473
  addRange(allDiagnostics, emitResult.diagnostics);
160356
160474
  const diagnostics = sortAndDeduplicateDiagnostics(allDiagnostics);
160357
160475
  diagnostics.forEach(reportDiagnostic);
160358
- if (write2) {
160476
+ if (write3) {
160359
160477
  const currentDir = program.getCurrentDirectory();
160360
160478
  forEach(emitResult.emittedFiles, (file) => {
160361
160479
  const filepath = getNormalizedAbsolutePath(file, currentDir);
160362
- write2(`TSFILE: ${filepath}`);
160480
+ write3(`TSFILE: ${filepath}`);
160363
160481
  });
160364
- listFiles3(program, write2);
160482
+ listFiles3(program, write3);
160365
160483
  }
160366
160484
  if (reportSummary) {
160367
160485
  reportSummary(getErrorCountForSummary(diagnostics), getFilesInErrorForSummary(diagnostics));
@@ -160371,11 +160489,11 @@ ${lanes.join("\n")}
160371
160489
  diagnostics
160372
160490
  };
160373
160491
  }
160374
- function emitFilesAndReportErrorsAndGetExitStatus(program, reportDiagnostic, write2, reportSummary, writeFile22, cancellationToken, emitOnlyDtsFiles, customTransformers) {
160492
+ function emitFilesAndReportErrorsAndGetExitStatus(program, reportDiagnostic, write3, reportSummary, writeFile22, cancellationToken, emitOnlyDtsFiles, customTransformers) {
160375
160493
  const { emitResult, diagnostics } = emitFilesAndReportErrors(
160376
160494
  program,
160377
160495
  reportDiagnostic,
160378
- write2,
160496
+ write3,
160379
160497
  reportSummary,
160380
160498
  writeFile22,
160381
160499
  cancellationToken,
@@ -160533,7 +160651,7 @@ ${lanes.join("\n")}
160533
160651
  };
160534
160652
  }
160535
160653
  function createWatchCompilerHost(system = sys2, createProgram22, reportDiagnostic, reportWatchStatus2) {
160536
- const write2 = (s) => system.write(s + system.newLine);
160654
+ const write3 = (s) => system.write(s + system.newLine);
160537
160655
  const result = createProgramHost(system, createProgram22);
160538
160656
  copyProperties(result, createWatchHost(system, reportWatchStatus2));
160539
160657
  result.afterProgramCreate = (builderProgram) => {
@@ -160542,7 +160660,7 @@ ${lanes.join("\n")}
160542
160660
  emitFilesAndReportErrors(
160543
160661
  builderProgram,
160544
160662
  reportDiagnostic,
160545
- write2,
160663
+ write3,
160546
160664
  (errorCount) => result.onWatchStatusChange(
160547
160665
  createCompilerDiagnostic(getWatchErrorSummaryDiagnosticMessage(errorCount), errorCount),
160548
160666
  newLine,
@@ -174564,23 +174682,23 @@ interface Symbol {
174564
174682
  addNewFileToTsconfig(program, changes, oldFile.fileName, targetFile, hostGetCanonicalFileName(host));
174565
174683
  }
174566
174684
  }
174567
- function getNewStatementsAndRemoveFromOldFile(oldFile, targetFile, usage4, changes, toMove, program, host, preferences, importAdderForNewFile, importAdderForOldFile) {
174685
+ function getNewStatementsAndRemoveFromOldFile(oldFile, targetFile, usage5, changes, toMove, program, host, preferences, importAdderForNewFile, importAdderForOldFile) {
174568
174686
  const checker = program.getTypeChecker();
174569
174687
  const prologueDirectives = takeWhile(oldFile.statements, isPrologueDirective);
174570
174688
  const useEsModuleSyntax = !fileShouldUseJavaScriptRequire(targetFile.fileName, program, host, !!oldFile.commonJsModuleIndicator);
174571
174689
  const quotePreference = getQuotePreference(oldFile, preferences);
174572
- addImportsForMovedSymbols(usage4.oldFileImportsFromTargetFile, targetFile.fileName, importAdderForOldFile, program);
174573
- deleteUnusedOldImports(oldFile, toMove.all, usage4.unusedImportsFromOldFile, importAdderForOldFile);
174690
+ addImportsForMovedSymbols(usage5.oldFileImportsFromTargetFile, targetFile.fileName, importAdderForOldFile, program);
174691
+ deleteUnusedOldImports(oldFile, toMove.all, usage5.unusedImportsFromOldFile, importAdderForOldFile);
174574
174692
  importAdderForOldFile.writeFixes(changes, quotePreference);
174575
174693
  deleteMovedStatements(oldFile, toMove.ranges, changes);
174576
- updateImportsInOtherFiles(changes, program, host, oldFile, usage4.movedSymbols, targetFile.fileName, quotePreference);
174577
- addExportsInOldFile(oldFile, usage4.targetFileImportsFromOldFile, changes, useEsModuleSyntax);
174578
- addTargetFileImports(oldFile, usage4.oldImportsNeededByTargetFile, usage4.targetFileImportsFromOldFile, checker, program, importAdderForNewFile);
174694
+ updateImportsInOtherFiles(changes, program, host, oldFile, usage5.movedSymbols, targetFile.fileName, quotePreference);
174695
+ addExportsInOldFile(oldFile, usage5.targetFileImportsFromOldFile, changes, useEsModuleSyntax);
174696
+ addTargetFileImports(oldFile, usage5.oldImportsNeededByTargetFile, usage5.targetFileImportsFromOldFile, checker, program, importAdderForNewFile);
174579
174697
  if (!isFullSourceFile(targetFile) && prologueDirectives.length) {
174580
174698
  changes.insertStatementsInNewFile(targetFile.fileName, prologueDirectives, oldFile);
174581
174699
  }
174582
174700
  importAdderForNewFile.writeFixes(changes, quotePreference);
174583
- const body = addExports(oldFile, toMove.all, arrayFrom(usage4.oldFileImportsFromTargetFile.keys()), useEsModuleSyntax);
174701
+ const body = addExports(oldFile, toMove.all, arrayFrom(usage5.oldFileImportsFromTargetFile.keys()), useEsModuleSyntax);
174584
174702
  if (isFullSourceFile(targetFile) && targetFile.statements.length > 0) {
174585
174703
  moveStatementsToTargetFile(changes, program, body, targetFile, toMove);
174586
174704
  } else if (isFullSourceFile(targetFile)) {
@@ -174999,7 +175117,7 @@ interface Symbol {
174999
175117
  function createNewFileName(oldFile, program, host, toMove) {
175000
175118
  const checker = program.getTypeChecker();
175001
175119
  if (toMove) {
175002
- const usage4 = getUsageInfo(oldFile, toMove.all, checker);
175120
+ const usage5 = getUsageInfo(oldFile, toMove.all, checker);
175003
175121
  const currentDirectory = getDirectoryPath(oldFile.fileName);
175004
175122
  const extension = extensionFromPath(oldFile.fileName);
175005
175123
  const newFileName = combinePaths(
@@ -175008,7 +175126,7 @@ interface Symbol {
175008
175126
  // ensures the filename computed below isn't already taken
175009
175127
  makeUniqueFilename(
175010
175128
  // infers a name for the new file from the symbols being moved
175011
- inferNewFileName(usage4.oldFileImportsFromTargetFile, usage4.movedSymbols),
175129
+ inferNewFileName(usage5.oldFileImportsFromTargetFile, usage5.movedSymbols),
175012
175130
  extension,
175013
175131
  currentDirectory,
175014
175132
  host
@@ -175579,12 +175697,12 @@ interface Symbol {
175579
175697
  });
175580
175698
  function doChange4(oldFile, program, toMove, changes, host, context, preferences) {
175581
175699
  const checker = program.getTypeChecker();
175582
- const usage4 = getUsageInfo(oldFile, toMove.all, checker);
175700
+ const usage5 = getUsageInfo(oldFile, toMove.all, checker);
175583
175701
  const newFilename = createNewFileName(oldFile, program, host, toMove);
175584
175702
  const newSourceFile = createFutureSourceFile(newFilename, oldFile.externalModuleIndicator ? 99 : oldFile.commonJsModuleIndicator ? 1 : void 0, program, host);
175585
175703
  const importAdderForOldFile = ts_codefix_exports.createImportAdder(oldFile, context.program, context.preferences, context.host);
175586
175704
  const importAdderForNewFile = ts_codefix_exports.createImportAdder(newSourceFile, context.program, context.preferences, context.host);
175587
- getNewStatementsAndRemoveFromOldFile(oldFile, newSourceFile, usage4, changes, toMove, program, host, preferences, importAdderForNewFile, importAdderForOldFile);
175705
+ getNewStatementsAndRemoveFromOldFile(oldFile, newSourceFile, usage5, changes, toMove, program, host, preferences, importAdderForNewFile, importAdderForOldFile);
175588
175706
  addNewFileToTsconfig(program, changes, oldFile.fileName, newFilename, hostGetCanonicalFileName(host));
175589
175707
  }
175590
175708
  var ts_refactor_addOrRemoveBracesToArrowFunction_exports = {};
@@ -177768,10 +177886,10 @@ ${newComment.split("\n").map((c2) => ` * ${c2}`).join("\n")}
177768
177886
  const parameters = [];
177769
177887
  const callArguments = [];
177770
177888
  let writes;
177771
- usagesInScope.forEach((usage4, name) => {
177889
+ usagesInScope.forEach((usage5, name) => {
177772
177890
  let typeNode;
177773
177891
  if (!isJS) {
177774
- let type = checker.getTypeOfSymbolAtLocation(usage4.symbol, usage4.node);
177892
+ let type = checker.getTypeOfSymbolAtLocation(usage5.symbol, usage5.node);
177775
177893
  type = checker.getBaseTypeOfLiteralType(type);
177776
177894
  typeNode = ts_codefix_exports.typeToAutoImportableTypeNode(
177777
177895
  checker,
@@ -177796,8 +177914,8 @@ ${newComment.split("\n").map((c2) => ` * ${c2}`).join("\n")}
177796
177914
  typeNode
177797
177915
  );
177798
177916
  parameters.push(paramDecl);
177799
- if (usage4.usage === 2) {
177800
- (writes || (writes = [])).push(usage4);
177917
+ if (usage5.usage === 2) {
177918
+ (writes || (writes = [])).push(usage5);
177801
177919
  }
177802
177920
  callArguments.push(factory.createIdentifier(name));
177803
177921
  });
@@ -178681,8 +178799,8 @@ ${newComment.split("\n").map((c2) => ` * ${c2}`).join("\n")}
178681
178799
  forEachChild2(node, collectUsages);
178682
178800
  }
178683
178801
  }
178684
- function recordUsage(n, usage4, isTypeNode2) {
178685
- const symbolId = recordUsagebySymbol(n, usage4, isTypeNode2);
178802
+ function recordUsage(n, usage5, isTypeNode2) {
178803
+ const symbolId = recordUsagebySymbol(n, usage5, isTypeNode2);
178686
178804
  if (symbolId) {
178687
178805
  for (let i = 0; i < scopes.length; i++) {
178688
178806
  const substitution = substitutionsPerScope[i].get(symbolId);
@@ -178692,22 +178810,22 @@ ${newComment.split("\n").map((c2) => ` * ${c2}`).join("\n")}
178692
178810
  }
178693
178811
  }
178694
178812
  }
178695
- function recordUsagebySymbol(identifier, usage4, isTypeName) {
178813
+ function recordUsagebySymbol(identifier, usage5, isTypeName) {
178696
178814
  const symbol = getSymbolReferencedByIdentifier(identifier);
178697
178815
  if (!symbol) {
178698
178816
  return void 0;
178699
178817
  }
178700
178818
  const symbolId = getSymbolId(symbol).toString();
178701
178819
  const lastUsage = seenUsages.get(symbolId);
178702
- if (lastUsage && lastUsage >= usage4) {
178820
+ if (lastUsage && lastUsage >= usage5) {
178703
178821
  return symbolId;
178704
178822
  }
178705
- seenUsages.set(symbolId, usage4);
178823
+ seenUsages.set(symbolId, usage5);
178706
178824
  if (lastUsage) {
178707
178825
  for (const perScope of usagesPerScope) {
178708
178826
  const prevEntry = perScope.usages.get(identifier.text);
178709
178827
  if (prevEntry) {
178710
- perScope.usages.set(identifier.text, { usage: usage4, symbol, node: identifier });
178828
+ perScope.usages.set(identifier.text, { usage: usage5, symbol, node: identifier });
178711
178829
  }
178712
178830
  }
178713
178831
  return symbolId;
@@ -178720,7 +178838,7 @@ ${newComment.split("\n").map((c2) => ` * ${c2}`).join("\n")}
178720
178838
  if (rangeContainsStartEnd(enclosingTextRange, declInFile.getStart(), declInFile.end)) {
178721
178839
  return void 0;
178722
178840
  }
178723
- if (targetRange.facts & 2 && usage4 === 2) {
178841
+ if (targetRange.facts & 2 && usage5 === 2) {
178724
178842
  const diag2 = createDiagnosticForNode(identifier, Messages.cannotExtractRangeThatContainsWritesToReferencesLocatedOutsideOfTheTargetRangeInGenerators);
178725
178843
  for (const errors of functionErrorsPerScope) {
178726
178844
  errors.push(diag2);
@@ -178752,7 +178870,7 @@ ${newComment.split("\n").map((c2) => ` * ${c2}`).join("\n")}
178752
178870
  constantErrorsPerScope[i].push(diag2);
178753
178871
  }
178754
178872
  } else {
178755
- usagesPerScope[i].usages.set(identifier.text, { usage: usage4, symbol, node: identifier });
178873
+ usagesPerScope[i].usages.set(identifier.text, { usage: usage5, symbol, node: identifier });
178756
178874
  }
178757
178875
  }
178758
178876
  }
@@ -185470,9 +185588,9 @@ ${newComment.split("\n").map((c2) => ` * ${c2}`).join("\n")}
185470
185588
  }
185471
185589
  const checker = program.getTypeChecker();
185472
185590
  for (const specifier2 of nonTypeOnlySpecifiers) {
185473
- const isUsedAsValue = ts_FindAllReferences_exports.Core.eachSymbolReferenceInFile(specifier2.name, checker, sourceFile, (usage4) => {
185474
- const symbol = checker.getSymbolAtLocation(usage4);
185475
- return !!symbol && checker.symbolIsValue(symbol) || !isValidTypeOnlyAliasUseSite(usage4);
185591
+ const isUsedAsValue = ts_FindAllReferences_exports.Core.eachSymbolReferenceInFile(specifier2.name, checker, sourceFile, (usage5) => {
185592
+ const symbol = checker.getSymbolAtLocation(usage5);
185593
+ return !!symbol && checker.symbolIsValue(symbol) || !isValidTypeOnlyAliasUseSite(usage5);
185476
185594
  });
185477
185595
  if (isUsedAsValue) {
185478
185596
  return false;
@@ -192118,12 +192236,12 @@ ${newComment.split("\n").map((c2) => ` * ${c2}`).join("\n")}
192118
192236
  if (references.length === 0 || !declaration.parameters) {
192119
192237
  return void 0;
192120
192238
  }
192121
- const usage4 = createEmptyUsage();
192239
+ const usage5 = createEmptyUsage();
192122
192240
  for (const reference of references) {
192123
192241
  cancellationToken.throwIfCancellationRequested();
192124
- calculateUsageOfNode(reference, usage4);
192242
+ calculateUsageOfNode(reference, usage5);
192125
192243
  }
192126
- const calls = [...usage4.constructs || [], ...usage4.calls || []];
192244
+ const calls = [...usage5.constructs || [], ...usage5.calls || []];
192127
192245
  return declaration.parameters.map((parameter, parameterIndex) => {
192128
192246
  const types = [];
192129
192247
  const isRest = isRestParameter(parameter);
@@ -192153,99 +192271,99 @@ ${newComment.split("\n").map((c2) => ` * ${c2}`).join("\n")}
192153
192271
  });
192154
192272
  }
192155
192273
  function thisParameter() {
192156
- const usage4 = createEmptyUsage();
192274
+ const usage5 = createEmptyUsage();
192157
192275
  for (const reference of references) {
192158
192276
  cancellationToken.throwIfCancellationRequested();
192159
- calculateUsageOfNode(reference, usage4);
192277
+ calculateUsageOfNode(reference, usage5);
192160
192278
  }
192161
- return combineTypes(usage4.candidateThisTypes || emptyArray);
192279
+ return combineTypes(usage5.candidateThisTypes || emptyArray);
192162
192280
  }
192163
192281
  function inferTypesFromReferencesSingle(references2) {
192164
- const usage4 = createEmptyUsage();
192282
+ const usage5 = createEmptyUsage();
192165
192283
  for (const reference of references2) {
192166
192284
  cancellationToken.throwIfCancellationRequested();
192167
- calculateUsageOfNode(reference, usage4);
192285
+ calculateUsageOfNode(reference, usage5);
192168
192286
  }
192169
- return inferTypes(usage4);
192287
+ return inferTypes(usage5);
192170
192288
  }
192171
- function calculateUsageOfNode(node, usage4) {
192289
+ function calculateUsageOfNode(node, usage5) {
192172
192290
  while (isRightSideOfQualifiedNameOrPropertyAccess(node)) {
192173
192291
  node = node.parent;
192174
192292
  }
192175
192293
  switch (node.parent.kind) {
192176
192294
  case 245:
192177
- inferTypeFromExpressionStatement(node, usage4);
192295
+ inferTypeFromExpressionStatement(node, usage5);
192178
192296
  break;
192179
192297
  case 226:
192180
- usage4.isNumber = true;
192298
+ usage5.isNumber = true;
192181
192299
  break;
192182
192300
  case 225:
192183
- inferTypeFromPrefixUnaryExpression(node.parent, usage4);
192301
+ inferTypeFromPrefixUnaryExpression(node.parent, usage5);
192184
192302
  break;
192185
192303
  case 227:
192186
- inferTypeFromBinaryExpression(node, node.parent, usage4);
192304
+ inferTypeFromBinaryExpression(node, node.parent, usage5);
192187
192305
  break;
192188
192306
  case 297:
192189
192307
  case 298:
192190
- inferTypeFromSwitchStatementLabel(node.parent, usage4);
192308
+ inferTypeFromSwitchStatementLabel(node.parent, usage5);
192191
192309
  break;
192192
192310
  case 214:
192193
192311
  case 215:
192194
192312
  if (node.parent.expression === node) {
192195
- inferTypeFromCallExpression(node.parent, usage4);
192313
+ inferTypeFromCallExpression(node.parent, usage5);
192196
192314
  } else {
192197
- inferTypeFromContextualType(node, usage4);
192315
+ inferTypeFromContextualType(node, usage5);
192198
192316
  }
192199
192317
  break;
192200
192318
  case 212:
192201
- inferTypeFromPropertyAccessExpression(node.parent, usage4);
192319
+ inferTypeFromPropertyAccessExpression(node.parent, usage5);
192202
192320
  break;
192203
192321
  case 213:
192204
- inferTypeFromPropertyElementExpression(node.parent, node, usage4);
192322
+ inferTypeFromPropertyElementExpression(node.parent, node, usage5);
192205
192323
  break;
192206
192324
  case 304:
192207
192325
  case 305:
192208
- inferTypeFromPropertyAssignment(node.parent, usage4);
192326
+ inferTypeFromPropertyAssignment(node.parent, usage5);
192209
192327
  break;
192210
192328
  case 173:
192211
- inferTypeFromPropertyDeclaration(node.parent, usage4);
192329
+ inferTypeFromPropertyDeclaration(node.parent, usage5);
192212
192330
  break;
192213
192331
  case 261: {
192214
192332
  const { name, initializer } = node.parent;
192215
192333
  if (node === name) {
192216
192334
  if (initializer) {
192217
- addCandidateType(usage4, checker.getTypeAtLocation(initializer));
192335
+ addCandidateType(usage5, checker.getTypeAtLocation(initializer));
192218
192336
  }
192219
192337
  break;
192220
192338
  }
192221
192339
  }
192222
192340
  // falls through
192223
192341
  default:
192224
- return inferTypeFromContextualType(node, usage4);
192342
+ return inferTypeFromContextualType(node, usage5);
192225
192343
  }
192226
192344
  }
192227
- function inferTypeFromContextualType(node, usage4) {
192345
+ function inferTypeFromContextualType(node, usage5) {
192228
192346
  if (isExpressionNode(node)) {
192229
- addCandidateType(usage4, checker.getContextualType(node));
192347
+ addCandidateType(usage5, checker.getContextualType(node));
192230
192348
  }
192231
192349
  }
192232
- function inferTypeFromExpressionStatement(node, usage4) {
192233
- addCandidateType(usage4, isCallExpression2(node) ? checker.getVoidType() : checker.getAnyType());
192350
+ function inferTypeFromExpressionStatement(node, usage5) {
192351
+ addCandidateType(usage5, isCallExpression2(node) ? checker.getVoidType() : checker.getAnyType());
192234
192352
  }
192235
- function inferTypeFromPrefixUnaryExpression(node, usage4) {
192353
+ function inferTypeFromPrefixUnaryExpression(node, usage5) {
192236
192354
  switch (node.operator) {
192237
192355
  case 46:
192238
192356
  case 47:
192239
192357
  case 41:
192240
192358
  case 55:
192241
- usage4.isNumber = true;
192359
+ usage5.isNumber = true;
192242
192360
  break;
192243
192361
  case 40:
192244
- usage4.isNumberOrString = true;
192362
+ usage5.isNumberOrString = true;
192245
192363
  break;
192246
192364
  }
192247
192365
  }
192248
- function inferTypeFromBinaryExpression(node, parent2, usage4) {
192366
+ function inferTypeFromBinaryExpression(node, parent2, usage5) {
192249
192367
  switch (parent2.operatorToken.kind) {
192250
192368
  // ExponentiationOperator
192251
192369
  case 43:
@@ -192288,23 +192406,23 @@ ${newComment.split("\n").map((c2) => ` * ${c2}`).join("\n")}
192288
192406
  case 34:
192289
192407
  const operandType = checker.getTypeAtLocation(parent2.left === node ? parent2.right : parent2.left);
192290
192408
  if (operandType.flags & 98304) {
192291
- addCandidateType(usage4, operandType);
192409
+ addCandidateType(usage5, operandType);
192292
192410
  } else {
192293
- usage4.isNumber = true;
192411
+ usage5.isNumber = true;
192294
192412
  }
192295
192413
  break;
192296
192414
  case 65:
192297
192415
  case 40:
192298
192416
  const otherOperandType = checker.getTypeAtLocation(parent2.left === node ? parent2.right : parent2.left);
192299
192417
  if (otherOperandType.flags & 98304) {
192300
- addCandidateType(usage4, otherOperandType);
192418
+ addCandidateType(usage5, otherOperandType);
192301
192419
  } else if (otherOperandType.flags & 67648) {
192302
- usage4.isNumber = true;
192420
+ usage5.isNumber = true;
192303
192421
  } else if (otherOperandType.flags & 12583968) {
192304
- usage4.isString = true;
192422
+ usage5.isString = true;
192305
192423
  } else if (otherOperandType.flags & 1) {
192306
192424
  } else {
192307
- usage4.isNumberOrString = true;
192425
+ usage5.isNumberOrString = true;
192308
192426
  }
192309
192427
  break;
192310
192428
  // AssignmentOperators
@@ -192316,11 +192434,11 @@ ${newComment.split("\n").map((c2) => ` * ${c2}`).join("\n")}
192316
192434
  case 77:
192317
192435
  case 78:
192318
192436
  case 76:
192319
- addCandidateType(usage4, checker.getTypeAtLocation(parent2.left === node ? parent2.right : parent2.left));
192437
+ addCandidateType(usage5, checker.getTypeAtLocation(parent2.left === node ? parent2.right : parent2.left));
192320
192438
  break;
192321
192439
  case 103:
192322
192440
  if (node === parent2.left) {
192323
- usage4.isString = true;
192441
+ usage5.isString = true;
192324
192442
  }
192325
192443
  break;
192326
192444
  // LogicalOperator Or NullishCoalescing
@@ -192331,7 +192449,7 @@ ${newComment.split("\n").map((c2) => ` * ${c2}`).join("\n")}
192331
192449
  /*excludeCompoundAssignment*/
192332
192450
  true
192333
192451
  ))) {
192334
- addCandidateType(usage4, checker.getTypeAtLocation(parent2.right));
192452
+ addCandidateType(usage5, checker.getTypeAtLocation(parent2.right));
192335
192453
  }
192336
192454
  break;
192337
192455
  case 56:
@@ -192340,10 +192458,10 @@ ${newComment.split("\n").map((c2) => ` * ${c2}`).join("\n")}
192340
192458
  break;
192341
192459
  }
192342
192460
  }
192343
- function inferTypeFromSwitchStatementLabel(parent2, usage4) {
192344
- addCandidateType(usage4, checker.getTypeAtLocation(parent2.parent.parent.expression));
192461
+ function inferTypeFromSwitchStatementLabel(parent2, usage5) {
192462
+ addCandidateType(usage5, checker.getTypeAtLocation(parent2.parent.parent.expression));
192345
192463
  }
192346
- function inferTypeFromCallExpression(parent2, usage4) {
192464
+ function inferTypeFromCallExpression(parent2, usage5) {
192347
192465
  const call = {
192348
192466
  argumentTypes: [],
192349
192467
  return_: createEmptyUsage()
@@ -192355,41 +192473,41 @@ ${newComment.split("\n").map((c2) => ` * ${c2}`).join("\n")}
192355
192473
  }
192356
192474
  calculateUsageOfNode(parent2, call.return_);
192357
192475
  if (parent2.kind === 214) {
192358
- (usage4.calls || (usage4.calls = [])).push(call);
192476
+ (usage5.calls || (usage5.calls = [])).push(call);
192359
192477
  } else {
192360
- (usage4.constructs || (usage4.constructs = [])).push(call);
192478
+ (usage5.constructs || (usage5.constructs = [])).push(call);
192361
192479
  }
192362
192480
  }
192363
- function inferTypeFromPropertyAccessExpression(parent2, usage4) {
192481
+ function inferTypeFromPropertyAccessExpression(parent2, usage5) {
192364
192482
  const name = escapeLeadingUnderscores(parent2.name.text);
192365
- if (!usage4.properties) {
192366
- usage4.properties = /* @__PURE__ */ new Map();
192483
+ if (!usage5.properties) {
192484
+ usage5.properties = /* @__PURE__ */ new Map();
192367
192485
  }
192368
- const propertyUsage = usage4.properties.get(name) || createEmptyUsage();
192486
+ const propertyUsage = usage5.properties.get(name) || createEmptyUsage();
192369
192487
  calculateUsageOfNode(parent2, propertyUsage);
192370
- usage4.properties.set(name, propertyUsage);
192488
+ usage5.properties.set(name, propertyUsage);
192371
192489
  }
192372
- function inferTypeFromPropertyElementExpression(parent2, node, usage4) {
192490
+ function inferTypeFromPropertyElementExpression(parent2, node, usage5) {
192373
192491
  if (node === parent2.argumentExpression) {
192374
- usage4.isNumberOrString = true;
192492
+ usage5.isNumberOrString = true;
192375
192493
  return;
192376
192494
  } else {
192377
192495
  const indexType = checker.getTypeAtLocation(parent2.argumentExpression);
192378
192496
  const indexUsage = createEmptyUsage();
192379
192497
  calculateUsageOfNode(parent2, indexUsage);
192380
192498
  if (indexType.flags & 67648) {
192381
- usage4.numberIndex = indexUsage;
192499
+ usage5.numberIndex = indexUsage;
192382
192500
  } else {
192383
- usage4.stringIndex = indexUsage;
192501
+ usage5.stringIndex = indexUsage;
192384
192502
  }
192385
192503
  }
192386
192504
  }
192387
- function inferTypeFromPropertyAssignment(assignment, usage4) {
192505
+ function inferTypeFromPropertyAssignment(assignment, usage5) {
192388
192506
  const nodeWithRealType = isVariableDeclaration2(assignment.parent.parent) ? assignment.parent.parent : assignment.parent;
192389
- addCandidateThisType(usage4, checker.getTypeAtLocation(nodeWithRealType));
192507
+ addCandidateThisType(usage5, checker.getTypeAtLocation(nodeWithRealType));
192390
192508
  }
192391
- function inferTypeFromPropertyDeclaration(declaration, usage4) {
192392
- addCandidateThisType(usage4, checker.getTypeAtLocation(declaration.parent));
192509
+ function inferTypeFromPropertyDeclaration(declaration, usage5) {
192510
+ addCandidateThisType(usage5, checker.getTypeAtLocation(declaration.parent));
192393
192511
  }
192394
192512
  function removeLowPriorityInferences(inferences, priorities) {
192395
192513
  const toRemove = [];
@@ -192403,8 +192521,8 @@ ${newComment.split("\n").map((c2) => ` * ${c2}`).join("\n")}
192403
192521
  }
192404
192522
  return inferences.filter((i) => toRemove.every((f) => !f(i)));
192405
192523
  }
192406
- function combineFromUsage(usage4) {
192407
- return combineTypes(inferTypes(usage4));
192524
+ function combineFromUsage(usage5) {
192525
+ return combineTypes(inferTypes(usage5));
192408
192526
  }
192409
192527
  function combineTypes(inferences) {
192410
192528
  if (!inferences.length) return checker.getAnyType();
@@ -192499,26 +192617,26 @@ ${newComment.split("\n").map((c2) => ` * ${c2}`).join("\n")}
192499
192617
  indexInfos
192500
192618
  );
192501
192619
  }
192502
- function inferTypes(usage4) {
192620
+ function inferTypes(usage5) {
192503
192621
  var _a, _b, _c;
192504
192622
  const types = [];
192505
- if (usage4.isNumber) {
192623
+ if (usage5.isNumber) {
192506
192624
  types.push(checker.getNumberType());
192507
192625
  }
192508
- if (usage4.isString) {
192626
+ if (usage5.isString) {
192509
192627
  types.push(checker.getStringType());
192510
192628
  }
192511
- if (usage4.isNumberOrString) {
192629
+ if (usage5.isNumberOrString) {
192512
192630
  types.push(checker.getUnionType([checker.getStringType(), checker.getNumberType()]));
192513
192631
  }
192514
- if (usage4.numberIndex) {
192515
- types.push(checker.createArrayType(combineFromUsage(usage4.numberIndex)));
192632
+ if (usage5.numberIndex) {
192633
+ types.push(checker.createArrayType(combineFromUsage(usage5.numberIndex)));
192516
192634
  }
192517
- if (((_a = usage4.properties) == null ? void 0 : _a.size) || ((_b = usage4.constructs) == null ? void 0 : _b.length) || usage4.stringIndex) {
192518
- types.push(inferStructuralType(usage4));
192635
+ if (((_a = usage5.properties) == null ? void 0 : _a.size) || ((_b = usage5.constructs) == null ? void 0 : _b.length) || usage5.stringIndex) {
192636
+ types.push(inferStructuralType(usage5));
192519
192637
  }
192520
- const candidateTypes = (usage4.candidateTypes || []).map((t3) => checker.getBaseTypeOfLiteralType(t3));
192521
- const callsType = ((_c = usage4.calls) == null ? void 0 : _c.length) ? inferStructuralType(usage4) : void 0;
192638
+ const candidateTypes = (usage5.candidateTypes || []).map((t3) => checker.getBaseTypeOfLiteralType(t3));
192639
+ const callsType = ((_c = usage5.calls) == null ? void 0 : _c.length) ? inferStructuralType(usage5) : void 0;
192522
192640
  if (callsType && candidateTypes) {
192523
192641
  types.push(checker.getUnionType(
192524
192642
  [callsType, ...candidateTypes],
@@ -192533,23 +192651,23 @@ ${newComment.split("\n").map((c2) => ` * ${c2}`).join("\n")}
192533
192651
  types.push(...candidateTypes);
192534
192652
  }
192535
192653
  }
192536
- types.push(...inferNamedTypesFromProperties(usage4));
192654
+ types.push(...inferNamedTypesFromProperties(usage5));
192537
192655
  return types;
192538
192656
  }
192539
- function inferStructuralType(usage4) {
192657
+ function inferStructuralType(usage5) {
192540
192658
  const members = /* @__PURE__ */ new Map();
192541
- if (usage4.properties) {
192542
- usage4.properties.forEach((u, name) => {
192659
+ if (usage5.properties) {
192660
+ usage5.properties.forEach((u, name) => {
192543
192661
  const symbol = checker.createSymbol(4, name);
192544
192662
  symbol.links.type = combineFromUsage(u);
192545
192663
  members.set(name, symbol);
192546
192664
  });
192547
192665
  }
192548
- const callSignatures = usage4.calls ? [getSignatureFromCalls(usage4.calls)] : [];
192549
- const constructSignatures = usage4.constructs ? [getSignatureFromCalls(usage4.constructs)] : [];
192550
- const indexInfos = usage4.stringIndex ? [checker.createIndexInfo(
192666
+ const callSignatures = usage5.calls ? [getSignatureFromCalls(usage5.calls)] : [];
192667
+ const constructSignatures = usage5.constructs ? [getSignatureFromCalls(usage5.constructs)] : [];
192668
+ const indexInfos = usage5.stringIndex ? [checker.createIndexInfo(
192551
192669
  checker.getStringType(),
192552
- combineFromUsage(usage4.stringIndex),
192670
+ combineFromUsage(usage5.stringIndex),
192553
192671
  /*isReadonly*/
192554
192672
  false
192555
192673
  )] : [];
@@ -192562,17 +192680,17 @@ ${newComment.split("\n").map((c2) => ` * ${c2}`).join("\n")}
192562
192680
  indexInfos
192563
192681
  );
192564
192682
  }
192565
- function inferNamedTypesFromProperties(usage4) {
192566
- if (!usage4.properties || !usage4.properties.size) return [];
192567
- const types = builtins.filter((t3) => allPropertiesAreAssignableToUsage(t3, usage4));
192683
+ function inferNamedTypesFromProperties(usage5) {
192684
+ if (!usage5.properties || !usage5.properties.size) return [];
192685
+ const types = builtins.filter((t3) => allPropertiesAreAssignableToUsage(t3, usage5));
192568
192686
  if (0 < types.length && types.length < 3) {
192569
- return types.map((t3) => inferInstantiationFromUsage(t3, usage4));
192687
+ return types.map((t3) => inferInstantiationFromUsage(t3, usage5));
192570
192688
  }
192571
192689
  return [];
192572
192690
  }
192573
- function allPropertiesAreAssignableToUsage(type, usage4) {
192574
- if (!usage4.properties) return false;
192575
- return !forEachEntry(usage4.properties, (propUsage, name) => {
192691
+ function allPropertiesAreAssignableToUsage(type, usage5) {
192692
+ if (!usage5.properties) return false;
192693
+ return !forEachEntry(usage5.properties, (propUsage, name) => {
192576
192694
  const source = checker.getTypeOfPropertyOfType(type, name);
192577
192695
  if (!source) {
192578
192696
  return true;
@@ -192589,15 +192707,15 @@ ${newComment.split("\n").map((c2) => ` * ${c2}`).join("\n")}
192589
192707
  }
192590
192708
  });
192591
192709
  }
192592
- function inferInstantiationFromUsage(type, usage4) {
192593
- if (!(getObjectFlags(type) & 4) || !usage4.properties) {
192710
+ function inferInstantiationFromUsage(type, usage5) {
192711
+ if (!(getObjectFlags(type) & 4) || !usage5.properties) {
192594
192712
  return type;
192595
192713
  }
192596
192714
  const generic = type.target;
192597
192715
  const singleTypeParameter = singleOrUndefined(generic.typeParameters);
192598
192716
  if (!singleTypeParameter) return type;
192599
192717
  const types = [];
192600
- usage4.properties.forEach((propUsage, name) => {
192718
+ usage5.properties.forEach((propUsage, name) => {
192601
192719
  const genericPropertyType = checker.getTypeOfPropertyOfType(generic, name);
192602
192720
  Debug.assert(!!genericPropertyType, "generic should have all the properties of its reference.");
192603
192721
  types.push(...inferTypeParameters(genericPropertyType, combineFromUsage(propUsage), singleTypeParameter));
@@ -192698,14 +192816,14 @@ ${newComment.split("\n").map((c2) => ` * ${c2}`).join("\n")}
192698
192816
  /* None */
192699
192817
  );
192700
192818
  }
192701
- function addCandidateType(usage4, type) {
192819
+ function addCandidateType(usage5, type) {
192702
192820
  if (type && !(type.flags & 1) && !(type.flags & 262144)) {
192703
- (usage4.candidateTypes || (usage4.candidateTypes = [])).push(type);
192821
+ (usage5.candidateTypes || (usage5.candidateTypes = [])).push(type);
192704
192822
  }
192705
192823
  }
192706
- function addCandidateThisType(usage4, type) {
192824
+ function addCandidateThisType(usage5, type) {
192707
192825
  if (type && !(type.flags & 1) && !(type.flags & 262144)) {
192708
- (usage4.candidateThisTypes || (usage4.candidateThisTypes = [])).push(type);
192826
+ (usage5.candidateThisTypes || (usage5.candidateThisTypes = [])).push(type);
192709
192827
  }
192710
192828
  }
192711
192829
  }
@@ -196127,15 +196245,15 @@ ${newComment.split("\n").map((c2) => ` * ${c2}`).join("\n")}
196127
196245
  printNode,
196128
196246
  printAndFormatNode
196129
196247
  };
196130
- function escapingWrite(s, write2) {
196248
+ function escapingWrite(s, write3) {
196131
196249
  const escaped = escapeSnippetText(s);
196132
196250
  if (escaped !== s) {
196133
196251
  const start = baseWriter.getTextPos();
196134
- write2();
196252
+ write3();
196135
196253
  const end = baseWriter.getTextPos();
196136
196254
  escapes = append(escapes || (escapes = []), { newText: escaped, span: { start, length: end - start } });
196137
196255
  } else {
196138
- write2();
196256
+ write3();
196139
196257
  }
196140
196258
  }
196141
196259
  function printSnippetList(format, list2, sourceFile) {
@@ -208582,7 +208700,7 @@ ${options.prefix}` : "\n" : options.prefix
208582
208700
  lastNonTriviaPosition -= i;
208583
208701
  }
208584
208702
  }
208585
- function write2(s) {
208703
+ function write3(s) {
208586
208704
  writer.write(s);
208587
208705
  setLastNonTriviaPosition(
208588
208706
  s,
@@ -208719,7 +208837,7 @@ ${options.prefix}` : "\n" : options.prefix
208719
208837
  onAfterEmitNodeArray,
208720
208838
  onBeforeEmitToken,
208721
208839
  onAfterEmitToken,
208722
- write: write2,
208840
+ write: write3,
208723
208841
  writeComment,
208724
208842
  writeKeyword,
208725
208843
  writeOperator,
@@ -212959,10 +213077,10 @@ ${options.prefix}` : "\n" : options.prefix
212959
213077
  Debug.assertIsDefined(originalProgram, "no original program found");
212960
213078
  const originalProgramTypeChecker = originalProgram.getTypeChecker();
212961
213079
  const usageInfoRange = getUsageInfoRangeForPasteEdits(copiedFrom);
212962
- const usage4 = getUsageInfo(copiedFrom.file, statements, originalProgramTypeChecker, getExistingLocals(updatedFile, statements, originalProgramTypeChecker), usageInfoRange);
213080
+ const usage5 = getUsageInfo(copiedFrom.file, statements, originalProgramTypeChecker, getExistingLocals(updatedFile, statements, originalProgramTypeChecker), usageInfoRange);
212963
213081
  const useEsModuleSyntax = !fileShouldUseJavaScriptRequire(targetFile.fileName, originalProgram, host, !!copiedFrom.file.commonJsModuleIndicator);
212964
- addExportsInOldFile(copiedFrom.file, usage4.targetFileImportsFromOldFile, changes, useEsModuleSyntax);
212965
- addTargetFileImports(copiedFrom.file, usage4.oldImportsNeededByTargetFile, usage4.targetFileImportsFromOldFile, originalProgramTypeChecker, updatedProgram, importAdder);
213082
+ addExportsInOldFile(copiedFrom.file, usage5.targetFileImportsFromOldFile, changes, useEsModuleSyntax);
213083
+ addTargetFileImports(copiedFrom.file, usage5.oldImportsNeededByTargetFile, usage5.targetFileImportsFromOldFile, originalProgramTypeChecker, updatedProgram, importAdder);
212966
213084
  } else {
212967
213085
  const context = {
212968
213086
  sourceFile: updatedFile,
@@ -228979,9 +229097,9 @@ __export(showcase_exports, {
228979
229097
  showcaseCommand: () => showcaseCommand
228980
229098
  });
228981
229099
  import { spawnSync as spawnSync11 } from "node:child_process";
228982
- import { cpSync, existsSync as existsSync92, mkdirSync as mkdirSync45, mkdtempSync as mkdtempSync6, readdirSync as readdirSync39, readFileSync as readFileSync87, rmSync as rmSync17, statSync as statSync28, writeFileSync as writeFileSync46 } from "node:fs";
229100
+ import { cpSync, existsSync as existsSync93, mkdirSync as mkdirSync45, mkdtempSync as mkdtempSync6, readdirSync as readdirSync39, readFileSync as readFileSync88, rmSync as rmSync17, statSync as statSync28, writeFileSync as writeFileSync47 } from "node:fs";
228983
229101
  import { tmpdir as tmpdir8 } from "node:os";
228984
- import { dirname as dirname44, join as join97 } from "node:path";
229102
+ import { dirname as dirname44, join as join98 } from "node:path";
228985
229103
  import { fileURLToPath as fileURLToPath3 } from "node:url";
228986
229104
  function parseArgs2(args) {
228987
229105
  const opts = {
@@ -229022,7 +229140,7 @@ function parseArgs2(args) {
229022
229140
  function packageRoot() {
229023
229141
  let dir = dirname44(fileURLToPath3(import.meta.url));
229024
229142
  for (let i = 0; i < 12; i++) {
229025
- if (existsSync92(join97(dir, "conventions")))
229143
+ if (existsSync93(join98(dir, "conventions")))
229026
229144
  return dir;
229027
229145
  const parent = dirname44(dir);
229028
229146
  if (parent === dir)
@@ -229032,8 +229150,8 @@ function packageRoot() {
229032
229150
  return dir;
229033
229151
  }
229034
229152
  function rollBin3() {
229035
- const devPath = join97(packageRoot(), "packages", "cli", "bin", "roll.js");
229036
- if (existsSync92(devPath))
229153
+ const devPath = join98(packageRoot(), "packages", "cli", "bin", "roll.js");
229154
+ if (existsSync93(devPath))
229037
229155
  return devPath;
229038
229156
  return "roll";
229039
229157
  }
@@ -229060,30 +229178,30 @@ function runRoll(sandbox, rollHome4, args, opts = {}) {
229060
229178
  }
229061
229179
  function fileNonEmpty2(p) {
229062
229180
  try {
229063
- return existsSync92(p) && statSync28(p).size > 0;
229181
+ return existsSync93(p) && statSync28(p).size > 0;
229064
229182
  } catch {
229065
229183
  return false;
229066
229184
  }
229067
229185
  }
229068
229186
  function makeSandbox(sourceProject) {
229069
- const root = mkdtempSync6(join97(tmpdir8(), "roll-showcase-"));
229070
- const sandbox = join97(root, "project");
229071
- const rollHome4 = join97(root, "home");
229187
+ const root = mkdtempSync6(join98(tmpdir8(), "roll-showcase-"));
229188
+ const sandbox = join98(root, "project");
229189
+ const rollHome4 = join98(root, "home");
229072
229190
  mkdirSync45(sandbox, { recursive: true });
229073
229191
  mkdirSync45(rollHome4, { recursive: true });
229074
- const srcRoll = join97(sourceProject, ".roll");
229075
- if (existsSync92(srcRoll)) {
229076
- cpSync(srcRoll, join97(sandbox, ".roll"), { recursive: true });
229192
+ const srcRoll = join98(sourceProject, ".roll");
229193
+ if (existsSync93(srcRoll)) {
229194
+ cpSync(srcRoll, join98(sandbox, ".roll"), { recursive: true });
229077
229195
  } else {
229078
- mkdirSync45(join97(sandbox, ".roll", "features"), { recursive: true });
229196
+ mkdirSync45(join98(sandbox, ".roll", "features"), { recursive: true });
229079
229197
  }
229080
229198
  return { sandbox, rollHome: rollHome4 };
229081
229199
  }
229082
229200
  function findCardSpec2(sandbox, card) {
229083
- const featuresDir = join97(sandbox, ".roll", "features");
229201
+ const featuresDir = join98(sandbox, ".roll", "features");
229084
229202
  const candidates = [];
229085
229203
  const walk2 = (dir, depth) => {
229086
- if (depth > 3 || !existsSync92(dir))
229204
+ if (depth > 3 || !existsSync93(dir))
229087
229205
  return;
229088
229206
  let entries = [];
229089
229207
  try {
@@ -229092,7 +229210,7 @@ function findCardSpec2(sandbox, card) {
229092
229210
  return;
229093
229211
  }
229094
229212
  for (const name of entries) {
229095
- const full = join97(dir, name);
229213
+ const full = join98(dir, name);
229096
229214
  let isDir3 = false;
229097
229215
  try {
229098
229216
  isDir3 = statSync28(full).isDirectory();
@@ -229100,8 +229218,8 @@ function findCardSpec2(sandbox, card) {
229100
229218
  continue;
229101
229219
  }
229102
229220
  if (isDir3) {
229103
- if (name === card && existsSync92(join97(full, "spec.md")))
229104
- candidates.push(join97(full, "spec.md"));
229221
+ if (name === card && existsSync93(join98(full, "spec.md")))
229222
+ candidates.push(join98(full, "spec.md"));
229105
229223
  walk2(full, depth + 1);
229106
229224
  }
229107
229225
  }
@@ -229113,9 +229231,9 @@ function resetSandbox(sandbox, card) {
229113
229231
  const notes = [];
229114
229232
  let reset2 = false;
229115
229233
  let ok13 = false;
229116
- const backlogPath = join97(sandbox, ".roll", "backlog.md");
229117
- if (existsSync92(backlogPath)) {
229118
- const before = readFileSync87(backlogPath, "utf8");
229234
+ const backlogPath = join98(sandbox, ".roll", "backlog.md");
229235
+ if (existsSync93(backlogPath)) {
229236
+ const before = readFileSync88(backlogPath, "utf8");
229119
229237
  const cardRow = before.split("\n").find((line) => line.startsWith("|") && line.includes(card));
229120
229238
  const hadStatusToken = cardRow !== void 0 && statusMarkerRe(false).test(cardRow);
229121
229239
  const alreadyTodo = cardRow !== void 0 && findStatusMarker(cardRow) === STATUS_MARKER.todo;
@@ -229126,7 +229244,7 @@ function resetSandbox(sandbox, card) {
229126
229244
  });
229127
229245
  const after = lines2.join("\n");
229128
229246
  if (after !== before) {
229129
- writeFileSync46(backlogPath, after, "utf8");
229247
+ writeFileSync47(backlogPath, after, "utf8");
229130
229248
  reset2 = true;
229131
229249
  ok13 = true;
229132
229250
  notes.push(`backlog: ${card} \u2192 Todo`);
@@ -229142,24 +229260,24 @@ function resetSandbox(sandbox, card) {
229142
229260
  } else {
229143
229261
  notes.push("backlog: .roll/backlog.md absent");
229144
229262
  }
229145
- const pulseCmd = join97(sandbox, "packages", "cli", "src", "commands", "pulse.ts");
229146
- if (existsSync92(pulseCmd)) {
229263
+ const pulseCmd = join98(sandbox, "packages", "cli", "src", "commands", "pulse.ts");
229264
+ if (existsSync93(pulseCmd)) {
229147
229265
  rmSync17(pulseCmd, { force: true });
229148
229266
  notes.push("removed prior pulse.ts surface");
229149
229267
  }
229150
229268
  return { ok: ok13, reset: reset2, notes };
229151
229269
  }
229152
229270
  function writeCasting(sandbox, casting) {
229153
- const agentsPath2 = join97(sandbox, ".roll", "agents.yaml");
229271
+ const agentsPath2 = join98(sandbox, ".roll", "agents.yaml");
229154
229272
  mkdirSync45(dirname44(agentsPath2), { recursive: true });
229155
- writeFileSync46(agentsPath2, castingAgentsYaml(casting), "utf8");
229273
+ writeFileSync47(agentsPath2, castingAgentsYaml(casting), "utf8");
229156
229274
  }
229157
229275
  async function captureScreenshots(sandbox, card) {
229158
229276
  const shots = [];
229159
229277
  const infra = await Promise.resolve().then(() => (init_dist3(), dist_exports));
229160
- const shotDir = join97(sandbox, ".roll", "showcase", card, "screenshots");
229278
+ const shotDir = join98(sandbox, ".roll", "showcase", card, "screenshots");
229161
229279
  mkdirSync45(shotDir, { recursive: true });
229162
- const cliOut = join97(shotDir, "pulse-cli.png");
229280
+ const cliOut = join98(shotDir, "pulse-cli.png");
229163
229281
  const cli = await infra.captureScreenshot({
229164
229282
  kind: "terminal",
229165
229283
  out: cliOut,
@@ -229171,12 +229289,12 @@ async function captureScreenshots(sandbox, card) {
229171
229289
  present: cli.taken && fileNonEmpty2(cliOut),
229172
229290
  ...cli.skipped !== void 0 ? { skipped: cli.skipped } : {}
229173
229291
  });
229174
- const nowPage = join97(sandbox, ".roll", "features", "index.html");
229175
- const webOut = join97(shotDir, "now-pulse-badge.png");
229292
+ const nowPage = join98(sandbox, ".roll", "features", "index.html");
229293
+ const webOut = join98(shotDir, "now-pulse-badge.png");
229176
229294
  const web = await infra.captureScreenshot({
229177
229295
  kind: "web",
229178
229296
  out: webOut,
229179
- url: existsSync92(nowPage) ? `file://${nowPage}#now` : "about:blank"
229297
+ url: existsSync93(nowPage) ? `file://${nowPage}#now` : "about:blank"
229180
229298
  });
229181
229299
  shots.push({
229182
229300
  surface: "web",
@@ -229187,10 +229305,10 @@ async function captureScreenshots(sandbox, card) {
229187
229305
  return shots;
229188
229306
  }
229189
229307
  function readBacklogStatus(sandbox, card) {
229190
- const backlogPath = join97(sandbox, ".roll", "backlog.md");
229191
- if (!existsSync92(backlogPath))
229308
+ const backlogPath = join98(sandbox, ".roll", "backlog.md");
229309
+ if (!existsSync93(backlogPath))
229192
229310
  return void 0;
229193
- for (const line of readFileSync87(backlogPath, "utf8").split("\n")) {
229311
+ for (const line of readFileSync88(backlogPath, "utf8").split("\n")) {
229194
229312
  if (line.startsWith("|") && line.includes(card)) {
229195
229313
  const marker = findStatusMarker(line);
229196
229314
  if (marker !== void 0)
@@ -229200,11 +229318,11 @@ function readBacklogStatus(sandbox, card) {
229200
229318
  return void 0;
229201
229319
  }
229202
229320
  function readTruthLadder(sandbox, card) {
229203
- const truthPath = join97(sandbox, ".roll", "features", "truth.json");
229204
- if (!existsSync92(truthPath))
229321
+ const truthPath = join98(sandbox, ".roll", "features", "truth.json");
229322
+ if (!existsSync93(truthPath))
229205
229323
  return void 0;
229206
229324
  try {
229207
- const snap = JSON.parse(readFileSync87(truthPath, "utf8"));
229325
+ const snap = JSON.parse(readFileSync88(truthPath, "utf8"));
229208
229326
  const row2 = (snap.stories ?? []).find((s) => s.id === card);
229209
229327
  return row2?.ladder;
229210
229328
  } catch {
@@ -229212,12 +229330,12 @@ function readTruthLadder(sandbox, card) {
229212
229330
  }
229213
229331
  }
229214
229332
  function readTcrCommits(sandbox) {
229215
- const runsPath3 = join97(sandbox, ".roll", "loop", "runs.jsonl");
229216
- if (!existsSync92(runsPath3))
229333
+ const runsPath3 = join98(sandbox, ".roll", "loop", "runs.jsonl");
229334
+ if (!existsSync93(runsPath3))
229217
229335
  return [];
229218
229336
  const out3 = [];
229219
229337
  try {
229220
- const lines2 = readFileSync87(runsPath3, "utf8").trim().split("\n").filter(Boolean);
229338
+ const lines2 = readFileSync88(runsPath3, "utf8").trim().split("\n").filter(Boolean);
229221
229339
  const last = lines2[lines2.length - 1];
229222
229340
  if (last === void 0)
229223
229341
  return [];
@@ -229296,7 +229414,7 @@ ${msg6}
229296
229414
  const backlogStatus = readBacklogStatus(sandbox, card);
229297
229415
  const truthLadder = readTruthLadder(sandbox, card);
229298
229416
  const tcrCommits = readTcrCommits(sandbox);
229299
- const reportPath = join97(sandbox, ".roll", "features");
229417
+ const reportPath = join98(sandbox, ".roll", "features");
229300
229418
  const gate = parseAttestGate(attest.stdout + attest.stderr);
229301
229419
  const run = {
229302
229420
  casting,
@@ -230552,12 +230670,12 @@ async function loopResumeCommand(_args, deps = realDeps()) {
230552
230670
  } catch {
230553
230671
  }
230554
230672
  }
230555
- const stateFile2 = join20(rt, `state-${id.slug}.yaml`);
230556
- if (existsSync16(stateFile2)) {
230673
+ const stateFile3 = join20(rt, `state-${id.slug}.yaml`);
230674
+ if (existsSync16(stateFile3)) {
230557
230675
  try {
230558
- const body = readFileSync14(stateFile2, "utf8");
230676
+ const body = readFileSync14(stateFile3, "utf8");
230559
230677
  const lines2 = body.split("\n").filter((l) => /^(?!heal_count_head_)/.test(l));
230560
- writeFileSync7(stateFile2, lines2.join("\n"), "utf8");
230678
+ writeFileSync7(stateFile3, lines2.join("\n"), "utf8");
230561
230679
  } catch {
230562
230680
  }
230563
230681
  }
@@ -231693,6 +231811,30 @@ function heartbeatRow(lane, generatedAt) {
231693
231811
  ].filter((s) => s !== "").join(" \xB7 ");
231694
231812
  return `<div style="display:grid;${HB_COLS}align-items:center;gap:14px;padding:13px 18px;border-top:1px solid #f4f6f9;"><div style="display:flex;align-items:center;gap:11px;min-width:0;"><span style="${dot}"></span><div style="min-width:0;"><div style="font-size:13.5px;font-weight:600;color:${C.ink};white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">${esc2(lane.name)}</div><div style="${MONO}font-size:10.5px;color:${stale ? C.red : on ? C.green : C.faint};margin-top:1px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">${stateLine}</div></div></div>` + cell2(esc2(lane.mode ?? "\u2014")) + cell2(mins(lane.everyMin)) + cell2(shortTs(lane.lastAt), true) + `<div class="hb-next" data-next="${esc2(lane.nextAt ?? "")}" style="${MONO}font-size:12.5px;color:${C.body};min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">${shortTs(lane.nextAt)}</div></div>`;
231695
231813
  }
231814
+ function loopStateBanner(input) {
231815
+ const loop = input.snapshot.loop;
231816
+ const state = loop?.runState ?? "ACTIVE";
231817
+ const lanes = loop?.lanes ?? [];
231818
+ const laneRunning = (mode) => lanes.find((l) => l.mode === mode)?.running === true;
231819
+ const since = loop?.stateSince !== void 0 && loop.stateSince !== "" ? esc2(loop.stateSince) : "\u2014";
231820
+ const reasonRaw = loop?.stateReason ?? "";
231821
+ const reason = reasonRaw !== "" ? ` \xB7 ${esc2(reasonRaw)}` : "";
231822
+ const wrap = (accent, bg, enLines, zhLines) => `<section data-loop-state="${state}" style="border:1px solid ${accent}33;border-left:3px solid ${accent};border-radius:12px;background:${bg};padding:14px 18px;margin:20px 0 4px;">` + enLines.map((l) => `<div style="${MONO}font-size:13px;color:${C.ink};line-height:1.7;">${l}</div>`).join("") + zhLines.map((l) => `<div style="${MONO}font-size:12px;color:${C.sub};line-height:1.7;">${l}</div>`).join("") + `</section>`;
231823
+ if (state === "DORMANT") {
231824
+ const laneEn = (laneRunning("backlog") ? "loop lane active" : "loop lane unloaded \xB7 zero idle") + " \xB7 " + (laneRunning("pr") ? "PR lane active" : "PR lane off") + " \xB7 " + (laneRunning("dream") ? "Dream lane active" : "Dream lane off");
231825
+ const laneZh = (laneRunning("backlog") ? "loop lane \u6D3B\u8DC3" : "loop lane \u5DF2\u5378\u8F7D \xB7 \u96F6\u95F2\u7F6E") + " \xB7 " + (laneRunning("pr") ? "PR lane \u6D3B\u8DC3" : "PR lane \u5173\u95ED") + " \xB7 " + (laneRunning("dream") ? "Dream lane \u6D3B\u8DC3" : "Dream lane \u5173\u95ED");
231826
+ return wrap(C.purple, "#f7f5fc", [
231827
+ `\u{1F4A4} <b>DORMANT</b> \xB7 since ${since}${reason}`,
231828
+ laneEn,
231829
+ "Wakes on: new Todo \xB7 PR merge \xB7 dream scan \xB7 roll loop resume"
231830
+ ], [`\u{1F4A4} \u4F11\u7720 \xB7 \u81EA ${since}${reason}`, laneZh, "\u5524\u9192\u4E8E\uFF1A\u65B0 Todo \xB7 PR \u5408\u5E76 \xB7 dream \u626B\u63CF \xB7 roll loop resume"]);
231831
+ }
231832
+ if (state === "PAUSED") {
231833
+ return wrap(C.amber, "#fdf8ef", [`\u23F8 <b>PAUSED</b>${since !== "\u2014" ? ` \xB7 since ${since}` : ""}${reason}`, "Resume: roll loop resume"], [`\u23F8 \u5DF2\u6682\u505C${since !== "\u2014" ? ` \xB7 \u81EA ${since}` : ""}${reason}`, "\u6062\u590D\uFF1Aroll loop resume"]);
231834
+ }
231835
+ const armed = lanes.filter((l) => l.running).length;
231836
+ return wrap(C.green, "#f1f9f4", [`\u25CF <b>ACTIVE</b> \xB7 loop running \xB7 ${armed}/${lanes.length} lanes armed`], [`\u25CF \u6D3B\u8DC3 \xB7 \u5FAA\u73AF\u8FD0\u884C\u4E2D \xB7 ${armed}/${lanes.length} lane \u5DF2\u5C31\u7EEA`]);
231837
+ }
231696
231838
  function repoLoopsPanel(input) {
231697
231839
  const lanes = input.snapshot.loop?.lanes ?? [];
231698
231840
  return `<div style="display:flex;align-items:baseline;gap:12px;margin:24px 0 12px;flex-wrap:wrap;"><span style="${MONO}font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:${C.sub};font-weight:600;">${bi("Loops on this repo", "\u672C\u4ED3 Loops")}</span><span style="${MONO}font-size:11.5px;color:${C.faint};">${bi("backlog \xB7 PR \xB7 dream \xB7 go sessions", "backlog \xB7 PR \xB7 dream \xB7 go \u4F1A\u8BDD")}</span><span style="flex:1;height:1px;background:#dfe4ec;min-width:16px;"></span><span style="${MONO}font-size:11.5px;color:${C.dim};white-space:nowrap;">${lanes.filter((l) => l.running).length}/${lanes.length} ${bi("running", "\u8FD0\u884C\u4E2D")}</span></div><section style="border:1px solid ${C.line};border-radius:14px;background:${C.card};overflow:hidden;margin:0 0 8px;box-shadow:0 1px 2px rgba(17,26,69,.05);">` + (lanes.length > 0 ? heartbeatHeader() + lanes.map((lane) => heartbeatRow(lane, input.snapshot.generatedAt)).join("") : `<div style="padding:16px 18px;font-size:12.5px;color:${C.faint};font-style:italic;">${bi("no loop lanes found for this repo", "\u672A\u53D1\u73B0\u672C\u4ED3 loop lane")}</div>`) + `</section>`;
@@ -232020,7 +232162,9 @@ function loopTab(input) {
232020
232162
  ["7", "7 days", "\u4E03\u5929"],
232021
232163
  ["all", "All", "\u5168\u90E8"]
232022
232164
  ];
232023
- return `<div style="padding:30px 0 4px;">` + kicker(bi("The engine says it runs \u2014 here is the tape", "\u5F15\u64CE\u8BF4\u5728\u8DD1\u2014\u2014\u8FD9\u662F\u8F68\u8FF9\u5E26")) + `<h1 style="margin:10px 0 0;font-size:28px;line-height:1.1;font-weight:700;letter-spacing:-.02em;color:${C.ink};">${bi("Loop & Cycles", "\u5FAA\u73AF\u4E0E\u5468\u671F")}</h1><p style="margin:10px 0 0;max-width:660px;font-size:14.5px;line-height:1.55;color:${C.sub};">${bi("Every cycle, complete and replayable. Failures are first-class \u2014 never swallowed.", "\u6BCF\u4E00\u4E2A cycle \u5B8C\u6574\u3001\u53EF\u56DE\u6EAF\u3002\u5931\u8D25\u662F\u4E00\u7B49\u516C\u6C11\u2014\u2014\u7EDD\u4E0D\u541E\u3002")}</p></div>` + // US-DOSSIER-040: the Loop tab is Loop&Cycle (heartbeat/lanes) + the
232165
+ return `<div style="padding:30px 0 4px;">` + kicker(bi("The engine says it runs \u2014 here is the tape", "\u5F15\u64CE\u8BF4\u5728\u8DD1\u2014\u2014\u8FD9\u662F\u8F68\u8FF9\u5E26")) + `<h1 style="margin:10px 0 0;font-size:28px;line-height:1.1;font-weight:700;letter-spacing:-.02em;color:${C.ink};">${bi("Loop & Cycles", "\u5FAA\u73AF\u4E0E\u5468\u671F")}</h1><p style="margin:10px 0 0;max-width:660px;font-size:14.5px;line-height:1.55;color:${C.sub};">${bi("Every cycle, complete and replayable. Failures are first-class \u2014 never swallowed.", "\u6BCF\u4E00\u4E2A cycle \u5B8C\u6574\u3001\u53EF\u56DE\u6EAF\u3002\u5931\u8D25\u662F\u4E00\u7B49\u516C\u6C11\u2014\u2014\u7EDD\u4E0D\u541E\u3002")}</p></div>` + // US-LOOP-079l: the 3-state run-state header (ACTIVE/DORMANT/PAUSED) sits
232166
+ // atop the lanes so the dossier reads its own liveness before the grid.
232167
+ loopStateBanner(input) + // US-DOSSIER-040: the Loop tab is Loop&Cycle (heartbeat/lanes) + the
232024
232168
  // project-scoped commit-hooks panel + the Cycle ledger. The inline agents
232025
232169
  // panel (now the machine Agents page) and the inline casting ladder (now its
232026
232170
  // own Casting tab) are NOT rendered here.
@@ -235687,7 +235831,7 @@ async function streamThroughRenderer(input, out3, opts) {
235687
235831
  const st = newNormalizerState();
235688
235832
  const gapMs = opts.gapMs ?? DEFAULT_HEARTBEAT_GAP_MS;
235689
235833
  let lastStatus = null;
235690
- const write2 = (sig) => {
235834
+ const write3 = (sig) => {
235691
235835
  if (tierVisible(sig.tier, opts.verbose))
235692
235836
  out3.write(renderSignal(sig, { ts: hms() }) + "\n");
235693
235837
  };
@@ -235702,14 +235846,14 @@ async function streamThroughRenderer(input, out3, opts) {
235702
235846
  return;
235703
235847
  }
235704
235848
  for (const sig of maybeHeartbeat(st, Date.now(), gapMs))
235705
- write2(sig);
235849
+ write3(sig);
235706
235850
  }, Math.min(gapMs, 15e3));
235707
235851
  beat.unref?.();
235708
235852
  const rl = createInterface({ input, crlfDelay: Infinity });
235709
235853
  try {
235710
235854
  for await (const raw of rl) {
235711
235855
  for (const sig of norm.normalize(raw, st, Date.now()))
235712
- write2(sig);
235856
+ write3(sig);
235713
235857
  }
235714
235858
  } finally {
235715
235859
  clearInterval(beat);
@@ -238165,7 +238309,7 @@ function skillsOnDisk(skillsRoot) {
238165
238309
  function collectSkillsPanel(projectPath3, deps = defaultSkillsPanelDeps(projectPath3)) {
238166
238310
  const audit = deps.audit();
238167
238311
  const auditRan = audit !== null;
238168
- const usage4 = deps.usageCounts();
238312
+ const usage5 = deps.usageCounts();
238169
238313
  const skillsRoot = join42(projectPath3, "skills");
238170
238314
  const byName = /* @__PURE__ */ new Map();
238171
238315
  for (const a of audit?.skills ?? [])
@@ -238185,7 +238329,7 @@ function collectSkillsPanel(projectPath3, deps = defaultSkillsPanelDeps(projectP
238185
238329
  hasGotchas: a?.hasGotchas === true,
238186
238330
  hasLoadTrigger: a?.descriptionLoadTrigger === true,
238187
238331
  routeCases: { positive: a?.routeCoverage.positiveCount ?? 0, negative: a?.routeCoverage.negativeCount ?? 0 },
238188
- usage: usage4[name] ?? 0,
238332
+ usage: usage5[name] ?? 0,
238189
238333
  files: skillFiles(dir),
238190
238334
  dirPath: dir,
238191
238335
  hubText: existsSync39(hubPath) ? readFileSync34(hubPath, "utf8") : ""
@@ -238591,6 +238735,16 @@ function defaultHeartbeatDeps(projectPath3, slug2, launchAgentsDir3) {
238591
238735
  } catch {
238592
238736
  return null;
238593
238737
  }
238738
+ },
238739
+ // US-LOOP-079l: resolve the 3-state run-state from on-disk markers; read the
238740
+ // DORMANT marker's since/reason so the dossier header is self-describing.
238741
+ runState: () => {
238742
+ const state = resolveLoopRunState(projectPath3, slug2);
238743
+ if (state === "DORMANT") {
238744
+ const body = readDormantMarker(dormantMarkerPath(projectPath3, slug2));
238745
+ return body !== null ? { state, since: body.since, reason: body.reason } : { state };
238746
+ }
238747
+ return { state };
238594
238748
  }
238595
238749
  };
238596
238750
  }
@@ -238690,7 +238844,16 @@ function collectLoopHeartbeat(deps) {
238690
238844
  const go = goalLane(deps);
238691
238845
  if (go !== void 0)
238692
238846
  lanes.push(go);
238693
- return { lanes };
238847
+ const snapshot = { lanes };
238848
+ const rs = deps.runState?.();
238849
+ if (rs !== void 0) {
238850
+ snapshot.runState = rs.state;
238851
+ if (rs.since !== void 0)
238852
+ snapshot.stateSince = rs.since;
238853
+ if (rs.reason !== void 0)
238854
+ snapshot.stateReason = rs.reason;
238855
+ }
238856
+ return snapshot;
238694
238857
  }
238695
238858
 
238696
238859
  // packages/cli/dist/lib/casting.js
@@ -239672,15 +239835,15 @@ function loadStreamJsonSessionUsage(label3, slug2, agent) {
239672
239835
  continue;
239673
239836
  }
239674
239837
  const msg6 = e["message"] ?? {};
239675
- const usage4 = msg6["usage"] ?? {};
239676
- if (Object.keys(usage4).length === 0)
239838
+ const usage5 = msg6["usage"] ?? {};
239839
+ if (Object.keys(usage5).length === 0)
239677
239840
  continue;
239678
239841
  if (msg6["model"] && model === null)
239679
239842
  model = msg6["model"];
239680
- sums.input_tokens += toInt2(usage4["input_tokens"]);
239681
- sums.output_tokens += toInt2(usage4["output_tokens"]);
239682
- sums.cache_creation_tokens += toInt2(usage4["cache_creation_input_tokens"]);
239683
- sums.cache_read_tokens += toInt2(usage4["cache_read_input_tokens"]);
239843
+ sums.input_tokens += toInt2(usage5["input_tokens"]);
239844
+ sums.output_tokens += toInt2(usage5["output_tokens"]);
239845
+ sums.cache_creation_tokens += toInt2(usage5["cache_creation_input_tokens"]);
239846
+ sums.cache_read_tokens += toInt2(usage5["cache_read_input_tokens"]);
239684
239847
  }
239685
239848
  if (sums.input_tokens === 0 && sums.output_tokens === 0)
239686
239849
  return null;
@@ -253503,20 +253666,59 @@ async function loopReviewResizeCommand(argv, deps = realReviewResizeDeps()) {
253503
253666
  return await deps.selfDowngrade(storyId, `reviewer resize: ${resize.reason}`, subIds);
253504
253667
  }
253505
253668
 
253669
+ // packages/cli/dist/commands/loop-exhaustion-split.js
253670
+ init_dist2();
253671
+ var DESIGN_TIMEOUT_MS = 12e4;
253672
+ function realExhaustionSplitDeps() {
253673
+ return {
253674
+ design: async (projectPath3, storyId) => {
253675
+ const installed = agentsInstalled(realAgentEnv()).map(canonicalAgentName).filter((a) => agentCanReviewHeadless(a));
253676
+ const designer = installed[0];
253677
+ if (designer === void 0)
253678
+ return [];
253679
+ const prompt = `Run the $roll-design workflow to split ${storyId} into 2 or more smaller INVEST sub-stories, each sized for a single TCR cycle \u2014 the current card is too large (every agent has failed it). Read its spec at .roll/features/<epic>/${storyId}/spec.md and carve it along natural seams. For each sub-story create its .roll/features/<epic>/<id>/spec.md. Do NOT edit the backlog. Output exactly one final line: SUBCARDS: <id1>,<id2>,...`;
253680
+ const r = await spawnPeerReviewAgent({ agent: designer, projectPath: projectPath3, prompt, timeoutMs: DESIGN_TIMEOUT_MS });
253681
+ const m7 = /^\s*SUBCARDS:\s*(.+?)\s*$/im.exec(r.stdout);
253682
+ if (m7?.[1] === void 0)
253683
+ return [];
253684
+ return m7[1].split(",").map((s) => s.trim()).filter((s) => s !== "");
253685
+ },
253686
+ selfDowngrade: (storyId, reason, subIds) => loopSelfDowngradeCommand([storyId, reason, subIds.join(",")])
253687
+ };
253688
+ }
253689
+ function usage4() {
253690
+ process.stderr.write("Usage: roll loop exhaustion-split <story-id> [reason]\n Agent-exhaustion auto-split: $roll-design mints 2+ sub-stories, then self-downgrade\n parks the parent at Hold + appends them (cap-hit / irreducible \u2192 ALERT for triage).\n");
253691
+ return 2;
253692
+ }
253693
+ async function loopExhaustionSplitCommand(argv, deps = realExhaustionSplitDeps()) {
253694
+ const storyId = (argv[0] ?? "").trim();
253695
+ if (storyId === "")
253696
+ return usage4();
253697
+ const detail = (argv[1] ?? "").trim() || "every agent exhausted on this card (zero TCR)";
253698
+ const project = (process.env["ROLL_MAIN_PROJECT"] ?? "").trim() || process.cwd();
253699
+ const log = deps.log ?? ((m7) => void process.stdout.write(m7));
253700
+ const subIds = await deps.design(project, storyId);
253701
+ const reason = `auto-split on agent-exhaustion: ${detail}`;
253702
+ log(subIds.length < 2 ? `exhaustion-split: ${storyId} \u2014 design produced <2 sub-stories; parking for triage
253703
+ ` : `exhaustion-split: ${storyId} \u2014 landing split \u2192 ${subIds.join(", ")}
253704
+ `);
253705
+ return await deps.selfDowngrade(storyId, reason, subIds);
253706
+ }
253707
+
253506
253708
  // packages/cli/dist/commands/loop-run-once.js
253507
253709
  init_dist2();
253508
253710
  init_dist();
253509
253711
  init_dist3();
253510
- import { appendFileSync as appendFileSync19, existsSync as existsSync86, mkdirSync as mkdirSync41, readFileSync as readFileSync81, writeFileSync as writeFileSync41 } from "node:fs";
253511
- import { dirname as dirname41, join as join91 } from "node:path";
253712
+ import { appendFileSync as appendFileSync19, existsSync as existsSync87, mkdirSync as mkdirSync41, readFileSync as readFileSync82, writeFileSync as writeFileSync42 } from "node:fs";
253713
+ import { dirname as dirname41, join as join92 } from "node:path";
253512
253714
 
253513
253715
  // packages/cli/dist/runner/executor.js
253514
253716
  init_dist2();
253515
253717
  init_dist();
253516
253718
  init_dist3();
253517
253719
  import { execFile as execFile10, execFileSync as execFileSync21 } from "node:child_process";
253518
- import { appendFileSync as appendFileSync16, existsSync as existsSync82, lstatSync as lstatSync4, mkdirSync as mkdirSync37, readdirSync as readdirSync34, readFileSync as readFileSync77, realpathSync as realpathSync9, rmSync as rmSync15, statSync as statSync26, symlinkSync as symlinkSync3, unlinkSync as unlinkSync3, writeFileSync as writeFileSync37 } from "node:fs";
253519
- import { dirname as dirname37, join as join87 } from "node:path";
253720
+ import { appendFileSync as appendFileSync16, existsSync as existsSync83, lstatSync as lstatSync4, mkdirSync as mkdirSync37, readdirSync as readdirSync34, readFileSync as readFileSync78, realpathSync as realpathSync9, rmSync as rmSync15, statSync as statSync26, symlinkSync as symlinkSync3, unlinkSync as unlinkSync3, writeFileSync as writeFileSync38 } from "node:fs";
253721
+ import { dirname as dirname37, join as join88 } from "node:path";
253520
253722
  import { promisify as promisify10 } from "node:util";
253521
253723
 
253522
253724
  // packages/cli/dist/runner/agent-liveness.js
@@ -253658,16 +253860,84 @@ function clearCardFailure(runtimeDir9, storyId) {
253658
253860
  write(runtimeDir9, s);
253659
253861
  }
253660
253862
 
253863
+ // packages/cli/dist/runner/selfheal-budget.js
253864
+ import { existsSync as existsSync80, readFileSync as readFileSync74, writeFileSync as writeFileSync35 } from "node:fs";
253865
+ import { join as join84 } from "node:path";
253866
+ var SELFHEAL_AGENT_BUDGET = 2;
253867
+ function selfHealBudget(env = process.env) {
253868
+ const raw = (env["ROLL_LOOP_AGENT_RETRY_MAX"] ?? "").trim();
253869
+ if (raw === "")
253870
+ return SELFHEAL_AGENT_BUDGET;
253871
+ const n = Number(raw);
253872
+ return Number.isFinite(n) && n >= 0 ? Math.trunc(n) : SELFHEAL_AGENT_BUDGET;
253873
+ }
253874
+ function autoRecoverEnabled(env = process.env) {
253875
+ return (env["ROLL_LOOP_NO_AUTO_RECOVER"] ?? "").trim() !== "1";
253876
+ }
253877
+ var EMPTY = { attempts: 0, triedAgents: [], lastReason: "" };
253878
+ function stateFile2(runtimeDir9) {
253879
+ return join84(runtimeDir9, "selfheal-cards.json");
253880
+ }
253881
+ function read2(runtimeDir9) {
253882
+ try {
253883
+ const p = stateFile2(runtimeDir9);
253884
+ if (!existsSync80(p))
253885
+ return { stories: {} };
253886
+ const o = JSON.parse(readFileSync74(p, "utf8"));
253887
+ return { stories: o.stories !== void 0 && typeof o.stories === "object" ? o.stories : {} };
253888
+ } catch {
253889
+ return { stories: {} };
253890
+ }
253891
+ }
253892
+ function write2(runtimeDir9, s) {
253893
+ try {
253894
+ writeFileSync35(stateFile2(runtimeDir9), JSON.stringify(s, null, 2), "utf8");
253895
+ } catch {
253896
+ }
253897
+ }
253898
+ function readSelfHeal(runtimeDir9, storyId) {
253899
+ if (storyId === "")
253900
+ return { ...EMPTY };
253901
+ const e = read2(runtimeDir9).stories[storyId];
253902
+ return e !== void 0 ? { attempts: e.attempts ?? 0, triedAgents: Array.isArray(e.triedAgents) ? e.triedAgents : [], lastReason: e.lastReason ?? "" } : { ...EMPTY };
253903
+ }
253904
+ function recordSelfHealAttempt(runtimeDir9, storyId, failedAgent, reason) {
253905
+ if (storyId === "")
253906
+ return { ...EMPTY };
253907
+ const s = read2(runtimeDir9);
253908
+ const prev = s.stories[storyId] ?? { ...EMPTY };
253909
+ const tried = new Set(prev.triedAgents);
253910
+ if (failedAgent !== "")
253911
+ tried.add(failedAgent);
253912
+ const next = {
253913
+ attempts: prev.attempts + 1,
253914
+ triedAgents: [...tried],
253915
+ lastReason: reason
253916
+ };
253917
+ s.stories[storyId] = next;
253918
+ write2(runtimeDir9, s);
253919
+ return next;
253920
+ }
253921
+ function clearSelfHeal(runtimeDir9, storyId) {
253922
+ if (storyId === "")
253923
+ return;
253924
+ const s = read2(runtimeDir9);
253925
+ if (s.stories[storyId] === void 0)
253926
+ return;
253927
+ delete s.stories[storyId];
253928
+ write2(runtimeDir9, s);
253929
+ }
253930
+
253661
253931
  // packages/cli/dist/runner/usage-recovery.js
253662
253932
  init_dist2();
253663
- import { readFileSync as readFileSync74, readdirSync as readdirSync32, statSync as statSync25 } from "node:fs";
253933
+ import { readFileSync as readFileSync75, readdirSync as readdirSync32, statSync as statSync25 } from "node:fs";
253664
253934
  import { homedir as homedir22 } from "node:os";
253665
- import { basename as basename16, join as join84 } from "node:path";
253935
+ import { basename as basename16, join as join85 } from "node:path";
253666
253936
  function defaultPiSessionsRoot() {
253667
- return join84(homedir22(), ".pi", "agent", "sessions");
253937
+ return join85(homedir22(), ".pi", "agent", "sessions");
253668
253938
  }
253669
253939
  function piSessionsDirFor(root, cwd) {
253670
- return join84(root, `--${cwd.replace(/^\//, "").replace(/\//g, "-")}--`);
253940
+ return join85(root, `--${cwd.replace(/^\//, "").replace(/\//g, "-")}--`);
253671
253941
  }
253672
253942
  function recoverPiUsage(worktreeCwd, sinceSec, sessionsRoot = defaultPiSessionsRoot()) {
253673
253943
  const dir = piSessionsDirFor(sessionsRoot, worktreeCwd);
@@ -253679,11 +253949,11 @@ function recoverPiUsage(worktreeCwd, sinceSec, sessionsRoot = defaultPiSessionsR
253679
253949
  }
253680
253950
  const summaries = [];
253681
253951
  for (const f of files) {
253682
- const p = join84(dir, f);
253952
+ const p = join85(dir, f);
253683
253953
  try {
253684
253954
  if (sinceSec !== void 0 && statSync25(p).mtimeMs / 1e3 < sinceSec)
253685
253955
  continue;
253686
- summaries.push(sumPiSession(readFileSync74(p, "utf8").split("\n")));
253956
+ summaries.push(sumPiSession(readFileSync75(p, "utf8").split("\n")));
253687
253957
  } catch {
253688
253958
  }
253689
253959
  }
@@ -253702,7 +253972,7 @@ function recoverPiUsage(worktreeCwd, sinceSec, sessionsRoot = defaultPiSessionsR
253702
253972
  };
253703
253973
  }
253704
253974
  function defaultKimiSessionsRoot() {
253705
- return (process.env["ROLL_KIMI_SESSIONS_DIR"] ?? "").trim() || join84(homedir22(), ".kimi-code", "sessions");
253975
+ return (process.env["ROLL_KIMI_SESSIONS_DIR"] ?? "").trim() || join85(homedir22(), ".kimi-code", "sessions");
253706
253976
  }
253707
253977
  function recoverKimiUsage(worktreeCwd, sinceSec, sessionsRoot = defaultKimiSessionsRoot()) {
253708
253978
  const wantBasename = basename16(worktreeCwd.replace(/\/+$/, ""));
@@ -253714,7 +253984,7 @@ function recoverKimiUsage(worktreeCwd, sinceSec, sessionsRoot = defaultKimiSessi
253714
253984
  }
253715
253985
  const wireFiles = [];
253716
253986
  for (const wd of wdDirs) {
253717
- const agentsRoot = join84(sessionsRoot, wd);
253987
+ const agentsRoot = join85(sessionsRoot, wd);
253718
253988
  let sessions;
253719
253989
  try {
253720
253990
  sessions = readdirSync32(agentsRoot).filter((s) => s.startsWith("session_"));
@@ -253722,7 +253992,7 @@ function recoverKimiUsage(worktreeCwd, sinceSec, sessionsRoot = defaultKimiSessi
253722
253992
  continue;
253723
253993
  }
253724
253994
  for (const session of sessions) {
253725
- wireFiles.push(join84(agentsRoot, session, "agents", "main", "wire.jsonl"));
253995
+ wireFiles.push(join85(agentsRoot, session, "agents", "main", "wire.jsonl"));
253726
253996
  }
253727
253997
  }
253728
253998
  const summaries = [];
@@ -253730,7 +254000,7 @@ function recoverKimiUsage(worktreeCwd, sinceSec, sessionsRoot = defaultKimiSessi
253730
254000
  try {
253731
254001
  if (sinceSec !== void 0 && statSync25(p).mtimeMs / 1e3 < sinceSec)
253732
254002
  continue;
253733
- summaries.push(sumKimiWire(readFileSync74(p, "utf8").split("\n")));
254003
+ summaries.push(sumKimiWire(readFileSync75(p, "utf8").split("\n")));
253734
254004
  } catch {
253735
254005
  }
253736
254006
  }
@@ -253748,11 +254018,11 @@ function recoverKimiUsage(worktreeCwd, sinceSec, sessionsRoot = defaultKimiSessi
253748
254018
 
253749
254019
  // packages/cli/dist/runner/attest-remediation.js
253750
254020
  init_dist2();
253751
- import { existsSync as existsSync80, mkdirSync as mkdirSync35, readFileSync as readFileSync75, writeFileSync as writeFileSync35 } from "node:fs";
253752
- import { basename as basename17, join as join85 } from "node:path";
254021
+ import { existsSync as existsSync81, mkdirSync as mkdirSync35, readFileSync as readFileSync76, writeFileSync as writeFileSync36 } from "node:fs";
254022
+ import { basename as basename17, join as join86 } from "node:path";
253753
254023
  var ACMAP_REMEDIATION_TIMEOUT_MS = 6 * 6e4;
253754
254024
  function acMapPath(worktreeCwd, storyId) {
253755
- return join85(cardArchiveDir(worktreeCwd, storyId), "ac-map.json");
254025
+ return join86(cardArchiveDir(worktreeCwd, storyId), "ac-map.json");
253756
254026
  }
253757
254027
  function needsAcMapRemediation(worktreeCwd, storyId) {
253758
254028
  if (storyId === "")
@@ -253760,10 +254030,10 @@ function needsAcMapRemediation(worktreeCwd, storyId) {
253760
254030
  if (storyHasAcBlock(worktreeCwd, storyId) !== true)
253761
254031
  return false;
253762
254032
  const p = acMapPath(worktreeCwd, storyId);
253763
- if (!existsSync80(p))
254033
+ if (!existsSync81(p))
253764
254034
  return true;
253765
254035
  try {
253766
- const entries = JSON.parse(readFileSync75(p, "utf8"));
254036
+ const entries = JSON.parse(readFileSync76(p, "utf8"));
253767
254037
  if (!Array.isArray(entries) || entries.length === 0)
253768
254038
  return true;
253769
254039
  const allDraft = entries.every((e) => typeof e === "object" && e !== null && (e["status"] === ACMAP_DRAFT_STATUS || e["status"] === ACMAP_PASS_WITH_EVIDENCE));
@@ -253881,13 +254151,13 @@ function generateAcMapDraft(specText, storyId, evidence, signals) {
253881
254151
  return JSON.stringify(entries, null, 2) + "\n";
253882
254152
  }
253883
254153
  function writeAcMapDraftEvidenceFiles(worktreeCwd, storyId, evidence) {
253884
- const evidenceDir = join85(cardArchiveDir(worktreeCwd, storyId), "evidence");
254154
+ const evidenceDir = join86(cardArchiveDir(worktreeCwd, storyId), "evidence");
253885
254155
  mkdirSync35(evidenceDir, { recursive: true });
253886
- writeFileSync35(join85(evidenceDir, `commits-${storyId}.txt`), `${evidence.commitLines.length === 0 ? "(no commits observed)" : evidence.commitLines.join("\n")}
254156
+ writeFileSync36(join86(evidenceDir, `commits-${storyId}.txt`), `${evidence.commitLines.length === 0 ? "(no commits observed)" : evidence.commitLines.join("\n")}
253887
254157
  `);
253888
- writeFileSync35(join85(evidenceDir, `changed-files-${storyId}.txt`), `${evidence.changedFilenames.length === 0 ? "(no changed files observed)" : evidence.changedFilenames.join("\n")}
254158
+ writeFileSync36(join86(evidenceDir, `changed-files-${storyId}.txt`), `${evidence.changedFilenames.length === 0 ? "(no changed files observed)" : evidence.changedFilenames.join("\n")}
253889
254159
  `);
253890
- writeFileSync35(join85(evidenceDir, `test-output-${storyId}.txt`), [
254160
+ writeFileSync36(join86(evidenceDir, `test-output-${storyId}.txt`), [
253891
254161
  "Harness ac-map draft test signals",
253892
254162
  "",
253893
254163
  "Changed test files:",
@@ -253900,8 +254170,8 @@ function writeAcMapDraftEvidenceFiles(worktreeCwd, storyId, evidence) {
253900
254170
  }
253901
254171
  function buildAcMapRemediationPrompt(worktreeCwd, storyId, runDir) {
253902
254172
  const target = acMapPath(worktreeCwd, storyId);
253903
- const storyDir = join85(cardArchiveDir(worktreeCwd, storyId));
253904
- const draftExists = existsSync80(target);
254173
+ const storyDir = join86(cardArchiveDir(worktreeCwd, storyId));
254174
+ const draftExists = existsSync81(target);
253905
254175
  if (draftExists) {
253906
254176
  return [
253907
254177
  `[attest confirmation / \u9A8C\u6536\u786E\u8BA4] \u9A8C\u6536\u8349\u7A3F ac-map.json \u5DF2\u7531 harness \u4ECE cycle \u8BC1\u636E(\u63D0\u4EA4/\u6D4B\u8BD5\u6587\u4EF6/\u6539\u52A8\u6587\u4EF6)\u81EA\u52A8\u751F\u6210\u3002\u4F60\u53EA\u9700\u786E\u8BA4\u6216\u66F4\u6B63\u6BCF\u6761 AC \u7684\u72B6\u6001\u3002`,
@@ -253917,7 +254187,7 @@ function buildAcMapRemediationPrompt(worktreeCwd, storyId, runDir) {
253917
254187
  ` - "claimed" \u2014 you believe it passes but have no hard evidence.`,
253918
254188
  ` - "missing" \u2014 not addressed this cycle.`,
253919
254189
  ` - Do NOT leave any row as "pass-with-evidence" or "needs-confirmation" \u2014 those are harness drafts, not final statuses.`,
253920
- `4. Where useful, save REAL command output from this cycle as text evidence under ${join85(storyDir, "evidence")}/.`,
254190
+ `4. Where useful, save REAL command output from this cycle as text evidence under ${join86(storyDir, "evidence")}/.`,
253921
254191
  `5. Edit ${target} \u2014 update ONLY the status fields (and optionally add real evidence). Keep the existing evidence chain.`,
253922
254192
  ``,
253923
254193
  `Proof that you updated: \`node -e 'const a=JSON.parse(require("fs").readFileSync("${target}","utf8")); const bad=a.filter(e=>e.status==="pass-with-evidence"||e.status==="needs-confirmation"); if(bad.length>0) throw new Error(bad.length+" ACs still have draft status"); console.log("ok "+a.length+" ACs confirmed")'\``,
@@ -253928,9 +254198,9 @@ function buildAcMapRemediationPrompt(worktreeCwd, storyId, runDir) {
253928
254198
  `[attest remediation / \u9A8C\u6536\u8865\u5168] \u4F60\u521A\u5728\u672C cycle \u4EA4\u4ED8\u4E86 ${storyId},\u4F46\u6F0F\u5199\u4E86\u9A8C\u6536\u610F\u56FE\u6620\u5C04 ac-map.json \u2014 \u8FD9\u662F\u552F\u4E00\u7F3A\u53E3,\u7F3A\u5B83\u6574\u4E2A\u4EA4\u4ED8\u4F1A\u88AB attest gate \u5224\u5931\u8D25\u3002`,
253929
254199
  `You delivered ${storyId} this cycle but skipped the acceptance intent map (skill step 10.6). Without it the attest gate fails the whole delivery. Do ONLY the following:`,
253930
254200
  ``,
253931
- `1. Read the story spec and its AC list: ${join85(storyDir, "spec.md")}`,
254201
+ `1. Read the story spec and its AC list: ${join86(storyDir, "spec.md")}`,
253932
254202
  `2. Review what you actually did this cycle: \`git log --oneline origin/main..HEAD\` and \`git diff origin/main...HEAD --stat\` in ${worktreeCwd}.`,
253933
- `3. Where useful, save REAL command output from this cycle as text evidence under ${join85(storyDir, "evidence")}/ (create the dir if absent).`,
254203
+ `3. Where useful, save REAL command output from this cycle as text evidence under ${join86(storyDir, "evidence")}/ (create the dir if absent).`,
253934
254204
  `4. Write ${target} \u2014 a JSON array with EXACTLY one entry per AC:`,
253935
254205
  ``,
253936
254206
  `[{ "ac": "${storyId}:AC1", "status": "pass",`,
@@ -253949,7 +254219,7 @@ function capturedScreenshotRef(runDir) {
253949
254219
  return null;
253950
254220
  const taken = /* @__PURE__ */ new Set();
253951
254221
  try {
253952
- const ev = JSON.parse(readFileSync75(join85(runDir, "evidence.json"), "utf8"));
254222
+ const ev = JSON.parse(readFileSync76(join86(runDir, "evidence.json"), "utf8"));
253953
254223
  for (const c2 of ev.captures ?? []) {
253954
254224
  if (c2.taken !== true || typeof c2.out !== "string" || c2.out === "")
253955
254225
  continue;
@@ -253961,7 +254231,7 @@ function capturedScreenshotRef(runDir) {
253961
254231
  return null;
253962
254232
  }
253963
254233
  for (const name of ["web.png", "terminal.png"]) {
253964
- if (taken.has(name) && existsSync80(join85(runDir, "screenshots", name)))
254234
+ if (taken.has(name) && existsSync81(join86(runDir, "screenshots", name)))
253965
254235
  return `screenshots/${name}`;
253966
254236
  }
253967
254237
  return null;
@@ -253978,11 +254248,11 @@ function autoAttachScreenshotToAcMap(worktreeCwd, storyId, runDir) {
253978
254248
  if (ref === null)
253979
254249
  return null;
253980
254250
  const p = acMapPath(worktreeCwd, storyId);
253981
- if (!existsSync80(p))
254251
+ if (!existsSync81(p))
253982
254252
  return null;
253983
254253
  let entries;
253984
254254
  try {
253985
- const parsed = JSON.parse(readFileSync75(p, "utf8"));
254255
+ const parsed = JSON.parse(readFileSync76(p, "utf8"));
253986
254256
  if (!Array.isArray(parsed))
253987
254257
  return null;
253988
254258
  entries = parsed;
@@ -254001,7 +254271,7 @@ function autoAttachScreenshotToAcMap(worktreeCwd, storyId, runDir) {
254001
254271
  }
254002
254272
  if (count === 0)
254003
254273
  return null;
254004
- writeFileSync35(p, JSON.stringify(entries, null, 2) + "\n");
254274
+ writeFileSync36(p, JSON.stringify(entries, null, 2) + "\n");
254005
254275
  return { href: ref, count };
254006
254276
  } catch {
254007
254277
  return null;
@@ -254011,21 +254281,21 @@ function autoAttachScreenshotToAcMap(worktreeCwd, storyId, runDir) {
254011
254281
  // packages/cli/dist/runner/correction-actuator.js
254012
254282
  init_dist2();
254013
254283
  init_dist();
254014
- import { appendFileSync as appendFileSync15, existsSync as existsSync81, mkdirSync as mkdirSync36, readFileSync as readFileSync76, readdirSync as readdirSync33, writeFileSync as writeFileSync36 } from "node:fs";
254015
- import { dirname as dirname36, join as join86 } from "node:path";
254284
+ import { appendFileSync as appendFileSync15, existsSync as existsSync82, mkdirSync as mkdirSync36, readFileSync as readFileSync77, readdirSync as readdirSync33, writeFileSync as writeFileSync37 } from "node:fs";
254285
+ import { dirname as dirname36, join as join87 } from "node:path";
254016
254286
  function readMode(projectPath3) {
254017
254287
  try {
254018
- const path = join86(projectPath3, ".roll", "policy.yaml");
254019
- if (!existsSync81(path))
254288
+ const path = join87(projectPath3, ".roll", "policy.yaml");
254289
+ if (!existsSync82(path))
254020
254290
  return "conservative";
254021
- return parsePolicy(readFileSync76(path, "utf8")).loopSafety.correctionActuator;
254291
+ return parsePolicy(readFileSync77(path, "utf8")).loopSafety.correctionActuator;
254022
254292
  } catch {
254023
254293
  return "conservative";
254024
254294
  }
254025
254295
  }
254026
254296
  function readEvents2(eventsPath2) {
254027
254297
  try {
254028
- return readFileSync76(eventsPath2, "utf8").split("\n").map(parseEventLine).filter((ev) => ev !== null);
254298
+ return readFileSync77(eventsPath2, "utf8").split("\n").map(parseEventLine).filter((ev) => ev !== null);
254029
254299
  } catch {
254030
254300
  return [];
254031
254301
  }
@@ -254048,7 +254318,7 @@ function appendAlert2(alertsPath, msg6) {
254048
254318
  }
254049
254319
  function markStoryTodo(projectPath3, storyId) {
254050
254320
  try {
254051
- const path = join86(projectPath3, ".roll", "backlog.md");
254321
+ const path = join87(projectPath3, ".roll", "backlog.md");
254052
254322
  const store = new BacklogStore();
254053
254323
  const snap = store.readBacklog(path);
254054
254324
  const row2 = snap.items.find((it) => it.id === storyId);
@@ -254064,18 +254334,18 @@ function markStoryTodo(projectPath3, storyId) {
254064
254334
  }
254065
254335
  function storyEpic(projectPath3, storyId) {
254066
254336
  try {
254067
- const idx = JSON.parse(readFileSync76(join86(projectPath3, ".roll", "index.json"), "utf8"));
254337
+ const idx = JSON.parse(readFileSync77(join87(projectPath3, ".roll", "index.json"), "utf8"));
254068
254338
  const epic = idx[storyId];
254069
254339
  if (typeof epic === "string" && epic.trim() !== "")
254070
254340
  return epic;
254071
254341
  } catch {
254072
254342
  }
254073
254343
  try {
254074
- const features = join86(projectPath3, ".roll", "features");
254344
+ const features = join87(projectPath3, ".roll", "features");
254075
254345
  for (const d of readdirSync33(features, { withFileTypes: true })) {
254076
254346
  if (!d.isDirectory())
254077
254347
  continue;
254078
- if (existsSync81(join86(features, d.name, storyId)))
254348
+ if (existsSync82(join87(features, d.name, storyId)))
254079
254349
  return d.name;
254080
254350
  }
254081
254351
  } catch {
@@ -254084,7 +254354,7 @@ function storyEpic(projectPath3, storyId) {
254084
254354
  }
254085
254355
  function existingFixId(projectPath3, storyId, signal) {
254086
254356
  try {
254087
- const snap = new BacklogStore().readBacklog(join86(projectPath3, ".roll", "backlog.md"));
254357
+ const snap = new BacklogStore().readBacklog(join87(projectPath3, ".roll", "backlog.md"));
254088
254358
  return snap.items.find((it) => {
254089
254359
  const desc = it.desc.toLowerCase();
254090
254360
  if (!it.id.startsWith("FIX-"))
@@ -254106,7 +254376,7 @@ function fixDescription(storyId, signal) {
254106
254376
  }
254107
254377
  function writeFixSpec(projectPath3, epic, fixId, decision) {
254108
254378
  try {
254109
- const dir = join86(projectPath3, ".roll", "features", epic, fixId);
254379
+ const dir = join87(projectPath3, ".roll", "features", epic, fixId);
254110
254380
  mkdirSync36(dir, { recursive: true });
254111
254381
  const body = [
254112
254382
  "---",
@@ -254137,7 +254407,7 @@ function writeFixSpec(projectPath3, epic, fixId, decision) {
254137
254407
  "- [ ] Leave the PR open for human merge approval",
254138
254408
  ""
254139
254409
  ].join("\n");
254140
- writeFileSync36(join86(dir, "spec.md"), body, "utf8");
254410
+ writeFileSync37(join87(dir, "spec.md"), body, "utf8");
254141
254411
  } catch {
254142
254412
  }
254143
254413
  }
@@ -254145,7 +254415,7 @@ function createFix(projectPath3, decision) {
254145
254415
  const existing = existingFixId(projectPath3, decision.storyId, decision.signal);
254146
254416
  if (existing !== void 0)
254147
254417
  return { mutation: "existing_fix", fixId: existing };
254148
- const path = join86(projectPath3, ".roll", "backlog.md");
254418
+ const path = join87(projectPath3, ".roll", "backlog.md");
254149
254419
  const store = new BacklogStore();
254150
254420
  for (let attempt = 0; attempt < 2; attempt++) {
254151
254421
  try {
@@ -254170,7 +254440,7 @@ function createFix(projectPath3, decision) {
254170
254440
  }
254171
254441
  function markStoryHold(projectPath3, storyId, reason) {
254172
254442
  try {
254173
- const path = join86(projectPath3, ".roll", "backlog.md");
254443
+ const path = join87(projectPath3, ".roll", "backlog.md");
254174
254444
  const store = new BacklogStore();
254175
254445
  const snap = store.readBacklog(path);
254176
254446
  const row2 = snap.items.find((it) => it.id === storyId);
@@ -254247,14 +254517,14 @@ async function rescueLeakedMain(repoCwd, refName) {
254247
254517
  code = 1;
254248
254518
  }
254249
254519
  let backlogWorktreeContent;
254250
- const backlogPath = join87(repoCwd, ".roll", "backlog.md");
254520
+ const backlogPath = join88(repoCwd, ".roll", "backlog.md");
254251
254521
  try {
254252
254522
  const status2 = await execFileAsync10("git", ["status", "--porcelain", "--", ".roll/backlog.md"], {
254253
254523
  cwd: repoCwd,
254254
254524
  encoding: "utf8"
254255
254525
  });
254256
254526
  if ((status2.stdout ?? "").trim() !== "") {
254257
- backlogWorktreeContent = readFileSync77(backlogPath, "utf8");
254527
+ backlogWorktreeContent = readFileSync78(backlogPath, "utf8");
254258
254528
  }
254259
254529
  } catch {
254260
254530
  backlogWorktreeContent = void 0;
@@ -254270,7 +254540,7 @@ async function rescueLeakedMain(repoCwd, refName) {
254270
254540
  if (backlogWorktreeContent !== void 0) {
254271
254541
  try {
254272
254542
  mkdirSync37(dirname37(backlogPath), { recursive: true });
254273
- writeFileSync37(backlogPath, backlogWorktreeContent, "utf8");
254543
+ writeFileSync38(backlogPath, backlogWorktreeContent, "utf8");
254274
254544
  } catch {
254275
254545
  code = 1;
254276
254546
  }
@@ -254290,7 +254560,7 @@ var ActivitySignalRecorder = class {
254290
254560
  this.state = newNormalizerState();
254291
254561
  try {
254292
254562
  mkdirSync37(dirname37(signalPath), { recursive: true });
254293
- writeFileSync37(signalPath, "", "utf8");
254563
+ writeFileSync38(signalPath, "", "utf8");
254294
254564
  } catch {
254295
254565
  }
254296
254566
  this.recordLine(banner);
@@ -254402,9 +254672,9 @@ function readCycleTimeoutThresholds(repoCwd) {
254402
254672
  let wallSec = CYCLE_WALL_TIMEOUT_SEC;
254403
254673
  let noProgressSec = CYCLE_NO_PROGRESS_SEC;
254404
254674
  try {
254405
- const p = join87(repoCwd, ".roll", "policy.yaml");
254406
- if (existsSync82(p)) {
254407
- const ls = parsePolicy(readFileSync77(p, "utf8")).loopSafety;
254675
+ const p = join88(repoCwd, ".roll", "policy.yaml");
254676
+ if (existsSync83(p)) {
254677
+ const ls = parsePolicy(readFileSync78(p, "utf8")).loopSafety;
254408
254678
  wallSec = ls.cycleWallTimeoutSec;
254409
254679
  noProgressSec = ls.cycleNoProgressSec;
254410
254680
  }
@@ -254415,6 +254685,17 @@ function readCycleTimeoutThresholds(repoCwd) {
254415
254685
  noProgressSec: envNum("ROLL_CYCLE_NO_PROGRESS_SEC") ?? noProgressSec
254416
254686
  };
254417
254687
  }
254688
+ function readStallThreshold(repoCwd) {
254689
+ const envNum = (key) => {
254690
+ const raw = (process.env[key] ?? "").trim();
254691
+ if (raw === "")
254692
+ return void 0;
254693
+ const n = Number(raw);
254694
+ return Number.isFinite(n) ? n : void 0;
254695
+ };
254696
+ const thresholdSec = envNum("ROLL_LOOP_STALL_THRESHOLD_MIN");
254697
+ return { thresholdSec: thresholdSec ?? CYCLE_STALL_THRESHOLD_SEC };
254698
+ }
254418
254699
  function startSpawnTimeoutWatchdog(opts) {
254419
254700
  const { cycleId, thresholds, clock: clock2, commitCount, appendEvent: appendEvent3 } = opts;
254420
254701
  const kill = opts.kill ?? (() => killLiveAgents("SIGKILL"));
@@ -254490,10 +254771,68 @@ function startSpawnTimeoutWatchdog(opts) {
254490
254771
  }
254491
254772
  };
254492
254773
  }
254774
+ function startStallDetector(opts) {
254775
+ const { cycleId, agent, clock: clock2, appendEvent: appendEvent3 } = opts;
254776
+ const thresholdSec = opts.thresholdSec ?? CYCLE_STALL_THRESHOLD_SEC;
254777
+ const startupGraceSec = opts.startupGraceSec ?? STALL_STARTUP_GRACE_SEC;
254778
+ const pollMs = opts.pollMs ?? (Number((process.env["ROLL_STALL_POLL_MS"] ?? "").trim()) || 5e3);
254779
+ if (thresholdSec <= 0) {
254780
+ return { markProgress: () => {
254781
+ }, stop: () => ({ stalled: false }) };
254782
+ }
254783
+ const startSec = clock2();
254784
+ let lastProgressSec = startSec;
254785
+ let fired = false;
254786
+ let running = false;
254787
+ const markProgress = () => {
254788
+ lastProgressSec = clock2();
254789
+ };
254790
+ const tick = () => {
254791
+ if (running || fired)
254792
+ return;
254793
+ running = true;
254794
+ try {
254795
+ const now = clock2();
254796
+ const verdict = stallVerdict({
254797
+ elapsedSec: now - startSec,
254798
+ idleSec: now - lastProgressSec,
254799
+ stallThresholdSec: thresholdSec,
254800
+ startupGraceSec,
254801
+ alreadyFired: fired
254802
+ });
254803
+ if (verdict.stalled) {
254804
+ fired = true;
254805
+ clearInterval(timer);
254806
+ try {
254807
+ appendEvent3({
254808
+ type: "agent:stall",
254809
+ cycleId,
254810
+ agent,
254811
+ idleSec: verdict.idleSec,
254812
+ thresholdSec: verdict.thresholdSec,
254813
+ ts: Date.now()
254814
+ });
254815
+ } catch {
254816
+ }
254817
+ }
254818
+ } finally {
254819
+ running = false;
254820
+ }
254821
+ };
254822
+ const timer = setInterval(tick, pollMs);
254823
+ timer.unref?.();
254824
+ return {
254825
+ markProgress,
254826
+ stop: () => {
254827
+ clearInterval(timer);
254828
+ return { stalled: fired };
254829
+ }
254830
+ };
254831
+ }
254493
254832
  function createCaptureMarkerSink(runDir, capture) {
254494
254833
  let buf = "";
254495
254834
  const pending = [];
254496
- const logPath = join87(runDir, "evidence", "capture-markers.log");
254835
+ const logPath = join88(runDir, "evidence", "capture-markers.log");
254497
254836
  const record = (marker, result) => {
254498
254837
  try {
254499
254838
  mkdirSync37(dirname37(logPath), { recursive: true });
@@ -254507,7 +254846,7 @@ function createCaptureMarkerSink(runDir, capture) {
254507
254846
  return;
254508
254847
  pending.push(capture.fromMarker(marker, runDir).then((result) => record(marker, result)).catch((e) => record(marker, {
254509
254848
  kind: marker.kind,
254510
- out: join87(runDir, "screenshots", `${marker.phase}-${marker.stem}.png`),
254849
+ out: join88(runDir, "screenshots", `${marker.phase}-${marker.stem}.png`),
254511
254850
  taken: false,
254512
254851
  skipped: `capture errored: ${String(e)}`
254513
254852
  })));
@@ -254674,16 +255013,23 @@ async function executeCommand(cmd, ports, ctx) {
254674
255013
  ctxPatch: { builderSessionId }
254675
255014
  };
254676
255015
  }
254677
- const livePath = join87(dirname37(ports.paths.eventsPath), "live.log");
255016
+ const livePath = join88(dirname37(ports.paths.eventsPath), "live.log");
254678
255017
  const liveBanner = `\u2500\u2500 cycle ${ctx.cycleId ?? "?"} \xB7 ${ctx.storyId ?? "?"} \xB7 agent ${cmd.agent} \xB7 build-session ${builderSessionId} \u2500\u2500`;
254679
255018
  try {
254680
- writeFileSync37(livePath, `${liveBanner}
255019
+ writeFileSync38(livePath, `${liveBanner}
254681
255020
  `);
254682
255021
  } catch {
254683
255022
  }
254684
- const signalRecorder = new ActivitySignalRecorder(join87(dirname37(ports.paths.eventsPath), `cycle-${ctx.cycleId ?? "unknown"}.signals.jsonl`), cmd.agent, liveBanner, () => eventTs2(ports));
255023
+ const signalRecorder = new ActivitySignalRecorder(join88(dirname37(ports.paths.eventsPath), `cycle-${ctx.cycleId ?? "unknown"}.signals.jsonl`), cmd.agent, liveBanner, () => eventTs2(ports));
254685
255024
  const captureSink = ctx.evidenceRunDir !== void 0 && ctx.evidenceRunDir !== "" ? createCaptureMarkerSink(ctx.evidenceRunDir, ports.capture) : void 0;
254686
255025
  const observer = await startCycleObserver(ports, ctx.cycleId ?? "");
255026
+ const stallDetector = startStallDetector({
255027
+ cycleId: ctx.cycleId ?? "",
255028
+ agent: cmd.agent,
255029
+ clock: ports.clock,
255030
+ appendEvent: (ev) => ports.events.appendEvent(ports.paths.eventsPath, ev),
255031
+ thresholdSec: readStallThreshold(ports.repoCwd).thresholdSec
255032
+ });
254687
255033
  const timeoutWatchdog = startSpawnTimeoutWatchdog({
254688
255034
  cycleId: ctx.cycleId ?? "",
254689
255035
  thresholds: readCycleTimeoutThresholds(ports.repoCwd),
@@ -254715,6 +255061,7 @@ ${skillBodyForSpawn}` : skillBodyForSpawn;
254715
255061
  ...ctx.storyId !== void 0 && ctx.storyId !== "" ? { storyId: ctx.storyId } : {},
254716
255062
  onChunk: (d) => {
254717
255063
  timeoutWatchdog.markProgress();
255064
+ stallDetector.markProgress();
254718
255065
  captureSink?.onChunk(d);
254719
255066
  try {
254720
255067
  appendFileSync16(livePath, d);
@@ -254727,6 +255074,7 @@ ${skillBodyForSpawn}` : skillBodyForSpawn;
254727
255074
  signalRecorder.flush();
254728
255075
  await observer.stop();
254729
255076
  timeoutFired = timeoutWatchdog.stop().firedReason;
255077
+ stallDetector.stop();
254730
255078
  }
254731
255079
  if (timeoutFired !== null)
254732
255080
  res = { ...res, timedOut: true };
@@ -254747,10 +255095,10 @@ ${res.stderr}`.split("\n").find((l) => l.trim() !== "") ?? "").slice(0, 200),
254747
255095
  });
254748
255096
  }
254749
255097
  try {
254750
- const logDir = join87(dirname37(ports.paths.eventsPath), "cycle-logs");
255098
+ const logDir = join88(dirname37(ports.paths.eventsPath), "cycle-logs");
254751
255099
  mkdirSync37(logDir, { recursive: true });
254752
- writeFileSync37(
254753
- join87(logDir, `${ctx.cycleId ?? "cycle"}.agent.log`),
255100
+ writeFileSync38(
255101
+ join88(logDir, `${ctx.cycleId ?? "cycle"}.agent.log`),
254754
255102
  // FIX-343 (step ①): the builder session id is part of the auditable
254755
255103
  // header — the attest gate's scorer≠builder-session invariant is then
254756
255104
  // traceable to a recorded build-session id, not asserted.
@@ -254768,19 +255116,19 @@ ${res.stderr}
254768
255116
  const agentName = ctx.agent ?? cmd.agent;
254769
255117
  const lines2 = res.stdout.split("\n");
254770
255118
  const usageSpec = getAgentSpec(agentName)?.usage;
254771
- let usage4 = usageSpec?.stdoutExtractor === "claude-stream" ? extractUsage(agentName, lines2) : null;
254772
- if (usage4 === null && usageSpec?.sessionRecovery === "pi") {
255119
+ let usage5 = usageSpec?.stdoutExtractor === "claude-stream" ? extractUsage(agentName, lines2) : null;
255120
+ if (usage5 === null && usageSpec?.sessionRecovery === "pi") {
254773
255121
  const rootOverride = (process.env["ROLL_PI_SESSIONS_ROOT"] ?? "").trim();
254774
- usage4 = recoverPiUsage(ports.paths.worktreePath, ctx.startSec, ...rootOverride !== "" ? [rootOverride] : []);
255122
+ usage5 = recoverPiUsage(ports.paths.worktreePath, ctx.startSec, ...rootOverride !== "" ? [rootOverride] : []);
254775
255123
  }
254776
- if (usage4 === null && usageSpec?.sessionRecovery === "kimi") {
255124
+ if (usage5 === null && usageSpec?.sessionRecovery === "kimi") {
254777
255125
  const rootOverride = (process.env["ROLL_KIMI_SESSIONS_DIR"] ?? "").trim();
254778
- usage4 = recoverKimiUsage(ports.paths.worktreePath, ctx.startSec, ...rootOverride !== "" ? [rootOverride] : []);
255126
+ usage5 = recoverKimiUsage(ports.paths.worktreePath, ctx.startSec, ...rootOverride !== "" ? [rootOverride] : []);
254779
255127
  }
254780
- if (usage4 === null)
254781
- usage4 = extractUsage(agentName, lines2);
254782
- if (usage4 !== null) {
254783
- costPatch = toCycleCost(usage4, {
255128
+ if (usage5 === null)
255129
+ usage5 = extractUsage(agentName, lines2);
255130
+ if (usage5 !== null) {
255131
+ costPatch = toCycleCost(usage5, {
254784
255132
  cycleId: ctx.cycleId,
254785
255133
  agent: agentName,
254786
255134
  // TCR reverts are not tracked at this layer yet; nominal == effective.
@@ -254848,9 +255196,9 @@ ${res.stderr}
254848
255196
  };
254849
255197
  const computeExcludedPeers = () => {
254850
255198
  try {
254851
- if (!existsSync82(ports.paths.eventsPath))
255199
+ if (!existsSync83(ports.paths.eventsPath))
254852
255200
  return /* @__PURE__ */ new Set();
254853
- const events = readFileSync77(ports.paths.eventsPath, "utf8").split("\n").map(parseEventLine).filter((e) => e !== null);
255201
+ const events = readFileSync78(ports.paths.eventsPath, "utf8").split("\n").map(parseEventLine).filter((e) => e !== null);
254854
255202
  const states = peerAuthStates(events);
254855
255203
  const excluded = excludedPeers(events);
254856
255204
  const announced = /* @__PURE__ */ new Set();
@@ -254967,8 +255315,8 @@ ${res.stderr}`, "review");
254967
255315
  {
254968
255316
  let pairHistory;
254969
255317
  try {
254970
- if (existsSync82(ports.paths.eventsPath)) {
254971
- const events = readFileSync77(ports.paths.eventsPath, "utf8").split("\n").map(parseEventLine).filter((e) => e !== null);
255318
+ if (existsSync83(ports.paths.eventsPath)) {
255319
+ const events = readFileSync78(ports.paths.eventsPath, "utf8").split("\n").map(parseEventLine).filter((e) => e !== null);
254972
255320
  pairHistory = pairingHistory(events);
254973
255321
  }
254974
255322
  } catch {
@@ -255085,9 +255433,9 @@ ${res.stderr}`;
255085
255433
  }
255086
255434
  let goalLine = "";
255087
255435
  try {
255088
- const specPath = join87(cardArchiveDir(ports.repoCwd, storyId), "spec.md");
255089
- if (existsSync82(specPath)) {
255090
- const title = (/^title:\s*(.+)$/m.exec(readFileSync77(specPath, "utf8"))?.[1] ?? "").trim();
255436
+ const specPath = join88(cardArchiveDir(ports.repoCwd, storyId), "spec.md");
255437
+ if (existsSync83(specPath)) {
255438
+ const title = (/^title:\s*(.+)$/m.exec(readFileSync78(specPath, "utf8"))?.[1] ?? "").trim();
255091
255439
  if (title !== "")
255092
255440
  goalLine = `Goal: ${title}
255093
255441
  `;
@@ -255116,7 +255464,7 @@ ${diffStat}`;
255116
255464
  try {
255117
255465
  const specPath = storySpecPath(ports.paths.worktreePath, storyId);
255118
255466
  if (specPath !== null) {
255119
- const specText = readFileSync77(specPath, "utf8");
255467
+ const specText = readFileSync78(specPath, "utf8");
255120
255468
  const gitEvidence = await collectDraftEvidence(ports.paths.worktreePath);
255121
255469
  let cycleSignals;
255122
255470
  try {
@@ -255131,7 +255479,7 @@ ${diffStat}`;
255131
255479
  const draftJson = generateAcMapDraft(specText, storyId, gitEvidence, cycleSignals);
255132
255480
  if (draftJson !== null) {
255133
255481
  writeAcMapDraftEvidenceFiles(ports.paths.worktreePath, storyId, gitEvidence);
255134
- writeFileSync37(acMapPath(ports.paths.worktreePath, storyId), draftJson);
255482
+ writeFileSync38(acMapPath(ports.paths.worktreePath, storyId), draftJson);
255135
255483
  ports.events.appendEvent(ports.paths.eventsPath, {
255136
255484
  type: "attest:draft-generated",
255137
255485
  cycleId: ctx.cycleId ?? "",
@@ -255348,7 +255696,7 @@ ${diffStat}`;
255348
255696
  // pure worktree teardown again.
255349
255697
  case "cleanup_worktree":
255350
255698
  try {
255351
- const dst = join87(ports.paths.worktreePath, ".roll");
255699
+ const dst = join88(ports.paths.worktreePath, ".roll");
255352
255700
  if (lstatSync4(dst, { throwIfNoEntry: false })?.isSymbolicLink() === true)
255353
255701
  unlinkSync3(dst);
255354
255702
  } catch {
@@ -255574,16 +255922,16 @@ function buildTerminalRecord(cmd, ctx, attestCwd, nowSec2) {
255574
255922
  attest = absent("not_applicable");
255575
255923
  } else {
255576
255924
  const report = verificationReportPath(attestCwd, storyId);
255577
- const hasReport = existsSync82(report);
255578
- const hasMap = existsSync82(acMapPath(attestCwd, storyId));
255925
+ const hasReport = existsSync83(report);
255926
+ const hasMap = existsSync83(acMapPath(attestCwd, storyId));
255579
255927
  if (hasReport)
255580
255928
  attest = present({ reportPath: report, acMap: hasMap });
255581
255929
  else
255582
255930
  attest = absent(hasMap ? "not_rendered" : "acmap_missing");
255583
255931
  }
255584
- let usage4;
255932
+ let usage5;
255585
255933
  if (ctx.cost !== void 0) {
255586
- usage4 = present({
255934
+ usage5 = present({
255587
255935
  model: ctx.cost.model,
255588
255936
  tokensIn: ctx.cost.tokensIn,
255589
255937
  tokensOut: ctx.cost.tokensOut,
@@ -255591,7 +255939,7 @@ function buildTerminalRecord(cmd, ctx, attestCwd, nowSec2) {
255591
255939
  ...ctx.cost.cacheWrite !== void 0 ? { cacheWrite: ctx.cost.cacheWrite } : {}
255592
255940
  });
255593
255941
  } else {
255594
- usage4 = absent("no_parseable_usage");
255942
+ usage5 = absent("no_parseable_usage");
255595
255943
  }
255596
255944
  const routedModel = (ctx.model ?? "").trim() !== "" ? ctx.model : ctx.agent ?? "";
255597
255945
  const model = ctx.cost !== void 0 && ctx.cost.model !== "" ? ctx.cost.model : routedModel;
@@ -255609,15 +255957,15 @@ function buildTerminalRecord(cmd, ctx, attestCwd, nowSec2) {
255609
255957
  commit: absent("not_recorded"),
255610
255958
  tcr: ctx.tcrCount !== void 0 ? present(ctx.tcrCount) : absent("not_recorded"),
255611
255959
  attest,
255612
- usage: usage4,
255960
+ usage: usage5,
255613
255961
  cost: ctx.cost !== void 0 ? present({ estimatedUsd: ctx.cost.estimatedCost, effectiveUsd: ctx.cost.effectiveCost }) : absent("no_parseable_usage")
255614
255962
  });
255615
255963
  }
255616
255964
  function readRunsRows(runsPath3) {
255617
255965
  try {
255618
- if (!existsSync82(runsPath3))
255966
+ if (!existsSync83(runsPath3))
255619
255967
  return [];
255620
- const all = readFileSync77(runsPath3, "utf8").split("\n").filter((l) => l.trim() !== "").map((l) => {
255968
+ const all = readFileSync78(runsPath3, "utf8").split("\n").filter((l) => l.trim() !== "").map((l) => {
255621
255969
  try {
255622
255970
  return JSON.parse(l);
255623
255971
  } catch {
@@ -255724,24 +256072,24 @@ function resetSpecTruthText(text2) {
255724
256072
  }
255725
256073
  function resetStaleSpecTruth(ports, storyId) {
255726
256074
  try {
255727
- const specPath = join87(cardArchiveDir(ports.repoCwd, storyId), "spec.md");
255728
- if (!existsSync82(specPath))
256075
+ const specPath = join88(cardArchiveDir(ports.repoCwd, storyId), "spec.md");
256076
+ if (!existsSync83(specPath))
255729
256077
  return;
255730
- const before = readFileSync77(specPath, "utf8");
256078
+ const before = readFileSync78(specPath, "utf8");
255731
256079
  const { text: text2, changed } = resetSpecTruthText(before);
255732
256080
  if (!changed)
255733
256081
  return;
255734
- writeFileSync37(specPath, text2);
256082
+ writeFileSync38(specPath, text2);
255735
256083
  ports.events.appendAlert(ports.paths.alertsPath, `spec truth reset for ${storyId}: a non-merged terminal cleared a stale \u2705/[x] spec claim so a re-run can deliver`);
255736
256084
  } catch {
255737
256085
  }
255738
256086
  }
255739
256087
  function runVisualEvidencePreflight(ports, storyId, cycleId) {
255740
256088
  try {
255741
- const specPath = join87(cardArchiveDir(ports.repoCwd, storyId), "spec.md");
255742
- if (!existsSync82(specPath))
256089
+ const specPath = join88(cardArchiveDir(ports.repoCwd, storyId), "spec.md");
256090
+ if (!existsSync83(specPath))
255743
256091
  return;
255744
- const specText = readFileSync77(specPath, "utf8");
256092
+ const specText = readFileSync78(specPath, "utf8");
255745
256093
  const v = validateStoryVisualEvidence(specText);
255746
256094
  if (v.ok) {
255747
256095
  ports.events.appendEvent(ports.paths.eventsPath, {
@@ -255796,14 +256144,14 @@ function storyRequiresManualMerge(repoCwd, storyId) {
255796
256144
  return needles.some((n) => lower.includes(n));
255797
256145
  };
255798
256146
  try {
255799
- const backlog = readFileSync77(join87(repoCwd, ".roll", "backlog.md"), "utf8");
256147
+ const backlog = readFileSync78(join88(repoCwd, ".roll", "backlog.md"), "utf8");
255800
256148
  const row2 = parseBacklog(backlog).find((it) => it.id === storyId);
255801
256149
  if (row2 !== void 0 && containsMarker(row2.desc))
255802
256150
  return true;
255803
256151
  } catch {
255804
256152
  }
255805
256153
  try {
255806
- return containsMarker(readFileSync77(join87(cardArchiveDir(repoCwd, storyId), "spec.md"), "utf8"));
256154
+ return containsMarker(readFileSync78(join88(cardArchiveDir(repoCwd, storyId), "spec.md"), "utf8"));
255807
256155
  } catch {
255808
256156
  return false;
255809
256157
  }
@@ -255845,12 +256193,12 @@ function agentWritableRoots(repoCwd, alertsPath) {
255845
256193
  const add = (p) => {
255846
256194
  if (p.trim() === "")
255847
256195
  return;
255848
- const real = existsSync82(p) ? realpathSync9(p) : p;
256196
+ const real = existsSync83(p) ? realpathSync9(p) : p;
255849
256197
  if (!roots.includes(real))
255850
256198
  roots.push(real);
255851
256199
  };
255852
- const rollDir = join87(repoCwd, ".roll");
255853
- if (existsSync82(rollDir))
256200
+ const rollDir = join88(repoCwd, ".roll");
256201
+ if (existsSync83(rollDir))
255854
256202
  add(rollDir);
255855
256203
  add(dirname37(alertsPath));
255856
256204
  try {
@@ -255872,10 +256220,10 @@ function persistWorktreeAlerts(worktreePath, alertsPath, events) {
255872
256220
  }
255873
256221
  for (const name of names) {
255874
256222
  try {
255875
- const path = join87(worktreePath, name);
256223
+ const path = join88(worktreePath, name);
255876
256224
  if (!lstatSync4(path).isFile())
255877
256225
  continue;
255878
- const body = readFileSync77(path, "utf8").trim();
256226
+ const body = readFileSync78(path, "utf8").trim();
255879
256227
  if (body === "")
255880
256228
  continue;
255881
256229
  events.appendAlert(alertsPath, `# worktree alert persisted: ${name}
@@ -255887,15 +256235,15 @@ ${body}`);
255887
256235
  }
255888
256236
  async function linkRollIntoWorktree(repoCwd, worktreePath) {
255889
256237
  try {
255890
- const src = join87(repoCwd, ".roll");
255891
- const dst = join87(worktreePath, ".roll");
255892
- if (!existsSync82(src))
256238
+ const src = join88(repoCwd, ".roll");
256239
+ const dst = join88(worktreePath, ".roll");
256240
+ if (!existsSync83(src))
255893
256241
  return;
255894
256242
  const dstStat = lstatSync4(dst, { throwIfNoEntry: false });
255895
256243
  if (dstStat) {
255896
256244
  if (dstStat.isSymbolicLink())
255897
256245
  return;
255898
- const incompleteFossil = existsSync82(join87(src, "backlog.md")) && !existsSync82(join87(dst, "backlog.md"));
256246
+ const incompleteFossil = existsSync83(join88(src, "backlog.md")) && !existsSync83(join88(dst, "backlog.md"));
255899
256247
  if (!incompleteFossil)
255900
256248
  return;
255901
256249
  rmSync15(dst, { recursive: true, force: true });
@@ -255904,8 +256252,8 @@ async function linkRollIntoWorktree(repoCwd, worktreePath) {
255904
256252
  const common = (await execFileAsync10("git", ["-C", repoCwd, "rev-parse", "--path-format=absolute", "--git-common-dir"])).stdout.trim();
255905
256253
  if (common === "")
255906
256254
  return;
255907
- const exclude = join87(common, "info", "exclude");
255908
- const cur = existsSync82(exclude) ? readFileSync77(exclude, "utf8") : "";
256255
+ const exclude = join88(common, "info", "exclude");
256256
+ const cur = existsSync83(exclude) ? readFileSync78(exclude, "utf8") : "";
255909
256257
  if (!/^\.roll$/m.test(cur)) {
255910
256258
  mkdirSync37(dirname37(exclude), { recursive: true });
255911
256259
  appendFileSync16(exclude, `${cur === "" || cur.endsWith("\n") ? "" : "\n"}.roll
@@ -255915,8 +256263,8 @@ async function linkRollIntoWorktree(repoCwd, worktreePath) {
255915
256263
  }
255916
256264
  }
255917
256265
  async function commitRollMetadataRepo(projectCwd, message) {
255918
- const rollDir = join87(projectCwd, ".roll");
255919
- if (!existsSync82(rollDir))
256266
+ const rollDir = join88(projectCwd, ".roll");
256267
+ if (!existsSync83(rollDir))
255920
256268
  return { committed: false, pushed: false, nothingToCommit: true };
255921
256269
  const top = await git(["rev-parse", "--show-toplevel"], rollDir);
255922
256270
  if (top.code !== 0)
@@ -255969,11 +256317,11 @@ async function rebaseRollMetaOntoUpstream(rollDir, branch) {
255969
256317
  }
255970
256318
  var DEPS_BOOTSTRAP_TIMEOUT_MS = 6e5;
255971
256319
  async function bootstrapWorktreeDeps(worktreePath, alertsPath, events, exec = execFileAsync10) {
255972
- if (!existsSync82(join87(worktreePath, "package.json")))
256320
+ if (!existsSync83(join88(worktreePath, "package.json")))
255973
256321
  return true;
255974
- if (existsSync82(join87(worktreePath, "node_modules")))
256322
+ if (existsSync83(join88(worktreePath, "node_modules")))
255975
256323
  return true;
255976
- const plan = existsSync82(join87(worktreePath, "pnpm-lock.yaml")) ? { cmd: "pnpm", args: ["install", "--prefer-offline"] } : existsSync82(join87(worktreePath, "package-lock.json")) ? { cmd: "npm", args: ["ci", "--prefer-offline"] } : void 0;
256324
+ const plan = existsSync83(join88(worktreePath, "pnpm-lock.yaml")) ? { cmd: "pnpm", args: ["install", "--prefer-offline"] } : existsSync83(join88(worktreePath, "package-lock.json")) ? { cmd: "npm", args: ["ci", "--prefer-offline"] } : void 0;
255977
256325
  if (plan === void 0)
255978
256326
  return true;
255979
256327
  try {
@@ -255992,10 +256340,10 @@ async function bootstrapWorktreeDeps(worktreePath, alertsPath, events, exec = ex
255992
256340
  var PREBUILD_TIMEOUT_MS = 6e5;
255993
256341
  function readPrebuildDistEnabled(repoCwd) {
255994
256342
  try {
255995
- const p = join87(repoCwd, ".roll", "policy.yaml");
255996
- if (!existsSync82(p))
256343
+ const p = join88(repoCwd, ".roll", "policy.yaml");
256344
+ if (!existsSync83(p))
255997
256345
  return false;
255998
- return parsePolicy(readFileSync77(p, "utf8")).loopSafety.prebuildDist === true;
256346
+ return parsePolicy(readFileSync78(p, "utf8")).loopSafety.prebuildDist === true;
255999
256347
  } catch {
256000
256348
  return false;
256001
256349
  }
@@ -256003,9 +256351,9 @@ function readPrebuildDistEnabled(repoCwd) {
256003
256351
  async function bootstrapWorktreePrebuild(worktreePath, alertsPath, events, enabled, exec = execFileAsync10) {
256004
256352
  if (!enabled)
256005
256353
  return;
256006
- if (!existsSync82(join87(worktreePath, "package.json")))
256354
+ if (!existsSync83(join88(worktreePath, "package.json")))
256007
256355
  return;
256008
- if (!existsSync82(join87(worktreePath, "pnpm-lock.yaml")))
256356
+ if (!existsSync83(join88(worktreePath, "pnpm-lock.yaml")))
256009
256357
  return;
256010
256358
  try {
256011
256359
  await exec("pnpm", ["-r", "build"], {
@@ -256020,10 +256368,10 @@ async function bootstrapWorktreePrebuild(worktreePath, alertsPath, events, enabl
256020
256368
  }
256021
256369
  function readProjectMapEnabled(repoCwd) {
256022
256370
  try {
256023
- const p = join87(repoCwd, ".roll", "policy.yaml");
256024
- if (!existsSync82(p))
256371
+ const p = join88(repoCwd, ".roll", "policy.yaml");
256372
+ if (!existsSync83(p))
256025
256373
  return false;
256026
- return parsePolicy(readFileSync77(p, "utf8")).loopSafety.projectMap === true;
256374
+ return parsePolicy(readFileSync78(p, "utf8")).loopSafety.projectMap === true;
256027
256375
  } catch {
256028
256376
  return false;
256029
256377
  }
@@ -256081,7 +256429,7 @@ function findRelevantFiles(root, token, limit) {
256081
256429
  scanned += 1;
256082
256430
  const childRel = rel === "" ? ent.name : `${rel}/${ent.name}`;
256083
256431
  if (ent.isDirectory()) {
256084
- walk2(join87(dir, ent.name), childRel);
256432
+ walk2(join88(dir, ent.name), childRel);
256085
256433
  } else if (childRel.toLowerCase().includes(needle)) {
256086
256434
  hits.push(childRel);
256087
256435
  }
@@ -256100,7 +256448,7 @@ function buildProjectMap(worktreePath, storyId) {
256100
256448
  lines2.push(` ${name}`);
256101
256449
  const bare = name.replace(/\/$/, "");
256102
256450
  if (name.endsWith("/") && PROJECT_MAP_CONTAINERS.has(bare)) {
256103
- for (const child of shallowList(join87(worktreePath, bare), PROJECT_MAP_MAX_TOPLEVEL)) {
256451
+ for (const child of shallowList(join88(worktreePath, bare), PROJECT_MAP_MAX_TOPLEVEL)) {
256104
256452
  lines2.push(` ${child}`);
256105
256453
  }
256106
256454
  }
@@ -256168,8 +256516,8 @@ function buildLowScoreFixForwardPrompt(projectPath3, storyId) {
256168
256516
  ].join("\n");
256169
256517
  }
256170
256518
  function skillsEntryCount(worktreePath) {
256171
- const dir = join87(worktreePath, "skills");
256172
- if (!existsSync82(dir))
256519
+ const dir = join88(worktreePath, "skills");
256520
+ if (!existsSync83(dir))
256173
256521
  return 0;
256174
256522
  try {
256175
256523
  return readdirSync34(dir).length;
@@ -256178,7 +256526,7 @@ function skillsEntryCount(worktreePath) {
256178
256526
  }
256179
256527
  }
256180
256528
  async function bootstrapWorktreeSkills(worktreePath, alertsPath, events, submoduleInit) {
256181
- if (!existsSync82(join87(worktreePath, ".gitmodules")))
256529
+ if (!existsSync83(join88(worktreePath, ".gitmodules")))
256182
256530
  return true;
256183
256531
  if (skillsEntryCount(worktreePath) > 0)
256184
256532
  return true;
@@ -256213,14 +256561,14 @@ function nodePorts(opts) {
256213
256561
  },
256214
256562
  readText(absPath) {
256215
256563
  try {
256216
- return readFileSync77(absPath, "utf8");
256564
+ return readFileSync78(absPath, "utf8");
256217
256565
  } catch {
256218
256566
  return "";
256219
256567
  }
256220
256568
  },
256221
256569
  writeText(absPath, text2) {
256222
256570
  mkdirSync37(dirname37(absPath), { recursive: true });
256223
- writeFileSync37(absPath, text2, "utf8");
256571
+ writeFileSync38(absPath, text2, "utf8");
256224
256572
  }
256225
256573
  };
256226
256574
  let deliveredCache;
@@ -256383,10 +256731,10 @@ function nodePorts(opts) {
256383
256731
  },
256384
256732
  backlog: {
256385
256733
  read(projectCwd) {
256386
- const p = join87(projectCwd, ".roll", "backlog.md");
256387
- if (!existsSync82(p))
256734
+ const p = join88(projectCwd, ".roll", "backlog.md");
256735
+ if (!existsSync83(p))
256388
256736
  return [];
256389
- return parseBacklog(readFileSync77(p, "utf8"));
256737
+ return parseBacklog(readFileSync78(p, "utf8"));
256390
256738
  },
256391
256739
  // FIX-198: the production binding was MISSING entirely (the optional
256392
256740
  // chain made every In-Progress claim a silent no-op). ID-anchored mark
@@ -256394,8 +256742,8 @@ function nodePorts(opts) {
256394
256742
  // never kill the cycle, the reconcile pass is the safety net.
256395
256743
  markStatus(projectCwd, id, status2) {
256396
256744
  try {
256397
- const p = join87(projectCwd, ".roll", "backlog.md");
256398
- if (!existsSync82(p))
256745
+ const p = join88(projectCwd, ".roll", "backlog.md");
256746
+ if (!existsSync83(p))
256399
256747
  return;
256400
256748
  const store = new BacklogStore();
256401
256749
  const snap = store.readBacklog(p);
@@ -256412,15 +256760,18 @@ function nodePorts(opts) {
256412
256760
  }
256413
256761
  },
256414
256762
  route: opts.routeDeps ? {
256415
- resolve(_storyId, estMin) {
256763
+ resolve(storyId, estMin) {
256416
256764
  const tier = classifyComplexity(estMin);
256417
- const dec = resolveRoute(tier, opts.routeDeps);
256765
+ const routeDeps = opts.routeDeps;
256766
+ const rt = (process.env["ROLL_PROJECT_RUNTIME_DIR"] ?? "").trim() || join88(opts.repoCwd, ".roll", "loop");
256767
+ const tried = storyId !== "" ? readSelfHeal(rt, storyId).triedAgents : [];
256768
+ const dec = tried.length > 0 ? resolveRouteExcluding(tier, routeDeps, tried) ?? resolveRoute(tier, routeDeps) : resolveRoute(tier, routeDeps);
256418
256769
  return { agent: dec.agent, model: dec.model ?? "" };
256419
256770
  }
256420
256771
  } : { resolve: () => ({ agent: "claude", model: "" }) },
256421
256772
  evidence: {
256422
256773
  openFrame(projectCwd, storyId, runId) {
256423
- return openEvidenceFrame({ runDir: join87(cardArchiveDir(projectCwd, storyId), runId) }).runDir;
256774
+ return openEvidenceFrame({ runDir: join88(cardArchiveDir(projectCwd, storyId), runId) }).runDir;
256424
256775
  }
256425
256776
  },
256426
256777
  capture: {
@@ -256633,10 +256984,39 @@ function describeCommand(cmd) {
256633
256984
  }
256634
256985
  }
256635
256986
 
256987
+ // packages/cli/dist/runner/selfheal-switch.js
256988
+ init_dist2();
256989
+ function maybeSwitchAgent(deps) {
256990
+ if (deps.storyId === "" || deps.failedAgent === "")
256991
+ return false;
256992
+ const read3 = deps.readEntry ?? readSelfHeal;
256993
+ const record = deps.recordAttempt ?? recordSelfHealAttempt;
256994
+ const entry = read3(deps.runtimeDir, deps.storyId);
256995
+ if (entry.attempts >= deps.budget)
256996
+ return false;
256997
+ const tier = classifyComplexity(deps.estMin);
256998
+ const next = resolveRouteExcluding(tier, deps.routeDeps, [...entry.triedAgents, deps.failedAgent]);
256999
+ if (next === null)
257000
+ return false;
257001
+ const updated = record(deps.runtimeDir, deps.storyId, deps.failedAgent, deps.reason);
257002
+ deps.remarkTodo(deps.storyId);
257003
+ deps.emit({
257004
+ type: "agent:retry",
257005
+ cycleId: deps.cycleId,
257006
+ storyId: deps.storyId,
257007
+ fromAgent: deps.failedAgent,
257008
+ toAgent: next.agent,
257009
+ attempt: updated.attempts,
257010
+ reason: deps.reason,
257011
+ ts: deps.now()
257012
+ });
257013
+ return true;
257014
+ }
257015
+
256636
257016
  // packages/cli/dist/runner/binary-staleness.js
256637
257017
  import { execFile as execFile11 } from "node:child_process";
256638
- import { existsSync as existsSync83, mkdirSync as mkdirSync38, readFileSync as readFileSync78, writeFileSync as writeFileSync38 } from "node:fs";
256639
- import { dirname as dirname38, join as join88 } from "node:path";
257018
+ import { existsSync as existsSync84, mkdirSync as mkdirSync38, readFileSync as readFileSync79, writeFileSync as writeFileSync39 } from "node:fs";
257019
+ import { dirname as dirname38, join as join89 } from "node:path";
256640
257020
  import { promisify as promisify11 } from "node:util";
256641
257021
  var execFileAsync11 = promisify11(execFile11);
256642
257022
  var STALE_CHECK_TTL_MS = 24 * 60 * 60 * 1e3;
@@ -256661,9 +257041,9 @@ function isOlderThan(running, latest) {
256661
257041
  }
256662
257042
  function readCache(cachePath, nowMs) {
256663
257043
  try {
256664
- if (!existsSync83(cachePath))
257044
+ if (!existsSync84(cachePath))
256665
257045
  return null;
256666
- const c2 = JSON.parse(readFileSync78(cachePath, "utf8"));
257046
+ const c2 = JSON.parse(readFileSync79(cachePath, "utf8"));
256667
257047
  if (typeof c2.latest !== "string" || typeof c2.fetchedAtMs !== "number")
256668
257048
  return null;
256669
257049
  if (nowMs - c2.fetchedAtMs >= STALE_CHECK_TTL_MS)
@@ -256676,7 +257056,7 @@ function readCache(cachePath, nowMs) {
256676
257056
  function writeCache(cachePath, cache) {
256677
257057
  try {
256678
257058
  mkdirSync38(dirname38(cachePath), { recursive: true });
256679
- writeFileSync38(cachePath, JSON.stringify(cache), "utf8");
257059
+ writeFileSync39(cachePath, JSON.stringify(cache), "utf8");
256680
257060
  } catch {
256681
257061
  }
256682
257062
  }
@@ -256714,7 +257094,7 @@ async function checkBinaryStaleness(deps) {
256714
257094
  async function warnIfBinaryStale(rollHomeDir, runningVersion, appendAlert3) {
256715
257095
  await checkBinaryStaleness({
256716
257096
  runningVersion,
256717
- cachePath: join88(rollHomeDir, ".loop-version-check"),
257097
+ cachePath: join89(rollHomeDir, ".loop-version-check"),
256718
257098
  nowMs: Date.now(),
256719
257099
  fetchLatest: fetchRemoteLatest,
256720
257100
  alert: appendAlert3
@@ -256724,21 +257104,21 @@ async function warnIfBinaryStale(rollHomeDir, runningVersion, appendAlert3) {
256724
257104
  // packages/cli/dist/runner/correction-circuit.js
256725
257105
  init_dist2();
256726
257106
  init_dist();
256727
- import { appendFileSync as appendFileSync17, existsSync as existsSync84, mkdirSync as mkdirSync39, readFileSync as readFileSync79, writeFileSync as writeFileSync39 } from "node:fs";
256728
- import { dirname as dirname39, join as join89 } from "node:path";
257107
+ import { appendFileSync as appendFileSync17, existsSync as existsSync85, mkdirSync as mkdirSync39, readFileSync as readFileSync80, writeFileSync as writeFileSync40 } from "node:fs";
257108
+ import { dirname as dirname39, join as join90 } from "node:path";
256729
257109
  function readLoopSafety(projectPath3) {
256730
257110
  try {
256731
- const path = join89(projectPath3, ".roll", "policy.yaml");
256732
- if (!existsSync84(path))
257111
+ const path = join90(projectPath3, ".roll", "policy.yaml");
257112
+ if (!existsSync85(path))
256733
257113
  return parsePolicy("").loopSafety;
256734
- return parsePolicy(readFileSync79(path, "utf8")).loopSafety;
257114
+ return parsePolicy(readFileSync80(path, "utf8")).loopSafety;
256735
257115
  } catch {
256736
257116
  return parsePolicy("").loopSafety;
256737
257117
  }
256738
257118
  }
256739
257119
  function readEvents3(eventsPath2) {
256740
257120
  try {
256741
- return readFileSync79(eventsPath2, "utf8").split("\n").map(parseEventLine).filter((ev) => ev !== null);
257121
+ return readFileSync80(eventsPath2, "utf8").split("\n").map(parseEventLine).filter((ev) => ev !== null);
256742
257122
  } catch {
256743
257123
  return [];
256744
257124
  }
@@ -256759,8 +257139,8 @@ function applyCorrectionCircuitBreaker(projectPath3, slug2, eventsPath2, alertsP
256759
257139
  return { status: "continue" };
256760
257140
  if (alreadyTripped(events, verdict))
256761
257141
  return { status: "already_tripped", verdict };
256762
- const pauseMarker = join89(projectPath3, ".roll", "loop", `PAUSE-${slug2}`);
256763
- const pauseWritten = !existsSync84(pauseMarker);
257142
+ const pauseMarker = join90(projectPath3, ".roll", "loop", `PAUSE-${slug2}`);
257143
+ const pauseWritten = !existsSync85(pauseMarker);
256764
257144
  const alertMsg = `# ALERT \u2014 correction circuit breaker tripped
256765
257145
 
256766
257146
  **Reason**: ${verdict.reason}
@@ -256772,7 +257152,7 @@ function applyCorrectionCircuitBreaker(projectPath3, slug2, eventsPath2, alertsP
256772
257152
  try {
256773
257153
  mkdirSync39(dirname39(pauseMarker), { recursive: true });
256774
257154
  if (pauseWritten)
256775
- writeFileSync39(pauseMarker, alertMsg, "utf8");
257155
+ writeFileSync40(pauseMarker, alertMsg, "utf8");
256776
257156
  mkdirSync39(dirname39(alertsPath), { recursive: true });
256777
257157
  appendFileSync17(alertsPath, `${alertMsg}
256778
257158
  `, "utf8");
@@ -256795,22 +257175,22 @@ function applyCorrectionCircuitBreaker(projectPath3, slug2, eventsPath2, alertsP
256795
257175
  // packages/cli/dist/lib/morning-report.js
256796
257176
  init_dist2();
256797
257177
  init_dist();
256798
- import { appendFileSync as appendFileSync18, existsSync as existsSync85, mkdirSync as mkdirSync40, readFileSync as readFileSync80, writeFileSync as writeFileSync40 } from "node:fs";
256799
- import { dirname as dirname40, join as join90 } from "node:path";
257178
+ import { appendFileSync as appendFileSync18, existsSync as existsSync86, mkdirSync as mkdirSync40, readFileSync as readFileSync81, writeFileSync as writeFileSync41 } from "node:fs";
257179
+ import { dirname as dirname40, join as join91 } from "node:path";
256800
257180
  var esc7 = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
256801
257181
  function iso3(sec) {
256802
257182
  return new Date(sec * 1e3).toISOString().replace(/\.\d{3}Z$/, "Z");
256803
257183
  }
256804
257184
  function readEvents4(path) {
256805
257185
  try {
256806
- return readFileSync80(path, "utf8").split("\n").map(parseEventLine).filter((ev) => ev !== null);
257186
+ return readFileSync81(path, "utf8").split("\n").map(parseEventLine).filter((ev) => ev !== null);
256807
257187
  } catch {
256808
257188
  return [];
256809
257189
  }
256810
257190
  }
256811
257191
  function readRuns(path) {
256812
257192
  try {
256813
- const all = readFileSync80(path, "utf8").split("\n").map((line) => line.trim()).filter((line) => line !== "").map((line) => JSON.parse(line));
257193
+ const all = readFileSync81(path, "utf8").split("\n").map((line) => line.trim()).filter((line) => line !== "").map((line) => JSON.parse(line));
256814
257194
  const lastWins = /* @__PURE__ */ new Map();
256815
257195
  const unkeyed = [];
256816
257196
  for (const row2 of all) {
@@ -256866,13 +257246,13 @@ function writeLatestMorningReport(projectPath3, eventsPath2, runsPath3, nowSec2
256866
257246
  windowEnd,
256867
257247
  runDelivered: (row2, now) => rowDelivered(row2, now)
256868
257248
  });
256869
- const dir = join90(projectPath3, ".roll", "reports", "morning");
256870
- const latest = join90(dir, "latest.html");
256871
- const dated = join90(dir, `${new Date(nowSec2 * 1e3).toISOString().slice(0, 10)}.html`);
257249
+ const dir = join91(projectPath3, ".roll", "reports", "morning");
257250
+ const latest = join91(dir, "latest.html");
257251
+ const dated = join91(dir, `${new Date(nowSec2 * 1e3).toISOString().slice(0, 10)}.html`);
256872
257252
  mkdirSync40(dir, { recursive: true });
256873
257253
  const html = renderMorningReportHtml(model);
256874
- writeFileSync40(latest, html, "utf8");
256875
- writeFileSync40(dated, html, "utf8");
257254
+ writeFileSync41(latest, html, "utf8");
257255
+ writeFileSync41(dated, html, "utf8");
256876
257256
  try {
256877
257257
  mkdirSync40(dirname40(eventsPath2), { recursive: true });
256878
257258
  appendFileSync18(eventsPath2, `${JSON.stringify({
@@ -256903,20 +257283,20 @@ function announceReport(projectPath3, slug2, storyId, opener = (p) => {
256903
257283
  }) {
256904
257284
  if (storyId === "")
256905
257285
  return null;
256906
- const report = join91(cardArchiveDir(projectPath3, storyId), "latest", reportFileName(storyId));
256907
- if (!existsSync86(report))
257286
+ const report = join92(cardArchiveDir(projectPath3, storyId), "latest", reportFileName(storyId));
257287
+ if (!existsSync87(report))
256908
257288
  return null;
256909
257289
  process.stdout.write(`evidence: ${report}
256910
257290
  \u9A8C\u6536\u62A5\u544A: ${report}
256911
257291
  `);
256912
- const muted = existsSync86(join91(projectPath3, ".roll", "loop", `mute-${slug2}`)) || existsSync86(join91(process.env["ROLL_SHARED_ROOT"] || join91(process.env["HOME"] ?? "", ".shared", "roll"), "loop", `mute-${slug2}`));
257292
+ const muted = existsSync87(join92(projectPath3, ".roll", "loop", `mute-${slug2}`)) || existsSync87(join92(process.env["ROLL_SHARED_ROOT"] || join92(process.env["HOME"] ?? "", ".shared", "roll"), "loop", `mute-${slug2}`));
256913
257293
  if (!muted)
256914
257294
  opener(report);
256915
257295
  return report;
256916
257296
  }
256917
257297
  function resetLiveLog(runtimeDirPath, cycleId) {
256918
257298
  try {
256919
- writeFileSync41(join91(runtimeDirPath, "live.log"), `=== cycle ${cycleId} ===
257299
+ writeFileSync42(join92(runtimeDirPath, "live.log"), `=== cycle ${cycleId} ===
256920
257300
  `, "utf8");
256921
257301
  } catch {
256922
257302
  }
@@ -256933,7 +257313,7 @@ function cycleSignalTeardown(paths, cycleId, branch, sig, deps = {}) {
256933
257313
  }
256934
257314
  let owned = false;
256935
257315
  try {
256936
- owned = existsSync86(paths.lockPath) && readLockOwner(paths.lockPath)?.pid === pid;
257316
+ owned = existsSync87(paths.lockPath) && readLockOwner(paths.lockPath)?.pid === pid;
256937
257317
  } catch {
256938
257318
  owned = false;
256939
257319
  }
@@ -257010,7 +257390,7 @@ function makeCycleId(now = /* @__PURE__ */ new Date(), pid = process.pid) {
257010
257390
  }
257011
257391
  function runtimeDir8(projectPath3) {
257012
257392
  const env = (process.env["ROLL_PROJECT_RUNTIME_DIR"] ?? "").trim();
257013
- return env !== "" ? env : join91(projectPath3, ".roll", "loop");
257393
+ return env !== "" ? env : join92(projectPath3, ".roll", "loop");
257014
257394
  }
257015
257395
  var PAUSE_THRESHOLD = 3;
257016
257396
  var CARD_SKIP_THRESHOLD = 3;
@@ -257041,24 +257421,24 @@ function writeCardSkipAlert(alertsPath, eventsPath2, cycleId, storyId, count) {
257041
257421
  }
257042
257422
  function incrementConsecutiveFails(projectPath3, slug2, alertsPath, eventsPath2, cycleId, storyId, terminal) {
257043
257423
  const rt = runtimeDir8(projectPath3);
257044
- const counterFile = join91(rt, "consecutive-fails");
257424
+ const counterFile = join92(rt, "consecutive-fails");
257045
257425
  let count = 0;
257046
257426
  try {
257047
- if (existsSync86(counterFile)) {
257048
- count = parseInt(readFileSync81(counterFile, "utf8").trim(), 10) || 0;
257427
+ if (existsSync87(counterFile)) {
257428
+ count = parseInt(readFileSync82(counterFile, "utf8").trim(), 10) || 0;
257049
257429
  }
257050
257430
  } catch {
257051
257431
  }
257052
257432
  count += 1;
257053
257433
  try {
257054
- writeFileSync41(counterFile, String(count), "utf8");
257434
+ writeFileSync42(counterFile, String(count), "utf8");
257055
257435
  } catch {
257056
257436
  }
257057
257437
  const threshold = readFailurePauseThreshold(projectPath3);
257058
257438
  if (count < threshold)
257059
257439
  return;
257060
- const pauseMarker = join91(projectPath3, ".roll", "loop", `PAUSE-${slug2}`);
257061
- if (existsSync86(pauseMarker))
257440
+ const pauseMarker = join92(projectPath3, ".roll", "loop", `PAUSE-${slug2}`);
257441
+ if (existsSync87(pauseMarker))
257062
257442
  return;
257063
257443
  const alertMsg = `# ALERT \u2014 loop auto-paused after ${count} consecutive failures
257064
257444
 
@@ -257069,7 +257449,7 @@ function incrementConsecutiveFails(projectPath3, slug2, alertsPath, eventsPath2,
257069
257449
  Resolve the root cause, then: \`roll loop resume\`
257070
257450
  `;
257071
257451
  try {
257072
- writeFileSync41(pauseMarker, alertMsg, "utf8");
257452
+ writeFileSync42(pauseMarker, alertMsg, "utf8");
257073
257453
  appendFileSync19(alertsPath, `${alertMsg}
257074
257454
  `, "utf8");
257075
257455
  const ts2 = Date.now();
@@ -257094,10 +257474,10 @@ loop run-once: \u8FDE\u7EED ${count} \u6B21\u5931\u8D25\u540E\u81EA\u52A8\u6682\
257094
257474
  }
257095
257475
  function readFailurePauseThreshold(projectPath3) {
257096
257476
  try {
257097
- const policy = join91(projectPath3, ".roll", "policy.yaml");
257098
- if (!existsSync86(policy))
257477
+ const policy = join92(projectPath3, ".roll", "policy.yaml");
257478
+ if (!existsSync87(policy))
257099
257479
  return PAUSE_THRESHOLD;
257100
- return parsePolicy(readFileSync81(policy, "utf8")).loopSafety.maxConsecutiveFailures;
257480
+ return parsePolicy(readFileSync82(policy, "utf8")).loopSafety.maxConsecutiveFailures;
257101
257481
  } catch {
257102
257482
  return PAUSE_THRESHOLD;
257103
257483
  }
@@ -257105,25 +257485,34 @@ function readFailurePauseThreshold(projectPath3) {
257105
257485
  function resetConsecutiveFails(projectPath3) {
257106
257486
  const rt = runtimeDir8(projectPath3);
257107
257487
  try {
257108
- writeFileSync41(join91(rt, "consecutive-fails"), "0", "utf8");
257488
+ writeFileSync42(join92(rt, "consecutive-fails"), "0", "utf8");
257489
+ } catch {
257490
+ }
257491
+ }
257492
+ async function autoSplitOnExhaustion(storyId, failCount) {
257493
+ process.stdout.write(`loop run-once: ${storyId} \u2014 agents exhausted (${failCount} failed cycles) \u2192 auto-split (FIX-931)
257494
+ loop run-once: ${storyId} \u2014 \u4EE3\u7406\u5168\u90E8\u8017\u5C3D(${failCount} \u6B21\u5931\u8D25)\u2192 \u81EA\u52A8\u62C6\u5361(FIX-931)
257495
+ `);
257496
+ try {
257497
+ await loopExhaustionSplitCommand([storyId, `${failCount} failed cycles`]);
257109
257498
  } catch {
257110
257499
  }
257111
257500
  }
257112
257501
  function idleCounterPath(projectPath3, slug2) {
257113
- return join91(runtimeDir8(projectPath3), `consecutive-idle-${slug2}`);
257502
+ return join92(runtimeDir8(projectPath3), `consecutive-idle-${slug2}`);
257114
257503
  }
257115
257504
  function incrementConsecutiveIdle(projectPath3, slug2) {
257116
257505
  const file = idleCounterPath(projectPath3, slug2);
257117
257506
  let count = 0;
257118
257507
  try {
257119
- if (existsSync86(file)) {
257120
- count = parseInt(readFileSync81(file, "utf8").trim(), 10) || 0;
257508
+ if (existsSync87(file)) {
257509
+ count = parseInt(readFileSync82(file, "utf8").trim(), 10) || 0;
257121
257510
  }
257122
257511
  } catch {
257123
257512
  }
257124
257513
  count += 1;
257125
257514
  try {
257126
- writeFileSync41(file, String(count), "utf8");
257515
+ writeFileSync42(file, String(count), "utf8");
257127
257516
  } catch {
257128
257517
  }
257129
257518
  return count;
@@ -257131,7 +257520,7 @@ function incrementConsecutiveIdle(projectPath3, slug2) {
257131
257520
  function resetConsecutiveIdle(projectPath3, slug2) {
257132
257521
  const file = idleCounterPath(projectPath3, slug2);
257133
257522
  try {
257134
- writeFileSync41(file, "0", "utf8");
257523
+ writeFileSync42(file, "0", "utf8");
257135
257524
  } catch {
257136
257525
  }
257137
257526
  }
@@ -257181,9 +257570,9 @@ function readExternalBlock(eventsPath2, cycleId) {
257181
257570
  const authDetails = [];
257182
257571
  const networkDetails = [];
257183
257572
  try {
257184
- if (!existsSync86(eventsPath2))
257573
+ if (!existsSync87(eventsPath2))
257185
257574
  return null;
257186
- for (const line of readFileSync81(eventsPath2, "utf8").split("\n")) {
257575
+ for (const line of readFileSync82(eventsPath2, "utf8").split("\n")) {
257187
257576
  if (line.trim() === "" || !line.includes("agent:blocked"))
257188
257577
  continue;
257189
257578
  let e;
@@ -257239,10 +257628,10 @@ function writeReviewerBlockedAlert(projectPath3, slug2, alertsPath, eventsPath2,
257239
257628
  } catch {
257240
257629
  }
257241
257630
  if (block.cause === "auth") {
257242
- const pauseMarker = join91(projectPath3, ".roll", "loop", `PAUSE-${slug2}`);
257243
- if (!existsSync86(pauseMarker)) {
257631
+ const pauseMarker = join92(projectPath3, ".roll", "loop", `PAUSE-${slug2}`);
257632
+ if (!existsSync87(pauseMarker)) {
257244
257633
  try {
257245
- writeFileSync41(pauseMarker, msg6, "utf8");
257634
+ writeFileSync42(pauseMarker, msg6, "utf8");
257246
257635
  bus.appendEvent(eventsPath2, { type: "policy:safety_pause", loop: "ci", reason: `agent auth block: ${agents}`, ts: ts2 });
257247
257636
  } catch {
257248
257637
  }
@@ -257259,15 +257648,15 @@ function readSkillBody2(projectPath3) {
257259
257648
  }
257260
257649
  function buildLoopRouteDeps(projectPath3) {
257261
257650
  function readSlot(slot) {
257262
- const agentsYaml = join91(projectPath3, ".roll", "agents.yaml");
257651
+ const agentsYaml = join92(projectPath3, ".roll", "agents.yaml");
257263
257652
  try {
257264
- return readSlotFromText(readFileSync81(agentsYaml, "utf8"), slot);
257653
+ return readSlotFromText(readFileSync82(agentsYaml, "utf8"), slot);
257265
257654
  } catch {
257266
257655
  return void 0;
257267
257656
  }
257268
257657
  }
257269
257658
  function firstInstalled() {
257270
- const fromLocal = readField(join91(projectPath3, ".roll", "local.yaml"), /^agent:/);
257659
+ const fromLocal = readField(join92(projectPath3, ".roll", "local.yaml"), /^agent:/);
257271
257660
  if (fromLocal !== void 0)
257272
257661
  return fromLocal;
257273
257662
  return firstInstalledAgent(realAgentEnv());
@@ -257276,7 +257665,7 @@ function buildLoopRouteDeps(projectPath3) {
257276
257665
  }
257277
257666
  function readField(path, re) {
257278
257667
  try {
257279
- const text2 = readFileSync81(path, "utf8");
257668
+ const text2 = readFileSync82(path, "utf8");
257280
257669
  for (const line of text2.split("\n")) {
257281
257670
  const m7 = line.match(re);
257282
257671
  if (m7 !== null) {
@@ -257318,15 +257707,15 @@ async function loopRunOnceCommand(args) {
257318
257707
  return 0;
257319
257708
  }
257320
257709
  const rt = runtimeDir8(id.path);
257321
- const alertsPath = join91(rt, `ALERT-${id.slug}.md`);
257710
+ const alertsPath = join92(rt, `ALERT-${id.slug}.md`);
257322
257711
  mkdirSync41(dirname41(alertsPath), { recursive: true });
257323
257712
  const paths = {
257324
- eventsPath: join91(rt, "events.ndjson"),
257325
- runsPath: join91(rt, "runs.jsonl"),
257713
+ eventsPath: join92(rt, "events.ndjson"),
257714
+ runsPath: join92(rt, "runs.jsonl"),
257326
257715
  alertsPath,
257327
- lockPath: join91(rt, "inner.lock"),
257328
- heartbeatPath: join91(rt, "heartbeat"),
257329
- worktreePath: join91(rt, "worktrees", `cycle-${cycleId}`)
257716
+ lockPath: join92(rt, "inner.lock"),
257717
+ heartbeatPath: join92(rt, "heartbeat"),
257718
+ worktreePath: join92(rt, "worktrees", `cycle-${cycleId}`)
257330
257719
  };
257331
257720
  {
257332
257721
  const lang9 = resolveLang({
@@ -257368,7 +257757,7 @@ async function loopRunOnceCommand(args) {
257368
257757
  process.stderr.write(`loop run-once: roll-loop SKILL.md not found \u2014 refusing to spawn a blind agent (ALERT written)
257369
257758
  loop run-once: \u627E\u4E0D\u5230 roll-loop SKILL.md \u2014 \u62D2\u7EDD\u76F2\u5F00 agent(\u5DF2\u5199 ALERT)
257370
257759
  `);
257371
- incrementConsecutiveFails(id.path, id.slug, alertsPath, join91(rt, "events.ndjson"), cycleId, "", "skill_missing");
257760
+ incrementConsecutiveFails(id.path, id.slug, alertsPath, join92(rt, "events.ndjson"), cycleId, "", "skill_missing");
257372
257761
  return 1;
257373
257762
  }
257374
257763
  const routeDeps = buildLoopRouteDeps(id.path);
@@ -257436,6 +257825,7 @@ loop run-once: \u8BC4\u5BA1\u5224\u5B9A ${resizeStory} \u8303\u56F4\u8FC7\u5927(
257436
257825
  resetConsecutiveFails(id.path);
257437
257826
  resetConsecutiveIdle(id.path, id.slug);
257438
257827
  clearCardFailure(runtimeDir8(id.path), storyId);
257828
+ clearSelfHeal(runtimeDir8(id.path), storyId);
257439
257829
  }
257440
257830
  if (result.terminal === "published") {
257441
257831
  process.stdout.write("loop run-once: delivery published \u2014 PR open, merge pending (PR loop merges; backfill credits on merge evidence)\nloop run-once: \u4EA4\u4ED8\u5DF2\u53D1\u5E03\u2014\u2014PR \u5DF2\u5F00,\u7B49\u5F85\u5408\u5E76(PR loop \u8D1F\u8D23\u5408\u5E76;\u5408\u5E76\u8BC1\u636E\u843D\u5730\u540E\u7531\u56DE\u586B\u8BB0\u8D26)\n");
@@ -257446,6 +257836,7 @@ loop run-once: \u8BC4\u5BA1\u5224\u5B9A ${resizeStory} \u8303\u56F4\u8FC7\u5927(
257446
257836
  resetConsecutiveFails(id.path);
257447
257837
  resetConsecutiveIdle(id.path, id.slug);
257448
257838
  clearCardFailure(runtimeDir8(id.path), storyId);
257839
+ clearSelfHeal(runtimeDir8(id.path), storyId);
257449
257840
  process.stdout.write("loop run-once: gates passed but publish did not complete \u2014 work committed locally on the branch, not published (unpublished, not a failure)\nloop run-once: \u95F8\u5DF2\u901A\u8FC7\u4F46\u672A\u5B8C\u6210\u53D1\u5E03\u2014\u2014\u5DE5\u4F5C\u5DF2\u5728\u5206\u652F\u4E0A\u672C\u5730\u63D0\u4EA4,\u5C1A\u672A\u53D1\u5E03(\u672A\u53D1\u5E03,\u975E\u5931\u8D25)\n");
257450
257841
  }
257451
257842
  if (result.terminal === "idle") {
@@ -257453,13 +257844,13 @@ loop run-once: \u8BC4\u5BA1\u5224\u5B9A ${resizeStory} \u8303\u56F4\u8FC7\u5927(
257453
257844
  const idleCount = incrementConsecutiveIdle(id.path, id.slug);
257454
257845
  try {
257455
257846
  const bus = new EventBus();
257456
- const backlogFile = join91(id.path, ".roll", "backlog.md");
257847
+ const backlogFile = join92(id.path, ".roll", "backlog.md");
257457
257848
  const nowSec2 = Math.floor(Date.now() / 1e3);
257458
257849
  const outcome = await maybeEnterDormancy({
257459
257850
  slug: id.slug,
257460
257851
  count: idleCount,
257461
257852
  resolveState: () => resolveLoopRunState(id.path, id.slug),
257462
- readBacklog: () => existsSync86(backlogFile) ? readFileSync81(backlogFile, "utf8") : "",
257853
+ readBacklog: () => existsSync87(backlogFile) ? readFileSync82(backlogFile, "utf8") : "",
257463
257854
  scheduler: createScheduler(process.platform, { uid: process.getuid?.() ?? 0 }),
257464
257855
  loopLabel: launchdLabel("loop", id.slug),
257465
257856
  now: () => (/* @__PURE__ */ new Date()).toISOString(),
@@ -257467,9 +257858,9 @@ loop run-once: \u8BC4\u5BA1\u5224\u5B9A ${resizeStory} \u8303\u56F4\u8FC7\u5927(
257467
257858
  writeDormant: (body) => writeDormantMarker(dormantMarkerPath(id.path, id.slug), body),
257468
257859
  upsertDormantRun: () => bus.upsertRun(paths.runsPath, { storyId: "", cycleId }, buildRunRow({ kind: "append_run", status: "dormant", outcome: mapV2Status("dormant"), cycleId }, { cycleId, branch, loop: "ci" }, nowSec2)),
257469
257860
  writePause: (reason) => {
257470
- const p = join91(id.path, ".roll", "loop", `PAUSE-${id.slug}`);
257861
+ const p = join92(id.path, ".roll", "loop", `PAUSE-${id.slug}`);
257471
257862
  mkdirSync41(dirname41(p), { recursive: true });
257472
- writeFileSync41(p, `# loop paused \u2014 dormancy bootout failed
257863
+ writeFileSync42(p, `# loop paused \u2014 dormancy bootout failed
257473
257864
 
257474
257865
  ${reason}
257475
257866
  `, "utf8");
@@ -257491,6 +257882,54 @@ loop run-once: cycle ${cycleId} \u2192 ${externalBlock.cause}_blocked(\u53EF\u60
257491
257882
  writeReviewerBlockedAlert(id.path, id.slug, alertsPath, paths.eventsPath, cycleId, externalBlock);
257492
257883
  return externalBlock.cause === "auth" ? 0 : isFail ? 1 : 0;
257493
257884
  }
257885
+ {
257886
+ const sid = (result.state?.ctx?.storyId ?? "").trim();
257887
+ const tcr = result.state?.ctx?.tcrCount ?? 0;
257888
+ const failedAgent = (result.state?.ctx?.agent ?? "").trim();
257889
+ const zeroTcr = tcr === 0 && (result.terminal === "gave_up" || result.terminal === "blocked");
257890
+ if (sid !== "" && failedAgent !== "" && zeroTcr) {
257891
+ const backlogFile = join92(id.path, ".roll", "backlog.md");
257892
+ const bus = new EventBus();
257893
+ const swapped = autoRecoverEnabled() ? maybeSwitchAgent({
257894
+ runtimeDir: runtimeDir8(id.path),
257895
+ storyId: sid,
257896
+ failedAgent,
257897
+ reason: result.terminal === "blocked" ? "stall" : "zero-tcr",
257898
+ estMin: parseEstMin(readBacklogRow(id.path, sid).description ?? ""),
257899
+ routeDeps,
257900
+ budget: selfHealBudget(),
257901
+ cycleId,
257902
+ now: () => Math.floor(Date.now() / 1e3),
257903
+ emit: (ev) => bus.appendEvent(paths.eventsPath, ev),
257904
+ remarkTodo: (storyId) => {
257905
+ try {
257906
+ const content = readFileSync82(backlogFile, "utf8");
257907
+ const r = markStatus(content, storyId, STATUS_MARKER.todo);
257908
+ if (r.count > 0)
257909
+ writeFileSync42(backlogFile, r.content, "utf8");
257910
+ } catch {
257911
+ }
257912
+ }
257913
+ }) : false;
257914
+ if (swapped) {
257915
+ resetConsecutiveIdle(id.path, id.slug);
257916
+ process.stdout.write(`loop run-once: zero-TCR on ${sid} (${failedAgent}) \u2014 auto-switching agent next cycle (self-heal)
257917
+ loop run-once: ${sid} \u96F6\u4EA7\u51FA(${failedAgent})\u2014\u2014\u4E0B\u4E00\u5468\u671F\u81EA\u52A8\u6362\u4EE3\u7406(\u81EA\u6108)
257918
+ `);
257919
+ return 0;
257920
+ }
257921
+ if (result.terminal === "gave_up") {
257922
+ const card = recordCardFailure(runtimeDir8(id.path), sid, CARD_SKIP_THRESHOLD);
257923
+ if (card.nowSkipped) {
257924
+ writeCardSkipAlert(alertsPath, paths.eventsPath, cycleId, sid, card.count);
257925
+ resetConsecutiveFails(id.path);
257926
+ clearSelfHeal(runtimeDir8(id.path), sid);
257927
+ if (autoRecoverEnabled())
257928
+ await autoSplitOnExhaustion(sid, card.count);
257929
+ }
257930
+ }
257931
+ }
257932
+ }
257494
257933
  if (isFail) {
257495
257934
  resetConsecutiveIdle(id.path, id.slug);
257496
257935
  if (await isOffline()) {
@@ -257508,6 +257947,10 @@ loop run-once: cycle ${cycleId} \u2192 ${externalBlock.cause}_blocked(\u53EF\u60
257508
257947
  if (card.nowSkipped) {
257509
257948
  writeCardSkipAlert(alertsPath, paths.eventsPath, cycleId, storyId, card.count);
257510
257949
  resetConsecutiveFails(id.path);
257950
+ if (result.terminal === "blocked" && autoRecoverEnabled()) {
257951
+ clearSelfHeal(runtimeDir8(id.path), storyId);
257952
+ await autoSplitOnExhaustion(storyId, card.count);
257953
+ }
257511
257954
  } else {
257512
257955
  incrementConsecutiveFails(id.path, id.slug, alertsPath, paths.eventsPath, cycleId, storyId, result.terminal ?? "unknown");
257513
257956
  }
@@ -257573,9 +258016,9 @@ async function isOffline(resolve9 = (h) => lookup2(h)) {
257573
258016
  // packages/cli/dist/commands/offboard.js
257574
258017
  init_dist();
257575
258018
  import { spawnSync as spawnSync10 } from "node:child_process";
257576
- import { existsSync as existsSync87, readFileSync as readFileSync82, realpathSync as realpathSync10, rmSync as rmSync16, writeFileSync as writeFileSync42 } from "node:fs";
258019
+ import { existsSync as existsSync88, readFileSync as readFileSync83, realpathSync as realpathSync10, rmSync as rmSync16, writeFileSync as writeFileSync43 } from "node:fs";
257577
258020
  import { homedir as homedir23 } from "node:os";
257578
- import { join as join92, resolve as resolve7 } from "node:path";
258021
+ import { join as join93, resolve as resolve7 } from "node:path";
257579
258022
  function pal5() {
257580
258023
  const noColor2 = (process.env["NO_COLOR"] ?? "") !== "";
257581
258024
  return noColor2 ? { RED: "", GREEN: "", YELLOW: "", CYAN: "", BOLD: "", NC: "" } : {
@@ -257613,7 +258056,7 @@ function m4(key, ...args) {
257613
258056
  return t(v2Catalog, msgLang7(), key, ...args);
257614
258057
  }
257615
258058
  function changesetPath2(projectDir) {
257616
- return join92(projectDir, ".roll", "onboard-changeset.yaml");
258059
+ return join93(projectDir, ".roll", "onboard-changeset.yaml");
257617
258060
  }
257618
258061
  function loopInCycle2() {
257619
258062
  return (process.env["ROLL_LOOP_AGENT"] ?? "") !== "" || (process.env["ROLL_CYCLE_LOG_RAW"] ?? "") !== "";
@@ -257623,7 +258066,7 @@ function runLaunchctl(args) {
257623
258066
  if (args[0] !== void 0 && readOnly.has(args[0])) {
257624
258067
  return spawnSync10("launchctl", args, { stdio: "inherit" }).status ?? 1;
257625
258068
  }
257626
- const canonical = join92(homedir23(), "Library", "LaunchAgents");
258069
+ const canonical = join93(homedir23(), "Library", "LaunchAgents");
257627
258070
  const launchdDir = process.env["_LAUNCHD_DIR"] ?? canonical;
257628
258071
  if (launchdDir !== canonical)
257629
258072
  return 0;
@@ -257687,7 +258130,7 @@ function offboardCommand(args) {
257687
258130
  projectDir = process.cwd();
257688
258131
  }
257689
258132
  const changeset = changesetPath2(projectDir);
257690
- if (!existsSync87(changeset)) {
258133
+ if (!existsSync88(changeset)) {
257691
258134
  err10(m4("offboard.no_changeset_en"));
257692
258135
  err10(m4("offboard.no_changeset_zh"));
257693
258136
  process.stderr.write("\n");
@@ -257701,7 +258144,7 @@ function offboardCommand(args) {
257701
258144
  `);
257702
258145
  return 1;
257703
258146
  }
257704
- const parsed = parseChangeset(readFileSync82(changeset, "utf8"));
258147
+ const parsed = parseChangeset(readFileSync83(changeset, "utf8"));
257705
258148
  if (!parsed.ok) {
257706
258149
  err10(m4("offboard.failed_to_parse_changeset"));
257707
258150
  return 1;
@@ -257777,8 +258220,8 @@ function offboardCommand(args) {
257777
258220
  process.stdout.write(m4("offboard.applying_offboard") + "\n");
257778
258221
  for (const item of files) {
257779
258222
  try {
257780
- rmSync16(join92(projectDir, item), { force: true });
257781
- if (!existsSync87(join92(projectDir, item)))
258223
+ rmSync16(join93(projectDir, item), { force: true });
258224
+ if (!existsSync88(join93(projectDir, item)))
257782
258225
  process.stdout.write(` removed file ${item}
257783
258226
  `);
257784
258227
  } catch {
@@ -257786,26 +258229,26 @@ function offboardCommand(args) {
257786
258229
  }
257787
258230
  for (const item of dirs) {
257788
258231
  try {
257789
- rmSync16(join92(projectDir, item), { recursive: true, force: true });
258232
+ rmSync16(join93(projectDir, item), { recursive: true, force: true });
257790
258233
  process.stdout.write(` removed dir ${item}
257791
258234
  `);
257792
258235
  } catch {
257793
258236
  }
257794
258237
  }
257795
258238
  for (const item of giEntries) {
257796
- const gi = join92(projectDir, ".gitignore");
257797
- if (existsSync87(gi)) {
257798
- const lines2 = readFileSync82(gi, "utf8").split("\n");
258239
+ const gi = join93(projectDir, ".gitignore");
258240
+ if (existsSync88(gi)) {
258241
+ const lines2 = readFileSync83(gi, "utf8").split("\n");
257799
258242
  if (lines2.includes(item)) {
257800
258243
  const kept = lines2.filter((l) => l !== item);
257801
- writeFileSync42(gi, kept.join("\n"));
258244
+ writeFileSync43(gi, kept.join("\n"));
257802
258245
  process.stdout.write(` .gitignore - ${item}
257803
258246
  `);
257804
258247
  }
257805
258248
  }
257806
258249
  }
257807
258250
  for (const item of plists) {
257808
- const plistPath = join92(homedir23(), "Library", "LaunchAgents", item);
258251
+ const plistPath = join93(homedir23(), "Library", "LaunchAgents", item);
257809
258252
  const r = runLaunchctl(["unload", "-w", plistPath]);
257810
258253
  if (r === 0)
257811
258254
  process.stdout.write(` unloaded ${item}
@@ -257819,13 +258262,13 @@ function offboardCommand(args) {
257819
258262
 
257820
258263
  // packages/cli/dist/commands/prices.js
257821
258264
  init_dist();
257822
- import { existsSync as existsSync89, readdirSync as readdirSync36, readFileSync as readFileSync84 } from "node:fs";
257823
- import { join as join94 } from "node:path";
258265
+ import { existsSync as existsSync90, readdirSync as readdirSync36, readFileSync as readFileSync85 } from "node:fs";
258266
+ import { join as join95 } from "node:path";
257824
258267
 
257825
258268
  // packages/cli/dist/commands/prices-refresh.js
257826
258269
  init_dist();
257827
- import { existsSync as existsSync88, mkdirSync as mkdirSync42, readdirSync as readdirSync35, readFileSync as readFileSync83, writeFileSync as writeFileSync43 } from "node:fs";
257828
- import { join as join93 } from "node:path";
258270
+ import { existsSync as existsSync89, mkdirSync as mkdirSync42, readdirSync as readdirSync35, readFileSync as readFileSync84, writeFileSync as writeFileSync44 } from "node:fs";
258271
+ import { join as join94 } from "node:path";
257829
258272
  var FetchError = class extends Error {
257830
258273
  constructor(message) {
257831
258274
  super(message);
@@ -258046,13 +258489,13 @@ function vendorFromSnapshotName(name) {
258046
258489
  return match[2] ?? "anthropic";
258047
258490
  }
258048
258491
  function latestSnapshotPath(snapshotDir, vendor) {
258049
- if (!existsSync88(snapshotDir))
258492
+ if (!existsSync89(snapshotDir))
258050
258493
  return null;
258051
- const snaps = readdirSync35(snapshotDir).filter((name) => SNAPSHOT_RE.test(name) && vendorFromSnapshotName(name) === vendor).sort().map((name) => join93(snapshotDir, name));
258494
+ const snaps = readdirSync35(snapshotDir).filter((name) => SNAPSHOT_RE.test(name) && vendorFromSnapshotName(name) === vendor).sort().map((name) => join94(snapshotDir, name));
258052
258495
  return snaps[snaps.length - 1] ?? null;
258053
258496
  }
258054
258497
  function readPrices(path) {
258055
- const data = JSON.parse(readFileSync83(path, "utf8"));
258498
+ const data = JSON.parse(readFileSync84(path, "utf8"));
258056
258499
  return data.prices ?? {};
258057
258500
  }
258058
258501
  function diffPrices(oldPrices, newPrices) {
@@ -258145,8 +258588,8 @@ function snapshotJson(payload) {
258145
258588
  function writeSnapshot(input) {
258146
258589
  mkdirSync42(input.snapshotDir, { recursive: true });
258147
258590
  const suffix = input.vendor === "anthropic" ? "" : `-${input.vendor}`;
258148
- const dest = join93(input.snapshotDir, `snapshot-${input.effectiveAt}${suffix}.json`);
258149
- writeFileSync43(dest, snapshotJson({
258591
+ const dest = join94(input.snapshotDir, `snapshot-${input.effectiveAt}${suffix}.json`);
258592
+ writeFileSync44(dest, snapshotJson({
258150
258593
  version: input.effectiveAt,
258151
258594
  effective_at: input.effectiveAt,
258152
258595
  source_url: input.sourceUrl,
@@ -258217,7 +258660,7 @@ async function pricesRefreshCommand(args, deps = {}) {
258217
258660
  } else {
258218
258661
  vendor = "anthropic";
258219
258662
  }
258220
- const snapshotDir = deps.snapshotDir ?? join93(repoRoot2(), "lib", "prices");
258663
+ const snapshotDir = deps.snapshotDir ?? join94(repoRoot2(), "lib", "prices");
258221
258664
  try {
258222
258665
  const result = await refresh({ snapshotDir, vendor, url, deps });
258223
258666
  if (result.action === "unchanged") {
@@ -258254,13 +258697,13 @@ async function pricesRefreshCommand(args, deps = {}) {
258254
258697
 
258255
258698
  // packages/cli/dist/commands/prices.js
258256
258699
  function loadSnapshots() {
258257
- const dir = join94(repoRoot2(), "lib", "prices");
258258
- if (!existsSync89(dir)) {
258700
+ const dir = join95(repoRoot2(), "lib", "prices");
258701
+ if (!existsSync90(dir)) {
258259
258702
  throw new Error(`no price snapshots found in ${dir}; run \`roll prices refresh\``);
258260
258703
  }
258261
258704
  const files = readdirSync36(dir).filter((n) => n.startsWith("snapshot-") && n.endsWith(".json")).sort();
258262
258705
  return files.map((name) => {
258263
- const data = JSON.parse(readFileSync84(join94(dir, name), "utf8"));
258706
+ const data = JSON.parse(readFileSync85(join95(dir, name), "utf8"));
258264
258707
  for (const key of ["version", "effective_at", "source_url", "prices"]) {
258265
258708
  if (data[key] === void 0)
258266
258709
  throw new Error(`snapshot ${name} missing required key ${key}`);
@@ -258439,24 +258882,24 @@ init_dist3();
258439
258882
  init_dist();
258440
258883
  init_render();
258441
258884
  import { execFileSync as execFileSync24 } from "node:child_process";
258442
- import { readFileSync as readFileSync88, writeFileSync as writeFileSync47, existsSync as existsSync93 } from "node:fs";
258443
- import { join as join98 } from "node:path";
258885
+ import { readFileSync as readFileSync89, writeFileSync as writeFileSync48, existsSync as existsSync94 } from "node:fs";
258886
+ import { join as join99 } from "node:path";
258444
258887
 
258445
258888
  // packages/cli/dist/lib/release-consistency.js
258446
258889
  init_dist2();
258447
258890
  init_dist();
258448
258891
  init_render();
258449
258892
  import { execFileSync as execFileSync23 } from "node:child_process";
258450
- import { existsSync as existsSync91, mkdirSync as mkdirSync44, readFileSync as readFileSync86, readdirSync as readdirSync38, statSync as statSync27, writeFileSync as writeFileSync45 } from "node:fs";
258451
- import { dirname as dirname43, join as join96 } from "node:path";
258893
+ import { existsSync as existsSync92, mkdirSync as mkdirSync44, readFileSync as readFileSync87, readdirSync as readdirSync38, statSync as statSync27, writeFileSync as writeFileSync46 } from "node:fs";
258894
+ import { dirname as dirname43, join as join97 } from "node:path";
258452
258895
 
258453
258896
  // packages/cli/dist/lib/consistency-audit.js
258454
258897
  init_dist2();
258455
258898
  init_dist3();
258456
258899
  init_dist();
258457
258900
  import { execFile as execFile12 } from "node:child_process";
258458
- import { existsSync as existsSync90, mkdirSync as mkdirSync43, readFileSync as readFileSync85, readdirSync as readdirSync37, writeFileSync as writeFileSync44 } from "node:fs";
258459
- import { dirname as dirname42, join as join95 } from "node:path";
258901
+ import { existsSync as existsSync91, mkdirSync as mkdirSync43, readFileSync as readFileSync86, readdirSync as readdirSync37, writeFileSync as writeFileSync45 } from "node:fs";
258902
+ import { dirname as dirname42, join as join96 } from "node:path";
258460
258903
  import { promisify as promisify12 } from "node:util";
258461
258904
  init_dist();
258462
258905
  init_dist();
@@ -258464,10 +258907,10 @@ var PROBE_CAP = 20;
258464
258907
  var COUNT_WINDOW_SEC = 72 * 3600;
258465
258908
  var execFileAsync12 = promisify12(execFile12);
258466
258909
  function readJsonl(path) {
258467
- if (!existsSync90(path))
258910
+ if (!existsSync91(path))
258468
258911
  return [];
258469
258912
  const out3 = [];
258470
- for (const line of readFileSync85(path, "utf8").split("\n")) {
258913
+ for (const line of readFileSync86(path, "utf8").split("\n")) {
258471
258914
  if (line.trim() === "")
258472
258915
  continue;
258473
258916
  try {
@@ -258480,10 +258923,10 @@ function readJsonl(path) {
258480
258923
  return out3;
258481
258924
  }
258482
258925
  function readJson(path) {
258483
- if (!existsSync90(path))
258926
+ if (!existsSync91(path))
258484
258927
  return null;
258485
258928
  try {
258486
- const parsed = JSON.parse(readFileSync85(path, "utf8"));
258929
+ const parsed = JSON.parse(readFileSync86(path, "utf8"));
258487
258930
  return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : null;
258488
258931
  } catch {
258489
258932
  return null;
@@ -258491,7 +258934,7 @@ function readJson(path) {
258491
258934
  }
258492
258935
  function hasScreenshotArtifact(reportPath) {
258493
258936
  const runDir = dirname42(reportPath);
258494
- const manifest = readJson(join95(runDir, "evidence.json"));
258937
+ const manifest = readJson(join96(runDir, "evidence.json"));
258495
258938
  if (manifest !== null) {
258496
258939
  const screenshots = manifest["screenshots"];
258497
258940
  if (Array.isArray(screenshots) && screenshots.some((x) => typeof x === "string" && x !== ""))
@@ -258507,8 +258950,8 @@ function hasScreenshotArtifact(reportPath) {
258507
258950
  }
258508
258951
  }
258509
258952
  }
258510
- const dir = join95(runDir, "screenshots");
258511
- if (!existsSync90(dir))
258953
+ const dir = join96(runDir, "screenshots");
258954
+ if (!existsSync91(dir))
258512
258955
  return false;
258513
258956
  try {
258514
258957
  return readdirSync37(dir).some((name) => /\.png$/i.test(name));
@@ -258517,7 +258960,7 @@ function hasScreenshotArtifact(reportPath) {
258517
258960
  }
258518
258961
  }
258519
258962
  function hasMachineCaptureSkip2(reportPath) {
258520
- const manifest = readJson(join95(dirname42(reportPath), "evidence.json"));
258963
+ const manifest = readJson(join96(dirname42(reportPath), "evidence.json"));
258521
258964
  const captures = manifest?.["captures"];
258522
258965
  if (!Array.isArray(captures))
258523
258966
  return false;
@@ -258544,18 +258987,18 @@ async function gatherAuditSnapshot(projectPath3, runtimeDir9, deps = {}) {
258544
258987
  const nowSec2 = deps.nowSec ?? Math.floor(Date.now() / 1e3);
258545
258988
  const snapshot = emptyAuditSnapshot(nowSec2, TERMINAL_SCHEMA_EPOCH_SEC);
258546
258989
  const skipped = [];
258547
- const backlogPath = join95(projectPath3, ".roll", "backlog.md");
258548
- if (existsSync90(backlogPath)) {
258549
- snapshot.backlog = parseBacklog(readFileSync85(backlogPath, "utf8")).map((r) => ({ id: r.id, status: r.status }));
258990
+ const backlogPath = join96(projectPath3, ".roll", "backlog.md");
258991
+ if (existsSync91(backlogPath)) {
258992
+ snapshot.backlog = parseBacklog(readFileSync86(backlogPath, "utf8")).map((r) => ({ id: r.id, status: r.status }));
258550
258993
  }
258551
258994
  snapshot.index = readIndex(projectPath3);
258552
258995
  snapshot.localMainAhead = deps.localMainAhead !== void 0 ? await deps.localMainAhead() : await gitLocalMainAhead(projectPath3);
258553
- snapshot.runs = readJsonl(join95(runtimeDir9, "runs.jsonl"));
258996
+ snapshot.runs = readJsonl(join96(runtimeDir9, "runs.jsonl"));
258554
258997
  let eventFailed = 0;
258555
258998
  const terminal = [];
258556
- const eventsPath2 = join95(runtimeDir9, "events.ndjson");
258557
- if (existsSync90(eventsPath2)) {
258558
- for (const line of readFileSync85(eventsPath2, "utf8").split("\n")) {
258999
+ const eventsPath2 = join96(runtimeDir9, "events.ndjson");
259000
+ if (existsSync91(eventsPath2)) {
259001
+ for (const line of readFileSync86(eventsPath2, "utf8").split("\n")) {
258559
259002
  const e = parseEventLine(line);
258560
259003
  if (e === null)
258561
259004
  continue;
@@ -258577,22 +259020,22 @@ async function gatherAuditSnapshot(projectPath3, runtimeDir9, deps = {}) {
258577
259020
  if (!row2.status.includes("\u2705"))
258578
259021
  continue;
258579
259022
  const card = cardArchiveDir(projectPath3, row2.id);
258580
- if (!existsSync90(card))
259023
+ if (!existsSync91(card))
258581
259024
  continue;
258582
- const reportPath = join95(card, "latest", reportFileName(row2.id));
258583
- const specPath = join95(card, "spec.md");
259025
+ const reportPath = join96(card, "latest", reportFileName(row2.id));
259026
+ const specPath = join96(card, "spec.md");
258584
259027
  let noVisualSurface = false;
258585
- if (existsSync90(specPath)) {
259028
+ if (existsSync91(specPath)) {
258586
259029
  try {
258587
- noVisualSurface = !hasVisualEvidenceAc(readFileSync85(specPath, "utf8"));
259030
+ noVisualSurface = !hasVisualEvidenceAc(readFileSync86(specPath, "utf8"));
258588
259031
  } catch {
258589
259032
  }
258590
259033
  }
258591
259034
  snapshot.attest[row2.id] = {
258592
- report: existsSync90(reportPath),
258593
- acMap: existsSync90(join95(card, "ac-map.json")),
258594
- visualEvidence: existsSync90(reportPath) ? hasScreenshotArtifact(reportPath) : false,
258595
- machineSkip: existsSync90(reportPath) ? hasMachineCaptureSkip2(reportPath) : false,
259035
+ report: existsSync91(reportPath),
259036
+ acMap: existsSync91(join96(card, "ac-map.json")),
259037
+ visualEvidence: existsSync91(reportPath) ? hasScreenshotArtifact(reportPath) : false,
259038
+ machineSkip: existsSync91(reportPath) ? hasMachineCaptureSkip2(reportPath) : false,
258596
259039
  noVisualSurface
258597
259040
  };
258598
259041
  }
@@ -258676,16 +259119,16 @@ async function consistencyAuditCommand(args, deps = {}) {
258676
259119
  const json = args.includes("--json");
258677
259120
  const projectPath3 = process.cwd();
258678
259121
  const rtEnv = (process.env["ROLL_PROJECT_RUNTIME_DIR"] ?? "").trim();
258679
- const runtimeDir9 = rtEnv !== "" ? rtEnv : join95(projectPath3, ".roll", "loop");
259122
+ const runtimeDir9 = rtEnv !== "" ? rtEnv : join96(projectPath3, ".roll", "loop");
258680
259123
  const { snapshot, skipped } = await gatherAuditSnapshot(projectPath3, runtimeDir9, deps);
258681
259124
  const report = runConsistencyAudit(snapshot);
258682
259125
  const nowMs = (deps.nowSec ?? Math.floor(Date.now() / 1e3)) * 1e3;
258683
259126
  const dateTag = new Date(nowMs).toISOString().slice(0, 10);
258684
- const outDir = join95(projectPath3, ".roll", "reports", "consistency");
259127
+ const outDir = join96(projectPath3, ".roll", "reports", "consistency");
258685
259128
  try {
258686
259129
  mkdirSync43(outDir, { recursive: true });
258687
- writeFileSync44(join95(outDir, `${dateTag}.json`), JSON.stringify({ generatedAt: dateTag, ...report, skipped }, null, 1));
258688
- writeFileSync44(join95(outDir, `${dateTag}.md`), renderMarkdown2(report, skipped, dateTag));
259130
+ writeFileSync45(join96(outDir, `${dateTag}.json`), JSON.stringify({ generatedAt: dateTag, ...report, skipped }, null, 1));
259131
+ writeFileSync45(join96(outDir, `${dateTag}.md`), renderMarkdown2(report, skipped, dateTag));
258689
259132
  } catch {
258690
259133
  process.stderr.write("consistency audit: report write failed (scan still completed)\n");
258691
259134
  }
@@ -258693,7 +259136,7 @@ async function consistencyAuditCommand(args, deps = {}) {
258693
259136
  process.stdout.write(JSON.stringify({ ...report, skipped }, null, 1) + "\n");
258694
259137
  } else {
258695
259138
  process.stdout.write(`consistency audit (shadow): fail ${report.summary.fail} \xB7 warn ${report.summary.warn} \xB7 unknown ${report.summary.unknown} \xB7 grandfathered ${report.summary.grandfathered}
258696
- \u4E00\u81F4\u6027\u5BA1\u8BA1(\u5F71\u5B50\u6A21\u5F0F): \u62A5\u544A\u5DF2\u5199\u5165 ${join95(".roll", "reports", "consistency", `${dateTag}.md`)}
259139
+ \u4E00\u81F4\u6027\u5BA1\u8BA1(\u5F71\u5B50\u6A21\u5F0F): \u62A5\u544A\u5DF2\u5199\u5165 ${join96(".roll", "reports", "consistency", `${dateTag}.md`)}
258697
259140
  `);
258698
259141
  for (const f of report.findings.filter((x) => x.severity === "fail").slice(0, 10)) {
258699
259142
  process.stdout.write(` \u2717 ${f.rule} ${f.subject} \u2014 ${f.detail}
@@ -258731,7 +259174,7 @@ function escapeRegExp3(s) {
258731
259174
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
258732
259175
  }
258733
259176
  function readText(p) {
258734
- return readFileSync86(p, "utf8");
259177
+ return readFileSync87(p, "utf8");
258735
259178
  }
258736
259179
  var COMMAND_SURFACE_REPLACEMENTS = /* @__PURE__ */ new Map([
258737
259180
  ["migrate", "npx @seanyao/roll@2 migrate"],
@@ -258749,7 +259192,7 @@ function lineNumberAt(text2, index) {
258749
259192
  return text2.slice(0, index).split("\n").length;
258750
259193
  }
258751
259194
  function existingTextFiles(projectDir, rels) {
258752
- return rels.map((rel) => ({ rel, abs: join96(projectDir, rel) })).filter((f) => {
259195
+ return rels.map((rel) => ({ rel, abs: join97(projectDir, rel) })).filter((f) => {
258753
259196
  try {
258754
259197
  return statSync27(f.abs).isFile();
258755
259198
  } catch {
@@ -258760,7 +259203,7 @@ function existingTextFiles(projectDir, rels) {
258760
259203
  function walkTextFiles(projectDir, relDir, extensions) {
258761
259204
  const out3 = [];
258762
259205
  const walk2 = (dirRel) => {
258763
- const dirAbs = join96(projectDir, dirRel);
259206
+ const dirAbs = join97(projectDir, dirRel);
258764
259207
  let entries;
258765
259208
  try {
258766
259209
  entries = readdirSync38(dirAbs, { withFileTypes: true });
@@ -258768,7 +259211,7 @@ function walkTextFiles(projectDir, relDir, extensions) {
258768
259211
  return;
258769
259212
  }
258770
259213
  for (const entry of entries) {
258771
- const rel = join96(dirRel, entry.name);
259214
+ const rel = join97(dirRel, entry.name);
258772
259215
  if (entry.isDirectory()) {
258773
259216
  walk2(rel);
258774
259217
  continue;
@@ -258776,7 +259219,7 @@ function walkTextFiles(projectDir, relDir, extensions) {
258776
259219
  const dot = entry.name.lastIndexOf(".");
258777
259220
  const ext = dot === -1 ? "" : entry.name.slice(dot);
258778
259221
  if (entry.isFile() && extensions.has(ext))
258779
- out3.push({ rel, abs: join96(projectDir, rel) });
259222
+ out3.push({ rel, abs: join97(projectDir, rel) });
258780
259223
  }
258781
259224
  };
258782
259225
  walk2(relDir);
@@ -258902,14 +259345,14 @@ var nodeFreshnessPort2 = {
258902
259345
  },
258903
259346
  readText(absPath) {
258904
259347
  try {
258905
- return readFileSync86(absPath, "utf8");
259348
+ return readFileSync87(absPath, "utf8");
258906
259349
  } catch {
258907
259350
  return "";
258908
259351
  }
258909
259352
  },
258910
259353
  writeText(absPath, text2) {
258911
259354
  mkdirSync44(dirname43(absPath), { recursive: true });
258912
- writeFileSync45(absPath, text2, "utf8");
259355
+ writeFileSync46(absPath, text2, "utf8");
258913
259356
  }
258914
259357
  };
258915
259358
  var quietExecPort = {
@@ -258946,13 +259389,13 @@ function mergeShasFromStatus(status2) {
258946
259389
  return shas;
258947
259390
  }
258948
259391
  function findCardSpec(projectDir, id) {
258949
- const featuresDir = join96(projectDir, ".roll", "features");
259392
+ const featuresDir = join97(projectDir, ".roll", "features");
258950
259393
  try {
258951
259394
  for (const epic of readdirSync38(featuresDir, { withFileTypes: true })) {
258952
259395
  if (!epic.isDirectory())
258953
259396
  continue;
258954
- const spec = join96(featuresDir, epic.name, id, "spec.md");
258955
- if (existsSync91(spec))
259397
+ const spec = join97(featuresDir, epic.name, id, "spec.md");
259398
+ if (existsSync92(spec))
258956
259399
  return spec;
258957
259400
  }
258958
259401
  } catch {
@@ -258970,13 +259413,13 @@ function cardChangelogExempt(projectDir, id) {
258970
259413
  }
258971
259414
  }
258972
259415
  function checkFeaturesCatalog(projectDir) {
258973
- const backlog = join96(projectDir, ".roll", "backlog.md");
258974
- if (!existsSync91(backlog))
259416
+ const backlog = join97(projectDir, ".roll", "backlog.md");
259417
+ if (!existsSync92(backlog))
258975
259418
  return { status: "pass", gaps: [] };
258976
259419
  const backlogText = readText(backlog);
258977
259420
  const gaps = [];
258978
- const features = join96(projectDir, ".roll", "features.md");
258979
- if (existsSync91(features)) {
259421
+ const features = join97(projectDir, ".roll", "features.md");
259422
+ if (existsSync92(features)) {
258980
259423
  const featuresText = readText(features);
258981
259424
  for (const featName of readDoneFeatures(backlogText).keys()) {
258982
259425
  const escaped = escapeRegExp3(featName);
@@ -258999,8 +259442,8 @@ function checkFeaturesCatalog(projectDir) {
258999
259442
  return { status: gaps.length === 0 ? "pass" : "fail", gaps };
259000
259443
  }
259001
259444
  function checkTruthLive(projectDir) {
259002
- const backlog = join96(projectDir, ".roll", "backlog.md");
259003
- if (!existsSync91(backlog))
259445
+ const backlog = join97(projectDir, ".roll", "backlog.md");
259446
+ if (!existsSync92(backlog))
259004
259447
  return { status: "pass", gaps: [] };
259005
259448
  const backlogText = readText(backlog);
259006
259449
  const facts = backlogRowFacts(backlogText);
@@ -259036,19 +259479,19 @@ function checkTruthLive(projectDir) {
259036
259479
  return { status: gaps.length === 0 ? "pass" : "fail", gaps };
259037
259480
  }
259038
259481
  function checkCards(projectDir) {
259039
- const backlog = join96(projectDir, ".roll", "backlog.md");
259040
- const featuresDir = join96(projectDir, ".roll", "features");
259041
- if (!existsSync91(backlog) || !existsSync91(featuresDir))
259482
+ const backlog = join97(projectDir, ".roll", "backlog.md");
259483
+ const featuresDir = join97(projectDir, ".roll", "features");
259484
+ if (!existsSync92(backlog) || !existsSync92(featuresDir))
259042
259485
  return { status: "pass", gaps: [] };
259043
259486
  const cardEpic = /* @__PURE__ */ new Map();
259044
259487
  try {
259045
259488
  for (const epic of readdirSync38(featuresDir, { withFileTypes: true })) {
259046
259489
  if (!epic.isDirectory())
259047
259490
  continue;
259048
- for (const card of readdirSync38(join96(featuresDir, epic.name), { withFileTypes: true })) {
259491
+ for (const card of readdirSync38(join97(featuresDir, epic.name), { withFileTypes: true })) {
259049
259492
  if (!card.isDirectory())
259050
259493
  continue;
259051
- if (existsSync91(join96(featuresDir, epic.name, card.name, "spec.md")) && !cardEpic.has(card.name)) {
259494
+ if (existsSync92(join97(featuresDir, epic.name, card.name, "spec.md")) && !cardEpic.has(card.name)) {
259052
259495
  cardEpic.set(card.name, epic.name);
259053
259496
  }
259054
259497
  }
@@ -259058,7 +259501,7 @@ function checkCards(projectDir) {
259058
259501
  }
259059
259502
  const hasAcBlock = (epic, id) => {
259060
259503
  try {
259061
- return /\*\*AC:\*\*[\s\S]*?-\s+\[[ xX]\]\s+/.test(readText(join96(featuresDir, epic, id, "spec.md")));
259504
+ return /\*\*AC:\*\*[\s\S]*?-\s+\[[ xX]\]\s+/.test(readText(join97(featuresDir, epic, id, "spec.md")));
259062
259505
  } catch {
259063
259506
  return true;
259064
259507
  }
@@ -259081,12 +259524,12 @@ function checkCards(projectDir) {
259081
259524
  const ev = /\[evidence\]\(([^)]+)\)/.exec(line);
259082
259525
  if (ev !== null) {
259083
259526
  const target = (ev[1] ?? "").replace(/^\.roll\//, "");
259084
- if (!existsSync91(join96(projectDir, ".roll", target))) {
259527
+ if (!existsSync92(join97(projectDir, ".roll", target))) {
259085
259528
  gaps.push(`Backlog row ${id} evidence link is broken: ${ev[1] ?? ""}`);
259086
259529
  }
259087
259530
  } else if (line.includes(STATUS_MARKER.done)) {
259088
259531
  const epic = cardEpic.get(id) ?? "";
259089
- if (!existsSync91(join96(featuresDir, epic, id, "latest", `${id}-report.html`))) {
259532
+ if (!existsSync92(join97(featuresDir, epic, id, "latest", `${id}-report.html`))) {
259090
259533
  if (hasAcBlock(epic, id)) {
259091
259534
  gaps.push(`Done backlog row ${id} has ACs but no attest report`);
259092
259535
  } else {
@@ -259107,8 +259550,8 @@ function checkCards(projectDir) {
259107
259550
  }
259108
259551
  function checkDocs(projectDir) {
259109
259552
  const gaps = checkTopLevelCommands(activeDocsFiles(projectDir), DOC_RETIRED_TOP_LEVEL_COMMANDS);
259110
- const changelogPath = join96(projectDir, "CHANGELOG.md");
259111
- if (existsSync91(changelogPath)) {
259553
+ const changelogPath = join97(projectDir, "CHANGELOG.md");
259554
+ if (existsSync92(changelogPath)) {
259112
259555
  const changelog = readText(changelogPath);
259113
259556
  for (const id of releaseDeltaCardIds(projectDir)) {
259114
259557
  const base = id.replace(/[a-z]$/, "");
@@ -259181,9 +259624,9 @@ function siteTokens(name) {
259181
259624
  }
259182
259625
  function checkSite(projectDir) {
259183
259626
  const gaps = checkTopLevelCommands(activeSiteFiles(projectDir), SITE_HIDDEN_TOP_LEVEL_COMMANDS);
259184
- const siteJs = join96(projectDir, "site", "roll-data.js");
259185
- const backlog = join96(projectDir, ".roll", "backlog.md");
259186
- if (!existsSync91(siteJs) || !existsSync91(backlog))
259627
+ const siteJs = join97(projectDir, "site", "roll-data.js");
259628
+ const backlog = join97(projectDir, ".roll", "backlog.md");
259629
+ if (!existsSync92(siteJs) || !existsSync92(backlog))
259187
259630
  return { status: gaps.length === 0 ? "pass" : "fail", gaps };
259188
259631
  const siteText = readText(siteJs);
259189
259632
  const seenGuideRefs = /* @__PURE__ */ new Set();
@@ -259192,7 +259635,7 @@ function checkSite(projectDir) {
259192
259635
  if (seenGuideRefs.has(rel))
259193
259636
  continue;
259194
259637
  seenGuideRefs.add(rel);
259195
- if (!existsSync91(join96(projectDir, rel))) {
259638
+ if (!existsSync92(join97(projectDir, rel))) {
259196
259639
  gaps.push(`site/roll-data.js links a guide that does not exist: ${rel}`);
259197
259640
  }
259198
259641
  }
@@ -259233,7 +259676,7 @@ function listFiles2(dir) {
259233
259676
  try {
259234
259677
  return readdirSync38(dir).filter((n) => {
259235
259678
  try {
259236
- return statSync27(join96(dir, n)).isFile();
259679
+ return statSync27(join97(dir, n)).isFile();
259237
259680
  } catch {
259238
259681
  return false;
259239
259682
  }
@@ -259244,9 +259687,9 @@ function listFiles2(dir) {
259244
259687
  }
259245
259688
  function checkI18n(projectDir) {
259246
259689
  const gaps = [];
259247
- const guideEn = join96(projectDir, "guide", "en");
259248
- const guideZh = join96(projectDir, "guide", "zh");
259249
- if (existsSync91(guideEn) && existsSync91(guideZh)) {
259690
+ const guideEn = join97(projectDir, "guide", "en");
259691
+ const guideZh = join97(projectDir, "guide", "zh");
259692
+ if (existsSync92(guideEn) && existsSync92(guideZh)) {
259250
259693
  const enFiles = new Set(listFiles2(guideEn));
259251
259694
  const zhFiles = new Set(listFiles2(guideZh));
259252
259695
  const enOnly = [...enFiles].filter((f) => !zhFiles.has(f)).sort();
@@ -259256,8 +259699,8 @@ function checkI18n(projectDir) {
259256
259699
  for (const f of zhOnly)
259257
259700
  gaps.push(`guide/zh/${f} has no corresponding guide/en/${f}`);
259258
259701
  }
259259
- const i18nDir = join96(projectDir, "lib", "i18n");
259260
- if (existsSync91(i18nDir)) {
259702
+ const i18nDir = join97(projectDir, "lib", "i18n");
259703
+ if (existsSync92(i18nDir)) {
259261
259704
  const keysEn = /* @__PURE__ */ new Set();
259262
259705
  const keysZh = /* @__PURE__ */ new Set();
259263
259706
  let shFiles = [];
@@ -259267,7 +259710,7 @@ function checkI18n(projectDir) {
259267
259710
  shFiles = [];
259268
259711
  }
259269
259712
  for (const name of shFiles) {
259270
- const text2 = readText(join96(i18nDir, name));
259713
+ const text2 = readText(join97(i18nDir, name));
259271
259714
  for (const m7 of text2.matchAll(/_i18n_set\s+(en|zh)\s+([^\s]+)/g)) {
259272
259715
  const lang9 = m7[1];
259273
259716
  const key = m7[2] ?? "";
@@ -259307,7 +259750,7 @@ function rglobBats(dir) {
259307
259750
  return;
259308
259751
  }
259309
259752
  for (const e of entries) {
259310
- const full = join96(d, e);
259753
+ const full = join97(d, e);
259311
259754
  let st;
259312
259755
  try {
259313
259756
  st = statSync27(full);
@@ -259325,9 +259768,9 @@ function rglobBats(dir) {
259325
259768
  }
259326
259769
  function checkTests(projectDir) {
259327
259770
  const gaps = [];
259328
- const backlog = join96(projectDir, ".roll", "backlog.md");
259329
- const testsDir = join96(projectDir, "tests");
259330
- if (!existsSync91(backlog))
259771
+ const backlog = join97(projectDir, ".roll", "backlog.md");
259772
+ const testsDir = join97(projectDir, "tests");
259773
+ if (!existsSync92(backlog))
259331
259774
  return { status: "pass", gaps: [] };
259332
259775
  const backlogText = readText(backlog);
259333
259776
  const allFeatures = /* @__PURE__ */ new Set();
@@ -259352,7 +259795,7 @@ function checkTests(projectDir) {
259352
259795
  doneFeatures.push(currentFeature);
259353
259796
  }
259354
259797
  }
259355
- const testFiles = existsSync91(testsDir) ? rglobBats(testsDir) : [];
259798
+ const testFiles = existsSync92(testsDir) ? rglobBats(testsDir) : [];
259356
259799
  if (testFiles.length === 0)
259357
259800
  return { status: "pass", gaps: [] };
259358
259801
  for (const feat of doneFeatures) {
@@ -259805,7 +260248,7 @@ function realReleaseDeps() {
259805
260248
  return {
259806
260249
  version: (cwd) => {
259807
260250
  try {
259808
- const pkg = JSON.parse(readFileSync88(join98(cwd, "package.json"), "utf8"));
260251
+ const pkg = JSON.parse(readFileSync89(join99(cwd, "package.json"), "utf8"));
259809
260252
  return typeof pkg.version === "string" ? pkg.version : "";
259810
260253
  } catch {
259811
260254
  return "";
@@ -259840,13 +260283,13 @@ function realReleaseDeps() {
259840
260283
  return true;
259841
260284
  }
259842
260285
  },
259843
- readChangelog: (cwd) => readFileSync88(join98(cwd, "CHANGELOG.md"), "utf8"),
259844
- writeChangelog: (cwd, text2) => writeFileSync47(join98(cwd, "CHANGELOG.md"), text2, "utf8"),
260286
+ readChangelog: (cwd) => readFileSync89(join99(cwd, "CHANGELOG.md"), "utf8"),
260287
+ writeChangelog: (cwd, text2) => writeFileSync48(join99(cwd, "CHANGELOG.md"), text2, "utf8"),
259845
260288
  bumpVersion: (cwd, version) => {
259846
- const path = join98(cwd, "package.json");
259847
- const pkg = JSON.parse(readFileSync88(path, "utf8"));
260289
+ const path = join99(cwd, "package.json");
260290
+ const pkg = JSON.parse(readFileSync89(path, "utf8"));
259848
260291
  pkg["version"] = version;
259849
- writeFileSync47(path, `${JSON.stringify(pkg, null, 2)}
260292
+ writeFileSync48(path, `${JSON.stringify(pkg, null, 2)}
259850
260293
  `, "utf8");
259851
260294
  },
259852
260295
  packageGate: (cwd) => {
@@ -259861,7 +260304,7 @@ function realReleaseDeps() {
259861
260304
  commitPushWithGate({
259862
260305
  branch,
259863
260306
  message,
259864
- rollManaged: existsSync93(join98(cwd, ".roll")),
260307
+ rollManaged: existsSync94(join99(cwd, ".roll")),
259865
260308
  exec: (cmd, args) => execFileSync24(cmd, args, { cwd, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"], timeout: 6e5 })
259866
260309
  });
259867
260310
  },
@@ -259954,7 +260397,7 @@ function realReleaseDeps() {
259954
260397
  recordReleaseFact: (cwd, tagName) => {
259955
260398
  try {
259956
260399
  const runtimeDir9 = (process.env["ROLL_PROJECT_RUNTIME_DIR"] ?? "").trim();
259957
- const eventsPath2 = runtimeDir9 !== "" ? join98(runtimeDir9, EVENTS_FILE) : join98(cwd, ".roll", "loop", EVENTS_FILE);
260400
+ const eventsPath2 = runtimeDir9 !== "" ? join99(runtimeDir9, EVENTS_FILE) : join99(cwd, ".roll", "loop", EVENTS_FILE);
259958
260401
  new EventBus().appendEvent(eventsPath2, {
259959
260402
  type: "release:gate",
259960
260403
  tag: tagName,
@@ -260175,8 +260618,8 @@ ${c("dim", "\u2192 Running the golden-path showcase (real models; its verdict do
260175
260618
  init_dist();
260176
260619
  init_render();
260177
260620
  import { spawnSync as spawnSync12 } from "node:child_process";
260178
- import { existsSync as existsSync94, lstatSync as lstatSync5, mkdirSync as mkdirSync46, readFileSync as readFileSync89, readdirSync as readdirSync40, readlinkSync as readlinkSync2, statSync as statSync29 } from "node:fs";
260179
- import { join as join99 } from "node:path";
260621
+ import { existsSync as existsSync95, lstatSync as lstatSync5, mkdirSync as mkdirSync46, readFileSync as readFileSync90, readdirSync as readdirSync40, readlinkSync as readlinkSync2, statSync as statSync29 } from "node:fs";
260622
+ import { join as join100 } from "node:path";
260180
260623
  function err13(line) {
260181
260624
  const noColor2 = (process.env["NO_COLOR"] ?? "") !== "";
260182
260625
  const RED = noColor2 ? "" : "\x1B[0;31m";
@@ -260219,7 +260662,7 @@ function walk(dir, lines2) {
260219
260662
  return;
260220
260663
  }
260221
260664
  for (const name of names) {
260222
- const p = join99(dir, name);
260665
+ const p = join100(dir, name);
260223
260666
  let isLink = false;
260224
260667
  try {
260225
260668
  isLink = lstatSync5(p).isSymbolicLink();
@@ -260249,7 +260692,7 @@ function walk(dir, lines2) {
260249
260692
  }
260250
260693
  function fileFingerprint(p) {
260251
260694
  try {
260252
- const buf = readFileSync89(p);
260695
+ const buf = readFileSync90(p);
260253
260696
  let sum = 0;
260254
260697
  for (let i = 0; i < buf.length; i++)
260255
260698
  sum = sum * 31 + (buf[i] ?? 0) >>> 0;
@@ -260279,18 +260722,18 @@ function ensureHooksPath(repoPath) {
260279
260722
  }
260280
260723
  }
260281
260724
  function peerEnsureStateDir() {
260282
- const base = join99(rollHome2(), ".peer-state");
260725
+ const base = join100(rollHome2(), ".peer-state");
260283
260726
  mkdirSync46(base, { recursive: true });
260284
- mkdirSync46(join99(base, "logs"), { recursive: true });
260727
+ mkdirSync46(join100(base, "logs"), { recursive: true });
260285
260728
  }
260286
260729
  function tmuxPresent() {
260287
260730
  return onPath("tmux");
260288
260731
  }
260289
260732
  function submoduleGuard() {
260290
260733
  const pkg = rollPkgDir();
260291
- const skills = join99(pkg, "skills");
260292
- const hasGit = existsSync94(join99(pkg, ".git"));
260293
- const hasMods = existsSync94(join99(pkg, ".gitmodules"));
260734
+ const skills = join100(pkg, "skills");
260735
+ const hasGit = existsSync95(join100(pkg, ".git"));
260736
+ const hasMods = existsSync95(join100(pkg, ".gitmodules"));
260294
260737
  let empty = true;
260295
260738
  try {
260296
260739
  empty = readdirSync40(skills).length === 0;
@@ -260383,7 +260826,7 @@ function setupCommand(args) {
260383
260826
  return 1;
260384
260827
  }
260385
260828
  }
260386
- if (!existsSync94(rollPkgConventions())) {
260829
+ if (!existsSync95(rollPkgConventions())) {
260387
260830
  err13(m5("shared.convention_source_not_found_at_2", rollPkgConventions()));
260388
260831
  err13(m5("shared.run_this_from_the_roll_repo"));
260389
260832
  return 1;
@@ -260392,7 +260835,7 @@ function setupCommand(args) {
260392
260835
  const home = rollHome2();
260393
260836
  const aiDirsList = [".claude", ".kimi", ".kimi-code", ".codex", ".pi", ".agentrules", ".reasonix"];
260394
260837
  const homeDir = process.env["HOME"] ?? "";
260395
- const aiDirs = aiDirsList.map((d) => join99(homeDir, d)).join(":");
260838
+ const aiDirs = aiDirsList.map((d) => join100(homeDir, d)).join(":");
260396
260839
  const steps = [];
260397
260840
  const s1 = runSetupStep(home, () => {
260398
260841
  installLocal(force);
@@ -260406,7 +260849,7 @@ function setupCommand(args) {
260406
260849
  syncSkills(force);
260407
260850
  });
260408
260851
  steps.push({ num: 3, label: "Install skills to ~/.claude", status: stateToMarker(s3, force) });
260409
- const s4 = runSetupStep(join99(home, ".peer-state"), () => {
260852
+ const s4 = runSetupStep(join100(home, ".peer-state"), () => {
260410
260853
  peerEnsureStateDir();
260411
260854
  });
260412
260855
  steps.push({ num: 4, label: "Initialize peer-review state directory", status: stateToMarker(s4, force) });
@@ -260436,8 +260879,8 @@ init_showcase2();
260436
260879
 
260437
260880
  // packages/cli/dist/commands/test.js
260438
260881
  import { spawnSync as spawnSync13 } from "node:child_process";
260439
- import { appendFileSync as appendFileSync20, existsSync as existsSync95, mkdirSync as mkdirSync47, readFileSync as readFileSync90, rmSync as rmSync18, writeFileSync as writeFileSync48 } from "node:fs";
260440
- import { dirname as dirname45, join as join100, resolve as resolve8 } from "node:path";
260882
+ import { appendFileSync as appendFileSync20, existsSync as existsSync96, mkdirSync as mkdirSync47, readFileSync as readFileSync91, rmSync as rmSync18, writeFileSync as writeFileSync49 } from "node:fs";
260883
+ import { dirname as dirname45, join as join101, resolve as resolve8 } from "node:path";
260441
260884
  function pal7() {
260442
260885
  const noColor2 = (process.env["NO_COLOR"] ?? "") !== "";
260443
260886
  return noColor2 ? { CYAN: "", GREEN: "", YELLOW: "", RED: "", NC: "" } : { CYAN: "\x1B[0;36m", GREEN: "\x1B[0;32m", YELLOW: "\x1B[0;33m", RED: "\x1B[0;31m", NC: "\x1B[0m" };
@@ -260458,12 +260901,12 @@ function currentEvidenceFrame() {
260458
260901
  if (raw === "")
260459
260902
  return null;
260460
260903
  const runDir = resolve8(raw);
260461
- if (!existsSync95(runDir))
260904
+ if (!existsSync96(runDir))
260462
260905
  return null;
260463
260906
  const frame = {
260464
260907
  runDir,
260465
- evidenceDir: join100(runDir, "evidence"),
260466
- screenshotsDir: join100(runDir, "screenshots")
260908
+ evidenceDir: join101(runDir, "evidence"),
260909
+ screenshotsDir: join101(runDir, "screenshots")
260467
260910
  };
260468
260911
  try {
260469
260912
  mkdirSync47(frame.evidenceDir, { recursive: true });
@@ -260494,7 +260937,7 @@ function appendRollTestEvidence(frame, cmd, argv, status2, stdout, stderr) {
260494
260937
  try {
260495
260938
  const ts2 = (/* @__PURE__ */ new Date()).toISOString();
260496
260939
  const command = [cmd, ...argv];
260497
- appendFileSync20(join100(frame.evidenceDir, "roll-test-output.log"), [
260940
+ appendFileSync20(join101(frame.evidenceDir, "roll-test-output.log"), [
260498
260941
  `===== roll test ${ts2} exit=${status2} =====`,
260499
260942
  `$ ${command.join(" ")}`,
260500
260943
  "--- stdout ---",
@@ -260503,7 +260946,7 @@ function appendRollTestEvidence(frame, cmd, argv, status2, stdout, stderr) {
260503
260946
  stderr,
260504
260947
  ""
260505
260948
  ].join("\n"), "utf8");
260506
- appendFileSync20(join100(frame.evidenceDir, "roll-test-summary.txt"), JSON.stringify({
260949
+ appendFileSync20(join101(frame.evidenceDir, "roll-test-summary.txt"), JSON.stringify({
260507
260950
  ts: ts2,
260508
260951
  command,
260509
260952
  exitCode: status2,
@@ -260514,12 +260957,12 @@ function appendRollTestEvidence(frame, cmd, argv, status2, stdout, stderr) {
260514
260957
  }
260515
260958
  }
260516
260959
  function isolationGetType() {
260517
- const file = join100(process.cwd(), ".roll", "local.yaml");
260518
- if (!existsSync95(file))
260960
+ const file = join101(process.cwd(), ".roll", "local.yaml");
260961
+ if (!existsSync96(file))
260519
260962
  return "none";
260520
260963
  let text2;
260521
260964
  try {
260522
- text2 = readFileSync90(file, "utf8");
260965
+ text2 = readFileSync91(file, "utf8");
260523
260966
  } catch {
260524
260967
  return "none";
260525
260968
  }
@@ -260567,14 +261010,14 @@ function resetLockPath() {
260567
261010
  return ".roll/.iso-reset.lock";
260568
261011
  }
260569
261012
  function resetLockHeld() {
260570
- return existsSync95(resetLockPath());
261013
+ return existsSync96(resetLockPath());
260571
261014
  }
260572
261015
  function resetAcquireLock() {
260573
261016
  const lock = resetLockPath();
260574
- if (existsSync95(lock))
261017
+ if (existsSync96(lock))
260575
261018
  return false;
260576
261019
  mkdirSync47(dirname45(lock), { recursive: true });
260577
- writeFileSync48(lock, `${process.pid}
261020
+ writeFileSync49(lock, `${process.pid}
260578
261021
  `);
260579
261022
  return true;
260580
261023
  }
@@ -260597,15 +261040,15 @@ function runForward(cmd, argv) {
260597
261040
  }
260598
261041
  function ensureSkillsSubmoduleReady() {
260599
261042
  const pkg = rollPkgDir();
260600
- const required2 = join100(pkg, "skills", "roll-onboard", "SKILL.md");
260601
- if (existsSync95(required2))
261043
+ const required2 = join101(pkg, "skills", "roll-onboard", "SKILL.md");
261044
+ if (existsSync96(required2))
260602
261045
  return true;
260603
- if (existsSync95(join100(pkg, ".git")) && existsSync95(join100(pkg, ".gitmodules"))) {
261046
+ if (existsSync96(join101(pkg, ".git")) && existsSync96(join101(pkg, ".gitmodules"))) {
260604
261047
  spawnSync13("git", ["submodule", "update", "--init", "--recursive", "--quiet", "skills"], {
260605
261048
  cwd: pkg,
260606
261049
  stdio: "ignore"
260607
261050
  });
260608
- if (existsSync95(required2))
261051
+ if (existsSync96(required2))
260609
261052
  return true;
260610
261053
  }
260611
261054
  err14("roll test: skills submodule is empty");
@@ -260614,7 +261057,7 @@ function ensureSkillsSubmoduleReady() {
260614
261057
  }
260615
261058
  function isolationDispatch(method, args) {
260616
261059
  const type = isolationGetType();
260617
- if (type === "none" && !existsSync95(join100(process.cwd(), ".roll", "local.yaml"))) {
261060
+ if (type === "none" && !existsSync96(join101(process.cwd(), ".roll", "local.yaml"))) {
260618
261061
  infoErr("isolation: no test_isolation config, falling back to type=none (host)");
260619
261062
  }
260620
261063
  if (!SUPPORTED_TYPES.includes(type)) {
@@ -260710,7 +261153,7 @@ function testCommand(args) {
260710
261153
 
260711
261154
  // packages/cli/dist/commands/tool.js
260712
261155
  init_dist2();
260713
- import { join as join101 } from "node:path";
261156
+ import { join as join102 } from "node:path";
260714
261157
  var TOOL_USAGE = "Usage: roll tool status\n Show registered tools, input contracts, effective policy state, and requirement readiness.\n\u5C55\u793A\u5DF2\u6CE8\u518C\u5DE5\u5177\u3001\u5165\u53C2\u5951\u7EA6\u3001\u6709\u6548 policy \u72B6\u6001\u4E0E requirement \u5C31\u7EEA\u5EA6\u3002\n";
260715
261158
  async function toolCommand(args) {
260716
261159
  const sub = args[0] ?? "";
@@ -260728,7 +261171,7 @@ async function toolCommand(args) {
260728
261171
  return 0;
260729
261172
  }
260730
261173
  async function collectToolRows(projectRoot2, requirementResolver = resolveRequirement) {
260731
- const policy = new ToolPolicyEngine({ policyPath: join101(projectRoot2, ".roll", "policy.yaml") });
261174
+ const policy = new ToolPolicyEngine({ policyPath: join102(projectRoot2, ".roll", "policy.yaml") });
260732
261175
  const rows = [];
260733
261176
  for (const declaration of collectBuiltinToolDeclarations(projectRoot2)) {
260734
261177
  const effective = await policy.resolve(declaration.id, declaration.defaults);
@@ -260790,8 +261233,8 @@ function pad4(value, width) {
260790
261233
  // packages/cli/dist/commands/truth.js
260791
261234
  init_dist();
260792
261235
  init_dist2();
260793
- import { statSync as statSync30, readFileSync as readFileSync91, writeFileSync as writeFileSync49, mkdirSync as mkdirSync48, existsSync as existsSync96 } from "node:fs";
260794
- import { dirname as dirname46, join as join102 } from "node:path";
261236
+ import { statSync as statSync30, readFileSync as readFileSync92, writeFileSync as writeFileSync50, mkdirSync as mkdirSync48, existsSync as existsSync97 } from "node:fs";
261237
+ import { dirname as dirname46, join as join103 } from "node:path";
260795
261238
  var TRUTH_USAGE = "Usage: roll truth <command>\n query <storyId> Deterministic delivery-truth query (structured, zero markdown parse).\n audit Bidirectional drift audit: backlog Done \u2194 projection truth.\n\u547D\u4EE4:\n query <storyId> \u7ED3\u6784\u5316\u4EA4\u4ED8\u771F\u76F8\u67E5\u8BE2\uFF08\u786E\u5B9A\u6027\uFF0C\u4E0D\u89E3\u6790 markdown\uFF09\n audit \u53CC\u5411\u6F02\u79FB\u5BA1\u8BA1\uFF1Abacklog Done \u2194 \u6295\u5F71\u771F\u76F8";
260796
261239
  function formatTruth(t3, lang9) {
260797
261240
  const lines2 = [];
@@ -260823,22 +261266,22 @@ var nodeFreshnessPort3 = {
260823
261266
  },
260824
261267
  readText(absPath) {
260825
261268
  try {
260826
- return readFileSync91(absPath, "utf8");
261269
+ return readFileSync92(absPath, "utf8");
260827
261270
  } catch {
260828
261271
  return "";
260829
261272
  }
260830
261273
  },
260831
261274
  writeText(absPath, text2) {
260832
261275
  mkdirSync48(dirname46(absPath), { recursive: true });
260833
- writeFileSync49(absPath, text2, "utf8");
261276
+ writeFileSync50(absPath, text2, "utf8");
260834
261277
  }
260835
261278
  };
260836
261279
  function truthAuditCommand(args, lang9) {
260837
261280
  const json = args.includes("--json");
260838
261281
  const cwd = process.cwd();
260839
261282
  const nowSec2 = Math.floor(Date.now() / 1e3);
260840
- const backlogPath = join102(cwd, ".roll", "backlog.md");
260841
- const backlogRows = existsSync96(backlogPath) ? parseBacklog(readFileSync91(backlogPath, "utf8")).map((r) => ({ id: r.id, status: r.status })) : [];
261283
+ const backlogPath = join103(cwd, ".roll", "backlog.md");
261284
+ const backlogRows = existsSync97(backlogPath) ? parseBacklog(readFileSync92(backlogPath, "utf8")).map((r) => ({ id: r.id, status: r.status })) : [];
260842
261285
  const deliveries = ensureDeliveriesFresh(cwd, nodeFreshnessPort3, nodeExecPort);
260843
261286
  const snapshot = emptyAuditSnapshot(nowSec2, TERMINAL_SCHEMA_EPOCH_SEC);
260844
261287
  snapshot.backlog = backlogRows;
@@ -260923,8 +261366,8 @@ function truthCommand(args) {
260923
261366
 
260924
261367
  // packages/cli/dist/commands/tune.js
260925
261368
  init_dist2();
260926
- import { existsSync as existsSync97, readFileSync as readFileSync92 } from "node:fs";
260927
- import { join as join103 } from "node:path";
261369
+ import { existsSync as existsSync98, readFileSync as readFileSync93 } from "node:fs";
261370
+ import { join as join104 } from "node:path";
260928
261371
  function projectPath2() {
260929
261372
  return (process.env["ROLL_MAIN_PROJECT"] ?? "").trim() || process.cwd();
260930
261373
  }
@@ -260932,11 +261375,11 @@ function str6(v, dflt = "") {
260932
261375
  return typeof v === "string" ? v : dflt;
260933
261376
  }
260934
261377
  function parseJsonl(path) {
260935
- if (!existsSync97(path))
261378
+ if (!existsSync98(path))
260936
261379
  return [];
260937
261380
  let text2;
260938
261381
  try {
260939
- text2 = readFileSync92(path, "utf8");
261382
+ text2 = readFileSync93(path, "utf8");
260940
261383
  } catch {
260941
261384
  return [];
260942
261385
  }
@@ -261067,9 +261510,9 @@ function tuneCommand(argv) {
261067
261510
  if (argv[0] === "reset")
261068
261511
  return printReset();
261069
261512
  const proj = projectPath2();
261070
- const loopDir = join103(proj, ".roll", "loop");
261071
- const runs = parseJsonl(join103(loopDir, "runs.jsonl"));
261072
- const events = parseJsonl(join103(loopDir, "events.ndjson"));
261513
+ const loopDir = join104(proj, ".roll", "loop");
261514
+ const runs = parseJsonl(join104(loopDir, "runs.jsonl"));
261515
+ const events = parseJsonl(join104(loopDir, "events.ndjson"));
261073
261516
  const minSamplesRaw = flag(argv, "--min-samples");
261074
261517
  const now = flag(argv, "--now") ?? (/* @__PURE__ */ new Date()).toISOString();
261075
261518
  const input = {
@@ -261108,9 +261551,9 @@ function tuneCommand(argv) {
261108
261551
  // packages/cli/dist/commands/update.js
261109
261552
  init_dist();
261110
261553
  import { spawnSync as spawnSync14 } from "node:child_process";
261111
- import { existsSync as existsSync98, mkdtempSync as mkdtempSync7, readFileSync as readFileSync93, rmSync as rmSync19 } from "node:fs";
261554
+ import { existsSync as existsSync99, mkdtempSync as mkdtempSync7, readFileSync as readFileSync94, rmSync as rmSync19 } from "node:fs";
261112
261555
  import { tmpdir as tmpdir9 } from "node:os";
261113
- import { join as join104 } from "node:path";
261556
+ import { join as join105 } from "node:path";
261114
261557
  function pal8() {
261115
261558
  const noColor2 = (process.env["NO_COLOR"] ?? "") !== "";
261116
261559
  return noColor2 ? { CYAN: "", GREEN: "", YELLOW: "", RED: "", BOLD: "", NC: "" } : {
@@ -261174,20 +261617,20 @@ function resolveRemoteVersion() {
261174
261617
  }
261175
261618
  function downloadAndInstallCurl(tag) {
261176
261619
  const url = `https://github.com/seanyao/roll/archive/refs/tags/${tag}.tar.gz`;
261177
- const tmpDir = mkdtempSync7(join104(tmpdir9(), "roll-update-"));
261620
+ const tmpDir = mkdtempSync7(join105(tmpdir9(), "roll-update-"));
261178
261621
  try {
261179
261622
  info5(`[roll] Downloading roll ${tag} ...`);
261180
- const dl = runForward2("curl", ["-fsSL", url, "-o", join104(tmpDir, "roll.tar.gz")]);
261623
+ const dl = runForward2("curl", ["-fsSL", url, "-o", join105(tmpDir, "roll.tar.gz")]);
261181
261624
  if (dl !== 0) {
261182
261625
  err15(m6("update.curl_download_failed"));
261183
261626
  return { ok: false };
261184
261627
  }
261185
261628
  info5("[roll] Extracting ...");
261186
- const extractDir = join104(tmpDir, "extract");
261629
+ const extractDir = join105(tmpDir, "extract");
261187
261630
  spawnSync14("mkdir", ["-p", extractDir], { stdio: "ignore" });
261188
261631
  const ex = runForward2("tar", [
261189
261632
  "-xzf",
261190
- join104(tmpDir, "roll.tar.gz"),
261633
+ join105(tmpDir, "roll.tar.gz"),
261191
261634
  "--strip-components=1",
261192
261635
  "-C",
261193
261636
  extractDir
@@ -261204,7 +261647,7 @@ function downloadAndInstallCurl(tag) {
261204
261647
  function checkInstalledVersionOrRetry() {
261205
261648
  const expected = (spawnSync14("npm", ["view", "@seanyao/roll", "version"], { encoding: "utf8" }).stdout ?? "").trim();
261206
261649
  const pkgRoot = (spawnSync14("npm", ["root", "-g"], { encoding: "utf8" }).stdout ?? "").trim();
261207
- const installedTree = join104(pkgRoot, "@seanyao", "roll");
261650
+ const installedTree = join105(pkgRoot, "@seanyao", "roll");
261208
261651
  const installed = treeVersion(installedTree);
261209
261652
  if (expected === "" || installed === "")
261210
261653
  return;
@@ -261218,18 +261661,18 @@ function checkInstalledVersionOrRetry() {
261218
261661
  }
261219
261662
  }
261220
261663
  function invalidateUpdateCache() {
261221
- rmSync19(join104(rollHome2(), ".update-check"), { force: true });
261664
+ rmSync19(join105(rollHome2(), ".update-check"), { force: true });
261222
261665
  }
261223
261666
  function showChangelog() {
261224
- const changelog = join104(rollPkgDir(), "CHANGELOG.md");
261225
- if (!existsSync98(changelog))
261667
+ const changelog = join105(rollPkgDir(), "CHANGELOG.md");
261668
+ if (!existsSync99(changelog))
261226
261669
  return;
261227
261670
  const { BOLD: BOLD2, CYAN, NC } = pal8();
261228
261671
  process.stdout.write(`${BOLD2}${m6("changelog.heading")}:${NC}
261229
261672
  `);
261230
261673
  let count = 0;
261231
261674
  let inSection = false;
261232
- for (const line of readFileSync93(changelog, "utf8").split("\n")) {
261675
+ for (const line of readFileSync94(changelog, "utf8").split("\n")) {
261233
261676
  if (/^## /.test(line)) {
261234
261677
  count += 1;
261235
261678
  if (count > 3)
@@ -261252,9 +261695,9 @@ function updateCommand(args) {
261252
261695
  }
261253
261696
  info5(m6("update.current_version", rollVersion()));
261254
261697
  let installMethod = "npm";
261255
- const methodFile = join104(rollPkgDir(), ".install-method");
261256
- if (existsSync98(methodFile)) {
261257
- installMethod = readFileSync93(methodFile, "utf8").trim() || "npm";
261698
+ const methodFile = join105(rollPkgDir(), ".install-method");
261699
+ if (existsSync99(methodFile)) {
261700
+ installMethod = readFileSync94(methodFile, "utf8").trim() || "npm";
261258
261701
  }
261259
261702
  if (installMethod === "curl") {
261260
261703
  info5(m6("update.upgrading_via_curl"));
@@ -261418,6 +261861,8 @@ function registerAll() {
261418
261861
  return loopSelfDowngradeCommand(args.slice(1));
261419
261862
  if (args[0] === "review-resize")
261420
261863
  return loopReviewResizeCommand(args.slice(1));
261864
+ if (args[0] === "exhaustion-split")
261865
+ return loopExhaustionSplitCommand(args.slice(1));
261421
261866
  if (args[0] === "fmt")
261422
261867
  return loopFmtCommand(args.slice(1));
261423
261868
  if (args[0] === "watch")