agent-yes 1.267.2 → 1.269.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 (108) hide show
  1. package/README.md +73 -0
  2. package/dist/{SUPPORTED_CLIS-CpWKDCtL.js → SUPPORTED_CLIS-Bne04-66.js} +2 -2
  3. package/dist/SUPPORTED_CLIS-CdyjhpZP.js +12 -0
  4. package/dist/{agent-yes.config-DzNini0E.js → agent-yes.config-2xKNJM5Y.js} +2 -2
  5. package/dist/{agentShare-D0reU6LW.js → agentShare-BI126Ej9.js} +8 -8
  6. package/dist/askCli-Bbxt9Umz.js +272 -0
  7. package/dist/{browser-DSduVZeZ.js → browser-CorYp8Yu.js} +1 -1
  8. package/dist/{browser-B7eYrBy7.js → browser-_2ndf80G.js} +5 -5
  9. package/dist/callback-BnUbjH7p.js +13 -0
  10. package/dist/{callback-Dlqwh9n7.js → callback-DI2r3NrV.js} +5 -5
  11. package/dist/{callbackCore-K99x3C75.js → callbackCore-Bbe7rpN2.js} +1 -1
  12. package/dist/{callbackCore-DcptaZwH.js → callbackCore-C0Cg9RbS.js} +1 -1
  13. package/dist/{channels-DQaZbare.js → channels-3gz9gHP7.js} +6 -6
  14. package/dist/{channels-yE1YUHCl.js → channels-CkaCyvEp.js} +2 -2
  15. package/dist/channels.js +5 -5
  16. package/dist/cli.js +11 -11
  17. package/dist/{cmdPs-D8gsRFVV.js → cmdPs-CVnlflxP.js} +7 -7
  18. package/dist/{configShared-DtHMBCl7.js → configShared-DYxlvrH0.js} +1 -1
  19. package/dist/{cwdConflictWarn-BpweoAiy.js → cwdConflictWarn-Buy3r_qc.js} +1 -1
  20. package/dist/{cwdPassthroughHint-BlRuOGo_.js → cwdPassthroughHint-BlWO-h5w.js} +1 -1
  21. package/dist/{e2e-CUMZC53I.js → e2e-OLfcNxiv.js} +1 -1
  22. package/dist/{expose-DyiZ5AU0.js → expose-Bfo-dZdy.js} +1 -1
  23. package/dist/{forkNested-B_4c-TQk.js → forkNested-jc2ER9xn.js} +1 -1
  24. package/dist/{hist-BoZPJ2ah.js → hist-DiOYRXuD.js} +1 -1
  25. package/dist/{html2canvas-pro.esm-cq4l_ZIw.js → html2canvas-pro.esm-D19oTQeV.js} +1 -1
  26. package/dist/identity-BmDYOuZE.js +3 -0
  27. package/dist/identity-CLaJ9-uE.js +109 -0
  28. package/dist/index.js +4 -3
  29. package/dist/{initMsg-D8cmdY76.js → initMsg-Bat5PUDf.js} +1 -1
  30. package/dist/{initMsg-BKqWDYFk.js → initMsg-CTAIqBWF.js} +8 -4
  31. package/dist/{needsInput-103zhZ90.js → needsInput-DhfIwxse.js} +1 -1
  32. package/dist/{nodeRuntime-QihGFQbI.js → nodeRuntime-CKc1BN5J.js} +1 -1
  33. package/dist/{notifyDaemon-TKtSYtEO.js → notifyDaemon-Cf4KHDOr.js} +7 -7
  34. package/dist/{notifyStore-CEDiVyis.js → notifyStore-0hlFPa6z.js} +1 -1
  35. package/dist/{notifyStore-Cbw2ZJ0X.js → notifyStore-Dus2D1XA.js} +1 -1
  36. package/dist/{openBrowser-Cs46NiH6.js → openBrowser-Dmg2Oi4q.js} +1 -1
  37. package/dist/{parentLink-CTgZZCgw.js → parentLink-BwX4jaGD.js} +1 -1
  38. package/dist/{parentLink-CQrn998L.js → parentLink-DS-XflaJ.js} +1 -1
  39. package/dist/{parentPingLoop-BEvJ2ElR.js → parentPingLoop-Bxd3dXWO.js} +6 -6
  40. package/dist/{peer-DIl5xtx8.js → peer-Dr4zvtcd.js} +3 -3
  41. package/dist/peer-u1AUAZeA.js +4 -0
  42. package/dist/{remotes-M8FbM92D.js → remotes-BiftUp09.js} +3 -3
  43. package/dist/{remotes-DdAfueOu.js → remotes-IzQHupeo.js} +3 -3
  44. package/dist/{rustBinary-B9FEbqTu.js → rustBinary-B2lNFJSe.js} +2 -2
  45. package/dist/{schedule-Bmh5uaDr.js → schedule-D1CNvuKT.js} +8 -7
  46. package/dist/{serve-BqRNIxeq.js → serve-BaHCO0bU.js} +49 -42
  47. package/dist/{setup-GYkQYxlf.js → setup-B8EL0SWL.js} +4 -4
  48. package/dist/{share-Db_zb6gH.js → share-DTPZgbfH.js} +2 -2
  49. package/dist/{share-NUhi-Wdd.js → share-RgJUhzqG.js} +2 -2
  50. package/dist/{spawnGate-CZlMs6uV.js → spawnGate-C6YKlnmb.js} +1 -1
  51. package/dist/{spawnGate-DN4wNXHq.js → spawnGate-CS3oFdJ9.js} +2 -2
  52. package/dist/{store-BW5NBouz.js → store-C7I2CAu9.js} +1 -1
  53. package/dist/{subcommands-DJpVXIb6.js → subcommands-03ghe-aZ.js} +192 -157
  54. package/dist/{subcommands-DLrJfG4D.js → subcommands-BS4lnTrb.js} +6 -6
  55. package/dist/{systemPathLink-BHv1I6wh.js → systemPathLink-DGVcx0fg.js} +1 -1
  56. package/dist/{terminal-CRLPUaKF.js → terminal-DrCP-200.js} +2 -2
  57. package/dist/terminal.js +1 -1
  58. package/dist/todoAutomation-BETGOik9.js +302 -0
  59. package/dist/{todoCli-BYGZ7_C5.js → todoCli-DUoxA1dh.js} +164 -37
  60. package/dist/todoIdentity-BffBxRHA.js +138 -0
  61. package/dist/{todoAutomation-BQRW614S.js → todoStore-Wk8U4zJ8.js} +63 -280
  62. package/dist/{tray-CzGs9-ch.js → tray-Bxq_sfvU.js} +1 -1
  63. package/dist/trayApp-BDMzlxRo.js +5 -0
  64. package/dist/{trayApp-DLMUu2sB.js → trayApp-DC4qjut7.js} +2 -2
  65. package/dist/{ts-ClwhahH9.js → ts-D0Pk-WJg.js} +14 -8
  66. package/dist/{versionChecker-ZQYirfMp.js → versionChecker-V6ceVsu9.js} +2 -2
  67. package/dist/{webrtcLink-DyCj380i.js → webrtcLink-B72AQ2eb.js} +2 -2
  68. package/dist/{webrtcRemote-Bl8eowma.js → webrtcRemote-D68dkqFp.js} +3 -3
  69. package/dist/{widget-DtZ1WXkf.js → widget-BM03OkC1.js} +3 -3
  70. package/dist/widget.js +1 -1
  71. package/dist/widgets.js +5 -5
  72. package/dist/{workspaceConfig-CBKlgA_q.js → workspaceConfig-EK7XNsgR.js} +1 -1
  73. package/dist/{ws-CiR2nOD3.js → ws-6l7Wb_0r.js} +7 -7
  74. package/dist/{ws-Ba372Tym.js → ws-pRFrqms9.js} +3 -3
  75. package/lab/ui/console-logic.js +64 -0
  76. package/lab/ui/index.html +58 -4
  77. package/package.json +1 -1
  78. package/ts/askCli.spec.ts +304 -0
  79. package/ts/askCli.ts +378 -0
  80. package/ts/identity.spec.ts +80 -1
  81. package/ts/identity.ts +16 -9
  82. package/ts/index.ts +6 -1
  83. package/ts/initMsg.spec.ts +22 -14
  84. package/ts/initMsg.ts +7 -2
  85. package/ts/ipcLock.spec.ts +107 -0
  86. package/ts/ipcLock.ts +130 -0
  87. package/ts/serve.ts +68 -17
  88. package/ts/subcommandMirror.spec.ts +76 -0
  89. package/ts/subcommands.spec.ts +115 -10
  90. package/ts/subcommands.ts +108 -36
  91. package/ts/todoAutomation.spec.ts +64 -0
  92. package/ts/todoAutomation.ts +25 -2
  93. package/ts/todoBlock.spec.ts +31 -1
  94. package/ts/todoBlock.ts +33 -1
  95. package/ts/todoCli.spec.ts +199 -4
  96. package/ts/todoCli.ts +266 -42
  97. package/ts/todoIdentity.spec.ts +85 -0
  98. package/ts/todoIdentity.ts +76 -0
  99. package/ts/todoLifecycle.spec.ts +13 -1
  100. package/ts/todoLifecycle.ts +35 -1
  101. package/ts/todoRoot.spec.ts +117 -0
  102. package/ts/todoRoot.ts +90 -0
  103. package/ts/todoStore.spec.ts +25 -0
  104. package/ts/todoStore.ts +36 -2
  105. package/dist/SUPPORTED_CLIS-DDs0xUvV.js +0 -11
  106. package/dist/callback-Bgehh-IW.js +0 -13
  107. package/dist/peer-Cvntlw1i.js +0 -4
  108. package/dist/trayApp-CoD89Y1_.js +0 -5
@@ -0,0 +1,302 @@
1
+ import { i as DONE_STATE, o as ORPHANED_STATE, p as transitionsOf } from "./todoStore-Wk8U4zJ8.js";
2
+
3
+ //#region ts/removeControlCharacters.ts
4
+ const ESC = String.fromCharCode(27);
5
+ const C1 = String.fromCharCode(155);
6
+ const BACKSLASH = String.fromCharCode(92);
7
+ const ST_PATTERN_SOURCE = ESC + BACKSLASH + BACKSLASH;
8
+ const OSC_PATTERN = new RegExp(ESC + "][^\x07\x1B]*(?:\x07|" + ST_PATTERN_SOURCE + ")", "g");
9
+ const CSI_PATTERN = new RegExp("[" + ESC + C1 + "][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]", "g");
10
+ function removeControlCharacters(str) {
11
+ return str.replace(OSC_PATTERN, "").replace(CSI_PATTERN, "");
12
+ }
13
+
14
+ //#endregion
15
+ //#region ts/todoBlock.ts
16
+ /**
17
+ * How a block of this type should be watched. Kept as one pure function so
18
+ * every caller (CLI rendering, automation, `/ask` aggregation) agrees on the
19
+ * same classification instead of re-deriving it ad hoc.
20
+ */
21
+ function monitorHint(block) {
22
+ switch (block.type) {
23
+ case "blocked-by-task":
24
+ case "blocked-by-human": return "none";
25
+ case "waiting-on-agent":
26
+ case "waiting-on-answer": return "notify-agent";
27
+ case "blocked-by-external": return "poll-external";
28
+ }
29
+ }
30
+ /** One-line human-readable summary, used by CLI/digest rendering. */
31
+ function describeBlock(block) {
32
+ switch (block.type) {
33
+ case "blocked-by-task": return `blocked by task ${block.taskId}`;
34
+ case "blocked-by-human": return `waiting on ${block.who}${block.question ? `: ${block.question}` : ""}${block.actionLink ? ` (action: ${block.actionLink})` : ""}`;
35
+ case "blocked-by-external": return `waiting on external signal: ${block.signal}`;
36
+ case "waiting-on-agent": return `waiting on agent ${block.agentId}`;
37
+ case "waiting-on-answer": return `waiting for an answer from ${block.agentId}${block.question ? `: ${block.question}` : ""}`;
38
+ }
39
+ }
40
+ /**
41
+ * The agent this block is waiting on, if any — the one identifier a caller
42
+ * needs to ask "is that party still alive?". Centralised so every surface
43
+ * (list rendering, reconcile, JSON output) agrees on which block shapes name
44
+ * an agent, instead of each one re-listing the cases and quietly missing the
45
+ * next shape that gets added.
46
+ */
47
+ function blockedOnAgent(block) {
48
+ if (!block) return null;
49
+ return block.type === "waiting-on-agent" || block.type === "waiting-on-answer" ? block.agentId : null;
50
+ }
51
+
52
+ //#endregion
53
+ //#region ts/todoDigest.ts
54
+ /**
55
+ * Read-side views over the `ay todo` store: dependency-tree rendering and a
56
+ * per-tag digest board. Pure functions over an already-loaded task list — no
57
+ * I/O — so they are trivially unit-testable and reusable by both the CLI
58
+ * (`todoCli.ts`) and any future web view.
59
+ *
60
+ * `unblockedTasks` is ported near-verbatim from the equivalent, already
61
+ * mutation-tested algorithm in a private sibling CLI's `deps.ts` (a closed-source
62
+ * downstream consumer of an earlier, less general version of this idea) —
63
+ * generalized here to the new `TodoRecord` shape and the `done` state name
64
+ * from `todoLifecycle.ts` instead of a hardcoded status string.
65
+ */
66
+ /**
67
+ * The full set of task ids `t` is waiting on: the structural `blockedBy`
68
+ * array PLUS, if `t.block` is a `blocked-by-task` shape, that block's own
69
+ * `taskId`. Without folding the latter in, a task blocked via
70
+ * `ay todo block --type blocked-by-task --task X` would never be detected
71
+ * as resolved once X reaches `done` — contradicting `todoBlock.ts`'s own
72
+ * documented promise that this block type "clears itself... pure data, no
73
+ * monitor needed" (codex-review Important: the two mechanisms didn't
74
+ * actually talk to each other, making `blocked-by-task` blocks inert).
75
+ */
76
+ function declaredTaskDeps(t) {
77
+ return t.block?.type === "blocked-by-task" ? [...t.blockedBy, t.block.taskId] : t.blockedBy;
78
+ }
79
+ /**
80
+ * A task is "unblocked" when it is not itself finished, it declares task
81
+ * dependencies (via `blockedBy` and/or a `blocked-by-task` block), and
82
+ * every one of them has reached `done`.
83
+ * Surfaced for a caller to act on — never auto-applied here (deciding to
84
+ * resume a task is left to automation, a later milestone, or a human).
85
+ */
86
+ function unblockedTasks(tasks) {
87
+ const byId = new Map(tasks.map((t) => [t._id, t]));
88
+ return tasks.filter((t) => {
89
+ if (t.state === DONE_STATE) return false;
90
+ const deps = declaredTaskDeps(t);
91
+ if (deps.length === 0) return false;
92
+ return deps.every((d) => byId.get(d)?.state === DONE_STATE);
93
+ });
94
+ }
95
+ /** Blockers of `t` that have not reached `done` yet (a missing id is reported as-is, still "open"). */
96
+ function openBlockers(t, byId) {
97
+ return declaredTaskDeps(t).filter((d) => byId.get(d)?.state !== DONE_STATE);
98
+ }
99
+ function nodeLine(t) {
100
+ return [`${t._id} [${t.state}] ${t.summary}`, ...t.owner ? [`owner:${t.owner}`] : []].join(" ");
101
+ }
102
+ /**
103
+ * Dependency tree, rendered from roots (tasks nothing depends on, that
104
+ * themselves declare at least one dependency) down their `blockedBy` edges:
105
+ * a parent's children are what it is waiting for.
106
+ */
107
+ function renderTree(tasks, rootId) {
108
+ const byId = new Map(tasks.map((t) => [t._id, t]));
109
+ const dependedOn = new Set(tasks.flatMap((t) => t.blockedBy));
110
+ const roots = rootId ? [byId.get(rootId) ?? null].filter((t) => t !== null) : tasks.filter((t) => !dependedOn.has(t._id) && t.blockedBy.length > 0);
111
+ if (rootId && roots.length === 0) throw new Error(`no such task: ${rootId}`);
112
+ if (roots.length === 0) return "(no dependency links)";
113
+ const lines = [];
114
+ const walk = (t, prefix, isLast, depth, seen) => {
115
+ lines.push(depth === 0 ? nodeLine(t) : `${prefix}${isLast ? "└─" : "├─"} ${nodeLine(t)}`);
116
+ if (seen.has(t._id)) return;
117
+ seen.add(t._id);
118
+ const deps = t.blockedBy.map((d) => byId.get(d)).filter((x) => x !== void 0);
119
+ deps.forEach((d, i) => {
120
+ walk(d, depth === 0 ? "" : `${prefix}${isLast ? " " : "│ "}`, i === deps.length - 1, depth + 1, seen);
121
+ });
122
+ };
123
+ roots.forEach((r) => walk(r, "", true, 0, /* @__PURE__ */ new Set()));
124
+ return lines.join("\n");
125
+ }
126
+ /**
127
+ * JSON-shaped equivalent of `renderTree` — same roots-and-edges logic, built
128
+ * as data instead of formatted lines, so a machine caller (`--format json`)
129
+ * gets the actual tree structure rather than a string it would have to
130
+ * re-parse (codex-review Important: the CLI previously ignored --format for
131
+ * this command entirely, always writing the human text with exit code 0).
132
+ */
133
+ function buildTreeJSON(tasks, rootId) {
134
+ const byId = new Map(tasks.map((t) => [t._id, t]));
135
+ const dependedOn = new Set(tasks.flatMap((t) => t.blockedBy));
136
+ const roots = rootId ? [byId.get(rootId) ?? null].filter((t) => t !== null) : tasks.filter((t) => !dependedOn.has(t._id) && t.blockedBy.length > 0);
137
+ if (rootId && roots.length === 0) throw new Error(`no such task: ${rootId}`);
138
+ const build = (t, ancestors) => {
139
+ const node = {
140
+ id: t._id,
141
+ state: t.state,
142
+ summary: t.summary,
143
+ ...t.owner ? { owner: t.owner } : {},
144
+ children: []
145
+ };
146
+ if (ancestors.has(t._id)) return node;
147
+ const nextAncestors = new Set(ancestors).add(t._id);
148
+ node.children = t.blockedBy.map((d) => byId.get(d)).filter((x) => x !== void 0).map((d) => build(d, nextAncestors));
149
+ return node;
150
+ };
151
+ return roots.map((r) => build(r, /* @__PURE__ */ new Set()));
152
+ }
153
+ /** Per-tag board: state counts per tag, plus an unblocked-tasks callout. */
154
+ function renderDigest(tasks) {
155
+ if (tasks.length === 0) return "(no tasks)";
156
+ const byId = new Map(tasks.map((t) => [t._id, t]));
157
+ const unblocked = new Set(unblockedTasks(tasks).map((t) => t._id));
158
+ const streams = /* @__PURE__ */ new Map();
159
+ for (const t of tasks) for (const tag of t.tags.length ? t.tags : ["(untagged)"]) {
160
+ if (!streams.has(tag)) streams.set(tag, []);
161
+ streams.get(tag).push(t);
162
+ }
163
+ const lines = [];
164
+ for (const [stream, items] of [...streams.entries()].sort(([a], [b]) => a.localeCompare(b))) {
165
+ const allStates = [...new Set(items.map((t) => t.state))].sort();
166
+ const counts = allStates.map((s) => `${s}:${items.filter((t) => t.state === s).length}`).join(" ");
167
+ lines.push(`## ${stream} (${counts})`);
168
+ for (const s of allStates) for (const t of items.filter((x) => x.state === s)) {
169
+ const open = openBlockers(t, byId);
170
+ const extra = [
171
+ ...t.owner ? [`owner:${t.owner}`] : [],
172
+ ...t.block ? [`block:${t.block.type}`] : [],
173
+ ...open.length ? [`blockedBy:${open.join(",")}`] : [],
174
+ ...unblocked.has(t._id) ? ["UNBLOCKED"] : []
175
+ ];
176
+ lines.push(` [${t.state}] ${t._id} ${t.summary}${extra.length ? ` [${extra.join(" ")}]` : ""}`);
177
+ }
178
+ lines.push("");
179
+ }
180
+ const ub = unblockedTasks(tasks);
181
+ if (ub.length) {
182
+ lines.push("## unblocked (all blockers reached done — resume these)");
183
+ for (const t of ub) lines.push(` ${t._id} ${t.summary}${t.owner ? ` (owner:${t.owner})` : ""}`);
184
+ lines.push("");
185
+ }
186
+ return lines.join("\n").trimEnd();
187
+ }
188
+
189
+ //#endregion
190
+ //#region ts/todoAutomation.ts
191
+ /**
192
+ * Reactive layer for the `ay todo` engine (Milestone 2): makes the engine
193
+ * self-driving for agent-facing signals `agent-yes` already tracks, instead
194
+ * of requiring every state change to be typed by hand.
195
+ *
196
+ * `reconcileTodos` is pure — decision logic only, no I/O — exactly the same
197
+ * "decide" / "do" split a private sibling CLI's existing `watchdog.ts`
198
+ * (`decideActions`) already uses successfully: the hard-to-get-right parts
199
+ * (edge cases) live in a function that takes plain data in and returns plain
200
+ * data out, so they are trivially unit-testable without a real store, real
201
+ * processes, or real time. Applying the returned actions to a real
202
+ * `TodoStore` (I/O) is a separate, thin step (see `todoCli.ts`'s `reconcile`
203
+ * verb) deliberately kept out of this file — including revalidating each
204
+ * action against a FRESH record immediately before writing, since the
205
+ * snapshot this function decided from can be stale by the time the caller
206
+ * applies it (codex-review Important, see the action shapes below).
207
+ */
208
+ /**
209
+ * `TodoRecord.owner` is opaque — a human name/handle OR a tracked agent's
210
+ * stable id, this module cannot tell which just by looking at the string.
211
+ * The only safe signal is whether the identifier appears in the live-agent
212
+ * registry AT ALL: a KNOWN agent id whose latest record says `exited` is
213
+ * confirmed dead and orphan-eligible; an identifier with NO record at all is
214
+ * assumed to be a human owner (who was never going to appear there) and is
215
+ * never orphaned on that basis alone. Getting this backwards would orphan
216
+ * every human-owned task on every tick, since a human obviously never shows
217
+ * up in the agent process table.
218
+ */
219
+ function deadOwnerAgent(ownerId, agents) {
220
+ const rec = agents.find((a) => a.agent_id === ownerId);
221
+ return rec !== void 0 && rec.status === "exited";
222
+ }
223
+ /** Up to `limit` OTHER agent ids currently idle — candidates to hand an orphaned task to. */
224
+ function idleCandidates(excludeAgentId, agents, limit = 3) {
225
+ return agents.filter((a) => !!a.agent_id).filter((a) => a.agent_id !== excludeAgentId && a.status === "idle").map((a) => a.agent_id).slice(0, limit);
226
+ }
227
+ /**
228
+ * Decide what should happen given the current tasks and the current live-agent
229
+ * snapshot. Four rules, each traceable to a specific requirement (see
230
+ * `docs/2026-07-23-todo-lifecycle-execplan.md`'s Milestone 2 section):
231
+ *
232
+ * - owner's agent process is gone and the task isn't finished → `orphan`.
233
+ * - a `waiting-on-agent` block whose agent went idle or exited successfully
234
+ * (exit code 0) → `clear-waiting-on-agent`.
235
+ * - a task currently in `unblockedTasks()` with an owner → `notify-unblocked`,
236
+ * reported on EVERY call (no dedup/state file): there is no real delivery
237
+ * channel wired yet (see `todoCli.ts`'s `reconcile` verb doc comment), so
238
+ * persisting "already notified" would silently retire the one signal an
239
+ * owner would ever get with nobody having actually received it
240
+ * (codex-review Important) — the same no-dedup convention `renderDigest`'s
241
+ * own "unblocked" section already uses.
242
+ * - a task in a state whose outgoing edge's gate is registered → `auto-verify`
243
+ * (the actual gate CALL is real I/O and happens in the caller via `store.verify()`;
244
+ * this only decides which tasks are eligible to try).
245
+ *
246
+ * An orphaned task is skipped for the OTHER rules this same tick (its owner is
247
+ * gone, so it cannot also be "waiting on" that same dead agent in a meaningful
248
+ * way, and it is no longer eligible for auto-verify either).
249
+ */
250
+ function reconcileTodos(tasks, agents, registeredGates) {
251
+ const actions = [];
252
+ const orphanedThisTick = /* @__PURE__ */ new Set();
253
+ for (const t of tasks) {
254
+ if (t.state === DONE_STATE || t.state === ORPHANED_STATE) continue;
255
+ if (t.owner && deadOwnerAgent(t.owner, agents)) {
256
+ actions.push({
257
+ type: "orphan",
258
+ taskId: t._id,
259
+ from: t.state,
260
+ expectedOwner: t.owner,
261
+ candidates: idleCandidates(t.owner, agents)
262
+ });
263
+ orphanedThisTick.add(t._id);
264
+ continue;
265
+ }
266
+ if (t.block?.type === "waiting-on-answer") {
267
+ const block = t.block;
268
+ if (agents.find((a) => a.agent_id === block.agentId)?.status === "exited") actions.push({
269
+ type: "answerer-gone",
270
+ taskId: t._id,
271
+ agentId: block.agentId,
272
+ ...t.owner ? { owner: t.owner } : {}
273
+ });
274
+ }
275
+ if (t.block?.type === "waiting-on-agent") {
276
+ const agentId = t.block.agentId;
277
+ const agent = agents.find((a) => a.agent_id === agentId);
278
+ if (agent && (agent.status === "idle" || agent.status === "exited" && agent.exit_code === 0)) actions.push({
279
+ type: "clear-waiting-on-agent",
280
+ taskId: t._id,
281
+ expectedAgentId: agentId
282
+ });
283
+ }
284
+ if (transitionsOf(t.kind).some((edge) => edge.from === t.state && edge.gate && registeredGates.has(edge.gate))) actions.push({
285
+ type: "auto-verify",
286
+ taskId: t._id
287
+ });
288
+ }
289
+ for (const t of unblockedTasks(tasks)) {
290
+ if (orphanedThisTick.has(t._id) || !t.owner) continue;
291
+ actions.push({
292
+ type: "notify-unblocked",
293
+ taskId: t._id,
294
+ owner: t.owner
295
+ });
296
+ }
297
+ return actions;
298
+ }
299
+
300
+ //#endregion
301
+ export { renderTree as a, describeBlock as c, renderDigest as i, monitorHint as l, buildTreeJSON as n, unblockedTasks as o, openBlockers as r, blockedOnAgent as s, reconcileTodos as t, removeControlCharacters as u };
302
+ //# sourceMappingURL=todoAutomation-BETGOik9.js.map