@ordewell/core 0.7.0 → 0.7.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 (55) hide show
  1. package/dist/{IFileSystem-DgpX0BU7.d.mts → IFileSystem-B5asBRDa.d.mts} +1 -1
  2. package/dist/{IFileSystem-D4ADfTrX.d.ts → IFileSystem-CbCmUDBn.d.ts} +1 -1
  3. package/dist/{ModeResolver-Cv01ZDd9.d.mts → ModeResolver-DcqAho4y.d.mts} +1 -1
  4. package/dist/{ModeResolver-BEcRAz1c.d.ts → ModeResolver-DtfhWeVL.d.ts} +1 -1
  5. package/dist/{Task-CoKhvBa1.d.mts → Task-BpzIbunq.d.mts} +146 -22
  6. package/dist/{Task-CoKhvBa1.d.ts → Task-BpzIbunq.d.ts} +146 -22
  7. package/dist/{chunk-LSGY7AIZ.mjs → chunk-AJ5KDO6V.mjs} +219 -77
  8. package/dist/chunk-AJ5KDO6V.mjs.map +1 -0
  9. package/dist/chunk-H5O74L77.mjs +185 -0
  10. package/dist/chunk-H5O74L77.mjs.map +1 -0
  11. package/dist/{chunk-YU4UKKKI.mjs → chunk-MZYZS7B3.mjs} +14 -186
  12. package/dist/chunk-MZYZS7B3.mjs.map +1 -0
  13. package/dist/{chunk-J3YSTPCE.mjs → chunk-OUIQWNS3.mjs} +8 -5
  14. package/dist/chunk-OUIQWNS3.mjs.map +1 -0
  15. package/dist/{chunk-N66ZHFGN.mjs → chunk-OYUSADFM.mjs} +11 -1
  16. package/dist/chunk-OYUSADFM.mjs.map +1 -0
  17. package/dist/{chunk-HPNUFBIT.mjs → chunk-V3JHS7AX.mjs} +9 -1
  18. package/dist/chunk-V3JHS7AX.mjs.map +1 -0
  19. package/dist/index.d.mts +909 -459
  20. package/dist/index.d.ts +909 -459
  21. package/dist/index.js +5671 -3776
  22. package/dist/index.js.map +1 -1
  23. package/dist/index.mjs +5548 -3795
  24. package/dist/index.mjs.map +1 -1
  25. package/dist/order-labels.d.mts +15 -2
  26. package/dist/order-labels.d.ts +15 -2
  27. package/dist/order-labels.js +12 -2
  28. package/dist/order-labels.js.map +1 -1
  29. package/dist/order-labels.mjs +7 -3
  30. package/dist/{parsing-DMdOq-BV.d.ts → parsing-COFGUEWx.d.ts} +2 -2
  31. package/dist/{parsing-B4OCHH1_.d.mts → parsing-D0uo-Icd.d.mts} +2 -2
  32. package/dist/parsing.d.mts +3 -3
  33. package/dist/parsing.d.ts +3 -3
  34. package/dist/parsing.js +6 -3
  35. package/dist/parsing.js.map +1 -1
  36. package/dist/parsing.mjs +4 -3
  37. package/dist/{plan-utils-CD1Xu65s.d.mts → plan-utils-CdW3mxt5.d.mts} +226 -9
  38. package/dist/{plan-utils-BdYPRBno.d.ts → plan-utils-D4Z8UyLL.d.ts} +226 -9
  39. package/dist/plan-utils.d.mts +4 -3
  40. package/dist/plan-utils.d.ts +4 -3
  41. package/dist/plan-utils.js +210 -3
  42. package/dist/plan-utils.js.map +1 -1
  43. package/dist/plan-utils.mjs +44 -3
  44. package/dist/testing.d.mts +17 -5
  45. package/dist/testing.d.ts +17 -5
  46. package/dist/testing.js +50 -3
  47. package/dist/testing.js.map +1 -1
  48. package/dist/testing.mjs +50 -5
  49. package/dist/testing.mjs.map +1 -1
  50. package/package.json +1 -1
  51. package/dist/chunk-HPNUFBIT.mjs.map +0 -1
  52. package/dist/chunk-J3YSTPCE.mjs.map +0 -1
  53. package/dist/chunk-LSGY7AIZ.mjs.map +0 -1
  54. package/dist/chunk-N66ZHFGN.mjs.map +0 -1
  55. package/dist/chunk-YU4UKKKI.mjs.map +0 -1
@@ -1,16 +1,25 @@
1
1
  import {
2
2
  PlanParseError,
3
3
  TASK_OPS_ENVELOPE_KEY,
4
- addTaskToPlan,
5
- createTask,
6
4
  escapeControlCharsInStrings,
7
5
  extractObjectsWithKey,
6
+ stripTrailingCommas
7
+ } from "./chunk-H5O74L77.mjs";
8
+ import {
9
+ addTaskToPlan,
10
+ createTask,
8
11
  flattenTasks,
12
+ inheritedOps,
13
+ opsFlag,
9
14
  removeTaskFromPlan,
10
15
  renumberTasks,
11
- stripTrailingCommas,
12
16
  updateTaskInPlan
13
- } from "./chunk-YU4UKKKI.mjs";
17
+ } from "./chunk-MZYZS7B3.mjs";
18
+ import {
19
+ taskOrderLabel,
20
+ taskRef,
21
+ titledTaskRef
22
+ } from "./chunk-V3JHS7AX.mjs";
14
23
 
15
24
  // src/models/Usage.ts
16
25
  function partedPromptUsage(parts) {
@@ -731,9 +740,25 @@ function endTurn(view, { reason }) {
731
740
  const closed = closeOpenBlocks({ ...view, working: false, lastTurnEnd: reason, streams: {} }, CUT[reason]);
732
741
  return reason === "interrupted" ? append(closed, (id) => settledMessage(id, "system", "Interrupted.")) : closed;
733
742
  }
734
- function queueMessage(view, { messageId, text: text2 }) {
735
- if (view.queued.some((m) => m.id === messageId)) return view;
736
- return { ...view, queued: [...view.queued, { id: messageId, text: text2 }] };
743
+ function queueMessage(view, { messageId, text: text2, forced }) {
744
+ const listed = view.queued.find((m) => m.id === messageId);
745
+ if (forced) {
746
+ const rest = view.queued.filter((m) => m !== listed);
747
+ const at = rest.findIndex((m) => !m.forced);
748
+ const placed = at < 0 ? rest.length : at;
749
+ return { ...view, queued: [...rest.slice(0, placed), { id: messageId, text: text2, forced: true }, ...rest.slice(placed)] };
750
+ }
751
+ if (!listed) return { ...view, queued: [...view.queued, { id: messageId, text: text2 }] };
752
+ if (!listed.handedOver) return view;
753
+ return { ...view, queued: view.queued.map((m) => m === listed ? { id: m.id, text: m.text } : m) };
754
+ }
755
+ function handOver(view, { messageId }) {
756
+ const listed = view.queued.find((m) => m.id === messageId);
757
+ if (!listed || listed.handedOver) return view;
758
+ return { ...view, queued: view.queued.map((m) => m === listed ? { ...m, handedOver: true } : m) };
759
+ }
760
+ function deliverMidTurn(view, event) {
761
+ return appendOutput(unqueueMessage(view, event), null, (id) => settledMessage(id, "user", event.text));
737
762
  }
738
763
  function unqueueMessage(view, { messageId }) {
739
764
  const queued = view.queued.filter((m) => m.id !== messageId);
@@ -767,6 +792,12 @@ function reduceTaskLog(view, event) {
767
792
  return queueMessage(view, event);
768
793
  case "message_removed":
769
794
  return unqueueMessage(view, event);
795
+ case "message_handed_over":
796
+ return handOver(view, event);
797
+ case "message_delivered":
798
+ return deliverMidTurn(view, event);
799
+ case "message_undelivered":
800
+ return append(unqueueMessage(view, event), (id) => settledMessage(id, "system", `${event.text} \xB7 not delivered`));
770
801
  case "error":
771
802
  return appendOutput(view, null, (id) => settledMessage(id, "error", event.message));
772
803
  case "approval_requested":
@@ -893,6 +924,37 @@ function coerceAssignments(tasks, perRunnerAllowlist, allowedRunners, modelsByRu
893
924
  });
894
925
  }
895
926
 
927
+ // src/taskRow/status.ts
928
+ var isTaskRunning = (task) => task.status === "in_progress" || task.status === "running";
929
+ var NOT_STARTED = /* @__PURE__ */ new Set(["pending", "approved", "blocked"]);
930
+ function taskStatusKind(task) {
931
+ switch (task.status) {
932
+ case "completed":
933
+ return "done";
934
+ case "failed":
935
+ return "failed";
936
+ case "blocked":
937
+ return "blocked";
938
+ case "awaiting_user":
939
+ return "awaiting";
940
+ }
941
+ if (!isTaskRunning(task)) return "todo";
942
+ return task.status === "in_progress" && task.idleSince ? "quiet" : "running";
943
+ }
944
+ var AWAITING_LABELS = {
945
+ input: "Waiting for your input",
946
+ checkpoint: "Checkpoint",
947
+ conflict: "Merge conflict",
948
+ "files-changed": "Changed tracked files"
949
+ };
950
+ function awaitingLabel(task) {
951
+ return task.status === "awaiting_user" && task.awaitingReason ? AWAITING_LABELS[task.awaitingReason] : null;
952
+ }
953
+ function approvalLabel(count) {
954
+ if (!count) return null;
955
+ return count > 1 ? `Waiting for approval (${count})` : "Waiting for approval";
956
+ }
957
+
896
958
  // src/services/TaskOps.ts
897
959
  import { v4 as uuidv4 } from "uuid";
898
960
 
@@ -934,7 +996,6 @@ function typeCoherenceCheck(target, changes) {
934
996
  }
935
997
  return { ok: true, clear: target.userSteps && target.userSteps.length > 0 ? ["userSteps"] : [] };
936
998
  }
937
- var NOT_STARTED = /* @__PURE__ */ new Set(["pending", "approved", "blocked"]);
938
999
  function opsCheck(tasks, target, changes) {
939
1000
  if (!("ops" in changes) || !!changes.ops === !!target.ops) return null;
940
1001
  if (!NOT_STARTED.has(target.status)) {
@@ -1099,7 +1160,7 @@ function updatableChanges(raw) {
1099
1160
  for (const key of UPDATABLE_FIELDS) {
1100
1161
  if (raw && key in raw) changes[key] = raw[key];
1101
1162
  }
1102
- if ("ops" in changes) changes.ops = changes.ops === true ? true : void 0;
1163
+ if ("ops" in changes) changes.ops = opsFlag(changes.ops);
1103
1164
  return changes;
1104
1165
  }
1105
1166
  function findInTasks(tasks, id) {
@@ -1269,41 +1330,38 @@ function applyTaskOps(currentTasks, ops, runners, catalog) {
1269
1330
  }
1270
1331
  return { ids, bad };
1271
1332
  };
1333
+ const prepareEdit = (op, opIndex, label, audience, refuseRunning = false) => {
1334
+ const ref = resolveRef(op.taskId, originalFlatAll, flattenTasks(tasks), handleOwner, handleId, opIndex);
1335
+ if ("error" in ref) return { error: `${label}: ${ref.error}` };
1336
+ const target = findInTasks(tasks, ref.id);
1337
+ if (!target) return { error: `${label}: task "${op.taskId}" no longer exists in this batch (removed, merged, or split by an earlier op)` };
1338
+ if (refuseRunning && target.status === "in_progress") return { error: `${label}: "${target.title}" is running and cannot be re-armed` };
1339
+ const changes = updatableChanges(op.changes);
1340
+ if (changes.assignedRunner && !runners.includes(changes.assignedRunner)) {
1341
+ return { error: `${label}: runner "${changes.assignedRunner}" is not in this plan's runner set [${runners.join(", ")}]` };
1342
+ }
1343
+ const changesForCheck = { ...changes };
1344
+ delete changesForCheck.dependencies;
1345
+ const check = validateTaskEdit(audience, flattenTasks(tasks), target.id, changesForCheck, catalog);
1346
+ if (!check.ok) return { error: `${label}: ${check.error}` };
1347
+ for (const field of check.clear ?? []) changes[field] = void 0;
1348
+ if ("dependencies" in changes) {
1349
+ const { ids, bad } = resolveDeps(changes.dependencies, opIndex);
1350
+ if (bad.length) return { error: `${label}: unknown dependencies: ${bad.join(", ")}` };
1351
+ changes.dependencies = ids.filter((id) => id !== target.id);
1352
+ }
1353
+ return { target, changes, check };
1354
+ };
1272
1355
  for (const [i, op] of ops.entries()) {
1273
1356
  const label = `op ${i + 1} (${op.op})`;
1274
1357
  switch (op.op) {
1275
1358
  case "update": {
1276
- const ref = resolveRef(op.taskId, originalFlatAll, flattenTasks(tasks), handleOwner, handleId, i);
1277
- if ("error" in ref) {
1278
- errors.push(`${label}: ${ref.error}`);
1279
- break;
1280
- }
1281
- const target = findInTasks(tasks, ref.id);
1282
- if (!target) {
1283
- errors.push(`${label}: task "${op.taskId}" no longer exists in this batch (removed, merged, or split by an earlier op)`);
1284
- break;
1285
- }
1286
- const changes = updatableChanges(op.changes);
1287
- if (changes.assignedRunner && !runners.includes(changes.assignedRunner)) {
1288
- errors.push(`${label}: runner "${changes.assignedRunner}" is not in this plan's runner set [${runners.join(", ")}]`);
1289
- break;
1290
- }
1291
- const changesForCheck = { ...changes };
1292
- delete changesForCheck.dependencies;
1293
- const check = validateTaskEdit("planner", flattenTasks(tasks), target.id, changesForCheck, catalog);
1294
- if (!check.ok) {
1295
- errors.push(`${label}: ${check.error}`);
1359
+ const prep = prepareEdit(op, i, label, "planner");
1360
+ if ("error" in prep) {
1361
+ errors.push(prep.error);
1296
1362
  break;
1297
1363
  }
1298
- for (const field of check.clear ?? []) changes[field] = void 0;
1299
- if ("dependencies" in changes) {
1300
- const { ids, bad } = resolveDeps(changes.dependencies, i);
1301
- if (bad.length) {
1302
- errors.push(`${label}: unknown dependencies: ${bad.join(", ")}`);
1303
- break;
1304
- }
1305
- changes.dependencies = ids.filter((id) => id !== target.id);
1306
- }
1364
+ const { target, changes, check } = prep;
1307
1365
  if (Object.keys(changes).length === 0) {
1308
1366
  errors.push(`${label}: no valid changes provided`);
1309
1367
  break;
@@ -1400,7 +1458,7 @@ function applyTaskOps(currentTasks, ops, runners, catalog) {
1400
1458
  errors.push(`${label}: unknown task in merge list (already removed, merged, or split by an earlier op)`);
1401
1459
  break;
1402
1460
  }
1403
- const toMerge = resolved.map((t) => t).sort((a, b) => a.order - b.order);
1461
+ const toMerge = [...new Map(resolved.map((t) => [t.id, t])).values()].sort((a, b) => a.order - b.order);
1404
1462
  if (toMerge.length < 2) {
1405
1463
  errors.push(`${label}: merge needs at least two tasks`);
1406
1464
  break;
@@ -1435,7 +1493,7 @@ function applyTaskOps(currentTasks, ops, runners, catalog) {
1435
1493
  taskMode: spec.taskMode ?? toMerge[0].taskMode,
1436
1494
  autonomy: spec.autonomy ?? toMerge.find((t) => t.autonomy)?.autonomy,
1437
1495
  sliceType: spec.sliceType ?? toMerge.find((t) => t.sliceType)?.sliceType,
1438
- ops: spec.ops ?? toMerge.every((t) => t.ops),
1496
+ ops: inheritedOps(toMerge, spec.ops),
1439
1497
  userStoriesCovered: spec.userStoriesCovered ?? (toMerge.flatMap((t) => t.userStoriesCovered ?? []).length ? [...new Set(toMerge.flatMap((t) => t.userStoriesCovered ?? []))] : void 0)
1440
1498
  });
1441
1499
  const mergedId = mergedTask.id;
@@ -1516,7 +1574,7 @@ function applyTaskOps(currentTasks, ops, runners, catalog) {
1516
1574
  taskMode: spec.taskMode ?? target.taskMode,
1517
1575
  autonomy: spec.autonomy ?? target.autonomy,
1518
1576
  sliceType: spec.sliceType ?? target.sliceType,
1519
- ops: spec.ops ?? target.ops,
1577
+ ops: inheritedOps([target], spec.ops),
1520
1578
  userStoriesCovered: spec.userStoriesCovered ?? target.userStoriesCovered
1521
1579
  });
1522
1580
  newTasks.push(nt);
@@ -1538,41 +1596,12 @@ function applyTaskOps(currentTasks, ops, runners, catalog) {
1538
1596
  break;
1539
1597
  }
1540
1598
  case "rearm": {
1541
- const ref = resolveRef(op.taskId, originalFlatAll, flattenTasks(tasks), handleOwner, handleId, i);
1542
- if ("error" in ref) {
1543
- errors.push(`${label}: ${ref.error}`);
1599
+ const prep = prepareEdit(op, i, label, "direct", true);
1600
+ if ("error" in prep) {
1601
+ errors.push(prep.error);
1544
1602
  break;
1545
1603
  }
1546
- const target = findInTasks(tasks, ref.id);
1547
- if (!target) {
1548
- errors.push(`${label}: task "${op.taskId}" no longer exists in this batch (removed, merged, or split by an earlier op)`);
1549
- break;
1550
- }
1551
- if (target.status === "in_progress") {
1552
- errors.push(`${label}: "${target.title}" is running and cannot be re-armed`);
1553
- break;
1554
- }
1555
- const changes = updatableChanges(op.changes);
1556
- if (changes.assignedRunner && !runners.includes(changes.assignedRunner)) {
1557
- errors.push(`${label}: runner "${changes.assignedRunner}" is not in this plan's runner set [${runners.join(", ")}]`);
1558
- break;
1559
- }
1560
- const changesForCheck = { ...changes };
1561
- delete changesForCheck.dependencies;
1562
- const check = validateTaskEdit("direct", flattenTasks(tasks), target.id, changesForCheck, catalog);
1563
- if (!check.ok) {
1564
- errors.push(`${label}: ${check.error}`);
1565
- break;
1566
- }
1567
- for (const field of check.clear ?? []) changes[field] = void 0;
1568
- if ("dependencies" in changes) {
1569
- const { ids, bad } = resolveDeps(changes.dependencies, i);
1570
- if (bad.length) {
1571
- errors.push(`${label}: unknown dependencies: ${bad.join(", ")}`);
1572
- break;
1573
- }
1574
- changes.dependencies = ids.filter((id) => id !== target.id);
1575
- }
1604
+ const { target, changes, check } = prep;
1576
1605
  tasks = updateTaskInPlan(tasks, target.id, { ...changes, status: "pending", verdict: void 0, outputSummary: void 0, awaitingReason: void 0 });
1577
1606
  for (const dep of flattenTasks(tasks)) {
1578
1607
  if (dep.status === "blocked" && dep.dependencies.includes(target.id)) {
@@ -1720,7 +1749,7 @@ function serializeTask(t) {
1720
1749
  ...t.ops ? { ops: true } : {}
1721
1750
  };
1722
1751
  }
1723
- function serializeTaskStatus(t, idleSince = null, isolation = null, queued = [], awaitingApproval = 0, mergeGate = []) {
1752
+ function serializeTaskStatus(t, idleSince = null, isolation = null, queued = [], awaitingApproval = 0, mergeGate = [], checkpoint = "") {
1724
1753
  return {
1725
1754
  id: t.id,
1726
1755
  status: t.status,
@@ -1729,6 +1758,7 @@ function serializeTaskStatus(t, idleSince = null, isolation = null, queued = [],
1729
1758
  ...isolation ? { isolation } : {},
1730
1759
  ...t.transport ? { transport: t.transport.fallback ? { kind: t.transport.kind, fallback: t.transport.fallback } : { kind: t.transport.kind } } : {},
1731
1760
  ...t.status === "awaiting_user" && t.awaitingReason ? { awaitingReason: t.awaitingReason } : {},
1761
+ ...t.status === "awaiting_user" && t.awaitingReason === "checkpoint" && checkpoint ? { checkpoint } : {},
1732
1762
  ...queued.length > 0 ? { queued: queued.map((m) => ({ ...m })) } : {},
1733
1763
  ...canContinue(t) ? { continuable: true } : {},
1734
1764
  ...awaitingApproval > 0 ? { awaitingApproval } : {},
@@ -2123,6 +2153,103 @@ function taskStartedNotice(title, runner) {
2123
2153
  return runner ? `Started "${title}" \xB7 ${runner}` : `Started "${title}"`;
2124
2154
  }
2125
2155
 
2156
+ // src/taskRow/actions.ts
2157
+ var UNSTARTED_AI = (t) => t.type === "ai" && NOT_STARTED.has(t.status);
2158
+ var QUEUED = (t) => t.status === "pending" || t.status === "approved";
2159
+ var TASK_RULES = [
2160
+ ["cancel", (t) => t.status === "in_progress"],
2161
+ ["skip", (t) => t.status === "blocked"],
2162
+ ["force-start", UNSTARTED_AI],
2163
+ // A manual task has no runner to report it done, so it can always be marked.
2164
+ ["complete", (t) => t.status === "awaiting_user" || t.type === "user"],
2165
+ ["uncomplete", (t) => t.status === "completed"]
2166
+ ];
2167
+ var SUBTASK_RULES = [
2168
+ ["cancel", (t) => t.status === "in_progress"],
2169
+ ["complete", (t) => t.status === "in_progress" && t.type === "ai"],
2170
+ ["force-start", (t) => t.type === "ai" && QUEUED(t)],
2171
+ ["skip", QUEUED],
2172
+ ["complete", (t) => t.status === "awaiting_user"],
2173
+ ["uncomplete", (t) => t.status === "completed"]
2174
+ ];
2175
+ function taskRowActions(task, placement = "task") {
2176
+ const rules = placement === "subtask" ? SUBTASK_RULES : TASK_RULES;
2177
+ return rules.filter(([, applies]) => applies(task)).map(([action]) => action);
2178
+ }
2179
+ function markAction(task) {
2180
+ return task.status === "completed" ? "uncomplete" : "complete";
2181
+ }
2182
+ function markRequestFor(action) {
2183
+ if (action === "complete" || action === "skip") return "complete";
2184
+ if (action === "uncomplete") return "uncomplete";
2185
+ return null;
2186
+ }
2187
+ function opsEditable(task) {
2188
+ return UNSTARTED_AI(task);
2189
+ }
2190
+
2191
+ // src/taskRow/view.ts
2192
+ var refsOf = (ids, orderOf) => ids.map((id) => {
2193
+ const order = orderOf?.get(id);
2194
+ return order === void 0 ? id : taskRef({ order });
2195
+ });
2196
+ var namedRepo = (repo) => repo && repo !== "." ? repo : null;
2197
+ var namedRepos = (repos) => (repos ?? []).filter((r) => r !== ".");
2198
+ var filesOf = (files) => files?.length ? capConflictFiles(files) : null;
2199
+ function taskRowView(task, context = {}) {
2200
+ const parent = context.parent ?? void 0;
2201
+ const isolation = task.isolation && task.isolation.state !== "none" ? task.isolation : null;
2202
+ return {
2203
+ orderLabel: taskOrderLabel(task, parent),
2204
+ kind: task.type === "user" ? "user" : task.ops ? "ops" : "ai",
2205
+ status: taskStatusKind(task),
2206
+ running: isTaskRunning(task),
2207
+ awaiting: awaitingLabel(task),
2208
+ approvals: approvalLabel(task.awaitingApproval),
2209
+ autonomous: task.type === "ai" && context.modes?.find((m) => m.id === task.taskMode)?.autonomous === true,
2210
+ repos: namedRepos(isolation?.repos),
2211
+ conflict: isolation?.state === "conflict" ? { repo: namedRepo(isolation.conflictRepo), files: filesOf(isolation.conflictFiles) } : null,
2212
+ repairing: isolation?.state === "repairing" ? { files: filesOf(isolation.conflictFiles), attempt: isolation.repair ?? null } : null,
2213
+ repaired: isolation?.repairedFiles?.length ? { files: capConflictFiles(isolation.repairedFiles), landed: isolation.state === "integrated" } : null,
2214
+ mergeGate: task.mergeGate?.length ? refsOf(task.mergeGate, context.orderOf) : null,
2215
+ opsChangedFiles: task.status === "awaiting_user" && task.awaitingReason === "files-changed",
2216
+ forcedPastGate: task.forcedPastGate?.length ? task.forcedPastGate : null,
2217
+ dependencies: refsOf(task.dependencies, context.orderOf),
2218
+ actions: taskRowActions(task, context.placement ?? (parent ? "subtask" : "task")),
2219
+ mark: markAction(task),
2220
+ opsEditable: opsEditable(task)
2221
+ };
2222
+ }
2223
+
2224
+ // src/taskRow/texts.ts
2225
+ function findNamed(tasks, id) {
2226
+ for (const task of tasks) {
2227
+ if (task.id === id) return task;
2228
+ const nested = findNamed(task.subtasks ?? [], id);
2229
+ if (nested) return nested;
2230
+ }
2231
+ return void 0;
2232
+ }
2233
+ function titledRefs(ids, tasks) {
2234
+ return ids.map((id) => {
2235
+ const task = findNamed(tasks, id);
2236
+ return task ? titledTaskRef(task) : id;
2237
+ });
2238
+ }
2239
+ function dependentsNotice(dependents) {
2240
+ if (dependents.length === 0) return null;
2241
+ const subject = dependents.length === 1 ? "1 task depends" : `${dependents.length} tasks depend`;
2242
+ return `${subject} on it and will lose that dependency: ${dependents.map((t) => titledTaskRef(t)).join(", ")}.`;
2243
+ }
2244
+ function pastGateConfirmation(unmerged, subject = "This task") {
2245
+ return `${subject} waits for Merge all: the work of ${unmerged.join(", ")} is not merged into your branch yet, so it would act without it. Starting it now is kept on the task.`;
2246
+ }
2247
+ function newTaskFields(title, prompt) {
2248
+ const name = title.trim();
2249
+ if (!name) return null;
2250
+ return { title: name, description: name, prompt: prompt?.trim() ? prompt : name, type: "ai" };
2251
+ }
2252
+
2126
2253
  export {
2127
2254
  partedPromptUsage,
2128
2255
  addUsage,
@@ -2150,6 +2277,11 @@ export {
2150
2277
  filterModelsForPrompt,
2151
2278
  clampThinkingEffort,
2152
2279
  coerceAssignments,
2280
+ isTaskRunning,
2281
+ NOT_STARTED,
2282
+ taskStatusKind,
2283
+ awaitingLabel,
2284
+ approvalLabel,
2153
2285
  validateTaskEdit,
2154
2286
  taskOpsProtocol,
2155
2287
  textHasTaskOps,
@@ -2185,6 +2317,16 @@ export {
2185
2317
  followTurn,
2186
2318
  stopTurn,
2187
2319
  hasHiddenDetail,
2188
- taskStartedNotice
2320
+ taskStartedNotice,
2321
+ taskRowActions,
2322
+ markAction,
2323
+ markRequestFor,
2324
+ opsEditable,
2325
+ namedRepos,
2326
+ taskRowView,
2327
+ titledRefs,
2328
+ dependentsNotice,
2329
+ pastGateConfirmation,
2330
+ newTaskFields
2189
2331
  };
2190
- //# sourceMappingURL=chunk-LSGY7AIZ.mjs.map
2332
+ //# sourceMappingURL=chunk-AJ5KDO6V.mjs.map