@nestos/kanban 0.0.0-stage → 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 +165 -2
- package/dist/activity-BbC4sgKL.d.cts +258 -0
- package/dist/activity-Czlan5xW.d.ts +258 -0
- 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 +16 -0
- package/dist/activity.cjs.map +1 -0
- package/dist/activity.d.cts +12 -0
- package/dist/activity.d.ts +12 -0
- package/dist/activity.js +16 -0
- package/dist/activity.js.map +1 -0
- package/dist/chunk-3JYLJPE5.js +95 -0
- package/dist/chunk-3JYLJPE5.js.map +1 -0
- package/dist/chunk-3LEIHB7Y.js +221 -0
- package/dist/chunk-3LEIHB7Y.js.map +1 -0
- package/dist/chunk-4XF6LQSU.cjs +9 -0
- package/dist/chunk-4XF6LQSU.cjs.map +1 -0
- package/dist/chunk-5Q7WB63A.cjs +282 -0
- package/dist/chunk-5Q7WB63A.cjs.map +1 -0
- package/dist/chunk-7KDOTBRX.cjs +58 -0
- package/dist/chunk-7KDOTBRX.cjs.map +1 -0
- package/dist/chunk-AHHEGTUA.js +148 -0
- package/dist/chunk-AHHEGTUA.js.map +1 -0
- package/dist/chunk-AOHQCX7K.cjs +95 -0
- package/dist/chunk-AOHQCX7K.cjs.map +1 -0
- package/dist/chunk-DINLR6E6.cjs +443 -0
- package/dist/chunk-DINLR6E6.cjs.map +1 -0
- package/dist/chunk-EYTVC2H5.cjs +1612 -0
- 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-KH3WF3K4.js +443 -0
- package/dist/chunk-KH3WF3K4.js.map +1 -0
- package/dist/chunk-M35X5PHO.js +196 -0
- 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-RBOER6EW.cjs +221 -0
- package/dist/chunk-RBOER6EW.cjs.map +1 -0
- package/dist/chunk-RQP77ZTY.js +9 -0
- package/dist/chunk-RQP77ZTY.js.map +1 -0
- package/dist/chunk-RSH6QSEC.cjs +196 -0
- package/dist/chunk-RSH6QSEC.cjs.map +1 -0
- package/dist/chunk-VMRDXOLX.cjs +148 -0
- package/dist/chunk-VMRDXOLX.cjs.map +1 -0
- package/dist/chunk-X4UHZX6F.js +58 -0
- package/dist/chunk-X4UHZX6F.js.map +1 -0
- package/dist/chunk-XBSGUVCY.cjs +382 -0
- package/dist/chunk-XBSGUVCY.cjs.map +1 -0
- package/dist/chunk-XKDZHAUE.js +1612 -0
- 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-C5aJZFlw.d.cts +35 -0
- package/dist/content-hLH5BNud.d.ts +35 -0
- package/dist/contracts/index.cjs +31 -0
- package/dist/contracts/index.cjs.map +1 -0
- package/dist/contracts/index.d.cts +5 -0
- package/dist/contracts/index.d.ts +5 -0
- package/dist/contracts/index.js +31 -0
- package/dist/contracts/index.js.map +1 -0
- package/dist/discovery-9E-LfwIw.d.cts +61 -0
- package/dist/discovery-D60yrjej.d.ts +61 -0
- package/dist/discovery.cjs +377 -0
- package/dist/discovery.cjs.map +1 -0
- package/dist/discovery.d.cts +22 -0
- package/dist/discovery.d.ts +22 -0
- package/dist/discovery.js +377 -0
- package/dist/discovery.js.map +1 -0
- package/dist/execution-bridge-fpCnH6z5.d.cts +52 -0
- package/dist/execution-bridge-rk0uVy_n.d.ts +52 -0
- package/dist/execution.cjs +18 -0
- package/dist/execution.cjs.map +1 -0
- package/dist/execution.d.cts +42 -0
- package/dist/execution.d.ts +42 -0
- package/dist/execution.js +18 -0
- package/dist/execution.js.map +1 -0
- package/dist/index.cjs +74 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +54 -0
- package/dist/index.d.ts +54 -0
- package/dist/index.js +74 -0
- package/dist/index.js.map +1 -0
- package/dist/module-CYfE7YhM.d.ts +11 -0
- package/dist/module-Ca9L3qCn.d.cts +11 -0
- package/dist/planning-CHrOqQ6b.d.cts +879 -0
- package/dist/planning-CHrOqQ6b.d.ts +879 -0
- package/dist/ports-B0McVg7B.d.ts +143 -0
- package/dist/ports-BeGO1VRI.d.cts +49 -0
- package/dist/ports-GQy0x-RI.d.cts +143 -0
- 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 +21 -0
- package/dist/storage.cjs.map +1 -0
- package/dist/storage.d.cts +71 -0
- package/dist/storage.d.ts +71 -0
- package/dist/storage.js +21 -0
- package/dist/storage.js.map +1 -0
- package/dist/store-DPwHzGiz.d.cts +28 -0
- package/dist/store-DgdrPCV9.d.ts +28 -0
- 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 +143 -4
|
@@ -0,0 +1,1612 @@
|
|
|
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 _chunk4XF6LQSUcjs = require('./chunk-4XF6LQSU.cjs');
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
var _chunkRBOER6EWcjs = require('./chunk-RBOER6EW.cjs');
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
var _chunk7KDOTBRXcjs = require('./chunk-7KDOTBRX.cjs');
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
var _chunkRSH6QSECcjs = require('./chunk-RSH6QSEC.cjs');
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
var _chunkAOHQCX7Kcjs = require('./chunk-AOHQCX7K.cjs');
|
|
39
|
+
|
|
40
|
+
// src/planning.ts
|
|
41
|
+
function plan(item) {
|
|
42
|
+
return _nullishCoalesce(item.planning, () => ( { kind: "task", priority: 2, dependencies: [], references: [] }));
|
|
43
|
+
}
|
|
44
|
+
function summary(item) {
|
|
45
|
+
return {
|
|
46
|
+
deletedAt: item.deletedAt,
|
|
47
|
+
launch: item.launch,
|
|
48
|
+
analysis: item.analysis,
|
|
49
|
+
control: item.control,
|
|
50
|
+
issues: item.issues,
|
|
51
|
+
blocked: item.blocked,
|
|
52
|
+
id: item.id,
|
|
53
|
+
number: item.number,
|
|
54
|
+
title: item.title,
|
|
55
|
+
status: item.status,
|
|
56
|
+
revision: item.revision,
|
|
57
|
+
createdAt: item.createdAt,
|
|
58
|
+
updatedAt: item.updatedAt,
|
|
59
|
+
discoveryFingerprint: _optionalChain([item, 'access', _ => _.origin, 'optionalAccess', _2 => _2.fingerprint]),
|
|
60
|
+
pendingAmendments: _optionalChain([item, 'access', _3 => _3.amendments, 'optionalAccess', _4 => _4.filter, 'call', _5 => _5((proposal) => proposal.status === "pending"), 'access', _6 => _6.length]),
|
|
61
|
+
externalRefs: item.externalRefs,
|
|
62
|
+
closedAt: item.closedAt,
|
|
63
|
+
planning: plan(item),
|
|
64
|
+
sessionIds: item.participants.map((p) => p.sessionId)
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function terminal(item) {
|
|
68
|
+
return item.status === "completed" || item.status === "cancelled";
|
|
69
|
+
}
|
|
70
|
+
function catalog(state) {
|
|
71
|
+
return [...state.board.items.map(summary), ..._nullishCoalesce(state.archiveIndex, () => ( []))];
|
|
72
|
+
}
|
|
73
|
+
function limits(state) {
|
|
74
|
+
const p = state.board.policy;
|
|
75
|
+
return { ready: _nullishCoalesce(p.maxReady, () => ( 20)), inProgress: _nullishCoalesce(p.maxInProgress, () => ( 3)), perAgent: _nullishCoalesce(_nullishCoalesce(p.maxInProgressPerAssignee, () => ( p.maxInProgressPerAgent)), () => ( 1)), perAssignee: _nullishCoalesce(_nullishCoalesce(p.maxInProgressPerAssignee, () => ( p.maxInProgressPerAgent)), () => ( 1)) };
|
|
76
|
+
}
|
|
77
|
+
function validatePlan(state, item, value) {
|
|
78
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, typeof value.kind === "string" && Number.isInteger(value.priority) && value.priority >= 0 && value.priority <= 4, "INVALID_PLANNING");
|
|
79
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, Array.isArray(value.dependencies) && value.dependencies.length <= 100 && Array.isArray(value.references) && value.references.length <= 100, "PLANNING_LIMIT");
|
|
80
|
+
value.dependencies.forEach(_chunkRBOER6EWcjs.identity);
|
|
81
|
+
value.references.forEach(_chunkRBOER6EWcjs.text);
|
|
82
|
+
if (value.area !== void 0) _chunkRBOER6EWcjs.identity.call(void 0, value.area);
|
|
83
|
+
if (value.milestone !== void 0) _chunkRBOER6EWcjs.identity.call(void 0, value.milestone);
|
|
84
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, value.execution === void 0 || ["direct", "children"].includes(value.execution), "INVALID_EXECUTION_MODE");
|
|
85
|
+
const type = _chunkRBOER6EWcjs.workType.call(void 0, state.board, value.kind);
|
|
86
|
+
if (value.dueAt !== void 0) _chunkRBOER6EWcjs.requireValue.call(void 0, Number.isFinite(value.dueAt) && value.dueAt >= 0, "INVALID_DUE_DATE");
|
|
87
|
+
const all = catalog(state), parent = all.find((i) => i.id === value.parentId);
|
|
88
|
+
if (value.parentId) {
|
|
89
|
+
_chunkRBOER6EWcjs.identity.call(void 0, value.parentId);
|
|
90
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, parent && !parent.archivedAt && !parent.deletedAt && !terminal(parent) && _optionalChain([parent, 'access', _7 => _7.control, 'optionalAccess', _8 => _8.action]) !== "cancel" && !["claimed", "review"].includes(parent.status), "PARENT_UNAVAILABLE");
|
|
91
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, parent.id !== item.id && _chunkRBOER6EWcjs.workType.call(void 0, state.board, parent.planning.kind).rank < type.rank, "INVALID_PARENT_KIND");
|
|
92
|
+
}
|
|
93
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, value.execution === "children" || !all.some((child) => child.planning.parentId === item.id), "CHILDREN_REQUIRE_AGGREGATION");
|
|
94
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !all.some((child) => child.planning.parentId === item.id && _chunkRBOER6EWcjs.workType.call(void 0, state.board, child.planning.kind).rank <= type.rank), "INVALID_CHILD_KIND");
|
|
95
|
+
for (const id of value.dependencies) _chunkRBOER6EWcjs.requireValue.call(void 0, id !== item.id && all.some((i) => i.id === id), "INVALID_DEPENDENCY");
|
|
96
|
+
const visited = /* @__PURE__ */ new Set(), pending = [...value.dependencies];
|
|
97
|
+
while (pending.length) {
|
|
98
|
+
const id = pending.pop();
|
|
99
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, id !== item.id, "DEPENDENCY_CYCLE");
|
|
100
|
+
if (visited.has(id)) continue;
|
|
101
|
+
visited.add(id);
|
|
102
|
+
pending.push(..._nullishCoalesce(_optionalChain([all, 'access', _9 => _9.find, 'call', _10 => _10((i) => i.id === id), 'optionalAccess', _11 => _11.planning, 'access', _12 => _12.dependencies]), () => ( [])));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function assertReady(state, item) {
|
|
106
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !state.board.lifecycle, "BOARD_STOPPING");
|
|
107
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !_optionalChain([state, 'access', _13 => _13.board, 'access', _14 => _14.executionControl, 'optionalAccess', _15 => _15.paused]), "BOARD_EXECUTION_PAUSED");
|
|
108
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, _chunkRBOER6EWcjs.executable.call(void 0, state.board, item), "PLAN_NOT_EXECUTABLE");
|
|
109
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !item.blocked, "ITEM_BLOCKED");
|
|
110
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !item.control || item.control.action === "resume" && item.control.state === "resumed", "TASK_CONTROL_PENDING");
|
|
111
|
+
const all = catalog(state);
|
|
112
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, plan(item).dependencies.every((id) => _optionalChain([all, 'access', _16 => _16.find, 'call', _17 => _17((i) => i.id === id), 'optionalAccess', _18 => _18.status]) === "completed"), "DEPENDENCIES_UNFINISHED");
|
|
113
|
+
}
|
|
114
|
+
function setStage(state, item, stage, now) {
|
|
115
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, ["proposed", "backlog", "open"].includes(item.status), "ITEM_NOT_PLANNABLE");
|
|
116
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, stage === "backlog" || stage === "open", "INVALID_STAGE");
|
|
117
|
+
if (stage === "open") {
|
|
118
|
+
assertReady(state, item);
|
|
119
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, item.status === "open" || state.board.items.filter((i) => i.status === "open").length < limits(state).ready, "READY_LIMIT");
|
|
120
|
+
}
|
|
121
|
+
item.status = stage;
|
|
122
|
+
item.readyAt = now;
|
|
123
|
+
item.updatedAt = now;
|
|
124
|
+
item.revision++;
|
|
125
|
+
}
|
|
126
|
+
function automaticStage(state, item) {
|
|
127
|
+
const all = catalog(state);
|
|
128
|
+
const dependenciesComplete = plan(item).dependencies.every((id) => _optionalChain([all, 'access', _19 => _19.find, 'call', _20 => _20((i) => i.id === id), 'optionalAccess', _21 => _21.status]) === "completed");
|
|
129
|
+
return _chunkRBOER6EWcjs.executable.call(void 0, state.board, item) && !item.blocked && dependenciesComplete && state.board.items.filter((i) => i.status === "open").length < limits(state).ready ? "open" : "backlog";
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// src/amendments.ts
|
|
133
|
+
var textOf = (item) => ({ title: item.title, responsibility: item.responsibility, acceptance: item.acceptance });
|
|
134
|
+
var textDigest = (item) => _chunkRSH6QSECcjs.sha256HexSync.call(void 0, JSON.stringify(textOf(item)));
|
|
135
|
+
function workFingerprint(item) {
|
|
136
|
+
const planning = plan(item);
|
|
137
|
+
return _chunkRSH6QSECcjs.sha256HexSync.call(void 0, JSON.stringify({
|
|
138
|
+
text: textOf(item),
|
|
139
|
+
kind: planning.kind,
|
|
140
|
+
parentId: _nullishCoalesce(planning.parentId, () => ( null)),
|
|
141
|
+
area: _nullishCoalesce(planning.area, () => ( null)),
|
|
142
|
+
milestone: _nullishCoalesce(planning.milestone, () => ( null)),
|
|
143
|
+
priority: planning.priority,
|
|
144
|
+
dependencies: [...planning.dependencies].sort(),
|
|
145
|
+
dueAt: _nullishCoalesce(planning.dueAt, () => ( null))
|
|
146
|
+
}));
|
|
147
|
+
}
|
|
148
|
+
function validateSources(sources) {
|
|
149
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, Array.isArray(sources) && sources.length <= 100, "SOURCE_LIMIT");
|
|
150
|
+
for (const source of sources) {
|
|
151
|
+
_chunkRBOER6EWcjs.identity.call(void 0, source.sessionId);
|
|
152
|
+
_chunkRBOER6EWcjs.identity.call(void 0, source.messageId);
|
|
153
|
+
_chunkRBOER6EWcjs.identity.call(void 0, source.revision);
|
|
154
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, source.role === "user" || source.role === "assistant", "INVALID_SOURCE");
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
function proposeAmendment(item, change, actor, now, runId) {
|
|
158
|
+
_chunkRBOER6EWcjs.text.call(void 0, change.title);
|
|
159
|
+
_chunkRBOER6EWcjs.text.call(void 0, change.responsibility);
|
|
160
|
+
_chunkRBOER6EWcjs.text.call(void 0, change.acceptance);
|
|
161
|
+
validateSources(change.sources);
|
|
162
|
+
const proposed = textOf(change), fingerprint = textDigest(proposed);
|
|
163
|
+
if (textDigest(item) === fingerprint || _optionalChain([item, 'access', _22 => _22.amendments, 'optionalAccess', _23 => _23.some, 'call', _24 => _24((p) => p.fingerprint === fingerprint)])) return;
|
|
164
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, (_nullishCoalesce(_optionalChain([item, 'access', _25 => _25.amendments, 'optionalAccess', _26 => _26.length]), () => ( 0))) < 20, "AMENDMENT_LIMIT");
|
|
165
|
+
(item.amendments ??= []).push({
|
|
166
|
+
runId,
|
|
167
|
+
id: `amendment-${_chunkRSH6QSECcjs.sha256HexSync.call(void 0, JSON.stringify([runId, item.id, fingerprint]))}`,
|
|
168
|
+
fingerprint,
|
|
169
|
+
baseRevision: item.revision,
|
|
170
|
+
baseDigest: textDigest(item),
|
|
171
|
+
proposed,
|
|
172
|
+
proposedBy: _chunkRBOER6EWcjs.principal.call(void 0, actor),
|
|
173
|
+
sources: structuredClone(change.sources),
|
|
174
|
+
createdAt: now,
|
|
175
|
+
status: "pending"
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
function requireReviewer(board, actor) {
|
|
179
|
+
const key = _chunkRBOER6EWcjs.principalKey.call(void 0, _chunkRBOER6EWcjs.principal.call(void 0, actor));
|
|
180
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0,
|
|
181
|
+
_optionalChain([board, 'access', _27 => _27.members, 'optionalAccess', _28 => _28.some, 'call', _29 => _29((m) => _chunkRBOER6EWcjs.principalKey.call(void 0, m) === key && _optionalChain([m, 'access', _30 => _30.roles, 'optionalAccess', _31 => _31.some, 'call', _32 => _32((role) => role === "coordinator" || role === "reviewer")]))]),
|
|
182
|
+
"REVIEWER_REQUIRED"
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
function reviewAmendment(board, command, actor, now) {
|
|
186
|
+
requireReviewer(board, actor);
|
|
187
|
+
const item = board.items.find((i) => i.id === command.itemId), proposal = _optionalChain([item, 'optionalAccess', _33 => _33.amendments, 'optionalAccess', _34 => _34.find, 'call', _35 => _35((p) => p.id === command.amendmentId)]);
|
|
188
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, item && _optionalChain([proposal, 'optionalAccess', _36 => _36.status]) === "pending", "AMENDMENT_NOT_PENDING");
|
|
189
|
+
if (command.accept) {
|
|
190
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, _chunkRBOER6EWcjs.principal.call(void 0, actor).kind === "human" || _chunkRBOER6EWcjs.principalKey.call(void 0, proposal.proposedBy) !== _chunkRBOER6EWcjs.principalKey.call(void 0, _chunkRBOER6EWcjs.principal.call(void 0, actor)), "INDEPENDENT_REVIEW_REQUIRED");
|
|
191
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, ["proposed", "backlog", "open"].includes(item.status), "ITEM_NOT_PLANNABLE");
|
|
192
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, textDigest(item) === proposal.baseDigest, "AMENDMENT_STALE");
|
|
193
|
+
Object.assign(item, proposal.proposed);
|
|
194
|
+
if (item.status === "open") {
|
|
195
|
+
item.status = "backlog";
|
|
196
|
+
item.readyAt = now;
|
|
197
|
+
}
|
|
198
|
+
} else {
|
|
199
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !!_optionalChain([command, 'access', _37 => _37.reason, 'optionalAccess', _38 => _38.trim, 'call', _39 => _39()]), "AMENDMENT_REASON_REQUIRED");
|
|
200
|
+
_chunkRBOER6EWcjs.text.call(void 0, command.reason);
|
|
201
|
+
}
|
|
202
|
+
proposal.status = command.accept ? "accepted" : "rejected";
|
|
203
|
+
proposal.reviewedAt = now;
|
|
204
|
+
proposal.reviewedBy = _chunkRBOER6EWcjs.principal.call(void 0, actor);
|
|
205
|
+
proposal.reason = command.reason;
|
|
206
|
+
item.updatedAt = now;
|
|
207
|
+
item.revision++;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// src/project-records.ts
|
|
211
|
+
function isRecordCommand(command) {
|
|
212
|
+
return ["append-record", "review-record", "link-record", "request-record-cancellation", "cancel-record", "delete-record"].includes(command.type);
|
|
213
|
+
}
|
|
214
|
+
function applyRecord(state, command, actor, now, forceDraft = false) {
|
|
215
|
+
if (command.type === "append-record") {
|
|
216
|
+
append(state, command, actor, now, forceDraft);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
const record = _optionalChain([state, 'access', _40 => _40.records, 'optionalAccess', _41 => _41.find, 'call', _42 => _42((record2) => record2.id === command.recordId)]);
|
|
220
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, record, "RECORD_NOT_FOUND");
|
|
221
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, record.deletedAt === void 0, "RECORD_DELETED");
|
|
222
|
+
if (command.type === "request-record-cancellation" || command.type === "cancel-record" || command.type === "delete-record") {
|
|
223
|
+
requireReviewer(state.board, actor);
|
|
224
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, _chunkRBOER6EWcjs.principal.call(void 0, actor).kind === "human", "FORBIDDEN");
|
|
225
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, record.kind === "decision", "DECISION_REQUIRED");
|
|
226
|
+
if (command.type !== "request-record-cancellation") _chunkRBOER6EWcjs.requireValue.call(void 0, record.itemIds.every((id) => {
|
|
227
|
+
const item = _nullishCoalesce(state.board.items.find((i) => i.id === id), () => ( _optionalChain([state, 'access', _43 => _43.archiveIndex, 'optionalAccess', _44 => _44.find, 'call', _45 => _45((i) => i.id === id)])));
|
|
228
|
+
return item && ["completed", "cancelled"].includes(item.status);
|
|
229
|
+
}), "RECORD_EXECUTION_UNSETTLED");
|
|
230
|
+
if (command.type === "request-record-cancellation") record.status = record.status === "cancelled" ? "cancelled" : "cancelling";
|
|
231
|
+
else if (command.type === "cancel-record") record.status = "cancelled";
|
|
232
|
+
else {
|
|
233
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, ["cancelled", "rejected", "superseded"].includes(record.status), "RECORD_CANCEL_REQUIRED");
|
|
234
|
+
record.deletedAt = now;
|
|
235
|
+
}
|
|
236
|
+
} else if (command.type === "link-record") {
|
|
237
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !["cancelling", "cancelled"].includes(record.status), "RECORD_CANCELLING");
|
|
238
|
+
validateItems(state, [command.itemId]);
|
|
239
|
+
if (!record.itemIds.includes(command.itemId)) {
|
|
240
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, record.itemIds.length < 100, "RECORD_LINK_LIMIT");
|
|
241
|
+
record.itemIds.push(command.itemId);
|
|
242
|
+
}
|
|
243
|
+
} else {
|
|
244
|
+
requireReviewer(state.board, actor);
|
|
245
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, record.status === "draft", "RECORD_NOT_DRAFT");
|
|
246
|
+
if (command.accept) {
|
|
247
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, _chunkRBOER6EWcjs.principal.call(void 0, actor).kind === "human" || _chunkRBOER6EWcjs.principalKey.call(void 0, record.author) !== _chunkRBOER6EWcjs.principalKey.call(void 0, _chunkRBOER6EWcjs.principal.call(void 0, actor)), "INDEPENDENT_REVIEW_REQUIRED");
|
|
248
|
+
supersede(state, record, now);
|
|
249
|
+
record.status = "confirmed";
|
|
250
|
+
} else record.status = "rejected";
|
|
251
|
+
record.reviewedBy = _chunkRBOER6EWcjs.principal.call(void 0, actor);
|
|
252
|
+
}
|
|
253
|
+
record.updatedAt = now;
|
|
254
|
+
record.revision++;
|
|
255
|
+
}
|
|
256
|
+
function append(state, command, actor, now, forceDraft) {
|
|
257
|
+
validateSources(command.record.sources);
|
|
258
|
+
const { id, kind, title, content, rationale, itemIds, sources, supersedes, coordination, externalRefs } = command.record;
|
|
259
|
+
const input = structuredClone({ id, kind, title, content, rationale, itemIds, sources: sources.map((source) => ({ sessionId: source.sessionId, messageId: source.messageId, revision: source.revision, role: source.role })), supersedes, ...coordination ? { coordination } : {}, ...externalRefs ? { externalRefs } : {} });
|
|
260
|
+
_chunkRBOER6EWcjs.identity.call(void 0, input.id);
|
|
261
|
+
_chunkRBOER6EWcjs.text.call(void 0, input.title);
|
|
262
|
+
_chunkRBOER6EWcjs.text.call(void 0, input.content);
|
|
263
|
+
validateRecordReferences(externalRefs);
|
|
264
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, input.kind === "log" || input.kind === "decision", "INVALID_RECORD_KIND");
|
|
265
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !_optionalChain([state, 'access', _46 => _46.records, 'optionalAccess', _47 => _47.some, 'call', _48 => _48((record) => record.id === input.id)]), "RECORD_EXISTS");
|
|
266
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, (_nullishCoalesce(_optionalChain([state, 'access', _49 => _49.records, 'optionalAccess', _50 => _50.length]), () => ( 0))) < 200, "RECORD_LIMIT");
|
|
267
|
+
validateItems(state, input.itemIds);
|
|
268
|
+
validateSources(input.sources);
|
|
269
|
+
if (input.rationale !== void 0) _chunkRBOER6EWcjs.text.call(void 0, input.rationale);
|
|
270
|
+
if (input.kind === "decision") _chunkRBOER6EWcjs.text.call(void 0, _nullishCoalesce(input.rationale, () => ( "")));
|
|
271
|
+
if (coordination) validateCoordination(state, input);
|
|
272
|
+
if (input.supersedes) {
|
|
273
|
+
_chunkRBOER6EWcjs.identity.call(void 0, input.supersedes);
|
|
274
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, input.kind === "decision" && input.supersedes !== input.id && _optionalChain([state, 'access', _51 => _51.records, 'optionalAccess', _52 => _52.some, 'call', _53 => _53((record) => record.id === input.supersedes && record.kind === "decision" && record.status === "confirmed")]), "INVALID_SUPERSEDED_RECORD");
|
|
275
|
+
}
|
|
276
|
+
const author = _chunkRBOER6EWcjs.principal.call(void 0, actor), manual = author.kind === "human" && !forceDraft;
|
|
277
|
+
(state.records ??= []).push({
|
|
278
|
+
...input,
|
|
279
|
+
author,
|
|
280
|
+
origin: manual ? "manual" : "flow",
|
|
281
|
+
status: manual && input.kind === "log" ? "confirmed" : "draft",
|
|
282
|
+
revision: 1,
|
|
283
|
+
createdAt: now,
|
|
284
|
+
updatedAt: now
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
function validateCoordination(state, input) {
|
|
288
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, input.kind === "decision", "DECISION_COORDINATION_ONLY");
|
|
289
|
+
for (const owner of [input.coordination.manager, input.coordination.executor].filter(Boolean)) {
|
|
290
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, owner && ["agent", "human", "service"].includes(owner.kind), "INVALID_PRINCIPAL");
|
|
291
|
+
_chunkRBOER6EWcjs.identity.call(void 0, owner.id);
|
|
292
|
+
const member = _optionalChain([state, 'access', _54 => _54.board, 'access', _55 => _55.members, 'optionalAccess', _56 => _56.find, 'call', _57 => _57((member2) => _chunkRBOER6EWcjs.principalKey.call(void 0, member2) === _chunkRBOER6EWcjs.principalKey.call(void 0, owner))]);
|
|
293
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, member, "ASSIGNEE_NOT_REGISTERED");
|
|
294
|
+
if (owner === input.coordination.manager) _chunkRBOER6EWcjs.requireValue.call(void 0, _optionalChain([member, 'access', _58 => _58.roles, 'optionalAccess', _59 => _59.includes, 'call', _60 => _60("coordinator")]), "COORDINATOR_REQUIRED");
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
function validateItems(state, ids) {
|
|
298
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, Array.isArray(ids) && ids.length <= 100 && new Set(ids).size === ids.length, "RECORD_LINK_LIMIT");
|
|
299
|
+
for (const id of ids) {
|
|
300
|
+
_chunkRBOER6EWcjs.identity.call(void 0, id);
|
|
301
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, state.board.items.some((item) => item.id === id) || _optionalChain([state, 'access', _61 => _61.archiveIndex, 'optionalAccess', _62 => _62.some, 'call', _63 => _63((item) => item.id === id)]), "ITEM_NOT_FOUND");
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
function supersede(state, record, now) {
|
|
305
|
+
if (!record.supersedes) return;
|
|
306
|
+
const previous = _optionalChain([state, 'access', _64 => _64.records, 'optionalAccess', _65 => _65.find, 'call', _66 => _66((entry) => entry.id === record.supersedes)]);
|
|
307
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, _optionalChain([previous, 'optionalAccess', _67 => _67.kind]) === "decision" && previous.status === "confirmed", "SUPERSEDED_RECORD_CHANGED");
|
|
308
|
+
previous.status = "superseded";
|
|
309
|
+
previous.supersededBy = record.id;
|
|
310
|
+
previous.revision++;
|
|
311
|
+
previous.updatedAt = now;
|
|
312
|
+
}
|
|
313
|
+
function queryRecords(state, query = {}, summaries = (_nullishCoalesce(state.records, () => ( []))).map(recordSummary)) {
|
|
314
|
+
const { cursor, ...filter } = query, limit = _nullishCoalesce(query.limit, () => ( 50));
|
|
315
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, Number.isSafeInteger(limit) && limit > 0 && limit <= 200, "INVALID_LIMIT");
|
|
316
|
+
if (query.kind) _chunkRBOER6EWcjs.requireValue.call(void 0, ["log", "decision"].includes(query.kind), "INVALID_RECORD_KIND");
|
|
317
|
+
if (query.itemId !== void 0) _chunkRBOER6EWcjs.identity.call(void 0, query.itemId);
|
|
318
|
+
if (query.status) _chunkRBOER6EWcjs.requireValue.call(void 0, ["draft", "confirmed", "rejected", "superseded", "cancelling", "cancelled"].includes(query.status), "INVALID_RECORD_STATUS");
|
|
319
|
+
const digest = _chunkRSH6QSECcjs.sha256HexSync.call(void 0, JSON.stringify(filter));
|
|
320
|
+
let offset = 0;
|
|
321
|
+
if (cursor) {
|
|
322
|
+
let decoded;
|
|
323
|
+
try {
|
|
324
|
+
decoded = JSON.parse(decodeURIComponent(cursor));
|
|
325
|
+
} catch (e) {
|
|
326
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, false, "INVALID_CURSOR");
|
|
327
|
+
}
|
|
328
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, decoded && typeof decoded === "object" && !Array.isArray(decoded) && typeof decoded.filter === "string" && typeof decoded.revision === "number", "INVALID_CURSOR");
|
|
329
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, decoded.revision === state.board.revision && decoded.filter === digest, "CURSOR_STALE");
|
|
330
|
+
offset = decoded.offset;
|
|
331
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, Number.isSafeInteger(offset) && offset >= 0, "INVALID_CURSOR");
|
|
332
|
+
}
|
|
333
|
+
const matched = summaries.filter((record) => (query.includeDeleted || record.deletedAt === void 0) && (!query.kind || query.kind === record.kind) && (!query.itemId || record.itemIds.includes(query.itemId)) && (!query.status || query.status === record.status)).sort((a, b) => b.createdAt - a.createdAt || a.id.localeCompare(b.id));
|
|
334
|
+
const items = matched.slice(offset, offset + limit);
|
|
335
|
+
return { revision: state.board.revision, total: matched.length, items, ...offset + limit < matched.length ? { nextCursor: encodeURIComponent(JSON.stringify({ revision: state.board.revision, filter: digest, offset: offset + limit })) } : {} };
|
|
336
|
+
}
|
|
337
|
+
function recordFingerprint(record) {
|
|
338
|
+
return _chunkRSH6QSECcjs.sha256HexSync.call(void 0, JSON.stringify({
|
|
339
|
+
kind: record.kind,
|
|
340
|
+
title: record.title,
|
|
341
|
+
content: record.content,
|
|
342
|
+
rationale: _nullishCoalesce(record.rationale, () => ( null)),
|
|
343
|
+
itemIds: [...record.itemIds].sort(),
|
|
344
|
+
sources: record.sources.map((source) => JSON.stringify([source.sessionId, source.messageId, source.role])).sort(),
|
|
345
|
+
...record.coordination ? { coordination: record.coordination } : {},
|
|
346
|
+
...record.externalRefs ? { externalRefs: record.externalRefs } : {}
|
|
347
|
+
}));
|
|
348
|
+
}
|
|
349
|
+
function validateRecordReferences(refs) {
|
|
350
|
+
if (refs === void 0) return;
|
|
351
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, Array.isArray(refs) && refs.length <= 100, "REFERENCE_LIMIT");
|
|
352
|
+
const keys = /* @__PURE__ */ new Set();
|
|
353
|
+
for (const ref of refs) {
|
|
354
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, ref && typeof ref === "object", "INVALID_REFERENCE");
|
|
355
|
+
_chunkRBOER6EWcjs.identity.call(void 0, ref.system);
|
|
356
|
+
_chunkRBOER6EWcjs.identity.call(void 0, ref.id);
|
|
357
|
+
if (ref.revision !== void 0) _chunkRBOER6EWcjs.text.call(void 0, ref.revision);
|
|
358
|
+
const key = JSON.stringify([ref.system, ref.id]);
|
|
359
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !keys.has(key), "DUPLICATE_REFERENCE");
|
|
360
|
+
keys.add(key);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
function recordSummary(record) {
|
|
364
|
+
const { content: _content, rationale: _rationale, sources, ...metadata } = record;
|
|
365
|
+
return { ...metadata, sessionIds: [...new Set(sources.map((source) => source.sessionId))] };
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// src/board.ts
|
|
369
|
+
function createBoardState(input, actor, now) {
|
|
370
|
+
const board = { ...structuredClone(input), policy: _chunkRBOER6EWcjs.policy.call(void 0, input.policy), revision: 1, items: [], participants: [] };
|
|
371
|
+
_chunkRBOER6EWcjs.validateBoard.call(void 0, board);
|
|
372
|
+
if (actor.sessionId) _chunkRBOER6EWcjs.participant.call(void 0, board.participants, actor.sessionId, actor.agentId, "creator", true, now);
|
|
373
|
+
for (const session of board.policy.escalationSessionIds) _chunkRBOER6EWcjs.participant.call(void 0, board.participants, session, void 0, "escalation", true, now);
|
|
374
|
+
return { schema: 1, board, sequence: 0, events: [], escalations: [] };
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// src/storage-codec.ts
|
|
378
|
+
var boardKey = (id) => `board/${encodeURIComponent(id)}`;
|
|
379
|
+
var archiveKey = (board, item) => `archive/${encodeURIComponent(board)}/${encodeURIComponent(item)}`;
|
|
380
|
+
var rowKey = (kind, board, id) => `${kind}/${encodeURIComponent(board)}/${encodeURIComponent(id)}`;
|
|
381
|
+
function rowKeys(raw) {
|
|
382
|
+
if (raw === null) return [];
|
|
383
|
+
const saved = JSON.parse(raw);
|
|
384
|
+
if (saved.layout !== 2) return [];
|
|
385
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, Array.isArray(saved.itemIds) && Array.isArray(saved.recordIds) && _optionalChain([saved, 'access', _68 => _68.state, 'optionalAccess', _69 => _69.board]), "INVALID_STORAGE");
|
|
386
|
+
return [...saved.itemIds.map((id) => rowKey("item", saved.state.board.id, id)), ...saved.recordIds.map((id) => rowKey("record", saved.state.board.id, id))];
|
|
387
|
+
}
|
|
388
|
+
async function hydrate(saved, bodies) {
|
|
389
|
+
if (saved.raw === null) return null;
|
|
390
|
+
const parsed = JSON.parse(saved.raw);
|
|
391
|
+
if (parsed.layout !== 2) return validateState(parsed);
|
|
392
|
+
const state = validateState(parsed.state), id = state.board.id;
|
|
393
|
+
state.board.items = await Promise.all(parsed.itemIds.map(async (itemId) => {
|
|
394
|
+
const item = await decodeRow(requiredRow(saved, rowKey("item", id, itemId)), bodies);
|
|
395
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, item.id === itemId, "INVALID_STORAGE");
|
|
396
|
+
return item;
|
|
397
|
+
}));
|
|
398
|
+
state.records = await Promise.all(parsed.recordIds.map(async (recordId) => {
|
|
399
|
+
const record = await decodeRow(requiredRow(saved, rowKey("record", id, recordId)), bodies);
|
|
400
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, record.id === recordId, "INVALID_STORAGE");
|
|
401
|
+
return record;
|
|
402
|
+
}));
|
|
403
|
+
return state;
|
|
404
|
+
}
|
|
405
|
+
async function encodeBoard(state, bodies) {
|
|
406
|
+
const rows = {}, id = state.board.id;
|
|
407
|
+
for (const item of state.board.items) rows[rowKey("item", id, item.id)] = await encodeRow(item, bodies);
|
|
408
|
+
for (const record of _nullishCoalesce(state.records, () => ( []))) rows[rowKey("record", id, record.id)] = await encodeRow(record, bodies);
|
|
409
|
+
const manifest = {
|
|
410
|
+
itemIndex: state.board.items.map(summary),
|
|
411
|
+
recordIndex: (_nullishCoalesce(state.records, () => ( []))).map(recordSummary),
|
|
412
|
+
layout: 2,
|
|
413
|
+
generation: _chunkRSH6QSECcjs.randomUUID.call(void 0, ),
|
|
414
|
+
state: { ...state, board: { ...state.board, items: [] }, records: [] },
|
|
415
|
+
itemIds: state.board.items.map((item) => item.id),
|
|
416
|
+
recordIds: (_nullishCoalesce(state.records, () => ( []))).map((record) => record.id)
|
|
417
|
+
};
|
|
418
|
+
return { raw: JSON.stringify(manifest), rows };
|
|
419
|
+
}
|
|
420
|
+
function rowChanges(before, after) {
|
|
421
|
+
const writes = Object.entries(after.rows).filter(([key, value]) => before.rows[key] !== value).map(([key, value]) => ({ key, value }));
|
|
422
|
+
for (const key of Object.keys(before.rows)) if (!(key in after.rows)) writes.push({ key, value: null });
|
|
423
|
+
return writes;
|
|
424
|
+
}
|
|
425
|
+
function receiptDigest(fingerprint) {
|
|
426
|
+
return `sha256:v1:${_chunkRSH6QSECcjs.sha256HexSync.call(void 0, fingerprint)}`;
|
|
427
|
+
}
|
|
428
|
+
function verifyReceipt(saved, fingerprint) {
|
|
429
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, saved === fingerprint || saved === receiptDigest(fingerprint), "IDEMPOTENCY_CONFLICT");
|
|
430
|
+
}
|
|
431
|
+
async function encodeRow(value, bodies) {
|
|
432
|
+
const raw = JSON.stringify(value), bytes = new TextEncoder().encode(raw);
|
|
433
|
+
if (!bodies || bytes.length <= 8192) return raw;
|
|
434
|
+
const ref = { body: "kanban-body/v1", sha256: _chunkRSH6QSECcjs.sha256HexSync.call(void 0, bytes), bytes: bytes.length };
|
|
435
|
+
const existing = await bodies.read(ref.sha256);
|
|
436
|
+
if (existing !== null) verifyBody(existing, ref);
|
|
437
|
+
else {
|
|
438
|
+
let failure;
|
|
439
|
+
try {
|
|
440
|
+
await bodies.write(ref.sha256, bytes.buffer);
|
|
441
|
+
} catch (error) {
|
|
442
|
+
failure = error;
|
|
443
|
+
}
|
|
444
|
+
const confirmed = await bodies.read(ref.sha256);
|
|
445
|
+
if (confirmed === null) throw _nullishCoalesce(failure, () => ( new (0, _chunkRSH6QSECcjs.KanbanError)("BODY_WRITE_UNCONFIRMED")));
|
|
446
|
+
verifyBody(confirmed, ref);
|
|
447
|
+
}
|
|
448
|
+
return JSON.stringify(ref);
|
|
449
|
+
}
|
|
450
|
+
async function decodeRow(raw, bodies) {
|
|
451
|
+
const parsed = JSON.parse(raw);
|
|
452
|
+
if (_optionalChain([parsed, 'optionalAccess', _70 => _70.body]) !== "kanban-body/v1") return parsed;
|
|
453
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, /^[a-f0-9]{64}$/.test(parsed.sha256) && Number.isSafeInteger(parsed.bytes) && parsed.bytes > 8192, "INVALID_BODY_REFERENCE");
|
|
454
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, bodies, "BODY_STORE_REQUIRED");
|
|
455
|
+
const bytes = await bodies.read(parsed.sha256);
|
|
456
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, bytes !== null, "BODY_MISSING");
|
|
457
|
+
verifyBody(bytes, parsed);
|
|
458
|
+
return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
|
|
459
|
+
}
|
|
460
|
+
function verifyBody(bytes, ref) {
|
|
461
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, bytes instanceof ArrayBuffer && bytes.byteLength === ref.bytes && _chunkRSH6QSECcjs.sha256HexSync.call(void 0, bytes) === ref.sha256, "BODY_INTEGRITY");
|
|
462
|
+
}
|
|
463
|
+
function requiredRow(saved, key) {
|
|
464
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, typeof saved.rows[key] === "string", "MISSING_STORAGE_ROW");
|
|
465
|
+
return saved.rows[key];
|
|
466
|
+
}
|
|
467
|
+
function validateState(state) {
|
|
468
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, _optionalChain([state, 'optionalAccess', _71 => _71.schema]) === 1 && state.board && Array.isArray(state.board.items) && Array.isArray(state.events), "INVALID_STORAGE");
|
|
469
|
+
return state;
|
|
470
|
+
}
|
|
471
|
+
function indexedView(raw) {
|
|
472
|
+
if (raw === null) return null;
|
|
473
|
+
const parsed = JSON.parse(raw);
|
|
474
|
+
if (parsed.layout === 2 && Array.isArray(parsed.itemIndex) && Array.isArray(parsed.recordIndex))
|
|
475
|
+
return { state: validateState(parsed.state), items: parsed.itemIndex, records: parsed.recordIndex };
|
|
476
|
+
return null;
|
|
477
|
+
}
|
|
478
|
+
function viewFromState(state) {
|
|
479
|
+
return { state: { ...state, board: { ...state.board, items: [] }, records: [] }, items: state.board.items.map(summary), records: (_nullishCoalesce(state.records, () => ( []))).map(recordSummary) };
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
// src/numbering.ts
|
|
483
|
+
var boardCounterKey = "counter/board";
|
|
484
|
+
var boardNumberKey = (number) => `reference/board/${number}`;
|
|
485
|
+
function counter(raw) {
|
|
486
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, raw === null || /^(0|[1-9]\d*)$/.test(raw), "INVALID_NUMBER_COUNTER");
|
|
487
|
+
const value = raw === null ? 0 : Number(raw);
|
|
488
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, Number.isSafeInteger(value) && value >= 0 && value <= Number.MAX_SAFE_INTEGER, "INVALID_NUMBER_COUNTER");
|
|
489
|
+
return value;
|
|
490
|
+
}
|
|
491
|
+
function storedBoardNumber(raw) {
|
|
492
|
+
if (raw === null) return void 0;
|
|
493
|
+
const parsed = JSON.parse(raw), number = _optionalChain([(parsed.layout === 2 ? _optionalChain([parsed, 'access', _72 => _72.state, 'optionalAccess', _73 => _73.board]) : parsed.board), 'optionalAccess', _74 => _74.number]);
|
|
494
|
+
if (number !== void 0) _chunkRBOER6EWcjs.requireValue.call(void 0, Number.isSafeInteger(number) && number > 0, "INVALID_NUMBERING");
|
|
495
|
+
return number;
|
|
496
|
+
}
|
|
497
|
+
function patchBoardNumber(raw, number) {
|
|
498
|
+
const parsed = JSON.parse(raw);
|
|
499
|
+
parsed.state.board.number = number;
|
|
500
|
+
return JSON.stringify(parsed);
|
|
501
|
+
}
|
|
502
|
+
function numberEntities(state) {
|
|
503
|
+
const high = state.numbering ??= { item: 0, log: 0, decision: 0 };
|
|
504
|
+
const items = [...state.board.items, ..._nullishCoalesce(state.archiveIndex, () => ( [])), ...(_nullishCoalesce(state.archiveWrites, () => ( []))).flatMap((write) => write.value ? [write.value.item] : [])];
|
|
505
|
+
high.item = assign(items, high.item);
|
|
506
|
+
for (const kind of ["log", "decision"]) high[kind] = assign((_nullishCoalesce(state.records, () => ( []))).filter((record) => record.kind === kind), high[kind]);
|
|
507
|
+
}
|
|
508
|
+
function assign(rows, high) {
|
|
509
|
+
counter(String(high));
|
|
510
|
+
const used = /* @__PURE__ */ new Map(), known = /* @__PURE__ */ new Map();
|
|
511
|
+
for (const row of rows) if (row.number !== void 0) {
|
|
512
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, Number.isSafeInteger(row.number) && row.number > 0 && (!used.has(row.number) || used.get(row.number) === row.id) && (!known.has(row.id) || known.get(row.id) === row.number), "INVALID_NUMBERING");
|
|
513
|
+
used.set(row.number, row.id);
|
|
514
|
+
known.set(row.id, row.number);
|
|
515
|
+
high = Math.max(high, row.number);
|
|
516
|
+
}
|
|
517
|
+
for (const row of rows) if (row.number === void 0) {
|
|
518
|
+
if (!known.has(row.id)) {
|
|
519
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, high < Number.MAX_SAFE_INTEGER, "NUMBER_COUNTER_EXHAUSTED");
|
|
520
|
+
known.set(row.id, ++high);
|
|
521
|
+
}
|
|
522
|
+
row.number = known.get(row.id);
|
|
523
|
+
}
|
|
524
|
+
return high;
|
|
525
|
+
}
|
|
526
|
+
function allocateBoardNumber(raw, high) {
|
|
527
|
+
const known = storedBoardNumber(raw);
|
|
528
|
+
if (known !== void 0) return known;
|
|
529
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, high < Number.MAX_SAFE_INTEGER, "NUMBER_COUNTER_EXHAUSTED");
|
|
530
|
+
return high + 1;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
// src/workflow-plans.ts
|
|
534
|
+
function requireCoordinator(state, actor) {
|
|
535
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, _optionalChain([state, 'access', _75 => _75.board, 'access', _76 => _76.members, 'optionalAccess', _77 => _77.some, 'call', _78 => _78((member) => _chunkRBOER6EWcjs.principalKey.call(void 0, member) === _chunkRBOER6EWcjs.principalKey.call(void 0, _chunkRBOER6EWcjs.principal.call(void 0, actor)) && _optionalChain([member, 'access', _79 => _79.roles, 'optionalAccess', _80 => _80.includes, 'call', _81 => _81("coordinator")]))]), "COORDINATOR_REQUIRED");
|
|
536
|
+
}
|
|
537
|
+
function publishPlan(state, plan2, actor, apply) {
|
|
538
|
+
requireCoordinator(state, actor);
|
|
539
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, plan2 && typeof plan2 === "object", "INVALID_WORK_PLAN");
|
|
540
|
+
_chunkRBOER6EWcjs.identity.call(void 0, plan2.id);
|
|
541
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, plan2.schema === "kanban.plan/1" && typeof plan2.sealed === "boolean" && Array.isArray(plan2.items) && plan2.items.length > 0 && plan2.items.length <= 100, "INVALID_WORK_PLAN");
|
|
542
|
+
const workflow = state.workflow, previous = workflow.plans[plan2.id];
|
|
543
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, Number.isSafeInteger(plan2.revision) && plan2.revision === (_nullishCoalesce(_optionalChain([previous, 'optionalAccess', _82 => _82.revision]), () => ( 0))) + 1, "PLAN_REVISION_CONFLICT");
|
|
544
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !Object.values(workflow.dispatches).some((dispatch) => dispatch.planId === plan2.id && ["prepared", "running", "unknown", "succeeded"].includes(dispatch.outcome)), "PLAN_EXECUTION_UNSETTLED");
|
|
545
|
+
if (plan2.decisionId) {
|
|
546
|
+
const decision = _optionalChain([state, 'access', _83 => _83.records, 'optionalAccess', _84 => _84.find, 'call', _85 => _85((record) => record.id === plan2.decisionId && record.kind === "decision" && record.status === "confirmed")]);
|
|
547
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, decision, "DECISION_NOT_CONFIRMED");
|
|
548
|
+
if (decision.coordination) _chunkRBOER6EWcjs.requireValue.call(void 0, _chunkRBOER6EWcjs.principalKey.call(void 0, decision.coordination.manager) === _chunkRBOER6EWcjs.principalKey.call(void 0, _chunkRBOER6EWcjs.principal.call(void 0, actor)), "DECISION_MANAGER_REQUIRED");
|
|
549
|
+
}
|
|
550
|
+
if (plan2.rootItemId) {
|
|
551
|
+
const root = state.board.items.find((item) => item.id === plan2.rootItemId);
|
|
552
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, root && !root.owner && ["backlog", "open"].includes(root.status), "PLAN_ROOT_UNAVAILABLE");
|
|
553
|
+
if (_optionalChain([root, 'access', _86 => _86.planning, 'optionalAccess', _87 => _87.execution]) !== "children") apply({ type: "plan-item", itemId: root.id, planning: { ...plan(root), execution: "children" } });
|
|
554
|
+
}
|
|
555
|
+
const ordered = orderWork(plan2.items, state), definitions = {};
|
|
556
|
+
for (const item of ordered) {
|
|
557
|
+
const digest = _chunkRSH6QSECcjs.sha256HexSync.call(void 0, JSON.stringify(item));
|
|
558
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !Object.values(workflow.plans).some((other) => other.id !== plan2.id && other.itemIds.includes(item.id)), "ITEM_IN_OTHER_PLAN");
|
|
559
|
+
const exists = state.board.items.some((old) => old.id === item.id) || _optionalChain([state, 'access', _88 => _88.archiveIndex, 'optionalAccess', _89 => _89.some, 'call', _90 => _90((old) => old.id === item.id)]);
|
|
560
|
+
if (exists && _optionalChain([previous, 'optionalAccess', _91 => _91.definitions, 'access', _92 => _92[item.id], 'optionalAccess', _93 => _93.digest]) !== digest) {
|
|
561
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !_optionalChain([previous, 'optionalAccess', _94 => _94.definitions, 'access', _95 => _95[item.id]]), "PLAN_ITEM_CHANGED_REQUIRES_NEW_ID");
|
|
562
|
+
adoptItem(state, item, apply);
|
|
563
|
+
}
|
|
564
|
+
if (!exists) apply({
|
|
565
|
+
type: "create-item",
|
|
566
|
+
item: { id: item.id, title: item.title, responsibility: item.responsibility, acceptance: item.acceptance, eligiblePrincipals: [item.assignee], externalRefs: item.externalRefs },
|
|
567
|
+
planning: { kind: _nullishCoalesce(_nullishCoalesce(item.workType, () => ( state.board.defaultWorkType)), () => ( "task")), priority: 2, dependencies: item.dependsOn, references: [], ...plan2.rootItemId ? { parentId: plan2.rootItemId } : {} }
|
|
568
|
+
});
|
|
569
|
+
definitions[item.id] = { digest, inputs: item.inputs, outputs: _nullishCoalesce(item.outputs, () => ( [])) };
|
|
570
|
+
}
|
|
571
|
+
workflow.plans[plan2.id] = { schema: plan2.schema, id: plan2.id, revision: plan2.revision, decisionId: plan2.decisionId, rootItemId: plan2.rootItemId, sealed: plan2.sealed, itemIds: ordered.map((item) => item.id), definitions };
|
|
572
|
+
}
|
|
573
|
+
function adoptItem(state, definition, apply) {
|
|
574
|
+
const item = state.board.items.find((item2) => item2.id === definition.id);
|
|
575
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, item && definition.expectedRevision === item.revision && ["backlog", "open"].includes(item.status) && !item.owner && !item.blocked && (!item.control || item.control.action === "resume" && item.control.state === "resumed"), "PLAN_ITEM_CHANGED_REQUIRES_NEW_ID");
|
|
576
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !definition.workType || definition.workType === _optionalChain([item, 'access', _96 => _96.planning, 'optionalAccess', _97 => _97.kind]), "PLAN_ITEM_CHANGED_REQUIRES_NEW_ID");
|
|
577
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !definition.externalRefs || definition.externalRefs.every((ref) => _optionalChain([item, 'access', _98 => _98.externalRefs, 'optionalAccess', _99 => _99.some, 'call', _100 => _100((existing) => JSON.stringify(existing) === JSON.stringify(ref))])), "PLAN_RESOURCE_MISMATCH");
|
|
578
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, item.title === definition.title && item.responsibility === definition.responsibility && item.acceptance === definition.acceptance, "PLAN_ITEM_CHANGED_REQUIRES_NEW_ID");
|
|
579
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, plan(item).dependencies.every((id) => definition.dependsOn.includes(id)), "EXISTING_DEPENDENCY_REQUIRED");
|
|
580
|
+
apply({ type: "plan-item", itemId: item.id, planning: { ...plan(item), dependencies: definition.dependsOn } });
|
|
581
|
+
item.eligiblePrincipals = [definition.assignee];
|
|
582
|
+
delete item.eligibleAgentIds;
|
|
583
|
+
_chunkRBOER6EWcjs.validateCandidates.call(void 0, state.board, item, true);
|
|
584
|
+
}
|
|
585
|
+
function orderWork(items, state) {
|
|
586
|
+
for (const item of items) validateDefinition(item);
|
|
587
|
+
const ids = new Set(items.map((item) => item.id));
|
|
588
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, ids.size === items.length, "DUPLICATE_PLAN_ITEM");
|
|
589
|
+
for (const item of items) {
|
|
590
|
+
_chunkRBOER6EWcjs.identity.call(void 0, item.id);
|
|
591
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, Array.isArray(item.dependsOn) && item.dependsOn.length <= 100 && new Set(item.dependsOn).size === item.dependsOn.length, "INVALID_DEPENDENCIES");
|
|
592
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, Object.keys(_nullishCoalesce(item.inputs, () => ( {}))).length <= 100 && Array.isArray(_nullishCoalesce(item.outputs, () => ( []))) && (_nullishCoalesce(item.outputs, () => ( []))).length <= 100 && new Set(_nullishCoalesce(item.outputs, () => ( []))).size === (_nullishCoalesce(item.outputs, () => ( []))).length, "PLAN_BINDING_LIMIT");
|
|
593
|
+
for (const name of [...Object.keys(_nullishCoalesce(item.inputs, () => ( {}))), ..._nullishCoalesce(item.outputs, () => ( []))]) _chunkRBOER6EWcjs.requireValue.call(void 0, /^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$/.test(name), "INVALID_OUTPUT_NAME");
|
|
594
|
+
for (const binding of Object.values(_nullishCoalesce(item.inputs, () => ( {})))) {
|
|
595
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, binding && item.dependsOn.includes(binding.fromItemId) && typeof binding.output === "string", "INPUT_DEPENDENCY_REQUIRED");
|
|
596
|
+
const producer = items.find((other) => other.id === binding.fromItemId), existing = Object.values(state.workflow.dispatches).some((dispatch) => dispatch.itemId === binding.fromItemId && dispatch.outcome === "accepted" && _optionalChain([dispatch, 'access', _101 => _101.outputs, 'optionalAccess', _102 => _102.some, 'call', _103 => _103((output) => output.name === binding.output)]));
|
|
597
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, producer ? _optionalChain([producer, 'access', _104 => _104.outputs, 'optionalAccess', _105 => _105.includes, 'call', _106 => _106(binding.output)]) : existing, "OUTPUT_NOT_DECLARED");
|
|
598
|
+
}
|
|
599
|
+
for (const dependency of item.dependsOn) _chunkRBOER6EWcjs.requireValue.call(void 0, ids.has(dependency) || [...state.board.items, ..._nullishCoalesce(state.archiveIndex, () => ( []))].some((old) => old.id === dependency), "DEPENDENCY_NOT_FOUND");
|
|
600
|
+
}
|
|
601
|
+
const ordered = [], remaining = [...items], done = /* @__PURE__ */ new Set();
|
|
602
|
+
while (remaining.length) {
|
|
603
|
+
const next = remaining.findIndex((item2) => item2.dependsOn.every((id) => !ids.has(id) || done.has(id)));
|
|
604
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, next >= 0, "DEPENDENCY_CYCLE");
|
|
605
|
+
const [item] = remaining.splice(next, 1);
|
|
606
|
+
ordered.push(item);
|
|
607
|
+
done.add(item.id);
|
|
608
|
+
}
|
|
609
|
+
return ordered;
|
|
610
|
+
}
|
|
611
|
+
function validateDefinition(item) {
|
|
612
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, item && typeof item === "object" && !Array.isArray(item), "INVALID_WORK_DEFINITION");
|
|
613
|
+
const assignee = item.assignee;
|
|
614
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, assignee && ["agent", "human", "service"].includes(assignee.kind), "INVALID_PRINCIPAL");
|
|
615
|
+
_chunkRBOER6EWcjs.identity.call(void 0, assignee.id);
|
|
616
|
+
if (item.inputs !== void 0) _chunkRBOER6EWcjs.requireValue.call(void 0, item.inputs && typeof item.inputs === "object" && !Array.isArray(item.inputs), "INVALID_INPUT_BINDINGS");
|
|
617
|
+
if (item.outputs !== void 0) _chunkRBOER6EWcjs.requireValue.call(void 0, Array.isArray(item.outputs) && item.outputs.every((name) => typeof name === "string"), "INVALID_OUTPUT_NAMES");
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
// src/archives.ts
|
|
621
|
+
function archiveItems(state, ids, reason, now) {
|
|
622
|
+
_chunkRBOER6EWcjs.text.call(void 0, reason);
|
|
623
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, ids.length > 0 && ids.length <= 50 && new Set(ids).size === ids.length, "ARCHIVE_BATCH_LIMIT");
|
|
624
|
+
const items = ids.map((id) => state.board.items.find((i) => i.id === id));
|
|
625
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, items.every((item) => item && terminal(item)), "ARCHIVE_REQUIRES_CLOSED_ITEM");
|
|
626
|
+
for (const item of items) {
|
|
627
|
+
const archived = { item, archivedAt: now, reason };
|
|
628
|
+
(state.archiveIndex ??= []).push({ ...summary(item), archivedAt: now, archiveReason: reason });
|
|
629
|
+
(state.archiveWrites ??= []).push({ id: item.id, value: archived });
|
|
630
|
+
}
|
|
631
|
+
const selected = new Set(ids);
|
|
632
|
+
state.board.items = state.board.items.filter((i) => !selected.has(i.id));
|
|
633
|
+
}
|
|
634
|
+
function restoreItem(state, id, now) {
|
|
635
|
+
const record = state.restore;
|
|
636
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, _optionalChain([record, 'optionalAccess', _107 => _107.item, 'access', _108 => _108.id]) === id && _optionalChain([state, 'access', _109 => _109.archiveIndex, 'optionalAccess', _110 => _110.some, 'call', _111 => _111((i) => i.id === id)]), "ARCHIVED_ITEM_NOT_FOUND");
|
|
637
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !state.board.items.some((i) => i.id === id), "ITEM_EXISTS");
|
|
638
|
+
record.item.restoredAt = now;
|
|
639
|
+
record.item.updatedAt = now;
|
|
640
|
+
record.item.revision++;
|
|
641
|
+
state.board.items.push(record.item);
|
|
642
|
+
state.archiveIndex = state.archiveIndex.filter((i) => i.id !== id);
|
|
643
|
+
(state.archiveWrites ??= []).push({ id, value: null });
|
|
644
|
+
delete state.restore;
|
|
645
|
+
}
|
|
646
|
+
function archiveExpired(state, now) {
|
|
647
|
+
const age = state.board.policy.archiveAfterMs;
|
|
648
|
+
if (age === void 0) return [];
|
|
649
|
+
const ids = state.board.items.filter((i) => terminal(i) && now - Math.max(_nullishCoalesce(i.closedAt, () => ( i.updatedAt)), _nullishCoalesce(i.restoredAt, () => ( 0))) >= age).slice(0, 50).map((i) => i.id);
|
|
650
|
+
if (ids.length) archiveItems(state, ids, "retention-policy", now);
|
|
651
|
+
return ids;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
// src/planning-commands.ts
|
|
655
|
+
function planningCommand(command) {
|
|
656
|
+
return ["edit-item", "plan-item", "set-stage", "publish-proposal", "cancel-item", "close-plan", "archive-items", "restore-item", "block-item", "unblock-item", "link-reference", "release-item"].includes(command.type);
|
|
657
|
+
}
|
|
658
|
+
function applyPlanningCommand(state, command, now, actor, internal = false) {
|
|
659
|
+
if (command.type === "archive-items") return archiveItems(state, command.itemIds, command.reason, now);
|
|
660
|
+
if (command.type === "restore-item") return restoreItem(state, command.itemId, now);
|
|
661
|
+
const item = state.board.items.find((i) => i.id === command.itemId);
|
|
662
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, item, "ITEM_NOT_FOUND");
|
|
663
|
+
if (isOperational(command)) operate(item, command, now, actor);
|
|
664
|
+
else {
|
|
665
|
+
if (!internal && ["edit-item", "plan-item", "review-amendment"].includes(command.type)) assertDefinitionEditable(item, now);
|
|
666
|
+
updatePlan(state, item, command, now);
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
function isOperational(command) {
|
|
670
|
+
return ["block-item", "unblock-item", "link-reference", "release-item"].includes(command.type);
|
|
671
|
+
}
|
|
672
|
+
function operate(item, command, now, actor) {
|
|
673
|
+
if (command.type === "release-item") {
|
|
674
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, ["claimed", "review"].includes(item.status) && _optionalChain([item, 'access', _112 => _112.owner, 'optionalAccess', _113 => _113.token]) === command.token, "OWNER_MISMATCH");
|
|
675
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, ["backlog", "cancelled"].includes(command.next), "INVALID_STAGE");
|
|
676
|
+
_chunkRBOER6EWcjs.text.call(void 0, command.reason);
|
|
677
|
+
item.status = command.next;
|
|
678
|
+
if (command.next === "cancelled") {
|
|
679
|
+
item.closedAt = now;
|
|
680
|
+
item.closureReason = command.reason;
|
|
681
|
+
}
|
|
682
|
+
delete item.owner;
|
|
683
|
+
delete item.transfer;
|
|
684
|
+
delete item.estimate;
|
|
685
|
+
} else if (command.type === "link-reference") attachReference(item, command.reference);
|
|
686
|
+
else {
|
|
687
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !terminal(item), "ITEM_COMPLETED");
|
|
688
|
+
if (item.status === "claimed") _chunkRBOER6EWcjs.owned.call(void 0, item, actor, _nullishCoalesce(command.token, () => ( "")), now);
|
|
689
|
+
if (command.type === "block-item") {
|
|
690
|
+
_chunkRBOER6EWcjs.text.call(void 0, command.reason);
|
|
691
|
+
item.blocked = { reason: command.reason, at: now };
|
|
692
|
+
} else delete item.blocked;
|
|
693
|
+
}
|
|
694
|
+
item.updatedAt = now;
|
|
695
|
+
item.revision++;
|
|
696
|
+
}
|
|
697
|
+
function updatePlan(state, item, command, now) {
|
|
698
|
+
if (command.type === "close-plan") _chunkRBOER6EWcjs.requireValue.call(void 0, _optionalChain([item, 'access', _114 => _114.control, 'optionalAccess', _115 => _115.action]) !== "cancel", "TASK_CANCELLING");
|
|
699
|
+
if (command.type === "cancel-item") _chunkRBOER6EWcjs.requireValue.call(void 0, _optionalChain([item, 'access', _116 => _116.launch, 'optionalAccess', _117 => _117.admittedAt]) === void 0, "TASK_CONTROL_REQUIRED");
|
|
700
|
+
if (command.type === "publish-proposal") {
|
|
701
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, item.status === "proposed", "NOT_PROPOSED");
|
|
702
|
+
return setStage(state, item, _nullishCoalesce(command.stage, () => ( "backlog")), now);
|
|
703
|
+
}
|
|
704
|
+
if (command.type === "set-stage") return setStage(state, item, command.stage, now);
|
|
705
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, ["proposed", "backlog", "open"].includes(item.status), "ITEM_NOT_PLANNABLE");
|
|
706
|
+
if (command.type === "edit-item") {
|
|
707
|
+
_chunkRBOER6EWcjs.text.call(void 0, command.title);
|
|
708
|
+
_chunkRBOER6EWcjs.text.call(void 0, command.responsibility);
|
|
709
|
+
_chunkRBOER6EWcjs.text.call(void 0, command.acceptance);
|
|
710
|
+
item.title = command.title;
|
|
711
|
+
item.responsibility = command.responsibility;
|
|
712
|
+
item.acceptance = command.acceptance;
|
|
713
|
+
if (item.status === "open") return setStage(state, item, "backlog", now);
|
|
714
|
+
} else if (command.type === "plan-item") {
|
|
715
|
+
validatePlan(state, item, command.planning);
|
|
716
|
+
item.planning = command.planning;
|
|
717
|
+
if (item.status === "open") return setStage(state, item, "backlog", now);
|
|
718
|
+
} else {
|
|
719
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, catalog(state).filter((i) => i.planning.parentId === item.id).every(terminal), "CHILDREN_UNFINISHED");
|
|
720
|
+
if (command.type === "close-plan") {
|
|
721
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !_chunkRBOER6EWcjs.executable.call(void 0, state.board, item), "TASK_REQUIRES_REVIEW");
|
|
722
|
+
_chunkRBOER6EWcjs.text.call(void 0, command.resultRef);
|
|
723
|
+
const children = catalog(state).filter((child) => child.planning.parentId === item.id);
|
|
724
|
+
if (_optionalChain([item, 'access', _118 => _118.planning, 'optionalAccess', _119 => _119.execution]) === "children") _chunkRBOER6EWcjs.requireValue.call(void 0, children.length > 0 && children.every((child) => child.status === "completed"), "CHILDREN_UNFINISHED");
|
|
725
|
+
item.status = "completed";
|
|
726
|
+
item.resultRef = command.resultRef;
|
|
727
|
+
} else {
|
|
728
|
+
_chunkRBOER6EWcjs.text.call(void 0, command.reason);
|
|
729
|
+
item.status = "cancelled";
|
|
730
|
+
item.closureReason = command.reason;
|
|
731
|
+
}
|
|
732
|
+
item.closedAt = now;
|
|
733
|
+
}
|
|
734
|
+
item.updatedAt = now;
|
|
735
|
+
item.revision++;
|
|
736
|
+
}
|
|
737
|
+
function attachReference(item, reference) {
|
|
738
|
+
_chunkRBOER6EWcjs.identity.call(void 0, reference.system);
|
|
739
|
+
_chunkRBOER6EWcjs.identity.call(void 0, reference.id);
|
|
740
|
+
if (reference.revision !== void 0) _chunkRBOER6EWcjs.text.call(void 0, reference.revision);
|
|
741
|
+
item.externalRefs ??= [];
|
|
742
|
+
if (item.externalRefs.some((r) => r.system === reference.system && r.id === reference.id && r.revision === reference.revision)) return;
|
|
743
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, item.externalRefs.length < 100, "REFERENCE_LIMIT");
|
|
744
|
+
item.externalRefs.push(reference);
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
// src/task-commands.ts
|
|
748
|
+
var types = ["set-launch-mode", "retry-analysis", "begin-edit", "end-edit", "save-edit", "request-run", "admit-item", "report-analysis", "request-control", "control-receipt", "report-issue", "resolve-issue"];
|
|
749
|
+
function taskCommand(command) {
|
|
750
|
+
return types.includes(command.type);
|
|
751
|
+
}
|
|
752
|
+
function assertDefinitionEditable(item, now, editId, actor) {
|
|
753
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, _optionalChain([item, 'access', _120 => _120.control, 'optionalAccess', _121 => _121.action]) !== "cancel", "TASK_CANCELLING");
|
|
754
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, ["proposed", "backlog", "open"].includes(item.status) && !item.owner && _optionalChain([item, 'access', _122 => _122.launch, 'optionalAccess', _123 => _123.admittedAt]) === void 0, "TASK_DEFINITION_FROZEN");
|
|
755
|
+
if (_chunkAOHQCX7Kcjs.taskEditing.call(void 0, item, now)) _chunkRBOER6EWcjs.requireValue.call(void 0, item.launch.editing.id === editId && !!actor && _chunkRBOER6EWcjs.principalKey.call(void 0, item.launch.editing.principal) === _chunkRBOER6EWcjs.principalKey.call(void 0, _chunkRBOER6EWcjs.principal.call(void 0, actor)), "EDIT_LEASE_ACTIVE");
|
|
756
|
+
}
|
|
757
|
+
function applyTaskCommand(state, command, actor, now) {
|
|
758
|
+
const item = state.board.items.find((i) => i.id === command.itemId);
|
|
759
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, item, "ITEM_NOT_FOUND");
|
|
760
|
+
item.launch ??= { startAt: _chunkAOHQCX7Kcjs.taskStartAt.call(void 0, item) };
|
|
761
|
+
if (["begin-edit", "end-edit", "save-edit"].includes(command.type)) edit(state, item, command, actor, now);
|
|
762
|
+
else if (command.type === "retry-analysis") {
|
|
763
|
+
_chunkRBOER6EWcjs.identity.call(void 0, command.retryId);
|
|
764
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, ["failed", "clarification"].includes(_nullishCoalesce(_optionalChain([item, 'access', _124 => _124.analysis, 'optionalAccess', _125 => _125.state]), () => ( ""))) && !item.owner, "ANALYSIS_NOT_RETRYABLE");
|
|
765
|
+
item.launch.analysisEpoch = command.retryId;
|
|
766
|
+
delete item.analysis;
|
|
767
|
+
} else if (command.type === "set-launch-mode") {
|
|
768
|
+
assertDefinitionEditable(item, now);
|
|
769
|
+
setMode(item, command.mode);
|
|
770
|
+
} else if (command.type === "request-run") {
|
|
771
|
+
assertDefinitionEditable(item, now);
|
|
772
|
+
item.launch.requestedAt ??= now;
|
|
773
|
+
} else if (command.type === "admit-item") {
|
|
774
|
+
requireCoordinator(state, actor);
|
|
775
|
+
assertDefinitionEditable(item, now);
|
|
776
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, _chunkAOHQCX7Kcjs.boardAllowsStart.call(void 0, state.board, item), "BOARD_EXECUTION_PAUSED");
|
|
777
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !item.control || item.control.action === "resume" && item.control.state === "resumed", "TASK_CONTROL_PENDING");
|
|
778
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, command.trigger === "manual" ? item.launch.requestedAt !== void 0 : _chunkAOHQCX7Kcjs.taskDue.call(void 0, item, now), "START_NOT_DUE");
|
|
779
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !item.blocked && _optionalChain([item, 'access', _126 => _126.control, 'optionalAccess', _127 => _127.action]) !== "pause", "ITEM_BLOCKED");
|
|
780
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, _nullishCoalesce(_optionalChain([item, 'access', _128 => _128.planning, 'optionalAccess', _129 => _129.dependencies, 'access', _130 => _130.every, 'call', _131 => _131((id) => _optionalChain([catalog, 'call', _132 => _132(state), 'access', _133 => _133.find, 'call', _134 => _134((i) => i.id === id), 'optionalAccess', _135 => _135.status]) === "completed")]), () => ( true)), "DEPENDENCIES_UNFINISHED");
|
|
781
|
+
item.launch.admittedAt = now;
|
|
782
|
+
} else if (command.type === "report-analysis") {
|
|
783
|
+
requireCoordinator(state, actor);
|
|
784
|
+
_chunkRBOER6EWcjs.identity.call(void 0, command.operationId);
|
|
785
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, command.status.itemId === item.id, "ANALYSIS_SCOPE_MISMATCH");
|
|
786
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, _optionalChain([item, 'access', _136 => _136.control, 'optionalAccess', _137 => _137.action]) !== "cancel" && !["completed", "cancelled"].includes(item.status), "TASK_CANCELLING");
|
|
787
|
+
item.analysis = structuredClone(command.status);
|
|
788
|
+
} else if (command.type === "request-control") {
|
|
789
|
+
requestControl(state, item, command);
|
|
790
|
+
if (command.action === "cancel") cancelChildren(state, item, command.controlId);
|
|
791
|
+
} else if (command.type === "control-receipt") applyControlReceipt(state, item, command, actor, now);
|
|
792
|
+
else issues(state, item, command, actor);
|
|
793
|
+
item.updatedAt = now;
|
|
794
|
+
item.revision++;
|
|
795
|
+
}
|
|
796
|
+
function edit(state, item, command, actor, now) {
|
|
797
|
+
if (command.type === "begin-edit") {
|
|
798
|
+
assertDefinitionEditable(item, now, command.editId, actor);
|
|
799
|
+
_chunkRBOER6EWcjs.identity.call(void 0, command.editId);
|
|
800
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, Number.isSafeInteger(command.leaseMs) && command.leaseMs >= 1e3 && command.leaseMs <= 3e5, "INVALID_EDIT_LEASE");
|
|
801
|
+
item.launch.editing = { id: command.editId, principal: _chunkRBOER6EWcjs.principal.call(void 0, actor), expiresAt: now + command.leaseMs };
|
|
802
|
+
return;
|
|
803
|
+
}
|
|
804
|
+
if (command.type !== "save-edit" && command.type !== "end-edit") return;
|
|
805
|
+
assertDefinitionEditable(item, now, command.editId, actor);
|
|
806
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, _chunkAOHQCX7Kcjs.taskEditing.call(void 0, item, now) && item.launch.editing.id === command.editId, "EDIT_LEASE_EXPIRED");
|
|
807
|
+
if (command.type === "save-edit") {
|
|
808
|
+
_chunkRBOER6EWcjs.text.call(void 0, command.title);
|
|
809
|
+
_chunkRBOER6EWcjs.text.call(void 0, command.responsibility);
|
|
810
|
+
_chunkRBOER6EWcjs.text.call(void 0, command.acceptance);
|
|
811
|
+
validatePlan(state, item, command.planning);
|
|
812
|
+
if (command.launchMode !== void 0) setMode(item, command.launchMode);
|
|
813
|
+
Object.assign(item, { title: command.title, responsibility: command.responsibility, acceptance: command.acceptance, planning: command.planning });
|
|
814
|
+
if (command.externalRefs) {
|
|
815
|
+
item.externalRefs = [];
|
|
816
|
+
for (const ref of command.externalRefs) attachReference(item, ref);
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
if (command.type === "save-edit") for (const plan2 of Object.values(_nullishCoalesce(_optionalChain([state, 'access', _138 => _138.workflow, 'optionalAccess', _139 => _139.plans]), () => ( {})))) {
|
|
820
|
+
const definition = plan2.definitions[item.id];
|
|
821
|
+
if (!definition) continue;
|
|
822
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, Object.values(_nullishCoalesce(definition.inputs, () => ( {}))).every((binding) => _optionalChain([item, 'access', _140 => _140.planning, 'optionalAccess', _141 => _141.dependencies, 'access', _142 => _142.includes, 'call', _143 => _143(binding.fromItemId)])), "EXISTING_DEPENDENCY_REQUIRED");
|
|
823
|
+
definition.digest = _chunkRSH6QSECcjs.sha256HexSync.call(void 0, JSON.stringify([item.title, item.responsibility, item.acceptance, item.planning, item.externalRefs, definition.inputs, definition.outputs]));
|
|
824
|
+
}
|
|
825
|
+
delete item.launch.editing;
|
|
826
|
+
}
|
|
827
|
+
function requestControl(state, item, command) {
|
|
828
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !["completed", "cancelled"].includes(item.status), "ITEM_COMPLETED");
|
|
829
|
+
_chunkRBOER6EWcjs.identity.call(void 0, command.controlId);
|
|
830
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, ["pause", "resume", "cancel"].includes(command.action), "INVALID_CONTROL_ACTION");
|
|
831
|
+
if (_optionalChain([item, 'access', _144 => _144.control, 'optionalAccess', _145 => _145.id]) === command.controlId) {
|
|
832
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, item.control.action === command.action, "IDEMPOTENCY_CONFLICT");
|
|
833
|
+
return;
|
|
834
|
+
}
|
|
835
|
+
if (command.action === "cancel" && _optionalChain([item, 'access', _146 => _146.control, 'optionalAccess', _147 => _147.action]) === "cancel" && item.control.state !== "failed") return;
|
|
836
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, command.action === "cancel" || !item.control || !["requested", "unknown"].includes(item.control.state), "CONTROL_UNSETTLED");
|
|
837
|
+
const dispatch = Object.values(_nullishCoalesce(_optionalChain([state, 'access', _148 => _148.workflow, 'optionalAccess', _149 => _149.dispatches]), () => ( {}))).filter((d) => d.itemId === item.id).sort((a, b) => b.attempt - a.attempt)[0];
|
|
838
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !item.owner || dispatch || command.action === "cancel", "TASK_CONTROL_UNSUPPORTED");
|
|
839
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, command.action !== "resume" || _optionalChain([item, 'access', _150 => _150.control, 'optionalAccess', _151 => _151.action]) === "pause", "TASK_NOT_PAUSED");
|
|
840
|
+
item.control = { id: command.controlId, dispatchId: _optionalChain([dispatch, 'optionalAccess', _152 => _152.id]), action: command.action, state: "requested" };
|
|
841
|
+
}
|
|
842
|
+
function issues(state, item, command, actor) {
|
|
843
|
+
requireCoordinator(state, actor);
|
|
844
|
+
if (command.type === "report-issue") {
|
|
845
|
+
const issue = command.issue;
|
|
846
|
+
_chunkRBOER6EWcjs.identity.call(void 0, issue.id);
|
|
847
|
+
_chunkRBOER6EWcjs.identity.call(void 0, issue.attemptId);
|
|
848
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !issue.resolvedBy && ["clarification", "error"].includes(issue.type), "INVALID_ISSUE");
|
|
849
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, _optionalChain([state, 'access', _153 => _153.workflow, 'optionalAccess', _154 => _154.dispatches, 'access', _155 => _155[issue.attemptId], 'optionalAccess', _156 => _156.itemId]) === item.id && _optionalChain([item, 'access', _157 => _157.owner, 'optionalAccess', _158 => _158.token]) === state.workflow.dispatches[issue.attemptId].fence, "STALE_EXECUTION_RESULT");
|
|
850
|
+
item.issues ??= [];
|
|
851
|
+
const old = item.issues.find((i) => i.id === issue.id && i.attemptId === issue.attemptId);
|
|
852
|
+
if (!old) {
|
|
853
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, item.issues.length < 200, "ISSUE_LIMIT");
|
|
854
|
+
item.issues.push(structuredClone(issue));
|
|
855
|
+
}
|
|
856
|
+
} else if (command.type === "resolve-issue") {
|
|
857
|
+
const issue = _optionalChain([item, 'access', _159 => _159.issues, 'optionalAccess', _160 => _160.find, 'call', _161 => _161((i) => i.id === command.issueId && i.attemptId === command.attemptId)]);
|
|
858
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, issue, "ISSUE_NOT_FOUND");
|
|
859
|
+
_chunkRBOER6EWcjs.identity.call(void 0, command.resolvedBy);
|
|
860
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !issue.resolvedBy || issue.resolvedBy === command.resolvedBy, "ISSUE_ALREADY_RESOLVED");
|
|
861
|
+
issue.resolvedBy = command.resolvedBy;
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
function initializeTaskLaunch(state, item) {
|
|
865
|
+
if (item.launch) return false;
|
|
866
|
+
const first = Object.values(_nullishCoalesce(_optionalChain([state, 'access', _162 => _162.workflow, 'optionalAccess', _163 => _163.dispatches]), () => ( {}))).filter((d) => d.itemId === item.id).sort((a, b) => a.attempt - b.attempt)[0];
|
|
867
|
+
const admittedAt = _nullishCoalesce(_optionalChain([first, 'optionalAccess', _164 => _164.preparedAt]), () => ( _optionalChain([item, 'access', _165 => _165.owner, 'optionalAccess', _166 => _166.claimedAt])));
|
|
868
|
+
item.launch = { startAt: _chunkAOHQCX7Kcjs.taskStartAt.call(void 0, item), ...admittedAt === void 0 ? {} : { admittedAt } };
|
|
869
|
+
item.revision++;
|
|
870
|
+
return true;
|
|
871
|
+
}
|
|
872
|
+
function setMode(item, mode) {
|
|
873
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, ["automatic", "manual"].includes(mode), "INVALID_LAUNCH_MODE");
|
|
874
|
+
item.launch.mode = mode;
|
|
875
|
+
delete item.launch.requestedAt;
|
|
876
|
+
}
|
|
877
|
+
function cancelChildren(state, parent, controlId) {
|
|
878
|
+
const ids = /* @__PURE__ */ new Set([parent.id]);
|
|
879
|
+
for (let pass = 0; pass < state.board.items.length; pass++) {
|
|
880
|
+
const children = state.board.items.filter((item) => _optionalChain([item, 'access', _167 => _167.planning, 'optionalAccess', _168 => _168.parentId]) && ids.has(item.planning.parentId) && !ids.has(item.id));
|
|
881
|
+
if (!children.length) return;
|
|
882
|
+
for (const child of children) {
|
|
883
|
+
ids.add(child.id);
|
|
884
|
+
if (["completed", "cancelled"].includes(child.status) || _optionalChain([child, 'access', _169 => _169.control, 'optionalAccess', _170 => _170.action]) === "cancel") continue;
|
|
885
|
+
requestControl(state, child, { type: "request-control", itemId: child.id, controlId: _chunkRSH6QSECcjs.sha256HexSync.call(void 0, JSON.stringify([controlId, child.id])), action: "cancel" });
|
|
886
|
+
child.updatedAt = parent.updatedAt;
|
|
887
|
+
child.revision++;
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
function applyControlReceipt(state, item, command, actor, now) {
|
|
892
|
+
requireCoordinator(state, actor);
|
|
893
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, _optionalChain([item, 'access', _171 => _171.control, 'optionalAccess', _172 => _172.id]) === command.controlId, "STALE_CONTROL_RECEIPT");
|
|
894
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, ["accepted", "paused", "resumed", "cancelled", "failed", "unknown"].includes(command.state), "INVALID_CONTROL_STATE");
|
|
895
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, command.code === void 0 || /^[A-Z][A-Z0-9_]{0,79}$/.test(command.code), "INVALID_ERROR_CODE");
|
|
896
|
+
if (command.state === "cancelled") {
|
|
897
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, item.control.action === "cancel", "INVALID_CONTROL_STATE");
|
|
898
|
+
for (const dispatch of Object.values(_nullishCoalesce(_optionalChain([state, 'access', _173 => _173.workflow, 'optionalAccess', _174 => _174.dispatches]), () => ( {}))).filter((d) => d.itemId === item.id && ["prepared", "running", "unknown", "succeeded"].includes(d.outcome))) {
|
|
899
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, dispatch.id === item.control.dispatchId && _optionalChain([item, 'access', _175 => _175.owner, 'optionalAccess', _176 => _176.token]) === dispatch.fence, "STALE_EXECUTION_RESULT");
|
|
900
|
+
dispatch.outcome = "cancelled";
|
|
901
|
+
dispatch.code = "USER_CANCELLED";
|
|
902
|
+
}
|
|
903
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !catalog(state).some((i) => i.planning.parentId === item.id && !["completed", "cancelled"].includes(i.status)), "CHILDREN_UNFINISHED");
|
|
904
|
+
item.status = "cancelled";
|
|
905
|
+
item.closedAt = now;
|
|
906
|
+
item.closureReason = "USER_CANCELLED";
|
|
907
|
+
delete item.owner;
|
|
908
|
+
delete item.transfer;
|
|
909
|
+
delete item.blocked;
|
|
910
|
+
delete item.launch.editing;
|
|
911
|
+
}
|
|
912
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, item.control.state !== "cancelled" || command.state === "cancelled", "STALE_CONTROL_RECEIPT");
|
|
913
|
+
item.control.state = command.state;
|
|
914
|
+
item.control.code = command.code;
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
// src/board-stop.ts
|
|
918
|
+
function stopBoard(state, command, actor, now) {
|
|
919
|
+
requireCoordinator(state, actor);
|
|
920
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, actor.kind === "human", "FORBIDDEN");
|
|
921
|
+
_chunkRBOER6EWcjs.identity.call(void 0, command.controlId);
|
|
922
|
+
if (command.type === "observe-board-stop") {
|
|
923
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, _optionalChain([state, 'access', _177 => _177.board, 'access', _178 => _178.lifecycle, 'optionalAccess', _179 => _179.operationId]) === command.controlId, "STALE_CONTROL_RECEIPT");
|
|
924
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, ["waiting", "ready", "blocked"].includes(command.phase), "INVALID_CONTROL_STATE");
|
|
925
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, command.code === void 0 || /^[A-Z][A-Z0-9_]{0,79}$/.test(command.code), "INVALID_ERROR_CODE");
|
|
926
|
+
state.board.lifecycle.phase = command.phase;
|
|
927
|
+
state.board.lifecycle.code = command.code;
|
|
928
|
+
return;
|
|
929
|
+
}
|
|
930
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, ["cancel", "delete"].includes(command.intent) && ["drain", "cancel"].includes(command.mode), "INVALID_BOARD_CONTROL");
|
|
931
|
+
const old = state.board.lifecycle;
|
|
932
|
+
if (old) {
|
|
933
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, old.intent === "cancel" && command.intent === "delete" || old.operationId === command.controlId, "BOARD_STOP_PENDING");
|
|
934
|
+
if (old.operationId === command.controlId) return;
|
|
935
|
+
}
|
|
936
|
+
state.board.lifecycle = { operationId: command.controlId, intent: command.intent, mode: command.mode, phase: "waiting" };
|
|
937
|
+
state.board.executionControl = { ...state.board.executionControl, mode: "manual", paused: true, controls: {} };
|
|
938
|
+
if (state.board.automation) state.board.automation.enabled = false;
|
|
939
|
+
if (command.mode !== "cancel") return;
|
|
940
|
+
for (const item of state.board.items) if (!["completed", "cancelled"].includes(item.status)) applyTaskCommand(
|
|
941
|
+
state,
|
|
942
|
+
{ type: "request-control", itemId: item.id, controlId: _chunkRSH6QSECcjs.sha256HexSync.call(void 0, JSON.stringify([command.controlId, item.id])), action: "cancel" },
|
|
943
|
+
actor,
|
|
944
|
+
now
|
|
945
|
+
);
|
|
946
|
+
}
|
|
947
|
+
function protectStoppedBoard(state, command) {
|
|
948
|
+
if (!state.board.lifecycle) return;
|
|
949
|
+
if (command.type === "append-record" && command.record.kind === "decision") _chunkRBOER6EWcjs.requireValue.call(void 0, false, "BOARD_STOPPING");
|
|
950
|
+
const fresh = ["create-item", "admit-item", "prepare-dispatch", "continue-execution", "publish-plan", "request-run", "apply-discovery", "begin-edit", "save-edit"];
|
|
951
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !fresh.includes(command.type), "BOARD_STOPPING");
|
|
952
|
+
if (command.type === "set-board-control") _chunkRBOER6EWcjs.requireValue.call(void 0, command.paused !== false && command.mode !== "automatic", "BOARD_STOPPING");
|
|
953
|
+
if (command.type === "configure-automation") _chunkRBOER6EWcjs.requireValue.call(void 0, !command.settings.enabled, "BOARD_STOPPING");
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
// src/board-control.ts
|
|
957
|
+
function setBoardControl(state, command, actor, now, token) {
|
|
958
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, actor.kind === "human", "FORBIDDEN");
|
|
959
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, command.mode !== void 0 || command.paused !== void 0, "INVALID_BOARD_CONTROL");
|
|
960
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, command.mode === void 0 || ["automatic", "manual"].includes(command.mode), "INVALID_LAUNCH_MODE");
|
|
961
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, command.paused === void 0 || typeof command.paused === "boolean", "INVALID_BOARD_CONTROL");
|
|
962
|
+
const policy2 = state.board.executionControl ??= { mode: "automatic", paused: false, controls: {} };
|
|
963
|
+
if (command.mode) policy2.mode = command.mode;
|
|
964
|
+
if (command.paused === void 0 || command.paused === policy2.paused) return;
|
|
965
|
+
if (!command.paused) _chunkRBOER6EWcjs.requireValue.call(void 0, !state.board.items.some((item) => policy2.controls[item.id] === _optionalChain([item, 'access', _180 => _180.control, 'optionalAccess', _181 => _181.id]) && ["requested", "unknown"].includes(item.control.state)), "CONTROL_UNSETTLED");
|
|
966
|
+
policy2.paused = command.paused;
|
|
967
|
+
if (policy2.paused) policy2.controls = {};
|
|
968
|
+
state.board.items.forEach((item, index) => {
|
|
969
|
+
if (["completed", "cancelled", "review"].includes(item.status)) return;
|
|
970
|
+
const active = _optionalChain([item, 'access', _182 => _182.analysis, 'optionalAccess', _183 => _183.state]) === "analyzing" || _optionalChain([item, 'access', _184 => _184.launch, 'optionalAccess', _185 => _185.admittedAt]) !== void 0 || Object.values(_nullishCoalesce(_optionalChain([state, 'access', _186 => _186.workflow, 'optionalAccess', _187 => _187.dispatches]), () => ( {}))).some((d) => d.itemId === item.id && ["prepared", "running", "unknown"].includes(d.outcome));
|
|
971
|
+
const managed = policy2.controls[item.id] === _optionalChain([item, 'access', _188 => _188.control, 'optionalAccess', _189 => _189.id]);
|
|
972
|
+
if (policy2.paused ? !active || _optionalChain([item, 'access', _190 => _190.control, 'optionalAccess', _191 => _191.action]) === "pause" : !managed || _optionalChain([item, 'access', _192 => _192.control, 'optionalAccess', _193 => _193.action]) !== "pause") return;
|
|
973
|
+
if (item.control && ["requested", "unknown"].includes(item.control.state)) return;
|
|
974
|
+
const controlId = token + "-" + index;
|
|
975
|
+
applyTaskCommand(state, { type: "request-control", itemId: item.id, controlId, action: policy2.paused ? "pause" : "resume" }, actor, now);
|
|
976
|
+
policy2.controls[item.id] = controlId;
|
|
977
|
+
});
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
// src/scan-commit.ts
|
|
981
|
+
function applyDiscovery(state, batch, actor, now) {
|
|
982
|
+
const discovery = _chunkRBOER6EWcjs.discoveryState.call(void 0, state), pending = _optionalChain([discovery, 'optionalAccess', _194 => _194.pending]);
|
|
983
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, pending && pending.runId === batch.runId && pending.token === batch.leaseToken && pending.leaseUntil > now, "SCAN_LEASE_EXPIRED");
|
|
984
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, _optionalChain([pending, 'access', _195 => _195.request, 'optionalAccess', _196 => _196.command, 'access', _197 => _197.type]) === "apply-discovery" && JSON.stringify(pending.request.command.batch) === JSON.stringify(batch), "SCAN_BATCH_MISMATCH");
|
|
985
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, batch.changes.length <= 50, "SCAN_CHANGE_LIMIT");
|
|
986
|
+
for (const change of batch.changes) {
|
|
987
|
+
_chunkRBOER6EWcjs.identity.call(void 0, change.itemId);
|
|
988
|
+
validateSources(change.sources);
|
|
989
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, change.sources.length > 0 && change.sources.some((s) => s.role === "user"), "USER_EVIDENCE_REQUIRED");
|
|
990
|
+
const item = change.action === "create" ? createItem(state, change, actor, now, batch.autoCreate, batch.runId) : updateItem(state, change, actor, now, batch.runId);
|
|
991
|
+
if (item) attachSources(item, change, now);
|
|
992
|
+
}
|
|
993
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, (_nullishCoalesce(_optionalChain([batch, 'access', _198 => _198.records, 'optionalAccess', _199 => _199.length]), () => ( 0))) <= 20, "SCAN_RECORD_LIMIT");
|
|
994
|
+
for (const record of _nullishCoalesce(batch.records, () => ( []))) {
|
|
995
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, record.sources.some((source) => source.role === "user"), "USER_EVIDENCE_REQUIRED");
|
|
996
|
+
const duplicate = _optionalChain([state, 'access', _200 => _200.records, 'optionalAccess', _201 => _201.some, 'call', _202 => _202((old) => recordFingerprint(old) === recordFingerprint(record))]);
|
|
997
|
+
if (!duplicate) {
|
|
998
|
+
applyRecord(state, { type: "append-record", record }, actor, now, true);
|
|
999
|
+
state.records.find((entry) => entry.id === record.id).originRunId = batch.runId;
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
for (const checkpoint of batch.checkpoints) discovery.checkpoints[checkpoint.sessionId] = checkpoint.revision;
|
|
1003
|
+
discovery.lastRun = { runId: batch.runId, outcome: "committed", at: now };
|
|
1004
|
+
delete discovery.pending;
|
|
1005
|
+
}
|
|
1006
|
+
function createItem(state, change, actor, now, autoCreate, runId) {
|
|
1007
|
+
_chunkRBOER6EWcjs.text.call(void 0, change.title);
|
|
1008
|
+
_chunkRBOER6EWcjs.text.call(void 0, change.responsibility);
|
|
1009
|
+
_chunkRBOER6EWcjs.text.call(void 0, change.acceptance);
|
|
1010
|
+
const item = {
|
|
1011
|
+
origin: { kind: "discovery", principal: _chunkRBOER6EWcjs.principal.call(void 0, actor), runId },
|
|
1012
|
+
id: change.itemId,
|
|
1013
|
+
title: change.title,
|
|
1014
|
+
responsibility: change.responsibility,
|
|
1015
|
+
acceptance: change.acceptance,
|
|
1016
|
+
eligibleAgentIds: change.eligibleAgentIds,
|
|
1017
|
+
eligiblePrincipals: change.eligiblePrincipals,
|
|
1018
|
+
status: "proposed",
|
|
1019
|
+
revision: 1,
|
|
1020
|
+
createdAt: now,
|
|
1021
|
+
readyAt: now,
|
|
1022
|
+
updatedAt: now,
|
|
1023
|
+
workUnits: 0,
|
|
1024
|
+
participants: [],
|
|
1025
|
+
sources: []
|
|
1026
|
+
};
|
|
1027
|
+
item.launch = { startAt: now + _chunkAOHQCX7Kcjs.TASK_START_DELAY_MS };
|
|
1028
|
+
item.planning = _nullishCoalesce(change.planning, () => ( { ...plan(item), kind: _nullishCoalesce(state.board.defaultWorkType, () => ( "task")) }));
|
|
1029
|
+
const fingerprint = workFingerprint(item);
|
|
1030
|
+
item.origin.fingerprint = fingerprint;
|
|
1031
|
+
_chunkRBOER6EWcjs.validateCandidates.call(void 0, state.board, item, _chunkRBOER6EWcjs.executable.call(void 0, state.board, item));
|
|
1032
|
+
if (_optionalChain([state, 'access', _203 => _203.archiveIndex, 'optionalAccess', _204 => _204.some, 'call', _205 => _205((old) => old.discoveryFingerprint === fingerprint)])) return void 0;
|
|
1033
|
+
const existing = state.board.items.find((old) => workFingerprint(old) === fingerprint || _optionalChain([old, 'access', _206 => _206.origin, 'optionalAccess', _207 => _207.fingerprint]) === fingerprint);
|
|
1034
|
+
if (existing) {
|
|
1035
|
+
existing.revision++;
|
|
1036
|
+
existing.updatedAt = now;
|
|
1037
|
+
return existing;
|
|
1038
|
+
}
|
|
1039
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !state.board.items.some((old) => old.id === change.itemId) && !_optionalChain([state, 'access', _208 => _208.archiveIndex, 'optionalAccess', _209 => _209.some, 'call', _210 => _210((old) => old.id === change.itemId)]), "ITEM_EXISTS");
|
|
1040
|
+
validatePlan(state, item, item.planning);
|
|
1041
|
+
state.board.items.push(item);
|
|
1042
|
+
if (autoCreate) setStage(state, item, automaticStage(state, item), now);
|
|
1043
|
+
if (actor.sessionId) _chunkRBOER6EWcjs.participant.call(void 0, item.participants, actor.sessionId, actor.agentId, "creator", true, now);
|
|
1044
|
+
return item;
|
|
1045
|
+
}
|
|
1046
|
+
function updateItem(state, change, actor, now, runId) {
|
|
1047
|
+
const item = state.board.items.find((i) => i.id === change.itemId);
|
|
1048
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, item, "ITEM_NOT_FOUND");
|
|
1049
|
+
if (change.action === "update") {
|
|
1050
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !change.planning, "SCAN_PLANNING_REQUIRES_REVIEW");
|
|
1051
|
+
const ownDraft = item.status === "proposed" && _optionalChain([item, 'access', _211 => _211.origin, 'optionalAccess', _212 => _212.kind]) === "discovery" && _chunkRBOER6EWcjs.principalKey.call(void 0, item.origin.principal) === _chunkRBOER6EWcjs.principalKey.call(void 0, _chunkRBOER6EWcjs.principal.call(void 0, actor));
|
|
1052
|
+
if (ownDraft) {
|
|
1053
|
+
_chunkRBOER6EWcjs.text.call(void 0, change.title);
|
|
1054
|
+
_chunkRBOER6EWcjs.text.call(void 0, change.responsibility);
|
|
1055
|
+
_chunkRBOER6EWcjs.text.call(void 0, change.acceptance);
|
|
1056
|
+
item.title = change.title;
|
|
1057
|
+
item.responsibility = change.responsibility;
|
|
1058
|
+
item.acceptance = change.acceptance;
|
|
1059
|
+
} else proposeAmendment(item, change, actor, now, runId);
|
|
1060
|
+
} else _chunkRBOER6EWcjs.requireValue.call(void 0, change.action === "link", "INVALID_CHANGE");
|
|
1061
|
+
item.revision++;
|
|
1062
|
+
item.updatedAt = now;
|
|
1063
|
+
return item;
|
|
1064
|
+
}
|
|
1065
|
+
function attachSources(item, change, now) {
|
|
1066
|
+
for (const source of change.sources) {
|
|
1067
|
+
const subscribed = _nullishCoalesce(_optionalChain([item, 'access', _213 => _213.participants, 'access', _214 => _214.find, 'call', _215 => _215((p) => p.sessionId === source.sessionId), 'optionalAccess', _216 => _216.subscribed]), () => ( false));
|
|
1068
|
+
_chunkRBOER6EWcjs.participant.call(void 0, item.participants, source.sessionId, void 0, source.role === "user" ? "creator" : "consultant", subscribed, now);
|
|
1069
|
+
item.sources ??= [];
|
|
1070
|
+
if (!item.sources.some((s) => s.sessionId === source.sessionId && s.messageId === source.messageId && s.revision === source.revision)) item.sources.push(source);
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
// src/automation.ts
|
|
1075
|
+
function configureAutomation(board, settings, actor) {
|
|
1076
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, settings && typeof settings.enabled === "boolean" && typeof settings.autoAccept === "boolean", "INVALID_AUTOMATION");
|
|
1077
|
+
for (const ref of [settings.planner, settings.executor, ...settings.preparation ? [settings.preparation] : []]) {
|
|
1078
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, ref && typeof ref === "object", "INVALID_AUTOMATION_TARGET");
|
|
1079
|
+
_chunkRBOER6EWcjs.identity.call(void 0, ref.system);
|
|
1080
|
+
_chunkRBOER6EWcjs.identity.call(void 0, ref.id);
|
|
1081
|
+
_chunkRBOER6EWcjs.identity.call(void 0, _nullishCoalesce(ref.revision, () => ( "")));
|
|
1082
|
+
}
|
|
1083
|
+
validateOptions(settings.preparationOptions);
|
|
1084
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, settings.preparation || !Object.keys(_nullishCoalesce(settings.preparationOptions, () => ( {}))).length, "PREPARATION_REQUIRED");
|
|
1085
|
+
const members = [..._nullishCoalesce(board.members, () => ( [])), ...(_nullishCoalesce(board.agents, () => ( []))).filter((agent) => !_optionalChain([board, 'access', _217 => _217.members, 'optionalAccess', _218 => _218.some, 'call', _219 => _219((member) => member.kind === "agent" && member.id === agent.agentId)])).map((agent) => ({ kind: "agent", id: agent.agentId, responsibility: agent.responsibility }))];
|
|
1086
|
+
for (const [principal2, role] of [[settings.coordinator, "coordinator"], [settings.worker, "worker"]]) {
|
|
1087
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, principal2 && ["agent", "human", "service"].includes(principal2.kind), "INVALID_PRINCIPAL");
|
|
1088
|
+
_chunkRBOER6EWcjs.identity.call(void 0, principal2.id);
|
|
1089
|
+
const existing = members.find((member) => member.kind === principal2.kind && member.id === principal2.id);
|
|
1090
|
+
if (existing) existing.roles = [.../* @__PURE__ */ new Set([..._nullishCoalesce(existing.roles, () => ( [])), role])];
|
|
1091
|
+
else members.push({ ...principal2, responsibility: role, roles: [role] });
|
|
1092
|
+
}
|
|
1093
|
+
addReviewer(members, actor);
|
|
1094
|
+
board.members = members;
|
|
1095
|
+
delete board.agents;
|
|
1096
|
+
board.automation = structuredClone(settings);
|
|
1097
|
+
board.policy.review = settings.autoAccept ? "assignee" : "independent";
|
|
1098
|
+
_chunkRBOER6EWcjs.validateBoard.call(void 0, board);
|
|
1099
|
+
}
|
|
1100
|
+
function addReviewer(members, actor) {
|
|
1101
|
+
if (actor.kind !== "human" || !actor.id) return;
|
|
1102
|
+
const existing = members.find((member) => member.kind === "human" && member.id === actor.id);
|
|
1103
|
+
if (existing) existing.roles = [.../* @__PURE__ */ new Set([..._nullishCoalesce(existing.roles, () => ( [])), "reviewer", "coordinator"])];
|
|
1104
|
+
else members.push({ kind: "human", id: actor.id, responsibility: "Review work", roles: ["reviewer", "coordinator"] });
|
|
1105
|
+
}
|
|
1106
|
+
function validateOptions(options) {
|
|
1107
|
+
if (options === void 0) return;
|
|
1108
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, options && typeof options === "object" && !Array.isArray(options) && Object.keys(options).length <= 16, "INVALID_PREPARATION_OPTIONS");
|
|
1109
|
+
for (const [key, value] of Object.entries(options)) {
|
|
1110
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, /^[a-zA-Z][a-zA-Z0-9_-]{0,63}$/.test(key) && typeof value === "string" && value.length <= 4096, "INVALID_PREPARATION_OPTIONS");
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
// src/workflow-continuation.ts
|
|
1115
|
+
function continueExecution(state, command, actor, now, apply) {
|
|
1116
|
+
requireCoordinator(state, actor);
|
|
1117
|
+
_chunkRBOER6EWcjs.identity.call(void 0, command.dispatchId);
|
|
1118
|
+
const workflow = state.workflow, previous = workflow.dispatches[command.previousDispatchId];
|
|
1119
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, previous && ["failed", "cancelled"].includes(previous.outcome), "EXECUTION_NOT_CONTINUABLE");
|
|
1120
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !workflow.dispatches[command.dispatchId], "DISPATCH_EXISTS");
|
|
1121
|
+
const item = state.board.items.find((item2) => item2.id === previous.itemId), plan2 = workflow.plans[previous.planId];
|
|
1122
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, item && ["backlog", "open"].includes(item.status) && !item.owner, "ITEM_NOT_CONTINUABLE");
|
|
1123
|
+
const attempts = Object.values(workflow.dispatches).filter((row) => row.itemId === item.id);
|
|
1124
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, attempts.every((row) => row.attempt <= previous.attempt), "STALE_CONTINUATION");
|
|
1125
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !attempts.some((row) => ["prepared", "running", "unknown", "succeeded"].includes(row.outcome)), "EXECUTION_UNSETTLED");
|
|
1126
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, _optionalChain([plan2, 'optionalAccess', _220 => _220.revision]) === previous.planRevision && _optionalChain([plan2, 'access', _221 => _221.definitions, 'access', _222 => _222[item.id], 'optionalAccess', _223 => _223.digest]) === previous.definitionDigest, "PLAN_CHANGED");
|
|
1127
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, command.instruction === void 0 || typeof command.instruction === "string" && command.instruction.trim().length > 0 && command.instruction.length <= 8e3, "INVALID_CONTINUATION_INSTRUCTION");
|
|
1128
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !item.blocked || item.blocked.reason === (_nullishCoalesce(previous.code, () => ( "EXECUTION_FAILED"))), "ITEM_BLOCKED");
|
|
1129
|
+
delete item.blocked;
|
|
1130
|
+
if (item.status === "backlog") apply({ type: "set-stage", itemId: item.id, stage: "open" });
|
|
1131
|
+
apply({ type: "claim", itemId: item.id, estimate: item.estimate }, previous.principal);
|
|
1132
|
+
workflow.dispatches[command.dispatchId] = {
|
|
1133
|
+
id: command.dispatchId,
|
|
1134
|
+
itemId: item.id,
|
|
1135
|
+
itemRevision: item.revision,
|
|
1136
|
+
planId: previous.planId,
|
|
1137
|
+
planRevision: previous.planRevision,
|
|
1138
|
+
principal: previous.principal,
|
|
1139
|
+
definitionDigest: previous.definitionDigest,
|
|
1140
|
+
attempt: previous.attempt + 1,
|
|
1141
|
+
fence: item.owner.token,
|
|
1142
|
+
preparedAt: now,
|
|
1143
|
+
outcome: "prepared",
|
|
1144
|
+
inputs: structuredClone(previous.inputs),
|
|
1145
|
+
continuation: { previousDispatchId: previous.id, ...command.instruction ? { instruction: command.instruction } : {} }
|
|
1146
|
+
};
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
// src/workflow.ts
|
|
1150
|
+
function isWorkflowCommand(command) {
|
|
1151
|
+
return ["publish-plan", "prepare-dispatch", "continue-execution", "observe-execution", "accept-execution"].includes(command.type);
|
|
1152
|
+
}
|
|
1153
|
+
function protectWorkflowItem(state, command) {
|
|
1154
|
+
if (command.type === "configure-automation" && Object.values(_nullishCoalesce(_optionalChain([state, 'access', _224 => _224.workflow, 'optionalAccess', _225 => _225.dispatches]), () => ( {}))).some((dispatch) => ["prepared", "running", "unknown", "succeeded"].includes(dispatch.outcome))) {
|
|
1155
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, _chunk7KDOTBRXcjs.sameAutomationBinding.call(void 0, state.board.automation, command.settings), "PLAN_EXECUTION_UNSETTLED");
|
|
1156
|
+
}
|
|
1157
|
+
if (!("itemId" in command) || !command.itemId || !state.workflow) return;
|
|
1158
|
+
const plan2 = Object.values(state.workflow.plans).find((plan3) => plan3.itemIds.includes(command.itemId));
|
|
1159
|
+
if (!plan2) return;
|
|
1160
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !["edit-item", "plan-item", "review-amendment"].includes(command.type), "PLAN_ITEM_CHANGED_REQUIRES_NEW_ID");
|
|
1161
|
+
if (plan2.sealed) _chunkRBOER6EWcjs.requireValue.call(void 0, !["claim", "submit", "review", "close-plan"].includes(command.type), "WORKFLOW_COMMAND_REQUIRED");
|
|
1162
|
+
const live = Object.values(state.workflow.dispatches).some((dispatch) => dispatch.itemId === command.itemId && ["prepared", "running", "unknown", "succeeded"].includes(dispatch.outcome));
|
|
1163
|
+
if (live) _chunkRBOER6EWcjs.requireValue.call(void 0, !["delete-item", "request-transfer", "accept-transfer", "release-item", "cancel-item"].includes(command.type), "EXECUTION_UNSETTLED");
|
|
1164
|
+
}
|
|
1165
|
+
function applyWorkflow(state, command, actor, now, apply) {
|
|
1166
|
+
state.workflow ??= { plans: {}, dispatches: {}, ready: [], completedPlans: [] };
|
|
1167
|
+
let changed = true;
|
|
1168
|
+
if (command.type === "publish-plan") publishPlan(state, command.plan, actor, apply);
|
|
1169
|
+
else if (command.type === "prepare-dispatch") prepare(state, command, actor, now, apply);
|
|
1170
|
+
else if (command.type === "continue-execution") {
|
|
1171
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !_optionalChain([state, 'access', _226 => _226.board, 'access', _227 => _227.executionControl, 'optionalAccess', _228 => _228.paused]), "BOARD_EXECUTION_PAUSED");
|
|
1172
|
+
continueExecution(state, command, actor, now, apply);
|
|
1173
|
+
} else if (command.type === "observe-execution") changed = observe(state, command, actor, now);
|
|
1174
|
+
else accept(state, command, actor, apply);
|
|
1175
|
+
refreshReady(state);
|
|
1176
|
+
return changed;
|
|
1177
|
+
}
|
|
1178
|
+
function prepare(state, command, actor, now, apply) {
|
|
1179
|
+
_chunkRBOER6EWcjs.identity.call(void 0, command.dispatchId);
|
|
1180
|
+
const workflow = state.workflow;
|
|
1181
|
+
const controlled = state.board.items.find((item2) => item2.id === command.itemId);
|
|
1182
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !_optionalChain([controlled, 'optionalAccess', _229 => _229.control]) || controlled.control.action === "resume" && controlled.control.state === "resumed", "TASK_CONTROL_PENDING");
|
|
1183
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !workflow.dispatches[command.dispatchId], "DISPATCH_EXISTS");
|
|
1184
|
+
refreshReady(state);
|
|
1185
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, workflow.ready.includes(command.itemId), "WORK_NOT_READY");
|
|
1186
|
+
const plan2 = Object.values(workflow.plans).find((plan3) => plan3.itemIds.includes(command.itemId));
|
|
1187
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !Object.values(workflow.dispatches).some((dispatch) => dispatch.itemId === command.itemId && ["prepared", "running", "unknown", "succeeded"].includes(dispatch.outcome)), "EXECUTION_UNSETTLED");
|
|
1188
|
+
const item = state.board.items.find((item2) => item2.id === command.itemId);
|
|
1189
|
+
if (item.status === "backlog") apply({ type: "set-stage", itemId: item.id, stage: "open" });
|
|
1190
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !_chunkAOHQCX7Kcjs.taskEditing.call(void 0, item, now), "EDIT_LEASE_ACTIVE");
|
|
1191
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !_optionalChain([state, 'access', _230 => _230.board, 'access', _231 => _231.executionControl, 'optionalAccess', _232 => _232.paused]), "BOARD_EXECUTION_PAUSED");
|
|
1192
|
+
if (command.trigger === "automatic") _chunkRBOER6EWcjs.requireValue.call(void 0, _chunkAOHQCX7Kcjs.boardAllowsStart.call(void 0, state.board, item) && _chunkAOHQCX7Kcjs.taskDue.call(void 0, item, now), "START_NOT_DUE");
|
|
1193
|
+
item.launch ??= { startAt: _chunkAOHQCX7Kcjs.taskStartAt.call(void 0, item) };
|
|
1194
|
+
item.launch.admittedAt ??= now;
|
|
1195
|
+
apply({ type: "claim", itemId: item.id, estimate: command.estimate });
|
|
1196
|
+
const inputs = {};
|
|
1197
|
+
for (const [name, binding] of Object.entries(_nullishCoalesce(plan2.definitions[item.id].inputs, () => ( {})))) {
|
|
1198
|
+
const producer = Object.values(workflow.dispatches).reverse().find((dispatch) => dispatch.itemId === binding.fromItemId && dispatch.outcome === "accepted");
|
|
1199
|
+
const output = _optionalChain([producer, 'optionalAccess', _233 => _233.outputs, 'optionalAccess', _234 => _234.find, 'call', _235 => _235((output2) => output2.name === binding.output)]);
|
|
1200
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, output, "DEPENDENCY_OUTPUT_MISSING");
|
|
1201
|
+
inputs[name] = structuredClone(output);
|
|
1202
|
+
}
|
|
1203
|
+
const attempt = Math.max(0, ...Object.values(workflow.dispatches).filter((dispatch) => dispatch.itemId === item.id).map((dispatch) => dispatch.attempt)) + 1;
|
|
1204
|
+
workflow.dispatches[command.dispatchId] = { id: command.dispatchId, itemId: item.id, itemRevision: item.revision, planId: plan2.id, planRevision: plan2.revision, principal: _chunkRBOER6EWcjs.principal.call(void 0, actor), definitionDigest: plan2.definitions[item.id].digest, attempt, fence: item.owner.token, preparedAt: now, outcome: "prepared", inputs };
|
|
1205
|
+
}
|
|
1206
|
+
function observe(state, command, actor, now) {
|
|
1207
|
+
requireCoordinator(state, actor);
|
|
1208
|
+
const dispatch = activeDispatch(state, command.dispatchId);
|
|
1209
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, command.fence === dispatch.fence && ["prepared", "running", "unknown"].includes(dispatch.outcome), "STALE_EXECUTION_RESULT");
|
|
1210
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, ["running", "unknown", "succeeded", "failed", "cancelled"].includes(command.outcome), "INVALID_EXECUTION_OUTCOME");
|
|
1211
|
+
if (command.code !== void 0) _chunkRBOER6EWcjs.requireValue.call(void 0, /^[A-Z][A-Z0-9_]{0,79}$/.test(command.code), "INVALID_ERROR_CODE");
|
|
1212
|
+
const item = state.board.items.find((item2) => item2.id === dispatch.itemId);
|
|
1213
|
+
if (command.executionSessionId) {
|
|
1214
|
+
_chunkRBOER6EWcjs.identity.call(void 0, command.executionSessionId);
|
|
1215
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !dispatch.executionSessionId || dispatch.executionSessionId === command.executionSessionId, "EXECUTION_SESSION_LOCKED");
|
|
1216
|
+
dispatch.executionSessionId = command.executionSessionId;
|
|
1217
|
+
}
|
|
1218
|
+
if (command.controlCapabilities) {
|
|
1219
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, ["boundary", "none"].includes(command.controlCapabilities.pause) && typeof command.controlCapabilities.resume === "boolean", "INVALID_CONTROL_CAPABILITIES");
|
|
1220
|
+
dispatch.controlCapabilities = structuredClone(command.controlCapabilities);
|
|
1221
|
+
}
|
|
1222
|
+
const outputs = _nullishCoalesce(command.outputs, () => ( []));
|
|
1223
|
+
validateOutputs(outputs);
|
|
1224
|
+
if (["running", "unknown"].includes(command.outcome)) item.owner.leaseUntil = Math.max(item.owner.leaseUntil, now + state.board.policy.leaseMs);
|
|
1225
|
+
if (!_chunk4XF6LQSUcjs.executionObservationChanged.call(void 0, dispatch, command)) return false;
|
|
1226
|
+
if (command.outcome === "succeeded") {
|
|
1227
|
+
const required = state.workflow.plans[dispatch.planId].definitions[item.id].outputs;
|
|
1228
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, required.every((name) => outputs.some((output) => output.name === name)), "REQUIRED_OUTPUT_MISSING");
|
|
1229
|
+
item.status = state.board.policy.review === "assignee" ? "completed" : "review";
|
|
1230
|
+
if (item.status === "completed") item.closedAt = now;
|
|
1231
|
+
item.resultRef = `kanban:dispatch:${dispatch.id}`;
|
|
1232
|
+
dispatch.outputs = structuredClone(outputs);
|
|
1233
|
+
} else if (command.outcome === "failed" || command.outcome === "cancelled") {
|
|
1234
|
+
item.status = "backlog";
|
|
1235
|
+
item.blocked = { reason: _nullishCoalesce(command.code, () => ( "EXECUTION_FAILED")), at: now };
|
|
1236
|
+
delete item.owner;
|
|
1237
|
+
}
|
|
1238
|
+
dispatch.outcome = command.outcome === "succeeded" && state.board.policy.review === "assignee" ? "accepted" : command.outcome;
|
|
1239
|
+
dispatch.code = command.code;
|
|
1240
|
+
item.updatedAt = now;
|
|
1241
|
+
item.revision++;
|
|
1242
|
+
dispatch.itemRevision = item.revision;
|
|
1243
|
+
return true;
|
|
1244
|
+
}
|
|
1245
|
+
function accept(state, command, actor, apply) {
|
|
1246
|
+
requireCoordinator(state, actor);
|
|
1247
|
+
const dispatch = activeDispatch(state, command.dispatchId);
|
|
1248
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, _optionalChain([state, 'access', _236 => _236.board, 'access', _237 => _237.items, 'access', _238 => _238.find, 'call', _239 => _239((item) => item.id === dispatch.itemId), 'optionalAccess', _240 => _240.control, 'optionalAccess', _241 => _241.action]) !== "cancel", "TASK_CANCELLING");
|
|
1249
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, dispatch.outcome === "succeeded", "EXECUTION_NOT_SUCCEEDED");
|
|
1250
|
+
apply({ type: "review", itemId: dispatch.itemId, accept: command.accept }, actor);
|
|
1251
|
+
dispatch.outcome = command.accept ? "accepted" : "rejected";
|
|
1252
|
+
if (!command.accept) {
|
|
1253
|
+
const item = state.board.items.find((item2) => item2.id === dispatch.itemId);
|
|
1254
|
+
item.status = "backlog";
|
|
1255
|
+
item.blocked = { reason: "EXECUTION_REJECTED", at: item.updatedAt };
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
function activeDispatch(state, id) {
|
|
1259
|
+
const dispatch = state.workflow.dispatches[id];
|
|
1260
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, dispatch, "DISPATCH_NOT_FOUND");
|
|
1261
|
+
const item = state.board.items.find((item2) => item2.id === dispatch.itemId), plan2 = state.workflow.plans[dispatch.planId];
|
|
1262
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, _optionalChain([plan2, 'optionalAccess', _242 => _242.revision]) === dispatch.planRevision && _optionalChain([item, 'optionalAccess', _243 => _243.owner, 'optionalAccess', _244 => _244.token]) === dispatch.fence && _optionalChain([plan2, 'access', _245 => _245.definitions, 'access', _246 => _246[dispatch.itemId], 'optionalAccess', _247 => _247.digest]) === dispatch.definitionDigest, "STALE_EXECUTION_RESULT");
|
|
1263
|
+
return dispatch;
|
|
1264
|
+
}
|
|
1265
|
+
function validateOutputs(outputs) {
|
|
1266
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, Array.isArray(outputs) && outputs.length <= 100 && outputs.every((output) => output && typeof output === "object" && typeof output.name === "string") && new Set(outputs.map((output) => output.name)).size === outputs.length, "INVALID_OUTPUTS");
|
|
1267
|
+
for (const output of outputs) _chunkRBOER6EWcjs.requireValue.call(void 0, /^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$/.test(output.name) && typeof output.ref === "string" && output.ref.length > 0 && output.ref.length <= 2048 && /^[a-f0-9]{64}$/.test(output.sha256) && Number.isSafeInteger(output.bytes) && output.bytes >= 0, "INVALID_OUTPUT_REFERENCE");
|
|
1268
|
+
}
|
|
1269
|
+
function refreshReady(state) {
|
|
1270
|
+
if (!state.workflow) return;
|
|
1271
|
+
const all = catalog(state), included = new Set(Object.values(state.workflow.plans).filter((plan2) => plan2.sealed).flatMap((plan2) => plan2.itemIds));
|
|
1272
|
+
state.workflow.completedPlans = Object.values(state.workflow.plans).filter((plan2) => plan2.sealed && plan2.itemIds.every((id) => _optionalChain([all, 'access', _248 => _248.find, 'call', _249 => _249((item) => item.id === id), 'optionalAccess', _250 => _250.status]) === "completed")).map((plan2) => plan2.id);
|
|
1273
|
+
state.workflow.ready = state.board.items.filter((item) => included.has(item.id) && _chunk7KDOTBRXcjs.executableWorkItem.call(void 0, state.board, item) && ["backlog", "open"].includes(item.status) && !item.owner && !item.blocked && (!item.control || item.control.action === "resume" && item.control.state === "resumed") && (_nullishCoalesce(_optionalChain([item, 'access', _251 => _251.planning, 'optionalAccess', _252 => _252.dependencies]), () => ( []))).every((id) => _optionalChain([all, 'access', _253 => _253.find, 'call', _254 => _254((other) => other.id === id), 'optionalAccess', _255 => _255.status]) === "completed")).map((item) => item.id);
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
// src/transitions.ts
|
|
1277
|
+
function transition(state, item, command, actor, now, token) {
|
|
1278
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, item.status !== "completed" && item.status !== "cancelled", "ITEM_COMPLETED");
|
|
1279
|
+
if (command.type === "claim" || command.type === "accept-transfer") claim(state, item, command, actor, now, token);
|
|
1280
|
+
else if (command.type === "review") review(state, item, command.accept, actor, now);
|
|
1281
|
+
else {
|
|
1282
|
+
_chunkRBOER6EWcjs.owned.call(void 0, item, actor, command.token, now);
|
|
1283
|
+
if (command.type === "submit") _chunkRBOER6EWcjs.requireValue.call(void 0, catalog(state).filter((i) => i.planning.parentId === item.id).every(terminal), "CHILDREN_UNFINISHED");
|
|
1284
|
+
ownerUpdate(state.board, item, command, now, token);
|
|
1285
|
+
}
|
|
1286
|
+
if (command.type !== "renew") {
|
|
1287
|
+
item.revision++;
|
|
1288
|
+
item.updatedAt = now;
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
function claim(state, item, command, actor, now, token) {
|
|
1292
|
+
const board = state.board, key = _chunkRBOER6EWcjs.principalKey.call(void 0, _chunkRBOER6EWcjs.principal.call(void 0, actor));
|
|
1293
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !_chunkAOHQCX7Kcjs.taskEditing.call(void 0, item, now), "EDIT_LEASE_ACTIVE");
|
|
1294
|
+
_chunkRBOER6EWcjs.eligible.call(void 0, board, item, actor);
|
|
1295
|
+
assertReady(state, item);
|
|
1296
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, command.estimate || board.policy.requireEstimate === false, "ESTIMATE_REQUIRED");
|
|
1297
|
+
if (command.estimate) _chunkRBOER6EWcjs.validateEstimate.call(void 0, command.estimate);
|
|
1298
|
+
const wip = board.items.filter((i) => i.status === "claimed" || i.status === "review");
|
|
1299
|
+
if (command.type === "claim") _chunkRBOER6EWcjs.requireValue.call(void 0, wip.length < limits(state).inProgress, "WIP_LIMIT");
|
|
1300
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, wip.filter((i) => i.id !== item.id && i.owner && _chunkRBOER6EWcjs.assigneeKey.call(void 0, i.owner) === key).length < limits(state).perAssignee, _chunkRBOER6EWcjs.principal.call(void 0, actor).kind === "agent" ? "AGENT_WIP_LIMIT" : "ASSIGNEE_WIP_LIMIT");
|
|
1301
|
+
if (command.type === "claim") _chunkRBOER6EWcjs.requireValue.call(void 0, item.status === "open" && !item.owner, "ALREADY_OWNED");
|
|
1302
|
+
else {
|
|
1303
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, item.status === "claimed" && item.transfer && _chunkRBOER6EWcjs.principalKey.call(void 0, transferTarget(item.transfer)) === key, "TRANSFER_NOT_OFFERED");
|
|
1304
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, item.transfer.expiresAt > now && item.owner && item.owner.leaseUntil > now, "TRANSFER_EXPIRED");
|
|
1305
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, _chunkRBOER6EWcjs.assigneeKey.call(void 0, item.owner) !== key, "SELF_TRANSFER");
|
|
1306
|
+
}
|
|
1307
|
+
item.owner = { ...actor, principalId: key, token, claimedAt: now, leaseUntil: now + board.policy.leaseMs };
|
|
1308
|
+
item.estimate = command.estimate;
|
|
1309
|
+
item.status = "claimed";
|
|
1310
|
+
item.progressAt = now;
|
|
1311
|
+
delete item.transfer;
|
|
1312
|
+
if (actor.sessionId) _chunkRBOER6EWcjs.participant.call(void 0, item.participants, actor.sessionId, actor.agentId, "owner", true, now);
|
|
1313
|
+
}
|
|
1314
|
+
function review(state, item, accept2, actor, now) {
|
|
1315
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, _optionalChain([item, 'access', _256 => _256.control, 'optionalAccess', _257 => _257.action]) !== "cancel", "TASK_CANCELLING");
|
|
1316
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, item.status === "review", "NOT_IN_REVIEW");
|
|
1317
|
+
const key = _chunkRBOER6EWcjs.principalKey.call(void 0, _chunkRBOER6EWcjs.principal.call(void 0, actor));
|
|
1318
|
+
const registered = actor.sessionId && item.participants.some((p) => p.sessionId === actor.sessionId && p.roles.includes("reviewer")) || _optionalChain([state, 'access', _258 => _258.board, 'access', _259 => _259.members, 'optionalAccess', _260 => _260.some, 'call', _261 => _261((m) => _chunkRBOER6EWcjs.principalKey.call(void 0, m) === key && _optionalChain([m, 'access', _262 => _262.roles, 'optionalAccess', _263 => _263.includes, 'call', _264 => _264("reviewer")]))]);
|
|
1319
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, registered, "REVIEWER_REQUIRED");
|
|
1320
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !item.owner || _chunkRBOER6EWcjs.assigneeKey.call(void 0, item.owner) !== key, "INDEPENDENT_REVIEW_REQUIRED");
|
|
1321
|
+
item.status = accept2 ? "completed" : state.board.items.filter((i) => i.status === "open").length < limits(state).ready ? "open" : "backlog";
|
|
1322
|
+
if (accept2) item.closedAt = now;
|
|
1323
|
+
if (!accept2) {
|
|
1324
|
+
delete item.owner;
|
|
1325
|
+
delete item.estimate;
|
|
1326
|
+
delete item.resultRef;
|
|
1327
|
+
item.readyAt = now;
|
|
1328
|
+
}
|
|
1329
|
+
}
|
|
1330
|
+
function ownerUpdate(board, item, command, now, token) {
|
|
1331
|
+
switch (command.type) {
|
|
1332
|
+
case "renew":
|
|
1333
|
+
item.owner.leaseUntil = now + board.policy.leaseMs;
|
|
1334
|
+
break;
|
|
1335
|
+
case "progress":
|
|
1336
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, Number.isFinite(command.workUnits) && command.workUnits >= item.workUnits, "INVALID_WORK_UNITS");
|
|
1337
|
+
item.workUnits = command.workUnits;
|
|
1338
|
+
item.progressAt = now;
|
|
1339
|
+
if (command.estimate) {
|
|
1340
|
+
_chunkRBOER6EWcjs.validateEstimate.call(void 0, command.estimate);
|
|
1341
|
+
item.estimate = command.estimate;
|
|
1342
|
+
}
|
|
1343
|
+
break;
|
|
1344
|
+
case "request-transfer":
|
|
1345
|
+
requestTransfer(board, item, command, now, token);
|
|
1346
|
+
break;
|
|
1347
|
+
case "submit":
|
|
1348
|
+
_chunkRBOER6EWcjs.text.call(void 0, command.resultRef);
|
|
1349
|
+
item.resultRef = command.resultRef;
|
|
1350
|
+
item.status = board.policy.review === "assignee" ? "completed" : "review";
|
|
1351
|
+
if (item.status === "completed") item.closedAt = now;
|
|
1352
|
+
delete item.transfer;
|
|
1353
|
+
break;
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
function requestTransfer(board, item, command, now, token) {
|
|
1357
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, Boolean(command.target) !== Boolean(command.agentId), "TRANSFER_TARGET_REQUIRED");
|
|
1358
|
+
const target = _nullishCoalesce(command.target, () => ( { kind: "agent", id: command.agentId })), key = _chunkRBOER6EWcjs.principalKey.call(void 0, target);
|
|
1359
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, _chunkRBOER6EWcjs.candidates.call(void 0, board, item).some((p) => _chunkRBOER6EWcjs.principalKey.call(void 0, p) === key), "AGENT_NOT_ELIGIBLE");
|
|
1360
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, _chunkRBOER6EWcjs.assigneeKey.call(void 0, item.owner) !== key, "SELF_TRANSFER");
|
|
1361
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !item.transfer, "TRANSFER_ALREADY_PENDING");
|
|
1362
|
+
item.transfer = { id: token, target, ...target.kind === "agent" ? { agentId: target.id } : {}, requestedAt: now, expiresAt: now + board.policy.transferTimeoutMs };
|
|
1363
|
+
}
|
|
1364
|
+
function transferTarget(value) {
|
|
1365
|
+
return _nullishCoalesce(value.target, () => ( { kind: "agent", id: value.agentId }));
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1368
|
+
// src/reducer.ts
|
|
1369
|
+
function reduce(state, command, actor, operationId, now, token, workflowInternal = false) {
|
|
1370
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, state.board.deletedAt === void 0, "BOARD_DELETED");
|
|
1371
|
+
numberEntities(state);
|
|
1372
|
+
protectStoppedBoard(state, command);
|
|
1373
|
+
if ("itemId" in command && command.itemId) _chunkRBOER6EWcjs.requireValue.call(void 0, _optionalChain([state, 'access', _265 => _265.board, 'access', _266 => _266.items, 'access', _267 => _267.find, 'call', _268 => _268((i) => i.id === command.itemId), 'optionalAccess', _269 => _269.deletedAt]) === void 0, "ITEM_DELETED");
|
|
1374
|
+
if (!workflowInternal) protectWorkflowItem(state, command);
|
|
1375
|
+
const board = state.board;
|
|
1376
|
+
if (command.type === "delete-board") return deleteBoard(state, actor, operationId, now);
|
|
1377
|
+
if (command.type === "scan") {
|
|
1378
|
+
scan(state, actor, operationId, now);
|
|
1379
|
+
refreshReady(state);
|
|
1380
|
+
return state;
|
|
1381
|
+
}
|
|
1382
|
+
let recordEvent = command.type !== "renew";
|
|
1383
|
+
if (command.type === "request-board-stop" || command.type === "observe-board-stop") stopBoard(state, command, actor, now);
|
|
1384
|
+
else if (command.type === "set-board-control") setBoardControl(state, command, actor, now, token);
|
|
1385
|
+
else if (command.type === "delete-item") {
|
|
1386
|
+
const item = itemFor(board, command.itemId);
|
|
1387
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, _chunkRBOER6EWcjs.principal.call(void 0, actor).kind === "human", "FORBIDDEN");
|
|
1388
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, terminal(item), "ITEM_DELETE_REQUIRES_CLOSED");
|
|
1389
|
+
delete item.owner;
|
|
1390
|
+
delete item.transfer;
|
|
1391
|
+
item.deletedAt = now;
|
|
1392
|
+
item.updatedAt = now;
|
|
1393
|
+
item.revision++;
|
|
1394
|
+
} else if (taskCommand(command)) applyTaskCommand(state, command, actor, now);
|
|
1395
|
+
else if (isWorkflowCommand(command)) recordEvent = applyWorkflow(state, command, actor, now, (inner, owner = actor) => {
|
|
1396
|
+
reduce(state, inner, owner, operationId, now, token, true);
|
|
1397
|
+
});
|
|
1398
|
+
else if (command.type === "apply-discovery") applyDiscovery(state, command.batch, actor, now);
|
|
1399
|
+
else if (isRecordCommand(command)) applyRecord(state, command, actor, now);
|
|
1400
|
+
else if (command.type === "review-amendment") {
|
|
1401
|
+
if (command.accept) assertDefinitionEditable(itemFor(board, command.itemId), now);
|
|
1402
|
+
reviewAmendment(board, command, actor, now);
|
|
1403
|
+
} else if (planningCommand(command)) applyPlanningCommand(state, command, now, actor, workflowInternal);
|
|
1404
|
+
else if (command.type === "create-item") createItem2(state, command, actor, now, token);
|
|
1405
|
+
else if (command.type === "configure-automation") configureAutomation(board, command.settings, actor);
|
|
1406
|
+
else if (command.type === "register-session") {
|
|
1407
|
+
const item = command.itemId ? itemFor(board, command.itemId) : void 0;
|
|
1408
|
+
const list = item ? item.participants : board.participants;
|
|
1409
|
+
_chunkRBOER6EWcjs.participant.call(void 0, list, command.sessionId, command.agentId, command.role, command.subscribed, now);
|
|
1410
|
+
if (item) item.revision++;
|
|
1411
|
+
} else if (command.type === "message") {
|
|
1412
|
+
_chunkRBOER6EWcjs.text.call(void 0, command.message);
|
|
1413
|
+
command.recipientSessionIds.forEach(_chunkRBOER6EWcjs.identity);
|
|
1414
|
+
if (command.itemId) itemFor(board, command.itemId);
|
|
1415
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, command.recipientSessionIds.every((id) => related(board).includes(id)), "UNKNOWN_RECIPIENT");
|
|
1416
|
+
} else transition(state, itemFor(board, command.itemId), command, actor, now, token);
|
|
1417
|
+
numberEntities(state);
|
|
1418
|
+
refreshReady(state);
|
|
1419
|
+
board.revision++;
|
|
1420
|
+
if (recordEvent) append2(
|
|
1421
|
+
state,
|
|
1422
|
+
actor,
|
|
1423
|
+
operationId,
|
|
1424
|
+
now,
|
|
1425
|
+
command.type,
|
|
1426
|
+
"itemId" in command ? command.itemId : command.type === "create-item" ? command.item.id : "dispatchId" in command ? _optionalChain([state, 'access', _270 => _270.workflow, 'optionalAccess', _271 => _271.dispatches, 'access', _272 => _272[command.dispatchId], 'optionalAccess', _273 => _273.itemId]) : void 0,
|
|
1427
|
+
eventData(command, state),
|
|
1428
|
+
command.type === "message" ? command.recipientSessionIds : void 0
|
|
1429
|
+
);
|
|
1430
|
+
scan(state, actor, operationId, now);
|
|
1431
|
+
return state;
|
|
1432
|
+
}
|
|
1433
|
+
function createItem2(state, command, actor, now, token) {
|
|
1434
|
+
const { id, title, responsibility, acceptance, eligibleAgentIds, eligiblePrincipals, externalRefs } = command.item;
|
|
1435
|
+
const input = { id, title, responsibility, acceptance, eligibleAgentIds, eligiblePrincipals, externalRefs }, board = state.board;
|
|
1436
|
+
_chunkRBOER6EWcjs.identity.call(void 0, input.id);
|
|
1437
|
+
_chunkRBOER6EWcjs.text.call(void 0, input.title);
|
|
1438
|
+
_chunkRBOER6EWcjs.text.call(void 0, input.responsibility);
|
|
1439
|
+
_chunkRBOER6EWcjs.text.call(void 0, input.acceptance);
|
|
1440
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !board.items.some((i) => i.id === input.id) && !_optionalChain([state, 'access', _274 => _274.archiveIndex, 'optionalAccess', _275 => _275.some, 'call', _276 => _276((i) => i.id === input.id)]), "ITEM_EXISTS");
|
|
1441
|
+
const item = { ...input, origin: { kind: "direct", principal: _chunkRBOER6EWcjs.principal.call(void 0, actor) }, status: "backlog", revision: 1, createdAt: now, readyAt: now, updatedAt: now, workUnits: 0, participants: [] };
|
|
1442
|
+
item.launch = { startAt: now + _chunkAOHQCX7Kcjs.TASK_START_DELAY_MS };
|
|
1443
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, _optionalChain([command, 'access', _277 => _277.launch, 'optionalAccess', _278 => _278.mode]) === void 0 || ["automatic", "manual"].includes(command.launch.mode), "INVALID_LAUNCH_MODE");
|
|
1444
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, _optionalChain([command, 'access', _279 => _279.launch, 'optionalAccess', _280 => _280.paused]) === void 0 || typeof command.launch.paused === "boolean", "INVALID_TASK_PAUSE");
|
|
1445
|
+
if (_optionalChain([command, 'access', _281 => _281.launch, 'optionalAccess', _282 => _282.mode])) item.launch.mode = command.launch.mode;
|
|
1446
|
+
if (_optionalChain([command, 'access', _283 => _283.launch, 'optionalAccess', _284 => _284.paused])) item.control = { id: "initial-" + token, action: "pause", state: "paused" };
|
|
1447
|
+
item.planning = _nullishCoalesce(command.planning, () => ( { ...plan(item), kind: _nullishCoalesce(board.defaultWorkType, () => ( "task")) }));
|
|
1448
|
+
const references = _nullishCoalesce(item.externalRefs, () => ( []));
|
|
1449
|
+
item.externalRefs = [];
|
|
1450
|
+
for (const reference of references) attachReference(item, reference);
|
|
1451
|
+
_chunkRBOER6EWcjs.validateCandidates.call(void 0, board, item, _chunkRBOER6EWcjs.executable.call(void 0, board, item));
|
|
1452
|
+
validatePlan(state, item, item.planning);
|
|
1453
|
+
if (item.planning.parentId) {
|
|
1454
|
+
const parent = board.items.find((parent2) => parent2.id === item.planning.parentId);
|
|
1455
|
+
if (_optionalChain([parent, 'access', _285 => _285.planning, 'optionalAccess', _286 => _286.execution]) !== "children") {
|
|
1456
|
+
parent.planning = { ...plan(parent), execution: "children" };
|
|
1457
|
+
parent.updatedAt = now;
|
|
1458
|
+
parent.revision++;
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
if (actor.sessionId) _chunkRBOER6EWcjs.participant.call(void 0, item.participants, actor.sessionId, actor.agentId, "creator", true, now);
|
|
1462
|
+
board.items.push(item);
|
|
1463
|
+
if (command.stage === "open") setStage(state, item, "open", now);
|
|
1464
|
+
}
|
|
1465
|
+
function itemFor(board, id) {
|
|
1466
|
+
const item = board.items.find((value) => value.id === id);
|
|
1467
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, item, "ITEM_NOT_FOUND");
|
|
1468
|
+
return item;
|
|
1469
|
+
}
|
|
1470
|
+
function related(board) {
|
|
1471
|
+
return [...new Set([...board.participants, ...board.items.flatMap((i) => i.participants)].map((p) => p.sessionId))];
|
|
1472
|
+
}
|
|
1473
|
+
function append2(state, actor, operationId, at, kind, itemId, data = {}, recipients) {
|
|
1474
|
+
const archived = _nullishCoalesce(_optionalChain([state, 'access', _287 => _287.archiveWrites, 'optionalAccess', _288 => _288.flatMap, 'call', _289 => _289((write) => _nullishCoalesce(_optionalChain([write, 'access', _290 => _290.value, 'optionalAccess', _291 => _291.item, 'access', _292 => _292.participants]), () => ( [])))]), () => ( []));
|
|
1475
|
+
const members = [...archived, ...state.board.participants, ...state.board.items.filter((i) => i.id === itemId).flatMap((i) => i.participants)];
|
|
1476
|
+
state.events.push({
|
|
1477
|
+
sequence: ++state.sequence,
|
|
1478
|
+
boardId: state.board.id,
|
|
1479
|
+
itemId,
|
|
1480
|
+
operationId,
|
|
1481
|
+
at,
|
|
1482
|
+
kind,
|
|
1483
|
+
actor,
|
|
1484
|
+
recipients: [...new Set(_nullishCoalesce(recipients, () => ( members.filter((p) => p.subscribed).map((p) => p.sessionId))))],
|
|
1485
|
+
data
|
|
1486
|
+
});
|
|
1487
|
+
}
|
|
1488
|
+
function scan(state, actor, operationId, now) {
|
|
1489
|
+
for (const item of state.board.items) {
|
|
1490
|
+
if (initializeTaskLaunch(state, item)) {
|
|
1491
|
+
state.board.revision++;
|
|
1492
|
+
append2(state, actor, operationId, now, "task-launch-initialized", item.id, { code: "LEGACY_LAUNCH_INITIALIZED" });
|
|
1493
|
+
}
|
|
1494
|
+
if (terminal(item)) continue;
|
|
1495
|
+
for (const reason of escalationReasons(state.board, item, now)) {
|
|
1496
|
+
const epoch = reason === "transfer-timeout" ? _optionalChain([item, 'access', _293 => _293.transfer, 'optionalAccess', _294 => _294.id]) : reason === "backlog-review" ? item.updatedAt : _nullishCoalesce(_optionalChain([item, 'access', _295 => _295.owner, 'optionalAccess', _296 => _296.token]), () => ( item.readyAt));
|
|
1497
|
+
const key = JSON.stringify([item.id, epoch, reason]);
|
|
1498
|
+
if (state.escalations.includes(key)) continue;
|
|
1499
|
+
state.escalations.push(key);
|
|
1500
|
+
state.board.revision++;
|
|
1501
|
+
append2(state, actor, operationId, now, "escalated", item.id, { reason }, state.board.policy.escalationSessionIds);
|
|
1502
|
+
}
|
|
1503
|
+
if (item.transfer && item.transfer.expiresAt <= now) {
|
|
1504
|
+
delete item.transfer;
|
|
1505
|
+
item.revision++;
|
|
1506
|
+
item.updatedAt = now;
|
|
1507
|
+
state.board.revision++;
|
|
1508
|
+
}
|
|
1509
|
+
}
|
|
1510
|
+
const archived = archiveExpired(state, now);
|
|
1511
|
+
if (archived.length) {
|
|
1512
|
+
state.board.revision++;
|
|
1513
|
+
append2(state, actor, operationId, now, "items.archived", void 0, { reason: "retention-policy" });
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
function escalationReasons(board, item, now) {
|
|
1517
|
+
const p = board.policy, result = [];
|
|
1518
|
+
if (item.status === "backlog" && p.backlogReviewMs && now - item.updatedAt >= p.backlogReviewMs) result.push("backlog-review");
|
|
1519
|
+
if (_optionalChain([item, 'access', _297 => _297.planning, 'optionalAccess', _298 => _298.dueAt]) !== void 0 && now >= item.planning.dueAt) result.push("due-date");
|
|
1520
|
+
if (item.blocked && now - item.blocked.at >= p.progressTimeoutMs) result.push("blocked-age");
|
|
1521
|
+
if (!item.blocked && item.status === "open" && now - item.readyAt >= p.claimTimeoutMs) result.push("unclaimed");
|
|
1522
|
+
if (item.status === "review" && now - item.updatedAt >= p.progressTimeoutMs) result.push("review-timeout");
|
|
1523
|
+
if (item.transfer && now >= item.transfer.expiresAt) result.push("transfer-timeout");
|
|
1524
|
+
if (item.status !== "claimed" || !item.owner) return result;
|
|
1525
|
+
if (now >= item.owner.leaseUntil) result.push("lease-expired");
|
|
1526
|
+
if (now - (_nullishCoalesce(item.progressAt, () => ( item.owner.claimedAt))) >= p.progressTimeoutMs) result.push("no-progress");
|
|
1527
|
+
if (now - item.owner.claimedAt >= Math.min(_nullishCoalesce(_optionalChain([item, 'access', _299 => _299.estimate, 'optionalAccess', _300 => _300.durationMs]), () => ( p.maxDurationMs)), p.maxDurationMs)) result.push("execution-timeout");
|
|
1528
|
+
if ((_nullishCoalesce(_optionalChain([item, 'access', _301 => _301.estimate, 'optionalAccess', _302 => _302.complexity]), () => ( 0))) >= p.maxComplexity) result.push("complexity-threshold");
|
|
1529
|
+
if (Math.max(item.workUnits, _nullishCoalesce(_optionalChain([item, 'access', _303 => _303.estimate, 'optionalAccess', _304 => _304.workUnits]), () => ( 0))) >= p.maxWorkUnits) result.push("work-threshold");
|
|
1530
|
+
if ((_nullishCoalesce(_optionalChain([item, 'access', _305 => _305.estimate, 'optionalAccess', _306 => _306.durationMs]), () => ( 0))) >= p.maxDurationMs) result.push("duration-threshold");
|
|
1531
|
+
return result;
|
|
1532
|
+
}
|
|
1533
|
+
function eventData(command, state) {
|
|
1534
|
+
if (command.type === "request-board-stop" || command.type === "observe-board-stop") return { code: _optionalChain([state, 'access', _307 => _307.board, 'access', _308 => _308.lifecycle, 'optionalAccess', _309 => _309.code]), reason: _optionalChain([state, 'access', _310 => _310.board, 'access', _311 => _311.lifecycle, 'optionalAccess', _312 => _312.intent]), itemIds: state.board.items.filter((item) => _optionalChain([item, 'access', _313 => _313.control, 'optionalAccess', _314 => _314.action]) === "cancel").map((item) => item.id) };
|
|
1535
|
+
else if (command.type === "set-board-control") return { code: "BOARD_" + (_optionalChain([state, 'access', _315 => _315.board, 'access', _316 => _316.executionControl, 'optionalAccess', _317 => _317.paused]) ? "PAUSE_REQUESTED" : _optionalChain([state, 'access', _318 => _318.board, 'access', _319 => _319.executionControl, 'optionalAccess', _320 => _320.mode, 'optionalAccess', _321 => _321.toUpperCase, 'call', _322 => _322()])) };
|
|
1536
|
+
if (command.type === "apply-discovery") return discoveryEvent(state, command.batch);
|
|
1537
|
+
if (command.type === "report-analysis") return { code: command.status.code, reason: "analysis-" + command.status.state };
|
|
1538
|
+
if (command.type === "control-receipt") return { code: command.code, reason: "control-" + command.state };
|
|
1539
|
+
if (isWorkflowCommand(command)) return { readyItemIds: _optionalChain([state, 'access', _323 => _323.workflow, 'optionalAccess', _324 => _324.ready]), ..."dispatchId" in command ? { dispatchId: command.dispatchId } : { planId: command.plan.id }, ..."outcome" in command ? { reason: `execution-${command.outcome}`, code: command.code, status: _optionalChain([state, 'access', _325 => _325.board, 'access', _326 => _326.items, 'access', _327 => _327.find, 'call', _328 => _328((item) => item.id === _optionalChain([state, 'access', _329 => _329.workflow, 'optionalAccess', _330 => _330.dispatches, 'access', _331 => _331[command.dispatchId], 'optionalAccess', _332 => _332.itemId])), 'optionalAccess', _333 => _333.status]) } : command.type === "accept-execution" ? { reason: command.accept ? "accepted" : "rejected" } : {} };
|
|
1540
|
+
if (command.type === "create-item") return { itemTitle: command.item.title };
|
|
1541
|
+
if (command.type === "link-reference") return { reference: command.reference };
|
|
1542
|
+
if (command.type === "block-item") return { reason: command.reason };
|
|
1543
|
+
if (command.type === "release-item") return { reason: command.next === "cancelled" ? "cancelled" : "released" };
|
|
1544
|
+
if (command.type === "review") return {
|
|
1545
|
+
reason: command.accept ? "accepted" : "rejected",
|
|
1546
|
+
dispatchId: _optionalChain([Object, 'access', _334 => _334.values, 'call', _335 => _335(_nullishCoalesce(_optionalChain([state, 'access', _336 => _336.workflow, 'optionalAccess', _337 => _337.dispatches]), () => ( {}))), 'access', _338 => _338.find, 'call', _339 => _339((dispatch) => dispatch.itemId === command.itemId && dispatch.outcome === "succeeded"), 'optionalAccess', _340 => _340.id])
|
|
1547
|
+
};
|
|
1548
|
+
if (command.type === "append-record") return { recordId: command.record.id, reason: command.record.kind === "decision" ? "decision-draft" : "log" };
|
|
1549
|
+
if (command.type === "review-record" || command.type === "link-record") return { recordId: command.recordId };
|
|
1550
|
+
if (command.type === "archive-items") return { itemIds: command.itemIds, reason: command.reason };
|
|
1551
|
+
if (command.type === "cancel-item") return { reason: command.reason };
|
|
1552
|
+
if (command.type === "plan-item") return { planning: command.planning };
|
|
1553
|
+
if (command.type === "message") return { message: command.message };
|
|
1554
|
+
if (command.type === "submit") return { resultRef: command.resultRef };
|
|
1555
|
+
if (command.type === "claim" || command.type === "accept-transfer") return { estimate: command.estimate };
|
|
1556
|
+
if (command.type === "progress") return { estimate: command.estimate, workUnits: command.workUnits };
|
|
1557
|
+
return {};
|
|
1558
|
+
}
|
|
1559
|
+
function discoveryEvent(state, batch) {
|
|
1560
|
+
return {
|
|
1561
|
+
itemIds: batch.changes.map((change) => change.itemId),
|
|
1562
|
+
recordIds: _optionalChain([batch, 'access', _341 => _341.records, 'optionalAccess', _342 => _342.filter, 'call', _343 => _343((record) => _optionalChain([state, 'access', _344 => _344.records, 'optionalAccess', _345 => _345.some, 'call', _346 => _346((entry) => entry.id === record.id && entry.originRunId === batch.runId)])), 'access', _347 => _347.map, 'call', _348 => _348((record) => record.id)]),
|
|
1563
|
+
...state.board.items.some((item) => _optionalChain([item, 'access', _349 => _349.amendments, 'optionalAccess', _350 => _350.some, 'call', _351 => _351((proposal) => proposal.runId === batch.runId && proposal.status === "pending")])) ? { reason: "amendment-proposed" } : state.board.items.some((item) => item.status === "proposed" && _optionalChain([item, 'access', _352 => _352.origin, 'optionalAccess', _353 => _353.runId]) === batch.runId) ? { reason: "proposal-created" } : {}
|
|
1564
|
+
};
|
|
1565
|
+
}
|
|
1566
|
+
function deleteBoard(state, actor, operationId, now) {
|
|
1567
|
+
const owner = _chunkRBOER6EWcjs.principal.call(void 0, actor), board = state.board;
|
|
1568
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, owner.kind === "human" && _optionalChain([board, 'access', _354 => _354.members, 'optionalAccess', _355 => _355.some, 'call', _356 => _356((member) => member.kind === owner.kind && member.id === owner.id && _optionalChain([member, 'access', _357 => _357.roles, 'optionalAccess', _358 => _358.includes, 'call', _359 => _359("coordinator")]))]), "COORDINATOR_REQUIRED");
|
|
1569
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !board.items.some((item) => !terminal(item) && (item.owner || item.transfer || item.status === "claimed")), "BOARD_EXECUTION_ACTIVE");
|
|
1570
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !Object.values(_nullishCoalesce(_optionalChain([state, 'access', _360 => _360.workflow, 'optionalAccess', _361 => _361.dispatches]), () => ( {}))).some((dispatch) => ["prepared", "running", "unknown", "succeeded"].includes(dispatch.outcome)), "BOARD_EXECUTION_UNSETTLED");
|
|
1571
|
+
_chunkRBOER6EWcjs.requireValue.call(void 0, !board.items.some((item) => _optionalChain([item, 'access', _362 => _362.control, 'optionalAccess', _363 => _363.action]) === "cancel" && item.control.state !== "cancelled" && !terminal(item)), "BOARD_CONTROL_UNSETTLED");
|
|
1572
|
+
board.deletedAt = now;
|
|
1573
|
+
board.revision++;
|
|
1574
|
+
if (board.automation) board.automation.enabled = false;
|
|
1575
|
+
if (state.workflow) state.workflow.ready = [];
|
|
1576
|
+
append2(state, actor, operationId, now, "delete-board");
|
|
1577
|
+
return state;
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
|
|
1581
|
+
|
|
1582
|
+
|
|
1583
|
+
|
|
1584
|
+
|
|
1585
|
+
|
|
1586
|
+
|
|
1587
|
+
|
|
1588
|
+
|
|
1589
|
+
|
|
1590
|
+
|
|
1591
|
+
|
|
1592
|
+
|
|
1593
|
+
|
|
1594
|
+
|
|
1595
|
+
|
|
1596
|
+
|
|
1597
|
+
|
|
1598
|
+
|
|
1599
|
+
|
|
1600
|
+
|
|
1601
|
+
|
|
1602
|
+
|
|
1603
|
+
|
|
1604
|
+
|
|
1605
|
+
|
|
1606
|
+
|
|
1607
|
+
|
|
1608
|
+
|
|
1609
|
+
|
|
1610
|
+
|
|
1611
|
+
exports.summary = summary; exports.terminal = terminal; exports.catalog = catalog; exports.limits = limits; exports.proposeAmendment = proposeAmendment; exports.queryRecords = queryRecords; exports.recordSummary = recordSummary; exports.createBoardState = createBoardState; exports.boardKey = boardKey; exports.archiveKey = archiveKey; exports.rowKeys = rowKeys; exports.hydrate = hydrate; exports.encodeBoard = encodeBoard; exports.rowChanges = rowChanges; exports.receiptDigest = receiptDigest; exports.verifyReceipt = verifyReceipt; exports.encodeRow = encodeRow; exports.decodeRow = decodeRow; exports.indexedView = indexedView; exports.viewFromState = viewFromState; exports.boardCounterKey = boardCounterKey; exports.boardNumberKey = boardNumberKey; exports.counter = counter; exports.storedBoardNumber = storedBoardNumber; exports.patchBoardNumber = patchBoardNumber; exports.numberEntities = numberEntities; exports.allocateBoardNumber = allocateBoardNumber; exports.reduce = reduce; exports.related = related; exports.escalationReasons = escalationReasons;
|
|
1612
|
+
//# sourceMappingURL=chunk-EYTVC2H5.cjs.map
|