ftown 0.27.0 → 0.28.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/attention-store.js +34 -2
- package/dist/attention-store.js.map +1 -1
- package/dist/command-rpc.d.ts +11 -0
- package/dist/command-rpc.js +79 -15
- package/dist/command-rpc.js.map +1 -1
- package/dist/coordination/board.js +82 -3
- package/dist/coordination/board.js.map +1 -1
- package/dist/coordination/contract-c.d.ts +117 -0
- package/dist/coordination/contract-c.js +47 -0
- package/dist/coordination/contract-c.js.map +1 -0
- package/dist/coordination/contract.d.ts +8 -1
- package/dist/coordination/contract.js +1 -1
- package/dist/coordination/contract.js.map +1 -1
- package/dist/coordination/format.js +37 -11
- package/dist/coordination/format.js.map +1 -1
- package/dist/coordination/plan.d.ts +74 -0
- package/dist/coordination/plan.js +534 -0
- package/dist/coordination/plan.js.map +1 -0
- package/dist/coordination/routes-plan.d.ts +13 -0
- package/dist/coordination/routes-plan.js +182 -0
- package/dist/coordination/routes-plan.js.map +1 -0
- package/dist/coordination/wiring.d.ts +6 -0
- package/dist/coordination/wiring.js +50 -2
- package/dist/coordination/wiring.js.map +1 -1
- package/dist/coordination-cli.d.ts +6 -1
- package/dist/coordination-cli.js +17 -7
- package/dist/coordination-cli.js.map +1 -1
- package/dist/create-ftown-session.d.ts +18 -0
- package/dist/create-ftown-session.js +44 -0
- package/dist/create-ftown-session.js.map +1 -1
- package/dist/ftown-cli.js +5 -2
- package/dist/ftown-cli.js.map +1 -1
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -1
- package/dist/local-api-server.js +14 -4
- package/dist/local-api-server.js.map +1 -1
- package/dist/local-pair-cli.js +2 -3
- package/dist/local-pair-cli.js.map +1 -1
- package/dist/plan-cli.d.ts +52 -0
- package/dist/plan-cli.js +374 -0
- package/dist/plan-cli.js.map +1 -0
- package/dist/security/bridge/permissions.js +21 -1
- package/dist/security/bridge/permissions.js.map +1 -1
- package/dist/security-cli.d.ts +13 -2
- package/dist/security-cli.js +35 -6
- package/dist/security-cli.js.map +1 -1
- package/dist/sessions-commands.js +10 -0
- package/dist/sessions-commands.js.map +1 -1
- package/dist/types.d.ts +4 -1
- package/dist/wire-types.d.ts +2 -0
- package/dist/wire-types.js.map +1 -1
- package/muse-plugin/.muse-plugin/plugin.json +41 -1
- package/muse-plugin/hooks/ftown-post-tool-use-failure.sh +27 -0
- package/muse-plugin/hooks/ftown-post-tool-use.sh +26 -0
- package/muse-plugin/hooks/ftown-pre-tool-use.sh +26 -0
- package/muse-plugin/hooks/ftown-user-prompt-submit.sh +26 -0
- package/muse-plugin/lib/ftown-hook.sh +42 -5
- package/opencode-plugin/ftown.js +121 -11
- package/package.json +2 -2
- package/skills/ftown/SKILL.md +42 -0
- package/skills/ftown/references/orchestrator.md +29 -25
- package/skills/ftown/references/sessions.md +64 -4
|
@@ -0,0 +1,534 @@
|
|
|
1
|
+
import { PLAN_LIMITS, PLAN_STATES, PlanValidationError, } from './contract-c.js';
|
|
2
|
+
const ITEM_ID_RE = /^p(\d{1,6})$/;
|
|
3
|
+
const SESSION_ID_RE = /^[A-Za-z0-9_-]{1,200}$/;
|
|
4
|
+
const ADD_KEYS = new Set(['title', 'note', 'after', 'priority']);
|
|
5
|
+
const PATCH_KEYS = new Set(['id', 'title', 'note', 'after', 'priority', 'state', 'sessionId']);
|
|
6
|
+
function hasOwn(record, key) {
|
|
7
|
+
return Object.prototype.hasOwnProperty.call(record, key);
|
|
8
|
+
}
|
|
9
|
+
function emptyPlan() {
|
|
10
|
+
return { items: [], seq: 1 };
|
|
11
|
+
}
|
|
12
|
+
function requireNow(now) {
|
|
13
|
+
if (typeof now !== 'string' || now.trim() === '' || Number.isNaN(Date.parse(now))) {
|
|
14
|
+
throw new PlanValidationError('now must be an ISO timestamp');
|
|
15
|
+
}
|
|
16
|
+
return now;
|
|
17
|
+
}
|
|
18
|
+
function asRecord(input, label) {
|
|
19
|
+
if (typeof input !== 'object' || input === null || Array.isArray(input)) {
|
|
20
|
+
throw new PlanValidationError(`${label} must be an object`);
|
|
21
|
+
}
|
|
22
|
+
return input;
|
|
23
|
+
}
|
|
24
|
+
function asPlan(plan) {
|
|
25
|
+
if (plan == null)
|
|
26
|
+
return emptyPlan();
|
|
27
|
+
if (typeof plan !== 'object' || !Array.isArray(plan.items) || !Number.isInteger(plan.seq)) {
|
|
28
|
+
throw new PlanValidationError('plan is invalid');
|
|
29
|
+
}
|
|
30
|
+
return plan;
|
|
31
|
+
}
|
|
32
|
+
/** Control characters become spaces, then whitespace runs collapse. Length is in code points. */
|
|
33
|
+
function cleanText(value, field, minLength, maxLength) {
|
|
34
|
+
if (typeof value !== 'string')
|
|
35
|
+
throw new PlanValidationError(`${field} must be a string`);
|
|
36
|
+
const withoutControls = [...value].map((char) => {
|
|
37
|
+
const code = char.codePointAt(0) ?? 0;
|
|
38
|
+
return code <= 31 || code === 127 ? ' ' : char;
|
|
39
|
+
}).join('');
|
|
40
|
+
const cleaned = withoutControls.replace(/\s+/g, ' ').trim();
|
|
41
|
+
const cleanedLength = [...cleaned].length;
|
|
42
|
+
if (cleanedLength < minLength)
|
|
43
|
+
throw new PlanValidationError(`${field} must not be empty`);
|
|
44
|
+
if (cleanedLength > maxLength)
|
|
45
|
+
throw new PlanValidationError(`${field} must be at most ${maxLength} characters`);
|
|
46
|
+
return cleaned;
|
|
47
|
+
}
|
|
48
|
+
function cloneItem(item) {
|
|
49
|
+
const copy = {
|
|
50
|
+
id: item.id,
|
|
51
|
+
title: item.title,
|
|
52
|
+
after: [...item.after],
|
|
53
|
+
priority: item.priority,
|
|
54
|
+
state: item.state,
|
|
55
|
+
createdAt: item.createdAt,
|
|
56
|
+
updatedAt: item.updatedAt,
|
|
57
|
+
};
|
|
58
|
+
if (item.note !== undefined)
|
|
59
|
+
copy.note = item.note;
|
|
60
|
+
if (item.sessionId !== undefined)
|
|
61
|
+
copy.sessionId = item.sessionId;
|
|
62
|
+
return copy;
|
|
63
|
+
}
|
|
64
|
+
function compareText(left, right) {
|
|
65
|
+
if (left < right)
|
|
66
|
+
return -1;
|
|
67
|
+
if (left > right)
|
|
68
|
+
return 1;
|
|
69
|
+
return 0;
|
|
70
|
+
}
|
|
71
|
+
function compareId(left, right) {
|
|
72
|
+
const leftMatch = ITEM_ID_RE.exec(left);
|
|
73
|
+
const rightMatch = ITEM_ID_RE.exec(right);
|
|
74
|
+
if (leftMatch && rightMatch) {
|
|
75
|
+
const delta = Number(leftMatch[1]) - Number(rightMatch[1]);
|
|
76
|
+
if (delta !== 0)
|
|
77
|
+
return delta;
|
|
78
|
+
}
|
|
79
|
+
return compareText(left, right);
|
|
80
|
+
}
|
|
81
|
+
function comparePrecedence(left, right) {
|
|
82
|
+
return left.priority - right.priority || compareText(left.createdAt, right.createdAt) || compareId(left.id, right.id);
|
|
83
|
+
}
|
|
84
|
+
function compareUpdatedAsc(left, right) {
|
|
85
|
+
return compareText(left.updatedAt, right.updatedAt) || compareId(left.id, right.id);
|
|
86
|
+
}
|
|
87
|
+
function compareUpdatedDesc(left, right) {
|
|
88
|
+
return compareText(right.updatedAt, left.updatedAt) || compareId(left.id, right.id);
|
|
89
|
+
}
|
|
90
|
+
function isSatisfied(item) {
|
|
91
|
+
return item?.state === 'done' || item?.state === 'dropped';
|
|
92
|
+
}
|
|
93
|
+
function isReady(item, byId) {
|
|
94
|
+
for (const id of item.after) {
|
|
95
|
+
if (!isSatisfied(byId.get(id)))
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
function partition(items) {
|
|
101
|
+
const byId = new Map(items.map((item) => [item.id, item]));
|
|
102
|
+
const groups = {
|
|
103
|
+
ready: [],
|
|
104
|
+
waiting: [],
|
|
105
|
+
started: [],
|
|
106
|
+
done: [],
|
|
107
|
+
dropped: [],
|
|
108
|
+
};
|
|
109
|
+
for (const item of items) {
|
|
110
|
+
if (item.state === 'todo')
|
|
111
|
+
groups[isReady(item, byId) ? 'ready' : 'waiting'].push(item);
|
|
112
|
+
else
|
|
113
|
+
groups[item.state].push(item);
|
|
114
|
+
}
|
|
115
|
+
groups.ready.sort(comparePrecedence);
|
|
116
|
+
groups.waiting.sort(comparePrecedence);
|
|
117
|
+
groups.started.sort(compareUpdatedAsc);
|
|
118
|
+
groups.done.sort(compareUpdatedDesc);
|
|
119
|
+
groups.dropped.sort(compareUpdatedDesc);
|
|
120
|
+
return groups;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Ready, then waiting, then started, then done, then dropped.
|
|
124
|
+
* Ready and waiting: priority ascending, then createdAt ascending.
|
|
125
|
+
* Started: updatedAt ascending. Done and dropped: updatedAt descending.
|
|
126
|
+
* Id number breaks remaining ties.
|
|
127
|
+
*/
|
|
128
|
+
export function orderPlan(items) {
|
|
129
|
+
const groups = partition(items);
|
|
130
|
+
return {
|
|
131
|
+
items: [...groups.ready, ...groups.waiting, ...groups.started, ...groups.done, ...groups.dropped],
|
|
132
|
+
ready: groups.ready.map((item) => item.id),
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
/** Ids of todo items whose every `after` dependency is done or dropped, in plan order. */
|
|
136
|
+
export function readyIds(items) {
|
|
137
|
+
return orderPlan(items).ready;
|
|
138
|
+
}
|
|
139
|
+
/** Ids that are ready in `after` and were not ready in `before`, in the new ready order. */
|
|
140
|
+
export function newlyReady(before, after) {
|
|
141
|
+
const previous = new Set(readyIds(before));
|
|
142
|
+
return readyIds(after).filter((id) => !previous.has(id));
|
|
143
|
+
}
|
|
144
|
+
function withReady(base, before, after) {
|
|
145
|
+
const ready = newlyReady(before, after);
|
|
146
|
+
if (ready.length === 0)
|
|
147
|
+
return base;
|
|
148
|
+
return `${base} → ready: ${ready.join(', ')}`;
|
|
149
|
+
}
|
|
150
|
+
function eventSummary(item, before, after) {
|
|
151
|
+
return withReady(`${item.id} ${item.state}: ${item.title}`, before, after);
|
|
152
|
+
}
|
|
153
|
+
function rejectUnknown(record, allowed) {
|
|
154
|
+
const keys = Object.keys(record).filter((key) => record[key] !== undefined);
|
|
155
|
+
for (const key of keys) {
|
|
156
|
+
if (!allowed.has(key))
|
|
157
|
+
throw new PlanValidationError(`Unknown plan field: ${key}`);
|
|
158
|
+
}
|
|
159
|
+
return keys;
|
|
160
|
+
}
|
|
161
|
+
function parsePriority(value) {
|
|
162
|
+
if (value !== 1 && value !== 2 && value !== 3)
|
|
163
|
+
throw new PlanValidationError('priority must be 1, 2 or 3');
|
|
164
|
+
return value;
|
|
165
|
+
}
|
|
166
|
+
function parseState(value) {
|
|
167
|
+
if (typeof value !== 'string' || !PLAN_STATES.includes(value)) {
|
|
168
|
+
throw new PlanValidationError(`state must be one of: ${PLAN_STATES.join(', ')}`);
|
|
169
|
+
}
|
|
170
|
+
return value;
|
|
171
|
+
}
|
|
172
|
+
function parseSessionId(value) {
|
|
173
|
+
if (value === null)
|
|
174
|
+
return null;
|
|
175
|
+
if (typeof value !== 'string')
|
|
176
|
+
throw new PlanValidationError('sessionId must be a string');
|
|
177
|
+
if (!SESSION_ID_RE.test(value))
|
|
178
|
+
throw new PlanValidationError('sessionId is invalid');
|
|
179
|
+
return value;
|
|
180
|
+
}
|
|
181
|
+
function parseItemId(value) {
|
|
182
|
+
if (typeof value !== 'string' || !ITEM_ID_RE.test(value))
|
|
183
|
+
throw new PlanValidationError('plan item id is invalid');
|
|
184
|
+
return value;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* `selfId`, when set, is the item being edited (or the id about to be allocated).
|
|
188
|
+
* Existence is checked against `items`, which does not include an item still being added.
|
|
189
|
+
*/
|
|
190
|
+
function parseAfter(value, items, selfId) {
|
|
191
|
+
if (!Array.isArray(value) || value.some((id) => typeof id !== 'string')) {
|
|
192
|
+
throw new PlanValidationError('after must be an array of item ids');
|
|
193
|
+
}
|
|
194
|
+
const ids = value;
|
|
195
|
+
if (ids.length > PLAN_LIMITS.after) {
|
|
196
|
+
throw new PlanValidationError(`after must list at most ${PLAN_LIMITS.after} items`);
|
|
197
|
+
}
|
|
198
|
+
const known = new Set(items.map((item) => item.id));
|
|
199
|
+
const seen = new Set();
|
|
200
|
+
for (const id of ids) {
|
|
201
|
+
if (!ITEM_ID_RE.test(id))
|
|
202
|
+
throw new PlanValidationError(`after id ${id} is invalid`);
|
|
203
|
+
if (seen.has(id))
|
|
204
|
+
throw new PlanValidationError(`duplicate after id ${id}`);
|
|
205
|
+
seen.add(id);
|
|
206
|
+
if (selfId !== null && id === selfId)
|
|
207
|
+
throw new PlanValidationError('plan item cannot depend on itself');
|
|
208
|
+
if (!known.has(id))
|
|
209
|
+
throw new PlanValidationError(`after id ${id} does not exist`);
|
|
210
|
+
}
|
|
211
|
+
return [...ids];
|
|
212
|
+
}
|
|
213
|
+
/** Depth-first search from the edited item. A back-edge to a visiting node is a cycle. */
|
|
214
|
+
function assertNoCycle(items, startId) {
|
|
215
|
+
const edges = new Map(items.map((item) => [item.id, item.after]));
|
|
216
|
+
const color = new Map();
|
|
217
|
+
const stack = [startId];
|
|
218
|
+
const nextIndex = [0];
|
|
219
|
+
color.set(startId, 1);
|
|
220
|
+
while (stack.length > 0) {
|
|
221
|
+
const depth = stack.length - 1;
|
|
222
|
+
const id = stack[depth];
|
|
223
|
+
const after = id === undefined ? [] : edges.get(id) ?? [];
|
|
224
|
+
const index = nextIndex[depth] ?? 0;
|
|
225
|
+
if (id === undefined || index >= after.length) {
|
|
226
|
+
if (id !== undefined)
|
|
227
|
+
color.set(id, 2);
|
|
228
|
+
stack.pop();
|
|
229
|
+
nextIndex.pop();
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
nextIndex[depth] = index + 1;
|
|
233
|
+
const next = after[index];
|
|
234
|
+
if (next === undefined)
|
|
235
|
+
continue;
|
|
236
|
+
const mark = color.get(next);
|
|
237
|
+
if (mark === 1)
|
|
238
|
+
throw new PlanValidationError('plan after contains a cycle');
|
|
239
|
+
if (mark === 2 || !edges.has(next))
|
|
240
|
+
continue;
|
|
241
|
+
color.set(next, 1);
|
|
242
|
+
stack.push(next);
|
|
243
|
+
nextIndex.push(0);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
function buildItem(fields) {
|
|
247
|
+
const item = {
|
|
248
|
+
id: fields.id,
|
|
249
|
+
title: fields.title,
|
|
250
|
+
after: fields.after,
|
|
251
|
+
priority: fields.priority,
|
|
252
|
+
state: fields.state,
|
|
253
|
+
createdAt: fields.createdAt,
|
|
254
|
+
updatedAt: fields.updatedAt,
|
|
255
|
+
};
|
|
256
|
+
if (fields.note !== undefined)
|
|
257
|
+
item.note = fields.note;
|
|
258
|
+
if (fields.sessionId !== undefined)
|
|
259
|
+
item.sessionId = fields.sessionId;
|
|
260
|
+
return item;
|
|
261
|
+
}
|
|
262
|
+
export function applyAdd(plan, input, now) {
|
|
263
|
+
const stamp = requireNow(now);
|
|
264
|
+
const current = asPlan(plan);
|
|
265
|
+
const record = asRecord(input, 'plan add');
|
|
266
|
+
const keys = rejectUnknown(record, ADD_KEYS);
|
|
267
|
+
if (!keys.includes('title'))
|
|
268
|
+
throw new PlanValidationError('title is required');
|
|
269
|
+
if (current.items.length >= PLAN_LIMITS.items) {
|
|
270
|
+
throw new PlanValidationError(`plan is limited to ${PLAN_LIMITS.items} items`);
|
|
271
|
+
}
|
|
272
|
+
const id = `p${current.seq}`;
|
|
273
|
+
if (!ITEM_ID_RE.test(id))
|
|
274
|
+
throw new PlanValidationError('plan sequence is exhausted');
|
|
275
|
+
if (current.items.some((item) => item.id === id))
|
|
276
|
+
throw new PlanValidationError(`plan id ${id} already exists`);
|
|
277
|
+
const title = cleanText(record.title, 'title', 1, PLAN_LIMITS.title);
|
|
278
|
+
// A note that cleans to nothing is omitted. Patch still rejects an empty note; null clears there.
|
|
279
|
+
let note;
|
|
280
|
+
if (keys.includes('note')) {
|
|
281
|
+
const cleaned = cleanText(record.note, 'note', 0, PLAN_LIMITS.note);
|
|
282
|
+
if (cleaned !== '')
|
|
283
|
+
note = cleaned;
|
|
284
|
+
}
|
|
285
|
+
const after = keys.includes('after') ? parseAfter(record.after, current.items, id) : [];
|
|
286
|
+
const priority = keys.includes('priority') ? parsePriority(record.priority) : 2;
|
|
287
|
+
const created = buildItem({
|
|
288
|
+
id,
|
|
289
|
+
title,
|
|
290
|
+
after,
|
|
291
|
+
priority,
|
|
292
|
+
state: 'todo',
|
|
293
|
+
...(note !== undefined ? { note } : {}),
|
|
294
|
+
createdAt: stamp,
|
|
295
|
+
updatedAt: stamp,
|
|
296
|
+
});
|
|
297
|
+
const items = [...current.items.map(cloneItem), created];
|
|
298
|
+
assertNoCycle(items, id);
|
|
299
|
+
return { seq: current.seq + 1, items };
|
|
300
|
+
}
|
|
301
|
+
function parsePatch(input) {
|
|
302
|
+
const record = asRecord(input, 'plan update');
|
|
303
|
+
const keys = rejectUnknown(record, PATCH_KEYS);
|
|
304
|
+
if (!keys.includes('id'))
|
|
305
|
+
throw new PlanValidationError('plan item id is invalid');
|
|
306
|
+
const parsed = {
|
|
307
|
+
id: parseItemId(record.id),
|
|
308
|
+
hasTitle: keys.includes('title'),
|
|
309
|
+
hasNote: keys.includes('note'),
|
|
310
|
+
hasAfter: keys.includes('after'),
|
|
311
|
+
hasPriority: keys.includes('priority'),
|
|
312
|
+
hasState: keys.includes('state'),
|
|
313
|
+
hasSessionId: keys.includes('sessionId'),
|
|
314
|
+
};
|
|
315
|
+
if (!parsed.hasTitle && !parsed.hasNote && !parsed.hasAfter && !parsed.hasPriority && !parsed.hasState && !parsed.hasSessionId) {
|
|
316
|
+
throw new PlanValidationError('Empty plan update');
|
|
317
|
+
}
|
|
318
|
+
if (parsed.hasTitle)
|
|
319
|
+
parsed.title = cleanText(record.title, 'title', 1, PLAN_LIMITS.title);
|
|
320
|
+
if (parsed.hasNote) {
|
|
321
|
+
parsed.note = record.note === null ? null : cleanText(record.note, 'note', 1, PLAN_LIMITS.note);
|
|
322
|
+
}
|
|
323
|
+
if (parsed.hasPriority)
|
|
324
|
+
parsed.priority = parsePriority(record.priority);
|
|
325
|
+
// Any state may follow any other state. There is no transition table.
|
|
326
|
+
if (parsed.hasState)
|
|
327
|
+
parsed.state = parseState(record.state);
|
|
328
|
+
if (parsed.hasSessionId)
|
|
329
|
+
parsed.sessionId = parseSessionId(record.sessionId);
|
|
330
|
+
return parsed;
|
|
331
|
+
}
|
|
332
|
+
/** Validates a patch and returns the updated plan. `applyPatch` delegates here. */
|
|
333
|
+
export function validatePatch(plan, input, now) {
|
|
334
|
+
const stamp = requireNow(now);
|
|
335
|
+
const current = asPlan(plan);
|
|
336
|
+
const parsed = parsePatch(input);
|
|
337
|
+
// `after` existence uses the pre-edit items. Parse before replacing the target.
|
|
338
|
+
const existing = current.items.find((item) => item.id === parsed.id);
|
|
339
|
+
if (!existing)
|
|
340
|
+
throw new PlanValidationError(`Plan item ${parsed.id} does not exist`);
|
|
341
|
+
if (parsed.hasAfter)
|
|
342
|
+
parsed.after = parseAfter(recordAfter(input), current.items, parsed.id);
|
|
343
|
+
const title = parsed.hasTitle ? parsed.title ?? existing.title : existing.title;
|
|
344
|
+
let note = existing.note;
|
|
345
|
+
if (parsed.hasNote)
|
|
346
|
+
note = parsed.note === null ? undefined : parsed.note;
|
|
347
|
+
const after = parsed.hasAfter ? parsed.after ?? [] : [...existing.after];
|
|
348
|
+
const priority = parsed.hasPriority ? parsed.priority ?? existing.priority : existing.priority;
|
|
349
|
+
const state = parsed.hasState ? parsed.state ?? existing.state : existing.state;
|
|
350
|
+
let sessionId = existing.sessionId;
|
|
351
|
+
if (parsed.hasSessionId)
|
|
352
|
+
sessionId = parsed.sessionId === null ? undefined : parsed.sessionId;
|
|
353
|
+
// Setting state to todo drops the child link. An explicit sessionId in the same patch does not keep it.
|
|
354
|
+
if (parsed.hasState && parsed.state === 'todo')
|
|
355
|
+
sessionId = undefined;
|
|
356
|
+
const updated = buildItem({
|
|
357
|
+
id: existing.id,
|
|
358
|
+
title,
|
|
359
|
+
after,
|
|
360
|
+
priority,
|
|
361
|
+
state,
|
|
362
|
+
...(note !== undefined ? { note } : {}),
|
|
363
|
+
...(sessionId !== undefined ? { sessionId } : {}),
|
|
364
|
+
createdAt: existing.createdAt,
|
|
365
|
+
updatedAt: stamp,
|
|
366
|
+
});
|
|
367
|
+
const items = current.items.map((item) => (item.id === existing.id ? updated : cloneItem(item)));
|
|
368
|
+
if (parsed.hasAfter)
|
|
369
|
+
assertNoCycle(items, existing.id);
|
|
370
|
+
return { seq: current.seq, items };
|
|
371
|
+
}
|
|
372
|
+
function recordAfter(input) {
|
|
373
|
+
const record = asRecord(input, 'plan update');
|
|
374
|
+
return record.after;
|
|
375
|
+
}
|
|
376
|
+
export function applyPatch(plan, input, now) {
|
|
377
|
+
return validatePatch(plan, input, now);
|
|
378
|
+
}
|
|
379
|
+
export function applyRemove(plan, input, now) {
|
|
380
|
+
requireNow(now);
|
|
381
|
+
const current = asPlan(plan);
|
|
382
|
+
const id = typeof input === 'string' || input == null || typeof input !== 'object'
|
|
383
|
+
? parseItemId(input)
|
|
384
|
+
: parseItemId(asRecord(input, 'plan remove').id);
|
|
385
|
+
if (!current.items.some((item) => item.id === id))
|
|
386
|
+
throw new PlanValidationError(`Plan item ${id} does not exist`);
|
|
387
|
+
// Survivors keep their timestamps. Only the dependency edge is removed, so a pure
|
|
388
|
+
// unlink does not reshuffle started/done/dropped order.
|
|
389
|
+
const items = current.items
|
|
390
|
+
.filter((item) => item.id !== id)
|
|
391
|
+
.map((item) => cloneItem({ ...item, after: item.after.filter((afterId) => afterId !== id) }));
|
|
392
|
+
return { seq: current.seq, items };
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Reloads the parent before every save. Each successful change publishes the saved
|
|
396
|
+
* session, then emits one `plan` summary — `<id> <state>: <title>`, plus
|
|
397
|
+
* ` → ready: <id>, <id>` when items became ready. An emit failure is warned and
|
|
398
|
+
* does not undo the publish.
|
|
399
|
+
*/
|
|
400
|
+
export class PlanStore {
|
|
401
|
+
deps;
|
|
402
|
+
constructor(deps) {
|
|
403
|
+
this.deps = deps;
|
|
404
|
+
}
|
|
405
|
+
async get(parentId) {
|
|
406
|
+
const session = await this.deps.loadSession(parentId);
|
|
407
|
+
if (!session?.plan || !Array.isArray(session.plan.items))
|
|
408
|
+
return null;
|
|
409
|
+
return { seq: session.plan.seq, items: session.plan.items.map(cloneItem) };
|
|
410
|
+
}
|
|
411
|
+
async add(parentId, input) {
|
|
412
|
+
const change = await this.change(parentId, (plan) => {
|
|
413
|
+
const next = applyAdd(plan, input, this.stamp());
|
|
414
|
+
const created = next.items.find((item) => !plan.items.some((existing) => existing.id === item.id));
|
|
415
|
+
if (!created)
|
|
416
|
+
throw new PlanValidationError('plan item was not created');
|
|
417
|
+
return { plan: next, summary: eventSummary(created, plan.items, next.items), item: created };
|
|
418
|
+
});
|
|
419
|
+
if (!change.item)
|
|
420
|
+
throw new PlanValidationError('plan item was not created');
|
|
421
|
+
return change.item;
|
|
422
|
+
}
|
|
423
|
+
async patch(parentId, itemId, input) {
|
|
424
|
+
const change = await this.change(parentId, (plan) => {
|
|
425
|
+
const next = validatePatch(plan, { ...input, id: itemId }, this.stamp());
|
|
426
|
+
const updated = next.items.find((item) => item.id === itemId);
|
|
427
|
+
if (!updated)
|
|
428
|
+
throw new PlanValidationError(`Plan item ${itemId} does not exist`);
|
|
429
|
+
return { plan: next, summary: eventSummary(updated, plan.items, next.items), item: updated };
|
|
430
|
+
});
|
|
431
|
+
if (!change.item)
|
|
432
|
+
throw new PlanValidationError(`Plan item ${itemId} does not exist`);
|
|
433
|
+
return change.item;
|
|
434
|
+
}
|
|
435
|
+
async remove(parentId, itemId) {
|
|
436
|
+
await this.change(parentId, (plan) => {
|
|
437
|
+
const existing = plan.items.find((item) => item.id === itemId);
|
|
438
|
+
if (!existing)
|
|
439
|
+
throw new PlanValidationError(`Plan item ${itemId} does not exist`);
|
|
440
|
+
const next = applyRemove(plan, itemId, this.stamp());
|
|
441
|
+
return { plan: next, summary: withReady(`${existing.id} removed: ${existing.title}`, plan.items, next.items) };
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
/** Binds a todo item to a child: state `started`, sessionId = childId. */
|
|
445
|
+
async startForChild(parentId, itemId, childId) {
|
|
446
|
+
await this.change(parentId, (plan) => {
|
|
447
|
+
const current = plan.items.find((item) => item.id === itemId);
|
|
448
|
+
if (!current)
|
|
449
|
+
throw new PlanValidationError(`Plan item ${itemId} does not exist`);
|
|
450
|
+
if (current.state !== 'todo')
|
|
451
|
+
throw new PlanValidationError(`Plan item ${itemId} is ${current.state}, not todo`);
|
|
452
|
+
const next = applyPatch(plan, { id: itemId, state: 'started', sessionId: childId }, this.stamp());
|
|
453
|
+
const updated = next.items.find((item) => item.id === itemId);
|
|
454
|
+
if (!updated)
|
|
455
|
+
throw new PlanValidationError(`Plan item ${itemId} does not exist`);
|
|
456
|
+
return { plan: next, summary: eventSummary(updated, plan.items, next.items), item: updated };
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
/**
|
|
460
|
+
* Marks every item with this child and state `started` as `done`.
|
|
461
|
+
* No match, or a missing parent, is a no-op: a failed card stays `started` for the manager.
|
|
462
|
+
*/
|
|
463
|
+
async completeForChild(parentId, childId) {
|
|
464
|
+
const seen = await this.deps.loadSession(parentId);
|
|
465
|
+
if (!seen)
|
|
466
|
+
return;
|
|
467
|
+
const fresh = await this.deps.loadSession(parentId);
|
|
468
|
+
if (!fresh?.plan)
|
|
469
|
+
return;
|
|
470
|
+
const matches = fresh.plan.items.filter((item) => item.sessionId === childId && item.state === 'started');
|
|
471
|
+
if (matches.length === 0)
|
|
472
|
+
return;
|
|
473
|
+
const stamp = this.stamp();
|
|
474
|
+
let next = fresh.plan;
|
|
475
|
+
for (const match of matches) {
|
|
476
|
+
next = applyPatch(next, { id: match.id, state: 'done' }, stamp);
|
|
477
|
+
}
|
|
478
|
+
const primary = next.items.find((item) => item.id === matches[0]?.id);
|
|
479
|
+
if (!primary)
|
|
480
|
+
return;
|
|
481
|
+
await this.persist(fresh, { plan: next, summary: eventSummary(primary, fresh.plan.items, next.items), item: primary });
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* Returns every item with this child and state `started` to `todo` and clears sessionId.
|
|
485
|
+
* No match, or a missing parent, is a no-op. One event: `<id> todo: <title> (session removed)`.
|
|
486
|
+
*/
|
|
487
|
+
async releaseForChild(parentId, childId) {
|
|
488
|
+
const seen = await this.deps.loadSession(parentId);
|
|
489
|
+
if (!seen)
|
|
490
|
+
return;
|
|
491
|
+
const fresh = await this.deps.loadSession(parentId);
|
|
492
|
+
if (!fresh?.plan)
|
|
493
|
+
return;
|
|
494
|
+
const matches = fresh.plan.items.filter((item) => item.sessionId === childId && item.state === 'started');
|
|
495
|
+
if (matches.length === 0)
|
|
496
|
+
return;
|
|
497
|
+
const stamp = this.stamp();
|
|
498
|
+
let next = fresh.plan;
|
|
499
|
+
for (const match of matches) {
|
|
500
|
+
next = applyPatch(next, { id: match.id, state: 'todo' }, stamp);
|
|
501
|
+
}
|
|
502
|
+
const primary = next.items.find((item) => item.id === matches[0]?.id);
|
|
503
|
+
if (!primary)
|
|
504
|
+
return;
|
|
505
|
+
const summary = withReady(`${primary.id} todo: ${primary.title} (session removed)`, fresh.plan.items, next.items);
|
|
506
|
+
await this.persist(fresh, { plan: next, summary, item: primary });
|
|
507
|
+
}
|
|
508
|
+
stamp() {
|
|
509
|
+
return new Date(this.deps.now()).toISOString();
|
|
510
|
+
}
|
|
511
|
+
async change(parentId, mutate) {
|
|
512
|
+
const seen = await this.deps.loadSession(parentId);
|
|
513
|
+
if (!seen)
|
|
514
|
+
throw new Error('Session not found');
|
|
515
|
+
const fresh = await this.deps.loadSession(parentId);
|
|
516
|
+
if (!fresh)
|
|
517
|
+
throw new Error('Session not found');
|
|
518
|
+
const result = mutate(fresh.plan ?? emptyPlan());
|
|
519
|
+
await this.persist(fresh, result);
|
|
520
|
+
return result;
|
|
521
|
+
}
|
|
522
|
+
async persist(fresh, result) {
|
|
523
|
+
const saved = { ...fresh, plan: result.plan };
|
|
524
|
+
await this.deps.saveSession(saved);
|
|
525
|
+
await this.deps.publishSession(saved);
|
|
526
|
+
try {
|
|
527
|
+
await this.deps.emit(saved, result.summary);
|
|
528
|
+
}
|
|
529
|
+
catch (error) {
|
|
530
|
+
console.warn('PlanStore emit failed', error);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
//# sourceMappingURL=plan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan.js","sourceRoot":"","sources":["../../src/coordination/plan.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type PlanStore } from './plan.js';
|
|
2
|
+
import { type RouteModule } from './contract-b.js';
|
|
3
|
+
/**
|
|
4
|
+
* Route module factory for PLAN_ROUTES:
|
|
5
|
+
* GET /api/sessions/:id/plan → PlanView (ordered via orderPlan)
|
|
6
|
+
* POST /api/sessions/:id/plan → { item } (body { title, note?, after?, priority? })
|
|
7
|
+
* PATCH /api/sessions/:id/plan/:itemId → { item } (body { title?, note?: string|null, after?, priority?, state?, sessionId?: string|null })
|
|
8
|
+
* DELETE /api/sessions/:id/plan/:itemId → { ok: true }
|
|
9
|
+
* Strict bodies (unknown keys → 400), PlanValidationError → 400 (a store-reported missing
|
|
10
|
+
* item or session → 404), unknown session/item → 404, wrong method → 405.
|
|
11
|
+
* Item ids must match p\d{1,6}; other paths fall through (returns false).
|
|
12
|
+
*/
|
|
13
|
+
export declare function createPlanRoutes(store: PlanStore): RouteModule;
|