@nestos/kanban 0.5.1 → 0.5.2
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/LICENSE +674 -0
- package/README.md +73 -29
- package/dist/{activity-C6xDM-cg.d.cts → activity-BbC4sgKL.d.cts} +28 -2
- package/dist/{activity-Dw8DOw0L.d.ts → activity-Czlan5xW.d.ts} +28 -2
- package/dist/activity-module-DaO1Rry0.d.cts +22 -0
- package/dist/activity-module-T22wliZu.d.ts +22 -0
- package/dist/activity-ports-Dqxa86zT.d.cts +12 -0
- package/dist/activity-ports-cxfrelaL.d.ts +12 -0
- package/dist/activity.cjs +10 -282
- package/dist/activity.cjs.map +1 -1
- package/dist/activity.d.cts +8 -30
- package/dist/activity.d.ts +8 -30
- package/dist/activity.js +9 -281
- package/dist/activity.js.map +1 -1
- package/dist/{chunk-O4OGAAV4.js → chunk-3JYLJPE5.js} +29 -5
- package/dist/chunk-3JYLJPE5.js.map +1 -0
- package/dist/{chunk-ATUFFNLV.js → chunk-3LEIHB7Y.js} +5 -5
- package/dist/chunk-4XF6LQSU.cjs.map +1 -1
- package/dist/chunk-5Q7WB63A.cjs +282 -0
- package/dist/chunk-5Q7WB63A.cjs.map +1 -0
- package/dist/{chunk-PSKQAFDF.cjs → chunk-7KDOTBRX.cjs} +1 -1
- package/dist/chunk-7KDOTBRX.cjs.map +1 -0
- package/dist/{chunk-5DLZWW5Y.js → chunk-AHHEGTUA.js} +3 -3
- package/dist/chunk-AOHQCX7K.cjs +95 -0
- package/dist/chunk-AOHQCX7K.cjs.map +1 -0
- package/dist/{chunk-IUI5CI2S.cjs → chunk-DINLR6E6.cjs} +96 -92
- package/dist/chunk-DINLR6E6.cjs.map +1 -0
- package/dist/{chunk-L44TM4EE.cjs → chunk-EYTVC2H5.cjs} +568 -454
- package/dist/chunk-EYTVC2H5.cjs.map +1 -0
- package/dist/chunk-FEE2YBZ7.js +1972 -0
- package/dist/chunk-FEE2YBZ7.js.map +1 -0
- package/dist/chunk-FNO5K3A7.js +282 -0
- package/dist/chunk-FNO5K3A7.js.map +1 -0
- package/dist/chunk-IHHDXZPZ.js +382 -0
- package/dist/chunk-IHHDXZPZ.js.map +1 -0
- package/dist/chunk-J3EAIVA3.js +280 -0
- package/dist/chunk-J3EAIVA3.js.map +1 -0
- package/dist/{chunk-DFTOTBGF.js → chunk-KH3WF3K4.js} +20 -16
- package/dist/chunk-KH3WF3K4.js.map +1 -0
- package/dist/{chunk-TB2RZGDV.js → chunk-M35X5PHO.js} +14 -1
- package/dist/chunk-M35X5PHO.js.map +1 -0
- package/dist/chunk-QRGZD2JU.cjs +1972 -0
- package/dist/chunk-QRGZD2JU.cjs.map +1 -0
- package/dist/{chunk-4KF7KUAI.cjs → chunk-RBOER6EW.cjs} +6 -6
- package/dist/chunk-RBOER6EW.cjs.map +1 -0
- package/dist/{chunk-6MN3H3YF.cjs → chunk-RSH6QSEC.cjs} +16 -3
- package/dist/chunk-RSH6QSEC.cjs.map +1 -0
- package/dist/{chunk-T7P5EIC4.cjs → chunk-VMRDXOLX.cjs} +33 -33
- package/dist/chunk-VMRDXOLX.cjs.map +1 -0
- package/dist/{chunk-5XKOCKY2.js → chunk-X4UHZX6F.js} +1 -1
- package/dist/chunk-XBSGUVCY.cjs +382 -0
- package/dist/chunk-XBSGUVCY.cjs.map +1 -0
- package/dist/{chunk-OHQTKGQN.js → chunk-XKDZHAUE.js} +242 -128
- package/dist/chunk-XKDZHAUE.js.map +1 -0
- package/dist/chunk-ZUZGAO6G.cjs +280 -0
- package/dist/chunk-ZUZGAO6G.cjs.map +1 -0
- package/dist/{content-CAIp1njn.d.cts → content-C5aJZFlw.d.cts} +1 -1
- package/dist/{content-CGMJdyH_.d.ts → content-hLH5BNud.d.ts} +1 -1
- package/dist/contracts/index.cjs +13 -3
- package/dist/contracts/index.cjs.map +1 -1
- package/dist/contracts/index.d.cts +5 -4
- package/dist/contracts/index.d.ts +5 -4
- package/dist/contracts/index.js +14 -4
- package/dist/{discovery-DxpirOz3.d.cts → discovery-9E-LfwIw.d.cts} +1 -1
- package/dist/{discovery-gSqWpuRm.d.ts → discovery-D60yrjej.d.ts} +1 -1
- package/dist/discovery.cjs +63 -65
- package/dist/discovery.cjs.map +1 -1
- package/dist/discovery.d.cts +4 -4
- package/dist/discovery.d.ts +4 -4
- package/dist/discovery.js +5 -7
- package/dist/discovery.js.map +1 -1
- package/dist/execution-bridge-fpCnH6z5.d.cts +52 -0
- package/dist/execution-bridge-rk0uVy_n.d.ts +52 -0
- package/dist/execution.cjs +6 -356
- package/dist/execution.cjs.map +1 -1
- package/dist/execution.d.cts +4 -51
- package/dist/execution.d.ts +4 -51
- package/dist/execution.js +9 -359
- package/dist/execution.js.map +1 -1
- package/dist/index.cjs +10 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -16
- package/dist/index.d.ts +9 -16
- package/dist/index.js +10 -12
- package/dist/index.js.map +1 -1
- package/dist/{module-CWNK2BMj.d.ts → module-CYfE7YhM.d.ts} +2 -2
- package/dist/{module-BbvwdCDF.d.cts → module-Ca9L3qCn.d.cts} +2 -2
- package/dist/{planning-CcFZYdIL.d.cts → planning-CHrOqQ6b.d.cts} +45 -10
- package/dist/{planning-CcFZYdIL.d.ts → planning-CHrOqQ6b.d.ts} +45 -10
- package/dist/{ports-Bn6ro2FB.d.ts → ports-B0McVg7B.d.ts} +4 -3
- package/dist/ports-BeGO1VRI.d.cts +49 -0
- package/dist/{ports-CaL6geqR.d.cts → ports-GQy0x-RI.d.cts} +4 -3
- package/dist/ports-ykGiNUSx.d.ts +49 -0
- package/dist/runtime/index.cjs +205 -0
- package/dist/runtime/index.cjs.map +1 -0
- package/dist/runtime/index.d.cts +75 -0
- package/dist/runtime/index.d.ts +75 -0
- package/dist/runtime/index.js +205 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/integration.cjs +423 -0
- package/dist/runtime/integration.cjs.map +1 -0
- package/dist/runtime/integration.d.cts +658 -0
- package/dist/runtime/integration.d.ts +658 -0
- package/dist/runtime/integration.js +423 -0
- package/dist/runtime/integration.js.map +1 -0
- package/dist/storage.cjs +9 -277
- package/dist/storage.cjs.map +1 -1
- package/dist/storage.d.cts +6 -6
- package/dist/storage.d.ts +6 -6
- package/dist/storage.js +11 -279
- package/dist/storage.js.map +1 -1
- package/dist/{store-q63eSMoT.d.cts → store-DPwHzGiz.d.cts} +2 -2
- package/dist/{store-Ct0gOAAg.d.ts → store-DgdrPCV9.d.ts} +2 -2
- package/dist/task-projection-CSorlMws.d.ts +11 -0
- package/dist/task-projection-DKKB_ueb.d.cts +11 -0
- package/examples/standalone.ts +22 -0
- package/package.json +117 -87
- package/dist/chunk-2YFPV5GF.cjs +0 -16
- package/dist/chunk-2YFPV5GF.cjs.map +0 -1
- package/dist/chunk-4KF7KUAI.cjs.map +0 -1
- package/dist/chunk-6MN3H3YF.cjs.map +0 -1
- package/dist/chunk-DFTOTBGF.js.map +0 -1
- package/dist/chunk-G6FCDLDF.js +0 -16
- package/dist/chunk-G6FCDLDF.js.map +0 -1
- package/dist/chunk-IUI5CI2S.cjs.map +0 -1
- package/dist/chunk-KYNYPKKH.cjs +0 -71
- package/dist/chunk-KYNYPKKH.cjs.map +0 -1
- package/dist/chunk-L44TM4EE.cjs.map +0 -1
- package/dist/chunk-LSE6JG5I.cjs +0 -20
- package/dist/chunk-LSE6JG5I.cjs.map +0 -1
- package/dist/chunk-O4OGAAV4.js.map +0 -1
- package/dist/chunk-OHQTKGQN.js.map +0 -1
- package/dist/chunk-PSKQAFDF.cjs.map +0 -1
- package/dist/chunk-QTMTBEBA.js +0 -20
- package/dist/chunk-QTMTBEBA.js.map +0 -1
- package/dist/chunk-T7P5EIC4.cjs.map +0 -1
- package/dist/chunk-TB2RZGDV.js.map +0 -1
- package/dist/ui/index.cjs +0 -1961
- package/dist/ui/index.cjs.map +0 -1
- package/dist/ui/index.d.cts +0 -209
- package/dist/ui/index.d.ts +0 -209
- package/dist/ui/index.js +0 -1961
- package/dist/ui/index.js.map +0 -1
- package/dist/ui/kanban.css +0 -194
- /package/dist/{chunk-ATUFFNLV.js.map → chunk-3LEIHB7Y.js.map} +0 -0
- /package/dist/{chunk-5DLZWW5Y.js.map → chunk-AHHEGTUA.js.map} +0 -0
- /package/dist/{chunk-5XKOCKY2.js.map → chunk-X4UHZX6F.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/home/li/share/prj/x1/libraries/kanban/dist/chunk-AOHQCX7K.cjs","../src/contracts/board-control.ts","../src/contracts/task-projection.ts"],"names":["item"],"mappings":"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","file":"/home/li/share/prj/x1/libraries/kanban/dist/chunk-AOHQCX7K.cjs","sourcesContent":[null,"import type {KanbanBoard, KanbanItem} from './contracts';\n\nexport interface KanbanBoardControl {\n mode: 'automatic' | 'manual'; paused: boolean;\n controls: Record<string, string>;\n}\n/** Manual mode still honors an explicit per-task run request. */\nexport function boardAllowsStart(board: Pick<KanbanBoard, 'executionControl' | 'lifecycle'>, item?: Pick<KanbanItem, 'launch'>): boolean {\n return !board.lifecycle && !board.executionControl?.paused && (board.executionControl?.mode !== 'manual' || item?.launch?.requestedAt !== undefined);\n}\nexport function boardControlPhase(board: Pick<KanbanBoard, 'executionControl' | 'lifecycle'> & {items: Array<Pick<KanbanItem, 'id' | 'status' | 'control'>>}): 'automatic' | 'manual' | 'pausing' | 'paused' | 'resuming' | 'error' | 'cancelling' | 'cancelled' | 'waiting-deletion' {\n if (board.lifecycle) return board.lifecycle.intent === 'delete' ? 'waiting-deletion' : board.lifecycle.phase === 'ready' ? 'cancelled' : 'cancelling';\n const policy = board.executionControl;\n const controls = Object.entries(policy?.controls ?? {}).flatMap(([id, controlId]) => {\n const item = board.items.find(item => item.id === id);\n return item && !['completed', 'cancelled', 'review'].includes(item.status) && item.control?.id === controlId ? [item.control] : [];\n });\n if (controls.some(control => control?.state === 'failed' || control?.state === 'unknown')) return 'error';\n if (controls.some(control => control?.state === 'requested' || control?.state === 'accepted')) return policy?.paused ? 'pausing' : 'resuming';\n return policy?.paused ? 'paused' : policy?.mode ?? 'automatic';\n}\n","import type {KanbanDispatch,KanbanItem,KanbanItemSummary,KanbanWorkflowState,KanbanTaskProjection,KanbanTaskPhase} from './index';\n\ntype Item=Pick<KanbanItem,'deletedAt'|'id'|'status'|'createdAt'|'launch'|'analysis'|'control'|'issues'|'blocked'|'externalRefs'|'planning'>;\ntype Fact={phase:KanbanTaskPhase;reason?:string;actions?:KanbanTaskProjection['actions']};\nexport const TASK_START_DELAY_MS=300000;\nexport function taskStartAt(item:Pick<Item,'createdAt'|'launch'>):number {return item.launch?.startAt??item.createdAt+TASK_START_DELAY_MS;}\nexport function taskEditing(item:Pick<Item,'launch'>,now:number):boolean {return (item.launch?.editing?.expiresAt??0)>now;}\nexport function taskDue(item:Item,now:number):boolean {\n return !taskEditing(item,now)&&!item.blocked&&(!item.control || item.control.action === 'resume' && item.control.state === 'resumed')\n &&(item.launch?.requestedAt!==undefined||item.launch?.mode!=='manual'&&taskStartAt(item)<=now);\n}\n/** Ordered evidence projection shared by storage queries, CLI and UI. Session idle never proves acceptance. */\nexport function projectKanbanTask(item:Item,workflow?:KanbanWorkflowState,now=Date.now(),all:Array<Pick<KanbanItemSummary,'id'|'status'>>=[]):KanbanTaskProjection {\n const dispatch=Object.values(workflow?.dispatches??{}).filter(d=>d.itemId===item.id).sort((a,b)=>b.attempt-a.attempt)[0];\n const fact=terminalFact(item)??controlFact(item)??issueFact(item,dispatch)??failureFact(item,dispatch)??executionFact(item,dispatch)??waitingFact(item,now,all);\n const extra: KanbanTaskProjection['actions'] = [];\n if (!['completed','cancelled'].includes(item.status) && item.control?.action !== 'cancel') {\n if (!fact.actions?.includes('cancel')) extra.push('cancel');\n if (item.status !== 'review' && !fact.actions?.includes('pause') && !fact.actions?.includes('resume') && (dispatch?.controlCapabilities?.pause === 'boundary' || !dispatch)) extra.push('pause');\n }\n return {...fact,startAt:taskStartAt(item),dispatchId:dispatch?.id,sessionId:dispatch?.executionSessionId,\n actions:item.deletedAt === undefined ? [...fact.actions??[],...extra,...(dispatch||item.launch?.admittedAt!==undefined||['claimed','review','completed'].includes(item.status)?['fix' as const]:[]),...(dispatch?.executionSessionId?['open-session' as const]:[])] : []};\n}\nfunction terminalFact(item:Item):Fact|undefined {\n if(item.status==='completed'||item.status==='cancelled')return {phase:item.status,actions:['delete']};\n if(item.control?.action==='cancel')return {phase:item.control.state==='failed'?'error':item.control.state==='unknown'?'unknown':'cancelling',reason:item.control.code,actions:item.control.state==='failed'?['cancel']:[]};\n if(item.status==='review')return {phase:'review',actions:['review']};\n}\nfunction issueFact(item:Item,dispatch?:KanbanDispatch):Fact|undefined {\n const issue=item.issues?.find(i=>!i.resolvedBy&&(!dispatch||i.attemptId===dispatch.id));\n if(issue)return {phase:issue.type==='clarification'?'waiting-input':'error',reason:issue.id,actions:['resolve']};\n}\nfunction controlFact(item:Item):Fact|undefined {\n const control=item.control;if(!control)return;\n const reason=control.code;\n if(control.state==='unknown')return {phase:'unknown',reason};\n if(control.state==='failed')return {phase:'error',reason,actions:['resume']};\n if(control.action==='pause')return {phase:control.state==='paused'?'paused':'pausing',reason,actions:['resume']};\n if(['requested','accepted'].includes(control.state))return {phase:'resuming',reason};\n}\nfunction failureFact(item:Item,dispatch?:KanbanDispatch):Fact|undefined {\n if(dispatch?.outcome==='unknown'||item.analysis?.state==='unknown')return {phase:'unknown',reason:dispatch?.code??item.analysis?.code};\n if(dispatch&&['failed','cancelled','rejected'].includes(dispatch.outcome))return {phase:'error',reason:dispatch.code??dispatch.outcome};\n if(item.analysis?.state==='failed')return {phase:'error',reason:item.analysis.code};\n}\nfunction executionFact(item:Item,dispatch?:KanbanDispatch):Fact|undefined {\n if(item.blocked)return {phase:item.blocked.reason==='WORKSPACE_INPUT_REQUIRED'?'waiting-input':'error',reason:item.blocked.reason};\n if(dispatch?.outcome==='prepared')return {phase:'preparing'};\n if(dispatch?.outcome==='running'||item.status==='claimed')return {phase:'running',actions:dispatch?.controlCapabilities?.pause==='boundary'?['pause']:[]};\n}\nfunction waitingFact(item:Item,now:number,all:Array<Pick<KanbanItemSummary,'id'|'status'>>):Fact {\n const analysis=analysisFact(item);if(analysis)return analysis;\n const dependency=item.planning?.dependencies.find(id=>all.find(i=>i.id===id)?.status!=='completed');\n if(dependency)return {phase:'waiting-dependency',reason:'DEPENDENCY_UNFINISHED:'+dependency,actions:item.launch?.admittedAt===undefined?['edit','cancel']:[]};\n if(taskEditing(item,now))return {phase:'waiting-start',reason:'EDIT_LEASE_ACTIVE'};\n if(item.launch?.admittedAt!==undefined)return {phase:'queued'};\n return {phase:'waiting-start',reason:item.launch?.mode==='manual'?'MANUAL_START_REQUIRED':taskDue(item,now)?'ADMISSION_PENDING':'START_AT_PENDING',actions:['run','edit','pause','cancel']};\n}\nfunction analysisFact(item:Item):Fact|undefined {\n if(item.analysis?.state==='clarification')return {phase:'waiting-input',reason:item.analysis.reason};\n if(item.analysis?.state==='analyzing')return {phase:'analyzing'};\n}\n"]}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
var
|
|
12
|
+
var _chunkEYTVC2H5cjs = require('./chunk-EYTVC2H5.cjs');
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
|
|
@@ -19,59 +19,55 @@ var _chunkL44TM4EEcjs = require('./chunk-L44TM4EE.cjs');
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
var
|
|
22
|
+
var _chunkRBOER6EWcjs = require('./chunk-RBOER6EW.cjs');
|
|
23
23
|
|
|
24
24
|
|
|
25
|
-
var
|
|
25
|
+
var _chunk7KDOTBRXcjs = require('./chunk-7KDOTBRX.cjs');
|
|
26
26
|
|
|
27
27
|
|
|
28
|
-
var _chunkKYNYPKKHcjs = require('./chunk-KYNYPKKH.cjs');
|
|
29
28
|
|
|
29
|
+
var _chunkRSH6QSECcjs = require('./chunk-RSH6QSEC.cjs');
|
|
30
30
|
|
|
31
|
-
var _chunkPSKQAFDFcjs = require('./chunk-PSKQAFDF.cjs');
|
|
32
31
|
|
|
33
32
|
|
|
34
|
-
var
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
var _chunkLSE6JG5Icjs = require('./chunk-LSE6JG5I.cjs');
|
|
33
|
+
var _chunkAOHQCX7Kcjs = require('./chunk-AOHQCX7K.cjs');
|
|
38
34
|
|
|
39
35
|
// src/references.ts
|
|
40
36
|
async function resolveReference(reference, store, read) {
|
|
41
|
-
|
|
37
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, typeof reference === "string" && reference.length <= 100, "INVALID_REFERENCE");
|
|
42
38
|
const match = /^KB-([1-9]\d*)(?:#([1-9]\d*)|\/(L|D)-([1-9]\d*))?$/i.exec(reference.trim());
|
|
43
|
-
|
|
39
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, match && [match[1], match[2], match[4]].every((value) => value === void 0 || Number.isSafeInteger(Number(value))), "INVALID_REFERENCE");
|
|
44
40
|
const id = await _optionalChain([store, 'access', _ => _.boardId, 'optionalCall', _2 => _2(Number(match[1]))]);
|
|
45
|
-
|
|
41
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, id, "REFERENCE_NOT_FOUND");
|
|
46
42
|
const view = await read(id), board = view.state.board;
|
|
47
|
-
|
|
48
|
-
const target = { boardId: id, scope: board.scope, reference:
|
|
43
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, board.number === Number(match[1]), "INVALID_NUMBERING");
|
|
44
|
+
const target = { boardId: id, scope: board.scope, reference: _chunk7KDOTBRXcjs.kanbanReference.call(void 0, board) };
|
|
49
45
|
if (match[2]) {
|
|
50
46
|
const item = [...view.items, ..._nullishCoalesce(view.state.archiveIndex, () => ( []))].find((item2) => item2.number === Number(match[2]));
|
|
51
|
-
|
|
47
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, item, "REFERENCE_NOT_FOUND");
|
|
52
48
|
target.itemId = item.id;
|
|
53
|
-
target.reference =
|
|
49
|
+
target.reference = _chunk7KDOTBRXcjs.kanbanReference.call(void 0, board, item);
|
|
54
50
|
} else if (match[3]) {
|
|
55
51
|
const record = view.records.find((record2) => record2.kind === (match[3].toUpperCase() === "L" ? "log" : "decision") && record2.number === Number(match[4]));
|
|
56
|
-
|
|
52
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, record, "REFERENCE_NOT_FOUND");
|
|
57
53
|
target.recordId = record.id;
|
|
58
|
-
target.reference =
|
|
54
|
+
target.reference = _chunk7KDOTBRXcjs.kanbanReference.call(void 0, board, record);
|
|
59
55
|
}
|
|
60
56
|
return target;
|
|
61
57
|
}
|
|
62
58
|
|
|
63
59
|
// src/suggestions.ts
|
|
64
60
|
function validateSuggestionQuery(query) {
|
|
65
|
-
|
|
66
|
-
|
|
61
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, query && ["item", "parent", "dependency", "area", "milestone", "decision", "session"].includes(query.kind), "INVALID_SUGGESTION_KIND");
|
|
62
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, query.search === void 0 || typeof query.search === "string" && query.search.length <= 256, "INVALID_FILTER");
|
|
67
63
|
const limit = _nullishCoalesce(query.limit, () => ( 20));
|
|
68
|
-
|
|
69
|
-
if (query.excludeItemId !== void 0)
|
|
64
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, Number.isSafeInteger(limit) && limit > 0 && limit <= 50, "INVALID_LIMIT");
|
|
65
|
+
if (query.excludeItemId !== void 0) _chunkRBOER6EWcjs.identity.call(void 0, query.excludeItemId);
|
|
70
66
|
if (query.excludeIds !== void 0) {
|
|
71
|
-
|
|
72
|
-
query.excludeIds.forEach(
|
|
67
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, Array.isArray(query.excludeIds) && query.excludeIds.length <= 100, "INVALID_FILTER");
|
|
68
|
+
query.excludeIds.forEach(_chunkRBOER6EWcjs.identity);
|
|
73
69
|
}
|
|
74
|
-
if (query.childKind !== void 0)
|
|
70
|
+
if (query.childKind !== void 0) _chunkRBOER6EWcjs.identity.call(void 0, query.childKind);
|
|
75
71
|
return limit;
|
|
76
72
|
}
|
|
77
73
|
function suggestionPage(revision, rows, query) {
|
|
@@ -80,13 +76,13 @@ function suggestionPage(revision, rows, query) {
|
|
|
80
76
|
return { revision, items: matched.slice(0, limit).map((row) => ({ id: row.id, label: row.label.slice(0, 256), ...row.detail ? { detail: row.detail.slice(0, 512) } : {}, ...row.status ? { status: row.status } : {}, ...row.archived !== void 0 ? { archived: row.archived } : {} })), hasMore: matched.length > limit };
|
|
81
77
|
}
|
|
82
78
|
var score = (label, query) => label.toLocaleLowerCase() === query ? 0 : label.toLocaleLowerCase().startsWith(query) ? 1 : 2;
|
|
83
|
-
function suggestFromState(state, query, items =
|
|
79
|
+
function suggestFromState(state, query, items = _chunkEYTVC2H5cjs.catalog.call(void 0, state), records = (_nullishCoalesce(state.records, () => ( []))).map(_chunkEYTVC2H5cjs.recordSummary)) {
|
|
84
80
|
validateSuggestionQuery(query);
|
|
85
81
|
if (query.kind === "area" || query.kind === "milestone") {
|
|
86
82
|
const names = [...new Set(items.map((item) => item.planning[query.kind]).filter((name) => !!name))];
|
|
87
83
|
return suggestionPage(state.board.revision, names.map((name) => ({ id: name, label: name })), query);
|
|
88
84
|
}
|
|
89
|
-
if (query.kind === "decision") return suggestionPage(state.board.revision, records.filter((record) => record.kind === "decision" && record.status === "confirmed").map((record) => ({ id: record.id, label: record.title, detail:
|
|
85
|
+
if (query.kind === "decision") return suggestionPage(state.board.revision, records.filter((record) => record.kind === "decision" && record.status === "confirmed").map((record) => ({ id: record.id, label: record.title, detail: _chunk7KDOTBRXcjs.kanbanReference.call(void 0, state.board, record) })), query);
|
|
90
86
|
if (query.kind === "session") {
|
|
91
87
|
const ids = /* @__PURE__ */ new Set([
|
|
92
88
|
...state.board.participants.map((p) => p.sessionId),
|
|
@@ -96,13 +92,13 @@ function suggestFromState(state, query, items = _chunkL44TM4EEcjs.catalog.call(v
|
|
|
96
92
|
return suggestionPage(state.board.revision, [...ids].map((id) => ({ id, label: id })), query);
|
|
97
93
|
}
|
|
98
94
|
const blocked = query.kind === "dependency" && query.excludeItemId ? dependents(items, query.excludeItemId) : /* @__PURE__ */ new Set();
|
|
99
|
-
const rank = query.kind === "parent" ?
|
|
100
|
-
const rows = items.filter((item) => item.id !== query.excludeItemId && !blocked.has(item.id) && (query.kind !== "dependency" || item.status !== "cancelled") && (rank === void 0 || item.archivedAt === void 0 && !
|
|
95
|
+
const rank = query.kind === "parent" ? _chunkRBOER6EWcjs.workType.call(void 0, state.board, _nullishCoalesce(_nullishCoalesce(query.childKind, () => ( state.board.defaultWorkType)), () => ( "task"))).rank : void 0;
|
|
96
|
+
const rows = items.filter((item) => item.id !== query.excludeItemId && !blocked.has(item.id) && (query.kind !== "dependency" || item.status !== "cancelled") && (rank === void 0 || item.archivedAt === void 0 && !_chunkEYTVC2H5cjs.terminal.call(void 0, item) && _chunkRBOER6EWcjs.workType.call(void 0, state.board, item.planning.kind).rank < rank)).map((item) => ({
|
|
101
97
|
id: item.id,
|
|
102
98
|
label: item.title,
|
|
103
99
|
status: item.status,
|
|
104
100
|
archived: item.archivedAt !== void 0,
|
|
105
|
-
detail: [
|
|
101
|
+
detail: [_chunk7KDOTBRXcjs.kanbanReference.call(void 0, state.board, item), item.planning.area, item.planning.milestone].filter(Boolean).join(" \xB7 ")
|
|
106
102
|
}));
|
|
107
103
|
return suggestionPage(state.board.revision, rows, query);
|
|
108
104
|
}
|
|
@@ -118,28 +114,28 @@ function dependents(items, id) {
|
|
|
118
114
|
}
|
|
119
115
|
|
|
120
116
|
// src/queries.ts
|
|
121
|
-
function queryItems(state, query = {}, all =
|
|
117
|
+
function queryItems(state, query = {}, all = _chunkEYTVC2H5cjs.catalog.call(void 0, state), now = Date.now()) {
|
|
122
118
|
const { cursor, limit = 50, ...filters } = query;
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
for (const field of ["area", "milestone", "parentId", "kind", "sessionId", "search"]) if (filters[field] !== void 0)
|
|
126
|
-
if (filters.reference)
|
|
119
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, Number.isSafeInteger(limit) && limit >= 1 && limit <= 200, "INVALID_PAGE_SIZE");
|
|
120
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, ["ready", "backlog", "in-progress", "review", "closed", "proposed", "archive", "all"].includes(_nullishCoalesce(query.view, () => ( "ready"))), "INVALID_VIEW");
|
|
121
|
+
for (const field of ["area", "milestone", "parentId", "kind", "sessionId", "search"]) if (filters[field] !== void 0) _chunkRBOER6EWcjs.requireValue.call(void 0, typeof filters[field] === "string" && filters[field].length <= 256, "INVALID_FILTER");
|
|
122
|
+
if (filters.reference) _chunkRBOER6EWcjs.requireValue.call(void 0, typeof filters.reference.system === "string" && typeof filters.reference.id === "string" && filters.reference.system.length <= 256 && filters.reference.id.length <= 256, "INVALID_REFERENCE_FILTER");
|
|
127
123
|
const fingerprint = JSON.stringify(Object.fromEntries(Object.entries({ ...filters, view: _nullishCoalesce(filters.view, () => ( "ready")) }).sort(([a], [b]) => a.localeCompare(b)))), revision = state.board.revision;
|
|
128
|
-
all = all.map((item) => ({ ...item, task:
|
|
124
|
+
all = all.map((item) => ({ ...item, task: _chunkAOHQCX7Kcjs.projectKanbanTask.call(void 0, item, state.workflow, now, all) }));
|
|
129
125
|
const matches = all.filter((item) => matchesQuery(item, filters, state.board)).sort(filters.view === "archive" ? (a, b) => (_nullishCoalesce(b.archivedAt, () => ( 0))) - (_nullishCoalesce(a.archivedAt, () => ( 0))) || a.id.localeCompare(b.id) : order);
|
|
130
126
|
let start = 0;
|
|
131
127
|
if (cursor) {
|
|
132
|
-
|
|
128
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, typeof cursor === "string" && cursor.length <= 4e3, "INVALID_CURSOR");
|
|
133
129
|
let decoded;
|
|
134
130
|
try {
|
|
135
131
|
decoded = JSON.parse(cursor);
|
|
136
132
|
} catch (e) {
|
|
137
|
-
|
|
133
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, false, "INVALID_CURSOR");
|
|
138
134
|
}
|
|
139
|
-
|
|
140
|
-
|
|
135
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, decoded && decoded.filter === fingerprint, "CURSOR_SCOPE_MISMATCH");
|
|
136
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, decoded.revision === revision, "CURSOR_STALE");
|
|
141
137
|
start = matches.findIndex((i) => i.id === decoded.after) + 1;
|
|
142
|
-
|
|
138
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, start > 0, "INVALID_CURSOR");
|
|
143
139
|
}
|
|
144
140
|
const progress = progressByParent(state, all);
|
|
145
141
|
const items = matches.slice(start, start + limit).map((item) => ({ ...item, ...progress.has(item.id) ? { progress: progress.get(item.id) } : {} }));
|
|
@@ -151,12 +147,13 @@ function order(a, b) {
|
|
|
151
147
|
return a.planning.priority - b.planning.priority || a.createdAt - b.createdAt || a.id.localeCompare(b.id);
|
|
152
148
|
}
|
|
153
149
|
function matchesQuery(item, query, board) {
|
|
150
|
+
if (item.deletedAt !== void 0 && !query.includeDeleted) return false;
|
|
154
151
|
if (query.phase && _optionalChain([item, 'access', _11 => _11.task, 'optionalAccess', _12 => _12.phase]) !== query.phase) return false;
|
|
155
152
|
if (!matchesView(item, _nullishCoalesce(query.view, () => ( "ready")))) return false;
|
|
156
153
|
for (const field of ["area", "milestone", "parentId", "kind"]) if (query[field] !== void 0 && item.planning[field] !== query[field]) return false;
|
|
157
154
|
if (query.reference && !_optionalChain([item, 'access', _13 => _13.externalRefs, 'optionalAccess', _14 => _14.some, 'call', _15 => _15((r) => r.system === query.reference.system && r.id === query.reference.id)])) return false;
|
|
158
155
|
if (query.sessionId && !item.sessionIds.includes(query.sessionId)) return false;
|
|
159
|
-
if (query.search && !`${
|
|
156
|
+
if (query.search && !`${_chunk7KDOTBRXcjs.kanbanReference.call(void 0, board, item)} ${item.id} ${item.title} ${_nullishCoalesce(item.planning.area, () => ( ""))}`.toLowerCase().includes(query.search.toLowerCase())) return false;
|
|
160
157
|
return true;
|
|
161
158
|
}
|
|
162
159
|
function matchesView(item, view) {
|
|
@@ -164,16 +161,17 @@ function matchesView(item, view) {
|
|
|
164
161
|
if (view === "all") return true;
|
|
165
162
|
if (item.archivedAt !== void 0) return false;
|
|
166
163
|
if (view === "in-progress") return item.status === "claimed" || item.status === "review";
|
|
167
|
-
if (view === "closed") return
|
|
164
|
+
if (view === "closed") return _chunkEYTVC2H5cjs.terminal.call(void 0, item);
|
|
168
165
|
return item.status === { ready: "open", backlog: "backlog", review: "review", proposed: "proposed" }[view];
|
|
169
166
|
}
|
|
170
|
-
function overview(state, now, items = state.board.items.map(
|
|
167
|
+
function overview(state, now, items = state.board.items.map(_chunkEYTVC2H5cjs.summary)) {
|
|
168
|
+
items = items.filter((item) => item.deletedAt === void 0);
|
|
171
169
|
const count = (status) => items.filter((i) => i.status === status).length;
|
|
172
170
|
const age = state.board.policy.backlogReviewMs;
|
|
173
171
|
return {
|
|
174
172
|
revision: state.board.revision,
|
|
175
173
|
visible: items.length,
|
|
176
|
-
active: items.filter((i) => !
|
|
174
|
+
active: items.filter((i) => !_chunkEYTVC2H5cjs.terminal.call(void 0, i)).length,
|
|
177
175
|
archived: _nullishCoalesce(_optionalChain([state, 'access', _16 => _16.archiveIndex, 'optionalAccess', _17 => _17.length]), () => ( 0)),
|
|
178
176
|
ready: count("open"),
|
|
179
177
|
inProgress: count("claimed") + count("review"),
|
|
@@ -181,13 +179,13 @@ function overview(state, now, items = state.board.items.map(_chunkL44TM4EEcjs.su
|
|
|
181
179
|
proposed: count("proposed"),
|
|
182
180
|
closed: count("completed") + count("cancelled"),
|
|
183
181
|
dueForReview: age ? items.filter((i) => i.status === "backlog" && now - i.updatedAt >= age).length : 0,
|
|
184
|
-
limits:
|
|
182
|
+
limits: _chunkEYTVC2H5cjs.limits.call(void 0, state)
|
|
185
183
|
};
|
|
186
184
|
}
|
|
187
185
|
function progressByParent(state, all) {
|
|
188
186
|
const byId = new Map(all.map((i) => [i.id, i]));
|
|
189
187
|
const result = /* @__PURE__ */ new Map();
|
|
190
|
-
for (const item of all.filter((i) =>
|
|
188
|
+
for (const item of all.filter((i) => _chunkRBOER6EWcjs.executable.call(void 0, state.board, i))) {
|
|
191
189
|
let parent = item.planning.parentId;
|
|
192
190
|
const seen = /* @__PURE__ */ new Set();
|
|
193
191
|
while (parent && !seen.has(parent)) {
|
|
@@ -212,8 +210,8 @@ var KanbanModule = (_class = class {
|
|
|
212
210
|
constructor(options) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this);_class.prototype.__init5.call(this);_class.prototype.__init6.call(this);_class.prototype.__init7.call(this);_class.prototype.__init8.call(this);_class.prototype.__init9.call(this);_class.prototype.__init10.call(this);_class.prototype.__init11.call(this);_class.prototype.__init12.call(this);_class.prototype.__init13.call(this);_class.prototype.__init14.call(this);_class.prototype.__init15.call(this);_class.prototype.__init16.call(this);_class.prototype.__init17.call(this);_class.prototype.__init18.call(this);_class.prototype.__init19.call(this);
|
|
213
211
|
this.options = options;
|
|
214
212
|
this.now = _nullishCoalesce(options.now, () => ( Date.now));
|
|
215
|
-
this.id = _nullishCoalesce(options.id, () => (
|
|
216
|
-
this.actor =
|
|
213
|
+
this.id = _nullishCoalesce(options.id, () => ( _chunkRSH6QSECcjs.randomUUID));
|
|
214
|
+
this.actor = _chunkRBOER6EWcjs.normalizeActor.call(void 0, options.actor);
|
|
217
215
|
}
|
|
218
216
|
__init() {this.stopping = false}
|
|
219
217
|
__init2() {this.pending = /* @__PURE__ */ new Set()}
|
|
@@ -233,29 +231,29 @@ var KanbanModule = (_class = class {
|
|
|
233
231
|
const snapshot = structuredClone(query), limit = validateSuggestionQuery(snapshot), view = await this.readView(boardId), state = view.state;
|
|
234
232
|
const suggestions = () => suggestFromState(state, snapshot, [...view.items, ..._nullishCoalesce(state.archiveIndex, () => ( []))], view.records);
|
|
235
233
|
if (!this.options.suggestions) return suggestions();
|
|
236
|
-
const rows = await this.options.suggestions(structuredClone(state.board), snapshot.kind, _nullishCoalesce(_optionalChain([snapshot, 'access',
|
|
234
|
+
const rows = await this.options.suggestions(structuredClone(state.board), snapshot.kind, _nullishCoalesce(_optionalChain([snapshot, 'access', _50 => _50.search, 'optionalAccess', _51 => _51.trim, 'call', _52 => _52()]), () => ( "")), limit + 1);
|
|
237
235
|
if (rows === void 0) return suggestions();
|
|
238
236
|
const known = suggestions().items.filter((row) => !rows.some((entry) => entry.id === row.id));
|
|
239
237
|
return suggestionPage(state.board.revision, [...rows, ...known], snapshot);
|
|
240
238
|
})}
|
|
241
239
|
__init6() {this.records = (boardId, query) => this.guard(this.id(), boardId, "records", async () => {
|
|
242
240
|
const view = await this.readView(boardId);
|
|
243
|
-
return structuredClone(
|
|
241
|
+
return structuredClone(_chunkEYTVC2H5cjs.queryRecords.call(void 0, view.state, query, view.records));
|
|
244
242
|
})}
|
|
245
243
|
__init7() {this.record = (boardId, recordId) => this.guard(this.id(), boardId, "record", async () => {
|
|
246
|
-
|
|
247
|
-
const record = await _asyncOptionalChain([(await this.readState(boardId)), 'access', async
|
|
248
|
-
|
|
244
|
+
_chunkRBOER6EWcjs.identity.call(void 0, recordId);
|
|
245
|
+
const record = await _asyncOptionalChain([(await this.readState(boardId)), 'access', async _53 => _53.records, 'optionalAccess', async _54 => _54.find, 'call', async _55 => _55((record2) => record2.id === recordId)]);
|
|
246
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, record, "RECORD_NOT_FOUND");
|
|
249
247
|
return structuredClone(record);
|
|
250
248
|
})}
|
|
251
|
-
__init8() {this.currentPrincipal = async () => structuredClone(
|
|
249
|
+
__init8() {this.currentPrincipal = async () => structuredClone(_chunkRBOER6EWcjs.principal.call(void 0, this.actor))}
|
|
252
250
|
__init9() {this.create = (input) => {
|
|
253
251
|
const snapshot = structuredClone(input);
|
|
254
252
|
return this.guard(this.id(), snapshot.id, "create", async () => {
|
|
255
|
-
const initial =
|
|
253
|
+
const initial = _chunkEYTVC2H5cjs.createBoardState.call(void 0, snapshot, this.actor, this.now()), board = initial.board;
|
|
256
254
|
await this.authorize(board, "create");
|
|
257
255
|
const state = await this.options.store.update(board.id, `create:${board.id}`, JSON.stringify({ snapshot, actor: this.actor }), (previous) => {
|
|
258
|
-
|
|
256
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !previous, "BOARD_EXISTS");
|
|
259
257
|
return initial;
|
|
260
258
|
});
|
|
261
259
|
return structuredClone(state.board);
|
|
@@ -273,9 +271,9 @@ var KanbanModule = (_class = class {
|
|
|
273
271
|
try {
|
|
274
272
|
const view = await this.readView(id);
|
|
275
273
|
if (view.state.board.deletedAt !== void 0) continue;
|
|
276
|
-
boards.push({ ...view.state.board, executionPhase:
|
|
274
|
+
boards.push({ ...view.state.board, executionPhase: _chunkAOHQCX7Kcjs.boardControlPhase.call(void 0, { ...view.state.board, items: view.items }), items: view.items.filter((item) => item.deletedAt === void 0).map(({ id: id2, title, number }) => ({ id: id2, title, ...number === void 0 ? {} : { number } })) });
|
|
277
275
|
} catch (error) {
|
|
278
|
-
if (!(error instanceof
|
|
276
|
+
if (!(error instanceof _chunkRSH6QSECcjs.KanbanError) || error.code !== "FORBIDDEN") throw error;
|
|
279
277
|
}
|
|
280
278
|
}
|
|
281
279
|
return structuredClone(boards);
|
|
@@ -287,25 +285,26 @@ var KanbanModule = (_class = class {
|
|
|
287
285
|
const board = (await this.readState(boardId)).board;
|
|
288
286
|
if (board.deletedAt === void 0) boards.push(structuredClone(board));
|
|
289
287
|
} catch (error) {
|
|
290
|
-
if (!(error instanceof
|
|
288
|
+
if (!(error instanceof _chunkRSH6QSECcjs.KanbanError) || error.code !== "FORBIDDEN") throw error;
|
|
291
289
|
}
|
|
292
290
|
}
|
|
293
291
|
return boards;
|
|
294
292
|
})}
|
|
295
293
|
__init13() {this.execute = (boardId, input) => this.guard(input.operationId, boardId, `execute:${input.command.type}`, async () => {
|
|
296
294
|
const request = structuredClone(input);
|
|
297
|
-
|
|
295
|
+
_chunkRBOER6EWcjs.identity.call(void 0, request.operationId);
|
|
298
296
|
const state = await this.readState(boardId);
|
|
299
297
|
await this.authorize(state.board, request.command.type, request.command);
|
|
300
|
-
|
|
301
|
-
if (request.command.type === "delete-board") await _optionalChain([this, 'access',
|
|
298
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, state.board.deletedAt === void 0, "BOARD_DELETED");
|
|
299
|
+
if (request.command.type === "delete-board") await _optionalChain([this, 'access', _56 => _56.options, 'access', _57 => _57.verifyDeletion, 'optionalCall', _58 => _58(structuredClone(state.board))]);
|
|
300
|
+
await _optionalChain([this, 'access', _59 => _59.options, 'access', _60 => _60.verifyLifecycle, 'optionalCall', _61 => _61(structuredClone(state.board), request.command)]);
|
|
302
301
|
await this.verifyRelease(state.board, request.command);
|
|
303
302
|
const verifyStage = request.command.type === "observe-execution" && request.command.outcome === "succeeded" ? "observe" : request.command.type === "accept-execution" && request.command.accept ? "accept" : void 0;
|
|
304
303
|
if (verifyStage && "dispatchId" in request.command) {
|
|
305
|
-
const dispatch = _optionalChain([state, 'access',
|
|
306
|
-
|
|
304
|
+
const dispatch = _optionalChain([state, 'access', _62 => _62.workflow, 'optionalAccess', _63 => _63.dispatches, 'access', _64 => _64[request.command.dispatchId]]);
|
|
305
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, dispatch, "DISPATCH_NOT_FOUND");
|
|
307
306
|
const outputs = request.command.type === "observe-execution" ? request.command.outputs : dispatch.outputs;
|
|
308
|
-
if (_optionalChain([outputs, 'optionalAccess',
|
|
307
|
+
if (_optionalChain([outputs, 'optionalAccess', _65 => _65.length])) _chunkRBOER6EWcjs.requireValue.call(void 0, await _optionalChain([this, 'access', _66 => _66.options, 'access', _67 => _67.verifyOutputs, 'optionalCall', _68 => _68({
|
|
309
308
|
stage: verifyStage,
|
|
310
309
|
board: state.board,
|
|
311
310
|
itemId: dispatch.itemId,
|
|
@@ -315,16 +314,16 @@ var KanbanModule = (_class = class {
|
|
|
315
314
|
}
|
|
316
315
|
const restore = request.command.type === "restore-item" ? await this.options.store.archived(boardId, request.command.itemId) : void 0;
|
|
317
316
|
const result = await this.options.store.update(boardId, request.operationId, JSON.stringify({ actor: this.actor, request }), (current) => {
|
|
318
|
-
|
|
319
|
-
|
|
317
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, current && current.board.revision === state.board.revision, "REVISION_CONFLICT");
|
|
318
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, current.board.revision === request.expectedRevision, "REVISION_CONFLICT");
|
|
320
319
|
if (restore) current.restore = restore;
|
|
321
|
-
return
|
|
320
|
+
return _chunkEYTVC2H5cjs.reduce.call(void 0, current, request.command, this.actor, request.operationId, this.now(), this.id());
|
|
322
321
|
});
|
|
323
322
|
await this.publishNotifications(boardId, request.operationId);
|
|
324
323
|
return structuredClone(result.board);
|
|
325
324
|
})}
|
|
326
325
|
__init14() {this.events = (boardId, after = 0, limit = 100) => this.guard(this.id(), boardId, "events", async () => {
|
|
327
|
-
|
|
326
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, Number.isSafeInteger(after) && after >= 0 && Number.isSafeInteger(limit) && limit > 0 && limit <= 500, "INVALID_CURSOR");
|
|
328
327
|
const { state } = await this.readView(boardId);
|
|
329
328
|
return this.options.store.events(boardId, after, limit, state.sequence);
|
|
330
329
|
})}
|
|
@@ -337,30 +336,35 @@ var KanbanModule = (_class = class {
|
|
|
337
336
|
return overview(view.state, this.now(), view.items);
|
|
338
337
|
})}
|
|
339
338
|
__init17() {this.item = (boardId, itemId) => this.guard(this.id(), boardId, "item", async () => {
|
|
340
|
-
|
|
339
|
+
_chunkRBOER6EWcjs.identity.call(void 0, itemId);
|
|
341
340
|
const state = await this.readState(boardId), item = state.board.items.find((i) => i.id === itemId);
|
|
342
|
-
if (item) return { item: structuredClone(item), task:
|
|
343
|
-
|
|
341
|
+
if (item) return { item: structuredClone(item), task: _chunkAOHQCX7Kcjs.projectKanbanTask.call(void 0, item, state.workflow, this.now(), [...state.board.items, ..._nullishCoalesce(state.archiveIndex, () => ( []))]) };
|
|
342
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, _optionalChain([state, 'access', _69 => _69.archiveIndex, 'optionalAccess', _70 => _70.some, 'call', _71 => _71((i) => i.id === itemId)]), "ITEM_NOT_FOUND");
|
|
344
343
|
const record = await this.options.store.archived(boardId, itemId);
|
|
345
|
-
|
|
346
|
-
return { item: structuredClone(record.item), task:
|
|
344
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, record, "REVISION_CONFLICT");
|
|
345
|
+
return { item: structuredClone(record.item), task: _chunkAOHQCX7Kcjs.projectKanbanTask.call(void 0, record.item, state.workflow, this.now(), state.archiveIndex), archive: { archivedAt: record.archivedAt, reason: record.reason } };
|
|
347
346
|
})}
|
|
348
347
|
__init18() {this.related = (sessionId) => this.guard(this.id(), void 0, "related", async () => {
|
|
349
|
-
|
|
348
|
+
_chunkRBOER6EWcjs.identity.call(void 0, sessionId);
|
|
350
349
|
const result = [];
|
|
351
350
|
for (const board of await this.list()) {
|
|
352
351
|
const state = await this.readState(board.id);
|
|
353
|
-
if (
|
|
352
|
+
if (_chunkEYTVC2H5cjs.related.call(void 0, board).includes(sessionId) || _optionalChain([state, 'access', _72 => _72.records, 'optionalAccess', _73 => _73.some, 'call', _74 => _74((record) => record.sources.some((source) => source.sessionId === sessionId))]) || _optionalChain([state, 'access', _75 => _75.archiveIndex, 'optionalAccess', _76 => _76.some, 'call', _77 => _77((i) => i.sessionIds.includes(sessionId))])) result.push(board);
|
|
354
353
|
}
|
|
355
354
|
return result;
|
|
356
355
|
})}
|
|
357
356
|
__init19() {this.scan = () => this.guard(this.id(), void 0, "scan", async () => {
|
|
358
357
|
const errors = [];
|
|
359
|
-
for (const
|
|
358
|
+
for (const id of await this.options.store.ids()) {
|
|
360
359
|
try {
|
|
360
|
+
const board = (await this.readState(id)).board;
|
|
361
|
+
if (board.deletedAt !== void 0) {
|
|
362
|
+
await this.publishNotifications(id, this.id());
|
|
363
|
+
continue;
|
|
364
|
+
}
|
|
361
365
|
await this.execute(board.id, { operationId: this.id(), expectedRevision: board.revision, command: { type: "scan" } });
|
|
362
366
|
} catch (error) {
|
|
363
|
-
if (!(error instanceof
|
|
367
|
+
if (!(error instanceof _chunkRSH6QSECcjs.KanbanError) || !["REVISION_CONFLICT", "FORBIDDEN"].includes(error.code)) errors.push(error);
|
|
364
368
|
}
|
|
365
369
|
}
|
|
366
370
|
if (errors.length) throw new AggregateError(errors, "KANBAN_SCAN_FAILED");
|
|
@@ -368,11 +372,11 @@ var KanbanModule = (_class = class {
|
|
|
368
372
|
async verifyRelease(board, command) {
|
|
369
373
|
if (command.type !== "release-item") return;
|
|
370
374
|
const item = board.items.find((i) => i.id === command.itemId);
|
|
371
|
-
|
|
372
|
-
const own =
|
|
373
|
-
const coordinator = _optionalChain([board, 'access',
|
|
374
|
-
|
|
375
|
-
if (!(own && actor.kind === "human"))
|
|
375
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, _optionalChain([item, 'optionalAccess', _78 => _78.owner]) && item.owner.token === command.token, "OWNER_MISMATCH");
|
|
376
|
+
const own = _chunkRBOER6EWcjs.sameOwner.call(void 0, item.owner, this.actor), actor = _chunkRBOER6EWcjs.principal.call(void 0, this.actor);
|
|
377
|
+
const coordinator = _optionalChain([board, 'access', _79 => _79.members, 'optionalAccess', _80 => _80.some, 'call', _81 => _81((m) => _chunkRBOER6EWcjs.principalKey.call(void 0, m) === _chunkRBOER6EWcjs.principalKey.call(void 0, actor) && _optionalChain([m, 'access', _82 => _82.roles, 'optionalAccess', _83 => _83.includes, 'call', _84 => _84("coordinator")]))]);
|
|
378
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, own || coordinator, "OWNER_MISMATCH");
|
|
379
|
+
if (!(own && actor.kind === "human")) _chunkRBOER6EWcjs.requireValue.call(void 0, await _optionalChain([this, 'access', _85 => _85.options, 'access', _86 => _86.verifyRelease, 'optionalCall', _87 => _87({ actor: this.actor, board: structuredClone(board), item: structuredClone(item) })]), "EXECUTION_NOT_SETTLED");
|
|
376
380
|
}
|
|
377
381
|
async publishNotifications(boardId, operationId) {
|
|
378
382
|
if (!this.options.onCommitted) return;
|
|
@@ -385,17 +389,17 @@ var KanbanModule = (_class = class {
|
|
|
385
389
|
}
|
|
386
390
|
}
|
|
387
391
|
async readView(boardId) {
|
|
388
|
-
|
|
389
|
-
if (!this.options.store.view) return
|
|
392
|
+
_chunkRBOER6EWcjs.identity.call(void 0, boardId);
|
|
393
|
+
if (!this.options.store.view) return _chunkEYTVC2H5cjs.viewFromState.call(void 0, await this.readState(boardId));
|
|
390
394
|
const view = await this.options.store.view(boardId);
|
|
391
|
-
|
|
395
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, view, "BOARD_NOT_FOUND");
|
|
392
396
|
await this.authorize(view.state.board, "read");
|
|
393
397
|
return view;
|
|
394
398
|
}
|
|
395
399
|
async readState(boardId) {
|
|
396
|
-
|
|
400
|
+
_chunkRBOER6EWcjs.identity.call(void 0, boardId);
|
|
397
401
|
const state = await this.options.store.read(boardId);
|
|
398
|
-
|
|
402
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, state, "BOARD_NOT_FOUND");
|
|
399
403
|
await this.authorize(state.board, "read");
|
|
400
404
|
return state;
|
|
401
405
|
}
|
|
@@ -406,7 +410,7 @@ var KanbanModule = (_class = class {
|
|
|
406
410
|
const start = this.now();
|
|
407
411
|
if (this.stopping) {
|
|
408
412
|
this.log(operationId, boardId, stage, start, "failure", "SERVICE_STOPPING");
|
|
409
|
-
throw new (0,
|
|
413
|
+
throw new (0, _chunkRSH6QSECcjs.KanbanError)("SERVICE_STOPPING");
|
|
410
414
|
}
|
|
411
415
|
const operation = Promise.resolve().then(run);
|
|
412
416
|
this.pending.add(operation);
|
|
@@ -429,11 +433,11 @@ var KanbanModule = (_class = class {
|
|
|
429
433
|
}
|
|
430
434
|
}, _class);
|
|
431
435
|
function safeCode(error, fallback) {
|
|
432
|
-
const code = _optionalChain([error, 'optionalAccess',
|
|
436
|
+
const code = _optionalChain([error, 'optionalAccess', _88 => _88.code]);
|
|
433
437
|
return typeof code === "string" && /^[A-Z][A-Z0-9_]{0,79}$/.test(code) ? code : fallback;
|
|
434
438
|
}
|
|
435
439
|
|
|
436
440
|
|
|
437
441
|
|
|
438
442
|
exports.createKanbanModule = createKanbanModule;
|
|
439
|
-
//# sourceMappingURL=chunk-
|
|
443
|
+
//# sourceMappingURL=chunk-DINLR6E6.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/home/li/share/prj/x1/libraries/kanban/dist/chunk-DINLR6E6.cjs","../src/references.ts","../src/suggestions.ts","../src/queries.ts","../src/module.ts"],"names":["item","record"],"mappings":"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","file":"/home/li/share/prj/x1/libraries/kanban/dist/chunk-DINLR6E6.cjs","sourcesContent":[null,"import {kanbanReference, type KanbanReferenceTarget} from './contracts';\nimport type {KanbanReadView, KanbanStore} from './ports';\nimport {requireValue} from './rules';\n\nexport async function resolveReference(reference: string, store: KanbanStore, read: (id: string) => Promise<KanbanReadView>): Promise<KanbanReferenceTarget> {\n requireValue(typeof reference === 'string' && reference.length <= 100, 'INVALID_REFERENCE');\n const match = /^KB-([1-9]\\d*)(?:#([1-9]\\d*)|\\/(L|D)-([1-9]\\d*))?$/i.exec(reference.trim());\n requireValue(match && [match[1], match[2], match[4]].every(value => value === undefined || Number.isSafeInteger(Number(value))), 'INVALID_REFERENCE');\n const id = await store.boardId?.(Number(match[1])); requireValue(id, 'REFERENCE_NOT_FOUND');\n const view = await read(id), board = view.state.board;\n requireValue(board.number === Number(match[1]), 'INVALID_NUMBERING');\n const target: KanbanReferenceTarget = {boardId: id, scope: board.scope, reference: kanbanReference(board)};\n if (match[2]) {\n const item = [...view.items, ...(view.state.archiveIndex ?? [])].find(item => item.number === Number(match[2]));\n requireValue(item, 'REFERENCE_NOT_FOUND'); target.itemId = item.id; target.reference = kanbanReference(board, item);\n } else if (match[3]) {\n const record = view.records.find(record => record.kind === (match[3].toUpperCase() === 'L' ? 'log' : 'decision') && record.number === Number(match[4]));\n requireValue(record, 'REFERENCE_NOT_FOUND'); target.recordId = record.id; target.reference = kanbanReference(board, record);\n }\n return target;\n}\n","import {kanbanReference} from './contracts';\nimport type {KanbanSuggestion, KanbanSuggestionPage, KanbanSuggestionQuery} from './contracts';\nimport type {KanbanState} from './ports';\nimport {recordSummary} from './project-records';\nimport {catalog, terminal} from './planning';\nimport {workType} from './configuration';\nimport {identity, requireValue} from './rules';\n\nexport function validateSuggestionQuery(query: KanbanSuggestionQuery): number {\n requireValue(query && ['item', 'parent', 'dependency', 'area', 'milestone', 'decision', 'session'].includes(query.kind), 'INVALID_SUGGESTION_KIND');\n requireValue(query.search === undefined || typeof query.search === 'string' && query.search.length <= 256, 'INVALID_FILTER');\n const limit = query.limit ?? 20; requireValue(Number.isSafeInteger(limit) && limit > 0 && limit <= 50, 'INVALID_LIMIT');\n if (query.excludeItemId !== undefined) identity(query.excludeItemId);\n if (query.excludeIds !== undefined) {requireValue(Array.isArray(query.excludeIds) && query.excludeIds.length <= 100, 'INVALID_FILTER'); query.excludeIds.forEach(identity);}\n if (query.childKind !== undefined) identity(query.childKind);\n return limit;\n}\nexport function suggestionPage(revision: number, rows: KanbanSuggestion[], query: KanbanSuggestionQuery): KanbanSuggestionPage {\n const limit = validateSuggestionQuery(query), search = query.search?.trim().toLocaleLowerCase() ?? '';\n const matched = rows.filter(row => !query.excludeIds?.includes(row.id)).filter(row => `${row.id} ${row.label} ${row.detail ?? ''}`.toLocaleLowerCase().includes(search))\n .sort((a, b) => score(a.label, search) - score(b.label, search) || a.label.localeCompare(b.label) || a.id.localeCompare(b.id));\n return {revision, items: matched.slice(0, limit).map(row => ({id: row.id, label: row.label.slice(0, 256), ...(row.detail ? {detail: row.detail.slice(0, 512)} : {}), ...(row.status ? {status: row.status} : {}), ...(row.archived !== undefined ? {archived: row.archived} : {})})), hasMore: matched.length > limit};\n}\nconst score = (label: string, query: string) => label.toLocaleLowerCase() === query ? 0 : label.toLocaleLowerCase().startsWith(query) ? 1 : 2;\nexport function suggestFromState(state: KanbanState, query: KanbanSuggestionQuery, items = catalog(state), records = (state.records ?? []).map(recordSummary)): KanbanSuggestionPage {\n validateSuggestionQuery(query);\n if (query.kind === 'area' || query.kind === 'milestone') {\n const names = [...new Set(items.map(item => item.planning[query.kind as 'area' | 'milestone']).filter((name): name is string => !!name))];\n return suggestionPage(state.board.revision, names.map(name => ({id: name, label: name})), query);\n }\n if (query.kind === 'decision') return suggestionPage(state.board.revision, records\n .filter(record => record.kind === 'decision' && record.status === 'confirmed').map(record => ({id: record.id, label: record.title, detail: kanbanReference(state.board, record)})), query);\n if (query.kind === 'session') {\n const ids = new Set([...state.board.participants.map(p => p.sessionId), ...items.flatMap(item => item.sessionIds),\n ...records.flatMap(record => record.sessionIds)]);\n return suggestionPage(state.board.revision, [...ids].map(id => ({id, label: id})), query);\n }\n const blocked = query.kind === 'dependency' && query.excludeItemId ? dependents(items, query.excludeItemId) : new Set<string>();\n const rank = query.kind === 'parent' ? workType(state.board, query.childKind ?? state.board.defaultWorkType ?? 'task').rank : undefined;\n const rows = items.filter(item => item.id !== query.excludeItemId && !blocked.has(item.id)\n && (query.kind !== 'dependency' || item.status !== 'cancelled')\n && (rank === undefined || item.archivedAt === undefined && !terminal(item) && workType(state.board, item.planning.kind).rank < rank))\n .map(item => ({id: item.id, label: item.title, status: item.status, archived: item.archivedAt !== undefined,\n detail: [kanbanReference(state.board, item), item.planning.area, item.planning.milestone].filter(Boolean).join(' · ')}));\n return suggestionPage(state.board.revision, rows, query);\n}\nfunction dependents(items: import('./contracts').KanbanItemSummary[], id: string): Set<string> {\n const reverse = new Map<string, string[]>();\n for (const item of items) for (const dependency of item.planning.dependencies) reverse.set(dependency, [...(reverse.get(dependency) ?? []), item.id]);\n const result = new Set([id]), pending = [id];\n while (pending.length) for (const next of reverse.get(pending.pop()!) ?? []) if (!result.has(next)) {result.add(next); pending.push(next);}\n return result;\n}\n","import {projectKanbanTask} from './contracts/task-projection';\nimport {kanbanReference} from './contracts';\nimport type {KanbanItemPage, KanbanItemQuery, KanbanItemSummary, KanbanOverview} from './contracts';\nimport type {KanbanState} from './ports';\nimport {requireValue} from './rules';\nimport {executable} from './configuration';\nimport {catalog, limits, summary, terminal} from './planning';\n\nexport function queryItems(state: KanbanState, query: KanbanItemQuery = {}, all = catalog(state), now = Date.now()): KanbanItemPage {\n const {cursor, limit = 50, ...filters} = query;\n requireValue(Number.isSafeInteger(limit) && limit >= 1 && limit <= 200, 'INVALID_PAGE_SIZE');\n requireValue(['ready', 'backlog', 'in-progress', 'review', 'closed', 'proposed', 'archive', 'all'].includes(query.view ?? 'ready'), 'INVALID_VIEW');\n for (const field of ['area', 'milestone', 'parentId', 'kind', 'sessionId', 'search'] as const) if (filters[field] !== undefined) requireValue(typeof filters[field] === 'string' && filters[field]!.length <= 256, 'INVALID_FILTER');\n if (filters.reference) requireValue(typeof filters.reference.system === 'string' && typeof filters.reference.id === 'string' && filters.reference.system.length <= 256 && filters.reference.id.length <= 256, 'INVALID_REFERENCE_FILTER');\n const fingerprint = JSON.stringify(Object.fromEntries(Object.entries({...filters, view: filters.view ?? 'ready'}).sort(([a], [b]) => a.localeCompare(b)))), revision = state.board.revision;\n all = all.map(item => ({...item, task: projectKanbanTask(item, state.workflow, now, all)}));\n const matches = all.filter(item => matchesQuery(item, filters, state.board)).sort(filters.view === 'archive'\n ? (a, b) => (b.archivedAt ?? 0) - (a.archivedAt ?? 0) || a.id.localeCompare(b.id) : order);\n let start = 0;\n if (cursor) {\n requireValue(typeof cursor === 'string' && cursor.length <= 4000, 'INVALID_CURSOR');\n let decoded: {revision: number; after: string; filter: string};\n try {decoded = JSON.parse(cursor);} catch {requireValue(false, 'INVALID_CURSOR');}\n requireValue(decoded && decoded.filter === fingerprint, 'CURSOR_SCOPE_MISMATCH');\n requireValue(decoded.revision === revision, 'CURSOR_STALE');\n start = matches.findIndex(i => i.id === decoded.after) + 1; requireValue(start > 0, 'INVALID_CURSOR');\n }\n const progress = progressByParent(state, all);\n const items = matches.slice(start, start + limit).map(item => ({...item, ...(progress.has(item.id) ? {progress: progress.get(item.id)} : {})}));\n return {revision, total: matches.length, items, ...(start + items.length < matches.length ? {\n nextCursor: JSON.stringify({revision, after: items.at(-1)!.id, filter: fingerprint}),\n } : {})};\n}\nfunction order(a: KanbanItemSummary, b: KanbanItemSummary): number {\n return a.planning.priority - b.planning.priority || a.createdAt - b.createdAt || a.id.localeCompare(b.id);\n}\nfunction matchesQuery(item: KanbanItemSummary, query: Omit<KanbanItemQuery, 'cursor' | 'limit'>, board: KanbanState['board']): boolean {\n if (item.deletedAt !== undefined && !query.includeDeleted) return false;\n if (query.phase && item.task?.phase !== query.phase) return false;\n if (!matchesView(item, query.view ?? 'ready')) return false;\n for (const field of ['area', 'milestone', 'parentId', 'kind'] as const) if (query[field] !== undefined && item.planning[field] !== query[field]) return false;\n if (query.reference && !item.externalRefs?.some(r => r.system === query.reference!.system && r.id === query.reference!.id)) return false;\n if (query.sessionId && !item.sessionIds.includes(query.sessionId)) return false;\n if (query.search && !`${kanbanReference(board, item)} ${item.id} ${item.title} ${item.planning.area ?? ''}`.toLowerCase().includes(query.search.toLowerCase())) return false;\n return true;\n}\nfunction matchesView(item: KanbanItemSummary, view: KanbanItemQuery['view']): boolean {\n if (view === 'archive') return item.archivedAt !== undefined;\n if (view === 'all') return true;\n if (item.archivedAt !== undefined) return false;\n if (view === 'in-progress') return item.status === 'claimed' || item.status === 'review';\n if (view === 'closed') return terminal(item);\n return item.status === ({ready: 'open', backlog: 'backlog', review: 'review', proposed: 'proposed'} as Record<string, string>)[view!];\n}\nexport function overview(state: KanbanState, now: number, items = state.board.items.map(summary)): KanbanOverview {\n items = items.filter(item => item.deletedAt === undefined);\n const count = (status: string) => items.filter(i => i.status === status).length;\n const age = state.board.policy.backlogReviewMs;\n return {revision: state.board.revision, visible: items.length, active: items.filter(i => !terminal(i)).length, archived: state.archiveIndex?.length ?? 0, ready: count('open'),\n inProgress: count('claimed') + count('review'), backlog: count('backlog'), proposed: count('proposed'),\n closed: count('completed') + count('cancelled'), dueForReview: age ? items.filter(i => i.status === 'backlog' && now - i.updatedAt >= age).length : 0,\n limits: limits(state)};\n}\n\nfunction progressByParent(state: KanbanState, all: KanbanItemSummary[]): Map<string, NonNullable<KanbanItemSummary['progress']>> {\n const byId = new Map(all.map(i => [i.id, i]));\n const result = new Map<string, NonNullable<KanbanItemSummary['progress']>>();\n for (const item of all.filter(i => executable(state.board, i))) {\n let parent = item.planning.parentId; const seen = new Set<string>();\n while (parent && !seen.has(parent)) {\n seen.add(parent); const progress = result.get(parent) ?? {total: 0, completed: 0, cancelled: 0, inProgress: 0};\n progress.total++; if (item.status === 'completed') progress.completed++; if (item.status === 'cancelled') progress.cancelled++;\n if (item.status === 'claimed' || item.status === 'review') progress.inProgress++;\n result.set(parent, progress); parent = byId.get(parent)?.planning.parentId;\n }\n }\n return result;\n}\n","import {boardControlPhase} from './contracts/board-control';\nimport {projectKanbanTask} from './contracts/task-projection';\nimport {resolveReference} from './references';\nimport {suggestFromState, suggestionPage, validateSuggestionQuery} from './suggestions';\nimport {queryRecords} from './project-records';\nimport { randomUUID } from './utils';\nimport type { KanbanBoard, KanbanRequest, KanbanService, KanbanItemQuery, KanbanBoardInput } from './contracts';\nimport { KanbanError, type KanbanModuleOptions, type KanbanState } from './ports';\nimport { identity, requireValue } from './rules';\nimport {createBoardState} from './board';\nimport {normalizeActor, principal, principalKey, sameOwner} from './identity';\nimport {queryItems, overview} from './queries';\nimport {viewFromState} from './storage-codec';\nimport { reduce, related } from './reducer';\n\n/** Optional host-owned service; no timer or model calls are started implicitly. */\nexport function createKanbanModule(options: KanbanModuleOptions): KanbanModuleHandle { return new KanbanModule(options); }\nexport interface KanbanModuleHandle extends KanbanService {quiesce(): Promise<void>; dispose(): Promise<void>}\nclass KanbanModule implements KanbanService {\n private stopping = false;\n private readonly pending = new Set<Promise<unknown>>();\n async quiesce(): Promise<void> {this.stopping = true; await Promise.allSettled([...this.pending]);}\n async dispose(): Promise<void> {await this.quiesce();}\n private readonly now;\n private readonly id;\n private readonly actor;\n constructor(private readonly options: KanbanModuleOptions) {\n this.now = options.now ?? Date.now; this.id = options.id ?? randomUUID;\n this.actor = normalizeActor(options.actor);\n }\n workflow = (boardId: string) => this.guard(this.id(), boardId, 'workflow', async () => structuredClone((await this.readView(boardId)).state.workflow ?? {plans:{},dispatches:{},ready:[],completedPlans:[]}));\n resolve = (reference: string) => this.guard(this.id(), undefined, 'resolve', () => resolveReference(reference, this.options.store, id => this.readView(id)));\n suggest = (boardId: string, query: import('./contracts').KanbanSuggestionQuery) => this.guard(this.id(), boardId, 'suggest', async () => {\n const snapshot = structuredClone(query), limit = validateSuggestionQuery(snapshot), view = await this.readView(boardId), state = view.state;\n const suggestions = () => suggestFromState(state, snapshot, [...view.items, ...(state.archiveIndex ?? [])], view.records);\n if (!this.options.suggestions) return suggestions();\n const rows = await this.options.suggestions(structuredClone(state.board), snapshot.kind, snapshot.search?.trim() ?? '', limit + 1);\n if (rows === undefined) return suggestions();\n const known = suggestions().items.filter(row => !rows.some(entry => entry.id === row.id));\n return suggestionPage(state.board.revision, [...rows, ...known], snapshot);\n });\n records = (boardId: string, query?: import('./contracts').KanbanRecordQuery) => this.guard(this.id(), boardId, 'records', async () => {const view = await this.readView(boardId); return structuredClone(queryRecords(view.state, query, view.records));});\n record = (boardId: string, recordId: string) => this.guard(this.id(), boardId, 'record', async () => {\n identity(recordId); const record = (await this.readState(boardId)).records?.find(record => record.id === recordId);\n requireValue(record, 'RECORD_NOT_FOUND'); return structuredClone(record);\n });\n currentPrincipal = async () => structuredClone(principal(this.actor));\n create = (input: KanbanBoardInput): Promise<KanbanBoard> => {\n const snapshot = structuredClone(input);\n return this.guard(this.id(), snapshot.id, 'create', async () => {\n const initial = createBoardState(snapshot, this.actor, this.now()), board = initial.board;\n await this.authorize(board, 'create');\n const state = await this.options.store.update(board.id, `create:${board.id}`, JSON.stringify({ snapshot, actor: this.actor }), previous => {\n requireValue(!previous, 'BOARD_EXISTS'); return initial;\n });\n return structuredClone(state.board);\n });\n };\n read = (boardId: string): Promise<KanbanBoard> => this.guard(this.id(), boardId, 'read',\n async () => structuredClone((await this.readState(boardId)).board));\n catalog = () => this.guard(this.id(), undefined, 'catalog', async () => {\n const boards: import('./contracts').KanbanBoardSummary[] = [];\n for (const id of await this.options.store.ids()) {\n try {const view = await this.readView(id); if (view.state.board.deletedAt !== undefined) continue; boards.push({...view.state.board, executionPhase: boardControlPhase({...view.state.board, items: view.items}), items: view.items.filter(item => item.deletedAt === undefined).map(({id, title, number}) => ({id, title, ...(number === undefined ? {} : {number})}))});}\n catch (error) {if (!(error instanceof KanbanError) || error.code !== 'FORBIDDEN') throw error;}\n }\n return structuredClone(boards);\n });\n list = (): Promise<KanbanBoard[]> => this.guard(this.id(), undefined, 'list', async () => {\n const boards: KanbanBoard[] = [];\n for (const boardId of await this.options.store.ids()) {\n try { const board = (await this.readState(boardId)).board; if (board.deletedAt === undefined) boards.push(structuredClone(board)); }\n catch (error) { if (!(error instanceof KanbanError) || error.code !== 'FORBIDDEN') throw error; }\n }\n return boards;\n });\n execute = (boardId: string, input: KanbanRequest): Promise<KanbanBoard> => this.guard(input.operationId, boardId, `execute:${input.command.type}`, async () => {\n const request = structuredClone(input); identity(request.operationId);\n const state = await this.readState(boardId);\n await this.authorize(state.board, request.command.type, request.command);\n requireValue(state.board.deletedAt === undefined, 'BOARD_DELETED');\n if (request.command.type === 'delete-board') await this.options.verifyDeletion?.(structuredClone(state.board));\n await this.options.verifyLifecycle?.(structuredClone(state.board), request.command);\n await this.verifyRelease(state.board, request.command);\n const verifyStage = request.command.type === 'observe-execution' && request.command.outcome === 'succeeded' ? 'observe'\n : request.command.type === 'accept-execution' && request.command.accept ? 'accept' : undefined;\n if (verifyStage && 'dispatchId' in request.command) {\n const dispatch = state.workflow?.dispatches[request.command.dispatchId]; requireValue(dispatch, 'DISPATCH_NOT_FOUND');\n const outputs = request.command.type === 'observe-execution' ? request.command.outputs : dispatch.outputs;\n if (outputs?.length) requireValue(await this.options.verifyOutputs?.({stage: verifyStage, board: state.board, itemId: dispatch.itemId,\n dispatchId: dispatch.id, outputs: structuredClone(outputs)}), 'OUTPUT_VERIFICATION_REQUIRED');\n }\n const restore = request.command.type === 'restore-item' ? await this.options.store.archived(boardId, request.command.itemId) : undefined;\n const result = await this.options.store.update(boardId, request.operationId, JSON.stringify({ actor: this.actor, request }), current => {\n requireValue(current && current.board.revision === state.board.revision, 'REVISION_CONFLICT');\n requireValue(current.board.revision === request.expectedRevision, 'REVISION_CONFLICT');\n if (restore) current.restore = restore;\n return reduce(current, request.command, this.actor, request.operationId, this.now(), this.id());\n });\n await this.publishNotifications(boardId, request.operationId);\n return structuredClone(result.board);\n });\n events = (boardId: string, after = 0, limit = 100) => this.guard(this.id(), boardId, 'events', async () => {\n requireValue(Number.isSafeInteger(after) && after >= 0 && Number.isSafeInteger(limit) && limit > 0 && limit <= 500, 'INVALID_CURSOR');\n const {state} = await this.readView(boardId);\n return this.options.store.events(boardId, after, limit, state.sequence);\n });\n query = (boardId: string, query?: KanbanItemQuery) => this.guard(this.id(), boardId, 'query', async () => {const view = await this.readView(boardId); return structuredClone(queryItems(view.state, query, [...view.items, ...(view.state.archiveIndex ?? [])], this.now()));});\n overview = (boardId: string) => this.guard(this.id(), boardId, 'overview', async () => {const view = await this.readView(boardId); return overview(view.state, this.now(), view.items);});\n item = (boardId: string, itemId: string) => this.guard(this.id(), boardId, 'item', async () => {\n identity(itemId); const state = await this.readState(boardId), item = state.board.items.find(i => i.id === itemId);\n if (item) return {item: structuredClone(item),task:projectKanbanTask(item,state.workflow,this.now(),[...state.board.items,...state.archiveIndex??[]])};\n requireValue(state.archiveIndex?.some(i => i.id === itemId), 'ITEM_NOT_FOUND');\n const record = await this.options.store.archived(boardId, itemId); requireValue(record, 'REVISION_CONFLICT');\n return {item: structuredClone(record.item), task:projectKanbanTask(record.item,state.workflow,this.now(),state.archiveIndex), archive: {archivedAt: record.archivedAt, reason: record.reason}};\n });\n related = (sessionId: string): Promise<KanbanBoard[]> => this.guard(this.id(), undefined, 'related', async () => {\n identity(sessionId); const result: KanbanBoard[] = [];\n for (const board of await this.list()) {\n const state = await this.readState(board.id);\n if (related(board).includes(sessionId) || state.records?.some(record => record.sources.some(source => source.sessionId === sessionId)) || state.archiveIndex?.some(i => i.sessionIds.includes(sessionId))) result.push(board);\n }\n return result;\n });\n scan = (): Promise<void> => this.guard(this.id(), undefined, 'scan', async () => {\n const errors: unknown[] = [];\n for (const id of await this.options.store.ids()) {\n try {\n const board = (await this.readState(id)).board;\n if (board.deletedAt !== undefined) {await this.publishNotifications(id,this.id()); continue;}\n await this.execute(board.id, { operationId: this.id(), expectedRevision: board.revision, command: { type: 'scan' } });\n }\n catch (error) {\n if (!(error instanceof KanbanError) || !['REVISION_CONFLICT','FORBIDDEN'].includes(error.code)) errors.push(error);\n }\n }\n if (errors.length) throw new AggregateError(errors, 'KANBAN_SCAN_FAILED');\n });\n private async verifyRelease(board: KanbanBoard, command: KanbanRequest['command']): Promise<void> {\n if (command.type !== 'release-item') return;\n const item = board.items.find(i => i.id === command.itemId); requireValue(item?.owner && item.owner.token === command.token, 'OWNER_MISMATCH');\n const own = sameOwner(item.owner, this.actor), actor = principal(this.actor);\n const coordinator = board.members?.some(m => principalKey(m) === principalKey(actor) && m.roles?.includes('coordinator'));\n requireValue(own || coordinator, 'OWNER_MISMATCH');\n if (!(own && actor.kind === 'human')) requireValue(await this.options.verifyRelease?.({actor: this.actor, board: structuredClone(board), item: structuredClone(item)}), 'EXECUTION_NOT_SETTLED');\n }\n private async publishNotifications(boardId: string, operationId: string): Promise<void> {\n if (!this.options.onCommitted) return;\n const started = this.now();\n try {await this.options.onCommitted(boardId, this, this.now()); this.log(operationId, boardId, 'notify', started, 'success');}\n catch (error) {this.log(operationId, boardId, 'notify', started, 'failure', safeCode(error, 'NOTIFICATION_PROJECTION_FAILED'));}\n }\n private async readView(boardId: string) {\n identity(boardId);\n if (!this.options.store.view) return viewFromState(await this.readState(boardId));\n const view = await this.options.store.view(boardId); requireValue(view, 'BOARD_NOT_FOUND');\n await this.authorize(view.state.board, 'read'); return view;\n }\n private async readState(boardId: string): Promise<KanbanState> {\n identity(boardId); const state = await this.options.store.read(boardId); requireValue(state, 'BOARD_NOT_FOUND');\n await this.authorize(state.board, 'read'); return state;\n }\n private authorize(board: KanbanBoard, action: Parameters<KanbanModuleOptions['authorize']>[0]['action'], command?: KanbanRequest['command']) {\n return this.options.authorize({ actor: structuredClone(this.actor), board: structuredClone(board), action, command: structuredClone(command) });\n }\n private async guard<T>(operationId: string, boardId: string | undefined, stage: string, run: () => Promise<T>): Promise<T> {\n const start = this.now();\n if (this.stopping) {this.log(operationId,boardId,stage,start,'failure','SERVICE_STOPPING'); throw new KanbanError('SERVICE_STOPPING');}\n const operation = Promise.resolve().then(run); this.pending.add(operation);\n try { const result = await operation; this.log(operationId, boardId, stage, start, 'success'); return result; }\n catch (error) {\n this.log(operationId, boardId, stage, start, 'failure', safeCode(error, 'PORT_FAILURE')); throw error;\n } finally {this.pending.delete(operation);}\n }\n private log(operationId: string, boardId: string | undefined, stage: string, start: number, result: 'success' | 'failure', code?: string): void {\n try { this.options.log({ operationId, boardId, stage, result, code, durationMs: this.now() - start }); }\n catch { /* Diagnostics cannot undo a commit. */ }\n }\n}\n\nfunction safeCode(error: unknown, fallback: string): string {\n const code = (error as {code?: unknown})?.code;\n return typeof code === 'string' && /^[A-Z][A-Z0-9_]{0,79}$/.test(code) ? code : fallback;\n}\n"]}
|