kanban 0.1.19 → 0.1.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -46,7 +46,7 @@ kanban
46
46
  Run this from the root of any git repo. Kanban will detect your installed CLI agent and launch a local running webserver in your browser. No account or setup required, it works right out of the box.
47
47
 
48
48
  ### 2. Create tasks
49
- Create a task card manually, or open the built-in terminal (<kbd>⌘</kbd> + <kbd>J</kbd>) and ask your agent to break work down into tasks for you. A `kanban` skill is automatically added to your CLI agent so it knows how to create, edit, start, and link tasks on your kanban board. Use `/kanban` or `$kanban`, or simply ask your agent to "add tasks..."
49
+ Create a task card manually, or open the built-in terminal (<kbd>⌘</kbd> + <kbd>J</kbd>) and ask your agent to break work down into tasks for you. A `kanban` skill is automatically added to your CLI agent so it knows how to create, edit, start, and link tasks on your kanban board. Use `/kanban` or `$kanban`, or simply ask your agent to "add tasks to kanban..."
50
50
 
51
51
  ### 3. Link and automate
52
52
  <kbd>⌘</kbd> + click a card to link it to another task. When a card is completed and moved to trash, linked tasks auto-start. Combine with auto-commit for fully autonomous dependency chains: one task completes → commits → kicks off the next → repeat. It’s a pretty magical experience asking your agent to decompose a big task into subtasks that auto-commit - he’ll cleverly do it in a way that parallelizes for maximum efficiency and links tasks together for end-to-end autonomy.
@@ -46,7 +46,7 @@ export function renderKanbanSkillMarkdown(commandPrefix) {
46
46
  const kanbanCommand = commandPrefix.trim() || DEFAULT_COMMAND_PREFIX;
47
47
  return `---
48
48
  name: kanban
49
- description: Manage tasks on the user's Kanban, a tool for orchestrating agents in worktrees. Use when the user asks to create tasks, add tasks, make multiple tasks, break work down into tasks, split work into tasks, decompose work into tasks, turn work into Kanban tasks, or manage existing Kanban task dependencies. Also use when the user vaguely asks to add or create tasks without specifically mentioning Kanban -- if they say things like "add some tasks", "create a few tasks for this", "make tasks for these changes", or any generic task creation request, default to using Kanban.
49
+ description: Manage tasks on the user's Kanban, a tool for orchestrating coding agents in worktrees via a kanban board. This skill helps you create, edit, link, and start tasks using the kanban CLI. The user first launches kanban with e.g. npx kanban, then may ask you to help 'add tasks to kanban' or something to that effect (e.g. link / port over / break work down / split into kanban tasks). Only use this skill when the user mentions kanban.
50
50
  ---
51
51
 
52
52
  # Kanban
@@ -1 +1 @@
1
- {"version":3,"file":"kanban-skill.js","sourceRoot":"","sources":["../../src/skills/kanban-skill.ts"],"names":[],"mappings":"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","sourcesContent":["import { realpathSync } from \"node:fs\";\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nimport { AutoUpdatePackageManager, detectAutoUpdateInstallation } from \"../update/auto-update.js\";\n\nconst SKILL_NAME = \"kanban\";\nconst DEFAULT_COMMAND_PREFIX = \"kanban\";\n\nexport interface ResolveKanbanSkillCommandPrefixOptions {\n\tcurrentVersion: string;\n\targv?: string[];\n\tcwd?: string;\n\tresolveRealPath?: (path: string) => string;\n}\n\nexport function resolveKanbanSkillCommandPrefix(options: ResolveKanbanSkillCommandPrefixOptions): string {\n\tconst argv = options.argv ?? process.argv;\n\tconst entrypointArg = argv[1];\n\tif (!entrypointArg) {\n\t\treturn DEFAULT_COMMAND_PREFIX;\n\t}\n\n\tconst resolveRealPath = options.resolveRealPath ?? realpathSync;\n\tlet entrypointPath: string;\n\ttry {\n\t\tentrypointPath = resolveRealPath(entrypointArg);\n\t} catch {\n\t\treturn DEFAULT_COMMAND_PREFIX;\n\t}\n\n\tconst installation = detectAutoUpdateInstallation({\n\t\tcurrentVersion: options.currentVersion,\n\t\tpackageName: \"kanban\",\n\t\tentrypointPath,\n\t\tcwd: options.cwd ?? process.cwd(),\n\t});\n\n\tif (installation.updateTiming !== \"shutdown\") {\n\t\treturn DEFAULT_COMMAND_PREFIX;\n\t}\n\n\tif (installation.packageManager === AutoUpdatePackageManager.NPX) {\n\t\treturn \"npx -y kanban\";\n\t}\n\tif (installation.packageManager === AutoUpdatePackageManager.PNPM) {\n\t\treturn \"pnpm dlx kanban\";\n\t}\n\tif (installation.packageManager === AutoUpdatePackageManager.YARN) {\n\t\treturn \"yarn dlx kanban\";\n\t}\n\tif (installation.packageManager === AutoUpdatePackageManager.BUN) {\n\t\treturn \"bun x kanban\";\n\t}\n\n\treturn DEFAULT_COMMAND_PREFIX;\n}\n\nexport function renderKanbanSkillMarkdown(commandPrefix: string): string {\n\tconst kanbanCommand = commandPrefix.trim() || DEFAULT_COMMAND_PREFIX;\n\treturn `---\nname: kanban\ndescription: Manage tasks on the user's Kanban, a tool for orchestrating agents in worktrees. Use when the user asks to create tasks, add tasks, make multiple tasks, break work down into tasks, split work into tasks, decompose work into tasks, turn work into Kanban tasks, or manage existing Kanban task dependencies. Also use when the user vaguely asks to add or create tasks without specifically mentioning Kanban -- if they say things like \"add some tasks\", \"create a few tasks for this\", \"make tasks for these changes\", or any generic task creation request, default to using Kanban.\n---\n\n# Kanban\n\nKanban is a CLI tool for orchestrating multiple coding agents working on tasks in parallel on a kanban board. It manages git worktrees automatically so that each task can run a dedicated CLI agent in its own worktree.\n\n- If the user asks to add tasks to kb, ask kb, kanban, or says add tasks without other context, they likely want to add tasks in Kanban. This includes phrases like \"create tasks\", \"make 3 tasks\", \"add a task\", \"break down into tasks\", \"split into tasks\", \"decompose into tasks\", \"turn into tasks\", etc.\n- Kanban also supports linking tasks. Linking is useful both for parallelization and for dependencies: when work is easy to decompose into multiple pieces that can be done in parallel, link multiple backlog tasks to the same dependency so they all become ready to start once that dependency finishes; when one piece of work depends on another, use links to represent that follow-on dependency. A link requires at least one backlog task, and when the linked review task is moved to trash, that backlog task becomes ready to start.\n- Tasks can also enable automatic review actions: auto-commit, auto-open-pr, or auto-move-to-trash once completed, sending the task to trash and kicking off any linked tasks.\n- There is a special case where the user may create a Kanban task to create new Kanban tasks. If the current working directory contains .kanban/worktrees/ in its path, you are running inside an ephemeral Kanban worktree. In this case, pass the main worktree path with \\`--project-path\\` so the new tasks are created under the correct workspace, not the ephemeral worktree path.\n- If a task command fails because the runtime is unavailable, tell the user to start Kanban in that workspace first with \\`${kanbanCommand}\\`, then retry the task command.\n\n# Command Prefix\n\nUse this prefix for every Kanban command in this session:\n\\`${kanbanCommand}\\`\n\n# CLI Reference\n\nAll commands return JSON.\n\n## task list\n\nPurpose: list Kanban tasks for a workspace, including auto-review settings and dependency links.\n\nCommand:\n\\`${kanbanCommand} task list [--project-path <path>] [--column backlog|in_progress|review]\\`\n\nParameters:\n- \\`--project-path <path>\\` optional workspace path. If omitted, uses the current working directory workspace.\n- \\`--column <value>\\` optional filter. Allowed values: \\`backlog\\`, \\`in_progress\\`, \\`review\\`.\n\n## task create\n\nPurpose: create a new task in \\`backlog\\`, with optional plan mode and auto-review behavior.\n\nCommand:\n\\`${kanbanCommand} task create --prompt \"<text>\" [--project-path <path>] [--base-ref <branch>] [--start-in-plan-mode <true|false>] [--auto-review-enabled <true|false>] [--auto-review-mode commit|pr|move_to_trash]\\`\n\nParameters:\n- \\`--prompt \"<text>\"\\` required task prompt text.\n- \\`--project-path <path>\\` optional workspace path. If not already registered in Kanban, it is auto-added for git repos.\n- \\`--base-ref <branch>\\` optional base branch/worktree ref. Defaults to current branch, then default branch, then first known branch.\n- \\`--start-in-plan-mode <true|false>\\` optional. Default false. Set true only when explicitly requested.\n- \\`--auto-review-enabled <true|false>\\` optional. Default false. Enables automatic action once task reaches review.\n- \\`--auto-review-mode commit|pr|move_to_trash\\` optional auto-review action. Default \\`commit\\`.\n\n## task update\n\nPurpose: update an existing task, including prompt, base ref, plan mode, and auto-review behavior.\n\nCommand:\n\\`${kanbanCommand} task update --task-id <task_id> [--prompt \"<text>\"] [--project-path <path>] [--base-ref <branch>] [--start-in-plan-mode <true|false>] [--auto-review-enabled <true|false>] [--auto-review-mode commit|pr|move_to_trash]\\`\n\nParameters:\n- \\`--task-id <task_id>\\` required task ID.\n- \\`--project-path <path>\\` optional workspace path. If not already registered in Kanban, it is auto-added for git repos.\n- \\`--prompt \"<text>\"\\` optional replacement prompt text.\n- \\`--base-ref <branch>\\` optional replacement base ref.\n- \\`--start-in-plan-mode <true|false>\\` optional replacement of plan-mode behavior.\n- \\`--auto-review-enabled <true|false>\\` optional replacement of auto-review toggle. Set false to cancel pending automatic review actions.\n- \\`--auto-review-mode commit|pr|move_to_trash\\` optional replacement auto-review action.\n\nNotes:\n- Provide at least one field to change in addition to \\`--task-id\\`.\n\n## task link\n\nPurpose: link two tasks so one can wait on another. At least one linked task must be in backlog.\n\nCommand:\n\\`${kanbanCommand} task link --task-id <task_id> --linked-task-id <task_id> [--project-path <path>]\\`\n\nParameters:\n- \\`--task-id <task_id>\\` required first task ID.\n- \\`--linked-task-id <task_id>\\` required second task ID.\n- \\`--project-path <path>\\` optional workspace path. If not already registered in Kanban, it is auto-added for git repos.\n\n## task unlink\n\nPurpose: remove an existing task link (dependency) by dependency ID.\n\nCommand:\n\\`${kanbanCommand} task unlink --dependency-id <dependency_id> [--project-path <path>]\\`\n\nParameters:\n- \\`--dependency-id <dependency_id>\\` required dependency ID. Use \\`task list\\` to inspect existing links.\n- \\`--project-path <path>\\` optional workspace path. If not already registered in Kanban, it is auto-added for git repos.\n\n## task start\n\nPurpose: start a task by ensuring its worktree, launching its agent session, and moving it to \\`in_progress\\`.\n\nCommand:\n\\`${kanbanCommand} task start --task-id <task_id> [--project-path <path>]\\`\n\nParameters:\n- \\`--task-id <task_id>\\` required task ID.\n- \\`--project-path <path>\\` optional workspace path. If not already registered in Kanban, it is auto-added for git repos.\n\n# Workflow Notes\n\n- Prefer \\`task list\\` first when task IDs or dependency IDs are needed.\n- To create multiple linked tasks, create tasks first, then call \\`task link\\` for each dependency edge.\n- If \\`pwd\\` includes \\`/.kanban/worktrees/\\`, set \\`--project-path\\` to the main workspace path. You can derive it with:\n\\`main_path=\"\\${PWD%%/.kanban/worktrees/*}\"\\`\n`;\n}\n\nfunction getSkillInstallPaths(homePath: string, includeClaudeSkill: boolean): string[] {\n\tconst paths = [join(homePath, \".agents\", \"skills\", SKILL_NAME, \"SKILL.md\")];\n\tif (includeClaudeSkill) {\n\t\tpaths.push(join(homePath, \".claude\", \"skills\", SKILL_NAME, \"SKILL.md\"));\n\t}\n\treturn paths;\n}\n\nexport interface InstallKanbanSkillFilesOptions {\n\tcommandPrefix: string;\n\tinstallClaudeSkill?: boolean;\n\thomePath?: string;\n}\n\nexport async function installKanbanSkillFiles(options: InstallKanbanSkillFilesOptions): Promise<string[]> {\n\tconst skillContent = renderKanbanSkillMarkdown(options.commandPrefix);\n\tconst installPaths = getSkillInstallPaths(options.homePath ?? homedir(), options.installClaudeSkill === true);\n\n\tfor (const installPath of installPaths) {\n\t\tawait mkdir(dirname(installPath), { recursive: true });\n\t\tawait writeFile(installPath, skillContent, \"utf8\");\n\t}\n\n\treturn installPaths;\n}\n"]}
1
+ {"version":3,"file":"kanban-skill.js","sourceRoot":"","sources":["../../src/skills/kanban-skill.ts"],"names":[],"mappings":"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","sourcesContent":["import { realpathSync } from \"node:fs\";\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nimport { AutoUpdatePackageManager, detectAutoUpdateInstallation } from \"../update/auto-update.js\";\n\nconst SKILL_NAME = \"kanban\";\nconst DEFAULT_COMMAND_PREFIX = \"kanban\";\n\nexport interface ResolveKanbanSkillCommandPrefixOptions {\n\tcurrentVersion: string;\n\targv?: string[];\n\tcwd?: string;\n\tresolveRealPath?: (path: string) => string;\n}\n\nexport function resolveKanbanSkillCommandPrefix(options: ResolveKanbanSkillCommandPrefixOptions): string {\n\tconst argv = options.argv ?? process.argv;\n\tconst entrypointArg = argv[1];\n\tif (!entrypointArg) {\n\t\treturn DEFAULT_COMMAND_PREFIX;\n\t}\n\n\tconst resolveRealPath = options.resolveRealPath ?? realpathSync;\n\tlet entrypointPath: string;\n\ttry {\n\t\tentrypointPath = resolveRealPath(entrypointArg);\n\t} catch {\n\t\treturn DEFAULT_COMMAND_PREFIX;\n\t}\n\n\tconst installation = detectAutoUpdateInstallation({\n\t\tcurrentVersion: options.currentVersion,\n\t\tpackageName: \"kanban\",\n\t\tentrypointPath,\n\t\tcwd: options.cwd ?? process.cwd(),\n\t});\n\n\tif (installation.updateTiming !== \"shutdown\") {\n\t\treturn DEFAULT_COMMAND_PREFIX;\n\t}\n\n\tif (installation.packageManager === AutoUpdatePackageManager.NPX) {\n\t\treturn \"npx -y kanban\";\n\t}\n\tif (installation.packageManager === AutoUpdatePackageManager.PNPM) {\n\t\treturn \"pnpm dlx kanban\";\n\t}\n\tif (installation.packageManager === AutoUpdatePackageManager.YARN) {\n\t\treturn \"yarn dlx kanban\";\n\t}\n\tif (installation.packageManager === AutoUpdatePackageManager.BUN) {\n\t\treturn \"bun x kanban\";\n\t}\n\n\treturn DEFAULT_COMMAND_PREFIX;\n}\n\nexport function renderKanbanSkillMarkdown(commandPrefix: string): string {\n\tconst kanbanCommand = commandPrefix.trim() || DEFAULT_COMMAND_PREFIX;\n\treturn `---\nname: kanban\ndescription: Manage tasks on the user's Kanban, a tool for orchestrating coding agents in worktrees via a kanban board. This skill helps you create, edit, link, and start tasks using the kanban CLI. The user first launches kanban with e.g. npx kanban, then may ask you to help 'add tasks to kanban' or something to that effect (e.g. link / port over / break work down / split into kanban tasks). Only use this skill when the user mentions kanban.\n---\n\n# Kanban\n\nKanban is a CLI tool for orchestrating multiple coding agents working on tasks in parallel on a kanban board. It manages git worktrees automatically so that each task can run a dedicated CLI agent in its own worktree.\n\n- If the user asks to add tasks to kb, ask kb, kanban, or says add tasks without other context, they likely want to add tasks in Kanban. This includes phrases like \"create tasks\", \"make 3 tasks\", \"add a task\", \"break down into tasks\", \"split into tasks\", \"decompose into tasks\", \"turn into tasks\", etc.\n- Kanban also supports linking tasks. Linking is useful both for parallelization and for dependencies: when work is easy to decompose into multiple pieces that can be done in parallel, link multiple backlog tasks to the same dependency so they all become ready to start once that dependency finishes; when one piece of work depends on another, use links to represent that follow-on dependency. A link requires at least one backlog task, and when the linked review task is moved to trash, that backlog task becomes ready to start.\n- Tasks can also enable automatic review actions: auto-commit, auto-open-pr, or auto-move-to-trash once completed, sending the task to trash and kicking off any linked tasks.\n- There is a special case where the user may create a Kanban task to create new Kanban tasks. If the current working directory contains .kanban/worktrees/ in its path, you are running inside an ephemeral Kanban worktree. In this case, pass the main worktree path with \\`--project-path\\` so the new tasks are created under the correct workspace, not the ephemeral worktree path.\n- If a task command fails because the runtime is unavailable, tell the user to start Kanban in that workspace first with \\`${kanbanCommand}\\`, then retry the task command.\n\n# Command Prefix\n\nUse this prefix for every Kanban command in this session:\n\\`${kanbanCommand}\\`\n\n# CLI Reference\n\nAll commands return JSON.\n\n## task list\n\nPurpose: list Kanban tasks for a workspace, including auto-review settings and dependency links.\n\nCommand:\n\\`${kanbanCommand} task list [--project-path <path>] [--column backlog|in_progress|review]\\`\n\nParameters:\n- \\`--project-path <path>\\` optional workspace path. If omitted, uses the current working directory workspace.\n- \\`--column <value>\\` optional filter. Allowed values: \\`backlog\\`, \\`in_progress\\`, \\`review\\`.\n\n## task create\n\nPurpose: create a new task in \\`backlog\\`, with optional plan mode and auto-review behavior.\n\nCommand:\n\\`${kanbanCommand} task create --prompt \"<text>\" [--project-path <path>] [--base-ref <branch>] [--start-in-plan-mode <true|false>] [--auto-review-enabled <true|false>] [--auto-review-mode commit|pr|move_to_trash]\\`\n\nParameters:\n- \\`--prompt \"<text>\"\\` required task prompt text.\n- \\`--project-path <path>\\` optional workspace path. If not already registered in Kanban, it is auto-added for git repos.\n- \\`--base-ref <branch>\\` optional base branch/worktree ref. Defaults to current branch, then default branch, then first known branch.\n- \\`--start-in-plan-mode <true|false>\\` optional. Default false. Set true only when explicitly requested.\n- \\`--auto-review-enabled <true|false>\\` optional. Default false. Enables automatic action once task reaches review.\n- \\`--auto-review-mode commit|pr|move_to_trash\\` optional auto-review action. Default \\`commit\\`.\n\n## task update\n\nPurpose: update an existing task, including prompt, base ref, plan mode, and auto-review behavior.\n\nCommand:\n\\`${kanbanCommand} task update --task-id <task_id> [--prompt \"<text>\"] [--project-path <path>] [--base-ref <branch>] [--start-in-plan-mode <true|false>] [--auto-review-enabled <true|false>] [--auto-review-mode commit|pr|move_to_trash]\\`\n\nParameters:\n- \\`--task-id <task_id>\\` required task ID.\n- \\`--project-path <path>\\` optional workspace path. If not already registered in Kanban, it is auto-added for git repos.\n- \\`--prompt \"<text>\"\\` optional replacement prompt text.\n- \\`--base-ref <branch>\\` optional replacement base ref.\n- \\`--start-in-plan-mode <true|false>\\` optional replacement of plan-mode behavior.\n- \\`--auto-review-enabled <true|false>\\` optional replacement of auto-review toggle. Set false to cancel pending automatic review actions.\n- \\`--auto-review-mode commit|pr|move_to_trash\\` optional replacement auto-review action.\n\nNotes:\n- Provide at least one field to change in addition to \\`--task-id\\`.\n\n## task link\n\nPurpose: link two tasks so one can wait on another. At least one linked task must be in backlog.\n\nCommand:\n\\`${kanbanCommand} task link --task-id <task_id> --linked-task-id <task_id> [--project-path <path>]\\`\n\nParameters:\n- \\`--task-id <task_id>\\` required first task ID.\n- \\`--linked-task-id <task_id>\\` required second task ID.\n- \\`--project-path <path>\\` optional workspace path. If not already registered in Kanban, it is auto-added for git repos.\n\n## task unlink\n\nPurpose: remove an existing task link (dependency) by dependency ID.\n\nCommand:\n\\`${kanbanCommand} task unlink --dependency-id <dependency_id> [--project-path <path>]\\`\n\nParameters:\n- \\`--dependency-id <dependency_id>\\` required dependency ID. Use \\`task list\\` to inspect existing links.\n- \\`--project-path <path>\\` optional workspace path. If not already registered in Kanban, it is auto-added for git repos.\n\n## task start\n\nPurpose: start a task by ensuring its worktree, launching its agent session, and moving it to \\`in_progress\\`.\n\nCommand:\n\\`${kanbanCommand} task start --task-id <task_id> [--project-path <path>]\\`\n\nParameters:\n- \\`--task-id <task_id>\\` required task ID.\n- \\`--project-path <path>\\` optional workspace path. If not already registered in Kanban, it is auto-added for git repos.\n\n# Workflow Notes\n\n- Prefer \\`task list\\` first when task IDs or dependency IDs are needed.\n- To create multiple linked tasks, create tasks first, then call \\`task link\\` for each dependency edge.\n- If \\`pwd\\` includes \\`/.kanban/worktrees/\\`, set \\`--project-path\\` to the main workspace path. You can derive it with:\n\\`main_path=\"\\${PWD%%/.kanban/worktrees/*}\"\\`\n`;\n}\n\nfunction getSkillInstallPaths(homePath: string, includeClaudeSkill: boolean): string[] {\n\tconst paths = [join(homePath, \".agents\", \"skills\", SKILL_NAME, \"SKILL.md\")];\n\tif (includeClaudeSkill) {\n\t\tpaths.push(join(homePath, \".claude\", \"skills\", SKILL_NAME, \"SKILL.md\"));\n\t}\n\treturn paths;\n}\n\nexport interface InstallKanbanSkillFilesOptions {\n\tcommandPrefix: string;\n\tinstallClaudeSkill?: boolean;\n\thomePath?: string;\n}\n\nexport async function installKanbanSkillFiles(options: InstallKanbanSkillFilesOptions): Promise<string[]> {\n\tconst skillContent = renderKanbanSkillMarkdown(options.commandPrefix);\n\tconst installPaths = getSkillInstallPaths(options.homePath ?? homedir(), options.installClaudeSkill === true);\n\n\tfor (const installPath of installPaths) {\n\t\tawait mkdir(dirname(installPath), { recursive: true });\n\t\tawait writeFile(installPath, skillContent, \"utf8\");\n\t}\n\n\treturn installPaths;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"workspace-state.d.ts","sourceRoot":"","sources":["../../src/state/workspace-state.ts"],"names":[],"mappings":"AAOA,OAAO,EAGN,KAAK,wBAAwB,EAE7B,KAAK,6BAA6B,EAClC,KAAK,gCAAgC,EAIrC,MAAM,yBAAyB,CAAC;AAyBjC,MAAM,WAAW,0BAA0B;IAC1C,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CACjB;AAkFD,MAAM,WAAW,uBAAuB;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,wBAAwB,CAAC;CAC9B;AAED,MAAM,WAAW,2BAA2B;IAC3C,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAqBD,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAMD,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAErE;AA2VD,qBAAa,2BAA4B,SAAQ,KAAK;IACrD,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;gBAErB,gBAAgB,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM;CAK7D;AAED,wBAAsB,oBAAoB,CACzC,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,2BAAgC,GACvC,OAAO,CAAC,uBAAuB,CAAC,CA+BlC;AAED,wBAAsB,wBAAwB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAW3G;AAED,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,0BAA0B,EAAE,CAAC,CAQvF;AAED,wBAAsB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAUrF;AAED,wBAAsB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKlF;AAED,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,6BAA6B,CAAC,CAM5F;AAED,wBAAsB,kBAAkB,CACvC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,gCAAgC,GACvC,OAAO,CAAC,6BAA6B,CAAC,CA2BxC"}
1
+ {"version":3,"file":"workspace-state.d.ts","sourceRoot":"","sources":["../../src/state/workspace-state.ts"],"names":[],"mappings":"AAOA,OAAO,EAGN,KAAK,wBAAwB,EAE7B,KAAK,6BAA6B,EAClC,KAAK,gCAAgC,EAIrC,MAAM,yBAAyB,CAAC;AAyBjC,MAAM,WAAW,0BAA0B;IAC1C,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CACjB;AAkFD,MAAM,WAAW,uBAAuB;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,wBAAwB,CAAC;CAC9B;AAED,MAAM,WAAW,2BAA2B;IAC3C,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAqBD,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAMD,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAErE;AAoVD,qBAAa,2BAA4B,SAAQ,KAAK;IACrD,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;gBAErB,gBAAgB,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM;CAK7D;AAED,wBAAsB,oBAAoB,CACzC,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,2BAAgC,GACvC,OAAO,CAAC,uBAAuB,CAAC,CA+BlC;AAED,wBAAsB,wBAAwB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAW3G;AAED,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,0BAA0B,EAAE,CAAC,CAQvF;AAED,wBAAsB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAUrF;AAED,wBAAsB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKlF;AAED,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,6BAA6B,CAAC,CAM5F;AAED,wBAAsB,kBAAkB,CACvC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,gCAAgC,GACvC,OAAO,CAAC,6BAA6B,CAAC,CA2BxC"}
@@ -315,26 +315,19 @@ function detectGitCurrentBranch(repoPath) {
315
315
  return runGitCapture(repoPath, ["symbolic-ref", "--quiet", "--short", "HEAD"]);
316
316
  }
317
317
  function detectGitBranches(repoPath) {
318
- const output = runGitCapture(repoPath, [
319
- "for-each-ref",
320
- "--format=%(refname:short)",
321
- "refs/heads",
322
- "refs/remotes/origin",
323
- ]);
318
+ // TODO: support showing remote branches again once worktree creation can safely fetch/pull
319
+ // and resolve missing local tracking branches automatically.
320
+ const output = runGitCapture(repoPath, ["for-each-ref", "--format=%(refname:short)", "refs/heads"]);
324
321
  if (!output) {
325
322
  return [];
326
323
  }
327
324
  const unique = new Set();
328
325
  for (const line of output.split("\n")) {
329
326
  const trimmed = line.trim();
330
- if (!trimmed || trimmed === "origin/HEAD" || trimmed === "HEAD") {
327
+ if (!trimmed || trimmed === "HEAD") {
331
328
  continue;
332
329
  }
333
- const normalized = trimmed.startsWith("origin/") ? trimmed.slice("origin/".length) : trimmed;
334
- if (!normalized || normalized === "HEAD") {
335
- continue;
336
- }
337
- unique.add(normalized);
330
+ unique.add(trimmed);
338
331
  }
339
332
  return Array.from(unique).sort((left, right) => left.localeCompare(right));
340
333
  }
@@ -1 +1 @@
1
- {"version":3,"file":"workspace-state.js","sourceRoot":"","sources":["../../src/state/workspace-state.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawnSync } from \"node:child_process\";\nimport { randomBytes, randomUUID } from \"node:crypto\";\nimport { mkdir, readFile, realpath, rename, rm, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { basename, dirname, join, resolve } from \"node:path\";\nimport { z } from \"zod\";\n\nimport {\n\ttype RuntimeBoardColumnId,\n\ttype RuntimeBoardData,\n\ttype RuntimeGitRepositoryInfo,\n\ttype RuntimeTaskSessionSummary,\n\ttype RuntimeWorkspaceStateResponse,\n\ttype RuntimeWorkspaceStateSaveRequest,\n\truntimeBoardDataSchema,\n\truntimeTaskSessionSummarySchema,\n\truntimeWorkspaceStateSaveRequestSchema,\n} from \"../core/api-contract.js\";\nimport { createGitProcessEnv } from \"../core/git-process-env.js\";\nimport { updateTaskDependencies } from \"../core/task-board-mutations.js\";\n\nconst RUNTIME_HOME_DIR = \".kanban\";\nconst WORKSPACES_DIR = \"workspaces\";\nconst INDEX_FILENAME = \"index.json\";\nconst BOARD_FILENAME = \"board.json\";\nconst SESSIONS_FILENAME = \"sessions.json\";\nconst META_FILENAME = \"meta.json\";\nconst INDEX_VERSION = 1;\nconst WORKSPACE_ID_COLLISION_SUFFIX_LENGTH = 4;\n\nconst BOARD_COLUMNS: Array<{ id: RuntimeBoardColumnId; title: string }> = [\n\t{ id: \"backlog\", title: \"Backlog\" },\n\t{ id: \"in_progress\", title: \"In Progress\" },\n\t{ id: \"review\", title: \"Review\" },\n\t{ id: \"trash\", title: \"Trash\" },\n];\n\ninterface WorkspaceIndexEntry {\n\tworkspaceId: string;\n\trepoPath: string;\n}\n\nexport interface RuntimeWorkspaceIndexEntry {\n\tworkspaceId: string;\n\trepoPath: string;\n}\n\ninterface WorkspaceIndexFile {\n\tversion: number;\n\tentries: Record<string, WorkspaceIndexEntry>;\n\trepoPathToId: Record<string, string>;\n}\n\ninterface WorkspaceStateMeta {\n\trevision: number;\n\tupdatedAt: number;\n}\n\nconst workspaceStateMetaSchema = z.object({\n\trevision: z.number().int().nonnegative(),\n\tupdatedAt: z.number(),\n});\n\nconst workspaceIndexEntrySchema = z.object({\n\tworkspaceId: z.string().min(1, \"Workspace ID cannot be empty.\"),\n\trepoPath: z.string().min(1, \"Workspace repository path cannot be empty.\"),\n});\n\nconst workspaceIndexFileSchema = z\n\t.object({\n\t\tversion: z.literal(INDEX_VERSION),\n\t\tentries: z.record(z.string(), workspaceIndexEntrySchema),\n\t\trepoPathToId: z.record(z.string(), z.string().min(1, \"Workspace ID cannot be empty.\")),\n\t})\n\t.superRefine((index, context) => {\n\t\tfor (const [workspaceId, entry] of Object.entries(index.entries)) {\n\t\t\tif (entry.workspaceId !== workspaceId) {\n\t\t\t\tcontext.addIssue({\n\t\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\t\tpath: [\"entries\", workspaceId, \"workspaceId\"],\n\t\t\t\t\tmessage: `Workspace ID must match entry key \"${workspaceId}\".`,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst mappedWorkspaceId = index.repoPathToId[entry.repoPath];\n\t\t\tif (mappedWorkspaceId !== workspaceId) {\n\t\t\t\tcontext.addIssue({\n\t\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\t\tpath: [\"entries\", workspaceId, \"repoPath\"],\n\t\t\t\t\tmessage: `Missing repoPathToId mapping for \"${entry.repoPath}\" to \"${workspaceId}\".`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tfor (const [repoPath, workspaceId] of Object.entries(index.repoPathToId)) {\n\t\t\tconst entry = index.entries[workspaceId];\n\t\t\tif (!entry) {\n\t\t\t\tcontext.addIssue({\n\t\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\t\tpath: [\"repoPathToId\", repoPath],\n\t\t\t\t\tmessage: `Mapped workspace \"${workspaceId}\" does not exist in entries.`,\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (entry.repoPath !== repoPath) {\n\t\t\t\tcontext.addIssue({\n\t\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\t\tpath: [\"repoPathToId\", repoPath],\n\t\t\t\t\tmessage: `Mapped repoPath does not match workspace entry path \"${entry.repoPath}\".`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t});\n\nconst workspaceSessionsSchema = z\n\t.record(z.string(), runtimeTaskSessionSummarySchema)\n\t.superRefine((sessions, context) => {\n\t\tfor (const [taskId, session] of Object.entries(sessions)) {\n\t\t\tif (session.taskId !== taskId) {\n\t\t\t\tcontext.addIssue({\n\t\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\t\tpath: [taskId, \"taskId\"],\n\t\t\t\t\tmessage: `Session taskId must match record key \"${taskId}\".`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t});\n\nexport interface RuntimeWorkspaceContext {\n\trepoPath: string;\n\tworkspaceId: string;\n\tstatePath: string;\n\tgit: RuntimeGitRepositoryInfo;\n}\n\nexport interface LoadWorkspaceContextOptions {\n\tautoCreateIfMissing?: boolean;\n}\n\nfunction createEmptyBoard(): RuntimeBoardData {\n\treturn {\n\t\tcolumns: BOARD_COLUMNS.map((column) => ({\n\t\t\tid: column.id,\n\t\t\ttitle: column.title,\n\t\t\tcards: [],\n\t\t})),\n\t\tdependencies: [],\n\t};\n}\n\nfunction createEmptyWorkspaceIndex(): WorkspaceIndexFile {\n\treturn {\n\t\tversion: INDEX_VERSION,\n\t\tentries: {},\n\t\trepoPathToId: {},\n\t};\n}\n\nexport function getRuntimeHomePath(): string {\n\treturn join(homedir(), RUNTIME_HOME_DIR);\n}\n\nexport function getWorkspacesRootPath(): string {\n\treturn join(getRuntimeHomePath(), WORKSPACES_DIR);\n}\n\nfunction getWorkspaceIndexPath(): string {\n\treturn join(getWorkspacesRootPath(), INDEX_FILENAME);\n}\n\nexport function getWorkspaceDirectoryPath(workspaceId: string): string {\n\treturn join(getWorkspacesRootPath(), workspaceId);\n}\n\nfunction getWorkspaceBoardPath(workspaceId: string): string {\n\treturn join(getWorkspaceDirectoryPath(workspaceId), BOARD_FILENAME);\n}\n\nfunction getWorkspaceSessionsPath(workspaceId: string): string {\n\treturn join(getWorkspaceDirectoryPath(workspaceId), SESSIONS_FILENAME);\n}\n\nfunction getWorkspaceMetaPath(workspaceId: string): string {\n\treturn join(getWorkspaceDirectoryPath(workspaceId), META_FILENAME);\n}\n\nfunction isNodeErrorWithCode(error: unknown, code: string): boolean {\n\treturn typeof error === \"object\" && error !== null && \"code\" in error && (error as { code?: unknown }).code === code;\n}\n\nasync function readJsonFile(path: string): Promise<unknown | null> {\n\ttry {\n\t\tconst raw = await readFile(path, \"utf8\");\n\t\ttry {\n\t\t\treturn JSON.parse(raw) as unknown;\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tthrow new Error(`Malformed JSON in ${path}. ${message}`);\n\t\t}\n\t} catch (error) {\n\t\tif (isNodeErrorWithCode(error, \"ENOENT\")) {\n\t\t\treturn null;\n\t\t}\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tthrow new Error(`Could not read JSON file at ${path}. ${message}`);\n\t}\n}\n\nasync function writeJsonFileAtomic(path: string, payload: unknown): Promise<void> {\n\tawait mkdir(dirname(path), { recursive: true });\n\tconst tempPath = `${path}.tmp.${process.pid}.${Date.now()}.${randomUUID()}`;\n\tawait writeFile(tempPath, JSON.stringify(payload, null, 2), \"utf8\");\n\tawait rename(tempPath, path);\n}\n\nfunction formatSchemaIssuePath(pathSegments: PropertyKey[]): string {\n\tif (pathSegments.length === 0) {\n\t\treturn \"root\";\n\t}\n\treturn pathSegments\n\t\t.map((segment) => {\n\t\t\tif (typeof segment === \"number\") {\n\t\t\t\treturn `[${segment}]`;\n\t\t\t}\n\t\t\treturn String(segment);\n\t\t})\n\t\t.join(\".\");\n}\n\nfunction formatSchemaIssues(error: z.ZodError): string {\n\treturn error.issues.map((issue) => `${formatSchemaIssuePath(issue.path)}: ${issue.message}`).join(\"; \");\n}\n\nfunction parsePersistedStateFile<T>(\n\tfilePath: string,\n\tfileLabel: string,\n\traw: unknown | null,\n\tschema: z.ZodType<T>,\n\tdefaultValue: T,\n): T {\n\tif (raw === null) {\n\t\treturn defaultValue;\n\t}\n\tconst parsed = schema.safeParse(raw);\n\tif (!parsed.success) {\n\t\tthrow new Error(\n\t\t\t`Invalid ${fileLabel} file at ${filePath}. ` +\n\t\t\t\t`Fix or remove the file. Validation errors: ${formatSchemaIssues(parsed.error)}`,\n\t\t);\n\t}\n\treturn parsed.data;\n}\n\nfunction parseWorkspaceIndex(rawIndex: unknown | null): WorkspaceIndexFile {\n\tconst indexPath = getWorkspaceIndexPath();\n\treturn parsePersistedStateFile(\n\t\tindexPath,\n\t\tINDEX_FILENAME,\n\t\trawIndex,\n\t\tworkspaceIndexFileSchema,\n\t\tcreateEmptyWorkspaceIndex(),\n\t);\n}\n\nfunction parseWorkspaceStateSavePayload(payload: RuntimeWorkspaceStateSaveRequest): RuntimeWorkspaceStateSaveRequest {\n\tconst parsed = runtimeWorkspaceStateSaveRequestSchema.safeParse(payload);\n\tif (!parsed.success) {\n\t\tthrow new Error(`Invalid workspace state save payload. ${formatSchemaIssues(parsed.error)}`);\n\t}\n\treturn parsed.data;\n}\n\nasync function readWorkspaceBoard(workspaceId: string): Promise<RuntimeBoardData> {\n\tconst boardPath = getWorkspaceBoardPath(workspaceId);\n\tconst rawBoard = await readJsonFile(boardPath);\n\treturn updateTaskDependencies(\n\t\tparsePersistedStateFile(boardPath, BOARD_FILENAME, rawBoard, runtimeBoardDataSchema, createEmptyBoard()),\n\t);\n}\n\nasync function readWorkspaceSessions(workspaceId: string): Promise<Record<string, RuntimeTaskSessionSummary>> {\n\tconst sessionsPath = getWorkspaceSessionsPath(workspaceId);\n\tconst rawSessions = await readJsonFile(sessionsPath);\n\treturn parsePersistedStateFile(sessionsPath, SESSIONS_FILENAME, rawSessions, workspaceSessionsSchema, {});\n}\n\nasync function readWorkspaceMeta(workspaceId: string): Promise<WorkspaceStateMeta> {\n\tconst metaPath = getWorkspaceMetaPath(workspaceId);\n\tconst rawMeta = await readJsonFile(metaPath);\n\treturn parsePersistedStateFile(metaPath, META_FILENAME, rawMeta, workspaceStateMetaSchema, {\n\t\trevision: 0,\n\t\tupdatedAt: 0,\n\t});\n}\n\nasync function readWorkspaceIndex(): Promise<WorkspaceIndexFile> {\n\tconst raw = await readJsonFile(getWorkspaceIndexPath());\n\treturn parseWorkspaceIndex(raw);\n}\n\nasync function writeWorkspaceIndex(index: WorkspaceIndexFile): Promise<void> {\n\tawait writeJsonFileAtomic(getWorkspaceIndexPath(), index);\n}\n\nfunction toWorkspaceIdBase(repoPath: string): string {\n\tconst trimmed = repoPath.trim().replace(/[\\\\/]+$/g, \"\");\n\tconst folderName = basename(trimmed) || \"project\";\n\tconst normalized = folderName\n\t\t.normalize(\"NFKD\")\n\t\t.toLowerCase()\n\t\t.replace(/[^a-z0-9]+/g, \"-\")\n\t\t.replace(/^-+|-+$/g, \"\");\n\treturn normalized || \"project\";\n}\n\nfunction createWorkspaceIdCollisionSuffix(length: number): string {\n\tconst alphabet = \"abcdefghijklmnopqrstuvwxyz0123456789\";\n\tlet suffix = \"\";\n\twhile (suffix.length < length) {\n\t\tconst bytes = randomBytes(length);\n\t\tfor (const byte of bytes) {\n\t\t\tsuffix += alphabet[byte % alphabet.length] ?? \"\";\n\t\t\tif (suffix.length === length) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\treturn suffix;\n}\n\nfunction createWorkspaceId(index: WorkspaceIndexFile, repoPath: string): string {\n\tconst baseId = toWorkspaceIdBase(repoPath);\n\tif (!index.entries[baseId] || index.entries[baseId]?.repoPath === repoPath) {\n\t\treturn baseId;\n\t}\n\n\tfor (let attempt = 0; attempt < 256; attempt += 1) {\n\t\tconst candidate = `${baseId}-${createWorkspaceIdCollisionSuffix(WORKSPACE_ID_COLLISION_SUFFIX_LENGTH)}`;\n\t\tif (!index.entries[candidate] || index.entries[candidate]?.repoPath === repoPath) {\n\t\t\treturn candidate;\n\t\t}\n\t}\n\n\tthrow new Error(`Could not generate a unique workspace ID for ${repoPath}.`);\n}\n\nfunction ensureWorkspaceEntry(\n\tindex: WorkspaceIndexFile,\n\trepoPath: string,\n): { index: WorkspaceIndexFile; entry: WorkspaceIndexEntry; changed: boolean } {\n\tconst existingWorkspaceId = index.repoPathToId[repoPath];\n\tif (existingWorkspaceId) {\n\t\tconst existingEntry = index.entries[existingWorkspaceId];\n\t\tif (existingEntry && existingEntry.repoPath === repoPath) {\n\t\t\treturn {\n\t\t\t\tindex,\n\t\t\t\tentry: existingEntry,\n\t\t\t\tchanged: false,\n\t\t\t};\n\t\t}\n\t}\n\n\tconst workspaceId = createWorkspaceId(index, repoPath);\n\n\tconst entry: WorkspaceIndexEntry = {\n\t\tworkspaceId,\n\t\trepoPath,\n\t};\n\n\treturn {\n\t\tindex: {\n\t\t\tversion: INDEX_VERSION,\n\t\t\tentries: {\n\t\t\t\t...index.entries,\n\t\t\t\t[workspaceId]: entry,\n\t\t\t},\n\t\t\trepoPathToId: {\n\t\t\t\t...index.repoPathToId,\n\t\t\t\t[repoPath]: workspaceId,\n\t\t\t},\n\t\t},\n\t\tentry,\n\t\tchanged: true,\n\t};\n}\n\nfunction findWorkspaceEntry(index: WorkspaceIndexFile, repoPath: string): WorkspaceIndexEntry | null {\n\tconst workspaceId = index.repoPathToId[repoPath];\n\tif (!workspaceId) {\n\t\treturn null;\n\t}\n\tconst entry = index.entries[workspaceId];\n\tif (!entry || entry.repoPath !== repoPath) {\n\t\treturn null;\n\t}\n\treturn entry;\n}\n\nfunction runGitCapture(cwd: string, args: string[]): string | null {\n\tconst result = spawnSync(\"git\", args, {\n\t\tcwd,\n\t\tencoding: \"utf8\",\n\t\tstdio: [\"ignore\", \"pipe\", \"ignore\"],\n\t\tenv: createGitProcessEnv(),\n\t});\n\tif (result.status !== 0 || typeof result.stdout !== \"string\") {\n\t\treturn null;\n\t}\n\tconst value = result.stdout.trim();\n\treturn value.length > 0 ? value : null;\n}\n\nfunction detectGitRoot(cwd: string): string | null {\n\treturn runGitCapture(cwd, [\"rev-parse\", \"--show-toplevel\"]);\n}\n\nfunction detectGitCurrentBranch(repoPath: string): string | null {\n\treturn runGitCapture(repoPath, [\"symbolic-ref\", \"--quiet\", \"--short\", \"HEAD\"]);\n}\n\nfunction detectGitBranches(repoPath: string): string[] {\n\tconst output = runGitCapture(repoPath, [\n\t\t\"for-each-ref\",\n\t\t\"--format=%(refname:short)\",\n\t\t\"refs/heads\",\n\t\t\"refs/remotes/origin\",\n\t]);\n\tif (!output) {\n\t\treturn [];\n\t}\n\n\tconst unique = new Set<string>();\n\tfor (const line of output.split(\"\\n\")) {\n\t\tconst trimmed = line.trim();\n\t\tif (!trimmed || trimmed === \"origin/HEAD\" || trimmed === \"HEAD\") {\n\t\t\tcontinue;\n\t\t}\n\t\tconst normalized = trimmed.startsWith(\"origin/\") ? trimmed.slice(\"origin/\".length) : trimmed;\n\t\tif (!normalized || normalized === \"HEAD\") {\n\t\t\tcontinue;\n\t\t}\n\t\tunique.add(normalized);\n\t}\n\treturn Array.from(unique).sort((left, right) => left.localeCompare(right));\n}\n\nfunction detectGitDefaultBranch(repoPath: string, branches: string[]): string | null {\n\tconst remoteHead = runGitCapture(repoPath, [\"symbolic-ref\", \"--quiet\", \"--short\", \"refs/remotes/origin/HEAD\"]);\n\tif (remoteHead) {\n\t\tconst normalized = remoteHead.startsWith(\"origin/\") ? remoteHead.slice(\"origin/\".length) : remoteHead;\n\t\tif (normalized) {\n\t\t\treturn normalized;\n\t\t}\n\t}\n\tif (branches.includes(\"main\")) {\n\t\treturn \"main\";\n\t}\n\tif (branches.includes(\"master\")) {\n\t\treturn \"master\";\n\t}\n\treturn branches[0] ?? null;\n}\n\nfunction detectGitRepositoryInfo(repoPath: string): RuntimeGitRepositoryInfo {\n\tconst gitRoot = detectGitRoot(repoPath);\n\tif (!gitRoot) {\n\t\tthrow new Error(`No git repository detected at ${repoPath}`);\n\t}\n\n\tconst currentBranch = detectGitCurrentBranch(repoPath);\n\tconst branches = detectGitBranches(repoPath);\n\tconst orderedBranches = currentBranch && !branches.includes(currentBranch) ? [currentBranch, ...branches] : branches;\n\tconst defaultBranch = detectGitDefaultBranch(repoPath, orderedBranches);\n\n\treturn {\n\t\tcurrentBranch,\n\t\tdefaultBranch,\n\t\tbranches: orderedBranches,\n\t};\n}\n\nasync function resolveWorkspacePath(cwd: string): Promise<string> {\n\tconst resolvedCwd = resolve(cwd);\n\tlet canonicalCwd = resolvedCwd;\n\ttry {\n\t\tcanonicalCwd = await realpath(resolvedCwd);\n\t} catch {\n\t\tcanonicalCwd = resolvedCwd;\n\t}\n\n\tconst gitRoot = detectGitRoot(canonicalCwd);\n\tif (!gitRoot) {\n\t\tthrow new Error(`No git repository detected at ${canonicalCwd}`);\n\t}\n\n\tconst resolvedGitRoot = resolve(gitRoot);\n\ttry {\n\t\treturn await realpath(resolvedGitRoot);\n\t} catch {\n\t\treturn resolvedGitRoot;\n\t}\n}\n\nfunction toWorkspaceStateResponse(\n\tcontext: RuntimeWorkspaceContext,\n\tboard: RuntimeBoardData,\n\tsessions: Record<string, RuntimeTaskSessionSummary>,\n\trevision: number,\n): RuntimeWorkspaceStateResponse {\n\treturn {\n\t\trepoPath: context.repoPath,\n\t\tstatePath: context.statePath,\n\t\tgit: context.git,\n\t\tboard,\n\t\tsessions,\n\t\trevision,\n\t};\n}\n\nexport class WorkspaceStateConflictError extends Error {\n\treadonly currentRevision: number;\n\n\tconstructor(expectedRevision: number, currentRevision: number) {\n\t\tsuper(`Workspace state revision mismatch: expected ${expectedRevision}, current ${currentRevision}.`);\n\t\tthis.name = \"WorkspaceStateConflictError\";\n\t\tthis.currentRevision = currentRevision;\n\t}\n}\n\nexport async function loadWorkspaceContext(\n\tcwd: string,\n\toptions: LoadWorkspaceContextOptions = {},\n): Promise<RuntimeWorkspaceContext> {\n\tconst repoPath = await resolveWorkspacePath(cwd);\n\tconst autoCreateIfMissing = options.autoCreateIfMissing ?? true;\n\tlet index = await readWorkspaceIndex();\n\tconst existingEntry = findWorkspaceEntry(index, repoPath);\n\tif (!autoCreateIfMissing) {\n\t\tif (!existingEntry) {\n\t\t\tthrow new Error(`Project ${repoPath} is not added to Kanban yet.`);\n\t\t}\n\t\treturn {\n\t\t\trepoPath,\n\t\t\tworkspaceId: existingEntry.workspaceId,\n\t\t\tstatePath: getWorkspaceDirectoryPath(existingEntry.workspaceId),\n\t\t\tgit: detectGitRepositoryInfo(repoPath),\n\t\t};\n\t}\n\n\tconst ensured = existingEntry\n\t\t? { index, entry: existingEntry, changed: false }\n\t\t: ensureWorkspaceEntry(index, repoPath);\n\tindex = ensured.index;\n\tif (ensured.changed) {\n\t\tawait writeWorkspaceIndex(index);\n\t}\n\n\treturn {\n\t\trepoPath,\n\t\tworkspaceId: ensured.entry.workspaceId,\n\t\tstatePath: getWorkspaceDirectoryPath(ensured.entry.workspaceId),\n\t\tgit: detectGitRepositoryInfo(repoPath),\n\t};\n}\n\nexport async function loadWorkspaceContextById(workspaceId: string): Promise<RuntimeWorkspaceContext | null> {\n\tconst index = await readWorkspaceIndex();\n\tconst entry = index.entries[workspaceId];\n\tif (!entry) {\n\t\treturn null;\n\t}\n\ttry {\n\t\treturn await loadWorkspaceContext(entry.repoPath);\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport async function listWorkspaceIndexEntries(): Promise<RuntimeWorkspaceIndexEntry[]> {\n\tconst index = await readWorkspaceIndex();\n\treturn Object.values(index.entries)\n\t\t.map((entry) => ({\n\t\t\tworkspaceId: entry.workspaceId,\n\t\t\trepoPath: entry.repoPath,\n\t\t}))\n\t\t.sort((left, right) => left.repoPath.localeCompare(right.repoPath));\n}\n\nexport async function removeWorkspaceIndexEntry(workspaceId: string): Promise<boolean> {\n\tconst index = await readWorkspaceIndex();\n\tconst entry = index.entries[workspaceId];\n\tif (!entry) {\n\t\treturn false;\n\t}\n\tdelete index.entries[workspaceId];\n\tdelete index.repoPathToId[entry.repoPath];\n\tawait writeWorkspaceIndex(index);\n\treturn true;\n}\n\nexport async function removeWorkspaceStateFiles(workspaceId: string): Promise<void> {\n\tawait rm(getWorkspaceDirectoryPath(workspaceId), {\n\t\trecursive: true,\n\t\tforce: true,\n\t});\n}\n\nexport async function loadWorkspaceState(cwd: string): Promise<RuntimeWorkspaceStateResponse> {\n\tconst context = await loadWorkspaceContext(cwd);\n\tconst board = await readWorkspaceBoard(context.workspaceId);\n\tconst sessions = await readWorkspaceSessions(context.workspaceId);\n\tconst meta = await readWorkspaceMeta(context.workspaceId);\n\treturn toWorkspaceStateResponse(context, board, sessions, meta.revision);\n}\n\nexport async function saveWorkspaceState(\n\tcwd: string,\n\tpayload: RuntimeWorkspaceStateSaveRequest,\n): Promise<RuntimeWorkspaceStateResponse> {\n\tconst parsedPayload = parseWorkspaceStateSavePayload(payload);\n\tconst context = await loadWorkspaceContext(cwd);\n\tconst metaPath = getWorkspaceMetaPath(context.workspaceId);\n\tconst currentMeta = await readWorkspaceMeta(context.workspaceId);\n\tconst expectedRevision = parsedPayload.expectedRevision;\n\tif (\n\t\ttypeof expectedRevision === \"number\" &&\n\t\tNumber.isInteger(expectedRevision) &&\n\t\texpectedRevision >= 0 &&\n\t\texpectedRevision !== currentMeta.revision\n\t) {\n\t\tthrow new WorkspaceStateConflictError(expectedRevision, currentMeta.revision);\n\t}\n\tconst board = parsedPayload.board;\n\tconst sessions = parsedPayload.sessions;\n\tconst nextRevision = currentMeta.revision + 1;\n\tconst nextMeta: WorkspaceStateMeta = {\n\t\trevision: nextRevision,\n\t\tupdatedAt: Date.now(),\n\t};\n\n\tawait writeJsonFileAtomic(getWorkspaceBoardPath(context.workspaceId), board);\n\tawait writeJsonFileAtomic(getWorkspaceSessionsPath(context.workspaceId), sessions);\n\tawait writeJsonFileAtomic(metaPath, nextMeta);\n\n\treturn toWorkspaceStateResponse(context, board, sessions, nextRevision);\n}\n"]}
1
+ {"version":3,"file":"workspace-state.js","sourceRoot":"","sources":["../../src/state/workspace-state.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawnSync } from \"node:child_process\";\nimport { randomBytes, randomUUID } from \"node:crypto\";\nimport { mkdir, readFile, realpath, rename, rm, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { basename, dirname, join, resolve } from \"node:path\";\nimport { z } from \"zod\";\n\nimport {\n\ttype RuntimeBoardColumnId,\n\ttype RuntimeBoardData,\n\ttype RuntimeGitRepositoryInfo,\n\ttype RuntimeTaskSessionSummary,\n\ttype RuntimeWorkspaceStateResponse,\n\ttype RuntimeWorkspaceStateSaveRequest,\n\truntimeBoardDataSchema,\n\truntimeTaskSessionSummarySchema,\n\truntimeWorkspaceStateSaveRequestSchema,\n} from \"../core/api-contract.js\";\nimport { createGitProcessEnv } from \"../core/git-process-env.js\";\nimport { updateTaskDependencies } from \"../core/task-board-mutations.js\";\n\nconst RUNTIME_HOME_DIR = \".kanban\";\nconst WORKSPACES_DIR = \"workspaces\";\nconst INDEX_FILENAME = \"index.json\";\nconst BOARD_FILENAME = \"board.json\";\nconst SESSIONS_FILENAME = \"sessions.json\";\nconst META_FILENAME = \"meta.json\";\nconst INDEX_VERSION = 1;\nconst WORKSPACE_ID_COLLISION_SUFFIX_LENGTH = 4;\n\nconst BOARD_COLUMNS: Array<{ id: RuntimeBoardColumnId; title: string }> = [\n\t{ id: \"backlog\", title: \"Backlog\" },\n\t{ id: \"in_progress\", title: \"In Progress\" },\n\t{ id: \"review\", title: \"Review\" },\n\t{ id: \"trash\", title: \"Trash\" },\n];\n\ninterface WorkspaceIndexEntry {\n\tworkspaceId: string;\n\trepoPath: string;\n}\n\nexport interface RuntimeWorkspaceIndexEntry {\n\tworkspaceId: string;\n\trepoPath: string;\n}\n\ninterface WorkspaceIndexFile {\n\tversion: number;\n\tentries: Record<string, WorkspaceIndexEntry>;\n\trepoPathToId: Record<string, string>;\n}\n\ninterface WorkspaceStateMeta {\n\trevision: number;\n\tupdatedAt: number;\n}\n\nconst workspaceStateMetaSchema = z.object({\n\trevision: z.number().int().nonnegative(),\n\tupdatedAt: z.number(),\n});\n\nconst workspaceIndexEntrySchema = z.object({\n\tworkspaceId: z.string().min(1, \"Workspace ID cannot be empty.\"),\n\trepoPath: z.string().min(1, \"Workspace repository path cannot be empty.\"),\n});\n\nconst workspaceIndexFileSchema = z\n\t.object({\n\t\tversion: z.literal(INDEX_VERSION),\n\t\tentries: z.record(z.string(), workspaceIndexEntrySchema),\n\t\trepoPathToId: z.record(z.string(), z.string().min(1, \"Workspace ID cannot be empty.\")),\n\t})\n\t.superRefine((index, context) => {\n\t\tfor (const [workspaceId, entry] of Object.entries(index.entries)) {\n\t\t\tif (entry.workspaceId !== workspaceId) {\n\t\t\t\tcontext.addIssue({\n\t\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\t\tpath: [\"entries\", workspaceId, \"workspaceId\"],\n\t\t\t\t\tmessage: `Workspace ID must match entry key \"${workspaceId}\".`,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst mappedWorkspaceId = index.repoPathToId[entry.repoPath];\n\t\t\tif (mappedWorkspaceId !== workspaceId) {\n\t\t\t\tcontext.addIssue({\n\t\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\t\tpath: [\"entries\", workspaceId, \"repoPath\"],\n\t\t\t\t\tmessage: `Missing repoPathToId mapping for \"${entry.repoPath}\" to \"${workspaceId}\".`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tfor (const [repoPath, workspaceId] of Object.entries(index.repoPathToId)) {\n\t\t\tconst entry = index.entries[workspaceId];\n\t\t\tif (!entry) {\n\t\t\t\tcontext.addIssue({\n\t\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\t\tpath: [\"repoPathToId\", repoPath],\n\t\t\t\t\tmessage: `Mapped workspace \"${workspaceId}\" does not exist in entries.`,\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (entry.repoPath !== repoPath) {\n\t\t\t\tcontext.addIssue({\n\t\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\t\tpath: [\"repoPathToId\", repoPath],\n\t\t\t\t\tmessage: `Mapped repoPath does not match workspace entry path \"${entry.repoPath}\".`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t});\n\nconst workspaceSessionsSchema = z\n\t.record(z.string(), runtimeTaskSessionSummarySchema)\n\t.superRefine((sessions, context) => {\n\t\tfor (const [taskId, session] of Object.entries(sessions)) {\n\t\t\tif (session.taskId !== taskId) {\n\t\t\t\tcontext.addIssue({\n\t\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\t\tpath: [taskId, \"taskId\"],\n\t\t\t\t\tmessage: `Session taskId must match record key \"${taskId}\".`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t});\n\nexport interface RuntimeWorkspaceContext {\n\trepoPath: string;\n\tworkspaceId: string;\n\tstatePath: string;\n\tgit: RuntimeGitRepositoryInfo;\n}\n\nexport interface LoadWorkspaceContextOptions {\n\tautoCreateIfMissing?: boolean;\n}\n\nfunction createEmptyBoard(): RuntimeBoardData {\n\treturn {\n\t\tcolumns: BOARD_COLUMNS.map((column) => ({\n\t\t\tid: column.id,\n\t\t\ttitle: column.title,\n\t\t\tcards: [],\n\t\t})),\n\t\tdependencies: [],\n\t};\n}\n\nfunction createEmptyWorkspaceIndex(): WorkspaceIndexFile {\n\treturn {\n\t\tversion: INDEX_VERSION,\n\t\tentries: {},\n\t\trepoPathToId: {},\n\t};\n}\n\nexport function getRuntimeHomePath(): string {\n\treturn join(homedir(), RUNTIME_HOME_DIR);\n}\n\nexport function getWorkspacesRootPath(): string {\n\treturn join(getRuntimeHomePath(), WORKSPACES_DIR);\n}\n\nfunction getWorkspaceIndexPath(): string {\n\treturn join(getWorkspacesRootPath(), INDEX_FILENAME);\n}\n\nexport function getWorkspaceDirectoryPath(workspaceId: string): string {\n\treturn join(getWorkspacesRootPath(), workspaceId);\n}\n\nfunction getWorkspaceBoardPath(workspaceId: string): string {\n\treturn join(getWorkspaceDirectoryPath(workspaceId), BOARD_FILENAME);\n}\n\nfunction getWorkspaceSessionsPath(workspaceId: string): string {\n\treturn join(getWorkspaceDirectoryPath(workspaceId), SESSIONS_FILENAME);\n}\n\nfunction getWorkspaceMetaPath(workspaceId: string): string {\n\treturn join(getWorkspaceDirectoryPath(workspaceId), META_FILENAME);\n}\n\nfunction isNodeErrorWithCode(error: unknown, code: string): boolean {\n\treturn typeof error === \"object\" && error !== null && \"code\" in error && (error as { code?: unknown }).code === code;\n}\n\nasync function readJsonFile(path: string): Promise<unknown | null> {\n\ttry {\n\t\tconst raw = await readFile(path, \"utf8\");\n\t\ttry {\n\t\t\treturn JSON.parse(raw) as unknown;\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tthrow new Error(`Malformed JSON in ${path}. ${message}`);\n\t\t}\n\t} catch (error) {\n\t\tif (isNodeErrorWithCode(error, \"ENOENT\")) {\n\t\t\treturn null;\n\t\t}\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tthrow new Error(`Could not read JSON file at ${path}. ${message}`);\n\t}\n}\n\nasync function writeJsonFileAtomic(path: string, payload: unknown): Promise<void> {\n\tawait mkdir(dirname(path), { recursive: true });\n\tconst tempPath = `${path}.tmp.${process.pid}.${Date.now()}.${randomUUID()}`;\n\tawait writeFile(tempPath, JSON.stringify(payload, null, 2), \"utf8\");\n\tawait rename(tempPath, path);\n}\n\nfunction formatSchemaIssuePath(pathSegments: PropertyKey[]): string {\n\tif (pathSegments.length === 0) {\n\t\treturn \"root\";\n\t}\n\treturn pathSegments\n\t\t.map((segment) => {\n\t\t\tif (typeof segment === \"number\") {\n\t\t\t\treturn `[${segment}]`;\n\t\t\t}\n\t\t\treturn String(segment);\n\t\t})\n\t\t.join(\".\");\n}\n\nfunction formatSchemaIssues(error: z.ZodError): string {\n\treturn error.issues.map((issue) => `${formatSchemaIssuePath(issue.path)}: ${issue.message}`).join(\"; \");\n}\n\nfunction parsePersistedStateFile<T>(\n\tfilePath: string,\n\tfileLabel: string,\n\traw: unknown | null,\n\tschema: z.ZodType<T>,\n\tdefaultValue: T,\n): T {\n\tif (raw === null) {\n\t\treturn defaultValue;\n\t}\n\tconst parsed = schema.safeParse(raw);\n\tif (!parsed.success) {\n\t\tthrow new Error(\n\t\t\t`Invalid ${fileLabel} file at ${filePath}. ` +\n\t\t\t\t`Fix or remove the file. Validation errors: ${formatSchemaIssues(parsed.error)}`,\n\t\t);\n\t}\n\treturn parsed.data;\n}\n\nfunction parseWorkspaceIndex(rawIndex: unknown | null): WorkspaceIndexFile {\n\tconst indexPath = getWorkspaceIndexPath();\n\treturn parsePersistedStateFile(\n\t\tindexPath,\n\t\tINDEX_FILENAME,\n\t\trawIndex,\n\t\tworkspaceIndexFileSchema,\n\t\tcreateEmptyWorkspaceIndex(),\n\t);\n}\n\nfunction parseWorkspaceStateSavePayload(payload: RuntimeWorkspaceStateSaveRequest): RuntimeWorkspaceStateSaveRequest {\n\tconst parsed = runtimeWorkspaceStateSaveRequestSchema.safeParse(payload);\n\tif (!parsed.success) {\n\t\tthrow new Error(`Invalid workspace state save payload. ${formatSchemaIssues(parsed.error)}`);\n\t}\n\treturn parsed.data;\n}\n\nasync function readWorkspaceBoard(workspaceId: string): Promise<RuntimeBoardData> {\n\tconst boardPath = getWorkspaceBoardPath(workspaceId);\n\tconst rawBoard = await readJsonFile(boardPath);\n\treturn updateTaskDependencies(\n\t\tparsePersistedStateFile(boardPath, BOARD_FILENAME, rawBoard, runtimeBoardDataSchema, createEmptyBoard()),\n\t);\n}\n\nasync function readWorkspaceSessions(workspaceId: string): Promise<Record<string, RuntimeTaskSessionSummary>> {\n\tconst sessionsPath = getWorkspaceSessionsPath(workspaceId);\n\tconst rawSessions = await readJsonFile(sessionsPath);\n\treturn parsePersistedStateFile(sessionsPath, SESSIONS_FILENAME, rawSessions, workspaceSessionsSchema, {});\n}\n\nasync function readWorkspaceMeta(workspaceId: string): Promise<WorkspaceStateMeta> {\n\tconst metaPath = getWorkspaceMetaPath(workspaceId);\n\tconst rawMeta = await readJsonFile(metaPath);\n\treturn parsePersistedStateFile(metaPath, META_FILENAME, rawMeta, workspaceStateMetaSchema, {\n\t\trevision: 0,\n\t\tupdatedAt: 0,\n\t});\n}\n\nasync function readWorkspaceIndex(): Promise<WorkspaceIndexFile> {\n\tconst raw = await readJsonFile(getWorkspaceIndexPath());\n\treturn parseWorkspaceIndex(raw);\n}\n\nasync function writeWorkspaceIndex(index: WorkspaceIndexFile): Promise<void> {\n\tawait writeJsonFileAtomic(getWorkspaceIndexPath(), index);\n}\n\nfunction toWorkspaceIdBase(repoPath: string): string {\n\tconst trimmed = repoPath.trim().replace(/[\\\\/]+$/g, \"\");\n\tconst folderName = basename(trimmed) || \"project\";\n\tconst normalized = folderName\n\t\t.normalize(\"NFKD\")\n\t\t.toLowerCase()\n\t\t.replace(/[^a-z0-9]+/g, \"-\")\n\t\t.replace(/^-+|-+$/g, \"\");\n\treturn normalized || \"project\";\n}\n\nfunction createWorkspaceIdCollisionSuffix(length: number): string {\n\tconst alphabet = \"abcdefghijklmnopqrstuvwxyz0123456789\";\n\tlet suffix = \"\";\n\twhile (suffix.length < length) {\n\t\tconst bytes = randomBytes(length);\n\t\tfor (const byte of bytes) {\n\t\t\tsuffix += alphabet[byte % alphabet.length] ?? \"\";\n\t\t\tif (suffix.length === length) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\treturn suffix;\n}\n\nfunction createWorkspaceId(index: WorkspaceIndexFile, repoPath: string): string {\n\tconst baseId = toWorkspaceIdBase(repoPath);\n\tif (!index.entries[baseId] || index.entries[baseId]?.repoPath === repoPath) {\n\t\treturn baseId;\n\t}\n\n\tfor (let attempt = 0; attempt < 256; attempt += 1) {\n\t\tconst candidate = `${baseId}-${createWorkspaceIdCollisionSuffix(WORKSPACE_ID_COLLISION_SUFFIX_LENGTH)}`;\n\t\tif (!index.entries[candidate] || index.entries[candidate]?.repoPath === repoPath) {\n\t\t\treturn candidate;\n\t\t}\n\t}\n\n\tthrow new Error(`Could not generate a unique workspace ID for ${repoPath}.`);\n}\n\nfunction ensureWorkspaceEntry(\n\tindex: WorkspaceIndexFile,\n\trepoPath: string,\n): { index: WorkspaceIndexFile; entry: WorkspaceIndexEntry; changed: boolean } {\n\tconst existingWorkspaceId = index.repoPathToId[repoPath];\n\tif (existingWorkspaceId) {\n\t\tconst existingEntry = index.entries[existingWorkspaceId];\n\t\tif (existingEntry && existingEntry.repoPath === repoPath) {\n\t\t\treturn {\n\t\t\t\tindex,\n\t\t\t\tentry: existingEntry,\n\t\t\t\tchanged: false,\n\t\t\t};\n\t\t}\n\t}\n\n\tconst workspaceId = createWorkspaceId(index, repoPath);\n\n\tconst entry: WorkspaceIndexEntry = {\n\t\tworkspaceId,\n\t\trepoPath,\n\t};\n\n\treturn {\n\t\tindex: {\n\t\t\tversion: INDEX_VERSION,\n\t\t\tentries: {\n\t\t\t\t...index.entries,\n\t\t\t\t[workspaceId]: entry,\n\t\t\t},\n\t\t\trepoPathToId: {\n\t\t\t\t...index.repoPathToId,\n\t\t\t\t[repoPath]: workspaceId,\n\t\t\t},\n\t\t},\n\t\tentry,\n\t\tchanged: true,\n\t};\n}\n\nfunction findWorkspaceEntry(index: WorkspaceIndexFile, repoPath: string): WorkspaceIndexEntry | null {\n\tconst workspaceId = index.repoPathToId[repoPath];\n\tif (!workspaceId) {\n\t\treturn null;\n\t}\n\tconst entry = index.entries[workspaceId];\n\tif (!entry || entry.repoPath !== repoPath) {\n\t\treturn null;\n\t}\n\treturn entry;\n}\n\nfunction runGitCapture(cwd: string, args: string[]): string | null {\n\tconst result = spawnSync(\"git\", args, {\n\t\tcwd,\n\t\tencoding: \"utf8\",\n\t\tstdio: [\"ignore\", \"pipe\", \"ignore\"],\n\t\tenv: createGitProcessEnv(),\n\t});\n\tif (result.status !== 0 || typeof result.stdout !== \"string\") {\n\t\treturn null;\n\t}\n\tconst value = result.stdout.trim();\n\treturn value.length > 0 ? value : null;\n}\n\nfunction detectGitRoot(cwd: string): string | null {\n\treturn runGitCapture(cwd, [\"rev-parse\", \"--show-toplevel\"]);\n}\n\nfunction detectGitCurrentBranch(repoPath: string): string | null {\n\treturn runGitCapture(repoPath, [\"symbolic-ref\", \"--quiet\", \"--short\", \"HEAD\"]);\n}\n\nfunction detectGitBranches(repoPath: string): string[] {\n\t// TODO: support showing remote branches again once worktree creation can safely fetch/pull\n\t// and resolve missing local tracking branches automatically.\n\tconst output = runGitCapture(repoPath, [\"for-each-ref\", \"--format=%(refname:short)\", \"refs/heads\"]);\n\tif (!output) {\n\t\treturn [];\n\t}\n\n\tconst unique = new Set<string>();\n\tfor (const line of output.split(\"\\n\")) {\n\t\tconst trimmed = line.trim();\n\t\tif (!trimmed || trimmed === \"HEAD\") {\n\t\t\tcontinue;\n\t\t}\n\t\tunique.add(trimmed);\n\t}\n\treturn Array.from(unique).sort((left, right) => left.localeCompare(right));\n}\n\nfunction detectGitDefaultBranch(repoPath: string, branches: string[]): string | null {\n\tconst remoteHead = runGitCapture(repoPath, [\"symbolic-ref\", \"--quiet\", \"--short\", \"refs/remotes/origin/HEAD\"]);\n\tif (remoteHead) {\n\t\tconst normalized = remoteHead.startsWith(\"origin/\") ? remoteHead.slice(\"origin/\".length) : remoteHead;\n\t\tif (normalized) {\n\t\t\treturn normalized;\n\t\t}\n\t}\n\tif (branches.includes(\"main\")) {\n\t\treturn \"main\";\n\t}\n\tif (branches.includes(\"master\")) {\n\t\treturn \"master\";\n\t}\n\treturn branches[0] ?? null;\n}\n\nfunction detectGitRepositoryInfo(repoPath: string): RuntimeGitRepositoryInfo {\n\tconst gitRoot = detectGitRoot(repoPath);\n\tif (!gitRoot) {\n\t\tthrow new Error(`No git repository detected at ${repoPath}`);\n\t}\n\n\tconst currentBranch = detectGitCurrentBranch(repoPath);\n\tconst branches = detectGitBranches(repoPath);\n\tconst orderedBranches = currentBranch && !branches.includes(currentBranch) ? [currentBranch, ...branches] : branches;\n\tconst defaultBranch = detectGitDefaultBranch(repoPath, orderedBranches);\n\n\treturn {\n\t\tcurrentBranch,\n\t\tdefaultBranch,\n\t\tbranches: orderedBranches,\n\t};\n}\n\nasync function resolveWorkspacePath(cwd: string): Promise<string> {\n\tconst resolvedCwd = resolve(cwd);\n\tlet canonicalCwd = resolvedCwd;\n\ttry {\n\t\tcanonicalCwd = await realpath(resolvedCwd);\n\t} catch {\n\t\tcanonicalCwd = resolvedCwd;\n\t}\n\n\tconst gitRoot = detectGitRoot(canonicalCwd);\n\tif (!gitRoot) {\n\t\tthrow new Error(`No git repository detected at ${canonicalCwd}`);\n\t}\n\n\tconst resolvedGitRoot = resolve(gitRoot);\n\ttry {\n\t\treturn await realpath(resolvedGitRoot);\n\t} catch {\n\t\treturn resolvedGitRoot;\n\t}\n}\n\nfunction toWorkspaceStateResponse(\n\tcontext: RuntimeWorkspaceContext,\n\tboard: RuntimeBoardData,\n\tsessions: Record<string, RuntimeTaskSessionSummary>,\n\trevision: number,\n): RuntimeWorkspaceStateResponse {\n\treturn {\n\t\trepoPath: context.repoPath,\n\t\tstatePath: context.statePath,\n\t\tgit: context.git,\n\t\tboard,\n\t\tsessions,\n\t\trevision,\n\t};\n}\n\nexport class WorkspaceStateConflictError extends Error {\n\treadonly currentRevision: number;\n\n\tconstructor(expectedRevision: number, currentRevision: number) {\n\t\tsuper(`Workspace state revision mismatch: expected ${expectedRevision}, current ${currentRevision}.`);\n\t\tthis.name = \"WorkspaceStateConflictError\";\n\t\tthis.currentRevision = currentRevision;\n\t}\n}\n\nexport async function loadWorkspaceContext(\n\tcwd: string,\n\toptions: LoadWorkspaceContextOptions = {},\n): Promise<RuntimeWorkspaceContext> {\n\tconst repoPath = await resolveWorkspacePath(cwd);\n\tconst autoCreateIfMissing = options.autoCreateIfMissing ?? true;\n\tlet index = await readWorkspaceIndex();\n\tconst existingEntry = findWorkspaceEntry(index, repoPath);\n\tif (!autoCreateIfMissing) {\n\t\tif (!existingEntry) {\n\t\t\tthrow new Error(`Project ${repoPath} is not added to Kanban yet.`);\n\t\t}\n\t\treturn {\n\t\t\trepoPath,\n\t\t\tworkspaceId: existingEntry.workspaceId,\n\t\t\tstatePath: getWorkspaceDirectoryPath(existingEntry.workspaceId),\n\t\t\tgit: detectGitRepositoryInfo(repoPath),\n\t\t};\n\t}\n\n\tconst ensured = existingEntry\n\t\t? { index, entry: existingEntry, changed: false }\n\t\t: ensureWorkspaceEntry(index, repoPath);\n\tindex = ensured.index;\n\tif (ensured.changed) {\n\t\tawait writeWorkspaceIndex(index);\n\t}\n\n\treturn {\n\t\trepoPath,\n\t\tworkspaceId: ensured.entry.workspaceId,\n\t\tstatePath: getWorkspaceDirectoryPath(ensured.entry.workspaceId),\n\t\tgit: detectGitRepositoryInfo(repoPath),\n\t};\n}\n\nexport async function loadWorkspaceContextById(workspaceId: string): Promise<RuntimeWorkspaceContext | null> {\n\tconst index = await readWorkspaceIndex();\n\tconst entry = index.entries[workspaceId];\n\tif (!entry) {\n\t\treturn null;\n\t}\n\ttry {\n\t\treturn await loadWorkspaceContext(entry.repoPath);\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport async function listWorkspaceIndexEntries(): Promise<RuntimeWorkspaceIndexEntry[]> {\n\tconst index = await readWorkspaceIndex();\n\treturn Object.values(index.entries)\n\t\t.map((entry) => ({\n\t\t\tworkspaceId: entry.workspaceId,\n\t\t\trepoPath: entry.repoPath,\n\t\t}))\n\t\t.sort((left, right) => left.repoPath.localeCompare(right.repoPath));\n}\n\nexport async function removeWorkspaceIndexEntry(workspaceId: string): Promise<boolean> {\n\tconst index = await readWorkspaceIndex();\n\tconst entry = index.entries[workspaceId];\n\tif (!entry) {\n\t\treturn false;\n\t}\n\tdelete index.entries[workspaceId];\n\tdelete index.repoPathToId[entry.repoPath];\n\tawait writeWorkspaceIndex(index);\n\treturn true;\n}\n\nexport async function removeWorkspaceStateFiles(workspaceId: string): Promise<void> {\n\tawait rm(getWorkspaceDirectoryPath(workspaceId), {\n\t\trecursive: true,\n\t\tforce: true,\n\t});\n}\n\nexport async function loadWorkspaceState(cwd: string): Promise<RuntimeWorkspaceStateResponse> {\n\tconst context = await loadWorkspaceContext(cwd);\n\tconst board = await readWorkspaceBoard(context.workspaceId);\n\tconst sessions = await readWorkspaceSessions(context.workspaceId);\n\tconst meta = await readWorkspaceMeta(context.workspaceId);\n\treturn toWorkspaceStateResponse(context, board, sessions, meta.revision);\n}\n\nexport async function saveWorkspaceState(\n\tcwd: string,\n\tpayload: RuntimeWorkspaceStateSaveRequest,\n): Promise<RuntimeWorkspaceStateResponse> {\n\tconst parsedPayload = parseWorkspaceStateSavePayload(payload);\n\tconst context = await loadWorkspaceContext(cwd);\n\tconst metaPath = getWorkspaceMetaPath(context.workspaceId);\n\tconst currentMeta = await readWorkspaceMeta(context.workspaceId);\n\tconst expectedRevision = parsedPayload.expectedRevision;\n\tif (\n\t\ttypeof expectedRevision === \"number\" &&\n\t\tNumber.isInteger(expectedRevision) &&\n\t\texpectedRevision >= 0 &&\n\t\texpectedRevision !== currentMeta.revision\n\t) {\n\t\tthrow new WorkspaceStateConflictError(expectedRevision, currentMeta.revision);\n\t}\n\tconst board = parsedPayload.board;\n\tconst sessions = parsedPayload.sessions;\n\tconst nextRevision = currentMeta.revision + 1;\n\tconst nextMeta: WorkspaceStateMeta = {\n\t\trevision: nextRevision,\n\t\tupdatedAt: Date.now(),\n\t};\n\n\tawait writeJsonFileAtomic(getWorkspaceBoardPath(context.workspaceId), board);\n\tawait writeJsonFileAtomic(getWorkspaceSessionsPath(context.workspaceId), sessions);\n\tawait writeJsonFileAtomic(metaPath, nextMeta);\n\n\treturn toWorkspaceStateResponse(context, board, sessions, nextRevision);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"agent-session-adapters.d.ts","sourceRoot":"","sources":["../../src/terminal/agent-session-adapters.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAoB,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAW3G,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAEzE,MAAM,WAAW,uBAAuB;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,cAAc,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,6BAA6B,GAAG,CAC3C,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,yBAAyB,KAC9B,sBAAsB,GAAG,IAAI,CAAC;AAEnC,MAAM,MAAM,wCAAwC,GAAG,CAAC,OAAO,EAAE,yBAAyB,KAAK,OAAO,CAAC;AAEvG,MAAM,WAAW,mBAAmB;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACxC,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,sBAAsB,CAAC,EAAE,6BAA6B,CAAC;IACvD,gCAAgC,CAAC,EAAE,wCAAwC,CAAC;CAC5E;AAi9BD,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAErG"}
1
+ {"version":3,"file":"agent-session-adapters.d.ts","sourceRoot":"","sources":["../../src/terminal/agent-session-adapters.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAoB,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAW3G,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAEzE,MAAM,WAAW,uBAAuB;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,cAAc,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,6BAA6B,GAAG,CAC3C,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,yBAAyB,KAC9B,sBAAsB,GAAG,IAAI,CAAC;AAEnC,MAAM,MAAM,wCAAwC,GAAG,CAAC,OAAO,EAAE,yBAAyB,KAAK,OAAO,CAAC;AAEvG,MAAM,WAAW,mBAAmB;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACxC,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,sBAAsB,CAAC,EAAE,6BAA6B,CAAC;IACvD,gCAAgC,CAAC,EAAE,wCAAwC,CAAC;CAC5E;AAguCD,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAErG"}