@nestos/kanban 0.0.0-stage → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/README.md +121 -2
  2. package/dist/activity-C6xDM-cg.d.cts +232 -0
  3. package/dist/activity-Dw8DOw0L.d.ts +232 -0
  4. package/dist/activity.cjs +288 -0
  5. package/dist/activity.cjs.map +1 -0
  6. package/dist/activity.d.cts +34 -0
  7. package/dist/activity.d.ts +34 -0
  8. package/dist/activity.js +288 -0
  9. package/dist/activity.js.map +1 -0
  10. package/dist/chunk-2YFPV5GF.cjs +16 -0
  11. package/dist/chunk-2YFPV5GF.cjs.map +1 -0
  12. package/dist/chunk-4KF7KUAI.cjs +221 -0
  13. package/dist/chunk-4KF7KUAI.cjs.map +1 -0
  14. package/dist/chunk-4XF6LQSU.cjs +9 -0
  15. package/dist/chunk-4XF6LQSU.cjs.map +1 -0
  16. package/dist/chunk-5DLZWW5Y.js +148 -0
  17. package/dist/chunk-5DLZWW5Y.js.map +1 -0
  18. package/dist/chunk-5XKOCKY2.js +58 -0
  19. package/dist/chunk-5XKOCKY2.js.map +1 -0
  20. package/dist/chunk-6MN3H3YF.cjs +183 -0
  21. package/dist/chunk-6MN3H3YF.cjs.map +1 -0
  22. package/dist/chunk-ATUFFNLV.js +221 -0
  23. package/dist/chunk-ATUFFNLV.js.map +1 -0
  24. package/dist/chunk-DFTOTBGF.js +439 -0
  25. package/dist/chunk-DFTOTBGF.js.map +1 -0
  26. package/dist/chunk-G6FCDLDF.js +16 -0
  27. package/dist/chunk-G6FCDLDF.js.map +1 -0
  28. package/dist/chunk-IUI5CI2S.cjs +439 -0
  29. package/dist/chunk-IUI5CI2S.cjs.map +1 -0
  30. package/dist/chunk-KYNYPKKH.cjs +71 -0
  31. package/dist/chunk-KYNYPKKH.cjs.map +1 -0
  32. package/dist/chunk-L44TM4EE.cjs +1498 -0
  33. package/dist/chunk-L44TM4EE.cjs.map +1 -0
  34. package/dist/chunk-LSE6JG5I.cjs +20 -0
  35. package/dist/chunk-LSE6JG5I.cjs.map +1 -0
  36. package/dist/chunk-O4OGAAV4.js +71 -0
  37. package/dist/chunk-O4OGAAV4.js.map +1 -0
  38. package/dist/chunk-OHQTKGQN.js +1498 -0
  39. package/dist/chunk-OHQTKGQN.js.map +1 -0
  40. package/dist/chunk-PSKQAFDF.cjs +58 -0
  41. package/dist/chunk-PSKQAFDF.cjs.map +1 -0
  42. package/dist/chunk-QTMTBEBA.js +20 -0
  43. package/dist/chunk-QTMTBEBA.js.map +1 -0
  44. package/dist/chunk-RQP77ZTY.js +9 -0
  45. package/dist/chunk-RQP77ZTY.js.map +1 -0
  46. package/dist/chunk-T7P5EIC4.cjs +148 -0
  47. package/dist/chunk-T7P5EIC4.cjs.map +1 -0
  48. package/dist/chunk-TB2RZGDV.js +183 -0
  49. package/dist/chunk-TB2RZGDV.js.map +1 -0
  50. package/dist/content-CAIp1njn.d.cts +35 -0
  51. package/dist/content-CGMJdyH_.d.ts +35 -0
  52. package/dist/contracts/index.cjs +21 -0
  53. package/dist/contracts/index.cjs.map +1 -0
  54. package/dist/contracts/index.d.cts +4 -0
  55. package/dist/contracts/index.d.ts +4 -0
  56. package/dist/contracts/index.js +21 -0
  57. package/dist/contracts/index.js.map +1 -0
  58. package/dist/discovery-DxpirOz3.d.cts +61 -0
  59. package/dist/discovery-gSqWpuRm.d.ts +61 -0
  60. package/dist/discovery.cjs +379 -0
  61. package/dist/discovery.cjs.map +1 -0
  62. package/dist/discovery.d.cts +22 -0
  63. package/dist/discovery.d.ts +22 -0
  64. package/dist/discovery.js +379 -0
  65. package/dist/discovery.js.map +1 -0
  66. package/dist/execution.cjs +368 -0
  67. package/dist/execution.cjs.map +1 -0
  68. package/dist/execution.d.cts +89 -0
  69. package/dist/execution.d.ts +89 -0
  70. package/dist/execution.js +368 -0
  71. package/dist/execution.js.map +1 -0
  72. package/dist/index.cjs +76 -0
  73. package/dist/index.cjs.map +1 -0
  74. package/dist/index.d.cts +61 -0
  75. package/dist/index.d.ts +61 -0
  76. package/dist/index.js +76 -0
  77. package/dist/index.js.map +1 -0
  78. package/dist/module-BbvwdCDF.d.cts +11 -0
  79. package/dist/module-CWNK2BMj.d.ts +11 -0
  80. package/dist/planning-CcFZYdIL.d.cts +844 -0
  81. package/dist/planning-CcFZYdIL.d.ts +844 -0
  82. package/dist/ports-Bn6ro2FB.d.ts +142 -0
  83. package/dist/ports-CaL6geqR.d.cts +142 -0
  84. package/dist/storage.cjs +289 -0
  85. package/dist/storage.cjs.map +1 -0
  86. package/dist/storage.d.cts +71 -0
  87. package/dist/storage.d.ts +71 -0
  88. package/dist/storage.js +289 -0
  89. package/dist/storage.js.map +1 -0
  90. package/dist/store-Ct0gOAAg.d.ts +28 -0
  91. package/dist/store-q63eSMoT.d.cts +28 -0
  92. package/dist/ui/index.cjs +1961 -0
  93. package/dist/ui/index.cjs.map +1 -0
  94. package/dist/ui/index.d.cts +209 -0
  95. package/dist/ui/index.d.ts +209 -0
  96. package/dist/ui/index.js +1961 -0
  97. package/dist/ui/index.js.map +1 -0
  98. package/dist/ui/kanban.css +194 -0
  99. package/package.json +113 -4
@@ -0,0 +1,288 @@
1
+ import {
2
+ createKanbanModule
3
+ } from "./chunk-DFTOTBGF.js";
4
+ import "./chunk-OHQTKGQN.js";
5
+ import "./chunk-RQP77ZTY.js";
6
+ import {
7
+ candidates,
8
+ principal,
9
+ principalKey
10
+ } from "./chunk-ATUFFNLV.js";
11
+ import {
12
+ KanbanError
13
+ } from "./chunk-G6FCDLDF.js";
14
+ import "./chunk-O4OGAAV4.js";
15
+ import "./chunk-5XKOCKY2.js";
16
+ import {
17
+ randomUUID,
18
+ sha256HexSync
19
+ } from "./chunk-TB2RZGDV.js";
20
+ import "./chunk-QTMTBEBA.js";
21
+
22
+ // src/session-activity-query.ts
23
+ async function querySessionItems(core, boardId, input, project) {
24
+ const { execution = "all", ...query } = input;
25
+ if (!["all", "running", "recent", "active"].includes(execution)) throw new KanbanError("INVALID_EXECUTION_FILTER");
26
+ if (execution === "all") {
27
+ const page2 = await core.query(boardId, query);
28
+ return { ...page2, items: await project(page2.items) };
29
+ }
30
+ const { cursor, limit = 50, ...filters } = query;
31
+ if (!Number.isSafeInteger(limit) || limit < 1 || limit > 200) throw new KanbanError("INVALID_PAGE_SIZE");
32
+ let page = await core.query(boardId, { ...filters, limit: 200 }), rows = [...page.items];
33
+ const revision = page.revision;
34
+ while (page.nextCursor) {
35
+ if (rows.length >= 1e4) throw new KanbanError("ACTIVITY_QUERY_LIMIT");
36
+ page = await core.query(boardId, { ...filters, limit: 200, cursor: page.nextCursor });
37
+ if (page.revision !== revision) throw new KanbanError("CURSOR_STALE");
38
+ rows.push(...page.items);
39
+ }
40
+ const matching = (await project(rows)).filter((row) => matchesExecution(row, execution));
41
+ if ((await core.query(boardId, { ...filters, limit: 1 })).revision !== revision) throw new KanbanError("CURSOR_STALE");
42
+ const scope = sha256HexSync(JSON.stringify({ filters, execution, limit })), signature = sha256HexSync(JSON.stringify(matching.map((row) => row.id)));
43
+ let start = 0;
44
+ if (cursor) {
45
+ let saved;
46
+ try {
47
+ saved = JSON.parse(cursor);
48
+ } catch {
49
+ throw new KanbanError("INVALID_CURSOR");
50
+ }
51
+ if (saved.scope !== scope) throw new KanbanError("CURSOR_SCOPE_MISMATCH");
52
+ if (saved.revision !== revision || saved.signature !== signature) throw new KanbanError("CURSOR_STALE");
53
+ start = matching.findIndex((row) => row.id === saved.after) + 1;
54
+ if (start < 1) throw new KanbanError("INVALID_CURSOR");
55
+ }
56
+ const items = matching.slice(start, start + limit);
57
+ return { revision, total: matching.length, items, ...start + items.length < matching.length ? { nextCursor: JSON.stringify({ scope, revision, signature, after: items.at(-1).id }) } : {} };
58
+ }
59
+ function matchesExecution(row, filter) {
60
+ const session = row.execution;
61
+ if (!session || session.stale) return false;
62
+ return filter === "running" ? session.state === "running" : filter === "recent" ? session.recent : session.state === "running" || session.recent;
63
+ }
64
+
65
+ // src/session-relations.ts
66
+ function sessionAssociations(item, bindings, workflow) {
67
+ return [...bindings.map((ref) => {
68
+ const dispatch = workflow.dispatches[ref.revision ?? ""];
69
+ const execution = dispatch?.itemId === item.id ? {
70
+ id: dispatch.id,
71
+ purpose: "execution",
72
+ dispatchId: dispatch.id,
73
+ attempt: dispatch.attempt,
74
+ outcome: dispatch.outcome,
75
+ createdAt: dispatch.preparedAt,
76
+ code: dispatch.code,
77
+ ...dispatch.continuation ? { previousDispatchId: dispatch.continuation.previousDispatchId } : {}
78
+ } : void 0;
79
+ return { sessionId: ref.id, purpose: "execution", ...execution ? { execution } : {} };
80
+ }), ...item.participants.filter((row) => !bindings.some((ref) => ref.id === row.sessionId)).map((row) => ({ sessionId: row.sessionId, purpose: "discussion" }))];
81
+ }
82
+ async function projectRelatedSessions(associations, currentId, inspect) {
83
+ const grouped = /* @__PURE__ */ new Map();
84
+ for (const row of associations) {
85
+ let group = grouped.get(row.sessionId);
86
+ if (!group) grouped.set(row.sessionId, group = { purposes: /* @__PURE__ */ new Set(), executions: /* @__PURE__ */ new Map() });
87
+ group.purposes.add(row.purpose);
88
+ if (row.execution) group.executions.set(row.execution.id, { ...group.executions.get(row.execution.id), ...row.execution });
89
+ }
90
+ const rows = [], entries = [...grouped];
91
+ let next = 0;
92
+ await Promise.all(Array.from({ length: Math.min(entries.length, 8) }, async () => {
93
+ while (next < entries.length) {
94
+ const [sessionId, group] = entries[next++], state = await inspect(sessionId);
95
+ rows.push({
96
+ ...state,
97
+ current: sessionId === currentId,
98
+ purposes: [...group.purposes].sort(),
99
+ executions: [...group.executions.values()].sort((a, b) => (a.createdAt ?? 0) - (b.createdAt ?? 0) || a.id.localeCompare(b.id))
100
+ });
101
+ }
102
+ }));
103
+ return rows.sort((a, b) => Number(b.current) - Number(a.current) || a.sessionId.localeCompare(b.sessionId));
104
+ }
105
+
106
+ // src/session-activity.ts
107
+ function executionBindings(refs, referenceSystem) {
108
+ return (refs ?? []).filter((ref) => ref.system === referenceSystem);
109
+ }
110
+ function currentBinding(refs, itemId, workflow, referenceSystem) {
111
+ const binding = executionBindings(refs, referenceSystem).at(-1), latest = Object.values(workflow.dispatches).filter((dispatch) => dispatch.itemId === itemId).sort((a, b) => b.attempt - a.attempt)[0];
112
+ if (!binding || !latest || binding.revision === latest.id) return binding;
113
+ return ["prepared", "running", "unknown", "succeeded"].includes(latest.outcome) || workflow.dispatches[binding.revision ?? ""] ? void 0 : binding;
114
+ }
115
+ function createKanbanSessionActivity(core, options, log, referenceSystem) {
116
+ const inspect = createSessionInspector(options, log);
117
+ const project = async (boardId, rows) => {
118
+ if (!rows.some((row) => executionBindings(row.externalRefs, referenceSystem).length)) return rows;
119
+ const [board, workflow] = await Promise.all([boardMetadata(core, boardId), core.workflow(boardId)]), bindings = new Map(rows.map((row) => [row.id, currentBinding(row.externalRefs, row.id, workflow, referenceSystem)]));
120
+ const ids = [...new Set([...bindings.values()].flatMap((ref) => ref ? [ref.id] : []))], states = /* @__PURE__ */ new Map();
121
+ let next = 0;
122
+ await Promise.all(Array.from({ length: Math.min(ids.length, 8) }, async () => {
123
+ while (next < ids.length) {
124
+ const id = ids[next++];
125
+ states.set(id, await inspect(board, id));
126
+ }
127
+ }));
128
+ return rows.map((row) => {
129
+ const binding = bindings.get(row.id);
130
+ return { ...row, ...binding ? { execution: states.get(binding.id) } : {} };
131
+ });
132
+ };
133
+ return {
134
+ queryActivity: (boardId, query = {}) => querySessionItems(core, boardId, query, (rows) => project(boardId, rows)),
135
+ async executionSession(boardId, itemId, query = {}) {
136
+ const started = Date.now();
137
+ if (!query || typeof query !== "object" || Array.isArray(query) || Object.keys(query).some((key) => key !== "includeRelated") || query.includeRelated !== void 0 && typeof query.includeRelated !== "boolean") throw new KanbanError("INVALID_QUERY");
138
+ const { item } = await core.item(boardId, itemId), bindings = executionBindings(item.externalRefs, referenceSystem);
139
+ if (!bindings.length && !query.includeRelated) return { history: [] };
140
+ const [board, workflow] = await Promise.all([boardMetadata(core, boardId), core.workflow(boardId)]), last = currentBinding(item.externalRefs, itemId, workflow, referenceSystem);
141
+ let sessionsCode;
142
+ const related = query.includeRelated ? await options?.source.related?.(board, item, workflow).catch((error) => {
143
+ const candidate = error?.code;
144
+ sessionsCode = candidate && /^[A-Z][A-Z0-9_]{0,79}$/.test(candidate) ? candidate : "SESSION_RELATIONS_FAILED";
145
+ try {
146
+ log({ operationId: randomUUID(), stage: "session.relations", result: "failure", code: sessionsCode, durationMs: Date.now() - started });
147
+ } catch {
148
+ }
149
+ return [];
150
+ }) : [];
151
+ const sessions = query.includeRelated ? await projectRelatedSessions([
152
+ ...sessionAssociations(item, bindings, workflow),
153
+ ...related ?? []
154
+ ], last?.id, (id) => inspect(board, id)) : void 0;
155
+ return {
156
+ current: last ? sessions?.find((row) => row.sessionId === last.id) ?? await inspect(board, last.id) : void 0,
157
+ history: bindings.map((ref) => ({ sessionId: ref.id, bindingId: ref.revision, current: ref === last })).reverse(),
158
+ ...sessions ? { sessions } : {},
159
+ ...sessionsCode ? { sessionsCode } : {}
160
+ };
161
+ },
162
+ validate: (board, command, actor) => validateBinding(core, options, board, command, actor, referenceSystem)
163
+ };
164
+ }
165
+ function createSessionInspector(options, log) {
166
+ const now = options?.now ?? Date.now, cache = /* @__PURE__ */ new Map();
167
+ return async (board, sessionId) => {
168
+ const started = now(), key = JSON.stringify([board.id, sessionId]);
169
+ try {
170
+ if (!options) throw new KanbanError("EXECUTION_SESSION_UNAVAILABLE");
171
+ const row = await options.source.inspect(board, sessionId);
172
+ if (row.sessionId !== sessionId) throw new KanbanError("SESSION_ACTIVITY_SCOPE_MISMATCH");
173
+ const stale = row.stale || row.observedAt === void 0 || now() - row.observedAt > 9e4;
174
+ const value = {
175
+ sessionId,
176
+ ...typeof row.resourceId === "string" && row.resourceId.length <= 4096 && !row.resourceId.includes("\0") ? { resourceId: row.resourceId } : {},
177
+ title: row.title?.slice(0, 256),
178
+ state: row.state,
179
+ createdAt: row.createdAt,
180
+ lastActivityAt: row.lastActivityAt,
181
+ observedAt: row.observedAt,
182
+ stale,
183
+ recent: !stale && row.lastActivityAt !== void 0 && row.lastActivityAt <= now() && now() - row.lastActivityAt <= 6e5,
184
+ ...row.code && /^[A-Z][A-Z0-9_]{0,79}$/.test(row.code) ? { code: row.code } : {}
185
+ };
186
+ if (cache.size >= 256) cache.delete(cache.keys().next().value);
187
+ cache.set(key, value);
188
+ return value;
189
+ } catch (error) {
190
+ const candidate = error?.code, code = candidate && /^[A-Z][A-Z0-9_]{0,79}$/.test(candidate) ? candidate : "SESSION_ACTIVITY_FAILED";
191
+ try {
192
+ log({ operationId: randomUUID(), sessionId, stage: "session.activity", result: "failure", code, durationMs: now() - started });
193
+ } catch {
194
+ }
195
+ const prior = ["EIO", "ETIMEDOUT", "ECONNRESET", "ECONNREFUSED", "SESSION_ACTIVITY_FAILED"].includes(code) ? cache.get(key) : void 0;
196
+ return { ...prior, sessionId, state: prior?.state ?? "unknown", stale: true, recent: false, code };
197
+ }
198
+ };
199
+ }
200
+ async function boardMetadata(core, boardId) {
201
+ const board = (await core.catalog()).find((board2) => board2.id === boardId) ?? await core.read(boardId);
202
+ return { ...board, items: [] };
203
+ }
204
+ async function validateBinding(core, options, board, command, actor, referenceSystem) {
205
+ if (command?.type !== "link-reference" || command.reference.system !== referenceSystem) return;
206
+ if (!options || !command.reference.revision) throw new KanbanError("EXECUTION_SESSION_UNAVAILABLE");
207
+ const item = board.items.find((item2) => item2.id === command.itemId);
208
+ if (!item) throw new KanbanError("ITEM_NOT_FOUND");
209
+ const key = principalKey(principal(actor)), coordinator = board.members?.some((member) => principalKey(member) === key && member.roles?.includes("coordinator"));
210
+ if (!coordinator && item.owner?.principalId !== key && !(item.owner === void 0 && candidates(board, item).some((candidate) => principalKey(candidate) === key))) throw new KanbanError("EXECUTION_SESSION_ASSIGNMENT_DENIED");
211
+ const active = Object.values((await core.workflow(board.id)).dispatches).filter((dispatch) => dispatch.itemId === item.id).sort((a, b) => b.attempt - a.attempt)[0];
212
+ if (active && command.reference.revision !== active.id) throw new KanbanError("EXECUTION_SESSION_LOCKED");
213
+ if (active && executionBindings(item.externalRefs, referenceSystem).some((ref) => ref.revision === active.id && ref.id !== command.reference.id)) throw new KanbanError("EXECUTION_SESSION_LOCKED");
214
+ if (options.source.authorizeBinding) return options.source.authorizeBinding(board, command.reference.id);
215
+ const state = await options.source.inspect(board, command.reference.id);
216
+ if (state.sessionId !== command.reference.id || state.stale) throw new KanbanError("EXECUTION_SESSION_UNAVAILABLE");
217
+ }
218
+
219
+ // src/activity-module.ts
220
+ function createKanbanActivityModule(options) {
221
+ const { executionSessions, referenceSystem, ...core } = options;
222
+ let activity;
223
+ const service = createKanbanModule({
224
+ ...core,
225
+ authorize: async (input) => {
226
+ await core.authorize(input);
227
+ await activity.validate(input.board, input.command, input.actor);
228
+ }
229
+ });
230
+ activity = createKanbanSessionActivity(service, executionSessions, core.log, referenceSystem);
231
+ let stopping = false;
232
+ const pending = /* @__PURE__ */ new Set();
233
+ const track = (run) => {
234
+ if (stopping) return Promise.reject(new KanbanError("SERVICE_STOPPING"));
235
+ const work = Promise.resolve().then(run).finally(() => {
236
+ pending.delete(work);
237
+ });
238
+ pending.add(work);
239
+ return work;
240
+ };
241
+ const quiesce = async () => {
242
+ stopping = true;
243
+ await Promise.allSettled([...pending]);
244
+ await service.quiesce();
245
+ };
246
+ return {
247
+ ...forwardCore(service, track),
248
+ queryActivity: (...args) => track(() => activity.queryActivity(...args)),
249
+ executionSession: (...args) => track(() => activity.executionSession(...args)),
250
+ related: (sessionId) => track(() => relatedBoards(service, referenceSystem, sessionId)),
251
+ quiesce,
252
+ dispose: quiesce
253
+ };
254
+ }
255
+ function forwardCore(service, track) {
256
+ return {
257
+ create: (input) => track(() => service.create(input)),
258
+ read: (id) => track(() => service.read(id)),
259
+ list: () => track(() => service.list()),
260
+ catalog: () => track(() => service.catalog()),
261
+ execute: (id, request) => track(() => service.execute(id, request)),
262
+ events: (id, after, limit) => track(() => service.events(id, after, limit)),
263
+ query: (id, query) => track(() => service.query(id, query)),
264
+ item: (id, item) => track(() => service.item(id, item)),
265
+ overview: (id) => track(() => service.overview(id)),
266
+ scan: () => track(() => service.scan()),
267
+ workflow: (id) => track(() => service.workflow(id)),
268
+ resolve: (reference) => track(() => service.resolve(reference)),
269
+ suggest: (id, query) => track(() => service.suggest(id, query)),
270
+ records: (id, query) => track(() => service.records(id, query)),
271
+ record: (id, record) => track(() => service.record(id, record)),
272
+ currentPrincipal: () => track(() => service.currentPrincipal())
273
+ };
274
+ }
275
+ async function relatedBoards(service, referenceSystem, sessionId) {
276
+ const boards = await service.related(sessionId);
277
+ for (const board of await service.catalog()) {
278
+ if (boards.some((old) => old.id === board.id)) continue;
279
+ const matches = await service.query(board.id, { view: "all", reference: { system: referenceSystem, id: sessionId }, limit: 1 });
280
+ if (matches.total) boards.push(await service.read(board.id));
281
+ }
282
+ return boards;
283
+ }
284
+ export {
285
+ createKanbanActivityModule,
286
+ querySessionItems
287
+ };
288
+ //# sourceMappingURL=activity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/session-activity-query.ts","../src/session-relations.ts","../src/session-activity.ts","../src/activity-module.ts"],"sourcesContent":["import {sha256HexSync} from './utils';\nimport type {KanbanService, KanbanSessionActivityQuery, KanbanSessionItemPage, KanbanSessionItemSummary} from './contracts';\nimport {KanbanError} from './ports';\n/** Filter before pagination; Session activity changes invalidate the filtered keyset. */\nexport async function querySessionItems(core: KanbanService, boardId: string, input: KanbanSessionActivityQuery,\n project: (rows: KanbanSessionItemSummary[])=>Promise<KanbanSessionItemSummary[]>): Promise<KanbanSessionItemPage> {\n const {execution='all',...query}=input;\n if(!['all','running','recent','active'].includes(execution)) throw new KanbanError('INVALID_EXECUTION_FILTER');\n if(execution==='all') {const page=await core.query(boardId,query);return {...page,items:await project(page.items)};}\n const {cursor,limit=50,...filters}=query;\n if(!Number.isSafeInteger(limit)||limit<1||limit>200) throw new KanbanError('INVALID_PAGE_SIZE');\n let page=await core.query(boardId,{...filters,limit:200}), rows=[...page.items];const revision=page.revision;\n while(page.nextCursor) {\n if(rows.length>=10000) throw new KanbanError('ACTIVITY_QUERY_LIMIT');\n page=await core.query(boardId,{...filters,limit:200,cursor:page.nextCursor});\n if(page.revision!==revision) throw new KanbanError('CURSOR_STALE');rows.push(...page.items);\n }\n const matching=(await project(rows)).filter(row=>matchesExecution(row,execution));\n if((await core.query(boardId,{...filters,limit:1})).revision!==revision) throw new KanbanError('CURSOR_STALE');\n const scope=sha256HexSync(JSON.stringify({filters,execution,limit})), signature=sha256HexSync(JSON.stringify(matching.map(row=>row.id)));\n let start=0;\n if(cursor) {\n let saved;try {saved=JSON.parse(cursor);} catch {throw new KanbanError('INVALID_CURSOR');}\n if(saved.scope!==scope) throw new KanbanError('CURSOR_SCOPE_MISMATCH');\n if(saved.revision!==revision||saved.signature!==signature) throw new KanbanError('CURSOR_STALE');\n start=matching.findIndex(row=>row.id===saved.after)+1;if(start<1) throw new KanbanError('INVALID_CURSOR');\n }\n const items=matching.slice(start,start+limit);\n return {revision,total:matching.length,items,...(start+items.length<matching.length?{nextCursor:JSON.stringify({scope,revision,signature,after:items.at(-1)!.id})}: {})};\n}\nfunction matchesExecution(row: KanbanSessionItemSummary, filter: string): boolean {\n const session=row.execution;if(!session||session.stale) return false;\n return filter==='running'?session.state==='running':filter==='recent'?session.recent:session.state==='running'||session.recent;\n}\n","import type {KanbanItem, KanbanExternalReference, KanbanWorkflowState, KanbanSessionAssociation, KanbanRelatedSession, KanbanSessionExecution, KanbanExecutionSession} from './contracts';\n\nexport function sessionAssociations(item: KanbanItem, bindings: KanbanExternalReference[], workflow: KanbanWorkflowState): KanbanSessionAssociation[] {\n return [...bindings.map(ref => {\n const dispatch = workflow.dispatches[ref.revision ?? ''];\n const execution: KanbanSessionExecution | undefined = dispatch?.itemId === item.id ? {\n id: dispatch.id, purpose: 'execution', dispatchId: dispatch.id, attempt: dispatch.attempt,\n outcome: dispatch.outcome, createdAt: dispatch.preparedAt, code: dispatch.code,\n ...(dispatch.continuation ? {previousDispatchId: dispatch.continuation.previousDispatchId} : {}),\n } : undefined;\n return {sessionId: ref.id, purpose: 'execution' as const, ...(execution ? {execution} : {})};\n }), ...item.participants.filter(row => !bindings.some(ref => ref.id === row.sessionId)).map(row => ({sessionId: row.sessionId, purpose: 'discussion' as const}))];\n}\n\n/** Session identity and run identity are independent; neither activity nor a hook selects the primary. */\nexport async function projectRelatedSessions(associations: KanbanSessionAssociation[], currentId: string | undefined,\n inspect: (id: string) => Promise<KanbanExecutionSession>): Promise<KanbanRelatedSession[]> {\n const grouped = new Map<string, {purposes: Set<KanbanSessionAssociation['purpose']>; executions: Map<string, KanbanSessionExecution>}>();\n for (const row of associations) {\n let group = grouped.get(row.sessionId);\n if (!group) grouped.set(row.sessionId, group = {purposes: new Set(), executions: new Map()});\n group.purposes.add(row.purpose);\n if (row.execution) group.executions.set(row.execution.id, {...group.executions.get(row.execution.id), ...row.execution});\n }\n const rows: KanbanRelatedSession[] = [], entries = [...grouped]; let next = 0;\n await Promise.all(Array.from({length: Math.min(entries.length, 8)}, async () => {\n while (next < entries.length) {\n const [sessionId, group] = entries[next++], state = await inspect(sessionId);\n rows.push({...state, current: sessionId === currentId, purposes: [...group.purposes].sort(),\n executions: [...group.executions.values()].sort((a, b) => (a.createdAt ?? 0) - (b.createdAt ?? 0) || a.id.localeCompare(b.id))});\n }\n }));\n return rows.sort((a, b) => Number(b.current) - Number(a.current) || a.sessionId.localeCompare(b.sessionId));\n}\n","import type {KanbanBoard, KanbanCommand, KanbanActor, KanbanService, KanbanExecutionSession, KanbanExternalReference, KanbanSessionItemSummary, KanbanWorkflowState} from './contracts';\nimport type {KanbanSessionSource} from './activity-ports';\nimport {principal,principalKey,candidates} from './identity';\nimport {KanbanError} from './ports';\nimport {querySessionItems} from './session-activity-query';\nimport {randomUUID} from './utils';\nimport {sessionAssociations, projectRelatedSessions} from './session-relations';\nexport interface KanbanSessionActivityOptions {source: KanbanSessionSource; now?:()=>number}\nexport function executionBindings(refs: KanbanExternalReference[] | undefined, referenceSystem: string) {return (refs ?? []).filter(ref=>ref.system===referenceSystem);}\nfunction currentBinding(refs: KanbanExternalReference[]|undefined, itemId:string, workflow:KanbanWorkflowState, referenceSystem: string) {\n const binding=executionBindings(refs, referenceSystem).at(-1),latest=Object.values(workflow.dispatches).filter(dispatch=>dispatch.itemId===itemId).sort((a,b)=>b.attempt-a.attempt)[0];\n if(!binding||!latest||binding.revision===latest.id) return binding;\n return ['prepared','running','unknown','succeeded'].includes(latest.outcome)||workflow.dispatches[binding.revision ?? '']?undefined:binding;\n}\n\n/** Optional resource projection; access checks remain owned by the injected source. */\nexport function createKanbanSessionActivity(core: KanbanService, options: KanbanSessionActivityOptions | undefined, log: (event: {operationId:string;sessionId?:string;stage:string;result:'failure';code:string;durationMs:number})=>void, referenceSystem: string) {\n const inspect=createSessionInspector(options,log);\n const project=async(boardId:string,rows:KanbanSessionItemSummary[])=>{\n if(!rows.some(row=>executionBindings(row.externalRefs,referenceSystem).length))return rows;\n const [board,workflow]=await Promise.all([boardMetadata(core,boardId),core.workflow(boardId)]), bindings=new Map(rows.map(row=>[row.id,currentBinding(row.externalRefs,row.id,workflow,referenceSystem)]));\n const ids=[...new Set([...bindings.values()].flatMap(ref=>ref?[ref.id]:[]))], states=new Map<string,KanbanExecutionSession>();let next=0;\n await Promise.all(Array.from({length:Math.min(ids.length,8)},async()=>{while(next<ids.length) {const id=ids[next++];states.set(id,await inspect(board,id));}}));\n return rows.map(row=>{const binding=bindings.get(row.id);return {...row,...(binding?{execution:states.get(binding.id)}: {})};});\n };\n return {\n queryActivity:(boardId:string,query:import('./contracts').KanbanSessionActivityQuery={})=>querySessionItems(core,boardId,query,rows=>project(boardId,rows)),\n async executionSession(boardId:string,itemId:string, query: import('./contracts').KanbanSessionDetailQuery = {}) {\n const started = Date.now();\n if (!query || typeof query !== 'object' || Array.isArray(query) || Object.keys(query).some(key => key !== 'includeRelated') || query.includeRelated !== undefined && typeof query.includeRelated !== 'boolean') throw new KanbanError('INVALID_QUERY');\n const {item}=await core.item(boardId,itemId),bindings=executionBindings(item.externalRefs,referenceSystem);\n if(!bindings.length && !query.includeRelated)return {history:[]};\n const [board,workflow]=await Promise.all([boardMetadata(core,boardId),core.workflow(boardId)]),last=currentBinding(item.externalRefs,itemId,workflow,referenceSystem);\n let sessionsCode: string | undefined;\n const related = query.includeRelated ? await options?.source.related?.(board, item, workflow).catch(error => {\n const candidate = (error as {code?: string})?.code;\n sessionsCode = candidate && /^[A-Z][A-Z0-9_]{0,79}$/.test(candidate) ? candidate : 'SESSION_RELATIONS_FAILED';\n try {log({operationId: randomUUID(), stage: 'session.relations', result: 'failure', code: sessionsCode, durationMs: Date.now() - started});} catch { /* Diagnostics cannot hide known associations. */ }\n return [];\n }) : [];\n const sessions = query.includeRelated ? await projectRelatedSessions([\n ...sessionAssociations(item, bindings, workflow), ...related ?? [],\n ], last?.id, id => inspect(board, id)) : undefined;\n return {current:last?(sessions?.find(row=>row.sessionId===last.id) ?? await inspect(board,last.id)):undefined,\n history:bindings.map(ref=>({sessionId:ref.id,bindingId:ref.revision,current:ref===last})).reverse(), ...(sessions ? {sessions} : {}), ...(sessionsCode ? {sessionsCode} : {})};\n },\n validate:(board:KanbanBoard,command:KanbanCommand|undefined,actor:KanbanActor)=>validateBinding(core,options,board,command,actor,referenceSystem),\n };\n}\nfunction createSessionInspector(options:KanbanSessionActivityOptions|undefined,log:Parameters<typeof createKanbanSessionActivity>[2]) {\n const now=options?.now ?? Date.now, cache=new Map<string,KanbanExecutionSession>();\n return async(board:KanbanBoard,sessionId:string):Promise<KanbanExecutionSession>=>{\n const started=now(),key=JSON.stringify([board.id,sessionId]);\n try {\n if(!options) throw new KanbanError('EXECUTION_SESSION_UNAVAILABLE');\n const row=await options.source.inspect(board,sessionId);\n if(row.sessionId!==sessionId) throw new KanbanError('SESSION_ACTIVITY_SCOPE_MISMATCH');\n const stale=row.stale||row.observedAt===undefined||now()-row.observedAt>90000;\n const value:KanbanExecutionSession={sessionId,...(typeof row.resourceId==='string'&&row.resourceId.length<=4096&&!row.resourceId.includes('\\0')?{resourceId:row.resourceId}:{}),title:row.title?.slice(0,256),state:row.state,createdAt:row.createdAt,lastActivityAt:row.lastActivityAt,observedAt:row.observedAt,stale,\n recent:!stale&&row.lastActivityAt!==undefined&&row.lastActivityAt<=now()&&now()-row.lastActivityAt<=600000,...(row.code&&/^[A-Z][A-Z0-9_]{0,79}$/.test(row.code)?{code:row.code}:{})};\n if(cache.size>=256) cache.delete(cache.keys().next().value!);cache.set(key,value);return value;\n } catch(error) {\n const candidate=(error as {code?:string})?.code,code=candidate&&/^[A-Z][A-Z0-9_]{0,79}$/.test(candidate)?candidate:'SESSION_ACTIVITY_FAILED';\n try {log({operationId:randomUUID(),sessionId,stage:'session.activity',result:'failure',code,durationMs:now()-started});} catch { /* Observation diagnostics cannot change assignments. */ }\n const prior=['EIO','ETIMEDOUT','ECONNRESET','ECONNREFUSED','SESSION_ACTIVITY_FAILED'].includes(code)?cache.get(key):undefined;\n return {...prior,sessionId,state:prior?.state ?? 'unknown',stale:true,recent:false,code};\n }\n };\n}\nasync function boardMetadata(core: KanbanService, boardId: string): Promise<KanbanBoard> {\n const board=(await core.catalog()).find(board=>board.id===boardId) ?? await core.read(boardId);\n return {...board,items:[]};\n}\nasync function validateBinding(core: KanbanService, options:KanbanSessionActivityOptions|undefined, board:KanbanBoard, command:KanbanCommand|undefined, actor:KanbanActor, referenceSystem: string): Promise<void> {\n if(command?.type!=='link-reference'||command.reference.system!==referenceSystem) return;\n if(!options||!command.reference.revision) throw new KanbanError('EXECUTION_SESSION_UNAVAILABLE');\n const item=board.items.find(item=>item.id===command.itemId);if(!item) throw new KanbanError('ITEM_NOT_FOUND');\n const key=principalKey(principal(actor)), coordinator=board.members?.some(member=>principalKey(member)===key&&member.roles?.includes('coordinator'));\n if(!coordinator&&item.owner?.principalId!==key&&!(item.owner===undefined&&candidates(board,item).some(candidate=>principalKey(candidate)===key))) throw new KanbanError('EXECUTION_SESSION_ASSIGNMENT_DENIED');\n const active=Object.values((await core.workflow(board.id)).dispatches).filter(dispatch=>dispatch.itemId===item.id).sort((a,b)=>b.attempt-a.attempt)[0];\n if(active&&command.reference.revision!==active.id) throw new KanbanError('EXECUTION_SESSION_LOCKED');\n if(active&&executionBindings(item.externalRefs,referenceSystem).some(ref=>ref.revision===active.id&&ref.id!==command.reference.id)) throw new KanbanError('EXECUTION_SESSION_LOCKED');\n if(options.source.authorizeBinding) return options.source.authorizeBinding(board,command.reference.id);\n const state=await options.source.inspect(board,command.reference.id);\n if(state.sessionId!==command.reference.id||state.stale) throw new KanbanError('EXECUTION_SESSION_UNAVAILABLE');\n}\n","import {createKanbanModule as createCore, type KanbanModuleHandle as CoreHandle} from './module';\nimport type {KanbanModuleOptions} from './ports';\nimport {KanbanError} from './ports';\nimport type {KanbanSessionActivityQuery, KanbanSessionItemPage, KanbanExecutionSessionDetail} from './contracts';\nimport {createKanbanSessionActivity, type KanbanSessionActivityOptions} from './session-activity';\nexport interface KanbanActivityModuleOptions extends KanbanModuleOptions {\n executionSessions?: KanbanSessionActivityOptions;\n referenceSystem: string;\n}\nexport interface KanbanActivityHandle extends CoreHandle {\n queryActivity: (boardId: string, query?: KanbanSessionActivityQuery) => Promise<KanbanSessionItemPage>;\n executionSession: (boardId: string, itemId: string, query?: import('./contracts').KanbanSessionDetailQuery) => Promise<KanbanExecutionSessionDetail>;\n}\n\n/** Application integrations stay outside the portable core. */\nexport function createKanbanActivityModule(options: KanbanActivityModuleOptions): KanbanActivityHandle {\n const {executionSessions, referenceSystem, ...core} = options;\n let activity: ReturnType<typeof createKanbanSessionActivity>;\n const service=createCore({...core,\n authorize:async input=>{await core.authorize(input);await activity.validate(input.board,input.command,input.actor);},\n });\n activity=createKanbanSessionActivity(service,executionSessions,core.log,referenceSystem);\n let stopping = false;\n const pending = new Set<Promise<unknown>>();\n const track = <T>(run: () => Promise<T>): Promise<T> => {\n if (stopping) return Promise.reject(new KanbanError('SERVICE_STOPPING'));\n const work = Promise.resolve().then(run).finally(() => {pending.delete(work);});\n pending.add(work); return work;\n };\n const quiesce = async () => {\n stopping = true;\n await Promise.allSettled([...pending]);\n await service.quiesce();\n };\n return {\n ...forwardCore(service, track),\n queryActivity: (...args) => track(() => activity.queryActivity(...args)),\n executionSession: (...args) => track(() => activity.executionSession(...args)),\n related: sessionId => track(() => relatedBoards(service, referenceSystem, sessionId)),\n quiesce, dispose: quiesce,\n };\n}\n\nfunction forwardCore(service: CoreHandle, track: <T>(run: () => Promise<T>) => Promise<T>): Omit<CoreHandle, 'related' | 'quiesce' | 'dispose'> {\n return {\n create: (input) => track(() => service.create(input)),\n read: (id) => track(() => service.read(id)),\n list: () => track(() => service.list()),\n catalog: () => track(() => service.catalog()),\n execute: (id, request) => track(() => service.execute(id, request)),\n events: (id, after, limit) => track(() => service.events(id, after, limit)),\n query: (id, query) => track(() => service.query(id, query)),\n item: (id, item) => track(() => service.item(id, item)),\n overview: (id) => track(() => service.overview(id)),\n scan: () => track(() => service.scan()),\n workflow: (id) => track(() => service.workflow(id)),\n resolve: (reference) => track(() => service.resolve(reference)),\n suggest: (id, query) => track(() => service.suggest(id, query)),\n records: (id, query) => track(() => service.records(id, query)),\n record: (id, record) => track(() => service.record(id, record)),\n currentPrincipal: () => track(() => service.currentPrincipal()),\n };\n}\nasync function relatedBoards(service: CoreHandle, referenceSystem: string, sessionId: string) {\n const boards = await service.related(sessionId);\n for (const board of await service.catalog()) {\n if (boards.some(old => old.id === board.id)) continue;\n const matches = await service.query(board.id, {view: 'all', reference: {system: referenceSystem, id: sessionId}, limit: 1});\n if (matches.total) boards.push(await service.read(board.id));\n }\n return boards;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAIA,eAAsB,kBAAkB,MAAqB,SAAiB,OAC1E,SAAkH;AAClH,QAAM,EAAC,YAAU,OAAM,GAAG,MAAK,IAAE;AACjC,MAAG,CAAC,CAAC,OAAM,WAAU,UAAS,QAAQ,EAAE,SAAS,SAAS,EAAG,OAAM,IAAI,YAAY,0BAA0B;AAC7G,MAAG,cAAY,OAAO;AAAC,UAAMA,QAAK,MAAM,KAAK,MAAM,SAAQ,KAAK;AAAE,WAAO,EAAC,GAAGA,OAAK,OAAM,MAAM,QAAQA,MAAK,KAAK,EAAC;AAAA,EAAE;AACnH,QAAM,EAAC,QAAO,QAAM,IAAG,GAAG,QAAO,IAAE;AACnC,MAAG,CAAC,OAAO,cAAc,KAAK,KAAG,QAAM,KAAG,QAAM,IAAK,OAAM,IAAI,YAAY,mBAAmB;AAC9F,MAAI,OAAK,MAAM,KAAK,MAAM,SAAQ,EAAC,GAAG,SAAQ,OAAM,IAAG,CAAC,GAAG,OAAK,CAAC,GAAG,KAAK,KAAK;AAAE,QAAM,WAAS,KAAK;AACpG,SAAM,KAAK,YAAY;AACnB,QAAG,KAAK,UAAQ,IAAO,OAAM,IAAI,YAAY,sBAAsB;AACnE,WAAK,MAAM,KAAK,MAAM,SAAQ,EAAC,GAAG,SAAQ,OAAM,KAAI,QAAO,KAAK,WAAU,CAAC;AAC3E,QAAG,KAAK,aAAW,SAAU,OAAM,IAAI,YAAY,cAAc;AAAE,SAAK,KAAK,GAAG,KAAK,KAAK;AAAA,EAC9F;AACA,QAAM,YAAU,MAAM,QAAQ,IAAI,GAAG,OAAO,SAAK,iBAAiB,KAAI,SAAS,CAAC;AAChF,OAAI,MAAM,KAAK,MAAM,SAAQ,EAAC,GAAG,SAAQ,OAAM,EAAC,CAAC,GAAG,aAAW,SAAU,OAAM,IAAI,YAAY,cAAc;AAC7G,QAAM,QAAM,cAAc,KAAK,UAAU,EAAC,SAAQ,WAAU,MAAK,CAAC,CAAC,GAAG,YAAU,cAAc,KAAK,UAAU,SAAS,IAAI,SAAK,IAAI,EAAE,CAAC,CAAC;AACvI,MAAI,QAAM;AACV,MAAG,QAAQ;AACP,QAAI;AAAM,QAAI;AAAC,cAAM,KAAK,MAAM,MAAM;AAAA,IAAE,QAAQ;AAAC,YAAM,IAAI,YAAY,gBAAgB;AAAA,IAAE;AACzF,QAAG,MAAM,UAAQ,MAAO,OAAM,IAAI,YAAY,uBAAuB;AACrE,QAAG,MAAM,aAAW,YAAU,MAAM,cAAY,UAAW,OAAM,IAAI,YAAY,cAAc;AAC/F,YAAM,SAAS,UAAU,SAAK,IAAI,OAAK,MAAM,KAAK,IAAE;AAAE,QAAG,QAAM,EAAG,OAAM,IAAI,YAAY,gBAAgB;AAAA,EAC5G;AACA,QAAM,QAAM,SAAS,MAAM,OAAM,QAAM,KAAK;AAC5C,SAAO,EAAC,UAAS,OAAM,SAAS,QAAO,OAAM,GAAI,QAAM,MAAM,SAAO,SAAS,SAAO,EAAC,YAAW,KAAK,UAAU,EAAC,OAAM,UAAS,WAAU,OAAM,MAAM,GAAG,EAAE,EAAG,GAAE,CAAC,EAAC,IAAG,CAAC,EAAE;AAC3K;AACA,SAAS,iBAAiB,KAA+B,QAAyB;AAC9E,QAAM,UAAQ,IAAI;AAAU,MAAG,CAAC,WAAS,QAAQ,MAAO,QAAO;AAC/D,SAAO,WAAS,YAAU,QAAQ,UAAQ,YAAU,WAAS,WAAS,QAAQ,SAAO,QAAQ,UAAQ,aAAW,QAAQ;AAC5H;;;AC/BO,SAAS,oBAAoB,MAAkB,UAAqC,UAA2D;AAClJ,SAAO,CAAC,GAAG,SAAS,IAAI,SAAO;AAC3B,UAAM,WAAW,SAAS,WAAW,IAAI,YAAY,EAAE;AACvD,UAAM,YAAgD,UAAU,WAAW,KAAK,KAAK;AAAA,MACjF,IAAI,SAAS;AAAA,MAAI,SAAS;AAAA,MAAa,YAAY,SAAS;AAAA,MAAI,SAAS,SAAS;AAAA,MAClF,SAAS,SAAS;AAAA,MAAS,WAAW,SAAS;AAAA,MAAY,MAAM,SAAS;AAAA,MAC1E,GAAI,SAAS,eAAe,EAAC,oBAAoB,SAAS,aAAa,mBAAkB,IAAI,CAAC;AAAA,IAClG,IAAI;AACJ,WAAO,EAAC,WAAW,IAAI,IAAI,SAAS,aAAsB,GAAI,YAAY,EAAC,UAAS,IAAI,CAAC,EAAE;AAAA,EAC/F,CAAC,GAAG,GAAG,KAAK,aAAa,OAAO,SAAO,CAAC,SAAS,KAAK,SAAO,IAAI,OAAO,IAAI,SAAS,CAAC,EAAE,IAAI,UAAQ,EAAC,WAAW,IAAI,WAAW,SAAS,aAAqB,EAAE,CAAC;AACpK;AAGA,eAAsB,uBAAuB,cAA0C,WACnF,SAA2F;AAC3F,QAAM,UAAU,oBAAI,IAAmH;AACvI,aAAW,OAAO,cAAc;AAC5B,QAAI,QAAQ,QAAQ,IAAI,IAAI,SAAS;AACrC,QAAI,CAAC,MAAO,SAAQ,IAAI,IAAI,WAAW,QAAQ,EAAC,UAAU,oBAAI,IAAI,GAAG,YAAY,oBAAI,IAAI,EAAC,CAAC;AAC3F,UAAM,SAAS,IAAI,IAAI,OAAO;AAC9B,QAAI,IAAI,UAAW,OAAM,WAAW,IAAI,IAAI,UAAU,IAAI,EAAC,GAAG,MAAM,WAAW,IAAI,IAAI,UAAU,EAAE,GAAG,GAAG,IAAI,UAAS,CAAC;AAAA,EAC3H;AACA,QAAM,OAA+B,CAAC,GAAG,UAAU,CAAC,GAAG,OAAO;AAAG,MAAI,OAAO;AAC5E,QAAM,QAAQ,IAAI,MAAM,KAAK,EAAC,QAAQ,KAAK,IAAI,QAAQ,QAAQ,CAAC,EAAC,GAAG,YAAY;AAC5E,WAAO,OAAO,QAAQ,QAAQ;AAC1B,YAAM,CAAC,WAAW,KAAK,IAAI,QAAQ,MAAM,GAAG,QAAQ,MAAM,QAAQ,SAAS;AAC3E,WAAK,KAAK;AAAA,QAAC,GAAG;AAAA,QAAO,SAAS,cAAc;AAAA,QAAW,UAAU,CAAC,GAAG,MAAM,QAAQ,EAAE,KAAK;AAAA,QACtF,YAAY,CAAC,GAAG,MAAM,WAAW,OAAO,CAAC,EAAE,KAAK,CAAC,GAAG,OAAO,EAAE,aAAa,MAAM,EAAE,aAAa,MAAM,EAAE,GAAG,cAAc,EAAE,EAAE,CAAC;AAAA,MAAC,CAAC;AAAA,IACvI;AAAA,EACJ,CAAC,CAAC;AACF,SAAO,KAAK,KAAK,CAAC,GAAG,MAAM,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,OAAO,KAAK,EAAE,UAAU,cAAc,EAAE,SAAS,CAAC;AAC9G;;;ACzBO,SAAS,kBAAkB,MAA6C,iBAAyB;AAAC,UAAQ,QAAQ,CAAC,GAAG,OAAO,SAAK,IAAI,WAAS,eAAe;AAAE;AACvK,SAAS,eAAe,MAA2C,QAAe,UAA8B,iBAAyB;AACrI,QAAM,UAAQ,kBAAkB,MAAM,eAAe,EAAE,GAAG,EAAE,GAAE,SAAO,OAAO,OAAO,SAAS,UAAU,EAAE,OAAO,cAAU,SAAS,WAAS,MAAM,EAAE,KAAK,CAAC,GAAE,MAAI,EAAE,UAAQ,EAAE,OAAO,EAAE,CAAC;AACrL,MAAG,CAAC,WAAS,CAAC,UAAQ,QAAQ,aAAW,OAAO,GAAI,QAAO;AAC3D,SAAO,CAAC,YAAW,WAAU,WAAU,WAAW,EAAE,SAAS,OAAO,OAAO,KAAG,SAAS,WAAW,QAAQ,YAAY,EAAE,IAAE,SAAU;AACxI;AAGO,SAAS,4BAA4B,MAAqB,SAAmD,KAAwH,iBAAyB;AACjQ,QAAM,UAAQ,uBAAuB,SAAQ,GAAG;AAChD,QAAM,UAAQ,OAAM,SAAe,SAAkC;AACjE,QAAG,CAAC,KAAK,KAAK,SAAK,kBAAkB,IAAI,cAAa,eAAe,EAAE,MAAM,EAAE,QAAO;AACtF,UAAM,CAAC,OAAM,QAAQ,IAAE,MAAM,QAAQ,IAAI,CAAC,cAAc,MAAK,OAAO,GAAE,KAAK,SAAS,OAAO,CAAC,CAAC,GAAG,WAAS,IAAI,IAAI,KAAK,IAAI,SAAK,CAAC,IAAI,IAAG,eAAe,IAAI,cAAa,IAAI,IAAG,UAAS,eAAe,CAAC,CAAC,CAAC;AACzM,UAAM,MAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,SAAS,OAAO,CAAC,EAAE,QAAQ,SAAK,MAAI,CAAC,IAAI,EAAE,IAAE,CAAC,CAAC,CAAC,CAAC,GAAG,SAAO,oBAAI,IAAmC;AAAE,QAAI,OAAK;AACvI,UAAM,QAAQ,IAAI,MAAM,KAAK,EAAC,QAAO,KAAK,IAAI,IAAI,QAAO,CAAC,EAAC,GAAE,YAAS;AAAC,aAAM,OAAK,IAAI,QAAQ;AAAC,cAAM,KAAG,IAAI,MAAM;AAAE,eAAO,IAAI,IAAG,MAAM,QAAQ,OAAM,EAAE,CAAC;AAAA,MAAE;AAAA,IAAC,CAAC,CAAC;AAC9J,WAAO,KAAK,IAAI,SAAK;AAAC,YAAM,UAAQ,SAAS,IAAI,IAAI,EAAE;AAAE,aAAO,EAAC,GAAG,KAAI,GAAI,UAAQ,EAAC,WAAU,OAAO,IAAI,QAAQ,EAAE,EAAC,IAAG,CAAC,EAAE;AAAA,IAAE,CAAC;AAAA,EAClI;AACA,SAAO;AAAA,IACH,eAAc,CAAC,SAAe,QAAuD,CAAC,MAAI,kBAAkB,MAAK,SAAQ,OAAM,UAAM,QAAQ,SAAQ,IAAI,CAAC;AAAA,IAC1J,MAAM,iBAAiB,SAAe,QAAe,QAAwD,CAAC,GAAG;AAC7G,YAAM,UAAU,KAAK,IAAI;AACzB,UAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,KAAK,OAAO,KAAK,KAAK,EAAE,KAAK,SAAO,QAAQ,gBAAgB,KAAK,MAAM,mBAAmB,UAAa,OAAO,MAAM,mBAAmB,UAAW,OAAM,IAAI,YAAY,eAAe;AACrP,YAAM,EAAC,KAAI,IAAE,MAAM,KAAK,KAAK,SAAQ,MAAM,GAAE,WAAS,kBAAkB,KAAK,cAAa,eAAe;AACzG,UAAG,CAAC,SAAS,UAAU,CAAC,MAAM,eAAe,QAAO,EAAC,SAAQ,CAAC,EAAC;AAC/D,YAAM,CAAC,OAAM,QAAQ,IAAE,MAAM,QAAQ,IAAI,CAAC,cAAc,MAAK,OAAO,GAAE,KAAK,SAAS,OAAO,CAAC,CAAC,GAAE,OAAK,eAAe,KAAK,cAAa,QAAO,UAAS,eAAe;AACpK,UAAI;AACJ,YAAM,UAAU,MAAM,iBAAiB,MAAM,SAAS,OAAO,UAAU,OAAO,MAAM,QAAQ,EAAE,MAAM,WAAS;AACzG,cAAM,YAAa,OAA2B;AAC9C,uBAAe,aAAa,yBAAyB,KAAK,SAAS,IAAI,YAAY;AACnF,YAAI;AAAC,cAAI,EAAC,aAAa,WAAW,GAAG,OAAO,qBAAqB,QAAQ,WAAW,MAAM,cAAc,YAAY,KAAK,IAAI,IAAI,QAAO,CAAC;AAAA,QAAE,QAAQ;AAAA,QAAoD;AACvM,eAAO,CAAC;AAAA,MACZ,CAAC,IAAI,CAAC;AACN,YAAM,WAAW,MAAM,iBAAiB,MAAM,uBAAuB;AAAA,QACjE,GAAG,oBAAoB,MAAM,UAAU,QAAQ;AAAA,QAAG,GAAG,WAAW,CAAC;AAAA,MACrE,GAAG,MAAM,IAAI,QAAM,QAAQ,OAAO,EAAE,CAAC,IAAI;AACzC,aAAO;AAAA,QAAC,SAAQ,OAAM,UAAU,KAAK,SAAK,IAAI,cAAY,KAAK,EAAE,KAAK,MAAM,QAAQ,OAAM,KAAK,EAAE,IAAG;AAAA,QAChG,SAAQ,SAAS,IAAI,UAAM,EAAC,WAAU,IAAI,IAAG,WAAU,IAAI,UAAS,SAAQ,QAAM,KAAI,EAAE,EAAE,QAAQ;AAAA,QAAG,GAAI,WAAW,EAAC,SAAQ,IAAI,CAAC;AAAA,QAAI,GAAI,eAAe,EAAC,aAAY,IAAI,CAAC;AAAA,MAAE;AAAA,IACrL;AAAA,IACA,UAAS,CAAC,OAAkB,SAAgC,UAAoB,gBAAgB,MAAK,SAAQ,OAAM,SAAQ,OAAM,eAAe;AAAA,EACpJ;AACJ;AACA,SAAS,uBAAuB,SAA+C,KAAuD;AAClI,QAAM,MAAI,SAAS,OAAO,KAAK,KAAK,QAAM,oBAAI,IAAmC;AACjF,SAAO,OAAM,OAAkB,cAAmD;AAC9E,UAAM,UAAQ,IAAI,GAAE,MAAI,KAAK,UAAU,CAAC,MAAM,IAAG,SAAS,CAAC;AAC3D,QAAI;AACA,UAAG,CAAC,QAAS,OAAM,IAAI,YAAY,+BAA+B;AAClE,YAAM,MAAI,MAAM,QAAQ,OAAO,QAAQ,OAAM,SAAS;AACtD,UAAG,IAAI,cAAY,UAAW,OAAM,IAAI,YAAY,iCAAiC;AACrF,YAAM,QAAM,IAAI,SAAO,IAAI,eAAa,UAAW,IAAI,IAAE,IAAI,aAAW;AACxE,YAAM,QAA6B;AAAA,QAAC;AAAA,QAAU,GAAI,OAAO,IAAI,eAAa,YAAU,IAAI,WAAW,UAAQ,QAAM,CAAC,IAAI,WAAW,SAAS,IAAI,IAAE,EAAC,YAAW,IAAI,WAAU,IAAE,CAAC;AAAA,QAAG,OAAM,IAAI,OAAO,MAAM,GAAE,GAAG;AAAA,QAAE,OAAM,IAAI;AAAA,QAAM,WAAU,IAAI;AAAA,QAAU,gBAAe,IAAI;AAAA,QAAe,YAAW,IAAI;AAAA,QAAW;AAAA,QAC9S,QAAO,CAAC,SAAO,IAAI,mBAAiB,UAAW,IAAI,kBAAgB,IAAI,KAAG,IAAI,IAAE,IAAI,kBAAgB;AAAA,QAAO,GAAI,IAAI,QAAM,yBAAyB,KAAK,IAAI,IAAI,IAAE,EAAC,MAAK,IAAI,KAAI,IAAE,CAAC;AAAA,MAAE;AACxL,UAAG,MAAM,QAAM,IAAK,OAAM,OAAO,MAAM,KAAK,EAAE,KAAK,EAAE,KAAM;AAAE,YAAM,IAAI,KAAI,KAAK;AAAE,aAAO;AAAA,IAC7F,SAAQ,OAAO;AACX,YAAM,YAAW,OAA0B,MAAK,OAAK,aAAW,yBAAyB,KAAK,SAAS,IAAE,YAAU;AACnH,UAAI;AAAC,YAAI,EAAC,aAAY,WAAW,GAAE,WAAU,OAAM,oBAAmB,QAAO,WAAU,MAAK,YAAW,IAAI,IAAE,QAAO,CAAC;AAAA,MAAE,QAAQ;AAAA,MAA2D;AAC1L,YAAM,QAAM,CAAC,OAAM,aAAY,cAAa,gBAAe,yBAAyB,EAAE,SAAS,IAAI,IAAE,MAAM,IAAI,GAAG,IAAE;AACpH,aAAO,EAAC,GAAG,OAAM,WAAU,OAAM,OAAO,SAAS,WAAU,OAAM,MAAK,QAAO,OAAM,KAAI;AAAA,IAC3F;AAAA,EACJ;AACJ;AACA,eAAe,cAAc,MAAqB,SAAuC;AACrF,QAAM,SAAO,MAAM,KAAK,QAAQ,GAAG,KAAK,CAAAC,WAAOA,OAAM,OAAK,OAAO,KAAK,MAAM,KAAK,KAAK,OAAO;AAC7F,SAAO,EAAC,GAAG,OAAM,OAAM,CAAC,EAAC;AAC7B;AACA,eAAe,gBAAgB,MAAqB,SAAgD,OAAmB,SAAiC,OAAmB,iBAAwC;AAC/M,MAAG,SAAS,SAAO,oBAAkB,QAAQ,UAAU,WAAS,gBAAiB;AACjF,MAAG,CAAC,WAAS,CAAC,QAAQ,UAAU,SAAU,OAAM,IAAI,YAAY,+BAA+B;AAC/F,QAAM,OAAK,MAAM,MAAM,KAAK,CAAAC,UAAMA,MAAK,OAAK,QAAQ,MAAM;AAAE,MAAG,CAAC,KAAM,OAAM,IAAI,YAAY,gBAAgB;AAC5G,QAAM,MAAI,aAAa,UAAU,KAAK,CAAC,GAAG,cAAY,MAAM,SAAS,KAAK,YAAQ,aAAa,MAAM,MAAI,OAAK,OAAO,OAAO,SAAS,aAAa,CAAC;AACnJ,MAAG,CAAC,eAAa,KAAK,OAAO,gBAAc,OAAK,EAAE,KAAK,UAAQ,UAAW,WAAW,OAAM,IAAI,EAAE,KAAK,eAAW,aAAa,SAAS,MAAI,GAAG,GAAI,OAAM,IAAI,YAAY,qCAAqC;AAC7M,QAAM,SAAO,OAAO,QAAQ,MAAM,KAAK,SAAS,MAAM,EAAE,GAAG,UAAU,EAAE,OAAO,cAAU,SAAS,WAAS,KAAK,EAAE,EAAE,KAAK,CAAC,GAAE,MAAI,EAAE,UAAQ,EAAE,OAAO,EAAE,CAAC;AACrJ,MAAG,UAAQ,QAAQ,UAAU,aAAW,OAAO,GAAI,OAAM,IAAI,YAAY,0BAA0B;AACnG,MAAG,UAAQ,kBAAkB,KAAK,cAAa,eAAe,EAAE,KAAK,SAAK,IAAI,aAAW,OAAO,MAAI,IAAI,OAAK,QAAQ,UAAU,EAAE,EAAG,OAAM,IAAI,YAAY,0BAA0B;AACpL,MAAG,QAAQ,OAAO,iBAAkB,QAAO,QAAQ,OAAO,iBAAiB,OAAM,QAAQ,UAAU,EAAE;AACrG,QAAM,QAAM,MAAM,QAAQ,OAAO,QAAQ,OAAM,QAAQ,UAAU,EAAE;AACnE,MAAG,MAAM,cAAY,QAAQ,UAAU,MAAI,MAAM,MAAO,OAAM,IAAI,YAAY,+BAA+B;AACjH;;;ACtEO,SAAS,2BAA2B,SAA4D;AACnG,QAAM,EAAC,mBAAmB,iBAAiB,GAAG,KAAI,IAAI;AACtD,MAAI;AACJ,QAAM,UAAQ,mBAAW;AAAA,IAAC,GAAG;AAAA,IACzB,WAAU,OAAM,UAAO;AAAC,YAAM,KAAK,UAAU,KAAK;AAAE,YAAM,SAAS,SAAS,MAAM,OAAM,MAAM,SAAQ,MAAM,KAAK;AAAA,IAAE;AAAA,EACvH,CAAC;AACD,aAAS,4BAA4B,SAAQ,mBAAkB,KAAK,KAAI,eAAe;AACvF,MAAI,WAAW;AACf,QAAM,UAAU,oBAAI,IAAsB;AAC1C,QAAM,QAAQ,CAAI,QAAsC;AACpD,QAAI,SAAU,QAAO,QAAQ,OAAO,IAAI,YAAY,kBAAkB,CAAC;AACvE,UAAM,OAAO,QAAQ,QAAQ,EAAE,KAAK,GAAG,EAAE,QAAQ,MAAM;AAAC,cAAQ,OAAO,IAAI;AAAA,IAAE,CAAC;AAC9E,YAAQ,IAAI,IAAI;AAAG,WAAO;AAAA,EAC9B;AACA,QAAM,UAAU,YAAY;AACxB,eAAW;AACX,UAAM,QAAQ,WAAW,CAAC,GAAG,OAAO,CAAC;AACrC,UAAM,QAAQ,QAAQ;AAAA,EAC1B;AACA,SAAO;AAAA,IACH,GAAG,YAAY,SAAS,KAAK;AAAA,IAC7B,eAAe,IAAI,SAAS,MAAM,MAAM,SAAS,cAAc,GAAG,IAAI,CAAC;AAAA,IACvE,kBAAkB,IAAI,SAAS,MAAM,MAAM,SAAS,iBAAiB,GAAG,IAAI,CAAC;AAAA,IAC7E,SAAS,eAAa,MAAM,MAAM,cAAc,SAAS,iBAAiB,SAAS,CAAC;AAAA,IACpF;AAAA,IAAS,SAAS;AAAA,EACtB;AACJ;AAEA,SAAS,YAAY,SAAqB,OAAsG;AAC5I,SAAO;AAAA,IACH,QAAQ,CAAC,UAAU,MAAM,MAAM,QAAQ,OAAO,KAAK,CAAC;AAAA,IACpD,MAAM,CAAC,OAAO,MAAM,MAAM,QAAQ,KAAK,EAAE,CAAC;AAAA,IAC1C,MAAM,MAAM,MAAM,MAAM,QAAQ,KAAK,CAAC;AAAA,IACtC,SAAS,MAAM,MAAM,MAAM,QAAQ,QAAQ,CAAC;AAAA,IAC5C,SAAS,CAAC,IAAI,YAAY,MAAM,MAAM,QAAQ,QAAQ,IAAI,OAAO,CAAC;AAAA,IAClE,QAAQ,CAAC,IAAI,OAAO,UAAU,MAAM,MAAM,QAAQ,OAAO,IAAI,OAAO,KAAK,CAAC;AAAA,IAC1E,OAAO,CAAC,IAAI,UAAU,MAAM,MAAM,QAAQ,MAAM,IAAI,KAAK,CAAC;AAAA,IAC1D,MAAM,CAAC,IAAI,SAAS,MAAM,MAAM,QAAQ,KAAK,IAAI,IAAI,CAAC;AAAA,IACtD,UAAU,CAAC,OAAO,MAAM,MAAM,QAAQ,SAAS,EAAE,CAAC;AAAA,IAClD,MAAM,MAAM,MAAM,MAAM,QAAQ,KAAK,CAAC;AAAA,IACtC,UAAU,CAAC,OAAO,MAAM,MAAM,QAAQ,SAAS,EAAE,CAAC;AAAA,IAClD,SAAS,CAAC,cAAc,MAAM,MAAM,QAAQ,QAAQ,SAAS,CAAC;AAAA,IAC9D,SAAS,CAAC,IAAI,UAAU,MAAM,MAAM,QAAQ,QAAQ,IAAI,KAAK,CAAC;AAAA,IAC9D,SAAS,CAAC,IAAI,UAAU,MAAM,MAAM,QAAQ,QAAQ,IAAI,KAAK,CAAC;AAAA,IAC9D,QAAQ,CAAC,IAAI,WAAW,MAAM,MAAM,QAAQ,OAAO,IAAI,MAAM,CAAC;AAAA,IAC9D,kBAAkB,MAAM,MAAM,MAAM,QAAQ,iBAAiB,CAAC;AAAA,EAClE;AACJ;AACA,eAAe,cAAc,SAAqB,iBAAyB,WAAmB;AAC1F,QAAM,SAAS,MAAM,QAAQ,QAAQ,SAAS;AAC9C,aAAW,SAAS,MAAM,QAAQ,QAAQ,GAAG;AACzC,QAAI,OAAO,KAAK,SAAO,IAAI,OAAO,MAAM,EAAE,EAAG;AAC7C,UAAM,UAAU,MAAM,QAAQ,MAAM,MAAM,IAAI,EAAC,MAAM,OAAO,WAAW,EAAC,QAAQ,iBAAiB,IAAI,UAAS,GAAG,OAAO,EAAC,CAAC;AAC1H,QAAI,QAAQ,MAAO,QAAO,KAAK,MAAM,QAAQ,KAAK,MAAM,EAAE,CAAC;AAAA,EAC/D;AACA,SAAO;AACX;","names":["page","board","item"]}
@@ -0,0 +1,16 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/ports.ts
2
+ var KanbanError = class extends Error {
3
+ constructor(code) {
4
+ super(code);
5
+ this.code = code;
6
+ this.name = "KanbanError";
7
+ }
8
+ };
9
+ var KanbanScanNotStartedError = class extends KanbanError {
10
+ };
11
+
12
+
13
+
14
+
15
+ exports.KanbanError = KanbanError; exports.KanbanScanNotStartedError = KanbanScanNotStartedError;
16
+ //# sourceMappingURL=chunk-2YFPV5GF.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/home/li/share/prj/x1/release/local-libraries/work/1ca933a0-6fe7-4e9c-b13b-76d7f318e0fb/source/libraries/kanban/dist/chunk-2YFPV5GF.cjs","../src/ports.ts"],"names":[],"mappings":"AAAA;AC8CO,IAAM,YAAA,EAAN,MAAA,QAA0B,MAAM;AAAA,EACnC,WAAA,CAAqB,IAAA,EAAc;AAAE,IAAA,KAAA,CAAM,IAAI,CAAA;AAA1B,IAAA,IAAA,CAAA,KAAA,EAAA,IAAA;AAA6B,IAAA,IAAA,CAAK,KAAA,EAAO,aAAA;AAAA,EAAe;AACjF,CAAA;AAEO,IAAM,0BAAA,EAAN,MAAA,QAAwC,YAAY;AAAC,CAAA;ADxC5D;AACA;AACE;AACA;AACF,iGAAC","file":"/home/li/share/prj/x1/release/local-libraries/work/1ca933a0-6fe7-4e9c-b13b-76d7f318e0fb/source/libraries/kanban/dist/chunk-2YFPV5GF.cjs","sourcesContent":[null,"import type { KanbanActor, KanbanBoard, KanbanCommand, KanbanEvent, KanbanArchivedItem, KanbanItemSummary } from './contracts';\n\nexport interface KanbanState {\n workflow?: import('./contracts').KanbanWorkflowState;\n numbering?: {item: number; log: number; decision: number};\n presetVersions?: Record<string, number>;\n records?: import('./contracts').KanbanProjectRecord[];\n discovery?: import('./scan-ports').KanbanDiscoveryState;\n archiveIndex?: KanbanItemSummary[];\n archiveWrites?: Array<{id: string; value: KanbanArchivedItem | null}>;\n restore?: KanbanArchivedItem;\n schema: 1; board: KanbanBoard; sequence: number; events: KanbanEvent[]; escalations: string[];\n}\nexport interface KanbanReadView {\n /** Board metadata and summary indexes; no item/record bodies. */\n state: KanbanState;\n items: import('./contracts').KanbanItemSummary[];\n records: import('./contracts').KanbanRecordSummary[];\n}\nexport interface KanbanStore {\n boardId?(number: number): Promise<string | null>;\n view?(id: string): Promise<KanbanReadView | null>;\n ids(): Promise<string[]>;\n archived(boardId: string, itemId: string): Promise<KanbanArchivedItem | null>;\n events(id: string, after: number, limit: number, through: number): Promise<KanbanEvent[]>;\n read(id: string): Promise<KanbanState | null>;\n update(id: string, operationId: string, fingerprint: string,\n change: (state: KanbanState | null) => KanbanState): Promise<KanbanState>;\n}\nexport interface KanbanModuleOptions {\n /** Host supplies metadata within the authorized user's/project's session scope. */\n suggestions?(board: KanbanBoard, kind: import('./contracts').KanbanSuggestionKind, search: string, limit: number): Promise<import('./contracts').KanbanSuggestion[] | undefined>;\n verifyOutputs?(input: {stage?: 'observe' | 'accept'; board: KanbanBoard; itemId: string; dispatchId?: string; outputs: import('./contracts').KanbanArtifactRef[]}): Promise<boolean>;\n onCommitted?(boardId: string, service: import('./contracts').KanbanService, now: number): Promise<void>;\n store: KanbanStore;\n /** Trusted identity resolved by the host, never from command payloads. */\n actor: KanbanActor;\n /** Must validate project access, delegated authority and session registration. */\n authorize(input: { actor: KanbanActor; board: KanbanBoard; action: 'create' | 'read' | 'install-content' | KanbanCommand['type']; command?: KanbanCommand }): Promise<void>;\n /** Confirm an automated owner has settled before releasing responsibility. */\n verifyDeletion?(board: KanbanBoard): Promise<void>;\n verifyRelease?(input: {actor: KanbanActor; board: KanbanBoard; item: import('./contracts').KanbanItem}): Promise<boolean>;\n now?: () => number;\n id?: () => string;\n log(event: { operationId: string; boardId?: string; sessionId?: string; stage: string; result: 'success' | 'failure'; code?: string; durationMs: number }): void;\n}\nexport class KanbanError extends Error {\n constructor(readonly code: string) { super(code); this.name = 'KanbanError'; }\n}\n\nexport class KanbanScanNotStartedError extends KanbanError {}\n"]}
@@ -0,0 +1,221 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
+
3
+ var _chunk2YFPV5GFcjs = require('./chunk-2YFPV5GF.cjs');
4
+
5
+
6
+
7
+ var _chunkPSKQAFDFcjs = require('./chunk-PSKQAFDF.cjs');
8
+
9
+ // src/discovery-state.ts
10
+ function discoveryState(state) {
11
+ return _optionalChain([state, 'optionalAccess', _ => _.discovery]);
12
+ }
13
+
14
+ // src/configuration.ts
15
+ function policy(input = {}) {
16
+ return {
17
+ claimTimeoutMs: 864e5,
18
+ leaseMs: 6e5,
19
+ progressTimeoutMs: 36e5,
20
+ transferTimeoutMs: 18e5,
21
+ maxComplexity: 10,
22
+ maxWorkUnits: 100,
23
+ maxDurationMs: 288e5,
24
+ escalationSessionIds: [],
25
+ ...input
26
+ };
27
+ }
28
+ function workTypes(board) {
29
+ return _nullishCoalesce(board.workTypes, () => ( _chunkPSKQAFDFcjs.DEFAULT_KANBAN_WORK_TYPES));
30
+ }
31
+ function workType(board, id) {
32
+ const found = workTypes(board).find((type) => type.id === id);
33
+ requireValue(found, "UNKNOWN_WORK_TYPE");
34
+ return found;
35
+ }
36
+ function executable(board, item) {
37
+ workType(board, _nullishCoalesce(_nullishCoalesce(_optionalChain([item, 'access', _2 => _2.planning, 'optionalAccess', _3 => _3.kind]), () => ( board.defaultWorkType)), () => ( "task")));
38
+ return _chunkPSKQAFDFcjs.executableWorkItem.call(void 0, board, item);
39
+ }
40
+ function validateConfiguration(board) {
41
+ const types = workTypes(board);
42
+ requireValue(types.length > 0 && types.length <= 20, "WORK_TYPE_LIMIT");
43
+ requireValue(new Set(types.map((t) => t.id)).size === types.length, "DUPLICATE_WORK_TYPE");
44
+ for (const type of types) {
45
+ identity(type.id);
46
+ text(type.label);
47
+ requireValue(Number.isInteger(type.rank) && type.rank >= 0 && type.rank <= 9 && typeof type.executable === "boolean", "INVALID_WORK_TYPE");
48
+ }
49
+ workType(board, _nullishCoalesce(board.defaultWorkType, () => ( "task")));
50
+ const members = roster(board);
51
+ requireValue(members.length > 0, "MEMBER_ROSTER_REQUIRED");
52
+ requireValue(new Set(members.map(principalKey)).size === members.length, "DUPLICATE_MEMBER");
53
+ for (const member of members) {
54
+ identity(member.id);
55
+ requireValue(["agent", "human", "service"].includes(member.kind), "INVALID_PRINCIPAL");
56
+ }
57
+ for (const member of _nullishCoalesce(board.members, () => ( []))) {
58
+ text(member.responsibility);
59
+ requireValue(!member.roles || member.roles.every((r) => ["worker", "reviewer", "coordinator"].includes(r)), "INVALID_MEMBER_ROLE");
60
+ }
61
+ validateColumns(board);
62
+ for (const [kind, value] of Object.entries(_nullishCoalesce(_optionalChain([board, 'access', _4 => _4.notifications, 'optionalAccess', _5 => _5.rules]), () => ( {}))))
63
+ requireValue(/^[a-z][a-z0-9.-]{0,79}$/.test(kind) && ["info", "error", "none"].includes(value), "INVALID_NOTIFICATION_RULE");
64
+ }
65
+ function validateColumns(board) {
66
+ if (!board.columns) return;
67
+ const states = board.columns.flatMap((c) => c.states);
68
+ requireValue(states.length === 7 && new Set(states).size === 7 && ["proposed", "backlog", "open", "claimed", "review", "completed", "cancelled"].every((s) => states.includes(s)), "INVALID_COLUMNS");
69
+ requireValue(new Set(board.columns.map((c) => c.id)).size === board.columns.length, "DUPLICATE_COLUMN");
70
+ for (const column of board.columns) {
71
+ identity(column.id);
72
+ text(column.label);
73
+ requireValue(column.states.length > 0, "EMPTY_COLUMN");
74
+ }
75
+ }
76
+
77
+ // src/rules.ts
78
+ function requireValue(condition, code) {
79
+ if (!condition) throw new (0, _chunk2YFPV5GFcjs.KanbanError)(code);
80
+ }
81
+ function text(value) {
82
+ requireValue(typeof value === "string" && value.trim().length > 0 && value.length <= 8e3, "INVALID_TEXT");
83
+ }
84
+ function identity(value) {
85
+ requireValue(typeof value === "string" && value.length > 0 && value.length <= 256 && !["__proto__", "prototype", "constructor"].includes(value), "INVALID_ID");
86
+ }
87
+ function positive(value) {
88
+ requireValue(Number.isFinite(value) && value > 0, "INVALID_THRESHOLD");
89
+ }
90
+ function validateEstimate(estimate) {
91
+ positive(estimate.complexity);
92
+ positive(estimate.workUnits);
93
+ positive(estimate.durationMs);
94
+ requireValue(["low", "medium", "high"].includes(estimate.confidence), "INVALID_CONFIDENCE");
95
+ }
96
+ function validateBoard(board) {
97
+ identity(board.id);
98
+ text(board.title);
99
+ requireValue(["system", "project", "collection"].includes(board.scope.kind), "INVALID_SCOPE");
100
+ if (board.scope.kind === "project") identity(board.scope.projectId);
101
+ if (board.scope.kind === "collection") {
102
+ identity(board.scope.namespace);
103
+ identity(board.scope.id);
104
+ }
105
+ validateConfiguration(board);
106
+ for (const agent of _nullishCoalesce(board.agents, () => ( []))) {
107
+ identity(agent.agentId);
108
+ text(agent.responsibility);
109
+ }
110
+ requireValue(new Set((_nullishCoalesce(board.agents, () => ( []))).map((a) => a.agentId)).size === (_nullishCoalesce(board.agents, () => ( []))).length, "DUPLICATE_AGENT");
111
+ const p = board.policy;
112
+ for (const value of [p.maxReady, p.maxInProgress, p.maxInProgressPerAgent, p.maxInProgressPerAssignee]) if (value !== void 0) requireValue(Number.isSafeInteger(value) && value > 0, "INVALID_LIMIT");
113
+ requireValue(p.maxInProgressPerAgent === void 0 || p.maxInProgressPerAssignee === void 0 || p.maxInProgressPerAgent === p.maxInProgressPerAssignee, "POLICY_LIMIT_CONFLICT");
114
+ for (const value of [p.archiveAfterMs, p.backlogReviewMs]) if (value !== void 0) positive(value);
115
+ for (const value of [
116
+ p.claimTimeoutMs,
117
+ p.leaseMs,
118
+ p.progressTimeoutMs,
119
+ p.transferTimeoutMs,
120
+ p.maxComplexity,
121
+ p.maxWorkUnits,
122
+ p.maxDurationMs
123
+ ]) positive(value);
124
+ requireValue(Array.isArray(p.escalationSessionIds), "INVALID_ESCALATION_TARGETS");
125
+ requireValue(p.review === void 0 || ["independent", "assignee"].includes(p.review), "INVALID_REVIEW_POLICY");
126
+ requireValue(p.requireEstimate === void 0 || typeof p.requireEstimate === "boolean", "INVALID_ESTIMATE_POLICY");
127
+ p.escalationSessionIds.forEach(identity);
128
+ }
129
+ function participant(list, sessionId, agentId, role, subscribed, now) {
130
+ identity(sessionId);
131
+ requireValue(["creator", "owner", "consultant", "reviewer", "observer", "escalation"].includes(role), "INVALID_ROLE");
132
+ let entry = list.find((value) => value.sessionId === sessionId);
133
+ if (!entry) {
134
+ entry = { sessionId, agentId, roles: [], subscribed, joinedAt: now };
135
+ list.push(entry);
136
+ }
137
+ if (entry.agentId && agentId) requireValue(entry.agentId === agentId, "SESSION_AGENT_CONFLICT");
138
+ entry.agentId ??= agentId;
139
+ if (!entry.roles.includes(role)) entry.roles.push(role);
140
+ entry.subscribed = subscribed;
141
+ }
142
+ function owned(item, actor, token, now) {
143
+ requireValue(item.status === "claimed", "ITEM_NOT_RUNNING");
144
+ requireValue(item.owner && sameOwner(item.owner, actor) && item.owner.token === token, "OWNER_MISMATCH");
145
+ requireValue(item.owner.leaseUntil > now, "LEASE_EXPIRED");
146
+ }
147
+
148
+ // src/identity.ts
149
+ function principal(actor) {
150
+ const kind = _nullishCoalesce(actor.kind, () => ( "agent")), id = kind === "agent" ? _nullishCoalesce(actor.agentId, () => ( actor.id)) : actor.id;
151
+ requireValue(["agent", "human", "service"].includes(kind) && id, "INVALID_ACTOR");
152
+ identity(id);
153
+ if (kind === "agent") {
154
+ requireValue(!actor.agentId || !actor.id || actor.agentId === actor.id, "ACTOR_ID_MISMATCH");
155
+ if (actor.sessionId !== void 0) identity(actor.sessionId);
156
+ if (actor.taskId !== void 0) identity(actor.taskId);
157
+ }
158
+ return { kind, id };
159
+ }
160
+ function principalKey(value) {
161
+ return JSON.stringify([value.kind, value.id]);
162
+ }
163
+ function assigneeKey(value) {
164
+ return _nullishCoalesce(value.principalId, () => ( principalKey({ kind: "agent", id: value.agentId })));
165
+ }
166
+ function sameOwner(owner, actor) {
167
+ const value = principal(actor);
168
+ return assigneeKey(owner) === principalKey(value) && (value.kind !== "agent" || owner.sessionId === actor.sessionId && owner.taskId === actor.taskId);
169
+ }
170
+ function roster(board) {
171
+ return [...(_nullishCoalesce(board.agents, () => ( []))).map((a) => ({ kind: "agent", id: a.agentId })), ..._nullishCoalesce(board.members, () => ( []))];
172
+ }
173
+ function candidates(board, item) {
174
+ if (item.eligibleAgentIds === void 0 && item.eligiblePrincipals === void 0)
175
+ return [
176
+ ...(_nullishCoalesce(board.agents, () => ( []))).map((a) => ({ kind: "agent", id: a.agentId })),
177
+ ...(_nullishCoalesce(board.members, () => ( []))).filter((m) => !m.roles || m.roles.includes("worker"))
178
+ ];
179
+ return [...(_nullishCoalesce(item.eligibleAgentIds, () => ( []))).map((id) => ({ kind: "agent", id })), ..._nullishCoalesce(item.eligiblePrincipals, () => ( []))];
180
+ }
181
+ function eligible(board, item, actor) {
182
+ const key = principalKey(principal(actor));
183
+ requireValue(candidates(board, item).some((p) => principalKey(p) === key), actor.kind && actor.kind !== "agent" ? "ASSIGNEE_NOT_ELIGIBLE" : "AGENT_NOT_ELIGIBLE");
184
+ }
185
+ function validateCandidates(board, item, executable2) {
186
+ const allowed = new Set(roster(board).map(principalKey)), values = candidates(board, item);
187
+ requireValue(!executable2 || values.length > 0, "ELIGIBLE_ASSIGNEES_REQUIRED");
188
+ for (const value of values) {
189
+ identity(value.id);
190
+ requireValue(["agent", "human", "service"].includes(value.kind), "INVALID_PRINCIPAL");
191
+ requireValue(allowed.has(principalKey(value)), value.kind === "agent" ? "AGENT_NOT_REGISTERED" : "ASSIGNEE_NOT_REGISTERED");
192
+ }
193
+ }
194
+ function normalizeActor(actor) {
195
+ const value = principal(actor);
196
+ return value.kind === "agent" ? { agentId: value.id, sessionId: actor.sessionId, taskId: actor.taskId } : { kind: value.kind, id: value.id };
197
+ }
198
+
199
+
200
+
201
+
202
+
203
+
204
+
205
+
206
+
207
+
208
+
209
+
210
+
211
+
212
+
213
+
214
+
215
+
216
+
217
+
218
+
219
+
220
+ exports.principal = principal; exports.principalKey = principalKey; exports.assigneeKey = assigneeKey; exports.sameOwner = sameOwner; exports.candidates = candidates; exports.eligible = eligible; exports.validateCandidates = validateCandidates; exports.normalizeActor = normalizeActor; exports.policy = policy; exports.workType = workType; exports.executable = executable; exports.requireValue = requireValue; exports.text = text; exports.identity = identity; exports.positive = positive; exports.validateEstimate = validateEstimate; exports.validateBoard = validateBoard; exports.participant = participant; exports.owned = owned; exports.discoveryState = discoveryState;
221
+ //# sourceMappingURL=chunk-4KF7KUAI.cjs.map