@astralyn/pi 0.82.4 → 0.82.5

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 (89) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/core/agent-session.d.ts.map +1 -1
  3. package/dist/core/agent-session.js +2 -2
  4. package/dist/core/agent-session.js.map +1 -1
  5. package/dist/core/extensions/index.d.ts +1 -1
  6. package/dist/core/extensions/index.d.ts.map +1 -1
  7. package/dist/core/extensions/index.js +1 -1
  8. package/dist/core/extensions/index.js.map +1 -1
  9. package/dist/core/extensions/loader.d.ts +1 -1
  10. package/dist/core/extensions/loader.d.ts.map +1 -1
  11. package/dist/core/extensions/loader.js +2 -3
  12. package/dist/core/extensions/loader.js.map +1 -1
  13. package/dist/core/extensions/types.d.ts +9 -0
  14. package/dist/core/extensions/types.d.ts.map +1 -1
  15. package/dist/core/extensions/types.js +11 -0
  16. package/dist/core/extensions/types.js.map +1 -1
  17. package/dist/extensions/question/dialog.d.ts +3 -1
  18. package/dist/extensions/question/dialog.d.ts.map +1 -1
  19. package/dist/extensions/question/dialog.js +106 -52
  20. package/dist/extensions/question/dialog.js.map +1 -1
  21. package/dist/extensions/question/index.d.ts.map +1 -1
  22. package/dist/extensions/question/index.js +2 -2
  23. package/dist/extensions/question/index.js.map +1 -1
  24. package/dist/extensions/question/render-cache.d.ts +9 -0
  25. package/dist/extensions/question/render-cache.d.ts.map +1 -1
  26. package/dist/extensions/question/render-cache.js +22 -0
  27. package/dist/extensions/question/render-cache.js.map +1 -1
  28. package/dist/extensions/question/results.d.ts.map +1 -1
  29. package/dist/extensions/question/results.js +6 -1
  30. package/dist/extensions/question/results.js.map +1 -1
  31. package/dist/extensions/question/schema.d.ts +4 -0
  32. package/dist/extensions/question/schema.d.ts.map +1 -1
  33. package/dist/extensions/question/schema.js +19 -28
  34. package/dist/extensions/question/schema.js.map +1 -1
  35. package/dist/extensions/question/types.d.ts +1 -1
  36. package/dist/extensions/question/types.d.ts.map +1 -1
  37. package/dist/extensions/question/types.js.map +1 -1
  38. package/dist/extensions/subagent/agents.d.ts.map +1 -1
  39. package/dist/extensions/subagent/agents.js +12 -6
  40. package/dist/extensions/subagent/agents.js.map +1 -1
  41. package/dist/extensions/subagent/constants.d.ts +1 -1
  42. package/dist/extensions/subagent/constants.d.ts.map +1 -1
  43. package/dist/extensions/subagent/constants.js +3 -2
  44. package/dist/extensions/subagent/constants.js.map +1 -1
  45. package/dist/extensions/subagent/runner.d.ts +1 -1
  46. package/dist/extensions/subagent/runner.d.ts.map +1 -1
  47. package/dist/extensions/subagent/runner.js +5 -1
  48. package/dist/extensions/subagent/runner.js.map +1 -1
  49. package/dist/extensions/subagent/schema.d.ts.map +1 -1
  50. package/dist/extensions/subagent/schema.js +2 -2
  51. package/dist/extensions/subagent/schema.js.map +1 -1
  52. package/dist/extensions/subagent/sdk-runner.d.ts.map +1 -1
  53. package/dist/extensions/subagent/sdk-runner.js +5 -0
  54. package/dist/extensions/subagent/sdk-runner.js.map +1 -1
  55. package/dist/extensions/subagent/types.d.ts +7 -0
  56. package/dist/extensions/subagent/types.d.ts.map +1 -1
  57. package/dist/extensions/subagent/types.js.map +1 -1
  58. package/dist/extensions/todo/constants.d.ts +1 -1
  59. package/dist/extensions/todo/constants.d.ts.map +1 -1
  60. package/dist/extensions/todo/constants.js +29 -4
  61. package/dist/extensions/todo/constants.js.map +1 -1
  62. package/dist/extensions/todo/index.d.ts +1 -1
  63. package/dist/extensions/todo/index.d.ts.map +1 -1
  64. package/dist/extensions/todo/index.js +22 -3
  65. package/dist/extensions/todo/index.js.map +1 -1
  66. package/dist/extensions/todo/schema.d.ts +6 -5
  67. package/dist/extensions/todo/schema.d.ts.map +1 -1
  68. package/dist/extensions/todo/schema.js +20 -9
  69. package/dist/extensions/todo/schema.js.map +1 -1
  70. package/dist/extensions/todo/state.d.ts +5 -1
  71. package/dist/extensions/todo/state.d.ts.map +1 -1
  72. package/dist/extensions/todo/state.js +184 -38
  73. package/dist/extensions/todo/state.js.map +1 -1
  74. package/dist/extensions/todo/view.d.ts.map +1 -1
  75. package/dist/extensions/todo/view.js +10 -6
  76. package/dist/extensions/todo/view.js.map +1 -1
  77. package/dist/modes/interactive/interactive-mode.d.ts +2 -0
  78. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  79. package/dist/modes/interactive/interactive-mode.js +34 -1
  80. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  81. package/dist/utils/coalescing-terminal.d.ts +71 -17
  82. package/dist/utils/coalescing-terminal.d.ts.map +1 -1
  83. package/dist/utils/coalescing-terminal.js +136 -31
  84. package/dist/utils/coalescing-terminal.js.map +1 -1
  85. package/docs/bundled/extensions/question.md +9 -7
  86. package/docs/bundled/extensions/subagent.md +2 -2
  87. package/docs/bundled/extensions/todo.md +5 -3
  88. package/npm-shrinkwrap.json +2 -2
  89. package/package.json +1 -1
@@ -14,8 +14,9 @@ let activeSid = "";
14
14
  export function setActiveTodoSession(sid) {
15
15
  activeSid = sid;
16
16
  }
17
+ /** Snapshot of the active session's state; mutate via applyTodoMutation + commitTodoState. */
17
18
  export function getTodoState() {
18
- return states.get(activeSid) ?? cloneState(EMPTY_TODO_STATE);
19
+ return cloneState(states.get(activeSid) ?? EMPTY_TODO_STATE);
19
20
  }
20
21
  export function replaceTodoState(next) {
21
22
  states.set(activeSid, cloneState(next));
@@ -53,7 +54,11 @@ function omitBlockedBy(item) {
53
54
  delete next.blockedBy;
54
55
  return next;
55
56
  }
56
- /** Keep a tombstone while detaching its id from every dependent task. */
57
+ /**
58
+ * Keep a tombstone while detaching its id from every dependent task. Also
59
+ * reports which pending dependents ended up fully unblocked, so the tool
60
+ * result can tell the model what became workable (mirrors the demote note).
61
+ */
57
62
  function markDeleted(state, id) {
58
63
  const items = state.items.map((item) => {
59
64
  if (item.id === id)
@@ -63,11 +68,63 @@ function markDeleted(state, id) {
63
68
  const blockedBy = item.blockedBy.filter((dependencyId) => dependencyId !== id);
64
69
  return blockedBy.length ? { ...item, blockedBy } : omitBlockedBy(item);
65
70
  });
66
- return { items, nextId: state.nextId };
71
+ const nextState = { items, nextId: state.nextId };
72
+ const releasedIds = state.items
73
+ .filter((item) => item.id !== id && item.status === "pending" && item.blockedBy?.includes(id))
74
+ .map((item) => item.id)
75
+ .filter((dependentId) => {
76
+ const dependent = findItem(nextState, dependentId);
77
+ return dependent !== undefined && unresolvedDependencyIds(nextState, dependent).length === 0;
78
+ });
79
+ return { state: nextState, releasedIds };
67
80
  }
68
81
  function error(state, message) {
69
82
  return { state, operation: { kind: "error", message } };
70
83
  }
84
+ // ---- per-action parameter validation ---------------------------------------
85
+ // Parameters each action accepts. Anything else is rejected with guidance
86
+ // instead of being silently ignored (a model that passes blockedBy on update
87
+ // should learn about addBlockedBy, not lose the edit).
88
+ const ACTION_PARAMS = {
89
+ create: new Set(["subject", "description", "activeForm", "status", "blockedBy", "owner", "metadata"]),
90
+ update: new Set([
91
+ "id",
92
+ "subject",
93
+ "description",
94
+ "activeForm",
95
+ "status",
96
+ "addBlockedBy",
97
+ "removeBlockedBy",
98
+ "addBlocks",
99
+ "removeBlocks",
100
+ "owner",
101
+ "metadata",
102
+ ]),
103
+ list: new Set(["status", "includeDeleted"]),
104
+ get: new Set(["id"]),
105
+ delete: new Set(["id"]),
106
+ clear: new Set(),
107
+ };
108
+ const UPDATE_ONLY_EDGE_PARAMS = new Set(["addBlockedBy", "removeBlockedBy", "addBlocks", "removeBlocks"]);
109
+ function inapplicableParamError(action, key) {
110
+ if (action === "update" && key === "blockedBy") {
111
+ return "blockedBy is create-only; use addBlockedBy/removeBlockedBy on update";
112
+ }
113
+ if (action === "create" && UPDATE_ONLY_EDGE_PARAMS.has(key)) {
114
+ return `${key} is update-only; use blockedBy on create`;
115
+ }
116
+ return `${key} does not apply to action ${action}`;
117
+ }
118
+ function findInapplicableParam(params) {
119
+ const allowed = ACTION_PARAMS[params.action];
120
+ for (const [key, value] of Object.entries(params)) {
121
+ if (key === "action" || value === undefined)
122
+ continue;
123
+ if (!allowed.has(key))
124
+ return inapplicableParamError(params.action, key);
125
+ }
126
+ return undefined;
127
+ }
71
128
  function isTransitionAllowed(from, to) {
72
129
  // `deleted` is the only terminal status; `completed` can be reopened to
73
130
  // in_progress or pending so a premature completion recovers without losing
@@ -123,11 +180,13 @@ export function unresolvedDependencyIds(state, item) {
123
180
  export function dependenciesSatisfied(state, item) {
124
181
  return unresolvedDependencyIds(state, item).length === 0;
125
182
  }
126
- function createsCycle(items, id, nextDeps) {
183
+ /** True when any task whose deps change in nextDepsById can reach itself through blockedBy edges. */
184
+ function createsCycle(items, nextDepsById) {
127
185
  const depsById = new Map();
128
186
  for (const item of items)
129
187
  depsById.set(item.id, item.blockedBy ?? []);
130
- depsById.set(id, nextDeps);
188
+ for (const [id, deps] of nextDepsById)
189
+ depsById.set(id, deps);
131
190
  const seen = new Set();
132
191
  const stack = new Set();
133
192
  function visit(node) {
@@ -144,15 +203,25 @@ function createsCycle(items, id, nextDeps) {
144
203
  stack.delete(node);
145
204
  return false;
146
205
  }
147
- return visit(id);
206
+ for (const id of nextDepsById.keys()) {
207
+ if (visit(id))
208
+ return true;
209
+ }
210
+ return false;
148
211
  }
149
212
  export function applyTodoMutation(input, params) {
150
213
  const state = cloneState(input);
214
+ const inapplicable = findInapplicableParam(params);
215
+ if (inapplicable)
216
+ return error(state, inapplicable);
151
217
  switch (params.action) {
152
218
  case "create": {
153
219
  const subject = params.subject?.trim();
154
220
  if (!subject)
155
221
  return error(state, "subject required for create");
222
+ if (!params.description?.trim()) {
223
+ return error(state, "description required for create: state what done means for this task");
224
+ }
156
225
  if (params.status !== undefined && params.status !== "pending") {
157
226
  return error(state, "create always starts pending; use update to start or complete a task");
158
227
  }
@@ -163,9 +232,8 @@ export function applyTodoMutation(input, params) {
163
232
  id: state.nextId,
164
233
  subject,
165
234
  status: "pending",
235
+ description: params.description,
166
236
  };
167
- if (params.description)
168
- item.description = params.description;
169
237
  if (params.activeForm)
170
238
  item.activeForm = params.activeForm;
171
239
  if (params.blockedBy?.length)
@@ -190,28 +258,45 @@ export function applyTodoMutation(input, params) {
190
258
  return error(state, `#${params.id} is deleted and cannot be updated`);
191
259
  if (params.subject !== undefined && !params.subject.trim())
192
260
  return error(state, "subject cannot be empty");
193
- const hasChange = params.subject !== undefined ||
261
+ const edgeChange = (params.addBlockedBy?.length ?? 0) > 0 ||
262
+ (params.removeBlockedBy?.length ?? 0) > 0 ||
263
+ (params.addBlocks?.length ?? 0) > 0 ||
264
+ (params.removeBlocks?.length ?? 0) > 0;
265
+ const fieldChange = params.subject !== undefined ||
194
266
  params.description !== undefined ||
195
267
  params.activeForm !== undefined ||
196
- params.status !== undefined ||
197
268
  params.owner !== undefined ||
198
- params.metadata !== undefined ||
199
- (params.addBlockedBy?.length ?? 0) > 0 ||
200
- (params.removeBlockedBy?.length ?? 0) > 0;
201
- if (!hasChange)
269
+ params.metadata !== undefined;
270
+ if (!fieldChange && !edgeChange && params.status === undefined) {
202
271
  return error(state, "update requires at least one field");
272
+ }
203
273
  // `status: deleted` is the update form of delete; keep its dependency
204
- // cleanup identical to the dedicated delete action.
274
+ // cleanup identical to the dedicated delete action. Other edits do not
275
+ // combine with it: a tombstone is immutable, so applying them would
276
+ // silently produce an unreachable revision.
205
277
  if (params.status === "deleted") {
278
+ if (fieldChange || edgeChange) {
279
+ return error(state, "status deleted cannot be combined with other changes; apply edits first or delete in a separate call");
280
+ }
281
+ const deleted = markDeleted(state, current.id);
206
282
  return {
207
- state: markDeleted(state, current.id),
208
- operation: { kind: "update", id: current.id, from: current.status, to: "deleted" },
283
+ state: deleted.state,
284
+ operation: {
285
+ kind: "update",
286
+ id: current.id,
287
+ from: current.status,
288
+ to: "deleted",
289
+ ...(deleted.releasedIds.length ? { releasedIds: deleted.releasedIds } : {}),
290
+ },
209
291
  };
210
292
  }
211
293
  const nextStatus = params.status ?? current.status;
212
294
  if (!isTransitionAllowed(current.status, nextStatus)) {
213
295
  return error(state, `illegal transition ${current.status} -> ${nextStatus}`);
214
296
  }
297
+ // Collect every task whose blockedBy changes: this task (addBlockedBy /
298
+ // removeBlockedBy) plus reverse-edge targets (addBlocks / removeBlocks).
299
+ const nextDepsById = new Map();
215
300
  let nextDeps = current.blockedBy ? [...current.blockedBy] : [];
216
301
  if (params.removeBlockedBy?.length) {
217
302
  const remove = new Set(params.removeBlockedBy);
@@ -226,9 +311,36 @@ export function applyTodoMutation(input, params) {
226
311
  nextDeps.push(dep);
227
312
  }
228
313
  }
229
- if (createsCycle(state.items, current.id, nextDeps)) {
314
+ nextDepsById.set(current.id, nextDeps);
315
+ if (params.removeBlocks?.length) {
316
+ const release = new Set(params.removeBlocks);
317
+ for (const candidate of state.items) {
318
+ if (!release.has(candidate.id) || !candidate.blockedBy?.includes(current.id))
319
+ continue;
320
+ nextDepsById.set(candidate.id, candidate.blockedBy.filter((dependencyId) => dependencyId !== current.id));
321
+ }
322
+ }
323
+ if (params.addBlocks?.length) {
324
+ for (const targetId of params.addBlocks) {
325
+ if (targetId === current.id)
326
+ return error(state, `cannot block #${targetId} on itself`);
327
+ const target = findItem(state, targetId);
328
+ if (!target)
329
+ return error(state, `addBlocks: #${targetId} not found`);
330
+ if (target.status === "deleted")
331
+ return error(state, `addBlocks: #${targetId} is deleted`);
332
+ const deps = nextDepsById.get(targetId) ?? (target.blockedBy ? [...target.blockedBy] : []);
333
+ if (!deps.includes(current.id))
334
+ deps.push(current.id);
335
+ nextDepsById.set(targetId, deps);
336
+ }
337
+ }
338
+ if (createsCycle(state.items, nextDepsById)) {
230
339
  return error(state, "blockedBy would create a cycle");
231
340
  }
341
+ // Readiness gates only status *changes*: an already-active task may take
342
+ // on a new incomplete dependency — a prerequisite discovered mid-work.
343
+ // The overlay flags it as "deps incomplete" instead.
232
344
  if ((nextStatus === "in_progress" || nextStatus === "completed") && current.status !== nextStatus) {
233
345
  const readyError = validateDependenciesReady(state, nextDeps);
234
346
  if (readyError)
@@ -237,12 +349,25 @@ export function applyTodoMutation(input, params) {
237
349
  const updated = { ...current, status: nextStatus };
238
350
  if (params.subject !== undefined)
239
351
  updated.subject = params.subject.trim();
240
- if (params.description !== undefined)
241
- updated.description = params.description;
242
- if (params.activeForm !== undefined)
243
- updated.activeForm = params.activeForm;
244
- if (params.owner !== undefined)
245
- updated.owner = params.owner;
352
+ // Empty string removes an optional text field (metadata uses null keys).
353
+ if (params.description !== undefined) {
354
+ if (params.description)
355
+ updated.description = params.description;
356
+ else
357
+ delete updated.description;
358
+ }
359
+ if (params.activeForm !== undefined) {
360
+ if (params.activeForm)
361
+ updated.activeForm = params.activeForm;
362
+ else
363
+ delete updated.activeForm;
364
+ }
365
+ if (params.owner !== undefined) {
366
+ if (params.owner)
367
+ updated.owner = params.owner;
368
+ else
369
+ delete updated.owner;
370
+ }
246
371
  if (nextDeps.length)
247
372
  updated.blockedBy = nextDeps;
248
373
  else
@@ -260,7 +385,14 @@ export function applyTodoMutation(input, params) {
260
385
  else
261
386
  delete updated.metadata;
262
387
  }
263
- const items = [...state.items];
388
+ const items = state.items.map((task) => {
389
+ if (task.id === current.id)
390
+ return task;
391
+ const deps = nextDepsById.get(task.id);
392
+ if (deps === undefined)
393
+ return task;
394
+ return deps.length ? { ...task, blockedBy: deps } : omitBlockedBy(task);
395
+ });
264
396
  items[index] = updated;
265
397
  // Exactly one in_progress: demote any other active tasks to pending.
266
398
  const demotedIds = [];
@@ -315,9 +447,15 @@ export function applyTodoMutation(input, params) {
315
447
  const current = state.items[index];
316
448
  if (current.status === "deleted")
317
449
  return error(state, `#${params.id} is already deleted`);
450
+ const deleted = markDeleted(state, current.id);
318
451
  return {
319
- state: markDeleted(state, current.id),
320
- operation: { kind: "delete", id: current.id, subject: current.subject },
452
+ state: deleted.state,
453
+ operation: {
454
+ kind: "delete",
455
+ id: current.id,
456
+ subject: current.subject,
457
+ ...(deleted.releasedIds.length ? { releasedIds: deleted.releasedIds } : {}),
458
+ },
321
459
  };
322
460
  }
323
461
  case "clear":
@@ -354,16 +492,20 @@ export function replayTodosFromBranch(ctx) {
354
492
  }
355
493
  return cloneState(EMPTY_TODO_STATE);
356
494
  }
357
- export function buildTodoDetails(params, next, operation) {
495
+ export function buildTodoDetails(params, next) {
358
496
  return {
359
497
  action: params.action,
360
498
  params: params,
361
499
  items: cloneState(next).items,
362
500
  nextId: next.nextId,
363
- ...(operation.kind === "error" ? { error: operation.message } : {}),
364
501
  };
365
502
  }
366
503
  const VERIFICATION_NUDGE_NOTE = "NOTE: You closed out 3+ tasks with no verification/test/review step. Before the final summary, run checks or add a verification task and complete it — do not self-declare done with known failures.";
504
+ function formatReleasedSuffix(releasedIds) {
505
+ if (!releasedIds?.length)
506
+ return "";
507
+ return `; released ${releasedIds.map((id) => `#${id}`).join(",")} (no longer blocked)`;
508
+ }
367
509
  export function formatTodoContent(operation, state) {
368
510
  switch (operation.kind) {
369
511
  case "create": {
@@ -376,12 +518,13 @@ export function formatTodoContent(operation, state) {
376
518
  if (operation.demotedIds?.length) {
377
519
  text += `; ${operation.demotedIds.map((id) => `#${id}`).join(",")} demoted to pending`;
378
520
  }
521
+ text += formatReleasedSuffix(operation.releasedIds);
379
522
  if (operation.verificationNudge)
380
523
  text += `\n\n${VERIFICATION_NUDGE_NOTE}`;
381
524
  return text;
382
525
  }
383
526
  case "delete":
384
- return `Deleted #${operation.id}: ${operation.subject}`;
527
+ return `Deleted #${operation.id}: ${operation.subject}${formatReleasedSuffix(operation.releasedIds)}`;
385
528
  case "clear":
386
529
  return `Cleared ${operation.count} tasks`;
387
530
  case "list": {
@@ -391,7 +534,7 @@ export function formatTodoContent(operation, state) {
391
534
  view = view.filter((item) => item.status !== "deleted");
392
535
  if (operation.status)
393
536
  view = view.filter((item) => item.status === operation.status);
394
- return formatBoundedList(view, operation.status, operation.includeDeleted);
537
+ return formatBoundedList(view, state, operation.status);
395
538
  }
396
539
  case "get":
397
540
  return formatDetailItem(operation.item, state);
@@ -415,22 +558,25 @@ function needsVerificationNudge(state) {
415
558
  return !completed.some((item) => VERIFICATION_PATTERN.test(item.subject) ||
416
559
  (item.description !== undefined && VERIFICATION_PATTERN.test(item.description)));
417
560
  }
418
- function formatBoundedList(view, statusFilter, includeDeleted) {
561
+ function formatBoundedList(view, state, statusFilter) {
419
562
  if (!view.length)
420
563
  return "No tasks";
421
564
  const shown = view.slice(0, LIST_DISPLAY_MAX_ITEMS);
422
- const lines = shown.map(formatListItem);
565
+ const lines = shown.map((item) => formatListItem(item, state));
423
566
  const omitted = view.length - shown.length;
424
567
  if (omitted > 0) {
425
- const filterHint = statusFilter ? `status=${statusFilter}` : includeDeleted ? "includeDeleted=true" : "list";
426
- lines.push(`… and ${omitted} more (${shown.length} of ${view.length} shown). Narrow with ${filterHint} or use get with id=.`);
568
+ // Do not suggest a filter that is already applied.
569
+ const hint = statusFilter ? "use get with id= for details" : "narrow with status= or use get with id=";
570
+ lines.push(`… and ${omitted} more (${shown.length} of ${view.length} shown); ${hint}.`);
427
571
  }
428
572
  return lines.join("\n");
429
573
  }
430
- function formatListItem(item) {
431
- const deps = item.blockedBy?.length ? ` blockedBy=${item.blockedBy.map((id) => `#${id}`).join(",")}` : "";
574
+ function formatListItem(item, state) {
575
+ const unresolved = unresolvedDependencyIds(state, item);
576
+ const deps = unresolved.length ? ` blockedBy=${unresolved.map((id) => `#${id}`).join(",")}` : "";
577
+ const owner = item.owner ? ` @${item.owner}` : "";
432
578
  const active = item.status === "in_progress" && item.activeForm ? ` (${item.activeForm})` : "";
433
- return `[${item.status}] #${item.id} ${item.subject}${active}${deps}`;
579
+ return `[${item.status}] #${item.id} ${item.subject}${active}${owner}${deps}`;
434
580
  }
435
581
  function formatDetailItem(item, state) {
436
582
  const lines = [`#${item.id} [${item.status}] ${item.subject}`];
@@ -1 +1 @@
1
- {"version":3,"file":"state.js","sourceRoot":"","sources":["../../../src/extensions/todo/state.ts"],"names":[],"mappings":"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","sourcesContent":["import { LIST_DISPLAY_MAX_ITEMS, TODO_TOOL_NAME } from \"./constants.ts\";\nimport {\n\tEMPTY_TODO_STATE,\n\ttype TodoDetails,\n\ttype TodoItem,\n\ttype TodoParams,\n\ttype TodoState,\n\ttype TodoStatus,\n} from \"./schema.ts\";\n\ntype Operation =\n\t| { kind: \"create\"; id: number }\n\t| {\n\t\t\tkind: \"update\";\n\t\t\tid: number;\n\t\t\tfrom: TodoStatus;\n\t\t\tto: TodoStatus;\n\t\t\t/** Other tasks auto-demoted from in_progress → pending to keep exactly one active. */\n\t\t\tdemotedIds?: number[];\n\t\t\t/** Soft note when the list is fully closed without a verification-style task. */\n\t\t\tverificationNudge?: boolean;\n\t }\n\t| { kind: \"delete\"; id: number; subject: string }\n\t| { kind: \"list\"; status?: TodoStatus; includeDeleted: boolean }\n\t| { kind: \"get\"; item: TodoItem }\n\t| { kind: \"clear\"; count: number }\n\t| { kind: \"error\"; message: string };\n\n/** Subjects/descriptions that count as a verification step (CC-style soft nudge). */\nconst VERIFICATION_PATTERN = /verif|test|check|review/i;\n\nexport interface MutationResult {\n\tstate: TodoState;\n\toperation: Operation;\n}\n\n// ---- per-session state ------------------------------------------------------\n// Keyed by session id like rewind's engine state: one Pi process can host more\n// than one session over its lifetime (resume, /tree branch switches), and a\n// module-level singleton would leak one session's list into another. Tool\n// renderers get no ctx, so the active session is a module-level pointer kept\n// current by execute and the lifecycle handlers (which do have ctx).\nconst states = new Map<string, TodoState>();\nlet activeSid = \"\";\n\n/** Point the module at a session's state bucket. Call wherever ctx is in hand. */\nexport function setActiveTodoSession(sid: string): void {\n\tactiveSid = sid;\n}\n\nexport function getTodoState(): TodoState {\n\treturn states.get(activeSid) ?? cloneState(EMPTY_TODO_STATE);\n}\n\nexport function replaceTodoState(next: TodoState): void {\n\tstates.set(activeSid, cloneState(next));\n}\n\nexport function commitTodoState(next: TodoState): void {\n\treplaceTodoState(next);\n}\n\n/** Drop in-memory state for a session (call from session_shutdown). */\nexport function disposeTodoSession(sid: string): void {\n\tif (!sid) return;\n\tstates.delete(sid);\n\tif (activeSid === sid) activeSid = \"\";\n}\n\nexport function cloneState(source: TodoState): TodoState {\n\treturn {\n\t\titems: source.items.map((item) => {\n\t\t\tconst clone: TodoItem = { ...item };\n\t\t\tif (item.blockedBy) clone.blockedBy = [...item.blockedBy];\n\t\t\telse delete clone.blockedBy;\n\t\t\tif (item.metadata) clone.metadata = { ...item.metadata };\n\t\t\telse delete clone.metadata;\n\t\t\treturn clone;\n\t\t}),\n\t\tnextId: source.nextId,\n\t};\n}\n\nfunction omitBlockedBy(item: TodoItem): TodoItem {\n\tconst next = { ...item };\n\tdelete next.blockedBy;\n\treturn next;\n}\n\n/** Keep a tombstone while detaching its id from every dependent task. */\nfunction markDeleted(state: TodoState, id: number): TodoState {\n\tconst items = state.items.map((item) => {\n\t\tif (item.id === id) return { ...item, status: \"deleted\" as const };\n\t\tif (!item.blockedBy?.includes(id)) return item;\n\t\tconst blockedBy = item.blockedBy.filter((dependencyId) => dependencyId !== id);\n\t\treturn blockedBy.length ? { ...item, blockedBy } : omitBlockedBy(item);\n\t});\n\treturn { items, nextId: state.nextId };\n}\n\nfunction error(state: TodoState, message: string): MutationResult {\n\treturn { state, operation: { kind: \"error\", message } };\n}\n\nfunction isTransitionAllowed(from: TodoStatus, to: TodoStatus): boolean {\n\t// `deleted` is the only terminal status; `completed` can be reopened to\n\t// in_progress or pending so a premature completion recovers without losing\n\t// the task id and its blockedBy edges.\n\tif (from === to) return true;\n\tif (from === \"deleted\") return false;\n\tif (to === \"deleted\") return true;\n\tif (to === \"completed\") return from === \"pending\" || from === \"in_progress\";\n\tif (to === \"pending\") return from === \"in_progress\" || from === \"completed\";\n\tif (to === \"in_progress\") return from === \"pending\" || from === \"completed\";\n\treturn false;\n}\n\nfunction findItem(state: TodoState, id: number): TodoItem | undefined {\n\treturn state.items.find((item) => item.id === id);\n}\n\nfunction validateDependencies(state: TodoState, deps: number[] | undefined, currentId?: number): string | undefined {\n\tif (!deps?.length) return undefined;\n\tfor (const dep of deps) {\n\t\tif (dep === currentId) return `cannot block #${currentId} on itself`;\n\t\tconst item = findItem(state, dep);\n\t\tif (!item) return `blockedBy: #${dep} not found`;\n\t\tif (item.status === \"deleted\") return `blockedBy: #${dep} is deleted`;\n\t}\n\treturn undefined;\n}\n\n/** All listed dependencies must be completed before starting or closing a task. */\nfunction validateDependenciesReady(state: TodoState, deps: number[] | undefined): string | undefined {\n\tif (!deps?.length) return undefined;\n\tfor (const dep of deps) {\n\t\tconst item = findItem(state, dep);\n\t\tif (!item || item.status !== \"completed\") {\n\t\t\treturn `blockedBy: complete #${dep} before starting or finishing this task`;\n\t\t}\n\t}\n\treturn undefined;\n}\n\n/** IDs of dependencies that still prevent a task from starting or completing. */\nexport function unresolvedDependencyIds(state: TodoState, item: TodoItem): number[] {\n\treturn (item.blockedBy ?? []).filter((id) => findItem(state, id)?.status !== \"completed\");\n}\n\n/** True when every blockedBy dependency is completed (for transition and overlay checks). */\nexport function dependenciesSatisfied(state: TodoState, item: TodoItem): boolean {\n\treturn unresolvedDependencyIds(state, item).length === 0;\n}\n\nfunction createsCycle(items: TodoItem[], id: number, nextDeps: number[]): boolean {\n\tconst depsById = new Map<number, number[]>();\n\tfor (const item of items) depsById.set(item.id, item.blockedBy ?? []);\n\tdepsById.set(id, nextDeps);\n\n\tconst seen = new Set<number>();\n\tconst stack = new Set<number>();\n\n\tfunction visit(node: number): boolean {\n\t\tif (stack.has(node)) return true;\n\t\tif (seen.has(node)) return false;\n\t\tseen.add(node);\n\t\tstack.add(node);\n\t\tfor (const dep of depsById.get(node) ?? []) {\n\t\t\tif (visit(dep)) return true;\n\t\t}\n\t\tstack.delete(node);\n\t\treturn false;\n\t}\n\n\treturn visit(id);\n}\n\nexport function applyTodoMutation(input: TodoState, params: TodoParams): MutationResult {\n\tconst state = cloneState(input);\n\n\tswitch (params.action) {\n\t\tcase \"create\": {\n\t\t\tconst subject = params.subject?.trim();\n\t\t\tif (!subject) return error(state, \"subject required for create\");\n\t\t\tif (params.status !== undefined && params.status !== \"pending\") {\n\t\t\t\treturn error(state, \"create always starts pending; use update to start or complete a task\");\n\t\t\t}\n\t\t\tconst dependencyError = validateDependencies(state, params.blockedBy);\n\t\t\tif (dependencyError) return error(state, dependencyError);\n\n\t\t\tconst item: TodoItem = {\n\t\t\t\tid: state.nextId,\n\t\t\t\tsubject,\n\t\t\t\tstatus: \"pending\",\n\t\t\t};\n\t\t\tif (params.description) item.description = params.description;\n\t\t\tif (params.activeForm) item.activeForm = params.activeForm;\n\t\t\tif (params.blockedBy?.length) item.blockedBy = Array.from(new Set<number>(params.blockedBy));\n\t\t\tif (params.owner) item.owner = params.owner;\n\t\t\tif (params.metadata) item.metadata = { ...params.metadata };\n\n\t\t\treturn {\n\t\t\t\tstate: { items: [...state.items, item], nextId: state.nextId + 1 },\n\t\t\t\toperation: { kind: \"create\", id: item.id },\n\t\t\t};\n\t\t}\n\n\t\tcase \"update\": {\n\t\t\tif (params.id === undefined) return error(state, \"id required for update\");\n\t\t\tconst index = state.items.findIndex((item) => item.id === params.id);\n\t\t\tif (index === -1) return error(state, `#${params.id} not found`);\n\t\t\tconst current = state.items[index];\n\t\t\tif (current.status === \"deleted\") return error(state, `#${params.id} is deleted and cannot be updated`);\n\t\t\tif (params.subject !== undefined && !params.subject.trim()) return error(state, \"subject cannot be empty\");\n\n\t\t\tconst hasChange =\n\t\t\t\tparams.subject !== undefined ||\n\t\t\t\tparams.description !== undefined ||\n\t\t\t\tparams.activeForm !== undefined ||\n\t\t\t\tparams.status !== undefined ||\n\t\t\t\tparams.owner !== undefined ||\n\t\t\t\tparams.metadata !== undefined ||\n\t\t\t\t(params.addBlockedBy?.length ?? 0) > 0 ||\n\t\t\t\t(params.removeBlockedBy?.length ?? 0) > 0;\n\t\t\tif (!hasChange) return error(state, \"update requires at least one field\");\n\n\t\t\t// `status: deleted` is the update form of delete; keep its dependency\n\t\t\t// cleanup identical to the dedicated delete action.\n\t\t\tif (params.status === \"deleted\") {\n\t\t\t\treturn {\n\t\t\t\t\tstate: markDeleted(state, current.id),\n\t\t\t\t\toperation: { kind: \"update\", id: current.id, from: current.status, to: \"deleted\" },\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst nextStatus = params.status ?? current.status;\n\t\t\tif (!isTransitionAllowed(current.status, nextStatus)) {\n\t\t\t\treturn error(state, `illegal transition ${current.status} -> ${nextStatus}`);\n\t\t\t}\n\n\t\t\tlet nextDeps = current.blockedBy ? [...current.blockedBy] : [];\n\t\t\tif (params.removeBlockedBy?.length) {\n\t\t\t\tconst remove = new Set(params.removeBlockedBy);\n\t\t\t\tnextDeps = nextDeps.filter((id) => !remove.has(id));\n\t\t\t}\n\t\t\tif (params.addBlockedBy?.length) {\n\t\t\t\tconst dependencyError = validateDependencies(state, params.addBlockedBy, current.id);\n\t\t\t\tif (dependencyError) return error(state, dependencyError);\n\t\t\t\tfor (const dep of params.addBlockedBy) {\n\t\t\t\t\tif (!nextDeps.includes(dep)) nextDeps.push(dep);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (createsCycle(state.items, current.id, nextDeps)) {\n\t\t\t\treturn error(state, \"blockedBy would create a cycle\");\n\t\t\t}\n\n\t\t\tif ((nextStatus === \"in_progress\" || nextStatus === \"completed\") && current.status !== nextStatus) {\n\t\t\t\tconst readyError = validateDependenciesReady(state, nextDeps);\n\t\t\t\tif (readyError) return error(state, readyError);\n\t\t\t}\n\n\t\t\tconst updated: TodoItem = { ...current, status: nextStatus };\n\t\t\tif (params.subject !== undefined) updated.subject = params.subject.trim();\n\t\t\tif (params.description !== undefined) updated.description = params.description;\n\t\t\tif (params.activeForm !== undefined) updated.activeForm = params.activeForm;\n\t\t\tif (params.owner !== undefined) updated.owner = params.owner;\n\t\t\tif (nextDeps.length) updated.blockedBy = nextDeps;\n\t\t\telse delete updated.blockedBy;\n\n\t\t\tif (params.metadata !== undefined) {\n\t\t\t\tconst merged = { ...(current.metadata ?? {}) };\n\t\t\t\tfor (const [key, value] of Object.entries(params.metadata)) {\n\t\t\t\t\tif (value === null) delete merged[key];\n\t\t\t\t\telse merged[key] = value;\n\t\t\t\t}\n\t\t\t\tif (Object.keys(merged).length) updated.metadata = merged;\n\t\t\t\telse delete updated.metadata;\n\t\t\t}\n\n\t\t\tconst items = [...state.items];\n\t\t\titems[index] = updated;\n\n\t\t\t// Exactly one in_progress: demote any other active tasks to pending.\n\t\t\tconst demotedIds: number[] = [];\n\t\t\tif (nextStatus === \"in_progress\") {\n\t\t\t\tfor (let i = 0; i < items.length; i++) {\n\t\t\t\t\tconst item = items[i];\n\t\t\t\t\tif (item.id === updated.id) continue;\n\t\t\t\t\tif (item.status !== \"in_progress\") continue;\n\t\t\t\t\titems[i] = { ...item, status: \"pending\" };\n\t\t\t\t\tdemotedIds.push(item.id);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst nextState: TodoState = { items, nextId: state.nextId };\n\t\t\tconst newlyCompleted = current.status !== \"completed\" && nextStatus === \"completed\";\n\t\t\treturn {\n\t\t\t\tstate: nextState,\n\t\t\t\toperation: {\n\t\t\t\t\tkind: \"update\",\n\t\t\t\t\tid: updated.id,\n\t\t\t\t\tfrom: current.status,\n\t\t\t\t\tto: updated.status,\n\t\t\t\t\t...(demotedIds.length ? { demotedIds } : {}),\n\t\t\t\t\t...(newlyCompleted && needsVerificationNudge(nextState) ? { verificationNudge: true } : {}),\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tcase \"list\":\n\t\t\treturn {\n\t\t\t\tstate,\n\t\t\t\toperation: {\n\t\t\t\t\tkind: \"list\",\n\t\t\t\t\tstatus: params.status,\n\t\t\t\t\tincludeDeleted: params.includeDeleted === true,\n\t\t\t\t},\n\t\t\t};\n\n\t\tcase \"get\": {\n\t\t\tif (params.id === undefined) return error(state, \"id required for get\");\n\t\t\tconst item = findItem(state, params.id);\n\t\t\tif (!item) return error(state, `#${params.id} not found`);\n\t\t\treturn { state, operation: { kind: \"get\", item } };\n\t\t}\n\n\t\tcase \"delete\": {\n\t\t\tif (params.id === undefined) return error(state, \"id required for delete\");\n\t\t\tconst index = state.items.findIndex((item) => item.id === params.id);\n\t\t\tif (index === -1) return error(state, `#${params.id} not found`);\n\t\t\tconst current = state.items[index];\n\t\t\tif (current.status === \"deleted\") return error(state, `#${params.id} is already deleted`);\n\n\t\t\treturn {\n\t\t\t\tstate: markDeleted(state, current.id),\n\t\t\t\toperation: { kind: \"delete\", id: current.id, subject: current.subject },\n\t\t\t};\n\t\t}\n\n\t\tcase \"clear\":\n\t\t\treturn {\n\t\t\t\t// IDs remain monotonic across a clear so stale references cannot point\n\t\t\t\t// at an unrelated task created later on the same conversation branch.\n\t\t\t\tstate: { items: [], nextId: state.nextId },\n\t\t\t\toperation: { kind: \"clear\", count: state.items.length },\n\t\t\t};\n\t}\n\n\treturn error(state, `unknown action: ${(params as { action?: unknown }).action}`);\n}\n\nfunction isTodoDetails(value: unknown): value is TodoDetails {\n\tif (!value || typeof value !== \"object\") return false;\n\tconst record = value as Record<string, unknown>;\n\treturn Array.isArray(record.items) && typeof record.nextId === \"number\";\n}\n\nexport function replayTodosFromBranch(ctx: { sessionManager: { getBranch(): Iterable<unknown> } }): TodoState {\n\t// Latest todo toolResult wins; scan tail → head so long branches stop early.\n\tconst branch = Array.from(ctx.sessionManager.getBranch());\n\tfor (let i = branch.length - 1; i >= 0; i--) {\n\t\tconst item = branch[i] as {\n\t\t\ttype?: string;\n\t\t\tmessage?: { role?: string; toolName?: string; details?: unknown };\n\t\t};\n\t\tif (item.type !== \"message\") continue;\n\t\tif (item.message?.role !== \"toolResult\" || item.message.toolName !== TODO_TOOL_NAME) continue;\n\t\tif (!isTodoDetails(item.message.details)) continue;\n\t\treturn cloneState({\n\t\t\titems: item.message.details.items,\n\t\t\tnextId: item.message.details.nextId,\n\t\t});\n\t}\n\treturn cloneState(EMPTY_TODO_STATE);\n}\n\nexport function buildTodoDetails(params: TodoParams, next: TodoState, operation: Operation): TodoDetails {\n\treturn {\n\t\taction: params.action,\n\t\tparams: params as Record<string, unknown>,\n\t\titems: cloneState(next).items,\n\t\tnextId: next.nextId,\n\t\t...(operation.kind === \"error\" ? { error: operation.message } : {}),\n\t};\n}\n\nconst VERIFICATION_NUDGE_NOTE =\n\t\"NOTE: You closed out 3+ tasks with no verification/test/review step. Before the final summary, run checks or add a verification task and complete it — do not self-declare done with known failures.\";\n\nexport function formatTodoContent(operation: Operation, state: TodoState): string {\n\tswitch (operation.kind) {\n\t\tcase \"create\": {\n\t\t\tconst item = findItem(state, operation.id);\n\t\t\treturn item ? `Created #${item.id}: ${item.subject} (pending)` : `Created #${operation.id}`;\n\t\t}\n\t\tcase \"update\": {\n\t\t\tconst transition = operation.from === operation.to ? \"\" : ` (${operation.from} -> ${operation.to})`;\n\t\t\tlet text = `Updated #${operation.id}${transition}`;\n\t\t\tif (operation.demotedIds?.length) {\n\t\t\t\ttext += `; ${operation.demotedIds.map((id) => `#${id}`).join(\",\")} demoted to pending`;\n\t\t\t}\n\t\t\tif (operation.verificationNudge) text += `\\n\\n${VERIFICATION_NUDGE_NOTE}`;\n\t\t\treturn text;\n\t\t}\n\t\tcase \"delete\":\n\t\t\treturn `Deleted #${operation.id}: ${operation.subject}`;\n\t\tcase \"clear\":\n\t\t\treturn `Cleared ${operation.count} tasks`;\n\t\tcase \"list\": {\n\t\t\tlet view = state.items;\n\t\t\t// An explicit deleted-status query is sufficient intent to include tombstones.\n\t\t\tif (!operation.includeDeleted && operation.status !== \"deleted\")\n\t\t\t\tview = view.filter((item) => item.status !== \"deleted\");\n\t\t\tif (operation.status) view = view.filter((item) => item.status === operation.status);\n\t\t\treturn formatBoundedList(view, operation.status, operation.includeDeleted);\n\t\t}\n\t\tcase \"get\":\n\t\t\treturn formatDetailItem(operation.item, state);\n\t\tcase \"error\":\n\t\t\treturn `Error: ${operation.message}`;\n\t}\n}\n\n/**\n * Soft nudge when the whole list is done (no active work), there are 3+ completed\n * tasks, and none look like a verification/test/review step — mirrors CC TodoWrite.\n */\nfunction needsVerificationNudge(state: TodoState): boolean {\n\tconst active = state.items.filter((item) => item.status !== \"deleted\");\n\tif (active.length < 3) return false;\n\tif (active.some((item) => item.status === \"pending\" || item.status === \"in_progress\")) return false;\n\tconst completed = active.filter((item) => item.status === \"completed\");\n\tif (completed.length < 3) return false;\n\treturn !completed.some(\n\t\t(item) =>\n\t\t\tVERIFICATION_PATTERN.test(item.subject) ||\n\t\t\t(item.description !== undefined && VERIFICATION_PATTERN.test(item.description)),\n\t);\n}\n\nfunction formatBoundedList(view: TodoItem[], statusFilter: TodoStatus | undefined, includeDeleted: boolean): string {\n\tif (!view.length) return \"No tasks\";\n\tconst shown = view.slice(0, LIST_DISPLAY_MAX_ITEMS);\n\tconst lines = shown.map(formatListItem);\n\tconst omitted = view.length - shown.length;\n\tif (omitted > 0) {\n\t\tconst filterHint = statusFilter ? `status=${statusFilter}` : includeDeleted ? \"includeDeleted=true\" : \"list\";\n\t\tlines.push(\n\t\t\t`… and ${omitted} more (${shown.length} of ${view.length} shown). Narrow with ${filterHint} or use get with id=.`,\n\t\t);\n\t}\n\treturn lines.join(\"\\n\");\n}\n\nfunction formatListItem(item: TodoItem): string {\n\tconst deps = item.blockedBy?.length ? ` blockedBy=${item.blockedBy.map((id) => `#${id}`).join(\",\")}` : \"\";\n\tconst active = item.status === \"in_progress\" && item.activeForm ? ` (${item.activeForm})` : \"\";\n\treturn `[${item.status}] #${item.id} ${item.subject}${active}${deps}`;\n}\n\nfunction formatDetailItem(item: TodoItem, state: TodoState): string {\n\tconst lines = [`#${item.id} [${item.status}] ${item.subject}`];\n\tif (item.description) lines.push(`description: ${item.description}`);\n\tif (item.activeForm) lines.push(`activeForm: ${item.activeForm}`);\n\tif (item.blockedBy?.length) lines.push(`blockedBy: ${item.blockedBy.map((id) => `#${id}`).join(\", \")}`);\n\tconst blocks = state.items\n\t\t.filter((candidate) => candidate.blockedBy?.includes(item.id))\n\t\t.map((candidate) => candidate.id);\n\tif (blocks.length) lines.push(`blocks: ${blocks.map((id) => `#${id}`).join(\", \")}`);\n\tif (item.owner) lines.push(`owner: ${item.owner}`);\n\treturn lines.join(\"\\n\");\n}\n"]}
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../../../src/extensions/todo/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACxE,OAAO,EACN,gBAAgB,GAOhB,MAAM,aAAa,CAAC;AAsBrB,qFAAqF;AACrF,MAAM,oBAAoB,GAAG,0BAA0B,CAAC;AAOxD,gFAAgF;AAChF,+EAA+E;AAC/E,4EAA4E;AAC5E,0EAA0E;AAC1E,6EAA6E;AAC7E,qEAAqE;AACrE,MAAM,MAAM,GAAG,IAAI,GAAG,EAAqB,CAAC;AAC5C,IAAI,SAAS,GAAG,EAAE,CAAC;AAEnB,kFAAkF;AAClF,MAAM,UAAU,oBAAoB,CAAC,GAAW,EAAQ;IACvD,SAAS,GAAG,GAAG,CAAC;AAAA,CAChB;AAED,8FAA8F;AAC9F,MAAM,UAAU,YAAY,GAAc;IACzC,OAAO,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,gBAAgB,CAAC,CAAC;AAAA,CAC7D;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAe,EAAQ;IACvD,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;AAAA,CACxC;AAED,MAAM,UAAU,eAAe,CAAC,IAAe,EAAQ;IACtD,gBAAgB,CAAC,IAAI,CAAC,CAAC;AAAA,CACvB;AAED,uEAAuE;AACvE,MAAM,UAAU,kBAAkB,CAAC,GAAW,EAAQ;IACrD,IAAI,CAAC,GAAG;QAAE,OAAO;IACjB,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACnB,IAAI,SAAS,KAAK,GAAG;QAAE,SAAS,GAAG,EAAE,CAAC;AAAA,CACtC;AAED,MAAM,UAAU,UAAU,CAAC,MAAiB,EAAa;IACxD,OAAO;QACN,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;YACjC,MAAM,KAAK,GAAa,EAAE,GAAG,IAAI,EAAE,CAAC;YACpC,IAAI,IAAI,CAAC,SAAS;gBAAE,KAAK,CAAC,SAAS,GAAG,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;;gBACrD,OAAO,KAAK,CAAC,SAAS,CAAC;YAC5B,IAAI,IAAI,CAAC,QAAQ;gBAAE,KAAK,CAAC,QAAQ,GAAG,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;;gBACpD,OAAO,KAAK,CAAC,QAAQ,CAAC;YAC3B,OAAO,KAAK,CAAC;QAAA,CACb,CAAC;QACF,MAAM,EAAE,MAAM,CAAC,MAAM;KACrB,CAAC;AAAA,CACF;AAED,SAAS,aAAa,CAAC,IAAc,EAAY;IAChD,MAAM,IAAI,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC;IACzB,OAAO,IAAI,CAAC,SAAS,CAAC;IACtB,OAAO,IAAI,CAAC;AAAA,CACZ;AAED;;;;GAIG;AACH,SAAS,WAAW,CAAC,KAAgB,EAAE,EAAU,EAA+C;IAC/F,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QACvC,IAAI,IAAI,CAAC,EAAE,KAAK,EAAE;YAAE,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,SAAkB,EAAE,CAAC;QACnE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,EAAE,CAAC;YAAE,OAAO,IAAI,CAAC;QAC/C,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,YAAY,KAAK,EAAE,CAAC,CAAC;QAC/E,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAAA,CACvE,CAAC,CAAC;IACH,MAAM,SAAS,GAAc,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;IAC7D,MAAM,WAAW,GAAG,KAAK,CAAC,KAAK;SAC7B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;SAC7F,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;SACtB,MAAM,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;QACxB,MAAM,SAAS,GAAG,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;QACnD,OAAO,SAAS,KAAK,SAAS,IAAI,uBAAuB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;IAAA,CAC7F,CAAC,CAAC;IACJ,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC;AAAA,CACzC;AAED,SAAS,KAAK,CAAC,KAAgB,EAAE,OAAe,EAAkB;IACjE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC;AAAA,CACxD;AAED,+EAA+E;AAC/E,0EAA0E;AAC1E,6EAA6E;AAC7E,uDAAuD;AACvD,MAAM,aAAa,GAA4C;IAC9D,MAAM,EAAE,IAAI,GAAG,CAAC,CAAC,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;IACrG,MAAM,EAAE,IAAI,GAAG,CAAC;QACf,IAAI;QACJ,SAAS;QACT,aAAa;QACb,YAAY;QACZ,QAAQ;QACR,cAAc;QACd,iBAAiB;QACjB,WAAW;QACX,cAAc;QACd,OAAO;QACP,UAAU;KACV,CAAC;IACF,IAAI,EAAE,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;IAC3C,GAAG,EAAE,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;IACpB,MAAM,EAAE,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;IACvB,KAAK,EAAE,IAAI,GAAG,EAAU;CACxB,CAAC;AAEF,MAAM,uBAAuB,GAAG,IAAI,GAAG,CAAC,CAAC,cAAc,EAAE,iBAAiB,EAAE,WAAW,EAAE,cAAc,CAAC,CAAC,CAAC;AAE1G,SAAS,sBAAsB,CAAC,MAAkB,EAAE,GAAW,EAAU;IACxE,IAAI,MAAM,KAAK,QAAQ,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;QAChD,OAAO,sEAAsE,CAAC;IAC/E,CAAC;IACD,IAAI,MAAM,KAAK,QAAQ,IAAI,uBAAuB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7D,OAAO,GAAG,GAAG,0CAA0C,CAAC;IACzD,CAAC;IACD,OAAO,GAAG,GAAG,6BAA6B,MAAM,EAAE,CAAC;AAAA,CACnD;AAED,SAAS,qBAAqB,CAAC,MAAkB,EAAsB;IACtE,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC7C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACnD,IAAI,GAAG,KAAK,QAAQ,IAAI,KAAK,KAAK,SAAS;YAAE,SAAS;QACtD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO,sBAAsB,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,SAAS,CAAC;AAAA,CACjB;AAED,SAAS,mBAAmB,CAAC,IAAgB,EAAE,EAAc,EAAW;IACvE,wEAAwE;IACxE,2EAA2E;IAC3E,uCAAuC;IACvC,IAAI,IAAI,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAC7B,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACrC,IAAI,EAAE,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAClC,IAAI,EAAE,KAAK,WAAW;QAAE,OAAO,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,aAAa,CAAC;IAC5E,IAAI,EAAE,KAAK,SAAS;QAAE,OAAO,IAAI,KAAK,aAAa,IAAI,IAAI,KAAK,WAAW,CAAC;IAC5E,IAAI,EAAE,KAAK,aAAa;QAAE,OAAO,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,WAAW,CAAC;IAC5E,OAAO,KAAK,CAAC;AAAA,CACb;AAED,SAAS,QAAQ,CAAC,KAAgB,EAAE,EAAU,EAAwB;IACrE,OAAO,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;AAAA,CAClD;AAED,SAAS,oBAAoB,CAAC,KAAgB,EAAE,IAA0B,EAAE,SAAkB,EAAsB;IACnH,IAAI,CAAC,IAAI,EAAE,MAAM;QAAE,OAAO,SAAS,CAAC;IACpC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACxB,IAAI,GAAG,KAAK,SAAS;YAAE,OAAO,iBAAiB,SAAS,YAAY,CAAC;QACrE,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,IAAI;YAAE,OAAO,eAAe,GAAG,YAAY,CAAC;QACjD,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;YAAE,OAAO,eAAe,GAAG,aAAa,CAAC;IACvE,CAAC;IACD,OAAO,SAAS,CAAC;AAAA,CACjB;AAED,mFAAmF;AACnF,SAAS,yBAAyB,CAAC,KAAgB,EAAE,IAA0B,EAAsB;IACpG,IAAI,CAAC,IAAI,EAAE,MAAM;QAAE,OAAO,SAAS,CAAC;IACpC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YAC1C,OAAO,wBAAwB,GAAG,yCAAyC,CAAC;QAC7E,CAAC;IACF,CAAC;IACD,OAAO,SAAS,CAAC;AAAA,CACjB;AAED,iFAAiF;AACjF,MAAM,UAAU,uBAAuB,CAAC,KAAgB,EAAE,IAAc,EAAY;IACnF,OAAO,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,MAAM,KAAK,WAAW,CAAC,CAAC;AAAA,CAC1F;AAED,6FAA6F;AAC7F,MAAM,UAAU,qBAAqB,CAAC,KAAgB,EAAE,IAAc,EAAW;IAChF,OAAO,uBAAuB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;AAAA,CACzD;AAED,qGAAqG;AACrG,SAAS,YAAY,CAAC,KAAiB,EAAE,YAA2C,EAAW;IAC9F,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC7C,KAAK,MAAM,IAAI,IAAI,KAAK;QAAE,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;IACtE,KAAK,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,YAAY;QAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IAE9D,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAEhC,SAAS,KAAK,CAAC,IAAY,EAAW;QACrC,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QACjC,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,OAAO,KAAK,CAAC;QACjC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACf,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAChB,KAAK,MAAM,GAAG,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;YAC5C,IAAI,KAAK,CAAC,GAAG,CAAC;gBAAE,OAAO,IAAI,CAAC;QAC7B,CAAC;QACD,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACnB,OAAO,KAAK,CAAC;IAAA,CACb;IAED,KAAK,MAAM,EAAE,IAAI,YAAY,CAAC,IAAI,EAAE,EAAE,CAAC;QACtC,IAAI,KAAK,CAAC,EAAE,CAAC;YAAE,OAAO,IAAI,CAAC;IAC5B,CAAC;IACD,OAAO,KAAK,CAAC;AAAA,CACb;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAgB,EAAE,MAAkB,EAAkB;IACvF,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAEhC,MAAM,YAAY,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;IACnD,IAAI,YAAY;QAAE,OAAO,KAAK,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;IAEpD,QAAQ,MAAM,CAAC,MAAM,EAAE,CAAC;QACvB,KAAK,QAAQ,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC;YACvC,IAAI,CAAC,OAAO;gBAAE,OAAO,KAAK,CAAC,KAAK,EAAE,6BAA6B,CAAC,CAAC;YACjE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,IAAI,EAAE,EAAE,CAAC;gBACjC,OAAO,KAAK,CAAC,KAAK,EAAE,sEAAsE,CAAC,CAAC;YAC7F,CAAC;YACD,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBAChE,OAAO,KAAK,CAAC,KAAK,EAAE,sEAAsE,CAAC,CAAC;YAC7F,CAAC;YACD,MAAM,eAAe,GAAG,oBAAoB,CAAC,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;YACtE,IAAI,eAAe;gBAAE,OAAO,KAAK,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;YAE1D,MAAM,IAAI,GAAa;gBACtB,EAAE,EAAE,KAAK,CAAC,MAAM;gBAChB,OAAO;gBACP,MAAM,EAAE,SAAS;gBACjB,WAAW,EAAE,MAAM,CAAC,WAAW;aAC/B,CAAC;YACF,IAAI,MAAM,CAAC,UAAU;gBAAE,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;YAC3D,IAAI,MAAM,CAAC,SAAS,EAAE,MAAM;gBAAE,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAS,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;YAC7F,IAAI,MAAM,CAAC,KAAK;gBAAE,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;YAC5C,IAAI,MAAM,CAAC,QAAQ;gBAAE,IAAI,CAAC,QAAQ,GAAG,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;YAE5D,OAAO;gBACN,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,GAAG,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE;gBAClE,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE;aAC1C,CAAC;QACH,CAAC;QAED,KAAK,QAAQ,EAAE,CAAC;YACf,IAAI,MAAM,CAAC,EAAE,KAAK,SAAS;gBAAE,OAAO,KAAK,CAAC,KAAK,EAAE,wBAAwB,CAAC,CAAC;YAC3E,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC;YACrE,IAAI,KAAK,KAAK,CAAC,CAAC;gBAAE,OAAO,KAAK,CAAC,KAAK,EAAE,IAAI,MAAM,CAAC,EAAE,YAAY,CAAC,CAAC;YACjE,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACnC,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS;gBAAE,OAAO,KAAK,CAAC,KAAK,EAAE,IAAI,MAAM,CAAC,EAAE,mCAAmC,CAAC,CAAC;YACxG,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE;gBAAE,OAAO,KAAK,CAAC,KAAK,EAAE,yBAAyB,CAAC,CAAC;YAE3G,MAAM,UAAU,GACf,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC;gBACtC,CAAC,MAAM,CAAC,eAAe,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC;gBACzC,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC;gBACnC,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;YACxC,MAAM,WAAW,GAChB,MAAM,CAAC,OAAO,KAAK,SAAS;gBAC5B,MAAM,CAAC,WAAW,KAAK,SAAS;gBAChC,MAAM,CAAC,UAAU,KAAK,SAAS;gBAC/B,MAAM,CAAC,KAAK,KAAK,SAAS;gBAC1B,MAAM,CAAC,QAAQ,KAAK,SAAS,CAAC;YAC/B,IAAI,CAAC,WAAW,IAAI,CAAC,UAAU,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBAChE,OAAO,KAAK,CAAC,KAAK,EAAE,oCAAoC,CAAC,CAAC;YAC3D,CAAC;YAED,sEAAsE;YACtE,uEAAuE;YACvE,oEAAoE;YACpE,4CAA4C;YAC5C,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBACjC,IAAI,WAAW,IAAI,UAAU,EAAE,CAAC;oBAC/B,OAAO,KAAK,CACX,KAAK,EACL,sGAAsG,CACtG,CAAC;gBACH,CAAC;gBACD,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;gBAC/C,OAAO;oBACN,KAAK,EAAE,OAAO,CAAC,KAAK;oBACpB,SAAS,EAAE;wBACV,IAAI,EAAE,QAAQ;wBACd,EAAE,EAAE,OAAO,CAAC,EAAE;wBACd,IAAI,EAAE,OAAO,CAAC,MAAM;wBACpB,EAAE,EAAE,SAAS;wBACb,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;qBAC3E;iBACD,CAAC;YACH,CAAC;YAED,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;YACnD,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,CAAC;gBACtD,OAAO,KAAK,CAAC,KAAK,EAAE,sBAAsB,OAAO,CAAC,MAAM,OAAO,UAAU,EAAE,CAAC,CAAC;YAC9E,CAAC;YAED,wEAAwE;YACxE,yEAAyE;YACzE,MAAM,YAAY,GAAG,IAAI,GAAG,EAAoB,CAAC;YACjD,IAAI,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/D,IAAI,MAAM,CAAC,eAAe,EAAE,MAAM,EAAE,CAAC;gBACpC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;gBAC/C,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;YACrD,CAAC;YACD,IAAI,MAAM,CAAC,YAAY,EAAE,MAAM,EAAE,CAAC;gBACjC,MAAM,eAAe,GAAG,oBAAoB,CAAC,KAAK,EAAE,MAAM,CAAC,YAAY,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;gBACrF,IAAI,eAAe;oBAAE,OAAO,KAAK,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;gBAC1D,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;oBACvC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC;wBAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACjD,CAAC;YACF,CAAC;YACD,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;YAEvC,IAAI,MAAM,CAAC,YAAY,EAAE,MAAM,EAAE,CAAC;gBACjC,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;gBAC7C,KAAK,MAAM,SAAS,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;oBACrC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;wBAAE,SAAS;oBACvF,YAAY,CAAC,GAAG,CACf,SAAS,CAAC,EAAE,EACZ,SAAS,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,YAAY,KAAK,OAAO,CAAC,EAAE,CAAC,CACzE,CAAC;gBACH,CAAC;YACF,CAAC;YACD,IAAI,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;gBAC9B,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;oBACzC,IAAI,QAAQ,KAAK,OAAO,CAAC,EAAE;wBAAE,OAAO,KAAK,CAAC,KAAK,EAAE,iBAAiB,QAAQ,YAAY,CAAC,CAAC;oBACxF,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;oBACzC,IAAI,CAAC,MAAM;wBAAE,OAAO,KAAK,CAAC,KAAK,EAAE,eAAe,QAAQ,YAAY,CAAC,CAAC;oBACtE,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS;wBAAE,OAAO,KAAK,CAAC,KAAK,EAAE,eAAe,QAAQ,aAAa,CAAC,CAAC;oBAC3F,MAAM,IAAI,GAAG,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;oBAC3F,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;wBAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;oBACtD,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;gBAClC,CAAC;YACF,CAAC;YACD,IAAI,YAAY,CAAC,KAAK,CAAC,KAAK,EAAE,YAAY,CAAC,EAAE,CAAC;gBAC7C,OAAO,KAAK,CAAC,KAAK,EAAE,gCAAgC,CAAC,CAAC;YACvD,CAAC;YAED,yEAAyE;YACzE,yEAAuE;YACvE,qDAAqD;YACrD,IAAI,CAAC,UAAU,KAAK,aAAa,IAAI,UAAU,KAAK,WAAW,CAAC,IAAI,OAAO,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;gBACnG,MAAM,UAAU,GAAG,yBAAyB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;gBAC9D,IAAI,UAAU;oBAAE,OAAO,KAAK,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;YACjD,CAAC;YAED,MAAM,OAAO,GAAa,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;YAC7D,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS;gBAAE,OAAO,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAC1E,yEAAyE;YACzE,IAAI,MAAM,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;gBACtC,IAAI,MAAM,CAAC,WAAW;oBAAE,OAAO,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;;oBAC5D,OAAO,OAAO,CAAC,WAAW,CAAC;YACjC,CAAC;YACD,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;gBACrC,IAAI,MAAM,CAAC,UAAU;oBAAE,OAAO,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;;oBACzD,OAAO,OAAO,CAAC,UAAU,CAAC;YAChC,CAAC;YACD,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;gBAChC,IAAI,MAAM,CAAC,KAAK;oBAAE,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;;oBAC1C,OAAO,OAAO,CAAC,KAAK,CAAC;YAC3B,CAAC;YACD,IAAI,QAAQ,CAAC,MAAM;gBAAE,OAAO,CAAC,SAAS,GAAG,QAAQ,CAAC;;gBAC7C,OAAO,OAAO,CAAC,SAAS,CAAC;YAE9B,IAAI,MAAM,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;gBACnC,MAAM,MAAM,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE,CAAC;gBAC/C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAC5D,IAAI,KAAK,KAAK,IAAI;wBAAE,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;;wBAClC,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;gBAC1B,CAAC;gBACD,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM;oBAAE,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC;;oBACrD,OAAO,OAAO,CAAC,QAAQ,CAAC;YAC9B,CAAC;YAED,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;gBACvC,IAAI,IAAI,CAAC,EAAE,KAAK,OAAO,CAAC,EAAE;oBAAE,OAAO,IAAI,CAAC;gBACxC,MAAM,IAAI,GAAG,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACvC,IAAI,IAAI,KAAK,SAAS;oBAAE,OAAO,IAAI,CAAC;gBACpC,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;YAAA,CACxE,CAAC,CAAC;YACH,KAAK,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC;YAEvB,qEAAqE;YACrE,MAAM,UAAU,GAAa,EAAE,CAAC;YAChC,IAAI,UAAU,KAAK,aAAa,EAAE,CAAC;gBAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBACvC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;oBACtB,IAAI,IAAI,CAAC,EAAE,KAAK,OAAO,CAAC,EAAE;wBAAE,SAAS;oBACrC,IAAI,IAAI,CAAC,MAAM,KAAK,aAAa;wBAAE,SAAS;oBAC5C,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;oBAC1C,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBAC1B,CAAC;YACF,CAAC;YAED,MAAM,SAAS,GAAc,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;YAC7D,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,KAAK,WAAW,IAAI,UAAU,KAAK,WAAW,CAAC;YACpF,OAAO;gBACN,KAAK,EAAE,SAAS;gBAChB,SAAS,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,EAAE,EAAE,OAAO,CAAC,EAAE;oBACd,IAAI,EAAE,OAAO,CAAC,MAAM;oBACpB,EAAE,EAAE,OAAO,CAAC,MAAM;oBAClB,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC5C,GAAG,CAAC,cAAc,IAAI,sBAAsB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBAC3F;aACD,CAAC;QACH,CAAC;QAED,KAAK,MAAM;YACV,OAAO;gBACN,KAAK;gBACL,SAAS,EAAE;oBACV,IAAI,EAAE,MAAM;oBACZ,MAAM,EAAE,MAAM,CAAC,MAAM;oBACrB,cAAc,EAAE,MAAM,CAAC,cAAc,KAAK,IAAI;iBAC9C;aACD,CAAC;QAEH,KAAK,KAAK,EAAE,CAAC;YACZ,IAAI,MAAM,CAAC,EAAE,KAAK,SAAS;gBAAE,OAAO,KAAK,CAAC,KAAK,EAAE,qBAAqB,CAAC,CAAC;YACxE,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;YACxC,IAAI,CAAC,IAAI;gBAAE,OAAO,KAAK,CAAC,KAAK,EAAE,IAAI,MAAM,CAAC,EAAE,YAAY,CAAC,CAAC;YAC1D,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC;QACpD,CAAC;QAED,KAAK,QAAQ,EAAE,CAAC;YACf,IAAI,MAAM,CAAC,EAAE,KAAK,SAAS;gBAAE,OAAO,KAAK,CAAC,KAAK,EAAE,wBAAwB,CAAC,CAAC;YAC3E,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC;YACrE,IAAI,KAAK,KAAK,CAAC,CAAC;gBAAE,OAAO,KAAK,CAAC,KAAK,EAAE,IAAI,MAAM,CAAC,EAAE,YAAY,CAAC,CAAC;YACjE,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACnC,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS;gBAAE,OAAO,KAAK,CAAC,KAAK,EAAE,IAAI,MAAM,CAAC,EAAE,qBAAqB,CAAC,CAAC;YAE1F,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;YAC/C,OAAO;gBACN,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,SAAS,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,EAAE,EAAE,OAAO,CAAC,EAAE;oBACd,OAAO,EAAE,OAAO,CAAC,OAAO;oBACxB,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBAC3E;aACD,CAAC;QACH,CAAC;QAED,KAAK,OAAO;YACX,OAAO;gBACN,uEAAuE;gBACvE,sEAAsE;gBACtE,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE;gBAC1C,SAAS,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE;aACvD,CAAC;IACJ,CAAC;IAED,OAAO,KAAK,CAAC,KAAK,EAAE,mBAAoB,MAA+B,CAAC,MAAM,EAAE,CAAC,CAAC;AAAA,CAClF;AAED,SAAS,aAAa,CAAC,KAAc,EAAwB;IAC5D,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACtD,MAAM,MAAM,GAAG,KAAgC,CAAC;IAChD,OAAO,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC;AAAA,CACxE;AAED,MAAM,UAAU,qBAAqB,CAAC,GAA2D,EAAa;IAC7G,+EAA6E;IAC7E,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC,SAAS,EAAE,CAAC,CAAC;IAC1D,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7C,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAGpB,CAAC;QACF,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;YAAE,SAAS;QACtC,IAAI,IAAI,CAAC,OAAO,EAAE,IAAI,KAAK,YAAY,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,KAAK,cAAc;YAAE,SAAS;QAC9F,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC;YAAE,SAAS;QACnD,OAAO,UAAU,CAAC;YACjB,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK;YACjC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM;SACnC,CAAC,CAAC;IACJ,CAAC;IACD,OAAO,UAAU,CAAC,gBAAgB,CAAC,CAAC;AAAA,CACpC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAkB,EAAE,IAAe,EAAe;IAClF,OAAO;QACN,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,MAAM,EAAE,MAAiC;QACzC,KAAK,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK;QAC7B,MAAM,EAAE,IAAI,CAAC,MAAM;KACnB,CAAC;AAAA,CACF;AAED,MAAM,uBAAuB,GAC5B,wMAAsM,CAAC;AAExM,SAAS,oBAAoB,CAAC,WAAiC,EAAU;IACxE,IAAI,CAAC,WAAW,EAAE,MAAM;QAAE,OAAO,EAAE,CAAC;IACpC,OAAO,cAAc,WAAW,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,sBAAsB,CAAC;AAAA,CACvF;AAED,MAAM,UAAU,iBAAiB,CAAC,SAAoB,EAAE,KAAgB,EAAU;IACjF,QAAQ,SAAS,CAAC,IAAI,EAAE,CAAC;QACxB,KAAK,QAAQ,EAAE,CAAC;YACf,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC;YAC3C,OAAO,IAAI,CAAC,CAAC,CAAC,YAAY,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,OAAO,YAAY,CAAC,CAAC,CAAC,YAAY,SAAS,CAAC,EAAE,EAAE,CAAC;QAC7F,CAAC;QACD,KAAK,QAAQ,EAAE,CAAC;YACf,MAAM,UAAU,GAAG,SAAS,CAAC,IAAI,KAAK,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,IAAI,OAAO,SAAS,CAAC,EAAE,GAAG,CAAC;YACpG,IAAI,IAAI,GAAG,YAAY,SAAS,CAAC,EAAE,GAAG,UAAU,EAAE,CAAC;YACnD,IAAI,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC;gBAClC,IAAI,IAAI,KAAK,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,qBAAqB,CAAC;YACxF,CAAC;YACD,IAAI,IAAI,oBAAoB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;YACpD,IAAI,SAAS,CAAC,iBAAiB;gBAAE,IAAI,IAAI,OAAO,uBAAuB,EAAE,CAAC;YAC1E,OAAO,IAAI,CAAC;QACb,CAAC;QACD,KAAK,QAAQ;YACZ,OAAO,YAAY,SAAS,CAAC,EAAE,KAAK,SAAS,CAAC,OAAO,GAAG,oBAAoB,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE,CAAC;QACvG,KAAK,OAAO;YACX,OAAO,WAAW,SAAS,CAAC,KAAK,QAAQ,CAAC;QAC3C,KAAK,MAAM,EAAE,CAAC;YACb,IAAI,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC;YACvB,+EAA+E;YAC/E,IAAI,CAAC,SAAS,CAAC,cAAc,IAAI,SAAS,CAAC,MAAM,KAAK,SAAS;gBAC9D,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC;YACzD,IAAI,SAAS,CAAC,MAAM;gBAAE,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,MAAM,CAAC,CAAC;YACrF,OAAO,iBAAiB,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;QACzD,CAAC;QACD,KAAK,KAAK;YACT,OAAO,gBAAgB,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAChD,KAAK,OAAO;YACX,OAAO,UAAU,SAAS,CAAC,OAAO,EAAE,CAAC;IACvC,CAAC;AAAA,CACD;AAED;;;GAGG;AACH,SAAS,sBAAsB,CAAC,KAAgB,EAAW;IAC1D,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC;IACvE,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IACpC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,KAAK,aAAa,CAAC;QAAE,OAAO,KAAK,CAAC;IACpG,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC;IACvE,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IACvC,OAAO,CAAC,SAAS,CAAC,IAAI,CACrB,CAAC,IAAI,EAAE,EAAE,CACR,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;QACvC,CAAC,IAAI,CAAC,WAAW,KAAK,SAAS,IAAI,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAChF,CAAC;AAAA,CACF;AAED,SAAS,iBAAiB,CAAC,IAAgB,EAAE,KAAgB,EAAE,YAAoC,EAAU;IAC5G,IAAI,CAAC,IAAI,CAAC,MAAM;QAAE,OAAO,UAAU,CAAC;IACpC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,sBAAsB,CAAC,CAAC;IACpD,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;IAC/D,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAC3C,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;QACjB,mDAAmD;QACnD,MAAM,IAAI,GAAG,YAAY,CAAC,CAAC,CAAC,8BAA8B,CAAC,CAAC,CAAC,yCAAyC,CAAC;QACvG,KAAK,CAAC,IAAI,CAAC,WAAS,OAAO,UAAU,KAAK,CAAC,MAAM,OAAO,IAAI,CAAC,MAAM,YAAY,IAAI,GAAG,CAAC,CAAC;IACzF,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAAA,CACxB;AAED,SAAS,cAAc,CAAC,IAAc,EAAE,KAAgB,EAAU;IACjE,MAAM,UAAU,GAAG,uBAAuB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACxD,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACjG,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAClD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,KAAK,aAAa,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/F,OAAO,IAAI,IAAI,CAAC,MAAM,MAAM,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,IAAI,EAAE,CAAC;AAAA,CAC9E;AAED,SAAS,gBAAgB,CAAC,IAAc,EAAE,KAAgB,EAAU;IACnE,MAAM,KAAK,GAAG,CAAC,IAAI,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IAC/D,IAAI,IAAI,CAAC,WAAW;QAAE,KAAK,CAAC,IAAI,CAAC,gBAAgB,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;IACrE,IAAI,IAAI,CAAC,UAAU;QAAE,KAAK,CAAC,IAAI,CAAC,eAAe,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;IAClE,IAAI,IAAI,CAAC,SAAS,EAAE,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,cAAc,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACxG,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK;SACxB,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;SAC7D,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IACnC,IAAI,MAAM,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,WAAW,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACpF,IAAI,IAAI,CAAC,KAAK;QAAE,KAAK,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;IACnD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAAA,CACxB","sourcesContent":["import { LIST_DISPLAY_MAX_ITEMS, TODO_TOOL_NAME } from \"./constants.ts\";\nimport {\n\tEMPTY_TODO_STATE,\n\ttype TodoAction,\n\ttype TodoDetails,\n\ttype TodoItem,\n\ttype TodoParams,\n\ttype TodoState,\n\ttype TodoStatus,\n} from \"./schema.ts\";\n\ntype Operation =\n\t| { kind: \"create\"; id: number }\n\t| {\n\t\t\tkind: \"update\";\n\t\t\tid: number;\n\t\t\tfrom: TodoStatus;\n\t\t\tto: TodoStatus;\n\t\t\t/** Other tasks auto-demoted from in_progress → pending to keep exactly one active. */\n\t\t\tdemotedIds?: number[];\n\t\t\t/** Pending dependents left fully unblocked by an update to status deleted. */\n\t\t\treleasedIds?: number[];\n\t\t\t/** Soft note when the list is fully closed without a verification-style task. */\n\t\t\tverificationNudge?: boolean;\n\t }\n\t| { kind: \"delete\"; id: number; subject: string; releasedIds?: number[] }\n\t| { kind: \"list\"; status?: TodoStatus; includeDeleted: boolean }\n\t| { kind: \"get\"; item: TodoItem }\n\t| { kind: \"clear\"; count: number }\n\t| { kind: \"error\"; message: string };\n\n/** Subjects/descriptions that count as a verification step (CC-style soft nudge). */\nconst VERIFICATION_PATTERN = /verif|test|check|review/i;\n\nexport interface MutationResult {\n\tstate: TodoState;\n\toperation: Operation;\n}\n\n// ---- per-session state ------------------------------------------------------\n// Keyed by session id like rewind's engine state: one Pi process can host more\n// than one session over its lifetime (resume, /tree branch switches), and a\n// module-level singleton would leak one session's list into another. Tool\n// renderers get no ctx, so the active session is a module-level pointer kept\n// current by execute and the lifecycle handlers (which do have ctx).\nconst states = new Map<string, TodoState>();\nlet activeSid = \"\";\n\n/** Point the module at a session's state bucket. Call wherever ctx is in hand. */\nexport function setActiveTodoSession(sid: string): void {\n\tactiveSid = sid;\n}\n\n/** Snapshot of the active session's state; mutate via applyTodoMutation + commitTodoState. */\nexport function getTodoState(): TodoState {\n\treturn cloneState(states.get(activeSid) ?? EMPTY_TODO_STATE);\n}\n\nexport function replaceTodoState(next: TodoState): void {\n\tstates.set(activeSid, cloneState(next));\n}\n\nexport function commitTodoState(next: TodoState): void {\n\treplaceTodoState(next);\n}\n\n/** Drop in-memory state for a session (call from session_shutdown). */\nexport function disposeTodoSession(sid: string): void {\n\tif (!sid) return;\n\tstates.delete(sid);\n\tif (activeSid === sid) activeSid = \"\";\n}\n\nexport function cloneState(source: TodoState): TodoState {\n\treturn {\n\t\titems: source.items.map((item) => {\n\t\t\tconst clone: TodoItem = { ...item };\n\t\t\tif (item.blockedBy) clone.blockedBy = [...item.blockedBy];\n\t\t\telse delete clone.blockedBy;\n\t\t\tif (item.metadata) clone.metadata = { ...item.metadata };\n\t\t\telse delete clone.metadata;\n\t\t\treturn clone;\n\t\t}),\n\t\tnextId: source.nextId,\n\t};\n}\n\nfunction omitBlockedBy(item: TodoItem): TodoItem {\n\tconst next = { ...item };\n\tdelete next.blockedBy;\n\treturn next;\n}\n\n/**\n * Keep a tombstone while detaching its id from every dependent task. Also\n * reports which pending dependents ended up fully unblocked, so the tool\n * result can tell the model what became workable (mirrors the demote note).\n */\nfunction markDeleted(state: TodoState, id: number): { state: TodoState; releasedIds: number[] } {\n\tconst items = state.items.map((item) => {\n\t\tif (item.id === id) return { ...item, status: \"deleted\" as const };\n\t\tif (!item.blockedBy?.includes(id)) return item;\n\t\tconst blockedBy = item.blockedBy.filter((dependencyId) => dependencyId !== id);\n\t\treturn blockedBy.length ? { ...item, blockedBy } : omitBlockedBy(item);\n\t});\n\tconst nextState: TodoState = { items, nextId: state.nextId };\n\tconst releasedIds = state.items\n\t\t.filter((item) => item.id !== id && item.status === \"pending\" && item.blockedBy?.includes(id))\n\t\t.map((item) => item.id)\n\t\t.filter((dependentId) => {\n\t\t\tconst dependent = findItem(nextState, dependentId);\n\t\t\treturn dependent !== undefined && unresolvedDependencyIds(nextState, dependent).length === 0;\n\t\t});\n\treturn { state: nextState, releasedIds };\n}\n\nfunction error(state: TodoState, message: string): MutationResult {\n\treturn { state, operation: { kind: \"error\", message } };\n}\n\n// ---- per-action parameter validation ---------------------------------------\n// Parameters each action accepts. Anything else is rejected with guidance\n// instead of being silently ignored (a model that passes blockedBy on update\n// should learn about addBlockedBy, not lose the edit).\nconst ACTION_PARAMS: Record<TodoAction, ReadonlySet<string>> = {\n\tcreate: new Set([\"subject\", \"description\", \"activeForm\", \"status\", \"blockedBy\", \"owner\", \"metadata\"]),\n\tupdate: new Set([\n\t\t\"id\",\n\t\t\"subject\",\n\t\t\"description\",\n\t\t\"activeForm\",\n\t\t\"status\",\n\t\t\"addBlockedBy\",\n\t\t\"removeBlockedBy\",\n\t\t\"addBlocks\",\n\t\t\"removeBlocks\",\n\t\t\"owner\",\n\t\t\"metadata\",\n\t]),\n\tlist: new Set([\"status\", \"includeDeleted\"]),\n\tget: new Set([\"id\"]),\n\tdelete: new Set([\"id\"]),\n\tclear: new Set<string>(),\n};\n\nconst UPDATE_ONLY_EDGE_PARAMS = new Set([\"addBlockedBy\", \"removeBlockedBy\", \"addBlocks\", \"removeBlocks\"]);\n\nfunction inapplicableParamError(action: TodoAction, key: string): string {\n\tif (action === \"update\" && key === \"blockedBy\") {\n\t\treturn \"blockedBy is create-only; use addBlockedBy/removeBlockedBy on update\";\n\t}\n\tif (action === \"create\" && UPDATE_ONLY_EDGE_PARAMS.has(key)) {\n\t\treturn `${key} is update-only; use blockedBy on create`;\n\t}\n\treturn `${key} does not apply to action ${action}`;\n}\n\nfunction findInapplicableParam(params: TodoParams): string | undefined {\n\tconst allowed = ACTION_PARAMS[params.action];\n\tfor (const [key, value] of Object.entries(params)) {\n\t\tif (key === \"action\" || value === undefined) continue;\n\t\tif (!allowed.has(key)) return inapplicableParamError(params.action, key);\n\t}\n\treturn undefined;\n}\n\nfunction isTransitionAllowed(from: TodoStatus, to: TodoStatus): boolean {\n\t// `deleted` is the only terminal status; `completed` can be reopened to\n\t// in_progress or pending so a premature completion recovers without losing\n\t// the task id and its blockedBy edges.\n\tif (from === to) return true;\n\tif (from === \"deleted\") return false;\n\tif (to === \"deleted\") return true;\n\tif (to === \"completed\") return from === \"pending\" || from === \"in_progress\";\n\tif (to === \"pending\") return from === \"in_progress\" || from === \"completed\";\n\tif (to === \"in_progress\") return from === \"pending\" || from === \"completed\";\n\treturn false;\n}\n\nfunction findItem(state: TodoState, id: number): TodoItem | undefined {\n\treturn state.items.find((item) => item.id === id);\n}\n\nfunction validateDependencies(state: TodoState, deps: number[] | undefined, currentId?: number): string | undefined {\n\tif (!deps?.length) return undefined;\n\tfor (const dep of deps) {\n\t\tif (dep === currentId) return `cannot block #${currentId} on itself`;\n\t\tconst item = findItem(state, dep);\n\t\tif (!item) return `blockedBy: #${dep} not found`;\n\t\tif (item.status === \"deleted\") return `blockedBy: #${dep} is deleted`;\n\t}\n\treturn undefined;\n}\n\n/** All listed dependencies must be completed before starting or closing a task. */\nfunction validateDependenciesReady(state: TodoState, deps: number[] | undefined): string | undefined {\n\tif (!deps?.length) return undefined;\n\tfor (const dep of deps) {\n\t\tconst item = findItem(state, dep);\n\t\tif (!item || item.status !== \"completed\") {\n\t\t\treturn `blockedBy: complete #${dep} before starting or finishing this task`;\n\t\t}\n\t}\n\treturn undefined;\n}\n\n/** IDs of dependencies that still prevent a task from starting or completing. */\nexport function unresolvedDependencyIds(state: TodoState, item: TodoItem): number[] {\n\treturn (item.blockedBy ?? []).filter((id) => findItem(state, id)?.status !== \"completed\");\n}\n\n/** True when every blockedBy dependency is completed (for transition and overlay checks). */\nexport function dependenciesSatisfied(state: TodoState, item: TodoItem): boolean {\n\treturn unresolvedDependencyIds(state, item).length === 0;\n}\n\n/** True when any task whose deps change in nextDepsById can reach itself through blockedBy edges. */\nfunction createsCycle(items: TodoItem[], nextDepsById: ReadonlyMap<number, number[]>): boolean {\n\tconst depsById = new Map<number, number[]>();\n\tfor (const item of items) depsById.set(item.id, item.blockedBy ?? []);\n\tfor (const [id, deps] of nextDepsById) depsById.set(id, deps);\n\n\tconst seen = new Set<number>();\n\tconst stack = new Set<number>();\n\n\tfunction visit(node: number): boolean {\n\t\tif (stack.has(node)) return true;\n\t\tif (seen.has(node)) return false;\n\t\tseen.add(node);\n\t\tstack.add(node);\n\t\tfor (const dep of depsById.get(node) ?? []) {\n\t\t\tif (visit(dep)) return true;\n\t\t}\n\t\tstack.delete(node);\n\t\treturn false;\n\t}\n\n\tfor (const id of nextDepsById.keys()) {\n\t\tif (visit(id)) return true;\n\t}\n\treturn false;\n}\n\nexport function applyTodoMutation(input: TodoState, params: TodoParams): MutationResult {\n\tconst state = cloneState(input);\n\n\tconst inapplicable = findInapplicableParam(params);\n\tif (inapplicable) return error(state, inapplicable);\n\n\tswitch (params.action) {\n\t\tcase \"create\": {\n\t\t\tconst subject = params.subject?.trim();\n\t\t\tif (!subject) return error(state, \"subject required for create\");\n\t\t\tif (!params.description?.trim()) {\n\t\t\t\treturn error(state, \"description required for create: state what done means for this task\");\n\t\t\t}\n\t\t\tif (params.status !== undefined && params.status !== \"pending\") {\n\t\t\t\treturn error(state, \"create always starts pending; use update to start or complete a task\");\n\t\t\t}\n\t\t\tconst dependencyError = validateDependencies(state, params.blockedBy);\n\t\t\tif (dependencyError) return error(state, dependencyError);\n\n\t\t\tconst item: TodoItem = {\n\t\t\t\tid: state.nextId,\n\t\t\t\tsubject,\n\t\t\t\tstatus: \"pending\",\n\t\t\t\tdescription: params.description,\n\t\t\t};\n\t\t\tif (params.activeForm) item.activeForm = params.activeForm;\n\t\t\tif (params.blockedBy?.length) item.blockedBy = Array.from(new Set<number>(params.blockedBy));\n\t\t\tif (params.owner) item.owner = params.owner;\n\t\t\tif (params.metadata) item.metadata = { ...params.metadata };\n\n\t\t\treturn {\n\t\t\t\tstate: { items: [...state.items, item], nextId: state.nextId + 1 },\n\t\t\t\toperation: { kind: \"create\", id: item.id },\n\t\t\t};\n\t\t}\n\n\t\tcase \"update\": {\n\t\t\tif (params.id === undefined) return error(state, \"id required for update\");\n\t\t\tconst index = state.items.findIndex((item) => item.id === params.id);\n\t\t\tif (index === -1) return error(state, `#${params.id} not found`);\n\t\t\tconst current = state.items[index];\n\t\t\tif (current.status === \"deleted\") return error(state, `#${params.id} is deleted and cannot be updated`);\n\t\t\tif (params.subject !== undefined && !params.subject.trim()) return error(state, \"subject cannot be empty\");\n\n\t\t\tconst edgeChange =\n\t\t\t\t(params.addBlockedBy?.length ?? 0) > 0 ||\n\t\t\t\t(params.removeBlockedBy?.length ?? 0) > 0 ||\n\t\t\t\t(params.addBlocks?.length ?? 0) > 0 ||\n\t\t\t\t(params.removeBlocks?.length ?? 0) > 0;\n\t\t\tconst fieldChange =\n\t\t\t\tparams.subject !== undefined ||\n\t\t\t\tparams.description !== undefined ||\n\t\t\t\tparams.activeForm !== undefined ||\n\t\t\t\tparams.owner !== undefined ||\n\t\t\t\tparams.metadata !== undefined;\n\t\t\tif (!fieldChange && !edgeChange && params.status === undefined) {\n\t\t\t\treturn error(state, \"update requires at least one field\");\n\t\t\t}\n\n\t\t\t// `status: deleted` is the update form of delete; keep its dependency\n\t\t\t// cleanup identical to the dedicated delete action. Other edits do not\n\t\t\t// combine with it: a tombstone is immutable, so applying them would\n\t\t\t// silently produce an unreachable revision.\n\t\t\tif (params.status === \"deleted\") {\n\t\t\t\tif (fieldChange || edgeChange) {\n\t\t\t\t\treturn error(\n\t\t\t\t\t\tstate,\n\t\t\t\t\t\t\"status deleted cannot be combined with other changes; apply edits first or delete in a separate call\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst deleted = markDeleted(state, current.id);\n\t\t\t\treturn {\n\t\t\t\t\tstate: deleted.state,\n\t\t\t\t\toperation: {\n\t\t\t\t\t\tkind: \"update\",\n\t\t\t\t\t\tid: current.id,\n\t\t\t\t\t\tfrom: current.status,\n\t\t\t\t\t\tto: \"deleted\",\n\t\t\t\t\t\t...(deleted.releasedIds.length ? { releasedIds: deleted.releasedIds } : {}),\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst nextStatus = params.status ?? current.status;\n\t\t\tif (!isTransitionAllowed(current.status, nextStatus)) {\n\t\t\t\treturn error(state, `illegal transition ${current.status} -> ${nextStatus}`);\n\t\t\t}\n\n\t\t\t// Collect every task whose blockedBy changes: this task (addBlockedBy /\n\t\t\t// removeBlockedBy) plus reverse-edge targets (addBlocks / removeBlocks).\n\t\t\tconst nextDepsById = new Map<number, number[]>();\n\t\t\tlet nextDeps = current.blockedBy ? [...current.blockedBy] : [];\n\t\t\tif (params.removeBlockedBy?.length) {\n\t\t\t\tconst remove = new Set(params.removeBlockedBy);\n\t\t\t\tnextDeps = nextDeps.filter((id) => !remove.has(id));\n\t\t\t}\n\t\t\tif (params.addBlockedBy?.length) {\n\t\t\t\tconst dependencyError = validateDependencies(state, params.addBlockedBy, current.id);\n\t\t\t\tif (dependencyError) return error(state, dependencyError);\n\t\t\t\tfor (const dep of params.addBlockedBy) {\n\t\t\t\t\tif (!nextDeps.includes(dep)) nextDeps.push(dep);\n\t\t\t\t}\n\t\t\t}\n\t\t\tnextDepsById.set(current.id, nextDeps);\n\n\t\t\tif (params.removeBlocks?.length) {\n\t\t\t\tconst release = new Set(params.removeBlocks);\n\t\t\t\tfor (const candidate of state.items) {\n\t\t\t\t\tif (!release.has(candidate.id) || !candidate.blockedBy?.includes(current.id)) continue;\n\t\t\t\t\tnextDepsById.set(\n\t\t\t\t\t\tcandidate.id,\n\t\t\t\t\t\tcandidate.blockedBy.filter((dependencyId) => dependencyId !== current.id),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (params.addBlocks?.length) {\n\t\t\t\tfor (const targetId of params.addBlocks) {\n\t\t\t\t\tif (targetId === current.id) return error(state, `cannot block #${targetId} on itself`);\n\t\t\t\t\tconst target = findItem(state, targetId);\n\t\t\t\t\tif (!target) return error(state, `addBlocks: #${targetId} not found`);\n\t\t\t\t\tif (target.status === \"deleted\") return error(state, `addBlocks: #${targetId} is deleted`);\n\t\t\t\t\tconst deps = nextDepsById.get(targetId) ?? (target.blockedBy ? [...target.blockedBy] : []);\n\t\t\t\t\tif (!deps.includes(current.id)) deps.push(current.id);\n\t\t\t\t\tnextDepsById.set(targetId, deps);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (createsCycle(state.items, nextDepsById)) {\n\t\t\t\treturn error(state, \"blockedBy would create a cycle\");\n\t\t\t}\n\n\t\t\t// Readiness gates only status *changes*: an already-active task may take\n\t\t\t// on a new incomplete dependency — a prerequisite discovered mid-work.\n\t\t\t// The overlay flags it as \"deps incomplete\" instead.\n\t\t\tif ((nextStatus === \"in_progress\" || nextStatus === \"completed\") && current.status !== nextStatus) {\n\t\t\t\tconst readyError = validateDependenciesReady(state, nextDeps);\n\t\t\t\tif (readyError) return error(state, readyError);\n\t\t\t}\n\n\t\t\tconst updated: TodoItem = { ...current, status: nextStatus };\n\t\t\tif (params.subject !== undefined) updated.subject = params.subject.trim();\n\t\t\t// Empty string removes an optional text field (metadata uses null keys).\n\t\t\tif (params.description !== undefined) {\n\t\t\t\tif (params.description) updated.description = params.description;\n\t\t\t\telse delete updated.description;\n\t\t\t}\n\t\t\tif (params.activeForm !== undefined) {\n\t\t\t\tif (params.activeForm) updated.activeForm = params.activeForm;\n\t\t\t\telse delete updated.activeForm;\n\t\t\t}\n\t\t\tif (params.owner !== undefined) {\n\t\t\t\tif (params.owner) updated.owner = params.owner;\n\t\t\t\telse delete updated.owner;\n\t\t\t}\n\t\t\tif (nextDeps.length) updated.blockedBy = nextDeps;\n\t\t\telse delete updated.blockedBy;\n\n\t\t\tif (params.metadata !== undefined) {\n\t\t\t\tconst merged = { ...(current.metadata ?? {}) };\n\t\t\t\tfor (const [key, value] of Object.entries(params.metadata)) {\n\t\t\t\t\tif (value === null) delete merged[key];\n\t\t\t\t\telse merged[key] = value;\n\t\t\t\t}\n\t\t\t\tif (Object.keys(merged).length) updated.metadata = merged;\n\t\t\t\telse delete updated.metadata;\n\t\t\t}\n\n\t\t\tconst items = state.items.map((task) => {\n\t\t\t\tif (task.id === current.id) return task;\n\t\t\t\tconst deps = nextDepsById.get(task.id);\n\t\t\t\tif (deps === undefined) return task;\n\t\t\t\treturn deps.length ? { ...task, blockedBy: deps } : omitBlockedBy(task);\n\t\t\t});\n\t\t\titems[index] = updated;\n\n\t\t\t// Exactly one in_progress: demote any other active tasks to pending.\n\t\t\tconst demotedIds: number[] = [];\n\t\t\tif (nextStatus === \"in_progress\") {\n\t\t\t\tfor (let i = 0; i < items.length; i++) {\n\t\t\t\t\tconst item = items[i];\n\t\t\t\t\tif (item.id === updated.id) continue;\n\t\t\t\t\tif (item.status !== \"in_progress\") continue;\n\t\t\t\t\titems[i] = { ...item, status: \"pending\" };\n\t\t\t\t\tdemotedIds.push(item.id);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst nextState: TodoState = { items, nextId: state.nextId };\n\t\t\tconst newlyCompleted = current.status !== \"completed\" && nextStatus === \"completed\";\n\t\t\treturn {\n\t\t\t\tstate: nextState,\n\t\t\t\toperation: {\n\t\t\t\t\tkind: \"update\",\n\t\t\t\t\tid: updated.id,\n\t\t\t\t\tfrom: current.status,\n\t\t\t\t\tto: updated.status,\n\t\t\t\t\t...(demotedIds.length ? { demotedIds } : {}),\n\t\t\t\t\t...(newlyCompleted && needsVerificationNudge(nextState) ? { verificationNudge: true } : {}),\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tcase \"list\":\n\t\t\treturn {\n\t\t\t\tstate,\n\t\t\t\toperation: {\n\t\t\t\t\tkind: \"list\",\n\t\t\t\t\tstatus: params.status,\n\t\t\t\t\tincludeDeleted: params.includeDeleted === true,\n\t\t\t\t},\n\t\t\t};\n\n\t\tcase \"get\": {\n\t\t\tif (params.id === undefined) return error(state, \"id required for get\");\n\t\t\tconst item = findItem(state, params.id);\n\t\t\tif (!item) return error(state, `#${params.id} not found`);\n\t\t\treturn { state, operation: { kind: \"get\", item } };\n\t\t}\n\n\t\tcase \"delete\": {\n\t\t\tif (params.id === undefined) return error(state, \"id required for delete\");\n\t\t\tconst index = state.items.findIndex((item) => item.id === params.id);\n\t\t\tif (index === -1) return error(state, `#${params.id} not found`);\n\t\t\tconst current = state.items[index];\n\t\t\tif (current.status === \"deleted\") return error(state, `#${params.id} is already deleted`);\n\n\t\t\tconst deleted = markDeleted(state, current.id);\n\t\t\treturn {\n\t\t\t\tstate: deleted.state,\n\t\t\t\toperation: {\n\t\t\t\t\tkind: \"delete\",\n\t\t\t\t\tid: current.id,\n\t\t\t\t\tsubject: current.subject,\n\t\t\t\t\t...(deleted.releasedIds.length ? { releasedIds: deleted.releasedIds } : {}),\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tcase \"clear\":\n\t\t\treturn {\n\t\t\t\t// IDs remain monotonic across a clear so stale references cannot point\n\t\t\t\t// at an unrelated task created later on the same conversation branch.\n\t\t\t\tstate: { items: [], nextId: state.nextId },\n\t\t\t\toperation: { kind: \"clear\", count: state.items.length },\n\t\t\t};\n\t}\n\n\treturn error(state, `unknown action: ${(params as { action?: unknown }).action}`);\n}\n\nfunction isTodoDetails(value: unknown): value is TodoDetails {\n\tif (!value || typeof value !== \"object\") return false;\n\tconst record = value as Record<string, unknown>;\n\treturn Array.isArray(record.items) && typeof record.nextId === \"number\";\n}\n\nexport function replayTodosFromBranch(ctx: { sessionManager: { getBranch(): Iterable<unknown> } }): TodoState {\n\t// Latest todo toolResult wins; scan tail → head so long branches stop early.\n\tconst branch = Array.from(ctx.sessionManager.getBranch());\n\tfor (let i = branch.length - 1; i >= 0; i--) {\n\t\tconst item = branch[i] as {\n\t\t\ttype?: string;\n\t\t\tmessage?: { role?: string; toolName?: string; details?: unknown };\n\t\t};\n\t\tif (item.type !== \"message\") continue;\n\t\tif (item.message?.role !== \"toolResult\" || item.message.toolName !== TODO_TOOL_NAME) continue;\n\t\tif (!isTodoDetails(item.message.details)) continue;\n\t\treturn cloneState({\n\t\t\titems: item.message.details.items,\n\t\t\tnextId: item.message.details.nextId,\n\t\t});\n\t}\n\treturn cloneState(EMPTY_TODO_STATE);\n}\n\nexport function buildTodoDetails(params: TodoParams, next: TodoState): TodoDetails {\n\treturn {\n\t\taction: params.action,\n\t\tparams: params as Record<string, unknown>,\n\t\titems: cloneState(next).items,\n\t\tnextId: next.nextId,\n\t};\n}\n\nconst VERIFICATION_NUDGE_NOTE =\n\t\"NOTE: You closed out 3+ tasks with no verification/test/review step. Before the final summary, run checks or add a verification task and complete it — do not self-declare done with known failures.\";\n\nfunction formatReleasedSuffix(releasedIds: number[] | undefined): string {\n\tif (!releasedIds?.length) return \"\";\n\treturn `; released ${releasedIds.map((id) => `#${id}`).join(\",\")} (no longer blocked)`;\n}\n\nexport function formatTodoContent(operation: Operation, state: TodoState): string {\n\tswitch (operation.kind) {\n\t\tcase \"create\": {\n\t\t\tconst item = findItem(state, operation.id);\n\t\t\treturn item ? `Created #${item.id}: ${item.subject} (pending)` : `Created #${operation.id}`;\n\t\t}\n\t\tcase \"update\": {\n\t\t\tconst transition = operation.from === operation.to ? \"\" : ` (${operation.from} -> ${operation.to})`;\n\t\t\tlet text = `Updated #${operation.id}${transition}`;\n\t\t\tif (operation.demotedIds?.length) {\n\t\t\t\ttext += `; ${operation.demotedIds.map((id) => `#${id}`).join(\",\")} demoted to pending`;\n\t\t\t}\n\t\t\ttext += formatReleasedSuffix(operation.releasedIds);\n\t\t\tif (operation.verificationNudge) text += `\\n\\n${VERIFICATION_NUDGE_NOTE}`;\n\t\t\treturn text;\n\t\t}\n\t\tcase \"delete\":\n\t\t\treturn `Deleted #${operation.id}: ${operation.subject}${formatReleasedSuffix(operation.releasedIds)}`;\n\t\tcase \"clear\":\n\t\t\treturn `Cleared ${operation.count} tasks`;\n\t\tcase \"list\": {\n\t\t\tlet view = state.items;\n\t\t\t// An explicit deleted-status query is sufficient intent to include tombstones.\n\t\t\tif (!operation.includeDeleted && operation.status !== \"deleted\")\n\t\t\t\tview = view.filter((item) => item.status !== \"deleted\");\n\t\t\tif (operation.status) view = view.filter((item) => item.status === operation.status);\n\t\t\treturn formatBoundedList(view, state, operation.status);\n\t\t}\n\t\tcase \"get\":\n\t\t\treturn formatDetailItem(operation.item, state);\n\t\tcase \"error\":\n\t\t\treturn `Error: ${operation.message}`;\n\t}\n}\n\n/**\n * Soft nudge when the whole list is done (no active work), there are 3+ completed\n * tasks, and none look like a verification/test/review step — mirrors CC TodoWrite.\n */\nfunction needsVerificationNudge(state: TodoState): boolean {\n\tconst active = state.items.filter((item) => item.status !== \"deleted\");\n\tif (active.length < 3) return false;\n\tif (active.some((item) => item.status === \"pending\" || item.status === \"in_progress\")) return false;\n\tconst completed = active.filter((item) => item.status === \"completed\");\n\tif (completed.length < 3) return false;\n\treturn !completed.some(\n\t\t(item) =>\n\t\t\tVERIFICATION_PATTERN.test(item.subject) ||\n\t\t\t(item.description !== undefined && VERIFICATION_PATTERN.test(item.description)),\n\t);\n}\n\nfunction formatBoundedList(view: TodoItem[], state: TodoState, statusFilter: TodoStatus | undefined): string {\n\tif (!view.length) return \"No tasks\";\n\tconst shown = view.slice(0, LIST_DISPLAY_MAX_ITEMS);\n\tconst lines = shown.map((item) => formatListItem(item, state));\n\tconst omitted = view.length - shown.length;\n\tif (omitted > 0) {\n\t\t// Do not suggest a filter that is already applied.\n\t\tconst hint = statusFilter ? \"use get with id= for details\" : \"narrow with status= or use get with id=\";\n\t\tlines.push(`… and ${omitted} more (${shown.length} of ${view.length} shown); ${hint}.`);\n\t}\n\treturn lines.join(\"\\n\");\n}\n\nfunction formatListItem(item: TodoItem, state: TodoState): string {\n\tconst unresolved = unresolvedDependencyIds(state, item);\n\tconst deps = unresolved.length ? ` blockedBy=${unresolved.map((id) => `#${id}`).join(\",\")}` : \"\";\n\tconst owner = item.owner ? ` @${item.owner}` : \"\";\n\tconst active = item.status === \"in_progress\" && item.activeForm ? ` (${item.activeForm})` : \"\";\n\treturn `[${item.status}] #${item.id} ${item.subject}${active}${owner}${deps}`;\n}\n\nfunction formatDetailItem(item: TodoItem, state: TodoState): string {\n\tconst lines = [`#${item.id} [${item.status}] ${item.subject}`];\n\tif (item.description) lines.push(`description: ${item.description}`);\n\tif (item.activeForm) lines.push(`activeForm: ${item.activeForm}`);\n\tif (item.blockedBy?.length) lines.push(`blockedBy: ${item.blockedBy.map((id) => `#${id}`).join(\", \")}`);\n\tconst blocks = state.items\n\t\t.filter((candidate) => candidate.blockedBy?.includes(item.id))\n\t\t.map((candidate) => candidate.id);\n\tif (blocks.length) lines.push(`blocks: ${blocks.map((id) => `#${id}`).join(\", \")}`);\n\tif (item.owner) lines.push(`owner: ${item.owner}`);\n\treturn lines.join(\"\\n\");\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../../../src/extensions/todo/view.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wCAAwC,CAAC;AACpE,OAAO,KAAK,EAAY,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGnE,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAKlD,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,UAAU,EAAE,KAAK,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAKpF,CAAC;AAQF,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,OAAO,CAEtG;AAWD,wBAAgB,kBAAkB,CACjC,KAAK,EAAE,SAAS,EAChB,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,MAAM,EACb,eAAe,EAAE,WAAW,CAAC,MAAM,CAAC,GAClC,MAAM,EAAE,CAoBV;AAsDD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAiB1D","sourcesContent":["import { truncateToWidth } from \"@earendil-works/pi-tui\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport type { TodoItem, TodoState, TodoStatus } from \"./schema.ts\";\nimport { unresolvedDependencyIds } from \"./state.ts\";\n\nexport const STATUS_MARK: Record<TodoStatus, string> = {\n\tpending: \"[ ]\",\n\tin_progress: \"[>]\",\n\tcompleted: \"[x]\",\n\tdeleted: \"[-]\",\n};\n\nexport const STATUS_COLOR: Record<TodoStatus, \"dim\" | \"warning\" | \"success\" | \"muted\"> = {\n\tpending: \"dim\",\n\tin_progress: \"warning\",\n\tcompleted: \"success\",\n\tdeleted: \"muted\",\n};\n\nconst OVERLAY_BODY_MAX_ITEMS = 10;\n\nfunction visibleTodos(state: TodoState): TodoItem[] {\n\treturn state.items.filter((item) => item.status !== \"deleted\");\n}\n\nexport function hasVisibleOverlayItems(state: TodoState, hiddenCompleted: ReadonlySet<number>): boolean {\n\treturn visibleTodos(state).some((item) => item.status !== \"completed\" || !hiddenCompleted.has(item.id));\n}\n\nfunction todoCounts(items: TodoItem[]): { total: number; pending: number; inProgress: number; completed: number } {\n\treturn {\n\t\ttotal: items.length,\n\t\tpending: items.filter((item) => item.status === \"pending\").length,\n\t\tinProgress: items.filter((item) => item.status === \"in_progress\").length,\n\t\tcompleted: items.filter((item) => item.status === \"completed\").length,\n\t};\n}\n\nexport function renderOverlayLines(\n\tstate: TodoState,\n\ttheme: Theme,\n\twidth: number,\n\thiddenCompleted: ReadonlySet<number>,\n): string[] {\n\tconst allVisible = visibleTodos(state);\n\tconst visible = allVisible.filter((item) => item.status !== \"completed\" || !hiddenCompleted.has(item.id));\n\tif (!visible.length) return [];\n\n\tconst counts = todoCounts(allVisible);\n\tconst hasActive = visible.some((item) => item.status === \"pending\" || item.status === \"in_progress\");\n\tconst heading = `${theme.fg(hasActive ? \"accent\" : \"dim\", \"Todos\")} ${theme.fg(\"dim\", `(${counts.completed}/${counts.total})`)}`;\n\tconst lines = [truncateToWidth(heading, width, \"...\")];\n\n\tconst showIds = visible.some((item) => item.blockedBy?.length);\n\tconst body = chooseOverlayItems(visible, state, OVERLAY_BODY_MAX_ITEMS);\n\tfor (const item of body.items) {\n\t\tlines.push(truncateToWidth(` ${formatOverlayItem(item, state, theme, showIds)}`, width, \"...\"));\n\t}\n\tif (body.hidden.length > 0) {\n\t\tlines.push(truncateToWidth(theme.fg(\"dim\", ` ${formatHiddenSummary(body.hidden)}`), width, \"...\"));\n\t}\n\tlines.push(\"\");\n\treturn lines;\n}\n\nfunction byIdAsc(first: TodoItem, second: TodoItem): number {\n\treturn first.id - second.id;\n}\n\nfunction overlayPriority(state: TodoState, item: TodoItem): number {\n\tif (item.status === \"in_progress\") return 0;\n\tif (item.status === \"pending\" && unresolvedDependencyIds(state, item).length === 0) return 1;\n\tif (item.status === \"pending\") return 2;\n\treturn 3; // Completed items here are recent; older ones are hidden by TodoOverlay.\n}\n\nfunction chooseOverlayItems(\n\titems: TodoItem[],\n\tstate: TodoState,\n\tmaxBody: number,\n): { items: TodoItem[]; hidden: TodoItem[] } {\n\tconst prioritized = [...items].sort((first, second) => {\n\t\tconst priorityDelta = overlayPriority(state, first) - overlayPriority(state, second);\n\t\treturn priorityDelta || byIdAsc(first, second);\n\t});\n\tif (prioritized.length <= maxBody) return { items: prioritized, hidden: [] };\n\n\tconst shown = prioritized.slice(0, Math.max(1, maxBody - 1));\n\treturn { items: shown, hidden: prioritized.slice(shown.length) };\n}\n\nfunction formatHiddenSummary(items: TodoItem[]): string {\n\tconst counts = todoCounts(items);\n\tconst parts: string[] = [];\n\tif (counts.inProgress) parts.push(`${counts.inProgress} in progress`);\n\tif (counts.pending) parts.push(`${counts.pending} pending`);\n\tif (counts.completed) parts.push(`${counts.completed} completed`);\n\treturn `+${items.length} more${parts.length ? ` (${parts.join(\", \")})` : \"\"}`;\n}\n\nfunction formatOverlayItem(item: TodoItem, state: TodoState, theme: Theme, showId: boolean): string {\n\tlet text = theme.fg(STATUS_COLOR[item.status], STATUS_MARK[item.status]);\n\tif (showId) text += ` ${theme.fg(\"accent\", `#${item.id}`)}`;\n\tconst subject =\n\t\titem.status === \"completed\" ? theme.strikethrough(theme.fg(\"dim\", item.subject)) : theme.fg(\"text\", item.subject);\n\ttext += ` ${subject}`;\n\tif (item.status === \"in_progress\" && item.activeForm) text += ` ${theme.fg(\"dim\", `(${item.activeForm})`)}`;\n\n\tconst unresolved = unresolvedDependencyIds(state, item);\n\tif (unresolved.length) {\n\t\ttext += ` ${theme.fg(\"dim\", `blocked by ${unresolved.map((id) => `#${id}`).join(\",\")}`)}`;\n\t\tif (item.status === \"pending\" || item.status === \"in_progress\")\n\t\t\ttext += ` ${theme.fg(\"warning\", \"(deps incomplete)\")}`;\n\t}\n\treturn text;\n}\n\nexport function formatCommandList(state: TodoState): string {\n\tconst visible = visibleTodos(state);\n\tif (!visible.length) return \"No todos yet.\";\n\tconst lines: string[] = [];\n\tfor (const status of [\"in_progress\", \"pending\", \"completed\"] as const) {\n\t\tconst group = visible.filter((item) => item.status === status).sort(byIdAsc);\n\t\tif (!group.length) continue;\n\t\tlines.push(status);\n\t\tfor (const item of group) {\n\t\t\tconst active = item.status === \"in_progress\" && item.activeForm ? ` (${item.activeForm})` : \"\";\n\t\t\tconst owner = item.owner ? ` @${item.owner}` : \"\";\n\t\t\tconst unresolved = unresolvedDependencyIds(state, item);\n\t\t\tconst deps = unresolved.length ? ` blocked by ${unresolved.map((id) => `#${id}`).join(\",\")}` : \"\";\n\t\t\tlines.push(` ${STATUS_MARK[item.status]} #${item.id} ${item.subject}${active}${owner}${deps}`);\n\t\t}\n\t}\n\treturn lines.join(\"\\n\");\n}\n"]}
1
+ {"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../../../src/extensions/todo/view.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wCAAwC,CAAC;AACpE,OAAO,KAAK,EAAY,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGnE,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAKlD,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,UAAU,EAAE,KAAK,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAKpF,CAAC;AAQF,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,OAAO,CAEtG;AAYD,wBAAgB,kBAAkB,CACjC,KAAK,EAAE,SAAS,EAChB,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,MAAM,EACb,eAAe,EAAE,WAAW,CAAC,MAAM,CAAC,GAClC,MAAM,EAAE,CAoBV;AAsDD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAiB1D","sourcesContent":["import { truncateToWidth } from \"@earendil-works/pi-tui\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport type { TodoItem, TodoState, TodoStatus } from \"./schema.ts\";\nimport { unresolvedDependencyIds } from \"./state.ts\";\n\nexport const STATUS_MARK: Record<TodoStatus, string> = {\n\tpending: \"[ ]\",\n\tin_progress: \"[>]\",\n\tcompleted: \"[x]\",\n\tdeleted: \"[-]\",\n};\n\nexport const STATUS_COLOR: Record<TodoStatus, \"dim\" | \"warning\" | \"success\" | \"muted\"> = {\n\tpending: \"dim\",\n\tin_progress: \"warning\",\n\tcompleted: \"success\",\n\tdeleted: \"muted\",\n};\n\nconst OVERLAY_BODY_MAX_ITEMS = 10;\n\nfunction visibleTodos(state: TodoState): TodoItem[] {\n\treturn state.items.filter((item) => item.status !== \"deleted\");\n}\n\nexport function hasVisibleOverlayItems(state: TodoState, hiddenCompleted: ReadonlySet<number>): boolean {\n\treturn visibleTodos(state).some((item) => item.status !== \"completed\" || !hiddenCompleted.has(item.id));\n}\n\nfunction todoCounts(items: TodoItem[]): { total: number; pending: number; inProgress: number; completed: number } {\n\tconst counts = { total: items.length, pending: 0, inProgress: 0, completed: 0 };\n\tfor (const item of items) {\n\t\tif (item.status === \"pending\") counts.pending++;\n\t\telse if (item.status === \"in_progress\") counts.inProgress++;\n\t\telse if (item.status === \"completed\") counts.completed++;\n\t}\n\treturn counts;\n}\n\nexport function renderOverlayLines(\n\tstate: TodoState,\n\ttheme: Theme,\n\twidth: number,\n\thiddenCompleted: ReadonlySet<number>,\n): string[] {\n\tconst allVisible = visibleTodos(state);\n\tconst visible = allVisible.filter((item) => item.status !== \"completed\" || !hiddenCompleted.has(item.id));\n\tif (!visible.length) return [];\n\n\tconst counts = todoCounts(allVisible);\n\tconst hasActive = visible.some((item) => item.status === \"pending\" || item.status === \"in_progress\");\n\tconst heading = `${theme.fg(hasActive ? \"accent\" : \"dim\", \"Todos\")} ${theme.fg(\"dim\", `(${counts.completed}/${counts.total})`)}`;\n\tconst lines = [truncateToWidth(heading, width, \"...\")];\n\n\tconst showIds = visible.some((item) => item.blockedBy?.length);\n\tconst body = chooseOverlayItems(visible, state, OVERLAY_BODY_MAX_ITEMS);\n\tfor (const item of body.items) {\n\t\tlines.push(truncateToWidth(` ${formatOverlayItem(item, state, theme, showIds)}`, width, \"...\"));\n\t}\n\tif (body.hidden.length > 0) {\n\t\tlines.push(truncateToWidth(theme.fg(\"dim\", ` ${formatHiddenSummary(body.hidden)}`), width, \"...\"));\n\t}\n\tlines.push(\"\");\n\treturn lines;\n}\n\nfunction byIdAsc(first: TodoItem, second: TodoItem): number {\n\treturn first.id - second.id;\n}\n\nfunction overlayPriority(state: TodoState, item: TodoItem): number {\n\tif (item.status === \"in_progress\") return 0;\n\tif (item.status === \"pending\" && unresolvedDependencyIds(state, item).length === 0) return 1;\n\tif (item.status === \"pending\") return 2;\n\treturn 3; // Completed items here are recent; older ones are hidden by TodoOverlay.\n}\n\nfunction chooseOverlayItems(\n\titems: TodoItem[],\n\tstate: TodoState,\n\tmaxBody: number,\n): { items: TodoItem[]; hidden: TodoItem[] } {\n\tconst prioritized = [...items].sort((first, second) => {\n\t\tconst priorityDelta = overlayPriority(state, first) - overlayPriority(state, second);\n\t\treturn priorityDelta || byIdAsc(first, second);\n\t});\n\tif (prioritized.length <= maxBody) return { items: prioritized, hidden: [] };\n\n\tconst shown = prioritized.slice(0, Math.max(1, maxBody - 1));\n\treturn { items: shown, hidden: prioritized.slice(shown.length) };\n}\n\nfunction formatHiddenSummary(items: TodoItem[]): string {\n\tconst counts = todoCounts(items);\n\tconst parts: string[] = [];\n\tif (counts.inProgress) parts.push(`${counts.inProgress} in progress`);\n\tif (counts.pending) parts.push(`${counts.pending} pending`);\n\tif (counts.completed) parts.push(`${counts.completed} completed`);\n\treturn `+${items.length} more${parts.length ? ` (${parts.join(\", \")})` : \"\"}`;\n}\n\nfunction formatOverlayItem(item: TodoItem, state: TodoState, theme: Theme, showId: boolean): string {\n\tlet text = theme.fg(STATUS_COLOR[item.status], STATUS_MARK[item.status]);\n\tif (showId) text += ` ${theme.fg(\"accent\", `#${item.id}`)}`;\n\tconst subject =\n\t\titem.status === \"completed\" ? theme.strikethrough(theme.fg(\"dim\", item.subject)) : theme.fg(\"text\", item.subject);\n\ttext += ` ${subject}`;\n\tif (item.status === \"in_progress\" && item.activeForm) text += ` ${theme.fg(\"dim\", `(${item.activeForm})`)}`;\n\n\tconst unresolved = unresolvedDependencyIds(state, item);\n\tif (unresolved.length) {\n\t\ttext += ` ${theme.fg(\"dim\", `blocked by ${unresolved.map((id) => `#${id}`).join(\",\")}`)}`;\n\t\tif (item.status === \"pending\" || item.status === \"in_progress\")\n\t\t\ttext += ` ${theme.fg(\"warning\", \"(deps incomplete)\")}`;\n\t}\n\treturn text;\n}\n\nexport function formatCommandList(state: TodoState): string {\n\tconst visible = visibleTodos(state);\n\tif (!visible.length) return \"No todos yet.\";\n\tconst lines: string[] = [];\n\tfor (const status of [\"in_progress\", \"pending\", \"completed\"] as const) {\n\t\tconst group = visible.filter((item) => item.status === status).sort(byIdAsc);\n\t\tif (!group.length) continue;\n\t\tlines.push(status);\n\t\tfor (const item of group) {\n\t\t\tconst active = item.status === \"in_progress\" && item.activeForm ? ` (${item.activeForm})` : \"\";\n\t\t\tconst owner = item.owner ? ` @${item.owner}` : \"\";\n\t\t\tconst unresolved = unresolvedDependencyIds(state, item);\n\t\t\tconst deps = unresolved.length ? ` blocked by ${unresolved.map((id) => `#${id}`).join(\",\")}` : \"\";\n\t\t\tlines.push(` ${STATUS_MARK[item.status]} #${item.id} ${item.subject}${active}${owner}${deps}`);\n\t\t}\n\t}\n\treturn lines.join(\"\\n\");\n}\n"]}