@wrongstack/tools 0.282.0 → 0.282.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/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import * as path3 from 'node:path';
4
4
  import { resolve, sep, dirname, join } from 'node:path';
5
5
  import { spawn, execFileSync } from 'node:child_process';
6
6
  import * as Core from '@wrongstack/core';
7
- import { SKILL_LIMITS, buildChildEnv, getDesignKitLoader, isDesignStack, loadActiveKit, applyTokenOverrides, setActiveKit, recordKitChoice, recordOverrides, setDesignOverrides, materializeTokens, runDesignVerify, ToolValidationError, detectNewlineStyle, normalizeToLf, toStyle, atomicWrite, unifiedDiff, ToolError, FetchError, isPrivateIPv4, isPrivateIPv6, assessCommitSafety, compileGlob, expectDefined, recordPackageAction, detectPackageEcosystem, deepMerge, addLinkToTask, addNoteToTask, updateCheckOnTask, addCheckToTask, addDependency, updateTaskAssignment, assignTask, removeTask, moveTask, updateTask, getTask, transferTaskToBoard, copyTaskToBoard, addTask, removeColumn, updateColumn, addColumn, searchKanban, exportBoardAsMarkdown, generateBoardFromDescription, createBoard, parseLinesIntoTasks, getBoard, removeBoard, duplicateBoard, updateBoard, listBoards, mutatePlan, clearPlan, getPlanTemplate, addPlanItem, deriveTodosFromPlanItem, removePlanItem, setPlanItemStatus, mutateTasks, formatTaskList, formatPlan, FsError, toErrorMessage as toErrorMessage$2, computeTaskItemProgress, loadPlan, savePlan, loadTasks, saveTasks, stripFrontmatter, wstackGlobalRoot, resolveWstackPaths, truncate } from '@wrongstack/core';
7
+ import { SKILL_LIMITS, buildChildEnv, getDesignKitLoader, isDesignStack, loadActiveKit, applyTokenOverrides, setActiveKit, recordKitChoice, recordOverrides, setDesignOverrides, materializeTokens, runDesignVerify, ToolValidationError, detectNewlineStyle, normalizeToLf, toStyle, atomicWrite, unifiedDiff, ToolError, FetchError, isPrivateIPv4, isPrivateIPv6, assessCommitSafety, compileGlob, expectDefined, recordPackageAction, detectPackageEcosystem, deepMerge, addLinkToTask, addNoteToTask, updateCheckOnTask, addCheckToTask, updateGoalMetricOnTask, addGoalMetricToTask, addDependency, updateTaskAssignment, assignTask, releaseTaskClaim, claimReadyTask, getTaskChain, setTaskChain, removeTask, moveTask, updateTask, getTask, transferTaskToBoard, copyTaskToBoard, mergeTasks, splitTask, addTask, removeColumn, updateColumn, addColumn, getKanbanOrchestrationSnapshot, listReadyTasks, searchKanban, deserializeTaskGraph, syncBoardFromTaskGraph, exportBoardToTaskGraph, serializeTaskGraph, exportBoardAsMarkdown, generateBoardFromDescription, createBoard, parseLinesIntoTasks, getBoard, removeBoard, duplicateBoard, updateBoard, listBoards, mutatePlan, clearPlan, getPlanTemplate, addPlanItem, deriveTodosFromPlanItem, removePlanItem, setPlanItemStatus, mutateTasks, formatTaskList, formatPlan, FsError, toErrorMessage as toErrorMessage$2, computeTaskItemProgress, loadPlan, savePlan, loadTasks, saveTasks, stripFrontmatter, wstackGlobalRoot, resolveWstackPaths, truncate } from '@wrongstack/core';
8
8
  import * as fs2 from 'node:fs/promises';
9
9
  import * as os2 from 'node:os';
10
10
  import { toErrorMessage as toErrorMessage$3 } from '@wrongstack/core/utils';
@@ -9410,8 +9410,8 @@ function toYaml(data, indent = 0) {
9410
9410
  var kanbanTool = {
9411
9411
  name: "kanban",
9412
9412
  category: "Project",
9413
- description: "Manage project-scoped multi-kanban boards stored under .wrongstack/kanbans. Supports board/task/column CRUD, search, assignment metadata, provider/model/fallback routing hints, success checks, notes, links, and run status updates.",
9414
- usageHint: "Use this for durable project kanban state. Assign tasks with provider/model/fallback hints before spawning agents; after a subagent starts or finishes, call mark_assignment to record subagentId/runTaskId/status/result.",
9413
+ description: "Manage project-scoped multi-kanban boards stored under .wrongstack/kanbans. Supports board/task/column CRUD, ready-task queues, dependency chains, split/merge, assignment metadata, provider/model/fallback routing hints, goal metrics, success checks, notes, links, and run status updates.",
9414
+ usageHint: "Use this for durable project kanban state. Agents should call snapshot/ready_tasks, then claim_task before working. Use set_chain for ordered work, split_task/merge_tasks when task scope changes, assign_task with provider/model/fallback hints before spawning, mark_assignment when starting or finishing, and release_task if the claim cannot be worked.",
9415
9415
  permission: "confirm",
9416
9416
  mutating: true,
9417
9417
  capabilities: ["fs.write"],
@@ -9431,20 +9431,32 @@ var kanbanTool = {
9431
9431
  "delete_board",
9432
9432
  "generate_board",
9433
9433
  "export_markdown",
9434
+ "export_task_graph",
9435
+ "sync_task_graph",
9434
9436
  "search_tasks",
9437
+ "ready_tasks",
9438
+ "snapshot",
9435
9439
  "add_column",
9436
9440
  "update_column",
9437
9441
  "delete_column",
9438
9442
  "add_task",
9443
+ "split_task",
9444
+ "merge_tasks",
9439
9445
  "copy_task",
9440
9446
  "transfer_task",
9441
9447
  "get_task",
9442
9448
  "update_task",
9443
9449
  "move_task",
9444
9450
  "delete_task",
9451
+ "set_chain",
9452
+ "get_chain",
9453
+ "claim_task",
9454
+ "release_task",
9445
9455
  "assign_task",
9446
9456
  "mark_assignment",
9447
9457
  "add_dependency",
9458
+ "add_goal_metric",
9459
+ "update_goal_metric",
9448
9460
  "add_check",
9449
9461
  "update_check",
9450
9462
  "add_note",
@@ -9453,6 +9465,8 @@ var kanbanTool = {
9453
9465
  },
9454
9466
  boardId: { type: "string" },
9455
9467
  taskId: { type: "string" },
9468
+ taskIds: { type: "array", items: { type: "string" } },
9469
+ chainId: { type: "string" },
9456
9470
  columnId: { type: "string" },
9457
9471
  targetBoardId: { type: "string" },
9458
9472
  targetColumnId: { type: "string" },
@@ -9476,6 +9490,7 @@ var kanbanTool = {
9476
9490
  },
9477
9491
  order: { type: "number" },
9478
9492
  query: { type: "string" },
9493
+ limit: { type: "number" },
9479
9494
  agentId: { type: "string" },
9480
9495
  name: { type: "string" },
9481
9496
  role: { type: "string" },
@@ -9493,7 +9508,36 @@ var kanbanTool = {
9493
9508
  type: "string",
9494
9509
  enum: ["assigned", "queued", "running", "completed", "failed", "cancelled"]
9495
9510
  },
9511
+ releaseStatus: { type: "string", enum: ["pending", "ready", "blocked"] },
9512
+ releaseReason: { type: "string" },
9513
+ clearAssignee: { type: "boolean" },
9514
+ taskGraph: { type: "object" },
9515
+ graphId: { type: "string" },
9516
+ specId: { type: "string" },
9517
+ sourceSystem: { type: "string" },
9518
+ phaseId: { type: "string" },
9519
+ preserveOriginTaskIds: { type: "boolean" },
9520
+ includeArchived: { type: "boolean" },
9521
+ archiveMissingTasks: { type: "boolean" },
9522
+ preserveManualDependencies: { type: "boolean" },
9496
9523
  dependencyTaskId: { type: "string" },
9524
+ enforceDependencies: { type: "boolean" },
9525
+ childTitles: { type: "array", items: { type: "string" } },
9526
+ inheritAssignment: { type: "boolean" },
9527
+ inheritLabels: { type: "boolean" },
9528
+ inheritSuccessCriteria: { type: "boolean" },
9529
+ inheritGoalMetrics: { type: "boolean" },
9530
+ inheritDependencies: { type: "boolean" },
9531
+ chainChildren: { type: "boolean" },
9532
+ rewireDependents: { type: "boolean" },
9533
+ closeSourceTasks: { type: "boolean" },
9534
+ metricId: { type: "string" },
9535
+ metricName: { type: "string" },
9536
+ metricTarget: { oneOf: [{ type: "string" }, { type: "number" }] },
9537
+ metricCurrent: { oneOf: [{ type: "string" }, { type: "number" }] },
9538
+ metricUnit: { type: "string" },
9539
+ metricStatus: { type: "string", enum: ["pending", "met", "missed", "waived"] },
9540
+ metricNotes: { type: "string" },
9497
9541
  checkId: { type: "string" },
9498
9542
  checkDescription: { type: "string" },
9499
9543
  checkStatus: { type: "string", enum: ["pending", "passed", "failed", "skipped"] },
@@ -9519,270 +9563,470 @@ var kanbanTool = {
9519
9563
  async execute(input, ctx) {
9520
9564
  const projectRoot = ctx.projectRoot;
9521
9565
  if (!projectRoot) return fail("No project root is available.");
9522
- switch (input.action) {
9523
- case "list_boards": {
9524
- const boards = await listBoards(projectRoot);
9525
- return { ok: true, message: `${boards.length} board(s).`, boards };
9526
- }
9527
- case "get_board": {
9528
- const board = await requireBoard(projectRoot, input.boardId);
9529
- return board ? okBoard(board) : fail("Board not found.");
9530
- }
9531
- case "create_board": {
9532
- if (!input.title) return fail("create_board requires title.");
9533
- const board = await createBoard(projectRoot, {
9534
- title: input.title,
9535
- ...input.description !== void 0 ? { description: input.description } : {},
9536
- ...input.tags !== void 0 ? { tags: input.tags } : {},
9537
- ...input.generatedBy !== void 0 ? { generatedBy: input.generatedBy } : {}
9538
- });
9539
- return { ok: true, message: `Board created: ${board.title}`, board };
9540
- }
9541
- case "update_board": {
9542
- if (!input.boardId) return fail("update_board requires boardId.");
9543
- const board = await updateBoard(projectRoot, input.boardId, {
9544
- ...input.title !== void 0 ? { title: input.title } : {},
9545
- ...input.description !== void 0 ? { description: input.description } : {},
9546
- ...input.tags !== void 0 ? { tags: input.tags } : {}
9547
- });
9548
- return board ? okBoard(board, "Board updated.") : fail("Board not found.");
9549
- }
9550
- case "duplicate_board": {
9551
- if (!input.boardId) return fail("duplicate_board requires boardId.");
9552
- const board = await duplicateBoard(projectRoot, input.boardId, {
9553
- ...input.title !== void 0 ? { title: input.title } : {},
9554
- ...input.generatedBy !== void 0 ? { generatedBy: input.generatedBy } : {},
9555
- ...input.includeTasks !== void 0 ? { includeTasks: input.includeTasks } : {},
9556
- ...input.includeCompletedTasks !== void 0 ? { includeCompletedTasks: input.includeCompletedTasks } : {},
9557
- ...input.preserveAssignment !== void 0 ? { preserveAssignment: input.preserveAssignment } : {}
9558
- });
9559
- return board ? okBoard(board, "Board duplicated.") : fail("Board not found.");
9560
- }
9561
- case "delete_board": {
9562
- if (!input.boardId) return fail("delete_board requires boardId.");
9563
- const removed = await removeBoard(projectRoot, input.boardId);
9564
- return { ok: removed, message: removed ? "Board deleted." : "Board not found." };
9565
- }
9566
- case "generate_board": {
9567
- if (!input.description) return fail("generate_board requires description.");
9568
- const boardInput = generateBoardFromDescription({
9569
- description: input.description,
9570
- ...input.title !== void 0 ? { title: input.title } : {},
9571
- ...input.context !== void 0 ? { context: input.context } : {},
9572
- ...input.columns !== void 0 ? { columns: input.columns } : {}
9573
- });
9574
- const board = await createBoard(projectRoot, boardInput);
9575
- for (const taskInput2 of parseLinesIntoTasks(
9576
- input.description,
9577
- board.columns[0]?.id ?? "backlog"
9578
- )) {
9579
- await addTask(projectRoot, board.id, taskInput2);
9566
+ try {
9567
+ switch (input.action) {
9568
+ case "list_boards": {
9569
+ const boards = await listBoards(projectRoot);
9570
+ return { ok: true, message: `${boards.length} board(s).`, boards };
9580
9571
  }
9581
- return okBoard(await getBoard(projectRoot, board.id) ?? board, "Board generated.");
9582
- }
9583
- case "export_markdown": {
9584
- const board = await requireBoard(projectRoot, input.boardId);
9585
- if (!board) return fail("Board not found.");
9586
- return {
9587
- ok: true,
9588
- message: "Board exported.",
9589
- board,
9590
- markdown: exportBoardAsMarkdown(board)
9591
- };
9592
- }
9593
- case "search_tasks": {
9594
- const tasks = await searchKanban(projectRoot, {
9595
- query: input.query,
9596
- boardId: input.boardId,
9597
- assignedAgent: input.agentId,
9598
- status: input.status,
9599
- priority: input.priority,
9600
- label: input.labels?.[0]
9601
- });
9602
- return { ok: true, message: `${tasks.length} task(s) matched.`, tasks };
9603
- }
9604
- case "add_column": {
9605
- if (!input.boardId || !input.title) return fail("add_column requires boardId and title.");
9606
- const result = await addColumn(projectRoot, input.boardId, {
9607
- title: input.title,
9608
- ...input.description !== void 0 ? { description: input.description } : {}
9609
- });
9610
- return result ? okBoard(result.board, "Column added.") : fail("Board not found.");
9611
- }
9612
- case "update_column": {
9613
- if (!input.boardId || !input.columnId)
9614
- return fail("update_column requires boardId and columnId.");
9615
- const board = await updateColumn(projectRoot, input.boardId, input.columnId, {
9616
- ...input.title !== void 0 ? { title: input.title } : {},
9617
- ...input.description !== void 0 ? { description: input.description } : {},
9618
- ...input.order !== void 0 ? { order: input.order } : {}
9619
- });
9620
- return board ? okBoard(board, "Column updated.") : fail("Column not found.");
9621
- }
9622
- case "delete_column": {
9623
- if (!input.boardId || !input.columnId)
9624
- return fail("delete_column requires boardId and columnId.");
9625
- const board = await removeColumn(projectRoot, input.boardId, input.columnId, {
9626
- moveTasksToColumnId: input.moveTasksToColumnId
9627
- });
9628
- return board ? okBoard(board, "Column deleted.") : fail("Column not found.");
9629
- }
9630
- case "add_task": {
9631
- if (!input.boardId || !input.title) return fail("add_task requires boardId and title.");
9632
- const result = await addTask(projectRoot, input.boardId, taskInput(input));
9633
- return result ? okTask(result.board, result.task, "Task added.") : fail("Board not found.");
9634
- }
9635
- case "copy_task": {
9636
- if (!input.boardId || !input.taskId || !input.targetBoardId) {
9637
- return fail("copy_task requires boardId, taskId, and targetBoardId.");
9572
+ case "get_board": {
9573
+ const board = await requireBoard(projectRoot, input.boardId);
9574
+ return board ? okBoard(board) : fail("Board not found.");
9638
9575
  }
9639
- const result = await copyTaskToBoard(
9640
- projectRoot,
9641
- input.boardId,
9642
- input.taskId,
9643
- input.targetBoardId,
9644
- {
9645
- ...input.targetColumnId !== void 0 ? { targetColumnId: input.targetColumnId } : {},
9646
- ...input.order !== void 0 ? { targetOrder: input.order } : {},
9647
- ...input.preserveAssignment !== void 0 ? { preserveAssignment: input.preserveAssignment } : {},
9648
- ...input.preserveDependencies !== void 0 ? { preserveDependencies: input.preserveDependencies } : {}
9576
+ case "create_board": {
9577
+ if (!input.title) return fail("create_board requires title.");
9578
+ const board = await createBoard(projectRoot, {
9579
+ title: input.title,
9580
+ ...input.description !== void 0 ? { description: input.description } : {},
9581
+ ...input.tags !== void 0 ? { tags: input.tags } : {},
9582
+ ...input.generatedBy !== void 0 ? { generatedBy: input.generatedBy } : {}
9583
+ });
9584
+ return { ok: true, message: `Board created: ${board.title}`, board };
9585
+ }
9586
+ case "update_board": {
9587
+ if (!input.boardId) return fail("update_board requires boardId.");
9588
+ const board = await updateBoard(projectRoot, input.boardId, {
9589
+ ...input.title !== void 0 ? { title: input.title } : {},
9590
+ ...input.description !== void 0 ? { description: input.description } : {},
9591
+ ...input.tags !== void 0 ? { tags: input.tags } : {}
9592
+ });
9593
+ return board ? okBoard(board, "Board updated.") : fail("Board not found.");
9594
+ }
9595
+ case "duplicate_board": {
9596
+ if (!input.boardId) return fail("duplicate_board requires boardId.");
9597
+ const board = await duplicateBoard(projectRoot, input.boardId, {
9598
+ ...input.title !== void 0 ? { title: input.title } : {},
9599
+ ...input.generatedBy !== void 0 ? { generatedBy: input.generatedBy } : {},
9600
+ ...input.includeTasks !== void 0 ? { includeTasks: input.includeTasks } : {},
9601
+ ...input.includeCompletedTasks !== void 0 ? { includeCompletedTasks: input.includeCompletedTasks } : {},
9602
+ ...input.preserveAssignment !== void 0 ? { preserveAssignment: input.preserveAssignment } : {}
9603
+ });
9604
+ return board ? okBoard(board, "Board duplicated.") : fail("Board not found.");
9605
+ }
9606
+ case "delete_board": {
9607
+ if (!input.boardId) return fail("delete_board requires boardId.");
9608
+ const removed = await removeBoard(projectRoot, input.boardId);
9609
+ return { ok: removed, message: removed ? "Board deleted." : "Board not found." };
9610
+ }
9611
+ case "generate_board": {
9612
+ if (!input.description) return fail("generate_board requires description.");
9613
+ const boardInput = generateBoardFromDescription({
9614
+ description: input.description,
9615
+ ...input.title !== void 0 ? { title: input.title } : {},
9616
+ ...input.context !== void 0 ? { context: input.context } : {},
9617
+ ...input.columns !== void 0 ? { columns: input.columns } : {}
9618
+ });
9619
+ const board = await createBoard(projectRoot, boardInput);
9620
+ for (const taskInput2 of parseLinesIntoTasks(
9621
+ input.description,
9622
+ board.columns[0]?.id ?? "backlog"
9623
+ )) {
9624
+ await addTask(projectRoot, board.id, taskInput2);
9649
9625
  }
9650
- );
9651
- return result ? okTask(result.targetBoard, result.task, "Task copied to target board.") : fail("Board or task not found.");
9652
- }
9653
- case "transfer_task": {
9654
- if (!input.boardId || !input.taskId || !input.targetBoardId) {
9655
- return fail("transfer_task requires boardId, taskId, and targetBoardId.");
9626
+ return okBoard(await getBoard(projectRoot, board.id) ?? board, "Board generated.");
9656
9627
  }
9657
- const result = await transferTaskToBoard(
9658
- projectRoot,
9659
- input.boardId,
9660
- input.taskId,
9661
- input.targetBoardId,
9662
- {
9628
+ case "export_markdown": {
9629
+ const board = await requireBoard(projectRoot, input.boardId);
9630
+ if (!board) return fail("Board not found.");
9631
+ return {
9632
+ ok: true,
9633
+ message: "Board exported.",
9634
+ board,
9635
+ markdown: exportBoardAsMarkdown(board)
9636
+ };
9637
+ }
9638
+ case "export_task_graph": {
9639
+ if (!input.boardId) return fail("export_task_graph requires boardId.");
9640
+ const exported = await exportBoardToTaskGraph(projectRoot, input.boardId, {
9641
+ ...input.graphId !== void 0 ? { graphId: input.graphId } : {},
9642
+ ...input.specId !== void 0 ? { specId: input.specId } : {},
9643
+ ...input.title !== void 0 ? { title: input.title } : {},
9644
+ ...input.preserveOriginTaskIds !== void 0 ? { preserveOriginTaskIds: input.preserveOriginTaskIds } : {},
9645
+ ...input.includeArchived !== void 0 ? { includeArchived: input.includeArchived } : {}
9646
+ });
9647
+ if (!exported) return fail("Board not found.");
9648
+ return {
9649
+ ok: true,
9650
+ message: `Task graph exported with ${exported.graph.nodes.size} node(s).`,
9651
+ board: exported.board,
9652
+ taskGraph: serializeTaskGraph(exported.graph)
9653
+ };
9654
+ }
9655
+ case "sync_task_graph": {
9656
+ if (!input.boardId || !input.taskGraph) {
9657
+ return fail("sync_task_graph requires boardId and taskGraph.");
9658
+ }
9659
+ const graph = deserializeTaskGraph(input.taskGraph);
9660
+ const result = await syncBoardFromTaskGraph(projectRoot, input.boardId, graph, {
9661
+ ...input.title !== void 0 ? { title: input.title } : {},
9662
+ ...input.description !== void 0 ? { description: input.description } : {},
9663
+ ...input.tags !== void 0 ? { tags: input.tags } : {},
9664
+ ...input.generatedBy !== void 0 ? { generatedBy: input.generatedBy } : {},
9665
+ ...input.sourceSystem !== void 0 ? { sourceSystem: input.sourceSystem } : {},
9666
+ ...input.phaseId !== void 0 ? { phaseId: input.phaseId } : {},
9667
+ ...input.includeCompletedTasks !== void 0 ? { includeCompletedTasks: input.includeCompletedTasks } : {},
9668
+ ...input.archiveMissingTasks !== void 0 ? { archiveMissingTasks: input.archiveMissingTasks } : {},
9669
+ ...input.preserveManualDependencies !== void 0 ? { preserveManualDependencies: input.preserveManualDependencies } : {}
9670
+ });
9671
+ return result ? {
9672
+ ok: true,
9673
+ message: `Task graph synced: ${result.createdTaskIds.length} created, ${result.updatedTaskIds.length} updated, ${result.archivedTaskIds.length} archived.`,
9674
+ board: result.board
9675
+ } : fail("Board not found.");
9676
+ }
9677
+ case "search_tasks": {
9678
+ const tasks = await searchKanban(projectRoot, {
9679
+ query: input.query,
9680
+ boardId: input.boardId,
9681
+ assignedAgent: input.agentId,
9682
+ status: input.status,
9683
+ priority: input.priority,
9684
+ label: input.labels?.[0],
9685
+ chainId: input.chainId
9686
+ });
9687
+ return { ok: true, message: `${tasks.length} task(s) matched.`, tasks };
9688
+ }
9689
+ case "ready_tasks": {
9690
+ const tasks = await listReadyTasks(projectRoot, {
9691
+ query: input.query,
9692
+ boardId: input.boardId,
9693
+ assignedAgent: input.agentId,
9694
+ priority: input.priority,
9695
+ label: input.labels?.[0],
9696
+ chainId: input.chainId,
9697
+ limit: input.limit
9698
+ });
9699
+ return { ok: true, message: `${tasks.length} ready task(s).`, tasks };
9700
+ }
9701
+ case "snapshot": {
9702
+ const snapshot = await getKanbanOrchestrationSnapshot(projectRoot, {
9703
+ query: input.query,
9704
+ boardId: input.boardId,
9705
+ assignedAgent: input.agentId,
9706
+ status: input.status,
9707
+ priority: input.priority,
9708
+ label: input.labels?.[0],
9709
+ chainId: input.chainId
9710
+ });
9711
+ return {
9712
+ ok: true,
9713
+ message: `${snapshot.ready.length} ready, ${snapshot.running.length} running, ${snapshot.blocked.length} blocked.`,
9714
+ snapshot
9715
+ };
9716
+ }
9717
+ case "add_column": {
9718
+ if (!input.boardId || !input.title) return fail("add_column requires boardId and title.");
9719
+ const result = await addColumn(projectRoot, input.boardId, {
9720
+ title: input.title,
9721
+ ...input.description !== void 0 ? { description: input.description } : {}
9722
+ });
9723
+ return result ? okBoard(result.board, "Column added.") : fail("Board not found.");
9724
+ }
9725
+ case "update_column": {
9726
+ if (!input.boardId || !input.columnId)
9727
+ return fail("update_column requires boardId and columnId.");
9728
+ const board = await updateColumn(projectRoot, input.boardId, input.columnId, {
9729
+ ...input.title !== void 0 ? { title: input.title } : {},
9730
+ ...input.description !== void 0 ? { description: input.description } : {},
9731
+ ...input.order !== void 0 ? { order: input.order } : {}
9732
+ });
9733
+ return board ? okBoard(board, "Column updated.") : fail("Column not found.");
9734
+ }
9735
+ case "delete_column": {
9736
+ if (!input.boardId || !input.columnId)
9737
+ return fail("delete_column requires boardId and columnId.");
9738
+ const board = await removeColumn(projectRoot, input.boardId, input.columnId, {
9739
+ moveTasksToColumnId: input.moveTasksToColumnId
9740
+ });
9741
+ return board ? okBoard(board, "Column deleted.") : fail("Column not found.");
9742
+ }
9743
+ case "add_task": {
9744
+ if (!input.boardId || !input.title) return fail("add_task requires boardId and title.");
9745
+ const result = await addTask(projectRoot, input.boardId, taskInput(input));
9746
+ return result ? okTask(result.board, result.task, "Task added.") : fail("Board not found.");
9747
+ }
9748
+ case "split_task": {
9749
+ if (!input.boardId || !input.taskId || !input.childTitles?.length) {
9750
+ return fail("split_task requires boardId, taskId, and childTitles.");
9751
+ }
9752
+ const result = await splitTask(projectRoot, input.boardId, input.taskId, {
9753
+ titles: input.childTitles,
9754
+ ...input.targetColumnId !== void 0 ? { columnId: input.targetColumnId } : {},
9755
+ ...input.inheritAssignment !== void 0 ? { inheritAssignment: input.inheritAssignment } : {},
9756
+ ...input.inheritLabels !== void 0 ? { inheritLabels: input.inheritLabels } : {},
9757
+ ...input.inheritSuccessCriteria !== void 0 ? { inheritSuccessCriteria: input.inheritSuccessCriteria } : {},
9758
+ ...input.inheritGoalMetrics !== void 0 ? { inheritGoalMetrics: input.inheritGoalMetrics } : {},
9759
+ ...input.inheritDependencies !== void 0 ? { inheritDependencies: input.inheritDependencies } : {},
9760
+ ...input.chainChildren !== void 0 ? { chainChildren: input.chainChildren } : {},
9761
+ ...input.rewireDependents !== void 0 ? { rewireDependents: input.rewireDependents } : {}
9762
+ });
9763
+ return result ? {
9764
+ ok: true,
9765
+ message: `${result.children.length} child task(s) created.`,
9766
+ board: result.board,
9767
+ task: result.parent,
9768
+ children: result.children
9769
+ } : fail("Task not found.");
9770
+ }
9771
+ case "merge_tasks": {
9772
+ if (!input.boardId || !input.taskIds?.length || !input.title) {
9773
+ return fail("merge_tasks requires boardId, taskIds, and title.");
9774
+ }
9775
+ const result = await mergeTasks(projectRoot, input.boardId, {
9776
+ taskIds: input.taskIds,
9777
+ title: input.title,
9778
+ ...input.description !== void 0 ? { description: input.description } : {},
9663
9779
  ...input.targetColumnId !== void 0 ? { targetColumnId: input.targetColumnId } : {},
9664
- ...input.order !== void 0 ? { targetOrder: input.order } : {},
9665
9780
  ...input.preserveAssignment !== void 0 ? { preserveAssignment: input.preserveAssignment } : {},
9666
- ...input.preserveDependencies !== void 0 ? { preserveDependencies: input.preserveDependencies } : {}
9781
+ ...input.closeSourceTasks !== void 0 ? { closeSourceTasks: input.closeSourceTasks } : {}
9782
+ });
9783
+ return result ? okTask(result.board, result.task, "Tasks merged.") : fail("Board or task not found.");
9784
+ }
9785
+ case "copy_task": {
9786
+ if (!input.boardId || !input.taskId || !input.targetBoardId) {
9787
+ return fail("copy_task requires boardId, taskId, and targetBoardId.");
9667
9788
  }
9668
- );
9669
- return result ? okTask(result.targetBoard, result.task, "Task transferred to target board.") : fail("Board or task not found.");
9670
- }
9671
- case "get_task": {
9672
- if (!input.boardId || !input.taskId) return fail("get_task requires boardId and taskId.");
9673
- const task = await getTask(projectRoot, input.boardId, input.taskId);
9674
- return task ? { ok: true, message: "Task loaded.", task } : fail("Task not found.");
9675
- }
9676
- case "update_task": {
9677
- if (!input.boardId || !input.taskId)
9678
- return fail("update_task requires boardId and taskId.");
9679
- const board = await updateTask(projectRoot, input.boardId, input.taskId, taskPatch(input));
9680
- return board ? okBoard(board, "Task updated.") : fail("Task not found.");
9681
- }
9682
- case "move_task": {
9683
- if (!input.boardId || !input.taskId || !input.targetColumnId) {
9684
- return fail("move_task requires boardId, taskId, and targetColumnId.");
9789
+ const result = await copyTaskToBoard(
9790
+ projectRoot,
9791
+ input.boardId,
9792
+ input.taskId,
9793
+ input.targetBoardId,
9794
+ {
9795
+ ...input.targetColumnId !== void 0 ? { targetColumnId: input.targetColumnId } : {},
9796
+ ...input.order !== void 0 ? { targetOrder: input.order } : {},
9797
+ ...input.preserveAssignment !== void 0 ? { preserveAssignment: input.preserveAssignment } : {},
9798
+ ...input.preserveDependencies !== void 0 ? { preserveDependencies: input.preserveDependencies } : {}
9799
+ }
9800
+ );
9801
+ return result ? okTask(result.targetBoard, result.task, "Task copied to target board.") : fail("Board or task not found.");
9685
9802
  }
9686
- const board = await moveTask(
9687
- projectRoot,
9688
- input.boardId,
9689
- input.taskId,
9690
- input.targetColumnId,
9691
- input.order
9692
- );
9693
- return board ? okBoard(board, "Task moved.") : fail("Move failed.");
9694
- }
9695
- case "delete_task": {
9696
- if (!input.boardId || !input.taskId)
9697
- return fail("delete_task requires boardId and taskId.");
9698
- const board = await removeTask(projectRoot, input.boardId, input.taskId);
9699
- return board ? okBoard(board, "Task deleted.") : fail("Task not found.");
9700
- }
9701
- case "assign_task": {
9702
- if (!input.boardId || !input.taskId)
9703
- return fail("assign_task requires boardId and taskId.");
9704
- const board = await assignTask(
9705
- projectRoot,
9706
- input.boardId,
9707
- input.taskId,
9708
- assignmentInput(input)
9709
- );
9710
- return board ? okBoard(board, "Task assigned.") : fail("Task not found.");
9711
- }
9712
- case "mark_assignment": {
9713
- if (!input.boardId || !input.taskId)
9714
- return fail("mark_assignment requires boardId and taskId.");
9715
- const assignmentStatus = input.assignmentStatus ?? (input.status === "completed" ? "completed" : input.error ? "failed" : void 0);
9716
- const board = await updateTaskAssignment(projectRoot, input.boardId, input.taskId, {
9717
- ...assignmentStatus !== void 0 ? { status: assignmentStatus } : {},
9718
- ...input.subagentId !== void 0 ? { subagentId: input.subagentId } : {},
9719
- ...input.runTaskId !== void 0 ? { runTaskId: input.runTaskId } : {},
9720
- ...input.lastResult !== void 0 ? { lastResult: input.lastResult } : {},
9721
- ...input.error !== void 0 ? { error: input.error } : {},
9722
- ...input.agentId !== void 0 ? { agentId: input.agentId } : {}
9723
- });
9724
- return board ? okBoard(board, "Assignment updated.") : fail("Task not found.");
9725
- }
9726
- case "add_dependency": {
9727
- if (!input.boardId || !input.taskId || !input.dependencyTaskId) {
9728
- return fail("add_dependency requires boardId, taskId, and dependencyTaskId.");
9803
+ case "transfer_task": {
9804
+ if (!input.boardId || !input.taskId || !input.targetBoardId) {
9805
+ return fail("transfer_task requires boardId, taskId, and targetBoardId.");
9806
+ }
9807
+ const result = await transferTaskToBoard(
9808
+ projectRoot,
9809
+ input.boardId,
9810
+ input.taskId,
9811
+ input.targetBoardId,
9812
+ {
9813
+ ...input.targetColumnId !== void 0 ? { targetColumnId: input.targetColumnId } : {},
9814
+ ...input.order !== void 0 ? { targetOrder: input.order } : {},
9815
+ ...input.preserveAssignment !== void 0 ? { preserveAssignment: input.preserveAssignment } : {},
9816
+ ...input.preserveDependencies !== void 0 ? { preserveDependencies: input.preserveDependencies } : {}
9817
+ }
9818
+ );
9819
+ return result ? okTask(result.targetBoard, result.task, "Task transferred to target board.") : fail("Board or task not found.");
9729
9820
  }
9730
- const board = await addDependency(
9731
- projectRoot,
9732
- input.boardId,
9733
- input.taskId,
9734
- input.dependencyTaskId
9735
- );
9736
- return board ? okBoard(board, "Dependency added.") : fail("Task not found.");
9737
- }
9738
- case "add_check": {
9739
- if (!input.boardId || !input.taskId || !input.checkDescription) {
9740
- return fail("add_check requires boardId, taskId, and checkDescription.");
9821
+ case "get_task": {
9822
+ if (!input.boardId || !input.taskId) return fail("get_task requires boardId and taskId.");
9823
+ const task = await getTask(projectRoot, input.boardId, input.taskId);
9824
+ return task ? { ok: true, message: "Task loaded.", task } : fail("Task not found.");
9741
9825
  }
9742
- const board = await addCheckToTask(projectRoot, input.boardId, input.taskId, {
9743
- description: input.checkDescription,
9744
- type: "manual",
9745
- status: input.checkStatus
9746
- });
9747
- return board ? okBoard(board, "Check added.") : fail("Task not found.");
9748
- }
9749
- case "update_check": {
9750
- if (!input.boardId || !input.taskId || !input.checkId) {
9751
- return fail("update_check requires boardId, taskId, and checkId.");
9826
+ case "update_task": {
9827
+ if (!input.boardId || !input.taskId)
9828
+ return fail("update_task requires boardId and taskId.");
9829
+ const board = await updateTask(
9830
+ projectRoot,
9831
+ input.boardId,
9832
+ input.taskId,
9833
+ taskPatch(input)
9834
+ );
9835
+ return board ? okBoard(board, "Task updated.") : fail("Task not found.");
9752
9836
  }
9753
- const board = await updateCheckOnTask(
9754
- projectRoot,
9755
- input.boardId,
9756
- input.taskId,
9757
- input.checkId,
9758
- {
9759
- ...input.checkDescription !== void 0 ? { description: input.checkDescription } : {},
9760
- ...input.checkStatus !== void 0 ? { status: input.checkStatus } : {}
9837
+ case "move_task": {
9838
+ if (!input.boardId || !input.taskId || !input.targetColumnId) {
9839
+ return fail("move_task requires boardId, taskId, and targetColumnId.");
9761
9840
  }
9762
- );
9763
- return board ? okBoard(board, "Check updated.") : fail("Check not found.");
9764
- }
9765
- case "add_note": {
9766
- if (!input.boardId || !input.taskId || !input.note)
9767
- return fail("add_note requires boardId, taskId, and note.");
9768
- const board = await addNoteToTask(projectRoot, input.boardId, input.taskId, {
9769
- author: input.author ?? "agent",
9770
- content: input.note
9771
- });
9772
- return board ? okBoard(board, "Note added.") : fail("Task not found.");
9773
- }
9774
- case "add_link": {
9775
- if (!input.boardId || !input.taskId || !input.url)
9776
- return fail("add_link requires boardId, taskId, and url.");
9777
- const board = await addLinkToTask(projectRoot, input.boardId, input.taskId, {
9778
- url: input.url,
9779
- type: input.linkType ?? "url",
9780
- ...input.linkTitle !== void 0 ? { title: input.linkTitle } : {}
9781
- });
9782
- return board ? okBoard(board, "Link added.") : fail("Task not found.");
9841
+ const board = await moveTask(
9842
+ projectRoot,
9843
+ input.boardId,
9844
+ input.taskId,
9845
+ input.targetColumnId,
9846
+ input.order
9847
+ );
9848
+ return board ? okBoard(board, "Task moved.") : fail("Move failed.");
9849
+ }
9850
+ case "delete_task": {
9851
+ if (!input.boardId || !input.taskId)
9852
+ return fail("delete_task requires boardId and taskId.");
9853
+ const board = await removeTask(projectRoot, input.boardId, input.taskId);
9854
+ return board ? okBoard(board, "Task deleted.") : fail("Task not found.");
9855
+ }
9856
+ case "set_chain": {
9857
+ if (!input.boardId || !input.taskIds?.length) {
9858
+ return fail("set_chain requires boardId and taskIds.");
9859
+ }
9860
+ const result = await setTaskChain(projectRoot, input.boardId, {
9861
+ taskIds: input.taskIds,
9862
+ ...input.chainId !== void 0 ? { chainId: input.chainId } : {},
9863
+ ...input.enforceDependencies !== void 0 ? { enforceDependencies: input.enforceDependencies } : {}
9864
+ });
9865
+ return result ? {
9866
+ ok: true,
9867
+ message: `Chain set: ${result.chainId}`,
9868
+ board: result.board,
9869
+ chain: result.tasks
9870
+ } : fail("Board or task not found.");
9871
+ }
9872
+ case "get_chain": {
9873
+ if (!input.boardId || !(input.taskId || input.chainId)) {
9874
+ return fail("get_chain requires boardId and taskId or chainId.");
9875
+ }
9876
+ const result = await getTaskChain(
9877
+ projectRoot,
9878
+ input.boardId,
9879
+ input.taskId ?? input.chainId ?? ""
9880
+ );
9881
+ return result ? {
9882
+ ok: true,
9883
+ message: `Chain loaded: ${result.chainId}`,
9884
+ board: result.board,
9885
+ chain: result.tasks
9886
+ } : fail("Chain not found.");
9887
+ }
9888
+ case "claim_task": {
9889
+ const result = await claimReadyTask(projectRoot, {
9890
+ ...input.boardId !== void 0 ? { boardId: input.boardId } : {},
9891
+ ...input.taskId !== void 0 ? { taskId: input.taskId } : {},
9892
+ ...assignmentInput(input),
9893
+ status: input.assignmentStatus ?? "queued"
9894
+ });
9895
+ return result ? okTask(result.board, result.task, "Task claimed.") : fail("No ready kanban task matched the claim.");
9896
+ }
9897
+ case "release_task": {
9898
+ if (!input.boardId || !input.taskId) {
9899
+ return fail("release_task requires boardId and taskId.");
9900
+ }
9901
+ const board = await releaseTaskClaim(projectRoot, input.boardId, input.taskId, {
9902
+ ...input.releaseStatus !== void 0 ? { status: input.releaseStatus } : {},
9903
+ ...input.releaseReason !== void 0 ? { reason: input.releaseReason } : {},
9904
+ ...input.clearAssignee !== void 0 ? { clearAssignee: input.clearAssignee } : {}
9905
+ });
9906
+ return board ? okBoard(board, "Task claim released.") : fail("Task not found.");
9907
+ }
9908
+ case "assign_task": {
9909
+ if (!input.boardId || !input.taskId)
9910
+ return fail("assign_task requires boardId and taskId.");
9911
+ const board = await assignTask(
9912
+ projectRoot,
9913
+ input.boardId,
9914
+ input.taskId,
9915
+ assignmentInput(input)
9916
+ );
9917
+ return board ? okBoard(board, "Task assigned.") : fail("Task not found.");
9918
+ }
9919
+ case "mark_assignment": {
9920
+ if (!input.boardId || !input.taskId)
9921
+ return fail("mark_assignment requires boardId and taskId.");
9922
+ const assignmentStatus = input.assignmentStatus ?? (input.status === "completed" ? "completed" : input.error ? "failed" : void 0);
9923
+ const board = await updateTaskAssignment(projectRoot, input.boardId, input.taskId, {
9924
+ ...assignmentStatus !== void 0 ? { status: assignmentStatus } : {},
9925
+ ...input.subagentId !== void 0 ? { subagentId: input.subagentId } : {},
9926
+ ...input.runTaskId !== void 0 ? { runTaskId: input.runTaskId } : {},
9927
+ ...input.lastResult !== void 0 ? { lastResult: input.lastResult } : {},
9928
+ ...input.error !== void 0 ? { error: input.error } : {},
9929
+ ...input.agentId !== void 0 ? { agentId: input.agentId } : {}
9930
+ });
9931
+ return board ? okBoard(board, "Assignment updated.") : fail("Task not found.");
9932
+ }
9933
+ case "add_dependency": {
9934
+ if (!input.boardId || !input.taskId || !input.dependencyTaskId) {
9935
+ return fail("add_dependency requires boardId, taskId, and dependencyTaskId.");
9936
+ }
9937
+ const board = await addDependency(
9938
+ projectRoot,
9939
+ input.boardId,
9940
+ input.taskId,
9941
+ input.dependencyTaskId
9942
+ );
9943
+ return board ? okBoard(board, "Dependency added.") : fail("Task not found.");
9944
+ }
9945
+ case "add_goal_metric": {
9946
+ if (!input.boardId || !input.taskId || !input.metricName) {
9947
+ return fail("add_goal_metric requires boardId, taskId, and metricName.");
9948
+ }
9949
+ const board = await addGoalMetricToTask(projectRoot, input.boardId, input.taskId, {
9950
+ name: input.metricName,
9951
+ ...input.metricStatus !== void 0 ? { status: input.metricStatus } : {},
9952
+ ...input.metricTarget !== void 0 ? { target: input.metricTarget } : {},
9953
+ ...input.metricCurrent !== void 0 ? { current: input.metricCurrent } : {},
9954
+ ...input.metricUnit !== void 0 ? { unit: input.metricUnit } : {},
9955
+ ...input.metricNotes !== void 0 ? { notes: input.metricNotes } : {}
9956
+ });
9957
+ return board ? okBoard(board, "Goal metric added.") : fail("Task not found.");
9958
+ }
9959
+ case "update_goal_metric": {
9960
+ if (!input.boardId || !input.taskId || !input.metricId) {
9961
+ return fail("update_goal_metric requires boardId, taskId, and metricId.");
9962
+ }
9963
+ const board = await updateGoalMetricOnTask(
9964
+ projectRoot,
9965
+ input.boardId,
9966
+ input.taskId,
9967
+ input.metricId,
9968
+ {
9969
+ ...input.metricName !== void 0 ? { name: input.metricName } : {},
9970
+ ...input.metricStatus !== void 0 ? { status: input.metricStatus } : {},
9971
+ ...input.metricTarget !== void 0 ? { target: input.metricTarget } : {},
9972
+ ...input.metricCurrent !== void 0 ? { current: input.metricCurrent } : {},
9973
+ ...input.metricUnit !== void 0 ? { unit: input.metricUnit } : {},
9974
+ ...input.metricNotes !== void 0 ? { notes: input.metricNotes } : {}
9975
+ }
9976
+ );
9977
+ return board ? okBoard(board, "Goal metric updated.") : fail("Metric not found.");
9978
+ }
9979
+ case "add_check": {
9980
+ if (!input.boardId || !input.taskId || !input.checkDescription) {
9981
+ return fail("add_check requires boardId, taskId, and checkDescription.");
9982
+ }
9983
+ const board = await addCheckToTask(projectRoot, input.boardId, input.taskId, {
9984
+ description: input.checkDescription,
9985
+ type: "manual",
9986
+ status: input.checkStatus
9987
+ });
9988
+ return board ? okBoard(board, "Check added.") : fail("Task not found.");
9989
+ }
9990
+ case "update_check": {
9991
+ if (!input.boardId || !input.taskId || !input.checkId) {
9992
+ return fail("update_check requires boardId, taskId, and checkId.");
9993
+ }
9994
+ const board = await updateCheckOnTask(
9995
+ projectRoot,
9996
+ input.boardId,
9997
+ input.taskId,
9998
+ input.checkId,
9999
+ {
10000
+ ...input.checkDescription !== void 0 ? { description: input.checkDescription } : {},
10001
+ ...input.checkStatus !== void 0 ? { status: input.checkStatus } : {}
10002
+ }
10003
+ );
10004
+ return board ? okBoard(board, "Check updated.") : fail("Check not found.");
10005
+ }
10006
+ case "add_note": {
10007
+ if (!input.boardId || !input.taskId || !input.note)
10008
+ return fail("add_note requires boardId, taskId, and note.");
10009
+ const board = await addNoteToTask(projectRoot, input.boardId, input.taskId, {
10010
+ author: input.author ?? "agent",
10011
+ content: input.note
10012
+ });
10013
+ return board ? okBoard(board, "Note added.") : fail("Task not found.");
10014
+ }
10015
+ case "add_link": {
10016
+ if (!input.boardId || !input.taskId || !input.url)
10017
+ return fail("add_link requires boardId, taskId, and url.");
10018
+ const board = await addLinkToTask(projectRoot, input.boardId, input.taskId, {
10019
+ url: input.url,
10020
+ type: input.linkType ?? "url",
10021
+ ...input.linkTitle !== void 0 ? { title: input.linkTitle } : {}
10022
+ });
10023
+ return board ? okBoard(board, "Link added.") : fail("Task not found.");
10024
+ }
10025
+ default:
10026
+ return fail(`Unknown kanban action: ${input.action}`);
9783
10027
  }
9784
- default:
9785
- return fail(`Unknown kanban action: ${input.action}`);
10028
+ } catch (err) {
10029
+ return fail(err instanceof Error ? err.message : String(err));
9786
10030
  }
9787
10031
  }
9788
10032
  };
@@ -9799,6 +10043,7 @@ async function requireBoard(projectRoot, boardId) {
9799
10043
  return boardId ? getBoard(projectRoot, boardId) : null;
9800
10044
  }
9801
10045
  function taskInput(input) {
10046
+ const assignment = hasAssignmentInput(input) ? assignmentForTaskCreate(input) : void 0;
9802
10047
  return {
9803
10048
  title: input.title ?? "",
9804
10049
  columnId: input.columnId,
@@ -9806,8 +10051,10 @@ function taskInput(input) {
9806
10051
  priority: input.priority,
9807
10052
  status: input.status,
9808
10053
  labels: input.labels,
9809
- assignedAgent: input.agentId,
9810
- ...input.agentId || input.provider || input.model ? { assignment: assignmentForTaskCreate(input) } : {}
10054
+ ...assignment?.agentId ?? assignment?.role ?? assignment?.name ? { assignedAgent: assignment.agentId ?? assignment.role ?? assignment.name } : {},
10055
+ ...input.assignee ?? assignment?.name ?? assignment?.agentId ? { assignee: input.assignee ?? assignment?.name ?? assignment?.agentId } : {},
10056
+ ...input.dependencyTaskId !== void 0 ? { dependsOn: [input.dependencyTaskId] } : {},
10057
+ ...assignment ? { assignment } : {}
9811
10058
  };
9812
10059
  }
9813
10060
  function taskPatch(input) {
@@ -9819,7 +10066,8 @@ function taskPatch(input) {
9819
10066
  priority: input.priority,
9820
10067
  status: input.status,
9821
10068
  labels: input.labels,
9822
- assignedAgent: input.agentId
10069
+ assignedAgent: input.agentId,
10070
+ ...input.dependencyTaskId !== void 0 ? { dependsOn: [input.dependencyTaskId] } : {}
9823
10071
  };
9824
10072
  }
9825
10073
  function assignmentInput(input) {
@@ -9836,6 +10084,9 @@ function assignmentInput(input) {
9836
10084
  assignee: input.assignee
9837
10085
  };
9838
10086
  }
10087
+ function hasAssignmentInput(input) {
10088
+ return input.agentId !== void 0 || input.name !== void 0 || input.role !== void 0 || input.provider !== void 0 || input.model !== void 0 || input.fallbackProfile !== void 0 || input.fallbackModels !== void 0 || input.tools !== void 0 || input.allowedCapabilities !== void 0 || input.assignee !== void 0 || input.assignmentStatus !== void 0;
10089
+ }
9839
10090
  function assignmentForTaskCreate(input) {
9840
10091
  return {
9841
10092
  status: input.assignmentStatus ?? "assigned",