@wrongstack/tools 0.313.1 → 0.316.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_edit-match.d.ts +3 -2
- package/dist/_output-spool.d.ts +4 -3
- package/dist/_shell-pick.d.ts +2 -1
- package/dist/_spawn-stream.d.ts +2 -1
- package/dist/_syntax-check.d.ts +2 -1
- package/dist/audit.js +5 -5
- package/dist/bash-kill-guard.d.ts +3 -6
- package/dist/bash.js +3 -3
- package/dist/browser/index.js +1 -1
- package/dist/browser/network-guard-proxy.d.ts +2 -1
- package/dist/builtin.js +36 -36
- package/dist/{chunk-MAN26PZ5.js → chunk-22B7GE5T.js} +2 -2
- package/dist/{chunk-2TFQDEPU.js → chunk-2VSZC6QM.js} +1 -1
- package/dist/{chunk-IWDFZ6XR.js → chunk-42BHI7TN.js} +2 -2
- package/dist/{chunk-TVTCSBJF.js → chunk-4UESMQDP.js} +2 -2
- package/dist/{chunk-H5OHH6F4.js → chunk-5H4GSJAI.js} +3 -3
- package/dist/{chunk-J4SRJKBW.js → chunk-7EY5DCRO.js} +13 -7
- package/dist/{chunk-HC5RM4WY.js → chunk-BSLVR56S.js} +3 -3
- package/dist/{chunk-OA6YJIWL.js → chunk-DA4KNE2H.js} +4 -4
- package/dist/{chunk-FW65TP4G.js → chunk-DR7JOQTC.js} +3 -3
- package/dist/{chunk-B2CIOKWP.js → chunk-EEOFQDT6.js} +1 -2
- package/dist/{chunk-INF5CGAO.js → chunk-EJWSCQ6D.js} +3 -3
- package/dist/{chunk-3QMQBO5Z.js → chunk-FQZOHLG3.js} +1 -1
- package/dist/{chunk-2ME7ZWDD.js → chunk-HYX2TZ7O.js} +4 -4
- package/dist/{chunk-RP2ZA47V.js → chunk-I64BS3VC.js} +2 -2
- package/dist/{chunk-FGOABE4Z.js → chunk-IVWV2UM6.js} +3 -3
- package/dist/{chunk-QHVW4AAM.js → chunk-IYK7XGDZ.js} +10 -10
- package/dist/{chunk-55KF77OK.js → chunk-JNNVRHMV.js} +339 -172
- package/dist/{chunk-H5MJUAA6.js → chunk-JOHXDF3D.js} +3 -3
- package/dist/{chunk-XMIFYKUT.js → chunk-K3WNSHUF.js} +1 -1
- package/dist/{chunk-OZC255IC.js → chunk-L25CVUVR.js} +6 -6
- package/dist/{chunk-2CTB3UK5.js → chunk-LWKUTMD5.js} +2 -2
- package/dist/{chunk-YF2RSV34.js → chunk-MQX2KXVW.js} +3 -3
- package/dist/{chunk-6HLZK37X.js → chunk-MZZN7VCD.js} +2 -2
- package/dist/{chunk-KXNDHMUB.js → chunk-NKJW5GFO.js} +3 -3
- package/dist/{chunk-ZIGAZFWE.js → chunk-NKNOBUBU.js} +2 -2
- package/dist/{chunk-DIJKHSUO.js → chunk-O4MBV4AX.js} +3 -3
- package/dist/{chunk-DPL47QGS.js → chunk-OUBDL3WH.js} +2 -2
- package/dist/{chunk-NHA6BEIH.js → chunk-PQKK5JH7.js} +2 -2
- package/dist/{chunk-QNJ7AQ4B.js → chunk-PY2IOS7C.js} +1 -1
- package/dist/{chunk-2ZCJNKFE.js → chunk-QZQSPUBF.js} +2 -2
- package/dist/{chunk-UTV7YAW7.js → chunk-SDLVH5RZ.js} +3 -3
- package/dist/{chunk-HXSBQ2SE.js → chunk-T2F4S7U4.js} +3 -3
- package/dist/{chunk-ILESNGNM.js → chunk-TEBQ4VPZ.js} +1 -1
- package/dist/{chunk-42SKEETB.js → chunk-UCYQTZ7F.js} +1 -1
- package/dist/{chunk-PUR6WU2B.js → chunk-VFKPWSOX.js} +3 -3
- package/dist/{chunk-HEQFMLZ7.js → chunk-VJNHFZ7J.js} +3 -3
- package/dist/{chunk-URFKEIHM.js → chunk-VXECAJJ7.js} +23 -23
- package/dist/{chunk-MKRQMLZA.js → chunk-ZJQ4IGXK.js} +3 -3
- package/dist/{chunk-42AKKX7O.js → chunk-ZLTFLC25.js} +2 -2
- package/dist/codebase-index/ast-invariant-engine.d.ts +5 -4
- package/dist/codebase-index/binary-frame.d.ts +0 -2
- package/dist/codebase-index/bm25.d.ts +1 -1
- package/dist/codebase-index/circuit-breaker.d.ts +2 -1
- package/dist/codebase-index/codebase-ast-replace-tool.d.ts +3 -2
- package/dist/codebase-index/codebase-impact-analysis-tool.d.ts +4 -3
- package/dist/codebase-index/codebase-invariant-check-tool.d.ts +3 -2
- package/dist/codebase-index/codebase-repo-map-tool.d.ts +3 -2
- package/dist/codebase-index/codebase-skeleton-tool.d.ts +3 -2
- package/dist/codebase-index/codebase-targeted-test-tool.d.ts +3 -2
- package/dist/codebase-index/content-hash.d.ts +0 -2
- package/dist/codebase-index/import-extractor.d.ts +0 -13
- package/dist/codebase-index/index-service.d.ts +1 -1
- package/dist/codebase-index/index.js +11 -11
- package/dist/codebase-index/languages.d.ts +2 -1
- package/dist/codebase-index/module-roots.d.ts +3 -2
- package/dist/codebase-index/parser-batch.d.ts +0 -5
- package/dist/codebase-index/parser-dispatch.d.ts +2 -1
- package/dist/codebase-index/parser-output.d.ts +4 -3
- package/dist/codebase-index/parser-worker-pool.d.ts +0 -2
- package/dist/codebase-index/parser-worker-script.d.ts +1 -16
- package/dist/codebase-index/parser-worker-script.js +4 -4
- package/dist/codebase-index/project-server-client-state.d.ts +2 -2
- package/dist/codebase-index/project-server-endpoint.d.ts +0 -15
- package/dist/codebase-index/project-server.js +6 -6
- package/dist/codebase-index/tree-sitter/visitor.d.ts +2 -1
- package/dist/codebase-index/tree-sitter-parser.d.ts +0 -2
- package/dist/codebase-index/ts-parser.d.ts +1 -1
- package/dist/codebase-index/vector-search.d.ts +2 -1
- package/dist/codebase-index/wal-maintenance.d.ts +3 -2
- package/dist/codebase-index/worker.js +5 -5
- package/dist/codebase-index/writer-admin.d.ts +0 -1
- package/dist/codebase-index/writer-search.d.ts +0 -9
- package/dist/edit.js +9 -9
- package/dist/exec.js +3 -3
- package/dist/format.js +5 -5
- package/dist/{go-parser-6CA77WZ4.js → go-parser-JXYKJHRC.js} +3 -3
- package/dist/index.js +39 -39
- package/dist/install.js +5 -5
- package/dist/{json-parser-7YMDJSBJ.js → json-parser-IBHZ4BZC.js} +2 -2
- package/dist/kanban-contract-actions.d.ts +1 -1
- package/dist/kanban-detail-actions.d.ts +2 -1
- package/dist/kanban-presence.d.ts +2 -1
- package/dist/kanban-serializer.d.ts +0 -8
- package/dist/kanban-split-task-handler.d.ts +2 -2
- package/dist/kanban-tool-types.d.ts +2 -1
- package/dist/kanban.js +2 -2
- package/dist/languages/diagnostics.d.ts +2 -1
- package/dist/languages/index.js +3 -3
- package/dist/languages/legacy-bridge.d.ts +3 -2
- package/dist/languages/types.d.ts +2 -1
- package/dist/{legacy-bridge-7UKZT46G.js → legacy-bridge-7M6QLUQN.js} +5 -5
- package/dist/lint.js +5 -5
- package/dist/outdated.js +1 -1
- package/dist/pack.js +37 -37
- package/dist/parser-dispatch-QH4XPGG6.js +14 -0
- package/dist/patch.js +8 -8
- package/dist/plan.js +4 -4
- package/dist/ps-slash.js +2 -2
- package/dist/pwsh.d.ts +0 -1
- package/dist/{py-parser-GPM5VYRG.js → py-parser-IS4HKYMF.js} +4 -4
- package/dist/read.js +8 -8
- package/dist/replace.js +8 -8
- package/dist/{rs-parser-WVQ4KYCX.js → rs-parser-XHUUO2KZ.js} +2 -2
- package/dist/session-kanban-sync.d.ts +0 -6
- package/dist/session-kanban.js +1 -1
- package/dist/spawn-background.d.ts +1 -1
- package/dist/task.js +4 -4
- package/dist/test.js +5 -5
- package/dist/todo.js +3 -3
- package/dist/tool-tier.js +38 -38
- package/dist/{tree-sitter-parser-YCILHGZD.js → tree-sitter-parser-AIERW3YI.js} +2 -4
- package/dist/{ts-parser-YH4ZMWMH.js → ts-parser-RCTYKSVI.js} +2 -2
- package/dist/typecheck.js +5 -5
- package/dist/write.js +9 -9
- package/dist/{yaml-parser-GFAOKV53.js → yaml-parser-4SAXV3PL.js} +2 -2
- package/package.json +5 -5
- package/dist/parser-dispatch-VPOFDO2U.js +0 -14
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
applySessionKanbanTaskToSource,
|
|
3
3
|
taskFileToSerializedGraph
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-PY2IOS7C.js";
|
|
5
5
|
|
|
6
6
|
// src/kanban.ts
|
|
7
7
|
import { stripLifecycleIssues as stripLifecycleIssues2 } from "@wrongstack/kanban";
|
|
@@ -99,7 +99,7 @@ function okTask(board, task, message) {
|
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
// src/kanban-split-task-handler.ts
|
|
102
|
-
async function handleSplitTask(projectRoot, input, extraSplitOptions) {
|
|
102
|
+
async function handleSplitTask(projectRoot, input, extraSplitOptions, eventContext) {
|
|
103
103
|
const boardId = input.boardId;
|
|
104
104
|
const taskId = input.taskId;
|
|
105
105
|
const childTitles = input.childTitles;
|
|
@@ -116,18 +116,24 @@ async function handleSplitTask(projectRoot, input, extraSplitOptions) {
|
|
|
116
116
|
chainChildren,
|
|
117
117
|
rewireDependents
|
|
118
118
|
} = input;
|
|
119
|
-
const result = await splitTask(
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
119
|
+
const result = await splitTask(
|
|
120
|
+
projectRoot,
|
|
121
|
+
boardId,
|
|
122
|
+
taskId,
|
|
123
|
+
{
|
|
124
|
+
titles: childTitles,
|
|
125
|
+
...extraSplitOptions,
|
|
126
|
+
...targetColumnId !== void 0 ? { columnId: targetColumnId } : {},
|
|
127
|
+
...inheritAssignment !== void 0 ? { inheritAssignment } : {},
|
|
128
|
+
...inheritLabels !== void 0 ? { inheritLabels } : {},
|
|
129
|
+
...inheritSuccessCriteria !== void 0 ? { inheritSuccessCriteria } : {},
|
|
130
|
+
...inheritGoalMetrics !== void 0 ? { inheritGoalMetrics } : {},
|
|
131
|
+
...inheritDependencies !== void 0 ? { inheritDependencies } : {},
|
|
132
|
+
...chainChildren !== void 0 ? { chainChildren } : {},
|
|
133
|
+
...rewireDependents !== void 0 ? { rewireDependents } : {}
|
|
134
|
+
},
|
|
135
|
+
eventContext
|
|
136
|
+
);
|
|
131
137
|
if (!result) return fail("Task not found.");
|
|
132
138
|
const freshParent = result.board.tasks?.find((t) => t.id === taskId);
|
|
133
139
|
if (!freshParent) {
|
|
@@ -149,6 +155,10 @@ async function requireBoard(projectRoot, boardId) {
|
|
|
149
155
|
|
|
150
156
|
// src/kanban-board-actions.ts
|
|
151
157
|
async function handleKanbanBoardAction(projectRoot, input, ctx) {
|
|
158
|
+
const eventContext = {
|
|
159
|
+
sessionId: ctx.eventSessionId(),
|
|
160
|
+
...ctx.agentId !== void 0 ? { actor: ctx.agentId } : {}
|
|
161
|
+
};
|
|
152
162
|
switch (input.action) {
|
|
153
163
|
case "list_boards": {
|
|
154
164
|
const boards = await listBoards(projectRoot);
|
|
@@ -226,7 +236,7 @@ async function handleKanbanBoardAction(projectRoot, input, ctx) {
|
|
|
226
236
|
input.description,
|
|
227
237
|
board.columns[0]?.id ?? "backlog"
|
|
228
238
|
)) {
|
|
229
|
-
await addTask(projectRoot, board.id, tInput);
|
|
239
|
+
await addTask(projectRoot, board.id, tInput, eventContext);
|
|
230
240
|
}
|
|
231
241
|
return okBoard(await getBoard2(projectRoot, board.id) ?? board, "Board generated.");
|
|
232
242
|
}
|
|
@@ -406,7 +416,8 @@ import {
|
|
|
406
416
|
removeContractNode,
|
|
407
417
|
upsertContractNode
|
|
408
418
|
} from "@wrongstack/kanban";
|
|
409
|
-
async function handleKanbanContractAction(projectRoot, input, actor) {
|
|
419
|
+
async function handleKanbanContractAction(projectRoot, input, actor, sessionId) {
|
|
420
|
+
const eventContext = { sessionId, ...actor !== void 0 ? { actor } : {} };
|
|
410
421
|
switch (input.action) {
|
|
411
422
|
case "get_contract_graph": {
|
|
412
423
|
if (!input.boardId) return fail("get_contract_graph requires boardId.");
|
|
@@ -425,7 +436,12 @@ async function handleKanbanContractAction(projectRoot, input, actor) {
|
|
|
425
436
|
case "configure_contract_graph": {
|
|
426
437
|
if (!input.boardId) return fail("configure_contract_graph requires boardId.");
|
|
427
438
|
const enforcement = input.contractEnforcement ?? "advisory";
|
|
428
|
-
const board = await configureContractGraph(
|
|
439
|
+
const board = await configureContractGraph(
|
|
440
|
+
projectRoot,
|
|
441
|
+
input.boardId,
|
|
442
|
+
enforcement,
|
|
443
|
+
eventContext
|
|
444
|
+
);
|
|
429
445
|
return board ? okBoard(board, `Contract map enforcement set to ${enforcement}.`) : fail("Board not found.");
|
|
430
446
|
}
|
|
431
447
|
case "upsert_contract_node": {
|
|
@@ -443,19 +459,24 @@ async function handleKanbanContractAction(projectRoot, input, actor) {
|
|
|
443
459
|
if (waiver && !waiver.reason.trim()) {
|
|
444
460
|
return fail("A waived contract node requires contractWaiverReason.");
|
|
445
461
|
}
|
|
446
|
-
const result = await upsertContractNode(
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
462
|
+
const result = await upsertContractNode(
|
|
463
|
+
projectRoot,
|
|
464
|
+
input.boardId,
|
|
465
|
+
{
|
|
466
|
+
taskId: input.taskId,
|
|
467
|
+
kind: input.contractNodeKind,
|
|
468
|
+
title: input.contractNodeTitle,
|
|
469
|
+
...input.contractNodeId !== void 0 ? { id: input.contractNodeId } : {},
|
|
470
|
+
...input.contractNodeDescription !== void 0 ? { description: input.contractNodeDescription } : {},
|
|
471
|
+
...input.contractNodeState !== void 0 ? { state: input.contractNodeState } : {},
|
|
472
|
+
...input.contractNodeEnforcement !== void 0 ? { enforcement: input.contractNodeEnforcement } : {},
|
|
473
|
+
...input.contractCheckId !== void 0 ? { checkId: input.contractCheckId } : {},
|
|
474
|
+
...input.contractMetricId !== void 0 ? { metricId: input.contractMetricId } : {},
|
|
475
|
+
...waiver ? { waiver } : {},
|
|
476
|
+
...actor !== void 0 ? { createdBy: actor } : {}
|
|
477
|
+
},
|
|
478
|
+
eventContext
|
|
479
|
+
);
|
|
459
480
|
if (!result) return fail("Board or task not found.");
|
|
460
481
|
return {
|
|
461
482
|
ok: true,
|
|
@@ -468,7 +489,12 @@ async function handleKanbanContractAction(projectRoot, input, actor) {
|
|
|
468
489
|
if (!input.boardId || !input.contractNodeId) {
|
|
469
490
|
return fail("remove_contract_node requires boardId and contractNodeId.");
|
|
470
491
|
}
|
|
471
|
-
const board = await removeContractNode(
|
|
492
|
+
const board = await removeContractNode(
|
|
493
|
+
projectRoot,
|
|
494
|
+
input.boardId,
|
|
495
|
+
input.contractNodeId,
|
|
496
|
+
eventContext
|
|
497
|
+
);
|
|
472
498
|
return board ? okBoard(board, "Contract node removed, along with every edge that touched it.") : fail("Contract node not found.");
|
|
473
499
|
}
|
|
474
500
|
case "add_contract_edge": {
|
|
@@ -476,15 +502,20 @@ async function handleKanbanContractAction(projectRoot, input, actor) {
|
|
|
476
502
|
return fail("add_contract_edge requires boardId, contractEdgeFrom, and contractEdgeTo.");
|
|
477
503
|
}
|
|
478
504
|
if (!input.contractEdgeType) return fail("add_contract_edge requires contractEdgeType.");
|
|
479
|
-
const result = await addContractEdge(
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
505
|
+
const result = await addContractEdge(
|
|
506
|
+
projectRoot,
|
|
507
|
+
input.boardId,
|
|
508
|
+
{
|
|
509
|
+
from: input.contractEdgeFrom,
|
|
510
|
+
to: input.contractEdgeTo,
|
|
511
|
+
type: input.contractEdgeType,
|
|
512
|
+
...input.contractEdgeId !== void 0 ? { id: input.contractEdgeId } : {},
|
|
513
|
+
...input.contractNodeEnforcement !== void 0 ? { enforcement: input.contractNodeEnforcement } : {},
|
|
514
|
+
...input.contractEdgeRationale !== void 0 ? { rationale: input.contractEdgeRationale } : {},
|
|
515
|
+
...actor !== void 0 ? { createdBy: actor } : {}
|
|
516
|
+
},
|
|
517
|
+
eventContext
|
|
518
|
+
);
|
|
488
519
|
if (!result) return fail("Board not found.");
|
|
489
520
|
return {
|
|
490
521
|
ok: true,
|
|
@@ -497,7 +528,12 @@ async function handleKanbanContractAction(projectRoot, input, actor) {
|
|
|
497
528
|
if (!input.boardId || !input.contractEdgeId) {
|
|
498
529
|
return fail("remove_contract_edge requires boardId and contractEdgeId.");
|
|
499
530
|
}
|
|
500
|
-
const board = await removeContractEdge(
|
|
531
|
+
const board = await removeContractEdge(
|
|
532
|
+
projectRoot,
|
|
533
|
+
input.boardId,
|
|
534
|
+
input.contractEdgeId,
|
|
535
|
+
eventContext
|
|
536
|
+
);
|
|
501
537
|
return board ? okBoard(board, "Contract edge removed.") : fail("Contract edge not found.");
|
|
502
538
|
}
|
|
503
539
|
default:
|
|
@@ -538,6 +574,10 @@ function recordKanbanVerificationEvidence(ctx, report) {
|
|
|
538
574
|
|
|
539
575
|
// src/kanban-decomposition-actions.ts
|
|
540
576
|
async function handleKanbanDecompositionAction(projectRoot, input, ctx) {
|
|
577
|
+
const eventContext = {
|
|
578
|
+
sessionId: ctx.eventSessionId(),
|
|
579
|
+
...ctx.agentId !== void 0 ? { actor: ctx.agentId } : {}
|
|
580
|
+
};
|
|
541
581
|
switch (input.action) {
|
|
542
582
|
case "assess_atomicity": {
|
|
543
583
|
if (!input.boardId || !input.taskId) {
|
|
@@ -545,7 +585,7 @@ async function handleKanbanDecompositionAction(projectRoot, input, ctx) {
|
|
|
545
585
|
}
|
|
546
586
|
const result = await assessTaskAtomicity(projectRoot, input.boardId, input.taskId, {
|
|
547
587
|
assessedBy: "agent",
|
|
548
|
-
|
|
588
|
+
eventContext
|
|
549
589
|
});
|
|
550
590
|
if (!result) return fail("Task not found.");
|
|
551
591
|
const failing = result.assessment.criteria.filter((entry) => entry.score < 1).map((entry) => entry.reason);
|
|
@@ -576,7 +616,7 @@ async function handleKanbanDecompositionAction(projectRoot, input, ctx) {
|
|
|
576
616
|
...input.note !== void 0 ? { rationale: input.note } : {},
|
|
577
617
|
...ctx.agentId !== void 0 ? { proposedBy: ctx.agentId } : {}
|
|
578
618
|
},
|
|
579
|
-
|
|
619
|
+
eventContext
|
|
580
620
|
);
|
|
581
621
|
if (!result) return fail("Task not found.");
|
|
582
622
|
const message = result.proposal.status === "applied" ? `Decomposition applied: ${result.proposal.appliedChildTaskIds?.length ?? 0} child tasks created (parent marked atomic).` : 'Decomposition proposal recorded \u2014 awaiting approval (board policy is "propose"). It can be approved from the WebUI or via update_task.';
|
|
@@ -587,10 +627,16 @@ async function handleKanbanDecompositionAction(projectRoot, input, ctx) {
|
|
|
587
627
|
return fail("verify_completion requires boardId and taskId.");
|
|
588
628
|
}
|
|
589
629
|
const verResult = await verifyTaskCompletion(projectRoot, input.boardId, input.taskId);
|
|
590
|
-
const persistedBoard = await updateTask(
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
630
|
+
const persistedBoard = await updateTask(
|
|
631
|
+
projectRoot,
|
|
632
|
+
input.boardId,
|
|
633
|
+
input.taskId,
|
|
634
|
+
{
|
|
635
|
+
verificationReport: verResult.report,
|
|
636
|
+
successCriteria: verResult.task.successCriteria
|
|
637
|
+
},
|
|
638
|
+
eventContext
|
|
639
|
+
);
|
|
594
640
|
if (!persistedBoard) {
|
|
595
641
|
return {
|
|
596
642
|
ok: false,
|
|
@@ -629,7 +675,11 @@ import {
|
|
|
629
675
|
updateCheckOnTask,
|
|
630
676
|
updateGoalMetricOnTask
|
|
631
677
|
} from "@wrongstack/kanban";
|
|
632
|
-
async function handleKanbanDetailAction(projectRoot, input) {
|
|
678
|
+
async function handleKanbanDetailAction(projectRoot, input, ctx) {
|
|
679
|
+
const eventContext = {
|
|
680
|
+
sessionId: ctx.eventSessionId(),
|
|
681
|
+
...ctx.agentId !== void 0 ? { actor: ctx.agentId } : {}
|
|
682
|
+
};
|
|
633
683
|
switch (input.action) {
|
|
634
684
|
case "workbench": {
|
|
635
685
|
const workbench = await getKanbanWorkbench(projectRoot, {
|
|
@@ -649,7 +699,8 @@ async function handleKanbanDetailAction(projectRoot, input) {
|
|
|
649
699
|
projectRoot,
|
|
650
700
|
input.boardId,
|
|
651
701
|
input.taskId,
|
|
652
|
-
input.dependencyTaskId
|
|
702
|
+
input.dependencyTaskId,
|
|
703
|
+
eventContext
|
|
653
704
|
);
|
|
654
705
|
return board ? okBoard(board, "Dependency added.") : fail("Task not found.");
|
|
655
706
|
}
|
|
@@ -657,15 +708,21 @@ async function handleKanbanDetailAction(projectRoot, input) {
|
|
|
657
708
|
if (!input.boardId || !input.taskId || !input.metricName) {
|
|
658
709
|
return fail("add_goal_metric requires boardId, taskId, and metricName.");
|
|
659
710
|
}
|
|
660
|
-
const board = await addGoalMetricToTask(
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
711
|
+
const board = await addGoalMetricToTask(
|
|
712
|
+
projectRoot,
|
|
713
|
+
input.boardId,
|
|
714
|
+
input.taskId,
|
|
715
|
+
{
|
|
716
|
+
name: input.metricName,
|
|
717
|
+
...input.metricStatus !== void 0 ? { status: input.metricStatus } : {},
|
|
718
|
+
...input.metricTarget !== void 0 ? { target: input.metricTarget } : {},
|
|
719
|
+
...input.metricCurrent !== void 0 ? { current: input.metricCurrent } : {},
|
|
720
|
+
...input.metricDirection !== void 0 ? { direction: input.metricDirection } : {},
|
|
721
|
+
...input.metricUnit !== void 0 ? { unit: input.metricUnit } : {},
|
|
722
|
+
...input.metricNotes !== void 0 ? { notes: input.metricNotes } : {}
|
|
723
|
+
},
|
|
724
|
+
eventContext
|
|
725
|
+
);
|
|
669
726
|
return board ? okBoard(board, "Goal metric added.") : fail("Task not found.");
|
|
670
727
|
}
|
|
671
728
|
case "update_goal_metric": {
|
|
@@ -685,7 +742,8 @@ async function handleKanbanDetailAction(projectRoot, input) {
|
|
|
685
742
|
...input.metricDirection !== void 0 ? { direction: input.metricDirection } : {},
|
|
686
743
|
...input.metricUnit !== void 0 ? { unit: input.metricUnit } : {},
|
|
687
744
|
...input.metricNotes !== void 0 ? { notes: input.metricNotes } : {}
|
|
688
|
-
}
|
|
745
|
+
},
|
|
746
|
+
eventContext
|
|
689
747
|
);
|
|
690
748
|
return board ? okBoard(board, "Goal metric updated.") : fail("Metric not found.");
|
|
691
749
|
}
|
|
@@ -693,12 +751,18 @@ async function handleKanbanDetailAction(projectRoot, input) {
|
|
|
693
751
|
if (!input.boardId || !input.taskId || !input.checkDescription) {
|
|
694
752
|
return fail("add_check requires boardId, taskId, and checkDescription.");
|
|
695
753
|
}
|
|
696
|
-
const board = await addCheckToTask(
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
754
|
+
const board = await addCheckToTask(
|
|
755
|
+
projectRoot,
|
|
756
|
+
input.boardId,
|
|
757
|
+
input.taskId,
|
|
758
|
+
{
|
|
759
|
+
description: input.checkDescription,
|
|
760
|
+
type: input.checkType ?? "manual",
|
|
761
|
+
status: input.checkStatus,
|
|
762
|
+
...input.checkNotes !== void 0 ? { notes: input.checkNotes } : {}
|
|
763
|
+
},
|
|
764
|
+
eventContext
|
|
765
|
+
);
|
|
702
766
|
return board ? okBoard(board, "Check added.") : fail("Task not found.");
|
|
703
767
|
}
|
|
704
768
|
case "update_check": {
|
|
@@ -717,7 +781,8 @@ async function handleKanbanDetailAction(projectRoot, input) {
|
|
|
717
781
|
// common repair: the card was written before anyone knew the command.
|
|
718
782
|
...input.checkType !== void 0 ? { type: input.checkType } : {},
|
|
719
783
|
...input.checkNotes !== void 0 ? { notes: input.checkNotes } : {}
|
|
720
|
-
}
|
|
784
|
+
},
|
|
785
|
+
eventContext
|
|
721
786
|
);
|
|
722
787
|
return board ? okBoard(board, "Check updated.") : fail("Check not found.");
|
|
723
788
|
}
|
|
@@ -729,34 +794,47 @@ async function handleKanbanDetailAction(projectRoot, input) {
|
|
|
729
794
|
projectRoot,
|
|
730
795
|
input.boardId,
|
|
731
796
|
input.taskId,
|
|
732
|
-
input.checkId
|
|
797
|
+
input.checkId,
|
|
798
|
+
eventContext
|
|
733
799
|
);
|
|
734
800
|
return board ? okBoard(board, "Acceptance criterion removed.") : fail("Check not found on this task.");
|
|
735
801
|
}
|
|
736
802
|
case "add_note": {
|
|
737
803
|
if (!input.boardId || !input.taskId || !input.note)
|
|
738
804
|
return fail("add_note requires boardId, taskId, and note.");
|
|
739
|
-
const board = await addNoteToTask(
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
805
|
+
const board = await addNoteToTask(
|
|
806
|
+
projectRoot,
|
|
807
|
+
input.boardId,
|
|
808
|
+
input.taskId,
|
|
809
|
+
{
|
|
810
|
+
author: input.author ?? "agent",
|
|
811
|
+
content: input.note
|
|
812
|
+
},
|
|
813
|
+
eventContext
|
|
814
|
+
);
|
|
743
815
|
return board ? okBoard(board, "Note added.") : fail("Task not found.");
|
|
744
816
|
}
|
|
745
817
|
case "add_link": {
|
|
746
818
|
if (!input.boardId || !input.taskId || !input.url)
|
|
747
819
|
return fail("add_link requires boardId, taskId, and url.");
|
|
748
|
-
const board = await addLinkToTask(
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
820
|
+
const board = await addLinkToTask(
|
|
821
|
+
projectRoot,
|
|
822
|
+
input.boardId,
|
|
823
|
+
input.taskId,
|
|
824
|
+
{
|
|
825
|
+
url: input.url,
|
|
826
|
+
type: input.linkType ?? "url",
|
|
827
|
+
...input.linkTitle !== void 0 ? { title: input.linkTitle } : {}
|
|
828
|
+
},
|
|
829
|
+
eventContext
|
|
830
|
+
);
|
|
753
831
|
return board ? okBoard(board, "Link added.") : fail("Task not found.");
|
|
754
832
|
}
|
|
755
833
|
case "split_atomic": {
|
|
756
834
|
if (!input.boardId || !input.taskId || !input.childTitles?.length) {
|
|
757
835
|
return fail("split_atomic requires boardId, taskId, and childTitles (at least one).");
|
|
758
836
|
}
|
|
759
|
-
return handleSplitTask(projectRoot, input, { atomic: true });
|
|
837
|
+
return handleSplitTask(projectRoot, input, { atomic: true }, eventContext);
|
|
760
838
|
}
|
|
761
839
|
default:
|
|
762
840
|
return void 0;
|
|
@@ -976,10 +1054,14 @@ async function syncContextTask(ctx, task, options = {}) {
|
|
|
976
1054
|
}
|
|
977
1055
|
}
|
|
978
1056
|
async function handleKanbanLifecycleAction(projectRoot, input, ctx) {
|
|
1057
|
+
const eventContext = {
|
|
1058
|
+
sessionId: ctx.eventSessionId(),
|
|
1059
|
+
...ctx.agentId !== void 0 ? { actor: ctx.agentId } : {}
|
|
1060
|
+
};
|
|
979
1061
|
switch (input.action) {
|
|
980
1062
|
case "add_task": {
|
|
981
1063
|
if (!input.boardId || !input.title) return fail("add_task requires boardId and title.");
|
|
982
|
-
const result = await addTask2(projectRoot, input.boardId, taskInput(input));
|
|
1064
|
+
const result = await addTask2(projectRoot, input.boardId, taskInput(input), eventContext);
|
|
983
1065
|
if (!result) return fail("Board not found.");
|
|
984
1066
|
await syncContextTask(ctx, result.task);
|
|
985
1067
|
return okTask(result.board, result.task, `Task added.${atomicityNudge(result.task)}`);
|
|
@@ -988,20 +1070,25 @@ async function handleKanbanLifecycleAction(projectRoot, input, ctx) {
|
|
|
988
1070
|
if (!input.boardId || !input.taskId || !input.childTitles?.length) {
|
|
989
1071
|
return fail("split_task requires boardId, taskId, and childTitles.");
|
|
990
1072
|
}
|
|
991
|
-
return handleSplitTask(projectRoot, input, {});
|
|
1073
|
+
return handleSplitTask(projectRoot, input, {}, eventContext);
|
|
992
1074
|
}
|
|
993
1075
|
case "merge_tasks": {
|
|
994
1076
|
if (!input.boardId || !input.taskIds?.length || !input.title) {
|
|
995
1077
|
return fail("merge_tasks requires boardId, taskIds, and title.");
|
|
996
1078
|
}
|
|
997
|
-
const result = await mergeTasks(
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1079
|
+
const result = await mergeTasks(
|
|
1080
|
+
projectRoot,
|
|
1081
|
+
input.boardId,
|
|
1082
|
+
{
|
|
1083
|
+
taskIds: input.taskIds,
|
|
1084
|
+
title: input.title,
|
|
1085
|
+
...input.description !== void 0 ? { description: input.description } : {},
|
|
1086
|
+
...input.targetColumnId !== void 0 ? { targetColumnId: input.targetColumnId } : {},
|
|
1087
|
+
...input.preserveAssignment !== void 0 ? { preserveAssignment: input.preserveAssignment } : {},
|
|
1088
|
+
...input.closeSourceTasks !== void 0 ? { closeSourceTasks: input.closeSourceTasks } : {}
|
|
1089
|
+
},
|
|
1090
|
+
eventContext
|
|
1091
|
+
);
|
|
1005
1092
|
return result ? okTask(result.board, result.task, "Tasks merged.") : fail("Board or task not found.");
|
|
1006
1093
|
}
|
|
1007
1094
|
case "copy_task": {
|
|
@@ -1017,7 +1104,8 @@ async function handleKanbanLifecycleAction(projectRoot, input, ctx) {
|
|
|
1017
1104
|
...input.targetColumnId !== void 0 ? { targetColumnId: input.targetColumnId } : {},
|
|
1018
1105
|
...input.order !== void 0 ? { targetOrder: input.order } : {},
|
|
1019
1106
|
...input.preserveAssignment !== void 0 ? { preserveAssignment: input.preserveAssignment } : {},
|
|
1020
|
-
...input.preserveDependencies !== void 0 ? { preserveDependencies: input.preserveDependencies } : {}
|
|
1107
|
+
...input.preserveDependencies !== void 0 ? { preserveDependencies: input.preserveDependencies } : {},
|
|
1108
|
+
eventContext
|
|
1021
1109
|
}
|
|
1022
1110
|
);
|
|
1023
1111
|
return result ? okTask(result.targetBoard, result.task, "Task copied to target board.") : fail("Board or task not found.");
|
|
@@ -1035,7 +1123,8 @@ async function handleKanbanLifecycleAction(projectRoot, input, ctx) {
|
|
|
1035
1123
|
...input.targetColumnId !== void 0 ? { targetColumnId: input.targetColumnId } : {},
|
|
1036
1124
|
...input.order !== void 0 ? { targetOrder: input.order } : {},
|
|
1037
1125
|
...input.preserveAssignment !== void 0 ? { preserveAssignment: input.preserveAssignment } : {},
|
|
1038
|
-
...input.preserveDependencies !== void 0 ? { preserveDependencies: input.preserveDependencies } : {}
|
|
1126
|
+
...input.preserveDependencies !== void 0 ? { preserveDependencies: input.preserveDependencies } : {},
|
|
1127
|
+
eventContext
|
|
1039
1128
|
}
|
|
1040
1129
|
);
|
|
1041
1130
|
return result ? okTask(result.targetBoard, result.task, "Task transferred to target board.") : fail("Board or task not found.");
|
|
@@ -1060,20 +1149,30 @@ async function handleKanbanLifecycleAction(projectRoot, input, ctx) {
|
|
|
1060
1149
|
}
|
|
1061
1150
|
if (board.lifecycle?.mode !== "managed") {
|
|
1062
1151
|
const now = /* @__PURE__ */ new Date();
|
|
1063
|
-
const assigned = await updateTaskAssignment(
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1152
|
+
const assigned = await updateTaskAssignment(
|
|
1153
|
+
projectRoot,
|
|
1154
|
+
board.id,
|
|
1155
|
+
task.id,
|
|
1156
|
+
{
|
|
1157
|
+
status: "running",
|
|
1158
|
+
agentId: input.agentId ?? input.author,
|
|
1159
|
+
leaseId: input.leaseId ?? randomUUID2(),
|
|
1160
|
+
claimedAt: input.claimedAt ?? now.toISOString(),
|
|
1161
|
+
heartbeatAt: input.heartbeatAt ?? now.toISOString(),
|
|
1162
|
+
leaseExpiresAt: input.leaseExpiresAt ?? new Date(now.getTime() + 15 * 6e4).toISOString(),
|
|
1163
|
+
attempt: input.attempt ?? 1,
|
|
1164
|
+
maxAttempts: input.maxAttempts ?? 3
|
|
1165
|
+
},
|
|
1166
|
+
eventContext
|
|
1167
|
+
);
|
|
1073
1168
|
if (!assigned) return fail("Task assignment could not be started.");
|
|
1074
|
-
const started = await updateTask2(
|
|
1075
|
-
|
|
1076
|
-
|
|
1169
|
+
const started = await updateTask2(
|
|
1170
|
+
projectRoot,
|
|
1171
|
+
board.id,
|
|
1172
|
+
task.id,
|
|
1173
|
+
{ status: "in_progress" },
|
|
1174
|
+
eventContext
|
|
1175
|
+
);
|
|
1077
1176
|
const current = started ?? assigned;
|
|
1078
1177
|
const claimed = task;
|
|
1079
1178
|
const currentTask = current.tasks.find((candidate) => candidate.id === claimed.id) ?? claimed;
|
|
@@ -1088,6 +1187,7 @@ async function handleKanbanLifecycleAction(projectRoot, input, ctx) {
|
|
|
1088
1187
|
if (stage === "backlog") {
|
|
1089
1188
|
const moved = await transitionTask(projectRoot, board.id, task.id, {
|
|
1090
1189
|
to: "todo",
|
|
1190
|
+
sessionId: eventContext.sessionId,
|
|
1091
1191
|
actor: input.author,
|
|
1092
1192
|
comment: input.transitionComment
|
|
1093
1193
|
});
|
|
@@ -1099,19 +1199,26 @@ async function handleKanbanLifecycleAction(projectRoot, input, ctx) {
|
|
|
1099
1199
|
if (stage === "todo" || stage === "review") {
|
|
1100
1200
|
const now = /* @__PURE__ */ new Date();
|
|
1101
1201
|
const leaseId = input.leaseId ?? randomUUID2();
|
|
1102
|
-
const assigned = await updateTaskAssignment(
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1202
|
+
const assigned = await updateTaskAssignment(
|
|
1203
|
+
projectRoot,
|
|
1204
|
+
board.id,
|
|
1205
|
+
task.id,
|
|
1206
|
+
{
|
|
1207
|
+
status: "running",
|
|
1208
|
+
agentId: input.agentId ?? input.author,
|
|
1209
|
+
leaseId,
|
|
1210
|
+
claimedAt: input.claimedAt ?? now.toISOString(),
|
|
1211
|
+
heartbeatAt: input.heartbeatAt ?? now.toISOString(),
|
|
1212
|
+
leaseExpiresAt: input.leaseExpiresAt ?? new Date(now.getTime() + 15 * 6e4).toISOString(),
|
|
1213
|
+
attempt: input.attempt ?? 1,
|
|
1214
|
+
maxAttempts: input.maxAttempts ?? 3
|
|
1215
|
+
},
|
|
1216
|
+
eventContext
|
|
1217
|
+
);
|
|
1112
1218
|
if (!assigned) return fail("Task assignment could not be started.");
|
|
1113
1219
|
const moved = await transitionTask(projectRoot, board.id, task.id, {
|
|
1114
1220
|
to: "running",
|
|
1221
|
+
sessionId: eventContext.sessionId,
|
|
1115
1222
|
actor: input.author,
|
|
1116
1223
|
comment: input.transitionComment
|
|
1117
1224
|
});
|
|
@@ -1135,9 +1242,18 @@ async function handleKanbanLifecycleAction(projectRoot, input, ctx) {
|
|
|
1135
1242
|
}
|
|
1136
1243
|
case "update_task": {
|
|
1137
1244
|
if (!input.boardId || !input.taskId) return fail("update_task requires boardId and taskId.");
|
|
1138
|
-
const board = await updateTask2(
|
|
1245
|
+
const board = await updateTask2(
|
|
1246
|
+
projectRoot,
|
|
1247
|
+
input.boardId,
|
|
1248
|
+
input.taskId,
|
|
1249
|
+
taskPatch(input),
|
|
1250
|
+
eventContext
|
|
1251
|
+
);
|
|
1139
1252
|
if (board) {
|
|
1140
|
-
await syncContextTask(
|
|
1253
|
+
await syncContextTask(
|
|
1254
|
+
ctx,
|
|
1255
|
+
board.tasks.find((t) => t.id === input.taskId)
|
|
1256
|
+
);
|
|
1141
1257
|
}
|
|
1142
1258
|
return board ? okBoard(board, "Task updated.") : fail("Task not found.");
|
|
1143
1259
|
}
|
|
@@ -1154,14 +1270,21 @@ async function handleKanbanLifecycleAction(projectRoot, input, ctx) {
|
|
|
1154
1270
|
const preGate = await verifyTaskCompletion2(projectRoot, input.boardId, taskBefore.id, {
|
|
1155
1271
|
persist: false
|
|
1156
1272
|
});
|
|
1157
|
-
await updateTask2(
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1273
|
+
await updateTask2(
|
|
1274
|
+
projectRoot,
|
|
1275
|
+
input.boardId,
|
|
1276
|
+
taskBefore.id,
|
|
1277
|
+
{
|
|
1278
|
+
verificationReport: preGate.report,
|
|
1279
|
+
successCriteria: preGate.task.successCriteria
|
|
1280
|
+
},
|
|
1281
|
+
eventContext
|
|
1282
|
+
);
|
|
1161
1283
|
}
|
|
1162
1284
|
}
|
|
1163
1285
|
const result = await transitionTask(projectRoot, input.boardId, input.taskId, {
|
|
1164
1286
|
to: input.lifecycleStage,
|
|
1287
|
+
sessionId: eventContext.sessionId,
|
|
1165
1288
|
actor: input.author,
|
|
1166
1289
|
comment: input.transitionComment,
|
|
1167
1290
|
...input.transitionAction !== void 0 ? { action: input.transitionAction } : {},
|
|
@@ -1211,10 +1334,14 @@ async function handleKanbanLifecycleAction(projectRoot, input, ctx) {
|
|
|
1211
1334
|
input.boardId,
|
|
1212
1335
|
input.taskId,
|
|
1213
1336
|
input.targetColumnId,
|
|
1214
|
-
input.order
|
|
1337
|
+
input.order,
|
|
1338
|
+
eventContext
|
|
1215
1339
|
);
|
|
1216
1340
|
if (board) {
|
|
1217
|
-
await syncContextTask(
|
|
1341
|
+
await syncContextTask(
|
|
1342
|
+
ctx,
|
|
1343
|
+
board.tasks.find((t) => t.id === input.taskId)
|
|
1344
|
+
);
|
|
1218
1345
|
}
|
|
1219
1346
|
return board ? okBoard(board, "Task moved.") : fail("Move failed.");
|
|
1220
1347
|
}
|
|
@@ -1222,7 +1349,7 @@ async function handleKanbanLifecycleAction(projectRoot, input, ctx) {
|
|
|
1222
1349
|
if (!input.boardId || !input.taskId) return fail("delete_task requires boardId and taskId.");
|
|
1223
1350
|
const boardBefore = await getBoard3(projectRoot, input.boardId);
|
|
1224
1351
|
const taskToDelete = boardBefore?.tasks.find((t) => t.id === input.taskId);
|
|
1225
|
-
const board = await removeTask(projectRoot, input.boardId, input.taskId);
|
|
1352
|
+
const board = await removeTask(projectRoot, input.boardId, input.taskId, eventContext);
|
|
1226
1353
|
if (board && ctx.currentKanbanTaskId === input.taskId) {
|
|
1227
1354
|
ctx.setCurrentKanbanTask?.(void 0, ctx.currentKanbanBoardId);
|
|
1228
1355
|
}
|
|
@@ -1235,11 +1362,16 @@ async function handleKanbanLifecycleAction(projectRoot, input, ctx) {
|
|
|
1235
1362
|
if (!input.boardId || !input.taskIds?.length) {
|
|
1236
1363
|
return fail("set_chain requires boardId and taskIds.");
|
|
1237
1364
|
}
|
|
1238
|
-
const result = await setTaskChain(
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1365
|
+
const result = await setTaskChain(
|
|
1366
|
+
projectRoot,
|
|
1367
|
+
input.boardId,
|
|
1368
|
+
{
|
|
1369
|
+
taskIds: input.taskIds,
|
|
1370
|
+
...input.chainId !== void 0 ? { chainId: input.chainId } : {},
|
|
1371
|
+
...input.enforceDependencies !== void 0 ? { enforceDependencies: input.enforceDependencies } : {}
|
|
1372
|
+
},
|
|
1373
|
+
eventContext
|
|
1374
|
+
);
|
|
1243
1375
|
return result ? {
|
|
1244
1376
|
ok: true,
|
|
1245
1377
|
message: `Chain set: ${result.chainId}`,
|
|
@@ -1264,23 +1396,33 @@ async function handleKanbanLifecycleAction(projectRoot, input, ctx) {
|
|
|
1264
1396
|
} : fail("Chain not found.");
|
|
1265
1397
|
}
|
|
1266
1398
|
case "claim_task": {
|
|
1267
|
-
const result = await claimReadyTask(
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1399
|
+
const result = await claimReadyTask(
|
|
1400
|
+
projectRoot,
|
|
1401
|
+
{
|
|
1402
|
+
...input.boardId !== void 0 ? { boardId: input.boardId } : {},
|
|
1403
|
+
...input.taskId !== void 0 ? { taskId: input.taskId } : {},
|
|
1404
|
+
...assignmentInput(input),
|
|
1405
|
+
status: input.assignmentStatus ?? "queued"
|
|
1406
|
+
},
|
|
1407
|
+
eventContext
|
|
1408
|
+
);
|
|
1273
1409
|
return result ? okTask(result.board, result.task, "Task claimed.") : fail("No ready kanban task matched the claim.");
|
|
1274
1410
|
}
|
|
1275
1411
|
case "release_task": {
|
|
1276
1412
|
if (!input.boardId || !input.taskId) {
|
|
1277
1413
|
return fail("release_task requires boardId and taskId.");
|
|
1278
1414
|
}
|
|
1279
|
-
const board = await releaseTaskClaim(
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1415
|
+
const board = await releaseTaskClaim(
|
|
1416
|
+
projectRoot,
|
|
1417
|
+
input.boardId,
|
|
1418
|
+
input.taskId,
|
|
1419
|
+
{
|
|
1420
|
+
...input.releaseStatus !== void 0 ? { status: input.releaseStatus } : {},
|
|
1421
|
+
...input.releaseReason !== void 0 ? { reason: input.releaseReason } : {},
|
|
1422
|
+
...input.clearAssignee !== void 0 ? { clearAssignee: input.clearAssignee } : {}
|
|
1423
|
+
},
|
|
1424
|
+
eventContext
|
|
1425
|
+
);
|
|
1284
1426
|
return board ? okBoard(board, "Task claim released.") : fail("Task not found.");
|
|
1285
1427
|
}
|
|
1286
1428
|
case "assign_task": {
|
|
@@ -1289,7 +1431,8 @@ async function handleKanbanLifecycleAction(projectRoot, input, ctx) {
|
|
|
1289
1431
|
projectRoot,
|
|
1290
1432
|
input.boardId,
|
|
1291
1433
|
input.taskId,
|
|
1292
|
-
assignmentInput(input)
|
|
1434
|
+
assignmentInput(input),
|
|
1435
|
+
eventContext
|
|
1293
1436
|
);
|
|
1294
1437
|
return board ? okBoard(board, "Task assigned.") : fail("Task not found.");
|
|
1295
1438
|
}
|
|
@@ -1315,14 +1458,17 @@ async function handleKanbanLifecycleAction(projectRoot, input, ctx) {
|
|
|
1315
1458
|
...input.attempt !== void 0 ? { attempt: input.attempt } : {},
|
|
1316
1459
|
...input.maxAttempts !== void 0 ? { maxAttempts: input.maxAttempts } : {}
|
|
1317
1460
|
},
|
|
1318
|
-
|
|
1461
|
+
{
|
|
1462
|
+
...eventContext,
|
|
1463
|
+
...input.expectedLeaseId !== void 0 ? { expectedLeaseId: input.expectedLeaseId } : {}
|
|
1464
|
+
}
|
|
1319
1465
|
);
|
|
1320
1466
|
if (!board) return fail("Task not found.");
|
|
1321
1467
|
if (assignmentStatus === "completed" && board.lifecycle?.mode !== "managed") {
|
|
1322
1468
|
const envGate = readEnvGateEnforcement();
|
|
1323
1469
|
const finalized = await finalizeTaskCompletion(projectRoot, board.id, input.taskId, {
|
|
1324
1470
|
...board.completionGate === void 0 && envGate !== void 0 ? { enforcement: envGate } : {},
|
|
1325
|
-
|
|
1471
|
+
eventContext
|
|
1326
1472
|
});
|
|
1327
1473
|
if (finalized) {
|
|
1328
1474
|
if (finalized.gate.report) {
|
|
@@ -1351,6 +1497,7 @@ async function handleKanbanLifecycleAction(projectRoot, input, ctx) {
|
|
|
1351
1497
|
try {
|
|
1352
1498
|
transitionResult = await transitionTask(projectRoot, board.id, input.taskId, {
|
|
1353
1499
|
to: "running",
|
|
1500
|
+
sessionId: eventContext.sessionId,
|
|
1354
1501
|
actor,
|
|
1355
1502
|
comment: "Work started."
|
|
1356
1503
|
});
|
|
@@ -1365,6 +1512,7 @@ async function handleKanbanLifecycleAction(projectRoot, input, ctx) {
|
|
|
1365
1512
|
try {
|
|
1366
1513
|
transitionResult = await transitionTask(projectRoot, board.id, input.taskId, {
|
|
1367
1514
|
to: "review",
|
|
1515
|
+
sessionId: eventContext.sessionId,
|
|
1368
1516
|
actor,
|
|
1369
1517
|
comment,
|
|
1370
1518
|
attachment: {
|
|
@@ -1389,10 +1537,16 @@ async function handleKanbanLifecycleAction(projectRoot, input, ctx) {
|
|
|
1389
1537
|
if (verResult.report) {
|
|
1390
1538
|
recordKanbanVerificationEvidence(ctx, verResult.report);
|
|
1391
1539
|
}
|
|
1392
|
-
await updateTask2(
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1540
|
+
await updateTask2(
|
|
1541
|
+
projectRoot,
|
|
1542
|
+
board.id,
|
|
1543
|
+
input.taskId,
|
|
1544
|
+
{
|
|
1545
|
+
verificationReport: verResult.report,
|
|
1546
|
+
successCriteria: verResult.task.successCriteria
|
|
1547
|
+
},
|
|
1548
|
+
eventContext
|
|
1549
|
+
);
|
|
1396
1550
|
const verdict = verResult.report.verdict;
|
|
1397
1551
|
if (verdict === "passed" && !resolveAutoAccept(board)) {
|
|
1398
1552
|
lifecycleWarnings.push(
|
|
@@ -1402,6 +1556,7 @@ async function handleKanbanLifecycleAction(projectRoot, input, ctx) {
|
|
|
1402
1556
|
try {
|
|
1403
1557
|
const doneResult = await transitionTask(projectRoot, board.id, input.taskId, {
|
|
1404
1558
|
to: "done",
|
|
1559
|
+
sessionId: eventContext.sessionId,
|
|
1405
1560
|
actor,
|
|
1406
1561
|
action: "Automated acceptance after verification",
|
|
1407
1562
|
comment: "Auto-accepted: verification passed.",
|
|
@@ -1450,11 +1605,17 @@ async function handleKanbanLifecycleAction(projectRoot, input, ctx) {
|
|
|
1450
1605
|
if (!input.boardId || !input.taskId) {
|
|
1451
1606
|
return fail("heartbeat_assignment requires boardId and taskId.");
|
|
1452
1607
|
}
|
|
1453
|
-
const board = await heartbeatTaskAssignment(
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1608
|
+
const board = await heartbeatTaskAssignment(
|
|
1609
|
+
projectRoot,
|
|
1610
|
+
input.boardId,
|
|
1611
|
+
input.taskId,
|
|
1612
|
+
{
|
|
1613
|
+
...input.heartbeatAt !== void 0 ? { heartbeatAt: input.heartbeatAt } : {},
|
|
1614
|
+
...input.leaseExpiresAt !== void 0 ? { leaseExpiresAt: input.leaseExpiresAt } : {},
|
|
1615
|
+
...input.expectedLeaseId !== void 0 ? { expectedLeaseId: input.expectedLeaseId } : {}
|
|
1616
|
+
},
|
|
1617
|
+
eventContext
|
|
1618
|
+
);
|
|
1458
1619
|
return board ? okBoard(board, "Assignment heartbeat updated.") : fail("Task assignment not found.");
|
|
1459
1620
|
}
|
|
1460
1621
|
case "recover_stale": {
|
|
@@ -1465,26 +1626,31 @@ async function handleKanbanLifecycleAction(projectRoot, input, ctx) {
|
|
|
1465
1626
|
input.recoveryPolicyReleaseOnHeartbeatDue !== void 0,
|
|
1466
1627
|
input.recoveryPolicyRetryPolicyOverride !== void 0
|
|
1467
1628
|
].some(Boolean);
|
|
1468
|
-
const result = await recoverStaleTaskAssignments(
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1629
|
+
const result = await recoverStaleTaskAssignments(
|
|
1630
|
+
projectRoot,
|
|
1631
|
+
input.boardId,
|
|
1632
|
+
{
|
|
1633
|
+
...input.recoveryMode !== void 0 ? { mode: input.recoveryMode } : {},
|
|
1634
|
+
...input.recoveryNow !== void 0 ? { now: input.recoveryNow } : {},
|
|
1635
|
+
...input.releaseReason !== void 0 ? { reason: input.releaseReason } : {},
|
|
1636
|
+
...input.clearAssignee !== void 0 ? { clearAssignee: input.clearAssignee } : {},
|
|
1637
|
+
...policyFields ? {
|
|
1638
|
+
policy: {
|
|
1639
|
+
...input.recoveryPolicyFailOnCostCeiling !== void 0 ? { failWhenCostCeilingSet: input.recoveryPolicyFailOnCostCeiling } : {},
|
|
1640
|
+
...input.recoveryPolicyReleaseOnFailureKinds !== void 0 ? {
|
|
1641
|
+
releaseOnFailureKinds: input.recoveryPolicyReleaseOnFailureKinds
|
|
1642
|
+
} : {},
|
|
1643
|
+
...input.recoveryPolicyReleaseOnHeartbeatDue !== void 0 ? {
|
|
1644
|
+
releaseOnHeartbeatDue: input.recoveryPolicyReleaseOnHeartbeatDue
|
|
1645
|
+
} : {},
|
|
1646
|
+
...input.recoveryPolicyRetryPolicyOverride !== void 0 ? {
|
|
1647
|
+
retryPolicyOverride: input.recoveryPolicyRetryPolicyOverride
|
|
1648
|
+
} : {}
|
|
1649
|
+
}
|
|
1650
|
+
} : {}
|
|
1651
|
+
},
|
|
1652
|
+
eventContext
|
|
1653
|
+
);
|
|
1488
1654
|
return result ? {
|
|
1489
1655
|
ok: true,
|
|
1490
1656
|
message: `Recovered ${result.tasks.length} stale assignment(s).`,
|
|
@@ -1918,10 +2084,11 @@ var kanbanTool = {
|
|
|
1918
2084
|
const contractResult = await handleKanbanContractAction(
|
|
1919
2085
|
projectRoot,
|
|
1920
2086
|
input,
|
|
1921
|
-
input.author ?? input.agentId
|
|
2087
|
+
input.author ?? input.agentId,
|
|
2088
|
+
ctx.eventSessionId()
|
|
1922
2089
|
);
|
|
1923
2090
|
if (contractResult !== void 0) return contractResult;
|
|
1924
|
-
const detailResult = await handleKanbanDetailAction(projectRoot, input);
|
|
2091
|
+
const detailResult = await handleKanbanDetailAction(projectRoot, input, ctx);
|
|
1925
2092
|
if (detailResult !== void 0) return detailResult;
|
|
1926
2093
|
return fail(`Unknown kanban action: ${input.action}`);
|
|
1927
2094
|
})();
|
|
@@ -1941,4 +2108,4 @@ export {
|
|
|
1941
2108
|
recordKanbanVerificationEvidence,
|
|
1942
2109
|
kanbanTool
|
|
1943
2110
|
};
|
|
1944
|
-
//# sourceMappingURL=chunk-
|
|
2111
|
+
//# sourceMappingURL=chunk-JNNVRHMV.js.map
|