@tomkapa/tayto 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +217 -0
- package/dist/chunk-6NQOFUIQ.js +133 -0
- package/dist/chunk-6NQOFUIQ.js.map +1 -0
- package/dist/index.js +1962 -0
- package/dist/index.js.map +1 -0
- package/dist/migrations/001_initial.sql +37 -0
- package/dist/migrations/002_dependencies_and_fts.sql +47 -0
- package/dist/migrations/003_soft_delete.sql +39 -0
- package/dist/tui-JNZRBEIQ.js +2352 -0
- package/dist/tui-JNZRBEIQ.js.map +1 -0
- package/package.json +54 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/config/index.ts","../src/db/connection.ts","../src/db/migrator.ts","../src/logging/telemetry.ts","../src/types/common.ts","../src/errors/app-error.ts","../src/repository/project.repository.ts","../src/repository/shared.ts","../src/repository/task.repository.ts","../src/repository/dependency.repository.ts","../src/types/project.ts","../src/service/project.service.ts","../src/types/task.ts","../src/service/task.service.ts","../src/types/dependency.ts","../src/service/dependency.service.ts","../src/types/portability.ts","../src/service/portability.service.ts","../src/cli/container.ts","../src/cli/index.ts","../src/cli/output.ts","../src/cli/commands/project/create.ts","../src/cli/commands/project/list.ts","../src/cli/commands/project/update.ts","../src/cli/commands/project/delete.ts","../src/cli/commands/project/set-default.ts","../src/cli/commands/task/create.ts","../src/cli/commands/task/list.ts","../src/cli/commands/task/show.ts","../src/cli/commands/task/update.ts","../src/cli/commands/task/delete.ts","../src/cli/commands/task/breakdown.ts","../src/cli/commands/task/rank.ts","../src/cli/commands/task/search.ts","../src/cli/commands/task/export.ts","../src/cli/commands/task/import.ts","../src/cli/commands/dep/add.ts","../src/cli/commands/dep/remove.ts","../src/cli/commands/dep/list.ts","../src/cli/commands/dep/graph.ts","../src/index.ts"],"sourcesContent":["import { mkdirSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\n\nexport interface Config {\n dbPath: string;\n logDir: string;\n logLevel: string;\n otelEndpoint: string | undefined;\n}\n\nfunction ensureDir(dir: string): void {\n mkdirSync(dir, { recursive: true });\n}\n\nexport function loadConfig(): Config {\n const dataDir = process.env['TASK_DATA_DIR'] ?? join(homedir(), '.task');\n ensureDir(dataDir);\n\n const logDir = process.env['TASK_LOG_DIR'] ?? join(dataDir, 'logs');\n ensureDir(logDir);\n\n return {\n dbPath: process.env['TASK_DB_PATH'] ?? join(dataDir, 'data.db'),\n logDir,\n logLevel: process.env['TASK_LOG_LEVEL'] ?? 'info',\n otelEndpoint: process.env['OTEL_EXPORTER_OTLP_ENDPOINT'],\n };\n}\n","import Database from 'better-sqlite3';\n\nexport function createDatabase(dbPath: string): Database.Database {\n const db = new Database(dbPath);\n db.pragma('journal_mode = WAL');\n db.pragma('foreign_keys = ON');\n return db;\n}\n","import { readdirSync, readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type Database from 'better-sqlite3';\nimport { logger } from '../logging/logger.js';\n\nconst migrationsDir = join(dirname(fileURLToPath(import.meta.url)), 'migrations');\n\nfunction loadMigrations(): Array<{ name: string; sql: string }> {\n const files = readdirSync(migrationsDir)\n .filter((f) => f.endsWith('.sql'))\n .sort();\n\n return files.map((name) => ({\n name,\n sql: readFileSync(join(migrationsDir, name), 'utf-8'),\n }));\n}\n\nexport function runMigrations(db: Database.Database): void {\n db.exec(`\n CREATE TABLE IF NOT EXISTS _migrations (\n name TEXT PRIMARY KEY,\n applied_at TEXT NOT NULL\n );\n `);\n\n const applied = new Set(\n (db.prepare('SELECT name FROM _migrations').all() as Array<{ name: string }>).map(\n (r) => r.name,\n ),\n );\n\n const migrations = loadMigrations();\n\n for (const migration of migrations) {\n if (applied.has(migration.name)) continue;\n\n logger.info(`Applying migration: ${migration.name}`);\n\n const migrate = db.transaction(() => {\n db.exec(migration.sql);\n db.prepare('INSERT INTO _migrations (name, applied_at) VALUES (?, ?)').run(\n migration.name,\n new Date().toISOString(),\n );\n });\n\n migrate();\n logger.info(`Migration applied: ${migration.name}`);\n }\n}\n","import { NodeSDK } from '@opentelemetry/sdk-node';\nimport { BatchSpanProcessor, ConsoleSpanExporter } from '@opentelemetry/sdk-trace-base';\nimport { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';\nimport type { Config } from '../config/index.js';\n\nlet sdk: NodeSDK | undefined;\n\nexport function initTelemetry(config: Config): void {\n const spanProcessor = config.otelEndpoint\n ? new BatchSpanProcessor(new OTLPTraceExporter({ url: config.otelEndpoint }))\n : config.logLevel === 'debug'\n ? new BatchSpanProcessor(new ConsoleSpanExporter())\n : undefined;\n\n sdk = new NodeSDK({\n serviceName: 'task',\n spanProcessors: spanProcessor ? [spanProcessor] : [],\n });\n\n sdk.start();\n}\n\nexport async function shutdownTelemetry(): Promise<void> {\n if (sdk) {\n await sdk.shutdown();\n }\n}\n","import type { AppError } from '../errors/app-error.js';\n\nexport type Result<T, E = AppError> = { ok: true; value: T } | { ok: false; error: E };\n\nexport function ok<T>(value: T): Result<T, never> {\n return { ok: true, value };\n}\n\nexport function err<E>(error: E): Result<never, E> {\n return { ok: false, error };\n}\n\nexport interface CLIOutput<T> {\n ok: boolean;\n data?: T;\n error?: { code: string; message: string };\n}\n","export type AppErrorCode = 'NOT_FOUND' | 'DUPLICATE' | 'VALIDATION' | 'DB_ERROR' | 'UNKNOWN';\n\nexport class AppError extends Error {\n constructor(\n public readonly code: AppErrorCode,\n message: string,\n public readonly cause?: unknown,\n ) {\n super(message);\n this.name = 'AppError';\n }\n}\n","import type Database from 'better-sqlite3';\nimport type { Result } from '../types/common.js';\nimport { ok, err } from '../types/common.js';\nimport type { Project, CreateProjectInput, UpdateProjectInput } from '../types/project.js';\nimport { AppError } from '../errors/app-error.js';\nimport { ulid } from 'ulid';\nimport { logger } from '../logging/logger.js';\nimport { NOT_DELETED } from './shared.js';\n\ninterface ProjectRow {\n id: string;\n key: string;\n name: string;\n description: string;\n is_default: number;\n task_counter: number;\n created_at: string;\n updated_at: string;\n}\n\nfunction rowToProject(row: ProjectRow): Project {\n return {\n id: row.id,\n key: row.key,\n name: row.name,\n description: row.description,\n isDefault: row.is_default === 1,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n}\n\nexport interface ProjectRepository {\n insert(input: CreateProjectInput & { key: string }): Result<Project>;\n findById(id: string): Result<Project | null>;\n findByKey(key: string): Result<Project | null>;\n findByName(name: string): Result<Project | null>;\n findDefault(): Result<Project | null>;\n findAll(): Result<Project[]>;\n update(id: string, input: UpdateProjectInput): Result<Project>;\n delete(id: string): Result<void>;\n incrementTaskCounter(id: string): Result<number>;\n}\n\nexport class SqliteProjectRepository implements ProjectRepository {\n constructor(private readonly db: Database.Database) {}\n\n insert(input: CreateProjectInput & { key: string }): Result<Project> {\n return logger.startSpan('ProjectRepository.insert', () => {\n try {\n const now = new Date().toISOString();\n const id = ulid();\n\n if (input.isDefault) {\n this.db.prepare('UPDATE projects SET is_default = 0 WHERE is_default = 1').run();\n }\n\n this.db\n .prepare(\n `INSERT INTO projects (id, key, name, description, is_default, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n id,\n input.key,\n input.name,\n input.description ?? '',\n input.isDefault ? 1 : 0,\n now,\n now,\n );\n\n const row = this.db.prepare('SELECT * FROM projects WHERE id = ?').get(id) as\n | ProjectRow\n | undefined;\n if (!row) {\n return err(new AppError('DB_ERROR', 'Failed to retrieve inserted project'));\n }\n return ok(rowToProject(row));\n } catch (e) {\n if (e instanceof Error && e.message.includes('UNIQUE constraint')) {\n return err(new AppError('DUPLICATE', `Project name already exists: ${input.name}`, e));\n }\n return err(new AppError('DB_ERROR', 'Failed to insert project', e));\n }\n });\n }\n\n findById(id: string): Result<Project | null> {\n try {\n const row = this.db\n .prepare(`SELECT * FROM projects WHERE id = ? AND ${NOT_DELETED}`)\n .get(id) as ProjectRow | undefined;\n return ok(row ? rowToProject(row) : null);\n } catch (e) {\n return err(new AppError('DB_ERROR', 'Failed to find project by id', e));\n }\n }\n\n findByKey(key: string): Result<Project | null> {\n try {\n const row = this.db\n .prepare(`SELECT * FROM projects WHERE key = ? AND ${NOT_DELETED}`)\n .get(key) as ProjectRow | undefined;\n return ok(row ? rowToProject(row) : null);\n } catch (e) {\n return err(new AppError('DB_ERROR', 'Failed to find project by key', e));\n }\n }\n\n findByName(name: string): Result<Project | null> {\n try {\n const row = this.db\n .prepare(`SELECT * FROM projects WHERE name = ? AND ${NOT_DELETED}`)\n .get(name) as ProjectRow | undefined;\n return ok(row ? rowToProject(row) : null);\n } catch (e) {\n return err(new AppError('DB_ERROR', 'Failed to find project by name', e));\n }\n }\n\n findDefault(): Result<Project | null> {\n try {\n const row = this.db\n .prepare(`SELECT * FROM projects WHERE is_default = 1 AND ${NOT_DELETED}`)\n .get() as ProjectRow | undefined;\n return ok(row ? rowToProject(row) : null);\n } catch (e) {\n return err(new AppError('DB_ERROR', 'Failed to find default project', e));\n }\n }\n\n findAll(): Result<Project[]> {\n try {\n const rows = this.db\n .prepare(`SELECT * FROM projects WHERE ${NOT_DELETED} ORDER BY created_at DESC`)\n .all() as ProjectRow[];\n return ok(rows.map(rowToProject));\n } catch (e) {\n return err(new AppError('DB_ERROR', 'Failed to list projects', e));\n }\n }\n\n update(id: string, input: UpdateProjectInput): Result<Project> {\n return logger.startSpan('ProjectRepository.update', () => {\n try {\n const existing = this.db\n .prepare(`SELECT * FROM projects WHERE id = ? AND ${NOT_DELETED}`)\n .get(id) as ProjectRow | undefined;\n if (!existing) {\n return err(new AppError('NOT_FOUND', `Project not found: ${id}`));\n }\n\n const now = new Date().toISOString();\n\n if (input.isDefault) {\n this.db.prepare('UPDATE projects SET is_default = 0 WHERE is_default = 1').run();\n }\n\n this.db\n .prepare(\n `UPDATE projects SET\n name = ?, description = ?, is_default = ?, updated_at = ?\n WHERE id = ?`,\n )\n .run(\n input.name ?? existing.name,\n input.description ?? existing.description,\n input.isDefault !== undefined ? (input.isDefault ? 1 : 0) : existing.is_default,\n now,\n id,\n );\n\n const row = this.db.prepare('SELECT * FROM projects WHERE id = ?').get(id) as\n | ProjectRow\n | undefined;\n if (!row) {\n return err(new AppError('DB_ERROR', 'Failed to retrieve updated project'));\n }\n return ok(rowToProject(row));\n } catch (e) {\n if (e instanceof Error && e.message.includes('UNIQUE constraint')) {\n return err(new AppError('DUPLICATE', `Project name already exists`, e));\n }\n return err(new AppError('DB_ERROR', 'Failed to update project', e));\n }\n });\n }\n\n delete(id: string): Result<void> {\n return logger.startSpan('ProjectRepository.delete', () => {\n try {\n const existing = this.db\n .prepare(`SELECT * FROM projects WHERE id = ? AND ${NOT_DELETED}`)\n .get(id) as ProjectRow | undefined;\n if (!existing) {\n return err(new AppError('NOT_FOUND', `Project not found: ${id}`));\n }\n const now = new Date().toISOString();\n this.db\n .prepare('UPDATE projects SET deleted_at = ?, updated_at = ? WHERE id = ?')\n .run(now, now, id);\n // Soft-delete all tasks in this project\n this.db\n .prepare(\n 'UPDATE tasks SET deleted_at = ?, updated_at = ? WHERE project_id = ? AND deleted_at IS NULL',\n )\n .run(now, now, id);\n return ok(undefined);\n } catch (e) {\n return err(new AppError('DB_ERROR', 'Failed to delete project', e));\n }\n });\n }\n\n incrementTaskCounter(id: string): Result<number> {\n return logger.startSpan('ProjectRepository.incrementTaskCounter', () => {\n try {\n this.db\n .prepare(\n `UPDATE projects SET task_counter = task_counter + 1 WHERE id = ? AND ${NOT_DELETED}`,\n )\n .run(id);\n const row = this.db\n .prepare(`SELECT task_counter FROM projects WHERE id = ? AND ${NOT_DELETED}`)\n .get(id) as { task_counter: number } | undefined;\n if (!row) {\n return err(new AppError('NOT_FOUND', `Project not found: ${id}`));\n }\n return ok(row.task_counter);\n } catch (e) {\n return err(new AppError('DB_ERROR', 'Failed to increment task counter', e));\n }\n });\n }\n}\n","import type { Task } from '../types/task.js';\nimport type { TaskStatus, TaskType } from '../types/enums.js';\n\nexport const NOT_DELETED = 'deleted_at IS NULL';\n\nexport interface TaskRow {\n id: string;\n project_id: string;\n parent_id: string | null;\n name: string;\n description: string;\n type: string;\n status: string;\n rank: number;\n technical_notes: string;\n additional_requirements: string;\n created_at: string;\n updated_at: string;\n}\n\nexport function rowToTask(row: TaskRow): Task {\n return {\n id: row.id,\n projectId: row.project_id,\n parentId: row.parent_id,\n name: row.name,\n description: row.description,\n type: row.type as TaskType,\n status: row.status as TaskStatus,\n rank: row.rank,\n technicalNotes: row.technical_notes,\n additionalRequirements: row.additional_requirements,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n}\n","import type Database from 'better-sqlite3';\nimport type { Result } from '../types/common.js';\nimport { ok, err } from '../types/common.js';\nimport type { Task, CreateTaskInput, UpdateTaskInput, TaskFilter } from '../types/task.js';\nimport { RANK_GAP, TERMINAL_STATUSES } from '../types/enums.js';\nimport { AppError } from '../errors/app-error.js';\nimport { logger } from '../logging/logger.js';\nimport { NOT_DELETED, type TaskRow, rowToTask } from './shared.js';\n\nconst TERMINAL_STATUS_ARRAY = [...TERMINAL_STATUSES];\nconst TERMINAL_PLACEHOLDERS = TERMINAL_STATUS_ARRAY.map(() => '?').join(', ');\n\nexport interface SearchResult {\n task: Task;\n rank: number;\n}\n\nexport interface TaskRepository {\n insert(id: string, input: CreateTaskInput & { projectId: string }): Result<Task>;\n findById(id: string): Result<Task | null>;\n findMany(filter: TaskFilter): Result<Task[]>;\n update(id: string, input: UpdateTaskInput): Result<Task>;\n delete(id: string): Result<void>;\n rerank(taskId: string, newRank: number): Result<Task>;\n getMaxRank(projectId: string): Result<number>;\n /** Max rank among non-terminal (not done/cancelled) tasks. Returns 0 if none. */\n getMaxActiveRank(projectId: string): Result<number>;\n /** Min rank among terminal (done/cancelled) tasks. Returns null if none. */\n getMinTerminalRank(projectId: string): Result<number | null>;\n getRankedTasks(projectId: string, status?: string): Result<Task[]>;\n /** FTS5 ranked search across all text fields */\n search(query: string, projectId?: string): Result<SearchResult[]>;\n}\n\nexport class SqliteTaskRepository implements TaskRepository {\n constructor(private readonly db: Database.Database) {}\n\n insert(id: string, input: CreateTaskInput & { projectId: string }): Result<Task> {\n return logger.startSpan('TaskRepository.insert', () => {\n try {\n const now = new Date().toISOString();\n\n // New tasks go after the last active task but before terminal (done/cancelled) tasks\n const maxActiveResult = this.getMaxActiveRank(input.projectId);\n if (!maxActiveResult.ok) return maxActiveResult;\n const maxActiveRank = maxActiveResult.value;\n\n const minTerminalResult = this.getMinTerminalRank(input.projectId);\n if (!minTerminalResult.ok) return minTerminalResult;\n const minTerminalRank = minTerminalResult.value;\n\n let rank: number;\n if (minTerminalRank !== null && minTerminalRank > maxActiveRank) {\n rank =\n maxActiveRank > 0 ? (maxActiveRank + minTerminalRank) / 2 : minTerminalRank - RANK_GAP;\n } else {\n rank = maxActiveRank + RANK_GAP;\n }\n\n this.db\n .prepare(\n `INSERT INTO tasks (id, project_id, parent_id, name, description, type, status, rank, technical_notes, additional_requirements, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n id,\n input.projectId,\n input.parentId ?? null,\n input.name,\n input.description ?? '',\n input.type,\n input.status,\n rank,\n input.technicalNotes ?? '',\n input.additionalRequirements ?? '',\n now,\n now,\n );\n\n const row = this.db.prepare('SELECT * FROM tasks WHERE id = ?').get(id) as\n | TaskRow\n | undefined;\n if (!row) {\n return err(new AppError('DB_ERROR', 'Failed to retrieve inserted task'));\n }\n return ok(rowToTask(row));\n } catch (e) {\n return err(new AppError('DB_ERROR', 'Failed to insert task', e));\n }\n });\n }\n\n findById(id: string): Result<Task | null> {\n try {\n const row = this.db.prepare(`SELECT * FROM tasks WHERE id = ? AND ${NOT_DELETED}`).get(id) as\n | TaskRow\n | undefined;\n return ok(row ? rowToTask(row) : null);\n } catch (e) {\n return err(new AppError('DB_ERROR', 'Failed to find task by id', e));\n }\n }\n\n findMany(filter: TaskFilter): Result<Task[]> {\n try {\n const conditions: string[] = [NOT_DELETED];\n const params: unknown[] = [];\n\n if (filter.projectId) {\n conditions.push('project_id = ?');\n params.push(filter.projectId);\n }\n if (filter.status) {\n conditions.push('status = ?');\n params.push(filter.status);\n }\n if (filter.type) {\n conditions.push('type = ?');\n params.push(filter.type);\n }\n if (filter.parentId) {\n conditions.push('parent_id = ?');\n params.push(filter.parentId);\n }\n if (filter.search) {\n // Use FTS5 for tokenized, ranked search with prefix matching\n const ftsQuery = filter.search\n .trim()\n .split(/\\s+/)\n .map((term) => `\"${term.replace(/\"/g, '\"\"')}\"*`)\n .join(' ');\n conditions.push(`id IN (SELECT id FROM tasks_fts WHERE tasks_fts MATCH ?)`);\n params.push(ftsQuery);\n }\n\n const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';\n const sql = `SELECT * FROM tasks ${where} ORDER BY rank ASC`;\n\n const rows = this.db.prepare(sql).all(...params) as TaskRow[];\n return ok(rows.map(rowToTask));\n } catch (e) {\n return err(new AppError('DB_ERROR', 'Failed to list tasks', e));\n }\n }\n\n update(id: string, input: UpdateTaskInput): Result<Task> {\n return logger.startSpan('TaskRepository.update', () => {\n try {\n const existing = this.db\n .prepare(`SELECT * FROM tasks WHERE id = ? AND ${NOT_DELETED}`)\n .get(id) as TaskRow | undefined;\n if (!existing) {\n return err(new AppError('NOT_FOUND', `Task not found: ${id}`));\n }\n\n const now = new Date().toISOString();\n\n let technicalNotes = input.technicalNotes ?? existing.technical_notes;\n if (input.appendNotes) {\n technicalNotes =\n existing.technical_notes +\n (existing.technical_notes ? `\\n\\n---\\n_${now}_\\n\\n` : '') +\n input.appendNotes;\n }\n\n let additionalRequirements =\n input.additionalRequirements ?? existing.additional_requirements;\n if (input.appendRequirements) {\n additionalRequirements =\n existing.additional_requirements +\n (existing.additional_requirements ? `\\n\\n---\\n_${now}_\\n\\n` : '') +\n input.appendRequirements;\n }\n\n this.db\n .prepare(\n `UPDATE tasks SET\n name = ?, description = ?, type = ?, status = ?,\n parent_id = ?, technical_notes = ?, additional_requirements = ?, updated_at = ?\n WHERE id = ?`,\n )\n .run(\n input.name ?? existing.name,\n input.description ?? existing.description,\n input.type ?? existing.type,\n input.status ?? existing.status,\n input.parentId !== undefined ? input.parentId : existing.parent_id,\n technicalNotes,\n additionalRequirements,\n now,\n id,\n );\n\n const row = this.db.prepare('SELECT * FROM tasks WHERE id = ?').get(id) as\n | TaskRow\n | undefined;\n if (!row) {\n return err(new AppError('DB_ERROR', 'Failed to retrieve updated task'));\n }\n return ok(rowToTask(row));\n } catch (e) {\n return err(new AppError('DB_ERROR', 'Failed to update task', e));\n }\n });\n }\n\n delete(id: string): Result<void> {\n return logger.startSpan('TaskRepository.delete', () => {\n try {\n const existing = this.db\n .prepare(`SELECT * FROM tasks WHERE id = ? AND ${NOT_DELETED}`)\n .get(id) as TaskRow | undefined;\n if (!existing) {\n return err(new AppError('NOT_FOUND', `Task not found: ${id}`));\n }\n const now = new Date().toISOString();\n this.db\n .prepare('UPDATE tasks SET deleted_at = ?, updated_at = ? WHERE id = ?')\n .run(now, now, id);\n return ok(undefined);\n } catch (e) {\n return err(new AppError('DB_ERROR', 'Failed to delete task', e));\n }\n });\n }\n\n rerank(taskId: string, newRank: number): Result<Task> {\n return logger.startSpan('TaskRepository.rerank', () => {\n try {\n const now = new Date().toISOString();\n const existing = this.db\n .prepare(`SELECT * FROM tasks WHERE id = ? AND ${NOT_DELETED}`)\n .get(taskId) as TaskRow | undefined;\n if (!existing) {\n return err(new AppError('NOT_FOUND', `Task not found: ${taskId}`));\n }\n this.db\n .prepare('UPDATE tasks SET rank = ?, updated_at = ? WHERE id = ?')\n .run(newRank, now, taskId);\n\n const row = this.db.prepare('SELECT * FROM tasks WHERE id = ?').get(taskId) as\n | TaskRow\n | undefined;\n if (!row) {\n return err(new AppError('DB_ERROR', 'Failed to retrieve reranked task'));\n }\n return ok(rowToTask(row));\n } catch (e) {\n return err(new AppError('DB_ERROR', 'Failed to rerank task', e));\n }\n });\n }\n\n getMaxRank(projectId: string): Result<number> {\n try {\n const row = this.db\n .prepare(`SELECT MAX(rank) as max_rank FROM tasks WHERE project_id = ? AND ${NOT_DELETED}`)\n .get(projectId) as { max_rank: number | null } | undefined;\n return ok(row?.max_rank ?? 0);\n } catch (e) {\n return err(new AppError('DB_ERROR', 'Failed to get max rank', e));\n }\n }\n\n getMaxActiveRank(projectId: string): Result<number> {\n try {\n const row = this.db\n .prepare(\n `SELECT MAX(rank) as max_rank FROM tasks WHERE project_id = ? AND ${NOT_DELETED} AND status NOT IN (${TERMINAL_PLACEHOLDERS})`,\n )\n .get(projectId, ...TERMINAL_STATUS_ARRAY) as { max_rank: number | null } | undefined;\n return ok(row?.max_rank ?? 0);\n } catch (e) {\n return err(new AppError('DB_ERROR', 'Failed to get max active rank', e));\n }\n }\n\n getMinTerminalRank(projectId: string): Result<number | null> {\n try {\n const row = this.db\n .prepare(\n `SELECT MIN(rank) as min_rank FROM tasks WHERE project_id = ? AND ${NOT_DELETED} AND status IN (${TERMINAL_PLACEHOLDERS})`,\n )\n .get(projectId, ...TERMINAL_STATUS_ARRAY) as { min_rank: number | null } | undefined;\n return ok(row?.min_rank ?? null);\n } catch (e) {\n return err(new AppError('DB_ERROR', 'Failed to get min terminal rank', e));\n }\n }\n\n getRankedTasks(projectId: string, status?: string): Result<Task[]> {\n try {\n let sql: string;\n let params: unknown[];\n if (status) {\n sql = `SELECT * FROM tasks WHERE project_id = ? AND ${NOT_DELETED} AND status = ? ORDER BY rank ASC`;\n params = [projectId, status];\n } else {\n sql = `SELECT * FROM tasks WHERE project_id = ? AND ${NOT_DELETED} ORDER BY rank ASC`;\n params = [projectId];\n }\n const rows = this.db.prepare(sql).all(...params) as TaskRow[];\n return ok(rows.map(rowToTask));\n } catch (e) {\n return err(new AppError('DB_ERROR', 'Failed to get ranked tasks', e));\n }\n }\n\n search(query: string, projectId?: string): Result<SearchResult[]> {\n return logger.startSpan('TaskRepository.search', () => {\n try {\n const ftsQuery = query\n .trim()\n .split(/\\s+/)\n .map((term) => `\"${term.replace(/\"/g, '\"\"')}\"*`)\n .join(' ');\n\n let sql: string;\n let params: unknown[];\n\n if (projectId) {\n sql = `SELECT t.*, bm25(tasks_fts) AS fts_rank\n FROM tasks_fts f\n JOIN tasks t ON t.id = f.id AND t.deleted_at IS NULL\n WHERE tasks_fts MATCH ? AND t.project_id = ?\n ORDER BY fts_rank ASC`;\n params = [ftsQuery, projectId];\n } else {\n sql = `SELECT t.*, bm25(tasks_fts) AS fts_rank\n FROM tasks_fts f\n JOIN tasks t ON t.id = f.id AND t.deleted_at IS NULL\n WHERE tasks_fts MATCH ?\n ORDER BY fts_rank ASC`;\n params = [ftsQuery];\n }\n\n const rows = this.db.prepare(sql).all(...params) as (TaskRow & { fts_rank: number })[];\n return ok(\n rows.map((row) => ({\n task: rowToTask(row),\n rank: row.fts_rank,\n })),\n );\n } catch (e) {\n return err(new AppError('DB_ERROR', 'Full-text search failed', e));\n }\n });\n }\n}\n","import type Database from 'better-sqlite3';\nimport type { Result } from '../types/common.js';\nimport { ok, err } from '../types/common.js';\nimport type { TaskDependency } from '../types/dependency.js';\nimport type { Task } from '../types/task.js';\nimport type { DependencyType } from '../types/enums.js';\nimport { AppError } from '../errors/app-error.js';\nimport { logger } from '../logging/logger.js';\nimport { type TaskRow, rowToTask } from './shared.js';\n\ninterface DependencyRow {\n task_id: string;\n depends_on_id: string;\n type: string;\n created_at: string;\n}\n\nfunction rowToDependency(row: DependencyRow): TaskDependency {\n return {\n taskId: row.task_id,\n dependsOnId: row.depends_on_id,\n type: row.type as DependencyType,\n createdAt: row.created_at,\n };\n}\n\nexport interface DependencyRepository {\n insert(taskId: string, dependsOnId: string, type: DependencyType): Result<TaskDependency>;\n delete(taskId: string, dependsOnId: string): Result<void>;\n findByTask(taskId: string): Result<TaskDependency[]>;\n findDependents(taskId: string): Result<TaskDependency[]>;\n /** Tasks that block taskId (taskId depends on them via 'blocks' type). */\n getBlockers(taskId: string): Result<Task[]>;\n /** Tasks that taskId blocks (they depend on taskId via 'blocks' type). */\n getDependents(taskId: string): Result<Task[]>;\n /** Tasks related to taskId via 'relates-to' in either direction. */\n getRelated(taskId: string): Result<Task[]>;\n /** Tasks connected to taskId via 'duplicates' in either direction. */\n getDuplicates(taskId: string): Result<Task[]>;\n /** Returns all transitive blockers using recursive CTE */\n getTransitiveClosure(taskId: string): Result<Task[]>;\n /** Checks if adding an edge would create a cycle */\n wouldCreateCycle(taskId: string, dependsOnId: string): Result<boolean>;\n}\n\nexport class SqliteDependencyRepository implements DependencyRepository {\n constructor(private readonly db: Database.Database) {}\n\n insert(taskId: string, dependsOnId: string, type: DependencyType): Result<TaskDependency> {\n return logger.startSpan('DependencyRepository.insert', () => {\n try {\n const now = new Date().toISOString();\n this.db\n .prepare(\n `INSERT INTO task_dependencies (task_id, depends_on_id, type, created_at)\n VALUES (?, ?, ?, ?)`,\n )\n .run(taskId, dependsOnId, type, now);\n\n const row = this.db\n .prepare('SELECT * FROM task_dependencies WHERE task_id = ? AND depends_on_id = ?')\n .get(taskId, dependsOnId) as DependencyRow | undefined;\n if (!row) {\n return err(new AppError('DB_ERROR', 'Failed to retrieve inserted dependency'));\n }\n return ok(rowToDependency(row));\n } catch (e) {\n if (e instanceof Error && e.message.includes('UNIQUE constraint')) {\n return err(\n new AppError('DUPLICATE', `Dependency already exists: ${taskId} -> ${dependsOnId}`, e),\n );\n }\n if (e instanceof Error && e.message.includes('FOREIGN KEY constraint')) {\n return err(new AppError('NOT_FOUND', 'One or both tasks do not exist', e));\n }\n if (e instanceof Error && e.message.includes('CHECK constraint')) {\n return err(new AppError('VALIDATION', 'A task cannot depend on itself', e));\n }\n return err(new AppError('DB_ERROR', 'Failed to insert dependency', e));\n }\n });\n }\n\n delete(taskId: string, dependsOnId: string): Result<void> {\n return logger.startSpan('DependencyRepository.delete', () => {\n try {\n const existing = this.db\n .prepare('SELECT * FROM task_dependencies WHERE task_id = ? AND depends_on_id = ?')\n .get(taskId, dependsOnId) as DependencyRow | undefined;\n if (!existing) {\n return err(\n new AppError('NOT_FOUND', `Dependency not found: ${taskId} -> ${dependsOnId}`),\n );\n }\n this.db\n .prepare('DELETE FROM task_dependencies WHERE task_id = ? AND depends_on_id = ?')\n .run(taskId, dependsOnId);\n return ok(undefined);\n } catch (e) {\n return err(new AppError('DB_ERROR', 'Failed to delete dependency', e));\n }\n });\n }\n\n findByTask(taskId: string): Result<TaskDependency[]> {\n try {\n const rows = this.db\n .prepare('SELECT * FROM task_dependencies WHERE task_id = ? ORDER BY created_at ASC')\n .all(taskId) as DependencyRow[];\n return ok(rows.map(rowToDependency));\n } catch (e) {\n return err(new AppError('DB_ERROR', 'Failed to find dependencies for task', e));\n }\n }\n\n findDependents(taskId: string): Result<TaskDependency[]> {\n try {\n const rows = this.db\n .prepare('SELECT * FROM task_dependencies WHERE depends_on_id = ? ORDER BY created_at ASC')\n .all(taskId) as DependencyRow[];\n return ok(rows.map(rowToDependency));\n } catch (e) {\n return err(new AppError('DB_ERROR', 'Failed to find dependents for task', e));\n }\n }\n\n getBlockers(taskId: string): Result<Task[]> {\n try {\n const rows = this.db\n .prepare(\n `SELECT t.* FROM tasks t\n JOIN task_dependencies td ON t.id = td.depends_on_id\n WHERE td.task_id = ? AND td.type = 'blocks' AND t.deleted_at IS NULL\n ORDER BY t.rank ASC`,\n )\n .all(taskId) as TaskRow[];\n return ok(rows.map(rowToTask));\n } catch (e) {\n return err(new AppError('DB_ERROR', 'Failed to get blockers', e));\n }\n }\n\n getDependents(taskId: string): Result<Task[]> {\n try {\n const rows = this.db\n .prepare(\n `SELECT t.* FROM tasks t\n JOIN task_dependencies td ON t.id = td.task_id\n WHERE td.depends_on_id = ? AND td.type = 'blocks' AND t.deleted_at IS NULL\n ORDER BY t.rank ASC`,\n )\n .all(taskId) as TaskRow[];\n return ok(rows.map(rowToTask));\n } catch (e) {\n return err(new AppError('DB_ERROR', 'Failed to get dependents', e));\n }\n }\n\n getRelated(taskId: string): Result<Task[]> {\n try {\n const rows = this.db\n .prepare(\n `SELECT DISTINCT t.* FROM tasks t\n JOIN task_dependencies td ON (\n (td.task_id = ? AND td.depends_on_id = t.id) OR\n (td.depends_on_id = ? AND td.task_id = t.id)\n )\n WHERE td.type = 'relates-to' AND t.deleted_at IS NULL\n ORDER BY t.rank ASC`,\n )\n .all(taskId, taskId) as TaskRow[];\n return ok(rows.map(rowToTask));\n } catch (e) {\n return err(new AppError('DB_ERROR', 'Failed to get related tasks', e));\n }\n }\n\n getDuplicates(taskId: string): Result<Task[]> {\n try {\n const rows = this.db\n .prepare(\n `SELECT DISTINCT t.* FROM tasks t\n JOIN task_dependencies td ON (\n (td.task_id = ? AND td.depends_on_id = t.id) OR\n (td.depends_on_id = ? AND td.task_id = t.id)\n )\n WHERE td.type = 'duplicates' AND t.deleted_at IS NULL\n ORDER BY t.rank ASC`,\n )\n .all(taskId, taskId) as TaskRow[];\n return ok(rows.map(rowToTask));\n } catch (e) {\n return err(new AppError('DB_ERROR', 'Failed to get duplicate tasks', e));\n }\n }\n\n getTransitiveClosure(taskId: string): Result<Task[]> {\n try {\n const rows = this.db\n .prepare(\n `WITH RECURSIVE transitive_deps(id) AS (\n SELECT depends_on_id FROM task_dependencies WHERE task_id = ?\n UNION\n SELECT td.depends_on_id FROM task_dependencies td\n JOIN transitive_deps d ON td.task_id = d.id\n )\n SELECT t.* FROM tasks t\n WHERE t.id IN (SELECT id FROM transitive_deps) AND t.deleted_at IS NULL\n ORDER BY t.rank ASC`,\n )\n .all(taskId) as TaskRow[];\n return ok(rows.map(rowToTask));\n } catch (e) {\n return err(new AppError('DB_ERROR', 'Failed to get transitive closure', e));\n }\n }\n\n wouldCreateCycle(taskId: string, dependsOnId: string): Result<boolean> {\n try {\n // Check: can we reach taskId starting from dependsOnId by following depends_on edges?\n // If yes, adding dependsOnId -> taskId would create a cycle.\n const row = this.db\n .prepare(\n `WITH RECURSIVE reachable(id) AS (\n SELECT depends_on_id FROM task_dependencies WHERE task_id = ?\n UNION\n SELECT td.depends_on_id FROM task_dependencies td\n JOIN reachable r ON td.task_id = r.id\n )\n SELECT 1 AS found FROM reachable WHERE id = ? LIMIT 1`,\n )\n .get(dependsOnId, taskId) as { found: number } | undefined;\n return ok(row !== undefined);\n } catch (e) {\n return err(new AppError('DB_ERROR', 'Failed to check for cycle', e));\n }\n }\n}\n","import { z } from 'zod/v4';\n\nexport const CreateProjectSchema = z.object({\n name: z.string().min(1, 'Project name is required').max(255),\n key: z\n .string()\n .min(2, 'Project key must be at least 2 characters')\n .max(7, 'Project key must be at most 7 characters')\n .regex(/^[A-Za-z0-9]+$/, 'Project key must contain only letters and digits')\n .transform((v) => v.toUpperCase())\n .optional(),\n description: z.string().max(5000).optional(),\n isDefault: z.boolean().optional(),\n});\nexport type CreateProjectInput = z.infer<typeof CreateProjectSchema>;\n\nexport const UpdateProjectSchema = z.object({\n name: z.string().min(1).max(255).optional(),\n description: z.string().max(5000).optional(),\n isDefault: z.boolean().optional(),\n});\nexport type UpdateProjectInput = z.infer<typeof UpdateProjectSchema>;\n\nexport interface Project {\n id: string;\n key: string;\n name: string;\n description: string;\n isDefault: boolean;\n createdAt: string;\n updatedAt: string;\n}\n","import type { Result } from '../types/common.js';\nimport { ok, err } from '../types/common.js';\nimport type { Project } from '../types/project.js';\nimport { CreateProjectSchema, UpdateProjectSchema } from '../types/project.js';\nimport type { ProjectRepository } from '../repository/project.repository.js';\nimport { AppError } from '../errors/app-error.js';\nimport { logger } from '../logging/logger.js';\n\nexport interface ProjectService {\n createProject(input: unknown): Result<Project>;\n listProjects(): Result<Project[]>;\n getProject(id: string): Result<Project>;\n updateProject(id: string, input: unknown): Result<Project>;\n deleteProject(id: string): Result<void>;\n resolveProject(idOrName?: string): Result<Project>;\n nextTaskId(project: Project): Result<string>;\n}\n\nexport class ProjectServiceImpl implements ProjectService {\n constructor(private readonly repo: ProjectRepository) {}\n\n createProject(input: unknown): Result<Project> {\n return logger.startSpan('ProjectService.createProject', () => {\n const parsed = CreateProjectSchema.safeParse(input);\n if (!parsed.success) {\n return err(new AppError('VALIDATION', parsed.error.message));\n }\n\n const key = parsed.data.key ?? this.generateKey(parsed.data.name);\n const keyError = this.validateKey(key);\n if (keyError) {\n return err(new AppError('VALIDATION', keyError));\n }\n\n const existingResult = this.repo.findByKey(key);\n if (!existingResult.ok) return existingResult;\n if (existingResult.value) {\n return err(new AppError('DUPLICATE', `Project key already exists: ${key}`));\n }\n\n return this.repo.insert({ ...parsed.data, key });\n });\n }\n\n private generateKey(name: string): string {\n return name\n .replace(/[^A-Za-z0-9]/g, '')\n .slice(0, 3)\n .toUpperCase();\n }\n\n private validateKey(key: string): string | null {\n if (key.length < 2 || key.length > 7) {\n return `Project key must be 2-7 characters, got ${key.length}. Provide a --key explicitly.`;\n }\n if (!/^[A-Z0-9]+$/.test(key)) {\n return 'Project key must contain only uppercase letters and digits.';\n }\n return null;\n }\n\n listProjects(): Result<Project[]> {\n return this.repo.findAll();\n }\n\n getProject(id: string): Result<Project> {\n return logger.startSpan('ProjectService.getProject', () => {\n const result = this.repo.findById(id);\n if (!result.ok) return result;\n if (!result.value) {\n return err(new AppError('NOT_FOUND', `Project not found: ${id}`));\n }\n return ok(result.value);\n });\n }\n\n updateProject(id: string, input: unknown): Result<Project> {\n return logger.startSpan('ProjectService.updateProject', () => {\n const parsed = UpdateProjectSchema.safeParse(input);\n if (!parsed.success) {\n return err(new AppError('VALIDATION', parsed.error.message));\n }\n return this.repo.update(id, parsed.data);\n });\n }\n\n deleteProject(id: string): Result<void> {\n return this.repo.delete(id);\n }\n\n resolveProject(idOrName?: string): Result<Project> {\n return logger.startSpan('ProjectService.resolveProject', () => {\n if (idOrName) {\n const byId = this.repo.findById(idOrName);\n if (!byId.ok) return byId;\n if (byId.value) return ok(byId.value);\n\n const byKey = this.repo.findByKey(idOrName.toUpperCase());\n if (!byKey.ok) return byKey;\n if (byKey.value) return ok(byKey.value);\n\n const byName = this.repo.findByName(idOrName);\n if (!byName.ok) return byName;\n if (byName.value) return ok(byName.value);\n\n return err(new AppError('NOT_FOUND', `Project not found: ${idOrName}`));\n }\n\n const defaultProject = this.repo.findDefault();\n if (!defaultProject.ok) return defaultProject;\n if (defaultProject.value) return ok(defaultProject.value);\n\n return err(\n new AppError(\n 'NOT_FOUND',\n 'No project specified and no default project set. Create a project first.',\n ),\n );\n });\n }\n\n nextTaskId(project: Project): Result<string> {\n return logger.startSpan('ProjectService.nextTaskId', () => {\n const counterResult = this.repo.incrementTaskCounter(project.id);\n if (!counterResult.ok) return counterResult;\n return ok(`${project.key}-${counterResult.value}`);\n });\n }\n}\n","import { z } from 'zod/v4';\nimport { TaskStatus, TaskType, DependencyType, UIDependencyType } from './enums.js';\n\nconst taskStatusValues = Object.values(TaskStatus) as [string, ...string[]];\nconst taskTypeValues = Object.values(TaskType) as [string, ...string[]];\nconst uiDepTypeValues = Object.values(UIDependencyType) as [string, ...string[]];\n\nconst DependencyEntrySchema = z.object({\n id: z.string().min(1),\n type: z.enum(uiDepTypeValues).default(DependencyType.Blocks),\n});\nexport type DependencyEntry = z.infer<typeof DependencyEntrySchema>;\n\nexport const CreateTaskSchema = z.object({\n name: z.string().min(1, 'Task name is required').max(500),\n description: z.string().max(10000).optional(),\n type: z.enum(taskTypeValues).default(TaskType.Story),\n status: z.enum(taskStatusValues).default(TaskStatus.Backlog),\n projectId: z.string().optional(),\n parentId: z.string().optional(),\n technicalNotes: z.string().max(50000).optional(),\n additionalRequirements: z.string().max(50000).optional(),\n dependsOn: z.array(DependencyEntrySchema).optional(),\n});\nexport type CreateTaskInput = z.infer<typeof CreateTaskSchema>;\n\nexport const UpdateTaskSchema = z.object({\n name: z.string().min(1).max(500).optional(),\n description: z.string().max(10000).optional(),\n type: z.enum(taskTypeValues).optional(),\n status: z.enum(taskStatusValues).optional(),\n parentId: z.string().nullable().optional(),\n technicalNotes: z.string().max(50000).optional(),\n additionalRequirements: z.string().max(50000).optional(),\n appendNotes: z.string().max(50000).optional(),\n appendRequirements: z.string().max(50000).optional(),\n});\nexport type UpdateTaskInput = z.infer<typeof UpdateTaskSchema>;\n\nexport const TaskFilterSchema = z.object({\n projectId: z.string().optional(),\n status: z.enum(taskStatusValues).optional(),\n type: z.enum(taskTypeValues).optional(),\n parentId: z.string().optional(),\n search: z.string().optional(),\n});\nexport type TaskFilter = z.infer<typeof TaskFilterSchema>;\n\nexport const RerankTaskSchema = z.object({\n taskId: z.string().min(1, 'Task id is required'),\n afterId: z.string().optional(),\n beforeId: z.string().optional(),\n position: z.number().int().min(1).optional(),\n});\nexport type RerankTaskInput = z.infer<typeof RerankTaskSchema>;\n\nexport interface Task {\n id: string;\n projectId: string;\n parentId: string | null;\n name: string;\n description: string;\n type: TaskType;\n status: TaskStatus;\n rank: number;\n technicalNotes: string;\n additionalRequirements: string;\n createdAt: string;\n updatedAt: string;\n}\n","import type { Result } from '../types/common.js';\nimport { ok, err } from '../types/common.js';\nimport type { Task, TaskFilter } from '../types/task.js';\nimport {\n CreateTaskSchema,\n UpdateTaskSchema,\n TaskFilterSchema,\n RerankTaskSchema,\n} from '../types/task.js';\nimport type { TaskRepository, SearchResult } from '../repository/task.repository.js';\nimport type { ProjectService } from './project.service.js';\nimport type { DependencyService } from './dependency.service.js';\nimport { AppError } from '../errors/app-error.js';\nimport { logger } from '../logging/logger.js';\nimport { TaskStatus, RANK_GAP, isTerminalStatus } from '../types/enums.js';\n\nexport interface TaskService {\n createTask(input: unknown, projectIdOrName?: string): Result<Task>;\n getTask(id: string): Result<Task>;\n listTasks(filter: unknown): Result<Task[]>;\n updateTask(id: string, input: unknown): Result<Task>;\n deleteTask(id: string): Result<void>;\n breakdownTask(parentId: string, subtasks: unknown[]): Result<Task[]>;\n rerankTask(input: unknown, projectIdOrName?: string): Result<Task>;\n searchTasks(query: string, projectIdOrName?: string): Result<SearchResult[]>;\n}\n\nexport class TaskServiceImpl implements TaskService {\n constructor(\n private readonly repo: TaskRepository,\n private readonly projectService: ProjectService,\n private readonly getDependencyService: () => DependencyService,\n ) {}\n\n createTask(input: unknown, projectIdOrName?: string): Result<Task> {\n return logger.startSpan('TaskService.createTask', () => {\n const parsed = CreateTaskSchema.safeParse(input);\n if (!parsed.success) {\n return err(new AppError('VALIDATION', parsed.error.message));\n }\n\n const projectRef = parsed.data.projectId ?? projectIdOrName;\n const projectResult = this.projectService.resolveProject(projectRef);\n if (!projectResult.ok) return projectResult;\n\n if (parsed.data.parentId) {\n const parentResult = this.repo.findById(parsed.data.parentId);\n if (!parentResult.ok) return parentResult;\n if (!parentResult.value) {\n return err(new AppError('NOT_FOUND', `Parent task not found: ${parsed.data.parentId}`));\n }\n }\n\n const project = projectResult.value;\n const taskIdResult = this.projectService.nextTaskId(project);\n if (!taskIdResult.ok) return taskIdResult;\n\n const insertResult = this.repo.insert(taskIdResult.value, {\n ...parsed.data,\n projectId: project.id,\n });\n if (!insertResult.ok) return insertResult;\n\n if (parsed.data.dependsOn && parsed.data.dependsOn.length > 0) {\n for (const entry of parsed.data.dependsOn) {\n const depResult = this.getDependencyService().addDependency({\n taskId: insertResult.value.id,\n dependsOnId: entry.id,\n type: entry.type,\n });\n if (!depResult.ok) return depResult;\n }\n }\n\n return insertResult;\n });\n }\n\n getTask(id: string): Result<Task> {\n return logger.startSpan('TaskService.getTask', () => {\n const result = this.repo.findById(id);\n if (!result.ok) return result;\n if (!result.value) {\n return err(new AppError('NOT_FOUND', `Task not found: ${id}`));\n }\n return ok(result.value);\n });\n }\n\n listTasks(filter: unknown): Result<Task[]> {\n return logger.startSpan('TaskService.listTasks', () => {\n const parsed = TaskFilterSchema.safeParse(filter);\n if (!parsed.success) {\n return err(new AppError('VALIDATION', parsed.error.message));\n }\n\n let resolvedFilter: TaskFilter = parsed.data;\n\n if (parsed.data.projectId) {\n const projectResult = this.projectService.resolveProject(parsed.data.projectId);\n if (!projectResult.ok) return projectResult;\n resolvedFilter = { ...resolvedFilter, projectId: projectResult.value.id };\n }\n\n return this.repo.findMany(resolvedFilter);\n });\n }\n\n updateTask(id: string, input: unknown): Result<Task> {\n return logger.startSpan('TaskService.updateTask', () => {\n const parsed = UpdateTaskSchema.safeParse(input);\n if (!parsed.success) {\n return err(new AppError('VALIDATION', parsed.error.message));\n }\n\n // Enforce: cannot start a task that still has unfinished blockers.\n if (parsed.data.status === TaskStatus.InProgress) {\n const blockersResult = this.getDependencyService().listBlockers(id);\n if (!blockersResult.ok) return blockersResult;\n const hasNonTerminalBlocker = blockersResult.value.some((b) => !isTerminalStatus(b.status));\n if (hasNonTerminalBlocker) {\n return err(\n new AppError('VALIDATION', 'Task is blocked by unfinished dependencies'),\n );\n }\n }\n\n // Check if transitioning to terminal status (done/cancelled)\n if (parsed.data.status && isTerminalStatus(parsed.data.status)) {\n const existingResult = this.repo.findById(id);\n if (!existingResult.ok) return existingResult;\n if (!existingResult.value) {\n return err(new AppError('NOT_FOUND', `Task not found: ${id}`));\n }\n const existing = existingResult.value;\n\n const updateResult = this.repo.update(id, parsed.data);\n if (!updateResult.ok) return updateResult;\n\n // Auto-rerank to bottom only when transitioning from active → terminal\n if (!isTerminalStatus(existing.status)) {\n const maxRankResult = this.repo.getMaxRank(existing.projectId);\n if (!maxRankResult.ok) return maxRankResult;\n return this.repo.rerank(id, maxRankResult.value + RANK_GAP);\n }\n return updateResult;\n }\n\n return this.repo.update(id, parsed.data);\n });\n }\n\n deleteTask(id: string): Result<void> {\n return this.repo.delete(id);\n }\n\n breakdownTask(parentId: string, subtasks: unknown[]): Result<Task[]> {\n return logger.startSpan('TaskService.breakdownTask', () => {\n const parentResult = this.repo.findById(parentId);\n if (!parentResult.ok) return parentResult;\n if (!parentResult.value) {\n return err(new AppError('NOT_FOUND', `Parent task not found: ${parentId}`));\n }\n\n const parent = parentResult.value;\n\n const projectResult = this.projectService.resolveProject(parent.projectId);\n if (!projectResult.ok) return projectResult;\n const project = projectResult.value;\n\n const created: Task[] = [];\n\n for (const subtask of subtasks) {\n const parsed = CreateTaskSchema.safeParse(subtask);\n if (!parsed.success) {\n return err(new AppError('VALIDATION', `Invalid subtask: ${parsed.error.message}`));\n }\n\n const taskIdResult = this.projectService.nextTaskId(project);\n if (!taskIdResult.ok) return taskIdResult;\n\n const result = this.repo.insert(taskIdResult.value, {\n ...parsed.data,\n projectId: parent.projectId,\n parentId,\n });\n if (!result.ok) return result;\n created.push(result.value);\n }\n\n return ok(created);\n });\n }\n\n /**\n * Re-rank a task using Jira-style ranking:\n * - afterId: place the task immediately after the given task\n * - beforeId: place the task immediately before the given task\n * - position: place the task at the given 1-based position in the backlog\n *\n * New rank is computed as the midpoint between neighbors.\n * If moving to the top, rank = first_rank - GAP.\n * If moving to the bottom, rank = last_rank + GAP.\n */\n rerankTask(input: unknown, projectIdOrName?: string): Result<Task> {\n return logger.startSpan('TaskService.rerankTask', () => {\n const parsed = RerankTaskSchema.safeParse(input);\n if (!parsed.success) {\n return err(new AppError('VALIDATION', parsed.error.message));\n }\n\n const { taskId, afterId, beforeId, position } = parsed.data;\n\n const specifiedCount = [afterId, beforeId, position].filter((v) => v !== undefined).length;\n if (specifiedCount !== 1) {\n return err(\n new AppError(\n 'VALIDATION',\n 'Exactly one of --after, --before, or --position must be specified',\n ),\n );\n }\n\n const taskResult = this.repo.findById(taskId);\n if (!taskResult.ok) return taskResult;\n if (!taskResult.value) {\n return err(new AppError('NOT_FOUND', `Task not found: ${taskId}`));\n }\n const task = taskResult.value;\n\n if (isTerminalStatus(task.status)) {\n return err(\n new AppError(\n 'VALIDATION',\n `Cannot rerank a task with status '${task.status}'. Only active tasks can be reranked.`,\n ),\n );\n }\n\n // Resolve project for getting ranked list\n const projectRef = projectIdOrName ?? task.projectId;\n const projectResult = this.projectService.resolveProject(projectRef);\n if (!projectResult.ok) return projectResult;\n const projectId = projectResult.value.id;\n\n // Get all backlog tasks in rank order (excluding the task being moved)\n const rankedResult = this.repo.getRankedTasks(projectId, TaskStatus.Backlog);\n if (!rankedResult.ok) return rankedResult;\n const ranked = rankedResult.value.filter((t) => t.id !== taskId);\n\n let newRank: number;\n\n if (afterId) {\n const anchor = ranked.find((t) => t.id === afterId);\n if (!anchor) {\n return err(new AppError('NOT_FOUND', `Anchor task not found in backlog: ${afterId}`));\n }\n const anchorIndex = ranked.indexOf(anchor);\n const next = ranked[anchorIndex + 1];\n newRank = next ? (anchor.rank + next.rank) / 2 : anchor.rank + RANK_GAP;\n } else if (beforeId) {\n const anchor = ranked.find((t) => t.id === beforeId);\n if (!anchor) {\n return err(new AppError('NOT_FOUND', `Anchor task not found in backlog: ${beforeId}`));\n }\n const anchorIndex = ranked.indexOf(anchor);\n const prev = ranked[anchorIndex - 1];\n newRank = prev ? (prev.rank + anchor.rank) / 2 : anchor.rank - RANK_GAP;\n } else {\n // position is defined (guaranteed by specifiedCount === 1 check above)\n const pos = position as number;\n if (pos < 1) {\n return err(new AppError('VALIDATION', 'Position must be >= 1'));\n }\n if (pos === 1) {\n const first = ranked[0];\n newRank = first ? first.rank - RANK_GAP : RANK_GAP;\n } else if (pos > ranked.length) {\n const last = ranked[ranked.length - 1];\n newRank = last ? last.rank + RANK_GAP : RANK_GAP;\n } else {\n const above = ranked[pos - 2];\n const below = ranked[pos - 1];\n if (!above || !below) {\n return err(new AppError('DB_ERROR', 'Unexpected missing neighbor tasks'));\n }\n newRank = (above.rank + below.rank) / 2;\n }\n }\n\n // Dependency constraint: a blocked task must not rank higher (lower number)\n // than any of its blockers, and must not rank lower than any of its dependents.\n const depService = this.getDependencyService();\n const blockersResult = depService.listBlockers(taskId);\n if (blockersResult.ok) {\n for (const blocker of blockersResult.value) {\n if (blocker.projectId === projectId && newRank < blocker.rank) {\n return err(\n new AppError(\n 'VALIDATION',\n `Cannot rank above blocker \"${blocker.id}\" (${blocker.name}). Complete or remove the dependency first.`,\n ),\n );\n }\n }\n }\n\n const dependentsResult = depService.listDependents(taskId);\n if (dependentsResult.ok) {\n for (const dep of dependentsResult.value) {\n if (dep.projectId === projectId && newRank > dep.rank) {\n return err(\n new AppError(\n 'VALIDATION',\n `Cannot rank below dependent \"${dep.id}\" (${dep.name}). Complete or remove the dependency first.`,\n ),\n );\n }\n }\n }\n\n return this.repo.rerank(taskId, newRank);\n });\n }\n\n searchTasks(query: string, projectIdOrName?: string): Result<SearchResult[]> {\n return logger.startSpan('TaskService.searchTasks', () => {\n if (!query.trim()) {\n return err(new AppError('VALIDATION', 'Search query cannot be empty'));\n }\n\n let projectId: string | undefined;\n if (projectIdOrName) {\n const projectResult = this.projectService.resolveProject(projectIdOrName);\n if (!projectResult.ok) return projectResult;\n projectId = projectResult.value.id;\n }\n\n return this.repo.search(query, projectId);\n });\n }\n}\n","import { z } from 'zod/v4';\nimport { DependencyType } from './enums.js';\n\n// Only DB-persisted types; blocked-by is resolved to blocks at the service layer.\nconst dbDepTypeValues = [\n DependencyType.Blocks,\n DependencyType.RelatesTo,\n DependencyType.Duplicates,\n] as const;\n\nexport const AddDependencySchema = z.object({\n taskId: z.string().min(1, 'Task id is required'),\n dependsOnId: z.string().min(1, 'Depends-on task id is required'),\n type: z.enum(dbDepTypeValues).default(DependencyType.Blocks),\n});\nexport type AddDependencyInput = z.infer<typeof AddDependencySchema>;\n\nexport const RemoveDependencySchema = z.object({\n taskId: z.string().min(1, 'Task id is required'),\n dependsOnId: z.string().min(1, 'Depends-on task id is required'),\n});\nexport type RemoveDependencyInput = z.infer<typeof RemoveDependencySchema>;\n\nexport interface TaskDependency {\n taskId: string;\n dependsOnId: string;\n type: DependencyType;\n createdAt: string;\n}\n","import type { Result } from '../types/common.js';\nimport { ok, err } from '../types/common.js';\nimport type { Task } from '../types/task.js';\nimport type { TaskDependency } from '../types/dependency.js';\nimport { AddDependencySchema, RemoveDependencySchema } from '../types/dependency.js';\nimport type { DependencyRepository } from '../repository/dependency.repository.js';\nimport type { TaskRepository } from '../repository/task.repository.js';\nimport { AppError } from '../errors/app-error.js';\nimport { logger } from '../logging/logger.js';\nimport { UIDependencyType, DependencyType } from '../types/enums.js';\n\nexport interface DependencyEdge {\n from: string;\n to: string;\n type: string;\n}\n\nexport interface DependencyGraph {\n nodes: Task[];\n edges: DependencyEdge[];\n mermaid: string;\n}\n\nexport interface DependencyService {\n addDependency(input: unknown): Result<TaskDependency>;\n removeDependency(input: unknown): Result<void>;\n /** Remove a dependency between two tasks regardless of which direction it was stored. */\n removeDependencyBetween(taskId: string, otherId: string): Result<void>;\n listBlockers(taskId: string): Result<Task[]>;\n listDependents(taskId: string): Result<Task[]>;\n listRelated(taskId: string): Result<Task[]>;\n listDuplicates(taskId: string): Result<Task[]>;\n listAllDeps(taskId: string): Result<TaskDependency[]>;\n getTransitiveDeps(taskId: string): Result<Task[]>;\n buildGraph(taskId: string): Result<DependencyGraph>;\n}\n\nexport class DependencyServiceImpl implements DependencyService {\n constructor(\n private readonly depRepo: DependencyRepository,\n private readonly taskRepo: TaskRepository,\n ) {}\n\n private requireTask(taskId: string): Result<Task> {\n const result = this.taskRepo.findById(taskId);\n if (!result.ok) return result;\n if (!result.value) {\n return err(new AppError('NOT_FOUND', `Task not found: ${taskId}`));\n }\n return ok(result.value);\n }\n\n addDependency(input: unknown): Result<TaskDependency> {\n return logger.startSpan('DependencyService.addDependency', () => {\n // Normalize blocked-by: callers express \"A is blocked-by B\" as\n // {taskId: A, dependsOnId: B, type: blocked-by}; we store it as\n // {taskId: B, dependsOnId: A, type: blocks} (B blocks A).\n const normalized = normalizeBlockedBy(input);\n const parsed = AddDependencySchema.safeParse(normalized);\n if (!parsed.success) {\n return err(new AppError('VALIDATION', parsed.error.message));\n }\n\n const { taskId, dependsOnId, type } = parsed.data;\n\n const taskResult = this.requireTask(taskId);\n if (!taskResult.ok) return taskResult;\n\n const depResult = this.requireTask(dependsOnId);\n if (!depResult.ok) return depResult;\n\n const cycleResult = this.depRepo.wouldCreateCycle(taskId, dependsOnId);\n if (!cycleResult.ok) return cycleResult;\n if (cycleResult.value) {\n return err(\n new AppError(\n 'VALIDATION',\n `Adding this dependency would create a cycle: ${taskId} -> ${dependsOnId}`,\n ),\n );\n }\n\n return this.depRepo.insert(taskId, dependsOnId, type);\n });\n }\n\n removeDependency(input: unknown): Result<void> {\n return logger.startSpan('DependencyService.removeDependency', () => {\n const parsed = RemoveDependencySchema.safeParse(input);\n if (!parsed.success) {\n return err(new AppError('VALIDATION', parsed.error.message));\n }\n return this.depRepo.delete(parsed.data.taskId, parsed.data.dependsOnId);\n });\n }\n\n removeDependencyBetween(taskId: string, otherId: string): Result<void> {\n return logger.startSpan('DependencyService.removeDependencyBetween', () => {\n const forward = this.depRepo.delete(taskId, otherId);\n if (forward.ok) return forward;\n return this.depRepo.delete(otherId, taskId);\n });\n }\n\n listBlockers(taskId: string): Result<Task[]> {\n return this.depRepo.getBlockers(taskId);\n }\n\n listDependents(taskId: string): Result<Task[]> {\n return this.depRepo.getDependents(taskId);\n }\n\n listRelated(taskId: string): Result<Task[]> {\n return this.depRepo.getRelated(taskId);\n }\n\n listDuplicates(taskId: string): Result<Task[]> {\n return this.depRepo.getDuplicates(taskId);\n }\n\n listAllDeps(taskId: string): Result<TaskDependency[]> {\n return this.depRepo.findByTask(taskId);\n }\n\n getTransitiveDeps(taskId: string): Result<Task[]> {\n return this.depRepo.getTransitiveClosure(taskId);\n }\n\n buildGraph(taskId: string): Result<DependencyGraph> {\n return logger.startSpan('DependencyService.buildGraph', () => {\n const taskResult = this.taskRepo.findById(taskId);\n if (!taskResult.ok) return taskResult;\n if (!taskResult.value) {\n return err(new AppError('NOT_FOUND', `Task not found: ${taskId}`));\n }\n const rootTask = taskResult.value;\n\n // Collect all reachable nodes via BFS in both directions\n const visited = new Map<string, Task>();\n const allEdges: DependencyEdge[] = [];\n const queue: string[] = [taskId];\n visited.set(taskId, rootTask);\n\n while (queue.length > 0) {\n const current = queue.shift();\n if (!current) break;\n\n // Outgoing: things this task depends on\n const blockersResult = this.depRepo.findByTask(current);\n if (!blockersResult.ok) return blockersResult;\n for (const dep of blockersResult.value) {\n allEdges.push({ from: dep.taskId, to: dep.dependsOnId, type: dep.type });\n if (!visited.has(dep.dependsOnId)) {\n const t = this.taskRepo.findById(dep.dependsOnId);\n if (!t.ok) return t;\n if (t.value) {\n visited.set(dep.dependsOnId, t.value);\n queue.push(dep.dependsOnId);\n }\n }\n }\n\n // Incoming: things that depend on this task\n const dependentsResult = this.depRepo.findDependents(current);\n if (!dependentsResult.ok) return dependentsResult;\n for (const dep of dependentsResult.value) {\n allEdges.push({ from: dep.taskId, to: dep.dependsOnId, type: dep.type });\n if (!visited.has(dep.taskId)) {\n const t = this.taskRepo.findById(dep.taskId);\n if (!t.ok) return t;\n if (t.value) {\n visited.set(dep.taskId, t.value);\n queue.push(dep.taskId);\n }\n }\n }\n }\n\n // Deduplicate edges\n const edgeSet = new Set<string>();\n const uniqueEdges: DependencyEdge[] = [];\n for (const edge of allEdges) {\n const key = `${edge.from}->${edge.to}`;\n if (!edgeSet.has(key)) {\n edgeSet.add(key);\n uniqueEdges.push(edge);\n }\n }\n\n const nodes = Array.from(visited.values());\n const mermaid = this.toMermaid(nodes, uniqueEdges, taskId);\n\n return ok({ nodes, edges: uniqueEdges, mermaid });\n });\n }\n\n private toMermaid(nodes: Task[], edges: DependencyEdge[], highlightId: string): string {\n const lines: string[] = ['graph LR'];\n\n for (const node of nodes) {\n const label = `${node.id}: ${node.name} [${node.status}]`;\n const escaped = label.replace(/\"/g, '#quot;');\n if (node.id === highlightId) {\n lines.push(` ${node.id}(\"${escaped}\"):::highlight`);\n } else {\n lines.push(` ${node.id}[\"${escaped}\"]`);\n }\n }\n\n for (const edge of edges) {\n const label = edge.type === 'blocks' ? 'blocks' : edge.type;\n lines.push(` ${edge.from} -->|${label}| ${edge.to}`);\n }\n\n lines.push(' classDef highlight fill:#f9f,stroke:#333,stroke-width:2px');\n\n return lines.join('\\n');\n }\n}\n\n/**\n * Normalizes a blocked-by relationship before schema validation.\n * \"A blocked-by B\" is stored as \"B blocks A\": swap taskId/dependsOnId\n * and change type from blocked-by to blocks.\n */\nfunction normalizeBlockedBy(input: unknown): unknown {\n if (\n typeof input === 'object' &&\n input !== null &&\n 'type' in input &&\n (input as Record<string, unknown>).type === UIDependencyType.BlockedBy\n ) {\n const { taskId, dependsOnId, ...rest } = input as Record<string, unknown>;\n return { ...rest, taskId: dependsOnId, dependsOnId: taskId, type: DependencyType.Blocks };\n }\n return input;\n}\n","import { z } from 'zod/v4';\n\n// ── Export types ──────────────────────────────────────────────────────\n\nexport interface ExportTask {\n id: string;\n name: string;\n description: string;\n type: string;\n status: string;\n parentId: string | null;\n technicalNotes: string;\n additionalRequirements: string;\n rank: number;\n}\n\nexport interface ExportDependency {\n taskId: string;\n dependsOnId: string;\n type: string;\n}\n\nexport interface ExportData {\n version: 1;\n exportedAt: string;\n tasks: ExportTask[];\n dependencies: ExportDependency[];\n}\n\n// ── Import types ──────────────────────────────────────────────────────\n\n/** Loose schema: tasks/dependencies are arbitrary objects to allow field mapping. */\nexport const ImportFileSchema = z.object({\n version: z.number().optional(),\n tasks: z.array(z.record(z.string(), z.unknown())).min(1, 'At least one task is required'),\n dependencies: z.array(z.record(z.string(), z.unknown())).optional().default([]),\n});\nexport type ImportFile = z.infer<typeof ImportFileSchema>;\n\n/** Map from source field name → our field name. */\nexport type FieldMapping = Map<string, string>;\n\nexport interface ImportResult {\n imported: number;\n dependencies: number;\n idMap: Record<string, string>;\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────\n\n/**\n * Parse a comma-separated \"source:target\" mapping string.\n * Example: \"title:name,summary:description,key:id\"\n */\nexport function parseFieldMapping(raw: string): FieldMapping {\n const mapping = new Map<string, string>();\n for (const pair of raw.split(',')) {\n const parts = pair.split(':').map((s) => s.trim());\n if (parts.length === 2 && parts[0] && parts[1]) {\n mapping.set(parts[0], parts[1]);\n }\n }\n return mapping;\n}\n","import type { Result } from '../types/common.js';\nimport { ok, err } from '../types/common.js';\nimport type {\n ExportData,\n ExportTask,\n ExportDependency,\n FieldMapping,\n ImportResult,\n} from '../types/portability.js';\nimport { ImportFileSchema } from '../types/portability.js';\nimport type { TaskService } from './task.service.js';\nimport type { DependencyService } from './dependency.service.js';\nimport type { ProjectService } from './project.service.js';\nimport { AppError } from '../errors/app-error.js';\nimport { logger } from '../logging/logger.js';\n\n// ── Internal mapped types ─────────────────────────────────────────────\n\ninterface MappedTask {\n sourceId: string;\n name: string;\n description: string;\n type: string;\n status: string;\n parentId: string | null;\n technicalNotes: string;\n additionalRequirements: string;\n}\n\ninterface MappedDependency {\n sourceTaskId: string;\n sourceDependsOnId: string;\n type: string;\n}\n\n// ── Service interface ─────────────────────────────────────────────────\n\nexport interface PortabilityService {\n exportTasks(projectIdOrName?: string): Result<ExportData>;\n importTasks(\n fileData: unknown,\n projectIdOrName?: string,\n fieldMapping?: FieldMapping,\n ): Result<ImportResult>;\n}\n\n// ── Implementation ────────────────────────────────────────────────────\n\nexport class PortabilityServiceImpl implements PortabilityService {\n constructor(\n private readonly taskService: TaskService,\n private readonly depService: DependencyService,\n private readonly projectService: ProjectService,\n ) {}\n\n exportTasks(projectIdOrName?: string): Result<ExportData> {\n return logger.startSpan('PortabilityService.exportTasks', () => {\n const projectResult = this.projectService.resolveProject(projectIdOrName);\n if (!projectResult.ok) return projectResult;\n const project = projectResult.value;\n\n const tasksResult = this.taskService.listTasks({ projectId: project.id });\n if (!tasksResult.ok) return tasksResult;\n const tasks = tasksResult.value;\n\n const taskIds = new Set(tasks.map((t) => t.id));\n\n const exportTasks: ExportTask[] = tasks.map((t) => ({\n id: t.id,\n name: t.name,\n description: t.description,\n type: t.type,\n status: t.status,\n parentId: t.parentId,\n technicalNotes: t.technicalNotes,\n additionalRequirements: t.additionalRequirements,\n rank: t.rank,\n }));\n\n // Collect dependencies where both ends belong to this project\n const allDeps: ExportDependency[] = [];\n for (const task of tasks) {\n const depsResult = this.depService.listAllDeps(task.id);\n if (!depsResult.ok) return depsResult;\n for (const dep of depsResult.value) {\n if (taskIds.has(dep.dependsOnId)) {\n allDeps.push({\n taskId: dep.taskId,\n dependsOnId: dep.dependsOnId,\n type: dep.type,\n });\n }\n }\n }\n\n logger.info('Exported tasks', {\n project: project.key,\n tasks: tasks.length,\n dependencies: allDeps.length,\n });\n\n return ok({\n version: 1 as const,\n exportedAt: new Date().toISOString(),\n tasks: exportTasks,\n dependencies: allDeps,\n });\n });\n }\n\n importTasks(\n fileData: unknown,\n projectIdOrName?: string,\n fieldMapping?: FieldMapping,\n ): Result<ImportResult> {\n return logger.startSpan('PortabilityService.importTasks', () => {\n // 1. Validate input structure\n const parsed = ImportFileSchema.safeParse(fileData);\n if (!parsed.success) {\n return err(new AppError('VALIDATION', parsed.error.message));\n }\n\n // 2. Build reverse map (ourField → sourceField)\n const reverseMap = this.buildReverseMap(fieldMapping);\n\n // 3. Map source tasks to our schema\n const mappedTasks: MappedTask[] = [];\n for (const sourceTask of parsed.data.tasks) {\n const mapped = this.mapTaskFields(sourceTask, reverseMap);\n if (!mapped.ok) return mapped;\n mappedTasks.push(mapped.value);\n }\n\n // 4. Map source dependencies\n const mappedDeps: MappedDependency[] = [];\n for (const sourceDep of parsed.data.dependencies) {\n const mapped = this.mapDependencyFields(sourceDep, reverseMap);\n if (!mapped.ok) return mapped;\n mappedDeps.push(mapped.value);\n }\n\n // 5. Topological sort so parents are created before children\n const sorted = this.topoSortByParent(mappedTasks);\n\n // 6. Create tasks, building sourceId → newId map\n const idMap = new Map<string, string>();\n for (const task of sorted) {\n let parentId: string | undefined;\n if (task.parentId) {\n parentId = idMap.get(task.parentId) ?? task.parentId;\n }\n\n const createResult = this.taskService.createTask(\n {\n name: task.name,\n description: task.description || undefined,\n type: task.type || undefined,\n status: task.status || undefined,\n parentId,\n technicalNotes: task.technicalNotes || undefined,\n additionalRequirements: task.additionalRequirements || undefined,\n },\n projectIdOrName,\n );\n if (!createResult.ok) return createResult;\n\n idMap.set(task.sourceId, createResult.value.id);\n logger.info('Imported task', {\n sourceId: task.sourceId,\n newId: createResult.value.id,\n });\n }\n\n // 7. Add dependencies with remapped IDs\n let depCount = 0;\n for (const dep of mappedDeps) {\n const taskId = idMap.get(dep.sourceTaskId) ?? dep.sourceTaskId;\n const dependsOnId = idMap.get(dep.sourceDependsOnId) ?? dep.sourceDependsOnId;\n\n const depResult = this.depService.addDependency({\n taskId,\n dependsOnId,\n type: dep.type || undefined,\n });\n if (!depResult.ok) return depResult;\n\n depCount++;\n logger.info('Imported dependency', { from: taskId, to: dependsOnId });\n }\n\n const idMapObj: Record<string, string> = {};\n for (const [k, v] of idMap) {\n idMapObj[k] = v;\n }\n\n logger.info('Import completed', {\n tasks: mappedTasks.length,\n dependencies: depCount,\n });\n\n return ok({\n imported: mappedTasks.length,\n dependencies: depCount,\n idMap: idMapObj,\n });\n });\n }\n\n // ── Private helpers ───────────────────────────────────────────────\n\n /** Invert the user-provided mapping (source→target) into (target→source). */\n private buildReverseMap(fieldMapping?: FieldMapping): Map<string, string> {\n const reverse = new Map<string, string>();\n if (!fieldMapping) return reverse;\n for (const [source, target] of fieldMapping) {\n reverse.set(target, source);\n }\n return reverse;\n }\n\n /** Read a field from a source object, checking reverse-mapped name first, then literal name. */\n private getField(\n source: Record<string, unknown>,\n field: string,\n reverseMap: Map<string, string>,\n ): string {\n const sourceField = reverseMap.get(field) ?? field;\n const value = source[sourceField];\n if (value == null) return '';\n if (typeof value === 'string') return value;\n if (typeof value === 'number' || typeof value === 'boolean') return `${value}`;\n return JSON.stringify(value);\n }\n\n private mapTaskFields(\n source: Record<string, unknown>,\n reverseMap: Map<string, string>,\n ): Result<MappedTask> {\n const sourceId = this.getField(source, 'id', reverseMap);\n const name = this.getField(source, 'name', reverseMap);\n\n if (!sourceId) {\n return err(new AppError('VALIDATION', 'Each imported task must have an id'));\n }\n if (!name) {\n return err(\n new AppError('VALIDATION', `Imported task '${sourceId}' is missing required field 'name'`),\n );\n }\n\n return ok({\n sourceId,\n name,\n description: this.getField(source, 'description', reverseMap),\n type: this.getField(source, 'type', reverseMap),\n status: this.getField(source, 'status', reverseMap),\n parentId: this.getField(source, 'parentId', reverseMap) || null,\n technicalNotes: this.getField(source, 'technicalNotes', reverseMap),\n additionalRequirements: this.getField(source, 'additionalRequirements', reverseMap),\n });\n }\n\n private mapDependencyFields(\n source: Record<string, unknown>,\n reverseMap: Map<string, string>,\n ): Result<MappedDependency> {\n const taskId = this.getField(source, 'taskId', reverseMap);\n const dependsOnId = this.getField(source, 'dependsOnId', reverseMap);\n\n if (!taskId || !dependsOnId) {\n return err(new AppError('VALIDATION', 'Each dependency must have taskId and dependsOnId'));\n }\n\n return ok({\n sourceTaskId: taskId,\n sourceDependsOnId: dependsOnId,\n type: this.getField(source, 'type', reverseMap),\n });\n }\n\n /**\n * Sort tasks so that parents come before children within the import set.\n * Tasks whose parentId is outside the import set are treated as roots.\n */\n private topoSortByParent(tasks: MappedTask[]): MappedTask[] {\n const sourceIds = new Set(tasks.map((t) => t.sourceId));\n const sorted: MappedTask[] = [];\n const remaining = new Set(tasks);\n const created = new Set<string>();\n\n while (remaining.size > 0) {\n const batch: MappedTask[] = [];\n for (const task of remaining) {\n const parentInImport = task.parentId !== null && sourceIds.has(task.parentId);\n if (!parentInImport || (task.parentId !== null && created.has(task.parentId))) {\n batch.push(task);\n }\n }\n\n if (batch.length === 0) {\n logger.warn('Circular parent references detected during import, forcing remaining tasks');\n for (const t of remaining) {\n sorted.push(t);\n }\n break;\n }\n\n for (const t of batch) {\n remaining.delete(t);\n created.add(t.sourceId);\n sorted.push(t);\n }\n }\n\n return sorted;\n }\n}\n","import type Database from 'better-sqlite3';\nimport { SqliteProjectRepository } from '../repository/project.repository.js';\nimport { SqliteTaskRepository } from '../repository/task.repository.js';\nimport { SqliteDependencyRepository } from '../repository/dependency.repository.js';\nimport { ProjectServiceImpl } from '../service/project.service.js';\nimport { TaskServiceImpl } from '../service/task.service.js';\nimport { DependencyServiceImpl } from '../service/dependency.service.js';\nimport { PortabilityServiceImpl } from '../service/portability.service.js';\nimport type { ProjectService } from '../service/project.service.js';\nimport type { TaskService } from '../service/task.service.js';\nimport type { DependencyService } from '../service/dependency.service.js';\nimport type { PortabilityService } from '../service/portability.service.js';\n\nexport interface Container {\n projectService: ProjectService;\n taskService: TaskService;\n dependencyService: DependencyService;\n portabilityService: PortabilityService;\n}\n\nexport function createContainer(db: Database.Database): Container {\n const projectRepo = new SqliteProjectRepository(db);\n const taskRepo = new SqliteTaskRepository(db);\n const depRepo = new SqliteDependencyRepository(db);\n const projectService = new ProjectServiceImpl(projectRepo);\n const dependencyService = new DependencyServiceImpl(depRepo, taskRepo);\n const taskService = new TaskServiceImpl(taskRepo, projectService, () => dependencyService);\n const portabilityService = new PortabilityServiceImpl(\n taskService,\n dependencyService,\n projectService,\n );\n\n return { projectService, taskService, dependencyService, portabilityService };\n}\n","import { Command } from 'commander';\nimport type { Container } from './container.js';\nimport { registerProjectCreate } from './commands/project/create.js';\nimport { registerProjectList } from './commands/project/list.js';\nimport { registerProjectUpdate } from './commands/project/update.js';\nimport { registerProjectDelete } from './commands/project/delete.js';\nimport { registerProjectSetDefault } from './commands/project/set-default.js';\nimport { registerTaskCreate } from './commands/task/create.js';\nimport { registerTaskList } from './commands/task/list.js';\nimport { registerTaskShow } from './commands/task/show.js';\nimport { registerTaskUpdate } from './commands/task/update.js';\nimport { registerTaskDelete } from './commands/task/delete.js';\nimport { registerTaskBreakdown } from './commands/task/breakdown.js';\nimport { registerTaskRank } from './commands/task/rank.js';\nimport { registerTaskSearch } from './commands/task/search.js';\nimport { registerTaskExport } from './commands/task/export.js';\nimport { registerTaskImport } from './commands/task/import.js';\nimport { registerDepAdd } from './commands/dep/add.js';\nimport { registerDepRemove } from './commands/dep/remove.js';\nimport { registerDepList } from './commands/dep/list.js';\nimport { registerDepGraph } from './commands/dep/graph.js';\n\nexport function buildCLI(container: Container): Command {\n const program = new Command();\n program\n .name('tayto')\n .description('CLI task management for solo devs and AI agents')\n .version('0.1.0');\n\n const project = program.command('project').description('Manage projects');\n registerProjectCreate(project, container);\n registerProjectList(project, container);\n registerProjectUpdate(project, container);\n registerProjectDelete(project, container);\n registerProjectSetDefault(project, container);\n\n const task = program.command('task').description('Manage tasks');\n registerTaskCreate(task, container);\n registerTaskList(task, container);\n registerTaskShow(task, container);\n registerTaskUpdate(task, container);\n registerTaskDelete(task, container);\n registerTaskBreakdown(task, container);\n registerTaskRank(task, container);\n registerTaskSearch(task, container);\n registerTaskExport(task, container);\n registerTaskImport(task, container);\n\n const dep = program.command('dep').description('Manage task dependencies');\n registerDepAdd(dep, container);\n registerDepRemove(dep, container);\n registerDepList(dep, container);\n registerDepGraph(dep, container);\n\n program\n .command('tui')\n .description('Launch interactive terminal UI')\n .option('-p, --project <project>', 'Start with specific project')\n .action(async (opts: { project?: string }) => {\n const { launchTUI } = await import('../tui/index.js');\n await launchTUI(container, opts.project);\n });\n\n return program;\n}\n","import type { AppError } from '../errors/app-error.js';\n\nexport function printSuccess(data: unknown): void {\n process.stdout.write(JSON.stringify({ ok: true, data }, null, 2) + '\\n');\n}\n\nexport function printError(error: AppError): never {\n process.stderr.write(\n JSON.stringify({ ok: false, error: { code: error.code, message: error.message } }, null, 2) +\n '\\n',\n );\n process.exit(1);\n}\n\nexport function handleResult(\n result: { ok: true; value: unknown } | { ok: false; error: AppError },\n): void {\n if (result.ok) {\n printSuccess(result.value);\n } else {\n printError(result.error);\n }\n}\n","import { Command } from 'commander';\nimport type { Container } from '../../container.js';\nimport { handleResult } from '../../output.js';\n\nexport function registerProjectCreate(parent: Command, container: Container): void {\n parent\n .command('create')\n .description('Create a new project')\n .requiredOption('-n, --name <name>', 'Project name')\n .option(\n '-k, --key <key>',\n 'Project key (2-10 alphanumeric chars, defaults to first 3 chars of name)',\n )\n .option('-d, --description <description>', 'Project description')\n .option('--default', 'Set as default project')\n .action((opts: { name: string; key?: string; description?: string; default?: boolean }) => {\n const result = container.projectService.createProject({\n name: opts.name,\n key: opts.key,\n description: opts.description,\n isDefault: opts.default,\n });\n handleResult(result);\n });\n}\n","import { Command } from 'commander';\nimport type { Container } from '../../container.js';\nimport { handleResult } from '../../output.js';\n\nexport function registerProjectList(parent: Command, container: Container): void {\n parent\n .command('list')\n .description('List all projects')\n .action(() => {\n const result = container.projectService.listProjects();\n handleResult(result);\n });\n}\n","import { Command } from 'commander';\nimport type { Container } from '../../container.js';\nimport { handleResult } from '../../output.js';\n\nexport function registerProjectUpdate(parent: Command, container: Container): void {\n parent\n .command('update <idOrKeyOrName>')\n .description('Update a project (lookup by id, key, or name)')\n .option('-n, --name <name>', 'Project name')\n .option('-d, --description <description>', 'Project description')\n .option('--default', 'Set as default project')\n .action(\n (idOrKeyOrName: string, opts: { name?: string; description?: string; default?: boolean }) => {\n const resolved = container.projectService.resolveProject(idOrKeyOrName);\n if (!resolved.ok) {\n handleResult(resolved);\n return;\n }\n const result = container.projectService.updateProject(resolved.value.id, {\n name: opts.name,\n description: opts.description,\n isDefault: opts.default,\n });\n handleResult(result);\n },\n );\n}\n","import { Command } from 'commander';\nimport type { Container } from '../../container.js';\nimport { handleResult } from '../../output.js';\n\nexport function registerProjectDelete(parent: Command, container: Container): void {\n parent\n .command('delete <idOrKeyOrName>')\n .description('Delete a project (lookup by id, key, or name)')\n .action((idOrKeyOrName: string) => {\n const resolved = container.projectService.resolveProject(idOrKeyOrName);\n if (!resolved.ok) {\n handleResult(resolved);\n return;\n }\n const result = container.projectService.deleteProject(resolved.value.id);\n handleResult(result);\n });\n}\n","import { Command } from 'commander';\nimport type { Container } from '../../container.js';\nimport { handleResult } from '../../output.js';\n\nexport function registerProjectSetDefault(parent: Command, container: Container): void {\n parent\n .command('set-default <idOrKeyOrName>')\n .description('Set a project as the default (lookup by id, key, or name)')\n .action((idOrKeyOrName: string) => {\n const resolved = container.projectService.resolveProject(idOrKeyOrName);\n if (!resolved.ok) {\n handleResult(resolved);\n return;\n }\n const result = container.projectService.updateProject(resolved.value.id, {\n isDefault: true,\n });\n handleResult(result);\n });\n}\n","import { Command } from 'commander';\nimport type { Container } from '../../container.js';\nimport { handleResult } from '../../output.js';\n\nexport function registerTaskCreate(parent: Command, container: Container): void {\n parent\n .command('create')\n .description('Create a new task (appended to bottom of backlog)')\n .requiredOption('-n, --name <name>', 'Task name')\n .option('-p, --project <project>', 'Project id or name')\n .option('-d, --description <description>', 'Task description')\n .option('-t, --type <type>', 'Task type: story, tech-debt, bug', 'story')\n .option('-s, --status <status>', 'Task status', 'backlog')\n .option('--parent <parentId>', 'Parent task id for subtask')\n .option('--technical-notes <notes>', 'Technical notes (markdown)')\n .option('--additional-requirements <requirements>', 'Additional requirements (markdown)')\n .option('--depends-on <ids...>', 'Task ids this task depends on (blocks relationship)')\n .action(\n (opts: {\n name: string;\n project?: string;\n description?: string;\n type?: string;\n status?: string;\n parent?: string;\n technicalNotes?: string;\n additionalRequirements?: string;\n dependsOn?: string[];\n }) => {\n const result = container.taskService.createTask(\n {\n name: opts.name,\n description: opts.description,\n type: opts.type,\n status: opts.status,\n parentId: opts.parent,\n technicalNotes: opts.technicalNotes,\n additionalRequirements: opts.additionalRequirements,\n dependsOn: opts.dependsOn?.map((id) => ({ id })),\n },\n opts.project,\n );\n handleResult(result);\n },\n );\n}\n","import { Command } from 'commander';\nimport type { Container } from '../../container.js';\nimport { handleResult } from '../../output.js';\n\nexport function registerTaskList(parent: Command, container: Container): void {\n parent\n .command('list')\n .description('List tasks in rank order (defaults to backlog)')\n .option('-p, --project <project>', 'Filter by project id or name')\n .option('-s, --status <status>', 'Filter by status (default: backlog)')\n .option('-t, --type <type>', 'Filter by type')\n .option('--parent <parentId>', 'Filter by parent task id')\n .option('--search <text>', 'Search in name, description, and notes')\n .action(\n (opts: {\n project?: string;\n status?: string;\n type?: string;\n parent?: string;\n search?: string;\n }) => {\n const result = container.taskService.listTasks({\n projectId: opts.project,\n status: opts.status ?? 'backlog',\n type: opts.type,\n parentId: opts.parent,\n search: opts.search,\n });\n handleResult(result);\n },\n );\n}\n","import { Command } from 'commander';\nimport type { Container } from '../../container.js';\nimport { handleResult } from '../../output.js';\n\nexport function registerTaskShow(parent: Command, container: Container): void {\n parent\n .command('show <id>')\n .description('Show task details')\n .action((id: string) => {\n const result = container.taskService.getTask(id);\n handleResult(result);\n });\n}\n","import { Command } from 'commander';\nimport type { Container } from '../../container.js';\nimport { handleResult } from '../../output.js';\n\nexport function registerTaskUpdate(parent: Command, container: Container): void {\n parent\n .command('update <id>')\n .description('Update a task')\n .option('-n, --name <name>', 'Task name')\n .option('-d, --description <description>', 'Task description')\n .option('-t, --type <type>', 'Task type: story, tech-debt, bug')\n .option('-s, --status <status>', 'Task status')\n .option('--parent <parentId>', 'Parent task id')\n .option('--technical-notes <notes>', 'Replace technical notes')\n .option('--additional-requirements <requirements>', 'Replace additional requirements')\n .option('--append-notes <notes>', 'Append to technical notes')\n .option('--append-requirements <requirements>', 'Append to additional requirements')\n .action(\n (\n id: string,\n opts: {\n name?: string;\n description?: string;\n type?: string;\n status?: string;\n parent?: string;\n technicalNotes?: string;\n additionalRequirements?: string;\n appendNotes?: string;\n appendRequirements?: string;\n },\n ) => {\n const result = container.taskService.updateTask(id, {\n name: opts.name,\n description: opts.description,\n type: opts.type,\n status: opts.status,\n parentId: opts.parent,\n technicalNotes: opts.technicalNotes,\n additionalRequirements: opts.additionalRequirements,\n appendNotes: opts.appendNotes,\n appendRequirements: opts.appendRequirements,\n });\n handleResult(result);\n },\n );\n}\n","import { Command } from 'commander';\nimport type { Container } from '../../container.js';\nimport { handleResult } from '../../output.js';\n\nexport function registerTaskDelete(parent: Command, container: Container): void {\n parent\n .command('delete <id>')\n .description('Delete a task')\n .action((id: string) => {\n const result = container.taskService.deleteTask(id);\n handleResult(result);\n });\n}\n","import { readFileSync } from 'node:fs';\nimport { Command } from 'commander';\nimport type { Container } from '../../container.js';\nimport { handleResult, printError } from '../../output.js';\nimport { AppError } from '../../../errors/app-error.js';\n\nexport function registerTaskBreakdown(parent: Command, container: Container): void {\n parent\n .command('breakdown <parentId>')\n .description('Create subtasks from a JSON file')\n .requiredOption('-f, --file <path>', 'JSON file with array of subtask definitions')\n .action((parentId: string, opts: { file: string }) => {\n let content: string;\n try {\n content = readFileSync(opts.file, 'utf-8');\n } catch (e) {\n return printError(\n new AppError('VALIDATION', `Failed to read subtasks file: ${opts.file}`, e),\n );\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(content);\n } catch (e) {\n return printError(\n new AppError('VALIDATION', `Invalid JSON in subtasks file: ${opts.file}`, e),\n );\n }\n\n if (!Array.isArray(parsed)) {\n return printError(new AppError('VALIDATION', 'File must contain a JSON array of subtasks'));\n }\n\n handleResult(container.taskService.breakdownTask(parentId, parsed));\n });\n}\n","import { Command } from 'commander';\nimport type { Container } from '../../container.js';\nimport { handleResult } from '../../output.js';\n\nexport function registerTaskRank(parent: Command, container: Container): void {\n parent\n .command('rank <id>')\n .description('Re-rank a task in the backlog (Jira-style positioning)')\n .option('--after <taskId>', 'Place immediately after this task')\n .option('--before <taskId>', 'Place immediately before this task')\n .option('--position <n>', 'Place at 1-based position in backlog')\n .option('-p, --project <project>', 'Project id or name')\n .action(\n (\n id: string,\n opts: {\n after?: string;\n before?: string;\n position?: string;\n project?: string;\n },\n ) => {\n const result = container.taskService.rerankTask(\n {\n taskId: id,\n afterId: opts.after,\n beforeId: opts.before,\n position: opts.position ? parseInt(opts.position, 10) : undefined,\n },\n opts.project,\n );\n handleResult(result);\n },\n );\n}\n","import { Command } from 'commander';\nimport type { Container } from '../../container.js';\nimport { handleResult } from '../../output.js';\n\nexport function registerTaskSearch(parent: Command, container: Container): void {\n parent\n .command('search <query>')\n .description('Full-text search tasks with relevance ranking (FTS5)')\n .option('-p, --project <project>', 'Limit search to a project')\n .action((query: string, opts: { project?: string }) => {\n const result = container.taskService.searchTasks(query, opts.project);\n handleResult(result);\n });\n}\n","import { writeFileSync } from 'node:fs';\nimport { Command } from 'commander';\nimport type { Container } from '../../container.js';\nimport { printSuccess, printError } from '../../output.js';\nimport { AppError } from '../../../errors/app-error.js';\n\nexport function registerTaskExport(parent: Command, container: Container): void {\n parent\n .command('export')\n .description('Export tasks to JSON file')\n .option('-p, --project <project>', 'Project id or name')\n .option('-o, --output <file>', 'Output file path (defaults to stdout)')\n .action((opts: { project?: string; output?: string }) => {\n const result = container.portabilityService.exportTasks(opts.project);\n if (!result.ok) {\n return printError(result.error);\n }\n\n if (opts.output) {\n try {\n writeFileSync(opts.output, JSON.stringify(result.value, null, 2) + '\\n', 'utf-8');\n } catch (e) {\n return printError(new AppError('UNKNOWN', `Failed to write file: ${opts.output}`, e));\n }\n printSuccess({\n file: opts.output,\n tasks: result.value.tasks.length,\n dependencies: result.value.dependencies.length,\n });\n } else {\n printSuccess(result.value);\n }\n });\n}\n","import { readFileSync } from 'node:fs';\nimport { Command } from 'commander';\nimport type { Container } from '../../container.js';\nimport { handleResult, printError } from '../../output.js';\nimport { parseFieldMapping } from '../../../types/portability.js';\nimport { AppError } from '../../../errors/app-error.js';\n\nexport function registerTaskImport(parent: Command, container: Container): void {\n parent\n .command('import')\n .description('Import tasks from JSON file')\n .requiredOption('-f, --file <file>', 'Input JSON file path')\n .option('-p, --project <project>', 'Target project id or name')\n .option(\n '--map <mapping>',\n 'Field mapping as comma-separated source:target pairs (e.g. \"title:name,summary:description\")',\n )\n .action((opts: { file: string; project?: string; map?: string }) => {\n let fileData: unknown;\n try {\n const raw = readFileSync(opts.file, 'utf-8');\n fileData = JSON.parse(raw);\n } catch (e) {\n return printError(\n new AppError(\n 'VALIDATION',\n `Failed to read or parse file: ${opts.file}${e instanceof Error ? ` - ${e.message}` : ''}`,\n ),\n );\n }\n\n const fieldMapping = opts.map ? parseFieldMapping(opts.map) : undefined;\n\n const result = container.portabilityService.importTasks(fileData, opts.project, fieldMapping);\n handleResult(result);\n });\n}\n","import { Command } from 'commander';\nimport type { Container } from '../../container.js';\nimport { handleResult } from '../../output.js';\n\nexport function registerDepAdd(parent: Command, container: Container): void {\n parent\n .command('add <taskId> <dependsOnId>')\n .description('Add a dependency (taskId depends on dependsOnId)')\n .option(\n '-t, --type <type>',\n 'Dependency type: blocks, relates-to, duplicates, blocked-by',\n 'blocks',\n )\n .action((taskId: string, dependsOnId: string, opts: { type?: string }) => {\n const result = container.dependencyService.addDependency({\n taskId,\n dependsOnId,\n type: opts.type,\n });\n handleResult(result);\n });\n}\n","import { Command } from 'commander';\nimport type { Container } from '../../container.js';\nimport { handleResult } from '../../output.js';\n\nexport function registerDepRemove(parent: Command, container: Container): void {\n parent\n .command('remove <taskId> <dependsOnId>')\n .description('Remove a dependency')\n .action((taskId: string, dependsOnId: string) => {\n const result = container.dependencyService.removeDependency({\n taskId,\n dependsOnId,\n });\n handleResult(result);\n });\n}\n","import { Command } from 'commander';\nimport type { Container } from '../../container.js';\nimport { handleResult } from '../../output.js';\n\nexport function registerDepList(parent: Command, container: Container): void {\n parent\n .command('list <taskId>')\n .description('List direct dependencies of a task')\n .option('--blockers', 'Show tasks that block this task')\n .option('--dependents', 'Show tasks that depend on this task')\n .option('--transitive', 'Show all transitive blockers (deep)')\n .action(\n (\n taskId: string,\n opts: { blockers?: boolean; dependents?: boolean; transitive?: boolean },\n ) => {\n if (opts.transitive) {\n handleResult(container.dependencyService.getTransitiveDeps(taskId));\n } else if (opts.dependents) {\n handleResult(container.dependencyService.listDependents(taskId));\n } else if (opts.blockers) {\n handleResult(container.dependencyService.listBlockers(taskId));\n } else {\n // Default: show all dependency edges\n handleResult(container.dependencyService.listAllDeps(taskId));\n }\n },\n );\n}\n","import { Command } from 'commander';\nimport type { Container } from '../../container.js';\nimport { handleResult } from '../../output.js';\n\nexport function registerDepGraph(parent: Command, container: Container): void {\n parent\n .command('graph <taskId>')\n .description('Build full dependency graph centered on a task (outputs Mermaid)')\n .action((taskId: string) => {\n const result = container.dependencyService.buildGraph(taskId);\n handleResult(result);\n });\n}\n","import { loadConfig } from './config/index.js';\nimport { createDatabase } from './db/connection.js';\nimport { runMigrations } from './db/migrator.js';\nimport { initTelemetry, shutdownTelemetry } from './logging/telemetry.js';\nimport { logger } from './logging/logger.js';\nimport { createContainer } from './cli/container.js';\nimport { buildCLI } from './cli/index.js';\nimport { AppError } from './errors/app-error.js';\n\nasync function main(): Promise<void> {\n const config = loadConfig();\n logger.init(config.logDir);\n initTelemetry(config);\n\n const db = createDatabase(config.dbPath);\n runMigrations(db);\n\n const container = createContainer(db);\n\n const args = process.argv.slice(2);\n if (args.length === 0) {\n // Default: launch TUI when no subcommand\n const { launchTUI } = await import('./tui/index.js');\n await launchTUI(container);\n } else {\n const program = buildCLI(container);\n await program.parseAsync(process.argv);\n }\n\n db.close();\n await shutdownTelemetry();\n}\n\nmain().catch((e: unknown) => {\n const error =\n e instanceof AppError\n ? e\n : new AppError('UNKNOWN', e instanceof Error ? e.message : 'Unknown error', e);\n\n process.stderr.write(\n JSON.stringify({ ok: false, error: { code: error.code, message: error.message } }, null, 2) +\n '\\n',\n );\n process.exit(1);\n});\n"],"mappings":"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","names":["join","join","z","z","z","z","z","readFileSync","readFileSync","readFileSync","readFileSync"]}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
-- Projects
|
|
2
|
+
CREATE TABLE IF NOT EXISTS projects (
|
|
3
|
+
id TEXT PRIMARY KEY,
|
|
4
|
+
key TEXT NOT NULL UNIQUE CHECK(LENGTH(key) BETWEEN 2 AND 7 AND key = UPPER(key) AND key NOT GLOB '*[^A-Z0-9]*'),
|
|
5
|
+
name TEXT NOT NULL UNIQUE,
|
|
6
|
+
description TEXT NOT NULL DEFAULT '',
|
|
7
|
+
is_default INTEGER NOT NULL DEFAULT 0,
|
|
8
|
+
task_counter INTEGER NOT NULL DEFAULT 0,
|
|
9
|
+
created_at TEXT NOT NULL,
|
|
10
|
+
updated_at TEXT NOT NULL
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
-- Tasks
|
|
14
|
+
CREATE TABLE IF NOT EXISTS tasks (
|
|
15
|
+
id TEXT PRIMARY KEY,
|
|
16
|
+
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
17
|
+
parent_id TEXT REFERENCES tasks(id) ON DELETE SET NULL,
|
|
18
|
+
name TEXT NOT NULL,
|
|
19
|
+
description TEXT NOT NULL DEFAULT '',
|
|
20
|
+
type TEXT NOT NULL CHECK(type IN ('story','tech-debt','bug')),
|
|
21
|
+
status TEXT NOT NULL CHECK(status IN ('backlog','todo','in-progress','review','done','cancelled')),
|
|
22
|
+
rank REAL NOT NULL DEFAULT 0,
|
|
23
|
+
technical_notes TEXT NOT NULL DEFAULT '',
|
|
24
|
+
additional_requirements TEXT NOT NULL DEFAULT '',
|
|
25
|
+
created_at TEXT NOT NULL,
|
|
26
|
+
updated_at TEXT NOT NULL
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_project_id ON tasks(project_id);
|
|
30
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_parent_id ON tasks(parent_id);
|
|
31
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status);
|
|
32
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_type ON tasks(type);
|
|
33
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_rank ON tasks(rank);
|
|
34
|
+
|
|
35
|
+
-- Seed default project
|
|
36
|
+
INSERT INTO projects (id, key, name, description, is_default, task_counter, created_at, updated_at)
|
|
37
|
+
VALUES ('default', 'DEFAULT', 'default', 'Default project', 1, 0, datetime('now'), datetime('now'));
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
-- Task dependencies (DAG edges)
|
|
2
|
+
CREATE TABLE IF NOT EXISTS task_dependencies (
|
|
3
|
+
task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
4
|
+
depends_on_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
5
|
+
type TEXT NOT NULL DEFAULT 'blocks' CHECK(type IN ('blocks','relates-to','duplicates')),
|
|
6
|
+
created_at TEXT NOT NULL,
|
|
7
|
+
PRIMARY KEY (task_id, depends_on_id),
|
|
8
|
+
CHECK (task_id != depends_on_id)
|
|
9
|
+
);
|
|
10
|
+
|
|
11
|
+
CREATE INDEX IF NOT EXISTS idx_deps_depends_on ON task_dependencies(depends_on_id);
|
|
12
|
+
CREATE INDEX IF NOT EXISTS idx_deps_type ON task_dependencies(type);
|
|
13
|
+
|
|
14
|
+
-- Full-text search index on tasks
|
|
15
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS tasks_fts USING fts5(
|
|
16
|
+
id UNINDEXED,
|
|
17
|
+
name,
|
|
18
|
+
description,
|
|
19
|
+
technical_notes,
|
|
20
|
+
additional_requirements,
|
|
21
|
+
content='tasks',
|
|
22
|
+
content_rowid='rowid'
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
-- Populate FTS from existing tasks
|
|
26
|
+
INSERT INTO tasks_fts(rowid, id, name, description, technical_notes, additional_requirements)
|
|
27
|
+
SELECT rowid, id, name, description, technical_notes, additional_requirements FROM tasks;
|
|
28
|
+
|
|
29
|
+
-- Keep FTS in sync: INSERT
|
|
30
|
+
CREATE TRIGGER IF NOT EXISTS tasks_fts_ai AFTER INSERT ON tasks BEGIN
|
|
31
|
+
INSERT INTO tasks_fts(rowid, id, name, description, technical_notes, additional_requirements)
|
|
32
|
+
VALUES (NEW.rowid, NEW.id, NEW.name, NEW.description, NEW.technical_notes, NEW.additional_requirements);
|
|
33
|
+
END;
|
|
34
|
+
|
|
35
|
+
-- Keep FTS in sync: DELETE
|
|
36
|
+
CREATE TRIGGER IF NOT EXISTS tasks_fts_ad AFTER DELETE ON tasks BEGIN
|
|
37
|
+
INSERT INTO tasks_fts(tasks_fts, rowid, id, name, description, technical_notes, additional_requirements)
|
|
38
|
+
VALUES ('delete', OLD.rowid, OLD.id, OLD.name, OLD.description, OLD.technical_notes, OLD.additional_requirements);
|
|
39
|
+
END;
|
|
40
|
+
|
|
41
|
+
-- Keep FTS in sync: UPDATE
|
|
42
|
+
CREATE TRIGGER IF NOT EXISTS tasks_fts_au AFTER UPDATE ON tasks BEGIN
|
|
43
|
+
INSERT INTO tasks_fts(tasks_fts, rowid, id, name, description, technical_notes, additional_requirements)
|
|
44
|
+
VALUES ('delete', OLD.rowid, OLD.id, OLD.name, OLD.description, OLD.technical_notes, OLD.additional_requirements);
|
|
45
|
+
INSERT INTO tasks_fts(rowid, id, name, description, technical_notes, additional_requirements)
|
|
46
|
+
VALUES (NEW.rowid, NEW.id, NEW.name, NEW.description, NEW.technical_notes, NEW.additional_requirements);
|
|
47
|
+
END;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
-- Add soft-delete column to projects
|
|
2
|
+
ALTER TABLE projects ADD COLUMN deleted_at TEXT DEFAULT NULL;
|
|
3
|
+
|
|
4
|
+
-- Add soft-delete column to tasks
|
|
5
|
+
ALTER TABLE tasks ADD COLUMN deleted_at TEXT DEFAULT NULL;
|
|
6
|
+
|
|
7
|
+
-- Index for efficient filtering of non-deleted rows
|
|
8
|
+
CREATE INDEX IF NOT EXISTS idx_projects_deleted_at ON projects(deleted_at);
|
|
9
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_deleted_at ON tasks(deleted_at);
|
|
10
|
+
|
|
11
|
+
-- Replace FTS triggers to exclude soft-deleted tasks.
|
|
12
|
+
-- DROP + re-CREATE because SQLite does not support CREATE OR REPLACE TRIGGER.
|
|
13
|
+
|
|
14
|
+
DROP TRIGGER IF EXISTS tasks_fts_ai;
|
|
15
|
+
DROP TRIGGER IF EXISTS tasks_fts_ad;
|
|
16
|
+
DROP TRIGGER IF EXISTS tasks_fts_au;
|
|
17
|
+
|
|
18
|
+
-- INSERT: only index if not soft-deleted
|
|
19
|
+
CREATE TRIGGER tasks_fts_ai AFTER INSERT ON tasks
|
|
20
|
+
WHEN NEW.deleted_at IS NULL
|
|
21
|
+
BEGIN
|
|
22
|
+
INSERT INTO tasks_fts(rowid, id, name, description, technical_notes, additional_requirements)
|
|
23
|
+
VALUES (NEW.rowid, NEW.id, NEW.name, NEW.description, NEW.technical_notes, NEW.additional_requirements);
|
|
24
|
+
END;
|
|
25
|
+
|
|
26
|
+
-- DELETE: remove from FTS (hard deletes still possible via cascade)
|
|
27
|
+
CREATE TRIGGER tasks_fts_ad AFTER DELETE ON tasks BEGIN
|
|
28
|
+
INSERT INTO tasks_fts(tasks_fts, rowid, id, name, description, technical_notes, additional_requirements)
|
|
29
|
+
VALUES ('delete', OLD.rowid, OLD.id, OLD.name, OLD.description, OLD.technical_notes, OLD.additional_requirements);
|
|
30
|
+
END;
|
|
31
|
+
|
|
32
|
+
-- UPDATE: re-index. If deleted_at was just set, remove from FTS. If cleared, add back.
|
|
33
|
+
CREATE TRIGGER tasks_fts_au AFTER UPDATE ON tasks BEGIN
|
|
34
|
+
INSERT INTO tasks_fts(tasks_fts, rowid, id, name, description, technical_notes, additional_requirements)
|
|
35
|
+
VALUES ('delete', OLD.rowid, OLD.id, OLD.name, OLD.description, OLD.technical_notes, OLD.additional_requirements);
|
|
36
|
+
INSERT INTO tasks_fts(rowid, id, name, description, technical_notes, additional_requirements)
|
|
37
|
+
SELECT NEW.rowid, NEW.id, NEW.name, NEW.description, NEW.technical_notes, NEW.additional_requirements
|
|
38
|
+
WHERE NEW.deleted_at IS NULL;
|
|
39
|
+
END;
|