@ordewell/core 0.11.3 → 0.12.1

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 (49) hide show
  1. package/AUTHORS.md +3 -1
  2. package/dist/{ModeResolver-DyXeZ9ib.d.ts → ModeResolver-B64aUZXJ.d.ts} +1 -1
  3. package/dist/{ModeResolver-BDAgouuE.d.mts → ModeResolver-CA2fUU9h.d.mts} +1 -1
  4. package/dist/{Task-BL4Idm9r.d.mts → Task-CxGgN6I0.d.mts} +801 -39
  5. package/dist/{Task-BL4Idm9r.d.ts → Task-CxGgN6I0.d.ts} +801 -39
  6. package/dist/{chunk-YAFNYNFX.mjs → chunk-2IFKPYPO.mjs} +453 -17
  7. package/dist/chunk-2IFKPYPO.mjs.map +1 -0
  8. package/dist/{chunk-MYXMIVWA.mjs → chunk-FX33UKAD.mjs} +8 -6
  9. package/dist/chunk-FX33UKAD.mjs.map +1 -0
  10. package/dist/{chunk-QTZ5XTBY.mjs → chunk-PKJTN2PD.mjs} +458 -13
  11. package/dist/chunk-PKJTN2PD.mjs.map +1 -0
  12. package/dist/{chunk-7WNLN63J.mjs → chunk-RZ23BMVR.mjs} +599 -124
  13. package/dist/chunk-RZ23BMVR.mjs.map +1 -0
  14. package/dist/chunk-UDUATSCJ.mjs +48 -0
  15. package/dist/chunk-UDUATSCJ.mjs.map +1 -0
  16. package/dist/{IRunner-DOMtDTVt.d.ts → eventStore-CTCSKS9E.d.ts} +976 -145
  17. package/dist/{IRunner-ihalYfTo.d.mts → eventStore-CcB8yELZ.d.mts} +976 -145
  18. package/dist/index.d.mts +905 -164
  19. package/dist/index.d.ts +905 -164
  20. package/dist/index.js +12496 -3308
  21. package/dist/index.js.map +1 -1
  22. package/dist/index.mjs +10830 -2919
  23. package/dist/index.mjs.map +1 -1
  24. package/dist/parsing.d.mts +2 -2
  25. package/dist/parsing.d.ts +2 -2
  26. package/dist/parsing.js +277 -21
  27. package/dist/parsing.js.map +1 -1
  28. package/dist/parsing.mjs +3 -3
  29. package/dist/plan-utils.d.mts +8 -5
  30. package/dist/plan-utils.d.ts +8 -5
  31. package/dist/plan-utils.js +262 -33
  32. package/dist/plan-utils.js.map +1 -1
  33. package/dist/plan-utils.mjs +39 -3
  34. package/dist/{runSettingsText-DVOd7vKC.d.ts → runSettingsText-DFVpe6aU.d.mts} +1996 -895
  35. package/dist/{runSettingsText-BuLVBlXS.d.mts → runSettingsText-lKLDsyli.d.ts} +1996 -895
  36. package/dist/testing.d.mts +99 -4
  37. package/dist/testing.d.ts +99 -4
  38. package/dist/testing.js +213 -8
  39. package/dist/testing.js.map +1 -1
  40. package/dist/testing.mjs +193 -8
  41. package/dist/testing.mjs.map +1 -1
  42. package/docker/task.Dockerfile +22 -0
  43. package/package.json +3 -1
  44. package/skills/diagnose/SKILL.md +2 -2
  45. package/skills/explore/SKILL.md +1 -1
  46. package/dist/chunk-7WNLN63J.mjs.map +0 -1
  47. package/dist/chunk-MYXMIVWA.mjs.map +0 -1
  48. package/dist/chunk-QTZ5XTBY.mjs.map +0 -1
  49. package/dist/chunk-YAFNYNFX.mjs.map +0 -1
@@ -32,6 +32,7 @@ var plan_utils_exports = {};
32
32
  __export(plan_utils_exports, {
33
33
  CHECKPOINT_TRUNCATE_LENGTH: () => CHECKPOINT_TRUNCATE_LENGTH,
34
34
  DEFAULT_RUNNERS: () => DEFAULT_RUNNERS,
35
+ DELEGATION_OFFERED: () => DELEGATION_OFFERED,
35
36
  EMPTY_CONVERSATION: () => EMPTY_CONVERSATION,
36
37
  EMPTY_HOLD: () => EMPTY_HOLD,
37
38
  EMPTY_RUN: () => EMPTY_RUN,
@@ -43,6 +44,8 @@ __export(plan_utils_exports, {
43
44
  PLANNED_WITH_LABEL: () => PLANNED_WITH_LABEL,
44
45
  REPORT_PREVIEW_LINES: () => REPORT_PREVIEW_LINES,
45
46
  SEVERITY_LABEL: () => SEVERITY_LABEL,
47
+ STALLED_LABEL: () => STALLED_LABEL,
48
+ STOPPING_LABEL: () => STOPPING_LABEL,
46
49
  SUPERVISOR_LEVEL_LABEL: () => SUPERVISOR_LEVEL_LABEL,
47
50
  WAITS_FOR_APPROVAL_LABEL: () => WAITS_FOR_APPROVAL_LABEL,
48
51
  accountLimitPercentText: () => accountLimitPercentText,
@@ -50,6 +53,7 @@ __export(plan_utils_exports, {
50
53
  accountLimitsOf: () => accountLimitsOf,
51
54
  accountLimitsText: () => accountLimitsText,
52
55
  accountLimitsTitle: () => accountLimitsTitle,
56
+ activityLabel: () => activityLabel,
53
57
  addAttemptUsage: () => addAttemptUsage,
54
58
  addModelUsage: () => addModelUsage,
55
59
  addPlannerUsage: () => addPlannerUsage,
@@ -77,12 +81,14 @@ __export(plan_utils_exports, {
77
81
  cardEditable: () => cardEditable,
78
82
  checkOf: () => checkOf,
79
83
  clampThinkingEffort: () => clampThinkingEffort,
84
+ closeTurn: () => closeTurn,
80
85
  compactionText: () => compactionText,
81
86
  confirmedOverride: () => confirmedOverride,
82
87
  contextMeterText: () => contextMeterText,
83
88
  contextMeterTitle: () => contextMeterTitle,
84
89
  costText: () => costText,
85
90
  countedSessionCost: () => countedSessionCost,
91
+ delegatedRowView: () => delegatedRowView,
86
92
  dependencyCandidates: () => dependencyCandidates,
87
93
  dependentsNotice: () => dependentsNotice,
88
94
  dependentsOf: () => dependentsOf,
@@ -93,10 +99,12 @@ __export(plan_utils_exports, {
93
99
  diffSummary: () => diffSummary,
94
100
  drainNext: () => drainNext,
95
101
  editableWhileRunning: () => editableWhileRunning,
102
+ elapsedSince: () => elapsedSince,
96
103
  endAttemptUsage: () => endAttemptUsage,
97
104
  followTaskLog: () => followTaskLog,
98
105
  followTurn: () => followTurn,
99
106
  formatCost: () => formatCost,
107
+ formatElapsed: () => formatElapsed,
100
108
  formatTokenCount: () => formatTokenCount,
101
109
  fromTranscript: () => fromTranscript,
102
110
  handoffBaseLine: () => handoffBaseLine,
@@ -107,6 +115,7 @@ __export(plan_utils_exports, {
107
115
  hasAccountLimits: () => hasAccountLimits,
108
116
  hasHiddenDetail: () => hasHiddenDetail,
109
117
  hasLongReport: () => hasLongReport,
118
+ heldWords: () => heldWords,
110
119
  holdLabel: () => holdLabel,
111
120
  holdPrompt: () => holdPrompt,
112
121
  isFileEditTool: () => isFileEditTool,
@@ -130,10 +139,12 @@ __export(plan_utils_exports, {
130
139
  markdownHtml: () => markdownHtml,
131
140
  markdownTokens: () => markdownTokens,
132
141
  mergeOutcome: () => mergeOutcome,
142
+ mergePastChecksConfirmation: () => mergePastChecksConfirmation,
133
143
  modelCostTitle: () => modelCostTitle,
134
144
  namedRepos: () => namedRepos,
135
145
  newTaskFields: () => newTaskFields,
136
146
  noExecutorRefusal: () => noExecutorRefusal,
147
+ onOneLine: () => onOneLine,
137
148
  opsEditable: () => opsEditable,
138
149
  outOfRounds: () => outOfRounds,
139
150
  outputLines: () => outputLines,
@@ -152,6 +163,7 @@ __export(plan_utils_exports, {
152
163
  reconcileApprovals: () => reconcileApprovals,
153
164
  reduceConversation: () => reduceConversation,
154
165
  reduceTaskLog: () => reduceTaskLog,
166
+ repairWaitLabel: () => repairWaitLabel,
155
167
  repairedLanded: () => repairedLanded,
156
168
  repairedNotice: () => repairedNotice,
157
169
  repeatingChecks: () => repeatingChecks,
@@ -163,6 +175,9 @@ __export(plan_utils_exports, {
163
175
  resumeLabel: () => resumeLabel,
164
176
  resumeTime: () => resumeTime,
165
177
  resumedSessionWindow: () => resumedSessionWindow,
178
+ revertEffect: () => revertEffect,
179
+ revertListLine: () => revertListLine,
180
+ revertTaskRef: () => revertTaskRef,
166
181
  runHoldsEditors: () => runHoldsEditors,
167
182
  runnerToolSubject: () => runnerToolSubject,
168
183
  savedPatchView: () => savedPatchView,
@@ -171,13 +186,16 @@ __export(plan_utils_exports, {
171
186
  severityLabel: () => severityLabel,
172
187
  skillTokens: () => skillTokens,
173
188
  skippedLabel: () => skippedLabel,
189
+ spentTokens: () => spentTokens,
174
190
  startAttemptUsage: () => startAttemptUsage,
175
191
  stopTurn: () => stopTurn,
176
192
  subagentCostTitle: () => subagentCostTitle,
177
193
  subtreeIds: () => subtreeIds,
194
+ subtreeView: () => subtreeView,
178
195
  summarizeToolCall: () => summarizeToolCall,
179
196
  takeAt: () => takeAt,
180
197
  taskActionCommand: () => taskActionCommand,
198
+ taskActivity: () => taskActivity,
181
199
  taskChatAvailable: () => taskChatAvailable,
182
200
  taskLogCommands: () => taskLogCommands,
183
201
  taskLogHeaderView: () => taskLogHeaderView,
@@ -390,9 +408,11 @@ function taskStatusKind(task) {
390
408
  if (!isTaskRunning(task)) return "todo";
391
409
  return task.status === "in_progress" && task.idleSince ? "quiet" : "running";
392
410
  }
411
+ var STALLED_LABEL = "Stalled";
393
412
  var AWAITING_LABELS = {
394
413
  input: "Waiting for your input",
395
414
  checkpoint: "Checkpoint",
415
+ "question-lost": "Question lost in a restart",
396
416
  conflict: "Merge conflict",
397
417
  "files-changed": "Changed tracked files",
398
418
  "usage-limit": "Paused on a usage limit"
@@ -400,6 +420,14 @@ var AWAITING_LABELS = {
400
420
  function awaitingLabel(task) {
401
421
  return task.status === "awaiting_user" && task.awaitingReason ? AWAITING_LABELS[task.awaitingReason] : null;
402
422
  }
423
+ var REPAIR_WAIT_LABELS = {
424
+ slot: "Repair waits for a free slot",
425
+ planner: "Repair waits for the planner's turn to end",
426
+ "usage-limit": "Repair waits for its runner's usage limit to reset"
427
+ };
428
+ function repairWaitLabel(wait) {
429
+ return REPAIR_WAIT_LABELS[wait];
430
+ }
403
431
  function blockedByLabel(refs) {
404
432
  return `Blocked by ${refs.join(", ")}`;
405
433
  }
@@ -569,10 +597,25 @@ function loopRemovalRefusal(task) {
569
597
  return task.loop ? `"${task.title}" is a loop's check: remove its body tasks first, or drop its loop ("loop": null), so they do not run on their own` : null;
570
598
  }
571
599
  function loopReshapeRefusal(tasks, target, action) {
600
+ if (target.type === "delegated") return `"${target.title}" is a delegated task and cannot be ${action}: remove it and add what should replace it`;
572
601
  if (target.loop) return `"${target.title}" is a loop's check and cannot be ${action}: drop its loop first ("loop": null)`;
573
602
  return checkOf(tasks, target.id) ? `"${target.title}" is in a loop's body and cannot be ${action}: take it out of the loop first` : null;
574
603
  }
575
604
 
605
+ // src/models/lineBreaks.ts
606
+ var BREAKS = "\\n\\v\\f\\r\\u0085\\u2028\\u2029";
607
+ var LINE_BREAK = new RegExp(`\\r\\n|[${BREAKS}]`);
608
+ var ONE_LINE = new RegExp(`^[^${BREAKS}]*$`);
609
+ function splitLines(text2) {
610
+ return text2.split(LINE_BREAK);
611
+ }
612
+ function quotedLine(text2) {
613
+ return JSON.stringify(text2).replace(/[\u0085\u2028\u2029]/g, (char) => `\\u${char.charCodeAt(0).toString(16).padStart(4, "0")}`);
614
+ }
615
+ function onOneLine(text2) {
616
+ return ONE_LINE.test(text2) ? text2 : quotedLine(text2);
617
+ }
618
+
576
619
  // src/services/PlannedTask.ts
577
620
  function findCycle(tasks) {
578
621
  return findDependencyCycle(tasks);
@@ -1023,7 +1066,8 @@ function truncateCheckpointSummary(summary) {
1023
1066
 
1024
1067
  // src/services/conflictFiles.ts
1025
1068
  function capConflictFiles(files, max = 5) {
1026
- return files.length <= max ? files.join(", ") : `${files.slice(0, max).join(", ")}, +${files.length - max} more`;
1069
+ const named = files.map(onOneLine);
1070
+ return named.length <= max ? named.join(", ") : `${named.slice(0, max).join(", ")}, +${named.length - max} more`;
1027
1071
  }
1028
1072
 
1029
1073
  // src/services/mergeResultNotice.ts
@@ -1171,10 +1215,33 @@ function handoffBaseLine(handoff, length) {
1171
1215
  function repoResultLines(handoff) {
1172
1216
  return handoff.repos.map(({ path, landed }) => `${path}: ${landed.length === 0 ? "nothing to merge" : `${landed.length} task${landed.length === 1 ? "" : "s"} landed`}`);
1173
1217
  }
1218
+ function mergePastChecksConfirmation(checks) {
1219
+ return `This merges work no check has passed: ${checks.join(", ")} ${checks.length === 1 ? "has" : "have"} not.`;
1220
+ }
1174
1221
 
1175
1222
  // src/services/runSettingsText.ts
1176
1223
  var SUPERVISOR_LEVEL_LABEL = { off: "Off", watch: "Watch", act: "Act" };
1177
1224
  var PLANNED_WITH_LABEL = "Planned-with line in commits Ordewell writes";
1225
+ var DELEGATION_ENV = "ORDEWELL_DELEGATION";
1226
+ function delegationSwitchedOn({ env, moduleDir, exists }) {
1227
+ if (env !== "1" || moduleDir === null) return false;
1228
+ const parts = moduleDir.split(/[\\/]/);
1229
+ if (parts.includes("node_modules")) return false;
1230
+ const packages = parts.lastIndexOf("packages");
1231
+ if (packages < 1) return false;
1232
+ const root = parts.slice(0, packages).join("/");
1233
+ return exists(`${root}/.git`) && exists(`${root}/packages/core/package.json`);
1234
+ }
1235
+ function placeHere(variable) {
1236
+ const fs = typeof process === "undefined" ? void 0 : process.getBuiltinModule?.("fs");
1237
+ if (!fs) return { env: void 0, moduleDir: null, exists: () => false };
1238
+ const file = typeof __filename !== "undefined" ? __filename : new URL(
1239
+ // @ts-expect-error - import.meta is only valid under an ESM module setting; see builtinSkills.ts
1240
+ __filename
1241
+ ).pathname;
1242
+ return { env: process.env[variable], moduleDir: file.replace(/[\\/][^\\/]*$/, ""), exists: (path) => fs.existsSync(path) };
1243
+ }
1244
+ var DELEGATION_OFFERED = delegationSwitchedOn(placeHere(DELEGATION_ENV));
1178
1245
  function parseCount(arg, min) {
1179
1246
  if (arg === void 0 || !/^\d+$/.test(arg)) return null;
1180
1247
  const n = Number(arg);
@@ -1183,18 +1250,21 @@ function parseCount(arg, min) {
1183
1250
 
1184
1251
  // src/models/Usage.ts
1185
1252
  function partedPromptUsage(parts) {
1186
- const reported = [parts.uncached, parts.cacheRead, parts.cacheWrite].filter((n) => n !== void 0);
1253
+ const reported2 = [parts.uncached, parts.cacheRead, parts.cacheWrite].filter((n) => n !== void 0);
1187
1254
  return {
1188
- ...reported.length > 0 ? { inputTokens: reported.reduce((a, b) => a + b, 0) } : {},
1255
+ ...reported2.length > 0 ? { inputTokens: reported2.reduce((a, b) => a + b, 0) } : {},
1189
1256
  ...parts.cacheRead !== void 0 ? { cachedInputTokens: parts.cacheRead } : {}
1190
1257
  };
1191
1258
  }
1192
1259
  var TOKEN_FIELDS = ["inputTokens", "outputTokens", "cachedInputTokens"];
1260
+ function spentTokens({ inputTokens, outputTokens }) {
1261
+ return (inputTokens ?? 0) + (outputTokens ?? 0);
1262
+ }
1193
1263
  function addUsage(totals, record) {
1194
1264
  const next = { ...totals };
1195
1265
  for (const field of TOKEN_FIELDS) {
1196
- const reported = record[field];
1197
- if (reported !== void 0) next[field] = (totals[field] ?? 0) + reported;
1266
+ const reported2 = record[field];
1267
+ if (reported2 !== void 0) next[field] = (totals[field] ?? 0) + reported2;
1198
1268
  }
1199
1269
  if (record.reportedCost) {
1200
1270
  const { amount, currency } = record.reportedCost;
@@ -1338,7 +1408,7 @@ function planUsage(tasks) {
1338
1408
  function taskUsageSummary(task) {
1339
1409
  const attempts = task.attemptUsage ?? [];
1340
1410
  const latest = attempts.at(-1);
1341
- const contextFill = latest ? plannerContextFill(latest) : void 0;
1411
+ const contextFill = latest && task.type !== "delegated" ? plannerContextFill(latest) : void 0;
1342
1412
  return {
1343
1413
  totals: attempts.reduce((sum, attempt) => addUsageTotals(sum, attempt.totals), {}),
1344
1414
  attempts: attempts.length,
@@ -2176,17 +2246,17 @@ function answered(block, decision, note) {
2176
2246
  function decideApproval2(view, { approvalId, decision, note }) {
2177
2247
  return settleApproval2(view, approvalId, (block) => answered(block, decision, note));
2178
2248
  }
2179
- function startTurn(view, { message, messageId, from, forced }) {
2249
+ function startTurn(view, { message, messageId, from, forced, startedAt }) {
2180
2250
  const queued = messageId ? view.queued.filter((m) => m.id !== messageId) : view.queued;
2181
- const working = { ...view, queued, working: true, latestText: void 0 };
2251
+ const working = { ...view, queued, working: true, turnStartedAt: startedAt, latestText: void 0 };
2182
2252
  return message ? append(working, (id) => ({ ...sentMessage(id, message, from), ...forced ? { forced: true } : {} })) : working;
2183
2253
  }
2184
2254
  function sentMessage(id, text2, from) {
2185
2255
  return from === "ordewell" ? settledMessage(id, "system", `Ordewell: ${text2}`) : settledMessage(id, "user", text2);
2186
2256
  }
2187
- function startCommand(view, { name, args, messageId }) {
2257
+ function startCommand(view, { name, args, messageId, startedAt }) {
2188
2258
  const queued = messageId ? view.queued.filter((m) => m.id !== messageId) : view.queued;
2189
- return append({ ...view, queued, working: true, latestText: void 0 }, (id) => ({
2259
+ return append({ ...view, queued, working: true, turnStartedAt: startedAt, latestText: void 0 }, (id) => ({
2190
2260
  type: "command",
2191
2261
  id,
2192
2262
  name,
@@ -2221,7 +2291,7 @@ function endTurn2(view, { reason }) {
2221
2291
  const i = runningCommand(view);
2222
2292
  const command = view.blocks[i];
2223
2293
  const settled = command?.type === "command" ? { ...view, blocks: replaceAt(view.blocks, i, { ...command, status: COMMAND_END[reason] }) } : view;
2224
- const closed = closeOpenBlocks({ ...settled, working: false, lastTurnEnd: reason, streams: {}, latestText: void 0 }, CUT[reason]);
2294
+ const closed = closeOpenBlocks({ ...settled, working: false, turnStartedAt: void 0, lastTurnEnd: reason, streams: {}, latestText: void 0 }, CUT[reason]);
2225
2295
  return reason === "interrupted" ? append(closed, (id) => settledMessage(id, "system", "Interrupted.")) : closed;
2226
2296
  }
2227
2297
  function queueMessage(view, { messageId, text: text2, forced, from }) {
@@ -2271,7 +2341,7 @@ function endScriptStep(view, event) {
2271
2341
  const passed = event.code === 0 && !event.signal && event.error === void 0;
2272
2342
  const i = runningScriptStep(view);
2273
2343
  const block = view.blocks[i];
2274
- const ended = { ...view, working: false };
2344
+ const ended = { ...view, working: false, turnStartedAt: void 0 };
2275
2345
  if (block?.type !== "tool") return append(ended, (id) => settledMessage(id, "system", status));
2276
2346
  const output = block.output.trim() ? `${block.output.replace(/\n+$/, "")}
2277
2347
  ${status}` : status;
@@ -2368,7 +2438,7 @@ function reduceTaskLog(view, event) {
2368
2438
  case "handoff":
2369
2439
  return showHandoff(view, event);
2370
2440
  case "runner_ended":
2371
- return closeOpenBlocks({ ...endOpenCalls(view), working: false, streams: {}, latestText: void 0 }, "stopped");
2441
+ return closeOpenBlocks({ ...endOpenCalls(view), working: false, turnStartedAt: void 0, streams: {}, latestText: void 0 }, "stopped");
2372
2442
  default:
2373
2443
  return view;
2374
2444
  }
@@ -2377,6 +2447,61 @@ function replayTaskLog(events, from = EMPTY_TASK_LOG) {
2377
2447
  return events.reduce(reduceTaskLog, from);
2378
2448
  }
2379
2449
 
2450
+ // src/conversation/activity.ts
2451
+ function activityLabel(view) {
2452
+ for (let i = view.blocks.length - 1; i >= 0; i--) {
2453
+ const label = openLabel(view.blocks[i], view);
2454
+ if (label) return label;
2455
+ }
2456
+ return "Working\u2026";
2457
+ }
2458
+ function isAtWork(view) {
2459
+ if (view.working !== false) return true;
2460
+ if (view.blocks.some((b) => b.type === "subagent" && b.status === "running")) return true;
2461
+ return view.lastTurnEnd === void 0 && view.blocks.some((b) => openLabel(b, view) !== null);
2462
+ }
2463
+ function openLabel(block, view) {
2464
+ switch (block.type) {
2465
+ case "thinking":
2466
+ return block.streaming ? "Thinking\u2026" : null;
2467
+ case "message":
2468
+ return block.streaming ? "Writing\u2026" : null;
2469
+ case "tool": {
2470
+ if (block.status !== "pending") return null;
2471
+ const { name, keyArg } = block.headline;
2472
+ return keyArg ? `Running ${name}(${keyArg})\u2026` : `Running ${name}\u2026`;
2473
+ }
2474
+ case "subagent": {
2475
+ if (block.status !== "running") return null;
2476
+ const running = view.blocks.filter((b) => b.type === "subagent" && b.status === "running");
2477
+ return running.length > 1 ? `${running.length} subagents running\u2026` : `Subagent: ${block.brief}\u2026`;
2478
+ }
2479
+ default:
2480
+ return null;
2481
+ }
2482
+ }
2483
+ function taskActivity(view, task) {
2484
+ if (!isTaskRunning(task) || view.archived) return null;
2485
+ if (task.awaitingApproval || view.blocks.some((b) => b.type === "approval" && b.status === "pending")) return null;
2486
+ const since = view.turnStartedAt ? { since: view.turnStartedAt } : {};
2487
+ if (taskStatusKind(task) === "quiet") return { label: STALLED_LABEL, busy: false, ...since };
2488
+ if (!isAtWork(view)) return null;
2489
+ return { label: activityLabel(view), busy: true, ...since };
2490
+ }
2491
+
2492
+ // src/conversation/elapsed.ts
2493
+ function formatElapsed(ms) {
2494
+ if (!Number.isFinite(ms) || ms < 0) return "";
2495
+ const seconds = Math.floor(ms / 1e3);
2496
+ if (seconds < 60) return `${seconds}s`;
2497
+ const minutes = Math.floor(seconds / 60);
2498
+ if (minutes < 60) return `${minutes}m ${String(seconds % 60).padStart(2, "0")}s`;
2499
+ return `${Math.floor(minutes / 60)}h ${String(minutes % 60).padStart(2, "0")}m`;
2500
+ }
2501
+ function elapsedSince(startedAt, now) {
2502
+ return startedAt === void 0 ? "" : formatElapsed(now - Date.parse(startedAt));
2503
+ }
2504
+
2380
2505
  // src/models/Handoff.ts
2381
2506
  var SEVERITY_LABEL = {
2382
2507
  blocker: "Blocker",
@@ -2395,16 +2520,23 @@ function worstSeverity(findings) {
2395
2520
  }
2396
2521
  return worst;
2397
2522
  }
2523
+ var ROOT_NODE = "root";
2524
+ function nodeText(node) {
2525
+ return node.startsWith(`${ROOT_NODE}/`) ? node.slice(ROOT_NODE.length + 1) : node;
2526
+ }
2527
+ function findingRefText(task, ref) {
2528
+ return `${task}${ref.attempt !== void 0 ? `@${ref.attempt}` : ""}${ref.finding ? `/${ref.finding}` : ""}`;
2529
+ }
2398
2530
  function handoffReferenceText(ref, taskName = () => void 0) {
2399
2531
  switch (ref.kind) {
2400
2532
  case "file":
2401
- return `${ref.line !== void 0 ? `${ref.path}:${ref.line}` : ref.path}${ref.resolved === true ? "" : " (unresolved)"}`;
2533
+ return `${onOneLine(ref.line !== void 0 ? `${ref.path}:${ref.line}` : ref.path)}${ref.resolved === true ? "" : " (unresolved)"}`;
2402
2534
  case "commit":
2403
- return `commit ${ref.sha}${ref.repo ? ` in ${ref.repo}` : ""}${ref.resolved === true ? "" : " (unresolved)"}`;
2535
+ return `commit ${ref.sha}${ref.repo ? ` in ${onOneLine(ref.repo)}` : ""}${ref.resolved === true ? "" : " (unresolved)"}`;
2404
2536
  case "task":
2405
- return `task ${taskName(ref.task) ?? ref.task}${ref.finding ? ` ${ref.finding}` : ""}`;
2537
+ return onOneLine(findingRefText(ref.label !== void 0 ? `${nodeText(ref.node ?? ROOT_NODE)}:${ref.label}` : taskName(ref.task) ?? ref.task, ref));
2406
2538
  case "url":
2407
- return ref.url;
2539
+ return onOneLine(ref.url);
2408
2540
  case "patch":
2409
2541
  return patchText(ref);
2410
2542
  }
@@ -2424,7 +2556,7 @@ function byteSize(bytes) {
2424
2556
  }
2425
2557
  function patchFlagText(flag) {
2426
2558
  const more = flag.count - flag.paths.length;
2427
- return `${FLAG_WORDS[flag.kind]}: ${counted(flag.count, "file")}${flag.paths.length ? ` (${flag.paths.join(", ")}${more > 0 ? `, +${more} more` : ""})` : ""}`;
2559
+ return `${FLAG_WORDS[flag.kind]}: ${counted(flag.count, "file")}${flag.paths.length ? ` (${flag.paths.map(onOneLine).join(", ")}${more > 0 ? `, +${more} more` : ""})` : ""}`;
2428
2560
  }
2429
2561
  function patchChangesText(patch) {
2430
2562
  const binary = patch.binary > 0 ? `, ${patch.binary} binary` : "";
@@ -2455,6 +2587,9 @@ function savedPatchViews(handoff) {
2455
2587
  function savedPatchView(handoff) {
2456
2588
  return savedPatchViews(handoff)[0] ?? null;
2457
2589
  }
2590
+ function heldWords(text2) {
2591
+ return splitLines(text2).map((line) => line ? ` ${line}` : line);
2592
+ }
2458
2593
 
2459
2594
  // src/conversation/labels.ts
2460
2595
  var APPROVAL_KIND_TEXT = {
@@ -2579,18 +2714,18 @@ function cutOff(gate, input) {
2579
2714
  return turnId === void 0 || turnId === gate.stopped;
2580
2715
  }
2581
2716
  function withGate(live2, gate) {
2582
- return gate.open === live2.gate.open && gate.stopped === live2.gate.stopped ? live2 : { ...live2, gate };
2717
+ return gate.open === live2.gate.open && gate.stopped === live2.gate.stopped && gate.openedAt === live2.gate.openedAt ? live2 : { ...live2, gate };
2583
2718
  }
2584
2719
  function followTurn(view, gate, input) {
2585
2720
  const live2 = { view, gate };
2586
2721
  if (input.type === "planner_turn_started") {
2587
- return withGate({ view: reduceConversation(view, input), gate }, { open: input.turnId, stopped: null });
2722
+ return withGate({ view: reduceConversation(view, input), gate }, { open: input.turnId, stopped: null, ...input.startedAt ? { openedAt: input.startedAt } : {} });
2588
2723
  }
2589
2724
  if (cutOff(gate, input)) {
2590
2725
  return input.type === "planner_turn_ended" ? withGate(live2, { ...gate, stopped: null }) : live2;
2591
2726
  }
2592
2727
  const next = { view: reduceConversation(view, input), gate };
2593
- return input.type === "planner_turn_ended" && input.turnId === gate.open ? withGate(next, { ...gate, open: null }) : next;
2728
+ return input.type === "planner_turn_ended" && input.turnId === gate.open ? withGate(next, { open: null, stopped: gate.stopped }) : next;
2594
2729
  }
2595
2730
  function stopTurn(view, gate) {
2596
2731
  if (gate.open === null) return { view, gate };
@@ -2599,9 +2734,16 @@ function stopTurn(view, gate) {
2599
2734
  gate: { open: null, stopped: gate.open }
2600
2735
  };
2601
2736
  }
2737
+ function closeTurn(gate) {
2738
+ return gate.open === null ? gate : { open: null, stopped: gate.stopped };
2739
+ }
2602
2740
 
2603
2741
  // src/services/WakePolicy.ts
2604
2742
  var REPORT_LEAD = ", whose result you asked for, has ended.";
2743
+ var RIDE_ALONG_CHARS = 120;
2744
+ var LEFT_OUT_EVENTS = 8;
2745
+ var LEFT_OUT_ROOM = 100 + LEFT_OUT_EVENTS * (RIDE_ALONG_CHARS + 1);
2746
+ var UNKNOWN_CACHE_TTL_MS = 5 * 6e4;
2605
2747
 
2606
2748
  // src/conversation/wakeUp.ts
2607
2749
  var DIGEST_HEAD = "Run update:";
@@ -2755,8 +2897,9 @@ var PAUSED = (t) => t.status === "awaiting_user" && t.awaitingReason === "usage-
2755
2897
  var RESUMES = (t) => PAUSED(t) && !!t.resumeAt;
2756
2898
  var RESUMABLE = (t) => PAUSED(t) && t.continuable === true;
2757
2899
  var HOLDS_UP = (t) => t.status === "failed" || t.status === "blocked" || t.status === "awaiting_user";
2900
+ var STOPPABLE = (t) => t.status === "in_progress" || !!t.repairWaits;
2758
2901
  var TASK_RULES = [
2759
- ["cancel", (t) => t.status === "in_progress"],
2902
+ ["cancel", STOPPABLE],
2760
2903
  ["resume-now", RESUMABLE],
2761
2904
  ["cancel-resume", RESUMES],
2762
2905
  ["skip", HOLDS_UP],
@@ -2767,7 +2910,7 @@ var TASK_RULES = [
2767
2910
  ["uncomplete", (t) => t.status === "completed"]
2768
2911
  ];
2769
2912
  var SUBTASK_RULES = [
2770
- ["cancel", (t) => t.status === "in_progress"],
2913
+ ["cancel", STOPPABLE],
2771
2914
  ["resume-now", RESUMABLE],
2772
2915
  ["cancel-resume", RESUMES],
2773
2916
  ["complete", (t) => t.status === "in_progress" && t.type === "ai"],
@@ -2818,11 +2961,11 @@ function opsEditable(task) {
2818
2961
 
2819
2962
  // src/services/AssignmentScope.ts
2820
2963
  function assignedRunnerOf(task) {
2821
- return task.type === "ai" ? task.assignedRunner || void 0 : void 0;
2964
+ return task.type === "ai" || task.type === "delegated" ? task.assignedRunner || void 0 : void 0;
2822
2965
  }
2823
2966
  var OVER = /* @__PURE__ */ new Set(["completed", "skipped"]);
2824
2967
  function assignmentIssue(task, scope) {
2825
- if (task.type !== "ai" || OVER.has(task.status)) return null;
2968
+ if (task.type !== "ai" && task.type !== "delegated" || OVER.has(task.status)) return null;
2826
2969
  if (!scope.enabledRunners.includes(task.assignedRunner)) return { kind: "runner-off", runner: task.assignedRunner };
2827
2970
  const model = task.assignedModel;
2828
2971
  const allowed = effectiveAllowlist(scope.allowlist[task.assignedRunner], task.assignedRunner, scope.models);
@@ -2844,6 +2987,54 @@ function assignmentConsequence({ status, awaitingReason, resumeAt }) {
2844
2987
  return "runs as assigned unless moved";
2845
2988
  }
2846
2989
 
2990
+ // src/taskRow/delegated.ts
2991
+ var STOPPING_LABEL = "Stopping: its child plan is still winding down.";
2992
+ function countsText({ completed, running, waiting, pending, failed, skipped }) {
2993
+ const total = completed + running + waiting + pending + failed + skipped;
2994
+ const said = [[running, "running"], [waiting, "waiting"], [failed, "failed"], [skipped, "skipped"]];
2995
+ return [`${completed} of ${total} done`, ...said.filter(([n]) => n > 0).map(([n, word]) => `${n} ${word}`)].join(", ");
2996
+ }
2997
+ function reported(handoff) {
2998
+ const counts = handoff?.subtree?.counts;
2999
+ return counts && { completed: counts.done, running: 0, waiting: 0, pending: counts.blocked, failed: counts.failed, skipped: counts.skipped };
3000
+ }
3001
+ function delegatedRowView(task) {
3002
+ if (task.type !== "delegated") return null;
3003
+ const { delegation } = task;
3004
+ const counts = delegation?.tasks ?? reported(task.handoff);
3005
+ return {
3006
+ goal: task.goal?.trim() || null,
3007
+ tokens: delegation?.tokens ? `${formatTokenCount(delegation.tokens.left)} of ${formatTokenCount(delegation.tokens.budget)} tokens left` : null,
3008
+ counts: counts ? countsText(counts) : null,
3009
+ stopping: delegation?.stopping ? STOPPING_LABEL : null
3010
+ };
3011
+ }
3012
+ var SEVERITIES = ["blocker", "major", "minor", "info"];
3013
+ function itemView({ ref, finding }) {
3014
+ return {
3015
+ reference: ref ? handoffReferenceText(ref) : null,
3016
+ heading: `${finding.id} \xB7 ${severityLabel(finding.severity)} \xB7 ${onOneLine(finding.title)}`,
3017
+ ...finding.detail ? { detail: finding.detail } : {}
3018
+ };
3019
+ }
3020
+ function subtreeView(subtree) {
3021
+ const { counts, findings, outsideScope } = subtree;
3022
+ const ran = [["done", counts.done], ["failed", counts.failed], ["blocked", counts.blocked], ["skipped", counts.skipped]].filter(([, n]) => n > 0).map(([word, n]) => `${n} ${word}`).join(", ");
3023
+ const found = SEVERITIES.filter((severity) => findings[severity] > 0).map((severity) => `${findings[severity]} ${severity}`).join(", ");
3024
+ const summary = [
3025
+ ran || "nothing ran",
3026
+ ...counts.commits > 0 ? [`${counts.commits} commit${counts.commits === 1 ? "" : "s"}`] : [],
3027
+ `${formatTokenCount(counts.tokens)} tokens`,
3028
+ found ? `${found} finding${SEVERITIES.reduce((n, s) => n + findings[s], 0) === 1 ? "" : "s"} below` : "no findings below"
3029
+ ].join(" \xB7 ");
3030
+ return {
3031
+ summary,
3032
+ outsideScope: outsideScope && outsideScope.count > 0 ? `Changed outside its declared scope: ${outsideScope.paths.map(onOneLine).join(", ")}${outsideScope.count > outsideScope.paths.length ? ` (+${outsideScope.count - outsideScope.paths.length} more)` : ""}` : null,
3033
+ open: subtree.open.map(itemView),
3034
+ promoted: subtree.promoted.map(itemView)
3035
+ };
3036
+ }
3037
+
2847
3038
  // src/taskRow/loop.ts
2848
3039
  function loopCheckState(check, goesOn) {
2849
3040
  switch (check.status) {
@@ -2914,17 +3105,23 @@ function blockedBy(task, reading) {
2914
3105
  if (!reading || !NOT_STARTED.has(task.status)) return [];
2915
3106
  return reading.blocks.blocked.get(task.id) ?? [];
2916
3107
  }
3108
+ function strandedDetail(check, dependencies, reading) {
3109
+ const status = (id) => reading?.tasks.find((t) => t.id === id)?.status;
3110
+ const landed = reading && check.loop.body.every((id) => status(id) === "completed");
3111
+ const finished = dependencies.every((id) => [void 0, "completed", "skipped"].includes(status(id)));
3112
+ return landed && finished ? `Nothing runs it now: start it for round ${loopRoundOf(check) + 1} of ${check.loop.maxRounds}` : "Nothing runs it now: execute the plan and the loop goes on";
3113
+ }
2917
3114
  function loopOf(task, reading) {
2918
3115
  const tasks = reading?.tasks;
2919
3116
  if (task.loop) {
2920
3117
  const check2 = { id: task.id, status: task.status, loop: task.loop, loopRound: task.loopRound, ...task.verdict ? { verdict: task.verdict } : {} };
2921
- const state = loopCheckState(check2, reading ? reading.blocks.repeating.has(task.id) : true);
3118
+ const state = loopCheckState(check2, !task.loopStranded && (reading ? reading.blocks.repeating.has(task.id) : true));
2922
3119
  const body = refsOf(task.loop.body, tasks);
2923
3120
  const halted = reading ? task.loop.body.filter((id) => {
2924
3121
  const status = reading.tasks.find((t) => t.id === id)?.status;
2925
3122
  return status === "failed" || status === "skipped" || reading.blocks.blocked.has(id);
2926
3123
  }) : [];
2927
- const detail = state === "repeating" ? `Found problems: runs again once ${body.join(", ")} ${body.length === 1 ? "has" : "have"} landed` : state === "stopped" ? `${refsOf(halted, tasks).join(", ")} did not pass: retry ${halted.length === 1 ? "it" : "them"} and the loop goes on` : null;
3124
+ const detail = state === "repeating" ? `Found problems: runs again once ${body.join(", ")} ${body.length === 1 ? "has" : "have"} landed` : state === "stopped" ? task.loopStranded ? strandedDetail(check2, task.dependencies, reading) : `${refsOf(halted, tasks).join(", ")} did not pass: retry ${halted.length === 1 ? "it" : "them"} and the loop goes on` : null;
2928
3125
  return { role: "check", state, label: loopCheckLabel(check2, state), detail, body };
2929
3126
  }
2930
3127
  const owner = reading && checkOf(reading.tasks, task.id);
@@ -2958,9 +3155,10 @@ function taskRowView(task, context = {}) {
2958
3155
  const blocked = blockedBy(task, reading);
2959
3156
  const loop = loopOf(task, reading);
2960
3157
  return {
3158
+ delegated: delegatedRowView(task),
2961
3159
  usage: latestAttempt ? { totals: spend.totals, ...spend.contextFill ? { contextFill: spend.contextFill } : {}, attempt: latestAttempt.attempt } : task.type === "ai" && ["completed", "failed", "in_progress", "awaiting_user"].includes(task.status) ? { totals: {}, attempt: 0 } : null,
2962
3160
  orderLabel: taskOrderLabel(task, parent),
2963
- kind: task.type === "user" ? "user" : task.type === "script" ? "script" : task.ops ? "ops" : "ai",
3161
+ kind: task.type === "user" ? "user" : task.type === "script" ? "script" : task.type === "delegated" ? "delegated" : task.ops ? "ops" : "ai",
2964
3162
  // Between rounds a check waits for its fix as a task waits for its dependencies, and is no failure (ADR-0045 L3).
2965
3163
  status: blocked.length > 0 ? "blocked" : loop?.role === "check" && loop.state === "repeating" ? "todo" : taskStatusKind(task),
2966
3164
  running: isTaskRunning(task),
@@ -2977,7 +3175,8 @@ function taskRowView(task, context = {}) {
2977
3175
  ...flagOf(task, context.runnerScope),
2978
3176
  autonomous: task.type === "ai" && context.modes?.find((m) => m.id === task.taskMode)?.autonomous === true,
2979
3177
  repos: namedRepos(isolation?.repos),
2980
- conflict: isolation?.state === "conflict" ? { repo: namedRepo(isolation.conflictRepo), files: filesOf(isolation.conflictFiles) } : null,
3178
+ conflict: isolation?.state === "conflict" && !isolation.repairWaits ? { repo: namedRepo(isolation.conflictRepo), files: filesOf(isolation.conflictFiles), resolver: isolation.resolver ? refsOf([isolation.resolver], context.tasks)[0] : null } : null,
3179
+ repairWaiting: isolation?.state === "conflict" && isolation.repairWaits ? { label: repairWaitLabel(isolation.repairWaits), files: filesOf(isolation.conflictFiles) } : null,
2981
3180
  repairing: isolation?.state === "repairing" ? { files: filesOf(isolation.conflictFiles), attempt: isolation.repair ?? null } : null,
2982
3181
  repaired: isolation?.repairedFiles?.length ? { files: capConflictFiles(isolation.repairedFiles), landed: isolation.state === "integrated" } : null,
2983
3182
  mergeGate: task.mergeGate?.length ? refsOf(task.mergeGate, context.tasks) : null,
@@ -2989,7 +3188,9 @@ function taskRowView(task, context = {}) {
2989
3188
  handoff: handoffOf(task),
2990
3189
  dependencies: refsOf(task.dependencies, context.tasks),
2991
3190
  // A block read off the plan offers what a stored one does: Skip among them.
2992
- actions: taskRowActions(blocked.length > 0 ? { ...task, status: "blocked" } : task, context.placement ?? (parent ? "subtask" : "task")),
3191
+ actions: taskRowActions({ ...task, ...blocked.length > 0 ? { status: "blocked" } : {}, ...isolation?.repairWaits ? { repairWaits: isolation.repairWaits } : {} }, context.placement ?? (parent ? "subtask" : "task")),
3192
+ // Read off the mark itself: a task with merges left and no record has state `none`.
3193
+ revertible: task.isolation?.revertible === true,
2993
3194
  mark: markAction(task),
2994
3195
  opsEditable: opsEditable(task)
2995
3196
  };
@@ -3005,7 +3206,7 @@ var STATE_LABEL = {
3005
3206
  done: "Done",
3006
3207
  failed: "Failed",
3007
3208
  running: "Running",
3008
- quiet: "Stalled",
3209
+ quiet: STALLED_LABEL,
3009
3210
  awaiting: "Waiting for your input",
3010
3211
  blocked: "Blocked",
3011
3212
  skipped: "Skipped",
@@ -3022,6 +3223,7 @@ function stateOf(task, follow, approvals) {
3022
3223
  return { kind: task.awaitingReason === "checkpoint" ? "checkpoint" : "awaiting", label: awaitingLabel(task) ?? STATE_LABEL.awaiting };
3023
3224
  }
3024
3225
  if (task.status === "blocked") return { kind: "blocked", label: STATE_LABEL.blocked };
3226
+ if (task.repairWaits) return { kind: "todo", label: repairWaitLabel(task.repairWaits) };
3025
3227
  if (follow.view.lastTurnEnd === "failed") return { kind: "failed", label: "Turn failed" };
3026
3228
  if (follow.view.lastTurnEnd === "interrupted") return { kind: "todo", label: "Interrupted" };
3027
3229
  const kind = taskStatusKind(task);
@@ -3063,7 +3265,8 @@ function taskLogCommands(view) {
3063
3265
  }
3064
3266
  function logContinues(task) {
3065
3267
  const finished = task.status === "completed" || task.status === "failed" || task.status === "skipped";
3066
- return task.continuable === true && (finished || task.status === "awaiting_user" && task.awaitingReason === "usage-limit");
3268
+ const childLeft = task.type === "delegated" && (task.status === "pending" || task.awaitingReason === "question-lost");
3269
+ return task.continuable === true && (finished || childLeft || task.status === "awaiting_user" && task.awaitingReason === "usage-limit");
3067
3270
  }
3068
3271
  function logResumes(task) {
3069
3272
  return task.continuable === true && task.status === "awaiting_user" && task.awaitingReason === "usage-limit";
@@ -3101,6 +3304,14 @@ function pastGateConfirmation(unmerged, subject = "This task") {
3101
3304
  function manualOverrideConfirmation(direction, label) {
3102
3305
  return direction === "complete" ? `Mark ${label} complete? You vouch for its work although no passing verdict said it was done. Any changes it kept may land in your run, and the tasks that depend on it are released to start on a future run.` : `Mark ${label} not done? This clears its completion and holds it until you retry or start it. The work it did stays where it is, and tasks that already ran on its result are not undone.`;
3103
3306
  }
3307
+ var revertEffect = "Its landed work comes off the integration branch, newest first, and each task listed is held as not started until you retry it. Nothing in your own branch changes.";
3308
+ function revertTaskRef(task) {
3309
+ return task.ref ?? `#${task.order}`;
3310
+ }
3311
+ function revertListLine(task) {
3312
+ const repos = task.repos.length === 1 && task.repos[0] === "." ? "" : ` (${task.repos.join(", ")})`;
3313
+ return `${revertTaskRef(task)} ${task.title}${repos}${task.dependent ? " (goes with it)" : ""}`;
3314
+ }
3104
3315
  function manualOverrideStopFirst(direction, label) {
3105
3316
  return `${label.charAt(0).toUpperCase()}${label.slice(1)} cannot be marked ${direction === "complete" ? "complete" : "not done"} while the plan is starting, running or waiting to resume, because the run could still move it on. Stop the run first, and mark it once everything has stopped.`;
3106
3317
  }
@@ -3114,7 +3325,7 @@ function noExecutorRefusal(type, manual, script) {
3114
3325
  }
3115
3326
 
3116
3327
  // src/services/runView.ts
3117
- var EMPTY_RUN = { tasks: [], runMerge: null, handoff: null, mergeResult: null, activity: IDLE_ACTIVITY };
3328
+ var EMPTY_RUN = { tasks: [], runMerge: null, handoff: null, mergeResult: null, activity: IDLE_ACTIVITY, escalations: [] };
3118
3329
 
3119
3330
  // src/models/AccountLimits.ts
3120
3331
  function hasAccountLimits(snapshot) {
@@ -3169,6 +3380,7 @@ function accountLimitsTitle(snapshot, time) {
3169
3380
  0 && (module.exports = {
3170
3381
  CHECKPOINT_TRUNCATE_LENGTH,
3171
3382
  DEFAULT_RUNNERS,
3383
+ DELEGATION_OFFERED,
3172
3384
  EMPTY_CONVERSATION,
3173
3385
  EMPTY_HOLD,
3174
3386
  EMPTY_RUN,
@@ -3180,6 +3392,8 @@ function accountLimitsTitle(snapshot, time) {
3180
3392
  PLANNED_WITH_LABEL,
3181
3393
  REPORT_PREVIEW_LINES,
3182
3394
  SEVERITY_LABEL,
3395
+ STALLED_LABEL,
3396
+ STOPPING_LABEL,
3183
3397
  SUPERVISOR_LEVEL_LABEL,
3184
3398
  WAITS_FOR_APPROVAL_LABEL,
3185
3399
  accountLimitPercentText,
@@ -3187,6 +3401,7 @@ function accountLimitsTitle(snapshot, time) {
3187
3401
  accountLimitsOf,
3188
3402
  accountLimitsText,
3189
3403
  accountLimitsTitle,
3404
+ activityLabel,
3190
3405
  addAttemptUsage,
3191
3406
  addModelUsage,
3192
3407
  addPlannerUsage,
@@ -3214,12 +3429,14 @@ function accountLimitsTitle(snapshot, time) {
3214
3429
  cardEditable,
3215
3430
  checkOf,
3216
3431
  clampThinkingEffort,
3432
+ closeTurn,
3217
3433
  compactionText,
3218
3434
  confirmedOverride,
3219
3435
  contextMeterText,
3220
3436
  contextMeterTitle,
3221
3437
  costText,
3222
3438
  countedSessionCost,
3439
+ delegatedRowView,
3223
3440
  dependencyCandidates,
3224
3441
  dependentsNotice,
3225
3442
  dependentsOf,
@@ -3230,10 +3447,12 @@ function accountLimitsTitle(snapshot, time) {
3230
3447
  diffSummary,
3231
3448
  drainNext,
3232
3449
  editableWhileRunning,
3450
+ elapsedSince,
3233
3451
  endAttemptUsage,
3234
3452
  followTaskLog,
3235
3453
  followTurn,
3236
3454
  formatCost,
3455
+ formatElapsed,
3237
3456
  formatTokenCount,
3238
3457
  fromTranscript,
3239
3458
  handoffBaseLine,
@@ -3244,6 +3463,7 @@ function accountLimitsTitle(snapshot, time) {
3244
3463
  hasAccountLimits,
3245
3464
  hasHiddenDetail,
3246
3465
  hasLongReport,
3466
+ heldWords,
3247
3467
  holdLabel,
3248
3468
  holdPrompt,
3249
3469
  isFileEditTool,
@@ -3267,10 +3487,12 @@ function accountLimitsTitle(snapshot, time) {
3267
3487
  markdownHtml,
3268
3488
  markdownTokens,
3269
3489
  mergeOutcome,
3490
+ mergePastChecksConfirmation,
3270
3491
  modelCostTitle,
3271
3492
  namedRepos,
3272
3493
  newTaskFields,
3273
3494
  noExecutorRefusal,
3495
+ onOneLine,
3274
3496
  opsEditable,
3275
3497
  outOfRounds,
3276
3498
  outputLines,
@@ -3289,6 +3511,7 @@ function accountLimitsTitle(snapshot, time) {
3289
3511
  reconcileApprovals,
3290
3512
  reduceConversation,
3291
3513
  reduceTaskLog,
3514
+ repairWaitLabel,
3292
3515
  repairedLanded,
3293
3516
  repairedNotice,
3294
3517
  repeatingChecks,
@@ -3300,6 +3523,9 @@ function accountLimitsTitle(snapshot, time) {
3300
3523
  resumeLabel,
3301
3524
  resumeTime,
3302
3525
  resumedSessionWindow,
3526
+ revertEffect,
3527
+ revertListLine,
3528
+ revertTaskRef,
3303
3529
  runHoldsEditors,
3304
3530
  runnerToolSubject,
3305
3531
  savedPatchView,
@@ -3308,13 +3534,16 @@ function accountLimitsTitle(snapshot, time) {
3308
3534
  severityLabel,
3309
3535
  skillTokens,
3310
3536
  skippedLabel,
3537
+ spentTokens,
3311
3538
  startAttemptUsage,
3312
3539
  stopTurn,
3313
3540
  subagentCostTitle,
3314
3541
  subtreeIds,
3542
+ subtreeView,
3315
3543
  summarizeToolCall,
3316
3544
  takeAt,
3317
3545
  taskActionCommand,
3546
+ taskActivity,
3318
3547
  taskChatAvailable,
3319
3548
  taskLogCommands,
3320
3549
  taskLogHeaderView,