kanban 0.1.18 → 0.1.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -381,7 +381,7 @@ async function runMainCommand(options) {
381
381
  }
382
382
  };
383
383
  closeWithGrace({
384
- delay: 3000,
384
+ delay: 10000,
385
385
  skip: ["uncaughtException", "unhandledRejection", "beforeExit"],
386
386
  onTimeout: (delayMs) => {
387
387
  console.error(`Forced exit after shutdown timeout (${delayMs}ms).`);
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n\nimport { spawn, spawnSync } from \"node:child_process\";\nimport { stat } from \"node:fs/promises\";\nimport { createServer as createNetServer } from \"node:net\";\nimport closeWithGrace from \"close-with-grace\";\nimport { Command } from \"commander\";\nimport packageJson from \"../package.json\" with { type: \"json\" };\n\nimport { registerHooksCommand } from \"./commands/hooks.js\";\nimport { registerTaskCommand } from \"./commands/task.js\";\nimport { loadRuntimeConfig, updateRuntimeConfig } from \"./config/runtime-config.js\";\nimport type { RuntimeAgentId, RuntimeCommandRunResponse } from \"./core/api-contract.js\";\nimport { createGitProcessEnv } from \"./core/git-process-env.js\";\nimport {\n\tbuildKanbanRuntimeUrl,\n\tDEFAULT_KANBAN_RUNTIME_PORT,\n\tgetKanbanRuntimeOrigin,\n\tgetKanbanRuntimePort,\n\tparseRuntimePort,\n\tsetKanbanRuntimePort,\n} from \"./core/runtime-endpoint.js\";\nimport { resolveProjectInputPath } from \"./projects/project-path.js\";\nimport { openInBrowser } from \"./server/browser.js\";\nimport { pickDirectoryPathFromSystemDialog } from \"./server/directory-picker.js\";\nimport { terminateProcessForTimeout } from \"./server/process-termination.js\";\nimport { createRuntimeServer } from \"./server/runtime-server.js\";\nimport { createRuntimeStateHub } from \"./server/runtime-state-hub.js\";\nimport { resolveInteractiveShellCommand } from \"./server/shell.js\";\nimport { shutdownRuntimeServer } from \"./server/shutdown-coordinator.js\";\nimport { collectProjectWorktreeTaskIdsForRemoval, createWorkspaceRegistry } from \"./server/workspace-registry.js\";\nimport { installKanbanSkillFiles, resolveKanbanSkillCommandPrefix } from \"./skills/kanban-skill.js\";\nimport { loadWorkspaceContext } from \"./state/workspace-state.js\";\nimport { detectInstalledCommands } from \"./terminal/agent-registry.js\";\nimport type { TerminalSessionManager } from \"./terminal/session-manager.js\";\nimport { autoUpdateOnStartup, runPendingAutoUpdateOnShutdown } from \"./update/auto-update.js\";\n\ninterface CliOptions {\n\tnoOpen: boolean;\n\tskipShutdownCleanup: boolean;\n\tagent: RuntimeAgentId | null;\n\tport: { mode: \"fixed\"; value: number } | { mode: \"auto\" } | null;\n}\n\nconst CLI_AGENT_IDS: readonly RuntimeAgentId[] = [\"claude\", \"codex\", \"gemini\", \"opencode\", \"droid\", \"cline\"];\nconst KANBAN_VERSION = typeof packageJson.version === \"string\" ? packageJson.version : \"0.1.0\";\n\nfunction parseCliAgentId(value: string): RuntimeAgentId {\n\tconst normalized = value.trim().toLowerCase();\n\tif (\n\t\tnormalized === \"claude\" ||\n\t\tnormalized === \"codex\" ||\n\t\tnormalized === \"gemini\" ||\n\t\tnormalized === \"opencode\" ||\n\t\tnormalized === \"droid\" ||\n\t\tnormalized === \"cline\"\n\t) {\n\t\treturn normalized;\n\t}\n\tthrow new Error(`Invalid agent: ${value}. Expected one of: ${CLI_AGENT_IDS.join(\", \")}`);\n}\n\nfunction parseCliPortValue(rawValue: string): { mode: \"fixed\"; value: number } | { mode: \"auto\" } {\n\tconst normalized = rawValue.trim().toLowerCase();\n\tif (!normalized) {\n\t\tthrow new Error(\"Missing value for --port.\");\n\t}\n\tif (normalized === \"auto\") {\n\t\treturn { mode: \"auto\" };\n\t}\n\ttry {\n\t\treturn { mode: \"fixed\", value: parseRuntimePort(normalized) };\n\t} catch {\n\t\tthrow new Error(`Invalid port value: ${rawValue}. Expected an integer from 1-65535 or \"auto\".`);\n\t}\n}\n\ninterface RootCommandOptions {\n\tagent?: RuntimeAgentId;\n\tport?: { mode: \"fixed\"; value: number } | { mode: \"auto\" };\n\topen?: boolean;\n\tskipShutdownCleanup?: boolean;\n}\n\nasync function isPortAvailable(port: number): Promise<boolean> {\n\treturn await new Promise<boolean>((resolve) => {\n\t\tconst probe = createNetServer();\n\t\tprobe.once(\"error\", () => {\n\t\t\tresolve(false);\n\t\t});\n\t\tprobe.listen(port, \"127.0.0.1\", () => {\n\t\t\tprobe.close(() => {\n\t\t\t\tresolve(true);\n\t\t\t});\n\t\t});\n\t});\n}\n\nasync function findAvailableRuntimePort(startPort: number): Promise<number> {\n\tfor (let candidate = startPort; candidate <= 65535; candidate += 1) {\n\t\tif (await isPortAvailable(candidate)) {\n\t\t\treturn candidate;\n\t\t}\n\t}\n\tthrow new Error(\"No available runtime port found.\");\n}\n\nasync function applyRuntimePortOption(portOption: CliOptions[\"port\"]): Promise<number | null> {\n\tif (!portOption) {\n\t\treturn null;\n\t}\n\tif (portOption.mode === \"fixed\") {\n\t\tsetKanbanRuntimePort(portOption.value);\n\t\treturn portOption.value;\n\t}\n\tconst autoPort = await findAvailableRuntimePort(DEFAULT_KANBAN_RUNTIME_PORT);\n\tsetKanbanRuntimePort(autoPort);\n\treturn autoPort;\n}\n\nasync function persistCliAgentSelection(cwd: string, selectedAgentId: RuntimeAgentId): Promise<boolean> {\n\tconst currentRuntimeConfig = await loadRuntimeConfig(cwd);\n\tif (currentRuntimeConfig.selectedAgentId === selectedAgentId) {\n\t\treturn false;\n\t}\n\tawait updateRuntimeConfig(cwd, { selectedAgentId });\n\treturn true;\n}\n\nasync function assertPathIsDirectory(path: string): Promise<void> {\n\tconst info = await stat(path);\n\tif (!info.isDirectory()) {\n\t\tthrow new Error(`Project path is not a directory: ${path}`);\n\t}\n}\n\nasync function pathIsDirectory(path: string): Promise<boolean> {\n\ttry {\n\t\tconst info = await stat(path);\n\t\treturn info.isDirectory();\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction hasGitRepository(path: string): boolean {\n\tconst result = spawnSync(\"git\", [\"rev-parse\", \"--is-inside-work-tree\"], {\n\t\tcwd: path,\n\t\tencoding: \"utf8\",\n\t\tstdio: [\"ignore\", \"pipe\", \"ignore\"],\n\t\tenv: createGitProcessEnv(),\n\t});\n\treturn result.status === 0 && result.stdout.trim() === \"true\";\n}\n\nfunction isAddressInUseError(error: unknown): error is NodeJS.ErrnoException {\n\treturn (\n\t\ttypeof error === \"object\" &&\n\t\terror !== null &&\n\t\t\"code\" in error &&\n\t\t(error as NodeJS.ErrnoException).code === \"EADDRINUSE\"\n\t);\n}\n\nasync function canReachKanbanServer(workspaceId: string | null): Promise<boolean> {\n\ttry {\n\t\tconst headers: Record<string, string> = {};\n\t\tif (workspaceId) {\n\t\t\theaders[\"x-kanban-workspace-id\"] = workspaceId;\n\t\t}\n\t\tconst response = await fetch(buildKanbanRuntimeUrl(\"/api/trpc/projects.list\"), {\n\t\t\tmethod: \"GET\",\n\t\t\theaders,\n\t\t\tsignal: AbortSignal.timeout(1_500),\n\t\t});\n\t\tif (response.status === 404) {\n\t\t\treturn false;\n\t\t}\n\t\tconst payload = (await response.json().catch(() => null)) as {\n\t\t\tresult?: { data?: unknown };\n\t\t\terror?: unknown;\n\t\t} | null;\n\t\treturn Boolean(payload && (payload.result || payload.error));\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nasync function tryOpenExistingServer(noOpen: boolean): Promise<boolean> {\n\tlet workspaceId: string | null = null;\n\tif (hasGitRepository(process.cwd())) {\n\t\tconst context = await loadWorkspaceContext(process.cwd());\n\t\tworkspaceId = context.workspaceId;\n\t}\n\tconst running = await canReachKanbanServer(workspaceId);\n\tif (!running) {\n\t\treturn false;\n\t}\n\tconst projectUrl = workspaceId\n\t\t? buildKanbanRuntimeUrl(`/${encodeURIComponent(workspaceId)}`)\n\t\t: getKanbanRuntimeOrigin();\n\tconsole.log(`Kanban already running at ${getKanbanRuntimeOrigin()}`);\n\tif (!noOpen) {\n\t\ttry {\n\t\t\topenInBrowser(projectUrl, {\n\t\t\t\twarn: (message) => {\n\t\t\t\t\tconsole.warn(message);\n\t\t\t\t},\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tconsole.warn(`Could not open browser automatically: ${message}`);\n\t\t}\n\t}\n\tconsole.log(`Project URL: ${projectUrl}`);\n\treturn true;\n}\n\nasync function runScopedCommand(command: string, cwd: string): Promise<RuntimeCommandRunResponse> {\n\tconst startedAt = Date.now();\n\tconst outputLimitBytes = 64 * 1024;\n\n\treturn await new Promise<RuntimeCommandRunResponse>((resolve, reject) => {\n\t\tconst child = spawn(command, {\n\t\t\tcwd,\n\t\t\tshell: true,\n\t\t\tenv: process.env,\n\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t});\n\n\t\tif (!child.stdout || !child.stderr) {\n\t\t\treject(new Error(\"Shortcut process did not expose stdout/stderr.\"));\n\t\t\treturn;\n\t\t}\n\n\t\tlet stdout = \"\";\n\t\tlet stderr = \"\";\n\n\t\tconst appendOutput = (current: string, chunk: string): string => {\n\t\t\tconst next = current + chunk;\n\t\t\tif (next.length <= outputLimitBytes) {\n\t\t\t\treturn next;\n\t\t\t}\n\t\t\treturn next.slice(0, outputLimitBytes);\n\t\t};\n\n\t\tchild.stdout.on(\"data\", (chunk: Buffer | string) => {\n\t\t\tstdout = appendOutput(stdout, String(chunk));\n\t\t});\n\n\t\tchild.stderr.on(\"data\", (chunk: Buffer | string) => {\n\t\t\tstderr = appendOutput(stderr, String(chunk));\n\t\t});\n\n\t\tchild.on(\"error\", (error) => {\n\t\t\treject(error);\n\t\t});\n\n\t\tconst timeout = setTimeout(() => {\n\t\t\tterminateProcessForTimeout(child);\n\t\t}, 60_000);\n\n\t\tchild.on(\"close\", (code) => {\n\t\t\tclearTimeout(timeout);\n\t\t\tconst exitCode = typeof code === \"number\" ? code : 1;\n\t\t\tconst combinedOutput = [stdout.trim(), stderr.trim()].filter(Boolean).join(\"\\n\");\n\t\t\tresolve({\n\t\t\t\texitCode,\n\t\t\t\tstdout: stdout.trim(),\n\t\t\t\tstderr: stderr.trim(),\n\t\t\t\tcombinedOutput,\n\t\t\t\tdurationMs: Date.now() - startedAt,\n\t\t\t});\n\t\t});\n\t});\n}\n\nasync function startServer(): Promise<{\n\turl: string;\n\tclose: () => Promise<void>;\n\tshutdown: (options?: { skipSessionCleanup?: boolean }) => Promise<void>;\n}> {\n\tlet runtimeStateHub: ReturnType<typeof createRuntimeStateHub> | undefined;\n\tconst workspaceRegistry = await createWorkspaceRegistry({\n\t\tcwd: process.cwd(),\n\t\tloadRuntimeConfig,\n\t\thasGitRepository,\n\t\tpathIsDirectory,\n\t\tonTerminalManagerReady: (workspaceId, manager) => {\n\t\t\truntimeStateHub?.trackTerminalManager(workspaceId, manager);\n\t\t},\n\t});\n\truntimeStateHub = createRuntimeStateHub({\n\t\tworkspaceRegistry,\n\t});\n\tconst runtimeHub = runtimeStateHub;\n\tfor (const { workspaceId, terminalManager } of workspaceRegistry.listManagedWorkspaces()) {\n\t\truntimeHub.trackTerminalManager(workspaceId, terminalManager);\n\t}\n\n\tconst disposeTrackedWorkspace = (\n\t\tworkspaceId: string,\n\t\toptions?: {\n\t\t\tstopTerminalSessions?: boolean;\n\t\t},\n\t): { terminalManager: TerminalSessionManager | null; workspacePath: string | null } => {\n\t\tconst disposed = workspaceRegistry.disposeWorkspace(workspaceId, {\n\t\t\tstopTerminalSessions: options?.stopTerminalSessions,\n\t\t});\n\t\truntimeHub.disposeWorkspace(workspaceId);\n\t\treturn disposed;\n\t};\n\n\tconst runtimeServer = await createRuntimeServer({\n\t\tworkspaceRegistry,\n\t\truntimeStateHub: runtimeHub,\n\t\twarn: (message) => {\n\t\t\tconsole.warn(`[kanban] ${message}`);\n\t\t},\n\t\tensureTerminalManagerForWorkspace: workspaceRegistry.ensureTerminalManagerForWorkspace,\n\t\tresolveInteractiveShellCommand,\n\t\trunCommand: runScopedCommand,\n\t\tresolveProjectInputPath,\n\t\tassertPathIsDirectory,\n\t\thasGitRepository,\n\t\tdisposeWorkspace: disposeTrackedWorkspace,\n\t\tcollectProjectWorktreeTaskIdsForRemoval,\n\t\tpickDirectoryPathFromSystemDialog,\n\t});\n\n\tconst close = async () => {\n\t\tawait runtimeServer.close();\n\t};\n\n\tconst shutdown = async (options?: { skipSessionCleanup?: boolean }) => {\n\t\tawait shutdownRuntimeServer({\n\t\t\tworkspaceRegistry,\n\t\t\twarn: (message) => {\n\t\t\t\tconsole.warn(`[kanban] ${message}`);\n\t\t\t},\n\t\t\tcloseRuntimeServer: close,\n\t\t\tskipSessionCleanup: options?.skipSessionCleanup ?? false,\n\t\t});\n\t};\n\n\treturn {\n\t\turl: runtimeServer.url,\n\t\tclose,\n\t\tshutdown,\n\t};\n}\n\nasync function startServerWithAutoPortRetry(options: CliOptions): Promise<Awaited<ReturnType<typeof startServer>>> {\n\tif (options.port?.mode !== \"auto\") {\n\t\treturn await startServer();\n\t}\n\n\twhile (true) {\n\t\ttry {\n\t\t\treturn await startServer();\n\t\t} catch (error) {\n\t\t\tif (!isAddressInUseError(error)) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tconst currentPort = getKanbanRuntimePort();\n\t\t\tconst retryPort = await findAvailableRuntimePort(currentPort + 1);\n\t\t\tsetKanbanRuntimePort(retryPort);\n\t\t\tconsole.warn(`Runtime port ${currentPort} became busy during startup, retrying on ${retryPort}.`);\n\t\t}\n\t}\n}\n\nasync function runMainCommand(options: CliOptions): Promise<void> {\n\tconst selectedPort = await applyRuntimePortOption(options.port);\n\tif (selectedPort !== null) {\n\t\tconsole.log(`Using runtime port ${selectedPort}.`);\n\t}\n\n\tautoUpdateOnStartup({\n\t\tcurrentVersion: KANBAN_VERSION,\n\t});\n\n\tif (options.agent) {\n\t\tconst didChange = await persistCliAgentSelection(process.cwd(), options.agent);\n\t\tif (didChange) {\n\t\t\tconsole.log(`Default agent set to ${options.agent}.`);\n\t\t}\n\t}\n\n\ttry {\n\t\tconst detectedCommands = detectInstalledCommands();\n\t\tconst commandPrefix = resolveKanbanSkillCommandPrefix({\n\t\t\tcurrentVersion: KANBAN_VERSION,\n\t\t});\n\t\tawait installKanbanSkillFiles({\n\t\t\tcommandPrefix,\n\t\t\tinstallClaudeSkill: detectedCommands.includes(\"claude\"),\n\t\t});\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tconsole.warn(`Could not install Kanban skill files: ${message}`);\n\t}\n\n\tlet runtime: Awaited<ReturnType<typeof startServer>>;\n\ttry {\n\t\truntime = await startServerWithAutoPortRetry(options);\n\t} catch (error) {\n\t\tif (\n\t\t\toptions.port?.mode !== \"auto\" &&\n\t\t\tisAddressInUseError(error) &&\n\t\t\t(await tryOpenExistingServer(options.noOpen))\n\t\t) {\n\t\t\treturn;\n\t\t}\n\t\tthrow error;\n\t}\n\tconsole.log(`Kanban running at ${runtime.url}`);\n\tif (!options.noOpen) {\n\t\ttry {\n\t\t\topenInBrowser(runtime.url, {\n\t\t\t\twarn: (message) => {\n\t\t\t\t\tconsole.warn(message);\n\t\t\t\t},\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tconsole.warn(`Could not open browser automatically: ${message}`);\n\t\t}\n\t}\n\tconsole.log(\"Press Ctrl+C to stop.\");\n\n\tlet isShuttingDown = false;\n\tconst shutdown = async (signal: NodeJS.Signals | null) => {\n\t\tif (isShuttingDown) {\n\t\t\tprocess.exit(130);\n\t\t\treturn;\n\t\t}\n\t\tisShuttingDown = true;\n\t\trunPendingAutoUpdateOnShutdown();\n\t\ttry {\n\t\t\tif (options.skipShutdownCleanup) {\n\t\t\t\tconsole.warn(\"Skipping shutdown task cleanup for this instance.\");\n\t\t\t}\n\t\t\tawait runtime.shutdown({\n\t\t\t\tskipSessionCleanup: options.skipShutdownCleanup,\n\t\t\t});\n\t\t\tprocess.exit(signal ? 130 : 0);\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tconsole.error(`Shutdown failed: ${message}`);\n\t\t\tprocess.exit(1);\n\t\t}\n\t};\n\n\tcloseWithGrace(\n\t\t{\n\t\t\tdelay: 3000,\n\t\t\tskip: [\"uncaughtException\", \"unhandledRejection\", \"beforeExit\"],\n\t\t\tonTimeout: (delayMs) => {\n\t\t\t\tconsole.error(`Forced exit after shutdown timeout (${delayMs}ms).`);\n\t\t\t},\n\t\t\tonSecondSignal: (signal) => {\n\t\t\t\tconsole.error(`Forced exit on second signal: ${signal}`);\n\t\t\t},\n\t\t},\n\t\tasync ({ signal }) => {\n\t\t\tawait shutdown(signal ?? null);\n\t\t},\n\t);\n}\n\nfunction createProgram(): Command {\n\tconst program = new Command();\n\tprogram\n\t\t.name(\"kanban\")\n\t\t.description(\"Local orchestration board for coding agents.\")\n\t\t.version(KANBAN_VERSION, \"-v, --version\", \"Output the version number\")\n\t\t.option(\"--agent <id>\", `Default agent ID (${CLI_AGENT_IDS.join(\", \")}).`, parseCliAgentId)\n\t\t.option(\"--port <number|auto>\", \"Runtime port (1-65535) or auto.\", parseCliPortValue)\n\t\t.option(\"--no-open\", \"Do not open browser automatically.\")\n\t\t.option(\"--skip-shutdown-cleanup\", \"Do not move sessions to trash or delete task worktrees on shutdown.\")\n\t\t.showHelpAfterError()\n\t\t.addHelpText(\"after\", `\\nRuntime URL: ${getKanbanRuntimeOrigin()}\\nAgent IDs: ${CLI_AGENT_IDS.join(\", \")}`);\n\n\tregisterTaskCommand(program);\n\tregisterHooksCommand(program);\n\n\tprogram\n\t\t.command(\"mcp\")\n\t\t.description(\"Deprecated compatibility command.\")\n\t\t.action(() => {\n\t\t\tconsole.warn(\"Deprecated. Please uninstall Kanban MCP.\");\n\t\t});\n\n\tprogram.action(async (options: RootCommandOptions) => {\n\t\tawait runMainCommand({\n\t\t\tagent: options.agent ?? null,\n\t\t\tport: options.port ?? null,\n\t\t\tnoOpen: options.open === false,\n\t\t\tskipShutdownCleanup: options.skipShutdownCleanup === true,\n\t\t});\n\t});\n\n\treturn program;\n}\n\nasync function run(): Promise<void> {\n\tconst argv = process.argv.slice(2);\n\tconst program = createProgram();\n\tawait program.parseAsync(argv, { from: \"user\" });\n}\n\nrun().catch((error) => {\n\tconst message = error instanceof Error ? error.message : String(error);\n\tconsole.error(`Failed to start Kanban: ${message}`);\n\tprocess.exit(1);\n});\n"]}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n\nimport { spawn, spawnSync } from \"node:child_process\";\nimport { stat } from \"node:fs/promises\";\nimport { createServer as createNetServer } from \"node:net\";\nimport closeWithGrace from \"close-with-grace\";\nimport { Command } from \"commander\";\nimport packageJson from \"../package.json\" with { type: \"json\" };\n\nimport { registerHooksCommand } from \"./commands/hooks.js\";\nimport { registerTaskCommand } from \"./commands/task.js\";\nimport { loadRuntimeConfig, updateRuntimeConfig } from \"./config/runtime-config.js\";\nimport type { RuntimeAgentId, RuntimeCommandRunResponse } from \"./core/api-contract.js\";\nimport { createGitProcessEnv } from \"./core/git-process-env.js\";\nimport {\n\tbuildKanbanRuntimeUrl,\n\tDEFAULT_KANBAN_RUNTIME_PORT,\n\tgetKanbanRuntimeOrigin,\n\tgetKanbanRuntimePort,\n\tparseRuntimePort,\n\tsetKanbanRuntimePort,\n} from \"./core/runtime-endpoint.js\";\nimport { resolveProjectInputPath } from \"./projects/project-path.js\";\nimport { openInBrowser } from \"./server/browser.js\";\nimport { pickDirectoryPathFromSystemDialog } from \"./server/directory-picker.js\";\nimport { terminateProcessForTimeout } from \"./server/process-termination.js\";\nimport { createRuntimeServer } from \"./server/runtime-server.js\";\nimport { createRuntimeStateHub } from \"./server/runtime-state-hub.js\";\nimport { resolveInteractiveShellCommand } from \"./server/shell.js\";\nimport { shutdownRuntimeServer } from \"./server/shutdown-coordinator.js\";\nimport { collectProjectWorktreeTaskIdsForRemoval, createWorkspaceRegistry } from \"./server/workspace-registry.js\";\nimport { installKanbanSkillFiles, resolveKanbanSkillCommandPrefix } from \"./skills/kanban-skill.js\";\nimport { loadWorkspaceContext } from \"./state/workspace-state.js\";\nimport { detectInstalledCommands } from \"./terminal/agent-registry.js\";\nimport type { TerminalSessionManager } from \"./terminal/session-manager.js\";\nimport { autoUpdateOnStartup, runPendingAutoUpdateOnShutdown } from \"./update/auto-update.js\";\n\ninterface CliOptions {\n\tnoOpen: boolean;\n\tskipShutdownCleanup: boolean;\n\tagent: RuntimeAgentId | null;\n\tport: { mode: \"fixed\"; value: number } | { mode: \"auto\" } | null;\n}\n\nconst CLI_AGENT_IDS: readonly RuntimeAgentId[] = [\"claude\", \"codex\", \"gemini\", \"opencode\", \"droid\", \"cline\"];\nconst KANBAN_VERSION = typeof packageJson.version === \"string\" ? packageJson.version : \"0.1.0\";\n\nfunction parseCliAgentId(value: string): RuntimeAgentId {\n\tconst normalized = value.trim().toLowerCase();\n\tif (\n\t\tnormalized === \"claude\" ||\n\t\tnormalized === \"codex\" ||\n\t\tnormalized === \"gemini\" ||\n\t\tnormalized === \"opencode\" ||\n\t\tnormalized === \"droid\" ||\n\t\tnormalized === \"cline\"\n\t) {\n\t\treturn normalized;\n\t}\n\tthrow new Error(`Invalid agent: ${value}. Expected one of: ${CLI_AGENT_IDS.join(\", \")}`);\n}\n\nfunction parseCliPortValue(rawValue: string): { mode: \"fixed\"; value: number } | { mode: \"auto\" } {\n\tconst normalized = rawValue.trim().toLowerCase();\n\tif (!normalized) {\n\t\tthrow new Error(\"Missing value for --port.\");\n\t}\n\tif (normalized === \"auto\") {\n\t\treturn { mode: \"auto\" };\n\t}\n\ttry {\n\t\treturn { mode: \"fixed\", value: parseRuntimePort(normalized) };\n\t} catch {\n\t\tthrow new Error(`Invalid port value: ${rawValue}. Expected an integer from 1-65535 or \"auto\".`);\n\t}\n}\n\ninterface RootCommandOptions {\n\tagent?: RuntimeAgentId;\n\tport?: { mode: \"fixed\"; value: number } | { mode: \"auto\" };\n\topen?: boolean;\n\tskipShutdownCleanup?: boolean;\n}\n\nasync function isPortAvailable(port: number): Promise<boolean> {\n\treturn await new Promise<boolean>((resolve) => {\n\t\tconst probe = createNetServer();\n\t\tprobe.once(\"error\", () => {\n\t\t\tresolve(false);\n\t\t});\n\t\tprobe.listen(port, \"127.0.0.1\", () => {\n\t\t\tprobe.close(() => {\n\t\t\t\tresolve(true);\n\t\t\t});\n\t\t});\n\t});\n}\n\nasync function findAvailableRuntimePort(startPort: number): Promise<number> {\n\tfor (let candidate = startPort; candidate <= 65535; candidate += 1) {\n\t\tif (await isPortAvailable(candidate)) {\n\t\t\treturn candidate;\n\t\t}\n\t}\n\tthrow new Error(\"No available runtime port found.\");\n}\n\nasync function applyRuntimePortOption(portOption: CliOptions[\"port\"]): Promise<number | null> {\n\tif (!portOption) {\n\t\treturn null;\n\t}\n\tif (portOption.mode === \"fixed\") {\n\t\tsetKanbanRuntimePort(portOption.value);\n\t\treturn portOption.value;\n\t}\n\tconst autoPort = await findAvailableRuntimePort(DEFAULT_KANBAN_RUNTIME_PORT);\n\tsetKanbanRuntimePort(autoPort);\n\treturn autoPort;\n}\n\nasync function persistCliAgentSelection(cwd: string, selectedAgentId: RuntimeAgentId): Promise<boolean> {\n\tconst currentRuntimeConfig = await loadRuntimeConfig(cwd);\n\tif (currentRuntimeConfig.selectedAgentId === selectedAgentId) {\n\t\treturn false;\n\t}\n\tawait updateRuntimeConfig(cwd, { selectedAgentId });\n\treturn true;\n}\n\nasync function assertPathIsDirectory(path: string): Promise<void> {\n\tconst info = await stat(path);\n\tif (!info.isDirectory()) {\n\t\tthrow new Error(`Project path is not a directory: ${path}`);\n\t}\n}\n\nasync function pathIsDirectory(path: string): Promise<boolean> {\n\ttry {\n\t\tconst info = await stat(path);\n\t\treturn info.isDirectory();\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction hasGitRepository(path: string): boolean {\n\tconst result = spawnSync(\"git\", [\"rev-parse\", \"--is-inside-work-tree\"], {\n\t\tcwd: path,\n\t\tencoding: \"utf8\",\n\t\tstdio: [\"ignore\", \"pipe\", \"ignore\"],\n\t\tenv: createGitProcessEnv(),\n\t});\n\treturn result.status === 0 && result.stdout.trim() === \"true\";\n}\n\nfunction isAddressInUseError(error: unknown): error is NodeJS.ErrnoException {\n\treturn (\n\t\ttypeof error === \"object\" &&\n\t\terror !== null &&\n\t\t\"code\" in error &&\n\t\t(error as NodeJS.ErrnoException).code === \"EADDRINUSE\"\n\t);\n}\n\nasync function canReachKanbanServer(workspaceId: string | null): Promise<boolean> {\n\ttry {\n\t\tconst headers: Record<string, string> = {};\n\t\tif (workspaceId) {\n\t\t\theaders[\"x-kanban-workspace-id\"] = workspaceId;\n\t\t}\n\t\tconst response = await fetch(buildKanbanRuntimeUrl(\"/api/trpc/projects.list\"), {\n\t\t\tmethod: \"GET\",\n\t\t\theaders,\n\t\t\tsignal: AbortSignal.timeout(1_500),\n\t\t});\n\t\tif (response.status === 404) {\n\t\t\treturn false;\n\t\t}\n\t\tconst payload = (await response.json().catch(() => null)) as {\n\t\t\tresult?: { data?: unknown };\n\t\t\terror?: unknown;\n\t\t} | null;\n\t\treturn Boolean(payload && (payload.result || payload.error));\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nasync function tryOpenExistingServer(noOpen: boolean): Promise<boolean> {\n\tlet workspaceId: string | null = null;\n\tif (hasGitRepository(process.cwd())) {\n\t\tconst context = await loadWorkspaceContext(process.cwd());\n\t\tworkspaceId = context.workspaceId;\n\t}\n\tconst running = await canReachKanbanServer(workspaceId);\n\tif (!running) {\n\t\treturn false;\n\t}\n\tconst projectUrl = workspaceId\n\t\t? buildKanbanRuntimeUrl(`/${encodeURIComponent(workspaceId)}`)\n\t\t: getKanbanRuntimeOrigin();\n\tconsole.log(`Kanban already running at ${getKanbanRuntimeOrigin()}`);\n\tif (!noOpen) {\n\t\ttry {\n\t\t\topenInBrowser(projectUrl, {\n\t\t\t\twarn: (message) => {\n\t\t\t\t\tconsole.warn(message);\n\t\t\t\t},\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tconsole.warn(`Could not open browser automatically: ${message}`);\n\t\t}\n\t}\n\tconsole.log(`Project URL: ${projectUrl}`);\n\treturn true;\n}\n\nasync function runScopedCommand(command: string, cwd: string): Promise<RuntimeCommandRunResponse> {\n\tconst startedAt = Date.now();\n\tconst outputLimitBytes = 64 * 1024;\n\n\treturn await new Promise<RuntimeCommandRunResponse>((resolve, reject) => {\n\t\tconst child = spawn(command, {\n\t\t\tcwd,\n\t\t\tshell: true,\n\t\t\tenv: process.env,\n\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t});\n\n\t\tif (!child.stdout || !child.stderr) {\n\t\t\treject(new Error(\"Shortcut process did not expose stdout/stderr.\"));\n\t\t\treturn;\n\t\t}\n\n\t\tlet stdout = \"\";\n\t\tlet stderr = \"\";\n\n\t\tconst appendOutput = (current: string, chunk: string): string => {\n\t\t\tconst next = current + chunk;\n\t\t\tif (next.length <= outputLimitBytes) {\n\t\t\t\treturn next;\n\t\t\t}\n\t\t\treturn next.slice(0, outputLimitBytes);\n\t\t};\n\n\t\tchild.stdout.on(\"data\", (chunk: Buffer | string) => {\n\t\t\tstdout = appendOutput(stdout, String(chunk));\n\t\t});\n\n\t\tchild.stderr.on(\"data\", (chunk: Buffer | string) => {\n\t\t\tstderr = appendOutput(stderr, String(chunk));\n\t\t});\n\n\t\tchild.on(\"error\", (error) => {\n\t\t\treject(error);\n\t\t});\n\n\t\tconst timeout = setTimeout(() => {\n\t\t\tterminateProcessForTimeout(child);\n\t\t}, 60_000);\n\n\t\tchild.on(\"close\", (code) => {\n\t\t\tclearTimeout(timeout);\n\t\t\tconst exitCode = typeof code === \"number\" ? code : 1;\n\t\t\tconst combinedOutput = [stdout.trim(), stderr.trim()].filter(Boolean).join(\"\\n\");\n\t\t\tresolve({\n\t\t\t\texitCode,\n\t\t\t\tstdout: stdout.trim(),\n\t\t\t\tstderr: stderr.trim(),\n\t\t\t\tcombinedOutput,\n\t\t\t\tdurationMs: Date.now() - startedAt,\n\t\t\t});\n\t\t});\n\t});\n}\n\nasync function startServer(): Promise<{\n\turl: string;\n\tclose: () => Promise<void>;\n\tshutdown: (options?: { skipSessionCleanup?: boolean }) => Promise<void>;\n}> {\n\tlet runtimeStateHub: ReturnType<typeof createRuntimeStateHub> | undefined;\n\tconst workspaceRegistry = await createWorkspaceRegistry({\n\t\tcwd: process.cwd(),\n\t\tloadRuntimeConfig,\n\t\thasGitRepository,\n\t\tpathIsDirectory,\n\t\tonTerminalManagerReady: (workspaceId, manager) => {\n\t\t\truntimeStateHub?.trackTerminalManager(workspaceId, manager);\n\t\t},\n\t});\n\truntimeStateHub = createRuntimeStateHub({\n\t\tworkspaceRegistry,\n\t});\n\tconst runtimeHub = runtimeStateHub;\n\tfor (const { workspaceId, terminalManager } of workspaceRegistry.listManagedWorkspaces()) {\n\t\truntimeHub.trackTerminalManager(workspaceId, terminalManager);\n\t}\n\n\tconst disposeTrackedWorkspace = (\n\t\tworkspaceId: string,\n\t\toptions?: {\n\t\t\tstopTerminalSessions?: boolean;\n\t\t},\n\t): { terminalManager: TerminalSessionManager | null; workspacePath: string | null } => {\n\t\tconst disposed = workspaceRegistry.disposeWorkspace(workspaceId, {\n\t\t\tstopTerminalSessions: options?.stopTerminalSessions,\n\t\t});\n\t\truntimeHub.disposeWorkspace(workspaceId);\n\t\treturn disposed;\n\t};\n\n\tconst runtimeServer = await createRuntimeServer({\n\t\tworkspaceRegistry,\n\t\truntimeStateHub: runtimeHub,\n\t\twarn: (message) => {\n\t\t\tconsole.warn(`[kanban] ${message}`);\n\t\t},\n\t\tensureTerminalManagerForWorkspace: workspaceRegistry.ensureTerminalManagerForWorkspace,\n\t\tresolveInteractiveShellCommand,\n\t\trunCommand: runScopedCommand,\n\t\tresolveProjectInputPath,\n\t\tassertPathIsDirectory,\n\t\thasGitRepository,\n\t\tdisposeWorkspace: disposeTrackedWorkspace,\n\t\tcollectProjectWorktreeTaskIdsForRemoval,\n\t\tpickDirectoryPathFromSystemDialog,\n\t});\n\n\tconst close = async () => {\n\t\tawait runtimeServer.close();\n\t};\n\n\tconst shutdown = async (options?: { skipSessionCleanup?: boolean }) => {\n\t\tawait shutdownRuntimeServer({\n\t\t\tworkspaceRegistry,\n\t\t\twarn: (message) => {\n\t\t\t\tconsole.warn(`[kanban] ${message}`);\n\t\t\t},\n\t\t\tcloseRuntimeServer: close,\n\t\t\tskipSessionCleanup: options?.skipSessionCleanup ?? false,\n\t\t});\n\t};\n\n\treturn {\n\t\turl: runtimeServer.url,\n\t\tclose,\n\t\tshutdown,\n\t};\n}\n\nasync function startServerWithAutoPortRetry(options: CliOptions): Promise<Awaited<ReturnType<typeof startServer>>> {\n\tif (options.port?.mode !== \"auto\") {\n\t\treturn await startServer();\n\t}\n\n\twhile (true) {\n\t\ttry {\n\t\t\treturn await startServer();\n\t\t} catch (error) {\n\t\t\tif (!isAddressInUseError(error)) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tconst currentPort = getKanbanRuntimePort();\n\t\t\tconst retryPort = await findAvailableRuntimePort(currentPort + 1);\n\t\t\tsetKanbanRuntimePort(retryPort);\n\t\t\tconsole.warn(`Runtime port ${currentPort} became busy during startup, retrying on ${retryPort}.`);\n\t\t}\n\t}\n}\n\nasync function runMainCommand(options: CliOptions): Promise<void> {\n\tconst selectedPort = await applyRuntimePortOption(options.port);\n\tif (selectedPort !== null) {\n\t\tconsole.log(`Using runtime port ${selectedPort}.`);\n\t}\n\n\tautoUpdateOnStartup({\n\t\tcurrentVersion: KANBAN_VERSION,\n\t});\n\n\tif (options.agent) {\n\t\tconst didChange = await persistCliAgentSelection(process.cwd(), options.agent);\n\t\tif (didChange) {\n\t\t\tconsole.log(`Default agent set to ${options.agent}.`);\n\t\t}\n\t}\n\n\ttry {\n\t\tconst detectedCommands = detectInstalledCommands();\n\t\tconst commandPrefix = resolveKanbanSkillCommandPrefix({\n\t\t\tcurrentVersion: KANBAN_VERSION,\n\t\t});\n\t\tawait installKanbanSkillFiles({\n\t\t\tcommandPrefix,\n\t\t\tinstallClaudeSkill: detectedCommands.includes(\"claude\"),\n\t\t});\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tconsole.warn(`Could not install Kanban skill files: ${message}`);\n\t}\n\n\tlet runtime: Awaited<ReturnType<typeof startServer>>;\n\ttry {\n\t\truntime = await startServerWithAutoPortRetry(options);\n\t} catch (error) {\n\t\tif (\n\t\t\toptions.port?.mode !== \"auto\" &&\n\t\t\tisAddressInUseError(error) &&\n\t\t\t(await tryOpenExistingServer(options.noOpen))\n\t\t) {\n\t\t\treturn;\n\t\t}\n\t\tthrow error;\n\t}\n\tconsole.log(`Kanban running at ${runtime.url}`);\n\tif (!options.noOpen) {\n\t\ttry {\n\t\t\topenInBrowser(runtime.url, {\n\t\t\t\twarn: (message) => {\n\t\t\t\t\tconsole.warn(message);\n\t\t\t\t},\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tconsole.warn(`Could not open browser automatically: ${message}`);\n\t\t}\n\t}\n\tconsole.log(\"Press Ctrl+C to stop.\");\n\n\tlet isShuttingDown = false;\n\tconst shutdown = async (signal: NodeJS.Signals | null) => {\n\t\tif (isShuttingDown) {\n\t\t\tprocess.exit(130);\n\t\t\treturn;\n\t\t}\n\t\tisShuttingDown = true;\n\t\trunPendingAutoUpdateOnShutdown();\n\t\ttry {\n\t\t\tif (options.skipShutdownCleanup) {\n\t\t\t\tconsole.warn(\"Skipping shutdown task cleanup for this instance.\");\n\t\t\t}\n\t\t\tawait runtime.shutdown({\n\t\t\t\tskipSessionCleanup: options.skipShutdownCleanup,\n\t\t\t});\n\t\t\tprocess.exit(signal ? 130 : 0);\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tconsole.error(`Shutdown failed: ${message}`);\n\t\t\tprocess.exit(1);\n\t\t}\n\t};\n\n\tcloseWithGrace(\n\t\t{\n\t\t\tdelay: 10000,\n\t\t\tskip: [\"uncaughtException\", \"unhandledRejection\", \"beforeExit\"],\n\t\t\tonTimeout: (delayMs) => {\n\t\t\t\tconsole.error(`Forced exit after shutdown timeout (${delayMs}ms).`);\n\t\t\t},\n\t\t\tonSecondSignal: (signal) => {\n\t\t\t\tconsole.error(`Forced exit on second signal: ${signal}`);\n\t\t\t},\n\t\t},\n\t\tasync ({ signal }) => {\n\t\t\tawait shutdown(signal ?? null);\n\t\t},\n\t);\n}\n\nfunction createProgram(): Command {\n\tconst program = new Command();\n\tprogram\n\t\t.name(\"kanban\")\n\t\t.description(\"Local orchestration board for coding agents.\")\n\t\t.version(KANBAN_VERSION, \"-v, --version\", \"Output the version number\")\n\t\t.option(\"--agent <id>\", `Default agent ID (${CLI_AGENT_IDS.join(\", \")}).`, parseCliAgentId)\n\t\t.option(\"--port <number|auto>\", \"Runtime port (1-65535) or auto.\", parseCliPortValue)\n\t\t.option(\"--no-open\", \"Do not open browser automatically.\")\n\t\t.option(\"--skip-shutdown-cleanup\", \"Do not move sessions to trash or delete task worktrees on shutdown.\")\n\t\t.showHelpAfterError()\n\t\t.addHelpText(\"after\", `\\nRuntime URL: ${getKanbanRuntimeOrigin()}\\nAgent IDs: ${CLI_AGENT_IDS.join(\", \")}`);\n\n\tregisterTaskCommand(program);\n\tregisterHooksCommand(program);\n\n\tprogram\n\t\t.command(\"mcp\")\n\t\t.description(\"Deprecated compatibility command.\")\n\t\t.action(() => {\n\t\t\tconsole.warn(\"Deprecated. Please uninstall Kanban MCP.\");\n\t\t});\n\n\tprogram.action(async (options: RootCommandOptions) => {\n\t\tawait runMainCommand({\n\t\t\tagent: options.agent ?? null,\n\t\t\tport: options.port ?? null,\n\t\t\tnoOpen: options.open === false,\n\t\t\tskipShutdownCleanup: options.skipShutdownCleanup === true,\n\t\t});\n\t});\n\n\treturn program;\n}\n\nasync function run(): Promise<void> {\n\tconst argv = process.argv.slice(2);\n\tconst program = createProgram();\n\tawait program.parseAsync(argv, { from: \"user\" });\n}\n\nrun().catch((error) => {\n\tconst message = error instanceof Error ? error.message : String(error);\n\tconsole.error(`Failed to start Kanban: ${message}`);\n\tprocess.exit(1);\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"shutdown-coordinator.d.ts","sourceRoot":"","sources":["../../src/server/shutdown-coordinator.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAGjE,MAAM,WAAW,sCAAsC;IACtD,iBAAiB,EAAE,IAAI,CAAC,iBAAiB,EAAE,uBAAuB,CAAC,CAAC;IACpE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,kBAAkB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC7B;AA6HD,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,sCAAsC,GAAG,OAAO,CAAC,IAAI,CAAC,CAqCvG"}
1
+ {"version":3,"file":"shutdown-coordinator.d.ts","sourceRoot":"","sources":["../../src/server/shutdown-coordinator.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAGjE,MAAM,WAAW,sCAAsC;IACtD,iBAAiB,EAAE,IAAI,CAAC,iBAAiB,EAAE,uBAAuB,CAAC,CAAC;IACpE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,kBAAkB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAqID,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,sCAAsC,GAAG,OAAO,CAAC,IAAI,CAAC,CAuEvG"}
@@ -1,5 +1,5 @@
1
1
  import { updateTaskDependencies } from "../core/task-board-mutations.js";
2
- import { loadWorkspaceState, saveWorkspaceState } from "../state/workspace-state.js";
2
+ import { listWorkspaceIndexEntries, loadWorkspaceState, saveWorkspaceState } from "../state/workspace-state.js";
3
3
  import { deleteTaskWorktree } from "../workspace/task-worktree.js";
4
4
  import { collectProjectWorktreeTaskIdsForRemoval } from "./workspace-registry.js";
5
5
  function moveTaskToTrash(board, taskId) {
@@ -36,11 +36,11 @@ function moveTaskToTrash(board, taskId) {
36
36
  columns,
37
37
  });
38
38
  }
39
- async function persistInterruptedSessions(workspacePath, interruptedTaskIds, terminalManager) {
39
+ async function persistInterruptedSessions(workspacePath, interruptedTaskIds, options) {
40
40
  if (interruptedTaskIds.length === 0) {
41
41
  return [];
42
42
  }
43
- const workspaceState = await loadWorkspaceState(workspacePath);
43
+ const workspaceState = options?.workspaceState ?? (await loadWorkspaceState(workspacePath));
44
44
  const worktreeTaskIds = collectProjectWorktreeTaskIdsForRemoval(workspaceState.board);
45
45
  const worktreeTaskIdsToCleanup = interruptedTaskIds.filter((taskId) => worktreeTaskIds.has(taskId));
46
46
  let nextBoard = workspaceState.board;
@@ -51,12 +51,13 @@ async function persistInterruptedSessions(workspacePath, interruptedTaskIds, ter
51
51
  ...workspaceState.sessions,
52
52
  };
53
53
  for (const taskId of interruptedTaskIds) {
54
- const summary = terminalManager.getSummary(taskId);
54
+ const summary = options?.resolveSummary?.(taskId) ?? workspaceState.sessions[taskId] ?? null;
55
55
  if (summary) {
56
56
  nextSessions[taskId] = {
57
57
  ...summary,
58
58
  state: "interrupted",
59
59
  reviewReason: "interrupted",
60
+ pid: null,
60
61
  updatedAt: Date.now(),
61
62
  };
62
63
  }
@@ -102,26 +103,67 @@ function collectShutdownInterruptedTaskIds(interruptedSummaries, terminalManager
102
103
  }
103
104
  return Array.from(taskIds);
104
105
  }
106
+ function collectWorkColumnTaskIds(workspaceState) {
107
+ return Array.from(collectProjectWorktreeTaskIdsForRemoval(workspaceState.board));
108
+ }
105
109
  export async function shutdownRuntimeServer(deps) {
106
110
  if (deps.skipSessionCleanup) {
107
111
  await deps.closeRuntimeServer();
108
112
  return;
109
113
  }
110
114
  const interruptedByWorkspace = [];
115
+ const managedWorkspacePaths = new Set();
111
116
  for (const { workspacePath, terminalManager } of deps.workspaceRegistry.listManagedWorkspaces()) {
112
117
  const interrupted = terminalManager.markInterruptedAndStopAll();
113
- const interruptedTaskIds = collectShutdownInterruptedTaskIds(interrupted, terminalManager);
118
+ const interruptedTaskIds = new Set(collectShutdownInterruptedTaskIds(interrupted, terminalManager));
114
119
  if (!workspacePath) {
115
120
  continue;
116
121
  }
117
- interruptedByWorkspace.push({
118
- workspacePath,
119
- terminalManager,
120
- interruptedTaskIds,
121
- });
122
+ managedWorkspacePaths.add(workspacePath);
123
+ try {
124
+ const workspaceState = await loadWorkspaceState(workspacePath);
125
+ for (const taskId of collectWorkColumnTaskIds(workspaceState)) {
126
+ interruptedTaskIds.add(taskId);
127
+ }
128
+ interruptedByWorkspace.push({
129
+ workspacePath,
130
+ interruptedTaskIds: Array.from(interruptedTaskIds),
131
+ workspaceState,
132
+ resolveSummary: (taskId) => terminalManager.getSummary(taskId),
133
+ });
134
+ }
135
+ catch (error) {
136
+ const message = error instanceof Error ? error.message : String(error);
137
+ deps.warn(`Could not load workspace state for ${workspacePath} during shutdown cleanup. ${message}`);
138
+ }
139
+ }
140
+ const indexedWorkspaces = await listWorkspaceIndexEntries();
141
+ for (const workspace of indexedWorkspaces) {
142
+ if (managedWorkspacePaths.has(workspace.repoPath)) {
143
+ continue;
144
+ }
145
+ try {
146
+ const workspaceState = await loadWorkspaceState(workspace.repoPath);
147
+ const interruptedTaskIds = collectWorkColumnTaskIds(workspaceState);
148
+ if (interruptedTaskIds.length === 0) {
149
+ continue;
150
+ }
151
+ interruptedByWorkspace.push({
152
+ workspacePath: workspace.repoPath,
153
+ interruptedTaskIds,
154
+ workspaceState,
155
+ });
156
+ }
157
+ catch (error) {
158
+ const message = error instanceof Error ? error.message : String(error);
159
+ deps.warn(`Could not load workspace state for ${workspace.repoPath} during shutdown cleanup. ${message}`);
160
+ }
122
161
  }
123
162
  await Promise.all(interruptedByWorkspace.map(async (workspace) => {
124
- const worktreeTaskIds = await persistInterruptedSessions(workspace.workspacePath, workspace.interruptedTaskIds, workspace.terminalManager);
163
+ const worktreeTaskIds = await persistInterruptedSessions(workspace.workspacePath, workspace.interruptedTaskIds, {
164
+ workspaceState: workspace.workspaceState,
165
+ resolveSummary: workspace.resolveSummary,
166
+ });
125
167
  await cleanupInterruptedTaskWorktrees(workspace.workspacePath, worktreeTaskIds, deps.warn);
126
168
  }));
127
169
  await deps.closeRuntimeServer();
@@ -1 +1 @@
1
- {"version":3,"file":"shutdown-coordinator.js","sourceRoot":"","sources":["../../src/server/shutdown-coordinator.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RuntimeTaskSessionSummary, RuntimeWorkspaceStateResponse } from \"../core/api-contract.js\";\nimport { updateTaskDependencies } from \"../core/task-board-mutations.js\";\nimport { loadWorkspaceState, saveWorkspaceState } from \"../state/workspace-state.js\";\nimport type { TerminalSessionManager } from \"../terminal/session-manager.js\";\nimport { deleteTaskWorktree } from \"../workspace/task-worktree.js\";\nimport type { WorkspaceRegistry } from \"./workspace-registry.js\";\nimport { collectProjectWorktreeTaskIdsForRemoval } from \"./workspace-registry.js\";\n\nexport interface RuntimeShutdownCoordinatorDependencies {\n\tworkspaceRegistry: Pick<WorkspaceRegistry, \"listManagedWorkspaces\">;\n\twarn: (message: string) => void;\n\tcloseRuntimeServer: () => Promise<void>;\n\tskipSessionCleanup?: boolean;\n}\n\nfunction moveTaskToTrash(\n\tboard: RuntimeWorkspaceStateResponse[\"board\"],\n\ttaskId: string,\n): RuntimeWorkspaceStateResponse[\"board\"] {\n\tconst columns = board.columns.map((column) => ({\n\t\t...column,\n\t\tcards: [...column.cards],\n\t}));\n\tlet removedCard: RuntimeWorkspaceStateResponse[\"board\"][\"columns\"][number][\"cards\"][number] | undefined;\n\n\tfor (const column of columns) {\n\t\tconst cardIndex = column.cards.findIndex((candidate) => candidate.id === taskId);\n\t\tif (cardIndex === -1) {\n\t\t\tcontinue;\n\t\t}\n\t\tremovedCard = column.cards[cardIndex];\n\t\tcolumn.cards.splice(cardIndex, 1);\n\t\tbreak;\n\t}\n\n\tif (!removedCard) {\n\t\treturn board;\n\t}\n\tconst trashColumnIndex = columns.findIndex((column) => column.id === \"trash\");\n\tif (trashColumnIndex === -1) {\n\t\treturn board;\n\t}\n\tconst trashColumn = columns[trashColumnIndex];\n\tif (!trashColumn.cards.some((candidate) => candidate.id === taskId)) {\n\t\ttrashColumn.cards.unshift({\n\t\t\t...removedCard,\n\t\t\tupdatedAt: Date.now(),\n\t\t});\n\t}\n\treturn updateTaskDependencies({\n\t\t...board,\n\t\tcolumns,\n\t});\n}\n\nasync function persistInterruptedSessions(\n\tworkspacePath: string,\n\tinterruptedTaskIds: string[],\n\tterminalManager: TerminalSessionManager,\n): Promise<string[]> {\n\tif (interruptedTaskIds.length === 0) {\n\t\treturn [];\n\t}\n\tconst workspaceState = await loadWorkspaceState(workspacePath);\n\tconst worktreeTaskIds = collectProjectWorktreeTaskIdsForRemoval(workspaceState.board);\n\tconst worktreeTaskIdsToCleanup = interruptedTaskIds.filter((taskId) => worktreeTaskIds.has(taskId));\n\tlet nextBoard = workspaceState.board;\n\tfor (const taskId of interruptedTaskIds) {\n\t\tnextBoard = moveTaskToTrash(nextBoard, taskId);\n\t}\n\tconst nextSessions = {\n\t\t...workspaceState.sessions,\n\t};\n\tfor (const taskId of interruptedTaskIds) {\n\t\tconst summary = terminalManager.getSummary(taskId);\n\t\tif (summary) {\n\t\t\tnextSessions[taskId] = {\n\t\t\t\t...summary,\n\t\t\t\tstate: \"interrupted\",\n\t\t\t\treviewReason: \"interrupted\",\n\t\t\t\tupdatedAt: Date.now(),\n\t\t\t};\n\t\t}\n\t}\n\tawait saveWorkspaceState(workspacePath, {\n\t\tboard: nextBoard,\n\t\tsessions: nextSessions,\n\t});\n\treturn worktreeTaskIdsToCleanup;\n}\n\nasync function cleanupInterruptedTaskWorktrees(\n\trepoPath: string,\n\ttaskIds: string[],\n\twarn: (message: string) => void,\n): Promise<void> {\n\tif (taskIds.length === 0) {\n\t\treturn;\n\t}\n\tconst deletions = await Promise.all(\n\t\ttaskIds.map(async (taskId) => ({\n\t\t\ttaskId,\n\t\t\tdeleted: await deleteTaskWorktree({\n\t\t\t\trepoPath,\n\t\t\t\ttaskId,\n\t\t\t}),\n\t\t})),\n\t);\n\tfor (const { taskId, deleted } of deletions) {\n\t\tif (deleted.ok) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst message = deleted.error ?? `Could not delete task workspace for task \"${taskId}\" during shutdown.`;\n\t\twarn(message);\n\t}\n}\n\nfunction shouldInterruptSessionOnShutdown(summary: RuntimeTaskSessionSummary): boolean {\n\tif (summary.state === \"running\") {\n\t\treturn true;\n\t}\n\treturn summary.state === \"awaiting_review\";\n}\n\nfunction collectShutdownInterruptedTaskIds(\n\tinterruptedSummaries: RuntimeTaskSessionSummary[],\n\tterminalManager: TerminalSessionManager,\n): string[] {\n\tconst taskIds = new Set(interruptedSummaries.map((summary) => summary.taskId));\n\tfor (const summary of terminalManager.listSummaries()) {\n\t\tif (!shouldInterruptSessionOnShutdown(summary)) {\n\t\t\tcontinue;\n\t\t}\n\t\ttaskIds.add(summary.taskId);\n\t}\n\treturn Array.from(taskIds);\n}\n\nexport async function shutdownRuntimeServer(deps: RuntimeShutdownCoordinatorDependencies): Promise<void> {\n\tif (deps.skipSessionCleanup) {\n\t\tawait deps.closeRuntimeServer();\n\t\treturn;\n\t}\n\n\tconst interruptedByWorkspace: Array<{\n\t\tworkspacePath: string;\n\t\tterminalManager: TerminalSessionManager;\n\t\tinterruptedTaskIds: string[];\n\t}> = [];\n\n\tfor (const { workspacePath, terminalManager } of deps.workspaceRegistry.listManagedWorkspaces()) {\n\t\tconst interrupted = terminalManager.markInterruptedAndStopAll();\n\t\tconst interruptedTaskIds = collectShutdownInterruptedTaskIds(interrupted, terminalManager);\n\t\tif (!workspacePath) {\n\t\t\tcontinue;\n\t\t}\n\t\tinterruptedByWorkspace.push({\n\t\t\tworkspacePath,\n\t\t\tterminalManager,\n\t\t\tinterruptedTaskIds,\n\t\t});\n\t}\n\n\tawait Promise.all(\n\t\tinterruptedByWorkspace.map(async (workspace) => {\n\t\t\tconst worktreeTaskIds = await persistInterruptedSessions(\n\t\t\t\tworkspace.workspacePath,\n\t\t\t\tworkspace.interruptedTaskIds,\n\t\t\t\tworkspace.terminalManager,\n\t\t\t);\n\t\t\tawait cleanupInterruptedTaskWorktrees(workspace.workspacePath, worktreeTaskIds, deps.warn);\n\t\t}),\n\t);\n\n\tawait deps.closeRuntimeServer();\n}\n"]}
1
+ {"version":3,"file":"shutdown-coordinator.js","sourceRoot":"","sources":["../../src/server/shutdown-coordinator.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RuntimeTaskSessionSummary, RuntimeWorkspaceStateResponse } from \"../core/api-contract.js\";\nimport { updateTaskDependencies } from \"../core/task-board-mutations.js\";\nimport { listWorkspaceIndexEntries, loadWorkspaceState, saveWorkspaceState } from \"../state/workspace-state.js\";\nimport type { TerminalSessionManager } from \"../terminal/session-manager.js\";\nimport { deleteTaskWorktree } from \"../workspace/task-worktree.js\";\nimport type { WorkspaceRegistry } from \"./workspace-registry.js\";\nimport { collectProjectWorktreeTaskIdsForRemoval } from \"./workspace-registry.js\";\n\nexport interface RuntimeShutdownCoordinatorDependencies {\n\tworkspaceRegistry: Pick<WorkspaceRegistry, \"listManagedWorkspaces\">;\n\twarn: (message: string) => void;\n\tcloseRuntimeServer: () => Promise<void>;\n\tskipSessionCleanup?: boolean;\n}\n\nfunction moveTaskToTrash(\n\tboard: RuntimeWorkspaceStateResponse[\"board\"],\n\ttaskId: string,\n): RuntimeWorkspaceStateResponse[\"board\"] {\n\tconst columns = board.columns.map((column) => ({\n\t\t...column,\n\t\tcards: [...column.cards],\n\t}));\n\tlet removedCard: RuntimeWorkspaceStateResponse[\"board\"][\"columns\"][number][\"cards\"][number] | undefined;\n\n\tfor (const column of columns) {\n\t\tconst cardIndex = column.cards.findIndex((candidate) => candidate.id === taskId);\n\t\tif (cardIndex === -1) {\n\t\t\tcontinue;\n\t\t}\n\t\tremovedCard = column.cards[cardIndex];\n\t\tcolumn.cards.splice(cardIndex, 1);\n\t\tbreak;\n\t}\n\n\tif (!removedCard) {\n\t\treturn board;\n\t}\n\tconst trashColumnIndex = columns.findIndex((column) => column.id === \"trash\");\n\tif (trashColumnIndex === -1) {\n\t\treturn board;\n\t}\n\tconst trashColumn = columns[trashColumnIndex];\n\tif (!trashColumn.cards.some((candidate) => candidate.id === taskId)) {\n\t\ttrashColumn.cards.unshift({\n\t\t\t...removedCard,\n\t\t\tupdatedAt: Date.now(),\n\t\t});\n\t}\n\treturn updateTaskDependencies({\n\t\t...board,\n\t\tcolumns,\n\t});\n}\n\nasync function persistInterruptedSessions(\n\tworkspacePath: string,\n\tinterruptedTaskIds: string[],\n\toptions?: {\n\t\tworkspaceState?: RuntimeWorkspaceStateResponse;\n\t\tresolveSummary?: (taskId: string) => RuntimeTaskSessionSummary | null;\n\t},\n): Promise<string[]> {\n\tif (interruptedTaskIds.length === 0) {\n\t\treturn [];\n\t}\n\tconst workspaceState = options?.workspaceState ?? (await loadWorkspaceState(workspacePath));\n\tconst worktreeTaskIds = collectProjectWorktreeTaskIdsForRemoval(workspaceState.board);\n\tconst worktreeTaskIdsToCleanup = interruptedTaskIds.filter((taskId) => worktreeTaskIds.has(taskId));\n\tlet nextBoard = workspaceState.board;\n\tfor (const taskId of interruptedTaskIds) {\n\t\tnextBoard = moveTaskToTrash(nextBoard, taskId);\n\t}\n\tconst nextSessions = {\n\t\t...workspaceState.sessions,\n\t};\n\tfor (const taskId of interruptedTaskIds) {\n\t\tconst summary = options?.resolveSummary?.(taskId) ?? workspaceState.sessions[taskId] ?? null;\n\t\tif (summary) {\n\t\t\tnextSessions[taskId] = {\n\t\t\t\t...summary,\n\t\t\t\tstate: \"interrupted\",\n\t\t\t\treviewReason: \"interrupted\",\n\t\t\t\tpid: null,\n\t\t\t\tupdatedAt: Date.now(),\n\t\t\t};\n\t\t}\n\t}\n\tawait saveWorkspaceState(workspacePath, {\n\t\tboard: nextBoard,\n\t\tsessions: nextSessions,\n\t});\n\treturn worktreeTaskIdsToCleanup;\n}\n\nasync function cleanupInterruptedTaskWorktrees(\n\trepoPath: string,\n\ttaskIds: string[],\n\twarn: (message: string) => void,\n): Promise<void> {\n\tif (taskIds.length === 0) {\n\t\treturn;\n\t}\n\tconst deletions = await Promise.all(\n\t\ttaskIds.map(async (taskId) => ({\n\t\t\ttaskId,\n\t\t\tdeleted: await deleteTaskWorktree({\n\t\t\t\trepoPath,\n\t\t\t\ttaskId,\n\t\t\t}),\n\t\t})),\n\t);\n\tfor (const { taskId, deleted } of deletions) {\n\t\tif (deleted.ok) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst message = deleted.error ?? `Could not delete task workspace for task \"${taskId}\" during shutdown.`;\n\t\twarn(message);\n\t}\n}\n\nfunction shouldInterruptSessionOnShutdown(summary: RuntimeTaskSessionSummary): boolean {\n\tif (summary.state === \"running\") {\n\t\treturn true;\n\t}\n\treturn summary.state === \"awaiting_review\";\n}\n\nfunction collectShutdownInterruptedTaskIds(\n\tinterruptedSummaries: RuntimeTaskSessionSummary[],\n\tterminalManager: TerminalSessionManager,\n): string[] {\n\tconst taskIds = new Set(interruptedSummaries.map((summary) => summary.taskId));\n\tfor (const summary of terminalManager.listSummaries()) {\n\t\tif (!shouldInterruptSessionOnShutdown(summary)) {\n\t\t\tcontinue;\n\t\t}\n\t\ttaskIds.add(summary.taskId);\n\t}\n\treturn Array.from(taskIds);\n}\n\nfunction collectWorkColumnTaskIds(workspaceState: RuntimeWorkspaceStateResponse): string[] {\n\treturn Array.from(collectProjectWorktreeTaskIdsForRemoval(workspaceState.board));\n}\n\nexport async function shutdownRuntimeServer(deps: RuntimeShutdownCoordinatorDependencies): Promise<void> {\n\tif (deps.skipSessionCleanup) {\n\t\tawait deps.closeRuntimeServer();\n\t\treturn;\n\t}\n\n\tconst interruptedByWorkspace: Array<{\n\t\tworkspacePath: string;\n\t\tinterruptedTaskIds: string[];\n\t\tworkspaceState?: RuntimeWorkspaceStateResponse;\n\t\tresolveSummary?: (taskId: string) => RuntimeTaskSessionSummary | null;\n\t}> = [];\n\tconst managedWorkspacePaths = new Set<string>();\n\n\tfor (const { workspacePath, terminalManager } of deps.workspaceRegistry.listManagedWorkspaces()) {\n\t\tconst interrupted = terminalManager.markInterruptedAndStopAll();\n\t\tconst interruptedTaskIds = new Set(collectShutdownInterruptedTaskIds(interrupted, terminalManager));\n\t\tif (!workspacePath) {\n\t\t\tcontinue;\n\t\t}\n\t\tmanagedWorkspacePaths.add(workspacePath);\n\t\ttry {\n\t\t\tconst workspaceState = await loadWorkspaceState(workspacePath);\n\t\t\tfor (const taskId of collectWorkColumnTaskIds(workspaceState)) {\n\t\t\t\tinterruptedTaskIds.add(taskId);\n\t\t\t}\n\t\t\tinterruptedByWorkspace.push({\n\t\t\t\tworkspacePath,\n\t\t\t\tinterruptedTaskIds: Array.from(interruptedTaskIds),\n\t\t\t\tworkspaceState,\n\t\t\t\tresolveSummary: (taskId) => terminalManager.getSummary(taskId),\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tdeps.warn(`Could not load workspace state for ${workspacePath} during shutdown cleanup. ${message}`);\n\t\t}\n\t}\n\n\tconst indexedWorkspaces = await listWorkspaceIndexEntries();\n\tfor (const workspace of indexedWorkspaces) {\n\t\tif (managedWorkspacePaths.has(workspace.repoPath)) {\n\t\t\tcontinue;\n\t\t}\n\t\ttry {\n\t\t\tconst workspaceState = await loadWorkspaceState(workspace.repoPath);\n\t\t\tconst interruptedTaskIds = collectWorkColumnTaskIds(workspaceState);\n\t\t\tif (interruptedTaskIds.length === 0) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tinterruptedByWorkspace.push({\n\t\t\t\tworkspacePath: workspace.repoPath,\n\t\t\t\tinterruptedTaskIds,\n\t\t\t\tworkspaceState,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tdeps.warn(`Could not load workspace state for ${workspace.repoPath} during shutdown cleanup. ${message}`);\n\t\t}\n\t}\n\n\tawait Promise.all(\n\t\tinterruptedByWorkspace.map(async (workspace) => {\n\t\t\tconst worktreeTaskIds = await persistInterruptedSessions(workspace.workspacePath, workspace.interruptedTaskIds, {\n\t\t\t\tworkspaceState: workspace.workspaceState,\n\t\t\t\tresolveSummary: workspace.resolveSummary,\n\t\t\t});\n\t\t\tawait cleanupInterruptedTaskWorktrees(workspace.workspacePath, worktreeTaskIds, deps.warn);\n\t\t}),\n\t);\n\n\tawait deps.closeRuntimeServer();\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"}