@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.
- package/CHANGELOG.md +24 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +2 -2
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +2 -3
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/types.d.ts +9 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js +11 -0
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/extensions/question/dialog.d.ts +3 -1
- package/dist/extensions/question/dialog.d.ts.map +1 -1
- package/dist/extensions/question/dialog.js +106 -52
- package/dist/extensions/question/dialog.js.map +1 -1
- package/dist/extensions/question/index.d.ts.map +1 -1
- package/dist/extensions/question/index.js +2 -2
- package/dist/extensions/question/index.js.map +1 -1
- package/dist/extensions/question/render-cache.d.ts +9 -0
- package/dist/extensions/question/render-cache.d.ts.map +1 -1
- package/dist/extensions/question/render-cache.js +22 -0
- package/dist/extensions/question/render-cache.js.map +1 -1
- package/dist/extensions/question/results.d.ts.map +1 -1
- package/dist/extensions/question/results.js +6 -1
- package/dist/extensions/question/results.js.map +1 -1
- package/dist/extensions/question/schema.d.ts +4 -0
- package/dist/extensions/question/schema.d.ts.map +1 -1
- package/dist/extensions/question/schema.js +19 -28
- package/dist/extensions/question/schema.js.map +1 -1
- package/dist/extensions/question/types.d.ts +1 -1
- package/dist/extensions/question/types.d.ts.map +1 -1
- package/dist/extensions/question/types.js.map +1 -1
- package/dist/extensions/subagent/agents.d.ts.map +1 -1
- package/dist/extensions/subagent/agents.js +12 -6
- package/dist/extensions/subagent/agents.js.map +1 -1
- package/dist/extensions/subagent/constants.d.ts +1 -1
- package/dist/extensions/subagent/constants.d.ts.map +1 -1
- package/dist/extensions/subagent/constants.js +3 -2
- package/dist/extensions/subagent/constants.js.map +1 -1
- package/dist/extensions/subagent/runner.d.ts +1 -1
- package/dist/extensions/subagent/runner.d.ts.map +1 -1
- package/dist/extensions/subagent/runner.js +5 -1
- package/dist/extensions/subagent/runner.js.map +1 -1
- package/dist/extensions/subagent/schema.d.ts.map +1 -1
- package/dist/extensions/subagent/schema.js +2 -2
- package/dist/extensions/subagent/schema.js.map +1 -1
- package/dist/extensions/subagent/sdk-runner.d.ts.map +1 -1
- package/dist/extensions/subagent/sdk-runner.js +5 -0
- package/dist/extensions/subagent/sdk-runner.js.map +1 -1
- package/dist/extensions/subagent/types.d.ts +7 -0
- package/dist/extensions/subagent/types.d.ts.map +1 -1
- package/dist/extensions/subagent/types.js.map +1 -1
- package/dist/extensions/todo/constants.d.ts +1 -1
- package/dist/extensions/todo/constants.d.ts.map +1 -1
- package/dist/extensions/todo/constants.js +29 -4
- package/dist/extensions/todo/constants.js.map +1 -1
- package/dist/extensions/todo/index.d.ts +1 -1
- package/dist/extensions/todo/index.d.ts.map +1 -1
- package/dist/extensions/todo/index.js +22 -3
- package/dist/extensions/todo/index.js.map +1 -1
- package/dist/extensions/todo/schema.d.ts +6 -5
- package/dist/extensions/todo/schema.d.ts.map +1 -1
- package/dist/extensions/todo/schema.js +20 -9
- package/dist/extensions/todo/schema.js.map +1 -1
- package/dist/extensions/todo/state.d.ts +5 -1
- package/dist/extensions/todo/state.d.ts.map +1 -1
- package/dist/extensions/todo/state.js +184 -38
- package/dist/extensions/todo/state.js.map +1 -1
- package/dist/extensions/todo/view.d.ts.map +1 -1
- package/dist/extensions/todo/view.js +10 -6
- package/dist/extensions/todo/view.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +2 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +34 -1
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/utils/coalescing-terminal.d.ts +71 -17
- package/dist/utils/coalescing-terminal.d.ts.map +1 -1
- package/dist/utils/coalescing-terminal.js +136 -31
- package/dist/utils/coalescing-terminal.js.map +1 -1
- package/docs/bundled/extensions/question.md +9 -7
- package/docs/bundled/extensions/subagent.md +2 -2
- package/docs/bundled/extensions/todo.md +5 -3
- package/npm-shrinkwrap.json +2 -2
- 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) ??
|
|
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
|
-
/**
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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:
|
|
208
|
-
operation: {
|
|
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
|
-
|
|
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
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
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 =
|
|
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:
|
|
320
|
-
operation: {
|
|
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
|
|
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,
|
|
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,
|
|
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
|
-
|
|
426
|
-
|
|
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
|
|
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;
|
|
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"]}
|