@wrongstack/tools 0.285.0 → 0.287.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/README.md +21 -2
  2. package/dist/_edit-match.d.ts.map +1 -1
  3. package/dist/batch-tool-use.d.ts +1 -1
  4. package/dist/batch-tool-use.d.ts.map +1 -1
  5. package/dist/batch-tool-use.js +26 -8
  6. package/dist/batch-tool-use.js.map +2 -2
  7. package/dist/browser/artifacts.d.ts +13 -0
  8. package/dist/browser/artifacts.d.ts.map +1 -0
  9. package/dist/browser/index.d.ts +7 -0
  10. package/dist/browser/index.d.ts.map +1 -0
  11. package/dist/browser/index.js +1264 -0
  12. package/dist/browser/index.js.map +7 -0
  13. package/dist/browser/manager.d.ts +57 -0
  14. package/dist/browser/manager.d.ts.map +1 -0
  15. package/dist/browser/network-guard-proxy.d.ts +23 -0
  16. package/dist/browser/network-guard-proxy.d.ts.map +1 -0
  17. package/dist/browser/security.d.ts +29 -0
  18. package/dist/browser/security.d.ts.map +1 -0
  19. package/dist/browser/tools.d.ts +62 -0
  20. package/dist/browser/tools.d.ts.map +1 -0
  21. package/dist/browser/types.d.ts +60 -0
  22. package/dist/browser/types.d.ts.map +1 -0
  23. package/dist/builtin.d.ts +4 -3
  24. package/dist/builtin.d.ts.map +1 -1
  25. package/dist/builtin.js +2609 -525
  26. package/dist/builtin.js.map +4 -4
  27. package/dist/codebase-index/go-parser.d.ts.map +1 -1
  28. package/dist/codebase-index/index.js +190 -96
  29. package/dist/codebase-index/index.js.map +4 -4
  30. package/dist/codebase-index/py-parser.d.ts.map +1 -1
  31. package/dist/codebase-index/rs-parser.d.ts.map +1 -1
  32. package/dist/codebase-index/worker.js +188 -94
  33. package/dist/codebase-index/worker.js.map +4 -4
  34. package/dist/e2e.d.ts +56 -0
  35. package/dist/e2e.d.ts.map +1 -0
  36. package/dist/edit.d.ts.map +1 -1
  37. package/dist/edit.js +36 -12
  38. package/dist/edit.js.map +3 -3
  39. package/dist/exec.js +1 -1
  40. package/dist/exec.js.map +2 -2
  41. package/dist/index.d.ts +3 -0
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.js +2895 -511
  44. package/dist/index.js.map +4 -4
  45. package/dist/kanban.d.ts +7 -2
  46. package/dist/kanban.d.ts.map +1 -1
  47. package/dist/kanban.js +158 -19
  48. package/dist/kanban.js.map +4 -4
  49. package/dist/next-steps.d.ts +6 -2
  50. package/dist/next-steps.d.ts.map +1 -1
  51. package/dist/next-steps.js +3 -3
  52. package/dist/next-steps.js.map +2 -2
  53. package/dist/pack.js +2625 -525
  54. package/dist/pack.js.map +4 -4
  55. package/dist/plan.d.ts.map +1 -1
  56. package/dist/plan.js +154 -4
  57. package/dist/plan.js.map +4 -4
  58. package/dist/search.d.ts.map +1 -1
  59. package/dist/search.js +8 -2
  60. package/dist/search.js.map +2 -2
  61. package/dist/session-kanban.d.ts +38 -0
  62. package/dist/session-kanban.d.ts.map +1 -0
  63. package/dist/session-kanban.js +489 -0
  64. package/dist/session-kanban.js.map +7 -0
  65. package/dist/task.d.ts.map +1 -1
  66. package/dist/task.js +163 -4
  67. package/dist/task.js.map +4 -4
  68. package/dist/todo.d.ts.map +1 -1
  69. package/dist/todo.js +155 -7
  70. package/dist/todo.js.map +4 -4
  71. package/dist/tool-icon-map.d.ts +2 -1
  72. package/dist/tool-icon-map.d.ts.map +1 -1
  73. package/dist/tool-icons.d.ts.map +1 -1
  74. package/dist/tool-icons.js +7 -1
  75. package/dist/tool-icons.js.map +2 -2
  76. package/package.json +12 -3
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/kanban.ts"],
4
- "sourcesContent": ["// Kanban data model + manager moved from @wrongstack/core to the standalone\n// @wrongstack/kanban package; only the Tool contract and the task-graph\n// serialization types still come from core.\nimport type { SerializableTaskGraph, SerializedTaskGraph, Tool } from '@wrongstack/core';\nimport { deserializeTaskGraph, serializeTaskGraph } from '@wrongstack/core';\nimport type {\n AssignKanbanTaskInput,\n KanbanAgentAssignment,\n KanbanAgentRunStatus,\n KanbanBoard,\n KanbanBoardSummary,\n KanbanEvent,\n KanbanOrchestrationSnapshot,\n KanbanQueueHealth,\n KanbanSearchResult,\n KanbanTask,\n KanbanTaskPriority,\n KanbanTaskStatus,\n} from '@wrongstack/kanban';\nimport {\n addCheckToTask,\n addColumn,\n addDependency,\n addGoalMetricToTask,\n addLinkToTask,\n addNoteToTask,\n addTask,\n assignTask,\n claimReadyTask,\n copyTaskToBoard,\n createBoard,\n duplicateBoard,\n exportBoardAsMarkdown,\n exportBoardToTaskGraph,\n generateBoardFromDescription,\n getBoard,\n getKanbanOrchestrationSnapshot,\n getKanbanQueueHealth,\n getTask,\n getTaskChain,\n heartbeatTaskAssignment,\n listBoards,\n listKanbanEvents,\n listReadyTasks,\n mergeTasks,\n moveTask,\n parseLinesIntoTasks,\n recoverStaleTaskAssignments,\n releaseTaskClaim,\n removeBoard,\n removeColumn,\n removeTask,\n searchKanban,\n setTaskChain,\n splitTask,\n syncBoardFromTaskGraph,\n transferTaskToBoard,\n updateBoard,\n updateCheckOnTask,\n updateColumn,\n updateGoalMetricOnTask,\n updateTask,\n updateTaskAssignment,\n} from '@wrongstack/kanban';\n\ntype KanbanAction =\n | 'list_boards'\n | 'get_board'\n | 'create_board'\n | 'duplicate_board'\n | 'update_board'\n | 'delete_board'\n | 'generate_board'\n | 'export_markdown'\n | 'export_task_graph'\n | 'sync_task_graph'\n | 'search_tasks'\n | 'ready_tasks'\n | 'snapshot'\n | 'add_column'\n | 'update_column'\n | 'delete_column'\n | 'add_task'\n | 'split_task'\n | 'merge_tasks'\n | 'copy_task'\n | 'transfer_task'\n | 'get_task'\n | 'update_task'\n | 'move_task'\n | 'delete_task'\n | 'set_chain'\n | 'get_chain'\n | 'claim_task'\n | 'release_task'\n | 'assign_task'\n | 'mark_assignment'\n | 'heartbeat_assignment'\n | 'recover_stale'\n | 'events'\n | 'queue_health'\n | 'add_dependency'\n | 'add_goal_metric'\n | 'update_goal_metric'\n | 'add_check'\n | 'update_check'\n | 'add_note'\n | 'add_link';\n\ninterface KanbanToolInput extends Omit<AssignKanbanTaskInput, 'status'> {\n action: KanbanAction;\n boardId?: string | undefined;\n taskId?: string | undefined;\n columnId?: string | undefined;\n targetBoardId?: string | undefined;\n taskIds?: string[] | undefined;\n chainId?: string | undefined;\n title?: string | undefined;\n description?: string | undefined;\n tags?: string[] | undefined;\n labels?: string[] | undefined;\n priority?: KanbanTaskPriority | undefined;\n status?: KanbanTaskStatus | undefined;\n order?: number | undefined;\n targetColumnId?: string | undefined;\n moveTasksToColumnId?: string | undefined;\n query?: string | undefined;\n limit?: number | undefined;\n dependencyTaskId?: string | undefined;\n enforceDependencies?: boolean | undefined;\n childTitles?: string[] | undefined;\n inheritAssignment?: boolean | undefined;\n inheritLabels?: boolean | undefined;\n inheritSuccessCriteria?: boolean | undefined;\n inheritGoalMetrics?: boolean | undefined;\n inheritDependencies?: boolean | undefined;\n chainChildren?: boolean | undefined;\n rewireDependents?: boolean | undefined;\n closeSourceTasks?: boolean | undefined;\n metricId?: string | undefined;\n metricName?: string | undefined;\n metricTarget?: string | number | undefined;\n metricCurrent?: string | number | undefined;\n metricUnit?: string | undefined;\n metricStatus?: 'pending' | 'met' | 'missed' | 'waived' | undefined;\n metricNotes?: string | undefined;\n checkId?: string | undefined;\n checkDescription?: string | undefined;\n checkStatus?: 'pending' | 'passed' | 'failed' | 'skipped' | undefined;\n note?: string | undefined;\n author?: string | undefined;\n url?: string | undefined;\n linkTitle?: string | undefined;\n linkType?: 'issue' | 'pr' | 'doc' | 'commit' | 'design' | 'file' | 'url' | 'other' | undefined;\n context?: string | undefined;\n columns?: string[] | undefined;\n generatedBy?: string | undefined;\n includeTasks?: boolean | undefined;\n includeCompletedTasks?: boolean | undefined;\n preserveAssignment?: boolean | undefined;\n preserveDependencies?: boolean | undefined;\n leaseId?: string | undefined;\n claimedAt?: string | undefined;\n heartbeatAt?: string | undefined;\n leaseExpiresAt?: string | undefined;\n attempt?: number | undefined;\n maxAttempts?: number | undefined;\n costCeilingUsd?: number | undefined;\n retryPolicy?: 'off' | 'incremental' | 'exponential' | undefined;\n lastFailureKind?: string | undefined;\n subagentId?: string | undefined;\n runTaskId?: string | undefined;\n lastResult?: string | undefined;\n error?: string | undefined;\n assignmentStatus?: KanbanAgentRunStatus | undefined;\n releaseStatus?: 'pending' | 'ready' | 'blocked' | undefined;\n releaseReason?: string | undefined;\n clearAssignee?: boolean | undefined;\n recoveryMode?: 'auto' | 'release' | 'retry' | 'fail' | undefined;\n recoveryNow?: string | undefined;\n recoveryPolicyFailOnCostCeiling?: boolean | undefined;\n recoveryPolicyReleaseOnFailureKinds?: string[] | undefined;\n recoveryPolicyReleaseOnHeartbeatDue?: boolean | undefined;\n recoveryPolicyRetryPolicyOverride?: 'off' | 'incremental' | 'exponential' | undefined;\n taskGraph?: unknown;\n graphId?: string | undefined;\n specId?: string | undefined;\n sourceSystem?: string | undefined;\n phaseId?: string | undefined;\n preserveOriginTaskIds?: boolean | undefined;\n includeArchived?: boolean | undefined;\n archiveMissingTasks?: boolean | undefined;\n preserveManualDependencies?: boolean | undefined;\n}\n\ninterface KanbanToolOutput {\n ok: boolean;\n message: string;\n board?: KanbanBoard | undefined;\n boards?: KanbanBoardSummary[] | undefined;\n task?: KanbanTask | undefined;\n tasks?: KanbanSearchResult[] | undefined;\n recoveredTasks?: KanbanTask[] | undefined;\n events?: KanbanEvent[] | undefined;\n queueHealth?: KanbanQueueHealth | undefined;\n children?: KanbanTask[] | undefined;\n chain?: KanbanTask[] | undefined;\n snapshot?: KanbanOrchestrationSnapshot | undefined;\n taskGraph?: SerializedTaskGraph | undefined;\n markdown?: string | undefined;\n}\n\nexport const kanbanTool: Tool<KanbanToolInput, KanbanToolOutput> = {\n name: 'kanban',\n category: 'Project',\n description:\n '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.',\n usageHint:\n '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.',\n permission: 'confirm',\n mutating: true,\n capabilities: ['fs.write'],\n icon: 'task',\n timeoutMs: 5_000,\n inputSchema: {\n type: 'object',\n properties: {\n action: {\n type: 'string',\n enum: [\n 'list_boards',\n 'get_board',\n 'create_board',\n 'duplicate_board',\n 'update_board',\n 'delete_board',\n 'generate_board',\n 'export_markdown',\n 'export_task_graph',\n 'sync_task_graph',\n 'search_tasks',\n 'ready_tasks',\n 'snapshot',\n 'add_column',\n 'update_column',\n 'delete_column',\n 'add_task',\n 'split_task',\n 'merge_tasks',\n 'copy_task',\n 'transfer_task',\n 'get_task',\n 'update_task',\n 'move_task',\n 'delete_task',\n 'set_chain',\n 'get_chain',\n 'claim_task',\n 'release_task',\n 'assign_task',\n 'mark_assignment',\n 'heartbeat_assignment',\n 'recover_stale',\n 'events',\n 'queue_health',\n 'add_dependency',\n 'add_goal_metric',\n 'update_goal_metric',\n 'add_check',\n 'update_check',\n 'add_note',\n 'add_link',\n ],\n },\n boardId: { type: 'string' },\n taskId: { type: 'string' },\n taskIds: { type: 'array', items: { type: 'string' } },\n chainId: { type: 'string' },\n columnId: { type: 'string' },\n targetBoardId: { type: 'string' },\n targetColumnId: { type: 'string' },\n title: { type: 'string' },\n description: { type: 'string' },\n tags: { type: 'array', items: { type: 'string' } },\n labels: { type: 'array', items: { type: 'string' } },\n priority: { type: 'string', enum: ['critical', 'high', 'medium', 'low'] },\n status: {\n type: 'string',\n enum: [\n 'pending',\n 'ready',\n 'in_progress',\n 'blocked',\n 'review',\n 'completed',\n 'failed',\n 'archived',\n ],\n },\n order: { type: 'number' },\n query: { type: 'string' },\n limit: { type: 'number' },\n agentId: { type: 'string' },\n name: { type: 'string' },\n role: { type: 'string' },\n provider: { type: 'string' },\n model: { type: 'string' },\n fallbackProfile: { type: 'string' },\n fallbackModels: { type: 'array', items: { type: 'string' } },\n tools: { type: 'array', items: { type: 'string' } },\n allowedCapabilities: { type: 'array', items: { type: 'string' } },\n leaseId: { type: 'string' },\n claimedAt: { type: 'string' },\n heartbeatAt: { type: 'string' },\n leaseExpiresAt: { type: 'string' },\n attempt: { type: 'number' },\n maxAttempts: { type: 'number' },\n subagentId: { type: 'string' },\n runTaskId: { type: 'string' },\n lastResult: { type: 'string' },\n error: { type: 'string' },\n assignmentStatus: {\n type: 'string',\n enum: ['assigned', 'queued', 'running', 'completed', 'failed', 'cancelled'],\n },\n releaseStatus: { type: 'string', enum: ['pending', 'ready', 'blocked'] },\n releaseReason: { type: 'string' },\n clearAssignee: { type: 'boolean' },\n recoveryMode: { type: 'string', enum: ['release', 'retry', 'fail'] },\n recoveryNow: { type: 'string' },\n taskGraph: { type: 'object' },\n graphId: { type: 'string' },\n specId: { type: 'string' },\n sourceSystem: { type: 'string' },\n phaseId: { type: 'string' },\n preserveOriginTaskIds: { type: 'boolean' },\n includeArchived: { type: 'boolean' },\n archiveMissingTasks: { type: 'boolean' },\n preserveManualDependencies: { type: 'boolean' },\n dependencyTaskId: { type: 'string' },\n enforceDependencies: { type: 'boolean' },\n childTitles: { type: 'array', items: { type: 'string' } },\n inheritAssignment: { type: 'boolean' },\n inheritLabels: { type: 'boolean' },\n inheritSuccessCriteria: { type: 'boolean' },\n inheritGoalMetrics: { type: 'boolean' },\n inheritDependencies: { type: 'boolean' },\n chainChildren: { type: 'boolean' },\n rewireDependents: { type: 'boolean' },\n closeSourceTasks: { type: 'boolean' },\n metricId: { type: 'string' },\n metricName: { type: 'string' },\n metricTarget: { oneOf: [{ type: 'string' }, { type: 'number' }] },\n metricCurrent: { oneOf: [{ type: 'string' }, { type: 'number' }] },\n metricUnit: { type: 'string' },\n metricStatus: { type: 'string', enum: ['pending', 'met', 'missed', 'waived'] },\n metricNotes: { type: 'string' },\n checkId: { type: 'string' },\n checkDescription: { type: 'string' },\n checkStatus: { type: 'string', enum: ['pending', 'passed', 'failed', 'skipped'] },\n note: { type: 'string' },\n author: { type: 'string' },\n url: { type: 'string' },\n linkTitle: { type: 'string' },\n linkType: {\n type: 'string',\n enum: ['issue', 'pr', 'doc', 'commit', 'design', 'file', 'url', 'other'],\n },\n context: { type: 'string' },\n columns: { type: 'array', items: { type: 'string' } },\n generatedBy: { type: 'string' },\n includeTasks: { type: 'boolean' },\n includeCompletedTasks: { type: 'boolean' },\n preserveAssignment: { type: 'boolean' },\n preserveDependencies: { type: 'boolean' },\n moveTasksToColumnId: { type: 'string' },\n },\n required: ['action'],\n },\n async execute(input, ctx) {\n const projectRoot = ctx.projectRoot;\n if (!projectRoot) return fail('No project root is available.');\n\n try {\n switch (input.action) {\n case 'list_boards': {\n const boards = await listBoards(projectRoot);\n return { ok: true, message: `${boards.length} board(s).`, boards };\n }\n case 'get_board': {\n const board = await requireBoard(projectRoot, input.boardId);\n return board ? okBoard(board) : fail('Board not found.');\n }\n case 'create_board': {\n if (!input.title) return fail('create_board requires title.');\n const board = await createBoard(projectRoot, {\n title: input.title,\n ...(input.description !== undefined ? { description: input.description } : {}),\n ...(input.tags !== undefined ? { tags: input.tags } : {}),\n ...(input.generatedBy !== undefined ? { generatedBy: input.generatedBy } : {}),\n });\n return { ok: true, message: `Board created: ${board.title}`, board };\n }\n case 'update_board': {\n if (!input.boardId) return fail('update_board requires boardId.');\n const board = await updateBoard(projectRoot, input.boardId, {\n ...(input.title !== undefined ? { title: input.title } : {}),\n ...(input.description !== undefined ? { description: input.description } : {}),\n ...(input.tags !== undefined ? { tags: input.tags } : {}),\n });\n return board ? okBoard(board, 'Board updated.') : fail('Board not found.');\n }\n case 'duplicate_board': {\n if (!input.boardId) return fail('duplicate_board requires boardId.');\n const board = await duplicateBoard(projectRoot, input.boardId, {\n ...(input.title !== undefined ? { title: input.title } : {}),\n ...(input.generatedBy !== undefined ? { generatedBy: input.generatedBy } : {}),\n ...(input.includeTasks !== undefined ? { includeTasks: input.includeTasks } : {}),\n ...(input.includeCompletedTasks !== undefined\n ? { includeCompletedTasks: input.includeCompletedTasks }\n : {}),\n ...(input.preserveAssignment !== undefined\n ? { preserveAssignment: input.preserveAssignment }\n : {}),\n });\n return board ? okBoard(board, 'Board duplicated.') : fail('Board not found.');\n }\n case 'delete_board': {\n if (!input.boardId) return fail('delete_board requires boardId.');\n const removed = await removeBoard(projectRoot, input.boardId);\n return { ok: removed, message: removed ? 'Board deleted.' : 'Board not found.' };\n }\n case 'generate_board': {\n if (!input.description) return fail('generate_board requires description.');\n const boardInput = generateBoardFromDescription({\n description: input.description,\n ...(input.title !== undefined ? { title: input.title } : {}),\n ...(input.context !== undefined ? { context: input.context } : {}),\n ...(input.columns !== undefined ? { columns: input.columns } : {}),\n });\n const board = await createBoard(projectRoot, boardInput);\n for (const taskInput of parseLinesIntoTasks(\n input.description,\n board.columns[0]?.id ?? 'backlog',\n )) {\n await addTask(projectRoot, board.id, taskInput);\n }\n return okBoard((await getBoard(projectRoot, board.id)) ?? board, 'Board generated.');\n }\n case 'export_markdown': {\n const board = await requireBoard(projectRoot, input.boardId);\n if (!board) return fail('Board not found.');\n return {\n ok: true,\n message: 'Board exported.',\n board,\n markdown: exportBoardAsMarkdown(board),\n };\n }\n case 'export_task_graph': {\n if (!input.boardId) return fail('export_task_graph requires boardId.');\n const exported = await exportBoardToTaskGraph(projectRoot, input.boardId, {\n ...(input.graphId !== undefined ? { graphId: input.graphId } : {}),\n ...(input.specId !== undefined ? { specId: input.specId } : {}),\n ...(input.title !== undefined ? { title: input.title } : {}),\n ...(input.preserveOriginTaskIds !== undefined\n ? { preserveOriginTaskIds: input.preserveOriginTaskIds }\n : {}),\n ...(input.includeArchived !== undefined\n ? { includeArchived: input.includeArchived }\n : {}),\n });\n if (!exported) return fail('Board not found.');\n return {\n ok: true,\n message: `Task graph exported with ${exported.graph.nodes.size} node(s).`,\n board: exported.board,\n taskGraph: serializeTaskGraph(exported.graph),\n };\n }\n case 'sync_task_graph': {\n if (!input.boardId || !input.taskGraph) {\n return fail('sync_task_graph requires boardId and taskGraph.');\n }\n const graph = deserializeTaskGraph(input.taskGraph as SerializableTaskGraph);\n const result = await syncBoardFromTaskGraph(projectRoot, input.boardId, graph, {\n ...(input.title !== undefined ? { title: input.title } : {}),\n ...(input.description !== undefined ? { description: input.description } : {}),\n ...(input.tags !== undefined ? { tags: input.tags } : {}),\n ...(input.generatedBy !== undefined ? { generatedBy: input.generatedBy } : {}),\n ...(input.sourceSystem !== undefined ? { sourceSystem: input.sourceSystem } : {}),\n ...(input.phaseId !== undefined ? { phaseId: input.phaseId } : {}),\n ...(input.includeCompletedTasks !== undefined\n ? { includeCompletedTasks: input.includeCompletedTasks }\n : {}),\n ...(input.archiveMissingTasks !== undefined\n ? { archiveMissingTasks: input.archiveMissingTasks }\n : {}),\n ...(input.preserveManualDependencies !== undefined\n ? { preserveManualDependencies: input.preserveManualDependencies }\n : {}),\n });\n return result\n ? {\n ok: true,\n message: `Task graph synced: ${result.createdTaskIds.length} created, ${result.updatedTaskIds.length} updated, ${result.archivedTaskIds.length} archived.`,\n board: result.board,\n }\n : fail('Board not found.');\n }\n case 'search_tasks': {\n const tasks = await searchKanban(projectRoot, {\n query: input.query,\n boardId: input.boardId,\n assignedAgent: input.agentId,\n status: input.status,\n priority: input.priority,\n label: input.labels?.[0],\n chainId: input.chainId,\n });\n return { ok: true, message: `${tasks.length} task(s) matched.`, tasks };\n }\n case 'ready_tasks': {\n const tasks = await listReadyTasks(projectRoot, {\n query: input.query,\n boardId: input.boardId,\n assignedAgent: input.agentId,\n priority: input.priority,\n label: input.labels?.[0],\n chainId: input.chainId,\n limit: input.limit,\n });\n return { ok: true, message: `${tasks.length} ready task(s).`, tasks };\n }\n case 'snapshot': {\n const snapshot = await getKanbanOrchestrationSnapshot(projectRoot, {\n query: input.query,\n boardId: input.boardId,\n assignedAgent: input.agentId,\n status: input.status,\n priority: input.priority,\n label: input.labels?.[0],\n chainId: input.chainId,\n });\n return {\n ok: true,\n message: `${snapshot.ready.length} ready, ${snapshot.running.length} running, ${snapshot.blocked.length} blocked.`,\n snapshot,\n };\n }\n case 'add_column': {\n if (!input.boardId || !input.title) return fail('add_column requires boardId and title.');\n const result = await addColumn(projectRoot, input.boardId, {\n title: input.title,\n ...(input.description !== undefined ? { description: input.description } : {}),\n });\n return result ? okBoard(result.board, 'Column added.') : fail('Board not found.');\n }\n case 'update_column': {\n if (!input.boardId || !input.columnId)\n return fail('update_column requires boardId and columnId.');\n const board = await updateColumn(projectRoot, input.boardId, input.columnId, {\n ...(input.title !== undefined ? { title: input.title } : {}),\n ...(input.description !== undefined ? { description: input.description } : {}),\n ...(input.order !== undefined ? { order: input.order } : {}),\n });\n return board ? okBoard(board, 'Column updated.') : fail('Column not found.');\n }\n case 'delete_column': {\n if (!input.boardId || !input.columnId)\n return fail('delete_column requires boardId and columnId.');\n const board = await removeColumn(projectRoot, input.boardId, input.columnId, {\n moveTasksToColumnId: input.moveTasksToColumnId,\n });\n return board ? okBoard(board, 'Column deleted.') : fail('Column not found.');\n }\n case 'add_task': {\n if (!input.boardId || !input.title) return fail('add_task requires boardId and title.');\n const result = await addTask(projectRoot, input.boardId, taskInput(input));\n return result\n ? okTask(result.board, result.task, 'Task added.')\n : fail('Board not found.');\n }\n case 'split_task': {\n if (!input.boardId || !input.taskId || !input.childTitles?.length) {\n return fail('split_task requires boardId, taskId, and childTitles.');\n }\n const result = await splitTask(projectRoot, input.boardId, input.taskId, {\n titles: input.childTitles,\n ...(input.targetColumnId !== undefined ? { columnId: input.targetColumnId } : {}),\n ...(input.inheritAssignment !== undefined\n ? { inheritAssignment: input.inheritAssignment }\n : {}),\n ...(input.inheritLabels !== undefined ? { inheritLabels: input.inheritLabels } : {}),\n ...(input.inheritSuccessCriteria !== undefined\n ? { inheritSuccessCriteria: input.inheritSuccessCriteria }\n : {}),\n ...(input.inheritGoalMetrics !== undefined\n ? { inheritGoalMetrics: input.inheritGoalMetrics }\n : {}),\n ...(input.inheritDependencies !== undefined\n ? { inheritDependencies: input.inheritDependencies }\n : {}),\n ...(input.chainChildren !== undefined ? { chainChildren: input.chainChildren } : {}),\n ...(input.rewireDependents !== undefined\n ? { rewireDependents: input.rewireDependents }\n : {}),\n });\n return result\n ? {\n ok: true,\n message: `${result.children.length} child task(s) created.`,\n board: result.board,\n task: result.parent,\n children: result.children,\n }\n : fail('Task not found.');\n }\n case 'merge_tasks': {\n if (!input.boardId || !input.taskIds?.length || !input.title) {\n return fail('merge_tasks requires boardId, taskIds, and title.');\n }\n const result = await mergeTasks(projectRoot, input.boardId, {\n taskIds: input.taskIds,\n title: input.title,\n ...(input.description !== undefined ? { description: input.description } : {}),\n ...(input.targetColumnId !== undefined ? { targetColumnId: input.targetColumnId } : {}),\n ...(input.preserveAssignment !== undefined\n ? { preserveAssignment: input.preserveAssignment }\n : {}),\n ...(input.closeSourceTasks !== undefined\n ? { closeSourceTasks: input.closeSourceTasks }\n : {}),\n });\n return result\n ? okTask(result.board, result.task, 'Tasks merged.')\n : fail('Board or task not found.');\n }\n case 'copy_task': {\n if (!input.boardId || !input.taskId || !input.targetBoardId) {\n return fail('copy_task requires boardId, taskId, and targetBoardId.');\n }\n const result = await copyTaskToBoard(\n projectRoot,\n input.boardId,\n input.taskId,\n input.targetBoardId,\n {\n ...(input.targetColumnId !== undefined\n ? { targetColumnId: input.targetColumnId }\n : {}),\n ...(input.order !== undefined ? { targetOrder: input.order } : {}),\n ...(input.preserveAssignment !== undefined\n ? { preserveAssignment: input.preserveAssignment }\n : {}),\n ...(input.preserveDependencies !== undefined\n ? { preserveDependencies: input.preserveDependencies }\n : {}),\n },\n );\n return result\n ? okTask(result.targetBoard, result.task, 'Task copied to target board.')\n : fail('Board or task not found.');\n }\n case 'transfer_task': {\n if (!input.boardId || !input.taskId || !input.targetBoardId) {\n return fail('transfer_task requires boardId, taskId, and targetBoardId.');\n }\n const result = await transferTaskToBoard(\n projectRoot,\n input.boardId,\n input.taskId,\n input.targetBoardId,\n {\n ...(input.targetColumnId !== undefined\n ? { targetColumnId: input.targetColumnId }\n : {}),\n ...(input.order !== undefined ? { targetOrder: input.order } : {}),\n ...(input.preserveAssignment !== undefined\n ? { preserveAssignment: input.preserveAssignment }\n : {}),\n ...(input.preserveDependencies !== undefined\n ? { preserveDependencies: input.preserveDependencies }\n : {}),\n },\n );\n return result\n ? okTask(result.targetBoard, result.task, 'Task transferred to target board.')\n : fail('Board or task not found.');\n }\n case 'get_task': {\n if (!input.boardId || !input.taskId) return fail('get_task requires boardId and taskId.');\n const task = await getTask(projectRoot, input.boardId, input.taskId);\n return task ? { ok: true, message: 'Task loaded.', task } : fail('Task not found.');\n }\n case 'update_task': {\n if (!input.boardId || !input.taskId)\n return fail('update_task requires boardId and taskId.');\n const board = await updateTask(\n projectRoot,\n input.boardId,\n input.taskId,\n taskPatch(input),\n );\n return board ? okBoard(board, 'Task updated.') : fail('Task not found.');\n }\n case 'move_task': {\n if (!input.boardId || !input.taskId || !input.targetColumnId) {\n return fail('move_task requires boardId, taskId, and targetColumnId.');\n }\n const board = await moveTask(\n projectRoot,\n input.boardId,\n input.taskId,\n input.targetColumnId,\n input.order,\n );\n return board ? okBoard(board, 'Task moved.') : fail('Move failed.');\n }\n case 'delete_task': {\n if (!input.boardId || !input.taskId)\n return fail('delete_task requires boardId and taskId.');\n const board = await removeTask(projectRoot, input.boardId, input.taskId);\n return board ? okBoard(board, 'Task deleted.') : fail('Task not found.');\n }\n case 'set_chain': {\n if (!input.boardId || !input.taskIds?.length) {\n return fail('set_chain requires boardId and taskIds.');\n }\n const result = await setTaskChain(projectRoot, input.boardId, {\n taskIds: input.taskIds,\n ...(input.chainId !== undefined ? { chainId: input.chainId } : {}),\n ...(input.enforceDependencies !== undefined\n ? { enforceDependencies: input.enforceDependencies }\n : {}),\n });\n return result\n ? {\n ok: true,\n message: `Chain set: ${result.chainId}`,\n board: result.board,\n chain: result.tasks,\n }\n : fail('Board or task not found.');\n }\n case 'get_chain': {\n if (!input.boardId || !(input.taskId || input.chainId)) {\n return fail('get_chain requires boardId and taskId or chainId.');\n }\n const result = await getTaskChain(\n projectRoot,\n input.boardId,\n input.taskId ?? input.chainId ?? '',\n );\n return result\n ? {\n ok: true,\n message: `Chain loaded: ${result.chainId}`,\n board: result.board,\n chain: result.tasks,\n }\n : fail('Chain not found.');\n }\n case 'claim_task': {\n const result = await claimReadyTask(projectRoot, {\n ...(input.boardId !== undefined ? { boardId: input.boardId } : {}),\n ...(input.taskId !== undefined ? { taskId: input.taskId } : {}),\n ...assignmentInput(input),\n status: input.assignmentStatus ?? 'queued',\n });\n return result\n ? okTask(result.board, result.task, 'Task claimed.')\n : fail('No ready kanban task matched the claim.');\n }\n case 'release_task': {\n if (!input.boardId || !input.taskId) {\n return fail('release_task requires boardId and taskId.');\n }\n const board = await releaseTaskClaim(projectRoot, input.boardId, input.taskId, {\n ...(input.releaseStatus !== undefined ? { status: input.releaseStatus } : {}),\n ...(input.releaseReason !== undefined ? { reason: input.releaseReason } : {}),\n ...(input.clearAssignee !== undefined ? { clearAssignee: input.clearAssignee } : {}),\n });\n return board ? okBoard(board, 'Task claim released.') : fail('Task not found.');\n }\n case 'assign_task': {\n if (!input.boardId || !input.taskId)\n return fail('assign_task requires boardId and taskId.');\n const board = await assignTask(\n projectRoot,\n input.boardId,\n input.taskId,\n assignmentInput(input),\n );\n return board ? okBoard(board, 'Task assigned.') : fail('Task not found.');\n }\n case 'mark_assignment': {\n if (!input.boardId || !input.taskId)\n return fail('mark_assignment requires boardId and taskId.');\n const assignmentStatus =\n input.assignmentStatus ??\n (input.status === 'completed' ? 'completed' : input.error ? 'failed' : undefined);\n const board = await updateTaskAssignment(projectRoot, input.boardId, input.taskId, {\n ...(assignmentStatus !== undefined ? { status: assignmentStatus } : {}),\n ...(input.subagentId !== undefined ? { subagentId: input.subagentId } : {}),\n ...(input.runTaskId !== undefined ? { runTaskId: input.runTaskId } : {}),\n ...(input.lastResult !== undefined ? { lastResult: input.lastResult } : {}),\n ...(input.error !== undefined ? { error: input.error } : {}),\n ...(input.agentId !== undefined ? { agentId: input.agentId } : {}),\n ...(input.leaseId !== undefined ? { leaseId: input.leaseId } : {}),\n ...(input.claimedAt !== undefined ? { claimedAt: input.claimedAt } : {}),\n ...(input.heartbeatAt !== undefined ? { heartbeatAt: input.heartbeatAt } : {}),\n ...(input.leaseExpiresAt !== undefined ? { leaseExpiresAt: input.leaseExpiresAt } : {}),\n ...(input.attempt !== undefined ? { attempt: input.attempt } : {}),\n ...(input.maxAttempts !== undefined ? { maxAttempts: input.maxAttempts } : {}),\n });\n return board ? okBoard(board, 'Assignment updated.') : fail('Task not found.');\n }\n case 'heartbeat_assignment': {\n if (!input.boardId || !input.taskId) {\n return fail('heartbeat_assignment requires boardId and taskId.');\n }\n const board = await heartbeatTaskAssignment(projectRoot, input.boardId, input.taskId, {\n ...(input.heartbeatAt !== undefined ? { heartbeatAt: input.heartbeatAt } : {}),\n ...(input.leaseExpiresAt !== undefined ? { leaseExpiresAt: input.leaseExpiresAt } : {}),\n });\n return board\n ? okBoard(board, 'Assignment heartbeat updated.')\n : fail('Task assignment not found.');\n }\n case 'recover_stale': {\n if (!input.boardId) return fail('recover_stale requires boardId.');\n const policyFields = [\n input.recoveryPolicyFailOnCostCeiling !== undefined,\n input.recoveryPolicyReleaseOnFailureKinds !== undefined,\n input.recoveryPolicyReleaseOnHeartbeatDue !== undefined,\n input.recoveryPolicyRetryPolicyOverride !== undefined,\n ].some(Boolean);\n const result = await recoverStaleTaskAssignments(projectRoot, input.boardId, {\n ...(input.recoveryMode !== undefined ? { mode: input.recoveryMode } : {}),\n ...(input.recoveryNow !== undefined ? { now: input.recoveryNow } : {}),\n ...(input.releaseReason !== undefined ? { reason: input.releaseReason } : {}),\n ...(input.clearAssignee !== undefined ? { clearAssignee: input.clearAssignee } : {}),\n ...(policyFields\n ? {\n policy: {\n ...(input.recoveryPolicyFailOnCostCeiling !== undefined\n ? { failWhenCostCeilingSet: input.recoveryPolicyFailOnCostCeiling }\n : {}),\n ...(input.recoveryPolicyReleaseOnFailureKinds !== undefined\n ? {\n releaseOnFailureKinds: input.recoveryPolicyReleaseOnFailureKinds,\n }\n : {}),\n ...(input.recoveryPolicyReleaseOnHeartbeatDue !== undefined\n ? {\n releaseOnHeartbeatDue: input.recoveryPolicyReleaseOnHeartbeatDue,\n }\n : {}),\n ...(input.recoveryPolicyRetryPolicyOverride !== undefined\n ? {\n retryPolicyOverride: input.recoveryPolicyRetryPolicyOverride,\n }\n : {}),\n },\n }\n : {}),\n });\n return result\n ? {\n ok: true,\n message: `Recovered ${result.tasks.length} stale assignment(s).`,\n board: result.board,\n recoveredTasks: result.tasks,\n }\n : { ok: true, message: 'No stale assignment matched.', recoveredTasks: [] };\n }\n case 'events': {\n if (!input.boardId) return fail('events requires boardId.');\n const eventList = await listKanbanEvents(projectRoot, input.boardId);\n return {\n ok: true,\n message: `${eventList.length} event(s).`,\n events: eventList,\n };\n }\n case 'queue_health': {\n const health = await getKanbanQueueHealth(projectRoot, {\n ...(input.boardId !== undefined ? { boardId: input.boardId } : {}),\n });\n return {\n ok: true,\n message: `Counts: ready=${health.counts.ready}, running=${health.counts.running}, stale=${health.staleAssignments.count}.`,\n queueHealth: health,\n };\n }\n case 'add_dependency': {\n if (!input.boardId || !input.taskId || !input.dependencyTaskId) {\n return fail('add_dependency requires boardId, taskId, and dependencyTaskId.');\n }\n const board = await addDependency(\n projectRoot,\n input.boardId,\n input.taskId,\n input.dependencyTaskId,\n );\n return board ? okBoard(board, 'Dependency added.') : fail('Task not found.');\n }\n case 'add_goal_metric': {\n if (!input.boardId || !input.taskId || !input.metricName) {\n return fail('add_goal_metric requires boardId, taskId, and metricName.');\n }\n const board = await addGoalMetricToTask(projectRoot, input.boardId, input.taskId, {\n name: input.metricName,\n ...(input.metricStatus !== undefined ? { status: input.metricStatus } : {}),\n ...(input.metricTarget !== undefined ? { target: input.metricTarget } : {}),\n ...(input.metricCurrent !== undefined ? { current: input.metricCurrent } : {}),\n ...(input.metricUnit !== undefined ? { unit: input.metricUnit } : {}),\n ...(input.metricNotes !== undefined ? { notes: input.metricNotes } : {}),\n });\n return board ? okBoard(board, 'Goal metric added.') : fail('Task not found.');\n }\n case 'update_goal_metric': {\n if (!input.boardId || !input.taskId || !input.metricId) {\n return fail('update_goal_metric requires boardId, taskId, and metricId.');\n }\n const board = await updateGoalMetricOnTask(\n projectRoot,\n input.boardId,\n input.taskId,\n input.metricId,\n {\n ...(input.metricName !== undefined ? { name: input.metricName } : {}),\n ...(input.metricStatus !== undefined ? { status: input.metricStatus } : {}),\n ...(input.metricTarget !== undefined ? { target: input.metricTarget } : {}),\n ...(input.metricCurrent !== undefined ? { current: input.metricCurrent } : {}),\n ...(input.metricUnit !== undefined ? { unit: input.metricUnit } : {}),\n ...(input.metricNotes !== undefined ? { notes: input.metricNotes } : {}),\n },\n );\n return board ? okBoard(board, 'Goal metric updated.') : fail('Metric not found.');\n }\n case 'add_check': {\n if (!input.boardId || !input.taskId || !input.checkDescription) {\n return fail('add_check requires boardId, taskId, and checkDescription.');\n }\n const board = await addCheckToTask(projectRoot, input.boardId, input.taskId, {\n description: input.checkDescription,\n type: 'manual',\n status: input.checkStatus,\n });\n return board ? okBoard(board, 'Check added.') : fail('Task not found.');\n }\n case 'update_check': {\n if (!input.boardId || !input.taskId || !input.checkId) {\n return fail('update_check requires boardId, taskId, and checkId.');\n }\n const board = await updateCheckOnTask(\n projectRoot,\n input.boardId,\n input.taskId,\n input.checkId,\n {\n ...(input.checkDescription !== undefined\n ? { description: input.checkDescription }\n : {}),\n ...(input.checkStatus !== undefined ? { status: input.checkStatus } : {}),\n },\n );\n return board ? okBoard(board, 'Check updated.') : fail('Check not found.');\n }\n case 'add_note': {\n if (!input.boardId || !input.taskId || !input.note)\n return fail('add_note requires boardId, taskId, and note.');\n const board = await addNoteToTask(projectRoot, input.boardId, input.taskId, {\n author: input.author ?? 'agent',\n content: input.note,\n });\n return board ? okBoard(board, 'Note added.') : fail('Task not found.');\n }\n case 'add_link': {\n if (!input.boardId || !input.taskId || !input.url)\n return fail('add_link requires boardId, taskId, and url.');\n const board = await addLinkToTask(projectRoot, input.boardId, input.taskId, {\n url: input.url,\n type: input.linkType ?? 'url',\n ...(input.linkTitle !== undefined ? { title: input.linkTitle } : {}),\n });\n return board ? okBoard(board, 'Link added.') : fail('Task not found.');\n }\n default:\n return fail(`Unknown kanban action: ${(input as { action: string }).action}`);\n }\n } catch (err) {\n return fail(err instanceof Error ? err.message : String(err));\n }\n },\n};\n\nfunction fail(message: string): KanbanToolOutput {\n return { ok: false, message };\n}\n\nfunction okBoard(board: KanbanBoard, message = 'Board loaded.'): KanbanToolOutput {\n return { ok: true, message, board };\n}\n\nfunction okTask(board: KanbanBoard, task: KanbanTask, message: string): KanbanToolOutput {\n return { ok: true, message, board, task };\n}\n\nasync function requireBoard(\n projectRoot: string,\n boardId: string | undefined,\n): Promise<KanbanBoard | null> {\n return boardId ? getBoard(projectRoot, boardId) : null;\n}\n\nfunction taskInput(input: KanbanToolInput) {\n const assignment = hasAssignmentInput(input) ? assignmentForTaskCreate(input) : undefined;\n return {\n title: input.title ?? '',\n columnId: input.columnId,\n description: input.description,\n priority: input.priority,\n status: input.status,\n labels: input.labels,\n ...((assignment?.agentId ?? assignment?.role ?? assignment?.name)\n ? { assignedAgent: assignment.agentId ?? assignment.role ?? assignment.name }\n : {}),\n ...((input.assignee ?? assignment?.name ?? assignment?.agentId)\n ? { assignee: input.assignee ?? assignment?.name ?? assignment?.agentId }\n : {}),\n ...(input.dependencyTaskId !== undefined ? { dependsOn: [input.dependencyTaskId] } : {}),\n ...(assignment ? { assignment } : {}),\n };\n}\n\nfunction taskPatch(input: KanbanToolInput) {\n return {\n title: input.title,\n description: input.description,\n columnId: input.columnId,\n order: input.order,\n priority: input.priority,\n status: input.status,\n labels: input.labels,\n assignedAgent: input.agentId,\n ...(input.dependencyTaskId !== undefined ? { dependsOn: [input.dependencyTaskId] } : {}),\n };\n}\n\nfunction assignmentInput(input: KanbanToolInput): AssignKanbanTaskInput {\n return {\n agentId: input.agentId,\n name: input.name,\n role: input.role,\n provider: input.provider,\n model: input.model,\n fallbackProfile: input.fallbackProfile,\n fallbackModels: input.fallbackModels,\n tools: input.tools,\n allowedCapabilities: input.allowedCapabilities,\n assignee: input.assignee,\n leaseId: input.leaseId,\n claimedAt: input.claimedAt,\n heartbeatAt: input.heartbeatAt,\n leaseExpiresAt: input.leaseExpiresAt,\n attempt: input.attempt,\n maxAttempts: input.maxAttempts,\n costCeilingUsd: input.costCeilingUsd,\n retryPolicy: input.retryPolicy,\n lastFailureKind: input.lastFailureKind,\n };\n}\n\nfunction hasAssignmentInput(input: KanbanToolInput): boolean {\n return (\n input.agentId !== undefined ||\n input.name !== undefined ||\n input.role !== undefined ||\n input.provider !== undefined ||\n input.model !== undefined ||\n input.fallbackProfile !== undefined ||\n input.fallbackModels !== undefined ||\n input.tools !== undefined ||\n input.allowedCapabilities !== undefined ||\n input.assignee !== undefined ||\n input.leaseId !== undefined ||\n input.claimedAt !== undefined ||\n input.heartbeatAt !== undefined ||\n input.leaseExpiresAt !== undefined ||\n input.attempt !== undefined ||\n input.maxAttempts !== undefined ||\n input.costCeilingUsd !== undefined ||\n input.retryPolicy !== undefined ||\n input.lastFailureKind !== undefined ||\n input.assignmentStatus !== undefined\n );\n}\n\nfunction assignmentForTaskCreate(input: KanbanToolInput): KanbanAgentAssignment {\n return {\n status: input.assignmentStatus ?? 'assigned',\n ...(input.agentId !== undefined ? { agentId: input.agentId } : {}),\n ...(input.name !== undefined ? { name: input.name } : {}),\n ...(input.role !== undefined ? { role: input.role } : {}),\n ...(input.provider !== undefined ? { provider: input.provider } : {}),\n ...(input.model !== undefined ? { model: input.model } : {}),\n ...(input.fallbackProfile !== undefined ? { fallbackProfile: input.fallbackProfile } : {}),\n ...(input.fallbackModels !== undefined ? { fallbackModels: input.fallbackModels } : {}),\n ...(input.tools !== undefined ? { tools: input.tools } : {}),\n ...(input.allowedCapabilities !== undefined\n ? { allowedCapabilities: input.allowedCapabilities }\n : {}),\n ...(input.leaseId !== undefined ? { leaseId: input.leaseId } : {}),\n ...(input.claimedAt !== undefined ? { claimedAt: input.claimedAt } : {}),\n ...(input.heartbeatAt !== undefined ? { heartbeatAt: input.heartbeatAt } : {}),\n ...(input.leaseExpiresAt !== undefined ? { leaseExpiresAt: input.leaseExpiresAt } : {}),\n ...(input.attempt !== undefined ? { attempt: input.attempt } : {}),\n ...(input.maxAttempts !== undefined ? { maxAttempts: input.maxAttempts } : {}),\n ...(input.costCeilingUsd !== undefined ? { costCeilingUsd: input.costCeilingUsd } : {}),\n ...(input.retryPolicy !== undefined ? { retryPolicy: input.retryPolicy } : {}),\n ...(input.lastFailureKind !== undefined ? { lastFailureKind: input.lastFailureKind } : {}),\n };\n}\n"],
5
- "mappings": "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",
6
- "names": ["taskInput"]
3
+ "sources": ["../src/kanban.ts", "../src/session-kanban.ts"],
4
+ "sourcesContent": ["// Kanban data model + manager moved from @wrongstack/core to the standalone\n// @wrongstack/kanban package; only the Tool contract and the task-graph\n// serialization types still come from core.\nimport type { SerializableTaskGraph, SerializedTaskGraph, Tool } from '@wrongstack/core';\nimport { deserializeTaskGraph, loadTasks, serializeTaskGraph } from '@wrongstack/core';\nimport type {\n AssignKanbanTaskInput,\n KanbanAgentAssignment,\n KanbanAgentRunStatus,\n KanbanBoard,\n KanbanBoardSummary,\n KanbanEvent,\n KanbanOrchestrationSnapshot,\n KanbanQueueHealth,\n KanbanSearchResult,\n KanbanTask,\n KanbanTaskPriority,\n KanbanTaskStatus,\n KanbanTaskType,\n} from '@wrongstack/kanban';\nimport {\n addCheckToTask,\n addColumn,\n addDependency,\n addGoalMetricToTask,\n addLinkToTask,\n addNoteToTask,\n addTask,\n assignTask,\n claimReadyTask,\n copyTaskToBoard,\n createBoard,\n createBoardFromTaskGraph,\n duplicateBoard,\n exportBoardAsMarkdown,\n exportBoardToTaskGraph,\n generateBoardFromDescription,\n getBoard,\n getKanbanOrchestrationSnapshot,\n getKanbanQueueHealth,\n getTask,\n getTaskChain,\n heartbeatTaskAssignment,\n listBoards,\n listKanbanEvents,\n listReadyTasks,\n mergeTasks,\n moveTask,\n parseLinesIntoTasks,\n recoverStaleTaskAssignments,\n releaseTaskClaim,\n removeBoard,\n removeColumn,\n removeTask,\n searchKanban,\n setTaskChain,\n splitTask,\n syncBoardFromTaskGraph,\n transferTaskToBoard,\n updateBoard,\n updateCheckOnTask,\n updateColumn,\n updateGoalMetricOnTask,\n updateTask,\n updateTaskAssignment,\n} from '@wrongstack/kanban';\nimport { taskFileToSerializedGraph } from './session-kanban.js';\n\ntype KanbanAction =\n | 'list_boards'\n | 'get_board'\n | 'create_board'\n | 'duplicate_board'\n | 'update_board'\n | 'delete_board'\n | 'generate_board'\n | 'export_markdown'\n | 'export_task_graph'\n | 'sync_task_graph'\n | 'create_from_graph'\n | 'import_session_tasks'\n | 'search_tasks'\n | 'ready_tasks'\n | 'snapshot'\n | 'add_column'\n | 'update_column'\n | 'delete_column'\n | 'add_task'\n | 'split_task'\n | 'merge_tasks'\n | 'copy_task'\n | 'transfer_task'\n | 'get_task'\n | 'update_task'\n | 'move_task'\n | 'delete_task'\n | 'set_chain'\n | 'get_chain'\n | 'claim_task'\n | 'release_task'\n | 'assign_task'\n | 'mark_assignment'\n | 'heartbeat_assignment'\n | 'recover_stale'\n | 'events'\n | 'queue_health'\n | 'add_dependency'\n | 'add_goal_metric'\n | 'update_goal_metric'\n | 'add_check'\n | 'update_check'\n | 'add_note'\n | 'add_link';\n\ninterface KanbanToolInput extends Omit<AssignKanbanTaskInput, 'status'> {\n action: KanbanAction;\n boardId?: string | undefined;\n taskId?: string | undefined;\n columnId?: string | undefined;\n targetBoardId?: string | undefined;\n taskIds?: string[] | undefined;\n chainId?: string | undefined;\n title?: string | undefined;\n description?: string | undefined;\n tags?: string[] | undefined;\n labels?: string[] | undefined;\n priority?: KanbanTaskPriority | undefined;\n taskType?: KanbanTaskType | undefined;\n status?: KanbanTaskStatus | undefined;\n order?: number | undefined;\n targetColumnId?: string | undefined;\n moveTasksToColumnId?: string | undefined;\n query?: string | undefined;\n limit?: number | undefined;\n dependencyTaskId?: string | undefined;\n enforceDependencies?: boolean | undefined;\n childTitles?: string[] | undefined;\n inheritAssignment?: boolean | undefined;\n inheritLabels?: boolean | undefined;\n inheritSuccessCriteria?: boolean | undefined;\n inheritGoalMetrics?: boolean | undefined;\n inheritDependencies?: boolean | undefined;\n chainChildren?: boolean | undefined;\n rewireDependents?: boolean | undefined;\n closeSourceTasks?: boolean | undefined;\n metricId?: string | undefined;\n metricName?: string | undefined;\n metricTarget?: string | number | undefined;\n metricCurrent?: string | number | undefined;\n metricUnit?: string | undefined;\n metricStatus?: 'pending' | 'met' | 'missed' | 'waived' | undefined;\n metricNotes?: string | undefined;\n checkId?: string | undefined;\n checkDescription?: string | undefined;\n checkStatus?: 'pending' | 'passed' | 'failed' | 'skipped' | undefined;\n note?: string | undefined;\n author?: string | undefined;\n url?: string | undefined;\n linkTitle?: string | undefined;\n linkType?: 'issue' | 'pr' | 'doc' | 'commit' | 'design' | 'file' | 'url' | 'other' | undefined;\n context?: string | undefined;\n columns?: string[] | undefined;\n generatedBy?: string | undefined;\n includeTasks?: boolean | undefined;\n includeCompletedTasks?: boolean | undefined;\n preserveAssignment?: boolean | undefined;\n preserveDependencies?: boolean | undefined;\n leaseId?: string | undefined;\n claimedAt?: string | undefined;\n heartbeatAt?: string | undefined;\n leaseExpiresAt?: string | undefined;\n attempt?: number | undefined;\n maxAttempts?: number | undefined;\n costCeilingUsd?: number | undefined;\n retryPolicy?: 'off' | 'incremental' | 'exponential' | undefined;\n lastFailureKind?: string | undefined;\n subagentId?: string | undefined;\n runTaskId?: string | undefined;\n lastResult?: string | undefined;\n error?: string | undefined;\n assignmentStatus?: KanbanAgentRunStatus | undefined;\n releaseStatus?: 'pending' | 'ready' | 'blocked' | undefined;\n releaseReason?: string | undefined;\n clearAssignee?: boolean | undefined;\n recoveryMode?: 'auto' | 'release' | 'retry' | 'fail' | undefined;\n recoveryNow?: string | undefined;\n recoveryPolicyFailOnCostCeiling?: boolean | undefined;\n recoveryPolicyReleaseOnFailureKinds?: string[] | undefined;\n recoveryPolicyReleaseOnHeartbeatDue?: boolean | undefined;\n recoveryPolicyRetryPolicyOverride?: 'off' | 'incremental' | 'exponential' | undefined;\n taskGraph?: unknown;\n graphId?: string | undefined;\n specId?: string | undefined;\n sourceSystem?: string | undefined;\n phaseId?: string | undefined;\n preserveOriginTaskIds?: boolean | undefined;\n includeArchived?: boolean | undefined;\n archiveMissingTasks?: boolean | undefined;\n preserveManualDependencies?: boolean | undefined;\n /** Full dependency id list for add_task/update_task (superset of dependencyTaskId). */\n dependsOn?: string[] | undefined;\n /** Estimated effort in hours for add_task/update_task. */\n estimatedHours?: number | undefined;\n}\n\ninterface KanbanToolOutput {\n ok: boolean;\n message: string;\n board?: KanbanBoard | undefined;\n boards?: KanbanBoardSummary[] | undefined;\n task?: KanbanTask | undefined;\n tasks?: KanbanSearchResult[] | undefined;\n recoveredTasks?: KanbanTask[] | undefined;\n events?: KanbanEvent[] | undefined;\n queueHealth?: KanbanQueueHealth | undefined;\n children?: KanbanTask[] | undefined;\n chain?: KanbanTask[] | undefined;\n snapshot?: KanbanOrchestrationSnapshot | undefined;\n taskGraph?: SerializedTaskGraph | undefined;\n markdown?: string | undefined;\n}\n\nexport const kanbanTool: Tool<KanbanToolInput, KanbanToolOutput> = {\n name: 'kanban',\n category: 'Project',\n description:\n '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.',\n usageHint:\n '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.',\n permission: 'confirm',\n mutating: true,\n capabilities: ['fs.write'],\n icon: 'task',\n timeoutMs: 5_000,\n inputSchema: {\n type: 'object',\n properties: {\n action: {\n type: 'string',\n enum: [\n 'list_boards',\n 'get_board',\n 'create_board',\n 'duplicate_board',\n 'update_board',\n 'delete_board',\n 'generate_board',\n 'export_markdown',\n 'export_task_graph',\n 'sync_task_graph',\n 'create_from_graph',\n 'import_session_tasks',\n 'search_tasks',\n 'ready_tasks',\n 'snapshot',\n 'add_column',\n 'update_column',\n 'delete_column',\n 'add_task',\n 'split_task',\n 'merge_tasks',\n 'copy_task',\n 'transfer_task',\n 'get_task',\n 'update_task',\n 'move_task',\n 'delete_task',\n 'set_chain',\n 'get_chain',\n 'claim_task',\n 'release_task',\n 'assign_task',\n 'mark_assignment',\n 'heartbeat_assignment',\n 'recover_stale',\n 'events',\n 'queue_health',\n 'add_dependency',\n 'add_goal_metric',\n 'update_goal_metric',\n 'add_check',\n 'update_check',\n 'add_note',\n 'add_link',\n ],\n },\n boardId: { type: 'string' },\n taskId: { type: 'string' },\n taskIds: { type: 'array', items: { type: 'string' } },\n chainId: { type: 'string' },\n columnId: { type: 'string' },\n targetBoardId: { type: 'string' },\n targetColumnId: { type: 'string' },\n title: { type: 'string' },\n description: { type: 'string' },\n tags: { type: 'array', items: { type: 'string' } },\n labels: { type: 'array', items: { type: 'string' } },\n priority: { type: 'string', enum: ['critical', 'high', 'medium', 'low'] },\n taskType: {\n type: 'string',\n enum: ['feature', 'bugfix', 'refactor', 'docs', 'test', 'chore'],\n },\n status: {\n type: 'string',\n enum: [\n 'pending',\n 'ready',\n 'in_progress',\n 'blocked',\n 'review',\n 'completed',\n 'failed',\n 'archived',\n ],\n },\n order: { type: 'number' },\n query: { type: 'string' },\n limit: { type: 'number' },\n agentId: { type: 'string' },\n name: { type: 'string' },\n role: { type: 'string' },\n provider: { type: 'string' },\n model: { type: 'string' },\n fallbackProfile: { type: 'string' },\n fallbackModels: { type: 'array', items: { type: 'string' } },\n tools: { type: 'array', items: { type: 'string' } },\n allowedCapabilities: { type: 'array', items: { type: 'string' } },\n leaseId: { type: 'string' },\n claimedAt: { type: 'string' },\n heartbeatAt: { type: 'string' },\n leaseExpiresAt: { type: 'string' },\n attempt: { type: 'number' },\n maxAttempts: { type: 'number' },\n subagentId: { type: 'string' },\n runTaskId: { type: 'string' },\n lastResult: { type: 'string' },\n error: { type: 'string' },\n assignmentStatus: {\n type: 'string',\n enum: ['assigned', 'queued', 'running', 'completed', 'failed', 'cancelled'],\n },\n releaseStatus: { type: 'string', enum: ['pending', 'ready', 'blocked'] },\n releaseReason: { type: 'string' },\n clearAssignee: { type: 'boolean' },\n recoveryMode: { type: 'string', enum: ['auto', 'release', 'retry', 'fail'] },\n recoveryNow: { type: 'string' },\n recoveryPolicyFailOnCostCeiling: { type: 'boolean' },\n recoveryPolicyReleaseOnFailureKinds: { type: 'array', items: { type: 'string' } },\n recoveryPolicyReleaseOnHeartbeatDue: { type: 'boolean' },\n recoveryPolicyRetryPolicyOverride: {\n type: 'string',\n enum: ['off', 'incremental', 'exponential'],\n },\n assignee: { type: 'string' },\n costCeilingUsd: { type: 'number' },\n retryPolicy: { type: 'string', enum: ['off', 'incremental', 'exponential'] },\n lastFailureKind: { type: 'string' },\n dependsOn: { type: 'array', items: { type: 'string' } },\n estimatedHours: { type: 'number' },\n taskGraph: { type: 'object' },\n graphId: { type: 'string' },\n specId: { type: 'string' },\n sourceSystem: { type: 'string' },\n phaseId: { type: 'string' },\n preserveOriginTaskIds: { type: 'boolean' },\n includeArchived: { type: 'boolean' },\n archiveMissingTasks: { type: 'boolean' },\n preserveManualDependencies: { type: 'boolean' },\n dependencyTaskId: { type: 'string' },\n enforceDependencies: { type: 'boolean' },\n childTitles: { type: 'array', items: { type: 'string' } },\n inheritAssignment: { type: 'boolean' },\n inheritLabels: { type: 'boolean' },\n inheritSuccessCriteria: { type: 'boolean' },\n inheritGoalMetrics: { type: 'boolean' },\n inheritDependencies: { type: 'boolean' },\n chainChildren: { type: 'boolean' },\n rewireDependents: { type: 'boolean' },\n closeSourceTasks: { type: 'boolean' },\n metricId: { type: 'string' },\n metricName: { type: 'string' },\n metricTarget: { oneOf: [{ type: 'string' }, { type: 'number' }] },\n metricCurrent: { oneOf: [{ type: 'string' }, { type: 'number' }] },\n metricUnit: { type: 'string' },\n metricStatus: { type: 'string', enum: ['pending', 'met', 'missed', 'waived'] },\n metricNotes: { type: 'string' },\n checkId: { type: 'string' },\n checkDescription: { type: 'string' },\n checkStatus: { type: 'string', enum: ['pending', 'passed', 'failed', 'skipped'] },\n note: { type: 'string' },\n author: { type: 'string' },\n url: { type: 'string' },\n linkTitle: { type: 'string' },\n linkType: {\n type: 'string',\n enum: ['issue', 'pr', 'doc', 'commit', 'design', 'file', 'url', 'other'],\n },\n context: { type: 'string' },\n columns: { type: 'array', items: { type: 'string' } },\n generatedBy: { type: 'string' },\n includeTasks: { type: 'boolean' },\n includeCompletedTasks: { type: 'boolean' },\n preserveAssignment: { type: 'boolean' },\n preserveDependencies: { type: 'boolean' },\n moveTasksToColumnId: { type: 'string' },\n },\n required: ['action'],\n },\n async execute(input, ctx) {\n const projectRoot = ctx.projectRoot;\n if (!projectRoot) return fail('No project root is available.');\n\n try {\n switch (input.action) {\n case 'list_boards': {\n const boards = await listBoards(projectRoot);\n return { ok: true, message: `${boards.length} board(s).`, boards };\n }\n case 'get_board': {\n const board = await requireBoard(projectRoot, input.boardId);\n return board ? okBoard(board) : fail('Board not found.');\n }\n case 'create_board': {\n if (!input.title) return fail('create_board requires title.');\n const board = await createBoard(projectRoot, {\n title: input.title,\n ...(input.description !== undefined ? { description: input.description } : {}),\n ...(input.tags !== undefined ? { tags: input.tags } : {}),\n ...(input.generatedBy !== undefined ? { generatedBy: input.generatedBy } : {}),\n });\n return { ok: true, message: `Board created: ${board.title}`, board };\n }\n case 'update_board': {\n if (!input.boardId) return fail('update_board requires boardId.');\n const board = await updateBoard(projectRoot, input.boardId, {\n ...(input.title !== undefined ? { title: input.title } : {}),\n ...(input.description !== undefined ? { description: input.description } : {}),\n ...(input.tags !== undefined ? { tags: input.tags } : {}),\n });\n return board ? okBoard(board, 'Board updated.') : fail('Board not found.');\n }\n case 'duplicate_board': {\n if (!input.boardId) return fail('duplicate_board requires boardId.');\n const board = await duplicateBoard(projectRoot, input.boardId, {\n ...(input.title !== undefined ? { title: input.title } : {}),\n ...(input.generatedBy !== undefined ? { generatedBy: input.generatedBy } : {}),\n ...(input.includeTasks !== undefined ? { includeTasks: input.includeTasks } : {}),\n ...(input.includeCompletedTasks !== undefined\n ? { includeCompletedTasks: input.includeCompletedTasks }\n : {}),\n ...(input.preserveAssignment !== undefined\n ? { preserveAssignment: input.preserveAssignment }\n : {}),\n });\n return board ? okBoard(board, 'Board duplicated.') : fail('Board not found.');\n }\n case 'delete_board': {\n if (!input.boardId) return fail('delete_board requires boardId.');\n const removed = await removeBoard(projectRoot, input.boardId);\n return { ok: removed, message: removed ? 'Board deleted.' : 'Board not found.' };\n }\n case 'generate_board': {\n if (!input.description) return fail('generate_board requires description.');\n const boardInput = generateBoardFromDescription({\n description: input.description,\n ...(input.title !== undefined ? { title: input.title } : {}),\n ...(input.context !== undefined ? { context: input.context } : {}),\n ...(input.columns !== undefined ? { columns: input.columns } : {}),\n });\n const board = await createBoard(projectRoot, boardInput);\n for (const taskInput of parseLinesIntoTasks(\n input.description,\n board.columns[0]?.id ?? 'backlog',\n )) {\n await addTask(projectRoot, board.id, taskInput);\n }\n return okBoard((await getBoard(projectRoot, board.id)) ?? board, 'Board generated.');\n }\n case 'export_markdown': {\n const board = await requireBoard(projectRoot, input.boardId);\n if (!board) return fail('Board not found.');\n return {\n ok: true,\n message: 'Board exported.',\n board,\n markdown: exportBoardAsMarkdown(board),\n };\n }\n case 'export_task_graph': {\n if (!input.boardId) return fail('export_task_graph requires boardId.');\n const exported = await exportBoardToTaskGraph(projectRoot, input.boardId, {\n ...(input.graphId !== undefined ? { graphId: input.graphId } : {}),\n ...(input.specId !== undefined ? { specId: input.specId } : {}),\n ...(input.title !== undefined ? { title: input.title } : {}),\n ...(input.preserveOriginTaskIds !== undefined\n ? { preserveOriginTaskIds: input.preserveOriginTaskIds }\n : {}),\n ...(input.includeArchived !== undefined\n ? { includeArchived: input.includeArchived }\n : {}),\n });\n if (!exported) return fail('Board not found.');\n return {\n ok: true,\n message: `Task graph exported with ${exported.graph.nodes.size} node(s).`,\n board: exported.board,\n taskGraph: serializeTaskGraph(exported.graph),\n };\n }\n case 'sync_task_graph': {\n if (!input.boardId || !input.taskGraph) {\n return fail('sync_task_graph requires boardId and taskGraph.');\n }\n const graph = deserializeTaskGraph(input.taskGraph as SerializableTaskGraph);\n const result = await syncBoardFromTaskGraph(projectRoot, input.boardId, graph, {\n ...(input.title !== undefined ? { title: input.title } : {}),\n ...(input.description !== undefined ? { description: input.description } : {}),\n ...(input.tags !== undefined ? { tags: input.tags } : {}),\n ...(input.generatedBy !== undefined ? { generatedBy: input.generatedBy } : {}),\n ...(input.sourceSystem !== undefined ? { sourceSystem: input.sourceSystem } : {}),\n ...(input.phaseId !== undefined ? { phaseId: input.phaseId } : {}),\n ...(input.includeCompletedTasks !== undefined\n ? { includeCompletedTasks: input.includeCompletedTasks }\n : {}),\n ...(input.archiveMissingTasks !== undefined\n ? { archiveMissingTasks: input.archiveMissingTasks }\n : {}),\n ...(input.preserveManualDependencies !== undefined\n ? { preserveManualDependencies: input.preserveManualDependencies }\n : {}),\n });\n return result\n ? {\n ok: true,\n message: `Task graph synced: ${result.createdTaskIds.length} created, ${result.updatedTaskIds.length} updated, ${result.archivedTaskIds.length} archived.`,\n board: result.board,\n }\n : fail('Board not found.');\n }\n case 'create_from_graph': {\n if (!input.taskGraph) return fail('create_from_graph requires taskGraph.');\n const graph = deserializeTaskGraph(input.taskGraph as SerializableTaskGraph);\n const { board } = await createBoardFromTaskGraph(projectRoot, graph, {\n ...(input.title !== undefined ? { title: input.title } : {}),\n ...(input.description !== undefined ? { description: input.description } : {}),\n ...(input.tags !== undefined ? { tags: input.tags } : {}),\n ...(input.generatedBy !== undefined ? { generatedBy: input.generatedBy } : {}),\n ...(input.sourceSystem !== undefined ? { sourceSystem: input.sourceSystem } : {}),\n ...(input.phaseId !== undefined ? { phaseId: input.phaseId } : {}),\n ...(input.includeCompletedTasks !== undefined\n ? { includeCompletedTasks: input.includeCompletedTasks }\n : {}),\n });\n return {\n ok: true,\n message: `Created board \"${board.title}\" from task graph with ${board.tasks.length} tasks.`,\n board,\n };\n }\n case 'import_session_tasks': {\n // One-way projection: mirror this session's `.tasks.json` (the `task`\n // tool's list) into a kanban board so session work shows up on a board\n // without swapping the task tool's storage. Origin-keyed + re-runnable.\n const taskPath = (ctx.meta as Record<string, unknown>)?.['task.path'] as\n | string\n | undefined;\n if (!taskPath) return fail('No session task file for this session.');\n const file = await loadTasks(taskPath);\n if (!file || file.tasks.length === 0) return fail('No session tasks to import.');\n const sessionId = ctx.session?.id ?? file.sessionId ?? 'session';\n const graph = deserializeTaskGraph(taskFileToSerializedGraph(file.tasks, sessionId));\n const tags = ['session', `session:${sessionId}`];\n const existing = (await listBoards(projectRoot)).find((b) =>\n b.tags?.includes(`session:${sessionId}`),\n );\n if (existing) {\n const result = await syncBoardFromTaskGraph(projectRoot, existing.id, graph, {\n sourceSystem: 'session',\n tags,\n archiveMissingTasks: true,\n includeCompletedTasks: true,\n });\n return result\n ? {\n ok: true,\n message: `Synced ${file.tasks.length} session tasks into board \"${result.board.title}\".`,\n board: result.board,\n }\n : fail('Session board vanished mid-sync.');\n }\n const { board } = await createBoardFromTaskGraph(projectRoot, graph, {\n title: `Session tasks (${sessionId.slice(0, 8)})`,\n sourceSystem: 'session',\n tags,\n });\n return {\n ok: true,\n message: `Imported ${file.tasks.length} session tasks into new board \"${board.title}\".`,\n board,\n };\n }\n case 'search_tasks': {\n const tasks = await searchKanban(projectRoot, {\n query: input.query,\n boardId: input.boardId,\n assignedAgent: input.agentId,\n status: input.status,\n priority: input.priority,\n label: input.labels?.[0],\n chainId: input.chainId,\n });\n return { ok: true, message: `${tasks.length} task(s) matched.`, tasks };\n }\n case 'ready_tasks': {\n const tasks = await listReadyTasks(projectRoot, {\n query: input.query,\n boardId: input.boardId,\n assignedAgent: input.agentId,\n priority: input.priority,\n label: input.labels?.[0],\n chainId: input.chainId,\n limit: input.limit,\n });\n return { ok: true, message: `${tasks.length} ready task(s).`, tasks };\n }\n case 'snapshot': {\n const snapshot = await getKanbanOrchestrationSnapshot(projectRoot, {\n query: input.query,\n boardId: input.boardId,\n assignedAgent: input.agentId,\n status: input.status,\n priority: input.priority,\n label: input.labels?.[0],\n chainId: input.chainId,\n });\n return {\n ok: true,\n message: `${snapshot.ready.length} ready, ${snapshot.running.length} running, ${snapshot.blocked.length} blocked.`,\n snapshot,\n };\n }\n case 'add_column': {\n if (!input.boardId || !input.title) return fail('add_column requires boardId and title.');\n const result = await addColumn(projectRoot, input.boardId, {\n title: input.title,\n ...(input.description !== undefined ? { description: input.description } : {}),\n });\n return result ? okBoard(result.board, 'Column added.') : fail('Board not found.');\n }\n case 'update_column': {\n if (!input.boardId || !input.columnId)\n return fail('update_column requires boardId and columnId.');\n const board = await updateColumn(projectRoot, input.boardId, input.columnId, {\n ...(input.title !== undefined ? { title: input.title } : {}),\n ...(input.description !== undefined ? { description: input.description } : {}),\n ...(input.order !== undefined ? { order: input.order } : {}),\n });\n return board ? okBoard(board, 'Column updated.') : fail('Column not found.');\n }\n case 'delete_column': {\n if (!input.boardId || !input.columnId)\n return fail('delete_column requires boardId and columnId.');\n const board = await removeColumn(projectRoot, input.boardId, input.columnId, {\n moveTasksToColumnId: input.moveTasksToColumnId,\n });\n return board ? okBoard(board, 'Column deleted.') : fail('Column not found.');\n }\n case 'add_task': {\n if (!input.boardId || !input.title) return fail('add_task requires boardId and title.');\n const result = await addTask(projectRoot, input.boardId, taskInput(input));\n return result\n ? okTask(result.board, result.task, 'Task added.')\n : fail('Board not found.');\n }\n case 'split_task': {\n if (!input.boardId || !input.taskId || !input.childTitles?.length) {\n return fail('split_task requires boardId, taskId, and childTitles.');\n }\n const result = await splitTask(projectRoot, input.boardId, input.taskId, {\n titles: input.childTitles,\n ...(input.targetColumnId !== undefined ? { columnId: input.targetColumnId } : {}),\n ...(input.inheritAssignment !== undefined\n ? { inheritAssignment: input.inheritAssignment }\n : {}),\n ...(input.inheritLabels !== undefined ? { inheritLabels: input.inheritLabels } : {}),\n ...(input.inheritSuccessCriteria !== undefined\n ? { inheritSuccessCriteria: input.inheritSuccessCriteria }\n : {}),\n ...(input.inheritGoalMetrics !== undefined\n ? { inheritGoalMetrics: input.inheritGoalMetrics }\n : {}),\n ...(input.inheritDependencies !== undefined\n ? { inheritDependencies: input.inheritDependencies }\n : {}),\n ...(input.chainChildren !== undefined ? { chainChildren: input.chainChildren } : {}),\n ...(input.rewireDependents !== undefined\n ? { rewireDependents: input.rewireDependents }\n : {}),\n });\n return result\n ? {\n ok: true,\n message: `${result.children.length} child task(s) created.`,\n board: result.board,\n task: result.parent,\n children: result.children,\n }\n : fail('Task not found.');\n }\n case 'merge_tasks': {\n if (!input.boardId || !input.taskIds?.length || !input.title) {\n return fail('merge_tasks requires boardId, taskIds, and title.');\n }\n const result = await mergeTasks(projectRoot, input.boardId, {\n taskIds: input.taskIds,\n title: input.title,\n ...(input.description !== undefined ? { description: input.description } : {}),\n ...(input.targetColumnId !== undefined ? { targetColumnId: input.targetColumnId } : {}),\n ...(input.preserveAssignment !== undefined\n ? { preserveAssignment: input.preserveAssignment }\n : {}),\n ...(input.closeSourceTasks !== undefined\n ? { closeSourceTasks: input.closeSourceTasks }\n : {}),\n });\n return result\n ? okTask(result.board, result.task, 'Tasks merged.')\n : fail('Board or task not found.');\n }\n case 'copy_task': {\n if (!input.boardId || !input.taskId || !input.targetBoardId) {\n return fail('copy_task requires boardId, taskId, and targetBoardId.');\n }\n const result = await copyTaskToBoard(\n projectRoot,\n input.boardId,\n input.taskId,\n input.targetBoardId,\n {\n ...(input.targetColumnId !== undefined\n ? { targetColumnId: input.targetColumnId }\n : {}),\n ...(input.order !== undefined ? { targetOrder: input.order } : {}),\n ...(input.preserveAssignment !== undefined\n ? { preserveAssignment: input.preserveAssignment }\n : {}),\n ...(input.preserveDependencies !== undefined\n ? { preserveDependencies: input.preserveDependencies }\n : {}),\n },\n );\n return result\n ? okTask(result.targetBoard, result.task, 'Task copied to target board.')\n : fail('Board or task not found.');\n }\n case 'transfer_task': {\n if (!input.boardId || !input.taskId || !input.targetBoardId) {\n return fail('transfer_task requires boardId, taskId, and targetBoardId.');\n }\n const result = await transferTaskToBoard(\n projectRoot,\n input.boardId,\n input.taskId,\n input.targetBoardId,\n {\n ...(input.targetColumnId !== undefined\n ? { targetColumnId: input.targetColumnId }\n : {}),\n ...(input.order !== undefined ? { targetOrder: input.order } : {}),\n ...(input.preserveAssignment !== undefined\n ? { preserveAssignment: input.preserveAssignment }\n : {}),\n ...(input.preserveDependencies !== undefined\n ? { preserveDependencies: input.preserveDependencies }\n : {}),\n },\n );\n return result\n ? okTask(result.targetBoard, result.task, 'Task transferred to target board.')\n : fail('Board or task not found.');\n }\n case 'get_task': {\n if (!input.boardId || !input.taskId) return fail('get_task requires boardId and taskId.');\n const task = await getTask(projectRoot, input.boardId, input.taskId);\n return task ? { ok: true, message: 'Task loaded.', task } : fail('Task not found.');\n }\n case 'update_task': {\n if (!input.boardId || !input.taskId)\n return fail('update_task requires boardId and taskId.');\n const board = await updateTask(\n projectRoot,\n input.boardId,\n input.taskId,\n taskPatch(input),\n );\n return board ? okBoard(board, 'Task updated.') : fail('Task not found.');\n }\n case 'move_task': {\n if (!input.boardId || !input.taskId || !input.targetColumnId) {\n return fail('move_task requires boardId, taskId, and targetColumnId.');\n }\n const board = await moveTask(\n projectRoot,\n input.boardId,\n input.taskId,\n input.targetColumnId,\n input.order,\n );\n return board ? okBoard(board, 'Task moved.') : fail('Move failed.');\n }\n case 'delete_task': {\n if (!input.boardId || !input.taskId)\n return fail('delete_task requires boardId and taskId.');\n const board = await removeTask(projectRoot, input.boardId, input.taskId);\n return board ? okBoard(board, 'Task deleted.') : fail('Task not found.');\n }\n case 'set_chain': {\n if (!input.boardId || !input.taskIds?.length) {\n return fail('set_chain requires boardId and taskIds.');\n }\n const result = await setTaskChain(projectRoot, input.boardId, {\n taskIds: input.taskIds,\n ...(input.chainId !== undefined ? { chainId: input.chainId } : {}),\n ...(input.enforceDependencies !== undefined\n ? { enforceDependencies: input.enforceDependencies }\n : {}),\n });\n return result\n ? {\n ok: true,\n message: `Chain set: ${result.chainId}`,\n board: result.board,\n chain: result.tasks,\n }\n : fail('Board or task not found.');\n }\n case 'get_chain': {\n if (!input.boardId || !(input.taskId || input.chainId)) {\n return fail('get_chain requires boardId and taskId or chainId.');\n }\n const result = await getTaskChain(\n projectRoot,\n input.boardId,\n input.taskId ?? input.chainId ?? '',\n );\n return result\n ? {\n ok: true,\n message: `Chain loaded: ${result.chainId}`,\n board: result.board,\n chain: result.tasks,\n }\n : fail('Chain not found.');\n }\n case 'claim_task': {\n const result = await claimReadyTask(projectRoot, {\n ...(input.boardId !== undefined ? { boardId: input.boardId } : {}),\n ...(input.taskId !== undefined ? { taskId: input.taskId } : {}),\n ...assignmentInput(input),\n status: input.assignmentStatus ?? 'queued',\n });\n return result\n ? okTask(result.board, result.task, 'Task claimed.')\n : fail('No ready kanban task matched the claim.');\n }\n case 'release_task': {\n if (!input.boardId || !input.taskId) {\n return fail('release_task requires boardId and taskId.');\n }\n const board = await releaseTaskClaim(projectRoot, input.boardId, input.taskId, {\n ...(input.releaseStatus !== undefined ? { status: input.releaseStatus } : {}),\n ...(input.releaseReason !== undefined ? { reason: input.releaseReason } : {}),\n ...(input.clearAssignee !== undefined ? { clearAssignee: input.clearAssignee } : {}),\n });\n return board ? okBoard(board, 'Task claim released.') : fail('Task not found.');\n }\n case 'assign_task': {\n if (!input.boardId || !input.taskId)\n return fail('assign_task requires boardId and taskId.');\n const board = await assignTask(\n projectRoot,\n input.boardId,\n input.taskId,\n assignmentInput(input),\n );\n return board ? okBoard(board, 'Task assigned.') : fail('Task not found.');\n }\n case 'mark_assignment': {\n if (!input.boardId || !input.taskId)\n return fail('mark_assignment requires boardId and taskId.');\n const assignmentStatus =\n input.assignmentStatus ??\n (input.status === 'completed' ? 'completed' : input.error ? 'failed' : undefined);\n const board = await updateTaskAssignment(projectRoot, input.boardId, input.taskId, {\n ...(assignmentStatus !== undefined ? { status: assignmentStatus } : {}),\n ...(input.subagentId !== undefined ? { subagentId: input.subagentId } : {}),\n ...(input.runTaskId !== undefined ? { runTaskId: input.runTaskId } : {}),\n ...(input.lastResult !== undefined ? { lastResult: input.lastResult } : {}),\n ...(input.error !== undefined ? { error: input.error } : {}),\n ...(input.agentId !== undefined ? { agentId: input.agentId } : {}),\n ...(input.leaseId !== undefined ? { leaseId: input.leaseId } : {}),\n ...(input.claimedAt !== undefined ? { claimedAt: input.claimedAt } : {}),\n ...(input.heartbeatAt !== undefined ? { heartbeatAt: input.heartbeatAt } : {}),\n ...(input.leaseExpiresAt !== undefined ? { leaseExpiresAt: input.leaseExpiresAt } : {}),\n ...(input.attempt !== undefined ? { attempt: input.attempt } : {}),\n ...(input.maxAttempts !== undefined ? { maxAttempts: input.maxAttempts } : {}),\n });\n return board ? okBoard(board, 'Assignment updated.') : fail('Task not found.');\n }\n case 'heartbeat_assignment': {\n if (!input.boardId || !input.taskId) {\n return fail('heartbeat_assignment requires boardId and taskId.');\n }\n const board = await heartbeatTaskAssignment(projectRoot, input.boardId, input.taskId, {\n ...(input.heartbeatAt !== undefined ? { heartbeatAt: input.heartbeatAt } : {}),\n ...(input.leaseExpiresAt !== undefined ? { leaseExpiresAt: input.leaseExpiresAt } : {}),\n });\n return board\n ? okBoard(board, 'Assignment heartbeat updated.')\n : fail('Task assignment not found.');\n }\n case 'recover_stale': {\n if (!input.boardId) return fail('recover_stale requires boardId.');\n const policyFields = [\n input.recoveryPolicyFailOnCostCeiling !== undefined,\n input.recoveryPolicyReleaseOnFailureKinds !== undefined,\n input.recoveryPolicyReleaseOnHeartbeatDue !== undefined,\n input.recoveryPolicyRetryPolicyOverride !== undefined,\n ].some(Boolean);\n const result = await recoverStaleTaskAssignments(projectRoot, input.boardId, {\n ...(input.recoveryMode !== undefined ? { mode: input.recoveryMode } : {}),\n ...(input.recoveryNow !== undefined ? { now: input.recoveryNow } : {}),\n ...(input.releaseReason !== undefined ? { reason: input.releaseReason } : {}),\n ...(input.clearAssignee !== undefined ? { clearAssignee: input.clearAssignee } : {}),\n ...(policyFields\n ? {\n policy: {\n ...(input.recoveryPolicyFailOnCostCeiling !== undefined\n ? { failWhenCostCeilingSet: input.recoveryPolicyFailOnCostCeiling }\n : {}),\n ...(input.recoveryPolicyReleaseOnFailureKinds !== undefined\n ? {\n releaseOnFailureKinds: input.recoveryPolicyReleaseOnFailureKinds,\n }\n : {}),\n ...(input.recoveryPolicyReleaseOnHeartbeatDue !== undefined\n ? {\n releaseOnHeartbeatDue: input.recoveryPolicyReleaseOnHeartbeatDue,\n }\n : {}),\n ...(input.recoveryPolicyRetryPolicyOverride !== undefined\n ? {\n retryPolicyOverride: input.recoveryPolicyRetryPolicyOverride,\n }\n : {}),\n },\n }\n : {}),\n });\n return result\n ? {\n ok: true,\n message: `Recovered ${result.tasks.length} stale assignment(s).`,\n board: result.board,\n recoveredTasks: result.tasks,\n }\n : { ok: true, message: 'No stale assignment matched.', recoveredTasks: [] };\n }\n case 'events': {\n if (!input.boardId) return fail('events requires boardId.');\n const eventList = await listKanbanEvents(projectRoot, input.boardId);\n return {\n ok: true,\n message: `${eventList.length} event(s).`,\n events: eventList,\n };\n }\n case 'queue_health': {\n const health = await getKanbanQueueHealth(projectRoot, {\n ...(input.boardId !== undefined ? { boardId: input.boardId } : {}),\n });\n return {\n ok: true,\n message: `Counts: ready=${health.counts.ready}, running=${health.counts.running}, stale=${health.staleAssignments.count}.`,\n queueHealth: health,\n };\n }\n case 'add_dependency': {\n if (!input.boardId || !input.taskId || !input.dependencyTaskId) {\n return fail('add_dependency requires boardId, taskId, and dependencyTaskId.');\n }\n const board = await addDependency(\n projectRoot,\n input.boardId,\n input.taskId,\n input.dependencyTaskId,\n );\n return board ? okBoard(board, 'Dependency added.') : fail('Task not found.');\n }\n case 'add_goal_metric': {\n if (!input.boardId || !input.taskId || !input.metricName) {\n return fail('add_goal_metric requires boardId, taskId, and metricName.');\n }\n const board = await addGoalMetricToTask(projectRoot, input.boardId, input.taskId, {\n name: input.metricName,\n ...(input.metricStatus !== undefined ? { status: input.metricStatus } : {}),\n ...(input.metricTarget !== undefined ? { target: input.metricTarget } : {}),\n ...(input.metricCurrent !== undefined ? { current: input.metricCurrent } : {}),\n ...(input.metricUnit !== undefined ? { unit: input.metricUnit } : {}),\n ...(input.metricNotes !== undefined ? { notes: input.metricNotes } : {}),\n });\n return board ? okBoard(board, 'Goal metric added.') : fail('Task not found.');\n }\n case 'update_goal_metric': {\n if (!input.boardId || !input.taskId || !input.metricId) {\n return fail('update_goal_metric requires boardId, taskId, and metricId.');\n }\n const board = await updateGoalMetricOnTask(\n projectRoot,\n input.boardId,\n input.taskId,\n input.metricId,\n {\n ...(input.metricName !== undefined ? { name: input.metricName } : {}),\n ...(input.metricStatus !== undefined ? { status: input.metricStatus } : {}),\n ...(input.metricTarget !== undefined ? { target: input.metricTarget } : {}),\n ...(input.metricCurrent !== undefined ? { current: input.metricCurrent } : {}),\n ...(input.metricUnit !== undefined ? { unit: input.metricUnit } : {}),\n ...(input.metricNotes !== undefined ? { notes: input.metricNotes } : {}),\n },\n );\n return board ? okBoard(board, 'Goal metric updated.') : fail('Metric not found.');\n }\n case 'add_check': {\n if (!input.boardId || !input.taskId || !input.checkDescription) {\n return fail('add_check requires boardId, taskId, and checkDescription.');\n }\n const board = await addCheckToTask(projectRoot, input.boardId, input.taskId, {\n description: input.checkDescription,\n type: 'manual',\n status: input.checkStatus,\n });\n return board ? okBoard(board, 'Check added.') : fail('Task not found.');\n }\n case 'update_check': {\n if (!input.boardId || !input.taskId || !input.checkId) {\n return fail('update_check requires boardId, taskId, and checkId.');\n }\n const board = await updateCheckOnTask(\n projectRoot,\n input.boardId,\n input.taskId,\n input.checkId,\n {\n ...(input.checkDescription !== undefined\n ? { description: input.checkDescription }\n : {}),\n ...(input.checkStatus !== undefined ? { status: input.checkStatus } : {}),\n },\n );\n return board ? okBoard(board, 'Check updated.') : fail('Check not found.');\n }\n case 'add_note': {\n if (!input.boardId || !input.taskId || !input.note)\n return fail('add_note requires boardId, taskId, and note.');\n const board = await addNoteToTask(projectRoot, input.boardId, input.taskId, {\n author: input.author ?? 'agent',\n content: input.note,\n });\n return board ? okBoard(board, 'Note added.') : fail('Task not found.');\n }\n case 'add_link': {\n if (!input.boardId || !input.taskId || !input.url)\n return fail('add_link requires boardId, taskId, and url.');\n const board = await addLinkToTask(projectRoot, input.boardId, input.taskId, {\n url: input.url,\n type: input.linkType ?? 'url',\n ...(input.linkTitle !== undefined ? { title: input.linkTitle } : {}),\n });\n return board ? okBoard(board, 'Link added.') : fail('Task not found.');\n }\n default:\n return fail(`Unknown kanban action: ${(input as { action: string }).action}`);\n }\n } catch (err) {\n return fail(err instanceof Error ? err.message : String(err));\n }\n },\n};\n\nfunction fail(message: string): KanbanToolOutput {\n return { ok: false, message };\n}\n\nfunction okBoard(board: KanbanBoard, message = 'Board loaded.'): KanbanToolOutput {\n return { ok: true, message, board };\n}\n\nfunction okTask(board: KanbanBoard, task: KanbanTask, message: string): KanbanToolOutput {\n return { ok: true, message, board, task };\n}\n\nasync function requireBoard(\n projectRoot: string,\n boardId: string | undefined,\n): Promise<KanbanBoard | null> {\n return boardId ? getBoard(projectRoot, boardId) : null;\n}\n\nfunction taskInput(input: KanbanToolInput) {\n const assignment = hasAssignmentInput(input) ? assignmentForTaskCreate(input) : undefined;\n return {\n title: input.title ?? '',\n columnId: input.columnId,\n description: input.description,\n priority: input.priority,\n ...(input.taskType !== undefined ? { type: input.taskType } : {}),\n status: input.status,\n labels: input.labels,\n ...((assignment?.agentId ?? assignment?.role ?? assignment?.name)\n ? { assignedAgent: assignment.agentId ?? assignment.role ?? assignment.name }\n : {}),\n ...((input.assignee ?? assignment?.name ?? assignment?.agentId)\n ? { assignee: input.assignee ?? assignment?.name ?? assignment?.agentId }\n : {}),\n ...(mergedDependsOn(input) ? { dependsOn: mergedDependsOn(input) } : {}),\n ...(input.estimatedHours !== undefined ? { estimatedHours: input.estimatedHours } : {}),\n ...(assignment ? { assignment } : {}),\n };\n}\n\n/** Union of the single `dependencyTaskId` and the multi `dependsOn[]` inputs. */\nfunction mergedDependsOn(input: KanbanToolInput): string[] | undefined {\n const ids = [\n ...(input.dependsOn ?? []),\n ...(input.dependencyTaskId !== undefined ? [input.dependencyTaskId] : []),\n ].filter((id, i, arr) => id && arr.indexOf(id) === i);\n return ids.length > 0 ? ids : undefined;\n}\n\nfunction taskPatch(input: KanbanToolInput) {\n return {\n title: input.title,\n description: input.description,\n columnId: input.columnId,\n order: input.order,\n priority: input.priority,\n ...(input.taskType !== undefined ? { type: input.taskType } : {}),\n status: input.status,\n labels: input.labels,\n assignedAgent: input.agentId,\n ...(mergedDependsOn(input) ? { dependsOn: mergedDependsOn(input) } : {}),\n ...(input.estimatedHours !== undefined ? { estimatedHours: input.estimatedHours } : {}),\n };\n}\n\nfunction assignmentInput(input: KanbanToolInput): AssignKanbanTaskInput {\n return {\n agentId: input.agentId,\n name: input.name,\n role: input.role,\n provider: input.provider,\n model: input.model,\n fallbackProfile: input.fallbackProfile,\n fallbackModels: input.fallbackModels,\n tools: input.tools,\n allowedCapabilities: input.allowedCapabilities,\n assignee: input.assignee,\n leaseId: input.leaseId,\n claimedAt: input.claimedAt,\n heartbeatAt: input.heartbeatAt,\n leaseExpiresAt: input.leaseExpiresAt,\n attempt: input.attempt,\n maxAttempts: input.maxAttempts,\n costCeilingUsd: input.costCeilingUsd,\n retryPolicy: input.retryPolicy,\n lastFailureKind: input.lastFailureKind,\n };\n}\n\nfunction hasAssignmentInput(input: KanbanToolInput): boolean {\n return (\n input.agentId !== undefined ||\n input.name !== undefined ||\n input.role !== undefined ||\n input.provider !== undefined ||\n input.model !== undefined ||\n input.fallbackProfile !== undefined ||\n input.fallbackModels !== undefined ||\n input.tools !== undefined ||\n input.allowedCapabilities !== undefined ||\n input.assignee !== undefined ||\n input.leaseId !== undefined ||\n input.claimedAt !== undefined ||\n input.heartbeatAt !== undefined ||\n input.leaseExpiresAt !== undefined ||\n input.attempt !== undefined ||\n input.maxAttempts !== undefined ||\n input.costCeilingUsd !== undefined ||\n input.retryPolicy !== undefined ||\n input.lastFailureKind !== undefined ||\n input.assignmentStatus !== undefined\n );\n}\n\nfunction assignmentForTaskCreate(input: KanbanToolInput): KanbanAgentAssignment {\n return {\n status: input.assignmentStatus ?? 'assigned',\n ...(input.agentId !== undefined ? { agentId: input.agentId } : {}),\n ...(input.name !== undefined ? { name: input.name } : {}),\n ...(input.role !== undefined ? { role: input.role } : {}),\n ...(input.provider !== undefined ? { provider: input.provider } : {}),\n ...(input.model !== undefined ? { model: input.model } : {}),\n ...(input.fallbackProfile !== undefined ? { fallbackProfile: input.fallbackProfile } : {}),\n ...(input.fallbackModels !== undefined ? { fallbackModels: input.fallbackModels } : {}),\n ...(input.tools !== undefined ? { tools: input.tools } : {}),\n ...(input.allowedCapabilities !== undefined\n ? { allowedCapabilities: input.allowedCapabilities }\n : {}),\n ...(input.leaseId !== undefined ? { leaseId: input.leaseId } : {}),\n ...(input.claimedAt !== undefined ? { claimedAt: input.claimedAt } : {}),\n ...(input.heartbeatAt !== undefined ? { heartbeatAt: input.heartbeatAt } : {}),\n ...(input.leaseExpiresAt !== undefined ? { leaseExpiresAt: input.leaseExpiresAt } : {}),\n ...(input.attempt !== undefined ? { attempt: input.attempt } : {}),\n ...(input.maxAttempts !== undefined ? { maxAttempts: input.maxAttempts } : {}),\n ...(input.costCeilingUsd !== undefined ? { costCeilingUsd: input.costCeilingUsd } : {}),\n ...(input.retryPolicy !== undefined ? { retryPolicy: input.retryPolicy } : {}),\n ...(input.lastFailureKind !== undefined ? { lastFailureKind: input.lastFailureKind } : {}),\n };\n}\n", "import { type FSWatcher, watch } from 'node:fs';\nimport { basename, dirname } from 'node:path';\nimport {\n type Context,\n deserializeTaskGraph,\n loadPlan,\n loadTasks,\n mutatePlan,\n mutateTasks,\n type PlanFile,\n type PlanItem,\n type SerializedTaskGraph,\n type TaskFile,\n type TaskItem,\n type TaskStatus,\n type TodoItem,\n} from '@wrongstack/core';\nimport {\n createBoard,\n getBoard,\n type KanbanBoard,\n type KanbanColumn,\n type KanbanTask,\n listBoards,\n removeBoard,\n syncBoardFromTaskGraph,\n updateBoard,\n} from '@wrongstack/kanban';\n\nconst SESSION_BOARD_TAG = 'session-work';\nconst MIRROR_DISABLED_ENV = 'WRONGSTACK_KANBAN_TASK_MIRROR';\n\n/** The canonical workflow shared by WebUI and TUI session boards. */\nexport const SESSION_KANBAN_COLUMNS: KanbanColumn[] = [\n { id: 'todo', title: 'Todo', order: 0, wipLimit: 0, color: '#2563eb' },\n { id: 'in-progress', title: 'Running', order: 1, wipLimit: 1, color: '#d97706' },\n { id: 'review', title: 'Preview', order: 2, wipLimit: 0, color: '#7c3aed' },\n { id: 'done', title: 'Done', order: 3, wipLimit: 0, color: '#16a34a' },\n];\n\nconst boardQueue = new Map<string, Promise<void>>();\nconst boardEnsures = new Map<string, Promise<KanbanBoard>>();\nconst bindings = new WeakMap<Context, () => void>();\nconst suppressedTodoMirrors = new WeakSet<Context>();\nconst activeSessionBoards = new Map<string, number>();\n\nfunction boardKey(projectRoot: string, sessionId: string): string {\n return `${projectRoot}\\0${sessionId}`;\n}\n\nfunction sessionTag(sessionId: string): string {\n return `session:${sessionId}`;\n}\n\nfunction sessionBoardTitle(sessionId: string): string {\n const leaf = sessionId.split(/[\\\\/]/).filter(Boolean).pop() ?? sessionId;\n return `Session ${leaf.slice(0, 12)}`;\n}\n\nfunction sessionBoardTags(sessionId: string): string[] {\n return ['session', SESSION_BOARD_TAG, sessionTag(sessionId)];\n}\n\nfunction sessionIdFromTags(tags: readonly string[] | undefined): string | null {\n const tag = tags?.find((candidate) => candidate.startsWith('session:'));\n return tag?.slice('session:'.length) || null;\n}\n\nfunction isOwnedSessionBoard(tags: readonly string[] | undefined): boolean {\n return Boolean(tags?.includes(SESSION_BOARD_TAG) && sessionIdFromTags(tags));\n}\n\nfunction retainActiveSessionBoard(projectRoot: string, sessionId: string): void {\n const key = boardKey(projectRoot, sessionId);\n activeSessionBoards.set(key, (activeSessionBoards.get(key) ?? 0) + 1);\n}\n\nfunction releaseActiveSessionBoard(projectRoot: string, sessionId: string): void {\n const key = boardKey(projectRoot, sessionId);\n const remaining = (activeSessionBoards.get(key) ?? 0) - 1;\n if (remaining > 0) activeSessionBoards.set(key, remaining);\n else activeSessionBoards.delete(key);\n}\n\nfunction isSessionBoardActive(projectRoot: string, sessionId: string): boolean {\n return (activeSessionBoards.get(boardKey(projectRoot, sessionId)) ?? 0) > 0;\n}\n\nfunction sameColumns(columns: readonly KanbanColumn[]): boolean {\n return (\n columns.length === SESSION_KANBAN_COLUMNS.length &&\n columns.every((column, index) => column.id === SESSION_KANBAN_COLUMNS[index]?.id)\n );\n}\n\n/** Create (or migrate) the single Kanban board owned by a session. */\nexport async function ensureSessionKanbanBoard(\n projectRoot: string | undefined,\n sessionId: string,\n): Promise<KanbanBoard | null> {\n if (!projectRoot || !sessionId || process.env[MIRROR_DISABLED_ENV] === '0') return null;\n const key = boardKey(projectRoot, sessionId);\n const inFlight = boardEnsures.get(key);\n if (inFlight) return inFlight;\n\n const promise = (async () => {\n const summary = (await listBoards(projectRoot)).find((board) =>\n board.tags?.includes(sessionTag(sessionId)),\n );\n let board = summary ? await getBoard(projectRoot, summary.id) : null;\n if (!board) {\n return createBoard(projectRoot, {\n title: sessionBoardTitle(sessionId),\n description: 'Live session work: todos, tasks, and plan items.',\n tags: sessionBoardTags(sessionId),\n columns: SESSION_KANBAN_COLUMNS,\n generatedBy: `session-kanban:${sessionId}`,\n });\n }\n\n // Boards produced by the older task/plan mirrors used the generic five\n // columns. Migrate only session-owned boards; updateBoard reconciles cards\n // from Backlog into Todo while preserving Running/Preview/Done cards.\n if (!sameColumns(board.columns) || !board.tags?.includes(SESSION_BOARD_TAG)) {\n board =\n (await updateBoard(projectRoot, board.id, {\n title: sessionBoardTitle(sessionId),\n description: 'Live session work: todos, tasks, and plan items.',\n tags: [...new Set([...(board.tags ?? []), ...sessionBoardTags(sessionId)])],\n columns: SESSION_KANBAN_COLUMNS,\n })) ?? board;\n }\n return board;\n })();\n\n boardEnsures.set(key, promise);\n try {\n return await promise;\n } finally {\n boardEnsures.delete(key);\n }\n}\n\nfunction enqueueBoardWork<T>(\n projectRoot: string,\n sessionId: string,\n work: () => Promise<T>,\n): Promise<T> {\n const key = boardKey(projectRoot, sessionId);\n const previous = boardQueue.get(key) ?? Promise.resolve();\n const result = previous.catch(() => undefined).then(work);\n const tail = result.then(\n () => undefined,\n () => undefined,\n );\n boardQueue.set(key, tail);\n void tail.then(() => {\n if (boardQueue.get(key) === tail) boardQueue.delete(key);\n });\n return result;\n}\n\nasync function removeEmptySessionBoard(\n projectRoot: string,\n boardId: string,\n sessionId: string,\n): Promise<string | null> {\n return enqueueBoardWork(projectRoot, sessionId, async () => {\n if (isSessionBoardActive(projectRoot, sessionId)) return null;\n const board = await getBoard(projectRoot, boardId);\n if (!board || board.tasks.length > 0 || !isOwnedSessionBoard(board.tags)) return null;\n if (sessionIdFromTags(board.tags) !== sessionId) return null;\n return (await removeBoard(projectRoot, board.id)) ? board.id : null;\n });\n}\n\n/** Remove a particular inactive session's system-owned board when it has no cards. */\nexport async function cleanupSessionKanbanBoardIfEmpty(\n projectRoot: string | undefined,\n sessionId: string,\n): Promise<string[]> {\n if (!projectRoot || !sessionId || process.env[MIRROR_DISABLED_ENV] === '0') return [];\n if (isSessionBoardActive(projectRoot, sessionId)) return [];\n const candidates = (await listBoards(projectRoot)).filter(\n (board) =>\n board.taskCount === 0 &&\n isOwnedSessionBoard(board.tags) &&\n sessionIdFromTags(board.tags) === sessionId,\n );\n const removed = await Promise.all(\n candidates.map((board) => removeEmptySessionBoard(projectRoot, board.id, sessionId)),\n );\n return removed.filter((boardId): boardId is string => Boolean(boardId));\n}\n\n/** Prune stale empty session boards while preserving manual and live boards. */\nexport async function cleanupEmptySessionKanbanBoards(\n projectRoot: string | undefined,\n activeSessionId = '',\n): Promise<string[]> {\n if (!projectRoot || process.env[MIRROR_DISABLED_ENV] === '0') return [];\n const candidates = (await listBoards(projectRoot)).flatMap((board) => {\n const ownerSessionId = sessionIdFromTags(board.tags);\n return board.taskCount === 0 &&\n isOwnedSessionBoard(board.tags) &&\n ownerSessionId &&\n ownerSessionId !== activeSessionId &&\n !isSessionBoardActive(projectRoot, ownerSessionId)\n ? [{ boardId: board.id, sessionId: ownerSessionId }]\n : [];\n });\n const removed = await Promise.all(\n candidates.map(({ boardId, sessionId }) =>\n removeEmptySessionBoard(projectRoot, boardId, sessionId),\n ),\n );\n return removed.filter((boardId): boardId is string => Boolean(boardId));\n}\n\nasync function projectGraph(\n projectRoot: string | undefined,\n sessionId: string,\n graph: SerializedTaskGraph,\n sourceSystem: 'session-todo' | 'session-task' | 'session-plan',\n): Promise<KanbanBoard | null> {\n if (!projectRoot || !sessionId || process.env[MIRROR_DISABLED_ENV] === '0') return null;\n return enqueueBoardWork(projectRoot, sessionId, async () => {\n const board = await ensureSessionKanbanBoard(projectRoot, sessionId);\n if (!board) return null;\n const result = await syncBoardFromTaskGraph(\n projectRoot,\n board.id,\n deserializeTaskGraph(graph),\n {\n sourceSystem,\n tags: [...new Set([...(board.tags ?? []), ...sessionBoardTags(sessionId)])],\n archiveMissingTasks: true,\n includeCompletedTasks: true,\n },\n );\n return result?.board ?? null;\n });\n}\n\nexport function todoListToSerializedGraph(\n todos: readonly TodoItem[],\n sessionId: string,\n): SerializedTaskGraph {\n const nodes = todos.map((todo, index) => ({\n id: todo.id,\n title: todo.content,\n description: todo.activeForm ?? '',\n type: 'chore' as const,\n priority: 'medium' as const,\n status: todo.status,\n createdAt: index,\n updatedAt: index,\n }));\n return {\n id: `todo:${sessionId}`,\n specId: `todo:${sessionId}`,\n title: 'Session todos',\n nodes,\n edges: [],\n rootNodes: nodes.map((node) => node.id),\n createdAt: 0,\n updatedAt: 0,\n };\n}\n\nexport function taskFileToSerializedGraph(\n tasks: readonly TaskItem[],\n sessionId: string,\n): SerializedTaskGraph {\n const ids = new Set(tasks.map((task) => task.id));\n const nodes = tasks.map((task, index) => ({\n id: task.id,\n title: task.title,\n description: task.description ?? '',\n type: task.type,\n priority: task.priority,\n status: task.status,\n ...(task.assignee ? { assignee: task.assignee } : {}),\n ...(task.estimateHours !== undefined ? { estimateHours: task.estimateHours } : {}),\n createdAt: index,\n updatedAt: index,\n }));\n const edges = tasks.flatMap((task) =>\n (task.dependsOn ?? [])\n .filter((dependency) => ids.has(dependency))\n .map((dependency) => ({\n id: `${dependency}->${task.id}`,\n from: dependency,\n to: task.id,\n type: 'depends_on' as const,\n })),\n );\n const hasIncoming = new Set(edges.map((edge) => edge.to));\n const rootNodes = nodes.filter((node) => !hasIncoming.has(node.id)).map((node) => node.id);\n return {\n // Keep the historical graph id so existing mirrored task cards are reused.\n id: `session:${sessionId}`,\n specId: `session:${sessionId}`,\n title: 'Session tasks',\n nodes,\n edges,\n rootNodes: rootNodes.length ? rootNodes : nodes[0] ? [nodes[0].id] : [],\n createdAt: 0,\n updatedAt: 0,\n };\n}\n\nconst PLAN_STATUS_TO_TASK: Record<PlanItem['status'], TaskStatus> = {\n open: 'pending',\n in_progress: 'in_progress',\n done: 'completed',\n};\n\nexport function planFileToSerializedGraph(\n items: readonly PlanItem[],\n sessionId: string,\n): SerializedTaskGraph {\n const nodes = items.map((item, index) => ({\n id: item.id,\n title: item.title,\n description: item.details ?? '',\n type: 'chore' as const,\n priority: 'medium' as const,\n status: PLAN_STATUS_TO_TASK[item.status],\n createdAt: index,\n updatedAt: index,\n }));\n return {\n id: `plan:${sessionId}`,\n specId: `plan:${sessionId}`,\n title: 'Session plan',\n nodes,\n edges: [],\n rootNodes: nodes.map((node) => node.id),\n createdAt: 0,\n updatedAt: 0,\n };\n}\n\nexport function projectSessionTodosToKanban(\n projectRoot: string | undefined,\n todos: readonly TodoItem[],\n sessionId: string,\n): Promise<KanbanBoard | null> {\n return projectGraph(\n projectRoot,\n sessionId,\n todoListToSerializedGraph(todos, sessionId),\n 'session-todo',\n );\n}\n\nexport function projectSessionTasksToKanban(\n projectRoot: string | undefined,\n tasks: readonly TaskItem[],\n sessionId: string,\n): Promise<KanbanBoard | null> {\n return projectGraph(\n projectRoot,\n sessionId,\n taskFileToSerializedGraph(tasks, sessionId),\n 'session-task',\n );\n}\n\nexport function projectSessionPlanToKanban(\n projectRoot: string | undefined,\n items: readonly PlanItem[],\n sessionId: string,\n): Promise<KanbanBoard | null> {\n return projectGraph(\n projectRoot,\n sessionId,\n planFileToSerializedGraph(items, sessionId),\n 'session-plan',\n );\n}\n\nfunction fireAndForget(work: Promise<unknown>): void {\n void work.catch(() => {\n // The session files/state remain recoverable if the observational board\n // cannot be written; the next mutation or file watcher retries the mirror.\n });\n}\n\nexport function mirrorSessionTodosToKanban(\n projectRoot: string | undefined,\n todos: readonly TodoItem[],\n sessionId: string,\n): void {\n fireAndForget(projectSessionTodosToKanban(projectRoot, todos, sessionId));\n}\n\nexport function mirrorSessionTasksToKanban(\n projectRoot: string | undefined,\n tasks: readonly TaskItem[],\n sessionId: string,\n): void {\n fireAndForget(projectSessionTasksToKanban(projectRoot, tasks, sessionId));\n}\n\nexport function mirrorSessionPlanToKanban(\n projectRoot: string | undefined,\n items: readonly PlanItem[],\n sessionId: string,\n): void {\n fireAndForget(projectSessionPlanToKanban(projectRoot, items, sessionId));\n}\n\n/**\n * Bind all live session work paths to Kanban. Todo changes are observed from\n * ConversationState; plan/task sidecars are watched so slash commands, WebUI,\n * plugins, and tools all pass through the same board.\n */\nexport function attachSessionKanbanMirror(context: Context): () => void {\n const existing = bindings.get(context);\n if (existing) return existing;\n\n const attachedProjectRoot = context.projectRoot ?? '';\n let registeredSessionId = '';\n const syncActiveSessionRegistration = () => {\n if (!attachedProjectRoot) return;\n const currentSessionId = context.session?.id ?? '';\n if (currentSessionId === registeredSessionId) return;\n if (registeredSessionId) {\n releaseActiveSessionBoard(attachedProjectRoot, registeredSessionId);\n fireAndForget(cleanupSessionKanbanBoardIfEmpty(attachedProjectRoot, registeredSessionId));\n }\n registeredSessionId = currentSessionId;\n if (registeredSessionId) {\n retainActiveSessionBoard(attachedProjectRoot, registeredSessionId);\n }\n };\n syncActiveSessionRegistration();\n\n let watcher: FSWatcher | null = null;\n let watchedDir = '';\n let timer: NodeJS.Timeout | null = null;\n\n const sessionId = () => context.session?.id ?? '';\n const refreshFiles = async () => {\n const id = sessionId();\n if (!id) return;\n const planPath = context.meta['plan.path'];\n if (typeof planPath === 'string' && planPath) {\n const plan = await loadPlan(planPath);\n if (plan) await projectSessionPlanToKanban(context.projectRoot, plan.items, id);\n }\n const taskPath = context.meta['task.path'];\n if (typeof taskPath === 'string' && taskPath) {\n const tasks = await loadTasks(taskPath);\n if (tasks) await projectSessionTasksToKanban(context.projectRoot, tasks.tasks, id);\n }\n };\n\n const configureWatcher = () => {\n const planPath = context.meta['plan.path'];\n const taskPath = context.meta['task.path'];\n const candidate =\n typeof planPath === 'string' && planPath\n ? dirname(planPath)\n : typeof taskPath === 'string' && taskPath\n ? dirname(taskPath)\n : '';\n if (!candidate || candidate === watchedDir) return;\n watcher?.close();\n watcher = null;\n watchedDir = candidate;\n try {\n watcher = watch(candidate, { persistent: false }, (_event, filename) => {\n const name = filename?.toString();\n const currentPlanPath = context.meta['plan.path'];\n const currentTaskPath = context.meta['task.path'];\n const planName = typeof currentPlanPath === 'string' ? basename(currentPlanPath) : '';\n const taskName = typeof currentTaskPath === 'string' ? basename(currentTaskPath) : '';\n if (name && name !== planName && name !== taskName) return;\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => fireAndForget(refreshFiles()), 60);\n });\n watcher.on('error', () => watcher?.close());\n } catch {\n // The session directory can briefly disappear during project/session\n // switches; the next meta update re-attempts the binding.\n watcher = null;\n watchedDir = '';\n }\n };\n\n const unsubscribe = context.state.onChange((change) => {\n if (change.kind === 'todos_replaced' && !suppressedTodoMirrors.has(context)) {\n // ConversationState auto-clears an all-done tactical list. Project the\n // pre-clear completion snapshot so every card reaches Done atomically.\n mirrorSessionTodosToKanban(\n context.projectRoot,\n change.completedSnapshot ?? change.todos,\n sessionId(),\n );\n return;\n }\n if (change.kind === 'meta_set' && (change.key === 'plan.path' || change.key === 'task.path')) {\n syncActiveSessionRegistration();\n configureWatcher();\n fireAndForget(ensureSessionKanbanBoard(context.projectRoot, sessionId()));\n fireAndForget(refreshFiles());\n }\n });\n\n configureWatcher();\n\n const detach = () => {\n unsubscribe();\n if (timer) clearTimeout(timer);\n watcher?.close();\n bindings.delete(context);\n if (attachedProjectRoot && registeredSessionId) {\n releaseActiveSessionBoard(attachedProjectRoot, registeredSessionId);\n fireAndForget(cleanupSessionKanbanBoardIfEmpty(attachedProjectRoot, registeredSessionId));\n registeredSessionId = '';\n }\n };\n bindings.set(context, detach);\n return detach;\n}\n\n/** Fully hydrate a session board before a host announces the session as ready. */\nexport async function hydrateSessionKanban(context: Context): Promise<KanbanBoard | null> {\n const id = context.session?.id ?? '';\n if (!id) return null;\n await cleanupEmptySessionKanbanBoards(context.projectRoot, id);\n let board = await ensureSessionKanbanBoard(context.projectRoot, id);\n if (context.todos.length) {\n board = await projectSessionTodosToKanban(context.projectRoot, context.todos, id);\n }\n const planPath = context.meta['plan.path'];\n if (typeof planPath === 'string' && planPath) {\n const plan = await loadPlan(planPath);\n if (plan) board = await projectSessionPlanToKanban(context.projectRoot, plan.items, id);\n }\n const taskPath = context.meta['task.path'];\n if (typeof taskPath === 'string' && taskPath) {\n const tasks = await loadTasks(taskPath);\n if (tasks) board = await projectSessionTasksToKanban(context.projectRoot, tasks.tasks, id);\n }\n return board;\n}\n\nexport interface SessionKanbanSourceUpdate {\n source: 'todo' | 'task' | 'plan' | null;\n todos?: TodoItem[] | undefined;\n tasks?: TaskFile | undefined;\n plan?: PlanFile | undefined;\n}\n\nfunction sourceStatus(task: KanbanTask): TaskStatus {\n if (task.status === 'completed') return 'completed';\n if (task.status === 'in_progress') return 'in_progress';\n if (task.status === 'review') return 'review';\n if (task.status === 'blocked') return 'blocked';\n if (task.status === 'failed') return 'failed';\n return 'pending';\n}\n\n/** Reflect a TUI/WebUI Kanban card edit back to its originating work list. */\nexport async function applySessionKanbanTaskToSource(\n context: Context,\n task: KanbanTask,\n options: { remove?: boolean | undefined } = {},\n): Promise<SessionKanbanSourceUpdate> {\n const originId = task.origin?.taskId;\n const graphId = task.origin?.graphId ?? '';\n if (!originId) return { source: null };\n\n if (task.origin?.system === 'session-todo' || graphId.startsWith('todo:')) {\n const next = options.remove\n ? context.todos.filter((todo) => todo.id !== originId)\n : context.todos.map((todo) =>\n todo.id === originId\n ? {\n ...todo,\n content: task.title,\n status:\n sourceStatus(task) === 'completed'\n ? ('completed' as const)\n : sourceStatus(task) === 'in_progress' || sourceStatus(task) === 'review'\n ? ('in_progress' as const)\n : ('pending' as const),\n }\n : todo,\n );\n suppressedTodoMirrors.add(context);\n try {\n context.state.replaceTodos(next);\n } finally {\n suppressedTodoMirrors.delete(context);\n }\n return { source: 'todo', todos: [...context.todos] };\n }\n\n const id = context.session?.id ?? '';\n if (task.origin?.system === 'session-plan' || graphId.startsWith('plan:')) {\n const planPath = context.meta['plan.path'];\n if (typeof planPath !== 'string' || !planPath) return { source: 'plan' };\n const plan = await mutatePlan(planPath, id, (file) => ({\n ...file,\n updatedAt: new Date().toISOString(),\n items: options.remove\n ? file.items.filter((item) => item.id !== originId)\n : file.items.map((item) =>\n item.id === originId\n ? {\n ...item,\n title: task.title,\n details: task.description,\n status:\n task.status === 'completed'\n ? ('done' as const)\n : task.status === 'in_progress' || task.status === 'review'\n ? ('in_progress' as const)\n : ('open' as const),\n updatedAt: new Date().toISOString(),\n }\n : item,\n ),\n }));\n return { source: 'plan', plan };\n }\n\n if (\n task.origin?.system === 'session-task' ||\n task.origin?.system === 'session' ||\n graphId.startsWith('session:')\n ) {\n const taskPath = context.meta['task.path'];\n if (typeof taskPath !== 'string' || !taskPath) return { source: 'task' };\n const tasks = await mutateTasks(taskPath, id, (file) => ({\n ...file,\n tasks: options.remove\n ? file.tasks.filter((item) => item.id !== originId)\n : file.tasks.map((item) =>\n item.id === originId\n ? {\n ...item,\n title: task.title,\n description: task.description,\n status: sourceStatus(task),\n updatedAt: new Date().toISOString(),\n }\n : item,\n ),\n }));\n return { source: 'task', tasks };\n }\n\n return { source: null };\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["deserializeTaskGraph", "loadTasks", "createBoard", "getBoard", "listBoards", "removeBoard", "syncBoardFromTaskGraph", "updateBoard", "listBoards", "createBoard", "updateBoard", "removeBoard", "taskInput", "getBoard", "deserializeTaskGraph", "syncBoardFromTaskGraph", "loadTasks"]
7
7
  }
@@ -19,6 +19,10 @@
19
19
  * Supported assistant-output format:
20
20
  * <nextsteps> (canonical XML tag format)
21
21
  *
22
+ * The parser also tolerates attributes on the opening tag so malformed model
23
+ * output such as `<nextsteps auto="true">` does not leak into the UI. Opening
24
+ * tag attributes are ignored; `auto="true"` has meaning only on the first item.
25
+ *
22
26
  * This module is BROWSER-SAFE — no Node-only imports — so it is safe to import
23
27
  * from Vite-bundled WebUI as well as Node-based CLI/TUI. Mirrors the proven
24
28
  * `tool-summary` / `tool-icons` extraction pattern (PRs #236 / #237 / #238).
@@ -26,7 +30,7 @@
26
30
  export interface ParsedNextStep {
27
31
  index: number;
28
32
  text: string;
29
- /** Whether this item has auto="true" attribute for YOLO+auto autonomy mode. */
33
+ /** Whether the first item has auto="true" for YOLO+auto autonomy mode. */
30
34
  auto?: boolean;
31
35
  }
32
36
  export interface ParseNextStepsResult {
@@ -39,7 +43,7 @@ export interface ParseNextStepsResult {
39
43
  * Used by entry.tsx to strip suggestions from the rendered message body.
40
44
  */
41
45
  stripped: string;
42
- /** Flat string array texts of items with auto="true" attribute only. */
46
+ /** The first item's text when it has auto="true"; otherwise empty. */
43
47
  autoTexts: string[];
44
48
  }
45
49
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"next-steps.d.ts","sourceRoot":"","sources":["../src/next-steps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,iEAAiE;IACjE,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,oEAAoE;IACpE,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB,0EAA0E;IAC1E,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAeD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,MAAM,UAAQ,EACd,cAAc,UAAO,GACpB,oBAAoB,CAKtB;AAoKD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMxD"}
1
+ {"version":3,"file":"next-steps.d.ts","sourceRoot":"","sources":["../src/next-steps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAIH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,iEAAiE;IACjE,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,oEAAoE;IACpE,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB,sEAAsE;IACtE,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAoBD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,MAAM,UAAQ,EACd,cAAc,UAAO,GACpB,oBAAoB,CAKtB;AAuKD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMxD"}
@@ -1,5 +1,5 @@
1
1
  // src/next-steps.ts
2
- var NEXT_STEPS_TAG_RE = /<nextsteps>\s*\n+/i;
2
+ var NEXT_STEPS_TAG_RE = /<nextsteps\b[^>]*>\s*\n+/i;
3
3
  var ITEM_RE = /^(?:(\d+)[.)]\s*|[-*•]\s*)(.+?)(\s+auto="true")?$/;
4
4
  var MAX_STEPS = 6;
5
5
  function parseNextSteps(content, strict = false, requireHeading = true) {
@@ -22,7 +22,6 @@ function parseRawNumbered(content) {
22
22
  if (!m) continue;
23
23
  const numPart = m[1];
24
24
  const text = m[2].trim();
25
- const hasAuto = !!m[3];
26
25
  let index;
27
26
  if (numPart !== void 0) {
28
27
  index = Number.parseInt(numPart, 10);
@@ -31,6 +30,7 @@ function parseRawNumbered(content) {
31
30
  }
32
31
  if (seenNumbers.has(index)) continue;
33
32
  seenNumbers.add(index);
33
+ const hasAuto = !!m[3] && steps.length === 0 && index === 1;
34
34
  pushStep(steps, index, text, hasAuto);
35
35
  if (steps.length >= MAX_STEPS) break;
36
36
  }
@@ -58,7 +58,6 @@ function parseWithHeading(content, _strict) {
58
58
  if (!m) break;
59
59
  const numPart = m[1];
60
60
  const text = m[2].trim();
61
- const hasAuto = !!m[3];
62
61
  let index;
63
62
  if (numPart !== void 0) {
64
63
  index = Number.parseInt(numPart, 10);
@@ -67,6 +66,7 @@ function parseWithHeading(content, _strict) {
67
66
  }
68
67
  if (seenNumbers.has(index)) continue;
69
68
  seenNumbers.add(index);
69
+ const hasAuto = !!m[3] && steps.length === 0 && index === 1;
70
70
  pushStep(steps, index, text, hasAuto);
71
71
  if (steps.length >= MAX_STEPS) break;
72
72
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/next-steps.ts"],
4
- "sourcesContent": ["/**\n * Canonical `<nextsteps>` block parser \u2014 the single source of truth shared by\n * the TUI history renderer, the CLI REPL suggestion store, the CLI /suggest\n * subagent output, and the WebUI MessageBubble/NextStepsBar.\n *\n * Three code paths feed into the parser:\n * 1. TUI rendering \u2014 entry.tsx parses only \"<nextsteps>\" from assistant output\n * 2. REPL store \u2014 repl.ts parses only \"<nextsteps>\" from final agent output\n * 3. /suggest output \u2014 suggest.ts parses LLM-generated numbered lists (raw mode)\n *\n * Heading mode (`requireHeading = true`, the default):\n * Assistant-output paths accept only balanced <nextsteps>...</nextsteps> blocks.\n * Loose headings like \"Next steps:\" are intentionally ignored so `/next` only\n * activates for the canonical machine-readable format.\n *\n * Raw mode (`requireHeading = false`):\n * Parses numbered/bullet items from anywhere in text (subagent /suggest output).\n *\n * Supported assistant-output format:\n * <nextsteps> (canonical XML tag format)\n *\n * This module is BROWSER-SAFE \u2014 no Node-only imports \u2014 so it is safe to import\n * from Vite-bundled WebUI as well as Node-based CLI/TUI. Mirrors the proven\n * `tool-summary` / `tool-icons` extraction pattern (PRs #236 / #237 / #238).\n */\n\n// \u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface ParsedNextStep {\n index: number;\n text: string;\n /** Whether this item has auto=\"true\" attribute for YOLO+auto autonomy mode. */\n auto?: boolean;\n}\n\nexport interface ParseNextStepsResult {\n /** Matched steps with their original index and stripped text. */\n steps: ParsedNextStep[];\n /** Flat string array \u2014 what gets stored in the suggestion store. */\n texts: string[];\n /**\n * Content with the entire canonical \"<nextsteps>\" block removed.\n * Used by entry.tsx to strip suggestions from the rendered message body.\n */\n stripped: string;\n /** Flat string array \u2014 texts of items with auto=\"true\" attribute only. */\n autoTexts: string[];\n}\n\n// \u2500\u2500 Patterns \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Matches the canonical <nextsteps> tag before numbered items. */\nconst NEXT_STEPS_TAG_RE = /<nextsteps>\\s*\\n+/i;\n\n/** Matches an item line: \"1. text\", \"1) text\", \"- text\", \"* text\". */\n/** Also captures optional auto=\"true\" attribute at the end. */\nconst ITEM_RE = /^(?:(\\d+)[.)]\\s*|[-*\u2022]\\s*)(.+?)(\\s+auto=\"true\")?$/;\n\nconst MAX_STEPS = 6;\n\n// \u2500\u2500 Core parser \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Parse canonical \"<nextsteps>\" blocks from assistant output (or raw numbered lines).\n *\n * @param content \u2014 raw assistant message text or subagent output\n * @param strict \u2014 retained for compatibility; assistant-output paths always require the canonical XML tag.\n * @param requireHeading \u2014 when true, a canonical XML tag must precede the item list.\n * when false, numbered/bullet items are parsed from anywhere in text\n * (used by /suggest subagent output which has no heading).\n */\nexport function parseNextSteps(\n content: string,\n strict = false,\n requireHeading = true,\n): ParseNextStepsResult {\n if (requireHeading) {\n return parseWithHeading(content, strict);\n }\n return parseRawNumbered(content);\n}\n\n/** Push a step into the array, omitting `auto` when false (cleaner shape, matches WebUI parity). */\nfunction pushStep(\n steps: ParsedNextStep[],\n index: number,\n text: string,\n hasAuto: boolean,\n): void {\n steps.push(hasAuto ? { index, text, auto: true } : { index, text });\n}\n\n/** Parse numbered/bullet items from raw text without a heading. */\nfunction parseRawNumbered(content: string): ParseNextStepsResult {\n const lines = content.split('\\n');\n const steps: ParsedNextStep[] = [];\n const seenNumbers = new Set<number>();\n\n for (const rawLine of lines) {\n const line = rawLine.trim();\n if (!line) continue;\n\n const m = ITEM_RE.exec(line);\n if (!m) continue; // skip non-item lines in raw mode\n\n const numPart = m[1];\n const text = m[2]!.trim();\n const hasAuto = !!m[3]; // auto=\"true\" captured in group 3\n let index: number;\n\n if (numPart !== undefined) {\n index = Number.parseInt(numPart, 10);\n } else {\n index = steps.length + 1; // bullet items get sequential indices\n }\n\n if (seenNumbers.has(index)) continue;\n seenNumbers.add(index);\n pushStep(steps, index, text, hasAuto);\n\n if (steps.length >= MAX_STEPS) break;\n }\n\n return {\n steps,\n texts: steps.map((s) => s.text),\n stripped: content,\n autoTexts: steps.filter((s) => s.auto).map((s) => s.text),\n };\n}\n\n/** Parse a heading + item block (the main assistant-message path). */\nfunction parseWithHeading(content: string, _strict: boolean): ParseNextStepsResult {\n const headingMatch = NEXT_STEPS_TAG_RE.exec(content);\n\n if (!headingMatch) {\n return { steps: [], texts: [], stripped: content, autoTexts: [] };\n }\n\n const headingEnd = headingMatch.index + headingMatch[0]!.length;\n const afterHeading = content.slice(headingEnd);\n const lines = afterHeading.split('\\n');\n const steps: ParsedNextStep[] = [];\n const seenNumbers = new Set<number>();\n\n for (const rawLine of lines) {\n const line = rawLine.trim();\n if (!line) continue;\n\n const m = ITEM_RE.exec(line);\n if (!m) break; // non-item line \u2014 block ends\n\n const numPart = m[1];\n const text = m[2]!.trim();\n const hasAuto = !!m[3]; // auto=\"true\" captured in group 3\n let index: number;\n\n if (numPart !== undefined) {\n index = Number.parseInt(numPart, 10);\n } else {\n index = steps.length + 1;\n }\n\n if (seenNumbers.has(index)) continue;\n seenNumbers.add(index);\n pushStep(steps, index, text, hasAuto);\n\n if (steps.length >= MAX_STEPS) break;\n }\n\n if (steps.length === 0) {\n return { steps: [], texts: [], stripped: content, autoTexts: [] };\n }\n\n // Require a closing tag. Malformed XML is rejected so raw text remains\n // visible instead of being partially consumed as automation input.\n if (!afterHeading.includes('</nextsteps>')) {\n return { steps: [], texts: [], stripped: content, autoTexts: [] };\n }\n\n const texts = steps.map((s) => s.text);\n const autoTexts = steps.filter((s) => s.auto).map((s) => s.text);\n\n // Strip the entire XML block from the content. `blockEnd` is the LENGTH of\n // that block, so `content.slice(blockStart + blockEnd)` is the rest of the content.\n const blockStart = headingMatch.index;\n const blockEnd = headingMatch[0]!.length + findBlockEnd(afterHeading, steps.length);\n const stripped =\n (content.slice(0, blockStart) + content.slice(blockStart + blockEnd))\n .replace(/\\n{3,}/g, '\\n\\n')\n .trim();\n\n return { steps, texts, stripped, autoTexts };\n}\n\n/**\n * Find the byte offset in `afterHeading` where the block ends.\n *\n * The block to strip is the items (one per line) plus the `</nextsteps>`\n * closing tag (and the trailing newline after it).\n *\n * Returns the byte offset of the first character AFTER the block. The\n * caller's `content.slice(0, blockStart) + content.slice(blockStart + offset)`\n * then produces the stripped content.\n *\n * Walks line-by-line. Stops at the first non-item line, the closing XML\n * tag, or the end of the input \u2014 whichever comes first.\n */\nfunction findBlockEnd(afterHeading: string, stepCount: number): number {\n // Fast path: if the block is the <nextsteps> XML form, find the closing\n // tag and return its end (consuming the tag + trailing newline).\n const closeIdx = afterHeading.indexOf('</nextsteps>');\n if (closeIdx !== -1) {\n let end = closeIdx + '</nextsteps>'.length;\n if (afterHeading[end] === '\\n') end += 1;\n return end;\n }\n\n // Defensive fallback for malformed input that reached this helper without a\n // closing tag. The caller rejects such input before using the stripped text.\n const lines = afterHeading.split('\\n');\n let consumed = 0;\n let found = 0;\n\n for (const rawLine of lines) {\n const line = rawLine.trim();\n if (!line) break; // blank line ends the block\n\n const m = ITEM_RE.exec(line);\n if (!m) break; // non-item line ends the block\n\n consumed += rawLine.length + 1; // +1 for the \\n separator\n found++;\n if (found >= stepCount) {\n // Don't include the trailing newline of the last item \u2014 the slice\n // logic in the caller handles whitespace cleanup.\n consumed -= 1;\n break;\n }\n }\n\n return consumed;\n}\n\n/**\n * Strip <nextsteps>...</nextsteps> blocks from subagent output text.\n * Subagent results should not contain suggestion blocks \u2014 those belong to\n * the main assistant's output. This prevents raw XML tags from appearing\n * as literal text in the fleet panel.\n *\n * Also strips the legacy `<next_steps>` spelling that older persisted\n * subagent output may contain (WebUI parity).\n */\nexport function stripNextStepsBlock(text: string): string {\n return text\n .replace(/<next_?steps\\b[^>]*>[\\s\\S]*?<\\/next_?steps>/gi, '')\n .replace(/<next_?steps\\b[^>]*\\/?>/gi, '')\n .replace(/\\n{3,}/g, '\\n\\n')\n .trim();\n}"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Canonical `<nextsteps>` block parser \u2014 the single source of truth shared by\n * the TUI history renderer, the CLI REPL suggestion store, the CLI /suggest\n * subagent output, and the WebUI MessageBubble/NextStepsBar.\n *\n * Three code paths feed into the parser:\n * 1. TUI rendering \u2014 entry.tsx parses only \"<nextsteps>\" from assistant output\n * 2. REPL store \u2014 repl.ts parses only \"<nextsteps>\" from final agent output\n * 3. /suggest output \u2014 suggest.ts parses LLM-generated numbered lists (raw mode)\n *\n * Heading mode (`requireHeading = true`, the default):\n * Assistant-output paths accept only balanced <nextsteps>...</nextsteps> blocks.\n * Loose headings like \"Next steps:\" are intentionally ignored so `/next` only\n * activates for the canonical machine-readable format.\n *\n * Raw mode (`requireHeading = false`):\n * Parses numbered/bullet items from anywhere in text (subagent /suggest output).\n *\n * Supported assistant-output format:\n * <nextsteps> (canonical XML tag format)\n *\n * The parser also tolerates attributes on the opening tag so malformed model\n * output such as `<nextsteps auto=\"true\">` does not leak into the UI. Opening\n * tag attributes are ignored; `auto=\"true\"` has meaning only on the first item.\n *\n * This module is BROWSER-SAFE \u2014 no Node-only imports \u2014 so it is safe to import\n * from Vite-bundled WebUI as well as Node-based CLI/TUI. Mirrors the proven\n * `tool-summary` / `tool-icons` extraction pattern (PRs #236 / #237 / #238).\n */\n\n// \u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface ParsedNextStep {\n index: number;\n text: string;\n /** Whether the first item has auto=\"true\" for YOLO+auto autonomy mode. */\n auto?: boolean;\n}\n\nexport interface ParseNextStepsResult {\n /** Matched steps with their original index and stripped text. */\n steps: ParsedNextStep[];\n /** Flat string array \u2014 what gets stored in the suggestion store. */\n texts: string[];\n /**\n * Content with the entire canonical \"<nextsteps>\" block removed.\n * Used by entry.tsx to strip suggestions from the rendered message body.\n */\n stripped: string;\n /** The first item's text when it has auto=\"true\"; otherwise empty. */\n autoTexts: string[];\n}\n\n// \u2500\u2500 Patterns \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Matches the canonical <nextsteps> tag before numbered items.\n *\n * Attributes are accepted defensively because models occasionally attach the\n * item-only `auto=\"true\"` marker to this tag. They never affect parser state.\n */\nconst NEXT_STEPS_TAG_RE = /<nextsteps\\b[^>]*>\\s*\\n+/i;\n\n/** Matches an item line: \"1. text\", \"1) text\", \"- text\", \"* text\". */\n/** Also captures optional auto=\"true\" attribute at the end. */\nconst ITEM_RE = /^(?:(\\d+)[.)]\\s*|[-*\u2022]\\s*)(.+?)(\\s+auto=\"true\")?$/;\n\nconst MAX_STEPS = 6;\n\n// \u2500\u2500 Core parser \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Parse canonical \"<nextsteps>\" blocks from assistant output (or raw numbered lines).\n *\n * @param content \u2014 raw assistant message text or subagent output\n * @param strict \u2014 retained for compatibility; assistant-output paths always require the canonical XML tag.\n * @param requireHeading \u2014 when true, a canonical XML tag must precede the item list.\n * when false, numbered/bullet items are parsed from anywhere in text\n * (used by /suggest subagent output which has no heading).\n */\nexport function parseNextSteps(\n content: string,\n strict = false,\n requireHeading = true,\n): ParseNextStepsResult {\n if (requireHeading) {\n return parseWithHeading(content, strict);\n }\n return parseRawNumbered(content);\n}\n\n/** Push a step into the array, omitting `auto` when false (cleaner shape, matches WebUI parity). */\nfunction pushStep(\n steps: ParsedNextStep[],\n index: number,\n text: string,\n hasAuto: boolean,\n): void {\n steps.push(hasAuto ? { index, text, auto: true } : { index, text });\n}\n\n/** Parse numbered/bullet items from raw text without a heading. */\nfunction parseRawNumbered(content: string): ParseNextStepsResult {\n const lines = content.split('\\n');\n const steps: ParsedNextStep[] = [];\n const seenNumbers = new Set<number>();\n\n for (const rawLine of lines) {\n const line = rawLine.trim();\n if (!line) continue;\n\n const m = ITEM_RE.exec(line);\n if (!m) continue; // skip non-item lines in raw mode\n\n const numPart = m[1];\n const text = m[2]!.trim();\n let index: number;\n\n if (numPart !== undefined) {\n index = Number.parseInt(numPart, 10);\n } else {\n index = steps.length + 1; // bullet items get sequential indices\n }\n\n if (seenNumbers.has(index)) continue;\n seenNumbers.add(index);\n // Auto-submit is deliberately restricted to the first accepted item.\n // Later misplaced markers are stripped from display text but ignored.\n const hasAuto = !!m[3] && steps.length === 0 && index === 1;\n pushStep(steps, index, text, hasAuto);\n\n if (steps.length >= MAX_STEPS) break;\n }\n\n return {\n steps,\n texts: steps.map((s) => s.text),\n stripped: content,\n autoTexts: steps.filter((s) => s.auto).map((s) => s.text),\n };\n}\n\n/** Parse a heading + item block (the main assistant-message path). */\nfunction parseWithHeading(content: string, _strict: boolean): ParseNextStepsResult {\n const headingMatch = NEXT_STEPS_TAG_RE.exec(content);\n\n if (!headingMatch) {\n return { steps: [], texts: [], stripped: content, autoTexts: [] };\n }\n\n const headingEnd = headingMatch.index + headingMatch[0]!.length;\n const afterHeading = content.slice(headingEnd);\n const lines = afterHeading.split('\\n');\n const steps: ParsedNextStep[] = [];\n const seenNumbers = new Set<number>();\n\n for (const rawLine of lines) {\n const line = rawLine.trim();\n if (!line) continue;\n\n const m = ITEM_RE.exec(line);\n if (!m) break; // non-item line \u2014 block ends\n\n const numPart = m[1];\n const text = m[2]!.trim();\n let index: number;\n\n if (numPart !== undefined) {\n index = Number.parseInt(numPart, 10);\n } else {\n index = steps.length + 1;\n }\n\n if (seenNumbers.has(index)) continue;\n seenNumbers.add(index);\n // Only the first accepted item may opt into unattended auto-submit.\n const hasAuto = !!m[3] && steps.length === 0 && index === 1;\n pushStep(steps, index, text, hasAuto);\n\n if (steps.length >= MAX_STEPS) break;\n }\n\n if (steps.length === 0) {\n return { steps: [], texts: [], stripped: content, autoTexts: [] };\n }\n\n // Require a closing tag. Malformed XML is rejected so raw text remains\n // visible instead of being partially consumed as automation input.\n if (!afterHeading.includes('</nextsteps>')) {\n return { steps: [], texts: [], stripped: content, autoTexts: [] };\n }\n\n const texts = steps.map((s) => s.text);\n const autoTexts = steps.filter((s) => s.auto).map((s) => s.text);\n\n // Strip the entire XML block from the content. `blockEnd` is the LENGTH of\n // that block, so `content.slice(blockStart + blockEnd)` is the rest of the content.\n const blockStart = headingMatch.index;\n const blockEnd = headingMatch[0]!.length + findBlockEnd(afterHeading, steps.length);\n const stripped =\n (content.slice(0, blockStart) + content.slice(blockStart + blockEnd))\n .replace(/\\n{3,}/g, '\\n\\n')\n .trim();\n\n return { steps, texts, stripped, autoTexts };\n}\n\n/**\n * Find the byte offset in `afterHeading` where the block ends.\n *\n * The block to strip is the items (one per line) plus the `</nextsteps>`\n * closing tag (and the trailing newline after it).\n *\n * Returns the byte offset of the first character AFTER the block. The\n * caller's `content.slice(0, blockStart) + content.slice(blockStart + offset)`\n * then produces the stripped content.\n *\n * Walks line-by-line. Stops at the first non-item line, the closing XML\n * tag, or the end of the input \u2014 whichever comes first.\n */\nfunction findBlockEnd(afterHeading: string, stepCount: number): number {\n // Fast path: if the block is the <nextsteps> XML form, find the closing\n // tag and return its end (consuming the tag + trailing newline).\n const closeIdx = afterHeading.indexOf('</nextsteps>');\n if (closeIdx !== -1) {\n let end = closeIdx + '</nextsteps>'.length;\n if (afterHeading[end] === '\\n') end += 1;\n return end;\n }\n\n // Defensive fallback for malformed input that reached this helper without a\n // closing tag. The caller rejects such input before using the stripped text.\n const lines = afterHeading.split('\\n');\n let consumed = 0;\n let found = 0;\n\n for (const rawLine of lines) {\n const line = rawLine.trim();\n if (!line) break; // blank line ends the block\n\n const m = ITEM_RE.exec(line);\n if (!m) break; // non-item line ends the block\n\n consumed += rawLine.length + 1; // +1 for the \\n separator\n found++;\n if (found >= stepCount) {\n // Don't include the trailing newline of the last item \u2014 the slice\n // logic in the caller handles whitespace cleanup.\n consumed -= 1;\n break;\n }\n }\n\n return consumed;\n}\n\n/**\n * Strip <nextsteps>...</nextsteps> blocks from subagent output text.\n * Subagent results should not contain suggestion blocks \u2014 those belong to\n * the main assistant's output. This prevents raw XML tags from appearing\n * as literal text in the fleet panel.\n *\n * Also strips the legacy `<next_steps>` spelling that older persisted\n * subagent output may contain (WebUI parity).\n */\nexport function stripNextStepsBlock(text: string): string {\n return text\n .replace(/<next_?steps\\b[^>]*>[\\s\\S]*?<\\/next_?steps>/gi, '')\n .replace(/<next_?steps\\b[^>]*\\/?>/gi, '')\n .replace(/\\n{3,}/g, '\\n\\n')\n .trim();\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }