ftown 0.27.0 → 0.28.0
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/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 +25 -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/plan-cli.d.ts +52 -0
- package/dist/plan-cli.js +357 -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/sessions-commands.js +10 -0
- package/dist/sessions-commands.js.map +1 -1
- package/dist/types.d.ts +4 -1
- 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,47 @@
|
|
|
1
|
+
// ───────────────────────── Plan (todo list with precedence) ─────────────────────────
|
|
2
|
+
export const PLAN_LIMITS = { items: 200, title: 140, note: 500, after: 20 };
|
|
3
|
+
export const PLAN_STATES = ['todo', 'started', 'done', 'dropped'];
|
|
4
|
+
/**
|
|
5
|
+
* Derived ordering (pure helper `orderPlan(items)` in bridge/src/coordination/plan.ts, also re-implemented
|
|
6
|
+
* identically in the UI — see PLAN_ORDER_RULE):
|
|
7
|
+
* ready = state 'todo' && every `after` item is 'done' or 'dropped'
|
|
8
|
+
* waiting = state 'todo' && not ready
|
|
9
|
+
* Order: ready (priority asc, createdAt asc), then waiting (same), then started (updatedAt asc),
|
|
10
|
+
* then done (updatedAt desc), then dropped (updatedAt desc).
|
|
11
|
+
*/
|
|
12
|
+
export const PLAN_ORDER_RULE = 'ready>waiting>started>done>dropped; within ready/waiting: priority asc, createdAt asc';
|
|
13
|
+
/** Routes (via dispatchSecure; :id = parent session). Caller: local-cli principal; any session may edit the plan of :id (owner-only enforcement is out of scope). */
|
|
14
|
+
export const PLAN_ROUTES = {
|
|
15
|
+
/** GET → PlanView; POST body { title, note?, after?, priority? } → { item } */
|
|
16
|
+
plan: '/api/sessions/:id/plan',
|
|
17
|
+
/** PATCH body { title?, note?: string|null, after?, priority?, state?, sessionId?: string|null } → { item }; DELETE → { ok: true } (removes id from others' `after`) */
|
|
18
|
+
item: '/api/sessions/:id/plan/:itemId',
|
|
19
|
+
};
|
|
20
|
+
export class PlanValidationError extends Error {
|
|
21
|
+
constructor(message) { super(message); this.name = 'PlanValidationError'; }
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Automatic transitions (bridge wiring):
|
|
25
|
+
* - `ftown sessions create --parent --plan-item <id>`: after the child exists, item.state = 'started', item.sessionId = child.id.
|
|
26
|
+
* Unknown/non-todo item → create fails 400 BEFORE the session is created.
|
|
27
|
+
* - When a child's declared card becomes 'done' and an item of its parent has sessionId === child.id and state 'started' → 'done'.
|
|
28
|
+
* 'failed' card → item back to 'todo' with sessionId cleared? NO: leave 'started' (manager decides).
|
|
29
|
+
* - Every plan change emits ONE tree event kind 'plan' on the parent's log with summary
|
|
30
|
+
* `<id> <state>: <title>` ; when items become ready because of it, append ` → ready: <id>, <id>`.
|
|
31
|
+
*
|
|
32
|
+
* CLI (bridge/src/plan-cli.ts, group `ftown plan`, default session = FTOWN_SESSION_ID = the manager):
|
|
33
|
+
* ftown plan [--json] [--session-id <id>] list in order: `<mark> <id> [P<prio>] <title> (after p1,p2 | → <child name>)`
|
|
34
|
+
* marks: `→` ready, `·` waiting, `▸` started, `✓` done, `✗` dropped
|
|
35
|
+
* ftown plan add <title...> [--note <t>] [--after <id,id>] [--priority 1|2|3]
|
|
36
|
+
* ftown plan start <id> --session <child-id>
|
|
37
|
+
* ftown plan done <id> | drop <id> | todo <id>
|
|
38
|
+
* ftown plan edit <id> [--title <t>] [--note <t>|--no-note] [--after <ids>|--no-after] [--priority n]
|
|
39
|
+
* ftown plan rm <id>
|
|
40
|
+
* ftown sessions create --parent --plan-item <id> ... (in sessions-commands.ts)
|
|
41
|
+
* Exit codes: 0 ok, 1 error, 2 usage.
|
|
42
|
+
*/
|
|
43
|
+
// ───────────────────────── Tree events: new kinds ─────────────────────────
|
|
44
|
+
/** Added to TREE_EVENT_KINDS in contract.ts (phase C edit): 'plan' and 'removed'. */
|
|
45
|
+
export const PHASE_C_EVENT_KINDS = ['plan', 'removed'];
|
|
46
|
+
export const BOARD_SNAPSHOT_EVENTS = 50;
|
|
47
|
+
//# sourceMappingURL=contract-c.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract-c.js","sourceRoot":"","sources":["../../src/coordination/contract-c.ts"],"names":[],"mappings":"AAQA,uFAAuF;AAEvF,MAAM,CAAC,MAAM,WAAW,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAW,CAAC;AACrF,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,CAAU,CAAC;AAmB3E;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,uFAAgG,CAAC;AAIhI,qKAAqK;AACrK,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,+EAA+E;IAC/E,IAAI,EAAE,wBAAwB;IAC9B,wKAAwK;IACxK,IAAI,EAAE,gCAAgC;CAC9B,CAAC;AAEX,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAC5C,YAAY,OAAe,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC,CAAC,CAAC;CACpF;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,6EAA6E;AAE7E,qFAAqF;AACrF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,MAAM,EAAE,SAAS,CAAU,CAAC;AA6BhE,MAAM,CAAC,MAAM,qBAAqB,GAAG,EAAE,CAAC"}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import type { Activity } from '../attention-events.js';
|
|
7
7
|
import type { PullRequestState } from '../pull-request-status-protocol.js';
|
|
8
|
+
import type { PlanView } from './contract-c.js';
|
|
8
9
|
import type { MailMessage, Session, SessionStatus } from '../types.js';
|
|
9
10
|
export declare const CARD_STATES: readonly ["working", "blocked", "waiting_review", "done", "failed"];
|
|
10
11
|
export type CardState = typeof CARD_STATES[number];
|
|
@@ -70,6 +71,8 @@ export interface CardDerived {
|
|
|
70
71
|
model?: string;
|
|
71
72
|
}
|
|
72
73
|
export interface SessionCard {
|
|
74
|
+
/** phase C: true for retired (archived) children included by board(all) */
|
|
75
|
+
archived?: boolean;
|
|
73
76
|
sessionId: string;
|
|
74
77
|
name: string;
|
|
75
78
|
parentSessionId?: string;
|
|
@@ -99,7 +102,7 @@ export declare const TREE_EVENTS_RETAIN = 5000;
|
|
|
99
102
|
export declare const TREE_EVENTS_COMPACT_AT = 6000;
|
|
100
103
|
export declare const TREE_EVENTS_MAX_WAIT_MS = 300000;
|
|
101
104
|
export declare const TREE_EVENT_SUMMARY_MAX = 300;
|
|
102
|
-
export declare const TREE_EVENT_KINDS: readonly ["status", "attention", "pr", "preview", "exit", "idle", "result", "mail"];
|
|
105
|
+
export declare const TREE_EVENT_KINDS: readonly ["status", "attention", "pr", "preview", "exit", "idle", "result", "mail", "plan", "removed"];
|
|
103
106
|
export type TreeEventKind = typeof TREE_EVENT_KINDS[number];
|
|
104
107
|
export interface TreeEvent {
|
|
105
108
|
seq: number;
|
|
@@ -135,6 +138,8 @@ export interface TreeEventLogApi {
|
|
|
135
138
|
}
|
|
136
139
|
export type BoardRollupKey = CardState | 'unset';
|
|
137
140
|
export interface Board {
|
|
141
|
+
/** phase C: the root's plan, ordered */
|
|
142
|
+
plan?: PlanView;
|
|
138
143
|
rootId: string;
|
|
139
144
|
/** tree event head at render time; pass back as `since` */
|
|
140
145
|
cursor: number;
|
|
@@ -153,6 +158,8 @@ export interface BoardQuery {
|
|
|
153
158
|
all?: boolean;
|
|
154
159
|
}
|
|
155
160
|
export interface BoardDeps {
|
|
161
|
+
/** phase C: archived session records */
|
|
162
|
+
listArchived?(): Promise<Session[]>;
|
|
156
163
|
loadSession(id: string): Promise<Session | null>;
|
|
157
164
|
listSessions(): Promise<Session[]>;
|
|
158
165
|
attention(id: string): Promise<{
|
|
@@ -19,7 +19,7 @@ export const TREE_EVENTS_RETAIN = 5_000; // keep newest N on compaction
|
|
|
19
19
|
export const TREE_EVENTS_COMPACT_AT = 6_000;
|
|
20
20
|
export const TREE_EVENTS_MAX_WAIT_MS = 300_000;
|
|
21
21
|
export const TREE_EVENT_SUMMARY_MAX = 300;
|
|
22
|
-
export const TREE_EVENT_KINDS = ['status', 'attention', 'pr', 'preview', 'exit', 'idle', 'result', 'mail'];
|
|
22
|
+
export const TREE_EVENT_KINDS = ['status', 'attention', 'pr', 'preview', 'exit', 'idle', 'result', 'mail', 'plan', 'removed'];
|
|
23
23
|
/**
|
|
24
24
|
* Digest line format (exact):
|
|
25
25
|
* `[ftown] since HH:MM: <part> | <part> | ...`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../../src/coordination/contract.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../../src/coordination/contract.ts"],"names":[],"mappings":"AAUA,2FAA2F;AAE3F,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,SAAS,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,EAAE,QAAQ,CAAU,CAAC;AAG/F,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,CAAU,CAAC;AAGpF,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,QAAQ,EAAE,GAAG;IACb,IAAI,EAAE,GAAG;IACT,WAAW,EAAE,GAAG;IAChB,yDAAyD;IACzD,aAAa,EAAE,MAAM;CACb,CAAC;AA4BX,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAC5C,YAAY,OAAe,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC,CAAC,CAAC;CACpF;AAgCD,MAAM,CAAC,MAAM,aAAa,GAAG,EAAE,GAAG,MAAM,CAAC;AAoBzC,qEAAqE;AAErE,uFAAuF;AACvF,MAAM,CAAC,MAAM,gBAAgB,GAAG,mBAAmB,CAAC,CAAC,wBAAwB;AAC7E,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,CAAC,CAAG,8BAA8B;AACzE,MAAM,CAAC,MAAM,sBAAsB,GAAG,KAAK,CAAC;AAC5C,MAAM,CAAC,MAAM,uBAAuB,GAAG,OAAO,CAAC;AAC/C,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,CAAC;AAE1C,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,CAAU,CAAC;AA4EvI;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,GAAG,CAAC;AAE9B;;GAEG;AAEH,6EAA6E;AAE7E,iEAAiE;AACjE,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,CAAU,CAAC;AAEzF,0FAA0F;AAC1F,MAAM,CAAC,MAAM,qBAAqB,GAA4B,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;AAC/E,gGAAgG;AAChG,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC;AAsBnC,+GAA+G;AAE/G,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,8GAA8G;IAC9G,IAAI,EAAE,wBAAwB;IAC9B,2CAA2C;IAC3C,KAAK,EAAE,yBAAyB;IAChC,kFAAkF;IAClF,MAAM,EAAE,0BAA0B;CAC1B,CAAC;AAEX,iGAAiG;AACjG;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,CAAU,CAAC"}
|
|
@@ -47,24 +47,50 @@ export function formatBoardRow(card, nowMs) {
|
|
|
47
47
|
if (card.stale) {
|
|
48
48
|
suffix += ' (stale)';
|
|
49
49
|
}
|
|
50
|
+
if (card.archived) {
|
|
51
|
+
suffix += ' (retired)';
|
|
52
|
+
}
|
|
50
53
|
return `${card.name} ${state} ${activity}${idlePart} ${headline}${suffix}`;
|
|
51
54
|
}
|
|
55
|
+
const PLANNED_READY_LIMIT = 5;
|
|
56
|
+
function formatPlannedLines(board) {
|
|
57
|
+
const ready = board.plan?.ready ?? [];
|
|
58
|
+
if (ready.length === 0)
|
|
59
|
+
return [];
|
|
60
|
+
const titleById = new Map((board.plan?.items ?? []).map((item) => [item.id, item.title]));
|
|
61
|
+
const shown = ready.slice(0, PLANNED_READY_LIMIT);
|
|
62
|
+
const lines = ['planned'];
|
|
63
|
+
for (const id of shown) {
|
|
64
|
+
const title = titleById.get(id) ?? '';
|
|
65
|
+
lines.push(title === '' ? `→ ${id}` : `→ ${id} ${title}`);
|
|
66
|
+
}
|
|
67
|
+
const more = ready.length - shown.length;
|
|
68
|
+
if (more > 0)
|
|
69
|
+
lines.push(`+${more} more`);
|
|
70
|
+
return lines;
|
|
71
|
+
}
|
|
52
72
|
export function formatBoard(board, nowMs) {
|
|
73
|
+
const lines = [];
|
|
53
74
|
if (board.cards.length === 0) {
|
|
54
|
-
|
|
75
|
+
lines.push('no child sessions');
|
|
55
76
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
77
|
+
else {
|
|
78
|
+
for (const card of board.cards) {
|
|
79
|
+
lines.push(formatBoardRow(card, nowMs));
|
|
80
|
+
}
|
|
81
|
+
const rollupParts = [];
|
|
82
|
+
for (const key of ROLLUP_ORDER) {
|
|
83
|
+
const count = board.rollup[key] ?? 0;
|
|
84
|
+
if (count > 0) {
|
|
85
|
+
rollupParts.push(`${count} ${key}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (rollupParts.length > 0) {
|
|
89
|
+
lines.push(rollupParts.join(', '));
|
|
62
90
|
}
|
|
63
91
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
67
|
-
return rows.join('\n');
|
|
92
|
+
lines.push(...formatPlannedLines(board));
|
|
93
|
+
return lines.join('\n');
|
|
68
94
|
}
|
|
69
95
|
export function formatEvent(e) {
|
|
70
96
|
const hhmm = formatLocalHHMM(e.ts);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/coordination/format.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,GAKZ,MAAM,eAAe,CAAC;AAEvB,MAAM,YAAY,GAA8B,CAAC,GAAG,WAAW,EAAE,OAAO,CAAC,CAAC;AAE1E,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAE5B,SAAS,IAAI,CAAC,CAAS;IACrB,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AACpC,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY,EAAE,GAAW;IACzC,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,GAAW;IACzC,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;IACxB,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAiB,EAAE,KAAa;IAC7D,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,KAAK,IAAI,GAAG,CAAC;IAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;IAEvC,IAAI,QAAQ,GAAG,EAAE,CAAC;IAClB,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;QACxB,MAAM,WAAW,GACf,IAAI,CAAC,OAAO,CAAC,SAAS,KAAK,SAAS;YAClC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;YACpC,CAAC,CAAC,GAAG,CAAC;QACV,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC;YACvC,CAAC,CAAC,CAAC;YACH,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,WAAW,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;QAC5D,QAAQ,GAAG,SAAS,OAAO,GAAG,CAAC;IACjC,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,QAAQ,IAAI,GAAG,CAAC;IAEhD,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC;IACzC,IAAI,QAAQ,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;IACnD,CAAC;IACD,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC;IAC3C,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,gBAAgB,SAAS,CAAC,IAAI,GAAG,GAAG,KAAK,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE,gBAAgB,CAAC,EAAE,CAAC;IAClG,CAAC;IACD,IAAI,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;QACpB,MAAM,IAAI,QAAQ,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;IAC5C,CAAC;IACD,IAAI,IAAI,CAAC,OAAO,CAAC,aAAa,GAAG,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,MAAM,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;IAC/C,CAAC;IACD,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,MAAM,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;IAC5C,CAAC;IACD,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,WAAW,CAAC;IACxB,CAAC;IAED,OAAO,GAAG,IAAI,CAAC,IAAI,IAAI,KAAK,IAAI,QAAQ,GAAG,QAAQ,KAAK,QAAQ,GAAG,MAAM,EAAE,CAAC;AAC9E,CAAC;AAED,MAAM,
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/coordination/format.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan list: precedence ordering, pure edits, and the session-backed store.
|
|
3
|
+
* Ordering follows PLAN_ORDER_RULE. Ids are `p<seq>` allocated from SessionPlan.seq
|
|
4
|
+
* and then incremented, so a removed id is never reused. A plan that does not exist
|
|
5
|
+
* yet starts at seq 1 (first item `p1`).
|
|
6
|
+
*/
|
|
7
|
+
import type { Session } from '../types.js';
|
|
8
|
+
import { type PlanItem, type PlanPriority, type PlanState, type PlanView, type SessionPlan } from './contract-c.js';
|
|
9
|
+
export interface PlanAddInput {
|
|
10
|
+
title: string;
|
|
11
|
+
note?: string;
|
|
12
|
+
after?: string[];
|
|
13
|
+
priority?: PlanPriority;
|
|
14
|
+
}
|
|
15
|
+
export interface PlanPatchInput {
|
|
16
|
+
title?: string;
|
|
17
|
+
note?: string | null;
|
|
18
|
+
after?: string[];
|
|
19
|
+
priority?: PlanPriority;
|
|
20
|
+
state?: PlanState;
|
|
21
|
+
sessionId?: string | null;
|
|
22
|
+
}
|
|
23
|
+
export interface PlanStoreDeps {
|
|
24
|
+
loadSession(id: string): Promise<Session | null>;
|
|
25
|
+
saveSession(session: Session): Promise<void>;
|
|
26
|
+
publishSession(session: Session): void | Promise<void>;
|
|
27
|
+
emit(parent: Session, summary: string): Promise<void>;
|
|
28
|
+
now(): number;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Ready, then waiting, then started, then done, then dropped.
|
|
32
|
+
* Ready and waiting: priority ascending, then createdAt ascending.
|
|
33
|
+
* Started: updatedAt ascending. Done and dropped: updatedAt descending.
|
|
34
|
+
* Id number breaks remaining ties.
|
|
35
|
+
*/
|
|
36
|
+
export declare function orderPlan(items: readonly PlanItem[]): PlanView;
|
|
37
|
+
/** Ids of todo items whose every `after` dependency is done or dropped, in plan order. */
|
|
38
|
+
export declare function readyIds(items: readonly PlanItem[]): string[];
|
|
39
|
+
/** Ids that are ready in `after` and were not ready in `before`, in the new ready order. */
|
|
40
|
+
export declare function newlyReady(before: readonly PlanItem[], after: readonly PlanItem[]): string[];
|
|
41
|
+
export declare function applyAdd(plan: SessionPlan | null | undefined, input: unknown, now: string): SessionPlan;
|
|
42
|
+
/** Validates a patch and returns the updated plan. `applyPatch` delegates here. */
|
|
43
|
+
export declare function validatePatch(plan: SessionPlan | null | undefined, input: unknown, now: string): SessionPlan;
|
|
44
|
+
export declare function applyPatch(plan: SessionPlan | null | undefined, input: unknown, now: string): SessionPlan;
|
|
45
|
+
export declare function applyRemove(plan: SessionPlan | null | undefined, input: unknown, now: string): SessionPlan;
|
|
46
|
+
/**
|
|
47
|
+
* Reloads the parent before every save. Each successful change publishes the saved
|
|
48
|
+
* session, then emits one `plan` summary — `<id> <state>: <title>`, plus
|
|
49
|
+
* ` → ready: <id>, <id>` when items became ready. An emit failure is warned and
|
|
50
|
+
* does not undo the publish.
|
|
51
|
+
*/
|
|
52
|
+
export declare class PlanStore {
|
|
53
|
+
private readonly deps;
|
|
54
|
+
constructor(deps: PlanStoreDeps);
|
|
55
|
+
get(parentId: string): Promise<SessionPlan | null>;
|
|
56
|
+
add(parentId: string, input: PlanAddInput): Promise<PlanItem>;
|
|
57
|
+
patch(parentId: string, itemId: string, input: PlanPatchInput): Promise<PlanItem>;
|
|
58
|
+
remove(parentId: string, itemId: string): Promise<void>;
|
|
59
|
+
/** Binds a todo item to a child: state `started`, sessionId = childId. */
|
|
60
|
+
startForChild(parentId: string, itemId: string, childId: string): Promise<void>;
|
|
61
|
+
/**
|
|
62
|
+
* Marks every item with this child and state `started` as `done`.
|
|
63
|
+
* No match, or a missing parent, is a no-op: a failed card stays `started` for the manager.
|
|
64
|
+
*/
|
|
65
|
+
completeForChild(parentId: string, childId: string): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* Returns every item with this child and state `started` to `todo` and clears sessionId.
|
|
68
|
+
* No match, or a missing parent, is a no-op. One event: `<id> todo: <title> (session removed)`.
|
|
69
|
+
*/
|
|
70
|
+
releaseForChild(parentId: string, childId: string): Promise<void>;
|
|
71
|
+
private stamp;
|
|
72
|
+
private change;
|
|
73
|
+
private persist;
|
|
74
|
+
}
|