syntaur 0.16.0 → 0.16.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dashboard/dist/assets/{_basePickBy-B1S22H85.js → _basePickBy-DTuHiZCP.js} +1 -1
  2. package/dashboard/dist/assets/{_baseUniq-CJIRCCsh.js → _baseUniq-BjbISCNN.js} +1 -1
  3. package/dashboard/dist/assets/{arc-CdlNYTcd.js → arc-D9mCa8If.js} +1 -1
  4. package/dashboard/dist/assets/{architectureDiagram-2XIMDMQ5-KVI0HWOy.js → architectureDiagram-2XIMDMQ5-CLWheiZu.js} +1 -1
  5. package/dashboard/dist/assets/{blockDiagram-WCTKOSBZ-ClnG7gaq.js → blockDiagram-WCTKOSBZ-BBxrVTWB.js} +1 -1
  6. package/dashboard/dist/assets/{c4Diagram-IC4MRINW-BD9lkttL.js → c4Diagram-IC4MRINW-DnhDZ2W3.js} +1 -1
  7. package/dashboard/dist/assets/channel-CN5VmjNa.js +1 -0
  8. package/dashboard/dist/assets/{chunk-4BX2VUAB-BM3DXZMG.js → chunk-4BX2VUAB-DeAfVeDa.js} +1 -1
  9. package/dashboard/dist/assets/{chunk-55IACEB6-DUIbFJ3r.js → chunk-55IACEB6-cKEeGDNI.js} +1 -1
  10. package/dashboard/dist/assets/{chunk-FMBD7UC4-B_cxCRkA.js → chunk-FMBD7UC4-7RuZ6HEq.js} +1 -1
  11. package/dashboard/dist/assets/{chunk-JSJVCQXG-2mLf1WoM.js → chunk-JSJVCQXG-B5dwG0bv.js} +1 -1
  12. package/dashboard/dist/assets/{chunk-KX2RTZJC-BMz3ND2R.js → chunk-KX2RTZJC-DeyQYDVj.js} +1 -1
  13. package/dashboard/dist/assets/{chunk-NQ4KR5QH-DiCxpw3L.js → chunk-NQ4KR5QH-NYo4hSqA.js} +1 -1
  14. package/dashboard/dist/assets/{chunk-QZHKN3VN-BcaWPzd5.js → chunk-QZHKN3VN-CtJFICF8.js} +1 -1
  15. package/dashboard/dist/assets/{chunk-WL4C6EOR-BbsfhS6J.js → chunk-WL4C6EOR-DZ3WYdab.js} +1 -1
  16. package/dashboard/dist/assets/classDiagram-VBA2DB6C-CqLb9GuU.js +1 -0
  17. package/dashboard/dist/assets/classDiagram-v2-RAHNMMFH-CqLb9GuU.js +1 -0
  18. package/dashboard/dist/assets/clone-DwvrjCQs.js +1 -0
  19. package/dashboard/dist/assets/{cose-bilkent-S5V4N54A-iuQzyyrA.js → cose-bilkent-S5V4N54A-DaYOsf-M.js} +1 -1
  20. package/dashboard/dist/assets/{dagre-KLK3FWXG-C0TB1zg5.js → dagre-KLK3FWXG-DzLc7ykF.js} +1 -1
  21. package/dashboard/dist/assets/{diagram-E7M64L7V-Ck8tvxP2.js → diagram-E7M64L7V-kpjEdOqb.js} +1 -1
  22. package/dashboard/dist/assets/{diagram-IFDJBPK2-rQKIi-sc.js → diagram-IFDJBPK2-D3EHoh6j.js} +1 -1
  23. package/dashboard/dist/assets/{diagram-P4PSJMXO-DS1RGSgx.js → diagram-P4PSJMXO-Cp6Un2ys.js} +1 -1
  24. package/dashboard/dist/assets/{erDiagram-INFDFZHY-BqWCybWW.js → erDiagram-INFDFZHY-DDjOUPWk.js} +1 -1
  25. package/dashboard/dist/assets/{flowDiagram-PKNHOUZH-BCoQtyQ5.js → flowDiagram-PKNHOUZH-CfO51xge.js} +1 -1
  26. package/dashboard/dist/assets/{ganttDiagram-A5KZAMGK-CD1BmicP.js → ganttDiagram-A5KZAMGK-BDzAtkcp.js} +1 -1
  27. package/dashboard/dist/assets/{gitGraphDiagram-K3NZZRJ6-tGDYOZuO.js → gitGraphDiagram-K3NZZRJ6-JPMFN2zF.js} +1 -1
  28. package/dashboard/dist/assets/{graph-BT0s-094.js → graph-DXDryilu.js} +1 -1
  29. package/dashboard/dist/assets/index-D7UtkCYM.js +515 -0
  30. package/dashboard/dist/assets/{index-D2Yoi6DJ.css → index-DTXSWSzH.css} +1 -1
  31. package/dashboard/dist/assets/{infoDiagram-LFFYTUFH-E4dVb8BD.js → infoDiagram-LFFYTUFH-CYi5kkvz.js} +1 -1
  32. package/dashboard/dist/assets/{ishikawaDiagram-PHBUUO56-CubuM_ev.js → ishikawaDiagram-PHBUUO56-DQl_IUe8.js} +1 -1
  33. package/dashboard/dist/assets/{journeyDiagram-4ABVD52K-DfyJbgMF.js → journeyDiagram-4ABVD52K-BXXGPcrS.js} +1 -1
  34. package/dashboard/dist/assets/{kanban-definition-K7BYSVSG-BXamajyZ.js → kanban-definition-K7BYSVSG-BqJestUY.js} +1 -1
  35. package/dashboard/dist/assets/{layout-6b_SlWD_.js → layout-D5VdYmWn.js} +1 -1
  36. package/dashboard/dist/assets/{linear-BE0O-66A.js → linear-dZA_O_GN.js} +1 -1
  37. package/dashboard/dist/assets/{mermaid.core-DM3qWr07.js → mermaid.core-B0Ixd1yP.js} +4 -4
  38. package/dashboard/dist/assets/{mindmap-definition-YRQLILUH-puOtERrG.js → mindmap-definition-YRQLILUH-CSJYdSMG.js} +1 -1
  39. package/dashboard/dist/assets/{pieDiagram-SKSYHLDU-cE6l8UBX.js → pieDiagram-SKSYHLDU-DmYrRZHN.js} +1 -1
  40. package/dashboard/dist/assets/{quadrantDiagram-337W2JSQ-CgDAyZQP.js → quadrantDiagram-337W2JSQ-La3ce5kE.js} +1 -1
  41. package/dashboard/dist/assets/{requirementDiagram-Z7DCOOCP-CJrai_8U.js → requirementDiagram-Z7DCOOCP-DPitIZQl.js} +1 -1
  42. package/dashboard/dist/assets/{sankeyDiagram-WA2Y5GQK-Bf72l7UW.js → sankeyDiagram-WA2Y5GQK-CAmCqGkr.js} +1 -1
  43. package/dashboard/dist/assets/{sequenceDiagram-2WXFIKYE-0D8RN7ds.js → sequenceDiagram-2WXFIKYE-6lEzNTWG.js} +1 -1
  44. package/dashboard/dist/assets/{stateDiagram-RAJIS63D-B8LucUIt.js → stateDiagram-RAJIS63D-DyGKCS2C.js} +1 -1
  45. package/dashboard/dist/assets/stateDiagram-v2-FVOUBMTO-BOmRICoY.js +1 -0
  46. package/dashboard/dist/assets/{timeline-definition-YZTLITO2-DL3Hq8ii.js → timeline-definition-YZTLITO2-D9RxQE3j.js} +1 -1
  47. package/dashboard/dist/assets/{treemap-KZPCXAKY-wF1X4_uI.js → treemap-KZPCXAKY-TuXbGNN4.js} +1 -1
  48. package/dashboard/dist/assets/{vennDiagram-LZ73GAT5-DDAjoGTZ.js → vennDiagram-LZ73GAT5-Bly5knr-.js} +1 -1
  49. package/dashboard/dist/assets/{xychartDiagram-JWTSCODW-T-YmzRW8.js → xychartDiagram-JWTSCODW-CA-5z7-4.js} +1 -1
  50. package/dashboard/dist/index.html +2 -2
  51. package/dist/dashboard/server.js +820 -166
  52. package/dist/dashboard/server.js.map +1 -1
  53. package/dist/index.js +1244 -774
  54. package/dist/index.js.map +1 -1
  55. package/dist/launch/index.d.ts +20 -2
  56. package/dist/launch/index.js +67 -20
  57. package/dist/launch/index.js.map +1 -1
  58. package/package.json +1 -1
  59. package/scripts/install-macos-url-handler.mjs +40 -7
  60. package/dashboard/dist/assets/channel-Cm_FzKJq.js +0 -1
  61. package/dashboard/dist/assets/classDiagram-VBA2DB6C-Bdan2Dp5.js +0 -1
  62. package/dashboard/dist/assets/classDiagram-v2-RAHNMMFH-Bdan2Dp5.js +0 -1
  63. package/dashboard/dist/assets/clone-9PoPEM_s.js +0 -1
  64. package/dashboard/dist/assets/index-BdSkANCC.js +0 -510
  65. package/dashboard/dist/assets/stateDiagram-v2-FVOUBMTO-D0dc7wxQ.js +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/paths.ts","../../src/lifecycle/types.ts","../../src/lifecycle/state-machine.ts","../../src/lifecycle/frontmatter.ts","../../src/utils/fs.ts","../../src/utils/timestamp.ts","../../src/dashboard/parser.ts","../../src/todos/parser.ts","../../src/lifecycle/linked-todos.ts","../../src/lifecycle/transitions.ts","../../src/lifecycle/index.ts","../../src/templates/config.ts","../../src/utils/fs-migration.ts","../../src/utils/hotkeysCatalog.ts","../../src/utils/agents-schema.ts","../../src/utils/config.ts","../../src/utils/slug.ts","../../src/utils/playbooks.ts","../../src/utils/assignment-resolver.ts","../../src/dashboard/help.ts","../../src/dashboard/session-db.ts","../../src/dashboard/agent-sessions.ts","../../src/dashboard/overviewCopy.ts","../../src/dashboard/servers.ts","../../src/dashboard/scanner.ts","../../src/dashboard/api.ts","../../src/utils/assignment-todos.ts","../../src/dashboard/server.ts","../../src/dashboard/session-liveness.ts","../../src/dashboard/watcher.ts","../../src/utils/view-prefs-schema.ts","../../src/utils/view-prefs.ts","../../src/dashboard/todos-locks.ts","../../src/dashboard/api-write.ts","../../src/utils/uuid.ts","../../src/dashboard/acceptance-criteria.ts","../../src/templates/index.ts","../../src/templates/manifest.ts","../../src/utils/yaml.ts","../../src/templates/project.ts","../../src/templates/assignment.ts","../../src/templates/scratchpad.ts","../../src/templates/handoff.ts","../../src/templates/progress.ts","../../src/templates/comments.ts","../../src/templates/decision-record.ts","../../src/templates/index-stubs.ts","../../src/templates/playbook.ts","../../src/dashboard/api-servers.ts","../../src/dashboard/api-agent-sessions.ts","../../src/utils/transcript.ts","../../src/utils/process-info.ts","../../src/dashboard/api-agents.ts","../../src/dashboard/api-leases.ts","../../src/db/leases-db.ts","../../src/dashboard/api-playbooks.ts","../../src/dashboard/api-todos.ts","../../src/utils/promote-todos.ts","../../src/commands/create-assignment.ts","../../src/dashboard/api-project-todos.ts","../../src/dashboard/api-backup.ts","../../src/utils/github-backup.ts","../../src/dashboard/autodiscovery.ts"],"sourcesContent":["import { homedir } from 'node:os';\nimport { resolve } from 'node:path';\n\nexport function expandHome(p: string): string {\n if (p.startsWith('~/') || p === '~') {\n return resolve(homedir(), p.slice(2));\n }\n return p;\n}\n\nexport function syntaurRoot(): string {\n const override = process.env.SYNTAUR_HOME;\n if (override && override.length > 0) {\n return resolve(expandHome(override));\n }\n return resolve(homedir(), '.syntaur');\n}\n\nexport function defaultProjectDir(): string {\n return resolve(syntaurRoot(), 'projects');\n}\n\nexport function assignmentsDir(): string {\n return resolve(syntaurRoot(), 'assignments');\n}\n\nexport function serversDir(): string {\n return resolve(syntaurRoot(), 'servers');\n}\n\nexport function playbooksDir(): string {\n return resolve(syntaurRoot(), 'playbooks');\n}\n\nexport function todosDir(): string {\n return resolve(syntaurRoot(), 'todos');\n}\n\nexport function viewPrefsFile(): string {\n return resolve(syntaurRoot(), 'view-prefs.json');\n}\n\nexport function projectTodosDir(projectsDir: string, projectSlug: string): string {\n return resolve(projectsDir, projectSlug, 'todos');\n}\n\nexport function todoPlanDir(todosDir: string, workspaceOrProject: string, todoId: string): string {\n return resolve(todosDir, 'plans', workspaceOrProject, todoId);\n}\n\nexport function proofDir(assignmentDir: string): string {\n return resolve(assignmentDir, 'proof');\n}\n","export type AssignmentStatus = string;\n\nexport type TransitionCommand = string;\n\nexport const DEFAULT_STATUSES = [\n 'draft',\n 'pending',\n 'ready_for_planning',\n 'ready_to_implement',\n 'in_progress',\n 'blocked',\n 'review',\n 'completed',\n 'failed',\n] as const;\n\nexport const DEFAULT_COMMANDS = [\n 'start',\n 'shape',\n 'plan-ready',\n 'implement',\n 'complete',\n 'block',\n 'unblock',\n 'review',\n 'fail',\n 'reopen',\n 'assign',\n] as const;\n\nexport const DEFAULT_TERMINAL_STATUSES: ReadonlySet<string> = new Set([\n 'completed',\n 'failed',\n]);\n\nexport const TERMINAL_STATUSES: ReadonlySet<string> = DEFAULT_TERMINAL_STATUSES;\n\nexport interface ExternalId {\n system: string;\n id: string;\n url: string | null;\n}\n\nexport interface Workspace {\n repository: string | null;\n worktreePath: string | null;\n branch: string | null;\n parentBranch: string | null;\n}\n\nexport interface AssignmentFrontmatter {\n id: string;\n slug: string;\n title: string;\n project: string | null;\n type: string | null;\n status: AssignmentStatus;\n priority: 'low' | 'medium' | 'high' | 'critical';\n created: string;\n updated: string;\n assignee: string | null;\n externalIds: ExternalId[];\n dependsOn: string[];\n links: string[];\n blockedReason: string | null;\n workspace: Workspace;\n tags: string[];\n}\n\nexport interface TransitionResult {\n success: boolean;\n message: string;\n fromStatus: AssignmentStatus;\n toStatus?: AssignmentStatus;\n warnings?: string[];\n}\n","import type { AssignmentStatus, TransitionCommand } from './types.js';\nimport { TERMINAL_STATUSES } from './types.js';\n\n/**\n * Maps a command to its target status. Commands always produce the same\n * target regardless of the current status — workflow enforcement is\n * handled via agent prompting, not code guards.\n */\nexport const DEFAULT_COMMAND_TARGETS = new Map<string, string>([\n ['start', 'in_progress'],\n ['shape', 'ready_for_planning'],\n ['plan-ready', 'ready_to_implement'],\n ['implement', 'in_progress'],\n ['block', 'blocked'],\n ['unblock', 'in_progress'],\n ['review', 'review'],\n ['complete', 'completed'],\n ['fail', 'failed'],\n ['reopen', 'in_progress'],\n]);\n\n/** @deprecated Transition guards removed — kept for API compat, always returns true */\nexport const DEFAULT_TRANSITION_TABLE = new Map<string, string>([\n ['pending:start', 'in_progress'],\n ['pending:block', 'blocked'],\n ['draft:shape', 'ready_for_planning'],\n ['draft:start', 'in_progress'],\n ['ready_for_planning:plan-ready', 'ready_to_implement'],\n ['ready_for_planning:start', 'in_progress'],\n ['ready_to_implement:implement', 'in_progress'],\n ['in_progress:block', 'blocked'],\n ['in_progress:review', 'review'],\n ['in_progress:complete', 'completed'],\n ['in_progress:fail', 'failed'],\n ['blocked:unblock', 'in_progress'],\n ['review:start', 'in_progress'],\n ['review:complete', 'completed'],\n ['review:fail', 'failed'],\n ['completed:reopen', 'in_progress'],\n ['failed:reopen', 'in_progress'],\n]);\n\nexport function buildTransitionTable(\n transitions: Array<{ from: string; command: string; to: string }>,\n): Map<string, string> {\n const table = new Map<string, string>();\n for (const t of transitions) {\n table.set(`${t.from}:${t.command}`, t.to);\n }\n return table;\n}\n\nexport function buildCommandTargets(\n transitions: Array<{ from: string; command: string; to: string }>,\n): Map<string, string> {\n const targets = new Map<string, string>();\n for (const t of transitions) {\n targets.set(t.command, t.to);\n }\n return targets;\n}\n\nexport function getTargetStatus(\n _from: AssignmentStatus,\n command: TransitionCommand,\n table?: Map<string, string>,\n): AssignmentStatus | null {\n // Try command-only lookup first, fall back to from:command for backwards compat\n if (!table || table === DEFAULT_TRANSITION_TABLE) {\n return DEFAULT_COMMAND_TARGETS.get(command) ?? null;\n }\n // Custom table: try command-only key first, then from:command\n return table.get(command) ?? table.get(`${_from}:${command}`) ?? null;\n}\n\n/** @deprecated Guards removed — always returns true for known commands */\nexport function canTransition(\n _from: AssignmentStatus,\n command: TransitionCommand,\n table?: Map<string, string>,\n): boolean {\n return getTargetStatus(_from, command, table) !== null;\n}\n\nexport function isTerminalStatus(\n status: AssignmentStatus,\n terminalSet?: ReadonlySet<string>,\n): boolean {\n return (terminalSet ?? TERMINAL_STATUSES).has(status);\n}\n","import type { AssignmentFrontmatter, ExternalId, Workspace } from './types.js';\n\nfunction extractFrontmatter(fileContent: string): [string, string] {\n const match = fileContent.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) {\n throw new Error('No frontmatter found in file. Expected --- delimiters.');\n }\n const frontmatterBlock = match[1];\n const body = fileContent.slice(match[0].length);\n return [frontmatterBlock, body];\n}\n\nfunction parseSimpleValue(raw: string): string | null {\n const trimmed = raw.trim();\n if (trimmed === 'null' || trimmed === '~' || trimmed === '') return null;\n if (\n (trimmed.startsWith('\"') && trimmed.endsWith('\"')) ||\n (trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\"))\n ) {\n return trimmed.slice(1, -1);\n }\n return trimmed;\n}\n\nfunction parseDependsOn(frontmatter: string): string[] {\n const inlineMatch = frontmatter.match(/^dependsOn:\\s*\\[\\s*\\]/m);\n if (inlineMatch) return [];\n\n const results: string[] = [];\n const blockMatch = frontmatter.match(/^dependsOn:\\s*\\n((?:\\s+-\\s+.*\\n?)*)/m);\n if (blockMatch) {\n const items = blockMatch[1].matchAll(/^\\s+-\\s+(.+)$/gm);\n for (const item of items) {\n results.push(item[1].trim());\n }\n }\n return results;\n}\n\nfunction parseLinks(frontmatter: string): string[] {\n const inlineMatch = frontmatter.match(/^links:\\s*\\[\\s*\\]/m);\n if (inlineMatch) return [];\n\n const results: string[] = [];\n const blockMatch = frontmatter.match(/^links:\\s*\\n((?:\\s+-\\s+.*\\n?)*)/m);\n if (blockMatch) {\n const items = blockMatch[1].matchAll(/^\\s+-\\s+(.+)$/gm);\n for (const item of items) {\n results.push(item[1].trim());\n }\n }\n return results;\n}\n\nfunction parseExternalIds(frontmatter: string): ExternalId[] {\n const inlineMatch = frontmatter.match(/^externalIds:\\s*\\[\\s*\\]/m);\n if (inlineMatch) return [];\n\n const results: ExternalId[] = [];\n const blockMatch = frontmatter.match(\n /^externalIds:\\s*\\n((?:\\s+-\\s+[\\s\\S]*?)(?=^\\w|\\n---))/m,\n );\n if (!blockMatch) return [];\n\n const itemBlocks = blockMatch[1].split(/\\n\\s+-\\s+/).filter(Boolean);\n for (const block of itemBlocks) {\n const lines = block.split('\\n');\n const entry: Record<string, string | null> = {};\n for (const line of lines) {\n const colonIdx = line.indexOf(':');\n if (colonIdx < 0) continue;\n const key = line.slice(0, colonIdx).trim().replace(/^-\\s+/, '');\n if (!key) continue;\n entry[key] = parseSimpleValue(line.slice(colonIdx + 1));\n }\n if (entry['system'] && entry['id']) {\n results.push({\n system: entry['system'],\n id: entry['id'],\n url: entry['url'] || null,\n });\n }\n }\n return results;\n}\n\nfunction parseWorkspace(frontmatter: string): Workspace {\n const defaults: Workspace = {\n repository: null,\n worktreePath: null,\n branch: null,\n parentBranch: null,\n };\n\n const fields = ['repository', 'worktreePath', 'branch', 'parentBranch'] as const;\n for (const field of fields) {\n const match = frontmatter.match(new RegExp(`^\\\\s+${field}:\\\\s*(.*)$`, 'm'));\n if (match) {\n defaults[field] = parseSimpleValue(match[1]);\n }\n }\n return defaults;\n}\n\nfunction parseTags(frontmatter: string): string[] {\n const inlineMatch = frontmatter.match(/^tags:\\s*\\[\\s*\\]/m);\n if (inlineMatch) return [];\n\n const results: string[] = [];\n const blockMatch = frontmatter.match(/^tags:\\s*\\n((?:\\s+-\\s+.*\\n?)*)/m);\n if (blockMatch) {\n const items = blockMatch[1].matchAll(/^\\s+-\\s+(.+)$/gm);\n for (const item of items) {\n results.push(item[1].trim());\n }\n }\n return results;\n}\n\nexport function parseAssignmentFrontmatter(fileContent: string): AssignmentFrontmatter {\n const [frontmatter] = extractFrontmatter(fileContent);\n\n function getField(key: string): string | null {\n const match = frontmatter.match(new RegExp(`^${key}:\\\\s*(.*)$`, 'm'));\n if (!match) return null;\n return parseSimpleValue(match[1]);\n }\n\n return {\n id: getField('id') ?? '',\n slug: getField('slug') ?? '',\n title: getField('title') ?? '',\n project: getField('project'),\n type: getField('type'),\n status: getField('status') ?? 'pending',\n priority: (getField('priority') ?? 'medium') as AssignmentFrontmatter['priority'],\n created: getField('created') ?? '',\n updated: getField('updated') ?? '',\n assignee: getField('assignee'),\n externalIds: parseExternalIds(frontmatter),\n dependsOn: parseDependsOn(frontmatter),\n links: parseLinks(frontmatter),\n blockedReason: getField('blockedReason'),\n workspace: parseWorkspace(frontmatter),\n tags: parseTags(frontmatter),\n };\n}\n\nfunction formatYamlValue(value: string | null): string {\n if (value === null) return 'null';\n if (/^\\d{4}-\\d{2}-\\d{2}T/.test(value)) {\n return `\"${value}\"`;\n }\n // Quote values containing YAML-special characters that could cause parse issues\n if (/[:#{}[\\],&*?|>!%@`]/.test(value) || /^\\s|\\s$/.test(value) || value === '') {\n const escaped = value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"');\n return `\"${escaped}\"`;\n }\n return value;\n}\n\nexport function updateAssignmentFile(\n fileContent: string,\n updates: Partial<Pick<AssignmentFrontmatter, 'status' | 'assignee' | 'blockedReason' | 'updated'>>,\n): string {\n let result = fileContent;\n\n for (const [key, value] of Object.entries(updates)) {\n if (value === undefined) continue;\n const formatted = formatYamlValue(value as string | null);\n const fieldRegex = new RegExp(`^(${key}:)\\\\s*.*$`, 'm');\n if (fieldRegex.test(result)) {\n result = result.replace(fieldRegex, `$1 ${formatted}`);\n }\n }\n\n return result;\n}\n\n/**\n * Locate the `workspace:` block inside a frontmatter string and return the\n * [start, end) byte offsets of the *body* of that block (lines indented under\n * `workspace:`, excluding the `workspace:` header line itself). Returns null\n * if no `workspace:` block is present.\n */\nfunction findWorkspaceBlock(\n fmBlock: string,\n): { headerStart: number; bodyStart: number; bodyEnd: number } | null {\n const headerMatch = fmBlock.match(/^workspace:\\s*$/m);\n if (!headerMatch) return null;\n const headerStart = fmBlock.indexOf(headerMatch[0]);\n const bodyStart = headerStart + headerMatch[0].length + 1; // skip the trailing \\n\n const after = fmBlock.slice(bodyStart);\n const lines = after.split('\\n');\n let consumed = 0;\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (line.length === 0) {\n // blank line — consume but keep scanning; YAML allows blanks inside a block\n consumed += line.length + 1;\n continue;\n }\n if (line[0] !== ' ') break; // top-level key — block ended\n consumed += line.length + 1;\n }\n // Trim a trailing newline we counted past EOF\n const bodyEnd = Math.min(bodyStart + consumed, fmBlock.length);\n return { headerStart, bodyStart, bodyEnd };\n}\n\n/**\n * Update nested workspace.* fields (repository, worktreePath, branch, parentBranch)\n * in-place. Edits only inside the `workspace:` block — other indented keys\n * with the same name elsewhere in frontmatter are not touched. Preserves\n * field ordering and unknown workspace fields. If the `workspace:` block does\n * not exist, it is appended to the frontmatter.\n */\nexport function updateAssignmentWorkspace(\n fileContent: string,\n partial: Partial<Workspace>,\n): string {\n const fmMatch = fileContent.match(/^(---\\n)([\\s\\S]*?)(\\n---)/);\n if (!fmMatch) {\n throw new Error('No frontmatter found in assignment file. Expected --- delimiters.');\n }\n\n const fmBlock = fmMatch[2];\n const fields = ['repository', 'worktreePath', 'branch', 'parentBranch'] as const;\n const block = findWorkspaceBlock(fmBlock);\n\n let newFm = fmBlock;\n\n if (block) {\n let body = fmBlock.slice(block.bodyStart, block.bodyEnd);\n for (const field of fields) {\n if (!(field in partial)) continue;\n const value = partial[field] ?? null;\n const formatted = formatYamlValue(value);\n const lineRegex = new RegExp(`^(\\\\s+${field}:)\\\\s*.*$`, 'm');\n if (lineRegex.test(body)) {\n body = body.replace(lineRegex, `$1 ${formatted}`);\n } else {\n const trimmed = body.replace(/\\n+$/, '');\n body = `${trimmed}${trimmed.length > 0 ? '\\n' : ''} ${field}: ${formatted}\\n`;\n }\n }\n newFm =\n fmBlock.slice(0, block.bodyStart) + body + fmBlock.slice(block.bodyEnd);\n } else {\n const lines = ['workspace:'];\n for (const field of fields) {\n const value = field in partial ? (partial[field] ?? null) : null;\n lines.push(` ${field}: ${formatYamlValue(value)}`);\n }\n newFm = `${fmBlock.replace(/\\n+$/, '')}\\n${lines.join('\\n')}`;\n }\n\n return `${fmMatch[1]}${newFm}${fmMatch[3]}${fileContent.slice(fmMatch[0].length)}`;\n}\n","import { mkdir, writeFile, access, rename } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\n\nexport async function ensureDir(dir: string): Promise<void> {\n await mkdir(dir, { recursive: true });\n}\n\nexport async function fileExists(filePath: string): Promise<boolean> {\n try {\n await access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function writeFileSafe(\n filePath: string,\n content: string,\n): Promise<boolean> {\n if (await fileExists(filePath)) {\n return false;\n }\n await ensureDir(dirname(filePath));\n await writeFile(filePath, content, 'utf-8');\n return true;\n}\n\nexport async function writeFileForce(\n filePath: string,\n content: string,\n): Promise<void> {\n const dir = dirname(filePath);\n const tempPath = join(\n dir,\n `.${Math.random().toString(36).slice(2)}.${Date.now()}.tmp`,\n );\n await ensureDir(dir);\n await writeFile(tempPath, content, 'utf-8');\n await rename(tempPath, filePath);\n}\n","export function nowTimestamp(): string {\n return new Date().toISOString().replace(/\\.\\d{3}Z$/, 'Z');\n}\n","/**\n * Generic frontmatter/markdown parser for all Syntaur file types.\n * Pattern copied from src/lifecycle/frontmatter.ts:3-23 (extractFrontmatter + parseSimpleValue).\n */\n\nexport interface ParsedFile {\n frontmatter: Record<string, string>;\n body: string;\n}\n\n/**\n * Split a markdown file into its frontmatter block and body.\n */\nexport function extractFrontmatter(fileContent: string): [string, string] {\n const match = fileContent.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) {\n return ['', fileContent];\n }\n const frontmatterBlock = match[1];\n const body = fileContent.slice(match[0].length).trim();\n return [frontmatterBlock, body];\n}\n\n/**\n * Parse a simple YAML value, handling null and quoted strings.\n */\nfunction parseSimpleValue(raw: string): string | null {\n const trimmed = raw.trim();\n if (trimmed === 'null' || trimmed === '~' || trimmed === '') return null;\n if (\n (trimmed.startsWith('\"') && trimmed.endsWith('\"')) ||\n (trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\"))\n ) {\n return trimmed.slice(1, -1);\n }\n return trimmed;\n}\n\n/**\n * Extract a top-level scalar field from frontmatter text.\n */\nexport function getField(frontmatter: string, key: string): string | null {\n const match = frontmatter.match(new RegExp(`^${key}:\\\\s*(.*)$`, 'm'));\n if (!match) return null;\n return parseSimpleValue(match[1]);\n}\n\n/**\n * Extract an indented scalar field (one level deep) from frontmatter text.\n */\nexport function getNestedField(frontmatter: string, parent: string, key: string): string | null {\n const parentRegex = new RegExp(`^${parent}:\\\\s*\\\\n((?:\\\\s+.*\\\\n?)*)`, 'm');\n const parentMatch = frontmatter.match(parentRegex);\n if (!parentMatch) return null;\n const block = parentMatch[1];\n const fieldMatch = block.match(new RegExp(`^\\\\s+${key}:\\\\s*(.*)$`, 'm'));\n if (!fieldMatch) return null;\n return parseSimpleValue(fieldMatch[1]);\n}\n\n/**\n * Parse a YAML list field (e.g., tags, dependsOn, relatedAssignments).\n */\nfunction parseListField(frontmatter: string, fieldName: string): string[] {\n const inlineMatch = frontmatter.match(new RegExp(`^${fieldName}:\\\\s*\\\\[\\\\s*\\\\]`, 'm'));\n if (inlineMatch) return [];\n\n const results: string[] = [];\n const blockMatch = frontmatter.match(\n new RegExp(`^${fieldName}:\\\\s*\\\\n((?:\\\\s+-\\\\s+.*\\\\n?)*)`, 'm'),\n );\n if (blockMatch) {\n let item: RegExpExecArray | null;\n const regex = /^\\s+-\\s+(.+)$/gm;\n while ((item = regex.exec(blockMatch[1])) !== null) {\n results.push(item[1].trim());\n }\n }\n return results;\n}\n\n// --- Project Parser ---\n\nexport interface ParsedProject {\n id: string;\n slug: string;\n title: string;\n archived: boolean;\n archivedAt: string | null;\n archivedReason: string | null;\n statusOverride: string | null;\n created: string;\n updated: string;\n tags: string[];\n workspace: string | null;\n externalIds: Array<{ system: string; id: string; url: string | null }>;\n body: string;\n}\n\nexport function parseProject(fileContent: string): ParsedProject {\n const [fm, body] = extractFrontmatter(fileContent);\n // Legacy alias: pre-v0.2.0 installs used `mission` as the slug key. The\n // fs-migration helper renames the file but doesn't rewrite user-owned\n // frontmatter. Accept either key.\n const slug = getField(fm, 'slug') ?? getField(fm, 'mission') ?? '';\n return {\n id: getField(fm, 'id') ?? '',\n slug,\n title: getField(fm, 'title') ?? '',\n archived: getField(fm, 'archived') === 'true',\n archivedAt: getField(fm, 'archivedAt'),\n archivedReason: getField(fm, 'archivedReason'),\n statusOverride: getField(fm, 'statusOverride'),\n created: getField(fm, 'created') ?? '',\n updated: getField(fm, 'updated') ?? '',\n tags: parseListField(fm, 'tags'),\n workspace: getField(fm, 'workspace'),\n externalIds: parseExternalIds(fm),\n body,\n };\n}\n\n// --- Status Parser (for _status.md) ---\n\nexport interface ParsedStatus {\n project: string;\n status: string;\n progress: Record<string, number> & { total: number };\n needsAttention: {\n blockedCount: number;\n failedCount: number;\n openQuestions: number;\n };\n body: string;\n}\n\nexport function parseStatus(fileContent: string): ParsedStatus {\n const [fm, body] = extractFrontmatter(fileContent);\n\n // Dynamically parse progress fields\n const progress: Record<string, number> & { total: number } = { total: 0 };\n const progressMatch = fm.match(/^progress:\\s*\\n((?:\\s+.*\\n?)*)/m);\n if (progressMatch) {\n const lines = progressMatch[1].split('\\n');\n for (const line of lines) {\n const kv = line.match(/^\\s+(\\w+):\\s*(\\d+)/);\n if (kv) {\n progress[kv[1]] = parseInt(kv[2], 10);\n }\n }\n }\n\n return {\n project: getField(fm, 'project') ?? '',\n status: getField(fm, 'status') ?? 'pending',\n progress,\n needsAttention: {\n blockedCount: parseInt(getNestedField(fm, 'needsAttention', 'blockedCount') ?? '0', 10),\n failedCount: parseInt(getNestedField(fm, 'needsAttention', 'failedCount') ?? '0', 10),\n openQuestions: parseInt(getNestedField(fm, 'needsAttention', 'openQuestions') ?? '0', 10),\n },\n body,\n };\n}\n\n// --- Assignment Summary Parser ---\n\nexport interface ParsedAssignmentSummary {\n id: string;\n slug: string;\n title: string;\n status: string;\n priority: string;\n assignee: string | null;\n dependsOn: string[];\n links: string[];\n updated: string;\n}\n\nexport function parseAssignmentSummary(fileContent: string): ParsedAssignmentSummary {\n const [fm] = extractFrontmatter(fileContent);\n return {\n id: getField(fm, 'id') ?? '',\n slug: getField(fm, 'slug') ?? '',\n title: getField(fm, 'title') ?? '',\n status: getField(fm, 'status') ?? 'pending',\n priority: getField(fm, 'priority') ?? 'medium',\n assignee: getField(fm, 'assignee'),\n dependsOn: parseListField(fm, 'dependsOn'),\n links: parseListField(fm, 'links'),\n updated: getField(fm, 'updated') ?? '',\n };\n}\n\n// --- Full Assignment Parser ---\n\nexport interface ParsedAssignmentFull {\n id: string;\n slug: string;\n title: string;\n project: string | null;\n workspaceGroup: string | null;\n type: string | null;\n status: string;\n priority: string;\n assignee: string | null;\n dependsOn: string[];\n links: string[];\n blockedReason: string | null;\n workspace: {\n repository: string | null;\n worktreePath: string | null;\n branch: string | null;\n parentBranch: string | null;\n };\n externalIds: Array<{ system: string; id: string; url: string | null }>;\n tags: string[];\n created: string;\n updated: string;\n body: string;\n}\n\nfunction parseExternalIds(frontmatter: string): Array<{ system: string; id: string; url: string | null }> {\n const inlineMatch = frontmatter.match(/^externalIds:\\s*\\[\\s*\\]/m);\n if (inlineMatch) return [];\n\n const results: Array<{ system: string; id: string; url: string | null }> = [];\n const blockMatch = frontmatter.match(\n /^externalIds:\\s*\\n((?:\\s+-\\s+[\\s\\S]*?)(?=^\\w|\\n---))/m,\n );\n if (!blockMatch) return [];\n\n const itemBlocks = blockMatch[1].split(/\\n\\s+-\\s+/).filter(Boolean);\n for (const block of itemBlocks) {\n const lines = block.split('\\n');\n const entry: Record<string, string | null> = {};\n for (const line of lines) {\n const colonIdx = line.indexOf(':');\n if (colonIdx < 0) continue;\n const key = line.slice(0, colonIdx).trim().replace(/^-\\s+/, '');\n if (!key) continue;\n entry[key] = parseSimpleValue(line.slice(colonIdx + 1));\n }\n if (entry['system'] && entry['id']) {\n results.push({\n system: entry['system'],\n id: entry['id'],\n url: entry['url'] || null,\n });\n }\n }\n return results;\n}\n\nexport function parseAssignmentFull(fileContent: string): ParsedAssignmentFull {\n const [fm, body] = extractFrontmatter(fileContent);\n return {\n id: getField(fm, 'id') ?? '',\n slug: getField(fm, 'slug') ?? '',\n title: getField(fm, 'title') ?? '',\n project: getField(fm, 'project'),\n workspaceGroup: getField(fm, 'workspaceGroup'),\n type: getField(fm, 'type'),\n status: getField(fm, 'status') ?? 'pending',\n priority: getField(fm, 'priority') ?? 'medium',\n assignee: getField(fm, 'assignee'),\n dependsOn: parseListField(fm, 'dependsOn'),\n links: parseListField(fm, 'links'),\n blockedReason: getField(fm, 'blockedReason'),\n workspace: {\n repository: getNestedField(fm, 'workspace', 'repository'),\n worktreePath: getNestedField(fm, 'workspace', 'worktreePath'),\n branch: getNestedField(fm, 'workspace', 'branch'),\n parentBranch: getNestedField(fm, 'workspace', 'parentBranch'),\n },\n externalIds: parseExternalIds(fm),\n tags: parseListField(fm, 'tags'),\n created: getField(fm, 'created') ?? '',\n updated: getField(fm, 'updated') ?? '',\n body,\n };\n}\n\n// --- Plan Parser ---\n\nexport interface ParsedPlan {\n assignment: string;\n status: string;\n created: string;\n updated: string;\n body: string;\n}\n\nexport function parsePlan(fileContent: string): ParsedPlan {\n const [fm, body] = extractFrontmatter(fileContent);\n return {\n assignment: getField(fm, 'assignment') ?? '',\n status: getField(fm, 'status') ?? '',\n created: getField(fm, 'created') ?? '',\n updated: getField(fm, 'updated') ?? '',\n body,\n };\n}\n\n// --- Scratchpad Parser ---\n\nexport interface ParsedScratchpad {\n assignment: string;\n updated: string;\n body: string;\n}\n\nexport function parseScratchpad(fileContent: string): ParsedScratchpad {\n const [fm, body] = extractFrontmatter(fileContent);\n return {\n assignment: getField(fm, 'assignment') ?? '',\n updated: getField(fm, 'updated') ?? '',\n body,\n };\n}\n\n// --- Handoff Parser ---\n\nexport interface ParsedHandoff {\n assignment: string;\n handoffCount: number;\n updated: string;\n body: string;\n}\n\nexport function parseHandoff(fileContent: string): ParsedHandoff {\n const [fm, body] = extractFrontmatter(fileContent);\n return {\n assignment: getField(fm, 'assignment') ?? '',\n handoffCount: parseInt(getField(fm, 'handoffCount') ?? '0', 10),\n updated: getField(fm, 'updated') ?? '',\n body,\n };\n}\n\n// --- Decision Record Parser ---\n\nexport interface ParsedDecisionRecord {\n assignment: string;\n decisionCount: number;\n updated: string;\n body: string;\n}\n\nexport function parseDecisionRecord(fileContent: string): ParsedDecisionRecord {\n const [fm, body] = extractFrontmatter(fileContent);\n return {\n assignment: getField(fm, 'assignment') ?? '',\n decisionCount: parseInt(getField(fm, 'decisionCount') ?? '0', 10),\n updated: getField(fm, 'updated') ?? '',\n body,\n };\n}\n\n// --- Comments Parser ---\n\nexport interface ParsedComment {\n id: string;\n timestamp: string;\n author: string;\n type: 'question' | 'note' | 'feedback';\n body: string;\n replyTo?: string;\n resolved?: boolean;\n}\n\nexport interface ParsedComments {\n assignment: string;\n entryCount: number;\n updated: string;\n entries: ParsedComment[];\n body: string;\n}\n\nexport function parseComments(fileContent: string): ParsedComments {\n const [fm, body] = extractFrontmatter(fileContent);\n const entries: ParsedComment[] = [];\n const sections = body.split(/^## /m).slice(1);\n for (const section of sections) {\n const newlineIdx = section.indexOf('\\n');\n if (newlineIdx === -1) continue;\n const id = section.slice(0, newlineIdx).trim();\n const rest = section.slice(newlineIdx + 1);\n const headerMatch = rest.match(\n /^\\s*\\*\\*Recorded:\\*\\*\\s*(.*)\\n\\*\\*Author:\\*\\*\\s*(.*)\\n\\*\\*Type:\\*\\*\\s*(question|note|feedback)(?:\\n\\*\\*Reply to:\\*\\*\\s*(.*))?(?:\\n\\*\\*Resolved:\\*\\*\\s*(true|false))?\\n+([\\s\\S]*)$/,\n );\n if (!headerMatch) continue;\n const [, timestamp, author, type, replyTo, resolvedStr, entryBody] = headerMatch;\n const entry: ParsedComment = {\n id,\n timestamp: timestamp.trim(),\n author: author.trim(),\n type: type as 'question' | 'note' | 'feedback',\n body: entryBody.trim(),\n };\n if (replyTo) entry.replyTo = replyTo.trim();\n if (resolvedStr) entry.resolved = resolvedStr === 'true';\n entries.push(entry);\n }\n return {\n assignment: getField(fm, 'assignment') ?? '',\n entryCount: parseInt(getField(fm, 'entryCount') ?? '0', 10),\n updated: getField(fm, 'updated') ?? '',\n entries,\n body,\n };\n}\n\n// --- Progress Parser ---\n\nexport interface ProgressEntry {\n timestamp: string;\n body: string;\n}\n\nexport interface ParsedProgress {\n assignment: string;\n entryCount: number;\n updated: string;\n entries: ProgressEntry[];\n body: string;\n}\n\nexport function parseProgress(fileContent: string): ParsedProgress {\n const [fm, body] = extractFrontmatter(fileContent);\n const entries: ProgressEntry[] = [];\n const sections = body.split(/^## /m).slice(1);\n for (const section of sections) {\n const newlineIdx = section.indexOf('\\n');\n if (newlineIdx === -1) continue;\n const timestamp = section.slice(0, newlineIdx).trim();\n const entryBody = section.slice(newlineIdx + 1).trim();\n entries.push({ timestamp, body: entryBody });\n }\n return {\n assignment: getField(fm, 'assignment') ?? '',\n entryCount: parseInt(getField(fm, 'entryCount') ?? '0', 10),\n updated: getField(fm, 'updated') ?? '',\n entries,\n body,\n };\n}\n\n// --- Resource Parser ---\n\nexport interface ParsedResource {\n name: string;\n source: string;\n category: string;\n relatedAssignments: string[];\n created: string;\n updated: string;\n body: string;\n}\n\nexport function parseResource(fileContent: string): ParsedResource {\n const [fm, body] = extractFrontmatter(fileContent);\n return {\n name: getField(fm, 'name') ?? '',\n source: getField(fm, 'source') ?? '',\n category: getField(fm, 'category') ?? '',\n relatedAssignments: parseListField(fm, 'relatedAssignments'),\n created: getField(fm, 'created') ?? '',\n updated: getField(fm, 'updated') ?? '',\n body,\n };\n}\n\n// --- Memory Parser ---\n\nexport interface ParsedMemory {\n name: string;\n source: string;\n scope: string;\n sourceAssignment: string | null;\n relatedAssignments: string[];\n tags: string[];\n created: string;\n updated: string;\n body: string;\n}\n\nexport function parseMemory(fileContent: string): ParsedMemory {\n const [fm, body] = extractFrontmatter(fileContent);\n return {\n name: getField(fm, 'name') ?? '',\n source: getField(fm, 'source') ?? '',\n scope: getField(fm, 'scope') ?? '',\n sourceAssignment: getField(fm, 'sourceAssignment'),\n relatedAssignments: parseListField(fm, 'relatedAssignments'),\n tags: parseListField(fm, 'tags'),\n created: getField(fm, 'created') ?? '',\n updated: getField(fm, 'updated') ?? '',\n body,\n };\n}\n\n// --- Playbook Parser ---\n\nexport interface ParsedPlaybook {\n slug: string;\n name: string;\n description: string;\n whenToUse: string;\n created: string;\n updated: string;\n tags: string[];\n body: string;\n}\n\nexport function parsePlaybook(fileContent: string): ParsedPlaybook {\n const [fm, body] = extractFrontmatter(fileContent);\n return {\n slug: getField(fm, 'slug') ?? '',\n name: getField(fm, 'name') ?? '',\n description: getField(fm, 'description') ?? '',\n whenToUse: getField(fm, 'when_to_use') ?? '',\n created: getField(fm, 'created') ?? '',\n updated: getField(fm, 'updated') ?? '',\n tags: parseListField(fm, 'tags'),\n body,\n };\n}\n\n// --- Mermaid Graph Extractor ---\n\n/**\n * Extract the mermaid code block from _status.md body content.\n * Returns null if no mermaid block is found.\n */\nexport function extractMermaidGraph(body: string): string | null {\n const match = body.match(/```mermaid\\n([\\s\\S]*?)```/);\n return match ? match[1].trim() : null;\n}\n","import { randomBytes } from 'node:crypto';\nimport { readFile } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { extractFrontmatter, getField } from '../dashboard/parser.js';\nimport { ensureDir, fileExists, writeFileForce } from '../utils/fs.js';\nimport type {\n TodoItem,\n TodoChecklist,\n TodoStatus,\n ArchiveInterval,\n LogEntry,\n TodoLog,\n} from './types.js';\n\n// --- Short ID ---\n\nexport function generateShortId(): string {\n return randomBytes(2).toString('hex');\n}\n\nexport function generateUniqueId(existingIds: Set<string>): string {\n let id = generateShortId();\n let attempts = 0;\n while (existingIds.has(id) && attempts < 100) {\n id = generateShortId();\n attempts++;\n }\n return id;\n}\n\n// --- Checklist parsing ---\n\nconst ITEM_REGEX = /^- \\[([ x!]|>[^\\]]*)\\]\\s+(.+)$/;\nconst ID_REGEX = /\\[t:([a-f0-9]{4})\\]/;\nconst TAG_REGEX = /#([a-zA-Z0-9_-]+)/g;\n// Meta token follows `[t:<id>]` and looks like `<key=value;key=value;...>`.\n// Anchored at end of line. Recognized keys: b (branch), w (worktreePath),\n// c (createdAt), u (updatedAt), p (planDir), l (linkedAssignmentId),\n// lr (linkedAssignmentRef). Unknown keys are dropped.\nconst META_TOKEN_REGEX = /\\[t:[a-f0-9]{4}\\]\\s+<([^>]*)>\\s*$/;\nconst META_ENCODE_CHARS = ['%', '<', '>', '[', ']', '=', ';', '\\n', '\\r'];\n\nexport function encodeMetaValue(value: string): string {\n let out = '';\n for (const ch of value) {\n if (META_ENCODE_CHARS.includes(ch)) {\n out += '%' + ch.charCodeAt(0).toString(16).toUpperCase().padStart(2, '0');\n } else {\n out += ch;\n }\n }\n return out;\n}\n\nexport function decodeMetaValue(value: string): string {\n return value.replace(/%([0-9A-Fa-f]{2})/g, (_, hex) =>\n String.fromCharCode(parseInt(hex, 16)),\n );\n}\n\ninterface MetaFields {\n branch: string | null;\n worktreePath: string | null;\n createdAt: string | null;\n updatedAt: string | null;\n planDir: string | null;\n linkedAssignmentId: string | null;\n linkedAssignmentRef: string | null;\n}\n\nfunction emptyMetaFields(): MetaFields {\n return {\n branch: null,\n worktreePath: null,\n createdAt: null,\n updatedAt: null,\n planDir: null,\n linkedAssignmentId: null,\n linkedAssignmentRef: null,\n };\n}\n\nexport function parseMetaToken(line: string): MetaFields {\n const match = line.match(META_TOKEN_REGEX);\n if (!match) return emptyMetaFields();\n const body = match[1];\n if (!body) return emptyMetaFields();\n const fields = emptyMetaFields();\n for (const pair of body.split(';')) {\n const trimmed = pair.trim();\n if (!trimmed) continue;\n const eq = trimmed.indexOf('=');\n if (eq < 0) continue;\n const key = trimmed.slice(0, eq).trim();\n const rawValue = trimmed.slice(eq + 1);\n const value = decodeMetaValue(rawValue);\n switch (key) {\n case 'b': fields.branch = value; break;\n case 'w': fields.worktreePath = value; break;\n case 'c': fields.createdAt = value; break;\n case 'u': fields.updatedAt = value; break;\n case 'p': fields.planDir = value; break;\n case 'l': fields.linkedAssignmentId = value; break;\n case 'lr': fields.linkedAssignmentRef = value; break;\n }\n }\n return fields;\n}\n\nexport function serializeMetaToken(item: TodoItem): string {\n const pairs: string[] = [];\n if (item.branch !== null) pairs.push(`b=${encodeMetaValue(item.branch)}`);\n if (item.worktreePath !== null) pairs.push(`w=${encodeMetaValue(item.worktreePath)}`);\n if (item.createdAt !== null) pairs.push(`c=${encodeMetaValue(item.createdAt)}`);\n if (item.updatedAt !== null) pairs.push(`u=${encodeMetaValue(item.updatedAt)}`);\n if (item.planDir !== null) pairs.push(`p=${encodeMetaValue(item.planDir)}`);\n if (item.linkedAssignmentId !== null) pairs.push(`l=${encodeMetaValue(item.linkedAssignmentId)}`);\n if (item.linkedAssignmentRef !== null) pairs.push(`lr=${encodeMetaValue(item.linkedAssignmentRef)}`);\n if (pairs.length === 0) return '';\n return `<${pairs.join(';')}>`;\n}\n\nfunction parseStatus(marker: string): { status: TodoStatus; session: string | null } {\n if (marker === ' ') return { status: 'open', session: null };\n if (marker === 'x') return { status: 'completed', session: null };\n if (marker === '!') return { status: 'blocked', session: null };\n if (marker.startsWith('>:')) return { status: 'in_progress', session: marker.slice(2) };\n if (marker === '>') return { status: 'in_progress', session: null };\n return { status: 'open', session: null };\n}\n\nfunction sanitizeSession(session: string): string {\n // Strip characters that would break the markdown checkbox syntax\n return session.replace(/[\\[\\]]/g, '');\n}\n\nfunction statusToMarker(item: TodoItem): string {\n switch (item.status) {\n case 'open':\n return ' ';\n case 'completed':\n return 'x';\n case 'blocked':\n return '!';\n case 'in_progress':\n return item.session ? `>:${sanitizeSession(item.session)}` : '>';\n }\n}\n\nexport function parseChecklistItem(line: string): TodoItem | null {\n const match = line.match(ITEM_REGEX);\n if (!match) return null;\n\n const marker = match[1];\n const rest = match[2];\n\n const { status, session } = parseStatus(marker);\n\n const idMatch = rest.match(ID_REGEX);\n const id = idMatch ? idMatch[1] : '';\n\n const tags: string[] = [];\n let tagMatch;\n const tagRegex = new RegExp(TAG_REGEX.source, 'g');\n while ((tagMatch = tagRegex.exec(rest)) !== null) {\n tags.push(tagMatch[1]);\n }\n\n // Description is everything before the first #tag or [t:...], trimmed\n let description = rest;\n const firstTagIdx = rest.search(/#[a-zA-Z0-9_-]/);\n const firstIdIdx = rest.search(/\\[t:[a-f0-9]{4}\\]/);\n const cutPoints = [firstTagIdx, firstIdIdx].filter((i) => i >= 0);\n if (cutPoints.length > 0) {\n description = rest.slice(0, Math.min(...cutPoints)).trim();\n }\n\n const meta = parseMetaToken(line);\n\n return {\n id,\n description,\n status,\n tags,\n session,\n branch: meta.branch,\n worktreePath: meta.worktreePath,\n createdAt: meta.createdAt,\n updatedAt: meta.updatedAt,\n planDir: meta.planDir,\n linkedAssignmentId: meta.linkedAssignmentId,\n linkedAssignmentRef: meta.linkedAssignmentRef,\n };\n}\n\nexport function serializeChecklistItem(item: TodoItem): string {\n const marker = statusToMarker(item);\n const tagStr = item.tags.map((t) => `#${t}`).join(' ');\n const parts = [`- [${marker}] ${item.description}`];\n if (tagStr) parts.push(tagStr);\n parts.push(`[t:${item.id}]`);\n const meta = serializeMetaToken(item);\n if (meta) parts.push(meta);\n return parts.join(' ');\n}\n\nexport function parseChecklist(content: string): TodoChecklist {\n const [fm, body] = extractFrontmatter(content);\n const workspace = getField(fm, 'workspace') || '_global';\n const archiveIntervalRaw = getField(fm, 'archiveInterval') || 'weekly';\n const archiveInterval = (['daily', 'weekly', 'monthly', 'never'].includes(archiveIntervalRaw)\n ? archiveIntervalRaw\n : 'weekly') as ArchiveInterval;\n\n const items: TodoItem[] = [];\n for (const line of body.split('\\n')) {\n const item = parseChecklistItem(line);\n if (item) items.push(item);\n }\n\n return { workspace, archiveInterval, items };\n}\n\nexport function serializeChecklist(checklist: TodoChecklist): string {\n const fm = [\n '---',\n `workspace: ${checklist.workspace}`,\n `archiveInterval: ${checklist.archiveInterval}`,\n '---',\n ].join('\\n');\n\n const header = '# Quick Todos';\n const items = checklist.items.map(serializeChecklistItem).join('\\n');\n\n return `${fm}\\n\\n${header}\\n\\n${items}\\n`;\n}\n\n// --- Log parsing ---\n\nexport function parseLog(content: string): TodoLog {\n const [fm, body] = extractFrontmatter(content);\n const workspace = getField(fm, 'workspace') || '_global';\n\n const entries: LogEntry[] = [];\n const sections = body.split(/^### /m).filter((s) => s.match(/^\\d{4}-/));\n\n for (const section of sections) {\n const lines = section.split('\\n');\n const heading = lines[0]?.trim() || '';\n\n // Heading format: 2026-04-07T14:30:00Z — t:a3f1, t:b7c2\n const headingMatch = heading.match(/^(\\S+)\\s*—?\\s*(.*)/);\n if (!headingMatch) continue;\n\n const timestamp = headingMatch[1];\n const idsPart = headingMatch[2] || '';\n const itemIds = [...idsPart.matchAll(/t:([a-f0-9]{4})/g)].map((m) => m[1]);\n\n const entry: LogEntry = {\n timestamp,\n itemIds,\n items: '',\n session: null,\n branch: null,\n summary: '',\n blockers: null,\n status: null,\n };\n\n for (const line of lines.slice(1)) {\n const fieldMatch = line.match(/^\\*\\*(\\w+):\\*\\*\\s*(.*)/);\n if (!fieldMatch) continue;\n const key = fieldMatch[1].toLowerCase();\n const value = fieldMatch[2].trim();\n switch (key) {\n case 'items':\n entry.items = value;\n break;\n case 'session':\n entry.session = value;\n break;\n case 'branch':\n entry.branch = value;\n break;\n case 'summary':\n entry.summary = value;\n break;\n case 'blockers':\n entry.blockers = value;\n break;\n case 'status':\n entry.status = value;\n break;\n }\n }\n\n entries.push(entry);\n }\n\n return { workspace, entries };\n}\n\nexport function serializeLogEntry(entry: LogEntry): string {\n const idStr = entry.itemIds.map((id) => `t:${id}`).join(', ');\n const lines = [`### ${entry.timestamp} — ${idStr}`];\n if (entry.items) lines.push(`**Items:** ${entry.items}`);\n if (entry.session) lines.push(`**Session:** ${entry.session}`);\n if (entry.branch) lines.push(`**Branch:** ${entry.branch}`);\n if (entry.summary) lines.push(`**Summary:** ${entry.summary}`);\n if (entry.blockers) lines.push(`**Blockers:** ${entry.blockers}`);\n if (entry.status) lines.push(`**Status:** ${entry.status}`);\n return lines.join('\\n');\n}\n\n// --- File I/O ---\n\nexport function checklistPath(todosDir: string, workspace: string): string {\n return resolve(todosDir, `${workspace}.md`);\n}\n\nexport function logPath(todosDir: string, workspace: string): string {\n return resolve(todosDir, `${workspace}-log.md`);\n}\n\nexport function archivePath(\n todosDir: string,\n workspace: string,\n interval: ArchiveInterval,\n now: Date = new Date(),\n): string {\n const year = now.getFullYear();\n const month = String(now.getMonth() + 1).padStart(2, '0');\n const day = String(now.getDate()).padStart(2, '0');\n\n let suffix: string;\n switch (interval) {\n case 'daily':\n suffix = `${year}-${month}-${day}`;\n break;\n case 'weekly': {\n // ISO week number\n const jan1 = new Date(year, 0, 1);\n const days = Math.floor((now.getTime() - jan1.getTime()) / 86400000);\n const week = String(Math.ceil((days + jan1.getDay() + 1) / 7)).padStart(2, '0');\n suffix = `${year}-W${week}`;\n break;\n }\n case 'monthly':\n suffix = `${year}-${month}`;\n break;\n default:\n suffix = `${year}-${month}-${day}`;\n }\n\n return resolve(todosDir, 'archive', `${workspace}-${suffix}.md`);\n}\n\nexport async function readChecklist(todosDir: string, workspace: string): Promise<TodoChecklist> {\n const path = checklistPath(todosDir, workspace);\n if (!(await fileExists(path))) {\n return { workspace, archiveInterval: 'weekly', items: [] };\n }\n const content = await readFile(path, 'utf-8');\n return parseChecklist(content);\n}\n\nexport async function writeChecklist(todosDir: string, checklist: TodoChecklist): Promise<void> {\n await ensureDir(todosDir);\n const path = checklistPath(todosDir, checklist.workspace);\n await writeFileForce(path, serializeChecklist(checklist));\n}\n\nexport async function readLog(todosDir: string, workspace: string): Promise<TodoLog> {\n const path = logPath(todosDir, workspace);\n if (!(await fileExists(path))) {\n return { workspace, entries: [] };\n }\n const content = await readFile(path, 'utf-8');\n return parseLog(content);\n}\n\nexport async function appendLogEntry(\n todosDir: string,\n workspace: string,\n entry: LogEntry,\n): Promise<void> {\n await ensureDir(todosDir);\n const path = logPath(todosDir, workspace);\n let content: string;\n if (await fileExists(path)) {\n content = await readFile(path, 'utf-8');\n content = content.trimEnd() + '\\n\\n' + serializeLogEntry(entry) + '\\n';\n } else {\n const fm = `---\\nworkspace: ${workspace}\\n---\\n\\n# Todo Log\\n\\n`;\n content = fm + serializeLogEntry(entry) + '\\n';\n }\n await writeFileForce(path, content);\n}\n\nexport function computeCounts(items: TodoItem[]) {\n const counts = { open: 0, in_progress: 0, completed: 0, blocked: 0, total: items.length };\n for (const item of items) {\n counts[item.status]++;\n }\n return counts;\n}\n","import { readdir } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport {\n readChecklist,\n writeChecklist,\n readLog,\n appendLogEntry,\n} from '../todos/parser.js';\nimport { fileExists } from '../utils/fs.js';\nimport type { TodoItem, LogEntry } from '../todos/types.js';\n\nexport interface LinkedTodosLookup {\n /** Workspace todos dir (e.g. ~/.syntaur/todos). */\n todosDir: string;\n /** Projects root dir (e.g. ~/.syntaur/projects). Used to scan per-project todo checklists. */\n projectsDir: string;\n}\n\nexport interface LinkedTodosResult {\n completed?: number;\n reopened?: number;\n touched: Array<{ workspace: string; id: string }>;\n}\n\nconst AUTO_COMPLETE_PREFIX = 'Auto-completed: linked assignment ';\nconst AUTO_REOPEN_PREFIX = 'Auto-reopened: linked assignment ';\n\nfunction touchItem(item: TodoItem): void {\n const now = new Date().toISOString();\n if (item.createdAt === null) item.createdAt = now;\n item.updatedAt = now;\n}\n\nasync function listWorkspaceTodosFiles(todosDir: string): Promise<string[]> {\n if (!(await fileExists(todosDir))) return [];\n const files = await readdir(todosDir).catch(() => [] as string[]);\n return files\n .filter((f): f is string => typeof f === 'string')\n .filter((f) => f.endsWith('.md') && !f.endsWith('-log.md'))\n .map((f) => f.replace(/\\.md$/, ''));\n}\n\nasync function listProjectTodosWorkspaces(projectsDir: string): Promise<Array<{ projectSlug: string; todosDir: string; workspace: string }>> {\n if (!(await fileExists(projectsDir))) return [];\n const projects = await readdir(projectsDir).catch(() => [] as string[]);\n const result: Array<{ projectSlug: string; todosDir: string; workspace: string }> = [];\n for (const p of projects) {\n if (typeof p !== 'string') continue;\n const todosDir = resolve(projectsDir, p, 'todos');\n if (await fileExists(resolve(todosDir, `${p}.md`))) {\n result.push({ projectSlug: p, todosDir, workspace: p });\n }\n }\n return result;\n}\n\n/**\n * Returns true if the most recent log entry for this item has summary\n * starting with `prefix`. Used to identify items that were auto-completed\n * (so we know it is safe to auto-reopen them) and items that were already\n * auto-reopened (idempotency).\n */\nasync function lastLogEntryMatches(\n todosDir: string,\n workspace: string,\n itemId: string,\n prefix: string,\n): Promise<boolean> {\n const log = await readLog(todosDir, workspace);\n // Scan in reverse: most recent matching entry for this item.\n for (let i = log.entries.length - 1; i >= 0; i--) {\n const entry = log.entries[i];\n if (!entry.itemIds.includes(itemId)) continue;\n return entry.summary.startsWith(prefix);\n }\n return false;\n}\n\nexport async function completeLinkedTodos(\n lookup: LinkedTodosLookup,\n assignmentId: string,\n assignmentRef: string,\n): Promise<LinkedTodosResult> {\n const touched: Array<{ workspace: string; id: string }> = [];\n\n const workspaces = await listWorkspaceTodosFiles(lookup.todosDir);\n const projectWorkspaces = await listProjectTodosWorkspaces(lookup.projectsDir);\n const all: Array<{ todosDir: string; workspace: string }> = [\n ...workspaces.map((workspace) => ({ todosDir: lookup.todosDir, workspace })),\n ...projectWorkspaces.map(({ todosDir, workspace }) => ({ todosDir, workspace })),\n ];\n\n for (const { todosDir, workspace } of all) {\n const checklist = await readChecklist(todosDir, workspace);\n const idsTouched: string[] = [];\n for (const item of checklist.items) {\n if (item.linkedAssignmentId !== assignmentId) continue;\n if (item.status === 'completed') continue;\n item.status = 'completed';\n item.session = null;\n touchItem(item);\n idsTouched.push(item.id);\n }\n if (idsTouched.length === 0) continue;\n await writeChecklist(todosDir, checklist);\n for (const id of idsTouched) {\n const entry: LogEntry = {\n timestamp: new Date().toISOString(),\n itemIds: [id],\n items: checklist.items.find((i) => i.id === id)?.description ?? '',\n session: null,\n branch: null,\n summary: `${AUTO_COMPLETE_PREFIX}${assignmentRef} closed`,\n blockers: null,\n status: null,\n };\n await appendLogEntry(todosDir, workspace, entry);\n touched.push({ workspace, id });\n }\n }\n\n return { completed: touched.length, touched };\n}\n\nexport async function reopenLinkedTodos(\n lookup: LinkedTodosLookup,\n assignmentId: string,\n assignmentRef: string,\n): Promise<LinkedTodosResult> {\n const touched: Array<{ workspace: string; id: string }> = [];\n\n const workspaces = await listWorkspaceTodosFiles(lookup.todosDir);\n const projectWorkspaces = await listProjectTodosWorkspaces(lookup.projectsDir);\n const all: Array<{ todosDir: string; workspace: string }> = [\n ...workspaces.map((workspace) => ({ todosDir: lookup.todosDir, workspace })),\n ...projectWorkspaces.map(({ todosDir, workspace }) => ({ todosDir, workspace })),\n ];\n\n for (const { todosDir, workspace } of all) {\n const checklist = await readChecklist(todosDir, workspace);\n const candidates = checklist.items.filter(\n (i) => i.linkedAssignmentId === assignmentId && i.status === 'completed',\n );\n if (candidates.length === 0) continue;\n const idsTouched: string[] = [];\n for (const item of candidates) {\n // Manual-completion guard: only auto-reopen items whose most recent log\n // entry is the auto-complete marker. If the user marked them complete\n // by hand afterwards, leave them alone.\n const wasAutoCompleted = await lastLogEntryMatches(\n todosDir,\n workspace,\n item.id,\n AUTO_COMPLETE_PREFIX,\n );\n if (!wasAutoCompleted) continue;\n item.status = 'in_progress';\n item.session = null;\n touchItem(item);\n idsTouched.push(item.id);\n }\n if (idsTouched.length === 0) continue;\n await writeChecklist(todosDir, checklist);\n for (const id of idsTouched) {\n const entry: LogEntry = {\n timestamp: new Date().toISOString(),\n itemIds: [id],\n items: checklist.items.find((i) => i.id === id)?.description ?? '',\n session: null,\n branch: null,\n summary: `${AUTO_REOPEN_PREFIX}${assignmentRef} reopened`,\n blockers: null,\n status: null,\n };\n await appendLogEntry(todosDir, workspace, entry);\n touched.push({ workspace, id });\n }\n }\n\n return { reopened: touched.length, touched };\n}\n","import { resolve } from 'node:path';\nimport { readFile } from 'node:fs/promises';\nimport { fileExists, writeFileForce } from '../utils/fs.js';\nimport { nowTimestamp } from '../utils/timestamp.js';\nimport { getTargetStatus } from './state-machine.js';\nimport { parseAssignmentFrontmatter, updateAssignmentFile } from './frontmatter.js';\nimport {\n completeLinkedTodos,\n reopenLinkedTodos,\n type LinkedTodosLookup,\n} from './linked-todos.js';\nimport type { TransitionCommand, TransitionResult, AssignmentFrontmatter } from './types.js';\n\nfunction linkedAssignmentRef(frontmatter: AssignmentFrontmatter): string {\n return frontmatter.project ? `${frontmatter.project}/${frontmatter.slug}` : frontmatter.id;\n}\n\nasync function applyLinkedTodosSideEffect(\n lookup: LinkedTodosLookup | undefined,\n command: string,\n targetStatus: string,\n frontmatter: AssignmentFrontmatter,\n): Promise<void> {\n if (!lookup) return;\n const ref = linkedAssignmentRef(frontmatter);\n if (targetStatus === 'completed') {\n await completeLinkedTodos(lookup, frontmatter.id, ref);\n } else if (command === 'reopen') {\n await reopenLinkedTodos(lookup, frontmatter.id, ref);\n }\n}\n\nfunction resolveAssignmentPath(projectDir: string, assignmentSlug: string): string {\n return resolve(projectDir, 'assignments', assignmentSlug, 'assignment.md');\n}\n\nasync function readAssignment(\n filePath: string,\n): Promise<{ content: string; frontmatter: AssignmentFrontmatter }> {\n if (!(await fileExists(filePath))) {\n throw new Error(`Assignment file not found: ${filePath}`);\n }\n const content = await readFile(filePath, 'utf-8');\n const frontmatter = parseAssignmentFrontmatter(content);\n return { content, frontmatter };\n}\n\nasync function checkDependencies(\n projectDir: string,\n dependsOn: string[],\n terminalStatuses?: ReadonlySet<string>,\n): Promise<{ satisfied: boolean; unmet: string[] }> {\n const terminals = terminalStatuses ?? new Set(['completed']);\n const unmet: string[] = [];\n for (const depSlug of dependsOn) {\n const depPath = resolveAssignmentPath(projectDir, depSlug);\n if (!(await fileExists(depPath))) {\n unmet.push(`${depSlug} (file not found)`);\n continue;\n }\n const depContent = await readFile(depPath, 'utf-8');\n const depFrontmatter = parseAssignmentFrontmatter(depContent);\n if (!terminals.has(depFrontmatter.status)) {\n unmet.push(`${depSlug} (status: ${depFrontmatter.status})`);\n }\n }\n return { satisfied: unmet.length === 0, unmet };\n}\n\nexport interface TransitionOptions {\n reason?: string;\n agent?: string;\n transitionTable?: Map<string, string>;\n terminalStatuses?: ReadonlySet<string>;\n /**\n * When provided, on a transition to `completed` we scan the configured todos\n * dirs and auto-complete any todo whose `linkedAssignmentId` matches this\n * assignment's UUID. On `reopen` we auto-reopen any such todo whose most\n * recent log entry is the auto-complete marker (manual completions are left\n * untouched).\n */\n linkedTodosLookup?: LinkedTodosLookup;\n}\n\nconst ASSIGNEE_SETTING_COMMANDS = new Set(['start', 'shape', 'plan-ready', 'implement']);\n\nexport async function executeTransition(\n projectDir: string,\n assignmentSlug: string,\n command: Exclude<TransitionCommand, 'assign'>,\n options: TransitionOptions = {},\n): Promise<TransitionResult> {\n const filePath = resolveAssignmentPath(projectDir, assignmentSlug);\n const { content, frontmatter } = await readAssignment(filePath);\n\n const targetStatus = getTargetStatus(frontmatter.status, command, options.transitionTable);\n\n if (!targetStatus) {\n return {\n success: false,\n message: `Unknown command '${command}' for assignment \"${assignmentSlug}\".`,\n fromStatus: frontmatter.status,\n };\n }\n\n const warnings: string[] = [];\n\n if (command === 'start' && frontmatter.dependsOn.length > 0) {\n const depCheck = await checkDependencies(projectDir, frontmatter.dependsOn, options.terminalStatuses);\n if (!depCheck.satisfied) {\n warnings.push(`Starting with unmet dependencies: ${depCheck.unmet.join(', ')}`);\n }\n }\n\n const updates: Partial<Pick<AssignmentFrontmatter, 'status' | 'assignee' | 'blockedReason' | 'updated'>> = {\n status: targetStatus,\n updated: nowTimestamp(),\n };\n\n if (ASSIGNEE_SETTING_COMMANDS.has(command) && options.agent && !frontmatter.assignee) {\n updates.assignee = options.agent;\n }\n if (command === 'block') {\n updates.blockedReason = options.reason ?? null;\n }\n if (command === 'unblock') {\n updates.blockedReason = null;\n }\n\n const updatedContent = updateAssignmentFile(content, updates);\n await writeFileForce(filePath, updatedContent);\n\n await applyLinkedTodosSideEffect(options.linkedTodosLookup, command, targetStatus, frontmatter);\n\n return {\n success: true,\n message: `Assignment \"${assignmentSlug}\" transitioned: ${frontmatter.status} -> ${targetStatus}`,\n fromStatus: frontmatter.status,\n toStatus: targetStatus,\n warnings: warnings.length > 0 ? warnings : undefined,\n };\n}\n\nexport async function executeAssign(\n projectDir: string,\n assignmentSlug: string,\n agent: string,\n): Promise<TransitionResult> {\n const filePath = resolveAssignmentPath(projectDir, assignmentSlug);\n const { content, frontmatter } = await readAssignment(filePath);\n\n const updates: Partial<Pick<AssignmentFrontmatter, 'status' | 'assignee' | 'blockedReason' | 'updated'>> = {\n assignee: agent,\n updated: nowTimestamp(),\n };\n\n const updatedContent = updateAssignmentFile(content, updates);\n await writeFileForce(filePath, updatedContent);\n\n return {\n success: true,\n message: `Assignment \"${assignmentSlug}\" assigned to '${agent}'.`,\n fromStatus: frontmatter.status,\n };\n}\n\nexport interface TransitionByDirOptions extends TransitionOptions {\n standalone?: boolean;\n}\n\nexport async function executeTransitionByDir(\n assignmentDir: string,\n command: Exclude<TransitionCommand, 'assign'>,\n options: TransitionByDirOptions = {},\n): Promise<TransitionResult> {\n const filePath = resolve(assignmentDir, 'assignment.md');\n const { content, frontmatter } = await readAssignment(filePath);\n\n const targetStatus = getTargetStatus(frontmatter.status, command, options.transitionTable);\n if (!targetStatus) {\n return {\n success: false,\n message: `Unknown command '${command}' for assignment \"${frontmatter.slug || assignmentDir}\".`,\n fromStatus: frontmatter.status,\n };\n }\n\n const warnings: string[] = [];\n\n if (command === 'start' && !options.standalone && frontmatter.dependsOn.length > 0) {\n // Dependency check requires a project context — skip for standalone\n const projectDir = resolve(assignmentDir, '..', '..');\n const depCheck = await checkDependencies(\n projectDir,\n frontmatter.dependsOn,\n options.terminalStatuses,\n );\n if (!depCheck.satisfied) {\n warnings.push(`Starting with unmet dependencies: ${depCheck.unmet.join(', ')}`);\n }\n }\n\n const updates: Partial<Pick<AssignmentFrontmatter, 'status' | 'assignee' | 'blockedReason' | 'updated'>> = {\n status: targetStatus,\n updated: nowTimestamp(),\n };\n\n if (ASSIGNEE_SETTING_COMMANDS.has(command) && options.agent && !frontmatter.assignee) {\n updates.assignee = options.agent;\n }\n if (command === 'block') {\n updates.blockedReason = options.reason ?? null;\n }\n if (command === 'unblock') {\n updates.blockedReason = null;\n }\n\n const updatedContent = updateAssignmentFile(content, updates);\n await writeFileForce(filePath, updatedContent);\n\n await applyLinkedTodosSideEffect(options.linkedTodosLookup, command, targetStatus, frontmatter);\n\n return {\n success: true,\n message: `Assignment \"${frontmatter.slug || assignmentDir}\" transitioned: ${frontmatter.status} -> ${targetStatus}`,\n fromStatus: frontmatter.status,\n toStatus: targetStatus,\n warnings: warnings.length > 0 ? warnings : undefined,\n };\n}\n\nexport async function executeAssignByDir(\n assignmentDir: string,\n agent: string,\n): Promise<TransitionResult> {\n const filePath = resolve(assignmentDir, 'assignment.md');\n const { content, frontmatter } = await readAssignment(filePath);\n\n const updates: Partial<Pick<AssignmentFrontmatter, 'status' | 'assignee' | 'blockedReason' | 'updated'>> = {\n assignee: agent,\n updated: nowTimestamp(),\n };\n\n const updatedContent = updateAssignmentFile(content, updates);\n await writeFileForce(filePath, updatedContent);\n\n return {\n success: true,\n message: `Assignment \"${frontmatter.slug || assignmentDir}\" assigned to '${agent}'.`,\n fromStatus: frontmatter.status,\n };\n}\n","export type {\n AssignmentStatus,\n TransitionCommand,\n AssignmentFrontmatter,\n ExternalId,\n Workspace,\n TransitionResult,\n} from './types.js';\nexport { TERMINAL_STATUSES, DEFAULT_STATUSES, DEFAULT_COMMANDS, DEFAULT_TERMINAL_STATUSES } from './types.js';\nexport { canTransition, getTargetStatus, isTerminalStatus, DEFAULT_TRANSITION_TABLE, DEFAULT_COMMAND_TARGETS, buildTransitionTable, buildCommandTargets } from './state-machine.js';\nexport { parseAssignmentFrontmatter, updateAssignmentFile, updateAssignmentWorkspace } from './frontmatter.js';\nexport { executeTransition, executeAssign, executeTransitionByDir, executeAssignByDir } from './transitions.js';\nexport type { TransitionOptions, TransitionByDirOptions } from './transitions.js';\n","export interface ConfigParams {\n defaultProjectDir: string;\n}\n\nexport function renderConfig(params: ConfigParams): string {\n return `---\nversion: \"1.0\"\ndefaultProjectDir: ${params.defaultProjectDir}\nonboarding:\n completed: false\nagentDefaults:\n trustLevel: medium\n autoApprove: false\nbackup:\n repo: null\n categories: projects, playbooks, todos, servers, config\n lastBackup: null\n lastRestore: null\nterminal: terminal-app\n---\n\n# Syntaur Configuration\n\nGlobal configuration for the Syntaur CLI.\n`;\n}\n","import { readdir, readFile, rename, writeFile } from 'node:fs/promises';\nimport type { Dirent } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { fileExists } from './fs.js';\n\n/**\n * Filesystem-level migrations for users upgrading from pre-v0.2.0 installs,\n * where the product used \"mission\" terminology. v0.2.0 renamed code but\n * shipped no on-disk migration, leaving user state unreadable by the new\n * scanner. These helpers close that gap.\n *\n * All helpers are idempotent, safe on missing paths, and NEVER delete user\n * files. Legacy files that are no longer read (e.g., per-project agent.md,\n * claude.md) are left untouched.\n */\n\nexport interface ProjectFilesMigrationResult {\n /** Relative paths of files that were renamed (e.g. `ai-chat-v2/mission.md`). */\n renamedProjectFiles: string[];\n /** Project slugs that still have stale agent.md / claude.md files. Reported, not deleted. */\n legacyExtras: string[];\n}\n\nexport interface ConfigMigrationResult {\n /** True if `defaultMissionDir` was renamed to `defaultProjectDir`. */\n renamedField: boolean;\n /** True if the on-disk `<root>/missions` dir was renamed to `<root>/projects`. */\n renamedDir: boolean;\n /** The resolved projects dir after migration (absolute, or null if config absent). */\n resolvedProjectsDir: string | null;\n}\n\n/**\n * Walk each project directory under `projectsDir` and rename\n * `mission.md` → `project.md` when the legacy file is present and the new\n * name isn't. Reports stale per-project `agent.md` / `claude.md` files\n * without touching them.\n *\n * Swallows per-entry errors (e.g., EPERM on a single dir) so one bad\n * project can't block the rest. Never throws.\n */\nexport async function migrateLegacyProjectFiles(\n projectsDir: string,\n): Promise<ProjectFilesMigrationResult> {\n const result: ProjectFilesMigrationResult = {\n renamedProjectFiles: [],\n legacyExtras: [],\n };\n\n if (!(await fileExists(projectsDir))) return result;\n\n let entries: Dirent[];\n try {\n entries = (await readdir(projectsDir, { withFileTypes: true })) as Dirent[];\n } catch {\n return result;\n }\n\n for (const entry of entries) {\n if (!entry.isDirectory() || entry.name.startsWith('.')) continue;\n\n const projectDir = resolve(projectsDir, entry.name);\n const legacy = resolve(projectDir, 'mission.md');\n const target = resolve(projectDir, 'project.md');\n\n try {\n if ((await fileExists(legacy)) && !(await fileExists(target))) {\n await rename(legacy, target);\n result.renamedProjectFiles.push(`${entry.name}/mission.md`);\n }\n } catch {\n // Swallow per-project errors (permission denied, racing editor, etc).\n continue;\n }\n\n // Surface stale legacy files without deleting them — caller decides how\n // to present (log once at startup).\n for (const stale of ['agent.md', 'claude.md']) {\n try {\n if (await fileExists(resolve(projectDir, stale))) {\n result.legacyExtras.push(`${entry.name}/${stale}`);\n }\n } catch {\n // Ignore.\n }\n }\n }\n\n return result;\n}\n\n/**\n * Migrate ~/.syntaur/config.md frontmatter and, optionally, the on-disk\n * projects directory, from the pre-v0.2.0 \"mission\" layout.\n *\n * - Renames `defaultMissionDir` → `defaultProjectDir` in frontmatter when\n * the new key isn't already present.\n * - If the resolved projects dir ends in `/missions` AND that dir exists\n * AND its `/projects` sibling does not, renames the directory on disk\n * and updates the config to point at the new path.\n *\n * Only rewrites the config file when an actual change is made.\n */\nexport async function migrateLegacyConfig(\n configPath: string,\n): Promise<ConfigMigrationResult> {\n const result: ConfigMigrationResult = {\n renamedField: false,\n renamedDir: false,\n resolvedProjectsDir: null,\n };\n\n if (!(await fileExists(configPath))) return result;\n\n let content: string;\n try {\n content = await readFile(configPath, 'utf-8');\n } catch {\n return result;\n }\n\n const fmMatch = content.match(/^---\\n([\\s\\S]*?)\\n---\\n?/);\n if (!fmMatch) return result;\n\n const fmBlock = fmMatch[1];\n const afterFm = content.slice(fmMatch[0].length);\n\n // --- Field rename ---\n const missionLineRe = /^(\\s*)defaultMissionDir\\s*:\\s*(.*)$/m;\n const missionLineMatch = fmBlock.match(missionLineRe);\n const hasProjectLine = /^\\s*defaultProjectDir\\s*:/m.test(fmBlock);\n\n let newFmBlock = fmBlock;\n let missionValue: string | null = null;\n if (missionLineMatch) {\n missionValue = missionLineMatch[2].trim();\n if (!hasProjectLine) {\n newFmBlock = fmBlock.replace(\n missionLineRe,\n `$1defaultProjectDir: ${missionValue}`,\n );\n result.renamedField = true;\n } else {\n // Both keys present; strip the legacy one to avoid drift.\n newFmBlock = fmBlock.replace(missionLineRe, '').replace(/\\n{2,}/g, '\\n');\n result.renamedField = true;\n }\n }\n\n // --- Resolve the current projects dir from whatever the frontmatter says. ---\n const projectLineRe = /^\\s*defaultProjectDir\\s*:\\s*(.*)$/m;\n const projectLineMatch = newFmBlock.match(projectLineRe);\n const projectsDirRaw = projectLineMatch\n ? projectLineMatch[1].trim().replace(/^['\"]|['\"]$/g, '')\n : missionValue;\n\n const expand = (p: string): string =>\n p.startsWith('~')\n ? resolve(process.env.HOME ?? '/', p.slice(p.startsWith('~/') ? 2 : 1))\n : p;\n\n let resolvedProjectsDir = projectsDirRaw ? expand(projectsDirRaw) : null;\n\n // --- Directory rename (only if the value still points at a /missions dir). ---\n if (resolvedProjectsDir && resolvedProjectsDir.endsWith('/missions')) {\n const siblingProjectsDir = resolvedProjectsDir.replace(/\\/missions$/, '/projects');\n if (\n (await fileExists(resolvedProjectsDir)) &&\n !(await fileExists(siblingProjectsDir))\n ) {\n try {\n await rename(resolvedProjectsDir, siblingProjectsDir);\n // Update the config line to point at the new dir. Preserve any ~ prefix.\n const newValue = projectsDirRaw!.endsWith('/missions')\n ? projectsDirRaw!.replace(/\\/missions$/, '/projects')\n : siblingProjectsDir;\n newFmBlock = newFmBlock.replace(\n projectLineRe,\n `defaultProjectDir: ${newValue}`,\n );\n resolvedProjectsDir = siblingProjectsDir;\n result.renamedDir = true;\n } catch {\n // If rename fails (permissions, cross-device), leave both config and\n // filesystem alone. Scanner will still hit the legacy dir.\n }\n }\n }\n\n result.resolvedProjectsDir = resolvedProjectsDir;\n\n if (result.renamedField || result.renamedDir) {\n const newContent = `---\\n${newFmBlock.replace(/\\n+$/, '')}\\n---\\n${afterFm.startsWith('\\n') ? afterFm.slice(1) : afterFm}`;\n try {\n await writeFile(configPath, newContent, 'utf-8');\n } catch {\n // If we can't persist the config, revert the flags so the caller\n // doesn't report a fake success.\n result.renamedField = false;\n result.renamedDir = false;\n }\n }\n\n return result;\n}\n\n/**\n * Format a concise summary line for startup logs. Empty string when nothing\n * material happened (caller should skip the log).\n */\nexport function summarizeMigration(\n project: ProjectFilesMigrationResult,\n config?: ConfigMigrationResult,\n): string {\n const parts: string[] = [];\n if (project.renamedProjectFiles.length > 0) {\n const firstThree = project.renamedProjectFiles\n .map((p) => p.split('/')[0])\n .slice(0, 3)\n .join(', ');\n const more =\n project.renamedProjectFiles.length > 3\n ? ` and ${project.renamedProjectFiles.length - 3} more`\n : '';\n parts.push(\n `renamed mission.md → project.md in ${project.renamedProjectFiles.length} project${project.renamedProjectFiles.length === 1 ? '' : 's'} (${firstThree}${more})`,\n );\n }\n if (config?.renamedField) parts.push('updated config defaultMissionDir → defaultProjectDir');\n if (config?.renamedDir) parts.push('renamed projects directory on disk');\n if (project.legacyExtras.length > 0) {\n parts.push(\n `${project.legacyExtras.length} legacy agent.md / claude.md file${project.legacyExtras.length === 1 ? '' : 's'} left in place (no longer read)`,\n );\n }\n return parts.length ? `[syntaur] legacy migration: ${parts.join('; ')}` : '';\n}\n","// Shared hotkey catalog: bindable action kinds, reserved combos, and the\n// canonical combo string format. Imported directly by the Express server\n// (src/dashboard/server.ts) and by the dashboard via the\n// `@shared/hotkeys-catalog` alias defined in dashboard/tsconfig.json +\n// dashboard/vite.config.ts.\n\nexport type BindableActionKind =\n | 'new-workspace'\n | 'new-project'\n | 'new-todo'\n | 'new-assignment';\n\nexport const BINDABLE_ACTION_KINDS: readonly BindableActionKind[] = [\n 'new-workspace',\n 'new-project',\n 'new-todo',\n 'new-assignment',\n];\n\nexport function isBindableActionKind(value: unknown): value is BindableActionKind {\n return (\n typeof value === 'string' &&\n (BINDABLE_ACTION_KINDS as readonly string[]).includes(value)\n );\n}\n\n// Reserved combos that user-bound hotkeys may NOT shadow. Hand-maintained;\n// scripts/check-hotkey-catalog.ts greps `useHotkey({` across the dashboard and\n// fails if it sees a `keys` value that is not represented here.\n//\n// Combos are stored in canonical form (see canonicalizeCombo). The list\n// includes:\n// - global UI combos (Mod+k, Mod+Shift+k, ?, Escape, Enter, Shift+t)\n// - g <suffix> chord prefixes (the lone \"g\" is reserved as a chord starter)\n// - list-scope letters\n// - page-scoped shortcuts that exist when those pages are mounted\nexport const BUILTIN_RESERVED_COMBOS: readonly string[] = [\n 'mod+k',\n 'mod+shift+k',\n '?',\n 'escape',\n 'enter',\n 'shift+t',\n // g-chord starter + suffixes\n 'g',\n 'g o',\n 'g m',\n 'g a',\n 'g t',\n 'g s',\n 'g !',\n 'g ,',\n // list-scope navigation\n 'j',\n 'k',\n 'o',\n // ProjectDetail page\n 'a',\n 'e',\n // AssignmentsPage board\n '/',\n 'r',\n // AssignmentDetail page\n 'p',\n 'h',\n 'd',\n 's',\n '[',\n ']',\n];\n\nconst MODIFIER_ORDER: readonly string[] = ['mod', 'ctrl', 'alt', 'shift'];\n\n/**\n * Canonicalize a combo string for storage and comparison.\n *\n * - Trims whitespace.\n * - Splits on `+` for single-key combos; preserves space-separated chord form\n * (e.g. `g a`) by canonicalizing each part independently.\n * - Lowercases everything (modifiers and the trailing key alike).\n * - Reorders modifiers into canonical order: mod, ctrl, alt, shift.\n *\n * Examples:\n * canonicalizeCombo(\"Shift+Mod+K\") -> \"mod+shift+k\"\n * canonicalizeCombo(\" cmd + Enter\") -> \"mod+enter\" (after caller maps cmd->mod)\n * canonicalizeCombo(\"g A\") -> \"g a\"\n * canonicalizeCombo(\"?\") -> \"?\"\n */\nexport function canonicalizeCombo(input: string): string {\n if (typeof input !== 'string') return '';\n const trimmed = input.trim();\n if (!trimmed) return '';\n\n // Chord form: space-separated, no `+` separators (e.g. \"g a\"). When the\n // input contains `+` it's treated as a single combo even if it has stray\n // whitespace around the separators (e.g. \"Mod + K\").\n if (/\\s/.test(trimmed) && !trimmed.includes('+')) {\n return trimmed\n .split(/\\s+/)\n .map(canonicalizeCombo)\n .filter((part) => part.length > 0)\n .join(' ');\n }\n\n const parts = trimmed.split('+').map((p) => p.trim()).filter((p) => p.length > 0);\n if (parts.length === 0) return '';\n if (parts.length === 1) {\n return parts[0].toLowerCase();\n }\n\n const key = parts[parts.length - 1].toLowerCase();\n const mods = parts.slice(0, -1).map((m) => m.toLowerCase());\n\n const seen = new Set<string>();\n const ordered: string[] = [];\n for (const m of MODIFIER_ORDER) {\n if (mods.includes(m) && !seen.has(m)) {\n ordered.push(m);\n seen.add(m);\n }\n }\n // Append any non-standard modifiers at the end (preserves user intent for\n // anything we don't recognize).\n for (const m of mods) {\n if (!seen.has(m)) {\n ordered.push(m);\n seen.add(m);\n }\n }\n\n return [...ordered, key].join('+');\n}\n\n/**\n * Returns true when `combo` (canonicalized) collides with a built-in reserved\n * combo. Server-side enforcement entry point.\n */\nexport function isReservedCombo(combo: string): boolean {\n const c = canonicalizeCombo(combo);\n if (!c) return false;\n return (BUILTIN_RESERVED_COMBOS as readonly string[]).includes(c);\n}\n\n/**\n * Default hotkey bindings shipped with the dashboard. The triple-modifier\n * `Mod+Shift+Alt+<letter>` namespace is intentionally chosen to avoid common\n * browser shortcuts (Cmd+Shift+T reopens closed tab, Cmd+Shift+P opens\n * private mode, Cmd+Shift+W closes window, etc.) while keeping the action\n * mnemonic. Users can override any of these from Settings → Hotkey Bindings.\n *\n * These are EFFECTIVE only when the user has not bound a custom combo for\n * that action — `effectiveBindings()` overlays the user's custom bindings on\n * top, so a custom binding always wins.\n */\nexport const DEFAULT_BINDABLE_HOTKEYS: Readonly<Record<BindableActionKind, string>> = {\n 'new-workspace': canonicalizeCombo('Mod+Shift+Alt+w'),\n 'new-project': canonicalizeCombo('Mod+Shift+Alt+p'),\n 'new-todo': canonicalizeCombo('Mod+Shift+Alt+t'),\n 'new-assignment': canonicalizeCombo('Mod+Shift+Alt+a'),\n};\n\n/**\n * Returns the effective binding map: defaults underneath, user customs on top.\n * A user-bound combo always wins; if the user has no entry for a kind, the\n * default is returned (if any).\n */\nexport function effectiveBindings(\n custom: Partial<Record<BindableActionKind, string>>,\n): Partial<Record<BindableActionKind, string>> {\n const out: Partial<Record<BindableActionKind, string>> = {\n ...DEFAULT_BINDABLE_HOTKEYS,\n };\n for (const kind of BINDABLE_ACTION_KINDS) {\n const override = custom[kind];\n if (typeof override === 'string' && override.length > 0) {\n out[kind] = override;\n }\n }\n return out;\n}\n\n/** True when the given kind currently uses its default combo (no user override). */\nexport function isDefaultBinding(\n custom: Partial<Record<BindableActionKind, string>>,\n kind: BindableActionKind,\n): boolean {\n const override = custom[kind];\n return typeof override !== 'string' || override.length === 0;\n}\n","export type PromptArgPosition = 'first' | 'last' | 'none';\n\n/**\n * Per-agent argv recipe for continuing a recorded session in a specific mode.\n *\n * `args` is a literal argv list with the substring `{id}` substituted for the\n * agent's session id at launch time. `command` overrides the agent's main\n * `command` field — used by subcommand-style agents (e.g. `codex resume <id>`\n * is documented as command=codex, args=['resume','{id}']; the override exists\n * for future agents whose subcommand binary differs).\n */\nexport interface SessionInvocation {\n command?: string;\n args: string[];\n}\n\nexport interface AgentConfig {\n id: string;\n label: string;\n command: string;\n args?: string[];\n promptArgPosition?: PromptArgPosition;\n default?: boolean;\n resolveFromShellAliases?: boolean;\n resume?: SessionInvocation;\n fork?: SessionInvocation;\n}\n\nexport const BUILTIN_AGENTS: AgentConfig[] = [\n {\n id: 'claude',\n label: 'Claude',\n command: 'claude',\n default: true,\n resume: { args: ['--resume', '{id}'] },\n fork: { args: ['--resume', '{id}', '--fork-session'] },\n },\n {\n id: 'codex',\n label: 'Codex',\n command: 'codex',\n resume: { args: ['resume', '{id}'] },\n fork: { args: ['fork', '{id}'] },\n },\n];\n\nexport const AGENT_ID_PATTERN = /^[a-z0-9][a-z0-9_-]*$/;\nexport const PROMPT_ARG_POSITIONS: readonly PromptArgPosition[] = ['first', 'last', 'none'];\n","import { readFile } from 'node:fs/promises';\nimport { resolve, isAbsolute } from 'node:path';\nimport { syntaurRoot, defaultProjectDir, expandHome } from './paths.js';\nimport { fileExists, writeFileForce } from './fs.js';\nimport { renderConfig } from '../templates/config.js';\nimport { migrateLegacyConfig } from './fs-migration.js';\nimport {\n BINDABLE_ACTION_KINDS,\n canonicalizeCombo,\n isBindableActionKind,\n isReservedCombo,\n type BindableActionKind,\n} from './hotkeysCatalog.js';\nimport {\n AGENT_ID_PATTERN,\n BUILTIN_AGENTS,\n PROMPT_ARG_POSITIONS,\n type AgentConfig,\n type PromptArgPosition,\n type SessionInvocation,\n} from './agents-schema.js';\n\nexport {\n AGENT_ID_PATTERN,\n BUILTIN_AGENTS,\n PROMPT_ARG_POSITIONS,\n type AgentConfig,\n type PromptArgPosition,\n type SessionInvocation,\n};\n\nexport interface StatusDefinition {\n id: string;\n label: string;\n description?: string;\n color?: string;\n icon?: string;\n terminal?: boolean;\n}\n\nexport interface StatusTransition {\n from: string;\n command: string;\n to: string;\n label?: string;\n description?: string;\n requiresReason?: boolean;\n}\n\nexport interface StatusConfig {\n statuses: StatusDefinition[];\n order: string[];\n transitions: StatusTransition[];\n}\n\nexport interface TypeDefinition {\n id: string;\n label?: string;\n description?: string;\n color?: string;\n icon?: string;\n}\n\nexport interface TypesConfig {\n definitions: TypeDefinition[];\n default: string;\n}\n\nexport const DEFAULT_ASSIGNMENT_TYPES: TypesConfig = {\n definitions: [\n { id: 'feature', label: 'Feature' },\n { id: 'bug', label: 'Bug' },\n { id: 'refactor', label: 'Refactor' },\n { id: 'research', label: 'Research' },\n { id: 'chore', label: 'Chore' },\n ],\n default: 'feature',\n};\n\nexport interface IntegrationConfig {\n claudePluginDir: string | null;\n codexPluginDir: string | null;\n codexMarketplacePath: string | null;\n}\n\nexport interface OnboardingConfig {\n completed: boolean;\n}\n\nexport interface BackupConfig {\n repo: string | null;\n categories: string;\n lastBackup: string | null;\n lastRestore: string | null;\n}\n\nexport type AutoCreateWorktree = 'skip' | 'ask' | 'always';\n\nexport interface PlaybooksConfig {\n disabled: string[];\n}\n\nexport interface ThemeConfig {\n preset: string;\n}\n\nexport interface HotkeyBindingsConfig {\n bindings: Partial<Record<BindableActionKind, string>>;\n}\n\nexport type TerminalChoice =\n | 'terminal-app'\n | 'iterm'\n | 'ghostty'\n | 'alacritty'\n | 'warp'\n | 'kitty';\n\nexport const TERMINAL_CHOICES: readonly TerminalChoice[] = [\n 'terminal-app',\n 'iterm',\n 'ghostty',\n 'alacritty',\n 'warp',\n 'kitty',\n];\n\nexport interface SyntaurConfig {\n version: string;\n defaultProjectDir: string;\n onboarding: OnboardingConfig;\n agentDefaults: {\n trustLevel: 'low' | 'medium' | 'high';\n autoApprove: boolean;\n autoCreateWorktree: AutoCreateWorktree;\n };\n integrations: IntegrationConfig;\n backup: BackupConfig | null;\n statuses: StatusConfig | null;\n types: TypesConfig | null;\n agents: AgentConfig[] | null;\n playbooks: PlaybooksConfig;\n theme: ThemeConfig | null;\n hotkeys: HotkeyBindingsConfig | null;\n terminal: TerminalChoice | null;\n}\n\nconst DEFAULT_CONFIG: SyntaurConfig = {\n version: '2.0',\n defaultProjectDir: defaultProjectDir(),\n onboarding: {\n completed: false,\n },\n agentDefaults: {\n trustLevel: 'medium',\n autoApprove: false,\n autoCreateWorktree: 'ask',\n },\n integrations: {\n claudePluginDir: null,\n codexPluginDir: null,\n codexMarketplacePath: null,\n },\n backup: null,\n statuses: null,\n types: null,\n agents: null,\n playbooks: {\n disabled: [],\n },\n theme: null,\n hotkeys: null,\n terminal: null,\n};\n\nconst AUTO_CREATE_WORKTREE_VALUES: readonly AutoCreateWorktree[] = ['skip', 'ask', 'always'];\n\nexport class AgentConfigError extends Error {}\n\n/**\n * Validate an agent command string.\n * - Absolute paths (after ~ expansion) are accepted verbatim.\n * - Bare names (no \"/\" after expansion) are accepted for PATH lookup at launch time.\n * - Relative paths (contain \"/\" but not absolute) are rejected.\n */\nexport function parseAgentCommand(value: string, agentId?: string): string {\n if (typeof value !== 'string' || value.trim() === '') {\n throw new AgentConfigError(\n `agent${agentId ? ` \"${agentId}\"` : ''} has empty command`,\n );\n }\n const expanded = expandHome(value.trim());\n if (isAbsolute(expanded)) {\n return resolve(expanded);\n }\n if (expanded.includes('/')) {\n throw new AgentConfigError(\n `agent${agentId ? ` \"${agentId}\"` : ''} command \"${value}\" is a relative path — use an absolute path or a bare binary name`,\n );\n }\n return expanded;\n}\n\nexport function validateAgentList(agents: AgentConfig[]): void {\n const seen = new Set<string>();\n let defaults = 0;\n for (const agent of agents) {\n if (!AGENT_ID_PATTERN.test(agent.id)) {\n throw new AgentConfigError(\n `agent id \"${agent.id}\" is invalid — must match /^[a-z0-9][a-z0-9_-]*$/`,\n );\n }\n if (seen.has(agent.id)) {\n throw new AgentConfigError(`duplicate agent id \"${agent.id}\"`);\n }\n seen.add(agent.id);\n if (!agent.label || agent.label.trim() === '') {\n throw new AgentConfigError(`agent \"${agent.id}\" has empty label`);\n }\n parseAgentCommand(agent.command, agent.id);\n if (\n agent.promptArgPosition !== undefined &&\n !PROMPT_ARG_POSITIONS.includes(agent.promptArgPosition)\n ) {\n throw new AgentConfigError(\n `agent \"${agent.id}\" has invalid promptArgPosition \"${agent.promptArgPosition}\" — expected first|last|none`,\n );\n }\n validateSessionInvocation(agent, 'resume', agent.resume);\n validateSessionInvocation(agent, 'fork', agent.fork);\n if (agent.default) defaults++;\n }\n if (defaults > 1) {\n throw new AgentConfigError(\n `more than one agent is marked default: true (only one is allowed)`,\n );\n }\n}\n\nfunction validateSessionInvocation(\n agent: AgentConfig,\n mode: 'resume' | 'fork',\n invocation: SessionInvocation | undefined,\n): void {\n if (invocation === undefined) return;\n if (!Array.isArray(invocation.args)) {\n throw new AgentConfigError(\n `agent \"${agent.id}\" ${mode}.args must be an array of strings`,\n );\n }\n for (const a of invocation.args) {\n if (typeof a !== 'string') {\n throw new AgentConfigError(\n `agent \"${agent.id}\" ${mode}.args must contain only strings`,\n );\n }\n }\n if (\n invocation.command !== undefined &&\n (typeof invocation.command !== 'string' || invocation.command.trim() === '')\n ) {\n throw new AgentConfigError(\n `agent \"${agent.id}\" ${mode}.command must be a non-empty string when present`,\n );\n }\n}\n\nfunction cloneDefaultConfig(): SyntaurConfig {\n return {\n ...DEFAULT_CONFIG,\n onboarding: { ...DEFAULT_CONFIG.onboarding },\n agentDefaults: { ...DEFAULT_CONFIG.agentDefaults },\n integrations: { ...DEFAULT_CONFIG.integrations },\n backup: DEFAULT_CONFIG.backup ? { ...DEFAULT_CONFIG.backup } : null,\n statuses: DEFAULT_CONFIG.statuses\n ? {\n statuses: DEFAULT_CONFIG.statuses.statuses.map((s) => ({ ...s })),\n order: [...DEFAULT_CONFIG.statuses.order],\n transitions: DEFAULT_CONFIG.statuses.transitions.map((t) => ({ ...t })),\n }\n : null,\n types: DEFAULT_CONFIG.types\n ? {\n definitions: DEFAULT_CONFIG.types.definitions.map((d) => ({ ...d })),\n default: DEFAULT_CONFIG.types.default,\n }\n : null,\n agents: DEFAULT_CONFIG.agents\n ? DEFAULT_CONFIG.agents.map((a) => ({\n ...a,\n ...(a.args ? { args: [...a.args] } : {}),\n ...(a.resume ? { resume: { ...a.resume, args: [...a.resume.args] } } : {}),\n ...(a.fork ? { fork: { ...a.fork, args: [...a.fork.args] } } : {}),\n }))\n : null,\n playbooks: {\n disabled: [...DEFAULT_CONFIG.playbooks.disabled],\n },\n theme: DEFAULT_CONFIG.theme ? { ...DEFAULT_CONFIG.theme } : null,\n hotkeys: DEFAULT_CONFIG.hotkeys\n ? { bindings: { ...DEFAULT_CONFIG.hotkeys.bindings } }\n : null,\n terminal: DEFAULT_CONFIG.terminal,\n };\n}\n\nfunction parseFrontmatter(content: string): Record<string, string> {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return {};\n const result: Record<string, string> = {};\n const lines = match[1].split('\\n');\n let currentParent: string | null = null;\n for (const line of lines) {\n if (line.trim() === '') continue;\n const indent = line.length - line.trimStart().length;\n const colonIndex = line.indexOf(':');\n if (colonIndex < 0) continue;\n const key = line.slice(0, colonIndex).trim();\n const value = line.slice(colonIndex + 1).trim();\n if (indent === 0) {\n if (value === '' || value === undefined) {\n currentParent = key;\n } else {\n currentParent = null;\n result[key] = value.replace(/^[\"']|[\"']$/g, '');\n }\n } else if (indent > 0 && currentParent) {\n result[`${currentParent}.${key}`] = value.replace(/^[\"']|[\"']$/g, '');\n }\n }\n return result;\n}\n\nfunction parseStatusConfig(content: string): StatusConfig | null {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return null;\n const fmBlock = match[1];\n\n // Check if there's a top-level statuses: section\n const statusesStart = fmBlock.match(/^statuses:\\s*$/m);\n if (!statusesStart) return null;\n\n // Extract the statuses block (everything indented after \"statuses:\")\n const startIdx = fmBlock.indexOf(statusesStart[0]) + statusesStart[0].length;\n const remaining = fmBlock.slice(startIdx);\n\n const statuses: StatusDefinition[] = [];\n const order: string[] = [];\n const transitions: StatusTransition[] = [];\n\n // Parse sub-sections: definitions, order, transitions\n let currentSection: 'definitions' | 'order' | 'transitions' | null = null;\n const lines = remaining.split('\\n');\n\n function parseListEntry(lineIdx: number, baseIndent: number): { entry: Record<string, string>; consumed: number } {\n const entry: Record<string, string> = {};\n const firstLine = lines[lineIdx].trimStart().slice(2).trim();\n const colonIdx = firstLine.indexOf(':');\n if (colonIdx > 0) {\n entry[firstLine.slice(0, colonIdx).trim()] = firstLine.slice(colonIdx + 1).trim();\n }\n let consumed = 1;\n for (let i = lineIdx + 1; i < lines.length; i++) {\n const next = lines[i];\n const nextTrimmed = next.trimStart();\n const nextIndent = next.length - nextTrimmed.length;\n if (nextIndent <= baseIndent || nextTrimmed.startsWith('- ')) break;\n const ci = nextTrimmed.indexOf(':');\n if (ci > 0) {\n entry[nextTrimmed.slice(0, ci).trim()] = nextTrimmed.slice(ci + 1).trim();\n }\n consumed++;\n }\n return { entry, consumed };\n }\n\n for (let lineIdx = 0; lineIdx < lines.length; lineIdx++) {\n const line = lines[lineIdx];\n const trimmed = line.trimStart();\n const indent = line.length - trimmed.length;\n\n // Top-level key under statuses (indent 2)\n if (indent === 2 && trimmed.endsWith(':')) {\n const key = trimmed.slice(0, -1).trim();\n if (key === 'definitions') currentSection = 'definitions';\n else if (key === 'order') currentSection = 'order';\n else if (key === 'transitions') currentSection = 'transitions';\n else currentSection = null;\n continue;\n }\n\n // Stop if we hit a new top-level key (no indent)\n if (indent === 0 && trimmed.includes(':')) break;\n\n if (currentSection === 'order' && indent >= 4 && trimmed.startsWith('- ')) {\n order.push(trimmed.slice(2).trim());\n continue;\n }\n\n if (currentSection === 'definitions' && indent >= 4 && trimmed.startsWith('- ')) {\n const { entry, consumed } = parseListEntry(lineIdx, indent);\n if (entry['id']) {\n statuses.push({\n id: entry['id'],\n label: entry['label'] ?? entry['id'],\n description: entry['description'],\n color: entry['color'],\n icon: entry['icon'],\n terminal: entry['terminal'] === 'true',\n });\n }\n lineIdx += consumed - 1; // skip consumed continuation lines\n continue;\n }\n\n if (currentSection === 'transitions' && indent >= 4 && trimmed.startsWith('- ')) {\n const { entry, consumed } = parseListEntry(lineIdx, indent);\n if (entry['from'] && entry['command'] && entry['to']) {\n transitions.push({\n from: entry['from'],\n command: entry['command'],\n to: entry['to'],\n label: entry['label'],\n description: entry['description'],\n requiresReason: entry['requiresReason'] === 'true',\n });\n }\n lineIdx += consumed - 1;\n continue;\n }\n }\n\n if (statuses.length === 0) return null;\n\n return {\n statuses,\n order: order.length > 0 ? order : statuses.map((s) => s.id),\n transitions,\n };\n}\n\nfunction serializeStatusConfig(statuses: StatusConfig): string {\n const lines: string[] = [];\n lines.push('statuses:');\n\n // definitions\n lines.push(' definitions:');\n for (const s of statuses.statuses) {\n lines.push(` - id: ${s.id}`);\n lines.push(` label: ${s.label}`);\n if (s.description) lines.push(` description: ${s.description}`);\n if (s.color) lines.push(` color: ${s.color}`);\n if (s.icon) lines.push(` icon: ${s.icon}`);\n if (s.terminal) lines.push(` terminal: true`);\n }\n\n // order\n lines.push(' order:');\n for (const id of statuses.order) {\n lines.push(` - ${id}`);\n }\n\n // transitions\n if (statuses.transitions.length > 0) {\n lines.push(' transitions:');\n for (const t of statuses.transitions) {\n lines.push(` - from: ${t.from}`);\n lines.push(` command: ${t.command}`);\n lines.push(` to: ${t.to}`);\n if (t.label) lines.push(` label: ${t.label}`);\n if (t.description) lines.push(` description: ${t.description}`);\n if (t.requiresReason) lines.push(` requiresReason: true`);\n }\n }\n\n return lines.join('\\n');\n}\n\nfunction serializeIntegrationConfig(integrations: IntegrationConfig): string | null {\n const lines: string[] = [];\n\n if (integrations.claudePluginDir) {\n lines.push(` claudePluginDir: ${integrations.claudePluginDir}`);\n }\n if (integrations.codexPluginDir) {\n lines.push(` codexPluginDir: ${integrations.codexPluginDir}`);\n }\n if (integrations.codexMarketplacePath) {\n lines.push(` codexMarketplacePath: ${integrations.codexMarketplacePath}`);\n }\n\n if (lines.length === 0) {\n return null;\n }\n\n return ['integrations:', ...lines].join('\\n');\n}\n\nfunction serializeOnboardingConfig(onboarding: OnboardingConfig): string {\n return ['onboarding:', ` completed: ${onboarding.completed ? 'true' : 'false'}`].join('\\n');\n}\n\nfunction serializeBackupConfig(backup: BackupConfig): string {\n const lines: string[] = ['backup:'];\n lines.push(` repo: ${backup.repo ?? 'null'}`);\n lines.push(` categories: ${backup.categories}`);\n lines.push(` lastBackup: ${backup.lastBackup ?? 'null'}`);\n lines.push(` lastRestore: ${backup.lastRestore ?? 'null'}`);\n return lines.join('\\n');\n}\n\nfunction serializePlaybooksConfig(playbooks: PlaybooksConfig): string | null {\n if (!playbooks.disabled || playbooks.disabled.length === 0) {\n return null;\n }\n const lines: string[] = ['playbooks:', ' disabled:'];\n for (const slug of playbooks.disabled) {\n lines.push(` - ${slug}`);\n }\n return lines.join('\\n');\n}\n\nfunction parsePlaybooksConfig(fmBlock: string): PlaybooksConfig {\n const blockStart = fmBlock.match(/^playbooks:\\s*$/m);\n if (!blockStart) {\n return { disabled: [] };\n }\n\n const startIdx = fmBlock.indexOf(blockStart[0]) + blockStart[0].length;\n const remaining = fmBlock.slice(startIdx).split('\\n');\n\n const disabled: string[] = [];\n let currentSection: 'disabled' | null = null;\n\n for (const line of remaining) {\n const trimmed = line.trimStart();\n const indent = line.length - trimmed.length;\n\n // End of playbooks block — next top-level key\n if (indent === 0 && trimmed.length > 0) break;\n\n if (trimmed === '') continue;\n\n if (indent === 2 && trimmed.startsWith('disabled:')) {\n currentSection = 'disabled';\n // Support inline form `disabled: []` — treat as empty list.\n const afterColon = trimmed.slice('disabled:'.length).trim();\n if (afterColon === '[]' || afterColon === '') {\n continue;\n }\n // Any other inline value is malformed; skip.\n continue;\n }\n\n if (currentSection === 'disabled' && indent >= 4 && trimmed.startsWith('- ')) {\n const raw = trimmed.slice(2).trim().replace(/^[\"']|[\"']$/g, '');\n if (raw.length === 0) continue;\n // Defer slug-format validation to callers via isValidSlug where needed;\n // here we only filter obviously invalid whitespace-containing entries.\n if (/\\s/.test(raw)) {\n console.warn(`Warning: config.md playbooks.disabled entry \"${raw}\" contains whitespace, ignoring`);\n continue;\n }\n disabled.push(raw);\n continue;\n }\n }\n\n return { disabled };\n}\n\nexport async function updatePlaybooksConfig(\n playbooks: Partial<PlaybooksConfig>,\n): Promise<void> {\n const configPath = resolve(syntaurRoot(), 'config.md');\n const current = (await readConfig()).playbooks;\n const nextPlaybooks: PlaybooksConfig = {\n disabled: Array.from(new Set(playbooks.disabled ?? current.disabled)),\n };\n\n const playbooksBlock = serializePlaybooksConfig(nextPlaybooks);\n const existing = await fileExists(configPath)\n ? await readFile(configPath, 'utf-8')\n : renderConfig({ defaultProjectDir: defaultProjectDir() });\n\n const fmMatch = existing.match(/^(---\\n)([\\s\\S]*?)\\n(---)/);\n if (!fmMatch) {\n const bodyBlock = playbooksBlock ? `${playbooksBlock}\\n` : '';\n const content = `---\\nversion: \"2.0\"\\ndefaultProjectDir: ${defaultProjectDir()}\\n${bodyBlock}---\\n${existing}`;\n await writeFileForce(configPath, content);\n return;\n }\n\n const fmBlock = fmMatch[2];\n const afterFrontmatter = existing.slice(fmMatch[0].length);\n const cleanedFm = stripTopLevelBlock(fmBlock, 'playbooks');\n const newFm = playbooksBlock\n ? `${cleanedFm}\\n${playbooksBlock}`.replace(/^\\n+/, '')\n : cleanedFm;\n const normalizedFm = newFm.replace(/\\n+$/, '');\n const newContent = `---\\n${normalizedFm}\\n---${afterFrontmatter}`;\n await writeFileForce(configPath, newContent);\n}\n\nfunction parseThemeConfig(content: string): ThemeConfig | null {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return null;\n const fmBlock = match[1];\n\n const blockStart = fmBlock.match(/^theme:\\s*$/m);\n if (!blockStart) return null;\n\n const startIdx = fmBlock.indexOf(blockStart[0]) + blockStart[0].length;\n const remaining = fmBlock.slice(startIdx).split('\\n');\n\n let preset: string | null = null;\n for (const line of remaining) {\n const trimmed = line.trimStart();\n const indent = line.length - trimmed.length;\n if (indent === 0 && trimmed.length > 0) break;\n if (trimmed === '') continue;\n if (indent === 2 && trimmed.startsWith('preset:')) {\n const value = trimmed.slice('preset:'.length).trim().replace(/^[\"']|[\"']$/g, '');\n if (value.length > 0) preset = value;\n }\n }\n\n if (!preset) return null;\n return { preset };\n}\n\nfunction serializeThemeConfig(theme: ThemeConfig): string {\n return ['theme:', ` preset: ${theme.preset}`].join('\\n');\n}\n\nexport async function writeThemeConfig(theme: ThemeConfig): Promise<void> {\n const configPath = resolve(syntaurRoot(), 'config.md');\n const themeBlock = serializeThemeConfig(theme);\n\n const existing = await fileExists(configPath)\n ? await readFile(configPath, 'utf-8')\n : renderConfig({ defaultProjectDir: defaultProjectDir() });\n\n const fmMatch = existing.match(/^(---\\n)([\\s\\S]*?)\\n(---)/);\n if (!fmMatch) {\n const content = `---\\nversion: \"2.0\"\\ndefaultProjectDir: ${defaultProjectDir()}\\n${themeBlock}\\n---\\n${existing}`;\n await writeFileForce(configPath, content);\n return;\n }\n\n const fmBlock = fmMatch[2];\n const afterFrontmatter = existing.slice(fmMatch[0].length);\n const cleanedFm = stripTopLevelBlock(fmBlock, 'theme');\n const newFm = `${cleanedFm}\\n${themeBlock}`.replace(/^\\n+/, '');\n const normalizedFm = newFm.replace(/\\n+$/, '');\n const newContent = `---\\n${normalizedFm}\\n---${afterFrontmatter}`;\n await writeFileForce(configPath, newContent);\n}\n\nexport async function deleteThemeConfig(): Promise<void> {\n const configPath = resolve(syntaurRoot(), 'config.md');\n if (!(await fileExists(configPath))) return;\n\n const existing = await readFile(configPath, 'utf-8');\n const fmMatch = existing.match(/^(---\\n)([\\s\\S]*?)\\n(---)/);\n if (!fmMatch) return;\n\n const fmBlock = fmMatch[2];\n const afterFrontmatter = existing.slice(fmMatch[0].length);\n const cleanedFm = stripTopLevelBlock(fmBlock, 'theme');\n const newContent = `---\\n${cleanedFm}\\n---${afterFrontmatter}`;\n await writeFileForce(configPath, newContent);\n}\n\nfunction parseHotkeyBindingsConfig(content: string): HotkeyBindingsConfig | null {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return null;\n const fmBlock = match[1];\n\n const blockStart = fmBlock.match(/^hotkeys:\\s*$/m);\n if (!blockStart) return null;\n\n const startIdx = fmBlock.indexOf(blockStart[0]) + blockStart[0].length;\n const remaining = fmBlock.slice(startIdx).split('\\n');\n\n const bindings: Partial<Record<BindableActionKind, string>> = {};\n let inBindings = false;\n for (const line of remaining) {\n const trimmed = line.trimStart();\n const indent = line.length - trimmed.length;\n if (indent === 0 && trimmed.length > 0) break;\n if (trimmed === '') continue;\n if (indent === 2 && trimmed === 'bindings:') {\n inBindings = true;\n continue;\n }\n if (inBindings && indent === 4) {\n const colonIdx = trimmed.indexOf(':');\n if (colonIdx <= 0) continue;\n const rawKind = trimmed.slice(0, colonIdx).trim();\n const rawValue = trimmed\n .slice(colonIdx + 1)\n .trim()\n .replace(/^[\"']|[\"']$/g, '');\n if (!isBindableActionKind(rawKind)) continue;\n if (rawValue.length === 0) continue;\n bindings[rawKind] = canonicalizeCombo(rawValue);\n }\n }\n\n if (Object.keys(bindings).length === 0) return null;\n return { bindings };\n}\n\nfunction serializeHotkeyBindingsConfig(cfg: HotkeyBindingsConfig): string {\n const lines: string[] = ['hotkeys:', ' bindings:'];\n // Emit in the canonical kind order so on-disk diffs are stable.\n for (const kind of BINDABLE_ACTION_KINDS) {\n const value = cfg.bindings[kind];\n if (!value) continue;\n lines.push(` ${kind}: \"${canonicalizeCombo(value)}\"`);\n }\n // If no bindings remain, return an empty block (caller will treat as delete).\n if (lines.length === 2) return '';\n return lines.join('\\n');\n}\n\nexport async function writeHotkeyBindingsConfig(\n cfg: HotkeyBindingsConfig,\n): Promise<void> {\n // Validate + canonicalize + drop reserved-combo collisions before writing.\n const cleaned: Partial<Record<BindableActionKind, string>> = {};\n for (const kind of BINDABLE_ACTION_KINDS) {\n const raw = cfg.bindings[kind];\n if (typeof raw !== 'string' || raw.trim() === '') continue;\n const canonical = canonicalizeCombo(raw);\n if (!canonical) continue;\n if (isReservedCombo(canonical)) continue;\n cleaned[kind] = canonical;\n }\n\n if (Object.keys(cleaned).length === 0) {\n await deleteHotkeyBindingsConfig();\n return;\n }\n\n const configPath = resolve(syntaurRoot(), 'config.md');\n const block = serializeHotkeyBindingsConfig({ bindings: cleaned });\n\n const existing = (await fileExists(configPath))\n ? await readFile(configPath, 'utf-8')\n : renderConfig({ defaultProjectDir: defaultProjectDir() });\n\n const fmMatch = existing.match(/^(---\\n)([\\s\\S]*?)\\n(---)/);\n if (!fmMatch) {\n const content = `---\\nversion: \"2.0\"\\ndefaultProjectDir: ${defaultProjectDir()}\\n${block}\\n---\\n${existing}`;\n await writeFileForce(configPath, content);\n return;\n }\n\n const fmBlock = fmMatch[2];\n const afterFrontmatter = existing.slice(fmMatch[0].length);\n const cleanedFm = stripTopLevelBlock(fmBlock, 'hotkeys');\n const newFm = `${cleanedFm}\\n${block}`.replace(/^\\n+/, '');\n const normalizedFm = newFm.replace(/\\n+$/, '');\n const newContent = `---\\n${normalizedFm}\\n---${afterFrontmatter}`;\n await writeFileForce(configPath, newContent);\n}\n\nexport async function deleteHotkeyBindingsConfig(): Promise<void> {\n const configPath = resolve(syntaurRoot(), 'config.md');\n if (!(await fileExists(configPath))) return;\n\n const existing = await readFile(configPath, 'utf-8');\n const fmMatch = existing.match(/^(---\\n)([\\s\\S]*?)\\n(---)/);\n if (!fmMatch) return;\n\n const fmBlock = fmMatch[2];\n const afterFrontmatter = existing.slice(fmMatch[0].length);\n const cleanedFm = stripTopLevelBlock(fmBlock, 'hotkeys');\n const newContent = `---\\n${cleanedFm}\\n---${afterFrontmatter}`;\n await writeFileForce(configPath, newContent);\n}\n\nfunction stripTopLevelBlock(fmBlock: string, key: string): string {\n const blockStart = fmBlock.match(new RegExp(`^${key}:\\\\s*$`, 'm'));\n if (!blockStart) {\n return fmBlock.replace(/\\n+$/, '');\n }\n\n const startIdx = fmBlock.indexOf(blockStart[0]);\n const before = fmBlock.slice(0, startIdx);\n const after = fmBlock.slice(startIdx + blockStart[0].length);\n const remaining = after.split('\\n');\n let endIdx = 0;\n\n for (let i = 0; i < remaining.length; i++) {\n const line = remaining[i];\n if (line.trim() === '') {\n endIdx = i + 1;\n continue;\n }\n if (line.length > 0 && line[0] !== ' ') {\n break;\n }\n endIdx = i + 1;\n }\n\n return (before + remaining.slice(endIdx).join('\\n')).replace(/\\n+$/, '');\n}\n\nfunction parseOptionalAbsolutePath(\n value: string | undefined,\n fieldName: string,\n): string | null {\n if (!value) {\n return null;\n }\n\n const expanded = expandHome(String(value));\n if (!isAbsolute(expanded)) {\n console.warn(\n `Warning: config.md ${fieldName} is not an absolute path (\"${value}\"), ignoring it`,\n );\n return null;\n }\n\n return resolve(expanded);\n}\n\nfunction parseAgentsConfig(content: string): AgentConfig[] | null {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return null;\n const fmBlock = match[1];\n\n const agentsStart = fmBlock.match(/^agents:\\s*$/m);\n if (!agentsStart) return null;\n\n const startIdx = fmBlock.indexOf(agentsStart[0]) + agentsStart[0].length;\n const remaining = fmBlock.slice(startIdx);\n const lines = remaining.split('\\n');\n\n const agents: AgentConfig[] = [];\n let current: Partial<AgentConfig> & { args?: string[] } | null = null;\n let argsCapture: string[] | null = null;\n let argsBaseIndent = 0;\n // Active nested block state (e.g. `resume:` or `fork:` sub-mapping under an\n // agent). When `nestedKey` is one of `resume` / `fork`, lines at deeper\n // indent are parsed as that invocation's `command` / `args` fields. When\n // `nestedKey === '__skip__'` we swallow the indented block without\n // recording anything — this is the forward-compat path for unknown nested\n // keys added in future syntaur versions.\n let nestedKey: string | null = null;\n let nestedInvocation: SessionInvocation | null = null;\n let nestedBaseIndent = 0;\n\n function flushCurrent() {\n if (!current) return;\n if (!current.id || !current.command || !current.label) {\n current = null;\n return;\n }\n agents.push({\n id: current.id,\n label: current.label,\n command: current.command,\n ...(current.args && current.args.length > 0 ? { args: current.args } : {}),\n ...(current.promptArgPosition\n ? { promptArgPosition: current.promptArgPosition }\n : {}),\n ...(current.default ? { default: true } : {}),\n ...(current.resolveFromShellAliases ? { resolveFromShellAliases: true } : {}),\n ...(current.resume ? { resume: current.resume } : {}),\n ...(current.fork ? { fork: current.fork } : {}),\n });\n current = null;\n argsCapture = null;\n nestedKey = null;\n nestedInvocation = null;\n }\n\n function closeNestedBlock() {\n if (!nestedKey) return;\n if (current && (nestedKey === 'resume' || nestedKey === 'fork') && nestedInvocation) {\n // Only attach when args were populated — empty invocation is a no-op.\n if (Array.isArray(nestedInvocation.args)) {\n current[nestedKey] = nestedInvocation;\n }\n }\n nestedKey = null;\n nestedInvocation = null;\n argsCapture = null;\n }\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const trimmed = line.trimStart();\n const indent = line.length - trimmed.length;\n\n if (indent === 0 && trimmed !== '' && !trimmed.startsWith('#')) {\n closeNestedBlock();\n break; // new top-level key\n }\n\n // Continue capturing list items for the active argsCapture target.\n if (argsCapture) {\n if (indent > argsBaseIndent && trimmed.startsWith('- ')) {\n argsCapture.push(decodeYamlScalar(trimmed.slice(2).trim()));\n continue;\n } else {\n argsCapture = null;\n }\n }\n\n if (indent === 2 && trimmed.startsWith('- ')) {\n closeNestedBlock();\n flushCurrent();\n current = {};\n const rest = trimmed.slice(2).trim();\n const colonIdx = rest.indexOf(':');\n if (colonIdx > 0) {\n const k = rest.slice(0, colonIdx).trim();\n const v = rest.slice(colonIdx + 1).trim();\n assignAgentField(current, k, v);\n }\n continue;\n }\n\n if (!current) continue;\n\n // Inside a nested block (resume / fork / skip-unknown).\n if (nestedKey && indent > nestedBaseIndent) {\n const colonIdx = trimmed.indexOf(':');\n if (colonIdx <= 0) continue;\n const k = trimmed.slice(0, colonIdx).trim();\n const v = trimmed.slice(colonIdx + 1).trim();\n if (nestedKey === 'resume' || nestedKey === 'fork') {\n if (!nestedInvocation) nestedInvocation = { args: [] };\n if (k === 'args' && v === '') {\n nestedInvocation.args = [];\n argsCapture = nestedInvocation.args;\n argsBaseIndent = indent;\n continue;\n }\n if (k === 'command' && v !== '') {\n nestedInvocation.command = decodeYamlScalar(v);\n continue;\n }\n // Unknown nested-of-nested: ignore for forward compat.\n }\n // nestedKey === '__skip__' → swallow without recording.\n continue;\n }\n\n // Returning out to indent 4 (or shallower) — close any open nested block.\n if (nestedKey && indent <= nestedBaseIndent) {\n closeNestedBlock();\n }\n\n if (indent >= 4 && current) {\n const colonIdx = trimmed.indexOf(':');\n if (colonIdx <= 0) continue;\n const k = trimmed.slice(0, colonIdx).trim();\n const v = trimmed.slice(colonIdx + 1).trim();\n if (k === 'args' && v === '') {\n argsCapture = [];\n argsBaseIndent = indent;\n current.args = argsCapture;\n continue;\n }\n // Recognized nested mapping blocks: resume / fork. Empty value + no\n // recognized scalar field → enter nested mode.\n if ((k === 'resume' || k === 'fork') && v === '') {\n nestedKey = k;\n nestedInvocation = { args: [] };\n nestedBaseIndent = indent;\n continue;\n }\n // Unknown key with empty value at agent-field indent: forward-compat\n // skip. Older parsers would crash here once a future version emits\n // a new nested block; this branch lets us pass through gracefully.\n if (v === '' && !KNOWN_AGENT_SCALAR_FIELDS.has(k)) {\n nestedKey = '__skip__';\n nestedInvocation = null;\n nestedBaseIndent = indent;\n continue;\n }\n assignAgentField(current, k, v);\n }\n }\n closeNestedBlock();\n flushCurrent();\n\n if (agents.length === 0) return [];\n return agents;\n}\n\nconst KNOWN_AGENT_SCALAR_FIELDS: ReadonlySet<string> = new Set([\n 'id',\n 'label',\n 'command',\n 'promptArgPosition',\n 'default',\n 'resolveFromShellAliases',\n]);\n\n/**\n * Normalize and validate an agents list parsed from config.md. On any\n * AgentConfigError, log a warning and fall back to built-in defaults so a\n * malformed user config does not brick `syntaur browse`. Returns the\n * normalized list (with `command` resolved through `parseAgentCommand`).\n */\nfunction normalizeAgentsFromConfig(agents: AgentConfig[] | null): AgentConfig[] | null {\n if (agents === null) return null;\n try {\n const normalized = agents.map((agent) => ({\n ...agent,\n command: parseAgentCommand(agent.command, agent.id),\n }));\n validateAgentList(normalized);\n return normalized;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.warn(\n `Warning: ~/.syntaur/config.md agents block is invalid (${msg}) — using built-in defaults`,\n );\n return null;\n }\n}\n\n/**\n * Decode a YAML-ish scalar:\n * - Bare values returned verbatim.\n * - Single-quoted: strip outer quotes, unescape '' → '.\n * - Double-quoted: strip outer quotes, unescape \\\\ \\\" \\n \\t \\r.\n * Rejects unterminated quoted scalars (caller should surface as a parse error).\n */\nfunction decodeYamlScalar(value: string): string {\n const trimmed = value.trim();\n if (trimmed.length >= 2 && trimmed.startsWith('\"') && trimmed.endsWith('\"')) {\n const body = trimmed.slice(1, -1);\n let out = '';\n for (let i = 0; i < body.length; i++) {\n const ch = body[i];\n if (ch === '\\\\' && i + 1 < body.length) {\n const next = body[i + 1];\n switch (next) {\n case '\\\\': out += '\\\\'; break;\n case '\"': out += '\"'; break;\n case 'n': out += '\\n'; break;\n case 't': out += '\\t'; break;\n case 'r': out += '\\r'; break;\n default: out += next; break;\n }\n i++;\n continue;\n }\n out += ch;\n }\n return out;\n }\n if (trimmed.length >= 2 && trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\")) {\n return trimmed.slice(1, -1).replace(/''/g, \"'\");\n }\n return trimmed;\n}\n\nfunction assignAgentField(target: Partial<AgentConfig>, key: string, rawValue: string): void {\n const value = decodeYamlScalar(rawValue);\n switch (key) {\n case 'id':\n target.id = value;\n break;\n case 'label':\n target.label = value;\n break;\n case 'command':\n target.command = value;\n break;\n case 'promptArgPosition':\n target.promptArgPosition = value as PromptArgPosition;\n break;\n case 'default':\n target.default = value === 'true';\n break;\n case 'resolveFromShellAliases':\n target.resolveFromShellAliases = value === 'true';\n break;\n }\n}\n\nfunction yamlQuoteScalar(value: string): string {\n if (/[\\r\\n]/.test(value)) {\n throw new AgentConfigError(\n `value contains newlines, which the agents config serializer does not support: ${JSON.stringify(value)}`,\n );\n }\n if (value === '' || /[:#{}[\\],&*?|>!%@`\"'\\\\\\t]/.test(value) || /^\\s|\\s$/.test(value)) {\n const escaped = value\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\"/g, '\\\\\"')\n .replace(/\\t/g, '\\\\t');\n return `\"${escaped}\"`;\n }\n return value;\n}\n\nfunction serializeAgentsConfig(agents: AgentConfig[]): string {\n const lines: string[] = ['agents:'];\n for (const a of agents) {\n lines.push(` - id: ${yamlQuoteScalar(a.id)}`);\n lines.push(` label: ${yamlQuoteScalar(a.label)}`);\n lines.push(` command: ${yamlQuoteScalar(a.command)}`);\n if (a.args && a.args.length > 0) {\n lines.push(` args:`);\n for (const arg of a.args) {\n lines.push(` - ${yamlQuoteScalar(arg)}`);\n }\n }\n if (a.promptArgPosition && a.promptArgPosition !== 'first') {\n lines.push(` promptArgPosition: ${a.promptArgPosition}`);\n }\n if (a.default) {\n lines.push(` default: true`);\n }\n if (a.resolveFromShellAliases) {\n lines.push(` resolveFromShellAliases: true`);\n }\n if (a.resume) {\n appendSessionInvocation(lines, 'resume', a.resume);\n }\n if (a.fork) {\n appendSessionInvocation(lines, 'fork', a.fork);\n }\n }\n return lines.join('\\n');\n}\n\nfunction appendSessionInvocation(\n lines: string[],\n key: 'resume' | 'fork',\n invocation: SessionInvocation,\n): void {\n lines.push(` ${key}:`);\n if (invocation.command !== undefined) {\n lines.push(` command: ${yamlQuoteScalar(invocation.command)}`);\n }\n lines.push(` args:`);\n for (const arg of invocation.args) {\n lines.push(` - ${yamlQuoteScalar(arg)}`);\n }\n}\n\nexport async function writeAgentsConfig(agents: AgentConfig[]): Promise<void> {\n validateAgentList(agents);\n const configPath = resolve(syntaurRoot(), 'config.md');\n const agentsBlock = serializeAgentsConfig(agents);\n\n const existing = (await fileExists(configPath))\n ? await readFile(configPath, 'utf-8')\n : renderConfig({ defaultProjectDir: defaultProjectDir() });\n\n const fmMatch = existing.match(/^(---\\n)([\\s\\S]*?)\\n(---)/);\n if (!fmMatch) {\n const content = `---\\nversion: \"2.0\"\\ndefaultProjectDir: ${defaultProjectDir()}\\n${agentsBlock}\\n---\\n${existing}`;\n await writeFileForce(configPath, content.replace(/\\n\\n---/, '\\n---'));\n return;\n }\n\n const fmBlock = fmMatch[2];\n const afterFrontmatter = existing.slice(fmMatch[0].length);\n const cleanedFm = stripTopLevelBlock(fmBlock, 'agents');\n const newFm = `${cleanedFm}\\n${agentsBlock}`.replace(/^\\n+/, '').replace(/\\n+$/, '');\n const newContent = `---\\n${newFm}\\n---${afterFrontmatter}`;\n await writeFileForce(configPath, newContent);\n}\n\nexport async function deleteAgentsConfig(): Promise<void> {\n const configPath = resolve(syntaurRoot(), 'config.md');\n if (!(await fileExists(configPath))) return;\n\n const existing = await readFile(configPath, 'utf-8');\n const fmMatch = existing.match(/^(---\\n)([\\s\\S]*?)\\n(---)/);\n if (!fmMatch) return;\n\n const fmBlock = fmMatch[2];\n const afterFrontmatter = existing.slice(fmMatch[0].length);\n const cleanedFm = stripTopLevelBlock(fmBlock, 'agents');\n const newContent = `---\\n${cleanedFm}\\n---${afterFrontmatter}`;\n await writeFileForce(configPath, newContent);\n}\n\nexport async function writeStatusConfig(statuses: StatusConfig): Promise<void> {\n const configPath = resolve(syntaurRoot(), 'config.md');\n const statusBlock = serializeStatusConfig(statuses);\n\n if (!(await fileExists(configPath))) {\n // Create new config file with defaults + statuses\n const content = `---\\nversion: \"2.0\"\\ndefaultProjectDir: ~/projects\\n${statusBlock}\\n---\\n`;\n await writeFileForce(configPath, content);\n return;\n }\n\n const existing = await readFile(configPath, 'utf-8');\n const fmMatch = existing.match(/^(---\\n)([\\s\\S]*?)\\n(---)/);\n if (!fmMatch) {\n // No frontmatter — wrap in new frontmatter\n const content = `---\\nversion: \"2.0\"\\n${statusBlock}\\n---\\n${existing}`;\n await writeFileForce(configPath, content);\n return;\n }\n\n const fmBlock = fmMatch[2];\n const afterFrontmatter = existing.slice(fmMatch[0].length);\n\n // Remove existing statuses: block from frontmatter\n const statusesStart = fmBlock.match(/^statuses:\\s*$/m);\n let cleanedFm: string;\n if (statusesStart) {\n const startIdx = fmBlock.indexOf(statusesStart[0]);\n const before = fmBlock.slice(0, startIdx);\n const after = fmBlock.slice(startIdx + statusesStart[0].length);\n // Skip all indented lines (belonging to statuses block)\n const remaining = after.split('\\n');\n let endIdx = 0;\n for (let i = 0; i < remaining.length; i++) {\n const line = remaining[i];\n if (line.trim() === '') { endIdx = i + 1; continue; }\n if (line.length > 0 && line[0] !== ' ') break;\n endIdx = i + 1;\n }\n cleanedFm = before + remaining.slice(endIdx).join('\\n');\n } else {\n cleanedFm = fmBlock;\n }\n\n // Trim trailing whitespace/newlines from cleaned frontmatter\n cleanedFm = cleanedFm.replace(/\\n+$/, '');\n\n const newContent = `---\\n${cleanedFm}\\n${statusBlock}\\n---${afterFrontmatter}`;\n await writeFileForce(configPath, newContent);\n}\n\nexport async function deleteStatusConfig(): Promise<void> {\n const configPath = resolve(syntaurRoot(), 'config.md');\n if (!(await fileExists(configPath))) return;\n\n const existing = await readFile(configPath, 'utf-8');\n const fmMatch = existing.match(/^(---\\n)([\\s\\S]*?)\\n(---)/);\n if (!fmMatch) return;\n\n const fmBlock = fmMatch[2];\n const afterFrontmatter = existing.slice(fmMatch[0].length);\n const cleanedFm = stripTopLevelBlock(fmBlock, 'statuses');\n\n const newContent = `---\\n${cleanedFm}\\n---${afterFrontmatter}`;\n await writeFileForce(configPath, newContent);\n}\n\nexport async function updateIntegrationConfig(\n integrations: Partial<IntegrationConfig>,\n): Promise<void> {\n const configPath = resolve(syntaurRoot(), 'config.md');\n const nextIntegrations: IntegrationConfig = {\n ...(await readConfig()).integrations,\n ...integrations,\n };\n\n const integrationBlock = serializeIntegrationConfig(nextIntegrations);\n const existing = await fileExists(configPath)\n ? await readFile(configPath, 'utf-8')\n : renderConfig({ defaultProjectDir: defaultProjectDir() });\n\n const fmMatch = existing.match(/^(---\\n)([\\s\\S]*?)\\n(---)/);\n if (!fmMatch) {\n const content = `---\\nversion: \"2.0\"\\ndefaultProjectDir: ${defaultProjectDir()}\\n${integrationBlock ?? ''}\\n---\\n${existing}`;\n await writeFileForce(configPath, content.replace(/\\n\\n---/, '\\n---'));\n return;\n }\n\n const fmBlock = fmMatch[2];\n const afterFrontmatter = existing.slice(fmMatch[0].length);\n const cleanedFm = stripTopLevelBlock(fmBlock, 'integrations');\n const newFm = integrationBlock\n ? `${cleanedFm}\\n${integrationBlock}`.replace(/^\\n+/, '')\n : cleanedFm;\n const normalizedFm = newFm.replace(/\\n+$/, '');\n const newContent = `---\\n${normalizedFm}\\n---${afterFrontmatter}`;\n await writeFileForce(configPath, newContent);\n}\n\nexport async function updateOnboardingConfig(\n onboarding: Partial<OnboardingConfig>,\n): Promise<void> {\n const configPath = resolve(syntaurRoot(), 'config.md');\n const nextOnboarding: OnboardingConfig = {\n ...(await readConfig()).onboarding,\n ...onboarding,\n };\n\n const onboardingBlock = serializeOnboardingConfig(nextOnboarding);\n const existing = await fileExists(configPath)\n ? await readFile(configPath, 'utf-8')\n : renderConfig({ defaultProjectDir: defaultProjectDir() });\n\n const fmMatch = existing.match(/^(---\\n)([\\s\\S]*?)\\n(---)/);\n if (!fmMatch) {\n const content = `---\\nversion: \"2.0\"\\ndefaultProjectDir: ${defaultProjectDir()}\\n${onboardingBlock}\\n---\\n${existing}`;\n await writeFileForce(configPath, content.replace(/\\n\\n---/, '\\n---'));\n return;\n }\n\n const fmBlock = fmMatch[2];\n const afterFrontmatter = existing.slice(fmMatch[0].length);\n const cleanedFm = stripTopLevelBlock(fmBlock, 'onboarding');\n const newFm = `${cleanedFm}\\n${onboardingBlock}`.replace(/^\\n+/, '');\n const normalizedFm = newFm.replace(/\\n+$/, '');\n const newContent = `---\\n${normalizedFm}\\n---${afterFrontmatter}`;\n await writeFileForce(configPath, newContent);\n}\n\nexport async function updateBackupConfig(\n backup: Partial<BackupConfig>,\n): Promise<void> {\n const configPath = resolve(syntaurRoot(), 'config.md');\n const current = (await readConfig()).backup;\n const nextBackup: BackupConfig = {\n repo: current?.repo ?? null,\n categories: current?.categories ?? 'projects, playbooks, todos, servers, config',\n lastBackup: current?.lastBackup ?? null,\n lastRestore: current?.lastRestore ?? null,\n ...backup,\n };\n\n const backupBlock = serializeBackupConfig(nextBackup);\n const existing = await fileExists(configPath)\n ? await readFile(configPath, 'utf-8')\n : renderConfig({ defaultProjectDir: defaultProjectDir() });\n\n const fmMatch = existing.match(/^(---\\n)([\\s\\S]*?)\\n(---)/);\n if (!fmMatch) {\n const content = `---\\nversion: \"2.0\"\\ndefaultProjectDir: ${defaultProjectDir()}\\n${backupBlock}\\n---\\n${existing}`;\n await writeFileForce(configPath, content.replace(/\\n\\n---/, '\\n---'));\n return;\n }\n\n const fmBlock = fmMatch[2];\n const afterFrontmatter = existing.slice(fmMatch[0].length);\n const cleanedFm = stripTopLevelBlock(fmBlock, 'backup');\n const newFm = `${cleanedFm}\\n${backupBlock}`.replace(/^\\n+/, '');\n const normalizedFm = newFm.replace(/\\n+$/, '');\n const newContent = `---\\n${normalizedFm}\\n---${afterFrontmatter}`;\n await writeFileForce(configPath, newContent);\n}\n\n// Guard so the legacy-config migration runs at most once per config path per\n// process lifetime. Keyed by absolute path so tests with multiple sandbox\n// HOMEs still get the migration applied to each.\nconst migratedConfigPaths = new Set<string>();\n\nexport async function readConfig(): Promise<SyntaurConfig> {\n const configPath = resolve(syntaurRoot(), 'config.md');\n if (!(await fileExists(configPath))) {\n return cloneDefaultConfig();\n }\n\n if (!migratedConfigPaths.has(configPath)) {\n migratedConfigPaths.add(configPath);\n await migrateLegacyConfig(configPath);\n }\n\n const content = await readFile(configPath, 'utf-8');\n const fm = parseFrontmatter(content);\n\n if (Object.keys(fm).length === 0) {\n console.warn('Warning: ~/.syntaur/config.md has malformed frontmatter, using defaults');\n return cloneDefaultConfig();\n }\n\n let projectDir = fm['defaultProjectDir']\n ? expandHome(String(fm['defaultProjectDir']))\n : DEFAULT_CONFIG.defaultProjectDir;\n if (!isAbsolute(projectDir)) {\n console.warn(\n `Warning: config.md defaultProjectDir is not an absolute path (\"${fm['defaultProjectDir']}\"), using default`,\n );\n projectDir = DEFAULT_CONFIG.defaultProjectDir;\n }\n\n const fmBlock = content.match(/^---\\n([\\s\\S]*?)\\n---/)?.[1] ?? '';\n\n return {\n version: fm['version'] || DEFAULT_CONFIG.version,\n defaultProjectDir: projectDir,\n onboarding: {\n completed: fm['onboarding.completed'] === 'true',\n },\n agentDefaults: {\n trustLevel:\n (fm['agentDefaults.trustLevel'] as SyntaurConfig['agentDefaults']['trustLevel']) ||\n DEFAULT_CONFIG.agentDefaults.trustLevel,\n autoApprove:\n fm['agentDefaults.autoApprove'] === 'true' ||\n DEFAULT_CONFIG.agentDefaults.autoApprove,\n autoCreateWorktree: AUTO_CREATE_WORKTREE_VALUES.includes(\n fm['agentDefaults.autoCreateWorktree'] as AutoCreateWorktree,\n )\n ? (fm['agentDefaults.autoCreateWorktree'] as AutoCreateWorktree)\n : DEFAULT_CONFIG.agentDefaults.autoCreateWorktree,\n },\n integrations: {\n claudePluginDir: parseOptionalAbsolutePath(\n fm['integrations.claudePluginDir'],\n 'integrations.claudePluginDir',\n ),\n codexPluginDir: parseOptionalAbsolutePath(\n fm['integrations.codexPluginDir'],\n 'integrations.codexPluginDir',\n ),\n codexMarketplacePath: parseOptionalAbsolutePath(\n fm['integrations.codexMarketplacePath'],\n 'integrations.codexMarketplacePath',\n ),\n },\n backup: fm['backup.repo'] || fm['backup.categories']\n ? {\n repo: fm['backup.repo'] && fm['backup.repo'] !== 'null' ? fm['backup.repo'] : null,\n categories: fm['backup.categories'] || 'projects, playbooks, todos, servers, config',\n lastBackup: fm['backup.lastBackup'] && fm['backup.lastBackup'] !== 'null' ? fm['backup.lastBackup'] : null,\n lastRestore: fm['backup.lastRestore'] && fm['backup.lastRestore'] !== 'null' ? fm['backup.lastRestore'] : null,\n }\n : null,\n statuses: parseStatusConfig(content),\n types: null,\n agents: normalizeAgentsFromConfig(parseAgentsConfig(content)),\n playbooks: parsePlaybooksConfig(fmBlock),\n theme: parseThemeConfig(content),\n hotkeys: parseHotkeyBindingsConfig(content),\n terminal: (() => {\n try {\n return parseTerminalConfig(fm['terminal']);\n } catch (err) {\n const msg = err instanceof TerminalConfigError ? err.message : String(err);\n console.warn(`Warning: ${msg} — falling back to default`);\n return null;\n }\n })(),\n };\n}\n\nexport function getAssignmentTypes(config: SyntaurConfig): TypesConfig {\n return config.types ?? DEFAULT_ASSIGNMENT_TYPES;\n}\n\nexport function getAgents(config: SyntaurConfig): AgentConfig[] {\n return config.agents ?? BUILTIN_AGENTS;\n}\n\nexport class TerminalConfigError extends Error {}\n\n/**\n * Parse the `terminal:` scalar from raw frontmatter values.\n * Returns null when the key is absent (caller falls back to platform default).\n * Throws TerminalConfigError when the value is not a known choice.\n */\nexport function parseTerminalConfig(value: unknown): TerminalChoice | null {\n if (value === undefined || value === null || value === '') return null;\n if (typeof value !== 'string') {\n throw new TerminalConfigError(\n `terminal must be a string — got ${typeof value}`,\n );\n }\n const trimmed = value.trim();\n if (trimmed === '') return null;\n if (!TERMINAL_CHOICES.includes(trimmed as TerminalChoice)) {\n throw new TerminalConfigError(\n `terminal \"${trimmed}\" is not a known choice — expected one of ${TERMINAL_CHOICES.join('|')}`,\n );\n }\n return trimmed as TerminalChoice;\n}\n\n/**\n * Return the configured terminal, or the platform default when unset.\n * Darwin → terminal-app; other platforms have no sensible auto-default and\n * return terminal-app as a stable fallback (doctor will warn separately).\n */\nexport function getTerminal(config: SyntaurConfig): TerminalChoice {\n return config.terminal ?? 'terminal-app';\n}\n\nexport interface AgentsMutation {\n kind: 'add' | 'remove' | 'set' | 'reorder';\n apply: (current: AgentConfig[]) => AgentConfig[];\n}\n\n/**\n * Apply a mutation to the agents list, validate, and either write or return the\n * proposed new list (for --dry-run). Always runs full validation.\n */\nexport async function updateAgentsConfig(\n mutation: AgentsMutation,\n options: { dryRun?: boolean } = {},\n): Promise<{ previous: AgentConfig[]; next: AgentConfig[]; written: boolean }> {\n const config = await readConfig();\n const previous = config.agents ?? [...BUILTIN_AGENTS];\n const next = mutation.apply(previous);\n validateAgentList(next);\n\n if (options.dryRun) {\n return { previous, next, written: false };\n }\n\n await writeAgentsConfig(next);\n return { previous, next, written: true };\n}\n","export function slugify(title: string): string {\n return title\n .toLowerCase()\n .trim()\n .replace(/[^a-z0-9\\s-]/g, '')\n .replace(/\\s+/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '');\n}\n\nexport function isValidSlug(slug: string): boolean {\n return /^[a-z0-9]+(-[a-z0-9]+)*$/.test(slug);\n}\n","import { resolve } from 'node:path';\nimport { readdir, readFile, unlink } from 'node:fs/promises';\nimport { fileExists, writeFileForce } from './fs.js';\nimport { parsePlaybook, type ParsedPlaybook } from '../dashboard/parser.js';\nimport { nowTimestamp } from './timestamp.js';\nimport { readConfig, updatePlaybooksConfig } from './config.js';\nimport { isValidSlug } from './slug.js';\n\nexport interface ResolvedPlaybook {\n filename: string;\n slug: string;\n parsed: ParsedPlaybook;\n}\n\nexport type PlaybookErrorCode = 'manifest' | 'not-found' | 'invalid-slug' | 'collision';\n\n/**\n * Stable error thrown by playbook helpers. Routers and CLI commands branch on\n * `code` to map to HTTP status / exit code without string matching.\n */\nexport class PlaybookError extends Error {\n readonly code: PlaybookErrorCode;\n constructor(code: PlaybookErrorCode, message: string) {\n super(message);\n this.code = code;\n this.name = 'PlaybookError';\n }\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/**\n * Replace or insert a frontmatter scalar field. Playbook files always have\n * frontmatter (parsePlaybook depends on it). If the field is absent, insert it\n * just before the closing `---`. Values are written verbatim (caller decides\n * quoting).\n */\nfunction setFrontmatterField(content: string, key: string, value: string): string {\n const regex = new RegExp(`^(${escapeRegExp(key)}:)\\\\s*.*$`, 'm');\n if (regex.test(content)) {\n return content.replace(regex, `$1 ${value}`);\n }\n const closingIdx = content.indexOf('\\n---', 4);\n if (closingIdx === -1) {\n return content;\n }\n return `${content.slice(0, closingIdx)}\\n${key}: ${value}${content.slice(closingIdx)}`;\n}\n\nfunction isVisiblePlaybookFile(name: string, isFile: boolean): boolean {\n return isFile && name.endsWith('.md') && !name.startsWith('_') && name !== 'manifest.md';\n}\n\n/**\n * Resolve a requested slug to a concrete playbook file.\n *\n * Canonical slug is the `slug` field in the playbook's frontmatter. If that\n * field is missing we fall back to the filename stem. This means a playbook\n * with `filename: foo.md` and frontmatter `slug: bar` is reachable by `bar`\n * (and NOT by `foo`) — this keeps behavior consistent across dashboard +\n * CLI so enable/disable state is addressable by a single canonical slug.\n */\nexport async function resolvePlaybookSlug(\n playbooksDir: string,\n slug: string,\n): Promise<ResolvedPlaybook | null> {\n if (!(await fileExists(playbooksDir))) return null;\n\n const entries = await readdir(playbooksDir, { withFileTypes: true });\n\n let filenameStemFallback: ResolvedPlaybook | null = null;\n\n for (const entry of entries) {\n if (!isVisiblePlaybookFile(entry.name, entry.isFile())) continue;\n\n const filePath = resolve(playbooksDir, entry.name);\n const raw = await readFile(filePath, 'utf-8');\n const parsed = parsePlaybook(raw);\n const canonical = parsed.slug || entry.name.replace(/\\.md$/, '');\n\n if (canonical === slug) {\n return { filename: entry.name, slug: canonical, parsed };\n }\n\n // Only use the filename stem as a fallback when frontmatter slug is absent.\n if (!parsed.slug && entry.name.replace(/\\.md$/, '') === slug) {\n filenameStemFallback = { filename: entry.name, slug: canonical, parsed };\n }\n }\n\n return filenameStemFallback;\n}\n\n/**\n * Toggle a playbook's enabled/disabled state. Writes config.md, rebuilds the\n * manifest, and returns the canonical slug + resulting enabled flag.\n *\n * Throws if the slug cannot be resolved to a playbook file.\n */\nexport async function setPlaybookEnabled(\n playbooksDir: string,\n slug: string,\n enabled: boolean,\n): Promise<{ slug: string; enabled: boolean; changed: boolean }> {\n const resolved = await resolvePlaybookSlug(playbooksDir, slug);\n if (!resolved) {\n throw new Error(`Playbook \"${slug}\" not found in ${playbooksDir}`);\n }\n\n const config = await readConfig();\n const disabledSet = new Set(config.playbooks.disabled);\n const wasDisabled = disabledSet.has(resolved.slug);\n const shouldBeDisabled = !enabled;\n\n if (wasDisabled === shouldBeDisabled) {\n return { slug: resolved.slug, enabled, changed: false };\n }\n\n if (shouldBeDisabled) {\n disabledSet.add(resolved.slug);\n } else {\n disabledSet.delete(resolved.slug);\n }\n\n await updatePlaybooksConfig({ disabled: Array.from(disabledSet).sort() });\n await rebuildPlaybookManifest(playbooksDir);\n\n return { slug: resolved.slug, enabled, changed: true };\n}\n\n/**\n * Load a playbook ONLY if it is enabled. Returns null when the playbook does\n * not exist OR is disabled in config. Intended for agent-facing lookups that\n * must respect the disabled state.\n *\n * Dashboard admin code should NOT use this — it uses the unfiltered\n * `getPlaybookDetail` so admins can still see and re-enable disabled playbooks.\n */\nexport async function loadEnabledPlaybook(\n playbooksDir: string,\n slug: string,\n): Promise<ParsedPlaybook | null> {\n const resolved = await resolvePlaybookSlug(playbooksDir, slug);\n if (!resolved) return null;\n\n const config = await readConfig();\n if (config.playbooks.disabled.includes(resolved.slug)) {\n return null;\n }\n\n return resolved.parsed;\n}\n\n/**\n * Remove a slug from the disabled list. Called when a playbook is deleted so\n * a later reincarnation with the same slug doesn't silently start disabled.\n * No-op if the slug isn't currently disabled.\n */\nexport async function removeFromDisabledList(slug: string): Promise<void> {\n const config = await readConfig();\n if (!config.playbooks.disabled.includes(slug)) return;\n await updatePlaybooksConfig({\n disabled: config.playbooks.disabled.filter((s) => s !== slug),\n });\n}\n\nexport async function rebuildPlaybookManifest(playbooksDir: string): Promise<void> {\n if (!(await fileExists(playbooksDir))) return;\n\n const config = await readConfig();\n const disabledSet = new Set(config.playbooks.disabled);\n\n const entries = await readdir(playbooksDir, { withFileTypes: true });\n const rows: Array<{ name: string; slug: string; description: string; whenToUse: string }> = [];\n\n for (const entry of entries) {\n if (!isVisiblePlaybookFile(entry.name, entry.isFile())) continue;\n\n const raw = await readFile(resolve(playbooksDir, entry.name), 'utf-8');\n const parsed = parsePlaybook(raw);\n const slug = parsed.slug || entry.name.replace(/\\.md$/, '');\n\n if (disabledSet.has(slug)) continue;\n\n rows.push({\n name: parsed.name || slug,\n slug,\n description: parsed.description,\n whenToUse: parsed.whenToUse,\n });\n }\n\n rows.sort((a, b) => a.name.localeCompare(b.name));\n\n const timestamp = nowTimestamp();\n const lines = [\n '---',\n `generated: \"${timestamp}\"`,\n `total: ${rows.length}`,\n '---',\n '',\n '# Playbooks',\n '',\n 'Behavioral rules for AI agents. Read and follow all playbooks before starting work.',\n '',\n ];\n\n for (const row of rows) {\n lines.push(`- **[${row.name}](${row.slug}.md)** — ${row.description}`);\n if (row.whenToUse) {\n lines.push(` _When to use: ${row.whenToUse}_`);\n }\n }\n\n lines.push('');\n\n await writeFileForce(resolve(playbooksDir, 'manifest.md'), lines.join('\\n'));\n}\n\n/**\n * Delete a playbook file from disk and regenerate the manifest. Refuses\n * `manifest`. Drops the slug from `config.playbooks.disabled` if present so a\n * later recreation with the same slug doesn't silently start disabled. Throws\n * `PlaybookError` on `manifest` / `not-found`.\n *\n * Shared by `DELETE /api/playbooks/:slug` and `syntaur delete-playbook`.\n */\nexport async function deletePlaybook(\n playbooksDir: string,\n slug: string,\n): Promise<{ slug: string }> {\n if (slug === 'manifest') {\n throw new PlaybookError('manifest', 'The playbook manifest cannot be deleted.');\n }\n\n const resolved = await resolvePlaybookSlug(playbooksDir, slug);\n if (!resolved) {\n throw new PlaybookError('not-found', `Playbook \"${slug}\" not found.`);\n }\n\n await unlink(resolve(playbooksDir, resolved.filename));\n await removeFromDisabledList(resolved.slug);\n await rebuildPlaybookManifest(playbooksDir);\n\n return { slug: resolved.slug };\n}\n\n/**\n * Rename a playbook to a new slug. Validates the new slug, refuses `manifest`,\n * and rejects collisions at both filename and canonical-slug levels. Updates\n * the on-disk file's frontmatter `slug:` field. Migrates the disabled-list\n * entry if needed. Regenerates the manifest.\n *\n * Special case: if `oldPath === newPath` (e.g., file is `foo.md` with\n * frontmatter `slug: bar`, caller renames `bar -> foo`), rewrite the file in\n * place without unlinking. Returns `renamedInPlace: true` in that case.\n */\nexport async function renamePlaybook(\n playbooksDir: string,\n oldSlug: string,\n newSlug: string,\n): Promise<{ from: string; to: string; renamedInPlace: boolean }> {\n if (!isValidSlug(newSlug)) {\n throw new PlaybookError(\n 'invalid-slug',\n `Invalid slug \"${newSlug}\". Slugs must be lowercase, hyphen-separated, with no special characters.`,\n );\n }\n if (newSlug === 'manifest') {\n throw new PlaybookError('manifest', 'A playbook cannot be named \"manifest\".');\n }\n\n const resolved = await resolvePlaybookSlug(playbooksDir, oldSlug);\n if (!resolved) {\n throw new PlaybookError('not-found', `Playbook \"${oldSlug}\" not found.`);\n }\n\n const oldPath = resolve(playbooksDir, resolved.filename);\n const newPath = resolve(playbooksDir, `${newSlug}.md`);\n\n // Rename-in-place: e.g., file `foo.md` with `slug: bar` renamed `bar -> foo`.\n // The on-disk filename doesn't change; only the frontmatter slug field does.\n const renamedInPlace = oldPath === newPath;\n\n if (!renamedInPlace) {\n // Filename collision: another file already occupies the new path.\n if (await fileExists(newPath)) {\n throw new PlaybookError(\n 'collision',\n `A playbook file already exists at \"${newSlug}.md\".`,\n );\n }\n // Canonical-slug collision: another file declares this slug in its frontmatter.\n const existing = await resolvePlaybookSlug(playbooksDir, newSlug);\n if (existing && resolve(playbooksDir, existing.filename) !== oldPath) {\n throw new PlaybookError(\n 'collision',\n `Another playbook already uses the canonical slug \"${newSlug}\".`,\n );\n }\n }\n\n const raw = await readFile(oldPath, 'utf-8');\n let next = setFrontmatterField(raw, 'slug', newSlug);\n next = setFrontmatterField(next, 'updated', `\"${nowTimestamp()}\"`);\n\n await writeFileForce(newPath, next);\n if (!renamedInPlace) {\n await unlink(oldPath);\n }\n\n // Migrate disabled-list entry if the old canonical slug was disabled.\n const config = await readConfig();\n if (config.playbooks.disabled.includes(resolved.slug)) {\n const nextDisabled = config.playbooks.disabled\n .filter((s) => s !== resolved.slug)\n .concat(newSlug);\n await updatePlaybooksConfig({ disabled: Array.from(new Set(nextDisabled)).sort() });\n }\n\n await rebuildPlaybookManifest(playbooksDir);\n\n return { from: resolved.slug, to: newSlug, renamedInPlace };\n}\n","import { resolve } from 'node:path';\nimport { readdir, readFile } from 'node:fs/promises';\nimport { fileExists } from './fs.js';\nimport { extractFrontmatter, getField } from '../dashboard/parser.js';\n\nexport interface ResolvedAssignment {\n assignmentDir: string;\n projectSlug: string | null;\n assignmentSlug: string;\n id: string;\n standalone: boolean;\n workspaceGroup: string | null;\n}\n\nexport async function resolveAssignmentById(\n projectsDir: string,\n assignmentsDir: string,\n id: string,\n): Promise<ResolvedAssignment | null> {\n let standaloneMatch: ResolvedAssignment | null = null;\n let projectMatch: ResolvedAssignment | null = null;\n\n // 1) Standalone: <assignmentsDir>/<id>/assignment.md\n const standaloneDir = resolve(assignmentsDir, id);\n const standalonePath = resolve(standaloneDir, 'assignment.md');\n if (await fileExists(standalonePath)) {\n let workspaceGroup: string | null = null;\n try {\n const content = await readFile(standalonePath, 'utf-8');\n const [fm] = extractFrontmatter(content);\n workspaceGroup = getField(fm, 'workspaceGroup');\n } catch {\n // unreadable — leave null\n }\n standaloneMatch = {\n assignmentDir: standaloneDir,\n projectSlug: null,\n assignmentSlug: id,\n id,\n standalone: true,\n workspaceGroup,\n };\n }\n\n // 2) Project-nested: scan <projectsDir>/*/assignments/*/assignment.md and match by frontmatter id\n if (await fileExists(projectsDir)) {\n try {\n const projects = await readdir(projectsDir, { withFileTypes: true });\n for (const p of projects) {\n if (!p.isDirectory()) continue;\n if (p.name.startsWith('.') || p.name.startsWith('_')) continue;\n const assignmentsPath = resolve(projectsDir, p.name, 'assignments');\n if (!(await fileExists(assignmentsPath))) continue;\n\n const entries = await readdir(assignmentsPath, { withFileTypes: true });\n for (const a of entries) {\n if (!a.isDirectory()) continue;\n const aPath = resolve(assignmentsPath, a.name, 'assignment.md');\n if (!(await fileExists(aPath))) continue;\n\n try {\n const content = await readFile(aPath, 'utf-8');\n const [fm] = extractFrontmatter(content);\n const fileId = getField(fm, 'id');\n if (fileId === id) {\n projectMatch = {\n assignmentDir: resolve(assignmentsPath, a.name),\n projectSlug: p.name,\n assignmentSlug: a.name,\n id,\n standalone: false,\n workspaceGroup: null,\n };\n break;\n }\n } catch {\n // skip unreadable\n }\n }\n if (projectMatch) break;\n }\n } catch {\n // projectsDir not readable\n }\n }\n\n if (standaloneMatch && projectMatch) {\n console.warn(\n `Duplicate assignment ID ${id} found in both standalone and project-nested locations; using standalone`,\n );\n return standaloneMatch;\n }\n\n return standaloneMatch ?? projectMatch ?? null;\n}\n","import type {\n HelpChecklistItem,\n HelpCommand,\n HelpResponse,\n HelpStatusGuideEntry,\n} from './types.js';\nimport { getStatusConfig } from './api.js';\n\nconst CLI_COMMANDS: HelpCommand[] = [\n // --- Core setup & scaffolding (indices 0-4) ---\n {\n command: 'syntaur setup',\n description: 'Initialize Syntaur and optionally install plugins or launch the dashboard.',\n example: 'syntaur setup',\n },\n {\n command: 'syntaur init',\n description: 'Initialize the local Syntaur home directory and config scaffolding without any prompts.',\n example: 'syntaur init',\n },\n {\n command: 'syntaur create-project',\n description: 'Create a new project folder with the required source and derived files.',\n example: 'syntaur create-project \"Ship dashboard overhaul\"',\n },\n {\n command: 'syntaur create-assignment',\n description: 'Create a new assignment inside a project.',\n example: 'syntaur create-assignment \"Implement overview API\" --project ui-overhaul',\n },\n {\n command: 'syntaur assign',\n description: 'Set the assignee for an assignment before work begins.',\n example: 'syntaur assign implement-overview --project ui-overhaul --agent codex-1',\n },\n\n // --- Lifecycle transitions ---\n {\n command: 'syntaur start',\n description: 'Transition an assignment to in_progress.',\n example: 'syntaur start implement-overview --project ui-overhaul',\n },\n {\n command: 'syntaur shape',\n description: 'Transition a draft assignment to ready_for_planning once the Objective and Acceptance Criteria are fleshed out.',\n example: 'syntaur shape implement-overview --project ui-overhaul',\n },\n {\n command: 'syntaur plan-ready',\n description: 'Transition a ready_for_planning assignment to ready_to_implement once a plan has been written and approved.',\n example: 'syntaur plan-ready implement-overview --project ui-overhaul',\n },\n {\n command: 'syntaur implement',\n description: 'Transition a ready_to_implement assignment to in_progress when coding begins.',\n example: 'syntaur implement implement-overview --project ui-overhaul',\n },\n {\n command: 'syntaur migrate-statuses',\n description: 'Suggest pending -> ready_for_planning promotions for fleshed-out assignments. Dry-run by default; pass --apply to write.',\n example: 'syntaur migrate-statuses --apply',\n },\n {\n command: 'syntaur review',\n description: 'Move active work into review once implementation is ready for inspection.',\n example: 'syntaur review implement-overview --project ui-overhaul',\n },\n {\n command: 'syntaur complete',\n description: 'Mark an assignment completed after review or direct completion.',\n example: 'syntaur complete implement-overview --project ui-overhaul',\n },\n {\n command: 'syntaur block',\n description: 'Mark an assignment blocked and record the explicit reason.',\n example: 'syntaur block implement-overview --project ui-overhaul --reason \"Waiting on API spec\"',\n },\n {\n command: 'syntaur unblock',\n description: 'Move a blocked assignment back to in_progress after the blocker is cleared.',\n example: 'syntaur unblock implement-overview --project ui-overhaul',\n },\n {\n command: 'syntaur fail',\n description: 'Mark an assignment failed when it cannot be completed as planned.',\n example: 'syntaur fail implement-overview --project ui-overhaul',\n },\n {\n command: 'syntaur reopen',\n description: 'Reopen a completed or failed assignment back to in_progress.',\n example: 'syntaur reopen implement-overview --project ui-overhaul',\n },\n\n // --- Dashboard (index 12) ---\n {\n command: 'syntaur dashboard',\n description: 'Start the local dashboard UI over the project files on disk.',\n example: 'syntaur dashboard --port 4800',\n },\n\n // --- Plugin & adapter setup (indices 13-16) ---\n {\n command: 'syntaur install-plugin',\n description: 'Install the Syntaur Claude Code plugin, detecting the local Claude marketplace when available and prompting for the target directory when interactive.',\n example: 'syntaur install-plugin --target-dir ~/.claude/plugins/marketplaces/user-plugins/plugins/syntaur',\n },\n {\n command: 'syntaur install-codex-plugin',\n description: 'Install the Syntaur Codex plugin and register its marketplace entry, prompting for both paths when interactive.',\n example: 'syntaur install-codex-plugin --target-dir ~/plugins/syntaur --marketplace-path ~/.agents/plugins/marketplace.json',\n },\n {\n command: 'syntaur uninstall',\n description: 'Remove Syntaur plugins and optionally local ~/.syntaur data.',\n example: 'syntaur uninstall --all',\n },\n {\n command: 'syntaur setup-adapter',\n description: 'Generate adapter instruction files for cursor, codex, or opencode in the current directory.',\n example: 'syntaur setup-adapter cursor --project ui-overhaul --assignment implement-overview',\n },\n\n // --- Session & server tracking (index 17) ---\n {\n command: 'syntaur track-session',\n description:\n 'Register an agent session. Requires --session-id from the agent runtime (real, not generated). Pass --transcript-path for the rollout/transcript file. --project and --assignment are optional.',\n example:\n 'syntaur track-session --agent claude --session-id <real-id> --transcript-path <path> --project ui-overhaul --assignment implement-overview',\n },\n\n // --- Browsing & playbooks (indices 18-20) ---\n {\n command: 'syntaur browse',\n description: 'Interactive TUI browser for projects and assignments.',\n example: 'syntaur browse',\n },\n {\n command: 'syntaur create-playbook',\n description: 'Create a new playbook with behavioral rules for agents.',\n example: 'syntaur create-playbook \"Code Review Standards\"',\n },\n {\n command: 'syntaur list-playbooks',\n description:\n 'List playbooks in the Syntaur home directory. Disabled playbooks are excluded by default; pass --all to include them with a (disabled) tag.',\n example: 'syntaur list-playbooks --all',\n },\n {\n command: 'syntaur enable-playbook',\n description:\n 'Re-enable a previously-disabled playbook so agents load it again. Updates config.md and rebuilds manifest.md.',\n example: 'syntaur enable-playbook commit-discipline',\n },\n {\n command: 'syntaur disable-playbook',\n description:\n 'Disable a playbook so agents no longer list or load it. Playbook file is untouched; state is tracked in config.md.',\n example: 'syntaur disable-playbook commit-discipline',\n },\n {\n command: 'syntaur delete-playbook',\n description:\n 'Delete a playbook from disk and regenerate the manifest. Refuses to delete the manifest itself.',\n example: 'syntaur delete-playbook scratch-foo',\n },\n];\n\nconst WORKFLOW: HelpChecklistItem[] = [\n {\n title: 'Initialize the workspace',\n detail: 'Run setup once so Syntaur can initialize its local home directory and offer plugin installation.',\n command: CLI_COMMANDS[0],\n },\n {\n title: 'Create a project',\n detail: 'Use a project for a higher-level objective. Projects group assignments, shared resources, and memories.',\n command: CLI_COMMANDS[2],\n href: '/create/project',\n },\n {\n title: 'Create the first assignment',\n detail: 'Assignments are the execution unit. Create one for each concrete chunk of work inside the project.',\n command: CLI_COMMANDS[3],\n },\n {\n title: 'Assign the work',\n detail: 'Setting an assignee before starting is recommended for clarity, but not required.',\n command: CLI_COMMANDS[4],\n },\n {\n title: 'Start, review, complete, or block through lifecycle actions',\n detail: 'Status changes happen through lifecycle actions, kanban drag-and-drop, or the status override controls.',\n command: CLI_COMMANDS[5],\n },\n {\n title: 'Use the dashboard for triage and context',\n detail: 'Overview shows the current queue, project pages show health, assignment pages show the execution surface.',\n command: CLI_COMMANDS[12],\n href: '/',\n },\n];\n\nconst DEFAULT_STATUS_GUIDE: Record<string, { meaning: string; useWhen: string }> = {\n draft: {\n meaning: 'The assignment is a just-created stub; objective and acceptance criteria are not yet fleshed out.',\n useWhen: 'Use draft for newly-scaffolded assignments. Transition to ready_for_planning with `syntaur shape` once the Objective and AC are written.',\n },\n pending: {\n meaning: 'The assignment has not started yet.',\n useWhen: 'Use pending while waiting to start. If dependencies are unmet, pending is the normal waiting state.',\n },\n ready_for_planning: {\n meaning: 'The assignment is fully shaped; a plan needs to be written before implementation can begin.',\n useWhen: 'Use ready_for_planning after the Objective and Acceptance Criteria are filled out but before any plan.md exists. Transition to ready_to_implement with `syntaur plan-ready` after the plan is approved.',\n },\n ready_to_implement: {\n meaning: 'The plan has been written and approved; the assignment is ready to start coding.',\n useWhen: 'Use ready_to_implement once a plan.md exists and is approved. Transition to in_progress with `syntaur implement` when coding begins.',\n },\n in_progress: {\n meaning: 'An assigned agent is actively working the assignment.',\n useWhen: 'Use in_progress once the work has started and dependencies are satisfied.',\n },\n blocked: {\n meaning: 'The assignment hit a manual or runtime obstacle.',\n useWhen: 'Use blocked when work hits an obstacle. Adding a blockedReason is recommended for traceability.',\n },\n review: {\n meaning: 'Implementation is ready for inspection or validation.',\n useWhen: 'Use review after active work is ready to be checked before completion.',\n },\n completed: {\n meaning: 'The assignment is done.',\n useWhen: 'Use completed when the acceptance criteria are satisfied.',\n },\n failed: {\n meaning: 'The assignment could not be completed as planned.',\n useWhen: 'Use failed when the work cannot be recovered within the current assignment.',\n },\n};\n\nasync function buildStatusGuide(): Promise<HelpStatusGuideEntry[]> {\n const config = await getStatusConfig();\n\n return config.statuses.map((s) => {\n const defaults = DEFAULT_STATUS_GUIDE[s.id];\n return {\n status: s.id,\n meaning: s.description ?? defaults?.meaning ?? `The assignment is in the \"${s.label}\" state.`,\n useWhen: defaults?.useWhen ?? `Use ${s.id} when appropriate for the \"${s.label}\" workflow state.`,\n };\n });\n}\n\nexport async function getDashboardHelp(): Promise<HelpResponse> {\n return {\n generatedAt: new Date().toISOString(),\n whatIsSyntaur: {\n summary:\n 'Syntaur is a local-first, markdown-backed agent work system. The dashboard is a live view over project folders and files on disk.',\n bullets: [\n 'Markdown files are the source of truth.',\n 'The UI reads project folders, assignment files, and derived indexes from the local filesystem.',\n 'Derived underscore-prefixed files are projections, not the canonical edit target.',\n ],\n },\n coreConcepts: [\n {\n term: 'Project',\n description:\n 'A project is the higher-level objective. It owns assignments, shared resources, and project memories.',\n },\n {\n term: 'Assignment',\n description:\n 'An assignment is a concrete unit of execution. Assignment frontmatter is the source of truth for status, priority, assignee, and dependencies.',\n },\n {\n term: 'Resource',\n description:\n 'A project-level shared reference file that provides source material or constraints for the work.',\n },\n {\n term: 'Memory',\n description:\n 'A project-level learning or pattern captured during execution so future assignments can reuse it.',\n },\n {\n term: 'Manifest',\n description:\n 'A derived navigation file that points agents at the project overview, indexes, and agent instructions.',\n },\n {\n term: 'Derived file',\n description:\n 'An underscore-prefixed file regenerated from canonical markdown sources. Read it, but do not edit it directly.',\n },\n {\n term: 'Handoff',\n description:\n 'An append-only log that records baton-passes between agents or sessions without rewriting prior history.',\n },\n {\n term: 'Decision record',\n description:\n 'An append-only record of important decisions, rationale, and follow-up consequences.',\n },\n {\n term: 'Playbook',\n description:\n 'A behavioral rule set stored in ~/.syntaur/playbooks/. Playbooks define constraints and conventions that agents must follow during execution. Manage them via the CLI or the Playbooks page.',\n },\n {\n term: 'Workspace',\n description:\n 'The repository context for an assignment, including the repository path, worktree path, branch, and parent branch. Workspace fields connect an assignment to the code being worked on and define write boundaries.',\n },\n {\n term: 'Agent Session',\n description:\n 'A tracked AI session tied to assignment work. Sessions are registered via the track-session CLI command or the Claude Code plugin and visible on the Agent Sessions page.',\n },\n {\n term: 'Server',\n description:\n 'A tracked tmux session with automatic port discovery, branch detection, and assignment linking. The Servers page shows all tracked sessions with their windows, panes, and discovered services.',\n },\n ],\n workflow: WORKFLOW,\n statusGuide: await buildStatusGuide(),\n ownershipRules: [\n {\n label: 'Human-authored files',\n files: ['project.md', 'agent.md', 'claude.md'],\n description:\n 'These files define project intent and instructions. The dashboard treats project status as derived except for the archive fields.',\n },\n {\n label: 'Assignment working files',\n files: ['assignment.md', 'plan*.md (optional, versioned)', 'scratchpad.md'],\n description:\n 'These are agent-writable files. The dashboard lets you edit the source markdown while preserving unsupported frontmatter keys.',\n },\n {\n label: 'Append-only logs',\n files: ['handoff.md', 'decision-record.md'],\n description:\n 'These logs preserve history. The dashboard appends new entries instead of rewriting previous ones.',\n },\n {\n label: 'Derived files',\n files: ['_status.md', '_index-assignments.md', '_index-plans.md', '_index-decisions.md'],\n description:\n 'These files are read-only projections. They can lag behind source files, so the dashboard computes source-first state.',\n },\n ],\n commands: CLI_COMMANDS,\n navigation: [\n {\n label: 'Overview',\n description: 'Triage hub showing assignments that need action, recent activity, progress stats, and first-run setup guidance.',\n href: '/',\n },\n {\n label: 'Projects',\n description: 'Browse, search, filter, and sort the project directory. Create new projects and drill into project workspaces.',\n href: '/projects',\n },\n {\n label: 'Assignments',\n description: 'Cross-project kanban board of all assignments. Drag cards between columns to change status, or filter by project, assignee, or status.',\n href: '/assignments',\n },\n {\n label: 'Servers',\n description: 'Tracked tmux sessions with auto-discovered ports, URLs, git branches, and links to related assignments. Register sessions manually or let autodiscovery find them.',\n href: '/servers',\n },\n {\n label: 'Agent Sessions',\n description: 'Monitor which AI agents are currently working, what assignments they are linked to, and session duration. Sessions are registered via the Claude Code plugin or track-session CLI command.',\n href: '/agent-sessions',\n },\n {\n label: 'Playbooks',\n description: 'Create, browse, and edit behavioral rules that agents must follow. The playbook manifest at ~/.syntaur/playbooks/manifest.md is auto-generated for inclusion in agent instructions.',\n href: '/playbooks',\n },\n {\n label: 'Help',\n description: 'This page. Status guide, CLI quick reference, core concepts, and FAQ.',\n href: '/help',\n },\n {\n label: 'Settings',\n description: 'Customize status definitions, labels, colors, display order, and done states. Changes apply globally across the dashboard and CLI.',\n href: '/settings',\n },\n {\n label: 'Project page',\n description: 'The project workspace shows health stats, assignment list, dependency graph, shared resources, and memories.',\n href: '/projects',\n },\n {\n label: 'Assignment page',\n description: 'The assignment workspace shows lifecycle actions, plan editor, scratchpad, handoff log, decision records, and agent sessions.',\n href: '/projects',\n },\n ],\n faq: [\n {\n question: 'Why are some files read-only in the dashboard?',\n answer:\n 'Underscore-prefixed files are derived projections that can be rebuilt from canonical markdown sources. Editing them would create drift, so the UI treats them as read-only.',\n },\n {\n question: 'Why can an assignment be pending even when nothing looks broken?',\n answer:\n 'Pending often just means the work has not started yet or it is waiting on declared dependencies. Blocked is reserved for exceptional runtime obstacles that need intervention.',\n },\n {\n question: 'How do I change an assignment\\'s status?',\n answer:\n 'Use lifecycle CLI commands (syntaur start, syntaur complete, etc.), drag cards on the kanban board, or use the Override Status dropdown on the assignment page. Any status can be set from any other status.',\n },\n {\n question: 'How do I customize statuses?',\n answer:\n 'Open the Settings page from the sidebar. You can add, remove, rename, recolor, and reorder statuses. You can also mark statuses as done states. Changes are saved to ~/.syntaur/config.md and take effect immediately across the dashboard.',\n },\n {\n question: 'What is a done state?',\n answer:\n 'A done state (also called terminal status) means the assignment is finished. Done states fill the completed portion of progress bars and satisfy dependency requirements. By default, \"completed\" and \"failed\" are done states. You can configure which statuses are done states in Settings.',\n },\n {\n question: 'What are playbooks and how do I use them?',\n answer:\n 'Playbooks are markdown files in ~/.syntaur/playbooks/ that define behavioral rules agents must follow. Create them via the CLI (syntaur create-playbook) or the Playbooks page. The auto-generated manifest at ~/.syntaur/playbooks/manifest.md can be included in your CLAUDE.md so agents pick up the rules.',\n },\n {\n question: 'How does agent session tracking work?',\n answer:\n 'When an AI agent starts working on an assignment, it can register a session via the track-session CLI command or the Claude Code plugin\\'s /track-session command. The Agent Sessions page shows active and completed sessions with their linked assignments and duration.',\n },\n {\n question: 'How does server tracking work?',\n answer:\n 'Syntaur tracks tmux sessions to discover running dev servers, their ports, git branches, and linked assignments. Register sessions on the Servers page or let autodiscovery find them. Pane info refreshes automatically.',\n },\n ],\n firstProjectChecklist: [\n {\n title: 'Create the project',\n detail: 'Describe the overall objective in project.md, then add tags and archive metadata only when needed.',\n command: CLI_COMMANDS[1],\n href: '/create/project',\n },\n {\n title: 'Create at least one assignment',\n detail: 'Break the project into executable work units with explicit priority and dependencies.',\n command: CLI_COMMANDS[2],\n },\n {\n title: 'Assign and start the first assignment',\n detail: 'Set an assignee, then start the assignment once prerequisites are complete.',\n command: CLI_COMMANDS[3],\n },\n {\n title: 'Use the assignment workspace for execution',\n detail: 'Keep the objective and todos in assignment.md, implementation plans in optional versioned plan files (plan.md, plan-v2.md, ...), and transient notes in scratchpad.md.',\n href: '/projects',\n },\n {\n title: 'Record handoffs and decisions without rewriting history',\n detail: 'Append new handoff and decision entries instead of editing prior entries.',\n },\n {\n title: 'Return to Overview for triage',\n detail: 'Overview surfaces the queue of assignments that need action next.',\n href: '/',\n },\n ],\n links: [\n { label: 'Overview', href: '/' },\n { label: 'Project Directory', href: '/projects' },\n { label: 'Assignments Board', href: '/assignments' },\n { label: 'Servers', href: '/servers' },\n { label: 'Agent Sessions', href: '/agent-sessions' },\n { label: 'Playbooks', href: '/playbooks' },\n { label: 'Settings', href: '/settings' },\n { label: 'Create Project', href: '/create/project' },\n ],\n };\n}\n\nexport function getHelpCommandNames(): string[] {\n return CLI_COMMANDS.map((command) => command.command.replace(/^syntaur\\s+/, ''));\n}\n","import Database from 'better-sqlite3';\nimport { resolve } from 'node:path';\nimport { readdir } from 'node:fs/promises';\nimport { syntaurRoot } from '../utils/paths.js';\nimport { fileExists } from '../utils/fs.js';\nimport type { AgentSession, AgentSessionStatus } from './types.js';\n\nlet db: Database.Database | null = null;\n\nconst SCHEMA_VERSION = '4';\n\n// The base schema deliberately OMITS the project_slug indexes — they are\n// created after any legacy-schema migrations run below. Older installs may\n// have the `mission_slug` column, and creating an index that references\n// `project_slug` before the rename migration runs would fail.\nconst SCHEMA_SQL = `\nCREATE TABLE IF NOT EXISTS sessions (\n session_id TEXT PRIMARY KEY,\n project_slug TEXT,\n assignment_slug TEXT,\n agent TEXT NOT NULL,\n started TEXT NOT NULL,\n ended TEXT,\n status TEXT NOT NULL DEFAULT 'active',\n path TEXT,\n description TEXT,\n transcript_path TEXT,\n pid INTEGER,\n pid_started_at TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\nCREATE INDEX IF NOT EXISTS idx_sessions_status ON sessions(status);\nCREATE TABLE IF NOT EXISTS meta (key TEXT PRIMARY KEY, value TEXT);\n`;\n\nconst POST_MIGRATION_INDEXES_SQL = `\nCREATE INDEX IF NOT EXISTS idx_sessions_project ON sessions(project_slug);\nCREATE INDEX IF NOT EXISTS idx_sessions_assignment ON sessions(project_slug, assignment_slug);\n`;\n\n/**\n * Initialize the SQLite database for session tracking.\n * Creates the database file and schema if they don't exist.\n * @param dbPath Optional override for the database file path (used in tests).\n */\nexport function initSessionDb(dbPath?: string): Database.Database {\n if (db) return db;\n\n const finalPath = dbPath ?? resolve(syntaurRoot(), 'syntaur.db');\n db = new Database(finalPath);\n db.pragma('journal_mode = WAL');\n db.exec(SCHEMA_SQL);\n\n // Track schema version\n db.prepare('INSERT OR IGNORE INTO meta (key, value) VALUES (?, ?)').run(\n 'schema_version',\n SCHEMA_VERSION,\n );\n\n // Run migrations inside an EXCLUSIVE transaction. This closes two races:\n // 1. Crash between `DROP TABLE` / `RENAME` / `UPDATE meta` leaves the db\n // half-upgraded — the transaction rolls back on failure.\n // 2. Two processes (e.g. `syntaur dashboard` + `syntaur track-session`)\n // both calling initSessionDb() at once — EXCLUSIVE serializes the\n // migration and the version is re-checked inside the transaction so\n // the second process becomes a no-op once the first commits.\n // Narrow for the transaction closure — TS doesn't track the module-level\n // `db` assignment across the closure boundary.\n const database = db;\n const runMigrations = database.transaction(() => {\n // --- v1 → v2: make project/assignment nullable, add description ---\n const vBeforeV2 = (\n database\n .prepare(\"SELECT value FROM meta WHERE key = 'schema_version'\")\n .get() as { value: string } | undefined\n )?.value;\n\n if (vBeforeV2 === '1') {\n database.exec(`\n CREATE TABLE sessions_v2 (\n session_id TEXT PRIMARY KEY,\n project_slug TEXT,\n assignment_slug TEXT,\n agent TEXT NOT NULL,\n started TEXT NOT NULL,\n ended TEXT,\n status TEXT NOT NULL DEFAULT 'active',\n path TEXT,\n description TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n );\n INSERT INTO sessions_v2 SELECT session_id, project_slug, assignment_slug, agent, started, ended, status, path, NULL, created_at, updated_at FROM sessions;\n DROP TABLE sessions;\n ALTER TABLE sessions_v2 RENAME TO sessions;\n CREATE INDEX IF NOT EXISTS idx_sessions_project ON sessions(project_slug);\n CREATE INDEX IF NOT EXISTS idx_sessions_assignment ON sessions(project_slug, assignment_slug);\n CREATE INDEX IF NOT EXISTS idx_sessions_status ON sessions(status);\n UPDATE meta SET value = '2' WHERE key = 'schema_version';\n `);\n }\n\n // --- v2 → v3: add transcript_path, normalize legacy mission_slug ---\n // Re-read the version AFTER v1→v2 may have run.\n const vBeforeV3 = (\n database\n .prepare(\"SELECT value FROM meta WHERE key = 'schema_version'\")\n .get() as { value: string } | undefined\n )?.value;\n\n if (vBeforeV3 === '2') {\n const v2Columns = database\n .prepare('PRAGMA table_info(sessions)')\n .all() as Array<{ name: string }>;\n const v2ColNames = v2Columns.map((c) => c.name);\n const hasProject = v2ColNames.includes('project_slug');\n const hasMission = v2ColNames.includes('mission_slug');\n\n // If a db somehow has both columns (e.g. a partially-renamed table),\n // prefer project_slug but fall back to mission_slug so rows that only\n // populated mission_slug aren't dropped.\n const projectSlugExpr =\n hasProject && hasMission\n ? 'COALESCE(project_slug, mission_slug)'\n : hasProject\n ? 'project_slug'\n : hasMission\n ? 'mission_slug'\n : null;\n\n if (!projectSlugExpr) {\n throw new Error(\n 'sessions table has neither project_slug nor mission_slug; cannot migrate from v2 to v3',\n );\n }\n\n database.exec(`\n CREATE TABLE sessions_v3 (\n session_id TEXT PRIMARY KEY,\n project_slug TEXT,\n assignment_slug TEXT,\n agent TEXT NOT NULL,\n started TEXT NOT NULL,\n ended TEXT,\n status TEXT NOT NULL DEFAULT 'active',\n path TEXT,\n description TEXT,\n transcript_path TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n );\n INSERT INTO sessions_v3\n SELECT session_id, ${projectSlugExpr}, assignment_slug, agent, started, ended, status, path, description, NULL, created_at, updated_at\n FROM sessions;\n DROP TABLE sessions;\n ALTER TABLE sessions_v3 RENAME TO sessions;\n CREATE INDEX IF NOT EXISTS idx_sessions_project ON sessions(project_slug);\n CREATE INDEX IF NOT EXISTS idx_sessions_assignment ON sessions(project_slug, assignment_slug);\n CREATE INDEX IF NOT EXISTS idx_sessions_status ON sessions(status);\n UPDATE meta SET value = '3' WHERE key = 'schema_version';\n `);\n }\n\n // --- v3 → v4: add pid + pid_started_at for liveness detection ---\n const vBeforeV4 = (\n database\n .prepare(\"SELECT value FROM meta WHERE key = 'schema_version'\")\n .get() as { value: string } | undefined\n )?.value;\n\n if (vBeforeV4 === '3') {\n database.exec(`\n CREATE TABLE sessions_v4 (\n session_id TEXT PRIMARY KEY,\n project_slug TEXT,\n assignment_slug TEXT,\n agent TEXT NOT NULL,\n started TEXT NOT NULL,\n ended TEXT,\n status TEXT NOT NULL DEFAULT 'active',\n path TEXT,\n description TEXT,\n transcript_path TEXT,\n pid INTEGER,\n pid_started_at TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n );\n INSERT INTO sessions_v4\n SELECT session_id, project_slug, assignment_slug, agent, started, ended, status, path, description, transcript_path, NULL, NULL, created_at, updated_at\n FROM sessions;\n DROP TABLE sessions;\n ALTER TABLE sessions_v4 RENAME TO sessions;\n CREATE INDEX IF NOT EXISTS idx_sessions_project ON sessions(project_slug);\n CREATE INDEX IF NOT EXISTS idx_sessions_assignment ON sessions(project_slug, assignment_slug);\n CREATE INDEX IF NOT EXISTS idx_sessions_status ON sessions(status);\n UPDATE meta SET value = '4' WHERE key = 'schema_version';\n `);\n }\n });\n runMigrations.exclusive();\n\n // Create project-slug-dependent indexes now that we know the column exists.\n db.exec(POST_MIGRATION_INDEXES_SQL);\n\n return db;\n}\n\n/**\n * Get the initialized database handle.\n * Throws if initSessionDb() has not been called.\n */\nexport function getSessionDb(): Database.Database {\n if (!db) {\n throw new Error(\n 'Session database not initialized. Call initSessionDb() first.',\n );\n }\n return db;\n}\n\n/**\n * Close the database connection.\n */\nexport function closeSessionDb(): void {\n if (db) {\n db.close();\n db = null;\n }\n}\n\n/**\n * Reset the singleton for testing purposes.\n */\nexport function resetSessionDb(): void {\n db = null;\n}\n\n/**\n * One-time migration: import sessions from markdown _index-sessions.md files into SQLite.\n * Only runs if the sessions table is empty and markdown files exist.\n */\nexport async function migrateFromMarkdown(projectsDir: string): Promise<number> {\n const database = getSessionDb();\n\n // Skip if sessions already exist in the database\n const count = database.prepare('SELECT COUNT(*) as count FROM sessions').get() as { count: number };\n if (count.count > 0) return 0;\n\n if (!(await fileExists(projectsDir))) return 0;\n\n const entries = await readdir(projectsDir, { withFileTypes: true });\n const allSessions: AgentSession[] = [];\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n const projectDir = resolve(projectsDir, entry.name);\n const indexPath = resolve(projectDir, '_index-sessions.md');\n if (!(await fileExists(indexPath))) continue;\n\n const sessions = await parseMarkdownSessionsIndex(indexPath, entry.name);\n allSessions.push(...sessions);\n }\n\n if (allSessions.length === 0) return 0;\n\n const insert = database.prepare(`\n INSERT OR IGNORE INTO sessions (session_id, project_slug, assignment_slug, agent, started, status, path)\n VALUES (?, ?, ?, ?, ?, ?, ?)\n `);\n\n const insertAll = database.transaction((sessions: AgentSession[]) => {\n for (const s of sessions) {\n insert.run(s.sessionId, s.projectSlug, s.assignmentSlug, s.agent, s.started, s.status, s.path);\n }\n });\n\n insertAll(allSessions);\n console.log(`Migrated ${allSessions.length} sessions from markdown to SQLite.`);\n return allSessions.length;\n}\n\n/**\n * Parse an _index-sessions.md file into AgentSession objects.\n * Used only for one-time migration. This is a copy of the old parsing logic.\n */\nasync function parseMarkdownSessionsIndex(\n filePath: string,\n projectSlug: string,\n): Promise<AgentSession[]> {\n const { readFile } = await import('node:fs/promises');\n const raw = await readFile(filePath, 'utf-8');\n const sessions: AgentSession[] = [];\n\n const lines = raw.split('\\n');\n let inTable = false;\n let headerSeen = false;\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n\n if (trimmed.startsWith('| Assignment') || trimmed.startsWith('|Assignment')) {\n inTable = true;\n headerSeen = false;\n continue;\n }\n\n if (inTable && !headerSeen && trimmed.match(/^\\|[-\\s|]+\\|$/)) {\n headerSeen = true;\n continue;\n }\n\n if (inTable && headerSeen && trimmed.startsWith('|')) {\n const cells = trimmed\n .split('|')\n .slice(1, -1)\n .map((c) => c.trim());\n\n if (cells.length >= 6) {\n sessions.push({\n assignmentSlug: cells[0],\n agent: cells[1],\n sessionId: cells[2],\n started: cells[3],\n status: (cells[4] as AgentSessionStatus) || 'active',\n path: cells[5],\n projectSlug,\n });\n }\n }\n }\n\n return sessions;\n}\n","import { readFile } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { fileExists } from '../utils/fs.js';\nimport { getSessionDb } from './session-db.js';\nimport type { AgentSession, AgentSessionStatus } from './types.js';\n\ninterface SessionRow {\n session_id: string;\n project_slug: string | null;\n assignment_slug: string | null;\n agent: string;\n started: string;\n ended: string | null;\n status: string;\n path: string | null;\n description: string | null;\n transcript_path: string | null;\n pid: number | null;\n pid_started_at: string | null;\n}\n\nfunction rowToSession(row: SessionRow): AgentSession {\n return {\n sessionId: row.session_id,\n projectSlug: row.project_slug ?? null,\n assignmentSlug: row.assignment_slug ?? null,\n agent: row.agent,\n started: row.started,\n ended: row.ended ?? null,\n status: row.status as AgentSessionStatus,\n path: row.path ?? '',\n description: row.description ?? null,\n transcriptPath: row.transcript_path ?? null,\n pid: row.pid ?? null,\n pidStartedAt: row.pid_started_at ?? null,\n };\n}\n\n/**\n * Query sessions for a specific project.\n */\nexport async function parseSessionsIndex(\n _projectDir: string,\n projectSlug: string,\n): Promise<AgentSession[]> {\n const db = getSessionDb();\n const rows = db\n .prepare('SELECT * FROM sessions WHERE project_slug = ? ORDER BY started DESC')\n .all(projectSlug) as SessionRow[];\n return rows.map(rowToSession);\n}\n\n/**\n * Upsert a session keyed on `session_id`.\n *\n * On conflict, non-null fields in the new payload fill in missing values on the\n * existing row (COALESCE). `started` / `created_at` from the first insert are\n * preserved. A session already in a terminal state (`completed` / `stopped`)\n * is NOT revived by re-registration — status only moves forward.\n *\n * Makes registration idempotent across SessionStart hooks, `/track-session`,\n * and grab-assignment all touching the same real session ID.\n */\nexport async function appendSession(\n _projectDir: string,\n session: AgentSession,\n): Promise<void> {\n const db = getSessionDb();\n db.prepare(`\n INSERT INTO sessions (session_id, project_slug, assignment_slug, agent, started, status, path, description, transcript_path, pid, pid_started_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(session_id) DO UPDATE SET\n project_slug = COALESCE(NULLIF(excluded.project_slug, ''), project_slug),\n assignment_slug = COALESCE(NULLIF(excluded.assignment_slug, ''), assignment_slug),\n agent = excluded.agent,\n status = CASE WHEN status IN ('completed','stopped') THEN status ELSE excluded.status END,\n path = COALESCE(NULLIF(excluded.path, ''), path),\n description = COALESCE(NULLIF(excluded.description, ''), description),\n transcript_path = COALESCE(NULLIF(excluded.transcript_path, ''), transcript_path),\n pid = COALESCE(excluded.pid, pid),\n pid_started_at = COALESCE(NULLIF(excluded.pid_started_at, ''), pid_started_at),\n updated_at = datetime('now')\n `).run(\n session.sessionId,\n session.projectSlug ?? null,\n session.assignmentSlug ?? null,\n session.agent,\n session.started,\n session.status,\n session.path,\n session.description ?? null,\n session.transcriptPath ?? null,\n session.pid ?? null,\n session.pidStartedAt ?? null,\n );\n}\n\n/**\n * Update a session's status by sessionId.\n * Sets `ended` timestamp for terminal statuses (completed, stopped).\n */\nexport async function updateSessionStatus(\n _projectDir: string,\n sessionId: string,\n status: AgentSessionStatus,\n): Promise<boolean> {\n const db = getSessionDb();\n const isTerminal = status === 'completed' || status === 'stopped';\n\n const result = isTerminal\n ? db\n .prepare(\n 'UPDATE sessions SET status = ?, ended = datetime(\\'now\\'), updated_at = datetime(\\'now\\') WHERE session_id = ?',\n )\n .run(status, sessionId)\n : db\n .prepare(\n 'UPDATE sessions SET status = ?, updated_at = datetime(\\'now\\') WHERE session_id = ?',\n )\n .run(status, sessionId);\n\n return result.changes > 0;\n}\n\n/**\n * List all sessions across all projects.\n */\nexport async function listAllSessions(_projectsDir: string): Promise<AgentSession[]> {\n const db = getSessionDb();\n const rows = db\n .prepare('SELECT * FROM sessions ORDER BY started DESC')\n .all() as SessionRow[];\n return rows.map(rowToSession);\n}\n\n/**\n * Fetch a single session by its agent-assigned session id.\n * Returns null when no row matches. Throws if initSessionDb() has not run.\n */\nexport function getSessionById(sessionId: string): AgentSession | null {\n const db = getSessionDb();\n const row = db\n .prepare('SELECT * FROM sessions WHERE session_id = ? LIMIT 1')\n .get(sessionId) as SessionRow | undefined;\n return row ? rowToSession(row) : null;\n}\n\n/**\n * List sessions for a specific project, optionally filtered by assignment.\n */\nexport async function listProjectSessions(\n _projectsDir: string,\n projectSlug: string,\n assignmentSlug?: string,\n): Promise<AgentSession[]> {\n const db = getSessionDb();\n\n if (assignmentSlug) {\n const rows = db\n .prepare(\n 'SELECT * FROM sessions WHERE project_slug = ? AND assignment_slug = ? ORDER BY started DESC',\n )\n .all(projectSlug, assignmentSlug) as SessionRow[];\n return rows.map(rowToSession);\n }\n\n const rows = db\n .prepare('SELECT * FROM sessions WHERE project_slug = ? ORDER BY started DESC')\n .all(projectSlug) as SessionRow[];\n return rows.map(rowToSession);\n}\n\n/**\n * Delete sessions by their IDs. Returns the number of rows deleted.\n */\nexport async function deleteSessions(sessionIds: string[]): Promise<number> {\n if (sessionIds.length === 0) return 0;\n const db = getSessionDb();\n const placeholders = sessionIds.map(() => '?').join(', ');\n const result = db\n .prepare(`DELETE FROM sessions WHERE session_id IN (${placeholders})`)\n .run(...sessionIds);\n return result.changes;\n}\n\n// Statuses that imply the working session is done (review means agent finished)\nconst DONE_ASSIGNMENT_STATUSES = new Set(['completed', 'failed', 'review']);\n\n/**\n * Read the status field from an assignment.md frontmatter without full parsing.\n */\nasync function readAssignmentStatusFromPath(\n assignmentMdPath: string,\n): Promise<string | null> {\n if (!(await fileExists(assignmentMdPath))) return null;\n const raw = await readFile(assignmentMdPath, 'utf-8');\n const match = raw.match(/^status:\\s*(.+)$/m);\n return match ? match[1].trim() : null;\n}\n\nasync function readAssignmentStatus(\n projectDir: string,\n assignmentSlug: string,\n): Promise<string | null> {\n return readAssignmentStatusFromPath(\n resolve(projectDir, 'assignments', assignmentSlug, 'assignment.md'),\n );\n}\n\n/**\n * Reconcile active sessions against assignment statuses.\n * Sessions whose assignments have moved to completed/failed/review are\n * marked as completed (or stopped for failed assignments).\n * Standalone sessions (project_slug NULL) are resolved via assignmentsDir.\n * Returns the number of sessions that were updated.\n */\nexport async function reconcileActiveSessions(\n projectsDir: string,\n assignmentsDir?: string,\n): Promise<number> {\n const db = getSessionDb();\n\n // Include standalone sessions (project_slug NULL) when assignmentsDir is provided.\n const activeSessions = db\n .prepare('SELECT * FROM sessions WHERE status = \\'active\\' AND assignment_slug IS NOT NULL')\n .all() as SessionRow[];\n\n if (activeSessions.length === 0) return 0;\n\n // Read assignment statuses from disk. Key is `${projectSlug ?? '__standalone__'}/${slug}`.\n const assignmentStatuses = new Map<string, string>();\n const seen = new Set<string>();\n for (const session of activeSessions) {\n const aslug = session.assignment_slug;\n if (!aslug) continue;\n\n const projectKey = session.project_slug ?? '__standalone__';\n const key = `${projectKey}/${aslug}`;\n if (seen.has(key)) continue;\n seen.add(key);\n\n if (session.project_slug) {\n const status = await readAssignmentStatus(\n resolve(projectsDir, session.project_slug),\n aslug,\n );\n if (status) assignmentStatuses.set(key, status);\n } else if (assignmentsDir) {\n const status = await readAssignmentStatusFromPath(\n resolve(assignmentsDir, aslug, 'assignment.md'),\n );\n if (status) assignmentStatuses.set(key, status);\n }\n }\n\n // Update stale sessions\n let totalUpdated = 0;\n for (const session of activeSessions) {\n const projectKey = session.project_slug ?? '__standalone__';\n const key = `${projectKey}/${session.assignment_slug}`;\n const assignmentStatus = assignmentStatuses.get(key);\n if (!assignmentStatus || !DONE_ASSIGNMENT_STATUSES.has(assignmentStatus)) continue;\n\n const newStatus: AgentSessionStatus =\n assignmentStatus === 'failed' ? 'stopped' : 'completed';\n await updateSessionStatus('', session.session_id, newStatus);\n totalUpdated++;\n }\n\n return totalUpdated;\n}\n\n/**\n * List sessions for a resolved assignment (standalone or project-nested).\n * Standalone: filter by assignment_slug = id AND project_slug IS NULL.\n * Project-nested: filter by project_slug + assignment_slug.\n */\nexport async function listSessionsByAssignment(\n projectSlug: string | null,\n assignmentSlug: string,\n): Promise<AgentSession[]> {\n const db = getSessionDb();\n const rows = projectSlug === null\n ? (db\n .prepare(\n 'SELECT * FROM sessions WHERE assignment_slug = ? AND project_slug IS NULL ORDER BY started DESC',\n )\n .all(assignmentSlug) as SessionRow[])\n : (db\n .prepare(\n 'SELECT * FROM sessions WHERE project_slug = ? AND assignment_slug = ? ORDER BY started DESC',\n )\n .all(projectSlug, assignmentSlug) as SessionRow[]);\n return rows.map(rowToSession);\n}\n","/**\n * Locked Overview copy. Single source of truth for hero, segment, and dialog strings.\n *\n * Both the backend (`api.ts` hero + reason emission) and the frontend\n * (`OverviewHero`, `OverviewSegment`, etc.) import from this module so copy\n * cannot drift between the API payload and what the UI renders.\n */\n\nexport type HeroCopyKey =\n | 'review'\n | 'review.singular'\n | 'ready_to_implement'\n | 'ready_to_implement.singular'\n | 'ready_for_planning'\n | 'ready_for_planning.singular'\n | 'in_progress'\n | 'in_progress.singular'\n | 'draft'\n | 'draft.singular'\n | 'blocked'\n | 'blocked.singular'\n | 'stale'\n | 'stale.singular'\n | 'clean';\n\n/**\n * Hero strings. The `{total}` and `{title}` placeholders are substituted at\n * render time. Singular variants are used when `total === 1`.\n */\nexport const HERO_COPY: Record<HeroCopyKey, string> = {\n review: '{total} items ready for your review',\n 'review.singular': 'Review {title}',\n ready_to_implement: '{total} plans ready to implement — start with {title}',\n 'ready_to_implement.singular': 'Start implementing {title}',\n ready_for_planning: '{total} assignments ready to plan — start with {title}',\n 'ready_for_planning.singular': 'Plan {title}',\n in_progress: 'Resume {title} ({total} in progress)',\n 'in_progress.singular': 'Resume {title}',\n draft: 'Shape your {total} drafts — start with {title}',\n 'draft.singular': 'Shape {title}',\n blocked: 'Unblock {title} ({total} blocked)',\n 'blocked.singular': 'Unblock {title}',\n stale: 'Triage {total} stale items',\n 'stale.singular': 'Triage {title} — sitting stale',\n clean: 'You’re all clear. Nothing needs you right now.',\n};\n\nexport type SegmentId =\n | 'readyForReview'\n | 'readyToImplement'\n | 'readyForPlanning'\n | 'inProgress'\n | 'drafts'\n | 'blocked'\n | 'newestCreated'\n | 'stale';\n\n/** Per-segment row reason (the one-liner under the title). */\nexport const SEGMENT_REASON: Record<SegmentId, string> = {\n readyForReview: 'Ready for your review',\n readyToImplement: 'Plan finalized — ready to implement',\n readyForPlanning: 'Ready to plan',\n inProgress: 'In progress',\n drafts: 'Draft — needs shape',\n blocked: 'Blocked',\n newestCreated: 'Newly created',\n stale: 'Sitting stale',\n};\n\n/** Per-segment empty state copy. */\nexport const SEGMENT_EMPTY: Record<SegmentId, string> = {\n readyForReview: 'No assignments waiting for your review.',\n readyToImplement: 'No plans queued for implementation.',\n readyForPlanning: 'No assignments waiting to be planned.',\n inProgress: 'Nothing actively in progress.',\n drafts: 'No drafts — ideas captured here will live until they’re shaped.',\n blocked: 'Nothing is blocked. Good.',\n newestCreated: 'No assignments created recently.',\n stale: 'No stale work — everything is fresh.',\n};\n\n/** Per-segment header titles. */\nexport const SEGMENT_TITLE: Record<SegmentId, string> = {\n readyForReview: 'Ready for Review',\n readyToImplement: 'Ready to Implement',\n readyForPlanning: 'Ready for Planning',\n inProgress: 'In Progress',\n drafts: 'Drafts',\n blocked: 'Blocked',\n newestCreated: 'Newest Created',\n stale: 'Stale',\n};\n\n/** Dialog + button copy used across Overview components. */\nexport const DIALOG_COPY = {\n claimAsTitle: 'Claim assignments as',\n claimAsHint: 'Used when you claim an assignment from this dashboard. You can change it later in settings.',\n claimAsSubmit: 'Save',\n claimAsRemember: 'Remember this choice',\n quickCommentTitle: 'Add a quick note',\n quickCommentPlaceholder: 'Note…',\n quickCommentSubmit: 'Post',\n bulkArchiveLabel: 'Archive selected',\n bulkClearLabel: 'Clear',\n bulkPartialFailureBanner: 'Some items failed to archive. The list has been refreshed.',\n emptyStateCleanTitle: 'You’re all clear',\n emptyStateCleanCTA: 'Browse projects',\n draftsHeaderCTA: 'Shape →',\n staleLoadMore: 'Load more',\n staleLoadMoreRemaining: '{remaining} remaining',\n recentSessionsEmptyTitle: 'No recent sessions',\n recentSessionsEmptyHint: 'Use /grab-assignment or `syntaur track-session` to register one.',\n recentSessionsCopyPathLabel: 'Copy path',\n recentSessionsCopyPathDisabled: 'Session has no path',\n recentSessionsCopyFallbackHint: 'Press ⌘C to copy',\n} as const;\n\n/** Substitute `{key}` placeholders in a template. */\nexport function formatCopy(\n template: string,\n vars: Record<string, string | number>,\n): string {\n return template.replace(/\\{(\\w+)\\}/g, (_, key) => String(vars[key] ?? `{${key}}`));\n}\n","import { readdir, readFile, unlink } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { ensureDir, fileExists, writeFileForce } from '../utils/fs.js';\nimport { extractFrontmatter, getField } from './parser.js';\nimport type { SessionFileData, SessionKind } from './types.js';\n\nexport function sanitizeSessionName(name: string): string {\n return name.replace(/[^a-zA-Z0-9_-]/g, '-');\n}\n\nfunction nowTimestamp(): string {\n return new Date().toISOString();\n}\n\nexport interface BuildSessionOptions {\n session: string;\n registered: string;\n lastRefreshed: string;\n overrides: Record<string, { project: string; assignment: string }>;\n auto?: boolean;\n kind?: SessionKind;\n pid?: number;\n ports?: number[];\n cwd?: string;\n}\n\nexport function buildSessionContent(opts: BuildSessionOptions): string {\n const lines = [\n '---',\n `session: ${opts.session}`,\n `registered: ${opts.registered}`,\n `last_refreshed: ${opts.lastRefreshed}`,\n ];\n\n if (opts.auto != null) {\n lines.push(`auto: ${opts.auto}`);\n }\n if (opts.kind) {\n lines.push(`kind: ${opts.kind}`);\n }\n if (opts.pid != null) {\n lines.push(`pid: ${opts.pid}`);\n }\n if (opts.ports && opts.ports.length > 0) {\n lines.push(`ports: [${opts.ports.join(', ')}]`);\n }\n if (opts.cwd) {\n lines.push(`cwd: ${opts.cwd}`);\n }\n\n if (Object.keys(opts.overrides).length > 0) {\n lines.push('overrides:');\n for (const [key, val] of Object.entries(opts.overrides)) {\n lines.push(` \"${key}\": { project: \"${val.project}\", assignment: \"${val.assignment}\" }`);\n }\n }\n\n lines.push('---', '');\n return lines.join('\\n');\n}\n\nexport async function registerSession(dir: string, rawName: string): Promise<string> {\n const name = sanitizeSessionName(rawName);\n await ensureDir(dir);\n const now = nowTimestamp();\n const content = buildSessionContent({\n session: name, registered: now, lastRefreshed: now, overrides: {},\n });\n await writeFileForce(resolve(dir, `${name}.md`), content);\n return name;\n}\n\nexport async function listSessionFiles(dir: string): Promise<string[]> {\n if (!(await fileExists(dir))) return [];\n const entries = await readdir(dir);\n return entries\n .filter((f) => f.endsWith('.md'))\n .map((f) => f.replace(/\\.md$/, ''));\n}\n\nexport async function readSessionFile(dir: string, name: string): Promise<SessionFileData | null> {\n const filePath = resolve(dir, `${sanitizeSessionName(name)}.md`);\n if (!(await fileExists(filePath))) return null;\n\n const raw = await readFile(filePath, 'utf-8');\n const [frontmatter] = extractFrontmatter(raw);\n if (!frontmatter) return null;\n\n const session = getField(frontmatter, 'session') ?? name;\n const registered = getField(frontmatter, 'registered') ?? '';\n const lastRefreshed = getField(frontmatter, 'last_refreshed') ?? '';\n\n // Parse overrides block\n const overrides: Record<string, { project: string; assignment: string }> = {};\n const overridesMatch = frontmatter.match(/^overrides:\\n((?:\\s+\".+\\n?)*)/m);\n if (overridesMatch) {\n const overrideLines = overridesMatch[1].matchAll(\n /^\\s+\"([^\"]+)\":\\s*\\{\\s*project:\\s*\"([^\"]+)\",\\s*assignment:\\s*\"([^\"]+)\"\\s*\\}/gm,\n );\n for (const m of overrideLines) {\n overrides[m[1]] = { project: m[2], assignment: m[3] };\n }\n }\n\n const autoField = getField(frontmatter, 'auto');\n const auto = autoField === 'true' ? true : autoField === 'false' ? false : undefined;\n const kind = getField(frontmatter, 'kind') as SessionKind | undefined;\n const pidField = getField(frontmatter, 'pid');\n const pid = pidField ? parseInt(pidField, 10) : undefined;\n const cwdField = getField(frontmatter, 'cwd');\n\n let ports: number[] | undefined;\n const portsMatch = frontmatter.match(/^ports:\\s*\\[([^\\]]*)\\]/m);\n if (portsMatch) {\n ports = portsMatch[1].split(',').map((s) => parseInt(s.trim(), 10)).filter((n) => !isNaN(n));\n }\n\n return {\n session, registered, lastRefreshed, overrides,\n ...(auto != null && { auto }),\n ...(kind && { kind }),\n ...(pid != null && !isNaN(pid) && { pid }),\n ...(ports && ports.length > 0 && { ports }),\n ...(cwdField && { cwd: cwdField }),\n };\n}\n\nexport async function removeSession(dir: string, name: string): Promise<void> {\n const filePath = resolve(dir, `${sanitizeSessionName(name)}.md`);\n if (await fileExists(filePath)) {\n await unlink(filePath);\n }\n}\n\nexport async function updateLastRefreshed(dir: string, name: string): Promise<void> {\n const data = await readSessionFile(dir, name);\n if (!data) return;\n const content = buildSessionContent({ ...data, lastRefreshed: nowTimestamp() });\n await writeFileForce(resolve(dir, `${sanitizeSessionName(name)}.md`), content);\n}\n\nexport async function setOverride(\n dir: string,\n sessionName: string,\n windowIndex: number,\n paneIndex: number,\n assignment: { project: string; assignment: string } | null,\n): Promise<void> {\n const data = await readSessionFile(dir, sessionName);\n if (!data) return;\n const key = `${windowIndex}:${paneIndex}`;\n if (assignment) {\n data.overrides[key] = assignment;\n } else {\n delete data.overrides[key];\n }\n const content = buildSessionContent({ ...data });\n await writeFileForce(resolve(dir, `${sanitizeSessionName(sessionName)}.md`), content);\n}\n\nexport interface RegisterAutoOptions {\n kind: SessionKind;\n pid?: number;\n ports?: number[];\n cwd?: string;\n}\n\nexport async function registerAutoSession(\n dir: string,\n rawName: string,\n opts: RegisterAutoOptions,\n): Promise<string> {\n const name = sanitizeSessionName(rawName);\n await ensureDir(dir);\n const now = nowTimestamp();\n const content = buildSessionContent({\n session: name,\n registered: now,\n lastRefreshed: now,\n overrides: {},\n auto: true,\n kind: opts.kind,\n pid: opts.pid,\n ports: opts.ports,\n cwd: opts.cwd,\n });\n await writeFileForce(resolve(dir, `${name}.md`), content);\n return name;\n}\n","import { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { resolve } from 'node:path';\nimport { realpath, readdir, readFile } from 'node:fs/promises';\nimport { listProjects } from './api.js';\nimport {\n readSessionFile,\n listSessionFiles,\n} from './servers.js';\nimport { extractFrontmatter, getField, getNestedField } from './parser.js';\nimport type {\n TrackedSession,\n TrackedWindow,\n TrackedPane,\n ServersResponse,\n SessionFileData,\n} from './types.js';\n\nconst exec = promisify(execFile);\n\n// --- Cache ---\nlet cache: { data: ServersResponse; expiry: number } | null = null;\nconst CACHE_TTL_MS = 10_000;\n\nexport function clearScanCache(): void {\n cache = null;\n}\n\n// --- Pure parsing functions (exported for testing) ---\n\nexport interface RawPane {\n windowIndex: number;\n windowName: string;\n paneIndex: number;\n command: string;\n cwd: string;\n pid: number;\n}\n\nexport function parseTmuxPaneOutput(output: string): RawPane[] {\n return output\n .trim()\n .split('\\n')\n .filter((line) => line.length > 0)\n .map((line) => {\n const [wi, wn, pi, cmd, cwd, pid] = line.split('|');\n return {\n windowIndex: parseInt(wi, 10),\n windowName: wn,\n paneIndex: parseInt(pi, 10),\n command: cmd,\n cwd,\n pid: parseInt(pid, 10),\n };\n });\n}\n\nexport function findListeningPorts(lsofOutput: string, pids: Set<number>): number[] {\n const ports: number[] = [];\n for (const line of lsofOutput.split('\\n')) {\n const parts = line.trim().split(/\\s+/);\n if (parts.length < 9) continue;\n const pid = parseInt(parts[1], 10);\n if (!pids.has(pid)) continue;\n const tcpAddr = parts.find((p) => p.includes(':') && /:\\d+$/.test(p));\n if (tcpAddr) {\n const port = parseInt(tcpAddr.split(':').pop()!, 10);\n if (!isNaN(port) && !ports.includes(port)) {\n ports.push(port);\n }\n }\n }\n return ports;\n}\n\n// --- Shell helpers ---\n\nexport async function execQuiet(cmd: string, args: string[]): Promise<string> {\n try {\n const { stdout } = await exec(cmd, args);\n return stdout.trim();\n } catch {\n return '';\n }\n}\n\nexport async function checkTmuxAvailable(): Promise<boolean> {\n const result = await execQuiet('which', ['tmux']);\n return result.length > 0;\n}\n\nexport async function sessionAlive(name: string): Promise<boolean> {\n try {\n await exec('tmux', ['has-session', '-t', name]);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function listTmuxPanes(sessionName: string): Promise<RawPane[]> {\n const output = await execQuiet('tmux', [\n 'list-panes', '-s', '-t', sessionName,\n '-F', '#{window_index}|#{window_name}|#{pane_index}|#{pane_current_command}|#{pane_current_path}|#{pane_pid}',\n ]);\n return parseTmuxPaneOutput(output);\n}\n\nexport async function getDescendantPids(rootPid: number, maxDepth: number = 4): Promise<Set<number>> {\n const all = new Set<number>([rootPid]);\n let frontier = [rootPid];\n\n for (let depth = 0; depth < maxDepth && frontier.length > 0; depth++) {\n const nextFrontier: number[] = [];\n for (const pid of frontier) {\n const output = await execQuiet('pgrep', ['-P', String(pid)]);\n for (const line of output.split('\\n')) {\n const child = parseInt(line, 10);\n if (!isNaN(child) && !all.has(child)) {\n all.add(child);\n nextFrontier.push(child);\n }\n }\n }\n frontier = nextFrontier;\n }\n\n return all;\n}\n\nexport async function getLsofOutput(): Promise<string> {\n return execQuiet('lsof', ['-i', '-P', '-n', '-sTCP:LISTEN']);\n}\n\nexport async function getGitInfo(cwd: string): Promise<{ branch: string | null; worktree: boolean }> {\n const branch = await execQuiet('git', ['-C', cwd, 'rev-parse', '--abbrev-ref', 'HEAD']);\n if (!branch) return { branch: null, worktree: false };\n\n const commonDir = await execQuiet('git', ['-C', cwd, 'rev-parse', '--git-common-dir']);\n const gitDir = await execQuiet('git', ['-C', cwd, 'rev-parse', '--git-dir']);\n\n let isWorktree = false;\n if (commonDir && gitDir && commonDir !== gitDir) {\n try {\n const resolvedCommon = await realpath(resolve(cwd, commonDir));\n const resolvedGit = await realpath(resolve(cwd, gitDir));\n isWorktree = resolvedCommon !== resolvedGit;\n } catch {\n isWorktree = false;\n }\n }\n\n return { branch: branch || null, worktree: isWorktree };\n}\n\n// --- Auto-linking ---\n\nexport interface AssignmentLink {\n project: string | null;\n slug: string;\n title: string;\n}\n\nexport interface WorkspaceRecord {\n projectSlug: string | null;\n /** For project-nested, the slug. For standalone, the UUID. */\n assignmentSlug: string;\n assignmentTitle: string;\n worktreePath: string | null;\n branch: string | null;\n}\n\nexport async function loadWorkspaceRecords(\n projectsDir: string,\n assignmentsDir?: string,\n): Promise<WorkspaceRecord[]> {\n const records: WorkspaceRecord[] = [];\n try {\n const projects = await listProjects(projectsDir);\n\n for (const project of projects) {\n const projectAssignmentsDir = resolve(projectsDir, project.slug, 'assignments');\n let slugs: string[];\n try {\n slugs = await readdir(projectAssignmentsDir);\n } catch {\n continue;\n }\n for (const aslug of slugs) {\n const aFile = resolve(projectAssignmentsDir, aslug, 'assignment.md');\n try {\n const raw = await readFile(aFile, 'utf-8');\n const [fm] = extractFrontmatter(raw);\n if (!fm) continue;\n records.push({\n projectSlug: project.slug,\n assignmentSlug: aslug,\n assignmentTitle: getField(fm, 'title') ?? aslug,\n worktreePath: getNestedField(fm, 'workspace', 'worktreePath') ?? null,\n branch: getNestedField(fm, 'workspace', 'branch') ?? null,\n });\n } catch {\n continue;\n }\n }\n }\n } catch {\n // If projects can't be loaded, auto-linking just returns no matches\n }\n\n if (assignmentsDir) {\n try {\n const entries = await readdir(assignmentsDir);\n for (const id of entries) {\n if (id.startsWith('.') || id.startsWith('_')) continue;\n const aFile = resolve(assignmentsDir, id, 'assignment.md');\n try {\n const raw = await readFile(aFile, 'utf-8');\n const [fm] = extractFrontmatter(raw);\n if (!fm) continue;\n records.push({\n projectSlug: null,\n assignmentSlug: id,\n assignmentTitle: getField(fm, 'title') ?? id,\n worktreePath: getNestedField(fm, 'workspace', 'worktreePath') ?? null,\n branch: getNestedField(fm, 'workspace', 'branch') ?? null,\n });\n } catch {\n continue;\n }\n }\n } catch {\n // standalone dir missing is fine\n }\n }\n\n return records;\n}\n\nexport async function resolveAndNormalize(p: string): Promise<string> {\n try {\n const resolved = await realpath(p);\n return resolved.replace(/\\/+$/, '');\n } catch {\n return p.replace(/\\/+$/, '');\n }\n}\n\nexport async function autoLinkPane(\n cwd: string,\n branch: string | null,\n records: WorkspaceRecord[],\n): Promise<AssignmentLink | null> {\n const normalizedCwd = await resolveAndNormalize(cwd);\n for (const rec of records) {\n if (rec.worktreePath) {\n const normalizedWt = await resolveAndNormalize(rec.worktreePath);\n if (normalizedCwd === normalizedWt) {\n return { project: rec.projectSlug, slug: rec.assignmentSlug, title: rec.assignmentTitle };\n }\n }\n }\n if (branch) {\n for (const rec of records) {\n if (rec.branch && rec.branch === branch) {\n return { project: rec.projectSlug, slug: rec.assignmentSlug, title: rec.assignmentTitle };\n }\n }\n }\n return null;\n}\n\n// --- Main scan function ---\n\nasync function scanSession(\n sessionData: SessionFileData,\n lsofOutput: string,\n workspaceRecords: WorkspaceRecord[],\n): Promise<TrackedSession> {\n const now = new Date().toISOString();\n const alive = await sessionAlive(sessionData.session);\n\n if (!alive) {\n return {\n name: sessionData.session,\n kind: 'tmux',\n registered: sessionData.registered,\n lastRefreshed: sessionData.lastRefreshed,\n scannedAt: now,\n alive: false,\n windows: [],\n };\n }\n\n const rawPanes = await listTmuxPanes(sessionData.session);\n\n // Group panes by window\n const windowMap = new Map<number, { name: string; panes: RawPane[] }>();\n for (const rp of rawPanes) {\n if (!windowMap.has(rp.windowIndex)) {\n windowMap.set(rp.windowIndex, { name: rp.windowName, panes: [] });\n }\n windowMap.get(rp.windowIndex)!.panes.push(rp);\n }\n\n // Get git info per unique cwd\n const cwdSet = new Set(rawPanes.map((p) => p.cwd));\n const gitInfoCache = new Map<string, { branch: string | null; worktree: boolean }>();\n for (const cwd of cwdSet) {\n gitInfoCache.set(cwd, await getGitInfo(cwd));\n }\n\n // Get all descendant PIDs for port lookup\n const pidToPaneKey = new Map<number, string>();\n for (const rp of rawPanes) {\n const descendants = await getDescendantPids(rp.pid);\n const key = `${rp.windowIndex}:${rp.paneIndex}`;\n for (const pid of descendants) {\n pidToPaneKey.set(pid, key);\n }\n }\n\n // Find ports per pane\n const panePorts = new Map<string, number[]>();\n for (const line of lsofOutput.split('\\n')) {\n const parts = line.trim().split(/\\s+/);\n if (parts.length < 9) continue;\n const pid = parseInt(parts[1], 10);\n const paneKey = pidToPaneKey.get(pid);\n if (!paneKey) continue;\n const tcpAddr = parts.find((p) => p.includes(':') && /:\\d+$/.test(p));\n if (tcpAddr) {\n const port = parseInt(tcpAddr.split(':').pop()!, 10);\n if (!isNaN(port)) {\n if (!panePorts.has(paneKey)) panePorts.set(paneKey, []);\n const existing = panePorts.get(paneKey)!;\n if (!existing.includes(port)) existing.push(port);\n }\n }\n }\n\n // Build windows — use for-of loop, NOT .map() with async callback\n const windows: TrackedWindow[] = [];\n for (const [windowIndex, { name, panes: rawPanesInWindow }] of windowMap) {\n const panes: TrackedPane[] = [];\n for (const rp of rawPanesInWindow) {\n const key = `${rp.windowIndex}:${rp.paneIndex}`;\n const gitInfo = gitInfoCache.get(rp.cwd) ?? { branch: null, worktree: false };\n const ports = panePorts.get(key) ?? [];\n const urls = ports.map((p) => `http://localhost:${p}`);\n\n const override = sessionData.overrides[key];\n let assignment: AssignmentLink | null = null;\n if (override) {\n const rec = workspaceRecords.find(\n (r) => r.projectSlug === override.project && r.assignmentSlug === override.assignment,\n );\n assignment = {\n project: override.project,\n slug: override.assignment,\n title: rec?.assignmentTitle ?? override.assignment,\n };\n } else {\n assignment = await autoLinkPane(rp.cwd, gitInfo.branch, workspaceRecords);\n }\n\n panes.push({\n index: rp.paneIndex,\n command: rp.command,\n cwd: rp.cwd,\n branch: gitInfo.branch,\n worktree: gitInfo.worktree,\n ports,\n urls,\n assignment,\n });\n }\n\n windows.push({ index: windowIndex, name, panes });\n }\n\n windows.sort((a, b) => a.index - b.index);\n\n return {\n name: sessionData.session,\n kind: 'tmux' as const,\n registered: sessionData.registered,\n lastRefreshed: sessionData.lastRefreshed,\n scannedAt: now,\n alive: true,\n windows,\n };\n}\n\nasync function scanProcessSession(\n sessionData: SessionFileData,\n lsofOutput: string,\n workspaceRecords: WorkspaceRecord[],\n): Promise<TrackedSession> {\n const now = new Date().toISOString();\n\n // Check if the process is still alive\n let alive = false;\n if (sessionData.pid) {\n try {\n process.kill(sessionData.pid, 0);\n alive = true;\n } catch {\n alive = false;\n }\n }\n\n if (!alive || !sessionData.cwd) {\n return {\n name: sessionData.session,\n kind: 'process',\n registered: sessionData.registered,\n lastRefreshed: sessionData.lastRefreshed,\n scannedAt: now,\n alive: false,\n windows: [],\n };\n }\n\n // Re-resolve ports from lsof for the PID\n const ports = findListeningPorts(lsofOutput, new Set([sessionData.pid!]));\n\n const gitInfo = await getGitInfo(sessionData.cwd);\n\n // Honor manual overrides (process sessions use key \"0:0\")\n const override = sessionData.overrides['0:0'];\n let assignment: AssignmentLink | null = null;\n if (override) {\n const rec = workspaceRecords.find(\n (r) => r.projectSlug === override.project && r.assignmentSlug === override.assignment,\n );\n assignment = {\n project: override.project,\n slug: override.assignment,\n title: rec?.assignmentTitle ?? override.assignment,\n };\n } else {\n assignment = await autoLinkPane(sessionData.cwd, gitInfo.branch, workspaceRecords);\n }\n\n const pane: TrackedPane = {\n index: 0,\n command: sessionData.session,\n cwd: sessionData.cwd,\n branch: gitInfo.branch,\n worktree: gitInfo.worktree,\n ports,\n urls: ports.map((p) => `http://localhost:${p}`),\n assignment,\n };\n\n return {\n name: sessionData.session,\n kind: 'process' as const,\n registered: sessionData.registered,\n lastRefreshed: sessionData.lastRefreshed,\n scannedAt: now,\n alive: true,\n windows: [{ index: 0, name: 'process', panes: [pane] }],\n };\n}\n\nexport async function scanAllSessions(\n serversDir: string,\n projectsDir: string,\n options?: { bypassCache?: boolean; assignmentsDir?: string },\n): Promise<ServersResponse> {\n if (!options?.bypassCache && cache && Date.now() < cache.expiry) {\n return cache.data;\n }\n\n const tmuxAvailable = await checkTmuxAvailable();\n const names = await listSessionFiles(serversDir);\n const lsofOutput = await getLsofOutput();\n const workspaceRecords = await loadWorkspaceRecords(projectsDir, options?.assignmentsDir);\n\n const sessions: TrackedSession[] = [];\n for (const name of names) {\n const data = await readSessionFile(serversDir, name);\n if (!data) continue;\n\n if (data.kind === 'process') {\n sessions.push(await scanProcessSession(data, lsofOutput, workspaceRecords));\n } else if (tmuxAvailable) {\n sessions.push(await scanSession(data, lsofOutput, workspaceRecords));\n }\n // Skip tmux-kind entries when tmux is unavailable\n }\n\n const result: ServersResponse = { sessions, tmuxAvailable };\n cache = { data: result, expiry: Date.now() + CACHE_TTL_MS };\n return result;\n}\n\nexport async function scanSingleSession(\n serversDir: string,\n projectsDir: string,\n name: string,\n options?: { assignmentsDir?: string },\n): Promise<TrackedSession | null> {\n const data = await readSessionFile(serversDir, name);\n if (!data) return null;\n\n const lsofOutput = await getLsofOutput();\n const workspaceRecords = await loadWorkspaceRecords(projectsDir, options?.assignmentsDir);\n\n if (data.kind === 'process') {\n return scanProcessSession(data, lsofOutput, workspaceRecords);\n }\n return scanSession(data, lsofOutput, workspaceRecords);\n}\n","import { readdir, readFile, writeFile } from 'node:fs/promises';\nimport { resolve, dirname, basename } from 'node:path';\nimport { getTargetStatus, DEFAULT_STATUSES, DEFAULT_TRANSITION_TABLE, buildTransitionTable } from '../lifecycle/index.js';\nimport { fileExists, writeFileForce } from '../utils/fs.js';\nimport { nowTimestamp } from '../utils/timestamp.js';\nimport { readConfig, type StatusConfig, type StatusTransition } from '../utils/config.js';\nimport { resolvePlaybookSlug } from '../utils/playbooks.js';\nimport { migrateLegacyProjectFiles } from '../utils/fs-migration.js';\nimport { resolveAssignmentById, type ResolvedAssignment } from '../utils/assignment-resolver.js';\n\n/**\n * Thrown by `deleteWorkspace` when references exist and cascade is false.\n * Routers map this to a 409 response carrying the blocker payload.\n */\nexport class WorkspaceBlockedError extends Error {\n readonly blockedBy: { projects: string[]; standalones: string[] };\n constructor(blockedBy: { projects: string[]; standalones: string[] }) {\n super(\n `Workspace is referenced by ${blockedBy.projects.length} project(s) and ${blockedBy.standalones.length} standalone(s).`,\n );\n this.name = 'WorkspaceBlockedError';\n this.blockedBy = blockedBy;\n }\n}\n\n/**\n * Clear a single top-level frontmatter scalar field (regex-replace; assumes\n * the file already starts with `---` and the field exists). Used by the\n * cascade workspace delete to set `workspace:`/`workspaceGroup:` to `null`.\n */\nfunction clearFrontmatterField(content: string, key: string): string {\n const fieldRegex = new RegExp(`^(${escapeRegExp(key)}:)\\\\s*.*$`, 'm');\n return content.replace(fieldRegex, `$1 null`);\n}\n\nfunction setUpdatedField(content: string, value: string): string {\n const fieldRegex = /^(updated:)\\s*.*$/m;\n if (fieldRegex.test(content)) {\n return content.replace(fieldRegex, `$1 \"${value}\"`);\n }\n return content;\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\nimport {\n parseProject,\n parseStatus,\n parseAssignmentFull,\n parsePlan,\n parseScratchpad,\n parseHandoff,\n parseDecisionRecord,\n parseResource,\n parseMemory,\n parsePlaybook,\n parseProgress,\n parseComments,\n extractMermaidGraph,\n} from './parser.js';\nimport { getDashboardHelp } from './help.js';\nimport type {\n AssignmentBoardItem,\n AssignmentDetail,\n AssignmentReference,\n AssignmentSummary,\n AssignmentsBoardResponse,\n AssignmentTransitionAction,\n AttentionItem,\n EditableDocumentResponse,\n EnrichedLink,\n HelpResponse,\n MemoryDetail,\n MemorySummary,\n MemorySummaryWithProject,\n ProjectDetail,\n ProjectSummary,\n OverviewResponse,\n OverviewSegmentId,\n OverviewSegments,\n OverviewHeroRecommendation,\n OverviewHeroKind,\n OverviewSegmentPayload,\n OverviewStaleSegmentPayload,\n ProgressCounts,\n NeedsAttention,\n RecentActivityItem,\n ResourceDetail,\n ResourceSummary,\n ResourceSummaryWithProject,\n PlaybookSummary,\n PlaybookDetail,\n} from './types.js';\nimport { listAllSessions } from './agent-sessions.js';\nimport { SEGMENT_REASON } from './overviewCopy.js';\n\nconst STALE_ASSIGNMENT_MS = 7 * 24 * 60 * 60 * 1000;\nconst RECENT_PROJECTS_LIMIT = 6;\nconst RECENT_ACTIVITY_LIMIT = 12;\nconst RECENT_SESSIONS_LIMIT = 10;\nconst NEWEST_CREATED_LIMIT = 5;\nconst SEGMENT_DISPLAY_CAP = 5;\nconst STALE_LIMIT_DEFAULT = 50;\nconst STALE_LIMIT_MAX = 200;\n\nconst TERMINAL_STATUSES = new Set(['completed', 'failed', 'archived']);\n\nconst STATUS_TO_SEGMENT: Readonly<Record<string, OverviewSegmentId>> = {\n review: 'readyForReview',\n ready_to_implement: 'readyToImplement',\n ready_for_planning: 'readyForPlanning',\n in_progress: 'inProgress',\n draft: 'drafts',\n blocked: 'blocked',\n};\n\nconst HERO_PRIORITY: ReadonlyArray<[OverviewSegmentId, OverviewHeroKind]> = [\n ['readyForReview', 'review'],\n ['readyToImplement', 'ready_to_implement'],\n ['readyForPlanning', 'ready_for_planning'],\n ['inProgress', 'in_progress'],\n ['drafts', 'draft'],\n ['blocked', 'blocked'],\n ['stale', 'stale'],\n];\n\ntype AssignmentRecord = ReturnType<typeof parseAssignmentFull>;\n\ninterface ProjectRecord {\n projectPath: string;\n project: ReturnType<typeof parseProject>;\n assignments: AssignmentRecord[];\n summary: ProjectSummary;\n dependencyGraph: string | null;\n}\n\n/** A standalone assignment lives at `<assignmentsDir>/<uuid>/` and has no containing project. */\ninterface StandaloneRecord {\n assignmentDir: string;\n /** The UUID (folder name). */\n id: string;\n record: AssignmentRecord;\n}\n\nasync function listStandaloneRecords(assignmentsDir: string | undefined): Promise<StandaloneRecord[]> {\n if (!assignmentsDir) return [];\n if (!(await fileExists(assignmentsDir))) return [];\n\n const entries = await readdir(assignmentsDir, { withFileTypes: true });\n const records: StandaloneRecord[] = [];\n\n for (const entry of entries) {\n if (!entry.isDirectory() || entry.name.startsWith('.') || entry.name.startsWith('_')) continue;\n const assignmentDir = resolve(assignmentsDir, entry.name);\n const assignmentMdPath = resolve(assignmentDir, 'assignment.md');\n if (!(await fileExists(assignmentMdPath))) continue;\n try {\n const content = await readFile(assignmentMdPath, 'utf-8');\n const record = parseAssignmentFull(content);\n records.push({ assignmentDir, id: entry.name, record });\n } catch {\n // skip unreadable\n }\n }\n\n records.sort((left, right) => compareTimestamps(right.record.updated, left.record.updated));\n return records;\n}\n\nconst DEFAULT_TRANSITION_DEFINITIONS: Array<{\n command: string;\n label: string;\n description: string;\n requiresReason: boolean;\n}> = [\n {\n command: 'start',\n label: 'Start',\n description: 'Move pending or review work into active execution.',\n requiresReason: false,\n },\n {\n command: 'shape',\n label: 'Shape',\n description: 'Promote a draft assignment to ready_for_planning once the Objective and Acceptance Criteria are fleshed out.',\n requiresReason: false,\n },\n {\n command: 'plan-ready',\n label: 'Plan Ready',\n description: 'Promote a ready_for_planning assignment to ready_to_implement after the plan is written and approved.',\n requiresReason: false,\n },\n {\n command: 'implement',\n label: 'Implement',\n description: 'Move a ready_to_implement assignment into in_progress when coding begins.',\n requiresReason: false,\n },\n {\n command: 'review',\n label: 'Send To Review',\n description: 'Mark the assignment ready for inspection.',\n requiresReason: false,\n },\n {\n command: 'complete',\n label: 'Complete',\n description: 'Mark the assignment done.',\n requiresReason: false,\n },\n {\n command: 'block',\n label: 'Block',\n description: 'Record an exceptional blocker and pause work.',\n requiresReason: true,\n },\n {\n command: 'unblock',\n label: 'Unblock',\n description: 'Resume active work after the blocker is cleared.',\n requiresReason: false,\n },\n {\n command: 'fail',\n label: 'Fail',\n description: 'Mark the assignment as failed when it cannot be completed as planned.',\n requiresReason: false,\n },\n {\n command: 'reopen',\n label: 'Reopen',\n description: 'Reopen a completed or failed assignment to resume work.',\n requiresReason: false,\n },\n];\n\nconst DEFAULT_STATUS_COLORS: Record<string, string> = {\n pending: 'slate',\n in_progress: 'teal',\n blocked: 'amber',\n review: 'violet',\n completed: 'emerald',\n failed: 'rose',\n};\n\nfunction toTitleCase(s: string): string {\n return s.replace(/_/g, ' ').replace(/\\b\\w/g, (c) => c.toUpperCase());\n}\n\nfunction getTransitionDefinitions(config: ResolvedStatusConfig) {\n if (!config.custom) return DEFAULT_TRANSITION_DEFINITIONS;\n // Deduplicate commands from transitions\n const seen = new Set<string>();\n return config.transitions\n .filter((t) => {\n if (seen.has(t.command)) return false;\n seen.add(t.command);\n return true;\n })\n .map((t) => ({\n command: t.command,\n label: t.label ?? toTitleCase(t.command),\n description: t.description ?? `Transition via ${t.command}.`,\n requiresReason: t.requiresReason ?? false,\n }));\n}\n\ninterface ResolvedStatusConfig {\n custom: boolean;\n statuses: Array<{ id: string; label: string; description?: string; color?: string; terminal?: boolean }>;\n order: string[];\n transitions: StatusTransition[];\n transitionTable: Map<string, string>;\n terminalStatuses: ReadonlySet<string>;\n}\n\nlet _cachedConfig: ResolvedStatusConfig | null = null;\n\nexport async function getStatusConfig(): Promise<ResolvedStatusConfig> {\n if (_cachedConfig) return _cachedConfig;\n\n const config = await readConfig();\n\n if (config.statuses) {\n const terminalSet = new Set(\n config.statuses.statuses.filter((s) => s.terminal).map((s) => s.id),\n );\n _cachedConfig = {\n custom: true,\n statuses: config.statuses.statuses,\n order: config.statuses.order,\n transitions: config.statuses.transitions,\n transitionTable: buildTransitionTable(config.statuses.transitions),\n terminalStatuses: terminalSet.size > 0 ? terminalSet : new Set(['completed', 'failed']),\n };\n } else {\n _cachedConfig = {\n custom: false,\n statuses: DEFAULT_STATUSES.map((id) => ({\n id,\n label: toTitleCase(id),\n color: DEFAULT_STATUS_COLORS[id] ?? 'gray',\n terminal: id === 'completed' || id === 'failed',\n })),\n order: [...DEFAULT_STATUSES],\n transitions: Array.from(DEFAULT_TRANSITION_TABLE.entries()).map(([key, to]) => {\n const [from, command] = key.split(':');\n return { from, command, to };\n }),\n transitionTable: DEFAULT_TRANSITION_TABLE,\n terminalStatuses: new Set(['completed', 'failed']),\n };\n }\n\n return _cachedConfig;\n}\n\nexport function clearStatusConfigCache(): void {\n _cachedConfig = null;\n}\n\n/**\n * List all projects with source-first summary data.\n * GET /api/projects\n */\nexport async function listProjects(projectsDir: string): Promise<ProjectSummary[]> {\n const projectRecords = await listProjectRecords(projectsDir);\n return projectRecords.map((record) => record.summary);\n}\n\n/**\n * Read the workspace registry file (~/.syntaur/workspaces.json).\n * Returns an array of explicitly registered workspace names.\n */\nasync function readWorkspaceRegistry(projectsDir: string): Promise<string[]> {\n const registryPath = resolve(dirname(projectsDir), 'workspaces.json');\n try {\n const raw = await readFile(registryPath, 'utf-8');\n const parsed = JSON.parse(raw);\n return Array.isArray(parsed) ? parsed.filter((w): w is string => typeof w === 'string') : [];\n } catch {\n return [];\n }\n}\n\nasync function writeWorkspaceRegistry(projectsDir: string, workspaces: string[]): Promise<void> {\n const registryPath = resolve(dirname(projectsDir), 'workspaces.json');\n await writeFile(registryPath, JSON.stringify(workspaces, null, 2) + '\\n', 'utf-8');\n}\n\n/**\n * List all workspaces: merge registry (explicit) with workspaces discovered from\n * project `workspace:` fields and standalone-assignment `workspaceGroup` fields.\n * Standalones with no `workspaceGroup` contribute to `hasUngrouped`.\n * GET /api/workspaces\n */\nexport async function listWorkspaces(\n projectsDir: string,\n assignmentsDir?: string,\n): Promise<{ workspaces: string[]; hasUngrouped: boolean }> {\n const [projectRecords, registered, standaloneRecords] = await Promise.all([\n listProjectRecords(projectsDir),\n readWorkspaceRegistry(projectsDir),\n listStandaloneRecords(assignmentsDir),\n ]);\n const workspaceSet = new Set<string>(registered);\n let hasUngrouped = false;\n for (const record of projectRecords) {\n if (record.project.workspace) {\n workspaceSet.add(record.project.workspace);\n } else {\n hasUngrouped = true;\n }\n }\n for (const sr of standaloneRecords) {\n if (sr.record.workspaceGroup) {\n workspaceSet.add(sr.record.workspaceGroup);\n } else {\n hasUngrouped = true;\n }\n }\n const workspaces = Array.from(workspaceSet).sort();\n return { workspaces, hasUngrouped };\n}\n\n/**\n * Create an empty workspace by registering it.\n * POST /api/workspaces\n */\nexport async function createWorkspace(projectsDir: string, name: string): Promise<void> {\n const registered = await readWorkspaceRegistry(projectsDir);\n if (!registered.includes(name)) {\n registered.push(name);\n registered.sort();\n await writeWorkspaceRegistry(projectsDir, registered);\n }\n}\n\n/**\n * Delete a workspace from the registry.\n *\n * Modes:\n * - `cascade: false` (default): if any project or standalone still references\n * this workspace, throw `WorkspaceBlockedError` with the blocker lists.\n * Otherwise remove from the registry.\n * - `cascade: true`: rewrite every referencing project's `workspace:` field\n * and every referencing standalone's `workspaceGroup:` field to `null`,\n * then remove the registry entry.\n *\n * Returns `{ rewroteFiles }` so callers (server.ts) can decide whether the\n * explicit registry-level broadcast is still needed (watchers already emit\n * project-updated/assignment-updated for rewritten files).\n *\n * DELETE /api/workspaces/:name[?cascade=true]\n */\nexport async function deleteWorkspace(\n projectsDir: string,\n name: string,\n opts: { cascade?: boolean; assignmentsDir?: string } = {},\n): Promise<{ rewroteFiles: boolean }> {\n const cascade = Boolean(opts.cascade);\n const projectRecords = await listProjectRecords(projectsDir);\n const standaloneRecords = await listStandaloneRecords(opts.assignmentsDir);\n\n const projectsReferencing = projectRecords\n .filter((record) => record.project.workspace === name)\n .map((record) => record.project.slug);\n const standalonesReferencing = standaloneRecords\n .filter((record) => record.record.workspaceGroup === name)\n .map((record) => record.id);\n\n if (projectsReferencing.length + standalonesReferencing.length > 0 && !cascade) {\n throw new WorkspaceBlockedError({\n projects: projectsReferencing,\n standalones: standalonesReferencing,\n });\n }\n\n let rewroteFiles = false;\n if (cascade) {\n const timestamp = nowTimestamp();\n\n for (const slug of projectsReferencing) {\n const path = resolve(projectsDir, slug, 'project.md');\n const raw = await readFile(path, 'utf-8');\n let next = clearFrontmatterField(raw, 'workspace');\n next = setUpdatedField(next, timestamp);\n await writeFileForce(path, next);\n rewroteFiles = true;\n }\n\n for (const id of standalonesReferencing) {\n if (!opts.assignmentsDir) break;\n const path = resolve(opts.assignmentsDir, id, 'assignment.md');\n const raw = await readFile(path, 'utf-8');\n let next = clearFrontmatterField(raw, 'workspaceGroup');\n next = setUpdatedField(next, timestamp);\n await writeFileForce(path, next);\n rewroteFiles = true;\n }\n }\n\n const registered = await readWorkspaceRegistry(projectsDir);\n const filtered = registered.filter((w) => w !== name);\n await writeWorkspaceRegistry(projectsDir, filtered);\n\n return { rewroteFiles };\n}\n\n/**\n * Get overview data used by the app landing page.\n * GET /api/overview?staleLimit=&staleOffset=\n */\nexport async function getOverview(\n projectsDir: string,\n serversDir?: string,\n assignmentsDir?: string,\n options: { staleLimit?: number; staleOffset?: number } = {},\n): Promise<OverviewResponse> {\n const projectRecords = await listProjectRecords(projectsDir);\n const standaloneRecords = await listStandaloneRecords(assignmentsDir);\n const recentActivity = buildRecentActivity(projectRecords, standaloneRecords);\n\n const staleLimit = clamp(\n Number.isFinite(options.staleLimit) ? Number(options.staleLimit) : STALE_LIMIT_DEFAULT,\n 1,\n STALE_LIMIT_MAX,\n );\n const staleOffset = Math.max(0, Number.isFinite(options.staleOffset) ? Number(options.staleOffset) : 0);\n\n const buckets = await buildOverviewSegmentBuckets(projectsDir, projectRecords, standaloneRecords);\n const segments = toOverviewSegments(buckets, { staleLimit, staleOffset });\n const hero = pickOverviewHero(buckets);\n\n let recentSessions: OverviewResponse['recentSessions'] = [];\n try {\n const all = await listAllSessions(projectsDir);\n recentSessions = all.slice(0, RECENT_SESSIONS_LIMIT);\n } catch {\n // Sessions failure should not break overview.\n }\n\n let serverStats: OverviewResponse['serverStats'];\n if (serversDir) {\n try {\n const { scanAllSessions } = await import('./scanner.js');\n const servers = await scanAllSessions(serversDir, projectsDir, { assignmentsDir });\n if (servers.tmuxAvailable) {\n const alive = servers.sessions.filter(s => s.alive).length;\n const totalPorts = servers.sessions.reduce((sum, s) =>\n sum + s.windows.reduce((ws, w) =>\n ws + w.panes.reduce((ps, p) => ps + p.ports.length, 0), 0), 0);\n serverStats = {\n trackedSessions: servers.sessions.length,\n aliveSessions: alive,\n deadSessions: servers.sessions.length - alive,\n totalPorts,\n };\n }\n } catch {\n // Server scanning failure should not break overview\n }\n }\n\n return {\n generatedAt: new Date().toISOString(),\n firstRun: projectRecords.length === 0 && standaloneRecords.length === 0,\n stats: {\n activeProjects: projectRecords.filter((record) => record.summary.status === 'active').length,\n inProgressAssignments: projectRecords.reduce(\n (total, record) => total + (record.summary.progress['in_progress'] ?? 0),\n 0,\n ),\n blockedAssignments: projectRecords.reduce(\n (total, record) => total + (record.summary.progress['blocked'] ?? 0),\n 0,\n ),\n reviewAssignments: projectRecords.reduce(\n (total, record) => total + (record.summary.progress['review'] ?? 0),\n 0,\n ),\n failedAssignments: projectRecords.reduce(\n (total, record) => total + (record.summary.progress['failed'] ?? 0),\n 0,\n ),\n staleAssignments: projectRecords.reduce(\n (total, record) =>\n total + record.assignments.filter((assignment) => isStale(assignment.updated)).length,\n 0,\n ) + standaloneRecords.filter((sr) => isStale(sr.record.updated)).length,\n },\n hero,\n segments,\n recentSessions,\n recentProjects: projectRecords\n .map((record) => record.summary)\n .sort((left, right) => compareTimestamps(right.updated, left.updated))\n .slice(0, RECENT_PROJECTS_LIMIT),\n recentActivity: recentActivity.slice(0, RECENT_ACTIVITY_LIMIT),\n serverStats,\n };\n}\n\n/**\n * Get all assignments across all projects for the global kanban board.\n * GET /api/assignments\n */\nexport async function listAssignmentsBoard(\n projectsDir: string,\n assignmentsDir?: string,\n): Promise<AssignmentsBoardResponse> {\n const projectRecords = await listProjectRecords(projectsDir);\n const projectItems = await Promise.all(\n projectRecords.flatMap(async (record) =>\n Promise.all(\n record.assignments.map(async (assignment) =>\n toAssignmentBoardItem(projectsDir, record, assignment),\n ),\n ),\n ),\n );\n\n const standaloneRecords = await listStandaloneRecords(assignmentsDir);\n const standaloneItems = await Promise.all(\n standaloneRecords.map(async (sr) => toStandaloneBoardItem(sr)),\n );\n\n return {\n generatedAt: new Date().toISOString(),\n assignments: [...projectItems.flat(), ...standaloneItems]\n .sort((left, right) => compareTimestamps(right.updated, left.updated)),\n };\n}\n\nasync function toStandaloneBoardItem(sr: StandaloneRecord): Promise<AssignmentBoardItem> {\n return {\n ...toAssignmentSummary(sr.record),\n projectSlug: null,\n projectTitle: null,\n blockedReason: sr.record.blockedReason,\n projectWorkspace: sr.record.workspaceGroup ?? null,\n availableTransitions: await getStandaloneAvailableTransitions(sr.record),\n };\n}\n\nasync function getStandaloneAvailableTransitions(\n assignment: AssignmentRecord,\n): Promise<AssignmentTransitionAction[]> {\n // Standalone assignments have no dependencies, so skip dependency gating.\n const config = await getStatusConfig();\n const transitionDefs = getTransitionDefinitions(config);\n const actions: AssignmentTransitionAction[] = [];\n\n for (const definition of transitionDefs) {\n let warning: string | null = null;\n if (definition.command === 'start' && !assignment.assignee) {\n warning = 'No assignee set — consider assigning before starting.';\n }\n const target = getTargetStatus(assignment.status, definition.command, config.transitionTable);\n actions.push({\n command: definition.command,\n label: definition.label,\n description: definition.description,\n targetStatus: target ?? definition.command,\n disabled: false,\n disabledReason: null,\n warning,\n requiresReason: definition.requiresReason,\n });\n }\n\n return actions;\n}\n\n/**\n * Get the structured help model used by Help and onboarding surfaces.\n * GET /api/help\n */\nexport async function getHelp(): Promise<HelpResponse> {\n return getDashboardHelp();\n}\n\n/**\n * Get a raw editable document for dashboard editor pages.\n */\nexport async function getEditableDocument(\n projectsDir: string,\n documentType: EditableDocumentResponse['documentType'],\n projectSlug: string,\n assignmentSlug?: string,\n): Promise<EditableDocumentResponse | null> {\n const filePath = getDocumentPath(projectsDir, documentType, projectSlug, assignmentSlug);\n if (!filePath || !(await fileExists(filePath))) {\n return null;\n }\n\n const content = await readFile(filePath, 'utf-8');\n const title = getEditableDocumentTitle(documentType, projectSlug, assignmentSlug);\n\n return {\n documentType,\n title,\n content,\n projectSlug,\n assignmentSlug,\n appendOnly: documentType === 'handoff' || documentType === 'decision-record',\n };\n}\n\n/**\n * Resolve an assignment by UUID (standalone or project-nested) and return its\n * editable document payload for the given type.\n */\nexport async function getEditableDocumentById(\n projectsDir: string,\n assignmentsDir: string,\n documentType: EditableDocumentResponse['documentType'],\n id: string,\n): Promise<EditableDocumentResponse | null> {\n const resolved = await resolveAssignmentById(projectsDir, assignmentsDir, id);\n if (!resolved) return null;\n\n if (!resolved.standalone && resolved.projectSlug) {\n return getEditableDocument(\n projectsDir,\n documentType,\n resolved.projectSlug,\n resolved.assignmentSlug,\n );\n }\n\n const fileName =\n documentType === 'assignment'\n ? 'assignment.md'\n : documentType === 'plan'\n ? 'plan.md'\n : documentType === 'scratchpad'\n ? 'scratchpad.md'\n : documentType === 'handoff'\n ? 'handoff.md'\n : documentType === 'decision-record'\n ? 'decision-record.md'\n : null;\n if (!fileName) return null;\n const filePath = resolve(resolved.assignmentDir, fileName);\n if (!(await fileExists(filePath))) return null;\n\n const content = await readFile(filePath, 'utf-8');\n const label = resolved.id;\n const title =\n documentType === 'assignment'\n ? `Edit Assignment: ${label}`\n : documentType === 'plan'\n ? `Edit Plan: ${label}`\n : documentType === 'scratchpad'\n ? `Edit Scratchpad: ${label}`\n : documentType === 'handoff'\n ? `Append Handoff: ${label}`\n : `Append Decision: ${label}`;\n\n return {\n documentType,\n title,\n content,\n projectSlug: null,\n assignmentSlug: undefined,\n assignmentId: resolved.id,\n appendOnly: documentType === 'handoff' || documentType === 'decision-record',\n };\n}\n\n/**\n * Get full project detail with assignments, resources, and memories.\n * GET /api/projects/:slug\n */\nexport async function getProjectDetail(\n projectsDir: string,\n slug: string,\n): Promise<ProjectDetail | null> {\n const projectPath = resolve(projectsDir, slug);\n const projectMdPath = resolve(projectPath, 'project.md');\n\n if (!(await fileExists(projectMdPath))) {\n return null;\n }\n\n const projectContent = await readFile(projectMdPath, 'utf-8');\n const project = parseProject(projectContent);\n const assignments = await listAssignmentRecords(projectPath);\n const rollup = await buildProjectRollup(projectPath, project, assignments);\n const dependencyGraph = await loadDependencyGraph(projectPath, assignments);\n const resources = await listResources(projectPath);\n const memories = await listMemories(projectPath);\n const updated = getProjectActivityTimestamp(project.updated, assignments);\n\n return {\n slug: project.slug || slug,\n title: project.title,\n status: rollup.status,\n statusOverride: project.statusOverride,\n archived: project.archived,\n archivedAt: project.archivedAt,\n archivedReason: project.archivedReason,\n created: project.created,\n updated,\n tags: project.tags,\n externalIds: project.externalIds,\n body: project.body,\n progress: rollup.progress,\n needsAttention: rollup.needsAttention,\n assignments: assignments\n .map(toAssignmentSummary)\n .sort((left, right) => compareTimestamps(right.updated, left.updated)),\n resources,\n memories,\n dependencyGraph,\n workspace: project.workspace,\n };\n}\n\n/**\n * Get full assignment detail with plan, scratchpad, handoff, and decision record.\n * GET /api/projects/:slug/assignments/:aslug\n */\nexport async function getAssignmentDetail(\n projectsDir: string,\n projectSlug: string,\n assignmentSlug: string,\n): Promise<AssignmentDetail | null> {\n const assignmentDir = resolve(projectsDir, projectSlug, 'assignments', assignmentSlug);\n const assignmentMdPath = resolve(assignmentDir, 'assignment.md');\n\n if (!(await fileExists(assignmentMdPath))) {\n return null;\n }\n\n const assignmentContent = await readFile(assignmentMdPath, 'utf-8');\n const assignment = parseAssignmentFull(assignmentContent);\n\n let projectWorkspace: string | null = null;\n const projectMdPath = resolve(projectsDir, projectSlug, 'project.md');\n if (await fileExists(projectMdPath)) {\n const projectContent = await readFile(projectMdPath, 'utf-8');\n projectWorkspace = parseProject(projectContent).workspace;\n }\n\n let plan: AssignmentDetail['plan'] = null;\n const planPath = resolve(assignmentDir, 'plan.md');\n if (await fileExists(planPath)) {\n const planContent = await readFile(planPath, 'utf-8');\n const parsed = parsePlan(planContent);\n plan = {\n status: parsed.status,\n updated: parsed.updated,\n body: parsed.body,\n };\n }\n\n let scratchpad: AssignmentDetail['scratchpad'] = null;\n const scratchpadPath = resolve(assignmentDir, 'scratchpad.md');\n if (await fileExists(scratchpadPath)) {\n const scratchpadContent = await readFile(scratchpadPath, 'utf-8');\n const parsed = parseScratchpad(scratchpadContent);\n scratchpad = {\n updated: parsed.updated,\n body: parsed.body,\n };\n }\n\n let handoff: AssignmentDetail['handoff'] = null;\n const handoffPath = resolve(assignmentDir, 'handoff.md');\n if (await fileExists(handoffPath)) {\n const handoffContent = await readFile(handoffPath, 'utf-8');\n const parsed = parseHandoff(handoffContent);\n handoff = {\n updated: parsed.updated,\n handoffCount: parsed.handoffCount,\n body: parsed.body,\n };\n }\n\n let decisionRecord: AssignmentDetail['decisionRecord'] = null;\n const decisionRecordPath = resolve(assignmentDir, 'decision-record.md');\n if (await fileExists(decisionRecordPath)) {\n const decisionRecordContent = await readFile(decisionRecordPath, 'utf-8');\n const parsed = parseDecisionRecord(decisionRecordContent);\n decisionRecord = {\n updated: parsed.updated,\n decisionCount: parsed.decisionCount,\n body: parsed.body,\n };\n }\n\n let progress: AssignmentDetail['progress'] = null;\n const progressPath = resolve(assignmentDir, 'progress.md');\n if (await fileExists(progressPath)) {\n const progressContent = await readFile(progressPath, 'utf-8');\n const parsed = parseProgress(progressContent);\n progress = {\n updated: parsed.updated,\n entryCount: parsed.entryCount,\n entries: parsed.entries,\n };\n }\n\n let comments: AssignmentDetail['comments'] = null;\n const commentsPath = resolve(assignmentDir, 'comments.md');\n if (await fileExists(commentsPath)) {\n const commentsContent = await readFile(commentsPath, 'utf-8');\n const parsed = parseComments(commentsContent);\n comments = {\n updated: parsed.updated,\n entryCount: parsed.entryCount,\n entries: parsed.entries,\n };\n }\n\n const detail: AssignmentDetail = {\n id: assignment.id,\n projectSlug,\n slug: assignment.slug || assignmentSlug,\n title: assignment.title,\n status: assignment.status,\n priority: assignment.priority as AssignmentDetail['priority'],\n assignee: assignment.assignee,\n dependsOn: assignment.dependsOn,\n links: assignment.links,\n reverseLinks: [],\n enrichedLinks: [],\n blockedReason: assignment.blockedReason,\n workspace: assignment.workspace,\n projectWorkspace,\n externalIds: assignment.externalIds,\n tags: assignment.tags,\n created: assignment.created,\n updated: assignment.updated,\n body: assignment.body,\n plan,\n scratchpad,\n handoff,\n decisionRecord,\n progress,\n comments,\n referencedBy: [],\n availableTransitions: await getAvailableTransitions(\n projectsDir,\n projectSlug,\n assignmentSlug,\n assignment,\n ),\n };\n\n // Compute reverse links and enrich all links\n const selfSlug = `${projectSlug}/${detail.slug}`;\n const projectRecords = await listProjectRecords(projectsDir);\n\n // Find reverse links: assignments across all projects whose links contain this assignment\n const reverseLinks: string[] = [];\n for (const mr of projectRecords) {\n for (const a of mr.assignments) {\n const qualifiedSlug = `${mr.summary.slug}/${a.slug}`;\n if (qualifiedSlug === selfSlug) continue; // skip self\n if (a.links.includes(selfSlug)) {\n reverseLinks.push(qualifiedSlug);\n }\n }\n }\n\n // Filter self-links and malformed links from forward links\n const isValidLinkFormat = (l: string) => {\n const parts = l.split('/');\n return parts.length === 2 && parts[0].length > 0 && parts[1].length > 0;\n };\n const forwardLinks = assignment.links.filter((l) => l !== selfSlug && isValidLinkFormat(l));\n\n // Deduplicate: if a slug is in both forward and reverse, keep in forward only\n const forwardSet = new Set(forwardLinks);\n const dedupedReverseLinks = reverseLinks.filter((l) => !forwardSet.has(l));\n\n detail.links = forwardLinks;\n detail.reverseLinks = dedupedReverseLinks;\n\n // Build enriched links for the frontend\n const allProjectAssignments = new Map<string, { title: string; status: string }>();\n for (const mr of projectRecords) {\n for (const a of mr.assignments) {\n allProjectAssignments.set(`${mr.summary.slug}/${a.slug}`, {\n title: a.title,\n status: a.status,\n });\n }\n }\n\n const enrichedLinks: EnrichedLink[] = [];\n for (const linkSlug of forwardLinks) {\n const [ms, as] = linkSlug.split('/');\n const info = allProjectAssignments.get(linkSlug);\n enrichedLinks.push({\n slug: linkSlug,\n projectSlug: ms,\n assignmentSlug: as,\n title: info?.title ?? linkSlug,\n status: info?.status ?? 'pending',\n isReverse: false,\n });\n }\n for (const linkSlug of dedupedReverseLinks) {\n const [ms, as] = linkSlug.split('/');\n const info = allProjectAssignments.get(linkSlug);\n enrichedLinks.push({\n slug: linkSlug,\n projectSlug: ms,\n assignmentSlug: as,\n title: info?.title ?? linkSlug,\n status: info?.status ?? 'pending',\n isReverse: true,\n });\n }\n\n detail.enrichedLinks = enrichedLinks;\n\n // Populate referencedBy — assignments that mention this one.\n detail.referencedBy = await computeReferencedBy(\n { id: assignment.id, projectSlug, slug: detail.slug },\n projectsDir,\n undefined,\n );\n\n return detail;\n}\n\nconst REFERENCED_BY_LIMIT = 50;\n\ninterface ReferenceTarget {\n id: string;\n projectSlug: string | null;\n slug: string;\n}\n\n/**\n * Scan every *other* assignment's Todos, progress, comments, and handoff bodies\n * for markdown links that resolve to `target`, and return an aggregated per-source\n * count (capped at 50).\n */\nasync function computeReferencedBy(\n target: ReferenceTarget,\n projectsDir: string,\n assignmentsDir: string | undefined,\n): Promise<AssignmentReference[]> {\n const sources: Array<{\n id: string;\n slug: string;\n title: string;\n projectSlug: string | null;\n assignmentDir: string;\n }> = [];\n\n // project-nested\n const projectRecords = await listProjectRecords(projectsDir);\n for (const rec of projectRecords) {\n for (const a of rec.assignments) {\n sources.push({\n id: a.id,\n slug: a.slug,\n title: a.title,\n projectSlug: rec.summary.slug,\n assignmentDir: resolve(rec.projectPath, 'assignments', a.slug),\n });\n }\n }\n // standalone\n const standaloneRecords = await listStandaloneRecords(assignmentsDir);\n for (const sr of standaloneRecords) {\n sources.push({\n id: sr.id,\n slug: sr.record.slug || sr.id,\n title: sr.record.title,\n projectSlug: null,\n assignmentDir: sr.assignmentDir,\n });\n }\n\n const references: AssignmentReference[] = [];\n for (const source of sources) {\n if (source.id === target.id) continue; // skip self\n const mentions = await countMentionsInAssignment(source.assignmentDir, target);\n if (mentions > 0) {\n references.push({\n sourceId: source.id,\n sourceSlug: source.slug,\n sourceTitle: source.title,\n sourceProjectSlug: source.projectSlug,\n mentions,\n });\n }\n if (references.length >= REFERENCED_BY_LIMIT) break;\n }\n\n return references.slice(0, REFERENCED_BY_LIMIT);\n}\n\nasync function countMentionsInAssignment(\n sourceDir: string,\n target: ReferenceTarget,\n): Promise<number> {\n const bodies: string[] = [];\n\n // Todos section (from assignment.md)\n const assignmentMd = resolve(sourceDir, 'assignment.md');\n if (await fileExists(assignmentMd)) {\n const content = await readFile(assignmentMd, 'utf-8');\n const todosMatch = content.match(/^## Todos\\s*$([\\s\\S]*?)(?=^## |$(?![\\r\\n]))/m);\n if (todosMatch) bodies.push(todosMatch[1]);\n }\n\n for (const filename of ['progress.md', 'comments.md', 'handoff.md']) {\n const path = resolve(sourceDir, filename);\n if (await fileExists(path)) {\n try {\n bodies.push(await readFile(path, 'utf-8'));\n } catch {\n // ignore\n }\n }\n }\n\n let total = 0;\n const patterns = buildLinkPatternsForTarget(target);\n for (const body of bodies) {\n for (const pattern of patterns) {\n const matches = body.match(pattern);\n if (matches) total += matches.length;\n }\n }\n return total;\n}\n\nfunction buildLinkPatternsForTarget(target: ReferenceTarget): RegExp[] {\n const patterns: RegExp[] = [];\n // Standalone absolute route\n patterns.push(new RegExp(`/assignments/${escapeRegExpLocal(target.id)}(?:/|\\\\b)`, 'g'));\n if (target.projectSlug) {\n // Project-nested absolute route\n patterns.push(\n new RegExp(\n `/projects/${escapeRegExpLocal(target.projectSlug)}/assignments/${escapeRegExpLocal(target.slug)}(?:/|\\\\b)`,\n 'g',\n ),\n );\n // Project-nested relative route\n patterns.push(\n new RegExp(`\\\\.\\\\./${escapeRegExpLocal(target.slug)}(?:/|\\\\b)`, 'g'),\n );\n }\n return patterns;\n}\n\nfunction escapeRegExpLocal(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/**\n * Resolve an assignment by UUID (standalone or project-nested) and return its full detail payload.\n * GET /api/assignments/:id\n */\nexport async function getAssignmentDetailById(\n projectsDir: string,\n assignmentsDir: string,\n id: string,\n): Promise<AssignmentDetail | null> {\n const resolved = await resolveAssignmentById(projectsDir, assignmentsDir, id);\n if (!resolved) return null;\n\n if (!resolved.standalone && resolved.projectSlug) {\n // Use the standard detail fetcher, then also scan standalone assignments\n // for backlinks.\n const detail = await getAssignmentDetail(projectsDir, resolved.projectSlug, resolved.assignmentSlug);\n if (!detail) return null;\n detail.referencedBy = await computeReferencedBy(\n { id: detail.id, projectSlug: detail.projectSlug, slug: detail.slug },\n projectsDir,\n assignmentsDir,\n );\n return detail;\n }\n\n // Standalone path — load companion docs directly from the resolved dir.\n const standaloneDetail = await buildStandaloneAssignmentDetail(resolved);\n if (!standaloneDetail) return null;\n standaloneDetail.referencedBy = await computeReferencedBy(\n { id: standaloneDetail.id, projectSlug: null, slug: standaloneDetail.slug },\n projectsDir,\n assignmentsDir,\n );\n return standaloneDetail;\n}\n\nasync function buildStandaloneAssignmentDetail(\n resolved: ResolvedAssignment,\n): Promise<AssignmentDetail | null> {\n const assignmentDir = resolved.assignmentDir;\n const assignmentMdPath = resolve(assignmentDir, 'assignment.md');\n if (!(await fileExists(assignmentMdPath))) return null;\n\n const assignmentContent = await readFile(assignmentMdPath, 'utf-8');\n const assignment = parseAssignmentFull(assignmentContent);\n\n let plan: AssignmentDetail['plan'] = null;\n const planPath = resolve(assignmentDir, 'plan.md');\n if (await fileExists(planPath)) {\n const parsed = parsePlan(await readFile(planPath, 'utf-8'));\n plan = { status: parsed.status, updated: parsed.updated, body: parsed.body };\n }\n\n let scratchpad: AssignmentDetail['scratchpad'] = null;\n const scratchpadPath = resolve(assignmentDir, 'scratchpad.md');\n if (await fileExists(scratchpadPath)) {\n const parsed = parseScratchpad(await readFile(scratchpadPath, 'utf-8'));\n scratchpad = { updated: parsed.updated, body: parsed.body };\n }\n\n let handoff: AssignmentDetail['handoff'] = null;\n const handoffPath = resolve(assignmentDir, 'handoff.md');\n if (await fileExists(handoffPath)) {\n const parsed = parseHandoff(await readFile(handoffPath, 'utf-8'));\n handoff = { updated: parsed.updated, handoffCount: parsed.handoffCount, body: parsed.body };\n }\n\n let decisionRecord: AssignmentDetail['decisionRecord'] = null;\n const decisionRecordPath = resolve(assignmentDir, 'decision-record.md');\n if (await fileExists(decisionRecordPath)) {\n const parsed = parseDecisionRecord(await readFile(decisionRecordPath, 'utf-8'));\n decisionRecord = { updated: parsed.updated, decisionCount: parsed.decisionCount, body: parsed.body };\n }\n\n let progress: AssignmentDetail['progress'] = null;\n const progressPath = resolve(assignmentDir, 'progress.md');\n if (await fileExists(progressPath)) {\n const parsed = parseProgress(await readFile(progressPath, 'utf-8'));\n progress = { updated: parsed.updated, entryCount: parsed.entryCount, entries: parsed.entries };\n }\n\n let comments: AssignmentDetail['comments'] = null;\n const commentsPath = resolve(assignmentDir, 'comments.md');\n if (await fileExists(commentsPath)) {\n const parsed = parseComments(await readFile(commentsPath, 'utf-8'));\n comments = { updated: parsed.updated, entryCount: parsed.entryCount, entries: parsed.entries };\n }\n\n const detail: AssignmentDetail = {\n id: assignment.id,\n projectSlug: null,\n slug: assignment.slug || resolved.id,\n title: assignment.title,\n status: assignment.status,\n priority: assignment.priority as AssignmentDetail['priority'],\n assignee: assignment.assignee,\n dependsOn: [], // standalone cannot declare dependencies\n links: [],\n reverseLinks: [],\n enrichedLinks: [],\n blockedReason: assignment.blockedReason,\n workspace: assignment.workspace,\n projectWorkspace: assignment.workspaceGroup,\n externalIds: assignment.externalIds,\n tags: assignment.tags,\n created: assignment.created,\n updated: assignment.updated,\n body: assignment.body,\n plan,\n scratchpad,\n handoff,\n decisionRecord,\n progress,\n comments,\n referencedBy: [],\n availableTransitions: await getStandaloneAvailableTransitions(assignment),\n };\n\n return detail;\n}\n\n// Guard so legacy-file renames run at most once per `projectsDir` per process\n// lifetime. Keyed by absolute path to tolerate test suites that open multiple\n// sandboxes in the same process.\nconst migratedProjectsDirs = new Set<string>();\n\nasync function listProjectRecords(projectsDir: string): Promise<ProjectRecord[]> {\n if (!(await fileExists(projectsDir))) {\n return [];\n }\n\n if (!migratedProjectsDirs.has(projectsDir)) {\n migratedProjectsDirs.add(projectsDir);\n await migrateLegacyProjectFiles(projectsDir);\n }\n\n const entries = await readdir(projectsDir, { withFileTypes: true });\n const projectDirs = entries.filter((entry) => entry.isDirectory() && !entry.name.startsWith('.'));\n const records: ProjectRecord[] = [];\n\n for (const entry of projectDirs) {\n const projectPath = resolve(projectsDir, entry.name);\n const projectMdPath = resolve(projectPath, 'project.md');\n\n if (!(await fileExists(projectMdPath))) {\n continue;\n }\n\n const projectContent = await readFile(projectMdPath, 'utf-8');\n const project = parseProject(projectContent);\n const assignments = await listAssignmentRecords(projectPath);\n const rollup = await buildProjectRollup(projectPath, project, assignments);\n const updated = getProjectActivityTimestamp(project.updated, assignments);\n\n records.push({\n projectPath,\n project,\n assignments,\n dependencyGraph: await loadDependencyGraph(projectPath, assignments),\n summary: {\n slug: project.slug || entry.name,\n title: project.title,\n status: rollup.status,\n statusOverride: project.statusOverride,\n archived: project.archived,\n archivedAt: project.archivedAt,\n archivedReason: project.archivedReason,\n created: project.created,\n updated,\n tags: project.tags,\n progress: rollup.progress,\n needsAttention: rollup.needsAttention,\n workspace: project.workspace,\n },\n });\n }\n\n records.sort((left, right) => compareTimestamps(right.summary.updated, left.summary.updated));\n return records;\n}\n\nasync function listAssignmentRecords(projectPath: string): Promise<AssignmentRecord[]> {\n const assignmentsDir = resolve(projectPath, 'assignments');\n if (!(await fileExists(assignmentsDir))) {\n return [];\n }\n\n const entries = await readdir(assignmentsDir, { withFileTypes: true });\n const records: AssignmentRecord[] = [];\n\n for (const entry of entries) {\n if (!entry.isDirectory()) {\n continue;\n }\n\n const assignmentMd = resolve(assignmentsDir, entry.name, 'assignment.md');\n if (!(await fileExists(assignmentMd))) {\n continue;\n }\n\n const content = await readFile(assignmentMd, 'utf-8');\n records.push(parseAssignmentFull(content));\n }\n\n records.sort((left, right) => compareTimestamps(right.updated, left.updated));\n return records;\n}\n\nasync function listResources(projectPath: string): Promise<ResourceSummary[]> {\n const resourcesDir = resolve(projectPath, 'resources');\n if (!(await fileExists(resourcesDir))) {\n return [];\n }\n\n const entries = await readdir(resourcesDir, { withFileTypes: true });\n const results: ResourceSummary[] = [];\n\n for (const entry of entries) {\n if (!entry.isFile() || !entry.name.endsWith('.md') || entry.name.startsWith('_')) {\n continue;\n }\n\n const filePath = resolve(resourcesDir, entry.name);\n const content = await readFile(filePath, 'utf-8');\n const parsed = parseResource(content);\n results.push({\n name: parsed.name,\n slug: entry.name.replace(/\\.md$/, ''),\n category: parsed.category,\n source: parsed.source,\n relatedAssignments: parsed.relatedAssignments,\n updated: parsed.updated,\n });\n }\n\n results.sort((left, right) => compareTimestamps(right.updated, left.updated));\n return results;\n}\n\nasync function listMemories(projectPath: string): Promise<MemorySummary[]> {\n const memoriesDir = resolve(projectPath, 'memories');\n if (!(await fileExists(memoriesDir))) {\n return [];\n }\n\n const entries = await readdir(memoriesDir, { withFileTypes: true });\n const results: MemorySummary[] = [];\n\n for (const entry of entries) {\n if (!entry.isFile() || !entry.name.endsWith('.md') || entry.name.startsWith('_')) {\n continue;\n }\n\n const filePath = resolve(memoriesDir, entry.name);\n const content = await readFile(filePath, 'utf-8');\n const parsed = parseMemory(content);\n results.push({\n name: parsed.name,\n slug: entry.name.replace(/\\.md$/, ''),\n source: parsed.source,\n scope: parsed.scope,\n sourceAssignment: parsed.sourceAssignment,\n relatedAssignments: parsed.relatedAssignments,\n updated: parsed.updated,\n });\n }\n\n results.sort((left, right) => compareTimestamps(right.updated, left.updated));\n return results;\n}\n\n/**\n * Walk every project and return its memories enriched with project context.\n *\n * `projectSlug` is the on-disk directory name (used for path-based routes like\n * `/api/projects/:slug/memories/:itemSlug` and the `/projects/:slug/...` UI routes).\n * In typical projects this equals the frontmatter `slug`, but fixtures/legacy projects\n * may differ — and the directory name is what every path-based route resolves against.\n */\nexport async function listAllMemories(\n projectsDir: string,\n): Promise<MemorySummaryWithProject[]> {\n const projectRecords = await listProjectRecords(projectsDir);\n const all: MemorySummaryWithProject[] = [];\n for (const record of projectRecords) {\n const memories = await listMemories(record.projectPath);\n for (const memory of memories) {\n all.push({\n ...memory,\n projectSlug: basename(record.projectPath),\n projectTitle: record.summary.title,\n });\n }\n }\n all.sort((left, right) => compareTimestamps(right.updated, left.updated));\n return all;\n}\n\n/** Walk every project and return its resources enriched with project context. */\nexport async function listAllResources(\n projectsDir: string,\n): Promise<ResourceSummaryWithProject[]> {\n const projectRecords = await listProjectRecords(projectsDir);\n const all: ResourceSummaryWithProject[] = [];\n for (const record of projectRecords) {\n const resources = await listResources(record.projectPath);\n for (const resource of resources) {\n all.push({\n ...resource,\n projectSlug: basename(record.projectPath),\n projectTitle: record.summary.title,\n });\n }\n }\n all.sort((left, right) => compareTimestamps(right.updated, left.updated));\n return all;\n}\n\n/**\n * Resolve a project slug to its on-disk directory path.\n * Tries the dir-name match first (the typical case); falls back to scanning every project\n * for a frontmatter-slug match. Returns `null` when no project matches.\n */\nexport async function resolveProjectPath(\n projectsDir: string,\n projectSlug: string,\n): Promise<string | null> {\n const direct = resolve(projectsDir, projectSlug);\n if (await fileExists(resolve(direct, 'project.md'))) return direct;\n const records = await listProjectRecords(projectsDir);\n const match = records.find((r) => r.summary.slug === projectSlug);\n return match ? match.projectPath : null;\n}\n\nexport async function getMemoryDetail(\n projectsDir: string,\n projectSlug: string,\n itemSlug: string,\n): Promise<MemoryDetail | null> {\n if (itemSlug.startsWith('_')) return null;\n\n const projectRecords = await listProjectRecords(projectsDir);\n // Match by directory name first (the path-based routing convention) and fall back to\n // the frontmatter slug — covers fixtures/legacy projects whose dir name differs from slug.\n const projectRecord = projectRecords.find(\n (p) => basename(p.projectPath) === projectSlug || p.summary.slug === projectSlug,\n );\n if (!projectRecord) return null;\n\n const filePath = resolve(projectRecord.projectPath, 'memories', `${itemSlug}.md`);\n if (!(await fileExists(filePath))) return null;\n\n const content = await readFile(filePath, 'utf-8');\n const parsed = parseMemory(content);\n return {\n name: parsed.name,\n slug: itemSlug,\n source: parsed.source,\n scope: parsed.scope,\n sourceAssignment: parsed.sourceAssignment,\n relatedAssignments: parsed.relatedAssignments,\n updated: parsed.updated,\n created: parsed.created,\n body: parsed.body,\n tags: parsed.tags,\n projectSlug: basename(projectRecord.projectPath),\n projectTitle: projectRecord.summary.title,\n };\n}\n\nexport async function getResourceDetail(\n projectsDir: string,\n projectSlug: string,\n itemSlug: string,\n): Promise<ResourceDetail | null> {\n if (itemSlug.startsWith('_')) return null;\n\n const projectRecords = await listProjectRecords(projectsDir);\n const projectRecord = projectRecords.find(\n (p) => basename(p.projectPath) === projectSlug || p.summary.slug === projectSlug,\n );\n if (!projectRecord) return null;\n\n const filePath = resolve(projectRecord.projectPath, 'resources', `${itemSlug}.md`);\n if (!(await fileExists(filePath))) return null;\n\n const content = await readFile(filePath, 'utf-8');\n const parsed = parseResource(content);\n return {\n name: parsed.name,\n slug: itemSlug,\n category: parsed.category,\n source: parsed.source,\n relatedAssignments: parsed.relatedAssignments,\n updated: parsed.updated,\n created: parsed.created,\n body: parsed.body,\n projectSlug: basename(projectRecord.projectPath),\n projectTitle: projectRecord.summary.title,\n };\n}\n\nasync function loadDependencyGraph(\n projectPath: string,\n assignments: AssignmentRecord[],\n): Promise<string | null> {\n const statusPath = resolve(projectPath, '_status.md');\n if (await fileExists(statusPath)) {\n const statusContent = await readFile(statusPath, 'utf-8');\n const parsed = parseStatus(statusContent);\n const derivedGraph = extractMermaidGraph(parsed.body);\n if (derivedGraph) {\n return derivedGraph;\n }\n }\n\n return buildDependencyGraph(assignments);\n}\n\nasync function buildProjectRollup(\n projectPath: string,\n project: ReturnType<typeof parseProject>,\n assignments: AssignmentRecord[],\n): Promise<{\n progress: ProgressCounts;\n needsAttention: NeedsAttention;\n status: string;\n}> {\n const progress: ProgressCounts = { total: assignments.length };\n\n let openQuestions = 0;\n for (const assignment of assignments) {\n const s = assignment.status;\n progress[s] = (progress[s] ?? 0) + 1;\n openQuestions += await countOpenQuestions(projectPath, assignment.slug);\n }\n\n const needsAttention: NeedsAttention = {\n blockedCount: progress['blocked'] ?? 0,\n failedCount: progress['failed'] ?? 0,\n openQuestions,\n };\n\n let status = 'pending';\n if (project.statusOverride) {\n status = project.statusOverride;\n } else if (project.archived) {\n status = 'archived';\n } else if (progress.total > 0 && (progress['completed'] ?? 0) === progress.total) {\n status = 'completed';\n } else if ((progress['in_progress'] ?? 0) > 0 || (progress['review'] ?? 0) > 0) {\n status = 'active';\n } else if ((progress['failed'] ?? 0) > 0) {\n status = 'failed';\n } else if ((progress['blocked'] ?? 0) > 0) {\n status = 'blocked';\n } else if (progress.total === 0 || (progress['pending'] ?? 0) === progress.total) {\n status = 'pending';\n } else {\n status = 'active';\n }\n\n return { progress, needsAttention, status };\n}\n\nfunction toAssignmentSummary(assignment: AssignmentRecord): AssignmentSummary {\n return {\n id: assignment.id,\n slug: assignment.slug,\n title: assignment.title,\n status: assignment.status,\n priority: assignment.priority as AssignmentSummary['priority'],\n assignee: assignment.assignee,\n dependsOn: assignment.dependsOn,\n links: assignment.links,\n updated: assignment.updated,\n };\n}\n\nasync function toAssignmentBoardItem(\n projectsDir: string,\n projectRecord: ProjectRecord,\n assignment: AssignmentRecord,\n): Promise<AssignmentBoardItem> {\n return {\n ...toAssignmentSummary(assignment),\n projectSlug: projectRecord.summary.slug,\n projectTitle: projectRecord.summary.title,\n blockedReason: assignment.blockedReason,\n projectWorkspace: projectRecord.project.workspace,\n availableTransitions: await getAvailableTransitions(\n projectsDir,\n projectRecord.summary.slug,\n assignment.slug,\n assignment,\n ),\n };\n}\n\nconst DEFAULT_GRAPH_COLORS: Record<string, string> = {\n completed: 'fill:#4ea84f,stroke:#1f6b29,color:#ffffff',\n in_progress: 'fill:#1e6fd9,stroke:#0f3f8f,color:#ffffff',\n pending: 'fill:#c0ccd9,stroke:#738399,color:#163047',\n blocked: 'fill:#db5a3f,stroke:#8d2815,color:#ffffff',\n failed: 'fill:#9f2d2d,stroke:#651616,color:#ffffff',\n review: 'fill:#c6911e,stroke:#7a5a10,color:#ffffff',\n};\n\nfunction buildDependencyGraph(assignments: AssignmentRecord[]): string | null {\n const edges: string[] = [];\n const usedStatuses = new Set<string>();\n\n for (const assignment of assignments) {\n for (const dependency of assignment.dependsOn) {\n const depStatus = findAssignmentStatus(assignments, dependency);\n usedStatuses.add(depStatus);\n usedStatuses.add(assignment.status);\n edges.push(\n ` ${dependency}:::${depStatus} --> ${assignment.slug}:::${assignment.status}`,\n );\n }\n }\n\n if (edges.length === 0) {\n return null;\n }\n\n const classDefs: string[] = [];\n for (const status of usedStatuses) {\n const colors = DEFAULT_GRAPH_COLORS[status] ?? 'fill:#94a3b8,stroke:#64748b,color:#ffffff';\n classDefs.push(` classDef ${status} ${colors}`);\n }\n\n return ['graph TD', ...edges, ...classDefs].join('\\n');\n}\n\nfunction findAssignmentStatus(assignments: AssignmentRecord[], slug: string): string {\n return assignments.find((assignment) => assignment.slug === slug)?.status ?? 'pending';\n}\n\nasync function getAvailableTransitions(\n projectsDir: string,\n projectSlug: string,\n assignmentSlug: string,\n assignment: AssignmentRecord,\n): Promise<AssignmentTransitionAction[]> {\n const config = await getStatusConfig();\n const transitionDefs = getTransitionDefinitions(config);\n const actions: AssignmentTransitionAction[] = [];\n const projectPath = resolve(projectsDir, projectSlug);\n\n for (const definition of transitionDefs) {\n let warning: string | null = null;\n\n if (definition.command === 'start' && !assignment.assignee) {\n warning = 'No assignee set — consider assigning before starting.';\n }\n\n if (definition.command === 'start' && assignment.dependsOn.length > 0) {\n const unmetDependencies = await getUnmetDependencies(projectPath, assignment.dependsOn, config.terminalStatuses);\n if (unmetDependencies.length > 0) {\n warning = `Unmet dependencies: ${unmetDependencies.join(', ')}.`;\n }\n }\n\n const target = getTargetStatus(assignment.status, definition.command, config.transitionTable);\n\n actions.push({\n command: definition.command,\n label: definition.label,\n description: definition.description,\n targetStatus: target ?? definition.command,\n disabled: false,\n disabledReason: null,\n warning,\n requiresReason: definition.requiresReason,\n });\n }\n\n return actions;\n}\n\nasync function getUnmetDependencies(projectPath: string, dependsOn: string[], terminalStatuses?: ReadonlySet<string>): Promise<string[]> {\n const terminals = terminalStatuses ?? new Set(['completed']);\n const unmet: string[] = [];\n\n for (const dependency of dependsOn) {\n const dependencyPath = resolve(projectPath, 'assignments', dependency, 'assignment.md');\n if (!(await fileExists(dependencyPath))) {\n unmet.push(`${dependency} (missing)`);\n continue;\n }\n\n const content = await readFile(dependencyPath, 'utf-8');\n const parsed = parseAssignmentFull(content);\n if (!terminals.has(parsed.status)) {\n unmet.push(`${dependency} (${parsed.status})`);\n }\n }\n\n return unmet;\n}\n\ninterface OverviewSegmentBuckets {\n readyForReview: AttentionItem[];\n readyToImplement: AttentionItem[];\n readyForPlanning: AttentionItem[];\n inProgress: AttentionItem[];\n drafts: AttentionItem[];\n blocked: AttentionItem[];\n newestCreated: AttentionItem[];\n stale: AttentionItem[];\n}\n\nfunction emptyBuckets(): OverviewSegmentBuckets {\n return {\n readyForReview: [],\n readyToImplement: [],\n readyForPlanning: [],\n inProgress: [],\n drafts: [],\n blocked: [],\n newestCreated: [],\n stale: [],\n };\n}\n\nfunction segmentSeverity(segment: OverviewSegmentId): AttentionItem['severity'] {\n switch (segment) {\n case 'blocked':\n return 'high';\n case 'readyForReview':\n return 'medium';\n case 'stale':\n return 'low';\n default:\n return 'medium';\n }\n}\n\nasync function buildOverviewSegmentBuckets(\n projectsDir: string,\n projectRecords: ProjectRecord[],\n standaloneRecords: StandaloneRecord[],\n): Promise<OverviewSegmentBuckets> {\n const now = Date.now();\n const buckets = emptyBuckets();\n // Pool of all non-terminal rows (across primary segments) used to seed\n // `newestCreated`. Each entry remembers its `created` timestamp + the row\n // we'd clone into the segment.\n const newestPool: Array<{ created: string; clone: AttentionItem }> = [];\n\n for (const record of projectRecords) {\n for (const assignment of record.assignments) {\n const segmentId = STATUS_TO_SEGMENT[assignment.status];\n const stale = isStale(assignment.updated);\n const isTerminal = TERMINAL_STATUSES.has(assignment.status);\n const agingMs = Math.max(0, now - parseTimestamp(assignment.updated));\n const baseId = `${record.summary.slug}:${assignment.slug}`;\n const availableTransitions = await getAvailableTransitions(\n projectsDir,\n record.summary.slug,\n assignment.slug,\n assignment,\n );\n\n const shared = {\n projectSlug: record.summary.slug,\n projectTitle: record.summary.title,\n assignmentSlug: assignment.slug,\n assignmentTitle: assignment.title,\n status: assignment.status,\n updated: assignment.updated,\n href: `/projects/${record.summary.slug}/assignments/${assignment.slug}`,\n blockedReason: assignment.blockedReason,\n stale,\n agingMs,\n assignee: assignment.assignee ?? null,\n availableTransitions,\n };\n\n if (segmentId) {\n const reason =\n segmentId === 'blocked' && assignment.blockedReason\n ? assignment.blockedReason\n : SEGMENT_REASON[segmentId];\n const primary: AttentionItem = {\n ...shared,\n id: `${baseId}:${segmentId}`,\n severity: segmentSeverity(segmentId),\n reason,\n segment: segmentId,\n };\n buckets[segmentId].push(primary);\n }\n\n if (stale && !isTerminal) {\n const staleItem: AttentionItem = {\n ...shared,\n id: `${baseId}:stale`,\n severity: 'low',\n reason: SEGMENT_REASON.stale,\n segment: 'stale',\n };\n buckets.stale.push(staleItem);\n }\n\n if (!isTerminal) {\n newestPool.push({\n created: assignment.created,\n clone: {\n ...shared,\n id: `${baseId}:newest`,\n severity: 'low',\n reason: SEGMENT_REASON.newestCreated,\n segment: 'newestCreated',\n },\n });\n }\n }\n }\n\n for (const sr of standaloneRecords) {\n const assignment = sr.record;\n const segmentId = STATUS_TO_SEGMENT[assignment.status];\n const stale = isStale(assignment.updated);\n const isTerminal = TERMINAL_STATUSES.has(assignment.status);\n const agingMs = Math.max(0, now - parseTimestamp(assignment.updated));\n const baseId = `standalone:${sr.id}`;\n const availableTransitions = await getStandaloneAvailableTransitions(assignment);\n\n const shared = {\n projectSlug: null,\n projectTitle: null,\n assignmentSlug: assignment.slug || sr.id,\n assignmentTitle: assignment.title,\n status: assignment.status,\n updated: assignment.updated,\n href: `/assignments/${sr.id}`,\n blockedReason: assignment.blockedReason,\n stale,\n agingMs,\n assignee: assignment.assignee ?? null,\n availableTransitions,\n };\n\n if (segmentId) {\n const reason =\n segmentId === 'blocked' && assignment.blockedReason\n ? assignment.blockedReason\n : SEGMENT_REASON[segmentId];\n buckets[segmentId].push({\n ...shared,\n id: `${baseId}:${segmentId}`,\n severity: segmentSeverity(segmentId),\n reason,\n segment: segmentId,\n });\n }\n\n if (stale && !isTerminal) {\n buckets.stale.push({\n ...shared,\n id: `${baseId}:stale`,\n severity: 'low',\n reason: SEGMENT_REASON.stale,\n segment: 'stale',\n });\n }\n\n if (!isTerminal) {\n newestPool.push({\n created: assignment.created,\n clone: {\n ...shared,\n id: `${baseId}:newest`,\n severity: 'low',\n reason: SEGMENT_REASON.newestCreated,\n segment: 'newestCreated',\n },\n });\n }\n }\n\n newestPool.sort((a, b) => compareTimestamps(b.created, a.created));\n buckets.newestCreated = newestPool.slice(0, NEWEST_CREATED_LIMIT).map((entry) => entry.clone);\n\n for (const key of Object.keys(buckets) as OverviewSegmentId[]) {\n if (key === 'newestCreated') continue; // already sorted by `created`\n if (key === 'stale') {\n buckets[key].sort((a, b) => b.agingMs - a.agingMs);\n continue;\n }\n buckets[key].sort((a, b) => compareTimestamps(b.updated, a.updated));\n }\n\n return buckets;\n}\n\nfunction toOverviewSegments(\n buckets: OverviewSegmentBuckets,\n staleOpts: { staleLimit: number; staleOffset: number },\n): OverviewSegments {\n const sliceCap = (items: AttentionItem[]): OverviewSegmentPayload => ({\n items: items.slice(0, SEGMENT_DISPLAY_CAP),\n total: items.length,\n });\n\n const stale = buckets.stale;\n const staleSlice = stale.slice(staleOpts.staleOffset, staleOpts.staleOffset + staleOpts.staleLimit);\n const staleSegment: OverviewStaleSegmentPayload = {\n items: staleSlice,\n total: stale.length,\n limit: staleOpts.staleLimit,\n offset: staleOpts.staleOffset,\n hasMore: staleOpts.staleOffset + staleSlice.length < stale.length,\n };\n\n return {\n readyForReview: sliceCap(buckets.readyForReview),\n readyToImplement: sliceCap(buckets.readyToImplement),\n readyForPlanning: sliceCap(buckets.readyForPlanning),\n inProgress: sliceCap(buckets.inProgress),\n drafts: sliceCap(buckets.drafts),\n blocked: sliceCap(buckets.blocked),\n newestCreated: { items: buckets.newestCreated, total: buckets.newestCreated.length },\n stale: staleSegment,\n };\n}\n\nfunction pickOverviewHero(buckets: OverviewSegmentBuckets): OverviewHeroRecommendation {\n for (const [segmentId, kind] of HERO_PRIORITY) {\n const bucket = buckets[segmentId];\n if (bucket.length === 0) continue;\n const top = bucket[0];\n const total = bucket.length;\n const copyKey = total === 1 ? `${kind}.singular` : kind;\n return { kind, copyKey, itemId: top.id, total };\n }\n return { kind: 'clean', copyKey: 'clean', itemId: null, total: 0 };\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n if (!Number.isFinite(value)) return min;\n return Math.min(Math.max(value, min), max);\n}\n\nfunction buildRecentActivity(\n projectRecords: ProjectRecord[],\n standaloneRecords: StandaloneRecord[] = [],\n): RecentActivityItem[] {\n const activity: RecentActivityItem[] = [];\n\n for (const record of projectRecords) {\n activity.push({\n id: `project:${record.summary.slug}`,\n type: 'project',\n title: record.summary.title,\n updated: record.summary.updated,\n href: `/projects/${record.summary.slug}`,\n projectSlug: record.summary.slug,\n projectTitle: record.summary.title,\n assignmentSlug: null,\n summary: `Project status is ${record.summary.status}.`,\n });\n\n for (const assignment of record.assignments) {\n activity.push({\n id: `assignment:${record.summary.slug}:${assignment.slug}`,\n type: 'assignment',\n title: assignment.title,\n updated: assignment.updated,\n href: `/projects/${record.summary.slug}/assignments/${assignment.slug}`,\n projectSlug: record.summary.slug,\n projectTitle: record.summary.title,\n assignmentSlug: assignment.slug,\n summary: `Assignment is ${assignment.status} with ${assignment.priority} priority.`,\n });\n }\n }\n\n for (const sr of standaloneRecords) {\n const assignment = sr.record;\n activity.push({\n id: `standalone-assignment:${sr.id}`,\n type: 'assignment',\n title: assignment.title,\n updated: assignment.updated,\n href: `/assignments/${sr.id}`,\n projectSlug: null,\n projectTitle: null,\n assignmentSlug: assignment.slug || sr.id,\n summary: `Standalone assignment is ${assignment.status} with ${assignment.priority} priority.`,\n });\n }\n\n activity.sort((left, right) => compareTimestamps(right.updated, left.updated));\n return activity;\n}\n\nfunction compareTimestamps(left: string, right: string): number {\n return parseTimestamp(left) - parseTimestamp(right);\n}\n\nfunction parseTimestamp(timestamp: string): number {\n const parsed = Date.parse(timestamp);\n return Number.isFinite(parsed) ? parsed : 0;\n}\n\nfunction isStale(updated: string): boolean {\n const timestamp = parseTimestamp(updated);\n if (timestamp === 0) {\n return false;\n }\n return Date.now() - timestamp > STALE_ASSIGNMENT_MS;\n}\n\nfunction countPendingAnswers(body: string): number {\n const matches = body.match(/^\\*\\*A:\\*\\*\\s+pending\\s*$/gim);\n return matches ? matches.length : 0;\n}\n\nasync function countOpenQuestions(\n projectPath: string,\n assignmentSlug: string,\n): Promise<number> {\n const commentsPath = resolve(\n projectPath,\n 'assignments',\n assignmentSlug,\n 'comments.md',\n );\n if (!(await fileExists(commentsPath))) {\n return 0;\n }\n try {\n const content = await readFile(commentsPath, 'utf-8');\n const parsed = parseComments(content);\n return parsed.entries.filter(\n (e) => e.type === 'question' && e.resolved !== true,\n ).length;\n } catch {\n return 0;\n }\n}\n\nfunction getProjectActivityTimestamp(projectUpdated: string, assignments: AssignmentRecord[]): string {\n let latest = projectUpdated;\n for (const assignment of assignments) {\n if (compareTimestamps(assignment.updated, latest) > 0) {\n latest = assignment.updated;\n }\n }\n return latest;\n}\n\nfunction getDocumentPath(\n projectsDir: string,\n documentType: EditableDocumentResponse['documentType'],\n projectSlug: string,\n assignmentSlug?: string,\n): string | null {\n switch (documentType) {\n case 'project':\n return resolve(projectsDir, projectSlug, 'project.md');\n case 'assignment':\n return assignmentSlug\n ? resolve(projectsDir, projectSlug, 'assignments', assignmentSlug, 'assignment.md')\n : null;\n case 'plan':\n return assignmentSlug\n ? resolve(projectsDir, projectSlug, 'assignments', assignmentSlug, 'plan.md')\n : null;\n case 'scratchpad':\n return assignmentSlug\n ? resolve(projectsDir, projectSlug, 'assignments', assignmentSlug, 'scratchpad.md')\n : null;\n case 'handoff':\n return assignmentSlug\n ? resolve(projectsDir, projectSlug, 'assignments', assignmentSlug, 'handoff.md')\n : null;\n case 'decision-record':\n return assignmentSlug\n ? resolve(projectsDir, projectSlug, 'assignments', assignmentSlug, 'decision-record.md')\n : null;\n case 'memory':\n // For memory/resource, the second positional is the item slug.\n return assignmentSlug\n ? resolve(projectsDir, projectSlug, 'memories', `${assignmentSlug}.md`)\n : null;\n case 'resource':\n return assignmentSlug\n ? resolve(projectsDir, projectSlug, 'resources', `${assignmentSlug}.md`)\n : null;\n default:\n return null;\n }\n}\n\nfunction getEditableDocumentTitle(\n documentType: EditableDocumentResponse['documentType'],\n projectSlug: string,\n assignmentSlug?: string,\n): string {\n switch (documentType) {\n case 'project':\n return `Edit Project: ${projectSlug}`;\n case 'assignment':\n return `Edit Assignment: ${assignmentSlug || 'assignment'}`;\n case 'plan':\n return `Edit Plan: ${assignmentSlug || 'assignment'}`;\n case 'scratchpad':\n return `Edit Scratchpad: ${assignmentSlug || 'assignment'}`;\n case 'handoff':\n return `Append Handoff: ${assignmentSlug || 'assignment'}`;\n case 'decision-record':\n return `Append Decision: ${assignmentSlug || 'assignment'}`;\n case 'playbook':\n return `Edit Playbook: ${projectSlug}`;\n case 'memory':\n return `Edit Memory: ${assignmentSlug || 'memory'}`;\n case 'resource':\n return `Edit Resource: ${assignmentSlug || 'resource'}`;\n default:\n return projectSlug;\n }\n}\n\n// --- Playbook API ---\n\nexport async function listPlaybooks(playbooksDir: string): Promise<PlaybookSummary[]> {\n if (!(await fileExists(playbooksDir))) return [];\n\n const config = await readConfig();\n const disabledSet = new Set(config.playbooks.disabled);\n\n const entries = await readdir(playbooksDir, { withFileTypes: true });\n const playbooks: PlaybookSummary[] = [];\n\n for (const entry of entries) {\n if (!entry.isFile() || !entry.name.endsWith('.md') || entry.name.startsWith('_') || entry.name === 'manifest.md') continue;\n\n const filePath = resolve(playbooksDir, entry.name);\n const raw = await readFile(filePath, 'utf-8');\n const parsed = parsePlaybook(raw);\n\n const slug = parsed.slug || entry.name.replace(/\\.md$/, '');\n playbooks.push({\n slug,\n name: parsed.name || slug,\n description: parsed.description,\n whenToUse: parsed.whenToUse,\n tags: parsed.tags,\n created: parsed.created,\n updated: parsed.updated,\n enabled: !disabledSet.has(slug),\n });\n }\n\n return playbooks.sort((a, b) => (b.updated || b.created).localeCompare(a.updated || a.created));\n}\n\nexport async function getPlaybookDetail(\n playbooksDir: string,\n slug: string,\n): Promise<PlaybookDetail | null> {\n const resolved = await resolvePlaybookSlug(playbooksDir, slug);\n if (!resolved) return null;\n\n const config = await readConfig();\n const enabled = !config.playbooks.disabled.includes(resolved.slug);\n\n const parsed = resolved.parsed;\n return {\n slug: resolved.slug,\n name: parsed.name || resolved.slug,\n description: parsed.description,\n whenToUse: parsed.whenToUse,\n tags: parsed.tags,\n created: parsed.created,\n updated: parsed.updated,\n body: parsed.body,\n enabled,\n };\n}\n","export interface AppendTodoLine {\n description: string;\n trace?: string;\n}\n\nfunction setTopLevelField(content: string, key: string, value: string): string {\n const fieldRegex = new RegExp(`^(${key}:)\\\\s*.*$`, 'm');\n if (fieldRegex.test(content)) {\n return content.replace(fieldRegex, `$1 ${value}`);\n }\n return content;\n}\n\nexport function appendTodosToAssignmentBody(\n body: string,\n todos: AppendTodoLine[],\n): string {\n if (todos.length === 0) return body;\n\n const lines = todos.map((t) => {\n const base = `- [ ] ${t.description.trim()}`;\n return t.trace ? `${base} <!-- ${t.trace} -->` : base;\n });\n const block = lines.join('\\n');\n\n const todosHeading = /^## Todos\\s*$/m;\n if (todosHeading.test(body)) {\n return body.replace(\n /(^## Todos[\\s\\S]*?)(\\n## |\\n*$)/m,\n (_m, section, nextHeading) => {\n return `${section.trimEnd()}\\n${block}\\n${nextHeading}`;\n },\n );\n }\n return `${body.trimEnd()}\\n\\n## Todos\\n\\n${block}\\n`;\n}\n\nexport function touchAssignmentUpdated(content: string, timestamp: string): string {\n return setTopLevelField(content, 'updated', `\"${timestamp}\"`);\n}\n","import express from 'express';\nimport { createServer } from 'node:http';\nimport { resolve } from 'node:path';\nimport { writeFile, unlink } from 'node:fs/promises';\nimport { syntaurRoot } from '../utils/paths.js';\nimport { WebSocketServer, WebSocket } from 'ws';\nimport {\n listProjects,\n listAssignmentsBoard,\n listAllMemories,\n listAllResources,\n getProjectDetail,\n getAssignmentDetail,\n getAssignmentDetailById,\n getOverview,\n getHelp,\n getStatusConfig,\n clearStatusConfigCache,\n listWorkspaces,\n createWorkspace,\n deleteWorkspace,\n WorkspaceBlockedError,\n} from './api.js';\nimport { resolveAssignmentById } from '../utils/assignment-resolver.js';\nimport { listSessionsByAssignment, reconcileActiveSessions } from './agent-sessions.js';\nimport { enrichSessions } from './session-liveness.js';\nimport { createWatcher } from './watcher.js';\nimport { fileExists } from '../utils/fs.js';\nimport {\n writeStatusConfig,\n deleteStatusConfig,\n writeThemeConfig,\n deleteThemeConfig,\n writeHotkeyBindingsConfig,\n deleteHotkeyBindingsConfig,\n readConfig,\n getAgents,\n} from '../utils/config.js';\nimport {\n BINDABLE_ACTION_KINDS,\n canonicalizeCombo,\n isBindableActionKind,\n isReservedCombo,\n type BindableActionKind,\n} from '../utils/hotkeysCatalog.js';\nimport {\n isViewMode,\n isSortField,\n isSortDirection,\n isDensity,\n isGrouping,\n isActivity,\n isFilterString,\n type ViewPrefs,\n type ProjectViewPrefs,\n type ViewFilters,\n type ViewPrefsPatch,\n} from '../utils/view-prefs-schema.js';\nimport {\n readViewPrefsFile,\n applyViewPrefsPatch,\n resetViewPrefsFile,\n isViewPrefsDefaults,\n} from '../utils/view-prefs.js';\nimport { withLock } from './todos-locks.js';\nimport { createWriteRouter } from './api-write.js';\nimport { createServersRouter } from './api-servers.js';\nimport { createAgentSessionsRouter } from './api-agent-sessions.js';\nimport { createAgentsRouter } from './api-agents.js';\nimport { createLeasesRouter } from './api-leases.js';\nimport { createPlaybooksRouter } from './api-playbooks.js';\nimport {\n migrateLegacyProjectFiles,\n migrateLegacyConfig,\n summarizeMigration,\n} from '../utils/fs-migration.js';\nimport { createTodosRouter } from './api-todos.js';\nimport { createProjectTodosRouter } from './api-project-todos.js';\nimport { createBackupRouter } from './api-backup.js';\nimport { initSessionDb, migrateFromMarkdown, closeSessionDb } from './session-db.js';\nimport { initLeasesDb, closeLeasesDb } from '../db/leases-db.js';\nimport { startAutodiscovery, stopAutodiscovery } from './autodiscovery.js';\nimport type { WsMessage } from './types.js';\n\nexport interface DashboardServerOptions {\n port: number;\n projectsDir: string;\n /**\n * Absolute path to the standalone assignments directory (`~/.syntaur/assignments/`).\n * Standalone assignments have `project: null` and live in folders named by UUID.\n */\n assignmentsDir: string;\n serversDir: string;\n playbooksDir: string;\n todosDir: string;\n serveStaticUi: boolean;\n /** Absolute path to the built dashboard UI (dashboard/dist). Required when serveStaticUi is true. */\n dashboardDistPath?: string;\n}\n\nexport function createDashboardServer(options: DashboardServerOptions) {\n const { port, projectsDir, assignmentsDir, serversDir, playbooksDir, todosDir, serveStaticUi, dashboardDistPath } = options;\n const app = express();\n const server = createServer(app);\n\n // --- WebSocket ---\n const wss = new WebSocketServer({ noServer: true });\n const clients = new Set<WebSocket>();\n\n server.on('upgrade', (request, socket, head) => {\n if (request.url === '/ws') {\n wss.handleUpgrade(request, socket, head, (ws) => {\n wss.emit('connection', ws, request);\n });\n } else {\n socket.destroy();\n }\n });\n\n wss.on('connection', (ws) => {\n clients.add(ws);\n const connectMsg: WsMessage = {\n type: 'connected',\n timestamp: new Date().toISOString(),\n };\n ws.send(JSON.stringify(connectMsg));\n\n ws.on('close', () => {\n clients.delete(ws);\n });\n });\n\n function broadcast(message: WsMessage): void {\n const data = JSON.stringify(message);\n for (const client of clients) {\n if (client.readyState === WebSocket.OPEN) {\n client.send(data);\n }\n }\n }\n\n // --- Initialize session database ---\n initSessionDb();\n migrateFromMarkdown(projectsDir).catch((err) => {\n console.error('Session migration from markdown failed:', err);\n });\n\n // --- Initialize leases database (shares syntaur.db) ---\n initLeasesDb();\n\n // --- One-shot legacy filesystem migration (pre-v0.2.0 → v0.2.0+) ---\n // Idempotent, non-destructive, reports what it did. Run in the background\n // so startup isn't gated on filesystem work.\n (async () => {\n try {\n const configResult = await migrateLegacyConfig(\n resolve(syntaurRoot(), 'config.md'),\n );\n const projectResult = await migrateLegacyProjectFiles(projectsDir);\n const summary = summarizeMigration(projectResult, configResult);\n if (summary) console.log(summary);\n } catch (err) {\n console.error('Legacy filesystem migration failed:', err);\n }\n })();\n\n // --- JSON body parsing ---\n app.use(express.json());\n\n // --- API Routes ---\n app.get('/api/overview', async (req, res) => {\n try {\n const staleLimitRaw = req.query.staleLimit;\n const staleOffsetRaw = req.query.staleOffset;\n const staleLimit = typeof staleLimitRaw === 'string' ? Number(staleLimitRaw) : undefined;\n const staleOffset = typeof staleOffsetRaw === 'string' ? Number(staleOffsetRaw) : undefined;\n const overview = await getOverview(projectsDir, serversDir, assignmentsDir, {\n staleLimit,\n staleOffset,\n });\n res.json(overview);\n } catch (error) {\n console.error('Error getting overview:', error);\n res.status(500).json({ error: 'Failed to get overview' });\n }\n });\n\n app.get('/api/help', async (_req, res) => {\n try {\n const help = await getHelp();\n res.json(help);\n } catch (error) {\n console.error('Error getting help content:', error);\n res.status(500).json({ error: 'Failed to get help content' });\n }\n });\n\n app.get('/api/config/statuses', async (_req, res) => {\n try {\n const config = await getStatusConfig();\n res.json({\n statuses: config.statuses,\n order: config.order,\n transitions: config.transitions,\n custom: config.custom,\n });\n } catch (error) {\n console.error('Error getting status config:', error);\n res.status(500).json({ error: 'Failed to get status config' });\n }\n });\n\n app.post('/api/config/statuses', async (req, res) => {\n try {\n const { statuses, order, transitions } = req.body;\n if (!Array.isArray(statuses) || !Array.isArray(order) || !Array.isArray(transitions)) {\n res.status(400).json({ error: 'Request body must include statuses, order, and transitions arrays' });\n return;\n }\n await writeStatusConfig({ statuses, order, transitions });\n clearStatusConfigCache();\n const config = await getStatusConfig();\n res.json({\n statuses: config.statuses,\n order: config.order,\n transitions: config.transitions,\n custom: config.custom,\n });\n } catch (error) {\n console.error('Error saving status config:', error);\n res.status(500).json({ error: 'Failed to save status config' });\n }\n });\n\n app.delete('/api/config/statuses', async (_req, res) => {\n try {\n await deleteStatusConfig();\n clearStatusConfigCache();\n const config = await getStatusConfig();\n res.json({\n statuses: config.statuses,\n order: config.order,\n transitions: config.transitions,\n custom: config.custom,\n });\n } catch (error) {\n console.error('Error resetting status config:', error);\n res.status(500).json({ error: 'Failed to reset status config' });\n }\n });\n\n // Theme presets — keep in sync with PRESETS in dashboard/src/themes.ts (canonical client list).\n const THEME_PRESET_SLUGS = ['default', 'ocean', 'forest', 'sunset'] as const;\n const DEFAULT_THEME_PRESET = 'default';\n\n app.get('/api/config/theme', async (_req, res) => {\n try {\n const config = await readConfig();\n const preset = config.theme?.preset ?? DEFAULT_THEME_PRESET;\n res.json({ preset, custom: config.theme !== null });\n } catch (error) {\n console.error('Error getting theme config:', error);\n res.status(500).json({ error: 'Failed to get theme config' });\n }\n });\n\n app.post('/api/config/theme', async (req, res) => {\n try {\n const { preset } = req.body ?? {};\n if (typeof preset !== 'string' || !(THEME_PRESET_SLUGS as readonly string[]).includes(preset)) {\n res.status(400).json({\n error: `preset must be one of: ${THEME_PRESET_SLUGS.join(', ')}`,\n });\n return;\n }\n await writeThemeConfig({ preset });\n res.json({ preset, custom: true });\n } catch (error) {\n console.error('Error saving theme config:', error);\n res.status(500).json({ error: 'Failed to save theme config' });\n }\n });\n\n app.delete('/api/config/theme', async (_req, res) => {\n try {\n await deleteThemeConfig();\n res.json({ preset: DEFAULT_THEME_PRESET, custom: false });\n } catch (error) {\n console.error('Error resetting theme config:', error);\n res.status(500).json({ error: 'Failed to reset theme config' });\n }\n });\n\n app.get('/api/config/hotkeys', async (_req, res) => {\n try {\n const config = await readConfig();\n const bindings = config.hotkeys?.bindings ?? {};\n res.json({ bindings, custom: config.hotkeys !== null });\n } catch (error) {\n console.error('Error getting hotkeys config:', error);\n res.status(500).json({ error: 'Failed to get hotkeys config' });\n }\n });\n\n app.put('/api/config/hotkeys', async (req, res) => {\n try {\n const raw = (req.body && typeof req.body === 'object' ? req.body : {}) as {\n bindings?: unknown;\n };\n const incoming = raw.bindings;\n if (!incoming || typeof incoming !== 'object' || Array.isArray(incoming)) {\n res.status(400).json({ error: 'bindings must be an object keyed by action kind' });\n return;\n }\n const cleaned: Partial<Record<BindableActionKind, string>> = {};\n for (const [rawKind, rawValue] of Object.entries(incoming as Record<string, unknown>)) {\n if (!isBindableActionKind(rawKind)) {\n res.status(400).json({\n error: `unknown action kind \"${rawKind}\" — expected one of: ${BINDABLE_ACTION_KINDS.join(', ')}`,\n });\n return;\n }\n if (typeof rawValue !== 'string' || rawValue.trim() === '') {\n res.status(400).json({ error: `binding for \"${rawKind}\" must be a non-empty string` });\n return;\n }\n const canonical = canonicalizeCombo(rawValue);\n if (!canonical) {\n res.status(400).json({ error: `binding for \"${rawKind}\" is not a valid combo` });\n return;\n }\n if (isReservedCombo(canonical)) {\n res.status(400).json({\n error: `combo \"${canonical}\" is reserved by a built-in shortcut`,\n kind: rawKind,\n combo: canonical,\n });\n return;\n }\n cleaned[rawKind] = canonical;\n }\n // Detect duplicate combos across kinds.\n const seenCombos = new Map<string, BindableActionKind>();\n for (const [kind, combo] of Object.entries(cleaned) as Array<[BindableActionKind, string]>) {\n if (seenCombos.has(combo)) {\n res.status(400).json({\n error: `combo \"${combo}\" is bound to multiple actions`,\n kinds: [seenCombos.get(combo), kind],\n });\n return;\n }\n seenCombos.set(combo, kind);\n }\n\n await writeHotkeyBindingsConfig({ bindings: cleaned });\n res.json({ bindings: cleaned, custom: Object.keys(cleaned).length > 0 });\n } catch (error) {\n console.error('Error saving hotkeys config:', error);\n res.status(500).json({ error: 'Failed to save hotkeys config' });\n }\n });\n\n app.delete('/api/config/hotkeys', async (_req, res) => {\n try {\n await deleteHotkeyBindingsConfig();\n res.json({ bindings: {}, custom: false });\n } catch (error) {\n console.error('Error resetting hotkeys config:', error);\n res.status(500).json({ error: 'Failed to reset hotkeys config' });\n }\n });\n\n const VIEW_PREFS_LOCK = 'vp:global';\n\n const FILTER_KEYS = new Set(['status', 'priority', 'assignee', 'project', 'activity']);\n const GLOBAL_KEYS = new Set(['defaultView', 'sortField', 'sortDirection', 'density', 'grouping', 'filters']);\n const SCOPE_KEYS = new Set(['defaultView', 'sortField', 'sortDirection', 'grouping', 'filters']);\n const ROOT_KEYS = new Set(['global', 'projects']);\n\n function unknownKey(obj: Record<string, unknown>, allowed: Set<string>, where: string): string | null {\n for (const key of Object.keys(obj)) {\n if (!allowed.has(key)) return `unknown key \"${key}\" in ${where}`;\n }\n return null;\n }\n\n function validateFilters(value: unknown): { ok: true; value: ViewFilters } | { ok: false; error: string } {\n if (value === undefined) return { ok: true, value: {} };\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return { ok: false, error: 'filters must be an object' };\n }\n const obj = value as Record<string, unknown>;\n const unknown = unknownKey(obj, FILTER_KEYS, 'filters');\n if (unknown) return { ok: false, error: unknown };\n const out: ViewFilters = {};\n for (const key of ['status', 'priority', 'assignee', 'project']) {\n if (obj[key] !== undefined) {\n if (!isFilterString(obj[key])) return { ok: false, error: `filters.${key} must be a non-empty string` };\n (out as Record<string, string>)[key] = obj[key] as string;\n }\n }\n if (obj.activity !== undefined) {\n if (!isActivity(obj.activity)) return { ok: false, error: 'filters.activity invalid' };\n out.activity = obj.activity;\n }\n return { ok: true, value: out };\n }\n\n function validateGlobalPatch(value: unknown): { ok: true; value: Partial<ViewPrefs> } | { ok: false; error: string } {\n if (value === undefined) return { ok: true, value: {} };\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return { ok: false, error: 'global must be an object' };\n }\n const obj = value as Record<string, unknown>;\n const unknown = unknownKey(obj, GLOBAL_KEYS, 'global');\n if (unknown) return { ok: false, error: unknown };\n const out: Partial<ViewPrefs> = {};\n if (obj.defaultView !== undefined) {\n if (!isViewMode(obj.defaultView)) return { ok: false, error: 'global.defaultView invalid' };\n out.defaultView = obj.defaultView;\n }\n if (obj.sortField !== undefined) {\n if (!isSortField(obj.sortField)) return { ok: false, error: 'global.sortField invalid' };\n out.sortField = obj.sortField;\n }\n if (obj.sortDirection !== undefined) {\n if (!isSortDirection(obj.sortDirection)) return { ok: false, error: 'global.sortDirection invalid' };\n out.sortDirection = obj.sortDirection;\n }\n if (obj.density !== undefined) {\n if (!isDensity(obj.density)) return { ok: false, error: 'global.density invalid' };\n out.density = obj.density;\n }\n if (obj.grouping !== undefined) {\n if (!isGrouping(obj.grouping)) return { ok: false, error: 'global.grouping invalid' };\n out.grouping = obj.grouping;\n }\n if (obj.filters !== undefined) {\n const f = validateFilters(obj.filters);\n if (!f.ok) return f;\n out.filters = f.value;\n }\n return { ok: true, value: out };\n }\n\n function validateScopePatch(value: unknown): { ok: true; value: ProjectViewPrefs } | { ok: false; error: string } {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return { ok: false, error: 'project scope must be an object' };\n }\n const obj = value as Record<string, unknown>;\n if (obj.density !== undefined) {\n return { ok: false, error: 'density cannot be set per-project (global only)' };\n }\n const unknown = unknownKey(obj, SCOPE_KEYS, 'project scope');\n if (unknown) return { ok: false, error: unknown };\n const out: ProjectViewPrefs = {};\n if (obj.defaultView !== undefined) {\n if (!isViewMode(obj.defaultView)) return { ok: false, error: 'defaultView invalid' };\n out.defaultView = obj.defaultView;\n }\n if (obj.sortField !== undefined) {\n if (!isSortField(obj.sortField)) return { ok: false, error: 'sortField invalid' };\n out.sortField = obj.sortField;\n }\n if (obj.sortDirection !== undefined) {\n if (!isSortDirection(obj.sortDirection)) return { ok: false, error: 'sortDirection invalid' };\n out.sortDirection = obj.sortDirection;\n }\n if (obj.grouping !== undefined) {\n if (!isGrouping(obj.grouping)) return { ok: false, error: 'grouping invalid' };\n out.grouping = obj.grouping;\n }\n if (obj.filters !== undefined) {\n const f = validateFilters(obj.filters);\n if (!f.ok) return f;\n out.filters = f.value;\n }\n return { ok: true, value: out };\n }\n\n function validateViewPrefsPatch(body: unknown): { ok: true; value: ViewPrefsPatch } | { ok: false; error: string } {\n if (!body || typeof body !== 'object' || Array.isArray(body)) {\n return { ok: false, error: 'body must be an object with optional `global` and/or `projects` keys' };\n }\n const obj = body as Record<string, unknown>;\n const unknownRoot = unknownKey(obj, ROOT_KEYS, 'request body');\n if (unknownRoot) return { ok: false, error: unknownRoot };\n const patch: ViewPrefsPatch = {};\n const g = validateGlobalPatch(obj.global);\n if (!g.ok) return g;\n if (Object.keys(g.value).length > 0) patch.global = g.value;\n if (obj.projects !== undefined) {\n if (!obj.projects || typeof obj.projects !== 'object' || Array.isArray(obj.projects)) {\n return { ok: false, error: 'projects must be an object keyed by scope' };\n }\n const projectsOut: Record<string, ProjectViewPrefs> = {};\n for (const [scope, scopePatch] of Object.entries(obj.projects as Record<string, unknown>)) {\n if (typeof scope !== 'string' || scope.length === 0) {\n return { ok: false, error: 'project scope keys must be non-empty strings' };\n }\n const sp = validateScopePatch(scopePatch);\n if (!sp.ok) return { ok: false, error: `projects[\"${scope}\"]: ${sp.error}` };\n projectsOut[scope] = sp.value;\n }\n if (Object.keys(projectsOut).length > 0) patch.projects = projectsOut;\n }\n return { ok: true, value: patch };\n }\n\n app.get('/api/view-prefs', async (_req, res) => {\n try {\n const file = await readViewPrefsFile();\n res.json({ ...file, custom: !isViewPrefsDefaults(file) });\n } catch (error) {\n console.error('Error reading view-prefs:', error);\n res.status(500).json({ error: 'Failed to read view-prefs' });\n }\n });\n\n app.post('/api/view-prefs', async (req, res) => {\n const result = validateViewPrefsPatch(req.body);\n if (!result.ok) {\n res.status(400).json({ error: result.error });\n return;\n }\n try {\n const file = await withLock(VIEW_PREFS_LOCK, () => applyViewPrefsPatch(result.value));\n res.json({ ...file, custom: !isViewPrefsDefaults(file) });\n } catch (error) {\n console.error('Error saving view-prefs:', error);\n res.status(500).json({ error: 'Failed to save view-prefs' });\n }\n });\n\n app.delete('/api/view-prefs', async (_req, res) => {\n try {\n await withLock(VIEW_PREFS_LOCK, () => resetViewPrefsFile());\n const file = await readViewPrefsFile();\n res.json({ ...file, custom: false });\n } catch (error) {\n console.error('Error resetting view-prefs:', error);\n res.status(500).json({ error: 'Failed to reset view-prefs' });\n }\n });\n\n app.get('/api/projects', async (req, res) => {\n try {\n let projects = await listProjects(projectsDir);\n const workspaceParam = req.query.workspace as string | undefined;\n if (workspaceParam) {\n if (workspaceParam === '_ungrouped') {\n projects = projects.filter((m) => m.workspace === null);\n } else {\n projects = projects.filter((m) => m.workspace === workspaceParam);\n }\n }\n res.json(projects);\n } catch (error) {\n console.error('Error listing projects:', error);\n res.status(500).json({ error: 'Failed to list projects' });\n }\n });\n\n app.get('/api/workspaces', async (_req, res) => {\n try {\n const result = await listWorkspaces(projectsDir, assignmentsDir);\n res.json(result);\n } catch (error) {\n console.error('Error listing workspaces:', error);\n res.status(500).json({ error: 'Failed to list workspaces' });\n }\n });\n\n app.post('/api/workspaces', async (req, res) => {\n try {\n const { name } = req.body;\n if (!name || typeof name !== 'string' || !/^[a-z0-9][a-z0-9-]*$/.test(name)) {\n res.status(400).json({ error: 'Invalid workspace name. Use lowercase letters, numbers, and hyphens.' });\n return;\n }\n await createWorkspace(projectsDir, name);\n broadcast({ type: 'project-updated', projectSlug: '', timestamp: new Date().toISOString() });\n res.json({ name });\n } catch (error) {\n console.error('Error creating workspace:', error);\n res.status(500).json({ error: 'Failed to create workspace' });\n }\n });\n\n app.delete('/api/workspaces/:name', async (req, res) => {\n try {\n const cascade = req.query.cascade === 'true';\n const result = await deleteWorkspace(projectsDir, req.params.name, {\n cascade,\n assignmentsDir,\n });\n // Watchers emit project-updated / assignment-updated for any rewritten\n // file; only broadcast explicitly when the delete touched solely the\n // registry (which sits outside any watched tree).\n if (!result.rewroteFiles) {\n broadcast({ type: 'project-updated', projectSlug: '', timestamp: new Date().toISOString() });\n }\n res.json({ ok: true, rewroteFiles: result.rewroteFiles });\n } catch (error) {\n if (error instanceof WorkspaceBlockedError) {\n res.status(409).json({ error: error.message, blockedBy: error.blockedBy });\n return;\n }\n console.error('Error deleting workspace:', error);\n res.status(500).json({ error: 'Failed to delete workspace' });\n }\n });\n\n app.get('/api/assignments', async (req, res) => {\n try {\n const result = await listAssignmentsBoard(projectsDir, assignmentsDir);\n const workspaceParam = req.query.workspace as string | undefined;\n if (workspaceParam) {\n if (workspaceParam === '_ungrouped') {\n result.assignments = result.assignments.filter((a) => a.projectWorkspace === null);\n } else {\n result.assignments = result.assignments.filter((a) => a.projectWorkspace === workspaceParam);\n }\n }\n res.json(result);\n } catch (error) {\n console.error('Error listing assignments:', error);\n res.status(500).json({ error: 'Failed to list assignments' });\n }\n });\n\n app.get('/api/projects/:slug', async (req, res) => {\n try {\n const detail = await getProjectDetail(projectsDir, req.params.slug);\n if (!detail) {\n res.status(404).json({ error: `Project \"${req.params.slug}\" not found` });\n return;\n }\n res.json(detail);\n } catch (error) {\n console.error('Error getting project detail:', error);\n res.status(500).json({ error: 'Failed to get project detail' });\n }\n });\n\n app.get('/api/assignments/:id', async (req, res) => {\n try {\n const detail = await getAssignmentDetailById(projectsDir, assignmentsDir, req.params.id);\n if (!detail) {\n res.status(404).json({ error: `Assignment \"${req.params.id}\" not found` });\n return;\n }\n res.json(detail);\n } catch (error) {\n console.error('Error getting assignment by id:', error);\n res.status(500).json({ error: 'Failed to get assignment' });\n }\n });\n\n app.get('/api/assignments/:id/sessions', async (req, res) => {\n try {\n const resolved = await resolveAssignmentById(projectsDir, assignmentsDir, req.params.id);\n if (!resolved) {\n res.status(404).json({ error: `Assignment \"${req.params.id}\" not found` });\n return;\n }\n await reconcileActiveSessions(projectsDir, assignmentsDir);\n const sessions = await listSessionsByAssignment(\n resolved.standalone ? null : resolved.projectSlug,\n resolved.standalone ? resolved.id : resolved.assignmentSlug,\n );\n const agents = getAgents(await readConfig());\n res.json({\n sessions: enrichSessions(sessions, agents),\n generatedAt: new Date().toISOString(),\n });\n } catch (error) {\n console.error('Error listing sessions by id:', error);\n res.status(500).json({ error: 'Failed to list sessions' });\n }\n });\n\n app.get('/api/projects/:slug/assignments/:aslug', async (req, res) => {\n try {\n const detail = await getAssignmentDetail(\n projectsDir,\n req.params.slug,\n req.params.aslug,\n );\n if (!detail) {\n res.status(404).json({\n error: `Assignment \"${req.params.aslug}\" not found in project \"${req.params.slug}\"`,\n });\n return;\n }\n res.json(detail);\n } catch (error) {\n console.error('Error getting assignment detail:', error);\n res.status(500).json({ error: 'Failed to get assignment detail' });\n }\n });\n\n // --- Write API (create projects/assignments) ---\n app.use(createWriteRouter(projectsDir, assignmentsDir, todosDir));\n\n // --- Servers API ---\n app.use('/api/servers', createServersRouter(serversDir, projectsDir, assignmentsDir));\n\n // --- Leases API ---\n app.use('/api/leases', createLeasesRouter(broadcast));\n\n // --- Agent Sessions API ---\n app.use('/api/agent-sessions', createAgentSessionsRouter(projectsDir, broadcast, assignmentsDir));\n\n // --- Agents Config API ---\n app.use('/api/config/agents', createAgentsRouter());\n\n // --- Playbooks API ---\n app.use('/api/playbooks', createPlaybooksRouter(playbooksDir));\n\n // --- Memories / Resources (cross-project list) ---\n app.get('/api/memories', async (_req, res) => {\n try {\n const memories = await listAllMemories(projectsDir);\n res.json({ generatedAt: new Date().toISOString(), memories });\n } catch (error) {\n console.error('Error listing memories:', error);\n res.status(500).json({ error: `Failed to load memories: ${(error as Error).message}` });\n }\n });\n\n app.get('/api/resources', async (_req, res) => {\n try {\n const resources = await listAllResources(projectsDir);\n res.json({ generatedAt: new Date().toISOString(), resources });\n } catch (error) {\n console.error('Error listing resources:', error);\n res.status(500).json({ error: `Failed to load resources: ${(error as Error).message}` });\n }\n });\n\n // --- Todos API ---\n app.use('/api/todos', createTodosRouter(todosDir, broadcast, projectsDir));\n app.use('/api/projects/:projectId/todos', createProjectTodosRouter(projectsDir, broadcast, todosDir));\n\n // --- Backup API ---\n app.use('/api/backup', createBackupRouter());\n\n // --- Static files (production only) ---\n // Only serve the built asset directory as static — never let express.static\n // try to resolve arbitrary client-side route paths (e.g. /assignments/:id)\n // as files, which makes `send` emit NotFoundError on every SPA refresh.\n if (serveStaticUi && dashboardDistPath) {\n // `dotfiles: 'allow'` is required because the resolved package path may\n // live under a dot-prefixed directory (npm/npx caches under ~/.npm,\n // installs under ~/.nvm, ~/.local, etc.). The default 'ignore' makes\n // `send` 404 every file with a dot-component anywhere in the path.\n const sendOpts = { dotfiles: 'allow' as const };\n\n app.use('/assets', express.static(resolve(dashboardDistPath, 'assets'), sendOpts));\n // Files copied from dashboard/public/ (logo, favicon, etc.) land at the\n // dist root; serve them with fallthrough so missing paths still hit the\n // SPA fallback below. `index: false` prevents express.static from serving\n // index.html for \"/\" — that's the SPA fallback's job.\n app.use(express.static(dashboardDistPath, { ...sendOpts, index: false, fallthrough: true }));\n\n // SPA fallback: serve index.html for all non-API, non-WS, non-asset routes.\n // Express 5 requires named wildcards; use '{*path}' instead of '*'.\n app.get('{*path}', async (req: any, res: any) => {\n if (\n req.path.startsWith('/api') ||\n req.path === '/ws' ||\n req.path.startsWith('/assets')\n ) {\n res.status(404).json({ error: 'Not Found' });\n return;\n }\n const indexPath = resolve(dashboardDistPath, 'index.html');\n if (!(await fileExists(indexPath))) {\n res.status(503).send(\n 'Dashboard not built. Run \"npm run build:dashboard\" first.',\n );\n return;\n }\n res.sendFile(indexPath, sendOpts, (err: Error | null) => {\n if (err) {\n console.error('Error sending dashboard index.html:', err);\n if (!res.headersSent) res.status(500).send('Dashboard load error');\n }\n });\n });\n }\n\n // --- File watcher ---\n let watcherHandle: { close: () => Promise<void> } | null = null;\n\n return {\n async start(): Promise<void> {\n watcherHandle = createWatcher({\n projectsDir,\n assignmentsDir,\n serversDir,\n playbooksDir,\n todosDir,\n dbPath: resolve(syntaurRoot(), 'syntaur.db'),\n onMessage: broadcast,\n });\n\n startAutodiscovery({ serversDir, projectsDir, assignmentsDir, excludePids: new Set([process.pid]) });\n\n return new Promise<void>((resolvePromise, reject) => {\n server.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EADDRINUSE') {\n reject(new Error(\n `Port ${port} is already in use. Use --port <number> to specify a different port.`,\n ));\n } else {\n reject(err);\n }\n });\n server.listen(port, () => {\n const portFile = resolve(syntaurRoot(), 'dashboard-port');\n writeFile(portFile, String(port), 'utf-8').catch(() => {});\n resolvePromise();\n });\n });\n },\n\n async stop(): Promise<void> {\n await stopAutodiscovery();\n if (watcherHandle) {\n await watcherHandle.close();\n }\n closeSessionDb();\n closeLeasesDb();\n for (const client of clients) {\n client.terminate();\n }\n clients.clear();\n const portFile = resolve(syntaurRoot(), 'dashboard-port');\n await unlink(portFile).catch(() => {});\n server.closeAllConnections?.();\n return new Promise<void>((resolvePromise) => {\n server.close(() => resolvePromise());\n });\n },\n\n get port(): number {\n return port;\n },\n };\n}\n","import { execFileSync } from 'node:child_process';\nimport { statSync } from 'node:fs';\nimport type { AgentConfig } from '../utils/config.js';\nimport type { AgentSession, AgentSessionWithLiveness } from './types.js';\n\nconst FIVE_MINUTES_MS = 5 * 60 * 1000;\n\n/**\n * Injectable dependencies for the liveness probe so tests can supply\n * deterministic stubs instead of touching real processes / filesystem state.\n * Production callers pass nothing and get the real defaults.\n */\nexport interface LivenessDeps {\n /** Current wall-clock time. Defaults to Date.now. */\n now?: () => number;\n /** Returns the file mtime in ms, or null when the path is missing / unreadable. */\n statMtimeMs?: (path: string) => number | null;\n /** Returns true when a process with the given pid is currently running. */\n isPidAlive?: (pid: number) => boolean;\n /** Returns the stringified start time of the process, or null when unavailable. */\n pidStartedAt?: (pid: number) => string | null;\n}\n\nconst DEFAULT_DEPS: Required<LivenessDeps> = {\n now: () => Date.now(),\n statMtimeMs: (path) => {\n try {\n return statSync(path).mtimeMs;\n } catch {\n return null;\n }\n },\n isPidAlive: (pid) => {\n if (!Number.isFinite(pid) || pid <= 0) return false;\n try {\n // Signal 0 doesn't deliver — it only probes existence + permission.\n // ESRCH: no such process; EPERM: process exists but we cannot signal.\n process.kill(pid, 0);\n return true;\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === 'EPERM') return true;\n return false;\n }\n },\n pidStartedAt: (pid) => {\n if (!Number.isFinite(pid) || pid <= 0) return null;\n try {\n const out = execFileSync('ps', ['-o', 'lstart=', '-p', String(pid)], {\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n });\n const trimmed = out.trim();\n return trimmed === '' ? null : trimmed;\n } catch {\n return null;\n }\n },\n};\n\nfunction resolveDeps(deps?: LivenessDeps): Required<LivenessDeps> {\n return {\n now: deps?.now ?? DEFAULT_DEPS.now,\n statMtimeMs: deps?.statMtimeMs ?? DEFAULT_DEPS.statMtimeMs,\n isPidAlive: deps?.isPidAlive ?? DEFAULT_DEPS.isPidAlive,\n pidStartedAt: deps?.pidStartedAt ?? DEFAULT_DEPS.pidStartedAt,\n };\n}\n\n/**\n * Compute whether a session is \"live\" — i.e. there may still be a process\n * writing to its transcript. The UI disables Resume when isLive is true so\n * the user is forced to Fork instead, preventing two processes from\n * interleaving writes into the same transcript file.\n *\n * Tiered logic (matches Design Summary in assignment.md):\n * 1. status !== 'active' → false (manual override is definitive).\n * 2. pid present:\n * 2a. pid not alive → false (process is gone).\n * 2b. pid alive AND stored pid_started_at differs from current → false\n * (PID was recycled by a different process; original is gone).\n * 2c. pid alive otherwise → true.\n * 3. transcriptPath present AND recently-touched (<5 min) → true.\n * 4. Default → true (safer: disable Resume, force Fork when no signal).\n */\nexport function computeIsLive(\n session: AgentSession,\n deps?: LivenessDeps,\n): boolean {\n if (session.status !== 'active') return false;\n\n const d = resolveDeps(deps);\n\n const pid = session.pid;\n if (pid !== null && pid !== undefined) {\n if (!d.isPidAlive(pid)) return false;\n if (session.pidStartedAt) {\n const current = d.pidStartedAt(pid);\n if (current !== null && current !== session.pidStartedAt) {\n // PID exists but it's a different process now.\n return false;\n }\n }\n return true;\n }\n\n if (session.transcriptPath) {\n const mtime = d.statMtimeMs(session.transcriptPath);\n if (mtime !== null && d.now() - mtime < FIVE_MINUTES_MS) {\n return true;\n }\n }\n\n // No signal available — safer to assume live so Resume is gated off.\n return true;\n}\n\n/**\n * Enrich a session row with the server-derived flags the UI uses to render\n * Resume / Fork / Mark-stopped buttons.\n *\n * `resumeSupported` / `forkSupported` derive from the agent's `AgentConfig`\n * via the resolved agents list (typically `getAgents(config)`). When the\n * session's agent is missing from the list, both flags are false.\n */\nexport function enrichSession(\n session: AgentSession,\n agents: AgentConfig[],\n deps?: LivenessDeps,\n): AgentSessionWithLiveness {\n const agent = agents.find((a) => a.id === session.agent);\n return {\n ...session,\n isLive: computeIsLive(session, deps),\n resumeSupported: agent?.resume != null,\n forkSupported: agent?.fork != null,\n };\n}\n\nexport function enrichSessions(\n sessions: AgentSession[],\n agents: AgentConfig[],\n deps?: LivenessDeps,\n): AgentSessionWithLiveness[] {\n return sessions.map((s) => enrichSession(s, agents, deps));\n}\n","import { watch } from 'chokidar';\nimport { basename, dirname, relative, sep } from 'node:path';\nimport type { WsMessage } from './types.js';\n\nexport interface WatcherOptions {\n projectsDir: string;\n assignmentsDir?: string;\n serversDir?: string;\n playbooksDir?: string;\n todosDir?: string;\n /** Absolute path to ~/.syntaur/syntaur.db. When set, watch the parent dir\n * for changes to this file and its WAL siblings (-wal, -shm) and broadcast\n * `leases-updated`. chokidar 4 removed glob support so we must filter by\n * basename in the change handler. */\n dbPath?: string;\n onMessage: (message: WsMessage) => void;\n debounceMs?: number;\n}\n\nexport function createWatcher(options: WatcherOptions): { close: () => Promise<void> } {\n const { projectsDir, assignmentsDir, serversDir, playbooksDir, todosDir, dbPath, onMessage, debounceMs = 300 } = options;\n const pendingEvents = new Map<string, NodeJS.Timeout>();\n\n // --- Projects watcher (existing logic) ---\n const projectsWatcher = watch(projectsDir, {\n ignoreInitial: true,\n persistent: true,\n depth: 10,\n ignored: /(^|[\\/\\\\])\\../,\n });\n\n function handleProjectChange(filePath: string): void {\n const rel = relative(projectsDir, filePath);\n const parts = rel.split(sep);\n\n if (parts.length === 0) return;\n\n const projectSlug = parts[0];\n let assignmentSlug: string | undefined;\n let isProjectTodos = false;\n\n if (parts.length >= 3 && parts[1] === 'assignments') {\n assignmentSlug = parts[2];\n } else if (parts.length >= 2 && parts[1] === 'todos') {\n isProjectTodos = true;\n }\n\n const debounceKey = isProjectTodos\n ? `todos:${projectSlug}`\n : assignmentSlug\n ? `${projectSlug}/${assignmentSlug}`\n : projectSlug;\n\n const existing = pendingEvents.get(debounceKey);\n if (existing) clearTimeout(existing);\n\n // Session events are now emitted by the API write path, not the file watcher\n const messageType: WsMessage['type'] = isProjectTodos\n ? 'todos-updated'\n : assignmentSlug\n ? 'assignment-updated'\n : 'project-updated';\n\n pendingEvents.set(\n debounceKey,\n setTimeout(() => {\n pendingEvents.delete(debounceKey);\n const message: WsMessage = isProjectTodos\n ? {\n type: 'todos-updated',\n projectSlug,\n timestamp: new Date().toISOString(),\n }\n : {\n type: messageType,\n projectSlug,\n assignmentSlug,\n timestamp: new Date().toISOString(),\n };\n onMessage(message);\n }, debounceMs),\n );\n }\n\n projectsWatcher.on('change', handleProjectChange);\n projectsWatcher.on('add', handleProjectChange);\n projectsWatcher.on('unlink', handleProjectChange);\n\n // --- Standalone assignments watcher ---\n let standaloneWatcher: ReturnType<typeof watch> | null = null;\n\n if (assignmentsDir) {\n standaloneWatcher = watch(assignmentsDir, {\n ignoreInitial: true,\n persistent: true,\n depth: 5,\n ignored: /(^|[\\/\\\\])\\../,\n });\n\n function handleStandaloneChange(filePath: string): void {\n const rel = relative(assignmentsDir!, filePath);\n const parts = rel.split(sep);\n if (parts.length === 0) return;\n const assignmentId = parts[0];\n if (!assignmentId) return;\n\n const debounceKey = `__standalone__/${assignmentId}`;\n const existing = pendingEvents.get(debounceKey);\n if (existing) clearTimeout(existing);\n\n pendingEvents.set(\n debounceKey,\n setTimeout(() => {\n pendingEvents.delete(debounceKey);\n const message: WsMessage = {\n type: 'assignment-updated',\n projectSlug: null,\n assignmentSlug: assignmentId,\n timestamp: new Date().toISOString(),\n };\n onMessage(message);\n }, debounceMs),\n );\n }\n\n standaloneWatcher.on('change', handleStandaloneChange);\n standaloneWatcher.on('add', handleStandaloneChange);\n standaloneWatcher.on('unlink', handleStandaloneChange);\n }\n\n // --- Servers watcher (new) ---\n let serversWatcher: ReturnType<typeof watch> | null = null;\n\n if (serversDir) {\n serversWatcher = watch(serversDir, {\n ignoreInitial: true,\n persistent: true,\n depth: 1,\n ignored: /(^|[\\/\\\\])\\../,\n });\n\n function handleServerChange(): void {\n const debounceKey = '__servers__';\n const existing = pendingEvents.get(debounceKey);\n if (existing) clearTimeout(existing);\n\n pendingEvents.set(\n debounceKey,\n setTimeout(() => {\n pendingEvents.delete(debounceKey);\n const message: WsMessage = {\n type: 'servers-updated',\n timestamp: new Date().toISOString(),\n };\n onMessage(message);\n }, debounceMs),\n );\n }\n\n serversWatcher.on('change', handleServerChange);\n serversWatcher.on('add', handleServerChange);\n serversWatcher.on('unlink', handleServerChange);\n }\n\n // --- Playbooks watcher ---\n let playbooksWatcher: ReturnType<typeof watch> | null = null;\n\n if (playbooksDir) {\n playbooksWatcher = watch(playbooksDir, {\n ignoreInitial: true,\n persistent: true,\n depth: 1,\n ignored: /(^|[\\/\\\\])\\../,\n });\n\n function handlePlaybookChange(): void {\n const debounceKey = '__playbooks__';\n const existing = pendingEvents.get(debounceKey);\n if (existing) clearTimeout(existing);\n\n pendingEvents.set(\n debounceKey,\n setTimeout(() => {\n pendingEvents.delete(debounceKey);\n const message: WsMessage = {\n type: 'playbooks-updated',\n timestamp: new Date().toISOString(),\n };\n onMessage(message);\n }, debounceMs),\n );\n }\n\n playbooksWatcher.on('change', handlePlaybookChange);\n playbooksWatcher.on('add', handlePlaybookChange);\n playbooksWatcher.on('unlink', handlePlaybookChange);\n }\n\n // --- Todos watcher ---\n let todosWatcher: ReturnType<typeof watch> | null = null;\n\n if (todosDir) {\n todosWatcher = watch(todosDir, {\n ignoreInitial: true,\n persistent: true,\n depth: 1,\n ignored: /(^|[\\/\\\\])\\../,\n });\n\n function handleTodoChange(): void {\n const debounceKey = '__todos__';\n const existing = pendingEvents.get(debounceKey);\n if (existing) clearTimeout(existing);\n\n pendingEvents.set(\n debounceKey,\n setTimeout(() => {\n pendingEvents.delete(debounceKey);\n const message: WsMessage = {\n type: 'todos-updated',\n timestamp: new Date().toISOString(),\n };\n onMessage(message);\n }, debounceMs),\n );\n }\n\n todosWatcher.on('change', handleTodoChange);\n todosWatcher.on('add', handleTodoChange);\n todosWatcher.on('unlink', handleTodoChange);\n }\n\n // --- Leases DB watcher ---\n // SQLite WAL-mode writes mostly go to `<db>-wal`, not the main file. Watch\n // the parent directory and filter by basename to catch the main DB and its\n // -wal / -shm siblings. chokidar 4 has no glob support, so a literal pattern\n // like `${dbPath}*` would be silently a no-op.\n let leasesDbWatcher: ReturnType<typeof watch> | null = null;\n\n if (dbPath) {\n const dbDir = dirname(dbPath);\n const dbBase = basename(dbPath);\n\n leasesDbWatcher = watch(dbDir, {\n ignoreInitial: true,\n persistent: true,\n depth: 0,\n ignored: /(^|[\\/\\\\])\\../,\n });\n\n function handleDbChange(filePath: string): void {\n if (!basename(filePath).startsWith(dbBase)) return;\n const debounceKey = '__leases-db__';\n const existing = pendingEvents.get(debounceKey);\n if (existing) clearTimeout(existing);\n\n pendingEvents.set(\n debounceKey,\n setTimeout(() => {\n pendingEvents.delete(debounceKey);\n const message: WsMessage = {\n type: 'leases-updated',\n timestamp: new Date().toISOString(),\n };\n onMessage(message);\n }, debounceMs),\n );\n }\n\n leasesDbWatcher.on('change', handleDbChange);\n leasesDbWatcher.on('add', handleDbChange);\n leasesDbWatcher.on('unlink', handleDbChange);\n }\n\n return {\n close: async () => {\n pendingEvents.forEach((timeout) => {\n clearTimeout(timeout);\n });\n pendingEvents.clear();\n await projectsWatcher.close();\n if (standaloneWatcher) await standaloneWatcher.close();\n if (serversWatcher) await serversWatcher.close();\n if (playbooksWatcher) await playbooksWatcher.close();\n if (todosWatcher) await todosWatcher.close();\n if (leasesDbWatcher) await leasesDbWatcher.close();\n },\n };\n}\n","export type ViewMode = 'kanban' | 'list' | 'table';\n\nexport const VIEW_MODES: readonly ViewMode[] = ['kanban', 'list', 'table'];\n\nexport type SortField =\n | 'title'\n | 'status'\n | 'priority'\n | 'assignee'\n | 'dependencies'\n | 'updated';\n\nexport const SORT_FIELDS: readonly SortField[] = [\n 'title',\n 'status',\n 'priority',\n 'assignee',\n 'dependencies',\n 'updated',\n];\n\nexport type SortDirection = 'asc' | 'desc';\nexport const SORT_DIRECTIONS: readonly SortDirection[] = ['asc', 'desc'];\n\nexport type Density = 'comfortable' | 'compact';\nexport const DENSITIES: readonly Density[] = ['comfortable', 'compact'];\n\nexport type Grouping = 'none' | 'status' | 'priority' | 'assignee' | 'project';\nexport const GROUPINGS: readonly Grouping[] = [\n 'none',\n 'status',\n 'priority',\n 'assignee',\n 'project',\n];\n\nexport type Activity = 'all' | 'stale' | 'fresh';\nexport const ACTIVITIES: readonly Activity[] = ['all', 'stale', 'fresh'];\n\n// Filter values are user-data-driven strings (status ids, priority names,\n// assignee names, project slugs) plus 'all'. The codebase also uses the\n// sentinels '__unassigned__' and '__standalone__' for assignee/project,\n// so validation is allow-by-shape (non-empty string), not allow-by-value.\nexport interface ViewFilters {\n status?: string;\n priority?: string;\n assignee?: string;\n project?: string;\n activity?: Activity;\n}\n\nexport interface ViewPrefs {\n defaultView: ViewMode;\n sortField: SortField;\n sortDirection: SortDirection;\n density: Density;\n grouping: Grouping;\n filters: ViewFilters;\n}\n\n// Per-scope overrides cannot set density (global only by product decision).\nexport type ProjectViewPrefs = Partial<Omit<ViewPrefs, 'density'>>;\n\nexport interface ViewPrefsFile {\n version: 1;\n global: ViewPrefs;\n projects: Record<string, ProjectViewPrefs>;\n}\n\nexport const DEFAULT_VIEW_PREFS: ViewPrefs = {\n defaultView: 'kanban',\n sortField: 'updated',\n sortDirection: 'desc',\n density: 'comfortable',\n grouping: 'none',\n filters: {\n status: 'all',\n priority: 'all',\n assignee: 'all',\n project: 'all',\n activity: 'all',\n },\n};\n\nexport const DEFAULT_VIEW_PREFS_FILE: ViewPrefsFile = {\n version: 1,\n global: DEFAULT_VIEW_PREFS,\n projects: {},\n};\n\nexport function isViewMode(v: unknown): v is ViewMode {\n return typeof v === 'string' && (VIEW_MODES as readonly string[]).includes(v);\n}\n\nexport function isSortField(v: unknown): v is SortField {\n return typeof v === 'string' && (SORT_FIELDS as readonly string[]).includes(v);\n}\n\nexport function isSortDirection(v: unknown): v is SortDirection {\n return typeof v === 'string' && (SORT_DIRECTIONS as readonly string[]).includes(v);\n}\n\nexport function isDensity(v: unknown): v is Density {\n return typeof v === 'string' && (DENSITIES as readonly string[]).includes(v);\n}\n\nexport function isGrouping(v: unknown): v is Grouping {\n return typeof v === 'string' && (GROUPINGS as readonly string[]).includes(v);\n}\n\nexport function isActivity(v: unknown): v is Activity {\n return typeof v === 'string' && (ACTIVITIES as readonly string[]).includes(v);\n}\n\nexport function isFilterString(v: unknown): v is string {\n return typeof v === 'string' && v.length > 0;\n}\n\n// ProjectDetail only supports kanban/table; map 'list' onto 'kanban'.\nexport function coerceProjectDetailView(v: ViewMode): 'kanban' | 'table' {\n return v === 'table' ? 'table' : 'kanban';\n}\n\nfunction mergeFilters(base: ViewFilters, patch: ViewFilters | undefined): ViewFilters {\n if (!patch) return { ...base };\n return { ...base, ...patch };\n}\n\nfunction mergePrefs(base: ViewPrefs, patch: Partial<ViewPrefs> | undefined): ViewPrefs {\n if (!patch) return base;\n return {\n ...base,\n ...patch,\n filters: mergeFilters(base.filters, patch.filters),\n };\n}\n\nfunction mergeProjectOverride(\n base: ProjectViewPrefs,\n patch: ProjectViewPrefs | undefined,\n): ProjectViewPrefs {\n if (!patch) return { ...base };\n return {\n ...base,\n ...patch,\n filters: patch.filters || base.filters\n ? mergeFilters(base.filters ?? {}, patch.filters)\n : undefined,\n };\n}\n\n// Returns the effective ViewPrefs for a scope. `scope === null` returns global.\n// Density always comes from global (per the type constraint).\nexport function mergeForScope(file: ViewPrefsFile, scope: string | null): ViewPrefs {\n const global = file.global;\n if (scope === null) return global;\n const override = file.projects[scope];\n if (!override) return global;\n return {\n defaultView: override.defaultView ?? global.defaultView,\n sortField: override.sortField ?? global.sortField,\n sortDirection: override.sortDirection ?? global.sortDirection,\n density: global.density,\n grouping: override.grouping ?? global.grouping,\n filters: mergeFilters(global.filters, override.filters),\n };\n}\n\n// Canonical patch shape sent to POST /api/view-prefs.\nexport interface ViewPrefsPatch {\n global?: Partial<ViewPrefs>;\n projects?: Record<string, ProjectViewPrefs>;\n}\n\n// Deep-merges a patch into the current file. Does NOT validate; the route\n// handler is expected to validate the result before persisting.\nexport function mergePatch(current: ViewPrefsFile, patch: ViewPrefsPatch): ViewPrefsFile {\n const nextProjects: Record<string, ProjectViewPrefs> = { ...current.projects };\n if (patch.projects) {\n for (const [scope, scopePatch] of Object.entries(patch.projects)) {\n const prev = nextProjects[scope] ?? {};\n nextProjects[scope] = mergeProjectOverride(prev, scopePatch);\n }\n }\n return {\n version: 1,\n global: mergePrefs(current.global, patch.global),\n projects: nextProjects,\n };\n}\n","import { readFile, rename, unlink } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { syntaurRoot, viewPrefsFile } from './paths.js';\nimport { fileExists, writeFileForce } from './fs.js';\nimport {\n DEFAULT_VIEW_PREFS_FILE,\n type ViewPrefsFile,\n type ViewPrefsPatch,\n mergePatch,\n} from './view-prefs-schema.js';\n\n// Re-exports so consumers only need to import from this module.\nexport type { ViewPrefsFile, ViewPrefsPatch };\nexport { mergePatch } from './view-prefs-schema.js';\nexport { mergeForScope } from './view-prefs-schema.js';\n\nfunction corruptFilePath(): string {\n const ts = new Date().toISOString().replace(/[:.]/g, '-');\n return resolve(syntaurRoot(), `view-prefs.corrupt-${ts}.json`);\n}\n\nfunction isViewPrefsFileShape(value: unknown): value is ViewPrefsFile {\n if (!value || typeof value !== 'object') return false;\n const obj = value as Record<string, unknown>;\n // Treat missing `version` as v1 (forward-compat with previously-written files).\n // An explicit non-1 version is handled separately upstream.\n if (obj.version !== undefined && obj.version !== 1) return false;\n if (!obj.global || typeof obj.global !== 'object') return false;\n if (!obj.projects || typeof obj.projects !== 'object' || Array.isArray(obj.projects)) {\n return false;\n }\n return true;\n}\n\n// Returns the parsed file when readable + valid.\n// Returns defaults on missing, parse error, or shape mismatch.\n// On corruption (present but unparseable / bad shape), renames the bad file\n// to view-prefs.corrupt-<ISO>.json BEFORE returning defaults so the next save\n// does not overwrite the evidence. Unknown future versions return defaults\n// WITHOUT renaming (forward-compat).\nexport async function readViewPrefsFile(): Promise<ViewPrefsFile> {\n const path = viewPrefsFile();\n if (!(await fileExists(path))) {\n return { ...DEFAULT_VIEW_PREFS_FILE };\n }\n let raw: string;\n try {\n raw = await readFile(path, 'utf-8');\n } catch {\n return { ...DEFAULT_VIEW_PREFS_FILE };\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n await backupCorrupt(path);\n return { ...DEFAULT_VIEW_PREFS_FILE };\n }\n if (parsed && typeof parsed === 'object' && (parsed as Record<string, unknown>).version !== undefined) {\n const v = (parsed as Record<string, unknown>).version;\n if (typeof v === 'number' && v > 1) {\n console.warn(\n `[view-prefs] Unknown version ${v} at ${path}; returning defaults (file left intact).`,\n );\n return { ...DEFAULT_VIEW_PREFS_FILE };\n }\n }\n if (!isViewPrefsFileShape(parsed)) {\n await backupCorrupt(path);\n return { ...DEFAULT_VIEW_PREFS_FILE };\n }\n // Normalize version (missing -> 1).\n return { ...parsed, version: 1 };\n}\n\nasync function backupCorrupt(path: string): Promise<void> {\n const backup = corruptFilePath();\n try {\n await rename(path, backup);\n console.warn(`[view-prefs] Corrupt file moved to ${backup}; using defaults.`);\n } catch (err) {\n console.warn(`[view-prefs] Failed to back up corrupt file ${path}: ${String(err)}`);\n }\n}\n\nexport async function writeViewPrefsFile(file: ViewPrefsFile): Promise<void> {\n await writeFileForce(viewPrefsFile(), `${JSON.stringify(file, null, 2)}\\n`);\n}\n\nexport async function resetViewPrefsFile(): Promise<void> {\n const path = viewPrefsFile();\n if (await fileExists(path)) {\n await unlink(path);\n }\n}\n\n// Convenience for routes: read → mergePatch → write.\nexport async function applyViewPrefsPatch(patch: ViewPrefsPatch): Promise<ViewPrefsFile> {\n const current = await readViewPrefsFile();\n const next = mergePatch(current, patch);\n await writeViewPrefsFile(next);\n return next;\n}\n\nexport function isViewPrefsDefaults(file: ViewPrefsFile): boolean {\n if (Object.keys(file.projects).length > 0) return false;\n const g = file.global;\n const d = DEFAULT_VIEW_PREFS_FILE.global;\n if (g.defaultView !== d.defaultView) return false;\n if (g.sortField !== d.sortField) return false;\n if (g.sortDirection !== d.sortDirection) return false;\n if (g.density !== d.density) return false;\n if (g.grouping !== d.grouping) return false;\n const gf = g.filters;\n const df = d.filters;\n if (gf.status !== df.status) return false;\n if (gf.priority !== df.priority) return false;\n if (gf.assignee !== df.assignee) return false;\n if (gf.project !== df.project) return false;\n if (gf.activity !== df.activity) return false;\n return true;\n}\n","// Shared write-lock map for the todo routers. Both the workspace router\n// (api-todos.ts) and the project router (api-project-todos.ts) acquire from\n// this same Map so cross-scope move can hold both source and target locks\n// in lexical order of the prefixed key without risk of deadlock.\n//\n// Lock-key prefixes:\n// ws:<workspace> — workspace-scoped checklist (the singleton global\n// checklist is reached as ws:_global; see globalLockKey)\n// proj:<slug> — project-scoped checklist\nconst writeLocks = new Map<string, Promise<void>>();\n\nexport function withLock<T>(lockKey: string, fn: () => Promise<T>): Promise<T> {\n const prev = writeLocks.get(lockKey) ?? Promise.resolve();\n const next = prev.then(fn);\n writeLocks.set(\n lockKey,\n next.then(\n () => {},\n () => {},\n ),\n );\n return next;\n}\n\nexport function wsLock<T>(workspace: string, fn: () => Promise<T>): Promise<T> {\n return withLock(`ws:${workspace}`, fn);\n}\n\nexport function projLock<T>(slug: string, fn: () => Promise<T>): Promise<T> {\n return withLock(`proj:${slug}`, fn);\n}\n\n// The global checklist is just a workspace named \"_global\" by convention;\n// this helper exists to make that mapping explicit at call sites that\n// distinguish global from named-workspace scopes.\nexport function globalLockKey(): string {\n return 'ws:_global';\n}\n\n// Acquire two locks in lexical order to prevent deadlock when one request\n// needs to mutate two scopes (e.g. cross-scope todo move).\nexport function withTwoLocks<T>(\n keyA: string,\n keyB: string,\n fn: () => Promise<T>,\n): Promise<T> {\n if (keyA === keyB) return withLock(keyA, fn);\n const [first, second] = keyA < keyB ? [keyA, keyB] : [keyB, keyA];\n return withLock(first, () => withLock(second, fn));\n}\n","import { Router, type Request, type Response } from 'express';\nimport { resolve, basename } from 'node:path';\nimport { rm, readFile, open as fsOpen } from 'node:fs/promises';\nimport { executeTransition } from '../lifecycle/index.js';\nimport { isValidSlug, slugify } from '../utils/slug.js';\nimport { generateId } from '../utils/uuid.js';\nimport { nowTimestamp } from '../utils/timestamp.js';\nimport { ensureDir, writeFileForce, fileExists } from '../utils/fs.js';\nimport {\n parseAssignmentFull,\n parseDecisionRecord,\n parseHandoff,\n parseMemory,\n parseProject,\n parsePlan,\n parseResource,\n parseScratchpad,\n} from './parser.js';\nimport { toggleAcceptanceCriterion } from './acceptance-criteria.js';\nimport {\n getAssignmentDetail,\n getAssignmentDetailById,\n getEditableDocument,\n getEditableDocumentById,\n getMemoryDetail,\n getProjectDetail,\n getResourceDetail,\n getStatusConfig,\n resolveProjectPath,\n} from './api.js';\nimport { resolveAssignmentById } from '../utils/assignment-resolver.js';\nimport { renderProgress } from '../templates/index.js';\nimport { executeTransitionByDir } from '../lifecycle/index.js';\nimport {\n renderProject,\n renderManifest,\n renderIndexAssignments,\n renderIndexPlans,\n renderIndexDecisions,\n renderStatus,\n renderResourcesIndex,\n renderMemoriesIndex,\n renderMemoryStub,\n renderResourceStub,\n renderAssignment,\n renderScratchpad,\n renderHandoff,\n renderDecisionRecord,\n renderComments,\n formatCommentEntry,\n type Comment,\n type CommentType,\n} from '../templates/index.js';\nimport { parseComments } from './parser.js';\n\nfunction extractFrontmatter(content: string): Record<string, string> | null {\n const trimmed = content.trimStart();\n if (!trimmed.startsWith('---\\n') && !trimmed.startsWith('---\\r\\n')) {\n return null;\n }\n\n const afterFirst = trimmed.indexOf('\\n') + 1;\n const closingIdx = trimmed.indexOf('\\n---', afterFirst);\n if (closingIdx === -1) {\n return null;\n }\n\n const yamlBlock = trimmed.slice(afterFirst, closingIdx);\n const fields: Record<string, string> = {};\n\n for (const line of yamlBlock.split('\\n')) {\n const match = line.match(/^([a-zA-Z_][a-zA-Z0-9_]*):\\s*(.*)$/);\n if (!match) {\n continue;\n }\n\n let value = match[2].trim();\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n fields[match[1]] = value;\n }\n\n return fields;\n}\n\nfunction validateRequired(\n fields: Record<string, string>,\n required: string[],\n): { valid: true } | { valid: false; missing: string[] } {\n const missing = required.filter((key) => !fields[key] || fields[key] === 'null');\n if (missing.length > 0) {\n return { valid: false, missing };\n }\n return { valid: true };\n}\n\nfunction formatYamlValue(value: boolean | number | string | null): string {\n if (value === null) {\n return 'null';\n }\n if (typeof value === 'boolean' || typeof value === 'number') {\n return String(value);\n }\n if (/^\\d{4}-\\d{2}-\\d{2}T/.test(value)) {\n return `\"${value}\"`;\n }\n if (value === '' || /[:#{}[\\],&*?|>!%@`]/.test(value) || /^\\s|\\s$/.test(value)) {\n return `\"${value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')}\"`;\n }\n return value;\n}\n\nfunction setTopLevelField(\n content: string,\n key: string,\n value: boolean | number | string | null,\n): string {\n const formatted = formatYamlValue(value);\n const fieldRegex = new RegExp(`^(${escapeRegExp(key)}:)\\\\s*.*$`, 'm');\n\n if (fieldRegex.test(content)) {\n return content.replace(fieldRegex, `$1 ${formatted}`);\n }\n\n const closingIdx = content.indexOf('\\n---', 4);\n if (closingIdx === -1) {\n return content;\n }\n\n return `${content.slice(0, closingIdx)}\\n${key}: ${formatted}${content.slice(closingIdx)}`;\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nfunction appendLogEntry(\n existingContent: string,\n countField: 'handoffCount' | 'decisionCount',\n nextCount: number,\n heading: string,\n body: string,\n emptyPlaceholder: string,\n): string {\n const timestamp = nowTimestamp();\n let next = setTopLevelField(existingContent, 'updated', timestamp);\n next = setTopLevelField(next, countField, nextCount);\n\n const entryBody = body.trim();\n const entry = `## ${heading}\\n\\n**Recorded:** ${timestamp}\\n\\n${entryBody}\\n`;\n\n if (next.includes(emptyPlaceholder)) {\n return next.replace(emptyPlaceholder, entry.trimEnd());\n }\n\n return `${next.trimEnd()}\\n\\n${entry}`;\n}\n\nfunction requireContent(req: Request, res: Response): string | null {\n const { content } = req.body || {};\n if (!content || typeof content !== 'string' || !content.trim()) {\n res.status(400).json({ error: 'content is required' });\n return null;\n }\n return content;\n}\n\nfunction getParam(value: string | string[] | undefined): string {\n if (Array.isArray(value)) {\n return value[0] ?? '';\n }\n return value ?? '';\n}\n\nasync function readCurrentDocument(filePath: string): Promise<string | null> {\n if (!(await fileExists(filePath))) {\n return null;\n }\n return readFile(filePath, 'utf-8');\n}\n\nexport function createWriteRouter(\n projectsDir: string,\n assignmentsDir?: string,\n todosDir?: string,\n): Router {\n const linkedTodosLookup = todosDir ? { todosDir, projectsDir } : undefined;\n const router = Router();\n\n router.get('/api/templates/project', (_req: Request, res: Response) => {\n const content = renderProject({\n id: generateId(),\n slug: 'my-new-project',\n title: 'My New Project',\n timestamp: nowTimestamp(),\n });\n res.json({ content });\n });\n\n router.get('/api/templates/assignment', (req: Request, res: Response) => {\n const standalone = req.query.standalone === '1';\n const workspaceParam = typeof req.query.workspace === 'string' ? req.query.workspace : '';\n if (workspaceParam && !isValidSlug(workspaceParam)) {\n res.status(400).json({\n error: `Invalid workspace slug \"${workspaceParam}\". Slugs must be lowercase, hyphen-separated, with no special characters.`,\n });\n return;\n }\n const content = renderAssignment({\n id: generateId(),\n slug: 'my-new-assignment',\n title: 'My New Assignment',\n timestamp: nowTimestamp(),\n priority: 'medium',\n dependsOn: [],\n links: [],\n project: standalone ? null : undefined,\n workspaceGroup: standalone && workspaceParam ? workspaceParam : null,\n });\n res.json({ content });\n });\n\n router.get('/api/projects/:slug/edit', async (req: Request, res: Response) => {\n const slug = getParam(req.params.slug);\n const document = await getEditableDocument(projectsDir, 'project', slug);\n if (!document) {\n res.status(404).json({ error: `Project \"${slug}\" not found` });\n return;\n }\n res.json(document);\n });\n\n router.get('/api/projects/:slug/assignments/:aslug/edit', async (req: Request, res: Response) => {\n const slug = getParam(req.params.slug);\n const assignmentSlug = getParam(req.params.aslug);\n const document = await getEditableDocument(\n projectsDir,\n 'assignment',\n slug,\n assignmentSlug,\n );\n if (!document) {\n res.status(404).json({ error: 'Assignment not found' });\n return;\n }\n res.json(document);\n });\n\n router.get('/api/projects/:slug/assignments/:aslug/plan/edit', async (req: Request, res: Response) => {\n const slug = getParam(req.params.slug);\n const assignmentSlug = getParam(req.params.aslug);\n const document = await getEditableDocument(\n projectsDir,\n 'plan',\n slug,\n assignmentSlug,\n );\n if (!document) {\n res.status(404).json({ error: 'Plan not found' });\n return;\n }\n res.json(document);\n });\n\n router.get('/api/projects/:slug/assignments/:aslug/scratchpad/edit', async (req: Request, res: Response) => {\n const slug = getParam(req.params.slug);\n const assignmentSlug = getParam(req.params.aslug);\n const document = await getEditableDocument(\n projectsDir,\n 'scratchpad',\n slug,\n assignmentSlug,\n );\n if (!document) {\n res.status(404).json({ error: 'Scratchpad not found' });\n return;\n }\n res.json(document);\n });\n\n router.get('/api/projects/:slug/assignments/:aslug/handoff/edit', async (req: Request, res: Response) => {\n const slug = getParam(req.params.slug);\n const assignmentSlug = getParam(req.params.aslug);\n const document = await getEditableDocument(\n projectsDir,\n 'handoff',\n slug,\n assignmentSlug,\n );\n if (!document) {\n res.status(404).json({ error: 'Handoff log not found' });\n return;\n }\n res.json(document);\n });\n\n router.get('/api/projects/:slug/assignments/:aslug/decision-record/edit', async (req: Request, res: Response) => {\n const slug = getParam(req.params.slug);\n const assignmentSlug = getParam(req.params.aslug);\n const document = await getEditableDocument(\n projectsDir,\n 'decision-record',\n slug,\n assignmentSlug,\n );\n if (!document) {\n res.status(404).json({ error: 'Decision record not found' });\n return;\n }\n res.json(document);\n });\n\n router.get('/api/projects/:slug/memories/:itemSlug/edit', async (req: Request, res: Response) => {\n const slug = getParam(req.params.slug);\n const itemSlug = getParam(req.params.itemSlug);\n if (!isValidSlug(itemSlug)) {\n res.status(400).json({ error: 'Invalid memory slug.' });\n return;\n }\n const projectDir = await resolveProjectPath(projectsDir, slug);\n if (!projectDir) {\n res.status(404).json({ error: `Project \"${slug}\" not found` });\n return;\n }\n const document = await getEditableDocument(projectsDir, 'memory', basename(projectDir), itemSlug);\n if (!document) {\n res.status(404).json({ error: 'Memory not found' });\n return;\n }\n res.json(document);\n });\n\n router.get('/api/projects/:slug/resources/:itemSlug/edit', async (req: Request, res: Response) => {\n const slug = getParam(req.params.slug);\n const itemSlug = getParam(req.params.itemSlug);\n if (!isValidSlug(itemSlug)) {\n res.status(400).json({ error: 'Invalid resource slug.' });\n return;\n }\n const projectDir = await resolveProjectPath(projectsDir, slug);\n if (!projectDir) {\n res.status(404).json({ error: `Project \"${slug}\" not found` });\n return;\n }\n const document = await getEditableDocument(projectsDir, 'resource', basename(projectDir), itemSlug);\n if (!document) {\n res.status(404).json({ error: 'Resource not found' });\n return;\n }\n res.json(document);\n });\n\n // ----- Memory / Resource CRUD ----------------------------------------------\n // The two types share an identical contract; `kind` parameterizes the folder\n // and stub renderer.\n\n type ItemKind = 'memory' | 'resource';\n\n function itemFolder(kind: ItemKind): 'memories' | 'resources' {\n return kind === 'memory' ? 'memories' : 'resources';\n }\n\n function renderItemStub(\n kind: ItemKind,\n params: { slug: string; name: string; projectSlug: string; timestamp: string },\n ): string {\n return kind === 'memory' ? renderMemoryStub(params) : renderResourceStub(params);\n }\n\n /** Replace the body of a stub (everything after the closing frontmatter) with a custom body. */\n function replaceStubBody(stub: string, body: string): string {\n const match = stub.match(/^(---\\r?\\n[\\s\\S]*?\\r?\\n---\\r?\\n)/);\n if (!match) return stub; // shouldn't happen — stub always has frontmatter\n return `${match[1]}\\n${body.startsWith('\\n') ? body.slice(1) : body}${body.endsWith('\\n') ? '' : '\\n'}`;\n }\n\n /** Extract the verbatim frontmatter block (including the surrounding `---` lines). */\n function extractFrontmatterBlock(content: string): string | null {\n const match = content.match(/^(---\\r?\\n[\\s\\S]*?\\r?\\n---\\r?\\n)/);\n return match ? match[1] : null;\n }\n\n function parseItem(kind: ItemKind, content: string) {\n return kind === 'memory' ? parseMemory(content) : parseResource(content);\n }\n\n async function getItemDetail(kind: ItemKind, projectSlug: string, itemSlug: string) {\n return kind === 'memory'\n ? await getMemoryDetail(projectsDir, projectSlug, itemSlug)\n : await getResourceDetail(projectsDir, projectSlug, itemSlug);\n }\n\n /**\n * Resolve the on-disk project directory for a slug.\n * Tries the directory-name match first (the typical case); falls back to scanning every\n * project for a frontmatter-slug match (covers fixtures/legacy projects whose folder name\n * differs from `project.md` `slug`).\n */\n async function resolveProjectDir(projectSlug: string): Promise<string | null> {\n return resolveProjectPath(projectsDir, projectSlug);\n }\n\n /** 400 if the slug param wouldn't pass `isValidSlug`. Returns true if the response was sent. */\n function rejectBadItemSlug(itemSlug: string, kind: ItemKind, res: Response): boolean {\n if (isValidSlug(itemSlug)) return false;\n res.status(400).json({\n error: `Invalid ${kind} slug \"${itemSlug}\". Slugs must be lowercase letters, numbers, and hyphens only.`,\n });\n return true;\n }\n\n // GET detail\n for (const kind of ['memory', 'resource'] as const) {\n const folder = itemFolder(kind);\n\n router.get(`/api/projects/:slug/${folder}/:itemSlug`, async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const itemSlug = getParam(req.params.itemSlug);\n if (rejectBadItemSlug(itemSlug, kind, res)) return;\n const detail = await getItemDetail(kind, projectSlug, itemSlug);\n if (!detail) {\n res.status(404).json({ error: `${kind === 'memory' ? 'Memory' : 'Resource'} not found` });\n return;\n }\n res.json(detail);\n } catch (error) {\n console.error(`Error fetching ${kind} detail:`, error);\n res.status(500).json({ error: `Failed to load ${kind}: ${(error as Error).message}` });\n }\n });\n\n // POST — create\n router.post(`/api/projects/:slug/${folder}`, async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const projectDir = await resolveProjectDir(projectSlug);\n if (!projectDir) {\n res.status(404).json({ error: `Project \"${projectSlug}\" not found` });\n return;\n }\n\n const body = req.body ?? {};\n const name = typeof body.name === 'string' ? body.name.trim() : '';\n if (!name) {\n res.status(400).json({ error: 'Name is required.' });\n return;\n }\n\n const requestedSlug =\n typeof body.slug === 'string' && body.slug.trim() ? body.slug.trim() : slugify(name);\n if (!requestedSlug || !isValidSlug(requestedSlug)) {\n res.status(400).json({\n error: `Slug \"${requestedSlug}\" is invalid. Slugs must be lowercase letters, numbers, and hyphens only.`,\n });\n return;\n }\n\n const folderPath = resolve(projectDir, folder);\n await ensureDir(folderPath);\n const filePath = resolve(folderPath, `${requestedSlug}.md`);\n\n const timestamp = nowTimestamp();\n let content = renderItemStub(kind, {\n slug: requestedSlug,\n name,\n projectSlug: basename(projectDir),\n timestamp,\n });\n\n const customBody = typeof body.body === 'string' ? body.body : '';\n if (customBody.trim()) {\n content = replaceStubBody(content, customBody);\n }\n\n // Atomic create (`wx` flag fails if the file already exists). Closes the race window\n // where two concurrent POSTs both pass an existence check and the later write wins.\n try {\n const handle = await fsOpen(filePath, 'wx');\n try {\n await handle.writeFile(content, 'utf-8');\n } finally {\n await handle.close();\n }\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'EEXIST') {\n res.status(409).json({\n error: `${kind === 'memory' ? 'Memory' : 'Resource'} with slug \"${requestedSlug}\" already exists in project \"${basename(projectDir)}\".`,\n });\n return;\n }\n throw err;\n }\n\n res.status(201).json({ slug: requestedSlug, projectSlug: basename(projectDir), content });\n } catch (error) {\n console.error(`Error creating ${kind}:`, error);\n res.status(500).json({ error: `Failed to create ${kind}: ${(error as Error).message}` });\n }\n });\n\n // PATCH — body-only update\n router.patch(`/api/projects/:slug/${folder}/:itemSlug`, async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const itemSlug = getParam(req.params.itemSlug);\n if (rejectBadItemSlug(itemSlug, kind, res)) return;\n\n const projectDir = await resolveProjectDir(projectSlug);\n if (!projectDir) {\n res.status(404).json({ error: `Project \"${projectSlug}\" not found` });\n return;\n }\n const filePath = resolve(projectDir, folder, `${itemSlug}.md`);\n if (!(await fileExists(filePath))) {\n res.status(404).json({ error: `${kind === 'memory' ? 'Memory' : 'Resource'} not found` });\n return;\n }\n\n const nextContentRaw = requireContent(req, res);\n if (!nextContentRaw) return;\n\n const currentContent = await readFile(filePath, 'utf-8');\n const frontmatterBlock = extractFrontmatterBlock(currentContent);\n if (!frontmatterBlock) {\n res.status(500).json({ error: `${kind} file is malformed (no frontmatter)` });\n return;\n }\n\n const next = parseItem(kind, nextContentRaw);\n const nextBody = next.body.trimStart();\n\n let merged = `${frontmatterBlock}\\n${nextBody}${nextBody.endsWith('\\n') ? '' : '\\n'}`;\n merged = setTopLevelField(merged, 'updated', nowTimestamp());\n\n await writeFileForce(filePath, merged);\n const detail = await getItemDetail(kind, basename(projectDir), itemSlug);\n res.json({ [kind]: detail, content: merged });\n } catch (error) {\n console.error(`Error updating ${kind}:`, error);\n res.status(500).json({ error: `Failed to update ${kind}: ${(error as Error).message}` });\n }\n });\n\n // DELETE\n router.delete(`/api/projects/:slug/${folder}/:itemSlug`, async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const itemSlug = getParam(req.params.itemSlug);\n if (rejectBadItemSlug(itemSlug, kind, res)) return;\n\n const projectDir = await resolveProjectDir(projectSlug);\n if (!projectDir) {\n res.status(404).json({ error: `Project \"${projectSlug}\" not found` });\n return;\n }\n const filePath = resolve(projectDir, folder, `${itemSlug}.md`);\n if (!(await fileExists(filePath))) {\n res.status(404).json({ error: `${kind === 'memory' ? 'Memory' : 'Resource'} not found` });\n return;\n }\n await rm(filePath);\n res.status(204).end();\n } catch (error) {\n console.error(`Error deleting ${kind}:`, error);\n res.status(500).json({ error: `Failed to delete ${kind}: ${(error as Error).message}` });\n }\n });\n }\n\n router.post('/api/projects', async (req: Request, res: Response) => {\n try {\n const content = requireContent(req, res);\n if (!content) {\n return;\n }\n\n const fields = extractFrontmatter(content);\n if (!fields) {\n res.status(400).json({ error: 'Invalid frontmatter: missing --- delimiters' });\n return;\n }\n\n const validation = validateRequired(fields, ['slug', 'title']);\n if (!validation.valid) {\n res.status(400).json({ error: `Missing required fields: ${validation.missing.join(', ')}` });\n return;\n }\n\n const slug = fields.slug;\n if (!isValidSlug(slug)) {\n res.status(400).json({ error: `Invalid slug \"${slug}\". Must be lowercase and hyphen-separated.` });\n return;\n }\n\n const projectDir = resolve(projectsDir, slug);\n if (await fileExists(projectDir)) {\n res.status(409).json({ error: `Project \"${slug}\" already exists` });\n return;\n }\n\n const title = fields.title;\n const timestamp = fields.created || nowTimestamp();\n\n await ensureDir(resolve(projectDir, 'assignments'));\n await ensureDir(resolve(projectDir, 'resources'));\n await ensureDir(resolve(projectDir, 'memories'));\n\n await writeFileForce(resolve(projectDir, 'project.md'), content);\n\n try {\n const companions: Array<[string, string]> = [\n [resolve(projectDir, 'manifest.md'), renderManifest({ slug, timestamp })],\n [resolve(projectDir, '_index-assignments.md'), renderIndexAssignments({ slug, title, timestamp })],\n [resolve(projectDir, '_index-plans.md'), renderIndexPlans({ slug, title, timestamp })],\n [resolve(projectDir, '_index-decisions.md'), renderIndexDecisions({ slug, title, timestamp })],\n [resolve(projectDir, '_status.md'), renderStatus({ slug, title, timestamp })],\n [resolve(projectDir, 'resources', '_index.md'), renderResourcesIndex({ slug, title, timestamp })],\n [resolve(projectDir, 'memories', '_index.md'), renderMemoriesIndex({ slug, title, timestamp })],\n ];\n\n for (const [filePath, fileContent] of companions) {\n await writeFileForce(filePath, fileContent);\n }\n } catch (companionError) {\n try {\n await rm(projectDir, { recursive: true, force: true });\n } catch {\n // Best effort cleanup only.\n }\n throw companionError;\n }\n\n res.status(201).json({ slug });\n } catch (error) {\n console.error('Error creating project:', error);\n res.status(500).json({ error: `Failed to create project: ${(error as Error).message}` });\n }\n });\n\n router.post('/api/projects/:slug/assignments', async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const projectDir = resolve(projectsDir, projectSlug);\n const projectMdPath = resolve(projectDir, 'project.md');\n\n if (!(await fileExists(projectMdPath))) {\n res.status(404).json({ error: `Project \"${projectSlug}\" not found` });\n return;\n }\n\n const content = requireContent(req, res);\n if (!content) {\n return;\n }\n\n const fields = extractFrontmatter(content);\n if (!fields) {\n res.status(400).json({ error: 'Invalid frontmatter: missing --- delimiters' });\n return;\n }\n\n const validation = validateRequired(fields, ['slug', 'title']);\n if (!validation.valid) {\n res.status(400).json({ error: `Missing required fields: ${validation.missing.join(', ')}` });\n return;\n }\n\n const assignmentSlug = fields.slug;\n if (!isValidSlug(assignmentSlug)) {\n res.status(400).json({ error: `Invalid slug \"${assignmentSlug}\". Must be lowercase and hyphen-separated.` });\n return;\n }\n\n const validPriorities = ['low', 'medium', 'high', 'critical'];\n const priority = fields.priority || 'medium';\n if (!validPriorities.includes(priority)) {\n res.status(400).json({ error: `Invalid priority \"${priority}\". Must be low, medium, high, or critical.` });\n return;\n }\n\n const assignmentDir = resolve(projectDir, 'assignments', assignmentSlug);\n if (await fileExists(assignmentDir)) {\n res.status(409).json({\n error: `Assignment \"${assignmentSlug}\" already exists in project \"${projectSlug}\"`,\n });\n return;\n }\n\n const timestamp = fields.created || nowTimestamp();\n\n await ensureDir(assignmentDir);\n await writeFileForce(resolve(assignmentDir, 'assignment.md'), content);\n\n try {\n const companions: Array<[string, string]> = [\n [resolve(assignmentDir, 'scratchpad.md'), renderScratchpad({ assignmentSlug, timestamp })],\n [resolve(assignmentDir, 'handoff.md'), renderHandoff({ assignmentSlug, timestamp })],\n [resolve(assignmentDir, 'decision-record.md'), renderDecisionRecord({ assignmentSlug, timestamp })],\n ];\n\n for (const [filePath, fileContent] of companions) {\n await writeFileForce(filePath, fileContent);\n }\n } catch (companionError) {\n try {\n await rm(assignmentDir, { recursive: true, force: true });\n } catch {\n // Best effort cleanup only.\n }\n throw companionError;\n }\n\n res.status(201).json({ slug: assignmentSlug, projectSlug });\n } catch (error) {\n console.error('Error creating assignment:', error);\n res.status(500).json({ error: `Failed to create assignment: ${(error as Error).message}` });\n }\n });\n\n router.patch('/api/projects/:slug', async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const projectPath = resolve(projectsDir, projectSlug, 'project.md');\n const currentContent = await readCurrentDocument(projectPath);\n if (!currentContent) {\n res.status(404).json({ error: `Project \"${projectSlug}\" not found` });\n return;\n }\n\n const nextContentRaw = requireContent(req, res);\n if (!nextContentRaw) {\n return;\n }\n\n const current = parseProject(currentContent);\n const next = parseProject(nextContentRaw);\n\n if (!next.slug || !next.title) {\n res.status(400).json({ error: 'Project content must include slug and title.' });\n return;\n }\n\n if (next.slug !== current.slug) {\n res.status(400).json({ error: 'Project slug cannot be changed once created.' });\n return;\n }\n\n const nextContent = setTopLevelField(nextContentRaw, 'updated', nowTimestamp());\n await writeFileForce(projectPath, nextContent);\n\n const project = await getProjectDetail(projectsDir, projectSlug);\n res.json({ project, content: nextContent });\n } catch (error) {\n console.error('Error updating project:', error);\n res.status(500).json({ error: `Failed to update project: ${(error as Error).message}` });\n }\n });\n\n router.patch('/api/projects/:slug/assignments/:aslug', async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const assignmentSlug = getParam(req.params.aslug);\n const assignmentPath = resolve(\n projectsDir,\n projectSlug,\n 'assignments',\n assignmentSlug,\n 'assignment.md',\n );\n const currentContent = await readCurrentDocument(assignmentPath);\n if (!currentContent) {\n res.status(404).json({ error: 'Assignment not found' });\n return;\n }\n\n const nextContentRaw = requireContent(req, res);\n if (!nextContentRaw) {\n return;\n }\n\n const current = parseAssignmentFull(currentContent);\n const next = parseAssignmentFull(nextContentRaw);\n\n if (!next.slug || !next.title) {\n res.status(400).json({ error: 'Assignment content must include slug and title.' });\n return;\n }\n\n if (next.slug !== current.slug) {\n res.status(400).json({ error: 'Assignment slug cannot be changed once created.' });\n return;\n }\n\n let nextContent = nextContentRaw;\n\n // Clear blockedReason when status moves away from blocked\n if (next.status !== current.status && current.status === 'blocked' && next.status !== 'blocked') {\n nextContent = setTopLevelField(nextContent, 'blockedReason', null);\n }\n\n nextContent = setTopLevelField(nextContent, 'updated', nowTimestamp());\n await writeFileForce(assignmentPath, nextContent);\n\n const assignment = await getAssignmentDetail(projectsDir, projectSlug, assignmentSlug);\n res.json({ assignment, content: nextContent });\n } catch (error) {\n console.error('Error updating assignment:', error);\n res.status(500).json({ error: `Failed to update assignment: ${(error as Error).message}` });\n }\n });\n\n router.patch('/api/projects/:slug/assignments/:aslug/acceptance-criteria/:index', async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const assignmentSlug = getParam(req.params.aslug);\n const assignmentPath = resolve(\n projectsDir,\n projectSlug,\n 'assignments',\n assignmentSlug,\n 'assignment.md',\n );\n const currentContent = await readCurrentDocument(assignmentPath);\n if (!currentContent) {\n res.status(404).json({ error: 'Assignment not found' });\n return;\n }\n\n const { checked } = req.body || {};\n if (typeof checked !== 'boolean') {\n res.status(400).json({ error: 'checked must be a boolean' });\n return;\n }\n\n const index = Number.parseInt(getParam(req.params.index), 10);\n const result = toggleAcceptanceCriterion(currentContent, index, checked);\n if ('error' in result) {\n res.status(400).json({ error: result.error });\n return;\n }\n\n const nextContent = setTopLevelField(result.content, 'updated', nowTimestamp());\n await writeFileForce(assignmentPath, nextContent);\n\n const assignment = await getAssignmentDetail(projectsDir, projectSlug, assignmentSlug);\n res.json({ assignment, content: nextContent });\n } catch (error) {\n console.error('Error toggling acceptance criterion:', error);\n res.status(500).json({ error: `Failed to toggle acceptance criterion: ${(error as Error).message}` });\n }\n });\n\n router.patch('/api/projects/:slug/assignments/:aslug/plan', async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const assignmentSlug = getParam(req.params.aslug);\n const planPath = resolve(\n projectsDir,\n projectSlug,\n 'assignments',\n assignmentSlug,\n 'plan.md',\n );\n const currentContent = await readCurrentDocument(planPath);\n if (!currentContent) {\n res.status(404).json({ error: 'Plan not found' });\n return;\n }\n\n const nextContentRaw = requireContent(req, res);\n if (!nextContentRaw) {\n return;\n }\n\n const next = parsePlan(nextContentRaw);\n if (!next.assignment) {\n res.status(400).json({ error: 'Plan content must include the assignment field.' });\n return;\n }\n\n if (next.assignment !== assignmentSlug) {\n res.status(400).json({ error: 'Plan assignment field must match the route assignment slug.' });\n return;\n }\n\n const nextContent = setTopLevelField(nextContentRaw, 'updated', nowTimestamp());\n await writeFileForce(planPath, nextContent);\n\n const assignment = await getAssignmentDetail(projectsDir, projectSlug, assignmentSlug);\n res.json({ assignment, content: nextContent });\n } catch (error) {\n console.error('Error updating plan:', error);\n res.status(500).json({ error: `Failed to update plan: ${(error as Error).message}` });\n }\n });\n\n router.patch('/api/projects/:slug/assignments/:aslug/scratchpad', async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const assignmentSlug = getParam(req.params.aslug);\n const scratchpadPath = resolve(\n projectsDir,\n projectSlug,\n 'assignments',\n assignmentSlug,\n 'scratchpad.md',\n );\n const currentContent = await readCurrentDocument(scratchpadPath);\n if (!currentContent) {\n res.status(404).json({ error: 'Scratchpad not found' });\n return;\n }\n\n const nextContentRaw = requireContent(req, res);\n if (!nextContentRaw) {\n return;\n }\n\n const next = parseScratchpad(nextContentRaw);\n if (!next.assignment) {\n res.status(400).json({ error: 'Scratchpad content must include the assignment field.' });\n return;\n }\n\n if (next.assignment !== assignmentSlug) {\n res.status(400).json({ error: 'Scratchpad assignment field must match the route assignment slug.' });\n return;\n }\n\n const nextContent = setTopLevelField(nextContentRaw, 'updated', nowTimestamp());\n await writeFileForce(scratchpadPath, nextContent);\n\n const assignment = await getAssignmentDetail(projectsDir, projectSlug, assignmentSlug);\n res.json({ assignment, content: nextContent });\n } catch (error) {\n console.error('Error updating scratchpad:', error);\n res.status(500).json({ error: `Failed to update scratchpad: ${(error as Error).message}` });\n }\n });\n\n router.post('/api/projects/:slug/assignments/:aslug/handoff/entries', async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const assignmentSlug = getParam(req.params.aslug);\n const handoffPath = resolve(\n projectsDir,\n projectSlug,\n 'assignments',\n assignmentSlug,\n 'handoff.md',\n );\n const currentContent = await readCurrentDocument(handoffPath);\n if (!currentContent) {\n res.status(404).json({ error: 'Handoff log not found' });\n return;\n }\n\n const { title, body } = req.body || {};\n if (!body || typeof body !== 'string' || !body.trim()) {\n res.status(400).json({ error: 'body is required' });\n return;\n }\n\n const parsed = parseHandoff(currentContent);\n const nextContent = appendLogEntry(\n currentContent,\n 'handoffCount',\n parsed.handoffCount + 1,\n title && typeof title === 'string' && title.trim() ? title.trim() : `Handoff ${parsed.handoffCount + 1}`,\n body,\n 'No handoffs recorded yet.',\n );\n\n await writeFileForce(handoffPath, nextContent);\n const assignment = await getAssignmentDetail(projectsDir, projectSlug, assignmentSlug);\n res.status(201).json({ assignment, content: nextContent });\n } catch (error) {\n console.error('Error appending handoff entry:', error);\n res.status(500).json({ error: `Failed to append handoff entry: ${(error as Error).message}` });\n }\n });\n\n router.post('/api/projects/:slug/assignments/:aslug/decision-record/entries', async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const assignmentSlug = getParam(req.params.aslug);\n const decisionPath = resolve(\n projectsDir,\n projectSlug,\n 'assignments',\n assignmentSlug,\n 'decision-record.md',\n );\n const currentContent = await readCurrentDocument(decisionPath);\n if (!currentContent) {\n res.status(404).json({ error: 'Decision record not found' });\n return;\n }\n\n const { title, body } = req.body || {};\n if (!body || typeof body !== 'string' || !body.trim()) {\n res.status(400).json({ error: 'body is required' });\n return;\n }\n\n const parsed = parseDecisionRecord(currentContent);\n const nextContent = appendLogEntry(\n currentContent,\n 'decisionCount',\n parsed.decisionCount + 1,\n title && typeof title === 'string' && title.trim() ? title.trim() : `Decision ${parsed.decisionCount + 1}`,\n body,\n 'No decisions recorded yet.',\n );\n\n await writeFileForce(decisionPath, nextContent);\n const assignment = await getAssignmentDetail(projectsDir, projectSlug, assignmentSlug);\n res.status(201).json({ assignment, content: nextContent });\n } catch (error) {\n console.error('Error appending decision entry:', error);\n res.status(500).json({ error: `Failed to append decision entry: ${(error as Error).message}` });\n }\n });\n\n // --- Comments Endpoints ---\n\n router.post('/api/projects/:slug/assignments/:aslug/comments', async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const assignmentSlug = getParam(req.params.aslug);\n const commentsPath = resolve(\n projectsDir,\n projectSlug,\n 'assignments',\n assignmentSlug,\n 'comments.md',\n );\n\n const { body, author, type, replyTo } = req.body || {};\n if (!body || typeof body !== 'string' || !body.trim()) {\n res.status(400).json({ error: 'body is required' });\n return;\n }\n const commentType: CommentType = type && ['question', 'note', 'feedback'].includes(type)\n ? type\n : 'note';\n const timestamp = nowTimestamp();\n const entryAuthor = (typeof author === 'string' && author.trim()) ? author.trim() : 'human';\n\n let currentContent: string;\n let currentCount = 0;\n if (await fileExists(commentsPath)) {\n currentContent = await readFile(commentsPath, 'utf-8');\n const countMatch = currentContent.match(/^entryCount:\\s*(\\d+)/m);\n if (countMatch) currentCount = parseInt(countMatch[1], 10);\n } else {\n currentContent = renderComments({\n assignment: assignmentSlug,\n timestamp,\n });\n }\n\n const comment: Comment = {\n id: generateId().split('-')[0],\n timestamp,\n author: entryAuthor,\n type: commentType,\n body,\n replyTo: typeof replyTo === 'string' && replyTo.trim() ? replyTo.trim() : undefined,\n resolved: commentType === 'question' ? false : undefined,\n };\n const entry = formatCommentEntry(comment);\n let next = setTopLevelField(currentContent, 'entryCount', String(currentCount + 1));\n next = setTopLevelField(next, 'updated', `\"${timestamp}\"`);\n if (next.includes('No comments yet.')) {\n next = next.replace('No comments yet.', entry.trimEnd());\n } else {\n next = `${next.trimEnd()}\\n\\n${entry}`;\n }\n\n await writeFileForce(commentsPath, next);\n const assignment = await getAssignmentDetail(projectsDir, projectSlug, assignmentSlug);\n res.status(201).json({ assignment, comment: { id: comment.id } });\n } catch (error) {\n console.error('Error appending comment:', error);\n res.status(500).json({ error: `Failed to append comment: ${(error as Error).message}` });\n }\n });\n\n router.patch('/api/projects/:slug/assignments/:aslug/comments/:commentId/resolved', async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const assignmentSlug = getParam(req.params.aslug);\n const commentId = getParam(req.params.commentId);\n const commentsPath = resolve(\n projectsDir,\n projectSlug,\n 'assignments',\n assignmentSlug,\n 'comments.md',\n );\n if (!(await fileExists(commentsPath))) {\n res.status(404).json({ error: 'Comments file not found' });\n return;\n }\n const { resolved } = req.body || {};\n if (typeof resolved !== 'boolean') {\n res.status(400).json({ error: 'resolved (boolean) is required' });\n return;\n }\n\n const content = await readFile(commentsPath, 'utf-8');\n const parsed = parseComments(content);\n const target = parsed.entries.find((e) => e.id === commentId);\n if (!target) {\n res.status(404).json({ error: `Comment ${commentId} not found` });\n return;\n }\n if (target.type !== 'question') {\n res.status(400).json({ error: 'Only questions can be resolved' });\n return;\n }\n\n // Toggle the `**Resolved:**` line in the entry's block.\n const entryBlockRegex = new RegExp(\n `(^## ${commentId.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}[\\\\s\\\\S]*?)(\\\\*\\\\*Resolved:\\\\*\\\\*\\\\s*(?:true|false))`,\n 'm',\n );\n const next = content.replace(\n entryBlockRegex,\n (_m, preamble) => `${preamble}**Resolved:** ${resolved ? 'true' : 'false'}`,\n );\n if (next === content) {\n res.status(500).json({ error: 'Failed to update resolved flag' });\n return;\n }\n\n const withUpdated = setTopLevelField(next, 'updated', `\"${nowTimestamp()}\"`);\n await writeFileForce(commentsPath, withUpdated);\n const assignment = await getAssignmentDetail(projectsDir, projectSlug, assignmentSlug);\n res.json({ assignment });\n } catch (error) {\n console.error('Error toggling comment resolved flag:', error);\n res.status(500).json({ error: `Failed to toggle resolved: ${(error as Error).message}` });\n }\n });\n\n // --- Move Workspace Endpoint ---\n\n router.post('/api/projects/:slug/move-workspace', async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const projectPath = resolve(projectsDir, projectSlug, 'project.md');\n if (!(await fileExists(projectPath))) {\n res.status(404).json({ error: `Project \"${projectSlug}\" not found` });\n return;\n }\n\n const { workspace } = req.body || {};\n if (\n workspace !== null &&\n (typeof workspace !== 'string' || !workspace.trim() || !isValidSlug(workspace))\n ) {\n // isValidSlug forbids newlines, colons, and other YAML metacharacters,\n // so we can safely write the value into frontmatter without escaping.\n res.status(400).json({\n error:\n 'workspace must be a valid slug (lowercase letters, numbers, hyphens) or null (for ungrouped).',\n });\n return;\n }\n\n let content = await readFile(projectPath, 'utf-8');\n content = setTopLevelField(content, 'workspace', workspace ?? null);\n content = setTopLevelField(content, 'updated', nowTimestamp());\n await writeFileForce(projectPath, content);\n\n const project = await getProjectDetail(projectsDir, projectSlug);\n res.json({ project });\n } catch (error) {\n console.error('Error moving project workspace:', error);\n res.status(500).json({ error: `Failed to move workspace: ${(error as Error).message}` });\n }\n });\n\n router.post('/api/assignments/:id/move-workspace', async (req: Request, res: Response) => {\n try {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n\n const id = getParam(req.params.id);\n const resolved = await resolveAssignmentById(projectsDir, assignmentsDir, id);\n if (!resolved) {\n res.status(404).json({ error: `Assignment \"${id}\" not found` });\n return;\n }\n if (!resolved.standalone) {\n res.status(400).json({\n error:\n 'Project-nested assignments inherit workspace from their parent project. Move the project instead.',\n });\n return;\n }\n\n const { workspaceGroup } = req.body || {};\n if (\n workspaceGroup !== null &&\n (typeof workspaceGroup !== 'string' || !workspaceGroup.trim() || !isValidSlug(workspaceGroup))\n ) {\n // See workspace move route above: isValidSlug guards against frontmatter injection.\n res.status(400).json({\n error:\n 'workspaceGroup must be a valid slug (lowercase letters, numbers, hyphens) or null (for ungrouped).',\n });\n return;\n }\n\n const assignmentPath = resolve(resolved.assignmentDir, 'assignment.md');\n let content = await readFile(assignmentPath, 'utf-8');\n content = setTopLevelField(content, 'workspaceGroup', workspaceGroup ?? null);\n content = setTopLevelField(content, 'updated', nowTimestamp());\n await writeFileForce(assignmentPath, content);\n\n const assignment = await getAssignmentDetailById(projectsDir, assignmentsDir, id);\n res.json({ assignment });\n } catch (error) {\n console.error('Error moving assignment workspace:', error);\n res.status(500).json({ error: `Failed to move workspace: ${(error as Error).message}` });\n }\n });\n\n // --- Status Override Endpoints ---\n\n router.post('/api/projects/:slug/status-override', async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const projectPath = resolve(projectsDir, projectSlug, 'project.md');\n if (!(await fileExists(projectPath))) {\n res.status(404).json({ error: `Project \"${projectSlug}\" not found` });\n return;\n }\n\n const { status } = req.body || {};\n const config = await getStatusConfig();\n const validStatuses = ['active', 'archived', ...config.statuses.map((s) => s.id)];\n if (status !== null && (typeof status !== 'string' || !validStatuses.includes(status))) {\n res.status(400).json({ error: `Invalid status. Must be one of: ${validStatuses.join(', ')}, or null to clear.` });\n return;\n }\n\n let content = await readFile(projectPath, 'utf-8');\n content = setTopLevelField(content, 'statusOverride', status ?? null);\n content = setTopLevelField(content, 'updated', nowTimestamp());\n await writeFileForce(projectPath, content);\n\n const project = await getProjectDetail(projectsDir, projectSlug);\n res.json({ project });\n } catch (error) {\n console.error('Error setting project status override:', error);\n res.status(500).json({ error: `Failed to set status override: ${(error as Error).message}` });\n }\n });\n\n router.post('/api/projects/:slug/assignments/:aslug/status-override', async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const assignmentSlug = getParam(req.params.aslug);\n const assignmentPath = resolve(\n projectsDir,\n projectSlug,\n 'assignments',\n assignmentSlug,\n 'assignment.md',\n );\n if (!(await fileExists(assignmentPath))) {\n res.status(404).json({ error: 'Assignment not found' });\n return;\n }\n\n const { status } = req.body || {};\n const config = await getStatusConfig();\n const validStatuses = config.statuses.map((s) => s.id);\n if (typeof status !== 'string' || !validStatuses.includes(status)) {\n res.status(400).json({ error: `Invalid status. Must be one of: ${validStatuses.join(', ')}.` });\n return;\n }\n\n let content = await readFile(assignmentPath, 'utf-8');\n content = setTopLevelField(content, 'status', status);\n content = setTopLevelField(content, 'updated', nowTimestamp());\n\n // Clear blockedReason when moving away from blocked\n if (status !== 'blocked') {\n content = setTopLevelField(content, 'blockedReason', null);\n }\n\n await writeFileForce(assignmentPath, content);\n\n const assignment = await getAssignmentDetail(projectsDir, projectSlug, assignmentSlug);\n res.json({ assignment });\n } catch (error) {\n console.error('Error overriding assignment status:', error);\n res.status(500).json({ error: `Failed to override status: ${(error as Error).message}` });\n }\n });\n\n router.patch('/api/projects/:slug/assignments/:aslug/assignee', async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const assignmentSlug = getParam(req.params.aslug);\n const assignmentPath = resolve(\n projectsDir,\n projectSlug,\n 'assignments',\n assignmentSlug,\n 'assignment.md',\n );\n if (!(await fileExists(assignmentPath))) {\n res.status(404).json({ error: 'Assignment not found' });\n return;\n }\n const validation = validateAssigneeBody(req.body);\n if (!validation.ok) {\n res.status(400).json({ error: validation.error });\n return;\n }\n let content = await readFile(assignmentPath, 'utf-8');\n content = setTopLevelField(content, 'assignee', validation.value);\n content = setTopLevelField(content, 'updated', nowTimestamp());\n await writeFileForce(assignmentPath, content);\n const assignment = await getAssignmentDetail(projectsDir, projectSlug, assignmentSlug);\n res.json({ assignment });\n } catch (error) {\n console.error('Error updating assignee:', error);\n res.status(500).json({ error: `Failed to update assignee: ${(error as Error).message}` });\n }\n });\n\n // --- Lifecycle Transitions ---\n\n router.post('/api/projects/:slug/assignments/:aslug/transitions/:command', async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const assignmentSlug = getParam(req.params.aslug);\n const command = req.params.command as Parameters<typeof executeTransition>[2];\n const config = await getStatusConfig();\n const validCommands = [...new Set(config.transitions.map((t) => t.command))];\n if (!validCommands.includes(command)) {\n res.status(400).json({ error: `Unsupported transition command \"${req.params.command}\"` });\n return;\n }\n\n const projectDir = resolve(projectsDir, projectSlug);\n const assignmentPath = resolve(projectDir, 'assignments', assignmentSlug, 'assignment.md');\n if (!(await fileExists(assignmentPath))) {\n res.status(404).json({ error: 'Assignment not found' });\n return;\n }\n\n const { reason } = req.body || {};\n const result = await executeTransition(projectDir, assignmentSlug, command, {\n reason: typeof reason === 'string' ? reason : undefined,\n transitionTable: config.custom ? config.transitionTable : undefined,\n terminalStatuses: config.custom ? config.terminalStatuses : undefined,\n linkedTodosLookup,\n });\n\n if (!result.success) {\n res.status(400).json({ error: result.message });\n return;\n }\n\n const assignment = await getAssignmentDetail(projectsDir, projectSlug, assignmentSlug);\n res.json({ assignment, transition: result });\n } catch (error) {\n console.error('Error running assignment transition:', error);\n res.status(500).json({ error: `Failed to transition assignment: ${(error as Error).message}` });\n }\n });\n\n router.delete('/api/projects/:slug/assignments/:aslug', async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const assignmentSlug = getParam(req.params.aslug);\n const assignmentDir = resolve(projectsDir, projectSlug, 'assignments', assignmentSlug);\n const assignmentPath = resolve(assignmentDir, 'assignment.md');\n\n if (!(await fileExists(assignmentPath))) {\n res.status(404).json({ error: `Assignment \"${assignmentSlug}\" not found in project \"${projectSlug}\"` });\n return;\n }\n\n await rm(assignmentDir, { recursive: true, force: true });\n res.json({ deleted: assignmentSlug, projectSlug });\n } catch (error) {\n console.error('Error deleting assignment:', error);\n res.status(500).json({ error: `Failed to delete assignment: ${(error as Error).message}` });\n }\n });\n\n // =========================================================================\n // Standalone (by-id) routes — `~/.syntaur/assignments/<uuid>/`\n // Active only when the write router was constructed with an assignmentsDir.\n // =========================================================================\n\n router.post('/api/assignments', async (req: Request, res: Response) => {\n try {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n\n // Two body shapes are supported:\n // 1) { content: <markdown> } — same shape as POST /api/projects/:slug/assignments. Used by the dashboard UI.\n // 2) { title, slug?, priority?, type? } — original structured form, retained for back-compat.\n const rawContent = typeof req.body?.content === 'string' ? req.body.content : '';\n if (rawContent.trim()) {\n const fields = extractFrontmatter(rawContent);\n if (!fields) {\n res.status(400).json({ error: 'Invalid frontmatter: missing --- delimiters' });\n return;\n }\n const validation = validateRequired(fields, ['slug', 'title']);\n if (!validation.valid) {\n res.status(400).json({ error: `Missing required fields: ${validation.missing.join(', ')}` });\n return;\n }\n const submittedSlug = fields.slug;\n if (!isValidSlug(submittedSlug)) {\n res.status(400).json({ error: `Invalid slug \"${submittedSlug}\". Must be lowercase and hyphen-separated.` });\n return;\n }\n const validPriorities = ['low', 'medium', 'high', 'critical'];\n const submittedPriority = fields.priority || 'medium';\n if (!validPriorities.includes(submittedPriority)) {\n res.status(400).json({ error: `Invalid priority \"${submittedPriority}\". Must be low, medium, high, or critical.` });\n return;\n }\n\n // Standalone-specific guards: no project, optional workspaceGroup.\n if (fields.project && fields.project !== 'null') {\n res.status(400).json({\n error: 'Standalone assignments cannot have a project; remove \"project\" or set it to null.',\n });\n return;\n }\n const submittedWorkspaceGroup = fields.workspaceGroup && fields.workspaceGroup !== 'null'\n ? fields.workspaceGroup\n : '';\n if (submittedWorkspaceGroup && !isValidSlug(submittedWorkspaceGroup)) {\n res.status(400).json({\n error: `Invalid workspace slug \"${submittedWorkspaceGroup}\". Slugs must be lowercase, hyphen-separated, with no special characters.`,\n });\n return;\n }\n\n const id = generateId();\n const assignmentDir = resolve(assignmentsDir, id);\n if (await fileExists(assignmentDir)) {\n res.status(500).json({ error: 'UUID collision — try again' });\n return;\n }\n\n const timestamp = fields.created || nowTimestamp();\n await ensureDir(assignmentDir);\n // Normalize the frontmatter id to the freshly-generated UUID — the template ships a placeholder.\n const normalizedContent = setTopLevelField(rawContent, 'id', id);\n await writeFileForce(resolve(assignmentDir, 'assignment.md'), normalizedContent);\n await writeFileForce(\n resolve(assignmentDir, 'scratchpad.md'),\n renderScratchpad({ assignmentSlug: id, timestamp }),\n );\n await writeFileForce(\n resolve(assignmentDir, 'handoff.md'),\n renderHandoff({ assignmentSlug: id, timestamp }),\n );\n await writeFileForce(\n resolve(assignmentDir, 'decision-record.md'),\n renderDecisionRecord({ assignmentSlug: id, timestamp }),\n );\n await writeFileForce(\n resolve(assignmentDir, 'progress.md'),\n renderProgress({ assignment: id, timestamp }),\n );\n await writeFileForce(\n resolve(assignmentDir, 'comments.md'),\n renderComments({ assignment: id, timestamp }),\n );\n\n const detail = await getAssignmentDetailById(projectsDir, assignmentsDir, id);\n res.status(201).json({ assignment: detail });\n return;\n }\n\n // Structured-form path (back-compat).\n const { title, slug, priority, type } = req.body || {};\n if (!title || typeof title !== 'string' || !title.trim()) {\n res.status(400).json({ error: 'title is required' });\n return;\n }\n const { dependsOn } = req.body || {};\n if (Array.isArray(dependsOn) && dependsOn.length > 0) {\n res.status(400).json({ error: 'Standalone assignments cannot declare dependsOn.' });\n return;\n }\n\n const id = generateId();\n const assignmentDir = resolve(assignmentsDir, id);\n if (await fileExists(assignmentDir)) {\n res.status(500).json({ error: 'UUID collision — try again' });\n return;\n }\n\n const timestamp = nowTimestamp();\n const resolvedSlug = typeof slug === 'string' && slug.trim() ? slug.trim() : slugifyLocal(title);\n const resolvedPriority = (typeof priority === 'string' && ['low', 'medium', 'high', 'critical'].includes(priority))\n ? (priority as 'low' | 'medium' | 'high' | 'critical')\n : 'medium';\n\n await ensureDir(assignmentDir);\n const assignmentContent = renderAssignment({\n id,\n slug: resolvedSlug,\n title: title.trim(),\n timestamp,\n priority: resolvedPriority,\n dependsOn: [],\n links: [],\n project: null,\n type: typeof type === 'string' ? type : undefined,\n });\n await writeFileForce(resolve(assignmentDir, 'assignment.md'), assignmentContent);\n await writeFileForce(\n resolve(assignmentDir, 'scratchpad.md'),\n renderScratchpad({ assignmentSlug: id, timestamp }),\n );\n await writeFileForce(\n resolve(assignmentDir, 'handoff.md'),\n renderHandoff({ assignmentSlug: id, timestamp }),\n );\n await writeFileForce(\n resolve(assignmentDir, 'decision-record.md'),\n renderDecisionRecord({ assignmentSlug: id, timestamp }),\n );\n await writeFileForce(\n resolve(assignmentDir, 'progress.md'),\n renderProgress({ assignment: id, timestamp }),\n );\n await writeFileForce(\n resolve(assignmentDir, 'comments.md'),\n renderComments({ assignment: id, timestamp }),\n );\n\n const detail = await getAssignmentDetailById(projectsDir, assignmentsDir, id);\n res.status(201).json({ assignment: detail });\n } catch (error) {\n console.error('Error creating standalone assignment:', error);\n res.status(500).json({ error: `Failed to create standalone assignment: ${(error as Error).message}` });\n }\n });\n\n router.post('/api/assignments/:id/comments', async (req: Request, res: Response) => {\n try {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n const id = getParam(req.params.id);\n const resolved = await resolveAssignmentById(projectsDir, assignmentsDir, id);\n if (!resolved) {\n res.status(404).json({ error: `Assignment \"${id}\" not found` });\n return;\n }\n await appendCommentTo(resolved.assignmentDir, resolved.standalone ? resolved.id : resolved.assignmentSlug, req, res, async () => {\n return resolved.standalone\n ? getAssignmentDetailById(projectsDir, assignmentsDir, id)\n : getAssignmentDetail(projectsDir, resolved.projectSlug!, resolved.assignmentSlug);\n });\n } catch (error) {\n console.error('Error appending comment (by id):', error);\n res.status(500).json({ error: `Failed to append comment: ${(error as Error).message}` });\n }\n });\n\n router.patch('/api/assignments/:id/comments/:commentId/resolved', async (req: Request, res: Response) => {\n try {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n const id = getParam(req.params.id);\n const commentId = getParam(req.params.commentId);\n const resolved = await resolveAssignmentById(projectsDir, assignmentsDir, id);\n if (!resolved) {\n res.status(404).json({ error: `Assignment \"${id}\" not found` });\n return;\n }\n await toggleCommentResolvedAt(resolved.assignmentDir, commentId, req, res, async () => {\n return resolved.standalone\n ? getAssignmentDetailById(projectsDir, assignmentsDir, id)\n : getAssignmentDetail(projectsDir, resolved.projectSlug!, resolved.assignmentSlug);\n });\n } catch (error) {\n console.error('Error toggling comment resolved (by id):', error);\n res.status(500).json({ error: `Failed to toggle resolved: ${(error as Error).message}` });\n }\n });\n\n router.get('/api/assignments/:id/edit', async (req: Request, res: Response) => {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n const id = getParam(req.params.id);\n const doc = await getEditableDocumentById(projectsDir, assignmentsDir, 'assignment', id);\n if (!doc) {\n res.status(404).json({ error: 'Assignment not found' });\n return;\n }\n res.json(doc);\n });\n\n router.get('/api/assignments/:id/plan/edit', async (req: Request, res: Response) => {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n const id = getParam(req.params.id);\n const doc = await getEditableDocumentById(projectsDir, assignmentsDir, 'plan', id);\n if (!doc) {\n res.status(404).json({ error: 'Plan not found' });\n return;\n }\n res.json(doc);\n });\n\n router.get('/api/assignments/:id/scratchpad/edit', async (req: Request, res: Response) => {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n const id = getParam(req.params.id);\n const doc = await getEditableDocumentById(projectsDir, assignmentsDir, 'scratchpad', id);\n if (!doc) {\n res.status(404).json({ error: 'Scratchpad not found' });\n return;\n }\n res.json(doc);\n });\n\n router.get('/api/assignments/:id/handoff/edit', async (req: Request, res: Response) => {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n const id = getParam(req.params.id);\n const doc = await getEditableDocumentById(projectsDir, assignmentsDir, 'handoff', id);\n if (!doc) {\n res.status(404).json({ error: 'Handoff log not found' });\n return;\n }\n res.json(doc);\n });\n\n router.get('/api/assignments/:id/decision-record/edit', async (req: Request, res: Response) => {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n const id = getParam(req.params.id);\n const doc = await getEditableDocumentById(projectsDir, assignmentsDir, 'decision-record', id);\n if (!doc) {\n res.status(404).json({ error: 'Decision record not found' });\n return;\n }\n res.json(doc);\n });\n\n router.patch('/api/assignments/:id', async (req: Request, res: Response) => {\n try {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n const id = getParam(req.params.id);\n const resolved = await resolveAssignmentById(projectsDir, assignmentsDir, id);\n if (!resolved) {\n res.status(404).json({ error: `Assignment \"${id}\" not found` });\n return;\n }\n\n const assignmentPath = resolve(resolved.assignmentDir, 'assignment.md');\n const currentContent = await readCurrentDocument(assignmentPath);\n if (!currentContent) {\n res.status(404).json({ error: 'Assignment not found' });\n return;\n }\n\n const nextContentRaw = requireContent(req, res);\n if (!nextContentRaw) return;\n\n const current = parseAssignmentFull(currentContent);\n const next = parseAssignmentFull(nextContentRaw);\n\n if (!next.title) {\n res.status(400).json({ error: 'Assignment content must include a title.' });\n return;\n }\n\n // Standalone: restore id + project + slug frontmatter (all immutable after create).\n let nextContent = nextContentRaw;\n if (current.id) nextContent = setTopLevelField(nextContent, 'id', current.id);\n nextContent = setTopLevelField(nextContent, 'project', null);\n if (current.slug) nextContent = setTopLevelField(nextContent, 'slug', current.slug);\n\n if (next.status !== current.status && current.status === 'blocked' && next.status !== 'blocked') {\n nextContent = setTopLevelField(nextContent, 'blockedReason', null);\n }\n\n nextContent = setTopLevelField(nextContent, 'updated', nowTimestamp());\n await writeFileForce(assignmentPath, nextContent);\n\n const assignment = await getAssignmentDetailById(projectsDir, assignmentsDir, id);\n res.json({ assignment, content: nextContent });\n } catch (error) {\n console.error('Error updating standalone assignment:', error);\n res.status(500).json({ error: `Failed to update assignment: ${(error as Error).message}` });\n }\n });\n\n router.patch('/api/assignments/:id/plan', async (req: Request, res: Response) => {\n try {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n const id = getParam(req.params.id);\n const resolved = await resolveAssignmentById(projectsDir, assignmentsDir, id);\n if (!resolved) {\n res.status(404).json({ error: `Assignment \"${id}\" not found` });\n return;\n }\n\n const planPath = resolve(resolved.assignmentDir, 'plan.md');\n const currentContent = await readCurrentDocument(planPath);\n if (!currentContent) {\n res.status(404).json({ error: 'Plan not found' });\n return;\n }\n const nextContentRaw = requireContent(req, res);\n if (!nextContentRaw) return;\n\n const parsed = parsePlan(nextContentRaw);\n if (!parsed.assignment) {\n res.status(400).json({ error: 'Plan content must include the assignment field.' });\n return;\n }\n\n const nextContent = setTopLevelField(nextContentRaw, 'updated', nowTimestamp());\n await writeFileForce(planPath, nextContent);\n\n const assignment = await getAssignmentDetailById(projectsDir, assignmentsDir, id);\n res.json({ assignment, content: nextContent });\n } catch (error) {\n console.error('Error updating standalone plan:', error);\n res.status(500).json({ error: `Failed to update plan: ${(error as Error).message}` });\n }\n });\n\n router.patch('/api/assignments/:id/scratchpad', async (req: Request, res: Response) => {\n try {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n const id = getParam(req.params.id);\n const resolved = await resolveAssignmentById(projectsDir, assignmentsDir, id);\n if (!resolved) {\n res.status(404).json({ error: `Assignment \"${id}\" not found` });\n return;\n }\n\n const scratchpadPath = resolve(resolved.assignmentDir, 'scratchpad.md');\n const currentContent = await readCurrentDocument(scratchpadPath);\n if (!currentContent) {\n res.status(404).json({ error: 'Scratchpad not found' });\n return;\n }\n const nextContentRaw = requireContent(req, res);\n if (!nextContentRaw) return;\n\n const parsed = parseScratchpad(nextContentRaw);\n if (!parsed.assignment) {\n res.status(400).json({ error: 'Scratchpad content must include the assignment field.' });\n return;\n }\n\n const nextContent = setTopLevelField(nextContentRaw, 'updated', nowTimestamp());\n await writeFileForce(scratchpadPath, nextContent);\n\n const assignment = await getAssignmentDetailById(projectsDir, assignmentsDir, id);\n res.json({ assignment, content: nextContent });\n } catch (error) {\n console.error('Error updating standalone scratchpad:', error);\n res.status(500).json({ error: `Failed to update scratchpad: ${(error as Error).message}` });\n }\n });\n\n router.post('/api/assignments/:id/handoff/entries', async (req: Request, res: Response) => {\n try {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n const id = getParam(req.params.id);\n const resolved = await resolveAssignmentById(projectsDir, assignmentsDir, id);\n if (!resolved) {\n res.status(404).json({ error: `Assignment \"${id}\" not found` });\n return;\n }\n const handoffPath = resolve(resolved.assignmentDir, 'handoff.md');\n const currentContent = await readCurrentDocument(handoffPath);\n if (!currentContent) {\n res.status(404).json({ error: 'Handoff log not found' });\n return;\n }\n const { title, body } = req.body || {};\n if (!body || typeof body !== 'string' || !body.trim()) {\n res.status(400).json({ error: 'body is required' });\n return;\n }\n const parsed = parseHandoff(currentContent);\n const nextContent = appendLogEntry(\n currentContent,\n 'handoffCount',\n parsed.handoffCount + 1,\n title && typeof title === 'string' && title.trim() ? title.trim() : `Handoff ${parsed.handoffCount + 1}`,\n body,\n 'No handoffs recorded yet.',\n );\n await writeFileForce(handoffPath, nextContent);\n const assignment = await getAssignmentDetailById(projectsDir, assignmentsDir, id);\n res.status(201).json({ assignment, content: nextContent });\n } catch (error) {\n console.error('Error appending standalone handoff entry:', error);\n res.status(500).json({ error: `Failed to append handoff entry: ${(error as Error).message}` });\n }\n });\n\n router.post('/api/assignments/:id/decision-record/entries', async (req: Request, res: Response) => {\n try {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n const id = getParam(req.params.id);\n const resolved = await resolveAssignmentById(projectsDir, assignmentsDir, id);\n if (!resolved) {\n res.status(404).json({ error: `Assignment \"${id}\" not found` });\n return;\n }\n const decisionPath = resolve(resolved.assignmentDir, 'decision-record.md');\n const currentContent = await readCurrentDocument(decisionPath);\n if (!currentContent) {\n res.status(404).json({ error: 'Decision record not found' });\n return;\n }\n const { title, body } = req.body || {};\n if (!body || typeof body !== 'string' || !body.trim()) {\n res.status(400).json({ error: 'body is required' });\n return;\n }\n const parsed = parseDecisionRecord(currentContent);\n const nextContent = appendLogEntry(\n currentContent,\n 'decisionCount',\n parsed.decisionCount + 1,\n title && typeof title === 'string' && title.trim() ? title.trim() : `Decision ${parsed.decisionCount + 1}`,\n body,\n 'No decisions recorded yet.',\n );\n await writeFileForce(decisionPath, nextContent);\n const assignment = await getAssignmentDetailById(projectsDir, assignmentsDir, id);\n res.status(201).json({ assignment, content: nextContent });\n } catch (error) {\n console.error('Error appending standalone decision entry:', error);\n res.status(500).json({ error: `Failed to append decision entry: ${(error as Error).message}` });\n }\n });\n\n router.post('/api/assignments/:id/status-override', async (req: Request, res: Response) => {\n try {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n const id = getParam(req.params.id);\n const resolved = await resolveAssignmentById(projectsDir, assignmentsDir, id);\n if (!resolved) {\n res.status(404).json({ error: `Assignment \"${id}\" not found` });\n return;\n }\n const assignmentPath = resolve(resolved.assignmentDir, 'assignment.md');\n if (!(await fileExists(assignmentPath))) {\n res.status(404).json({ error: 'Assignment not found' });\n return;\n }\n const { status } = req.body || {};\n const config = await getStatusConfig();\n const validStatuses = config.statuses.map((s) => s.id);\n if (typeof status !== 'string' || !validStatuses.includes(status)) {\n res.status(400).json({ error: `Invalid status. Must be one of: ${validStatuses.join(', ')}.` });\n return;\n }\n let content = await readFile(assignmentPath, 'utf-8');\n content = setTopLevelField(content, 'status', status);\n content = setTopLevelField(content, 'updated', nowTimestamp());\n if (status !== 'blocked') {\n content = setTopLevelField(content, 'blockedReason', null);\n }\n await writeFileForce(assignmentPath, content);\n const assignment = await getAssignmentDetailById(projectsDir, assignmentsDir, id);\n res.json({ assignment });\n } catch (error) {\n console.error('Error overriding standalone status:', error);\n res.status(500).json({ error: `Failed to override status: ${(error as Error).message}` });\n }\n });\n\n router.patch('/api/assignments/:id/assignee', async (req: Request, res: Response) => {\n try {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n const id = getParam(req.params.id);\n const resolved = await resolveAssignmentById(projectsDir, assignmentsDir, id);\n if (!resolved) {\n res.status(404).json({ error: `Assignment \"${id}\" not found` });\n return;\n }\n const assignmentPath = resolve(resolved.assignmentDir, 'assignment.md');\n if (!(await fileExists(assignmentPath))) {\n res.status(404).json({ error: 'Assignment not found' });\n return;\n }\n const validation = validateAssigneeBody(req.body);\n if (!validation.ok) {\n res.status(400).json({ error: validation.error });\n return;\n }\n let content = await readFile(assignmentPath, 'utf-8');\n content = setTopLevelField(content, 'assignee', validation.value);\n content = setTopLevelField(content, 'updated', nowTimestamp());\n await writeFileForce(assignmentPath, content);\n const assignment = await getAssignmentDetailById(projectsDir, assignmentsDir, id);\n res.json({ assignment });\n } catch (error) {\n console.error('Error updating standalone assignee:', error);\n res.status(500).json({ error: `Failed to update assignee: ${(error as Error).message}` });\n }\n });\n\n router.post('/api/assignments/bulk-status-override', async (req: Request, res: Response) => {\n try {\n const body = req.body;\n if (!body || typeof body !== 'object' || !Array.isArray(body.items)) {\n res.status(400).json({ error: 'Request body must include `items` (array).' });\n return;\n }\n const items = body.items as Array<unknown>;\n if (items.length === 0) {\n res.status(400).json({ error: '`items` must contain at least one entry.' });\n return;\n }\n if (items.length > 200) {\n res.status(400).json({ error: '`items` is capped at 200 entries per call.' });\n return;\n }\n\n const config = await getStatusConfig();\n const validStatuses = new Set(config.statuses.map((s) => s.id));\n const timestamp = nowTimestamp();\n const results: Array<{ key: string; ok: boolean; error?: string }> = [];\n let succeeded = 0;\n let failed = 0;\n\n for (let index = 0; index < items.length; index += 1) {\n const raw = items[index];\n const itemKey = buildBulkItemKey(raw, index);\n try {\n if (!raw || typeof raw !== 'object') {\n throw new Error('item must be an object');\n }\n const item = raw as Record<string, unknown>;\n const status = typeof item.status === 'string' ? item.status : null;\n if (!status || !validStatuses.has(status)) {\n throw new Error(`invalid status \"${status ?? ''}\"`);\n }\n\n let assignmentPath: string | null = null;\n if (typeof item.id === 'string' && item.id.trim()) {\n if (!assignmentsDir) {\n throw new Error('standalone assignments are not configured on this server');\n }\n const resolved = await resolveAssignmentById(projectsDir, assignmentsDir, item.id);\n if (!resolved) {\n throw new Error(`assignment \"${item.id}\" not found`);\n }\n assignmentPath = resolve(resolved.assignmentDir, 'assignment.md');\n } else if (\n typeof item.projectSlug === 'string'\n && typeof item.assignmentSlug === 'string'\n && item.projectSlug\n && item.assignmentSlug\n ) {\n assignmentPath = resolve(\n projectsDir,\n item.projectSlug,\n 'assignments',\n item.assignmentSlug,\n 'assignment.md',\n );\n } else {\n throw new Error('must supply either `id` or both `projectSlug` and `assignmentSlug`');\n }\n\n if (!(await fileExists(assignmentPath))) {\n throw new Error('assignment file not found');\n }\n\n let content = await readFile(assignmentPath, 'utf-8');\n content = setTopLevelField(content, 'status', status);\n content = setTopLevelField(content, 'updated', timestamp);\n if (status !== 'blocked') {\n content = setTopLevelField(content, 'blockedReason', null);\n }\n await writeFileForce(assignmentPath, content);\n\n results.push({ key: itemKey, ok: true });\n succeeded += 1;\n } catch (error) {\n results.push({ key: itemKey, ok: false, error: (error as Error).message });\n failed += 1;\n }\n }\n\n res.json({ results, succeeded, failed });\n } catch (error) {\n console.error('Error in bulk-status-override:', error);\n res.status(500).json({ error: `Bulk status override failed: ${(error as Error).message}` });\n }\n });\n\n router.patch('/api/assignments/:id/acceptance-criteria/:index', async (req: Request, res: Response) => {\n try {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n const id = getParam(req.params.id);\n const resolved = await resolveAssignmentById(projectsDir, assignmentsDir, id);\n if (!resolved) {\n res.status(404).json({ error: `Assignment \"${id}\" not found` });\n return;\n }\n const assignmentPath = resolve(resolved.assignmentDir, 'assignment.md');\n const currentContent = await readCurrentDocument(assignmentPath);\n if (!currentContent) {\n res.status(404).json({ error: 'Assignment not found' });\n return;\n }\n const { checked } = req.body || {};\n if (typeof checked !== 'boolean') {\n res.status(400).json({ error: 'checked must be a boolean' });\n return;\n }\n const index = Number.parseInt(getParam(req.params.index), 10);\n const result = toggleAcceptanceCriterion(currentContent, index, checked);\n if ('error' in result) {\n res.status(400).json({ error: result.error });\n return;\n }\n const nextContent = setTopLevelField(result.content, 'updated', nowTimestamp());\n await writeFileForce(assignmentPath, nextContent);\n const assignment = await getAssignmentDetailById(projectsDir, assignmentsDir, id);\n res.json({ assignment, content: nextContent });\n } catch (error) {\n console.error('Error toggling standalone acceptance criterion:', error);\n res.status(500).json({ error: `Failed to toggle acceptance criterion: ${(error as Error).message}` });\n }\n });\n\n router.post('/api/assignments/:id/transitions/:command', async (req: Request, res: Response) => {\n try {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n const id = getParam(req.params.id);\n const command = getParam(req.params.command);\n const resolved = await resolveAssignmentById(projectsDir, assignmentsDir, id);\n if (!resolved) {\n res.status(404).json({ error: `Assignment \"${id}\" not found` });\n return;\n }\n\n const { reason } = req.body || {};\n const transitionResult = await executeTransitionByDir(\n resolved.assignmentDir,\n command as any,\n {\n standalone: resolved.standalone,\n reason: typeof reason === 'string' ? reason : undefined,\n linkedTodosLookup,\n },\n );\n if (!transitionResult.success) {\n res.status(400).json({ error: transitionResult.message, fromStatus: transitionResult.fromStatus });\n return;\n }\n\n const detail = resolved.standalone\n ? await getAssignmentDetailById(projectsDir, assignmentsDir, id)\n : await getAssignmentDetail(projectsDir, resolved.projectSlug!, resolved.assignmentSlug);\n res.json({ assignment: detail, warnings: transitionResult.warnings ?? [] });\n } catch (error) {\n console.error('Error transitioning by id:', error);\n res.status(500).json({ error: `Failed to transition: ${(error as Error).message}` });\n }\n });\n\n return router;\n}\n\nfunction slugifyLocal(input: string): string {\n return input\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '') || 'untitled';\n}\n\ntype AssigneeValidation =\n | { ok: true; value: string | null }\n | { ok: false; error: string };\n\nfunction validateAssigneeBody(body: unknown): AssigneeValidation {\n if (!body || typeof body !== 'object') {\n return { ok: false, error: 'Body must include `assignee` (string or null).' };\n }\n const assignee = (body as Record<string, unknown>).assignee;\n if (assignee === null) return { ok: true, value: null };\n if (typeof assignee !== 'string') {\n return { ok: false, error: '`assignee` must be a string or null.' };\n }\n const trimmed = assignee.trim();\n if (trimmed.length === 0) return { ok: true, value: null };\n if (trimmed.length > 120) {\n return { ok: false, error: '`assignee` must be 120 characters or fewer.' };\n }\n return { ok: true, value: trimmed };\n}\n\nfunction buildBulkItemKey(raw: unknown, index: number): string {\n if (raw && typeof raw === 'object') {\n const item = raw as Record<string, unknown>;\n if (typeof item.id === 'string' && item.id.trim()) return item.id;\n if (typeof item.projectSlug === 'string' && typeof item.assignmentSlug === 'string') {\n return `${item.projectSlug}/${item.assignmentSlug}`;\n }\n }\n return `#${index}`;\n}\n\nasync function appendCommentTo(\n assignmentDir: string,\n assignmentRef: string,\n req: Request,\n res: Response,\n reloadDetail: () => Promise<unknown>,\n): Promise<void> {\n const commentsPath = resolve(assignmentDir, 'comments.md');\n const { body, author, type, replyTo } = req.body || {};\n if (!body || typeof body !== 'string' || !body.trim()) {\n res.status(400).json({ error: 'body is required' });\n return;\n }\n const commentType: CommentType = type && ['question', 'note', 'feedback'].includes(type) ? type : 'note';\n const timestamp = nowTimestamp();\n const entryAuthor = (typeof author === 'string' && author.trim()) ? author.trim() : 'human';\n\n let currentContent: string;\n let currentCount = 0;\n if (await fileExists(commentsPath)) {\n currentContent = await readFile(commentsPath, 'utf-8');\n const countMatch = currentContent.match(/^entryCount:\\s*(\\d+)/m);\n if (countMatch) currentCount = parseInt(countMatch[1], 10);\n } else {\n currentContent = renderComments({ assignment: assignmentRef, timestamp });\n }\n\n const comment: Comment = {\n id: generateId().split('-')[0],\n timestamp,\n author: entryAuthor,\n type: commentType,\n body,\n replyTo: typeof replyTo === 'string' && replyTo.trim() ? replyTo.trim() : undefined,\n resolved: commentType === 'question' ? false : undefined,\n };\n const entry = formatCommentEntry(comment);\n let next = setTopLevelField(currentContent, 'entryCount', String(currentCount + 1));\n next = setTopLevelField(next, 'updated', `\"${timestamp}\"`);\n if (next.includes('No comments yet.')) {\n next = next.replace('No comments yet.', entry.trimEnd());\n } else {\n next = `${next.trimEnd()}\\n\\n${entry}`;\n }\n await writeFileForce(commentsPath, next);\n const assignment = await reloadDetail();\n res.status(201).json({ assignment, comment: { id: comment.id } });\n}\n\nasync function toggleCommentResolvedAt(\n assignmentDir: string,\n commentId: string,\n req: Request,\n res: Response,\n reloadDetail: () => Promise<unknown>,\n): Promise<void> {\n const commentsPath = resolve(assignmentDir, 'comments.md');\n if (!(await fileExists(commentsPath))) {\n res.status(404).json({ error: 'Comments file not found' });\n return;\n }\n const { resolved: desired } = req.body || {};\n if (typeof desired !== 'boolean') {\n res.status(400).json({ error: 'resolved (boolean) is required' });\n return;\n }\n const content = await readFile(commentsPath, 'utf-8');\n const parsed = parseComments(content);\n const target = parsed.entries.find((e) => e.id === commentId);\n if (!target) {\n res.status(404).json({ error: `Comment ${commentId} not found` });\n return;\n }\n if (target.type !== 'question') {\n res.status(400).json({ error: 'Only questions can be resolved' });\n return;\n }\n const entryBlockRegex = new RegExp(\n `(^## ${commentId.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}[\\\\s\\\\S]*?)(\\\\*\\\\*Resolved:\\\\*\\\\*\\\\s*(?:true|false))`,\n 'm',\n );\n const next = content.replace(entryBlockRegex, (_m, preamble) => `${preamble}**Resolved:** ${desired ? 'true' : 'false'}`);\n if (next === content) {\n res.status(500).json({ error: 'Failed to update resolved flag' });\n return;\n }\n const withUpdated = setTopLevelField(next, 'updated', `\"${nowTimestamp()}\"`);\n await writeFileForce(commentsPath, withUpdated);\n const assignment = await reloadDetail();\n res.json({ assignment });\n}\n","import { randomUUID } from 'node:crypto';\n\nexport function generateId(): string {\n return randomUUID();\n}\n","export interface ToggleAcceptanceCriterionResult {\n content: string;\n}\n\nexport interface ToggleAcceptanceCriterionError {\n error: string;\n}\n\nfunction splitFrontmatter(content: string): { prefix: string; body: string } {\n const match = content.match(/^(---\\r?\\n[\\s\\S]*?\\r?\\n---\\r?\\n?)([\\s\\S]*)$/);\n if (!match) {\n return { prefix: '', body: content };\n }\n\n return {\n prefix: match[1],\n body: match[2],\n };\n}\n\nexport function toggleAcceptanceCriterion(\n content: string,\n index: number,\n checked: boolean,\n): ToggleAcceptanceCriterionResult | ToggleAcceptanceCriterionError {\n if (!Number.isInteger(index) || index < 0) {\n return { error: 'acceptance criteria index must be a non-negative integer' };\n }\n\n const { prefix, body } = splitFrontmatter(content);\n const lines = body.split('\\n');\n const sectionStart = lines.findIndex((line) => /^##\\s+Acceptance Criteria\\s*$/i.test(line.trim()));\n\n if (sectionStart === -1) {\n return { error: 'Acceptance Criteria section not found.' };\n }\n\n let sectionEnd = lines.length;\n for (let lineIndex = sectionStart + 1; lineIndex < lines.length; lineIndex += 1) {\n if (/^#{1,2}\\s+\\S/.test(lines[lineIndex].trim())) {\n sectionEnd = lineIndex;\n break;\n }\n }\n\n const checklistLines = lines\n .map((line, lineIndex) => ({ line, lineIndex }))\n .filter(({ lineIndex, line }) =>\n lineIndex > sectionStart\n && lineIndex < sectionEnd\n && /^\\s*[-*]\\s+\\[( |x|X)\\]\\s+.*$/.test(line),\n );\n\n const target = checklistLines[index];\n if (!target) {\n return { error: `Acceptance criteria item ${index} not found.` };\n }\n\n const nextLine = target.line.replace(\n /^(\\s*[-*]\\s+\\[)( |x|X)(\\]\\s+.*)$/,\n `$1${checked ? 'x' : ' '}$3`,\n );\n\n lines[target.lineIndex] = nextLine;\n return {\n content: `${prefix}${lines.join('\\n')}`,\n };\n}\n","export { renderConfig } from './config.js';\nexport type { ConfigParams } from './config.js';\n\nexport { renderManifest } from './manifest.js';\nexport type { ManifestParams } from './manifest.js';\n\nexport { renderProject } from './project.js';\nexport type { ProjectParams } from './project.js';\n\nexport { renderAssignment } from './assignment.js';\nexport type { AssignmentParams } from './assignment.js';\n\nexport { renderPlan } from './plan.js';\nexport type { PlanParams } from './plan.js';\n\nexport { renderScratchpad } from './scratchpad.js';\nexport type { ScratchpadParams } from './scratchpad.js';\n\nexport { renderHandoff } from './handoff.js';\nexport type { HandoffParams } from './handoff.js';\n\nexport { renderSessionSummary } from './session-summary.js';\nexport type { SessionSummaryParams } from './session-summary.js';\n\nexport { renderProgress, formatProgressEntry } from './progress.js';\nexport type { ProgressParams } from './progress.js';\n\nexport { renderComments, formatCommentEntry } from './comments.js';\nexport type { CommentsParams, Comment, CommentType } from './comments.js';\n\nexport { renderDecisionRecord } from './decision-record.js';\nexport type { DecisionRecordParams } from './decision-record.js';\n\nexport {\n renderIndexAssignments,\n renderIndexPlans,\n renderIndexDecisions,\n renderStatus,\n renderResourcesIndex,\n renderMemoriesIndex,\n renderMemoryStub,\n renderResourceStub,\n} from './index-stubs.js';\nexport type { IndexStubParams, MemoryStubParams, ResourceStubParams } from './index-stubs.js';\n\nexport { renderPlaybook } from './playbook.js';\nexport type { PlaybookParams } from './playbook.js';\n\nexport { renderCursorProtocol, renderCursorAssignment } from './cursor-rules.js';\nexport type { CursorAssignmentParams } from './cursor-rules.js';\n\nexport { renderCodexAgents } from './codex-agents.js';\nexport type { CodexAgentsParams } from './codex-agents.js';\n\nexport { renderOpenCodeConfig } from './opencode-config.js';\nexport type { OpenCodeConfigParams } from './opencode-config.js';\n","export interface ManifestParams {\n slug: string;\n timestamp: string;\n}\n\nexport function renderManifest(params: ManifestParams): string {\n return `---\nversion: \"2.0\"\nproject: ${params.slug}\ngenerated: \"${params.timestamp}\"\n---\n\n# Project: ${params.slug}\n\n## Overview\n- [Project Overview](./project.md)\n\n## Indexes\n- [Assignments](./_index-assignments.md)\n- [Plans](./_index-plans.md)\n- [Decision Records](./_index-decisions.md)\n- [Status](./_status.md)\n- [Resources](./resources/_index.md)\n- [Memories](./memories/_index.md)\n`;\n}\n","export function escapeYamlString(value: string): string {\n if (value.includes('\\n') || value.includes('\\r')) {\n throw new Error(\n `YAML string values must be single-line. Got: \"${value.slice(0, 50)}...\"`,\n );\n }\n const escaped = value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"');\n return `\"${escaped}\"`;\n}\n","import { escapeYamlString } from '../utils/yaml.js';\n\nexport interface ProjectParams {\n id: string;\n slug: string;\n title: string;\n timestamp: string;\n workspace?: string;\n}\n\nexport function renderProject(params: ProjectParams): string {\n const safeTitle = escapeYamlString(params.title);\n const workspaceLine = params.workspace ? `\\nworkspace: ${params.workspace}` : '';\n return `---\nid: ${params.id}\nslug: ${params.slug}\ntitle: ${safeTitle}\narchived: false\narchivedAt: null\narchivedReason: null\ncreated: \"${params.timestamp}\"\nupdated: \"${params.timestamp}\"\nexternalIds: []\ntags: []${workspaceLine}\n---\n\n# ${params.title}\n\n## Overview\n\n<!-- Describe the project goal, context, and success criteria here. -->\n\n## Notes\n\n<!-- Optional human notes, updates, or context. -->\n`;\n}\n","import { escapeYamlString } from '../utils/yaml.js';\n\nexport interface AssignmentParams {\n id: string;\n slug: string;\n title: string;\n timestamp: string;\n priority: 'low' | 'medium' | 'high' | 'critical';\n dependsOn: string[];\n links: string[];\n project?: string | null;\n workspaceGroup?: string | null;\n type?: string;\n includeTodos?: boolean;\n status?: string;\n acceptanceCriteria?: string[];\n}\n\nexport function renderAssignment(params: AssignmentParams): string {\n const safeTitle = escapeYamlString(params.title);\n const dependsOnYaml =\n params.dependsOn.length === 0\n ? 'dependsOn: []'\n : `dependsOn:\\n - ${params.dependsOn.join('\\n - ')}`;\n const linksYaml =\n params.links.length === 0\n ? 'links: []'\n : `links:\\n - ${params.links.join('\\n - ')}`;\n const projectYaml = `project: ${params.project == null ? 'null' : params.project}`;\n const workspaceGroupLine = params.workspaceGroup\n ? `\\nworkspaceGroup: ${params.workspaceGroup}`\n : '';\n const typeYaml = `type: ${params.type ?? 'feature'}`;\n\n const criteriaLines = params.acceptanceCriteria && params.acceptanceCriteria.length > 0\n ? params.acceptanceCriteria.map((c) => `- [ ] ${c.replace(/\\n/g, ' ').trim()}`).join('\\n')\n : `- [ ] <!-- criterion 1 -->\n- [ ] <!-- criterion 2 -->\n- [ ] <!-- criterion 3 -->`;\n\n const todosSection = params.includeTodos\n ? `## Todos\n\n<!--\nChecklist of work items for this assignment. Items may be simple tasks\nor a markdown link to a plan file (e.g., \"- [ ] Execute [plan](./plan.md)\").\nWhen a plan is superseded by a new one, mark the old todo as:\n - [x] ~~Execute [old plan](./plan.md)~~ (superseded by plan-v2)\nNever delete superseded todos — preserve the history.\n-->\n\n`\n : '';\n\n return `---\nid: ${params.id}\nslug: ${params.slug}\ntitle: ${safeTitle}\n${projectYaml}${workspaceGroupLine}\n${typeYaml}\nstatus: ${params.status ?? 'draft'}\npriority: ${params.priority}\ncreated: \"${params.timestamp}\"\nupdated: \"${params.timestamp}\"\nassignee: null\nexternalIds: []\n${dependsOnYaml}\n${linksYaml}\nblockedReason: null\nworkspace:\n repository: null\n worktreePath: null\n branch: null\n parentBranch: null\ntags: []\n---\n\n# ${params.title}\n\n## Objective\n\n<!-- Clear description of what needs to be done and why. -->\n\n## Acceptance Criteria\n\n${criteriaLines}\n\n${todosSection}## Context\n\n<!-- Links to relevant docs, code, or other assignments. -->\n\n## Links\n\n- [Progress](./progress.md)\n- [Comments](./comments.md)\n- [Scratchpad](./scratchpad.md)\n- [Handoff](./handoff.md) — cross-ticket outbound\n- [Decision Record](./decision-record.md)\n- [Sessions](./sessions/) — per-session continuity summaries (one \\`<session-id>/summary.md\\` per session)\n`;\n}\n","export interface ScratchpadParams {\n assignmentSlug: string;\n timestamp: string;\n}\n\nexport function renderScratchpad(params: ScratchpadParams): string {\n return `---\nassignment: ${params.assignmentSlug}\nupdated: \"${params.timestamp}\"\n---\n\n# Scratchpad\n\nNo working notes yet.\n`;\n}\n","export interface HandoffParams {\n assignmentSlug: string;\n timestamp: string;\n}\n\nexport function renderHandoff(params: HandoffParams): string {\n return `---\nassignment: ${params.assignmentSlug}\nupdated: \"${params.timestamp}\"\nhandoffCount: 0\n---\n\n# Handoff Log\n\nNo handoffs recorded yet.\n`;\n}\n","export interface ProgressParams {\n assignment: string;\n timestamp: string;\n}\n\nexport function renderProgress(params: ProgressParams): string {\n return `---\nassignment: ${params.assignment}\nentryCount: 0\ngenerated: \"${params.timestamp}\"\nupdated: \"${params.timestamp}\"\n---\n\n# Progress\n\nNo progress yet.\n`;\n}\n\nexport function formatProgressEntry(body: string, timestamp: string): string {\n const trimmed = body.trim();\n return `## ${timestamp}\\n\\n${trimmed}\\n`;\n}\n","export interface CommentsParams {\n assignment: string;\n timestamp: string;\n}\n\nexport type CommentType = 'question' | 'note' | 'feedback';\n\nexport interface Comment {\n id: string;\n timestamp: string;\n author: string;\n type: CommentType;\n body: string;\n replyTo?: string;\n resolved?: boolean;\n}\n\nexport function renderComments(params: CommentsParams): string {\n return `---\nassignment: ${params.assignment}\nentryCount: 0\ngenerated: \"${params.timestamp}\"\nupdated: \"${params.timestamp}\"\n---\n\n# Comments\n\nNo comments yet.\n`;\n}\n\nexport function formatCommentEntry(comment: Comment): string {\n const lines: string[] = [];\n lines.push(`## ${comment.id}`);\n lines.push('');\n lines.push(`**Recorded:** ${comment.timestamp}`);\n lines.push(`**Author:** ${comment.author}`);\n lines.push(`**Type:** ${comment.type}`);\n if (comment.replyTo) {\n lines.push(`**Reply to:** ${comment.replyTo}`);\n }\n if (comment.type === 'question') {\n lines.push(`**Resolved:** ${comment.resolved ? 'true' : 'false'}`);\n }\n lines.push('');\n lines.push(comment.body.trim());\n lines.push('');\n return lines.join('\\n');\n}\n","export interface DecisionRecordParams {\n assignmentSlug: string;\n timestamp: string;\n}\n\nexport function renderDecisionRecord(\n params: DecisionRecordParams,\n): string {\n return `---\nassignment: ${params.assignmentSlug}\nupdated: \"${params.timestamp}\"\ndecisionCount: 0\n---\n\n# Decision Record\n\nNo decisions recorded yet.\n`;\n}\n","import { escapeYamlString } from '../utils/yaml.js';\n\nexport interface IndexStubParams {\n slug: string;\n title: string;\n timestamp: string;\n}\n\nexport interface MemoryStubParams {\n /** File slug (filename without `.md`). */\n slug: string;\n name: string;\n /** Project slug — written into frontmatter for traceability. */\n projectSlug: string;\n timestamp: string;\n}\n\nexport type ResourceStubParams = MemoryStubParams;\n\nexport function renderMemoryStub(params: MemoryStubParams): string {\n return `---\ntype: memory\nname: ${escapeYamlString(params.name)}\nsource: claude\nsourceAssignment: null\nrelatedAssignments: []\nscope: project\ncreated: \"${params.timestamp}\"\nupdated: \"${params.timestamp}\"\ntags: []\n---\n\n# ${params.name}\n\n`;\n}\n\nexport function renderResourceStub(params: ResourceStubParams): string {\n return `---\ntype: resource\nname: ${escapeYamlString(params.name)}\nsource: claude\ncategory: documentation\nsourceUrl: null\nsourceAssignment: null\nrelatedAssignments: []\ncreated: \"${params.timestamp}\"\nupdated: \"${params.timestamp}\"\n---\n\n# ${params.name}\n\n`;\n}\n\nexport function renderIndexAssignments(params: IndexStubParams): string {\n return `---\nproject: ${params.slug}\ngenerated: \"${params.timestamp}\"\ntotal: 0\nby_status:\n pending: 0\n in_progress: 0\n blocked: 0\n review: 0\n completed: 0\n failed: 0\n---\n\n# Assignments\n\n| Slug | Title | Status | Priority | Assignee | Dependencies | Updated |\n|------|-------|--------|----------|----------|--------------|---------|\n`;\n}\n\nexport function renderIndexPlans(params: IndexStubParams): string {\n return `---\nproject: ${params.slug}\ngenerated: \"${params.timestamp}\"\n---\n\n# Plans\n\n| Assignment | Plan Status | Updated |\n|------------|-------------|---------|\n`;\n}\n\nexport function renderIndexDecisions(params: IndexStubParams): string {\n return `---\nproject: ${params.slug}\ngenerated: \"${params.timestamp}\"\n---\n\n# Decision Records\n\n| Assignment | Count | Latest Decision | Latest Status | Updated |\n|------------|-------|-----------------|---------------|---------|\n`;\n}\n\nexport function renderStatus(params: IndexStubParams): string {\n return `---\nproject: ${params.slug}\ngenerated: \"${params.timestamp}\"\nstatus: pending\nprogress:\n total: 0\n completed: 0\n in_progress: 0\n blocked: 0\n pending: 0\n review: 0\n failed: 0\nneedsAttention:\n blockedCount: 0\n failedCount: 0\n openQuestions: 0\n---\n\n# Project Status: ${params.title}\n\n**Status:** pending\n**Progress:** 0/0 assignments complete\n\n## Assignments\n\nNo assignments yet.\n\n## Dependency Graph\n\nNo dependencies yet.\n\n## Needs Attention\n\n- **0 blocked** assignments\n- **0 failed** assignments\n- **0 unanswered** questions\n`;\n}\n\nexport function renderResourcesIndex(params: IndexStubParams): string {\n return `---\nproject: ${params.slug}\ngenerated: \"${params.timestamp}\"\ntotal: 0\n---\n\n# Resources\n\n| Name | Category | Source | Related Assignments | Updated |\n|------|----------|--------|---------------------|---------|\n`;\n}\n\nexport function renderMemoriesIndex(params: IndexStubParams): string {\n return `---\nproject: ${params.slug}\ngenerated: \"${params.timestamp}\"\ntotal: 0\n---\n\n# Memories\n\n| Name | Source | Scope | Source Assignment | Updated |\n|------|--------|-------|------------------|---------|\n`;\n}\n","import { escapeYamlString } from '../utils/yaml.js';\n\nexport interface PlaybookParams {\n slug: string;\n name: string;\n description: string;\n whenToUse?: string;\n timestamp: string;\n}\n\nexport function renderPlaybook(params: PlaybookParams): string {\n const whenToUse = params.whenToUse\n ? escapeYamlString(params.whenToUse)\n : 'null';\n return `---\nname: ${escapeYamlString(params.name)}\nslug: ${params.slug}\ndescription: ${escapeYamlString(params.description)}\nwhen_to_use: ${whenToUse}\ncreated: \"${params.timestamp}\"\nupdated: \"${params.timestamp}\"\ntags: []\n---\n\n# ${params.name}\n\n<!-- Write imperative rules and workflows here. Keep it under 50 lines. -->\n`;\n}\n","import { Router } from 'express';\nimport {\n registerSession,\n removeSession,\n listSessionFiles,\n readSessionFile,\n updateLastRefreshed,\n setOverride,\n sanitizeSessionName,\n} from './servers.js';\nimport {\n scanAllSessions,\n scanSingleSession,\n clearScanCache,\n} from './scanner.js';\n\nexport function createServersRouter(\n serversDir: string,\n projectsDir: string,\n assignmentsDir?: string,\n): Router {\n const router = Router();\n\n // GET /api/servers — all sessions with cached scan data\n router.get('/', async (_req, res) => {\n try {\n const result = await scanAllSessions(serversDir, projectsDir, { assignmentsDir });\n res.json(result);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Scan failed' });\n }\n });\n\n // GET /api/servers/:name — single session\n router.get('/:name', async (req, res) => {\n try {\n const session = await scanSingleSession(serversDir, projectsDir, req.params.name, { assignmentsDir });\n if (!session) {\n res.status(404).json({ error: 'Session not found' });\n return;\n }\n res.json(session);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Scan failed' });\n }\n });\n\n // POST /api/servers — register a new session\n router.post('/', async (req, res) => {\n try {\n const { name } = req.body;\n if (!name || typeof name !== 'string') {\n res.status(400).json({ error: 'name is required' });\n return;\n }\n const sanitized = sanitizeSessionName(name);\n const existing = await readSessionFile(serversDir, sanitized);\n if (existing) {\n res.status(409).json({ error: `Session \"${sanitized}\" already registered` });\n return;\n }\n await registerSession(serversDir, name);\n clearScanCache();\n res.status(201).json({ name: sanitized });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Registration failed' });\n }\n });\n\n // DELETE /api/servers/:name — unregister\n router.delete('/:name', async (req, res) => {\n try {\n const data = await readSessionFile(serversDir, req.params.name);\n if (!data) {\n res.status(404).json({ error: 'Session not found' });\n return;\n }\n await removeSession(serversDir, req.params.name);\n clearScanCache();\n res.json({ removed: req.params.name });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Removal failed' });\n }\n });\n\n // POST /api/servers/refresh — fresh scan all (must be before /:name/refresh)\n router.post('/refresh', async (_req, res) => {\n try {\n const names = await listSessionFiles(serversDir);\n for (const name of names) {\n await updateLastRefreshed(serversDir, name);\n }\n clearScanCache();\n const result = await scanAllSessions(serversDir, projectsDir, { bypassCache: true, assignmentsDir });\n res.json(result);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Refresh failed' });\n }\n });\n\n // POST /api/servers/:name/refresh — fresh scan one\n router.post('/:name/refresh', async (req, res) => {\n try {\n const data = await readSessionFile(serversDir, req.params.name);\n if (!data) {\n res.status(404).json({ error: 'Session not found' });\n return;\n }\n await updateLastRefreshed(serversDir, req.params.name);\n clearScanCache();\n const session = await scanSingleSession(serversDir, projectsDir, req.params.name, { assignmentsDir });\n res.json(session);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Refresh failed' });\n }\n });\n\n // PATCH /api/servers/:name/panes/:windowIndex/:paneIndex/assignment — manual link\n router.patch('/:name/panes/:windowIndex/:paneIndex/assignment', async (req, res) => {\n try {\n const { name, windowIndex, paneIndex } = req.params;\n const data = await readSessionFile(serversDir, name);\n if (!data) {\n res.status(404).json({ error: 'Session not found' });\n return;\n }\n const body = req.body;\n if (body === null || (body && body.project && body.assignment)) {\n await setOverride(\n serversDir,\n name,\n parseInt(windowIndex, 10),\n parseInt(paneIndex, 10),\n body,\n );\n clearScanCache();\n res.json({ updated: true });\n } else {\n res.status(400).json({ error: 'Body must be { project, assignment } or null' });\n }\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Update failed' });\n }\n });\n\n return router;\n}\n","import { Router } from 'express';\nimport { resolve } from 'node:path';\nimport {\n listAllSessions,\n listProjectSessions,\n appendSession,\n updateSessionStatus,\n deleteSessions,\n reconcileActiveSessions,\n getSessionById,\n} from './agent-sessions.js';\nimport { fileExists } from '../utils/fs.js';\nimport { derivePathFromTranscript } from '../utils/transcript.js';\nimport { enrichSessions } from './session-liveness.js';\nimport { getAgents, readConfig } from '../utils/config.js';\nimport { captureProcessStartedAt } from '../utils/process-info.js';\nimport type { AgentSessionStatus, WsMessage } from './types.js';\n\nexport function createAgentSessionsRouter(\n projectsDir: string,\n broadcast?: (msg: WsMessage) => void,\n assignmentsDir?: string,\n): Router {\n const router = Router();\n\n // GET /api/agent-sessions — all sessions across all projects\n router.get('/', async (_req, res) => {\n try {\n await reconcileActiveSessions(projectsDir, assignmentsDir);\n const sessions = await listAllSessions(projectsDir);\n const agents = getAgents(await readConfig());\n res.json({\n sessions: enrichSessions(sessions, agents),\n generatedAt: new Date().toISOString(),\n });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to list sessions' });\n }\n });\n\n // GET /api/agent-sessions/:projectSlug — sessions for one project\n router.get('/:projectSlug', async (req, res) => {\n try {\n const { projectSlug } = req.params;\n const assignment = req.query.assignment as string | undefined;\n const projectDir = resolve(projectsDir, projectSlug);\n if (!(await fileExists(projectDir))) {\n res.status(404).json({ error: `Project \"${projectSlug}\" not found` });\n return;\n }\n await reconcileActiveSessions(projectsDir, assignmentsDir);\n const sessions = await listProjectSessions(projectsDir, projectSlug, assignment);\n const agents = getAgents(await readConfig());\n res.json({\n sessions: enrichSessions(sessions, agents),\n generatedAt: new Date().toISOString(),\n });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to list sessions' });\n }\n });\n\n // POST /api/agent-sessions — register a new session\n router.post('/', async (req, res) => {\n try {\n const { projectSlug, assignmentSlug, agent, sessionId, path, description, transcriptPath, pid: rawPid } =\n req.body;\n\n if (!agent) {\n res.status(400).json({ error: 'agent is required' });\n return;\n }\n\n if (!sessionId) {\n res.status(400).json({\n error:\n 'sessionId is required. Pass the real agent-generated session id — do not synthesize one.',\n });\n return;\n }\n\n if (projectSlug) {\n const projectDir = resolve(projectsDir, projectSlug);\n if (!(await fileExists(projectDir))) {\n res.status(404).json({ error: `Project \"${projectSlug}\" not found` });\n return;\n }\n }\n\n // Prefer the launch cwd recorded inside the transcript over whatever\n // path the caller posted — the transcript is what determines where\n // Claude Code files the conversation, and the only directory from\n // which `claude --resume <id>` will find it.\n const derivedPath = await derivePathFromTranscript(transcriptPath);\n const recordedPath = derivedPath ?? path ?? '';\n\n const pid =\n typeof rawPid === 'number' && Number.isFinite(rawPid) && rawPid > 0\n ? rawPid\n : null;\n const pidStartedAt = pid !== null ? captureProcessStartedAt(pid) : null;\n\n const session = {\n projectSlug: projectSlug || null,\n assignmentSlug: assignmentSlug || null,\n agent,\n sessionId,\n started: new Date().toISOString(),\n status: 'active' as AgentSessionStatus,\n path: recordedPath,\n description: description || null,\n transcriptPath: transcriptPath || null,\n pid,\n pidStartedAt,\n };\n\n await appendSession('', session);\n broadcast?.({ type: 'agent-sessions-updated', timestamp: new Date().toISOString() });\n res.status(201).json({ sessionId });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Registration failed' });\n }\n });\n\n // PATCH /api/agent-sessions/:sessionId — terminal-only status update.\n // Used by the Mark-stopped affordance on session rows; the\n // /:sessionId/status route below remains available for full status updates\n // (non-terminal allowed) used by other internal flows. Express precedence\n // matches the more specific /:sessionId/status route first.\n router.patch('/:sessionId', async (req, res) => {\n try {\n const { sessionId } = req.params;\n const status = (req.body ?? {}).status;\n if (status !== 'stopped' && status !== 'completed') {\n res.status(400).json({\n error: 'status must be one of: stopped, completed',\n });\n return;\n }\n if (!getSessionById(sessionId)) {\n res.status(404).json({ error: `Session \"${sessionId}\" not found` });\n return;\n }\n const updated = await updateSessionStatus('', sessionId, status);\n if (!updated) {\n res.status(404).json({ error: `Session \"${sessionId}\" not found` });\n return;\n }\n broadcast?.({ type: 'agent-sessions-updated', timestamp: new Date().toISOString() });\n res.json({ updated: true });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Update failed' });\n }\n });\n\n // PATCH /api/agent-sessions/:sessionId/status — update session status\n router.patch('/:sessionId/status', async (req, res) => {\n try {\n const { sessionId } = req.params;\n const { status } = req.body;\n\n if (!status) {\n res.status(400).json({ error: 'status is required' });\n return;\n }\n\n if (!['active', 'completed', 'stopped'].includes(status)) {\n res.status(400).json({ error: 'status must be active, completed, or stopped' });\n return;\n }\n\n const updated = await updateSessionStatus('', sessionId, status);\n if (!updated) {\n res.status(404).json({ error: `Session \"${sessionId}\" not found` });\n return;\n }\n\n broadcast?.({ type: 'agent-sessions-updated', timestamp: new Date().toISOString() });\n res.json({ updated: true });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Update failed' });\n }\n });\n\n // DELETE /api/agent-sessions — delete one or more sessions\n router.delete('/', async (req, res) => {\n try {\n const { sessionIds } = req.body;\n\n if (!Array.isArray(sessionIds) || sessionIds.length === 0) {\n res.status(400).json({ error: 'sessionIds must be a non-empty array' });\n return;\n }\n\n const deleted = await deleteSessions(sessionIds);\n broadcast?.({ type: 'agent-sessions-updated', timestamp: new Date().toISOString() });\n res.json({ deleted });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Delete failed' });\n }\n });\n\n return router;\n}\n","import { open } from 'node:fs/promises';\n\n// Cap on lines we'll scan looking for `cwd`. The launch cwd is recorded in the\n// first few entries of every Claude Code transcript; 50 lines is generous\n// enough to absorb leading non-JSON noise (blank lines, permission-mode rows\n// without a cwd) without slurping multi-MB transcripts into memory.\nconst MAX_LINES_SCANNED = 50;\n\n/**\n * Read the first `cwd` field from a Claude Code transcript JSONL file.\n *\n * Claude Code derives `~/.claude/projects/<encoded-cwd>/<session-id>.jsonl`\n * from the *launch* cwd of the session, and `claude --resume <id>` only finds\n * the transcript when invoked from a matching cwd. The transcript itself is\n * therefore the authoritative source of truth for \"which directory does this\n * session belong to\" — read it once, prefer it over whatever a registering\n * caller might have happened to be sitting in.\n *\n * Returns `null` when the path is empty, the file doesn't exist or can't be\n * read, no JSON line within the scan window contains a `cwd` field, or the\n * value is not a non-empty string. Never throws.\n */\nexport async function derivePathFromTranscript(\n transcriptPath: string | null | undefined,\n): Promise<string | null> {\n if (!transcriptPath) return null;\n\n let handle;\n try {\n handle = await open(transcriptPath, 'r');\n } catch {\n return null;\n }\n\n try {\n const stream = handle.createReadStream({ encoding: 'utf-8' });\n let buffer = '';\n let scanned = 0;\n\n for await (const chunk of stream) {\n buffer += chunk;\n let nl = buffer.indexOf('\\n');\n while (nl !== -1) {\n const line = buffer.slice(0, nl);\n buffer = buffer.slice(nl + 1);\n\n const cwd = extractCwd(line);\n if (cwd) {\n stream.destroy();\n return cwd;\n }\n\n scanned++;\n if (scanned >= MAX_LINES_SCANNED) {\n stream.destroy();\n return null;\n }\n nl = buffer.indexOf('\\n');\n }\n }\n\n // Trailing line without a newline (rare, but handle it).\n if (buffer.length > 0) {\n const cwd = extractCwd(buffer);\n if (cwd) return cwd;\n }\n return null;\n } finally {\n await handle.close().catch(() => {});\n }\n}\n\nfunction extractCwd(line: string): string | null {\n const trimmed = line.trim();\n if (trimmed.length === 0 || trimmed[0] !== '{') return null;\n try {\n const parsed = JSON.parse(trimmed) as { cwd?: unknown };\n if (typeof parsed.cwd === 'string' && parsed.cwd.length > 0) {\n return parsed.cwd;\n }\n } catch {\n // Non-JSON or truncated line — keep scanning.\n }\n return null;\n}\n","import { execFileSync } from 'node:child_process';\n\n/**\n * Capture the start-time of a process via `ps -o lstart=`. Used as the\n * recycling-defense baseline for session liveness detection: the server later\n * compares this stored start-time to the current `ps -o lstart=` output, so a\n * recycled PID with the same number but different start-time correctly\n * reports as not-live.\n *\n * Returns null when `ps` fails (process already gone, or `ps` not on PATH).\n * Null is the expected sentinel for \"no recycling baseline available\" — the\n * liveness check trusts `kill -0` alone in that case (small false-positive\n * risk on PID reuse, acceptable).\n */\nexport function captureProcessStartedAt(pid: number): string | null {\n if (!Number.isFinite(pid) || pid <= 0) return null;\n try {\n const out = execFileSync('ps', ['-o', 'lstart=', '-p', String(pid)], {\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n });\n const trimmed = out.trim();\n return trimmed === '' ? null : trimmed;\n } catch {\n return null;\n }\n}\n","import { Router } from 'express';\nimport {\n readConfig,\n writeAgentsConfig,\n deleteAgentsConfig,\n AgentConfigError,\n} from '../utils/config.js';\nimport {\n BUILTIN_AGENTS,\n PROMPT_ARG_POSITIONS,\n type AgentConfig,\n type PromptArgPosition,\n} from '../utils/agents-schema.js';\n\nexport interface AgentFieldError {\n id?: string;\n index?: number;\n field: string;\n message: string;\n}\n\nexport function mapAgentErrorToFieldErrors(\n err: AgentConfigError,\n): { error: string; fieldErrors?: AgentFieldError[] } {\n const message = err.message;\n\n let match = message.match(/^agent id \"([^\"]*)\" is invalid/);\n if (match) {\n return {\n error: message,\n fieldErrors: [\n { id: match[1], field: 'id', message: 'must match /^[a-z0-9][a-z0-9_-]*$/' },\n ],\n };\n }\n\n match = message.match(/^duplicate agent id \"([^\"]+)\"/);\n if (match) {\n return {\n error: message,\n fieldErrors: [{ id: match[1], field: 'id', message: 'duplicate id' }],\n };\n }\n\n match = message.match(/^agent \"([^\"]+)\" has empty label/);\n if (match) {\n return {\n error: message,\n fieldErrors: [{ id: match[1], field: 'label', message: 'label is required' }],\n };\n }\n\n match = message.match(/^agent(?: \"([^\"]+)\")? has empty command/);\n if (match) {\n return {\n error: message,\n fieldErrors: [{ id: match[1], field: 'command', message: 'command is required' }],\n };\n }\n\n match = message.match(/^agent(?: \"([^\"]+)\")? command \"[^\"]*\" is a relative path/);\n if (match) {\n return {\n error: message,\n fieldErrors: [\n { id: match[1], field: 'command', message: 'use absolute path or bare name' },\n ],\n };\n }\n\n match = message.match(/^agent \"([^\"]+)\" has invalid promptArgPosition/);\n if (match) {\n return {\n error: message,\n fieldErrors: [\n {\n id: match[1],\n field: 'promptArgPosition',\n message: 'must be first|last|none',\n },\n ],\n };\n }\n\n if (/^more than one agent is marked default/.test(message)) {\n return {\n error: message,\n fieldErrors: [{ field: 'default', message: 'only one agent may be default' }],\n };\n }\n\n return { error: message };\n}\n\nfunction coerceAgentRow(\n raw: unknown,\n index: number,\n): { ok: true; value: AgentConfig } | { ok: false; status: number; body: { error: string; fieldErrors?: AgentFieldError[] } } {\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {\n return {\n ok: false,\n status: 400,\n body: {\n error: `agents[${index}] must be an object`,\n fieldErrors: [{ index, field: 'row', message: `agents[${index}] must be an object` }],\n },\n };\n }\n const entry = raw as Record<string, unknown>;\n\n if (typeof entry.id !== 'string' || entry.id.length === 0) {\n return {\n ok: false,\n status: 400,\n body: {\n error: `agents[${index}].id must be a non-empty string`,\n fieldErrors: [{ index, field: 'id', message: 'id must be a non-empty string' }],\n },\n };\n }\n const id = entry.id;\n\n if (typeof entry.label !== 'string') {\n return {\n ok: false,\n status: 400,\n body: {\n error: `agents[${index}].label must be a string`,\n fieldErrors: [{ id, field: 'label', message: 'label must be a string' }],\n },\n };\n }\n\n if (typeof entry.command !== 'string') {\n return {\n ok: false,\n status: 400,\n body: {\n error: `agents[${index}].command must be a string`,\n fieldErrors: [{ id, field: 'command', message: 'command must be a string' }],\n },\n };\n }\n\n const cleaned: AgentConfig = {\n id,\n label: entry.label,\n command: entry.command,\n };\n\n if (entry.args !== undefined) {\n if (!Array.isArray(entry.args) || entry.args.some((v) => typeof v !== 'string')) {\n return {\n ok: false,\n status: 400,\n body: {\n error: `agents[${index}].args must be an array of strings`,\n fieldErrors: [{ id, field: 'args', message: 'args must be an array of strings' }],\n },\n };\n }\n cleaned.args = entry.args as string[];\n }\n\n if (entry.promptArgPosition !== undefined) {\n if (\n typeof entry.promptArgPosition !== 'string' ||\n !PROMPT_ARG_POSITIONS.includes(entry.promptArgPosition as PromptArgPosition)\n ) {\n return {\n ok: false,\n status: 400,\n body: {\n error: `agents[${index}].promptArgPosition must be first|last|none`,\n fieldErrors: [\n { id, field: 'promptArgPosition', message: 'must be first|last|none' },\n ],\n },\n };\n }\n cleaned.promptArgPosition = entry.promptArgPosition as PromptArgPosition;\n }\n\n if (entry.resolveFromShellAliases !== undefined) {\n if (typeof entry.resolveFromShellAliases !== 'boolean') {\n return {\n ok: false,\n status: 400,\n body: {\n error: `agents[${index}].resolveFromShellAliases must be a boolean`,\n fieldErrors: [\n { id, field: 'resolveFromShellAliases', message: 'must be a boolean' },\n ],\n },\n };\n }\n cleaned.resolveFromShellAliases = entry.resolveFromShellAliases;\n }\n\n if (entry.default !== undefined) {\n if (typeof entry.default !== 'boolean') {\n return {\n ok: false,\n status: 400,\n body: {\n error: `agents[${index}].default must be a boolean`,\n fieldErrors: [{ id, field: 'default', message: 'must be a boolean' }],\n },\n };\n }\n cleaned.default = entry.default;\n }\n\n return { ok: true, value: cleaned };\n}\n\nexport function createAgentsRouter(): Router {\n const router = Router();\n\n router.get('/', async (_req, res) => {\n try {\n const config = await readConfig();\n const agents = config.agents ?? BUILTIN_AGENTS;\n res.json({ agents, custom: config.agents !== null });\n } catch (err) {\n console.error('Error getting agents config:', err);\n res.status(500).json({ error: 'Failed to get agents config' });\n }\n });\n\n router.put('/', async (req, res) => {\n try {\n const raw = (req.body && typeof req.body === 'object' ? req.body : {}) as {\n agents?: unknown;\n };\n if (!Array.isArray(raw.agents)) {\n res.status(400).json({ error: 'agents must be an array' });\n return;\n }\n\n const cleaned: AgentConfig[] = [];\n for (let i = 0; i < raw.agents.length; i++) {\n const result = coerceAgentRow(raw.agents[i], i);\n if (!result.ok) {\n res.status(result.status).json(result.body);\n return;\n }\n cleaned.push(result.value);\n }\n\n try {\n await writeAgentsConfig(cleaned);\n } catch (err) {\n if (err instanceof AgentConfigError) {\n res.status(400).json(mapAgentErrorToFieldErrors(err));\n return;\n }\n console.error('Error saving agents config:', err);\n res.status(500).json({ error: 'Failed to save agents config' });\n return;\n }\n\n res.json({ agents: cleaned, custom: true });\n } catch (err) {\n console.error('Error saving agents config:', err);\n res.status(500).json({ error: 'Failed to save agents config' });\n }\n });\n\n router.delete('/', async (_req, res) => {\n try {\n await deleteAgentsConfig();\n res.json({ agents: BUILTIN_AGENTS, custom: false });\n } catch (err) {\n console.error('Error resetting agents config:', err);\n res.status(500).json({ error: 'Failed to reset agents config' });\n }\n });\n\n return router;\n}\n","import { Router } from 'express';\nimport {\n initLeasesDb,\n listInventories,\n getInventoryDetail,\n forceReleaseLease,\n NotFoundError,\n LeaseContentionError,\n} from '../db/leases-db.js';\nimport type { WsMessage } from './types.js';\n\nexport function createLeasesRouter(\n broadcast?: (message: WsMessage) => void,\n): Router {\n const router = Router();\n\n // GET /api/leases — all inventories with members + active leases\n router.get('/', (_req, res) => {\n try {\n initLeasesDb();\n const inventories = listInventories();\n const details = inventories\n .map((inv) => getInventoryDetail(inv.slug))\n .filter((d): d is NonNullable<typeof d> => d !== null);\n res.json({ inventories: details });\n } catch (error) {\n res.status(500).json({\n error: error instanceof Error ? error.message : 'List failed',\n });\n }\n });\n\n // GET /api/leases/:slug — single inventory detail\n router.get('/:slug', (req, res) => {\n try {\n initLeasesDb();\n const detail = getInventoryDetail(req.params.slug);\n if (!detail) {\n res.status(404).json({ error: 'Inventory not found' });\n return;\n }\n res.json(detail);\n } catch (error) {\n res.status(500).json({\n error: error instanceof Error ? error.message : 'Read failed',\n });\n }\n });\n\n // POST /api/leases/:slug/force-release/:lease_id — admin force-release\n router.post('/:slug/force-release/:lease_id', (req, res) => {\n try {\n initLeasesDb();\n const result = forceReleaseLease(req.params.lease_id);\n broadcast?.({\n type: 'leases-updated',\n timestamp: new Date().toISOString(),\n });\n res.json({ ...result, lease_id: req.params.lease_id });\n } catch (error) {\n if (error instanceof NotFoundError) {\n res.status(404).json({ error: 'Lease not found' });\n return;\n }\n if (error instanceof LeaseContentionError) {\n res.status(503).json({ error: 'Contention timeout; retry' });\n return;\n }\n res.status(500).json({\n error: error instanceof Error ? error.message : 'Force release failed',\n });\n }\n });\n\n return router;\n}\n","/**\n * Resource leases database module.\n *\n * Shares `~/.syntaur/syntaur.db` with `session-db.ts` and `proof-db.ts`. Each\n * module owns its own schema-version row in the shared `meta` table and creates\n * `meta` with `IF NOT EXISTS` so init order is irrelevant and standalone init\n * (e.g. in a leases-only test DB) is safe.\n *\n * Concurrency model:\n * - `journal_mode = WAL` allows concurrent readers and one writer.\n * - `busy_timeout = 5000` lets SQLite absorb short lock contention internally.\n * - All mutating ops run inside `db.transaction(fn).immediate()` which issues\n * `BEGIN IMMEDIATE` — acquires the reserved lock up-front so two concurrent\n * writers serialize cleanly.\n *\n * Atomic claim uses the tuple-subquery form (the bundled SQLite is built\n * without `SQLITE_ENABLE_UPDATE_DELETE_LIMIT`, so `UPDATE...ORDER BY...LIMIT...\n * RETURNING` is a syntax error — verified empirically).\n *\n * Timestamp invariant: every timestamp written from this module is produced by\n * `nowIso()` which calls `new Date().toISOString()` (canonical UTC, lexicographic-\n * safe). Lexicographic `<=` comparisons in SQL rely on this. The CLI never\n * accepts user-supplied timestamps. A future caller writing a non-canonical\n * timestamp would silently misorder `<=` checks.\n */\n\nimport Database from 'better-sqlite3';\nimport { randomUUID } from 'node:crypto';\nimport { resolve } from 'node:path';\nimport { syntaurRoot } from '../utils/paths.js';\n\nlet db: Database.Database | null = null;\n\nconst LEASE_SCHEMA_VERSION = '1';\n\nconst SCHEMA_SQL = `\nCREATE TABLE IF NOT EXISTS meta (\n key TEXT PRIMARY KEY,\n value TEXT\n);\n\nCREATE TABLE IF NOT EXISTS inventories (\n slug TEXT PRIMARY KEY,\n kind TEXT NOT NULL,\n display_name TEXT,\n default_ttl_s INTEGER NOT NULL CHECK (default_ttl_s > 0),\n created_at TEXT NOT NULL\n);\n\nCREATE TABLE IF NOT EXISTS inventory_members (\n inventory_slug TEXT NOT NULL,\n member_id TEXT NOT NULL,\n status TEXT NOT NULL DEFAULT 'idle'\n CHECK (status IN ('idle','leased','retired')),\n generation INTEGER NOT NULL DEFAULT 0,\n metadata_json TEXT,\n last_used_at TEXT,\n retired_at TEXT,\n PRIMARY KEY (inventory_slug, member_id),\n FOREIGN KEY (inventory_slug) REFERENCES inventories(slug)\n);\n\nCREATE INDEX IF NOT EXISTS idx_members_idle\n ON inventory_members (inventory_slug, status, last_used_at);\n\nCREATE TABLE IF NOT EXISTS leases (\n lease_id TEXT PRIMARY KEY,\n inventory_slug TEXT NOT NULL,\n member_id TEXT NOT NULL,\n member_gen INTEGER NOT NULL,\n state TEXT NOT NULL\n CHECK (state IN ('active','released','expired','revoked')),\n granted_at TEXT NOT NULL,\n expires_at TEXT NOT NULL,\n released_at TEXT,\n requested_for TEXT,\n FOREIGN KEY (inventory_slug, member_id)\n REFERENCES inventory_members(inventory_slug, member_id)\n);\n\nCREATE INDEX IF NOT EXISTS idx_leases_gc\n ON leases (state, expires_at);\n\nCREATE TABLE IF NOT EXISTS lease_events (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n lease_id TEXT NOT NULL,\n event TEXT NOT NULL,\n at TEXT NOT NULL,\n detail_json TEXT,\n FOREIGN KEY (lease_id) REFERENCES leases(lease_id)\n);\n\nCREATE INDEX IF NOT EXISTS idx_events_lease\n ON lease_events (lease_id, at);\n`;\n\n// --- Types -----------------------------------------------------------------\n\nexport type MemberStatus = 'idle' | 'leased' | 'retired';\nexport type LeaseState = 'active' | 'released' | 'expired' | 'revoked';\n\nexport interface InventoryRow {\n slug: string;\n kind: string;\n display_name: string | null;\n default_ttl_s: number;\n created_at: string;\n}\n\nexport interface InventoryMemberRow {\n inventory_slug: string;\n member_id: string;\n status: MemberStatus;\n generation: number;\n metadata_json: string | null;\n last_used_at: string | null;\n retired_at: string | null;\n}\n\nexport interface LeaseRow {\n lease_id: string;\n inventory_slug: string;\n member_id: string;\n member_gen: number;\n state: LeaseState;\n granted_at: string;\n expires_at: string;\n released_at: string | null;\n requested_for: string | null;\n}\n\nexport interface LeaseEventRow {\n id: number;\n lease_id: string;\n event: string;\n at: string;\n detail_json: string | null;\n}\n\nexport interface InventoryDetail {\n inventory: InventoryRow;\n members: InventoryMemberRow[];\n active_leases: LeaseRow[];\n}\n\nexport interface CreateInventoryInput {\n slug: string;\n kind: string;\n display_name?: string;\n default_ttl_s: number;\n}\n\nexport interface AddMemberInput {\n inventory_slug: string;\n member_id: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface ClaimResult {\n lease_id: string;\n inventory_slug: string;\n member_id: string;\n member_gen: number;\n granted_at: string;\n expires_at: string;\n metadata: Record<string, unknown> | null;\n}\n\nexport interface ListLeasesFilter {\n inventory?: string;\n state?: LeaseState;\n}\n\n// --- Errors ----------------------------------------------------------------\n\nexport class NoIdleMemberError extends Error {\n constructor(public readonly inventorySlug: string) {\n super(`no idle members in '${inventorySlug}'`);\n this.name = 'NoIdleMemberError';\n }\n}\n\nexport class StaleLeaseError extends Error {\n constructor(public readonly leaseId: string) {\n super(`lease ${leaseId} is no longer active (expired or revoked)`);\n this.name = 'StaleLeaseError';\n }\n}\n\nexport class NotFoundError extends Error {\n constructor(public readonly id: string) {\n super(`lease ${id} not found`);\n this.name = 'NotFoundError';\n }\n}\n\nexport class LeaseContentionError extends Error {\n constructor(public readonly inventorySlug: string) {\n super(`contention timeout on '${inventorySlug}'; retry`);\n this.name = 'LeaseContentionError';\n }\n}\n\nexport class MemberInUseError extends Error {\n constructor(public readonly inventorySlug: string, public readonly memberId: string) {\n super(`member ${inventorySlug}/${memberId} is currently leased; release before retiring`);\n this.name = 'MemberInUseError';\n }\n}\n\nexport class DuplicateInventoryError extends Error {\n constructor(public readonly slug: string) {\n super(`inventory '${slug}' already exists`);\n this.name = 'DuplicateInventoryError';\n }\n}\n\nexport class DuplicateMemberError extends Error {\n constructor(public readonly inventorySlug: string, public readonly memberId: string) {\n super(`member ${inventorySlug}/${memberId} already exists`);\n this.name = 'DuplicateMemberError';\n }\n}\n\n// --- Helpers ---------------------------------------------------------------\n\n/** Canonical UTC ISO 8601 timestamp. Lexicographic-safe for SQL `<=` checks. */\nexport function nowIso(): string {\n return new Date().toISOString();\n}\n\nfunction isBusyError(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n const e = err as { code?: string };\n return e.code === 'SQLITE_BUSY' || e.code === 'SQLITE_BUSY_SNAPSHOT';\n}\n\n// --- Lifecycle -------------------------------------------------------------\n\n/**\n * Initialize the leases database. Idempotent — repeated calls return the same\n * singleton handle. Pass an explicit `dbPath` for tests; defaults to\n * `~/.syntaur/syntaur.db`. Safe to run standalone (creates its own `meta` table).\n */\nexport function initLeasesDb(dbPath?: string): Database.Database {\n if (db) return db;\n\n const finalPath = dbPath ?? resolve(syntaurRoot(), 'syntaur.db');\n db = new Database(finalPath);\n db.pragma('journal_mode = WAL');\n db.pragma('busy_timeout = 5000');\n db.pragma('foreign_keys = ON');\n\n const database = db;\n const runMigrations = database.transaction(() => {\n database.exec(SCHEMA_SQL);\n database\n .prepare('INSERT OR IGNORE INTO meta (key, value) VALUES (?, ?)')\n .run('lease_schema_version', LEASE_SCHEMA_VERSION);\n });\n runMigrations.exclusive();\n\n return db;\n}\n\nexport function getLeasesDb(): Database.Database {\n if (!db) {\n throw new Error('Leases database not initialized. Call initLeasesDb() first.');\n }\n return db;\n}\n\nexport function closeLeasesDb(): void {\n if (db) {\n db.close();\n db = null;\n }\n}\n\nexport function resetLeasesDb(): void {\n db = null;\n}\n\n// --- Inventories -----------------------------------------------------------\n\nexport function createInventory(input: CreateInventoryInput): InventoryRow {\n const database = getLeasesDb();\n const row: InventoryRow = {\n slug: input.slug,\n kind: input.kind,\n display_name: input.display_name ?? null,\n default_ttl_s: input.default_ttl_s,\n created_at: nowIso(),\n };\n try {\n database\n .prepare(\n `INSERT INTO inventories (slug, kind, display_name, default_ttl_s, created_at)\n VALUES (?, ?, ?, ?, ?)`,\n )\n .run(row.slug, row.kind, row.display_name, row.default_ttl_s, row.created_at);\n } catch (err) {\n if (err instanceof Error && err.message.includes('UNIQUE')) {\n throw new DuplicateInventoryError(input.slug);\n }\n throw err;\n }\n return row;\n}\n\nexport function listInventories(): InventoryRow[] {\n const database = getLeasesDb();\n return database\n .prepare(\n `SELECT slug, kind, display_name, default_ttl_s, created_at\n FROM inventories ORDER BY slug`,\n )\n .all() as InventoryRow[];\n}\n\nexport function getInventoryDetail(slug: string): InventoryDetail | null {\n const database = getLeasesDb();\n const inv = database\n .prepare(\n `SELECT slug, kind, display_name, default_ttl_s, created_at\n FROM inventories WHERE slug = ?`,\n )\n .get(slug) as InventoryRow | undefined;\n if (!inv) return null;\n const members = database\n .prepare(\n `SELECT inventory_slug, member_id, status, generation, metadata_json, last_used_at, retired_at\n FROM inventory_members WHERE inventory_slug = ?\n ORDER BY member_id`,\n )\n .all(slug) as InventoryMemberRow[];\n const active_leases = database\n .prepare(\n `SELECT lease_id, inventory_slug, member_id, member_gen, state, granted_at, expires_at, released_at, requested_for\n FROM leases WHERE inventory_slug = ? AND state = 'active'\n ORDER BY granted_at`,\n )\n .all(slug) as LeaseRow[];\n return { inventory: inv, members, active_leases };\n}\n\n// --- Members ---------------------------------------------------------------\n\nexport function addMember(input: AddMemberInput): InventoryMemberRow {\n const database = getLeasesDb();\n const row: InventoryMemberRow = {\n inventory_slug: input.inventory_slug,\n member_id: input.member_id,\n status: 'idle',\n generation: 0,\n metadata_json: input.metadata ? JSON.stringify(input.metadata) : null,\n last_used_at: null,\n retired_at: null,\n };\n try {\n database\n .prepare(\n `INSERT INTO inventory_members\n (inventory_slug, member_id, status, generation, metadata_json)\n VALUES (?, ?, 'idle', 0, ?)`,\n )\n .run(row.inventory_slug, row.member_id, row.metadata_json);\n } catch (err) {\n if (err instanceof Error && err.message.includes('UNIQUE')) {\n throw new DuplicateMemberError(input.inventory_slug, input.member_id);\n }\n throw err;\n }\n return row;\n}\n\nexport function retireMember(inventorySlug: string, memberId: string): void {\n const database = getLeasesDb();\n const retire = database.transaction(() => {\n const row = database\n .prepare(\n `SELECT status FROM inventory_members\n WHERE inventory_slug = ? AND member_id = ?`,\n )\n .get(inventorySlug, memberId) as { status: MemberStatus } | undefined;\n if (!row) throw new NotFoundError(`${inventorySlug}/${memberId}`);\n if (row.status === 'leased') {\n throw new MemberInUseError(inventorySlug, memberId);\n }\n database\n .prepare(\n `UPDATE inventory_members\n SET status = 'retired', generation = generation + 1, retired_at = ?\n WHERE inventory_slug = ? AND member_id = ?`,\n )\n .run(nowIso(), inventorySlug, memberId);\n });\n retire.immediate();\n}\n\n// --- Claim -----------------------------------------------------------------\n\n/**\n * Claim an idle member of `slug`. Atomic — uses `BEGIN IMMEDIATE` so two\n * concurrent claimants serialize. Returns lease metadata or throws\n * `NoIdleMemberError` if the inventory has nothing claimable after sweeping.\n */\nexport function claimLease(\n slug: string,\n ttl_s: number,\n requested_for?: string,\n): ClaimResult {\n const database = getLeasesDb();\n\n try {\n const fn = database.transaction(() => {\n const now = nowIso();\n\n // (1) Opportunistic sweep — expire active leases on this inventory whose TTL is up.\n database\n .prepare(\n `UPDATE leases\n SET state = 'expired'\n WHERE state = 'active'\n AND expires_at <= ?\n AND inventory_slug = ?`,\n )\n .run(now, slug);\n\n // (2) Free their members (CAS on generation match).\n database\n .prepare(\n `UPDATE inventory_members\n SET status = 'idle', generation = generation + 1\n WHERE inventory_slug = ?\n AND status = 'leased'\n AND (inventory_slug, member_id) IN (\n SELECT inventory_slug, member_id\n FROM leases\n WHERE inventory_slug = ?\n AND state = 'expired'\n AND released_at IS NULL\n )\n AND generation = (\n SELECT member_gen FROM leases l\n WHERE l.inventory_slug = inventory_members.inventory_slug\n AND l.member_id = inventory_members.member_id\n AND l.state = 'expired'\n AND l.released_at IS NULL\n ORDER BY l.granted_at DESC LIMIT 1\n )`,\n )\n .run(slug, slug);\n\n // (3) Mark those freshly-expired leases as fully released (idempotent sentinel).\n database\n .prepare(\n `UPDATE leases\n SET released_at = ?\n WHERE state = 'expired'\n AND released_at IS NULL\n AND inventory_slug = ?`,\n )\n .run(now, slug);\n\n // (4) Pick an idle member via tuple-subquery (verified portable form).\n const picked = database\n .prepare(\n `UPDATE inventory_members\n SET status = 'leased',\n generation = generation + 1,\n last_used_at = ?\n WHERE (inventory_slug, member_id) = (\n SELECT inventory_slug, member_id\n FROM inventory_members\n WHERE inventory_slug = ? AND status = 'idle'\n ORDER BY last_used_at ASC NULLS FIRST\n LIMIT 1\n )\n RETURNING member_id, generation, metadata_json`,\n )\n .get(now, slug) as\n | { member_id: string; generation: number; metadata_json: string | null }\n | undefined;\n\n if (!picked) {\n throw new NoIdleMemberError(slug);\n }\n\n // (5) Insert the lease tied to the new member_gen.\n const lease_id = randomUUID();\n const expires_at = new Date(Date.now() + ttl_s * 1000).toISOString();\n database\n .prepare(\n `INSERT INTO leases\n (lease_id, inventory_slug, member_id, member_gen,\n state, granted_at, expires_at, requested_for)\n VALUES (?, ?, ?, ?, 'active', ?, ?, ?)`,\n )\n .run(\n lease_id,\n slug,\n picked.member_id,\n picked.generation,\n now,\n expires_at,\n requested_for ?? null,\n );\n\n // (6) Event.\n database\n .prepare(\n `INSERT INTO lease_events (lease_id, event, at, detail_json)\n VALUES (?, 'claimed', ?, ?)`,\n )\n .run(lease_id, now, JSON.stringify({ member_id: picked.member_id }));\n\n return {\n lease_id,\n inventory_slug: slug,\n member_id: picked.member_id,\n member_gen: picked.generation,\n granted_at: now,\n expires_at,\n metadata: picked.metadata_json\n ? (JSON.parse(picked.metadata_json) as Record<string, unknown>)\n : null,\n } satisfies ClaimResult;\n });\n\n return fn.immediate();\n } catch (err) {\n if (isBusyError(err)) throw new LeaseContentionError(slug);\n throw err;\n }\n}\n\n// --- Release ---------------------------------------------------------------\n\nexport function releaseLease(lease_id: string): void {\n const database = getLeasesDb();\n\n try {\n const fn = database.transaction(() => {\n const now = nowIso();\n\n // (1) CAS-guarded member free.\n const memberRes = database\n .prepare(\n `UPDATE inventory_members\n SET status = 'idle', generation = generation + 1\n WHERE (inventory_slug, member_id) = (\n SELECT inventory_slug, member_id FROM leases\n WHERE lease_id = ? AND state = 'active'\n )\n AND generation = (\n SELECT member_gen FROM leases\n WHERE lease_id = ? AND state = 'active'\n )`,\n )\n .run(lease_id, lease_id);\n\n if (memberRes.changes === 0) {\n throw new StaleLeaseError(lease_id);\n }\n\n // (2) Mark lease released.\n database\n .prepare(\n `UPDATE leases\n SET state = 'released', released_at = ?\n WHERE lease_id = ? AND state = 'active'`,\n )\n .run(now, lease_id);\n\n // (3) Event.\n database\n .prepare(\n `INSERT INTO lease_events (lease_id, event, at)\n VALUES (?, 'released', ?)`,\n )\n .run(lease_id, now);\n });\n\n fn.immediate();\n } catch (err) {\n if (isBusyError(err)) throw new LeaseContentionError(lease_id);\n throw err;\n }\n}\n\n// --- Extend ----------------------------------------------------------------\n\n/**\n * Extend a lease's TTL from NOW. Refuses if the lease is no longer active,\n * already past its wall-clock expiry, or its bound member generation has\n * advanced.\n */\nexport function extendLease(lease_id: string, ttl_s: number): { new_expires_at: string } {\n const database = getLeasesDb();\n\n try {\n const fn = database.transaction(() => {\n const now = nowIso();\n const new_expires_at = new Date(Date.now() + ttl_s * 1000).toISOString();\n\n const res = database\n .prepare(\n `UPDATE leases\n SET expires_at = ?\n WHERE lease_id = ?\n AND state = 'active'\n AND expires_at > ?\n AND member_gen = (\n SELECT generation FROM inventory_members\n WHERE inventory_slug = leases.inventory_slug\n AND member_id = leases.member_id\n )`,\n )\n .run(new_expires_at, lease_id, now);\n\n if (res.changes === 0) {\n throw new StaleLeaseError(lease_id);\n }\n\n database\n .prepare(\n `INSERT INTO lease_events (lease_id, event, at, detail_json)\n VALUES (?, 'extended', ?, ?)`,\n )\n .run(lease_id, now, JSON.stringify({ new_expires_at }));\n\n return { new_expires_at };\n });\n\n return fn.immediate();\n } catch (err) {\n if (isBusyError(err)) throw new LeaseContentionError(lease_id);\n throw err;\n }\n}\n\n// --- Read ------------------------------------------------------------------\n\nexport function getLease(lease_id: string): LeaseRow | null {\n const database = getLeasesDb();\n const row = database\n .prepare(\n `SELECT lease_id, inventory_slug, member_id, member_gen, state,\n granted_at, expires_at, released_at, requested_for\n FROM leases WHERE lease_id = ?`,\n )\n .get(lease_id) as LeaseRow | undefined;\n return row ?? null;\n}\n\nexport function listLeases(filter?: ListLeasesFilter): LeaseRow[] {\n const database = getLeasesDb();\n const where: string[] = [];\n const params: unknown[] = [];\n if (filter?.inventory) {\n where.push('inventory_slug = ?');\n params.push(filter.inventory);\n }\n if (filter?.state) {\n where.push('state = ?');\n params.push(filter.state);\n }\n const whereSql = where.length > 0 ? `WHERE ${where.join(' AND ')}` : '';\n return database\n .prepare(\n `SELECT lease_id, inventory_slug, member_id, member_gen, state,\n granted_at, expires_at, released_at, requested_for\n FROM leases ${whereSql}\n ORDER BY granted_at DESC`,\n )\n .all(...params) as LeaseRow[];\n}\n\nexport function listMembers(inventory_slug: string): InventoryMemberRow[] {\n const database = getLeasesDb();\n const inv = database\n .prepare('SELECT slug FROM inventories WHERE slug = ?')\n .get(inventory_slug);\n if (!inv) throw new NotFoundError(inventory_slug);\n return database\n .prepare(\n `SELECT inventory_slug, member_id, status, generation, metadata_json, last_used_at, retired_at\n FROM inventory_members WHERE inventory_slug = ?\n ORDER BY member_id`,\n )\n .all(inventory_slug) as InventoryMemberRow[];\n}\n\n/**\n * Read lease_events. With a `lease_id`, returns that lease's event timeline in\n * chronological order (oldest first). Without, returns the most recent `limit`\n * events across all leases in reverse-chronological order (newest first).\n */\nexport function getLeaseEvents(lease_id?: string, limit = 50): LeaseEventRow[] {\n const database = getLeasesDb();\n if (lease_id) {\n return database\n .prepare(\n `SELECT id, lease_id, event, at, detail_json\n FROM lease_events WHERE lease_id = ?\n ORDER BY at ASC, id ASC\n LIMIT ?`,\n )\n .all(lease_id, limit) as LeaseEventRow[];\n }\n return database\n .prepare(\n `SELECT id, lease_id, event, at, detail_json\n FROM lease_events\n ORDER BY at DESC, id DESC\n LIMIT ?`,\n )\n .all(limit) as LeaseEventRow[];\n}\n\n// --- GC --------------------------------------------------------------------\n\n/**\n * Sweep expired leases across ALL inventories. Idempotent; safe to run\n * concurrently with claims (`BEGIN IMMEDIATE` serializes writers).\n * Returns the number of leases newly transitioned to `expired`.\n */\nexport function gcExpiredLeases(): number {\n const database = getLeasesDb();\n\n try {\n const fn = database.transaction(() => {\n const now = nowIso();\n\n const expRes = database\n .prepare(\n `UPDATE leases SET state = 'expired'\n WHERE state = 'active' AND expires_at <= ?`,\n )\n .run(now);\n\n database\n .prepare(\n `UPDATE inventory_members\n SET status = 'idle', generation = generation + 1\n WHERE status = 'leased'\n AND (inventory_slug, member_id) IN (\n SELECT inventory_slug, member_id FROM leases\n WHERE state = 'expired' AND released_at IS NULL\n )\n AND generation = (\n SELECT member_gen FROM leases l\n WHERE l.inventory_slug = inventory_members.inventory_slug\n AND l.member_id = inventory_members.member_id\n AND l.state = 'expired'\n AND l.released_at IS NULL\n ORDER BY l.granted_at DESC LIMIT 1\n )`,\n )\n .run();\n\n database\n .prepare(\n `UPDATE leases SET released_at = ?\n WHERE state = 'expired' AND released_at IS NULL AND expires_at <= ?`,\n )\n .run(now, now);\n\n return expRes.changes;\n });\n\n return fn.immediate();\n } catch (err) {\n if (isBusyError(err)) throw new LeaseContentionError('gc');\n throw err;\n }\n}\n\n// --- Force release ---------------------------------------------------------\n\n/**\n * Administrative force-release. Bypasses the lease's `state = 'active'` check\n * (humans force-releasing an already-expired-but-not-yet-released lease is\n * fine), but CAS-guards the member free on the lease's bound `member_gen`.\n * This prevents stomping a member that's currently held by a *different*\n * active lease (i.e. the targeted lease is already terminal and the slot has\n * been re-claimed).\n *\n * Returns `member_freed: true` if the member was actually idled by this call,\n * `false` if a newer claim has already taken the slot.\n */\nexport function forceReleaseLease(lease_id: string): { member_freed: boolean } {\n const database = getLeasesDb();\n\n try {\n const fn = database.transaction(() => {\n const now = nowIso();\n\n const lookup = database\n .prepare(\n `SELECT inventory_slug, member_id, member_gen, state\n FROM leases WHERE lease_id = ?`,\n )\n .get(lease_id) as\n | { inventory_slug: string; member_id: string; member_gen: number; state: LeaseState }\n | undefined;\n\n if (!lookup) throw new NotFoundError(lease_id);\n if (lookup.state === 'revoked') return { member_freed: false };\n\n // CAS: free the member only if the lease is still its current holder.\n const memberRes = database\n .prepare(\n `UPDATE inventory_members\n SET status = 'idle', generation = generation + 1\n WHERE inventory_slug = ? AND member_id = ?\n AND generation = ?`,\n )\n .run(lookup.inventory_slug, lookup.member_id, lookup.member_gen);\n\n database\n .prepare(\n `UPDATE leases\n SET state = 'revoked', released_at = ?\n WHERE lease_id = ? AND state != 'revoked'`,\n )\n .run(now, lease_id);\n\n const member_freed = memberRes.changes > 0;\n database\n .prepare(\n `INSERT INTO lease_events (lease_id, event, at, detail_json)\n VALUES (?, 'force_released', ?, ?)`,\n )\n .run(lease_id, now, JSON.stringify({ member_freed }));\n\n return { member_freed };\n });\n\n return fn.immediate();\n } catch (err) {\n if (isBusyError(err)) throw new LeaseContentionError(lease_id);\n throw err;\n }\n}\n\n// --- Inventory update / delete --------------------------------------------\n\nexport interface UpdateInventoryInput {\n default_ttl_s?: number;\n display_name?: string | null;\n}\n\n/**\n * Update mutable inventory fields. `kind` is immutable in v1 — the typed\n * signature excludes it, and a runtime guard rejects any caller that sneaks\n * a `kind` key through (defense in depth).\n */\nexport function updateInventory(\n slug: string,\n input: UpdateInventoryInput,\n): InventoryRow {\n if ('kind' in input) {\n throw new Error('inventory kind is immutable');\n }\n if (\n input.default_ttl_s === undefined &&\n input.display_name === undefined\n ) {\n throw new Error('nothing to update');\n }\n if (input.default_ttl_s !== undefined && input.default_ttl_s <= 0) {\n throw new Error('default_ttl_s must be positive');\n }\n const database = getLeasesDb();\n\n const fn = database.transaction(() => {\n const existing = database\n .prepare('SELECT slug FROM inventories WHERE slug = ?')\n .get(slug);\n if (!existing) throw new NotFoundError(slug);\n\n const sets: string[] = [];\n const params: unknown[] = [];\n if (input.default_ttl_s !== undefined) {\n sets.push('default_ttl_s = ?');\n params.push(input.default_ttl_s);\n }\n if (input.display_name !== undefined) {\n sets.push('display_name = ?');\n params.push(input.display_name);\n }\n params.push(slug);\n\n database\n .prepare(`UPDATE inventories SET ${sets.join(', ')} WHERE slug = ?`)\n .run(...params);\n\n return database\n .prepare(\n `SELECT slug, kind, display_name, default_ttl_s, created_at\n FROM inventories WHERE slug = ?`,\n )\n .get(slug) as InventoryRow;\n });\n\n try {\n return fn.immediate();\n } catch (err) {\n if (isBusyError(err)) throw new LeaseContentionError(slug);\n throw err;\n }\n}\n\n/**\n * Delete an inventory and all of its members, leases, and lease_events.\n *\n * Without `force`: refuses if any lease for the inventory is currently\n * `active` (throws `MemberInUseError`).\n *\n * With `force`: tallies active leases as `revoked` and cascades through\n * events → leases → members → inventory row, ALL inside one `BEGIN IMMEDIATE`\n * transaction. The acquire-up-front lock prevents a concurrent `claimLease`\n * from grabbing a freshly-idled member between the active-lease snapshot and\n * the cascade — what would otherwise be a use-after-free window. No explicit\n * `force_released` event is written because the entire event log for this\n * inventory is deleted in the same tx anyway.\n */\nexport function deleteInventory(\n slug: string,\n opts: { force?: boolean } = {},\n): { deleted: boolean; revoked: number } {\n const database = getLeasesDb();\n\n let revoked = 0;\n const fn = database.transaction(() => {\n const existing = database\n .prepare('SELECT slug FROM inventories WHERE slug = ?')\n .get(slug);\n if (!existing) throw new NotFoundError(slug);\n\n const activeLeases = database\n .prepare(\n `SELECT lease_id FROM leases\n WHERE inventory_slug = ? AND state = 'active'`,\n )\n .all(slug) as Array<{ lease_id: string }>;\n\n if (activeLeases.length > 0 && !opts.force) {\n throw new MemberInUseError(slug, '*');\n }\n revoked = activeLeases.length;\n\n database\n .prepare(\n `DELETE FROM lease_events\n WHERE lease_id IN (SELECT lease_id FROM leases WHERE inventory_slug = ?)`,\n )\n .run(slug);\n database.prepare('DELETE FROM leases WHERE inventory_slug = ?').run(slug);\n database\n .prepare('DELETE FROM inventory_members WHERE inventory_slug = ?')\n .run(slug);\n database.prepare('DELETE FROM inventories WHERE slug = ?').run(slug);\n });\n\n try {\n fn.immediate();\n } catch (err) {\n if (isBusyError(err)) throw new LeaseContentionError(slug);\n throw err;\n }\n return { deleted: true, revoked };\n}\n\n// --- Bulk release by tag --------------------------------------------------\n\n/**\n * Release every `active` lease whose `requested_for` matches `tag`. Per-row\n * `releaseLease` calls keep each release in its own transaction; a\n * `StaleLeaseError` from any individual release is tallied as `stale` and\n * swallowed (the caller asked for a best-effort sweep). Returns the\n * per-lease ids in two arrays so callers can render one-line-per-lease\n * summaries without re-querying.\n */\nexport function releaseLeasesByRequestedFor(\n tag: string,\n): { released: string[]; stale: string[] } {\n const database = getLeasesDb();\n const rows = database\n .prepare(\n `SELECT lease_id FROM leases\n WHERE state = 'active' AND requested_for = ?`,\n )\n .all(tag) as Array<{ lease_id: string }>;\n\n const released: string[] = [];\n const stale: string[] = [];\n for (const { lease_id } of rows) {\n try {\n releaseLease(lease_id);\n released.push(lease_id);\n } catch (err) {\n if (err instanceof StaleLeaseError) {\n stale.push(lease_id);\n continue;\n }\n throw err;\n }\n }\n return { released, stale };\n}\n","import { Router } from 'express';\nimport { resolve } from 'node:path';\nimport { readFile } from 'node:fs/promises';\nimport { listPlaybooks, getPlaybookDetail } from './api.js';\nimport { parsePlaybook } from './parser.js';\nimport { isValidSlug } from '../utils/slug.js';\nimport { nowTimestamp } from '../utils/timestamp.js';\nimport { ensureDir, fileExists, writeFileForce } from '../utils/fs.js';\nimport { renderPlaybook } from '../templates/playbook.js';\nimport {\n deletePlaybook,\n rebuildPlaybookManifest,\n renamePlaybook,\n resolvePlaybookSlug,\n setPlaybookEnabled,\n PlaybookError,\n} from '../utils/playbooks.js';\n\nfunction statusForPlaybookError(code: PlaybookError['code']): number {\n switch (code) {\n case 'manifest':\n return 403;\n case 'not-found':\n return 404;\n case 'invalid-slug':\n return 400;\n case 'collision':\n return 409;\n }\n}\n\nexport function createPlaybooksRouter(playbooksDir: string): Router {\n const router = Router();\n\n // GET / — list all playbooks\n router.get('/', async (_req, res) => {\n try {\n const playbooks = await listPlaybooks(playbooksDir);\n res.json({ playbooks, generatedAt: new Date().toISOString() });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to list playbooks' });\n }\n });\n\n // GET /template/new — scaffold template (must be before /:slug to avoid param capture)\n router.get('/template/new', async (_req, res) => {\n try {\n const content = renderPlaybook({\n slug: 'my-playbook',\n name: 'My Playbook',\n description: 'A new playbook',\n timestamp: nowTimestamp(),\n });\n res.json({ content });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to get template' });\n }\n });\n\n // POST /:slug/enable — re-enable a disabled playbook\n router.post('/:slug/enable', async (req, res) => {\n try {\n const result = await setPlaybookEnabled(playbooksDir, req.params.slug, true);\n res.json({ slug: result.slug, enabled: result.enabled, changed: result.changed });\n } catch (error) {\n const msg = error instanceof Error ? error.message : 'Failed to enable playbook';\n if (msg.startsWith('Playbook ')) {\n res.status(404).json({ error: msg });\n return;\n }\n res.status(500).json({ error: msg });\n }\n });\n\n // POST /:slug/disable — disable a playbook so agents no longer load it\n router.post('/:slug/disable', async (req, res) => {\n try {\n const result = await setPlaybookEnabled(playbooksDir, req.params.slug, false);\n res.json({ slug: result.slug, enabled: result.enabled, changed: result.changed });\n } catch (error) {\n const msg = error instanceof Error ? error.message : 'Failed to disable playbook';\n if (msg.startsWith('Playbook ')) {\n res.status(404).json({ error: msg });\n return;\n }\n res.status(500).json({ error: msg });\n }\n });\n\n // GET /:slug — get playbook detail\n router.get('/:slug', async (req, res) => {\n try {\n const detail = await getPlaybookDetail(playbooksDir, req.params.slug);\n if (!detail) {\n res.status(404).json({ error: `Playbook \"${req.params.slug}\" not found` });\n return;\n }\n res.json(detail);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to get playbook' });\n }\n });\n\n // GET /:slug/edit — raw file content for editor\n router.get('/:slug/edit', async (req, res) => {\n try {\n const resolved = await resolvePlaybookSlug(playbooksDir, req.params.slug);\n if (!resolved) {\n res.status(404).json({ error: `Playbook \"${req.params.slug}\" not found` });\n return;\n }\n const filePath = resolve(playbooksDir, resolved.filename);\n const content = await readFile(filePath, 'utf-8');\n res.json({\n documentType: 'playbook',\n title: `Edit Playbook: ${resolved.slug}`,\n content,\n slug: resolved.slug,\n });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to get playbook for editing' });\n }\n });\n\n // POST / — create new playbook\n router.post('/', async (req, res) => {\n try {\n const { content } = req.body;\n if (!content || typeof content !== 'string') {\n res.status(400).json({ error: 'content is required' });\n return;\n }\n\n const parsed = parsePlaybook(content);\n const slug = parsed.slug;\n if (!slug || !isValidSlug(slug)) {\n res.status(400).json({ error: `Invalid or missing slug: \"${slug}\"` });\n return;\n }\n\n await ensureDir(playbooksDir);\n const filePath = resolve(playbooksDir, `${slug}.md`);\n if (await fileExists(filePath)) {\n res.status(409).json({ error: `Playbook \"${slug}\" already exists` });\n return;\n }\n\n await writeFileForce(filePath, content);\n await rebuildPlaybookManifest(playbooksDir);\n res.status(201).json({ slug, path: filePath });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to create playbook' });\n }\n });\n\n // PUT /:slug — update playbook content\n router.put('/:slug', async (req, res) => {\n try {\n const { content } = req.body;\n if (!content || typeof content !== 'string') {\n res.status(400).json({ error: 'content is required' });\n return;\n }\n\n const resolved = await resolvePlaybookSlug(playbooksDir, req.params.slug);\n if (!resolved) {\n res.status(404).json({ error: `Playbook \"${req.params.slug}\" not found` });\n return;\n }\n\n const filePath = resolve(playbooksDir, resolved.filename);\n await writeFileForce(filePath, content);\n await rebuildPlaybookManifest(playbooksDir);\n res.json({ slug: resolved.slug, path: filePath });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to update playbook' });\n }\n });\n\n // DELETE /:slug — delete a playbook\n router.delete('/:slug', async (req, res) => {\n try {\n const { slug } = await deletePlaybook(playbooksDir, req.params.slug);\n res.json({ deleted: slug });\n } catch (error) {\n if (error instanceof PlaybookError) {\n res.status(statusForPlaybookError(error.code)).json({ error: error.message });\n return;\n }\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to delete playbook' });\n }\n });\n\n // PATCH /:slug — rename a playbook (slug change)\n router.patch('/:slug', async (req, res) => {\n try {\n const { newSlug } = req.body || {};\n if (typeof newSlug !== 'string' || !newSlug.trim()) {\n res.status(400).json({ error: 'newSlug is required' });\n return;\n }\n const result = await renamePlaybook(playbooksDir, req.params.slug, newSlug.trim());\n res.json(result);\n } catch (error) {\n if (error instanceof PlaybookError) {\n res.status(statusForPlaybookError(error.code)).json({ error: error.message });\n return;\n }\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to rename playbook' });\n }\n });\n\n return router;\n}\n","import { Router, type Request, type Response, type NextFunction } from 'express';\nimport { readdir } from 'node:fs/promises';\nimport {\n readChecklist,\n writeChecklist,\n readLog,\n appendLogEntry,\n generateUniqueId,\n computeCounts,\n} from '../todos/parser.js';\nimport { resolve as resolvePath, dirname } from 'node:path';\nimport { rename, mkdir } from 'node:fs/promises';\nimport { ensureDir, fileExists } from '../utils/fs.js';\nimport { projectTodosDir, todoPlanDir } from '../utils/paths.js';\nimport { wsLock, projLock, withTwoLocks, globalLockKey } from './todos-locks.js';\nimport { isValidSlug } from '../utils/slug.js';\nimport type { TodoItem, LogEntry } from '../todos/types.js';\nimport type { WsMessage } from './types.js';\nimport {\n promoteTodosToNewAssignment,\n parsePromoteTarget,\n} from '../utils/promote-todos.js';\n\nconst WORKSPACE_REGEX = /^[a-z0-9_][a-z0-9-]*$/;\n\nfunction getWorkspaceParam(value: string | string[] | undefined): string {\n if (Array.isArray(value)) {\n return value[0] ?? '';\n }\n return value ?? '';\n}\n\nfunction touchItem(item: TodoItem): void {\n const now = new Date().toISOString();\n if (item.createdAt === null) item.createdAt = now;\n item.updatedAt = now;\n}\n\nexport function createTodosRouter(\n todosDir: string,\n broadcast: (msg: WsMessage) => void,\n projectsDir?: string,\n): Router {\n const router = Router();\n\n function broadcastUpdate(): void {\n broadcast({ type: 'todos-updated', timestamp: new Date().toISOString() });\n }\n function broadcastProject(slug: string): void {\n broadcast({ type: 'todos-updated', projectSlug: slug, timestamp: new Date().toISOString() });\n }\n\n // Validate workspace name on all routes that use :workspace\n function validateWorkspace(req: Request, res: Response, next: NextFunction): void {\n const workspace = getWorkspaceParam(req.params.workspace);\n if (workspace && !WORKSPACE_REGEX.test(workspace)) {\n res.status(400).json({ error: `Invalid workspace name: \"${workspace}\". Use lowercase letters, numbers, hyphens, and underscores.` });\n return;\n }\n next();\n }\n\n // Apply workspace validation to all parameterized routes\n router.param('workspace', validateWorkspace as any);\n\n // POST /promote-bulk — aggregate promote across multiple workspaces into one\n // new assignment. Registered BEFORE any `/:workspace` route so the literal\n // `promote-bulk` segment is not mis-routed to the add-todo handler.\n // Only supports `mode: 'new-assignment'` in v1.\n router.post('/promote-bulk', async (req, res) => {\n try {\n const { groups, mode, target, title, type, priority, keepSource } = req.body ?? {};\n if (mode !== 'new-assignment') {\n res.status(400).json({ error: 'promote-bulk only supports mode \"new-assignment\" in v1' });\n return;\n }\n if (!Array.isArray(groups) || groups.length === 0) {\n res.status(400).json({ error: 'groups (non-empty array of { workspace, todoIds }) is required' });\n return;\n }\n // Preserve caller order — criteria order should follow request order.\n // Reject duplicate workspaces up front so we never nest wsLock on the\n // same key (a self-deadlock if the lock is non-reentrant).\n const callerOrder: Array<{ workspace: string; todoIds: string[] }> = [];\n const seen = new Set<string>();\n let total = 0;\n for (const g of groups) {\n if (!g || typeof g !== 'object') {\n res.status(400).json({ error: 'each group must be { workspace: string, todoIds: string[] }' });\n return;\n }\n const ws = typeof g.workspace === 'string' ? g.workspace : '';\n if (!ws || !WORKSPACE_REGEX.test(ws)) {\n res.status(400).json({ error: `Invalid workspace name in group: \"${ws}\"` });\n return;\n }\n if (seen.has(ws)) {\n res.status(400).json({ error: `Duplicate workspace \"${ws}\" in groups — merge ids client-side before posting` });\n return;\n }\n seen.add(ws);\n if (!Array.isArray(g.todoIds) || g.todoIds.length === 0) {\n res.status(400).json({ error: `group for workspace \"${ws}\" has no todoIds` });\n return;\n }\n callerOrder.push({ workspace: ws, todoIds: g.todoIds.map(String) });\n total += g.todoIds.length;\n }\n if (total > 1 && !title) {\n res.status(400).json({ error: 'title is required when promoting multiple todos' });\n return;\n }\n const parsed = parsePromoteTarget(target);\n if (!parsed.ok) { res.status(400).json({ error: parsed.error }); return; }\n\n // Lock in deterministic alpha order to avoid cross-request deadlock.\n const lockOrder = [...callerOrder].sort((a, b) =>\n a.workspace.localeCompare(b.workspace),\n );\n\n const runWithLocks = async (\n index: number,\n ): Promise<\n | { ok: true; result: { assignmentRef: string; assignmentDir: string; promoted: string[]; promotedByWorkspace: Array<{ workspace: string; ids: string[] }> } }\n | { ok: false; error: string }\n > => {\n if (index === lockOrder.length) {\n // All locks held. Build helper groups in CALLER order so criteria\n // come out in the order the user selected.\n const helperGroups: Array<{ todosDir: string; workspace: string; items: TodoItem[]; scopeLabel: string }> = [];\n for (const co of callerOrder) {\n const checklist = await readChecklist(todosDir, co.workspace);\n const items: TodoItem[] = [];\n for (const id of co.todoIds) {\n const item = checklist.items.find((i) => i.id === id);\n if (!item) return { ok: false, error: `Todo \"${id}\" not found in workspace \"${co.workspace}\"` };\n if (item.status === 'completed') return { ok: false, error: `Todo \"${id}\" is already completed` };\n items.push(item);\n }\n const scopeLabel = co.workspace === '_global' ? '_global' : `workspace:${co.workspace}`;\n helperGroups.push({ todosDir, workspace: co.workspace, items, scopeLabel });\n }\n if (helperGroups.every((g) => g.items.length === 0)) {\n return { ok: false, error: 'No selectable todos found in the requested groups' };\n }\n const firstItem = helperGroups.flatMap((g) => g.items)[0];\n const promoted = await promoteTodosToNewAssignment(helperGroups, {\n title: title || firstItem.description,\n target: parsed.target,\n type,\n priority,\n keepSource,\n });\n return {\n ok: true,\n result: {\n assignmentRef: promoted.assignmentRef,\n assignmentDir: promoted.assignmentDir,\n promoted: promoted.promoted.map((p) => p.id),\n promotedByWorkspace: promoted.promotedByWorkspace,\n },\n };\n }\n return wsLock(lockOrder[index].workspace, async () => runWithLocks(index + 1));\n };\n\n const out = await runWithLocks(0);\n if (!out.ok) { res.status(400).json({ error: out.error }); return; }\n broadcastUpdate();\n res.json(out.result);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to bulk-promote todos' });\n }\n });\n\n // GET / — aggregate all workspace checklists\n router.get('/', async (_req, res) => {\n try {\n await ensureDir(todosDir);\n const files = await readdir(todosDir).catch(() => []);\n const workspaces: Array<{\n workspace: string;\n archiveInterval: string;\n items: TodoItem[];\n counts: ReturnType<typeof computeCounts>;\n }> = [];\n\n for (const file of files) {\n if (typeof file !== 'string') continue;\n if (!file.endsWith('.md') || file.endsWith('-log.md')) continue;\n const workspace = file.replace('.md', '');\n const checklist = await readChecklist(todosDir, workspace);\n workspaces.push({\n workspace: checklist.workspace,\n archiveInterval: checklist.archiveInterval,\n items: checklist.items,\n counts: computeCounts(checklist.items),\n });\n }\n\n res.json({ workspaces });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to list todos' });\n }\n });\n\n // GET /:workspace — list items for one workspace\n router.get('/:workspace', async (req, res) => {\n try {\n const workspace = getWorkspaceParam(req.params.workspace);\n const checklist = await readChecklist(todosDir, workspace);\n res.json({\n workspace: checklist.workspace,\n archiveInterval: checklist.archiveInterval,\n items: checklist.items,\n counts: computeCounts(checklist.items),\n });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to get todos' });\n }\n });\n\n // POST /:workspace — add item\n router.post('/:workspace', async (req, res) => {\n try {\n const workspace = getWorkspaceParam(req.params.workspace);\n const { description, tags } = req.body;\n if (!description || typeof description !== 'string') {\n res.status(400).json({ error: 'description is required' });\n return;\n }\n\n const item = await wsLock(workspace, async () => {\n const checklist = await readChecklist(todosDir, workspace);\n const existingIds = new Set(checklist.items.map((i) => i.id));\n const id = generateUniqueId(existingIds);\n const now = new Date().toISOString();\n\n const newItem: TodoItem = {\n id,\n description,\n status: 'open',\n tags: Array.isArray(tags) ? tags : [],\n session: null,\n branch: null,\n worktreePath: null,\n createdAt: now,\n updatedAt: now,\n planDir: null,\n linkedAssignmentId: null,\n linkedAssignmentRef: null,\n };\n checklist.items.push(newItem);\n await writeChecklist(todosDir, checklist);\n return newItem;\n });\n broadcastUpdate();\n res.status(201).json(item);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to add todo' });\n }\n });\n\n // POST /:workspace/reorder — reorder items\n // Must be before /:workspace/:id to avoid param capture\n router.post('/:workspace/reorder', async (req, res) => {\n try {\n const workspace = getWorkspaceParam(req.params.workspace);\n const { ids } = req.body;\n if (!Array.isArray(ids) || !ids.every((id: unknown) => typeof id === 'string')) {\n res.status(400).json({ error: 'ids must be an array of strings' });\n return;\n }\n\n const items = await wsLock(workspace, async () => {\n const checklist = await readChecklist(todosDir, workspace);\n const itemMap = new Map(checklist.items.map((i) => [i.id, i]));\n\n // Build reordered list: requested order first, then any items not in the ids array\n const reordered: TodoItem[] = [];\n for (const id of ids) {\n const item = itemMap.get(id);\n if (item) {\n reordered.push(item);\n itemMap.delete(id);\n }\n }\n // Append any remaining items not mentioned in ids\n for (const item of itemMap.values()) {\n reordered.push(item);\n }\n\n checklist.items = reordered;\n await writeChecklist(todosDir, checklist);\n return reordered;\n });\n broadcastUpdate();\n res.json({ items });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to reorder todos' });\n }\n });\n\n // GET /:workspace/log — full log\n // Must be before /:workspace/:id to avoid param capture\n router.get('/:workspace/log', async (req, res) => {\n try {\n const log = await readLog(todosDir, getWorkspaceParam(req.params.workspace));\n res.json(log);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to get log' });\n }\n });\n\n // POST /:workspace/archive — trigger archive\n router.post('/:workspace/archive', async (req, res) => {\n try {\n // Import archive logic inline to avoid circular deps\n const { archivePath } = await import('../todos/parser.js');\n const { resolve } = await import('node:path');\n const { readFile } = await import('node:fs/promises');\n const { writeFileForce } = await import('../utils/fs.js');\n\n const workspace = getWorkspaceParam(req.params.workspace);\n const checklist = await readChecklist(todosDir, workspace);\n const log = await readLog(todosDir, workspace);\n\n const completedIds = new Set(\n checklist.items.filter((i) => i.status === 'completed').map((i) => i.id),\n );\n\n if (completedIds.size === 0) {\n res.json({ archived: 0, message: 'No completed items to archive' });\n return;\n }\n\n const toArchive = log.entries.filter((e) =>\n e.itemIds.every((id) => completedIds.has(id)),\n );\n\n const archFile = archivePath(todosDir, workspace, checklist.archiveInterval);\n await ensureDir(resolve(todosDir, 'archive'));\n let archContent = '';\n if (await fileExists(archFile)) {\n archContent = await readFile(archFile, 'utf-8');\n archContent = archContent.trimEnd() + '\\n\\n';\n } else {\n archContent = `---\\nworkspace: ${workspace}\\n---\\n\\n# Archive\\n\\n`;\n }\n\n const completedItems = checklist.items.filter((i) => completedIds.has(i.id));\n for (const item of completedItems) {\n archContent += `- [x] ${item.description} ${item.tags.map((t: string) => `#${t}`).join(' ')} [t:${item.id}]\\n`;\n }\n archContent += '\\n';\n for (const entry of toArchive) {\n archContent += `### ${entry.timestamp} — ${entry.itemIds.map((i: string) => `t:${i}`).join(', ')}\\n`;\n if (entry.items) archContent += `**Items:** ${entry.items}\\n`;\n if (entry.session) archContent += `**Session:** ${entry.session}\\n`;\n if (entry.branch) archContent += `**Branch:** ${entry.branch}\\n`;\n if (entry.summary) archContent += `**Summary:** ${entry.summary}\\n`;\n if (entry.blockers) archContent += `**Blockers:** ${entry.blockers}\\n`;\n archContent += '\\n';\n }\n await writeFileForce(archFile, archContent);\n\n checklist.items = checklist.items.filter((i) => !completedIds.has(i.id));\n await writeChecklist(todosDir, checklist);\n\n broadcastUpdate();\n res.json({ archived: completedIds.size, logEntries: toArchive.length });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to archive' });\n }\n });\n\n // GET /:workspace/log/:id — log for specific item\n router.get('/:workspace/log/:id', async (req, res) => {\n try {\n const log = await readLog(todosDir, getWorkspaceParam(req.params.workspace));\n const entries = log.entries.filter((e) => e.itemIds.includes(req.params.id));\n res.json({ workspace: log.workspace, entries });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to get log' });\n }\n });\n\n // GET /:workspace/:id — single item with log\n router.get('/:workspace/:id', async (req, res) => {\n try {\n const workspace = getWorkspaceParam(req.params.workspace);\n const checklist = await readChecklist(todosDir, workspace);\n const item = checklist.items.find((i) => i.id === req.params.id);\n if (!item) {\n res.status(404).json({ error: `Todo \"${req.params.id}\" not found` });\n return;\n }\n const log = await readLog(todosDir, workspace);\n const logEntries = log.entries.filter((e) => e.itemIds.includes(req.params.id));\n res.json({ ...item, log: logEntries });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to get todo' });\n }\n });\n\n // PATCH /:workspace/:id — update description or tags\n router.patch('/:workspace/:id', async (req, res) => {\n try {\n const workspace = getWorkspaceParam(req.params.workspace);\n const result = await wsLock(workspace, async () => {\n const checklist = await readChecklist(todosDir, workspace);\n const item = checklist.items.find((i) => i.id === req.params.id);\n if (!item) return null;\n if (req.body.description !== undefined) item.description = req.body.description;\n if (Array.isArray(req.body.tags)) item.tags = req.body.tags;\n touchItem(item);\n await writeChecklist(todosDir, checklist);\n return { ...item };\n });\n if (!result) { res.status(404).json({ error: `Todo \"${req.params.id}\" not found` }); return; }\n broadcastUpdate();\n res.json(result);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to update todo' });\n }\n });\n\n // DELETE /:workspace/:id\n router.delete('/:workspace/:id', async (req, res) => {\n try {\n const workspace = getWorkspaceParam(req.params.workspace);\n const deleted = await wsLock(workspace, async () => {\n const checklist = await readChecklist(todosDir, workspace);\n const idx = checklist.items.findIndex((i) => i.id === req.params.id);\n if (idx === -1) return false;\n checklist.items.splice(idx, 1);\n await writeChecklist(todosDir, checklist);\n return true;\n });\n if (!deleted) { res.status(404).json({ error: `Todo \"${req.params.id}\" not found` }); return; }\n broadcastUpdate();\n res.json({ deleted: req.params.id });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to delete todo' });\n }\n });\n\n // POST /:workspace/:id/start\n router.post('/:workspace/:id/start', async (req, res) => {\n try {\n const workspace = getWorkspaceParam(req.params.workspace);\n const result = await wsLock(workspace, async () => {\n const checklist = await readChecklist(todosDir, workspace);\n const item = checklist.items.find((i) => i.id === req.params.id);\n if (!item) return { error: 'not_found' as const };\n if (item.status === 'in_progress') return { error: 'conflict' as const, session: item.session };\n item.status = 'in_progress';\n item.session = req.body.session || null;\n if (req.body.branch) item.branch = req.body.branch;\n if (req.body.worktreePath) item.worktreePath = req.body.worktreePath;\n touchItem(item);\n await writeChecklist(todosDir, checklist);\n return { item: { ...item } };\n });\n if ('error' in result) {\n if (result.error === 'not_found') { res.status(404).json({ error: `Todo \"${req.params.id}\" not found` }); return; }\n res.status(409).json({ error: `Todo is already in progress (session: ${result.session})` }); return;\n }\n broadcastUpdate();\n res.json(result.item);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to start todo' });\n }\n });\n\n // POST /:workspace/:id/complete\n router.post('/:workspace/:id/complete', async (req, res) => {\n try {\n const workspace = getWorkspaceParam(req.params.workspace);\n const result = await wsLock(workspace, async () => {\n const checklist = await readChecklist(todosDir, workspace);\n const item = checklist.items.find((i) => i.id === req.params.id);\n if (!item) return null;\n item.status = 'completed';\n item.session = null;\n const branchForLog = req.body.branch || item.branch || null;\n touchItem(item);\n await writeChecklist(todosDir, checklist);\n\n const entry: LogEntry = {\n timestamp: new Date().toISOString(),\n itemIds: [item.id],\n items: item.description,\n session: req.body.session || null,\n branch: branchForLog,\n summary: req.body.summary || 'Completed.',\n blockers: null,\n status: null,\n };\n await appendLogEntry(todosDir, workspace, entry);\n return { ...item };\n });\n if (!result) { res.status(404).json({ error: `Todo \"${req.params.id}\" not found` }); return; }\n broadcastUpdate();\n res.json(result);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to complete todo' });\n }\n });\n\n // POST /:workspace/:id/block\n router.post('/:workspace/:id/block', async (req, res) => {\n try {\n const reason = req.body.reason || null;\n const workspace = getWorkspaceParam(req.params.workspace);\n const result = await wsLock(workspace, async () => {\n const checklist = await readChecklist(todosDir, workspace);\n const item = checklist.items.find((i) => i.id === req.params.id);\n if (!item) return null;\n item.status = 'blocked';\n item.session = null;\n touchItem(item);\n await writeChecklist(todosDir, checklist);\n\n const entry: LogEntry = {\n timestamp: new Date().toISOString(),\n itemIds: [item.id],\n items: item.description,\n session: req.body.session || null,\n branch: null,\n summary: reason || 'Blocked.',\n blockers: reason,\n status: 'blocked',\n };\n await appendLogEntry(todosDir, workspace, entry);\n return { ...item };\n });\n if (!result) { res.status(404).json({ error: `Todo \"${req.params.id}\" not found` }); return; }\n broadcastUpdate();\n res.json(result);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to block todo' });\n }\n });\n\n // POST /:workspace/:id/reopen — move completed back to open\n router.post('/:workspace/:id/reopen', async (req, res) => {\n try {\n const workspace = getWorkspaceParam(req.params.workspace);\n const result = await wsLock(workspace, async () => {\n const checklist = await readChecklist(todosDir, workspace);\n const item = checklist.items.find((i) => i.id === req.params.id);\n if (!item) return null;\n item.status = 'open';\n item.session = null;\n touchItem(item);\n await writeChecklist(todosDir, checklist);\n return { ...item };\n });\n if (!result) { res.status(404).json({ error: `Todo \"${req.params.id}\" not found` }); return; }\n broadcastUpdate();\n res.json(result);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to reopen todo' });\n }\n });\n\n // POST /:workspace/promote\n router.post('/:workspace/promote', async (req, res) => {\n try {\n const workspace = getWorkspaceParam(req.params.workspace);\n const { todoIds, mode, target, title, type, priority, keepSource } = req.body ?? {};\n if (!Array.isArray(todoIds) || todoIds.length === 0) {\n res.status(400).json({ error: 'todoIds (non-empty array of strings) is required' });\n return;\n }\n if (mode !== 'new-assignment' && mode !== 'to-assignment') {\n res.status(400).json({ error: 'mode must be \"new-assignment\" or \"to-assignment\"' });\n return;\n }\n\n const result = await wsLock(workspace, async () => {\n const checklist = await readChecklist(todosDir, workspace);\n const items: TodoItem[] = [];\n for (const id of todoIds) {\n const item = checklist.items.find((i) => i.id === id);\n if (!item) return { error: `Todo \"${id}\" not found` };\n if (item.status === 'completed') return { error: `Todo \"${id}\" is already completed` };\n items.push(item);\n }\n\n const scopeLabel = workspace === '_global' ? '_global' : `workspace:${workspace}`;\n\n if (mode === 'new-assignment') {\n if (items.length > 1 && !title) return { error: 'title is required when promoting multiple todos' };\n const parsed = parsePromoteTarget(target);\n if (!parsed.ok) return { error: parsed.error };\n const promoted = await promoteTodosToNewAssignment(\n [{ todosDir, workspace, items, scopeLabel }],\n {\n title: title || items[0].description,\n target: parsed.target,\n type,\n priority,\n keepSource,\n },\n );\n return {\n assignmentRef: promoted.assignmentRef,\n assignmentDir: promoted.assignmentDir,\n promoted: promoted.promoted.map((p) => p.id),\n };\n }\n\n // to-assignment mode (unchanged)\n const { resolve: resolvePath } = await import('node:path');\n const { readConfig } = await import('../utils/config.js');\n const { assignmentsDir: assignmentsDirFn } = await import('../utils/paths.js');\n const { fileExists, writeFileForce } = await import('../utils/fs.js');\n const { readFile } = await import('node:fs/promises');\n const { appendTodosToAssignmentBody, touchAssignmentUpdated } = await import('../utils/assignment-todos.js');\n const { nowTimestamp } = await import('../utils/timestamp.js');\n\n let assignmentRef: string;\n let assignmentDir: string;\n\n const tg: string = target?.assignment || '';\n if (!tg) return { error: 'target.assignment is required for to-assignment mode' };\n if (tg.includes('/')) {\n const parts = tg.split('/');\n if (parts.length !== 2) return { error: `Invalid target.assignment \"${tg}\"` };\n const config = await readConfig();\n assignmentDir = resolvePath(config.defaultProjectDir, parts[0], 'assignments', parts[1]);\n assignmentRef = `${parts[0]}/${parts[1]}`;\n } else if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(tg)) {\n assignmentDir = resolvePath(assignmentsDirFn(), tg);\n assignmentRef = tg;\n } else {\n return { error: `Invalid target.assignment \"${tg}\"` };\n }\n const assignmentMdPath = resolvePath(assignmentDir, 'assignment.md');\n if (!(await fileExists(assignmentMdPath))) return { error: `Target assignment not found: ${assignmentMdPath}` };\n\n let content = await readFile(assignmentMdPath, 'utf-8');\n content = appendTodosToAssignmentBody(\n content,\n items.map((it) => ({\n description: it.description,\n trace: `promoted from t:${it.id} in ${scopeLabel}`,\n })),\n );\n content = touchAssignmentUpdated(content, nowTimestamp());\n await writeFileForce(assignmentMdPath, content);\n\n if (!keepSource) {\n for (const item of items) {\n item.status = 'completed';\n item.session = null;\n touchItem(item);\n }\n await writeChecklist(todosDir, checklist);\n for (const item of items) {\n const entry: LogEntry = {\n timestamp: new Date().toISOString(),\n itemIds: [item.id],\n items: item.description,\n session: null,\n branch: item.branch || null,\n summary: `Promoted to assignment ${assignmentRef}`,\n blockers: null,\n status: null,\n };\n await appendLogEntry(todosDir, workspace, entry);\n }\n }\n\n return { assignmentRef, assignmentDir, promoted: items.map((i) => i.id) };\n });\n\n if ('error' in result) { res.status(400).json({ error: result.error }); return; }\n broadcastUpdate();\n res.json(result);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to promote todos' });\n }\n });\n\n // POST /:workspace/:id/move — cross-scope move (workspace/global ↔ project/global)\n router.post('/:workspace/:id/move', async (req, res) => {\n try {\n const sourceWs = getWorkspaceParam(req.params.workspace);\n const id = req.params.id;\n const to = req.body?.to;\n if (!to || typeof to !== 'object') {\n res.status(400).json({ error: 'body.to is required' });\n return;\n }\n const targetCount = [Boolean(to.workspace), Boolean(to.project), Boolean(to.global)].filter(Boolean).length;\n if (targetCount !== 1) {\n res.status(400).json({ error: 'body.to must specify exactly one of workspace, project, or global' });\n return;\n }\n if (to.project && !isValidSlug(to.project)) {\n res.status(400).json({ error: `Invalid target project slug: \"${to.project}\"` });\n return;\n }\n if (to.workspace && !WORKSPACE_REGEX.test(to.workspace)) {\n res.status(400).json({ error: `Invalid target workspace name: \"${to.workspace}\"` });\n return;\n }\n\n // Resolve target scope details (todosPath, scope id, lock key, broadcast).\n type Target =\n | { kind: 'workspace'; id: string; todosPath: string; lockKey: string }\n | { kind: 'project'; id: string; todosPath: string; lockKey: string };\n\n let target: Target;\n if (to.global) {\n target = { kind: 'workspace', id: '_global', todosPath: todosDir, lockKey: 'ws:_global' };\n } else if (to.workspace) {\n target = { kind: 'workspace', id: to.workspace, todosPath: todosDir, lockKey: `ws:${to.workspace}` };\n } else {\n if (!projectsDir) {\n res.status(500).json({ error: 'Server not configured with projectsDir; cannot move to project scope' });\n return;\n }\n const slug = to.project as string;\n const projectMd = resolvePath(projectsDir, slug, 'project.md');\n if (!(await fileExists(projectMd))) {\n res.status(404).json({ error: `Target project \"${slug}\" not found` });\n return;\n }\n target = {\n kind: 'project',\n id: slug,\n todosPath: projectTodosDir(projectsDir, slug),\n lockKey: `proj:${slug}`,\n };\n }\n\n const sourceLockKey = `ws:${sourceWs}`;\n if (sourceLockKey === target.lockKey) {\n res.status(400).json({ error: 'cannot move to the same scope' });\n return;\n }\n\n const result = await withTwoLocks(sourceLockKey, target.lockKey, async () => {\n const sourceChecklist = await readChecklist(todosDir, sourceWs);\n const targetChecklist = await readChecklist(target.todosPath, target.id);\n\n const idx = sourceChecklist.items.findIndex((i) => i.id === id);\n if (idx === -1) return { status: 404 as const, error: `Todo \"${id}\" not found` };\n\n if (targetChecklist.items.some((i) => i.id === id)) {\n return { status: 409 as const, error: 'id already exists in target' };\n }\n\n const item = sourceChecklist.items[idx];\n if (item.planDir) {\n const newPlanDir = todoPlanDir(target.todosPath, target.id, id);\n if (await fileExists(newPlanDir)) {\n return { status: 409 as const, error: 'plan dir already exists in target' };\n }\n await mkdir(dirname(newPlanDir), { recursive: true });\n await rename(item.planDir, newPlanDir);\n item.planDir = newPlanDir;\n }\n\n sourceChecklist.items.splice(idx, 1);\n targetChecklist.items.push(item);\n\n await writeChecklist(todosDir, sourceChecklist);\n await writeChecklist(target.todosPath, targetChecklist);\n\n const sourceLabel = sourceWs === '_global' ? '_global' : `workspace:${sourceWs}`;\n const targetLabel =\n target.kind === 'project' ? `project:${target.id}` : target.id === '_global' ? '_global' : `workspace:${target.id}`;\n const ts = new Date().toISOString();\n await appendLogEntry(todosDir, sourceWs, {\n timestamp: ts,\n itemIds: [id],\n items: item.description,\n session: null,\n branch: item.branch || null,\n summary: `Moved to ${targetLabel}`,\n blockers: null,\n status: null,\n });\n await appendLogEntry(target.todosPath, target.id, {\n timestamp: ts,\n itemIds: [id],\n items: item.description,\n session: null,\n branch: item.branch || null,\n summary: `Moved from ${sourceLabel}`,\n blockers: null,\n status: null,\n });\n\n return { status: 200 as const, item };\n });\n\n if (result.status !== 200) {\n res.status(result.status).json({ error: result.error });\n return;\n }\n\n // Dual broadcast: source scope, then target scope.\n broadcastUpdate(); // source is workspace\n if (target.kind === 'project') broadcastProject(target.id);\n else broadcastUpdate();\n\n res.json({ moved: id, to: target });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to move todo' });\n }\n });\n\n // POST /:workspace/:id/unblock\n router.post('/:workspace/:id/unblock', async (req, res) => {\n try {\n const workspace = getWorkspaceParam(req.params.workspace);\n const result = await wsLock(workspace, async () => {\n const checklist = await readChecklist(todosDir, workspace);\n const item = checklist.items.find((i) => i.id === req.params.id);\n if (!item) return null;\n item.status = 'open';\n item.session = null;\n touchItem(item);\n await writeChecklist(todosDir, checklist);\n return { ...item };\n });\n if (!result) { res.status(404).json({ error: `Todo \"${req.params.id}\" not found` }); return; }\n broadcastUpdate();\n res.json(result);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to unblock todo' });\n }\n });\n\n return router;\n}\n","import type { TodoItem, LogEntry } from '../todos/types.js';\nimport {\n readChecklist,\n writeChecklist,\n appendLogEntry,\n} from '../todos/parser.js';\nimport { createAssignmentCommand } from '../commands/create-assignment.js';\nimport { isValidSlug } from './slug.js';\n\nexport interface PromoteSourceGroup {\n /** Workspace todos dir OR projectTodosDir(...) for project-scope todos. */\n todosDir: string;\n /** Checklist workspace key (e.g. `_global`, `alpha`, or project slug for project todos). */\n workspace: string;\n /** Selected items from that checklist (already validated as non-completed). */\n items: TodoItem[];\n /** Human-readable scope label for log entries: `workspace:alpha` | `_global` | `project:foo`. */\n scopeLabel: string;\n}\n\nexport type PromoteTarget =\n | { project: string }\n | { oneOff: true; workspaceGroup?: string };\n\nexport interface PromoteToNewAssignmentOptions {\n title: string;\n target: PromoteTarget;\n type?: string;\n priority?: 'low' | 'medium' | 'high' | 'critical';\n keepSource?: boolean;\n}\n\nexport interface PromoteToNewAssignmentResult {\n id: string;\n slug: string;\n projectSlug: string | null;\n assignmentDir: string;\n assignmentRef: string;\n promoted: Array<{ workspace: string; id: string }>;\n promotedByWorkspace: Array<{ workspace: string; ids: string[] }>;\n}\n\n/**\n * Parse the JSON `target` field from a promote request body into the helper's\n * typed target. Returns `{ error }` for invalid combinations so callers can\n * surface the message verbatim (matching legacy validation messages where\n * possible).\n */\nexport function parsePromoteTarget(\n target: unknown,\n):\n | { ok: true; target: PromoteTarget }\n | { ok: false; error: string } {\n if (!target || typeof target !== 'object') {\n return { ok: false, error: 'target is required for new-assignment mode' };\n }\n const t = target as Record<string, unknown>;\n const hasProject = typeof t.project === 'string' && t.project.length > 0;\n const hasOneOff = t.oneOff === true;\n if (hasProject && hasOneOff) {\n return { ok: false, error: 'target cannot specify both project and oneOff' };\n }\n if (hasProject) {\n const project = t.project as string;\n if (!isValidSlug(project)) {\n return { ok: false, error: `Invalid target.project slug \"${project}\"` };\n }\n return { ok: true, target: { project } };\n }\n if (hasOneOff) {\n const wg = typeof t.workspaceGroup === 'string' ? t.workspaceGroup : undefined;\n if (wg !== undefined && !isValidSlug(wg)) {\n return { ok: false, error: `Invalid target.workspaceGroup slug \"${wg}\"` };\n }\n return { ok: true, target: { oneOff: true, workspaceGroup: wg } };\n }\n return { ok: false, error: 'target.project is required for new-assignment mode' };\n}\n\nfunction touchItem(item: TodoItem): void {\n const now = new Date().toISOString();\n if (item.createdAt === null) item.createdAt = now;\n item.updatedAt = now;\n}\n\n/**\n * Create a new assignment from the selected todos' descriptions and link the\n * source todos back to it. Source todos flip to `in_progress` with\n * `linkedAssignmentId` (UUID) and `linkedAssignmentRef` (`projectSlug/slug` or\n * bare UUID for one-off) populated, unless `keepSource` is true in which case\n * the source checklists are left untouched.\n */\nexport async function promoteTodosToNewAssignment(\n groups: PromoteSourceGroup[],\n options: PromoteToNewAssignmentOptions,\n): Promise<PromoteToNewAssignmentResult> {\n if (groups.length === 0 || groups.every((g) => g.items.length === 0)) {\n throw new Error('At least one source todo is required to promote.');\n }\n if (!options.title.trim()) {\n throw new Error('Title is required.');\n }\n\n const acceptanceCriteria: string[] = [];\n for (const g of groups) {\n for (const it of g.items) acceptanceCriteria.push(it.description);\n }\n\n const oneOff = 'oneOff' in options.target;\n const created = await createAssignmentCommand(options.title, {\n project: oneOff ? undefined : (options.target as { project: string }).project,\n oneOff: oneOff ? true : undefined,\n workspace: oneOff ? (options.target as { oneOff: true; workspaceGroup?: string }).workspaceGroup : undefined,\n type: options.type,\n priority: options.priority,\n acceptanceCriteria,\n withTodos: false,\n silent: true,\n });\n\n const assignmentRef = created.projectSlug\n ? `${created.projectSlug}/${created.slug}`\n : created.id;\n\n const promoted: Array<{ workspace: string; id: string }> = [];\n const promotedByWorkspace: Array<{ workspace: string; ids: string[] }> = [];\n\n if (!options.keepSource) {\n for (const group of groups) {\n // Re-read the checklist (caller is expected to hold the workspace lock\n // around this call when concurrency matters).\n const checklist = await readChecklist(group.todosDir, group.workspace);\n const idsTouched: string[] = [];\n for (const sel of group.items) {\n const item = checklist.items.find((i) => i.id === sel.id);\n if (!item) continue;\n item.status = 'in_progress';\n item.session = null;\n item.linkedAssignmentId = created.id;\n item.linkedAssignmentRef = assignmentRef;\n touchItem(item);\n idsTouched.push(item.id);\n }\n await writeChecklist(group.todosDir, checklist);\n for (const id of idsTouched) {\n const sourceItem = group.items.find((i) => i.id === id);\n const entry: LogEntry = {\n timestamp: new Date().toISOString(),\n itemIds: [id],\n items: sourceItem?.description ?? '',\n session: null,\n branch: sourceItem?.branch ?? null,\n summary: `Linked to assignment ${assignmentRef} (auto-promoted from ${group.scopeLabel})`,\n blockers: null,\n status: null,\n };\n await appendLogEntry(group.todosDir, group.workspace, entry);\n promoted.push({ workspace: group.workspace, id });\n }\n if (idsTouched.length > 0) {\n promotedByWorkspace.push({ workspace: group.workspace, ids: idsTouched });\n }\n }\n }\n\n return {\n id: created.id,\n slug: created.slug,\n projectSlug: created.projectSlug,\n assignmentDir: created.assignmentDir,\n assignmentRef,\n promoted,\n promotedByWorkspace,\n };\n}\n","import { resolve } from 'node:path';\nimport { slugify, isValidSlug } from '../utils/slug.js';\nimport { nowTimestamp } from '../utils/timestamp.js';\nimport { generateId } from '../utils/uuid.js';\nimport { expandHome, assignmentsDir as assignmentsDirFn } from '../utils/paths.js';\nimport { ensureDir, writeFileForce, fileExists } from '../utils/fs.js';\nimport { readConfig } from '../utils/config.js';\nimport {\n renderAssignment,\n renderScratchpad,\n renderHandoff,\n renderDecisionRecord,\n renderProgress,\n renderComments,\n} from '../templates/index.js';\n\nexport interface CreateAssignmentOptions {\n project?: string;\n oneOff?: boolean;\n slug?: string;\n priority?: 'low' | 'medium' | 'high' | 'critical';\n dependsOn?: string;\n links?: string;\n dir?: string;\n type?: string;\n withTodos?: boolean;\n workspace?: string;\n silent?: boolean;\n ready?: boolean;\n acceptanceCriteria?: string[];\n}\n\nexport interface CreateAssignmentResult {\n id: string;\n slug: string;\n projectSlug: string | null;\n assignmentDir: string;\n}\n\nexport async function createAssignmentCommand(\n title: string,\n options: CreateAssignmentOptions,\n): Promise<CreateAssignmentResult> {\n if (!title.trim()) {\n throw new Error('Assignment title cannot be empty.');\n }\n\n // --workspace guards run before the generic --project/--one-off guard so that\n // `--workspace <slug>` alone reports the actionable message rather than the\n // generic \"Either --project or --one-off is required.\" error.\n if (options.workspace && options.project) {\n throw new Error(\n 'Cannot use --workspace with --project (projects already carry a workspace via project.workspace).',\n );\n }\n if (options.workspace && !options.oneOff) {\n throw new Error('--workspace requires --one-off.');\n }\n\n if (!options.project && !options.oneOff) {\n throw new Error(\n 'Either --project <slug> or --one-off is required.',\n );\n }\n if (options.project && options.oneOff) {\n throw new Error(\n 'Cannot use both --project and --one-off. Use --project to add to an existing project, or --one-off to create a standalone assignment.',\n );\n }\n\n if (options.project && !isValidSlug(options.project)) {\n throw new Error(\n `Invalid project slug \"${options.project}\". Slugs must be lowercase, hyphen-separated, with no special characters.`,\n );\n }\n\n // Stricter than server.ts:240 / createProjectCommand by design — assignment slugs already use isValidSlug.\n if (options.workspace && !isValidSlug(options.workspace)) {\n throw new Error(\n `Invalid workspace slug \"${options.workspace}\". Slugs must be lowercase, hyphen-separated, with no special characters.`,\n );\n }\n\n if (options.oneOff && options.dependsOn) {\n throw new Error('Standalone assignments cannot have dependencies (--depends-on is not allowed with --one-off).');\n }\n\n const assignmentSlug = options.slug || slugify(title);\n if (!isValidSlug(assignmentSlug)) {\n throw new Error(\n `Invalid slug \"${assignmentSlug}\". Slugs must be lowercase, hyphen-separated, with no special characters.`,\n );\n }\n\n const dependsOn = options.dependsOn\n ? options.dependsOn.split(',').map((s) => s.trim()).filter(Boolean)\n : [];\n for (const dep of dependsOn) {\n if (!isValidSlug(dep)) {\n throw new Error(\n `Invalid dependency slug \"${dep}\". Slugs must be lowercase, hyphen-separated, with no special characters.`,\n );\n }\n }\n\n const links = options.links\n ? options.links.split(',').map((s) => s.trim()).filter(Boolean)\n : [];\n for (const link of links) {\n const parts = link.split('/');\n if (parts.length !== 2 || !parts.every(isValidSlug)) {\n throw new Error(\n `Invalid link \"${link}\". Links must be in projectSlug/assignmentSlug format (e.g., \"my-project/my-assignment\").`,\n );\n }\n }\n\n const validPriorities = ['low', 'medium', 'high', 'critical'] as const;\n const priority = (options.priority || 'medium') as typeof validPriorities[number];\n if (!validPriorities.includes(priority)) {\n throw new Error(\n `Invalid priority \"${options.priority}\". Must be one of: ${validPriorities.join(', ')}`,\n );\n }\n\n const config = await readConfig();\n const timestamp = nowTimestamp();\n const id = generateId();\n\n let assignmentDir: string;\n let projectSlug: string | null;\n let folderName: string;\n\n if (options.oneOff) {\n // Standalone: folder name = UUID, project: null\n const standaloneRoot = assignmentsDirFn();\n folderName = id;\n assignmentDir = resolve(standaloneRoot, folderName);\n projectSlug = null;\n await ensureDir(standaloneRoot);\n } else {\n const baseDir = options.dir\n ? expandHome(options.dir)\n : config.defaultProjectDir;\n projectSlug = options.project!;\n const projectDir = resolve(baseDir, projectSlug);\n\n const projectMdPath = resolve(projectDir, 'project.md');\n if (!(await fileExists(projectDir)) || !(await fileExists(projectMdPath))) {\n throw new Error(\n `Project \"${projectSlug}\" not found at ${projectDir}.\\nRun 'syntaur create-project' first or use --one-off.`,\n );\n }\n\n if (dependsOn.length > 0) {\n const depDirBase = resolve(projectDir, 'assignments');\n for (const dep of dependsOn) {\n const depDir = resolve(depDirBase, dep);\n if (!(await fileExists(depDir))) {\n console.warn(\n `Warning: dependency \"${dep}\" does not exist in project \"${projectSlug}\" yet.`,\n );\n }\n }\n }\n\n folderName = assignmentSlug;\n assignmentDir = resolve(projectDir, 'assignments', folderName);\n }\n\n if (await fileExists(assignmentDir)) {\n throw new Error(\n `Assignment folder already exists: ${assignmentDir}\\nUse --slug to specify a different slug.`,\n );\n }\n\n await ensureDir(assignmentDir);\n\n const companionAssignmentRef = projectSlug === null ? id : assignmentSlug;\n\n const files: Array<[string, string]> = [\n [\n resolve(assignmentDir, 'assignment.md'),\n renderAssignment({\n id,\n slug: assignmentSlug,\n title,\n timestamp,\n priority,\n dependsOn,\n links,\n project: projectSlug,\n workspaceGroup: options.workspace ?? null,\n type: options.type,\n includeTodos: options.withTodos === true,\n status: options.ready ? 'ready_for_planning' : 'draft',\n acceptanceCriteria: options.acceptanceCriteria,\n }),\n ],\n [\n resolve(assignmentDir, 'scratchpad.md'),\n renderScratchpad({\n assignmentSlug: companionAssignmentRef,\n timestamp,\n }),\n ],\n [\n resolve(assignmentDir, 'handoff.md'),\n renderHandoff({\n assignmentSlug: companionAssignmentRef,\n timestamp,\n }),\n ],\n [\n resolve(assignmentDir, 'decision-record.md'),\n renderDecisionRecord({\n assignmentSlug: companionAssignmentRef,\n timestamp,\n }),\n ],\n [\n resolve(assignmentDir, 'progress.md'),\n renderProgress({\n assignment: companionAssignmentRef,\n timestamp,\n }),\n ],\n [\n resolve(assignmentDir, 'comments.md'),\n renderComments({\n assignment: companionAssignmentRef,\n timestamp,\n }),\n ],\n ];\n\n for (const [filePath, content] of files) {\n await writeFileForce(filePath, content);\n }\n\n if (!options.silent) {\n if (projectSlug === null) {\n console.log(\n `Created standalone assignment \"${title}\" at ${assignmentDir}/`,\n );\n console.log(` UUID: ${id}`);\n console.log(` Slug: ${assignmentSlug} (display only)`);\n } else {\n console.log(\n `Created assignment \"${title}\" in project \"${projectSlug}\" at ${assignmentDir}/`,\n );\n console.log(` Slug: ${assignmentSlug}`);\n }\n console.log(` Priority: ${priority}`);\n if (options.type) {\n console.log(` Type: ${options.type}`);\n }\n if (dependsOn.length > 0) {\n console.log(` Depends on: ${dependsOn.join(', ')}`);\n }\n if (links.length > 0) {\n console.log(` Links: ${links.join(', ')}`);\n }\n console.log(` Files created:`);\n console.log(` assignment.md`);\n console.log(` scratchpad.md`);\n console.log(` handoff.md`);\n console.log(` decision-record.md`);\n console.log(` progress.md`);\n console.log(` comments.md`);\n console.log(\n ` Plan files (plan.md, plan-v2.md, ...) are created on demand by /plan-assignment.`,\n );\n }\n\n return { id, slug: assignmentSlug, projectSlug, assignmentDir };\n}\n","import { Router, type Request, type Response, type NextFunction } from 'express';\nimport { mkdir, readFile, rename } from 'node:fs/promises';\nimport { resolve, dirname } from 'node:path';\nimport {\n readChecklist,\n writeChecklist,\n readLog,\n appendLogEntry,\n archivePath,\n generateUniqueId,\n computeCounts,\n} from '../todos/parser.js';\nimport { fileExists, writeFileForce } from '../utils/fs.js';\nimport { projectTodosDir, todoPlanDir } from '../utils/paths.js';\nimport { isValidSlug } from '../utils/slug.js';\nimport { projLock, wsLock, withTwoLocks } from './todos-locks.js';\nimport type { TodoItem, LogEntry } from '../todos/types.js';\nimport type { WsMessage } from './types.js';\nimport {\n promoteTodosToNewAssignment,\n parsePromoteTarget,\n} from '../utils/promote-todos.js';\n\nconst WORKSPACE_REGEX = /^[a-z0-9_][a-z0-9-]*$/;\n\nfunction touchItem(item: TodoItem): void {\n const now = new Date().toISOString();\n if (item.createdAt === null) item.createdAt = now;\n item.updatedAt = now;\n}\n\nfunction getProjectIdParam(value: string | string[] | undefined): string {\n if (Array.isArray(value)) return value[0] ?? '';\n return value ?? '';\n}\n\ntype ProjectParams = { projectId?: string; id?: string };\nfunction params(req: Request): ProjectParams {\n return req.params as unknown as ProjectParams;\n}\n\nasync function projectExists(projectsDir: string, slug: string): Promise<boolean> {\n return fileExists(resolve(projectsDir, slug, 'project.md'));\n}\n\nasync function ensureProjectTodosDir(projectsDir: string, slug: string): Promise<void> {\n const todosDir = projectTodosDir(projectsDir, slug);\n try {\n await mkdir(todosDir, { recursive: false });\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === 'EEXIST') return;\n if (code === 'ENOENT') {\n const e = new Error('PROJECT_GONE');\n (e as NodeJS.ErrnoException).code = 'PROJECT_GONE';\n throw e;\n }\n throw err;\n }\n try {\n await mkdir(resolve(todosDir, 'archive'), { recursive: false });\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === 'EEXIST') return;\n if (code === 'ENOENT') {\n // Project (or its todos/) disappeared between the two mkdirs — map to\n // the same 404 path the caller already handles for PROJECT_GONE.\n const e = new Error('PROJECT_GONE');\n (e as NodeJS.ErrnoException).code = 'PROJECT_GONE';\n throw e;\n }\n throw err;\n }\n}\n\nfunction notFound(res: Response, slug: string): void {\n res.status(404).json({ error: `Project \"${slug}\" not found` });\n}\n\nexport function createProjectTodosRouter(\n projectsDir: string,\n broadcast: (msg: WsMessage) => void,\n workspaceTodosDir?: string,\n): Router {\n const router = Router({ mergeParams: true });\n\n function broadcastUpdate(projectSlug: string): void {\n broadcast({ type: 'todos-updated', projectSlug, timestamp: new Date().toISOString() });\n }\n function broadcastWorkspace(): void {\n broadcast({ type: 'todos-updated', timestamp: new Date().toISOString() });\n }\n\n function validateProjectId(req: Request, res: Response, next: NextFunction): void {\n const slug = getProjectIdParam(params(req).projectId);\n if (!slug || !isValidSlug(slug)) {\n res.status(400).json({ error: `Invalid project slug: \"${slug}\"` });\n return;\n }\n next();\n }\n\n // router.param only fires for params defined in the subrouter's own route\n // patterns. `:projectId` is on the parent mount path, so run the validator\n // as generic middleware instead.\n router.use(validateProjectId);\n\n // GET / — list this project's todos\n router.get('/', async (req, res) => {\n try {\n const slug = getProjectIdParam(params(req).projectId);\n if (!(await projectExists(projectsDir, slug))) { notFound(res, slug); return; }\n const todosDir = projectTodosDir(projectsDir, slug);\n const checklist = await readChecklist(todosDir, slug);\n res.json({\n workspace: checklist.workspace,\n archiveInterval: checklist.archiveInterval,\n items: checklist.items,\n counts: computeCounts(checklist.items),\n });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to get todos' });\n }\n });\n\n // POST / — add item\n router.post('/', async (req, res) => {\n try {\n const slug = getProjectIdParam(params(req).projectId);\n const { description, tags } = req.body;\n if (!description || typeof description !== 'string') {\n res.status(400).json({ error: 'description is required' });\n return;\n }\n if (!(await projectExists(projectsDir, slug))) { notFound(res, slug); return; }\n\n const item = await projLock(slug, async () => {\n if (!(await projectExists(projectsDir, slug))) return null;\n await ensureProjectTodosDir(projectsDir, slug);\n const todosDir = projectTodosDir(projectsDir, slug);\n const checklist = await readChecklist(todosDir, slug);\n const existingIds = new Set(checklist.items.map((i) => i.id));\n const id = generateUniqueId(existingIds);\n const now = new Date().toISOString();\n const newItem: TodoItem = {\n id,\n description,\n status: 'open',\n tags: Array.isArray(tags) ? tags : [],\n session: null,\n branch: null,\n worktreePath: null,\n createdAt: now,\n updatedAt: now,\n planDir: null,\n linkedAssignmentId: null,\n linkedAssignmentRef: null,\n };\n checklist.workspace = slug;\n checklist.items.push(newItem);\n await writeChecklist(todosDir, checklist);\n return newItem;\n });\n if (!item) { notFound(res, slug); return; }\n broadcastUpdate(slug);\n res.status(201).json(item);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'PROJECT_GONE') {\n notFound(res, getProjectIdParam(params(req).projectId));\n return;\n }\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to add todo' });\n }\n });\n\n // POST /reorder — reorder items (must precede /:id)\n router.post('/reorder', async (req, res) => {\n try {\n const slug = getProjectIdParam(params(req).projectId);\n const { ids } = req.body;\n if (!Array.isArray(ids) || !ids.every((id: unknown) => typeof id === 'string')) {\n res.status(400).json({ error: 'ids must be an array of strings' });\n return;\n }\n if (!(await projectExists(projectsDir, slug))) { notFound(res, slug); return; }\n\n const items = await projLock(slug, async () => {\n if (!(await projectExists(projectsDir, slug))) return null;\n await ensureProjectTodosDir(projectsDir, slug);\n const todosDir = projectTodosDir(projectsDir, slug);\n const checklist = await readChecklist(todosDir, slug);\n const itemMap = new Map(checklist.items.map((i) => [i.id, i]));\n const reordered: TodoItem[] = [];\n for (const id of ids) {\n const item = itemMap.get(id);\n if (item) { reordered.push(item); itemMap.delete(id); }\n }\n for (const item of itemMap.values()) reordered.push(item);\n checklist.workspace = slug;\n checklist.items = reordered;\n await writeChecklist(todosDir, checklist);\n return reordered;\n });\n if (!items) { notFound(res, slug); return; }\n broadcastUpdate(slug);\n res.json({ items });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'PROJECT_GONE') {\n notFound(res, getProjectIdParam(params(req).projectId));\n return;\n }\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to reorder todos' });\n }\n });\n\n // GET /log — full log (must precede /:id)\n router.get('/log', async (req, res) => {\n try {\n const slug = getProjectIdParam(params(req).projectId);\n if (!(await projectExists(projectsDir, slug))) { notFound(res, slug); return; }\n const todosDir = projectTodosDir(projectsDir, slug);\n const log = await readLog(todosDir, slug);\n res.json(log);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to get log' });\n }\n });\n\n // POST /archive\n router.post('/archive', async (req, res) => {\n try {\n const slug = getProjectIdParam(params(req).projectId);\n if (!(await projectExists(projectsDir, slug))) { notFound(res, slug); return; }\n const todosDir = projectTodosDir(projectsDir, slug);\n await ensureProjectTodosDir(projectsDir, slug);\n\n const checklist = await readChecklist(todosDir, slug);\n const log = await readLog(todosDir, slug);\n const completedIds = new Set(\n checklist.items.filter((i) => i.status === 'completed').map((i) => i.id),\n );\n if (completedIds.size === 0) {\n res.json({ archived: 0, message: 'No completed items to archive' });\n return;\n }\n const toArchive = log.entries.filter((e) =>\n e.itemIds.every((id) => completedIds.has(id)),\n );\n const archFile = archivePath(todosDir, slug, checklist.archiveInterval);\n let archContent = '';\n if (await fileExists(archFile)) {\n archContent = await readFile(archFile, 'utf-8');\n archContent = archContent.trimEnd() + '\\n\\n';\n } else {\n archContent = `---\\nworkspace: ${slug}\\n---\\n\\n# Archive\\n\\n`;\n }\n const completedItems = checklist.items.filter((i) => completedIds.has(i.id));\n for (const item of completedItems) {\n archContent += `- [x] ${item.description} ${item.tags.map((t: string) => `#${t}`).join(' ')} [t:${item.id}]\\n`;\n }\n archContent += '\\n';\n for (const entry of toArchive) {\n archContent += `### ${entry.timestamp} — ${entry.itemIds.map((i: string) => `t:${i}`).join(', ')}\\n`;\n if (entry.items) archContent += `**Items:** ${entry.items}\\n`;\n if (entry.session) archContent += `**Session:** ${entry.session}\\n`;\n if (entry.branch) archContent += `**Branch:** ${entry.branch}\\n`;\n if (entry.summary) archContent += `**Summary:** ${entry.summary}\\n`;\n if (entry.blockers) archContent += `**Blockers:** ${entry.blockers}\\n`;\n archContent += '\\n';\n }\n await writeFileForce(archFile, archContent);\n\n checklist.workspace = slug;\n checklist.items = checklist.items.filter((i) => !completedIds.has(i.id));\n await writeChecklist(todosDir, checklist);\n\n broadcastUpdate(slug);\n res.json({ archived: completedIds.size, logEntries: toArchive.length });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'PROJECT_GONE') {\n notFound(res, getProjectIdParam(params(req).projectId));\n return;\n }\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to archive' });\n }\n });\n\n // GET /log/:id — log for a specific item\n router.get('/log/:id', async (req, res) => {\n try {\n const slug = getProjectIdParam(params(req).projectId);\n if (!(await projectExists(projectsDir, slug))) { notFound(res, slug); return; }\n const todosDir = projectTodosDir(projectsDir, slug);\n const log = await readLog(todosDir, slug);\n const entries = log.entries.filter((e) => e.itemIds.includes((params(req).id ?? \"\")));\n res.json({ workspace: log.workspace, entries });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to get log' });\n }\n });\n\n // GET /:id — single item with log\n router.get('/:id', async (req, res) => {\n try {\n const slug = getProjectIdParam(params(req).projectId);\n if (!(await projectExists(projectsDir, slug))) { notFound(res, slug); return; }\n const todosDir = projectTodosDir(projectsDir, slug);\n const checklist = await readChecklist(todosDir, slug);\n const item = checklist.items.find((i) => i.id === (params(req).id ?? \"\"));\n if (!item) { res.status(404).json({ error: `Todo \"${(params(req).id ?? \"\")}\" not found` }); return; }\n const log = await readLog(todosDir, slug);\n const logEntries = log.entries.filter((e) => e.itemIds.includes((params(req).id ?? \"\")));\n res.json({ ...item, log: logEntries });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to get todo' });\n }\n });\n\n // PATCH /:id\n router.patch('/:id', async (req, res) => {\n try {\n const slug = getProjectIdParam(params(req).projectId);\n if (!(await projectExists(projectsDir, slug))) { notFound(res, slug); return; }\n const result = await projLock(slug, async () => {\n if (!(await projectExists(projectsDir, slug))) return 'gone' as const;\n await ensureProjectTodosDir(projectsDir, slug);\n const todosDir = projectTodosDir(projectsDir, slug);\n const checklist = await readChecklist(todosDir, slug);\n const item = checklist.items.find((i) => i.id === (params(req).id ?? \"\"));\n if (!item) return null;\n if (req.body.description !== undefined) item.description = req.body.description;\n if (Array.isArray(req.body.tags)) item.tags = req.body.tags;\n touchItem(item);\n checklist.workspace = slug;\n await writeChecklist(todosDir, checklist);\n return { ...item };\n });\n if (result === 'gone') { notFound(res, slug); return; }\n if (!result) { res.status(404).json({ error: `Todo \"${(params(req).id ?? \"\")}\" not found` }); return; }\n broadcastUpdate(slug);\n res.json(result);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'PROJECT_GONE') {\n notFound(res, getProjectIdParam(params(req).projectId));\n return;\n }\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to update todo' });\n }\n });\n\n // DELETE /:id\n router.delete('/:id', async (req, res) => {\n try {\n const slug = getProjectIdParam(params(req).projectId);\n if (!(await projectExists(projectsDir, slug))) { notFound(res, slug); return; }\n const deleted = await projLock(slug, async () => {\n if (!(await projectExists(projectsDir, slug))) return 'gone' as const;\n await ensureProjectTodosDir(projectsDir, slug);\n const todosDir = projectTodosDir(projectsDir, slug);\n const checklist = await readChecklist(todosDir, slug);\n const idx = checklist.items.findIndex((i) => i.id === (params(req).id ?? \"\"));\n if (idx === -1) return false;\n checklist.items.splice(idx, 1);\n checklist.workspace = slug;\n await writeChecklist(todosDir, checklist);\n return true;\n });\n if (deleted === 'gone') { notFound(res, slug); return; }\n if (!deleted) { res.status(404).json({ error: `Todo \"${(params(req).id ?? \"\")}\" not found` }); return; }\n broadcastUpdate(slug);\n res.json({ deleted: (params(req).id ?? \"\") });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'PROJECT_GONE') {\n notFound(res, getProjectIdParam(params(req).projectId));\n return;\n }\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to delete todo' });\n }\n });\n\n // POST /:id/start\n router.post('/:id/start', async (req, res) => {\n try {\n const slug = getProjectIdParam(params(req).projectId);\n if (!(await projectExists(projectsDir, slug))) { notFound(res, slug); return; }\n const result = await projLock(slug, async () => {\n if (!(await projectExists(projectsDir, slug))) return { error: 'gone' as const };\n await ensureProjectTodosDir(projectsDir, slug);\n const todosDir = projectTodosDir(projectsDir, slug);\n const checklist = await readChecklist(todosDir, slug);\n const item = checklist.items.find((i) => i.id === (params(req).id ?? \"\"));\n if (!item) return { error: 'not_found' as const };\n if (item.status === 'in_progress') return { error: 'conflict' as const, session: item.session };\n item.status = 'in_progress';\n item.session = req.body.session || null;\n if (req.body.branch) item.branch = req.body.branch;\n if (req.body.worktreePath) item.worktreePath = req.body.worktreePath;\n touchItem(item);\n checklist.workspace = slug;\n await writeChecklist(todosDir, checklist);\n return { item: { ...item } };\n });\n if ('error' in result) {\n if (result.error === 'gone') { notFound(res, slug); return; }\n if (result.error === 'not_found') { res.status(404).json({ error: `Todo \"${(params(req).id ?? \"\")}\" not found` }); return; }\n res.status(409).json({ error: `Todo is already in progress (session: ${result.session})` });\n return;\n }\n broadcastUpdate(slug);\n res.json(result.item);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'PROJECT_GONE') {\n notFound(res, getProjectIdParam(params(req).projectId));\n return;\n }\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to start todo' });\n }\n });\n\n // POST /:id/complete\n router.post('/:id/complete', async (req, res) => {\n try {\n const slug = getProjectIdParam(params(req).projectId);\n if (!(await projectExists(projectsDir, slug))) { notFound(res, slug); return; }\n const result = await projLock(slug, async () => {\n if (!(await projectExists(projectsDir, slug))) return 'gone' as const;\n await ensureProjectTodosDir(projectsDir, slug);\n const todosDir = projectTodosDir(projectsDir, slug);\n const checklist = await readChecklist(todosDir, slug);\n const item = checklist.items.find((i) => i.id === (params(req).id ?? \"\"));\n if (!item) return null;\n item.status = 'completed';\n item.session = null;\n const branchForLog = req.body.branch || item.branch || null;\n touchItem(item);\n checklist.workspace = slug;\n await writeChecklist(todosDir, checklist);\n const entry: LogEntry = {\n timestamp: new Date().toISOString(),\n itemIds: [item.id],\n items: item.description,\n session: req.body.session || null,\n branch: branchForLog,\n summary: req.body.summary || 'Completed.',\n blockers: null,\n status: null,\n };\n await appendLogEntry(todosDir, slug, entry);\n return { ...item };\n });\n if (result === 'gone') { notFound(res, slug); return; }\n if (!result) { res.status(404).json({ error: `Todo \"${(params(req).id ?? \"\")}\" not found` }); return; }\n broadcastUpdate(slug);\n res.json(result);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'PROJECT_GONE') {\n notFound(res, getProjectIdParam(params(req).projectId));\n return;\n }\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to complete todo' });\n }\n });\n\n // POST /:id/block\n router.post('/:id/block', async (req, res) => {\n try {\n const slug = getProjectIdParam(params(req).projectId);\n const reason = req.body.reason || null;\n if (!(await projectExists(projectsDir, slug))) { notFound(res, slug); return; }\n const result = await projLock(slug, async () => {\n if (!(await projectExists(projectsDir, slug))) return 'gone' as const;\n await ensureProjectTodosDir(projectsDir, slug);\n const todosDir = projectTodosDir(projectsDir, slug);\n const checklist = await readChecklist(todosDir, slug);\n const item = checklist.items.find((i) => i.id === (params(req).id ?? \"\"));\n if (!item) return null;\n item.status = 'blocked';\n item.session = null;\n touchItem(item);\n checklist.workspace = slug;\n await writeChecklist(todosDir, checklist);\n const entry: LogEntry = {\n timestamp: new Date().toISOString(),\n itemIds: [item.id],\n items: item.description,\n session: req.body.session || null,\n branch: null,\n summary: reason || 'Blocked.',\n blockers: reason,\n status: 'blocked',\n };\n await appendLogEntry(todosDir, slug, entry);\n return { ...item };\n });\n if (result === 'gone') { notFound(res, slug); return; }\n if (!result) { res.status(404).json({ error: `Todo \"${(params(req).id ?? \"\")}\" not found` }); return; }\n broadcastUpdate(slug);\n res.json(result);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'PROJECT_GONE') {\n notFound(res, getProjectIdParam(params(req).projectId));\n return;\n }\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to block todo' });\n }\n });\n\n // POST /:id/reopen\n router.post('/:id/reopen', async (req, res) => {\n try {\n const slug = getProjectIdParam(params(req).projectId);\n if (!(await projectExists(projectsDir, slug))) { notFound(res, slug); return; }\n const result = await projLock(slug, async () => {\n if (!(await projectExists(projectsDir, slug))) return 'gone' as const;\n await ensureProjectTodosDir(projectsDir, slug);\n const todosDir = projectTodosDir(projectsDir, slug);\n const checklist = await readChecklist(todosDir, slug);\n const item = checklist.items.find((i) => i.id === (params(req).id ?? \"\"));\n if (!item) return null;\n item.status = 'open';\n item.session = null;\n touchItem(item);\n checklist.workspace = slug;\n await writeChecklist(todosDir, checklist);\n return { ...item };\n });\n if (result === 'gone') { notFound(res, slug); return; }\n if (!result) { res.status(404).json({ error: `Todo \"${(params(req).id ?? \"\")}\" not found` }); return; }\n broadcastUpdate(slug);\n res.json(result);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'PROJECT_GONE') {\n notFound(res, getProjectIdParam(params(req).projectId));\n return;\n }\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to reopen todo' });\n }\n });\n\n // POST /:id/unblock\n router.post('/:id/unblock', async (req, res) => {\n try {\n const slug = getProjectIdParam(params(req).projectId);\n if (!(await projectExists(projectsDir, slug))) { notFound(res, slug); return; }\n const result = await projLock(slug, async () => {\n if (!(await projectExists(projectsDir, slug))) return 'gone' as const;\n await ensureProjectTodosDir(projectsDir, slug);\n const todosDir = projectTodosDir(projectsDir, slug);\n const checklist = await readChecklist(todosDir, slug);\n const item = checklist.items.find((i) => i.id === (params(req).id ?? \"\"));\n if (!item) return null;\n item.status = 'open';\n item.session = null;\n touchItem(item);\n checklist.workspace = slug;\n await writeChecklist(todosDir, checklist);\n return { ...item };\n });\n if (result === 'gone') { notFound(res, slug); return; }\n if (!result) { res.status(404).json({ error: `Todo \"${(params(req).id ?? \"\")}\" not found` }); return; }\n broadcastUpdate(slug);\n res.json(result);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'PROJECT_GONE') {\n notFound(res, getProjectIdParam(params(req).projectId));\n return;\n }\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to unblock todo' });\n }\n });\n\n // POST /promote — mirror of workspace router; promotes selected project todos\n // to a new or existing assignment.\n router.post('/promote', async (req, res) => {\n try {\n const slug = getProjectIdParam(params(req).projectId);\n if (!(await projectExists(projectsDir, slug))) { notFound(res, slug); return; }\n\n const { todoIds, mode, target, title, type, priority, keepSource } = req.body ?? {};\n if (!Array.isArray(todoIds) || todoIds.length === 0) {\n res.status(400).json({ error: 'todoIds (non-empty array of strings) is required' });\n return;\n }\n if (mode !== 'new-assignment' && mode !== 'to-assignment') {\n res.status(400).json({ error: 'mode must be \"new-assignment\" or \"to-assignment\"' });\n return;\n }\n\n const result = await projLock(slug, async () => {\n if (!(await projectExists(projectsDir, slug))) return { gone: true } as const;\n await ensureProjectTodosDir(projectsDir, slug);\n const todosDir = projectTodosDir(projectsDir, slug);\n const checklist = await readChecklist(todosDir, slug);\n\n const items: TodoItem[] = [];\n for (const id of todoIds) {\n const item = checklist.items.find((i) => i.id === id);\n if (!item) return { error: `Todo \"${id}\" not found` };\n if (item.status === 'completed') return { error: `Todo \"${id}\" is already completed` };\n items.push(item);\n }\n\n const scopeLabel = `project:${slug}`;\n\n if (mode === 'new-assignment') {\n if (items.length > 1 && !title) return { error: 'title is required when promoting multiple todos' };\n // Project endpoint default: target.project = current project slug\n const rawTarget = target && typeof target === 'object' && (target.project || target.oneOff)\n ? target\n : { project: slug };\n const parsed = parsePromoteTarget(rawTarget);\n if (!parsed.ok) return { error: parsed.error };\n const promoted = await promoteTodosToNewAssignment(\n [{ todosDir, workspace: slug, items, scopeLabel }],\n {\n title: title || items[0].description,\n target: parsed.target,\n type,\n priority,\n keepSource,\n },\n );\n return {\n assignmentRef: promoted.assignmentRef,\n assignmentDir: promoted.assignmentDir,\n promoted: promoted.promoted.map((p) => p.id),\n };\n }\n\n // to-assignment mode (unchanged)\n const { assignmentsDir: assignmentsDirFn } = await import('../utils/paths.js');\n const { appendTodosToAssignmentBody, touchAssignmentUpdated } = await import(\n '../utils/assignment-todos.js'\n );\n const { nowTimestamp } = await import('../utils/timestamp.js');\n\n let assignmentRef: string;\n let assignmentDir: string;\n\n const tg: string = target?.assignment || '';\n if (!tg) return { error: 'target.assignment is required for to-assignment mode' };\n if (tg.includes('/')) {\n const parts = tg.split('/');\n if (parts.length !== 2) return { error: `Invalid target.assignment \"${tg}\"` };\n assignmentDir = resolve(projectsDir, parts[0], 'assignments', parts[1]);\n assignmentRef = `${parts[0]}/${parts[1]}`;\n } else if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(tg)) {\n assignmentDir = resolve(assignmentsDirFn(), tg);\n assignmentRef = tg;\n } else {\n return { error: `Invalid target.assignment \"${tg}\"` };\n }\n const assignmentMdPath = resolve(assignmentDir, 'assignment.md');\n if (!(await fileExists(assignmentMdPath))) return { error: `Target assignment not found: ${assignmentMdPath}` };\n\n let content = await readFile(assignmentMdPath, 'utf-8');\n content = appendTodosToAssignmentBody(\n content,\n items.map((it) => ({\n description: it.description,\n trace: `promoted from t:${it.id} in ${scopeLabel}`,\n })),\n );\n content = touchAssignmentUpdated(content, nowTimestamp());\n await writeFileForce(assignmentMdPath, content);\n\n if (!keepSource) {\n for (const item of items) {\n item.status = 'completed';\n item.session = null;\n touchItem(item);\n }\n checklist.workspace = slug;\n await writeChecklist(todosDir, checklist);\n for (const item of items) {\n const entry: LogEntry = {\n timestamp: new Date().toISOString(),\n itemIds: [item.id],\n items: item.description,\n session: null,\n branch: item.branch || null,\n summary: `Promoted to assignment ${assignmentRef}`,\n blockers: null,\n status: null,\n };\n await appendLogEntry(todosDir, slug, entry);\n }\n }\n\n return { assignmentRef, assignmentDir, promoted: items.map((i) => i.id) };\n });\n\n if ('gone' in result) { notFound(res, slug); return; }\n if ('error' in result) { res.status(400).json({ error: result.error }); return; }\n broadcastUpdate(slug);\n res.json(result);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'PROJECT_GONE') {\n notFound(res, getProjectIdParam(params(req).projectId));\n return;\n }\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to promote todos' });\n }\n });\n\n // POST /:id/move — cross-scope move from a project to workspace/project/global\n router.post('/:id/move', async (req, res) => {\n try {\n const sourceSlug = getProjectIdParam(params(req).projectId);\n const id = params(req).id ?? '';\n if (!(await projectExists(projectsDir, sourceSlug))) { notFound(res, sourceSlug); return; }\n\n const to = req.body?.to;\n if (!to || typeof to !== 'object') {\n res.status(400).json({ error: 'body.to is required' });\n return;\n }\n const targetCount = [Boolean(to.workspace), Boolean(to.project), Boolean(to.global)].filter(Boolean).length;\n if (targetCount !== 1) {\n res.status(400).json({ error: 'body.to must specify exactly one of workspace, project, or global' });\n return;\n }\n if (to.project && !isValidSlug(to.project)) {\n res.status(400).json({ error: `Invalid target project slug: \"${to.project}\"` });\n return;\n }\n if (to.workspace && !WORKSPACE_REGEX.test(to.workspace)) {\n res.status(400).json({ error: `Invalid target workspace name: \"${to.workspace}\"` });\n return;\n }\n\n type Target =\n | { kind: 'workspace'; id: string; todosPath: string; lockKey: string }\n | { kind: 'project'; id: string; todosPath: string; lockKey: string };\n\n let target: Target;\n if (to.global) {\n if (!workspaceTodosDir) {\n res.status(500).json({ error: 'Server not configured with workspaceTodosDir; cannot move to global scope' });\n return;\n }\n target = { kind: 'workspace', id: '_global', todosPath: workspaceTodosDir, lockKey: 'ws:_global' };\n } else if (to.workspace) {\n if (!workspaceTodosDir) {\n res.status(500).json({ error: 'Server not configured with workspaceTodosDir; cannot move to workspace scope' });\n return;\n }\n target = { kind: 'workspace', id: to.workspace, todosPath: workspaceTodosDir, lockKey: `ws:${to.workspace}` };\n } else {\n const tslug = to.project as string;\n if (!(await projectExists(projectsDir, tslug))) {\n res.status(404).json({ error: `Target project \"${tslug}\" not found` });\n return;\n }\n target = {\n kind: 'project',\n id: tslug,\n todosPath: projectTodosDir(projectsDir, tslug),\n lockKey: `proj:${tslug}`,\n };\n }\n\n const sourceLockKey = `proj:${sourceSlug}`;\n if (sourceLockKey === target.lockKey) {\n res.status(400).json({ error: 'cannot move to the same scope' });\n return;\n }\n\n const result = await withTwoLocks(sourceLockKey, target.lockKey, async () => {\n if (!(await projectExists(projectsDir, sourceSlug))) return { status: 'gone' as const };\n if (target.kind === 'project' && !(await projectExists(projectsDir, target.id))) {\n return { status: 'targetGone' as const };\n }\n await ensureProjectTodosDir(projectsDir, sourceSlug);\n const sourceTodosDir = projectTodosDir(projectsDir, sourceSlug);\n const sourceChecklist = await readChecklist(sourceTodosDir, sourceSlug);\n const targetChecklist = await readChecklist(target.todosPath, target.id);\n\n const idx = sourceChecklist.items.findIndex((i) => i.id === id);\n if (idx === -1) return { status: 404 as const, error: `Todo \"${id}\" not found` };\n\n if (targetChecklist.items.some((i) => i.id === id)) {\n return { status: 409 as const, error: 'id already exists in target' };\n }\n\n const item = sourceChecklist.items[idx];\n if (item.planDir) {\n const newPlanDir = todoPlanDir(target.todosPath, target.id, id);\n if (await fileExists(newPlanDir)) {\n return { status: 409 as const, error: 'plan dir already exists in target' };\n }\n await mkdir(dirname(newPlanDir), { recursive: true });\n await rename(item.planDir, newPlanDir);\n item.planDir = newPlanDir;\n }\n\n sourceChecklist.items.splice(idx, 1);\n targetChecklist.items.push(item);\n\n sourceChecklist.workspace = sourceSlug;\n await writeChecklist(sourceTodosDir, sourceChecklist);\n await writeChecklist(target.todosPath, targetChecklist);\n\n const sourceLabel = `project:${sourceSlug}`;\n const targetLabel =\n target.kind === 'project' ? `project:${target.id}` : target.id === '_global' ? '_global' : `workspace:${target.id}`;\n const ts = new Date().toISOString();\n await appendLogEntry(sourceTodosDir, sourceSlug, {\n timestamp: ts,\n itemIds: [id],\n items: item.description,\n session: null,\n branch: item.branch || null,\n summary: `Moved to ${targetLabel}`,\n blockers: null,\n status: null,\n });\n await appendLogEntry(target.todosPath, target.id, {\n timestamp: ts,\n itemIds: [id],\n items: item.description,\n session: null,\n branch: item.branch || null,\n summary: `Moved from ${sourceLabel}`,\n blockers: null,\n status: null,\n });\n\n return { status: 200 as const, item };\n });\n\n if (result.status === 'gone') { notFound(res, sourceSlug); return; }\n if (result.status === 'targetGone') {\n res.status(404).json({ error: `Target project \"${(target as { id: string }).id}\" not found` });\n return;\n }\n if (result.status !== 200) {\n res.status(result.status).json({ error: result.error });\n return;\n }\n\n broadcastUpdate(sourceSlug);\n if (target.kind === 'project') broadcastUpdate(target.id);\n else broadcastWorkspace();\n\n res.json({ moved: id, to: target });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'PROJECT_GONE') {\n notFound(res, getProjectIdParam(params(req).projectId));\n return;\n }\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to move todo' });\n }\n });\n\n return router;\n}\n","import { Router } from 'express';\nimport { updateBackupConfig } from '../utils/config.js';\nimport {\n backupToGithub,\n restoreFromGithub,\n getBackupStatus,\n parseCategoriesStrict,\n validateRepoUrl,\n VALID_CATEGORIES,\n} from '../utils/github-backup.js';\n\nexport function createBackupRouter(): Router {\n const router = Router();\n\n router.get('/', async (_req, res) => {\n try {\n const status = await getBackupStatus();\n res.json(status);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : String(error) });\n }\n });\n\n router.put('/config', async (req, res) => {\n try {\n const body = req.body ?? {};\n const updates: { repo?: string; categories?: string } = {};\n\n if (body.repo !== undefined) {\n const trimmed = typeof body.repo === 'string' ? body.repo.trim() : body.repo;\n if (trimmed !== null && trimmed !== '' && !validateRepoUrl(trimmed)) {\n return res.status(400).json({\n error: `Invalid repo URL. Must start with https:// or git@.`,\n });\n }\n updates.repo = trimmed || null as unknown as string;\n }\n\n if (body.categories !== undefined) {\n let cats: string[];\n if (Array.isArray(body.categories)) {\n cats = body.categories.map((s: unknown) => String(s).trim()).filter(Boolean);\n } else if (typeof body.categories === 'string') {\n cats = body.categories.split(',').map((s: string) => s.trim()).filter(Boolean);\n } else {\n return res.status(400).json({ error: 'categories must be a string or array' });\n }\n if (cats.length === 0) {\n return res.status(400).json({\n error: `No categories provided. Valid: ${VALID_CATEGORIES.join(', ')}`,\n });\n }\n try {\n const valid = parseCategoriesStrict(cats);\n updates.categories = valid.join(', ');\n } catch (err) {\n return res.status(400).json({\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n if (Object.keys(updates).length === 0) {\n return res.status(400).json({ error: 'No fields to update' });\n }\n\n await updateBackupConfig(updates);\n const status = await getBackupStatus();\n res.json(status);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : String(error) });\n }\n });\n\n router.post('/push', async (_req, res) => {\n try {\n const result = await backupToGithub();\n res.json(result);\n } catch (error) {\n res.status(500).json({\n success: false,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n });\n\n router.post('/pull', async (_req, res) => {\n try {\n const result = await restoreFromGithub();\n res.json(result);\n } catch (error) {\n res.status(500).json({\n success: false,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n });\n\n return router;\n}\n","import { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { cp, mkdtemp, rm, readFile, writeFile, unlink, stat, open, rename } from 'node:fs/promises';\nimport { resolve, join } from 'node:path';\nimport { tmpdir } from 'node:os';\nimport { syntaurRoot, playbooksDir, todosDir, serversDir } from './paths.js';\nimport { ensureDir, fileExists } from './fs.js';\nimport { readConfig, updateBackupConfig, type BackupConfig } from './config.js';\n\nconst exec = promisify(execFile);\n\nexport const VALID_CATEGORIES = ['projects', 'playbooks', 'todos', 'servers', 'config'] as const;\nexport type BackupCategory = (typeof VALID_CATEGORIES)[number];\n\nconst LOCK_FILE_NAME = '.backup-lock';\n\nexport function parseCategories(csv: string): BackupCategory[] {\n return csv\n .split(',')\n .map((s) => s.trim())\n .filter((s): s is BackupCategory => (VALID_CATEGORIES as readonly string[]).includes(s));\n}\n\nexport function validateCategories(cats: string[]): BackupCategory[] {\n const valid: BackupCategory[] = [];\n for (const cat of cats) {\n if ((VALID_CATEGORIES as readonly string[]).includes(cat)) {\n valid.push(cat as BackupCategory);\n } else {\n console.warn(`Warning: unknown backup category \"${cat}\", skipping`);\n }\n }\n return valid;\n}\n\nexport function parseCategoriesStrict(cats: string[]): BackupCategory[] {\n const unknown: string[] = [];\n const valid: BackupCategory[] = [];\n for (const cat of cats) {\n if ((VALID_CATEGORIES as readonly string[]).includes(cat)) {\n valid.push(cat as BackupCategory);\n } else {\n unknown.push(cat);\n }\n }\n if (unknown.length > 0) {\n throw new Error(\n `Unknown categor${unknown.length === 1 ? 'y' : 'ies'}: ${unknown.map((c) => `\"${c}\"`).join(', ')}. Valid: ${VALID_CATEGORIES.join(', ')}`,\n );\n }\n return valid;\n}\n\nexport function validateRepoUrl(url: string): boolean {\n if (!url || typeof url !== 'string') return false;\n const trimmed = url.trim();\n return trimmed.startsWith('https://') || trimmed.startsWith('git@');\n}\n\nexport async function resolveCategoryPath(\n category: BackupCategory,\n): Promise<{ sourcePath: string; repoPath: string; isFile: boolean }> {\n switch (category) {\n case 'projects': {\n const config = await readConfig();\n return { sourcePath: config.defaultProjectDir, repoPath: 'projects', isFile: false };\n }\n case 'playbooks':\n return { sourcePath: playbooksDir(), repoPath: 'playbooks', isFile: false };\n case 'todos':\n return { sourcePath: todosDir(), repoPath: 'todos', isFile: false };\n case 'servers':\n return { sourcePath: serversDir(), repoPath: 'servers', isFile: false };\n case 'config':\n return { sourcePath: resolve(syntaurRoot(), 'config.md'), repoPath: 'config.md', isFile: true };\n }\n}\n\nasync function checkGitInstalled(): Promise<void> {\n try {\n await exec('git', ['--version']);\n } catch {\n throw new Error('git is not installed or not on PATH. Install git and try again.');\n }\n}\n\nasync function acquireLock(): Promise<string> {\n const lockPath = resolve(syntaurRoot(), LOCK_FILE_NAME);\n await ensureDir(syntaurRoot());\n try {\n const handle = await open(lockPath, 'wx');\n await handle.write(String(process.pid));\n await handle.close();\n return lockPath;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'EEXIST') {\n const pid = await readFile(lockPath, 'utf-8').catch(() => '');\n throw new Error(\n `Backup operation already in progress (lock file at ${lockPath}, pid ${pid.trim() || 'unknown'}). If stale, delete the file and retry.`,\n );\n }\n throw err;\n }\n}\n\nasync function releaseLock(lockPath: string): Promise<void> {\n try {\n await unlink(lockPath);\n } catch {\n // ignore\n }\n}\n\nasync function runGit(args: string[], cwd: string): Promise<{ stdout: string; stderr: string }> {\n return exec('git', args, { cwd });\n}\n\nasync function cloneOrInit(repoUrl: string, destDir: string): Promise<void> {\n try {\n await exec('git', ['clone', '--depth', '1', repoUrl, destDir]);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (message.includes('Repository not found') || message.includes('does not appear to be a git repository')) {\n throw new Error(`Repository not found or inaccessible: ${repoUrl}. Check URL and credentials.`);\n }\n if (message.includes('Authentication failed') || message.includes('could not read Username')) {\n throw new Error(`Authentication failed for ${repoUrl}. Check SSH keys or credentials.`);\n }\n throw new Error(`git clone failed: ${message}`);\n }\n}\n\nasync function copyRecursive(src: string, dest: string): Promise<void> {\n if (!(await fileExists(src))) return;\n const s = await stat(src);\n if (s.isDirectory()) {\n await ensureDir(dest);\n await cp(src, dest, { recursive: true, force: true });\n } else {\n await ensureDir(resolve(dest, '..'));\n await cp(src, dest, { force: true });\n }\n}\n\nexport interface BackupResult {\n success: boolean;\n timestamp: string;\n message: string;\n committed: boolean;\n}\n\nfunction resolveCategoriesStrict(csv: string): BackupCategory[] {\n const parts = csv.split(',').map((s) => s.trim()).filter(Boolean);\n return parseCategoriesStrict(parts);\n}\n\n/**\n * Read config.md and return a version with lastBackup/lastRestore set to null.\n * This is the copy that goes into the backup repo, so those timestamps — which\n * mutate on every local operation — never cause a self-diff on subsequent backups.\n */\nexport async function readSanitizedConfig(configPath: string): Promise<string> {\n const content = await readFile(configPath, 'utf-8');\n return content\n .replace(/^(\\s*lastBackup:\\s*).*$/m, '$1null')\n .replace(/^(\\s*lastRestore:\\s*).*$/m, '$1null');\n}\n\nexport async function backupToGithub(overrides?: {\n repo?: string;\n categories?: BackupCategory[];\n}): Promise<BackupResult> {\n await checkGitInstalled();\n const config = await readConfig();\n const rawRepo = overrides?.repo ?? config.backup?.repo ?? null;\n if (!rawRepo) {\n throw new Error('No backup repo configured. Set it via `syntaur backup config --repo <url>` or the dashboard.');\n }\n const repo = rawRepo.trim();\n if (!validateRepoUrl(repo)) {\n throw new Error(`Invalid repo URL: \"${rawRepo}\". Must start with https:// or git@.`);\n }\n\n const categoriesCsv = config.backup?.categories ?? 'projects, playbooks, todos, servers, config';\n const categories = overrides?.categories ?? resolveCategoriesStrict(categoriesCsv);\n if (categories.length === 0) {\n throw new Error('No valid backup categories selected.');\n }\n\n const lockPath = await acquireLock();\n let tmpDir: string | null = null;\n const timestamp = new Date().toISOString();\n\n try {\n tmpDir = await mkdtemp(join(tmpdir(), 'syntaur-backup-'));\n await cloneOrInit(repo, tmpDir);\n\n // Copy each selected category into the repo clone.\n // Always clear the destination first so local deletions propagate to the repo.\n for (const category of categories) {\n const { sourcePath, repoPath, isFile } = await resolveCategoryPath(category);\n const destPath = join(tmpDir, repoPath);\n\n if (isFile) {\n await rm(destPath, { force: true });\n } else {\n await rm(destPath, { recursive: true, force: true });\n }\n\n if (!(await fileExists(sourcePath))) {\n console.warn(`Category \"${category}\": no local data at ${sourcePath}; backup will reflect deletion.`);\n continue;\n }\n\n if (category === 'config') {\n // Sanitize config.md before writing to the repo: strip lastBackup/lastRestore\n // timestamps so they don't cause a self-diff on every backup.\n const sanitized = await readSanitizedConfig(sourcePath);\n await ensureDir(resolve(destPath, '..'));\n await writeFile(destPath, sanitized, 'utf-8');\n } else {\n await copyRecursive(sourcePath, destPath);\n }\n }\n\n // Stage and check for changes\n await runGit(['add', '-A'], tmpDir);\n const { stdout: status } = await runGit(['status', '--porcelain'], tmpDir);\n if (!status.trim()) {\n // No-op but successful: persist timestamp so UI reflects the completed check\n await updateBackupConfig({ lastBackup: timestamp }).catch(() => {});\n return {\n success: true,\n timestamp,\n message: 'No changes to back up.',\n committed: false,\n };\n }\n\n // Configure committer if unset (best-effort; user may have global config)\n try {\n await runGit(['config', 'user.email', 'syntaur@local'], tmpDir);\n await runGit(['config', 'user.name', 'Syntaur Backup'], tmpDir);\n } catch {\n // ignore\n }\n\n await runGit(['commit', '-m', `Syntaur backup ${timestamp}`], tmpDir);\n\n try {\n await runGit(['push'], tmpDir);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (message.includes('non-fast-forward') || message.includes('rejected')) {\n throw new Error('Push rejected (non-fast-forward). Pull and resolve manually, or delete remote contents.');\n }\n if (message.includes('Authentication') || message.includes('could not read Username')) {\n throw new Error('Push authentication failed. Check SSH keys or credentials.');\n }\n throw new Error(`git push failed: ${message}`);\n }\n\n // Push succeeded: persist timestamp\n await updateBackupConfig({ lastBackup: timestamp }).catch(() => {});\n\n return {\n success: true,\n timestamp,\n message: `Backed up ${categories.length} categor${categories.length === 1 ? 'y' : 'ies'} to ${repo}.`,\n committed: true,\n };\n } finally {\n if (tmpDir) {\n await rm(tmpDir, { recursive: true, force: true }).catch(() => {});\n }\n await releaseLock(lockPath);\n }\n}\n\nexport async function safeRestoreCategory(\n localPath: string,\n repoSrcPath: string,\n isFile: boolean,\n): Promise<void> {\n if (isFile) {\n // Single file: cp handles atomic rename internally. No staging needed.\n await ensureDir(resolve(localPath, '..'));\n await cp(repoSrcPath, localPath, { force: true });\n return;\n }\n\n // Directory: stage, then swap.\n const stagingPath = `${localPath}.syntaur-restore-staging`;\n const backupPath = `${localPath}.syntaur-restore-backup`;\n\n // Stale staging from a crashed run is always safe to discard.\n await rm(stagingPath, { recursive: true, force: true });\n\n // A pre-existing backup dir means a prior run crashed mid-swap and it may contain\n // the only copy of the user's original data. Do NOT delete it blindly.\n const backupExistsBefore = await fileExists(backupPath);\n const localExistsBefore = await fileExists(localPath);\n if (backupExistsBefore) {\n if (!localExistsBefore) {\n // Prior crash left the backup as the only copy. Restore it first.\n await rename(backupPath, localPath);\n } else {\n // Both exist — we can't tell which is authoritative. Bail out.\n throw new Error(\n `Cannot restore \"${localPath}\": a stale crash-recovery backup exists at ${backupPath} while the current path also exists. ` +\n `Inspect both and remove the one you don't need, then retry.`,\n );\n }\n }\n\n let localMovedAside = false;\n try {\n // Copy repo contents into staging. If this fails, local is untouched.\n await cp(repoSrcPath, stagingPath, { recursive: true, force: true });\n\n // Move current local aside (if it exists).\n const localExists = await fileExists(localPath);\n if (localExists) {\n await rename(localPath, backupPath);\n localMovedAside = true;\n }\n\n // Swap staging into place.\n await rename(stagingPath, localPath);\n\n // Success: remove the old data.\n await rm(backupPath, { recursive: true, force: true }).catch(() => {});\n } catch (err) {\n // Roll back: restore original if we moved it aside.\n if (localMovedAside && (await fileExists(backupPath))) {\n await rename(backupPath, localPath).catch(() => {});\n }\n // Always clean up staging (may or may not exist depending on where we failed).\n await rm(stagingPath, { recursive: true, force: true }).catch(() => {});\n throw err;\n }\n}\n\nexport async function restoreFromGithub(overrides?: {\n repo?: string;\n categories?: BackupCategory[];\n}): Promise<BackupResult> {\n await checkGitInstalled();\n const config = await readConfig();\n const rawRepo = overrides?.repo ?? config.backup?.repo ?? null;\n if (!rawRepo) {\n throw new Error('No backup repo configured.');\n }\n const repo = rawRepo.trim();\n if (!validateRepoUrl(repo)) {\n throw new Error(`Invalid repo URL: \"${rawRepo}\".`);\n }\n\n const categoriesCsv = config.backup?.categories ?? 'projects, playbooks, todos, servers, config';\n const categories = overrides?.categories ?? resolveCategoriesStrict(categoriesCsv);\n if (categories.length === 0) {\n throw new Error('No valid restore categories selected.');\n }\n\n const lockPath = await acquireLock();\n let tmpDir: string | null = null;\n const restored: string[] = [];\n const failed: string[] = [];\n const timestamp = new Date().toISOString();\n\n try {\n // Persist timestamp before work so UI reflects the attempt even on partial failure.\n // Inside try so lock is released even if config write fails.\n await updateBackupConfig({ lastRestore: timestamp });\n\n tmpDir = await mkdtemp(join(tmpdir(), 'syntaur-restore-'));\n await cloneOrInit(repo, tmpDir);\n\n for (const category of categories) {\n // Never overwrite config.md on restore — would clobber backup settings\n if (category === 'config') {\n console.warn('Skipping \"config\" on restore (would overwrite local backup settings).');\n continue;\n }\n try {\n const { sourcePath: localPath, repoPath, isFile } = await resolveCategoryPath(category);\n const repoSrcPath = join(tmpDir, repoPath);\n if (!(await fileExists(repoSrcPath))) {\n console.warn(`Category \"${category}\" not found in backup repo, skipping.`);\n continue;\n }\n await safeRestoreCategory(localPath, repoSrcPath, isFile);\n restored.push(category);\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n console.error(`Failed to restore \"${category}\": ${msg}`);\n failed.push(category);\n }\n }\n\n const success = failed.length === 0;\n return {\n success,\n timestamp,\n message: success\n ? `Restored ${restored.length} categor${restored.length === 1 ? 'y' : 'ies'} from ${repo}.`\n : `Partial restore: ${restored.length} succeeded, ${failed.length} failed (${failed.join(', ')}).`,\n committed: false,\n };\n } finally {\n if (tmpDir) {\n await rm(tmpDir, { recursive: true, force: true }).catch(() => {});\n }\n await releaseLock(lockPath);\n }\n}\n\nexport async function getBackupStatus(): Promise<{\n repo: string | null;\n categories: string;\n lastBackup: string | null;\n lastRestore: string | null;\n locked: boolean;\n}> {\n const config = await readConfig();\n const lockPath = resolve(syntaurRoot(), LOCK_FILE_NAME);\n const locked = await fileExists(lockPath);\n return {\n repo: config.backup?.repo ?? null,\n categories: config.backup?.categories ?? 'projects, playbooks, todos, servers, config',\n lastBackup: config.backup?.lastBackup ?? null,\n lastRestore: config.backup?.lastRestore ?? null,\n locked,\n };\n}\n","import {\n execQuiet,\n checkTmuxAvailable,\n sessionAlive,\n listTmuxPanes,\n getLsofOutput,\n loadWorkspaceRecords,\n autoLinkPane,\n getGitInfo,\n clearScanCache,\n} from './scanner.js';\nimport {\n readSessionFile,\n listSessionFiles,\n registerAutoSession,\n removeSession,\n sanitizeSessionName,\n} from './servers.js';\nimport type { SessionFileData } from './types.js';\n\n// --- Shared lsof helpers ---\n\nexport function parsePortsForPid(lsofOutput: string, targetPid: number): number[] {\n const ports: number[] = [];\n for (const line of lsofOutput.split('\\n')) {\n const parts = line.trim().split(/\\s+/);\n if (parts.length < 9) continue;\n const pid = parseInt(parts[1], 10);\n if (pid !== targetPid) continue;\n const tcpAddr = parts.find((p) => p.includes(':') && /:\\d+$/.test(p));\n if (tcpAddr) {\n const port = parseInt(tcpAddr.split(':').pop()!, 10);\n if (!isNaN(port) && !ports.includes(port)) ports.push(port);\n }\n }\n return ports;\n}\n\nexport function parseLsofForListeningProcesses(lsofOutput: string): ListeningProcess[] {\n const seen = new Map<number, ListeningProcess>();\n for (const line of lsofOutput.split('\\n')) {\n const parts = line.trim().split(/\\s+/);\n if (parts.length < 9) continue;\n const command = parts[0];\n const pid = parseInt(parts[1], 10);\n if (isNaN(pid)) continue;\n const tcpAddr = parts.find((p) => p.includes(':') && /:\\d+$/.test(p));\n if (!tcpAddr) continue;\n const port = parseInt(tcpAddr.split(':').pop()!, 10);\n if (isNaN(port)) continue;\n\n if (!seen.has(pid)) {\n seen.set(pid, { pid, port, command });\n }\n }\n return Array.from(seen.values());\n}\n\n// --- Singleton lifecycle ---\n\nlet timer: ReturnType<typeof setInterval> | null = null;\nlet activeReconcile: Promise<void> | null = null;\n\nexport interface AutodiscoveryOptions {\n serversDir: string;\n projectsDir: string;\n assignmentsDir?: string;\n intervalMs?: number;\n excludePids?: Set<number>;\n}\n\nlet savedOptions: AutodiscoveryOptions | null = null;\n\nexport function startAutodiscovery(opts: AutodiscoveryOptions): void {\n if (timer) return;\n savedOptions = opts;\n const interval = opts.intervalMs ?? 45_000;\n // Run once immediately, then on interval\n runReconcile();\n timer = setInterval(() => {\n runReconcile();\n }, interval);\n}\n\nexport async function stopAutodiscovery(): Promise<void> {\n if (timer) {\n clearInterval(timer);\n timer = null;\n }\n // Await in-flight reconcile to prevent overlap\n if (activeReconcile) {\n await activeReconcile;\n activeReconcile = null;\n }\n savedOptions = null;\n}\n\nfunction runReconcile(): void {\n if (activeReconcile || !savedOptions) return;\n const opts = savedOptions;\n activeReconcile = reconcile(opts.serversDir, opts.projectsDir, opts.excludePids, opts.assignmentsDir)\n .catch((err) => {\n console.error('[autodiscovery] reconcile failed:', err);\n })\n .finally(() => {\n activeReconcile = null;\n });\n}\n\n// --- Tmux discovery ---\n\nexport async function listAllTmuxSessions(): Promise<string[]> {\n const output = await execQuiet('tmux', ['list-sessions', '-F', '#{session_name}']);\n if (!output) return [];\n return output.split('\\n').filter((line) => line.length > 0);\n}\n\nasync function discoverTmuxSessions(\n serversDir: string,\n projectsDir: string,\n existingNames: Set<string>,\n assignmentsDir?: string,\n): Promise<boolean> {\n const tmuxAvailable = await checkTmuxAvailable();\n if (!tmuxAvailable) return false;\n\n const workspaceRecords = await loadWorkspaceRecords(projectsDir, assignmentsDir);\n if (workspaceRecords.length === 0) return false;\n\n const sessions = await listAllTmuxSessions();\n let changed = false;\n\n for (const sessionName of sessions) {\n const sanitized = sanitizeSessionName(sessionName);\n if (existingNames.has(sanitized)) {\n // Already tracked (manual or auto) — skip\n continue;\n }\n\n const panes = await listTmuxPanes(sessionName);\n if (panes.length === 0) continue;\n\n // Check if any pane matches a workspace\n let matched = false;\n const cwdGitCache = new Map<string, { branch: string | null; worktree: boolean }>();\n\n for (const pane of panes) {\n if (!cwdGitCache.has(pane.cwd)) {\n cwdGitCache.set(pane.cwd, await getGitInfo(pane.cwd));\n }\n const gitInfo = cwdGitCache.get(pane.cwd)!;\n const link = await autoLinkPane(pane.cwd, gitInfo.branch, workspaceRecords);\n if (link) {\n matched = true;\n break;\n }\n }\n\n if (matched) {\n await registerAutoSession(serversDir, sessionName, { kind: 'tmux' });\n changed = true;\n }\n }\n\n return changed;\n}\n\n// --- Non-tmux process discovery ---\n\ninterface ListeningProcess {\n pid: number;\n port: number;\n command: string;\n}\n\nasync function getProcessCwd(pid: number): Promise<string | null> {\n // macOS: use lsof to get cwd\n const output = await execQuiet('lsof', ['-a', '-d', 'cwd', '-p', String(pid), '-Fn']);\n if (!output) return null;\n // Output format: lines starting with 'n' contain the path\n for (const line of output.split('\\n')) {\n if (line.startsWith('n') && line.length > 1) {\n return line.slice(1);\n }\n }\n return null;\n}\n\nasync function discoverProcesses(\n serversDir: string,\n projectsDir: string,\n existingFiles: Map<string, SessionFileData>,\n excludePids?: Set<number>,\n assignmentsDir?: string,\n): Promise<boolean> {\n const workspaceRecords = await loadWorkspaceRecords(projectsDir, assignmentsDir);\n if (workspaceRecords.length === 0) return false;\n\n const lsofOutput = await getLsofOutput();\n if (!lsofOutput) return false;\n\n const processes = parseLsofForListeningProcesses(lsofOutput);\n let changed = false;\n\n // Track which PIDs are already tracked by existing process-kind entries\n const trackedPids = new Set<number>();\n for (const data of existingFiles.values()) {\n if (data.kind === 'process' && data.pid) {\n trackedPids.add(data.pid);\n }\n }\n\n for (const proc of processes) {\n if (trackedPids.has(proc.pid)) continue;\n if (excludePids?.has(proc.pid)) continue;\n\n const cwd = await getProcessCwd(proc.pid);\n if (!cwd) continue;\n\n const gitInfo = await getGitInfo(cwd);\n const link = await autoLinkPane(cwd, gitInfo.branch, workspaceRecords);\n if (!link) continue;\n\n // Build a session name from the command and port\n const sessionName = `proc-${proc.command}-${proc.port}`;\n const sanitized = sanitizeSessionName(sessionName);\n\n // Skip if already registered under this name\n if (existingFiles.has(sanitized)) continue;\n\n const ports = parsePortsForPid(lsofOutput, proc.pid);\n await registerAutoSession(serversDir, sessionName, {\n kind: 'process',\n pid: proc.pid,\n ports: ports.length > 0 ? ports : [proc.port],\n cwd,\n });\n changed = true;\n }\n\n return changed;\n}\n\n// --- Reconciliation ---\n\nasync function cleanupDeadAutoSessions(\n serversDir: string,\n existingFiles: Map<string, SessionFileData>,\n): Promise<{ changed: boolean; removedNames: Set<string> }> {\n let changed = false;\n const removedNames = new Set<string>();\n\n // Only check tmux liveness if tmux is available\n const tmuxAvailable = await checkTmuxAvailable();\n\n for (const [name, data] of existingFiles) {\n if (!data.auto) continue;\n\n let alive = true; // Default to alive for unknown kinds\n if (data.kind === 'tmux') {\n if (!tmuxAvailable) continue; // Don't delete tmux sessions when tmux is unavailable\n alive = await sessionAlive(data.session);\n } else if (data.kind === 'process' && data.pid) {\n alive = await isProcessAlive(data.pid);\n } else {\n // Unknown kind with auto: true — leave it alone\n continue;\n }\n\n if (!alive) {\n await removeSession(serversDir, name);\n removedNames.add(name);\n changed = true;\n }\n }\n\n return { changed, removedNames };\n}\n\nexport async function isProcessAlive(pid: number): Promise<boolean> {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function reconcile(serversDir: string, projectsDir: string, excludePids?: Set<number>, assignmentsDir?: string): Promise<void> {\n // Load all existing session files\n const names = await listSessionFiles(serversDir);\n const existingFiles = new Map<string, SessionFileData>();\n for (const name of names) {\n const data = await readSessionFile(serversDir, name);\n if (data) existingFiles.set(name, data);\n }\n\n // Clean up dead auto sessions FIRST so discovery can re-register restarted processes\n const { changed: cleanupChanged, removedNames } = await cleanupDeadAutoSessions(serversDir, existingFiles);\n\n // Remove cleaned-up entries from the maps so discovery sees them as available\n for (const name of removedNames) {\n existingFiles.delete(name);\n }\n const existingNames = new Set(existingFiles.keys());\n\n // Discover new sessions\n const tmuxChanged = await discoverTmuxSessions(serversDir, projectsDir, existingNames, assignmentsDir);\n const processChanged = await discoverProcesses(serversDir, projectsDir, existingFiles, excludePids, assignmentsDir);\n\n // Invalidate scan cache if anything changed\n if (tmuxChanged || processChanged || cleanupChanged) {\n clearScanCache();\n }\n}\n\n// --- Exports for testing ---\nexport { reconcile, getProcessCwd };\n"],"mappings":"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","names":["todosDir","getField","extractFrontmatter","parseSimpleValue","parseExternalIds","resolve","parseStatus","extractFrontmatter","todosDir","init_parser","resolve","todosDir","init_parser","resolve","readFile","params","readdir","readFile","rename","writeFile","resolve","readFile","resolve","init_config","resolve","readdir","readFile","playbooksDir","init_config","resolve","readdir","readFile","assignmentsDir","extractFrontmatter","resolve","readdir","readFile","readFile","resolve","db","rows","assignmentsDir","readdir","readFile","unlink","resolve","nowTimestamp","extractFrontmatter","resolve","readdir","readFile","assignmentsDir","extractFrontmatter","serversDir","readdir","readFile","writeFile","resolve","dirname","escapeRegExp","assignmentsDir","serversDir","scanAllSessions","TERMINAL_STATUSES","playbooksDir","init_config","setTopLevelField","resolve","writeFile","unlink","basename","dirname","assignmentsDir","serversDir","playbooksDir","todosDir","handleStandaloneChange","handleServerChange","handlePlaybookChange","handleTodoChange","handleDbChange","init_config","readFile","rename","unlink","resolve","resolve","readFile","rename","unlink","resolve","basename","readFile","params","params","params","params","params","params","params","params","params","params","extractFrontmatter","formatYamlValue","escapeRegExp","appendLogEntry","readFile","assignmentsDir","todosDir","basename","params","resolve","id","assignmentDir","timestamp","detail","Router","serversDir","assignmentsDir","Router","resolve","init_config","execFileSync","assignmentsDir","Router","resolve","init_config","Router","Router","Database","randomUUID","resolve","db","SCHEMA_SQL","db","resolve","Database","SCHEMA_SQL","Router","Router","resolve","readFile","playbooksDir","Router","resolve","readFile","init_parser","Router","readdir","dirname","rename","mkdir","init_parser","resolve","init_config","resolve","touchItem","touchItem","todosDir","Router","readdir","archivePath","resolve","readFile","writeFileForce","resolvePath","readConfig","fileExists","appendTodosToAssignmentBody","touchAssignmentUpdated","nowTimestamp","mkdir","dirname","rename","init_parser","Router","mkdir","readFile","rename","resolve","dirname","WORKSPACE_REGEX","touchItem","resolve","todosDir","mkdir","Router","readFile","appendTodosToAssignmentBody","touchAssignmentUpdated","nowTimestamp","dirname","rename","init_config","Router","init_config","execFile","promisify","rm","readFile","writeFile","unlink","open","rename","resolve","join","exec","resolve","exec","open","readFile","unlink","join","rm","writeFile","rename","Router","serversDir","assignmentsDir","assignmentsDir","serversDir","playbooksDir","todosDir","resolve","writeFile","unlink"]}
1
+ {"version":3,"sources":["../../src/utils/paths.ts","../../src/lifecycle/types.ts","../../src/lifecycle/state-machine.ts","../../src/lifecycle/frontmatter.ts","../../src/utils/fs.ts","../../src/utils/timestamp.ts","../../src/dashboard/parser.ts","../../src/todos/parser.ts","../../src/lifecycle/linked-todos.ts","../../src/lifecycle/transitions.ts","../../src/lifecycle/index.ts","../../src/templates/config.ts","../../src/utils/fs-migration.ts","../../src/utils/hotkeysCatalog.ts","../../src/utils/agents-schema.ts","../../src/utils/terminal-schema.ts","../../src/utils/config.ts","../../src/utils/slug.ts","../../src/utils/playbooks.ts","../../src/utils/assignment-resolver.ts","../../src/dashboard/help.ts","../../src/dashboard/session-db.ts","../../src/dashboard/agent-sessions.ts","../../src/dashboard/overviewCopy.ts","../../src/dashboard/servers.ts","../../src/dashboard/scanner.ts","../../src/dashboard/api.ts","../../src/utils/assignment-todos.ts","../../src/dashboard/server.ts","../../src/dashboard/session-liveness.ts","../../src/dashboard/watcher.ts","../../src/utils/view-prefs-schema.ts","../../src/utils/view-prefs.ts","../../src/dashboard/todos-locks.ts","../../src/dashboard/api-write.ts","../../src/utils/uuid.ts","../../src/utils/git-worktree.ts","../../src/utils/worktree-defaults.ts","../../src/dashboard/repository-candidates.ts","../../src/dashboard/acceptance-criteria.ts","../../src/templates/index.ts","../../src/templates/manifest.ts","../../src/utils/yaml.ts","../../src/templates/project.ts","../../src/templates/assignment.ts","../../src/templates/scratchpad.ts","../../src/templates/handoff.ts","../../src/templates/progress.ts","../../src/templates/comments.ts","../../src/templates/decision-record.ts","../../src/templates/index-stubs.ts","../../src/templates/playbook.ts","../../src/dashboard/api-servers.ts","../../src/dashboard/api-agent-sessions.ts","../../src/utils/transcript.ts","../../src/utils/process-info.ts","../../src/dashboard/api-agents.ts","../../src/dashboard/api-launch-preflight.ts","../../src/utils/terminal-probe.ts","../../src/dashboard/api-terminal-config.ts","../../src/dashboard/api-leases.ts","../../src/db/leases-db.ts","../../src/dashboard/api-playbooks.ts","../../src/dashboard/api-todos.ts","../../src/utils/promote-todos.ts","../../src/commands/create-assignment.ts","../../src/dashboard/api-project-todos.ts","../../src/dashboard/api-backup.ts","../../src/utils/github-backup.ts","../../src/dashboard/autodiscovery.ts"],"sourcesContent":["import { homedir } from 'node:os';\nimport { resolve } from 'node:path';\n\nexport function expandHome(p: string): string {\n if (p.startsWith('~/') || p === '~') {\n return resolve(homedir(), p.slice(2));\n }\n return p;\n}\n\nexport function syntaurRoot(): string {\n const override = process.env.SYNTAUR_HOME;\n if (override && override.length > 0) {\n return resolve(expandHome(override));\n }\n return resolve(homedir(), '.syntaur');\n}\n\nexport function defaultProjectDir(): string {\n return resolve(syntaurRoot(), 'projects');\n}\n\nexport function assignmentsDir(): string {\n return resolve(syntaurRoot(), 'assignments');\n}\n\nexport function serversDir(): string {\n return resolve(syntaurRoot(), 'servers');\n}\n\nexport function playbooksDir(): string {\n return resolve(syntaurRoot(), 'playbooks');\n}\n\nexport function todosDir(): string {\n return resolve(syntaurRoot(), 'todos');\n}\n\nexport function viewPrefsFile(): string {\n return resolve(syntaurRoot(), 'view-prefs.json');\n}\n\nexport function projectTodosDir(projectsDir: string, projectSlug: string): string {\n return resolve(projectsDir, projectSlug, 'todos');\n}\n\nexport function todoPlanDir(todosDir: string, workspaceOrProject: string, todoId: string): string {\n return resolve(todosDir, 'plans', workspaceOrProject, todoId);\n}\n\nexport function proofDir(assignmentDir: string): string {\n return resolve(assignmentDir, 'proof');\n}\n","export type AssignmentStatus = string;\n\nexport type TransitionCommand = string;\n\nexport const DEFAULT_STATUSES = [\n 'draft',\n 'pending',\n 'ready_for_planning',\n 'ready_to_implement',\n 'in_progress',\n 'blocked',\n 'review',\n 'completed',\n 'failed',\n] as const;\n\nexport const DEFAULT_COMMANDS = [\n 'start',\n 'shape',\n 'plan-ready',\n 'implement',\n 'complete',\n 'block',\n 'unblock',\n 'review',\n 'fail',\n 'reopen',\n 'assign',\n] as const;\n\nexport const DEFAULT_TERMINAL_STATUSES: ReadonlySet<string> = new Set([\n 'completed',\n 'failed',\n]);\n\nexport const TERMINAL_STATUSES: ReadonlySet<string> = DEFAULT_TERMINAL_STATUSES;\n\nexport interface ExternalId {\n system: string;\n id: string;\n url: string | null;\n}\n\nexport interface Workspace {\n repository: string | null;\n worktreePath: string | null;\n branch: string | null;\n parentBranch: string | null;\n}\n\nexport interface AssignmentFrontmatter {\n id: string;\n slug: string;\n title: string;\n project: string | null;\n type: string | null;\n status: AssignmentStatus;\n priority: 'low' | 'medium' | 'high' | 'critical';\n created: string;\n updated: string;\n assignee: string | null;\n externalIds: ExternalId[];\n dependsOn: string[];\n links: string[];\n blockedReason: string | null;\n workspace: Workspace;\n tags: string[];\n}\n\nexport interface TransitionResult {\n success: boolean;\n message: string;\n fromStatus: AssignmentStatus;\n toStatus?: AssignmentStatus;\n warnings?: string[];\n}\n","import type { AssignmentStatus, TransitionCommand } from './types.js';\nimport { TERMINAL_STATUSES } from './types.js';\n\n/**\n * Maps a command to its target status. Commands always produce the same\n * target regardless of the current status — workflow enforcement is\n * handled via agent prompting, not code guards.\n */\nexport const DEFAULT_COMMAND_TARGETS = new Map<string, string>([\n ['start', 'in_progress'],\n ['shape', 'ready_for_planning'],\n ['plan-ready', 'ready_to_implement'],\n ['implement', 'in_progress'],\n ['block', 'blocked'],\n ['unblock', 'in_progress'],\n ['review', 'review'],\n ['complete', 'completed'],\n ['fail', 'failed'],\n ['reopen', 'in_progress'],\n]);\n\n/** @deprecated Transition guards removed — kept for API compat, always returns true */\nexport const DEFAULT_TRANSITION_TABLE = new Map<string, string>([\n ['pending:start', 'in_progress'],\n ['pending:block', 'blocked'],\n ['draft:shape', 'ready_for_planning'],\n ['draft:start', 'in_progress'],\n ['ready_for_planning:plan-ready', 'ready_to_implement'],\n ['ready_for_planning:start', 'in_progress'],\n ['ready_to_implement:implement', 'in_progress'],\n ['in_progress:block', 'blocked'],\n ['in_progress:review', 'review'],\n ['in_progress:complete', 'completed'],\n ['in_progress:fail', 'failed'],\n ['blocked:unblock', 'in_progress'],\n ['review:start', 'in_progress'],\n ['review:complete', 'completed'],\n ['review:fail', 'failed'],\n ['completed:reopen', 'in_progress'],\n ['failed:reopen', 'in_progress'],\n]);\n\nexport function buildTransitionTable(\n transitions: Array<{ from: string; command: string; to: string }>,\n): Map<string, string> {\n const table = new Map<string, string>();\n for (const t of transitions) {\n table.set(`${t.from}:${t.command}`, t.to);\n }\n return table;\n}\n\nexport function buildCommandTargets(\n transitions: Array<{ from: string; command: string; to: string }>,\n): Map<string, string> {\n const targets = new Map<string, string>();\n for (const t of transitions) {\n targets.set(t.command, t.to);\n }\n return targets;\n}\n\nexport function getTargetStatus(\n _from: AssignmentStatus,\n command: TransitionCommand,\n table?: Map<string, string>,\n): AssignmentStatus | null {\n // Try command-only lookup first, fall back to from:command for backwards compat\n if (!table || table === DEFAULT_TRANSITION_TABLE) {\n return DEFAULT_COMMAND_TARGETS.get(command) ?? null;\n }\n // Custom table: try command-only key first, then from:command\n return table.get(command) ?? table.get(`${_from}:${command}`) ?? null;\n}\n\n/** @deprecated Guards removed — always returns true for known commands */\nexport function canTransition(\n _from: AssignmentStatus,\n command: TransitionCommand,\n table?: Map<string, string>,\n): boolean {\n return getTargetStatus(_from, command, table) !== null;\n}\n\nexport function isTerminalStatus(\n status: AssignmentStatus,\n terminalSet?: ReadonlySet<string>,\n): boolean {\n return (terminalSet ?? TERMINAL_STATUSES).has(status);\n}\n","import type { AssignmentFrontmatter, ExternalId, Workspace } from './types.js';\n\nfunction extractFrontmatter(fileContent: string): [string, string] {\n const match = fileContent.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) {\n throw new Error('No frontmatter found in file. Expected --- delimiters.');\n }\n const frontmatterBlock = match[1];\n const body = fileContent.slice(match[0].length);\n return [frontmatterBlock, body];\n}\n\nfunction parseSimpleValue(raw: string): string | null {\n const trimmed = raw.trim();\n if (trimmed === 'null' || trimmed === '~' || trimmed === '') return null;\n if (\n (trimmed.startsWith('\"') && trimmed.endsWith('\"')) ||\n (trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\"))\n ) {\n return trimmed.slice(1, -1);\n }\n return trimmed;\n}\n\nfunction parseDependsOn(frontmatter: string): string[] {\n const inlineMatch = frontmatter.match(/^dependsOn:\\s*\\[\\s*\\]/m);\n if (inlineMatch) return [];\n\n const results: string[] = [];\n const blockMatch = frontmatter.match(/^dependsOn:\\s*\\n((?:\\s+-\\s+.*\\n?)*)/m);\n if (blockMatch) {\n const items = blockMatch[1].matchAll(/^\\s+-\\s+(.+)$/gm);\n for (const item of items) {\n results.push(item[1].trim());\n }\n }\n return results;\n}\n\nfunction parseLinks(frontmatter: string): string[] {\n const inlineMatch = frontmatter.match(/^links:\\s*\\[\\s*\\]/m);\n if (inlineMatch) return [];\n\n const results: string[] = [];\n const blockMatch = frontmatter.match(/^links:\\s*\\n((?:\\s+-\\s+.*\\n?)*)/m);\n if (blockMatch) {\n const items = blockMatch[1].matchAll(/^\\s+-\\s+(.+)$/gm);\n for (const item of items) {\n results.push(item[1].trim());\n }\n }\n return results;\n}\n\nfunction parseExternalIds(frontmatter: string): ExternalId[] {\n const inlineMatch = frontmatter.match(/^externalIds:\\s*\\[\\s*\\]/m);\n if (inlineMatch) return [];\n\n const results: ExternalId[] = [];\n const blockMatch = frontmatter.match(\n /^externalIds:\\s*\\n((?:\\s+-\\s+[\\s\\S]*?)(?=^\\w|\\n---))/m,\n );\n if (!blockMatch) return [];\n\n const itemBlocks = blockMatch[1].split(/\\n\\s+-\\s+/).filter(Boolean);\n for (const block of itemBlocks) {\n const lines = block.split('\\n');\n const entry: Record<string, string | null> = {};\n for (const line of lines) {\n const colonIdx = line.indexOf(':');\n if (colonIdx < 0) continue;\n const key = line.slice(0, colonIdx).trim().replace(/^-\\s+/, '');\n if (!key) continue;\n entry[key] = parseSimpleValue(line.slice(colonIdx + 1));\n }\n if (entry['system'] && entry['id']) {\n results.push({\n system: entry['system'],\n id: entry['id'],\n url: entry['url'] || null,\n });\n }\n }\n return results;\n}\n\nfunction parseWorkspace(frontmatter: string): Workspace {\n const defaults: Workspace = {\n repository: null,\n worktreePath: null,\n branch: null,\n parentBranch: null,\n };\n\n const fields = ['repository', 'worktreePath', 'branch', 'parentBranch'] as const;\n for (const field of fields) {\n const match = frontmatter.match(new RegExp(`^\\\\s+${field}:\\\\s*(.*)$`, 'm'));\n if (match) {\n defaults[field] = parseSimpleValue(match[1]);\n }\n }\n return defaults;\n}\n\nfunction parseTags(frontmatter: string): string[] {\n const inlineMatch = frontmatter.match(/^tags:\\s*\\[\\s*\\]/m);\n if (inlineMatch) return [];\n\n const results: string[] = [];\n const blockMatch = frontmatter.match(/^tags:\\s*\\n((?:\\s+-\\s+.*\\n?)*)/m);\n if (blockMatch) {\n const items = blockMatch[1].matchAll(/^\\s+-\\s+(.+)$/gm);\n for (const item of items) {\n results.push(item[1].trim());\n }\n }\n return results;\n}\n\nexport function parseAssignmentFrontmatter(fileContent: string): AssignmentFrontmatter {\n const [frontmatter] = extractFrontmatter(fileContent);\n\n function getField(key: string): string | null {\n const match = frontmatter.match(new RegExp(`^${key}:\\\\s*(.*)$`, 'm'));\n if (!match) return null;\n return parseSimpleValue(match[1]);\n }\n\n return {\n id: getField('id') ?? '',\n slug: getField('slug') ?? '',\n title: getField('title') ?? '',\n project: getField('project'),\n type: getField('type'),\n status: getField('status') ?? 'pending',\n priority: (getField('priority') ?? 'medium') as AssignmentFrontmatter['priority'],\n created: getField('created') ?? '',\n updated: getField('updated') ?? '',\n assignee: getField('assignee'),\n externalIds: parseExternalIds(frontmatter),\n dependsOn: parseDependsOn(frontmatter),\n links: parseLinks(frontmatter),\n blockedReason: getField('blockedReason'),\n workspace: parseWorkspace(frontmatter),\n tags: parseTags(frontmatter),\n };\n}\n\nfunction formatYamlValue(value: string | null): string {\n if (value === null) return 'null';\n if (/^\\d{4}-\\d{2}-\\d{2}T/.test(value)) {\n return `\"${value}\"`;\n }\n // Quote values containing YAML-special characters that could cause parse issues\n if (/[:#{}[\\],&*?|>!%@`]/.test(value) || /^\\s|\\s$/.test(value) || value === '') {\n const escaped = value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"');\n return `\"${escaped}\"`;\n }\n return value;\n}\n\nexport function updateAssignmentFile(\n fileContent: string,\n updates: Partial<Pick<AssignmentFrontmatter, 'status' | 'assignee' | 'blockedReason' | 'updated'>>,\n): string {\n let result = fileContent;\n\n for (const [key, value] of Object.entries(updates)) {\n if (value === undefined) continue;\n const formatted = formatYamlValue(value as string | null);\n const fieldRegex = new RegExp(`^(${key}:)\\\\s*.*$`, 'm');\n if (fieldRegex.test(result)) {\n result = result.replace(fieldRegex, `$1 ${formatted}`);\n }\n }\n\n return result;\n}\n\n/**\n * Locate the `workspace:` block inside a frontmatter string and return the\n * [start, end) byte offsets of the *body* of that block (lines indented under\n * `workspace:`, excluding the `workspace:` header line itself). Returns null\n * if no `workspace:` block is present.\n */\nfunction findWorkspaceBlock(\n fmBlock: string,\n): { headerStart: number; bodyStart: number; bodyEnd: number } | null {\n const headerMatch = fmBlock.match(/^workspace:\\s*$/m);\n if (!headerMatch) return null;\n const headerStart = fmBlock.indexOf(headerMatch[0]);\n const bodyStart = headerStart + headerMatch[0].length + 1; // skip the trailing \\n\n const after = fmBlock.slice(bodyStart);\n const lines = after.split('\\n');\n let consumed = 0;\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (line.length === 0) {\n // blank line — consume but keep scanning; YAML allows blanks inside a block\n consumed += line.length + 1;\n continue;\n }\n if (line[0] !== ' ') break; // top-level key — block ended\n consumed += line.length + 1;\n }\n // Trim a trailing newline we counted past EOF\n const bodyEnd = Math.min(bodyStart + consumed, fmBlock.length);\n return { headerStart, bodyStart, bodyEnd };\n}\n\n/**\n * Update nested workspace.* fields (repository, worktreePath, branch, parentBranch)\n * in-place. Edits only inside the `workspace:` block — other indented keys\n * with the same name elsewhere in frontmatter are not touched. Preserves\n * field ordering and unknown workspace fields. If the `workspace:` block does\n * not exist, it is appended to the frontmatter.\n */\nexport function updateAssignmentWorkspace(\n fileContent: string,\n partial: Partial<Workspace>,\n): string {\n const fmMatch = fileContent.match(/^(---\\n)([\\s\\S]*?)(\\n---)/);\n if (!fmMatch) {\n throw new Error('No frontmatter found in assignment file. Expected --- delimiters.');\n }\n\n const fmBlock = fmMatch[2];\n const fields = ['repository', 'worktreePath', 'branch', 'parentBranch'] as const;\n const block = findWorkspaceBlock(fmBlock);\n\n let newFm = fmBlock;\n\n if (block) {\n let body = fmBlock.slice(block.bodyStart, block.bodyEnd);\n for (const field of fields) {\n if (!(field in partial)) continue;\n const value = partial[field] ?? null;\n const formatted = formatYamlValue(value);\n const lineRegex = new RegExp(`^(\\\\s+${field}:)\\\\s*.*$`, 'm');\n if (lineRegex.test(body)) {\n body = body.replace(lineRegex, `$1 ${formatted}`);\n } else {\n const trimmed = body.replace(/\\n+$/, '');\n body = `${trimmed}${trimmed.length > 0 ? '\\n' : ''} ${field}: ${formatted}\\n`;\n }\n }\n newFm =\n fmBlock.slice(0, block.bodyStart) + body + fmBlock.slice(block.bodyEnd);\n } else {\n const lines = ['workspace:'];\n for (const field of fields) {\n const value = field in partial ? (partial[field] ?? null) : null;\n lines.push(` ${field}: ${formatYamlValue(value)}`);\n }\n newFm = `${fmBlock.replace(/\\n+$/, '')}\\n${lines.join('\\n')}`;\n }\n\n return `${fmMatch[1]}${newFm}${fmMatch[3]}${fileContent.slice(fmMatch[0].length)}`;\n}\n","import { mkdir, writeFile, access, rename } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\n\nexport async function ensureDir(dir: string): Promise<void> {\n await mkdir(dir, { recursive: true });\n}\n\nexport async function fileExists(filePath: string): Promise<boolean> {\n try {\n await access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function writeFileSafe(\n filePath: string,\n content: string,\n): Promise<boolean> {\n if (await fileExists(filePath)) {\n return false;\n }\n await ensureDir(dirname(filePath));\n await writeFile(filePath, content, 'utf-8');\n return true;\n}\n\nexport async function writeFileForce(\n filePath: string,\n content: string,\n): Promise<void> {\n const dir = dirname(filePath);\n const tempPath = join(\n dir,\n `.${Math.random().toString(36).slice(2)}.${Date.now()}.tmp`,\n );\n await ensureDir(dir);\n await writeFile(tempPath, content, 'utf-8');\n await rename(tempPath, filePath);\n}\n","export function nowTimestamp(): string {\n return new Date().toISOString().replace(/\\.\\d{3}Z$/, 'Z');\n}\n","/**\n * Generic frontmatter/markdown parser for all Syntaur file types.\n * Pattern copied from src/lifecycle/frontmatter.ts:3-23 (extractFrontmatter + parseSimpleValue).\n */\n\nexport interface ParsedFile {\n frontmatter: Record<string, string>;\n body: string;\n}\n\n/**\n * Split a markdown file into its frontmatter block and body.\n */\nexport function extractFrontmatter(fileContent: string): [string, string] {\n const match = fileContent.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) {\n return ['', fileContent];\n }\n const frontmatterBlock = match[1];\n const body = fileContent.slice(match[0].length).trim();\n return [frontmatterBlock, body];\n}\n\n/**\n * Parse a simple YAML value, handling null and quoted strings.\n */\nfunction parseSimpleValue(raw: string): string | null {\n const trimmed = raw.trim();\n if (trimmed === 'null' || trimmed === '~' || trimmed === '') return null;\n if (\n (trimmed.startsWith('\"') && trimmed.endsWith('\"')) ||\n (trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\"))\n ) {\n return trimmed.slice(1, -1);\n }\n return trimmed;\n}\n\n/**\n * Extract a top-level scalar field from frontmatter text.\n */\nexport function getField(frontmatter: string, key: string): string | null {\n const match = frontmatter.match(new RegExp(`^${key}:\\\\s*(.*)$`, 'm'));\n if (!match) return null;\n return parseSimpleValue(match[1]);\n}\n\n/**\n * Extract an indented scalar field (one level deep) from frontmatter text.\n */\nexport function getNestedField(frontmatter: string, parent: string, key: string): string | null {\n const parentRegex = new RegExp(`^${parent}:\\\\s*\\\\n((?:\\\\s+.*\\\\n?)*)`, 'm');\n const parentMatch = frontmatter.match(parentRegex);\n if (!parentMatch) return null;\n const block = parentMatch[1];\n const fieldMatch = block.match(new RegExp(`^\\\\s+${key}:\\\\s*(.*)$`, 'm'));\n if (!fieldMatch) return null;\n return parseSimpleValue(fieldMatch[1]);\n}\n\n/**\n * Parse a YAML list field (e.g., tags, dependsOn, relatedAssignments).\n *\n * Supports the empty inline form `field: []` and the block-list form\n * `field:\\n - a\\n - b`. Does NOT support populated inline arrays\n * (`field: [a, b]`). List items are returned as raw trimmed text; callers\n * that expect quoted-string entries should pass each item through\n * {@link unquoteYamlString}.\n */\nfunction parseListField(frontmatter: string, fieldName: string): string[] {\n const inlineMatch = frontmatter.match(new RegExp(`^${fieldName}:\\\\s*\\\\[\\\\s*\\\\]`, 'm'));\n if (inlineMatch) return [];\n\n const results: string[] = [];\n const blockMatch = frontmatter.match(\n new RegExp(`^${fieldName}:\\\\s*\\\\n((?:\\\\s+-\\\\s+.*\\\\n?)*)`, 'm'),\n );\n if (blockMatch) {\n let item: RegExpExecArray | null;\n const regex = /^\\s+-\\s+(.+)$/gm;\n while ((item = regex.exec(blockMatch[1])) !== null) {\n results.push(item[1].trim());\n }\n }\n return results;\n}\n\n/**\n * Strip a paired surrounding `\"...\"` or `'...'` from a YAML scalar.\n * Mirrors `parseSimpleValue`'s quote handling for list-item entries (which\n * `parseListField` leaves raw).\n */\nfunction unquoteYamlString(value: string): string {\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n return value.slice(1, -1);\n }\n return value;\n}\n\n// --- Project Parser ---\n\nexport interface ParsedProject {\n id: string;\n slug: string;\n title: string;\n archived: boolean;\n archivedAt: string | null;\n archivedReason: string | null;\n statusOverride: string | null;\n created: string;\n updated: string;\n tags: string[];\n workspace: string | null;\n /**\n * Repositories the project spans. Empty array when the field is absent —\n * existing project.md files predate this field, so callers must treat\n * missing as `[]`. Paths with YAML-special characters (spaces, colons,\n * leading dashes) must be quoted in source; quotes are stripped here.\n */\n repositories: string[];\n externalIds: Array<{ system: string; id: string; url: string | null }>;\n body: string;\n}\n\nexport function parseProject(fileContent: string): ParsedProject {\n const [fm, body] = extractFrontmatter(fileContent);\n // Legacy alias: pre-v0.2.0 installs used `mission` as the slug key. The\n // fs-migration helper renames the file but doesn't rewrite user-owned\n // frontmatter. Accept either key.\n const slug = getField(fm, 'slug') ?? getField(fm, 'mission') ?? '';\n return {\n id: getField(fm, 'id') ?? '',\n slug,\n title: getField(fm, 'title') ?? '',\n archived: getField(fm, 'archived') === 'true',\n archivedAt: getField(fm, 'archivedAt'),\n archivedReason: getField(fm, 'archivedReason'),\n statusOverride: getField(fm, 'statusOverride'),\n created: getField(fm, 'created') ?? '',\n updated: getField(fm, 'updated') ?? '',\n tags: parseListField(fm, 'tags'),\n workspace: getField(fm, 'workspace'),\n repositories: parseListField(fm, 'repositories').map(unquoteYamlString),\n externalIds: parseExternalIds(fm),\n body,\n };\n}\n\n// --- Status Parser (for _status.md) ---\n\nexport interface ParsedStatus {\n project: string;\n status: string;\n progress: Record<string, number> & { total: number };\n needsAttention: {\n blockedCount: number;\n failedCount: number;\n openQuestions: number;\n };\n body: string;\n}\n\nexport function parseStatus(fileContent: string): ParsedStatus {\n const [fm, body] = extractFrontmatter(fileContent);\n\n // Dynamically parse progress fields\n const progress: Record<string, number> & { total: number } = { total: 0 };\n const progressMatch = fm.match(/^progress:\\s*\\n((?:\\s+.*\\n?)*)/m);\n if (progressMatch) {\n const lines = progressMatch[1].split('\\n');\n for (const line of lines) {\n const kv = line.match(/^\\s+(\\w+):\\s*(\\d+)/);\n if (kv) {\n progress[kv[1]] = parseInt(kv[2], 10);\n }\n }\n }\n\n return {\n project: getField(fm, 'project') ?? '',\n status: getField(fm, 'status') ?? 'pending',\n progress,\n needsAttention: {\n blockedCount: parseInt(getNestedField(fm, 'needsAttention', 'blockedCount') ?? '0', 10),\n failedCount: parseInt(getNestedField(fm, 'needsAttention', 'failedCount') ?? '0', 10),\n openQuestions: parseInt(getNestedField(fm, 'needsAttention', 'openQuestions') ?? '0', 10),\n },\n body,\n };\n}\n\n// --- Assignment Summary Parser ---\n\nexport interface ParsedAssignmentSummary {\n id: string;\n slug: string;\n title: string;\n status: string;\n priority: string;\n assignee: string | null;\n dependsOn: string[];\n links: string[];\n updated: string;\n}\n\nexport function parseAssignmentSummary(fileContent: string): ParsedAssignmentSummary {\n const [fm] = extractFrontmatter(fileContent);\n return {\n id: getField(fm, 'id') ?? '',\n slug: getField(fm, 'slug') ?? '',\n title: getField(fm, 'title') ?? '',\n status: getField(fm, 'status') ?? 'pending',\n priority: getField(fm, 'priority') ?? 'medium',\n assignee: getField(fm, 'assignee'),\n dependsOn: parseListField(fm, 'dependsOn'),\n links: parseListField(fm, 'links'),\n updated: getField(fm, 'updated') ?? '',\n };\n}\n\n// --- Full Assignment Parser ---\n\nexport interface ParsedAssignmentFull {\n id: string;\n slug: string;\n title: string;\n project: string | null;\n workspaceGroup: string | null;\n type: string | null;\n status: string;\n priority: string;\n assignee: string | null;\n dependsOn: string[];\n links: string[];\n blockedReason: string | null;\n workspace: {\n repository: string | null;\n worktreePath: string | null;\n branch: string | null;\n parentBranch: string | null;\n };\n externalIds: Array<{ system: string; id: string; url: string | null }>;\n tags: string[];\n created: string;\n updated: string;\n body: string;\n}\n\nfunction parseExternalIds(frontmatter: string): Array<{ system: string; id: string; url: string | null }> {\n const inlineMatch = frontmatter.match(/^externalIds:\\s*\\[\\s*\\]/m);\n if (inlineMatch) return [];\n\n const results: Array<{ system: string; id: string; url: string | null }> = [];\n const blockMatch = frontmatter.match(\n /^externalIds:\\s*\\n((?:\\s+-\\s+[\\s\\S]*?)(?=^\\w|\\n---))/m,\n );\n if (!blockMatch) return [];\n\n const itemBlocks = blockMatch[1].split(/\\n\\s+-\\s+/).filter(Boolean);\n for (const block of itemBlocks) {\n const lines = block.split('\\n');\n const entry: Record<string, string | null> = {};\n for (const line of lines) {\n const colonIdx = line.indexOf(':');\n if (colonIdx < 0) continue;\n const key = line.slice(0, colonIdx).trim().replace(/^-\\s+/, '');\n if (!key) continue;\n entry[key] = parseSimpleValue(line.slice(colonIdx + 1));\n }\n if (entry['system'] && entry['id']) {\n results.push({\n system: entry['system'],\n id: entry['id'],\n url: entry['url'] || null,\n });\n }\n }\n return results;\n}\n\nexport function parseAssignmentFull(fileContent: string): ParsedAssignmentFull {\n const [fm, body] = extractFrontmatter(fileContent);\n return {\n id: getField(fm, 'id') ?? '',\n slug: getField(fm, 'slug') ?? '',\n title: getField(fm, 'title') ?? '',\n project: getField(fm, 'project'),\n workspaceGroup: getField(fm, 'workspaceGroup'),\n type: getField(fm, 'type'),\n status: getField(fm, 'status') ?? 'pending',\n priority: getField(fm, 'priority') ?? 'medium',\n assignee: getField(fm, 'assignee'),\n dependsOn: parseListField(fm, 'dependsOn'),\n links: parseListField(fm, 'links'),\n blockedReason: getField(fm, 'blockedReason'),\n workspace: {\n repository: getNestedField(fm, 'workspace', 'repository'),\n worktreePath: getNestedField(fm, 'workspace', 'worktreePath'),\n branch: getNestedField(fm, 'workspace', 'branch'),\n parentBranch: getNestedField(fm, 'workspace', 'parentBranch'),\n },\n externalIds: parseExternalIds(fm),\n tags: parseListField(fm, 'tags'),\n created: getField(fm, 'created') ?? '',\n updated: getField(fm, 'updated') ?? '',\n body,\n };\n}\n\n// --- Plan Parser ---\n\nexport interface ParsedPlan {\n assignment: string;\n status: string;\n created: string;\n updated: string;\n body: string;\n}\n\nexport function parsePlan(fileContent: string): ParsedPlan {\n const [fm, body] = extractFrontmatter(fileContent);\n return {\n assignment: getField(fm, 'assignment') ?? '',\n status: getField(fm, 'status') ?? '',\n created: getField(fm, 'created') ?? '',\n updated: getField(fm, 'updated') ?? '',\n body,\n };\n}\n\n// --- Scratchpad Parser ---\n\nexport interface ParsedScratchpad {\n assignment: string;\n updated: string;\n body: string;\n}\n\nexport function parseScratchpad(fileContent: string): ParsedScratchpad {\n const [fm, body] = extractFrontmatter(fileContent);\n return {\n assignment: getField(fm, 'assignment') ?? '',\n updated: getField(fm, 'updated') ?? '',\n body,\n };\n}\n\n// --- Handoff Parser ---\n\nexport interface ParsedHandoff {\n assignment: string;\n handoffCount: number;\n updated: string;\n body: string;\n}\n\nexport function parseHandoff(fileContent: string): ParsedHandoff {\n const [fm, body] = extractFrontmatter(fileContent);\n return {\n assignment: getField(fm, 'assignment') ?? '',\n handoffCount: parseInt(getField(fm, 'handoffCount') ?? '0', 10),\n updated: getField(fm, 'updated') ?? '',\n body,\n };\n}\n\n// --- Decision Record Parser ---\n\nexport interface ParsedDecisionRecord {\n assignment: string;\n decisionCount: number;\n updated: string;\n body: string;\n}\n\nexport function parseDecisionRecord(fileContent: string): ParsedDecisionRecord {\n const [fm, body] = extractFrontmatter(fileContent);\n return {\n assignment: getField(fm, 'assignment') ?? '',\n decisionCount: parseInt(getField(fm, 'decisionCount') ?? '0', 10),\n updated: getField(fm, 'updated') ?? '',\n body,\n };\n}\n\n// --- Comments Parser ---\n\nexport interface ParsedComment {\n id: string;\n timestamp: string;\n author: string;\n type: 'question' | 'note' | 'feedback';\n body: string;\n replyTo?: string;\n resolved?: boolean;\n}\n\nexport interface ParsedComments {\n assignment: string;\n entryCount: number;\n updated: string;\n entries: ParsedComment[];\n body: string;\n}\n\nexport function parseComments(fileContent: string): ParsedComments {\n const [fm, body] = extractFrontmatter(fileContent);\n const entries: ParsedComment[] = [];\n const sections = body.split(/^## /m).slice(1);\n for (const section of sections) {\n const newlineIdx = section.indexOf('\\n');\n if (newlineIdx === -1) continue;\n const id = section.slice(0, newlineIdx).trim();\n const rest = section.slice(newlineIdx + 1);\n const headerMatch = rest.match(\n /^\\s*\\*\\*Recorded:\\*\\*\\s*(.*)\\n\\*\\*Author:\\*\\*\\s*(.*)\\n\\*\\*Type:\\*\\*\\s*(question|note|feedback)(?:\\n\\*\\*Reply to:\\*\\*\\s*(.*))?(?:\\n\\*\\*Resolved:\\*\\*\\s*(true|false))?\\n+([\\s\\S]*)$/,\n );\n if (!headerMatch) continue;\n const [, timestamp, author, type, replyTo, resolvedStr, entryBody] = headerMatch;\n const entry: ParsedComment = {\n id,\n timestamp: timestamp.trim(),\n author: author.trim(),\n type: type as 'question' | 'note' | 'feedback',\n body: entryBody.trim(),\n };\n if (replyTo) entry.replyTo = replyTo.trim();\n if (resolvedStr) entry.resolved = resolvedStr === 'true';\n entries.push(entry);\n }\n return {\n assignment: getField(fm, 'assignment') ?? '',\n entryCount: parseInt(getField(fm, 'entryCount') ?? '0', 10),\n updated: getField(fm, 'updated') ?? '',\n entries,\n body,\n };\n}\n\n// --- Progress Parser ---\n\nexport interface ProgressEntry {\n timestamp: string;\n body: string;\n}\n\nexport interface ParsedProgress {\n assignment: string;\n entryCount: number;\n updated: string;\n entries: ProgressEntry[];\n body: string;\n}\n\nexport function parseProgress(fileContent: string): ParsedProgress {\n const [fm, body] = extractFrontmatter(fileContent);\n const entries: ProgressEntry[] = [];\n const sections = body.split(/^## /m).slice(1);\n for (const section of sections) {\n const newlineIdx = section.indexOf('\\n');\n if (newlineIdx === -1) continue;\n const timestamp = section.slice(0, newlineIdx).trim();\n const entryBody = section.slice(newlineIdx + 1).trim();\n entries.push({ timestamp, body: entryBody });\n }\n return {\n assignment: getField(fm, 'assignment') ?? '',\n entryCount: parseInt(getField(fm, 'entryCount') ?? '0', 10),\n updated: getField(fm, 'updated') ?? '',\n entries,\n body,\n };\n}\n\n// --- Resource Parser ---\n\nexport interface ParsedResource {\n name: string;\n source: string;\n category: string;\n relatedAssignments: string[];\n created: string;\n updated: string;\n body: string;\n}\n\nexport function parseResource(fileContent: string): ParsedResource {\n const [fm, body] = extractFrontmatter(fileContent);\n return {\n name: getField(fm, 'name') ?? '',\n source: getField(fm, 'source') ?? '',\n category: getField(fm, 'category') ?? '',\n relatedAssignments: parseListField(fm, 'relatedAssignments'),\n created: getField(fm, 'created') ?? '',\n updated: getField(fm, 'updated') ?? '',\n body,\n };\n}\n\n// --- Memory Parser ---\n\nexport interface ParsedMemory {\n name: string;\n source: string;\n scope: string;\n sourceAssignment: string | null;\n relatedAssignments: string[];\n tags: string[];\n created: string;\n updated: string;\n body: string;\n}\n\nexport function parseMemory(fileContent: string): ParsedMemory {\n const [fm, body] = extractFrontmatter(fileContent);\n return {\n name: getField(fm, 'name') ?? '',\n source: getField(fm, 'source') ?? '',\n scope: getField(fm, 'scope') ?? '',\n sourceAssignment: getField(fm, 'sourceAssignment'),\n relatedAssignments: parseListField(fm, 'relatedAssignments'),\n tags: parseListField(fm, 'tags'),\n created: getField(fm, 'created') ?? '',\n updated: getField(fm, 'updated') ?? '',\n body,\n };\n}\n\n// --- Playbook Parser ---\n\nexport interface ParsedPlaybook {\n slug: string;\n name: string;\n description: string;\n whenToUse: string;\n created: string;\n updated: string;\n tags: string[];\n body: string;\n}\n\nexport function parsePlaybook(fileContent: string): ParsedPlaybook {\n const [fm, body] = extractFrontmatter(fileContent);\n return {\n slug: getField(fm, 'slug') ?? '',\n name: getField(fm, 'name') ?? '',\n description: getField(fm, 'description') ?? '',\n whenToUse: getField(fm, 'when_to_use') ?? '',\n created: getField(fm, 'created') ?? '',\n updated: getField(fm, 'updated') ?? '',\n tags: parseListField(fm, 'tags'),\n body,\n };\n}\n\n// --- Mermaid Graph Extractor ---\n\n/**\n * Extract the mermaid code block from _status.md body content.\n * Returns null if no mermaid block is found.\n */\nexport function extractMermaidGraph(body: string): string | null {\n const match = body.match(/```mermaid\\n([\\s\\S]*?)```/);\n return match ? match[1].trim() : null;\n}\n","import { randomBytes } from 'node:crypto';\nimport { readFile } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { extractFrontmatter, getField } from '../dashboard/parser.js';\nimport { ensureDir, fileExists, writeFileForce } from '../utils/fs.js';\nimport type {\n TodoItem,\n TodoChecklist,\n TodoStatus,\n ArchiveInterval,\n LogEntry,\n TodoLog,\n} from './types.js';\n\n// --- Short ID ---\n\nexport function generateShortId(): string {\n return randomBytes(2).toString('hex');\n}\n\nexport function generateUniqueId(existingIds: Set<string>): string {\n let id = generateShortId();\n let attempts = 0;\n while (existingIds.has(id) && attempts < 100) {\n id = generateShortId();\n attempts++;\n }\n return id;\n}\n\n// --- Checklist parsing ---\n\nconst ITEM_REGEX = /^- \\[([ x!]|>[^\\]]*)\\]\\s+(.+)$/;\nconst ID_REGEX = /\\[t:([a-f0-9]{4})\\]/;\nconst TAG_REGEX = /#([a-zA-Z0-9_-]+)/g;\n// Meta token follows `[t:<id>]` and looks like `<key=value;key=value;...>`.\n// Anchored at end of line. Recognized keys: b (branch), w (worktreePath),\n// c (createdAt), u (updatedAt), p (planDir), l (linkedAssignmentId),\n// lr (linkedAssignmentRef). Unknown keys are dropped.\nconst META_TOKEN_REGEX = /\\[t:[a-f0-9]{4}\\]\\s+<([^>]*)>\\s*$/;\nconst META_ENCODE_CHARS = ['%', '<', '>', '[', ']', '=', ';', '\\n', '\\r'];\n\nexport function encodeMetaValue(value: string): string {\n let out = '';\n for (const ch of value) {\n if (META_ENCODE_CHARS.includes(ch)) {\n out += '%' + ch.charCodeAt(0).toString(16).toUpperCase().padStart(2, '0');\n } else {\n out += ch;\n }\n }\n return out;\n}\n\nexport function decodeMetaValue(value: string): string {\n return value.replace(/%([0-9A-Fa-f]{2})/g, (_, hex) =>\n String.fromCharCode(parseInt(hex, 16)),\n );\n}\n\ninterface MetaFields {\n branch: string | null;\n worktreePath: string | null;\n createdAt: string | null;\n updatedAt: string | null;\n planDir: string | null;\n linkedAssignmentId: string | null;\n linkedAssignmentRef: string | null;\n}\n\nfunction emptyMetaFields(): MetaFields {\n return {\n branch: null,\n worktreePath: null,\n createdAt: null,\n updatedAt: null,\n planDir: null,\n linkedAssignmentId: null,\n linkedAssignmentRef: null,\n };\n}\n\nexport function parseMetaToken(line: string): MetaFields {\n const match = line.match(META_TOKEN_REGEX);\n if (!match) return emptyMetaFields();\n const body = match[1];\n if (!body) return emptyMetaFields();\n const fields = emptyMetaFields();\n for (const pair of body.split(';')) {\n const trimmed = pair.trim();\n if (!trimmed) continue;\n const eq = trimmed.indexOf('=');\n if (eq < 0) continue;\n const key = trimmed.slice(0, eq).trim();\n const rawValue = trimmed.slice(eq + 1);\n const value = decodeMetaValue(rawValue);\n switch (key) {\n case 'b': fields.branch = value; break;\n case 'w': fields.worktreePath = value; break;\n case 'c': fields.createdAt = value; break;\n case 'u': fields.updatedAt = value; break;\n case 'p': fields.planDir = value; break;\n case 'l': fields.linkedAssignmentId = value; break;\n case 'lr': fields.linkedAssignmentRef = value; break;\n }\n }\n return fields;\n}\n\nexport function serializeMetaToken(item: TodoItem): string {\n const pairs: string[] = [];\n if (item.branch !== null) pairs.push(`b=${encodeMetaValue(item.branch)}`);\n if (item.worktreePath !== null) pairs.push(`w=${encodeMetaValue(item.worktreePath)}`);\n if (item.createdAt !== null) pairs.push(`c=${encodeMetaValue(item.createdAt)}`);\n if (item.updatedAt !== null) pairs.push(`u=${encodeMetaValue(item.updatedAt)}`);\n if (item.planDir !== null) pairs.push(`p=${encodeMetaValue(item.planDir)}`);\n if (item.linkedAssignmentId !== null) pairs.push(`l=${encodeMetaValue(item.linkedAssignmentId)}`);\n if (item.linkedAssignmentRef !== null) pairs.push(`lr=${encodeMetaValue(item.linkedAssignmentRef)}`);\n if (pairs.length === 0) return '';\n return `<${pairs.join(';')}>`;\n}\n\nfunction parseStatus(marker: string): { status: TodoStatus; session: string | null } {\n if (marker === ' ') return { status: 'open', session: null };\n if (marker === 'x') return { status: 'completed', session: null };\n if (marker === '!') return { status: 'blocked', session: null };\n if (marker.startsWith('>:')) return { status: 'in_progress', session: marker.slice(2) };\n if (marker === '>') return { status: 'in_progress', session: null };\n return { status: 'open', session: null };\n}\n\nfunction sanitizeSession(session: string): string {\n // Strip characters that would break the markdown checkbox syntax\n return session.replace(/[\\[\\]]/g, '');\n}\n\nfunction statusToMarker(item: TodoItem): string {\n switch (item.status) {\n case 'open':\n return ' ';\n case 'completed':\n return 'x';\n case 'blocked':\n return '!';\n case 'in_progress':\n return item.session ? `>:${sanitizeSession(item.session)}` : '>';\n }\n}\n\nexport function parseChecklistItem(line: string): TodoItem | null {\n const match = line.match(ITEM_REGEX);\n if (!match) return null;\n\n const marker = match[1];\n const rest = match[2];\n\n const { status, session } = parseStatus(marker);\n\n const idMatch = rest.match(ID_REGEX);\n const id = idMatch ? idMatch[1] : '';\n\n const tags: string[] = [];\n let tagMatch;\n const tagRegex = new RegExp(TAG_REGEX.source, 'g');\n while ((tagMatch = tagRegex.exec(rest)) !== null) {\n tags.push(tagMatch[1]);\n }\n\n // Description is everything before the first #tag or [t:...], trimmed\n let description = rest;\n const firstTagIdx = rest.search(/#[a-zA-Z0-9_-]/);\n const firstIdIdx = rest.search(/\\[t:[a-f0-9]{4}\\]/);\n const cutPoints = [firstTagIdx, firstIdIdx].filter((i) => i >= 0);\n if (cutPoints.length > 0) {\n description = rest.slice(0, Math.min(...cutPoints)).trim();\n }\n\n const meta = parseMetaToken(line);\n\n return {\n id,\n description,\n status,\n tags,\n session,\n branch: meta.branch,\n worktreePath: meta.worktreePath,\n createdAt: meta.createdAt,\n updatedAt: meta.updatedAt,\n planDir: meta.planDir,\n linkedAssignmentId: meta.linkedAssignmentId,\n linkedAssignmentRef: meta.linkedAssignmentRef,\n };\n}\n\nexport function serializeChecklistItem(item: TodoItem): string {\n const marker = statusToMarker(item);\n const tagStr = item.tags.map((t) => `#${t}`).join(' ');\n const parts = [`- [${marker}] ${item.description}`];\n if (tagStr) parts.push(tagStr);\n parts.push(`[t:${item.id}]`);\n const meta = serializeMetaToken(item);\n if (meta) parts.push(meta);\n return parts.join(' ');\n}\n\nexport function parseChecklist(content: string): TodoChecklist {\n const [fm, body] = extractFrontmatter(content);\n const workspace = getField(fm, 'workspace') || '_global';\n const archiveIntervalRaw = getField(fm, 'archiveInterval') || 'weekly';\n const archiveInterval = (['daily', 'weekly', 'monthly', 'never'].includes(archiveIntervalRaw)\n ? archiveIntervalRaw\n : 'weekly') as ArchiveInterval;\n\n const items: TodoItem[] = [];\n for (const line of body.split('\\n')) {\n const item = parseChecklistItem(line);\n if (item) items.push(item);\n }\n\n return { workspace, archiveInterval, items };\n}\n\nexport function serializeChecklist(checklist: TodoChecklist): string {\n const fm = [\n '---',\n `workspace: ${checklist.workspace}`,\n `archiveInterval: ${checklist.archiveInterval}`,\n '---',\n ].join('\\n');\n\n const header = '# Quick Todos';\n const items = checklist.items.map(serializeChecklistItem).join('\\n');\n\n return `${fm}\\n\\n${header}\\n\\n${items}\\n`;\n}\n\n// --- Log parsing ---\n\nexport function parseLog(content: string): TodoLog {\n const [fm, body] = extractFrontmatter(content);\n const workspace = getField(fm, 'workspace') || '_global';\n\n const entries: LogEntry[] = [];\n const sections = body.split(/^### /m).filter((s) => s.match(/^\\d{4}-/));\n\n for (const section of sections) {\n const lines = section.split('\\n');\n const heading = lines[0]?.trim() || '';\n\n // Heading format: 2026-04-07T14:30:00Z — t:a3f1, t:b7c2\n const headingMatch = heading.match(/^(\\S+)\\s*—?\\s*(.*)/);\n if (!headingMatch) continue;\n\n const timestamp = headingMatch[1];\n const idsPart = headingMatch[2] || '';\n const itemIds = [...idsPart.matchAll(/t:([a-f0-9]{4})/g)].map((m) => m[1]);\n\n const entry: LogEntry = {\n timestamp,\n itemIds,\n items: '',\n session: null,\n branch: null,\n summary: '',\n blockers: null,\n status: null,\n };\n\n for (const line of lines.slice(1)) {\n const fieldMatch = line.match(/^\\*\\*(\\w+):\\*\\*\\s*(.*)/);\n if (!fieldMatch) continue;\n const key = fieldMatch[1].toLowerCase();\n const value = fieldMatch[2].trim();\n switch (key) {\n case 'items':\n entry.items = value;\n break;\n case 'session':\n entry.session = value;\n break;\n case 'branch':\n entry.branch = value;\n break;\n case 'summary':\n entry.summary = value;\n break;\n case 'blockers':\n entry.blockers = value;\n break;\n case 'status':\n entry.status = value;\n break;\n }\n }\n\n entries.push(entry);\n }\n\n return { workspace, entries };\n}\n\nexport function serializeLogEntry(entry: LogEntry): string {\n const idStr = entry.itemIds.map((id) => `t:${id}`).join(', ');\n const lines = [`### ${entry.timestamp} — ${idStr}`];\n if (entry.items) lines.push(`**Items:** ${entry.items}`);\n if (entry.session) lines.push(`**Session:** ${entry.session}`);\n if (entry.branch) lines.push(`**Branch:** ${entry.branch}`);\n if (entry.summary) lines.push(`**Summary:** ${entry.summary}`);\n if (entry.blockers) lines.push(`**Blockers:** ${entry.blockers}`);\n if (entry.status) lines.push(`**Status:** ${entry.status}`);\n return lines.join('\\n');\n}\n\n// --- File I/O ---\n\nexport function checklistPath(todosDir: string, workspace: string): string {\n return resolve(todosDir, `${workspace}.md`);\n}\n\nexport function logPath(todosDir: string, workspace: string): string {\n return resolve(todosDir, `${workspace}-log.md`);\n}\n\nexport function archivePath(\n todosDir: string,\n workspace: string,\n interval: ArchiveInterval,\n now: Date = new Date(),\n): string {\n const year = now.getFullYear();\n const month = String(now.getMonth() + 1).padStart(2, '0');\n const day = String(now.getDate()).padStart(2, '0');\n\n let suffix: string;\n switch (interval) {\n case 'daily':\n suffix = `${year}-${month}-${day}`;\n break;\n case 'weekly': {\n // ISO week number\n const jan1 = new Date(year, 0, 1);\n const days = Math.floor((now.getTime() - jan1.getTime()) / 86400000);\n const week = String(Math.ceil((days + jan1.getDay() + 1) / 7)).padStart(2, '0');\n suffix = `${year}-W${week}`;\n break;\n }\n case 'monthly':\n suffix = `${year}-${month}`;\n break;\n default:\n suffix = `${year}-${month}-${day}`;\n }\n\n return resolve(todosDir, 'archive', `${workspace}-${suffix}.md`);\n}\n\nexport async function readChecklist(todosDir: string, workspace: string): Promise<TodoChecklist> {\n const path = checklistPath(todosDir, workspace);\n if (!(await fileExists(path))) {\n return { workspace, archiveInterval: 'weekly', items: [] };\n }\n const content = await readFile(path, 'utf-8');\n return parseChecklist(content);\n}\n\nexport async function writeChecklist(todosDir: string, checklist: TodoChecklist): Promise<void> {\n await ensureDir(todosDir);\n const path = checklistPath(todosDir, checklist.workspace);\n await writeFileForce(path, serializeChecklist(checklist));\n}\n\nexport async function readLog(todosDir: string, workspace: string): Promise<TodoLog> {\n const path = logPath(todosDir, workspace);\n if (!(await fileExists(path))) {\n return { workspace, entries: [] };\n }\n const content = await readFile(path, 'utf-8');\n return parseLog(content);\n}\n\nexport async function appendLogEntry(\n todosDir: string,\n workspace: string,\n entry: LogEntry,\n): Promise<void> {\n await ensureDir(todosDir);\n const path = logPath(todosDir, workspace);\n let content: string;\n if (await fileExists(path)) {\n content = await readFile(path, 'utf-8');\n content = content.trimEnd() + '\\n\\n' + serializeLogEntry(entry) + '\\n';\n } else {\n const fm = `---\\nworkspace: ${workspace}\\n---\\n\\n# Todo Log\\n\\n`;\n content = fm + serializeLogEntry(entry) + '\\n';\n }\n await writeFileForce(path, content);\n}\n\nexport function computeCounts(items: TodoItem[]) {\n const counts = { open: 0, in_progress: 0, completed: 0, blocked: 0, total: items.length };\n for (const item of items) {\n counts[item.status]++;\n }\n return counts;\n}\n","import { readdir } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport {\n readChecklist,\n writeChecklist,\n readLog,\n appendLogEntry,\n} from '../todos/parser.js';\nimport { fileExists } from '../utils/fs.js';\nimport type { TodoItem, LogEntry } from '../todos/types.js';\n\nexport interface LinkedTodosLookup {\n /** Workspace todos dir (e.g. ~/.syntaur/todos). */\n todosDir: string;\n /** Projects root dir (e.g. ~/.syntaur/projects). Used to scan per-project todo checklists. */\n projectsDir: string;\n}\n\nexport interface LinkedTodosResult {\n completed?: number;\n reopened?: number;\n touched: Array<{ workspace: string; id: string }>;\n}\n\nconst AUTO_COMPLETE_PREFIX = 'Auto-completed: linked assignment ';\nconst AUTO_REOPEN_PREFIX = 'Auto-reopened: linked assignment ';\n\nfunction touchItem(item: TodoItem): void {\n const now = new Date().toISOString();\n if (item.createdAt === null) item.createdAt = now;\n item.updatedAt = now;\n}\n\nasync function listWorkspaceTodosFiles(todosDir: string): Promise<string[]> {\n if (!(await fileExists(todosDir))) return [];\n const files = await readdir(todosDir).catch(() => [] as string[]);\n return files\n .filter((f): f is string => typeof f === 'string')\n .filter((f) => f.endsWith('.md') && !f.endsWith('-log.md'))\n .map((f) => f.replace(/\\.md$/, ''));\n}\n\nasync function listProjectTodosWorkspaces(projectsDir: string): Promise<Array<{ projectSlug: string; todosDir: string; workspace: string }>> {\n if (!(await fileExists(projectsDir))) return [];\n const projects = await readdir(projectsDir).catch(() => [] as string[]);\n const result: Array<{ projectSlug: string; todosDir: string; workspace: string }> = [];\n for (const p of projects) {\n if (typeof p !== 'string') continue;\n const todosDir = resolve(projectsDir, p, 'todos');\n if (await fileExists(resolve(todosDir, `${p}.md`))) {\n result.push({ projectSlug: p, todosDir, workspace: p });\n }\n }\n return result;\n}\n\n/**\n * Returns true if the most recent log entry for this item has summary\n * starting with `prefix`. Used to identify items that were auto-completed\n * (so we know it is safe to auto-reopen them) and items that were already\n * auto-reopened (idempotency).\n */\nasync function lastLogEntryMatches(\n todosDir: string,\n workspace: string,\n itemId: string,\n prefix: string,\n): Promise<boolean> {\n const log = await readLog(todosDir, workspace);\n // Scan in reverse: most recent matching entry for this item.\n for (let i = log.entries.length - 1; i >= 0; i--) {\n const entry = log.entries[i];\n if (!entry.itemIds.includes(itemId)) continue;\n return entry.summary.startsWith(prefix);\n }\n return false;\n}\n\nexport async function completeLinkedTodos(\n lookup: LinkedTodosLookup,\n assignmentId: string,\n assignmentRef: string,\n): Promise<LinkedTodosResult> {\n const touched: Array<{ workspace: string; id: string }> = [];\n\n const workspaces = await listWorkspaceTodosFiles(lookup.todosDir);\n const projectWorkspaces = await listProjectTodosWorkspaces(lookup.projectsDir);\n const all: Array<{ todosDir: string; workspace: string }> = [\n ...workspaces.map((workspace) => ({ todosDir: lookup.todosDir, workspace })),\n ...projectWorkspaces.map(({ todosDir, workspace }) => ({ todosDir, workspace })),\n ];\n\n for (const { todosDir, workspace } of all) {\n const checklist = await readChecklist(todosDir, workspace);\n const idsTouched: string[] = [];\n for (const item of checklist.items) {\n if (item.linkedAssignmentId !== assignmentId) continue;\n if (item.status === 'completed') continue;\n item.status = 'completed';\n item.session = null;\n touchItem(item);\n idsTouched.push(item.id);\n }\n if (idsTouched.length === 0) continue;\n await writeChecklist(todosDir, checklist);\n for (const id of idsTouched) {\n const entry: LogEntry = {\n timestamp: new Date().toISOString(),\n itemIds: [id],\n items: checklist.items.find((i) => i.id === id)?.description ?? '',\n session: null,\n branch: null,\n summary: `${AUTO_COMPLETE_PREFIX}${assignmentRef} closed`,\n blockers: null,\n status: null,\n };\n await appendLogEntry(todosDir, workspace, entry);\n touched.push({ workspace, id });\n }\n }\n\n return { completed: touched.length, touched };\n}\n\nexport async function reopenLinkedTodos(\n lookup: LinkedTodosLookup,\n assignmentId: string,\n assignmentRef: string,\n): Promise<LinkedTodosResult> {\n const touched: Array<{ workspace: string; id: string }> = [];\n\n const workspaces = await listWorkspaceTodosFiles(lookup.todosDir);\n const projectWorkspaces = await listProjectTodosWorkspaces(lookup.projectsDir);\n const all: Array<{ todosDir: string; workspace: string }> = [\n ...workspaces.map((workspace) => ({ todosDir: lookup.todosDir, workspace })),\n ...projectWorkspaces.map(({ todosDir, workspace }) => ({ todosDir, workspace })),\n ];\n\n for (const { todosDir, workspace } of all) {\n const checklist = await readChecklist(todosDir, workspace);\n const candidates = checklist.items.filter(\n (i) => i.linkedAssignmentId === assignmentId && i.status === 'completed',\n );\n if (candidates.length === 0) continue;\n const idsTouched: string[] = [];\n for (const item of candidates) {\n // Manual-completion guard: only auto-reopen items whose most recent log\n // entry is the auto-complete marker. If the user marked them complete\n // by hand afterwards, leave them alone.\n const wasAutoCompleted = await lastLogEntryMatches(\n todosDir,\n workspace,\n item.id,\n AUTO_COMPLETE_PREFIX,\n );\n if (!wasAutoCompleted) continue;\n item.status = 'in_progress';\n item.session = null;\n touchItem(item);\n idsTouched.push(item.id);\n }\n if (idsTouched.length === 0) continue;\n await writeChecklist(todosDir, checklist);\n for (const id of idsTouched) {\n const entry: LogEntry = {\n timestamp: new Date().toISOString(),\n itemIds: [id],\n items: checklist.items.find((i) => i.id === id)?.description ?? '',\n session: null,\n branch: null,\n summary: `${AUTO_REOPEN_PREFIX}${assignmentRef} reopened`,\n blockers: null,\n status: null,\n };\n await appendLogEntry(todosDir, workspace, entry);\n touched.push({ workspace, id });\n }\n }\n\n return { reopened: touched.length, touched };\n}\n","import { resolve } from 'node:path';\nimport { readFile } from 'node:fs/promises';\nimport { fileExists, writeFileForce } from '../utils/fs.js';\nimport { nowTimestamp } from '../utils/timestamp.js';\nimport { getTargetStatus } from './state-machine.js';\nimport { parseAssignmentFrontmatter, updateAssignmentFile } from './frontmatter.js';\nimport {\n completeLinkedTodos,\n reopenLinkedTodos,\n type LinkedTodosLookup,\n} from './linked-todos.js';\nimport type { TransitionCommand, TransitionResult, AssignmentFrontmatter } from './types.js';\n\nfunction linkedAssignmentRef(frontmatter: AssignmentFrontmatter): string {\n return frontmatter.project ? `${frontmatter.project}/${frontmatter.slug}` : frontmatter.id;\n}\n\nasync function applyLinkedTodosSideEffect(\n lookup: LinkedTodosLookup | undefined,\n command: string,\n targetStatus: string,\n frontmatter: AssignmentFrontmatter,\n): Promise<void> {\n if (!lookup) return;\n const ref = linkedAssignmentRef(frontmatter);\n if (targetStatus === 'completed') {\n await completeLinkedTodos(lookup, frontmatter.id, ref);\n } else if (command === 'reopen') {\n await reopenLinkedTodos(lookup, frontmatter.id, ref);\n }\n}\n\nfunction resolveAssignmentPath(projectDir: string, assignmentSlug: string): string {\n return resolve(projectDir, 'assignments', assignmentSlug, 'assignment.md');\n}\n\nasync function readAssignment(\n filePath: string,\n): Promise<{ content: string; frontmatter: AssignmentFrontmatter }> {\n if (!(await fileExists(filePath))) {\n throw new Error(`Assignment file not found: ${filePath}`);\n }\n const content = await readFile(filePath, 'utf-8');\n const frontmatter = parseAssignmentFrontmatter(content);\n return { content, frontmatter };\n}\n\nasync function checkDependencies(\n projectDir: string,\n dependsOn: string[],\n terminalStatuses?: ReadonlySet<string>,\n): Promise<{ satisfied: boolean; unmet: string[] }> {\n const terminals = terminalStatuses ?? new Set(['completed']);\n const unmet: string[] = [];\n for (const depSlug of dependsOn) {\n const depPath = resolveAssignmentPath(projectDir, depSlug);\n if (!(await fileExists(depPath))) {\n unmet.push(`${depSlug} (file not found)`);\n continue;\n }\n const depContent = await readFile(depPath, 'utf-8');\n const depFrontmatter = parseAssignmentFrontmatter(depContent);\n if (!terminals.has(depFrontmatter.status)) {\n unmet.push(`${depSlug} (status: ${depFrontmatter.status})`);\n }\n }\n return { satisfied: unmet.length === 0, unmet };\n}\n\nexport interface TransitionOptions {\n reason?: string;\n agent?: string;\n transitionTable?: Map<string, string>;\n terminalStatuses?: ReadonlySet<string>;\n /**\n * When provided, on a transition to `completed` we scan the configured todos\n * dirs and auto-complete any todo whose `linkedAssignmentId` matches this\n * assignment's UUID. On `reopen` we auto-reopen any such todo whose most\n * recent log entry is the auto-complete marker (manual completions are left\n * untouched).\n */\n linkedTodosLookup?: LinkedTodosLookup;\n}\n\nconst ASSIGNEE_SETTING_COMMANDS = new Set(['start', 'shape', 'plan-ready', 'implement']);\n\nexport async function executeTransition(\n projectDir: string,\n assignmentSlug: string,\n command: Exclude<TransitionCommand, 'assign'>,\n options: TransitionOptions = {},\n): Promise<TransitionResult> {\n const filePath = resolveAssignmentPath(projectDir, assignmentSlug);\n const { content, frontmatter } = await readAssignment(filePath);\n\n const targetStatus = getTargetStatus(frontmatter.status, command, options.transitionTable);\n\n if (!targetStatus) {\n return {\n success: false,\n message: `Unknown command '${command}' for assignment \"${assignmentSlug}\".`,\n fromStatus: frontmatter.status,\n };\n }\n\n const warnings: string[] = [];\n\n if (command === 'start' && frontmatter.dependsOn.length > 0) {\n const depCheck = await checkDependencies(projectDir, frontmatter.dependsOn, options.terminalStatuses);\n if (!depCheck.satisfied) {\n warnings.push(`Starting with unmet dependencies: ${depCheck.unmet.join(', ')}`);\n }\n }\n\n const updates: Partial<Pick<AssignmentFrontmatter, 'status' | 'assignee' | 'blockedReason' | 'updated'>> = {\n status: targetStatus,\n updated: nowTimestamp(),\n };\n\n if (ASSIGNEE_SETTING_COMMANDS.has(command) && options.agent && !frontmatter.assignee) {\n updates.assignee = options.agent;\n }\n if (command === 'block') {\n updates.blockedReason = options.reason ?? null;\n }\n if (command === 'unblock') {\n updates.blockedReason = null;\n }\n\n const updatedContent = updateAssignmentFile(content, updates);\n await writeFileForce(filePath, updatedContent);\n\n await applyLinkedTodosSideEffect(options.linkedTodosLookup, command, targetStatus, frontmatter);\n\n return {\n success: true,\n message: `Assignment \"${assignmentSlug}\" transitioned: ${frontmatter.status} -> ${targetStatus}`,\n fromStatus: frontmatter.status,\n toStatus: targetStatus,\n warnings: warnings.length > 0 ? warnings : undefined,\n };\n}\n\nexport async function executeAssign(\n projectDir: string,\n assignmentSlug: string,\n agent: string,\n): Promise<TransitionResult> {\n const filePath = resolveAssignmentPath(projectDir, assignmentSlug);\n const { content, frontmatter } = await readAssignment(filePath);\n\n const updates: Partial<Pick<AssignmentFrontmatter, 'status' | 'assignee' | 'blockedReason' | 'updated'>> = {\n assignee: agent,\n updated: nowTimestamp(),\n };\n\n const updatedContent = updateAssignmentFile(content, updates);\n await writeFileForce(filePath, updatedContent);\n\n return {\n success: true,\n message: `Assignment \"${assignmentSlug}\" assigned to '${agent}'.`,\n fromStatus: frontmatter.status,\n };\n}\n\nexport interface TransitionByDirOptions extends TransitionOptions {\n standalone?: boolean;\n}\n\nexport async function executeTransitionByDir(\n assignmentDir: string,\n command: Exclude<TransitionCommand, 'assign'>,\n options: TransitionByDirOptions = {},\n): Promise<TransitionResult> {\n const filePath = resolve(assignmentDir, 'assignment.md');\n const { content, frontmatter } = await readAssignment(filePath);\n\n const targetStatus = getTargetStatus(frontmatter.status, command, options.transitionTable);\n if (!targetStatus) {\n return {\n success: false,\n message: `Unknown command '${command}' for assignment \"${frontmatter.slug || assignmentDir}\".`,\n fromStatus: frontmatter.status,\n };\n }\n\n const warnings: string[] = [];\n\n if (command === 'start' && !options.standalone && frontmatter.dependsOn.length > 0) {\n // Dependency check requires a project context — skip for standalone\n const projectDir = resolve(assignmentDir, '..', '..');\n const depCheck = await checkDependencies(\n projectDir,\n frontmatter.dependsOn,\n options.terminalStatuses,\n );\n if (!depCheck.satisfied) {\n warnings.push(`Starting with unmet dependencies: ${depCheck.unmet.join(', ')}`);\n }\n }\n\n const updates: Partial<Pick<AssignmentFrontmatter, 'status' | 'assignee' | 'blockedReason' | 'updated'>> = {\n status: targetStatus,\n updated: nowTimestamp(),\n };\n\n if (ASSIGNEE_SETTING_COMMANDS.has(command) && options.agent && !frontmatter.assignee) {\n updates.assignee = options.agent;\n }\n if (command === 'block') {\n updates.blockedReason = options.reason ?? null;\n }\n if (command === 'unblock') {\n updates.blockedReason = null;\n }\n\n const updatedContent = updateAssignmentFile(content, updates);\n await writeFileForce(filePath, updatedContent);\n\n await applyLinkedTodosSideEffect(options.linkedTodosLookup, command, targetStatus, frontmatter);\n\n return {\n success: true,\n message: `Assignment \"${frontmatter.slug || assignmentDir}\" transitioned: ${frontmatter.status} -> ${targetStatus}`,\n fromStatus: frontmatter.status,\n toStatus: targetStatus,\n warnings: warnings.length > 0 ? warnings : undefined,\n };\n}\n\nexport async function executeAssignByDir(\n assignmentDir: string,\n agent: string,\n): Promise<TransitionResult> {\n const filePath = resolve(assignmentDir, 'assignment.md');\n const { content, frontmatter } = await readAssignment(filePath);\n\n const updates: Partial<Pick<AssignmentFrontmatter, 'status' | 'assignee' | 'blockedReason' | 'updated'>> = {\n assignee: agent,\n updated: nowTimestamp(),\n };\n\n const updatedContent = updateAssignmentFile(content, updates);\n await writeFileForce(filePath, updatedContent);\n\n return {\n success: true,\n message: `Assignment \"${frontmatter.slug || assignmentDir}\" assigned to '${agent}'.`,\n fromStatus: frontmatter.status,\n };\n}\n","export type {\n AssignmentStatus,\n TransitionCommand,\n AssignmentFrontmatter,\n ExternalId,\n Workspace,\n TransitionResult,\n} from './types.js';\nexport { TERMINAL_STATUSES, DEFAULT_STATUSES, DEFAULT_COMMANDS, DEFAULT_TERMINAL_STATUSES } from './types.js';\nexport { canTransition, getTargetStatus, isTerminalStatus, DEFAULT_TRANSITION_TABLE, DEFAULT_COMMAND_TARGETS, buildTransitionTable, buildCommandTargets } from './state-machine.js';\nexport { parseAssignmentFrontmatter, updateAssignmentFile, updateAssignmentWorkspace } from './frontmatter.js';\nexport { executeTransition, executeAssign, executeTransitionByDir, executeAssignByDir } from './transitions.js';\nexport type { TransitionOptions, TransitionByDirOptions } from './transitions.js';\n","export interface ConfigParams {\n defaultProjectDir: string;\n}\n\nexport function renderConfig(params: ConfigParams): string {\n return `---\nversion: \"1.0\"\ndefaultProjectDir: ${params.defaultProjectDir}\nonboarding:\n completed: false\nagentDefaults:\n trustLevel: medium\n autoApprove: false\nbackup:\n repo: null\n categories: projects, playbooks, todos, servers, config\n lastBackup: null\n lastRestore: null\n---\n\n# Syntaur Configuration\n\nGlobal configuration for the Syntaur CLI.\n`;\n}\n","import { readdir, readFile, rename, writeFile } from 'node:fs/promises';\nimport type { Dirent } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { fileExists } from './fs.js';\n\n/**\n * Filesystem-level migrations for users upgrading from pre-v0.2.0 installs,\n * where the product used \"mission\" terminology. v0.2.0 renamed code but\n * shipped no on-disk migration, leaving user state unreadable by the new\n * scanner. These helpers close that gap.\n *\n * All helpers are idempotent, safe on missing paths, and NEVER delete user\n * files. Legacy files that are no longer read (e.g., per-project agent.md,\n * claude.md) are left untouched.\n */\n\nexport interface ProjectFilesMigrationResult {\n /** Relative paths of files that were renamed (e.g. `ai-chat-v2/mission.md`). */\n renamedProjectFiles: string[];\n /** Project slugs that still have stale agent.md / claude.md files. Reported, not deleted. */\n legacyExtras: string[];\n}\n\nexport interface ConfigMigrationResult {\n /** True if `defaultMissionDir` was renamed to `defaultProjectDir`. */\n renamedField: boolean;\n /** True if the on-disk `<root>/missions` dir was renamed to `<root>/projects`. */\n renamedDir: boolean;\n /** The resolved projects dir after migration (absolute, or null if config absent). */\n resolvedProjectsDir: string | null;\n}\n\n/**\n * Walk each project directory under `projectsDir` and rename\n * `mission.md` → `project.md` when the legacy file is present and the new\n * name isn't. Reports stale per-project `agent.md` / `claude.md` files\n * without touching them.\n *\n * Swallows per-entry errors (e.g., EPERM on a single dir) so one bad\n * project can't block the rest. Never throws.\n */\nexport async function migrateLegacyProjectFiles(\n projectsDir: string,\n): Promise<ProjectFilesMigrationResult> {\n const result: ProjectFilesMigrationResult = {\n renamedProjectFiles: [],\n legacyExtras: [],\n };\n\n if (!(await fileExists(projectsDir))) return result;\n\n let entries: Dirent[];\n try {\n entries = (await readdir(projectsDir, { withFileTypes: true })) as Dirent[];\n } catch {\n return result;\n }\n\n for (const entry of entries) {\n if (!entry.isDirectory() || entry.name.startsWith('.')) continue;\n\n const projectDir = resolve(projectsDir, entry.name);\n const legacy = resolve(projectDir, 'mission.md');\n const target = resolve(projectDir, 'project.md');\n\n try {\n if ((await fileExists(legacy)) && !(await fileExists(target))) {\n await rename(legacy, target);\n result.renamedProjectFiles.push(`${entry.name}/mission.md`);\n }\n } catch {\n // Swallow per-project errors (permission denied, racing editor, etc).\n continue;\n }\n\n // Surface stale legacy files without deleting them — caller decides how\n // to present (log once at startup).\n for (const stale of ['agent.md', 'claude.md']) {\n try {\n if (await fileExists(resolve(projectDir, stale))) {\n result.legacyExtras.push(`${entry.name}/${stale}`);\n }\n } catch {\n // Ignore.\n }\n }\n }\n\n return result;\n}\n\n/**\n * Migrate ~/.syntaur/config.md frontmatter and, optionally, the on-disk\n * projects directory, from the pre-v0.2.0 \"mission\" layout.\n *\n * - Renames `defaultMissionDir` → `defaultProjectDir` in frontmatter when\n * the new key isn't already present.\n * - If the resolved projects dir ends in `/missions` AND that dir exists\n * AND its `/projects` sibling does not, renames the directory on disk\n * and updates the config to point at the new path.\n *\n * Only rewrites the config file when an actual change is made.\n */\nexport async function migrateLegacyConfig(\n configPath: string,\n): Promise<ConfigMigrationResult> {\n const result: ConfigMigrationResult = {\n renamedField: false,\n renamedDir: false,\n resolvedProjectsDir: null,\n };\n\n if (!(await fileExists(configPath))) return result;\n\n let content: string;\n try {\n content = await readFile(configPath, 'utf-8');\n } catch {\n return result;\n }\n\n const fmMatch = content.match(/^---\\n([\\s\\S]*?)\\n---\\n?/);\n if (!fmMatch) return result;\n\n const fmBlock = fmMatch[1];\n const afterFm = content.slice(fmMatch[0].length);\n\n // --- Field rename ---\n const missionLineRe = /^(\\s*)defaultMissionDir\\s*:\\s*(.*)$/m;\n const missionLineMatch = fmBlock.match(missionLineRe);\n const hasProjectLine = /^\\s*defaultProjectDir\\s*:/m.test(fmBlock);\n\n let newFmBlock = fmBlock;\n let missionValue: string | null = null;\n if (missionLineMatch) {\n missionValue = missionLineMatch[2].trim();\n if (!hasProjectLine) {\n newFmBlock = fmBlock.replace(\n missionLineRe,\n `$1defaultProjectDir: ${missionValue}`,\n );\n result.renamedField = true;\n } else {\n // Both keys present; strip the legacy one to avoid drift.\n newFmBlock = fmBlock.replace(missionLineRe, '').replace(/\\n{2,}/g, '\\n');\n result.renamedField = true;\n }\n }\n\n // --- Resolve the current projects dir from whatever the frontmatter says. ---\n const projectLineRe = /^\\s*defaultProjectDir\\s*:\\s*(.*)$/m;\n const projectLineMatch = newFmBlock.match(projectLineRe);\n const projectsDirRaw = projectLineMatch\n ? projectLineMatch[1].trim().replace(/^['\"]|['\"]$/g, '')\n : missionValue;\n\n const expand = (p: string): string =>\n p.startsWith('~')\n ? resolve(process.env.HOME ?? '/', p.slice(p.startsWith('~/') ? 2 : 1))\n : p;\n\n let resolvedProjectsDir = projectsDirRaw ? expand(projectsDirRaw) : null;\n\n // --- Directory rename (only if the value still points at a /missions dir). ---\n if (resolvedProjectsDir && resolvedProjectsDir.endsWith('/missions')) {\n const siblingProjectsDir = resolvedProjectsDir.replace(/\\/missions$/, '/projects');\n if (\n (await fileExists(resolvedProjectsDir)) &&\n !(await fileExists(siblingProjectsDir))\n ) {\n try {\n await rename(resolvedProjectsDir, siblingProjectsDir);\n // Update the config line to point at the new dir. Preserve any ~ prefix.\n const newValue = projectsDirRaw!.endsWith('/missions')\n ? projectsDirRaw!.replace(/\\/missions$/, '/projects')\n : siblingProjectsDir;\n newFmBlock = newFmBlock.replace(\n projectLineRe,\n `defaultProjectDir: ${newValue}`,\n );\n resolvedProjectsDir = siblingProjectsDir;\n result.renamedDir = true;\n } catch {\n // If rename fails (permissions, cross-device), leave both config and\n // filesystem alone. Scanner will still hit the legacy dir.\n }\n }\n }\n\n result.resolvedProjectsDir = resolvedProjectsDir;\n\n if (result.renamedField || result.renamedDir) {\n const newContent = `---\\n${newFmBlock.replace(/\\n+$/, '')}\\n---\\n${afterFm.startsWith('\\n') ? afterFm.slice(1) : afterFm}`;\n try {\n await writeFile(configPath, newContent, 'utf-8');\n } catch {\n // If we can't persist the config, revert the flags so the caller\n // doesn't report a fake success.\n result.renamedField = false;\n result.renamedDir = false;\n }\n }\n\n return result;\n}\n\n/**\n * Format a concise summary line for startup logs. Empty string when nothing\n * material happened (caller should skip the log).\n */\nexport function summarizeMigration(\n project: ProjectFilesMigrationResult,\n config?: ConfigMigrationResult,\n): string {\n const parts: string[] = [];\n if (project.renamedProjectFiles.length > 0) {\n const firstThree = project.renamedProjectFiles\n .map((p) => p.split('/')[0])\n .slice(0, 3)\n .join(', ');\n const more =\n project.renamedProjectFiles.length > 3\n ? ` and ${project.renamedProjectFiles.length - 3} more`\n : '';\n parts.push(\n `renamed mission.md → project.md in ${project.renamedProjectFiles.length} project${project.renamedProjectFiles.length === 1 ? '' : 's'} (${firstThree}${more})`,\n );\n }\n if (config?.renamedField) parts.push('updated config defaultMissionDir → defaultProjectDir');\n if (config?.renamedDir) parts.push('renamed projects directory on disk');\n if (project.legacyExtras.length > 0) {\n parts.push(\n `${project.legacyExtras.length} legacy agent.md / claude.md file${project.legacyExtras.length === 1 ? '' : 's'} left in place (no longer read)`,\n );\n }\n return parts.length ? `[syntaur] legacy migration: ${parts.join('; ')}` : '';\n}\n","// Shared hotkey catalog: bindable action kinds, reserved combos, and the\n// canonical combo string format. Imported directly by the Express server\n// (src/dashboard/server.ts) and by the dashboard via the\n// `@shared/hotkeys-catalog` alias defined in dashboard/tsconfig.json +\n// dashboard/vite.config.ts.\n\nexport type BindableActionKind =\n | 'new-workspace'\n | 'new-project'\n | 'new-todo'\n | 'new-assignment';\n\nexport const BINDABLE_ACTION_KINDS: readonly BindableActionKind[] = [\n 'new-workspace',\n 'new-project',\n 'new-todo',\n 'new-assignment',\n];\n\nexport function isBindableActionKind(value: unknown): value is BindableActionKind {\n return (\n typeof value === 'string' &&\n (BINDABLE_ACTION_KINDS as readonly string[]).includes(value)\n );\n}\n\n// Reserved combos that user-bound hotkeys may NOT shadow. Hand-maintained;\n// scripts/check-hotkey-catalog.ts greps `useHotkey({` across the dashboard and\n// fails if it sees a `keys` value that is not represented here.\n//\n// Combos are stored in canonical form (see canonicalizeCombo). The list\n// includes:\n// - global UI combos (Mod+k, Mod+Shift+k, ?, Escape, Enter, Shift+t)\n// - g <suffix> chord prefixes (the lone \"g\" is reserved as a chord starter)\n// - list-scope letters\n// - page-scoped shortcuts that exist when those pages are mounted\nexport const BUILTIN_RESERVED_COMBOS: readonly string[] = [\n 'mod+k',\n 'mod+shift+k',\n '?',\n 'escape',\n 'enter',\n 'shift+t',\n // g-chord starter + suffixes\n 'g',\n 'g o',\n 'g m',\n 'g a',\n 'g t',\n 'g s',\n 'g !',\n 'g ,',\n // list-scope navigation\n 'j',\n 'k',\n 'o',\n // ProjectDetail page\n 'a',\n 'e',\n // AssignmentsPage board\n '/',\n 'r',\n // AssignmentDetail page\n 'p',\n 'h',\n 'd',\n 's',\n '[',\n ']',\n];\n\nconst MODIFIER_ORDER: readonly string[] = ['mod', 'ctrl', 'alt', 'shift'];\n\n/**\n * Canonicalize a combo string for storage and comparison.\n *\n * - Trims whitespace.\n * - Splits on `+` for single-key combos; preserves space-separated chord form\n * (e.g. `g a`) by canonicalizing each part independently.\n * - Lowercases everything (modifiers and the trailing key alike).\n * - Reorders modifiers into canonical order: mod, ctrl, alt, shift.\n *\n * Examples:\n * canonicalizeCombo(\"Shift+Mod+K\") -> \"mod+shift+k\"\n * canonicalizeCombo(\" cmd + Enter\") -> \"mod+enter\" (after caller maps cmd->mod)\n * canonicalizeCombo(\"g A\") -> \"g a\"\n * canonicalizeCombo(\"?\") -> \"?\"\n */\nexport function canonicalizeCombo(input: string): string {\n if (typeof input !== 'string') return '';\n const trimmed = input.trim();\n if (!trimmed) return '';\n\n // Chord form: space-separated, no `+` separators (e.g. \"g a\"). When the\n // input contains `+` it's treated as a single combo even if it has stray\n // whitespace around the separators (e.g. \"Mod + K\").\n if (/\\s/.test(trimmed) && !trimmed.includes('+')) {\n return trimmed\n .split(/\\s+/)\n .map(canonicalizeCombo)\n .filter((part) => part.length > 0)\n .join(' ');\n }\n\n const parts = trimmed.split('+').map((p) => p.trim()).filter((p) => p.length > 0);\n if (parts.length === 0) return '';\n if (parts.length === 1) {\n return parts[0].toLowerCase();\n }\n\n const key = parts[parts.length - 1].toLowerCase();\n const mods = parts.slice(0, -1).map((m) => m.toLowerCase());\n\n const seen = new Set<string>();\n const ordered: string[] = [];\n for (const m of MODIFIER_ORDER) {\n if (mods.includes(m) && !seen.has(m)) {\n ordered.push(m);\n seen.add(m);\n }\n }\n // Append any non-standard modifiers at the end (preserves user intent for\n // anything we don't recognize).\n for (const m of mods) {\n if (!seen.has(m)) {\n ordered.push(m);\n seen.add(m);\n }\n }\n\n return [...ordered, key].join('+');\n}\n\n/**\n * Returns true when `combo` (canonicalized) collides with a built-in reserved\n * combo. Server-side enforcement entry point.\n */\nexport function isReservedCombo(combo: string): boolean {\n const c = canonicalizeCombo(combo);\n if (!c) return false;\n return (BUILTIN_RESERVED_COMBOS as readonly string[]).includes(c);\n}\n\n/**\n * Default hotkey bindings shipped with the dashboard. The triple-modifier\n * `Mod+Shift+Alt+<letter>` namespace is intentionally chosen to avoid common\n * browser shortcuts (Cmd+Shift+T reopens closed tab, Cmd+Shift+P opens\n * private mode, Cmd+Shift+W closes window, etc.) while keeping the action\n * mnemonic. Users can override any of these from Settings → Hotkey Bindings.\n *\n * These are EFFECTIVE only when the user has not bound a custom combo for\n * that action — `effectiveBindings()` overlays the user's custom bindings on\n * top, so a custom binding always wins.\n */\nexport const DEFAULT_BINDABLE_HOTKEYS: Readonly<Record<BindableActionKind, string>> = {\n 'new-workspace': canonicalizeCombo('Mod+Shift+Alt+w'),\n 'new-project': canonicalizeCombo('Mod+Shift+Alt+p'),\n 'new-todo': canonicalizeCombo('Mod+Shift+Alt+t'),\n 'new-assignment': canonicalizeCombo('Mod+Shift+Alt+a'),\n};\n\n/**\n * Returns the effective binding map: defaults underneath, user customs on top.\n * A user-bound combo always wins; if the user has no entry for a kind, the\n * default is returned (if any).\n */\nexport function effectiveBindings(\n custom: Partial<Record<BindableActionKind, string>>,\n): Partial<Record<BindableActionKind, string>> {\n const out: Partial<Record<BindableActionKind, string>> = {\n ...DEFAULT_BINDABLE_HOTKEYS,\n };\n for (const kind of BINDABLE_ACTION_KINDS) {\n const override = custom[kind];\n if (typeof override === 'string' && override.length > 0) {\n out[kind] = override;\n }\n }\n return out;\n}\n\n/** True when the given kind currently uses its default combo (no user override). */\nexport function isDefaultBinding(\n custom: Partial<Record<BindableActionKind, string>>,\n kind: BindableActionKind,\n): boolean {\n const override = custom[kind];\n return typeof override !== 'string' || override.length === 0;\n}\n","export type PromptArgPosition = 'first' | 'last' | 'none';\n\n/**\n * Per-agent argv recipe for continuing a recorded session in a specific mode.\n *\n * `args` is a literal argv list with the substring `{id}` substituted for the\n * agent's session id at launch time. `command` overrides the agent's main\n * `command` field — used by subcommand-style agents (e.g. `codex resume <id>`\n * is documented as command=codex, args=['resume','{id}']; the override exists\n * for future agents whose subcommand binary differs).\n */\nexport interface SessionInvocation {\n command?: string;\n args: string[];\n}\n\nexport interface AgentConfig {\n id: string;\n label: string;\n command: string;\n args?: string[];\n promptArgPosition?: PromptArgPosition;\n default?: boolean;\n resolveFromShellAliases?: boolean;\n resume?: SessionInvocation;\n fork?: SessionInvocation;\n}\n\nexport const BUILTIN_AGENTS: AgentConfig[] = [\n {\n id: 'claude',\n label: 'Claude',\n command: 'claude',\n default: true,\n resume: { args: ['--resume', '{id}'] },\n fork: { args: ['--resume', '{id}', '--fork-session'] },\n },\n {\n id: 'codex',\n label: 'Codex',\n command: 'codex',\n resume: { args: ['resume', '{id}'] },\n fork: { args: ['fork', '{id}'] },\n },\n];\n\nexport const AGENT_ID_PATTERN = /^[a-z0-9][a-z0-9_-]*$/;\nexport const PROMPT_ARG_POSITIONS: readonly PromptArgPosition[] = ['first', 'last', 'none'];\n","export type TerminalChoice =\n | 'terminal-app'\n | 'iterm'\n | 'ghostty'\n | 'alacritty'\n | 'warp'\n | 'kitty';\n\nexport const TERMINAL_CHOICES: readonly TerminalChoice[] = [\n 'terminal-app',\n 'iterm',\n 'ghostty',\n 'alacritty',\n 'warp',\n 'kitty',\n];\n","import { readFile } from 'node:fs/promises';\nimport { spawnSync } from 'node:child_process';\nimport { resolve, isAbsolute } from 'node:path';\nimport { syntaurRoot, defaultProjectDir, expandHome } from './paths.js';\nimport { fileExists, writeFileForce } from './fs.js';\nimport { renderConfig } from '../templates/config.js';\nimport { migrateLegacyConfig } from './fs-migration.js';\nimport {\n BINDABLE_ACTION_KINDS,\n canonicalizeCombo,\n isBindableActionKind,\n isReservedCombo,\n type BindableActionKind,\n} from './hotkeysCatalog.js';\nimport {\n AGENT_ID_PATTERN,\n BUILTIN_AGENTS,\n PROMPT_ARG_POSITIONS,\n type AgentConfig,\n type PromptArgPosition,\n type SessionInvocation,\n} from './agents-schema.js';\n\nexport {\n AGENT_ID_PATTERN,\n BUILTIN_AGENTS,\n PROMPT_ARG_POSITIONS,\n type AgentConfig,\n type PromptArgPosition,\n type SessionInvocation,\n};\n\nexport interface StatusDefinition {\n id: string;\n label: string;\n description?: string;\n color?: string;\n icon?: string;\n terminal?: boolean;\n}\n\nexport interface StatusTransition {\n from: string;\n command: string;\n to: string;\n label?: string;\n description?: string;\n requiresReason?: boolean;\n}\n\nexport interface StatusConfig {\n statuses: StatusDefinition[];\n order: string[];\n transitions: StatusTransition[];\n}\n\nexport interface TypeDefinition {\n id: string;\n label?: string;\n description?: string;\n color?: string;\n icon?: string;\n}\n\nexport interface TypesConfig {\n definitions: TypeDefinition[];\n default: string;\n}\n\nexport const DEFAULT_ASSIGNMENT_TYPES: TypesConfig = {\n definitions: [\n { id: 'feature', label: 'Feature' },\n { id: 'bug', label: 'Bug' },\n { id: 'refactor', label: 'Refactor' },\n { id: 'research', label: 'Research' },\n { id: 'chore', label: 'Chore' },\n ],\n default: 'feature',\n};\n\nexport interface IntegrationConfig {\n claudePluginDir: string | null;\n codexPluginDir: string | null;\n codexMarketplacePath: string | null;\n}\n\nexport interface OnboardingConfig {\n completed: boolean;\n}\n\nexport interface BackupConfig {\n repo: string | null;\n categories: string;\n lastBackup: string | null;\n lastRestore: string | null;\n}\n\nexport type AutoCreateWorktree = 'skip' | 'ask' | 'always';\n\nexport interface PlaybooksConfig {\n disabled: string[];\n}\n\nexport interface ThemeConfig {\n preset: string;\n}\n\nexport interface HotkeyBindingsConfig {\n bindings: Partial<Record<BindableActionKind, string>>;\n}\n\nimport { TERMINAL_CHOICES, type TerminalChoice } from './terminal-schema.js';\nexport { TERMINAL_CHOICES, type TerminalChoice };\n\nexport interface SyntaurConfig {\n version: string;\n defaultProjectDir: string;\n onboarding: OnboardingConfig;\n agentDefaults: {\n trustLevel: 'low' | 'medium' | 'high';\n autoApprove: boolean;\n autoCreateWorktree: AutoCreateWorktree;\n };\n integrations: IntegrationConfig;\n backup: BackupConfig | null;\n statuses: StatusConfig | null;\n types: TypesConfig | null;\n agents: AgentConfig[] | null;\n playbooks: PlaybooksConfig;\n theme: ThemeConfig | null;\n hotkeys: HotkeyBindingsConfig | null;\n terminal: TerminalChoice | null;\n}\n\nconst DEFAULT_CONFIG: SyntaurConfig = {\n version: '2.0',\n defaultProjectDir: defaultProjectDir(),\n onboarding: {\n completed: false,\n },\n agentDefaults: {\n trustLevel: 'medium',\n autoApprove: false,\n autoCreateWorktree: 'ask',\n },\n integrations: {\n claudePluginDir: null,\n codexPluginDir: null,\n codexMarketplacePath: null,\n },\n backup: null,\n statuses: null,\n types: null,\n agents: null,\n playbooks: {\n disabled: [],\n },\n theme: null,\n hotkeys: null,\n terminal: null,\n};\n\nconst AUTO_CREATE_WORKTREE_VALUES: readonly AutoCreateWorktree[] = ['skip', 'ask', 'always'];\n\nexport class AgentConfigError extends Error {}\n\n/**\n * Validate an agent command string.\n * - Absolute paths (after ~ expansion) are accepted verbatim.\n * - Bare names (no \"/\" after expansion) are accepted for PATH lookup at launch time.\n * - Relative paths (contain \"/\" but not absolute) are rejected.\n */\nexport function parseAgentCommand(value: string, agentId?: string): string {\n if (typeof value !== 'string' || value.trim() === '') {\n throw new AgentConfigError(\n `agent${agentId ? ` \"${agentId}\"` : ''} has empty command`,\n );\n }\n const expanded = expandHome(value.trim());\n if (isAbsolute(expanded)) {\n return resolve(expanded);\n }\n if (expanded.includes('/')) {\n throw new AgentConfigError(\n `agent${agentId ? ` \"${agentId}\"` : ''} command \"${value}\" is a relative path — use an absolute path or a bare binary name`,\n );\n }\n return expanded;\n}\n\nexport function validateAgentList(agents: AgentConfig[]): void {\n const seen = new Set<string>();\n let defaults = 0;\n for (const agent of agents) {\n if (!AGENT_ID_PATTERN.test(agent.id)) {\n throw new AgentConfigError(\n `agent id \"${agent.id}\" is invalid — must match /^[a-z0-9][a-z0-9_-]*$/`,\n );\n }\n if (seen.has(agent.id)) {\n throw new AgentConfigError(`duplicate agent id \"${agent.id}\"`);\n }\n seen.add(agent.id);\n if (!agent.label || agent.label.trim() === '') {\n throw new AgentConfigError(`agent \"${agent.id}\" has empty label`);\n }\n parseAgentCommand(agent.command, agent.id);\n if (\n agent.promptArgPosition !== undefined &&\n !PROMPT_ARG_POSITIONS.includes(agent.promptArgPosition)\n ) {\n throw new AgentConfigError(\n `agent \"${agent.id}\" has invalid promptArgPosition \"${agent.promptArgPosition}\" — expected first|last|none`,\n );\n }\n validateSessionInvocation(agent, 'resume', agent.resume);\n validateSessionInvocation(agent, 'fork', agent.fork);\n if (agent.default) defaults++;\n }\n if (defaults > 1) {\n throw new AgentConfigError(\n `more than one agent is marked default: true (only one is allowed)`,\n );\n }\n}\n\nfunction validateSessionInvocation(\n agent: AgentConfig,\n mode: 'resume' | 'fork',\n invocation: SessionInvocation | undefined,\n): void {\n if (invocation === undefined) return;\n if (!Array.isArray(invocation.args)) {\n throw new AgentConfigError(\n `agent \"${agent.id}\" ${mode}.args must be an array of strings`,\n );\n }\n for (const a of invocation.args) {\n if (typeof a !== 'string') {\n throw new AgentConfigError(\n `agent \"${agent.id}\" ${mode}.args must contain only strings`,\n );\n }\n }\n if (\n invocation.command !== undefined &&\n (typeof invocation.command !== 'string' || invocation.command.trim() === '')\n ) {\n throw new AgentConfigError(\n `agent \"${agent.id}\" ${mode}.command must be a non-empty string when present`,\n );\n }\n}\n\nfunction cloneDefaultConfig(): SyntaurConfig {\n return {\n ...DEFAULT_CONFIG,\n onboarding: { ...DEFAULT_CONFIG.onboarding },\n agentDefaults: { ...DEFAULT_CONFIG.agentDefaults },\n integrations: { ...DEFAULT_CONFIG.integrations },\n backup: DEFAULT_CONFIG.backup ? { ...DEFAULT_CONFIG.backup } : null,\n statuses: DEFAULT_CONFIG.statuses\n ? {\n statuses: DEFAULT_CONFIG.statuses.statuses.map((s) => ({ ...s })),\n order: [...DEFAULT_CONFIG.statuses.order],\n transitions: DEFAULT_CONFIG.statuses.transitions.map((t) => ({ ...t })),\n }\n : null,\n types: DEFAULT_CONFIG.types\n ? {\n definitions: DEFAULT_CONFIG.types.definitions.map((d) => ({ ...d })),\n default: DEFAULT_CONFIG.types.default,\n }\n : null,\n agents: DEFAULT_CONFIG.agents\n ? DEFAULT_CONFIG.agents.map((a) => ({\n ...a,\n ...(a.args ? { args: [...a.args] } : {}),\n ...(a.resume ? { resume: { ...a.resume, args: [...a.resume.args] } } : {}),\n ...(a.fork ? { fork: { ...a.fork, args: [...a.fork.args] } } : {}),\n }))\n : null,\n playbooks: {\n disabled: [...DEFAULT_CONFIG.playbooks.disabled],\n },\n theme: DEFAULT_CONFIG.theme ? { ...DEFAULT_CONFIG.theme } : null,\n hotkeys: DEFAULT_CONFIG.hotkeys\n ? { bindings: { ...DEFAULT_CONFIG.hotkeys.bindings } }\n : null,\n terminal: DEFAULT_CONFIG.terminal,\n };\n}\n\nfunction parseFrontmatter(content: string): Record<string, string> {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return {};\n const result: Record<string, string> = {};\n const lines = match[1].split('\\n');\n let currentParent: string | null = null;\n for (const line of lines) {\n if (line.trim() === '') continue;\n const indent = line.length - line.trimStart().length;\n const colonIndex = line.indexOf(':');\n if (colonIndex < 0) continue;\n const key = line.slice(0, colonIndex).trim();\n const value = line.slice(colonIndex + 1).trim();\n if (indent === 0) {\n if (value === '' || value === undefined) {\n currentParent = key;\n } else {\n currentParent = null;\n result[key] = value.replace(/^[\"']|[\"']$/g, '');\n }\n } else if (indent > 0 && currentParent) {\n result[`${currentParent}.${key}`] = value.replace(/^[\"']|[\"']$/g, '');\n }\n }\n return result;\n}\n\nfunction parseStatusConfig(content: string): StatusConfig | null {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return null;\n const fmBlock = match[1];\n\n // Check if there's a top-level statuses: section\n const statusesStart = fmBlock.match(/^statuses:\\s*$/m);\n if (!statusesStart) return null;\n\n // Extract the statuses block (everything indented after \"statuses:\")\n const startIdx = fmBlock.indexOf(statusesStart[0]) + statusesStart[0].length;\n const remaining = fmBlock.slice(startIdx);\n\n const statuses: StatusDefinition[] = [];\n const order: string[] = [];\n const transitions: StatusTransition[] = [];\n\n // Parse sub-sections: definitions, order, transitions\n let currentSection: 'definitions' | 'order' | 'transitions' | null = null;\n const lines = remaining.split('\\n');\n\n function parseListEntry(lineIdx: number, baseIndent: number): { entry: Record<string, string>; consumed: number } {\n const entry: Record<string, string> = {};\n const firstLine = lines[lineIdx].trimStart().slice(2).trim();\n const colonIdx = firstLine.indexOf(':');\n if (colonIdx > 0) {\n entry[firstLine.slice(0, colonIdx).trim()] = firstLine.slice(colonIdx + 1).trim();\n }\n let consumed = 1;\n for (let i = lineIdx + 1; i < lines.length; i++) {\n const next = lines[i];\n const nextTrimmed = next.trimStart();\n const nextIndent = next.length - nextTrimmed.length;\n if (nextIndent <= baseIndent || nextTrimmed.startsWith('- ')) break;\n const ci = nextTrimmed.indexOf(':');\n if (ci > 0) {\n entry[nextTrimmed.slice(0, ci).trim()] = nextTrimmed.slice(ci + 1).trim();\n }\n consumed++;\n }\n return { entry, consumed };\n }\n\n for (let lineIdx = 0; lineIdx < lines.length; lineIdx++) {\n const line = lines[lineIdx];\n const trimmed = line.trimStart();\n const indent = line.length - trimmed.length;\n\n // Top-level key under statuses (indent 2)\n if (indent === 2 && trimmed.endsWith(':')) {\n const key = trimmed.slice(0, -1).trim();\n if (key === 'definitions') currentSection = 'definitions';\n else if (key === 'order') currentSection = 'order';\n else if (key === 'transitions') currentSection = 'transitions';\n else currentSection = null;\n continue;\n }\n\n // Stop if we hit a new top-level key (no indent)\n if (indent === 0 && trimmed.includes(':')) break;\n\n if (currentSection === 'order' && indent >= 4 && trimmed.startsWith('- ')) {\n order.push(trimmed.slice(2).trim());\n continue;\n }\n\n if (currentSection === 'definitions' && indent >= 4 && trimmed.startsWith('- ')) {\n const { entry, consumed } = parseListEntry(lineIdx, indent);\n if (entry['id']) {\n statuses.push({\n id: entry['id'],\n label: entry['label'] ?? entry['id'],\n description: entry['description'],\n color: entry['color'],\n icon: entry['icon'],\n terminal: entry['terminal'] === 'true',\n });\n }\n lineIdx += consumed - 1; // skip consumed continuation lines\n continue;\n }\n\n if (currentSection === 'transitions' && indent >= 4 && trimmed.startsWith('- ')) {\n const { entry, consumed } = parseListEntry(lineIdx, indent);\n if (entry['from'] && entry['command'] && entry['to']) {\n transitions.push({\n from: entry['from'],\n command: entry['command'],\n to: entry['to'],\n label: entry['label'],\n description: entry['description'],\n requiresReason: entry['requiresReason'] === 'true',\n });\n }\n lineIdx += consumed - 1;\n continue;\n }\n }\n\n if (statuses.length === 0) return null;\n\n return {\n statuses,\n order: order.length > 0 ? order : statuses.map((s) => s.id),\n transitions,\n };\n}\n\nfunction serializeStatusConfig(statuses: StatusConfig): string {\n const lines: string[] = [];\n lines.push('statuses:');\n\n // definitions\n lines.push(' definitions:');\n for (const s of statuses.statuses) {\n lines.push(` - id: ${s.id}`);\n lines.push(` label: ${s.label}`);\n if (s.description) lines.push(` description: ${s.description}`);\n if (s.color) lines.push(` color: ${s.color}`);\n if (s.icon) lines.push(` icon: ${s.icon}`);\n if (s.terminal) lines.push(` terminal: true`);\n }\n\n // order\n lines.push(' order:');\n for (const id of statuses.order) {\n lines.push(` - ${id}`);\n }\n\n // transitions\n if (statuses.transitions.length > 0) {\n lines.push(' transitions:');\n for (const t of statuses.transitions) {\n lines.push(` - from: ${t.from}`);\n lines.push(` command: ${t.command}`);\n lines.push(` to: ${t.to}`);\n if (t.label) lines.push(` label: ${t.label}`);\n if (t.description) lines.push(` description: ${t.description}`);\n if (t.requiresReason) lines.push(` requiresReason: true`);\n }\n }\n\n return lines.join('\\n');\n}\n\nfunction serializeIntegrationConfig(integrations: IntegrationConfig): string | null {\n const lines: string[] = [];\n\n if (integrations.claudePluginDir) {\n lines.push(` claudePluginDir: ${integrations.claudePluginDir}`);\n }\n if (integrations.codexPluginDir) {\n lines.push(` codexPluginDir: ${integrations.codexPluginDir}`);\n }\n if (integrations.codexMarketplacePath) {\n lines.push(` codexMarketplacePath: ${integrations.codexMarketplacePath}`);\n }\n\n if (lines.length === 0) {\n return null;\n }\n\n return ['integrations:', ...lines].join('\\n');\n}\n\nfunction serializeOnboardingConfig(onboarding: OnboardingConfig): string {\n return ['onboarding:', ` completed: ${onboarding.completed ? 'true' : 'false'}`].join('\\n');\n}\n\nfunction serializeBackupConfig(backup: BackupConfig): string {\n const lines: string[] = ['backup:'];\n lines.push(` repo: ${backup.repo ?? 'null'}`);\n lines.push(` categories: ${backup.categories}`);\n lines.push(` lastBackup: ${backup.lastBackup ?? 'null'}`);\n lines.push(` lastRestore: ${backup.lastRestore ?? 'null'}`);\n return lines.join('\\n');\n}\n\nfunction serializePlaybooksConfig(playbooks: PlaybooksConfig): string | null {\n if (!playbooks.disabled || playbooks.disabled.length === 0) {\n return null;\n }\n const lines: string[] = ['playbooks:', ' disabled:'];\n for (const slug of playbooks.disabled) {\n lines.push(` - ${slug}`);\n }\n return lines.join('\\n');\n}\n\nfunction parsePlaybooksConfig(fmBlock: string): PlaybooksConfig {\n const blockStart = fmBlock.match(/^playbooks:\\s*$/m);\n if (!blockStart) {\n return { disabled: [] };\n }\n\n const startIdx = fmBlock.indexOf(blockStart[0]) + blockStart[0].length;\n const remaining = fmBlock.slice(startIdx).split('\\n');\n\n const disabled: string[] = [];\n let currentSection: 'disabled' | null = null;\n\n for (const line of remaining) {\n const trimmed = line.trimStart();\n const indent = line.length - trimmed.length;\n\n // End of playbooks block — next top-level key\n if (indent === 0 && trimmed.length > 0) break;\n\n if (trimmed === '') continue;\n\n if (indent === 2 && trimmed.startsWith('disabled:')) {\n currentSection = 'disabled';\n // Support inline form `disabled: []` — treat as empty list.\n const afterColon = trimmed.slice('disabled:'.length).trim();\n if (afterColon === '[]' || afterColon === '') {\n continue;\n }\n // Any other inline value is malformed; skip.\n continue;\n }\n\n if (currentSection === 'disabled' && indent >= 4 && trimmed.startsWith('- ')) {\n const raw = trimmed.slice(2).trim().replace(/^[\"']|[\"']$/g, '');\n if (raw.length === 0) continue;\n // Defer slug-format validation to callers via isValidSlug where needed;\n // here we only filter obviously invalid whitespace-containing entries.\n if (/\\s/.test(raw)) {\n console.warn(`Warning: config.md playbooks.disabled entry \"${raw}\" contains whitespace, ignoring`);\n continue;\n }\n disabled.push(raw);\n continue;\n }\n }\n\n return { disabled };\n}\n\nexport async function updatePlaybooksConfig(\n playbooks: Partial<PlaybooksConfig>,\n): Promise<void> {\n const configPath = resolve(syntaurRoot(), 'config.md');\n const current = (await readConfig()).playbooks;\n const nextPlaybooks: PlaybooksConfig = {\n disabled: Array.from(new Set(playbooks.disabled ?? current.disabled)),\n };\n\n const playbooksBlock = serializePlaybooksConfig(nextPlaybooks);\n const existing = await fileExists(configPath)\n ? await readFile(configPath, 'utf-8')\n : renderConfig({ defaultProjectDir: defaultProjectDir() });\n\n const fmMatch = existing.match(/^(---\\n)([\\s\\S]*?)\\n(---)/);\n if (!fmMatch) {\n const bodyBlock = playbooksBlock ? `${playbooksBlock}\\n` : '';\n const content = `---\\nversion: \"2.0\"\\ndefaultProjectDir: ${defaultProjectDir()}\\n${bodyBlock}---\\n${existing}`;\n await writeFileForce(configPath, content);\n return;\n }\n\n const fmBlock = fmMatch[2];\n const afterFrontmatter = existing.slice(fmMatch[0].length);\n const cleanedFm = stripTopLevelBlock(fmBlock, 'playbooks');\n const newFm = playbooksBlock\n ? `${cleanedFm}\\n${playbooksBlock}`.replace(/^\\n+/, '')\n : cleanedFm;\n const normalizedFm = newFm.replace(/\\n+$/, '');\n const newContent = `---\\n${normalizedFm}\\n---${afterFrontmatter}`;\n await writeFileForce(configPath, newContent);\n}\n\nfunction parseThemeConfig(content: string): ThemeConfig | null {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return null;\n const fmBlock = match[1];\n\n const blockStart = fmBlock.match(/^theme:\\s*$/m);\n if (!blockStart) return null;\n\n const startIdx = fmBlock.indexOf(blockStart[0]) + blockStart[0].length;\n const remaining = fmBlock.slice(startIdx).split('\\n');\n\n let preset: string | null = null;\n for (const line of remaining) {\n const trimmed = line.trimStart();\n const indent = line.length - trimmed.length;\n if (indent === 0 && trimmed.length > 0) break;\n if (trimmed === '') continue;\n if (indent === 2 && trimmed.startsWith('preset:')) {\n const value = trimmed.slice('preset:'.length).trim().replace(/^[\"']|[\"']$/g, '');\n if (value.length > 0) preset = value;\n }\n }\n\n if (!preset) return null;\n return { preset };\n}\n\nfunction serializeThemeConfig(theme: ThemeConfig): string {\n return ['theme:', ` preset: ${theme.preset}`].join('\\n');\n}\n\nexport async function writeThemeConfig(theme: ThemeConfig): Promise<void> {\n const configPath = resolve(syntaurRoot(), 'config.md');\n const themeBlock = serializeThemeConfig(theme);\n\n const existing = await fileExists(configPath)\n ? await readFile(configPath, 'utf-8')\n : renderConfig({ defaultProjectDir: defaultProjectDir() });\n\n const fmMatch = existing.match(/^(---\\n)([\\s\\S]*?)\\n(---)/);\n if (!fmMatch) {\n const content = `---\\nversion: \"2.0\"\\ndefaultProjectDir: ${defaultProjectDir()}\\n${themeBlock}\\n---\\n${existing}`;\n await writeFileForce(configPath, content);\n return;\n }\n\n const fmBlock = fmMatch[2];\n const afterFrontmatter = existing.slice(fmMatch[0].length);\n const cleanedFm = stripTopLevelBlock(fmBlock, 'theme');\n const newFm = `${cleanedFm}\\n${themeBlock}`.replace(/^\\n+/, '');\n const normalizedFm = newFm.replace(/\\n+$/, '');\n const newContent = `---\\n${normalizedFm}\\n---${afterFrontmatter}`;\n await writeFileForce(configPath, newContent);\n}\n\nexport async function deleteThemeConfig(): Promise<void> {\n const configPath = resolve(syntaurRoot(), 'config.md');\n if (!(await fileExists(configPath))) return;\n\n const existing = await readFile(configPath, 'utf-8');\n const fmMatch = existing.match(/^(---\\n)([\\s\\S]*?)\\n(---)/);\n if (!fmMatch) return;\n\n const fmBlock = fmMatch[2];\n const afterFrontmatter = existing.slice(fmMatch[0].length);\n const cleanedFm = stripTopLevelBlock(fmBlock, 'theme');\n const newContent = `---\\n${cleanedFm}\\n---${afterFrontmatter}`;\n await writeFileForce(configPath, newContent);\n}\n\n/**\n * Remove any top-level `key: <value>` scalar line from a YAML frontmatter block.\n * Used for scalar keys (terminal:) that don't have child lines, so they can't\n * use the block-style `stripTopLevelBlock`. No-op when the key is absent.\n */\nfunction stripTopLevelScalar(fmBlock: string, key: string): string {\n const lines = fmBlock.split('\\n');\n const keyRegex = new RegExp(`^${key}:\\\\s*\\\\S`);\n const filtered = lines.filter((line) => !keyRegex.test(line));\n return filtered.join('\\n').replace(/\\n+$/, '');\n}\n\nexport async function writeTerminalConfig(terminal: TerminalChoice): Promise<void> {\n const configPath = resolve(syntaurRoot(), 'config.md');\n const terminalLine = `terminal: ${terminal}`;\n\n const existing = (await fileExists(configPath))\n ? await readFile(configPath, 'utf-8')\n : renderConfig({ defaultProjectDir: defaultProjectDir() });\n\n const fmMatch = existing.match(/^(---\\n)([\\s\\S]*?)\\n(---)/);\n if (!fmMatch) {\n const content = `---\\nversion: \"2.0\"\\ndefaultProjectDir: ${defaultProjectDir()}\\n${terminalLine}\\n---\\n${existing}`;\n await writeFileForce(configPath, content);\n return;\n }\n\n const fmBlock = fmMatch[2];\n const afterFrontmatter = existing.slice(fmMatch[0].length);\n const cleanedFm = stripTopLevelScalar(fmBlock, 'terminal');\n const newFm = `${cleanedFm}\\n${terminalLine}`.replace(/^\\n+/, '');\n const normalizedFm = newFm.replace(/\\n+$/, '');\n const newContent = `---\\n${normalizedFm}\\n---${afterFrontmatter}`;\n await writeFileForce(configPath, newContent);\n}\n\nexport async function deleteTerminalConfig(): Promise<void> {\n const configPath = resolve(syntaurRoot(), 'config.md');\n if (!(await fileExists(configPath))) return;\n\n const existing = await readFile(configPath, 'utf-8');\n const fmMatch = existing.match(/^(---\\n)([\\s\\S]*?)\\n(---)/);\n if (!fmMatch) return;\n\n const fmBlock = fmMatch[2];\n const afterFrontmatter = existing.slice(fmMatch[0].length);\n const cleanedFm = stripTopLevelScalar(fmBlock, 'terminal');\n const newContent = `---\\n${cleanedFm}\\n---${afterFrontmatter}`;\n await writeFileForce(configPath, newContent);\n}\n\nfunction parseHotkeyBindingsConfig(content: string): HotkeyBindingsConfig | null {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return null;\n const fmBlock = match[1];\n\n const blockStart = fmBlock.match(/^hotkeys:\\s*$/m);\n if (!blockStart) return null;\n\n const startIdx = fmBlock.indexOf(blockStart[0]) + blockStart[0].length;\n const remaining = fmBlock.slice(startIdx).split('\\n');\n\n const bindings: Partial<Record<BindableActionKind, string>> = {};\n let inBindings = false;\n for (const line of remaining) {\n const trimmed = line.trimStart();\n const indent = line.length - trimmed.length;\n if (indent === 0 && trimmed.length > 0) break;\n if (trimmed === '') continue;\n if (indent === 2 && trimmed === 'bindings:') {\n inBindings = true;\n continue;\n }\n if (inBindings && indent === 4) {\n const colonIdx = trimmed.indexOf(':');\n if (colonIdx <= 0) continue;\n const rawKind = trimmed.slice(0, colonIdx).trim();\n const rawValue = trimmed\n .slice(colonIdx + 1)\n .trim()\n .replace(/^[\"']|[\"']$/g, '');\n if (!isBindableActionKind(rawKind)) continue;\n if (rawValue.length === 0) continue;\n bindings[rawKind] = canonicalizeCombo(rawValue);\n }\n }\n\n if (Object.keys(bindings).length === 0) return null;\n return { bindings };\n}\n\nfunction serializeHotkeyBindingsConfig(cfg: HotkeyBindingsConfig): string {\n const lines: string[] = ['hotkeys:', ' bindings:'];\n // Emit in the canonical kind order so on-disk diffs are stable.\n for (const kind of BINDABLE_ACTION_KINDS) {\n const value = cfg.bindings[kind];\n if (!value) continue;\n lines.push(` ${kind}: \"${canonicalizeCombo(value)}\"`);\n }\n // If no bindings remain, return an empty block (caller will treat as delete).\n if (lines.length === 2) return '';\n return lines.join('\\n');\n}\n\nexport async function writeHotkeyBindingsConfig(\n cfg: HotkeyBindingsConfig,\n): Promise<void> {\n // Validate + canonicalize + drop reserved-combo collisions before writing.\n const cleaned: Partial<Record<BindableActionKind, string>> = {};\n for (const kind of BINDABLE_ACTION_KINDS) {\n const raw = cfg.bindings[kind];\n if (typeof raw !== 'string' || raw.trim() === '') continue;\n const canonical = canonicalizeCombo(raw);\n if (!canonical) continue;\n if (isReservedCombo(canonical)) continue;\n cleaned[kind] = canonical;\n }\n\n if (Object.keys(cleaned).length === 0) {\n await deleteHotkeyBindingsConfig();\n return;\n }\n\n const configPath = resolve(syntaurRoot(), 'config.md');\n const block = serializeHotkeyBindingsConfig({ bindings: cleaned });\n\n const existing = (await fileExists(configPath))\n ? await readFile(configPath, 'utf-8')\n : renderConfig({ defaultProjectDir: defaultProjectDir() });\n\n const fmMatch = existing.match(/^(---\\n)([\\s\\S]*?)\\n(---)/);\n if (!fmMatch) {\n const content = `---\\nversion: \"2.0\"\\ndefaultProjectDir: ${defaultProjectDir()}\\n${block}\\n---\\n${existing}`;\n await writeFileForce(configPath, content);\n return;\n }\n\n const fmBlock = fmMatch[2];\n const afterFrontmatter = existing.slice(fmMatch[0].length);\n const cleanedFm = stripTopLevelBlock(fmBlock, 'hotkeys');\n const newFm = `${cleanedFm}\\n${block}`.replace(/^\\n+/, '');\n const normalizedFm = newFm.replace(/\\n+$/, '');\n const newContent = `---\\n${normalizedFm}\\n---${afterFrontmatter}`;\n await writeFileForce(configPath, newContent);\n}\n\nexport async function deleteHotkeyBindingsConfig(): Promise<void> {\n const configPath = resolve(syntaurRoot(), 'config.md');\n if (!(await fileExists(configPath))) return;\n\n const existing = await readFile(configPath, 'utf-8');\n const fmMatch = existing.match(/^(---\\n)([\\s\\S]*?)\\n(---)/);\n if (!fmMatch) return;\n\n const fmBlock = fmMatch[2];\n const afterFrontmatter = existing.slice(fmMatch[0].length);\n const cleanedFm = stripTopLevelBlock(fmBlock, 'hotkeys');\n const newContent = `---\\n${cleanedFm}\\n---${afterFrontmatter}`;\n await writeFileForce(configPath, newContent);\n}\n\nfunction stripTopLevelBlock(fmBlock: string, key: string): string {\n const blockStart = fmBlock.match(new RegExp(`^${key}:\\\\s*$`, 'm'));\n if (!blockStart) {\n return fmBlock.replace(/\\n+$/, '');\n }\n\n const startIdx = fmBlock.indexOf(blockStart[0]);\n const before = fmBlock.slice(0, startIdx);\n const after = fmBlock.slice(startIdx + blockStart[0].length);\n const remaining = after.split('\\n');\n let endIdx = 0;\n\n for (let i = 0; i < remaining.length; i++) {\n const line = remaining[i];\n if (line.trim() === '') {\n endIdx = i + 1;\n continue;\n }\n if (line.length > 0 && line[0] !== ' ') {\n break;\n }\n endIdx = i + 1;\n }\n\n return (before + remaining.slice(endIdx).join('\\n')).replace(/\\n+$/, '');\n}\n\nfunction parseOptionalAbsolutePath(\n value: string | undefined,\n fieldName: string,\n): string | null {\n if (!value) {\n return null;\n }\n\n const expanded = expandHome(String(value));\n if (!isAbsolute(expanded)) {\n console.warn(\n `Warning: config.md ${fieldName} is not an absolute path (\"${value}\"), ignoring it`,\n );\n return null;\n }\n\n return resolve(expanded);\n}\n\nfunction parseAgentsConfig(content: string): AgentConfig[] | null {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return null;\n const fmBlock = match[1];\n\n const agentsStart = fmBlock.match(/^agents:\\s*$/m);\n if (!agentsStart) return null;\n\n const startIdx = fmBlock.indexOf(agentsStart[0]) + agentsStart[0].length;\n const remaining = fmBlock.slice(startIdx);\n const lines = remaining.split('\\n');\n\n const agents: AgentConfig[] = [];\n let current: Partial<AgentConfig> & { args?: string[] } | null = null;\n let argsCapture: string[] | null = null;\n let argsBaseIndent = 0;\n // Active nested block state (e.g. `resume:` or `fork:` sub-mapping under an\n // agent). When `nestedKey` is one of `resume` / `fork`, lines at deeper\n // indent are parsed as that invocation's `command` / `args` fields. When\n // `nestedKey === '__skip__'` we swallow the indented block without\n // recording anything — this is the forward-compat path for unknown nested\n // keys added in future syntaur versions.\n let nestedKey: string | null = null;\n let nestedInvocation: SessionInvocation | null = null;\n let nestedBaseIndent = 0;\n\n function flushCurrent() {\n if (!current) return;\n if (!current.id || !current.command || !current.label) {\n current = null;\n return;\n }\n agents.push({\n id: current.id,\n label: current.label,\n command: current.command,\n ...(current.args && current.args.length > 0 ? { args: current.args } : {}),\n ...(current.promptArgPosition\n ? { promptArgPosition: current.promptArgPosition }\n : {}),\n ...(current.default ? { default: true } : {}),\n ...(current.resolveFromShellAliases ? { resolveFromShellAliases: true } : {}),\n ...(current.resume ? { resume: current.resume } : {}),\n ...(current.fork ? { fork: current.fork } : {}),\n });\n current = null;\n argsCapture = null;\n nestedKey = null;\n nestedInvocation = null;\n }\n\n function closeNestedBlock() {\n if (!nestedKey) return;\n if (current && (nestedKey === 'resume' || nestedKey === 'fork') && nestedInvocation) {\n // Only attach when args were populated — empty invocation is a no-op.\n if (Array.isArray(nestedInvocation.args)) {\n current[nestedKey] = nestedInvocation;\n }\n }\n nestedKey = null;\n nestedInvocation = null;\n argsCapture = null;\n }\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const trimmed = line.trimStart();\n const indent = line.length - trimmed.length;\n\n if (indent === 0 && trimmed !== '' && !trimmed.startsWith('#')) {\n closeNestedBlock();\n break; // new top-level key\n }\n\n // Continue capturing list items for the active argsCapture target.\n if (argsCapture) {\n if (indent > argsBaseIndent && trimmed.startsWith('- ')) {\n argsCapture.push(decodeYamlScalar(trimmed.slice(2).trim()));\n continue;\n } else {\n argsCapture = null;\n }\n }\n\n if (indent === 2 && trimmed.startsWith('- ')) {\n closeNestedBlock();\n flushCurrent();\n current = {};\n const rest = trimmed.slice(2).trim();\n const colonIdx = rest.indexOf(':');\n if (colonIdx > 0) {\n const k = rest.slice(0, colonIdx).trim();\n const v = rest.slice(colonIdx + 1).trim();\n assignAgentField(current, k, v);\n }\n continue;\n }\n\n if (!current) continue;\n\n // Inside a nested block (resume / fork / skip-unknown).\n if (nestedKey && indent > nestedBaseIndent) {\n const colonIdx = trimmed.indexOf(':');\n if (colonIdx <= 0) continue;\n const k = trimmed.slice(0, colonIdx).trim();\n const v = trimmed.slice(colonIdx + 1).trim();\n if (nestedKey === 'resume' || nestedKey === 'fork') {\n if (!nestedInvocation) nestedInvocation = { args: [] };\n if (k === 'args' && v === '') {\n nestedInvocation.args = [];\n argsCapture = nestedInvocation.args;\n argsBaseIndent = indent;\n continue;\n }\n if (k === 'command' && v !== '') {\n nestedInvocation.command = decodeYamlScalar(v);\n continue;\n }\n // Unknown nested-of-nested: ignore for forward compat.\n }\n // nestedKey === '__skip__' → swallow without recording.\n continue;\n }\n\n // Returning out to indent 4 (or shallower) — close any open nested block.\n if (nestedKey && indent <= nestedBaseIndent) {\n closeNestedBlock();\n }\n\n if (indent >= 4 && current) {\n const colonIdx = trimmed.indexOf(':');\n if (colonIdx <= 0) continue;\n const k = trimmed.slice(0, colonIdx).trim();\n const v = trimmed.slice(colonIdx + 1).trim();\n if (k === 'args' && v === '') {\n argsCapture = [];\n argsBaseIndent = indent;\n current.args = argsCapture;\n continue;\n }\n // Recognized nested mapping blocks: resume / fork. Empty value + no\n // recognized scalar field → enter nested mode.\n if ((k === 'resume' || k === 'fork') && v === '') {\n nestedKey = k;\n nestedInvocation = { args: [] };\n nestedBaseIndent = indent;\n continue;\n }\n // Unknown key with empty value at agent-field indent: forward-compat\n // skip. Older parsers would crash here once a future version emits\n // a new nested block; this branch lets us pass through gracefully.\n if (v === '' && !KNOWN_AGENT_SCALAR_FIELDS.has(k)) {\n nestedKey = '__skip__';\n nestedInvocation = null;\n nestedBaseIndent = indent;\n continue;\n }\n assignAgentField(current, k, v);\n }\n }\n closeNestedBlock();\n flushCurrent();\n\n if (agents.length === 0) return [];\n return agents;\n}\n\nconst KNOWN_AGENT_SCALAR_FIELDS: ReadonlySet<string> = new Set([\n 'id',\n 'label',\n 'command',\n 'promptArgPosition',\n 'default',\n 'resolveFromShellAliases',\n]);\n\n/**\n * Normalize and validate an agents list parsed from config.md. On any\n * AgentConfigError, log a warning and fall back to built-in defaults so a\n * malformed user config does not brick `syntaur browse`. Returns the\n * normalized list (with `command` resolved through `parseAgentCommand`).\n */\nfunction normalizeAgentsFromConfig(agents: AgentConfig[] | null): AgentConfig[] | null {\n if (agents === null) return null;\n try {\n const normalized = agents.map((agent) => ({\n ...agent,\n command: parseAgentCommand(agent.command, agent.id),\n }));\n validateAgentList(normalized);\n return normalized;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.warn(\n `Warning: ~/.syntaur/config.md agents block is invalid (${msg}) — using built-in defaults`,\n );\n return null;\n }\n}\n\n/**\n * Decode a YAML-ish scalar:\n * - Bare values returned verbatim.\n * - Single-quoted: strip outer quotes, unescape '' → '.\n * - Double-quoted: strip outer quotes, unescape \\\\ \\\" \\n \\t \\r.\n * Rejects unterminated quoted scalars (caller should surface as a parse error).\n */\nfunction decodeYamlScalar(value: string): string {\n const trimmed = value.trim();\n if (trimmed.length >= 2 && trimmed.startsWith('\"') && trimmed.endsWith('\"')) {\n const body = trimmed.slice(1, -1);\n let out = '';\n for (let i = 0; i < body.length; i++) {\n const ch = body[i];\n if (ch === '\\\\' && i + 1 < body.length) {\n const next = body[i + 1];\n switch (next) {\n case '\\\\': out += '\\\\'; break;\n case '\"': out += '\"'; break;\n case 'n': out += '\\n'; break;\n case 't': out += '\\t'; break;\n case 'r': out += '\\r'; break;\n default: out += next; break;\n }\n i++;\n continue;\n }\n out += ch;\n }\n return out;\n }\n if (trimmed.length >= 2 && trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\")) {\n return trimmed.slice(1, -1).replace(/''/g, \"'\");\n }\n return trimmed;\n}\n\nfunction assignAgentField(target: Partial<AgentConfig>, key: string, rawValue: string): void {\n const value = decodeYamlScalar(rawValue);\n switch (key) {\n case 'id':\n target.id = value;\n break;\n case 'label':\n target.label = value;\n break;\n case 'command':\n target.command = value;\n break;\n case 'promptArgPosition':\n target.promptArgPosition = value as PromptArgPosition;\n break;\n case 'default':\n target.default = value === 'true';\n break;\n case 'resolveFromShellAliases':\n target.resolveFromShellAliases = value === 'true';\n break;\n }\n}\n\nfunction yamlQuoteScalar(value: string): string {\n if (/[\\r\\n]/.test(value)) {\n throw new AgentConfigError(\n `value contains newlines, which the agents config serializer does not support: ${JSON.stringify(value)}`,\n );\n }\n if (value === '' || /[:#{}[\\],&*?|>!%@`\"'\\\\\\t]/.test(value) || /^\\s|\\s$/.test(value)) {\n const escaped = value\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\"/g, '\\\\\"')\n .replace(/\\t/g, '\\\\t');\n return `\"${escaped}\"`;\n }\n return value;\n}\n\nfunction serializeAgentsConfig(agents: AgentConfig[]): string {\n const lines: string[] = ['agents:'];\n for (const a of agents) {\n lines.push(` - id: ${yamlQuoteScalar(a.id)}`);\n lines.push(` label: ${yamlQuoteScalar(a.label)}`);\n lines.push(` command: ${yamlQuoteScalar(a.command)}`);\n if (a.args && a.args.length > 0) {\n lines.push(` args:`);\n for (const arg of a.args) {\n lines.push(` - ${yamlQuoteScalar(arg)}`);\n }\n }\n if (a.promptArgPosition && a.promptArgPosition !== 'first') {\n lines.push(` promptArgPosition: ${a.promptArgPosition}`);\n }\n if (a.default) {\n lines.push(` default: true`);\n }\n if (a.resolveFromShellAliases) {\n lines.push(` resolveFromShellAliases: true`);\n }\n if (a.resume) {\n appendSessionInvocation(lines, 'resume', a.resume);\n }\n if (a.fork) {\n appendSessionInvocation(lines, 'fork', a.fork);\n }\n }\n return lines.join('\\n');\n}\n\nfunction appendSessionInvocation(\n lines: string[],\n key: 'resume' | 'fork',\n invocation: SessionInvocation,\n): void {\n lines.push(` ${key}:`);\n if (invocation.command !== undefined) {\n lines.push(` command: ${yamlQuoteScalar(invocation.command)}`);\n }\n lines.push(` args:`);\n for (const arg of invocation.args) {\n lines.push(` - ${yamlQuoteScalar(arg)}`);\n }\n}\n\nexport async function writeAgentsConfig(agents: AgentConfig[]): Promise<void> {\n validateAgentList(agents);\n const configPath = resolve(syntaurRoot(), 'config.md');\n const agentsBlock = serializeAgentsConfig(agents);\n\n const existing = (await fileExists(configPath))\n ? await readFile(configPath, 'utf-8')\n : renderConfig({ defaultProjectDir: defaultProjectDir() });\n\n const fmMatch = existing.match(/^(---\\n)([\\s\\S]*?)\\n(---)/);\n if (!fmMatch) {\n const content = `---\\nversion: \"2.0\"\\ndefaultProjectDir: ${defaultProjectDir()}\\n${agentsBlock}\\n---\\n${existing}`;\n await writeFileForce(configPath, content.replace(/\\n\\n---/, '\\n---'));\n return;\n }\n\n const fmBlock = fmMatch[2];\n const afterFrontmatter = existing.slice(fmMatch[0].length);\n const cleanedFm = stripTopLevelBlock(fmBlock, 'agents');\n const newFm = `${cleanedFm}\\n${agentsBlock}`.replace(/^\\n+/, '').replace(/\\n+$/, '');\n const newContent = `---\\n${newFm}\\n---${afterFrontmatter}`;\n await writeFileForce(configPath, newContent);\n}\n\nexport async function deleteAgentsConfig(): Promise<void> {\n const configPath = resolve(syntaurRoot(), 'config.md');\n if (!(await fileExists(configPath))) return;\n\n const existing = await readFile(configPath, 'utf-8');\n const fmMatch = existing.match(/^(---\\n)([\\s\\S]*?)\\n(---)/);\n if (!fmMatch) return;\n\n const fmBlock = fmMatch[2];\n const afterFrontmatter = existing.slice(fmMatch[0].length);\n const cleanedFm = stripTopLevelBlock(fmBlock, 'agents');\n const newContent = `---\\n${cleanedFm}\\n---${afterFrontmatter}`;\n await writeFileForce(configPath, newContent);\n}\n\nexport async function writeStatusConfig(statuses: StatusConfig): Promise<void> {\n const configPath = resolve(syntaurRoot(), 'config.md');\n const statusBlock = serializeStatusConfig(statuses);\n\n if (!(await fileExists(configPath))) {\n // Create new config file with defaults + statuses\n const content = `---\\nversion: \"2.0\"\\ndefaultProjectDir: ~/projects\\n${statusBlock}\\n---\\n`;\n await writeFileForce(configPath, content);\n return;\n }\n\n const existing = await readFile(configPath, 'utf-8');\n const fmMatch = existing.match(/^(---\\n)([\\s\\S]*?)\\n(---)/);\n if (!fmMatch) {\n // No frontmatter — wrap in new frontmatter\n const content = `---\\nversion: \"2.0\"\\n${statusBlock}\\n---\\n${existing}`;\n await writeFileForce(configPath, content);\n return;\n }\n\n const fmBlock = fmMatch[2];\n const afterFrontmatter = existing.slice(fmMatch[0].length);\n\n // Remove existing statuses: block from frontmatter\n const statusesStart = fmBlock.match(/^statuses:\\s*$/m);\n let cleanedFm: string;\n if (statusesStart) {\n const startIdx = fmBlock.indexOf(statusesStart[0]);\n const before = fmBlock.slice(0, startIdx);\n const after = fmBlock.slice(startIdx + statusesStart[0].length);\n // Skip all indented lines (belonging to statuses block)\n const remaining = after.split('\\n');\n let endIdx = 0;\n for (let i = 0; i < remaining.length; i++) {\n const line = remaining[i];\n if (line.trim() === '') { endIdx = i + 1; continue; }\n if (line.length > 0 && line[0] !== ' ') break;\n endIdx = i + 1;\n }\n cleanedFm = before + remaining.slice(endIdx).join('\\n');\n } else {\n cleanedFm = fmBlock;\n }\n\n // Trim trailing whitespace/newlines from cleaned frontmatter\n cleanedFm = cleanedFm.replace(/\\n+$/, '');\n\n const newContent = `---\\n${cleanedFm}\\n${statusBlock}\\n---${afterFrontmatter}`;\n await writeFileForce(configPath, newContent);\n}\n\nexport async function deleteStatusConfig(): Promise<void> {\n const configPath = resolve(syntaurRoot(), 'config.md');\n if (!(await fileExists(configPath))) return;\n\n const existing = await readFile(configPath, 'utf-8');\n const fmMatch = existing.match(/^(---\\n)([\\s\\S]*?)\\n(---)/);\n if (!fmMatch) return;\n\n const fmBlock = fmMatch[2];\n const afterFrontmatter = existing.slice(fmMatch[0].length);\n const cleanedFm = stripTopLevelBlock(fmBlock, 'statuses');\n\n const newContent = `---\\n${cleanedFm}\\n---${afterFrontmatter}`;\n await writeFileForce(configPath, newContent);\n}\n\nexport async function updateIntegrationConfig(\n integrations: Partial<IntegrationConfig>,\n): Promise<void> {\n const configPath = resolve(syntaurRoot(), 'config.md');\n const nextIntegrations: IntegrationConfig = {\n ...(await readConfig()).integrations,\n ...integrations,\n };\n\n const integrationBlock = serializeIntegrationConfig(nextIntegrations);\n const existing = await fileExists(configPath)\n ? await readFile(configPath, 'utf-8')\n : renderConfig({ defaultProjectDir: defaultProjectDir() });\n\n const fmMatch = existing.match(/^(---\\n)([\\s\\S]*?)\\n(---)/);\n if (!fmMatch) {\n const content = `---\\nversion: \"2.0\"\\ndefaultProjectDir: ${defaultProjectDir()}\\n${integrationBlock ?? ''}\\n---\\n${existing}`;\n await writeFileForce(configPath, content.replace(/\\n\\n---/, '\\n---'));\n return;\n }\n\n const fmBlock = fmMatch[2];\n const afterFrontmatter = existing.slice(fmMatch[0].length);\n const cleanedFm = stripTopLevelBlock(fmBlock, 'integrations');\n const newFm = integrationBlock\n ? `${cleanedFm}\\n${integrationBlock}`.replace(/^\\n+/, '')\n : cleanedFm;\n const normalizedFm = newFm.replace(/\\n+$/, '');\n const newContent = `---\\n${normalizedFm}\\n---${afterFrontmatter}`;\n await writeFileForce(configPath, newContent);\n}\n\nexport async function updateOnboardingConfig(\n onboarding: Partial<OnboardingConfig>,\n): Promise<void> {\n const configPath = resolve(syntaurRoot(), 'config.md');\n const nextOnboarding: OnboardingConfig = {\n ...(await readConfig()).onboarding,\n ...onboarding,\n };\n\n const onboardingBlock = serializeOnboardingConfig(nextOnboarding);\n const existing = await fileExists(configPath)\n ? await readFile(configPath, 'utf-8')\n : renderConfig({ defaultProjectDir: defaultProjectDir() });\n\n const fmMatch = existing.match(/^(---\\n)([\\s\\S]*?)\\n(---)/);\n if (!fmMatch) {\n const content = `---\\nversion: \"2.0\"\\ndefaultProjectDir: ${defaultProjectDir()}\\n${onboardingBlock}\\n---\\n${existing}`;\n await writeFileForce(configPath, content.replace(/\\n\\n---/, '\\n---'));\n return;\n }\n\n const fmBlock = fmMatch[2];\n const afterFrontmatter = existing.slice(fmMatch[0].length);\n const cleanedFm = stripTopLevelBlock(fmBlock, 'onboarding');\n const newFm = `${cleanedFm}\\n${onboardingBlock}`.replace(/^\\n+/, '');\n const normalizedFm = newFm.replace(/\\n+$/, '');\n const newContent = `---\\n${normalizedFm}\\n---${afterFrontmatter}`;\n await writeFileForce(configPath, newContent);\n}\n\nexport async function updateBackupConfig(\n backup: Partial<BackupConfig>,\n): Promise<void> {\n const configPath = resolve(syntaurRoot(), 'config.md');\n const current = (await readConfig()).backup;\n const nextBackup: BackupConfig = {\n repo: current?.repo ?? null,\n categories: current?.categories ?? 'projects, playbooks, todos, servers, config',\n lastBackup: current?.lastBackup ?? null,\n lastRestore: current?.lastRestore ?? null,\n ...backup,\n };\n\n const backupBlock = serializeBackupConfig(nextBackup);\n const existing = await fileExists(configPath)\n ? await readFile(configPath, 'utf-8')\n : renderConfig({ defaultProjectDir: defaultProjectDir() });\n\n const fmMatch = existing.match(/^(---\\n)([\\s\\S]*?)\\n(---)/);\n if (!fmMatch) {\n const content = `---\\nversion: \"2.0\"\\ndefaultProjectDir: ${defaultProjectDir()}\\n${backupBlock}\\n---\\n${existing}`;\n await writeFileForce(configPath, content.replace(/\\n\\n---/, '\\n---'));\n return;\n }\n\n const fmBlock = fmMatch[2];\n const afterFrontmatter = existing.slice(fmMatch[0].length);\n const cleanedFm = stripTopLevelBlock(fmBlock, 'backup');\n const newFm = `${cleanedFm}\\n${backupBlock}`.replace(/^\\n+/, '');\n const normalizedFm = newFm.replace(/\\n+$/, '');\n const newContent = `---\\n${normalizedFm}\\n---${afterFrontmatter}`;\n await writeFileForce(configPath, newContent);\n}\n\n// Guard so the legacy-config migration runs at most once per config path per\n// process lifetime. Keyed by absolute path so tests with multiple sandbox\n// HOMEs still get the migration applied to each.\nconst migratedConfigPaths = new Set<string>();\n\nexport async function readConfig(): Promise<SyntaurConfig> {\n const configPath = resolve(syntaurRoot(), 'config.md');\n if (!(await fileExists(configPath))) {\n return cloneDefaultConfig();\n }\n\n if (!migratedConfigPaths.has(configPath)) {\n migratedConfigPaths.add(configPath);\n await migrateLegacyConfig(configPath);\n }\n\n const content = await readFile(configPath, 'utf-8');\n const fm = parseFrontmatter(content);\n\n if (Object.keys(fm).length === 0) {\n console.warn('Warning: ~/.syntaur/config.md has malformed frontmatter, using defaults');\n return cloneDefaultConfig();\n }\n\n let projectDir = fm['defaultProjectDir']\n ? expandHome(String(fm['defaultProjectDir']))\n : DEFAULT_CONFIG.defaultProjectDir;\n if (!isAbsolute(projectDir)) {\n console.warn(\n `Warning: config.md defaultProjectDir is not an absolute path (\"${fm['defaultProjectDir']}\"), using default`,\n );\n projectDir = DEFAULT_CONFIG.defaultProjectDir;\n }\n\n const fmBlock = content.match(/^---\\n([\\s\\S]*?)\\n---/)?.[1] ?? '';\n\n return {\n version: fm['version'] || DEFAULT_CONFIG.version,\n defaultProjectDir: projectDir,\n onboarding: {\n completed: fm['onboarding.completed'] === 'true',\n },\n agentDefaults: {\n trustLevel:\n (fm['agentDefaults.trustLevel'] as SyntaurConfig['agentDefaults']['trustLevel']) ||\n DEFAULT_CONFIG.agentDefaults.trustLevel,\n autoApprove:\n fm['agentDefaults.autoApprove'] === 'true' ||\n DEFAULT_CONFIG.agentDefaults.autoApprove,\n autoCreateWorktree: AUTO_CREATE_WORKTREE_VALUES.includes(\n fm['agentDefaults.autoCreateWorktree'] as AutoCreateWorktree,\n )\n ? (fm['agentDefaults.autoCreateWorktree'] as AutoCreateWorktree)\n : DEFAULT_CONFIG.agentDefaults.autoCreateWorktree,\n },\n integrations: {\n claudePluginDir: parseOptionalAbsolutePath(\n fm['integrations.claudePluginDir'],\n 'integrations.claudePluginDir',\n ),\n codexPluginDir: parseOptionalAbsolutePath(\n fm['integrations.codexPluginDir'],\n 'integrations.codexPluginDir',\n ),\n codexMarketplacePath: parseOptionalAbsolutePath(\n fm['integrations.codexMarketplacePath'],\n 'integrations.codexMarketplacePath',\n ),\n },\n backup: fm['backup.repo'] || fm['backup.categories']\n ? {\n repo: fm['backup.repo'] && fm['backup.repo'] !== 'null' ? fm['backup.repo'] : null,\n categories: fm['backup.categories'] || 'projects, playbooks, todos, servers, config',\n lastBackup: fm['backup.lastBackup'] && fm['backup.lastBackup'] !== 'null' ? fm['backup.lastBackup'] : null,\n lastRestore: fm['backup.lastRestore'] && fm['backup.lastRestore'] !== 'null' ? fm['backup.lastRestore'] : null,\n }\n : null,\n statuses: parseStatusConfig(content),\n types: null,\n agents: normalizeAgentsFromConfig(parseAgentsConfig(content)),\n playbooks: parsePlaybooksConfig(fmBlock),\n theme: parseThemeConfig(content),\n hotkeys: parseHotkeyBindingsConfig(content),\n terminal: (() => {\n try {\n return parseTerminalConfig(fm['terminal']);\n } catch (err) {\n const msg = err instanceof TerminalConfigError ? err.message : String(err);\n console.warn(`Warning: ${msg} — falling back to default`);\n return null;\n }\n })(),\n };\n}\n\nexport function getAssignmentTypes(config: SyntaurConfig): TypesConfig {\n return config.types ?? DEFAULT_ASSIGNMENT_TYPES;\n}\n\nexport function getAgents(config: SyntaurConfig): AgentConfig[] {\n return config.agents ?? BUILTIN_AGENTS;\n}\n\nexport class TerminalConfigError extends Error {}\n\n/**\n * Parse the `terminal:` scalar from raw frontmatter values.\n * Returns null when the key is absent (caller falls back to platform default).\n * Throws TerminalConfigError when the value is not a known choice.\n */\nexport function parseTerminalConfig(value: unknown): TerminalChoice | null {\n if (value === undefined || value === null || value === '') return null;\n if (typeof value !== 'string') {\n throw new TerminalConfigError(\n `terminal must be a string — got ${typeof value}`,\n );\n }\n const trimmed = value.trim();\n if (trimmed === '') return null;\n if (!TERMINAL_CHOICES.includes(trimmed as TerminalChoice)) {\n throw new TerminalConfigError(\n `terminal \"${trimmed}\" is not a known choice — expected one of ${TERMINAL_CHOICES.join('|')}`,\n );\n }\n return trimmed as TerminalChoice;\n}\n\n/**\n * Return the configured terminal, or the platform default when unset.\n *\n * darwin → terminal-app (always available).\n * linux → first of [kitty, alacritty, warp] resolvable via `which`, in that\n * order. If none are installed, return terminal-app as a stable\n * sentinel (doctor will surface the install gap separately).\n * other → terminal-app sentinel.\n *\n * The Linux probe order is intentionally deterministic and documented so the\n * dashboard's preflight + the Settings hint show the same value.\n */\nexport function getTerminal(config: SyntaurConfig): TerminalChoice {\n if (config.terminal) return config.terminal;\n if (process.platform === 'darwin') return 'terminal-app';\n if (process.platform === 'linux') {\n const order: TerminalChoice[] = ['kitty', 'alacritty', 'warp'];\n for (const candidate of order) {\n const result = spawnSync('which', [candidate], { encoding: 'utf-8' });\n if (result.status === 0 && result.stdout.trim().length > 0) {\n return candidate;\n }\n }\n }\n return 'terminal-app';\n}\n\nexport interface AgentsMutation {\n kind: 'add' | 'remove' | 'set' | 'reorder';\n apply: (current: AgentConfig[]) => AgentConfig[];\n}\n\n/**\n * Apply a mutation to the agents list, validate, and either write or return the\n * proposed new list (for --dry-run). Always runs full validation.\n */\nexport async function updateAgentsConfig(\n mutation: AgentsMutation,\n options: { dryRun?: boolean } = {},\n): Promise<{ previous: AgentConfig[]; next: AgentConfig[]; written: boolean }> {\n const config = await readConfig();\n const previous = config.agents ?? [...BUILTIN_AGENTS];\n const next = mutation.apply(previous);\n validateAgentList(next);\n\n if (options.dryRun) {\n return { previous, next, written: false };\n }\n\n await writeAgentsConfig(next);\n return { previous, next, written: true };\n}\n","export function slugify(title: string): string {\n return title\n .toLowerCase()\n .trim()\n .replace(/[^a-z0-9\\s-]/g, '')\n .replace(/\\s+/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '');\n}\n\nexport function isValidSlug(slug: string): boolean {\n return /^[a-z0-9]+(-[a-z0-9]+)*$/.test(slug);\n}\n","import { resolve } from 'node:path';\nimport { readdir, readFile, unlink } from 'node:fs/promises';\nimport { fileExists, writeFileForce } from './fs.js';\nimport { parsePlaybook, type ParsedPlaybook } from '../dashboard/parser.js';\nimport { nowTimestamp } from './timestamp.js';\nimport { readConfig, updatePlaybooksConfig } from './config.js';\nimport { isValidSlug } from './slug.js';\n\nexport interface ResolvedPlaybook {\n filename: string;\n slug: string;\n parsed: ParsedPlaybook;\n}\n\nexport type PlaybookErrorCode = 'manifest' | 'not-found' | 'invalid-slug' | 'collision';\n\n/**\n * Stable error thrown by playbook helpers. Routers and CLI commands branch on\n * `code` to map to HTTP status / exit code without string matching.\n */\nexport class PlaybookError extends Error {\n readonly code: PlaybookErrorCode;\n constructor(code: PlaybookErrorCode, message: string) {\n super(message);\n this.code = code;\n this.name = 'PlaybookError';\n }\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/**\n * Replace or insert a frontmatter scalar field. Playbook files always have\n * frontmatter (parsePlaybook depends on it). If the field is absent, insert it\n * just before the closing `---`. Values are written verbatim (caller decides\n * quoting).\n */\nfunction setFrontmatterField(content: string, key: string, value: string): string {\n const regex = new RegExp(`^(${escapeRegExp(key)}:)\\\\s*.*$`, 'm');\n if (regex.test(content)) {\n return content.replace(regex, `$1 ${value}`);\n }\n const closingIdx = content.indexOf('\\n---', 4);\n if (closingIdx === -1) {\n return content;\n }\n return `${content.slice(0, closingIdx)}\\n${key}: ${value}${content.slice(closingIdx)}`;\n}\n\nfunction isVisiblePlaybookFile(name: string, isFile: boolean): boolean {\n return isFile && name.endsWith('.md') && !name.startsWith('_') && name !== 'manifest.md';\n}\n\n/**\n * Resolve a requested slug to a concrete playbook file.\n *\n * Canonical slug is the `slug` field in the playbook's frontmatter. If that\n * field is missing we fall back to the filename stem. This means a playbook\n * with `filename: foo.md` and frontmatter `slug: bar` is reachable by `bar`\n * (and NOT by `foo`) — this keeps behavior consistent across dashboard +\n * CLI so enable/disable state is addressable by a single canonical slug.\n */\nexport async function resolvePlaybookSlug(\n playbooksDir: string,\n slug: string,\n): Promise<ResolvedPlaybook | null> {\n if (!(await fileExists(playbooksDir))) return null;\n\n const entries = await readdir(playbooksDir, { withFileTypes: true });\n\n let filenameStemFallback: ResolvedPlaybook | null = null;\n\n for (const entry of entries) {\n if (!isVisiblePlaybookFile(entry.name, entry.isFile())) continue;\n\n const filePath = resolve(playbooksDir, entry.name);\n const raw = await readFile(filePath, 'utf-8');\n const parsed = parsePlaybook(raw);\n const canonical = parsed.slug || entry.name.replace(/\\.md$/, '');\n\n if (canonical === slug) {\n return { filename: entry.name, slug: canonical, parsed };\n }\n\n // Only use the filename stem as a fallback when frontmatter slug is absent.\n if (!parsed.slug && entry.name.replace(/\\.md$/, '') === slug) {\n filenameStemFallback = { filename: entry.name, slug: canonical, parsed };\n }\n }\n\n return filenameStemFallback;\n}\n\n/**\n * Toggle a playbook's enabled/disabled state. Writes config.md, rebuilds the\n * manifest, and returns the canonical slug + resulting enabled flag.\n *\n * Throws if the slug cannot be resolved to a playbook file.\n */\nexport async function setPlaybookEnabled(\n playbooksDir: string,\n slug: string,\n enabled: boolean,\n): Promise<{ slug: string; enabled: boolean; changed: boolean }> {\n const resolved = await resolvePlaybookSlug(playbooksDir, slug);\n if (!resolved) {\n throw new Error(`Playbook \"${slug}\" not found in ${playbooksDir}`);\n }\n\n const config = await readConfig();\n const disabledSet = new Set(config.playbooks.disabled);\n const wasDisabled = disabledSet.has(resolved.slug);\n const shouldBeDisabled = !enabled;\n\n if (wasDisabled === shouldBeDisabled) {\n return { slug: resolved.slug, enabled, changed: false };\n }\n\n if (shouldBeDisabled) {\n disabledSet.add(resolved.slug);\n } else {\n disabledSet.delete(resolved.slug);\n }\n\n await updatePlaybooksConfig({ disabled: Array.from(disabledSet).sort() });\n await rebuildPlaybookManifest(playbooksDir);\n\n return { slug: resolved.slug, enabled, changed: true };\n}\n\n/**\n * Load a playbook ONLY if it is enabled. Returns null when the playbook does\n * not exist OR is disabled in config. Intended for agent-facing lookups that\n * must respect the disabled state.\n *\n * Dashboard admin code should NOT use this — it uses the unfiltered\n * `getPlaybookDetail` so admins can still see and re-enable disabled playbooks.\n */\nexport async function loadEnabledPlaybook(\n playbooksDir: string,\n slug: string,\n): Promise<ParsedPlaybook | null> {\n const resolved = await resolvePlaybookSlug(playbooksDir, slug);\n if (!resolved) return null;\n\n const config = await readConfig();\n if (config.playbooks.disabled.includes(resolved.slug)) {\n return null;\n }\n\n return resolved.parsed;\n}\n\n/**\n * Remove a slug from the disabled list. Called when a playbook is deleted so\n * a later reincarnation with the same slug doesn't silently start disabled.\n * No-op if the slug isn't currently disabled.\n */\nexport async function removeFromDisabledList(slug: string): Promise<void> {\n const config = await readConfig();\n if (!config.playbooks.disabled.includes(slug)) return;\n await updatePlaybooksConfig({\n disabled: config.playbooks.disabled.filter((s) => s !== slug),\n });\n}\n\nexport async function rebuildPlaybookManifest(playbooksDir: string): Promise<void> {\n if (!(await fileExists(playbooksDir))) return;\n\n const config = await readConfig();\n const disabledSet = new Set(config.playbooks.disabled);\n\n const entries = await readdir(playbooksDir, { withFileTypes: true });\n const rows: Array<{ name: string; slug: string; description: string; whenToUse: string }> = [];\n\n for (const entry of entries) {\n if (!isVisiblePlaybookFile(entry.name, entry.isFile())) continue;\n\n const raw = await readFile(resolve(playbooksDir, entry.name), 'utf-8');\n const parsed = parsePlaybook(raw);\n const slug = parsed.slug || entry.name.replace(/\\.md$/, '');\n\n if (disabledSet.has(slug)) continue;\n\n rows.push({\n name: parsed.name || slug,\n slug,\n description: parsed.description,\n whenToUse: parsed.whenToUse,\n });\n }\n\n rows.sort((a, b) => a.name.localeCompare(b.name));\n\n const timestamp = nowTimestamp();\n const lines = [\n '---',\n `generated: \"${timestamp}\"`,\n `total: ${rows.length}`,\n '---',\n '',\n '# Playbooks',\n '',\n 'Behavioral rules for AI agents. Read and follow all playbooks before starting work.',\n '',\n ];\n\n for (const row of rows) {\n lines.push(`- **[${row.name}](${row.slug}.md)** — ${row.description}`);\n if (row.whenToUse) {\n lines.push(` _When to use: ${row.whenToUse}_`);\n }\n }\n\n lines.push('');\n\n await writeFileForce(resolve(playbooksDir, 'manifest.md'), lines.join('\\n'));\n}\n\n/**\n * Delete a playbook file from disk and regenerate the manifest. Refuses\n * `manifest`. Drops the slug from `config.playbooks.disabled` if present so a\n * later recreation with the same slug doesn't silently start disabled. Throws\n * `PlaybookError` on `manifest` / `not-found`.\n *\n * Shared by `DELETE /api/playbooks/:slug` and `syntaur delete-playbook`.\n */\nexport async function deletePlaybook(\n playbooksDir: string,\n slug: string,\n): Promise<{ slug: string }> {\n if (slug === 'manifest') {\n throw new PlaybookError('manifest', 'The playbook manifest cannot be deleted.');\n }\n\n const resolved = await resolvePlaybookSlug(playbooksDir, slug);\n if (!resolved) {\n throw new PlaybookError('not-found', `Playbook \"${slug}\" not found.`);\n }\n\n await unlink(resolve(playbooksDir, resolved.filename));\n await removeFromDisabledList(resolved.slug);\n await rebuildPlaybookManifest(playbooksDir);\n\n return { slug: resolved.slug };\n}\n\n/**\n * Rename a playbook to a new slug. Validates the new slug, refuses `manifest`,\n * and rejects collisions at both filename and canonical-slug levels. Updates\n * the on-disk file's frontmatter `slug:` field. Migrates the disabled-list\n * entry if needed. Regenerates the manifest.\n *\n * Special case: if `oldPath === newPath` (e.g., file is `foo.md` with\n * frontmatter `slug: bar`, caller renames `bar -> foo`), rewrite the file in\n * place without unlinking. Returns `renamedInPlace: true` in that case.\n */\nexport async function renamePlaybook(\n playbooksDir: string,\n oldSlug: string,\n newSlug: string,\n): Promise<{ from: string; to: string; renamedInPlace: boolean }> {\n if (!isValidSlug(newSlug)) {\n throw new PlaybookError(\n 'invalid-slug',\n `Invalid slug \"${newSlug}\". Slugs must be lowercase, hyphen-separated, with no special characters.`,\n );\n }\n if (newSlug === 'manifest') {\n throw new PlaybookError('manifest', 'A playbook cannot be named \"manifest\".');\n }\n\n const resolved = await resolvePlaybookSlug(playbooksDir, oldSlug);\n if (!resolved) {\n throw new PlaybookError('not-found', `Playbook \"${oldSlug}\" not found.`);\n }\n\n const oldPath = resolve(playbooksDir, resolved.filename);\n const newPath = resolve(playbooksDir, `${newSlug}.md`);\n\n // Rename-in-place: e.g., file `foo.md` with `slug: bar` renamed `bar -> foo`.\n // The on-disk filename doesn't change; only the frontmatter slug field does.\n const renamedInPlace = oldPath === newPath;\n\n if (!renamedInPlace) {\n // Filename collision: another file already occupies the new path.\n if (await fileExists(newPath)) {\n throw new PlaybookError(\n 'collision',\n `A playbook file already exists at \"${newSlug}.md\".`,\n );\n }\n // Canonical-slug collision: another file declares this slug in its frontmatter.\n const existing = await resolvePlaybookSlug(playbooksDir, newSlug);\n if (existing && resolve(playbooksDir, existing.filename) !== oldPath) {\n throw new PlaybookError(\n 'collision',\n `Another playbook already uses the canonical slug \"${newSlug}\".`,\n );\n }\n }\n\n const raw = await readFile(oldPath, 'utf-8');\n let next = setFrontmatterField(raw, 'slug', newSlug);\n next = setFrontmatterField(next, 'updated', `\"${nowTimestamp()}\"`);\n\n await writeFileForce(newPath, next);\n if (!renamedInPlace) {\n await unlink(oldPath);\n }\n\n // Migrate disabled-list entry if the old canonical slug was disabled.\n const config = await readConfig();\n if (config.playbooks.disabled.includes(resolved.slug)) {\n const nextDisabled = config.playbooks.disabled\n .filter((s) => s !== resolved.slug)\n .concat(newSlug);\n await updatePlaybooksConfig({ disabled: Array.from(new Set(nextDisabled)).sort() });\n }\n\n await rebuildPlaybookManifest(playbooksDir);\n\n return { from: resolved.slug, to: newSlug, renamedInPlace };\n}\n","import { resolve } from 'node:path';\nimport { readdir, readFile } from 'node:fs/promises';\nimport { fileExists } from './fs.js';\nimport { extractFrontmatter, getField } from '../dashboard/parser.js';\n\nexport interface ResolvedAssignment {\n assignmentDir: string;\n projectSlug: string | null;\n assignmentSlug: string;\n id: string;\n standalone: boolean;\n workspaceGroup: string | null;\n}\n\nexport async function resolveAssignmentById(\n projectsDir: string,\n assignmentsDir: string,\n id: string,\n): Promise<ResolvedAssignment | null> {\n let standaloneMatch: ResolvedAssignment | null = null;\n let projectMatch: ResolvedAssignment | null = null;\n\n // 1) Standalone: <assignmentsDir>/<id>/assignment.md\n const standaloneDir = resolve(assignmentsDir, id);\n const standalonePath = resolve(standaloneDir, 'assignment.md');\n if (await fileExists(standalonePath)) {\n let workspaceGroup: string | null = null;\n try {\n const content = await readFile(standalonePath, 'utf-8');\n const [fm] = extractFrontmatter(content);\n workspaceGroup = getField(fm, 'workspaceGroup');\n } catch {\n // unreadable — leave null\n }\n standaloneMatch = {\n assignmentDir: standaloneDir,\n projectSlug: null,\n assignmentSlug: id,\n id,\n standalone: true,\n workspaceGroup,\n };\n }\n\n // 2) Project-nested: scan <projectsDir>/*/assignments/*/assignment.md and match by frontmatter id\n if (await fileExists(projectsDir)) {\n try {\n const projects = await readdir(projectsDir, { withFileTypes: true });\n for (const p of projects) {\n if (!p.isDirectory()) continue;\n if (p.name.startsWith('.') || p.name.startsWith('_')) continue;\n const assignmentsPath = resolve(projectsDir, p.name, 'assignments');\n if (!(await fileExists(assignmentsPath))) continue;\n\n const entries = await readdir(assignmentsPath, { withFileTypes: true });\n for (const a of entries) {\n if (!a.isDirectory()) continue;\n const aPath = resolve(assignmentsPath, a.name, 'assignment.md');\n if (!(await fileExists(aPath))) continue;\n\n try {\n const content = await readFile(aPath, 'utf-8');\n const [fm] = extractFrontmatter(content);\n const fileId = getField(fm, 'id');\n if (fileId === id) {\n projectMatch = {\n assignmentDir: resolve(assignmentsPath, a.name),\n projectSlug: p.name,\n assignmentSlug: a.name,\n id,\n standalone: false,\n workspaceGroup: null,\n };\n break;\n }\n } catch {\n // skip unreadable\n }\n }\n if (projectMatch) break;\n }\n } catch {\n // projectsDir not readable\n }\n }\n\n if (standaloneMatch && projectMatch) {\n console.warn(\n `Duplicate assignment ID ${id} found in both standalone and project-nested locations; using standalone`,\n );\n return standaloneMatch;\n }\n\n return standaloneMatch ?? projectMatch ?? null;\n}\n","import type {\n HelpChecklistItem,\n HelpCommand,\n HelpResponse,\n HelpStatusGuideEntry,\n} from './types.js';\nimport { getStatusConfig } from './api.js';\n\nconst CLI_COMMANDS: HelpCommand[] = [\n // --- Core setup & scaffolding (indices 0-4) ---\n {\n command: 'syntaur setup',\n description: 'Initialize Syntaur and optionally install plugins or launch the dashboard.',\n example: 'syntaur setup',\n },\n {\n command: 'syntaur init',\n description: 'Initialize the local Syntaur home directory and config scaffolding without any prompts.',\n example: 'syntaur init',\n },\n {\n command: 'syntaur create-project',\n description: 'Create a new project folder with the required source and derived files.',\n example: 'syntaur create-project \"Ship dashboard overhaul\"',\n },\n {\n command: 'syntaur create-assignment',\n description: 'Create a new assignment inside a project.',\n example: 'syntaur create-assignment \"Implement overview API\" --project ui-overhaul',\n },\n {\n command: 'syntaur assign',\n description: 'Set the assignee for an assignment before work begins.',\n example: 'syntaur assign implement-overview --project ui-overhaul --agent codex-1',\n },\n\n // --- Lifecycle transitions ---\n {\n command: 'syntaur start',\n description: 'Transition an assignment to in_progress.',\n example: 'syntaur start implement-overview --project ui-overhaul',\n },\n {\n command: 'syntaur shape',\n description: 'Transition a draft assignment to ready_for_planning once the Objective and Acceptance Criteria are fleshed out.',\n example: 'syntaur shape implement-overview --project ui-overhaul',\n },\n {\n command: 'syntaur plan-ready',\n description: 'Transition a ready_for_planning assignment to ready_to_implement once a plan has been written and approved.',\n example: 'syntaur plan-ready implement-overview --project ui-overhaul',\n },\n {\n command: 'syntaur implement',\n description: 'Transition a ready_to_implement assignment to in_progress when coding begins.',\n example: 'syntaur implement implement-overview --project ui-overhaul',\n },\n {\n command: 'syntaur migrate-statuses',\n description: 'Suggest pending -> ready_for_planning promotions for fleshed-out assignments. Dry-run by default; pass --apply to write.',\n example: 'syntaur migrate-statuses --apply',\n },\n {\n command: 'syntaur review',\n description: 'Move active work into review once implementation is ready for inspection.',\n example: 'syntaur review implement-overview --project ui-overhaul',\n },\n {\n command: 'syntaur complete',\n description: 'Mark an assignment completed after review or direct completion.',\n example: 'syntaur complete implement-overview --project ui-overhaul',\n },\n {\n command: 'syntaur block',\n description: 'Mark an assignment blocked and record the explicit reason.',\n example: 'syntaur block implement-overview --project ui-overhaul --reason \"Waiting on API spec\"',\n },\n {\n command: 'syntaur unblock',\n description: 'Move a blocked assignment back to in_progress after the blocker is cleared.',\n example: 'syntaur unblock implement-overview --project ui-overhaul',\n },\n {\n command: 'syntaur fail',\n description: 'Mark an assignment failed when it cannot be completed as planned.',\n example: 'syntaur fail implement-overview --project ui-overhaul',\n },\n {\n command: 'syntaur reopen',\n description: 'Reopen a completed or failed assignment back to in_progress.',\n example: 'syntaur reopen implement-overview --project ui-overhaul',\n },\n\n // --- Dashboard (index 12) ---\n {\n command: 'syntaur dashboard',\n description: 'Start the local dashboard UI over the project files on disk.',\n example: 'syntaur dashboard --port 4800',\n },\n\n // --- Plugin & adapter setup (indices 13-16) ---\n {\n command: 'syntaur install-plugin',\n description: 'Install the Syntaur Claude Code plugin, detecting the local Claude marketplace when available and prompting for the target directory when interactive.',\n example: 'syntaur install-plugin --target-dir ~/.claude/plugins/marketplaces/user-plugins/plugins/syntaur',\n },\n {\n command: 'syntaur install-codex-plugin',\n description: 'Install the Syntaur Codex plugin and register its marketplace entry, prompting for both paths when interactive.',\n example: 'syntaur install-codex-plugin --target-dir ~/plugins/syntaur --marketplace-path ~/.agents/plugins/marketplace.json',\n },\n {\n command: 'syntaur uninstall',\n description: 'Remove Syntaur plugins and optionally local ~/.syntaur data.',\n example: 'syntaur uninstall --all',\n },\n {\n command: 'syntaur setup-adapter',\n description: 'Generate adapter instruction files for cursor, codex, or opencode in the current directory.',\n example: 'syntaur setup-adapter cursor --project ui-overhaul --assignment implement-overview',\n },\n\n // --- Session & server tracking (index 17) ---\n {\n command: 'syntaur track-session',\n description:\n 'Register an agent session. Requires --session-id from the agent runtime (real, not generated). Pass --transcript-path for the rollout/transcript file. --project and --assignment are optional.',\n example:\n 'syntaur track-session --agent claude --session-id <real-id> --transcript-path <path> --project ui-overhaul --assignment implement-overview',\n },\n\n // --- Browsing & playbooks (indices 18-20) ---\n {\n command: 'syntaur browse',\n description: 'Interactive TUI browser for projects and assignments.',\n example: 'syntaur browse',\n },\n {\n command: 'syntaur create-playbook',\n description: 'Create a new playbook with behavioral rules for agents.',\n example: 'syntaur create-playbook \"Code Review Standards\"',\n },\n {\n command: 'syntaur list-playbooks',\n description:\n 'List playbooks in the Syntaur home directory. Disabled playbooks are excluded by default; pass --all to include them with a (disabled) tag.',\n example: 'syntaur list-playbooks --all',\n },\n {\n command: 'syntaur enable-playbook',\n description:\n 'Re-enable a previously-disabled playbook so agents load it again. Updates config.md and rebuilds manifest.md.',\n example: 'syntaur enable-playbook commit-discipline',\n },\n {\n command: 'syntaur disable-playbook',\n description:\n 'Disable a playbook so agents no longer list or load it. Playbook file is untouched; state is tracked in config.md.',\n example: 'syntaur disable-playbook commit-discipline',\n },\n {\n command: 'syntaur delete-playbook',\n description:\n 'Delete a playbook from disk and regenerate the manifest. Refuses to delete the manifest itself.',\n example: 'syntaur delete-playbook scratch-foo',\n },\n];\n\nconst WORKFLOW: HelpChecklistItem[] = [\n {\n title: 'Initialize the workspace',\n detail: 'Run setup once so Syntaur can initialize its local home directory and offer plugin installation.',\n command: CLI_COMMANDS[0],\n },\n {\n title: 'Create a project',\n detail: 'Use a project for a higher-level objective. Projects group assignments, shared resources, and memories.',\n command: CLI_COMMANDS[2],\n href: '/create/project',\n },\n {\n title: 'Create the first assignment',\n detail: 'Assignments are the execution unit. Create one for each concrete chunk of work inside the project.',\n command: CLI_COMMANDS[3],\n },\n {\n title: 'Assign the work',\n detail: 'Setting an assignee before starting is recommended for clarity, but not required.',\n command: CLI_COMMANDS[4],\n },\n {\n title: 'Start, review, complete, or block through lifecycle actions',\n detail: 'Status changes happen through lifecycle actions, kanban drag-and-drop, or the status override controls.',\n command: CLI_COMMANDS[5],\n },\n {\n title: 'Use the dashboard for triage and context',\n detail: 'Overview shows the current queue, project pages show health, assignment pages show the execution surface.',\n command: CLI_COMMANDS[12],\n href: '/',\n },\n];\n\nconst DEFAULT_STATUS_GUIDE: Record<string, { meaning: string; useWhen: string }> = {\n draft: {\n meaning: 'The assignment is a just-created stub; objective and acceptance criteria are not yet fleshed out.',\n useWhen: 'Use draft for newly-scaffolded assignments. Transition to ready_for_planning with `syntaur shape` once the Objective and AC are written.',\n },\n pending: {\n meaning: 'The assignment has not started yet.',\n useWhen: 'Use pending while waiting to start. If dependencies are unmet, pending is the normal waiting state.',\n },\n ready_for_planning: {\n meaning: 'The assignment is fully shaped; a plan needs to be written before implementation can begin.',\n useWhen: 'Use ready_for_planning after the Objective and Acceptance Criteria are filled out but before any plan.md exists. Transition to ready_to_implement with `syntaur plan-ready` after the plan is approved.',\n },\n ready_to_implement: {\n meaning: 'The plan has been written and approved; the assignment is ready to start coding.',\n useWhen: 'Use ready_to_implement once a plan.md exists and is approved. Transition to in_progress with `syntaur implement` when coding begins.',\n },\n in_progress: {\n meaning: 'An assigned agent is actively working the assignment.',\n useWhen: 'Use in_progress once the work has started and dependencies are satisfied.',\n },\n blocked: {\n meaning: 'The assignment hit a manual or runtime obstacle.',\n useWhen: 'Use blocked when work hits an obstacle. Adding a blockedReason is recommended for traceability.',\n },\n review: {\n meaning: 'Implementation is ready for inspection or validation.',\n useWhen: 'Use review after active work is ready to be checked before completion.',\n },\n completed: {\n meaning: 'The assignment is done.',\n useWhen: 'Use completed when the acceptance criteria are satisfied.',\n },\n failed: {\n meaning: 'The assignment could not be completed as planned.',\n useWhen: 'Use failed when the work cannot be recovered within the current assignment.',\n },\n};\n\nasync function buildStatusGuide(): Promise<HelpStatusGuideEntry[]> {\n const config = await getStatusConfig();\n\n return config.statuses.map((s) => {\n const defaults = DEFAULT_STATUS_GUIDE[s.id];\n return {\n status: s.id,\n meaning: s.description ?? defaults?.meaning ?? `The assignment is in the \"${s.label}\" state.`,\n useWhen: defaults?.useWhen ?? `Use ${s.id} when appropriate for the \"${s.label}\" workflow state.`,\n };\n });\n}\n\nexport async function getDashboardHelp(): Promise<HelpResponse> {\n return {\n generatedAt: new Date().toISOString(),\n whatIsSyntaur: {\n summary:\n 'Syntaur is a local-first, markdown-backed agent work system. The dashboard is a live view over project folders and files on disk.',\n bullets: [\n 'Markdown files are the source of truth.',\n 'The UI reads project folders, assignment files, and derived indexes from the local filesystem.',\n 'Derived underscore-prefixed files are projections, not the canonical edit target.',\n ],\n },\n coreConcepts: [\n {\n term: 'Project',\n description:\n 'A project is the higher-level objective. It owns assignments, shared resources, and project memories.',\n },\n {\n term: 'Assignment',\n description:\n 'An assignment is a concrete unit of execution. Assignment frontmatter is the source of truth for status, priority, assignee, and dependencies.',\n },\n {\n term: 'Resource',\n description:\n 'A project-level shared reference file that provides source material or constraints for the work.',\n },\n {\n term: 'Memory',\n description:\n 'A project-level learning or pattern captured during execution so future assignments can reuse it.',\n },\n {\n term: 'Manifest',\n description:\n 'A derived navigation file that points agents at the project overview, indexes, and agent instructions.',\n },\n {\n term: 'Derived file',\n description:\n 'An underscore-prefixed file regenerated from canonical markdown sources. Read it, but do not edit it directly.',\n },\n {\n term: 'Handoff',\n description:\n 'An append-only log that records baton-passes between agents or sessions without rewriting prior history.',\n },\n {\n term: 'Decision record',\n description:\n 'An append-only record of important decisions, rationale, and follow-up consequences.',\n },\n {\n term: 'Playbook',\n description:\n 'A behavioral rule set stored in ~/.syntaur/playbooks/. Playbooks define constraints and conventions that agents must follow during execution. Manage them via the CLI or the Playbooks page.',\n },\n {\n term: 'Workspace',\n description:\n 'The repository context for an assignment, including the repository path, worktree path, branch, and parent branch. Workspace fields connect an assignment to the code being worked on and define write boundaries.',\n },\n {\n term: 'Agent Session',\n description:\n 'A tracked AI session tied to assignment work. Sessions are registered via the track-session CLI command or the Claude Code plugin and visible on the Agent Sessions page.',\n },\n {\n term: 'Server',\n description:\n 'A tracked tmux session with automatic port discovery, branch detection, and assignment linking. The Servers page shows all tracked sessions with their windows, panes, and discovered services.',\n },\n ],\n workflow: WORKFLOW,\n statusGuide: await buildStatusGuide(),\n ownershipRules: [\n {\n label: 'Human-authored files',\n files: ['project.md', 'agent.md', 'claude.md'],\n description:\n 'These files define project intent and instructions. The dashboard treats project status as derived except for the archive fields.',\n },\n {\n label: 'Assignment working files',\n files: ['assignment.md', 'plan*.md (optional, versioned)', 'scratchpad.md'],\n description:\n 'These are agent-writable files. The dashboard lets you edit the source markdown while preserving unsupported frontmatter keys.',\n },\n {\n label: 'Append-only logs',\n files: ['handoff.md', 'decision-record.md'],\n description:\n 'These logs preserve history. The dashboard appends new entries instead of rewriting previous ones.',\n },\n {\n label: 'Derived files',\n files: ['_status.md', '_index-assignments.md', '_index-plans.md', '_index-decisions.md'],\n description:\n 'These files are read-only projections. They can lag behind source files, so the dashboard computes source-first state.',\n },\n ],\n commands: CLI_COMMANDS,\n navigation: [\n {\n label: 'Overview',\n description: 'Triage hub showing assignments that need action, recent activity, progress stats, and first-run setup guidance.',\n href: '/',\n },\n {\n label: 'Projects',\n description: 'Browse, search, filter, and sort the project directory. Create new projects and drill into project workspaces.',\n href: '/projects',\n },\n {\n label: 'Assignments',\n description: 'Cross-project kanban board of all assignments. Drag cards between columns to change status, or filter by project, assignee, or status.',\n href: '/assignments',\n },\n {\n label: 'Servers',\n description: 'Tracked tmux sessions with auto-discovered ports, URLs, git branches, and links to related assignments. Register sessions manually or let autodiscovery find them.',\n href: '/servers',\n },\n {\n label: 'Agent Sessions',\n description: 'Monitor which AI agents are currently working, what assignments they are linked to, and session duration. Sessions are registered via the Claude Code plugin or track-session CLI command.',\n href: '/agent-sessions',\n },\n {\n label: 'Playbooks',\n description: 'Create, browse, and edit behavioral rules that agents must follow. The playbook manifest at ~/.syntaur/playbooks/manifest.md is auto-generated for inclusion in agent instructions.',\n href: '/playbooks',\n },\n {\n label: 'Help',\n description: 'This page. Status guide, CLI quick reference, core concepts, and FAQ.',\n href: '/help',\n },\n {\n label: 'Settings',\n description: 'Customize status definitions, labels, colors, display order, and done states. Changes apply globally across the dashboard and CLI.',\n href: '/settings',\n },\n {\n label: 'Project page',\n description: 'The project workspace shows health stats, assignment list, dependency graph, shared resources, and memories.',\n href: '/projects',\n },\n {\n label: 'Assignment page',\n description: 'The assignment workspace shows lifecycle actions, plan editor, scratchpad, handoff log, decision records, and agent sessions.',\n href: '/projects',\n },\n ],\n faq: [\n {\n question: 'Why are some files read-only in the dashboard?',\n answer:\n 'Underscore-prefixed files are derived projections that can be rebuilt from canonical markdown sources. Editing them would create drift, so the UI treats them as read-only.',\n },\n {\n question: 'Why can an assignment be pending even when nothing looks broken?',\n answer:\n 'Pending often just means the work has not started yet or it is waiting on declared dependencies. Blocked is reserved for exceptional runtime obstacles that need intervention.',\n },\n {\n question: 'How do I change an assignment\\'s status?',\n answer:\n 'Use lifecycle CLI commands (syntaur start, syntaur complete, etc.), drag cards on the kanban board, or use the Override Status dropdown on the assignment page. Any status can be set from any other status.',\n },\n {\n question: 'How do I customize statuses?',\n answer:\n 'Open the Settings page from the sidebar. You can add, remove, rename, recolor, and reorder statuses. You can also mark statuses as done states. Changes are saved to ~/.syntaur/config.md and take effect immediately across the dashboard.',\n },\n {\n question: 'What is a done state?',\n answer:\n 'A done state (also called terminal status) means the assignment is finished. Done states fill the completed portion of progress bars and satisfy dependency requirements. By default, \"completed\" and \"failed\" are done states. You can configure which statuses are done states in Settings.',\n },\n {\n question: 'What are playbooks and how do I use them?',\n answer:\n 'Playbooks are markdown files in ~/.syntaur/playbooks/ that define behavioral rules agents must follow. Create them via the CLI (syntaur create-playbook) or the Playbooks page. The auto-generated manifest at ~/.syntaur/playbooks/manifest.md can be included in your CLAUDE.md so agents pick up the rules.',\n },\n {\n question: 'How does agent session tracking work?',\n answer:\n 'When an AI agent starts working on an assignment, it can register a session via the track-session CLI command or the Claude Code plugin\\'s /track-session command. The Agent Sessions page shows active and completed sessions with their linked assignments and duration.',\n },\n {\n question: 'How does server tracking work?',\n answer:\n 'Syntaur tracks tmux sessions to discover running dev servers, their ports, git branches, and linked assignments. Register sessions on the Servers page or let autodiscovery find them. Pane info refreshes automatically.',\n },\n ],\n firstProjectChecklist: [\n {\n title: 'Create the project',\n detail: 'Describe the overall objective in project.md, then add tags and archive metadata only when needed.',\n command: CLI_COMMANDS[1],\n href: '/create/project',\n },\n {\n title: 'Create at least one assignment',\n detail: 'Break the project into executable work units with explicit priority and dependencies.',\n command: CLI_COMMANDS[2],\n },\n {\n title: 'Assign and start the first assignment',\n detail: 'Set an assignee, then start the assignment once prerequisites are complete.',\n command: CLI_COMMANDS[3],\n },\n {\n title: 'Use the assignment workspace for execution',\n detail: 'Keep the objective and todos in assignment.md, implementation plans in optional versioned plan files (plan.md, plan-v2.md, ...), and transient notes in scratchpad.md.',\n href: '/projects',\n },\n {\n title: 'Record handoffs and decisions without rewriting history',\n detail: 'Append new handoff and decision entries instead of editing prior entries.',\n },\n {\n title: 'Return to Overview for triage',\n detail: 'Overview surfaces the queue of assignments that need action next.',\n href: '/',\n },\n ],\n links: [\n { label: 'Overview', href: '/' },\n { label: 'Project Directory', href: '/projects' },\n { label: 'Assignments Board', href: '/assignments' },\n { label: 'Servers', href: '/servers' },\n { label: 'Agent Sessions', href: '/agent-sessions' },\n { label: 'Playbooks', href: '/playbooks' },\n { label: 'Settings', href: '/settings' },\n { label: 'Create Project', href: '/create/project' },\n ],\n };\n}\n\nexport function getHelpCommandNames(): string[] {\n return CLI_COMMANDS.map((command) => command.command.replace(/^syntaur\\s+/, ''));\n}\n","import Database from 'better-sqlite3';\nimport { resolve } from 'node:path';\nimport { readdir } from 'node:fs/promises';\nimport { syntaurRoot } from '../utils/paths.js';\nimport { fileExists } from '../utils/fs.js';\nimport type { AgentSession, AgentSessionStatus } from './types.js';\n\nlet db: Database.Database | null = null;\n\nconst SCHEMA_VERSION = '4';\n\n// The base schema deliberately OMITS the project_slug indexes — they are\n// created after any legacy-schema migrations run below. Older installs may\n// have the `mission_slug` column, and creating an index that references\n// `project_slug` before the rename migration runs would fail.\nconst SCHEMA_SQL = `\nCREATE TABLE IF NOT EXISTS sessions (\n session_id TEXT PRIMARY KEY,\n project_slug TEXT,\n assignment_slug TEXT,\n agent TEXT NOT NULL,\n started TEXT NOT NULL,\n ended TEXT,\n status TEXT NOT NULL DEFAULT 'active',\n path TEXT,\n description TEXT,\n transcript_path TEXT,\n pid INTEGER,\n pid_started_at TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\nCREATE INDEX IF NOT EXISTS idx_sessions_status ON sessions(status);\nCREATE TABLE IF NOT EXISTS meta (key TEXT PRIMARY KEY, value TEXT);\n`;\n\nconst POST_MIGRATION_INDEXES_SQL = `\nCREATE INDEX IF NOT EXISTS idx_sessions_project ON sessions(project_slug);\nCREATE INDEX IF NOT EXISTS idx_sessions_assignment ON sessions(project_slug, assignment_slug);\n`;\n\n/**\n * Initialize the SQLite database for session tracking.\n * Creates the database file and schema if they don't exist.\n * @param dbPath Optional override for the database file path (used in tests).\n */\nexport function initSessionDb(dbPath?: string): Database.Database {\n if (db) return db;\n\n const finalPath = dbPath ?? resolve(syntaurRoot(), 'syntaur.db');\n db = new Database(finalPath);\n db.pragma('journal_mode = WAL');\n db.exec(SCHEMA_SQL);\n\n // Track schema version\n db.prepare('INSERT OR IGNORE INTO meta (key, value) VALUES (?, ?)').run(\n 'schema_version',\n SCHEMA_VERSION,\n );\n\n // Run migrations inside an EXCLUSIVE transaction. This closes two races:\n // 1. Crash between `DROP TABLE` / `RENAME` / `UPDATE meta` leaves the db\n // half-upgraded — the transaction rolls back on failure.\n // 2. Two processes (e.g. `syntaur dashboard` + `syntaur track-session`)\n // both calling initSessionDb() at once — EXCLUSIVE serializes the\n // migration and the version is re-checked inside the transaction so\n // the second process becomes a no-op once the first commits.\n // Narrow for the transaction closure — TS doesn't track the module-level\n // `db` assignment across the closure boundary.\n const database = db;\n const runMigrations = database.transaction(() => {\n // --- v1 → v2: make project/assignment nullable, add description ---\n const vBeforeV2 = (\n database\n .prepare(\"SELECT value FROM meta WHERE key = 'schema_version'\")\n .get() as { value: string } | undefined\n )?.value;\n\n if (vBeforeV2 === '1') {\n database.exec(`\n CREATE TABLE sessions_v2 (\n session_id TEXT PRIMARY KEY,\n project_slug TEXT,\n assignment_slug TEXT,\n agent TEXT NOT NULL,\n started TEXT NOT NULL,\n ended TEXT,\n status TEXT NOT NULL DEFAULT 'active',\n path TEXT,\n description TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n );\n INSERT INTO sessions_v2 SELECT session_id, project_slug, assignment_slug, agent, started, ended, status, path, NULL, created_at, updated_at FROM sessions;\n DROP TABLE sessions;\n ALTER TABLE sessions_v2 RENAME TO sessions;\n CREATE INDEX IF NOT EXISTS idx_sessions_project ON sessions(project_slug);\n CREATE INDEX IF NOT EXISTS idx_sessions_assignment ON sessions(project_slug, assignment_slug);\n CREATE INDEX IF NOT EXISTS idx_sessions_status ON sessions(status);\n UPDATE meta SET value = '2' WHERE key = 'schema_version';\n `);\n }\n\n // --- v2 → v3: add transcript_path, normalize legacy mission_slug ---\n // Re-read the version AFTER v1→v2 may have run.\n const vBeforeV3 = (\n database\n .prepare(\"SELECT value FROM meta WHERE key = 'schema_version'\")\n .get() as { value: string } | undefined\n )?.value;\n\n if (vBeforeV3 === '2') {\n const v2Columns = database\n .prepare('PRAGMA table_info(sessions)')\n .all() as Array<{ name: string }>;\n const v2ColNames = v2Columns.map((c) => c.name);\n const hasProject = v2ColNames.includes('project_slug');\n const hasMission = v2ColNames.includes('mission_slug');\n\n // If a db somehow has both columns (e.g. a partially-renamed table),\n // prefer project_slug but fall back to mission_slug so rows that only\n // populated mission_slug aren't dropped.\n const projectSlugExpr =\n hasProject && hasMission\n ? 'COALESCE(project_slug, mission_slug)'\n : hasProject\n ? 'project_slug'\n : hasMission\n ? 'mission_slug'\n : null;\n\n if (!projectSlugExpr) {\n throw new Error(\n 'sessions table has neither project_slug nor mission_slug; cannot migrate from v2 to v3',\n );\n }\n\n database.exec(`\n CREATE TABLE sessions_v3 (\n session_id TEXT PRIMARY KEY,\n project_slug TEXT,\n assignment_slug TEXT,\n agent TEXT NOT NULL,\n started TEXT NOT NULL,\n ended TEXT,\n status TEXT NOT NULL DEFAULT 'active',\n path TEXT,\n description TEXT,\n transcript_path TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n );\n INSERT INTO sessions_v3\n SELECT session_id, ${projectSlugExpr}, assignment_slug, agent, started, ended, status, path, description, NULL, created_at, updated_at\n FROM sessions;\n DROP TABLE sessions;\n ALTER TABLE sessions_v3 RENAME TO sessions;\n CREATE INDEX IF NOT EXISTS idx_sessions_project ON sessions(project_slug);\n CREATE INDEX IF NOT EXISTS idx_sessions_assignment ON sessions(project_slug, assignment_slug);\n CREATE INDEX IF NOT EXISTS idx_sessions_status ON sessions(status);\n UPDATE meta SET value = '3' WHERE key = 'schema_version';\n `);\n }\n\n // --- v3 → v4: add pid + pid_started_at for liveness detection ---\n const vBeforeV4 = (\n database\n .prepare(\"SELECT value FROM meta WHERE key = 'schema_version'\")\n .get() as { value: string } | undefined\n )?.value;\n\n if (vBeforeV4 === '3') {\n database.exec(`\n CREATE TABLE sessions_v4 (\n session_id TEXT PRIMARY KEY,\n project_slug TEXT,\n assignment_slug TEXT,\n agent TEXT NOT NULL,\n started TEXT NOT NULL,\n ended TEXT,\n status TEXT NOT NULL DEFAULT 'active',\n path TEXT,\n description TEXT,\n transcript_path TEXT,\n pid INTEGER,\n pid_started_at TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n );\n INSERT INTO sessions_v4\n SELECT session_id, project_slug, assignment_slug, agent, started, ended, status, path, description, transcript_path, NULL, NULL, created_at, updated_at\n FROM sessions;\n DROP TABLE sessions;\n ALTER TABLE sessions_v4 RENAME TO sessions;\n CREATE INDEX IF NOT EXISTS idx_sessions_project ON sessions(project_slug);\n CREATE INDEX IF NOT EXISTS idx_sessions_assignment ON sessions(project_slug, assignment_slug);\n CREATE INDEX IF NOT EXISTS idx_sessions_status ON sessions(status);\n UPDATE meta SET value = '4' WHERE key = 'schema_version';\n `);\n }\n });\n runMigrations.exclusive();\n\n // Create project-slug-dependent indexes now that we know the column exists.\n db.exec(POST_MIGRATION_INDEXES_SQL);\n\n return db;\n}\n\n/**\n * Get the initialized database handle.\n * Throws if initSessionDb() has not been called.\n */\nexport function getSessionDb(): Database.Database {\n if (!db) {\n throw new Error(\n 'Session database not initialized. Call initSessionDb() first.',\n );\n }\n return db;\n}\n\n/**\n * Close the database connection.\n */\nexport function closeSessionDb(): void {\n if (db) {\n db.close();\n db = null;\n }\n}\n\n/**\n * Reset the singleton for testing purposes.\n */\nexport function resetSessionDb(): void {\n db = null;\n}\n\n/**\n * One-time migration: import sessions from markdown _index-sessions.md files into SQLite.\n * Only runs if the sessions table is empty and markdown files exist.\n */\nexport async function migrateFromMarkdown(projectsDir: string): Promise<number> {\n const database = getSessionDb();\n\n // Skip if sessions already exist in the database\n const count = database.prepare('SELECT COUNT(*) as count FROM sessions').get() as { count: number };\n if (count.count > 0) return 0;\n\n if (!(await fileExists(projectsDir))) return 0;\n\n const entries = await readdir(projectsDir, { withFileTypes: true });\n const allSessions: AgentSession[] = [];\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n const projectDir = resolve(projectsDir, entry.name);\n const indexPath = resolve(projectDir, '_index-sessions.md');\n if (!(await fileExists(indexPath))) continue;\n\n const sessions = await parseMarkdownSessionsIndex(indexPath, entry.name);\n allSessions.push(...sessions);\n }\n\n if (allSessions.length === 0) return 0;\n\n const insert = database.prepare(`\n INSERT OR IGNORE INTO sessions (session_id, project_slug, assignment_slug, agent, started, status, path)\n VALUES (?, ?, ?, ?, ?, ?, ?)\n `);\n\n const insertAll = database.transaction((sessions: AgentSession[]) => {\n for (const s of sessions) {\n insert.run(s.sessionId, s.projectSlug, s.assignmentSlug, s.agent, s.started, s.status, s.path);\n }\n });\n\n insertAll(allSessions);\n console.log(`Migrated ${allSessions.length} sessions from markdown to SQLite.`);\n return allSessions.length;\n}\n\n/**\n * Parse an _index-sessions.md file into AgentSession objects.\n * Used only for one-time migration. This is a copy of the old parsing logic.\n */\nasync function parseMarkdownSessionsIndex(\n filePath: string,\n projectSlug: string,\n): Promise<AgentSession[]> {\n const { readFile } = await import('node:fs/promises');\n const raw = await readFile(filePath, 'utf-8');\n const sessions: AgentSession[] = [];\n\n const lines = raw.split('\\n');\n let inTable = false;\n let headerSeen = false;\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n\n if (trimmed.startsWith('| Assignment') || trimmed.startsWith('|Assignment')) {\n inTable = true;\n headerSeen = false;\n continue;\n }\n\n if (inTable && !headerSeen && trimmed.match(/^\\|[-\\s|]+\\|$/)) {\n headerSeen = true;\n continue;\n }\n\n if (inTable && headerSeen && trimmed.startsWith('|')) {\n const cells = trimmed\n .split('|')\n .slice(1, -1)\n .map((c) => c.trim());\n\n if (cells.length >= 6) {\n sessions.push({\n assignmentSlug: cells[0],\n agent: cells[1],\n sessionId: cells[2],\n started: cells[3],\n status: (cells[4] as AgentSessionStatus) || 'active',\n path: cells[5],\n projectSlug,\n });\n }\n }\n }\n\n return sessions;\n}\n","import { readFile } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { fileExists } from '../utils/fs.js';\nimport { getSessionDb } from './session-db.js';\nimport type { AgentSession, AgentSessionStatus } from './types.js';\n\ninterface SessionRow {\n session_id: string;\n project_slug: string | null;\n assignment_slug: string | null;\n agent: string;\n started: string;\n ended: string | null;\n status: string;\n path: string | null;\n description: string | null;\n transcript_path: string | null;\n pid: number | null;\n pid_started_at: string | null;\n}\n\nfunction rowToSession(row: SessionRow): AgentSession {\n return {\n sessionId: row.session_id,\n projectSlug: row.project_slug ?? null,\n assignmentSlug: row.assignment_slug ?? null,\n agent: row.agent,\n started: row.started,\n ended: row.ended ?? null,\n status: row.status as AgentSessionStatus,\n path: row.path ?? '',\n description: row.description ?? null,\n transcriptPath: row.transcript_path ?? null,\n pid: row.pid ?? null,\n pidStartedAt: row.pid_started_at ?? null,\n };\n}\n\n/**\n * Query sessions for a specific project.\n */\nexport async function parseSessionsIndex(\n _projectDir: string,\n projectSlug: string,\n): Promise<AgentSession[]> {\n const db = getSessionDb();\n const rows = db\n .prepare('SELECT * FROM sessions WHERE project_slug = ? ORDER BY started DESC')\n .all(projectSlug) as SessionRow[];\n return rows.map(rowToSession);\n}\n\n/**\n * Upsert a session keyed on `session_id`.\n *\n * On conflict, non-null fields in the new payload fill in missing values on the\n * existing row (COALESCE). `started` / `created_at` from the first insert are\n * preserved. A session already in a terminal state (`completed` / `stopped`)\n * is NOT revived by re-registration — status only moves forward.\n *\n * Makes registration idempotent across SessionStart hooks, `/track-session`,\n * and grab-assignment all touching the same real session ID.\n */\nexport async function appendSession(\n _projectDir: string,\n session: AgentSession,\n): Promise<void> {\n const db = getSessionDb();\n db.prepare(`\n INSERT INTO sessions (session_id, project_slug, assignment_slug, agent, started, status, path, description, transcript_path, pid, pid_started_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(session_id) DO UPDATE SET\n project_slug = COALESCE(NULLIF(excluded.project_slug, ''), project_slug),\n assignment_slug = COALESCE(NULLIF(excluded.assignment_slug, ''), assignment_slug),\n agent = excluded.agent,\n status = CASE WHEN status IN ('completed','stopped') THEN status ELSE excluded.status END,\n path = COALESCE(NULLIF(excluded.path, ''), path),\n description = COALESCE(NULLIF(excluded.description, ''), description),\n transcript_path = COALESCE(NULLIF(excluded.transcript_path, ''), transcript_path),\n pid = COALESCE(excluded.pid, pid),\n pid_started_at = COALESCE(NULLIF(excluded.pid_started_at, ''), pid_started_at),\n updated_at = datetime('now')\n `).run(\n session.sessionId,\n session.projectSlug ?? null,\n session.assignmentSlug ?? null,\n session.agent,\n session.started,\n session.status,\n session.path,\n session.description ?? null,\n session.transcriptPath ?? null,\n session.pid ?? null,\n session.pidStartedAt ?? null,\n );\n}\n\n/**\n * Update a session's status by sessionId.\n * Sets `ended` timestamp for terminal statuses (completed, stopped).\n */\nexport async function updateSessionStatus(\n _projectDir: string,\n sessionId: string,\n status: AgentSessionStatus,\n): Promise<boolean> {\n const db = getSessionDb();\n const isTerminal = status === 'completed' || status === 'stopped';\n\n const result = isTerminal\n ? db\n .prepare(\n 'UPDATE sessions SET status = ?, ended = datetime(\\'now\\'), updated_at = datetime(\\'now\\') WHERE session_id = ?',\n )\n .run(status, sessionId)\n : db\n .prepare(\n 'UPDATE sessions SET status = ?, updated_at = datetime(\\'now\\') WHERE session_id = ?',\n )\n .run(status, sessionId);\n\n return result.changes > 0;\n}\n\n/**\n * List all sessions across all projects.\n */\nexport async function listAllSessions(_projectsDir: string): Promise<AgentSession[]> {\n const db = getSessionDb();\n const rows = db\n .prepare('SELECT * FROM sessions ORDER BY started DESC')\n .all() as SessionRow[];\n return rows.map(rowToSession);\n}\n\n/**\n * Fetch a single session by its agent-assigned session id.\n * Returns null when no row matches. Throws if initSessionDb() has not run.\n */\nexport function getSessionById(sessionId: string): AgentSession | null {\n const db = getSessionDb();\n const row = db\n .prepare('SELECT * FROM sessions WHERE session_id = ? LIMIT 1')\n .get(sessionId) as SessionRow | undefined;\n return row ? rowToSession(row) : null;\n}\n\n/**\n * List sessions for a specific project, optionally filtered by assignment.\n */\nexport async function listProjectSessions(\n _projectsDir: string,\n projectSlug: string,\n assignmentSlug?: string,\n): Promise<AgentSession[]> {\n const db = getSessionDb();\n\n if (assignmentSlug) {\n const rows = db\n .prepare(\n 'SELECT * FROM sessions WHERE project_slug = ? AND assignment_slug = ? ORDER BY started DESC',\n )\n .all(projectSlug, assignmentSlug) as SessionRow[];\n return rows.map(rowToSession);\n }\n\n const rows = db\n .prepare('SELECT * FROM sessions WHERE project_slug = ? ORDER BY started DESC')\n .all(projectSlug) as SessionRow[];\n return rows.map(rowToSession);\n}\n\n/**\n * Delete sessions by their IDs. Returns the number of rows deleted.\n */\nexport async function deleteSessions(sessionIds: string[]): Promise<number> {\n if (sessionIds.length === 0) return 0;\n const db = getSessionDb();\n const placeholders = sessionIds.map(() => '?').join(', ');\n const result = db\n .prepare(`DELETE FROM sessions WHERE session_id IN (${placeholders})`)\n .run(...sessionIds);\n return result.changes;\n}\n\n// Statuses that imply the working session is done (review means agent finished)\nconst DONE_ASSIGNMENT_STATUSES = new Set(['completed', 'failed', 'review']);\n\n/**\n * Read the status field from an assignment.md frontmatter without full parsing.\n */\nasync function readAssignmentStatusFromPath(\n assignmentMdPath: string,\n): Promise<string | null> {\n if (!(await fileExists(assignmentMdPath))) return null;\n const raw = await readFile(assignmentMdPath, 'utf-8');\n const match = raw.match(/^status:\\s*(.+)$/m);\n return match ? match[1].trim() : null;\n}\n\nasync function readAssignmentStatus(\n projectDir: string,\n assignmentSlug: string,\n): Promise<string | null> {\n return readAssignmentStatusFromPath(\n resolve(projectDir, 'assignments', assignmentSlug, 'assignment.md'),\n );\n}\n\n/**\n * Reconcile active sessions against assignment statuses.\n * Sessions whose assignments have moved to completed/failed/review are\n * marked as completed (or stopped for failed assignments).\n * Standalone sessions (project_slug NULL) are resolved via assignmentsDir.\n * Returns the number of sessions that were updated.\n */\nexport async function reconcileActiveSessions(\n projectsDir: string,\n assignmentsDir?: string,\n): Promise<number> {\n const db = getSessionDb();\n\n // Include standalone sessions (project_slug NULL) when assignmentsDir is provided.\n const activeSessions = db\n .prepare('SELECT * FROM sessions WHERE status = \\'active\\' AND assignment_slug IS NOT NULL')\n .all() as SessionRow[];\n\n if (activeSessions.length === 0) return 0;\n\n // Read assignment statuses from disk. Key is `${projectSlug ?? '__standalone__'}/${slug}`.\n const assignmentStatuses = new Map<string, string>();\n const seen = new Set<string>();\n for (const session of activeSessions) {\n const aslug = session.assignment_slug;\n if (!aslug) continue;\n\n const projectKey = session.project_slug ?? '__standalone__';\n const key = `${projectKey}/${aslug}`;\n if (seen.has(key)) continue;\n seen.add(key);\n\n if (session.project_slug) {\n const status = await readAssignmentStatus(\n resolve(projectsDir, session.project_slug),\n aslug,\n );\n if (status) assignmentStatuses.set(key, status);\n } else if (assignmentsDir) {\n const status = await readAssignmentStatusFromPath(\n resolve(assignmentsDir, aslug, 'assignment.md'),\n );\n if (status) assignmentStatuses.set(key, status);\n }\n }\n\n // Update stale sessions\n let totalUpdated = 0;\n for (const session of activeSessions) {\n const projectKey = session.project_slug ?? '__standalone__';\n const key = `${projectKey}/${session.assignment_slug}`;\n const assignmentStatus = assignmentStatuses.get(key);\n if (!assignmentStatus || !DONE_ASSIGNMENT_STATUSES.has(assignmentStatus)) continue;\n\n const newStatus: AgentSessionStatus =\n assignmentStatus === 'failed' ? 'stopped' : 'completed';\n await updateSessionStatus('', session.session_id, newStatus);\n totalUpdated++;\n }\n\n return totalUpdated;\n}\n\n/**\n * List sessions for a resolved assignment (standalone or project-nested).\n * Standalone: filter by assignment_slug = id AND project_slug IS NULL.\n * Project-nested: filter by project_slug + assignment_slug.\n */\nexport async function listSessionsByAssignment(\n projectSlug: string | null,\n assignmentSlug: string,\n): Promise<AgentSession[]> {\n const db = getSessionDb();\n const rows = projectSlug === null\n ? (db\n .prepare(\n 'SELECT * FROM sessions WHERE assignment_slug = ? AND project_slug IS NULL ORDER BY started DESC',\n )\n .all(assignmentSlug) as SessionRow[])\n : (db\n .prepare(\n 'SELECT * FROM sessions WHERE project_slug = ? AND assignment_slug = ? ORDER BY started DESC',\n )\n .all(projectSlug, assignmentSlug) as SessionRow[]);\n return rows.map(rowToSession);\n}\n","/**\n * Locked Overview copy. Single source of truth for hero, segment, and dialog strings.\n *\n * Both the backend (`api.ts` hero + reason emission) and the frontend\n * (`OverviewHero`, `OverviewSegment`, etc.) import from this module so copy\n * cannot drift between the API payload and what the UI renders.\n */\n\nexport type HeroCopyKey =\n | 'review'\n | 'review.singular'\n | 'ready_to_implement'\n | 'ready_to_implement.singular'\n | 'ready_for_planning'\n | 'ready_for_planning.singular'\n | 'in_progress'\n | 'in_progress.singular'\n | 'draft'\n | 'draft.singular'\n | 'blocked'\n | 'blocked.singular'\n | 'stale'\n | 'stale.singular'\n | 'clean';\n\n/**\n * Hero strings. The `{total}` and `{title}` placeholders are substituted at\n * render time. Singular variants are used when `total === 1`.\n */\nexport const HERO_COPY: Record<HeroCopyKey, string> = {\n review: '{total} items ready for your review',\n 'review.singular': 'Review {title}',\n ready_to_implement: '{total} plans ready to implement — start with {title}',\n 'ready_to_implement.singular': 'Start implementing {title}',\n ready_for_planning: '{total} assignments ready to plan — start with {title}',\n 'ready_for_planning.singular': 'Plan {title}',\n in_progress: 'Resume {title} ({total} in progress)',\n 'in_progress.singular': 'Resume {title}',\n draft: 'Shape your {total} drafts — start with {title}',\n 'draft.singular': 'Shape {title}',\n blocked: 'Unblock {title} ({total} blocked)',\n 'blocked.singular': 'Unblock {title}',\n stale: 'Triage {total} stale items',\n 'stale.singular': 'Triage {title} — sitting stale',\n clean: 'You’re all clear. Nothing needs you right now.',\n};\n\nexport type SegmentId =\n | 'readyForReview'\n | 'readyToImplement'\n | 'readyForPlanning'\n | 'inProgress'\n | 'drafts'\n | 'blocked'\n | 'newestCreated'\n | 'stale';\n\n/** Per-segment row reason (the one-liner under the title). */\nexport const SEGMENT_REASON: Record<SegmentId, string> = {\n readyForReview: 'Ready for your review',\n readyToImplement: 'Plan finalized — ready to implement',\n readyForPlanning: 'Ready to plan',\n inProgress: 'In progress',\n drafts: 'Draft — needs shape',\n blocked: 'Blocked',\n newestCreated: 'Newly created',\n stale: 'Sitting stale',\n};\n\n/** Per-segment empty state copy. */\nexport const SEGMENT_EMPTY: Record<SegmentId, string> = {\n readyForReview: 'No assignments waiting for your review.',\n readyToImplement: 'No plans queued for implementation.',\n readyForPlanning: 'No assignments waiting to be planned.',\n inProgress: 'Nothing actively in progress.',\n drafts: 'No drafts — ideas captured here will live until they’re shaped.',\n blocked: 'Nothing is blocked. Good.',\n newestCreated: 'No assignments created recently.',\n stale: 'No stale work — everything is fresh.',\n};\n\n/** Per-segment header titles. */\nexport const SEGMENT_TITLE: Record<SegmentId, string> = {\n readyForReview: 'Ready for Review',\n readyToImplement: 'Ready to Implement',\n readyForPlanning: 'Ready for Planning',\n inProgress: 'In Progress',\n drafts: 'Drafts',\n blocked: 'Blocked',\n newestCreated: 'Newest Created',\n stale: 'Stale',\n};\n\n/** Dialog + button copy used across Overview components. */\nexport const DIALOG_COPY = {\n claimAsTitle: 'Claim assignments as',\n claimAsHint: 'Used when you claim an assignment from this dashboard. You can change it later in settings.',\n claimAsSubmit: 'Save',\n claimAsRemember: 'Remember this choice',\n quickCommentTitle: 'Add a quick note',\n quickCommentPlaceholder: 'Note…',\n quickCommentSubmit: 'Post',\n bulkArchiveLabel: 'Archive selected',\n bulkClearLabel: 'Clear',\n bulkPartialFailureBanner: 'Some items failed to archive. The list has been refreshed.',\n emptyStateCleanTitle: 'You’re all clear',\n emptyStateCleanCTA: 'Browse projects',\n draftsHeaderCTA: 'Shape →',\n staleLoadMore: 'Load more',\n staleLoadMoreRemaining: '{remaining} remaining',\n recentSessionsEmptyTitle: 'No recent sessions',\n recentSessionsEmptyHint: 'Use /grab-assignment or `syntaur track-session` to register one.',\n recentSessionsCopyPathLabel: 'Copy path',\n recentSessionsCopyPathDisabled: 'Session has no path',\n recentSessionsCopyFallbackHint: 'Press ⌘C to copy',\n} as const;\n\n/** Substitute `{key}` placeholders in a template. */\nexport function formatCopy(\n template: string,\n vars: Record<string, string | number>,\n): string {\n return template.replace(/\\{(\\w+)\\}/g, (_, key) => String(vars[key] ?? `{${key}}`));\n}\n","import { readdir, readFile, unlink } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { ensureDir, fileExists, writeFileForce } from '../utils/fs.js';\nimport { extractFrontmatter, getField } from './parser.js';\nimport type { SessionFileData, SessionKind } from './types.js';\n\nexport function sanitizeSessionName(name: string): string {\n return name.replace(/[^a-zA-Z0-9_-]/g, '-');\n}\n\nfunction nowTimestamp(): string {\n return new Date().toISOString();\n}\n\nexport interface BuildSessionOptions {\n session: string;\n registered: string;\n lastRefreshed: string;\n overrides: Record<string, { project: string; assignment: string }>;\n auto?: boolean;\n kind?: SessionKind;\n pid?: number;\n ports?: number[];\n cwd?: string;\n}\n\nexport function buildSessionContent(opts: BuildSessionOptions): string {\n const lines = [\n '---',\n `session: ${opts.session}`,\n `registered: ${opts.registered}`,\n `last_refreshed: ${opts.lastRefreshed}`,\n ];\n\n if (opts.auto != null) {\n lines.push(`auto: ${opts.auto}`);\n }\n if (opts.kind) {\n lines.push(`kind: ${opts.kind}`);\n }\n if (opts.pid != null) {\n lines.push(`pid: ${opts.pid}`);\n }\n if (opts.ports && opts.ports.length > 0) {\n lines.push(`ports: [${opts.ports.join(', ')}]`);\n }\n if (opts.cwd) {\n lines.push(`cwd: ${opts.cwd}`);\n }\n\n if (Object.keys(opts.overrides).length > 0) {\n lines.push('overrides:');\n for (const [key, val] of Object.entries(opts.overrides)) {\n lines.push(` \"${key}\": { project: \"${val.project}\", assignment: \"${val.assignment}\" }`);\n }\n }\n\n lines.push('---', '');\n return lines.join('\\n');\n}\n\nexport async function registerSession(dir: string, rawName: string): Promise<string> {\n const name = sanitizeSessionName(rawName);\n await ensureDir(dir);\n const now = nowTimestamp();\n const content = buildSessionContent({\n session: name, registered: now, lastRefreshed: now, overrides: {},\n });\n await writeFileForce(resolve(dir, `${name}.md`), content);\n return name;\n}\n\nexport async function listSessionFiles(dir: string): Promise<string[]> {\n if (!(await fileExists(dir))) return [];\n const entries = await readdir(dir);\n return entries\n .filter((f) => f.endsWith('.md'))\n .map((f) => f.replace(/\\.md$/, ''));\n}\n\nexport async function readSessionFile(dir: string, name: string): Promise<SessionFileData | null> {\n const filePath = resolve(dir, `${sanitizeSessionName(name)}.md`);\n if (!(await fileExists(filePath))) return null;\n\n const raw = await readFile(filePath, 'utf-8');\n const [frontmatter] = extractFrontmatter(raw);\n if (!frontmatter) return null;\n\n const session = getField(frontmatter, 'session') ?? name;\n const registered = getField(frontmatter, 'registered') ?? '';\n const lastRefreshed = getField(frontmatter, 'last_refreshed') ?? '';\n\n // Parse overrides block\n const overrides: Record<string, { project: string; assignment: string }> = {};\n const overridesMatch = frontmatter.match(/^overrides:\\n((?:\\s+\".+\\n?)*)/m);\n if (overridesMatch) {\n const overrideLines = overridesMatch[1].matchAll(\n /^\\s+\"([^\"]+)\":\\s*\\{\\s*project:\\s*\"([^\"]+)\",\\s*assignment:\\s*\"([^\"]+)\"\\s*\\}/gm,\n );\n for (const m of overrideLines) {\n overrides[m[1]] = { project: m[2], assignment: m[3] };\n }\n }\n\n const autoField = getField(frontmatter, 'auto');\n const auto = autoField === 'true' ? true : autoField === 'false' ? false : undefined;\n const kind = getField(frontmatter, 'kind') as SessionKind | undefined;\n const pidField = getField(frontmatter, 'pid');\n const pid = pidField ? parseInt(pidField, 10) : undefined;\n const cwdField = getField(frontmatter, 'cwd');\n\n let ports: number[] | undefined;\n const portsMatch = frontmatter.match(/^ports:\\s*\\[([^\\]]*)\\]/m);\n if (portsMatch) {\n ports = portsMatch[1].split(',').map((s) => parseInt(s.trim(), 10)).filter((n) => !isNaN(n));\n }\n\n return {\n session, registered, lastRefreshed, overrides,\n ...(auto != null && { auto }),\n ...(kind && { kind }),\n ...(pid != null && !isNaN(pid) && { pid }),\n ...(ports && ports.length > 0 && { ports }),\n ...(cwdField && { cwd: cwdField }),\n };\n}\n\nexport async function removeSession(dir: string, name: string): Promise<void> {\n const filePath = resolve(dir, `${sanitizeSessionName(name)}.md`);\n if (await fileExists(filePath)) {\n await unlink(filePath);\n }\n}\n\nexport async function updateLastRefreshed(dir: string, name: string): Promise<void> {\n const data = await readSessionFile(dir, name);\n if (!data) return;\n const content = buildSessionContent({ ...data, lastRefreshed: nowTimestamp() });\n await writeFileForce(resolve(dir, `${sanitizeSessionName(name)}.md`), content);\n}\n\nexport async function setOverride(\n dir: string,\n sessionName: string,\n windowIndex: number,\n paneIndex: number,\n assignment: { project: string; assignment: string } | null,\n): Promise<void> {\n const data = await readSessionFile(dir, sessionName);\n if (!data) return;\n const key = `${windowIndex}:${paneIndex}`;\n if (assignment) {\n data.overrides[key] = assignment;\n } else {\n delete data.overrides[key];\n }\n const content = buildSessionContent({ ...data });\n await writeFileForce(resolve(dir, `${sanitizeSessionName(sessionName)}.md`), content);\n}\n\nexport interface RegisterAutoOptions {\n kind: SessionKind;\n pid?: number;\n ports?: number[];\n cwd?: string;\n}\n\nexport async function registerAutoSession(\n dir: string,\n rawName: string,\n opts: RegisterAutoOptions,\n): Promise<string> {\n const name = sanitizeSessionName(rawName);\n await ensureDir(dir);\n const now = nowTimestamp();\n const content = buildSessionContent({\n session: name,\n registered: now,\n lastRefreshed: now,\n overrides: {},\n auto: true,\n kind: opts.kind,\n pid: opts.pid,\n ports: opts.ports,\n cwd: opts.cwd,\n });\n await writeFileForce(resolve(dir, `${name}.md`), content);\n return name;\n}\n","import { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { resolve } from 'node:path';\nimport { realpath, readdir, readFile } from 'node:fs/promises';\nimport { listProjects } from './api.js';\nimport {\n readSessionFile,\n listSessionFiles,\n} from './servers.js';\nimport { extractFrontmatter, getField, getNestedField } from './parser.js';\nimport type {\n TrackedSession,\n TrackedWindow,\n TrackedPane,\n ServersResponse,\n SessionFileData,\n} from './types.js';\n\nconst exec = promisify(execFile);\n\n// --- Cache ---\nlet cache: { data: ServersResponse; expiry: number } | null = null;\nconst CACHE_TTL_MS = 10_000;\n\nexport function clearScanCache(): void {\n cache = null;\n}\n\n// --- Pure parsing functions (exported for testing) ---\n\nexport interface RawPane {\n windowIndex: number;\n windowName: string;\n paneIndex: number;\n command: string;\n cwd: string;\n pid: number;\n}\n\nexport function parseTmuxPaneOutput(output: string): RawPane[] {\n return output\n .trim()\n .split('\\n')\n .filter((line) => line.length > 0)\n .map((line) => {\n const [wi, wn, pi, cmd, cwd, pid] = line.split('|');\n return {\n windowIndex: parseInt(wi, 10),\n windowName: wn,\n paneIndex: parseInt(pi, 10),\n command: cmd,\n cwd,\n pid: parseInt(pid, 10),\n };\n });\n}\n\nexport function findListeningPorts(lsofOutput: string, pids: Set<number>): number[] {\n const ports: number[] = [];\n for (const line of lsofOutput.split('\\n')) {\n const parts = line.trim().split(/\\s+/);\n if (parts.length < 9) continue;\n const pid = parseInt(parts[1], 10);\n if (!pids.has(pid)) continue;\n const tcpAddr = parts.find((p) => p.includes(':') && /:\\d+$/.test(p));\n if (tcpAddr) {\n const port = parseInt(tcpAddr.split(':').pop()!, 10);\n if (!isNaN(port) && !ports.includes(port)) {\n ports.push(port);\n }\n }\n }\n return ports;\n}\n\n// --- Shell helpers ---\n\nexport async function execQuiet(cmd: string, args: string[]): Promise<string> {\n try {\n const { stdout } = await exec(cmd, args);\n return stdout.trim();\n } catch {\n return '';\n }\n}\n\nexport async function checkTmuxAvailable(): Promise<boolean> {\n const result = await execQuiet('which', ['tmux']);\n return result.length > 0;\n}\n\nexport async function sessionAlive(name: string): Promise<boolean> {\n try {\n await exec('tmux', ['has-session', '-t', name]);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function listTmuxPanes(sessionName: string): Promise<RawPane[]> {\n const output = await execQuiet('tmux', [\n 'list-panes', '-s', '-t', sessionName,\n '-F', '#{window_index}|#{window_name}|#{pane_index}|#{pane_current_command}|#{pane_current_path}|#{pane_pid}',\n ]);\n return parseTmuxPaneOutput(output);\n}\n\nexport async function getDescendantPids(rootPid: number, maxDepth: number = 4): Promise<Set<number>> {\n const all = new Set<number>([rootPid]);\n let frontier = [rootPid];\n\n for (let depth = 0; depth < maxDepth && frontier.length > 0; depth++) {\n const nextFrontier: number[] = [];\n for (const pid of frontier) {\n const output = await execQuiet('pgrep', ['-P', String(pid)]);\n for (const line of output.split('\\n')) {\n const child = parseInt(line, 10);\n if (!isNaN(child) && !all.has(child)) {\n all.add(child);\n nextFrontier.push(child);\n }\n }\n }\n frontier = nextFrontier;\n }\n\n return all;\n}\n\nexport async function getLsofOutput(): Promise<string> {\n return execQuiet('lsof', ['-i', '-P', '-n', '-sTCP:LISTEN']);\n}\n\nexport async function getGitInfo(cwd: string): Promise<{ branch: string | null; worktree: boolean }> {\n const branch = await execQuiet('git', ['-C', cwd, 'rev-parse', '--abbrev-ref', 'HEAD']);\n if (!branch) return { branch: null, worktree: false };\n\n const commonDir = await execQuiet('git', ['-C', cwd, 'rev-parse', '--git-common-dir']);\n const gitDir = await execQuiet('git', ['-C', cwd, 'rev-parse', '--git-dir']);\n\n let isWorktree = false;\n if (commonDir && gitDir && commonDir !== gitDir) {\n try {\n const resolvedCommon = await realpath(resolve(cwd, commonDir));\n const resolvedGit = await realpath(resolve(cwd, gitDir));\n isWorktree = resolvedCommon !== resolvedGit;\n } catch {\n isWorktree = false;\n }\n }\n\n return { branch: branch || null, worktree: isWorktree };\n}\n\n// --- Auto-linking ---\n\nexport interface AssignmentLink {\n project: string | null;\n slug: string;\n title: string;\n}\n\nexport interface WorkspaceRecord {\n projectSlug: string | null;\n /** For project-nested, the slug. For standalone, the UUID. */\n assignmentSlug: string;\n assignmentTitle: string;\n worktreePath: string | null;\n branch: string | null;\n}\n\nexport async function loadWorkspaceRecords(\n projectsDir: string,\n assignmentsDir?: string,\n): Promise<WorkspaceRecord[]> {\n const records: WorkspaceRecord[] = [];\n try {\n const projects = await listProjects(projectsDir);\n\n for (const project of projects) {\n const projectAssignmentsDir = resolve(projectsDir, project.slug, 'assignments');\n let slugs: string[];\n try {\n slugs = await readdir(projectAssignmentsDir);\n } catch {\n continue;\n }\n for (const aslug of slugs) {\n const aFile = resolve(projectAssignmentsDir, aslug, 'assignment.md');\n try {\n const raw = await readFile(aFile, 'utf-8');\n const [fm] = extractFrontmatter(raw);\n if (!fm) continue;\n records.push({\n projectSlug: project.slug,\n assignmentSlug: aslug,\n assignmentTitle: getField(fm, 'title') ?? aslug,\n worktreePath: getNestedField(fm, 'workspace', 'worktreePath') ?? null,\n branch: getNestedField(fm, 'workspace', 'branch') ?? null,\n });\n } catch {\n continue;\n }\n }\n }\n } catch {\n // If projects can't be loaded, auto-linking just returns no matches\n }\n\n if (assignmentsDir) {\n try {\n const entries = await readdir(assignmentsDir);\n for (const id of entries) {\n if (id.startsWith('.') || id.startsWith('_')) continue;\n const aFile = resolve(assignmentsDir, id, 'assignment.md');\n try {\n const raw = await readFile(aFile, 'utf-8');\n const [fm] = extractFrontmatter(raw);\n if (!fm) continue;\n records.push({\n projectSlug: null,\n assignmentSlug: id,\n assignmentTitle: getField(fm, 'title') ?? id,\n worktreePath: getNestedField(fm, 'workspace', 'worktreePath') ?? null,\n branch: getNestedField(fm, 'workspace', 'branch') ?? null,\n });\n } catch {\n continue;\n }\n }\n } catch {\n // standalone dir missing is fine\n }\n }\n\n return records;\n}\n\nexport async function resolveAndNormalize(p: string): Promise<string> {\n try {\n const resolved = await realpath(p);\n return resolved.replace(/\\/+$/, '');\n } catch {\n return p.replace(/\\/+$/, '');\n }\n}\n\nexport async function autoLinkPane(\n cwd: string,\n branch: string | null,\n records: WorkspaceRecord[],\n): Promise<AssignmentLink | null> {\n const normalizedCwd = await resolveAndNormalize(cwd);\n for (const rec of records) {\n if (rec.worktreePath) {\n const normalizedWt = await resolveAndNormalize(rec.worktreePath);\n if (normalizedCwd === normalizedWt) {\n return { project: rec.projectSlug, slug: rec.assignmentSlug, title: rec.assignmentTitle };\n }\n }\n }\n if (branch) {\n for (const rec of records) {\n if (rec.branch && rec.branch === branch) {\n return { project: rec.projectSlug, slug: rec.assignmentSlug, title: rec.assignmentTitle };\n }\n }\n }\n return null;\n}\n\n// --- Main scan function ---\n\nasync function scanSession(\n sessionData: SessionFileData,\n lsofOutput: string,\n workspaceRecords: WorkspaceRecord[],\n): Promise<TrackedSession> {\n const now = new Date().toISOString();\n const alive = await sessionAlive(sessionData.session);\n\n if (!alive) {\n return {\n name: sessionData.session,\n kind: 'tmux',\n registered: sessionData.registered,\n lastRefreshed: sessionData.lastRefreshed,\n scannedAt: now,\n alive: false,\n windows: [],\n };\n }\n\n const rawPanes = await listTmuxPanes(sessionData.session);\n\n // Group panes by window\n const windowMap = new Map<number, { name: string; panes: RawPane[] }>();\n for (const rp of rawPanes) {\n if (!windowMap.has(rp.windowIndex)) {\n windowMap.set(rp.windowIndex, { name: rp.windowName, panes: [] });\n }\n windowMap.get(rp.windowIndex)!.panes.push(rp);\n }\n\n // Get git info per unique cwd\n const cwdSet = new Set(rawPanes.map((p) => p.cwd));\n const gitInfoCache = new Map<string, { branch: string | null; worktree: boolean }>();\n for (const cwd of cwdSet) {\n gitInfoCache.set(cwd, await getGitInfo(cwd));\n }\n\n // Get all descendant PIDs for port lookup\n const pidToPaneKey = new Map<number, string>();\n for (const rp of rawPanes) {\n const descendants = await getDescendantPids(rp.pid);\n const key = `${rp.windowIndex}:${rp.paneIndex}`;\n for (const pid of descendants) {\n pidToPaneKey.set(pid, key);\n }\n }\n\n // Find ports per pane\n const panePorts = new Map<string, number[]>();\n for (const line of lsofOutput.split('\\n')) {\n const parts = line.trim().split(/\\s+/);\n if (parts.length < 9) continue;\n const pid = parseInt(parts[1], 10);\n const paneKey = pidToPaneKey.get(pid);\n if (!paneKey) continue;\n const tcpAddr = parts.find((p) => p.includes(':') && /:\\d+$/.test(p));\n if (tcpAddr) {\n const port = parseInt(tcpAddr.split(':').pop()!, 10);\n if (!isNaN(port)) {\n if (!panePorts.has(paneKey)) panePorts.set(paneKey, []);\n const existing = panePorts.get(paneKey)!;\n if (!existing.includes(port)) existing.push(port);\n }\n }\n }\n\n // Build windows — use for-of loop, NOT .map() with async callback\n const windows: TrackedWindow[] = [];\n for (const [windowIndex, { name, panes: rawPanesInWindow }] of windowMap) {\n const panes: TrackedPane[] = [];\n for (const rp of rawPanesInWindow) {\n const key = `${rp.windowIndex}:${rp.paneIndex}`;\n const gitInfo = gitInfoCache.get(rp.cwd) ?? { branch: null, worktree: false };\n const ports = panePorts.get(key) ?? [];\n const urls = ports.map((p) => `http://localhost:${p}`);\n\n const override = sessionData.overrides[key];\n let assignment: AssignmentLink | null = null;\n if (override) {\n const rec = workspaceRecords.find(\n (r) => r.projectSlug === override.project && r.assignmentSlug === override.assignment,\n );\n assignment = {\n project: override.project,\n slug: override.assignment,\n title: rec?.assignmentTitle ?? override.assignment,\n };\n } else {\n assignment = await autoLinkPane(rp.cwd, gitInfo.branch, workspaceRecords);\n }\n\n panes.push({\n index: rp.paneIndex,\n command: rp.command,\n cwd: rp.cwd,\n branch: gitInfo.branch,\n worktree: gitInfo.worktree,\n ports,\n urls,\n assignment,\n });\n }\n\n windows.push({ index: windowIndex, name, panes });\n }\n\n windows.sort((a, b) => a.index - b.index);\n\n return {\n name: sessionData.session,\n kind: 'tmux' as const,\n registered: sessionData.registered,\n lastRefreshed: sessionData.lastRefreshed,\n scannedAt: now,\n alive: true,\n windows,\n };\n}\n\nasync function scanProcessSession(\n sessionData: SessionFileData,\n lsofOutput: string,\n workspaceRecords: WorkspaceRecord[],\n): Promise<TrackedSession> {\n const now = new Date().toISOString();\n\n // Check if the process is still alive\n let alive = false;\n if (sessionData.pid) {\n try {\n process.kill(sessionData.pid, 0);\n alive = true;\n } catch {\n alive = false;\n }\n }\n\n if (!alive || !sessionData.cwd) {\n return {\n name: sessionData.session,\n kind: 'process',\n registered: sessionData.registered,\n lastRefreshed: sessionData.lastRefreshed,\n scannedAt: now,\n alive: false,\n windows: [],\n };\n }\n\n // Re-resolve ports from lsof for the PID\n const ports = findListeningPorts(lsofOutput, new Set([sessionData.pid!]));\n\n const gitInfo = await getGitInfo(sessionData.cwd);\n\n // Honor manual overrides (process sessions use key \"0:0\")\n const override = sessionData.overrides['0:0'];\n let assignment: AssignmentLink | null = null;\n if (override) {\n const rec = workspaceRecords.find(\n (r) => r.projectSlug === override.project && r.assignmentSlug === override.assignment,\n );\n assignment = {\n project: override.project,\n slug: override.assignment,\n title: rec?.assignmentTitle ?? override.assignment,\n };\n } else {\n assignment = await autoLinkPane(sessionData.cwd, gitInfo.branch, workspaceRecords);\n }\n\n const pane: TrackedPane = {\n index: 0,\n command: sessionData.session,\n cwd: sessionData.cwd,\n branch: gitInfo.branch,\n worktree: gitInfo.worktree,\n ports,\n urls: ports.map((p) => `http://localhost:${p}`),\n assignment,\n };\n\n return {\n name: sessionData.session,\n kind: 'process' as const,\n registered: sessionData.registered,\n lastRefreshed: sessionData.lastRefreshed,\n scannedAt: now,\n alive: true,\n windows: [{ index: 0, name: 'process', panes: [pane] }],\n };\n}\n\nexport async function scanAllSessions(\n serversDir: string,\n projectsDir: string,\n options?: { bypassCache?: boolean; assignmentsDir?: string },\n): Promise<ServersResponse> {\n if (!options?.bypassCache && cache && Date.now() < cache.expiry) {\n return cache.data;\n }\n\n const tmuxAvailable = await checkTmuxAvailable();\n const names = await listSessionFiles(serversDir);\n const lsofOutput = await getLsofOutput();\n const workspaceRecords = await loadWorkspaceRecords(projectsDir, options?.assignmentsDir);\n\n const sessions: TrackedSession[] = [];\n for (const name of names) {\n const data = await readSessionFile(serversDir, name);\n if (!data) continue;\n\n if (data.kind === 'process') {\n sessions.push(await scanProcessSession(data, lsofOutput, workspaceRecords));\n } else if (tmuxAvailable) {\n sessions.push(await scanSession(data, lsofOutput, workspaceRecords));\n }\n // Skip tmux-kind entries when tmux is unavailable\n }\n\n const result: ServersResponse = { sessions, tmuxAvailable };\n cache = { data: result, expiry: Date.now() + CACHE_TTL_MS };\n return result;\n}\n\nexport async function scanSingleSession(\n serversDir: string,\n projectsDir: string,\n name: string,\n options?: { assignmentsDir?: string },\n): Promise<TrackedSession | null> {\n const data = await readSessionFile(serversDir, name);\n if (!data) return null;\n\n const lsofOutput = await getLsofOutput();\n const workspaceRecords = await loadWorkspaceRecords(projectsDir, options?.assignmentsDir);\n\n if (data.kind === 'process') {\n return scanProcessSession(data, lsofOutput, workspaceRecords);\n }\n return scanSession(data, lsofOutput, workspaceRecords);\n}\n","import { readdir, readFile, writeFile } from 'node:fs/promises';\nimport { resolve, dirname, basename } from 'node:path';\nimport { getTargetStatus, DEFAULT_STATUSES, DEFAULT_TRANSITION_TABLE, buildTransitionTable } from '../lifecycle/index.js';\nimport { fileExists, writeFileForce } from '../utils/fs.js';\nimport { nowTimestamp } from '../utils/timestamp.js';\nimport { readConfig, type StatusConfig, type StatusTransition } from '../utils/config.js';\nimport { resolvePlaybookSlug } from '../utils/playbooks.js';\nimport { migrateLegacyProjectFiles } from '../utils/fs-migration.js';\nimport { resolveAssignmentById, type ResolvedAssignment } from '../utils/assignment-resolver.js';\n\n/**\n * Thrown by `deleteWorkspace` when references exist and cascade is false.\n * Routers map this to a 409 response carrying the blocker payload.\n */\nexport class WorkspaceBlockedError extends Error {\n readonly blockedBy: { projects: string[]; standalones: string[] };\n constructor(blockedBy: { projects: string[]; standalones: string[] }) {\n super(\n `Workspace is referenced by ${blockedBy.projects.length} project(s) and ${blockedBy.standalones.length} standalone(s).`,\n );\n this.name = 'WorkspaceBlockedError';\n this.blockedBy = blockedBy;\n }\n}\n\n/**\n * Clear a single top-level frontmatter scalar field (regex-replace; assumes\n * the file already starts with `---` and the field exists). Used by the\n * cascade workspace delete to set `workspace:`/`workspaceGroup:` to `null`.\n */\nfunction clearFrontmatterField(content: string, key: string): string {\n const fieldRegex = new RegExp(`^(${escapeRegExp(key)}:)\\\\s*.*$`, 'm');\n return content.replace(fieldRegex, `$1 null`);\n}\n\nfunction setUpdatedField(content: string, value: string): string {\n const fieldRegex = /^(updated:)\\s*.*$/m;\n if (fieldRegex.test(content)) {\n return content.replace(fieldRegex, `$1 \"${value}\"`);\n }\n return content;\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\nimport {\n parseProject,\n parseStatus,\n parseAssignmentFull,\n parsePlan,\n parseScratchpad,\n parseHandoff,\n parseDecisionRecord,\n parseResource,\n parseMemory,\n parsePlaybook,\n parseProgress,\n parseComments,\n extractMermaidGraph,\n} from './parser.js';\nimport { getDashboardHelp } from './help.js';\nimport type {\n AssignmentBoardItem,\n AssignmentDetail,\n AssignmentReference,\n AssignmentSummary,\n AssignmentsBoardResponse,\n AssignmentTransitionAction,\n AttentionItem,\n EditableDocumentResponse,\n EnrichedLink,\n HelpResponse,\n MemoryDetail,\n MemorySummary,\n MemorySummaryWithProject,\n ProjectDetail,\n ProjectSummary,\n OverviewResponse,\n OverviewSegmentId,\n OverviewSegments,\n OverviewHeroRecommendation,\n OverviewHeroKind,\n OverviewSegmentPayload,\n OverviewStaleSegmentPayload,\n ProgressCounts,\n NeedsAttention,\n RecentActivityItem,\n ResourceDetail,\n ResourceSummary,\n ResourceSummaryWithProject,\n PlaybookSummary,\n PlaybookDetail,\n} from './types.js';\nimport { listAllSessions } from './agent-sessions.js';\nimport { SEGMENT_REASON } from './overviewCopy.js';\n\nconst STALE_ASSIGNMENT_MS = 7 * 24 * 60 * 60 * 1000;\nconst RECENT_PROJECTS_LIMIT = 6;\nconst RECENT_ACTIVITY_LIMIT = 12;\nconst RECENT_SESSIONS_LIMIT = 10;\nconst NEWEST_CREATED_LIMIT = 5;\nconst SEGMENT_DISPLAY_CAP = 5;\nconst STALE_LIMIT_DEFAULT = 50;\nconst STALE_LIMIT_MAX = 200;\n\nconst TERMINAL_STATUSES = new Set(['completed', 'failed', 'archived']);\n\nconst STATUS_TO_SEGMENT: Readonly<Record<string, OverviewSegmentId>> = {\n review: 'readyForReview',\n ready_to_implement: 'readyToImplement',\n ready_for_planning: 'readyForPlanning',\n in_progress: 'inProgress',\n draft: 'drafts',\n blocked: 'blocked',\n};\n\nconst HERO_PRIORITY: ReadonlyArray<[OverviewSegmentId, OverviewHeroKind]> = [\n ['readyForReview', 'review'],\n ['readyToImplement', 'ready_to_implement'],\n ['readyForPlanning', 'ready_for_planning'],\n ['inProgress', 'in_progress'],\n ['drafts', 'draft'],\n ['blocked', 'blocked'],\n ['stale', 'stale'],\n];\n\ntype AssignmentRecord = ReturnType<typeof parseAssignmentFull>;\n\ninterface ProjectRecord {\n projectPath: string;\n project: ReturnType<typeof parseProject>;\n assignments: AssignmentRecord[];\n summary: ProjectSummary;\n dependencyGraph: string | null;\n}\n\n/** A standalone assignment lives at `<assignmentsDir>/<uuid>/` and has no containing project. */\ninterface StandaloneRecord {\n assignmentDir: string;\n /** The UUID (folder name). */\n id: string;\n record: AssignmentRecord;\n}\n\nasync function listStandaloneRecords(assignmentsDir: string | undefined): Promise<StandaloneRecord[]> {\n if (!assignmentsDir) return [];\n if (!(await fileExists(assignmentsDir))) return [];\n\n const entries = await readdir(assignmentsDir, { withFileTypes: true });\n const records: StandaloneRecord[] = [];\n\n for (const entry of entries) {\n if (!entry.isDirectory() || entry.name.startsWith('.') || entry.name.startsWith('_')) continue;\n const assignmentDir = resolve(assignmentsDir, entry.name);\n const assignmentMdPath = resolve(assignmentDir, 'assignment.md');\n if (!(await fileExists(assignmentMdPath))) continue;\n try {\n const content = await readFile(assignmentMdPath, 'utf-8');\n const record = parseAssignmentFull(content);\n records.push({ assignmentDir, id: entry.name, record });\n } catch {\n // skip unreadable\n }\n }\n\n records.sort((left, right) => compareTimestamps(right.record.updated, left.record.updated));\n return records;\n}\n\nconst DEFAULT_TRANSITION_DEFINITIONS: Array<{\n command: string;\n label: string;\n description: string;\n requiresReason: boolean;\n}> = [\n {\n command: 'start',\n label: 'Start',\n description: 'Move pending or review work into active execution.',\n requiresReason: false,\n },\n {\n command: 'shape',\n label: 'Shape',\n description: 'Promote a draft assignment to ready_for_planning once the Objective and Acceptance Criteria are fleshed out.',\n requiresReason: false,\n },\n {\n command: 'plan-ready',\n label: 'Plan Ready',\n description: 'Promote a ready_for_planning assignment to ready_to_implement after the plan is written and approved.',\n requiresReason: false,\n },\n {\n command: 'implement',\n label: 'Implement',\n description: 'Move a ready_to_implement assignment into in_progress when coding begins.',\n requiresReason: false,\n },\n {\n command: 'review',\n label: 'Send To Review',\n description: 'Mark the assignment ready for inspection.',\n requiresReason: false,\n },\n {\n command: 'complete',\n label: 'Complete',\n description: 'Mark the assignment done.',\n requiresReason: false,\n },\n {\n command: 'block',\n label: 'Block',\n description: 'Record an exceptional blocker and pause work.',\n requiresReason: true,\n },\n {\n command: 'unblock',\n label: 'Unblock',\n description: 'Resume active work after the blocker is cleared.',\n requiresReason: false,\n },\n {\n command: 'fail',\n label: 'Fail',\n description: 'Mark the assignment as failed when it cannot be completed as planned.',\n requiresReason: false,\n },\n {\n command: 'reopen',\n label: 'Reopen',\n description: 'Reopen a completed or failed assignment to resume work.',\n requiresReason: false,\n },\n];\n\nconst DEFAULT_STATUS_COLORS: Record<string, string> = {\n pending: 'slate',\n in_progress: 'teal',\n blocked: 'amber',\n review: 'violet',\n completed: 'emerald',\n failed: 'rose',\n};\n\nfunction toTitleCase(s: string): string {\n return s.replace(/_/g, ' ').replace(/\\b\\w/g, (c) => c.toUpperCase());\n}\n\nfunction getTransitionDefinitions(config: ResolvedStatusConfig) {\n if (!config.custom) return DEFAULT_TRANSITION_DEFINITIONS;\n // Deduplicate commands from transitions\n const seen = new Set<string>();\n return config.transitions\n .filter((t) => {\n if (seen.has(t.command)) return false;\n seen.add(t.command);\n return true;\n })\n .map((t) => ({\n command: t.command,\n label: t.label ?? toTitleCase(t.command),\n description: t.description ?? `Transition via ${t.command}.`,\n requiresReason: t.requiresReason ?? false,\n }));\n}\n\ninterface ResolvedStatusConfig {\n custom: boolean;\n statuses: Array<{ id: string; label: string; description?: string; color?: string; terminal?: boolean }>;\n order: string[];\n transitions: StatusTransition[];\n transitionTable: Map<string, string>;\n terminalStatuses: ReadonlySet<string>;\n}\n\nlet _cachedConfig: ResolvedStatusConfig | null = null;\n\nexport async function getStatusConfig(): Promise<ResolvedStatusConfig> {\n if (_cachedConfig) return _cachedConfig;\n\n const config = await readConfig();\n\n if (config.statuses) {\n const terminalSet = new Set(\n config.statuses.statuses.filter((s) => s.terminal).map((s) => s.id),\n );\n _cachedConfig = {\n custom: true,\n statuses: config.statuses.statuses,\n order: config.statuses.order,\n transitions: config.statuses.transitions,\n transitionTable: buildTransitionTable(config.statuses.transitions),\n terminalStatuses: terminalSet.size > 0 ? terminalSet : new Set(['completed', 'failed']),\n };\n } else {\n _cachedConfig = {\n custom: false,\n statuses: DEFAULT_STATUSES.map((id) => ({\n id,\n label: toTitleCase(id),\n color: DEFAULT_STATUS_COLORS[id] ?? 'gray',\n terminal: id === 'completed' || id === 'failed',\n })),\n order: [...DEFAULT_STATUSES],\n transitions: Array.from(DEFAULT_TRANSITION_TABLE.entries()).map(([key, to]) => {\n const [from, command] = key.split(':');\n return { from, command, to };\n }),\n transitionTable: DEFAULT_TRANSITION_TABLE,\n terminalStatuses: new Set(['completed', 'failed']),\n };\n }\n\n return _cachedConfig;\n}\n\nexport function clearStatusConfigCache(): void {\n _cachedConfig = null;\n}\n\n/**\n * List all projects with source-first summary data.\n * GET /api/projects\n */\nexport async function listProjects(projectsDir: string): Promise<ProjectSummary[]> {\n const projectRecords = await listProjectRecords(projectsDir);\n return projectRecords.map((record) => record.summary);\n}\n\n/**\n * Read the workspace registry file (~/.syntaur/workspaces.json).\n * Returns an array of explicitly registered workspace names.\n */\nasync function readWorkspaceRegistry(projectsDir: string): Promise<string[]> {\n const registryPath = resolve(dirname(projectsDir), 'workspaces.json');\n try {\n const raw = await readFile(registryPath, 'utf-8');\n const parsed = JSON.parse(raw);\n return Array.isArray(parsed) ? parsed.filter((w): w is string => typeof w === 'string') : [];\n } catch {\n return [];\n }\n}\n\nasync function writeWorkspaceRegistry(projectsDir: string, workspaces: string[]): Promise<void> {\n const registryPath = resolve(dirname(projectsDir), 'workspaces.json');\n await writeFile(registryPath, JSON.stringify(workspaces, null, 2) + '\\n', 'utf-8');\n}\n\n/**\n * List all workspaces: merge registry (explicit) with workspaces discovered from\n * project `workspace:` fields and standalone-assignment `workspaceGroup` fields.\n * Standalones with no `workspaceGroup` contribute to `hasUngrouped`.\n * GET /api/workspaces\n */\nexport async function listWorkspaces(\n projectsDir: string,\n assignmentsDir?: string,\n): Promise<{ workspaces: string[]; hasUngrouped: boolean }> {\n const [projectRecords, registered, standaloneRecords] = await Promise.all([\n listProjectRecords(projectsDir),\n readWorkspaceRegistry(projectsDir),\n listStandaloneRecords(assignmentsDir),\n ]);\n const workspaceSet = new Set<string>(registered);\n let hasUngrouped = false;\n for (const record of projectRecords) {\n if (record.project.workspace) {\n workspaceSet.add(record.project.workspace);\n } else {\n hasUngrouped = true;\n }\n }\n for (const sr of standaloneRecords) {\n if (sr.record.workspaceGroup) {\n workspaceSet.add(sr.record.workspaceGroup);\n } else {\n hasUngrouped = true;\n }\n }\n const workspaces = Array.from(workspaceSet).sort();\n return { workspaces, hasUngrouped };\n}\n\n/**\n * Create an empty workspace by registering it.\n * POST /api/workspaces\n */\nexport async function createWorkspace(projectsDir: string, name: string): Promise<void> {\n const registered = await readWorkspaceRegistry(projectsDir);\n if (!registered.includes(name)) {\n registered.push(name);\n registered.sort();\n await writeWorkspaceRegistry(projectsDir, registered);\n }\n}\n\n/**\n * Delete a workspace from the registry.\n *\n * Modes:\n * - `cascade: false` (default): if any project or standalone still references\n * this workspace, throw `WorkspaceBlockedError` with the blocker lists.\n * Otherwise remove from the registry.\n * - `cascade: true`: rewrite every referencing project's `workspace:` field\n * and every referencing standalone's `workspaceGroup:` field to `null`,\n * then remove the registry entry.\n *\n * Returns `{ rewroteFiles }` so callers (server.ts) can decide whether the\n * explicit registry-level broadcast is still needed (watchers already emit\n * project-updated/assignment-updated for rewritten files).\n *\n * DELETE /api/workspaces/:name[?cascade=true]\n */\nexport async function deleteWorkspace(\n projectsDir: string,\n name: string,\n opts: { cascade?: boolean; assignmentsDir?: string } = {},\n): Promise<{ rewroteFiles: boolean }> {\n const cascade = Boolean(opts.cascade);\n const projectRecords = await listProjectRecords(projectsDir);\n const standaloneRecords = await listStandaloneRecords(opts.assignmentsDir);\n\n const projectsReferencing = projectRecords\n .filter((record) => record.project.workspace === name)\n .map((record) => record.project.slug);\n const standalonesReferencing = standaloneRecords\n .filter((record) => record.record.workspaceGroup === name)\n .map((record) => record.id);\n\n if (projectsReferencing.length + standalonesReferencing.length > 0 && !cascade) {\n throw new WorkspaceBlockedError({\n projects: projectsReferencing,\n standalones: standalonesReferencing,\n });\n }\n\n let rewroteFiles = false;\n if (cascade) {\n const timestamp = nowTimestamp();\n\n for (const slug of projectsReferencing) {\n const path = resolve(projectsDir, slug, 'project.md');\n const raw = await readFile(path, 'utf-8');\n let next = clearFrontmatterField(raw, 'workspace');\n next = setUpdatedField(next, timestamp);\n await writeFileForce(path, next);\n rewroteFiles = true;\n }\n\n for (const id of standalonesReferencing) {\n if (!opts.assignmentsDir) break;\n const path = resolve(opts.assignmentsDir, id, 'assignment.md');\n const raw = await readFile(path, 'utf-8');\n let next = clearFrontmatterField(raw, 'workspaceGroup');\n next = setUpdatedField(next, timestamp);\n await writeFileForce(path, next);\n rewroteFiles = true;\n }\n }\n\n const registered = await readWorkspaceRegistry(projectsDir);\n const filtered = registered.filter((w) => w !== name);\n await writeWorkspaceRegistry(projectsDir, filtered);\n\n return { rewroteFiles };\n}\n\n/**\n * Get overview data used by the app landing page.\n * GET /api/overview?staleLimit=&staleOffset=\n */\nexport async function getOverview(\n projectsDir: string,\n serversDir?: string,\n assignmentsDir?: string,\n options: { staleLimit?: number; staleOffset?: number } = {},\n): Promise<OverviewResponse> {\n const projectRecords = await listProjectRecords(projectsDir);\n const standaloneRecords = await listStandaloneRecords(assignmentsDir);\n const recentActivity = buildRecentActivity(projectRecords, standaloneRecords);\n\n const staleLimit = clamp(\n Number.isFinite(options.staleLimit) ? Number(options.staleLimit) : STALE_LIMIT_DEFAULT,\n 1,\n STALE_LIMIT_MAX,\n );\n const staleOffset = Math.max(0, Number.isFinite(options.staleOffset) ? Number(options.staleOffset) : 0);\n\n const buckets = await buildOverviewSegmentBuckets(projectsDir, projectRecords, standaloneRecords);\n const segments = toOverviewSegments(buckets, { staleLimit, staleOffset });\n const hero = pickOverviewHero(buckets);\n\n let recentSessions: OverviewResponse['recentSessions'] = [];\n try {\n const all = await listAllSessions(projectsDir);\n recentSessions = all.slice(0, RECENT_SESSIONS_LIMIT);\n } catch {\n // Sessions failure should not break overview.\n }\n\n let serverStats: OverviewResponse['serverStats'];\n if (serversDir) {\n try {\n const { scanAllSessions } = await import('./scanner.js');\n const servers = await scanAllSessions(serversDir, projectsDir, { assignmentsDir });\n if (servers.tmuxAvailable) {\n const alive = servers.sessions.filter(s => s.alive).length;\n const totalPorts = servers.sessions.reduce((sum, s) =>\n sum + s.windows.reduce((ws, w) =>\n ws + w.panes.reduce((ps, p) => ps + p.ports.length, 0), 0), 0);\n serverStats = {\n trackedSessions: servers.sessions.length,\n aliveSessions: alive,\n deadSessions: servers.sessions.length - alive,\n totalPorts,\n };\n }\n } catch {\n // Server scanning failure should not break overview\n }\n }\n\n return {\n generatedAt: new Date().toISOString(),\n firstRun: projectRecords.length === 0 && standaloneRecords.length === 0,\n stats: {\n activeProjects: projectRecords.filter((record) => record.summary.status === 'active').length,\n inProgressAssignments: projectRecords.reduce(\n (total, record) => total + (record.summary.progress['in_progress'] ?? 0),\n 0,\n ),\n blockedAssignments: projectRecords.reduce(\n (total, record) => total + (record.summary.progress['blocked'] ?? 0),\n 0,\n ),\n reviewAssignments: projectRecords.reduce(\n (total, record) => total + (record.summary.progress['review'] ?? 0),\n 0,\n ),\n failedAssignments: projectRecords.reduce(\n (total, record) => total + (record.summary.progress['failed'] ?? 0),\n 0,\n ),\n staleAssignments: projectRecords.reduce(\n (total, record) =>\n total + record.assignments.filter((assignment) => isStale(assignment.updated)).length,\n 0,\n ) + standaloneRecords.filter((sr) => isStale(sr.record.updated)).length,\n },\n hero,\n segments,\n recentSessions,\n recentProjects: projectRecords\n .map((record) => record.summary)\n .sort((left, right) => compareTimestamps(right.updated, left.updated))\n .slice(0, RECENT_PROJECTS_LIMIT),\n recentActivity: recentActivity.slice(0, RECENT_ACTIVITY_LIMIT),\n serverStats,\n };\n}\n\n/**\n * Get all assignments across all projects for the global kanban board.\n * GET /api/assignments\n */\nexport async function listAssignmentsBoard(\n projectsDir: string,\n assignmentsDir?: string,\n): Promise<AssignmentsBoardResponse> {\n const projectRecords = await listProjectRecords(projectsDir);\n const projectItems = await Promise.all(\n projectRecords.flatMap(async (record) =>\n Promise.all(\n record.assignments.map(async (assignment) =>\n toAssignmentBoardItem(projectsDir, record, assignment),\n ),\n ),\n ),\n );\n\n const standaloneRecords = await listStandaloneRecords(assignmentsDir);\n const standaloneItems = await Promise.all(\n standaloneRecords.map(async (sr) => toStandaloneBoardItem(sr)),\n );\n\n return {\n generatedAt: new Date().toISOString(),\n assignments: [...projectItems.flat(), ...standaloneItems]\n .sort((left, right) => compareTimestamps(right.updated, left.updated)),\n };\n}\n\nasync function toStandaloneBoardItem(sr: StandaloneRecord): Promise<AssignmentBoardItem> {\n return {\n ...toAssignmentSummary(sr.record),\n projectSlug: null,\n projectTitle: null,\n blockedReason: sr.record.blockedReason,\n projectWorkspace: sr.record.workspaceGroup ?? null,\n availableTransitions: await getStandaloneAvailableTransitions(sr.record),\n };\n}\n\nasync function getStandaloneAvailableTransitions(\n assignment: AssignmentRecord,\n): Promise<AssignmentTransitionAction[]> {\n // Standalone assignments have no dependencies, so skip dependency gating.\n const config = await getStatusConfig();\n const transitionDefs = getTransitionDefinitions(config);\n const actions: AssignmentTransitionAction[] = [];\n\n for (const definition of transitionDefs) {\n let warning: string | null = null;\n if (definition.command === 'start' && !assignment.assignee) {\n warning = 'No assignee set — consider assigning before starting.';\n }\n const target = getTargetStatus(assignment.status, definition.command, config.transitionTable);\n actions.push({\n command: definition.command,\n label: definition.label,\n description: definition.description,\n targetStatus: target ?? definition.command,\n disabled: false,\n disabledReason: null,\n warning,\n requiresReason: definition.requiresReason,\n });\n }\n\n return actions;\n}\n\n/**\n * Get the structured help model used by Help and onboarding surfaces.\n * GET /api/help\n */\nexport async function getHelp(): Promise<HelpResponse> {\n return getDashboardHelp();\n}\n\n/**\n * Get a raw editable document for dashboard editor pages.\n */\nexport async function getEditableDocument(\n projectsDir: string,\n documentType: EditableDocumentResponse['documentType'],\n projectSlug: string,\n assignmentSlug?: string,\n): Promise<EditableDocumentResponse | null> {\n const filePath = getDocumentPath(projectsDir, documentType, projectSlug, assignmentSlug);\n if (!filePath || !(await fileExists(filePath))) {\n return null;\n }\n\n const content = await readFile(filePath, 'utf-8');\n const title = getEditableDocumentTitle(documentType, projectSlug, assignmentSlug);\n\n return {\n documentType,\n title,\n content,\n projectSlug,\n assignmentSlug,\n appendOnly: documentType === 'handoff' || documentType === 'decision-record',\n };\n}\n\n/**\n * Resolve an assignment by UUID (standalone or project-nested) and return its\n * editable document payload for the given type.\n */\nexport async function getEditableDocumentById(\n projectsDir: string,\n assignmentsDir: string,\n documentType: EditableDocumentResponse['documentType'],\n id: string,\n): Promise<EditableDocumentResponse | null> {\n const resolved = await resolveAssignmentById(projectsDir, assignmentsDir, id);\n if (!resolved) return null;\n\n if (!resolved.standalone && resolved.projectSlug) {\n return getEditableDocument(\n projectsDir,\n documentType,\n resolved.projectSlug,\n resolved.assignmentSlug,\n );\n }\n\n const fileName =\n documentType === 'assignment'\n ? 'assignment.md'\n : documentType === 'plan'\n ? 'plan.md'\n : documentType === 'scratchpad'\n ? 'scratchpad.md'\n : documentType === 'handoff'\n ? 'handoff.md'\n : documentType === 'decision-record'\n ? 'decision-record.md'\n : null;\n if (!fileName) return null;\n const filePath = resolve(resolved.assignmentDir, fileName);\n if (!(await fileExists(filePath))) return null;\n\n const content = await readFile(filePath, 'utf-8');\n const label = resolved.id;\n const title =\n documentType === 'assignment'\n ? `Edit Assignment: ${label}`\n : documentType === 'plan'\n ? `Edit Plan: ${label}`\n : documentType === 'scratchpad'\n ? `Edit Scratchpad: ${label}`\n : documentType === 'handoff'\n ? `Append Handoff: ${label}`\n : `Append Decision: ${label}`;\n\n return {\n documentType,\n title,\n content,\n projectSlug: null,\n assignmentSlug: undefined,\n assignmentId: resolved.id,\n appendOnly: documentType === 'handoff' || documentType === 'decision-record',\n };\n}\n\n/**\n * Get full project detail with assignments, resources, and memories.\n * GET /api/projects/:slug\n */\nexport async function getProjectDetail(\n projectsDir: string,\n slug: string,\n): Promise<ProjectDetail | null> {\n const projectPath = resolve(projectsDir, slug);\n const projectMdPath = resolve(projectPath, 'project.md');\n\n if (!(await fileExists(projectMdPath))) {\n return null;\n }\n\n const projectContent = await readFile(projectMdPath, 'utf-8');\n const project = parseProject(projectContent);\n const assignments = await listAssignmentRecords(projectPath);\n const rollup = await buildProjectRollup(projectPath, project, assignments);\n const dependencyGraph = await loadDependencyGraph(projectPath, assignments);\n const resources = await listResources(projectPath);\n const memories = await listMemories(projectPath);\n const updated = getProjectActivityTimestamp(project.updated, assignments);\n\n return {\n slug: project.slug || slug,\n title: project.title,\n status: rollup.status,\n statusOverride: project.statusOverride,\n archived: project.archived,\n archivedAt: project.archivedAt,\n archivedReason: project.archivedReason,\n created: project.created,\n updated,\n tags: project.tags,\n externalIds: project.externalIds,\n body: project.body,\n progress: rollup.progress,\n needsAttention: rollup.needsAttention,\n assignments: assignments\n .map(toAssignmentSummary)\n .sort((left, right) => compareTimestamps(right.updated, left.updated)),\n resources,\n memories,\n dependencyGraph,\n workspace: project.workspace,\n repositories: project.repositories,\n };\n}\n\n/**\n * Get full assignment detail with plan, scratchpad, handoff, and decision record.\n * GET /api/projects/:slug/assignments/:aslug\n */\nexport async function getAssignmentDetail(\n projectsDir: string,\n projectSlug: string,\n assignmentSlug: string,\n): Promise<AssignmentDetail | null> {\n const assignmentDir = resolve(projectsDir, projectSlug, 'assignments', assignmentSlug);\n const assignmentMdPath = resolve(assignmentDir, 'assignment.md');\n\n if (!(await fileExists(assignmentMdPath))) {\n return null;\n }\n\n const assignmentContent = await readFile(assignmentMdPath, 'utf-8');\n const assignment = parseAssignmentFull(assignmentContent);\n\n let projectWorkspace: string | null = null;\n const projectMdPath = resolve(projectsDir, projectSlug, 'project.md');\n if (await fileExists(projectMdPath)) {\n const projectContent = await readFile(projectMdPath, 'utf-8');\n projectWorkspace = parseProject(projectContent).workspace;\n }\n\n let plan: AssignmentDetail['plan'] = null;\n const planPath = resolve(assignmentDir, 'plan.md');\n if (await fileExists(planPath)) {\n const planContent = await readFile(planPath, 'utf-8');\n const parsed = parsePlan(planContent);\n plan = {\n status: parsed.status,\n updated: parsed.updated,\n body: parsed.body,\n };\n }\n\n let scratchpad: AssignmentDetail['scratchpad'] = null;\n const scratchpadPath = resolve(assignmentDir, 'scratchpad.md');\n if (await fileExists(scratchpadPath)) {\n const scratchpadContent = await readFile(scratchpadPath, 'utf-8');\n const parsed = parseScratchpad(scratchpadContent);\n scratchpad = {\n updated: parsed.updated,\n body: parsed.body,\n };\n }\n\n let handoff: AssignmentDetail['handoff'] = null;\n const handoffPath = resolve(assignmentDir, 'handoff.md');\n if (await fileExists(handoffPath)) {\n const handoffContent = await readFile(handoffPath, 'utf-8');\n const parsed = parseHandoff(handoffContent);\n handoff = {\n updated: parsed.updated,\n handoffCount: parsed.handoffCount,\n body: parsed.body,\n };\n }\n\n let decisionRecord: AssignmentDetail['decisionRecord'] = null;\n const decisionRecordPath = resolve(assignmentDir, 'decision-record.md');\n if (await fileExists(decisionRecordPath)) {\n const decisionRecordContent = await readFile(decisionRecordPath, 'utf-8');\n const parsed = parseDecisionRecord(decisionRecordContent);\n decisionRecord = {\n updated: parsed.updated,\n decisionCount: parsed.decisionCount,\n body: parsed.body,\n };\n }\n\n let progress: AssignmentDetail['progress'] = null;\n const progressPath = resolve(assignmentDir, 'progress.md');\n if (await fileExists(progressPath)) {\n const progressContent = await readFile(progressPath, 'utf-8');\n const parsed = parseProgress(progressContent);\n progress = {\n updated: parsed.updated,\n entryCount: parsed.entryCount,\n entries: parsed.entries,\n };\n }\n\n let comments: AssignmentDetail['comments'] = null;\n const commentsPath = resolve(assignmentDir, 'comments.md');\n if (await fileExists(commentsPath)) {\n const commentsContent = await readFile(commentsPath, 'utf-8');\n const parsed = parseComments(commentsContent);\n comments = {\n updated: parsed.updated,\n entryCount: parsed.entryCount,\n entries: parsed.entries,\n };\n }\n\n const detail: AssignmentDetail = {\n id: assignment.id,\n projectSlug,\n slug: assignment.slug || assignmentSlug,\n title: assignment.title,\n status: assignment.status,\n priority: assignment.priority as AssignmentDetail['priority'],\n assignee: assignment.assignee,\n dependsOn: assignment.dependsOn,\n links: assignment.links,\n reverseLinks: [],\n enrichedLinks: [],\n blockedReason: assignment.blockedReason,\n workspace: assignment.workspace,\n projectWorkspace,\n externalIds: assignment.externalIds,\n tags: assignment.tags,\n created: assignment.created,\n updated: assignment.updated,\n body: assignment.body,\n plan,\n scratchpad,\n handoff,\n decisionRecord,\n progress,\n comments,\n referencedBy: [],\n availableTransitions: await getAvailableTransitions(\n projectsDir,\n projectSlug,\n assignmentSlug,\n assignment,\n ),\n };\n\n // Compute reverse links and enrich all links\n const selfSlug = `${projectSlug}/${detail.slug}`;\n const projectRecords = await listProjectRecords(projectsDir);\n\n // Find reverse links: assignments across all projects whose links contain this assignment\n const reverseLinks: string[] = [];\n for (const mr of projectRecords) {\n for (const a of mr.assignments) {\n const qualifiedSlug = `${mr.summary.slug}/${a.slug}`;\n if (qualifiedSlug === selfSlug) continue; // skip self\n if (a.links.includes(selfSlug)) {\n reverseLinks.push(qualifiedSlug);\n }\n }\n }\n\n // Filter self-links and malformed links from forward links\n const isValidLinkFormat = (l: string) => {\n const parts = l.split('/');\n return parts.length === 2 && parts[0].length > 0 && parts[1].length > 0;\n };\n const forwardLinks = assignment.links.filter((l) => l !== selfSlug && isValidLinkFormat(l));\n\n // Deduplicate: if a slug is in both forward and reverse, keep in forward only\n const forwardSet = new Set(forwardLinks);\n const dedupedReverseLinks = reverseLinks.filter((l) => !forwardSet.has(l));\n\n detail.links = forwardLinks;\n detail.reverseLinks = dedupedReverseLinks;\n\n // Build enriched links for the frontend\n const allProjectAssignments = new Map<string, { title: string; status: string }>();\n for (const mr of projectRecords) {\n for (const a of mr.assignments) {\n allProjectAssignments.set(`${mr.summary.slug}/${a.slug}`, {\n title: a.title,\n status: a.status,\n });\n }\n }\n\n const enrichedLinks: EnrichedLink[] = [];\n for (const linkSlug of forwardLinks) {\n const [ms, as] = linkSlug.split('/');\n const info = allProjectAssignments.get(linkSlug);\n enrichedLinks.push({\n slug: linkSlug,\n projectSlug: ms,\n assignmentSlug: as,\n title: info?.title ?? linkSlug,\n status: info?.status ?? 'pending',\n isReverse: false,\n });\n }\n for (const linkSlug of dedupedReverseLinks) {\n const [ms, as] = linkSlug.split('/');\n const info = allProjectAssignments.get(linkSlug);\n enrichedLinks.push({\n slug: linkSlug,\n projectSlug: ms,\n assignmentSlug: as,\n title: info?.title ?? linkSlug,\n status: info?.status ?? 'pending',\n isReverse: true,\n });\n }\n\n detail.enrichedLinks = enrichedLinks;\n\n // Populate referencedBy — assignments that mention this one.\n detail.referencedBy = await computeReferencedBy(\n { id: assignment.id, projectSlug, slug: detail.slug },\n projectsDir,\n undefined,\n );\n\n return detail;\n}\n\nconst REFERENCED_BY_LIMIT = 50;\n\ninterface ReferenceTarget {\n id: string;\n projectSlug: string | null;\n slug: string;\n}\n\n/**\n * Scan every *other* assignment's Todos, progress, comments, and handoff bodies\n * for markdown links that resolve to `target`, and return an aggregated per-source\n * count (capped at 50).\n */\nasync function computeReferencedBy(\n target: ReferenceTarget,\n projectsDir: string,\n assignmentsDir: string | undefined,\n): Promise<AssignmentReference[]> {\n const sources: Array<{\n id: string;\n slug: string;\n title: string;\n projectSlug: string | null;\n assignmentDir: string;\n }> = [];\n\n // project-nested\n const projectRecords = await listProjectRecords(projectsDir);\n for (const rec of projectRecords) {\n for (const a of rec.assignments) {\n sources.push({\n id: a.id,\n slug: a.slug,\n title: a.title,\n projectSlug: rec.summary.slug,\n assignmentDir: resolve(rec.projectPath, 'assignments', a.slug),\n });\n }\n }\n // standalone\n const standaloneRecords = await listStandaloneRecords(assignmentsDir);\n for (const sr of standaloneRecords) {\n sources.push({\n id: sr.id,\n slug: sr.record.slug || sr.id,\n title: sr.record.title,\n projectSlug: null,\n assignmentDir: sr.assignmentDir,\n });\n }\n\n const references: AssignmentReference[] = [];\n for (const source of sources) {\n if (source.id === target.id) continue; // skip self\n const mentions = await countMentionsInAssignment(source.assignmentDir, target);\n if (mentions > 0) {\n references.push({\n sourceId: source.id,\n sourceSlug: source.slug,\n sourceTitle: source.title,\n sourceProjectSlug: source.projectSlug,\n mentions,\n });\n }\n if (references.length >= REFERENCED_BY_LIMIT) break;\n }\n\n return references.slice(0, REFERENCED_BY_LIMIT);\n}\n\nasync function countMentionsInAssignment(\n sourceDir: string,\n target: ReferenceTarget,\n): Promise<number> {\n const bodies: string[] = [];\n\n // Todos section (from assignment.md)\n const assignmentMd = resolve(sourceDir, 'assignment.md');\n if (await fileExists(assignmentMd)) {\n const content = await readFile(assignmentMd, 'utf-8');\n const todosMatch = content.match(/^## Todos\\s*$([\\s\\S]*?)(?=^## |$(?![\\r\\n]))/m);\n if (todosMatch) bodies.push(todosMatch[1]);\n }\n\n for (const filename of ['progress.md', 'comments.md', 'handoff.md']) {\n const path = resolve(sourceDir, filename);\n if (await fileExists(path)) {\n try {\n bodies.push(await readFile(path, 'utf-8'));\n } catch {\n // ignore\n }\n }\n }\n\n let total = 0;\n const patterns = buildLinkPatternsForTarget(target);\n for (const body of bodies) {\n for (const pattern of patterns) {\n const matches = body.match(pattern);\n if (matches) total += matches.length;\n }\n }\n return total;\n}\n\nfunction buildLinkPatternsForTarget(target: ReferenceTarget): RegExp[] {\n const patterns: RegExp[] = [];\n // Standalone absolute route\n patterns.push(new RegExp(`/assignments/${escapeRegExpLocal(target.id)}(?:/|\\\\b)`, 'g'));\n if (target.projectSlug) {\n // Project-nested absolute route\n patterns.push(\n new RegExp(\n `/projects/${escapeRegExpLocal(target.projectSlug)}/assignments/${escapeRegExpLocal(target.slug)}(?:/|\\\\b)`,\n 'g',\n ),\n );\n // Project-nested relative route\n patterns.push(\n new RegExp(`\\\\.\\\\./${escapeRegExpLocal(target.slug)}(?:/|\\\\b)`, 'g'),\n );\n }\n return patterns;\n}\n\nfunction escapeRegExpLocal(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/**\n * Resolve an assignment by UUID (standalone or project-nested) and return its full detail payload.\n * GET /api/assignments/:id\n */\nexport async function getAssignmentDetailById(\n projectsDir: string,\n assignmentsDir: string,\n id: string,\n): Promise<AssignmentDetail | null> {\n const resolved = await resolveAssignmentById(projectsDir, assignmentsDir, id);\n if (!resolved) return null;\n\n if (!resolved.standalone && resolved.projectSlug) {\n // Use the standard detail fetcher, then also scan standalone assignments\n // for backlinks.\n const detail = await getAssignmentDetail(projectsDir, resolved.projectSlug, resolved.assignmentSlug);\n if (!detail) return null;\n detail.referencedBy = await computeReferencedBy(\n { id: detail.id, projectSlug: detail.projectSlug, slug: detail.slug },\n projectsDir,\n assignmentsDir,\n );\n return detail;\n }\n\n // Standalone path — load companion docs directly from the resolved dir.\n const standaloneDetail = await buildStandaloneAssignmentDetail(resolved);\n if (!standaloneDetail) return null;\n standaloneDetail.referencedBy = await computeReferencedBy(\n { id: standaloneDetail.id, projectSlug: null, slug: standaloneDetail.slug },\n projectsDir,\n assignmentsDir,\n );\n return standaloneDetail;\n}\n\nasync function buildStandaloneAssignmentDetail(\n resolved: ResolvedAssignment,\n): Promise<AssignmentDetail | null> {\n const assignmentDir = resolved.assignmentDir;\n const assignmentMdPath = resolve(assignmentDir, 'assignment.md');\n if (!(await fileExists(assignmentMdPath))) return null;\n\n const assignmentContent = await readFile(assignmentMdPath, 'utf-8');\n const assignment = parseAssignmentFull(assignmentContent);\n\n let plan: AssignmentDetail['plan'] = null;\n const planPath = resolve(assignmentDir, 'plan.md');\n if (await fileExists(planPath)) {\n const parsed = parsePlan(await readFile(planPath, 'utf-8'));\n plan = { status: parsed.status, updated: parsed.updated, body: parsed.body };\n }\n\n let scratchpad: AssignmentDetail['scratchpad'] = null;\n const scratchpadPath = resolve(assignmentDir, 'scratchpad.md');\n if (await fileExists(scratchpadPath)) {\n const parsed = parseScratchpad(await readFile(scratchpadPath, 'utf-8'));\n scratchpad = { updated: parsed.updated, body: parsed.body };\n }\n\n let handoff: AssignmentDetail['handoff'] = null;\n const handoffPath = resolve(assignmentDir, 'handoff.md');\n if (await fileExists(handoffPath)) {\n const parsed = parseHandoff(await readFile(handoffPath, 'utf-8'));\n handoff = { updated: parsed.updated, handoffCount: parsed.handoffCount, body: parsed.body };\n }\n\n let decisionRecord: AssignmentDetail['decisionRecord'] = null;\n const decisionRecordPath = resolve(assignmentDir, 'decision-record.md');\n if (await fileExists(decisionRecordPath)) {\n const parsed = parseDecisionRecord(await readFile(decisionRecordPath, 'utf-8'));\n decisionRecord = { updated: parsed.updated, decisionCount: parsed.decisionCount, body: parsed.body };\n }\n\n let progress: AssignmentDetail['progress'] = null;\n const progressPath = resolve(assignmentDir, 'progress.md');\n if (await fileExists(progressPath)) {\n const parsed = parseProgress(await readFile(progressPath, 'utf-8'));\n progress = { updated: parsed.updated, entryCount: parsed.entryCount, entries: parsed.entries };\n }\n\n let comments: AssignmentDetail['comments'] = null;\n const commentsPath = resolve(assignmentDir, 'comments.md');\n if (await fileExists(commentsPath)) {\n const parsed = parseComments(await readFile(commentsPath, 'utf-8'));\n comments = { updated: parsed.updated, entryCount: parsed.entryCount, entries: parsed.entries };\n }\n\n const detail: AssignmentDetail = {\n id: assignment.id,\n projectSlug: null,\n slug: assignment.slug || resolved.id,\n title: assignment.title,\n status: assignment.status,\n priority: assignment.priority as AssignmentDetail['priority'],\n assignee: assignment.assignee,\n dependsOn: [], // standalone cannot declare dependencies\n links: [],\n reverseLinks: [],\n enrichedLinks: [],\n blockedReason: assignment.blockedReason,\n workspace: assignment.workspace,\n projectWorkspace: assignment.workspaceGroup,\n externalIds: assignment.externalIds,\n tags: assignment.tags,\n created: assignment.created,\n updated: assignment.updated,\n body: assignment.body,\n plan,\n scratchpad,\n handoff,\n decisionRecord,\n progress,\n comments,\n referencedBy: [],\n availableTransitions: await getStandaloneAvailableTransitions(assignment),\n };\n\n return detail;\n}\n\n// Guard so legacy-file renames run at most once per `projectsDir` per process\n// lifetime. Keyed by absolute path to tolerate test suites that open multiple\n// sandboxes in the same process.\nconst migratedProjectsDirs = new Set<string>();\n\nasync function listProjectRecords(projectsDir: string): Promise<ProjectRecord[]> {\n if (!(await fileExists(projectsDir))) {\n return [];\n }\n\n if (!migratedProjectsDirs.has(projectsDir)) {\n migratedProjectsDirs.add(projectsDir);\n await migrateLegacyProjectFiles(projectsDir);\n }\n\n const entries = await readdir(projectsDir, { withFileTypes: true });\n const projectDirs = entries.filter((entry) => entry.isDirectory() && !entry.name.startsWith('.'));\n const records: ProjectRecord[] = [];\n\n for (const entry of projectDirs) {\n const projectPath = resolve(projectsDir, entry.name);\n const projectMdPath = resolve(projectPath, 'project.md');\n\n if (!(await fileExists(projectMdPath))) {\n continue;\n }\n\n const projectContent = await readFile(projectMdPath, 'utf-8');\n const project = parseProject(projectContent);\n const assignments = await listAssignmentRecords(projectPath);\n const rollup = await buildProjectRollup(projectPath, project, assignments);\n const updated = getProjectActivityTimestamp(project.updated, assignments);\n\n records.push({\n projectPath,\n project,\n assignments,\n dependencyGraph: await loadDependencyGraph(projectPath, assignments),\n summary: {\n slug: project.slug || entry.name,\n title: project.title,\n status: rollup.status,\n statusOverride: project.statusOverride,\n archived: project.archived,\n archivedAt: project.archivedAt,\n archivedReason: project.archivedReason,\n created: project.created,\n updated,\n tags: project.tags,\n progress: rollup.progress,\n needsAttention: rollup.needsAttention,\n workspace: project.workspace,\n },\n });\n }\n\n records.sort((left, right) => compareTimestamps(right.summary.updated, left.summary.updated));\n return records;\n}\n\nasync function listAssignmentRecords(projectPath: string): Promise<AssignmentRecord[]> {\n const assignmentsDir = resolve(projectPath, 'assignments');\n if (!(await fileExists(assignmentsDir))) {\n return [];\n }\n\n const entries = await readdir(assignmentsDir, { withFileTypes: true });\n const records: AssignmentRecord[] = [];\n\n for (const entry of entries) {\n if (!entry.isDirectory()) {\n continue;\n }\n\n const assignmentMd = resolve(assignmentsDir, entry.name, 'assignment.md');\n if (!(await fileExists(assignmentMd))) {\n continue;\n }\n\n const content = await readFile(assignmentMd, 'utf-8');\n records.push(parseAssignmentFull(content));\n }\n\n records.sort((left, right) => compareTimestamps(right.updated, left.updated));\n return records;\n}\n\nasync function listResources(projectPath: string): Promise<ResourceSummary[]> {\n const resourcesDir = resolve(projectPath, 'resources');\n if (!(await fileExists(resourcesDir))) {\n return [];\n }\n\n const entries = await readdir(resourcesDir, { withFileTypes: true });\n const results: ResourceSummary[] = [];\n\n for (const entry of entries) {\n if (!entry.isFile() || !entry.name.endsWith('.md') || entry.name.startsWith('_')) {\n continue;\n }\n\n const filePath = resolve(resourcesDir, entry.name);\n const content = await readFile(filePath, 'utf-8');\n const parsed = parseResource(content);\n results.push({\n name: parsed.name,\n slug: entry.name.replace(/\\.md$/, ''),\n category: parsed.category,\n source: parsed.source,\n relatedAssignments: parsed.relatedAssignments,\n updated: parsed.updated,\n });\n }\n\n results.sort((left, right) => compareTimestamps(right.updated, left.updated));\n return results;\n}\n\nasync function listMemories(projectPath: string): Promise<MemorySummary[]> {\n const memoriesDir = resolve(projectPath, 'memories');\n if (!(await fileExists(memoriesDir))) {\n return [];\n }\n\n const entries = await readdir(memoriesDir, { withFileTypes: true });\n const results: MemorySummary[] = [];\n\n for (const entry of entries) {\n if (!entry.isFile() || !entry.name.endsWith('.md') || entry.name.startsWith('_')) {\n continue;\n }\n\n const filePath = resolve(memoriesDir, entry.name);\n const content = await readFile(filePath, 'utf-8');\n const parsed = parseMemory(content);\n results.push({\n name: parsed.name,\n slug: entry.name.replace(/\\.md$/, ''),\n source: parsed.source,\n scope: parsed.scope,\n sourceAssignment: parsed.sourceAssignment,\n relatedAssignments: parsed.relatedAssignments,\n updated: parsed.updated,\n });\n }\n\n results.sort((left, right) => compareTimestamps(right.updated, left.updated));\n return results;\n}\n\n/**\n * Walk every project and return its memories enriched with project context.\n *\n * `projectSlug` is the on-disk directory name (used for path-based routes like\n * `/api/projects/:slug/memories/:itemSlug` and the `/projects/:slug/...` UI routes).\n * In typical projects this equals the frontmatter `slug`, but fixtures/legacy projects\n * may differ — and the directory name is what every path-based route resolves against.\n */\nexport async function listAllMemories(\n projectsDir: string,\n): Promise<MemorySummaryWithProject[]> {\n const projectRecords = await listProjectRecords(projectsDir);\n const all: MemorySummaryWithProject[] = [];\n for (const record of projectRecords) {\n const memories = await listMemories(record.projectPath);\n for (const memory of memories) {\n all.push({\n ...memory,\n projectSlug: basename(record.projectPath),\n projectTitle: record.summary.title,\n });\n }\n }\n all.sort((left, right) => compareTimestamps(right.updated, left.updated));\n return all;\n}\n\n/** Walk every project and return its resources enriched with project context. */\nexport async function listAllResources(\n projectsDir: string,\n): Promise<ResourceSummaryWithProject[]> {\n const projectRecords = await listProjectRecords(projectsDir);\n const all: ResourceSummaryWithProject[] = [];\n for (const record of projectRecords) {\n const resources = await listResources(record.projectPath);\n for (const resource of resources) {\n all.push({\n ...resource,\n projectSlug: basename(record.projectPath),\n projectTitle: record.summary.title,\n });\n }\n }\n all.sort((left, right) => compareTimestamps(right.updated, left.updated));\n return all;\n}\n\n/**\n * Resolve a project slug to its on-disk directory path.\n * Tries the dir-name match first (the typical case); falls back to scanning every project\n * for a frontmatter-slug match. Returns `null` when no project matches.\n */\nexport async function resolveProjectPath(\n projectsDir: string,\n projectSlug: string,\n): Promise<string | null> {\n const direct = resolve(projectsDir, projectSlug);\n if (await fileExists(resolve(direct, 'project.md'))) return direct;\n const records = await listProjectRecords(projectsDir);\n const match = records.find((r) => r.summary.slug === projectSlug);\n return match ? match.projectPath : null;\n}\n\nexport async function getMemoryDetail(\n projectsDir: string,\n projectSlug: string,\n itemSlug: string,\n): Promise<MemoryDetail | null> {\n if (itemSlug.startsWith('_')) return null;\n\n const projectRecords = await listProjectRecords(projectsDir);\n // Match by directory name first (the path-based routing convention) and fall back to\n // the frontmatter slug — covers fixtures/legacy projects whose dir name differs from slug.\n const projectRecord = projectRecords.find(\n (p) => basename(p.projectPath) === projectSlug || p.summary.slug === projectSlug,\n );\n if (!projectRecord) return null;\n\n const filePath = resolve(projectRecord.projectPath, 'memories', `${itemSlug}.md`);\n if (!(await fileExists(filePath))) return null;\n\n const content = await readFile(filePath, 'utf-8');\n const parsed = parseMemory(content);\n return {\n name: parsed.name,\n slug: itemSlug,\n source: parsed.source,\n scope: parsed.scope,\n sourceAssignment: parsed.sourceAssignment,\n relatedAssignments: parsed.relatedAssignments,\n updated: parsed.updated,\n created: parsed.created,\n body: parsed.body,\n tags: parsed.tags,\n projectSlug: basename(projectRecord.projectPath),\n projectTitle: projectRecord.summary.title,\n };\n}\n\nexport async function getResourceDetail(\n projectsDir: string,\n projectSlug: string,\n itemSlug: string,\n): Promise<ResourceDetail | null> {\n if (itemSlug.startsWith('_')) return null;\n\n const projectRecords = await listProjectRecords(projectsDir);\n const projectRecord = projectRecords.find(\n (p) => basename(p.projectPath) === projectSlug || p.summary.slug === projectSlug,\n );\n if (!projectRecord) return null;\n\n const filePath = resolve(projectRecord.projectPath, 'resources', `${itemSlug}.md`);\n if (!(await fileExists(filePath))) return null;\n\n const content = await readFile(filePath, 'utf-8');\n const parsed = parseResource(content);\n return {\n name: parsed.name,\n slug: itemSlug,\n category: parsed.category,\n source: parsed.source,\n relatedAssignments: parsed.relatedAssignments,\n updated: parsed.updated,\n created: parsed.created,\n body: parsed.body,\n projectSlug: basename(projectRecord.projectPath),\n projectTitle: projectRecord.summary.title,\n };\n}\n\nasync function loadDependencyGraph(\n projectPath: string,\n assignments: AssignmentRecord[],\n): Promise<string | null> {\n const statusPath = resolve(projectPath, '_status.md');\n if (await fileExists(statusPath)) {\n const statusContent = await readFile(statusPath, 'utf-8');\n const parsed = parseStatus(statusContent);\n const derivedGraph = extractMermaidGraph(parsed.body);\n if (derivedGraph) {\n return derivedGraph;\n }\n }\n\n return buildDependencyGraph(assignments);\n}\n\nasync function buildProjectRollup(\n projectPath: string,\n project: ReturnType<typeof parseProject>,\n assignments: AssignmentRecord[],\n): Promise<{\n progress: ProgressCounts;\n needsAttention: NeedsAttention;\n status: string;\n}> {\n const progress: ProgressCounts = { total: assignments.length };\n\n let openQuestions = 0;\n for (const assignment of assignments) {\n const s = assignment.status;\n progress[s] = (progress[s] ?? 0) + 1;\n openQuestions += await countOpenQuestions(projectPath, assignment.slug);\n }\n\n const needsAttention: NeedsAttention = {\n blockedCount: progress['blocked'] ?? 0,\n failedCount: progress['failed'] ?? 0,\n openQuestions,\n };\n\n let status = 'pending';\n if (project.statusOverride) {\n status = project.statusOverride;\n } else if (project.archived) {\n status = 'archived';\n } else if (progress.total > 0 && (progress['completed'] ?? 0) === progress.total) {\n status = 'completed';\n } else if ((progress['in_progress'] ?? 0) > 0 || (progress['review'] ?? 0) > 0) {\n status = 'active';\n } else if ((progress['failed'] ?? 0) > 0) {\n status = 'failed';\n } else if ((progress['blocked'] ?? 0) > 0) {\n status = 'blocked';\n } else if (progress.total === 0 || (progress['pending'] ?? 0) === progress.total) {\n status = 'pending';\n } else {\n status = 'active';\n }\n\n return { progress, needsAttention, status };\n}\n\nfunction toAssignmentSummary(assignment: AssignmentRecord): AssignmentSummary {\n return {\n id: assignment.id,\n slug: assignment.slug,\n title: assignment.title,\n status: assignment.status,\n priority: assignment.priority as AssignmentSummary['priority'],\n assignee: assignment.assignee,\n dependsOn: assignment.dependsOn,\n links: assignment.links,\n updated: assignment.updated,\n };\n}\n\nasync function toAssignmentBoardItem(\n projectsDir: string,\n projectRecord: ProjectRecord,\n assignment: AssignmentRecord,\n): Promise<AssignmentBoardItem> {\n return {\n ...toAssignmentSummary(assignment),\n projectSlug: projectRecord.summary.slug,\n projectTitle: projectRecord.summary.title,\n blockedReason: assignment.blockedReason,\n projectWorkspace: projectRecord.project.workspace,\n availableTransitions: await getAvailableTransitions(\n projectsDir,\n projectRecord.summary.slug,\n assignment.slug,\n assignment,\n ),\n };\n}\n\nconst DEFAULT_GRAPH_COLORS: Record<string, string> = {\n completed: 'fill:#4ea84f,stroke:#1f6b29,color:#ffffff',\n in_progress: 'fill:#1e6fd9,stroke:#0f3f8f,color:#ffffff',\n pending: 'fill:#c0ccd9,stroke:#738399,color:#163047',\n blocked: 'fill:#db5a3f,stroke:#8d2815,color:#ffffff',\n failed: 'fill:#9f2d2d,stroke:#651616,color:#ffffff',\n review: 'fill:#c6911e,stroke:#7a5a10,color:#ffffff',\n};\n\nfunction buildDependencyGraph(assignments: AssignmentRecord[]): string | null {\n const edges: string[] = [];\n const usedStatuses = new Set<string>();\n\n for (const assignment of assignments) {\n for (const dependency of assignment.dependsOn) {\n const depStatus = findAssignmentStatus(assignments, dependency);\n usedStatuses.add(depStatus);\n usedStatuses.add(assignment.status);\n edges.push(\n ` ${dependency}:::${depStatus} --> ${assignment.slug}:::${assignment.status}`,\n );\n }\n }\n\n if (edges.length === 0) {\n return null;\n }\n\n const classDefs: string[] = [];\n for (const status of usedStatuses) {\n const colors = DEFAULT_GRAPH_COLORS[status] ?? 'fill:#94a3b8,stroke:#64748b,color:#ffffff';\n classDefs.push(` classDef ${status} ${colors}`);\n }\n\n return ['graph TD', ...edges, ...classDefs].join('\\n');\n}\n\nfunction findAssignmentStatus(assignments: AssignmentRecord[], slug: string): string {\n return assignments.find((assignment) => assignment.slug === slug)?.status ?? 'pending';\n}\n\nasync function getAvailableTransitions(\n projectsDir: string,\n projectSlug: string,\n assignmentSlug: string,\n assignment: AssignmentRecord,\n): Promise<AssignmentTransitionAction[]> {\n const config = await getStatusConfig();\n const transitionDefs = getTransitionDefinitions(config);\n const actions: AssignmentTransitionAction[] = [];\n const projectPath = resolve(projectsDir, projectSlug);\n\n for (const definition of transitionDefs) {\n let warning: string | null = null;\n\n if (definition.command === 'start' && !assignment.assignee) {\n warning = 'No assignee set — consider assigning before starting.';\n }\n\n if (definition.command === 'start' && assignment.dependsOn.length > 0) {\n const unmetDependencies = await getUnmetDependencies(projectPath, assignment.dependsOn, config.terminalStatuses);\n if (unmetDependencies.length > 0) {\n warning = `Unmet dependencies: ${unmetDependencies.join(', ')}.`;\n }\n }\n\n const target = getTargetStatus(assignment.status, definition.command, config.transitionTable);\n\n actions.push({\n command: definition.command,\n label: definition.label,\n description: definition.description,\n targetStatus: target ?? definition.command,\n disabled: false,\n disabledReason: null,\n warning,\n requiresReason: definition.requiresReason,\n });\n }\n\n return actions;\n}\n\nasync function getUnmetDependencies(projectPath: string, dependsOn: string[], terminalStatuses?: ReadonlySet<string>): Promise<string[]> {\n const terminals = terminalStatuses ?? new Set(['completed']);\n const unmet: string[] = [];\n\n for (const dependency of dependsOn) {\n const dependencyPath = resolve(projectPath, 'assignments', dependency, 'assignment.md');\n if (!(await fileExists(dependencyPath))) {\n unmet.push(`${dependency} (missing)`);\n continue;\n }\n\n const content = await readFile(dependencyPath, 'utf-8');\n const parsed = parseAssignmentFull(content);\n if (!terminals.has(parsed.status)) {\n unmet.push(`${dependency} (${parsed.status})`);\n }\n }\n\n return unmet;\n}\n\ninterface OverviewSegmentBuckets {\n readyForReview: AttentionItem[];\n readyToImplement: AttentionItem[];\n readyForPlanning: AttentionItem[];\n inProgress: AttentionItem[];\n drafts: AttentionItem[];\n blocked: AttentionItem[];\n newestCreated: AttentionItem[];\n stale: AttentionItem[];\n}\n\nfunction emptyBuckets(): OverviewSegmentBuckets {\n return {\n readyForReview: [],\n readyToImplement: [],\n readyForPlanning: [],\n inProgress: [],\n drafts: [],\n blocked: [],\n newestCreated: [],\n stale: [],\n };\n}\n\nfunction segmentSeverity(segment: OverviewSegmentId): AttentionItem['severity'] {\n switch (segment) {\n case 'blocked':\n return 'high';\n case 'readyForReview':\n return 'medium';\n case 'stale':\n return 'low';\n default:\n return 'medium';\n }\n}\n\nasync function buildOverviewSegmentBuckets(\n projectsDir: string,\n projectRecords: ProjectRecord[],\n standaloneRecords: StandaloneRecord[],\n): Promise<OverviewSegmentBuckets> {\n const now = Date.now();\n const buckets = emptyBuckets();\n // Pool of all non-terminal rows (across primary segments) used to seed\n // `newestCreated`. Each entry remembers its `created` timestamp + the row\n // we'd clone into the segment.\n const newestPool: Array<{ created: string; clone: AttentionItem }> = [];\n\n for (const record of projectRecords) {\n for (const assignment of record.assignments) {\n const segmentId = STATUS_TO_SEGMENT[assignment.status];\n const stale = isStale(assignment.updated);\n const isTerminal = TERMINAL_STATUSES.has(assignment.status);\n const agingMs = Math.max(0, now - parseTimestamp(assignment.updated));\n const baseId = `${record.summary.slug}:${assignment.slug}`;\n const availableTransitions = await getAvailableTransitions(\n projectsDir,\n record.summary.slug,\n assignment.slug,\n assignment,\n );\n\n const shared = {\n projectSlug: record.summary.slug,\n projectTitle: record.summary.title,\n assignmentSlug: assignment.slug,\n assignmentTitle: assignment.title,\n status: assignment.status,\n updated: assignment.updated,\n href: `/projects/${record.summary.slug}/assignments/${assignment.slug}`,\n blockedReason: assignment.blockedReason,\n stale,\n agingMs,\n assignee: assignment.assignee ?? null,\n availableTransitions,\n };\n\n if (segmentId) {\n const reason =\n segmentId === 'blocked' && assignment.blockedReason\n ? assignment.blockedReason\n : SEGMENT_REASON[segmentId];\n const primary: AttentionItem = {\n ...shared,\n id: `${baseId}:${segmentId}`,\n severity: segmentSeverity(segmentId),\n reason,\n segment: segmentId,\n };\n buckets[segmentId].push(primary);\n }\n\n if (stale && !isTerminal) {\n const staleItem: AttentionItem = {\n ...shared,\n id: `${baseId}:stale`,\n severity: 'low',\n reason: SEGMENT_REASON.stale,\n segment: 'stale',\n };\n buckets.stale.push(staleItem);\n }\n\n if (!isTerminal) {\n newestPool.push({\n created: assignment.created,\n clone: {\n ...shared,\n id: `${baseId}:newest`,\n severity: 'low',\n reason: SEGMENT_REASON.newestCreated,\n segment: 'newestCreated',\n },\n });\n }\n }\n }\n\n for (const sr of standaloneRecords) {\n const assignment = sr.record;\n const segmentId = STATUS_TO_SEGMENT[assignment.status];\n const stale = isStale(assignment.updated);\n const isTerminal = TERMINAL_STATUSES.has(assignment.status);\n const agingMs = Math.max(0, now - parseTimestamp(assignment.updated));\n const baseId = `standalone:${sr.id}`;\n const availableTransitions = await getStandaloneAvailableTransitions(assignment);\n\n const shared = {\n projectSlug: null,\n projectTitle: null,\n assignmentSlug: assignment.slug || sr.id,\n assignmentTitle: assignment.title,\n status: assignment.status,\n updated: assignment.updated,\n href: `/assignments/${sr.id}`,\n blockedReason: assignment.blockedReason,\n stale,\n agingMs,\n assignee: assignment.assignee ?? null,\n availableTransitions,\n };\n\n if (segmentId) {\n const reason =\n segmentId === 'blocked' && assignment.blockedReason\n ? assignment.blockedReason\n : SEGMENT_REASON[segmentId];\n buckets[segmentId].push({\n ...shared,\n id: `${baseId}:${segmentId}`,\n severity: segmentSeverity(segmentId),\n reason,\n segment: segmentId,\n });\n }\n\n if (stale && !isTerminal) {\n buckets.stale.push({\n ...shared,\n id: `${baseId}:stale`,\n severity: 'low',\n reason: SEGMENT_REASON.stale,\n segment: 'stale',\n });\n }\n\n if (!isTerminal) {\n newestPool.push({\n created: assignment.created,\n clone: {\n ...shared,\n id: `${baseId}:newest`,\n severity: 'low',\n reason: SEGMENT_REASON.newestCreated,\n segment: 'newestCreated',\n },\n });\n }\n }\n\n newestPool.sort((a, b) => compareTimestamps(b.created, a.created));\n buckets.newestCreated = newestPool.slice(0, NEWEST_CREATED_LIMIT).map((entry) => entry.clone);\n\n for (const key of Object.keys(buckets) as OverviewSegmentId[]) {\n if (key === 'newestCreated') continue; // already sorted by `created`\n if (key === 'stale') {\n buckets[key].sort((a, b) => b.agingMs - a.agingMs);\n continue;\n }\n buckets[key].sort((a, b) => compareTimestamps(b.updated, a.updated));\n }\n\n return buckets;\n}\n\nfunction toOverviewSegments(\n buckets: OverviewSegmentBuckets,\n staleOpts: { staleLimit: number; staleOffset: number },\n): OverviewSegments {\n const sliceCap = (items: AttentionItem[]): OverviewSegmentPayload => ({\n items: items.slice(0, SEGMENT_DISPLAY_CAP),\n total: items.length,\n });\n\n const stale = buckets.stale;\n const staleSlice = stale.slice(staleOpts.staleOffset, staleOpts.staleOffset + staleOpts.staleLimit);\n const staleSegment: OverviewStaleSegmentPayload = {\n items: staleSlice,\n total: stale.length,\n limit: staleOpts.staleLimit,\n offset: staleOpts.staleOffset,\n hasMore: staleOpts.staleOffset + staleSlice.length < stale.length,\n };\n\n return {\n readyForReview: sliceCap(buckets.readyForReview),\n readyToImplement: sliceCap(buckets.readyToImplement),\n readyForPlanning: sliceCap(buckets.readyForPlanning),\n inProgress: sliceCap(buckets.inProgress),\n drafts: sliceCap(buckets.drafts),\n blocked: sliceCap(buckets.blocked),\n newestCreated: { items: buckets.newestCreated, total: buckets.newestCreated.length },\n stale: staleSegment,\n };\n}\n\nfunction pickOverviewHero(buckets: OverviewSegmentBuckets): OverviewHeroRecommendation {\n for (const [segmentId, kind] of HERO_PRIORITY) {\n const bucket = buckets[segmentId];\n if (bucket.length === 0) continue;\n const top = bucket[0];\n const total = bucket.length;\n const copyKey = total === 1 ? `${kind}.singular` : kind;\n return { kind, copyKey, itemId: top.id, total };\n }\n return { kind: 'clean', copyKey: 'clean', itemId: null, total: 0 };\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n if (!Number.isFinite(value)) return min;\n return Math.min(Math.max(value, min), max);\n}\n\nfunction buildRecentActivity(\n projectRecords: ProjectRecord[],\n standaloneRecords: StandaloneRecord[] = [],\n): RecentActivityItem[] {\n const activity: RecentActivityItem[] = [];\n\n for (const record of projectRecords) {\n activity.push({\n id: `project:${record.summary.slug}`,\n type: 'project',\n title: record.summary.title,\n updated: record.summary.updated,\n href: `/projects/${record.summary.slug}`,\n projectSlug: record.summary.slug,\n projectTitle: record.summary.title,\n assignmentSlug: null,\n summary: `Project status is ${record.summary.status}.`,\n });\n\n for (const assignment of record.assignments) {\n activity.push({\n id: `assignment:${record.summary.slug}:${assignment.slug}`,\n type: 'assignment',\n title: assignment.title,\n updated: assignment.updated,\n href: `/projects/${record.summary.slug}/assignments/${assignment.slug}`,\n projectSlug: record.summary.slug,\n projectTitle: record.summary.title,\n assignmentSlug: assignment.slug,\n summary: `Assignment is ${assignment.status} with ${assignment.priority} priority.`,\n });\n }\n }\n\n for (const sr of standaloneRecords) {\n const assignment = sr.record;\n activity.push({\n id: `standalone-assignment:${sr.id}`,\n type: 'assignment',\n title: assignment.title,\n updated: assignment.updated,\n href: `/assignments/${sr.id}`,\n projectSlug: null,\n projectTitle: null,\n assignmentSlug: assignment.slug || sr.id,\n summary: `Standalone assignment is ${assignment.status} with ${assignment.priority} priority.`,\n });\n }\n\n activity.sort((left, right) => compareTimestamps(right.updated, left.updated));\n return activity;\n}\n\nfunction compareTimestamps(left: string, right: string): number {\n return parseTimestamp(left) - parseTimestamp(right);\n}\n\nfunction parseTimestamp(timestamp: string): number {\n const parsed = Date.parse(timestamp);\n return Number.isFinite(parsed) ? parsed : 0;\n}\n\nfunction isStale(updated: string): boolean {\n const timestamp = parseTimestamp(updated);\n if (timestamp === 0) {\n return false;\n }\n return Date.now() - timestamp > STALE_ASSIGNMENT_MS;\n}\n\nfunction countPendingAnswers(body: string): number {\n const matches = body.match(/^\\*\\*A:\\*\\*\\s+pending\\s*$/gim);\n return matches ? matches.length : 0;\n}\n\nasync function countOpenQuestions(\n projectPath: string,\n assignmentSlug: string,\n): Promise<number> {\n const commentsPath = resolve(\n projectPath,\n 'assignments',\n assignmentSlug,\n 'comments.md',\n );\n if (!(await fileExists(commentsPath))) {\n return 0;\n }\n try {\n const content = await readFile(commentsPath, 'utf-8');\n const parsed = parseComments(content);\n return parsed.entries.filter(\n (e) => e.type === 'question' && e.resolved !== true,\n ).length;\n } catch {\n return 0;\n }\n}\n\nfunction getProjectActivityTimestamp(projectUpdated: string, assignments: AssignmentRecord[]): string {\n let latest = projectUpdated;\n for (const assignment of assignments) {\n if (compareTimestamps(assignment.updated, latest) > 0) {\n latest = assignment.updated;\n }\n }\n return latest;\n}\n\nfunction getDocumentPath(\n projectsDir: string,\n documentType: EditableDocumentResponse['documentType'],\n projectSlug: string,\n assignmentSlug?: string,\n): string | null {\n switch (documentType) {\n case 'project':\n return resolve(projectsDir, projectSlug, 'project.md');\n case 'assignment':\n return assignmentSlug\n ? resolve(projectsDir, projectSlug, 'assignments', assignmentSlug, 'assignment.md')\n : null;\n case 'plan':\n return assignmentSlug\n ? resolve(projectsDir, projectSlug, 'assignments', assignmentSlug, 'plan.md')\n : null;\n case 'scratchpad':\n return assignmentSlug\n ? resolve(projectsDir, projectSlug, 'assignments', assignmentSlug, 'scratchpad.md')\n : null;\n case 'handoff':\n return assignmentSlug\n ? resolve(projectsDir, projectSlug, 'assignments', assignmentSlug, 'handoff.md')\n : null;\n case 'decision-record':\n return assignmentSlug\n ? resolve(projectsDir, projectSlug, 'assignments', assignmentSlug, 'decision-record.md')\n : null;\n case 'memory':\n // For memory/resource, the second positional is the item slug.\n return assignmentSlug\n ? resolve(projectsDir, projectSlug, 'memories', `${assignmentSlug}.md`)\n : null;\n case 'resource':\n return assignmentSlug\n ? resolve(projectsDir, projectSlug, 'resources', `${assignmentSlug}.md`)\n : null;\n default:\n return null;\n }\n}\n\nfunction getEditableDocumentTitle(\n documentType: EditableDocumentResponse['documentType'],\n projectSlug: string,\n assignmentSlug?: string,\n): string {\n switch (documentType) {\n case 'project':\n return `Edit Project: ${projectSlug}`;\n case 'assignment':\n return `Edit Assignment: ${assignmentSlug || 'assignment'}`;\n case 'plan':\n return `Edit Plan: ${assignmentSlug || 'assignment'}`;\n case 'scratchpad':\n return `Edit Scratchpad: ${assignmentSlug || 'assignment'}`;\n case 'handoff':\n return `Append Handoff: ${assignmentSlug || 'assignment'}`;\n case 'decision-record':\n return `Append Decision: ${assignmentSlug || 'assignment'}`;\n case 'playbook':\n return `Edit Playbook: ${projectSlug}`;\n case 'memory':\n return `Edit Memory: ${assignmentSlug || 'memory'}`;\n case 'resource':\n return `Edit Resource: ${assignmentSlug || 'resource'}`;\n default:\n return projectSlug;\n }\n}\n\n// --- Playbook API ---\n\nexport async function listPlaybooks(playbooksDir: string): Promise<PlaybookSummary[]> {\n if (!(await fileExists(playbooksDir))) return [];\n\n const config = await readConfig();\n const disabledSet = new Set(config.playbooks.disabled);\n\n const entries = await readdir(playbooksDir, { withFileTypes: true });\n const playbooks: PlaybookSummary[] = [];\n\n for (const entry of entries) {\n if (!entry.isFile() || !entry.name.endsWith('.md') || entry.name.startsWith('_') || entry.name === 'manifest.md') continue;\n\n const filePath = resolve(playbooksDir, entry.name);\n const raw = await readFile(filePath, 'utf-8');\n const parsed = parsePlaybook(raw);\n\n const slug = parsed.slug || entry.name.replace(/\\.md$/, '');\n playbooks.push({\n slug,\n name: parsed.name || slug,\n description: parsed.description,\n whenToUse: parsed.whenToUse,\n tags: parsed.tags,\n created: parsed.created,\n updated: parsed.updated,\n enabled: !disabledSet.has(slug),\n });\n }\n\n return playbooks.sort((a, b) => (b.updated || b.created).localeCompare(a.updated || a.created));\n}\n\nexport async function getPlaybookDetail(\n playbooksDir: string,\n slug: string,\n): Promise<PlaybookDetail | null> {\n const resolved = await resolvePlaybookSlug(playbooksDir, slug);\n if (!resolved) return null;\n\n const config = await readConfig();\n const enabled = !config.playbooks.disabled.includes(resolved.slug);\n\n const parsed = resolved.parsed;\n return {\n slug: resolved.slug,\n name: parsed.name || resolved.slug,\n description: parsed.description,\n whenToUse: parsed.whenToUse,\n tags: parsed.tags,\n created: parsed.created,\n updated: parsed.updated,\n body: parsed.body,\n enabled,\n };\n}\n","export interface AppendTodoLine {\n description: string;\n trace?: string;\n}\n\nfunction setTopLevelField(content: string, key: string, value: string): string {\n const fieldRegex = new RegExp(`^(${key}:)\\\\s*.*$`, 'm');\n if (fieldRegex.test(content)) {\n return content.replace(fieldRegex, `$1 ${value}`);\n }\n return content;\n}\n\nexport function appendTodosToAssignmentBody(\n body: string,\n todos: AppendTodoLine[],\n): string {\n if (todos.length === 0) return body;\n\n const lines = todos.map((t) => {\n const base = `- [ ] ${t.description.trim()}`;\n return t.trace ? `${base} <!-- ${t.trace} -->` : base;\n });\n const block = lines.join('\\n');\n\n const todosHeading = /^## Todos\\s*$/m;\n if (todosHeading.test(body)) {\n return body.replace(\n /(^## Todos[\\s\\S]*?)(\\n## |\\n*$)/m,\n (_m, section, nextHeading) => {\n return `${section.trimEnd()}\\n${block}\\n${nextHeading}`;\n },\n );\n }\n return `${body.trimEnd()}\\n\\n## Todos\\n\\n${block}\\n`;\n}\n\nexport function touchAssignmentUpdated(content: string, timestamp: string): string {\n return setTopLevelField(content, 'updated', `\"${timestamp}\"`);\n}\n","import express from 'express';\nimport { createServer } from 'node:http';\nimport { resolve } from 'node:path';\nimport { writeFile, unlink } from 'node:fs/promises';\nimport { syntaurRoot } from '../utils/paths.js';\nimport { WebSocketServer, WebSocket } from 'ws';\nimport {\n listProjects,\n listAssignmentsBoard,\n listAllMemories,\n listAllResources,\n getProjectDetail,\n getAssignmentDetail,\n getAssignmentDetailById,\n getOverview,\n getHelp,\n getStatusConfig,\n clearStatusConfigCache,\n listWorkspaces,\n createWorkspace,\n deleteWorkspace,\n WorkspaceBlockedError,\n} from './api.js';\nimport { resolveAssignmentById } from '../utils/assignment-resolver.js';\nimport { listSessionsByAssignment, reconcileActiveSessions } from './agent-sessions.js';\nimport { enrichSessions } from './session-liveness.js';\nimport { createWatcher } from './watcher.js';\nimport { fileExists } from '../utils/fs.js';\nimport {\n writeStatusConfig,\n deleteStatusConfig,\n writeThemeConfig,\n deleteThemeConfig,\n writeHotkeyBindingsConfig,\n deleteHotkeyBindingsConfig,\n readConfig,\n getAgents,\n} from '../utils/config.js';\nimport {\n BINDABLE_ACTION_KINDS,\n canonicalizeCombo,\n isBindableActionKind,\n isReservedCombo,\n type BindableActionKind,\n} from '../utils/hotkeysCatalog.js';\nimport {\n isViewMode,\n isSortField,\n isSortDirection,\n isDensity,\n isGrouping,\n isActivity,\n isFilterString,\n type ViewPrefs,\n type ProjectViewPrefs,\n type ViewFilters,\n type ViewPrefsPatch,\n} from '../utils/view-prefs-schema.js';\nimport {\n readViewPrefsFile,\n applyViewPrefsPatch,\n resetViewPrefsFile,\n isViewPrefsDefaults,\n} from '../utils/view-prefs.js';\nimport { withLock } from './todos-locks.js';\nimport { createWriteRouter } from './api-write.js';\nimport { createServersRouter } from './api-servers.js';\nimport { createAgentSessionsRouter } from './api-agent-sessions.js';\nimport { createAgentsRouter } from './api-agents.js';\nimport { createLaunchPreflightRouter } from './api-launch-preflight.js';\nimport { createTerminalConfigRouter } from './api-terminal-config.js';\nimport { createLeasesRouter } from './api-leases.js';\nimport { createPlaybooksRouter } from './api-playbooks.js';\nimport {\n migrateLegacyProjectFiles,\n migrateLegacyConfig,\n summarizeMigration,\n} from '../utils/fs-migration.js';\nimport { createTodosRouter } from './api-todos.js';\nimport { createProjectTodosRouter } from './api-project-todos.js';\nimport { createBackupRouter } from './api-backup.js';\nimport { initSessionDb, migrateFromMarkdown, closeSessionDb } from './session-db.js';\nimport { initLeasesDb, closeLeasesDb } from '../db/leases-db.js';\nimport { startAutodiscovery, stopAutodiscovery } from './autodiscovery.js';\nimport type { WsMessage } from './types.js';\n\nexport interface DashboardServerOptions {\n port: number;\n projectsDir: string;\n /**\n * Absolute path to the standalone assignments directory (`~/.syntaur/assignments/`).\n * Standalone assignments have `project: null` and live in folders named by UUID.\n */\n assignmentsDir: string;\n serversDir: string;\n playbooksDir: string;\n todosDir: string;\n serveStaticUi: boolean;\n /** Absolute path to the built dashboard UI (dashboard/dist). Required when serveStaticUi is true. */\n dashboardDistPath?: string;\n}\n\nexport function createDashboardServer(options: DashboardServerOptions) {\n const { port, projectsDir, assignmentsDir, serversDir, playbooksDir, todosDir, serveStaticUi, dashboardDistPath } = options;\n const app = express();\n const server = createServer(app);\n\n // --- WebSocket ---\n const wss = new WebSocketServer({ noServer: true });\n const clients = new Set<WebSocket>();\n\n server.on('upgrade', (request, socket, head) => {\n if (request.url === '/ws') {\n wss.handleUpgrade(request, socket, head, (ws) => {\n wss.emit('connection', ws, request);\n });\n } else {\n socket.destroy();\n }\n });\n\n wss.on('connection', (ws) => {\n clients.add(ws);\n const connectMsg: WsMessage = {\n type: 'connected',\n timestamp: new Date().toISOString(),\n };\n ws.send(JSON.stringify(connectMsg));\n\n ws.on('close', () => {\n clients.delete(ws);\n });\n });\n\n function broadcast(message: WsMessage): void {\n const data = JSON.stringify(message);\n for (const client of clients) {\n if (client.readyState === WebSocket.OPEN) {\n client.send(data);\n }\n }\n }\n\n // --- Initialize session database ---\n initSessionDb();\n migrateFromMarkdown(projectsDir).catch((err) => {\n console.error('Session migration from markdown failed:', err);\n });\n\n // --- Initialize leases database (shares syntaur.db) ---\n initLeasesDb();\n\n // --- One-shot legacy filesystem migration (pre-v0.2.0 → v0.2.0+) ---\n // Idempotent, non-destructive, reports what it did. Run in the background\n // so startup isn't gated on filesystem work.\n (async () => {\n try {\n const configResult = await migrateLegacyConfig(\n resolve(syntaurRoot(), 'config.md'),\n );\n const projectResult = await migrateLegacyProjectFiles(projectsDir);\n const summary = summarizeMigration(projectResult, configResult);\n if (summary) console.log(summary);\n } catch (err) {\n console.error('Legacy filesystem migration failed:', err);\n }\n })();\n\n // --- JSON body parsing ---\n app.use(express.json());\n\n // --- API Routes ---\n app.get('/api/overview', async (req, res) => {\n try {\n const staleLimitRaw = req.query.staleLimit;\n const staleOffsetRaw = req.query.staleOffset;\n const staleLimit = typeof staleLimitRaw === 'string' ? Number(staleLimitRaw) : undefined;\n const staleOffset = typeof staleOffsetRaw === 'string' ? Number(staleOffsetRaw) : undefined;\n const overview = await getOverview(projectsDir, serversDir, assignmentsDir, {\n staleLimit,\n staleOffset,\n });\n res.json(overview);\n } catch (error) {\n console.error('Error getting overview:', error);\n res.status(500).json({ error: 'Failed to get overview' });\n }\n });\n\n app.get('/api/help', async (_req, res) => {\n try {\n const help = await getHelp();\n res.json(help);\n } catch (error) {\n console.error('Error getting help content:', error);\n res.status(500).json({ error: 'Failed to get help content' });\n }\n });\n\n app.get('/api/config/statuses', async (_req, res) => {\n try {\n const config = await getStatusConfig();\n res.json({\n statuses: config.statuses,\n order: config.order,\n transitions: config.transitions,\n custom: config.custom,\n });\n } catch (error) {\n console.error('Error getting status config:', error);\n res.status(500).json({ error: 'Failed to get status config' });\n }\n });\n\n app.post('/api/config/statuses', async (req, res) => {\n try {\n const { statuses, order, transitions } = req.body;\n if (!Array.isArray(statuses) || !Array.isArray(order) || !Array.isArray(transitions)) {\n res.status(400).json({ error: 'Request body must include statuses, order, and transitions arrays' });\n return;\n }\n await writeStatusConfig({ statuses, order, transitions });\n clearStatusConfigCache();\n const config = await getStatusConfig();\n res.json({\n statuses: config.statuses,\n order: config.order,\n transitions: config.transitions,\n custom: config.custom,\n });\n } catch (error) {\n console.error('Error saving status config:', error);\n res.status(500).json({ error: 'Failed to save status config' });\n }\n });\n\n app.delete('/api/config/statuses', async (_req, res) => {\n try {\n await deleteStatusConfig();\n clearStatusConfigCache();\n const config = await getStatusConfig();\n res.json({\n statuses: config.statuses,\n order: config.order,\n transitions: config.transitions,\n custom: config.custom,\n });\n } catch (error) {\n console.error('Error resetting status config:', error);\n res.status(500).json({ error: 'Failed to reset status config' });\n }\n });\n\n // Theme presets — keep in sync with PRESETS in dashboard/src/themes.ts (canonical client list).\n const THEME_PRESET_SLUGS = ['default', 'ocean', 'forest', 'sunset'] as const;\n const DEFAULT_THEME_PRESET = 'default';\n\n app.get('/api/config/theme', async (_req, res) => {\n try {\n const config = await readConfig();\n const preset = config.theme?.preset ?? DEFAULT_THEME_PRESET;\n res.json({ preset, custom: config.theme !== null });\n } catch (error) {\n console.error('Error getting theme config:', error);\n res.status(500).json({ error: 'Failed to get theme config' });\n }\n });\n\n app.post('/api/config/theme', async (req, res) => {\n try {\n const { preset } = req.body ?? {};\n if (typeof preset !== 'string' || !(THEME_PRESET_SLUGS as readonly string[]).includes(preset)) {\n res.status(400).json({\n error: `preset must be one of: ${THEME_PRESET_SLUGS.join(', ')}`,\n });\n return;\n }\n await writeThemeConfig({ preset });\n res.json({ preset, custom: true });\n } catch (error) {\n console.error('Error saving theme config:', error);\n res.status(500).json({ error: 'Failed to save theme config' });\n }\n });\n\n app.delete('/api/config/theme', async (_req, res) => {\n try {\n await deleteThemeConfig();\n res.json({ preset: DEFAULT_THEME_PRESET, custom: false });\n } catch (error) {\n console.error('Error resetting theme config:', error);\n res.status(500).json({ error: 'Failed to reset theme config' });\n }\n });\n\n app.use('/api/config/terminal', createTerminalConfigRouter());\n\n app.get('/api/config/hotkeys', async (_req, res) => {\n try {\n const config = await readConfig();\n const bindings = config.hotkeys?.bindings ?? {};\n res.json({ bindings, custom: config.hotkeys !== null });\n } catch (error) {\n console.error('Error getting hotkeys config:', error);\n res.status(500).json({ error: 'Failed to get hotkeys config' });\n }\n });\n\n app.put('/api/config/hotkeys', async (req, res) => {\n try {\n const raw = (req.body && typeof req.body === 'object' ? req.body : {}) as {\n bindings?: unknown;\n };\n const incoming = raw.bindings;\n if (!incoming || typeof incoming !== 'object' || Array.isArray(incoming)) {\n res.status(400).json({ error: 'bindings must be an object keyed by action kind' });\n return;\n }\n const cleaned: Partial<Record<BindableActionKind, string>> = {};\n for (const [rawKind, rawValue] of Object.entries(incoming as Record<string, unknown>)) {\n if (!isBindableActionKind(rawKind)) {\n res.status(400).json({\n error: `unknown action kind \"${rawKind}\" — expected one of: ${BINDABLE_ACTION_KINDS.join(', ')}`,\n });\n return;\n }\n if (typeof rawValue !== 'string' || rawValue.trim() === '') {\n res.status(400).json({ error: `binding for \"${rawKind}\" must be a non-empty string` });\n return;\n }\n const canonical = canonicalizeCombo(rawValue);\n if (!canonical) {\n res.status(400).json({ error: `binding for \"${rawKind}\" is not a valid combo` });\n return;\n }\n if (isReservedCombo(canonical)) {\n res.status(400).json({\n error: `combo \"${canonical}\" is reserved by a built-in shortcut`,\n kind: rawKind,\n combo: canonical,\n });\n return;\n }\n cleaned[rawKind] = canonical;\n }\n // Detect duplicate combos across kinds.\n const seenCombos = new Map<string, BindableActionKind>();\n for (const [kind, combo] of Object.entries(cleaned) as Array<[BindableActionKind, string]>) {\n if (seenCombos.has(combo)) {\n res.status(400).json({\n error: `combo \"${combo}\" is bound to multiple actions`,\n kinds: [seenCombos.get(combo), kind],\n });\n return;\n }\n seenCombos.set(combo, kind);\n }\n\n await writeHotkeyBindingsConfig({ bindings: cleaned });\n res.json({ bindings: cleaned, custom: Object.keys(cleaned).length > 0 });\n } catch (error) {\n console.error('Error saving hotkeys config:', error);\n res.status(500).json({ error: 'Failed to save hotkeys config' });\n }\n });\n\n app.delete('/api/config/hotkeys', async (_req, res) => {\n try {\n await deleteHotkeyBindingsConfig();\n res.json({ bindings: {}, custom: false });\n } catch (error) {\n console.error('Error resetting hotkeys config:', error);\n res.status(500).json({ error: 'Failed to reset hotkeys config' });\n }\n });\n\n const VIEW_PREFS_LOCK = 'vp:global';\n\n const FILTER_KEYS = new Set(['status', 'priority', 'assignee', 'project', 'activity']);\n const GLOBAL_KEYS = new Set(['defaultView', 'sortField', 'sortDirection', 'density', 'grouping', 'filters']);\n const SCOPE_KEYS = new Set(['defaultView', 'sortField', 'sortDirection', 'grouping', 'filters']);\n const ROOT_KEYS = new Set(['global', 'projects']);\n\n function unknownKey(obj: Record<string, unknown>, allowed: Set<string>, where: string): string | null {\n for (const key of Object.keys(obj)) {\n if (!allowed.has(key)) return `unknown key \"${key}\" in ${where}`;\n }\n return null;\n }\n\n function validateFilters(value: unknown): { ok: true; value: ViewFilters } | { ok: false; error: string } {\n if (value === undefined) return { ok: true, value: {} };\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return { ok: false, error: 'filters must be an object' };\n }\n const obj = value as Record<string, unknown>;\n const unknown = unknownKey(obj, FILTER_KEYS, 'filters');\n if (unknown) return { ok: false, error: unknown };\n const out: ViewFilters = {};\n for (const key of ['status', 'priority', 'assignee', 'project']) {\n if (obj[key] !== undefined) {\n if (!isFilterString(obj[key])) return { ok: false, error: `filters.${key} must be a non-empty string` };\n (out as Record<string, string>)[key] = obj[key] as string;\n }\n }\n if (obj.activity !== undefined) {\n if (!isActivity(obj.activity)) return { ok: false, error: 'filters.activity invalid' };\n out.activity = obj.activity;\n }\n return { ok: true, value: out };\n }\n\n function validateGlobalPatch(value: unknown): { ok: true; value: Partial<ViewPrefs> } | { ok: false; error: string } {\n if (value === undefined) return { ok: true, value: {} };\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return { ok: false, error: 'global must be an object' };\n }\n const obj = value as Record<string, unknown>;\n const unknown = unknownKey(obj, GLOBAL_KEYS, 'global');\n if (unknown) return { ok: false, error: unknown };\n const out: Partial<ViewPrefs> = {};\n if (obj.defaultView !== undefined) {\n if (!isViewMode(obj.defaultView)) return { ok: false, error: 'global.defaultView invalid' };\n out.defaultView = obj.defaultView;\n }\n if (obj.sortField !== undefined) {\n if (!isSortField(obj.sortField)) return { ok: false, error: 'global.sortField invalid' };\n out.sortField = obj.sortField;\n }\n if (obj.sortDirection !== undefined) {\n if (!isSortDirection(obj.sortDirection)) return { ok: false, error: 'global.sortDirection invalid' };\n out.sortDirection = obj.sortDirection;\n }\n if (obj.density !== undefined) {\n if (!isDensity(obj.density)) return { ok: false, error: 'global.density invalid' };\n out.density = obj.density;\n }\n if (obj.grouping !== undefined) {\n if (!isGrouping(obj.grouping)) return { ok: false, error: 'global.grouping invalid' };\n out.grouping = obj.grouping;\n }\n if (obj.filters !== undefined) {\n const f = validateFilters(obj.filters);\n if (!f.ok) return f;\n out.filters = f.value;\n }\n return { ok: true, value: out };\n }\n\n function validateScopePatch(value: unknown): { ok: true; value: ProjectViewPrefs } | { ok: false; error: string } {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return { ok: false, error: 'project scope must be an object' };\n }\n const obj = value as Record<string, unknown>;\n if (obj.density !== undefined) {\n return { ok: false, error: 'density cannot be set per-project (global only)' };\n }\n const unknown = unknownKey(obj, SCOPE_KEYS, 'project scope');\n if (unknown) return { ok: false, error: unknown };\n const out: ProjectViewPrefs = {};\n if (obj.defaultView !== undefined) {\n if (!isViewMode(obj.defaultView)) return { ok: false, error: 'defaultView invalid' };\n out.defaultView = obj.defaultView;\n }\n if (obj.sortField !== undefined) {\n if (!isSortField(obj.sortField)) return { ok: false, error: 'sortField invalid' };\n out.sortField = obj.sortField;\n }\n if (obj.sortDirection !== undefined) {\n if (!isSortDirection(obj.sortDirection)) return { ok: false, error: 'sortDirection invalid' };\n out.sortDirection = obj.sortDirection;\n }\n if (obj.grouping !== undefined) {\n if (!isGrouping(obj.grouping)) return { ok: false, error: 'grouping invalid' };\n out.grouping = obj.grouping;\n }\n if (obj.filters !== undefined) {\n const f = validateFilters(obj.filters);\n if (!f.ok) return f;\n out.filters = f.value;\n }\n return { ok: true, value: out };\n }\n\n function validateViewPrefsPatch(body: unknown): { ok: true; value: ViewPrefsPatch } | { ok: false; error: string } {\n if (!body || typeof body !== 'object' || Array.isArray(body)) {\n return { ok: false, error: 'body must be an object with optional `global` and/or `projects` keys' };\n }\n const obj = body as Record<string, unknown>;\n const unknownRoot = unknownKey(obj, ROOT_KEYS, 'request body');\n if (unknownRoot) return { ok: false, error: unknownRoot };\n const patch: ViewPrefsPatch = {};\n const g = validateGlobalPatch(obj.global);\n if (!g.ok) return g;\n if (Object.keys(g.value).length > 0) patch.global = g.value;\n if (obj.projects !== undefined) {\n if (!obj.projects || typeof obj.projects !== 'object' || Array.isArray(obj.projects)) {\n return { ok: false, error: 'projects must be an object keyed by scope' };\n }\n const projectsOut: Record<string, ProjectViewPrefs> = {};\n for (const [scope, scopePatch] of Object.entries(obj.projects as Record<string, unknown>)) {\n if (typeof scope !== 'string' || scope.length === 0) {\n return { ok: false, error: 'project scope keys must be non-empty strings' };\n }\n const sp = validateScopePatch(scopePatch);\n if (!sp.ok) return { ok: false, error: `projects[\"${scope}\"]: ${sp.error}` };\n projectsOut[scope] = sp.value;\n }\n if (Object.keys(projectsOut).length > 0) patch.projects = projectsOut;\n }\n return { ok: true, value: patch };\n }\n\n app.get('/api/view-prefs', async (_req, res) => {\n try {\n const file = await readViewPrefsFile();\n res.json({ ...file, custom: !isViewPrefsDefaults(file) });\n } catch (error) {\n console.error('Error reading view-prefs:', error);\n res.status(500).json({ error: 'Failed to read view-prefs' });\n }\n });\n\n app.post('/api/view-prefs', async (req, res) => {\n const result = validateViewPrefsPatch(req.body);\n if (!result.ok) {\n res.status(400).json({ error: result.error });\n return;\n }\n try {\n const file = await withLock(VIEW_PREFS_LOCK, () => applyViewPrefsPatch(result.value));\n res.json({ ...file, custom: !isViewPrefsDefaults(file) });\n } catch (error) {\n console.error('Error saving view-prefs:', error);\n res.status(500).json({ error: 'Failed to save view-prefs' });\n }\n });\n\n app.delete('/api/view-prefs', async (_req, res) => {\n try {\n await withLock(VIEW_PREFS_LOCK, () => resetViewPrefsFile());\n const file = await readViewPrefsFile();\n res.json({ ...file, custom: false });\n } catch (error) {\n console.error('Error resetting view-prefs:', error);\n res.status(500).json({ error: 'Failed to reset view-prefs' });\n }\n });\n\n app.get('/api/projects', async (req, res) => {\n try {\n let projects = await listProjects(projectsDir);\n const workspaceParam = req.query.workspace as string | undefined;\n if (workspaceParam) {\n if (workspaceParam === '_ungrouped') {\n projects = projects.filter((m) => m.workspace === null);\n } else {\n projects = projects.filter((m) => m.workspace === workspaceParam);\n }\n }\n res.json(projects);\n } catch (error) {\n console.error('Error listing projects:', error);\n res.status(500).json({ error: 'Failed to list projects' });\n }\n });\n\n app.get('/api/workspaces', async (_req, res) => {\n try {\n const result = await listWorkspaces(projectsDir, assignmentsDir);\n res.json(result);\n } catch (error) {\n console.error('Error listing workspaces:', error);\n res.status(500).json({ error: 'Failed to list workspaces' });\n }\n });\n\n app.post('/api/workspaces', async (req, res) => {\n try {\n const { name } = req.body;\n if (!name || typeof name !== 'string' || !/^[a-z0-9][a-z0-9-]*$/.test(name)) {\n res.status(400).json({ error: 'Invalid workspace name. Use lowercase letters, numbers, and hyphens.' });\n return;\n }\n await createWorkspace(projectsDir, name);\n broadcast({ type: 'project-updated', projectSlug: '', timestamp: new Date().toISOString() });\n res.json({ name });\n } catch (error) {\n console.error('Error creating workspace:', error);\n res.status(500).json({ error: 'Failed to create workspace' });\n }\n });\n\n app.delete('/api/workspaces/:name', async (req, res) => {\n try {\n const cascade = req.query.cascade === 'true';\n const result = await deleteWorkspace(projectsDir, req.params.name, {\n cascade,\n assignmentsDir,\n });\n // Watchers emit project-updated / assignment-updated for any rewritten\n // file; only broadcast explicitly when the delete touched solely the\n // registry (which sits outside any watched tree).\n if (!result.rewroteFiles) {\n broadcast({ type: 'project-updated', projectSlug: '', timestamp: new Date().toISOString() });\n }\n res.json({ ok: true, rewroteFiles: result.rewroteFiles });\n } catch (error) {\n if (error instanceof WorkspaceBlockedError) {\n res.status(409).json({ error: error.message, blockedBy: error.blockedBy });\n return;\n }\n console.error('Error deleting workspace:', error);\n res.status(500).json({ error: 'Failed to delete workspace' });\n }\n });\n\n app.get('/api/assignments', async (req, res) => {\n try {\n const result = await listAssignmentsBoard(projectsDir, assignmentsDir);\n const workspaceParam = req.query.workspace as string | undefined;\n if (workspaceParam) {\n if (workspaceParam === '_ungrouped') {\n result.assignments = result.assignments.filter((a) => a.projectWorkspace === null);\n } else {\n result.assignments = result.assignments.filter((a) => a.projectWorkspace === workspaceParam);\n }\n }\n res.json(result);\n } catch (error) {\n console.error('Error listing assignments:', error);\n res.status(500).json({ error: 'Failed to list assignments' });\n }\n });\n\n app.get('/api/projects/:slug', async (req, res) => {\n try {\n const detail = await getProjectDetail(projectsDir, req.params.slug);\n if (!detail) {\n res.status(404).json({ error: `Project \"${req.params.slug}\" not found` });\n return;\n }\n res.json(detail);\n } catch (error) {\n console.error('Error getting project detail:', error);\n res.status(500).json({ error: 'Failed to get project detail' });\n }\n });\n\n app.get('/api/assignments/:id', async (req, res) => {\n try {\n const detail = await getAssignmentDetailById(projectsDir, assignmentsDir, req.params.id);\n if (!detail) {\n res.status(404).json({ error: `Assignment \"${req.params.id}\" not found` });\n return;\n }\n res.json(detail);\n } catch (error) {\n console.error('Error getting assignment by id:', error);\n res.status(500).json({ error: 'Failed to get assignment' });\n }\n });\n\n app.get('/api/assignments/:id/sessions', async (req, res) => {\n try {\n const resolved = await resolveAssignmentById(projectsDir, assignmentsDir, req.params.id);\n if (!resolved) {\n res.status(404).json({ error: `Assignment \"${req.params.id}\" not found` });\n return;\n }\n await reconcileActiveSessions(projectsDir, assignmentsDir);\n const sessions = await listSessionsByAssignment(\n resolved.standalone ? null : resolved.projectSlug,\n resolved.standalone ? resolved.id : resolved.assignmentSlug,\n );\n const agents = getAgents(await readConfig());\n res.json({\n sessions: enrichSessions(sessions, agents),\n generatedAt: new Date().toISOString(),\n });\n } catch (error) {\n console.error('Error listing sessions by id:', error);\n res.status(500).json({ error: 'Failed to list sessions' });\n }\n });\n\n app.get('/api/projects/:slug/assignments/:aslug', async (req, res) => {\n try {\n const detail = await getAssignmentDetail(\n projectsDir,\n req.params.slug,\n req.params.aslug,\n );\n if (!detail) {\n res.status(404).json({\n error: `Assignment \"${req.params.aslug}\" not found in project \"${req.params.slug}\"`,\n });\n return;\n }\n res.json(detail);\n } catch (error) {\n console.error('Error getting assignment detail:', error);\n res.status(500).json({ error: 'Failed to get assignment detail' });\n }\n });\n\n // --- Write API (create projects/assignments) ---\n app.use(createWriteRouter(projectsDir, assignmentsDir, todosDir));\n\n // --- Servers API ---\n app.use('/api/servers', createServersRouter(serversDir, projectsDir, assignmentsDir));\n\n // --- Leases API ---\n app.use('/api/leases', createLeasesRouter(broadcast));\n\n // --- Agent Sessions API ---\n app.use('/api/agent-sessions', createAgentSessionsRouter(projectsDir, broadcast, assignmentsDir));\n\n // --- Agents Config API ---\n app.use('/api/config/agents', createAgentsRouter());\n\n // --- Launch Preflight API ---\n app.use('/api/launch', createLaunchPreflightRouter());\n\n // --- Playbooks API ---\n app.use('/api/playbooks', createPlaybooksRouter(playbooksDir));\n\n // --- Memories / Resources (cross-project list) ---\n app.get('/api/memories', async (_req, res) => {\n try {\n const memories = await listAllMemories(projectsDir);\n res.json({ generatedAt: new Date().toISOString(), memories });\n } catch (error) {\n console.error('Error listing memories:', error);\n res.status(500).json({ error: `Failed to load memories: ${(error as Error).message}` });\n }\n });\n\n app.get('/api/resources', async (_req, res) => {\n try {\n const resources = await listAllResources(projectsDir);\n res.json({ generatedAt: new Date().toISOString(), resources });\n } catch (error) {\n console.error('Error listing resources:', error);\n res.status(500).json({ error: `Failed to load resources: ${(error as Error).message}` });\n }\n });\n\n // --- Todos API ---\n app.use('/api/todos', createTodosRouter(todosDir, broadcast, projectsDir));\n app.use('/api/projects/:projectId/todos', createProjectTodosRouter(projectsDir, broadcast, todosDir));\n\n // --- Backup API ---\n app.use('/api/backup', createBackupRouter());\n\n // --- Static files (production only) ---\n // Only serve the built asset directory as static — never let express.static\n // try to resolve arbitrary client-side route paths (e.g. /assignments/:id)\n // as files, which makes `send` emit NotFoundError on every SPA refresh.\n if (serveStaticUi && dashboardDistPath) {\n // `dotfiles: 'allow'` is required because the resolved package path may\n // live under a dot-prefixed directory (npm/npx caches under ~/.npm,\n // installs under ~/.nvm, ~/.local, etc.). The default 'ignore' makes\n // `send` 404 every file with a dot-component anywhere in the path.\n const sendOpts = { dotfiles: 'allow' as const };\n\n app.use('/assets', express.static(resolve(dashboardDistPath, 'assets'), sendOpts));\n // Files copied from dashboard/public/ (logo, favicon, etc.) land at the\n // dist root; serve them with fallthrough so missing paths still hit the\n // SPA fallback below. `index: false` prevents express.static from serving\n // index.html for \"/\" — that's the SPA fallback's job.\n app.use(express.static(dashboardDistPath, { ...sendOpts, index: false, fallthrough: true }));\n\n // SPA fallback: serve index.html for all non-API, non-WS, non-asset routes.\n // Express 5 requires named wildcards; use '{*path}' instead of '*'.\n app.get('{*path}', async (req: any, res: any) => {\n if (\n req.path.startsWith('/api') ||\n req.path === '/ws' ||\n req.path.startsWith('/assets')\n ) {\n res.status(404).json({ error: 'Not Found' });\n return;\n }\n const indexPath = resolve(dashboardDistPath, 'index.html');\n if (!(await fileExists(indexPath))) {\n res.status(503).send(\n 'Dashboard not built. Run \"npm run build:dashboard\" first.',\n );\n return;\n }\n res.sendFile(indexPath, sendOpts, (err: Error | null) => {\n if (err) {\n console.error('Error sending dashboard index.html:', err);\n if (!res.headersSent) res.status(500).send('Dashboard load error');\n }\n });\n });\n }\n\n // --- File watcher ---\n let watcherHandle: { close: () => Promise<void> } | null = null;\n\n return {\n async start(): Promise<void> {\n watcherHandle = createWatcher({\n projectsDir,\n assignmentsDir,\n serversDir,\n playbooksDir,\n todosDir,\n dbPath: resolve(syntaurRoot(), 'syntaur.db'),\n onMessage: broadcast,\n });\n\n startAutodiscovery({ serversDir, projectsDir, assignmentsDir, excludePids: new Set([process.pid]) });\n\n return new Promise<void>((resolvePromise, reject) => {\n server.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EADDRINUSE') {\n reject(new Error(\n `Port ${port} is already in use. Use --port <number> to specify a different port.`,\n ));\n } else {\n reject(err);\n }\n });\n server.listen(port, () => {\n const portFile = resolve(syntaurRoot(), 'dashboard-port');\n writeFile(portFile, String(port), 'utf-8').catch(() => {});\n resolvePromise();\n });\n });\n },\n\n async stop(): Promise<void> {\n await stopAutodiscovery();\n if (watcherHandle) {\n await watcherHandle.close();\n }\n closeSessionDb();\n closeLeasesDb();\n for (const client of clients) {\n client.terminate();\n }\n clients.clear();\n const portFile = resolve(syntaurRoot(), 'dashboard-port');\n await unlink(portFile).catch(() => {});\n server.closeAllConnections?.();\n return new Promise<void>((resolvePromise) => {\n server.close(() => resolvePromise());\n });\n },\n\n get port(): number {\n return port;\n },\n };\n}\n","import { execFileSync } from 'node:child_process';\nimport { statSync } from 'node:fs';\nimport type { AgentConfig } from '../utils/config.js';\nimport type { AgentSession, AgentSessionWithLiveness } from './types.js';\n\nconst FIVE_MINUTES_MS = 5 * 60 * 1000;\n\n/**\n * Injectable dependencies for the liveness probe so tests can supply\n * deterministic stubs instead of touching real processes / filesystem state.\n * Production callers pass nothing and get the real defaults.\n */\nexport interface LivenessDeps {\n /** Current wall-clock time. Defaults to Date.now. */\n now?: () => number;\n /** Returns the file mtime in ms, or null when the path is missing / unreadable. */\n statMtimeMs?: (path: string) => number | null;\n /** Returns true when a process with the given pid is currently running. */\n isPidAlive?: (pid: number) => boolean;\n /** Returns the stringified start time of the process, or null when unavailable. */\n pidStartedAt?: (pid: number) => string | null;\n}\n\nconst DEFAULT_DEPS: Required<LivenessDeps> = {\n now: () => Date.now(),\n statMtimeMs: (path) => {\n try {\n return statSync(path).mtimeMs;\n } catch {\n return null;\n }\n },\n isPidAlive: (pid) => {\n if (!Number.isFinite(pid) || pid <= 0) return false;\n try {\n // Signal 0 doesn't deliver — it only probes existence + permission.\n // ESRCH: no such process; EPERM: process exists but we cannot signal.\n process.kill(pid, 0);\n return true;\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === 'EPERM') return true;\n return false;\n }\n },\n pidStartedAt: (pid) => {\n if (!Number.isFinite(pid) || pid <= 0) return null;\n try {\n const out = execFileSync('ps', ['-o', 'lstart=', '-p', String(pid)], {\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n });\n const trimmed = out.trim();\n return trimmed === '' ? null : trimmed;\n } catch {\n return null;\n }\n },\n};\n\nfunction resolveDeps(deps?: LivenessDeps): Required<LivenessDeps> {\n return {\n now: deps?.now ?? DEFAULT_DEPS.now,\n statMtimeMs: deps?.statMtimeMs ?? DEFAULT_DEPS.statMtimeMs,\n isPidAlive: deps?.isPidAlive ?? DEFAULT_DEPS.isPidAlive,\n pidStartedAt: deps?.pidStartedAt ?? DEFAULT_DEPS.pidStartedAt,\n };\n}\n\n/**\n * Compute whether a session is \"live\" — i.e. there may still be a process\n * writing to its transcript. The UI disables Resume when isLive is true so\n * the user is forced to Fork instead, preventing two processes from\n * interleaving writes into the same transcript file.\n *\n * Tiered logic (matches Design Summary in assignment.md):\n * 1. status !== 'active' → false (manual override is definitive).\n * 2. pid present:\n * 2a. pid not alive → false (process is gone).\n * 2b. pid alive AND stored pid_started_at differs from current → false\n * (PID was recycled by a different process; original is gone).\n * 2c. pid alive otherwise → true.\n * 3. transcriptPath present AND recently-touched (<5 min) → true.\n * 4. Default → true (safer: disable Resume, force Fork when no signal).\n */\nexport function computeIsLive(\n session: AgentSession,\n deps?: LivenessDeps,\n): boolean {\n if (session.status !== 'active') return false;\n\n const d = resolveDeps(deps);\n\n const pid = session.pid;\n if (pid !== null && pid !== undefined) {\n if (!d.isPidAlive(pid)) return false;\n if (session.pidStartedAt) {\n const current = d.pidStartedAt(pid);\n if (current !== null && current !== session.pidStartedAt) {\n // PID exists but it's a different process now.\n return false;\n }\n }\n return true;\n }\n\n if (session.transcriptPath) {\n const mtime = d.statMtimeMs(session.transcriptPath);\n if (mtime !== null && d.now() - mtime < FIVE_MINUTES_MS) {\n return true;\n }\n }\n\n // No signal available — safer to assume live so Resume is gated off.\n return true;\n}\n\n/**\n * Enrich a session row with the server-derived flags the UI uses to render\n * Resume / Fork / Mark-stopped buttons.\n *\n * `resumeSupported` / `forkSupported` derive from the agent's `AgentConfig`\n * via the resolved agents list (typically `getAgents(config)`). When the\n * session's agent is missing from the list, both flags are false.\n */\nexport function enrichSession(\n session: AgentSession,\n agents: AgentConfig[],\n deps?: LivenessDeps,\n): AgentSessionWithLiveness {\n const agent = agents.find((a) => a.id === session.agent);\n return {\n ...session,\n isLive: computeIsLive(session, deps),\n resumeSupported: agent?.resume != null,\n forkSupported: agent?.fork != null,\n };\n}\n\nexport function enrichSessions(\n sessions: AgentSession[],\n agents: AgentConfig[],\n deps?: LivenessDeps,\n): AgentSessionWithLiveness[] {\n return sessions.map((s) => enrichSession(s, agents, deps));\n}\n","import { watch } from 'chokidar';\nimport { basename, dirname, relative, sep } from 'node:path';\nimport type { WsMessage } from './types.js';\n\nexport interface WatcherOptions {\n projectsDir: string;\n assignmentsDir?: string;\n serversDir?: string;\n playbooksDir?: string;\n todosDir?: string;\n /** Absolute path to ~/.syntaur/syntaur.db. When set, watch the parent dir\n * for changes to this file and its WAL siblings (-wal, -shm) and broadcast\n * `leases-updated`. chokidar 4 removed glob support so we must filter by\n * basename in the change handler. */\n dbPath?: string;\n onMessage: (message: WsMessage) => void;\n debounceMs?: number;\n}\n\nexport function createWatcher(options: WatcherOptions): { close: () => Promise<void> } {\n const { projectsDir, assignmentsDir, serversDir, playbooksDir, todosDir, dbPath, onMessage, debounceMs = 300 } = options;\n const pendingEvents = new Map<string, NodeJS.Timeout>();\n\n // --- Projects watcher (existing logic) ---\n const projectsWatcher = watch(projectsDir, {\n ignoreInitial: true,\n persistent: true,\n depth: 10,\n ignored: /(^|[\\/\\\\])\\../,\n });\n\n function handleProjectChange(filePath: string): void {\n const rel = relative(projectsDir, filePath);\n const parts = rel.split(sep);\n\n if (parts.length === 0) return;\n\n const projectSlug = parts[0];\n let assignmentSlug: string | undefined;\n let isProjectTodos = false;\n\n if (parts.length >= 3 && parts[1] === 'assignments') {\n assignmentSlug = parts[2];\n } else if (parts.length >= 2 && parts[1] === 'todos') {\n isProjectTodos = true;\n }\n\n const debounceKey = isProjectTodos\n ? `todos:${projectSlug}`\n : assignmentSlug\n ? `${projectSlug}/${assignmentSlug}`\n : projectSlug;\n\n const existing = pendingEvents.get(debounceKey);\n if (existing) clearTimeout(existing);\n\n // Session events are now emitted by the API write path, not the file watcher\n const messageType: WsMessage['type'] = isProjectTodos\n ? 'todos-updated'\n : assignmentSlug\n ? 'assignment-updated'\n : 'project-updated';\n\n pendingEvents.set(\n debounceKey,\n setTimeout(() => {\n pendingEvents.delete(debounceKey);\n const message: WsMessage = isProjectTodos\n ? {\n type: 'todos-updated',\n projectSlug,\n timestamp: new Date().toISOString(),\n }\n : {\n type: messageType,\n projectSlug,\n assignmentSlug,\n timestamp: new Date().toISOString(),\n };\n onMessage(message);\n }, debounceMs),\n );\n }\n\n projectsWatcher.on('change', handleProjectChange);\n projectsWatcher.on('add', handleProjectChange);\n projectsWatcher.on('unlink', handleProjectChange);\n\n // --- Standalone assignments watcher ---\n let standaloneWatcher: ReturnType<typeof watch> | null = null;\n\n if (assignmentsDir) {\n standaloneWatcher = watch(assignmentsDir, {\n ignoreInitial: true,\n persistent: true,\n depth: 5,\n ignored: /(^|[\\/\\\\])\\../,\n });\n\n function handleStandaloneChange(filePath: string): void {\n const rel = relative(assignmentsDir!, filePath);\n const parts = rel.split(sep);\n if (parts.length === 0) return;\n const assignmentId = parts[0];\n if (!assignmentId) return;\n\n const debounceKey = `__standalone__/${assignmentId}`;\n const existing = pendingEvents.get(debounceKey);\n if (existing) clearTimeout(existing);\n\n pendingEvents.set(\n debounceKey,\n setTimeout(() => {\n pendingEvents.delete(debounceKey);\n const message: WsMessage = {\n type: 'assignment-updated',\n projectSlug: null,\n assignmentSlug: assignmentId,\n timestamp: new Date().toISOString(),\n };\n onMessage(message);\n }, debounceMs),\n );\n }\n\n standaloneWatcher.on('change', handleStandaloneChange);\n standaloneWatcher.on('add', handleStandaloneChange);\n standaloneWatcher.on('unlink', handleStandaloneChange);\n }\n\n // --- Servers watcher (new) ---\n let serversWatcher: ReturnType<typeof watch> | null = null;\n\n if (serversDir) {\n serversWatcher = watch(serversDir, {\n ignoreInitial: true,\n persistent: true,\n depth: 1,\n ignored: /(^|[\\/\\\\])\\../,\n });\n\n function handleServerChange(): void {\n const debounceKey = '__servers__';\n const existing = pendingEvents.get(debounceKey);\n if (existing) clearTimeout(existing);\n\n pendingEvents.set(\n debounceKey,\n setTimeout(() => {\n pendingEvents.delete(debounceKey);\n const message: WsMessage = {\n type: 'servers-updated',\n timestamp: new Date().toISOString(),\n };\n onMessage(message);\n }, debounceMs),\n );\n }\n\n serversWatcher.on('change', handleServerChange);\n serversWatcher.on('add', handleServerChange);\n serversWatcher.on('unlink', handleServerChange);\n }\n\n // --- Playbooks watcher ---\n let playbooksWatcher: ReturnType<typeof watch> | null = null;\n\n if (playbooksDir) {\n playbooksWatcher = watch(playbooksDir, {\n ignoreInitial: true,\n persistent: true,\n depth: 1,\n ignored: /(^|[\\/\\\\])\\../,\n });\n\n function handlePlaybookChange(): void {\n const debounceKey = '__playbooks__';\n const existing = pendingEvents.get(debounceKey);\n if (existing) clearTimeout(existing);\n\n pendingEvents.set(\n debounceKey,\n setTimeout(() => {\n pendingEvents.delete(debounceKey);\n const message: WsMessage = {\n type: 'playbooks-updated',\n timestamp: new Date().toISOString(),\n };\n onMessage(message);\n }, debounceMs),\n );\n }\n\n playbooksWatcher.on('change', handlePlaybookChange);\n playbooksWatcher.on('add', handlePlaybookChange);\n playbooksWatcher.on('unlink', handlePlaybookChange);\n }\n\n // --- Todos watcher ---\n let todosWatcher: ReturnType<typeof watch> | null = null;\n\n if (todosDir) {\n todosWatcher = watch(todosDir, {\n ignoreInitial: true,\n persistent: true,\n depth: 1,\n ignored: /(^|[\\/\\\\])\\../,\n });\n\n function handleTodoChange(): void {\n const debounceKey = '__todos__';\n const existing = pendingEvents.get(debounceKey);\n if (existing) clearTimeout(existing);\n\n pendingEvents.set(\n debounceKey,\n setTimeout(() => {\n pendingEvents.delete(debounceKey);\n const message: WsMessage = {\n type: 'todos-updated',\n timestamp: new Date().toISOString(),\n };\n onMessage(message);\n }, debounceMs),\n );\n }\n\n todosWatcher.on('change', handleTodoChange);\n todosWatcher.on('add', handleTodoChange);\n todosWatcher.on('unlink', handleTodoChange);\n }\n\n // --- Leases DB watcher ---\n // SQLite WAL-mode writes mostly go to `<db>-wal`, not the main file. Watch\n // the parent directory and filter by basename to catch the main DB and its\n // -wal / -shm siblings. chokidar 4 has no glob support, so a literal pattern\n // like `${dbPath}*` would be silently a no-op.\n let leasesDbWatcher: ReturnType<typeof watch> | null = null;\n\n if (dbPath) {\n const dbDir = dirname(dbPath);\n const dbBase = basename(dbPath);\n\n leasesDbWatcher = watch(dbDir, {\n ignoreInitial: true,\n persistent: true,\n depth: 0,\n ignored: /(^|[\\/\\\\])\\../,\n });\n\n function handleDbChange(filePath: string): void {\n if (!basename(filePath).startsWith(dbBase)) return;\n const debounceKey = '__leases-db__';\n const existing = pendingEvents.get(debounceKey);\n if (existing) clearTimeout(existing);\n\n pendingEvents.set(\n debounceKey,\n setTimeout(() => {\n pendingEvents.delete(debounceKey);\n const message: WsMessage = {\n type: 'leases-updated',\n timestamp: new Date().toISOString(),\n };\n onMessage(message);\n }, debounceMs),\n );\n }\n\n leasesDbWatcher.on('change', handleDbChange);\n leasesDbWatcher.on('add', handleDbChange);\n leasesDbWatcher.on('unlink', handleDbChange);\n }\n\n return {\n close: async () => {\n pendingEvents.forEach((timeout) => {\n clearTimeout(timeout);\n });\n pendingEvents.clear();\n await projectsWatcher.close();\n if (standaloneWatcher) await standaloneWatcher.close();\n if (serversWatcher) await serversWatcher.close();\n if (playbooksWatcher) await playbooksWatcher.close();\n if (todosWatcher) await todosWatcher.close();\n if (leasesDbWatcher) await leasesDbWatcher.close();\n },\n };\n}\n","export type ViewMode = 'kanban' | 'list' | 'table';\n\nexport const VIEW_MODES: readonly ViewMode[] = ['kanban', 'list', 'table'];\n\nexport type SortField =\n | 'title'\n | 'status'\n | 'priority'\n | 'assignee'\n | 'dependencies'\n | 'updated';\n\nexport const SORT_FIELDS: readonly SortField[] = [\n 'title',\n 'status',\n 'priority',\n 'assignee',\n 'dependencies',\n 'updated',\n];\n\nexport type SortDirection = 'asc' | 'desc';\nexport const SORT_DIRECTIONS: readonly SortDirection[] = ['asc', 'desc'];\n\nexport type Density = 'comfortable' | 'compact';\nexport const DENSITIES: readonly Density[] = ['comfortable', 'compact'];\n\nexport type Grouping = 'none' | 'status' | 'priority' | 'assignee' | 'project';\nexport const GROUPINGS: readonly Grouping[] = [\n 'none',\n 'status',\n 'priority',\n 'assignee',\n 'project',\n];\n\nexport type Activity = 'all' | 'stale' | 'fresh';\nexport const ACTIVITIES: readonly Activity[] = ['all', 'stale', 'fresh'];\n\n// Filter values are user-data-driven strings (status ids, priority names,\n// assignee names, project slugs) plus 'all'. The codebase also uses the\n// sentinels '__unassigned__' and '__standalone__' for assignee/project,\n// so validation is allow-by-shape (non-empty string), not allow-by-value.\nexport interface ViewFilters {\n status?: string;\n priority?: string;\n assignee?: string;\n project?: string;\n activity?: Activity;\n}\n\nexport interface ViewPrefs {\n defaultView: ViewMode;\n sortField: SortField;\n sortDirection: SortDirection;\n density: Density;\n grouping: Grouping;\n filters: ViewFilters;\n}\n\n// Per-scope overrides cannot set density (global only by product decision).\nexport type ProjectViewPrefs = Partial<Omit<ViewPrefs, 'density'>>;\n\nexport interface ViewPrefsFile {\n version: 1;\n global: ViewPrefs;\n projects: Record<string, ProjectViewPrefs>;\n}\n\nexport const DEFAULT_VIEW_PREFS: ViewPrefs = {\n defaultView: 'kanban',\n sortField: 'updated',\n sortDirection: 'desc',\n density: 'comfortable',\n grouping: 'none',\n filters: {\n status: 'all',\n priority: 'all',\n assignee: 'all',\n project: 'all',\n activity: 'all',\n },\n};\n\nexport const DEFAULT_VIEW_PREFS_FILE: ViewPrefsFile = {\n version: 1,\n global: DEFAULT_VIEW_PREFS,\n projects: {},\n};\n\nexport function isViewMode(v: unknown): v is ViewMode {\n return typeof v === 'string' && (VIEW_MODES as readonly string[]).includes(v);\n}\n\nexport function isSortField(v: unknown): v is SortField {\n return typeof v === 'string' && (SORT_FIELDS as readonly string[]).includes(v);\n}\n\nexport function isSortDirection(v: unknown): v is SortDirection {\n return typeof v === 'string' && (SORT_DIRECTIONS as readonly string[]).includes(v);\n}\n\nexport function isDensity(v: unknown): v is Density {\n return typeof v === 'string' && (DENSITIES as readonly string[]).includes(v);\n}\n\nexport function isGrouping(v: unknown): v is Grouping {\n return typeof v === 'string' && (GROUPINGS as readonly string[]).includes(v);\n}\n\nexport function isActivity(v: unknown): v is Activity {\n return typeof v === 'string' && (ACTIVITIES as readonly string[]).includes(v);\n}\n\nexport function isFilterString(v: unknown): v is string {\n return typeof v === 'string' && v.length > 0;\n}\n\n// ProjectDetail only supports kanban/table; map 'list' onto 'kanban'.\nexport function coerceProjectDetailView(v: ViewMode): 'kanban' | 'table' {\n return v === 'table' ? 'table' : 'kanban';\n}\n\nfunction mergeFilters(base: ViewFilters, patch: ViewFilters | undefined): ViewFilters {\n if (!patch) return { ...base };\n return { ...base, ...patch };\n}\n\nfunction mergePrefs(base: ViewPrefs, patch: Partial<ViewPrefs> | undefined): ViewPrefs {\n if (!patch) return base;\n return {\n ...base,\n ...patch,\n filters: mergeFilters(base.filters, patch.filters),\n };\n}\n\nfunction mergeProjectOverride(\n base: ProjectViewPrefs,\n patch: ProjectViewPrefs | undefined,\n): ProjectViewPrefs {\n if (!patch) return { ...base };\n return {\n ...base,\n ...patch,\n filters: patch.filters || base.filters\n ? mergeFilters(base.filters ?? {}, patch.filters)\n : undefined,\n };\n}\n\n// Returns the effective ViewPrefs for a scope. `scope === null` returns global.\n// Density always comes from global (per the type constraint).\nexport function mergeForScope(file: ViewPrefsFile, scope: string | null): ViewPrefs {\n const global = file.global;\n if (scope === null) return global;\n const override = file.projects[scope];\n if (!override) return global;\n return {\n defaultView: override.defaultView ?? global.defaultView,\n sortField: override.sortField ?? global.sortField,\n sortDirection: override.sortDirection ?? global.sortDirection,\n density: global.density,\n grouping: override.grouping ?? global.grouping,\n filters: mergeFilters(global.filters, override.filters),\n };\n}\n\n// Canonical patch shape sent to POST /api/view-prefs.\nexport interface ViewPrefsPatch {\n global?: Partial<ViewPrefs>;\n projects?: Record<string, ProjectViewPrefs>;\n}\n\n// Deep-merges a patch into the current file. Does NOT validate; the route\n// handler is expected to validate the result before persisting.\nexport function mergePatch(current: ViewPrefsFile, patch: ViewPrefsPatch): ViewPrefsFile {\n const nextProjects: Record<string, ProjectViewPrefs> = { ...current.projects };\n if (patch.projects) {\n for (const [scope, scopePatch] of Object.entries(patch.projects)) {\n const prev = nextProjects[scope] ?? {};\n nextProjects[scope] = mergeProjectOverride(prev, scopePatch);\n }\n }\n return {\n version: 1,\n global: mergePrefs(current.global, patch.global),\n projects: nextProjects,\n };\n}\n","import { readFile, rename, unlink } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { syntaurRoot, viewPrefsFile } from './paths.js';\nimport { fileExists, writeFileForce } from './fs.js';\nimport {\n DEFAULT_VIEW_PREFS_FILE,\n type ViewPrefsFile,\n type ViewPrefsPatch,\n mergePatch,\n} from './view-prefs-schema.js';\n\n// Re-exports so consumers only need to import from this module.\nexport type { ViewPrefsFile, ViewPrefsPatch };\nexport { mergePatch } from './view-prefs-schema.js';\nexport { mergeForScope } from './view-prefs-schema.js';\n\nfunction corruptFilePath(): string {\n const ts = new Date().toISOString().replace(/[:.]/g, '-');\n return resolve(syntaurRoot(), `view-prefs.corrupt-${ts}.json`);\n}\n\nfunction isViewPrefsFileShape(value: unknown): value is ViewPrefsFile {\n if (!value || typeof value !== 'object') return false;\n const obj = value as Record<string, unknown>;\n // Treat missing `version` as v1 (forward-compat with previously-written files).\n // An explicit non-1 version is handled separately upstream.\n if (obj.version !== undefined && obj.version !== 1) return false;\n if (!obj.global || typeof obj.global !== 'object') return false;\n if (!obj.projects || typeof obj.projects !== 'object' || Array.isArray(obj.projects)) {\n return false;\n }\n return true;\n}\n\n// Returns the parsed file when readable + valid.\n// Returns defaults on missing, parse error, or shape mismatch.\n// On corruption (present but unparseable / bad shape), renames the bad file\n// to view-prefs.corrupt-<ISO>.json BEFORE returning defaults so the next save\n// does not overwrite the evidence. Unknown future versions return defaults\n// WITHOUT renaming (forward-compat).\nexport async function readViewPrefsFile(): Promise<ViewPrefsFile> {\n const path = viewPrefsFile();\n if (!(await fileExists(path))) {\n return { ...DEFAULT_VIEW_PREFS_FILE };\n }\n let raw: string;\n try {\n raw = await readFile(path, 'utf-8');\n } catch {\n return { ...DEFAULT_VIEW_PREFS_FILE };\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n await backupCorrupt(path);\n return { ...DEFAULT_VIEW_PREFS_FILE };\n }\n if (parsed && typeof parsed === 'object' && (parsed as Record<string, unknown>).version !== undefined) {\n const v = (parsed as Record<string, unknown>).version;\n if (typeof v === 'number' && v > 1) {\n console.warn(\n `[view-prefs] Unknown version ${v} at ${path}; returning defaults (file left intact).`,\n );\n return { ...DEFAULT_VIEW_PREFS_FILE };\n }\n }\n if (!isViewPrefsFileShape(parsed)) {\n await backupCorrupt(path);\n return { ...DEFAULT_VIEW_PREFS_FILE };\n }\n // Normalize version (missing -> 1).\n return { ...parsed, version: 1 };\n}\n\nasync function backupCorrupt(path: string): Promise<void> {\n const backup = corruptFilePath();\n try {\n await rename(path, backup);\n console.warn(`[view-prefs] Corrupt file moved to ${backup}; using defaults.`);\n } catch (err) {\n console.warn(`[view-prefs] Failed to back up corrupt file ${path}: ${String(err)}`);\n }\n}\n\nexport async function writeViewPrefsFile(file: ViewPrefsFile): Promise<void> {\n await writeFileForce(viewPrefsFile(), `${JSON.stringify(file, null, 2)}\\n`);\n}\n\nexport async function resetViewPrefsFile(): Promise<void> {\n const path = viewPrefsFile();\n if (await fileExists(path)) {\n await unlink(path);\n }\n}\n\n// Convenience for routes: read → mergePatch → write.\nexport async function applyViewPrefsPatch(patch: ViewPrefsPatch): Promise<ViewPrefsFile> {\n const current = await readViewPrefsFile();\n const next = mergePatch(current, patch);\n await writeViewPrefsFile(next);\n return next;\n}\n\nexport function isViewPrefsDefaults(file: ViewPrefsFile): boolean {\n if (Object.keys(file.projects).length > 0) return false;\n const g = file.global;\n const d = DEFAULT_VIEW_PREFS_FILE.global;\n if (g.defaultView !== d.defaultView) return false;\n if (g.sortField !== d.sortField) return false;\n if (g.sortDirection !== d.sortDirection) return false;\n if (g.density !== d.density) return false;\n if (g.grouping !== d.grouping) return false;\n const gf = g.filters;\n const df = d.filters;\n if (gf.status !== df.status) return false;\n if (gf.priority !== df.priority) return false;\n if (gf.assignee !== df.assignee) return false;\n if (gf.project !== df.project) return false;\n if (gf.activity !== df.activity) return false;\n return true;\n}\n","// Shared write-lock map for the todo routers. Both the workspace router\n// (api-todos.ts) and the project router (api-project-todos.ts) acquire from\n// this same Map so cross-scope move can hold both source and target locks\n// in lexical order of the prefixed key without risk of deadlock.\n//\n// Lock-key prefixes:\n// ws:<workspace> — workspace-scoped checklist (the singleton global\n// checklist is reached as ws:_global; see globalLockKey)\n// proj:<slug> — project-scoped checklist\nconst writeLocks = new Map<string, Promise<void>>();\n\nexport function withLock<T>(lockKey: string, fn: () => Promise<T>): Promise<T> {\n const prev = writeLocks.get(lockKey) ?? Promise.resolve();\n const next = prev.then(fn);\n writeLocks.set(\n lockKey,\n next.then(\n () => {},\n () => {},\n ),\n );\n return next;\n}\n\nexport function wsLock<T>(workspace: string, fn: () => Promise<T>): Promise<T> {\n return withLock(`ws:${workspace}`, fn);\n}\n\nexport function projLock<T>(slug: string, fn: () => Promise<T>): Promise<T> {\n return withLock(`proj:${slug}`, fn);\n}\n\n// The global checklist is just a workspace named \"_global\" by convention;\n// this helper exists to make that mapping explicit at call sites that\n// distinguish global from named-workspace scopes.\nexport function globalLockKey(): string {\n return 'ws:_global';\n}\n\n// Acquire two locks in lexical order to prevent deadlock when one request\n// needs to mutate two scopes (e.g. cross-scope todo move).\nexport function withTwoLocks<T>(\n keyA: string,\n keyB: string,\n fn: () => Promise<T>,\n): Promise<T> {\n if (keyA === keyB) return withLock(keyA, fn);\n const [first, second] = keyA < keyB ? [keyA, keyB] : [keyB, keyA];\n return withLock(first, () => withLock(second, fn));\n}\n","import { Router, type Request, type Response } from 'express';\nimport { resolve, basename, isAbsolute } from 'node:path';\nimport { rm, readFile, open as fsOpen, stat as fsStat, realpath as fsRealpath } from 'node:fs/promises';\nimport { spawnSync } from 'node:child_process';\nimport { executeTransition } from '../lifecycle/index.js';\nimport { isValidSlug, slugify } from '../utils/slug.js';\nimport { generateId } from '../utils/uuid.js';\nimport { nowTimestamp } from '../utils/timestamp.js';\nimport { ensureDir, writeFileForce, fileExists } from '../utils/fs.js';\nimport {\n createWorktreeAndRecord,\n GitWorktreeError,\n} from '../utils/git-worktree.js';\nimport { computeWorktreeDefaults } from '../utils/worktree-defaults.js';\nimport {\n getProjectRepositoryCandidates,\n getStandaloneRepositoryCandidates,\n} from './repository-candidates.js';\nimport {\n parseAssignmentFull,\n parseDecisionRecord,\n parseHandoff,\n parseMemory,\n parseProject,\n parsePlan,\n parseResource,\n parseScratchpad,\n} from './parser.js';\nimport { toggleAcceptanceCriterion } from './acceptance-criteria.js';\nimport {\n getAssignmentDetail,\n getAssignmentDetailById,\n getEditableDocument,\n getEditableDocumentById,\n getMemoryDetail,\n getProjectDetail,\n getResourceDetail,\n getStatusConfig,\n resolveProjectPath,\n} from './api.js';\nimport { resolveAssignmentById } from '../utils/assignment-resolver.js';\nimport { renderProgress } from '../templates/index.js';\nimport { executeTransitionByDir } from '../lifecycle/index.js';\nimport {\n renderProject,\n renderManifest,\n renderIndexAssignments,\n renderIndexPlans,\n renderIndexDecisions,\n renderStatus,\n renderResourcesIndex,\n renderMemoriesIndex,\n renderMemoryStub,\n renderResourceStub,\n renderAssignment,\n renderScratchpad,\n renderHandoff,\n renderDecisionRecord,\n renderComments,\n formatCommentEntry,\n type Comment,\n type CommentType,\n} from '../templates/index.js';\nimport { parseComments } from './parser.js';\n\nfunction extractFrontmatter(content: string): Record<string, string> | null {\n const trimmed = content.trimStart();\n if (!trimmed.startsWith('---\\n') && !trimmed.startsWith('---\\r\\n')) {\n return null;\n }\n\n const afterFirst = trimmed.indexOf('\\n') + 1;\n const closingIdx = trimmed.indexOf('\\n---', afterFirst);\n if (closingIdx === -1) {\n return null;\n }\n\n const yamlBlock = trimmed.slice(afterFirst, closingIdx);\n const fields: Record<string, string> = {};\n\n for (const line of yamlBlock.split('\\n')) {\n const match = line.match(/^([a-zA-Z_][a-zA-Z0-9_]*):\\s*(.*)$/);\n if (!match) {\n continue;\n }\n\n let value = match[2].trim();\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n fields[match[1]] = value;\n }\n\n return fields;\n}\n\nfunction validateRequired(\n fields: Record<string, string>,\n required: string[],\n): { valid: true } | { valid: false; missing: string[] } {\n const missing = required.filter((key) => !fields[key] || fields[key] === 'null');\n if (missing.length > 0) {\n return { valid: false, missing };\n }\n return { valid: true };\n}\n\nfunction formatYamlValue(value: boolean | number | string | null): string {\n if (value === null) {\n return 'null';\n }\n if (typeof value === 'boolean' || typeof value === 'number') {\n return String(value);\n }\n if (/^\\d{4}-\\d{2}-\\d{2}T/.test(value)) {\n return `\"${value}\"`;\n }\n if (value === '' || /[:#{}[\\],&*?|>!%@`]/.test(value) || /^\\s|\\s$/.test(value)) {\n return `\"${value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')}\"`;\n }\n return value;\n}\n\nfunction setTopLevelField(\n content: string,\n key: string,\n value: boolean | number | string | null,\n): string {\n const formatted = formatYamlValue(value);\n const fieldRegex = new RegExp(`^(${escapeRegExp(key)}:)\\\\s*.*$`, 'm');\n\n if (fieldRegex.test(content)) {\n return content.replace(fieldRegex, `$1 ${formatted}`);\n }\n\n const closingIdx = content.indexOf('\\n---', 4);\n if (closingIdx === -1) {\n return content;\n }\n\n return `${content.slice(0, closingIdx)}\\n${key}: ${formatted}${content.slice(closingIdx)}`;\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nfunction appendLogEntry(\n existingContent: string,\n countField: 'handoffCount' | 'decisionCount',\n nextCount: number,\n heading: string,\n body: string,\n emptyPlaceholder: string,\n): string {\n const timestamp = nowTimestamp();\n let next = setTopLevelField(existingContent, 'updated', timestamp);\n next = setTopLevelField(next, countField, nextCount);\n\n const entryBody = body.trim();\n const entry = `## ${heading}\\n\\n**Recorded:** ${timestamp}\\n\\n${entryBody}\\n`;\n\n if (next.includes(emptyPlaceholder)) {\n return next.replace(emptyPlaceholder, entry.trimEnd());\n }\n\n return `${next.trimEnd()}\\n\\n${entry}`;\n}\n\nfunction requireContent(req: Request, res: Response): string | null {\n const { content } = req.body || {};\n if (!content || typeof content !== 'string' || !content.trim()) {\n res.status(400).json({ error: 'content is required' });\n return null;\n }\n return content;\n}\n\nfunction getParam(value: string | string[] | undefined): string {\n if (Array.isArray(value)) {\n return value[0] ?? '';\n }\n return value ?? '';\n}\n\nasync function readCurrentDocument(filePath: string): Promise<string | null> {\n if (!(await fileExists(filePath))) {\n return null;\n }\n return readFile(filePath, 'utf-8');\n}\n\ninterface WorktreeCreateContext {\n assignmentPath: string;\n projectSlug: string;\n assignmentSlug: string;\n reload: () => Promise<unknown>;\n}\n\n/**\n * Shared body for both worktree-create routes. Validates inputs, runs the\n * disk-collision and parent-branch pre-flights, then calls the same\n * `createWorktreeAndRecord` helper the CLI / browse TUI use. Returns\n * `{ assignment }` shaped via `reload` on success.\n */\nasync function handleWorktreeCreate(\n req: Request,\n res: Response,\n ctx: WorktreeCreateContext,\n): Promise<void> {\n if (!(await fileExists(ctx.assignmentPath))) {\n res.status(404).json({ error: 'Assignment not found' });\n return;\n }\n\n const parsed = parseAssignmentFull(await readFile(ctx.assignmentPath, 'utf-8'));\n if (parsed.workspace.worktreePath) {\n res\n .status(409)\n .json({ error: 'Worktree already configured for this assignment' });\n return;\n }\n\n const { repository, branch: bodyBranch, parentBranch: bodyParent } = (req.body ?? {}) as {\n repository?: unknown;\n branch?: unknown;\n parentBranch?: unknown;\n };\n\n if (typeof repository !== 'string' || !repository.trim()) {\n res.status(400).json({ error: '`repository` is required.' });\n return;\n }\n if (!isAbsolute(repository)) {\n res\n .status(400)\n .json({ error: '`repository` must be an absolute path.' });\n return;\n }\n try {\n const st = await fsStat(repository);\n if (!st.isDirectory()) {\n res\n .status(400)\n .json({ error: `Repository path is not a directory: ${repository}` });\n return;\n }\n } catch {\n res\n .status(400)\n .json({ error: `Repository path does not exist: ${repository}` });\n return;\n }\n const topLevel = spawnSync('git', ['-C', repository, 'rev-parse', '--show-toplevel'], {\n encoding: 'utf-8',\n });\n const topLevelOut = topLevel.stdout.trim();\n if (topLevel.status !== 0 || !topLevelOut) {\n res\n .status(400)\n .json({ error: `Repository path is not a git working tree: ${repository}` });\n return;\n }\n // The plan requires the request `repository` to be the repo root, not a\n // subdirectory. `git -C <subdir> rev-parse --show-toplevel` succeeds for\n // any path inside a working tree, so we have to compare paths. Use\n // `realpath` so symlinks (e.g. macOS `/var` → `/private/var`) don't\n // produce spurious mismatches.\n const [requestReal, topLevelReal] = await Promise.all([\n fsRealpath(repository),\n fsRealpath(topLevelOut),\n ]);\n if (requestReal !== topLevelReal) {\n res.status(400).json({\n error:\n `Repository path must be the git working-tree root. Got ${repository}; the enclosing repo root is ${topLevelOut}.`,\n });\n return;\n }\n\n const defaults = computeWorktreeDefaults({\n projectSlug: ctx.projectSlug,\n assignmentSlug: ctx.assignmentSlug,\n existing: parsed.workspace,\n cwd: repository,\n });\n const branch =\n typeof bodyBranch === 'string' && bodyBranch.trim() ? bodyBranch.trim() : defaults.branch!;\n const parentBranch =\n typeof bodyParent === 'string' && bodyParent.trim() ? bodyParent.trim() : defaults.parentBranch!;\n const worktreePath = resolve(repository, '.worktrees', branch);\n\n try {\n await fsStat(worktreePath);\n res.status(409).json({\n error: `A file or directory already exists at ${worktreePath}. Remove it or choose a different branch.`,\n });\n return;\n } catch {\n // ENOENT — good.\n }\n\n const parentCheck = spawnSync(\n 'git',\n ['-C', repository, 'rev-parse', '--verify', '--quiet', parentBranch],\n { encoding: 'utf-8' },\n );\n if (parentCheck.status !== 0) {\n res.status(400).json({\n error: `Parent branch \"${parentBranch}\" does not exist in ${repository}.`,\n });\n return;\n }\n\n try {\n await createWorktreeAndRecord({\n assignmentPath: ctx.assignmentPath,\n repository,\n branch,\n worktreePath,\n parentBranch,\n });\n } catch (error) {\n if (error instanceof GitWorktreeError) {\n res.status(400).json({ error: error.message, stderr: error.stderr });\n return;\n }\n res.status(500).json({ error: (error as Error).message });\n return;\n }\n\n const assignment = await ctx.reload();\n res.json({ assignment });\n}\n\nexport function createWriteRouter(\n projectsDir: string,\n assignmentsDir?: string,\n todosDir?: string,\n): Router {\n const linkedTodosLookup = todosDir ? { todosDir, projectsDir } : undefined;\n const router = Router();\n\n router.get('/api/templates/project', (_req: Request, res: Response) => {\n const content = renderProject({\n id: generateId(),\n slug: 'my-new-project',\n title: 'My New Project',\n timestamp: nowTimestamp(),\n });\n res.json({ content });\n });\n\n router.get('/api/templates/assignment', (req: Request, res: Response) => {\n const standalone = req.query.standalone === '1';\n const workspaceParam = typeof req.query.workspace === 'string' ? req.query.workspace : '';\n if (workspaceParam && !isValidSlug(workspaceParam)) {\n res.status(400).json({\n error: `Invalid workspace slug \"${workspaceParam}\". Slugs must be lowercase, hyphen-separated, with no special characters.`,\n });\n return;\n }\n const content = renderAssignment({\n id: generateId(),\n slug: 'my-new-assignment',\n title: 'My New Assignment',\n timestamp: nowTimestamp(),\n priority: 'medium',\n dependsOn: [],\n links: [],\n project: standalone ? null : undefined,\n workspaceGroup: standalone && workspaceParam ? workspaceParam : null,\n });\n res.json({ content });\n });\n\n router.get('/api/projects/:slug/edit', async (req: Request, res: Response) => {\n const slug = getParam(req.params.slug);\n const document = await getEditableDocument(projectsDir, 'project', slug);\n if (!document) {\n res.status(404).json({ error: `Project \"${slug}\" not found` });\n return;\n }\n res.json(document);\n });\n\n router.get('/api/projects/:slug/assignments/:aslug/edit', async (req: Request, res: Response) => {\n const slug = getParam(req.params.slug);\n const assignmentSlug = getParam(req.params.aslug);\n const document = await getEditableDocument(\n projectsDir,\n 'assignment',\n slug,\n assignmentSlug,\n );\n if (!document) {\n res.status(404).json({ error: 'Assignment not found' });\n return;\n }\n res.json(document);\n });\n\n router.get('/api/projects/:slug/assignments/:aslug/plan/edit', async (req: Request, res: Response) => {\n const slug = getParam(req.params.slug);\n const assignmentSlug = getParam(req.params.aslug);\n const document = await getEditableDocument(\n projectsDir,\n 'plan',\n slug,\n assignmentSlug,\n );\n if (!document) {\n res.status(404).json({ error: 'Plan not found' });\n return;\n }\n res.json(document);\n });\n\n router.get('/api/projects/:slug/assignments/:aslug/scratchpad/edit', async (req: Request, res: Response) => {\n const slug = getParam(req.params.slug);\n const assignmentSlug = getParam(req.params.aslug);\n const document = await getEditableDocument(\n projectsDir,\n 'scratchpad',\n slug,\n assignmentSlug,\n );\n if (!document) {\n res.status(404).json({ error: 'Scratchpad not found' });\n return;\n }\n res.json(document);\n });\n\n router.get('/api/projects/:slug/assignments/:aslug/handoff/edit', async (req: Request, res: Response) => {\n const slug = getParam(req.params.slug);\n const assignmentSlug = getParam(req.params.aslug);\n const document = await getEditableDocument(\n projectsDir,\n 'handoff',\n slug,\n assignmentSlug,\n );\n if (!document) {\n res.status(404).json({ error: 'Handoff log not found' });\n return;\n }\n res.json(document);\n });\n\n router.get('/api/projects/:slug/assignments/:aslug/decision-record/edit', async (req: Request, res: Response) => {\n const slug = getParam(req.params.slug);\n const assignmentSlug = getParam(req.params.aslug);\n const document = await getEditableDocument(\n projectsDir,\n 'decision-record',\n slug,\n assignmentSlug,\n );\n if (!document) {\n res.status(404).json({ error: 'Decision record not found' });\n return;\n }\n res.json(document);\n });\n\n router.get('/api/projects/:slug/memories/:itemSlug/edit', async (req: Request, res: Response) => {\n const slug = getParam(req.params.slug);\n const itemSlug = getParam(req.params.itemSlug);\n if (!isValidSlug(itemSlug)) {\n res.status(400).json({ error: 'Invalid memory slug.' });\n return;\n }\n const projectDir = await resolveProjectPath(projectsDir, slug);\n if (!projectDir) {\n res.status(404).json({ error: `Project \"${slug}\" not found` });\n return;\n }\n const document = await getEditableDocument(projectsDir, 'memory', basename(projectDir), itemSlug);\n if (!document) {\n res.status(404).json({ error: 'Memory not found' });\n return;\n }\n res.json(document);\n });\n\n router.get('/api/projects/:slug/resources/:itemSlug/edit', async (req: Request, res: Response) => {\n const slug = getParam(req.params.slug);\n const itemSlug = getParam(req.params.itemSlug);\n if (!isValidSlug(itemSlug)) {\n res.status(400).json({ error: 'Invalid resource slug.' });\n return;\n }\n const projectDir = await resolveProjectPath(projectsDir, slug);\n if (!projectDir) {\n res.status(404).json({ error: `Project \"${slug}\" not found` });\n return;\n }\n const document = await getEditableDocument(projectsDir, 'resource', basename(projectDir), itemSlug);\n if (!document) {\n res.status(404).json({ error: 'Resource not found' });\n return;\n }\n res.json(document);\n });\n\n // ----- Memory / Resource CRUD ----------------------------------------------\n // The two types share an identical contract; `kind` parameterizes the folder\n // and stub renderer.\n\n type ItemKind = 'memory' | 'resource';\n\n function itemFolder(kind: ItemKind): 'memories' | 'resources' {\n return kind === 'memory' ? 'memories' : 'resources';\n }\n\n function renderItemStub(\n kind: ItemKind,\n params: { slug: string; name: string; projectSlug: string; timestamp: string },\n ): string {\n return kind === 'memory' ? renderMemoryStub(params) : renderResourceStub(params);\n }\n\n /** Replace the body of a stub (everything after the closing frontmatter) with a custom body. */\n function replaceStubBody(stub: string, body: string): string {\n const match = stub.match(/^(---\\r?\\n[\\s\\S]*?\\r?\\n---\\r?\\n)/);\n if (!match) return stub; // shouldn't happen — stub always has frontmatter\n return `${match[1]}\\n${body.startsWith('\\n') ? body.slice(1) : body}${body.endsWith('\\n') ? '' : '\\n'}`;\n }\n\n /** Extract the verbatim frontmatter block (including the surrounding `---` lines). */\n function extractFrontmatterBlock(content: string): string | null {\n const match = content.match(/^(---\\r?\\n[\\s\\S]*?\\r?\\n---\\r?\\n)/);\n return match ? match[1] : null;\n }\n\n function parseItem(kind: ItemKind, content: string) {\n return kind === 'memory' ? parseMemory(content) : parseResource(content);\n }\n\n async function getItemDetail(kind: ItemKind, projectSlug: string, itemSlug: string) {\n return kind === 'memory'\n ? await getMemoryDetail(projectsDir, projectSlug, itemSlug)\n : await getResourceDetail(projectsDir, projectSlug, itemSlug);\n }\n\n /**\n * Resolve the on-disk project directory for a slug.\n * Tries the directory-name match first (the typical case); falls back to scanning every\n * project for a frontmatter-slug match (covers fixtures/legacy projects whose folder name\n * differs from `project.md` `slug`).\n */\n async function resolveProjectDir(projectSlug: string): Promise<string | null> {\n return resolveProjectPath(projectsDir, projectSlug);\n }\n\n /** 400 if the slug param wouldn't pass `isValidSlug`. Returns true if the response was sent. */\n function rejectBadItemSlug(itemSlug: string, kind: ItemKind, res: Response): boolean {\n if (isValidSlug(itemSlug)) return false;\n res.status(400).json({\n error: `Invalid ${kind} slug \"${itemSlug}\". Slugs must be lowercase letters, numbers, and hyphens only.`,\n });\n return true;\n }\n\n // GET detail\n for (const kind of ['memory', 'resource'] as const) {\n const folder = itemFolder(kind);\n\n router.get(`/api/projects/:slug/${folder}/:itemSlug`, async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const itemSlug = getParam(req.params.itemSlug);\n if (rejectBadItemSlug(itemSlug, kind, res)) return;\n const detail = await getItemDetail(kind, projectSlug, itemSlug);\n if (!detail) {\n res.status(404).json({ error: `${kind === 'memory' ? 'Memory' : 'Resource'} not found` });\n return;\n }\n res.json(detail);\n } catch (error) {\n console.error(`Error fetching ${kind} detail:`, error);\n res.status(500).json({ error: `Failed to load ${kind}: ${(error as Error).message}` });\n }\n });\n\n // POST — create\n router.post(`/api/projects/:slug/${folder}`, async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const projectDir = await resolveProjectDir(projectSlug);\n if (!projectDir) {\n res.status(404).json({ error: `Project \"${projectSlug}\" not found` });\n return;\n }\n\n const body = req.body ?? {};\n const name = typeof body.name === 'string' ? body.name.trim() : '';\n if (!name) {\n res.status(400).json({ error: 'Name is required.' });\n return;\n }\n\n const requestedSlug =\n typeof body.slug === 'string' && body.slug.trim() ? body.slug.trim() : slugify(name);\n if (!requestedSlug || !isValidSlug(requestedSlug)) {\n res.status(400).json({\n error: `Slug \"${requestedSlug}\" is invalid. Slugs must be lowercase letters, numbers, and hyphens only.`,\n });\n return;\n }\n\n const folderPath = resolve(projectDir, folder);\n await ensureDir(folderPath);\n const filePath = resolve(folderPath, `${requestedSlug}.md`);\n\n const timestamp = nowTimestamp();\n let content = renderItemStub(kind, {\n slug: requestedSlug,\n name,\n projectSlug: basename(projectDir),\n timestamp,\n });\n\n const customBody = typeof body.body === 'string' ? body.body : '';\n if (customBody.trim()) {\n content = replaceStubBody(content, customBody);\n }\n\n // Atomic create (`wx` flag fails if the file already exists). Closes the race window\n // where two concurrent POSTs both pass an existence check and the later write wins.\n try {\n const handle = await fsOpen(filePath, 'wx');\n try {\n await handle.writeFile(content, 'utf-8');\n } finally {\n await handle.close();\n }\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'EEXIST') {\n res.status(409).json({\n error: `${kind === 'memory' ? 'Memory' : 'Resource'} with slug \"${requestedSlug}\" already exists in project \"${basename(projectDir)}\".`,\n });\n return;\n }\n throw err;\n }\n\n res.status(201).json({ slug: requestedSlug, projectSlug: basename(projectDir), content });\n } catch (error) {\n console.error(`Error creating ${kind}:`, error);\n res.status(500).json({ error: `Failed to create ${kind}: ${(error as Error).message}` });\n }\n });\n\n // PATCH — body-only update\n router.patch(`/api/projects/:slug/${folder}/:itemSlug`, async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const itemSlug = getParam(req.params.itemSlug);\n if (rejectBadItemSlug(itemSlug, kind, res)) return;\n\n const projectDir = await resolveProjectDir(projectSlug);\n if (!projectDir) {\n res.status(404).json({ error: `Project \"${projectSlug}\" not found` });\n return;\n }\n const filePath = resolve(projectDir, folder, `${itemSlug}.md`);\n if (!(await fileExists(filePath))) {\n res.status(404).json({ error: `${kind === 'memory' ? 'Memory' : 'Resource'} not found` });\n return;\n }\n\n const nextContentRaw = requireContent(req, res);\n if (!nextContentRaw) return;\n\n const currentContent = await readFile(filePath, 'utf-8');\n const frontmatterBlock = extractFrontmatterBlock(currentContent);\n if (!frontmatterBlock) {\n res.status(500).json({ error: `${kind} file is malformed (no frontmatter)` });\n return;\n }\n\n const next = parseItem(kind, nextContentRaw);\n const nextBody = next.body.trimStart();\n\n let merged = `${frontmatterBlock}\\n${nextBody}${nextBody.endsWith('\\n') ? '' : '\\n'}`;\n merged = setTopLevelField(merged, 'updated', nowTimestamp());\n\n await writeFileForce(filePath, merged);\n const detail = await getItemDetail(kind, basename(projectDir), itemSlug);\n res.json({ [kind]: detail, content: merged });\n } catch (error) {\n console.error(`Error updating ${kind}:`, error);\n res.status(500).json({ error: `Failed to update ${kind}: ${(error as Error).message}` });\n }\n });\n\n // DELETE\n router.delete(`/api/projects/:slug/${folder}/:itemSlug`, async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const itemSlug = getParam(req.params.itemSlug);\n if (rejectBadItemSlug(itemSlug, kind, res)) return;\n\n const projectDir = await resolveProjectDir(projectSlug);\n if (!projectDir) {\n res.status(404).json({ error: `Project \"${projectSlug}\" not found` });\n return;\n }\n const filePath = resolve(projectDir, folder, `${itemSlug}.md`);\n if (!(await fileExists(filePath))) {\n res.status(404).json({ error: `${kind === 'memory' ? 'Memory' : 'Resource'} not found` });\n return;\n }\n await rm(filePath);\n res.status(204).end();\n } catch (error) {\n console.error(`Error deleting ${kind}:`, error);\n res.status(500).json({ error: `Failed to delete ${kind}: ${(error as Error).message}` });\n }\n });\n }\n\n router.post('/api/projects', async (req: Request, res: Response) => {\n try {\n const content = requireContent(req, res);\n if (!content) {\n return;\n }\n\n const fields = extractFrontmatter(content);\n if (!fields) {\n res.status(400).json({ error: 'Invalid frontmatter: missing --- delimiters' });\n return;\n }\n\n const validation = validateRequired(fields, ['slug', 'title']);\n if (!validation.valid) {\n res.status(400).json({ error: `Missing required fields: ${validation.missing.join(', ')}` });\n return;\n }\n\n const slug = fields.slug;\n if (!isValidSlug(slug)) {\n res.status(400).json({ error: `Invalid slug \"${slug}\". Must be lowercase and hyphen-separated.` });\n return;\n }\n\n const projectDir = resolve(projectsDir, slug);\n if (await fileExists(projectDir)) {\n res.status(409).json({ error: `Project \"${slug}\" already exists` });\n return;\n }\n\n const title = fields.title;\n const timestamp = fields.created || nowTimestamp();\n\n await ensureDir(resolve(projectDir, 'assignments'));\n await ensureDir(resolve(projectDir, 'resources'));\n await ensureDir(resolve(projectDir, 'memories'));\n\n await writeFileForce(resolve(projectDir, 'project.md'), content);\n\n try {\n const companions: Array<[string, string]> = [\n [resolve(projectDir, 'manifest.md'), renderManifest({ slug, timestamp })],\n [resolve(projectDir, '_index-assignments.md'), renderIndexAssignments({ slug, title, timestamp })],\n [resolve(projectDir, '_index-plans.md'), renderIndexPlans({ slug, title, timestamp })],\n [resolve(projectDir, '_index-decisions.md'), renderIndexDecisions({ slug, title, timestamp })],\n [resolve(projectDir, '_status.md'), renderStatus({ slug, title, timestamp })],\n [resolve(projectDir, 'resources', '_index.md'), renderResourcesIndex({ slug, title, timestamp })],\n [resolve(projectDir, 'memories', '_index.md'), renderMemoriesIndex({ slug, title, timestamp })],\n ];\n\n for (const [filePath, fileContent] of companions) {\n await writeFileForce(filePath, fileContent);\n }\n } catch (companionError) {\n try {\n await rm(projectDir, { recursive: true, force: true });\n } catch {\n // Best effort cleanup only.\n }\n throw companionError;\n }\n\n res.status(201).json({ slug });\n } catch (error) {\n console.error('Error creating project:', error);\n res.status(500).json({ error: `Failed to create project: ${(error as Error).message}` });\n }\n });\n\n router.post('/api/projects/:slug/assignments', async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const projectDir = resolve(projectsDir, projectSlug);\n const projectMdPath = resolve(projectDir, 'project.md');\n\n if (!(await fileExists(projectMdPath))) {\n res.status(404).json({ error: `Project \"${projectSlug}\" not found` });\n return;\n }\n\n const content = requireContent(req, res);\n if (!content) {\n return;\n }\n\n const fields = extractFrontmatter(content);\n if (!fields) {\n res.status(400).json({ error: 'Invalid frontmatter: missing --- delimiters' });\n return;\n }\n\n const validation = validateRequired(fields, ['slug', 'title']);\n if (!validation.valid) {\n res.status(400).json({ error: `Missing required fields: ${validation.missing.join(', ')}` });\n return;\n }\n\n const assignmentSlug = fields.slug;\n if (!isValidSlug(assignmentSlug)) {\n res.status(400).json({ error: `Invalid slug \"${assignmentSlug}\". Must be lowercase and hyphen-separated.` });\n return;\n }\n\n const validPriorities = ['low', 'medium', 'high', 'critical'];\n const priority = fields.priority || 'medium';\n if (!validPriorities.includes(priority)) {\n res.status(400).json({ error: `Invalid priority \"${priority}\". Must be low, medium, high, or critical.` });\n return;\n }\n\n const assignmentDir = resolve(projectDir, 'assignments', assignmentSlug);\n if (await fileExists(assignmentDir)) {\n res.status(409).json({\n error: `Assignment \"${assignmentSlug}\" already exists in project \"${projectSlug}\"`,\n });\n return;\n }\n\n const timestamp = fields.created || nowTimestamp();\n\n await ensureDir(assignmentDir);\n await writeFileForce(resolve(assignmentDir, 'assignment.md'), content);\n\n try {\n const companions: Array<[string, string]> = [\n [resolve(assignmentDir, 'scratchpad.md'), renderScratchpad({ assignmentSlug, timestamp })],\n [resolve(assignmentDir, 'handoff.md'), renderHandoff({ assignmentSlug, timestamp })],\n [resolve(assignmentDir, 'decision-record.md'), renderDecisionRecord({ assignmentSlug, timestamp })],\n ];\n\n for (const [filePath, fileContent] of companions) {\n await writeFileForce(filePath, fileContent);\n }\n } catch (companionError) {\n try {\n await rm(assignmentDir, { recursive: true, force: true });\n } catch {\n // Best effort cleanup only.\n }\n throw companionError;\n }\n\n res.status(201).json({ slug: assignmentSlug, projectSlug });\n } catch (error) {\n console.error('Error creating assignment:', error);\n res.status(500).json({ error: `Failed to create assignment: ${(error as Error).message}` });\n }\n });\n\n router.patch('/api/projects/:slug', async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const projectPath = resolve(projectsDir, projectSlug, 'project.md');\n const currentContent = await readCurrentDocument(projectPath);\n if (!currentContent) {\n res.status(404).json({ error: `Project \"${projectSlug}\" not found` });\n return;\n }\n\n const nextContentRaw = requireContent(req, res);\n if (!nextContentRaw) {\n return;\n }\n\n const current = parseProject(currentContent);\n const next = parseProject(nextContentRaw);\n\n if (!next.slug || !next.title) {\n res.status(400).json({ error: 'Project content must include slug and title.' });\n return;\n }\n\n if (next.slug !== current.slug) {\n res.status(400).json({ error: 'Project slug cannot be changed once created.' });\n return;\n }\n\n const nextContent = setTopLevelField(nextContentRaw, 'updated', nowTimestamp());\n await writeFileForce(projectPath, nextContent);\n\n const project = await getProjectDetail(projectsDir, projectSlug);\n res.json({ project, content: nextContent });\n } catch (error) {\n console.error('Error updating project:', error);\n res.status(500).json({ error: `Failed to update project: ${(error as Error).message}` });\n }\n });\n\n router.patch('/api/projects/:slug/assignments/:aslug', async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const assignmentSlug = getParam(req.params.aslug);\n const assignmentPath = resolve(\n projectsDir,\n projectSlug,\n 'assignments',\n assignmentSlug,\n 'assignment.md',\n );\n const currentContent = await readCurrentDocument(assignmentPath);\n if (!currentContent) {\n res.status(404).json({ error: 'Assignment not found' });\n return;\n }\n\n const nextContentRaw = requireContent(req, res);\n if (!nextContentRaw) {\n return;\n }\n\n const current = parseAssignmentFull(currentContent);\n const next = parseAssignmentFull(nextContentRaw);\n\n if (!next.slug || !next.title) {\n res.status(400).json({ error: 'Assignment content must include slug and title.' });\n return;\n }\n\n if (next.slug !== current.slug) {\n res.status(400).json({ error: 'Assignment slug cannot be changed once created.' });\n return;\n }\n\n let nextContent = nextContentRaw;\n\n // Clear blockedReason when status moves away from blocked\n if (next.status !== current.status && current.status === 'blocked' && next.status !== 'blocked') {\n nextContent = setTopLevelField(nextContent, 'blockedReason', null);\n }\n\n nextContent = setTopLevelField(nextContent, 'updated', nowTimestamp());\n await writeFileForce(assignmentPath, nextContent);\n\n const assignment = await getAssignmentDetail(projectsDir, projectSlug, assignmentSlug);\n res.json({ assignment, content: nextContent });\n } catch (error) {\n console.error('Error updating assignment:', error);\n res.status(500).json({ error: `Failed to update assignment: ${(error as Error).message}` });\n }\n });\n\n router.patch('/api/projects/:slug/assignments/:aslug/acceptance-criteria/:index', async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const assignmentSlug = getParam(req.params.aslug);\n const assignmentPath = resolve(\n projectsDir,\n projectSlug,\n 'assignments',\n assignmentSlug,\n 'assignment.md',\n );\n const currentContent = await readCurrentDocument(assignmentPath);\n if (!currentContent) {\n res.status(404).json({ error: 'Assignment not found' });\n return;\n }\n\n const { checked } = req.body || {};\n if (typeof checked !== 'boolean') {\n res.status(400).json({ error: 'checked must be a boolean' });\n return;\n }\n\n const index = Number.parseInt(getParam(req.params.index), 10);\n const result = toggleAcceptanceCriterion(currentContent, index, checked);\n if ('error' in result) {\n res.status(400).json({ error: result.error });\n return;\n }\n\n const nextContent = setTopLevelField(result.content, 'updated', nowTimestamp());\n await writeFileForce(assignmentPath, nextContent);\n\n const assignment = await getAssignmentDetail(projectsDir, projectSlug, assignmentSlug);\n res.json({ assignment, content: nextContent });\n } catch (error) {\n console.error('Error toggling acceptance criterion:', error);\n res.status(500).json({ error: `Failed to toggle acceptance criterion: ${(error as Error).message}` });\n }\n });\n\n router.patch('/api/projects/:slug/assignments/:aslug/plan', async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const assignmentSlug = getParam(req.params.aslug);\n const planPath = resolve(\n projectsDir,\n projectSlug,\n 'assignments',\n assignmentSlug,\n 'plan.md',\n );\n const currentContent = await readCurrentDocument(planPath);\n if (!currentContent) {\n res.status(404).json({ error: 'Plan not found' });\n return;\n }\n\n const nextContentRaw = requireContent(req, res);\n if (!nextContentRaw) {\n return;\n }\n\n const next = parsePlan(nextContentRaw);\n if (!next.assignment) {\n res.status(400).json({ error: 'Plan content must include the assignment field.' });\n return;\n }\n\n if (next.assignment !== assignmentSlug) {\n res.status(400).json({ error: 'Plan assignment field must match the route assignment slug.' });\n return;\n }\n\n const nextContent = setTopLevelField(nextContentRaw, 'updated', nowTimestamp());\n await writeFileForce(planPath, nextContent);\n\n const assignment = await getAssignmentDetail(projectsDir, projectSlug, assignmentSlug);\n res.json({ assignment, content: nextContent });\n } catch (error) {\n console.error('Error updating plan:', error);\n res.status(500).json({ error: `Failed to update plan: ${(error as Error).message}` });\n }\n });\n\n router.patch('/api/projects/:slug/assignments/:aslug/scratchpad', async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const assignmentSlug = getParam(req.params.aslug);\n const scratchpadPath = resolve(\n projectsDir,\n projectSlug,\n 'assignments',\n assignmentSlug,\n 'scratchpad.md',\n );\n const currentContent = await readCurrentDocument(scratchpadPath);\n if (!currentContent) {\n res.status(404).json({ error: 'Scratchpad not found' });\n return;\n }\n\n const nextContentRaw = requireContent(req, res);\n if (!nextContentRaw) {\n return;\n }\n\n const next = parseScratchpad(nextContentRaw);\n if (!next.assignment) {\n res.status(400).json({ error: 'Scratchpad content must include the assignment field.' });\n return;\n }\n\n if (next.assignment !== assignmentSlug) {\n res.status(400).json({ error: 'Scratchpad assignment field must match the route assignment slug.' });\n return;\n }\n\n const nextContent = setTopLevelField(nextContentRaw, 'updated', nowTimestamp());\n await writeFileForce(scratchpadPath, nextContent);\n\n const assignment = await getAssignmentDetail(projectsDir, projectSlug, assignmentSlug);\n res.json({ assignment, content: nextContent });\n } catch (error) {\n console.error('Error updating scratchpad:', error);\n res.status(500).json({ error: `Failed to update scratchpad: ${(error as Error).message}` });\n }\n });\n\n router.post('/api/projects/:slug/assignments/:aslug/handoff/entries', async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const assignmentSlug = getParam(req.params.aslug);\n const handoffPath = resolve(\n projectsDir,\n projectSlug,\n 'assignments',\n assignmentSlug,\n 'handoff.md',\n );\n const currentContent = await readCurrentDocument(handoffPath);\n if (!currentContent) {\n res.status(404).json({ error: 'Handoff log not found' });\n return;\n }\n\n const { title, body } = req.body || {};\n if (!body || typeof body !== 'string' || !body.trim()) {\n res.status(400).json({ error: 'body is required' });\n return;\n }\n\n const parsed = parseHandoff(currentContent);\n const nextContent = appendLogEntry(\n currentContent,\n 'handoffCount',\n parsed.handoffCount + 1,\n title && typeof title === 'string' && title.trim() ? title.trim() : `Handoff ${parsed.handoffCount + 1}`,\n body,\n 'No handoffs recorded yet.',\n );\n\n await writeFileForce(handoffPath, nextContent);\n const assignment = await getAssignmentDetail(projectsDir, projectSlug, assignmentSlug);\n res.status(201).json({ assignment, content: nextContent });\n } catch (error) {\n console.error('Error appending handoff entry:', error);\n res.status(500).json({ error: `Failed to append handoff entry: ${(error as Error).message}` });\n }\n });\n\n router.post('/api/projects/:slug/assignments/:aslug/decision-record/entries', async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const assignmentSlug = getParam(req.params.aslug);\n const decisionPath = resolve(\n projectsDir,\n projectSlug,\n 'assignments',\n assignmentSlug,\n 'decision-record.md',\n );\n const currentContent = await readCurrentDocument(decisionPath);\n if (!currentContent) {\n res.status(404).json({ error: 'Decision record not found' });\n return;\n }\n\n const { title, body } = req.body || {};\n if (!body || typeof body !== 'string' || !body.trim()) {\n res.status(400).json({ error: 'body is required' });\n return;\n }\n\n const parsed = parseDecisionRecord(currentContent);\n const nextContent = appendLogEntry(\n currentContent,\n 'decisionCount',\n parsed.decisionCount + 1,\n title && typeof title === 'string' && title.trim() ? title.trim() : `Decision ${parsed.decisionCount + 1}`,\n body,\n 'No decisions recorded yet.',\n );\n\n await writeFileForce(decisionPath, nextContent);\n const assignment = await getAssignmentDetail(projectsDir, projectSlug, assignmentSlug);\n res.status(201).json({ assignment, content: nextContent });\n } catch (error) {\n console.error('Error appending decision entry:', error);\n res.status(500).json({ error: `Failed to append decision entry: ${(error as Error).message}` });\n }\n });\n\n // --- Comments Endpoints ---\n\n router.post('/api/projects/:slug/assignments/:aslug/comments', async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const assignmentSlug = getParam(req.params.aslug);\n const commentsPath = resolve(\n projectsDir,\n projectSlug,\n 'assignments',\n assignmentSlug,\n 'comments.md',\n );\n\n const { body, author, type, replyTo } = req.body || {};\n if (!body || typeof body !== 'string' || !body.trim()) {\n res.status(400).json({ error: 'body is required' });\n return;\n }\n const commentType: CommentType = type && ['question', 'note', 'feedback'].includes(type)\n ? type\n : 'note';\n const timestamp = nowTimestamp();\n const entryAuthor = (typeof author === 'string' && author.trim()) ? author.trim() : 'human';\n\n let currentContent: string;\n let currentCount = 0;\n if (await fileExists(commentsPath)) {\n currentContent = await readFile(commentsPath, 'utf-8');\n const countMatch = currentContent.match(/^entryCount:\\s*(\\d+)/m);\n if (countMatch) currentCount = parseInt(countMatch[1], 10);\n } else {\n currentContent = renderComments({\n assignment: assignmentSlug,\n timestamp,\n });\n }\n\n const comment: Comment = {\n id: generateId().split('-')[0],\n timestamp,\n author: entryAuthor,\n type: commentType,\n body,\n replyTo: typeof replyTo === 'string' && replyTo.trim() ? replyTo.trim() : undefined,\n resolved: commentType === 'question' ? false : undefined,\n };\n const entry = formatCommentEntry(comment);\n let next = setTopLevelField(currentContent, 'entryCount', String(currentCount + 1));\n next = setTopLevelField(next, 'updated', `\"${timestamp}\"`);\n if (next.includes('No comments yet.')) {\n next = next.replace('No comments yet.', entry.trimEnd());\n } else {\n next = `${next.trimEnd()}\\n\\n${entry}`;\n }\n\n await writeFileForce(commentsPath, next);\n const assignment = await getAssignmentDetail(projectsDir, projectSlug, assignmentSlug);\n res.status(201).json({ assignment, comment: { id: comment.id } });\n } catch (error) {\n console.error('Error appending comment:', error);\n res.status(500).json({ error: `Failed to append comment: ${(error as Error).message}` });\n }\n });\n\n router.patch('/api/projects/:slug/assignments/:aslug/comments/:commentId/resolved', async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const assignmentSlug = getParam(req.params.aslug);\n const commentId = getParam(req.params.commentId);\n const commentsPath = resolve(\n projectsDir,\n projectSlug,\n 'assignments',\n assignmentSlug,\n 'comments.md',\n );\n if (!(await fileExists(commentsPath))) {\n res.status(404).json({ error: 'Comments file not found' });\n return;\n }\n const { resolved } = req.body || {};\n if (typeof resolved !== 'boolean') {\n res.status(400).json({ error: 'resolved (boolean) is required' });\n return;\n }\n\n const content = await readFile(commentsPath, 'utf-8');\n const parsed = parseComments(content);\n const target = parsed.entries.find((e) => e.id === commentId);\n if (!target) {\n res.status(404).json({ error: `Comment ${commentId} not found` });\n return;\n }\n if (target.type !== 'question') {\n res.status(400).json({ error: 'Only questions can be resolved' });\n return;\n }\n\n // Toggle the `**Resolved:**` line in the entry's block.\n const entryBlockRegex = new RegExp(\n `(^## ${commentId.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}[\\\\s\\\\S]*?)(\\\\*\\\\*Resolved:\\\\*\\\\*\\\\s*(?:true|false))`,\n 'm',\n );\n const next = content.replace(\n entryBlockRegex,\n (_m, preamble) => `${preamble}**Resolved:** ${resolved ? 'true' : 'false'}`,\n );\n if (next === content) {\n res.status(500).json({ error: 'Failed to update resolved flag' });\n return;\n }\n\n const withUpdated = setTopLevelField(next, 'updated', `\"${nowTimestamp()}\"`);\n await writeFileForce(commentsPath, withUpdated);\n const assignment = await getAssignmentDetail(projectsDir, projectSlug, assignmentSlug);\n res.json({ assignment });\n } catch (error) {\n console.error('Error toggling comment resolved flag:', error);\n res.status(500).json({ error: `Failed to toggle resolved: ${(error as Error).message}` });\n }\n });\n\n // --- Move Workspace Endpoint ---\n\n router.post('/api/projects/:slug/move-workspace', async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const projectPath = resolve(projectsDir, projectSlug, 'project.md');\n if (!(await fileExists(projectPath))) {\n res.status(404).json({ error: `Project \"${projectSlug}\" not found` });\n return;\n }\n\n const { workspace } = req.body || {};\n if (\n workspace !== null &&\n (typeof workspace !== 'string' || !workspace.trim() || !isValidSlug(workspace))\n ) {\n // isValidSlug forbids newlines, colons, and other YAML metacharacters,\n // so we can safely write the value into frontmatter without escaping.\n res.status(400).json({\n error:\n 'workspace must be a valid slug (lowercase letters, numbers, hyphens) or null (for ungrouped).',\n });\n return;\n }\n\n let content = await readFile(projectPath, 'utf-8');\n content = setTopLevelField(content, 'workspace', workspace ?? null);\n content = setTopLevelField(content, 'updated', nowTimestamp());\n await writeFileForce(projectPath, content);\n\n const project = await getProjectDetail(projectsDir, projectSlug);\n res.json({ project });\n } catch (error) {\n console.error('Error moving project workspace:', error);\n res.status(500).json({ error: `Failed to move workspace: ${(error as Error).message}` });\n }\n });\n\n router.post('/api/assignments/:id/move-workspace', async (req: Request, res: Response) => {\n try {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n\n const id = getParam(req.params.id);\n const resolved = await resolveAssignmentById(projectsDir, assignmentsDir, id);\n if (!resolved) {\n res.status(404).json({ error: `Assignment \"${id}\" not found` });\n return;\n }\n if (!resolved.standalone) {\n res.status(400).json({\n error:\n 'Project-nested assignments inherit workspace from their parent project. Move the project instead.',\n });\n return;\n }\n\n const { workspaceGroup } = req.body || {};\n if (\n workspaceGroup !== null &&\n (typeof workspaceGroup !== 'string' || !workspaceGroup.trim() || !isValidSlug(workspaceGroup))\n ) {\n // See workspace move route above: isValidSlug guards against frontmatter injection.\n res.status(400).json({\n error:\n 'workspaceGroup must be a valid slug (lowercase letters, numbers, hyphens) or null (for ungrouped).',\n });\n return;\n }\n\n const assignmentPath = resolve(resolved.assignmentDir, 'assignment.md');\n let content = await readFile(assignmentPath, 'utf-8');\n content = setTopLevelField(content, 'workspaceGroup', workspaceGroup ?? null);\n content = setTopLevelField(content, 'updated', nowTimestamp());\n await writeFileForce(assignmentPath, content);\n\n const assignment = await getAssignmentDetailById(projectsDir, assignmentsDir, id);\n res.json({ assignment });\n } catch (error) {\n console.error('Error moving assignment workspace:', error);\n res.status(500).json({ error: `Failed to move workspace: ${(error as Error).message}` });\n }\n });\n\n // --- Worktree creation + candidate discovery ---\n // Mirrors the existing CLI flow (`syntaur worktree create`) and the browse\n // TUI's `runCreate`. All three paths call `createWorktreeAndRecord` so the\n // assignment.md frontmatter ends up identical regardless of entry point.\n\n router.get(\n '/api/projects/:slug/repository-candidates',\n async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const projectPath = resolve(projectsDir, projectSlug, 'project.md');\n if (!(await fileExists(projectPath))) {\n res.status(404).json({ error: `Project \"${projectSlug}\" not found` });\n return;\n }\n const candidates = await getProjectRepositoryCandidates(projectsDir, projectSlug);\n res.json({ candidates });\n } catch (error) {\n console.error('Error listing repository candidates:', error);\n res.status(500).json({\n error: `Failed to list repository candidates: ${(error as Error).message}`,\n });\n }\n },\n );\n\n router.get(\n '/api/assignments/:id/repository-candidates',\n async (req: Request, res: Response) => {\n try {\n if (!assignmentsDir) {\n res\n .status(501)\n .json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n const id = getParam(req.params.id);\n const resolved = await resolveAssignmentById(projectsDir, assignmentsDir, id);\n if (!resolved) {\n res.status(404).json({ error: `Assignment \"${id}\" not found` });\n return;\n }\n const candidates = resolved.standalone\n ? await getStandaloneRepositoryCandidates(assignmentsDir, id)\n : await getProjectRepositoryCandidates(projectsDir, resolved.projectSlug!);\n res.json({ candidates });\n } catch (error) {\n console.error('Error listing repository candidates:', error);\n res.status(500).json({\n error: `Failed to list repository candidates: ${(error as Error).message}`,\n });\n }\n },\n );\n\n router.post(\n '/api/projects/:slug/assignments/:aslug/worktree',\n async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const assignmentSlug = getParam(req.params.aslug);\n const assignmentPath = resolve(\n projectsDir,\n projectSlug,\n 'assignments',\n assignmentSlug,\n 'assignment.md',\n );\n await handleWorktreeCreate(req, res, {\n assignmentPath,\n projectSlug,\n assignmentSlug,\n reload: () => getAssignmentDetail(projectsDir, projectSlug, assignmentSlug),\n });\n } catch (error) {\n console.error('Error creating worktree:', error);\n res\n .status(500)\n .json({ error: `Failed to create worktree: ${(error as Error).message}` });\n }\n },\n );\n\n router.post(\n '/api/assignments/:id/worktree',\n async (req: Request, res: Response) => {\n try {\n if (!assignmentsDir) {\n res\n .status(501)\n .json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n const id = getParam(req.params.id);\n const resolved = await resolveAssignmentById(projectsDir, assignmentsDir, id);\n if (!resolved) {\n res.status(404).json({ error: `Assignment \"${id}\" not found` });\n return;\n }\n const assignmentPath = resolve(resolved.assignmentDir, 'assignment.md');\n // Standalone: resolveAssignmentById returns the UUID as `assignmentSlug`.\n // For branch naming we need the user-visible slug from frontmatter, so\n // parse it here and pass that down. parseAssignmentFull falls back to\n // empty string, hence the `|| resolved.id` belt-and-suspenders.\n const parsedForSlug = parseAssignmentFull(await readFile(assignmentPath, 'utf-8'));\n const assignmentSlugForBranch = parsedForSlug.slug || resolved.id;\n await handleWorktreeCreate(req, res, {\n assignmentPath,\n projectSlug: resolved.projectSlug ?? '',\n assignmentSlug: assignmentSlugForBranch,\n reload: () => getAssignmentDetailById(projectsDir, assignmentsDir!, id),\n });\n } catch (error) {\n console.error('Error creating worktree:', error);\n res\n .status(500)\n .json({ error: `Failed to create worktree: ${(error as Error).message}` });\n }\n },\n );\n\n // --- Status Override Endpoints ---\n\n router.post('/api/projects/:slug/status-override', async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const projectPath = resolve(projectsDir, projectSlug, 'project.md');\n if (!(await fileExists(projectPath))) {\n res.status(404).json({ error: `Project \"${projectSlug}\" not found` });\n return;\n }\n\n const { status } = req.body || {};\n const config = await getStatusConfig();\n const validStatuses = ['active', 'archived', ...config.statuses.map((s) => s.id)];\n if (status !== null && (typeof status !== 'string' || !validStatuses.includes(status))) {\n res.status(400).json({ error: `Invalid status. Must be one of: ${validStatuses.join(', ')}, or null to clear.` });\n return;\n }\n\n let content = await readFile(projectPath, 'utf-8');\n content = setTopLevelField(content, 'statusOverride', status ?? null);\n content = setTopLevelField(content, 'updated', nowTimestamp());\n await writeFileForce(projectPath, content);\n\n const project = await getProjectDetail(projectsDir, projectSlug);\n res.json({ project });\n } catch (error) {\n console.error('Error setting project status override:', error);\n res.status(500).json({ error: `Failed to set status override: ${(error as Error).message}` });\n }\n });\n\n router.post('/api/projects/:slug/assignments/:aslug/status-override', async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const assignmentSlug = getParam(req.params.aslug);\n const assignmentPath = resolve(\n projectsDir,\n projectSlug,\n 'assignments',\n assignmentSlug,\n 'assignment.md',\n );\n if (!(await fileExists(assignmentPath))) {\n res.status(404).json({ error: 'Assignment not found' });\n return;\n }\n\n const { status } = req.body || {};\n const config = await getStatusConfig();\n const validStatuses = config.statuses.map((s) => s.id);\n if (typeof status !== 'string' || !validStatuses.includes(status)) {\n res.status(400).json({ error: `Invalid status. Must be one of: ${validStatuses.join(', ')}.` });\n return;\n }\n\n let content = await readFile(assignmentPath, 'utf-8');\n content = setTopLevelField(content, 'status', status);\n content = setTopLevelField(content, 'updated', nowTimestamp());\n\n // Clear blockedReason when moving away from blocked\n if (status !== 'blocked') {\n content = setTopLevelField(content, 'blockedReason', null);\n }\n\n await writeFileForce(assignmentPath, content);\n\n const assignment = await getAssignmentDetail(projectsDir, projectSlug, assignmentSlug);\n res.json({ assignment });\n } catch (error) {\n console.error('Error overriding assignment status:', error);\n res.status(500).json({ error: `Failed to override status: ${(error as Error).message}` });\n }\n });\n\n router.patch('/api/projects/:slug/assignments/:aslug/assignee', async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const assignmentSlug = getParam(req.params.aslug);\n const assignmentPath = resolve(\n projectsDir,\n projectSlug,\n 'assignments',\n assignmentSlug,\n 'assignment.md',\n );\n if (!(await fileExists(assignmentPath))) {\n res.status(404).json({ error: 'Assignment not found' });\n return;\n }\n const validation = validateAssigneeBody(req.body);\n if (!validation.ok) {\n res.status(400).json({ error: validation.error });\n return;\n }\n let content = await readFile(assignmentPath, 'utf-8');\n content = setTopLevelField(content, 'assignee', validation.value);\n content = setTopLevelField(content, 'updated', nowTimestamp());\n await writeFileForce(assignmentPath, content);\n const assignment = await getAssignmentDetail(projectsDir, projectSlug, assignmentSlug);\n res.json({ assignment });\n } catch (error) {\n console.error('Error updating assignee:', error);\n res.status(500).json({ error: `Failed to update assignee: ${(error as Error).message}` });\n }\n });\n\n // --- Lifecycle Transitions ---\n\n router.post('/api/projects/:slug/assignments/:aslug/transitions/:command', async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const assignmentSlug = getParam(req.params.aslug);\n const command = req.params.command as Parameters<typeof executeTransition>[2];\n const config = await getStatusConfig();\n const validCommands = [...new Set(config.transitions.map((t) => t.command))];\n if (!validCommands.includes(command)) {\n res.status(400).json({ error: `Unsupported transition command \"${req.params.command}\"` });\n return;\n }\n\n const projectDir = resolve(projectsDir, projectSlug);\n const assignmentPath = resolve(projectDir, 'assignments', assignmentSlug, 'assignment.md');\n if (!(await fileExists(assignmentPath))) {\n res.status(404).json({ error: 'Assignment not found' });\n return;\n }\n\n const { reason } = req.body || {};\n const result = await executeTransition(projectDir, assignmentSlug, command, {\n reason: typeof reason === 'string' ? reason : undefined,\n transitionTable: config.custom ? config.transitionTable : undefined,\n terminalStatuses: config.custom ? config.terminalStatuses : undefined,\n linkedTodosLookup,\n });\n\n if (!result.success) {\n res.status(400).json({ error: result.message });\n return;\n }\n\n const assignment = await getAssignmentDetail(projectsDir, projectSlug, assignmentSlug);\n res.json({ assignment, transition: result });\n } catch (error) {\n console.error('Error running assignment transition:', error);\n res.status(500).json({ error: `Failed to transition assignment: ${(error as Error).message}` });\n }\n });\n\n router.delete('/api/projects/:slug/assignments/:aslug', async (req: Request, res: Response) => {\n try {\n const projectSlug = getParam(req.params.slug);\n const assignmentSlug = getParam(req.params.aslug);\n const assignmentDir = resolve(projectsDir, projectSlug, 'assignments', assignmentSlug);\n const assignmentPath = resolve(assignmentDir, 'assignment.md');\n\n if (!(await fileExists(assignmentPath))) {\n res.status(404).json({ error: `Assignment \"${assignmentSlug}\" not found in project \"${projectSlug}\"` });\n return;\n }\n\n await rm(assignmentDir, { recursive: true, force: true });\n res.json({ deleted: assignmentSlug, projectSlug });\n } catch (error) {\n console.error('Error deleting assignment:', error);\n res.status(500).json({ error: `Failed to delete assignment: ${(error as Error).message}` });\n }\n });\n\n // =========================================================================\n // Standalone (by-id) routes — `~/.syntaur/assignments/<uuid>/`\n // Active only when the write router was constructed with an assignmentsDir.\n // =========================================================================\n\n router.post('/api/assignments', async (req: Request, res: Response) => {\n try {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n\n // Two body shapes are supported:\n // 1) { content: <markdown> } — same shape as POST /api/projects/:slug/assignments. Used by the dashboard UI.\n // 2) { title, slug?, priority?, type? } — original structured form, retained for back-compat.\n const rawContent = typeof req.body?.content === 'string' ? req.body.content : '';\n if (rawContent.trim()) {\n const fields = extractFrontmatter(rawContent);\n if (!fields) {\n res.status(400).json({ error: 'Invalid frontmatter: missing --- delimiters' });\n return;\n }\n const validation = validateRequired(fields, ['slug', 'title']);\n if (!validation.valid) {\n res.status(400).json({ error: `Missing required fields: ${validation.missing.join(', ')}` });\n return;\n }\n const submittedSlug = fields.slug;\n if (!isValidSlug(submittedSlug)) {\n res.status(400).json({ error: `Invalid slug \"${submittedSlug}\". Must be lowercase and hyphen-separated.` });\n return;\n }\n const validPriorities = ['low', 'medium', 'high', 'critical'];\n const submittedPriority = fields.priority || 'medium';\n if (!validPriorities.includes(submittedPriority)) {\n res.status(400).json({ error: `Invalid priority \"${submittedPriority}\". Must be low, medium, high, or critical.` });\n return;\n }\n\n // Standalone-specific guards: no project, optional workspaceGroup.\n if (fields.project && fields.project !== 'null') {\n res.status(400).json({\n error: 'Standalone assignments cannot have a project; remove \"project\" or set it to null.',\n });\n return;\n }\n const submittedWorkspaceGroup = fields.workspaceGroup && fields.workspaceGroup !== 'null'\n ? fields.workspaceGroup\n : '';\n if (submittedWorkspaceGroup && !isValidSlug(submittedWorkspaceGroup)) {\n res.status(400).json({\n error: `Invalid workspace slug \"${submittedWorkspaceGroup}\". Slugs must be lowercase, hyphen-separated, with no special characters.`,\n });\n return;\n }\n\n const id = generateId();\n const assignmentDir = resolve(assignmentsDir, id);\n if (await fileExists(assignmentDir)) {\n res.status(500).json({ error: 'UUID collision — try again' });\n return;\n }\n\n const timestamp = fields.created || nowTimestamp();\n await ensureDir(assignmentDir);\n // Normalize the frontmatter id to the freshly-generated UUID — the template ships a placeholder.\n const normalizedContent = setTopLevelField(rawContent, 'id', id);\n await writeFileForce(resolve(assignmentDir, 'assignment.md'), normalizedContent);\n await writeFileForce(\n resolve(assignmentDir, 'scratchpad.md'),\n renderScratchpad({ assignmentSlug: id, timestamp }),\n );\n await writeFileForce(\n resolve(assignmentDir, 'handoff.md'),\n renderHandoff({ assignmentSlug: id, timestamp }),\n );\n await writeFileForce(\n resolve(assignmentDir, 'decision-record.md'),\n renderDecisionRecord({ assignmentSlug: id, timestamp }),\n );\n await writeFileForce(\n resolve(assignmentDir, 'progress.md'),\n renderProgress({ assignment: id, timestamp }),\n );\n await writeFileForce(\n resolve(assignmentDir, 'comments.md'),\n renderComments({ assignment: id, timestamp }),\n );\n\n const detail = await getAssignmentDetailById(projectsDir, assignmentsDir, id);\n res.status(201).json({ assignment: detail });\n return;\n }\n\n // Structured-form path (back-compat).\n const { title, slug, priority, type } = req.body || {};\n if (!title || typeof title !== 'string' || !title.trim()) {\n res.status(400).json({ error: 'title is required' });\n return;\n }\n const { dependsOn } = req.body || {};\n if (Array.isArray(dependsOn) && dependsOn.length > 0) {\n res.status(400).json({ error: 'Standalone assignments cannot declare dependsOn.' });\n return;\n }\n\n const id = generateId();\n const assignmentDir = resolve(assignmentsDir, id);\n if (await fileExists(assignmentDir)) {\n res.status(500).json({ error: 'UUID collision — try again' });\n return;\n }\n\n const timestamp = nowTimestamp();\n const resolvedSlug = typeof slug === 'string' && slug.trim() ? slug.trim() : slugifyLocal(title);\n const resolvedPriority = (typeof priority === 'string' && ['low', 'medium', 'high', 'critical'].includes(priority))\n ? (priority as 'low' | 'medium' | 'high' | 'critical')\n : 'medium';\n\n await ensureDir(assignmentDir);\n const assignmentContent = renderAssignment({\n id,\n slug: resolvedSlug,\n title: title.trim(),\n timestamp,\n priority: resolvedPriority,\n dependsOn: [],\n links: [],\n project: null,\n type: typeof type === 'string' ? type : undefined,\n });\n await writeFileForce(resolve(assignmentDir, 'assignment.md'), assignmentContent);\n await writeFileForce(\n resolve(assignmentDir, 'scratchpad.md'),\n renderScratchpad({ assignmentSlug: id, timestamp }),\n );\n await writeFileForce(\n resolve(assignmentDir, 'handoff.md'),\n renderHandoff({ assignmentSlug: id, timestamp }),\n );\n await writeFileForce(\n resolve(assignmentDir, 'decision-record.md'),\n renderDecisionRecord({ assignmentSlug: id, timestamp }),\n );\n await writeFileForce(\n resolve(assignmentDir, 'progress.md'),\n renderProgress({ assignment: id, timestamp }),\n );\n await writeFileForce(\n resolve(assignmentDir, 'comments.md'),\n renderComments({ assignment: id, timestamp }),\n );\n\n const detail = await getAssignmentDetailById(projectsDir, assignmentsDir, id);\n res.status(201).json({ assignment: detail });\n } catch (error) {\n console.error('Error creating standalone assignment:', error);\n res.status(500).json({ error: `Failed to create standalone assignment: ${(error as Error).message}` });\n }\n });\n\n router.post('/api/assignments/:id/comments', async (req: Request, res: Response) => {\n try {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n const id = getParam(req.params.id);\n const resolved = await resolveAssignmentById(projectsDir, assignmentsDir, id);\n if (!resolved) {\n res.status(404).json({ error: `Assignment \"${id}\" not found` });\n return;\n }\n await appendCommentTo(resolved.assignmentDir, resolved.standalone ? resolved.id : resolved.assignmentSlug, req, res, async () => {\n return resolved.standalone\n ? getAssignmentDetailById(projectsDir, assignmentsDir, id)\n : getAssignmentDetail(projectsDir, resolved.projectSlug!, resolved.assignmentSlug);\n });\n } catch (error) {\n console.error('Error appending comment (by id):', error);\n res.status(500).json({ error: `Failed to append comment: ${(error as Error).message}` });\n }\n });\n\n router.patch('/api/assignments/:id/comments/:commentId/resolved', async (req: Request, res: Response) => {\n try {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n const id = getParam(req.params.id);\n const commentId = getParam(req.params.commentId);\n const resolved = await resolveAssignmentById(projectsDir, assignmentsDir, id);\n if (!resolved) {\n res.status(404).json({ error: `Assignment \"${id}\" not found` });\n return;\n }\n await toggleCommentResolvedAt(resolved.assignmentDir, commentId, req, res, async () => {\n return resolved.standalone\n ? getAssignmentDetailById(projectsDir, assignmentsDir, id)\n : getAssignmentDetail(projectsDir, resolved.projectSlug!, resolved.assignmentSlug);\n });\n } catch (error) {\n console.error('Error toggling comment resolved (by id):', error);\n res.status(500).json({ error: `Failed to toggle resolved: ${(error as Error).message}` });\n }\n });\n\n router.get('/api/assignments/:id/edit', async (req: Request, res: Response) => {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n const id = getParam(req.params.id);\n const doc = await getEditableDocumentById(projectsDir, assignmentsDir, 'assignment', id);\n if (!doc) {\n res.status(404).json({ error: 'Assignment not found' });\n return;\n }\n res.json(doc);\n });\n\n router.get('/api/assignments/:id/plan/edit', async (req: Request, res: Response) => {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n const id = getParam(req.params.id);\n const doc = await getEditableDocumentById(projectsDir, assignmentsDir, 'plan', id);\n if (!doc) {\n res.status(404).json({ error: 'Plan not found' });\n return;\n }\n res.json(doc);\n });\n\n router.get('/api/assignments/:id/scratchpad/edit', async (req: Request, res: Response) => {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n const id = getParam(req.params.id);\n const doc = await getEditableDocumentById(projectsDir, assignmentsDir, 'scratchpad', id);\n if (!doc) {\n res.status(404).json({ error: 'Scratchpad not found' });\n return;\n }\n res.json(doc);\n });\n\n router.get('/api/assignments/:id/handoff/edit', async (req: Request, res: Response) => {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n const id = getParam(req.params.id);\n const doc = await getEditableDocumentById(projectsDir, assignmentsDir, 'handoff', id);\n if (!doc) {\n res.status(404).json({ error: 'Handoff log not found' });\n return;\n }\n res.json(doc);\n });\n\n router.get('/api/assignments/:id/decision-record/edit', async (req: Request, res: Response) => {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n const id = getParam(req.params.id);\n const doc = await getEditableDocumentById(projectsDir, assignmentsDir, 'decision-record', id);\n if (!doc) {\n res.status(404).json({ error: 'Decision record not found' });\n return;\n }\n res.json(doc);\n });\n\n router.patch('/api/assignments/:id', async (req: Request, res: Response) => {\n try {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n const id = getParam(req.params.id);\n const resolved = await resolveAssignmentById(projectsDir, assignmentsDir, id);\n if (!resolved) {\n res.status(404).json({ error: `Assignment \"${id}\" not found` });\n return;\n }\n\n const assignmentPath = resolve(resolved.assignmentDir, 'assignment.md');\n const currentContent = await readCurrentDocument(assignmentPath);\n if (!currentContent) {\n res.status(404).json({ error: 'Assignment not found' });\n return;\n }\n\n const nextContentRaw = requireContent(req, res);\n if (!nextContentRaw) return;\n\n const current = parseAssignmentFull(currentContent);\n const next = parseAssignmentFull(nextContentRaw);\n\n if (!next.title) {\n res.status(400).json({ error: 'Assignment content must include a title.' });\n return;\n }\n\n // Standalone: restore id + project + slug frontmatter (all immutable after create).\n let nextContent = nextContentRaw;\n if (current.id) nextContent = setTopLevelField(nextContent, 'id', current.id);\n nextContent = setTopLevelField(nextContent, 'project', null);\n if (current.slug) nextContent = setTopLevelField(nextContent, 'slug', current.slug);\n\n if (next.status !== current.status && current.status === 'blocked' && next.status !== 'blocked') {\n nextContent = setTopLevelField(nextContent, 'blockedReason', null);\n }\n\n nextContent = setTopLevelField(nextContent, 'updated', nowTimestamp());\n await writeFileForce(assignmentPath, nextContent);\n\n const assignment = await getAssignmentDetailById(projectsDir, assignmentsDir, id);\n res.json({ assignment, content: nextContent });\n } catch (error) {\n console.error('Error updating standalone assignment:', error);\n res.status(500).json({ error: `Failed to update assignment: ${(error as Error).message}` });\n }\n });\n\n router.patch('/api/assignments/:id/plan', async (req: Request, res: Response) => {\n try {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n const id = getParam(req.params.id);\n const resolved = await resolveAssignmentById(projectsDir, assignmentsDir, id);\n if (!resolved) {\n res.status(404).json({ error: `Assignment \"${id}\" not found` });\n return;\n }\n\n const planPath = resolve(resolved.assignmentDir, 'plan.md');\n const currentContent = await readCurrentDocument(planPath);\n if (!currentContent) {\n res.status(404).json({ error: 'Plan not found' });\n return;\n }\n const nextContentRaw = requireContent(req, res);\n if (!nextContentRaw) return;\n\n const parsed = parsePlan(nextContentRaw);\n if (!parsed.assignment) {\n res.status(400).json({ error: 'Plan content must include the assignment field.' });\n return;\n }\n\n const nextContent = setTopLevelField(nextContentRaw, 'updated', nowTimestamp());\n await writeFileForce(planPath, nextContent);\n\n const assignment = await getAssignmentDetailById(projectsDir, assignmentsDir, id);\n res.json({ assignment, content: nextContent });\n } catch (error) {\n console.error('Error updating standalone plan:', error);\n res.status(500).json({ error: `Failed to update plan: ${(error as Error).message}` });\n }\n });\n\n router.patch('/api/assignments/:id/scratchpad', async (req: Request, res: Response) => {\n try {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n const id = getParam(req.params.id);\n const resolved = await resolveAssignmentById(projectsDir, assignmentsDir, id);\n if (!resolved) {\n res.status(404).json({ error: `Assignment \"${id}\" not found` });\n return;\n }\n\n const scratchpadPath = resolve(resolved.assignmentDir, 'scratchpad.md');\n const currentContent = await readCurrentDocument(scratchpadPath);\n if (!currentContent) {\n res.status(404).json({ error: 'Scratchpad not found' });\n return;\n }\n const nextContentRaw = requireContent(req, res);\n if (!nextContentRaw) return;\n\n const parsed = parseScratchpad(nextContentRaw);\n if (!parsed.assignment) {\n res.status(400).json({ error: 'Scratchpad content must include the assignment field.' });\n return;\n }\n\n const nextContent = setTopLevelField(nextContentRaw, 'updated', nowTimestamp());\n await writeFileForce(scratchpadPath, nextContent);\n\n const assignment = await getAssignmentDetailById(projectsDir, assignmentsDir, id);\n res.json({ assignment, content: nextContent });\n } catch (error) {\n console.error('Error updating standalone scratchpad:', error);\n res.status(500).json({ error: `Failed to update scratchpad: ${(error as Error).message}` });\n }\n });\n\n router.post('/api/assignments/:id/handoff/entries', async (req: Request, res: Response) => {\n try {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n const id = getParam(req.params.id);\n const resolved = await resolveAssignmentById(projectsDir, assignmentsDir, id);\n if (!resolved) {\n res.status(404).json({ error: `Assignment \"${id}\" not found` });\n return;\n }\n const handoffPath = resolve(resolved.assignmentDir, 'handoff.md');\n const currentContent = await readCurrentDocument(handoffPath);\n if (!currentContent) {\n res.status(404).json({ error: 'Handoff log not found' });\n return;\n }\n const { title, body } = req.body || {};\n if (!body || typeof body !== 'string' || !body.trim()) {\n res.status(400).json({ error: 'body is required' });\n return;\n }\n const parsed = parseHandoff(currentContent);\n const nextContent = appendLogEntry(\n currentContent,\n 'handoffCount',\n parsed.handoffCount + 1,\n title && typeof title === 'string' && title.trim() ? title.trim() : `Handoff ${parsed.handoffCount + 1}`,\n body,\n 'No handoffs recorded yet.',\n );\n await writeFileForce(handoffPath, nextContent);\n const assignment = await getAssignmentDetailById(projectsDir, assignmentsDir, id);\n res.status(201).json({ assignment, content: nextContent });\n } catch (error) {\n console.error('Error appending standalone handoff entry:', error);\n res.status(500).json({ error: `Failed to append handoff entry: ${(error as Error).message}` });\n }\n });\n\n router.post('/api/assignments/:id/decision-record/entries', async (req: Request, res: Response) => {\n try {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n const id = getParam(req.params.id);\n const resolved = await resolveAssignmentById(projectsDir, assignmentsDir, id);\n if (!resolved) {\n res.status(404).json({ error: `Assignment \"${id}\" not found` });\n return;\n }\n const decisionPath = resolve(resolved.assignmentDir, 'decision-record.md');\n const currentContent = await readCurrentDocument(decisionPath);\n if (!currentContent) {\n res.status(404).json({ error: 'Decision record not found' });\n return;\n }\n const { title, body } = req.body || {};\n if (!body || typeof body !== 'string' || !body.trim()) {\n res.status(400).json({ error: 'body is required' });\n return;\n }\n const parsed = parseDecisionRecord(currentContent);\n const nextContent = appendLogEntry(\n currentContent,\n 'decisionCount',\n parsed.decisionCount + 1,\n title && typeof title === 'string' && title.trim() ? title.trim() : `Decision ${parsed.decisionCount + 1}`,\n body,\n 'No decisions recorded yet.',\n );\n await writeFileForce(decisionPath, nextContent);\n const assignment = await getAssignmentDetailById(projectsDir, assignmentsDir, id);\n res.status(201).json({ assignment, content: nextContent });\n } catch (error) {\n console.error('Error appending standalone decision entry:', error);\n res.status(500).json({ error: `Failed to append decision entry: ${(error as Error).message}` });\n }\n });\n\n router.post('/api/assignments/:id/status-override', async (req: Request, res: Response) => {\n try {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n const id = getParam(req.params.id);\n const resolved = await resolveAssignmentById(projectsDir, assignmentsDir, id);\n if (!resolved) {\n res.status(404).json({ error: `Assignment \"${id}\" not found` });\n return;\n }\n const assignmentPath = resolve(resolved.assignmentDir, 'assignment.md');\n if (!(await fileExists(assignmentPath))) {\n res.status(404).json({ error: 'Assignment not found' });\n return;\n }\n const { status } = req.body || {};\n const config = await getStatusConfig();\n const validStatuses = config.statuses.map((s) => s.id);\n if (typeof status !== 'string' || !validStatuses.includes(status)) {\n res.status(400).json({ error: `Invalid status. Must be one of: ${validStatuses.join(', ')}.` });\n return;\n }\n let content = await readFile(assignmentPath, 'utf-8');\n content = setTopLevelField(content, 'status', status);\n content = setTopLevelField(content, 'updated', nowTimestamp());\n if (status !== 'blocked') {\n content = setTopLevelField(content, 'blockedReason', null);\n }\n await writeFileForce(assignmentPath, content);\n const assignment = await getAssignmentDetailById(projectsDir, assignmentsDir, id);\n res.json({ assignment });\n } catch (error) {\n console.error('Error overriding standalone status:', error);\n res.status(500).json({ error: `Failed to override status: ${(error as Error).message}` });\n }\n });\n\n router.patch('/api/assignments/:id/assignee', async (req: Request, res: Response) => {\n try {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n const id = getParam(req.params.id);\n const resolved = await resolveAssignmentById(projectsDir, assignmentsDir, id);\n if (!resolved) {\n res.status(404).json({ error: `Assignment \"${id}\" not found` });\n return;\n }\n const assignmentPath = resolve(resolved.assignmentDir, 'assignment.md');\n if (!(await fileExists(assignmentPath))) {\n res.status(404).json({ error: 'Assignment not found' });\n return;\n }\n const validation = validateAssigneeBody(req.body);\n if (!validation.ok) {\n res.status(400).json({ error: validation.error });\n return;\n }\n let content = await readFile(assignmentPath, 'utf-8');\n content = setTopLevelField(content, 'assignee', validation.value);\n content = setTopLevelField(content, 'updated', nowTimestamp());\n await writeFileForce(assignmentPath, content);\n const assignment = await getAssignmentDetailById(projectsDir, assignmentsDir, id);\n res.json({ assignment });\n } catch (error) {\n console.error('Error updating standalone assignee:', error);\n res.status(500).json({ error: `Failed to update assignee: ${(error as Error).message}` });\n }\n });\n\n router.post('/api/assignments/bulk-status-override', async (req: Request, res: Response) => {\n try {\n const body = req.body;\n if (!body || typeof body !== 'object' || !Array.isArray(body.items)) {\n res.status(400).json({ error: 'Request body must include `items` (array).' });\n return;\n }\n const items = body.items as Array<unknown>;\n if (items.length === 0) {\n res.status(400).json({ error: '`items` must contain at least one entry.' });\n return;\n }\n if (items.length > 200) {\n res.status(400).json({ error: '`items` is capped at 200 entries per call.' });\n return;\n }\n\n const config = await getStatusConfig();\n const validStatuses = new Set(config.statuses.map((s) => s.id));\n const timestamp = nowTimestamp();\n const results: Array<{ key: string; ok: boolean; error?: string }> = [];\n let succeeded = 0;\n let failed = 0;\n\n for (let index = 0; index < items.length; index += 1) {\n const raw = items[index];\n const itemKey = buildBulkItemKey(raw, index);\n try {\n if (!raw || typeof raw !== 'object') {\n throw new Error('item must be an object');\n }\n const item = raw as Record<string, unknown>;\n const status = typeof item.status === 'string' ? item.status : null;\n if (!status || !validStatuses.has(status)) {\n throw new Error(`invalid status \"${status ?? ''}\"`);\n }\n\n let assignmentPath: string | null = null;\n if (typeof item.id === 'string' && item.id.trim()) {\n if (!assignmentsDir) {\n throw new Error('standalone assignments are not configured on this server');\n }\n const resolved = await resolveAssignmentById(projectsDir, assignmentsDir, item.id);\n if (!resolved) {\n throw new Error(`assignment \"${item.id}\" not found`);\n }\n assignmentPath = resolve(resolved.assignmentDir, 'assignment.md');\n } else if (\n typeof item.projectSlug === 'string'\n && typeof item.assignmentSlug === 'string'\n && item.projectSlug\n && item.assignmentSlug\n ) {\n assignmentPath = resolve(\n projectsDir,\n item.projectSlug,\n 'assignments',\n item.assignmentSlug,\n 'assignment.md',\n );\n } else {\n throw new Error('must supply either `id` or both `projectSlug` and `assignmentSlug`');\n }\n\n if (!(await fileExists(assignmentPath))) {\n throw new Error('assignment file not found');\n }\n\n let content = await readFile(assignmentPath, 'utf-8');\n content = setTopLevelField(content, 'status', status);\n content = setTopLevelField(content, 'updated', timestamp);\n if (status !== 'blocked') {\n content = setTopLevelField(content, 'blockedReason', null);\n }\n await writeFileForce(assignmentPath, content);\n\n results.push({ key: itemKey, ok: true });\n succeeded += 1;\n } catch (error) {\n results.push({ key: itemKey, ok: false, error: (error as Error).message });\n failed += 1;\n }\n }\n\n res.json({ results, succeeded, failed });\n } catch (error) {\n console.error('Error in bulk-status-override:', error);\n res.status(500).json({ error: `Bulk status override failed: ${(error as Error).message}` });\n }\n });\n\n router.patch('/api/assignments/:id/acceptance-criteria/:index', async (req: Request, res: Response) => {\n try {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n const id = getParam(req.params.id);\n const resolved = await resolveAssignmentById(projectsDir, assignmentsDir, id);\n if (!resolved) {\n res.status(404).json({ error: `Assignment \"${id}\" not found` });\n return;\n }\n const assignmentPath = resolve(resolved.assignmentDir, 'assignment.md');\n const currentContent = await readCurrentDocument(assignmentPath);\n if (!currentContent) {\n res.status(404).json({ error: 'Assignment not found' });\n return;\n }\n const { checked } = req.body || {};\n if (typeof checked !== 'boolean') {\n res.status(400).json({ error: 'checked must be a boolean' });\n return;\n }\n const index = Number.parseInt(getParam(req.params.index), 10);\n const result = toggleAcceptanceCriterion(currentContent, index, checked);\n if ('error' in result) {\n res.status(400).json({ error: result.error });\n return;\n }\n const nextContent = setTopLevelField(result.content, 'updated', nowTimestamp());\n await writeFileForce(assignmentPath, nextContent);\n const assignment = await getAssignmentDetailById(projectsDir, assignmentsDir, id);\n res.json({ assignment, content: nextContent });\n } catch (error) {\n console.error('Error toggling standalone acceptance criterion:', error);\n res.status(500).json({ error: `Failed to toggle acceptance criterion: ${(error as Error).message}` });\n }\n });\n\n router.post('/api/assignments/:id/transitions/:command', async (req: Request, res: Response) => {\n try {\n if (!assignmentsDir) {\n res.status(501).json({ error: 'Standalone assignments not configured on this server' });\n return;\n }\n const id = getParam(req.params.id);\n const command = getParam(req.params.command);\n const resolved = await resolveAssignmentById(projectsDir, assignmentsDir, id);\n if (!resolved) {\n res.status(404).json({ error: `Assignment \"${id}\" not found` });\n return;\n }\n\n const { reason } = req.body || {};\n const transitionResult = await executeTransitionByDir(\n resolved.assignmentDir,\n command as any,\n {\n standalone: resolved.standalone,\n reason: typeof reason === 'string' ? reason : undefined,\n linkedTodosLookup,\n },\n );\n if (!transitionResult.success) {\n res.status(400).json({ error: transitionResult.message, fromStatus: transitionResult.fromStatus });\n return;\n }\n\n const detail = resolved.standalone\n ? await getAssignmentDetailById(projectsDir, assignmentsDir, id)\n : await getAssignmentDetail(projectsDir, resolved.projectSlug!, resolved.assignmentSlug);\n res.json({ assignment: detail, warnings: transitionResult.warnings ?? [] });\n } catch (error) {\n console.error('Error transitioning by id:', error);\n res.status(500).json({ error: `Failed to transition: ${(error as Error).message}` });\n }\n });\n\n return router;\n}\n\nfunction slugifyLocal(input: string): string {\n return input\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '') || 'untitled';\n}\n\ntype AssigneeValidation =\n | { ok: true; value: string | null }\n | { ok: false; error: string };\n\nfunction validateAssigneeBody(body: unknown): AssigneeValidation {\n if (!body || typeof body !== 'object') {\n return { ok: false, error: 'Body must include `assignee` (string or null).' };\n }\n const assignee = (body as Record<string, unknown>).assignee;\n if (assignee === null) return { ok: true, value: null };\n if (typeof assignee !== 'string') {\n return { ok: false, error: '`assignee` must be a string or null.' };\n }\n const trimmed = assignee.trim();\n if (trimmed.length === 0) return { ok: true, value: null };\n if (trimmed.length > 120) {\n return { ok: false, error: '`assignee` must be 120 characters or fewer.' };\n }\n return { ok: true, value: trimmed };\n}\n\nfunction buildBulkItemKey(raw: unknown, index: number): string {\n if (raw && typeof raw === 'object') {\n const item = raw as Record<string, unknown>;\n if (typeof item.id === 'string' && item.id.trim()) return item.id;\n if (typeof item.projectSlug === 'string' && typeof item.assignmentSlug === 'string') {\n return `${item.projectSlug}/${item.assignmentSlug}`;\n }\n }\n return `#${index}`;\n}\n\nasync function appendCommentTo(\n assignmentDir: string,\n assignmentRef: string,\n req: Request,\n res: Response,\n reloadDetail: () => Promise<unknown>,\n): Promise<void> {\n const commentsPath = resolve(assignmentDir, 'comments.md');\n const { body, author, type, replyTo } = req.body || {};\n if (!body || typeof body !== 'string' || !body.trim()) {\n res.status(400).json({ error: 'body is required' });\n return;\n }\n const commentType: CommentType = type && ['question', 'note', 'feedback'].includes(type) ? type : 'note';\n const timestamp = nowTimestamp();\n const entryAuthor = (typeof author === 'string' && author.trim()) ? author.trim() : 'human';\n\n let currentContent: string;\n let currentCount = 0;\n if (await fileExists(commentsPath)) {\n currentContent = await readFile(commentsPath, 'utf-8');\n const countMatch = currentContent.match(/^entryCount:\\s*(\\d+)/m);\n if (countMatch) currentCount = parseInt(countMatch[1], 10);\n } else {\n currentContent = renderComments({ assignment: assignmentRef, timestamp });\n }\n\n const comment: Comment = {\n id: generateId().split('-')[0],\n timestamp,\n author: entryAuthor,\n type: commentType,\n body,\n replyTo: typeof replyTo === 'string' && replyTo.trim() ? replyTo.trim() : undefined,\n resolved: commentType === 'question' ? false : undefined,\n };\n const entry = formatCommentEntry(comment);\n let next = setTopLevelField(currentContent, 'entryCount', String(currentCount + 1));\n next = setTopLevelField(next, 'updated', `\"${timestamp}\"`);\n if (next.includes('No comments yet.')) {\n next = next.replace('No comments yet.', entry.trimEnd());\n } else {\n next = `${next.trimEnd()}\\n\\n${entry}`;\n }\n await writeFileForce(commentsPath, next);\n const assignment = await reloadDetail();\n res.status(201).json({ assignment, comment: { id: comment.id } });\n}\n\nasync function toggleCommentResolvedAt(\n assignmentDir: string,\n commentId: string,\n req: Request,\n res: Response,\n reloadDetail: () => Promise<unknown>,\n): Promise<void> {\n const commentsPath = resolve(assignmentDir, 'comments.md');\n if (!(await fileExists(commentsPath))) {\n res.status(404).json({ error: 'Comments file not found' });\n return;\n }\n const { resolved: desired } = req.body || {};\n if (typeof desired !== 'boolean') {\n res.status(400).json({ error: 'resolved (boolean) is required' });\n return;\n }\n const content = await readFile(commentsPath, 'utf-8');\n const parsed = parseComments(content);\n const target = parsed.entries.find((e) => e.id === commentId);\n if (!target) {\n res.status(404).json({ error: `Comment ${commentId} not found` });\n return;\n }\n if (target.type !== 'question') {\n res.status(400).json({ error: 'Only questions can be resolved' });\n return;\n }\n const entryBlockRegex = new RegExp(\n `(^## ${commentId.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}[\\\\s\\\\S]*?)(\\\\*\\\\*Resolved:\\\\*\\\\*\\\\s*(?:true|false))`,\n 'm',\n );\n const next = content.replace(entryBlockRegex, (_m, preamble) => `${preamble}**Resolved:** ${desired ? 'true' : 'false'}`);\n if (next === content) {\n res.status(500).json({ error: 'Failed to update resolved flag' });\n return;\n }\n const withUpdated = setTopLevelField(next, 'updated', `\"${nowTimestamp()}\"`);\n await writeFileForce(commentsPath, withUpdated);\n const assignment = await reloadDetail();\n res.json({ assignment });\n}\n","import { randomUUID } from 'node:crypto';\n\nexport function generateId(): string {\n return randomUUID();\n}\n","import { spawn } from 'node:child_process';\nimport { readFile } from 'node:fs/promises';\nimport { updateAssignmentWorkspace } from '../lifecycle/frontmatter.js';\nimport { writeFileForce } from './fs.js';\n\nexport interface CreateWorktreeOptions {\n repository: string;\n branch: string;\n worktreePath: string;\n parentBranch: string;\n}\n\nfunction run(\n command: string,\n args: string[],\n cwd?: string,\n): Promise<{ code: number; stdout: string; stderr: string }> {\n return new Promise((resolvePromise) => {\n const child = spawn(command, args, { cwd, stdio: ['ignore', 'pipe', 'pipe'] });\n let stdout = '';\n let stderr = '';\n child.stdout.on('data', (chunk) => (stdout += chunk.toString()));\n child.stderr.on('data', (chunk) => (stderr += chunk.toString()));\n child.on('error', (err) => {\n resolvePromise({ code: -1, stdout, stderr: stderr + String(err) });\n });\n child.on('close', (code) => {\n resolvePromise({ code: code ?? -1, stdout, stderr });\n });\n });\n}\n\nexport class GitWorktreeError extends Error {\n constructor(message: string, public readonly stderr: string) {\n super(message);\n }\n}\n\n/**\n * Run `git -C <repository> worktree add -b <branch> <worktreePath> <parentBranch>`.\n * Throws GitWorktreeError on non-zero exit, preserving stderr.\n */\nexport async function createWorktree(opts: CreateWorktreeOptions): Promise<void> {\n const { repository, branch, worktreePath, parentBranch } = opts;\n const result = await run(\n 'git',\n ['-C', repository, 'worktree', 'add', '-b', branch, worktreePath, parentBranch],\n );\n if (result.code !== 0) {\n throw new GitWorktreeError(\n `git worktree add failed (exit ${result.code}): ${result.stderr.trim() || '(no stderr)'}`,\n result.stderr,\n );\n }\n}\n\nexport async function removeWorktree(\n repository: string,\n worktreePath: string,\n): Promise<{ ok: boolean; stderr: string }> {\n const result = await run(\n 'git',\n ['-C', repository, 'worktree', 'remove', '--force', worktreePath],\n );\n return { ok: result.code === 0, stderr: result.stderr };\n}\n\nexport async function deleteBranch(\n repository: string,\n branch: string,\n): Promise<{ ok: boolean; stderr: string }> {\n const result = await run('git', ['-C', repository, 'branch', '-D', branch]);\n return { ok: result.code === 0, stderr: result.stderr };\n}\n\nexport interface CreateWorktreeAndRecordOptions extends CreateWorktreeOptions {\n assignmentPath: string;\n}\n\n/**\n * Transactional helper:\n * 1. `git worktree add` — on failure throws, nothing else touched.\n * 2. Read assignment.md, update `workspace.*` fields, write back via writeFileForce.\n * 3. If (2) fails, `git worktree remove --force` to undo step 1. If cleanup fails,\n * throw an error naming both the file-write error AND the orphan worktree path.\n */\nexport async function createWorktreeAndRecord(\n opts: CreateWorktreeAndRecordOptions,\n): Promise<void> {\n const { assignmentPath, repository, branch, worktreePath, parentBranch } = opts;\n\n await createWorktree({ repository, branch, worktreePath, parentBranch });\n\n try {\n const content = await readFile(assignmentPath, 'utf-8');\n const updated = updateAssignmentWorkspace(content, {\n repository,\n worktreePath,\n branch,\n parentBranch,\n });\n await writeFileForce(assignmentPath, updated);\n } catch (writeErr) {\n const cleanup = await removeWorktree(repository, worktreePath);\n // Always try to delete the branch created by -b, even if worktree removal already failed.\n const branchCleanup = await deleteBranch(repository, branch);\n const writeMsg = writeErr instanceof Error ? writeErr.message : String(writeErr);\n throw new Error(\n formatRollbackError({\n writeMsg,\n worktreePath,\n branch,\n worktreeCleanup: cleanup,\n branchCleanup,\n }),\n );\n }\n}\n\nexport function formatRollbackError(opts: {\n writeMsg: string;\n worktreePath: string;\n branch: string;\n worktreeCleanup: { ok: boolean; stderr: string };\n branchCleanup: { ok: boolean; stderr: string };\n}): string {\n const { writeMsg, worktreePath, branch, worktreeCleanup, branchCleanup } = opts;\n const wtMsg = worktreeCleanup.stderr.trim() || '(no stderr)';\n const brMsg = branchCleanup.stderr.trim() || '(no stderr)';\n if (!worktreeCleanup.ok && !branchCleanup.ok) {\n return (\n `Failed to update assignment frontmatter AND failed to clean up both worktree and branch. ` +\n `Write error: ${writeMsg}. Worktree cleanup error: ${wtMsg}. Branch cleanup error: ${brMsg}. ` +\n `Orphan worktree at ${worktreePath} and orphan branch \"${branch}\" — remove them manually.`\n );\n }\n if (!worktreeCleanup.ok) {\n return (\n `Failed to update assignment frontmatter AND failed to clean up worktree. ` +\n `Write error: ${writeMsg}. Worktree cleanup error: ${wtMsg}. ` +\n `Orphan worktree at ${worktreePath} — remove it manually.`\n );\n }\n if (!branchCleanup.ok) {\n return (\n `Failed to update assignment frontmatter: ${writeMsg}. Rolled back git worktree at ${worktreePath}, ` +\n `but could not delete branch \"${branch}\": ${brMsg}. ` +\n `Remove the branch manually.`\n );\n }\n return `Failed to update assignment frontmatter: ${writeMsg}. Rolled back git worktree at ${worktreePath} and branch \"${branch}\".`;\n}\n","import { spawnSync } from 'node:child_process';\nimport { resolve } from 'node:path';\nimport { syntaurRoot } from './paths.js';\n\nexport interface WorktreeDefaults {\n repository: string;\n branch: string;\n parentBranch: string;\n worktreePath: string;\n}\n\n/**\n * Compute branch + worktree-path defaults for an assignment.\n *\n * Branch: `syntaur/<projectSlug>/<assignmentSlug>` when `projectSlug` is\n * non-empty, else `syntaur/<assignmentSlug>` (standalone).\n *\n * Worktree path: `<repository>/.worktrees/<branch>` when a repository is\n * known. Falls back to `~/.syntaur/worktrees/<project|standalone>/<slug>` only\n * when no repository can be detected — keeps callers from producing a path\n * under the wrong tree.\n *\n * `cwd` controls where `detectCurrentGitRoot()` / `detectCurrentBranch()`\n * run. Defaults to the current process cwd (existing CLI/TUI behavior);\n * server-side callers should pass an explicit repo path or `undefined` and\n * resolve the repo via other means before calling.\n */\nexport function computeWorktreeDefaults(opts: {\n projectSlug: string;\n assignmentSlug: string;\n existing: { repository: string | null; branch: string | null; parentBranch: string | null };\n cwd?: string;\n}): Partial<WorktreeDefaults> & { repository?: string } {\n const repository = opts.existing.repository ?? detectCurrentGitRoot(opts.cwd);\n const branch = opts.projectSlug\n ? `syntaur/${opts.projectSlug}/${opts.assignmentSlug}`\n : `syntaur/${opts.assignmentSlug}`;\n const parentBranch = opts.existing.parentBranch ?? detectCurrentBranch(opts.cwd) ?? 'main';\n const worktreeBase = repository\n ? resolve(repository, '.worktrees', branch)\n : resolve(\n syntaurRoot(),\n 'worktrees',\n opts.projectSlug || 'standalone',\n opts.assignmentSlug,\n );\n return {\n ...(repository ? { repository } : {}),\n branch,\n parentBranch,\n worktreePath: worktreeBase,\n };\n}\n\nfunction detectCurrentGitRoot(cwd?: string): string | undefined {\n const result = spawnSync('git', ['rev-parse', '--show-toplevel'], {\n cwd,\n encoding: 'utf-8',\n });\n if (result.status !== 0) return undefined;\n const out = result.stdout.trim();\n return out.length > 0 ? out : undefined;\n}\n\nfunction detectCurrentBranch(cwd?: string): string | undefined {\n const result = spawnSync('git', ['rev-parse', '--abbrev-ref', 'HEAD'], {\n cwd,\n encoding: 'utf-8',\n });\n if (result.status !== 0) return undefined;\n const out = result.stdout.trim();\n if (!out || out === 'HEAD') return undefined;\n return out;\n}\n","import { readdir, readFile } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { fileExists } from '../utils/fs.js';\nimport { parseProject, parseAssignmentFull } from './parser.js';\n\nexport interface RepositoryCandidate {\n path: string;\n source: 'project' | 'sibling';\n /** Slug of the sibling assignment that provided this repo. Null for `project`-sourced. */\n sourceAssignmentSlug: string | null;\n}\n\n/**\n * Collect repository candidates for a project-nested assignment.\n *\n * Order: project-configured first (in declaration order), then\n * sibling-harvested from other assignments in the same project. Deduped by\n * absolute path; the first occurrence wins. Missing project.md or assignments\n * directory returns `[]`.\n */\nexport async function getProjectRepositoryCandidates(\n projectsDir: string,\n projectSlug: string,\n): Promise<RepositoryCandidate[]> {\n const seen = new Set<string>();\n const out: RepositoryCandidate[] = [];\n\n const projectPath = resolve(projectsDir, projectSlug, 'project.md');\n if (await fileExists(projectPath)) {\n const project = parseProject(await readFile(projectPath, 'utf-8'));\n for (const raw of project.repositories) {\n const path = raw.trim();\n if (!path) continue;\n const abs = resolve(path);\n if (seen.has(abs)) continue;\n seen.add(abs);\n out.push({ path: abs, source: 'project', sourceAssignmentSlug: null });\n }\n }\n\n const assignmentsDir = resolve(projectsDir, projectSlug, 'assignments');\n if (await fileExists(assignmentsDir)) {\n const entries = await readdir(assignmentsDir, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n const assignmentMd = resolve(assignmentsDir, entry.name, 'assignment.md');\n if (!(await fileExists(assignmentMd))) continue;\n const parsed = parseAssignmentFull(await readFile(assignmentMd, 'utf-8'));\n const repo = parsed.workspace.repository?.trim();\n if (!repo) continue;\n const abs = resolve(repo);\n if (seen.has(abs)) continue;\n seen.add(abs);\n out.push({ path: abs, source: 'sibling', sourceAssignmentSlug: parsed.slug });\n }\n }\n\n return out;\n}\n\n/**\n * Collect repository candidates for a standalone assignment by harvesting\n * `workspace.repository` from sibling standalone assignments. Excludes the\n * assignment id passed in (typically the one the user is configuring).\n */\nexport async function getStandaloneRepositoryCandidates(\n assignmentsDir: string,\n excludeAssignmentId: string,\n): Promise<RepositoryCandidate[]> {\n if (!(await fileExists(assignmentsDir))) {\n return [];\n }\n\n const seen = new Set<string>();\n const out: RepositoryCandidate[] = [];\n\n const entries = await readdir(assignmentsDir, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n if (entry.name === excludeAssignmentId) continue;\n const assignmentMd = resolve(assignmentsDir, entry.name, 'assignment.md');\n if (!(await fileExists(assignmentMd))) continue;\n const parsed = parseAssignmentFull(await readFile(assignmentMd, 'utf-8'));\n const repo = parsed.workspace.repository?.trim();\n if (!repo) continue;\n const abs = resolve(repo);\n if (seen.has(abs)) continue;\n seen.add(abs);\n out.push({ path: abs, source: 'sibling', sourceAssignmentSlug: parsed.slug });\n }\n\n return out;\n}\n","export interface ToggleAcceptanceCriterionResult {\n content: string;\n}\n\nexport interface ToggleAcceptanceCriterionError {\n error: string;\n}\n\nfunction splitFrontmatter(content: string): { prefix: string; body: string } {\n const match = content.match(/^(---\\r?\\n[\\s\\S]*?\\r?\\n---\\r?\\n?)([\\s\\S]*)$/);\n if (!match) {\n return { prefix: '', body: content };\n }\n\n return {\n prefix: match[1],\n body: match[2],\n };\n}\n\nexport function toggleAcceptanceCriterion(\n content: string,\n index: number,\n checked: boolean,\n): ToggleAcceptanceCriterionResult | ToggleAcceptanceCriterionError {\n if (!Number.isInteger(index) || index < 0) {\n return { error: 'acceptance criteria index must be a non-negative integer' };\n }\n\n const { prefix, body } = splitFrontmatter(content);\n const lines = body.split('\\n');\n const sectionStart = lines.findIndex((line) => /^##\\s+Acceptance Criteria\\s*$/i.test(line.trim()));\n\n if (sectionStart === -1) {\n return { error: 'Acceptance Criteria section not found.' };\n }\n\n let sectionEnd = lines.length;\n for (let lineIndex = sectionStart + 1; lineIndex < lines.length; lineIndex += 1) {\n if (/^#{1,2}\\s+\\S/.test(lines[lineIndex].trim())) {\n sectionEnd = lineIndex;\n break;\n }\n }\n\n const checklistLines = lines\n .map((line, lineIndex) => ({ line, lineIndex }))\n .filter(({ lineIndex, line }) =>\n lineIndex > sectionStart\n && lineIndex < sectionEnd\n && /^\\s*[-*]\\s+\\[( |x|X)\\]\\s+.*$/.test(line),\n );\n\n const target = checklistLines[index];\n if (!target) {\n return { error: `Acceptance criteria item ${index} not found.` };\n }\n\n const nextLine = target.line.replace(\n /^(\\s*[-*]\\s+\\[)( |x|X)(\\]\\s+.*)$/,\n `$1${checked ? 'x' : ' '}$3`,\n );\n\n lines[target.lineIndex] = nextLine;\n return {\n content: `${prefix}${lines.join('\\n')}`,\n };\n}\n","export { renderConfig } from './config.js';\nexport type { ConfigParams } from './config.js';\n\nexport { renderManifest } from './manifest.js';\nexport type { ManifestParams } from './manifest.js';\n\nexport { renderProject } from './project.js';\nexport type { ProjectParams } from './project.js';\n\nexport { renderAssignment } from './assignment.js';\nexport type { AssignmentParams } from './assignment.js';\n\nexport { renderPlan } from './plan.js';\nexport type { PlanParams } from './plan.js';\n\nexport { renderScratchpad } from './scratchpad.js';\nexport type { ScratchpadParams } from './scratchpad.js';\n\nexport { renderHandoff } from './handoff.js';\nexport type { HandoffParams } from './handoff.js';\n\nexport { renderSessionSummary } from './session-summary.js';\nexport type { SessionSummaryParams } from './session-summary.js';\n\nexport { renderProgress, formatProgressEntry } from './progress.js';\nexport type { ProgressParams } from './progress.js';\n\nexport { renderComments, formatCommentEntry } from './comments.js';\nexport type { CommentsParams, Comment, CommentType } from './comments.js';\n\nexport { renderDecisionRecord } from './decision-record.js';\nexport type { DecisionRecordParams } from './decision-record.js';\n\nexport {\n renderIndexAssignments,\n renderIndexPlans,\n renderIndexDecisions,\n renderStatus,\n renderResourcesIndex,\n renderMemoriesIndex,\n renderMemoryStub,\n renderResourceStub,\n} from './index-stubs.js';\nexport type { IndexStubParams, MemoryStubParams, ResourceStubParams } from './index-stubs.js';\n\nexport { renderPlaybook } from './playbook.js';\nexport type { PlaybookParams } from './playbook.js';\n\nexport { renderCursorProtocol, renderCursorAssignment } from './cursor-rules.js';\nexport type { CursorAssignmentParams } from './cursor-rules.js';\n\nexport { renderCodexAgents } from './codex-agents.js';\nexport type { CodexAgentsParams } from './codex-agents.js';\n\nexport { renderOpenCodeConfig } from './opencode-config.js';\nexport type { OpenCodeConfigParams } from './opencode-config.js';\n","export interface ManifestParams {\n slug: string;\n timestamp: string;\n}\n\nexport function renderManifest(params: ManifestParams): string {\n return `---\nversion: \"2.0\"\nproject: ${params.slug}\ngenerated: \"${params.timestamp}\"\n---\n\n# Project: ${params.slug}\n\n## Overview\n- [Project Overview](./project.md)\n\n## Indexes\n- [Assignments](./_index-assignments.md)\n- [Plans](./_index-plans.md)\n- [Decision Records](./_index-decisions.md)\n- [Status](./_status.md)\n- [Resources](./resources/_index.md)\n- [Memories](./memories/_index.md)\n`;\n}\n","export function escapeYamlString(value: string): string {\n if (value.includes('\\n') || value.includes('\\r')) {\n throw new Error(\n `YAML string values must be single-line. Got: \"${value.slice(0, 50)}...\"`,\n );\n }\n const escaped = value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"');\n return `\"${escaped}\"`;\n}\n","import { escapeYamlString } from '../utils/yaml.js';\n\nexport interface ProjectParams {\n id: string;\n slug: string;\n title: string;\n timestamp: string;\n workspace?: string;\n /**\n * Repository paths the project spans. Each entry is YAML-escaped on\n * render so paths with spaces / colons / quotes don't corrupt the\n * frontmatter. Empty by default for new projects.\n */\n repositories?: string[];\n}\n\nfunction renderRepositoriesBlock(repos: string[] | undefined): string {\n if (!repos || repos.length === 0) {\n return 'repositories: []';\n }\n return ['repositories:', ...repos.map((p) => ` - ${escapeYamlString(p)}`)].join('\\n');\n}\n\nexport function renderProject(params: ProjectParams): string {\n const safeTitle = escapeYamlString(params.title);\n const workspaceLine = params.workspace ? `\\nworkspace: ${params.workspace}` : '';\n const repositoriesBlock = renderRepositoriesBlock(params.repositories);\n return `---\nid: ${params.id}\nslug: ${params.slug}\ntitle: ${safeTitle}\narchived: false\narchivedAt: null\narchivedReason: null\ncreated: \"${params.timestamp}\"\nupdated: \"${params.timestamp}\"\nexternalIds: []\ntags: []\n${repositoriesBlock}${workspaceLine}\n---\n\n# ${params.title}\n\n## Overview\n\n<!-- Describe the project goal, context, and success criteria here. -->\n\n## Notes\n\n<!-- Optional human notes, updates, or context. -->\n`;\n}\n","import { escapeYamlString } from '../utils/yaml.js';\n\nexport interface AssignmentParams {\n id: string;\n slug: string;\n title: string;\n timestamp: string;\n priority: 'low' | 'medium' | 'high' | 'critical';\n dependsOn: string[];\n links: string[];\n project?: string | null;\n workspaceGroup?: string | null;\n type?: string;\n includeTodos?: boolean;\n status?: string;\n acceptanceCriteria?: string[];\n}\n\nexport function renderAssignment(params: AssignmentParams): string {\n const safeTitle = escapeYamlString(params.title);\n const dependsOnYaml =\n params.dependsOn.length === 0\n ? 'dependsOn: []'\n : `dependsOn:\\n - ${params.dependsOn.join('\\n - ')}`;\n const linksYaml =\n params.links.length === 0\n ? 'links: []'\n : `links:\\n - ${params.links.join('\\n - ')}`;\n const projectYaml = `project: ${params.project == null ? 'null' : params.project}`;\n const workspaceGroupLine = params.workspaceGroup\n ? `\\nworkspaceGroup: ${params.workspaceGroup}`\n : '';\n const typeYaml = `type: ${params.type ?? 'feature'}`;\n\n const criteriaLines = params.acceptanceCriteria && params.acceptanceCriteria.length > 0\n ? params.acceptanceCriteria.map((c) => `- [ ] ${c.replace(/\\n/g, ' ').trim()}`).join('\\n')\n : `- [ ] <!-- criterion 1 -->\n- [ ] <!-- criterion 2 -->\n- [ ] <!-- criterion 3 -->`;\n\n const todosSection = params.includeTodos\n ? `## Todos\n\n<!--\nChecklist of work items for this assignment. Items may be simple tasks\nor a markdown link to a plan file (e.g., \"- [ ] Execute [plan](./plan.md)\").\nWhen a plan is superseded by a new one, mark the old todo as:\n - [x] ~~Execute [old plan](./plan.md)~~ (superseded by plan-v2)\nNever delete superseded todos — preserve the history.\n-->\n\n`\n : '';\n\n return `---\nid: ${params.id}\nslug: ${params.slug}\ntitle: ${safeTitle}\n${projectYaml}${workspaceGroupLine}\n${typeYaml}\nstatus: ${params.status ?? 'draft'}\npriority: ${params.priority}\ncreated: \"${params.timestamp}\"\nupdated: \"${params.timestamp}\"\nassignee: null\nexternalIds: []\n${dependsOnYaml}\n${linksYaml}\nblockedReason: null\nworkspace:\n repository: null\n worktreePath: null\n branch: null\n parentBranch: null\ntags: []\n---\n\n# ${params.title}\n\n## Objective\n\n<!-- Clear description of what needs to be done and why. -->\n\n## Acceptance Criteria\n\n${criteriaLines}\n\n${todosSection}## Context\n\n<!-- Links to relevant docs, code, or other assignments. -->\n\n## Links\n\n- [Progress](./progress.md)\n- [Comments](./comments.md)\n- [Scratchpad](./scratchpad.md)\n- [Handoff](./handoff.md) — cross-ticket outbound\n- [Decision Record](./decision-record.md)\n- [Sessions](./sessions/) — per-session continuity summaries (one \\`<session-id>/summary.md\\` per session)\n`;\n}\n","export interface ScratchpadParams {\n assignmentSlug: string;\n timestamp: string;\n}\n\nexport function renderScratchpad(params: ScratchpadParams): string {\n return `---\nassignment: ${params.assignmentSlug}\nupdated: \"${params.timestamp}\"\n---\n\n# Scratchpad\n\nNo working notes yet.\n`;\n}\n","export interface HandoffParams {\n assignmentSlug: string;\n timestamp: string;\n}\n\nexport function renderHandoff(params: HandoffParams): string {\n return `---\nassignment: ${params.assignmentSlug}\nupdated: \"${params.timestamp}\"\nhandoffCount: 0\n---\n\n# Handoff Log\n\nNo handoffs recorded yet.\n`;\n}\n","export interface ProgressParams {\n assignment: string;\n timestamp: string;\n}\n\nexport function renderProgress(params: ProgressParams): string {\n return `---\nassignment: ${params.assignment}\nentryCount: 0\ngenerated: \"${params.timestamp}\"\nupdated: \"${params.timestamp}\"\n---\n\n# Progress\n\nNo progress yet.\n`;\n}\n\nexport function formatProgressEntry(body: string, timestamp: string): string {\n const trimmed = body.trim();\n return `## ${timestamp}\\n\\n${trimmed}\\n`;\n}\n","export interface CommentsParams {\n assignment: string;\n timestamp: string;\n}\n\nexport type CommentType = 'question' | 'note' | 'feedback';\n\nexport interface Comment {\n id: string;\n timestamp: string;\n author: string;\n type: CommentType;\n body: string;\n replyTo?: string;\n resolved?: boolean;\n}\n\nexport function renderComments(params: CommentsParams): string {\n return `---\nassignment: ${params.assignment}\nentryCount: 0\ngenerated: \"${params.timestamp}\"\nupdated: \"${params.timestamp}\"\n---\n\n# Comments\n\nNo comments yet.\n`;\n}\n\nexport function formatCommentEntry(comment: Comment): string {\n const lines: string[] = [];\n lines.push(`## ${comment.id}`);\n lines.push('');\n lines.push(`**Recorded:** ${comment.timestamp}`);\n lines.push(`**Author:** ${comment.author}`);\n lines.push(`**Type:** ${comment.type}`);\n if (comment.replyTo) {\n lines.push(`**Reply to:** ${comment.replyTo}`);\n }\n if (comment.type === 'question') {\n lines.push(`**Resolved:** ${comment.resolved ? 'true' : 'false'}`);\n }\n lines.push('');\n lines.push(comment.body.trim());\n lines.push('');\n return lines.join('\\n');\n}\n","export interface DecisionRecordParams {\n assignmentSlug: string;\n timestamp: string;\n}\n\nexport function renderDecisionRecord(\n params: DecisionRecordParams,\n): string {\n return `---\nassignment: ${params.assignmentSlug}\nupdated: \"${params.timestamp}\"\ndecisionCount: 0\n---\n\n# Decision Record\n\nNo decisions recorded yet.\n`;\n}\n","import { escapeYamlString } from '../utils/yaml.js';\n\nexport interface IndexStubParams {\n slug: string;\n title: string;\n timestamp: string;\n}\n\nexport interface MemoryStubParams {\n /** File slug (filename without `.md`). */\n slug: string;\n name: string;\n /** Project slug — written into frontmatter for traceability. */\n projectSlug: string;\n timestamp: string;\n}\n\nexport type ResourceStubParams = MemoryStubParams;\n\nexport function renderMemoryStub(params: MemoryStubParams): string {\n return `---\ntype: memory\nname: ${escapeYamlString(params.name)}\nsource: claude\nsourceAssignment: null\nrelatedAssignments: []\nscope: project\ncreated: \"${params.timestamp}\"\nupdated: \"${params.timestamp}\"\ntags: []\n---\n\n# ${params.name}\n\n`;\n}\n\nexport function renderResourceStub(params: ResourceStubParams): string {\n return `---\ntype: resource\nname: ${escapeYamlString(params.name)}\nsource: claude\ncategory: documentation\nsourceUrl: null\nsourceAssignment: null\nrelatedAssignments: []\ncreated: \"${params.timestamp}\"\nupdated: \"${params.timestamp}\"\n---\n\n# ${params.name}\n\n`;\n}\n\nexport function renderIndexAssignments(params: IndexStubParams): string {\n return `---\nproject: ${params.slug}\ngenerated: \"${params.timestamp}\"\ntotal: 0\nby_status:\n pending: 0\n in_progress: 0\n blocked: 0\n review: 0\n completed: 0\n failed: 0\n---\n\n# Assignments\n\n| Slug | Title | Status | Priority | Assignee | Dependencies | Updated |\n|------|-------|--------|----------|----------|--------------|---------|\n`;\n}\n\nexport function renderIndexPlans(params: IndexStubParams): string {\n return `---\nproject: ${params.slug}\ngenerated: \"${params.timestamp}\"\n---\n\n# Plans\n\n| Assignment | Plan Status | Updated |\n|------------|-------------|---------|\n`;\n}\n\nexport function renderIndexDecisions(params: IndexStubParams): string {\n return `---\nproject: ${params.slug}\ngenerated: \"${params.timestamp}\"\n---\n\n# Decision Records\n\n| Assignment | Count | Latest Decision | Latest Status | Updated |\n|------------|-------|-----------------|---------------|---------|\n`;\n}\n\nexport function renderStatus(params: IndexStubParams): string {\n return `---\nproject: ${params.slug}\ngenerated: \"${params.timestamp}\"\nstatus: pending\nprogress:\n total: 0\n completed: 0\n in_progress: 0\n blocked: 0\n pending: 0\n review: 0\n failed: 0\nneedsAttention:\n blockedCount: 0\n failedCount: 0\n openQuestions: 0\n---\n\n# Project Status: ${params.title}\n\n**Status:** pending\n**Progress:** 0/0 assignments complete\n\n## Assignments\n\nNo assignments yet.\n\n## Dependency Graph\n\nNo dependencies yet.\n\n## Needs Attention\n\n- **0 blocked** assignments\n- **0 failed** assignments\n- **0 unanswered** questions\n`;\n}\n\nexport function renderResourcesIndex(params: IndexStubParams): string {\n return `---\nproject: ${params.slug}\ngenerated: \"${params.timestamp}\"\ntotal: 0\n---\n\n# Resources\n\n| Name | Category | Source | Related Assignments | Updated |\n|------|----------|--------|---------------------|---------|\n`;\n}\n\nexport function renderMemoriesIndex(params: IndexStubParams): string {\n return `---\nproject: ${params.slug}\ngenerated: \"${params.timestamp}\"\ntotal: 0\n---\n\n# Memories\n\n| Name | Source | Scope | Source Assignment | Updated |\n|------|--------|-------|------------------|---------|\n`;\n}\n","import { escapeYamlString } from '../utils/yaml.js';\n\nexport interface PlaybookParams {\n slug: string;\n name: string;\n description: string;\n whenToUse?: string;\n timestamp: string;\n}\n\nexport function renderPlaybook(params: PlaybookParams): string {\n const whenToUse = params.whenToUse\n ? escapeYamlString(params.whenToUse)\n : 'null';\n return `---\nname: ${escapeYamlString(params.name)}\nslug: ${params.slug}\ndescription: ${escapeYamlString(params.description)}\nwhen_to_use: ${whenToUse}\ncreated: \"${params.timestamp}\"\nupdated: \"${params.timestamp}\"\ntags: []\n---\n\n# ${params.name}\n\n<!-- Write imperative rules and workflows here. Keep it under 50 lines. -->\n`;\n}\n","import { Router } from 'express';\nimport {\n registerSession,\n removeSession,\n listSessionFiles,\n readSessionFile,\n updateLastRefreshed,\n setOverride,\n sanitizeSessionName,\n} from './servers.js';\nimport {\n scanAllSessions,\n scanSingleSession,\n clearScanCache,\n} from './scanner.js';\n\nexport function createServersRouter(\n serversDir: string,\n projectsDir: string,\n assignmentsDir?: string,\n): Router {\n const router = Router();\n\n // GET /api/servers — all sessions with cached scan data\n router.get('/', async (_req, res) => {\n try {\n const result = await scanAllSessions(serversDir, projectsDir, { assignmentsDir });\n res.json(result);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Scan failed' });\n }\n });\n\n // GET /api/servers/:name — single session\n router.get('/:name', async (req, res) => {\n try {\n const session = await scanSingleSession(serversDir, projectsDir, req.params.name, { assignmentsDir });\n if (!session) {\n res.status(404).json({ error: 'Session not found' });\n return;\n }\n res.json(session);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Scan failed' });\n }\n });\n\n // POST /api/servers — register a new session\n router.post('/', async (req, res) => {\n try {\n const { name } = req.body;\n if (!name || typeof name !== 'string') {\n res.status(400).json({ error: 'name is required' });\n return;\n }\n const sanitized = sanitizeSessionName(name);\n const existing = await readSessionFile(serversDir, sanitized);\n if (existing) {\n res.status(409).json({ error: `Session \"${sanitized}\" already registered` });\n return;\n }\n await registerSession(serversDir, name);\n clearScanCache();\n res.status(201).json({ name: sanitized });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Registration failed' });\n }\n });\n\n // DELETE /api/servers/:name — unregister\n router.delete('/:name', async (req, res) => {\n try {\n const data = await readSessionFile(serversDir, req.params.name);\n if (!data) {\n res.status(404).json({ error: 'Session not found' });\n return;\n }\n await removeSession(serversDir, req.params.name);\n clearScanCache();\n res.json({ removed: req.params.name });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Removal failed' });\n }\n });\n\n // POST /api/servers/refresh — fresh scan all (must be before /:name/refresh)\n router.post('/refresh', async (_req, res) => {\n try {\n const names = await listSessionFiles(serversDir);\n for (const name of names) {\n await updateLastRefreshed(serversDir, name);\n }\n clearScanCache();\n const result = await scanAllSessions(serversDir, projectsDir, { bypassCache: true, assignmentsDir });\n res.json(result);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Refresh failed' });\n }\n });\n\n // POST /api/servers/:name/refresh — fresh scan one\n router.post('/:name/refresh', async (req, res) => {\n try {\n const data = await readSessionFile(serversDir, req.params.name);\n if (!data) {\n res.status(404).json({ error: 'Session not found' });\n return;\n }\n await updateLastRefreshed(serversDir, req.params.name);\n clearScanCache();\n const session = await scanSingleSession(serversDir, projectsDir, req.params.name, { assignmentsDir });\n res.json(session);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Refresh failed' });\n }\n });\n\n // PATCH /api/servers/:name/panes/:windowIndex/:paneIndex/assignment — manual link\n router.patch('/:name/panes/:windowIndex/:paneIndex/assignment', async (req, res) => {\n try {\n const { name, windowIndex, paneIndex } = req.params;\n const data = await readSessionFile(serversDir, name);\n if (!data) {\n res.status(404).json({ error: 'Session not found' });\n return;\n }\n const body = req.body;\n if (body === null || (body && body.project && body.assignment)) {\n await setOverride(\n serversDir,\n name,\n parseInt(windowIndex, 10),\n parseInt(paneIndex, 10),\n body,\n );\n clearScanCache();\n res.json({ updated: true });\n } else {\n res.status(400).json({ error: 'Body must be { project, assignment } or null' });\n }\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Update failed' });\n }\n });\n\n return router;\n}\n","import { Router } from 'express';\nimport { resolve } from 'node:path';\nimport {\n listAllSessions,\n listProjectSessions,\n appendSession,\n updateSessionStatus,\n deleteSessions,\n reconcileActiveSessions,\n getSessionById,\n} from './agent-sessions.js';\nimport { fileExists } from '../utils/fs.js';\nimport { derivePathFromTranscript } from '../utils/transcript.js';\nimport { enrichSessions } from './session-liveness.js';\nimport { getAgents, readConfig } from '../utils/config.js';\nimport { captureProcessStartedAt } from '../utils/process-info.js';\nimport type { AgentSessionStatus, WsMessage } from './types.js';\n\nexport function createAgentSessionsRouter(\n projectsDir: string,\n broadcast?: (msg: WsMessage) => void,\n assignmentsDir?: string,\n): Router {\n const router = Router();\n\n // GET /api/agent-sessions — all sessions across all projects\n router.get('/', async (_req, res) => {\n try {\n await reconcileActiveSessions(projectsDir, assignmentsDir);\n const sessions = await listAllSessions(projectsDir);\n const agents = getAgents(await readConfig());\n res.json({\n sessions: enrichSessions(sessions, agents),\n generatedAt: new Date().toISOString(),\n });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to list sessions' });\n }\n });\n\n // GET /api/agent-sessions/:projectSlug — sessions for one project\n router.get('/:projectSlug', async (req, res) => {\n try {\n const { projectSlug } = req.params;\n const assignment = req.query.assignment as string | undefined;\n const projectDir = resolve(projectsDir, projectSlug);\n if (!(await fileExists(projectDir))) {\n res.status(404).json({ error: `Project \"${projectSlug}\" not found` });\n return;\n }\n await reconcileActiveSessions(projectsDir, assignmentsDir);\n const sessions = await listProjectSessions(projectsDir, projectSlug, assignment);\n const agents = getAgents(await readConfig());\n res.json({\n sessions: enrichSessions(sessions, agents),\n generatedAt: new Date().toISOString(),\n });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to list sessions' });\n }\n });\n\n // POST /api/agent-sessions — register a new session\n router.post('/', async (req, res) => {\n try {\n const { projectSlug, assignmentSlug, agent, sessionId, path, description, transcriptPath, pid: rawPid } =\n req.body;\n\n if (!agent) {\n res.status(400).json({ error: 'agent is required' });\n return;\n }\n\n if (!sessionId) {\n res.status(400).json({\n error:\n 'sessionId is required. Pass the real agent-generated session id — do not synthesize one.',\n });\n return;\n }\n\n if (projectSlug) {\n const projectDir = resolve(projectsDir, projectSlug);\n if (!(await fileExists(projectDir))) {\n res.status(404).json({ error: `Project \"${projectSlug}\" not found` });\n return;\n }\n }\n\n // Prefer the launch cwd recorded inside the transcript over whatever\n // path the caller posted — the transcript is what determines where\n // Claude Code files the conversation, and the only directory from\n // which `claude --resume <id>` will find it.\n const derivedPath = await derivePathFromTranscript(transcriptPath);\n const recordedPath = derivedPath ?? path ?? '';\n\n const pid =\n typeof rawPid === 'number' && Number.isFinite(rawPid) && rawPid > 0\n ? rawPid\n : null;\n const pidStartedAt = pid !== null ? captureProcessStartedAt(pid) : null;\n\n const session = {\n projectSlug: projectSlug || null,\n assignmentSlug: assignmentSlug || null,\n agent,\n sessionId,\n started: new Date().toISOString(),\n status: 'active' as AgentSessionStatus,\n path: recordedPath,\n description: description || null,\n transcriptPath: transcriptPath || null,\n pid,\n pidStartedAt,\n };\n\n await appendSession('', session);\n broadcast?.({ type: 'agent-sessions-updated', timestamp: new Date().toISOString() });\n res.status(201).json({ sessionId });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Registration failed' });\n }\n });\n\n // PATCH /api/agent-sessions/:sessionId — terminal-only status update.\n // Used by the Mark-stopped affordance on session rows; the\n // /:sessionId/status route below remains available for full status updates\n // (non-terminal allowed) used by other internal flows. Express precedence\n // matches the more specific /:sessionId/status route first.\n router.patch('/:sessionId', async (req, res) => {\n try {\n const { sessionId } = req.params;\n const status = (req.body ?? {}).status;\n if (status !== 'stopped' && status !== 'completed') {\n res.status(400).json({\n error: 'status must be one of: stopped, completed',\n });\n return;\n }\n if (!getSessionById(sessionId)) {\n res.status(404).json({ error: `Session \"${sessionId}\" not found` });\n return;\n }\n const updated = await updateSessionStatus('', sessionId, status);\n if (!updated) {\n res.status(404).json({ error: `Session \"${sessionId}\" not found` });\n return;\n }\n broadcast?.({ type: 'agent-sessions-updated', timestamp: new Date().toISOString() });\n res.json({ updated: true });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Update failed' });\n }\n });\n\n // PATCH /api/agent-sessions/:sessionId/status — update session status\n router.patch('/:sessionId/status', async (req, res) => {\n try {\n const { sessionId } = req.params;\n const { status } = req.body;\n\n if (!status) {\n res.status(400).json({ error: 'status is required' });\n return;\n }\n\n if (!['active', 'completed', 'stopped'].includes(status)) {\n res.status(400).json({ error: 'status must be active, completed, or stopped' });\n return;\n }\n\n const updated = await updateSessionStatus('', sessionId, status);\n if (!updated) {\n res.status(404).json({ error: `Session \"${sessionId}\" not found` });\n return;\n }\n\n broadcast?.({ type: 'agent-sessions-updated', timestamp: new Date().toISOString() });\n res.json({ updated: true });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Update failed' });\n }\n });\n\n // DELETE /api/agent-sessions — delete one or more sessions\n router.delete('/', async (req, res) => {\n try {\n const { sessionIds } = req.body;\n\n if (!Array.isArray(sessionIds) || sessionIds.length === 0) {\n res.status(400).json({ error: 'sessionIds must be a non-empty array' });\n return;\n }\n\n const deleted = await deleteSessions(sessionIds);\n broadcast?.({ type: 'agent-sessions-updated', timestamp: new Date().toISOString() });\n res.json({ deleted });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Delete failed' });\n }\n });\n\n return router;\n}\n","import { open } from 'node:fs/promises';\n\n// Cap on lines we'll scan looking for `cwd`. The launch cwd is recorded in the\n// first few entries of every Claude Code transcript; 50 lines is generous\n// enough to absorb leading non-JSON noise (blank lines, permission-mode rows\n// without a cwd) without slurping multi-MB transcripts into memory.\nconst MAX_LINES_SCANNED = 50;\n\n/**\n * Read the first `cwd` field from a Claude Code transcript JSONL file.\n *\n * Claude Code derives `~/.claude/projects/<encoded-cwd>/<session-id>.jsonl`\n * from the *launch* cwd of the session, and `claude --resume <id>` only finds\n * the transcript when invoked from a matching cwd. The transcript itself is\n * therefore the authoritative source of truth for \"which directory does this\n * session belong to\" — read it once, prefer it over whatever a registering\n * caller might have happened to be sitting in.\n *\n * Returns `null` when the path is empty, the file doesn't exist or can't be\n * read, no JSON line within the scan window contains a `cwd` field, or the\n * value is not a non-empty string. Never throws.\n */\nexport async function derivePathFromTranscript(\n transcriptPath: string | null | undefined,\n): Promise<string | null> {\n if (!transcriptPath) return null;\n\n let handle;\n try {\n handle = await open(transcriptPath, 'r');\n } catch {\n return null;\n }\n\n try {\n const stream = handle.createReadStream({ encoding: 'utf-8' });\n let buffer = '';\n let scanned = 0;\n\n for await (const chunk of stream) {\n buffer += chunk;\n let nl = buffer.indexOf('\\n');\n while (nl !== -1) {\n const line = buffer.slice(0, nl);\n buffer = buffer.slice(nl + 1);\n\n const cwd = extractCwd(line);\n if (cwd) {\n stream.destroy();\n return cwd;\n }\n\n scanned++;\n if (scanned >= MAX_LINES_SCANNED) {\n stream.destroy();\n return null;\n }\n nl = buffer.indexOf('\\n');\n }\n }\n\n // Trailing line without a newline (rare, but handle it).\n if (buffer.length > 0) {\n const cwd = extractCwd(buffer);\n if (cwd) return cwd;\n }\n return null;\n } finally {\n await handle.close().catch(() => {});\n }\n}\n\nfunction extractCwd(line: string): string | null {\n const trimmed = line.trim();\n if (trimmed.length === 0 || trimmed[0] !== '{') return null;\n try {\n const parsed = JSON.parse(trimmed) as { cwd?: unknown };\n if (typeof parsed.cwd === 'string' && parsed.cwd.length > 0) {\n return parsed.cwd;\n }\n } catch {\n // Non-JSON or truncated line — keep scanning.\n }\n return null;\n}\n","import { execFileSync } from 'node:child_process';\n\n/**\n * Capture the start-time of a process via `ps -o lstart=`. Used as the\n * recycling-defense baseline for session liveness detection: the server later\n * compares this stored start-time to the current `ps -o lstart=` output, so a\n * recycled PID with the same number but different start-time correctly\n * reports as not-live.\n *\n * Returns null when `ps` fails (process already gone, or `ps` not on PATH).\n * Null is the expected sentinel for \"no recycling baseline available\" — the\n * liveness check trusts `kill -0` alone in that case (small false-positive\n * risk on PID reuse, acceptable).\n */\nexport function captureProcessStartedAt(pid: number): string | null {\n if (!Number.isFinite(pid) || pid <= 0) return null;\n try {\n const out = execFileSync('ps', ['-o', 'lstart=', '-p', String(pid)], {\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n });\n const trimmed = out.trim();\n return trimmed === '' ? null : trimmed;\n } catch {\n return null;\n }\n}\n","import { Router } from 'express';\nimport {\n readConfig,\n writeAgentsConfig,\n deleteAgentsConfig,\n AgentConfigError,\n} from '../utils/config.js';\nimport {\n BUILTIN_AGENTS,\n PROMPT_ARG_POSITIONS,\n type AgentConfig,\n type PromptArgPosition,\n} from '../utils/agents-schema.js';\n\nexport interface AgentFieldError {\n id?: string;\n index?: number;\n field: string;\n message: string;\n}\n\nexport function mapAgentErrorToFieldErrors(\n err: AgentConfigError,\n): { error: string; fieldErrors?: AgentFieldError[] } {\n const message = err.message;\n\n let match = message.match(/^agent id \"([^\"]*)\" is invalid/);\n if (match) {\n return {\n error: message,\n fieldErrors: [\n { id: match[1], field: 'id', message: 'must match /^[a-z0-9][a-z0-9_-]*$/' },\n ],\n };\n }\n\n match = message.match(/^duplicate agent id \"([^\"]+)\"/);\n if (match) {\n return {\n error: message,\n fieldErrors: [{ id: match[1], field: 'id', message: 'duplicate id' }],\n };\n }\n\n match = message.match(/^agent \"([^\"]+)\" has empty label/);\n if (match) {\n return {\n error: message,\n fieldErrors: [{ id: match[1], field: 'label', message: 'label is required' }],\n };\n }\n\n match = message.match(/^agent(?: \"([^\"]+)\")? has empty command/);\n if (match) {\n return {\n error: message,\n fieldErrors: [{ id: match[1], field: 'command', message: 'command is required' }],\n };\n }\n\n match = message.match(/^agent(?: \"([^\"]+)\")? command \"[^\"]*\" is a relative path/);\n if (match) {\n return {\n error: message,\n fieldErrors: [\n { id: match[1], field: 'command', message: 'use absolute path or bare name' },\n ],\n };\n }\n\n match = message.match(/^agent \"([^\"]+)\" has invalid promptArgPosition/);\n if (match) {\n return {\n error: message,\n fieldErrors: [\n {\n id: match[1],\n field: 'promptArgPosition',\n message: 'must be first|last|none',\n },\n ],\n };\n }\n\n if (/^more than one agent is marked default/.test(message)) {\n return {\n error: message,\n fieldErrors: [{ field: 'default', message: 'only one agent may be default' }],\n };\n }\n\n return { error: message };\n}\n\nfunction coerceAgentRow(\n raw: unknown,\n index: number,\n): { ok: true; value: AgentConfig } | { ok: false; status: number; body: { error: string; fieldErrors?: AgentFieldError[] } } {\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {\n return {\n ok: false,\n status: 400,\n body: {\n error: `agents[${index}] must be an object`,\n fieldErrors: [{ index, field: 'row', message: `agents[${index}] must be an object` }],\n },\n };\n }\n const entry = raw as Record<string, unknown>;\n\n if (typeof entry.id !== 'string' || entry.id.length === 0) {\n return {\n ok: false,\n status: 400,\n body: {\n error: `agents[${index}].id must be a non-empty string`,\n fieldErrors: [{ index, field: 'id', message: 'id must be a non-empty string' }],\n },\n };\n }\n const id = entry.id;\n\n if (typeof entry.label !== 'string') {\n return {\n ok: false,\n status: 400,\n body: {\n error: `agents[${index}].label must be a string`,\n fieldErrors: [{ id, field: 'label', message: 'label must be a string' }],\n },\n };\n }\n\n if (typeof entry.command !== 'string') {\n return {\n ok: false,\n status: 400,\n body: {\n error: `agents[${index}].command must be a string`,\n fieldErrors: [{ id, field: 'command', message: 'command must be a string' }],\n },\n };\n }\n\n const cleaned: AgentConfig = {\n id,\n label: entry.label,\n command: entry.command,\n };\n\n if (entry.args !== undefined) {\n if (!Array.isArray(entry.args) || entry.args.some((v) => typeof v !== 'string')) {\n return {\n ok: false,\n status: 400,\n body: {\n error: `agents[${index}].args must be an array of strings`,\n fieldErrors: [{ id, field: 'args', message: 'args must be an array of strings' }],\n },\n };\n }\n cleaned.args = entry.args as string[];\n }\n\n if (entry.promptArgPosition !== undefined) {\n if (\n typeof entry.promptArgPosition !== 'string' ||\n !PROMPT_ARG_POSITIONS.includes(entry.promptArgPosition as PromptArgPosition)\n ) {\n return {\n ok: false,\n status: 400,\n body: {\n error: `agents[${index}].promptArgPosition must be first|last|none`,\n fieldErrors: [\n { id, field: 'promptArgPosition', message: 'must be first|last|none' },\n ],\n },\n };\n }\n cleaned.promptArgPosition = entry.promptArgPosition as PromptArgPosition;\n }\n\n if (entry.resolveFromShellAliases !== undefined) {\n if (typeof entry.resolveFromShellAliases !== 'boolean') {\n return {\n ok: false,\n status: 400,\n body: {\n error: `agents[${index}].resolveFromShellAliases must be a boolean`,\n fieldErrors: [\n { id, field: 'resolveFromShellAliases', message: 'must be a boolean' },\n ],\n },\n };\n }\n cleaned.resolveFromShellAliases = entry.resolveFromShellAliases;\n }\n\n if (entry.default !== undefined) {\n if (typeof entry.default !== 'boolean') {\n return {\n ok: false,\n status: 400,\n body: {\n error: `agents[${index}].default must be a boolean`,\n fieldErrors: [{ id, field: 'default', message: 'must be a boolean' }],\n },\n };\n }\n cleaned.default = entry.default;\n }\n\n return { ok: true, value: cleaned };\n}\n\nexport function createAgentsRouter(): Router {\n const router = Router();\n\n router.get('/', async (_req, res) => {\n try {\n const config = await readConfig();\n const agents = config.agents ?? BUILTIN_AGENTS;\n res.json({ agents, custom: config.agents !== null });\n } catch (err) {\n console.error('Error getting agents config:', err);\n res.status(500).json({ error: 'Failed to get agents config' });\n }\n });\n\n router.put('/', async (req, res) => {\n try {\n const raw = (req.body && typeof req.body === 'object' ? req.body : {}) as {\n agents?: unknown;\n };\n if (!Array.isArray(raw.agents)) {\n res.status(400).json({ error: 'agents must be an array' });\n return;\n }\n\n const cleaned: AgentConfig[] = [];\n for (let i = 0; i < raw.agents.length; i++) {\n const result = coerceAgentRow(raw.agents[i], i);\n if (!result.ok) {\n res.status(result.status).json(result.body);\n return;\n }\n cleaned.push(result.value);\n }\n\n try {\n await writeAgentsConfig(cleaned);\n } catch (err) {\n if (err instanceof AgentConfigError) {\n res.status(400).json(mapAgentErrorToFieldErrors(err));\n return;\n }\n console.error('Error saving agents config:', err);\n res.status(500).json({ error: 'Failed to save agents config' });\n return;\n }\n\n res.json({ agents: cleaned, custom: true });\n } catch (err) {\n console.error('Error saving agents config:', err);\n res.status(500).json({ error: 'Failed to save agents config' });\n }\n });\n\n router.delete('/', async (_req, res) => {\n try {\n await deleteAgentsConfig();\n res.json({ agents: BUILTIN_AGENTS, custom: false });\n } catch (err) {\n console.error('Error resetting agents config:', err);\n res.status(500).json({ error: 'Failed to reset agents config' });\n }\n });\n\n return router;\n}\n","import { Router } from 'express';\nimport {\n readConfig,\n getTerminal,\n TERMINAL_CHOICES,\n type TerminalChoice,\n} from '../utils/config.js';\nimport { probeTerminalInstalled } from '../utils/terminal-probe.js';\n\nexport interface PreflightResponse {\n ok: boolean;\n terminal: TerminalChoice;\n reason?: 'not-installed';\n /** OS-aware default the dashboard can offer as a confirm-to-fallback. */\n suggestedFallback?: TerminalChoice;\n}\n\nexport function createLaunchPreflightRouter(): Router {\n const router = Router();\n\n router.post('/preflight', async (req, res) => {\n try {\n const body = (req.body ?? {}) as { terminal?: unknown };\n if (\n body.terminal !== undefined &&\n (typeof body.terminal !== 'string' ||\n !(TERMINAL_CHOICES as readonly string[]).includes(body.terminal))\n ) {\n res.status(400).json({\n error: `terminal must be one of: ${TERMINAL_CHOICES.join(', ')}`,\n });\n return;\n }\n\n const config = await readConfig();\n const terminal: TerminalChoice =\n (body.terminal as TerminalChoice | undefined) ?? getTerminal(config);\n\n const probe = probeTerminalInstalled(terminal);\n if (probe.ok) {\n const response: PreflightResponse = { ok: true, terminal };\n res.json(response);\n return;\n }\n\n const suggestedFallback = getTerminal({ ...config, terminal: null });\n const response: PreflightResponse = {\n ok: false,\n terminal,\n reason: 'not-installed',\n suggestedFallback,\n };\n res.json(response);\n } catch (error) {\n console.error('Error in launch preflight:', error);\n res.status(500).json({ error: 'preflight failed' });\n }\n });\n\n return router;\n}\n","import { spawnSync } from 'node:child_process';\nimport type { TerminalChoice } from './terminal-schema.js';\n\n/**\n * macOS bundle identifiers for Apple-Event-driven terminals. Used with\n * `mdfind kMDItemCFBundleIdentifier == '<id>'` to confirm install.\n */\nexport const APP_BUNDLE_IDS: Partial<Record<TerminalChoice, string>> = {\n 'terminal-app': 'com.apple.Terminal',\n iterm: 'com.googlecode.iterm2',\n ghostty: 'com.mitchellh.ghostty',\n warp: 'dev.warp.Warp-Stable',\n};\n\n/**\n * CLI names for shell-out-driven terminals. Used with `which <name>` to\n * confirm install on PATH.\n */\nexport const CLI_NAMES: Partial<Record<TerminalChoice, string>> = {\n alacritty: 'alacritty',\n kitty: 'kitty',\n};\n\nexport interface ProbeResult {\n ok: boolean;\n /** Absolute path to the .app bundle or CLI binary, when found. */\n foundPath?: string;\n /** Why the probe returned ok:false. */\n reason?: 'not-installed' | 'no-probe-available';\n}\n\n/**\n * Probe whether a terminal is installed on this machine, using the same\n * primitives as the doctor `terminal.installed` check:\n * - `mdfind` for Apple-Event terminals registered with LaunchServices\n * - `which` for CLI terminals on PATH\n *\n * Returns `{ ok: false, reason: 'no-probe-available' }` when the terminal id\n * has no entry in either map — this should be impossible for known\n * `TerminalChoice` values but lets callers handle a future terminal addition\n * gracefully.\n */\nexport function probeTerminalInstalled(terminal: TerminalChoice): ProbeResult {\n const bundleId = APP_BUNDLE_IDS[terminal];\n if (bundleId) {\n const result = spawnSync(\n 'mdfind',\n [`kMDItemCFBundleIdentifier == '${bundleId}'`],\n { encoding: 'utf-8' },\n );\n if (result.status === 0 && result.stdout.trim().length > 0) {\n return { ok: true, foundPath: result.stdout.trim().split('\\n')[0] };\n }\n return { ok: false, reason: 'not-installed' };\n }\n\n const cliName = CLI_NAMES[terminal];\n if (cliName) {\n const result = spawnSync('which', [cliName], { encoding: 'utf-8' });\n if (result.status === 0 && result.stdout.trim().length > 0) {\n return { ok: true, foundPath: result.stdout.trim() };\n }\n return { ok: false, reason: 'not-installed' };\n }\n\n return { ok: false, reason: 'no-probe-available' };\n}\n","import { Router } from 'express';\nimport {\n readConfig,\n writeTerminalConfig,\n deleteTerminalConfig,\n getTerminal,\n TERMINAL_CHOICES,\n type TerminalChoice,\n} from '../utils/config.js';\n\nexport function createTerminalConfigRouter(): Router {\n const router = Router();\n\n router.get('/', async (_req, res) => {\n try {\n const config = await readConfig();\n res.json({\n terminal: getTerminal(config),\n custom: config.terminal !== null,\n });\n } catch (error) {\n console.error('Error getting terminal config:', error);\n res.status(500).json({ error: 'Failed to get terminal config' });\n }\n });\n\n router.post('/', async (req, res) => {\n try {\n const { terminal } = req.body ?? {};\n if (\n typeof terminal !== 'string' ||\n !(TERMINAL_CHOICES as readonly string[]).includes(terminal)\n ) {\n res.status(400).json({\n error: `terminal must be one of: ${TERMINAL_CHOICES.join(', ')}`,\n });\n return;\n }\n await writeTerminalConfig(terminal as TerminalChoice);\n res.json({ terminal, custom: true });\n } catch (error) {\n console.error('Error saving terminal config:', error);\n res.status(500).json({ error: 'Failed to save terminal config' });\n }\n });\n\n router.delete('/', async (_req, res) => {\n try {\n await deleteTerminalConfig();\n const config = await readConfig();\n res.json({ terminal: getTerminal(config), custom: false });\n } catch (error) {\n console.error('Error resetting terminal config:', error);\n res.status(500).json({ error: 'Failed to reset terminal config' });\n }\n });\n\n return router;\n}\n","import { Router } from 'express';\nimport {\n initLeasesDb,\n listInventories,\n getInventoryDetail,\n forceReleaseLease,\n NotFoundError,\n LeaseContentionError,\n} from '../db/leases-db.js';\nimport type { WsMessage } from './types.js';\n\nexport function createLeasesRouter(\n broadcast?: (message: WsMessage) => void,\n): Router {\n const router = Router();\n\n // GET /api/leases — all inventories with members + active leases\n router.get('/', (_req, res) => {\n try {\n initLeasesDb();\n const inventories = listInventories();\n const details = inventories\n .map((inv) => getInventoryDetail(inv.slug))\n .filter((d): d is NonNullable<typeof d> => d !== null);\n res.json({ inventories: details });\n } catch (error) {\n res.status(500).json({\n error: error instanceof Error ? error.message : 'List failed',\n });\n }\n });\n\n // GET /api/leases/:slug — single inventory detail\n router.get('/:slug', (req, res) => {\n try {\n initLeasesDb();\n const detail = getInventoryDetail(req.params.slug);\n if (!detail) {\n res.status(404).json({ error: 'Inventory not found' });\n return;\n }\n res.json(detail);\n } catch (error) {\n res.status(500).json({\n error: error instanceof Error ? error.message : 'Read failed',\n });\n }\n });\n\n // POST /api/leases/:slug/force-release/:lease_id — admin force-release\n router.post('/:slug/force-release/:lease_id', (req, res) => {\n try {\n initLeasesDb();\n const result = forceReleaseLease(req.params.lease_id);\n broadcast?.({\n type: 'leases-updated',\n timestamp: new Date().toISOString(),\n });\n res.json({ ...result, lease_id: req.params.lease_id });\n } catch (error) {\n if (error instanceof NotFoundError) {\n res.status(404).json({ error: 'Lease not found' });\n return;\n }\n if (error instanceof LeaseContentionError) {\n res.status(503).json({ error: 'Contention timeout; retry' });\n return;\n }\n res.status(500).json({\n error: error instanceof Error ? error.message : 'Force release failed',\n });\n }\n });\n\n return router;\n}\n","/**\n * Resource leases database module.\n *\n * Shares `~/.syntaur/syntaur.db` with `session-db.ts` and `proof-db.ts`. Each\n * module owns its own schema-version row in the shared `meta` table and creates\n * `meta` with `IF NOT EXISTS` so init order is irrelevant and standalone init\n * (e.g. in a leases-only test DB) is safe.\n *\n * Concurrency model:\n * - `journal_mode = WAL` allows concurrent readers and one writer.\n * - `busy_timeout = 5000` lets SQLite absorb short lock contention internally.\n * - All mutating ops run inside `db.transaction(fn).immediate()` which issues\n * `BEGIN IMMEDIATE` — acquires the reserved lock up-front so two concurrent\n * writers serialize cleanly.\n *\n * Atomic claim uses the tuple-subquery form (the bundled SQLite is built\n * without `SQLITE_ENABLE_UPDATE_DELETE_LIMIT`, so `UPDATE...ORDER BY...LIMIT...\n * RETURNING` is a syntax error — verified empirically).\n *\n * Timestamp invariant: every timestamp written from this module is produced by\n * `nowIso()` which calls `new Date().toISOString()` (canonical UTC, lexicographic-\n * safe). Lexicographic `<=` comparisons in SQL rely on this. The CLI never\n * accepts user-supplied timestamps. A future caller writing a non-canonical\n * timestamp would silently misorder `<=` checks.\n */\n\nimport Database from 'better-sqlite3';\nimport { randomUUID } from 'node:crypto';\nimport { resolve } from 'node:path';\nimport { syntaurRoot } from '../utils/paths.js';\n\nlet db: Database.Database | null = null;\n\nconst LEASE_SCHEMA_VERSION = '1';\n\nconst SCHEMA_SQL = `\nCREATE TABLE IF NOT EXISTS meta (\n key TEXT PRIMARY KEY,\n value TEXT\n);\n\nCREATE TABLE IF NOT EXISTS inventories (\n slug TEXT PRIMARY KEY,\n kind TEXT NOT NULL,\n display_name TEXT,\n default_ttl_s INTEGER NOT NULL CHECK (default_ttl_s > 0),\n created_at TEXT NOT NULL\n);\n\nCREATE TABLE IF NOT EXISTS inventory_members (\n inventory_slug TEXT NOT NULL,\n member_id TEXT NOT NULL,\n status TEXT NOT NULL DEFAULT 'idle'\n CHECK (status IN ('idle','leased','retired')),\n generation INTEGER NOT NULL DEFAULT 0,\n metadata_json TEXT,\n last_used_at TEXT,\n retired_at TEXT,\n PRIMARY KEY (inventory_slug, member_id),\n FOREIGN KEY (inventory_slug) REFERENCES inventories(slug)\n);\n\nCREATE INDEX IF NOT EXISTS idx_members_idle\n ON inventory_members (inventory_slug, status, last_used_at);\n\nCREATE TABLE IF NOT EXISTS leases (\n lease_id TEXT PRIMARY KEY,\n inventory_slug TEXT NOT NULL,\n member_id TEXT NOT NULL,\n member_gen INTEGER NOT NULL,\n state TEXT NOT NULL\n CHECK (state IN ('active','released','expired','revoked')),\n granted_at TEXT NOT NULL,\n expires_at TEXT NOT NULL,\n released_at TEXT,\n requested_for TEXT,\n FOREIGN KEY (inventory_slug, member_id)\n REFERENCES inventory_members(inventory_slug, member_id)\n);\n\nCREATE INDEX IF NOT EXISTS idx_leases_gc\n ON leases (state, expires_at);\n\nCREATE TABLE IF NOT EXISTS lease_events (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n lease_id TEXT NOT NULL,\n event TEXT NOT NULL,\n at TEXT NOT NULL,\n detail_json TEXT,\n FOREIGN KEY (lease_id) REFERENCES leases(lease_id)\n);\n\nCREATE INDEX IF NOT EXISTS idx_events_lease\n ON lease_events (lease_id, at);\n`;\n\n// --- Types -----------------------------------------------------------------\n\nexport type MemberStatus = 'idle' | 'leased' | 'retired';\nexport type LeaseState = 'active' | 'released' | 'expired' | 'revoked';\n\nexport interface InventoryRow {\n slug: string;\n kind: string;\n display_name: string | null;\n default_ttl_s: number;\n created_at: string;\n}\n\nexport interface InventoryMemberRow {\n inventory_slug: string;\n member_id: string;\n status: MemberStatus;\n generation: number;\n metadata_json: string | null;\n last_used_at: string | null;\n retired_at: string | null;\n}\n\nexport interface LeaseRow {\n lease_id: string;\n inventory_slug: string;\n member_id: string;\n member_gen: number;\n state: LeaseState;\n granted_at: string;\n expires_at: string;\n released_at: string | null;\n requested_for: string | null;\n}\n\nexport interface LeaseEventRow {\n id: number;\n lease_id: string;\n event: string;\n at: string;\n detail_json: string | null;\n}\n\nexport interface InventoryDetail {\n inventory: InventoryRow;\n members: InventoryMemberRow[];\n active_leases: LeaseRow[];\n}\n\nexport interface CreateInventoryInput {\n slug: string;\n kind: string;\n display_name?: string;\n default_ttl_s: number;\n}\n\nexport interface AddMemberInput {\n inventory_slug: string;\n member_id: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface ClaimResult {\n lease_id: string;\n inventory_slug: string;\n member_id: string;\n member_gen: number;\n granted_at: string;\n expires_at: string;\n metadata: Record<string, unknown> | null;\n}\n\nexport interface ListLeasesFilter {\n inventory?: string;\n state?: LeaseState;\n}\n\n// --- Errors ----------------------------------------------------------------\n\nexport class NoIdleMemberError extends Error {\n constructor(public readonly inventorySlug: string) {\n super(`no idle members in '${inventorySlug}'`);\n this.name = 'NoIdleMemberError';\n }\n}\n\nexport class StaleLeaseError extends Error {\n constructor(public readonly leaseId: string) {\n super(`lease ${leaseId} is no longer active (expired or revoked)`);\n this.name = 'StaleLeaseError';\n }\n}\n\nexport class NotFoundError extends Error {\n constructor(public readonly id: string) {\n super(`lease ${id} not found`);\n this.name = 'NotFoundError';\n }\n}\n\nexport class LeaseContentionError extends Error {\n constructor(public readonly inventorySlug: string) {\n super(`contention timeout on '${inventorySlug}'; retry`);\n this.name = 'LeaseContentionError';\n }\n}\n\nexport class MemberInUseError extends Error {\n constructor(public readonly inventorySlug: string, public readonly memberId: string) {\n super(`member ${inventorySlug}/${memberId} is currently leased; release before retiring`);\n this.name = 'MemberInUseError';\n }\n}\n\nexport class DuplicateInventoryError extends Error {\n constructor(public readonly slug: string) {\n super(`inventory '${slug}' already exists`);\n this.name = 'DuplicateInventoryError';\n }\n}\n\nexport class DuplicateMemberError extends Error {\n constructor(public readonly inventorySlug: string, public readonly memberId: string) {\n super(`member ${inventorySlug}/${memberId} already exists`);\n this.name = 'DuplicateMemberError';\n }\n}\n\n// --- Helpers ---------------------------------------------------------------\n\n/** Canonical UTC ISO 8601 timestamp. Lexicographic-safe for SQL `<=` checks. */\nexport function nowIso(): string {\n return new Date().toISOString();\n}\n\nfunction isBusyError(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n const e = err as { code?: string };\n return e.code === 'SQLITE_BUSY' || e.code === 'SQLITE_BUSY_SNAPSHOT';\n}\n\n// --- Lifecycle -------------------------------------------------------------\n\n/**\n * Initialize the leases database. Idempotent — repeated calls return the same\n * singleton handle. Pass an explicit `dbPath` for tests; defaults to\n * `~/.syntaur/syntaur.db`. Safe to run standalone (creates its own `meta` table).\n */\nexport function initLeasesDb(dbPath?: string): Database.Database {\n if (db) return db;\n\n const finalPath = dbPath ?? resolve(syntaurRoot(), 'syntaur.db');\n db = new Database(finalPath);\n db.pragma('journal_mode = WAL');\n db.pragma('busy_timeout = 5000');\n db.pragma('foreign_keys = ON');\n\n const database = db;\n const runMigrations = database.transaction(() => {\n database.exec(SCHEMA_SQL);\n database\n .prepare('INSERT OR IGNORE INTO meta (key, value) VALUES (?, ?)')\n .run('lease_schema_version', LEASE_SCHEMA_VERSION);\n });\n runMigrations.exclusive();\n\n return db;\n}\n\nexport function getLeasesDb(): Database.Database {\n if (!db) {\n throw new Error('Leases database not initialized. Call initLeasesDb() first.');\n }\n return db;\n}\n\nexport function closeLeasesDb(): void {\n if (db) {\n db.close();\n db = null;\n }\n}\n\nexport function resetLeasesDb(): void {\n db = null;\n}\n\n// --- Inventories -----------------------------------------------------------\n\nexport function createInventory(input: CreateInventoryInput): InventoryRow {\n const database = getLeasesDb();\n const row: InventoryRow = {\n slug: input.slug,\n kind: input.kind,\n display_name: input.display_name ?? null,\n default_ttl_s: input.default_ttl_s,\n created_at: nowIso(),\n };\n try {\n database\n .prepare(\n `INSERT INTO inventories (slug, kind, display_name, default_ttl_s, created_at)\n VALUES (?, ?, ?, ?, ?)`,\n )\n .run(row.slug, row.kind, row.display_name, row.default_ttl_s, row.created_at);\n } catch (err) {\n if (err instanceof Error && err.message.includes('UNIQUE')) {\n throw new DuplicateInventoryError(input.slug);\n }\n throw err;\n }\n return row;\n}\n\nexport function listInventories(): InventoryRow[] {\n const database = getLeasesDb();\n return database\n .prepare(\n `SELECT slug, kind, display_name, default_ttl_s, created_at\n FROM inventories ORDER BY slug`,\n )\n .all() as InventoryRow[];\n}\n\nexport function getInventoryDetail(slug: string): InventoryDetail | null {\n const database = getLeasesDb();\n const inv = database\n .prepare(\n `SELECT slug, kind, display_name, default_ttl_s, created_at\n FROM inventories WHERE slug = ?`,\n )\n .get(slug) as InventoryRow | undefined;\n if (!inv) return null;\n const members = database\n .prepare(\n `SELECT inventory_slug, member_id, status, generation, metadata_json, last_used_at, retired_at\n FROM inventory_members WHERE inventory_slug = ?\n ORDER BY member_id`,\n )\n .all(slug) as InventoryMemberRow[];\n const active_leases = database\n .prepare(\n `SELECT lease_id, inventory_slug, member_id, member_gen, state, granted_at, expires_at, released_at, requested_for\n FROM leases WHERE inventory_slug = ? AND state = 'active'\n ORDER BY granted_at`,\n )\n .all(slug) as LeaseRow[];\n return { inventory: inv, members, active_leases };\n}\n\n// --- Members ---------------------------------------------------------------\n\nexport function addMember(input: AddMemberInput): InventoryMemberRow {\n const database = getLeasesDb();\n const row: InventoryMemberRow = {\n inventory_slug: input.inventory_slug,\n member_id: input.member_id,\n status: 'idle',\n generation: 0,\n metadata_json: input.metadata ? JSON.stringify(input.metadata) : null,\n last_used_at: null,\n retired_at: null,\n };\n try {\n database\n .prepare(\n `INSERT INTO inventory_members\n (inventory_slug, member_id, status, generation, metadata_json)\n VALUES (?, ?, 'idle', 0, ?)`,\n )\n .run(row.inventory_slug, row.member_id, row.metadata_json);\n } catch (err) {\n if (err instanceof Error && err.message.includes('UNIQUE')) {\n throw new DuplicateMemberError(input.inventory_slug, input.member_id);\n }\n throw err;\n }\n return row;\n}\n\nexport function retireMember(inventorySlug: string, memberId: string): void {\n const database = getLeasesDb();\n const retire = database.transaction(() => {\n const row = database\n .prepare(\n `SELECT status FROM inventory_members\n WHERE inventory_slug = ? AND member_id = ?`,\n )\n .get(inventorySlug, memberId) as { status: MemberStatus } | undefined;\n if (!row) throw new NotFoundError(`${inventorySlug}/${memberId}`);\n if (row.status === 'leased') {\n throw new MemberInUseError(inventorySlug, memberId);\n }\n database\n .prepare(\n `UPDATE inventory_members\n SET status = 'retired', generation = generation + 1, retired_at = ?\n WHERE inventory_slug = ? AND member_id = ?`,\n )\n .run(nowIso(), inventorySlug, memberId);\n });\n retire.immediate();\n}\n\n// --- Claim -----------------------------------------------------------------\n\n/**\n * Claim an idle member of `slug`. Atomic — uses `BEGIN IMMEDIATE` so two\n * concurrent claimants serialize. Returns lease metadata or throws\n * `NoIdleMemberError` if the inventory has nothing claimable after sweeping.\n */\nexport function claimLease(\n slug: string,\n ttl_s: number,\n requested_for?: string,\n): ClaimResult {\n const database = getLeasesDb();\n\n try {\n const fn = database.transaction(() => {\n const now = nowIso();\n\n // (1) Opportunistic sweep — expire active leases on this inventory whose TTL is up.\n database\n .prepare(\n `UPDATE leases\n SET state = 'expired'\n WHERE state = 'active'\n AND expires_at <= ?\n AND inventory_slug = ?`,\n )\n .run(now, slug);\n\n // (2) Free their members (CAS on generation match).\n database\n .prepare(\n `UPDATE inventory_members\n SET status = 'idle', generation = generation + 1\n WHERE inventory_slug = ?\n AND status = 'leased'\n AND (inventory_slug, member_id) IN (\n SELECT inventory_slug, member_id\n FROM leases\n WHERE inventory_slug = ?\n AND state = 'expired'\n AND released_at IS NULL\n )\n AND generation = (\n SELECT member_gen FROM leases l\n WHERE l.inventory_slug = inventory_members.inventory_slug\n AND l.member_id = inventory_members.member_id\n AND l.state = 'expired'\n AND l.released_at IS NULL\n ORDER BY l.granted_at DESC LIMIT 1\n )`,\n )\n .run(slug, slug);\n\n // (3) Mark those freshly-expired leases as fully released (idempotent sentinel).\n database\n .prepare(\n `UPDATE leases\n SET released_at = ?\n WHERE state = 'expired'\n AND released_at IS NULL\n AND inventory_slug = ?`,\n )\n .run(now, slug);\n\n // (4) Pick an idle member via tuple-subquery (verified portable form).\n const picked = database\n .prepare(\n `UPDATE inventory_members\n SET status = 'leased',\n generation = generation + 1,\n last_used_at = ?\n WHERE (inventory_slug, member_id) = (\n SELECT inventory_slug, member_id\n FROM inventory_members\n WHERE inventory_slug = ? AND status = 'idle'\n ORDER BY last_used_at ASC NULLS FIRST\n LIMIT 1\n )\n RETURNING member_id, generation, metadata_json`,\n )\n .get(now, slug) as\n | { member_id: string; generation: number; metadata_json: string | null }\n | undefined;\n\n if (!picked) {\n throw new NoIdleMemberError(slug);\n }\n\n // (5) Insert the lease tied to the new member_gen.\n const lease_id = randomUUID();\n const expires_at = new Date(Date.now() + ttl_s * 1000).toISOString();\n database\n .prepare(\n `INSERT INTO leases\n (lease_id, inventory_slug, member_id, member_gen,\n state, granted_at, expires_at, requested_for)\n VALUES (?, ?, ?, ?, 'active', ?, ?, ?)`,\n )\n .run(\n lease_id,\n slug,\n picked.member_id,\n picked.generation,\n now,\n expires_at,\n requested_for ?? null,\n );\n\n // (6) Event.\n database\n .prepare(\n `INSERT INTO lease_events (lease_id, event, at, detail_json)\n VALUES (?, 'claimed', ?, ?)`,\n )\n .run(lease_id, now, JSON.stringify({ member_id: picked.member_id }));\n\n return {\n lease_id,\n inventory_slug: slug,\n member_id: picked.member_id,\n member_gen: picked.generation,\n granted_at: now,\n expires_at,\n metadata: picked.metadata_json\n ? (JSON.parse(picked.metadata_json) as Record<string, unknown>)\n : null,\n } satisfies ClaimResult;\n });\n\n return fn.immediate();\n } catch (err) {\n if (isBusyError(err)) throw new LeaseContentionError(slug);\n throw err;\n }\n}\n\n// --- Release ---------------------------------------------------------------\n\nexport function releaseLease(lease_id: string): void {\n const database = getLeasesDb();\n\n try {\n const fn = database.transaction(() => {\n const now = nowIso();\n\n // (1) CAS-guarded member free.\n const memberRes = database\n .prepare(\n `UPDATE inventory_members\n SET status = 'idle', generation = generation + 1\n WHERE (inventory_slug, member_id) = (\n SELECT inventory_slug, member_id FROM leases\n WHERE lease_id = ? AND state = 'active'\n )\n AND generation = (\n SELECT member_gen FROM leases\n WHERE lease_id = ? AND state = 'active'\n )`,\n )\n .run(lease_id, lease_id);\n\n if (memberRes.changes === 0) {\n throw new StaleLeaseError(lease_id);\n }\n\n // (2) Mark lease released.\n database\n .prepare(\n `UPDATE leases\n SET state = 'released', released_at = ?\n WHERE lease_id = ? AND state = 'active'`,\n )\n .run(now, lease_id);\n\n // (3) Event.\n database\n .prepare(\n `INSERT INTO lease_events (lease_id, event, at)\n VALUES (?, 'released', ?)`,\n )\n .run(lease_id, now);\n });\n\n fn.immediate();\n } catch (err) {\n if (isBusyError(err)) throw new LeaseContentionError(lease_id);\n throw err;\n }\n}\n\n// --- Extend ----------------------------------------------------------------\n\n/**\n * Extend a lease's TTL from NOW. Refuses if the lease is no longer active,\n * already past its wall-clock expiry, or its bound member generation has\n * advanced.\n */\nexport function extendLease(lease_id: string, ttl_s: number): { new_expires_at: string } {\n const database = getLeasesDb();\n\n try {\n const fn = database.transaction(() => {\n const now = nowIso();\n const new_expires_at = new Date(Date.now() + ttl_s * 1000).toISOString();\n\n const res = database\n .prepare(\n `UPDATE leases\n SET expires_at = ?\n WHERE lease_id = ?\n AND state = 'active'\n AND expires_at > ?\n AND member_gen = (\n SELECT generation FROM inventory_members\n WHERE inventory_slug = leases.inventory_slug\n AND member_id = leases.member_id\n )`,\n )\n .run(new_expires_at, lease_id, now);\n\n if (res.changes === 0) {\n throw new StaleLeaseError(lease_id);\n }\n\n database\n .prepare(\n `INSERT INTO lease_events (lease_id, event, at, detail_json)\n VALUES (?, 'extended', ?, ?)`,\n )\n .run(lease_id, now, JSON.stringify({ new_expires_at }));\n\n return { new_expires_at };\n });\n\n return fn.immediate();\n } catch (err) {\n if (isBusyError(err)) throw new LeaseContentionError(lease_id);\n throw err;\n }\n}\n\n// --- Read ------------------------------------------------------------------\n\nexport function getLease(lease_id: string): LeaseRow | null {\n const database = getLeasesDb();\n const row = database\n .prepare(\n `SELECT lease_id, inventory_slug, member_id, member_gen, state,\n granted_at, expires_at, released_at, requested_for\n FROM leases WHERE lease_id = ?`,\n )\n .get(lease_id) as LeaseRow | undefined;\n return row ?? null;\n}\n\nexport function listLeases(filter?: ListLeasesFilter): LeaseRow[] {\n const database = getLeasesDb();\n const where: string[] = [];\n const params: unknown[] = [];\n if (filter?.inventory) {\n where.push('inventory_slug = ?');\n params.push(filter.inventory);\n }\n if (filter?.state) {\n where.push('state = ?');\n params.push(filter.state);\n }\n const whereSql = where.length > 0 ? `WHERE ${where.join(' AND ')}` : '';\n return database\n .prepare(\n `SELECT lease_id, inventory_slug, member_id, member_gen, state,\n granted_at, expires_at, released_at, requested_for\n FROM leases ${whereSql}\n ORDER BY granted_at DESC`,\n )\n .all(...params) as LeaseRow[];\n}\n\nexport function listMembers(inventory_slug: string): InventoryMemberRow[] {\n const database = getLeasesDb();\n const inv = database\n .prepare('SELECT slug FROM inventories WHERE slug = ?')\n .get(inventory_slug);\n if (!inv) throw new NotFoundError(inventory_slug);\n return database\n .prepare(\n `SELECT inventory_slug, member_id, status, generation, metadata_json, last_used_at, retired_at\n FROM inventory_members WHERE inventory_slug = ?\n ORDER BY member_id`,\n )\n .all(inventory_slug) as InventoryMemberRow[];\n}\n\n/**\n * Read lease_events. With a `lease_id`, returns that lease's event timeline in\n * chronological order (oldest first). Without, returns the most recent `limit`\n * events across all leases in reverse-chronological order (newest first).\n */\nexport function getLeaseEvents(lease_id?: string, limit = 50): LeaseEventRow[] {\n const database = getLeasesDb();\n if (lease_id) {\n return database\n .prepare(\n `SELECT id, lease_id, event, at, detail_json\n FROM lease_events WHERE lease_id = ?\n ORDER BY at ASC, id ASC\n LIMIT ?`,\n )\n .all(lease_id, limit) as LeaseEventRow[];\n }\n return database\n .prepare(\n `SELECT id, lease_id, event, at, detail_json\n FROM lease_events\n ORDER BY at DESC, id DESC\n LIMIT ?`,\n )\n .all(limit) as LeaseEventRow[];\n}\n\n// --- GC --------------------------------------------------------------------\n\n/**\n * Sweep expired leases across ALL inventories. Idempotent; safe to run\n * concurrently with claims (`BEGIN IMMEDIATE` serializes writers).\n * Returns the number of leases newly transitioned to `expired`.\n */\nexport function gcExpiredLeases(): number {\n const database = getLeasesDb();\n\n try {\n const fn = database.transaction(() => {\n const now = nowIso();\n\n const expRes = database\n .prepare(\n `UPDATE leases SET state = 'expired'\n WHERE state = 'active' AND expires_at <= ?`,\n )\n .run(now);\n\n database\n .prepare(\n `UPDATE inventory_members\n SET status = 'idle', generation = generation + 1\n WHERE status = 'leased'\n AND (inventory_slug, member_id) IN (\n SELECT inventory_slug, member_id FROM leases\n WHERE state = 'expired' AND released_at IS NULL\n )\n AND generation = (\n SELECT member_gen FROM leases l\n WHERE l.inventory_slug = inventory_members.inventory_slug\n AND l.member_id = inventory_members.member_id\n AND l.state = 'expired'\n AND l.released_at IS NULL\n ORDER BY l.granted_at DESC LIMIT 1\n )`,\n )\n .run();\n\n database\n .prepare(\n `UPDATE leases SET released_at = ?\n WHERE state = 'expired' AND released_at IS NULL AND expires_at <= ?`,\n )\n .run(now, now);\n\n return expRes.changes;\n });\n\n return fn.immediate();\n } catch (err) {\n if (isBusyError(err)) throw new LeaseContentionError('gc');\n throw err;\n }\n}\n\n// --- Force release ---------------------------------------------------------\n\n/**\n * Administrative force-release. Bypasses the lease's `state = 'active'` check\n * (humans force-releasing an already-expired-but-not-yet-released lease is\n * fine), but CAS-guards the member free on the lease's bound `member_gen`.\n * This prevents stomping a member that's currently held by a *different*\n * active lease (i.e. the targeted lease is already terminal and the slot has\n * been re-claimed).\n *\n * Returns `member_freed: true` if the member was actually idled by this call,\n * `false` if a newer claim has already taken the slot.\n */\nexport function forceReleaseLease(lease_id: string): { member_freed: boolean } {\n const database = getLeasesDb();\n\n try {\n const fn = database.transaction(() => {\n const now = nowIso();\n\n const lookup = database\n .prepare(\n `SELECT inventory_slug, member_id, member_gen, state\n FROM leases WHERE lease_id = ?`,\n )\n .get(lease_id) as\n | { inventory_slug: string; member_id: string; member_gen: number; state: LeaseState }\n | undefined;\n\n if (!lookup) throw new NotFoundError(lease_id);\n if (lookup.state === 'revoked') return { member_freed: false };\n\n // CAS: free the member only if the lease is still its current holder.\n const memberRes = database\n .prepare(\n `UPDATE inventory_members\n SET status = 'idle', generation = generation + 1\n WHERE inventory_slug = ? AND member_id = ?\n AND generation = ?`,\n )\n .run(lookup.inventory_slug, lookup.member_id, lookup.member_gen);\n\n database\n .prepare(\n `UPDATE leases\n SET state = 'revoked', released_at = ?\n WHERE lease_id = ? AND state != 'revoked'`,\n )\n .run(now, lease_id);\n\n const member_freed = memberRes.changes > 0;\n database\n .prepare(\n `INSERT INTO lease_events (lease_id, event, at, detail_json)\n VALUES (?, 'force_released', ?, ?)`,\n )\n .run(lease_id, now, JSON.stringify({ member_freed }));\n\n return { member_freed };\n });\n\n return fn.immediate();\n } catch (err) {\n if (isBusyError(err)) throw new LeaseContentionError(lease_id);\n throw err;\n }\n}\n\n// --- Inventory update / delete --------------------------------------------\n\nexport interface UpdateInventoryInput {\n default_ttl_s?: number;\n display_name?: string | null;\n}\n\n/**\n * Update mutable inventory fields. `kind` is immutable in v1 — the typed\n * signature excludes it, and a runtime guard rejects any caller that sneaks\n * a `kind` key through (defense in depth).\n */\nexport function updateInventory(\n slug: string,\n input: UpdateInventoryInput,\n): InventoryRow {\n if ('kind' in input) {\n throw new Error('inventory kind is immutable');\n }\n if (\n input.default_ttl_s === undefined &&\n input.display_name === undefined\n ) {\n throw new Error('nothing to update');\n }\n if (input.default_ttl_s !== undefined && input.default_ttl_s <= 0) {\n throw new Error('default_ttl_s must be positive');\n }\n const database = getLeasesDb();\n\n const fn = database.transaction(() => {\n const existing = database\n .prepare('SELECT slug FROM inventories WHERE slug = ?')\n .get(slug);\n if (!existing) throw new NotFoundError(slug);\n\n const sets: string[] = [];\n const params: unknown[] = [];\n if (input.default_ttl_s !== undefined) {\n sets.push('default_ttl_s = ?');\n params.push(input.default_ttl_s);\n }\n if (input.display_name !== undefined) {\n sets.push('display_name = ?');\n params.push(input.display_name);\n }\n params.push(slug);\n\n database\n .prepare(`UPDATE inventories SET ${sets.join(', ')} WHERE slug = ?`)\n .run(...params);\n\n return database\n .prepare(\n `SELECT slug, kind, display_name, default_ttl_s, created_at\n FROM inventories WHERE slug = ?`,\n )\n .get(slug) as InventoryRow;\n });\n\n try {\n return fn.immediate();\n } catch (err) {\n if (isBusyError(err)) throw new LeaseContentionError(slug);\n throw err;\n }\n}\n\n/**\n * Delete an inventory and all of its members, leases, and lease_events.\n *\n * Without `force`: refuses if any lease for the inventory is currently\n * `active` (throws `MemberInUseError`).\n *\n * With `force`: tallies active leases as `revoked` and cascades through\n * events → leases → members → inventory row, ALL inside one `BEGIN IMMEDIATE`\n * transaction. The acquire-up-front lock prevents a concurrent `claimLease`\n * from grabbing a freshly-idled member between the active-lease snapshot and\n * the cascade — what would otherwise be a use-after-free window. No explicit\n * `force_released` event is written because the entire event log for this\n * inventory is deleted in the same tx anyway.\n */\nexport function deleteInventory(\n slug: string,\n opts: { force?: boolean } = {},\n): { deleted: boolean; revoked: number } {\n const database = getLeasesDb();\n\n let revoked = 0;\n const fn = database.transaction(() => {\n const existing = database\n .prepare('SELECT slug FROM inventories WHERE slug = ?')\n .get(slug);\n if (!existing) throw new NotFoundError(slug);\n\n const activeLeases = database\n .prepare(\n `SELECT lease_id FROM leases\n WHERE inventory_slug = ? AND state = 'active'`,\n )\n .all(slug) as Array<{ lease_id: string }>;\n\n if (activeLeases.length > 0 && !opts.force) {\n throw new MemberInUseError(slug, '*');\n }\n revoked = activeLeases.length;\n\n database\n .prepare(\n `DELETE FROM lease_events\n WHERE lease_id IN (SELECT lease_id FROM leases WHERE inventory_slug = ?)`,\n )\n .run(slug);\n database.prepare('DELETE FROM leases WHERE inventory_slug = ?').run(slug);\n database\n .prepare('DELETE FROM inventory_members WHERE inventory_slug = ?')\n .run(slug);\n database.prepare('DELETE FROM inventories WHERE slug = ?').run(slug);\n });\n\n try {\n fn.immediate();\n } catch (err) {\n if (isBusyError(err)) throw new LeaseContentionError(slug);\n throw err;\n }\n return { deleted: true, revoked };\n}\n\n// --- Bulk release by tag --------------------------------------------------\n\n/**\n * Release every `active` lease whose `requested_for` matches `tag`. Per-row\n * `releaseLease` calls keep each release in its own transaction; a\n * `StaleLeaseError` from any individual release is tallied as `stale` and\n * swallowed (the caller asked for a best-effort sweep). Returns the\n * per-lease ids in two arrays so callers can render one-line-per-lease\n * summaries without re-querying.\n */\nexport function releaseLeasesByRequestedFor(\n tag: string,\n): { released: string[]; stale: string[] } {\n const database = getLeasesDb();\n const rows = database\n .prepare(\n `SELECT lease_id FROM leases\n WHERE state = 'active' AND requested_for = ?`,\n )\n .all(tag) as Array<{ lease_id: string }>;\n\n const released: string[] = [];\n const stale: string[] = [];\n for (const { lease_id } of rows) {\n try {\n releaseLease(lease_id);\n released.push(lease_id);\n } catch (err) {\n if (err instanceof StaleLeaseError) {\n stale.push(lease_id);\n continue;\n }\n throw err;\n }\n }\n return { released, stale };\n}\n","import { Router } from 'express';\nimport { resolve } from 'node:path';\nimport { readFile } from 'node:fs/promises';\nimport { listPlaybooks, getPlaybookDetail } from './api.js';\nimport { parsePlaybook } from './parser.js';\nimport { isValidSlug } from '../utils/slug.js';\nimport { nowTimestamp } from '../utils/timestamp.js';\nimport { ensureDir, fileExists, writeFileForce } from '../utils/fs.js';\nimport { renderPlaybook } from '../templates/playbook.js';\nimport {\n deletePlaybook,\n rebuildPlaybookManifest,\n renamePlaybook,\n resolvePlaybookSlug,\n setPlaybookEnabled,\n PlaybookError,\n} from '../utils/playbooks.js';\n\nfunction statusForPlaybookError(code: PlaybookError['code']): number {\n switch (code) {\n case 'manifest':\n return 403;\n case 'not-found':\n return 404;\n case 'invalid-slug':\n return 400;\n case 'collision':\n return 409;\n }\n}\n\nexport function createPlaybooksRouter(playbooksDir: string): Router {\n const router = Router();\n\n // GET / — list all playbooks\n router.get('/', async (_req, res) => {\n try {\n const playbooks = await listPlaybooks(playbooksDir);\n res.json({ playbooks, generatedAt: new Date().toISOString() });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to list playbooks' });\n }\n });\n\n // GET /template/new — scaffold template (must be before /:slug to avoid param capture)\n router.get('/template/new', async (_req, res) => {\n try {\n const content = renderPlaybook({\n slug: 'my-playbook',\n name: 'My Playbook',\n description: 'A new playbook',\n timestamp: nowTimestamp(),\n });\n res.json({ content });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to get template' });\n }\n });\n\n // POST /:slug/enable — re-enable a disabled playbook\n router.post('/:slug/enable', async (req, res) => {\n try {\n const result = await setPlaybookEnabled(playbooksDir, req.params.slug, true);\n res.json({ slug: result.slug, enabled: result.enabled, changed: result.changed });\n } catch (error) {\n const msg = error instanceof Error ? error.message : 'Failed to enable playbook';\n if (msg.startsWith('Playbook ')) {\n res.status(404).json({ error: msg });\n return;\n }\n res.status(500).json({ error: msg });\n }\n });\n\n // POST /:slug/disable — disable a playbook so agents no longer load it\n router.post('/:slug/disable', async (req, res) => {\n try {\n const result = await setPlaybookEnabled(playbooksDir, req.params.slug, false);\n res.json({ slug: result.slug, enabled: result.enabled, changed: result.changed });\n } catch (error) {\n const msg = error instanceof Error ? error.message : 'Failed to disable playbook';\n if (msg.startsWith('Playbook ')) {\n res.status(404).json({ error: msg });\n return;\n }\n res.status(500).json({ error: msg });\n }\n });\n\n // GET /:slug — get playbook detail\n router.get('/:slug', async (req, res) => {\n try {\n const detail = await getPlaybookDetail(playbooksDir, req.params.slug);\n if (!detail) {\n res.status(404).json({ error: `Playbook \"${req.params.slug}\" not found` });\n return;\n }\n res.json(detail);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to get playbook' });\n }\n });\n\n // GET /:slug/edit — raw file content for editor\n router.get('/:slug/edit', async (req, res) => {\n try {\n const resolved = await resolvePlaybookSlug(playbooksDir, req.params.slug);\n if (!resolved) {\n res.status(404).json({ error: `Playbook \"${req.params.slug}\" not found` });\n return;\n }\n const filePath = resolve(playbooksDir, resolved.filename);\n const content = await readFile(filePath, 'utf-8');\n res.json({\n documentType: 'playbook',\n title: `Edit Playbook: ${resolved.slug}`,\n content,\n slug: resolved.slug,\n });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to get playbook for editing' });\n }\n });\n\n // POST / — create new playbook\n router.post('/', async (req, res) => {\n try {\n const { content } = req.body;\n if (!content || typeof content !== 'string') {\n res.status(400).json({ error: 'content is required' });\n return;\n }\n\n const parsed = parsePlaybook(content);\n const slug = parsed.slug;\n if (!slug || !isValidSlug(slug)) {\n res.status(400).json({ error: `Invalid or missing slug: \"${slug}\"` });\n return;\n }\n\n await ensureDir(playbooksDir);\n const filePath = resolve(playbooksDir, `${slug}.md`);\n if (await fileExists(filePath)) {\n res.status(409).json({ error: `Playbook \"${slug}\" already exists` });\n return;\n }\n\n await writeFileForce(filePath, content);\n await rebuildPlaybookManifest(playbooksDir);\n res.status(201).json({ slug, path: filePath });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to create playbook' });\n }\n });\n\n // PUT /:slug — update playbook content\n router.put('/:slug', async (req, res) => {\n try {\n const { content } = req.body;\n if (!content || typeof content !== 'string') {\n res.status(400).json({ error: 'content is required' });\n return;\n }\n\n const resolved = await resolvePlaybookSlug(playbooksDir, req.params.slug);\n if (!resolved) {\n res.status(404).json({ error: `Playbook \"${req.params.slug}\" not found` });\n return;\n }\n\n const filePath = resolve(playbooksDir, resolved.filename);\n await writeFileForce(filePath, content);\n await rebuildPlaybookManifest(playbooksDir);\n res.json({ slug: resolved.slug, path: filePath });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to update playbook' });\n }\n });\n\n // DELETE /:slug — delete a playbook\n router.delete('/:slug', async (req, res) => {\n try {\n const { slug } = await deletePlaybook(playbooksDir, req.params.slug);\n res.json({ deleted: slug });\n } catch (error) {\n if (error instanceof PlaybookError) {\n res.status(statusForPlaybookError(error.code)).json({ error: error.message });\n return;\n }\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to delete playbook' });\n }\n });\n\n // PATCH /:slug — rename a playbook (slug change)\n router.patch('/:slug', async (req, res) => {\n try {\n const { newSlug } = req.body || {};\n if (typeof newSlug !== 'string' || !newSlug.trim()) {\n res.status(400).json({ error: 'newSlug is required' });\n return;\n }\n const result = await renamePlaybook(playbooksDir, req.params.slug, newSlug.trim());\n res.json(result);\n } catch (error) {\n if (error instanceof PlaybookError) {\n res.status(statusForPlaybookError(error.code)).json({ error: error.message });\n return;\n }\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to rename playbook' });\n }\n });\n\n return router;\n}\n","import { Router, type Request, type Response, type NextFunction } from 'express';\nimport { readdir } from 'node:fs/promises';\nimport {\n readChecklist,\n writeChecklist,\n readLog,\n appendLogEntry,\n generateUniqueId,\n computeCounts,\n} from '../todos/parser.js';\nimport { resolve as resolvePath, dirname } from 'node:path';\nimport { rename, mkdir } from 'node:fs/promises';\nimport { ensureDir, fileExists } from '../utils/fs.js';\nimport { projectTodosDir, todoPlanDir } from '../utils/paths.js';\nimport { wsLock, projLock, withTwoLocks, globalLockKey } from './todos-locks.js';\nimport { isValidSlug } from '../utils/slug.js';\nimport type { TodoItem, LogEntry } from '../todos/types.js';\nimport type { WsMessage } from './types.js';\nimport {\n promoteTodosToNewAssignment,\n parsePromoteTarget,\n} from '../utils/promote-todos.js';\n\nconst WORKSPACE_REGEX = /^[a-z0-9_][a-z0-9-]*$/;\n\nfunction getWorkspaceParam(value: string | string[] | undefined): string {\n if (Array.isArray(value)) {\n return value[0] ?? '';\n }\n return value ?? '';\n}\n\nfunction touchItem(item: TodoItem): void {\n const now = new Date().toISOString();\n if (item.createdAt === null) item.createdAt = now;\n item.updatedAt = now;\n}\n\nexport function createTodosRouter(\n todosDir: string,\n broadcast: (msg: WsMessage) => void,\n projectsDir?: string,\n): Router {\n const router = Router();\n\n function broadcastUpdate(): void {\n broadcast({ type: 'todos-updated', timestamp: new Date().toISOString() });\n }\n function broadcastProject(slug: string): void {\n broadcast({ type: 'todos-updated', projectSlug: slug, timestamp: new Date().toISOString() });\n }\n\n // Validate workspace name on all routes that use :workspace\n function validateWorkspace(req: Request, res: Response, next: NextFunction): void {\n const workspace = getWorkspaceParam(req.params.workspace);\n if (workspace && !WORKSPACE_REGEX.test(workspace)) {\n res.status(400).json({ error: `Invalid workspace name: \"${workspace}\". Use lowercase letters, numbers, hyphens, and underscores.` });\n return;\n }\n next();\n }\n\n // Apply workspace validation to all parameterized routes\n router.param('workspace', validateWorkspace as any);\n\n // POST /promote-bulk — aggregate promote across multiple workspaces into one\n // new assignment. Registered BEFORE any `/:workspace` route so the literal\n // `promote-bulk` segment is not mis-routed to the add-todo handler.\n // Only supports `mode: 'new-assignment'` in v1.\n router.post('/promote-bulk', async (req, res) => {\n try {\n const { groups, mode, target, title, type, priority, keepSource } = req.body ?? {};\n if (mode !== 'new-assignment') {\n res.status(400).json({ error: 'promote-bulk only supports mode \"new-assignment\" in v1' });\n return;\n }\n if (!Array.isArray(groups) || groups.length === 0) {\n res.status(400).json({ error: 'groups (non-empty array of { workspace, todoIds }) is required' });\n return;\n }\n // Preserve caller order — criteria order should follow request order.\n // Reject duplicate workspaces up front so we never nest wsLock on the\n // same key (a self-deadlock if the lock is non-reentrant).\n const callerOrder: Array<{ workspace: string; todoIds: string[] }> = [];\n const seen = new Set<string>();\n let total = 0;\n for (const g of groups) {\n if (!g || typeof g !== 'object') {\n res.status(400).json({ error: 'each group must be { workspace: string, todoIds: string[] }' });\n return;\n }\n const ws = typeof g.workspace === 'string' ? g.workspace : '';\n if (!ws || !WORKSPACE_REGEX.test(ws)) {\n res.status(400).json({ error: `Invalid workspace name in group: \"${ws}\"` });\n return;\n }\n if (seen.has(ws)) {\n res.status(400).json({ error: `Duplicate workspace \"${ws}\" in groups — merge ids client-side before posting` });\n return;\n }\n seen.add(ws);\n if (!Array.isArray(g.todoIds) || g.todoIds.length === 0) {\n res.status(400).json({ error: `group for workspace \"${ws}\" has no todoIds` });\n return;\n }\n callerOrder.push({ workspace: ws, todoIds: g.todoIds.map(String) });\n total += g.todoIds.length;\n }\n if (total > 1 && !title) {\n res.status(400).json({ error: 'title is required when promoting multiple todos' });\n return;\n }\n const parsed = parsePromoteTarget(target);\n if (!parsed.ok) { res.status(400).json({ error: parsed.error }); return; }\n\n // Lock in deterministic alpha order to avoid cross-request deadlock.\n const lockOrder = [...callerOrder].sort((a, b) =>\n a.workspace.localeCompare(b.workspace),\n );\n\n const runWithLocks = async (\n index: number,\n ): Promise<\n | { ok: true; result: { assignmentRef: string; assignmentDir: string; promoted: string[]; promotedByWorkspace: Array<{ workspace: string; ids: string[] }> } }\n | { ok: false; error: string }\n > => {\n if (index === lockOrder.length) {\n // All locks held. Build helper groups in CALLER order so criteria\n // come out in the order the user selected.\n const helperGroups: Array<{ todosDir: string; workspace: string; items: TodoItem[]; scopeLabel: string }> = [];\n for (const co of callerOrder) {\n const checklist = await readChecklist(todosDir, co.workspace);\n const items: TodoItem[] = [];\n for (const id of co.todoIds) {\n const item = checklist.items.find((i) => i.id === id);\n if (!item) return { ok: false, error: `Todo \"${id}\" not found in workspace \"${co.workspace}\"` };\n if (item.status === 'completed') return { ok: false, error: `Todo \"${id}\" is already completed` };\n items.push(item);\n }\n const scopeLabel = co.workspace === '_global' ? '_global' : `workspace:${co.workspace}`;\n helperGroups.push({ todosDir, workspace: co.workspace, items, scopeLabel });\n }\n if (helperGroups.every((g) => g.items.length === 0)) {\n return { ok: false, error: 'No selectable todos found in the requested groups' };\n }\n const firstItem = helperGroups.flatMap((g) => g.items)[0];\n const promoted = await promoteTodosToNewAssignment(helperGroups, {\n title: title || firstItem.description,\n target: parsed.target,\n type,\n priority,\n keepSource,\n });\n return {\n ok: true,\n result: {\n assignmentRef: promoted.assignmentRef,\n assignmentDir: promoted.assignmentDir,\n promoted: promoted.promoted.map((p) => p.id),\n promotedByWorkspace: promoted.promotedByWorkspace,\n },\n };\n }\n return wsLock(lockOrder[index].workspace, async () => runWithLocks(index + 1));\n };\n\n const out = await runWithLocks(0);\n if (!out.ok) { res.status(400).json({ error: out.error }); return; }\n broadcastUpdate();\n res.json(out.result);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to bulk-promote todos' });\n }\n });\n\n // GET / — aggregate all workspace checklists\n router.get('/', async (_req, res) => {\n try {\n await ensureDir(todosDir);\n const files = await readdir(todosDir).catch(() => []);\n const workspaces: Array<{\n workspace: string;\n archiveInterval: string;\n items: TodoItem[];\n counts: ReturnType<typeof computeCounts>;\n }> = [];\n\n for (const file of files) {\n if (typeof file !== 'string') continue;\n if (!file.endsWith('.md') || file.endsWith('-log.md')) continue;\n const workspace = file.replace('.md', '');\n const checklist = await readChecklist(todosDir, workspace);\n workspaces.push({\n workspace: checklist.workspace,\n archiveInterval: checklist.archiveInterval,\n items: checklist.items,\n counts: computeCounts(checklist.items),\n });\n }\n\n res.json({ workspaces });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to list todos' });\n }\n });\n\n // GET /:workspace — list items for one workspace\n router.get('/:workspace', async (req, res) => {\n try {\n const workspace = getWorkspaceParam(req.params.workspace);\n const checklist = await readChecklist(todosDir, workspace);\n res.json({\n workspace: checklist.workspace,\n archiveInterval: checklist.archiveInterval,\n items: checklist.items,\n counts: computeCounts(checklist.items),\n });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to get todos' });\n }\n });\n\n // POST /:workspace — add item\n router.post('/:workspace', async (req, res) => {\n try {\n const workspace = getWorkspaceParam(req.params.workspace);\n const { description, tags } = req.body;\n if (!description || typeof description !== 'string') {\n res.status(400).json({ error: 'description is required' });\n return;\n }\n\n const item = await wsLock(workspace, async () => {\n const checklist = await readChecklist(todosDir, workspace);\n const existingIds = new Set(checklist.items.map((i) => i.id));\n const id = generateUniqueId(existingIds);\n const now = new Date().toISOString();\n\n const newItem: TodoItem = {\n id,\n description,\n status: 'open',\n tags: Array.isArray(tags) ? tags : [],\n session: null,\n branch: null,\n worktreePath: null,\n createdAt: now,\n updatedAt: now,\n planDir: null,\n linkedAssignmentId: null,\n linkedAssignmentRef: null,\n };\n checklist.items.push(newItem);\n await writeChecklist(todosDir, checklist);\n return newItem;\n });\n broadcastUpdate();\n res.status(201).json(item);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to add todo' });\n }\n });\n\n // POST /:workspace/reorder — reorder items\n // Must be before /:workspace/:id to avoid param capture\n router.post('/:workspace/reorder', async (req, res) => {\n try {\n const workspace = getWorkspaceParam(req.params.workspace);\n const { ids } = req.body;\n if (!Array.isArray(ids) || !ids.every((id: unknown) => typeof id === 'string')) {\n res.status(400).json({ error: 'ids must be an array of strings' });\n return;\n }\n\n const items = await wsLock(workspace, async () => {\n const checklist = await readChecklist(todosDir, workspace);\n const itemMap = new Map(checklist.items.map((i) => [i.id, i]));\n\n // Build reordered list: requested order first, then any items not in the ids array\n const reordered: TodoItem[] = [];\n for (const id of ids) {\n const item = itemMap.get(id);\n if (item) {\n reordered.push(item);\n itemMap.delete(id);\n }\n }\n // Append any remaining items not mentioned in ids\n for (const item of itemMap.values()) {\n reordered.push(item);\n }\n\n checklist.items = reordered;\n await writeChecklist(todosDir, checklist);\n return reordered;\n });\n broadcastUpdate();\n res.json({ items });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to reorder todos' });\n }\n });\n\n // GET /:workspace/log — full log\n // Must be before /:workspace/:id to avoid param capture\n router.get('/:workspace/log', async (req, res) => {\n try {\n const log = await readLog(todosDir, getWorkspaceParam(req.params.workspace));\n res.json(log);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to get log' });\n }\n });\n\n // POST /:workspace/archive — trigger archive\n router.post('/:workspace/archive', async (req, res) => {\n try {\n // Import archive logic inline to avoid circular deps\n const { archivePath } = await import('../todos/parser.js');\n const { resolve } = await import('node:path');\n const { readFile } = await import('node:fs/promises');\n const { writeFileForce } = await import('../utils/fs.js');\n\n const workspace = getWorkspaceParam(req.params.workspace);\n const checklist = await readChecklist(todosDir, workspace);\n const log = await readLog(todosDir, workspace);\n\n const completedIds = new Set(\n checklist.items.filter((i) => i.status === 'completed').map((i) => i.id),\n );\n\n if (completedIds.size === 0) {\n res.json({ archived: 0, message: 'No completed items to archive' });\n return;\n }\n\n const toArchive = log.entries.filter((e) =>\n e.itemIds.every((id) => completedIds.has(id)),\n );\n\n const archFile = archivePath(todosDir, workspace, checklist.archiveInterval);\n await ensureDir(resolve(todosDir, 'archive'));\n let archContent = '';\n if (await fileExists(archFile)) {\n archContent = await readFile(archFile, 'utf-8');\n archContent = archContent.trimEnd() + '\\n\\n';\n } else {\n archContent = `---\\nworkspace: ${workspace}\\n---\\n\\n# Archive\\n\\n`;\n }\n\n const completedItems = checklist.items.filter((i) => completedIds.has(i.id));\n for (const item of completedItems) {\n archContent += `- [x] ${item.description} ${item.tags.map((t: string) => `#${t}`).join(' ')} [t:${item.id}]\\n`;\n }\n archContent += '\\n';\n for (const entry of toArchive) {\n archContent += `### ${entry.timestamp} — ${entry.itemIds.map((i: string) => `t:${i}`).join(', ')}\\n`;\n if (entry.items) archContent += `**Items:** ${entry.items}\\n`;\n if (entry.session) archContent += `**Session:** ${entry.session}\\n`;\n if (entry.branch) archContent += `**Branch:** ${entry.branch}\\n`;\n if (entry.summary) archContent += `**Summary:** ${entry.summary}\\n`;\n if (entry.blockers) archContent += `**Blockers:** ${entry.blockers}\\n`;\n archContent += '\\n';\n }\n await writeFileForce(archFile, archContent);\n\n checklist.items = checklist.items.filter((i) => !completedIds.has(i.id));\n await writeChecklist(todosDir, checklist);\n\n broadcastUpdate();\n res.json({ archived: completedIds.size, logEntries: toArchive.length });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to archive' });\n }\n });\n\n // GET /:workspace/log/:id — log for specific item\n router.get('/:workspace/log/:id', async (req, res) => {\n try {\n const log = await readLog(todosDir, getWorkspaceParam(req.params.workspace));\n const entries = log.entries.filter((e) => e.itemIds.includes(req.params.id));\n res.json({ workspace: log.workspace, entries });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to get log' });\n }\n });\n\n // GET /:workspace/:id — single item with log\n router.get('/:workspace/:id', async (req, res) => {\n try {\n const workspace = getWorkspaceParam(req.params.workspace);\n const checklist = await readChecklist(todosDir, workspace);\n const item = checklist.items.find((i) => i.id === req.params.id);\n if (!item) {\n res.status(404).json({ error: `Todo \"${req.params.id}\" not found` });\n return;\n }\n const log = await readLog(todosDir, workspace);\n const logEntries = log.entries.filter((e) => e.itemIds.includes(req.params.id));\n res.json({ ...item, log: logEntries });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to get todo' });\n }\n });\n\n // PATCH /:workspace/:id — update description or tags\n router.patch('/:workspace/:id', async (req, res) => {\n try {\n const workspace = getWorkspaceParam(req.params.workspace);\n const result = await wsLock(workspace, async () => {\n const checklist = await readChecklist(todosDir, workspace);\n const item = checklist.items.find((i) => i.id === req.params.id);\n if (!item) return null;\n if (req.body.description !== undefined) item.description = req.body.description;\n if (Array.isArray(req.body.tags)) item.tags = req.body.tags;\n touchItem(item);\n await writeChecklist(todosDir, checklist);\n return { ...item };\n });\n if (!result) { res.status(404).json({ error: `Todo \"${req.params.id}\" not found` }); return; }\n broadcastUpdate();\n res.json(result);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to update todo' });\n }\n });\n\n // DELETE /:workspace/:id\n router.delete('/:workspace/:id', async (req, res) => {\n try {\n const workspace = getWorkspaceParam(req.params.workspace);\n const deleted = await wsLock(workspace, async () => {\n const checklist = await readChecklist(todosDir, workspace);\n const idx = checklist.items.findIndex((i) => i.id === req.params.id);\n if (idx === -1) return false;\n checklist.items.splice(idx, 1);\n await writeChecklist(todosDir, checklist);\n return true;\n });\n if (!deleted) { res.status(404).json({ error: `Todo \"${req.params.id}\" not found` }); return; }\n broadcastUpdate();\n res.json({ deleted: req.params.id });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to delete todo' });\n }\n });\n\n // POST /:workspace/:id/start\n router.post('/:workspace/:id/start', async (req, res) => {\n try {\n const workspace = getWorkspaceParam(req.params.workspace);\n const result = await wsLock(workspace, async () => {\n const checklist = await readChecklist(todosDir, workspace);\n const item = checklist.items.find((i) => i.id === req.params.id);\n if (!item) return { error: 'not_found' as const };\n if (item.status === 'in_progress') return { error: 'conflict' as const, session: item.session };\n item.status = 'in_progress';\n item.session = req.body.session || null;\n if (req.body.branch) item.branch = req.body.branch;\n if (req.body.worktreePath) item.worktreePath = req.body.worktreePath;\n touchItem(item);\n await writeChecklist(todosDir, checklist);\n return { item: { ...item } };\n });\n if ('error' in result) {\n if (result.error === 'not_found') { res.status(404).json({ error: `Todo \"${req.params.id}\" not found` }); return; }\n res.status(409).json({ error: `Todo is already in progress (session: ${result.session})` }); return;\n }\n broadcastUpdate();\n res.json(result.item);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to start todo' });\n }\n });\n\n // POST /:workspace/:id/complete\n router.post('/:workspace/:id/complete', async (req, res) => {\n try {\n const workspace = getWorkspaceParam(req.params.workspace);\n const result = await wsLock(workspace, async () => {\n const checklist = await readChecklist(todosDir, workspace);\n const item = checklist.items.find((i) => i.id === req.params.id);\n if (!item) return null;\n item.status = 'completed';\n item.session = null;\n const branchForLog = req.body.branch || item.branch || null;\n touchItem(item);\n await writeChecklist(todosDir, checklist);\n\n const entry: LogEntry = {\n timestamp: new Date().toISOString(),\n itemIds: [item.id],\n items: item.description,\n session: req.body.session || null,\n branch: branchForLog,\n summary: req.body.summary || 'Completed.',\n blockers: null,\n status: null,\n };\n await appendLogEntry(todosDir, workspace, entry);\n return { ...item };\n });\n if (!result) { res.status(404).json({ error: `Todo \"${req.params.id}\" not found` }); return; }\n broadcastUpdate();\n res.json(result);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to complete todo' });\n }\n });\n\n // POST /:workspace/:id/block\n router.post('/:workspace/:id/block', async (req, res) => {\n try {\n const reason = req.body.reason || null;\n const workspace = getWorkspaceParam(req.params.workspace);\n const result = await wsLock(workspace, async () => {\n const checklist = await readChecklist(todosDir, workspace);\n const item = checklist.items.find((i) => i.id === req.params.id);\n if (!item) return null;\n item.status = 'blocked';\n item.session = null;\n touchItem(item);\n await writeChecklist(todosDir, checklist);\n\n const entry: LogEntry = {\n timestamp: new Date().toISOString(),\n itemIds: [item.id],\n items: item.description,\n session: req.body.session || null,\n branch: null,\n summary: reason || 'Blocked.',\n blockers: reason,\n status: 'blocked',\n };\n await appendLogEntry(todosDir, workspace, entry);\n return { ...item };\n });\n if (!result) { res.status(404).json({ error: `Todo \"${req.params.id}\" not found` }); return; }\n broadcastUpdate();\n res.json(result);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to block todo' });\n }\n });\n\n // POST /:workspace/:id/reopen — move completed back to open\n router.post('/:workspace/:id/reopen', async (req, res) => {\n try {\n const workspace = getWorkspaceParam(req.params.workspace);\n const result = await wsLock(workspace, async () => {\n const checklist = await readChecklist(todosDir, workspace);\n const item = checklist.items.find((i) => i.id === req.params.id);\n if (!item) return null;\n item.status = 'open';\n item.session = null;\n touchItem(item);\n await writeChecklist(todosDir, checklist);\n return { ...item };\n });\n if (!result) { res.status(404).json({ error: `Todo \"${req.params.id}\" not found` }); return; }\n broadcastUpdate();\n res.json(result);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to reopen todo' });\n }\n });\n\n // POST /:workspace/promote\n router.post('/:workspace/promote', async (req, res) => {\n try {\n const workspace = getWorkspaceParam(req.params.workspace);\n const { todoIds, mode, target, title, type, priority, keepSource } = req.body ?? {};\n if (!Array.isArray(todoIds) || todoIds.length === 0) {\n res.status(400).json({ error: 'todoIds (non-empty array of strings) is required' });\n return;\n }\n if (mode !== 'new-assignment' && mode !== 'to-assignment') {\n res.status(400).json({ error: 'mode must be \"new-assignment\" or \"to-assignment\"' });\n return;\n }\n\n const result = await wsLock(workspace, async () => {\n const checklist = await readChecklist(todosDir, workspace);\n const items: TodoItem[] = [];\n for (const id of todoIds) {\n const item = checklist.items.find((i) => i.id === id);\n if (!item) return { error: `Todo \"${id}\" not found` };\n if (item.status === 'completed') return { error: `Todo \"${id}\" is already completed` };\n items.push(item);\n }\n\n const scopeLabel = workspace === '_global' ? '_global' : `workspace:${workspace}`;\n\n if (mode === 'new-assignment') {\n if (items.length > 1 && !title) return { error: 'title is required when promoting multiple todos' };\n const parsed = parsePromoteTarget(target);\n if (!parsed.ok) return { error: parsed.error };\n const promoted = await promoteTodosToNewAssignment(\n [{ todosDir, workspace, items, scopeLabel }],\n {\n title: title || items[0].description,\n target: parsed.target,\n type,\n priority,\n keepSource,\n },\n );\n return {\n assignmentRef: promoted.assignmentRef,\n assignmentDir: promoted.assignmentDir,\n promoted: promoted.promoted.map((p) => p.id),\n };\n }\n\n // to-assignment mode (unchanged)\n const { resolve: resolvePath } = await import('node:path');\n const { readConfig } = await import('../utils/config.js');\n const { assignmentsDir: assignmentsDirFn } = await import('../utils/paths.js');\n const { fileExists, writeFileForce } = await import('../utils/fs.js');\n const { readFile } = await import('node:fs/promises');\n const { appendTodosToAssignmentBody, touchAssignmentUpdated } = await import('../utils/assignment-todos.js');\n const { nowTimestamp } = await import('../utils/timestamp.js');\n\n let assignmentRef: string;\n let assignmentDir: string;\n\n const tg: string = target?.assignment || '';\n if (!tg) return { error: 'target.assignment is required for to-assignment mode' };\n if (tg.includes('/')) {\n const parts = tg.split('/');\n if (parts.length !== 2) return { error: `Invalid target.assignment \"${tg}\"` };\n const config = await readConfig();\n assignmentDir = resolvePath(config.defaultProjectDir, parts[0], 'assignments', parts[1]);\n assignmentRef = `${parts[0]}/${parts[1]}`;\n } else if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(tg)) {\n assignmentDir = resolvePath(assignmentsDirFn(), tg);\n assignmentRef = tg;\n } else {\n return { error: `Invalid target.assignment \"${tg}\"` };\n }\n const assignmentMdPath = resolvePath(assignmentDir, 'assignment.md');\n if (!(await fileExists(assignmentMdPath))) return { error: `Target assignment not found: ${assignmentMdPath}` };\n\n let content = await readFile(assignmentMdPath, 'utf-8');\n content = appendTodosToAssignmentBody(\n content,\n items.map((it) => ({\n description: it.description,\n trace: `promoted from t:${it.id} in ${scopeLabel}`,\n })),\n );\n content = touchAssignmentUpdated(content, nowTimestamp());\n await writeFileForce(assignmentMdPath, content);\n\n if (!keepSource) {\n for (const item of items) {\n item.status = 'completed';\n item.session = null;\n touchItem(item);\n }\n await writeChecklist(todosDir, checklist);\n for (const item of items) {\n const entry: LogEntry = {\n timestamp: new Date().toISOString(),\n itemIds: [item.id],\n items: item.description,\n session: null,\n branch: item.branch || null,\n summary: `Promoted to assignment ${assignmentRef}`,\n blockers: null,\n status: null,\n };\n await appendLogEntry(todosDir, workspace, entry);\n }\n }\n\n return { assignmentRef, assignmentDir, promoted: items.map((i) => i.id) };\n });\n\n if ('error' in result) { res.status(400).json({ error: result.error }); return; }\n broadcastUpdate();\n res.json(result);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to promote todos' });\n }\n });\n\n // POST /:workspace/:id/move — cross-scope move (workspace/global ↔ project/global)\n router.post('/:workspace/:id/move', async (req, res) => {\n try {\n const sourceWs = getWorkspaceParam(req.params.workspace);\n const id = req.params.id;\n const to = req.body?.to;\n if (!to || typeof to !== 'object') {\n res.status(400).json({ error: 'body.to is required' });\n return;\n }\n const targetCount = [Boolean(to.workspace), Boolean(to.project), Boolean(to.global)].filter(Boolean).length;\n if (targetCount !== 1) {\n res.status(400).json({ error: 'body.to must specify exactly one of workspace, project, or global' });\n return;\n }\n if (to.project && !isValidSlug(to.project)) {\n res.status(400).json({ error: `Invalid target project slug: \"${to.project}\"` });\n return;\n }\n if (to.workspace && !WORKSPACE_REGEX.test(to.workspace)) {\n res.status(400).json({ error: `Invalid target workspace name: \"${to.workspace}\"` });\n return;\n }\n\n // Resolve target scope details (todosPath, scope id, lock key, broadcast).\n type Target =\n | { kind: 'workspace'; id: string; todosPath: string; lockKey: string }\n | { kind: 'project'; id: string; todosPath: string; lockKey: string };\n\n let target: Target;\n if (to.global) {\n target = { kind: 'workspace', id: '_global', todosPath: todosDir, lockKey: 'ws:_global' };\n } else if (to.workspace) {\n target = { kind: 'workspace', id: to.workspace, todosPath: todosDir, lockKey: `ws:${to.workspace}` };\n } else {\n if (!projectsDir) {\n res.status(500).json({ error: 'Server not configured with projectsDir; cannot move to project scope' });\n return;\n }\n const slug = to.project as string;\n const projectMd = resolvePath(projectsDir, slug, 'project.md');\n if (!(await fileExists(projectMd))) {\n res.status(404).json({ error: `Target project \"${slug}\" not found` });\n return;\n }\n target = {\n kind: 'project',\n id: slug,\n todosPath: projectTodosDir(projectsDir, slug),\n lockKey: `proj:${slug}`,\n };\n }\n\n const sourceLockKey = `ws:${sourceWs}`;\n if (sourceLockKey === target.lockKey) {\n res.status(400).json({ error: 'cannot move to the same scope' });\n return;\n }\n\n const result = await withTwoLocks(sourceLockKey, target.lockKey, async () => {\n const sourceChecklist = await readChecklist(todosDir, sourceWs);\n const targetChecklist = await readChecklist(target.todosPath, target.id);\n\n const idx = sourceChecklist.items.findIndex((i) => i.id === id);\n if (idx === -1) return { status: 404 as const, error: `Todo \"${id}\" not found` };\n\n if (targetChecklist.items.some((i) => i.id === id)) {\n return { status: 409 as const, error: 'id already exists in target' };\n }\n\n const item = sourceChecklist.items[idx];\n if (item.planDir) {\n const newPlanDir = todoPlanDir(target.todosPath, target.id, id);\n if (await fileExists(newPlanDir)) {\n return { status: 409 as const, error: 'plan dir already exists in target' };\n }\n await mkdir(dirname(newPlanDir), { recursive: true });\n await rename(item.planDir, newPlanDir);\n item.planDir = newPlanDir;\n }\n\n sourceChecklist.items.splice(idx, 1);\n targetChecklist.items.push(item);\n\n await writeChecklist(todosDir, sourceChecklist);\n await writeChecklist(target.todosPath, targetChecklist);\n\n const sourceLabel = sourceWs === '_global' ? '_global' : `workspace:${sourceWs}`;\n const targetLabel =\n target.kind === 'project' ? `project:${target.id}` : target.id === '_global' ? '_global' : `workspace:${target.id}`;\n const ts = new Date().toISOString();\n await appendLogEntry(todosDir, sourceWs, {\n timestamp: ts,\n itemIds: [id],\n items: item.description,\n session: null,\n branch: item.branch || null,\n summary: `Moved to ${targetLabel}`,\n blockers: null,\n status: null,\n });\n await appendLogEntry(target.todosPath, target.id, {\n timestamp: ts,\n itemIds: [id],\n items: item.description,\n session: null,\n branch: item.branch || null,\n summary: `Moved from ${sourceLabel}`,\n blockers: null,\n status: null,\n });\n\n return { status: 200 as const, item };\n });\n\n if (result.status !== 200) {\n res.status(result.status).json({ error: result.error });\n return;\n }\n\n // Dual broadcast: source scope, then target scope.\n broadcastUpdate(); // source is workspace\n if (target.kind === 'project') broadcastProject(target.id);\n else broadcastUpdate();\n\n res.json({ moved: id, to: target });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to move todo' });\n }\n });\n\n // POST /:workspace/:id/unblock\n router.post('/:workspace/:id/unblock', async (req, res) => {\n try {\n const workspace = getWorkspaceParam(req.params.workspace);\n const result = await wsLock(workspace, async () => {\n const checklist = await readChecklist(todosDir, workspace);\n const item = checklist.items.find((i) => i.id === req.params.id);\n if (!item) return null;\n item.status = 'open';\n item.session = null;\n touchItem(item);\n await writeChecklist(todosDir, checklist);\n return { ...item };\n });\n if (!result) { res.status(404).json({ error: `Todo \"${req.params.id}\" not found` }); return; }\n broadcastUpdate();\n res.json(result);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to unblock todo' });\n }\n });\n\n return router;\n}\n","import type { TodoItem, LogEntry } from '../todos/types.js';\nimport {\n readChecklist,\n writeChecklist,\n appendLogEntry,\n} from '../todos/parser.js';\nimport { createAssignmentCommand } from '../commands/create-assignment.js';\nimport { isValidSlug } from './slug.js';\n\nexport interface PromoteSourceGroup {\n /** Workspace todos dir OR projectTodosDir(...) for project-scope todos. */\n todosDir: string;\n /** Checklist workspace key (e.g. `_global`, `alpha`, or project slug for project todos). */\n workspace: string;\n /** Selected items from that checklist (already validated as non-completed). */\n items: TodoItem[];\n /** Human-readable scope label for log entries: `workspace:alpha` | `_global` | `project:foo`. */\n scopeLabel: string;\n}\n\nexport type PromoteTarget =\n | { project: string }\n | { oneOff: true; workspaceGroup?: string };\n\nexport interface PromoteToNewAssignmentOptions {\n title: string;\n target: PromoteTarget;\n type?: string;\n priority?: 'low' | 'medium' | 'high' | 'critical';\n keepSource?: boolean;\n}\n\nexport interface PromoteToNewAssignmentResult {\n id: string;\n slug: string;\n projectSlug: string | null;\n assignmentDir: string;\n assignmentRef: string;\n promoted: Array<{ workspace: string; id: string }>;\n promotedByWorkspace: Array<{ workspace: string; ids: string[] }>;\n}\n\n/**\n * Parse the JSON `target` field from a promote request body into the helper's\n * typed target. Returns `{ error }` for invalid combinations so callers can\n * surface the message verbatim (matching legacy validation messages where\n * possible).\n */\nexport function parsePromoteTarget(\n target: unknown,\n):\n | { ok: true; target: PromoteTarget }\n | { ok: false; error: string } {\n if (!target || typeof target !== 'object') {\n return { ok: false, error: 'target is required for new-assignment mode' };\n }\n const t = target as Record<string, unknown>;\n const hasProject = typeof t.project === 'string' && t.project.length > 0;\n const hasOneOff = t.oneOff === true;\n if (hasProject && hasOneOff) {\n return { ok: false, error: 'target cannot specify both project and oneOff' };\n }\n if (hasProject) {\n const project = t.project as string;\n if (!isValidSlug(project)) {\n return { ok: false, error: `Invalid target.project slug \"${project}\"` };\n }\n return { ok: true, target: { project } };\n }\n if (hasOneOff) {\n const wg = typeof t.workspaceGroup === 'string' ? t.workspaceGroup : undefined;\n if (wg !== undefined && !isValidSlug(wg)) {\n return { ok: false, error: `Invalid target.workspaceGroup slug \"${wg}\"` };\n }\n return { ok: true, target: { oneOff: true, workspaceGroup: wg } };\n }\n return { ok: false, error: 'target.project is required for new-assignment mode' };\n}\n\nfunction touchItem(item: TodoItem): void {\n const now = new Date().toISOString();\n if (item.createdAt === null) item.createdAt = now;\n item.updatedAt = now;\n}\n\n/**\n * Create a new assignment from the selected todos' descriptions and link the\n * source todos back to it. Source todos flip to `in_progress` with\n * `linkedAssignmentId` (UUID) and `linkedAssignmentRef` (`projectSlug/slug` or\n * bare UUID for one-off) populated, unless `keepSource` is true in which case\n * the source checklists are left untouched.\n */\nexport async function promoteTodosToNewAssignment(\n groups: PromoteSourceGroup[],\n options: PromoteToNewAssignmentOptions,\n): Promise<PromoteToNewAssignmentResult> {\n if (groups.length === 0 || groups.every((g) => g.items.length === 0)) {\n throw new Error('At least one source todo is required to promote.');\n }\n if (!options.title.trim()) {\n throw new Error('Title is required.');\n }\n\n const acceptanceCriteria: string[] = [];\n for (const g of groups) {\n for (const it of g.items) acceptanceCriteria.push(it.description);\n }\n\n const oneOff = 'oneOff' in options.target;\n const created = await createAssignmentCommand(options.title, {\n project: oneOff ? undefined : (options.target as { project: string }).project,\n oneOff: oneOff ? true : undefined,\n workspace: oneOff ? (options.target as { oneOff: true; workspaceGroup?: string }).workspaceGroup : undefined,\n type: options.type,\n priority: options.priority,\n acceptanceCriteria,\n withTodos: false,\n silent: true,\n });\n\n const assignmentRef = created.projectSlug\n ? `${created.projectSlug}/${created.slug}`\n : created.id;\n\n const promoted: Array<{ workspace: string; id: string }> = [];\n const promotedByWorkspace: Array<{ workspace: string; ids: string[] }> = [];\n\n if (!options.keepSource) {\n for (const group of groups) {\n // Re-read the checklist (caller is expected to hold the workspace lock\n // around this call when concurrency matters).\n const checklist = await readChecklist(group.todosDir, group.workspace);\n const idsTouched: string[] = [];\n for (const sel of group.items) {\n const item = checklist.items.find((i) => i.id === sel.id);\n if (!item) continue;\n item.status = 'in_progress';\n item.session = null;\n item.linkedAssignmentId = created.id;\n item.linkedAssignmentRef = assignmentRef;\n touchItem(item);\n idsTouched.push(item.id);\n }\n await writeChecklist(group.todosDir, checklist);\n for (const id of idsTouched) {\n const sourceItem = group.items.find((i) => i.id === id);\n const entry: LogEntry = {\n timestamp: new Date().toISOString(),\n itemIds: [id],\n items: sourceItem?.description ?? '',\n session: null,\n branch: sourceItem?.branch ?? null,\n summary: `Linked to assignment ${assignmentRef} (auto-promoted from ${group.scopeLabel})`,\n blockers: null,\n status: null,\n };\n await appendLogEntry(group.todosDir, group.workspace, entry);\n promoted.push({ workspace: group.workspace, id });\n }\n if (idsTouched.length > 0) {\n promotedByWorkspace.push({ workspace: group.workspace, ids: idsTouched });\n }\n }\n }\n\n return {\n id: created.id,\n slug: created.slug,\n projectSlug: created.projectSlug,\n assignmentDir: created.assignmentDir,\n assignmentRef,\n promoted,\n promotedByWorkspace,\n };\n}\n","import { resolve } from 'node:path';\nimport { slugify, isValidSlug } from '../utils/slug.js';\nimport { nowTimestamp } from '../utils/timestamp.js';\nimport { generateId } from '../utils/uuid.js';\nimport { expandHome, assignmentsDir as assignmentsDirFn } from '../utils/paths.js';\nimport { ensureDir, writeFileForce, fileExists } from '../utils/fs.js';\nimport { readConfig } from '../utils/config.js';\nimport {\n renderAssignment,\n renderScratchpad,\n renderHandoff,\n renderDecisionRecord,\n renderProgress,\n renderComments,\n} from '../templates/index.js';\n\nexport interface CreateAssignmentOptions {\n project?: string;\n oneOff?: boolean;\n slug?: string;\n priority?: 'low' | 'medium' | 'high' | 'critical';\n dependsOn?: string;\n links?: string;\n dir?: string;\n type?: string;\n withTodos?: boolean;\n workspace?: string;\n silent?: boolean;\n ready?: boolean;\n acceptanceCriteria?: string[];\n}\n\nexport interface CreateAssignmentResult {\n id: string;\n slug: string;\n projectSlug: string | null;\n assignmentDir: string;\n}\n\nexport async function createAssignmentCommand(\n title: string,\n options: CreateAssignmentOptions,\n): Promise<CreateAssignmentResult> {\n if (!title.trim()) {\n throw new Error('Assignment title cannot be empty.');\n }\n\n // --workspace guards run before the generic --project/--one-off guard so that\n // `--workspace <slug>` alone reports the actionable message rather than the\n // generic \"Either --project or --one-off is required.\" error.\n if (options.workspace && options.project) {\n throw new Error(\n 'Cannot use --workspace with --project (projects already carry a workspace via project.workspace).',\n );\n }\n if (options.workspace && !options.oneOff) {\n throw new Error('--workspace requires --one-off.');\n }\n\n if (!options.project && !options.oneOff) {\n throw new Error(\n 'Either --project <slug> or --one-off is required.',\n );\n }\n if (options.project && options.oneOff) {\n throw new Error(\n 'Cannot use both --project and --one-off. Use --project to add to an existing project, or --one-off to create a standalone assignment.',\n );\n }\n\n if (options.project && !isValidSlug(options.project)) {\n throw new Error(\n `Invalid project slug \"${options.project}\". Slugs must be lowercase, hyphen-separated, with no special characters.`,\n );\n }\n\n // Stricter than server.ts:240 / createProjectCommand by design — assignment slugs already use isValidSlug.\n if (options.workspace && !isValidSlug(options.workspace)) {\n throw new Error(\n `Invalid workspace slug \"${options.workspace}\". Slugs must be lowercase, hyphen-separated, with no special characters.`,\n );\n }\n\n if (options.oneOff && options.dependsOn) {\n throw new Error('Standalone assignments cannot have dependencies (--depends-on is not allowed with --one-off).');\n }\n\n const assignmentSlug = options.slug || slugify(title);\n if (!isValidSlug(assignmentSlug)) {\n throw new Error(\n `Invalid slug \"${assignmentSlug}\". Slugs must be lowercase, hyphen-separated, with no special characters.`,\n );\n }\n\n const dependsOn = options.dependsOn\n ? options.dependsOn.split(',').map((s) => s.trim()).filter(Boolean)\n : [];\n for (const dep of dependsOn) {\n if (!isValidSlug(dep)) {\n throw new Error(\n `Invalid dependency slug \"${dep}\". Slugs must be lowercase, hyphen-separated, with no special characters.`,\n );\n }\n }\n\n const links = options.links\n ? options.links.split(',').map((s) => s.trim()).filter(Boolean)\n : [];\n for (const link of links) {\n const parts = link.split('/');\n if (parts.length !== 2 || !parts.every(isValidSlug)) {\n throw new Error(\n `Invalid link \"${link}\". Links must be in projectSlug/assignmentSlug format (e.g., \"my-project/my-assignment\").`,\n );\n }\n }\n\n const validPriorities = ['low', 'medium', 'high', 'critical'] as const;\n const priority = (options.priority || 'medium') as typeof validPriorities[number];\n if (!validPriorities.includes(priority)) {\n throw new Error(\n `Invalid priority \"${options.priority}\". Must be one of: ${validPriorities.join(', ')}`,\n );\n }\n\n const config = await readConfig();\n const timestamp = nowTimestamp();\n const id = generateId();\n\n let assignmentDir: string;\n let projectSlug: string | null;\n let folderName: string;\n\n if (options.oneOff) {\n // Standalone: folder name = UUID, project: null\n const standaloneRoot = assignmentsDirFn();\n folderName = id;\n assignmentDir = resolve(standaloneRoot, folderName);\n projectSlug = null;\n await ensureDir(standaloneRoot);\n } else {\n const baseDir = options.dir\n ? expandHome(options.dir)\n : config.defaultProjectDir;\n projectSlug = options.project!;\n const projectDir = resolve(baseDir, projectSlug);\n\n const projectMdPath = resolve(projectDir, 'project.md');\n if (!(await fileExists(projectDir)) || !(await fileExists(projectMdPath))) {\n throw new Error(\n `Project \"${projectSlug}\" not found at ${projectDir}.\\nRun 'syntaur create-project' first or use --one-off.`,\n );\n }\n\n if (dependsOn.length > 0) {\n const depDirBase = resolve(projectDir, 'assignments');\n for (const dep of dependsOn) {\n const depDir = resolve(depDirBase, dep);\n if (!(await fileExists(depDir))) {\n console.warn(\n `Warning: dependency \"${dep}\" does not exist in project \"${projectSlug}\" yet.`,\n );\n }\n }\n }\n\n folderName = assignmentSlug;\n assignmentDir = resolve(projectDir, 'assignments', folderName);\n }\n\n if (await fileExists(assignmentDir)) {\n throw new Error(\n `Assignment folder already exists: ${assignmentDir}\\nUse --slug to specify a different slug.`,\n );\n }\n\n await ensureDir(assignmentDir);\n\n const companionAssignmentRef = projectSlug === null ? id : assignmentSlug;\n\n const files: Array<[string, string]> = [\n [\n resolve(assignmentDir, 'assignment.md'),\n renderAssignment({\n id,\n slug: assignmentSlug,\n title,\n timestamp,\n priority,\n dependsOn,\n links,\n project: projectSlug,\n workspaceGroup: options.workspace ?? null,\n type: options.type,\n includeTodos: options.withTodos === true,\n status: options.ready ? 'ready_for_planning' : 'draft',\n acceptanceCriteria: options.acceptanceCriteria,\n }),\n ],\n [\n resolve(assignmentDir, 'scratchpad.md'),\n renderScratchpad({\n assignmentSlug: companionAssignmentRef,\n timestamp,\n }),\n ],\n [\n resolve(assignmentDir, 'handoff.md'),\n renderHandoff({\n assignmentSlug: companionAssignmentRef,\n timestamp,\n }),\n ],\n [\n resolve(assignmentDir, 'decision-record.md'),\n renderDecisionRecord({\n assignmentSlug: companionAssignmentRef,\n timestamp,\n }),\n ],\n [\n resolve(assignmentDir, 'progress.md'),\n renderProgress({\n assignment: companionAssignmentRef,\n timestamp,\n }),\n ],\n [\n resolve(assignmentDir, 'comments.md'),\n renderComments({\n assignment: companionAssignmentRef,\n timestamp,\n }),\n ],\n ];\n\n for (const [filePath, content] of files) {\n await writeFileForce(filePath, content);\n }\n\n if (!options.silent) {\n if (projectSlug === null) {\n console.log(\n `Created standalone assignment \"${title}\" at ${assignmentDir}/`,\n );\n console.log(` UUID: ${id}`);\n console.log(` Slug: ${assignmentSlug} (display only)`);\n } else {\n console.log(\n `Created assignment \"${title}\" in project \"${projectSlug}\" at ${assignmentDir}/`,\n );\n console.log(` Slug: ${assignmentSlug}`);\n }\n console.log(` Priority: ${priority}`);\n if (options.type) {\n console.log(` Type: ${options.type}`);\n }\n if (dependsOn.length > 0) {\n console.log(` Depends on: ${dependsOn.join(', ')}`);\n }\n if (links.length > 0) {\n console.log(` Links: ${links.join(', ')}`);\n }\n console.log(` Files created:`);\n console.log(` assignment.md`);\n console.log(` scratchpad.md`);\n console.log(` handoff.md`);\n console.log(` decision-record.md`);\n console.log(` progress.md`);\n console.log(` comments.md`);\n console.log(\n ` Plan files (plan.md, plan-v2.md, ...) are created on demand by /plan-assignment.`,\n );\n }\n\n return { id, slug: assignmentSlug, projectSlug, assignmentDir };\n}\n","import { Router, type Request, type Response, type NextFunction } from 'express';\nimport { mkdir, readFile, rename } from 'node:fs/promises';\nimport { resolve, dirname } from 'node:path';\nimport {\n readChecklist,\n writeChecklist,\n readLog,\n appendLogEntry,\n archivePath,\n generateUniqueId,\n computeCounts,\n} from '../todos/parser.js';\nimport { fileExists, writeFileForce } from '../utils/fs.js';\nimport { projectTodosDir, todoPlanDir } from '../utils/paths.js';\nimport { isValidSlug } from '../utils/slug.js';\nimport { projLock, wsLock, withTwoLocks } from './todos-locks.js';\nimport type { TodoItem, LogEntry } from '../todos/types.js';\nimport type { WsMessage } from './types.js';\nimport {\n promoteTodosToNewAssignment,\n parsePromoteTarget,\n} from '../utils/promote-todos.js';\n\nconst WORKSPACE_REGEX = /^[a-z0-9_][a-z0-9-]*$/;\n\nfunction touchItem(item: TodoItem): void {\n const now = new Date().toISOString();\n if (item.createdAt === null) item.createdAt = now;\n item.updatedAt = now;\n}\n\nfunction getProjectIdParam(value: string | string[] | undefined): string {\n if (Array.isArray(value)) return value[0] ?? '';\n return value ?? '';\n}\n\ntype ProjectParams = { projectId?: string; id?: string };\nfunction params(req: Request): ProjectParams {\n return req.params as unknown as ProjectParams;\n}\n\nasync function projectExists(projectsDir: string, slug: string): Promise<boolean> {\n return fileExists(resolve(projectsDir, slug, 'project.md'));\n}\n\nasync function ensureProjectTodosDir(projectsDir: string, slug: string): Promise<void> {\n const todosDir = projectTodosDir(projectsDir, slug);\n try {\n await mkdir(todosDir, { recursive: false });\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === 'EEXIST') return;\n if (code === 'ENOENT') {\n const e = new Error('PROJECT_GONE');\n (e as NodeJS.ErrnoException).code = 'PROJECT_GONE';\n throw e;\n }\n throw err;\n }\n try {\n await mkdir(resolve(todosDir, 'archive'), { recursive: false });\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === 'EEXIST') return;\n if (code === 'ENOENT') {\n // Project (or its todos/) disappeared between the two mkdirs — map to\n // the same 404 path the caller already handles for PROJECT_GONE.\n const e = new Error('PROJECT_GONE');\n (e as NodeJS.ErrnoException).code = 'PROJECT_GONE';\n throw e;\n }\n throw err;\n }\n}\n\nfunction notFound(res: Response, slug: string): void {\n res.status(404).json({ error: `Project \"${slug}\" not found` });\n}\n\nexport function createProjectTodosRouter(\n projectsDir: string,\n broadcast: (msg: WsMessage) => void,\n workspaceTodosDir?: string,\n): Router {\n const router = Router({ mergeParams: true });\n\n function broadcastUpdate(projectSlug: string): void {\n broadcast({ type: 'todos-updated', projectSlug, timestamp: new Date().toISOString() });\n }\n function broadcastWorkspace(): void {\n broadcast({ type: 'todos-updated', timestamp: new Date().toISOString() });\n }\n\n function validateProjectId(req: Request, res: Response, next: NextFunction): void {\n const slug = getProjectIdParam(params(req).projectId);\n if (!slug || !isValidSlug(slug)) {\n res.status(400).json({ error: `Invalid project slug: \"${slug}\"` });\n return;\n }\n next();\n }\n\n // router.param only fires for params defined in the subrouter's own route\n // patterns. `:projectId` is on the parent mount path, so run the validator\n // as generic middleware instead.\n router.use(validateProjectId);\n\n // GET / — list this project's todos\n router.get('/', async (req, res) => {\n try {\n const slug = getProjectIdParam(params(req).projectId);\n if (!(await projectExists(projectsDir, slug))) { notFound(res, slug); return; }\n const todosDir = projectTodosDir(projectsDir, slug);\n const checklist = await readChecklist(todosDir, slug);\n res.json({\n workspace: checklist.workspace,\n archiveInterval: checklist.archiveInterval,\n items: checklist.items,\n counts: computeCounts(checklist.items),\n });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to get todos' });\n }\n });\n\n // POST / — add item\n router.post('/', async (req, res) => {\n try {\n const slug = getProjectIdParam(params(req).projectId);\n const { description, tags } = req.body;\n if (!description || typeof description !== 'string') {\n res.status(400).json({ error: 'description is required' });\n return;\n }\n if (!(await projectExists(projectsDir, slug))) { notFound(res, slug); return; }\n\n const item = await projLock(slug, async () => {\n if (!(await projectExists(projectsDir, slug))) return null;\n await ensureProjectTodosDir(projectsDir, slug);\n const todosDir = projectTodosDir(projectsDir, slug);\n const checklist = await readChecklist(todosDir, slug);\n const existingIds = new Set(checklist.items.map((i) => i.id));\n const id = generateUniqueId(existingIds);\n const now = new Date().toISOString();\n const newItem: TodoItem = {\n id,\n description,\n status: 'open',\n tags: Array.isArray(tags) ? tags : [],\n session: null,\n branch: null,\n worktreePath: null,\n createdAt: now,\n updatedAt: now,\n planDir: null,\n linkedAssignmentId: null,\n linkedAssignmentRef: null,\n };\n checklist.workspace = slug;\n checklist.items.push(newItem);\n await writeChecklist(todosDir, checklist);\n return newItem;\n });\n if (!item) { notFound(res, slug); return; }\n broadcastUpdate(slug);\n res.status(201).json(item);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'PROJECT_GONE') {\n notFound(res, getProjectIdParam(params(req).projectId));\n return;\n }\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to add todo' });\n }\n });\n\n // POST /reorder — reorder items (must precede /:id)\n router.post('/reorder', async (req, res) => {\n try {\n const slug = getProjectIdParam(params(req).projectId);\n const { ids } = req.body;\n if (!Array.isArray(ids) || !ids.every((id: unknown) => typeof id === 'string')) {\n res.status(400).json({ error: 'ids must be an array of strings' });\n return;\n }\n if (!(await projectExists(projectsDir, slug))) { notFound(res, slug); return; }\n\n const items = await projLock(slug, async () => {\n if (!(await projectExists(projectsDir, slug))) return null;\n await ensureProjectTodosDir(projectsDir, slug);\n const todosDir = projectTodosDir(projectsDir, slug);\n const checklist = await readChecklist(todosDir, slug);\n const itemMap = new Map(checklist.items.map((i) => [i.id, i]));\n const reordered: TodoItem[] = [];\n for (const id of ids) {\n const item = itemMap.get(id);\n if (item) { reordered.push(item); itemMap.delete(id); }\n }\n for (const item of itemMap.values()) reordered.push(item);\n checklist.workspace = slug;\n checklist.items = reordered;\n await writeChecklist(todosDir, checklist);\n return reordered;\n });\n if (!items) { notFound(res, slug); return; }\n broadcastUpdate(slug);\n res.json({ items });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'PROJECT_GONE') {\n notFound(res, getProjectIdParam(params(req).projectId));\n return;\n }\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to reorder todos' });\n }\n });\n\n // GET /log — full log (must precede /:id)\n router.get('/log', async (req, res) => {\n try {\n const slug = getProjectIdParam(params(req).projectId);\n if (!(await projectExists(projectsDir, slug))) { notFound(res, slug); return; }\n const todosDir = projectTodosDir(projectsDir, slug);\n const log = await readLog(todosDir, slug);\n res.json(log);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to get log' });\n }\n });\n\n // POST /archive\n router.post('/archive', async (req, res) => {\n try {\n const slug = getProjectIdParam(params(req).projectId);\n if (!(await projectExists(projectsDir, slug))) { notFound(res, slug); return; }\n const todosDir = projectTodosDir(projectsDir, slug);\n await ensureProjectTodosDir(projectsDir, slug);\n\n const checklist = await readChecklist(todosDir, slug);\n const log = await readLog(todosDir, slug);\n const completedIds = new Set(\n checklist.items.filter((i) => i.status === 'completed').map((i) => i.id),\n );\n if (completedIds.size === 0) {\n res.json({ archived: 0, message: 'No completed items to archive' });\n return;\n }\n const toArchive = log.entries.filter((e) =>\n e.itemIds.every((id) => completedIds.has(id)),\n );\n const archFile = archivePath(todosDir, slug, checklist.archiveInterval);\n let archContent = '';\n if (await fileExists(archFile)) {\n archContent = await readFile(archFile, 'utf-8');\n archContent = archContent.trimEnd() + '\\n\\n';\n } else {\n archContent = `---\\nworkspace: ${slug}\\n---\\n\\n# Archive\\n\\n`;\n }\n const completedItems = checklist.items.filter((i) => completedIds.has(i.id));\n for (const item of completedItems) {\n archContent += `- [x] ${item.description} ${item.tags.map((t: string) => `#${t}`).join(' ')} [t:${item.id}]\\n`;\n }\n archContent += '\\n';\n for (const entry of toArchive) {\n archContent += `### ${entry.timestamp} — ${entry.itemIds.map((i: string) => `t:${i}`).join(', ')}\\n`;\n if (entry.items) archContent += `**Items:** ${entry.items}\\n`;\n if (entry.session) archContent += `**Session:** ${entry.session}\\n`;\n if (entry.branch) archContent += `**Branch:** ${entry.branch}\\n`;\n if (entry.summary) archContent += `**Summary:** ${entry.summary}\\n`;\n if (entry.blockers) archContent += `**Blockers:** ${entry.blockers}\\n`;\n archContent += '\\n';\n }\n await writeFileForce(archFile, archContent);\n\n checklist.workspace = slug;\n checklist.items = checklist.items.filter((i) => !completedIds.has(i.id));\n await writeChecklist(todosDir, checklist);\n\n broadcastUpdate(slug);\n res.json({ archived: completedIds.size, logEntries: toArchive.length });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'PROJECT_GONE') {\n notFound(res, getProjectIdParam(params(req).projectId));\n return;\n }\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to archive' });\n }\n });\n\n // GET /log/:id — log for a specific item\n router.get('/log/:id', async (req, res) => {\n try {\n const slug = getProjectIdParam(params(req).projectId);\n if (!(await projectExists(projectsDir, slug))) { notFound(res, slug); return; }\n const todosDir = projectTodosDir(projectsDir, slug);\n const log = await readLog(todosDir, slug);\n const entries = log.entries.filter((e) => e.itemIds.includes((params(req).id ?? \"\")));\n res.json({ workspace: log.workspace, entries });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to get log' });\n }\n });\n\n // GET /:id — single item with log\n router.get('/:id', async (req, res) => {\n try {\n const slug = getProjectIdParam(params(req).projectId);\n if (!(await projectExists(projectsDir, slug))) { notFound(res, slug); return; }\n const todosDir = projectTodosDir(projectsDir, slug);\n const checklist = await readChecklist(todosDir, slug);\n const item = checklist.items.find((i) => i.id === (params(req).id ?? \"\"));\n if (!item) { res.status(404).json({ error: `Todo \"${(params(req).id ?? \"\")}\" not found` }); return; }\n const log = await readLog(todosDir, slug);\n const logEntries = log.entries.filter((e) => e.itemIds.includes((params(req).id ?? \"\")));\n res.json({ ...item, log: logEntries });\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to get todo' });\n }\n });\n\n // PATCH /:id\n router.patch('/:id', async (req, res) => {\n try {\n const slug = getProjectIdParam(params(req).projectId);\n if (!(await projectExists(projectsDir, slug))) { notFound(res, slug); return; }\n const result = await projLock(slug, async () => {\n if (!(await projectExists(projectsDir, slug))) return 'gone' as const;\n await ensureProjectTodosDir(projectsDir, slug);\n const todosDir = projectTodosDir(projectsDir, slug);\n const checklist = await readChecklist(todosDir, slug);\n const item = checklist.items.find((i) => i.id === (params(req).id ?? \"\"));\n if (!item) return null;\n if (req.body.description !== undefined) item.description = req.body.description;\n if (Array.isArray(req.body.tags)) item.tags = req.body.tags;\n touchItem(item);\n checklist.workspace = slug;\n await writeChecklist(todosDir, checklist);\n return { ...item };\n });\n if (result === 'gone') { notFound(res, slug); return; }\n if (!result) { res.status(404).json({ error: `Todo \"${(params(req).id ?? \"\")}\" not found` }); return; }\n broadcastUpdate(slug);\n res.json(result);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'PROJECT_GONE') {\n notFound(res, getProjectIdParam(params(req).projectId));\n return;\n }\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to update todo' });\n }\n });\n\n // DELETE /:id\n router.delete('/:id', async (req, res) => {\n try {\n const slug = getProjectIdParam(params(req).projectId);\n if (!(await projectExists(projectsDir, slug))) { notFound(res, slug); return; }\n const deleted = await projLock(slug, async () => {\n if (!(await projectExists(projectsDir, slug))) return 'gone' as const;\n await ensureProjectTodosDir(projectsDir, slug);\n const todosDir = projectTodosDir(projectsDir, slug);\n const checklist = await readChecklist(todosDir, slug);\n const idx = checklist.items.findIndex((i) => i.id === (params(req).id ?? \"\"));\n if (idx === -1) return false;\n checklist.items.splice(idx, 1);\n checklist.workspace = slug;\n await writeChecklist(todosDir, checklist);\n return true;\n });\n if (deleted === 'gone') { notFound(res, slug); return; }\n if (!deleted) { res.status(404).json({ error: `Todo \"${(params(req).id ?? \"\")}\" not found` }); return; }\n broadcastUpdate(slug);\n res.json({ deleted: (params(req).id ?? \"\") });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'PROJECT_GONE') {\n notFound(res, getProjectIdParam(params(req).projectId));\n return;\n }\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to delete todo' });\n }\n });\n\n // POST /:id/start\n router.post('/:id/start', async (req, res) => {\n try {\n const slug = getProjectIdParam(params(req).projectId);\n if (!(await projectExists(projectsDir, slug))) { notFound(res, slug); return; }\n const result = await projLock(slug, async () => {\n if (!(await projectExists(projectsDir, slug))) return { error: 'gone' as const };\n await ensureProjectTodosDir(projectsDir, slug);\n const todosDir = projectTodosDir(projectsDir, slug);\n const checklist = await readChecklist(todosDir, slug);\n const item = checklist.items.find((i) => i.id === (params(req).id ?? \"\"));\n if (!item) return { error: 'not_found' as const };\n if (item.status === 'in_progress') return { error: 'conflict' as const, session: item.session };\n item.status = 'in_progress';\n item.session = req.body.session || null;\n if (req.body.branch) item.branch = req.body.branch;\n if (req.body.worktreePath) item.worktreePath = req.body.worktreePath;\n touchItem(item);\n checklist.workspace = slug;\n await writeChecklist(todosDir, checklist);\n return { item: { ...item } };\n });\n if ('error' in result) {\n if (result.error === 'gone') { notFound(res, slug); return; }\n if (result.error === 'not_found') { res.status(404).json({ error: `Todo \"${(params(req).id ?? \"\")}\" not found` }); return; }\n res.status(409).json({ error: `Todo is already in progress (session: ${result.session})` });\n return;\n }\n broadcastUpdate(slug);\n res.json(result.item);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'PROJECT_GONE') {\n notFound(res, getProjectIdParam(params(req).projectId));\n return;\n }\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to start todo' });\n }\n });\n\n // POST /:id/complete\n router.post('/:id/complete', async (req, res) => {\n try {\n const slug = getProjectIdParam(params(req).projectId);\n if (!(await projectExists(projectsDir, slug))) { notFound(res, slug); return; }\n const result = await projLock(slug, async () => {\n if (!(await projectExists(projectsDir, slug))) return 'gone' as const;\n await ensureProjectTodosDir(projectsDir, slug);\n const todosDir = projectTodosDir(projectsDir, slug);\n const checklist = await readChecklist(todosDir, slug);\n const item = checklist.items.find((i) => i.id === (params(req).id ?? \"\"));\n if (!item) return null;\n item.status = 'completed';\n item.session = null;\n const branchForLog = req.body.branch || item.branch || null;\n touchItem(item);\n checklist.workspace = slug;\n await writeChecklist(todosDir, checklist);\n const entry: LogEntry = {\n timestamp: new Date().toISOString(),\n itemIds: [item.id],\n items: item.description,\n session: req.body.session || null,\n branch: branchForLog,\n summary: req.body.summary || 'Completed.',\n blockers: null,\n status: null,\n };\n await appendLogEntry(todosDir, slug, entry);\n return { ...item };\n });\n if (result === 'gone') { notFound(res, slug); return; }\n if (!result) { res.status(404).json({ error: `Todo \"${(params(req).id ?? \"\")}\" not found` }); return; }\n broadcastUpdate(slug);\n res.json(result);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'PROJECT_GONE') {\n notFound(res, getProjectIdParam(params(req).projectId));\n return;\n }\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to complete todo' });\n }\n });\n\n // POST /:id/block\n router.post('/:id/block', async (req, res) => {\n try {\n const slug = getProjectIdParam(params(req).projectId);\n const reason = req.body.reason || null;\n if (!(await projectExists(projectsDir, slug))) { notFound(res, slug); return; }\n const result = await projLock(slug, async () => {\n if (!(await projectExists(projectsDir, slug))) return 'gone' as const;\n await ensureProjectTodosDir(projectsDir, slug);\n const todosDir = projectTodosDir(projectsDir, slug);\n const checklist = await readChecklist(todosDir, slug);\n const item = checklist.items.find((i) => i.id === (params(req).id ?? \"\"));\n if (!item) return null;\n item.status = 'blocked';\n item.session = null;\n touchItem(item);\n checklist.workspace = slug;\n await writeChecklist(todosDir, checklist);\n const entry: LogEntry = {\n timestamp: new Date().toISOString(),\n itemIds: [item.id],\n items: item.description,\n session: req.body.session || null,\n branch: null,\n summary: reason || 'Blocked.',\n blockers: reason,\n status: 'blocked',\n };\n await appendLogEntry(todosDir, slug, entry);\n return { ...item };\n });\n if (result === 'gone') { notFound(res, slug); return; }\n if (!result) { res.status(404).json({ error: `Todo \"${(params(req).id ?? \"\")}\" not found` }); return; }\n broadcastUpdate(slug);\n res.json(result);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'PROJECT_GONE') {\n notFound(res, getProjectIdParam(params(req).projectId));\n return;\n }\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to block todo' });\n }\n });\n\n // POST /:id/reopen\n router.post('/:id/reopen', async (req, res) => {\n try {\n const slug = getProjectIdParam(params(req).projectId);\n if (!(await projectExists(projectsDir, slug))) { notFound(res, slug); return; }\n const result = await projLock(slug, async () => {\n if (!(await projectExists(projectsDir, slug))) return 'gone' as const;\n await ensureProjectTodosDir(projectsDir, slug);\n const todosDir = projectTodosDir(projectsDir, slug);\n const checklist = await readChecklist(todosDir, slug);\n const item = checklist.items.find((i) => i.id === (params(req).id ?? \"\"));\n if (!item) return null;\n item.status = 'open';\n item.session = null;\n touchItem(item);\n checklist.workspace = slug;\n await writeChecklist(todosDir, checklist);\n return { ...item };\n });\n if (result === 'gone') { notFound(res, slug); return; }\n if (!result) { res.status(404).json({ error: `Todo \"${(params(req).id ?? \"\")}\" not found` }); return; }\n broadcastUpdate(slug);\n res.json(result);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'PROJECT_GONE') {\n notFound(res, getProjectIdParam(params(req).projectId));\n return;\n }\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to reopen todo' });\n }\n });\n\n // POST /:id/unblock\n router.post('/:id/unblock', async (req, res) => {\n try {\n const slug = getProjectIdParam(params(req).projectId);\n if (!(await projectExists(projectsDir, slug))) { notFound(res, slug); return; }\n const result = await projLock(slug, async () => {\n if (!(await projectExists(projectsDir, slug))) return 'gone' as const;\n await ensureProjectTodosDir(projectsDir, slug);\n const todosDir = projectTodosDir(projectsDir, slug);\n const checklist = await readChecklist(todosDir, slug);\n const item = checklist.items.find((i) => i.id === (params(req).id ?? \"\"));\n if (!item) return null;\n item.status = 'open';\n item.session = null;\n touchItem(item);\n checklist.workspace = slug;\n await writeChecklist(todosDir, checklist);\n return { ...item };\n });\n if (result === 'gone') { notFound(res, slug); return; }\n if (!result) { res.status(404).json({ error: `Todo \"${(params(req).id ?? \"\")}\" not found` }); return; }\n broadcastUpdate(slug);\n res.json(result);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'PROJECT_GONE') {\n notFound(res, getProjectIdParam(params(req).projectId));\n return;\n }\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to unblock todo' });\n }\n });\n\n // POST /promote — mirror of workspace router; promotes selected project todos\n // to a new or existing assignment.\n router.post('/promote', async (req, res) => {\n try {\n const slug = getProjectIdParam(params(req).projectId);\n if (!(await projectExists(projectsDir, slug))) { notFound(res, slug); return; }\n\n const { todoIds, mode, target, title, type, priority, keepSource } = req.body ?? {};\n if (!Array.isArray(todoIds) || todoIds.length === 0) {\n res.status(400).json({ error: 'todoIds (non-empty array of strings) is required' });\n return;\n }\n if (mode !== 'new-assignment' && mode !== 'to-assignment') {\n res.status(400).json({ error: 'mode must be \"new-assignment\" or \"to-assignment\"' });\n return;\n }\n\n const result = await projLock(slug, async () => {\n if (!(await projectExists(projectsDir, slug))) return { gone: true } as const;\n await ensureProjectTodosDir(projectsDir, slug);\n const todosDir = projectTodosDir(projectsDir, slug);\n const checklist = await readChecklist(todosDir, slug);\n\n const items: TodoItem[] = [];\n for (const id of todoIds) {\n const item = checklist.items.find((i) => i.id === id);\n if (!item) return { error: `Todo \"${id}\" not found` };\n if (item.status === 'completed') return { error: `Todo \"${id}\" is already completed` };\n items.push(item);\n }\n\n const scopeLabel = `project:${slug}`;\n\n if (mode === 'new-assignment') {\n if (items.length > 1 && !title) return { error: 'title is required when promoting multiple todos' };\n // Project endpoint default: target.project = current project slug\n const rawTarget = target && typeof target === 'object' && (target.project || target.oneOff)\n ? target\n : { project: slug };\n const parsed = parsePromoteTarget(rawTarget);\n if (!parsed.ok) return { error: parsed.error };\n const promoted = await promoteTodosToNewAssignment(\n [{ todosDir, workspace: slug, items, scopeLabel }],\n {\n title: title || items[0].description,\n target: parsed.target,\n type,\n priority,\n keepSource,\n },\n );\n return {\n assignmentRef: promoted.assignmentRef,\n assignmentDir: promoted.assignmentDir,\n promoted: promoted.promoted.map((p) => p.id),\n };\n }\n\n // to-assignment mode (unchanged)\n const { assignmentsDir: assignmentsDirFn } = await import('../utils/paths.js');\n const { appendTodosToAssignmentBody, touchAssignmentUpdated } = await import(\n '../utils/assignment-todos.js'\n );\n const { nowTimestamp } = await import('../utils/timestamp.js');\n\n let assignmentRef: string;\n let assignmentDir: string;\n\n const tg: string = target?.assignment || '';\n if (!tg) return { error: 'target.assignment is required for to-assignment mode' };\n if (tg.includes('/')) {\n const parts = tg.split('/');\n if (parts.length !== 2) return { error: `Invalid target.assignment \"${tg}\"` };\n assignmentDir = resolve(projectsDir, parts[0], 'assignments', parts[1]);\n assignmentRef = `${parts[0]}/${parts[1]}`;\n } else if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(tg)) {\n assignmentDir = resolve(assignmentsDirFn(), tg);\n assignmentRef = tg;\n } else {\n return { error: `Invalid target.assignment \"${tg}\"` };\n }\n const assignmentMdPath = resolve(assignmentDir, 'assignment.md');\n if (!(await fileExists(assignmentMdPath))) return { error: `Target assignment not found: ${assignmentMdPath}` };\n\n let content = await readFile(assignmentMdPath, 'utf-8');\n content = appendTodosToAssignmentBody(\n content,\n items.map((it) => ({\n description: it.description,\n trace: `promoted from t:${it.id} in ${scopeLabel}`,\n })),\n );\n content = touchAssignmentUpdated(content, nowTimestamp());\n await writeFileForce(assignmentMdPath, content);\n\n if (!keepSource) {\n for (const item of items) {\n item.status = 'completed';\n item.session = null;\n touchItem(item);\n }\n checklist.workspace = slug;\n await writeChecklist(todosDir, checklist);\n for (const item of items) {\n const entry: LogEntry = {\n timestamp: new Date().toISOString(),\n itemIds: [item.id],\n items: item.description,\n session: null,\n branch: item.branch || null,\n summary: `Promoted to assignment ${assignmentRef}`,\n blockers: null,\n status: null,\n };\n await appendLogEntry(todosDir, slug, entry);\n }\n }\n\n return { assignmentRef, assignmentDir, promoted: items.map((i) => i.id) };\n });\n\n if ('gone' in result) { notFound(res, slug); return; }\n if ('error' in result) { res.status(400).json({ error: result.error }); return; }\n broadcastUpdate(slug);\n res.json(result);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'PROJECT_GONE') {\n notFound(res, getProjectIdParam(params(req).projectId));\n return;\n }\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to promote todos' });\n }\n });\n\n // POST /:id/move — cross-scope move from a project to workspace/project/global\n router.post('/:id/move', async (req, res) => {\n try {\n const sourceSlug = getProjectIdParam(params(req).projectId);\n const id = params(req).id ?? '';\n if (!(await projectExists(projectsDir, sourceSlug))) { notFound(res, sourceSlug); return; }\n\n const to = req.body?.to;\n if (!to || typeof to !== 'object') {\n res.status(400).json({ error: 'body.to is required' });\n return;\n }\n const targetCount = [Boolean(to.workspace), Boolean(to.project), Boolean(to.global)].filter(Boolean).length;\n if (targetCount !== 1) {\n res.status(400).json({ error: 'body.to must specify exactly one of workspace, project, or global' });\n return;\n }\n if (to.project && !isValidSlug(to.project)) {\n res.status(400).json({ error: `Invalid target project slug: \"${to.project}\"` });\n return;\n }\n if (to.workspace && !WORKSPACE_REGEX.test(to.workspace)) {\n res.status(400).json({ error: `Invalid target workspace name: \"${to.workspace}\"` });\n return;\n }\n\n type Target =\n | { kind: 'workspace'; id: string; todosPath: string; lockKey: string }\n | { kind: 'project'; id: string; todosPath: string; lockKey: string };\n\n let target: Target;\n if (to.global) {\n if (!workspaceTodosDir) {\n res.status(500).json({ error: 'Server not configured with workspaceTodosDir; cannot move to global scope' });\n return;\n }\n target = { kind: 'workspace', id: '_global', todosPath: workspaceTodosDir, lockKey: 'ws:_global' };\n } else if (to.workspace) {\n if (!workspaceTodosDir) {\n res.status(500).json({ error: 'Server not configured with workspaceTodosDir; cannot move to workspace scope' });\n return;\n }\n target = { kind: 'workspace', id: to.workspace, todosPath: workspaceTodosDir, lockKey: `ws:${to.workspace}` };\n } else {\n const tslug = to.project as string;\n if (!(await projectExists(projectsDir, tslug))) {\n res.status(404).json({ error: `Target project \"${tslug}\" not found` });\n return;\n }\n target = {\n kind: 'project',\n id: tslug,\n todosPath: projectTodosDir(projectsDir, tslug),\n lockKey: `proj:${tslug}`,\n };\n }\n\n const sourceLockKey = `proj:${sourceSlug}`;\n if (sourceLockKey === target.lockKey) {\n res.status(400).json({ error: 'cannot move to the same scope' });\n return;\n }\n\n const result = await withTwoLocks(sourceLockKey, target.lockKey, async () => {\n if (!(await projectExists(projectsDir, sourceSlug))) return { status: 'gone' as const };\n if (target.kind === 'project' && !(await projectExists(projectsDir, target.id))) {\n return { status: 'targetGone' as const };\n }\n await ensureProjectTodosDir(projectsDir, sourceSlug);\n const sourceTodosDir = projectTodosDir(projectsDir, sourceSlug);\n const sourceChecklist = await readChecklist(sourceTodosDir, sourceSlug);\n const targetChecklist = await readChecklist(target.todosPath, target.id);\n\n const idx = sourceChecklist.items.findIndex((i) => i.id === id);\n if (idx === -1) return { status: 404 as const, error: `Todo \"${id}\" not found` };\n\n if (targetChecklist.items.some((i) => i.id === id)) {\n return { status: 409 as const, error: 'id already exists in target' };\n }\n\n const item = sourceChecklist.items[idx];\n if (item.planDir) {\n const newPlanDir = todoPlanDir(target.todosPath, target.id, id);\n if (await fileExists(newPlanDir)) {\n return { status: 409 as const, error: 'plan dir already exists in target' };\n }\n await mkdir(dirname(newPlanDir), { recursive: true });\n await rename(item.planDir, newPlanDir);\n item.planDir = newPlanDir;\n }\n\n sourceChecklist.items.splice(idx, 1);\n targetChecklist.items.push(item);\n\n sourceChecklist.workspace = sourceSlug;\n await writeChecklist(sourceTodosDir, sourceChecklist);\n await writeChecklist(target.todosPath, targetChecklist);\n\n const sourceLabel = `project:${sourceSlug}`;\n const targetLabel =\n target.kind === 'project' ? `project:${target.id}` : target.id === '_global' ? '_global' : `workspace:${target.id}`;\n const ts = new Date().toISOString();\n await appendLogEntry(sourceTodosDir, sourceSlug, {\n timestamp: ts,\n itemIds: [id],\n items: item.description,\n session: null,\n branch: item.branch || null,\n summary: `Moved to ${targetLabel}`,\n blockers: null,\n status: null,\n });\n await appendLogEntry(target.todosPath, target.id, {\n timestamp: ts,\n itemIds: [id],\n items: item.description,\n session: null,\n branch: item.branch || null,\n summary: `Moved from ${sourceLabel}`,\n blockers: null,\n status: null,\n });\n\n return { status: 200 as const, item };\n });\n\n if (result.status === 'gone') { notFound(res, sourceSlug); return; }\n if (result.status === 'targetGone') {\n res.status(404).json({ error: `Target project \"${(target as { id: string }).id}\" not found` });\n return;\n }\n if (result.status !== 200) {\n res.status(result.status).json({ error: result.error });\n return;\n }\n\n broadcastUpdate(sourceSlug);\n if (target.kind === 'project') broadcastUpdate(target.id);\n else broadcastWorkspace();\n\n res.json({ moved: id, to: target });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'PROJECT_GONE') {\n notFound(res, getProjectIdParam(params(req).projectId));\n return;\n }\n res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to move todo' });\n }\n });\n\n return router;\n}\n","import { Router } from 'express';\nimport { updateBackupConfig } from '../utils/config.js';\nimport {\n backupToGithub,\n restoreFromGithub,\n getBackupStatus,\n parseCategoriesStrict,\n validateRepoUrl,\n VALID_CATEGORIES,\n} from '../utils/github-backup.js';\n\nexport function createBackupRouter(): Router {\n const router = Router();\n\n router.get('/', async (_req, res) => {\n try {\n const status = await getBackupStatus();\n res.json(status);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : String(error) });\n }\n });\n\n router.put('/config', async (req, res) => {\n try {\n const body = req.body ?? {};\n const updates: { repo?: string; categories?: string } = {};\n\n if (body.repo !== undefined) {\n const trimmed = typeof body.repo === 'string' ? body.repo.trim() : body.repo;\n if (trimmed !== null && trimmed !== '' && !validateRepoUrl(trimmed)) {\n return res.status(400).json({\n error: `Invalid repo URL. Must start with https:// or git@.`,\n });\n }\n updates.repo = trimmed || null as unknown as string;\n }\n\n if (body.categories !== undefined) {\n let cats: string[];\n if (Array.isArray(body.categories)) {\n cats = body.categories.map((s: unknown) => String(s).trim()).filter(Boolean);\n } else if (typeof body.categories === 'string') {\n cats = body.categories.split(',').map((s: string) => s.trim()).filter(Boolean);\n } else {\n return res.status(400).json({ error: 'categories must be a string or array' });\n }\n if (cats.length === 0) {\n return res.status(400).json({\n error: `No categories provided. Valid: ${VALID_CATEGORIES.join(', ')}`,\n });\n }\n try {\n const valid = parseCategoriesStrict(cats);\n updates.categories = valid.join(', ');\n } catch (err) {\n return res.status(400).json({\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n if (Object.keys(updates).length === 0) {\n return res.status(400).json({ error: 'No fields to update' });\n }\n\n await updateBackupConfig(updates);\n const status = await getBackupStatus();\n res.json(status);\n } catch (error) {\n res.status(500).json({ error: error instanceof Error ? error.message : String(error) });\n }\n });\n\n router.post('/push', async (_req, res) => {\n try {\n const result = await backupToGithub();\n res.json(result);\n } catch (error) {\n res.status(500).json({\n success: false,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n });\n\n router.post('/pull', async (_req, res) => {\n try {\n const result = await restoreFromGithub();\n res.json(result);\n } catch (error) {\n res.status(500).json({\n success: false,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n });\n\n return router;\n}\n","import { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { cp, mkdtemp, rm, readFile, writeFile, unlink, stat, open, rename } from 'node:fs/promises';\nimport { resolve, join } from 'node:path';\nimport { tmpdir } from 'node:os';\nimport { syntaurRoot, playbooksDir, todosDir, serversDir } from './paths.js';\nimport { ensureDir, fileExists } from './fs.js';\nimport { readConfig, updateBackupConfig, type BackupConfig } from './config.js';\n\nconst exec = promisify(execFile);\n\nexport const VALID_CATEGORIES = ['projects', 'playbooks', 'todos', 'servers', 'config'] as const;\nexport type BackupCategory = (typeof VALID_CATEGORIES)[number];\n\nconst LOCK_FILE_NAME = '.backup-lock';\n\nexport function parseCategories(csv: string): BackupCategory[] {\n return csv\n .split(',')\n .map((s) => s.trim())\n .filter((s): s is BackupCategory => (VALID_CATEGORIES as readonly string[]).includes(s));\n}\n\nexport function validateCategories(cats: string[]): BackupCategory[] {\n const valid: BackupCategory[] = [];\n for (const cat of cats) {\n if ((VALID_CATEGORIES as readonly string[]).includes(cat)) {\n valid.push(cat as BackupCategory);\n } else {\n console.warn(`Warning: unknown backup category \"${cat}\", skipping`);\n }\n }\n return valid;\n}\n\nexport function parseCategoriesStrict(cats: string[]): BackupCategory[] {\n const unknown: string[] = [];\n const valid: BackupCategory[] = [];\n for (const cat of cats) {\n if ((VALID_CATEGORIES as readonly string[]).includes(cat)) {\n valid.push(cat as BackupCategory);\n } else {\n unknown.push(cat);\n }\n }\n if (unknown.length > 0) {\n throw new Error(\n `Unknown categor${unknown.length === 1 ? 'y' : 'ies'}: ${unknown.map((c) => `\"${c}\"`).join(', ')}. Valid: ${VALID_CATEGORIES.join(', ')}`,\n );\n }\n return valid;\n}\n\nexport function validateRepoUrl(url: string): boolean {\n if (!url || typeof url !== 'string') return false;\n const trimmed = url.trim();\n return trimmed.startsWith('https://') || trimmed.startsWith('git@');\n}\n\nexport async function resolveCategoryPath(\n category: BackupCategory,\n): Promise<{ sourcePath: string; repoPath: string; isFile: boolean }> {\n switch (category) {\n case 'projects': {\n const config = await readConfig();\n return { sourcePath: config.defaultProjectDir, repoPath: 'projects', isFile: false };\n }\n case 'playbooks':\n return { sourcePath: playbooksDir(), repoPath: 'playbooks', isFile: false };\n case 'todos':\n return { sourcePath: todosDir(), repoPath: 'todos', isFile: false };\n case 'servers':\n return { sourcePath: serversDir(), repoPath: 'servers', isFile: false };\n case 'config':\n return { sourcePath: resolve(syntaurRoot(), 'config.md'), repoPath: 'config.md', isFile: true };\n }\n}\n\nasync function checkGitInstalled(): Promise<void> {\n try {\n await exec('git', ['--version']);\n } catch {\n throw new Error('git is not installed or not on PATH. Install git and try again.');\n }\n}\n\nasync function acquireLock(): Promise<string> {\n const lockPath = resolve(syntaurRoot(), LOCK_FILE_NAME);\n await ensureDir(syntaurRoot());\n try {\n const handle = await open(lockPath, 'wx');\n await handle.write(String(process.pid));\n await handle.close();\n return lockPath;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'EEXIST') {\n const pid = await readFile(lockPath, 'utf-8').catch(() => '');\n throw new Error(\n `Backup operation already in progress (lock file at ${lockPath}, pid ${pid.trim() || 'unknown'}). If stale, delete the file and retry.`,\n );\n }\n throw err;\n }\n}\n\nasync function releaseLock(lockPath: string): Promise<void> {\n try {\n await unlink(lockPath);\n } catch {\n // ignore\n }\n}\n\nasync function runGit(args: string[], cwd: string): Promise<{ stdout: string; stderr: string }> {\n return exec('git', args, { cwd });\n}\n\nasync function cloneOrInit(repoUrl: string, destDir: string): Promise<void> {\n try {\n await exec('git', ['clone', '--depth', '1', repoUrl, destDir]);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (message.includes('Repository not found') || message.includes('does not appear to be a git repository')) {\n throw new Error(`Repository not found or inaccessible: ${repoUrl}. Check URL and credentials.`);\n }\n if (message.includes('Authentication failed') || message.includes('could not read Username')) {\n throw new Error(`Authentication failed for ${repoUrl}. Check SSH keys or credentials.`);\n }\n throw new Error(`git clone failed: ${message}`);\n }\n}\n\nasync function copyRecursive(src: string, dest: string): Promise<void> {\n if (!(await fileExists(src))) return;\n const s = await stat(src);\n if (s.isDirectory()) {\n await ensureDir(dest);\n await cp(src, dest, { recursive: true, force: true });\n } else {\n await ensureDir(resolve(dest, '..'));\n await cp(src, dest, { force: true });\n }\n}\n\nexport interface BackupResult {\n success: boolean;\n timestamp: string;\n message: string;\n committed: boolean;\n}\n\nfunction resolveCategoriesStrict(csv: string): BackupCategory[] {\n const parts = csv.split(',').map((s) => s.trim()).filter(Boolean);\n return parseCategoriesStrict(parts);\n}\n\n/**\n * Read config.md and return a version with lastBackup/lastRestore set to null.\n * This is the copy that goes into the backup repo, so those timestamps — which\n * mutate on every local operation — never cause a self-diff on subsequent backups.\n */\nexport async function readSanitizedConfig(configPath: string): Promise<string> {\n const content = await readFile(configPath, 'utf-8');\n return content\n .replace(/^(\\s*lastBackup:\\s*).*$/m, '$1null')\n .replace(/^(\\s*lastRestore:\\s*).*$/m, '$1null');\n}\n\nexport async function backupToGithub(overrides?: {\n repo?: string;\n categories?: BackupCategory[];\n}): Promise<BackupResult> {\n await checkGitInstalled();\n const config = await readConfig();\n const rawRepo = overrides?.repo ?? config.backup?.repo ?? null;\n if (!rawRepo) {\n throw new Error('No backup repo configured. Set it via `syntaur backup config --repo <url>` or the dashboard.');\n }\n const repo = rawRepo.trim();\n if (!validateRepoUrl(repo)) {\n throw new Error(`Invalid repo URL: \"${rawRepo}\". Must start with https:// or git@.`);\n }\n\n const categoriesCsv = config.backup?.categories ?? 'projects, playbooks, todos, servers, config';\n const categories = overrides?.categories ?? resolveCategoriesStrict(categoriesCsv);\n if (categories.length === 0) {\n throw new Error('No valid backup categories selected.');\n }\n\n const lockPath = await acquireLock();\n let tmpDir: string | null = null;\n const timestamp = new Date().toISOString();\n\n try {\n tmpDir = await mkdtemp(join(tmpdir(), 'syntaur-backup-'));\n await cloneOrInit(repo, tmpDir);\n\n // Copy each selected category into the repo clone.\n // Always clear the destination first so local deletions propagate to the repo.\n for (const category of categories) {\n const { sourcePath, repoPath, isFile } = await resolveCategoryPath(category);\n const destPath = join(tmpDir, repoPath);\n\n if (isFile) {\n await rm(destPath, { force: true });\n } else {\n await rm(destPath, { recursive: true, force: true });\n }\n\n if (!(await fileExists(sourcePath))) {\n console.warn(`Category \"${category}\": no local data at ${sourcePath}; backup will reflect deletion.`);\n continue;\n }\n\n if (category === 'config') {\n // Sanitize config.md before writing to the repo: strip lastBackup/lastRestore\n // timestamps so they don't cause a self-diff on every backup.\n const sanitized = await readSanitizedConfig(sourcePath);\n await ensureDir(resolve(destPath, '..'));\n await writeFile(destPath, sanitized, 'utf-8');\n } else {\n await copyRecursive(sourcePath, destPath);\n }\n }\n\n // Stage and check for changes\n await runGit(['add', '-A'], tmpDir);\n const { stdout: status } = await runGit(['status', '--porcelain'], tmpDir);\n if (!status.trim()) {\n // No-op but successful: persist timestamp so UI reflects the completed check\n await updateBackupConfig({ lastBackup: timestamp }).catch(() => {});\n return {\n success: true,\n timestamp,\n message: 'No changes to back up.',\n committed: false,\n };\n }\n\n // Configure committer if unset (best-effort; user may have global config)\n try {\n await runGit(['config', 'user.email', 'syntaur@local'], tmpDir);\n await runGit(['config', 'user.name', 'Syntaur Backup'], tmpDir);\n } catch {\n // ignore\n }\n\n await runGit(['commit', '-m', `Syntaur backup ${timestamp}`], tmpDir);\n\n try {\n await runGit(['push'], tmpDir);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (message.includes('non-fast-forward') || message.includes('rejected')) {\n throw new Error('Push rejected (non-fast-forward). Pull and resolve manually, or delete remote contents.');\n }\n if (message.includes('Authentication') || message.includes('could not read Username')) {\n throw new Error('Push authentication failed. Check SSH keys or credentials.');\n }\n throw new Error(`git push failed: ${message}`);\n }\n\n // Push succeeded: persist timestamp\n await updateBackupConfig({ lastBackup: timestamp }).catch(() => {});\n\n return {\n success: true,\n timestamp,\n message: `Backed up ${categories.length} categor${categories.length === 1 ? 'y' : 'ies'} to ${repo}.`,\n committed: true,\n };\n } finally {\n if (tmpDir) {\n await rm(tmpDir, { recursive: true, force: true }).catch(() => {});\n }\n await releaseLock(lockPath);\n }\n}\n\nexport async function safeRestoreCategory(\n localPath: string,\n repoSrcPath: string,\n isFile: boolean,\n): Promise<void> {\n if (isFile) {\n // Single file: cp handles atomic rename internally. No staging needed.\n await ensureDir(resolve(localPath, '..'));\n await cp(repoSrcPath, localPath, { force: true });\n return;\n }\n\n // Directory: stage, then swap.\n const stagingPath = `${localPath}.syntaur-restore-staging`;\n const backupPath = `${localPath}.syntaur-restore-backup`;\n\n // Stale staging from a crashed run is always safe to discard.\n await rm(stagingPath, { recursive: true, force: true });\n\n // A pre-existing backup dir means a prior run crashed mid-swap and it may contain\n // the only copy of the user's original data. Do NOT delete it blindly.\n const backupExistsBefore = await fileExists(backupPath);\n const localExistsBefore = await fileExists(localPath);\n if (backupExistsBefore) {\n if (!localExistsBefore) {\n // Prior crash left the backup as the only copy. Restore it first.\n await rename(backupPath, localPath);\n } else {\n // Both exist — we can't tell which is authoritative. Bail out.\n throw new Error(\n `Cannot restore \"${localPath}\": a stale crash-recovery backup exists at ${backupPath} while the current path also exists. ` +\n `Inspect both and remove the one you don't need, then retry.`,\n );\n }\n }\n\n let localMovedAside = false;\n try {\n // Copy repo contents into staging. If this fails, local is untouched.\n await cp(repoSrcPath, stagingPath, { recursive: true, force: true });\n\n // Move current local aside (if it exists).\n const localExists = await fileExists(localPath);\n if (localExists) {\n await rename(localPath, backupPath);\n localMovedAside = true;\n }\n\n // Swap staging into place.\n await rename(stagingPath, localPath);\n\n // Success: remove the old data.\n await rm(backupPath, { recursive: true, force: true }).catch(() => {});\n } catch (err) {\n // Roll back: restore original if we moved it aside.\n if (localMovedAside && (await fileExists(backupPath))) {\n await rename(backupPath, localPath).catch(() => {});\n }\n // Always clean up staging (may or may not exist depending on where we failed).\n await rm(stagingPath, { recursive: true, force: true }).catch(() => {});\n throw err;\n }\n}\n\nexport async function restoreFromGithub(overrides?: {\n repo?: string;\n categories?: BackupCategory[];\n}): Promise<BackupResult> {\n await checkGitInstalled();\n const config = await readConfig();\n const rawRepo = overrides?.repo ?? config.backup?.repo ?? null;\n if (!rawRepo) {\n throw new Error('No backup repo configured.');\n }\n const repo = rawRepo.trim();\n if (!validateRepoUrl(repo)) {\n throw new Error(`Invalid repo URL: \"${rawRepo}\".`);\n }\n\n const categoriesCsv = config.backup?.categories ?? 'projects, playbooks, todos, servers, config';\n const categories = overrides?.categories ?? resolveCategoriesStrict(categoriesCsv);\n if (categories.length === 0) {\n throw new Error('No valid restore categories selected.');\n }\n\n const lockPath = await acquireLock();\n let tmpDir: string | null = null;\n const restored: string[] = [];\n const failed: string[] = [];\n const timestamp = new Date().toISOString();\n\n try {\n // Persist timestamp before work so UI reflects the attempt even on partial failure.\n // Inside try so lock is released even if config write fails.\n await updateBackupConfig({ lastRestore: timestamp });\n\n tmpDir = await mkdtemp(join(tmpdir(), 'syntaur-restore-'));\n await cloneOrInit(repo, tmpDir);\n\n for (const category of categories) {\n // Never overwrite config.md on restore — would clobber backup settings\n if (category === 'config') {\n console.warn('Skipping \"config\" on restore (would overwrite local backup settings).');\n continue;\n }\n try {\n const { sourcePath: localPath, repoPath, isFile } = await resolveCategoryPath(category);\n const repoSrcPath = join(tmpDir, repoPath);\n if (!(await fileExists(repoSrcPath))) {\n console.warn(`Category \"${category}\" not found in backup repo, skipping.`);\n continue;\n }\n await safeRestoreCategory(localPath, repoSrcPath, isFile);\n restored.push(category);\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n console.error(`Failed to restore \"${category}\": ${msg}`);\n failed.push(category);\n }\n }\n\n const success = failed.length === 0;\n return {\n success,\n timestamp,\n message: success\n ? `Restored ${restored.length} categor${restored.length === 1 ? 'y' : 'ies'} from ${repo}.`\n : `Partial restore: ${restored.length} succeeded, ${failed.length} failed (${failed.join(', ')}).`,\n committed: false,\n };\n } finally {\n if (tmpDir) {\n await rm(tmpDir, { recursive: true, force: true }).catch(() => {});\n }\n await releaseLock(lockPath);\n }\n}\n\nexport async function getBackupStatus(): Promise<{\n repo: string | null;\n categories: string;\n lastBackup: string | null;\n lastRestore: string | null;\n locked: boolean;\n}> {\n const config = await readConfig();\n const lockPath = resolve(syntaurRoot(), LOCK_FILE_NAME);\n const locked = await fileExists(lockPath);\n return {\n repo: config.backup?.repo ?? null,\n categories: config.backup?.categories ?? 'projects, playbooks, todos, servers, config',\n lastBackup: config.backup?.lastBackup ?? null,\n lastRestore: config.backup?.lastRestore ?? null,\n locked,\n };\n}\n","import {\n execQuiet,\n checkTmuxAvailable,\n sessionAlive,\n listTmuxPanes,\n getLsofOutput,\n loadWorkspaceRecords,\n autoLinkPane,\n getGitInfo,\n clearScanCache,\n} from './scanner.js';\nimport {\n readSessionFile,\n listSessionFiles,\n registerAutoSession,\n removeSession,\n sanitizeSessionName,\n} from './servers.js';\nimport type { SessionFileData } from './types.js';\n\n// --- Shared lsof helpers ---\n\nexport function parsePortsForPid(lsofOutput: string, targetPid: number): number[] {\n const ports: number[] = [];\n for (const line of lsofOutput.split('\\n')) {\n const parts = line.trim().split(/\\s+/);\n if (parts.length < 9) continue;\n const pid = parseInt(parts[1], 10);\n if (pid !== targetPid) continue;\n const tcpAddr = parts.find((p) => p.includes(':') && /:\\d+$/.test(p));\n if (tcpAddr) {\n const port = parseInt(tcpAddr.split(':').pop()!, 10);\n if (!isNaN(port) && !ports.includes(port)) ports.push(port);\n }\n }\n return ports;\n}\n\nexport function parseLsofForListeningProcesses(lsofOutput: string): ListeningProcess[] {\n const seen = new Map<number, ListeningProcess>();\n for (const line of lsofOutput.split('\\n')) {\n const parts = line.trim().split(/\\s+/);\n if (parts.length < 9) continue;\n const command = parts[0];\n const pid = parseInt(parts[1], 10);\n if (isNaN(pid)) continue;\n const tcpAddr = parts.find((p) => p.includes(':') && /:\\d+$/.test(p));\n if (!tcpAddr) continue;\n const port = parseInt(tcpAddr.split(':').pop()!, 10);\n if (isNaN(port)) continue;\n\n if (!seen.has(pid)) {\n seen.set(pid, { pid, port, command });\n }\n }\n return Array.from(seen.values());\n}\n\n// --- Singleton lifecycle ---\n\nlet timer: ReturnType<typeof setInterval> | null = null;\nlet activeReconcile: Promise<void> | null = null;\n\nexport interface AutodiscoveryOptions {\n serversDir: string;\n projectsDir: string;\n assignmentsDir?: string;\n intervalMs?: number;\n excludePids?: Set<number>;\n}\n\nlet savedOptions: AutodiscoveryOptions | null = null;\n\nexport function startAutodiscovery(opts: AutodiscoveryOptions): void {\n if (timer) return;\n savedOptions = opts;\n const interval = opts.intervalMs ?? 45_000;\n // Run once immediately, then on interval\n runReconcile();\n timer = setInterval(() => {\n runReconcile();\n }, interval);\n}\n\nexport async function stopAutodiscovery(): Promise<void> {\n if (timer) {\n clearInterval(timer);\n timer = null;\n }\n // Await in-flight reconcile to prevent overlap\n if (activeReconcile) {\n await activeReconcile;\n activeReconcile = null;\n }\n savedOptions = null;\n}\n\nfunction runReconcile(): void {\n if (activeReconcile || !savedOptions) return;\n const opts = savedOptions;\n activeReconcile = reconcile(opts.serversDir, opts.projectsDir, opts.excludePids, opts.assignmentsDir)\n .catch((err) => {\n console.error('[autodiscovery] reconcile failed:', err);\n })\n .finally(() => {\n activeReconcile = null;\n });\n}\n\n// --- Tmux discovery ---\n\nexport async function listAllTmuxSessions(): Promise<string[]> {\n const output = await execQuiet('tmux', ['list-sessions', '-F', '#{session_name}']);\n if (!output) return [];\n return output.split('\\n').filter((line) => line.length > 0);\n}\n\nasync function discoverTmuxSessions(\n serversDir: string,\n projectsDir: string,\n existingNames: Set<string>,\n assignmentsDir?: string,\n): Promise<boolean> {\n const tmuxAvailable = await checkTmuxAvailable();\n if (!tmuxAvailable) return false;\n\n const workspaceRecords = await loadWorkspaceRecords(projectsDir, assignmentsDir);\n if (workspaceRecords.length === 0) return false;\n\n const sessions = await listAllTmuxSessions();\n let changed = false;\n\n for (const sessionName of sessions) {\n const sanitized = sanitizeSessionName(sessionName);\n if (existingNames.has(sanitized)) {\n // Already tracked (manual or auto) — skip\n continue;\n }\n\n const panes = await listTmuxPanes(sessionName);\n if (panes.length === 0) continue;\n\n // Check if any pane matches a workspace\n let matched = false;\n const cwdGitCache = new Map<string, { branch: string | null; worktree: boolean }>();\n\n for (const pane of panes) {\n if (!cwdGitCache.has(pane.cwd)) {\n cwdGitCache.set(pane.cwd, await getGitInfo(pane.cwd));\n }\n const gitInfo = cwdGitCache.get(pane.cwd)!;\n const link = await autoLinkPane(pane.cwd, gitInfo.branch, workspaceRecords);\n if (link) {\n matched = true;\n break;\n }\n }\n\n if (matched) {\n await registerAutoSession(serversDir, sessionName, { kind: 'tmux' });\n changed = true;\n }\n }\n\n return changed;\n}\n\n// --- Non-tmux process discovery ---\n\ninterface ListeningProcess {\n pid: number;\n port: number;\n command: string;\n}\n\nasync function getProcessCwd(pid: number): Promise<string | null> {\n // macOS: use lsof to get cwd\n const output = await execQuiet('lsof', ['-a', '-d', 'cwd', '-p', String(pid), '-Fn']);\n if (!output) return null;\n // Output format: lines starting with 'n' contain the path\n for (const line of output.split('\\n')) {\n if (line.startsWith('n') && line.length > 1) {\n return line.slice(1);\n }\n }\n return null;\n}\n\nasync function discoverProcesses(\n serversDir: string,\n projectsDir: string,\n existingFiles: Map<string, SessionFileData>,\n excludePids?: Set<number>,\n assignmentsDir?: string,\n): Promise<boolean> {\n const workspaceRecords = await loadWorkspaceRecords(projectsDir, assignmentsDir);\n if (workspaceRecords.length === 0) return false;\n\n const lsofOutput = await getLsofOutput();\n if (!lsofOutput) return false;\n\n const processes = parseLsofForListeningProcesses(lsofOutput);\n let changed = false;\n\n // Track which PIDs are already tracked by existing process-kind entries\n const trackedPids = new Set<number>();\n for (const data of existingFiles.values()) {\n if (data.kind === 'process' && data.pid) {\n trackedPids.add(data.pid);\n }\n }\n\n for (const proc of processes) {\n if (trackedPids.has(proc.pid)) continue;\n if (excludePids?.has(proc.pid)) continue;\n\n const cwd = await getProcessCwd(proc.pid);\n if (!cwd) continue;\n\n const gitInfo = await getGitInfo(cwd);\n const link = await autoLinkPane(cwd, gitInfo.branch, workspaceRecords);\n if (!link) continue;\n\n // Build a session name from the command and port\n const sessionName = `proc-${proc.command}-${proc.port}`;\n const sanitized = sanitizeSessionName(sessionName);\n\n // Skip if already registered under this name\n if (existingFiles.has(sanitized)) continue;\n\n const ports = parsePortsForPid(lsofOutput, proc.pid);\n await registerAutoSession(serversDir, sessionName, {\n kind: 'process',\n pid: proc.pid,\n ports: ports.length > 0 ? ports : [proc.port],\n cwd,\n });\n changed = true;\n }\n\n return changed;\n}\n\n// --- Reconciliation ---\n\nasync function cleanupDeadAutoSessions(\n serversDir: string,\n existingFiles: Map<string, SessionFileData>,\n): Promise<{ changed: boolean; removedNames: Set<string> }> {\n let changed = false;\n const removedNames = new Set<string>();\n\n // Only check tmux liveness if tmux is available\n const tmuxAvailable = await checkTmuxAvailable();\n\n for (const [name, data] of existingFiles) {\n if (!data.auto) continue;\n\n let alive = true; // Default to alive for unknown kinds\n if (data.kind === 'tmux') {\n if (!tmuxAvailable) continue; // Don't delete tmux sessions when tmux is unavailable\n alive = await sessionAlive(data.session);\n } else if (data.kind === 'process' && data.pid) {\n alive = await isProcessAlive(data.pid);\n } else {\n // Unknown kind with auto: true — leave it alone\n continue;\n }\n\n if (!alive) {\n await removeSession(serversDir, name);\n removedNames.add(name);\n changed = true;\n }\n }\n\n return { changed, removedNames };\n}\n\nexport async function isProcessAlive(pid: number): Promise<boolean> {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function reconcile(serversDir: string, projectsDir: string, excludePids?: Set<number>, assignmentsDir?: string): Promise<void> {\n // Load all existing session files\n const names = await listSessionFiles(serversDir);\n const existingFiles = new Map<string, SessionFileData>();\n for (const name of names) {\n const data = await readSessionFile(serversDir, name);\n if (data) existingFiles.set(name, data);\n }\n\n // Clean up dead auto sessions FIRST so discovery can re-register restarted processes\n const { changed: cleanupChanged, removedNames } = await cleanupDeadAutoSessions(serversDir, existingFiles);\n\n // Remove cleaned-up entries from the maps so discovery sees them as available\n for (const name of removedNames) {\n existingFiles.delete(name);\n }\n const existingNames = new Set(existingFiles.keys());\n\n // Discover new sessions\n const tmuxChanged = await discoverTmuxSessions(serversDir, projectsDir, existingNames, assignmentsDir);\n const processChanged = await discoverProcesses(serversDir, projectsDir, existingFiles, excludePids, assignmentsDir);\n\n // Invalidate scan cache if anything changed\n if (tmuxChanged || processChanged || cleanupChanged) {\n clearScanCache();\n }\n}\n\n// --- Exports for testing ---\nexport { reconcile, getProcessCwd };\n"],"mappings":"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","names":["todosDir","getField","extractFrontmatter","parseSimpleValue","parseExternalIds","resolve","parseStatus","extractFrontmatter","todosDir","init_parser","resolve","todosDir","init_parser","resolve","readFile","params","readdir","readFile","rename","writeFile","resolve","readFile","resolve","init_config","resolve","readdir","readFile","playbooksDir","init_config","resolve","readdir","readFile","assignmentsDir","extractFrontmatter","resolve","readdir","readFile","readFile","resolve","db","rows","assignmentsDir","readdir","readFile","unlink","resolve","nowTimestamp","extractFrontmatter","resolve","readdir","readFile","assignmentsDir","extractFrontmatter","serversDir","readdir","readFile","writeFile","resolve","dirname","escapeRegExp","assignmentsDir","serversDir","scanAllSessions","TERMINAL_STATUSES","playbooksDir","init_config","setTopLevelField","resolve","writeFile","unlink","basename","dirname","assignmentsDir","serversDir","playbooksDir","todosDir","handleStandaloneChange","handleServerChange","handlePlaybookChange","handleTodoChange","handleDbChange","init_config","readFile","rename","unlink","resolve","resolve","readFile","rename","unlink","resolve","basename","isAbsolute","readFile","spawnSync","readFile","spawnSync","resolve","readdir","readFile","resolve","assignmentsDir","params","params","params","params","params","params","params","params","params","params","extractFrontmatter","formatYamlValue","escapeRegExp","appendLogEntry","readFile","isAbsolute","spawnSync","resolve","assignmentsDir","todosDir","basename","params","id","assignmentDir","timestamp","detail","Router","serversDir","assignmentsDir","Router","resolve","init_config","execFileSync","assignmentsDir","Router","resolve","init_config","Router","init_config","Router","spawnSync","Router","response","init_config","Router","Router","Database","randomUUID","resolve","db","SCHEMA_SQL","db","resolve","Database","SCHEMA_SQL","Router","Router","resolve","readFile","playbooksDir","Router","resolve","readFile","init_parser","Router","readdir","dirname","rename","mkdir","init_parser","resolve","init_config","resolve","touchItem","touchItem","todosDir","Router","readdir","archivePath","resolve","readFile","writeFileForce","resolvePath","readConfig","fileExists","appendTodosToAssignmentBody","touchAssignmentUpdated","nowTimestamp","mkdir","dirname","rename","init_parser","Router","mkdir","readFile","rename","resolve","dirname","WORKSPACE_REGEX","touchItem","resolve","todosDir","mkdir","Router","readFile","appendTodosToAssignmentBody","touchAssignmentUpdated","nowTimestamp","dirname","rename","init_config","Router","init_config","execFile","promisify","rm","readFile","writeFile","unlink","open","rename","resolve","join","exec","resolve","exec","open","readFile","unlink","join","rm","writeFile","rename","Router","serversDir","assignmentsDir","assignmentsDir","serversDir","playbooksDir","todosDir","resolve","writeFile","unlink"]}