zam-core 0.3.6 → 0.3.11

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/index.ts","../../src/cli/commands/bridge.ts","../../src/kernel/analytics/stats.ts","../../src/kernel/credentials.ts","../../src/kernel/connectors/azure-devops.ts","../../src/kernel/db/connection.ts","../../src/kernel/db/schema.ts","../../src/kernel/goals/engine.ts","../../src/kernel/goals/parser.ts","../../src/kernel/models/agent-skill.ts","../../src/kernel/models/card.ts","../../src/kernel/models/prerequisite.ts","../../src/kernel/models/review.ts","../../src/kernel/models/session.ts","../../src/kernel/models/settings.ts","../../src/kernel/models/token.ts","../../src/kernel/observation/analyzer.ts","../../src/kernel/observation/monitor-io.ts","../../src/kernel/observation/shell-hooks.ts","../../src/kernel/observation/skill-discovery.ts","../../src/kernel/scheduler/blocker.ts","../../src/kernel/recall/evaluator.ts","../../src/kernel/scheduler/fsrs.ts","../../src/kernel/recall/actions.ts","../../src/kernel/recall/prompter.ts","../../src/kernel/recall/reference-resolver.ts","../../src/kernel/scheduler/interleaver.ts","../../src/kernel/scheduler/queue.ts","../../src/kernel/system/hooks.ts","../../src/kernel/system/i18n.ts","../../src/kernel/system/installer.ts","../../src/kernel/system/locale.ts","../../src/kernel/system/profiler.ts","../../src/kernel/system/repos.ts","../../src/cli/llm/client.ts","../../src/cli/commands/resolve-user.ts","../../src/cli/commands/card.ts","../../src/cli/commands/connector.ts","../../src/cli/commands/git-sync.ts","../../src/cli/commands/goal.ts","../../src/cli/commands/init.ts","../../src/cli/commands/learn.ts","../../src/cli/learn-format.ts","../../src/cli/review-actions.ts","../../src/cli/commands/monitor.ts","../../src/cli/commands/review.ts","../../src/cli/commands/session.ts","../../src/cli/commands/settings.ts","../../src/cli/commands/setup.ts","../../src/cli/commands/skill.ts","../../src/cli/commands/stats.ts","../../src/cli/commands/token.ts","../../src/cli/commands/ui.ts","../../src/cli/commands/whoami.ts","../../src/cli/commands/workspace.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { bridgeCommand } from \"./commands/bridge.js\";\nimport { cardCommand } from \"./commands/card.js\";\nimport { connectorCommand } from \"./commands/connector.js\";\nimport { gitSyncCommand } from \"./commands/git-sync.js\";\nimport { goalCommand } from \"./commands/goal.js\";\nimport { initCommand } from \"./commands/init.js\";\nimport { learnCommand } from \"./commands/learn.js\";\nimport { monitorCommand } from \"./commands/monitor.js\";\nimport { reviewCommand } from \"./commands/review.js\";\nimport { sessionCommand } from \"./commands/session.js\";\nimport { settingsCommand } from \"./commands/settings.js\";\nimport { setupCommand } from \"./commands/setup.js\";\nimport { skillCommand } from \"./commands/skill.js\";\nimport { statsCommand } from \"./commands/stats.js\";\nimport { tokenCommand } from \"./commands/token.js\";\nimport { uiCommand } from \"./commands/ui.js\";\nimport { whoamiCommand } from \"./commands/whoami.js\";\nimport { workspaceCommand } from \"./commands/workspace.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"zam\")\n .description(\n \"The Symbiotic Learning Kernel: Elevating Human Intelligence through AI Collaboration.\",\n )\n .version(\"0.3.5\");\n\nprogram.addCommand(initCommand);\nprogram.addCommand(setupCommand);\nprogram.addCommand(tokenCommand);\nprogram.addCommand(cardCommand);\nprogram.addCommand(sessionCommand);\nprogram.addCommand(statsCommand);\nprogram.addCommand(reviewCommand);\nprogram.addCommand(learnCommand);\nprogram.addCommand(uiCommand);\nprogram.addCommand(bridgeCommand);\nprogram.addCommand(skillCommand);\nprogram.addCommand(monitorCommand);\nprogram.addCommand(settingsCommand);\nprogram.addCommand(whoamiCommand);\nprogram.addCommand(connectorCommand);\nprogram.addCommand(goalCommand);\nprogram.addCommand(gitSyncCommand);\nprogram.addCommand(workspaceCommand);\n\nprogram.parse();\n","/**\n * `zam bridge` — Machine-readable JSON protocol for AI integration.\n *\n * All output is valid JSON only. No human-readable formatting.\n * Errors are also JSON: { \"error\": \"message\" }\n */\n\nimport { readdirSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { Command } from \"commander\";\nimport type { Database } from \"libsql\";\nimport type {\n BloomLevel,\n Rating,\n ReviewActionType,\n SymbiosisMode,\n TokenPattern,\n} from \"../../kernel/index.js\";\nimport {\n analyzeObservation,\n buildReviewQueue,\n createToken,\n discoverSkills,\n ensureCard,\n executeReviewAction,\n generatePrompt,\n getAgentSkill,\n getCardDeletionImpact,\n getDueCards,\n getSetting,\n getTokenDeleteImpact,\n listAgentSkills,\n monitorLogExists,\n openDatabase,\n pairCommands,\n readMonitorLog,\n resolveReviewContext,\n} from \"../../kernel/index.js\";\nimport {\n ensureHighQualityQuestion,\n ensureLlmReadyHeadless,\n evaluateAnswerViaLLM,\n getAvailableModels,\n getLlmConfig,\n isLlmOnline,\n translateQuestionViaLLM,\n} from \"../llm/client.js\";\nimport { resolveUser } from \"./resolve-user.js\";\n\nfunction jsonOut(data: unknown): void {\n console.log(JSON.stringify(data, null, 2));\n}\n\nfunction jsonError(message: string): never {\n console.log(JSON.stringify({ error: message }, null, 2));\n process.exit(1);\n}\n\nfunction withDb(fn: (db: Database) => void): void {\n let db: Database | undefined;\n try {\n db = openDatabase();\n fn(db);\n } catch (err) {\n db?.close();\n jsonError((err as Error).message);\n } finally {\n db?.close();\n }\n}\n\nasync function withDbAsync(fn: (db: Database) => Promise<void>): Promise<void> {\n let db: Database | undefined;\n try {\n db = openDatabase();\n await fn(db);\n } catch (err) {\n db?.close();\n jsonError((err as Error).message);\n } finally {\n db?.close();\n }\n}\n\ninterface ReviewTargetRow {\n card_id: string;\n token_id: string;\n user_id: string;\n slug: string;\n}\n\nfunction getReviewTarget(\n db: Database,\n cardId: string,\n userId: string,\n): ReviewTargetRow {\n const target = db\n .prepare(\n `SELECT c.id AS card_id, c.token_id, c.user_id, t.slug\n FROM cards c\n JOIN tokens t ON t.id = c.token_id\n WHERE c.id = ?`,\n )\n .get(cardId) as ReviewTargetRow | undefined;\n\n if (!target) {\n jsonError(`Card not found: ${cardId}`);\n }\n if (target.user_id !== userId) {\n jsonError(`Card ${cardId} does not belong to user ${userId}`);\n }\n\n return target!;\n}\n\nfunction parseTokenUpdates(opts: {\n concept?: string;\n domain?: string;\n bloom?: string;\n context?: string;\n mode?: string;\n sourceLink?: string;\n}): {\n concept?: string;\n domain?: string;\n bloom_level?: BloomLevel;\n context?: string;\n symbiosis_mode?: SymbiosisMode | null;\n source_link?: string | null;\n} {\n const updates: {\n concept?: string;\n domain?: string;\n bloom_level?: BloomLevel;\n context?: string;\n symbiosis_mode?: SymbiosisMode | null;\n source_link?: string | null;\n } = {};\n\n if (opts.concept !== undefined) updates.concept = opts.concept;\n if (opts.domain !== undefined) updates.domain = opts.domain;\n if (opts.bloom !== undefined)\n updates.bloom_level = Number(opts.bloom) as BloomLevel;\n if (opts.context !== undefined) updates.context = opts.context;\n if (opts.sourceLink !== undefined) {\n updates.source_link = opts.sourceLink === \"\" ? null : opts.sourceLink;\n }\n if (opts.mode !== undefined) {\n const validModes = [\"shadowing\", \"copilot\", \"autonomy\", \"none\"];\n if (!validModes.includes(opts.mode)) {\n jsonError(`Invalid mode: ${opts.mode}`);\n }\n updates.symbiosis_mode =\n opts.mode === \"none\" ? null : (opts.mode as SymbiosisMode);\n }\n\n return updates;\n}\n\nexport const bridgeCommand = new Command(\"bridge\").description(\n \"Machine-readable JSON protocol for AI integration\",\n);\n\n// ── zam bridge check-due ──────────────────────────────────────────────────\n\nbridgeCommand\n .command(\"check-due\")\n .description(\"Check due cards for a user (JSON)\")\n .option(\"--user <id>\", \"User ID (default: whoami)\")\n .action((opts) => {\n withDb((db) => {\n const userId = resolveUser(opts, db, { json: true });\n const dueCards = getDueCards(db, userId);\n const domains = [\n ...new Set(dueCards.map((c) => c.domain).filter(Boolean)),\n ].sort();\n\n jsonOut({\n userId,\n dueCount: dueCards.length,\n domains,\n cards: dueCards.map((c) => ({\n cardId: c.id,\n tokenId: c.token_id,\n slug: c.slug,\n concept: c.concept,\n domain: c.domain,\n bloomLevel: c.bloom_level,\n state: c.state,\n dueAt: c.due_at,\n })),\n });\n });\n });\n\n// ── zam bridge get-review ─────────────────────────────────────────────────\n\nbridgeCommand\n .command(\"get-review\")\n .description(\"Get next review card with prompt (JSON)\")\n .option(\"--user <id>\", \"User ID (default: whoami)\")\n .option(\"--no-resolve\", \"Skip resolving the token's source_link into context\")\n .action(async (opts) => {\n await withDbAsync(async (db) => {\n const userId = resolveUser(opts, db, { json: true });\n const queue = buildReviewQueue(db, { userId, maxReviews: 1, maxNew: 1 });\n\n if (queue.items.length === 0) {\n jsonOut({\n userId,\n hasReview: false,\n card: null,\n prompt: null,\n resolvedContext: null,\n queueSize: 0,\n });\n return;\n }\n\n const item = queue.items[0];\n const isLlmEnabled = getSetting(db, \"llm.enabled\") === \"true\";\n\n // Dynamically generate a fresh, living active-recall question if LLM is enabled\n let resolvedQuestion = item.question;\n if (isLlmEnabled) {\n try {\n const healed = await ensureHighQualityQuestion(db, {\n id: item.tokenId,\n slug: item.slug,\n concept: item.concept,\n domain: item.domain,\n bloomLevel: item.bloomLevel as BloomLevel,\n sourceLink: item.sourceLink,\n question: item.question,\n });\n if (healed) {\n resolvedQuestion = healed;\n }\n } catch {\n // ignore and proceed\n }\n }\n\n const prompt = generatePrompt({\n cardId: item.cardId,\n tokenId: item.tokenId,\n slug: item.slug,\n concept: item.concept,\n domain: item.domain,\n bloomLevel: item.bloomLevel as BloomLevel,\n sourceLink: item.sourceLink,\n question: resolvedQuestion,\n });\n\n // Resolve the source_link into ready-to-use context for the AI client.\n // Defensive: never let a bad/unreachable reference break the review payload.\n let resolvedContext = null;\n if (opts.resolve !== false) {\n try {\n resolvedContext = await resolveReviewContext(item.sourceLink);\n } catch {\n resolvedContext = null;\n }\n }\n\n // Get full queue size for context\n const fullQueue = buildReviewQueue(db, { userId });\n\n jsonOut({\n userId,\n hasReview: true,\n card: item,\n prompt,\n resolvedContext,\n queueSize: fullQueue.items.length,\n });\n });\n });\n\n// ── zam bridge submit ─────────────────────────────────────────────────────\n\nbridgeCommand\n .command(\"submit\")\n .description(\"Submit a rating for a card (JSON)\")\n .option(\"--user <id>\", \"User ID (default: whoami)\")\n .requiredOption(\"--card-id <id>\", \"Card ID\")\n .requiredOption(\"--rating <n>\", \"Rating (1-4)\")\n .action((opts) => {\n withDb((db) => {\n const userId = resolveUser(opts, db, { json: true });\n const rating = Number(opts.rating) as Rating;\n if (rating < 1 || rating > 4) {\n jsonError(\"Rating must be between 1 and 4\");\n }\n\n const result = executeReviewAction(db, {\n action: \"rate\",\n cardId: opts.cardId,\n userId,\n rating,\n });\n\n jsonOut({\n success: true,\n rating,\n evaluation: result.evaluation,\n blocked: result.blocked ?? null,\n });\n });\n });\n\n// ── zam bridge review-action ───────────────────────────────────────────────\n\nbridgeCommand\n .command(\"review-action\")\n .description(\"Apply a review action (JSON)\")\n .option(\"--user <id>\", \"User ID (default: whoami)\")\n .requiredOption(\"--card-id <id>\", \"Card ID\")\n .requiredOption(\n \"--action <action>\",\n \"Action: rate | skip | edit-token | deprecate-token | delete-token | delete-card | stop\",\n )\n .option(\"--rating <n>\", \"Rating (1-4) for action=rate\")\n .option(\"--concept <concept>\", \"Updated concept text for action=edit-token\")\n .option(\"--domain <domain>\", \"Updated domain for action=edit-token\")\n .option(\"--bloom <level>\", \"Updated Bloom level for action=edit-token\")\n .option(\"--context <context>\", \"Updated context for action=edit-token\")\n .option(\"--mode <mode>\", \"Updated symbiosis mode for action=edit-token\")\n .option(\"--source-link <link>\", \"Updated source link for action=edit-token\")\n .option(\"--confirm\", \"Confirm destructive delete actions\")\n .action((opts) => {\n withDb((db) => {\n const userId = resolveUser(opts, db, { json: true });\n const action = opts.action as ReviewActionType;\n const validActions: ReviewActionType[] = [\n \"rate\",\n \"skip\",\n \"edit-token\",\n \"deprecate-token\",\n \"delete-token\",\n \"delete-card\",\n \"stop\",\n ];\n if (!validActions.includes(action)) {\n jsonError(`Unsupported action: ${opts.action}`);\n }\n\n const target = getReviewTarget(db, opts.cardId, userId);\n if (\n (action === \"delete-token\" || action === \"delete-card\") &&\n !opts.confirm\n ) {\n if (action === \"delete-token\") {\n jsonOut({\n success: true,\n action,\n preview: true,\n requiresConfirmation: true,\n token: { slug: target.slug, tokenId: target.token_id },\n impact: getTokenDeleteImpact(db, target.slug),\n });\n return;\n }\n\n jsonOut({\n success: true,\n action,\n preview: true,\n requiresConfirmation: true,\n token: { slug: target.slug, tokenId: target.token_id },\n impact: getCardDeletionImpact(db, target.token_id, userId),\n });\n return;\n }\n\n const rating =\n opts.rating !== undefined ? (Number(opts.rating) as Rating) : undefined;\n if (action === \"rate\" && (rating == null || rating < 1 || rating > 4)) {\n jsonError(\"Rating must be between 1 and 4 for action=rate\");\n }\n\n const result = executeReviewAction(db, {\n action,\n cardId: opts.cardId,\n userId,\n rating,\n tokenUpdates:\n action === \"edit-token\" ? parseTokenUpdates(opts) : undefined,\n });\n\n jsonOut({\n success: true,\n action,\n token: {\n slug: result.token.slug,\n tokenId: result.token.id,\n },\n rating: rating ?? null,\n evaluation: result.evaluation ?? null,\n blocked: result.blocked ?? null,\n updatedToken: result.updatedToken ?? null,\n deletedToken: result.deletedToken ?? null,\n deletedCard: result.deletedCard ?? null,\n skipped: result.skipped ?? false,\n stopped: result.stopped ?? false,\n });\n });\n });\n\n// ── zam bridge get-skill ──────────────────────────────────────────────────\n\nbridgeCommand\n .command(\"get-skill\")\n .description(\"Get an agent skill by slug (JSON)\")\n .requiredOption(\"--slug <slug>\", \"Skill slug\")\n .action((opts) => {\n withDb((db) => {\n const skill = getAgentSkill(db, opts.slug);\n if (!skill) {\n jsonError(`Skill not found: ${opts.slug}`);\n }\n\n jsonOut({\n slug: skill?.slug,\n description: skill?.description,\n steps: skill?.steps,\n tokenSlugs: skill?.token_slugs,\n source: skill?.source,\n });\n });\n });\n\n// ── zam bridge get-monitor ────────────────────────────────────────────────\n\nbridgeCommand\n .command(\"get-monitor\")\n .description(\"Read monitor log for a session (JSON)\")\n .requiredOption(\"--session <id>\", \"Session ID\")\n .action((opts) => {\n if (!monitorLogExists(opts.session)) {\n jsonOut({\n sessionId: opts.session,\n exists: false,\n commands: [],\n timeSpan: null,\n });\n return;\n }\n\n const events = readMonitorLog(opts.session);\n const commands = pairCommands(events);\n\n let timeSpan: { start: string; end: string; durationMs: number } | null =\n null;\n if (commands.length > 0) {\n const first = commands[0];\n const last = commands[commands.length - 1];\n const endTs = last.endedAt ?? last.startedAt;\n timeSpan = {\n start: first.startedAt,\n end: endTs,\n durationMs:\n new Date(endTs).getTime() - new Date(first.startedAt).getTime(),\n };\n }\n\n jsonOut({\n sessionId: opts.session,\n exists: true,\n commands: commands.map((c) => ({\n seq: c.seq,\n command: c.command,\n cwd: c.cwd,\n startedAt: c.startedAt,\n endedAt: c.endedAt,\n durationMs: c.durationMs,\n exitCode: c.exitCode,\n })),\n timeSpan,\n });\n });\n\n// ── zam bridge analyze-monitor ───────────────────────────────────────────\n\nbridgeCommand\n .command(\"analyze-monitor\")\n .description(\"Analyze monitor log with token patterns from stdin (JSON)\")\n .requiredOption(\"--session <id>\", \"Session ID\")\n .action(async (opts) => {\n try {\n if (!monitorLogExists(opts.session)) {\n jsonOut({\n sessionId: opts.session,\n ratings: [],\n unmatchedCommands: [],\n timeSpan: null,\n });\n return;\n }\n\n // Read token patterns from stdin\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(chunk as Buffer);\n }\n const raw = Buffer.concat(chunks).toString(\"utf-8\").trim();\n\n if (!raw) {\n jsonError(\"No input received on stdin. Pipe JSON with token patterns.\");\n }\n\n let data: { patterns: TokenPattern[] };\n try {\n data = JSON.parse(raw);\n } catch {\n jsonError(\"Invalid JSON input\");\n }\n\n if (!Array.isArray(data?.patterns)) {\n jsonError(\"JSON must include 'patterns' array\");\n }\n\n const events = readMonitorLog(opts.session);\n const commands = pairCommands(events);\n const result = analyzeObservation(commands, data?.patterns);\n\n jsonOut({\n sessionId: opts.session,\n ...result,\n });\n } catch (err) {\n jsonError((err as Error).message);\n }\n });\n\n// ── zam bridge add-token ──────────────────────────────────────────────────\n\nbridgeCommand\n .command(\"add-token\")\n .description(\"Create a token + card from JSON stdin\")\n .option(\"--user <id>\", \"User ID (default: whoami)\")\n .action(async (opts) => {\n let db: Database | undefined;\n try {\n // Read JSON from stdin\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(chunk as Buffer);\n }\n const raw = Buffer.concat(chunks).toString(\"utf-8\").trim();\n\n if (!raw) {\n jsonError(\"No input received on stdin. Pipe JSON with token data.\");\n }\n\n let data: {\n slug: string;\n concept: string;\n domain?: string;\n bloom_level?: number;\n context?: string;\n symbiosis_mode?: string | null;\n source_link?: string | null;\n };\n\n try {\n data = JSON.parse(raw);\n } catch {\n jsonError(\"Invalid JSON input\");\n }\n\n if (!data?.slug || !data?.concept) {\n jsonError(\"JSON must include 'slug' and 'concept' fields\");\n }\n\n db = openDatabase();\n const userId = resolveUser(opts, db, { json: true });\n\n const token = createToken(db, {\n slug: data?.slug,\n concept: data?.concept,\n domain: data?.domain,\n bloom_level: (data?.bloom_level ?? 1) as BloomLevel,\n context: data?.context,\n symbiosis_mode: data?.symbiosis_mode as\n | \"shadowing\"\n | \"copilot\"\n | \"autonomy\"\n | null\n | undefined,\n source_link: data?.source_link ?? null,\n });\n\n const card = ensureCard(db, token.id, userId);\n\n jsonOut({\n success: true,\n token,\n card: {\n id: card.id,\n tokenId: card.token_id,\n userId: card.user_id,\n state: card.state,\n dueAt: card.due_at,\n blocked: card.blocked,\n },\n });\n\n db.close();\n } catch (err) {\n db?.close();\n // If it's already a JSON error exit, let it propagate\n if ((err as Error).message) {\n jsonError((err as Error).message);\n }\n }\n });\n\n// ── zam bridge discover-skills ──────────────────────────────────────────────\n\nbridgeCommand\n .command(\"discover-skills\")\n .description(\n \"Analyze monitor logs across sessions to discover recurring patterns\",\n )\n .option(\n \"--min-sessions <n>\",\n \"Minimum sessions a pattern must appear in (default: 2)\",\n \"2\",\n )\n .option(\n \"--limit <n>\",\n \"Max number of sessions to analyze (default: 20)\",\n \"20\",\n )\n .action((opts) => {\n try {\n const monitorDir = join(homedir(), \".zam\", \"monitor\");\n let files: string[];\n try {\n files = readdirSync(monitorDir).filter((f) => f.endsWith(\".jsonl\"));\n } catch {\n jsonOut({ proposals: [], message: \"No monitor logs found.\" });\n return;\n }\n\n if (files.length === 0) {\n jsonOut({ proposals: [], message: \"No monitor logs found.\" });\n return;\n }\n\n // Take the most recent N sessions by file modification time\n const limit = Number(opts.limit);\n const sorted = files\n .map((f) => ({ name: f, path: join(monitorDir, f) }))\n .sort((a, b) => b.name.localeCompare(a.name)) // ULID session IDs sort chronologically\n .slice(0, limit);\n\n // Load and parse each session's commands\n const sessionCommands = new Map<\n string,\n ReturnType<typeof pairCommands>\n >();\n for (const file of sorted) {\n const sessionId = file.name.replace(\".jsonl\", \"\");\n const events = readMonitorLog(sessionId);\n const commands = pairCommands(events);\n if (commands.length > 0) {\n sessionCommands.set(sessionId, commands);\n }\n }\n\n if (sessionCommands.size === 0) {\n jsonOut({ proposals: [], message: \"No command data in monitor logs.\" });\n return;\n }\n\n // Get existing skills to exclude\n let existingSkillSlugs: string[] = [];\n let db: Database | undefined;\n try {\n db = openDatabase();\n existingSkillSlugs = listAgentSkills(db).map((s) => s.slug);\n } catch {\n // DB not available — proceed without exclusion\n } finally {\n db?.close();\n }\n\n const proposals = discoverSkills(sessionCommands, {\n minSessions: Number(opts.minSessions),\n existingSkillSlugs,\n });\n\n jsonOut({\n sessionsAnalyzed: sessionCommands.size,\n proposals,\n });\n } catch (err) {\n jsonError((err as Error).message);\n }\n });\n\n// ── zam bridge check-llm ──────────────────────────────────────────────────\n\nbridgeCommand\n .command(\"check-llm\")\n .description(\"Check if LLM is enabled and online (JSON)\")\n .action(async () => {\n await withDbAsync(async (db) => {\n const { enabled, url, model, apiKey } = getLlmConfig(db);\n let online = false;\n let availableModels: string[] = [];\n let modelAvailable = false;\n if (enabled) {\n online = await isLlmOnline(url);\n if (online) {\n availableModels = await getAvailableModels(url, apiKey);\n // Empty list = server doesn't expose /models; don't claim it's wrong.\n modelAvailable =\n availableModels.length === 0 ||\n availableModels.some(\n (m) => m.toLowerCase() === model.toLowerCase(),\n );\n }\n }\n jsonOut({\n enabled,\n online,\n url,\n model,\n modelAvailable,\n availableModels,\n });\n });\n });\n\n// ── zam bridge ensure-llm ─────────────────────────────────────────────────\n\nbridgeCommand\n .command(\"ensure-llm\")\n .description(\n \"Start the local LLM server if needed and report readiness (JSON)\",\n )\n .option(\n \"--timeout <ms>\",\n \"Max time to wait for the server to come online\",\n \"25000\",\n )\n .action(async (opts) => {\n await withDbAsync(async (db) => {\n const result = await ensureLlmReadyHeadless(db, {\n timeoutMs: Number(opts.timeout),\n });\n jsonOut(result);\n });\n });\n\n// ── zam bridge translate-question ──────────────────────────────────────────\n\nbridgeCommand\n .command(\"translate-question\")\n .description(\"Translate a question dynamically using the local LLM (JSON)\")\n .requiredOption(\"--question <text>\", \"Question in English to translate\")\n .action(async (opts) => {\n await withDbAsync(async (db) => {\n const isEnabled = getSetting(db, \"llm.enabled\") === \"true\";\n if (!isEnabled) {\n jsonOut({\n success: false,\n error: \"LLM integration is disabled\",\n translation: opts.question,\n });\n return;\n }\n try {\n const translation = await translateQuestionViaLLM(db, opts.question);\n jsonOut({ success: true, translation });\n } catch (err) {\n jsonOut({\n success: false,\n error: (err as Error).message,\n translation: opts.question,\n });\n }\n });\n });\n\n// ── zam bridge evaluate-answer ────────────────────────────────────────────\n\nbridgeCommand\n .command(\"evaluate-answer\")\n .description(\n \"Evaluate the learner's active-recall answer using the local LLM (JSON)\",\n )\n .requiredOption(\"--slug <slug>\", \"Token slug\")\n .requiredOption(\"--concept <concept>\", \"Target concept text\")\n .requiredOption(\"--domain <domain>\", \"Token domain\")\n .requiredOption(\"--bloom-level <level>\", \"Bloom taxonomy level\")\n .requiredOption(\"--question <question>\", \"Question prompt presented\")\n .requiredOption(\"--user-answer <answer>\", \"User's typed answer\")\n .option(\"--context <context>\", \"Optional token context details\")\n .option(\"--source-link <link>\", \"Optional source link\")\n .action(async (opts) => {\n await withDbAsync(async (db) => {\n const isEnabled = getSetting(db, \"llm.enabled\") === \"true\";\n if (!isEnabled) {\n jsonOut({\n success: false,\n error: \"LLM integration is disabled\",\n evaluation: \"\",\n });\n return;\n }\n\n let resolvedContextContent = null;\n if (opts.sourceLink) {\n try {\n const resolved = await resolveReviewContext(opts.sourceLink);\n resolvedContextContent = resolved?.content ?? null;\n } catch {\n // ignore context resolution errors\n }\n }\n\n try {\n const evaluation = await evaluateAnswerViaLLM(db, {\n slug: opts.slug,\n concept: opts.concept,\n domain: opts.domain,\n bloomLevel: Number(opts.bloomLevel),\n context: opts.context,\n question: opts.question,\n userAnswer: opts.userAnswer,\n sourceLinkContent: resolvedContextContent,\n });\n jsonOut({ success: true, evaluation });\n } catch (err) {\n jsonOut({\n success: false,\n error: (err as Error).message,\n evaluation: \"\",\n });\n }\n });\n });\n\n// ── zam bridge get-settings ───────────────────────────────────────────────\n\nbridgeCommand\n .command(\"get-settings\")\n .description(\"Get active ZAM settings (JSON)\")\n .action(() => {\n withDb((db) => {\n const { enabled, url, model, locale } = getLlmConfig(db);\n jsonOut({\n locale,\n llm: {\n enabled,\n url,\n model,\n },\n });\n });\n });\n","/**\n * Learning Analytics\n *\n * Progress statistics, competence tracking, and session summaries.\n * Ported from PoC's `stats` command with additions for FSRS and symbiosis modes.\n */\n\nimport type { Database } from \"libsql\";\n\nexport interface UserStats {\n userId: string;\n totalTokens: number;\n cardsInDeck: number;\n dueToday: number;\n blocked: number;\n mature: number;\n avgStability: number | null;\n totalSessions: number;\n lastSession: string | null;\n}\n\nexport interface DomainCompetence {\n domain: string;\n totalCards: number;\n matureCards: number;\n avgStability: number;\n retentionRate: number;\n suggestedMode: \"shadowing\" | \"copilot\" | \"autonomy\";\n}\n\nfunction q(db: Database, sql: string, ...params: unknown[]) {\n return db.prepare(sql).get(...params) as Record<string, unknown>;\n}\n\n/**\n * Get overall learning stats for a user (ported from PoC's `stats` command).\n */\nexport function getUserStats(db: Database, userId: string): UserStats {\n return {\n userId,\n totalTokens: (q(db, \"SELECT COUNT(*) as n FROM tokens\") as { n: number }).n,\n cardsInDeck: (\n q(db, \"SELECT COUNT(*) as n FROM cards WHERE user_id = ?\", userId) as {\n n: number;\n }\n ).n,\n dueToday: (\n q(\n db,\n \"SELECT COUNT(*) as n FROM cards WHERE user_id = ? AND blocked = 0 AND due_at <= datetime('now')\",\n userId,\n ) as { n: number }\n ).n,\n blocked: (\n q(\n db,\n \"SELECT COUNT(*) as n FROM cards WHERE user_id = ? AND blocked = 1\",\n userId,\n ) as { n: number }\n ).n,\n mature: (\n q(\n db,\n \"SELECT COUNT(*) as n FROM cards WHERE user_id = ? AND reps >= 3 AND stability >= 21\",\n userId,\n ) as { n: number }\n ).n,\n avgStability: (() => {\n const v = q(\n db,\n \"SELECT AVG(stability) as v FROM cards WHERE user_id = ? AND reps > 0\",\n userId,\n ) as { v: number | null };\n return v.v ? Math.round(v.v * 100) / 100 : null;\n })(),\n totalSessions: (\n q(db, \"SELECT COUNT(*) as n FROM sessions WHERE user_id = ?\", userId) as {\n n: number;\n }\n ).n,\n lastSession: (() => {\n const r = db\n .prepare(\n \"SELECT started_at FROM sessions WHERE user_id = ? ORDER BY started_at DESC LIMIT 1\",\n )\n .get(userId) as { started_at: string } | undefined;\n return r?.started_at ?? null;\n })(),\n };\n}\n\n/**\n * Get competence per domain for a user.\n * Used to suggest symbiosis mode transitions.\n */\nexport function getDomainCompetence(\n db: Database,\n userId: string,\n): DomainCompetence[] {\n const domains = db\n .prepare(\n `SELECT DISTINCT t.domain FROM cards c\n JOIN tokens t ON t.id = c.token_id\n WHERE c.user_id = ? AND t.domain != ''`,\n )\n .all(userId) as { domain: string }[];\n\n return domains.map((d) => {\n const total = (\n q(\n db,\n `SELECT COUNT(*) as n FROM cards c\n JOIN tokens t ON t.id = c.token_id\n WHERE c.user_id = ? AND t.domain = ?`,\n userId,\n d.domain,\n ) as { n: number }\n ).n;\n\n const mature = (\n q(\n db,\n `SELECT COUNT(*) as n FROM cards c\n JOIN tokens t ON t.id = c.token_id\n WHERE c.user_id = ? AND t.domain = ? AND c.reps >= 3 AND c.stability >= 21`,\n userId,\n d.domain,\n ) as { n: number }\n ).n;\n\n const avgStab =\n (\n q(\n db,\n `SELECT AVG(c.stability) as v FROM cards c\n JOIN tokens t ON t.id = c.token_id\n WHERE c.user_id = ? AND t.domain = ? AND c.reps > 0`,\n userId,\n d.domain,\n ) as { v: number | null }\n ).v ?? 0;\n\n // Estimate retention from review history\n const reviews = q(\n db,\n `SELECT COUNT(*) as total,\n SUM(CASE WHEN rating >= 2 THEN 1 ELSE 0 END) as passed\n FROM review_logs\n WHERE user_id = ? AND token_id IN (SELECT id FROM tokens WHERE domain = ?)`,\n userId,\n d.domain,\n ) as { total: number; passed: number };\n\n const retentionRate =\n reviews.total > 0 ? reviews.passed / reviews.total : 0;\n\n let suggestedMode: DomainCompetence[\"suggestedMode\"];\n if (retentionRate > 0.9 && avgStab > 30) {\n suggestedMode = \"autonomy\";\n } else if (retentionRate > 0.7 && avgStab > 7) {\n suggestedMode = \"copilot\";\n } else {\n suggestedMode = \"shadowing\";\n }\n\n return {\n domain: d.domain,\n totalCards: total,\n matureCards: mature,\n avgStability: Math.round(avgStab * 100) / 100,\n retentionRate: Math.round(retentionRate * 1000) / 1000,\n suggestedMode,\n };\n });\n}\n","/**\n * Credential store — reads/writes ~/.zam/credentials.json\n *\n * Connector secrets (Turso URL/token, ADO PAT, etc.) live here instead of\n * inside the SQLite database. This ensures credentials survive db deletion,\n * which is required when migrating from plain SQLite to a libsql embedded\n * replica (Turso cloud sync).\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nconst DEFAULT_CREDENTIALS_PATH = join(homedir(), \".zam\", \"credentials.json\");\n\nexport interface TursoCredentials {\n url: string;\n token: string;\n}\n\nexport interface ADOCredentials {\n org_url: string;\n project: string;\n pat: string;\n}\n\nexport interface Credentials {\n turso?: Partial<TursoCredentials>;\n ado?: Partial<ADOCredentials>;\n}\n\n/** Load credentials from ~/.zam/credentials.json. Returns empty object if missing. */\nexport function loadCredentials(path?: string): Credentials {\n const p = path ?? DEFAULT_CREDENTIALS_PATH;\n if (!existsSync(p)) return {};\n try {\n return JSON.parse(readFileSync(p, \"utf-8\")) as Credentials;\n } catch {\n return {};\n }\n}\n\n/** Save credentials to ~/.zam/credentials.json. */\nexport function saveCredentials(creds: Credentials, path?: string): void {\n const p = path ?? DEFAULT_CREDENTIALS_PATH;\n const dir = dirname(p);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n writeFileSync(p, `${JSON.stringify(creds, null, 2)}\\n`, \"utf-8\");\n}\n\n/** Get complete Turso credentials, or null if incomplete. */\nexport function getTursoCredentials(path?: string): TursoCredentials | null {\n const creds = loadCredentials(path);\n if (creds.turso?.url && creds.turso?.token) {\n return { url: creds.turso.url, token: creds.turso.token };\n }\n return null;\n}\n\n/** Set Turso credentials. */\nexport function setTursoCredentials(\n url: string,\n token: string,\n path?: string,\n): void {\n const creds = loadCredentials(path);\n creds.turso = { url, token };\n saveCredentials(creds, path);\n}\n\n/** Clear Turso credentials. */\nexport function clearTursoCredentials(path?: string): void {\n const creds = loadCredentials(path);\n delete creds.turso;\n saveCredentials(creds, path);\n}\n\n/** Get complete ADO credentials, or null if incomplete. */\nexport function getADOCredentials(path?: string): ADOCredentials | null {\n const creds = loadCredentials(path);\n if (creds.ado?.org_url && creds.ado?.project && creds.ado?.pat) {\n return {\n org_url: creds.ado.org_url,\n project: creds.ado.project,\n pat: creds.ado.pat,\n };\n }\n return null;\n}\n\n/** Set ADO credentials. */\nexport function setADOCredentials(\n orgUrl: string,\n project: string,\n pat: string,\n path?: string,\n): void {\n const creds = loadCredentials(path);\n creds.ado = { org_url: orgUrl, project, pat };\n saveCredentials(creds, path);\n}\n\n/** Clear ADO credentials. */\nexport function clearADOCredentials(path?: string): void {\n const creds = loadCredentials(path);\n delete creds.ado;\n saveCredentials(creds, path);\n}\n","/**\n * Azure DevOps connector — fetches work items from ADO boards.\n */\n\nimport { getADOCredentials } from \"../credentials.js\";\n\nexport interface ADOConfig {\n orgUrl: string;\n project: string;\n pat: string;\n}\n\nexport interface WorkItem {\n id: number;\n title: string;\n state: string;\n type: string;\n assignedTo: string;\n}\n\n/** Load ADO config from credentials file. Returns null if not configured. */\nexport function loadADOConfig(): ADOConfig | null {\n const creds = getADOCredentials();\n if (!creds) return null;\n return {\n orgUrl: creds.org_url.replace(/\\/+$/, \"\"),\n project: creds.project,\n pat: creds.pat,\n };\n}\n\nfunction authHeader(pat: string): string {\n return `Basic ${Buffer.from(`:${pat}`).toString(\"base64\")}`;\n}\n\n/**\n * Fetch active work items assigned to the current user.\n * Uses WIQL to query, then batch-fetches work item details.\n */\nexport async function fetchActiveWorkItems(\n config: ADOConfig,\n): Promise<WorkItem[]> {\n const { orgUrl, project, pat } = config;\n\n // Step 1: WIQL query for work item IDs\n const wiqlUrl = `${orgUrl}/${project}/_apis/wit/wiql?api-version=7.1`;\n const wiqlBody = {\n query: `SELECT [System.Id] FROM WorkItems WHERE [System.AssignedTo] = @me AND [System.State] NOT IN ('Closed', 'Completed', 'Done', 'Removed') ORDER BY [Microsoft.VSTS.Common.Priority] ASC, [System.ChangedDate] DESC`,\n };\n\n const wiqlRes = await fetch(wiqlUrl, {\n method: \"POST\",\n headers: {\n Authorization: authHeader(pat),\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(wiqlBody),\n });\n\n if (!wiqlRes.ok) {\n const text = await wiqlRes.text();\n throw new Error(`ADO WIQL query failed (${wiqlRes.status}): ${text}`);\n }\n\n const wiqlData = (await wiqlRes.json()) as { workItems: { id: number }[] };\n const ids = wiqlData.workItems.map((wi) => wi.id);\n\n if (ids.length === 0) return [];\n\n // Step 2: Batch fetch work item details (max 200 per request)\n const batchIds = ids.slice(0, 200);\n const fields =\n \"System.Id,System.Title,System.State,System.WorkItemType,System.AssignedTo\";\n const detailUrl = `${orgUrl}/${project}/_apis/wit/workitems?ids=${batchIds.join(\",\")}&fields=${fields}&api-version=7.1`;\n\n const detailRes = await fetch(detailUrl, {\n headers: { Authorization: authHeader(pat) },\n });\n\n if (!detailRes.ok) {\n const text = await detailRes.text();\n throw new Error(\n `ADO work items fetch failed (${detailRes.status}): ${text}`,\n );\n }\n\n const detailData = (await detailRes.json()) as {\n value: Array<{\n id: number;\n fields: {\n \"System.Title\": string;\n \"System.State\": string;\n \"System.WorkItemType\": string;\n \"System.AssignedTo\"?: { displayName: string };\n };\n }>;\n };\n\n return detailData.value.map((wi) => ({\n id: wi.id,\n title: wi.fields[\"System.Title\"],\n state: wi.fields[\"System.State\"],\n type: wi.fields[\"System.WorkItemType\"],\n assignedTo: wi.fields[\"System.AssignedTo\"]?.displayName ?? \"\",\n }));\n}\n","import { existsSync, mkdirSync, readFileSync, rmSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport Database, { type Database as DatabaseType } from \"libsql\";\nimport { getTursoCredentials } from \"../credentials.js\";\nimport { SCHEMA } from \"./schema.js\";\n\nconst DEFAULT_DB_DIR = join(homedir(), \".zam\");\nconst DEFAULT_DB_PATH = join(DEFAULT_DB_DIR, \"zam.db\");\n\nexport interface ConnectionOptions {\n /** Path to the SQLite database file. Defaults to ~/.zam/zam.db */\n dbPath?: string;\n /** If true, create the directory and run schema migrations on open */\n initialize?: boolean;\n /** Turso sync URL for embedded replica mode (e.g. libsql://db-name.turso.io) */\n syncUrl?: string;\n /** Turso auth token for direct remote or embedded replica access */\n authToken?: string;\n /** If false, ignore ~/.zam/credentials.json and force the local/default database. */\n useConfiguredCloud?: boolean;\n}\n\nfunction isRemoteDatabasePath(dbPath: string): boolean {\n return /^(libsql|https?):\\/\\//i.test(dbPath);\n}\n\n/**\n * Open (or create) the ZAM database.\n * Uses configured Turso credentials for the default database when present.\n * Falls back to local SQLite and WAL mode when no cloud credentials exist.\n * When syncUrl is provided explicitly, enables embedded replica sync with Turso.\n */\nexport function openDatabase(options: ConnectionOptions = {}): DatabaseType {\n const configuredCloud =\n options.useConfiguredCloud !== false && !options.dbPath && !options.syncUrl\n ? getTursoCredentials()\n : null;\n\n let requiresTurso = false;\n try {\n const configPath = join(process.cwd(), \".zam\", \"config.yaml\");\n if (existsSync(configPath)) {\n const configText = readFileSync(configPath, \"utf-8\");\n if (/[\\s\\S]*turso:[\\s\\S]*url:/m.test(configText)) {\n requiresTurso = true;\n }\n }\n } catch (_e) {}\n\n if (\n requiresTurso &&\n !configuredCloud &&\n options.useConfiguredCloud !== false &&\n !options.dbPath &&\n !options.syncUrl\n ) {\n throw new Error(\n \"Turso cloud database is configured in .zam/config.yaml but missing local credentials. Run: zam connector setup turso\",\n );\n }\n const dbPath = configuredCloud?.url ?? options.dbPath ?? DEFAULT_DB_PATH;\n const isRemote = isRemoteDatabasePath(dbPath);\n const isEmbeddedReplica = Boolean(options.syncUrl);\n\n if (options.initialize && !isRemote) {\n const dir = dirname(dbPath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n }\n\n // Build constructor options for libsql\n const dbOpts: Record<string, unknown> = {};\n if (options.syncUrl) {\n dbOpts.syncUrl = options.syncUrl;\n\n // When syncUrl is provided, the db must be a libsql embedded replica (not\n // plain SQLite). The presence of a companion .meta (or -info) file proves\n // it was created by libsql.\n //\n // If the db exists WITHOUT metadata, it was created before Turso was\n // configured — delete it so libsql can sync fresh from cloud.\n //\n // If metadata exists WITHOUT the db, libsql throws InvalidLocalState —\n // delete the metadata so it can start fresh.\n const metaPath = `${dbPath}.meta`;\n const infoPath = `${dbPath}-info`;\n\n if (existsSync(dbPath) && !existsSync(metaPath) && !existsSync(infoPath)) {\n for (const suffix of [\"\", \"-wal\", \"-shm\"]) {\n const f = `${dbPath}${suffix}`;\n if (existsSync(f)) rmSync(f, { force: true });\n }\n } else if (\n !existsSync(dbPath) &&\n (existsSync(metaPath) || existsSync(infoPath))\n ) {\n if (existsSync(metaPath)) rmSync(metaPath);\n if (existsSync(infoPath)) rmSync(infoPath);\n }\n }\n const authToken = configuredCloud?.token ?? options.authToken;\n if (authToken) {\n dbOpts.authToken = authToken;\n }\n\n let db: DatabaseType;\n try {\n db = new Database(dbPath, dbOpts as Database.Options);\n } catch (err) {\n const msg = (err as Error).message;\n if (msg.includes(\"InvalidLocalState\") && options.syncUrl) {\n // Last-ditch recovery: metadata is corrupt or mismatched\n const metaPath = `${dbPath}.meta`;\n const infoPath = `${dbPath}-info`;\n if (existsSync(metaPath)) rmSync(metaPath);\n if (existsSync(infoPath)) rmSync(infoPath);\n db = new Database(dbPath, dbOpts as Database.Options);\n } else {\n throw err;\n }\n }\n\n // Enable WAL mode and foreign keys for local SQLite.\n // Remote Turso databases and embedded replicas manage their own journaling.\n if (!isRemote && !isEmbeddedReplica) {\n db.pragma(\"journal_mode = WAL\");\n }\n db.pragma(\"foreign_keys = ON\");\n if (!isRemote) {\n db.pragma(\"busy_timeout = 5000\");\n }\n\n // For embedded replicas: sync from cloud FIRST so the local file has the\n // primary's schema before we try to run migrations or create tables.\n if (isEmbeddedReplica) {\n (db as unknown as { sync: () => void }).sync();\n }\n\n if (options.initialize) {\n db.exec(SCHEMA);\n }\n\n runMigrations(db);\n\n return db;\n}\n\n/**\n * Open the database with Turso cloud credentials auto-detected.\n * Credentials live in ~/.zam/credentials.json (NOT in the db), so a fresh\n * machine only has to collect missing secrets instead of bootstrapping local\n * state first.\n */\nexport function openDatabaseWithSync(\n options: Omit<ConnectionOptions, \"syncUrl\" | \"authToken\"> = {},\n): DatabaseType {\n return openDatabase(options);\n}\n\n/** Get the default database path */\nexport function getDefaultDbPath(): string {\n return DEFAULT_DB_PATH;\n}\n\n/**\n * Run incremental schema migrations on every open.\n * Each migration is idempotent — safe to run repeatedly.\n */\nfunction runMigrations(db: DatabaseType): void {\n // M001: add execution_context to sessions\n const sessionCols = db.pragma(\"table_info(sessions)\") as Array<{\n name: string;\n }>;\n if (\n sessionCols.length > 0 &&\n !sessionCols.some((c) => c.name === \"execution_context\")\n ) {\n db.exec(\n `ALTER TABLE sessions ADD COLUMN execution_context TEXT NOT NULL DEFAULT 'shell'`,\n );\n }\n\n // M002: add deprecated_at to tokens\n const tokenCols = db.pragma(\"table_info(tokens)\") as Array<{ name: string }>;\n if (\n tokenCols.length > 0 &&\n !tokenCols.some((c) => c.name === \"deprecated_at\")\n ) {\n db.exec(`ALTER TABLE tokens ADD COLUMN deprecated_at TEXT`);\n }\n\n // M004: add source_link to tokens\n if (\n tokenCols.length > 0 &&\n !tokenCols.some((c) => c.name === \"source_link\")\n ) {\n db.exec(`ALTER TABLE tokens ADD COLUMN source_link TEXT`);\n }\n\n // M005: add question to tokens\n if (tokenCols.length > 0 && !tokenCols.some((c) => c.name === \"question\")) {\n db.exec(`ALTER TABLE tokens ADD COLUMN question TEXT`);\n }\n\n // M003: create agent_skills table (idempotent via IF NOT EXISTS in SCHEMA,\n // but also needed for databases that skipped the init path)\n db.exec(`\n CREATE TABLE IF NOT EXISTS agent_skills (\n id TEXT PRIMARY KEY,\n slug TEXT NOT NULL UNIQUE,\n description TEXT NOT NULL,\n steps TEXT NOT NULL DEFAULT '[]',\n token_slugs TEXT NOT NULL DEFAULT '[]',\n source TEXT NOT NULL DEFAULT 'learned',\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n )\n `);\n}\n","/**\n * ZAM Learning Kernel — SQLite Schema\n *\n * Evolves the PoC's schema with:\n * - FSRS scheduling fields (replaces SM-2's ef/interval_days)\n * - Bloom taxonomy levels on tokens\n * - Symbiosis modes (shadowing/copilot/autonomy)\n * - ULID-based IDs\n * - Immutable review log\n */\n\nexport const SCHEMA = `\n-- PRAGMAs (WAL, foreign_keys) are set programmatically in connection.ts,\n-- not here, because libsql embedded replicas manage their own WAL.\n\n-- Knowledge tokens: atomic concepts/facts with Bloom levels\nCREATE TABLE IF NOT EXISTS tokens (\n id TEXT PRIMARY KEY,\n slug TEXT UNIQUE NOT NULL,\n concept TEXT NOT NULL,\n domain TEXT NOT NULL DEFAULT '',\n bloom_level INTEGER NOT NULL DEFAULT 1 CHECK (bloom_level BETWEEN 1 AND 5),\n context TEXT NOT NULL DEFAULT '',\n symbiosis_mode TEXT CHECK (symbiosis_mode IN ('shadowing', 'copilot', 'autonomy')),\n source_link TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now')),\n deprecated_at TEXT,\n question TEXT\n);\n\n-- Prerequisite dependency graph: \"to learn A, first know B\"\nCREATE TABLE IF NOT EXISTS prerequisites (\n token_id TEXT NOT NULL REFERENCES tokens(id) ON DELETE CASCADE,\n requires_id TEXT NOT NULL REFERENCES tokens(id) ON DELETE CASCADE,\n PRIMARY KEY (token_id, requires_id)\n);\n\n-- Per-user scheduling state for each token (FSRS fields)\nCREATE TABLE IF NOT EXISTS cards (\n id TEXT PRIMARY KEY,\n token_id TEXT NOT NULL REFERENCES tokens(id) ON DELETE CASCADE,\n user_id TEXT NOT NULL,\n stability REAL NOT NULL DEFAULT 0.0,\n difficulty REAL NOT NULL DEFAULT 0.5,\n elapsed_days REAL NOT NULL DEFAULT 0.0,\n scheduled_days REAL NOT NULL DEFAULT 0.0,\n reps INTEGER NOT NULL DEFAULT 0,\n lapses INTEGER NOT NULL DEFAULT 0,\n state TEXT NOT NULL DEFAULT 'new' CHECK (state IN ('new', 'learning', 'review', 'relearning')),\n due_at TEXT NOT NULL DEFAULT (datetime('now')),\n last_review_at TEXT,\n blocked INTEGER NOT NULL DEFAULT 0,\n UNIQUE(token_id, user_id)\n);\n\n-- Immutable review log: every rating event\nCREATE TABLE IF NOT EXISTS review_logs (\n id TEXT PRIMARY KEY,\n card_id TEXT NOT NULL REFERENCES cards(id) ON DELETE CASCADE,\n token_id TEXT NOT NULL REFERENCES tokens(id) ON DELETE CASCADE,\n user_id TEXT NOT NULL,\n rating INTEGER NOT NULL CHECK (rating BETWEEN 1 AND 4),\n response_time_ms INTEGER,\n reviewed_at TEXT NOT NULL DEFAULT (datetime('now')),\n scheduled_at TEXT NOT NULL,\n session_id TEXT REFERENCES sessions(id)\n);\n\n-- Work+learning sessions\nCREATE TABLE IF NOT EXISTS sessions (\n id TEXT PRIMARY KEY,\n user_id TEXT NOT NULL,\n task TEXT NOT NULL,\n started_at TEXT NOT NULL DEFAULT (datetime('now')),\n completed_at TEXT\n);\n\n-- Steps within a session: who did what\nCREATE TABLE IF NOT EXISTS session_steps (\n id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,\n token_id TEXT NOT NULL REFERENCES tokens(id) ON DELETE CASCADE,\n done_by TEXT NOT NULL CHECK (done_by IN ('user', 'agent')),\n rating INTEGER CHECK (rating BETWEEN 1 AND 4),\n notes TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- User configuration\nCREATE TABLE IF NOT EXISTS user_config (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL,\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Agent skills: task recipes the agent learns from user guidance\nCREATE TABLE IF NOT EXISTS agent_skills (\n id TEXT PRIMARY KEY,\n slug TEXT NOT NULL UNIQUE,\n description TEXT NOT NULL,\n steps TEXT NOT NULL DEFAULT '[]', -- JSON array of step strings\n token_slugs TEXT NOT NULL DEFAULT '[]', -- JSON array of related token slugs\n source TEXT NOT NULL DEFAULT 'learned'\n CHECK(source IN ('learned', 'builtin')),\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Performance indexes\nCREATE INDEX IF NOT EXISTS idx_tokens_domain ON tokens(domain);\nCREATE INDEX IF NOT EXISTS idx_tokens_slug ON tokens(slug);\nCREATE INDEX IF NOT EXISTS idx_prereqs_token ON prerequisites(token_id);\nCREATE INDEX IF NOT EXISTS idx_prereqs_requires ON prerequisites(requires_id);\nCREATE INDEX IF NOT EXISTS idx_cards_user_due ON cards(user_id, blocked, due_at);\nCREATE INDEX IF NOT EXISTS idx_cards_token_user ON cards(token_id, user_id);\nCREATE INDEX IF NOT EXISTS idx_review_logs_card ON review_logs(card_id);\nCREATE INDEX IF NOT EXISTS idx_review_logs_user ON review_logs(user_id, reviewed_at);\nCREATE INDEX IF NOT EXISTS idx_session_steps_session ON session_steps(session_id);\n`;\n","/**\n * Goal Engine — manages goal lifecycle via markdown files.\n *\n * Goals live as markdown files in a directory (typically the personal repo's\n * goals/ folder). The engine reads, creates, and updates these files.\n * It does not depend on the database — goals are git-tracked, not DB-tracked.\n */\n\nimport { existsSync, readdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { basename, join } from \"node:path\";\nimport type { Goal, GoalStatus } from \"./parser.js\";\nimport {\n extractTasks,\n extractTokenRefs,\n parseGoalFile,\n serializeGoal,\n} from \"./parser.js\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface GoalSummary {\n slug: string;\n title: string;\n status: GoalStatus;\n parent: string | null;\n taskCount: number;\n tasksDone: number;\n tokenCount: number;\n}\n\nexport interface CreateGoalInput {\n slug: string;\n title: string;\n status?: GoalStatus;\n parent?: string;\n description?: string;\n}\n\n// ── Functions ────────────────────────────────────────────────────────────────\n\n/**\n * List all goals in the goals directory.\n * Returns summaries sorted by status (active first) then title.\n */\nexport function listGoals(goalsDir: string): GoalSummary[] {\n if (!existsSync(goalsDir)) return [];\n\n const files = readdirSync(goalsDir).filter(\n (f) => f.endsWith(\".md\") && f !== \"README.md\",\n );\n\n const summaries: GoalSummary[] = [];\n\n for (const file of files) {\n const filePath = join(goalsDir, file);\n const content = readFileSync(filePath, \"utf-8\");\n const slug = basename(file, \".md\");\n const goal = parseGoalFile(content, slug, filePath);\n const tasks = extractTasks(goal.body);\n const tokens = extractTokenRefs(goal.body);\n\n summaries.push({\n slug: goal.slug,\n title: goal.title,\n status: goal.status,\n parent: goal.parent,\n taskCount: tasks.length,\n tasksDone: tasks.filter((t) => t.done).length,\n tokenCount: tokens.length,\n });\n }\n\n const statusOrder: Record<GoalStatus, number> = {\n active: 0,\n paused: 1,\n completed: 2,\n abandoned: 3,\n };\n\n summaries.sort((a, b) => {\n const statusDiff = statusOrder[a.status] - statusOrder[b.status];\n if (statusDiff !== 0) return statusDiff;\n return a.title.localeCompare(b.title);\n });\n\n return summaries;\n}\n\n/**\n * Get a single goal by slug (filename without .md).\n * Returns undefined if the file doesn't exist.\n */\nexport function getGoal(goalsDir: string, slug: string): Goal | undefined {\n const filePath = join(goalsDir, `${slug}.md`);\n if (!existsSync(filePath)) return undefined;\n\n const content = readFileSync(filePath, \"utf-8\");\n return parseGoalFile(content, slug, filePath);\n}\n\n/**\n * Create a new goal file. Throws if a goal with this slug already exists.\n */\nexport function createGoal(goalsDir: string, input: CreateGoalInput): Goal {\n const filePath = join(goalsDir, `${input.slug}.md`);\n\n if (existsSync(filePath)) {\n throw new Error(`Goal already exists: ${input.slug}`);\n }\n\n const now = new Date().toISOString().slice(0, 10);\n\n const goal: Goal = {\n slug: input.slug,\n title: input.title,\n status: input.status ?? \"active\",\n parent: input.parent ?? null,\n created: now,\n updated: now,\n body: input.description\n ? `## Description\\n${input.description}\\n\\n## Tasks\\n\\n## Tokens`\n : \"## Description\\n\\n## Tasks\\n\\n## Tokens\",\n filePath,\n };\n\n writeFileSync(filePath, serializeGoal(goal), \"utf-8\");\n return goal;\n}\n\n/**\n * Update a goal's status. Writes the updated file back to disk.\n */\nexport function updateGoalStatus(\n goalsDir: string,\n slug: string,\n status: GoalStatus,\n): Goal {\n const goal = getGoal(goalsDir, slug);\n if (!goal) throw new Error(`Goal not found: ${slug}`);\n\n goal.status = status;\n goal.updated = new Date().toISOString().slice(0, 10);\n\n writeFileSync(goal.filePath, serializeGoal(goal), \"utf-8\");\n return goal;\n}\n\n/**\n * Get the goal tree — goals organized by parent relationships.\n * Returns root goals (no parent) with nested children.\n */\nexport function getGoalTree(\n goalsDir: string,\n): Array<GoalSummary & { children: GoalSummary[] }> {\n const all = listGoals(goalsDir);\n const bySlug = new Map(all.map((g) => [g.slug, g]));\n\n const roots: Array<GoalSummary & { children: GoalSummary[] }> = [];\n const children = new Map<string, GoalSummary[]>();\n\n for (const g of all) {\n if (g.parent && bySlug.has(g.parent)) {\n const list = children.get(g.parent) ?? [];\n list.push(g);\n children.set(g.parent, list);\n }\n }\n\n for (const g of all) {\n if (!g.parent || !bySlug.has(g.parent)) {\n roots.push({ ...g, children: children.get(g.slug) ?? [] });\n }\n }\n\n return roots;\n}\n","/**\n * Goal file parser — reads markdown files with YAML-style frontmatter.\n *\n * Goals are persisted as markdown files in the personal repo.\n * Each file has simple key: value frontmatter (no nested structures)\n * and a markdown body with description, tasks, and token references.\n */\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport type GoalStatus = \"active\" | \"completed\" | \"paused\" | \"abandoned\";\n\nexport interface Goal {\n slug: string; // derived from filename (e.g., \"learn-rust\" from \"learn-rust.md\")\n title: string;\n status: GoalStatus;\n parent: string | null; // slug of parent goal\n created: string; // ISO date\n updated: string; // ISO date\n body: string; // markdown body after frontmatter\n filePath: string; // absolute path to the file\n}\n\nexport interface GoalFrontmatter {\n title?: string;\n status?: string;\n parent?: string;\n created?: string;\n updated?: string;\n}\n\n// ── Parser ───────────────────────────────────────────────────────────────────\n\n/**\n * Parse a goal markdown file into a Goal object.\n *\n * Expected format:\n * ```\n * ---\n * title: Learn Rust fundamentals\n * status: active\n * parent: become-systems-programmer\n * created: 2026-03-28\n * updated: 2026-03-28\n * ---\n *\n * ## Description\n * ...\n * ```\n *\n * @param content - Raw file content\n * @param slug - Goal slug (derived from filename by caller)\n * @param filePath - Absolute path to the file\n */\nexport function parseGoalFile(\n content: string,\n slug: string,\n filePath: string,\n): Goal {\n const { frontmatter, body } = splitFrontmatter(content);\n\n const validStatuses: GoalStatus[] = [\n \"active\",\n \"completed\",\n \"paused\",\n \"abandoned\",\n ];\n const status = validStatuses.includes(frontmatter.status as GoalStatus)\n ? (frontmatter.status as GoalStatus)\n : \"active\";\n\n const now = new Date().toISOString().slice(0, 10);\n\n return {\n slug,\n title: frontmatter.title || slug,\n status,\n parent: frontmatter.parent || null,\n created: frontmatter.created || now,\n updated: frontmatter.updated || now,\n body,\n filePath,\n };\n}\n\n/**\n * Serialize a Goal back to markdown with frontmatter.\n */\nexport function serializeGoal(goal: Goal): string {\n const lines = [\"---\", `title: ${goal.title}`, `status: ${goal.status}`];\n\n if (goal.parent) {\n lines.push(`parent: ${goal.parent}`);\n }\n\n lines.push(`created: ${goal.created}`);\n lines.push(`updated: ${goal.updated}`);\n lines.push(\"---\");\n lines.push(\"\");\n\n if (goal.body.trim()) {\n lines.push(goal.body.trim());\n lines.push(\"\");\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Extract tasks (checklist items) from goal body.\n * Returns items like { text: \"Complete Rustlings\", done: false }.\n */\nexport function extractTasks(\n body: string,\n): Array<{ text: string; done: boolean }> {\n const tasks: Array<{ text: string; done: boolean }> = [];\n const taskRegex = /^[-*]\\s+\\[([ xX])\\]\\s+(.+)$/gm;\n let match: RegExpExecArray | null = taskRegex.exec(body);\n\n while (match !== null) {\n tasks.push({\n done: match[1] !== \" \",\n text: match[2].trim(),\n });\n match = taskRegex.exec(body);\n }\n\n return tasks;\n}\n\n/**\n * Extract token references from goal body.\n * Looks for lines like `- token/slug` under a \"## Tokens\" section.\n */\nexport function extractTokenRefs(body: string): string[] {\n const tokensSection = body.match(/## Tokens\\n([\\s\\S]*?)(?=\\n## |\\n*$)/);\n if (!tokensSection) return [];\n\n const refs: string[] = [];\n const lines = tokensSection[1].split(\"\\n\");\n\n for (const line of lines) {\n const match = line.match(/^[-*]\\s+(\\S+)/);\n if (match) {\n refs.push(match[1]);\n }\n }\n\n return refs;\n}\n\n// ── Internal helpers ─────────────────────────────────────────────────────────\n\nfunction splitFrontmatter(content: string): {\n frontmatter: GoalFrontmatter;\n body: string;\n} {\n const trimmed = content.trim();\n\n if (!trimmed.startsWith(\"---\")) {\n return { frontmatter: {}, body: trimmed };\n }\n\n const endIndex = trimmed.indexOf(\"---\", 3);\n if (endIndex === -1) {\n return { frontmatter: {}, body: trimmed };\n }\n\n const fmBlock = trimmed.slice(3, endIndex).trim();\n const body = trimmed.slice(endIndex + 3).trim();\n\n const frontmatter: GoalFrontmatter = {};\n for (const line of fmBlock.split(\"\\n\")) {\n const colonIndex = line.indexOf(\":\");\n if (colonIndex === -1) continue;\n\n const key = line.slice(0, colonIndex).trim();\n const value = line.slice(colonIndex + 1).trim();\n\n if (key && value) {\n (frontmatter as Record<string, string>)[key] = value;\n }\n }\n\n return { frontmatter, body };\n}\n","/**\n * Agent skills: task recipes the agent learns from user guidance.\n *\n * When the agent cannot execute a step, it admits it, asks for guidance,\n * and saves the successful approach here. Skills are linked to tokens so\n * FSRS decay naturally resurfaces them for review — automation ≠ retention.\n */\n\nimport type { Database } from \"libsql\";\nimport { ulid } from \"ulid\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport type SkillSource = \"learned\" | \"builtin\";\n\nexport interface AgentSkill {\n id: string;\n slug: string;\n description: string;\n steps: string[]; // parsed from JSON\n token_slugs: string[]; // parsed from JSON\n source: SkillSource;\n created_at: string;\n updated_at: string;\n}\n\n/** Raw DB row — steps and token_slugs are stored as JSON strings */\ninterface AgentSkillRow {\n id: string;\n slug: string;\n description: string;\n steps: string;\n token_slugs: string;\n source: SkillSource;\n created_at: string;\n updated_at: string;\n}\n\nexport interface CreateAgentSkillInput {\n slug: string;\n description: string;\n steps: string[];\n token_slugs?: string[];\n source?: SkillSource;\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction parseRow(row: AgentSkillRow): AgentSkill {\n return {\n ...row,\n steps: JSON.parse(row.steps) as string[],\n token_slugs: JSON.parse(row.token_slugs) as string[],\n };\n}\n\n// ── Functions ────────────────────────────────────────────────────────────────\n\nexport function createAgentSkill(\n db: Database,\n input: CreateAgentSkillInput,\n): AgentSkill {\n const existing = db\n .prepare(\"SELECT * FROM agent_skills WHERE slug = ?\")\n .get(input.slug) as AgentSkillRow | undefined;\n\n if (existing) {\n throw new Error(`Agent skill already exists: ${input.slug}`);\n }\n\n const id = ulid();\n const now = new Date().toISOString();\n\n db.prepare(\n `INSERT INTO agent_skills (id, slug, description, steps, token_slugs, source, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,\n ).run(\n id,\n input.slug,\n input.description,\n JSON.stringify(input.steps),\n JSON.stringify(input.token_slugs ?? []),\n input.source ?? \"learned\",\n now,\n now,\n );\n\n return parseRow(\n db\n .prepare(\"SELECT * FROM agent_skills WHERE id = ?\")\n .get(id) as AgentSkillRow,\n );\n}\n\nexport function getAgentSkill(\n db: Database,\n slug: string,\n): AgentSkill | undefined {\n const row = db\n .prepare(\"SELECT * FROM agent_skills WHERE slug = ?\")\n .get(slug) as AgentSkillRow | undefined;\n\n return row ? parseRow(row) : undefined;\n}\n\nexport function listAgentSkills(db: Database): AgentSkill[] {\n const rows = db\n .prepare(\"SELECT * FROM agent_skills ORDER BY created_at ASC\")\n .all() as AgentSkillRow[];\n\n return rows.map(parseRow);\n}\n","/**\n * Card repository — typed wrappers around the cards table.\n *\n * Each card tracks one user's scheduling state for one token,\n * using FSRS fields (stability, difficulty, elapsed_days, etc.).\n */\n\nimport type { Database } from \"libsql\";\nimport { ulid } from \"ulid\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport type CardState = \"new\" | \"learning\" | \"review\" | \"relearning\";\n\nexport interface Card {\n id: string;\n token_id: string;\n user_id: string;\n stability: number;\n difficulty: number;\n elapsed_days: number;\n scheduled_days: number;\n reps: number;\n lapses: number;\n state: CardState;\n due_at: string;\n last_review_at: string | null;\n blocked: number; // 0 or 1\n}\n\nexport interface UpdateCardInput {\n stability?: number;\n difficulty?: number;\n elapsed_days?: number;\n scheduled_days?: number;\n reps?: number;\n lapses?: number;\n state?: CardState;\n due_at?: string;\n last_review_at?: string | null;\n blocked?: number;\n}\n\nexport interface CardDeletionImpact {\n review_logs: number;\n}\n\nexport interface DeleteCardResult {\n card: Card;\n impact: CardDeletionImpact;\n}\n\n/** A due card joined with its token details. */\nexport interface DueCard extends Card {\n slug: string;\n concept: string;\n domain: string;\n bloom_level: number;\n}\n\n/** A blocked card joined with its token details. */\nexport interface BlockedCard extends Card {\n slug: string;\n concept: string;\n domain: string;\n bloom_level: number;\n}\n\n// ── Functions ────────────────────────────────────────────────────────────────\n\n/**\n * Ensure a card exists for the given token+user pair.\n *\n * If one already exists, return it. Otherwise create a new card with\n * default FSRS values (due immediately) and return it.\n *\n * Ported from the PoC's ensureCard helper.\n */\nexport function ensureCard(\n db: Database,\n tokenId: string,\n userId: string,\n): Card {\n const existing = db\n .prepare(\"SELECT * FROM cards WHERE token_id = ? AND user_id = ?\")\n .get(tokenId, userId) as Card | undefined;\n\n if (existing) return existing;\n\n const id = ulid();\n const now = new Date().toISOString();\n\n db.prepare(\n `INSERT INTO cards (id, token_id, user_id, due_at)\n VALUES (?, ?, ?, ?)`,\n ).run(id, tokenId, userId, now);\n\n return db.prepare(\"SELECT * FROM cards WHERE id = ?\").get(id) as Card;\n}\n\n/**\n * Get a card by token+user. Returns undefined if no card exists.\n */\nexport function getCard(\n db: Database,\n tokenId: string,\n userId: string,\n): Card | undefined {\n return db\n .prepare(\"SELECT * FROM cards WHERE token_id = ? AND user_id = ?\")\n .get(tokenId, userId) as Card | undefined;\n}\n\n/**\n * Get a card by its ULID.\n */\nexport function getCardById(db: Database, cardId: string): Card | undefined {\n return db.prepare(\"SELECT * FROM cards WHERE id = ?\").get(cardId) as\n | Card\n | undefined;\n}\n\n/**\n * Update a card's scheduling fields.\n *\n * Only the fields present in `updates` are changed. Throws if the card\n * does not exist.\n */\nexport function updateCard(\n db: Database,\n cardId: string,\n updates: UpdateCardInput,\n): Card {\n const fields: string[] = [];\n const values: unknown[] = [];\n\n if (updates.stability !== undefined) {\n fields.push(\"stability = ?\");\n values.push(updates.stability);\n }\n if (updates.difficulty !== undefined) {\n fields.push(\"difficulty = ?\");\n values.push(updates.difficulty);\n }\n if (updates.elapsed_days !== undefined) {\n fields.push(\"elapsed_days = ?\");\n values.push(updates.elapsed_days);\n }\n if (updates.scheduled_days !== undefined) {\n fields.push(\"scheduled_days = ?\");\n values.push(updates.scheduled_days);\n }\n if (updates.reps !== undefined) {\n fields.push(\"reps = ?\");\n values.push(updates.reps);\n }\n if (updates.lapses !== undefined) {\n fields.push(\"lapses = ?\");\n values.push(updates.lapses);\n }\n if (updates.state !== undefined) {\n fields.push(\"state = ?\");\n values.push(updates.state);\n }\n if (updates.due_at !== undefined) {\n fields.push(\"due_at = ?\");\n values.push(updates.due_at);\n }\n if (updates.last_review_at !== undefined) {\n fields.push(\"last_review_at = ?\");\n values.push(updates.last_review_at);\n }\n if (updates.blocked !== undefined) {\n fields.push(\"blocked = ?\");\n values.push(updates.blocked);\n }\n\n if (fields.length === 0) {\n throw new Error(\"updateCard called with no fields to update\");\n }\n\n values.push(cardId);\n\n const result = db\n .prepare(`UPDATE cards SET ${fields.join(\", \")} WHERE id = ?`)\n .run(...values);\n\n if (result.changes === 0) {\n throw new Error(`Card not found: ${cardId}`);\n }\n\n return db.prepare(\"SELECT * FROM cards WHERE id = ?\").get(cardId) as Card;\n}\n\n/**\n * Preview the review-log rows that will be removed when deleting a user's card.\n */\nexport function getCardDeletionImpact(\n db: Database,\n tokenId: string,\n userId: string,\n): CardDeletionImpact {\n const card = getCard(db, tokenId, userId);\n if (!card) {\n throw new Error(`Card not found for token ${tokenId} and user ${userId}`);\n }\n\n const reviewLogs = db\n .prepare(\"SELECT COUNT(*) AS n FROM review_logs WHERE card_id = ?\")\n .get(card.id) as { n: number };\n\n return { review_logs: reviewLogs.n };\n}\n\n/**\n * Delete one user's card for a token. Review logs cascade via FK.\n */\nexport function deleteCardForUser(\n db: Database,\n tokenId: string,\n userId: string,\n): DeleteCardResult {\n const card = getCard(db, tokenId, userId);\n if (!card) {\n throw new Error(`Card not found for token ${tokenId} and user ${userId}`);\n }\n\n const impact = getCardDeletionImpact(db, tokenId, userId);\n db.prepare(\"DELETE FROM cards WHERE id = ?\").run(card.id);\n\n return { card, impact };\n}\n\n/**\n * Get all cards that are due for review.\n *\n * A card is due when it is not blocked and due_at <= now.\n * Results are ordered by bloom_level ascending (fundamentals first),\n * then by due_at ascending (oldest first).\n *\n * Ported from the PoC's due-tokens command.\n */\nexport function getDueCards(\n db: Database,\n userId: string,\n now?: string,\n): DueCard[] {\n const cutoff = now ?? new Date().toISOString();\n\n return db\n .prepare(\n `SELECT c.*, t.slug, t.concept, t.domain, t.bloom_level\n FROM cards c\n JOIN tokens t ON t.id = c.token_id\n WHERE c.user_id = ? AND c.blocked = 0 AND c.due_at <= ?\n ORDER BY t.bloom_level ASC, c.due_at ASC`,\n )\n .all(userId, cutoff) as DueCard[];\n}\n\n/**\n * Get all blocked cards for a user.\n *\n * Returns cards joined with their token details so the caller can\n * see what is waiting and why.\n */\nexport function getBlockedCards(db: Database, userId: string): BlockedCard[] {\n return db\n .prepare(\n `SELECT c.*, t.slug, t.concept, t.domain, t.bloom_level\n FROM cards c\n JOIN tokens t ON t.id = c.token_id\n WHERE c.user_id = ? AND c.blocked = 1\n ORDER BY t.bloom_level ASC, t.slug ASC`,\n )\n .all(userId) as BlockedCard[];\n}\n","/**\n * Prerequisite repository — typed wrappers around the prerequisites table.\n *\n * Models the dependency graph: \"to learn token A, first know token B.\"\n */\n\nimport type { Database } from \"libsql\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface Prerequisite {\n token_id: string;\n requires_id: string;\n}\n\n/** A prerequisite row joined with the token it points to. */\nexport interface PrerequisiteWithToken extends Prerequisite {\n slug: string;\n concept: string;\n domain: string;\n bloom_level: number;\n}\n\n// ── Functions ────────────────────────────────────────────────────────────────\n\n/**\n * Add a prerequisite edge: tokenId requires requiresId.\n *\n * Idempotent — silently ignores duplicate edges.\n * Throws if either token ID does not exist (FK constraint).\n * Throws if a token is declared as its own prerequisite.\n */\nexport function addPrerequisite(\n db: Database,\n tokenId: string,\n requiresId: string,\n): void {\n if (tokenId === requiresId) {\n throw new Error(\"A token cannot be a prerequisite of itself\");\n }\n\n db.prepare(\n \"INSERT OR IGNORE INTO prerequisites (token_id, requires_id) VALUES (?, ?)\",\n ).run(tokenId, requiresId);\n}\n\n/**\n * Get the direct prerequisites of a token — \"what does token X require?\"\n *\n * Returns prerequisite rows joined with the required token's details.\n */\nexport function getPrerequisites(\n db: Database,\n tokenId: string,\n): PrerequisiteWithToken[] {\n return db\n .prepare(\n `SELECT p.token_id, p.requires_id, t.slug, t.concept, t.domain, t.bloom_level\n FROM prerequisites p\n JOIN tokens t ON t.id = p.requires_id\n WHERE p.token_id = ?`,\n )\n .all(tokenId) as PrerequisiteWithToken[];\n}\n\n/**\n * Get the direct dependents of a token — \"what depends on token X?\"\n *\n * Returns prerequisite rows joined with the dependent token's details.\n */\nexport function getDependents(\n db: Database,\n tokenId: string,\n): PrerequisiteWithToken[] {\n return db\n .prepare(\n `SELECT p.token_id, p.requires_id, t.slug, t.concept, t.domain, t.bloom_level\n FROM prerequisites p\n JOIN tokens t ON t.id = p.token_id\n WHERE p.requires_id = ?`,\n )\n .all(tokenId) as PrerequisiteWithToken[];\n}\n","/**\n * Review log repository — typed wrappers around the review_logs table.\n *\n * The review log is immutable: every rating event is appended, never\n * updated or deleted. This provides a complete audit trail of a user's\n * learning history.\n */\n\nimport type { Database } from \"libsql\";\nimport { ulid } from \"ulid\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface ReviewLog {\n id: string;\n card_id: string;\n token_id: string;\n user_id: string;\n rating: number; // 1-4\n response_time_ms: number | null;\n reviewed_at: string;\n scheduled_at: string;\n session_id: string | null;\n}\n\nexport interface CreateReviewInput {\n card_id: string;\n token_id: string;\n user_id: string;\n rating: number; // 1-4\n scheduled_at: string;\n response_time_ms?: number | null;\n session_id?: string | null;\n}\n\nexport interface ListReviewsOptions {\n /** Maximum number of reviews to return. */\n limit?: number;\n /** Return reviews after this ISO timestamp. */\n after?: string;\n /** Return reviews before this ISO timestamp. */\n before?: string;\n}\n\n// ── Functions ────────────────────────────────────────────────────────────────\n\n/**\n * Log an immutable review event.\n *\n * Validates that the rating is between 1 and 4 (matching the schema CHECK).\n * Returns the created review log entry.\n */\nexport function logReview(db: Database, input: CreateReviewInput): ReviewLog {\n if (input.rating < 1 || input.rating > 4) {\n throw new Error(`Rating must be between 1 and 4, got ${input.rating}`);\n }\n\n const id = ulid();\n const now = new Date().toISOString();\n\n db.prepare(\n `INSERT INTO review_logs (id, card_id, token_id, user_id, rating, response_time_ms, reviewed_at, scheduled_at, session_id)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n ).run(\n id,\n input.card_id,\n input.token_id,\n input.user_id,\n input.rating,\n input.response_time_ms ?? null,\n now,\n input.scheduled_at,\n input.session_id ?? null,\n );\n\n return db\n .prepare(\"SELECT * FROM review_logs WHERE id = ?\")\n .get(id) as ReviewLog;\n}\n\n/**\n * Get all reviews for a specific card, ordered by reviewed_at ascending.\n */\nexport function getReviewsForCard(db: Database, cardId: string): ReviewLog[] {\n return db\n .prepare(\n \"SELECT * FROM review_logs WHERE card_id = ? ORDER BY reviewed_at ASC\",\n )\n .all(cardId) as ReviewLog[];\n}\n\n/**\n * Get reviews for a user, with optional filtering.\n *\n * Results are ordered by reviewed_at descending (most recent first).\n */\nexport function getReviewsForUser(\n db: Database,\n userId: string,\n options?: ListReviewsOptions,\n): ReviewLog[] {\n const conditions = [\"user_id = ?\"];\n const params: unknown[] = [userId];\n\n if (options?.after) {\n conditions.push(\"reviewed_at > ?\");\n params.push(options.after);\n }\n if (options?.before) {\n conditions.push(\"reviewed_at < ?\");\n params.push(options.before);\n }\n\n let sql = `SELECT * FROM review_logs WHERE ${conditions.join(\" AND \")} ORDER BY reviewed_at DESC`;\n\n if (options?.limit) {\n sql += \" LIMIT ?\";\n params.push(options.limit);\n }\n\n return db.prepare(sql).all(...params) as ReviewLog[];\n}\n","/**\n * Session repository — typed wrappers around sessions and session_steps.\n *\n * A session represents a work+learning episode. Steps within a session\n * record which tokens were touched and by whom (user or agent).\n */\n\nimport type { Database } from \"libsql\";\nimport { ulid } from \"ulid\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport type ExecutionContext = \"shell\" | \"ui\" | \"reallife\";\n\nexport interface Session {\n id: string;\n user_id: string;\n task: string;\n execution_context: ExecutionContext;\n started_at: string;\n completed_at: string | null;\n}\n\nexport interface SessionStep {\n id: string;\n session_id: string;\n token_id: string;\n done_by: \"user\" | \"agent\";\n rating: number | null; // 1-4 or null\n notes: string | null;\n created_at: string;\n}\n\nexport interface CreateSessionInput {\n user_id: string;\n task: string;\n execution_context?: ExecutionContext;\n}\n\nexport interface LogStepInput {\n session_id: string;\n token_id: string;\n done_by: \"user\" | \"agent\";\n rating?: number | null;\n notes?: string | null;\n}\n\n/** A step joined with its token details, returned by getSessionSummary. */\nexport interface StepWithToken extends SessionStep {\n slug: string;\n concept: string;\n domain: string;\n bloom_level: number;\n}\n\nexport interface SessionSummary {\n session: Session;\n steps: StepWithToken[];\n}\n\n// ── Functions ────────────────────────────────────────────────────────────────\n\n/**\n * Start a new session. Returns the created session.\n *\n * Ported from the PoC's start-session command.\n */\nexport function startSession(db: Database, input: CreateSessionInput): Session {\n const id = ulid();\n const now = new Date().toISOString();\n const ctx = input.execution_context ?? \"shell\";\n\n db.prepare(\n `INSERT INTO sessions (id, user_id, task, execution_context, started_at)\n VALUES (?, ?, ?, ?, ?)`,\n ).run(id, input.user_id, input.task, ctx, now);\n\n return db.prepare(\"SELECT * FROM sessions WHERE id = ?\").get(id) as Session;\n}\n\n/**\n * End a session by setting its completed_at timestamp.\n *\n * Throws if the session does not exist or is already completed.\n *\n * Ported from the PoC's end-session command.\n */\nexport function endSession(db: Database, sessionId: string): Session {\n const session = db\n .prepare(\"SELECT * FROM sessions WHERE id = ?\")\n .get(sessionId) as Session | undefined;\n\n if (!session) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n if (session.completed_at) {\n throw new Error(`Session already completed: ${sessionId}`);\n }\n\n const now = new Date().toISOString();\n db.prepare(\"UPDATE sessions SET completed_at = ? WHERE id = ?\").run(\n now,\n sessionId,\n );\n\n return db\n .prepare(\"SELECT * FROM sessions WHERE id = ?\")\n .get(sessionId) as Session;\n}\n\n/**\n * Log a step within a session.\n *\n * Validates that done_by is 'user' or 'agent' and that the rating\n * (if provided) is between 1 and 4.\n *\n * Ported from the PoC's log-step command.\n */\nexport function logStep(db: Database, input: LogStepInput): SessionStep {\n if (input.done_by !== \"user\" && input.done_by !== \"agent\") {\n throw new Error(\n `done_by must be 'user' or 'agent', got '${input.done_by}'`,\n );\n }\n if (input.rating != null && (input.rating < 1 || input.rating > 4)) {\n throw new Error(`Rating must be between 1 and 4, got ${input.rating}`);\n }\n\n // Verify the session exists\n const session = db\n .prepare(\"SELECT id FROM sessions WHERE id = ?\")\n .get(input.session_id);\n if (!session) {\n throw new Error(`Session not found: ${input.session_id}`);\n }\n\n const id = ulid();\n const now = new Date().toISOString();\n\n db.prepare(\n `INSERT INTO session_steps (id, session_id, token_id, done_by, rating, notes, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n ).run(\n id,\n input.session_id,\n input.token_id,\n input.done_by,\n input.rating ?? null,\n input.notes ?? null,\n now,\n );\n\n return db\n .prepare(\"SELECT * FROM session_steps WHERE id = ?\")\n .get(id) as SessionStep;\n}\n\n/**\n * Get a full session summary: the session record plus all steps\n * joined with their token details.\n *\n * Ported from the PoC's session-summary command.\n * Throws if the session does not exist.\n */\nexport function getSessionSummary(\n db: Database,\n sessionId: string,\n): SessionSummary {\n const session = db\n .prepare(\"SELECT * FROM sessions WHERE id = ?\")\n .get(sessionId) as Session | undefined;\n\n if (!session) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n\n const steps = db\n .prepare(\n `SELECT ss.*, t.slug, t.concept, t.domain, t.bloom_level\n FROM session_steps ss\n JOIN tokens t ON t.id = ss.token_id\n WHERE ss.session_id = ?\n ORDER BY ss.created_at ASC`,\n )\n .all(sessionId) as StepWithToken[];\n\n return { session, steps };\n}\n","/**\n * User settings — key/value store backed by the user_config table.\n */\n\nimport type { Database } from \"libsql\";\n\nexport interface UserSetting {\n key: string;\n value: string;\n updated_at: string;\n}\n\n/** Get a single setting by key. Returns undefined if not set. */\nexport function getSetting(db: Database, key: string): string | undefined {\n const row = db\n .prepare(\"SELECT value FROM user_config WHERE key = ?\")\n .get(key) as { value: string } | undefined;\n return row?.value;\n}\n\n/** Get all settings as a key-value map. */\nexport function getAllSettings(db: Database): Record<string, string> {\n const rows = db\n .prepare(\"SELECT key, value FROM user_config ORDER BY key\")\n .all() as { key: string; value: string }[];\n const map: Record<string, string> = {};\n for (const row of rows) {\n map[row.key] = row.value;\n }\n return map;\n}\n\n/** Get all settings with metadata. */\nexport function getAllSettingsDetailed(db: Database): UserSetting[] {\n return db\n .prepare(\"SELECT key, value, updated_at FROM user_config ORDER BY key\")\n .all() as UserSetting[];\n}\n\n/** Set a setting (insert or update). */\nexport function setSetting(db: Database, key: string, value: string): void {\n db.prepare(\n `INSERT INTO user_config (key, value, updated_at)\n VALUES (?, ?, datetime('now'))\n ON CONFLICT(key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at`,\n ).run(key, value);\n}\n\n/** Delete a setting. Returns true if it existed. */\nexport function deleteSetting(db: Database, key: string): boolean {\n const result = db.prepare(\"DELETE FROM user_config WHERE key = ?\").run(key);\n return result.changes > 0;\n}\n","/**\n * Token repository — typed wrappers around the tokens table.\n *\n * Tokens are atomic knowledge concepts with Bloom taxonomy levels\n * and optional symbiosis modes (shadowing / copilot / autonomy).\n */\n\nimport type { Database } from \"libsql\";\nimport { ulid } from \"ulid\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport type BloomLevel = 1 | 2 | 3 | 4 | 5;\n\nexport type SymbiosisMode = \"shadowing\" | \"copilot\" | \"autonomy\";\n\nexport interface Token {\n id: string;\n slug: string;\n concept: string;\n domain: string;\n bloom_level: BloomLevel;\n context: string;\n symbiosis_mode: SymbiosisMode | null;\n source_link: string | null;\n question: string | null;\n created_at: string;\n updated_at: string;\n deprecated_at: string | null;\n}\n\nexport interface CreateTokenInput {\n slug: string;\n concept: string;\n domain?: string;\n bloom_level?: BloomLevel;\n context?: string;\n symbiosis_mode?: SymbiosisMode | null;\n source_link?: string | null;\n question?: string | null;\n}\n\nexport interface UpdateTokenInput {\n concept?: string;\n domain?: string;\n bloom_level?: BloomLevel;\n context?: string;\n symbiosis_mode?: SymbiosisMode | null;\n source_link?: string | null;\n question?: string | null;\n}\n\nexport interface ListTokensOptions {\n domain?: string;\n}\n\nexport interface TokenDeleteImpact {\n cards: number;\n review_logs: number;\n prerequisite_edges_from_token: number;\n prerequisite_edges_to_token: number;\n session_steps: number;\n sessions_touched: number;\n agent_skills: number;\n}\n\nexport interface DeleteTokenResult {\n token: Token;\n impact: TokenDeleteImpact;\n}\n\n// ── Scored result from fuzzy search ──────────────────────────────────────────\n\nexport interface ScoredToken extends Token {\n score: number;\n}\n\n// ── Functions ────────────────────────────────────────────────────────────────\n\n/**\n * Create a new knowledge token.\n * Throws if a token with the same slug already exists.\n */\nexport function createToken(db: Database, input: CreateTokenInput): Token {\n const id = ulid();\n const now = new Date().toISOString();\n\n const bloom = input.bloom_level ?? 1;\n if (bloom < 1 || bloom > 5) {\n throw new Error(`bloom_level must be between 1 and 5, got ${bloom}`);\n }\n\n db.prepare(`\n INSERT INTO tokens (id, slug, concept, domain, bloom_level, context, symbiosis_mode, source_link, question, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `).run(\n id,\n input.slug,\n input.concept,\n input.domain ?? \"\",\n bloom,\n input.context ?? \"\",\n input.symbiosis_mode ?? null,\n input.source_link ?? null,\n input.question ?? null,\n now,\n now,\n );\n\n return getTokenById(db, id)!;\n}\n\n/**\n * Look up a token by its unique slug.\n * Returns undefined if not found.\n */\nexport function getTokenBySlug(db: Database, slug: string): Token | undefined {\n return db.prepare(\"SELECT * FROM tokens WHERE slug = ?\").get(slug) as\n | Token\n | undefined;\n}\n\n/**\n * Look up a token by its ULID.\n * Returns undefined if not found.\n */\nexport function getTokenById(db: Database, id: string): Token | undefined {\n return db.prepare(\"SELECT * FROM tokens WHERE id = ?\").get(id) as\n | Token\n | undefined;\n}\n\n/**\n * Update mutable fields on a token.\n *\n * Slug is intentionally immutable in v1 because it is referenced by other\n * parts of the system (for example agent skill metadata).\n */\nexport function updateToken(\n db: Database,\n slug: string,\n updates: UpdateTokenInput,\n): Token {\n const token = getTokenBySlug(db, slug);\n if (!token) {\n throw new Error(`Token not found: ${slug}`);\n }\n\n const fields: string[] = [];\n const values: unknown[] = [];\n\n if (updates.concept !== undefined) {\n fields.push(\"concept = ?\");\n values.push(updates.concept);\n }\n if (updates.domain !== undefined) {\n fields.push(\"domain = ?\");\n values.push(updates.domain);\n }\n if (updates.bloom_level !== undefined) {\n if (updates.bloom_level < 1 || updates.bloom_level > 5) {\n throw new Error(\n `bloom_level must be between 1 and 5, got ${updates.bloom_level}`,\n );\n }\n fields.push(\"bloom_level = ?\");\n values.push(updates.bloom_level);\n }\n if (updates.context !== undefined) {\n fields.push(\"context = ?\");\n values.push(updates.context);\n }\n if (updates.symbiosis_mode !== undefined) {\n const validModes = [\"shadowing\", \"copilot\", \"autonomy\"];\n if (\n updates.symbiosis_mode !== null &&\n !validModes.includes(updates.symbiosis_mode)\n ) {\n throw new Error(`Invalid symbiosis_mode: ${updates.symbiosis_mode}`);\n }\n fields.push(\"symbiosis_mode = ?\");\n values.push(updates.symbiosis_mode);\n }\n if (updates.source_link !== undefined) {\n fields.push(\"source_link = ?\");\n values.push(updates.source_link);\n }\n if (updates.question !== undefined) {\n fields.push(\"question = ?\");\n values.push(updates.question);\n }\n\n if (fields.length === 0) {\n throw new Error(\"updateToken called with no fields to update\");\n }\n\n fields.push(\"updated_at = ?\");\n values.push(new Date().toISOString());\n values.push(slug);\n\n db.prepare(`UPDATE tokens SET ${fields.join(\", \")} WHERE slug = ?`).run(\n ...values,\n );\n return getTokenBySlug(db, slug)!;\n}\n\n/**\n * Mark a token as deprecated. Deprecated tokens are excluded from review queues\n * and search results but are not deleted — they can still be consulted.\n *\n * Throws if the token does not exist or is already deprecated.\n */\nexport function deprecateToken(db: Database, slug: string): Token {\n const token = getTokenBySlug(db, slug);\n if (!token) {\n throw new Error(`Token not found: ${slug}`);\n }\n if (token.deprecated_at) {\n throw new Error(`Token already deprecated: ${slug}`);\n }\n\n const now = new Date().toISOString();\n db.prepare(\n \"UPDATE tokens SET deprecated_at = ?, updated_at = ? WHERE slug = ?\",\n ).run(now, now, slug);\n\n return getTokenBySlug(db, slug)!;\n}\n\n/**\n * Preview the rows that will be removed or updated when deleting a token.\n */\nexport function getTokenDeleteImpact(\n db: Database,\n slug: string,\n): TokenDeleteImpact {\n const token = getTokenBySlug(db, slug);\n if (!token) {\n throw new Error(`Token not found: ${slug}`);\n }\n\n const cards = db\n .prepare(\"SELECT COUNT(*) AS n FROM cards WHERE token_id = ?\")\n .get(token.id) as { n: number };\n const reviewLogs = db\n .prepare(\"SELECT COUNT(*) AS n FROM review_logs WHERE token_id = ?\")\n .get(token.id) as { n: number };\n const prereqsFrom = db\n .prepare(\"SELECT COUNT(*) AS n FROM prerequisites WHERE token_id = ?\")\n .get(token.id) as { n: number };\n const prereqsTo = db\n .prepare(\"SELECT COUNT(*) AS n FROM prerequisites WHERE requires_id = ?\")\n .get(token.id) as { n: number };\n const sessionSteps = db\n .prepare(\"SELECT COUNT(*) AS n FROM session_steps WHERE token_id = ?\")\n .get(token.id) as { n: number };\n const sessionsTouched = db\n .prepare(\n \"SELECT COUNT(DISTINCT session_id) AS n FROM session_steps WHERE token_id = ?\",\n )\n .get(token.id) as { n: number };\n\n const skillRows = db\n .prepare(\"SELECT token_slugs FROM agent_skills\")\n .all() as Array<{ token_slugs: string }>;\n const agentSkills = skillRows.filter((row) => {\n const tokenSlugs = JSON.parse(row.token_slugs) as string[];\n return tokenSlugs.includes(slug);\n }).length;\n\n return {\n cards: cards.n,\n review_logs: reviewLogs.n,\n prerequisite_edges_from_token: prereqsFrom.n,\n prerequisite_edges_to_token: prereqsTo.n,\n session_steps: sessionSteps.n,\n sessions_touched: sessionsTouched.n,\n agent_skills: agentSkills,\n };\n}\n\n/**\n * Hard-delete a token and clean up non-FK references that point at its slug.\n */\nexport function deleteToken(db: Database, slug: string): DeleteTokenResult {\n const token = getTokenBySlug(db, slug);\n if (!token) {\n throw new Error(`Token not found: ${slug}`);\n }\n\n const impact = getTokenDeleteImpact(db, slug);\n\n db.exec(\"BEGIN\");\n try {\n const now = new Date().toISOString();\n const skillRows = db\n .prepare(\"SELECT id, token_slugs FROM agent_skills\")\n .all() as Array<{ id: string; token_slugs: string }>;\n\n for (const row of skillRows) {\n const tokenSlugs = JSON.parse(row.token_slugs) as string[];\n const filtered = tokenSlugs.filter((tokenSlug) => tokenSlug !== slug);\n if (filtered.length !== tokenSlugs.length) {\n db.prepare(\n \"UPDATE agent_skills SET token_slugs = ?, updated_at = ? WHERE id = ?\",\n ).run(JSON.stringify(filtered), now, row.id);\n }\n }\n\n db.prepare(\"DELETE FROM tokens WHERE id = ?\").run(token.id);\n db.exec(\"COMMIT\");\n } catch (err) {\n db.exec(\"ROLLBACK\");\n throw err;\n }\n\n return { token, impact };\n}\n\n/**\n * Fuzzy search for tokens by keyword query.\n *\n * Ported from the PoC's find-token command: splits the query into word\n * tokens, scores each database token by word overlap plus a substring\n * bonus on the concept field, and returns all matches sorted by score\n * descending.\n */\nexport function findTokens(db: Database, query: string): ScoredToken[] {\n const normalised = query.toLowerCase();\n const qTokens = new Set(\n normalised.split(/[\\s,.\\-_/\\\\:;!?()[\\]{}]+/).filter((t) => t.length > 2),\n );\n\n const tokens = db\n .prepare(\"SELECT * FROM tokens WHERE deprecated_at IS NULL\")\n .all() as Token[];\n\n const scored: ScoredToken[] = [];\n\n for (const t of tokens) {\n const words = `${t.slug} ${t.concept} ${t.domain}`\n .toLowerCase()\n .split(/[\\s,.\\-_/\\\\:;!?()[\\]{}]+/)\n .filter(Boolean);\n\n let score = 0;\n for (const w of words) {\n if (qTokens.has(w)) score++;\n }\n\n // Substring bonus: if the concept contains the start of the query\n if (t.concept.toLowerCase().includes(normalised.slice(0, 25))) {\n score += 3;\n }\n\n if (score > 0) {\n scored.push({ score, ...t });\n }\n }\n\n scored.sort((a, b) => b.score - a.score);\n return scored;\n}\n\n/**\n * List all tokens, optionally filtered by domain.\n * Results are ordered by bloom_level then slug.\n */\nexport function listTokens(db: Database, options?: ListTokensOptions): Token[] {\n if (options?.domain) {\n return db\n .prepare(\n \"SELECT * FROM tokens WHERE domain = ? AND deprecated_at IS NULL ORDER BY bloom_level, slug\",\n )\n .all(options.domain) as Token[];\n }\n return db\n .prepare(\n \"SELECT * FROM tokens WHERE deprecated_at IS NULL ORDER BY bloom_level, domain, slug\",\n )\n .all() as Token[];\n}\n","/**\n * Monitor log analyzer — maps observed shell commands to token ratings.\n *\n * Pure functions, no DB or filesystem access. Takes parsed command records\n * and a token-to-pattern mapping, returns ratings with evidence.\n */\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface MonitorEvent {\n type: \"command_start\" | \"command_end\" | \"monitor_meta\";\n ts: string;\n seq?: number;\n pid?: number;\n command?: string;\n cwd?: string;\n exit_code?: number;\n event?: \"start\" | \"stop\";\n session_id?: string;\n shell?: string;\n}\n\nexport interface CommandRecord {\n seq: number;\n pid: number;\n command: string;\n cwd: string;\n startedAt: string;\n endedAt: string | null;\n durationMs: number | null;\n exitCode: number | null;\n}\n\nexport interface TokenPattern {\n slug: string;\n patterns: string[]; // command prefixes or regex strings\n}\n\nexport interface ObservationRating {\n tokenSlug: string;\n rating: 1 | 2 | 3 | 4 | null;\n confidence: \"high\" | \"medium\" | \"low\";\n evidence: {\n matchedCommands: number;\n helpSeeking: boolean;\n errorCount: number;\n selfCorrections: number;\n medianGapMs: number | null;\n thinkingGapMs: number | null;\n };\n matchedCommandTexts: string[];\n}\n\nexport interface AnalysisResult {\n ratings: ObservationRating[];\n unmatchedCommands: string[];\n timeSpan: { start: string; end: string; durationMs: number } | null;\n}\n\n// ── Parsing ──────────────────────────────────────────────────────────────────\n\n/**\n * Parse a JSONL string into MonitorEvent objects.\n * Skips malformed lines silently.\n */\nexport function parseMonitorLog(jsonl: string): MonitorEvent[] {\n const events: MonitorEvent[] = [];\n for (const line of jsonl.split(\"\\n\")) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n try {\n events.push(JSON.parse(trimmed) as MonitorEvent);\n } catch {\n // skip malformed lines\n }\n }\n return events;\n}\n\n/**\n * Pair command_start and command_end events by (pid, seq) into CommandRecords.\n */\nexport function pairCommands(events: MonitorEvent[]): CommandRecord[] {\n const starts = new Map<string, MonitorEvent>();\n const records: CommandRecord[] = [];\n\n for (const e of events) {\n if (e.type === \"command_start\" && e.seq != null) {\n const key = `${e.pid ?? 0}:${e.seq}`;\n starts.set(key, e);\n } else if (e.type === \"command_end\" && e.seq != null) {\n const key = `${e.pid ?? 0}:${e.seq}`;\n const start = starts.get(key);\n if (start) {\n const startMs = new Date(start.ts).getTime();\n const endMs = new Date(e.ts).getTime();\n records.push({\n seq: e.seq,\n pid: e.pid ?? 0,\n command: start.command ?? \"\",\n cwd: start.cwd ?? \"\",\n startedAt: start.ts,\n endedAt: e.ts,\n durationMs: endMs - startMs,\n exitCode: e.exit_code ?? null,\n });\n starts.delete(key);\n }\n }\n }\n\n // Remaining unpaired starts (monitoring stopped mid-command)\n for (const [, start] of starts) {\n records.push({\n seq: start.seq ?? 0,\n pid: start.pid ?? 0,\n command: start.command ?? \"\",\n cwd: start.cwd ?? \"\",\n startedAt: start.ts,\n endedAt: null,\n durationMs: null,\n exitCode: null,\n });\n }\n\n records.sort(\n (a, b) => new Date(a.startedAt).getTime() - new Date(b.startedAt).getTime(),\n );\n return records;\n}\n\n// ── Analysis ─────────────────────────────────────────────────────────────────\n\nconst HELP_PATTERNS = [\"--help\", \"man \", \"tldr \", \"help \"];\nconst HELP_WINDOW_MS = 60_000;\nconst _RETRY_WINDOW_MS = 30_000;\n\nfunction matchesToken(command: string, patterns: string[]): boolean {\n const lower = command.toLowerCase();\n return patterns.some((p) => lower.includes(p.toLowerCase()));\n}\n\nfunction isHelpCommand(command: string): boolean {\n const lower = command.toLowerCase();\n return HELP_PATTERNS.some((p) => lower.includes(p));\n}\n\nfunction commandPrefix(command: string): string {\n return command.split(/\\s+/).slice(0, 2).join(\" \").toLowerCase();\n}\n\nfunction computeMedian(values: number[]): number | null {\n if (values.length === 0) return null;\n const sorted = [...values].sort((a, b) => a - b);\n const mid = Math.floor(sorted.length / 2);\n return sorted.length % 2 !== 0\n ? sorted[mid]\n : (sorted[mid - 1] + sorted[mid]) / 2;\n}\n\n/**\n * Analyze observed commands against token patterns and produce ratings.\n */\nexport function analyzeObservation(\n commands: CommandRecord[],\n tokenPatterns: TokenPattern[],\n): AnalysisResult {\n const matchedSet = new Set<number>(); // indices of commands matched to any token\n const ratings: ObservationRating[] = [];\n\n for (const tp of tokenPatterns) {\n const matchIndices: number[] = [];\n const matchedTexts: string[] = [];\n\n for (let i = 0; i < commands.length; i++) {\n if (matchesToken(commands[i].command, tp.patterns)) {\n matchIndices.push(i);\n matchedTexts.push(commands[i].command);\n matchedSet.add(i);\n }\n }\n\n if (matchIndices.length === 0) {\n ratings.push({\n tokenSlug: tp.slug,\n rating: null,\n confidence: \"low\",\n evidence: {\n matchedCommands: 0,\n helpSeeking: false,\n errorCount: 0,\n selfCorrections: 0,\n medianGapMs: null,\n thinkingGapMs: null,\n },\n matchedCommandTexts: [],\n });\n continue;\n }\n\n // Help-seeking: any help command within HELP_WINDOW_MS before a matched command\n let helpSeeking = false;\n for (const mi of matchIndices) {\n const matchTime = new Date(commands[mi].startedAt).getTime();\n for (let j = 0; j < commands.length; j++) {\n if (j === mi) continue;\n const cmdTime = new Date(commands[j].startedAt).getTime();\n if (cmdTime >= matchTime - HELP_WINDOW_MS && cmdTime < matchTime) {\n if (isHelpCommand(commands[j].command)) {\n helpSeeking = true;\n break;\n }\n }\n }\n if (helpSeeking) break;\n }\n\n // Error count: matched commands with non-zero exit code\n let errorCount = 0;\n for (const mi of matchIndices) {\n if (commands[mi].exitCode != null && commands[mi].exitCode !== 0) {\n errorCount++;\n }\n }\n\n // Self-corrections: same command prefix run multiple times with different args\n let selfCorrections = 0;\n const prefixGroups = new Map<string, number>();\n for (const mi of matchIndices) {\n const prefix = commandPrefix(commands[mi].command);\n prefixGroups.set(prefix, (prefixGroups.get(prefix) ?? 0) + 1);\n }\n for (const count of prefixGroups.values()) {\n if (count > 1) selfCorrections += count - 1;\n }\n\n // Speed: inter-command gaps between matched commands\n const gaps: number[] = [];\n for (let k = 1; k < matchIndices.length; k++) {\n const prev = commands[matchIndices[k - 1]];\n const curr = commands[matchIndices[k]];\n if (prev.endedAt) {\n const gap =\n new Date(curr.startedAt).getTime() - new Date(prev.endedAt).getTime();\n if (gap >= 0) gaps.push(gap);\n }\n }\n\n // Thinking gap: time before first matched command from previous command's end\n let thinkingGapMs: number | null = null;\n const firstMatchIdx = matchIndices[0];\n if (firstMatchIdx > 0) {\n const prev = commands[firstMatchIdx - 1];\n if (prev.endedAt) {\n thinkingGapMs =\n new Date(commands[firstMatchIdx].startedAt).getTime() -\n new Date(prev.endedAt).getTime();\n }\n }\n\n const medianGapMs = computeMedian(gaps);\n\n // Determine rating\n const rating = inferRating({\n helpSeeking,\n errorCount,\n selfCorrections,\n medianGapMs,\n thinkingGapMs,\n matchedCommands: matchIndices.length,\n });\n\n // Confidence: more matched commands = higher confidence\n const confidence =\n matchIndices.length >= 3\n ? \"high\"\n : matchIndices.length >= 2\n ? \"medium\"\n : \"low\";\n\n ratings.push({\n tokenSlug: tp.slug,\n rating,\n confidence,\n evidence: {\n matchedCommands: matchIndices.length,\n helpSeeking,\n errorCount,\n selfCorrections,\n medianGapMs,\n thinkingGapMs,\n },\n matchedCommandTexts: matchedTexts,\n });\n }\n\n // Unmatched commands\n const unmatchedCommands: string[] = [];\n for (let i = 0; i < commands.length; i++) {\n if (!matchedSet.has(i) && !isHelpCommand(commands[i].command)) {\n unmatchedCommands.push(commands[i].command);\n }\n }\n\n // Time span\n let timeSpan: AnalysisResult[\"timeSpan\"] = null;\n if (commands.length > 0) {\n const first = commands[0];\n const last = commands[commands.length - 1];\n const endTs = last.endedAt ?? last.startedAt;\n timeSpan = {\n start: first.startedAt,\n end: endTs,\n durationMs:\n new Date(endTs).getTime() - new Date(first.startedAt).getTime(),\n };\n }\n\n return { ratings, unmatchedCommands, timeSpan };\n}\n\n// ── Rating Inference ─────────────────────────────────────────────────────────\n\ninterface RatingSignals {\n helpSeeking: boolean;\n errorCount: number;\n selfCorrections: number;\n medianGapMs: number | null;\n thinkingGapMs: number | null;\n matchedCommands: number;\n}\n\nfunction inferRating(signals: RatingSignals): 1 | 2 | 3 | 4 {\n const {\n helpSeeking,\n errorCount,\n selfCorrections,\n medianGapMs,\n thinkingGapMs,\n } = signals;\n\n // Count negative signals\n let negatives = 0;\n if (helpSeeking) negatives += 2;\n if (errorCount >= 3) negatives += 3;\n else if (errorCount >= 1) negatives += 1;\n if (selfCorrections >= 2) negatives += 2;\n else if (selfCorrections >= 1) negatives += 1;\n if (medianGapMs != null && medianGapMs > 30_000) negatives += 2;\n else if (medianGapMs != null && medianGapMs > 10_000) negatives += 1;\n if (thinkingGapMs != null && thinkingGapMs > 30_000) negatives += 1;\n\n if (negatives >= 5) return 1;\n if (negatives >= 3) return 2;\n if (negatives >= 1) return 3;\n return 4;\n}\n","/**\n * Monitor I/O — read/write JSONL files for shell observation.\n *\n * Monitor logs live at ~/.zam/monitor/<session-id>.jsonl.\n * Separated from analyzer.ts so the analyzer remains pure-function testable.\n */\n\nimport {\n appendFileSync,\n existsSync,\n mkdirSync,\n readFileSync,\n statSync,\n} from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { MonitorEvent } from \"./analyzer.js\";\nimport { parseMonitorLog } from \"./analyzer.js\";\n\nconst MONITOR_DIR = join(homedir(), \".zam\", \"monitor\");\n\n/** Get the monitor directory path. */\nexport function getMonitorDir(): string {\n return MONITOR_DIR;\n}\n\n/** Get the JSONL file path for a session. */\nexport function getMonitorPath(sessionId: string): string {\n return join(MONITOR_DIR, `${sessionId}.jsonl`);\n}\n\n/** Ensure the monitor directory exists (mode 0700 for privacy). */\nexport function ensureMonitorDir(): void {\n if (!existsSync(MONITOR_DIR)) {\n mkdirSync(MONITOR_DIR, { recursive: true, mode: 0o700 });\n }\n}\n\n/** Append a single event to the session's JSONL file. */\nexport function writeMonitorEvent(\n sessionId: string,\n event: MonitorEvent,\n): void {\n ensureMonitorDir();\n const path = getMonitorPath(sessionId);\n appendFileSync(path, `${JSON.stringify(event)}\\n`);\n}\n\n/** Read and parse all events from a session's monitor log. */\nexport function readMonitorLog(sessionId: string): MonitorEvent[] {\n const path = getMonitorPath(sessionId);\n if (!existsSync(path)) {\n return [];\n }\n const content = readFileSync(path, \"utf-8\");\n return parseMonitorLog(content);\n}\n\n/** Check if a monitor log exists for a session. */\nexport function monitorLogExists(sessionId: string): boolean {\n return existsSync(getMonitorPath(sessionId));\n}\n\n/** Get basic stats about a monitor log without full parsing. */\nexport function getMonitorLogStats(sessionId: string): {\n exists: boolean;\n sizeBytes: number;\n lineCount: number;\n} {\n const path = getMonitorPath(sessionId);\n if (!existsSync(path)) {\n return { exists: false, sizeBytes: 0, lineCount: 0 };\n }\n const stat = statSync(path);\n const content = readFileSync(path, \"utf-8\");\n const lineCount = content.split(\"\\n\").filter((l) => l.trim()).length;\n return { exists: true, sizeBytes: stat.size, lineCount };\n}\n","/**\n * Shell hook code generation for zsh, bash, and PowerShell.\n *\n * Pure functions that return shell code strings. The CLI command\n * `zam monitor start/stop` calls these and prints to stdout.\n */\n\nfunction psSingleQuoted(value: string): string {\n return `'${value.replace(/'/g, \"''\")}'`;\n}\n\n/**\n * Generate zsh hooks that capture commands to a JSONL file.\n * Uses $EPOCHREALTIME for sub-second timestamp precision.\n */\nexport function generateZshHooks(\n monitorFile: string,\n sessionId: string,\n): string {\n return `\n# ZAM monitor hooks for session ${sessionId}\nexport __ZAM_MONITOR_FILE=\"${monitorFile}\"\nexport __ZAM_MONITOR_SEQ=0\nexport __ZAM_MONITOR_SESSION=\"${sessionId}\"\n\n__zam_ts() {\n if [[ -n \"\\${EPOCHREALTIME:-}\" ]]; then\n local sec=\"\\${EPOCHREALTIME%%.*}\"\n local frac=\"\\${EPOCHREALTIME##*.}\"\n frac=\"\\${frac:0:3}\"\n printf '%s.%sZ' \"$(date -u -r \"$sec\" '+%Y-%m-%dT%H:%M:%S' 2>/dev/null || date -u '+%Y-%m-%dT%H:%M:%S')\" \"$frac\"\n else\n date -u '+%Y-%m-%dT%H:%M:%SZ'\n fi\n}\n\n__zam_preexec() {\n (( __ZAM_MONITOR_SEQ++ ))\n local cmd=\"\\${1//\\\\\"/\\\\\\\\\\\\\"}\"\n local cwd=\"\\${PWD//\\\\\"/\\\\\\\\\\\\\"}\"\n local ts=\"$(__zam_ts)\"\n printf '{\"type\":\"command_start\",\"ts\":\"%s\",\"command\":\"%s\",\"cwd\":\"%s\",\"seq\":%d,\"pid\":%d}\\\\n' \\\\\n \"$ts\" \"$cmd\" \"$cwd\" \"$__ZAM_MONITOR_SEQ\" \"$$\" \\\\\n >> \"$__ZAM_MONITOR_FILE\"\n}\n\n__zam_precmd() {\n local exit_code=$?\n [[ $__ZAM_MONITOR_SEQ -eq 0 ]] && return\n local ts=\"$(__zam_ts)\"\n printf '{\"type\":\"command_end\",\"ts\":\"%s\",\"exit_code\":%d,\"seq\":%d,\"pid\":%d}\\\\n' \\\\\n \"$ts\" \"$exit_code\" \"$__ZAM_MONITOR_SEQ\" \"$$\" \\\\\n >> \"$__ZAM_MONITOR_FILE\"\n}\n\nautoload -Uz add-zsh-hook\nadd-zsh-hook preexec __zam_preexec\nadd-zsh-hook precmd __zam_precmd\n\necho \"ZAM monitor active for session $__ZAM_MONITOR_SESSION\"\n`.trim();\n}\n\n/**\n * Generate bash hooks that capture commands to a JSONL file.\n * Uses DEBUG trap for preexec, PROMPT_COMMAND for precmd.\n */\nexport function generateBashHooks(\n monitorFile: string,\n sessionId: string,\n): string {\n return `\n# ZAM monitor hooks for session ${sessionId}\nexport __ZAM_MONITOR_FILE=\"${monitorFile}\"\nexport __ZAM_MONITOR_SEQ=0\nexport __ZAM_MONITOR_SESSION=\"${sessionId}\"\nexport __ZAM_MONITOR_CMD_ACTIVE=0\n\n__zam_ts() {\n date -u '+%Y-%m-%dT%H:%M:%SZ'\n}\n\n__zam_debug_trap() {\n [[ \"$__ZAM_MONITOR_CMD_ACTIVE\" -eq 1 ]] && return\n __ZAM_MONITOR_CMD_ACTIVE=1\n (( __ZAM_MONITOR_SEQ++ ))\n local cmd=\"\\${BASH_COMMAND//\\\\\"/\\\\\\\\\\\\\"}\"\n local cwd=\"\\${PWD//\\\\\"/\\\\\\\\\\\\\"}\"\n local ts=\"$(__zam_ts)\"\n printf '{\"type\":\"command_start\",\"ts\":\"%s\",\"command\":\"%s\",\"cwd\":\"%s\",\"seq\":%d,\"pid\":%d}\\\\n' \\\\\n \"$ts\" \"$cmd\" \"$cwd\" \"$__ZAM_MONITOR_SEQ\" \"$$\" \\\\\n >> \"$__ZAM_MONITOR_FILE\"\n}\n\n__zam_prompt_cmd() {\n local exit_code=$?\n if [[ \"$__ZAM_MONITOR_CMD_ACTIVE\" -eq 1 ]]; then\n __ZAM_MONITOR_CMD_ACTIVE=0\n local ts=\"$(__zam_ts)\"\n printf '{\"type\":\"command_end\",\"ts\":\"%s\",\"exit_code\":%d,\"seq\":%d,\"pid\":%d}\\\\n' \\\\\n \"$ts\" \"$exit_code\" \"$__ZAM_MONITOR_SEQ\" \"$$\" \\\\\n >> \"$__ZAM_MONITOR_FILE\"\n fi\n}\n\ntrap '__zam_debug_trap' DEBUG\nPROMPT_COMMAND=\"__zam_prompt_cmd;\\${PROMPT_COMMAND:-}\"\n\necho \"ZAM monitor active for session $__ZAM_MONITOR_SESSION\"\n`.trim();\n}\n\n/**\n * Generate PowerShell hooks that capture completed commands to a JSONL file.\n * PowerShell has no zsh-style preexec hook, so this records the most recent\n * history item from the prompt function after each command completes.\n */\nexport function generatePowerShellHooks(\n monitorFile: string,\n sessionId: string,\n): string {\n return `\n# ZAM monitor hooks for session ${sessionId}\n$global:__ZAM_MONITOR_FILE = ${psSingleQuoted(monitorFile)}\n$global:__ZAM_MONITOR_SEQ = 0\n$global:__ZAM_MONITOR_SESSION = ${psSingleQuoted(sessionId)}\n$global:__ZAM_MONITOR_SKIP_NEXT_PROMPT = $true\n\nfunction global:__zam_write_monitor_event {\n param([hashtable]$Event)\n $json = $Event | ConvertTo-Json -Compress -Depth 4\n $utf8NoBom = New-Object System.Text.UTF8Encoding $false\n [System.IO.File]::AppendAllText($global:__ZAM_MONITOR_FILE, $json + [Environment]::NewLine, $utf8NoBom)\n}\n\nfunction global:__zam_iso_utc {\n param([datetime]$Date)\n if ($Date -eq [datetime]::MinValue) {\n return (Get-Date).ToUniversalTime().ToString(\"o\")\n }\n return $Date.ToUniversalTime().ToString(\"o\")\n}\n\nfunction global:__zam_update_last_history_id {\n $history = Get-History -Count 1\n if ($null -ne $history) {\n $global:__ZAM_MONITOR_LAST_HISTORY_ID = $history.Id\n } elseif ($null -eq $global:__ZAM_MONITOR_LAST_HISTORY_ID) {\n $global:__ZAM_MONITOR_LAST_HISTORY_ID = 0\n }\n}\n\nfunction global:__zam_record_last_history {\n param(\n [bool]$Success,\n [object]$NativeExitCode\n )\n\n $history = Get-History -Count 1\n if ($null -eq $history) { return }\n if ($history.Id -le $global:__ZAM_MONITOR_LAST_HISTORY_ID) { return }\n\n $global:__ZAM_MONITOR_LAST_HISTORY_ID = $history.Id\n $global:__ZAM_MONITOR_SEQ += 1\n\n $exitCode = 0\n if (-not $Success) {\n if ($NativeExitCode -is [int] -and $NativeExitCode -ne 0) {\n $exitCode = $NativeExitCode\n } else {\n $exitCode = 1\n }\n }\n\n $cwd = (Get-Location).Path\n __zam_write_monitor_event @{\n type = \"command_start\"\n ts = (__zam_iso_utc $history.StartExecutionTime)\n command = $history.CommandLine\n cwd = $cwd\n seq = $global:__ZAM_MONITOR_SEQ\n pid = $PID\n }\n __zam_write_monitor_event @{\n type = \"command_end\"\n ts = (__zam_iso_utc $history.EndExecutionTime)\n exit_code = $exitCode\n seq = $global:__ZAM_MONITOR_SEQ\n pid = $PID\n }\n}\n\nif (-not (Test-Path function:\\\\__zam_previous_prompt) -and (Test-Path function:\\\\prompt)) {\n Set-Item -Path function:\\\\__zam_previous_prompt -Value (Get-Item function:\\\\prompt).ScriptBlock\n}\n__zam_update_last_history_id\n\nfunction global:prompt {\n $zamSuccess = $?\n $zamNativeExitCode = $global:LASTEXITCODE\n\n if ($global:__ZAM_MONITOR_SKIP_NEXT_PROMPT) {\n __zam_update_last_history_id\n $global:__ZAM_MONITOR_SKIP_NEXT_PROMPT = $false\n } else {\n __zam_record_last_history -Success $zamSuccess -NativeExitCode $zamNativeExitCode\n }\n\n if (Test-Path function:\\\\__zam_previous_prompt) {\n & (Get-Item function:\\\\__zam_previous_prompt).ScriptBlock\n } else {\n \"PS $($executionContext.SessionState.Path.CurrentLocation)$('>' * ($nestedPromptLevel + 1)) \"\n }\n}\n\nWrite-Host \"ZAM monitor active for session $global:__ZAM_MONITOR_SESSION\"\n`.trim();\n}\n\n/** Generate zsh code to remove monitor hooks. */\nexport function generateZshUnhooks(): string {\n return `\n# Remove ZAM monitor hooks\nadd-zsh-hook -d preexec __zam_preexec 2>/dev/null\nadd-zsh-hook -d precmd __zam_precmd 2>/dev/null\nunset -f __zam_preexec __zam_precmd __zam_ts 2>/dev/null\nunset __ZAM_MONITOR_FILE __ZAM_MONITOR_SEQ __ZAM_MONITOR_SESSION 2>/dev/null\necho \"ZAM monitor stopped.\"\n`.trim();\n}\n\n/** Generate bash code to remove monitor hooks. */\nexport function generateBashUnhooks(): string {\n return `\n# Remove ZAM monitor hooks\ntrap - DEBUG\nPROMPT_COMMAND=\"\\${PROMPT_COMMAND/__zam_prompt_cmd;/}\"\nunset -f __zam_debug_trap __zam_prompt_cmd __zam_ts 2>/dev/null\nunset __ZAM_MONITOR_FILE __ZAM_MONITOR_SEQ __ZAM_MONITOR_SESSION __ZAM_MONITOR_CMD_ACTIVE 2>/dev/null\necho \"ZAM monitor stopped.\"\n`.trim();\n}\n\n/** Generate PowerShell code to remove monitor hooks. */\nexport function generatePowerShellUnhooks(): string {\n return `\n# Remove ZAM monitor hooks\nif (Test-Path function:\\\\__zam_previous_prompt) {\n Set-Item -Path function:\\\\prompt -Value (Get-Item function:\\\\__zam_previous_prompt).ScriptBlock\n Remove-Item function:\\\\__zam_previous_prompt -Force -ErrorAction SilentlyContinue\n}\nRemove-Item function:\\\\__zam_write_monitor_event,function:\\\\__zam_iso_utc,function:\\\\__zam_update_last_history_id,function:\\\\__zam_record_last_history -ErrorAction SilentlyContinue\nRemove-Variable -Name __ZAM_MONITOR_FILE,__ZAM_MONITOR_SEQ,__ZAM_MONITOR_SESSION,__ZAM_MONITOR_LAST_HISTORY_ID,__ZAM_MONITOR_SKIP_NEXT_PROMPT -Scope Global -ErrorAction SilentlyContinue\nWrite-Host \"ZAM monitor stopped.\"\n`.trim();\n}\n","/**\n * Skill Discovery — identifies recurring non-standard command patterns\n * across multiple sessions and proposes them as minimal reusable skills.\n *\n * The key insight from Increment 2: \"The human's demonstrated competence\n * is the gate for automation — not the other way around.\" A pattern must\n * appear consistently across sessions before being proposed as a skill.\n *\n * Pure functions — no DB access. Callers provide command records and\n * existing skills; this module returns proposed skills.\n */\n\nimport type { CommandRecord } from \"./analyzer.js\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface CommandSequence {\n /** The ordered command prefixes forming the pattern (e.g., [\"git checkout\", \"npm install\", \"npm run build\"]) */\n steps: string[];\n /** How many sessions contained this sequence */\n sessionCount: number;\n /** Total occurrences across all sessions */\n totalOccurrences: number;\n /** Example full commands from the most recent occurrence */\n examples: string[];\n}\n\nexport interface SkillProposal {\n /** Suggested slug for the skill */\n slug: string;\n /** Human-readable description of what the pattern does */\n description: string;\n /** The command steps forming the skill */\n steps: string[];\n /** How many sessions demonstrated this pattern */\n sessionCount: number;\n /** Confidence that this is a real, repeatable skill */\n confidence: \"high\" | \"medium\" | \"low\";\n /** Example commands from actual usage */\n examples: string[];\n}\n\nexport interface DiscoveryOptions {\n /** Minimum number of sessions a pattern must appear in (default: 2) */\n minSessions?: number;\n /** Minimum sequence length to consider (default: 2) */\n minSequenceLength?: number;\n /** Maximum sequence length to consider (default: 5) */\n maxSequenceLength?: number;\n /** Existing skill slugs to exclude from proposals */\n existingSkillSlugs?: string[];\n}\n\n// ── Discovery ────────────────────────────────────────────────────────────────\n\n/**\n * Discover recurring command patterns across multiple sessions.\n *\n * Takes a map of session ID → command records, finds command sequences\n * that appear in multiple sessions, and proposes them as skills.\n *\n * @param sessionCommands - Map of session ID to that session's commands\n * @param options - Discovery configuration\n * @returns Array of skill proposals, sorted by confidence then session count\n */\nexport function discoverSkills(\n sessionCommands: Map<string, CommandRecord[]>,\n options: DiscoveryOptions = {},\n): SkillProposal[] {\n const minSessions = options.minSessions ?? 2;\n const minLen = options.minSequenceLength ?? 2;\n const maxLen = options.maxSequenceLength ?? 5;\n const existing = new Set(options.existingSkillSlugs ?? []);\n\n // Step 1: Extract normalized command sequences from each session\n const sessionSequences = new Map<string, string[][]>();\n for (const [sessionId, commands] of sessionCommands) {\n const sequences = extractSequences(commands, minLen, maxLen);\n if (sequences.length > 0) {\n sessionSequences.set(sessionId, sequences);\n }\n }\n\n // Step 2: Count how many sessions contain each unique sequence\n const sequenceIndex = new Map<string, CommandSequence>();\n\n for (const [, sequences] of sessionSequences) {\n // Deduplicate within a session — count each sequence once per session\n const seen = new Set<string>();\n for (const seq of sequences) {\n const key = seq.join(\" → \");\n if (seen.has(key)) continue;\n seen.add(key);\n\n const entry = sequenceIndex.get(key);\n if (entry) {\n entry.sessionCount++;\n entry.totalOccurrences++;\n } else {\n sequenceIndex.set(key, {\n steps: seq,\n sessionCount: 1,\n totalOccurrences: 1,\n examples: [],\n });\n }\n }\n }\n\n // Step 3: Collect examples from the most recent session for qualifying sequences\n const lastSessionId = [...sessionCommands.keys()].pop();\n if (lastSessionId) {\n const lastCommands = sessionCommands.get(lastSessionId)!;\n for (const [_key, entry] of sequenceIndex) {\n if (entry.sessionCount >= minSessions) {\n entry.examples = findExamplesForSequence(lastCommands, entry.steps);\n }\n }\n }\n\n // Step 4: Filter to patterns that appear in enough sessions\n const candidates = [...sequenceIndex.values()].filter(\n (s) => s.sessionCount >= minSessions,\n );\n\n // Step 5: Remove subsequences of longer patterns (prefer maximal patterns)\n const pruned = removeSubsequences(candidates);\n\n // Step 6: Convert to skill proposals\n const proposals: SkillProposal[] = [];\n for (const seq of pruned) {\n const slug = generateSlug(seq.steps);\n\n // Skip if this skill already exists\n if (existing.has(slug)) continue;\n\n proposals.push({\n slug,\n description: describeSequence(seq.steps),\n steps: seq.steps,\n sessionCount: seq.sessionCount,\n confidence:\n seq.sessionCount >= 4\n ? \"high\"\n : seq.sessionCount >= 3\n ? \"medium\"\n : \"low\",\n examples: seq.examples,\n });\n }\n\n // Sort: high confidence first, then by session count\n const confidenceOrder = { high: 0, medium: 1, low: 2 };\n proposals.sort((a, b) => {\n const confDiff =\n confidenceOrder[a.confidence] - confidenceOrder[b.confidence];\n if (confDiff !== 0) return confDiff;\n return b.sessionCount - a.sessionCount;\n });\n\n return proposals;\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\n/**\n * Normalize a command to its tool + subcommand prefix.\n * \"git checkout -b feat/foo\" → \"git checkout\"\n * \"npm run build\" → \"npm run build\"\n * \"docker compose up -d\" → \"docker compose up\"\n */\nfunction normalizeCommand(command: string): string {\n const parts = command.trim().split(/\\s+/);\n\n // Known multi-word tools\n const multiWord = [\"docker compose\", \"npm run\", \"npx\", \"git\"];\n const lower = command.toLowerCase();\n\n for (const mw of multiWord) {\n if (lower.startsWith(mw) && parts.length >= mw.split(\" \").length + 1) {\n return parts\n .slice(0, mw.split(\" \").length + 1)\n .join(\" \")\n .toLowerCase();\n }\n }\n\n // Default: first two words\n return parts.slice(0, Math.min(2, parts.length)).join(\" \").toLowerCase();\n}\n\n/**\n * Extract all command subsequences of length minLen..maxLen from a session.\n * Uses normalized command prefixes for comparison.\n */\nfunction extractSequences(\n commands: CommandRecord[],\n minLen: number,\n maxLen: number,\n): string[][] {\n // Filter out trivial commands\n const filtered = commands.filter((c) => {\n const lower = c.command.toLowerCase().trim();\n return (\n lower.length > 0 &&\n !lower.startsWith(\"cd \") &&\n lower !== \"cd\" &&\n lower !== \"ls\" &&\n lower !== \"pwd\" &&\n lower !== \"clear\" &&\n lower !== \"exit\" &&\n !lower.startsWith(\"echo \")\n );\n });\n\n const normalized = filtered.map((c) => normalizeCommand(c.command));\n const sequences: string[][] = [];\n\n for (let len = minLen; len <= maxLen; len++) {\n for (let i = 0; i <= normalized.length - len; i++) {\n const seq = normalized.slice(i, i + len);\n // Only include if at least 2 distinct commands (not just \"git commit\" repeated)\n if (new Set(seq).size >= 2) {\n sequences.push(seq);\n }\n }\n }\n\n return sequences;\n}\n\n/**\n * Find example full commands for a given normalized sequence in a command list.\n */\nfunction findExamplesForSequence(\n commands: CommandRecord[],\n steps: string[],\n): string[] {\n const normalized = commands.map((c) => ({\n norm: normalizeCommand(c.command),\n full: c.command,\n }));\n\n for (let i = 0; i <= normalized.length - steps.length; i++) {\n let match = true;\n for (let j = 0; j < steps.length; j++) {\n if (normalized[i + j].norm !== steps[j]) {\n match = false;\n break;\n }\n }\n if (match) {\n return normalized.slice(i, i + steps.length).map((n) => n.full);\n }\n }\n\n return [];\n}\n\n/**\n * Remove sequences that are strict subsequences of longer qualifying sequences.\n */\nfunction removeSubsequences(candidates: CommandSequence[]): CommandSequence[] {\n // Sort by length descending so we check long sequences first\n const sorted = [...candidates].sort(\n (a, b) => b.steps.length - a.steps.length,\n );\n const result: CommandSequence[] = [];\n\n for (const candidate of sorted) {\n const key = candidate.steps.join(\" → \");\n const isSubsequence = result.some((longer) => {\n const longerKey = longer.steps.join(\" → \");\n return longerKey.includes(key) && longerKey !== key;\n });\n\n if (!isSubsequence) {\n result.push(candidate);\n }\n }\n\n return result;\n}\n\n/**\n * Generate a slug from command steps.\n * [\"git checkout\", \"npm install\", \"npm run build\"] → \"checkout-install-build\"\n */\nfunction generateSlug(steps: string[]): string {\n return steps\n .map((s) => {\n const parts = s.split(/\\s+/);\n return parts[parts.length - 1]; // last word of each step\n })\n .join(\"-\");\n}\n\n/**\n * Generate a human-readable description of what a command sequence does.\n */\nfunction describeSequence(steps: string[]): string {\n return `Recurring pattern: ${steps.join(\" → \")}`;\n}\n","/**\n * Cascade Block & Unblock — prerequisite-aware blocking logic.\n *\n * Ported from the PoC's cascade-block and unblock-ready commands.\n *\n * When a user rates a token as \"forgot\" (rating 1) and that token has\n * prerequisites, we block the token and surface its prerequisites into\n * the active deck. When all prerequisites are met, we unblock.\n */\n\nimport type { Database } from \"libsql\";\nimport { ensureCard } from \"../models/card.js\";\nimport { getPrerequisites } from \"../models/prerequisite.js\";\nimport { getTokenBySlug } from \"../models/token.js\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface CascadeBlockResult {\n blockedSlug: string;\n prerequisites: Array<{ slug: string; concept: string; bloomLevel: number }>;\n}\n\nexport interface UnblockResult {\n unblocked: Array<{ slug: string; concept: string }>;\n}\n\n// ── Functions ────────────────────────────────────────────────────────────────\n\n/**\n * Block a token and surface its prerequisites.\n *\n * Called when a user rates a token as \"forgot\" (rating 1). The token is\n * marked as blocked so it won't appear in review queues. All direct\n * prerequisites are ensured to have cards (unblocked, due now) so they\n * appear in the user's next review session.\n *\n * @param db - Database connection\n * @param userId - The user whose card to block\n * @param tokenSlug - Slug of the token the user forgot\n * @returns Info about what was blocked and which prerequisites were surfaced\n */\nexport function cascadeBlock(\n db: Database,\n userId: string,\n tokenSlug: string,\n): CascadeBlockResult {\n const token = getTokenBySlug(db, tokenSlug);\n if (!token) {\n throw new Error(`Unknown token slug: ${tokenSlug}`);\n }\n\n // Ensure a card exists, then block it\n ensureCard(db, token.id, userId);\n db.prepare(\n \"UPDATE cards SET blocked = 1 WHERE token_id = ? AND user_id = ?\",\n ).run(token.id, userId);\n\n // Surface all direct prerequisites — ensure cards exist (unblocked, due now)\n const prereqs = getPrerequisites(db, token.id);\n const surfaced: Array<{ slug: string; concept: string; bloomLevel: number }> =\n [];\n\n for (const prereq of prereqs) {\n // ensureCard creates a new card if missing (defaults: blocked=0, due_at=now)\n const card = ensureCard(db, prereq.requires_id, userId);\n\n // If the prerequisite card was somehow blocked with no prereqs of its own,\n // make sure it's unblocked and due now so it surfaces\n if (card.blocked === 1) {\n const prereqOfPrereq = db\n .prepare(\"SELECT COUNT(*) as n FROM prerequisites WHERE token_id = ?\")\n .get(prereq.requires_id) as { n: number };\n\n // Only force-unblock if it has no prerequisites of its own\n if (prereqOfPrereq.n === 0) {\n const now = new Date().toISOString();\n db.prepare(\n \"UPDATE cards SET blocked = 0, due_at = ? WHERE token_id = ? AND user_id = ?\",\n ).run(now, prereq.requires_id, userId);\n }\n }\n\n surfaced.push({\n slug: prereq.slug,\n concept: prereq.concept,\n bloomLevel: prereq.bloom_level,\n });\n }\n\n return {\n blockedSlug: tokenSlug,\n prerequisites: surfaced,\n };\n}\n\n/**\n * Scan all blocked cards for a user and unblock any whose prerequisites are met.\n *\n * A blocked card is ready to unblock when ALL of its direct prerequisites have:\n * - reps >= 1 (the user has successfully recalled it at least once)\n * - blocked = 0 (the prerequisite itself is not blocked)\n *\n * If a blocked card has no prerequisites at all, it is unblocked immediately\n * (it was likely blocked in error or its prerequisites were removed).\n *\n * @param db - Database connection\n * @param userId - The user whose blocked cards to check\n * @returns List of cards that were unblocked\n */\nexport function unblockReady(db: Database, userId: string): UnblockResult {\n const blockedCards = db\n .prepare(\n `SELECT c.token_id, t.slug, t.concept\n FROM cards c\n JOIN tokens t ON t.id = c.token_id\n WHERE c.user_id = ? AND c.blocked = 1`,\n )\n .all(userId) as Array<{ token_id: string; slug: string; concept: string }>;\n\n const unblocked: Array<{ slug: string; concept: string }> = [];\n\n for (const card of blockedCards) {\n const totalPrereqs = db\n .prepare(\"SELECT COUNT(*) as n FROM prerequisites WHERE token_id = ?\")\n .get(card.token_id) as { n: number };\n\n const metPrereqs = db\n .prepare(\n `SELECT COUNT(*) as n FROM cards c\n JOIN prerequisites p ON p.requires_id = c.token_id\n WHERE p.token_id = ? AND c.user_id = ? AND c.reps >= 1 AND c.blocked = 0`,\n )\n .get(card.token_id, userId) as { n: number };\n\n if (totalPrereqs.n === 0 || metPrereqs.n === totalPrereqs.n) {\n const now = new Date().toISOString();\n db.prepare(\n \"UPDATE cards SET blocked = 0, due_at = ? WHERE token_id = ? AND user_id = ?\",\n ).run(now, card.token_id, userId);\n\n unblocked.push({ slug: card.slug, concept: card.concept });\n }\n }\n\n return { unblocked };\n}\n","/**\n * Rating Evaluator\n *\n * Processes a user's self-assessment rating after a recall attempt.\n * Coordinates between FSRS scheduling, review logging, and blocking.\n */\n\nimport type { Database } from \"libsql\";\nimport { ulid } from \"ulid\";\nimport { updateCard } from \"../models/card.js\";\nimport type { Rating, SchedulingCard } from \"../scheduler/fsrs.js\";\nimport { createFSRS } from \"../scheduler/fsrs.js\";\n\nexport interface EvaluateInput {\n cardId: string;\n tokenId: string;\n userId: string;\n rating: Rating;\n sessionId?: string;\n responseTimeMs?: number;\n}\n\nexport interface EvaluateResult {\n nextDueAt: string;\n stability: number;\n difficulty: number;\n state: string;\n scheduledDays: number;\n reps: number;\n lapses: number;\n}\n\n/**\n * Process a rating: update the card via FSRS, log the review.\n * Returns the updated scheduling state.\n *\n * Note: blocking logic (cascade-block) is handled separately by the caller\n * when rating === 1 and the token has prerequisites.\n */\nexport function evaluateRating(\n db: Database,\n input: EvaluateInput,\n): EvaluateResult {\n // Get current card state\n const card = db\n .prepare(\"SELECT * FROM cards WHERE id = ?\")\n .get(input.cardId) as\n | {\n stability: number;\n difficulty: number;\n elapsed_days: number;\n scheduled_days: number;\n reps: number;\n lapses: number;\n state: string;\n due_at: string;\n last_review_at: string | null;\n }\n | undefined;\n\n if (!card) {\n throw new Error(`Card not found: ${input.cardId}`);\n }\n\n const now = new Date();\n const fsrs = createFSRS();\n\n // Build scheduling card from DB state\n const schedulingCard: SchedulingCard = {\n stability: card.stability,\n difficulty: card.difficulty,\n elapsedDays: card.elapsed_days,\n scheduledDays: card.scheduled_days,\n reps: card.reps,\n lapses: card.lapses,\n state: card.state as SchedulingCard[\"state\"],\n dueAt: new Date(card.due_at),\n lastReviewAt: card.last_review_at ? new Date(card.last_review_at) : null,\n };\n\n // Run FSRS\n const updated = fsrs.schedule(schedulingCard, input.rating, now);\n\n // Update the card in the DB\n updateCard(db, input.cardId, {\n stability: updated.stability,\n difficulty: updated.difficulty,\n elapsed_days: updated.elapsedDays,\n scheduled_days: updated.scheduledDays,\n reps: updated.reps,\n lapses: updated.lapses,\n state: updated.state,\n due_at: updated.dueAt.toISOString(),\n last_review_at: now.toISOString(),\n });\n\n // Log the review (immutable)\n db.prepare(\n `INSERT INTO review_logs (id, card_id, token_id, user_id, rating, response_time_ms, reviewed_at, scheduled_at, session_id)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n ).run(\n ulid(),\n input.cardId,\n input.tokenId,\n input.userId,\n input.rating,\n input.responseTimeMs ?? null,\n now.toISOString(),\n card.due_at,\n input.sessionId ?? null,\n );\n\n return {\n nextDueAt: updated.dueAt.toISOString(),\n stability: updated.stability,\n difficulty: updated.difficulty,\n state: updated.state,\n scheduledDays: updated.scheduledDays,\n reps: updated.reps,\n lapses: updated.lapses,\n };\n}\n","/**\n * FSRS-5 — Free Spaced Repetition Scheduler (v5)\n *\n * Pure-function implementation of the FSRS algorithm that replaces\n * the PoC's SM-2 scheduler. This is the mathematical heart of ZAM's\n * spaced-repetition engine.\n *\n * Reference: https://github.com/open-spaced-repetition/fsrs4anki/wiki/The-Algorithm\n */\n\n// ── Rating scale ────────────────────────────────────────────────────────────\n\n/** 1 = Again (forgot), 2 = Hard, 3 = Good, 4 = Easy */\nexport type Rating = 1 | 2 | 3 | 4;\n\n// ── Card states ─────────────────────────────────────────────────────────────\n\nexport type CardState = \"new\" | \"learning\" | \"review\" | \"relearning\";\n\n// ── Scheduling card ─────────────────────────────────────────────────────────\n\nexport interface SchedulingCard {\n /** Memory stability in days — expected half-life of recall probability. */\n stability: number;\n /** Intrinsic difficulty on a 1–10 scale. */\n difficulty: number;\n /** Days elapsed since the last review. */\n elapsedDays: number;\n /** Currently scheduled interval in days. */\n scheduledDays: number;\n /** Count of successful consecutive reviews. */\n reps: number;\n /** Times the card was forgotten (rated Again). */\n lapses: number;\n /** Current learning state. */\n state: CardState;\n /** When the card is next due. */\n dueAt: Date;\n /** When the card was last reviewed (null for new cards). */\n lastReviewAt: Date | null;\n}\n\n// ── Parameters ──────────────────────────────────────────────────────────────\n\nexport interface FSRSParameters {\n /** 19 optimised weight parameters (w0 – w18). */\n w: number[];\n /** Target retention rate, e.g. 0.9 means we aim for 90% recall. */\n requestRetention: number;\n}\n\n// ── FSRS-5 default weights ──────────────────────────────────────────────────\n\nconst DEFAULT_W: number[] = [\n 0.4072,\n 1.1829,\n 3.1262,\n 15.4722, // w0–w3: initial stability per rating\n 7.2102,\n 0.5316,\n 1.0651, // w4–w6: difficulty\n 0.0092,\n 1.5988,\n 0.1176,\n 1.0014, // w7–w10: stability after forgetting\n 2.0032,\n 0.0266,\n 0.3077,\n 0.15, // w11–w14: stability increase\n 0.0,\n 2.7849,\n 0.3477,\n 0.6831, // w15–w18: additional parameters\n];\n\nconst DEFAULT_REQUEST_RETENTION = 0.9;\n\n// ── FSRS object returned by the factory ─────────────────────────────────────\n\nexport interface FSRS {\n /** Return a fully updated card after applying a rating. Pure function. */\n schedule(card: SchedulingCard, rating: Rating, now?: Date): SchedulingCard;\n /** The parameters baked into this instance. */\n readonly params: Readonly<FSRSParameters>;\n}\n\n// ── Helpers ─────────────────────────────────────────────────────────────────\n\n/** Clamp a number to [lo, hi]. */\nfunction clamp(value: number, lo: number, hi: number): number {\n return Math.min(hi, Math.max(lo, value));\n}\n\n/** Days between two Date objects (may be fractional). */\nfunction daysBetween(a: Date, b: Date): number {\n return (b.getTime() - a.getTime()) / (1000 * 60 * 60 * 24);\n}\n\n// ── Core FSRS-5 formulas ────────────────────────────────────────────────────\n\n/**\n * Initial stability for a brand-new card.\n * S₀ = w[rating - 1]\n */\nfunction initialStability(w: number[], rating: Rating): number {\n return w[rating - 1];\n}\n\n/**\n * Initial difficulty for a brand-new card.\n * D₀(rating) = w4 - exp(w5 * (rating - 1)) + 1\n * Clamped to [1, 10].\n */\nfunction initialDifficulty(w: number[], rating: Rating): number {\n return clamp(w[4] - Math.exp(w[5] * (rating - 1)) + 1, 1, 10);\n}\n\n/**\n * Updated difficulty after a review.\n * D' = w7 * D₀(3) + (1 - w7) * (D - w6 * (rating - 3))\n * Clamped to [1, 10].\n */\nfunction nextDifficulty(w: number[], d: number, rating: Rating): number {\n const d0ForGood = initialDifficulty(w, 3);\n const updated = w[7] * d0ForGood + (1 - w[7]) * (d - w[6] * (rating - 3));\n return clamp(updated, 1, 10);\n}\n\n/**\n * Retrievability — probability of recall.\n * R = (1 + elapsed / (9 * S))^(-1)\n */\nfunction retrievability(elapsed: number, stability: number): number {\n if (stability <= 0) return 0;\n return (1 + elapsed / (9 * stability)) ** -1;\n}\n\n/**\n * Stability after a **successful** recall (rating >= 2).\n * S' = S * (exp(w8) * (11 - D) * S^(-w9) * (exp(w10 * (1 - R)) - 1) * hard_penalty * easy_bonus + 1)\n */\nfunction stabilityAfterSuccess(\n w: number[],\n s: number,\n d: number,\n r: number,\n rating: Rating,\n): number {\n const hardPenalty = rating === 2 ? w[15] : 1;\n const easyBonus = rating === 4 ? w[16] : 1;\n\n const inner =\n Math.exp(w[8]) *\n (11 - d) *\n s ** -w[9] *\n (Math.exp(w[10] * (1 - r)) - 1) *\n hardPenalty *\n easyBonus;\n\n return s * (inner + 1);\n}\n\n/**\n * Stability after **forgetting** (rating = 1).\n * S' = w11 * D^(-w12) * ((S+1)^w13 - 1) * exp(w14 * (1 - R))\n */\nfunction stabilityAfterForgetting(\n w: number[],\n s: number,\n d: number,\n r: number,\n): number {\n return (\n w[11] * d ** -w[12] * ((s + 1) ** w[13] - 1) * Math.exp(w[14] * (1 - r))\n );\n}\n\n/**\n * Optimal interval given new stability and target retention.\n * I = 9 * S' * (1/requestRetention - 1)\n * Minimum 1 day.\n */\nfunction nextInterval(stability: number, requestRetention: number): number {\n const interval = 9 * stability * (1 / requestRetention - 1);\n return Math.max(1, Math.round(interval));\n}\n\n// ── Factory ─────────────────────────────────────────────────────────────────\n\n/**\n * Create a new card with default initial values.\n */\nexport function createEmptyCard(now?: Date): SchedulingCard {\n const ts = now ?? new Date();\n return {\n stability: 0,\n difficulty: 0,\n elapsedDays: 0,\n scheduledDays: 0,\n reps: 0,\n lapses: 0,\n state: \"new\",\n dueAt: ts,\n lastReviewAt: null,\n };\n}\n\n/**\n * Create an FSRS scheduler instance.\n *\n * All scheduling is done through pure functions — no side effects,\n * no database access, no mutation of the input card.\n */\nexport function createFSRS(params?: Partial<FSRSParameters>): FSRS {\n const resolvedParams: FSRSParameters = {\n w: params?.w ?? [...DEFAULT_W],\n requestRetention: params?.requestRetention ?? DEFAULT_REQUEST_RETENTION,\n };\n\n function schedule(\n card: SchedulingCard,\n rating: Rating,\n now?: Date,\n ): SchedulingCard {\n const reviewTime = now ?? new Date();\n const w = resolvedParams.w;\n\n // Compute elapsed days since last review (or 0 for new cards).\n const elapsed =\n card.lastReviewAt !== null\n ? Math.max(0, daysBetween(card.lastReviewAt, reviewTime))\n : 0;\n\n // ── New card ──────────────────────────────────────────────────────\n if (card.state === \"new\") {\n const s = initialStability(w, rating);\n const d = initialDifficulty(w, rating);\n const interval = nextInterval(s, resolvedParams.requestRetention);\n\n const dueAt = new Date(reviewTime);\n dueAt.setDate(dueAt.getDate() + interval);\n\n // New cards always move to \"learning\" after first rating.\n\n return {\n stability: s,\n difficulty: d,\n elapsedDays: 0,\n scheduledDays: interval,\n reps: rating >= 2 ? 1 : 0,\n lapses: rating === 1 ? 1 : 0,\n state: \"learning\",\n dueAt,\n lastReviewAt: reviewTime,\n };\n }\n\n // ── Existing card (learning / review / relearning) ───────────────\n\n const r = retrievability(elapsed, card.stability);\n\n let newStability: number;\n let newDifficulty: number;\n let newReps: number;\n let newLapses: number;\n let newState: CardState;\n\n if (rating === 1) {\n // Forgot — apply forgetting formula\n newStability = stabilityAfterForgetting(\n w,\n card.stability,\n card.difficulty,\n r,\n );\n newDifficulty = nextDifficulty(w, card.difficulty, rating);\n newReps = 0;\n newLapses = card.lapses + 1;\n newState = \"relearning\";\n } else {\n // Recalled — apply success formula\n newStability = stabilityAfterSuccess(\n w,\n card.stability,\n card.difficulty,\n r,\n rating,\n );\n newDifficulty = nextDifficulty(w, card.difficulty, rating);\n newReps = card.reps + 1;\n newLapses = card.lapses;\n // Successful recall transitions any state to review.\n newState = \"review\";\n }\n\n const interval = nextInterval(\n newStability,\n resolvedParams.requestRetention,\n );\n\n const dueAt = new Date(reviewTime);\n dueAt.setDate(dueAt.getDate() + interval);\n\n return {\n stability: newStability,\n difficulty: newDifficulty,\n elapsedDays: elapsed,\n scheduledDays: interval,\n reps: newReps,\n lapses: newLapses,\n state: newState,\n dueAt,\n lastReviewAt: reviewTime,\n };\n }\n\n return {\n schedule,\n params: Object.freeze(resolvedParams),\n };\n}\n","import type { Database } from \"libsql\";\nimport type { DeleteCardResult } from \"../models/card.js\";\nimport { deleteCardForUser, getCardById } from \"../models/card.js\";\nimport { getPrerequisites } from \"../models/prerequisite.js\";\nimport type {\n DeleteTokenResult,\n Token,\n UpdateTokenInput,\n} from \"../models/token.js\";\nimport {\n deleteToken,\n deprecateToken,\n getTokenById,\n updateToken,\n} from \"../models/token.js\";\nimport type { CascadeBlockResult } from \"../scheduler/blocker.js\";\nimport { cascadeBlock } from \"../scheduler/blocker.js\";\nimport type { Rating } from \"../scheduler/fsrs.js\";\nimport type { EvaluateResult } from \"./evaluator.js\";\nimport { evaluateRating } from \"./evaluator.js\";\n\nexport type ReviewActionType =\n | \"rate\"\n | \"skip\"\n | \"edit-token\"\n | \"deprecate-token\"\n | \"delete-token\"\n | \"delete-card\"\n | \"stop\";\n\nexport interface ExecuteReviewActionInput {\n cardId: string;\n userId: string;\n action: ReviewActionType;\n rating?: Rating;\n tokenUpdates?: UpdateTokenInput;\n}\n\nexport interface ReviewActionResult {\n action: ReviewActionType;\n token: Token;\n evaluation?: EvaluateResult;\n blocked?: CascadeBlockResult;\n updatedToken?: Token;\n deletedToken?: DeleteTokenResult;\n deletedCard?: DeleteCardResult;\n skipped?: boolean;\n stopped?: boolean;\n}\n\nfunction getReviewTarget(\n db: Database,\n cardId: string,\n userId: string,\n): { cardId: string; token: Token } {\n const card = getCardById(db, cardId);\n if (!card) {\n throw new Error(`Card not found: ${cardId}`);\n }\n if (card.user_id !== userId) {\n throw new Error(`Card ${cardId} does not belong to user ${userId}`);\n }\n\n const token = getTokenById(db, card.token_id);\n if (!token) {\n throw new Error(`Token not found for card ${cardId}`);\n }\n\n return { cardId: card.id, token };\n}\n\nexport function executeReviewAction(\n db: Database,\n input: ExecuteReviewActionInput,\n): ReviewActionResult {\n const target = getReviewTarget(db, input.cardId, input.userId);\n\n switch (input.action) {\n case \"rate\": {\n if (input.rating == null) {\n throw new Error(\"rating is required for action=rate\");\n }\n\n const evaluation = evaluateRating(db, {\n cardId: target.cardId,\n tokenId: target.token.id,\n userId: input.userId,\n rating: input.rating,\n });\n\n let blocked: CascadeBlockResult | undefined;\n if (input.rating === 1) {\n const prereqs = getPrerequisites(db, target.token.id);\n if (prereqs.length > 0) {\n blocked = cascadeBlock(db, input.userId, target.token.slug);\n }\n }\n\n return {\n action: input.action,\n token: target.token,\n evaluation,\n blocked,\n };\n }\n\n case \"skip\":\n return { action: input.action, token: target.token, skipped: true };\n\n case \"stop\":\n return { action: input.action, token: target.token, stopped: true };\n\n case \"edit-token\": {\n const updatedToken = updateToken(\n db,\n target.token.slug,\n input.tokenUpdates ?? {},\n );\n return {\n action: input.action,\n token: target.token,\n updatedToken,\n };\n }\n\n case \"deprecate-token\": {\n const updatedToken = deprecateToken(db, target.token.slug);\n return {\n action: input.action,\n token: target.token,\n updatedToken,\n };\n }\n\n case \"delete-token\": {\n const deletedToken = deleteToken(db, target.token.slug);\n return {\n action: input.action,\n token: target.token,\n deletedToken,\n };\n }\n\n case \"delete-card\": {\n const deletedCard = deleteCardForUser(db, target.token.id, input.userId);\n return {\n action: input.action,\n token: target.token,\n deletedCard,\n };\n }\n\n default: {\n const exhaustive: never = input.action;\n throw new Error(`Unsupported review action: ${exhaustive}`);\n }\n }\n}\n","/**\n * Active Recall Prompt Generation\n *\n * Generates review prompts from tokens, adapting the question style\n * to the token's Bloom taxonomy level. This is NOT an LLM call —\n * it's template-based prompt assembly for the CLI and bridge.\n */\n\nexport type BloomLevel = 1 | 2 | 3 | 4 | 5;\n\nexport interface RecallPrompt {\n cardId: string;\n tokenId: string;\n slug: string;\n question: string;\n concept: string;\n domain: string;\n bloomLevel: BloomLevel;\n bloomVerb: string;\n hints: string[];\n sourceLink?: string | null;\n}\n\nconst BLOOM_VERBS: Record<BloomLevel, string> = {\n 1: \"Remember\",\n 2: \"Understand\",\n 3: \"Apply\",\n 4: \"Analyze\",\n 5: \"Synthesize\",\n};\n\nfunction formatSlugForCue(slug: string): string {\n return slug.replace(/[-_]/g, \" \");\n}\n\nconst BLOOM_CUES: Record<BloomLevel, (slug: string) => string> = {\n 1: (slug) =>\n `Recall the definition and core concept of: ${formatSlugForCue(slug)}`,\n 2: (slug) => `Explain the concept and how ${formatSlugForCue(slug)} works.`,\n 3: (slug) =>\n `Describe how or where you would apply the concept of ${formatSlugForCue(slug)}.`,\n 4: (slug) =>\n `Analyze the trade-offs, advantages, or alternatives of ${formatSlugForCue(slug)}.`,\n 5: (slug) =>\n `How would you design a solution using the concept of ${formatSlugForCue(slug)}?`,\n};\n\nexport interface PromptInput {\n cardId: string;\n tokenId: string;\n slug: string;\n concept: string;\n domain: string;\n bloomLevel: BloomLevel;\n sourceLink?: string | null;\n question?: string | null;\n}\n\n/**\n * Generate a template-based concept-free recall cue using the slug and domain.\n */\nexport function generateConceptFreeCue(\n bloomLevel: BloomLevel,\n slug: string,\n _domain: string,\n): string {\n const bloom = (\n bloomLevel >= 1 && bloomLevel <= 5 ? bloomLevel : 1\n ) as BloomLevel;\n return BLOOM_CUES[bloom](slug);\n}\n\n/**\n * Generate a recall prompt for a token at its Bloom level.\n * When called from the CLI, the prompt is rendered in the terminal.\n * When called from the AI bridge, the JSON is returned for the AI to present conversationally.\n */\nexport function generatePrompt(input: PromptInput): RecallPrompt {\n const bloom = (\n input.bloomLevel >= 1 && input.bloomLevel <= 5 ? input.bloomLevel : 1\n ) as BloomLevel;\n\n const question = input.question?.trim()\n ? input.question.trim()\n : generateConceptFreeCue(bloom, input.slug, input.domain);\n\n return {\n cardId: input.cardId,\n tokenId: input.tokenId,\n slug: input.slug,\n question,\n concept: input.concept,\n domain: input.domain,\n bloomLevel: bloom,\n bloomVerb: BLOOM_VERBS[bloom],\n hints: [],\n sourceLink: input.sourceLink ?? null,\n };\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\n\nexport interface ResolvedReference {\n sourceType: \"local\" | \"remote_web\" | \"dynamic_search\";\n content: string;\n filePath?: string;\n url?: string;\n}\n\n/**\n * A source reference resolved and bounded for inclusion in a review payload.\n * Same shape as ResolvedReference plus the originating link and a truncation flag.\n */\nexport interface ReviewContext {\n sourceLink: string;\n sourceType: ResolvedReference[\"sourceType\"];\n content: string;\n filePath?: string;\n url?: string;\n truncated: boolean;\n}\n\n/** Default cap on resolved content length, so bridge JSON / terminal output stays bounded. */\nexport const DEFAULT_REVIEW_CONTEXT_MAX_CHARS = 6000;\n\n/**\n * Strips HTML tags and attempts to convert basic structure to readable text/markdown.\n */\nfunction htmlToText(html: string): string {\n // Extract body if present\n let content = html;\n const bodyMatch = /<body[^>]*>([\\s\\S]*?)<\\/body>/i.exec(html);\n if (bodyMatch) {\n content = bodyMatch[1];\n }\n\n // Strip script, style, and head tags completely\n content = content.replace(/<(script|style|head)[^>]*>([\\s\\S]*?)<\\/\\1>/gi, \"\");\n // Replace headings\n content = content.replace(\n /<h[1-6][^>]*>([\\s\\S]*?)<\\/h[1-6]>/gi,\n \"\\n\\n# $1\\n\",\n );\n // Replace paragraph/div/li tags with line breaks\n content = content.replace(/<(p|div|li)[^>]*>/gi, \"\\n\");\n content = content.replace(/<\\/(p|div|li)>/gi, \"\\n\");\n content = content.replace(/<br\\s*\\/?>/gi, \"\\n\");\n // Strip all other HTML tags\n content = content.replace(/<[^>]+>/g, \"\");\n // Decode basic HTML entities\n content = content\n .replace(/&nbsp;/g, \" \")\n .replace(/&lt;/g, \"<\")\n .replace(/&gt;/g, \">\")\n .replace(/&amp;/g, \"&\")\n .replace(/&quot;/g, '\"')\n .replace(/&#39;/g, \"'\");\n\n // Collapse consecutive newlines\n content = content.replace(/\\n{3,}/g, \"\\n\\n\").trim();\n return content;\n}\n\n/**\n * Parse line anchors like #L10-L25 or #L10 and extract the lines from file content.\n */\nfunction extractLines(content: string, anchor: string): string {\n const lines = content.split(/\\r?\\n/);\n const match = /#L(\\d+)(?:-L(\\d+))?$/i.exec(anchor);\n if (!match) return content;\n\n const start = Number.parseInt(match[1], 10) - 1; // 0-indexed\n const end = match[2] ? Number.parseInt(match[2], 10) - 1 : start;\n\n if (start < 0 || start >= lines.length) return content;\n\n const slice = lines.slice(start, Math.min(end + 1, lines.length));\n return slice.join(\"\\n\");\n}\n\n/**\n * Resolves a given token's source_link into readable textual content.\n */\nexport async function resolveReference(\n sourceLink: string,\n): Promise<ResolvedReference> {\n const cleaned = sourceLink.trim();\n\n // 1. Dynamic Web Search\n if (cleaned.startsWith(\"search://\")) {\n try {\n const url = new URL(cleaned);\n const query = url.searchParams.get(\"q\") || \"\";\n return {\n sourceType: \"dynamic_search\",\n content: `QUERY_DIRECTIVE: Run web search for \"${query}\"`,\n url: cleaned,\n };\n } catch {\n // Fallback if URL parsing fails\n const query = cleaned.replace(/^search:\\/\\/(\\??q=)?/, \"\");\n return {\n sourceType: \"dynamic_search\",\n content: `QUERY_DIRECTIVE: Run web search for \"${decodeURIComponent(query)}\"`,\n url: cleaned,\n };\n }\n }\n\n // 2. HTTP/HTTPS URLs\n if (cleaned.startsWith(\"http://\") || cleaned.startsWith(\"https://\")) {\n // 2.a GitHub URIs\n const gitHubMatch =\n /^https?:\\/\\/(?:www\\.)?github\\.com\\/([^/]+)\\/([^/]+)\\/blob\\/([^/]+)\\/(.+)$/i.exec(\n cleaned,\n );\n if (gitHubMatch) {\n const [_, owner, repo, branch, fullPathWithAnchor] = gitHubMatch;\n const anchorIndex = fullPathWithAnchor.indexOf(\"#\");\n const filePath =\n anchorIndex !== -1\n ? fullPathWithAnchor.slice(0, anchorIndex)\n : fullPathWithAnchor;\n const anchor =\n anchorIndex !== -1 ? fullPathWithAnchor.slice(anchorIndex) : \"\";\n\n // Try local resolution: check if repo folder exists in sibling directories\n const parentDir = dirname(process.cwd());\n const localRepoPath = join(parentDir, repo);\n const localFilePath = join(localRepoPath, filePath);\n\n if (existsSync(localFilePath)) {\n try {\n let fileContent = readFileSync(localFilePath, \"utf-8\");\n if (anchor) {\n fileContent = extractLines(fileContent, anchor);\n }\n return {\n sourceType: \"local\",\n content: fileContent,\n filePath: localFilePath,\n };\n } catch (_e) {\n // Fallback to fetch if file read fails\n }\n }\n\n // Remote fallback: fetch raw content from githubusercontent\n const rawUrl = `https://raw.githubusercontent.com/${owner}/${repo}/${branch}/${filePath}`;\n try {\n const response = await fetch(rawUrl);\n if (response.ok) {\n let rawText = await response.text();\n if (anchor) {\n rawText = extractLines(rawText, anchor);\n }\n return {\n sourceType: \"remote_web\",\n content: rawText,\n url: cleaned,\n };\n }\n } catch (_e) {\n // Fallback to generic URL loading\n }\n }\n\n // 2.b Generic HTTPS/HTTP URLs\n try {\n const response = await fetch(cleaned);\n if (response.ok) {\n const text = await response.text();\n const cleanText = htmlToText(text);\n return {\n sourceType: \"remote_web\",\n content: cleanText,\n url: cleaned,\n };\n }\n throw new Error(`HTTP error ${response.status}: ${response.statusText}`);\n } catch (err) {\n return {\n sourceType: \"remote_web\",\n content: `Error fetching URL reference: ${(err as Error).message}\\nLink: ${cleaned}`,\n url: cleaned,\n };\n }\n }\n\n // 3. Local Workspace Path (relative to process.cwd)\n const anchorIndex = cleaned.indexOf(\"#\");\n const relativePath =\n anchorIndex !== -1 ? cleaned.slice(0, anchorIndex) : cleaned;\n const anchor = anchorIndex !== -1 ? cleaned.slice(anchorIndex) : \"\";\n const absolutePath = resolve(process.cwd(), relativePath);\n\n if (existsSync(absolutePath)) {\n try {\n let fileContent = readFileSync(absolutePath, \"utf-8\");\n if (anchor) {\n fileContent = extractLines(fileContent, anchor);\n }\n return {\n sourceType: \"local\",\n content: fileContent,\n filePath: absolutePath,\n };\n } catch (_e) {\n // Fallback\n }\n }\n\n // Final fallback: return the path/link description as string\n return {\n sourceType: \"local\",\n content: `Local reference file not found or unreadable.\\nReference: ${cleaned}`,\n filePath: absolutePath,\n };\n}\n\n/**\n * Resolve a token's source_link into bounded, review-ready context.\n *\n * Wraps {@link resolveReference} for the review/bridge flow: returns `null`\n * for empty links and caps content length so the surrounding payload (bridge\n * JSON or terminal output) stays manageable, flagging when truncation occurred.\n */\nexport async function resolveReviewContext(\n sourceLink: string | null | undefined,\n opts: { maxChars?: number } = {},\n): Promise<ReviewContext | null> {\n const cleaned = sourceLink?.trim();\n if (!cleaned) return null;\n\n const maxChars = opts.maxChars ?? DEFAULT_REVIEW_CONTEXT_MAX_CHARS;\n const resolved = await resolveReference(cleaned);\n\n let content = resolved.content;\n let truncated = false;\n if (content.length > maxChars) {\n content = content.slice(0, maxChars);\n truncated = true;\n }\n\n return {\n sourceLink: cleaned,\n sourceType: resolved.sourceType,\n content,\n filePath: resolved.filePath,\n url: resolved.url,\n truncated,\n };\n}\n\n/**\n * Normalizes a path, stripping anchors and converting separators.\n */\nexport function normalizePath(p: string): string {\n const base = p.split(\"#\")[0].trim();\n return base.replace(/\\\\/g, \"/\").toLowerCase();\n}\n\n/**\n * Checks if a token's source_link references a changed file.\n */\nexport function matchesFilePath(\n sourceLink: string | null,\n changedFile: string,\n): boolean {\n if (!sourceLink) return false;\n\n const normSource = normalizePath(sourceLink);\n const normChanged = normalizePath(changedFile);\n\n if (!normSource || !normChanged) return false;\n\n // 1. GitHub URI matching\n const gitHubMatch =\n /^https?:\\/\\/(?:www\\.)?github\\.com\\/([^/]+)\\/([^/]+)\\/blob\\/([^/]+)\\/(.+)$/i.exec(\n normSource,\n );\n if (gitHubMatch) {\n const filePath = gitHubMatch[4];\n return filePath === normChanged;\n }\n\n // Generic URL check (don't match web references against local paths)\n if (normSource.startsWith(\"http://\") || normSource.startsWith(\"https://\")) {\n return false;\n }\n\n // 2. Relative/Absolute path matching\n return normSource.endsWith(normChanged) || normChanged.endsWith(normSource);\n}\n","/**\n * Cross-domain interleaving — prevents same-domain streaks in review queues.\n *\n * Given an array of items with a `domain` field, reorders them using a\n * round-robin strategy so that consecutive items come from different domains.\n * This leverages the interleaving effect: mixing topics during practice\n * strengthens discrimination and long-term retention.\n */\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface QueueItem {\n cardId: string;\n tokenId: string;\n domain: string;\n}\n\n// ── Functions ────────────────────────────────────────────────────────────────\n\n/**\n * Reorder items so no domain appears more than `maxConsecutive` times in a row.\n *\n * Algorithm: group items by domain, then round-robin across domain groups.\n * Each round picks one item from each non-exhausted domain. Within a domain,\n * the original order is preserved (so urgency sorting survives).\n *\n * If a domain has more items than others, its extras will appear after all\n * other domains are exhausted — but the `maxConsecutive` cap is still\n * respected by inserting items from the largest remaining domains first.\n *\n * @param items - Array of items to interleave. Not mutated.\n * @param maxConsecutive - Max consecutive items from the same domain. Defaults to 2.\n * @returns A new array with the same items in interleaved order.\n */\nexport function interleave<T extends { domain: string }>(\n items: T[],\n maxConsecutive: number = 2,\n): T[] {\n if (items.length <= 1) return [...items];\n\n // Group items by domain, preserving original order within each group\n const byDomain = new Map<string, T[]>();\n for (const item of items) {\n const group = byDomain.get(item.domain);\n if (group) {\n group.push(item);\n } else {\n byDomain.set(item.domain, [item]);\n }\n }\n\n // If there's only one domain, no interleaving possible\n if (byDomain.size === 1) return [...items];\n\n const result: T[] = [];\n let consecutiveCount = 0;\n let lastDomain: string | null = null;\n\n // Track how many items we've consumed from each domain\n const cursors = new Map<string, number>();\n for (const domain of byDomain.keys()) {\n cursors.set(domain, 0);\n }\n\n // Round-robin: sort domains by remaining count (largest first) each round\n while (result.length < items.length) {\n // Get domains that still have items, sorted by remaining count descending\n const activeDomains = [...byDomain.entries()]\n .filter(\n ([domain]) =>\n (cursors.get(domain) ?? 0) < (byDomain.get(domain)?.length ?? 0),\n )\n .sort((a, b) => {\n const remainA = a[1].length - (cursors.get(a[0]) ?? 0);\n const remainB = b[1].length - (cursors.get(b[0]) ?? 0);\n return remainB - remainA;\n });\n\n if (activeDomains.length === 0) break;\n\n let pickedThisRound = false;\n\n for (const [domain, group] of activeDomains) {\n const cursor = cursors.get(domain) ?? 0;\n if (cursor >= group.length) continue;\n\n // Check if adding from this domain would exceed maxConsecutive\n if (domain === lastDomain && consecutiveCount >= maxConsecutive) {\n // Try to find another domain first\n continue;\n }\n\n // Pick one item from this domain\n result.push(group[cursor]);\n cursors.set(domain, cursor + 1);\n pickedThisRound = true;\n\n if (domain === lastDomain) {\n consecutiveCount++;\n } else {\n lastDomain = domain;\n consecutiveCount = 1;\n }\n\n break;\n }\n\n // If we couldn't pick without exceeding maxConsecutive, we must accept\n // a streak from whatever domain has items left\n if (!pickedThisRound) {\n for (const [domain, group] of activeDomains) {\n const cursor = cursors.get(domain) ?? 0;\n if (cursor >= group.length) continue;\n\n result.push(group[cursor]);\n cursors.set(domain, cursor + 1);\n\n if (domain === lastDomain) {\n consecutiveCount++;\n } else {\n lastDomain = domain;\n consecutiveCount = 1;\n }\n\n break;\n }\n }\n }\n\n return result;\n}\n","/**\n * Review Queue Builder — assembles a session's review queue.\n *\n * Combines due-card fetching, new-card selection, urgency sorting,\n * and cross-domain interleaving into a single ready-to-review queue.\n */\n\nimport type { Database } from \"libsql\";\nimport { interleave } from \"./interleaver.js\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface ReviewQueueOptions {\n userId: string;\n maxNew?: number; // default 10\n maxReviews?: number; // default 50\n now?: Date;\n}\n\nexport interface ReviewQueueItem {\n cardId: string;\n tokenId: string;\n slug: string;\n concept: string;\n domain: string;\n bloomLevel: number;\n state: string; // 'new' | 'learning' | 'review' | 'relearning'\n dueAt: string;\n sourceLink: string | null;\n question: string | null;\n}\n\nexport interface ReviewQueue {\n items: ReviewQueueItem[];\n newCount: number;\n reviewCount: number;\n relearnCount: number;\n totalDomains: string[];\n}\n\n// ── Internal row type from SQL queries ───────────────────────────────────────\n\ninterface CardRow {\n card_id: string;\n token_id: string;\n slug: string;\n concept: string;\n domain: string;\n bloom_level: number;\n state: string;\n due_at: string;\n source_link: string | null;\n question: string | null;\n}\n\n// ── Functions ────────────────────────────────────────────────────────────────\n\n/**\n * Build a review queue for a user's study session.\n *\n * The queue is assembled in stages:\n * 1. Fetch all due cards (not blocked, due_at <= now, state in review/relearning/learning)\n * 2. Fetch new cards (state = 'new', not blocked) up to maxNew\n * 3. Sort overdue cards by urgency — most overdue first\n * 4. Apply cross-domain interleaving to prevent same-domain streaks\n * 5. Intersperse new cards at regular intervals (every 5th position)\n * 6. Cap total at maxReviews\n *\n * @param db - Database connection\n * @param options - Queue building options\n * @returns The assembled review queue with metadata\n */\nexport function buildReviewQueue(\n db: Database,\n options: ReviewQueueOptions,\n): ReviewQueue {\n const maxNew = options.maxNew ?? 10;\n const maxReviews = options.maxReviews ?? 50;\n const now = options.now ?? new Date();\n const nowISO = now.toISOString();\n\n // ── Step 1: Fetch due cards (review, relearning, learning — not new) ───\n const dueRows = db\n .prepare(\n `SELECT\n c.id AS card_id,\n c.token_id AS token_id,\n t.slug AS slug,\n t.concept AS concept,\n t.domain AS domain,\n t.bloom_level AS bloom_level,\n c.state AS state,\n c.due_at AS due_at,\n t.source_link AS source_link,\n t.question AS question\n FROM cards c\n JOIN tokens t ON t.id = c.token_id\n WHERE c.user_id = ?\n AND c.blocked = 0\n AND c.due_at <= ?\n AND c.state IN ('review', 'relearning', 'learning')\n AND t.deprecated_at IS NULL\n ORDER BY c.due_at ASC`,\n )\n .all(options.userId, nowISO) as CardRow[];\n\n // ── Step 2: Fetch new cards ────────────────────────────────────────────\n const newRows = db\n .prepare(\n `SELECT\n c.id AS card_id,\n c.token_id AS token_id,\n t.slug AS slug,\n t.concept AS concept,\n t.domain AS domain,\n t.bloom_level AS bloom_level,\n c.state AS state,\n c.due_at AS due_at,\n t.source_link AS source_link,\n t.question AS question\n FROM cards c\n JOIN tokens t ON t.id = c.token_id\n WHERE c.user_id = ?\n AND c.blocked = 0\n AND c.state = 'new'\n AND t.deprecated_at IS NULL\n ORDER BY t.bloom_level ASC, t.slug ASC\n LIMIT ?`,\n )\n .all(options.userId, maxNew) as CardRow[];\n\n // ── Step 3: Sort overdue cards by urgency (most overdue first) ─────────\n const nowMs = now.getTime();\n const sortedDue = [...dueRows].sort((a, b) => {\n const overdueA = nowMs - new Date(a.due_at).getTime();\n const overdueB = nowMs - new Date(b.due_at).getTime();\n return overdueB - overdueA; // most overdue first\n });\n\n // ── Step 4: Apply cross-domain interleaving to due cards ───────────────\n const interleavedDue = interleave(\n sortedDue.map((row) => ({ ...rowToItem(row), domain: row.domain })),\n );\n\n // ── Step 5: Intersperse new cards at regular intervals ─────────────────\n const newItems = newRows.map(rowToItem);\n const merged = intersperseNew(interleavedDue, newItems, 5);\n\n // ── Step 6: Cap total at maxReviews ────────────────────────────────────\n const capped = merged.slice(0, maxReviews);\n\n // ── Compute metadata ──────────────────────────────────────────────────\n let newCount = 0;\n let reviewCount = 0;\n let relearnCount = 0;\n const domainSet = new Set<string>();\n\n for (const item of capped) {\n domainSet.add(item.domain);\n switch (item.state) {\n case \"new\":\n newCount++;\n break;\n case \"relearning\":\n relearnCount++;\n break;\n default:\n reviewCount++;\n break;\n }\n }\n\n return {\n items: capped,\n newCount,\n reviewCount,\n relearnCount,\n totalDomains: [...domainSet].sort(),\n };\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\n/** Convert a SQL row to a ReviewQueueItem. */\nfunction rowToItem(row: CardRow): ReviewQueueItem {\n return {\n cardId: row.card_id,\n tokenId: row.token_id,\n slug: row.slug,\n concept: row.concept,\n domain: row.domain,\n bloomLevel: row.bloom_level,\n state: row.state,\n dueAt: row.due_at,\n sourceLink: row.source_link,\n question: row.question,\n };\n}\n\n/**\n * Intersperse new cards into the review queue at regular intervals.\n *\n * Instead of front-loading or back-loading new cards, places one new card\n * every `interval` positions (e.g., positions 4, 9, 14, ...).\n * This gives the user a mix of familiar reviews and new material.\n *\n * @param reviews - The interleaved review cards\n * @param newCards - New cards to intersperse\n * @param interval - Place a new card every N positions (default 5)\n * @returns Merged array with new cards interspersed\n */\nfunction intersperseNew(\n reviews: ReviewQueueItem[],\n newCards: ReviewQueueItem[],\n interval: number,\n): ReviewQueueItem[] {\n if (newCards.length === 0) return [...reviews];\n if (reviews.length === 0) return [...newCards];\n\n const result: ReviewQueueItem[] = [];\n let reviewIdx = 0;\n let newIdx = 0;\n\n // Position counter tracks where we are in the final queue\n let position = 0;\n\n while (reviewIdx < reviews.length || newIdx < newCards.length) {\n // Insert a new card every `interval` positions (0-indexed: at 4, 9, 14, ...)\n if (\n newIdx < newCards.length &&\n position > 0 &&\n position % interval === interval - 1\n ) {\n result.push(newCards[newIdx]);\n newIdx++;\n } else if (reviewIdx < reviews.length) {\n result.push(reviews[reviewIdx]);\n reviewIdx++;\n } else if (newIdx < newCards.length) {\n // No more reviews — append remaining new cards\n result.push(newCards[newIdx]);\n newIdx++;\n }\n\n position++;\n }\n\n return result;\n}\n","import {\n appendFileSync,\n copyFileSync,\n existsSync,\n mkdirSync,\n readFileSync,\n} from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst HOME = homedir();\n\n/**\n * Get the path to ZAM's internal package SKILL.md.\n */\nexport function getPackageSkillPath(\n agent: \"default\" | \"claude\" | \"codex\" = \"default\",\n): string {\n // Support source modules plus the dist/index.js and dist/cli/index.js bundles.\n const packageRoot =\n [\n fileURLToPath(new URL(\"../../..\", import.meta.url)),\n fileURLToPath(new URL(\"../..\", import.meta.url)),\n fileURLToPath(new URL(\"..\", import.meta.url)),\n ].find((candidate) => existsSync(join(candidate, \"package.json\"))) ?? \"\";\n\n if (!packageRoot) return \"\";\n\n if (agent === \"codex\") {\n const codexPath = join(packageRoot, \".agents\", \"skills\", \"zam\", \"SKILL.md\");\n if (existsSync(codexPath)) return codexPath;\n return \"\";\n }\n\n if (agent === \"claude\") {\n const claudePath = join(\n packageRoot,\n \".claude\",\n \"skills\",\n \"zam\",\n \"SKILL.md\",\n );\n if (existsSync(claudePath)) return claudePath;\n return \"\";\n }\n\n // Try .agent first\n let path = join(packageRoot, \".agent\", \"skills\", \"zam\", \"SKILL.md\");\n if (existsSync(path)) return path;\n\n // Try .claude\n path = join(packageRoot, \".claude\", \"skills\", \"zam\", \"SKILL.md\");\n if (existsSync(path)) return path;\n\n return \"\";\n}\n\n/**\n * Distribute the ZAM active-recall training skill globally.\n * Copies SKILL.md into global directories for supported coding agents.\n */\nexport function distributeGlobalSkills(home: string = HOME): Array<{\n name: string;\n path: string;\n success: boolean;\n}> {\n const sourceSkill = getPackageSkillPath();\n const claudeSourceSkill = getPackageSkillPath(\"claude\");\n const codexSourceSkill = getPackageSkillPath(\"codex\");\n const results: Array<{ name: string; path: string; success: boolean }> = [];\n\n if (!sourceSkill) {\n console.warn(\"Could not find ZAM source SKILL.md in the package folder.\");\n return results;\n }\n\n // 1. Claude Code global directory\n const claudeSkillsDir = join(home, \".claude\", \"skills\", \"zam\");\n try {\n if (!claudeSourceSkill) {\n throw new Error(\"Claude skill source not found\");\n }\n mkdirSync(claudeSkillsDir, { recursive: true });\n copyFileSync(claudeSourceSkill, join(claudeSkillsDir, \"SKILL.md\"));\n results.push({\n name: \"Claude Code Global\",\n path: join(claudeSkillsDir, \"SKILL.md\"),\n success: true,\n });\n } catch (_err) {\n results.push({\n name: \"Claude Code Global\",\n path: claudeSkillsDir,\n success: false,\n });\n }\n\n // 2. Gemini/agy global directory\n const geminiSkillsDir = join(home, \".gemini\", \"skills\", \"zam\");\n try {\n mkdirSync(geminiSkillsDir, { recursive: true });\n copyFileSync(sourceSkill, join(geminiSkillsDir, \"SKILL.md\"));\n results.push({\n name: \"Gemini CLI Global\",\n path: join(geminiSkillsDir, \"SKILL.md\"),\n success: true,\n });\n } catch (_err) {\n results.push({\n name: \"Gemini CLI Global\",\n path: geminiSkillsDir,\n success: false,\n });\n }\n\n // 3. Codex global skills directory\n const codexSkillsDir = join(home, \".agents\", \"skills\", \"zam\");\n try {\n if (!codexSourceSkill) {\n throw new Error(\"Codex skill source not found\");\n }\n mkdirSync(codexSkillsDir, { recursive: true });\n copyFileSync(codexSourceSkill, join(codexSkillsDir, \"SKILL.md\"));\n results.push({\n name: \"Codex Global\",\n path: join(codexSkillsDir, \"SKILL.md\"),\n success: true,\n });\n } catch (_err) {\n results.push({\n name: \"Codex Global\",\n path: codexSkillsDir,\n success: false,\n });\n }\n\n // 4. Goose skills directory\n const gooseSkillsDir = join(home, \".goose\", \"skills\", \"zam\");\n try {\n mkdirSync(gooseSkillsDir, { recursive: true });\n copyFileSync(sourceSkill, join(gooseSkillsDir, \"SKILL.md\"));\n results.push({\n name: \"Goose Global\",\n path: join(gooseSkillsDir, \"SKILL.md\"),\n success: true,\n });\n } catch (_err) {\n results.push({\n name: \"Goose Global\",\n path: gooseSkillsDir,\n success: false,\n });\n }\n\n return results;\n}\n\n/**\n * Inject the ZAM shell observation hook into user profile scripts so monitoring\n * is automatically initialized on startup.\n */\nexport function injectShellHooks(): Array<{\n shell: string;\n file: string;\n success: boolean;\n alreadyHooked: boolean;\n}> {\n const results: Array<{\n shell: string;\n file: string;\n success: boolean;\n alreadyHooked: boolean;\n }> = [];\n const hookLine = `\\n# ZAM Shell Observation Hooks\\nif (command -v zam >/dev/null 2>&1); then eval \"$(zam monitor start --quiet)\"; fi\\n`;\n const pwshHookLine = `\\n# ZAM Shell Observation Hooks\\nif (Get-Command zam -ErrorAction SilentlyContinue) { Invoke-Expression (& zam monitor start --quiet pwsh) }\\n`;\n\n // 1. Zsh profile (~/.zshrc)\n const zshrc = join(HOME, \".zshrc\");\n if (existsSync(zshrc)) {\n try {\n const content = readFileSync(zshrc, \"utf8\");\n if (content.includes(\"zam monitor start\")) {\n results.push({\n shell: \"zsh\",\n file: zshrc,\n success: true,\n alreadyHooked: true,\n });\n } else {\n appendFileSync(zshrc, hookLine);\n results.push({\n shell: \"zsh\",\n file: zshrc,\n success: true,\n alreadyHooked: false,\n });\n }\n } catch {\n results.push({\n shell: \"zsh\",\n file: zshrc,\n success: false,\n alreadyHooked: false,\n });\n }\n }\n\n // 2. Bash profile (~/.bashrc)\n const bashrc = join(HOME, \".bashrc\");\n if (existsSync(bashrc)) {\n try {\n const content = readFileSync(bashrc, \"utf8\");\n if (content.includes(\"zam monitor start\")) {\n results.push({\n shell: \"bash\",\n file: bashrc,\n success: true,\n alreadyHooked: true,\n });\n } else {\n appendFileSync(bashrc, hookLine);\n results.push({\n shell: \"bash\",\n file: bashrc,\n success: true,\n alreadyHooked: false,\n });\n }\n } catch {\n results.push({\n shell: \"bash\",\n file: bashrc,\n success: false,\n alreadyHooked: false,\n });\n }\n }\n\n // 3. PowerShell Profile ($HOME\\Documents\\PowerShell\\Microsoft.PowerShell_profile.ps1)\n // Check both PowerShell and WindowsPowerShell\n const pwshDirs = [\n join(HOME, \"Documents\", \"PowerShell\"),\n join(HOME, \"Documents\", \"WindowsPowerShell\"),\n ];\n\n for (const dir of pwshDirs) {\n const profileFile = join(dir, \"Microsoft.PowerShell_profile.ps1\");\n try {\n mkdirSync(dir, { recursive: true });\n let content = \"\";\n if (existsSync(profileFile)) {\n content = readFileSync(profileFile, \"utf8\");\n }\n\n if (content.includes(\"zam monitor start\")) {\n results.push({\n shell: \"powershell\",\n file: profileFile,\n success: true,\n alreadyHooked: true,\n });\n } else {\n appendFileSync(profileFile, pwshHookLine);\n results.push({\n shell: \"powershell\",\n file: profileFile,\n success: true,\n alreadyHooked: false,\n });\n }\n } catch {\n results.push({\n shell: \"powershell\",\n file: profileFile,\n success: false,\n alreadyHooked: false,\n });\n }\n }\n\n return results;\n}\n","import type { SupportedLocale } from \"./locale.js\";\n\nexport type TranslationKey =\n | \"welcome\"\n | \"new_review_relearn\"\n | \"domains\"\n | \"instruction\"\n | \"quit_hint\"\n | \"offline_warning\"\n | \"offline_instruction\"\n | \"nothing_due\"\n | \"evaluating\"\n | \"generating_question\"\n | \"translating\"\n | \"prompt_answer\"\n | \"session_ended\"\n | \"session_complete\"\n | \"cards_rated\"\n | \"avg_rating\"\n | \"forgot\"\n | \"feedback_title\"\n | \"answer_title\"\n | \"keep_waiting\"\n | \"local_ai_working\"\n | \"wait_warning\"\n | \"wait_info\"\n | \"keep_waiting_llm\"\n | \"proceeding_offline\"\n | \"eval_skipped\";\n\nexport const TRANSLATIONS: Record<\n SupportedLocale,\n Record<TranslationKey, string>\n> = {\n en: {\n welcome: \"Learning session: {count} card(s)\",\n new_review_relearn: \" New: {newC} Review: {reviewC} Relearn: {relearnC}\",\n domains: \" Domains: {domains}\",\n instruction:\n \"\\nRecall each answer first, reveal it, then rate yourself honestly.\",\n quit_hint:\n \"Type 'q' at the answer prompt (or press Ctrl+C) to stop anytime.\",\n offline_warning:\n \"\\n\\x1b[33m⚠ LLM-Feedback & automatic translation are disabled.\\x1b[0m\",\n offline_instruction:\n \" Enable with: \\x1b[36mnpm run dev -- settings llm on\\x1b[0m\\n\",\n nothing_due: \"Nothing due to learn. You're all caught up!\",\n evaluating: \"Evaluating answer via local AI...\",\n generating_question: \"Generating dynamic question...\",\n translating: \"Translating question dynamically...\",\n prompt_answer: \"Your answer (Enter to reveal · 'q' to stop):\",\n session_ended: \"Learning session ended.\",\n session_complete: \"Learning session complete!\",\n cards_rated: \" Cards rated: {count}\",\n avg_rating: \" Average rating: {avg}\",\n forgot: \" Forgot: {count} card(s)\",\n feedback_title: \"── ZAM Feedback {line}\",\n answer_title: \"── Answer {line}\",\n keep_waiting: \"Would you like to keep waiting?\",\n local_ai_working: \"The local AI is still generating the response.\",\n wait_warning: \"⚠ The LLM server is taking a while to load the model.\",\n wait_info:\n \"(This is expected when transitioning between models or starting up from cold.)\",\n keep_waiting_llm: \"Would you like to keep waiting for the model?\",\n proceeding_offline:\n \"⚠ Proceeding in offline-mode (without active LLM evaluations for this session).\",\n eval_skipped: \" [LLM Evaluation skipped: {reason}]\",\n },\n de: {\n welcome: \"Lern-Session: {count} Karte(n)\",\n new_review_relearn:\n \" Neu: {newC} Wiederholen: {reviewC} Lernen: {relearnC}\",\n domains: \" Domänen: {domains}\",\n instruction:\n \"\\nRufe jede Antwort zuerst ab, decke sie auf und bewerte dich dann ehrlich selbst.\",\n quit_hint:\n \"Gib 'q' bei der Antwortaufforderung ein (oder drücke Strg+C), um jederzeit zu beenden.\",\n offline_warning:\n \"\\n\\x1b[33m⚠ LLM-Feedback & automatische Übersetzung sind deaktiviert.\\x1b[0m\",\n offline_instruction:\n \" Aktivieren mit: \\x1b[36mnpm run dev -- settings llm on\\x1b[0m\\n\",\n nothing_due: \"Nichts fällig zu lernen. Du bist komplett auf dem Laufenden!\",\n evaluating: \"Bewerte Antwort via lokaler KI...\",\n generating_question: \"Generiere dynamische Frage...\",\n translating: \"Übersetze Frage dynamisch...\",\n prompt_answer: \"Deine Antwort (Eingabe zum Aufdecken · 'q' zum Beenden):\",\n session_ended: \"Lern-Session beendet.\",\n session_complete: \"Lern-Session abgeschlossen!\",\n cards_rated: \" Bewertete Karten: {count}\",\n avg_rating: \" Durchschnittliche Bewertung: {avg}\",\n forgot: \" Vergessen: {count} Karte(n)\",\n feedback_title: \"── ZAM Feedback {line}\",\n answer_title: \"── Antwort {line}\",\n keep_waiting: \"Möchtest du weiter auf die Bewertung warten?\",\n local_ai_working: \"Die lokale KI arbeitet noch an der Antwort.\",\n wait_warning:\n \"⚠ Der LLM-Server braucht ungewöhnlich lange, um das Modell zu laden.\",\n wait_info:\n \"(Das ist normal, wenn das Modell gewechselt wird oder kalt startet.)\",\n keep_waiting_llm: \"Möchtest du weiter auf das Modell warten?\",\n proceeding_offline:\n \"⚠ Fahre im Offline-Modus fort (ohne aktive LLM-Bewertungen in dieser Runde).\",\n eval_skipped: \" [LLM-Bewertung übersprungen: {reason}]\",\n },\n es: {\n welcome: \"Sesión de aprendizaje: {count} tarjeta(s)\",\n new_review_relearn:\n \" Nuevas: {newC} Repasar: {reviewC} Reaprender: {relearnC}\",\n domains: \" Dominios: {domains}\",\n instruction:\n \"\\nRecuerda cada respuesta primero, revélala y califícate honestamente.\",\n quit_hint:\n \"Escribe 'q' en la respuesta (o presiona Ctrl+C) para salir en cualquier momento.\",\n offline_warning:\n \"\\n\\x1b[33m⚠ Los comentarios de LLM y la traducción automática están desactivados.\\x1b[0m\",\n offline_instruction:\n \" Activar con: \\x1b[36mnpm run dev -- settings llm on\\x1b[0m\\n\",\n nothing_due: \"No hay nada pendiente para aprender. ¡Estás al día!\",\n evaluating: \"Evaluando respuesta con IA local...\",\n generating_question: \"Generando pregunta dinámica...\",\n translating: \"Traduciendo pregunta dinámicamente...\",\n prompt_answer: \"Tu respuesta (Intro para revelar · 'q' para salir):\",\n session_ended: \"Sesión de aprendizaje finalizada.\",\n session_complete: \"¡Sesión de aprendizaje completada!\",\n cards_rated: \" Tarjetas calificadas: {count}\",\n avg_rating: \" Calificación promedio: {avg}\",\n forgot: \" Olvidadas: {count} tarjeta(s)\",\n feedback_title: \"── Comentarios de ZAM {line}\",\n answer_title: \"── Respuesta {line}\",\n keep_waiting: \"¿Deseas seguir esperando la evaluación?\",\n local_ai_working: \"La IA local todavía está generando la respuesta.\",\n wait_warning: \"⚠ El servidor LLM está tardando en cargar el modelo.\",\n wait_info: \"(Esto es normal al cambiar de modelo o iniciar en frío.)\",\n keep_waiting_llm: \"¿Deseas seguir esperando el modelo?\",\n proceeding_offline:\n \"⚠ Continuando en modo fuera de línea (sin evaluaciones de LLM en esta sesión).\",\n eval_skipped: \" [Evaluación de LLM omitida: {reason}]\",\n },\n fr: {\n welcome: \"Session d'apprentissage : {count} carte(s)\",\n new_review_relearn:\n \" Nouveau: {newC} Révision: {reviewC} Relever: {relearnC}\",\n domains: \" Domaines: {domains}\",\n instruction:\n \"\\nRappelez-vous chaque réponse d'abord, révélez-la, puis évaluez-vous honnêtement.\",\n quit_hint: \"Tapez 'q' (ou Ctrl+C) pour quitter à tout moment.\",\n offline_warning:\n \"\\n\\x1b[33m⚠ Les commentaires LLM et la traduction automatique sont désactivés.\\x1b[0m\",\n offline_instruction:\n \" Activer avec : \\x1b[36mnpm run dev -- settings llm on\\x1b[0m\\n\",\n nothing_due: \"Rien à apprendre. Vous êtes à jour !\",\n evaluating: \"Évaluation de la réponse via l'IA locale...\",\n generating_question: \"Génération d'une question dynamique...\",\n translating: \"Traduction dynamique de la question...\",\n prompt_answer: \"Votre réponse (Entrée pour révéler · 'q' pour quitter) :\",\n session_ended: \"Session d'apprentissage arrêtée.\",\n session_complete: \"Session d'apprentissage terminée !\",\n cards_rated: \" Cartes évaluées: {count}\",\n avg_rating: \" Note moyenne: {avg}\",\n forgot: \" Oubliées: {count} carte(s)\",\n feedback_title: \"── Commentaires ZAM {line}\",\n answer_title: \"── Réponse {line}\",\n keep_waiting: \"Voulez-vous continuer à attendre l'évaluation ?\",\n local_ai_working:\n \"L'IA locale est toujours en train de générer la réponse.\",\n wait_warning: \"⚠ Le serveur LLM prend du temps pour charger le modèle.\",\n wait_info:\n \"(Ceci est normal lors de la transition entre modèles ou du démarrage à froid.)\",\n keep_waiting_llm: \"Voulez-vous continuer à attendre le modèle ?\",\n proceeding_offline:\n \"⚠ Poursuite en mode hors ligne (sans évaluation active de l'IA pour cette session).\",\n eval_skipped: \" [Évaluation LLM ignorée : {reason}]\",\n },\n pt: {\n welcome: \"Sessão de aprendizado: {count} cartão(ões)\",\n new_review_relearn:\n \" Novos: {newC} Revisar: {reviewC} Reaprender: {relearnC}\",\n domains: \" Domínios: {domains}\",\n instruction:\n \"\\nLembre-se de cada resposta primeiro, revele-a e avalie-se honestamente.\",\n quit_hint: \"Digite 'q' (ou Ctrl+C) para parar a qualquer momento.\",\n offline_warning:\n \"\\n\\x1b[33m⚠ O feedback do LLM e a tradução automática estão desativados.\\x1b[0m\",\n offline_instruction:\n \" Ativar com: \\x1b[36mnpm run dev -- settings llm on\\x1b[0m\\n\",\n nothing_due: \"Nada faturado para aprender. Você está atualizado!\",\n evaluating: \"Avaliando a resposta via IA local...\",\n generating_question: \"Gerando pergunta dinâmica...\",\n translating: \"Traduzindo pergunta dinamicamente...\",\n prompt_answer: \"Sua resposta (Enter para revelar · 'q' para parar):\",\n session_ended: \"Sessão de aprendizado encerrada.\",\n session_complete: \"Sessão de aprendizado concluída!\",\n cards_rated: \" Cartões avaliados: {count}\",\n avg_rating: \" Nota média: {avg}\",\n forgot: \" Esquecidos: {count} cartão(ões)\",\n feedback_title: \"── Feedback ZAM {line}\",\n answer_title: \"── Resposta {line}\",\n keep_waiting: \"Deseja continuar esperando pela avaliação?\",\n local_ai_working: \"A IA local ainda está gerando a resposta.\",\n wait_warning: \"⚠ O servidor LLM está demorando para carregar o modelo.\",\n wait_info: \"(Isso é esperado ao alternar modelos ou iniciar do zero.)\",\n keep_waiting_llm: \"Deseja continuar esperando o modelo?\",\n proceeding_offline:\n \"⚠ Continuando no modo offline (sem avaliações de LLM ativas nesta sessão).\",\n eval_skipped: \" [Avaliação LLM omitida: {reason}]\",\n },\n zh: {\n welcome: \"学习课: {count} 张卡片\",\n new_review_relearn: \" 新卡: {newC} 复习: {reviewC} 重学: {relearnC}\",\n domains: \" 知识领域: {domains}\",\n instruction: \"\\n首先在脑中回忆答案,然后揭晓并诚实自我评分。\",\n quit_hint: \"在回答提示处输入 'q' (或按 Ctrl+C) 可随时退出。\",\n offline_warning: \"\\n\\x1b[33m⚠ LLM 反馈与自动翻译已禁用。\\x1b[0m\",\n offline_instruction:\n \" 开启命令: \\x1b[36mnpm run dev -- settings llm on\\x1b[0m\\n\",\n nothing_due: \"目前没有需要学习的内容。您已全部掌握!\",\n evaluating: \"正在通过本地 AI 评估回答...\",\n generating_question: \"正在动态生成问题...\",\n translating: \"正在动态翻译问题...\",\n prompt_answer: \"您的回答 (按回车揭晓 · 输入 'q' 退出):\",\n session_ended: \"学习课已结束。\",\n session_complete: \"学习课已完成!\",\n cards_rated: \" 已评分卡片: {count}\",\n avg_rating: \" 平均分: {avg}\",\n forgot: \" 遗忘: {count} 张卡片\",\n feedback_title: \"── ZAM 反馈 {line}\",\n answer_title: \"── 参考答案 {line}\",\n keep_waiting: \"是否继续等待评分?\",\n local_ai_working: \"本地 AI 仍在生成回答。\",\n wait_warning: \"⚠ LLM 服务器正在加载模型,这可能需要一些时间。\",\n wait_info: \"(这在切换模型或冷启动时是正常现象。)\",\n keep_waiting_llm: \"是否继续等待模型加载?\",\n proceeding_offline:\n \"⚠ 正在以离线模式继续(本次学习课将不包含活跃的 AI 评估)。\",\n eval_skipped: \" [已跳过 LLM 评估: {reason}]\",\n },\n ja: {\n welcome: \"学習セッション: {count} 枚のカード\",\n new_review_relearn: \" 新規: {newC} 復習: {reviewC} 再学習: {relearnC}\",\n domains: \" ドメイン: {domains}\",\n instruction:\n \"\\n最初に回答を思い出し、次に回答を表示して、正直に自己評価してください。\",\n quit_hint:\n \"回答プロンプトで「q」を入力する(または Ctrl+C を押す)と、いつでも終了できます。\",\n offline_warning:\n \"\\n\\x1b[33m⚠ LLM フィードバックと自動翻訳は無効です。\\x1b[0m\",\n offline_instruction:\n \" 有効化するには: \\x1b[36mnpm run dev -- settings llm on\\x1b[0m\\n\",\n nothing_due: \"学習予定のカードはありません。すべて完了しています!\",\n evaluating: \"ローカルAIによる回答の評価中...\",\n generating_question: \"質問を動的に生成中...\",\n translating: \"質問を動的に翻訳中...\",\n prompt_answer: \"あなたの回答 (Enterで表示 · 'q'で終了):\",\n session_ended: \"学習セッションが終了しました。\",\n session_complete: \"学習セッションが完了しました!\",\n cards_rated: \" 評価済みカード数: {count}\",\n avg_rating: \" 平均評価: {avg}\",\n forgot: \" 忘れたカード数: {count} 枚\",\n feedback_title: \"── ZAM フィードバック {line}\",\n answer_title: \"── 解答 {line}\",\n keep_waiting: \"評価の生成を待ちますか?\",\n local_ai_working: \"ローカルAIが回答を生成しています。\",\n wait_warning:\n \"⚠ LLM サーバーがモデルをロードするのに時間がかかっています。\",\n wait_info: \"(モデルの移行中やコールドスタート時には、これが予想されます。)\",\n keep_waiting_llm: \"モデルのロードを待ち続けますか?\",\n proceeding_offline:\n \"⚠ オフラインモードで続行します(このセッションではアクティブな AI 評価は行われません)。\",\n eval_skipped: \" [LLM 評価がスキップされました: {reason}]\",\n },\n};\n\n/**\n * Format and interpolate a translation string with key-value params.\n */\nexport function t(\n locale: SupportedLocale,\n key: TranslationKey,\n params: Record<string, string | number> = {},\n): string {\n const dict = TRANSLATIONS[locale] || TRANSLATIONS.en;\n let str = dict[key] || TRANSLATIONS.en[key] || \"\";\n\n for (const [k, v] of Object.entries(params)) {\n str = str.replace(new RegExp(`{${k}}`, \"g\"), String(v));\n }\n\n return str;\n}\n","import { execSync } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nexport interface InstallResult {\n success: boolean;\n message: string;\n}\n\n/**\n * Check if a command is executable on the system.\n */\nexport function hasCommand(cmd: string): boolean {\n try {\n const checkCmd =\n process.platform === \"win32\" ? `where ${cmd}` : `which ${cmd}`;\n execSync(checkCmd, { stdio: \"ignore\" });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Install FastFlowLM via winget on Windows.\n */\nexport function installFastFlowLM(): InstallResult {\n if (process.platform !== \"win32\") {\n return {\n success: false,\n message: \"FastFlowLM is only supported on Windows.\",\n };\n }\n\n // Check if already installed\n const hasFlm =\n hasCommand(\"flm\") || existsSync(\"C:\\\\Program Files\\\\flm\\\\flm.exe\");\n if (hasFlm) {\n return { success: true, message: \"FastFlowLM is already installed.\" };\n }\n\n if (!hasCommand(\"winget\")) {\n return {\n success: false,\n message: \"winget package manager was not found on this system.\",\n };\n }\n\n console.log(\"Installing FastFlowLM via winget...\");\n try {\n // -e option exact match, --accept-source-agreements --accept-package-agreements\n execSync(\n \"winget install -e --id FastFlowLM --accept-source-agreements --accept-package-agreements\",\n { stdio: \"inherit\" },\n );\n return { success: true, message: \"FastFlowLM installed successfully.\" };\n } catch (err) {\n return {\n success: false,\n message: `Failed to install FastFlowLM: ${(err as Error).message}`,\n };\n }\n}\n\n/**\n * Install Ollama via Homebrew on macOS.\n */\nexport function installOllama(): InstallResult {\n // Check if already installed\n const isMac = process.platform === \"darwin\";\n const isWin = process.platform === \"win32\";\n const hasOllama =\n hasCommand(\"ollama\") ||\n (isMac && existsSync(\"/Applications/Ollama.app\")) ||\n (isWin &&\n existsSync(\n join(homedir(), \"AppData\", \"Local\", \"Programs\", \"Ollama\", \"ollama.exe\"),\n ));\n\n if (hasOllama) {\n return { success: true, message: \"Ollama is already installed.\" };\n }\n\n if (process.platform === \"darwin\") {\n if (!hasCommand(\"brew\")) {\n return {\n success: false,\n message:\n \"Homebrew was not found. Please install Homebrew from brew.sh first.\",\n };\n }\n console.log(\"Installing Ollama via Homebrew Cask...\");\n try {\n execSync(\"brew install --cask ollama\", { stdio: \"inherit\" });\n return { success: true, message: \"Ollama installed successfully.\" };\n } catch (err) {\n return {\n success: false,\n message: `Failed to install Ollama: ${(err as Error).message}`,\n };\n }\n } else if (process.platform === \"win32\") {\n if (!hasCommand(\"winget\")) {\n return {\n success: false,\n message: \"winget was not found. Please install winget first.\",\n };\n }\n console.log(\"Installing Ollama via winget...\");\n try {\n execSync(\n \"winget install -e --id Ollama.Ollama --accept-source-agreements --accept-package-agreements\",\n { stdio: \"inherit\" },\n );\n return { success: true, message: \"Ollama installed successfully.\" };\n } catch (err) {\n return {\n success: false,\n message: `Failed to install Ollama: ${(err as Error).message}`,\n };\n }\n } else {\n // Linux installer script\n console.log(\"Installing Ollama via official installer script...\");\n try {\n execSync(\"curl -fsSL https://ollama.com/install.sh | sh\", {\n stdio: \"inherit\",\n });\n return { success: true, message: \"Ollama installed successfully.\" };\n } catch (err) {\n return {\n success: false,\n message: `Failed to install Ollama: ${(err as Error).message}`,\n };\n }\n }\n}\n","import { execSync } from \"node:child_process\";\n\nexport type SupportedLocale = \"en\" | \"de\" | \"es\" | \"fr\" | \"pt\" | \"zh\" | \"ja\";\n\nconst SUPPORTED_LOCALES: Set<SupportedLocale> = new Set([\n \"en\",\n \"de\",\n \"es\",\n \"fr\",\n \"pt\",\n \"zh\",\n \"ja\",\n]);\n\n/**\n * Clean and map raw locale string (e.g., \"de_DE.UTF-8\" or \"en-US\") to SupportedLocale.\n */\nexport function normalizeLocale(raw: string): SupportedLocale {\n const clean = raw.trim().toLowerCase().split(/[_-]/)[0];\n if (SUPPORTED_LOCALES.has(clean as SupportedLocale)) {\n return clean as SupportedLocale;\n }\n return \"en\";\n}\n\n/**\n * Detect the operating system's active language code dynamically.\n */\nexport function detectSystemLocale(): SupportedLocale {\n try {\n // 1. Check standard POSIX env vars (common on macOS/Linux/Git Bash/WSL)\n const envVars = [\n process.env.LANG,\n process.env.LANGUAGE,\n process.env.LC_ALL,\n process.env.LC_MESSAGES,\n ];\n\n for (const val of envVars) {\n if (val && val.trim().length > 0) {\n return normalizeLocale(val);\n }\n }\n\n // 2. On Windows, fallback to querying PowerShell Culture\n if (process.platform === \"win32\") {\n const output = execSync(\n 'powershell -NoProfile -Command \"[System.Globalization.CultureInfo]::CurrentCulture.Name\"',\n { stdio: \"pipe\", encoding: \"utf8\", timeout: 2000 },\n ).trim();\n if (output && output.length > 0) {\n return normalizeLocale(output);\n }\n }\n } catch {\n // Ignore errors and default to English\n }\n\n return \"en\";\n}\n","import { execSync } from \"node:child_process\";\n\nexport interface SystemProfile {\n os: \"windows\" | \"macos\" | \"linux\" | \"unknown\";\n arch: \"x64\" | \"arm64\" | \"unknown\";\n hasRyzenNPU: boolean;\n hasAppleSilicon: boolean;\n recommendedRunner: \"fastflowlm\" | \"ollama\" | \"generic\";\n recommendedModel: string;\n}\n\n/**\n * Run a shell command synchronously and return stdout.\n * Returns empty string on failure.\n */\nfunction runCommand(cmd: string): string {\n try {\n return execSync(cmd, { stdio: \"pipe\", encoding: \"utf8\" }).trim();\n } catch {\n return \"\";\n }\n}\n\nfunction detectWindowsAMDIPU(): boolean {\n if (process.platform !== \"win32\") return false;\n\n // WMI query for AMD IPU (Image Processing Unit), NPU, Ryzen AI CPUs, and modern NPU compute devices (DEV_1502, DEV_17F0)\n const cmd = `powershell -NoProfile -Command \"Get-CimInstance Win32_PnPEntity | Where-Object { $_.Name -like '*AMD IPU*' -or $_.Name -like '*AMD NPU*' -or $_.Name -like '*NPU Compute*' -or $_.Name -like '*Ryzen AI*' -or $_.HardwareID -like '*VEN_1022&DEV_1502*' -or $_.HardwareID -like '*VEN_1022&DEV_17F0*' } | Select-Object -First 1 -ExpandProperty Name\"`;\n const output = runCommand(cmd);\n\n return Boolean(\n output &&\n (output.toLowerCase().includes(\"amd\") ||\n output.toLowerCase().includes(\"ipu\") ||\n output.toLowerCase().includes(\"npu\") ||\n output.toLowerCase().includes(\"ryzen\")),\n );\n}\n\n/**\n * Profile the active system hardware and software capabilities.\n */\nexport function getSystemProfile(): SystemProfile {\n const platform = process.platform;\n const archStr = process.arch;\n\n let os: \"windows\" | \"macos\" | \"linux\" | \"unknown\" = \"unknown\";\n if (platform === \"win32\") os = \"windows\";\n else if (platform === \"darwin\") os = \"macos\";\n else if (platform === \"linux\") os = \"linux\";\n\n let arch: \"x64\" | \"arm64\" | \"unknown\" = \"unknown\";\n if (archStr === \"x64\") arch = \"x64\";\n else if (archStr === \"arm64\") arch = \"arm64\";\n\n const hasRyzenNPU = os === \"windows\" && detectWindowsAMDIPU();\n const hasAppleSilicon = os === \"macos\" && arch === \"arm64\";\n\n let recommendedRunner: \"fastflowlm\" | \"ollama\" | \"generic\" = \"generic\";\n let recommendedModel = \"qwen3.5:4b\";\n\n if (hasRyzenNPU) {\n recommendedRunner = \"fastflowlm\";\n recommendedModel = \"qwen3.5:4b\";\n } else if (hasAppleSilicon) {\n recommendedRunner = \"ollama\";\n recommendedModel = \"llama3.2:3b\";\n } else if (os === \"macos\" || os === \"linux\" || os === \"windows\") {\n // Standard PC / generic Mac\n recommendedRunner = \"ollama\";\n recommendedModel = \"llama3.2:3b\";\n }\n\n return {\n os,\n arch,\n hasRyzenNPU,\n hasAppleSilicon,\n recommendedRunner,\n recommendedModel,\n };\n}\n","import { existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { Database } from \"libsql\";\nimport { getSetting } from \"../models/settings.js\";\n\nexport interface RepoPaths {\n personal: string | null;\n team: string | null;\n org: string | null;\n}\n\n/**\n * Resolve absolute paths for personal, team, and organization repositories.\n * Personal falls back to personal.workspace_dir if repo.personal is not set.\n */\nexport function getRepoPaths(db: Database): RepoPaths {\n const personalSetting =\n getSetting(db, \"repo.personal\") || getSetting(db, \"personal.workspace_dir\");\n const teamSetting = getSetting(db, \"repo.team\");\n const orgSetting = getSetting(db, \"repo.org\");\n\n return {\n personal: personalSetting ? resolve(personalSetting) : null,\n team: teamSetting ? resolve(teamSetting) : null,\n org: orgSetting ? resolve(orgSetting) : null,\n };\n}\n\n/**\n * Resolve a specific repo's path, or null if not configured.\n */\nexport function resolveRepoPath(\n db: Database,\n type: \"personal\" | \"team\" | \"org\",\n): string | null {\n const paths = getRepoPaths(db);\n return paths[type];\n}\n\n/**\n * Resolve paths to all existing \"/beliefs\" directories in the hierarchy,\n * sorted from most specific (personal) to most general (org).\n */\nexport function resolveAllBeliefPaths(db: Database): string[] {\n const paths = getRepoPaths(db);\n const dirs: string[] = [];\n\n if (paths.personal) {\n const personalDir = resolve(paths.personal, \"beliefs\");\n if (existsSync(personalDir)) dirs.push(personalDir);\n }\n if (paths.team) {\n const teamDir = resolve(paths.team, \"beliefs\");\n if (existsSync(teamDir)) dirs.push(teamDir);\n }\n if (paths.org) {\n const orgDir = resolve(paths.org, \"beliefs\");\n if (existsSync(orgDir)) dirs.push(orgDir);\n }\n\n return dirs;\n}\n\n/**\n * Resolve paths to all existing \"/goals\" directories in the hierarchy,\n * sorted from most specific (personal) to most general (org).\n */\nexport function resolveAllGoalPaths(db: Database): string[] {\n const paths = getRepoPaths(db);\n const dirs: string[] = [];\n\n if (paths.personal) {\n const personalDir = resolve(paths.personal, \"goals\");\n if (existsSync(personalDir)) dirs.push(personalDir);\n }\n if (paths.team) {\n const teamDir = resolve(paths.team, \"goals\");\n if (existsSync(teamDir)) dirs.push(teamDir);\n }\n if (paths.org) {\n const orgDir = resolve(paths.org, \"goals\");\n if (existsSync(orgDir)) dirs.push(orgDir);\n }\n\n return dirs;\n}\n","/**\n * Local LLM client — CLI/harness layer.\n *\n * This module talks to a user-run, OpenAI-compatible local LLM server\n * (FastFlowLM `flm serve`, Ollama, LM Studio, …). It deliberately lives in the\n * CLI layer, NOT the kernel: the kernel is AI-agnostic and carries zero LLM\n * dependencies (see CLAUDE.md). Everything that does HTTP, spawns runner\n * processes, prints to the terminal, or prompts interactively belongs here.\n *\n * Config is read from kernel settings via a single `getLlmConfig` helper so the\n * default model lives in exactly one place (it changes every few weeks as local\n * models improve).\n */\n\nimport { spawn } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport type { Database } from \"libsql\";\nimport type { SupportedLocale } from \"../../kernel/index.js\";\nimport {\n getSetting,\n getSystemProfile,\n hasCommand,\n resolveReviewContext,\n t,\n updateToken,\n} from \"../../kernel/index.js\";\n\n/** Single source of truth for connection defaults (easy to bump as models evolve). */\nexport const DEFAULT_LLM_URL = \"http://localhost:8000/v1\";\nexport const DEFAULT_LLM_MODEL = \"gemma4-it:e4b\";\nexport const DEFAULT_LLM_API_KEY = \"sk-none\";\n\nexport interface LlmConfig {\n enabled: boolean;\n url: string;\n model: string;\n apiKey: string;\n locale: SupportedLocale;\n}\n\n/** Read all LLM-related settings at once, applying defaults in one place. */\nexport function getLlmConfig(db: Database): LlmConfig {\n return {\n enabled: getSetting(db, \"llm.enabled\") === \"true\",\n url: getSetting(db, \"llm.url\") || DEFAULT_LLM_URL,\n model: getSetting(db, \"llm.model\") || DEFAULT_LLM_MODEL,\n apiKey: getSetting(db, \"llm.api_key\") || DEFAULT_LLM_API_KEY,\n locale: (getSetting(db, \"system.locale\") || \"en\") as SupportedLocale,\n };\n}\n\nconst LANGUAGE_NAMES: Record<SupportedLocale, string> = {\n en: \"English\",\n de: \"German\",\n es: \"Spanish\",\n fr: \"French\",\n pt: \"Portuguese\",\n zh: \"Chinese\",\n ja: \"Japanese\",\n};\n\nconst LOCALIZED_RATING_PREFIX: Record<SupportedLocale, string> = {\n en: \"Suggested rating\",\n de: \"Empfohlene Bewertung\",\n es: \"Calificación sugerida\",\n fr: \"Note suggérée\",\n pt: \"Avaliação sugerida\",\n zh: \"建议评分\",\n ja: \"推奨評価\",\n};\n\nconst BLOOM_VERBS = {\n 1: \"Remember\",\n 2: \"Understand\",\n 3: \"Apply\",\n 4: \"Analyze\",\n 5: \"Synthesize\",\n} as const;\n\ninterface ChatCompletionResponse {\n choices?: Array<{ message?: { content?: string } }>;\n}\n\n/** Extract the assistant message content from an OpenAI-compatible response. */\nasync function readChatContent(res: Response, label: string): Promise<string> {\n if (!res.ok) {\n const errorText = await res.text().catch(() => \"\");\n throw new Error(\n `${label} failed: ${res.statusText} (${res.status}) - ${errorText}`,\n );\n }\n const data = (await res.json()) as ChatCompletionResponse;\n const content = data.choices?.[0]?.message?.content;\n if (!content) {\n throw new Error(\"Empty response from LLM\");\n }\n return content.trim();\n}\n\n/**\n * Generate a high-quality, concept-free active-recall question using the local LLM.\n */\nexport async function generateQuestionViaLLM(\n db: Database,\n input: {\n slug: string;\n concept: string;\n domain: string;\n bloomLevel: number;\n context?: string;\n sourceLinkContent?: string | null;\n },\n): Promise<string> {\n const cfg = getLlmConfig(db);\n if (!cfg.enabled) {\n throw new Error(\"LLM integration is disabled in settings (llm.enabled)\");\n }\n\n const bloom = (\n input.bloomLevel >= 1 && input.bloomLevel <= 5 ? input.bloomLevel : 1\n ) as keyof typeof BLOOM_VERBS;\n const verb = BLOOM_VERBS[bloom];\n\n const langName = LANGUAGE_NAMES[cfg.locale] || \"English\";\n\n const systemPrompt = `You are ZAM, a highly precise agentic skills trainer.\nYour task is to generate a single, clear, conceptual active-recall question (flashcard front) in ${langName} for a knowledge token.\n\nGuidelines:\n1. The question MUST match the Bloom level: ${verb} (Level ${bloom}).\n2. CRITICAL: The question MUST NOT contain or reveal the concept text itself! The concept is the answer (flashcard back) that the learner needs to recall.\n3. Keep the question concise, highly specific, and clear. Avoid generic prompts like \"What is the concept of...\" if possible, and ask about the core mechanism, function, or purpose of the slug/concept without giving the answer away.\n4. Output ONLY the raw question text in ${langName}. Do not include any preamble, headers, markdown fences, or conversational filler.`;\n\n const userPrompt = `Domain: ${input.domain}\nSlug: ${input.slug}\nConcept to Recall (DO NOT REVEAL IN QUESTION): ${input.concept}\nContext: ${input.context || \"(none)\"}\n${input.sourceLinkContent ? `Source Reference:\\n${input.sourceLinkContent}` : \"\"}\n\nActive-Recall Question:`;\n\n const res = await fetchWithInteractiveTimeout(`${cfg.url}/chat/completions`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${cfg.apiKey}`,\n },\n body: JSON.stringify({\n model: cfg.model,\n messages: [\n { role: \"system\", content: systemPrompt },\n { role: \"user\", content: userPrompt },\n ],\n temperature: 0.1,\n max_tokens: 150,\n }),\n locale: cfg.locale,\n });\n\n return readChatContent(res, \"LLM request\");\n}\n\n/**\n * Warmly evaluate the learner's active-recall answer against the target concept.\n * Suggests an FSRS rating (1-4) and explains in the active locale with praise/motivation.\n */\nexport async function evaluateAnswerViaLLM(\n db: Database,\n input: {\n slug: string;\n concept: string;\n domain: string;\n bloomLevel: number;\n context?: string;\n question: string;\n userAnswer: string;\n sourceLinkContent?: string | null;\n },\n): Promise<string> {\n const cfg = getLlmConfig(db);\n if (!cfg.enabled) {\n throw new Error(\"LLM integration is disabled in settings (llm.enabled)\");\n }\n const langName = LANGUAGE_NAMES[cfg.locale] || \"English\";\n const ratingPrefix =\n LOCALIZED_RATING_PREFIX[cfg.locale] || \"Suggested rating\";\n\n const systemPrompt = `You are ZAM, an extremely warm, encouraging, and patient skills trainer.\nYour mission is to build lasting autonomy through conceptual knowledge, not rote procedure.\nCompare the learner's active-recall answer against the target concept, context, and optional source code.\n\nFSRS Rating scale:\n- 1: drew a blank / completely forgot or wrong (Again)\n- 2: hard recall / partially correct (Hard)\n- 3: knew it / mostly correct (Good)\n- 4: perfect, instant, and accurate recall (Easy)\n\nGuidelines:\n1. Provide a constructive, encouraging evaluation in ${langName} (2-3 sentences) to promote the joy of learning. Seamlessly weave a brief explanation of the correct solution (target concept) into your feedback paragraphs. Do NOT append a separate, duplicate reference answer or raw \"Musterlösung\" block at the end of your response.\n2. Celebrate every honest attempt! Offer high praise or a motivating word of encouragement in ${langName} if they did well or tried hard.\n3. CRITICAL: ZAM is a strict one-shot card flow, NOT an interactive chat. The correct Musterlösung (reference answer) is revealed alongside your feedback. Therefore, NEVER ask the user to think further, keep guessing, or suggest they try to solve the remaining parts of the question. Instead, immediately evaluate what they wrote, explain the complete solution and target concept directly.\n4. Suggest a clear FSRS rating (1 to 4) at the very end of your response in the exact format: \"${ratingPrefix}: X\" in ${langName}.\n5. Output ONLY the evaluation and rating suggestion. Keep it concise, friendly, and clean. No conversational introduction or markdown wrapper.`;\n\n const userPrompt = `Domain: ${input.domain}\nSlug: ${input.slug}\nRecall Question: ${input.question}\nLearner's Answer: ${input.userAnswer}\n\nTarget Concept (Correct Answer): ${input.concept}\nTarget Context: ${input.context || \"(none)\"}\n${input.sourceLinkContent ? `Source Code Reference:\\n${input.sourceLinkContent}` : \"\"}\n\nEvaluation:`;\n\n const res = await fetchWithInteractiveTimeout(`${cfg.url}/chat/completions`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${cfg.apiKey}`,\n },\n body: JSON.stringify({\n model: cfg.model,\n messages: [\n { role: \"system\", content: systemPrompt },\n { role: \"user\", content: userPrompt },\n ],\n temperature: 0.2,\n max_tokens: 300,\n }),\n locale: cfg.locale,\n });\n\n return readChatContent(res, \"LLM evaluation\");\n}\n\n/**\n * Translate a question into the active locale using the local LLM.\n */\nexport async function translateQuestionViaLLM(\n db: Database,\n question: string,\n): Promise<string> {\n const cfg = getLlmConfig(db);\n if (!cfg.enabled) {\n throw new Error(\"LLM integration is disabled in settings\");\n }\n const targetLang = LANGUAGE_NAMES[cfg.locale] || \"English\";\n\n const systemPrompt = `You are a highly precise translator. Translate the given active-recall question into clear, natural ${targetLang}.\nOutput ONLY the raw translation. Do not include any headers, preamble, quotes, or conversational filler.`;\n\n const res = await fetchWithInteractiveTimeout(`${cfg.url}/chat/completions`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${cfg.apiKey}`,\n },\n body: JSON.stringify({\n model: cfg.model,\n messages: [\n { role: \"system\", content: systemPrompt },\n { role: \"user\", content: question },\n ],\n temperature: 0.1,\n max_tokens: 150,\n }),\n locale: cfg.locale,\n });\n\n return readChatContent(res, \"Translation\");\n}\n\n/**\n * Checks if the LLM server is online and responsive at the specified URL.\n * A reachable server returning any HTTP status counts as online; only network\n * failures / timeouts count as offline.\n */\nexport async function isLlmOnline(url: string): Promise<boolean> {\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), 1500);\n // Check OpenAI standard /models list to verify readiness\n const res = await fetch(`${url}/models`, {\n method: \"GET\",\n signal: controller.signal,\n });\n clearTimeout(timeoutId);\n return res.ok || res.status < 500;\n } catch {\n return false;\n }\n}\n\n/**\n * List the model ids the server actually serves (OpenAI `/v1/models`).\n * Returns [] on any error so callers can treat \"unknown\" as \"skip validation\".\n */\nexport async function getAvailableModels(\n url: string,\n apiKey = DEFAULT_LLM_API_KEY,\n): Promise<string[]> {\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), 3000);\n const res = await fetch(`${url}/models`, {\n method: \"GET\",\n headers: { Authorization: `Bearer ${apiKey}` },\n signal: controller.signal,\n });\n clearTimeout(timeoutId);\n if (!res.ok) return [];\n const data = (await res.json()) as { data?: Array<{ id?: string }> };\n return (data.data ?? [])\n .map((m) => m.id)\n .filter((id): id is string => typeof id === \"string\" && id.length > 0);\n } catch {\n return [];\n }\n}\n\n/** Whether the local LLM can actually be used this session, and if not, why. */\nexport interface LlmReadiness {\n usable: boolean;\n reason?: \"disabled\" | \"offline\" | \"model-not-found\";\n}\n\ntype RunnerKind = \"fastflowlm\" | \"ollama\" | \"generic\" | \"unknown\";\n\n/** Pick the local runner from the URL port / model name (shared heuristic). */\nfunction detectRunner(\n url: string,\n model: string,\n): { runner: RunnerKind; port: string } {\n let runner: RunnerKind = \"unknown\";\n let port = \"8000\";\n try {\n const urlObj = new URL(url);\n port = urlObj.port || (urlObj.protocol === \"https:\" ? \"443\" : \"80\");\n if (\n port === \"8000\" ||\n port === \"8080\" ||\n model.includes(\"qwen\") ||\n model.includes(\"gemma\")\n ) {\n runner = \"fastflowlm\";\n } else if (port === \"11434\" || model.includes(\"llama\")) {\n runner = \"ollama\";\n }\n } catch {\n runner = getSystemProfile().recommendedRunner;\n }\n return { runner, port };\n}\n\n/**\n * Best-effort, SILENT runner start for non-interactive contexts (bridge / GUI).\n * No console output, no prompts — just spawn the detached server if we can.\n */\nfunction spawnLocalRunner(url: string, model: string): void {\n const { runner, port } = detectRunner(url, model);\n try {\n if (runner === \"fastflowlm\") {\n const flmExe = existsSync(\"C:\\\\Program Files\\\\flm\\\\flm.exe\")\n ? \"C:\\\\Program Files\\\\flm\\\\flm.exe\"\n : \"flm\";\n if (!hasCommand(\"flm\") && flmExe === \"flm\") return;\n spawn(flmExe, [\"serve\", model, \"--port\", port], {\n detached: true,\n stdio: \"ignore\",\n windowsHide: true,\n }).unref();\n } else if (runner === \"ollama\" || runner === \"generic\") {\n if (!hasCommand(\"ollama\")) return;\n spawn(\"ollama\", [\"serve\"], {\n detached: true,\n stdio: \"ignore\",\n windowsHide: true,\n }).unref();\n }\n } catch {\n // best-effort: caller polls for the server and reports offline if it fails\n }\n}\n\n/**\n * Detect the configured runner and start it, then poll until the server is\n * online (or the user opts out). Returns true once reachable, false otherwise.\n */\nasync function startLocalRunner(\n url: string,\n model: string,\n locale: SupportedLocale,\n): Promise<boolean> {\n const { runner, port } = detectRunner(url, model);\n\n if (runner === \"fastflowlm\") {\n const flmExe = existsSync(\"C:\\\\Program Files\\\\flm\\\\flm.exe\")\n ? \"C:\\\\Program Files\\\\flm\\\\flm.exe\"\n : \"flm\";\n if (!hasCommand(\"flm\") && flmExe === \"flm\") {\n console.warn(\n \"\\x1b[31m✗ FastFlowLM is configured but could not be found on the system.\\x1b[0m\",\n );\n console.warn(\"Please run 'zam init' or install it manually.\");\n return false;\n }\n const args = [\"serve\", model, \"--port\", port];\n console.log(\n `\\x1b[36mStarting FastFlowLM serve process: ${flmExe} ${args.join(\" \")}\\x1b[0m`,\n );\n try {\n spawn(flmExe, args, {\n detached: true,\n stdio: \"ignore\",\n windowsHide: true,\n }).unref();\n } catch (err) {\n console.error(\n `\\x1b[31m✗ Failed to launch FastFlowLM process: ${(err as Error).message}\\x1b[0m`,\n );\n return false;\n }\n } else if (runner === \"ollama\" || runner === \"generic\") {\n if (!hasCommand(\"ollama\")) {\n console.warn(\n \"\\x1b[31m✗ Ollama is configured but the 'ollama' command is not available in PATH.\\x1b[0m\",\n );\n console.warn(\"Please run 'zam init' or install it manually.\");\n return false;\n }\n console.log(\"\\x1b[36mStarting Ollama serve process: ollama serve\\x1b[0m\");\n try {\n spawn(\"ollama\", [\"serve\"], {\n detached: true,\n stdio: \"ignore\",\n windowsHide: true,\n }).unref();\n } catch (err) {\n console.error(\n `\\x1b[31m✗ Failed to launch Ollama process: ${(err as Error).message}\\x1b[0m`,\n );\n return false;\n }\n } else {\n console.warn(\n \"\\x1b[33m⚠ Unknown local LLM runner configured. Cannot auto-start.\\x1b[0m\",\n );\n return false;\n }\n\n // Poll until the server is online (or the user opts out).\n console.log(\n \"Waiting for LLM server to become responsive and load the model...\",\n );\n let attempts = 0;\n const dotsPerLine = 30;\n while (true) {\n await new Promise((resolve) => setTimeout(resolve, 500));\n if (await isLlmOnline(url)) {\n if (attempts > 0) process.stdout.write(\"\\n\");\n return true;\n }\n attempts++;\n process.stdout.write(\".\");\n if (attempts % dotsPerLine === 0) process.stdout.write(\"\\n\");\n\n // 60 attempts * 500ms = 30 seconds\n if (attempts >= 60) {\n process.stdout.write(\"\\n\");\n console.log(`\\x1b[33m${t(locale, \"wait_warning\")}\\x1b[0m`);\n console.log(`\\x1b[2m${t(locale, \"wait_info\")}\\x1b[0m`);\n\n const { confirm } = await import(\"@inquirer/prompts\");\n const keepWaiting = await confirm({\n message: t(locale, \"keep_waiting_llm\"),\n default: true,\n }).catch(() => false);\n\n if (!keepWaiting) {\n return false;\n }\n attempts = 0;\n }\n }\n}\n\n/**\n * Make the local LLM ready for the session and report whether it is usable.\n *\n * Starts the local runner if needed, then — crucially — verifies the configured\n * model is actually served. A wrong model name otherwise leaves the server\n * reachable but every request hanging/failing, which previously looked like\n * \"the AI is just slow\". We now fail fast with an actionable message instead.\n */\nexport async function ensureLocalLlmRunning(\n db: Database,\n): Promise<LlmReadiness> {\n const cfg = getLlmConfig(db);\n if (!cfg.enabled) {\n return { usable: false, reason: \"disabled\" };\n }\n\n const { url, model, apiKey, locale } = cfg;\n const isLocal = url.includes(\"localhost\") || url.includes(\"127.0.0.1\");\n\n console.log(`Checking if local LLM server is online at ${url}...`);\n let online = await isLlmOnline(url);\n\n if (!online && isLocal) {\n console.log(`\\x1b[33m⚠ Local LLM server is offline on ${url}.\\x1b[0m`);\n online = await startLocalRunner(url, model, locale);\n }\n\n if (!online) {\n console.warn(\n `\\x1b[33m⚠ LLM server is not reachable at ${url}. Continuing without AI coaching.\\x1b[0m\\n`,\n );\n return { usable: false, reason: \"offline\" };\n }\n\n console.log(\"\\x1b[32m✓ Local LLM server is online.\\x1b[0m\");\n\n // Validate the configured model against what the server actually serves, so\n // a typo / wrong tag fails immediately instead of hanging on every request.\n const available = await getAvailableModels(url, apiKey);\n const modelKnown =\n available.length === 0 ||\n available.some((m) => m.toLowerCase() === model.toLowerCase());\n\n if (!modelKnown) {\n console.warn(\n `\\x1b[31m✗ Configured model \"${model}\" is not available on the server.\\x1b[0m`,\n );\n console.warn(` Available models: ${available.join(\", \")}`);\n console.warn(\n ` Set the right one: \\x1b[36mzam settings set llm.model <name>\\x1b[0m`,\n );\n console.warn(\n \"\\x1b[33m Continuing this session without AI coaching.\\x1b[0m\\n\",\n );\n return { usable: false, reason: \"model-not-found\" };\n }\n\n return { usable: true };\n}\n\n/** Readiness plus the live status details a UI needs to render. */\nexport interface LlmReadyResult extends LlmReadiness {\n online: boolean;\n model: string;\n availableModels: string[];\n}\n\n/**\n * Non-interactive readiness check for the bridge / desktop GUI: start the local\n * runner if needed, wait (bounded) for it to come online, validate the model —\n * all WITHOUT console output or prompts, so the bridge's JSON stays clean.\n */\nexport async function ensureLlmReadyHeadless(\n db: Database,\n opts: { timeoutMs?: number } = {},\n): Promise<LlmReadyResult> {\n const timeoutMs = opts.timeoutMs ?? 25000;\n const { enabled, url, model, apiKey } = getLlmConfig(db);\n if (!enabled) {\n return {\n usable: false,\n reason: \"disabled\",\n online: false,\n model,\n availableModels: [],\n };\n }\n\n const isLocal = url.includes(\"localhost\") || url.includes(\"127.0.0.1\");\n\n let online = await isLlmOnline(url);\n if (!online && isLocal) {\n spawnLocalRunner(url, model);\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n await new Promise((r) => setTimeout(r, 1000));\n if (await isLlmOnline(url)) {\n online = true;\n break;\n }\n }\n }\n\n if (!online) {\n return {\n usable: false,\n reason: \"offline\",\n online: false,\n model,\n availableModels: [],\n };\n }\n\n const availableModels = await getAvailableModels(url, apiKey);\n const modelKnown =\n availableModels.length === 0 ||\n availableModels.some((m) => m.toLowerCase() === model.toLowerCase());\n if (!modelKnown) {\n return {\n usable: false,\n reason: \"model-not-found\",\n online: true,\n model,\n availableModels,\n };\n }\n\n return { usable: true, online: true, model, availableModels };\n}\n\n/**\n * Wraps a fetch call in an interactive wait loop with progress dots.\n * Every `timeoutMs`, prompts the user (in their locale) to keep waiting or skip.\n * In non-TTY / bridge contexts it degrades to a plain fetch.\n */\nexport async function fetchWithInteractiveTimeout(\n url: string,\n options: RequestInit & { timeoutMs?: number; locale?: SupportedLocale } = {},\n): Promise<Response> {\n const { timeoutMs = 20000, locale = \"en\", ...fetchOptions } = options;\n const controller = new AbortController();\n const fetchPromise = fetch(url, {\n ...fetchOptions,\n signal: controller.signal,\n });\n\n if (!process.stdout.isTTY || process.env.ZAM_BRIDGE === \"true\") {\n return fetchPromise;\n }\n\n let attempts = 0;\n const dotsPerLine = 30;\n while (true) {\n let timeoutId: NodeJS.Timeout | undefined;\n const timeoutPromise = new Promise<\"timeout\">((resolve) => {\n timeoutId = setTimeout(() => resolve(\"timeout\"), timeoutMs);\n });\n const dotsInterval = setInterval(() => {\n process.stdout.write(\".\");\n attempts++;\n if (attempts % dotsPerLine === 0) process.stdout.write(\"\\n\");\n }, 500);\n\n try {\n const result = await Promise.race([fetchPromise, timeoutPromise]);\n clearInterval(dotsInterval);\n clearTimeout(timeoutId);\n\n if (result !== \"timeout\") {\n if (attempts > 0) process.stdout.write(\"\\n\");\n return result;\n }\n\n // Timeout hit — ask the learner whether to keep waiting.\n console.log(`\\n\\x1b[33m${t(locale, \"local_ai_working\")}\\x1b[0m`);\n const { confirm } = await import(\"@inquirer/prompts\");\n const keepWaiting = await confirm({\n message: t(locale, \"keep_waiting\"),\n default: true,\n }).catch(() => false);\n\n if (!keepWaiting) {\n controller.abort();\n console.log(`\\x1b[33m${t(locale, \"proceeding_offline\")}\\x1b[0m\\n`);\n throw new Error(\"User cancelled waiting for slow LLM response\");\n }\n attempts = 0;\n } catch (err) {\n clearInterval(dotsInterval);\n clearTimeout(timeoutId);\n if (attempts > 0) process.stdout.write(\"\\n\");\n throw err;\n }\n }\n}\n\n/**\n * Ensures a token has a high-quality active-recall question.\n * When LLM is enabled, generates a fresh question on the fly, self-heals it into\n * the database, and returns it. Otherwise falls back to the stored question.\n */\nexport async function ensureHighQualityQuestion(\n db: Database,\n token: {\n id: string;\n slug: string;\n concept: string;\n domain: string;\n bloomLevel: number;\n sourceLink?: string | null;\n question?: string | null;\n },\n): Promise<string | null> {\n const { enabled } = getLlmConfig(db);\n\n if (enabled) {\n try {\n let sourceLinkContent: string | null = null;\n if (token.sourceLink) {\n const resolved = await resolveReviewContext(token.sourceLink).catch(\n () => null,\n );\n if (resolved) {\n sourceLinkContent = resolved.content;\n }\n }\n\n const generated = await generateQuestionViaLLM(db, {\n slug: token.slug,\n concept: token.concept,\n domain: token.domain,\n bloomLevel: token.bloomLevel,\n sourceLinkContent,\n });\n\n if (generated && generated.trim().length > 0) {\n // Persist the latest high-quality question as the offline fallback.\n updateToken(db, token.slug, { question: generated });\n return generated;\n }\n } catch {\n // Fail silently and fall back to the stored database question.\n }\n }\n\n if (token.question && token.question.trim().length > 0) {\n return token.question;\n }\n\n return null;\n}\n","/**\n * Resolve the active user ID from --user flag or stored whoami setting.\n */\n\nimport type { Database } from \"libsql\";\nimport { getSetting } from \"../../kernel/index.js\";\n\nexport interface ResolveUserOptions {\n /** If true, output JSON error instead of console.error (for bridge commands). */\n json?: boolean;\n}\n\n/**\n * Returns the user ID from the explicit --user flag, or falls back to the\n * stored `user.id` setting. Exits with an error if neither is available.\n */\nexport function resolveUser(\n opts: { user?: string },\n db: Database,\n resolveOpts?: ResolveUserOptions,\n): string {\n if (opts.user) return opts.user;\n\n const stored = getSetting(db, \"user.id\");\n if (stored) return stored;\n\n const message =\n \"No user specified. Set a default with: zam whoami --set <id>\";\n if (resolveOpts?.json) {\n console.log(JSON.stringify({ error: message }, null, 2));\n } else {\n console.error(message);\n }\n process.exit(1);\n}\n","/**\n * `zam card` — Card scheduling subcommand group.\n */\n\nimport { Command } from \"commander\";\nimport type { Database } from \"libsql\";\nimport type { Rating } from \"../../kernel/index.js\";\nimport {\n cascadeBlock,\n deleteCardForUser,\n ensureCard,\n evaluateRating,\n getCardDeletionImpact,\n getDueCards,\n getPrerequisites,\n getTokenBySlug,\n openDatabase,\n unblockReady,\n} from \"../../kernel/index.js\";\nimport { resolveUser } from \"./resolve-user.js\";\n\nfunction withDb(fn: (db: Database) => void): void {\n let db: Database | undefined;\n try {\n db = openDatabase();\n fn(db);\n } catch (err) {\n console.error(\"Error:\", (err as Error).message);\n process.exit(1);\n } finally {\n db?.close();\n }\n}\n\nexport const cardCommand = new Command(\"card\").description(\n \"Manage spaced-repetition cards\",\n);\n\n// ── zam card due ──────────────────────────────────────────────────────────\n\ncardCommand\n .command(\"due\")\n .description(\"Show due tokens for a user\")\n .option(\"--user <id>\", \"User ID (default: whoami)\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--summary\", \"Show only counts per domain (no slugs or concepts)\")\n .action((opts) => {\n withDb((db) => {\n const userId = resolveUser(opts, db);\n const dueCards = getDueCards(db, userId);\n\n if (opts.json) {\n console.log(JSON.stringify(dueCards, null, 2));\n return;\n }\n\n if (dueCards.length === 0) {\n console.log(\"No cards due for review.\");\n return;\n }\n\n if (opts.summary) {\n const byDomain = new Map<string, { count: number; blooms: number[] }>();\n for (const c of dueCards) {\n const d = c.domain || \"general\";\n const entry = byDomain.get(d) ?? { count: 0, blooms: [] };\n entry.count++;\n entry.blooms.push(c.bloom_level);\n byDomain.set(d, entry);\n }\n console.log(`${dueCards.length} card(s) due:\\n`);\n console.log(\"Domain Count Bloom levels\");\n console.log(\"─\".repeat(45));\n for (const [domain, { count, blooms }] of [\n ...byDomain.entries(),\n ].sort()) {\n const bloomStr = blooms.sort().join(\", \");\n console.log(\n `${domain.padEnd(16)} ${String(count).padEnd(6)} ${bloomStr}`,\n );\n }\n return;\n }\n\n console.log(`${dueCards.length} card(s) due:\\n`);\n console.log(\n \"Slug Concept Domain Bloom State\",\n );\n console.log(\"─\".repeat(90));\n for (const c of dueCards) {\n console.log(\n `${c.slug.padEnd(21)} ${c.concept.slice(0, 31).padEnd(31)} ${(c.domain || \"-\").padEnd(11)} ${String(c.bloom_level).padEnd(6)} ${c.state}`,\n );\n }\n });\n });\n\n// ── zam card update ───────────────────────────────────────────────────────\n\ncardCommand\n .command(\"update\")\n .description(\"Apply a rating to a card\")\n .option(\"--user <id>\", \"User ID (default: whoami)\")\n .requiredOption(\"--token <slug>\", \"Token slug\")\n .requiredOption(\"--rating <n>\", \"Rating (1=Again, 2=Hard, 3=Good, 4=Easy)\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--quiet\", \"Suppress output (exit code only)\")\n .action((opts) => {\n withDb((db) => {\n const userId = resolveUser(opts, db);\n const token = getTokenBySlug(db, opts.token);\n if (!token) {\n console.error(`Token not found: ${opts.token}`);\n process.exit(1);\n }\n\n const card = ensureCard(db, token.id, userId);\n const rating = Number(opts.rating) as Rating;\n\n if (rating < 1 || rating > 4) {\n console.error(\"Rating must be between 1 and 4.\");\n process.exit(1);\n }\n\n const result = evaluateRating(db, {\n cardId: card.id,\n tokenId: token.id,\n userId,\n rating,\n });\n\n // If rating is 1 (forgot) and token has prerequisites, cascade block\n if (rating === 1) {\n const prereqs = getPrerequisites(db, token.id);\n if (prereqs.length > 0) {\n const blockResult = cascadeBlock(db, userId, token.slug);\n if (opts.quiet) return;\n if (opts.json) {\n console.log(\n JSON.stringify(\n { evaluation: result, blocked: blockResult },\n null,\n 2,\n ),\n );\n } else {\n console.log(\n `Rated ${token.slug} as Again (1) — next due: ${result.nextDueAt}`,\n );\n console.log(\n `Blocked ${blockResult.blockedSlug}. Prerequisites surfaced:`,\n );\n for (const p of blockResult.prerequisites) {\n console.log(` - ${p.slug}: ${p.concept}`);\n }\n }\n return;\n }\n }\n\n if (opts.quiet) return;\n if (opts.json) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n const ratingLabels: Record<number, string> = {\n 1: \"Again\",\n 2: \"Hard\",\n 3: \"Good\",\n 4: \"Easy\",\n };\n console.log(\n `Rated ${token.slug} as ${ratingLabels[rating]} (${rating})`,\n );\n console.log(` Next due: ${result.nextDueAt}`);\n console.log(` Stability: ${result.stability.toFixed(2)}`);\n console.log(` State: ${result.state}`);\n console.log(` Reps: ${result.reps}`);\n }\n });\n });\n\n// ── zam card unblock ──────────────────────────────────────────────────────\n\ncardCommand\n .command(\"unblock\")\n .description(\"Unblock cards whose prerequisites are met\")\n .option(\"--user <id>\", \"User ID (default: whoami)\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--quiet\", \"Suppress output (exit code only)\")\n .action((opts) => {\n withDb((db) => {\n const userId = resolveUser(opts, db);\n const result = unblockReady(db, userId);\n\n if (opts.quiet) return;\n if (opts.json) {\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n\n if (result.unblocked.length === 0) {\n console.log(\"No cards ready to unblock.\");\n } else {\n console.log(`Unblocked ${result.unblocked.length} card(s):`);\n for (const u of result.unblocked) {\n console.log(` - ${u.slug}: ${u.concept}`);\n }\n }\n });\n });\n\n// ── zam card delete ───────────────────────────────────────────────────────\n\ncardCommand\n .command(\"delete\")\n .description(\"Delete one user's card for a token\")\n .option(\"--user <id>\", \"User ID (default: whoami)\")\n .requiredOption(\"--token <slug>\", \"Token slug\")\n .option(\"--json\", \"Output as JSON\")\n .action((opts) => {\n withDb((db) => {\n const userId = resolveUser(opts, db);\n const token = getTokenBySlug(db, opts.token);\n if (!token) {\n console.error(`Token not found: ${opts.token}`);\n process.exit(1);\n }\n\n const impact = getCardDeletionImpact(db, token.id, userId);\n const result = deleteCardForUser(db, token.id, userId);\n\n if (opts.json) {\n console.log(\n JSON.stringify(\n {\n token: opts.token,\n userId,\n deleted: true,\n cardId: result.card.id,\n impact: result.impact,\n },\n null,\n 2,\n ),\n );\n return;\n }\n\n console.log(`Deleted card for ${opts.token}`);\n console.log(` User: ${userId}`);\n console.log(` Card ID: ${result.card.id}`);\n console.log(` Review logs removed: ${impact.review_logs}`);\n });\n });\n","/**\n * `zam connector` — Manage external service connectors.\n */\n\nimport { input, password } from \"@inquirer/prompts\";\nimport { Command } from \"commander\";\nimport type { Database } from \"libsql\";\nimport { fetchActiveWorkItems } from \"../../kernel/connectors/azure-devops.js\";\nimport {\n clearADOCredentials,\n clearTursoCredentials,\n getADOCredentials,\n getTursoCredentials,\n setADOCredentials,\n setTursoCredentials,\n} from \"../../kernel/credentials.js\";\nimport { openDatabaseWithSync } from \"../../kernel/index.js\";\n\nexport const connectorCommand = new Command(\"connector\").description(\n \"Manage external service connectors\",\n);\n\n// ── zam connector setup ado ─────────────────────────────────────────────────\n\nconnectorCommand\n .command(\"setup\")\n .description(\"Configure a connector\")\n .argument(\"<type>\", \"Connector type (ado, turso)\")\n .option(\"--url <url>\", \"Turso database URL (non-interactive)\")\n .option(\"--token <token>\", \"Turso auth token (non-interactive)\")\n .action(async (type, opts) => {\n if (type === \"turso\") {\n return setupTurso(opts.url, opts.token);\n }\n if (type !== \"ado\") {\n console.error(`Unknown connector type: ${type}. Supported: ado, turso`);\n process.exit(1);\n }\n\n try {\n const orgUrl = await input({\n message: \"Organization URL (e.g. https://dev.azure.com/myorg):\",\n });\n const project = await input({\n message: \"Project name:\",\n });\n const pat = await password({\n message: \"Personal Access Token:\",\n });\n\n if (!orgUrl || !project || !pat) {\n console.error(\"All fields are required.\");\n process.exit(1);\n }\n\n setADOCredentials(orgUrl.replace(/\\/+$/, \"\"), project, pat);\n console.log(`Azure DevOps connector configured for ${orgUrl}/${project}`);\n } catch (err) {\n if ((err as Error).name === \"ExitPromptError\") {\n console.log(\"\\nSetup cancelled.\");\n process.exit(0);\n }\n console.error(\"Error:\", (err as Error).message);\n process.exit(1);\n }\n });\n\n// ── zam connector tasks ─────────────────────────────────────────────────────\n\nconnectorCommand\n .command(\"tasks\")\n .description(\"List active tasks from connected board\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (opts) => {\n try {\n const config = getADOCredentials();\n\n if (!config) {\n console.error(\"No connector configured. Run: zam connector setup ado\");\n process.exit(1);\n }\n\n const items = await fetchActiveWorkItems({\n orgUrl: config.org_url,\n project: config.project,\n pat: config.pat,\n });\n\n if (opts.json) {\n console.log(JSON.stringify(items, null, 2));\n return;\n }\n\n if (items.length === 0) {\n console.log(\"No active work items assigned to you.\");\n return;\n }\n\n console.log(`${items.length} active work item(s):\\n`);\n console.log(\"ID Type State Title\");\n console.log(\"─\".repeat(80));\n for (const wi of items) {\n console.log(\n `${String(wi.id).padEnd(8)} ${wi.type.padEnd(13)} ${wi.state.padEnd(11)} ${wi.title.slice(0, 45)}`,\n );\n }\n } catch (err) {\n console.error(\"Error:\", (err as Error).message);\n process.exit(1);\n }\n });\n\n// ── zam connector clear ─────────────────────────────────────────────────────\n\nconnectorCommand\n .command(\"clear\")\n .description(\"Remove a connector configuration\")\n .argument(\"<type>\", \"Connector type (ado, turso)\")\n .action((type) => {\n if (type === \"turso\") {\n clearTursoCredentials();\n console.log(\"Turso cloud sync removed. Database remains local-only.\");\n return;\n }\n\n if (type !== \"ado\") {\n console.error(`Unknown connector type: ${type}. Supported: ado, turso`);\n process.exit(1);\n }\n\n clearADOCredentials();\n console.log(\"Azure DevOps connector removed.\");\n });\n\n// ── zam connector sync ──────────────────────────────────────────────────────\n\nconnectorCommand\n .command(\"sync\")\n .description(\"Verify the Turso cloud database connection\")\n .action(() => {\n const turso = getTursoCredentials();\n if (!turso) {\n console.error(\n \"No Turso cloud database configured. Run: zam connector setup turso\",\n );\n process.exit(1);\n }\n\n let db: Database | undefined;\n try {\n db = openDatabaseWithSync({ initialize: true });\n db.prepare(\"SELECT 1\").get();\n console.log(`Connected to ${turso.url}`);\n db.close();\n } catch (err) {\n db?.close();\n console.error(\"Error:\", (err as Error).message);\n process.exit(1);\n }\n });\n\n// ── Turso setup helper ──────────────────────────────────────────────────────\n\nasync function setupTurso(urlArg?: string, tokenArg?: string): Promise<void> {\n let db: Database | undefined;\n try {\n const url =\n urlArg ??\n (await input({\n message: \"Turso database URL (e.g. libsql://my-db-user.turso.io):\",\n }));\n const token =\n tokenArg ??\n (await password({\n message: \"Auth token:\",\n }));\n\n if (!url || !token) {\n console.error(\"Both URL and token are required.\");\n process.exit(1);\n }\n\n // Store credentials outside the db so they survive db deletion\n setTursoCredentials(url, token);\n\n // Verify by opening the configured cloud database.\n db = openDatabaseWithSync({ initialize: true });\n db.prepare(\"SELECT 1\").get();\n db.close();\n\n console.log(`Turso cloud database configured and verified: ${url}`);\n } catch (err) {\n db?.close();\n if ((err as Error).name === \"ExitPromptError\") {\n console.log(\"\\nSetup cancelled.\");\n process.exit(0);\n }\n console.error(\"Error:\", (err as Error).message);\n process.exit(1);\n }\n}\n","/**\n * `zam git-sync` — Git integration subcommand.\n *\n * Automatically marks cards as stale/due when their source files change in git.\n */\n\nimport { execSync } from \"node:child_process\";\nimport { chmodSync, existsSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { Command } from \"commander\";\nimport type { Database } from \"libsql\";\nimport type { Token } from \"../../kernel/index.js\";\nimport { getCard, matchesFilePath, openDatabase } from \"../../kernel/index.js\";\nimport { resolveUser } from \"./resolve-user.js\";\n\nfunction withDb(fn: (db: Database) => void): void {\n let db: Database | undefined;\n try {\n db = openDatabase();\n fn(db);\n } catch (err) {\n console.error(\"Error:\", (err as Error).message);\n process.exit(1);\n } finally {\n db?.close();\n }\n}\n\n/**\n * Installs the Git post-commit hook.\n */\nfunction installHook(): void {\n const gitDir = join(process.cwd(), \".git\");\n if (!existsSync(gitDir)) {\n console.error(\n \"Error: Current directory is not the root of a Git repository.\",\n );\n process.exit(1);\n }\n\n const hooksDir = join(gitDir, \"hooks\");\n const hookPath = join(hooksDir, \"post-commit\");\n\n const hookContent = `#!/bin/sh\n# ZAM Spaced Repetition Auto-Stale Hook\n# Triggered automatically on git commits to decay modified concept cards.\nzam git-sync --commit HEAD --quiet\n`;\n\n try {\n writeFileSync(hookPath, hookContent, { encoding: \"utf-8\", flag: \"w\" });\n try {\n chmodSync(hookPath, \"755\");\n } catch (_e) {\n // Best-effort chmod (Windows might ignore/fail, which is fine)\n }\n console.log(\n \"Successfully installed ZAM post-commit hook at .git/hooks/post-commit\",\n );\n } catch (err) {\n console.error(\"Failed to write post-commit hook:\", (err as Error).message);\n process.exit(1);\n }\n}\n\nexport const gitSyncCommand = new Command(\"git-sync\")\n .description(\"Sync learning cards with recent Git file modifications\")\n .option(\"--commit <hash>\", \"Git commit hash to check\", \"HEAD\")\n .option(\"--user <id>\", \"User ID (default: whoami)\")\n .option(\"--install\", \"Install git post-commit hook in current repo\")\n .option(\"--quiet\", \"Suppress verbose output\")\n .action((opts) => {\n if (opts.install) {\n installHook();\n return;\n }\n\n withDb((db) => {\n const userId = resolveUser(opts, db);\n\n let changedFiles: string[] = [];\n try {\n const output = execSync(\n `git diff-tree --no-commit-id --name-only -r ${opts.commit}`,\n {\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n },\n );\n changedFiles = output\n .split(/\\r?\\n/)\n .map((f) => f.trim())\n .filter(Boolean);\n } catch (_err) {\n if (!opts.quiet) {\n console.warn(\n \"Notice: Failed to read git modifications. Ensure you are in a Git repo and commit hash is valid.\",\n );\n }\n return;\n }\n\n if (changedFiles.length === 0) {\n if (!opts.quiet) {\n console.log(\"No file changes detected in commit.\");\n }\n return;\n }\n\n // Fetch active tokens\n const tokens = db\n .prepare(`\n SELECT * FROM tokens \n WHERE source_link IS NOT NULL \n AND deprecated_at IS NULL\n `)\n .all() as Token[];\n\n const matchedTokens: Token[] = [];\n\n for (const token of tokens) {\n const matches = changedFiles.some((cf) =>\n matchesFilePath(token.source_link, cf),\n );\n if (matches) {\n matchedTokens.push(token);\n }\n }\n\n if (matchedTokens.length === 0) {\n if (!opts.quiet) {\n console.log(\n `Scanned ${changedFiles.length} file(s), no associated learning tokens found.`,\n );\n }\n return;\n }\n\n let decayedCount = 0;\n const now = new Date().toISOString();\n\n for (const token of matchedTokens) {\n const card = getCard(db, token.id, userId);\n if (card) {\n // Decay stability to a quarter (concept's source changed → likely stale),\n // with a 0.2-day floor so the card surfaces for review soon. Using max,\n // not min: min would collapse every card to <=0.2 regardless of prior strength.\n const newStability = Math.max(0.2, card.stability / 4.0);\n\n db.prepare(`\n UPDATE cards\n SET due_at = ?,\n stability = ?,\n state = CASE WHEN state = 'new' THEN 'new' ELSE 'review' END,\n elapsed_days = 0.0,\n scheduled_days = 0.0\n WHERE id = ?\n `).run(now, newStability, card.id);\n\n decayedCount++;\n if (!opts.quiet) {\n console.log(\n ` Decayed card for: ${token.slug} (Source: ${token.source_link})`,\n );\n }\n }\n }\n\n if (!opts.quiet) {\n console.log(\n `\\nZAM Auto-Stale Complete: Scanned ${changedFiles.length} file(s).`,\n );\n console.log(\n `Successfully decayed FSRS stability and scheduled reviews for ${decayedCount} concept(s).`,\n );\n }\n });\n });\n","/**\n * `zam goal` — Goal management subcommand group.\n *\n * Goals are markdown files in the personal repo's goals/ directory.\n * The directory is configured via the `personal.goals_dir` setting,\n * or defaults to `./goals` relative to the current working directory.\n */\n\nimport { existsSync, mkdirSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { input } from \"@inquirer/prompts\";\nimport { Command } from \"commander\";\nimport type { GoalStatus } from \"../../kernel/index.js\";\nimport {\n createGoal,\n extractTasks,\n extractTokenRefs,\n getGoal,\n getGoalTree,\n getSetting,\n listGoals,\n openDatabase,\n updateGoalStatus,\n} from \"../../kernel/index.js\";\n\nfunction resolveGoalsDir(): string {\n let goalsDir: string | undefined;\n\n let db: ReturnType<typeof openDatabase> | undefined;\n try {\n db = openDatabase();\n goalsDir = getSetting(db, \"personal.goals_dir\");\n } catch {\n // DB not available — fall back to default\n } finally {\n db?.close();\n }\n\n return goalsDir ? resolve(goalsDir) : resolve(\"goals\");\n}\n\nexport const goalCommand = new Command(\"goal\").description(\n \"Manage learning goals (markdown files)\",\n);\n\n// ── zam goal list ────────────────────────────────────────────────────────────\n\ngoalCommand\n .command(\"list\")\n .description(\"List all goals\")\n .option(\n \"--status <status>\",\n \"Filter by status (active, completed, paused, abandoned)\",\n )\n .option(\"--tree\", \"Show goals as a tree with parent/child relationships\")\n .option(\"--json\", \"Output as JSON\")\n .action((opts) => {\n const goalsDir = resolveGoalsDir();\n\n if (!existsSync(goalsDir)) {\n console.error(`Goals directory not found: ${goalsDir}`);\n console.error(\n \"Set it with: zam settings set personal.goals_dir /path/to/goals\",\n );\n process.exit(1);\n }\n\n if (opts.tree) {\n const tree = getGoalTree(goalsDir);\n const filtered = opts.status\n ? tree.filter((g) => g.status === opts.status)\n : tree;\n\n if (opts.json) {\n console.log(JSON.stringify(filtered, null, 2));\n return;\n }\n\n if (filtered.length === 0) {\n console.log(\"No goals found.\");\n return;\n }\n\n for (const root of filtered) {\n printGoalLine(root, 0);\n for (const child of root.children) {\n printGoalLine(child, 1);\n }\n }\n return;\n }\n\n let goals = listGoals(goalsDir);\n\n if (opts.status) {\n goals = goals.filter((g) => g.status === opts.status);\n }\n\n if (opts.json) {\n console.log(JSON.stringify(goals, null, 2));\n return;\n }\n\n if (goals.length === 0) {\n console.log(\"No goals found.\");\n return;\n }\n\n console.log(\"Goals:\");\n console.log(` ${\"─\".repeat(70)}`);\n for (const g of goals) {\n printGoalLine(g, 0);\n }\n });\n\nfunction printGoalLine(\n g: {\n slug: string;\n title: string;\n status: string;\n taskCount: number;\n tasksDone: number;\n },\n indent: number,\n): void {\n const prefix = \" \".repeat(indent + 1);\n const statusIcon: Record<string, string> = {\n active: \"[*]\",\n paused: \"[-]\",\n completed: \"[x]\",\n abandoned: \"[ ]\",\n };\n const icon = statusIcon[g.status] || \"[ ]\";\n const tasks = g.taskCount > 0 ? ` (${g.tasksDone}/${g.taskCount} tasks)` : \"\";\n console.log(`${prefix}${icon} ${g.title}${tasks} — ${g.slug}`);\n}\n\n// ── zam goal show ────────────────────────────────────────────────────────────\n\ngoalCommand\n .command(\"show <slug>\")\n .description(\"Show a goal's details\")\n .option(\"--json\", \"Output as JSON\")\n .action((slug, opts) => {\n const goalsDir = resolveGoalsDir();\n const goal = getGoal(goalsDir, slug);\n\n if (!goal) {\n console.error(`Goal not found: ${slug}`);\n process.exit(1);\n }\n\n if (opts.json) {\n const tasks = extractTasks(goal.body);\n const tokens = extractTokenRefs(goal.body);\n console.log(JSON.stringify({ ...goal, tasks, tokens }, null, 2));\n return;\n }\n\n console.log(`Title: ${goal.title}`);\n console.log(`Slug: ${goal.slug}`);\n console.log(`Status: ${goal.status}`);\n if (goal.parent) console.log(`Parent: ${goal.parent}`);\n console.log(`Created: ${goal.created}`);\n console.log(`Updated: ${goal.updated}`);\n\n const tasks = extractTasks(goal.body);\n if (tasks.length > 0) {\n console.log(\n `\\nTasks (${tasks.filter((t) => t.done).length}/${tasks.length}):`,\n );\n for (const t of tasks) {\n console.log(` [${t.done ? \"x\" : \" \"}] ${t.text}`);\n }\n }\n\n const tokens = extractTokenRefs(goal.body);\n if (tokens.length > 0) {\n console.log(`\\nTokens:`);\n for (const ref of tokens) {\n console.log(` - ${ref}`);\n }\n }\n\n if (goal.body) {\n console.log(`\\n${\"─\".repeat(50)}`);\n console.log(goal.body);\n }\n });\n\n// ── zam goal create ──────────────────────────────────────────────────────────\n\ngoalCommand\n .command(\"create\")\n .description(\"Create a new goal\")\n .option(\"--slug <slug>\", \"Goal slug (used as filename)\")\n .option(\"--title <title>\", \"Goal title\")\n .option(\"--parent <slug>\", \"Parent goal slug\")\n .option(\"--description <text>\", \"Goal description\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (opts) => {\n const goalsDir = resolveGoalsDir();\n\n if (!existsSync(goalsDir)) {\n mkdirSync(goalsDir, { recursive: true });\n }\n\n let slug = opts.slug;\n let title = opts.title;\n const parent = opts.parent;\n const description = opts.description;\n\n // Interactive mode if slug or title not provided\n if (!slug || !title) {\n try {\n if (!title) {\n title = await input({ message: \"Goal title:\" });\n }\n if (!slug) {\n const suggested = title\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n slug = await input({\n message: \"Goal slug (filename):\",\n default: suggested,\n });\n }\n } catch (err) {\n if ((err as Error).name === \"ExitPromptError\") {\n console.log(\"\\nCancelled.\");\n process.exit(0);\n }\n throw err;\n }\n }\n\n const goal = createGoal(goalsDir, { slug, title, parent, description });\n\n if (opts.json) {\n console.log(JSON.stringify(goal, null, 2));\n return;\n }\n\n console.log(`Goal created: ${goal.slug}`);\n console.log(` Title: ${goal.title}`);\n console.log(` Status: ${goal.status}`);\n console.log(` File: ${goal.filePath}`);\n });\n\n// ── zam goal status ──────────────────────────────────────────────────────────\n\ngoalCommand\n .command(\"status <slug> <status>\")\n .description(\"Update a goal's status (active, paused, completed, abandoned)\")\n .option(\"--json\", \"Output as JSON\")\n .action((slug, status, opts) => {\n const validStatuses: GoalStatus[] = [\n \"active\",\n \"completed\",\n \"paused\",\n \"abandoned\",\n ];\n if (!validStatuses.includes(status)) {\n console.error(\n `Invalid status: ${status}. Must be one of: ${validStatuses.join(\", \")}`,\n );\n process.exit(1);\n }\n\n const goalsDir = resolveGoalsDir();\n const goal = updateGoalStatus(goalsDir, slug, status);\n\n if (opts.json) {\n console.log(JSON.stringify(goal, null, 2));\n return;\n }\n\n console.log(`Goal ${slug} updated to: ${status}`);\n });\n","/**\n * `zam init` — Guided interactive onboarding wizard.\n *\n * Bootstraps a fresh ZAM installation:\n * 1. Initializes a zero-dependency \"Local Sandbox\" workspace.\n * 2. Runs hardware profiling to detect NPUs/CPUs.\n * 3. Installs and configures the hardware-optimized local LLM runtime (flm or Ollama).\n * 4. Automatically distributes global agent skill files and hooks.\n * 5. Sets up the local database and configuration.\n */\n\nimport { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { confirm, input } from \"@inquirer/prompts\";\nimport { Command } from \"commander\";\nimport {\n detectSystemLocale,\n distributeGlobalSkills,\n getSystemProfile,\n injectShellHooks,\n installFastFlowLM,\n installOllama,\n openDatabaseWithSync,\n setSetting,\n} from \"../../kernel/index.js\";\n\nconst HOME = homedir();\n\n/**\n * Helper to print thick borders.\n */\nfunction printLine(char = \"═\", len = 60, color = \"\\x1b[36m\") {\n console.log(`${color}${char.repeat(len)}\\x1b[0m`);\n}\n\n/**\n * Bootstrap the default \"Local Sandbox\" workspace structure.\n */\nfunction bootstrapSandboxWorkspace(workspaceDir: string) {\n mkdirSync(join(workspaceDir, \"beliefs\"), { recursive: true });\n mkdirSync(join(workspaceDir, \"goals\"), { recursive: true });\n mkdirSync(join(workspaceDir, \"skills\"), { recursive: true });\n\n const worldviewFile = join(workspaceDir, \"beliefs\", \"worldview.md\");\n if (!existsSync(worldviewFile)) {\n writeFileSync(\n worldviewFile,\n `# Personal Worldview\n\nHere, I declare the core concepts and principles I want to master.\n\n- **Conceptual Autonomy**: I value deep conceptual understanding over copy-pasting rote procedures.\n- **Continuous Retention**: I use spaced repetition to prevent my professional skills from decaying.\n`,\n \"utf8\",\n );\n }\n\n const goalsFile = join(workspaceDir, \"goals\", \"goals.md\");\n if (!existsSync(goalsFile)) {\n writeFileSync(\n goalsFile,\n `# Personal Goals\n\n- **[ ] Learn Spaced Repetition Core Concepts**\n - #fsrs-stability\n - #fsrs-difficulty\n`,\n \"utf8\",\n );\n }\n}\n\nexport const initCommand = new Command(\"init\")\n .description(\"Launch the guided interactive onboarding wizard\")\n .action(async () => {\n printLine();\n console.log(\n \"\\x1b[1m\\x1b[32m ZAM — The Symbiotic Learning Agent Onboarding\\x1b[0m\",\n );\n console.log(\n \"\\x1b[2m Welcome! ZAM helps you build conceptual skills while you work.\\x1b[0m\",\n );\n printLine();\n\n // ── STEP 1: Workspace Selection ──────────────────────────────────────────\n console.log(\"\\n\\x1b[1m[1/5] Setting up Local Workspace Sandbox\\x1b[0m\");\n const defaultWorkspace = join(HOME, \"Documents\", \"zam\");\n\n const workspacePath = await input({\n message: \"Choose your ZAM workspace directory:\",\n default: defaultWorkspace,\n });\n\n try {\n bootstrapSandboxWorkspace(workspacePath);\n console.log(\n `\\x1b[32m✓ Local Sandbox created at: ${workspacePath}\\x1b[0m`,\n );\n } catch (err) {\n console.error(\n `\\x1b[31m✗ Failed to create workspace: ${(err as Error).message}\\x1b[0m`,\n );\n process.exit(1);\n }\n\n // ── STEP 2: Hardware Auto-Detection ──────────────────────────────────────\n console.log(\"\\n\\x1b[1m[2/5] Running Hardware Profiling...\\x1b[0m\");\n const profile = getSystemProfile();\n\n console.log(` OS Detected: \\x1b[36m${profile.os}\\x1b[0m`);\n console.log(` CPU Architecture: \\x1b[36m${profile.arch}\\x1b[0m`);\n if (profile.hasRyzenNPU) {\n console.log(\n \" NPU Detected: \\x1b[32mAMD Ryzen AI NPU detected! (Optimum Setup)\\x1b[0m\",\n );\n } else if (profile.hasAppleSilicon) {\n console.log(\n \" CPU Brand: \\x1b[32mmacOS Apple Silicon detected! (Optimum Setup)\\x1b[0m\",\n );\n } else {\n console.log(\" Hardware: \\x1b[33mStandard CPU detected.\\x1b[0m\");\n }\n\n const runnerLabel =\n profile.recommendedRunner === \"fastflowlm\"\n ? \"FastFlowLM (NPU Optimized)\"\n : \"Ollama\";\n console.log(\n `\\n \\x1b[1mRecommendation:\\x1b[0m ZAM suggests installing \\x1b[32m${runnerLabel}\\x1b[0m with \\x1b[36m${profile.recommendedModel}\\x1b[0m.`,\n );\n\n // ── STEP 3: Local LLM Runner Installation ───────────────────────────────\n console.log(\"\\n\\x1b[1m[3/5] Setting up Local LLM Runner\\x1b[0m\");\n const proceedInstall = await confirm({\n message: `Would you like ZAM to install and configure ${runnerLabel} automatically?`,\n default: true,\n });\n\n let installSuccess = false;\n if (proceedInstall) {\n let result: ReturnType<typeof installFastFlowLM> | undefined;\n if (profile.recommendedRunner === \"fastflowlm\") {\n result = installFastFlowLM();\n } else {\n result = installOllama();\n }\n\n if (result.success) {\n console.log(`\\x1b[32m✓ ${result.message}\\x1b[0m`);\n installSuccess = true;\n } else {\n console.warn(`\\x1b[33m⚠ Installation failed: ${result.message}\\x1b[0m`);\n console.log(\n \"You can install it manually or continue with offline templates.\",\n );\n }\n }\n\n // ── STEP 4: Initialize Database & Write Local Settings ─────────────────\n console.log(\"\\n\\x1b[1m[4/5] Bootstrapping database & settings...\\x1b[0m\");\n let db: ReturnType<typeof openDatabaseWithSync> | undefined;\n try {\n db = openDatabaseWithSync({ initialize: true });\n\n // Save workspace directory to settings\n setSetting(db, \"personal.workspace_dir\", workspacePath);\n\n // Auto-detect and save system locale\n const detectedLocale = detectSystemLocale();\n setSetting(db, \"system.locale\", detectedLocale);\n console.log(\n `\\x1b[32m✓ Detected and set system language to: ${detectedLocale}\\x1b[0m`,\n );\n\n if (installSuccess) {\n setSetting(db, \"llm.enabled\", \"true\");\n if (profile.recommendedRunner === \"fastflowlm\") {\n setSetting(db, \"llm.url\", \"http://localhost:8000/v1\");\n setSetting(db, \"llm.model\", \"gemma4-it:e4b\");\n } else {\n setSetting(db, \"llm.url\", \"http://localhost:11434/v1\");\n setSetting(db, \"llm.model\", \"llama3.2:3b\");\n }\n console.log(\n \"\\x1b[32m✓ Configured LLM runner settings in database.\\x1b[0m\",\n );\n } else {\n setSetting(db, \"llm.enabled\", \"false\");\n }\n db.close();\n console.log(\"\\x1b[32m✓ Database initialized successfully.\\x1b[0m\");\n } catch (err) {\n console.error(\n `\\x1b[31m✗ Database setup failed: ${(err as Error).message}\\x1b[0m`,\n );\n db?.close();\n }\n\n // ── STEP 5: Distribute Agent Skills & Hooks ──────────────────────────────\n console.log(\n \"\\n\\x1b[1m[5/5] Wiring Developer Agents & Terminal Hooks\\x1b[0m\",\n );\n const proceedHooks = await confirm({\n message:\n \"Distribute ZAM active-recall skills and enable automatic terminal command observation?\",\n default: true,\n });\n\n if (proceedHooks) {\n console.log(\"Copying SKILL.md into global agent directories...\");\n const skillResults = distributeGlobalSkills();\n for (const res of skillResults) {\n if (res.success) {\n console.log(` \\x1b[32m✓ Installed ZAM Skill in ${res.name}\\x1b[0m`);\n } else {\n console.log(` \\x1b[31m✗ Failed to install in ${res.name}\\x1b[0m`);\n }\n }\n\n console.log(\"Injecting observation hooks into shell profiles...\");\n const hookResults = injectShellHooks();\n for (const res of hookResults) {\n if (res.success) {\n const action = res.alreadyHooked\n ? \"already up-to-date\"\n : \"injected successfully\";\n console.log(` \\x1b[32m✓ ${res.shell} hook: ${action}\\x1b[0m`);\n } else {\n console.log(\n ` \\x1b[31m✗ Failed to inject hook in ${res.shell} (${res.file})\\x1b[0m`,\n );\n }\n }\n }\n\n printLine();\n console.log(\n \"\\x1b[1m\\x1b[32m Congratulations! ZAM Onboarding Complete!\\x1b[0m\",\n );\n console.log(\n \"\\x1b[1m You are now ready to start your symbiotic learning journey.\\x1b[0m\",\n );\n console.log(\"\\n \\x1b[1mUseful commands to get started:\\x1b[0m\");\n console.log(\n \" \\x1b[36mzam stats\\x1b[0m — Display your learning queue stats\",\n );\n console.log(\n \" \\x1b[36mzam learn\\x1b[0m — Start a standalone learning session\",\n );\n console.log(\n \" \\x1b[36mzam workspace publish\\x1b[0m — Publish your workspace sandbox to GitHub\",\n );\n printLine();\n });\n","/**\n * `zam learn` — Standalone, spoiler-free, in-process learning session.\n *\n * Slice 1 of the Session Harness (Increment 5), variant (a): no LLM.\n * Flow per card: show a concept-free cue → capture the learner's answer →\n * ONLY THEN reveal the stored answer (concept + context + resolved source_link)\n * → single self-rating 1–4 via the shared interactive action handler.\n *\n * Because the harness owns its own prompt and never prints the answer before\n * input is captured, no external autocomplete/ghost-text can spoil it, and\n * ratings/logs are written in-process (no per-subcommand permission prompts).\n */\n\nimport { input } from \"@inquirer/prompts\";\nimport { Command } from \"commander\";\nimport type { Database } from \"libsql\";\nimport type { BloomLevel, SupportedLocale } from \"../../kernel/index.js\";\nimport {\n buildReviewQueue,\n generatePrompt,\n getSetting,\n getTokenById,\n openDatabase,\n resolveReviewContext,\n t,\n} from \"../../kernel/index.js\";\nimport { formatHeader, formatReveal } from \"../learn-format.js\";\nimport {\n ensureHighQualityQuestion,\n ensureLocalLlmRunning,\n evaluateAnswerViaLLM,\n} from \"../llm/client.js\";\nimport { runInteractiveReviewAction } from \"../review-actions.js\";\nimport { resolveUser } from \"./resolve-user.js\";\n\n/** Words the learner can type at the answer prompt to end the session. */\nconst STOP_WORDS = new Set([\"q\", \":q\", \"quit\", \"stop\"]);\n\nfunction isExitPrompt(err: unknown): boolean {\n return err instanceof Error && err.name === \"ExitPromptError\";\n}\n\nexport const learnCommand = new Command(\"learn\")\n .description(\n \"Run a spoiler-free, in-process learning session (recall → reveal → self-rate)\",\n )\n .option(\"--user <id>\", \"User ID (default: whoami)\")\n .option(\"--max-new <n>\", \"Maximum new cards\", \"10\")\n .option(\"--max-reviews <n>\", \"Maximum review cards\", \"50\")\n .option(\"--no-resolve\", \"Skip resolving source_link into the revealed answer\")\n .action(async (opts) => {\n let db: Database | undefined;\n try {\n db = openDatabase();\n const userId = resolveUser(opts, db);\n\n const queue = buildReviewQueue(db, {\n userId,\n maxNew: Number(opts.maxNew),\n maxReviews: Number(opts.maxReviews),\n });\n\n const locale = (getSetting(db, \"system.locale\") ||\n \"en\") as SupportedLocale;\n\n if (queue.items.length === 0) {\n console.log(t(locale, \"nothing_due\"));\n db.close();\n return;\n }\n\n // Start the local LLM if needed and verify it is actually usable\n // (reachable AND serving the configured model). A wrong model name\n // otherwise looks like \"the AI is slow\" — instead we fall back cleanly.\n const llm = await ensureLocalLlmRunning(db);\n const isLlmEnabled = llm.usable;\n\n console.log(`\\n${t(locale, \"welcome\", { count: queue.items.length })}`);\n console.log(\n t(locale, \"new_review_relearn\", {\n newC: queue.newCount,\n reviewC: queue.reviewCount,\n relearnC: queue.relearnCount,\n }),\n );\n console.log(\n t(locale, \"domains\", { domains: queue.totalDomains.join(\", \") }),\n );\n\n // When the LLM is simply switched off, nudge the user; offline /\n // model-not-found already printed their own actionable message.\n if (!isLlmEnabled && llm.reason === \"disabled\") {\n console.log(t(locale, \"offline_warning\"));\n console.log(t(locale, \"offline_instruction\"));\n }\n\n console.log(t(locale, \"instruction\"));\n console.log(t(locale, \"quit_hint\"));\n\n let stoppedEarly = false;\n let maintenanceActions = 0;\n const results: Array<{ slug: string; rating: number }> = [];\n\n for (const [index, item] of queue.items.entries()) {\n // Dynamically generate a fresh, living active-recall question if LLM is enabled\n let resolvedQuestion = item.question;\n if (isLlmEnabled) {\n console.log(` \\x1b[2m${t(locale, \"generating_question\")}\\x1b[0m`);\n try {\n const healed = await ensureHighQualityQuestion(db, {\n id: item.tokenId,\n slug: item.slug,\n concept: item.concept,\n domain: item.domain,\n bloomLevel: item.bloomLevel as BloomLevel,\n sourceLink: item.sourceLink,\n question: item.question,\n });\n if (healed) {\n resolvedQuestion = healed;\n }\n } catch {\n // ignore and proceed\n }\n }\n\n const prompt = generatePrompt({\n cardId: item.cardId,\n tokenId: item.tokenId,\n slug: item.slug,\n concept: item.concept,\n domain: item.domain,\n bloomLevel: item.bloomLevel as BloomLevel,\n sourceLink: item.sourceLink,\n question: resolvedQuestion,\n });\n\n console.log(`\\n${\"─\".repeat(50)}`);\n console.log(\n `[${index + 1}/${queue.items.length}] ${formatHeader(item)}`,\n );\n\n console.log(`\\n ${prompt.question}`);\n\n // Capture the learner's answer FIRST — nothing is revealed yet.\n // Typing a stop word (or Ctrl+C) ends the session gracefully.\n let answer: string;\n try {\n answer = await input({\n message: t(locale, \"prompt_answer\"),\n });\n } catch (err) {\n if (isExitPrompt(err)) {\n stoppedEarly = true;\n console.log(\"\\nStopping session.\");\n break;\n }\n throw err;\n }\n\n if (STOP_WORDS.has(answer.trim().toLowerCase())) {\n stoppedEarly = true;\n console.log(\"Stopping session.\");\n break;\n }\n\n // Now reveal the stored answer.\n let resolved = null;\n if (opts.resolve !== false && item.sourceLink) {\n resolved = await resolveReviewContext(item.sourceLink).catch(\n () => null,\n );\n }\n const token = getTokenById(db, item.tokenId);\n\n // Perform LLM evaluation if enabled and there is a typed answer\n if (isLlmEnabled && answer.trim().length > 0) {\n console.log(`\\n ${t(locale, \"evaluating\")}`);\n try {\n const evaluation = await evaluateAnswerViaLLM(db, {\n slug: item.slug,\n concept: item.concept,\n domain: item.domain,\n bloomLevel: item.bloomLevel,\n context: token?.context,\n question: prompt.question,\n userAnswer: answer,\n sourceLinkContent: resolved?.content,\n });\n console.log(\n `\\n ${t(locale, \"feedback_title\", { line: \"─\".repeat(34) })}`,\n );\n for (const line of evaluation.split(\"\\n\")) {\n console.log(` ${line}`);\n }\n } catch (err) {\n console.warn(\n `\\n${t(locale, \"eval_skipped\", { reason: (err as Error).message })}`,\n );\n }\n }\n\n console.log(\n `\\n ${t(locale, \"answer_title\", { line: \"─\".repeat(38) })}`,\n );\n const reveal = formatReveal({\n slug: item.slug,\n concept: item.concept,\n context: token?.context,\n resolved,\n });\n for (const line of reveal.split(\"\\n\")) {\n console.log(` ${line}`);\n }\n console.log();\n\n let action: Awaited<ReturnType<typeof runInteractiveReviewAction>>;\n try {\n action = await runInteractiveReviewAction({\n db,\n userId,\n item,\n mode: \"review\",\n });\n } catch (err) {\n if (isExitPrompt(err)) {\n stoppedEarly = true;\n console.log(\"\\nStopping session.\");\n break;\n }\n throw err;\n }\n\n if (action.action === \"stop\") {\n stoppedEarly = true;\n console.log(\"\\nStopping session.\");\n break;\n }\n if (action.action === \"rate\") {\n results.push({ slug: item.slug, rating: action.rating! });\n } else if (action.action !== \"skip\") {\n maintenanceActions++;\n }\n }\n\n console.log(`\\n${\"═\".repeat(50)}`);\n console.log(\n stoppedEarly\n ? t(locale, \"session_ended\")\n : t(locale, \"session_complete\"),\n );\n console.log(t(locale, \"cards_rated\", { count: results.length }));\n if (maintenanceActions > 0) {\n console.log(` Maintenance actions: ${maintenanceActions}`);\n }\n if (results.length > 0) {\n const avg = results.reduce((s, r) => s + r.rating, 0) / results.length;\n console.log(t(locale, \"avg_rating\", { avg: avg.toFixed(1) }));\n const forgot = results.filter((r) => r.rating === 1).length;\n if (forgot > 0) {\n console.log(t(locale, \"forgot\", { count: forgot }));\n }\n }\n\n db.close();\n } catch (err) {\n db?.close();\n if ((err as Error).name === \"ExitPromptError\") {\n console.log(\"\\nLearning session cancelled.\");\n process.exit(0);\n }\n console.error(\"Error:\", (err as Error).message);\n process.exit(1);\n }\n });\n","/**\n * Pure formatting helpers for the spoiler-free learning session (`zam learn`).\n *\n * Kept free of terminal/prompt code so the presentation logic is unit-testable.\n * The up-front question is the kernel's Bloom-templated prompt (built in\n * learn.ts via generatePrompt); these helpers render the header line and the\n * answer that is revealed only AFTER the learner has committed an answer.\n */\n\nimport type { ReviewContext } from \"../kernel/index.js\";\n\nexport const BLOOM_VERBS: Record<number, string> = {\n 1: \"Remember\",\n 2: \"Understand\",\n 3: \"Apply\",\n 4: \"Analyze\",\n 5: \"Synthesize\",\n};\n\nfunction clampBloom(n: number): number {\n return Number.isFinite(n) && n >= 1 && n <= 5 ? Math.trunc(n) : 1;\n}\n\n/**\n * Build the card header, e.g. \"Understand (Bloom 2) · web\".\n */\nexport function formatHeader(input: {\n bloomLevel: number;\n domain: string;\n}): string {\n const lvl = clampBloom(input.bloomLevel);\n const parts = [`${BLOOM_VERBS[lvl]} (Bloom ${lvl})`];\n if (input.domain?.trim()) {\n parts.push(input.domain.trim());\n }\n return parts.join(\" · \");\n}\n\nexport interface RevealInput {\n slug: string;\n concept: string;\n context?: string | null;\n resolved?: ReviewContext | null;\n}\n\n/**\n * Format the stored answer revealed AFTER the learner has committed: the\n * token slug, concept, optional context, and resolved source_link content.\n */\nexport function formatReveal(input: RevealInput): string {\n const lines: string[] = [\n `Token: #${input.slug}`,\n `Concept: ${input.concept}`,\n ];\n\n if (input.context?.trim()) {\n lines.push(\"\", `Context: ${input.context.trim()}`);\n }\n\n const resolved = input.resolved;\n if (resolved?.content.trim()) {\n lines.push(\"\");\n if (resolved.sourceType === \"dynamic_search\") {\n // content is a QUERY_DIRECTIVE — there is nothing to quote inline\n lines.push(`Source: ${resolved.content}`);\n } else {\n const label = resolved.url ?? resolved.filePath ?? resolved.sourceLink;\n lines.push(`Source (${resolved.sourceType}: ${label}):`);\n for (const line of resolved.content.trimEnd().split(\"\\n\")) {\n lines.push(` │ ${line}`);\n }\n if (resolved.truncated) {\n lines.push(\" │ … (truncated)\");\n }\n }\n }\n\n return lines.join(\"\\n\");\n}\n","import { confirm, input, select } from \"@inquirer/prompts\";\nimport type { Database } from \"libsql\";\nimport type {\n BloomLevel,\n Rating,\n ReviewActionResult,\n ReviewQueueItem,\n SymbiosisMode,\n Token,\n UpdateTokenInput,\n} from \"../kernel/index.js\";\nimport {\n executeReviewAction,\n generatePrompt,\n getCardDeletionImpact,\n getTokenById,\n getTokenDeleteImpact,\n} from \"../kernel/index.js\";\n\ntype InteractiveTerminalAction =\n | \"rate\"\n | \"skip\"\n | \"deprecate-token\"\n | \"delete-token\"\n | \"delete-card\"\n | \"stop\";\n\nexport interface RunInteractiveReviewActionInput {\n db: Database;\n userId: string;\n item: ReviewQueueItem;\n mode: \"review\" | \"session\";\n}\n\nexport interface RunInteractiveReviewActionResult {\n action: InteractiveTerminalAction;\n result: ReviewActionResult;\n rating?: Rating;\n}\n\nexport async function runInteractiveReviewAction(\n inputData: RunInteractiveReviewActionInput,\n): Promise<RunInteractiveReviewActionResult> {\n let currentItem = { ...inputData.item };\n\n while (true) {\n const choice = (await select({\n message: \"What next?\",\n choices: [\n { name: \"1 - Again (forgot)\", value: 1 },\n { name: \"2 - Hard\", value: 2 },\n { name: \"3 - Good\", value: 3 },\n { name: \"4 - Easy\", value: 4 },\n { name: \"Skip this card\", value: \"skip\" },\n { name: \"Edit token\", value: \"edit-token\" },\n { name: \"Deprecate token\", value: \"deprecate-token\" },\n { name: \"Delete token\", value: \"delete-token\" },\n { name: \"Delete my card\", value: \"delete-card\" },\n {\n name:\n inputData.mode === \"session\"\n ? \"Stop review and continue to task selection\"\n : \"Stop review\",\n value: \"stop\",\n },\n ],\n })) as Rating | InteractiveTerminalAction | \"edit-token\";\n\n if (typeof choice === \"number\") {\n const result = executeReviewAction(inputData.db, {\n action: \"rate\",\n cardId: currentItem.cardId,\n userId: inputData.userId,\n rating: choice,\n });\n\n const ratingLabels: Record<number, string> = {\n 1: \"Again\",\n 2: \"Hard\",\n 3: \"Good\",\n 4: \"Easy\",\n };\n console.log(\n ` ${ratingLabels[choice]} — next due: ${result.evaluation?.nextDueAt}`,\n );\n\n if (result.blocked) {\n console.log(\n ` Blocked ${result.blocked.blockedSlug}. Review these prerequisites:`,\n );\n for (const prereq of result.blocked.prerequisites) {\n console.log(` - ${prereq.slug}: ${prereq.concept}`);\n }\n }\n\n console.log();\n return { action: \"rate\", result, rating: choice };\n }\n\n if (choice === \"skip\") {\n console.log(\"Skipped this card.\\n\");\n return {\n action: \"skip\",\n result: executeReviewAction(inputData.db, {\n action: \"skip\",\n cardId: currentItem.cardId,\n userId: inputData.userId,\n }),\n };\n }\n\n if (choice === \"stop\") {\n return {\n action: \"stop\",\n result: executeReviewAction(inputData.db, {\n action: \"stop\",\n cardId: currentItem.cardId,\n userId: inputData.userId,\n }),\n };\n }\n\n if (choice === \"edit-token\") {\n const token = getTokenById(inputData.db, currentItem.tokenId);\n if (!token) {\n throw new Error(`Token not found: ${currentItem.tokenId}`);\n }\n\n const updates = await promptTokenEdit(token);\n if (!updates) {\n console.log(\"No token changes made.\\n\");\n continue;\n }\n\n const result = executeReviewAction(inputData.db, {\n action: \"edit-token\",\n cardId: currentItem.cardId,\n userId: inputData.userId,\n tokenUpdates: updates,\n });\n\n const updatedToken = result.updatedToken!;\n currentItem = {\n ...currentItem,\n slug: updatedToken.slug,\n concept: updatedToken.concept,\n domain: updatedToken.domain,\n bloomLevel: updatedToken.bloom_level,\n };\n\n const refreshedPrompt = generatePrompt({\n cardId: currentItem.cardId,\n tokenId: currentItem.tokenId,\n slug: currentItem.slug,\n concept: currentItem.concept,\n domain: currentItem.domain,\n bloomLevel: currentItem.bloomLevel as BloomLevel,\n });\n\n console.log(`Updated token: ${updatedToken.slug}`);\n console.log(` Concept: ${updatedToken.concept}`);\n console.log(` Domain: ${updatedToken.domain || \"(none)\"}`);\n console.log(` Bloom: ${updatedToken.bloom_level}`);\n if (updatedToken.source_link) {\n console.log(` Source: ${updatedToken.source_link}`);\n }\n console.log(`\\n ${refreshedPrompt.question}\\n`);\n continue;\n }\n\n if (choice === \"deprecate-token\") {\n const approved = await confirm({\n message: `Deprecate ${currentItem.slug} so it stops appearing in review queues?`,\n default: false,\n });\n if (!approved) {\n console.log(\"Token deprecation cancelled.\\n\");\n continue;\n }\n\n const result = executeReviewAction(inputData.db, {\n action: \"deprecate-token\",\n cardId: currentItem.cardId,\n userId: inputData.userId,\n });\n\n console.log(`Deprecated token: ${currentItem.slug}\\n`);\n return { action: \"deprecate-token\", result };\n }\n\n if (choice === \"delete-token\") {\n const impact = getTokenDeleteImpact(inputData.db, currentItem.slug);\n console.log(`Delete token ${currentItem.slug}?`);\n console.log(` Cards: ${impact.cards}`);\n console.log(` Review logs: ${impact.review_logs}`);\n console.log(\n ` Prereq edges from it: ${impact.prerequisite_edges_from_token}`,\n );\n console.log(\n ` Prereq edges to it: ${impact.prerequisite_edges_to_token}`,\n );\n console.log(` Session steps: ${impact.session_steps}`);\n console.log(` Sessions touched: ${impact.sessions_touched}`);\n console.log(` Agent skills updated: ${impact.agent_skills}`);\n\n const approved = await confirm({\n message:\n \"Permanently delete this token and its dependent learning data?\",\n default: false,\n });\n if (!approved) {\n console.log(\"Token deletion cancelled.\\n\");\n continue;\n }\n\n const result = executeReviewAction(inputData.db, {\n action: \"delete-token\",\n cardId: currentItem.cardId,\n userId: inputData.userId,\n });\n\n console.log(`Deleted token: ${currentItem.slug}\\n`);\n return { action: \"delete-token\", result };\n }\n\n if (choice === \"delete-card\") {\n const impact = getCardDeletionImpact(\n inputData.db,\n currentItem.tokenId,\n inputData.userId,\n );\n console.log(`Delete your card for ${currentItem.slug}?`);\n console.log(` Review logs removed: ${impact.review_logs}`);\n\n const approved = await confirm({\n message: \"Delete only your card for this token?\",\n default: false,\n });\n if (!approved) {\n console.log(\"Card deletion cancelled.\\n\");\n continue;\n }\n\n const result = executeReviewAction(inputData.db, {\n action: \"delete-card\",\n cardId: currentItem.cardId,\n userId: inputData.userId,\n });\n\n console.log(`Deleted your card for: ${currentItem.slug}\\n`);\n return { action: \"delete-card\", result };\n }\n }\n}\n\nasync function promptTokenEdit(token: Token): Promise<UpdateTokenInput | null> {\n const field = (await select({\n message: `Edit which field on ${token.slug}?`,\n choices: [\n { name: \"Concept\", value: \"concept\" },\n { name: \"Domain\", value: \"domain\" },\n { name: \"Bloom level\", value: \"bloom_level\" },\n { name: \"Context\", value: \"context\" },\n { name: \"Symbiosis mode\", value: \"symbiosis_mode\" },\n { name: \"Source link\", value: \"source_link\" },\n { name: \"Cancel\", value: \"cancel\" },\n ],\n })) as keyof UpdateTokenInput | \"cancel\";\n\n if (field === \"cancel\") {\n return null;\n }\n\n switch (field) {\n case \"concept\": {\n const concept = await input({\n message: \"Concept:\",\n default: token.concept,\n });\n return concept === token.concept ? null : { concept };\n }\n\n case \"domain\": {\n const domain = await input({\n message: \"Domain (blank allowed):\",\n default: token.domain,\n });\n return domain === token.domain ? null : { domain };\n }\n\n case \"context\": {\n const context = await input({\n message: \"Context (blank allowed):\",\n default: token.context,\n });\n return context === token.context ? null : { context };\n }\n\n case \"bloom_level\": {\n const bloom = (await select({\n message: \"Bloom level:\",\n choices: [1, 2, 3, 4, 5].map((value) => ({\n name:\n value === token.bloom_level ? `${value} (current)` : String(value),\n value,\n })),\n })) as BloomLevel;\n return bloom === token.bloom_level ? null : { bloom_level: bloom };\n }\n\n case \"symbiosis_mode\": {\n const mode = (await select({\n message: \"Symbiosis mode:\",\n choices: [\n {\n name: token.symbiosis_mode === null ? \"none (current)\" : \"none\",\n value: null,\n },\n {\n name:\n token.symbiosis_mode === \"shadowing\"\n ? \"shadowing (current)\"\n : \"shadowing\",\n value: \"shadowing\",\n },\n {\n name:\n token.symbiosis_mode === \"copilot\"\n ? \"copilot (current)\"\n : \"copilot\",\n value: \"copilot\",\n },\n {\n name:\n token.symbiosis_mode === \"autonomy\"\n ? \"autonomy (current)\"\n : \"autonomy\",\n value: \"autonomy\",\n },\n ],\n })) as SymbiosisMode | null;\n return mode === token.symbiosis_mode ? null : { symbiosis_mode: mode };\n }\n\n case \"source_link\": {\n const link = await input({\n message: \"Source link (blank allowed):\",\n default: token.source_link ?? \"\",\n });\n return link === token.source_link ? null : { source_link: link || null };\n }\n }\n}\n","/**\n * `zam monitor` — Shell observation for real-time task monitoring.\n *\n * Installs shell hooks (zsh/bash/PowerShell) that capture commands with timing,\n * exit codes, and working directory to a JSONL file. The agent reads\n * this log to infer ratings for knowledge tokens.\n *\n * Usage:\n * eval \"$(zam monitor start --session <id>)\" # zsh/bash\n * Invoke-Expression (& zam monitor start --session <id>) # PowerShell\n * zam monitor status --session <id> # check log stats\n */\n\nimport { execFileSync, execSync } from \"node:child_process\";\nimport { unlinkSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { basename, join } from \"node:path\";\nimport { Command } from \"commander\";\nimport type { Database } from \"libsql\";\nimport type { MonitorEvent } from \"../../kernel/index.js\";\nimport {\n ensureMonitorDir,\n generateBashHooks,\n generateBashUnhooks,\n generatePowerShellHooks,\n generatePowerShellUnhooks,\n generateZshHooks,\n generateZshUnhooks,\n getMonitorLogStats,\n getMonitorPath,\n getSetting,\n monitorLogExists,\n openDatabase,\n pairCommands,\n readMonitorLog,\n setSetting,\n writeMonitorEvent,\n} from \"../../kernel/index.js\";\n\ntype MonitorShell = \"zsh\" | \"bash\" | \"pwsh\" | \"powershell\";\n\nfunction isPowerShellShell(shell: MonitorShell): boolean {\n return shell === \"pwsh\" || shell === \"powershell\";\n}\n\nfunction normalizeShell(shell: string | undefined): MonitorShell {\n if (!shell) return detectShell();\n const normalized = shell.toLowerCase();\n if (\n normalized === \"zsh\" ||\n normalized === \"bash\" ||\n normalized === \"pwsh\" ||\n normalized === \"powershell\"\n ) {\n return normalized;\n }\n throw new Error(\n `Unsupported shell: ${shell}. Expected zsh, bash, pwsh, or powershell.`,\n );\n}\n\nfunction psSingleQuoted(value: string): string {\n return `'${value.replace(/'/g, \"''\")}'`;\n}\n\nfunction detectShell(): MonitorShell {\n if (process.platform === \"win32\")\n return findExecutable(\"pwsh.exe\") ? \"pwsh\" : \"powershell\";\n const shell = process.env.SHELL ?? \"\";\n return basename(shell) === \"bash\" ? \"bash\" : \"zsh\";\n}\n\nexport const monitorCommand = new Command(\"monitor\").description(\n \"Shell observation for real-time task monitoring\",\n);\n\n// ── zam monitor start ─────────────────────────────────────────────────────\n\nmonitorCommand\n .command(\"start\")\n .description(\"Output shell hook code to install monitoring\")\n .requiredOption(\"--session <id>\", \"Session ID to monitor\")\n .option(\n \"--shell <type>\",\n \"Shell type: zsh | bash | pwsh | powershell (auto-detected)\",\n )\n .action((opts) => {\n let shell: MonitorShell;\n try {\n shell = normalizeShell(opts.shell);\n } catch (err) {\n console.error(`# Error: ${(err as Error).message}`);\n process.exit(1);\n }\n\n // Validate session exists\n let db: Database | undefined;\n try {\n db = openDatabase();\n const session = db\n .prepare(\"SELECT id, completed_at FROM sessions WHERE id = ?\")\n .get(opts.session) as\n | { id: string; completed_at: string | null }\n | undefined;\n\n if (!session) {\n console.error(`# Error: Session not found: ${opts.session}`);\n process.exit(1);\n }\n if (session.completed_at) {\n console.error(`# Error: Session already completed: ${opts.session}`);\n process.exit(1);\n }\n } catch (err) {\n console.error(`# Error: ${(err as Error).message}`);\n process.exit(1);\n } finally {\n db?.close();\n }\n\n ensureMonitorDir();\n const monitorFile = getMonitorPath(opts.session);\n\n // Write initial meta event\n const meta: MonitorEvent = {\n type: \"monitor_meta\",\n ts: new Date().toISOString(),\n event: \"start\",\n session_id: opts.session,\n shell,\n pid: process.pid,\n };\n writeMonitorEvent(opts.session, meta);\n\n // Output hook code to stdout\n if (shell === \"bash\") {\n console.log(generateBashHooks(monitorFile, opts.session));\n } else if (isPowerShellShell(shell)) {\n console.log(generatePowerShellHooks(monitorFile, opts.session));\n } else {\n console.log(generateZshHooks(monitorFile, opts.session));\n }\n });\n\n// ── zam monitor stop ──────────────────────────────────────────────────────\n\nmonitorCommand\n .command(\"stop\")\n .description(\"Output shell code to remove monitoring hooks\")\n .requiredOption(\"--session <id>\", \"Session ID\")\n .option(\n \"--shell <type>\",\n \"Shell type: zsh | bash | pwsh | powershell (auto-detected)\",\n )\n .action((opts) => {\n // Write stop meta event\n if (monitorLogExists(opts.session)) {\n const meta: MonitorEvent = {\n type: \"monitor_meta\",\n ts: new Date().toISOString(),\n event: \"stop\",\n session_id: opts.session,\n };\n writeMonitorEvent(opts.session, meta);\n }\n\n let shell: MonitorShell;\n try {\n shell = normalizeShell(opts.shell);\n } catch (err) {\n console.error(`# Error: ${(err as Error).message}`);\n process.exit(1);\n }\n\n if (shell === \"bash\") {\n console.log(generateBashUnhooks());\n } else if (isPowerShellShell(shell)) {\n console.log(generatePowerShellUnhooks());\n } else {\n console.log(generateZshUnhooks());\n }\n });\n\n// ── zam monitor status ────────────────────────────────────────────────────\n\nmonitorCommand\n .command(\"status\")\n .description(\"Show monitoring status for a session\")\n .requiredOption(\"--session <id>\", \"Session ID\")\n .option(\"--json\", \"Output as JSON\")\n .action((opts) => {\n const stats = getMonitorLogStats(opts.session);\n\n if (!stats.exists) {\n if (opts.json) {\n console.log(JSON.stringify({ exists: false }));\n } else {\n console.log(`No monitor log found for session ${opts.session}`);\n }\n return;\n }\n\n const events = readMonitorLog(opts.session);\n const commands = pairCommands(events);\n const errors = commands.filter(\n (c) => c.exitCode != null && c.exitCode !== 0,\n ).length;\n\n const meta = events.find(\n (e) => e.type === \"monitor_meta\" && e.event === \"start\",\n );\n const stopped = events.some(\n (e) => e.type === \"monitor_meta\" && e.event === \"stop\",\n );\n\n const result = {\n sessionId: opts.session,\n exists: true,\n active: !stopped,\n shell: meta?.shell ?? \"unknown\",\n totalCommands: commands.length,\n errors,\n sizeBytes: stats.sizeBytes,\n timeSpan:\n commands.length > 0\n ? {\n start: commands[0].startedAt,\n end:\n commands[commands.length - 1].endedAt ??\n commands[commands.length - 1].startedAt,\n }\n : null,\n };\n\n if (opts.json) {\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n\n console.log(`Monitor: ${opts.session}`);\n console.log(` Status: ${result.active ? \"active\" : \"stopped\"}`);\n console.log(` Shell: ${result.shell}`);\n console.log(` Commands: ${result.totalCommands}`);\n console.log(` Errors: ${result.errors}`);\n if (result.timeSpan) {\n console.log(` From: ${result.timeSpan.start}`);\n console.log(` To: ${result.timeSpan.end}`);\n }\n });\n\n// ── zam monitor open ─────────────────────────────────────────────────────\n\n/**\n * Resolve the `zam` invocation — built CLI if available, otherwise tsx source.\n * This ensures the spawned terminal uses the correct entrypoint.\n */\nfunction findExecutable(command: string): string | null {\n try {\n const lookup =\n process.platform === \"win32\"\n ? `where.exe ${command}`\n : `command -v ${command}`;\n const result = execSync(lookup, { encoding: \"utf-8\" })\n .split(/\\r?\\n/)[0]\n ?.trim();\n return result || null;\n } catch {\n return null;\n }\n}\n\nfunction resolveZamInvocation(shell: MonitorShell): string {\n const installed = findExecutable(\"zam\");\n if (installed) {\n return isPowerShellShell(shell)\n ? `& ${psSingleQuoted(installed)}`\n : installed;\n }\n\n const projectRoot = join(import.meta.dirname, \"..\", \"..\", \"..\");\n const cliSource = join(projectRoot, \"src/cli/index.ts\");\n if (isPowerShellShell(shell)) {\n return `& npx --prefix ${psSingleQuoted(projectRoot)} tsx ${psSingleQuoted(cliSource)}`;\n }\n return `npx --prefix ${JSON.stringify(projectRoot)} tsx ${JSON.stringify(cliSource)}`;\n}\n\nfunction buildMonitorSetupCommand(\n dir: string,\n sessionId: string,\n shell: MonitorShell,\n): string {\n const zamInvocation = resolveZamInvocation(shell);\n if (isPowerShellShell(shell)) {\n return [\n `Set-Location -LiteralPath ${psSingleQuoted(dir)}`,\n `$__zamHook = ${zamInvocation} monitor start --session ${psSingleQuoted(sessionId)} --shell ${shell}`,\n \"Invoke-Expression ($__zamHook -join [Environment]::NewLine)\",\n \"Remove-Variable __zamHook\",\n ].join(\"; \");\n }\n\n return `cd ${JSON.stringify(dir)} && eval \"$(${zamInvocation} monitor start --session ${sessionId} --shell ${shell})\"`;\n}\n\n/**\n * Detect whether iTerm2 is running (preferred on macOS).\n */\nfunction isItermRunning(): boolean {\n try {\n const result = execSync(\n 'osascript -e \\'tell application \"System Events\" to (name of processes) contains \"iTerm2\"\\' 2>/dev/null',\n { encoding: \"utf-8\" },\n ).trim();\n return result === \"true\";\n } catch {\n return false;\n }\n}\n\nmonitorCommand\n .command(\"open\")\n .description(\"Open a new monitored terminal window for a session\")\n .requiredOption(\"--session <id>\", \"Session ID to monitor\")\n .option(\"--dir <path>\", \"Working directory (defaults to cwd)\")\n .option(\n \"--shell <type>\",\n \"Shell type: zsh | bash | pwsh | powershell (auto-detected)\",\n )\n .action((opts) => {\n let shell: MonitorShell;\n try {\n shell = normalizeShell(opts.shell);\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n\n // Validate session exists\n let db: Database | undefined;\n try {\n db = openDatabase();\n const session = db\n .prepare(\"SELECT id, completed_at FROM sessions WHERE id = ?\")\n .get(opts.session) as\n | { id: string; completed_at: string | null }\n | undefined;\n\n if (!session) {\n console.error(`Error: Session not found: ${opts.session}`);\n process.exit(1);\n }\n if (session.completed_at) {\n console.error(`Error: Session already completed: ${opts.session}`);\n process.exit(1);\n }\n\n // Save monitor preference so the agent knows to default to terminal\n if (!getSetting(db, \"monitor_method\")) {\n setSetting(db, \"monitor_method\", \"terminal\");\n }\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n } finally {\n db?.close();\n }\n\n const dir = opts.dir ?? process.cwd();\n const shellSetup = buildMonitorSetupCommand(dir, opts.session, shell);\n\n if (process.platform === \"darwin\" && !isPowerShellShell(shell)) {\n openMacTerminal(shellSetup, opts.session, dir);\n } else if (process.platform === \"win32\" && isPowerShellShell(shell)) {\n openWindowsPowerShell(shellSetup, opts.session, dir, shell);\n } else {\n console.log(`Run this in a new terminal:\\n`);\n console.log(` ${shellSetup}\\n`);\n console.log(\n `(Automatic terminal opening is only supported on macOS Terminal/iTerm2 and Windows PowerShell for now.)`,\n );\n }\n });\n\n/**\n * Open a macOS terminal window via AppleScript.\n * Uses a temp .scpt file to avoid shell quoting hell.\n */\nfunction openMacTerminal(\n shellSetup: string,\n sessionId: string,\n dir: string,\n): void {\n const useIterm = isItermRunning();\n const escaped = shellSetup.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n\n const appleScript = useIterm\n ? `tell application \"iTerm2\"\n activate\n set newWindow to (create window with default profile)\n tell current session of newWindow\n write text \"${escaped}\"\n end tell\nend tell`\n : `tell application \"Terminal\"\n activate\n do script \"${escaped}\"\nend tell`;\n\n const tmpFile = join(tmpdir(), `zam-monitor-${sessionId}.scpt`);\n try {\n writeFileSync(tmpFile, appleScript);\n execSync(`osascript ${JSON.stringify(tmpFile)}`, { stdio: \"ignore\" });\n console.log(\n `Opened ${useIterm ? \"iTerm2\" : \"Terminal.app\"} window with monitoring for session ${sessionId}`,\n );\n console.log(` Directory: ${dir}`);\n } catch (err) {\n console.error(`Failed to open terminal: ${(err as Error).message}`);\n console.log(`\\nRun this manually in a new terminal:\\n`);\n console.log(` ${shellSetup}`);\n } finally {\n try {\n unlinkSync(tmpFile);\n } catch {\n /* ignore */\n }\n }\n}\n\n/**\n * Open a Windows PowerShell/pwsh window with monitoring installed.\n */\nfunction openWindowsPowerShell(\n shellSetup: string,\n sessionId: string,\n dir: string,\n requestedShell: MonitorShell,\n): void {\n const requestedExecutable =\n requestedShell === \"powershell\" ? \"powershell.exe\" : \"pwsh.exe\";\n const executable = findExecutable(requestedExecutable)\n ? requestedExecutable\n : \"powershell.exe\";\n const startCommand = [\n \"Start-Process\",\n `-FilePath ${psSingleQuoted(executable)}`,\n `-ArgumentList @('-NoExit','-NoProfile','-Command',${psSingleQuoted(shellSetup)})`,\n ].join(\" \");\n\n try {\n execFileSync(\n \"powershell.exe\",\n [\"-NoProfile\", \"-ExecutionPolicy\", \"Bypass\", \"-Command\", startCommand],\n {\n stdio: \"ignore\",\n },\n );\n console.log(\n `Opened ${executable === \"pwsh.exe\" ? \"PowerShell\" : \"Windows PowerShell\"} window with monitoring for session ${sessionId}`,\n );\n console.log(` Directory: ${dir}`);\n } catch (err) {\n console.error(`Failed to open PowerShell: ${(err as Error).message}`);\n console.log(`\\nRun this manually in a new PowerShell terminal:\\n`);\n console.log(` ${shellSetup}`);\n }\n}\n","/**\n * `zam review` — Interactive review session.\n */\n\nimport { Command } from \"commander\";\nimport type { Database } from \"libsql\";\nimport type { BloomLevel } from \"../../kernel/index.js\";\nimport {\n buildReviewQueue,\n generatePrompt,\n openDatabase,\n resolveReviewContext,\n} from \"../../kernel/index.js\";\nimport { runInteractiveReviewAction } from \"../review-actions.js\";\nimport { resolveUser } from \"./resolve-user.js\";\n\nexport const reviewCommand = new Command(\"review\")\n .description(\"Start an interactive review session\")\n .option(\"--user <id>\", \"User ID (default: whoami)\")\n .option(\"--max-new <n>\", \"Maximum new cards\", \"10\")\n .option(\"--max-reviews <n>\", \"Maximum review cards\", \"50\")\n .option(\"--no-resolve\", \"Skip resolving source_link into inline context\")\n .action(async (opts) => {\n let db: Database | undefined;\n try {\n db = openDatabase();\n const userId = resolveUser(opts, db);\n\n const queue = buildReviewQueue(db, {\n userId,\n maxNew: Number(opts.maxNew),\n maxReviews: Number(opts.maxReviews),\n });\n\n if (queue.items.length === 0) {\n console.log(\"No cards due for review. You're all caught up!\");\n db.close();\n return;\n }\n\n console.log(`\\nReview session: ${queue.items.length} card(s)`);\n console.log(\n ` New: ${queue.newCount} Review: ${queue.reviewCount} Relearn: ${queue.relearnCount}`,\n );\n console.log(` Domains: ${queue.totalDomains.join(\", \")}`);\n console.log();\n\n const _completed = 0;\n let stoppedEarly = false;\n let maintenanceActions = 0;\n const results: Array<{\n slug: string;\n rating: number;\n nextDue: string;\n }> = [];\n\n for (const [index, item] of queue.items.entries()) {\n const prompt = generatePrompt({\n cardId: item.cardId,\n tokenId: item.tokenId,\n slug: item.slug,\n concept: item.concept,\n domain: item.domain,\n bloomLevel: item.bloomLevel as BloomLevel,\n sourceLink: item.sourceLink,\n });\n\n console.log(\n `\\n[${index + 1}/${queue.items.length}] ${prompt.bloomVerb} (Bloom ${prompt.bloomLevel})`,\n );\n console.log(`Domain: ${prompt.domain || \"(none)\"}`);\n if (prompt.sourceLink) {\n console.log(`Source: ${prompt.sourceLink}`);\n if (opts.resolve !== false) {\n const ctx = await resolveReviewContext(item.sourceLink, {\n maxChars: 1200,\n }).catch(() => null);\n if (ctx && ctx.sourceType === \"dynamic_search\") {\n console.log(` ↳ ${ctx.content}`);\n } else if (ctx?.content.trim()) {\n const indented = ctx.content\n .trimEnd()\n .split(\"\\n\")\n .map((line) => ` │ ${line}`)\n .join(\"\\n\");\n console.log(\" Context:\");\n console.log(indented);\n if (ctx.truncated) {\n console.log(\" │ … (truncated)\");\n }\n }\n }\n }\n console.log(`\\n ${prompt.question}\\n`);\n\n const action = await runInteractiveReviewAction({\n db,\n userId,\n item,\n mode: \"review\",\n });\n\n if (action.action === \"stop\") {\n stoppedEarly = true;\n console.log(\"\\nStopping review.\");\n break;\n }\n\n if (action.action === \"rate\") {\n results.push({\n slug: item.slug,\n rating: action.rating!,\n nextDue: action.result.evaluation?.nextDueAt,\n });\n } else if (action.action !== \"skip\") {\n maintenanceActions++;\n }\n }\n\n // Session summary\n console.log(`\\n${\"═\".repeat(50)}`);\n console.log(\n stoppedEarly ? \"Review session ended.\" : \"Review session complete!\",\n );\n console.log(` Cards rated: ${results.length}`);\n if (maintenanceActions > 0) {\n console.log(` Maintenance actions: ${maintenanceActions}`);\n }\n\n if (results.length > 0) {\n const avgRating =\n results.reduce((s, r) => s + r.rating, 0) / results.length;\n console.log(` Average rating: ${avgRating.toFixed(1)}`);\n\n const forgot = results.filter((r) => r.rating === 1).length;\n if (forgot > 0) {\n console.log(` Forgot: ${forgot} card(s)`);\n }\n }\n\n db.close();\n } catch (err) {\n db?.close();\n // User cancelled with Ctrl+C — exit gracefully\n if ((err as Error).name === \"ExitPromptError\") {\n console.log(\"\\nReview session cancelled.\");\n process.exit(0);\n }\n console.error(\"Error:\", (err as Error).message);\n process.exit(1);\n }\n });\n","/**\n * `zam session` — Session management subcommand group.\n *\n * Session start follows the two-phase flow from Increment 2:\n * Phase 1 — Repetition: review due cards (pure recall first, skippable)\n * Phase 2 — Task execution: pick a work item from ADO or enter a custom task\n */\n\nimport { input, select } from \"@inquirer/prompts\";\nimport { Command } from \"commander\";\nimport type { Database } from \"libsql\";\nimport type { BloomLevel, ExecutionContext } from \"../../kernel/index.js\";\nimport {\n buildReviewQueue,\n endSession,\n fetchActiveWorkItems,\n generatePrompt,\n getSessionSummary,\n getTokenBySlug,\n loadADOConfig,\n logStep,\n openDatabase,\n startSession,\n} from \"../../kernel/index.js\";\nimport { runInteractiveReviewAction } from \"../review-actions.js\";\nimport { resolveUser } from \"./resolve-user.js\";\n\nfunction withDb(fn: (db: Database) => void): void {\n let db: Database | undefined;\n try {\n db = openDatabase();\n fn(db);\n } catch (err) {\n console.error(\"Error:\", (err as Error).message);\n process.exit(1);\n } finally {\n db?.close();\n }\n}\n\nexport const sessionCommand = new Command(\"session\").description(\n \"Manage learning sessions\",\n);\n\n// ── zam session start ─────────────────────────────────────────────────────\n\nsessionCommand\n .command(\"start\")\n .description(\"Start a new learning session (review → task)\")\n .option(\"--user <id>\", \"User ID (default: whoami)\")\n .option(\"--task <description>\", \"Task description (interactive if omitted)\")\n .option(\n \"--context <level>\",\n \"Execution context: shell | ui | reallife (default: shell)\",\n \"shell\",\n )\n .option(\n \"--skip-review\",\n \"Skip the repetition phase and go straight to task selection\",\n )\n .option(\n \"--review-minutes <n>\",\n \"Maximum minutes for the repetition phase (default: 20)\",\n \"20\",\n )\n .option(\"--json\", \"Output as JSON\")\n .option(\"--quiet\", \"Output only the session ID\")\n .action(async (opts) => {\n let db: Database | undefined;\n try {\n db = openDatabase();\n\n const validContexts = [\"shell\", \"ui\", \"reallife\"];\n if (!validContexts.includes(opts.context)) {\n console.error(\n `Invalid context: ${opts.context}. Must be one of: ${validContexts.join(\", \")}`,\n );\n process.exit(1);\n }\n\n const userId = resolveUser(opts, db);\n const reviewMinutes = Number(opts.reviewMinutes);\n\n // ── Phase 1: Repetition ────────────────────────────────────────────\n if (!opts.skipReview && !opts.quiet && !opts.json) {\n const reviewResults = await runRepetitionPhase(\n db,\n userId,\n reviewMinutes,\n );\n if (reviewResults.reviewed > 0) {\n console.log();\n }\n }\n\n // ── Phase 2: Task Selection ────────────────────────────────────────\n let task: string = opts.task;\n\n if (!task && !opts.quiet && !opts.json) {\n task = await selectTask(db);\n }\n\n if (!task) {\n // Fallback for --quiet/--json without --task\n console.error(\n \"Task description is required. Use --task or run interactively.\",\n );\n process.exit(1);\n }\n\n const session = startSession(db, {\n user_id: userId,\n task,\n execution_context: opts.context as ExecutionContext,\n });\n\n db.close();\n\n if (opts.quiet) {\n console.log(session.id);\n } else if (opts.json) {\n console.log(JSON.stringify(session, null, 2));\n } else {\n console.log(`\\nSession started: ${session.id}`);\n console.log(` User: ${session.user_id}`);\n console.log(` Task: ${session.task}`);\n console.log(` Context: ${session.execution_context}`);\n console.log(` Started: ${session.started_at}`);\n }\n } catch (err) {\n db?.close();\n if ((err as Error).name === \"ExitPromptError\") {\n console.log(\"\\nSession cancelled.\");\n process.exit(0);\n }\n console.error(\"Error:\", (err as Error).message);\n process.exit(1);\n }\n });\n\n// ── Phase 1: Repetition ─────────────────────────────────────────────────────\n\ninterface RepetitionResult {\n reviewed: number;\n maintained: number;\n skipped: boolean;\n}\n\nasync function runRepetitionPhase(\n db: Database,\n userId: string,\n maxMinutes: number,\n): Promise<RepetitionResult> {\n const queue = buildReviewQueue(db, { userId });\n\n if (queue.items.length === 0) {\n console.log(\"No cards due for review — moving to task selection.\\n\");\n return { reviewed: 0, maintained: 0, skipped: false };\n }\n\n console.log(\"═\".repeat(50));\n console.log(\"Phase 1: Repetition\");\n console.log(\"═\".repeat(50));\n console.log(`${queue.items.length} card(s) due`);\n console.log(\n ` New: ${queue.newCount} Review: ${queue.reviewCount} Relearn: ${queue.relearnCount}`,\n );\n console.log(` Domains: ${queue.totalDomains.join(\", \")}`);\n console.log(` Time limit: ${maxMinutes} minutes (skip anytime with 's')`);\n console.log();\n\n const startTime = Date.now();\n const timeLimitMs = maxMinutes * 60 * 1000;\n let reviewed = 0;\n let maintained = 0;\n\n for (const [index, item] of queue.items.entries()) {\n // Check time limit\n if (Date.now() - startTime >= timeLimitMs) {\n console.log(\n `\\nTime limit reached (${maxMinutes} min). Moving to task selection.`,\n );\n break;\n }\n\n const prompt = generatePrompt({\n cardId: item.cardId,\n tokenId: item.tokenId,\n slug: item.slug,\n concept: item.concept,\n domain: item.domain,\n bloomLevel: item.bloomLevel as BloomLevel,\n });\n\n const elapsed = Math.round((Date.now() - startTime) / 60000);\n console.log(\n `[${index + 1}/${queue.items.length}] ${prompt.bloomVerb} (Bloom ${prompt.bloomLevel}) — ${elapsed}/${maxMinutes} min`,\n );\n console.log(`Domain: ${prompt.domain || \"(none)\"}`);\n console.log(`\\n ${prompt.question}\\n`);\n\n const action = await runInteractiveReviewAction({\n db,\n userId,\n item,\n mode: \"session\",\n });\n\n if (action.action === \"stop\") {\n console.log(\"Stopping review and moving to task selection.\");\n return { reviewed, maintained, skipped: true };\n }\n\n if (action.action === \"rate\") {\n reviewed++;\n } else if (action.action !== \"skip\") {\n maintained++;\n }\n }\n\n if (reviewed > 0 || maintained > 0) {\n console.log(\"─\".repeat(50));\n console.log(`Repetition complete — ${reviewed} card(s) rated.`);\n if (maintained > 0) {\n console.log(`Maintenance actions: ${maintained}`);\n }\n }\n\n return { reviewed, maintained, skipped: false };\n}\n\n// ── Phase 2: Task Selection ─────────────────────────────────────────────────\n\nasync function selectTask(db: Database): Promise<string> {\n console.log(\"═\".repeat(50));\n console.log(\"Phase 2: Task Selection\");\n console.log(\"═\".repeat(50));\n\n const adoConfig = loadADOConfig(db);\n\n if (adoConfig) {\n const items = await fetchActiveWorkItems(adoConfig);\n\n if (items.length > 0) {\n const choices = items.map((wi) => ({\n name: `[${wi.type}] ${wi.title} (${wi.state})`,\n value: `[ADO-${wi.id}] ${wi.title}`,\n }));\n choices.push({ name: \"Enter a custom task...\", value: \"__custom__\" });\n\n const picked = await select({\n message: `${items.length} active work item(s) — pick one:`,\n choices,\n });\n\n if (picked !== \"__custom__\") return picked;\n } else {\n console.log(\"No active work items found in Azure DevOps.\");\n }\n }\n\n return input({ message: \"Task description:\" });\n}\n\n// ── zam session log ───────────────────────────────────────────────────────\n\nsessionCommand\n .command(\"log\")\n .description(\"Log a step within a session\")\n .requiredOption(\"--session <id>\", \"Session ID\")\n .requiredOption(\"--token <slug>\", \"Token slug\")\n .requiredOption(\"--done-by <who>\", \"Who performed the step (user or agent)\")\n .option(\"--rating <n>\", \"Rating (1-4)\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--quiet\", \"Suppress output (exit code only)\")\n .action((opts) => {\n withDb((db) => {\n const token = getTokenBySlug(db, opts.token);\n if (!token) {\n console.error(`Token not found: ${opts.token}`);\n process.exit(1);\n }\n\n const step = logStep(db, {\n session_id: opts.session,\n token_id: token.id,\n done_by: opts.doneBy as \"user\" | \"agent\",\n rating: opts.rating ? Number(opts.rating) : undefined,\n });\n\n if (opts.quiet) return;\n if (opts.json) {\n console.log(JSON.stringify(step, null, 2));\n } else {\n console.log(`Step logged: ${step.id}`);\n console.log(` Token: ${opts.token}`);\n console.log(` Done by: ${step.done_by}`);\n if (step.rating != null) {\n console.log(` Rating: ${step.rating}`);\n }\n }\n });\n });\n\n// ── zam session end ───────────────────────────────────────────────────────\n\nsessionCommand\n .command(\"end\")\n .description(\"End a session and show summary\")\n .requiredOption(\"--session <id>\", \"Session ID\")\n .option(\"--json\", \"Output as JSON\")\n .action((opts) => {\n withDb((db) => {\n endSession(db, opts.session);\n const summary = getSessionSummary(db, opts.session);\n\n if (opts.json) {\n console.log(JSON.stringify(summary, null, 2));\n return;\n }\n\n console.log(`Session ${summary.session.id} completed.`);\n console.log(` Task: ${summary.session.task}`);\n console.log(` Started: ${summary.session.started_at}`);\n console.log(` Completed: ${summary.session.completed_at}`);\n console.log(` Steps: ${summary.steps.length}`);\n\n if (summary.steps.length > 0) {\n console.log(\"\\nSteps:\");\n console.log(\" Token Done by Rating Concept\");\n console.log(` ${\"─\".repeat(70)}`);\n for (const s of summary.steps) {\n console.log(\n ` ${s.slug.padEnd(21)} ${s.done_by.padEnd(8)} ${String(s.rating ?? \"-\").padEnd(7)} ${s.concept.slice(0, 30)}`,\n );\n }\n }\n });\n });\n","/**\n * `zam settings` — User settings management.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { Command } from \"commander\";\nimport type { Database } from \"libsql\";\nimport {\n deleteSetting,\n getAllSettings,\n getAllSettingsDetailed,\n getRepoPaths,\n getSetting,\n openDatabase,\n setSetting,\n} from \"../../kernel/index.js\";\n\nfunction withDb(fn: (db: Database) => void): void {\n let db: Database | undefined;\n try {\n db = openDatabase();\n fn(db);\n } catch (err) {\n console.error(\"Error:\", (err as Error).message);\n process.exit(1);\n } finally {\n db?.close();\n }\n}\n\nexport const settingsCommand = new Command(\"settings\").description(\n \"Manage user settings\",\n);\n\n// ── zam settings show ─────────────────────────────────────────────────────\n\nsettingsCommand\n .command(\"show\")\n .description(\"Show all settings\")\n .option(\"--json\", \"Output as JSON\")\n .action((opts) => {\n withDb((db) => {\n if (opts.json) {\n console.log(JSON.stringify(getAllSettings(db), null, 2));\n return;\n }\n\n const settings = getAllSettingsDetailed(db);\n if (settings.length === 0) {\n console.log(\"No settings configured.\");\n return;\n }\n\n console.log(\"Settings:\\n\");\n console.log(\"Key Value Updated\");\n console.log(\"─\".repeat(65));\n for (const s of settings) {\n console.log(\n `${s.key.padEnd(20)} ${s.value.padEnd(20)} ${s.updated_at}`,\n );\n }\n });\n });\n\n// ── zam settings get ──────────────────────────────────────────────────────\n\nsettingsCommand\n .command(\"get <key>\")\n .description(\"Get a single setting\")\n .option(\"--json\", \"Output as JSON\")\n .action((key, opts) => {\n withDb((db) => {\n const value = getSetting(db, key);\n\n if (opts.json) {\n console.log(JSON.stringify({ key, value: value ?? null }));\n return;\n }\n\n if (value === undefined) {\n console.log(`Not set: ${key}`);\n } else {\n console.log(value);\n }\n });\n });\n\n// ── zam settings set ──────────────────────────────────────────────────────\n\nsettingsCommand\n .command(\"set <key> <value>\")\n .description(\"Set a setting\")\n .option(\"--quiet\", \"Suppress output\")\n .action((key, value, opts) => {\n withDb((db) => {\n let parsedVal = value;\n if (key === \"llm.enabled\") {\n const lower = value.toLowerCase();\n if (\n lower === \"on\" ||\n lower === \"enable\" ||\n lower === \"enabled\" ||\n lower === \"true\"\n ) {\n parsedVal = \"true\";\n } else if (\n lower === \"off\" ||\n lower === \"disable\" ||\n lower === \"disabled\" ||\n lower === \"false\"\n ) {\n parsedVal = \"false\";\n }\n }\n setSetting(db, key, parsedVal);\n if (!opts.quiet) {\n console.log(`Set ${key} = ${parsedVal}`);\n }\n });\n });\n\n// ── zam settings delete ───────────────────────────────────────────────────\n\nsettingsCommand\n .command(\"delete <key>\")\n .description(\"Delete a setting\")\n .option(\"--quiet\", \"Suppress output\")\n .action((key, opts) => {\n withDb((db) => {\n const deleted = deleteSetting(db, key);\n if (!opts.quiet) {\n if (deleted) {\n console.log(`Deleted: ${key}`);\n } else {\n console.log(`Not found: ${key}`);\n }\n }\n });\n });\n\n// ── zam settings llm [state] ──────────────────────────────────────────────\n\nsettingsCommand\n .command(\"llm [state]\")\n .description(\n \"Quickly enable/disable or check local LLM integration (on/off/enable/disable)\",\n )\n .action((state) => {\n withDb((db) => {\n if (!state) {\n const enabled = getSetting(db, \"llm.enabled\") || \"false\";\n console.log(\n `LLM Integration is currently: ${\n enabled === \"true\"\n ? \"\\x1b[32mON (enabled)\\x1b[0m\"\n : \"\\x1b[31mOFF (disabled)\\x1b[0m\"\n }`,\n );\n return;\n }\n\n const lower = state.toLowerCase();\n let value = \"false\";\n if (\n lower === \"on\" ||\n lower === \"enable\" ||\n lower === \"enabled\" ||\n lower === \"true\"\n ) {\n value = \"true\";\n } else if (\n lower === \"off\" ||\n lower === \"disable\" ||\n lower === \"disabled\" ||\n lower === \"false\"\n ) {\n value = \"false\";\n } else {\n console.error(\n `Invalid state: ${state}. Use on, off, enable, or disable.`,\n );\n process.exit(1);\n }\n\n setSetting(db, \"llm.enabled\", value);\n console.log(\n `LLM Integration is now: ${\n value === \"true\"\n ? \"\\x1b[32mON (enabled)\\x1b[0m\"\n : \"\\x1b[31mOFF (disabled)\\x1b[0m\"\n }`,\n );\n });\n });\n\n// ── zam settings locale [lang] ───────────────────────────────────────────\n\nsettingsCommand\n .command(\"locale [lang]\")\n .description(\n \"Quickly set or check manual ZAM language override (en/de/es/fr/pt/zh/ja)\",\n )\n .action((lang) => {\n withDb((db) => {\n if (!lang) {\n const locale = getSetting(db, \"system.locale\") || \"en\";\n console.log(`Active language (locale): \\x1b[36m${locale}\\x1b[0m`);\n return;\n }\n\n const lower = lang.toLowerCase();\n const supported = [\"en\", \"de\", \"es\", \"fr\", \"pt\", \"zh\", \"ja\"];\n if (!supported.includes(lower)) {\n console.error(\n `Invalid language code: ${lang}. Supported: ${supported.join(\", \")}`,\n );\n process.exit(1);\n }\n\n setSetting(db, \"system.locale\", lower);\n console.log(`Language set to: \\x1b[32m${lower}\\x1b[0m`);\n });\n });\n\n// ── zam settings repos ───────────────────────────────────────────────────\n\nsettingsCommand\n .command(\"repos\")\n .description(\"Show or set Personal, Team, and Organization repository paths\")\n .option(\"--personal <path>\", \"Set the Personal Repository path\")\n .option(\"--team <path>\", \"Set the Team Repository path\")\n .option(\"--org <path>\", \"Set the Organization Repository path\")\n .action((opts) => {\n withDb((db) => {\n let changed = false;\n\n if (opts.personal !== undefined) {\n setSetting(db, \"repo.personal\", opts.personal);\n console.log(`Set repo.personal = ${opts.personal}`);\n changed = true;\n }\n if (opts.team !== undefined) {\n setSetting(db, \"repo.team\", opts.team);\n console.log(`Set repo.team = ${opts.team}`);\n changed = true;\n }\n if (opts.org !== undefined) {\n setSetting(db, \"repo.org\", opts.org);\n console.log(`Set repo.org = ${opts.org}`);\n changed = true;\n }\n\n if (changed) {\n console.log(\"\\nUpdated Repository Settings:\\n\");\n } else {\n console.log(\"Repository Settings:\\n\");\n }\n\n const paths = getRepoPaths(db);\n console.log(\n `Personal Repo: ${\n paths.personal\n ? `\\x1b[32m${paths.personal}\\x1b[0m`\n : \"\\x1b[31mNot Configured\\x1b[0m\"\n }`,\n );\n console.log(\n `Team Repo: ${\n paths.team\n ? `\\x1b[32m${paths.team}\\x1b[0m`\n : \"\\x1b[31mNot Configured\\x1b[0m\"\n }`,\n );\n console.log(\n `Org Repo: ${\n paths.org\n ? `\\x1b[32m${paths.org}\\x1b[0m`\n : \"\\x1b[31mNot Configured\\x1b[0m\"\n }`,\n );\n\n // Check if folders exist\n console.log(\"\\nValidation:\");\n for (const [name, path] of Object.entries(paths)) {\n if (path) {\n const exists = existsSync(path);\n console.log(\n ` ${name.padEnd(9)}: ${\n exists\n ? \"\\x1b[32m✓ Valid folder\\x1b[0m\"\n : \"\\x1b[31m✗ Directory does not exist\\x1b[0m\"\n }`,\n );\n } else {\n console.log(` ${name.padEnd(9)}: \\x1b[33m- Not Set\\x1b[0m`);\n }\n }\n });\n });\n","/**\n * `zam setup` — Distribute skill files from the zam package into the current\n * personal instance's agent skill directories, and optionally initialize the\n * ZAM database and generate agent-specific instruction files.\n *\n * Run this once after cloning a ZAM personal instance, and again after\n * upgrading zam (with --force) to refresh the skill files.\n */\n\nimport { copyFileSync, existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { basename, dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { Command } from \"commander\";\nimport { getDefaultDbPath, openDatabaseWithSync } from \"../../kernel/index.js\";\n\n// The bundled CLI resolves from dist/cli/index.js; source tests resolve from\n// src/cli/commands/setup.ts. Select the first candidate containing package.json.\nconst packageRoot =\n [\n fileURLToPath(new URL(\"../..\", import.meta.url)),\n fileURLToPath(new URL(\"../../..\", import.meta.url)),\n ].find((candidate) => existsSync(join(candidate, \"package.json\"))) ??\n fileURLToPath(new URL(\"../..\", import.meta.url));\n\nconst SKILL_PAIRS: Array<{ from: string; to: string }> = [\n {\n from: join(packageRoot, \".claude\", \"skills\", \"zam\", \"SKILL.md\"),\n to: join(\".claude\", \"skills\", \"zam\", \"SKILL.md\"),\n },\n {\n from: join(packageRoot, \".agent\", \"skills\", \"zam\", \"SKILL.md\"),\n to: join(\".agent\", \"skills\", \"zam\", \"SKILL.md\"),\n },\n {\n from: join(packageRoot, \".agents\", \"skills\", \"zam\", \"SKILL.md\"),\n to: join(\".agents\", \"skills\", \"zam\", \"SKILL.md\"),\n },\n];\n\nexport function copySkills(force: boolean, cwd: string = process.cwd()): void {\n let anyAction = false;\n\n for (const { from, to } of SKILL_PAIRS) {\n const dest = join(cwd, to);\n\n if (!existsSync(from)) {\n console.warn(` warn source not found, skipping: ${from}`);\n continue;\n }\n\n if (existsSync(dest) && !force) {\n console.log(` skip ${to} (already present — use --force to update)`);\n continue;\n }\n\n mkdirSync(dirname(dest), { recursive: true });\n copyFileSync(from, dest);\n console.log(` copy ${to}`);\n anyAction = true;\n }\n\n if (!anyAction && !force) {\n console.log(\n \"\\nSkill files are already up to date. Run with --force to overwrite.\",\n );\n }\n}\n\nfunction initDatabase(skipInit: boolean): void {\n if (skipInit) return;\n\n try {\n const dbPath = getDefaultDbPath();\n const db = openDatabaseWithSync({ initialize: true });\n db.close();\n console.log(` init ZAM database at ${dbPath}`);\n } catch (err) {\n // Database may already exist — not an error during setup.\n const msg = (err as Error).message;\n if (!msg.includes(\"already\")) {\n console.warn(` warn database init: ${msg}`);\n } else {\n console.log(` skip database already initialized`);\n }\n }\n}\n\nexport function writeClaudeMd(\n skipClaudeMd: boolean,\n cwd: string = process.cwd(),\n): void {\n if (skipClaudeMd) return;\n\n const dest = join(cwd, \"CLAUDE.md\");\n if (existsSync(dest)) {\n console.log(` skip CLAUDE.md (already present)`);\n return;\n }\n\n const name = basename(cwd);\n writeFileSync(\n dest,\n `# ZAM Personal Kernel — ${name}\n\nThis is a ZAM personal instance. ZAM builds lasting skills through spaced\nrepetition during real work — not separate study sessions.\n\n## First time here?\nRun \\`/setup\\` in Claude Code or Gemini CLI to complete first-time setup.\n\n## Regular use\nRun \\`/zam\\` to start a learning session on whatever you are working on.\n\n## What lives here\n- \\`beliefs/\\` — your worldview, approved by git commit\n- \\`goals/\\` — your objectives, decomposed into tasks and learning tokens\n\n## Fast-changing data\nLearning tokens, cards, and review history live in local SQLite by default.\nUse \\`zam connector setup turso\\` to store cloud credentials in\n\\`~/.zam/credentials.json\\` and use a Turso database across machines.\n`,\n \"utf8\",\n );\n console.log(` write CLAUDE.md`);\n}\n\nexport function writeAgentsMd(\n skipAgentsMd: boolean,\n cwd: string = process.cwd(),\n): void {\n if (skipAgentsMd) return;\n\n const dest = join(cwd, \"AGENTS.md\");\n if (existsSync(dest)) {\n console.log(` skip AGENTS.md (already present)`);\n return;\n }\n\n const name = basename(cwd);\n writeFileSync(\n dest,\n `# ZAM Personal Kernel - ${name}\n\nThis is a ZAM personal instance. ZAM builds lasting skills through spaced\nrepetition during real work, not separate study sessions.\n\n## First time here?\nRun \\`zam setup\\` from the shell. When this repository includes\n\\`.agents/skills/setup/\\`, you can instead select \\`setup\\` through \\`/skills\\`\nor invoke \\`$setup\\`.\n\n## Regular use\nSelect the \\`zam\\` skill through \\`/skills\\` or invoke \\`$zam\\` to start a\nlearning session on whatever you are working on.\n\n## What lives here\n- \\`beliefs/\\` - your worldview, approved by git commit\n- \\`goals/\\` - your objectives, decomposed into tasks and learning tokens\n\n## Fast-changing data\nLearning tokens, cards, and review history live in local SQLite by default.\nUse \\`zam connector setup turso\\` to store cloud credentials in\n\\`~/.zam/credentials.json\\` and use a Turso database across machines.\n\n## Codex skills\nCodex discovers repository skills under \\`.agents/skills/\\`. Run\n\\`zam setup --force\\` after upgrading \\`zam-core\\` to refresh them.\n`,\n \"utf8\",\n );\n console.log(` write AGENTS.md`);\n}\n\nexport const setupCommand = new Command(\"setup\")\n .description(\n \"Distribute ZAM skill files into this personal instance and initialize the database\",\n )\n .option(\n \"--force\",\n \"overwrite existing skill files (use after upgrading zam)\",\n false,\n )\n .option(\"--skip-init\", \"skip database initialization\", false)\n .option(\"--skip-claude-md\", \"skip CLAUDE.md generation\", false)\n .option(\"--skip-agents-md\", \"skip AGENTS.md generation\", false)\n .action(\n (opts: {\n force: boolean;\n skipInit: boolean;\n skipClaudeMd: boolean;\n skipAgentsMd: boolean;\n }) => {\n console.log(`Setting up ZAM in ${process.cwd()}\\n`);\n\n copySkills(opts.force);\n initDatabase(opts.skipInit);\n writeClaudeMd(opts.skipClaudeMd);\n writeAgentsMd(opts.skipAgentsMd);\n\n console.log(\n \"\\nDone. Run `zam whoami --set <your-id>` to set your identity. Start the `zam` skill with `/zam` in Claude/Gemini-compatible clients or `$zam` (or `/skills`) in Codex.\",\n );\n },\n );\n","/**\n * `zam skill` — Manage agent skill entries (task recipes).\n */\n\nimport { Command } from \"commander\";\nimport type { Database } from \"libsql\";\nimport {\n createAgentSkill,\n getAgentSkill,\n listAgentSkills,\n openDatabase,\n} from \"../../kernel/index.js\";\n\nfunction withDb(fn: (db: Database) => void): void {\n let db: Database | undefined;\n try {\n db = openDatabase();\n fn(db);\n } catch (err) {\n console.error(\"Error:\", (err as Error).message);\n process.exit(1);\n } finally {\n db?.close();\n }\n}\n\nexport const skillCommand = new Command(\"skill\").description(\n \"Manage agent skill entries (task recipes)\",\n);\n\n// ── zam skill list ────────────────────────────────────────────────────────\n\nskillCommand\n .command(\"list\")\n .description(\"List all agent skills\")\n .option(\"--json\", \"Output as JSON\")\n .action((opts) => {\n withDb((db) => {\n const skills = listAgentSkills(db);\n\n if (opts.json) {\n console.log(JSON.stringify(skills, null, 2));\n return;\n }\n\n if (skills.length === 0) {\n console.log(\"No agent skills registered yet.\");\n return;\n }\n\n console.log(`Agent Skills (${skills.length})`);\n console.log(\"─\".repeat(60));\n for (const s of skills) {\n console.log(\n ` ${s.slug.padEnd(30)} [${s.source}] ${s.description.slice(0, 40)}`,\n );\n console.log(\n ` ${s.steps.length} step(s) tokens: ${s.token_slugs.join(\", \") || \"none\"}`,\n );\n }\n });\n });\n\n// ── zam skill show ────────────────────────────────────────────────────────\n\nskillCommand\n .command(\"show\")\n .description(\"Show a specific agent skill\")\n .requiredOption(\"--slug <slug>\", \"Skill slug\")\n .option(\"--json\", \"Output as JSON\")\n .action((opts) => {\n withDb((db) => {\n const skill = getAgentSkill(db, opts.slug);\n if (!skill) {\n console.error(`Skill not found: ${opts.slug}`);\n process.exit(1);\n }\n\n if (opts.json) {\n console.log(JSON.stringify(skill, null, 2));\n return;\n }\n\n console.log(`Skill: ${skill.slug}`);\n console.log(` Description: ${skill.description}`);\n console.log(` Source: ${skill.source}`);\n console.log(` Tokens: ${skill.token_slugs.join(\", \") || \"none\"}`);\n console.log(` Created: ${skill.created_at}`);\n console.log(`\\nSteps:`);\n skill.steps.forEach((step, i) => {\n console.log(` ${i + 1}. ${step}`);\n });\n });\n });\n\n// ── zam skill add ─────────────────────────────────────────────────────────\n\nskillCommand\n .command(\"add\")\n .description(\"Register a new agent skill\")\n .requiredOption(\"--slug <slug>\", \"Unique skill identifier\")\n .requiredOption(\"--description <text>\", \"One-sentence description\")\n .requiredOption(\"--steps <json>\", \"JSON array of step strings\")\n .option(\n \"--tokens <slugs>\",\n \"Comma-separated token slugs related to this skill\",\n )\n .option(\n \"--source <type>\",\n \"Source: learned | builtin (default: learned)\",\n \"learned\",\n )\n .option(\"--json\", \"Output as JSON\")\n .action((opts) => {\n withDb((db) => {\n let steps: string[];\n try {\n steps = JSON.parse(opts.steps) as string[];\n if (!Array.isArray(steps))\n throw new Error(\"steps must be a JSON array\");\n } catch {\n console.error(\"Invalid --steps: must be a valid JSON array of strings\");\n process.exit(1);\n }\n\n const tokenSlugs = opts.tokens\n ? opts.tokens\n .split(\",\")\n .map((s: string) => s.trim())\n .filter(Boolean)\n : [];\n\n const skill = createAgentSkill(db, {\n slug: opts.slug,\n description: opts.description,\n steps,\n token_slugs: tokenSlugs,\n source: opts.source as \"learned\" | \"builtin\",\n });\n\n if (opts.json) {\n console.log(JSON.stringify(skill, null, 2));\n } else {\n console.log(`Skill registered: ${skill.slug}`);\n console.log(` ${skill.steps.length} step(s) saved`);\n }\n });\n });\n","/**\n * `zam stats` — Learning dashboard.\n */\n\nimport { Command } from \"commander\";\nimport type { Database } from \"libsql\";\nimport {\n getDomainCompetence,\n getUserStats,\n openDatabase,\n} from \"../../kernel/index.js\";\nimport { resolveUser } from \"./resolve-user.js\";\n\nfunction withDb(fn: (db: Database) => void): void {\n let db: Database | undefined;\n try {\n db = openDatabase();\n fn(db);\n } catch (err) {\n console.error(\"Error:\", (err as Error).message);\n process.exit(1);\n } finally {\n db?.close();\n }\n}\n\nexport const statsCommand = new Command(\"stats\")\n .description(\"Show learning dashboard for a user\")\n .option(\"--user <id>\", \"User ID (default: whoami)\")\n .option(\"--json\", \"Output as JSON\")\n .action((opts) => {\n withDb((db) => {\n const userId = resolveUser(opts, db);\n const stats = getUserStats(db, userId);\n const domains = getDomainCompetence(db, userId);\n\n if (opts.json) {\n console.log(JSON.stringify({ stats, domains }, null, 2));\n return;\n }\n\n console.log(`Learning Dashboard — ${stats.userId}`);\n console.log(\"═\".repeat(50));\n console.log(` Total tokens: ${stats.totalTokens}`);\n console.log(` Cards in deck: ${stats.cardsInDeck}`);\n console.log(` Due today: ${stats.dueToday}`);\n console.log(` Blocked: ${stats.blocked}`);\n console.log(` Mature: ${stats.mature}`);\n console.log(` Avg stability: ${stats.avgStability ?? \"N/A\"}`);\n console.log(` Total sessions: ${stats.totalSessions}`);\n console.log(` Last session: ${stats.lastSession ?? \"N/A\"}`);\n\n if (domains.length > 0) {\n console.log(\"\\nDomain Competence:\");\n console.log(\"─\".repeat(80));\n console.log(\n \" Domain Cards Mature Stability Retention Suggested Mode\",\n );\n console.log(` ${\"─\".repeat(74)}`);\n for (const d of domains) {\n console.log(\n ` ${d.domain.padEnd(17)} ${String(d.totalCards).padEnd(6)} ${String(d.matureCards).padEnd(7)} ${String(d.avgStability).padEnd(10)} ${(d.retentionRate * 100).toFixed(1).padStart(5)}% ${d.suggestedMode}`,\n );\n }\n }\n });\n });\n","/**\n * `zam token` — Token management subcommand group.\n */\n\nimport { Command } from \"commander\";\nimport type { Database } from \"libsql\";\nimport type { BloomLevel, SymbiosisMode } from \"../../kernel/index.js\";\nimport {\n addPrerequisite,\n createToken,\n deleteToken,\n deprecateToken,\n findTokens,\n generateConceptFreeCue,\n getCard,\n getDependents,\n getPrerequisites,\n getSetting,\n getTokenBySlug,\n getTokenDeleteImpact,\n listTokens,\n openDatabase,\n resolveReviewContext,\n updateToken,\n} from \"../../kernel/index.js\";\nimport { generateQuestionViaLLM } from \"../llm/client.js\";\nimport { resolveUser } from \"./resolve-user.js\";\n\nasync function withDb(\n fn: (db: Database) => Promise<void> | void,\n): Promise<void> {\n let db: Database | undefined;\n try {\n db = openDatabase();\n await fn(db);\n } catch (err) {\n console.error(\"Error:\", (err as Error).message);\n process.exit(1);\n } finally {\n db?.close();\n }\n}\n\nfunction jsonOut(data: unknown): void {\n console.log(JSON.stringify(data, null, 2));\n}\n\nexport const tokenCommand = new Command(\"token\").description(\n \"Manage knowledge tokens\",\n);\n\n// ── zam token register ────────────────────────────────────────────────────\n\ntokenCommand\n .command(\"register\")\n .description(\"Register a new knowledge token\")\n .requiredOption(\"--slug <slug>\", \"Unique token slug\")\n .requiredOption(\"--concept <concept>\", \"Concept description\")\n .option(\"--domain <domain>\", \"Knowledge domain\", \"\")\n .option(\"--bloom <level>\", \"Bloom taxonomy level (1-5)\", \"1\")\n .option(\"--source-link <link>\", \"Source file path or reference URL\", \"\")\n .option(\"--question <question>\", \"Specific question prompt for recall\", \"\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (opts) => {\n await withDb(async (db) => {\n let question: string | null = opts.question || null;\n if (!question) {\n const isLlmEnabled = getSetting(db, \"llm.enabled\") === \"true\";\n if (isLlmEnabled) {\n console.log(\n \"Generating high-quality active-recall question via local LLM...\",\n );\n try {\n let sourceLinkContent: string | null = null;\n if (opts.sourceLink) {\n const resolved = await resolveReviewContext(\n opts.sourceLink,\n ).catch(() => null);\n if (resolved) {\n sourceLinkContent = resolved.content;\n }\n }\n question = await generateQuestionViaLLM(db, {\n slug: opts.slug,\n concept: opts.concept,\n domain: opts.domain,\n bloomLevel: Number(opts.bloom),\n context: \"\",\n sourceLinkContent,\n });\n console.log(`Generated: \"${question}\"`);\n } catch (err) {\n console.warn(\n `LLM question generation failed: ${(err as Error).message}. Falling back to template.`,\n );\n }\n }\n\n if (!question) {\n question = generateConceptFreeCue(\n Number(opts.bloom) as BloomLevel,\n opts.slug,\n opts.domain,\n );\n }\n }\n\n const token = createToken(db, {\n slug: opts.slug,\n concept: opts.concept,\n domain: opts.domain,\n bloom_level: Number(opts.bloom) as BloomLevel,\n source_link: opts.sourceLink || null,\n question,\n });\n\n if (opts.json) {\n console.log(JSON.stringify(token, null, 2));\n } else {\n console.log(`Registered token: ${token.slug} (${token.id})`);\n console.log(` Concept: ${token.concept}`);\n console.log(` Domain: ${token.domain || \"(none)\"}`);\n console.log(` Bloom: ${token.bloom_level}`);\n console.log(` Question: ${token.question}`);\n if (token.source_link) {\n console.log(` Source: ${token.source_link}`);\n }\n }\n });\n });\n\n// ── zam token find ────────────────────────────────────────────────────────\n\ntokenCommand\n .command(\"find\")\n .description(\"Fuzzy search for tokens\")\n .requiredOption(\"--query <query>\", \"Search query\")\n .option(\"--json\", \"Output as JSON\")\n .action((opts) => {\n withDb((db) => {\n const results = findTokens(db, opts.query);\n\n if (opts.json) {\n console.log(JSON.stringify(results, null, 2));\n return;\n }\n\n if (results.length === 0) {\n console.log(\"No tokens found.\");\n return;\n }\n\n console.log(`Found ${results.length} token(s):\\n`);\n console.log(\n \"Score Slug Concept Domain Bloom\",\n );\n console.log(\"─\".repeat(90));\n for (const t of results) {\n console.log(\n `${String(t.score).padEnd(6)} ${t.slug.padEnd(21)} ${t.concept.slice(0, 31).padEnd(31)} ${(t.domain || \"-\").padEnd(11)} ${t.bloom_level}`,\n );\n }\n });\n });\n\n// ── zam token list ────────────────────────────────────────────────────────\n\ntokenCommand\n .command(\"list\")\n .description(\"List all tokens\")\n .option(\"--domain <domain>\", \"Filter by domain\")\n .option(\"--json\", \"Output as JSON\")\n .action((opts) => {\n withDb((db) => {\n const tokens = listTokens(\n db,\n opts.domain ? { domain: opts.domain } : undefined,\n );\n\n if (opts.json) {\n console.log(JSON.stringify(tokens, null, 2));\n return;\n }\n\n if (tokens.length === 0) {\n console.log(\"No tokens registered.\");\n return;\n }\n\n console.log(\n \"Slug Concept Domain Bloom\",\n );\n console.log(\"─\".repeat(80));\n for (const t of tokens) {\n console.log(\n `${t.slug.padEnd(21)} ${t.concept.slice(0, 31).padEnd(31)} ${(t.domain || \"-\").padEnd(11)} ${t.bloom_level}`,\n );\n }\n console.log(`\\n${tokens.length} token(s) total.`);\n });\n });\n\n// ── zam token edit ────────────────────────────────────────────────────────\n\ntokenCommand\n .command(\"edit\")\n .description(\"Edit a token's mutable fields\")\n .requiredOption(\"--slug <slug>\", \"Token slug\")\n .option(\"--concept <concept>\", \"Updated concept text\")\n .option(\"--domain <domain>\", \"Updated domain (blank allowed)\")\n .option(\"--bloom <level>\", \"Updated Bloom taxonomy level (1-5)\")\n .option(\"--context <context>\", \"Updated context (blank allowed)\")\n .option(\n \"--mode <mode>\",\n \"Updated symbiosis mode: shadowing | copilot | autonomy | none\",\n )\n .option(\n \"--source-link <link>\",\n \"Updated source file path or reference URL (blank allowed)\",\n )\n .option(\"--question <question>\", \"Updated question text (blank allowed)\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (opts) => {\n await withDb(async (db) => {\n const updates: {\n concept?: string;\n domain?: string;\n bloom_level?: BloomLevel;\n context?: string;\n symbiosis_mode?: SymbiosisMode | null;\n source_link?: string | null;\n question?: string | null;\n } = {};\n\n if (opts.concept !== undefined) updates.concept = opts.concept;\n if (opts.domain !== undefined) updates.domain = opts.domain;\n if (opts.bloom !== undefined)\n updates.bloom_level = Number(opts.bloom) as BloomLevel;\n if (opts.context !== undefined) updates.context = opts.context;\n if (opts.sourceLink !== undefined) {\n updates.source_link = opts.sourceLink === \"\" ? null : opts.sourceLink;\n }\n if (opts.question !== undefined) {\n updates.question = opts.question === \"\" ? null : opts.question;\n }\n if (opts.mode !== undefined) {\n const validModes = [\"shadowing\", \"copilot\", \"autonomy\", \"none\"];\n if (!validModes.includes(opts.mode)) {\n console.error(`Invalid --mode: ${opts.mode}`);\n process.exit(1);\n }\n updates.symbiosis_mode =\n opts.mode === \"none\" ? null : (opts.mode as SymbiosisMode);\n }\n\n const token = updateToken(db, opts.slug, updates);\n\n if (opts.json) {\n jsonOut(token);\n return;\n }\n\n console.log(`Updated token: ${token.slug}`);\n console.log(` Concept: ${token.concept}`);\n console.log(` Domain: ${token.domain || \"(none)\"}`);\n console.log(` Bloom: ${token.bloom_level}`);\n console.log(` Question: ${token.question || \"(none)\"}`);\n console.log(` Context: ${token.context || \"(none)\"}`);\n console.log(` Mode: ${token.symbiosis_mode ?? \"none\"}`);\n console.log(` Source: ${token.source_link || \"(none)\"}`);\n });\n });\n\n// ── zam token prereq ─────────────────────────────────────────────────────\n\ntokenCommand\n .command(\"prereq\")\n .description(\"Add a prerequisite edge between tokens\")\n .requiredOption(\"--token <slug>\", \"Token that requires a prerequisite\")\n .requiredOption(\"--requires <slug>\", \"Required prerequisite token\")\n .option(\"--json\", \"Output as JSON\")\n .action((opts) => {\n withDb((db) => {\n const token = getTokenBySlug(db, opts.token);\n if (!token) {\n console.error(`Token not found: ${opts.token}`);\n process.exit(1);\n }\n\n const requires = getTokenBySlug(db, opts.requires);\n if (!requires) {\n console.error(`Prerequisite token not found: ${opts.requires}`);\n process.exit(1);\n }\n\n addPrerequisite(db, token.id, requires.id);\n\n if (opts.json) {\n console.log(\n JSON.stringify(\n { token: opts.token, requires: opts.requires },\n null,\n 2,\n ),\n );\n } else {\n console.log(\n `Added prerequisite: ${opts.token} requires ${opts.requires}`,\n );\n }\n });\n });\n\n// ── zam token deprecate ───────────────────────────────────────────────────\n\ntokenCommand\n .command(\"deprecate\")\n .description(\n \"Mark a token as deprecated (excluded from reviews, not deleted)\",\n )\n .requiredOption(\"--slug <slug>\", \"Token slug to deprecate\")\n .option(\"--json\", \"Output as JSON\")\n .action((opts) => {\n withDb((db) => {\n const token = deprecateToken(db, opts.slug);\n\n if (opts.json) {\n console.log(JSON.stringify(token, null, 2));\n } else {\n console.log(`Deprecated: ${token.slug}`);\n console.log(` Concept: ${token.concept}`);\n console.log(` At: ${token.deprecated_at}`);\n }\n });\n });\n\n// ── zam token delete ──────────────────────────────────────────────────────\n\ntokenCommand\n .command(\"delete\")\n .description(\"Hard-delete a token and its dependent learning data\")\n .requiredOption(\"--slug <slug>\", \"Token slug to delete\")\n .option(\"--force\", \"Actually delete the token\")\n .option(\"--json\", \"Output as JSON\")\n .action((opts) => {\n withDb((db) => {\n const impact = getTokenDeleteImpact(db, opts.slug);\n\n if (!opts.force) {\n const preview = {\n slug: opts.slug,\n deleted: false,\n requiresForce: true,\n impact,\n };\n\n if (opts.json) {\n jsonOut(preview);\n return;\n }\n\n console.log(`Delete preview for ${opts.slug}:`);\n console.log(` Cards: ${impact.cards}`);\n console.log(` Review logs: ${impact.review_logs}`);\n console.log(\n ` Prereq edges from it: ${impact.prerequisite_edges_from_token}`,\n );\n console.log(\n ` Prereq edges to it: ${impact.prerequisite_edges_to_token}`,\n );\n console.log(` Session steps: ${impact.session_steps}`);\n console.log(` Sessions touched: ${impact.sessions_touched}`);\n console.log(` Agent skills updated: ${impact.agent_skills}`);\n console.log(\"\\nRe-run with --force to delete.\");\n return;\n }\n\n const result = deleteToken(db, opts.slug);\n\n if (opts.json) {\n jsonOut({\n slug: result.token.slug,\n deleted: true,\n impact: result.impact,\n });\n return;\n }\n\n console.log(`Deleted token: ${result.token.slug}`);\n console.log(` Cards removed: ${result.impact.cards}`);\n console.log(` Review logs removed: ${result.impact.review_logs}`);\n console.log(` Session steps removed: ${result.impact.session_steps}`);\n console.log(` Agent skills updated: ${result.impact.agent_skills}`);\n });\n });\n\n// ── zam token status ─────────────────────────────────────────────────────\n\ntokenCommand\n .command(\"status\")\n .description(\"Show full status of a token for a user\")\n .requiredOption(\"--token <slug>\", \"Token slug\")\n .option(\"--user <id>\", \"User ID (default: whoami)\")\n .option(\"--json\", \"Output as JSON\")\n .action((opts) => {\n withDb((db) => {\n const userId = resolveUser(opts, db);\n const token = getTokenBySlug(db, opts.token);\n if (!token) {\n console.error(`Token not found: ${opts.token}`);\n process.exit(1);\n }\n\n const card = getCard(db, token.id, userId);\n const prereqs = getPrerequisites(db, token.id);\n const dependents = getDependents(db, token.id);\n\n const status = {\n token,\n card: card ?? null,\n prerequisites: prereqs,\n dependents,\n };\n\n if (opts.json) {\n console.log(JSON.stringify(status, null, 2));\n return;\n }\n\n console.log(`Token: ${token.slug} (${token.id})`);\n console.log(` Concept: ${token.concept}`);\n console.log(` Question: ${token.question || \"(none)\"}`);\n console.log(` Domain: ${token.domain || \"(none)\"}`);\n console.log(` Bloom: ${token.bloom_level}`);\n if (token.source_link) {\n console.log(` Source: ${token.source_link}`);\n }\n console.log();\n\n if (card) {\n console.log(\"Card status:\");\n console.log(` State: ${card.state}`);\n console.log(` Due at: ${card.due_at}`);\n console.log(` Stability: ${card.stability}`);\n console.log(` Difficulty: ${card.difficulty}`);\n console.log(` Reps: ${card.reps}`);\n console.log(` Lapses: ${card.lapses}`);\n console.log(` Blocked: ${card.blocked ? \"Yes\" : \"No\"}`);\n } else {\n console.log(\"No card exists for this user yet.\");\n }\n\n console.log();\n if (prereqs.length > 0) {\n console.log(\"Prerequisites:\");\n for (const p of prereqs) {\n console.log(` - ${p.slug}: ${p.concept} (bloom ${p.bloom_level})`);\n }\n } else {\n console.log(\"No prerequisites.\");\n }\n\n if (dependents.length > 0) {\n console.log(\"\\nDependents:\");\n for (const d of dependents) {\n console.log(` - ${d.slug}: ${d.concept} (bloom ${d.bloom_level})`);\n }\n }\n });\n });\n","/**\n * `zam ui` — one-word launcher for the ZAM Desktop GUI (Tauri Studio).\n *\n * The desktop app is a Tauri shell that re-uses the compiled CLI bridge\n * (dist/cli/index.js), so it needs:\n * - a built CLI (npm run build at the repo root), and\n * - either a previously built native binary, or the Rust toolchain to\n * compile one.\n *\n * Usage:\n * zam ui launch the GUI (built binary if present, else guide)\n * zam ui --dev run in hot-reload dev mode (needs Rust)\n * zam ui --build build the native installer (needs Rust, one-time)\n * zam ui --shortcut create Desktop + Start-menu shortcuts to the GUI\n */\n\nimport { type SpawnSyncOptions, spawn, spawnSync } from \"node:child_process\";\nimport { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { Command } from \"commander\";\nimport { hasCommand } from \"../../kernel/index.js\";\n\nconst C = {\n reset: \"\\x1b[0m\",\n red: \"\\x1b[31m\",\n green: \"\\x1b[32m\",\n yellow: \"\\x1b[33m\",\n cyan: \"\\x1b[36m\",\n dim: \"\\x1b[2m\",\n};\n\n/** Walk up from cwd and from this module to find the repo's `desktop/` dir. */\nfunction findDesktopDir(): string | null {\n const starts = [process.cwd(), dirname(fileURLToPath(import.meta.url))];\n for (const start of starts) {\n let dir = start;\n for (let i = 0; i < 10; i++) {\n if (existsSync(join(dir, \"desktop\", \"src-tauri\", \"tauri.conf.json\"))) {\n return join(dir, \"desktop\");\n }\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n }\n return null;\n}\n\n/** Locate a previously built native binary, if any. */\nfunction findBuiltApp(desktopDir: string): string | null {\n const releaseDir = join(desktopDir, \"src-tauri\", \"target\", \"release\");\n if (process.platform === \"win32\") {\n for (const name of [\"ZAM.exe\", \"zam.exe\", \"zam-desktop.exe\"]) {\n const p = join(releaseDir, name);\n if (existsSync(p)) return p;\n }\n } else if (process.platform === \"darwin\") {\n const app = join(releaseDir, \"bundle\", \"macos\", \"ZAM.app\");\n if (existsSync(app)) return app;\n } else {\n for (const name of [\"zam\", \"ZAM\", \"zam-desktop\"]) {\n const p = join(releaseDir, name);\n if (existsSync(p)) return p;\n }\n }\n return null;\n}\n\n/** npm is npm.cmd on Windows, so child processes need a shell there. */\nfunction runNpm(args: string[], opts: SpawnSyncOptions): number {\n const res = spawnSync(\"npm\", args, {\n stdio: \"inherit\",\n shell: process.platform === \"win32\",\n ...opts,\n });\n return res.status ?? 1;\n}\n\nfunction ensureDesktopDeps(desktopDir: string): boolean {\n if (existsSync(join(desktopDir, \"node_modules\"))) return true;\n console.log(\n `${C.cyan}Installing desktop dependencies (one-time)...${C.reset}`,\n );\n return runNpm([\"install\"], { cwd: desktopDir }) === 0;\n}\n\nfunction requireRust(): boolean {\n if (hasCommand(\"cargo\")) return true;\n console.error(\n `${C.red}✗ The desktop GUI needs the Rust toolchain to compile.${C.reset}`,\n );\n console.error(\" Install it once, then re-run this command:\");\n console.error(\n ` ${C.cyan}winget install Rustlang.Rustup${C.reset} (or https://rustup.rs)`,\n );\n return false;\n}\n\n/**\n * On Windows the default MSVC Rust target needs the Visual Studio C++ linker\n * (link.exe), which rustup does NOT install. Detect it via vswhere so we fail\n * with guidance up front instead of after minutes of compiling.\n */\nfunction hasMsvcBuildTools(): boolean {\n if (process.platform !== \"win32\") return true;\n const pf86 = process.env[\"ProgramFiles(x86)\"] || \"C:\\\\Program Files (x86)\";\n const vswhere = join(\n pf86,\n \"Microsoft Visual Studio\",\n \"Installer\",\n \"vswhere.exe\",\n );\n if (!existsSync(vswhere)) return false;\n const res = spawnSync(\n vswhere,\n [\n \"-latest\",\n \"-products\",\n \"*\",\n \"-requires\",\n \"Microsoft.VisualStudio.Component.VC.Tools.x86.x64\",\n \"-property\",\n \"installationPath\",\n ],\n { encoding: \"utf8\" },\n );\n return (res.stdout ?? \"\").trim().length > 0;\n}\n\nfunction requireMsvcOnWindows(): boolean {\n if (hasMsvcBuildTools()) return true;\n console.error(\n `${C.red}✗ The MSVC C++ linker (link.exe) is missing.${C.reset}`,\n );\n console.error(\n \" Rust on Windows needs the Visual Studio Build Tools with the C++ workload\",\n );\n console.error(\" (rustup does not include it). Install it once (~a few GB),\");\n console.error(\" then open a NEW terminal and retry:\");\n console.error(\n ` ${C.cyan}winget install --id Microsoft.VisualStudio.2022.BuildTools -e --override \"--quiet --wait --add Microsoft.VisualStudio.Workload.VCTools --includeRecommended\"${C.reset}`,\n );\n return false;\n}\n\nfunction warnIfCliMissing(repoRoot: string): void {\n if (!existsSync(join(repoRoot, \"dist\", \"cli\", \"index.js\"))) {\n console.warn(\n `${C.yellow}⚠ CLI build not found (dist/cli/index.js). The GUI bridge needs it — run 'npm run build' at the repo root.${C.reset}`,\n );\n }\n}\n\n/**\n * Record this repo root in ~/.zam/cli_path so the installed GUI can locate the\n * CLI bridge regardless of where it is launched from (Start menu / Program\n * Files have no idea where the repo lives). The Tauri backend reads this file.\n */\nfunction recordCliHome(repoRoot: string): void {\n try {\n const zamDir = join(homedir(), \".zam\");\n if (!existsSync(zamDir)) mkdirSync(zamDir, { recursive: true });\n writeFileSync(join(zamDir, \"cli_path\"), repoRoot, \"utf8\");\n } catch {\n // best-effort: a missing marker just falls back to cwd resolution\n }\n}\n\nfunction launchApp(appPath: string, repoRoot: string): void {\n // Run from the repo root so the Tauri backend resolves dist/cli/index.js.\n console.log(`${C.green}✓ Launching ZAM Desktop...${C.reset}`);\n if (process.platform === \"darwin\" && appPath.endsWith(\".app\")) {\n spawn(\"open\", [appPath], {\n cwd: repoRoot,\n detached: true,\n stdio: \"ignore\",\n }).unref();\n } else {\n spawn(appPath, [], {\n cwd: repoRoot,\n detached: true,\n stdio: \"ignore\",\n windowsHide: true,\n }).unref();\n }\n}\n\nfunction createShortcuts(appPath: string, repoRoot: string): void {\n if (process.platform !== \"win32\") {\n console.error(\n `${C.red}✗ --shortcut is currently implemented for Windows only.${C.reset}`,\n );\n console.error(\n \" On macOS drag ZAM.app to the Dock; on Linux create a .desktop entry.\",\n );\n return;\n }\n // WScript.Shell creates a .lnk on the Desktop and in the Start menu.\n const ps = [\n \"$ws = New-Object -ComObject WScript.Shell\",\n \"foreach ($dir in @([Environment]::GetFolderPath('Desktop'), [Environment]::GetFolderPath('Programs'))) {\",\n \" $lnk = $ws.CreateShortcut((Join-Path $dir 'ZAM.lnk'))\",\n ` $lnk.TargetPath = '${appPath}'`,\n ` $lnk.WorkingDirectory = '${repoRoot}'`,\n ` $lnk.IconLocation = '${appPath},0'`,\n \" $lnk.Description = 'ZAM Active-Recall Studio'\",\n \" $lnk.Save()\",\n \"}\",\n ].join(\"\\n\");\n const res = spawnSync(\n \"powershell\",\n [\"-NoProfile\", \"-ExecutionPolicy\", \"Bypass\", \"-Command\", ps],\n { stdio: \"inherit\" },\n );\n if (res.status === 0) {\n console.log(\n `${C.green}✓ Created 'ZAM' shortcuts on your Desktop and in the Start menu.${C.reset}`,\n );\n } else {\n console.error(`${C.red}✗ Could not create shortcuts.${C.reset}`);\n }\n}\n\nexport const uiCommand = new Command(\"ui\")\n .description(\"Launch the ZAM Desktop GUI (Active-Recall Studio)\")\n .option(\"--dev\", \"Run in hot-reload development mode (needs Rust)\")\n .option(\n \"--build\",\n \"Build the native installer for your OS (needs Rust, one-time)\",\n )\n .option(\"--shortcut\", \"Create Desktop + Start-menu shortcuts to the GUI\")\n .action((opts) => {\n const desktopDir = findDesktopDir();\n if (!desktopDir) {\n console.error(\n `${C.red}✗ Could not find the desktop/ app. Run 'zam ui' from inside the ZAM repository.${C.reset}`,\n );\n process.exit(1);\n }\n const repoRoot = dirname(desktopDir);\n\n // Record where the CLI lives so the installed GUI can always find the\n // bridge, no matter which directory it is launched from.\n recordCliHome(repoRoot);\n\n // --build: compile the native installer.\n if (opts.build) {\n if (!requireRust()) process.exit(1);\n if (!requireMsvcOnWindows()) process.exit(1);\n if (!ensureDesktopDeps(desktopDir)) process.exit(1);\n console.log(\n `${C.cyan}Building the native ZAM installer (this takes a few minutes)...${C.reset}`,\n );\n const code = runNpm([\"run\", \"tauri\", \"build\"], { cwd: desktopDir });\n if (code === 0) {\n const bundle = join(\n desktopDir,\n \"src-tauri\",\n \"target\",\n \"release\",\n \"bundle\",\n );\n console.log(\n `\\n${C.green}✓ Done. Installer is in:${C.reset}\\n ${bundle}`,\n );\n console.log(\n `${C.dim}Run that installer once — it adds ZAM to the Start menu and Desktop automatically.${C.reset}`,\n );\n console.log(\n `${C.dim}Recorded this repo (${repoRoot}) in ~/.zam/cli_path so the installed app finds the CLI.${C.reset}`,\n );\n }\n process.exit(code);\n }\n\n // --dev: hot-reload development mode.\n if (opts.dev) {\n if (!requireRust()) process.exit(1);\n if (!requireMsvcOnWindows()) process.exit(1);\n if (!ensureDesktopDeps(desktopDir)) process.exit(1);\n warnIfCliMissing(repoRoot);\n console.log(\n `${C.cyan}Starting ZAM Desktop in dev mode (Ctrl+C to stop)...${C.reset}`,\n );\n process.exit(runNpm([\"run\", \"tauri\", \"dev\"], { cwd: desktopDir }));\n }\n\n const builtApp = findBuiltApp(desktopDir);\n\n // --shortcut: needs a built binary to point at.\n if (opts.shortcut) {\n if (!builtApp) {\n console.error(\n `${C.red}✗ No built app yet. Build it first:${C.reset} ${C.cyan}zam ui --build${C.reset}`,\n );\n process.exit(1);\n }\n createShortcuts(builtApp, repoRoot);\n return;\n }\n\n // Default: launch the built app, or guide the user to get one.\n if (builtApp) {\n warnIfCliMissing(repoRoot);\n launchApp(builtApp, repoRoot);\n return;\n }\n\n console.log(\n `${C.yellow}The ZAM Desktop GUI hasn't been built yet.${C.reset}\\n`,\n );\n if (hasCommand(\"cargo\")) {\n console.log(\"Pick one:\");\n console.log(\n ` ${C.cyan}zam ui --build${C.reset} Build a native installer (Start-menu + Desktop entry)`,\n );\n console.log(\n ` ${C.cyan}zam ui --dev${C.reset} Just run it now in dev mode`,\n );\n } else {\n console.log(\"To get a clickable Start-menu app, do this once:\");\n console.log(\n ` 1. Install Rust: ${C.cyan}winget install Rustlang.Rustup${C.reset}`,\n );\n console.log(` 2. Build the app: ${C.cyan}zam ui --build${C.reset}`);\n console.log(\n ` 3. Run the installer it prints — ZAM then lives in your Start menu.`,\n );\n console.log(\n `\\n${C.dim}After that, 'zam ui' launches it directly.${C.reset}`,\n );\n }\n });\n","/**\n * `zam whoami` — Manage default user identity.\n */\n\nimport { Command } from \"commander\";\nimport type { Database } from \"libsql\";\nimport {\n deleteSetting,\n getSetting,\n openDatabase,\n setSetting,\n} from \"../../kernel/index.js\";\n\nfunction withDb(fn: (db: Database) => void): void {\n let db: Database | undefined;\n try {\n db = openDatabase();\n fn(db);\n } catch (err) {\n console.error(\"Error:\", (err as Error).message);\n process.exit(1);\n } finally {\n db?.close();\n }\n}\n\nexport const whoamiCommand = new Command(\"whoami\")\n .description(\"Show or set the default user identity\")\n .option(\"--set <id>\", \"Set the default user ID\")\n .option(\"--clear\", \"Remove the default user ID\")\n .option(\"--json\", \"Output as JSON\")\n .action((opts) => {\n withDb((db) => {\n if (opts.set) {\n setSetting(db, \"user.id\", opts.set);\n if (opts.json) {\n console.log(JSON.stringify({ userId: opts.set }));\n } else {\n console.log(`Default user set to: ${opts.set}`);\n }\n return;\n }\n\n if (opts.clear) {\n const deleted = deleteSetting(db, \"user.id\");\n if (opts.json) {\n console.log(JSON.stringify({ userId: null, cleared: deleted }));\n } else if (deleted) {\n console.log(\"Default user cleared.\");\n } else {\n console.log(\"No default user was set.\");\n }\n return;\n }\n\n const userId = getSetting(db, \"user.id\");\n if (opts.json) {\n console.log(JSON.stringify({ userId: userId ?? null }));\n return;\n }\n\n if (userId) {\n console.log(userId);\n } else {\n console.log(\"No default user set. Use: zam whoami --set <id>\");\n }\n });\n });\n","/**\n * `zam workspace` — Workspace management commands.\n *\n * `zam workspace publish` initializes a Git repository inside the local sandbox\n * workspace and pushes it to GitHub, establishing a secure version-controlled backup\n * and change-managed team workflow.\n */\n\nimport { execSync } from \"node:child_process\";\nimport { existsSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { confirm, input } from \"@inquirer/prompts\";\nimport { Command } from \"commander\";\nimport { getSetting, hasCommand, openDatabase } from \"../../kernel/index.js\";\n\n/**\n * Execute a shell command inside a specific directory.\n */\nfunction runGit(cwd: string, args: string): string {\n try {\n return execSync(`git ${args}`, {\n cwd,\n stdio: \"pipe\",\n encoding: \"utf8\",\n }).trim();\n } catch (err) {\n throw new Error(`Git command failed: ${(err as Error).message}`);\n }\n}\n\nexport const workspaceCommand = new Command(\"workspace\").description(\n \"Manage your ZAM learning workspace\",\n);\n\nworkspaceCommand\n .command(\"publish\")\n .description(\"Publish your local workspace sandbox to GitHub\")\n .action(async () => {\n let db: ReturnType<typeof openDatabase> | undefined;\n let workspaceDir = \"\";\n\n try {\n db = openDatabase();\n workspaceDir = getSetting(db, \"personal.workspace_dir\") || \"\";\n db.close();\n } catch {\n // Fallback if DB doesn't exist\n db?.close();\n }\n\n if (!workspaceDir) {\n console.error(\n \"\\x1b[31m✗ No active workspace configured. Please run `zam init` first.\\x1b[0m\",\n );\n process.exit(1);\n }\n\n if (!existsSync(workspaceDir)) {\n console.error(\n `\\x1b[31m✗ Workspace directory does not exist: ${workspaceDir}\\x1b[0m`,\n );\n process.exit(1);\n }\n\n console.log(`\\nActive workspace: \\x1b[36m${workspaceDir}\\x1b[0m`);\n\n // ── Check Git command ────────────────────────────────────────────────────\n if (!hasCommand(\"git\")) {\n console.error(\n \"\\x1b[31m✗ Git command was not found on this system. Please install Git first.\\x1b[0m\",\n );\n process.exit(1);\n }\n\n // ── Setup .gitignore ─────────────────────────────────────────────────────\n const gitignorePath = join(workspaceDir, \".gitignore\");\n if (!existsSync(gitignorePath)) {\n writeFileSync(\n gitignorePath,\n \"node_modules/\\n.agent/\\n.agents/\\n.claude/\\n.gemini/\\n.goose/\\n*.log\\n\",\n \"utf8\",\n );\n }\n\n // ── Initialize Local Git Repo ────────────────────────────────────────────\n const hasGitRepo = existsSync(join(workspaceDir, \".git\"));\n if (!hasGitRepo) {\n console.log(\"Initializing local Git repository...\");\n runGit(workspaceDir, \"init -b main\");\n runGit(workspaceDir, \"add .\");\n runGit(\n workspaceDir,\n 'commit -m \"chore: initial workspace sandbox bootstrap\"',\n );\n console.log(\"\\x1b[32m✓ Local Git repository initialized.\\x1b[0m\");\n } else {\n console.log(\"Git repository is already initialized.\");\n }\n\n // ── GitHub Publishing options ────────────────────────────────────────────\n const repoName = await input({\n message: \"Choose a name for your GitHub repository:\",\n default: \"zam-personal\",\n });\n\n const isPrivate = await confirm({\n message: \"Should the repository be private?\",\n default: true,\n });\n\n const repoVisibility = isPrivate ? \"--private\" : \"--public\";\n\n // ── Method A: Using GitHub CLI (gh) ──────────────────────────────────────\n if (hasCommand(\"gh\")) {\n console.log(\"GitHub CLI detected! Automating repository creation...\");\n const proceedGh = await confirm({\n message:\n \"Would you like ZAM to create the repository using the GitHub CLI?\",\n default: true,\n });\n\n if (proceedGh) {\n try {\n console.log(`Creating GitHub repository ${repoName}...`);\n execSync(\n `gh repo create ${repoName} ${repoVisibility} --source=. --push`,\n {\n cwd: workspaceDir,\n stdio: \"inherit\",\n },\n );\n console.log(\n \"\\n\\x1b[32m✓ Successfully published workspace to GitHub!\\x1b[0m\",\n );\n process.exit(0);\n } catch (err) {\n console.warn(\n `\\x1b[33m⚠ GitHub CLI creation failed: ${(err as Error).message}\\x1b[0m`,\n );\n }\n }\n }\n\n // ── Method B: Manual Git setup instructions ──────────────────────────────\n console.log(\n \"\\n\\x1b[1mPlease create the repository manually on GitHub:\\x1b[0m\",\n );\n console.log(\" 1. Go to https://github.com/new\");\n console.log(` 2. Name it exactly: \\x1b[36m${repoName}\\x1b[0m`);\n console.log(\n ` 3. Choose \\x1b[36m${isPrivate ? \"Private\" : \"Public\"}\\x1b[0m`,\n );\n console.log(\n \" 4. Do NOT initialize it with README, .gitignore, or license\",\n );\n console.log(\" 5. Click 'Create repository'\\n\");\n\n const githubUrl = await input({\n message:\n \"Paste the repository Git URL (e.g. git@github.com:user/repo.git):\",\n });\n\n if (githubUrl) {\n try {\n console.log(\"Linking remote repository and pushing...\");\n // Check if origin already exists\n let hasOrigin = false;\n try {\n runGit(workspaceDir, \"remote get-url origin\");\n hasOrigin = true;\n } catch {}\n\n if (hasOrigin) {\n runGit(workspaceDir, `remote set-url origin ${githubUrl}`);\n } else {\n runGit(workspaceDir, `remote add origin ${githubUrl}`);\n }\n\n runGit(workspaceDir, \"push -u origin main\");\n console.log(\n \"\\x1b[32m✓ Successfully linked and pushed to GitHub!\\x1b[0m\",\n );\n } catch (err) {\n console.error(\n `\\x1b[31m✗ Push failed: ${(err as Error).message}\\x1b[0m`,\n );\n console.log(\n \"You can push manually later using: git push -u origin main\",\n );\n }\n }\n });\n"],"mappings":"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","names":["Command","readdirSync","homedir","join","existsSync","mkdirSync","readFileSync","homedir","dirname","join","join","homedir","existsSync","readFileSync","dirname","mkdirSync","existsSync","readFileSync","writeFileSync","join","existsSync","join","readFileSync","t","input","writeFileSync","input","ulid","ulid","ulid","input","ulid","input","t","existsSync","mkdirSync","readFileSync","homedir","join","join","homedir","join","existsSync","mkdirSync","readFileSync","ulid","interval","dueAt","input","ulid","input","input","existsSync","readFileSync","dirname","join","anchorIndex","anchor","appendFileSync","existsSync","mkdirSync","readFileSync","homedir","join","packageRoot","existsSync","homedir","join","execSync","execSync","existsSync","resolve","resolve","existsSync","BLOOM_VERBS","input","existsSync","resolve","confirm","getReviewTarget","join","homedir","readdirSync","Command","withDb","Command","Command","Command","execSync","existsSync","writeFileSync","join","Command","withDb","join","existsSync","writeFileSync","Command","execSync","existsSync","mkdirSync","resolve","input","Command","resolve","Command","existsSync","tasks","tokens","t","mkdirSync","input","existsSync","mkdirSync","writeFileSync","homedir","join","input","Command","HOME","homedir","mkdirSync","join","existsSync","writeFileSync","Command","input","input","Command","BLOOM_VERBS","input","confirm","input","confirm","input","Command","input","execSync","writeFileSync","basename","join","Command","psSingleQuoted","basename","Command","execSync","join","writeFileSync","Command","Command","input","select","Command","withDb","Command","select","input","existsSync","Command","withDb","Command","existsSync","copyFileSync","existsSync","mkdirSync","writeFileSync","basename","dirname","join","fileURLToPath","Command","fileURLToPath","existsSync","join","mkdirSync","dirname","copyFileSync","basename","writeFileSync","Command","Command","withDb","Command","Command","withDb","Command","Command","withDb","jsonOut","Command","t","spawn","existsSync","mkdirSync","writeFileSync","homedir","dirname","join","fileURLToPath","Command","dirname","fileURLToPath","existsSync","join","homedir","mkdirSync","writeFileSync","spawn","Command","Command","withDb","Command","execSync","existsSync","writeFileSync","join","confirm","input","Command","execSync","Command","existsSync","join","writeFileSync","input","confirm","Command"]}
1
+ {"version":3,"sources":["../../src/cli/index.ts","../../src/cli/commands/agent.ts","../../src/kernel/analytics/stats.ts","../../src/kernel/credentials.ts","../../src/kernel/connectors/azure-devops.ts","../../src/kernel/db/connection.ts","../../src/kernel/db/remote/hrana.ts","../../src/kernel/db/remote/provider.ts","../../src/kernel/db/schema.ts","../../src/kernel/db/sync-adapter.ts","../../src/kernel/db/snapshot.ts","../../src/kernel/goals/engine.ts","../../src/kernel/goals/parser.ts","../../src/kernel/models/agent-skill.ts","../../src/kernel/models/card.ts","../../src/kernel/models/token.ts","../../src/kernel/models/prerequisite.ts","../../src/kernel/models/review.ts","../../src/kernel/models/session.ts","../../src/kernel/models/settings.ts","../../src/kernel/observation/analyzer.ts","../../src/kernel/observation/monitor-io.ts","../../src/kernel/observation/session-synthesis.ts","../../src/kernel/recall/evaluator.ts","../../src/kernel/scheduler/fsrs.ts","../../src/kernel/scheduler/blocker.ts","../../src/kernel/observation/shell-hooks.ts","../../src/kernel/observation/skill-discovery.ts","../../src/kernel/recall/actions.ts","../../src/kernel/recall/prompter.ts","../../src/kernel/recall/reference-resolver.ts","../../src/kernel/scheduler/interleaver.ts","../../src/kernel/scheduler/queue.ts","../../src/kernel/system/hooks.ts","../../src/kernel/system/i18n.ts","../../src/kernel/system/install-config.ts","../../src/kernel/system/installer.ts","../../src/kernel/system/locale.ts","../../src/kernel/system/profiler.ts","../../src/kernel/system/repos.ts","../../src/kernel/system/update-check.ts","../../src/cli/commands/bridge.ts","../../src/cli/llm/client.ts","../../src/cli/commands/resolve-user.ts","../../src/cli/commands/shared/db.ts","../../src/cli/commands/card.ts","../../src/cli/commands/connector.ts","../../src/cli/commands/git-sync.ts","../../src/cli/commands/goal.ts","../../src/cli/commands/init.ts","../../src/cli/commands/learn.ts","../../src/cli/learn-format.ts","../../src/cli/review-actions.ts","../../src/cli/commands/monitor.ts","../../src/cli/commands/profile.ts","../../src/cli/commands/review.ts","../../src/cli/commands/session.ts","../../src/cli/commands/settings.ts","../../src/cli/commands/setup.ts","../../src/cli/commands/skill.ts","../../src/cli/commands/snapshot.ts","../../src/cli/commands/stats.ts","../../src/cli/commands/token.ts","../../src/cli/commands/ui.ts","../../src/cli/commands/update.ts","../../src/cli/commands/whoami.ts","../../src/cli/commands/workspace.ts"],"sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { Command } from \"commander\";\nimport { agentCommand } from \"./commands/agent.js\";\nimport { bridgeCommand } from \"./commands/bridge.js\";\nimport { cardCommand } from \"./commands/card.js\";\nimport { connectorCommand } from \"./commands/connector.js\";\nimport { gitSyncCommand } from \"./commands/git-sync.js\";\nimport { goalCommand } from \"./commands/goal.js\";\nimport { initCommand } from \"./commands/init.js\";\nimport { learnCommand } from \"./commands/learn.js\";\nimport { monitorCommand } from \"./commands/monitor.js\";\nimport { profileCommand } from \"./commands/profile.js\";\nimport { reviewCommand } from \"./commands/review.js\";\nimport { sessionCommand } from \"./commands/session.js\";\nimport { settingsCommand } from \"./commands/settings.js\";\nimport { setupCommand } from \"./commands/setup.js\";\nimport { skillCommand } from \"./commands/skill.js\";\nimport { snapshotCommand } from \"./commands/snapshot.js\";\nimport { statsCommand } from \"./commands/stats.js\";\nimport { tokenCommand } from \"./commands/token.js\";\nimport { uiCommand } from \"./commands/ui.js\";\nimport { updateCommand } from \"./commands/update.js\";\nimport { whoamiCommand } from \"./commands/whoami.js\";\nimport { workspaceCommand } from \"./commands/workspace.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst pkg = JSON.parse(\n readFileSync(join(__dirname, \"..\", \"..\", \"package.json\"), \"utf-8\"),\n) as { version: string };\n\nconst program = new Command();\n\nprogram\n .name(\"zam\")\n .description(\n \"The Symbiotic Learning Kernel: Elevating Human Intelligence through AI Collaboration.\",\n )\n .version(pkg.version);\n\nprogram.addCommand(initCommand);\nprogram.addCommand(setupCommand);\nprogram.addCommand(tokenCommand);\nprogram.addCommand(cardCommand);\nprogram.addCommand(sessionCommand);\nprogram.addCommand(statsCommand);\nprogram.addCommand(reviewCommand);\nprogram.addCommand(learnCommand);\nprogram.addCommand(uiCommand);\nprogram.addCommand(bridgeCommand);\nprogram.addCommand(skillCommand);\nprogram.addCommand(monitorCommand);\nprogram.addCommand(settingsCommand);\nprogram.addCommand(whoamiCommand);\nprogram.addCommand(connectorCommand);\nprogram.addCommand(snapshotCommand);\nprogram.addCommand(profileCommand);\nprogram.addCommand(updateCommand);\nprogram.addCommand(agentCommand);\nprogram.addCommand(goalCommand);\nprogram.addCommand(gitSyncCommand);\nprogram.addCommand(workspaceCommand);\n\nawait program.parseAsync();\n","/**\n * `zam agent` — provision and inspect the AI agent that drives ZAM sessions.\n *\n * Default mode still relies on an external agent CLI; this command installs one\n * for the user (currently opencode — the only candidate native on both Apple\n * Silicon and Windows on ARM with its own GUI) so non-developers don't have to.\n * opencode reads the AGENTS.md that `zam setup` writes, which is how it picks\n * up the ZAM skill. (Increment 12, Phase 6.)\n */\n\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { Command } from \"commander\";\nimport { hasCommand, installOpenCode } from \"../../kernel/index.js\";\n\nconst C = {\n reset: \"\\x1b[0m\",\n bold: \"\\x1b[1m\",\n cyan: \"\\x1b[36m\",\n dim: \"\\x1b[2m\",\n green: \"\\x1b[32m\",\n yellow: \"\\x1b[33m\",\n};\n\nconst SUPPORTED_AGENTS = [\"opencode\"];\n\nfunction agentsMdPresent(cwd = process.cwd()): boolean {\n return existsSync(join(cwd, \"AGENTS.md\"));\n}\n\nfunction printStatus(): void {\n const installed = hasCommand(\"opencode\");\n const wired = agentsMdPresent();\n\n console.log(`${C.bold}ZAM agent${C.reset}`);\n console.log(\n ` opencode: ${\n installed\n ? `${C.green}installed${C.reset}`\n : `${C.yellow}not installed${C.reset} ${C.dim}(zam agent install)${C.reset}`\n }`,\n );\n console.log(\n ` AGENTS.md: ${\n wired\n ? `${C.green}present${C.reset} ${C.dim}(opencode reads this)${C.reset}`\n : `${C.yellow}missing${C.reset} ${C.dim}(run zam setup to wire the ZAM skill)${C.reset}`\n }`,\n );\n}\n\nconst installCmd = new Command(\"install\")\n .description(\"Download and install the default agent (opencode)\")\n .option(\"--agent <name>\", \"Agent to install\", \"opencode\")\n .action((opts: { agent: string }) => {\n if (!SUPPORTED_AGENTS.includes(opts.agent)) {\n console.error(\n `Unsupported agent: ${opts.agent}. Supported: ${SUPPORTED_AGENTS.join(\", \")}.`,\n );\n process.exit(1);\n }\n\n const result = installOpenCode();\n if (!result.success) {\n console.error(`${C.yellow}✗${C.reset} ${result.message}`);\n process.exit(1);\n }\n\n console.log(`${C.green}✓${C.reset} ${result.message}`);\n if (agentsMdPresent()) {\n console.log(\n ` ${C.dim}opencode will read AGENTS.md here and pick up the ZAM skill.${C.reset}`,\n );\n } else {\n console.log(\n ` Run ${C.cyan}zam setup${C.reset} to write AGENTS.md so opencode uses the ZAM skill.`,\n );\n }\n console.log(` Start it with: ${C.cyan}opencode${C.reset}`);\n });\n\nconst statusCmd = new Command(\"status\")\n .description(\"Show whether the agent is installed and wired to ZAM\")\n .action(printStatus);\n\nexport const agentCommand = new Command(\"agent\")\n .description(\"Provision and inspect the agent that drives ZAM sessions\")\n .addCommand(installCmd)\n .addCommand(statusCmd)\n .action(printStatus);\n","/**\n * Learning Analytics\n *\n * Progress statistics, competence tracking, and session summaries.\n * Ported from PoC's `stats` command with additions for FSRS and symbiosis modes.\n */\n\nimport type { Database } from \"../db/types.js\";\n\nexport interface UserStats {\n userId: string;\n totalTokens: number;\n cardsInDeck: number;\n dueToday: number;\n blocked: number;\n mature: number;\n avgStability: number | null;\n totalSessions: number;\n lastSession: string | null;\n}\n\nexport interface DomainCompetence {\n domain: string;\n totalCards: number;\n matureCards: number;\n avgStability: number;\n retentionRate: number;\n suggestedMode: \"shadowing\" | \"copilot\" | \"autonomy\";\n}\n\nasync function q(db: Database, sql: string, ...params: unknown[]) {\n return (await db.prepare(sql).get(...params)) as Record<string, unknown>;\n}\n\nasync function count(\n db: Database,\n sql: string,\n ...params: unknown[]\n): Promise<number> {\n return ((await q(db, sql, ...params)) as { n: number }).n;\n}\n\n/**\n * Get overall learning stats for a user (ported from PoC's `stats` command).\n */\nexport async function getUserStats(\n db: Database,\n userId: string,\n): Promise<UserStats> {\n const avgRow = (await q(\n db,\n \"SELECT AVG(stability) as v FROM cards WHERE user_id = ? AND reps > 0\",\n userId,\n )) as { v: number | null };\n\n const lastSessionRow = (await db\n .prepare(\n \"SELECT started_at FROM sessions WHERE user_id = ? ORDER BY started_at DESC LIMIT 1\",\n )\n .get(userId)) as { started_at: string } | undefined;\n\n return {\n userId,\n totalTokens: await count(db, \"SELECT COUNT(*) as n FROM tokens\"),\n cardsInDeck: await count(\n db,\n \"SELECT COUNT(*) as n FROM cards WHERE user_id = ?\",\n userId,\n ),\n dueToday: await count(\n db,\n \"SELECT COUNT(*) as n FROM cards WHERE user_id = ? AND blocked = 0 AND due_at <= datetime('now')\",\n userId,\n ),\n blocked: await count(\n db,\n \"SELECT COUNT(*) as n FROM cards WHERE user_id = ? AND blocked = 1\",\n userId,\n ),\n mature: await count(\n db,\n \"SELECT COUNT(*) as n FROM cards WHERE user_id = ? AND reps >= 3 AND stability >= 21\",\n userId,\n ),\n avgStability: avgRow.v ? Math.round(avgRow.v * 100) / 100 : null,\n totalSessions: await count(\n db,\n \"SELECT COUNT(*) as n FROM sessions WHERE user_id = ?\",\n userId,\n ),\n lastSession: lastSessionRow?.started_at ?? null,\n };\n}\n\n/**\n * Get competence per domain for a user.\n * Used to suggest symbiosis mode transitions.\n */\nexport async function getDomainCompetence(\n db: Database,\n userId: string,\n): Promise<DomainCompetence[]> {\n const domains = (await db\n .prepare(\n `SELECT DISTINCT t.domain FROM cards c\n JOIN tokens t ON t.id = c.token_id\n WHERE c.user_id = ? AND t.domain != ''`,\n )\n .all(userId)) as { domain: string }[];\n\n const competences: DomainCompetence[] = [];\n for (const d of domains) {\n const total = await count(\n db,\n `SELECT COUNT(*) as n FROM cards c\n JOIN tokens t ON t.id = c.token_id\n WHERE c.user_id = ? AND t.domain = ?`,\n userId,\n d.domain,\n );\n\n const mature = await count(\n db,\n `SELECT COUNT(*) as n FROM cards c\n JOIN tokens t ON t.id = c.token_id\n WHERE c.user_id = ? AND t.domain = ? AND c.reps >= 3 AND c.stability >= 21`,\n userId,\n d.domain,\n );\n\n const avgStab =\n (\n (await q(\n db,\n `SELECT AVG(c.stability) as v FROM cards c\n JOIN tokens t ON t.id = c.token_id\n WHERE c.user_id = ? AND t.domain = ? AND c.reps > 0`,\n userId,\n d.domain,\n )) as { v: number | null }\n ).v ?? 0;\n\n // Estimate retention from review history\n const reviews = (await q(\n db,\n `SELECT COUNT(*) as total,\n SUM(CASE WHEN rating >= 2 THEN 1 ELSE 0 END) as passed\n FROM review_logs\n WHERE user_id = ? AND token_id IN (SELECT id FROM tokens WHERE domain = ?)`,\n userId,\n d.domain,\n )) as { total: number; passed: number };\n\n const retentionRate =\n reviews.total > 0 ? reviews.passed / reviews.total : 0;\n\n let suggestedMode: DomainCompetence[\"suggestedMode\"];\n if (retentionRate > 0.9 && avgStab > 30) {\n suggestedMode = \"autonomy\";\n } else if (retentionRate > 0.7 && avgStab > 7) {\n suggestedMode = \"copilot\";\n } else {\n suggestedMode = \"shadowing\";\n }\n\n competences.push({\n domain: d.domain,\n totalCards: total,\n matureCards: mature,\n avgStability: Math.round(avgStab * 100) / 100,\n retentionRate: Math.round(retentionRate * 1000) / 1000,\n suggestedMode,\n });\n }\n return competences;\n}\n","/**\n * Credential store — reads/writes ~/.zam/credentials.json\n *\n * Connector secrets (Turso URL/token, ADO PAT, etc.) live here instead of\n * inside the SQLite database. This ensures credentials survive db deletion,\n * which is required when migrating from plain SQLite to a libsql embedded\n * replica (Turso cloud sync).\n */\n\nimport {\n chmodSync,\n existsSync,\n mkdirSync,\n readFileSync,\n writeFileSync,\n} from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nconst DEFAULT_CREDENTIALS_PATH = join(homedir(), \".zam\", \"credentials.json\");\n\nexport interface TursoCredentials {\n url: string;\n token: string;\n /**\n * Database access mode: \"native\" uses the legacy libsql driver, \"remote\"\n * uses the HTTP provider (no native bindings; required on Windows ARM64).\n */\n mode?: \"native\" | \"remote\";\n}\n\nexport interface ADOCredentials {\n org_url: string;\n project: string;\n pat: string;\n}\n\nexport interface Credentials {\n turso?: Partial<TursoCredentials>;\n ado?: Partial<ADOCredentials>;\n}\n\n/** Load credentials from ~/.zam/credentials.json. Returns empty object if missing. */\nexport function loadCredentials(path?: string): Credentials {\n const p = path ?? DEFAULT_CREDENTIALS_PATH;\n if (!existsSync(p)) return {};\n try {\n return JSON.parse(readFileSync(p, \"utf-8\")) as Credentials;\n } catch {\n return {};\n }\n}\n\n/** Save credentials to ~/.zam/credentials.json. */\nexport function saveCredentials(creds: Credentials, path?: string): void {\n const p = path ?? DEFAULT_CREDENTIALS_PATH;\n const dir = dirname(p);\n let createdDirectory = false;\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true, mode: 0o700 });\n createdDirectory = true;\n }\n if (\n process.platform !== \"win32\" &&\n (path === undefined || createdDirectory)\n ) {\n chmodSync(dir, 0o700);\n }\n writeFileSync(p, `${JSON.stringify(creds, null, 2)}\\n`, {\n encoding: \"utf-8\",\n mode: 0o600,\n });\n if (process.platform !== \"win32\") {\n chmodSync(p, 0o600);\n }\n}\n\n/** Get complete Turso credentials, or null if incomplete. */\nexport function getTursoCredentials(path?: string): TursoCredentials | null {\n const creds = loadCredentials(path);\n if (creds.turso?.url && creds.turso?.token) {\n return {\n url: creds.turso.url,\n token: creds.turso.token,\n ...(creds.turso.mode ? { mode: creds.turso.mode } : {}),\n };\n }\n return null;\n}\n\n/** Set Turso credentials. */\nexport function setTursoCredentials(\n url: string,\n token: string,\n path?: string,\n mode?: TursoCredentials[\"mode\"],\n): void {\n const creds = loadCredentials(path);\n creds.turso = { url, token, ...(mode ? { mode } : {}) };\n saveCredentials(creds, path);\n}\n\n/** Clear Turso credentials. */\nexport function clearTursoCredentials(path?: string): void {\n const creds = loadCredentials(path);\n delete creds.turso;\n saveCredentials(creds, path);\n}\n\n/** Get complete ADO credentials, or null if incomplete. */\nexport function getADOCredentials(path?: string): ADOCredentials | null {\n const creds = loadCredentials(path);\n if (creds.ado?.org_url && creds.ado?.project && creds.ado?.pat) {\n return {\n org_url: creds.ado.org_url,\n project: creds.ado.project,\n pat: creds.ado.pat,\n };\n }\n return null;\n}\n\n/** Set ADO credentials. */\nexport function setADOCredentials(\n orgUrl: string,\n project: string,\n pat: string,\n path?: string,\n): void {\n const creds = loadCredentials(path);\n creds.ado = { org_url: orgUrl, project, pat };\n saveCredentials(creds, path);\n}\n\n/** Clear ADO credentials. */\nexport function clearADOCredentials(path?: string): void {\n const creds = loadCredentials(path);\n delete creds.ado;\n saveCredentials(creds, path);\n}\n","/**\n * Azure DevOps connector — fetches work items from ADO boards.\n */\n\nimport { getADOCredentials } from \"../credentials.js\";\n\nexport interface ADOConfig {\n orgUrl: string;\n project: string;\n pat: string;\n}\n\nexport interface WorkItem {\n id: number;\n title: string;\n state: string;\n type: string;\n assignedTo: string;\n}\n\n/** Load ADO config from credentials file. Returns null if not configured. */\nexport function loadADOConfig(): ADOConfig | null {\n const creds = getADOCredentials();\n if (!creds) return null;\n return {\n orgUrl: creds.org_url.replace(/\\/+$/, \"\"),\n project: creds.project,\n pat: creds.pat,\n };\n}\n\nfunction authHeader(pat: string): string {\n return `Basic ${Buffer.from(`:${pat}`).toString(\"base64\")}`;\n}\n\n/**\n * Fetch active work items assigned to the current user.\n * Uses WIQL to query, then batch-fetches work item details.\n */\nexport async function fetchActiveWorkItems(\n config: ADOConfig,\n): Promise<WorkItem[]> {\n const { orgUrl, project, pat } = config;\n\n // Step 1: WIQL query for work item IDs\n const wiqlUrl = `${orgUrl}/${project}/_apis/wit/wiql?api-version=7.1`;\n const wiqlBody = {\n query: `SELECT [System.Id] FROM WorkItems WHERE [System.AssignedTo] = @me AND [System.State] NOT IN ('Closed', 'Completed', 'Done', 'Removed') ORDER BY [Microsoft.VSTS.Common.Priority] ASC, [System.ChangedDate] DESC`,\n };\n\n const wiqlRes = await fetch(wiqlUrl, {\n method: \"POST\",\n headers: {\n Authorization: authHeader(pat),\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(wiqlBody),\n });\n\n if (!wiqlRes.ok) {\n const text = await wiqlRes.text();\n throw new Error(`ADO WIQL query failed (${wiqlRes.status}): ${text}`);\n }\n\n const wiqlData = (await wiqlRes.json()) as { workItems: { id: number }[] };\n const ids = wiqlData.workItems.map((wi) => wi.id);\n\n if (ids.length === 0) return [];\n\n // Step 2: Batch fetch work item details (max 200 per request)\n const batchIds = ids.slice(0, 200);\n const fields =\n \"System.Id,System.Title,System.State,System.WorkItemType,System.AssignedTo\";\n const detailUrl = `${orgUrl}/${project}/_apis/wit/workitems?ids=${batchIds.join(\",\")}&fields=${fields}&api-version=7.1`;\n\n const detailRes = await fetch(detailUrl, {\n headers: { Authorization: authHeader(pat) },\n });\n\n if (!detailRes.ok) {\n const text = await detailRes.text();\n throw new Error(\n `ADO work items fetch failed (${detailRes.status}): ${text}`,\n );\n }\n\n const detailData = (await detailRes.json()) as {\n value: Array<{\n id: number;\n fields: {\n \"System.Title\": string;\n \"System.State\": string;\n \"System.WorkItemType\": string;\n \"System.AssignedTo\"?: { displayName: string };\n };\n }>;\n };\n\n return detailData.value.map((wi) => ({\n id: wi.id,\n title: wi.fields[\"System.Title\"],\n state: wi.fields[\"System.State\"],\n type: wi.fields[\"System.WorkItemType\"],\n assignedTo: wi.fields[\"System.AssignedTo\"]?.displayName ?? \"\",\n }));\n}\n","import { existsSync, mkdirSync, readFileSync, rmSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { getTursoCredentials } from \"../credentials.js\";\nimport { openRemoteDatabase } from \"./remote/provider.js\";\nimport { SCHEMA } from \"./schema.js\";\nimport { wrapSyncDatabase } from \"./sync-adapter.js\";\nimport type { Database, SyncDatabase } from \"./types.js\";\n\nconst DEFAULT_DB_DIR = join(homedir(), \".zam\");\nconst DEFAULT_DB_PATH = join(DEFAULT_DB_DIR, \"zam.db\");\nconst require = createRequire(import.meta.url);\n\ntype LibsqlConstructor = new (\n path: string,\n options?: Record<string, unknown>,\n) => SyncDatabase;\n\n/**\n * - `local`: better-sqlite3 file database (default without cloud credentials)\n * - `native`: legacy native libsql driver (remote URLs and embedded replicas)\n * - `remote`: Turso over HTTP, no native bindings (works on Windows ARM64)\n */\nexport type DatabaseProvider = \"local\" | \"native\" | \"remote\";\n\nexport interface ConnectionOptions {\n /** Path to the SQLite database file. Defaults to ~/.zam/zam.db */\n dbPath?: string;\n /** If true, run the schema even when the database already exists. */\n initialize?: boolean;\n /** Turso sync URL for embedded replica mode (e.g. libsql://db-name.turso.io) */\n syncUrl?: string;\n /** Turso auth token for direct remote or embedded replica access */\n authToken?: string;\n /** If false, ignore ~/.zam/credentials.json and force the local/default database. */\n useConfiguredCloud?: boolean;\n /** Explicit provider; overrides ZAM_DB_PROVIDER and the credentials mode. */\n provider?: DatabaseProvider;\n}\n\nfunction isRemoteDatabasePath(dbPath: string): boolean {\n return /^(libsql|https?|wss?):\\/\\//i.test(dbPath);\n}\n\nfunction isDatabaseProvider(value: unknown): value is DatabaseProvider {\n return value === \"local\" || value === \"native\" || value === \"remote\";\n}\n\nfunction openLocalSqlite(dbPath: string): SyncDatabase {\n // Loaded lazily (not as a top-level import) so that remote/HTTP Turso users\n // never trigger the native better-sqlite3 binding. A failure to load that\n // binding inside the packaged desktop app would otherwise crash the whole\n // CLI at startup — before any provider selection or error handling runs.\n const mod = require(\"better-sqlite3\") as\n | (new (\n path: string,\n ) => unknown)\n | { default: new (path: string) => unknown };\n const BetterSqlite3 = (\"default\" in mod ? mod.default : mod) as new (\n path: string,\n ) => unknown;\n return new BetterSqlite3(dbPath) as unknown as SyncDatabase;\n}\n\nfunction loadLibsql(): LibsqlConstructor {\n try {\n const module = require(\"libsql\") as\n | LibsqlConstructor\n | { default: LibsqlConstructor };\n return \"default\" in module ? module.default : module;\n } catch (err) {\n const detail = err instanceof Error ? ` ${err.message}` : \"\";\n throw new Error(\n \"Turso sync requires the optional native libsql backend, which is not \" +\n `available for ${process.platform}/${process.arch}. Switch to the ` +\n \"HTTP provider instead: zam connector setup turso --mode remote \" +\n `(or set ZAM_DB_PROVIDER=remote).${detail}`,\n );\n }\n}\n\n/**\n * Open (or create) the ZAM database.\n * Uses configured Turso credentials for the default database when present.\n * Falls back to local SQLite and WAL mode when no cloud credentials exist.\n * When syncUrl is provided explicitly, enables embedded replica sync with Turso.\n */\nexport async function openDatabase(\n options: ConnectionOptions = {},\n): Promise<Database> {\n const configuredCloud =\n options.useConfiguredCloud !== false && !options.dbPath && !options.syncUrl\n ? getTursoCredentials()\n : null;\n\n let requiresTurso = false;\n try {\n const configPath = join(process.cwd(), \".zam\", \"config.yaml\");\n if (existsSync(configPath)) {\n const configText = readFileSync(configPath, \"utf-8\");\n if (/[\\s\\S]*turso:[\\s\\S]*url:/m.test(configText)) {\n requiresTurso = true;\n }\n }\n } catch (_e) {}\n\n if (\n requiresTurso &&\n !configuredCloud &&\n options.useConfiguredCloud !== false &&\n !options.dbPath &&\n !options.syncUrl\n ) {\n throw new Error(\n \"Turso cloud database is configured in .zam/config.yaml but missing local credentials. Run: zam connector setup turso\",\n );\n }\n const dbPath = configuredCloud?.url ?? options.dbPath ?? DEFAULT_DB_PATH;\n const isRemote = isRemoteDatabasePath(dbPath);\n const isEmbeddedReplica = Boolean(options.syncUrl);\n const provider = resolveProvider(options, configuredCloud?.mode, isRemote);\n const shouldInitialize =\n options.initialize === true ||\n (!isRemote && !isEmbeddedReplica && !existsSync(dbPath));\n\n if (provider === \"remote\") {\n const url = isRemote ? dbPath : options.syncUrl;\n if (!url) {\n throw new Error(\n \"The remote database provider is selected but no Turso URL is \" +\n \"configured. Run: zam connector setup turso\",\n );\n }\n const db = openRemoteDatabase({\n url,\n authToken: configuredCloud?.token ?? options.authToken,\n });\n if (options.initialize) {\n await db.exec(SCHEMA);\n }\n await runMigrations(db);\n return db;\n }\n\n if (shouldInitialize && !isRemote) {\n const dir = dirname(dbPath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n }\n\n // Build constructor options for the optional libsql cloud/sync backend.\n const dbOpts: Record<string, unknown> = {};\n if (options.syncUrl) {\n dbOpts.syncUrl = options.syncUrl;\n\n // When syncUrl is provided, the db must be a libsql embedded replica (not\n // plain SQLite). The presence of a companion .meta (or -info) file proves\n // it was created by libsql.\n //\n // If the db exists WITHOUT metadata, it was created before Turso was\n // configured — delete it so libsql can sync fresh from cloud.\n //\n // If metadata exists WITHOUT the db, libsql throws InvalidLocalState —\n // delete the metadata so it can start fresh.\n const metaPath = `${dbPath}.meta`;\n const infoPath = `${dbPath}-info`;\n\n if (existsSync(dbPath) && !existsSync(metaPath) && !existsSync(infoPath)) {\n for (const suffix of [\"\", \"-wal\", \"-shm\"]) {\n const f = `${dbPath}${suffix}`;\n if (existsSync(f)) rmSync(f, { force: true });\n }\n } else if (\n !existsSync(dbPath) &&\n (existsSync(metaPath) || existsSync(infoPath))\n ) {\n if (existsSync(metaPath)) rmSync(metaPath);\n if (existsSync(infoPath)) rmSync(infoPath);\n }\n }\n const authToken = configuredCloud?.token ?? options.authToken;\n if (authToken) {\n dbOpts.authToken = authToken;\n }\n\n let driver: SyncDatabase;\n if (isRemote || isEmbeddedReplica) {\n try {\n const LibsqlDatabase = loadLibsql();\n try {\n driver = new LibsqlDatabase(dbPath, dbOpts);\n } catch (err) {\n const msg = (err as Error).message;\n if (msg.includes(\"InvalidLocalState\") && options.syncUrl) {\n // Last-ditch recovery: metadata is corrupt or mismatched\n const metaPath = `${dbPath}.meta`;\n const infoPath = `${dbPath}-info`;\n if (existsSync(metaPath)) rmSync(metaPath);\n if (existsSync(infoPath)) rmSync(infoPath);\n driver = new LibsqlDatabase(dbPath, dbOpts);\n } else {\n throw err;\n }\n }\n } catch (nativeErr) {\n // The native libsql driver is unavailable or failed to initialise — a\n // failure mode that can occur inside the packaged desktop app. For a pure\n // remote database we transparently fall back to the HTTP provider, which\n // needs no native bindings. Embedded replicas require the native driver,\n // so those still surface the original error.\n const fallbackUrl = isRemote ? dbPath : options.syncUrl;\n if (isRemote && !isEmbeddedReplica && fallbackUrl) {\n const db = openRemoteDatabase({\n url: fallbackUrl,\n authToken: configuredCloud?.token ?? options.authToken,\n });\n if (options.initialize) {\n await db.exec(SCHEMA);\n }\n await runMigrations(db);\n return db;\n }\n throw nativeErr;\n }\n } else {\n driver = openLocalSqlite(dbPath);\n }\n\n // Enable WAL mode and foreign keys for local SQLite.\n // Remote Turso databases and embedded replicas manage their own journaling.\n if (!isRemote && !isEmbeddedReplica) {\n driver.pragma(\"journal_mode = WAL\");\n }\n driver.pragma(\"foreign_keys = ON\");\n if (!isRemote) {\n driver.pragma(\"busy_timeout = 5000\");\n }\n\n const db = wrapSyncDatabase(driver);\n\n // For embedded replicas: sync from cloud FIRST so the local file has the\n // primary's schema before we try to run migrations or create tables.\n if (isEmbeddedReplica) {\n await db.sync?.();\n }\n\n if (shouldInitialize) {\n await db.exec(SCHEMA);\n }\n\n await runMigrations(db);\n\n return db;\n}\n\nfunction resolveProvider(\n options: ConnectionOptions,\n credentialsMode: string | undefined,\n isRemote: boolean,\n): DatabaseProvider {\n if (options.provider) return options.provider;\n const env = process.env.ZAM_DB_PROVIDER;\n if (isDatabaseProvider(env)) return env;\n if (isDatabaseProvider(credentialsMode) && (isRemote || options.syncUrl)) {\n return credentialsMode;\n }\n // Legacy default: cloud URLs and embedded replicas use the native driver.\n if (isRemote || options.syncUrl) return \"native\";\n return \"local\";\n}\n\n/**\n * Open the database with Turso cloud credentials auto-detected.\n * Credentials live in ~/.zam/credentials.json (NOT in the db), so a fresh\n * machine only has to collect missing secrets instead of bootstrapping local\n * state first.\n */\nexport async function openDatabaseWithSync(\n options: Omit<ConnectionOptions, \"syncUrl\" | \"authToken\"> = {},\n): Promise<Database> {\n return openDatabase(options);\n}\n\n/** Get the default database path */\nexport function getDefaultDbPath(): string {\n return DEFAULT_DB_PATH;\n}\n\n/**\n * Run incremental schema migrations on every open.\n * Each migration is idempotent — safe to run repeatedly.\n */\nasync function runMigrations(db: Database): Promise<void> {\n // M001: add execution_context to sessions\n const sessionCols = (await db.pragma(\"table_info(sessions)\")) as Array<{\n name: string;\n }>;\n if (\n sessionCols.length > 0 &&\n !sessionCols.some((c) => c.name === \"execution_context\")\n ) {\n await db.exec(\n `ALTER TABLE sessions ADD COLUMN execution_context TEXT NOT NULL DEFAULT 'shell'`,\n );\n }\n\n // M002: add deprecated_at to tokens\n const tokenCols = (await db.pragma(\"table_info(tokens)\")) as Array<{\n name: string;\n }>;\n if (\n tokenCols.length > 0 &&\n !tokenCols.some((c) => c.name === \"deprecated_at\")\n ) {\n await db.exec(`ALTER TABLE tokens ADD COLUMN deprecated_at TEXT`);\n }\n\n // M004: add source_link to tokens\n if (\n tokenCols.length > 0 &&\n !tokenCols.some((c) => c.name === \"source_link\")\n ) {\n await db.exec(`ALTER TABLE tokens ADD COLUMN source_link TEXT`);\n }\n\n // M005: add question to tokens\n if (tokenCols.length > 0 && !tokenCols.some((c) => c.name === \"question\")) {\n await db.exec(`ALTER TABLE tokens ADD COLUMN question TEXT`);\n }\n\n // M003: create agent_skills table (idempotent via IF NOT EXISTS in SCHEMA,\n // but also needed for databases that skipped the init path)\n await db.exec(`\n CREATE TABLE IF NOT EXISTS agent_skills (\n id TEXT PRIMARY KEY,\n slug TEXT NOT NULL UNIQUE,\n description TEXT NOT NULL,\n steps TEXT NOT NULL DEFAULT '[]',\n token_slugs TEXT NOT NULL DEFAULT '[]',\n source TEXT NOT NULL DEFAULT 'learned',\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n )\n `);\n\n // M006: persist confirmed monitor-derived ratings for audit and idempotence.\n await db.exec(`\n CREATE TABLE IF NOT EXISTS session_syntheses (\n session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,\n token_id TEXT NOT NULL REFERENCES tokens(id) ON DELETE CASCADE,\n card_id TEXT NOT NULL REFERENCES cards(id) ON DELETE CASCADE,\n inferred_rating INTEGER NOT NULL CHECK (inferred_rating BETWEEN 1 AND 4),\n confirmed_rating INTEGER NOT NULL CHECK (confirmed_rating BETWEEN 1 AND 4),\n confidence TEXT NOT NULL CHECK (confidence IN ('medium', 'high')),\n evidence TEXT NOT NULL DEFAULT '{}',\n review_log_id TEXT NOT NULL REFERENCES review_logs(id) ON DELETE CASCADE,\n session_step_id TEXT NOT NULL REFERENCES session_steps(id) ON DELETE CASCADE,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n PRIMARY KEY (session_id, token_id)\n )\n `);\n}\n","/**\n * Minimal Hrana v3 over HTTP transport for Turso/libsql servers.\n *\n * Implements exactly the subset ZAM needs — execute, sequence, close, and\n * baton-scoped streams for transactions — over plain `fetch`, so it runs on\n * every architecture Node.js supports (including Windows ARM64, which has no\n * native libsql binding).\n *\n * Protocol reference: https://github.com/tursodatabase/libsql/blob/main/docs/HRANA_3_SPEC.md\n */\n\nexport interface HranaTransportOptions {\n /** Database URL (libsql://, https:// or http://). */\n url: string;\n /** Turso auth token; omitted for unauthenticated local servers. */\n authToken?: string;\n /** Per-request timeout in milliseconds. */\n timeoutMs?: number;\n /**\n * Total attempts for requests that failed at the transport level before a\n * response was received. Stateful stream requests (open batons) are never\n * retried.\n */\n maxAttempts?: number;\n}\n\nexport type HranaValue =\n | { type: \"null\" }\n | { type: \"integer\"; value: string }\n | { type: \"float\"; value: number }\n | { type: \"text\"; value: string }\n | { type: \"blob\"; base64: string };\n\nexport interface HranaStmt {\n sql: string;\n args?: HranaValue[];\n want_rows: boolean;\n}\n\nexport type HranaRequest =\n | { type: \"execute\"; stmt: HranaStmt }\n | { type: \"sequence\"; sql: string }\n | { type: \"close\" };\n\nexport interface HranaStmtResult {\n cols: Array<{ name: string | null }>;\n rows: HranaValue[][];\n affected_row_count: number;\n last_insert_rowid: string | null;\n}\n\ninterface HranaPipelineResponse {\n baton: string | null;\n base_url: string | null;\n results: Array<\n | { type: \"ok\"; response: { type: string; result?: HranaStmtResult } }\n | { type: \"error\"; error: { message: string; code?: string | null } }\n >;\n}\n\nconst DEFAULT_TIMEOUT_MS = 15_000;\nconst DEFAULT_MAX_ATTEMPTS = 2;\n\n/** Convert libsql:// and ws(s):// URLs to their HTTP equivalents. */\nexport function toHttpUrl(url: string): string {\n return url\n .replace(/^libsql:\\/\\//i, \"https://\")\n .replace(/^wss:\\/\\//i, \"https://\")\n .replace(/^ws:\\/\\//i, \"http://\")\n .replace(/\\/+$/, \"\");\n}\n\nexport function encodeValue(param: unknown): HranaValue {\n if (param === null) return { type: \"null\" };\n if (typeof param === \"string\") return { type: \"text\", value: param };\n if (typeof param === \"bigint\") {\n return { type: \"integer\", value: param.toString() };\n }\n if (typeof param === \"number\") {\n if (Number.isSafeInteger(param)) {\n return { type: \"integer\", value: param.toString() };\n }\n return { type: \"float\", value: param };\n }\n if (param instanceof Uint8Array) {\n return { type: \"blob\", base64: Buffer.from(param).toString(\"base64\") };\n }\n throw new TypeError(\n `Cannot bind a value of type ${typeof param} to a SQL parameter`,\n );\n}\n\nexport function decodeValue(value: HranaValue): unknown {\n switch (value.type) {\n case \"null\":\n return null;\n case \"integer\":\n return Number(value.value);\n case \"float\":\n return value.value;\n case \"text\":\n return value.value;\n case \"blob\":\n return new Uint8Array(Buffer.from(value.base64, \"base64\"));\n }\n}\n\nexport function rowsToObjects(\n result: HranaStmtResult,\n): Record<string, unknown>[] {\n return result.rows.map((row) => {\n const obj: Record<string, unknown> = {};\n row.forEach((value, i) => {\n obj[result.cols[i]?.name ?? `col${i}`] = decodeValue(value);\n });\n return obj;\n });\n}\n\n/**\n * Only failures that provably happened before the server could have seen the\n * request are retried; anything else (timeouts, resets mid-response) might\n * have executed the statement already, and retrying could duplicate a write.\n */\nfunction isRetryableTransportError(err: unknown): boolean {\n if (!(err instanceof Error) || err.name === \"HranaResponseError\") {\n return false;\n }\n const code = (err.cause as { code?: string } | undefined)?.code;\n return (\n code === \"ECONNREFUSED\" || code === \"ENOTFOUND\" || code === \"EAI_AGAIN\"\n );\n}\n\nclass HranaResponseError extends Error {\n override name = \"HranaResponseError\";\n}\n\n/**\n * A Hrana stream. Stateless requests use a fresh stream per call (the\n * pipeline ends with `close`); transactions keep the stream open via the\n * baton returned by the server.\n */\nexport class HranaTransport {\n private readonly pipelineUrl: string;\n private readonly authToken?: string;\n private readonly timeoutMs: number;\n private readonly maxAttempts: number;\n\n constructor(options: HranaTransportOptions) {\n this.pipelineUrl = `${toHttpUrl(options.url)}/v3/pipeline`;\n this.authToken = options.authToken;\n this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n this.maxAttempts = options.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;\n }\n\n /**\n * POST one pipeline of requests. Returns the server results plus the baton\n * for continuing an open stream. Retries transport-level failures only for\n * stateless pipelines (no baton involved on either side).\n */\n async pipeline(\n requests: HranaRequest[],\n baton?: string | null,\n baseUrl?: string | null,\n ): Promise<HranaPipelineResponse> {\n const url = baseUrl\n ? `${toHttpUrl(baseUrl)}/v3/pipeline`\n : this.pipelineUrl;\n const keepsState =\n baton != null || !requests.some((r) => r.type === \"close\");\n const attempts = keepsState ? 1 : this.maxAttempts;\n\n let lastError: unknown;\n for (let attempt = 1; attempt <= attempts; attempt++) {\n try {\n return await this.post(url, { baton: baton ?? null, requests });\n } catch (err) {\n lastError = err;\n if (!isRetryableTransportError(err) || attempt === attempts) {\n throw this.offline(err);\n }\n }\n }\n throw this.offline(lastError);\n }\n\n private async post(\n url: string,\n body: unknown,\n ): Promise<HranaPipelineResponse> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeoutMs);\n let response: Response;\n try {\n response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n ...(this.authToken\n ? { authorization: `Bearer ${this.authToken}` }\n : {}),\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n } finally {\n clearTimeout(timer);\n }\n\n if (response.status === 401 || response.status === 403) {\n throw new HranaResponseError(\n `Turso rejected the configured credentials (HTTP ${response.status}). ` +\n \"Refresh the token with: zam connector setup turso\",\n );\n }\n if (!response.ok) {\n const detail = await response.text().catch(() => \"\");\n throw new HranaResponseError(\n `Turso request failed with HTTP ${response.status}${detail ? `: ${detail.slice(0, 200)}` : \"\"}`,\n );\n }\n return (await response.json()) as HranaPipelineResponse;\n }\n\n private offline(err: unknown): Error {\n if (err instanceof HranaResponseError) return err;\n const cause =\n err instanceof Error\n ? ((err.cause as Error | undefined)?.message ?? err.message)\n : String(err);\n return new HranaResponseError(\n `Cannot reach the Turso database at ${this.pipelineUrl}: ${cause}. ` +\n \"Check your network connection, or switch to the local provider \" +\n \"(ZAM_DB_PROVIDER=local).\",\n );\n }\n}\n\n/** Unwrap a single pipeline result entry, throwing on stream-level errors. */\nexport function unwrapResult(\n response: HranaPipelineResponse,\n index: number,\n): HranaStmtResult | undefined {\n const entry = response.results[index];\n if (!entry) {\n throw new HranaResponseError(`Turso response is missing result #${index}`);\n }\n if (entry.type === \"error\") {\n throw new Error(entry.error.message);\n }\n return entry.response.result;\n}\n","/**\n * RemoteTursoProvider — implements the async `Database` contract directly\n * against a Turso/libsql server over HTTP (Hrana v3).\n *\n * No native bindings and no extra runtime dependencies, so this provider is\n * the cloud path for architectures without a native libsql artifact (for\n * example Windows ARM64). Under ZAM's online-first assumption it is suitable\n * for interactive sessions: the per-review LLM call dominates latency.\n */\n\nimport type { Database, RunResult, Statement } from \"../types.js\";\nimport {\n encodeValue,\n type HranaRequest,\n type HranaStmtResult,\n HranaTransport,\n type HranaTransportOptions,\n rowsToObjects,\n unwrapResult,\n} from \"./hrana.js\";\n\nconst TABLE_INFO_PRAGMA = /^\\s*table_info\\s*\\(\\s*['\"]?(\\w+)['\"]?\\s*\\)\\s*$/i;\n\nfunction toRunResult(result: HranaStmtResult | undefined): RunResult {\n return {\n changes: result?.affected_row_count ?? 0,\n lastInsertRowid:\n result?.last_insert_rowid != null ? Number(result.last_insert_rowid) : 0,\n };\n}\n\n/** A pipeline executor; stateless by default, baton-scoped in transactions. */\ntype RunPipeline = (\n requests: HranaRequest[],\n) => Promise<{ results: Array<HranaStmtResult | undefined> }>;\n\nfunction makeStatement(sql: string, run: RunPipeline): Statement {\n const execute = async (params: unknown[], wantRows: boolean) => {\n const { results } = await run([\n {\n type: \"execute\",\n stmt: { sql, args: params.map(encodeValue), want_rows: wantRows },\n },\n ]);\n return results[0];\n };\n\n return {\n async run(...params: unknown[]) {\n return toRunResult(await execute(params, false));\n },\n async get(...params: unknown[]) {\n const result = await execute(params, true);\n return result ? rowsToObjects(result)[0] : undefined;\n },\n async all(...params: unknown[]) {\n const result = await execute(params, true);\n return result ? rowsToObjects(result) : [];\n },\n };\n}\n\nfunction makeDatabase(run: RunPipeline, transport: HranaTransport): Database {\n let txTail: Promise<unknown> = Promise.resolve();\n\n const db: Database = {\n prepare(sql: string) {\n return makeStatement(sql, run);\n },\n\n async exec(sql: string) {\n await run([{ type: \"sequence\", sql }]);\n },\n\n async pragma(source: string) {\n const tableInfo = TABLE_INFO_PRAGMA.exec(source);\n const sql = tableInfo\n ? `SELECT * FROM pragma_table_info('${tableInfo[1]}')`\n : `PRAGMA ${source}`;\n return db.prepare(sql).all();\n },\n\n transaction<T>(fn: (db: Database) => Promise<T>): Promise<T> {\n const next = txTail.then(async () => {\n const stream = openStream(transport);\n try {\n await stream.run([\n {\n type: \"execute\",\n stmt: { sql: \"BEGIN IMMEDIATE\", want_rows: false },\n },\n ]);\n const result = await fn(makeDatabase(stream.run, transport));\n await stream.run(\n [{ type: \"execute\", stmt: { sql: \"COMMIT\", want_rows: false } }],\n true,\n );\n return result;\n } catch (err) {\n await stream\n .run(\n [\n {\n type: \"execute\",\n stmt: { sql: \"ROLLBACK\", want_rows: false },\n },\n ],\n true,\n )\n .catch(() => {});\n throw err;\n }\n });\n txTail = next.catch(() => {});\n return next;\n },\n\n async close() {\n // Stateless transport: nothing to release.\n },\n };\n\n return db;\n}\n\ninterface Stream {\n run(requests: HranaRequest[], close?: boolean): ReturnType<RunPipeline>;\n}\n\n/** Open a baton-scoped stream that threads server state between pipelines. */\nfunction openStream(transport: HranaTransport): Stream {\n let baton: string | null = null;\n let baseUrl: string | null = null;\n\n return {\n async run(requests: HranaRequest[], close = false) {\n const sent: HranaRequest[] = close\n ? [...requests, { type: \"close\" }]\n : requests;\n const response = await transport.pipeline(sent, baton, baseUrl);\n baton = response.baton;\n baseUrl = response.base_url ?? baseUrl;\n return {\n results: requests.map((_, i) => unwrapResult(response, i)),\n };\n },\n };\n}\n\nexport type RemoteDatabaseOptions = HranaTransportOptions;\n\n/** Open a remote Turso database over HTTP. */\nexport function openRemoteDatabase(options: RemoteDatabaseOptions): Database {\n const transport = new HranaTransport(options);\n\n const statelessRun: RunPipeline = async (requests) => {\n const response = await transport.pipeline([...requests, { type: \"close\" }]);\n return { results: requests.map((_, i) => unwrapResult(response, i)) };\n };\n\n return makeDatabase(statelessRun, transport);\n}\n","/**\n * ZAM Learning Kernel — SQLite Schema\n *\n * Evolves the PoC's schema with:\n * - FSRS scheduling fields (replaces SM-2's ef/interval_days)\n * - Bloom taxonomy levels on tokens\n * - Symbiosis modes (shadowing/copilot/autonomy)\n * - ULID-based IDs\n * - Immutable review log\n */\n\nexport const SCHEMA = `\n-- PRAGMAs (WAL, foreign_keys) are set programmatically in connection.ts,\n-- not here, because libsql embedded replicas manage their own WAL.\n\n-- Knowledge tokens: atomic concepts/facts with Bloom levels\nCREATE TABLE IF NOT EXISTS tokens (\n id TEXT PRIMARY KEY,\n slug TEXT UNIQUE NOT NULL,\n concept TEXT NOT NULL,\n domain TEXT NOT NULL DEFAULT '',\n bloom_level INTEGER NOT NULL DEFAULT 1 CHECK (bloom_level BETWEEN 1 AND 5),\n context TEXT NOT NULL DEFAULT '',\n symbiosis_mode TEXT CHECK (symbiosis_mode IN ('shadowing', 'copilot', 'autonomy')),\n source_link TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now')),\n deprecated_at TEXT,\n question TEXT\n);\n\n-- Prerequisite dependency graph: \"to learn A, first know B\"\nCREATE TABLE IF NOT EXISTS prerequisites (\n token_id TEXT NOT NULL REFERENCES tokens(id) ON DELETE CASCADE,\n requires_id TEXT NOT NULL REFERENCES tokens(id) ON DELETE CASCADE,\n PRIMARY KEY (token_id, requires_id)\n);\n\n-- Per-user scheduling state for each token (FSRS fields)\nCREATE TABLE IF NOT EXISTS cards (\n id TEXT PRIMARY KEY,\n token_id TEXT NOT NULL REFERENCES tokens(id) ON DELETE CASCADE,\n user_id TEXT NOT NULL,\n stability REAL NOT NULL DEFAULT 0.0,\n difficulty REAL NOT NULL DEFAULT 0.5,\n elapsed_days REAL NOT NULL DEFAULT 0.0,\n scheduled_days REAL NOT NULL DEFAULT 0.0,\n reps INTEGER NOT NULL DEFAULT 0,\n lapses INTEGER NOT NULL DEFAULT 0,\n state TEXT NOT NULL DEFAULT 'new' CHECK (state IN ('new', 'learning', 'review', 'relearning')),\n due_at TEXT NOT NULL DEFAULT (datetime('now')),\n last_review_at TEXT,\n blocked INTEGER NOT NULL DEFAULT 0,\n UNIQUE(token_id, user_id)\n);\n\n-- Immutable review log: every rating event\nCREATE TABLE IF NOT EXISTS review_logs (\n id TEXT PRIMARY KEY,\n card_id TEXT NOT NULL REFERENCES cards(id) ON DELETE CASCADE,\n token_id TEXT NOT NULL REFERENCES tokens(id) ON DELETE CASCADE,\n user_id TEXT NOT NULL,\n rating INTEGER NOT NULL CHECK (rating BETWEEN 1 AND 4),\n response_time_ms INTEGER,\n reviewed_at TEXT NOT NULL DEFAULT (datetime('now')),\n scheduled_at TEXT NOT NULL,\n session_id TEXT REFERENCES sessions(id)\n);\n\n-- Work+learning sessions\nCREATE TABLE IF NOT EXISTS sessions (\n id TEXT PRIMARY KEY,\n user_id TEXT NOT NULL,\n task TEXT NOT NULL,\n started_at TEXT NOT NULL DEFAULT (datetime('now')),\n completed_at TEXT\n);\n\n-- Steps within a session: who did what\nCREATE TABLE IF NOT EXISTS session_steps (\n id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,\n token_id TEXT NOT NULL REFERENCES tokens(id) ON DELETE CASCADE,\n done_by TEXT NOT NULL CHECK (done_by IN ('user', 'agent')),\n rating INTEGER CHECK (rating BETWEEN 1 AND 4),\n notes TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Confirmed ratings synthesized from monitor evidence.\n-- The composite primary key makes repeated synthesis idempotent per token.\nCREATE TABLE IF NOT EXISTS session_syntheses (\n session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,\n token_id TEXT NOT NULL REFERENCES tokens(id) ON DELETE CASCADE,\n card_id TEXT NOT NULL REFERENCES cards(id) ON DELETE CASCADE,\n inferred_rating INTEGER NOT NULL CHECK (inferred_rating BETWEEN 1 AND 4),\n confirmed_rating INTEGER NOT NULL CHECK (confirmed_rating BETWEEN 1 AND 4),\n confidence TEXT NOT NULL CHECK (confidence IN ('medium', 'high')),\n evidence TEXT NOT NULL DEFAULT '{}',\n review_log_id TEXT NOT NULL REFERENCES review_logs(id) ON DELETE CASCADE,\n session_step_id TEXT NOT NULL REFERENCES session_steps(id) ON DELETE CASCADE,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n PRIMARY KEY (session_id, token_id)\n);\n\n-- User configuration\nCREATE TABLE IF NOT EXISTS user_config (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL,\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Agent skills: task recipes the agent learns from user guidance\nCREATE TABLE IF NOT EXISTS agent_skills (\n id TEXT PRIMARY KEY,\n slug TEXT NOT NULL UNIQUE,\n description TEXT NOT NULL,\n steps TEXT NOT NULL DEFAULT '[]', -- JSON array of step strings\n token_slugs TEXT NOT NULL DEFAULT '[]', -- JSON array of related token slugs\n source TEXT NOT NULL DEFAULT 'learned'\n CHECK(source IN ('learned', 'builtin')),\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Performance indexes\nCREATE INDEX IF NOT EXISTS idx_tokens_domain ON tokens(domain);\nCREATE INDEX IF NOT EXISTS idx_tokens_slug ON tokens(slug);\nCREATE INDEX IF NOT EXISTS idx_prereqs_token ON prerequisites(token_id);\nCREATE INDEX IF NOT EXISTS idx_prereqs_requires ON prerequisites(requires_id);\nCREATE INDEX IF NOT EXISTS idx_cards_user_due ON cards(user_id, blocked, due_at);\nCREATE INDEX IF NOT EXISTS idx_cards_token_user ON cards(token_id, user_id);\nCREATE INDEX IF NOT EXISTS idx_review_logs_card ON review_logs(card_id);\nCREATE INDEX IF NOT EXISTS idx_review_logs_user ON review_logs(user_id, reviewed_at);\nCREATE INDEX IF NOT EXISTS idx_session_steps_session ON session_steps(session_id);\n`;\n","/**\n * Adapter that lifts a synchronous SQLite driver (better-sqlite3 or the\n * optional libsql embedded replica) into the async `Database` contract.\n *\n * Statements execute synchronously under the hood, so per-statement atomicity\n * is unchanged. Transactions are serialized through a promise queue because\n * an async callback can yield between statements, and two interleaved\n * BEGIN IMMEDIATE blocks on one connection would otherwise corrupt each\n * other's boundaries.\n */\n\nimport type { Database, SyncDatabase } from \"./types.js\";\n\nexport function wrapSyncDatabase(driver: SyncDatabase): Database {\n let txTail: Promise<unknown> = Promise.resolve();\n\n const db: Database = {\n prepare(sql: string) {\n return {\n async run(...params: unknown[]) {\n return driver.prepare(sql).run(...params);\n },\n async get(...params: unknown[]) {\n return driver.prepare(sql).get(...params);\n },\n async all(...params: unknown[]) {\n return driver.prepare(sql).all(...params);\n },\n };\n },\n\n async exec(sql: string) {\n driver.exec(sql);\n },\n\n async pragma(source: string) {\n return driver.pragma(source);\n },\n\n transaction<T>(fn: (db: Database) => Promise<T>): Promise<T> {\n const run = txTail.then(async () => {\n driver.exec(\"BEGIN IMMEDIATE\");\n try {\n const result = await fn(db);\n driver.exec(\"COMMIT\");\n return result;\n } catch (err) {\n driver.exec(\"ROLLBACK\");\n throw err;\n }\n });\n txTail = run.catch(() => {});\n return run;\n },\n\n ...(driver.sync\n ? {\n async sync() {\n driver.sync?.();\n },\n }\n : {}),\n\n async close() {\n driver.close();\n },\n };\n\n return db;\n}\n","/**\n * Portable database snapshots — Increment 12, Phase 4.\n *\n * A snapshot is portable SQL text: a one-line JSON manifest comment followed by\n * `INSERT` statements for every data row. It deliberately does NOT copy the\n * live WAL database file, so a user can move their learning history between\n * machines through a file-sync folder (Google Drive, OneDrive, iCloud, …)\n * without risking the corruption that comes from syncing an open SQLite/WAL\n * file directly.\n *\n * The schema is NOT embedded. Importing into a freshly initialized database —\n * which always runs the current SCHEMA + migrations on open — keeps snapshots\n * forward compatible across schema changes. Columns are written explicitly so a\n * later-added column never breaks an older snapshot.\n */\n\nimport { createHash } from \"node:crypto\";\nimport type { Database } from \"./types.js\";\n\nexport const SNAPSHOT_FORMAT = \"zam-snapshot\";\nexport const SNAPSHOT_VERSION = 1;\nconst MANIFEST_PREFIX = \"-- zam-snapshot: \";\n\n/**\n * Data tables in foreign-key-safe insertion order (parents before children).\n * Deletes for a `force` restore walk this list in reverse.\n */\nexport const SNAPSHOT_TABLES = [\n \"tokens\",\n \"sessions\",\n \"cards\",\n \"prerequisites\",\n \"session_steps\",\n \"review_logs\",\n \"session_syntheses\",\n \"user_config\",\n \"agent_skills\",\n] as const;\n\nexport interface SnapshotManifest {\n format: string;\n version: number;\n createdAt: string;\n /** Row count per table at export time. */\n tables: Record<string, number>;\n /** SHA-256 of the snapshot body (everything after the manifest line). */\n checksum: string;\n}\n\nexport interface ImportResult {\n /** Row count per table after the restore. */\n tables: Record<string, number>;\n total: number;\n}\n\n/** Render one SQL literal for a value read back from the database. */\nfunction quoteValue(value: unknown): string {\n if (value === null || value === undefined) return \"NULL\";\n if (typeof value === \"number\") {\n return Number.isFinite(value) ? String(value) : \"NULL\";\n }\n if (typeof value === \"bigint\") return value.toString();\n if (typeof value === \"string\") return `'${value.replace(/'/g, \"''\")}'`;\n if (value instanceof Uint8Array) {\n let hex = \"\";\n for (const byte of value) hex += byte.toString(16).padStart(2, \"0\");\n return `X'${hex}'`;\n }\n throw new Error(`Cannot serialize value of type ${typeof value} to SQL`);\n}\n\n/** Column names for a table, in definition order, adapting to migrations. */\nasync function getColumns(db: Database, table: string): Promise<string[]> {\n const cols = (await db.pragma(`table_info(${table})`)) as Array<{\n name: string;\n }>;\n return cols.map((c) => c.name);\n}\n\nasync function countRows(db: Database, table: string): Promise<number> {\n const row = (await db\n .prepare(`SELECT COUNT(*) AS n FROM ${table}`)\n .get()) as { n: number };\n return Number(row.n);\n}\n\n/**\n * Serialize the active database to a portable SQL-text snapshot.\n */\nexport async function exportSnapshot(\n db: Database,\n options: { createdAt?: string } = {},\n): Promise<string> {\n const createdAt = options.createdAt ?? new Date().toISOString();\n const tables: Record<string, number> = {};\n const sections: string[] = [];\n\n for (const table of SNAPSHOT_TABLES) {\n const columns = await getColumns(db, table);\n if (columns.length === 0) {\n // Table absent (older/partial database): record zero and skip.\n tables[table] = 0;\n continue;\n }\n\n const colList = columns.join(\", \");\n const rows = (await db\n .prepare(`SELECT ${colList} FROM ${table}`)\n .all()) as Array<Record<string, unknown>>;\n\n tables[table] = rows.length;\n if (rows.length === 0) continue;\n\n const lines = [`-- ${table} (${rows.length})`];\n for (const row of rows) {\n const values = columns.map((c) => quoteValue(row[c])).join(\", \");\n lines.push(`INSERT INTO ${table} (${colList}) VALUES (${values});`);\n }\n sections.push(lines.join(\"\\n\"));\n }\n\n const body = sections.length > 0 ? `${sections.join(\"\\n\\n\")}\\n` : \"\";\n const checksum = createHash(\"sha256\").update(body).digest(\"hex\");\n const manifest: SnapshotManifest = {\n format: SNAPSHOT_FORMAT,\n version: SNAPSHOT_VERSION,\n createdAt,\n tables,\n checksum,\n };\n\n return `${MANIFEST_PREFIX}${JSON.stringify(manifest)}\\n${body}`;\n}\n\n/** Split a snapshot into its manifest and body; validates the header only. */\nexport function parseSnapshot(snapshot: string): {\n manifest: SnapshotManifest;\n body: string;\n} {\n const newline = snapshot.indexOf(\"\\n\");\n const header = (\n newline === -1 ? snapshot : snapshot.slice(0, newline)\n ).trim();\n const body = newline === -1 ? \"\" : snapshot.slice(newline + 1);\n\n if (!header.startsWith(MANIFEST_PREFIX)) {\n throw new Error(\"Not a ZAM snapshot: missing manifest header.\");\n }\n\n let manifest: SnapshotManifest;\n try {\n manifest = JSON.parse(header.slice(MANIFEST_PREFIX.length));\n } catch {\n throw new Error(\"Snapshot manifest is not valid JSON.\");\n }\n\n if (manifest.format !== SNAPSHOT_FORMAT) {\n throw new Error(`Unsupported snapshot format: ${manifest.format}`);\n }\n if (manifest.version > SNAPSHOT_VERSION) {\n throw new Error(\n `Snapshot version ${manifest.version} is newer than supported ` +\n `(${SNAPSHOT_VERSION}). Upgrade ZAM to import it.`,\n );\n }\n\n return { manifest, body };\n}\n\n/** Parse a snapshot and verify its body checksum. Returns the manifest. */\nexport function verifySnapshot(snapshot: string): SnapshotManifest {\n const { manifest, body } = parseSnapshot(snapshot);\n const actual = createHash(\"sha256\").update(body).digest(\"hex\");\n if (actual !== manifest.checksum) {\n throw new Error(\"Snapshot is corrupted: checksum mismatch.\");\n }\n return manifest;\n}\n\n/**\n * Restore a snapshot into `db`. The database must already carry the current\n * schema (open it with `initialize: true`). Refuses to overwrite a non-empty\n * database unless `force` is set, and verifies row counts inside the\n * transaction so any mismatch rolls the whole restore back.\n */\nexport async function importSnapshot(\n db: Database,\n snapshot: string,\n options: { force?: boolean } = {},\n): Promise<ImportResult> {\n const { manifest, body } = parseSnapshot(snapshot);\n const actual = createHash(\"sha256\").update(body).digest(\"hex\");\n if (actual !== manifest.checksum) {\n throw new Error(\"Snapshot is corrupted: checksum mismatch.\");\n }\n\n return db.transaction(async (tx) => {\n let existing = 0;\n for (const table of SNAPSHOT_TABLES) {\n existing += await countRows(tx, table);\n }\n if (existing > 0 && !options.force) {\n throw new Error(\n `Target database already holds ${existing} row(s). ` +\n \"Pass force to overwrite it.\",\n );\n }\n\n if (options.force) {\n for (const table of [...SNAPSHOT_TABLES].reverse()) {\n await tx.exec(`DELETE FROM ${table};`);\n }\n }\n\n if (body.trim().length > 0) {\n await tx.exec(body);\n }\n\n const tables: Record<string, number> = {};\n let total = 0;\n for (const table of SNAPSHOT_TABLES) {\n const count = await countRows(tx, table);\n tables[table] = count;\n total += count;\n\n const expected = manifest.tables[table] ?? 0;\n if (count !== expected) {\n throw new Error(\n `Restore verification failed for ${table}: ` +\n `expected ${expected} row(s), found ${count}.`,\n );\n }\n }\n\n return { tables, total };\n });\n}\n","/**\n * Goal Engine — manages goal lifecycle via markdown files.\n *\n * Goals live as markdown files in a directory (typically the personal repo's\n * goals/ folder). The engine reads, creates, and updates these files.\n * It does not depend on the database — goals are git-tracked, not DB-tracked.\n */\n\nimport { existsSync, readdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { basename, join } from \"node:path\";\nimport type { Goal, GoalStatus } from \"./parser.js\";\nimport {\n extractTasks,\n extractTokenRefs,\n parseGoalFile,\n serializeGoal,\n} from \"./parser.js\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface GoalSummary {\n slug: string;\n title: string;\n status: GoalStatus;\n parent: string | null;\n taskCount: number;\n tasksDone: number;\n tokenCount: number;\n}\n\nexport interface CreateGoalInput {\n slug: string;\n title: string;\n status?: GoalStatus;\n parent?: string;\n description?: string;\n}\n\n// ── Functions ────────────────────────────────────────────────────────────────\n\n/**\n * List all goals in the goals directory.\n * Returns summaries sorted by status (active first) then title.\n */\nexport function listGoals(goalsDir: string): GoalSummary[] {\n if (!existsSync(goalsDir)) return [];\n\n const files = readdirSync(goalsDir).filter(\n (f) => f.endsWith(\".md\") && f !== \"README.md\",\n );\n\n const summaries: GoalSummary[] = [];\n\n for (const file of files) {\n const filePath = join(goalsDir, file);\n const content = readFileSync(filePath, \"utf-8\");\n const slug = basename(file, \".md\");\n const goal = parseGoalFile(content, slug, filePath);\n const tasks = extractTasks(goal.body);\n const tokens = extractTokenRefs(goal.body);\n\n summaries.push({\n slug: goal.slug,\n title: goal.title,\n status: goal.status,\n parent: goal.parent,\n taskCount: tasks.length,\n tasksDone: tasks.filter((t) => t.done).length,\n tokenCount: tokens.length,\n });\n }\n\n const statusOrder: Record<GoalStatus, number> = {\n active: 0,\n paused: 1,\n completed: 2,\n abandoned: 3,\n };\n\n summaries.sort((a, b) => {\n const statusDiff = statusOrder[a.status] - statusOrder[b.status];\n if (statusDiff !== 0) return statusDiff;\n return a.title.localeCompare(b.title);\n });\n\n return summaries;\n}\n\n/**\n * Get a single goal by slug (filename without .md).\n * Returns undefined if the file doesn't exist.\n */\nexport function getGoal(goalsDir: string, slug: string): Goal | undefined {\n const filePath = join(goalsDir, `${slug}.md`);\n if (!existsSync(filePath)) return undefined;\n\n const content = readFileSync(filePath, \"utf-8\");\n return parseGoalFile(content, slug, filePath);\n}\n\n/**\n * Create a new goal file. Throws if a goal with this slug already exists.\n */\nexport function createGoal(goalsDir: string, input: CreateGoalInput): Goal {\n const filePath = join(goalsDir, `${input.slug}.md`);\n\n if (existsSync(filePath)) {\n throw new Error(`Goal already exists: ${input.slug}`);\n }\n\n const now = new Date().toISOString().slice(0, 10);\n\n const goal: Goal = {\n slug: input.slug,\n title: input.title,\n status: input.status ?? \"active\",\n parent: input.parent ?? null,\n created: now,\n updated: now,\n body: input.description\n ? `## Description\\n${input.description}\\n\\n## Tasks\\n\\n## Tokens`\n : \"## Description\\n\\n## Tasks\\n\\n## Tokens\",\n filePath,\n };\n\n writeFileSync(filePath, serializeGoal(goal), \"utf-8\");\n return goal;\n}\n\n/**\n * Update a goal's status. Writes the updated file back to disk.\n */\nexport function updateGoalStatus(\n goalsDir: string,\n slug: string,\n status: GoalStatus,\n): Goal {\n const goal = getGoal(goalsDir, slug);\n if (!goal) throw new Error(`Goal not found: ${slug}`);\n\n goal.status = status;\n goal.updated = new Date().toISOString().slice(0, 10);\n\n writeFileSync(goal.filePath, serializeGoal(goal), \"utf-8\");\n return goal;\n}\n\n/**\n * Get the goal tree — goals organized by parent relationships.\n * Returns root goals (no parent) with nested children.\n */\nexport function getGoalTree(\n goalsDir: string,\n): Array<GoalSummary & { children: GoalSummary[] }> {\n const all = listGoals(goalsDir);\n const bySlug = new Map(all.map((g) => [g.slug, g]));\n\n const roots: Array<GoalSummary & { children: GoalSummary[] }> = [];\n const children = new Map<string, GoalSummary[]>();\n\n for (const g of all) {\n if (g.parent && bySlug.has(g.parent)) {\n const list = children.get(g.parent) ?? [];\n list.push(g);\n children.set(g.parent, list);\n }\n }\n\n for (const g of all) {\n if (!g.parent || !bySlug.has(g.parent)) {\n roots.push({ ...g, children: children.get(g.slug) ?? [] });\n }\n }\n\n return roots;\n}\n","/**\n * Goal file parser — reads markdown files with YAML-style frontmatter.\n *\n * Goals are persisted as markdown files in the personal repo.\n * Each file has simple key: value frontmatter (no nested structures)\n * and a markdown body with description, tasks, and token references.\n */\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport type GoalStatus = \"active\" | \"completed\" | \"paused\" | \"abandoned\";\n\nexport interface Goal {\n slug: string; // derived from filename (e.g., \"learn-rust\" from \"learn-rust.md\")\n title: string;\n status: GoalStatus;\n parent: string | null; // slug of parent goal\n created: string; // ISO date\n updated: string; // ISO date\n body: string; // markdown body after frontmatter\n filePath: string; // absolute path to the file\n}\n\nexport interface GoalFrontmatter {\n title?: string;\n status?: string;\n parent?: string;\n created?: string;\n updated?: string;\n}\n\n// ── Parser ───────────────────────────────────────────────────────────────────\n\n/**\n * Parse a goal markdown file into a Goal object.\n *\n * Expected format:\n * ```\n * ---\n * title: Learn Rust fundamentals\n * status: active\n * parent: become-systems-programmer\n * created: 2026-03-28\n * updated: 2026-03-28\n * ---\n *\n * ## Description\n * ...\n * ```\n *\n * @param content - Raw file content\n * @param slug - Goal slug (derived from filename by caller)\n * @param filePath - Absolute path to the file\n */\nexport function parseGoalFile(\n content: string,\n slug: string,\n filePath: string,\n): Goal {\n const { frontmatter, body } = splitFrontmatter(content);\n\n const validStatuses: GoalStatus[] = [\n \"active\",\n \"completed\",\n \"paused\",\n \"abandoned\",\n ];\n const status = validStatuses.includes(frontmatter.status as GoalStatus)\n ? (frontmatter.status as GoalStatus)\n : \"active\";\n\n const now = new Date().toISOString().slice(0, 10);\n\n return {\n slug,\n title: frontmatter.title || slug,\n status,\n parent: frontmatter.parent || null,\n created: frontmatter.created || now,\n updated: frontmatter.updated || now,\n body,\n filePath,\n };\n}\n\n/**\n * Serialize a Goal back to markdown with frontmatter.\n */\nexport function serializeGoal(goal: Goal): string {\n const lines = [\"---\", `title: ${goal.title}`, `status: ${goal.status}`];\n\n if (goal.parent) {\n lines.push(`parent: ${goal.parent}`);\n }\n\n lines.push(`created: ${goal.created}`);\n lines.push(`updated: ${goal.updated}`);\n lines.push(\"---\");\n lines.push(\"\");\n\n if (goal.body.trim()) {\n lines.push(goal.body.trim());\n lines.push(\"\");\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Extract tasks (checklist items) from goal body.\n * Returns items like { text: \"Complete Rustlings\", done: false }.\n */\nexport function extractTasks(\n body: string,\n): Array<{ text: string; done: boolean }> {\n const tasks: Array<{ text: string; done: boolean }> = [];\n const taskRegex = /^[-*]\\s+\\[([ xX])\\]\\s+(.+)$/gm;\n let match: RegExpExecArray | null = taskRegex.exec(body);\n\n while (match !== null) {\n tasks.push({\n done: match[1] !== \" \",\n text: match[2].trim(),\n });\n match = taskRegex.exec(body);\n }\n\n return tasks;\n}\n\n/**\n * Extract token references from goal body.\n * Looks for lines like `- token/slug` under a \"## Tokens\" section.\n */\nexport function extractTokenRefs(body: string): string[] {\n const tokensSection = body.match(/## Tokens\\n([\\s\\S]*?)(?=\\n## |\\n*$)/);\n if (!tokensSection) return [];\n\n const refs: string[] = [];\n const lines = tokensSection[1].split(\"\\n\");\n\n for (const line of lines) {\n const match = line.match(/^[-*]\\s+(\\S+)/);\n if (match) {\n refs.push(match[1]);\n }\n }\n\n return refs;\n}\n\n// ── Internal helpers ─────────────────────────────────────────────────────────\n\nfunction splitFrontmatter(content: string): {\n frontmatter: GoalFrontmatter;\n body: string;\n} {\n const trimmed = content.trim();\n\n if (!trimmed.startsWith(\"---\")) {\n return { frontmatter: {}, body: trimmed };\n }\n\n const endIndex = trimmed.indexOf(\"---\", 3);\n if (endIndex === -1) {\n return { frontmatter: {}, body: trimmed };\n }\n\n const fmBlock = trimmed.slice(3, endIndex).trim();\n const body = trimmed.slice(endIndex + 3).trim();\n\n const frontmatter: GoalFrontmatter = {};\n for (const line of fmBlock.split(\"\\n\")) {\n const colonIndex = line.indexOf(\":\");\n if (colonIndex === -1) continue;\n\n const key = line.slice(0, colonIndex).trim();\n const value = line.slice(colonIndex + 1).trim();\n\n if (key && value) {\n (frontmatter as Record<string, string>)[key] = value;\n }\n }\n\n return { frontmatter, body };\n}\n","/**\n * Agent skills: task recipes the agent learns from user guidance.\n *\n * When the agent cannot execute a step, it admits it, asks for guidance,\n * and saves the successful approach here. Skills are linked to tokens so\n * FSRS decay naturally resurfaces them for review — automation ≠ retention.\n */\n\nimport { ulid } from \"ulid\";\nimport type { Database } from \"../db/types.js\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport type SkillSource = \"learned\" | \"builtin\";\n\nexport interface AgentSkill {\n id: string;\n slug: string;\n description: string;\n steps: string[]; // parsed from JSON\n token_slugs: string[]; // parsed from JSON\n source: SkillSource;\n created_at: string;\n updated_at: string;\n}\n\n/** Raw DB row — steps and token_slugs are stored as JSON strings */\ninterface AgentSkillRow {\n id: string;\n slug: string;\n description: string;\n steps: string;\n token_slugs: string;\n source: SkillSource;\n created_at: string;\n updated_at: string;\n}\n\nexport interface CreateAgentSkillInput {\n slug: string;\n description: string;\n steps: string[];\n token_slugs?: string[];\n source?: SkillSource;\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction parseRow(row: AgentSkillRow): AgentSkill {\n return {\n ...row,\n steps: JSON.parse(row.steps) as string[],\n token_slugs: JSON.parse(row.token_slugs) as string[],\n };\n}\n\n// ── Functions ────────────────────────────────────────────────────────────────\n\nexport async function createAgentSkill(\n db: Database,\n input: CreateAgentSkillInput,\n): Promise<AgentSkill> {\n const existing = (await db\n .prepare(\"SELECT * FROM agent_skills WHERE slug = ?\")\n .get(input.slug)) as AgentSkillRow | undefined;\n\n if (existing) {\n throw new Error(`Agent skill already exists: ${input.slug}`);\n }\n\n const id = ulid();\n const now = new Date().toISOString();\n\n await db\n .prepare(\n `INSERT INTO agent_skills (id, slug, description, steps, token_slugs, source, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n id,\n input.slug,\n input.description,\n JSON.stringify(input.steps),\n JSON.stringify(input.token_slugs ?? []),\n input.source ?? \"learned\",\n now,\n now,\n );\n\n return parseRow(\n (await db\n .prepare(\"SELECT * FROM agent_skills WHERE id = ?\")\n .get(id)) as AgentSkillRow,\n );\n}\n\nexport async function getAgentSkill(\n db: Database,\n slug: string,\n): Promise<AgentSkill | undefined> {\n const row = (await db\n .prepare(\"SELECT * FROM agent_skills WHERE slug = ?\")\n .get(slug)) as AgentSkillRow | undefined;\n\n return row ? parseRow(row) : undefined;\n}\n\nexport async function listAgentSkills(db: Database): Promise<AgentSkill[]> {\n const rows = (await db\n .prepare(\"SELECT * FROM agent_skills ORDER BY created_at ASC\")\n .all()) as AgentSkillRow[];\n\n return rows.map(parseRow);\n}\n","/**\n * Card repository — typed wrappers around the cards table.\n *\n * Each card tracks one user's scheduling state for one token,\n * using FSRS fields (stability, difficulty, elapsed_days, etc.).\n */\n\nimport { ulid } from \"ulid\";\nimport type { Database } from \"../db/types.js\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport type CardState = \"new\" | \"learning\" | \"review\" | \"relearning\";\n\nexport interface Card {\n id: string;\n token_id: string;\n user_id: string;\n stability: number;\n difficulty: number;\n elapsed_days: number;\n scheduled_days: number;\n reps: number;\n lapses: number;\n state: CardState;\n due_at: string;\n last_review_at: string | null;\n blocked: number; // 0 or 1\n}\n\nexport interface UpdateCardInput {\n stability?: number;\n difficulty?: number;\n elapsed_days?: number;\n scheduled_days?: number;\n reps?: number;\n lapses?: number;\n state?: CardState;\n due_at?: string;\n last_review_at?: string | null;\n blocked?: number;\n}\n\nexport interface CardDeletionImpact {\n review_logs: number;\n}\n\nexport interface DeleteCardResult {\n card: Card;\n impact: CardDeletionImpact;\n}\n\n/** A due card joined with its token details. */\nexport interface DueCard extends Card {\n slug: string;\n concept: string;\n domain: string;\n bloom_level: number;\n}\n\n/** A blocked card joined with its token details. */\nexport interface BlockedCard extends Card {\n slug: string;\n concept: string;\n domain: string;\n bloom_level: number;\n}\n\n// ── Functions ────────────────────────────────────────────────────────────────\n\n/**\n * Ensure a card exists for the given token+user pair.\n *\n * If one already exists, return it. Otherwise create a new card with\n * default FSRS values (due immediately) and return it.\n *\n * Ported from the PoC's ensureCard helper.\n */\nexport async function ensureCard(\n db: Database,\n tokenId: string,\n userId: string,\n): Promise<Card> {\n const existing = (await db\n .prepare(\"SELECT * FROM cards WHERE token_id = ? AND user_id = ?\")\n .get(tokenId, userId)) as Card | undefined;\n\n if (existing) return existing;\n\n const id = ulid();\n const now = new Date().toISOString();\n\n await db\n .prepare(\n `INSERT INTO cards (id, token_id, user_id, due_at)\n VALUES (?, ?, ?, ?)`,\n )\n .run(id, tokenId, userId, now);\n\n return (await db.prepare(\"SELECT * FROM cards WHERE id = ?\").get(id)) as Card;\n}\n\n/**\n * Get a card by token+user. Returns undefined if no card exists.\n */\nexport async function getCard(\n db: Database,\n tokenId: string,\n userId: string,\n): Promise<Card | undefined> {\n return (await db\n .prepare(\"SELECT * FROM cards WHERE token_id = ? AND user_id = ?\")\n .get(tokenId, userId)) as Card | undefined;\n}\n\n/**\n * Get a card by its ULID.\n */\nexport async function getCardById(\n db: Database,\n cardId: string,\n): Promise<Card | undefined> {\n return (await db.prepare(\"SELECT * FROM cards WHERE id = ?\").get(cardId)) as\n | Card\n | undefined;\n}\n\n/**\n * Update a card's scheduling fields.\n *\n * Only the fields present in `updates` are changed. Throws if the card\n * does not exist.\n */\nexport async function updateCard(\n db: Database,\n cardId: string,\n updates: UpdateCardInput,\n): Promise<Card> {\n const fields: string[] = [];\n const values: unknown[] = [];\n\n if (updates.stability !== undefined) {\n fields.push(\"stability = ?\");\n values.push(updates.stability);\n }\n if (updates.difficulty !== undefined) {\n fields.push(\"difficulty = ?\");\n values.push(updates.difficulty);\n }\n if (updates.elapsed_days !== undefined) {\n fields.push(\"elapsed_days = ?\");\n values.push(updates.elapsed_days);\n }\n if (updates.scheduled_days !== undefined) {\n fields.push(\"scheduled_days = ?\");\n values.push(updates.scheduled_days);\n }\n if (updates.reps !== undefined) {\n fields.push(\"reps = ?\");\n values.push(updates.reps);\n }\n if (updates.lapses !== undefined) {\n fields.push(\"lapses = ?\");\n values.push(updates.lapses);\n }\n if (updates.state !== undefined) {\n fields.push(\"state = ?\");\n values.push(updates.state);\n }\n if (updates.due_at !== undefined) {\n fields.push(\"due_at = ?\");\n values.push(updates.due_at);\n }\n if (updates.last_review_at !== undefined) {\n fields.push(\"last_review_at = ?\");\n values.push(updates.last_review_at);\n }\n if (updates.blocked !== undefined) {\n fields.push(\"blocked = ?\");\n values.push(updates.blocked);\n }\n\n if (fields.length === 0) {\n throw new Error(\"updateCard called with no fields to update\");\n }\n\n values.push(cardId);\n\n const result = await db\n .prepare(`UPDATE cards SET ${fields.join(\", \")} WHERE id = ?`)\n .run(...values);\n\n if (result.changes === 0) {\n throw new Error(`Card not found: ${cardId}`);\n }\n\n return (await db\n .prepare(\"SELECT * FROM cards WHERE id = ?\")\n .get(cardId)) as Card;\n}\n\n/**\n * Preview the review-log rows that will be removed when deleting a user's card.\n */\nexport async function getCardDeletionImpact(\n db: Database,\n tokenId: string,\n userId: string,\n): Promise<CardDeletionImpact> {\n const card = await getCard(db, tokenId, userId);\n if (!card) {\n throw new Error(`Card not found for token ${tokenId} and user ${userId}`);\n }\n\n const reviewLogs = (await db\n .prepare(\"SELECT COUNT(*) AS n FROM review_logs WHERE card_id = ?\")\n .get(card.id)) as { n: number };\n\n return { review_logs: reviewLogs.n };\n}\n\n/**\n * Delete one user's card for a token. Review logs cascade via FK.\n */\nexport async function deleteCardForUser(\n db: Database,\n tokenId: string,\n userId: string,\n): Promise<DeleteCardResult> {\n const card = await getCard(db, tokenId, userId);\n if (!card) {\n throw new Error(`Card not found for token ${tokenId} and user ${userId}`);\n }\n\n const impact = await getCardDeletionImpact(db, tokenId, userId);\n await db.prepare(\"DELETE FROM cards WHERE id = ?\").run(card.id);\n\n return { card, impact };\n}\n\n/**\n * Get all cards that are due for review.\n *\n * A card is due when it is not blocked and due_at <= now.\n * Results are ordered by bloom_level ascending (fundamentals first),\n * then by due_at ascending (oldest first).\n *\n * Ported from the PoC's due-tokens command.\n */\nexport async function getDueCards(\n db: Database,\n userId: string,\n now?: string,\n): Promise<DueCard[]> {\n const cutoff = now ?? new Date().toISOString();\n\n return (await db\n .prepare(\n `SELECT c.*, t.slug, t.concept, t.domain, t.bloom_level\n FROM cards c\n JOIN tokens t ON t.id = c.token_id\n WHERE c.user_id = ? AND c.blocked = 0 AND c.due_at <= ?\n ORDER BY t.bloom_level ASC, c.due_at ASC`,\n )\n .all(userId, cutoff)) as DueCard[];\n}\n\n/**\n * Get all blocked cards for a user.\n *\n * Returns cards joined with their token details so the caller can\n * see what is waiting and why.\n */\nexport async function getBlockedCards(\n db: Database,\n userId: string,\n): Promise<BlockedCard[]> {\n return (await db\n .prepare(\n `SELECT c.*, t.slug, t.concept, t.domain, t.bloom_level\n FROM cards c\n JOIN tokens t ON t.id = c.token_id\n WHERE c.user_id = ? AND c.blocked = 1\n ORDER BY t.bloom_level ASC, t.slug ASC`,\n )\n .all(userId)) as BlockedCard[];\n}\n","/**\n * Token repository — typed wrappers around the tokens table.\n *\n * Tokens are atomic knowledge concepts with Bloom taxonomy levels\n * and optional symbiosis modes (shadowing / copilot / autonomy).\n */\n\nimport { ulid } from \"ulid\";\nimport type { Database } from \"../db/types.js\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport type BloomLevel = 1 | 2 | 3 | 4 | 5;\n\nexport type SymbiosisMode = \"shadowing\" | \"copilot\" | \"autonomy\";\n\nexport interface Token {\n id: string;\n slug: string;\n concept: string;\n domain: string;\n bloom_level: BloomLevel;\n context: string;\n symbiosis_mode: SymbiosisMode | null;\n source_link: string | null;\n question: string | null;\n created_at: string;\n updated_at: string;\n deprecated_at: string | null;\n}\n\nexport interface CreateTokenInput {\n slug: string;\n concept: string;\n domain?: string;\n bloom_level?: BloomLevel;\n context?: string;\n symbiosis_mode?: SymbiosisMode | null;\n source_link?: string | null;\n question?: string | null;\n}\n\nexport interface UpdateTokenInput {\n concept?: string;\n domain?: string;\n bloom_level?: BloomLevel;\n context?: string;\n symbiosis_mode?: SymbiosisMode | null;\n source_link?: string | null;\n question?: string | null;\n}\n\nexport interface ListTokensOptions {\n domain?: string;\n}\n\nexport interface TokenDeleteImpact {\n cards: number;\n review_logs: number;\n prerequisite_edges_from_token: number;\n prerequisite_edges_to_token: number;\n session_steps: number;\n sessions_touched: number;\n agent_skills: number;\n}\n\nexport interface DeleteTokenResult {\n token: Token;\n impact: TokenDeleteImpact;\n}\n\n// ── Scored result from fuzzy search ──────────────────────────────────────────\n\nexport interface ScoredToken extends Token {\n score: number;\n}\n\n// ── Functions ────────────────────────────────────────────────────────────────\n\n/**\n * Create a new knowledge token.\n * Throws if a token with the same slug already exists.\n */\nexport async function createToken(\n db: Database,\n input: CreateTokenInput,\n): Promise<Token> {\n const id = ulid();\n const now = new Date().toISOString();\n\n const bloom = input.bloom_level ?? 1;\n if (bloom < 1 || bloom > 5) {\n throw new Error(`bloom_level must be between 1 and 5, got ${bloom}`);\n }\n\n await db\n .prepare(`\n INSERT INTO tokens (id, slug, concept, domain, bloom_level, context, symbiosis_mode, source_link, question, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `)\n .run(\n id,\n input.slug,\n input.concept,\n input.domain ?? \"\",\n bloom,\n input.context ?? \"\",\n input.symbiosis_mode ?? null,\n input.source_link ?? null,\n input.question ?? null,\n now,\n now,\n );\n\n return (await getTokenById(db, id)) as Token;\n}\n\n/**\n * Look up a token by its unique slug.\n * Returns undefined if not found.\n */\nexport async function getTokenBySlug(\n db: Database,\n slug: string,\n): Promise<Token | undefined> {\n return (await db.prepare(\"SELECT * FROM tokens WHERE slug = ?\").get(slug)) as\n | Token\n | undefined;\n}\n\n/**\n * Look up a token by its ULID.\n * Returns undefined if not found.\n */\nexport async function getTokenById(\n db: Database,\n id: string,\n): Promise<Token | undefined> {\n return (await db.prepare(\"SELECT * FROM tokens WHERE id = ?\").get(id)) as\n | Token\n | undefined;\n}\n\n/**\n * Update mutable fields on a token.\n *\n * Slug is intentionally immutable in v1 because it is referenced by other\n * parts of the system (for example agent skill metadata).\n */\nexport async function updateToken(\n db: Database,\n slug: string,\n updates: UpdateTokenInput,\n): Promise<Token> {\n const token = await getTokenBySlug(db, slug);\n if (!token) {\n throw new Error(`Token not found: ${slug}`);\n }\n\n const fields: string[] = [];\n const values: unknown[] = [];\n\n if (updates.concept !== undefined) {\n fields.push(\"concept = ?\");\n values.push(updates.concept);\n }\n if (updates.domain !== undefined) {\n fields.push(\"domain = ?\");\n values.push(updates.domain);\n }\n if (updates.bloom_level !== undefined) {\n if (updates.bloom_level < 1 || updates.bloom_level > 5) {\n throw new Error(\n `bloom_level must be between 1 and 5, got ${updates.bloom_level}`,\n );\n }\n fields.push(\"bloom_level = ?\");\n values.push(updates.bloom_level);\n }\n if (updates.context !== undefined) {\n fields.push(\"context = ?\");\n values.push(updates.context);\n }\n if (updates.symbiosis_mode !== undefined) {\n const validModes = [\"shadowing\", \"copilot\", \"autonomy\"];\n if (\n updates.symbiosis_mode !== null &&\n !validModes.includes(updates.symbiosis_mode)\n ) {\n throw new Error(`Invalid symbiosis_mode: ${updates.symbiosis_mode}`);\n }\n fields.push(\"symbiosis_mode = ?\");\n values.push(updates.symbiosis_mode);\n }\n if (updates.source_link !== undefined) {\n fields.push(\"source_link = ?\");\n values.push(updates.source_link);\n }\n if (updates.question !== undefined) {\n fields.push(\"question = ?\");\n values.push(updates.question);\n }\n\n if (fields.length === 0) {\n throw new Error(\"updateToken called with no fields to update\");\n }\n\n fields.push(\"updated_at = ?\");\n values.push(new Date().toISOString());\n values.push(slug);\n\n await db\n .prepare(`UPDATE tokens SET ${fields.join(\", \")} WHERE slug = ?`)\n .run(...values);\n return (await getTokenBySlug(db, slug)) as Token;\n}\n\n/**\n * Mark a token as deprecated. Deprecated tokens are excluded from review queues\n * and search results but are not deleted — they can still be consulted.\n *\n * Throws if the token does not exist or is already deprecated.\n */\nexport async function deprecateToken(\n db: Database,\n slug: string,\n): Promise<Token> {\n const token = await getTokenBySlug(db, slug);\n if (!token) {\n throw new Error(`Token not found: ${slug}`);\n }\n if (token.deprecated_at) {\n throw new Error(`Token already deprecated: ${slug}`);\n }\n\n const now = new Date().toISOString();\n await db\n .prepare(\n \"UPDATE tokens SET deprecated_at = ?, updated_at = ? WHERE slug = ?\",\n )\n .run(now, now, slug);\n\n return (await getTokenBySlug(db, slug)) as Token;\n}\n\n/**\n * Preview the rows that will be removed or updated when deleting a token.\n */\nexport async function getTokenDeleteImpact(\n db: Database,\n slug: string,\n): Promise<TokenDeleteImpact> {\n const token = await getTokenBySlug(db, slug);\n if (!token) {\n throw new Error(`Token not found: ${slug}`);\n }\n\n const cards = (await db\n .prepare(\"SELECT COUNT(*) AS n FROM cards WHERE token_id = ?\")\n .get(token.id)) as { n: number };\n const reviewLogs = (await db\n .prepare(\"SELECT COUNT(*) AS n FROM review_logs WHERE token_id = ?\")\n .get(token.id)) as { n: number };\n const prereqsFrom = (await db\n .prepare(\"SELECT COUNT(*) AS n FROM prerequisites WHERE token_id = ?\")\n .get(token.id)) as { n: number };\n const prereqsTo = (await db\n .prepare(\"SELECT COUNT(*) AS n FROM prerequisites WHERE requires_id = ?\")\n .get(token.id)) as { n: number };\n const sessionSteps = (await db\n .prepare(\"SELECT COUNT(*) AS n FROM session_steps WHERE token_id = ?\")\n .get(token.id)) as { n: number };\n const sessionsTouched = (await db\n .prepare(\n \"SELECT COUNT(DISTINCT session_id) AS n FROM session_steps WHERE token_id = ?\",\n )\n .get(token.id)) as { n: number };\n\n const skillRows = (await db\n .prepare(\"SELECT token_slugs FROM agent_skills\")\n .all()) as Array<{ token_slugs: string }>;\n const agentSkills = skillRows.filter((row) => {\n const tokenSlugs = JSON.parse(row.token_slugs) as string[];\n return tokenSlugs.includes(slug);\n }).length;\n\n return {\n cards: cards.n,\n review_logs: reviewLogs.n,\n prerequisite_edges_from_token: prereqsFrom.n,\n prerequisite_edges_to_token: prereqsTo.n,\n session_steps: sessionSteps.n,\n sessions_touched: sessionsTouched.n,\n agent_skills: agentSkills,\n };\n}\n\n/**\n * Hard-delete a token and clean up non-FK references that point at its slug.\n */\nexport async function deleteToken(\n db: Database,\n slug: string,\n): Promise<DeleteTokenResult> {\n const token = await getTokenBySlug(db, slug);\n if (!token) {\n throw new Error(`Token not found: ${slug}`);\n }\n\n const impact = await getTokenDeleteImpact(db, slug);\n\n await db.transaction(async (tx) => {\n const now = new Date().toISOString();\n const skillRows = (await tx\n .prepare(\"SELECT id, token_slugs FROM agent_skills\")\n .all()) as Array<{ id: string; token_slugs: string }>;\n\n for (const row of skillRows) {\n const tokenSlugs = JSON.parse(row.token_slugs) as string[];\n const filtered = tokenSlugs.filter((tokenSlug) => tokenSlug !== slug);\n if (filtered.length !== tokenSlugs.length) {\n await tx\n .prepare(\n \"UPDATE agent_skills SET token_slugs = ?, updated_at = ? WHERE id = ?\",\n )\n .run(JSON.stringify(filtered), now, row.id);\n }\n }\n\n await tx.prepare(\"DELETE FROM tokens WHERE id = ?\").run(token.id);\n });\n\n return { token, impact };\n}\n\n/**\n * Fuzzy search for tokens by keyword query.\n *\n * Uses SQLite LIKE queries on slug, concept, and domain to avoid loading\n * every non-deprecated token into memory. Each search term runs its own\n * LIKE query; results are aggregated in JS with a word-overlap score plus\n * a substring bonus on the concept field. Results are returned sorted by\n * relevance score descending.\n *\n * For very small search terms (< 3 chars) a light in-memory fallback is\n * used to avoid matching every token.\n */\nexport async function findTokens(\n db: Database,\n query: string,\n): Promise<ScoredToken[]> {\n const normalised = query.toLowerCase();\n const searchTokens = normalised\n .split(/[\\s,.\\-_/\\\\:;!?()[\\]{}]+/)\n .filter((t) => t.length > 0);\n\n if (searchTokens.length === 0) return [];\n\n // Short terms: fall back to in-memory scan (cheap — few tokens match anyway)\n const shortTerms = searchTokens.filter((t) => t.length <= 2);\n const longTerms = searchTokens.filter((t) => t.length > 2);\n\n const scoreMap = new Map<string, { token: Token; score: number }>();\n\n // Per-term SQL LIKE queries for each substantive search token.\n const likeSQL =\n `SELECT * FROM tokens WHERE deprecated_at IS NULL AND ` +\n `(lower(slug) LIKE ? OR lower(concept) LIKE ? OR lower(domain) LIKE ?)`;\n\n for (const term of longTerms) {\n const pattern = `%${term}%`;\n const rows = (await db\n .prepare(likeSQL)\n .all(pattern, pattern, pattern)) as Token[];\n for (const row of rows) {\n const entry = scoreMap.get(row.id);\n if (entry) {\n entry.score++;\n } else {\n scoreMap.set(row.id, { token: row, score: 1 });\n }\n }\n }\n\n // If there were short terms, or all terms were short, scan in-memory.\n if (shortTerms.length > 0 || longTerms.length === 0) {\n const allTokens = (await db\n .prepare(\"SELECT * FROM tokens WHERE deprecated_at IS NULL\")\n .all()) as Token[];\n\n for (const token of allTokens) {\n const words = `${token.slug} ${token.concept} ${token.domain}`\n .toLowerCase()\n .split(/[\\s,.\\-_/\\\\:;!?()[\\]{}]+/)\n .filter(Boolean);\n\n let matchCount = 0;\n for (const term of shortTerms.length > 0 ? shortTerms : searchTokens) {\n for (const w of words) {\n if (w === term) matchCount++;\n }\n }\n\n if (matchCount > 0) {\n const entry = scoreMap.get(token.id);\n if (entry) {\n entry.score += matchCount;\n } else {\n scoreMap.set(token.id, { token, score: matchCount });\n }\n }\n }\n }\n\n // Apply substring bonus and build result.\n const scored: ScoredToken[] = [];\n for (const { token, score } of scoreMap.values()) {\n let finalScore = score;\n if (token.concept.toLowerCase().includes(normalised.slice(0, 25))) {\n finalScore += 3;\n }\n scored.push({ score: finalScore, ...token });\n }\n\n scored.sort((a, b) => b.score - a.score);\n return scored;\n}\n\n/**\n * List all tokens, optionally filtered by domain.\n * Results are ordered by bloom_level then slug.\n */\nexport async function listTokens(\n db: Database,\n options?: ListTokensOptions,\n): Promise<Token[]> {\n if (options?.domain) {\n return (await db\n .prepare(\n \"SELECT * FROM tokens WHERE domain = ? AND deprecated_at IS NULL ORDER BY bloom_level, slug\",\n )\n .all(options.domain)) as Token[];\n }\n return (await db\n .prepare(\n \"SELECT * FROM tokens WHERE deprecated_at IS NULL ORDER BY bloom_level, domain, slug\",\n )\n .all()) as Token[];\n}\n","/**\n * Prerequisite repository — typed wrappers around the prerequisites table.\n *\n * Models the dependency graph: \"to learn token A, first know token B.\"\n * The graph must remain acyclic — cycles are rejected at insert time.\n */\n\nimport type { Database } from \"../db/types.js\";\nimport { type Card, type CardState, getCard } from \"./card.js\";\nimport { getTokenById } from \"./token.js\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface Prerequisite {\n token_id: string;\n requires_id: string;\n}\n\n/** A prerequisite row joined with the token it points to. */\nexport interface PrerequisiteWithToken extends Prerequisite {\n slug: string;\n concept: string;\n domain: string;\n bloom_level: number;\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\n/**\n * Collect all prerequisite edges as an adjacency map: child → parent set.\n * Only used for cycle detection; the full graph is loaded once per\n * addPrerequisite call (small N in practice).\n */\nasync function buildAncestorMap(\n db: Database,\n): Promise<Map<string, Set<string>>> {\n const rows = (await db\n .prepare(\"SELECT token_id, requires_id FROM prerequisites\")\n .all()) as Array<{ token_id: string; requires_id: string }>;\n const map = new Map<string, Set<string>>();\n for (const row of rows) {\n let ancestors = map.get(row.token_id);\n if (!ancestors) {\n ancestors = new Set();\n map.set(row.token_id, ancestors);\n }\n ancestors.add(row.requires_id);\n }\n return map;\n}\n\n/**\n * Returns true if adding edge (tokenId → requiresId) would create a cycle.\n * Uses BFS from requiresId: if tokenId is reachable, adding the edge closes\n * a loop.\n */\nexport async function wouldCreateCycle(\n db: Database,\n tokenId: string,\n requiresId: string,\n): Promise<boolean> {\n if (tokenId === requiresId) return true;\n\n const ancestors = await buildAncestorMap(db);\n const visited = new Set<string>();\n const queue = [requiresId];\n\n while (queue.length > 0) {\n const current = queue.shift() as string;\n if (current === tokenId) return true;\n if (visited.has(current)) continue;\n visited.add(current);\n\n const parents = ancestors.get(current);\n if (parents) {\n for (const parent of parents) {\n if (!visited.has(parent)) queue.push(parent);\n }\n }\n }\n return false;\n}\n\n// ── Functions ────────────────────────────────────────────────────────────────\n\n/**\n * Add a prerequisite edge: tokenId requires requiresId.\n *\n * Idempotent — silently ignores duplicate edges.\n * Throws if either token ID does not exist (FK constraint).\n * Throws if a token is declared as its own prerequisite.\n * Throws if the edge would create a cycle in the prerequisite graph.\n */\nexport async function addPrerequisite(\n db: Database,\n tokenId: string,\n requiresId: string,\n): Promise<void> {\n if (tokenId === requiresId) {\n throw new Error(\"A token cannot be a prerequisite of itself\");\n }\n\n if (await wouldCreateCycle(db, tokenId, requiresId)) {\n throw new Error(\n `Cannot add prerequisite: would create a cycle. ` +\n `${requiresId} already depends on ${tokenId} (directly or transitively).`,\n );\n }\n\n await db\n .prepare(\n \"INSERT OR IGNORE INTO prerequisites (token_id, requires_id) VALUES (?, ?)\",\n )\n .run(tokenId, requiresId);\n}\n\n/**\n * Get the direct prerequisites of a token — \"what does token X require?\"\n *\n * Returns prerequisite rows joined with the required token's details.\n */\nexport async function getPrerequisites(\n db: Database,\n tokenId: string,\n): Promise<PrerequisiteWithToken[]> {\n return (await db\n .prepare(\n `SELECT p.token_id, p.requires_id, t.slug, t.concept, t.domain, t.bloom_level\n FROM prerequisites p\n JOIN tokens t ON t.id = p.requires_id\n WHERE p.token_id = ?`,\n )\n .all(tokenId)) as PrerequisiteWithToken[];\n}\n\n/**\n * Get the direct dependents of a token — \"what depends on token X?\"\n *\n * Returns prerequisite rows joined with the dependent token's details.\n */\nexport async function getDependents(\n db: Database,\n tokenId: string,\n): Promise<PrerequisiteWithToken[]> {\n return (await db\n .prepare(\n `SELECT p.token_id, p.requires_id, t.slug, t.concept, t.domain, t.bloom_level\n FROM prerequisites p\n JOIN tokens t ON t.id = p.token_id\n WHERE p.requires_id = ?`,\n )\n .all(tokenId)) as PrerequisiteWithToken[];\n}\n\n// ── Visualization Neighborhood (for 3D focus graph) ──────────────────────────\n\n/** Token + optional per-user card snapshot, tailored for visual encoding (mastery, blocked state, bloom). */\nexport interface NeighborhoodToken {\n id: string;\n slug: string;\n concept: string;\n domain: string;\n bloom_level: number;\n card: {\n state: CardState;\n reps: number;\n stability: number;\n difficulty: number;\n blocked: boolean;\n due_at: string;\n last_review_at: string | null;\n } | null;\n}\n\n/**\n * The direct neighborhood for a focus-centric 3D view:\n * - center: the token in focus\n * - prerequisites: direct \"basis\" tokens required by the center (foundations, placed \"below\")\n * - dependents: direct tokens that require the center (higher-order abilities, placed \"above\")\n *\n * When userId is supplied, every node includes the user's Card state so the viz can\n * encode personal mastery (e.g. color by stability/reps, highlight blocked or due).\n */\nexport interface Neighborhood {\n center: NeighborhoodToken;\n prerequisites: NeighborhoodToken[];\n dependents: NeighborhoodToken[];\n}\n\n/**\n * Fetch the direct (depth-1) prerequisite neighborhood around one token.\n * This is the primary data source for the experimental 3D knowledge graph.\n */\nexport async function getTokenNeighborhood(\n db: Database,\n tokenId: string,\n userId?: string,\n): Promise<Neighborhood> {\n const token = await getTokenById(db, tokenId);\n if (!token) {\n throw new Error(`Token not found: ${tokenId}`);\n }\n\n const centerCard = userId ? await getCard(db, tokenId, userId) : undefined;\n\n const prereqRows = await getPrerequisites(db, tokenId);\n const depRows = await getDependents(db, tokenId);\n\n // Collect all related token ids for batched card lookup (when userId given)\n const relatedTokenIds = new Set<string>();\n for (const p of prereqRows) relatedTokenIds.add(p.requires_id);\n for (const d of depRows) relatedTokenIds.add(d.token_id);\n\n const cardMap = new Map<string, Card>();\n if (userId && relatedTokenIds.size > 0) {\n const ids = Array.from(relatedTokenIds);\n const placeholders = ids.map(() => \"?\").join(\",\");\n const rows = (await db\n .prepare(\n `SELECT * FROM cards WHERE token_id IN (${placeholders}) AND user_id = ?`,\n )\n .all(...ids, userId)) as Card[];\n for (const row of rows) {\n cardMap.set(row.token_id, row);\n }\n }\n\n const toNode = (\n t: {\n id: string;\n slug: string;\n concept: string;\n domain: string;\n bloom_level: number;\n },\n card?: Card,\n ): NeighborhoodToken => ({\n id: t.id,\n slug: t.slug,\n concept: t.concept,\n domain: t.domain,\n bloom_level: t.bloom_level,\n card: card\n ? {\n state: card.state,\n reps: card.reps,\n stability: card.stability,\n difficulty: card.difficulty,\n blocked: card.blocked === 1,\n due_at: card.due_at,\n last_review_at: card.last_review_at,\n }\n : null,\n });\n\n const center: NeighborhoodToken = toNode(token, centerCard);\n\n const prerequisites: NeighborhoodToken[] = prereqRows.map((p) =>\n toNode(\n {\n id: p.requires_id,\n slug: p.slug,\n concept: p.concept,\n domain: p.domain,\n bloom_level: p.bloom_level,\n },\n cardMap.get(p.requires_id),\n ),\n );\n\n const dependents: NeighborhoodToken[] = depRows.map((d) =>\n toNode(\n {\n id: d.token_id,\n slug: d.slug,\n concept: d.concept,\n domain: d.domain,\n bloom_level: d.bloom_level,\n },\n cardMap.get(d.token_id),\n ),\n );\n\n return { center, prerequisites, dependents };\n}\n","/**\n * Review log repository — typed wrappers around the review_logs table.\n *\n * The review log is immutable: every rating event is appended, never\n * updated or deleted. This provides a complete audit trail of a user's\n * learning history.\n */\n\nimport { ulid } from \"ulid\";\nimport type { Database } from \"../db/types.js\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface ReviewLog {\n id: string;\n card_id: string;\n token_id: string;\n user_id: string;\n rating: number; // 1-4\n response_time_ms: number | null;\n reviewed_at: string;\n scheduled_at: string;\n session_id: string | null;\n}\n\nexport interface CreateReviewInput {\n card_id: string;\n token_id: string;\n user_id: string;\n rating: number; // 1-4\n scheduled_at: string;\n response_time_ms?: number | null;\n session_id?: string | null;\n}\n\nexport interface ListReviewsOptions {\n /** Maximum number of reviews to return. */\n limit?: number;\n /** Return reviews after this ISO timestamp. */\n after?: string;\n /** Return reviews before this ISO timestamp. */\n before?: string;\n}\n\n// ── Functions ────────────────────────────────────────────────────────────────\n\n/**\n * Log an immutable review event.\n *\n * Validates that the rating is between 1 and 4 (matching the schema CHECK).\n * Returns the created review log entry.\n */\nexport async function logReview(\n db: Database,\n input: CreateReviewInput,\n): Promise<ReviewLog> {\n if (input.rating < 1 || input.rating > 4) {\n throw new Error(`Rating must be between 1 and 4, got ${input.rating}`);\n }\n\n const id = ulid();\n const now = new Date().toISOString();\n\n await db\n .prepare(\n `INSERT INTO review_logs (id, card_id, token_id, user_id, rating, response_time_ms, reviewed_at, scheduled_at, session_id)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n id,\n input.card_id,\n input.token_id,\n input.user_id,\n input.rating,\n input.response_time_ms ?? null,\n now,\n input.scheduled_at,\n input.session_id ?? null,\n );\n\n return (await db\n .prepare(\"SELECT * FROM review_logs WHERE id = ?\")\n .get(id)) as ReviewLog;\n}\n\n/**\n * Get all reviews for a specific card, ordered by reviewed_at ascending.\n */\nexport async function getReviewsForCard(\n db: Database,\n cardId: string,\n): Promise<ReviewLog[]> {\n return (await db\n .prepare(\n \"SELECT * FROM review_logs WHERE card_id = ? ORDER BY reviewed_at ASC\",\n )\n .all(cardId)) as ReviewLog[];\n}\n\n/**\n * Get reviews for a user, with optional filtering.\n *\n * Results are ordered by reviewed_at descending (most recent first).\n */\nexport async function getReviewsForUser(\n db: Database,\n userId: string,\n options?: ListReviewsOptions,\n): Promise<ReviewLog[]> {\n const conditions = [\"user_id = ?\"];\n const params: unknown[] = [userId];\n\n if (options?.after) {\n conditions.push(\"reviewed_at > ?\");\n params.push(options.after);\n }\n if (options?.before) {\n conditions.push(\"reviewed_at < ?\");\n params.push(options.before);\n }\n\n let sql = `SELECT * FROM review_logs WHERE ${conditions.join(\" AND \")} ORDER BY reviewed_at DESC`;\n\n if (options?.limit) {\n sql += \" LIMIT ?\";\n params.push(options.limit);\n }\n\n return (await db.prepare(sql).all(...params)) as ReviewLog[];\n}\n","/**\n * Session repository — typed wrappers around sessions and session_steps.\n *\n * A session represents a work+learning episode. Steps within a session\n * record which tokens were touched and by whom (user or agent).\n */\n\nimport { ulid } from \"ulid\";\nimport type { Database } from \"../db/types.js\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport type ExecutionContext = \"shell\" | \"ui\" | \"reallife\";\n\nexport interface Session {\n id: string;\n user_id: string;\n task: string;\n execution_context: ExecutionContext;\n started_at: string;\n completed_at: string | null;\n}\n\nexport interface SessionStep {\n id: string;\n session_id: string;\n token_id: string;\n done_by: \"user\" | \"agent\";\n rating: number | null; // 1-4 or null\n notes: string | null;\n created_at: string;\n}\n\nexport interface CreateSessionInput {\n user_id: string;\n task: string;\n execution_context?: ExecutionContext;\n}\n\nexport interface LogStepInput {\n session_id: string;\n token_id: string;\n done_by: \"user\" | \"agent\";\n rating?: number | null;\n notes?: string | null;\n}\n\n/** A step joined with its token details, returned by getSessionSummary. */\nexport interface StepWithToken extends SessionStep {\n slug: string;\n concept: string;\n domain: string;\n bloom_level: number;\n}\n\nexport interface SessionSummary {\n session: Session;\n steps: StepWithToken[];\n}\n\n// ── Functions ────────────────────────────────────────────────────────────────\n\n/**\n * Start a new session. Returns the created session.\n *\n * Ported from the PoC's start-session command.\n */\nexport async function startSession(\n db: Database,\n input: CreateSessionInput,\n): Promise<Session> {\n const id = ulid();\n const now = new Date().toISOString();\n const ctx = input.execution_context ?? \"shell\";\n\n await db\n .prepare(\n `INSERT INTO sessions (id, user_id, task, execution_context, started_at)\n VALUES (?, ?, ?, ?, ?)`,\n )\n .run(id, input.user_id, input.task, ctx, now);\n\n return (await db\n .prepare(\"SELECT * FROM sessions WHERE id = ?\")\n .get(id)) as Session;\n}\n\n/**\n * End a session by setting its completed_at timestamp.\n *\n * Throws if the session does not exist or is already completed.\n *\n * Ported from the PoC's end-session command.\n */\nexport async function endSession(\n db: Database,\n sessionId: string,\n): Promise<Session> {\n const session = (await db\n .prepare(\"SELECT * FROM sessions WHERE id = ?\")\n .get(sessionId)) as Session | undefined;\n\n if (!session) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n if (session.completed_at) {\n throw new Error(`Session already completed: ${sessionId}`);\n }\n\n const now = new Date().toISOString();\n await db\n .prepare(\"UPDATE sessions SET completed_at = ? WHERE id = ?\")\n .run(now, sessionId);\n\n return (await db\n .prepare(\"SELECT * FROM sessions WHERE id = ?\")\n .get(sessionId)) as Session;\n}\n\n/**\n * Log a step within a session.\n *\n * Validates that done_by is 'user' or 'agent' and that the rating\n * (if provided) is between 1 and 4.\n *\n * Ported from the PoC's log-step command.\n */\nexport async function logStep(\n db: Database,\n input: LogStepInput,\n): Promise<SessionStep> {\n if (input.done_by !== \"user\" && input.done_by !== \"agent\") {\n throw new Error(\n `done_by must be 'user' or 'agent', got '${input.done_by}'`,\n );\n }\n if (input.rating != null && (input.rating < 1 || input.rating > 4)) {\n throw new Error(`Rating must be between 1 and 4, got ${input.rating}`);\n }\n\n // Verify the session exists\n const session = await db\n .prepare(\"SELECT id FROM sessions WHERE id = ?\")\n .get(input.session_id);\n if (!session) {\n throw new Error(`Session not found: ${input.session_id}`);\n }\n\n const id = ulid();\n const now = new Date().toISOString();\n\n await db\n .prepare(\n `INSERT INTO session_steps (id, session_id, token_id, done_by, rating, notes, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n id,\n input.session_id,\n input.token_id,\n input.done_by,\n input.rating ?? null,\n input.notes ?? null,\n now,\n );\n\n return (await db\n .prepare(\"SELECT * FROM session_steps WHERE id = ?\")\n .get(id)) as SessionStep;\n}\n\n/**\n * Get a full session summary: the session record plus all steps\n * joined with their token details.\n *\n * Ported from the PoC's session-summary command.\n * Throws if the session does not exist.\n */\nexport async function getSessionSummary(\n db: Database,\n sessionId: string,\n): Promise<SessionSummary> {\n const session = (await db\n .prepare(\"SELECT * FROM sessions WHERE id = ?\")\n .get(sessionId)) as Session | undefined;\n\n if (!session) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n\n const steps = (await db\n .prepare(\n `SELECT ss.*, t.slug, t.concept, t.domain, t.bloom_level\n FROM session_steps ss\n JOIN tokens t ON t.id = ss.token_id\n WHERE ss.session_id = ?\n ORDER BY ss.created_at ASC`,\n )\n .all(sessionId)) as StepWithToken[];\n\n return { session, steps };\n}\n","/**\n * User settings — key/value store backed by the user_config table.\n */\n\nimport type { Database } from \"../db/types.js\";\n\nexport interface UserSetting {\n key: string;\n value: string;\n updated_at: string;\n}\n\n/** Get a single setting by key. Returns undefined if not set. */\nexport async function getSetting(\n db: Database,\n key: string,\n): Promise<string | undefined> {\n const row = (await db\n .prepare(\"SELECT value FROM user_config WHERE key = ?\")\n .get(key)) as { value: string } | undefined;\n return row?.value;\n}\n\n/** Get all settings as a key-value map. */\nexport async function getAllSettings(\n db: Database,\n): Promise<Record<string, string>> {\n const rows = (await db\n .prepare(\"SELECT key, value FROM user_config ORDER BY key\")\n .all()) as { key: string; value: string }[];\n const map: Record<string, string> = {};\n for (const row of rows) {\n map[row.key] = row.value;\n }\n return map;\n}\n\n/** Get all settings with metadata. */\nexport async function getAllSettingsDetailed(\n db: Database,\n): Promise<UserSetting[]> {\n return (await db\n .prepare(\"SELECT key, value, updated_at FROM user_config ORDER BY key\")\n .all()) as UserSetting[];\n}\n\n/** Set a setting (insert or update). */\nexport async function setSetting(\n db: Database,\n key: string,\n value: string,\n): Promise<void> {\n await db\n .prepare(\n `INSERT INTO user_config (key, value, updated_at)\n VALUES (?, ?, datetime('now'))\n ON CONFLICT(key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at`,\n )\n .run(key, value);\n}\n\n/** Delete a setting. Returns true if it existed. */\nexport async function deleteSetting(\n db: Database,\n key: string,\n): Promise<boolean> {\n const result = await db\n .prepare(\"DELETE FROM user_config WHERE key = ?\")\n .run(key);\n return result.changes > 0;\n}\n","/**\n * Monitor log analyzer — maps observed shell commands to token ratings.\n *\n * Pure functions, no DB or filesystem access. Takes parsed command records\n * and a token-to-pattern mapping, returns ratings with evidence.\n */\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface MonitorEvent {\n type: \"command_start\" | \"command_end\" | \"monitor_meta\";\n ts: string;\n seq?: number;\n pid?: number;\n command?: string;\n cwd?: string;\n exit_code?: number;\n event?: \"start\" | \"stop\";\n session_id?: string;\n shell?: string;\n}\n\nexport interface CommandRecord {\n seq: number;\n pid: number;\n command: string;\n cwd: string;\n startedAt: string;\n endedAt: string | null;\n durationMs: number | null;\n exitCode: number | null;\n}\n\nexport interface TokenPattern {\n slug: string;\n patterns: string[]; // command prefixes or regex strings\n}\n\nexport interface ObservationRating {\n tokenSlug: string;\n rating: 1 | 2 | 3 | 4 | null;\n confidence: \"high\" | \"medium\" | \"low\";\n evidence: {\n matchedCommands: number;\n helpSeeking: boolean;\n errorCount: number;\n selfCorrections: number;\n medianGapMs: number | null;\n thinkingGapMs: number | null;\n };\n matchedCommandTexts: string[];\n}\n\nexport interface AnalysisResult {\n ratings: ObservationRating[];\n unmatchedCommands: string[];\n timeSpan: { start: string; end: string; durationMs: number } | null;\n}\n\n// ── Parsing ──────────────────────────────────────────────────────────────────\n\n/**\n * Parse a JSONL string into MonitorEvent objects.\n * Skips malformed lines silently.\n */\nexport function parseMonitorLog(jsonl: string): MonitorEvent[] {\n const events: MonitorEvent[] = [];\n for (const line of jsonl.split(\"\\n\")) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n try {\n events.push(JSON.parse(trimmed) as MonitorEvent);\n } catch {\n // skip malformed lines\n }\n }\n return events;\n}\n\n/**\n * Pair command_start and command_end events by (pid, seq) into CommandRecords.\n */\nexport function pairCommands(events: MonitorEvent[]): CommandRecord[] {\n const starts = new Map<string, MonitorEvent>();\n const records: CommandRecord[] = [];\n\n for (const e of events) {\n if (e.type === \"command_start\" && e.seq != null) {\n const key = `${e.pid ?? 0}:${e.seq}`;\n starts.set(key, e);\n } else if (e.type === \"command_end\" && e.seq != null) {\n const key = `${e.pid ?? 0}:${e.seq}`;\n const start = starts.get(key);\n if (start) {\n const startMs = new Date(start.ts).getTime();\n const endMs = new Date(e.ts).getTime();\n records.push({\n seq: e.seq,\n pid: e.pid ?? 0,\n command: start.command ?? \"\",\n cwd: start.cwd ?? \"\",\n startedAt: start.ts,\n endedAt: e.ts,\n durationMs: endMs - startMs,\n exitCode: e.exit_code ?? null,\n });\n starts.delete(key);\n }\n }\n }\n\n // Remaining unpaired starts (monitoring stopped mid-command)\n for (const [, start] of starts) {\n records.push({\n seq: start.seq ?? 0,\n pid: start.pid ?? 0,\n command: start.command ?? \"\",\n cwd: start.cwd ?? \"\",\n startedAt: start.ts,\n endedAt: null,\n durationMs: null,\n exitCode: null,\n });\n }\n\n records.sort(\n (a, b) => new Date(a.startedAt).getTime() - new Date(b.startedAt).getTime(),\n );\n return records;\n}\n\n// ── Analysis ─────────────────────────────────────────────────────────────────\n\nconst HELP_PATTERNS = [\"--help\", \"man \", \"tldr \", \"help \"];\nconst HELP_WINDOW_MS = 60_000;\nconst _RETRY_WINDOW_MS = 30_000;\n\nfunction matchesToken(command: string, patterns: string[]): boolean {\n const lower = command.toLowerCase();\n return patterns.some((p) => lower.includes(p.toLowerCase()));\n}\n\nfunction isHelpCommand(command: string): boolean {\n const lower = command.toLowerCase();\n return HELP_PATTERNS.some((p) => lower.includes(p));\n}\n\nfunction commandPrefix(command: string): string {\n return command.split(/\\s+/).slice(0, 2).join(\" \").toLowerCase();\n}\n\nfunction computeMedian(values: number[]): number | null {\n if (values.length === 0) return null;\n const sorted = [...values].sort((a, b) => a - b);\n const mid = Math.floor(sorted.length / 2);\n return sorted.length % 2 !== 0\n ? sorted[mid]\n : (sorted[mid - 1] + sorted[mid]) / 2;\n}\n\n/**\n * Analyze observed commands against token patterns and produce ratings.\n */\nexport function analyzeObservation(\n commands: CommandRecord[],\n tokenPatterns: TokenPattern[],\n): AnalysisResult {\n const matchedSet = new Set<number>(); // indices of commands matched to any token\n const ratings: ObservationRating[] = [];\n\n for (const tp of tokenPatterns) {\n const matchIndices: number[] = [];\n const matchedTexts: string[] = [];\n\n for (let i = 0; i < commands.length; i++) {\n if (matchesToken(commands[i].command, tp.patterns)) {\n matchIndices.push(i);\n matchedTexts.push(commands[i].command);\n matchedSet.add(i);\n }\n }\n\n if (matchIndices.length === 0) {\n ratings.push({\n tokenSlug: tp.slug,\n rating: null,\n confidence: \"low\",\n evidence: {\n matchedCommands: 0,\n helpSeeking: false,\n errorCount: 0,\n selfCorrections: 0,\n medianGapMs: null,\n thinkingGapMs: null,\n },\n matchedCommandTexts: [],\n });\n continue;\n }\n\n // Help-seeking: any help command within HELP_WINDOW_MS before a matched command\n let helpSeeking = false;\n for (const mi of matchIndices) {\n const matchTime = new Date(commands[mi].startedAt).getTime();\n for (let j = 0; j < commands.length; j++) {\n if (j === mi) continue;\n const cmdTime = new Date(commands[j].startedAt).getTime();\n if (cmdTime >= matchTime - HELP_WINDOW_MS && cmdTime < matchTime) {\n if (isHelpCommand(commands[j].command)) {\n helpSeeking = true;\n break;\n }\n }\n }\n if (helpSeeking) break;\n }\n\n // Error count: matched commands with non-zero exit code\n let errorCount = 0;\n for (const mi of matchIndices) {\n if (commands[mi].exitCode != null && commands[mi].exitCode !== 0) {\n errorCount++;\n }\n }\n\n // Self-corrections: same command prefix run multiple times with different args\n let selfCorrections = 0;\n const prefixGroups = new Map<string, number>();\n for (const mi of matchIndices) {\n const prefix = commandPrefix(commands[mi].command);\n prefixGroups.set(prefix, (prefixGroups.get(prefix) ?? 0) + 1);\n }\n for (const count of prefixGroups.values()) {\n if (count > 1) selfCorrections += count - 1;\n }\n\n // Speed: inter-command gaps between matched commands\n const gaps: number[] = [];\n for (let k = 1; k < matchIndices.length; k++) {\n const prev = commands[matchIndices[k - 1]];\n const curr = commands[matchIndices[k]];\n if (prev.endedAt) {\n const gap =\n new Date(curr.startedAt).getTime() - new Date(prev.endedAt).getTime();\n if (gap >= 0) gaps.push(gap);\n }\n }\n\n // Thinking gap: time before first matched command from previous command's end\n let thinkingGapMs: number | null = null;\n const firstMatchIdx = matchIndices[0];\n if (firstMatchIdx > 0) {\n const prev = commands[firstMatchIdx - 1];\n if (prev.endedAt) {\n thinkingGapMs =\n new Date(commands[firstMatchIdx].startedAt).getTime() -\n new Date(prev.endedAt).getTime();\n }\n }\n\n const medianGapMs = computeMedian(gaps);\n\n // Determine rating\n const rating = inferRating({\n helpSeeking,\n errorCount,\n selfCorrections,\n medianGapMs,\n thinkingGapMs,\n matchedCommands: matchIndices.length,\n });\n\n // Confidence: more matched commands = higher confidence\n const confidence =\n matchIndices.length >= 3\n ? \"high\"\n : matchIndices.length >= 2\n ? \"medium\"\n : \"low\";\n\n ratings.push({\n tokenSlug: tp.slug,\n rating,\n confidence,\n evidence: {\n matchedCommands: matchIndices.length,\n helpSeeking,\n errorCount,\n selfCorrections,\n medianGapMs,\n thinkingGapMs,\n },\n matchedCommandTexts: matchedTexts,\n });\n }\n\n // Unmatched commands\n const unmatchedCommands: string[] = [];\n for (let i = 0; i < commands.length; i++) {\n if (!matchedSet.has(i) && !isHelpCommand(commands[i].command)) {\n unmatchedCommands.push(commands[i].command);\n }\n }\n\n // Time span\n let timeSpan: AnalysisResult[\"timeSpan\"] = null;\n if (commands.length > 0) {\n const first = commands[0];\n const last = commands[commands.length - 1];\n const endTs = last.endedAt ?? last.startedAt;\n timeSpan = {\n start: first.startedAt,\n end: endTs,\n durationMs:\n new Date(endTs).getTime() - new Date(first.startedAt).getTime(),\n };\n }\n\n return { ratings, unmatchedCommands, timeSpan };\n}\n\n// ── Rating Inference ─────────────────────────────────────────────────────────\n\ninterface RatingSignals {\n helpSeeking: boolean;\n errorCount: number;\n selfCorrections: number;\n medianGapMs: number | null;\n thinkingGapMs: number | null;\n matchedCommands: number;\n}\n\nfunction inferRating(signals: RatingSignals): 1 | 2 | 3 | 4 {\n const {\n helpSeeking,\n errorCount,\n selfCorrections,\n medianGapMs,\n thinkingGapMs,\n } = signals;\n\n // Count negative signals\n let negatives = 0;\n if (helpSeeking) negatives += 2;\n if (errorCount >= 3) negatives += 3;\n else if (errorCount >= 1) negatives += 1;\n if (selfCorrections >= 2) negatives += 2;\n else if (selfCorrections >= 1) negatives += 1;\n if (medianGapMs != null && medianGapMs > 30_000) negatives += 2;\n else if (medianGapMs != null && medianGapMs > 10_000) negatives += 1;\n if (thinkingGapMs != null && thinkingGapMs > 30_000) negatives += 1;\n\n if (negatives >= 5) return 1;\n if (negatives >= 3) return 2;\n if (negatives >= 1) return 3;\n return 4;\n}\n","/**\n * Monitor I/O — read/write JSONL files for shell observation.\n *\n * Monitor logs live at ~/.zam/monitor/<session-id>.jsonl.\n * Separated from analyzer.ts so the analyzer remains pure-function testable.\n */\n\nimport {\n appendFileSync,\n existsSync,\n mkdirSync,\n readFileSync,\n statSync,\n} from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { MonitorEvent } from \"./analyzer.js\";\nimport { parseMonitorLog } from \"./analyzer.js\";\n\nconst MONITOR_DIR = join(homedir(), \".zam\", \"monitor\");\n\n/** Get the monitor directory path. */\nexport function getMonitorDir(): string {\n return MONITOR_DIR;\n}\n\n/** Get the JSONL file path for a session. */\nexport function getMonitorPath(sessionId: string): string {\n return join(MONITOR_DIR, `${sessionId}.jsonl`);\n}\n\n/** Ensure the monitor directory exists (mode 0700 for privacy). */\nexport function ensureMonitorDir(): void {\n if (!existsSync(MONITOR_DIR)) {\n mkdirSync(MONITOR_DIR, { recursive: true, mode: 0o700 });\n }\n}\n\n/** Append a single event to the session's JSONL file. */\nexport function writeMonitorEvent(\n sessionId: string,\n event: MonitorEvent,\n): void {\n ensureMonitorDir();\n const path = getMonitorPath(sessionId);\n appendFileSync(path, `${JSON.stringify(event)}\\n`);\n}\n\n/** Read and parse all events from a session's monitor log. */\nexport function readMonitorLog(sessionId: string): MonitorEvent[] {\n const path = getMonitorPath(sessionId);\n if (!existsSync(path)) {\n return [];\n }\n const content = readFileSync(path, \"utf-8\");\n return parseMonitorLog(content);\n}\n\n/** Check if a monitor log exists for a session. */\nexport function monitorLogExists(sessionId: string): boolean {\n return existsSync(getMonitorPath(sessionId));\n}\n\n/** Get basic stats about a monitor log without full parsing. */\nexport function getMonitorLogStats(sessionId: string): {\n exists: boolean;\n sizeBytes: number;\n lineCount: number;\n} {\n const path = getMonitorPath(sessionId);\n if (!existsSync(path)) {\n return { exists: false, sizeBytes: 0, lineCount: 0 };\n }\n const stat = statSync(path);\n const content = readFileSync(path, \"utf-8\");\n const lineCount = content.split(\"\\n\").filter((l) => l.trim()).length;\n return { exists: true, sizeBytes: stat.size, lineCount };\n}\n","/**\n * Session synthesis connects shell observation to durable learning state.\n *\n * A preview analyzes monitor commands without mutating the database. Applying\n * one confirmed candidate updates the card, review log, session step, blocking\n * state, and synthesis audit record in a single transaction.\n */\n\nimport { ulid } from \"ulid\";\nimport type { Database } from \"../db/types.js\";\nimport { listAgentSkills } from \"../models/agent-skill.js\";\nimport { ensureCard } from \"../models/card.js\";\nimport { getPrerequisites } from \"../models/prerequisite.js\";\nimport type { Session } from \"../models/session.js\";\nimport { logStep } from \"../models/session.js\";\nimport type { Token } from \"../models/token.js\";\nimport { getTokenBySlug } from \"../models/token.js\";\nimport { evaluateRatingWithinTransaction } from \"../recall/evaluator.js\";\nimport { cascadeBlock } from \"../scheduler/blocker.js\";\nimport type { Rating } from \"../scheduler/fsrs.js\";\nimport type {\n CommandRecord,\n ObservationRating,\n TokenPattern,\n} from \"./analyzer.js\";\nimport { analyzeObservation, pairCommands } from \"./analyzer.js\";\nimport { readMonitorLog } from \"./monitor-io.js\";\n\nexport type SynthesisConfidence = \"medium\" | \"high\";\n\nexport interface SessionSynthesisCandidate {\n tokenId: string;\n tokenSlug: string;\n concept: string;\n domain: string;\n inferredRating: Rating;\n confidence: SynthesisConfidence;\n evidence: ObservationRating[\"evidence\"];\n matchedCommandTexts: string[];\n}\n\nexport interface PrepareSessionSynthesisInput {\n sessionId: string;\n explicitPatterns?: TokenPattern[];\n minConfidence?: SynthesisConfidence;\n /** Test and integration hook; normal callers read the monitor log. */\n commands?: CommandRecord[];\n}\n\nexport interface SessionSynthesisPreview {\n sessionId: string;\n userId: string;\n patternCount: number;\n commandCount: number;\n alreadyApplied: number;\n skippedLowConfidence: number;\n candidates: SessionSynthesisCandidate[];\n unmatchedCommands: string[];\n timeSpan: {\n start: string;\n end: string;\n durationMs: number;\n } | null;\n}\n\nexport interface SessionSynthesisEvidence {\n signals: ObservationRating[\"evidence\"];\n matchedCommandTexts: string[];\n}\n\nexport interface SessionSynthesisRecord {\n session_id: string;\n token_id: string;\n card_id: string;\n inferred_rating: Rating;\n confirmed_rating: Rating;\n confidence: SynthesisConfidence;\n evidence: SessionSynthesisEvidence;\n review_log_id: string;\n session_step_id: string;\n created_at: string;\n}\n\ninterface SessionSynthesisRow extends Omit<SessionSynthesisRecord, \"evidence\"> {\n evidence: string;\n}\n\nexport interface ApplySessionSynthesisInput {\n sessionId: string;\n tokenSlug: string;\n inferredRating: Rating;\n confirmedRating: Rating;\n confidence: SynthesisConfidence;\n evidence: ObservationRating[\"evidence\"];\n matchedCommandTexts: string[];\n}\n\nexport interface ApplySessionSynthesisResult {\n applied: boolean;\n record: SessionSynthesisRecord;\n blocked?: Awaited<ReturnType<typeof cascadeBlock>>;\n}\n\nfunction parseSynthesisRow(row: SessionSynthesisRow): SessionSynthesisRecord {\n return {\n ...row,\n evidence: JSON.parse(row.evidence) as SessionSynthesisEvidence,\n };\n}\n\nfunction confidenceRank(confidence: ObservationRating[\"confidence\"]): number {\n return confidence === \"high\" ? 2 : confidence === \"medium\" ? 1 : 0;\n}\n\nfunction normalizeSkillStep(step: string): string[] {\n const codeSpans = [...step.matchAll(/`([^`]+)`/g)]\n .map((match) => match[1].trim())\n .filter(Boolean);\n if (codeSpans.length > 0) return codeSpans;\n\n const normalized = step\n .trim()\n .replace(/^(?:[-*]|\\d+[.)])\\s+/, \"\")\n .replace(/^(?:run|execute)\\s+/i, \"\")\n .replace(/^`|`$/g, \"\")\n .trim();\n return normalized ? [normalized] : [];\n}\n\nasync function buildSkillPatterns(db: Database): Promise<TokenPattern[]> {\n const byToken = new Map<string, Set<string>>();\n\n for (const skill of await listAgentSkills(db)) {\n if (skill.token_slugs.length !== 1) continue;\n const patterns = skill.steps.flatMap(normalizeSkillStep);\n for (const slug of skill.token_slugs) {\n const tokenPatterns = byToken.get(slug) ?? new Set<string>();\n for (const pattern of patterns) tokenPatterns.add(pattern);\n byToken.set(slug, tokenPatterns);\n }\n }\n\n return [...byToken.entries()].map(([slug, patterns]) => ({\n slug,\n patterns: [...patterns],\n }));\n}\n\nfunction mergePatterns(\n automatic: TokenPattern[],\n explicit: TokenPattern[],\n): TokenPattern[] {\n const merged = new Map<string, Set<string>>();\n for (const entry of [...automatic, ...explicit]) {\n const patterns = merged.get(entry.slug) ?? new Set<string>();\n for (const pattern of entry.patterns) {\n const trimmed = pattern.trim();\n if (trimmed) patterns.add(trimmed);\n }\n merged.set(entry.slug, patterns);\n }\n\n return [...merged.entries()]\n .filter(([, patterns]) => patterns.size > 0)\n .map(([slug, patterns]) => ({ slug, patterns: [...patterns] }));\n}\n\nasync function getSession(db: Database, sessionId: string): Promise<Session> {\n const session = (await db\n .prepare(\"SELECT * FROM sessions WHERE id = ?\")\n .get(sessionId)) as Session | undefined;\n if (!session) throw new Error(`Session not found: ${sessionId}`);\n return session;\n}\n\nexport async function getSessionSynthesisRecords(\n db: Database,\n sessionId: string,\n): Promise<SessionSynthesisRecord[]> {\n const rows = (await db\n .prepare(\n \"SELECT * FROM session_syntheses WHERE session_id = ? ORDER BY created_at\",\n )\n .all(sessionId)) as SessionSynthesisRow[];\n return rows.map(parseSynthesisRow);\n}\n\nexport async function prepareSessionSynthesis(\n db: Database,\n input: PrepareSessionSynthesisInput,\n): Promise<SessionSynthesisPreview> {\n const session = await getSession(db, input.sessionId);\n const patterns = mergePatterns(\n await buildSkillPatterns(db),\n input.explicitPatterns ?? [],\n );\n\n const validPatterns: TokenPattern[] = [];\n const tokens = new Map<string, Token>();\n for (const pattern of patterns) {\n const token = await getTokenBySlug(db, pattern.slug);\n if (!token || token.deprecated_at) continue;\n validPatterns.push(pattern);\n tokens.set(pattern.slug, token);\n }\n\n const commands =\n input.commands ?? pairCommands(readMonitorLog(input.sessionId));\n const analysis = analyzeObservation(commands, validPatterns);\n const applied = new Set(\n (await getSessionSynthesisRecords(db, input.sessionId)).map(\n (record) => record.token_id,\n ),\n );\n const minRank = confidenceRank(input.minConfidence ?? \"medium\");\n let skippedLowConfidence = 0;\n const candidates: SessionSynthesisCandidate[] = [];\n\n for (const rating of analysis.ratings) {\n const token = tokens.get(rating.tokenSlug);\n if (!token || rating.rating == null || applied.has(token.id)) continue;\n if (confidenceRank(rating.confidence) < minRank) {\n skippedLowConfidence++;\n continue;\n }\n\n candidates.push({\n tokenId: token.id,\n tokenSlug: token.slug,\n concept: token.concept,\n domain: token.domain,\n inferredRating: rating.rating,\n confidence: rating.confidence as SynthesisConfidence,\n evidence: rating.evidence,\n matchedCommandTexts: rating.matchedCommandTexts,\n });\n }\n\n return {\n sessionId: session.id,\n userId: session.user_id,\n patternCount: validPatterns.length,\n commandCount: commands.length,\n alreadyApplied: applied.size,\n skippedLowConfidence,\n candidates,\n unmatchedCommands: analysis.unmatchedCommands,\n timeSpan: analysis.timeSpan,\n };\n}\n\nexport async function applySessionSynthesis(\n db: Database,\n input: ApplySessionSynthesisInput,\n): Promise<ApplySessionSynthesisResult> {\n return db.transaction(async (tx) => {\n const session = await getSession(tx, input.sessionId);\n const token = await getTokenBySlug(tx, input.tokenSlug);\n if (!token || token.deprecated_at) {\n throw new Error(`Active token not found: ${input.tokenSlug}`);\n }\n\n const existing = (await tx\n .prepare(\n \"SELECT * FROM session_syntheses WHERE session_id = ? AND token_id = ?\",\n )\n .get(session.id, token.id)) as SessionSynthesisRow | undefined;\n if (existing) {\n return { applied: false, record: parseSynthesisRow(existing) };\n }\n\n const card = await ensureCard(tx, token.id, session.user_id);\n const reviewLogId = ulid();\n await evaluateRatingWithinTransaction(tx, {\n cardId: card.id,\n tokenId: token.id,\n userId: session.user_id,\n rating: input.confirmedRating,\n sessionId: session.id,\n reviewLogId,\n });\n\n let blocked: Awaited<ReturnType<typeof cascadeBlock>> | undefined;\n if (input.confirmedRating === 1) {\n const prerequisites = await getPrerequisites(tx, token.id);\n if (prerequisites.length > 0) {\n blocked = await cascadeBlock(tx, session.user_id, token.slug);\n }\n }\n\n const notes = `Observation synthesis (${input.confidence}, inferred ${input.inferredRating}): ${input.matchedCommandTexts.slice(0, 3).join(\" | \")}`;\n const step = await logStep(tx, {\n session_id: session.id,\n token_id: token.id,\n done_by: \"user\",\n rating: input.confirmedRating,\n notes,\n });\n\n const evidence: SessionSynthesisEvidence = {\n signals: input.evidence,\n matchedCommandTexts: input.matchedCommandTexts,\n };\n const now = new Date().toISOString();\n await tx\n .prepare(\n `INSERT INTO session_syntheses (\n session_id, token_id, card_id, inferred_rating, confirmed_rating,\n confidence, evidence, review_log_id, session_step_id, created_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n session.id,\n token.id,\n card.id,\n input.inferredRating,\n input.confirmedRating,\n input.confidence,\n JSON.stringify(evidence),\n reviewLogId,\n step.id,\n now,\n );\n\n const record = (await tx\n .prepare(\n \"SELECT * FROM session_syntheses WHERE session_id = ? AND token_id = ?\",\n )\n .get(session.id, token.id)) as SessionSynthesisRow;\n\n return {\n applied: true,\n record: parseSynthesisRow(record),\n blocked,\n };\n });\n}\n","/**\n * Rating Evaluator\n *\n * Processes a user's self-assessment rating after a recall attempt.\n * Coordinates between FSRS scheduling, review logging, and blocking.\n */\n\nimport { ulid } from \"ulid\";\nimport type { Database } from \"../db/types.js\";\nimport { updateCard } from \"../models/card.js\";\nimport type { Rating, SchedulingCard } from \"../scheduler/fsrs.js\";\nimport { createFSRS } from \"../scheduler/fsrs.js\";\n\nexport interface EvaluateInput {\n cardId: string;\n tokenId: string;\n userId: string;\n rating: Rating;\n sessionId?: string;\n responseTimeMs?: number;\n reviewLogId?: string;\n}\n\nexport interface EvaluateResult {\n nextDueAt: string;\n stability: number;\n difficulty: number;\n state: string;\n scheduledDays: number;\n reps: number;\n lapses: number;\n}\n\n/**\n * Process a rating: update the card via FSRS, log the review.\n * Returns the updated scheduling state.\n *\n * Note: blocking logic (cascade-block) is handled separately by the caller\n * when rating === 1 and the token has prerequisites.\n */\nexport async function evaluateRating(\n db: Database,\n input: EvaluateInput,\n): Promise<EvaluateResult> {\n return db.transaction((tx) => evaluateRatingWithinTransaction(tx, input));\n}\n\n/**\n * Apply a rating using a transaction already owned by the caller.\n * This is used when prerequisite blocking must commit with the review.\n */\nexport async function evaluateRatingWithinTransaction(\n db: Database,\n input: EvaluateInput,\n): Promise<EvaluateResult> {\n // Get current card state\n const card = (await db\n .prepare(\"SELECT * FROM cards WHERE id = ?\")\n .get(input.cardId)) as\n | {\n stability: number;\n difficulty: number;\n elapsed_days: number;\n scheduled_days: number;\n reps: number;\n lapses: number;\n state: string;\n due_at: string;\n last_review_at: string | null;\n }\n | undefined;\n\n if (!card) {\n throw new Error(`Card not found: ${input.cardId}`);\n }\n\n const now = new Date();\n const fsrs = createFSRS();\n\n // Build scheduling card from DB state\n const schedulingCard: SchedulingCard = {\n stability: card.stability,\n difficulty: card.difficulty,\n elapsedDays: card.elapsed_days,\n scheduledDays: card.scheduled_days,\n reps: card.reps,\n lapses: card.lapses,\n state: card.state as SchedulingCard[\"state\"],\n dueAt: new Date(card.due_at),\n lastReviewAt: card.last_review_at ? new Date(card.last_review_at) : null,\n };\n\n // Run FSRS\n const updated = fsrs.schedule(schedulingCard, input.rating, now);\n\n // Update the card in the DB\n await updateCard(db, input.cardId, {\n stability: updated.stability,\n difficulty: updated.difficulty,\n elapsed_days: updated.elapsedDays,\n scheduled_days: updated.scheduledDays,\n reps: updated.reps,\n lapses: updated.lapses,\n state: updated.state,\n due_at: updated.dueAt.toISOString(),\n last_review_at: now.toISOString(),\n });\n\n // Log the review (immutable)\n const reviewLogId = input.reviewLogId ?? ulid();\n await db\n .prepare(\n `INSERT INTO review_logs (id, card_id, token_id, user_id, rating, response_time_ms, reviewed_at, scheduled_at, session_id)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n reviewLogId,\n input.cardId,\n input.tokenId,\n input.userId,\n input.rating,\n input.responseTimeMs ?? null,\n now.toISOString(),\n card.due_at,\n input.sessionId ?? null,\n );\n\n return {\n nextDueAt: updated.dueAt.toISOString(),\n stability: updated.stability,\n difficulty: updated.difficulty,\n state: updated.state,\n scheduledDays: updated.scheduledDays,\n reps: updated.reps,\n lapses: updated.lapses,\n };\n}\n","/**\n * FSRS-5 — Free Spaced Repetition Scheduler (v5)\n *\n * Pure-function implementation of the FSRS algorithm that replaces\n * the PoC's SM-2 scheduler. This is the mathematical heart of ZAM's\n * spaced-repetition engine.\n *\n * Reference: https://github.com/open-spaced-repetition/fsrs4anki/wiki/The-Algorithm\n */\n\n// ── Rating scale ────────────────────────────────────────────────────────────\n\n/** 1 = Again (forgot), 2 = Hard, 3 = Good, 4 = Easy */\nexport type Rating = 1 | 2 | 3 | 4;\n\n// ── Card states ─────────────────────────────────────────────────────────────\n\nexport type CardState = \"new\" | \"learning\" | \"review\" | \"relearning\";\n\n// ── Scheduling card ─────────────────────────────────────────────────────────\n\nexport interface SchedulingCard {\n /** Memory stability in days — expected half-life of recall probability. */\n stability: number;\n /** Intrinsic difficulty on a 1–10 scale. */\n difficulty: number;\n /** Days elapsed since the last review. */\n elapsedDays: number;\n /** Currently scheduled interval in days. */\n scheduledDays: number;\n /** Count of successful consecutive reviews. */\n reps: number;\n /** Times the card was forgotten (rated Again). */\n lapses: number;\n /** Current learning state. */\n state: CardState;\n /** When the card is next due. */\n dueAt: Date;\n /** When the card was last reviewed (null for new cards). */\n lastReviewAt: Date | null;\n}\n\n// ── Parameters ──────────────────────────────────────────────────────────────\n\nexport interface FSRSParameters {\n /** 19 optimised weight parameters (w0 – w18). */\n w: number[];\n /** Target retention rate, e.g. 0.9 means we aim for 90% recall. */\n requestRetention: number;\n}\n\n// ── FSRS-5 default weights ──────────────────────────────────────────────────\n\nconst DEFAULT_W: number[] = [\n 0.4072,\n 1.1829,\n 3.1262,\n 15.4722, // w0–w3: initial stability per rating\n 7.2102,\n 0.5316,\n 1.0651, // w4–w6: difficulty\n 0.0092,\n 1.5988,\n 0.1176,\n 1.0014, // w7–w10: stability after forgetting\n 2.0032,\n 0.0266,\n 0.3077,\n 0.15, // w11–w14: stability increase\n 0.0,\n 2.7849,\n 0.3477,\n 0.6831, // w15–w18: additional parameters\n];\n\nconst DEFAULT_REQUEST_RETENTION = 0.9;\n\n// ── FSRS object returned by the factory ─────────────────────────────────────\n\nexport interface FSRS {\n /** Return a fully updated card after applying a rating. Pure function. */\n schedule(card: SchedulingCard, rating: Rating, now?: Date): SchedulingCard;\n /** The parameters baked into this instance. */\n readonly params: Readonly<FSRSParameters>;\n}\n\n// ── Helpers ─────────────────────────────────────────────────────────────────\n\n/** Clamp a number to [lo, hi]. */\nfunction clamp(value: number, lo: number, hi: number): number {\n return Math.min(hi, Math.max(lo, value));\n}\n\n/** Days between two Date objects (may be fractional). */\nfunction daysBetween(a: Date, b: Date): number {\n return (b.getTime() - a.getTime()) / (1000 * 60 * 60 * 24);\n}\n\n// ── Core FSRS-5 formulas ────────────────────────────────────────────────────\n\n/**\n * Initial stability for a brand-new card.\n * S₀ = w[rating - 1]\n */\nfunction initialStability(w: number[], rating: Rating): number {\n return w[rating - 1];\n}\n\n/**\n * Initial difficulty for a brand-new card.\n * D₀(rating) = w4 - exp(w5 * (rating - 1)) + 1\n * Clamped to [1, 10].\n */\nfunction initialDifficulty(w: number[], rating: Rating): number {\n return clamp(w[4] - Math.exp(w[5] * (rating - 1)) + 1, 1, 10);\n}\n\n/**\n * Updated difficulty after a review.\n * D' = w7 * D₀(3) + (1 - w7) * (D - w6 * (rating - 3))\n * Clamped to [1, 10].\n */\nfunction nextDifficulty(w: number[], d: number, rating: Rating): number {\n const d0ForGood = initialDifficulty(w, 3);\n const updated = w[7] * d0ForGood + (1 - w[7]) * (d - w[6] * (rating - 3));\n return clamp(updated, 1, 10);\n}\n\n/**\n * Retrievability — probability of recall.\n * R = (1 + elapsed / (9 * S))^(-1)\n */\nfunction retrievability(elapsed: number, stability: number): number {\n if (stability <= 0) return 0;\n return (1 + elapsed / (9 * stability)) ** -1;\n}\n\n/**\n * Stability after a **successful** recall (rating >= 2).\n * S' = S * (exp(w8) * (11 - D) * S^(-w9) * (exp(w10 * (1 - R)) - 1) * hard_penalty * easy_bonus + 1)\n */\nfunction stabilityAfterSuccess(\n w: number[],\n s: number,\n d: number,\n r: number,\n rating: Rating,\n): number {\n const hardPenalty = rating === 2 ? w[15] : 1;\n const easyBonus = rating === 4 ? w[16] : 1;\n\n const inner =\n Math.exp(w[8]) *\n (11 - d) *\n s ** -w[9] *\n (Math.exp(w[10] * (1 - r)) - 1) *\n hardPenalty *\n easyBonus;\n\n return s * (inner + 1);\n}\n\n/**\n * Stability after **forgetting** (rating = 1).\n * S' = w11 * D^(-w12) * ((S+1)^w13 - 1) * exp(w14 * (1 - R))\n */\nfunction stabilityAfterForgetting(\n w: number[],\n s: number,\n d: number,\n r: number,\n): number {\n return (\n w[11] * d ** -w[12] * ((s + 1) ** w[13] - 1) * Math.exp(w[14] * (1 - r))\n );\n}\n\n/**\n * Optimal interval given new stability and target retention.\n * I = 9 * S' * (1/requestRetention - 1)\n * Minimum 1 day.\n */\nfunction nextInterval(stability: number, requestRetention: number): number {\n const interval = 9 * stability * (1 / requestRetention - 1);\n return Math.max(1, Math.round(interval));\n}\n\n// ── Factory ─────────────────────────────────────────────────────────────────\n\n/**\n * Create a new card with default initial values.\n */\nexport function createEmptyCard(now?: Date): SchedulingCard {\n const ts = now ?? new Date();\n return {\n stability: 0,\n difficulty: 0,\n elapsedDays: 0,\n scheduledDays: 0,\n reps: 0,\n lapses: 0,\n state: \"new\",\n dueAt: ts,\n lastReviewAt: null,\n };\n}\n\n/**\n * Create an FSRS scheduler instance.\n *\n * All scheduling is done through pure functions — no side effects,\n * no database access, no mutation of the input card.\n */\nexport function createFSRS(params?: Partial<FSRSParameters>): FSRS {\n const resolvedParams: FSRSParameters = {\n w: params?.w ?? [...DEFAULT_W],\n requestRetention: params?.requestRetention ?? DEFAULT_REQUEST_RETENTION,\n };\n\n function schedule(\n card: SchedulingCard,\n rating: Rating,\n now?: Date,\n ): SchedulingCard {\n const reviewTime = now ?? new Date();\n const w = resolvedParams.w;\n\n // Compute elapsed days since last review (or 0 for new cards).\n const elapsed =\n card.lastReviewAt !== null\n ? Math.max(0, daysBetween(card.lastReviewAt, reviewTime))\n : 0;\n\n // ── New card ──────────────────────────────────────────────────────\n if (card.state === \"new\") {\n const s = initialStability(w, rating);\n const d = initialDifficulty(w, rating);\n const interval = nextInterval(s, resolvedParams.requestRetention);\n\n const dueAt = new Date(reviewTime);\n dueAt.setDate(dueAt.getDate() + interval);\n\n // New cards always move to \"learning\" after first rating.\n\n return {\n stability: s,\n difficulty: d,\n elapsedDays: 0,\n scheduledDays: interval,\n reps: rating >= 2 ? 1 : 0,\n lapses: rating === 1 ? 1 : 0,\n state: \"learning\",\n dueAt,\n lastReviewAt: reviewTime,\n };\n }\n\n // ── Existing card (learning / review / relearning) ───────────────\n\n const r = retrievability(elapsed, card.stability);\n\n let newStability: number;\n let newDifficulty: number;\n let newReps: number;\n let newLapses: number;\n let newState: CardState;\n\n if (rating === 1) {\n // Forgot — apply forgetting formula\n newStability = stabilityAfterForgetting(\n w,\n card.stability,\n card.difficulty,\n r,\n );\n newDifficulty = nextDifficulty(w, card.difficulty, rating);\n newReps = 0;\n newLapses = card.lapses + 1;\n newState = \"relearning\";\n } else {\n // Recalled — apply success formula\n newStability = stabilityAfterSuccess(\n w,\n card.stability,\n card.difficulty,\n r,\n rating,\n );\n newDifficulty = nextDifficulty(w, card.difficulty, rating);\n newReps = card.reps + 1;\n newLapses = card.lapses;\n // Successful recall transitions any state to review.\n newState = \"review\";\n }\n\n const interval = nextInterval(\n newStability,\n resolvedParams.requestRetention,\n );\n\n const dueAt = new Date(reviewTime);\n dueAt.setDate(dueAt.getDate() + interval);\n\n return {\n stability: newStability,\n difficulty: newDifficulty,\n elapsedDays: elapsed,\n scheduledDays: interval,\n reps: newReps,\n lapses: newLapses,\n state: newState,\n dueAt,\n lastReviewAt: reviewTime,\n };\n }\n\n return {\n schedule,\n params: Object.freeze(resolvedParams),\n };\n}\n","/**\n * Cascade Block & Unblock — prerequisite-aware blocking logic.\n *\n * Ported from the PoC's cascade-block and unblock-ready commands.\n *\n * When a user rates a token as \"forgot\" (rating 1) and that token has\n * prerequisites, we block the token and surface its prerequisites into\n * the active deck. When all prerequisites are met, we unblock.\n */\n\nimport type { Database } from \"../db/types.js\";\nimport { ensureCard } from \"../models/card.js\";\nimport { getPrerequisites } from \"../models/prerequisite.js\";\nimport { getTokenBySlug } from \"../models/token.js\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface CascadeBlockResult {\n blockedSlug: string;\n prerequisites: Array<{ slug: string; concept: string; bloomLevel: number }>;\n}\n\nexport interface UnblockResult {\n unblocked: Array<{ slug: string; concept: string }>;\n}\n\n// ── Functions ────────────────────────────────────────────────────────────────\n\n/**\n * Block a token and surface its prerequisites.\n *\n * Called when a user rates a token as \"forgot\" (rating 1). The token is\n * marked as blocked so it won't appear in review queues. All direct\n * prerequisites are ensured to have cards (unblocked, due now) so they\n * appear in the user's next review session.\n *\n * @param db - Database connection\n * @param userId - The user whose card to block\n * @param tokenSlug - Slug of the token the user forgot\n * @returns Info about what was blocked and which prerequisites were surfaced\n */\nexport async function cascadeBlock(\n db: Database,\n userId: string,\n tokenSlug: string,\n): Promise<CascadeBlockResult> {\n const token = await getTokenBySlug(db, tokenSlug);\n if (!token) {\n throw new Error(`Unknown token slug: ${tokenSlug}`);\n }\n\n const prereqs = await getPrerequisites(db, token.id);\n if (prereqs.length === 0) {\n throw new Error(`Cannot block ${tokenSlug}: token has no prerequisites`);\n }\n\n // Ensure a card exists, then block it\n await ensureCard(db, token.id, userId);\n await db\n .prepare(\"UPDATE cards SET blocked = 1 WHERE token_id = ? AND user_id = ?\")\n .run(token.id, userId);\n\n // Surface all direct prerequisites — ensure cards exist (unblocked, due now)\n const surfaced: Array<{ slug: string; concept: string; bloomLevel: number }> =\n [];\n\n for (const prereq of prereqs) {\n // ensureCard creates a new card if missing (defaults: blocked=0, due_at=now)\n const card = await ensureCard(db, prereq.requires_id, userId);\n\n // If the prerequisite card was somehow blocked with no prereqs of its own,\n // make sure it's unblocked and due now so it surfaces\n if (card.blocked === 1) {\n const prereqOfPrereq = (await db\n .prepare(\"SELECT COUNT(*) as n FROM prerequisites WHERE token_id = ?\")\n .get(prereq.requires_id)) as { n: number };\n\n // Only force-unblock if it has no prerequisites of its own\n if (prereqOfPrereq.n === 0) {\n const now = new Date().toISOString();\n await db\n .prepare(\n \"UPDATE cards SET blocked = 0, due_at = ? WHERE token_id = ? AND user_id = ?\",\n )\n .run(now, prereq.requires_id, userId);\n }\n }\n\n surfaced.push({\n slug: prereq.slug,\n concept: prereq.concept,\n bloomLevel: prereq.bloom_level,\n });\n }\n\n return {\n blockedSlug: tokenSlug,\n prerequisites: surfaced,\n };\n}\n\n/**\n * Scan all blocked cards for a user and unblock any whose prerequisites are met.\n *\n * A blocked card is ready to unblock when ALL of its direct prerequisites have:\n * - reps >= 1 (the user has successfully recalled it at least once)\n * - blocked = 0 (the prerequisite itself is not blocked)\n *\n * If a blocked card has no prerequisites at all, it is unblocked immediately\n * (it was likely blocked in error or its prerequisites were removed).\n *\n * @param db - Database connection\n * @param userId - The user whose blocked cards to check\n * @returns List of cards that were unblocked\n */\nexport async function unblockReady(\n db: Database,\n userId: string,\n): Promise<UnblockResult> {\n const blockedCards = (await db\n .prepare(\n `SELECT c.token_id, t.slug, t.concept\n FROM cards c\n JOIN tokens t ON t.id = c.token_id\n WHERE c.user_id = ? AND c.blocked = 1`,\n )\n .all(userId)) as Array<{\n token_id: string;\n slug: string;\n concept: string;\n }>;\n\n const unblocked: Array<{ slug: string; concept: string }> = [];\n\n for (const card of blockedCards) {\n const totalPrereqs = (await db\n .prepare(\"SELECT COUNT(*) as n FROM prerequisites WHERE token_id = ?\")\n .get(card.token_id)) as { n: number };\n\n const metPrereqs = (await db\n .prepare(\n `SELECT COUNT(*) as n FROM cards c\n JOIN prerequisites p ON p.requires_id = c.token_id\n WHERE p.token_id = ? AND c.user_id = ? AND c.reps >= 1 AND c.blocked = 0`,\n )\n .get(card.token_id, userId)) as { n: number };\n\n if (totalPrereqs.n === 0 || metPrereqs.n === totalPrereqs.n) {\n const now = new Date().toISOString();\n await db\n .prepare(\n \"UPDATE cards SET blocked = 0, due_at = ? WHERE token_id = ? AND user_id = ?\",\n )\n .run(now, card.token_id, userId);\n\n unblocked.push({ slug: card.slug, concept: card.concept });\n }\n }\n\n return { unblocked };\n}\n","/**\n * Shell hook code generation for zsh, bash, and PowerShell.\n *\n * Pure functions that return shell code strings. The CLI command\n * `zam monitor start/stop` calls these and prints to stdout.\n */\n\nfunction psSingleQuoted(value: string): string {\n return `'${value.replace(/'/g, \"''\")}'`;\n}\n\n/**\n * Generate zsh hooks that capture commands to a JSONL file.\n * Uses $EPOCHREALTIME for sub-second timestamp precision.\n */\nexport function generateZshHooks(\n monitorFile: string,\n sessionId: string,\n): string {\n return `\n# ZAM monitor hooks for session ${sessionId}\nexport __ZAM_MONITOR_FILE=\"${monitorFile}\"\nexport __ZAM_MONITOR_SEQ=0\nexport __ZAM_MONITOR_SESSION=\"${sessionId}\"\n\n__zam_ts() {\n if [[ -n \"\\${EPOCHREALTIME:-}\" ]]; then\n local sec=\"\\${EPOCHREALTIME%%.*}\"\n local frac=\"\\${EPOCHREALTIME##*.}\"\n frac=\"\\${frac:0:3}\"\n printf '%s.%sZ' \"$(date -u -r \"$sec\" '+%Y-%m-%dT%H:%M:%S' 2>/dev/null || date -u '+%Y-%m-%dT%H:%M:%S')\" \"$frac\"\n else\n date -u '+%Y-%m-%dT%H:%M:%SZ'\n fi\n}\n\n__zam_preexec() {\n (( __ZAM_MONITOR_SEQ++ ))\n local cmd=\"\\${1//\\\\\"/\\\\\\\\\\\\\"}\"\n local cwd=\"\\${PWD//\\\\\"/\\\\\\\\\\\\\"}\"\n local ts=\"$(__zam_ts)\"\n printf '{\"type\":\"command_start\",\"ts\":\"%s\",\"command\":\"%s\",\"cwd\":\"%s\",\"seq\":%d,\"pid\":%d}\\\\n' \\\\\n \"$ts\" \"$cmd\" \"$cwd\" \"$__ZAM_MONITOR_SEQ\" \"$$\" \\\\\n >> \"$__ZAM_MONITOR_FILE\"\n}\n\n__zam_precmd() {\n local exit_code=$?\n [[ $__ZAM_MONITOR_SEQ -eq 0 ]] && return\n local ts=\"$(__zam_ts)\"\n printf '{\"type\":\"command_end\",\"ts\":\"%s\",\"exit_code\":%d,\"seq\":%d,\"pid\":%d}\\\\n' \\\\\n \"$ts\" \"$exit_code\" \"$__ZAM_MONITOR_SEQ\" \"$$\" \\\\\n >> \"$__ZAM_MONITOR_FILE\"\n}\n\nautoload -Uz add-zsh-hook\nadd-zsh-hook preexec __zam_preexec\nadd-zsh-hook precmd __zam_precmd\n\necho \"ZAM monitor active for session $__ZAM_MONITOR_SESSION\"\n`.trim();\n}\n\n/**\n * Generate bash hooks that capture commands to a JSONL file.\n * Uses DEBUG trap for preexec, PROMPT_COMMAND for precmd.\n */\nexport function generateBashHooks(\n monitorFile: string,\n sessionId: string,\n): string {\n return `\n# ZAM monitor hooks for session ${sessionId}\nexport __ZAM_MONITOR_FILE=\"${monitorFile}\"\nexport __ZAM_MONITOR_SEQ=0\nexport __ZAM_MONITOR_SESSION=\"${sessionId}\"\nexport __ZAM_MONITOR_CMD_ACTIVE=0\n\n__zam_ts() {\n date -u '+%Y-%m-%dT%H:%M:%SZ'\n}\n\n__zam_debug_trap() {\n [[ \"$__ZAM_MONITOR_CMD_ACTIVE\" -eq 1 ]] && return\n __ZAM_MONITOR_CMD_ACTIVE=1\n (( __ZAM_MONITOR_SEQ++ ))\n local cmd=\"\\${BASH_COMMAND//\\\\\"/\\\\\\\\\\\\\"}\"\n local cwd=\"\\${PWD//\\\\\"/\\\\\\\\\\\\\"}\"\n local ts=\"$(__zam_ts)\"\n printf '{\"type\":\"command_start\",\"ts\":\"%s\",\"command\":\"%s\",\"cwd\":\"%s\",\"seq\":%d,\"pid\":%d}\\\\n' \\\\\n \"$ts\" \"$cmd\" \"$cwd\" \"$__ZAM_MONITOR_SEQ\" \"$$\" \\\\\n >> \"$__ZAM_MONITOR_FILE\"\n}\n\n__zam_prompt_cmd() {\n local exit_code=$?\n if [[ \"$__ZAM_MONITOR_CMD_ACTIVE\" -eq 1 ]]; then\n __ZAM_MONITOR_CMD_ACTIVE=0\n local ts=\"$(__zam_ts)\"\n printf '{\"type\":\"command_end\",\"ts\":\"%s\",\"exit_code\":%d,\"seq\":%d,\"pid\":%d}\\\\n' \\\\\n \"$ts\" \"$exit_code\" \"$__ZAM_MONITOR_SEQ\" \"$$\" \\\\\n >> \"$__ZAM_MONITOR_FILE\"\n fi\n}\n\ntrap '__zam_debug_trap' DEBUG\nPROMPT_COMMAND=\"__zam_prompt_cmd;\\${PROMPT_COMMAND:-}\"\n\necho \"ZAM monitor active for session $__ZAM_MONITOR_SESSION\"\n`.trim();\n}\n\n/**\n * Generate PowerShell hooks that capture completed commands to a JSONL file.\n * PowerShell has no zsh-style preexec hook, so this records the most recent\n * history item from the prompt function after each command completes.\n */\nexport function generatePowerShellHooks(\n monitorFile: string,\n sessionId: string,\n): string {\n return `\n# ZAM monitor hooks for session ${sessionId}\n$global:__ZAM_MONITOR_FILE = ${psSingleQuoted(monitorFile)}\n$global:__ZAM_MONITOR_SEQ = 0\n$global:__ZAM_MONITOR_SESSION = ${psSingleQuoted(sessionId)}\n$global:__ZAM_MONITOR_SKIP_NEXT_PROMPT = $true\n\nfunction global:__zam_write_monitor_event {\n param([hashtable]$Event)\n $json = $Event | ConvertTo-Json -Compress -Depth 4\n $utf8NoBom = New-Object System.Text.UTF8Encoding $false\n [System.IO.File]::AppendAllText($global:__ZAM_MONITOR_FILE, $json + [Environment]::NewLine, $utf8NoBom)\n}\n\nfunction global:__zam_iso_utc {\n param([datetime]$Date)\n if ($Date -eq [datetime]::MinValue) {\n return (Get-Date).ToUniversalTime().ToString(\"o\")\n }\n return $Date.ToUniversalTime().ToString(\"o\")\n}\n\nfunction global:__zam_update_last_history_id {\n $history = Get-History -Count 1\n if ($null -ne $history) {\n $global:__ZAM_MONITOR_LAST_HISTORY_ID = $history.Id\n } elseif ($null -eq $global:__ZAM_MONITOR_LAST_HISTORY_ID) {\n $global:__ZAM_MONITOR_LAST_HISTORY_ID = 0\n }\n}\n\nfunction global:__zam_record_last_history {\n param(\n [bool]$Success,\n [object]$NativeExitCode\n )\n\n $history = Get-History -Count 1\n if ($null -eq $history) { return }\n if ($history.Id -le $global:__ZAM_MONITOR_LAST_HISTORY_ID) { return }\n\n $global:__ZAM_MONITOR_LAST_HISTORY_ID = $history.Id\n $global:__ZAM_MONITOR_SEQ += 1\n\n $exitCode = 0\n if (-not $Success) {\n if ($NativeExitCode -is [int] -and $NativeExitCode -ne 0) {\n $exitCode = $NativeExitCode\n } else {\n $exitCode = 1\n }\n }\n\n $cwd = (Get-Location).Path\n __zam_write_monitor_event @{\n type = \"command_start\"\n ts = (__zam_iso_utc $history.StartExecutionTime)\n command = $history.CommandLine\n cwd = $cwd\n seq = $global:__ZAM_MONITOR_SEQ\n pid = $PID\n }\n __zam_write_monitor_event @{\n type = \"command_end\"\n ts = (__zam_iso_utc $history.EndExecutionTime)\n exit_code = $exitCode\n seq = $global:__ZAM_MONITOR_SEQ\n pid = $PID\n }\n}\n\nif (-not (Test-Path function:\\\\__zam_previous_prompt) -and (Test-Path function:\\\\prompt)) {\n Set-Item -Path function:\\\\__zam_previous_prompt -Value (Get-Item function:\\\\prompt).ScriptBlock\n}\n__zam_update_last_history_id\n\nfunction global:prompt {\n $zamSuccess = $?\n $zamNativeExitCode = $global:LASTEXITCODE\n\n if ($global:__ZAM_MONITOR_SKIP_NEXT_PROMPT) {\n __zam_update_last_history_id\n $global:__ZAM_MONITOR_SKIP_NEXT_PROMPT = $false\n } else {\n __zam_record_last_history -Success $zamSuccess -NativeExitCode $zamNativeExitCode\n }\n\n if (Test-Path function:\\\\__zam_previous_prompt) {\n & (Get-Item function:\\\\__zam_previous_prompt).ScriptBlock\n } else {\n \"PS $($executionContext.SessionState.Path.CurrentLocation)$('>' * ($nestedPromptLevel + 1)) \"\n }\n}\n\nWrite-Host \"ZAM monitor active for session $global:__ZAM_MONITOR_SESSION\"\n`.trim();\n}\n\n/** Generate zsh code to remove monitor hooks. */\nexport function generateZshUnhooks(): string {\n return `\n# Remove ZAM monitor hooks\nadd-zsh-hook -d preexec __zam_preexec 2>/dev/null\nadd-zsh-hook -d precmd __zam_precmd 2>/dev/null\nunset -f __zam_preexec __zam_precmd __zam_ts 2>/dev/null\nunset __ZAM_MONITOR_FILE __ZAM_MONITOR_SEQ __ZAM_MONITOR_SESSION 2>/dev/null\necho \"ZAM monitor stopped.\"\n`.trim();\n}\n\n/** Generate bash code to remove monitor hooks. */\nexport function generateBashUnhooks(): string {\n return `\n# Remove ZAM monitor hooks\ntrap - DEBUG\nPROMPT_COMMAND=\"\\${PROMPT_COMMAND/__zam_prompt_cmd;/}\"\nunset -f __zam_debug_trap __zam_prompt_cmd __zam_ts 2>/dev/null\nunset __ZAM_MONITOR_FILE __ZAM_MONITOR_SEQ __ZAM_MONITOR_SESSION __ZAM_MONITOR_CMD_ACTIVE 2>/dev/null\necho \"ZAM monitor stopped.\"\n`.trim();\n}\n\n/** Generate PowerShell code to remove monitor hooks. */\nexport function generatePowerShellUnhooks(): string {\n return `\n# Remove ZAM monitor hooks\nif (Test-Path function:\\\\__zam_previous_prompt) {\n Set-Item -Path function:\\\\prompt -Value (Get-Item function:\\\\__zam_previous_prompt).ScriptBlock\n Remove-Item function:\\\\__zam_previous_prompt -Force -ErrorAction SilentlyContinue\n}\nRemove-Item function:\\\\__zam_write_monitor_event,function:\\\\__zam_iso_utc,function:\\\\__zam_update_last_history_id,function:\\\\__zam_record_last_history -ErrorAction SilentlyContinue\nRemove-Variable -Name __ZAM_MONITOR_FILE,__ZAM_MONITOR_SEQ,__ZAM_MONITOR_SESSION,__ZAM_MONITOR_LAST_HISTORY_ID,__ZAM_MONITOR_SKIP_NEXT_PROMPT -Scope Global -ErrorAction SilentlyContinue\nWrite-Host \"ZAM monitor stopped.\"\n`.trim();\n}\n","/**\n * Skill Discovery — identifies recurring non-standard command patterns\n * across multiple sessions and proposes them as minimal reusable skills.\n *\n * The key insight from Increment 2: \"The human's demonstrated competence\n * is the gate for automation — not the other way around.\" A pattern must\n * appear consistently across sessions before being proposed as a skill.\n *\n * Pure functions — no DB access. Callers provide command records and\n * existing skills; this module returns proposed skills.\n */\n\nimport type { CommandRecord } from \"./analyzer.js\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface CommandSequence {\n /** The ordered command prefixes forming the pattern (e.g., [\"git checkout\", \"npm install\", \"npm run build\"]) */\n steps: string[];\n /** How many sessions contained this sequence */\n sessionCount: number;\n /** Total occurrences across all sessions */\n totalOccurrences: number;\n /** Example full commands from the most recent occurrence */\n examples: string[];\n}\n\nexport interface SkillProposal {\n /** Suggested slug for the skill */\n slug: string;\n /** Human-readable description of what the pattern does */\n description: string;\n /** The command steps forming the skill */\n steps: string[];\n /** How many sessions demonstrated this pattern */\n sessionCount: number;\n /** Confidence that this is a real, repeatable skill */\n confidence: \"high\" | \"medium\" | \"low\";\n /** Example commands from actual usage */\n examples: string[];\n}\n\nexport interface DiscoveryOptions {\n /** Minimum number of sessions a pattern must appear in (default: 2) */\n minSessions?: number;\n /** Minimum sequence length to consider (default: 2) */\n minSequenceLength?: number;\n /** Maximum sequence length to consider (default: 5) */\n maxSequenceLength?: number;\n /** Existing skill slugs to exclude from proposals */\n existingSkillSlugs?: string[];\n}\n\n// ── Discovery ────────────────────────────────────────────────────────────────\n\n/**\n * Discover recurring command patterns across multiple sessions.\n *\n * Takes a map of session ID → command records, finds command sequences\n * that appear in multiple sessions, and proposes them as skills.\n *\n * @param sessionCommands - Map of session ID to that session's commands\n * @param options - Discovery configuration\n * @returns Array of skill proposals, sorted by confidence then session count\n */\nexport function discoverSkills(\n sessionCommands: Map<string, CommandRecord[]>,\n options: DiscoveryOptions = {},\n): SkillProposal[] {\n const minSessions = options.minSessions ?? 2;\n const minLen = options.minSequenceLength ?? 2;\n const maxLen = options.maxSequenceLength ?? 5;\n const existing = new Set(options.existingSkillSlugs ?? []);\n\n // Step 1: Extract normalized command sequences from each session\n const sessionSequences = new Map<string, string[][]>();\n for (const [sessionId, commands] of sessionCommands) {\n const sequences = extractSequences(commands, minLen, maxLen);\n if (sequences.length > 0) {\n sessionSequences.set(sessionId, sequences);\n }\n }\n\n // Step 2: Count how many sessions contain each unique sequence\n const sequenceIndex = new Map<string, CommandSequence>();\n\n for (const [, sequences] of sessionSequences) {\n // Deduplicate within a session — count each sequence once per session\n const seen = new Set<string>();\n for (const seq of sequences) {\n const key = seq.join(\" → \");\n if (seen.has(key)) continue;\n seen.add(key);\n\n const entry = sequenceIndex.get(key);\n if (entry) {\n entry.sessionCount++;\n entry.totalOccurrences++;\n } else {\n sequenceIndex.set(key, {\n steps: seq,\n sessionCount: 1,\n totalOccurrences: 1,\n examples: [],\n });\n }\n }\n }\n\n // Step 3: Collect examples from the most recent session for qualifying sequences\n const lastSessionId = [...sessionCommands.keys()].pop();\n if (lastSessionId) {\n const lastCommands = sessionCommands.get(lastSessionId)!;\n for (const [_key, entry] of sequenceIndex) {\n if (entry.sessionCount >= minSessions) {\n entry.examples = findExamplesForSequence(lastCommands, entry.steps);\n }\n }\n }\n\n // Step 4: Filter to patterns that appear in enough sessions\n const candidates = [...sequenceIndex.values()].filter(\n (s) => s.sessionCount >= minSessions,\n );\n\n // Step 5: Remove subsequences of longer patterns (prefer maximal patterns)\n const pruned = removeSubsequences(candidates);\n\n // Step 6: Convert to skill proposals\n const proposals: SkillProposal[] = [];\n for (const seq of pruned) {\n const slug = generateSlug(seq.steps);\n\n // Skip if this skill already exists\n if (existing.has(slug)) continue;\n\n proposals.push({\n slug,\n description: describeSequence(seq.steps),\n steps: seq.steps,\n sessionCount: seq.sessionCount,\n confidence:\n seq.sessionCount >= 4\n ? \"high\"\n : seq.sessionCount >= 3\n ? \"medium\"\n : \"low\",\n examples: seq.examples,\n });\n }\n\n // Sort: high confidence first, then by session count\n const confidenceOrder = { high: 0, medium: 1, low: 2 };\n proposals.sort((a, b) => {\n const confDiff =\n confidenceOrder[a.confidence] - confidenceOrder[b.confidence];\n if (confDiff !== 0) return confDiff;\n return b.sessionCount - a.sessionCount;\n });\n\n return proposals;\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\n/**\n * Normalize a command to its tool + subcommand prefix.\n * \"git checkout -b feat/foo\" → \"git checkout\"\n * \"npm run build\" → \"npm run build\"\n * \"docker compose up -d\" → \"docker compose up\"\n */\nfunction normalizeCommand(command: string): string {\n const parts = command.trim().split(/\\s+/);\n\n // Known multi-word tools\n const multiWord = [\"docker compose\", \"npm run\", \"npx\", \"git\"];\n const lower = command.toLowerCase();\n\n for (const mw of multiWord) {\n if (lower.startsWith(mw) && parts.length >= mw.split(\" \").length + 1) {\n return parts\n .slice(0, mw.split(\" \").length + 1)\n .join(\" \")\n .toLowerCase();\n }\n }\n\n // Default: first two words\n return parts.slice(0, Math.min(2, parts.length)).join(\" \").toLowerCase();\n}\n\n/**\n * Extract all command subsequences of length minLen..maxLen from a session.\n * Uses normalized command prefixes for comparison.\n */\nfunction extractSequences(\n commands: CommandRecord[],\n minLen: number,\n maxLen: number,\n): string[][] {\n // Filter out trivial commands\n const filtered = commands.filter((c) => {\n const lower = c.command.toLowerCase().trim();\n return (\n lower.length > 0 &&\n !lower.startsWith(\"cd \") &&\n lower !== \"cd\" &&\n lower !== \"ls\" &&\n lower !== \"pwd\" &&\n lower !== \"clear\" &&\n lower !== \"exit\" &&\n !lower.startsWith(\"echo \")\n );\n });\n\n const normalized = filtered.map((c) => normalizeCommand(c.command));\n const sequences: string[][] = [];\n\n for (let len = minLen; len <= maxLen; len++) {\n for (let i = 0; i <= normalized.length - len; i++) {\n const seq = normalized.slice(i, i + len);\n // Only include if at least 2 distinct commands (not just \"git commit\" repeated)\n if (new Set(seq).size >= 2) {\n sequences.push(seq);\n }\n }\n }\n\n return sequences;\n}\n\n/**\n * Find example full commands for a given normalized sequence in a command list.\n */\nfunction findExamplesForSequence(\n commands: CommandRecord[],\n steps: string[],\n): string[] {\n const normalized = commands.map((c) => ({\n norm: normalizeCommand(c.command),\n full: c.command,\n }));\n\n for (let i = 0; i <= normalized.length - steps.length; i++) {\n let match = true;\n for (let j = 0; j < steps.length; j++) {\n if (normalized[i + j].norm !== steps[j]) {\n match = false;\n break;\n }\n }\n if (match) {\n return normalized.slice(i, i + steps.length).map((n) => n.full);\n }\n }\n\n return [];\n}\n\n/**\n * Remove sequences that are strict subsequences of longer qualifying sequences.\n */\nfunction removeSubsequences(candidates: CommandSequence[]): CommandSequence[] {\n // Sort by length descending so we check long sequences first\n const sorted = [...candidates].sort(\n (a, b) => b.steps.length - a.steps.length,\n );\n const result: CommandSequence[] = [];\n\n for (const candidate of sorted) {\n const key = candidate.steps.join(\" → \");\n const isSubsequence = result.some((longer) => {\n const longerKey = longer.steps.join(\" → \");\n return longerKey.includes(key) && longerKey !== key;\n });\n\n if (!isSubsequence) {\n result.push(candidate);\n }\n }\n\n return result;\n}\n\n/**\n * Generate a slug from command steps.\n * [\"git checkout\", \"npm install\", \"npm run build\"] → \"checkout-install-build\"\n */\nfunction generateSlug(steps: string[]): string {\n return steps\n .map((s) => {\n const parts = s.split(/\\s+/);\n return parts[parts.length - 1]; // last word of each step\n })\n .join(\"-\");\n}\n\n/**\n * Generate a human-readable description of what a command sequence does.\n */\nfunction describeSequence(steps: string[]): string {\n return `Recurring pattern: ${steps.join(\" → \")}`;\n}\n","import type { Database } from \"../db/types.js\";\nimport type { DeleteCardResult } from \"../models/card.js\";\nimport { deleteCardForUser, getCardById } from \"../models/card.js\";\nimport { getPrerequisites } from \"../models/prerequisite.js\";\nimport type {\n DeleteTokenResult,\n Token,\n UpdateTokenInput,\n} from \"../models/token.js\";\nimport {\n deleteToken,\n deprecateToken,\n getTokenById,\n updateToken,\n} from \"../models/token.js\";\nimport type { CascadeBlockResult } from \"../scheduler/blocker.js\";\nimport { cascadeBlock } from \"../scheduler/blocker.js\";\nimport type { Rating } from \"../scheduler/fsrs.js\";\nimport type { EvaluateResult } from \"./evaluator.js\";\nimport { evaluateRatingWithinTransaction } from \"./evaluator.js\";\n\nexport type ReviewActionType =\n | \"rate\"\n | \"skip\"\n | \"edit-token\"\n | \"deprecate-token\"\n | \"delete-token\"\n | \"delete-card\"\n | \"stop\";\n\nexport interface ExecuteReviewActionInput {\n cardId: string;\n userId: string;\n action: ReviewActionType;\n rating?: Rating;\n tokenUpdates?: UpdateTokenInput;\n}\n\nexport interface ReviewActionResult {\n action: ReviewActionType;\n token: Token;\n evaluation?: EvaluateResult;\n blocked?: CascadeBlockResult;\n updatedToken?: Token;\n deletedToken?: DeleteTokenResult;\n deletedCard?: DeleteCardResult;\n skipped?: boolean;\n stopped?: boolean;\n}\n\nasync function getReviewTarget(\n db: Database,\n cardId: string,\n userId: string,\n): Promise<{ cardId: string; token: Token }> {\n const card = await getCardById(db, cardId);\n if (!card) {\n throw new Error(`Card not found: ${cardId}`);\n }\n if (card.user_id !== userId) {\n throw new Error(`Card ${cardId} does not belong to user ${userId}`);\n }\n\n const token = await getTokenById(db, card.token_id);\n if (!token) {\n throw new Error(`Token not found for card ${cardId}`);\n }\n\n return { cardId: card.id, token };\n}\n\nexport async function executeReviewAction(\n db: Database,\n input: ExecuteReviewActionInput,\n): Promise<ReviewActionResult> {\n if (input.action === \"rate\") {\n if (input.rating == null) {\n throw new Error(\"rating is required for action=rate\");\n }\n const rating = input.rating;\n\n return db.transaction(async (tx) => {\n const target = await getReviewTarget(tx, input.cardId, input.userId);\n\n const evaluation = await evaluateRatingWithinTransaction(tx, {\n cardId: target.cardId,\n tokenId: target.token.id,\n userId: input.userId,\n rating,\n });\n\n let blocked: CascadeBlockResult | undefined;\n if (rating === 1) {\n const prereqs = await getPrerequisites(tx, target.token.id);\n if (prereqs.length > 0) {\n blocked = await cascadeBlock(tx, input.userId, target.token.slug);\n }\n }\n\n return {\n action: input.action,\n token: target.token,\n evaluation,\n blocked,\n };\n });\n }\n\n const target = await getReviewTarget(db, input.cardId, input.userId);\n\n switch (input.action) {\n case \"skip\":\n return { action: input.action, token: target.token, skipped: true };\n\n case \"stop\":\n return { action: input.action, token: target.token, stopped: true };\n\n case \"edit-token\": {\n const updatedToken = await updateToken(\n db,\n target.token.slug,\n input.tokenUpdates ?? {},\n );\n return {\n action: input.action,\n token: target.token,\n updatedToken,\n };\n }\n\n case \"deprecate-token\": {\n const updatedToken = await deprecateToken(db, target.token.slug);\n return {\n action: input.action,\n token: target.token,\n updatedToken,\n };\n }\n\n case \"delete-token\": {\n const deletedToken = await deleteToken(db, target.token.slug);\n return {\n action: input.action,\n token: target.token,\n deletedToken,\n };\n }\n\n case \"delete-card\": {\n const deletedCard = await deleteCardForUser(\n db,\n target.token.id,\n input.userId,\n );\n return {\n action: input.action,\n token: target.token,\n deletedCard,\n };\n }\n\n default: {\n const exhaustive: never = input.action;\n throw new Error(`Unsupported review action: ${exhaustive}`);\n }\n }\n}\n","/**\n * Active Recall Prompt Generation\n *\n * Generates review prompts from tokens, adapting the question style\n * to the token's Bloom taxonomy level. This is NOT an LLM call —\n * it's template-based prompt assembly for the CLI and bridge.\n */\n\nexport type BloomLevel = 1 | 2 | 3 | 4 | 5;\n\nexport interface RecallPrompt {\n cardId: string;\n tokenId: string;\n slug: string;\n question: string;\n concept: string;\n domain: string;\n bloomLevel: BloomLevel;\n bloomVerb: string;\n hints: string[];\n sourceLink?: string | null;\n}\n\nconst BLOOM_VERBS: Record<BloomLevel, string> = {\n 1: \"Remember\",\n 2: \"Understand\",\n 3: \"Apply\",\n 4: \"Analyze\",\n 5: \"Synthesize\",\n};\n\nfunction formatSlugForCue(slug: string): string {\n return slug.replace(/[-_]/g, \" \");\n}\n\nconst BLOOM_CUES: Record<BloomLevel, (slug: string) => string> = {\n 1: (slug) =>\n `Recall the definition and core concept of: ${formatSlugForCue(slug)}`,\n 2: (slug) => `Explain the concept and how ${formatSlugForCue(slug)} works.`,\n 3: (slug) =>\n `Describe how or where you would apply the concept of ${formatSlugForCue(slug)}.`,\n 4: (slug) =>\n `Analyze the trade-offs, advantages, or alternatives of ${formatSlugForCue(slug)}.`,\n 5: (slug) =>\n `How would you design a solution using the concept of ${formatSlugForCue(slug)}?`,\n};\n\nexport interface PromptInput {\n cardId: string;\n tokenId: string;\n slug: string;\n concept: string;\n domain: string;\n bloomLevel: BloomLevel;\n sourceLink?: string | null;\n question?: string | null;\n}\n\n/**\n * Generate a template-based concept-free recall cue using the slug and domain.\n */\nexport function generateConceptFreeCue(\n bloomLevel: BloomLevel,\n slug: string,\n _domain: string,\n): string {\n const bloom = (\n bloomLevel >= 1 && bloomLevel <= 5 ? bloomLevel : 1\n ) as BloomLevel;\n return BLOOM_CUES[bloom](slug);\n}\n\n/**\n * Generate a recall prompt for a token at its Bloom level.\n * When called from the CLI, the prompt is rendered in the terminal.\n * When called from the AI bridge, the JSON is returned for the AI to present conversationally.\n */\nexport function generatePrompt(input: PromptInput): RecallPrompt {\n const bloom = (\n input.bloomLevel >= 1 && input.bloomLevel <= 5 ? input.bloomLevel : 1\n ) as BloomLevel;\n\n const question = input.question?.trim()\n ? input.question.trim()\n : generateConceptFreeCue(bloom, input.slug, input.domain);\n\n return {\n cardId: input.cardId,\n tokenId: input.tokenId,\n slug: input.slug,\n question,\n concept: input.concept,\n domain: input.domain,\n bloomLevel: bloom,\n bloomVerb: BLOOM_VERBS[bloom],\n hints: [],\n sourceLink: input.sourceLink ?? null,\n };\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\n\nexport interface ResolvedReference {\n sourceType: \"local\" | \"remote_web\" | \"dynamic_search\";\n content: string;\n filePath?: string;\n url?: string;\n}\n\n/**\n * A source reference resolved and bounded for inclusion in a review payload.\n * Same shape as ResolvedReference plus the originating link and a truncation flag.\n */\nexport interface ReviewContext {\n sourceLink: string;\n sourceType: ResolvedReference[\"sourceType\"];\n content: string;\n filePath?: string;\n url?: string;\n truncated: boolean;\n}\n\n/** Default cap on resolved content length, so bridge JSON / terminal output stays bounded. */\nexport const DEFAULT_REVIEW_CONTEXT_MAX_CHARS = 6000;\n\n/**\n * Strips HTML tags and attempts to convert basic structure to readable text/markdown.\n */\nfunction htmlToText(html: string): string {\n // Extract body if present\n let content = html;\n const bodyMatch = /<body[^>]*>([\\s\\S]*?)<\\/body>/i.exec(html);\n if (bodyMatch) {\n content = bodyMatch[1];\n }\n\n // Strip script, style, and head tags completely\n content = content.replace(/<(script|style|head)[^>]*>([\\s\\S]*?)<\\/\\1>/gi, \"\");\n // Replace headings\n content = content.replace(\n /<h[1-6][^>]*>([\\s\\S]*?)<\\/h[1-6]>/gi,\n \"\\n\\n# $1\\n\",\n );\n // Replace paragraph/div/li tags with line breaks\n content = content.replace(/<(p|div|li)[^>]*>/gi, \"\\n\");\n content = content.replace(/<\\/(p|div|li)>/gi, \"\\n\");\n content = content.replace(/<br\\s*\\/?>/gi, \"\\n\");\n // Strip all other HTML tags\n content = content.replace(/<[^>]+>/g, \"\");\n // Decode basic HTML entities\n content = content\n .replace(/&nbsp;/g, \" \")\n .replace(/&lt;/g, \"<\")\n .replace(/&gt;/g, \">\")\n .replace(/&amp;/g, \"&\")\n .replace(/&quot;/g, '\"')\n .replace(/&#39;/g, \"'\");\n\n // Collapse consecutive newlines\n content = content.replace(/\\n{3,}/g, \"\\n\\n\").trim();\n return content;\n}\n\n/**\n * Parse line anchors like #L10-L25 or #L10 and extract the lines from file content.\n */\nfunction extractLines(content: string, anchor: string): string {\n const lines = content.split(/\\r?\\n/);\n const match = /#L(\\d+)(?:-L(\\d+))?$/i.exec(anchor);\n if (!match) return content;\n\n const start = Number.parseInt(match[1], 10) - 1; // 0-indexed\n const end = match[2] ? Number.parseInt(match[2], 10) - 1 : start;\n\n if (start < 0 || start >= lines.length) return content;\n\n const slice = lines.slice(start, Math.min(end + 1, lines.length));\n return slice.join(\"\\n\");\n}\n\n/**\n * Resolves a given token's source_link into readable textual content.\n */\nexport async function resolveReference(\n sourceLink: string,\n): Promise<ResolvedReference> {\n const cleaned = sourceLink.trim();\n\n // 1. Dynamic Web Search\n if (cleaned.startsWith(\"search://\")) {\n try {\n const url = new URL(cleaned);\n const query = url.searchParams.get(\"q\") || \"\";\n return {\n sourceType: \"dynamic_search\",\n content: `QUERY_DIRECTIVE: Run web search for \"${query}\"`,\n url: cleaned,\n };\n } catch {\n // Fallback if URL parsing fails\n const query = cleaned.replace(/^search:\\/\\/(\\??q=)?/, \"\");\n return {\n sourceType: \"dynamic_search\",\n content: `QUERY_DIRECTIVE: Run web search for \"${decodeURIComponent(query)}\"`,\n url: cleaned,\n };\n }\n }\n\n // 2. HTTP/HTTPS URLs\n if (cleaned.startsWith(\"http://\") || cleaned.startsWith(\"https://\")) {\n // 2.a GitHub URIs\n const gitHubMatch =\n /^https?:\\/\\/(?:www\\.)?github\\.com\\/([^/]+)\\/([^/]+)\\/blob\\/([^/]+)\\/(.+)$/i.exec(\n cleaned,\n );\n if (gitHubMatch) {\n const [_, owner, repo, branch, fullPathWithAnchor] = gitHubMatch;\n const anchorIndex = fullPathWithAnchor.indexOf(\"#\");\n const filePath =\n anchorIndex !== -1\n ? fullPathWithAnchor.slice(0, anchorIndex)\n : fullPathWithAnchor;\n const anchor =\n anchorIndex !== -1 ? fullPathWithAnchor.slice(anchorIndex) : \"\";\n\n // Try local resolution: check if repo folder exists in sibling directories\n const parentDir = dirname(process.cwd());\n const localRepoPath = join(parentDir, repo);\n const localFilePath = join(localRepoPath, filePath);\n\n if (existsSync(localFilePath)) {\n try {\n let fileContent = readFileSync(localFilePath, \"utf-8\");\n if (anchor) {\n fileContent = extractLines(fileContent, anchor);\n }\n return {\n sourceType: \"local\",\n content: fileContent,\n filePath: localFilePath,\n };\n } catch (_e) {\n // Fallback to fetch if file read fails\n }\n }\n\n // Remote fallback: fetch raw content from githubusercontent\n const rawUrl = `https://raw.githubusercontent.com/${owner}/${repo}/${branch}/${filePath}`;\n try {\n const response = await fetch(rawUrl);\n if (response.ok) {\n let rawText = await response.text();\n if (anchor) {\n rawText = extractLines(rawText, anchor);\n }\n return {\n sourceType: \"remote_web\",\n content: rawText,\n url: cleaned,\n };\n }\n } catch (_e) {\n // Fallback to generic URL loading\n }\n }\n\n // 2.b Generic HTTPS/HTTP URLs\n try {\n const response = await fetch(cleaned);\n if (response.ok) {\n const text = await response.text();\n const cleanText = htmlToText(text);\n return {\n sourceType: \"remote_web\",\n content: cleanText,\n url: cleaned,\n };\n }\n throw new Error(`HTTP error ${response.status}: ${response.statusText}`);\n } catch (err) {\n return {\n sourceType: \"remote_web\",\n content: `Error fetching URL reference: ${(err as Error).message}\\nLink: ${cleaned}`,\n url: cleaned,\n };\n }\n }\n\n // 3. Local Workspace Path (relative to process.cwd)\n const anchorIndex = cleaned.indexOf(\"#\");\n const relativePath =\n anchorIndex !== -1 ? cleaned.slice(0, anchorIndex) : cleaned;\n const anchor = anchorIndex !== -1 ? cleaned.slice(anchorIndex) : \"\";\n const absolutePath = resolve(process.cwd(), relativePath);\n\n if (existsSync(absolutePath)) {\n try {\n let fileContent = readFileSync(absolutePath, \"utf-8\");\n if (anchor) {\n fileContent = extractLines(fileContent, anchor);\n }\n return {\n sourceType: \"local\",\n content: fileContent,\n filePath: absolutePath,\n };\n } catch (_e) {\n // Fallback\n }\n }\n\n // Final fallback: return the path/link description as string\n return {\n sourceType: \"local\",\n content: `Local reference file not found or unreadable.\\nReference: ${cleaned}`,\n filePath: absolutePath,\n };\n}\n\n/**\n * Resolve a token's source_link into bounded, review-ready context.\n *\n * Wraps {@link resolveReference} for the review/bridge flow: returns `null`\n * for empty links and caps content length so the surrounding payload (bridge\n * JSON or terminal output) stays manageable, flagging when truncation occurred.\n */\nexport async function resolveReviewContext(\n sourceLink: string | null | undefined,\n opts: { maxChars?: number } = {},\n): Promise<ReviewContext | null> {\n const cleaned = sourceLink?.trim();\n if (!cleaned) return null;\n\n const maxChars = opts.maxChars ?? DEFAULT_REVIEW_CONTEXT_MAX_CHARS;\n const resolved = await resolveReference(cleaned);\n\n let content = resolved.content;\n let truncated = false;\n if (content.length > maxChars) {\n content = content.slice(0, maxChars);\n truncated = true;\n }\n\n return {\n sourceLink: cleaned,\n sourceType: resolved.sourceType,\n content,\n filePath: resolved.filePath,\n url: resolved.url,\n truncated,\n };\n}\n\n/**\n * Normalizes a path, stripping anchors and converting separators.\n */\nexport function normalizePath(p: string): string {\n const base = p.split(\"#\")[0].trim();\n return base.replace(/\\\\/g, \"/\").toLowerCase();\n}\n\n/**\n * Checks if a token's source_link references a changed file.\n */\nexport function matchesFilePath(\n sourceLink: string | null,\n changedFile: string,\n): boolean {\n if (!sourceLink) return false;\n\n const normSource = normalizePath(sourceLink);\n const normChanged = normalizePath(changedFile);\n\n if (!normSource || !normChanged) return false;\n\n // 1. GitHub URI matching\n const gitHubMatch =\n /^https?:\\/\\/(?:www\\.)?github\\.com\\/([^/]+)\\/([^/]+)\\/blob\\/([^/]+)\\/(.+)$/i.exec(\n normSource,\n );\n if (gitHubMatch) {\n const filePath = gitHubMatch[4];\n return filePath === normChanged;\n }\n\n // Generic URL check (don't match web references against local paths)\n if (normSource.startsWith(\"http://\") || normSource.startsWith(\"https://\")) {\n return false;\n }\n\n // 2. Relative/Absolute path matching\n return normSource.endsWith(normChanged) || normChanged.endsWith(normSource);\n}\n","/**\n * Cross-domain interleaving — prevents same-domain streaks in review queues.\n *\n * Given an array of items with a `domain` field, reorders them using a\n * round-robin strategy so that consecutive items come from different domains.\n * This leverages the interleaving effect: mixing topics during practice\n * strengthens discrimination and long-term retention.\n */\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface QueueItem {\n cardId: string;\n tokenId: string;\n domain: string;\n}\n\n// ── Functions ────────────────────────────────────────────────────────────────\n\n/**\n * Reorder items so no domain appears more than `maxConsecutive` times in a row.\n *\n * Algorithm: group items by domain, then round-robin across domain groups.\n * Each round picks one item from each non-exhausted domain. Within a domain,\n * the original order is preserved (so urgency sorting survives).\n *\n * If a domain has more items than others, its extras will appear after all\n * other domains are exhausted — but the `maxConsecutive` cap is still\n * respected by inserting items from the largest remaining domains first.\n *\n * @param items - Array of items to interleave. Not mutated.\n * @param maxConsecutive - Max consecutive items from the same domain. Defaults to 2.\n * @returns A new array with the same items in interleaved order.\n */\nexport function interleave<T extends { domain: string }>(\n items: T[],\n maxConsecutive: number = 2,\n): T[] {\n if (items.length <= 1) return [...items];\n\n // Group items by domain, preserving original order within each group\n const byDomain = new Map<string, T[]>();\n for (const item of items) {\n const group = byDomain.get(item.domain);\n if (group) {\n group.push(item);\n } else {\n byDomain.set(item.domain, [item]);\n }\n }\n\n // If there's only one domain, no interleaving possible\n if (byDomain.size === 1) return [...items];\n\n const result: T[] = [];\n let consecutiveCount = 0;\n let lastDomain: string | null = null;\n\n // Track how many items we've consumed from each domain\n const cursors = new Map<string, number>();\n for (const domain of byDomain.keys()) {\n cursors.set(domain, 0);\n }\n\n // Round-robin: sort domains by remaining count (largest first) each round\n while (result.length < items.length) {\n // Get domains that still have items, sorted by remaining count descending\n const activeDomains = [...byDomain.entries()]\n .filter(\n ([domain]) =>\n (cursors.get(domain) ?? 0) < (byDomain.get(domain)?.length ?? 0),\n )\n .sort((a, b) => {\n const remainA = a[1].length - (cursors.get(a[0]) ?? 0);\n const remainB = b[1].length - (cursors.get(b[0]) ?? 0);\n return remainB - remainA;\n });\n\n if (activeDomains.length === 0) break;\n\n let pickedThisRound = false;\n\n for (const [domain, group] of activeDomains) {\n const cursor = cursors.get(domain) ?? 0;\n if (cursor >= group.length) continue;\n\n // Check if adding from this domain would exceed maxConsecutive\n if (domain === lastDomain && consecutiveCount >= maxConsecutive) {\n // Try to find another domain first\n continue;\n }\n\n // Pick one item from this domain\n result.push(group[cursor]);\n cursors.set(domain, cursor + 1);\n pickedThisRound = true;\n\n if (domain === lastDomain) {\n consecutiveCount++;\n } else {\n lastDomain = domain;\n consecutiveCount = 1;\n }\n\n break;\n }\n\n // If we couldn't pick without exceeding maxConsecutive, we must accept\n // a streak from whatever domain has items left\n if (!pickedThisRound) {\n for (const [domain, group] of activeDomains) {\n const cursor = cursors.get(domain) ?? 0;\n if (cursor >= group.length) continue;\n\n result.push(group[cursor]);\n cursors.set(domain, cursor + 1);\n\n if (domain === lastDomain) {\n consecutiveCount++;\n } else {\n lastDomain = domain;\n consecutiveCount = 1;\n }\n\n break;\n }\n }\n }\n\n return result;\n}\n","/**\n * Review Queue Builder — assembles a session's review queue.\n *\n * Combines due-card fetching, new-card selection, urgency sorting,\n * and cross-domain interleaving into a single ready-to-review queue.\n */\n\nimport type { Database } from \"../db/types.js\";\nimport { interleave } from \"./interleaver.js\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface ReviewQueueOptions {\n userId: string;\n maxNew?: number; // default 10\n maxReviews?: number; // default 50\n now?: Date;\n}\n\nexport interface ReviewQueueItem {\n cardId: string;\n tokenId: string;\n slug: string;\n concept: string;\n domain: string;\n bloomLevel: number;\n state: string; // 'new' | 'learning' | 'review' | 'relearning'\n dueAt: string;\n sourceLink: string | null;\n question: string | null;\n}\n\nexport interface ReviewQueue {\n items: ReviewQueueItem[];\n newCount: number;\n reviewCount: number;\n relearnCount: number;\n totalDomains: string[];\n}\n\n// ── Internal row type from SQL queries ───────────────────────────────────────\n\ninterface CardRow {\n card_id: string;\n token_id: string;\n slug: string;\n concept: string;\n domain: string;\n bloom_level: number;\n state: string;\n due_at: string;\n source_link: string | null;\n question: string | null;\n}\n\n// ── Functions ────────────────────────────────────────────────────────────────\n\n/**\n * Build a review queue for a user's study session.\n *\n * The queue is assembled in stages:\n * 1. Fetch all due cards (not blocked, due_at <= now, state in review/relearning/learning)\n * 2. Fetch new cards (state = 'new', not blocked) up to maxNew\n * 3. Sort overdue cards by urgency — most overdue first\n * 4. Apply cross-domain interleaving to prevent same-domain streaks\n * 5. Intersperse new cards at regular intervals (every 5th position)\n * 6. Cap total at maxReviews\n *\n * @param db - Database connection\n * @param options - Queue building options\n * @returns The assembled review queue with metadata\n */\nexport async function buildReviewQueue(\n db: Database,\n options: ReviewQueueOptions,\n): Promise<ReviewQueue> {\n const maxNew = options.maxNew ?? 10;\n const maxReviews = options.maxReviews ?? 50;\n const now = options.now ?? new Date();\n const nowISO = now.toISOString();\n\n // ── Step 1: Fetch due cards (review, relearning, learning — not new) ───\n const dueRows = (await db\n .prepare(\n `SELECT\n c.id AS card_id,\n c.token_id AS token_id,\n t.slug AS slug,\n t.concept AS concept,\n t.domain AS domain,\n t.bloom_level AS bloom_level,\n c.state AS state,\n c.due_at AS due_at,\n t.source_link AS source_link,\n t.question AS question\n FROM cards c\n JOIN tokens t ON t.id = c.token_id\n WHERE c.user_id = ?\n AND c.blocked = 0\n AND c.due_at <= ?\n AND c.state IN ('review', 'relearning', 'learning')\n AND t.deprecated_at IS NULL\n ORDER BY c.due_at ASC`,\n )\n .all(options.userId, nowISO)) as CardRow[];\n\n // ── Step 2: Fetch new cards ────────────────────────────────────────────\n const newRows = (await db\n .prepare(\n `SELECT\n c.id AS card_id,\n c.token_id AS token_id,\n t.slug AS slug,\n t.concept AS concept,\n t.domain AS domain,\n t.bloom_level AS bloom_level,\n c.state AS state,\n c.due_at AS due_at,\n t.source_link AS source_link,\n t.question AS question\n FROM cards c\n JOIN tokens t ON t.id = c.token_id\n WHERE c.user_id = ?\n AND c.blocked = 0\n AND c.state = 'new'\n AND t.deprecated_at IS NULL\n ORDER BY t.bloom_level ASC, t.slug ASC\n LIMIT ?`,\n )\n .all(options.userId, maxNew)) as CardRow[];\n\n // ── Step 3: Sort overdue cards by urgency (most overdue first) ─────────\n const nowMs = now.getTime();\n const sortedDue = [...dueRows].sort((a, b) => {\n const overdueA = nowMs - new Date(a.due_at).getTime();\n const overdueB = nowMs - new Date(b.due_at).getTime();\n return overdueB - overdueA; // most overdue first\n });\n\n // ── Step 4: Apply cross-domain interleaving to due cards ───────────────\n const interleavedDue = interleave(\n sortedDue.map((row) => ({ ...rowToItem(row), domain: row.domain })),\n );\n\n // ── Step 5: Intersperse new cards at regular intervals ─────────────────\n const newItems = newRows.map(rowToItem);\n const merged = intersperseNew(interleavedDue, newItems, 5);\n\n // ── Step 6: Cap total at maxReviews ────────────────────────────────────\n const capped = merged.slice(0, maxReviews);\n\n // ── Compute metadata ──────────────────────────────────────────────────\n let newCount = 0;\n let reviewCount = 0;\n let relearnCount = 0;\n const domainSet = new Set<string>();\n\n for (const item of capped) {\n domainSet.add(item.domain);\n switch (item.state) {\n case \"new\":\n newCount++;\n break;\n case \"relearning\":\n relearnCount++;\n break;\n default:\n reviewCount++;\n break;\n }\n }\n\n return {\n items: capped,\n newCount,\n reviewCount,\n relearnCount,\n totalDomains: [...domainSet].sort(),\n };\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\n/** Convert a SQL row to a ReviewQueueItem. */\nfunction rowToItem(row: CardRow): ReviewQueueItem {\n return {\n cardId: row.card_id,\n tokenId: row.token_id,\n slug: row.slug,\n concept: row.concept,\n domain: row.domain,\n bloomLevel: row.bloom_level,\n state: row.state,\n dueAt: row.due_at,\n sourceLink: row.source_link,\n question: row.question,\n };\n}\n\n/**\n * Intersperse new cards into the review queue at regular intervals.\n *\n * Instead of front-loading or back-loading new cards, places one new card\n * every `interval` positions (e.g., positions 4, 9, 14, ...).\n * This gives the user a mix of familiar reviews and new material.\n *\n * @param reviews - The interleaved review cards\n * @param newCards - New cards to intersperse\n * @param interval - Place a new card every N positions (default 5)\n * @returns Merged array with new cards interspersed\n */\nfunction intersperseNew(\n reviews: ReviewQueueItem[],\n newCards: ReviewQueueItem[],\n interval: number,\n): ReviewQueueItem[] {\n if (newCards.length === 0) return [...reviews];\n if (reviews.length === 0) return [...newCards];\n\n const result: ReviewQueueItem[] = [];\n let reviewIdx = 0;\n let newIdx = 0;\n\n // Position counter tracks where we are in the final queue\n let position = 0;\n\n while (reviewIdx < reviews.length || newIdx < newCards.length) {\n // Insert a new card every `interval` positions (0-indexed: at 4, 9, 14, ...)\n if (\n newIdx < newCards.length &&\n position > 0 &&\n position % interval === interval - 1\n ) {\n result.push(newCards[newIdx]);\n newIdx++;\n } else if (reviewIdx < reviews.length) {\n result.push(reviews[reviewIdx]);\n reviewIdx++;\n } else if (newIdx < newCards.length) {\n // No more reviews — append remaining new cards\n result.push(newCards[newIdx]);\n newIdx++;\n }\n\n position++;\n }\n\n return result;\n}\n","import {\n appendFileSync,\n copyFileSync,\n existsSync,\n mkdirSync,\n readFileSync,\n writeFileSync,\n} from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst HOME = homedir();\n\n/**\n * Get the path to ZAM's internal package SKILL.md.\n */\nexport function getPackageSkillPath(\n agent: \"default\" | \"claude\" | \"codex\" = \"default\",\n): string {\n // Support source modules plus the dist/index.js and dist/cli/index.js bundles.\n const packageRoot =\n [\n fileURLToPath(new URL(\"../../..\", import.meta.url)),\n fileURLToPath(new URL(\"../..\", import.meta.url)),\n fileURLToPath(new URL(\"..\", import.meta.url)),\n ].find((candidate) => existsSync(join(candidate, \"package.json\"))) ?? \"\";\n\n if (!packageRoot) return \"\";\n\n if (agent === \"codex\") {\n const codexPath = join(packageRoot, \".agents\", \"skills\", \"zam\", \"SKILL.md\");\n if (existsSync(codexPath)) return codexPath;\n return \"\";\n }\n\n if (agent === \"claude\") {\n const claudePath = join(\n packageRoot,\n \".claude\",\n \"skills\",\n \"zam\",\n \"SKILL.md\",\n );\n if (existsSync(claudePath)) return claudePath;\n return \"\";\n }\n\n // Try .agent first\n let path = join(packageRoot, \".agent\", \"skills\", \"zam\", \"SKILL.md\");\n if (existsSync(path)) return path;\n\n // Try .claude\n path = join(packageRoot, \".claude\", \"skills\", \"zam\", \"SKILL.md\");\n if (existsSync(path)) return path;\n\n return \"\";\n}\n\n/**\n * Distribute the ZAM active-recall training skill globally.\n * Copies SKILL.md into global directories for supported coding agents.\n */\nexport function distributeGlobalSkills(home: string = HOME): Array<{\n name: string;\n path: string;\n success: boolean;\n}> {\n const sourceSkill = getPackageSkillPath();\n const claudeSourceSkill = getPackageSkillPath(\"claude\");\n const codexSourceSkill = getPackageSkillPath(\"codex\");\n const results: Array<{ name: string; path: string; success: boolean }> = [];\n\n if (!sourceSkill) {\n console.warn(\"Could not find ZAM source SKILL.md in the package folder.\");\n return results;\n }\n\n // 1. Claude Code global directory\n const claudeSkillsDir = join(home, \".claude\", \"skills\", \"zam\");\n try {\n if (!claudeSourceSkill) {\n throw new Error(\"Claude skill source not found\");\n }\n mkdirSync(claudeSkillsDir, { recursive: true });\n copyFileSync(claudeSourceSkill, join(claudeSkillsDir, \"SKILL.md\"));\n results.push({\n name: \"Claude Code Global\",\n path: join(claudeSkillsDir, \"SKILL.md\"),\n success: true,\n });\n } catch (_err) {\n results.push({\n name: \"Claude Code Global\",\n path: claudeSkillsDir,\n success: false,\n });\n }\n\n // 2. Gemini/agy global directory\n const geminiSkillsDir = join(home, \".gemini\", \"skills\", \"zam\");\n try {\n mkdirSync(geminiSkillsDir, { recursive: true });\n copyFileSync(sourceSkill, join(geminiSkillsDir, \"SKILL.md\"));\n results.push({\n name: \"Gemini CLI Global\",\n path: join(geminiSkillsDir, \"SKILL.md\"),\n success: true,\n });\n } catch (_err) {\n results.push({\n name: \"Gemini CLI Global\",\n path: geminiSkillsDir,\n success: false,\n });\n }\n\n // 3. Codex global skills directory\n const codexSkillsDir = join(home, \".agents\", \"skills\", \"zam\");\n try {\n if (!codexSourceSkill) {\n throw new Error(\"Codex skill source not found\");\n }\n mkdirSync(codexSkillsDir, { recursive: true });\n copyFileSync(codexSourceSkill, join(codexSkillsDir, \"SKILL.md\"));\n results.push({\n name: \"Codex Global\",\n path: join(codexSkillsDir, \"SKILL.md\"),\n success: true,\n });\n } catch (_err) {\n results.push({\n name: \"Codex Global\",\n path: codexSkillsDir,\n success: false,\n });\n }\n\n // 4. Goose skills directory\n const gooseSkillsDir = join(home, \".goose\", \"skills\", \"zam\");\n try {\n mkdirSync(gooseSkillsDir, { recursive: true });\n copyFileSync(sourceSkill, join(gooseSkillsDir, \"SKILL.md\"));\n results.push({\n name: \"Goose Global\",\n path: join(gooseSkillsDir, \"SKILL.md\"),\n success: true,\n });\n } catch (_err) {\n results.push({\n name: \"Goose Global\",\n path: gooseSkillsDir,\n success: false,\n });\n }\n\n return results;\n}\n\nconst POSIX_OLD_HOOK = `\n# ZAM Shell Observation Hooks\nif (command -v zam >/dev/null 2>&1); then eval \"$(zam monitor start --quiet)\"; fi\n`;\nconst POWERSHELL_OLD_HOOK = `\n# ZAM Shell Observation Hooks\nif (Get-Command zam -ErrorAction SilentlyContinue) { Invoke-Expression (& zam monitor start --quiet pwsh) }\n`;\nconst HOOK_MARKER = \"# ZAM Monitor Session Helper\";\n\nfunction posixHook(shell: \"bash\" | \"zsh\"): string {\n return `\n${HOOK_MARKER}\nzam-monitor-session() {\n local session_id=\"\\${1:-}\"\n if [ -z \"$session_id\" ]; then\n printf 'Usage: zam-monitor-session <session-id>\\n' >&2\n return 2\n fi\n eval \"$(command zam monitor start --session \"$session_id\" --shell ${shell})\"\n}\n`;\n}\n\nconst POWERSHELL_HOOK = `\n${HOOK_MARKER}\nfunction Start-ZamMonitor {\n param([Parameter(Mandatory = $true)][string]$Session)\n Invoke-Expression (& zam monitor start --session $Session --shell pwsh)\n}\n`;\n\nfunction installHook(\n file: string,\n hook: string,\n oldHook: string,\n): { success: boolean; alreadyHooked: boolean } {\n try {\n const content = existsSync(file) ? readFileSync(file, \"utf8\") : \"\";\n if (content.includes(HOOK_MARKER)) {\n return { success: true, alreadyHooked: true };\n }\n\n if (content.includes(oldHook.trim())) {\n writeFileSync(file, content.replace(oldHook.trim(), hook.trim()), \"utf8\");\n } else {\n appendFileSync(file, hook);\n }\n return { success: true, alreadyHooked: false };\n } catch {\n return { success: false, alreadyHooked: false };\n }\n}\n\n/**\n * Add opt-in helpers for starting a monitored session to user shell profiles.\n */\nexport function injectShellHooks(home: string = HOME): Array<{\n shell: string;\n file: string;\n success: boolean;\n alreadyHooked: boolean;\n}> {\n const results: Array<{\n shell: string;\n file: string;\n success: boolean;\n alreadyHooked: boolean;\n }> = [];\n\n // 1. Zsh profile (~/.zshrc)\n const zshrc = join(home, \".zshrc\");\n if (existsSync(zshrc)) {\n const status = installHook(zshrc, posixHook(\"zsh\"), POSIX_OLD_HOOK);\n results.push({ shell: \"zsh\", file: zshrc, ...status });\n }\n\n // 2. Bash profile (~/.bashrc)\n const bashrc = join(home, \".bashrc\");\n if (existsSync(bashrc)) {\n const status = installHook(bashrc, posixHook(\"bash\"), POSIX_OLD_HOOK);\n results.push({ shell: \"bash\", file: bashrc, ...status });\n }\n\n // 3. PowerShell Profile ($HOME\\Documents\\PowerShell\\Microsoft.PowerShell_profile.ps1)\n // Check both PowerShell and WindowsPowerShell\n const pwshDirs = [\n join(home, \"Documents\", \"PowerShell\"),\n join(home, \"Documents\", \"WindowsPowerShell\"),\n ];\n\n for (const dir of pwshDirs) {\n const profileFile = join(dir, \"Microsoft.PowerShell_profile.ps1\");\n try {\n mkdirSync(dir, { recursive: true });\n const status = installHook(\n profileFile,\n POWERSHELL_HOOK,\n POWERSHELL_OLD_HOOK,\n );\n results.push({\n shell: \"powershell\",\n file: profileFile,\n ...status,\n });\n } catch {\n results.push({\n shell: \"powershell\",\n file: profileFile,\n success: false,\n alreadyHooked: false,\n });\n }\n }\n\n return results;\n}\n","import type { SupportedLocale } from \"./locale.js\";\n\nexport type TranslationKey =\n | \"welcome\"\n | \"new_review_relearn\"\n | \"domains\"\n | \"instruction\"\n | \"quit_hint\"\n | \"offline_warning\"\n | \"offline_instruction\"\n | \"nothing_due\"\n | \"evaluating\"\n | \"generating_question\"\n | \"translating\"\n | \"prompt_answer\"\n | \"session_ended\"\n | \"session_complete\"\n | \"cards_rated\"\n | \"avg_rating\"\n | \"forgot\"\n | \"feedback_title\"\n | \"answer_title\"\n | \"keep_waiting\"\n | \"local_ai_working\"\n | \"wait_warning\"\n | \"wait_info\"\n | \"keep_waiting_llm\"\n | \"proceeding_offline\"\n | \"eval_skipped\";\n\nexport const TRANSLATIONS: Record<\n SupportedLocale,\n Record<TranslationKey, string>\n> = {\n en: {\n welcome: \"Learning session: {count} card(s)\",\n new_review_relearn: \" New: {newC} Review: {reviewC} Relearn: {relearnC}\",\n domains: \" Domains: {domains}\",\n instruction:\n \"\\nRecall each answer first, reveal it, then rate yourself honestly.\",\n quit_hint:\n \"Type 'q' at the answer prompt (or press Ctrl+C) to stop anytime.\",\n offline_warning:\n \"\\n\\x1b[33m⚠ LLM-Feedback & automatic translation are disabled.\\x1b[0m\",\n offline_instruction:\n \" Enable with: \\x1b[36mnpm run dev -- settings llm on\\x1b[0m\\n\",\n nothing_due: \"Nothing due to learn. You're all caught up!\",\n evaluating: \"Evaluating answer via local AI...\",\n generating_question: \"Generating dynamic question...\",\n translating: \"Translating question dynamically...\",\n prompt_answer: \"Your answer (Enter to reveal · 'q' to stop):\",\n session_ended: \"Learning session ended.\",\n session_complete: \"Learning session complete!\",\n cards_rated: \" Cards rated: {count}\",\n avg_rating: \" Average rating: {avg}\",\n forgot: \" Forgot: {count} card(s)\",\n feedback_title: \"── ZAM Feedback {line}\",\n answer_title: \"── Answer {line}\",\n keep_waiting: \"Would you like to keep waiting?\",\n local_ai_working: \"The local AI is still generating the response.\",\n wait_warning: \"⚠ The LLM server is taking a while to load the model.\",\n wait_info:\n \"(This is expected when transitioning between models or starting up from cold.)\",\n keep_waiting_llm: \"Would you like to keep waiting for the model?\",\n proceeding_offline:\n \"⚠ Proceeding in offline-mode (without active LLM evaluations for this session).\",\n eval_skipped: \" [LLM Evaluation skipped: {reason}]\",\n },\n de: {\n welcome: \"Lern-Session: {count} Karte(n)\",\n new_review_relearn:\n \" Neu: {newC} Wiederholen: {reviewC} Lernen: {relearnC}\",\n domains: \" Domänen: {domains}\",\n instruction:\n \"\\nRufe jede Antwort zuerst ab, decke sie auf und bewerte dich dann ehrlich selbst.\",\n quit_hint:\n \"Gib 'q' bei der Antwortaufforderung ein (oder drücke Strg+C), um jederzeit zu beenden.\",\n offline_warning:\n \"\\n\\x1b[33m⚠ LLM-Feedback & automatische Übersetzung sind deaktiviert.\\x1b[0m\",\n offline_instruction:\n \" Aktivieren mit: \\x1b[36mnpm run dev -- settings llm on\\x1b[0m\\n\",\n nothing_due: \"Nichts fällig zu lernen. Du bist komplett auf dem Laufenden!\",\n evaluating: \"Bewerte Antwort via lokaler KI...\",\n generating_question: \"Generiere dynamische Frage...\",\n translating: \"Übersetze Frage dynamisch...\",\n prompt_answer: \"Deine Antwort (Eingabe zum Aufdecken · 'q' zum Beenden):\",\n session_ended: \"Lern-Session beendet.\",\n session_complete: \"Lern-Session abgeschlossen!\",\n cards_rated: \" Bewertete Karten: {count}\",\n avg_rating: \" Durchschnittliche Bewertung: {avg}\",\n forgot: \" Vergessen: {count} Karte(n)\",\n feedback_title: \"── ZAM Feedback {line}\",\n answer_title: \"── Antwort {line}\",\n keep_waiting: \"Möchtest du weiter auf die Bewertung warten?\",\n local_ai_working: \"Die lokale KI arbeitet noch an der Antwort.\",\n wait_warning:\n \"⚠ Der LLM-Server braucht ungewöhnlich lange, um das Modell zu laden.\",\n wait_info:\n \"(Das ist normal, wenn das Modell gewechselt wird oder kalt startet.)\",\n keep_waiting_llm: \"Möchtest du weiter auf das Modell warten?\",\n proceeding_offline:\n \"⚠ Fahre im Offline-Modus fort (ohne aktive LLM-Bewertungen in dieser Runde).\",\n eval_skipped: \" [LLM-Bewertung übersprungen: {reason}]\",\n },\n es: {\n welcome: \"Sesión de aprendizaje: {count} tarjeta(s)\",\n new_review_relearn:\n \" Nuevas: {newC} Repasar: {reviewC} Reaprender: {relearnC}\",\n domains: \" Dominios: {domains}\",\n instruction:\n \"\\nRecuerda cada respuesta primero, revélala y califícate honestamente.\",\n quit_hint:\n \"Escribe 'q' en la respuesta (o presiona Ctrl+C) para salir en cualquier momento.\",\n offline_warning:\n \"\\n\\x1b[33m⚠ Los comentarios de LLM y la traducción automática están desactivados.\\x1b[0m\",\n offline_instruction:\n \" Activar con: \\x1b[36mnpm run dev -- settings llm on\\x1b[0m\\n\",\n nothing_due: \"No hay nada pendiente para aprender. ¡Estás al día!\",\n evaluating: \"Evaluando respuesta con IA local...\",\n generating_question: \"Generando pregunta dinámica...\",\n translating: \"Traduciendo pregunta dinámicamente...\",\n prompt_answer: \"Tu respuesta (Intro para revelar · 'q' para salir):\",\n session_ended: \"Sesión de aprendizaje finalizada.\",\n session_complete: \"¡Sesión de aprendizaje completada!\",\n cards_rated: \" Tarjetas calificadas: {count}\",\n avg_rating: \" Calificación promedio: {avg}\",\n forgot: \" Olvidadas: {count} tarjeta(s)\",\n feedback_title: \"── Comentarios de ZAM {line}\",\n answer_title: \"── Respuesta {line}\",\n keep_waiting: \"¿Deseas seguir esperando la evaluación?\",\n local_ai_working: \"La IA local todavía está generando la respuesta.\",\n wait_warning: \"⚠ El servidor LLM está tardando en cargar el modelo.\",\n wait_info: \"(Esto es normal al cambiar de modelo o iniciar en frío.)\",\n keep_waiting_llm: \"¿Deseas seguir esperando el modelo?\",\n proceeding_offline:\n \"⚠ Continuando en modo fuera de línea (sin evaluaciones de LLM en esta sesión).\",\n eval_skipped: \" [Evaluación de LLM omitida: {reason}]\",\n },\n fr: {\n welcome: \"Session d'apprentissage : {count} carte(s)\",\n new_review_relearn:\n \" Nouveau: {newC} Révision: {reviewC} Relever: {relearnC}\",\n domains: \" Domaines: {domains}\",\n instruction:\n \"\\nRappelez-vous chaque réponse d'abord, révélez-la, puis évaluez-vous honnêtement.\",\n quit_hint: \"Tapez 'q' (ou Ctrl+C) pour quitter à tout moment.\",\n offline_warning:\n \"\\n\\x1b[33m⚠ Les commentaires LLM et la traduction automatique sont désactivés.\\x1b[0m\",\n offline_instruction:\n \" Activer avec : \\x1b[36mnpm run dev -- settings llm on\\x1b[0m\\n\",\n nothing_due: \"Rien à apprendre. Vous êtes à jour !\",\n evaluating: \"Évaluation de la réponse via l'IA locale...\",\n generating_question: \"Génération d'une question dynamique...\",\n translating: \"Traduction dynamique de la question...\",\n prompt_answer: \"Votre réponse (Entrée pour révéler · 'q' pour quitter) :\",\n session_ended: \"Session d'apprentissage arrêtée.\",\n session_complete: \"Session d'apprentissage terminée !\",\n cards_rated: \" Cartes évaluées: {count}\",\n avg_rating: \" Note moyenne: {avg}\",\n forgot: \" Oubliées: {count} carte(s)\",\n feedback_title: \"── Commentaires ZAM {line}\",\n answer_title: \"── Réponse {line}\",\n keep_waiting: \"Voulez-vous continuer à attendre l'évaluation ?\",\n local_ai_working:\n \"L'IA locale est toujours en train de générer la réponse.\",\n wait_warning: \"⚠ Le serveur LLM prend du temps pour charger le modèle.\",\n wait_info:\n \"(Ceci est normal lors de la transition entre modèles ou du démarrage à froid.)\",\n keep_waiting_llm: \"Voulez-vous continuer à attendre le modèle ?\",\n proceeding_offline:\n \"⚠ Poursuite en mode hors ligne (sans évaluation active de l'IA pour cette session).\",\n eval_skipped: \" [Évaluation LLM ignorée : {reason}]\",\n },\n pt: {\n welcome: \"Sessão de aprendizado: {count} cartão(ões)\",\n new_review_relearn:\n \" Novos: {newC} Revisar: {reviewC} Reaprender: {relearnC}\",\n domains: \" Domínios: {domains}\",\n instruction:\n \"\\nLembre-se de cada resposta primeiro, revele-a e avalie-se honestamente.\",\n quit_hint: \"Digite 'q' (ou Ctrl+C) para parar a qualquer momento.\",\n offline_warning:\n \"\\n\\x1b[33m⚠ O feedback do LLM e a tradução automática estão desativados.\\x1b[0m\",\n offline_instruction:\n \" Ativar com: \\x1b[36mnpm run dev -- settings llm on\\x1b[0m\\n\",\n nothing_due: \"Nada faturado para aprender. Você está atualizado!\",\n evaluating: \"Avaliando a resposta via IA local...\",\n generating_question: \"Gerando pergunta dinâmica...\",\n translating: \"Traduzindo pergunta dinamicamente...\",\n prompt_answer: \"Sua resposta (Enter para revelar · 'q' para parar):\",\n session_ended: \"Sessão de aprendizado encerrada.\",\n session_complete: \"Sessão de aprendizado concluída!\",\n cards_rated: \" Cartões avaliados: {count}\",\n avg_rating: \" Nota média: {avg}\",\n forgot: \" Esquecidos: {count} cartão(ões)\",\n feedback_title: \"── Feedback ZAM {line}\",\n answer_title: \"── Resposta {line}\",\n keep_waiting: \"Deseja continuar esperando pela avaliação?\",\n local_ai_working: \"A IA local ainda está gerando a resposta.\",\n wait_warning: \"⚠ O servidor LLM está demorando para carregar o modelo.\",\n wait_info: \"(Isso é esperado ao alternar modelos ou iniciar do zero.)\",\n keep_waiting_llm: \"Deseja continuar esperando o modelo?\",\n proceeding_offline:\n \"⚠ Continuando no modo offline (sem avaliações de LLM ativas nesta sessão).\",\n eval_skipped: \" [Avaliação LLM omitida: {reason}]\",\n },\n zh: {\n welcome: \"学习课: {count} 张卡片\",\n new_review_relearn: \" 新卡: {newC} 复习: {reviewC} 重学: {relearnC}\",\n domains: \" 知识领域: {domains}\",\n instruction: \"\\n首先在脑中回忆答案,然后揭晓并诚实自我评分。\",\n quit_hint: \"在回答提示处输入 'q' (或按 Ctrl+C) 可随时退出。\",\n offline_warning: \"\\n\\x1b[33m⚠ LLM 反馈与自动翻译已禁用。\\x1b[0m\",\n offline_instruction:\n \" 开启命令: \\x1b[36mnpm run dev -- settings llm on\\x1b[0m\\n\",\n nothing_due: \"目前没有需要学习的内容。您已全部掌握!\",\n evaluating: \"正在通过本地 AI 评估回答...\",\n generating_question: \"正在动态生成问题...\",\n translating: \"正在动态翻译问题...\",\n prompt_answer: \"您的回答 (按回车揭晓 · 输入 'q' 退出):\",\n session_ended: \"学习课已结束。\",\n session_complete: \"学习课已完成!\",\n cards_rated: \" 已评分卡片: {count}\",\n avg_rating: \" 平均分: {avg}\",\n forgot: \" 遗忘: {count} 张卡片\",\n feedback_title: \"── ZAM 反馈 {line}\",\n answer_title: \"── 参考答案 {line}\",\n keep_waiting: \"是否继续等待评分?\",\n local_ai_working: \"本地 AI 仍在生成回答。\",\n wait_warning: \"⚠ LLM 服务器正在加载模型,这可能需要一些时间。\",\n wait_info: \"(这在切换模型或冷启动时是正常现象。)\",\n keep_waiting_llm: \"是否继续等待模型加载?\",\n proceeding_offline:\n \"⚠ 正在以离线模式继续(本次学习课将不包含活跃的 AI 评估)。\",\n eval_skipped: \" [已跳过 LLM 评估: {reason}]\",\n },\n ja: {\n welcome: \"学習セッション: {count} 枚のカード\",\n new_review_relearn: \" 新規: {newC} 復習: {reviewC} 再学習: {relearnC}\",\n domains: \" ドメイン: {domains}\",\n instruction:\n \"\\n最初に回答を思い出し、次に回答を表示して、正直に自己評価してください。\",\n quit_hint:\n \"回答プロンプトで「q」を入力する(または Ctrl+C を押す)と、いつでも終了できます。\",\n offline_warning:\n \"\\n\\x1b[33m⚠ LLM フィードバックと自動翻訳は無効です。\\x1b[0m\",\n offline_instruction:\n \" 有効化するには: \\x1b[36mnpm run dev -- settings llm on\\x1b[0m\\n\",\n nothing_due: \"学習予定のカードはありません。すべて完了しています!\",\n evaluating: \"ローカルAIによる回答の評価中...\",\n generating_question: \"質問を動的に生成中...\",\n translating: \"質問を動的に翻訳中...\",\n prompt_answer: \"あなたの回答 (Enterで表示 · 'q'で終了):\",\n session_ended: \"学習セッションが終了しました。\",\n session_complete: \"学習セッションが完了しました!\",\n cards_rated: \" 評価済みカード数: {count}\",\n avg_rating: \" 平均評価: {avg}\",\n forgot: \" 忘れたカード数: {count} 枚\",\n feedback_title: \"── ZAM フィードバック {line}\",\n answer_title: \"── 解答 {line}\",\n keep_waiting: \"評価の生成を待ちますか?\",\n local_ai_working: \"ローカルAIが回答を生成しています。\",\n wait_warning:\n \"⚠ LLM サーバーがモデルをロードするのに時間がかかっています。\",\n wait_info: \"(モデルの移行中やコールドスタート時には、これが予想されます。)\",\n keep_waiting_llm: \"モデルのロードを待ち続けますか?\",\n proceeding_offline:\n \"⚠ オフラインモードで続行します(このセッションではアクティブな AI 評価は行われません)。\",\n eval_skipped: \" [LLM 評価がスキップされました: {reason}]\",\n },\n};\n\n/**\n * Format and interpolate a translation string with key-value params.\n */\nexport function t(\n locale: SupportedLocale,\n key: TranslationKey,\n params: Record<string, string | number> = {},\n): string {\n const dict = TRANSLATIONS[locale] || TRANSLATIONS.en;\n let str = dict[key] || TRANSLATIONS.en[key] || \"\";\n\n for (const [k, v] of Object.entries(params)) {\n str = str.replace(new RegExp(`{${k}}`, \"g\"), String(v));\n }\n\n return str;\n}\n","/**\n * Per-machine install configuration — Increment 12, Phase 3.\n *\n * Records whether this machine runs ZAM in \"developer\" mode (source checkout,\n * git-backed workspace, manual `git`/`npm` updates) or \"default\" mode (an\n * installed application updated through a package manager or the in-app\n * updater). Stored in ~/.zam/config.json — a per-machine file, NOT the database\n * and NOT the personal folder, so the mode never travels through a shared Turso\n * database or a synced folder, where it would be wrong for the other machine.\n *\n * The personal-content folder itself is unchanged: it stays the existing\n * `personal.workspace_dir` setting, and can already point at any local or\n * file-synced directory (Drive, OneDrive, Dropbox, iCloud) — no GitHub required.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport type { InstallChannel } from \"./update-check.js\";\n\nexport type InstallMode = \"developer\" | \"default\";\n\nexport interface InstallConfig {\n mode?: InstallMode;\n /** How this copy was installed; drives the self-update mechanism. */\n channel?: InstallChannel;\n}\n\nconst DEFAULT_CONFIG_PATH = join(homedir(), \".zam\", \"config.json\");\n\n/** Load ~/.zam/config.json. Returns an empty config if missing or unreadable. */\nexport function loadInstallConfig(path = DEFAULT_CONFIG_PATH): InstallConfig {\n if (!existsSync(path)) return {};\n try {\n return JSON.parse(readFileSync(path, \"utf-8\")) as InstallConfig;\n } catch {\n return {};\n }\n}\n\n/** Persist the install config, preserving any unrelated keys already on disk. */\nexport function saveInstallConfig(\n config: InstallConfig,\n path = DEFAULT_CONFIG_PATH,\n): void {\n const dir = dirname(path);\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n writeFileSync(path, `${JSON.stringify(config, null, 2)}\\n`, \"utf-8\");\n}\n\n/**\n * This machine's install mode. Defaults to \"developer\" — the only historical\n * mode — so existing source/CLI installs keep their behavior. A packaged\n * \"default\" install writes mode explicitly at install time.\n */\nexport function getInstallMode(path = DEFAULT_CONFIG_PATH): InstallMode {\n return loadInstallConfig(path).mode ?? \"developer\";\n}\n\nexport function setInstallMode(\n mode: InstallMode,\n path = DEFAULT_CONFIG_PATH,\n): void {\n const config = loadInstallConfig(path);\n config.mode = mode;\n saveInstallConfig(config, path);\n}\n\n/**\n * How this copy was installed, used to pick the self-update mechanism. Falls\n * back to \"developer\" for developer mode and \"direct\" for an installed app\n * whose channel was not recorded.\n */\nexport function getInstallChannel(path = DEFAULT_CONFIG_PATH): InstallChannel {\n const config = loadInstallConfig(path);\n if (config.channel) return config.channel;\n return (config.mode ?? \"developer\") === \"developer\" ? \"developer\" : \"direct\";\n}\n\nexport function setInstallChannel(\n channel: InstallChannel,\n path = DEFAULT_CONFIG_PATH,\n): void {\n const config = loadInstallConfig(path);\n config.channel = channel;\n saveInstallConfig(config, path);\n}\n\n/**\n * Best-effort detection of the file-sync provider a folder lives in, from its\n * path. Used only for friendly messaging (\"this folder syncs via OneDrive —\n * good for moving snapshots between machines\"), never for behavior.\n */\nexport function detectSyncProvider(dir: string): string | null {\n const p = dir.toLowerCase();\n if (p.includes(\"onedrive\")) return \"OneDrive\";\n if (p.includes(\"dropbox\")) return \"Dropbox\";\n if (\n p.includes(\"google drive\") ||\n p.includes(\"googledrive\") ||\n p.includes(\"/my drive\")\n ) {\n return \"Google Drive\";\n }\n if (p.includes(\"icloud\") || p.includes(\"mobile documents\")) {\n return \"iCloud Drive\";\n }\n return null;\n}\n","import { execFileSync, execSync } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nexport interface InstallResult {\n success: boolean;\n message: string;\n}\n\nexport type LocalLLMRunner = \"fastflowlm\" | \"ollama\" | \"generic\";\n\n/** A resolved way to install a tool: a human label and the command to run. */\nexport interface InstallPlan {\n method: string;\n command: string;\n}\n\n/**\n * Check if a command is executable on the system.\n */\nexport function hasCommand(cmd: string): boolean {\n try {\n const checkCmd =\n process.platform === \"win32\" ? `where ${cmd}` : `which ${cmd}`;\n execSync(checkCmd, { stdio: \"ignore\" });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Install FastFlowLM via winget on Windows.\n */\nexport function installFastFlowLM(): InstallResult {\n if (process.platform !== \"win32\") {\n return {\n success: false,\n message: \"FastFlowLM is only supported on Windows.\",\n };\n }\n\n // Check if already installed\n const hasFlm =\n hasCommand(\"flm\") || existsSync(\"C:\\\\Program Files\\\\flm\\\\flm.exe\");\n if (hasFlm) {\n return { success: true, message: \"FastFlowLM is already installed.\" };\n }\n\n if (!hasCommand(\"winget\")) {\n return {\n success: false,\n message: \"winget package manager was not found on this system.\",\n };\n }\n\n console.log(\"Installing FastFlowLM via winget...\");\n try {\n // -e option exact match, --accept-source-agreements --accept-package-agreements\n execSync(\n \"winget install -e --id FastFlowLM --accept-source-agreements --accept-package-agreements\",\n { stdio: \"inherit\" },\n );\n return { success: true, message: \"FastFlowLM installed successfully.\" };\n } catch (err) {\n return {\n success: false,\n message: `Failed to install FastFlowLM: ${(err as Error).message}`,\n };\n }\n}\n\n/**\n * Install Ollama via Homebrew on macOS.\n */\nexport function installOllama(): InstallResult {\n // Check if already installed\n const isMac = process.platform === \"darwin\";\n const isWin = process.platform === \"win32\";\n const hasOllama =\n hasCommand(\"ollama\") ||\n (isMac && existsSync(\"/Applications/Ollama.app\")) ||\n (isWin &&\n existsSync(\n join(homedir(), \"AppData\", \"Local\", \"Programs\", \"Ollama\", \"ollama.exe\"),\n ));\n\n if (hasOllama) {\n return { success: true, message: \"Ollama is already installed.\" };\n }\n\n if (process.platform === \"darwin\") {\n if (!hasCommand(\"brew\")) {\n return {\n success: false,\n message:\n \"Homebrew was not found. Please install Homebrew from brew.sh first.\",\n };\n }\n console.log(\"Installing Ollama via Homebrew Cask...\");\n try {\n execSync(\"brew install --cask ollama\", { stdio: \"inherit\" });\n return { success: true, message: \"Ollama installed successfully.\" };\n } catch (err) {\n return {\n success: false,\n message: `Failed to install Ollama: ${(err as Error).message}`,\n };\n }\n } else if (process.platform === \"win32\") {\n if (!hasCommand(\"winget\")) {\n return {\n success: false,\n message: \"winget was not found. Please install winget first.\",\n };\n }\n console.log(\"Installing Ollama via winget...\");\n try {\n execSync(\n \"winget install -e --id Ollama.Ollama --accept-source-agreements --accept-package-agreements\",\n { stdio: \"inherit\" },\n );\n return { success: true, message: \"Ollama installed successfully.\" };\n } catch (err) {\n return {\n success: false,\n message: `Failed to install Ollama: ${(err as Error).message}`,\n };\n }\n } else {\n // Linux installer script\n console.log(\"Installing Ollama via official installer script...\");\n try {\n execSync(\"curl -fsSL https://ollama.com/install.sh | sh\", {\n stdio: \"inherit\",\n });\n return { success: true, message: \"Ollama installed successfully.\" };\n } catch (err) {\n return {\n success: false,\n message: `Failed to install Ollama: ${(err as Error).message}`,\n };\n }\n }\n}\n\nfunction resolveOllamaCommand(): string | undefined {\n if (hasCommand(\"ollama\")) return \"ollama\";\n\n const candidates =\n process.platform === \"win32\"\n ? [\n join(\n homedir(),\n \"AppData\",\n \"Local\",\n \"Programs\",\n \"Ollama\",\n \"ollama.exe\",\n ),\n ]\n : process.platform === \"darwin\"\n ? [\"/Applications/Ollama.app/Contents/Resources/ollama\"]\n : [];\n\n return candidates.find((candidate) => existsSync(candidate));\n}\n\n/**\n * Prepare the recommended model after installing a local LLM runner.\n */\nexport function prepareLocalModel(\n runner: LocalLLMRunner,\n model: string,\n): InstallResult {\n if (runner === \"fastflowlm\") {\n return {\n success: true,\n message: `${model} will be downloaded by FastFlowLM on first use.`,\n };\n }\n\n if (runner !== \"ollama\") {\n return {\n success: false,\n message: \"No supported local LLM runner was selected.\",\n };\n }\n\n const ollamaCommand = resolveOllamaCommand();\n if (!ollamaCommand) {\n return {\n success: false,\n message:\n \"Ollama was installed but its command is not available yet. Restart the terminal, then run \" +\n `ollama pull ${model}.`,\n };\n }\n\n console.log(`Downloading ${model} with Ollama...`);\n try {\n execFileSync(ollamaCommand, [\"pull\", model], { stdio: \"inherit\" });\n return { success: true, message: `${model} is ready in Ollama.` };\n } catch (err) {\n return {\n success: false,\n message:\n `Could not prepare ${model}: ${(err as Error).message}. ` +\n `Start Ollama and run: ollama pull ${model}`,\n };\n }\n}\n\n/**\n * Pick how to install the opencode agent for the current machine.\n *\n * npm is preferred on every platform: ZAM already requires Node, and the\n * `opencode-ai` package pulls the correct native binary for Apple Silicon and\n * Windows on ARM — avoiding the bash-on-Windows and Homebrew-tap caveats.\n * Returns null when no automatic method is available (e.g. Windows without npm,\n * Scoop, or Chocolatey).\n */\nexport function planOpenCodeInstall(env: {\n platform: NodeJS.Platform;\n hasNpm: boolean;\n hasBrew: boolean;\n hasScoop: boolean;\n hasChoco: boolean;\n}): InstallPlan | null {\n if (env.hasNpm) {\n return { method: \"npm\", command: \"npm install -g opencode-ai\" };\n }\n if (env.platform === \"darwin\") {\n if (env.hasBrew) {\n return {\n method: \"homebrew\",\n command: \"brew install anomalyco/tap/opencode\",\n };\n }\n return {\n method: \"script\",\n command: \"curl -fsSL https://opencode.ai/install | bash\",\n };\n }\n if (env.platform === \"win32\") {\n if (env.hasScoop)\n return { method: \"scoop\", command: \"scoop install opencode\" };\n if (env.hasChoco) {\n return { method: \"chocolatey\", command: \"choco install opencode\" };\n }\n return null;\n }\n // Linux and other Unix-likes.\n return {\n method: \"script\",\n command: \"curl -fsSL https://opencode.ai/install | bash\",\n };\n}\n\n/**\n * Install the opencode agent (the default agent ZAM provisions). opencode reads\n * the AGENTS.md that `zam setup` writes, so it picks up the ZAM skill once both\n * are present.\n */\nexport function installOpenCode(): InstallResult {\n if (hasCommand(\"opencode\")) {\n return { success: true, message: \"opencode is already installed.\" };\n }\n\n const plan = planOpenCodeInstall({\n platform: process.platform,\n hasNpm: hasCommand(\"npm\"),\n hasBrew: hasCommand(\"brew\"),\n hasScoop: hasCommand(\"scoop\"),\n hasChoco: hasCommand(\"choco\"),\n });\n\n if (!plan) {\n return {\n success: false,\n message:\n \"Could not find a way to install opencode automatically. Install npm, \" +\n \"Scoop, or Chocolatey, or follow https://opencode.ai/docs (native \" +\n \"Apple Silicon and Windows on ARM builds are available).\",\n };\n }\n\n console.log(`Installing opencode via ${plan.method}...`);\n try {\n execSync(plan.command, { stdio: \"inherit\" });\n return { success: true, message: `opencode installed via ${plan.method}.` };\n } catch (err) {\n return {\n success: false,\n message:\n `Failed to install opencode: ${(err as Error).message}. ` +\n `Try manually: ${plan.command}`,\n };\n }\n}\n","import { execSync } from \"node:child_process\";\n\nexport type SupportedLocale = \"en\" | \"de\" | \"es\" | \"fr\" | \"pt\" | \"zh\" | \"ja\";\n\nconst SUPPORTED_LOCALES: Set<SupportedLocale> = new Set([\n \"en\",\n \"de\",\n \"es\",\n \"fr\",\n \"pt\",\n \"zh\",\n \"ja\",\n]);\n\n/**\n * Clean and map raw locale string (e.g., \"de_DE.UTF-8\" or \"en-US\") to SupportedLocale.\n */\nexport function normalizeLocale(raw: string): SupportedLocale {\n const clean = raw.trim().toLowerCase().split(/[_-]/)[0];\n if (SUPPORTED_LOCALES.has(clean as SupportedLocale)) {\n return clean as SupportedLocale;\n }\n return \"en\";\n}\n\n/**\n * Detect the operating system's active language code dynamically.\n */\nexport function detectSystemLocale(): SupportedLocale {\n try {\n // 1. Check standard POSIX env vars (common on macOS/Linux/Git Bash/WSL)\n const envVars = [\n process.env.LANG,\n process.env.LANGUAGE,\n process.env.LC_ALL,\n process.env.LC_MESSAGES,\n ];\n\n for (const val of envVars) {\n if (val && val.trim().length > 0) {\n return normalizeLocale(val);\n }\n }\n\n // 2. On Windows, fallback to querying PowerShell Culture\n if (process.platform === \"win32\") {\n const output = execSync(\n 'powershell -NoProfile -Command \"[System.Globalization.CultureInfo]::CurrentCulture.Name\"',\n { stdio: \"pipe\", encoding: \"utf8\", timeout: 2000 },\n ).trim();\n if (output && output.length > 0) {\n return normalizeLocale(output);\n }\n }\n } catch {\n // Ignore errors and default to English\n }\n\n return \"en\";\n}\n","import { execSync } from \"node:child_process\";\n\nexport interface SystemProfile {\n os: \"windows\" | \"macos\" | \"linux\" | \"unknown\";\n arch: \"x64\" | \"arm64\" | \"unknown\";\n hasRyzenNPU: boolean;\n hasAppleSilicon: boolean;\n recommendedRunner: \"fastflowlm\" | \"ollama\" | \"generic\";\n recommendedModel: string;\n}\n\n/**\n * Run a shell command synchronously and return stdout.\n * Returns empty string on failure.\n */\nfunction runCommand(cmd: string): string {\n try {\n return execSync(cmd, { stdio: \"pipe\", encoding: \"utf8\" }).trim();\n } catch {\n return \"\";\n }\n}\n\nfunction detectWindowsAMDIPU(): boolean {\n if (process.platform !== \"win32\") return false;\n\n // WMI query for AMD IPU (Image Processing Unit), NPU, Ryzen AI CPUs, and modern NPU compute devices (DEV_1502, DEV_17F0)\n const cmd = `powershell -NoProfile -Command \"Get-CimInstance Win32_PnPEntity | Where-Object { $_.Name -like '*AMD IPU*' -or $_.Name -like '*AMD NPU*' -or $_.Name -like '*NPU Compute*' -or $_.Name -like '*Ryzen AI*' -or $_.HardwareID -like '*VEN_1022&DEV_1502*' -or $_.HardwareID -like '*VEN_1022&DEV_17F0*' } | Select-Object -First 1 -ExpandProperty Name\"`;\n const output = runCommand(cmd);\n\n return Boolean(\n output &&\n (output.toLowerCase().includes(\"amd\") ||\n output.toLowerCase().includes(\"ipu\") ||\n output.toLowerCase().includes(\"npu\") ||\n output.toLowerCase().includes(\"ryzen\")),\n );\n}\n\n/**\n * Profile the active system hardware and software capabilities.\n */\nexport function getSystemProfile(): SystemProfile {\n const platform = process.platform;\n const archStr = process.arch;\n\n let os: \"windows\" | \"macos\" | \"linux\" | \"unknown\" = \"unknown\";\n if (platform === \"win32\") os = \"windows\";\n else if (platform === \"darwin\") os = \"macos\";\n else if (platform === \"linux\") os = \"linux\";\n\n let arch: \"x64\" | \"arm64\" | \"unknown\" = \"unknown\";\n if (archStr === \"x64\") arch = \"x64\";\n else if (archStr === \"arm64\") arch = \"arm64\";\n\n const hasRyzenNPU = os === \"windows\" && detectWindowsAMDIPU();\n const hasAppleSilicon = os === \"macos\" && arch === \"arm64\";\n\n let recommendedRunner: \"fastflowlm\" | \"ollama\" | \"generic\" = \"generic\";\n let recommendedModel = \"qwen3.5:4b\";\n\n if (hasRyzenNPU) {\n recommendedRunner = \"fastflowlm\";\n recommendedModel = \"qwen3.5:4b\";\n } else if (hasAppleSilicon) {\n recommendedRunner = \"ollama\";\n recommendedModel = \"llama3.2:3b\";\n } else if (os === \"macos\" || os === \"linux\" || os === \"windows\") {\n // Standard PC / generic Mac\n recommendedRunner = \"ollama\";\n recommendedModel = \"llama3.2:3b\";\n }\n\n return {\n os,\n arch,\n hasRyzenNPU,\n hasAppleSilicon,\n recommendedRunner,\n recommendedModel,\n };\n}\n","import { existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { Database } from \"../db/types.js\";\nimport { getSetting } from \"../models/settings.js\";\n\nexport interface RepoPaths {\n personal: string | null;\n team: string | null;\n org: string | null;\n}\n\n/**\n * Resolve absolute paths for personal, team, and organization repositories.\n * Personal falls back to personal.workspace_dir if repo.personal is not set.\n */\nexport async function getRepoPaths(db: Database): Promise<RepoPaths> {\n const personalSetting =\n (await getSetting(db, \"repo.personal\")) ||\n (await getSetting(db, \"personal.workspace_dir\"));\n const teamSetting = await getSetting(db, \"repo.team\");\n const orgSetting = await getSetting(db, \"repo.org\");\n\n return {\n personal: personalSetting ? resolve(personalSetting) : null,\n team: teamSetting ? resolve(teamSetting) : null,\n org: orgSetting ? resolve(orgSetting) : null,\n };\n}\n\n/**\n * Resolve a specific repo's path, or null if not configured.\n */\nexport async function resolveRepoPath(\n db: Database,\n type: \"personal\" | \"team\" | \"org\",\n): Promise<string | null> {\n const paths = await getRepoPaths(db);\n return paths[type];\n}\n\n/**\n * Resolve paths to all existing \"/beliefs\" directories in the hierarchy,\n * sorted from most specific (personal) to most general (org).\n */\nexport async function resolveAllBeliefPaths(db: Database): Promise<string[]> {\n const paths = await getRepoPaths(db);\n const dirs: string[] = [];\n\n if (paths.personal) {\n const personalDir = resolve(paths.personal, \"beliefs\");\n if (existsSync(personalDir)) dirs.push(personalDir);\n }\n if (paths.team) {\n const teamDir = resolve(paths.team, \"beliefs\");\n if (existsSync(teamDir)) dirs.push(teamDir);\n }\n if (paths.org) {\n const orgDir = resolve(paths.org, \"beliefs\");\n if (existsSync(orgDir)) dirs.push(orgDir);\n }\n\n return dirs;\n}\n\n/**\n * Resolve paths to all existing \"/goals\" directories in the hierarchy,\n * sorted from most specific (personal) to most general (org).\n */\nexport async function resolveAllGoalPaths(db: Database): Promise<string[]> {\n const paths = await getRepoPaths(db);\n const dirs: string[] = [];\n\n if (paths.personal) {\n const personalDir = resolve(paths.personal, \"goals\");\n if (existsSync(personalDir)) dirs.push(personalDir);\n }\n if (paths.team) {\n const teamDir = resolve(paths.team, \"goals\");\n if (existsSync(teamDir)) dirs.push(teamDir);\n }\n if (paths.org) {\n const orgDir = resolve(paths.org, \"goals\");\n if (existsSync(orgDir)) dirs.push(orgDir);\n }\n\n return dirs;\n}\n","/**\n * Update-decision logic — Increment 12, Phase 5.\n *\n * The brain behind \"the app noticed a newer version\": given the current and\n * latest versions and how this copy was installed, decide what the UI should\n * do. Deliberately network-free and pure, so it is fully unit-tested; the\n * actual version fetch (e.g. GitHub releases) and the Tauri self-update live in\n * the CLI/desktop layers that call this.\n */\n\nexport type InstallChannel = \"developer\" | \"direct\" | \"winget\" | \"homebrew\";\n\n/** Provisional package identifiers; finalized when channels ship (Phase 2). */\nexport const WINGET_PACKAGE_ID = \"ZAM.ZAM\";\nexport const HOMEBREW_CASK = \"zam\";\n\nexport type UpdateActionKind =\n | \"none\"\n | \"self-update\"\n | \"run-command\"\n | \"inform\";\n\nexport interface UpdateDecision {\n updateAvailable: boolean;\n currentVersion: string;\n latestVersion: string;\n channel: InstallChannel;\n /** What the UI should do about the update. */\n action: UpdateActionKind;\n /** For \"run-command\"/\"inform\": the command to surface to the user. */\n command?: string;\n /** Locale-agnostic explanation; the UI provides its own localized copy. */\n reason: string;\n}\n\ninterface ParsedVersion {\n core: number[];\n pre: string[];\n}\n\nfunction parseVersion(version: string): ParsedVersion {\n const clean = version.trim().replace(/^v/i, \"\");\n const [main, pre = \"\"] = clean.split(\"-\", 2);\n const core = main.split(\".\").map((n) => Number.parseInt(n, 10) || 0);\n while (core.length < 3) core.push(0);\n return { core, pre: pre ? pre.split(\".\") : [] };\n}\n\n/**\n * Compare two semver-ish versions. Returns 1 if `a` is newer than `b`, -1 if\n * older, 0 if equal. A version with a prerelease tag (1.0.0-beta) sorts below\n * the same core release (1.0.0), per semver.\n */\nexport function compareVersions(a: string, b: string): -1 | 0 | 1 {\n const pa = parseVersion(a);\n const pb = parseVersion(b);\n\n for (let i = 0; i < 3; i++) {\n if (pa.core[i] !== pb.core[i]) return pa.core[i] > pb.core[i] ? 1 : -1;\n }\n\n if (pa.pre.length === 0 && pb.pre.length === 0) return 0;\n if (pa.pre.length === 0) return 1; // release > prerelease\n if (pb.pre.length === 0) return -1;\n\n const len = Math.max(pa.pre.length, pb.pre.length);\n for (let i = 0; i < len; i++) {\n const x = pa.pre[i];\n const y = pb.pre[i];\n if (x === undefined) return -1; // shorter prerelease set has lower precedence\n if (y === undefined) return 1;\n\n const xNum = /^\\d+$/.test(x);\n const yNum = /^\\d+$/.test(y);\n if (xNum && yNum) {\n const dx = Number(x);\n const dy = Number(y);\n if (dx !== dy) return dx > dy ? 1 : -1;\n } else if (xNum !== yNum) {\n return xNum ? -1 : 1; // numeric identifiers rank below alphanumeric\n } else if (x !== y) {\n return x > y ? 1 : -1;\n }\n }\n return 0;\n}\n\n/**\n * Decide what to do given current/latest versions and the install channel.\n * The mechanism follows how the copy was installed so we never self-replace a\n * package-managed install or a source checkout.\n */\nexport function decideUpdate(input: {\n currentVersion: string;\n latestVersion: string;\n channel: InstallChannel;\n}): UpdateDecision {\n const { currentVersion, latestVersion, channel } = input;\n const base = { currentVersion, latestVersion, channel };\n\n if (compareVersions(latestVersion, currentVersion) <= 0) {\n return {\n ...base,\n updateAvailable: false,\n action: \"none\",\n reason: \"Already on the latest version.\",\n };\n }\n\n switch (channel) {\n case \"direct\":\n return {\n ...base,\n updateAvailable: true,\n action: \"self-update\",\n reason: \"A signed update can be installed in place.\",\n };\n case \"winget\":\n return {\n ...base,\n updateAvailable: true,\n action: \"run-command\",\n command: `winget upgrade --id ${WINGET_PACKAGE_ID}`,\n reason: \"Update available through winget.\",\n };\n case \"homebrew\":\n return {\n ...base,\n updateAvailable: true,\n action: \"run-command\",\n command: `brew upgrade --cask ${HOMEBREW_CASK}`,\n reason: \"Update available through Homebrew.\",\n };\n default:\n return {\n ...base,\n updateAvailable: true,\n action: \"inform\",\n command: \"git pull && npm install && npm run build\",\n reason: \"Developer install — update from source.\",\n };\n }\n}\n","/**\n * `zam bridge` — Machine-readable JSON protocol for AI integration.\n *\n * All output is valid JSON only. No human-readable formatting.\n * Errors are also JSON: { \"error\": \"message\" }\n */\n\nimport { readdirSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { Command } from \"commander\";\nimport type {\n BloomLevel,\n Database,\n NeighborhoodToken,\n Rating,\n ReviewActionType,\n SymbiosisMode,\n TokenPattern,\n} from \"../../kernel/index.js\";\nimport {\n analyzeObservation,\n buildReviewQueue,\n createToken,\n discoverSkills,\n ensureCard,\n executeReviewAction,\n generatePrompt,\n getAgentSkill,\n getCardDeletionImpact,\n getDueCards,\n getSetting,\n getTokenBySlug,\n getTokenDeleteImpact,\n getTokenNeighborhood,\n listAgentSkills,\n listTokens,\n monitorLogExists,\n openDatabase,\n pairCommands,\n readMonitorLog,\n resolveReviewContext,\n} from \"../../kernel/index.js\";\nimport {\n ensureHighQualityQuestion,\n ensureLlmReadyHeadless,\n evaluateAnswerViaLLM,\n getAvailableModels,\n getLlmConfig,\n isLlmOnline,\n translateQuestionViaLLM,\n} from \"../llm/client.js\";\nimport { ensureDefaultUser, resolveUser } from \"./resolve-user.js\";\nimport { withDb as sharedWithDb } from \"./shared/db.js\";\n\nlet isServeMode = false;\n\nfunction jsonOut(data: unknown): void {\n console.log(JSON.stringify(data, null, 2));\n}\n\nfunction jsonError(message: string): never {\n if (isServeMode) {\n throw new Error(JSON.stringify({ error: message }));\n }\n console.log(JSON.stringify({ error: message }, null, 2));\n process.exit(1);\n}\n\nasync function withDb(\n fn: (db: Database) => void | Promise<void>,\n): Promise<void> {\n await sharedWithDb(fn, jsonError);\n}\n\ninterface ReviewTargetRow {\n card_id: string;\n token_id: string;\n user_id: string;\n slug: string;\n}\n\nasync function getReviewTarget(\n db: Database,\n cardId: string,\n userId: string,\n): Promise<ReviewTargetRow> {\n const target = (await db\n .prepare(\n `SELECT c.id AS card_id, c.token_id, c.user_id, t.slug\n FROM cards c\n JOIN tokens t ON t.id = c.token_id\n WHERE c.id = ?`,\n )\n .get(cardId)) as ReviewTargetRow | undefined;\n\n if (!target) {\n jsonError(`Card not found: ${cardId}`);\n }\n if (target.user_id !== userId) {\n jsonError(`Card ${cardId} does not belong to user ${userId}`);\n }\n\n return target!;\n}\n\nfunction parseTokenUpdates(opts: {\n concept?: string;\n domain?: string;\n bloom?: string;\n context?: string;\n mode?: string;\n sourceLink?: string;\n}): {\n concept?: string;\n domain?: string;\n bloom_level?: BloomLevel;\n context?: string;\n symbiosis_mode?: SymbiosisMode | null;\n source_link?: string | null;\n} {\n const updates: {\n concept?: string;\n domain?: string;\n bloom_level?: BloomLevel;\n context?: string;\n symbiosis_mode?: SymbiosisMode | null;\n source_link?: string | null;\n } = {};\n\n if (opts.concept !== undefined) updates.concept = opts.concept;\n if (opts.domain !== undefined) updates.domain = opts.domain;\n if (opts.bloom !== undefined)\n updates.bloom_level = Number(opts.bloom) as BloomLevel;\n if (opts.context !== undefined) updates.context = opts.context;\n if (opts.sourceLink !== undefined) {\n updates.source_link = opts.sourceLink === \"\" ? null : opts.sourceLink;\n }\n if (opts.mode !== undefined) {\n const validModes = [\"shadowing\", \"copilot\", \"autonomy\", \"none\"];\n if (!validModes.includes(opts.mode)) {\n jsonError(`Invalid mode: ${opts.mode}`);\n }\n updates.symbiosis_mode =\n opts.mode === \"none\" ? null : (opts.mode as SymbiosisMode);\n }\n\n return updates;\n}\n\nexport const bridgeCommand = new Command(\"bridge\").description(\n \"Machine-readable JSON protocol for AI integration\",\n);\n\n// ── zam bridge check-due ──────────────────────────────────────────────────\n\nbridgeCommand\n .command(\"check-due\")\n .description(\"Check due cards for a user (JSON)\")\n .option(\"--user <id>\", \"User ID (default: whoami)\")\n .action(async (opts) => {\n await withDb(async (db) => {\n const userId = await resolveUser(opts, db, { json: true });\n const dueCards = await getDueCards(db, userId);\n const domains = [\n ...new Set(dueCards.map((c) => c.domain).filter(Boolean)),\n ].sort();\n\n jsonOut({\n userId,\n dueCount: dueCards.length,\n domains,\n cards: dueCards.map((c) => ({\n cardId: c.id,\n tokenId: c.token_id,\n slug: c.slug,\n concept: c.concept,\n domain: c.domain,\n bloomLevel: c.bloom_level,\n state: c.state,\n dueAt: c.due_at,\n })),\n });\n });\n });\n\n// ── zam bridge get-review ─────────────────────────────────────────────────\n\nbridgeCommand\n .command(\"get-review\")\n .description(\"Get next review card with prompt (JSON)\")\n .option(\"--user <id>\", \"User ID (default: whoami)\")\n .option(\"--no-resolve\", \"Skip resolving the token's source_link into context\")\n .action(async (opts) => {\n await withDb(async (db) => {\n const userId = await resolveUser(opts, db, { json: true });\n const queue = await buildReviewQueue(db, {\n userId,\n maxReviews: 1,\n maxNew: 1,\n });\n\n if (queue.items.length === 0) {\n jsonOut({\n userId,\n hasReview: false,\n card: null,\n prompt: null,\n resolvedContext: null,\n queueSize: 0,\n });\n return;\n }\n\n const item = queue.items[0];\n const isLlmEnabled = (await getSetting(db, \"llm.enabled\")) === \"true\";\n\n // Dynamically generate a fresh, living active-recall question if LLM is enabled\n let resolvedQuestion = item.question;\n if (isLlmEnabled) {\n try {\n const healed = await ensureHighQualityQuestion(db, {\n id: item.tokenId,\n slug: item.slug,\n concept: item.concept,\n domain: item.domain,\n bloomLevel: item.bloomLevel as BloomLevel,\n sourceLink: item.sourceLink,\n question: item.question,\n });\n if (healed) {\n resolvedQuestion = healed;\n }\n } catch {\n // ignore and proceed\n }\n }\n\n const prompt = generatePrompt({\n cardId: item.cardId,\n tokenId: item.tokenId,\n slug: item.slug,\n concept: item.concept,\n domain: item.domain,\n bloomLevel: item.bloomLevel as BloomLevel,\n sourceLink: item.sourceLink,\n question: resolvedQuestion,\n });\n\n // Resolve the source_link into ready-to-use context for the AI client.\n // Defensive: never let a bad/unreachable reference break the review payload.\n let resolvedContext = null;\n if (opts.resolve !== false) {\n try {\n resolvedContext = await resolveReviewContext(item.sourceLink);\n } catch {\n resolvedContext = null;\n }\n }\n\n // Get full queue size for context\n const fullQueue = await buildReviewQueue(db, { userId });\n\n jsonOut({\n userId,\n hasReview: true,\n card: item,\n prompt,\n resolvedContext,\n queueSize: fullQueue.items.length,\n });\n });\n });\n\n// ── zam bridge submit ─────────────────────────────────────────────────────\n\nbridgeCommand\n .command(\"submit\")\n .description(\"Submit a rating for a card (JSON)\")\n .option(\"--user <id>\", \"User ID (default: whoami)\")\n .requiredOption(\"--card-id <id>\", \"Card ID\")\n .requiredOption(\"--rating <n>\", \"Rating (1-4)\")\n .action(async (opts) => {\n await withDb(async (db) => {\n const userId = await resolveUser(opts, db, { json: true });\n const rating = Number(opts.rating) as Rating;\n if (rating < 1 || rating > 4) {\n jsonError(\"Rating must be between 1 and 4\");\n }\n\n const result = await executeReviewAction(db, {\n action: \"rate\",\n cardId: opts.cardId,\n userId,\n rating,\n });\n\n jsonOut({\n success: true,\n rating,\n evaluation: result.evaluation,\n blocked: result.blocked ?? null,\n });\n });\n });\n\n// ── zam bridge review-action ───────────────────────────────────────────────\n\nbridgeCommand\n .command(\"review-action\")\n .description(\"Apply a review action (JSON)\")\n .option(\"--user <id>\", \"User ID (default: whoami)\")\n .requiredOption(\"--card-id <id>\", \"Card ID\")\n .requiredOption(\n \"--action <action>\",\n \"Action: rate | skip | edit-token | deprecate-token | delete-token | delete-card | stop\",\n )\n .option(\"--rating <n>\", \"Rating (1-4) for action=rate\")\n .option(\"--concept <concept>\", \"Updated concept text for action=edit-token\")\n .option(\"--domain <domain>\", \"Updated domain for action=edit-token\")\n .option(\"--bloom <level>\", \"Updated Bloom level for action=edit-token\")\n .option(\"--context <context>\", \"Updated context for action=edit-token\")\n .option(\"--mode <mode>\", \"Updated symbiosis mode for action=edit-token\")\n .option(\"--source-link <link>\", \"Updated source link for action=edit-token\")\n .option(\"--confirm\", \"Confirm destructive delete actions\")\n .action(async (opts) => {\n await withDb(async (db) => {\n const userId = await resolveUser(opts, db, { json: true });\n const action = opts.action as ReviewActionType;\n const validActions: ReviewActionType[] = [\n \"rate\",\n \"skip\",\n \"edit-token\",\n \"deprecate-token\",\n \"delete-token\",\n \"delete-card\",\n \"stop\",\n ];\n if (!validActions.includes(action)) {\n jsonError(`Unsupported action: ${opts.action}`);\n }\n\n const target = await getReviewTarget(db, opts.cardId, userId);\n if (\n (action === \"delete-token\" || action === \"delete-card\") &&\n !opts.confirm\n ) {\n if (action === \"delete-token\") {\n jsonOut({\n success: true,\n action,\n preview: true,\n requiresConfirmation: true,\n token: { slug: target.slug, tokenId: target.token_id },\n impact: await getTokenDeleteImpact(db, target.slug),\n });\n return;\n }\n\n jsonOut({\n success: true,\n action,\n preview: true,\n requiresConfirmation: true,\n token: { slug: target.slug, tokenId: target.token_id },\n impact: await getCardDeletionImpact(db, target.token_id, userId),\n });\n return;\n }\n\n const rating =\n opts.rating !== undefined ? (Number(opts.rating) as Rating) : undefined;\n if (action === \"rate\" && (rating == null || rating < 1 || rating > 4)) {\n jsonError(\"Rating must be between 1 and 4 for action=rate\");\n }\n\n const result = await executeReviewAction(db, {\n action,\n cardId: opts.cardId,\n userId,\n rating,\n tokenUpdates:\n action === \"edit-token\" ? parseTokenUpdates(opts) : undefined,\n });\n\n jsonOut({\n success: true,\n action,\n token: {\n slug: result.token.slug,\n tokenId: result.token.id,\n },\n rating: rating ?? null,\n evaluation: result.evaluation ?? null,\n blocked: result.blocked ?? null,\n updatedToken: result.updatedToken ?? null,\n deletedToken: result.deletedToken ?? null,\n deletedCard: result.deletedCard ?? null,\n skipped: result.skipped ?? false,\n stopped: result.stopped ?? false,\n });\n });\n });\n\n// ── zam bridge get-skill ──────────────────────────────────────────────────\n\nbridgeCommand\n .command(\"get-skill\")\n .description(\"Get an agent skill by slug (JSON)\")\n .requiredOption(\"--slug <slug>\", \"Skill slug\")\n .action(async (opts) => {\n await withDb(async (db) => {\n const skill = await getAgentSkill(db, opts.slug);\n if (!skill) {\n jsonError(`Skill not found: ${opts.slug}`);\n }\n\n jsonOut({\n slug: skill?.slug,\n description: skill?.description,\n steps: skill?.steps,\n tokenSlugs: skill?.token_slugs,\n source: skill?.source,\n });\n });\n });\n\n// ── zam bridge get-monitor ────────────────────────────────────────────────\n\nbridgeCommand\n .command(\"get-monitor\")\n .description(\"Read monitor log for a session (JSON)\")\n .requiredOption(\"--session <id>\", \"Session ID\")\n .action((opts) => {\n if (!monitorLogExists(opts.session)) {\n jsonOut({\n sessionId: opts.session,\n exists: false,\n commands: [],\n timeSpan: null,\n });\n return;\n }\n\n const events = readMonitorLog(opts.session);\n const commands = pairCommands(events);\n\n let timeSpan: { start: string; end: string; durationMs: number } | null =\n null;\n if (commands.length > 0) {\n const first = commands[0];\n const last = commands[commands.length - 1];\n const endTs = last.endedAt ?? last.startedAt;\n timeSpan = {\n start: first.startedAt,\n end: endTs,\n durationMs:\n new Date(endTs).getTime() - new Date(first.startedAt).getTime(),\n };\n }\n\n jsonOut({\n sessionId: opts.session,\n exists: true,\n commands: commands.map((c) => ({\n seq: c.seq,\n command: c.command,\n cwd: c.cwd,\n startedAt: c.startedAt,\n endedAt: c.endedAt,\n durationMs: c.durationMs,\n exitCode: c.exitCode,\n })),\n timeSpan,\n });\n });\n\n// ── zam bridge analyze-monitor ───────────────────────────────────────────\n\nbridgeCommand\n .command(\"analyze-monitor\")\n .description(\"Analyze monitor log with token patterns from stdin (JSON)\")\n .requiredOption(\"--session <id>\", \"Session ID\")\n .action(async (opts) => {\n try {\n if (!monitorLogExists(opts.session)) {\n jsonOut({\n sessionId: opts.session,\n ratings: [],\n unmatchedCommands: [],\n timeSpan: null,\n });\n return;\n }\n\n // Read token patterns from stdin\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(chunk as Buffer);\n }\n const raw = Buffer.concat(chunks).toString(\"utf-8\").trim();\n\n if (!raw) {\n jsonError(\"No input received on stdin. Pipe JSON with token patterns.\");\n }\n\n let data: { patterns: TokenPattern[] };\n try {\n data = JSON.parse(raw);\n } catch {\n jsonError(\"Invalid JSON input\");\n }\n\n if (!Array.isArray(data?.patterns)) {\n jsonError(\"JSON must include 'patterns' array\");\n }\n\n const events = readMonitorLog(opts.session);\n const commands = pairCommands(events);\n const result = analyzeObservation(commands, data?.patterns);\n\n jsonOut({\n sessionId: opts.session,\n ...result,\n });\n } catch (err) {\n jsonError((err as Error).message);\n }\n });\n\n// ── zam bridge add-token ──────────────────────────────────────────────────\n\nbridgeCommand\n .command(\"add-token\")\n .description(\"Create a token + card from JSON stdin\")\n .option(\"--user <id>\", \"User ID (default: whoami)\")\n .action(async (opts) => {\n let db: Database | undefined;\n try {\n // Read JSON from stdin\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(chunk as Buffer);\n }\n const raw = Buffer.concat(chunks).toString(\"utf-8\").trim();\n\n if (!raw) {\n jsonError(\"No input received on stdin. Pipe JSON with token data.\");\n }\n\n let data: {\n slug: string;\n concept: string;\n domain?: string;\n bloom_level?: number;\n context?: string;\n symbiosis_mode?: string | null;\n source_link?: string | null;\n };\n\n try {\n data = JSON.parse(raw);\n } catch {\n jsonError(\"Invalid JSON input\");\n }\n\n if (!data?.slug || !data?.concept) {\n jsonError(\"JSON must include 'slug' and 'concept' fields\");\n }\n\n db = await openDatabase();\n const userId = await resolveUser(opts, db, { json: true });\n\n const token = await createToken(db, {\n slug: data?.slug,\n concept: data?.concept,\n domain: data?.domain,\n bloom_level: (data?.bloom_level ?? 1) as BloomLevel,\n context: data?.context,\n symbiosis_mode: data?.symbiosis_mode as\n | \"shadowing\"\n | \"copilot\"\n | \"autonomy\"\n | null\n | undefined,\n source_link: data?.source_link ?? null,\n });\n\n const card = await ensureCard(db, token.id, userId);\n\n jsonOut({\n success: true,\n token,\n card: {\n id: card.id,\n tokenId: card.token_id,\n userId: card.user_id,\n state: card.state,\n dueAt: card.due_at,\n blocked: card.blocked,\n },\n });\n\n await db.close();\n } catch (err) {\n await db?.close();\n // If it's already a JSON error exit, let it propagate\n if ((err as Error).message) {\n jsonError((err as Error).message);\n }\n }\n });\n\n// ── zam bridge discover-skills ──────────────────────────────────────────────\n\nbridgeCommand\n .command(\"discover-skills\")\n .description(\n \"Analyze monitor logs across sessions to discover recurring patterns\",\n )\n .option(\n \"--min-sessions <n>\",\n \"Minimum sessions a pattern must appear in (default: 2)\",\n \"2\",\n )\n .option(\n \"--limit <n>\",\n \"Max number of sessions to analyze (default: 20)\",\n \"20\",\n )\n .action(async (opts) => {\n try {\n const monitorDir = join(homedir(), \".zam\", \"monitor\");\n let files: string[];\n try {\n files = readdirSync(monitorDir).filter((f) => f.endsWith(\".jsonl\"));\n } catch {\n jsonOut({ proposals: [], message: \"No monitor logs found.\" });\n return;\n }\n\n if (files.length === 0) {\n jsonOut({ proposals: [], message: \"No monitor logs found.\" });\n return;\n }\n\n // Take the most recent N sessions by file modification time\n const limit = Number(opts.limit);\n const sorted = files\n .map((f) => ({ name: f, path: join(monitorDir, f) }))\n .sort((a, b) => b.name.localeCompare(a.name)) // ULID session IDs sort chronologically\n .slice(0, limit);\n\n // Load and parse each session's commands\n const sessionCommands = new Map<\n string,\n ReturnType<typeof pairCommands>\n >();\n for (const file of sorted) {\n const sessionId = file.name.replace(\".jsonl\", \"\");\n const events = readMonitorLog(sessionId);\n const commands = pairCommands(events);\n if (commands.length > 0) {\n sessionCommands.set(sessionId, commands);\n }\n }\n\n if (sessionCommands.size === 0) {\n jsonOut({ proposals: [], message: \"No command data in monitor logs.\" });\n return;\n }\n\n // Get existing skills to exclude\n let existingSkillSlugs: string[] = [];\n let db: Database | undefined;\n try {\n db = await openDatabase();\n existingSkillSlugs = (await listAgentSkills(db)).map((s) => s.slug);\n } catch {\n // DB not available — proceed without exclusion\n } finally {\n await db?.close();\n }\n\n const proposals = discoverSkills(sessionCommands, {\n minSessions: Number(opts.minSessions),\n existingSkillSlugs,\n });\n\n jsonOut({\n sessionsAnalyzed: sessionCommands.size,\n proposals,\n });\n } catch (err) {\n jsonError((err as Error).message);\n }\n });\n\n// ── zam bridge check-llm ──────────────────────────────────────────────────\n\nbridgeCommand\n .command(\"check-llm\")\n .description(\"Check if LLM is enabled and online (JSON)\")\n .action(async () => {\n await withDb(async (db) => {\n const { enabled, url, model, apiKey } = await getLlmConfig(db);\n let online = false;\n let availableModels: string[] = [];\n let modelAvailable = false;\n if (enabled) {\n online = await isLlmOnline(url);\n if (online) {\n availableModels = await getAvailableModels(url, apiKey);\n // Empty list = server doesn't expose /models; don't claim it's wrong.\n modelAvailable =\n availableModels.length === 0 ||\n availableModels.some(\n (m) => m.toLowerCase() === model.toLowerCase(),\n );\n }\n }\n jsonOut({\n enabled,\n online,\n url,\n model,\n modelAvailable,\n availableModels,\n });\n });\n });\n\n// ── zam bridge ensure-llm ─────────────────────────────────────────────────\n\nbridgeCommand\n .command(\"ensure-llm\")\n .description(\n \"Start the local LLM server if needed and report readiness (JSON)\",\n )\n .option(\n \"--timeout <ms>\",\n \"Max time to wait for the server to come online\",\n \"25000\",\n )\n .action(async (opts) => {\n await withDb(async (db) => {\n const result = await ensureLlmReadyHeadless(db, {\n timeoutMs: Number(opts.timeout),\n });\n jsonOut(result);\n });\n });\n\n// ── zam bridge translate-question ──────────────────────────────────────────\n\nbridgeCommand\n .command(\"translate-question\")\n .description(\"Translate a question dynamically using the local LLM (JSON)\")\n .requiredOption(\"--question <text>\", \"Question in English to translate\")\n .action(async (opts) => {\n await withDb(async (db) => {\n const isEnabled = (await getSetting(db, \"llm.enabled\")) === \"true\";\n if (!isEnabled) {\n jsonOut({\n success: false,\n error: \"LLM integration is disabled\",\n translation: opts.question,\n });\n return;\n }\n try {\n const translation = await translateQuestionViaLLM(db, opts.question);\n jsonOut({ success: true, translation });\n } catch (err) {\n jsonOut({\n success: false,\n error: (err as Error).message,\n translation: opts.question,\n });\n }\n });\n });\n\n// ── zam bridge evaluate-answer ────────────────────────────────────────────\n\nbridgeCommand\n .command(\"evaluate-answer\")\n .description(\n \"Evaluate the learner's active-recall answer using the local LLM (JSON)\",\n )\n .requiredOption(\"--slug <slug>\", \"Token slug\")\n .requiredOption(\"--concept <concept>\", \"Target concept text\")\n .requiredOption(\"--domain <domain>\", \"Token domain\")\n .requiredOption(\"--bloom-level <level>\", \"Bloom taxonomy level\")\n .requiredOption(\"--question <question>\", \"Question prompt presented\")\n .requiredOption(\"--user-answer <answer>\", \"User's typed answer\")\n .option(\"--context <context>\", \"Optional token context details\")\n .option(\"--source-link <link>\", \"Optional source link\")\n .action(async (opts) => {\n await withDb(async (db) => {\n const isEnabled = (await getSetting(db, \"llm.enabled\")) === \"true\";\n if (!isEnabled) {\n jsonOut({\n success: false,\n error: \"LLM integration is disabled\",\n evaluation: \"\",\n });\n return;\n }\n\n let resolvedContextContent = null;\n if (opts.sourceLink) {\n try {\n const resolved = await resolveReviewContext(opts.sourceLink);\n resolvedContextContent = resolved?.content ?? null;\n } catch {\n // ignore context resolution errors\n }\n }\n\n try {\n const evaluation = await evaluateAnswerViaLLM(db, {\n slug: opts.slug,\n concept: opts.concept,\n domain: opts.domain,\n bloomLevel: Number(opts.bloomLevel),\n context: opts.context,\n question: opts.question,\n userAnswer: opts.userAnswer,\n sourceLinkContent: resolvedContextContent,\n });\n jsonOut({ success: true, evaluation });\n } catch (err) {\n jsonOut({\n success: false,\n error: (err as Error).message,\n evaluation: \"\",\n });\n }\n });\n });\n\n// ── zam bridge desktop-bootstrap / get-settings ───────────────────────────\n\nbridgeCommand\n .command(\"desktop-bootstrap\")\n .description(\"Initialize first-run desktop state (JSON)\")\n .option(\"--user <id>\", \"Preferred user ID when none is configured\")\n .action(async (opts) => {\n await withDb(async (db) => {\n const userId = await ensureDefaultUser(db, opts.user);\n const { enabled, url, model, locale } = await getLlmConfig(db);\n jsonOut({\n userId,\n locale,\n llm: { enabled, url, model },\n });\n });\n });\n\nbridgeCommand\n .command(\"get-settings\")\n .description(\"Get active ZAM settings (JSON)\")\n .action(async () => {\n await withDb(async (db) => {\n const { enabled, url, model, locale } = await getLlmConfig(db);\n jsonOut({\n locale,\n llm: {\n enabled,\n url,\n model,\n },\n });\n });\n });\n\n// ── zam bridge list-tokens (for graph pickers / entry points) ───────────────\n\nbridgeCommand\n .command(\"list-tokens\")\n .description(\n \"List tokens (optionally enriched with user card state for viz) (JSON)\",\n )\n .option(\n \"--user <id>\",\n \"User ID (default: whoami) — when provided, includes personal card info\",\n )\n .option(\"--domain <domain>\", \"Filter by domain\")\n .action(async (opts) => {\n await withDb(async (db) => {\n const userId = opts.user\n ? await resolveUser(opts, db, { json: true })\n : undefined;\n const tokens = await listTokens(\n db,\n opts.domain ? { domain: opts.domain } : undefined,\n );\n\n const cardMap = new Map<\n string,\n {\n token_id: string;\n state: string;\n reps: number;\n stability: number;\n difficulty: number;\n blocked: number;\n due_at: string;\n last_review_at: string | null;\n }\n >();\n if (userId && tokens.length > 0) {\n const ids = tokens.map((t) => t.id);\n const placeholders = ids.map(() => \"?\").join(\",\");\n const cards = (await db\n .prepare(\n `SELECT token_id, state, reps, stability, difficulty, blocked, due_at, last_review_at\n FROM cards WHERE token_id IN (${placeholders}) AND user_id = ?`,\n )\n .all(...ids, userId)) as Array<{\n token_id: string;\n state: string;\n reps: number;\n stability: number;\n difficulty: number;\n blocked: number;\n due_at: string;\n last_review_at: string | null;\n }>;\n for (const c of cards) cardMap.set(c.token_id, c);\n }\n\n const out = tokens.map((t) => {\n const c = cardMap.get(t.id);\n return {\n id: t.id,\n slug: t.slug,\n concept: t.concept,\n domain: t.domain,\n bloomLevel: t.bloom_level,\n card: c\n ? {\n state: c.state,\n reps: c.reps,\n stability: c.stability,\n difficulty: c.difficulty,\n blocked: c.blocked === 1,\n dueAt: c.due_at,\n lastReviewAt: c.last_review_at ?? null,\n }\n : null,\n };\n });\n\n jsonOut({ tokens: out });\n });\n });\n\n// ── zam bridge get-neighborhood (core for 3D focus + direct prereqs/dependents) ─\n\nbridgeCommand\n .command(\"get-neighborhood\")\n .description(\n \"Get direct prerequisite neighborhood around a token (for 3D graph viz) (JSON)\",\n )\n .requiredOption(\"--focus <slug>\", \"Token slug to center the neighborhood on\")\n .option(\n \"--user <id>\",\n \"User ID (default: whoami) for personal card state in the result\",\n )\n .action(async (opts) => {\n await withDb(async (db) => {\n const userId = await resolveUser(opts, db, { json: true });\n\n const token = await getTokenBySlug(db, opts.focus);\n if (!token) {\n jsonError(`Token not found: ${opts.focus}`);\n }\n\n const nb = await getTokenNeighborhood(db, token!.id, userId);\n\n const mapToken = (nt: NeighborhoodToken) => ({\n id: nt.id,\n slug: nt.slug,\n concept: nt.concept,\n domain: nt.domain,\n bloomLevel: nt.bloom_level,\n card: nt.card\n ? {\n state: nt.card.state,\n reps: nt.card.reps,\n stability: nt.card.stability,\n difficulty: nt.card.difficulty,\n blocked: nt.card.blocked,\n dueAt: nt.card.due_at,\n lastReviewAt: nt.card.last_review_at,\n }\n : null,\n });\n\n jsonOut({\n focus: opts.focus,\n center: mapToken(nb.center),\n prerequisites: nb.prerequisites.map(mapToken),\n dependents: nb.dependents.map(mapToken),\n });\n });\n });\n\n// ── zam bridge serve ──────────────────────────────────────────────────────\n\nbridgeCommand\n .command(\"serve\")\n .description(\"Start the persistent JSON-RPC stdin/stdout server\")\n .option(\"--stdin\", \"Use stdin/stdout for communication\")\n .action(async (_opts) => {\n isServeMode = true;\n\n // Diagnostic log. A windowed GUI swallows the daemon's stderr, so failures\n // that only happen when the bridge is spawned by the desktop app are\n // otherwise invisible. Logging the resolved environment makes a wrong\n // home directory (→ missing credentials → empty database) obvious.\n const {\n appendFileSync,\n existsSync: fileExists,\n mkdirSync: makeDir,\n } = await import(\"node:fs\");\n const nodeOs = await import(\"node:os\");\n const nodePath = await import(\"node:path\");\n const logDir = nodePath.join(nodeOs.homedir(), \".zam\");\n const logPath = nodePath.join(logDir, \"desktop-bridge.log\");\n const logDiag = (msg: string): void => {\n try {\n if (!fileExists(logDir)) makeDir(logDir, { recursive: true });\n appendFileSync(logPath, `[${new Date().toISOString()}] ${msg}\\n`);\n } catch {\n // best-effort only — never let logging break the bridge\n }\n };\n logDiag(\n `serve start | homedir=${nodeOs.homedir()} | USERPROFILE=${\n process.env.USERPROFILE ?? \"\"\n } | HOME=${process.env.HOME ?? \"\"} | cwd=${process.cwd()}`,\n );\n\n // Configure exitOverride so commander doesn't process.exit on parsing errors\n bridgeCommand.exitOverride();\n for (const cmd of bridgeCommand.commands) {\n cmd.exitOverride();\n }\n\n // Prevent Commander from writing directly to stdout/stderr\n let outputBuffer = \"\";\n const outputOpts = {\n writeOut: (str: string) => {\n outputBuffer += str;\n },\n writeErr: (str: string) => {\n outputBuffer += str;\n },\n };\n bridgeCommand.configureOutput(outputOpts);\n for (const cmd of bridgeCommand.commands) {\n cmd.configureOutput(outputOpts);\n }\n\n const processRequest = async (line: string): Promise<string> => {\n outputBuffer = \"\";\n let requestId: string | number | null = null;\n try {\n const req = JSON.parse(line);\n requestId = req.id ?? null;\n const cmd = req.cmd;\n const args = req.args ?? [];\n\n if (!cmd) {\n return JSON.stringify({\n id: requestId,\n error: \"Missing 'cmd' field\",\n });\n }\n\n const originalLog = console.log;\n const originalError = console.error;\n console.log = (...logArgs) => {\n outputBuffer += `${logArgs\n .map((a) => (typeof a === \"object\" ? JSON.stringify(a) : String(a)))\n .join(\" \")}\\n`;\n };\n console.error = (...logArgs) => {\n outputBuffer += `${logArgs\n .map((a) => (typeof a === \"object\" ? JSON.stringify(a) : String(a)))\n .join(\" \")}\\n`;\n };\n\n try {\n await bridgeCommand.parseAsync([\"node\", \"bridge\", cmd, ...args]);\n } catch (err) {\n if (err instanceof Error && err.message.startsWith('{\"error\":')) {\n try {\n const parsed = JSON.parse(err.message);\n return JSON.stringify({ id: requestId, error: parsed.error });\n } catch {\n return JSON.stringify({ id: requestId, error: err.message });\n }\n }\n if ((err as { code?: string }).code?.startsWith(\"commander.\")) {\n return JSON.stringify({\n id: requestId,\n error: outputBuffer.trim() || (err as Error).message,\n });\n }\n return JSON.stringify({\n id: requestId,\n error: (err as Error).message || String(err),\n });\n } finally {\n console.log = originalLog;\n console.error = originalError;\n }\n\n // Parse stdout accumulated output\n let result: unknown;\n const trimmed = outputBuffer.trim();\n try {\n result = JSON.parse(trimmed);\n } catch {\n result = trimmed;\n }\n\n return JSON.stringify({ id: requestId, result });\n } catch (err) {\n return JSON.stringify({\n id: requestId,\n error: `Invalid JSON request: ${(err as Error).message}`,\n });\n }\n };\n\n const readline = await import(\"node:readline\");\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n terminal: false,\n });\n\n // Process requests strictly one at a time. processRequest() relies on a\n // shared output buffer and temporarily swaps the global console methods, so\n // overlapping executions would corrupt each other's responses. Chaining on\n // a single promise serialises them regardless of how fast lines arrive.\n let pending: Promise<void> = Promise.resolve();\n rl.on(\"line\", (line) => {\n if (!line.trim()) return;\n pending = pending.then(async () => {\n const response = await processRequest(line);\n process.stdout.write(`${response}\\n`);\n });\n });\n });\n","/**\n * Local LLM client — CLI/harness layer.\n *\n * This module talks to a user-run, OpenAI-compatible local LLM server\n * (FastFlowLM `flm serve`, Ollama, LM Studio, …). It deliberately lives in the\n * CLI layer, NOT the kernel: the kernel is AI-agnostic and carries zero LLM\n * dependencies (see CLAUDE.md). Everything that does HTTP, spawns runner\n * processes, prints to the terminal, or prompts interactively belongs here.\n *\n * Config is read from kernel settings via a single `getLlmConfig` helper so the\n * default model lives in exactly one place (it changes every few weeks as local\n * models improve).\n */\n\nimport { spawn } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport type { Database, SupportedLocale } from \"../../kernel/index.js\";\nimport {\n getSetting,\n getSystemProfile,\n hasCommand,\n resolveReviewContext,\n t,\n updateToken,\n} from \"../../kernel/index.js\";\n\n/** Single source of truth for connection defaults (easy to bump as models evolve). */\nexport const DEFAULT_LLM_URL = \"http://localhost:8000/v1\";\nexport const DEFAULT_LLM_MODEL = \"qwen3.5:4b\";\nexport const DEFAULT_LLM_API_KEY = \"sk-none\";\n\nexport interface LlmConfig {\n enabled: boolean;\n url: string;\n model: string;\n apiKey: string;\n locale: SupportedLocale;\n}\n\n/** Read all LLM-related settings at once, applying defaults in one place. */\nexport async function getLlmConfig(db: Database): Promise<LlmConfig> {\n return {\n enabled: (await getSetting(db, \"llm.enabled\")) === \"true\",\n url: (await getSetting(db, \"llm.url\")) || DEFAULT_LLM_URL,\n model: (await getSetting(db, \"llm.model\")) || DEFAULT_LLM_MODEL,\n apiKey: (await getSetting(db, \"llm.api_key\")) || DEFAULT_LLM_API_KEY,\n locale: ((await getSetting(db, \"system.locale\")) ||\n \"en\") as SupportedLocale,\n };\n}\n\nconst LANGUAGE_NAMES: Record<SupportedLocale, string> = {\n en: \"English\",\n de: \"German\",\n es: \"Spanish\",\n fr: \"French\",\n pt: \"Portuguese\",\n zh: \"Chinese\",\n ja: \"Japanese\",\n};\n\nconst LOCALIZED_RATING_PREFIX: Record<SupportedLocale, string> = {\n en: \"Suggested rating\",\n de: \"Empfohlene Bewertung\",\n es: \"Calificación sugerida\",\n fr: \"Note suggérée\",\n pt: \"Avaliação sugerida\",\n zh: \"建议评分\",\n ja: \"推奨評価\",\n};\n\nconst BLOOM_VERBS = {\n 1: \"Remember\",\n 2: \"Understand\",\n 3: \"Apply\",\n 4: \"Analyze\",\n 5: \"Synthesize\",\n} as const;\n\ninterface ChatCompletionResponse {\n choices?: Array<{ message?: { content?: string } }>;\n}\n\n/** Extract the assistant message content from an OpenAI-compatible response. */\nasync function readChatContent(res: Response, label: string): Promise<string> {\n if (!res.ok) {\n const errorText = await res.text().catch(() => \"\");\n throw new Error(\n `${label} failed: ${res.statusText} (${res.status}) - ${errorText}`,\n );\n }\n const data = (await res.json()) as ChatCompletionResponse;\n const content = data.choices?.[0]?.message?.content;\n if (!content) {\n throw new Error(\"Empty response from LLM\");\n }\n return content.trim();\n}\n\n/**\n * Generate a high-quality, concept-free active-recall question using the local LLM.\n */\nexport async function generateQuestionViaLLM(\n db: Database,\n input: {\n slug: string;\n concept: string;\n domain: string;\n bloomLevel: number;\n context?: string;\n sourceLinkContent?: string | null;\n },\n): Promise<string> {\n const cfg = await getLlmConfig(db);\n if (!cfg.enabled) {\n throw new Error(\"LLM integration is disabled in settings (llm.enabled)\");\n }\n\n const bloom = (\n input.bloomLevel >= 1 && input.bloomLevel <= 5 ? input.bloomLevel : 1\n ) as keyof typeof BLOOM_VERBS;\n const verb = BLOOM_VERBS[bloom];\n\n const langName = LANGUAGE_NAMES[cfg.locale] || \"English\";\n\n const systemPrompt = `You are ZAM, a highly precise agentic skills trainer.\nYour task is to generate a single, clear, conceptual active-recall question (flashcard front) in ${langName} for a knowledge token.\n\nGuidelines:\n1. The question MUST match the Bloom level: ${verb} (Level ${bloom}).\n2. CRITICAL: The question MUST NOT contain or reveal the concept text itself! The concept is the answer (flashcard back) that the learner needs to recall.\n3. Keep the question concise, highly specific, and clear. Avoid generic prompts like \"What is the concept of...\" if possible, and ask about the core mechanism, function, or purpose of the slug/concept without giving the answer away.\n4. Output ONLY the raw question text in ${langName}. Do not include any preamble, headers, markdown fences, or conversational filler.`;\n\n const userPrompt = `Domain: ${input.domain}\nSlug: ${input.slug}\nConcept to Recall (DO NOT REVEAL IN QUESTION): ${input.concept}\nContext: ${input.context || \"(none)\"}\n${input.sourceLinkContent ? `Source Reference:\\n${input.sourceLinkContent}` : \"\"}\n\nActive-Recall Question:`;\n\n const res = await fetchWithInteractiveTimeout(`${cfg.url}/chat/completions`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${cfg.apiKey}`,\n },\n body: JSON.stringify({\n model: cfg.model,\n messages: [\n { role: \"system\", content: systemPrompt },\n { role: \"user\", content: userPrompt },\n ],\n temperature: 0.1,\n max_tokens: 150,\n }),\n locale: cfg.locale,\n });\n\n return readChatContent(res, \"LLM request\");\n}\n\n/**\n * Warmly evaluate the learner's active-recall answer against the target concept.\n * Suggests an FSRS rating (1-4) and explains in the active locale with praise/motivation.\n */\nexport async function evaluateAnswerViaLLM(\n db: Database,\n input: {\n slug: string;\n concept: string;\n domain: string;\n bloomLevel: number;\n context?: string;\n question: string;\n userAnswer: string;\n sourceLinkContent?: string | null;\n },\n): Promise<string> {\n const cfg = await getLlmConfig(db);\n if (!cfg.enabled) {\n throw new Error(\"LLM integration is disabled in settings (llm.enabled)\");\n }\n const langName = LANGUAGE_NAMES[cfg.locale] || \"English\";\n const ratingPrefix =\n LOCALIZED_RATING_PREFIX[cfg.locale] || \"Suggested rating\";\n\n const systemPrompt = `You are ZAM, an extremely warm, encouraging, and patient skills trainer.\nYour mission is to build lasting autonomy through conceptual knowledge, not rote procedure.\nCompare the learner's active-recall answer against the target concept, context, and optional source code.\n\nFSRS Rating scale:\n- 1: drew a blank / completely forgot or wrong (Again)\n- 2: hard recall / partially correct (Hard)\n- 3: knew it / mostly correct (Good)\n- 4: perfect, instant, and accurate recall (Easy)\n\nGuidelines:\n1. Provide a constructive, encouraging evaluation in ${langName} (2-3 sentences) to promote the joy of learning. Seamlessly weave a brief explanation of the correct solution (target concept) into your feedback paragraphs. Do NOT append a separate, duplicate reference answer or raw \"Musterlösung\" block at the end of your response.\n2. Celebrate every honest attempt! Offer high praise or a motivating word of encouragement in ${langName} if they did well or tried hard.\n3. CRITICAL: ZAM is a strict one-shot card flow, NOT an interactive chat. The correct Musterlösung (reference answer) is revealed alongside your feedback. Therefore, NEVER ask the user to think further, keep guessing, or suggest they try to solve the remaining parts of the question. Instead, immediately evaluate what they wrote, explain the complete solution and target concept directly.\n4. Suggest a clear FSRS rating (1 to 4) at the very end of your response in the exact format: \"${ratingPrefix}: X\" in ${langName}.\n5. Output ONLY the evaluation and rating suggestion. Keep it concise, friendly, and clean. No conversational introduction or markdown wrapper.`;\n\n const userPrompt = `Domain: ${input.domain}\nSlug: ${input.slug}\nRecall Question: ${input.question}\nLearner's Answer: ${input.userAnswer}\n\nTarget Concept (Correct Answer): ${input.concept}\nTarget Context: ${input.context || \"(none)\"}\n${input.sourceLinkContent ? `Source Code Reference:\\n${input.sourceLinkContent}` : \"\"}\n\nEvaluation:`;\n\n const res = await fetchWithInteractiveTimeout(`${cfg.url}/chat/completions`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${cfg.apiKey}`,\n },\n body: JSON.stringify({\n model: cfg.model,\n messages: [\n { role: \"system\", content: systemPrompt },\n { role: \"user\", content: userPrompt },\n ],\n temperature: 0.2,\n max_tokens: 300,\n }),\n locale: cfg.locale,\n });\n\n return readChatContent(res, \"LLM evaluation\");\n}\n\n/**\n * Translate a question into the active locale using the local LLM.\n */\nexport async function translateQuestionViaLLM(\n db: Database,\n question: string,\n): Promise<string> {\n const cfg = await getLlmConfig(db);\n if (!cfg.enabled) {\n throw new Error(\"LLM integration is disabled in settings\");\n }\n const targetLang = LANGUAGE_NAMES[cfg.locale] || \"English\";\n\n const systemPrompt = `You are a highly precise translator. Translate the given active-recall question into clear, natural ${targetLang}.\nOutput ONLY the raw translation. Do not include any headers, preamble, quotes, or conversational filler.`;\n\n const res = await fetchWithInteractiveTimeout(`${cfg.url}/chat/completions`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${cfg.apiKey}`,\n },\n body: JSON.stringify({\n model: cfg.model,\n messages: [\n { role: \"system\", content: systemPrompt },\n { role: \"user\", content: question },\n ],\n temperature: 0.1,\n max_tokens: 150,\n }),\n locale: cfg.locale,\n });\n\n return readChatContent(res, \"Translation\");\n}\n\n/**\n * Checks if the LLM server is online and responsive at the specified URL.\n * A reachable server returning any HTTP status counts as online; only network\n * failures / timeouts count as offline.\n */\nexport async function isLlmOnline(url: string): Promise<boolean> {\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), 1500);\n // Check OpenAI standard /models list to verify readiness\n const res = await fetch(`${url}/models`, {\n method: \"GET\",\n signal: controller.signal,\n });\n clearTimeout(timeoutId);\n return res.ok || res.status < 500;\n } catch {\n return false;\n }\n}\n\n/**\n * List the model ids the server actually serves (OpenAI `/v1/models`).\n * Returns [] on any error so callers can treat \"unknown\" as \"skip validation\".\n */\nexport async function getAvailableModels(\n url: string,\n apiKey = DEFAULT_LLM_API_KEY,\n): Promise<string[]> {\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), 3000);\n const res = await fetch(`${url}/models`, {\n method: \"GET\",\n headers: { Authorization: `Bearer ${apiKey}` },\n signal: controller.signal,\n });\n clearTimeout(timeoutId);\n if (!res.ok) return [];\n const data = (await res.json()) as { data?: Array<{ id?: string }> };\n return (data.data ?? [])\n .map((m) => m.id)\n .filter((id): id is string => typeof id === \"string\" && id.length > 0);\n } catch {\n return [];\n }\n}\n\n/** Whether the local LLM can actually be used this session, and if not, why. */\nexport interface LlmReadiness {\n usable: boolean;\n reason?: \"disabled\" | \"offline\" | \"model-not-found\";\n}\n\ntype RunnerKind = \"fastflowlm\" | \"ollama\" | \"generic\" | \"unknown\";\n\n/** Pick the local runner from the URL port / model name (shared heuristic). */\nfunction detectRunner(\n url: string,\n model: string,\n): { runner: RunnerKind; port: string } {\n let runner: RunnerKind = \"unknown\";\n let port = \"8000\";\n try {\n const urlObj = new URL(url);\n port = urlObj.port || (urlObj.protocol === \"https:\" ? \"443\" : \"80\");\n if (\n port === \"8000\" ||\n port === \"8080\" ||\n model.includes(\"qwen\") ||\n model.includes(\"gemma\")\n ) {\n runner = \"fastflowlm\";\n } else if (port === \"11434\" || model.includes(\"llama\")) {\n runner = \"ollama\";\n }\n } catch {\n runner = getSystemProfile().recommendedRunner;\n }\n return { runner, port };\n}\n\n/**\n * Best-effort, SILENT runner start for non-interactive contexts (bridge / GUI).\n * No console output, no prompts — just spawn the detached server if we can.\n */\nfunction spawnLocalRunner(url: string, model: string): void {\n const { runner, port } = detectRunner(url, model);\n try {\n if (runner === \"fastflowlm\") {\n const flmExe = existsSync(\"C:\\\\Program Files\\\\flm\\\\flm.exe\")\n ? \"C:\\\\Program Files\\\\flm\\\\flm.exe\"\n : \"flm\";\n if (!hasCommand(\"flm\") && flmExe === \"flm\") return;\n spawn(flmExe, [\"serve\", model, \"--port\", port], {\n detached: true,\n stdio: \"ignore\",\n windowsHide: true,\n }).unref();\n } else if (runner === \"ollama\" || runner === \"generic\") {\n if (!hasCommand(\"ollama\")) return;\n spawn(\"ollama\", [\"serve\"], {\n detached: true,\n stdio: \"ignore\",\n windowsHide: true,\n }).unref();\n }\n } catch {\n // best-effort: caller polls for the server and reports offline if it fails\n }\n}\n\n/**\n * Detect the configured runner and start it, then poll until the server is\n * online (or the user opts out). Returns true once reachable, false otherwise.\n */\nasync function startLocalRunner(\n url: string,\n model: string,\n locale: SupportedLocale,\n): Promise<boolean> {\n const { runner, port } = detectRunner(url, model);\n\n if (runner === \"fastflowlm\") {\n const flmExe = existsSync(\"C:\\\\Program Files\\\\flm\\\\flm.exe\")\n ? \"C:\\\\Program Files\\\\flm\\\\flm.exe\"\n : \"flm\";\n if (!hasCommand(\"flm\") && flmExe === \"flm\") {\n console.warn(\n \"\\x1b[31m✗ FastFlowLM is configured but could not be found on the system.\\x1b[0m\",\n );\n console.warn(\"Please run 'zam init' or install it manually.\");\n return false;\n }\n const args = [\"serve\", model, \"--port\", port];\n console.log(\n `\\x1b[36mStarting FastFlowLM serve process: ${flmExe} ${args.join(\" \")}\\x1b[0m`,\n );\n try {\n spawn(flmExe, args, {\n detached: true,\n stdio: \"ignore\",\n windowsHide: true,\n }).unref();\n } catch (err) {\n console.error(\n `\\x1b[31m✗ Failed to launch FastFlowLM process: ${(err as Error).message}\\x1b[0m`,\n );\n return false;\n }\n } else if (runner === \"ollama\" || runner === \"generic\") {\n if (!hasCommand(\"ollama\")) {\n console.warn(\n \"\\x1b[31m✗ Ollama is configured but the 'ollama' command is not available in PATH.\\x1b[0m\",\n );\n console.warn(\"Please run 'zam init' or install it manually.\");\n return false;\n }\n console.log(\"\\x1b[36mStarting Ollama serve process: ollama serve\\x1b[0m\");\n try {\n spawn(\"ollama\", [\"serve\"], {\n detached: true,\n stdio: \"ignore\",\n windowsHide: true,\n }).unref();\n } catch (err) {\n console.error(\n `\\x1b[31m✗ Failed to launch Ollama process: ${(err as Error).message}\\x1b[0m`,\n );\n return false;\n }\n } else {\n console.warn(\n \"\\x1b[33m⚠ Unknown local LLM runner configured. Cannot auto-start.\\x1b[0m\",\n );\n return false;\n }\n\n // Poll until the server is online (or the user opts out).\n console.log(\n \"Waiting for LLM server to become responsive and load the model...\",\n );\n let attempts = 0;\n const dotsPerLine = 30;\n while (true) {\n await new Promise((resolve) => setTimeout(resolve, 500));\n if (await isLlmOnline(url)) {\n if (attempts > 0) process.stdout.write(\"\\n\");\n return true;\n }\n attempts++;\n process.stdout.write(\".\");\n if (attempts % dotsPerLine === 0) process.stdout.write(\"\\n\");\n\n // 60 attempts * 500ms = 30 seconds\n if (attempts >= 60) {\n process.stdout.write(\"\\n\");\n console.log(`\\x1b[33m${t(locale, \"wait_warning\")}\\x1b[0m`);\n console.log(`\\x1b[2m${t(locale, \"wait_info\")}\\x1b[0m`);\n\n const { confirm } = await import(\"@inquirer/prompts\");\n const keepWaiting = await confirm({\n message: t(locale, \"keep_waiting_llm\"),\n default: true,\n }).catch(() => false);\n\n if (!keepWaiting) {\n return false;\n }\n attempts = 0;\n }\n }\n}\n\n/**\n * Make the local LLM ready for the session and report whether it is usable.\n *\n * Starts the local runner if needed, then — crucially — verifies the configured\n * model is actually served. A wrong model name otherwise leaves the server\n * reachable but every request hanging/failing, which previously looked like\n * \"the AI is just slow\". We now fail fast with an actionable message instead.\n */\nexport async function ensureLocalLlmRunning(\n db: Database,\n): Promise<LlmReadiness> {\n const cfg = await getLlmConfig(db);\n if (!cfg.enabled) {\n return { usable: false, reason: \"disabled\" };\n }\n\n const { url, model, apiKey, locale } = cfg;\n const isLocal = url.includes(\"localhost\") || url.includes(\"127.0.0.1\");\n\n console.log(`Checking if local LLM server is online at ${url}...`);\n let online = await isLlmOnline(url);\n\n if (!online && isLocal) {\n console.log(`\\x1b[33m⚠ Local LLM server is offline on ${url}.\\x1b[0m`);\n online = await startLocalRunner(url, model, locale);\n }\n\n if (!online) {\n console.warn(\n `\\x1b[33m⚠ LLM server is not reachable at ${url}. Continuing without AI coaching.\\x1b[0m\\n`,\n );\n return { usable: false, reason: \"offline\" };\n }\n\n console.log(\"\\x1b[32m✓ Local LLM server is online.\\x1b[0m\");\n\n // Validate the configured model against what the server actually serves, so\n // a typo / wrong tag fails immediately instead of hanging on every request.\n const available = await getAvailableModels(url, apiKey);\n const modelKnown =\n available.length === 0 ||\n available.some((m) => m.toLowerCase() === model.toLowerCase());\n\n if (!modelKnown) {\n console.warn(\n `\\x1b[31m✗ Configured model \"${model}\" is not available on the server.\\x1b[0m`,\n );\n console.warn(` Available models: ${available.join(\", \")}`);\n console.warn(\n ` Set the right one: \\x1b[36mzam settings set llm.model <name>\\x1b[0m`,\n );\n console.warn(\n \"\\x1b[33m Continuing this session without AI coaching.\\x1b[0m\\n\",\n );\n return { usable: false, reason: \"model-not-found\" };\n }\n\n return { usable: true };\n}\n\n/** Readiness plus the live status details a UI needs to render. */\nexport interface LlmReadyResult extends LlmReadiness {\n online: boolean;\n model: string;\n availableModels: string[];\n}\n\n/**\n * Non-interactive readiness check for the bridge / desktop GUI: start the local\n * runner if needed, wait (bounded) for it to come online, validate the model —\n * all WITHOUT console output or prompts, so the bridge's JSON stays clean.\n */\nexport async function ensureLlmReadyHeadless(\n db: Database,\n opts: { timeoutMs?: number } = {},\n): Promise<LlmReadyResult> {\n const timeoutMs = opts.timeoutMs ?? 25000;\n const { enabled, url, model, apiKey } = await getLlmConfig(db);\n if (!enabled) {\n return {\n usable: false,\n reason: \"disabled\",\n online: false,\n model,\n availableModels: [],\n };\n }\n\n const isLocal = url.includes(\"localhost\") || url.includes(\"127.0.0.1\");\n\n let online = await isLlmOnline(url);\n if (!online && isLocal) {\n spawnLocalRunner(url, model);\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n await new Promise((r) => setTimeout(r, 1000));\n if (await isLlmOnline(url)) {\n online = true;\n break;\n }\n }\n }\n\n if (!online) {\n return {\n usable: false,\n reason: \"offline\",\n online: false,\n model,\n availableModels: [],\n };\n }\n\n const availableModels = await getAvailableModels(url, apiKey);\n const modelKnown =\n availableModels.length === 0 ||\n availableModels.some((m) => m.toLowerCase() === model.toLowerCase());\n if (!modelKnown) {\n return {\n usable: false,\n reason: \"model-not-found\",\n online: true,\n model,\n availableModels,\n };\n }\n\n return { usable: true, online: true, model, availableModels };\n}\n\n/**\n * Wraps a fetch call in an interactive wait loop with progress dots.\n * Every `timeoutMs`, prompts the user (in their locale) to keep waiting or skip.\n * In non-TTY / bridge contexts the timeout is a hard deadline because there\n * is no interactive prompt that can ask whether to keep waiting.\n */\nexport async function fetchWithInteractiveTimeout(\n url: string,\n options: RequestInit & {\n timeoutMs?: number;\n hardTimeoutMs?: number;\n locale?: SupportedLocale;\n } = {},\n): Promise<Response> {\n const {\n timeoutMs = 20000,\n hardTimeoutMs = 120000,\n locale = \"en\",\n ...fetchOptions\n } = options;\n const controller = new AbortController();\n const fetchPromise = fetch(url, {\n ...fetchOptions,\n signal: controller.signal,\n });\n\n if (!process.stdout.isTTY || process.env.ZAM_BRIDGE === \"true\") {\n let timeoutId: NodeJS.Timeout | undefined;\n const hardTimeout = new Promise<never>((_resolve, reject) => {\n timeoutId = setTimeout(() => {\n reject(new Error(`LLM request timed out after ${hardTimeoutMs}ms`));\n controller.abort();\n }, hardTimeoutMs);\n });\n try {\n return await Promise.race([fetchPromise, hardTimeout]);\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n let attempts = 0;\n const dotsPerLine = 30;\n while (true) {\n let timeoutId: NodeJS.Timeout | undefined;\n const timeoutPromise = new Promise<\"timeout\">((resolve) => {\n timeoutId = setTimeout(() => resolve(\"timeout\"), timeoutMs);\n });\n const dotsInterval = setInterval(() => {\n process.stdout.write(\".\");\n attempts++;\n if (attempts % dotsPerLine === 0) process.stdout.write(\"\\n\");\n }, 500);\n\n try {\n const result = await Promise.race([fetchPromise, timeoutPromise]);\n clearInterval(dotsInterval);\n clearTimeout(timeoutId);\n\n if (result !== \"timeout\") {\n if (attempts > 0) process.stdout.write(\"\\n\");\n return result;\n }\n\n // Timeout hit — ask the learner whether to keep waiting.\n console.log(`\\n\\x1b[33m${t(locale, \"local_ai_working\")}\\x1b[0m`);\n const { confirm } = await import(\"@inquirer/prompts\");\n const keepWaiting = await confirm({\n message: t(locale, \"keep_waiting\"),\n default: true,\n }).catch(() => false);\n\n if (!keepWaiting) {\n controller.abort();\n console.log(`\\x1b[33m${t(locale, \"proceeding_offline\")}\\x1b[0m\\n`);\n throw new Error(\"User cancelled waiting for slow LLM response\");\n }\n attempts = 0;\n } catch (err) {\n clearInterval(dotsInterval);\n clearTimeout(timeoutId);\n if (attempts > 0) process.stdout.write(\"\\n\");\n throw err;\n }\n }\n}\n\n/**\n * Ensures a token has a high-quality active-recall question.\n * When LLM is enabled, generates a fresh question on the fly, self-heals it into\n * the database, and returns it. Otherwise falls back to the stored question.\n */\nexport async function ensureHighQualityQuestion(\n db: Database,\n token: {\n id: string;\n slug: string;\n concept: string;\n domain: string;\n bloomLevel: number;\n sourceLink?: string | null;\n question?: string | null;\n },\n): Promise<string | null> {\n const { enabled } = await getLlmConfig(db);\n\n if (enabled) {\n try {\n let sourceLinkContent: string | null = null;\n if (token.sourceLink) {\n const resolved = await resolveReviewContext(token.sourceLink).catch(\n () => null,\n );\n if (resolved) {\n sourceLinkContent = resolved.content;\n }\n }\n\n const generated = await generateQuestionViaLLM(db, {\n slug: token.slug,\n concept: token.concept,\n domain: token.domain,\n bloomLevel: token.bloomLevel,\n sourceLinkContent,\n });\n\n if (generated && generated.trim().length > 0) {\n // Persist the latest high-quality question as the offline fallback.\n await updateToken(db, token.slug, { question: generated });\n return generated;\n }\n } catch {\n // Fail silently and fall back to the stored database question.\n }\n }\n\n if (token.question && token.question.trim().length > 0) {\n return token.question;\n }\n\n return null;\n}\n","/**\n * Resolve the active user ID from --user flag or stored whoami setting.\n */\n\nimport type { Database } from \"../../kernel/index.js\";\nimport { getSetting, setSetting } from \"../../kernel/index.js\";\n\nexport interface ResolveUserOptions {\n /** If true, output JSON error instead of console.error (for bridge commands). */\n json?: boolean;\n}\n\n/**\n * Ensure the desktop has a usable local identity on first launch.\n * Existing explicit configuration always wins.\n */\nexport async function ensureDefaultUser(\n db: Database,\n preferredUserId?: string,\n): Promise<string> {\n const stored = await getSetting(db, \"user.id\");\n if (stored) return stored;\n\n const userId =\n preferredUserId?.trim() ||\n process.env.ZAM_USER?.trim() ||\n process.env.USERNAME?.trim() ||\n process.env.USER?.trim() ||\n \"default\";\n await setSetting(db, \"user.id\", userId);\n return userId;\n}\n\n/**\n * Returns the user ID from the explicit --user flag, or falls back to the\n * stored `user.id` setting. Exits with an error if neither is available.\n */\nexport async function resolveUser(\n opts: { user?: string },\n db: Database,\n resolveOpts?: ResolveUserOptions,\n): Promise<string> {\n if (opts.user) return opts.user;\n\n const stored = await getSetting(db, \"user.id\");\n if (stored) return stored;\n\n const message =\n \"No user specified. Set a default with: zam whoami --set <id>\";\n if (resolveOpts?.json) {\n console.log(JSON.stringify({ error: message }, null, 2));\n } else {\n console.error(message);\n }\n process.exit(1);\n}\n","/**\n * Shared database helpers for CLI commands.\n *\n * Every command needs the same openDatabase → execute → close → handle errors\n * pattern. These wrappers keep command files focused on their domain logic.\n */\n\nimport type { Database } from \"../../../kernel/index.js\";\nimport { openDatabase } from \"../../../kernel/index.js\";\n\ntype ErrorHandler = (message: string) => void;\n\nfunction defaultErrorHandler(message: string): void {\n console.error(\"Error:\", message);\n process.exit(1);\n}\n\n/** Opens the DB, awaits fn, closes the DB, handles errors. */\nexport async function withDb(\n fn: (db: Database) => void | Promise<void>,\n onError: ErrorHandler = defaultErrorHandler,\n): Promise<void> {\n let db: Database | undefined;\n try {\n db = await openDatabase();\n await fn(db);\n } catch (err) {\n onError((err as Error).message);\n } finally {\n await db?.close();\n }\n}\n\n/**\n * JSON output helper — used by commands that support --json.\n */\nexport function jsonOut(data: unknown): void {\n console.log(JSON.stringify(data, null, 2));\n}\n","/**\n * `zam card` — Card scheduling subcommand group.\n */\n\nimport { Command } from \"commander\";\nimport type { Rating } from \"../../kernel/index.js\";\nimport {\n cascadeBlock,\n deleteCardForUser,\n ensureCard,\n evaluateRating,\n getCardDeletionImpact,\n getDueCards,\n getPrerequisites,\n getTokenBySlug,\n unblockReady,\n} from \"../../kernel/index.js\";\nimport { resolveUser } from \"./resolve-user.js\";\nimport { withDb } from \"./shared/db.js\";\n\nexport const cardCommand = new Command(\"card\").description(\n \"Manage spaced-repetition cards\",\n);\n\n// ── zam card due ──────────────────────────────────────────────────────────\n\ncardCommand\n .command(\"due\")\n .description(\"Show due tokens for a user\")\n .option(\"--user <id>\", \"User ID (default: whoami)\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--summary\", \"Show only counts per domain (no slugs or concepts)\")\n .action(async (opts) => {\n await withDb(async (db) => {\n const userId = await resolveUser(opts, db);\n const dueCards = await getDueCards(db, userId);\n\n if (opts.json) {\n console.log(JSON.stringify(dueCards, null, 2));\n return;\n }\n\n if (dueCards.length === 0) {\n console.log(\"No cards due for review.\");\n return;\n }\n\n if (opts.summary) {\n const byDomain = new Map<string, { count: number; blooms: number[] }>();\n for (const c of dueCards) {\n const d = c.domain || \"general\";\n const entry = byDomain.get(d) ?? { count: 0, blooms: [] };\n entry.count++;\n entry.blooms.push(c.bloom_level);\n byDomain.set(d, entry);\n }\n console.log(`${dueCards.length} card(s) due:\\n`);\n console.log(\"Domain Count Bloom levels\");\n console.log(\"─\".repeat(45));\n for (const [domain, { count, blooms }] of [\n ...byDomain.entries(),\n ].sort()) {\n const bloomStr = blooms.sort().join(\", \");\n console.log(\n `${domain.padEnd(16)} ${String(count).padEnd(6)} ${bloomStr}`,\n );\n }\n return;\n }\n\n console.log(`${dueCards.length} card(s) due:\\n`);\n console.log(\n \"Slug Concept Domain Bloom State\",\n );\n console.log(\"─\".repeat(90));\n for (const c of dueCards) {\n console.log(\n `${c.slug.padEnd(21)} ${c.concept.slice(0, 31).padEnd(31)} ${(c.domain || \"-\").padEnd(11)} ${String(c.bloom_level).padEnd(6)} ${c.state}`,\n );\n }\n });\n });\n\n// ── zam card update ───────────────────────────────────────────────────────\n\ncardCommand\n .command(\"update\")\n .description(\"Apply a rating to a card\")\n .option(\"--user <id>\", \"User ID (default: whoami)\")\n .requiredOption(\"--token <slug>\", \"Token slug\")\n .requiredOption(\"--rating <n>\", \"Rating (1=Again, 2=Hard, 3=Good, 4=Easy)\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--quiet\", \"Suppress output (exit code only)\")\n .action(async (opts) => {\n await withDb(async (db) => {\n const userId = await resolveUser(opts, db);\n const token = await getTokenBySlug(db, opts.token);\n if (!token) {\n console.error(`Token not found: ${opts.token}`);\n process.exit(1);\n }\n\n const card = await ensureCard(db, token.id, userId);\n const rating = Number(opts.rating) as Rating;\n\n if (rating < 1 || rating > 4) {\n console.error(\"Rating must be between 1 and 4.\");\n process.exit(1);\n }\n\n const result = await evaluateRating(db, {\n cardId: card.id,\n tokenId: token.id,\n userId,\n rating,\n });\n\n // If rating is 1 (forgot) and token has prerequisites, cascade block\n if (rating === 1) {\n const prereqs = await getPrerequisites(db, token.id);\n if (prereqs.length > 0) {\n const blockResult = await cascadeBlock(db, userId, token.slug);\n if (opts.quiet) return;\n if (opts.json) {\n console.log(\n JSON.stringify(\n { evaluation: result, blocked: blockResult },\n null,\n 2,\n ),\n );\n } else {\n console.log(\n `Rated ${token.slug} as Again (1) — next due: ${result.nextDueAt}`,\n );\n console.log(\n `Blocked ${blockResult.blockedSlug}. Prerequisites surfaced:`,\n );\n for (const p of blockResult.prerequisites) {\n console.log(` - ${p.slug}: ${p.concept}`);\n }\n }\n return;\n }\n }\n\n if (opts.quiet) return;\n if (opts.json) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n const ratingLabels: Record<number, string> = {\n 1: \"Again\",\n 2: \"Hard\",\n 3: \"Good\",\n 4: \"Easy\",\n };\n console.log(\n `Rated ${token.slug} as ${ratingLabels[rating]} (${rating})`,\n );\n console.log(` Next due: ${result.nextDueAt}`);\n console.log(` Stability: ${result.stability.toFixed(2)}`);\n console.log(` State: ${result.state}`);\n console.log(` Reps: ${result.reps}`);\n }\n });\n });\n\n// ── zam card block ────────────────────────────────────────────────────────\n\ncardCommand\n .command(\"block\")\n .description(\"Block a card and surface its prerequisites\")\n .option(\"--user <id>\", \"User ID (default: whoami)\")\n .requiredOption(\"--token <slug>\", \"Token slug\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--quiet\", \"Suppress output (exit code only)\")\n .action(async (opts) => {\n await withDb(async (db) => {\n const userId = await resolveUser(opts, db);\n const token = await getTokenBySlug(db, opts.token);\n if (!token) {\n console.error(`Token not found: ${opts.token}`);\n process.exit(1);\n }\n\n const prereqs = await getPrerequisites(db, token.id);\n if (prereqs.length === 0) {\n console.error(\n `Cannot block ${opts.token}: token has no prerequisites.`,\n );\n process.exit(1);\n }\n\n const result = await cascadeBlock(db, userId, token.slug);\n\n if (opts.quiet) return;\n if (opts.json) {\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n\n console.log(`Blocked ${result.blockedSlug}. Prerequisites surfaced:`);\n for (const prerequisite of result.prerequisites) {\n console.log(` - ${prerequisite.slug}: ${prerequisite.concept}`);\n }\n });\n });\n\n// ── zam card unblock ──────────────────────────────────────────────────────\n\ncardCommand\n .command(\"unblock\")\n .description(\"Unblock cards whose prerequisites are met\")\n .option(\"--user <id>\", \"User ID (default: whoami)\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--quiet\", \"Suppress output (exit code only)\")\n .action(async (opts) => {\n await withDb(async (db) => {\n const userId = await resolveUser(opts, db);\n const result = await unblockReady(db, userId);\n\n if (opts.quiet) return;\n if (opts.json) {\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n\n if (result.unblocked.length === 0) {\n console.log(\"No cards ready to unblock.\");\n } else {\n console.log(`Unblocked ${result.unblocked.length} card(s):`);\n for (const u of result.unblocked) {\n console.log(` - ${u.slug}: ${u.concept}`);\n }\n }\n });\n });\n\n// ── zam card delete ───────────────────────────────────────────────────────\n\ncardCommand\n .command(\"delete\")\n .description(\"Delete one user's card for a token\")\n .option(\"--user <id>\", \"User ID (default: whoami)\")\n .requiredOption(\"--token <slug>\", \"Token slug\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (opts) => {\n await withDb(async (db) => {\n const userId = await resolveUser(opts, db);\n const token = await getTokenBySlug(db, opts.token);\n if (!token) {\n console.error(`Token not found: ${opts.token}`);\n process.exit(1);\n }\n\n const impact = await getCardDeletionImpact(db, token.id, userId);\n const result = await deleteCardForUser(db, token.id, userId);\n\n if (opts.json) {\n console.log(\n JSON.stringify(\n {\n token: opts.token,\n userId,\n deleted: true,\n cardId: result.card.id,\n impact: result.impact,\n },\n null,\n 2,\n ),\n );\n return;\n }\n\n console.log(`Deleted card for ${opts.token}`);\n console.log(` User: ${userId}`);\n console.log(` Card ID: ${result.card.id}`);\n console.log(` Review logs removed: ${impact.review_logs}`);\n });\n });\n","/**\n * `zam connector` — Manage external service connectors.\n */\n\nimport { input, password } from \"@inquirer/prompts\";\nimport { Command } from \"commander\";\nimport { fetchActiveWorkItems } from \"../../kernel/connectors/azure-devops.js\";\nimport {\n clearADOCredentials,\n clearTursoCredentials,\n getADOCredentials,\n getTursoCredentials,\n setADOCredentials,\n setTursoCredentials,\n} from \"../../kernel/credentials.js\";\nimport type { Database } from \"../../kernel/index.js\";\nimport { openDatabaseWithSync } from \"../../kernel/index.js\";\n\nexport const connectorCommand = new Command(\"connector\").description(\n \"Manage external service connectors\",\n);\n\n// ── zam connector setup ado ─────────────────────────────────────────────────\n\nconnectorCommand\n .command(\"setup\")\n .description(\"Configure a connector\")\n .argument(\"<type>\", \"Connector type (ado, turso)\")\n .option(\"--url <url>\", \"Turso database URL (non-interactive)\")\n .option(\"--token <token>\", \"Turso auth token (non-interactive)\")\n .option(\n \"--mode <mode>\",\n \"Turso access mode: native (libsql driver) | remote (HTTP, works on Windows ARM64)\",\n )\n .action(async (type, opts) => {\n if (type === \"turso\") {\n if (opts.mode && opts.mode !== \"native\" && opts.mode !== \"remote\") {\n console.error(`Invalid --mode: ${opts.mode}. Use native or remote.`);\n process.exit(1);\n }\n return setupTurso(opts.url, opts.token, opts.mode);\n }\n if (type !== \"ado\") {\n console.error(`Unknown connector type: ${type}. Supported: ado, turso`);\n process.exit(1);\n }\n\n try {\n const orgUrl = await input({\n message: \"Organization URL (e.g. https://dev.azure.com/myorg):\",\n });\n const project = await input({\n message: \"Project name:\",\n });\n const pat = await password({\n message: \"Personal Access Token:\",\n });\n\n if (!orgUrl || !project || !pat) {\n console.error(\"All fields are required.\");\n process.exit(1);\n }\n\n setADOCredentials(orgUrl.replace(/\\/+$/, \"\"), project, pat);\n console.log(`Azure DevOps connector configured for ${orgUrl}/${project}`);\n } catch (err) {\n if ((err as Error).name === \"ExitPromptError\") {\n console.log(\"\\nSetup cancelled.\");\n process.exit(0);\n }\n console.error(\"Error:\", (err as Error).message);\n process.exit(1);\n }\n });\n\n// ── zam connector tasks ─────────────────────────────────────────────────────\n\nconnectorCommand\n .command(\"tasks\")\n .description(\"List active tasks from connected board\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (opts) => {\n try {\n const config = getADOCredentials();\n\n if (!config) {\n console.error(\"No connector configured. Run: zam connector setup ado\");\n process.exit(1);\n }\n\n const items = await fetchActiveWorkItems({\n orgUrl: config.org_url,\n project: config.project,\n pat: config.pat,\n });\n\n if (opts.json) {\n console.log(JSON.stringify(items, null, 2));\n return;\n }\n\n if (items.length === 0) {\n console.log(\"No active work items assigned to you.\");\n return;\n }\n\n console.log(`${items.length} active work item(s):\\n`);\n console.log(\"ID Type State Title\");\n console.log(\"─\".repeat(80));\n for (const wi of items) {\n console.log(\n `${String(wi.id).padEnd(8)} ${wi.type.padEnd(13)} ${wi.state.padEnd(11)} ${wi.title.slice(0, 45)}`,\n );\n }\n } catch (err) {\n console.error(\"Error:\", (err as Error).message);\n process.exit(1);\n }\n });\n\n// ── zam connector clear ─────────────────────────────────────────────────────\n\nconnectorCommand\n .command(\"clear\")\n .description(\"Remove a connector configuration\")\n .argument(\"<type>\", \"Connector type (ado, turso)\")\n .action((type) => {\n if (type === \"turso\") {\n clearTursoCredentials();\n console.log(\"Turso cloud sync removed. Database remains local-only.\");\n return;\n }\n\n if (type !== \"ado\") {\n console.error(`Unknown connector type: ${type}. Supported: ado, turso`);\n process.exit(1);\n }\n\n clearADOCredentials();\n console.log(\"Azure DevOps connector removed.\");\n });\n\n// ── zam connector sync ──────────────────────────────────────────────────────\n\nconnectorCommand\n .command(\"sync\")\n .description(\"Verify the Turso cloud database connection\")\n .action(async () => {\n const turso = getTursoCredentials();\n if (!turso) {\n console.error(\n \"No Turso cloud database configured. Run: zam connector setup turso\",\n );\n process.exit(1);\n }\n\n let db: Database | undefined;\n try {\n db = await openDatabaseWithSync({ initialize: true });\n await db.prepare(\"SELECT 1\").get();\n console.log(`Connected to ${turso.url}`);\n await db.close();\n } catch (err) {\n await db?.close();\n console.error(\"Error:\", (err as Error).message);\n process.exit(1);\n }\n });\n\n// ── Turso setup helper ──────────────────────────────────────────────────────\n\nasync function setupTurso(\n urlArg?: string,\n tokenArg?: string,\n mode?: \"native\" | \"remote\",\n): Promise<void> {\n let db: Database | undefined;\n try {\n const url =\n urlArg ??\n (await input({\n message: \"Turso database URL (e.g. libsql://my-db-user.turso.io):\",\n }));\n const token =\n tokenArg ??\n (await password({\n message: \"Auth token:\",\n }));\n\n if (!url || !token) {\n console.error(\"Both URL and token are required.\");\n process.exit(1);\n }\n\n // Store credentials outside the db so they survive db deletion\n setTursoCredentials(url, token, undefined, mode);\n\n // Verify by opening the configured cloud database.\n db = await openDatabaseWithSync({ initialize: true });\n await db.prepare(\"SELECT 1\").get();\n await db.close();\n\n console.log(\n `Turso cloud database configured and verified: ${url}` +\n (mode ? ` (mode: ${mode})` : \"\"),\n );\n } catch (err) {\n await db?.close();\n if ((err as Error).name === \"ExitPromptError\") {\n console.log(\"\\nSetup cancelled.\");\n process.exit(0);\n }\n console.error(\"Error:\", (err as Error).message);\n process.exit(1);\n }\n}\n","/**\n * `zam git-sync` — Git integration subcommand.\n *\n * Automatically marks cards as stale/due when their source files change in git.\n */\n\nimport { execSync } from \"node:child_process\";\nimport { chmodSync, existsSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { Command } from \"commander\";\nimport type { Token } from \"../../kernel/index.js\";\nimport { getCard, matchesFilePath } from \"../../kernel/index.js\";\nimport { resolveUser } from \"./resolve-user.js\";\nimport { withDb } from \"./shared/db.js\";\n\n/**\n * Installs the Git post-commit hook.\n */\nfunction installHook(): void {\n const gitDir = join(process.cwd(), \".git\");\n if (!existsSync(gitDir)) {\n console.error(\n \"Error: Current directory is not the root of a Git repository.\",\n );\n process.exit(1);\n }\n\n const hooksDir = join(gitDir, \"hooks\");\n const hookPath = join(hooksDir, \"post-commit\");\n\n const hookContent = `#!/bin/sh\n# ZAM Spaced Repetition Auto-Stale Hook\n# Triggered automatically on git commits to decay modified concept cards.\nzam git-sync --commit HEAD --quiet\n`;\n\n try {\n writeFileSync(hookPath, hookContent, { encoding: \"utf-8\", flag: \"w\" });\n try {\n chmodSync(hookPath, \"755\");\n } catch (_e) {\n // Best-effort chmod (Windows might ignore/fail, which is fine)\n }\n console.log(\n \"Successfully installed ZAM post-commit hook at .git/hooks/post-commit\",\n );\n } catch (err) {\n console.error(\"Failed to write post-commit hook:\", (err as Error).message);\n process.exit(1);\n }\n}\n\nexport const gitSyncCommand = new Command(\"git-sync\")\n .description(\"Sync learning cards with recent Git file modifications\")\n .option(\"--commit <hash>\", \"Git commit hash to check\", \"HEAD\")\n .option(\"--user <id>\", \"User ID (default: whoami)\")\n .option(\"--install\", \"Install git post-commit hook in current repo\")\n .option(\"--quiet\", \"Suppress verbose output\")\n .action(async (opts) => {\n if (opts.install) {\n installHook();\n return;\n }\n\n await withDb(async (db) => {\n const userId = await resolveUser(opts, db);\n\n let changedFiles: string[] = [];\n try {\n const output = execSync(\n `git diff-tree --no-commit-id --name-only -r ${opts.commit}`,\n {\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n },\n );\n changedFiles = output\n .split(/\\r?\\n/)\n .map((f) => f.trim())\n .filter(Boolean);\n } catch (_err) {\n if (!opts.quiet) {\n console.warn(\n \"Notice: Failed to read git modifications. Ensure you are in a Git repo and commit hash is valid.\",\n );\n }\n return;\n }\n\n if (changedFiles.length === 0) {\n if (!opts.quiet) {\n console.log(\"No file changes detected in commit.\");\n }\n return;\n }\n\n // Fetch active tokens\n const tokens = (await db\n .prepare(`\n SELECT * FROM tokens\n WHERE source_link IS NOT NULL\n AND deprecated_at IS NULL\n `)\n .all()) as Token[];\n\n const matchedTokens: Token[] = [];\n\n for (const token of tokens) {\n const matches = changedFiles.some((cf) =>\n matchesFilePath(token.source_link, cf),\n );\n if (matches) {\n matchedTokens.push(token);\n }\n }\n\n if (matchedTokens.length === 0) {\n if (!opts.quiet) {\n console.log(\n `Scanned ${changedFiles.length} file(s), no associated learning tokens found.`,\n );\n }\n return;\n }\n\n let decayedCount = 0;\n const now = new Date().toISOString();\n\n for (const token of matchedTokens) {\n const card = await getCard(db, token.id, userId);\n if (card) {\n // Decay stability to a quarter (concept's source changed → likely stale),\n // with a 0.2-day floor so the card surfaces for review soon. Using max,\n // not min: min would collapse every card to <=0.2 regardless of prior strength.\n const newStability = Math.max(0.2, card.stability / 4.0);\n\n await db\n .prepare(`\n UPDATE cards\n SET due_at = ?,\n stability = ?,\n state = CASE WHEN state = 'new' THEN 'new' ELSE 'review' END,\n elapsed_days = 0.0,\n scheduled_days = 0.0\n WHERE id = ?\n `)\n .run(now, newStability, card.id);\n\n decayedCount++;\n if (!opts.quiet) {\n console.log(\n ` Decayed card for: ${token.slug} (Source: ${token.source_link})`,\n );\n }\n }\n }\n\n if (!opts.quiet) {\n console.log(\n `\\nZAM Auto-Stale Complete: Scanned ${changedFiles.length} file(s).`,\n );\n console.log(\n `Successfully decayed FSRS stability and scheduled reviews for ${decayedCount} concept(s).`,\n );\n }\n });\n });\n","/**\n * `zam goal` — Goal management subcommand group.\n *\n * Goals are markdown files in the personal repo's goals/ directory.\n * The directory is configured via the `personal.goals_dir` setting,\n * or defaults to `./goals` relative to the current working directory.\n */\n\nimport { existsSync, mkdirSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { input } from \"@inquirer/prompts\";\nimport { Command } from \"commander\";\nimport type { GoalStatus } from \"../../kernel/index.js\";\nimport {\n createGoal,\n extractTasks,\n extractTokenRefs,\n getGoal,\n getGoalTree,\n getSetting,\n listGoals,\n openDatabase,\n updateGoalStatus,\n} from \"../../kernel/index.js\";\n\nasync function resolveGoalsDir(): Promise<string> {\n let goalsDir: string | undefined;\n\n let db: Awaited<ReturnType<typeof openDatabase>> | undefined;\n try {\n db = await openDatabase();\n goalsDir = await getSetting(db, \"personal.goals_dir\");\n } catch {\n // DB not available — fall back to default\n } finally {\n await db?.close();\n }\n\n return goalsDir ? resolve(goalsDir) : resolve(\"goals\");\n}\n\nexport const goalCommand = new Command(\"goal\").description(\n \"Manage learning goals (markdown files)\",\n);\n\n// ── zam goal list ────────────────────────────────────────────────────────────\n\ngoalCommand\n .command(\"list\")\n .description(\"List all goals\")\n .option(\n \"--status <status>\",\n \"Filter by status (active, completed, paused, abandoned)\",\n )\n .option(\"--tree\", \"Show goals as a tree with parent/child relationships\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (opts) => {\n const goalsDir = await resolveGoalsDir();\n\n if (!existsSync(goalsDir)) {\n console.error(`Goals directory not found: ${goalsDir}`);\n console.error(\n \"Set it with: zam settings set personal.goals_dir /path/to/goals\",\n );\n process.exit(1);\n }\n\n if (opts.tree) {\n const tree = getGoalTree(goalsDir);\n const filtered = opts.status\n ? tree.filter((g) => g.status === opts.status)\n : tree;\n\n if (opts.json) {\n console.log(JSON.stringify(filtered, null, 2));\n return;\n }\n\n if (filtered.length === 0) {\n console.log(\"No goals found.\");\n return;\n }\n\n for (const root of filtered) {\n printGoalLine(root, 0);\n for (const child of root.children) {\n printGoalLine(child, 1);\n }\n }\n return;\n }\n\n let goals = listGoals(goalsDir);\n\n if (opts.status) {\n goals = goals.filter((g) => g.status === opts.status);\n }\n\n if (opts.json) {\n console.log(JSON.stringify(goals, null, 2));\n return;\n }\n\n if (goals.length === 0) {\n console.log(\"No goals found.\");\n return;\n }\n\n console.log(\"Goals:\");\n console.log(` ${\"─\".repeat(70)}`);\n for (const g of goals) {\n printGoalLine(g, 0);\n }\n });\n\nfunction printGoalLine(\n g: {\n slug: string;\n title: string;\n status: string;\n taskCount: number;\n tasksDone: number;\n },\n indent: number,\n): void {\n const prefix = \" \".repeat(indent + 1);\n const statusIcon: Record<string, string> = {\n active: \"[*]\",\n paused: \"[-]\",\n completed: \"[x]\",\n abandoned: \"[ ]\",\n };\n const icon = statusIcon[g.status] || \"[ ]\";\n const tasks = g.taskCount > 0 ? ` (${g.tasksDone}/${g.taskCount} tasks)` : \"\";\n console.log(`${prefix}${icon} ${g.title}${tasks} — ${g.slug}`);\n}\n\n// ── zam goal show ────────────────────────────────────────────────────────────\n\ngoalCommand\n .command(\"show <slug>\")\n .description(\"Show a goal's details\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (slug, opts) => {\n const goalsDir = await resolveGoalsDir();\n const goal = getGoal(goalsDir, slug);\n\n if (!goal) {\n console.error(`Goal not found: ${slug}`);\n process.exit(1);\n }\n\n if (opts.json) {\n const tasks = extractTasks(goal.body);\n const tokens = extractTokenRefs(goal.body);\n console.log(JSON.stringify({ ...goal, tasks, tokens }, null, 2));\n return;\n }\n\n console.log(`Title: ${goal.title}`);\n console.log(`Slug: ${goal.slug}`);\n console.log(`Status: ${goal.status}`);\n if (goal.parent) console.log(`Parent: ${goal.parent}`);\n console.log(`Created: ${goal.created}`);\n console.log(`Updated: ${goal.updated}`);\n\n const tasks = extractTasks(goal.body);\n if (tasks.length > 0) {\n console.log(\n `\\nTasks (${tasks.filter((t) => t.done).length}/${tasks.length}):`,\n );\n for (const t of tasks) {\n console.log(` [${t.done ? \"x\" : \" \"}] ${t.text}`);\n }\n }\n\n const tokens = extractTokenRefs(goal.body);\n if (tokens.length > 0) {\n console.log(`\\nTokens:`);\n for (const ref of tokens) {\n console.log(` - ${ref}`);\n }\n }\n\n if (goal.body) {\n console.log(`\\n${\"─\".repeat(50)}`);\n console.log(goal.body);\n }\n });\n\n// ── zam goal create ──────────────────────────────────────────────────────────\n\ngoalCommand\n .command(\"create\")\n .description(\"Create a new goal\")\n .option(\"--slug <slug>\", \"Goal slug (used as filename)\")\n .option(\"--title <title>\", \"Goal title\")\n .option(\"--parent <slug>\", \"Parent goal slug\")\n .option(\"--description <text>\", \"Goal description\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (opts) => {\n const goalsDir = await resolveGoalsDir();\n\n if (!existsSync(goalsDir)) {\n mkdirSync(goalsDir, { recursive: true });\n }\n\n let slug = opts.slug;\n let title = opts.title;\n const parent = opts.parent;\n const description = opts.description;\n\n // Interactive mode if slug or title not provided\n if (!slug || !title) {\n try {\n if (!title) {\n title = await input({ message: \"Goal title:\" });\n }\n if (!slug) {\n const suggested = title\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n slug = await input({\n message: \"Goal slug (filename):\",\n default: suggested,\n });\n }\n } catch (err) {\n if ((err as Error).name === \"ExitPromptError\") {\n console.log(\"\\nCancelled.\");\n process.exit(0);\n }\n throw err;\n }\n }\n\n const goal = createGoal(goalsDir, { slug, title, parent, description });\n\n if (opts.json) {\n console.log(JSON.stringify(goal, null, 2));\n return;\n }\n\n console.log(`Goal created: ${goal.slug}`);\n console.log(` Title: ${goal.title}`);\n console.log(` Status: ${goal.status}`);\n console.log(` File: ${goal.filePath}`);\n });\n\n// ── zam goal status ──────────────────────────────────────────────────────────\n\ngoalCommand\n .command(\"status <slug> <status>\")\n .description(\"Update a goal's status (active, paused, completed, abandoned)\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (slug, status, opts) => {\n const validStatuses: GoalStatus[] = [\n \"active\",\n \"completed\",\n \"paused\",\n \"abandoned\",\n ];\n if (!validStatuses.includes(status)) {\n console.error(\n `Invalid status: ${status}. Must be one of: ${validStatuses.join(\", \")}`,\n );\n process.exit(1);\n }\n\n const goalsDir = await resolveGoalsDir();\n const goal = updateGoalStatus(goalsDir, slug, status);\n\n if (opts.json) {\n console.log(JSON.stringify(goal, null, 2));\n return;\n }\n\n console.log(`Goal ${slug} updated to: ${status}`);\n });\n","/**\n * `zam init` — Guided interactive onboarding wizard.\n *\n * Bootstraps a fresh ZAM installation:\n * 1. Initializes a zero-dependency \"Local Sandbox\" workspace.\n * 2. Runs hardware profiling to detect NPUs/CPUs.\n * 3. Installs and configures the hardware-optimized local LLM runtime (flm or Ollama).\n * 4. Automatically distributes global agent skill files and hooks.\n * 5. Sets up the local database and configuration.\n */\n\nimport { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { confirm, input } from \"@inquirer/prompts\";\nimport { Command } from \"commander\";\nimport {\n detectSystemLocale,\n distributeGlobalSkills,\n getSystemProfile,\n injectShellHooks,\n installFastFlowLM,\n installOllama,\n openDatabaseWithSync,\n prepareLocalModel,\n setSetting,\n} from \"../../kernel/index.js\";\n\nconst HOME = homedir();\n\n/**\n * Helper to print thick borders.\n */\nfunction printLine(char = \"═\", len = 60, color = \"\\x1b[36m\") {\n console.log(`${color}${char.repeat(len)}\\x1b[0m`);\n}\n\n/**\n * Bootstrap the default \"Local Sandbox\" workspace structure.\n */\nfunction bootstrapSandboxWorkspace(workspaceDir: string) {\n mkdirSync(join(workspaceDir, \"beliefs\"), { recursive: true });\n mkdirSync(join(workspaceDir, \"goals\"), { recursive: true });\n mkdirSync(join(workspaceDir, \"skills\"), { recursive: true });\n\n const worldviewFile = join(workspaceDir, \"beliefs\", \"worldview.md\");\n if (!existsSync(worldviewFile)) {\n writeFileSync(\n worldviewFile,\n `# Personal Worldview\n\nHere, I declare the core concepts and principles I want to master.\n\n- **Conceptual Autonomy**: I value deep conceptual understanding over copy-pasting rote procedures.\n- **Continuous Retention**: I use spaced repetition to prevent my professional skills from decaying.\n`,\n \"utf8\",\n );\n }\n\n const goalsFile = join(workspaceDir, \"goals\", \"goals.md\");\n if (!existsSync(goalsFile)) {\n writeFileSync(\n goalsFile,\n `# Personal Goals\n\n- **[ ] Learn Spaced Repetition Core Concepts**\n - #fsrs-stability\n - #fsrs-difficulty\n`,\n \"utf8\",\n );\n }\n}\n\nexport const initCommand = new Command(\"init\")\n .description(\"Launch the guided interactive onboarding wizard\")\n .action(async () => {\n printLine();\n console.log(\n \"\\x1b[1m\\x1b[32m ZAM — The Symbiotic Learning Agent Onboarding\\x1b[0m\",\n );\n console.log(\n \"\\x1b[2m Welcome! ZAM helps you build conceptual skills while you work.\\x1b[0m\",\n );\n printLine();\n\n // ── STEP 1: Workspace Selection ──────────────────────────────────────────\n console.log(\"\\n\\x1b[1m[1/5] Setting up Local Workspace Sandbox\\x1b[0m\");\n const defaultWorkspace = join(HOME, \"Documents\", \"zam\");\n\n const workspacePath = await input({\n message: \"Choose your ZAM workspace directory:\",\n default: defaultWorkspace,\n });\n\n try {\n bootstrapSandboxWorkspace(workspacePath);\n console.log(\n `\\x1b[32m✓ Local Sandbox created at: ${workspacePath}\\x1b[0m`,\n );\n } catch (err) {\n console.error(\n `\\x1b[31m✗ Failed to create workspace: ${(err as Error).message}\\x1b[0m`,\n );\n process.exit(1);\n }\n\n // ── STEP 2: Hardware Auto-Detection ──────────────────────────────────────\n console.log(\"\\n\\x1b[1m[2/5] Running Hardware Profiling...\\x1b[0m\");\n const profile = getSystemProfile();\n\n console.log(` OS Detected: \\x1b[36m${profile.os}\\x1b[0m`);\n console.log(` CPU Architecture: \\x1b[36m${profile.arch}\\x1b[0m`);\n if (profile.hasRyzenNPU) {\n console.log(\n \" NPU Detected: \\x1b[32mAMD Ryzen AI NPU detected! (Optimum Setup)\\x1b[0m\",\n );\n } else if (profile.hasAppleSilicon) {\n console.log(\n \" CPU Brand: \\x1b[32mmacOS Apple Silicon detected! (Optimum Setup)\\x1b[0m\",\n );\n } else {\n console.log(\" Hardware: \\x1b[33mStandard CPU detected.\\x1b[0m\");\n }\n\n const runnerLabel =\n profile.recommendedRunner === \"fastflowlm\"\n ? \"FastFlowLM (NPU Optimized)\"\n : \"Ollama\";\n console.log(\n `\\n \\x1b[1mRecommendation:\\x1b[0m ZAM suggests installing \\x1b[32m${runnerLabel}\\x1b[0m with \\x1b[36m${profile.recommendedModel}\\x1b[0m.`,\n );\n\n // ── STEP 3: Local LLM Runner Installation ───────────────────────────────\n console.log(\"\\n\\x1b[1m[3/5] Setting up Local LLM Runner\\x1b[0m\");\n const proceedInstall = await confirm({\n message: `Would you like ZAM to install and configure ${runnerLabel} automatically?`,\n default: true,\n });\n\n let llmReady = false;\n if (proceedInstall) {\n let result: ReturnType<typeof installFastFlowLM> | undefined;\n if (profile.recommendedRunner === \"fastflowlm\") {\n result = installFastFlowLM();\n } else {\n result = installOllama();\n }\n\n if (result.success) {\n console.log(`\\x1b[32m✓ ${result.message}\\x1b[0m`);\n const modelResult = prepareLocalModel(\n profile.recommendedRunner,\n profile.recommendedModel,\n );\n if (modelResult.success) {\n console.log(`\\x1b[32m✓ ${modelResult.message}\\x1b[0m`);\n llmReady = true;\n } else {\n console.warn(\n `\\x1b[33m⚠ Model setup incomplete: ${modelResult.message}\\x1b[0m`,\n );\n }\n } else {\n console.warn(`\\x1b[33m⚠ Installation failed: ${result.message}\\x1b[0m`);\n console.log(\n \"You can install it manually or continue with offline templates.\",\n );\n }\n }\n\n // ── STEP 4: Initialize Database & Write Local Settings ─────────────────\n console.log(\"\\n\\x1b[1m[4/5] Bootstrapping database & settings...\\x1b[0m\");\n let db: Awaited<ReturnType<typeof openDatabaseWithSync>> | undefined;\n try {\n db = await openDatabaseWithSync({ initialize: true });\n\n // Save workspace directory to settings\n await setSetting(db, \"personal.workspace_dir\", workspacePath);\n\n // Auto-detect and save system locale\n const detectedLocale = detectSystemLocale();\n await setSetting(db, \"system.locale\", detectedLocale);\n console.log(\n `\\x1b[32m✓ Detected and set system language to: ${detectedLocale}\\x1b[0m`,\n );\n\n if (llmReady) {\n await setSetting(db, \"llm.enabled\", \"true\");\n if (profile.recommendedRunner === \"fastflowlm\") {\n await setSetting(db, \"llm.url\", \"http://localhost:8000/v1\");\n } else {\n await setSetting(db, \"llm.url\", \"http://localhost:11434/v1\");\n }\n await setSetting(db, \"llm.model\", profile.recommendedModel);\n console.log(\n \"\\x1b[32m✓ Configured LLM runner settings in database.\\x1b[0m\",\n );\n } else {\n await setSetting(db, \"llm.enabled\", \"false\");\n }\n await db.close();\n console.log(\"\\x1b[32m✓ Database initialized successfully.\\x1b[0m\");\n } catch (err) {\n console.error(\n `\\x1b[31m✗ Database setup failed: ${(err as Error).message}\\x1b[0m`,\n );\n await db?.close();\n }\n\n // ── STEP 5: Distribute Agent Skills & Helpers ────────────────────────────\n console.log(\n \"\\n\\x1b[1m[5/5] Wiring Developer Agents & Terminal Helpers\\x1b[0m\",\n );\n const proceedHooks = await confirm({\n message:\n \"Distribute ZAM skills and install optional monitored-session shell helpers?\",\n default: true,\n });\n\n if (proceedHooks) {\n console.log(\"Copying SKILL.md into global agent directories...\");\n const skillResults = distributeGlobalSkills();\n for (const res of skillResults) {\n if (res.success) {\n console.log(` \\x1b[32m✓ Installed ZAM Skill in ${res.name}\\x1b[0m`);\n } else {\n console.log(` \\x1b[31m✗ Failed to install in ${res.name}\\x1b[0m`);\n }\n }\n\n console.log(\"Installing monitored-session helpers in shell profiles...\");\n const hookResults = injectShellHooks();\n for (const res of hookResults) {\n if (res.success) {\n const action = res.alreadyHooked\n ? \"already up-to-date\"\n : \"installed successfully\";\n console.log(` \\x1b[32m✓ ${res.shell} helper: ${action}\\x1b[0m`);\n } else {\n console.log(\n ` \\x1b[31m✗ Failed to install helper in ${res.shell} (${res.file})\\x1b[0m`,\n );\n }\n }\n console.log(\n \" Start monitoring with zam-monitor-session <id> (bash/zsh) or Start-ZamMonitor <id> (PowerShell).\",\n );\n }\n\n printLine();\n console.log(\n \"\\x1b[1m\\x1b[32m Congratulations! ZAM Onboarding Complete!\\x1b[0m\",\n );\n console.log(\n \"\\x1b[1m You are now ready to start your symbiotic learning journey.\\x1b[0m\",\n );\n console.log(\"\\n \\x1b[1mUseful commands to get started:\\x1b[0m\");\n console.log(\n \" \\x1b[36mzam stats\\x1b[0m — Display your learning queue stats\",\n );\n console.log(\n \" \\x1b[36mzam learn\\x1b[0m — Start a standalone learning session\",\n );\n console.log(\n \" \\x1b[36mzam workspace publish\\x1b[0m — Publish your workspace sandbox to GitHub\",\n );\n printLine();\n });\n","/**\n * `zam learn` — Standalone, spoiler-free, in-process learning session.\n *\n * Slice 1 of the Session Harness (Increment 5), variant (a): no LLM.\n * Flow per card: show a concept-free cue → capture the learner's answer →\n * ONLY THEN reveal the stored answer (concept + context + resolved source_link)\n * → single self-rating 1–4 via the shared interactive action handler.\n *\n * Because the harness owns its own prompt and never prints the answer before\n * input is captured, no external autocomplete/ghost-text can spoil it, and\n * ratings/logs are written in-process (no per-subcommand permission prompts).\n */\n\nimport { input } from \"@inquirer/prompts\";\nimport { Command } from \"commander\";\nimport type {\n BloomLevel,\n Database,\n SupportedLocale,\n} from \"../../kernel/index.js\";\nimport {\n buildReviewQueue,\n generatePrompt,\n getSetting,\n getTokenById,\n openDatabase,\n resolveReviewContext,\n t,\n} from \"../../kernel/index.js\";\nimport { formatHeader, formatReveal } from \"../learn-format.js\";\nimport {\n ensureHighQualityQuestion,\n ensureLocalLlmRunning,\n evaluateAnswerViaLLM,\n} from \"../llm/client.js\";\nimport { runInteractiveReviewAction } from \"../review-actions.js\";\nimport { resolveUser } from \"./resolve-user.js\";\n\n/** Words the learner can type at the answer prompt to end the session. */\nconst STOP_WORDS = new Set([\"q\", \":q\", \"quit\", \"stop\"]);\n\nfunction isExitPrompt(err: unknown): boolean {\n return err instanceof Error && err.name === \"ExitPromptError\";\n}\n\nexport const learnCommand = new Command(\"learn\")\n .description(\n \"Run a spoiler-free, in-process learning session (recall → reveal → self-rate)\",\n )\n .option(\"--user <id>\", \"User ID (default: whoami)\")\n .option(\"--max-new <n>\", \"Maximum new cards\", \"10\")\n .option(\"--max-reviews <n>\", \"Maximum review cards\", \"50\")\n .option(\"--no-resolve\", \"Skip resolving source_link into the revealed answer\")\n .action(async (opts) => {\n let db: Database | undefined;\n try {\n db = await openDatabase();\n const userId = await resolveUser(opts, db);\n\n const queue = await buildReviewQueue(db, {\n userId,\n maxNew: Number(opts.maxNew),\n maxReviews: Number(opts.maxReviews),\n });\n\n const locale = ((await getSetting(db, \"system.locale\")) ||\n \"en\") as SupportedLocale;\n\n if (queue.items.length === 0) {\n console.log(t(locale, \"nothing_due\"));\n await db.close();\n return;\n }\n\n // Start the local LLM if needed and verify it is actually usable\n // (reachable AND serving the configured model). A wrong model name\n // otherwise looks like \"the AI is slow\" — instead we fall back cleanly.\n const llm = await ensureLocalLlmRunning(db);\n const isLlmEnabled = llm.usable;\n\n console.log(`\\n${t(locale, \"welcome\", { count: queue.items.length })}`);\n console.log(\n t(locale, \"new_review_relearn\", {\n newC: queue.newCount,\n reviewC: queue.reviewCount,\n relearnC: queue.relearnCount,\n }),\n );\n console.log(\n t(locale, \"domains\", { domains: queue.totalDomains.join(\", \") }),\n );\n\n // When the LLM is simply switched off, nudge the user; offline /\n // model-not-found already printed their own actionable message.\n if (!isLlmEnabled && llm.reason === \"disabled\") {\n console.log(t(locale, \"offline_warning\"));\n console.log(t(locale, \"offline_instruction\"));\n }\n\n console.log(t(locale, \"instruction\"));\n console.log(t(locale, \"quit_hint\"));\n\n let stoppedEarly = false;\n let maintenanceActions = 0;\n const results: Array<{ slug: string; rating: number }> = [];\n\n for (const [index, item] of queue.items.entries()) {\n // Dynamically generate a fresh, living active-recall question if LLM is enabled\n let resolvedQuestion = item.question;\n if (isLlmEnabled) {\n console.log(` \\x1b[2m${t(locale, \"generating_question\")}\\x1b[0m`);\n try {\n const healed = await ensureHighQualityQuestion(db, {\n id: item.tokenId,\n slug: item.slug,\n concept: item.concept,\n domain: item.domain,\n bloomLevel: item.bloomLevel as BloomLevel,\n sourceLink: item.sourceLink,\n question: item.question,\n });\n if (healed) {\n resolvedQuestion = healed;\n }\n } catch {\n // ignore and proceed\n }\n }\n\n const prompt = generatePrompt({\n cardId: item.cardId,\n tokenId: item.tokenId,\n slug: item.slug,\n concept: item.concept,\n domain: item.domain,\n bloomLevel: item.bloomLevel as BloomLevel,\n sourceLink: item.sourceLink,\n question: resolvedQuestion,\n });\n\n console.log(`\\n${\"─\".repeat(50)}`);\n console.log(\n `[${index + 1}/${queue.items.length}] ${formatHeader(item)}`,\n );\n\n console.log(`\\n ${prompt.question}`);\n\n // Capture the learner's answer FIRST — nothing is revealed yet.\n // Typing a stop word (or Ctrl+C) ends the session gracefully.\n let answer: string;\n try {\n answer = await input({\n message: t(locale, \"prompt_answer\"),\n });\n } catch (err) {\n if (isExitPrompt(err)) {\n stoppedEarly = true;\n console.log(\"\\nStopping session.\");\n break;\n }\n throw err;\n }\n\n if (STOP_WORDS.has(answer.trim().toLowerCase())) {\n stoppedEarly = true;\n console.log(\"Stopping session.\");\n break;\n }\n\n // Now reveal the stored answer.\n let resolved = null;\n if (opts.resolve !== false && item.sourceLink) {\n resolved = await resolveReviewContext(item.sourceLink).catch(\n () => null,\n );\n }\n const token = await getTokenById(db, item.tokenId);\n\n // Perform LLM evaluation if enabled and there is a typed answer\n if (isLlmEnabled && answer.trim().length > 0) {\n console.log(`\\n ${t(locale, \"evaluating\")}`);\n try {\n const evaluation = await evaluateAnswerViaLLM(db, {\n slug: item.slug,\n concept: item.concept,\n domain: item.domain,\n bloomLevel: item.bloomLevel,\n context: token?.context,\n question: prompt.question,\n userAnswer: answer,\n sourceLinkContent: resolved?.content,\n });\n console.log(\n `\\n ${t(locale, \"feedback_title\", { line: \"─\".repeat(34) })}`,\n );\n for (const line of evaluation.split(\"\\n\")) {\n console.log(` ${line}`);\n }\n } catch (err) {\n console.warn(\n `\\n${t(locale, \"eval_skipped\", { reason: (err as Error).message })}`,\n );\n }\n }\n\n console.log(\n `\\n ${t(locale, \"answer_title\", { line: \"─\".repeat(38) })}`,\n );\n const reveal = formatReveal({\n slug: item.slug,\n concept: item.concept,\n context: token?.context,\n resolved,\n });\n for (const line of reveal.split(\"\\n\")) {\n console.log(` ${line}`);\n }\n console.log();\n\n let action: Awaited<ReturnType<typeof runInteractiveReviewAction>>;\n try {\n action = await runInteractiveReviewAction({\n db,\n userId,\n item,\n mode: \"review\",\n });\n } catch (err) {\n if (isExitPrompt(err)) {\n stoppedEarly = true;\n console.log(\"\\nStopping session.\");\n break;\n }\n throw err;\n }\n\n if (action.action === \"stop\") {\n stoppedEarly = true;\n console.log(\"\\nStopping session.\");\n break;\n }\n if (action.action === \"rate\") {\n results.push({ slug: item.slug, rating: action.rating! });\n } else if (action.action !== \"skip\") {\n maintenanceActions++;\n }\n }\n\n console.log(`\\n${\"═\".repeat(50)}`);\n console.log(\n stoppedEarly\n ? t(locale, \"session_ended\")\n : t(locale, \"session_complete\"),\n );\n console.log(t(locale, \"cards_rated\", { count: results.length }));\n if (maintenanceActions > 0) {\n console.log(` Maintenance actions: ${maintenanceActions}`);\n }\n if (results.length > 0) {\n const avg = results.reduce((s, r) => s + r.rating, 0) / results.length;\n console.log(t(locale, \"avg_rating\", { avg: avg.toFixed(1) }));\n const forgot = results.filter((r) => r.rating === 1).length;\n if (forgot > 0) {\n console.log(t(locale, \"forgot\", { count: forgot }));\n }\n }\n\n await db.close();\n } catch (err) {\n await db?.close();\n if ((err as Error).name === \"ExitPromptError\") {\n console.log(\"\\nLearning session cancelled.\");\n process.exit(0);\n }\n console.error(\"Error:\", (err as Error).message);\n process.exit(1);\n }\n });\n","/**\n * Pure formatting helpers for the spoiler-free learning session (`zam learn`).\n *\n * Kept free of terminal/prompt code so the presentation logic is unit-testable.\n * The up-front question is the kernel's Bloom-templated prompt (built in\n * learn.ts via generatePrompt); these helpers render the header line and the\n * answer that is revealed only AFTER the learner has committed an answer.\n */\n\nimport type { ReviewContext } from \"../kernel/index.js\";\n\nexport const BLOOM_VERBS: Record<number, string> = {\n 1: \"Remember\",\n 2: \"Understand\",\n 3: \"Apply\",\n 4: \"Analyze\",\n 5: \"Synthesize\",\n};\n\nfunction clampBloom(n: number): number {\n return Number.isFinite(n) && n >= 1 && n <= 5 ? Math.trunc(n) : 1;\n}\n\n/**\n * Build the card header, e.g. \"Understand (Bloom 2) · web\".\n */\nexport function formatHeader(input: {\n bloomLevel: number;\n domain: string;\n}): string {\n const lvl = clampBloom(input.bloomLevel);\n const parts = [`${BLOOM_VERBS[lvl]} (Bloom ${lvl})`];\n if (input.domain?.trim()) {\n parts.push(input.domain.trim());\n }\n return parts.join(\" · \");\n}\n\nexport interface RevealInput {\n slug: string;\n concept: string;\n context?: string | null;\n resolved?: ReviewContext | null;\n}\n\n/**\n * Format the stored answer revealed AFTER the learner has committed: the\n * token slug, concept, optional context, and resolved source_link content.\n */\nexport function formatReveal(input: RevealInput): string {\n const lines: string[] = [\n `Token: #${input.slug}`,\n `Concept: ${input.concept}`,\n ];\n\n if (input.context?.trim()) {\n lines.push(\"\", `Context: ${input.context.trim()}`);\n }\n\n const resolved = input.resolved;\n if (resolved?.content.trim()) {\n lines.push(\"\");\n if (resolved.sourceType === \"dynamic_search\") {\n // content is a QUERY_DIRECTIVE — there is nothing to quote inline\n lines.push(`Source: ${resolved.content}`);\n } else {\n const label = resolved.url ?? resolved.filePath ?? resolved.sourceLink;\n lines.push(`Source (${resolved.sourceType}: ${label}):`);\n for (const line of resolved.content.trimEnd().split(\"\\n\")) {\n lines.push(` │ ${line}`);\n }\n if (resolved.truncated) {\n lines.push(\" │ … (truncated)\");\n }\n }\n }\n\n return lines.join(\"\\n\");\n}\n","import { confirm, input, select } from \"@inquirer/prompts\";\nimport type {\n BloomLevel,\n Database,\n Rating,\n ReviewActionResult,\n ReviewQueueItem,\n SymbiosisMode,\n Token,\n UpdateTokenInput,\n} from \"../kernel/index.js\";\nimport {\n executeReviewAction,\n generatePrompt,\n getCardDeletionImpact,\n getTokenById,\n getTokenDeleteImpact,\n} from \"../kernel/index.js\";\n\ntype InteractiveTerminalAction =\n | \"rate\"\n | \"skip\"\n | \"deprecate-token\"\n | \"delete-token\"\n | \"delete-card\"\n | \"stop\";\n\ntype InteractiveReviewChoice =\n | Rating\n | InteractiveTerminalAction\n | \"edit-token\";\n\ntype EditableTokenField =\n | \"concept\"\n | \"domain\"\n | \"bloom_level\"\n | \"context\"\n | \"symbiosis_mode\"\n | \"source_link\"\n | \"question\";\n\nexport interface RunInteractiveReviewActionInput {\n db: Database;\n userId: string;\n item: ReviewQueueItem;\n mode: \"review\" | \"session\";\n}\n\nexport interface RunInteractiveReviewActionResult {\n action: InteractiveTerminalAction;\n result: ReviewActionResult;\n rating?: Rating;\n}\n\nexport async function runInteractiveReviewAction(\n inputData: RunInteractiveReviewActionInput,\n): Promise<RunInteractiveReviewActionResult> {\n let currentItem = { ...inputData.item };\n\n while (true) {\n const choice = await select<InteractiveReviewChoice>({\n message: \"What next?\",\n choices: [\n { name: \"1 - Again (forgot)\", value: 1 },\n { name: \"2 - Hard\", value: 2 },\n { name: \"3 - Good\", value: 3 },\n { name: \"4 - Easy\", value: 4 },\n { name: \"Skip this card\", value: \"skip\" },\n { name: \"Edit token\", value: \"edit-token\" },\n { name: \"Deprecate token\", value: \"deprecate-token\" },\n { name: \"Delete token\", value: \"delete-token\" },\n { name: \"Delete my card\", value: \"delete-card\" },\n {\n name:\n inputData.mode === \"session\"\n ? \"Stop review and continue to task selection\"\n : \"Stop review\",\n value: \"stop\",\n },\n ],\n });\n\n if (typeof choice === \"number\") {\n const result = await executeReviewAction(inputData.db, {\n action: \"rate\",\n cardId: currentItem.cardId,\n userId: inputData.userId,\n rating: choice,\n });\n\n const ratingLabels: Record<number, string> = {\n 1: \"Again\",\n 2: \"Hard\",\n 3: \"Good\",\n 4: \"Easy\",\n };\n console.log(\n ` ${ratingLabels[choice]} — next due: ${result.evaluation?.nextDueAt}`,\n );\n\n if (result.blocked) {\n console.log(\n ` Blocked ${result.blocked.blockedSlug}. Review these prerequisites:`,\n );\n for (const prereq of result.blocked.prerequisites) {\n console.log(` - ${prereq.slug}: ${prereq.concept}`);\n }\n }\n\n console.log();\n return { action: \"rate\", result, rating: choice };\n }\n\n if (choice === \"skip\") {\n console.log(\"Skipped this card.\\n\");\n return {\n action: \"skip\",\n result: await executeReviewAction(inputData.db, {\n action: \"skip\",\n cardId: currentItem.cardId,\n userId: inputData.userId,\n }),\n };\n }\n\n if (choice === \"stop\") {\n return {\n action: \"stop\",\n result: await executeReviewAction(inputData.db, {\n action: \"stop\",\n cardId: currentItem.cardId,\n userId: inputData.userId,\n }),\n };\n }\n\n if (choice === \"edit-token\") {\n const token = await getTokenById(inputData.db, currentItem.tokenId);\n if (!token) {\n throw new Error(`Token not found: ${currentItem.tokenId}`);\n }\n\n const updates = await promptTokenEdit(token);\n if (!updates) {\n console.log(\"No token changes made.\\n\");\n continue;\n }\n\n const result = await executeReviewAction(inputData.db, {\n action: \"edit-token\",\n cardId: currentItem.cardId,\n userId: inputData.userId,\n tokenUpdates: updates,\n });\n\n const updatedToken = result.updatedToken!;\n currentItem = {\n ...currentItem,\n slug: updatedToken.slug,\n concept: updatedToken.concept,\n domain: updatedToken.domain,\n bloomLevel: updatedToken.bloom_level,\n };\n\n const refreshedPrompt = generatePrompt({\n cardId: currentItem.cardId,\n tokenId: currentItem.tokenId,\n slug: currentItem.slug,\n concept: currentItem.concept,\n domain: currentItem.domain,\n bloomLevel: currentItem.bloomLevel as BloomLevel,\n });\n\n console.log(`Updated token: ${updatedToken.slug}`);\n console.log(` Concept: ${updatedToken.concept}`);\n console.log(` Domain: ${updatedToken.domain || \"(none)\"}`);\n console.log(` Bloom: ${updatedToken.bloom_level}`);\n if (updatedToken.source_link) {\n console.log(` Source: ${updatedToken.source_link}`);\n }\n console.log(`\\n ${refreshedPrompt.question}\\n`);\n continue;\n }\n\n if (choice === \"deprecate-token\") {\n const approved = await confirm({\n message: `Deprecate ${currentItem.slug} so it stops appearing in review queues?`,\n default: false,\n });\n if (!approved) {\n console.log(\"Token deprecation cancelled.\\n\");\n continue;\n }\n\n const result = await executeReviewAction(inputData.db, {\n action: \"deprecate-token\",\n cardId: currentItem.cardId,\n userId: inputData.userId,\n });\n\n console.log(`Deprecated token: ${currentItem.slug}\\n`);\n return { action: \"deprecate-token\", result };\n }\n\n if (choice === \"delete-token\") {\n const impact = await getTokenDeleteImpact(inputData.db, currentItem.slug);\n console.log(`Delete token ${currentItem.slug}?`);\n console.log(` Cards: ${impact.cards}`);\n console.log(` Review logs: ${impact.review_logs}`);\n console.log(\n ` Prereq edges from it: ${impact.prerequisite_edges_from_token}`,\n );\n console.log(\n ` Prereq edges to it: ${impact.prerequisite_edges_to_token}`,\n );\n console.log(` Session steps: ${impact.session_steps}`);\n console.log(` Sessions touched: ${impact.sessions_touched}`);\n console.log(` Agent skills updated: ${impact.agent_skills}`);\n\n const approved = await confirm({\n message:\n \"Permanently delete this token and its dependent learning data?\",\n default: false,\n });\n if (!approved) {\n console.log(\"Token deletion cancelled.\\n\");\n continue;\n }\n\n const result = await executeReviewAction(inputData.db, {\n action: \"delete-token\",\n cardId: currentItem.cardId,\n userId: inputData.userId,\n });\n\n console.log(`Deleted token: ${currentItem.slug}\\n`);\n return { action: \"delete-token\", result };\n }\n\n if (choice === \"delete-card\") {\n const impact = await getCardDeletionImpact(\n inputData.db,\n currentItem.tokenId,\n inputData.userId,\n );\n console.log(`Delete your card for ${currentItem.slug}?`);\n console.log(` Review logs removed: ${impact.review_logs}`);\n\n const approved = await confirm({\n message: \"Delete only your card for this token?\",\n default: false,\n });\n if (!approved) {\n console.log(\"Card deletion cancelled.\\n\");\n continue;\n }\n\n const result = await executeReviewAction(inputData.db, {\n action: \"delete-card\",\n cardId: currentItem.cardId,\n userId: inputData.userId,\n });\n\n console.log(`Deleted your card for: ${currentItem.slug}\\n`);\n return { action: \"delete-card\", result };\n }\n }\n}\n\nasync function promptTokenEdit(token: Token): Promise<UpdateTokenInput | null> {\n const field = await select<EditableTokenField | \"cancel\">({\n message: `Edit which field on ${token.slug}?`,\n choices: [\n { name: \"Concept\", value: \"concept\" },\n { name: \"Domain\", value: \"domain\" },\n { name: \"Bloom level\", value: \"bloom_level\" },\n { name: \"Context\", value: \"context\" },\n { name: \"Symbiosis mode\", value: \"symbiosis_mode\" },\n { name: \"Source link\", value: \"source_link\" },\n { name: \"Question\", value: \"question\" },\n { name: \"Cancel\", value: \"cancel\" },\n ],\n });\n\n if (field === \"cancel\") {\n return null;\n }\n\n switch (field) {\n case \"concept\": {\n const concept = await input({\n message: \"Concept:\",\n default: token.concept,\n });\n return concept === token.concept ? null : { concept };\n }\n\n case \"domain\": {\n const domain = await input({\n message: \"Domain (blank allowed):\",\n default: token.domain,\n });\n return domain === token.domain ? null : { domain };\n }\n\n case \"context\": {\n const context = await input({\n message: \"Context (blank allowed):\",\n default: token.context,\n });\n return context === token.context ? null : { context };\n }\n\n case \"bloom_level\": {\n const bloom = (await select({\n message: \"Bloom level:\",\n choices: [1, 2, 3, 4, 5].map((value) => ({\n name:\n value === token.bloom_level ? `${value} (current)` : String(value),\n value,\n })),\n })) as BloomLevel;\n return bloom === token.bloom_level ? null : { bloom_level: bloom };\n }\n\n case \"symbiosis_mode\": {\n const mode = (await select({\n message: \"Symbiosis mode:\",\n choices: [\n {\n name: token.symbiosis_mode === null ? \"none (current)\" : \"none\",\n value: null,\n },\n {\n name:\n token.symbiosis_mode === \"shadowing\"\n ? \"shadowing (current)\"\n : \"shadowing\",\n value: \"shadowing\",\n },\n {\n name:\n token.symbiosis_mode === \"copilot\"\n ? \"copilot (current)\"\n : \"copilot\",\n value: \"copilot\",\n },\n {\n name:\n token.symbiosis_mode === \"autonomy\"\n ? \"autonomy (current)\"\n : \"autonomy\",\n value: \"autonomy\",\n },\n ],\n })) as SymbiosisMode | null;\n return mode === token.symbiosis_mode ? null : { symbiosis_mode: mode };\n }\n\n case \"source_link\": {\n const link = await input({\n message: \"Source link (blank allowed):\",\n default: token.source_link ?? \"\",\n });\n return link === token.source_link ? null : { source_link: link || null };\n }\n\n case \"question\": {\n const question = await input({\n message: \"Recall question (blank allowed):\",\n default: token.question ?? \"\",\n });\n return question === token.question\n ? null\n : { question: question || null };\n }\n\n default: {\n const exhaustive: never = field;\n throw new Error(`Unsupported token field: ${exhaustive}`);\n }\n }\n}\n","/**\n * `zam monitor` — Shell observation for real-time task monitoring.\n *\n * Installs shell hooks (zsh/bash/PowerShell) that capture commands with timing,\n * exit codes, and working directory to a JSONL file. The agent reads\n * this log to infer ratings for knowledge tokens.\n *\n * Usage:\n * eval \"$(zam monitor start --session <id>)\" # zsh/bash\n * Invoke-Expression (& zam monitor start --session <id>) # PowerShell\n * zam monitor status --session <id> # check log stats\n */\n\nimport { execFileSync, execSync } from \"node:child_process\";\nimport { unlinkSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { basename, join } from \"node:path\";\nimport { Command } from \"commander\";\nimport type { Database, MonitorEvent } from \"../../kernel/index.js\";\nimport {\n ensureMonitorDir,\n generateBashHooks,\n generateBashUnhooks,\n generatePowerShellHooks,\n generatePowerShellUnhooks,\n generateZshHooks,\n generateZshUnhooks,\n getMonitorLogStats,\n getMonitorPath,\n getSetting,\n monitorLogExists,\n openDatabase,\n pairCommands,\n readMonitorLog,\n setSetting,\n writeMonitorEvent,\n} from \"../../kernel/index.js\";\n\ntype MonitorShell = \"zsh\" | \"bash\" | \"pwsh\" | \"powershell\";\n\nfunction isPowerShellShell(shell: MonitorShell): boolean {\n return shell === \"pwsh\" || shell === \"powershell\";\n}\n\nfunction normalizeShell(shell: string | undefined): MonitorShell {\n if (!shell) return detectShell();\n const normalized = shell.toLowerCase();\n if (\n normalized === \"zsh\" ||\n normalized === \"bash\" ||\n normalized === \"pwsh\" ||\n normalized === \"powershell\"\n ) {\n return normalized;\n }\n throw new Error(\n `Unsupported shell: ${shell}. Expected zsh, bash, pwsh, or powershell.`,\n );\n}\n\nfunction psSingleQuoted(value: string): string {\n return `'${value.replace(/'/g, \"''\")}'`;\n}\n\nfunction detectShell(): MonitorShell {\n if (process.platform === \"win32\")\n return findExecutable(\"pwsh.exe\") ? \"pwsh\" : \"powershell\";\n const shell = process.env.SHELL ?? \"\";\n return basename(shell) === \"bash\" ? \"bash\" : \"zsh\";\n}\n\nexport const monitorCommand = new Command(\"monitor\").description(\n \"Shell observation for real-time task monitoring\",\n);\n\n// ── zam monitor start ─────────────────────────────────────────────────────\n\nmonitorCommand\n .command(\"start\")\n .description(\"Output shell hook code to install monitoring\")\n .requiredOption(\"--session <id>\", \"Session ID to monitor\")\n .option(\n \"--shell <type>\",\n \"Shell type: zsh | bash | pwsh | powershell (auto-detected)\",\n )\n .action(async (opts) => {\n let shell: MonitorShell;\n try {\n shell = normalizeShell(opts.shell);\n } catch (err) {\n console.error(`# Error: ${(err as Error).message}`);\n process.exit(1);\n }\n\n // Validate session exists\n let db: Database | undefined;\n try {\n db = await openDatabase();\n const session = (await db\n .prepare(\"SELECT id, completed_at FROM sessions WHERE id = ?\")\n .get(opts.session)) as\n | { id: string; completed_at: string | null }\n | undefined;\n\n if (!session) {\n console.error(`# Error: Session not found: ${opts.session}`);\n process.exit(1);\n }\n if (session.completed_at) {\n console.error(`# Error: Session already completed: ${opts.session}`);\n process.exit(1);\n }\n } catch (err) {\n console.error(`# Error: ${(err as Error).message}`);\n process.exit(1);\n } finally {\n await db?.close();\n }\n\n ensureMonitorDir();\n const monitorFile = getMonitorPath(opts.session);\n\n // Write initial meta event\n const meta: MonitorEvent = {\n type: \"monitor_meta\",\n ts: new Date().toISOString(),\n event: \"start\",\n session_id: opts.session,\n shell,\n pid: process.pid,\n };\n writeMonitorEvent(opts.session, meta);\n\n // Output hook code to stdout\n if (shell === \"bash\") {\n console.log(generateBashHooks(monitorFile, opts.session));\n } else if (isPowerShellShell(shell)) {\n console.log(generatePowerShellHooks(monitorFile, opts.session));\n } else {\n console.log(generateZshHooks(monitorFile, opts.session));\n }\n });\n\n// ── zam monitor stop ──────────────────────────────────────────────────────\n\nmonitorCommand\n .command(\"stop\")\n .description(\"Output shell code to remove monitoring hooks\")\n .requiredOption(\"--session <id>\", \"Session ID\")\n .option(\n \"--shell <type>\",\n \"Shell type: zsh | bash | pwsh | powershell (auto-detected)\",\n )\n .action((opts) => {\n // Write stop meta event\n if (monitorLogExists(opts.session)) {\n const meta: MonitorEvent = {\n type: \"monitor_meta\",\n ts: new Date().toISOString(),\n event: \"stop\",\n session_id: opts.session,\n };\n writeMonitorEvent(opts.session, meta);\n }\n\n let shell: MonitorShell;\n try {\n shell = normalizeShell(opts.shell);\n } catch (err) {\n console.error(`# Error: ${(err as Error).message}`);\n process.exit(1);\n }\n\n if (shell === \"bash\") {\n console.log(generateBashUnhooks());\n } else if (isPowerShellShell(shell)) {\n console.log(generatePowerShellUnhooks());\n } else {\n console.log(generateZshUnhooks());\n }\n });\n\n// ── zam monitor status ────────────────────────────────────────────────────\n\nmonitorCommand\n .command(\"status\")\n .description(\"Show monitoring status for a session\")\n .requiredOption(\"--session <id>\", \"Session ID\")\n .option(\"--json\", \"Output as JSON\")\n .action((opts) => {\n const stats = getMonitorLogStats(opts.session);\n\n if (!stats.exists) {\n if (opts.json) {\n console.log(JSON.stringify({ exists: false }));\n } else {\n console.log(`No monitor log found for session ${opts.session}`);\n }\n return;\n }\n\n const events = readMonitorLog(opts.session);\n const commands = pairCommands(events);\n const errors = commands.filter(\n (c) => c.exitCode != null && c.exitCode !== 0,\n ).length;\n\n const meta = events.find(\n (e) => e.type === \"monitor_meta\" && e.event === \"start\",\n );\n const stopped = events.some(\n (e) => e.type === \"monitor_meta\" && e.event === \"stop\",\n );\n\n const result = {\n sessionId: opts.session,\n exists: true,\n active: !stopped,\n shell: meta?.shell ?? \"unknown\",\n totalCommands: commands.length,\n errors,\n sizeBytes: stats.sizeBytes,\n timeSpan:\n commands.length > 0\n ? {\n start: commands[0].startedAt,\n end:\n commands[commands.length - 1].endedAt ??\n commands[commands.length - 1].startedAt,\n }\n : null,\n };\n\n if (opts.json) {\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n\n console.log(`Monitor: ${opts.session}`);\n console.log(` Status: ${result.active ? \"active\" : \"stopped\"}`);\n console.log(` Shell: ${result.shell}`);\n console.log(` Commands: ${result.totalCommands}`);\n console.log(` Errors: ${result.errors}`);\n if (result.timeSpan) {\n console.log(` From: ${result.timeSpan.start}`);\n console.log(` To: ${result.timeSpan.end}`);\n }\n });\n\n// ── zam monitor open ─────────────────────────────────────────────────────\n\n/**\n * Resolve the `zam` invocation — built CLI if available, otherwise tsx source.\n * This ensures the spawned terminal uses the correct entrypoint.\n */\nfunction findExecutable(command: string): string | null {\n try {\n const lookup =\n process.platform === \"win32\"\n ? `where.exe ${command}`\n : `command -v ${command}`;\n const result = execSync(lookup, { encoding: \"utf-8\" })\n .split(/\\r?\\n/)[0]\n ?.trim();\n return result || null;\n } catch {\n return null;\n }\n}\n\nfunction resolveZamInvocation(shell: MonitorShell): string {\n const installed = findExecutable(\"zam\");\n if (installed) {\n return isPowerShellShell(shell)\n ? `& ${psSingleQuoted(installed)}`\n : installed;\n }\n\n const projectRoot = join(import.meta.dirname, \"..\", \"..\", \"..\");\n const cliSource = join(projectRoot, \"src/cli/index.ts\");\n if (isPowerShellShell(shell)) {\n return `& npx --prefix ${psSingleQuoted(projectRoot)} tsx ${psSingleQuoted(cliSource)}`;\n }\n return `npx --prefix ${JSON.stringify(projectRoot)} tsx ${JSON.stringify(cliSource)}`;\n}\n\nfunction buildMonitorSetupCommand(\n dir: string,\n sessionId: string,\n shell: MonitorShell,\n): string {\n const zamInvocation = resolveZamInvocation(shell);\n if (isPowerShellShell(shell)) {\n return [\n `Set-Location -LiteralPath ${psSingleQuoted(dir)}`,\n `$__zamHook = ${zamInvocation} monitor start --session ${psSingleQuoted(sessionId)} --shell ${shell}`,\n \"Invoke-Expression ($__zamHook -join [Environment]::NewLine)\",\n \"Remove-Variable __zamHook\",\n ].join(\"; \");\n }\n\n return `cd ${JSON.stringify(dir)} && eval \"$(${zamInvocation} monitor start --session ${sessionId} --shell ${shell})\"`;\n}\n\n/**\n * Detect whether iTerm2 is running (preferred on macOS).\n */\nfunction isItermRunning(): boolean {\n try {\n const result = execSync(\n 'osascript -e \\'tell application \"System Events\" to (name of processes) contains \"iTerm2\"\\' 2>/dev/null',\n { encoding: \"utf-8\" },\n ).trim();\n return result === \"true\";\n } catch {\n return false;\n }\n}\n\nmonitorCommand\n .command(\"open\")\n .description(\"Open a new monitored terminal window for a session\")\n .requiredOption(\"--session <id>\", \"Session ID to monitor\")\n .option(\"--dir <path>\", \"Working directory (defaults to cwd)\")\n .option(\n \"--shell <type>\",\n \"Shell type: zsh | bash | pwsh | powershell (auto-detected)\",\n )\n .action(async (opts) => {\n let shell: MonitorShell;\n try {\n shell = normalizeShell(opts.shell);\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n\n // Validate session exists\n let db: Database | undefined;\n try {\n db = await openDatabase();\n const session = (await db\n .prepare(\"SELECT id, completed_at FROM sessions WHERE id = ?\")\n .get(opts.session)) as\n | { id: string; completed_at: string | null }\n | undefined;\n\n if (!session) {\n console.error(`Error: Session not found: ${opts.session}`);\n process.exit(1);\n }\n if (session.completed_at) {\n console.error(`Error: Session already completed: ${opts.session}`);\n process.exit(1);\n }\n\n // Save monitor preference so the agent knows to default to terminal\n if (!(await getSetting(db, \"monitor_method\"))) {\n await setSetting(db, \"monitor_method\", \"terminal\");\n }\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n } finally {\n await db?.close();\n }\n\n const dir = opts.dir ?? process.cwd();\n const shellSetup = buildMonitorSetupCommand(dir, opts.session, shell);\n\n if (process.platform === \"darwin\" && !isPowerShellShell(shell)) {\n openMacTerminal(shellSetup, opts.session, dir);\n } else if (process.platform === \"win32\" && isPowerShellShell(shell)) {\n openWindowsPowerShell(shellSetup, opts.session, dir, shell);\n } else {\n console.log(`Run this in a new terminal:\\n`);\n console.log(` ${shellSetup}\\n`);\n console.log(\n `(Automatic terminal opening is only supported on macOS Terminal/iTerm2 and Windows PowerShell for now.)`,\n );\n }\n });\n\n/**\n * Open a macOS terminal window via AppleScript.\n * Uses a temp .scpt file to avoid shell quoting hell.\n */\nfunction openMacTerminal(\n shellSetup: string,\n sessionId: string,\n dir: string,\n): void {\n const useIterm = isItermRunning();\n const escaped = shellSetup.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n\n const appleScript = useIterm\n ? `tell application \"iTerm2\"\n activate\n set newWindow to (create window with default profile)\n tell current session of newWindow\n write text \"${escaped}\"\n end tell\nend tell`\n : `tell application \"Terminal\"\n activate\n do script \"${escaped}\"\nend tell`;\n\n const tmpFile = join(tmpdir(), `zam-monitor-${sessionId}.scpt`);\n try {\n writeFileSync(tmpFile, appleScript);\n execSync(`osascript ${JSON.stringify(tmpFile)}`, { stdio: \"ignore\" });\n console.log(\n `Opened ${useIterm ? \"iTerm2\" : \"Terminal.app\"} window with monitoring for session ${sessionId}`,\n );\n console.log(` Directory: ${dir}`);\n } catch (err) {\n console.error(`Failed to open terminal: ${(err as Error).message}`);\n console.log(`\\nRun this manually in a new terminal:\\n`);\n console.log(` ${shellSetup}`);\n } finally {\n try {\n unlinkSync(tmpFile);\n } catch {\n /* ignore */\n }\n }\n}\n\n/**\n * Open a Windows PowerShell/pwsh window with monitoring installed.\n */\nfunction openWindowsPowerShell(\n shellSetup: string,\n sessionId: string,\n dir: string,\n requestedShell: MonitorShell,\n): void {\n const requestedExecutable =\n requestedShell === \"powershell\" ? \"powershell.exe\" : \"pwsh.exe\";\n const executable = findExecutable(requestedExecutable)\n ? requestedExecutable\n : \"powershell.exe\";\n const startCommand = [\n \"Start-Process\",\n `-FilePath ${psSingleQuoted(executable)}`,\n `-ArgumentList @('-NoExit','-NoProfile','-Command',${psSingleQuoted(shellSetup)})`,\n ].join(\" \");\n\n try {\n execFileSync(\n \"powershell.exe\",\n [\"-NoProfile\", \"-ExecutionPolicy\", \"Bypass\", \"-Command\", startCommand],\n {\n stdio: \"ignore\",\n },\n );\n console.log(\n `Opened ${executable === \"pwsh.exe\" ? \"PowerShell\" : \"Windows PowerShell\"} window with monitoring for session ${sessionId}`,\n );\n console.log(` Directory: ${dir}`);\n } catch (err) {\n console.error(`Failed to open PowerShell: ${(err as Error).message}`);\n console.log(`\\nRun this manually in a new PowerShell terminal:\\n`);\n console.log(` ${shellSetup}`);\n }\n}\n","/**\n * `zam profile` — show or change this machine's ZAM install profile.\n *\n * Surfaces where everything lives so a non-developer never has to guess:\n * - install mode (developer vs default),\n * - the personal-content folder (beliefs/goals/identity), which may sit in a\n * file-synced directory (Drive, OneDrive, Dropbox, iCloud) — no GitHub,\n * - the data directory and database path.\n *\n * (Increment 12, Phase 3.)\n */\n\nimport { homedir } from \"node:os\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { Command } from \"commander\";\nimport {\n type Database,\n detectSyncProvider,\n getDefaultDbPath,\n getInstallMode,\n getSetting,\n type InstallMode,\n openDatabaseWithSync,\n setInstallMode,\n setSetting,\n} from \"../../kernel/index.js\";\n\nconst C = {\n reset: \"\\x1b[0m\",\n bold: \"\\x1b[1m\",\n cyan: \"\\x1b[36m\",\n dim: \"\\x1b[2m\",\n green: \"\\x1b[32m\",\n};\n\nfunction defaultPersonalDir(): string {\n return join(homedir(), \"Documents\", \"zam\");\n}\n\ninterface Profile {\n mode: InstallMode;\n personalDir: string;\n syncProvider: string | null;\n dataDir: string;\n dbPath: string;\n}\n\nfunction render(profile: Profile): void {\n const sync = profile.syncProvider\n ? `${C.green}${profile.syncProvider}${C.reset} ${C.dim}(good for cross-device snapshots)${C.reset}`\n : `${C.dim}local folder (use a synced folder or snapshots to move between machines)${C.reset}`;\n\n console.log(`${C.bold}ZAM install profile${C.reset}`);\n console.log(` mode: ${C.cyan}${profile.mode}${C.reset}`);\n console.log(` personal dir: ${C.cyan}${profile.personalDir}${C.reset}`);\n console.log(` sync: ${sync}`);\n console.log(` data dir: ${C.cyan}${profile.dataDir}${C.reset}`);\n console.log(` database: ${C.cyan}${profile.dbPath}${C.reset}`);\n}\n\nexport const profileCommand = new Command(\"profile\")\n .description(\"Show or change this machine's ZAM install profile\")\n .option(\"--mode <mode>\", \"Set install mode: developer | default\")\n .option(\"--dir <path>\", \"Set the personal-content folder\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (opts: { mode?: string; dir?: string; json?: boolean }) => {\n if (opts.mode && opts.mode !== \"developer\" && opts.mode !== \"default\") {\n console.error(`Invalid --mode: ${opts.mode}. Use developer or default.`);\n process.exit(1);\n }\n\n let db: Database | undefined;\n try {\n if (opts.mode) setInstallMode(opts.mode as InstallMode);\n\n db = await openDatabaseWithSync({ initialize: true });\n if (opts.dir) {\n await setSetting(db, \"personal.workspace_dir\", resolve(opts.dir));\n }\n const personalDir =\n (await getSetting(db, \"personal.workspace_dir\")) ||\n defaultPersonalDir();\n await db.close();\n db = undefined;\n\n const dbPath = getDefaultDbPath();\n const profile: Profile = {\n mode: getInstallMode(),\n personalDir,\n syncProvider: detectSyncProvider(personalDir),\n dataDir: dirname(dbPath),\n dbPath,\n };\n\n if (opts.json) {\n console.log(JSON.stringify(profile, null, 2));\n return;\n }\n render(profile);\n } catch (err) {\n await db?.close();\n console.error(\"Error:\", (err as Error).message);\n process.exit(1);\n }\n });\n","/**\n * `zam review` — Interactive review session.\n */\n\nimport { Command } from \"commander\";\nimport type { BloomLevel, Database } from \"../../kernel/index.js\";\nimport {\n buildReviewQueue,\n generatePrompt,\n openDatabase,\n resolveReviewContext,\n} from \"../../kernel/index.js\";\nimport { runInteractiveReviewAction } from \"../review-actions.js\";\nimport { resolveUser } from \"./resolve-user.js\";\n\nexport const reviewCommand = new Command(\"review\")\n .description(\"Start an interactive review session\")\n .option(\"--user <id>\", \"User ID (default: whoami)\")\n .option(\"--max-new <n>\", \"Maximum new cards\", \"10\")\n .option(\"--max-reviews <n>\", \"Maximum review cards\", \"50\")\n .option(\"--no-resolve\", \"Skip resolving source_link into inline context\")\n .action(async (opts) => {\n let db: Database | undefined;\n try {\n db = await openDatabase();\n const userId = await resolveUser(opts, db);\n\n const queue = await buildReviewQueue(db, {\n userId,\n maxNew: Number(opts.maxNew),\n maxReviews: Number(opts.maxReviews),\n });\n\n if (queue.items.length === 0) {\n console.log(\"No cards due for review. You're all caught up!\");\n await db.close();\n return;\n }\n\n console.log(`\\nReview session: ${queue.items.length} card(s)`);\n console.log(\n ` New: ${queue.newCount} Review: ${queue.reviewCount} Relearn: ${queue.relearnCount}`,\n );\n console.log(` Domains: ${queue.totalDomains.join(\", \")}`);\n console.log();\n\n const _completed = 0;\n let stoppedEarly = false;\n let maintenanceActions = 0;\n const results: Array<{\n slug: string;\n rating: number;\n nextDue: string | undefined;\n }> = [];\n\n for (const [index, item] of queue.items.entries()) {\n const prompt = generatePrompt({\n cardId: item.cardId,\n tokenId: item.tokenId,\n slug: item.slug,\n concept: item.concept,\n domain: item.domain,\n bloomLevel: item.bloomLevel as BloomLevel,\n sourceLink: item.sourceLink,\n });\n\n console.log(\n `\\n[${index + 1}/${queue.items.length}] ${prompt.bloomVerb} (Bloom ${prompt.bloomLevel})`,\n );\n console.log(`Domain: ${prompt.domain || \"(none)\"}`);\n if (prompt.sourceLink) {\n console.log(`Source: ${prompt.sourceLink}`);\n if (opts.resolve !== false) {\n const ctx = await resolveReviewContext(item.sourceLink, {\n maxChars: 1200,\n }).catch(() => null);\n if (ctx && ctx.sourceType === \"dynamic_search\") {\n console.log(` ↳ ${ctx.content}`);\n } else if (ctx?.content.trim()) {\n const indented = ctx.content\n .trimEnd()\n .split(\"\\n\")\n .map((line) => ` │ ${line}`)\n .join(\"\\n\");\n console.log(\" Context:\");\n console.log(indented);\n if (ctx.truncated) {\n console.log(\" │ … (truncated)\");\n }\n }\n }\n }\n console.log(`\\n ${prompt.question}\\n`);\n\n const action = await runInteractiveReviewAction({\n db,\n userId,\n item,\n mode: \"review\",\n });\n\n if (action.action === \"stop\") {\n stoppedEarly = true;\n console.log(\"\\nStopping review.\");\n break;\n }\n\n if (action.action === \"rate\") {\n results.push({\n slug: item.slug,\n rating: action.rating!,\n nextDue: action.result.evaluation?.nextDueAt,\n });\n } else if (action.action !== \"skip\") {\n maintenanceActions++;\n }\n }\n\n // Session summary\n console.log(`\\n${\"═\".repeat(50)}`);\n console.log(\n stoppedEarly ? \"Review session ended.\" : \"Review session complete!\",\n );\n console.log(` Cards rated: ${results.length}`);\n if (maintenanceActions > 0) {\n console.log(` Maintenance actions: ${maintenanceActions}`);\n }\n\n if (results.length > 0) {\n const avgRating =\n results.reduce((s, r) => s + r.rating, 0) / results.length;\n console.log(` Average rating: ${avgRating.toFixed(1)}`);\n\n const forgot = results.filter((r) => r.rating === 1).length;\n if (forgot > 0) {\n console.log(` Forgot: ${forgot} card(s)`);\n }\n }\n\n await db.close();\n } catch (err) {\n await db?.close();\n // User cancelled with Ctrl+C — exit gracefully\n if ((err as Error).name === \"ExitPromptError\") {\n console.log(\"\\nReview session cancelled.\");\n process.exit(0);\n }\n console.error(\"Error:\", (err as Error).message);\n process.exit(1);\n }\n });\n","/**\n * `zam session` — Session management subcommand group.\n *\n * Session start follows the two-phase flow from Increment 2:\n * Phase 1 — Repetition: review due cards (pure recall first, skippable)\n * Phase 2 — Task execution: pick a work item from ADO or enter a custom task\n */\n\nimport { readFileSync } from \"node:fs\";\nimport { input, select } from \"@inquirer/prompts\";\nimport { Command } from \"commander\";\nimport type {\n BloomLevel,\n Database,\n ExecutionContext,\n Rating,\n SynthesisConfidence,\n TokenPattern,\n} from \"../../kernel/index.js\";\nimport {\n applySessionSynthesis,\n buildReviewQueue,\n endSession,\n fetchActiveWorkItems,\n generatePrompt,\n getSessionSummary,\n getTokenBySlug,\n loadADOConfig,\n logStep,\n openDatabase,\n prepareSessionSynthesis,\n startSession,\n} from \"../../kernel/index.js\";\nimport { runInteractiveReviewAction } from \"../review-actions.js\";\nimport { resolveUser } from \"./resolve-user.js\";\nimport { withDb } from \"./shared/db.js\";\n\nexport const sessionCommand = new Command(\"session\").description(\n \"Manage learning sessions\",\n);\n\n// ── zam session start ─────────────────────────────────────────────────────\n\nsessionCommand\n .command(\"start\")\n .description(\"Start a new learning session (review → task)\")\n .option(\"--user <id>\", \"User ID (default: whoami)\")\n .option(\"--task <description>\", \"Task description (interactive if omitted)\")\n .option(\n \"--context <level>\",\n \"Execution context: shell | ui | reallife (default: shell)\",\n \"shell\",\n )\n .option(\n \"--skip-review\",\n \"Skip the repetition phase and go straight to task selection\",\n )\n .option(\n \"--review-minutes <n>\",\n \"Maximum minutes for the repetition phase (default: 20)\",\n \"20\",\n )\n .option(\"--json\", \"Output as JSON\")\n .option(\"--quiet\", \"Output only the session ID\")\n .action(async (opts) => {\n let db: Database | undefined;\n try {\n db = await openDatabase();\n\n const validContexts = [\"shell\", \"ui\", \"reallife\"];\n if (!validContexts.includes(opts.context)) {\n console.error(\n `Invalid context: ${opts.context}. Must be one of: ${validContexts.join(\", \")}`,\n );\n process.exit(1);\n }\n\n const userId = await resolveUser(opts, db);\n const reviewMinutes = Number(opts.reviewMinutes);\n\n // ── Phase 1: Repetition ────────────────────────────────────────────\n if (!opts.skipReview && !opts.quiet && !opts.json) {\n const reviewResults = await runRepetitionPhase(\n db,\n userId,\n reviewMinutes,\n );\n if (reviewResults.reviewed > 0) {\n console.log();\n }\n }\n\n // ── Phase 2: Task Selection ────────────────────────────────────────\n let task: string = opts.task;\n\n if (!task && !opts.quiet && !opts.json) {\n task = await selectTask();\n }\n\n if (!task) {\n // Fallback for --quiet/--json without --task\n console.error(\n \"Task description is required. Use --task or run interactively.\",\n );\n process.exit(1);\n }\n\n const session = await startSession(db, {\n user_id: userId,\n task,\n execution_context: opts.context as ExecutionContext,\n });\n\n await db.close();\n\n if (opts.quiet) {\n console.log(session.id);\n } else if (opts.json) {\n console.log(JSON.stringify(session, null, 2));\n } else {\n console.log(`\\nSession started: ${session.id}`);\n console.log(` User: ${session.user_id}`);\n console.log(` Task: ${session.task}`);\n console.log(` Context: ${session.execution_context}`);\n console.log(` Started: ${session.started_at}`);\n }\n } catch (err) {\n await db?.close();\n if ((err as Error).name === \"ExitPromptError\") {\n console.log(\"\\nSession cancelled.\");\n process.exit(0);\n }\n console.error(\"Error:\", (err as Error).message);\n process.exit(1);\n }\n });\n\n// ── Phase 1: Repetition ─────────────────────────────────────────────────────\n\ninterface RepetitionResult {\n reviewed: number;\n maintained: number;\n skipped: boolean;\n}\n\nasync function runRepetitionPhase(\n db: Database,\n userId: string,\n maxMinutes: number,\n): Promise<RepetitionResult> {\n const queue = await buildReviewQueue(db, { userId });\n\n if (queue.items.length === 0) {\n console.log(\"No cards due for review — moving to task selection.\\n\");\n return { reviewed: 0, maintained: 0, skipped: false };\n }\n\n console.log(\"═\".repeat(50));\n console.log(\"Phase 1: Repetition\");\n console.log(\"═\".repeat(50));\n console.log(`${queue.items.length} card(s) due`);\n console.log(\n ` New: ${queue.newCount} Review: ${queue.reviewCount} Relearn: ${queue.relearnCount}`,\n );\n console.log(` Domains: ${queue.totalDomains.join(\", \")}`);\n console.log(` Time limit: ${maxMinutes} minutes (skip anytime with 's')`);\n console.log();\n\n const startTime = Date.now();\n const timeLimitMs = maxMinutes * 60 * 1000;\n let reviewed = 0;\n let maintained = 0;\n\n for (const [index, item] of queue.items.entries()) {\n // Check time limit\n if (Date.now() - startTime >= timeLimitMs) {\n console.log(\n `\\nTime limit reached (${maxMinutes} min). Moving to task selection.`,\n );\n break;\n }\n\n const prompt = generatePrompt({\n cardId: item.cardId,\n tokenId: item.tokenId,\n slug: item.slug,\n concept: item.concept,\n domain: item.domain,\n bloomLevel: item.bloomLevel as BloomLevel,\n });\n\n const elapsed = Math.round((Date.now() - startTime) / 60000);\n console.log(\n `[${index + 1}/${queue.items.length}] ${prompt.bloomVerb} (Bloom ${prompt.bloomLevel}) — ${elapsed}/${maxMinutes} min`,\n );\n console.log(`Domain: ${prompt.domain || \"(none)\"}`);\n console.log(`\\n ${prompt.question}\\n`);\n\n const action = await runInteractiveReviewAction({\n db,\n userId,\n item,\n mode: \"session\",\n });\n\n if (action.action === \"stop\") {\n console.log(\"Stopping review and moving to task selection.\");\n return { reviewed, maintained, skipped: true };\n }\n\n if (action.action === \"rate\") {\n reviewed++;\n } else if (action.action !== \"skip\") {\n maintained++;\n }\n }\n\n if (reviewed > 0 || maintained > 0) {\n console.log(\"─\".repeat(50));\n console.log(`Repetition complete — ${reviewed} card(s) rated.`);\n if (maintained > 0) {\n console.log(`Maintenance actions: ${maintained}`);\n }\n }\n\n return { reviewed, maintained, skipped: false };\n}\n\n// ── Phase 2: Task Selection ─────────────────────────────────────────────────\n\nasync function selectTask(): Promise<string> {\n console.log(\"═\".repeat(50));\n console.log(\"Phase 2: Task Selection\");\n console.log(\"═\".repeat(50));\n\n const adoConfig = loadADOConfig();\n\n if (adoConfig) {\n const items = await fetchActiveWorkItems(adoConfig);\n\n if (items.length > 0) {\n const choices = items.map((wi) => ({\n name: `[${wi.type}] ${wi.title} (${wi.state})`,\n value: `[ADO-${wi.id}] ${wi.title}`,\n }));\n choices.push({ name: \"Enter a custom task...\", value: \"__custom__\" });\n\n const picked = await select({\n message: `${items.length} active work item(s) — pick one:`,\n choices,\n });\n\n if (picked !== \"__custom__\") return picked;\n } else {\n console.log(\"No active work items found in Azure DevOps.\");\n }\n }\n\n return input({ message: \"Task description:\" });\n}\n\n// ── Session synthesis ───────────────────────────────────────────────────────\n\nconst RATING_LABELS: Record<Rating, string> = {\n 1: \"Again\",\n 2: \"Hard\",\n 3: \"Good\",\n 4: \"Easy\",\n};\n\nfunction loadPatternFile(path: string | undefined): TokenPattern[] {\n if (!path) return [];\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(readFileSync(path, \"utf-8\"));\n } catch (err) {\n throw new Error(\n `Cannot read synthesis patterns from ${path}: ${(err as Error).message}`,\n );\n }\n\n const patterns =\n typeof parsed === \"object\" &&\n parsed !== null &&\n \"patterns\" in parsed &&\n Array.isArray(parsed.patterns)\n ? parsed.patterns\n : parsed;\n\n if (!Array.isArray(patterns)) {\n throw new Error(\n \"Synthesis pattern file must contain an array or { patterns: [...] }\",\n );\n }\n\n return patterns.map((entry: unknown, index: number) => {\n if (\n typeof entry !== \"object\" ||\n entry === null ||\n !(\"slug\" in entry) ||\n typeof entry.slug !== \"string\" ||\n !(\"patterns\" in entry) ||\n !Array.isArray(entry.patterns) ||\n !entry.patterns.every((pattern) => typeof pattern === \"string\")\n ) {\n throw new Error(\n `Invalid synthesis pattern at index ${index}: expected { slug, patterns[] }`,\n );\n }\n return { slug: entry.slug, patterns: entry.patterns };\n });\n}\n\nasync function runSynthesisPhase(\n db: Database,\n sessionId: string,\n options: {\n patternFile?: string;\n minConfidence: SynthesisConfidence;\n },\n): Promise<number> {\n const preview = await prepareSessionSynthesis(db, {\n sessionId,\n explicitPatterns: loadPatternFile(options.patternFile),\n minConfidence: options.minConfidence,\n });\n\n console.log(\"\\nObservation synthesis\");\n console.log(\"─\".repeat(50));\n console.log(\n ` Commands: ${preview.commandCount} Token patterns: ${preview.patternCount}`,\n );\n if (preview.alreadyApplied > 0) {\n console.log(` Already applied: ${preview.alreadyApplied}`);\n }\n if (preview.skippedLowConfidence > 0) {\n console.log(\n ` Below ${options.minConfidence} confidence: ${preview.skippedLowConfidence}`,\n );\n }\n\n if (preview.patternCount === 0) {\n console.log(\n \" No token patterns found. Link tokens to agent skills or pass --patterns <file>.\",\n );\n return 0;\n }\n if (preview.candidates.length === 0) {\n console.log(\" No new medium/high-confidence ratings to confirm.\");\n return 0;\n }\n\n let applied = 0;\n for (const candidate of preview.candidates) {\n console.log(`\\n${candidate.tokenSlug}: ${candidate.concept}`);\n console.log(\n ` Suggested: ${candidate.inferredRating} - ${RATING_LABELS[candidate.inferredRating]} (${candidate.confidence} confidence)`,\n );\n console.log(\n ` Evidence: ${candidate.evidence.matchedCommands} command(s), ${candidate.evidence.errorCount} error(s), ${candidate.evidence.selfCorrections} correction(s)${candidate.evidence.helpSeeking ? \", help used\" : \"\"}`,\n );\n for (const command of candidate.matchedCommandTexts.slice(0, 5)) {\n console.log(` ${command}`);\n }\n\n const otherRatings = ([1, 2, 3, 4] as Rating[]).filter(\n (rating) => rating !== candidate.inferredRating,\n );\n const choice = await select<Rating | \"skip\">({\n message: `Confirm rating for ${candidate.tokenSlug}:`,\n choices: [\n {\n name: `Accept ${candidate.inferredRating} - ${RATING_LABELS[candidate.inferredRating]}`,\n value: candidate.inferredRating,\n },\n ...otherRatings.map((rating) => ({\n name: `Override with ${rating} - ${RATING_LABELS[rating]}`,\n value: rating,\n })),\n { name: \"Skip without changing learning state\", value: \"skip\" },\n ],\n });\n\n if (choice === \"skip\") {\n console.log(\" Skipped.\");\n continue;\n }\n\n const result = await applySessionSynthesis(db, {\n sessionId,\n tokenSlug: candidate.tokenSlug,\n inferredRating: candidate.inferredRating,\n confirmedRating: choice,\n confidence: candidate.confidence,\n evidence: candidate.evidence,\n matchedCommandTexts: candidate.matchedCommandTexts,\n });\n\n if (!result.applied) {\n console.log(\" Already applied; learning state unchanged.\");\n continue;\n }\n\n applied++;\n console.log(` Applied ${choice} - ${RATING_LABELS[choice]}.`);\n if (result.blocked) {\n console.log(\n ` Blocked ${result.blocked.blockedSlug}; prerequisites surfaced.`,\n );\n }\n }\n\n return applied;\n}\n\n// ── zam session log ───────────────────────────────────────────────────────\n\nsessionCommand\n .command(\"log\")\n .description(\"Log a step within a session\")\n .requiredOption(\"--session <id>\", \"Session ID\")\n .requiredOption(\"--token <slug>\", \"Token slug\")\n .requiredOption(\"--done-by <who>\", \"Who performed the step (user or agent)\")\n .option(\"--rating <n>\", \"Rating (1-4)\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--quiet\", \"Suppress output (exit code only)\")\n .action(async (opts) => {\n await withDb(async (db) => {\n const token = await getTokenBySlug(db, opts.token);\n if (!token) {\n console.error(`Token not found: ${opts.token}`);\n process.exit(1);\n }\n\n const step = await logStep(db, {\n session_id: opts.session,\n token_id: token.id,\n done_by: opts.doneBy as \"user\" | \"agent\",\n rating: opts.rating ? Number(opts.rating) : undefined,\n });\n\n if (opts.quiet) return;\n if (opts.json) {\n console.log(JSON.stringify(step, null, 2));\n } else {\n console.log(`Step logged: ${step.id}`);\n console.log(` Token: ${opts.token}`);\n console.log(` Done by: ${step.done_by}`);\n if (step.rating != null) {\n console.log(` Rating: ${step.rating}`);\n }\n }\n });\n });\n\n// ── zam session end ───────────────────────────────────────────────────────\n\nsessionCommand\n .command(\"end\")\n .description(\"End a session and show summary\")\n .requiredOption(\"--session <id>\", \"Session ID\")\n .option(\n \"--synthesize\",\n \"Analyze monitor evidence and confirm ratings before ending\",\n )\n .option(\n \"--patterns <path>\",\n \"JSON file with additional { slug, patterns[] } mappings\",\n )\n .option(\n \"--min-confidence <level>\",\n \"Minimum synthesis confidence: medium | high\",\n \"medium\",\n )\n .option(\"--json\", \"Output as JSON\")\n .action(async (opts) => {\n await withDb(async (db) => {\n if (opts.patterns && !opts.synthesize) {\n throw new Error(\"--patterns requires --synthesize\");\n }\n if (opts.synthesize && opts.json) {\n throw new Error(\"--json cannot be combined with interactive synthesis\");\n }\n if (![\"medium\", \"high\"].includes(opts.minConfidence)) {\n throw new Error(\"--min-confidence must be medium or high\");\n }\n\n const before = await getSessionSummary(db, opts.session);\n if (opts.synthesize) {\n await runSynthesisPhase(db, opts.session, {\n patternFile: opts.patterns,\n minConfidence: opts.minConfidence as SynthesisConfidence,\n });\n }\n\n if (!before.session.completed_at) {\n await endSession(db, opts.session);\n } else if (!opts.synthesize) {\n throw new Error(`Session already completed: ${opts.session}`);\n }\n\n const summary = await getSessionSummary(db, opts.session);\n\n if (opts.json) {\n console.log(JSON.stringify(summary, null, 2));\n return;\n }\n\n console.log(`Session ${summary.session.id} completed.`);\n console.log(` Task: ${summary.session.task}`);\n console.log(` Started: ${summary.session.started_at}`);\n console.log(` Completed: ${summary.session.completed_at}`);\n console.log(` Steps: ${summary.steps.length}`);\n\n if (summary.steps.length > 0) {\n console.log(\"\\nSteps:\");\n console.log(\" Token Done by Rating Concept\");\n console.log(` ${\"─\".repeat(70)}`);\n for (const s of summary.steps) {\n console.log(\n ` ${s.slug.padEnd(21)} ${s.done_by.padEnd(8)} ${String(s.rating ?? \"-\").padEnd(7)} ${s.concept.slice(0, 30)}`,\n );\n }\n }\n });\n });\n","/**\n * `zam settings` — User settings management.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { Command } from \"commander\";\nimport {\n deleteSetting,\n getAllSettings,\n getAllSettingsDetailed,\n getRepoPaths,\n getSetting,\n setSetting,\n} from \"../../kernel/index.js\";\nimport { withDb } from \"./shared/db.js\";\n\nexport const settingsCommand = new Command(\"settings\").description(\n \"Manage user settings\",\n);\n\n// ── zam settings show ─────────────────────────────────────────────────────\n\nsettingsCommand\n .command(\"show\")\n .description(\"Show all settings\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (opts) => {\n await withDb(async (db) => {\n if (opts.json) {\n console.log(JSON.stringify(await getAllSettings(db), null, 2));\n return;\n }\n\n const settings = await getAllSettingsDetailed(db);\n if (settings.length === 0) {\n console.log(\"No settings configured.\");\n return;\n }\n\n console.log(\"Settings:\\n\");\n console.log(\"Key Value Updated\");\n console.log(\"─\".repeat(65));\n for (const s of settings) {\n console.log(\n `${s.key.padEnd(20)} ${s.value.padEnd(20)} ${s.updated_at}`,\n );\n }\n });\n });\n\n// ── zam settings get ──────────────────────────────────────────────────────\n\nsettingsCommand\n .command(\"get <key>\")\n .description(\"Get a single setting\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (key, opts) => {\n await withDb(async (db) => {\n const value = await getSetting(db, key);\n\n if (opts.json) {\n console.log(JSON.stringify({ key, value: value ?? null }));\n return;\n }\n\n if (value === undefined) {\n console.log(`Not set: ${key}`);\n } else {\n console.log(value);\n }\n });\n });\n\n// ── zam settings set ──────────────────────────────────────────────────────\n\nsettingsCommand\n .command(\"set <key> <value>\")\n .description(\"Set a setting\")\n .option(\"--quiet\", \"Suppress output\")\n .action(async (key, value, opts) => {\n await withDb(async (db) => {\n let parsedVal = value;\n if (key === \"llm.enabled\") {\n const lower = value.toLowerCase();\n if (\n lower === \"on\" ||\n lower === \"enable\" ||\n lower === \"enabled\" ||\n lower === \"true\"\n ) {\n parsedVal = \"true\";\n } else if (\n lower === \"off\" ||\n lower === \"disable\" ||\n lower === \"disabled\" ||\n lower === \"false\"\n ) {\n parsedVal = \"false\";\n }\n }\n await setSetting(db, key, parsedVal);\n if (!opts.quiet) {\n console.log(`Set ${key} = ${parsedVal}`);\n }\n });\n });\n\n// ── zam settings delete ───────────────────────────────────────────────────\n\nsettingsCommand\n .command(\"delete <key>\")\n .description(\"Delete a setting\")\n .option(\"--quiet\", \"Suppress output\")\n .action(async (key, opts) => {\n await withDb(async (db) => {\n const deleted = await deleteSetting(db, key);\n if (!opts.quiet) {\n if (deleted) {\n console.log(`Deleted: ${key}`);\n } else {\n console.log(`Not found: ${key}`);\n }\n }\n });\n });\n\n// ── zam settings llm [state] ──────────────────────────────────────────────\n\nsettingsCommand\n .command(\"llm [state]\")\n .description(\n \"Quickly enable/disable or check local LLM integration (on/off/enable/disable)\",\n )\n .action(async (state) => {\n await withDb(async (db) => {\n if (!state) {\n const enabled = (await getSetting(db, \"llm.enabled\")) || \"false\";\n console.log(\n `LLM Integration is currently: ${\n enabled === \"true\"\n ? \"\\x1b[32mON (enabled)\\x1b[0m\"\n : \"\\x1b[31mOFF (disabled)\\x1b[0m\"\n }`,\n );\n return;\n }\n\n const lower = state.toLowerCase();\n let value = \"false\";\n if (\n lower === \"on\" ||\n lower === \"enable\" ||\n lower === \"enabled\" ||\n lower === \"true\"\n ) {\n value = \"true\";\n } else if (\n lower === \"off\" ||\n lower === \"disable\" ||\n lower === \"disabled\" ||\n lower === \"false\"\n ) {\n value = \"false\";\n } else {\n console.error(\n `Invalid state: ${state}. Use on, off, enable, or disable.`,\n );\n process.exit(1);\n }\n\n await setSetting(db, \"llm.enabled\", value);\n console.log(\n `LLM Integration is now: ${\n value === \"true\"\n ? \"\\x1b[32mON (enabled)\\x1b[0m\"\n : \"\\x1b[31mOFF (disabled)\\x1b[0m\"\n }`,\n );\n });\n });\n\n// ── zam settings locale [lang] ───────────────────────────────────────────\n\nsettingsCommand\n .command(\"locale [lang]\")\n .description(\n \"Quickly set or check manual ZAM language override (en/de/es/fr/pt/zh/ja)\",\n )\n .action(async (lang) => {\n await withDb(async (db) => {\n if (!lang) {\n const locale = (await getSetting(db, \"system.locale\")) || \"en\";\n console.log(`Active language (locale): \\x1b[36m${locale}\\x1b[0m`);\n return;\n }\n\n const lower = lang.toLowerCase();\n const supported = [\"en\", \"de\", \"es\", \"fr\", \"pt\", \"zh\", \"ja\"];\n if (!supported.includes(lower)) {\n console.error(\n `Invalid language code: ${lang}. Supported: ${supported.join(\", \")}`,\n );\n process.exit(1);\n }\n\n await setSetting(db, \"system.locale\", lower);\n console.log(`Language set to: \\x1b[32m${lower}\\x1b[0m`);\n });\n });\n\n// ── zam settings repos ───────────────────────────────────────────────────\n\nsettingsCommand\n .command(\"repos\")\n .description(\"Show or set Personal, Team, and Organization repository paths\")\n .option(\"--personal <path>\", \"Set the Personal Repository path\")\n .option(\"--team <path>\", \"Set the Team Repository path\")\n .option(\"--org <path>\", \"Set the Organization Repository path\")\n .action(async (opts) => {\n await withDb(async (db) => {\n let changed = false;\n\n if (opts.personal !== undefined) {\n await setSetting(db, \"repo.personal\", opts.personal);\n console.log(`Set repo.personal = ${opts.personal}`);\n changed = true;\n }\n if (opts.team !== undefined) {\n await setSetting(db, \"repo.team\", opts.team);\n console.log(`Set repo.team = ${opts.team}`);\n changed = true;\n }\n if (opts.org !== undefined) {\n await setSetting(db, \"repo.org\", opts.org);\n console.log(`Set repo.org = ${opts.org}`);\n changed = true;\n }\n\n if (changed) {\n console.log(\"\\nUpdated Repository Settings:\\n\");\n } else {\n console.log(\"Repository Settings:\\n\");\n }\n\n const paths = await getRepoPaths(db);\n console.log(\n `Personal Repo: ${\n paths.personal\n ? `\\x1b[32m${paths.personal}\\x1b[0m`\n : \"\\x1b[31mNot Configured\\x1b[0m\"\n }`,\n );\n console.log(\n `Team Repo: ${\n paths.team\n ? `\\x1b[32m${paths.team}\\x1b[0m`\n : \"\\x1b[31mNot Configured\\x1b[0m\"\n }`,\n );\n console.log(\n `Org Repo: ${\n paths.org\n ? `\\x1b[32m${paths.org}\\x1b[0m`\n : \"\\x1b[31mNot Configured\\x1b[0m\"\n }`,\n );\n\n // Check if folders exist\n console.log(\"\\nValidation:\");\n for (const [name, path] of Object.entries(paths)) {\n if (path) {\n const exists = existsSync(path);\n console.log(\n ` ${name.padEnd(9)}: ${\n exists\n ? \"\\x1b[32m✓ Valid folder\\x1b[0m\"\n : \"\\x1b[31m✗ Directory does not exist\\x1b[0m\"\n }`,\n );\n } else {\n console.log(` ${name.padEnd(9)}: \\x1b[33m- Not Set\\x1b[0m`);\n }\n }\n });\n });\n","/**\n * `zam setup` — Distribute skill files from the zam package into the current\n * personal instance's agent skill directories, and optionally initialize the\n * ZAM database and generate agent-specific instruction files.\n *\n * Run this once after cloning a ZAM personal instance, and again after\n * upgrading zam (with --force) to refresh the skill files.\n */\n\nimport { copyFileSync, existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { basename, dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { Command } from \"commander\";\nimport { getDefaultDbPath, openDatabaseWithSync } from \"../../kernel/index.js\";\n\n// The bundled CLI resolves from dist/cli/index.js; source tests resolve from\n// src/cli/commands/setup.ts. Select the first candidate containing package.json.\nconst packageRoot =\n [\n fileURLToPath(new URL(\"../..\", import.meta.url)),\n fileURLToPath(new URL(\"../../..\", import.meta.url)),\n ].find((candidate) => existsSync(join(candidate, \"package.json\"))) ??\n fileURLToPath(new URL(\"../..\", import.meta.url));\n\nconst SKILL_PAIRS: Array<{ from: string; to: string }> = [\n {\n from: join(packageRoot, \".claude\", \"skills\", \"zam\", \"SKILL.md\"),\n to: join(\".claude\", \"skills\", \"zam\", \"SKILL.md\"),\n },\n {\n from: join(packageRoot, \".agent\", \"skills\", \"zam\", \"SKILL.md\"),\n to: join(\".agent\", \"skills\", \"zam\", \"SKILL.md\"),\n },\n {\n from: join(packageRoot, \".agents\", \"skills\", \"zam\", \"SKILL.md\"),\n to: join(\".agents\", \"skills\", \"zam\", \"SKILL.md\"),\n },\n];\n\nexport function copySkills(force: boolean, cwd: string = process.cwd()): void {\n let anyAction = false;\n\n for (const { from, to } of SKILL_PAIRS) {\n const dest = join(cwd, to);\n\n if (!existsSync(from)) {\n console.warn(` warn source not found, skipping: ${from}`);\n continue;\n }\n\n if (existsSync(dest) && !force) {\n console.log(` skip ${to} (already present — use --force to update)`);\n continue;\n }\n\n mkdirSync(dirname(dest), { recursive: true });\n copyFileSync(from, dest);\n console.log(` copy ${to}`);\n anyAction = true;\n }\n\n if (!anyAction && !force) {\n console.log(\n \"\\nSkill files are already up to date. Run with --force to overwrite.\",\n );\n }\n}\n\nasync function initDatabase(skipInit: boolean): Promise<void> {\n if (skipInit) return;\n\n try {\n const dbPath = getDefaultDbPath();\n const db = await openDatabaseWithSync({ initialize: true });\n await db.close();\n console.log(` init ZAM database at ${dbPath}`);\n } catch (err) {\n // Database may already exist — not an error during setup.\n const msg = (err as Error).message;\n if (!msg.includes(\"already\")) {\n console.warn(` warn database init: ${msg}`);\n } else {\n console.log(` skip database already initialized`);\n }\n }\n}\n\nexport function writeClaudeMd(\n skipClaudeMd: boolean,\n cwd: string = process.cwd(),\n): void {\n if (skipClaudeMd) return;\n\n const dest = join(cwd, \"CLAUDE.md\");\n if (existsSync(dest)) {\n console.log(` skip CLAUDE.md (already present)`);\n return;\n }\n\n const name = basename(cwd);\n writeFileSync(\n dest,\n `# ZAM Personal Kernel — ${name}\n\nThis is a ZAM personal instance. ZAM builds lasting skills through spaced\nrepetition during real work — not separate study sessions.\n\n## First time here?\nRun \\`/setup\\` in Claude Code or Gemini CLI to complete first-time setup.\n\n## Regular use\nRun \\`/zam\\` to start a learning session on whatever you are working on.\n\n## What lives here\n- \\`beliefs/\\` — your worldview, approved by git commit\n- \\`goals/\\` — your objectives, decomposed into tasks and learning tokens\n\n## Fast-changing data\nLearning tokens, cards, and review history live in local SQLite by default.\nUse \\`zam connector setup turso\\` to store cloud credentials in\n\\`~/.zam/credentials.json\\` and use a Turso database across machines.\n`,\n \"utf8\",\n );\n console.log(` write CLAUDE.md`);\n}\n\nexport function writeAgentsMd(\n skipAgentsMd: boolean,\n cwd: string = process.cwd(),\n): void {\n if (skipAgentsMd) return;\n\n const dest = join(cwd, \"AGENTS.md\");\n if (existsSync(dest)) {\n console.log(` skip AGENTS.md (already present)`);\n return;\n }\n\n const name = basename(cwd);\n writeFileSync(\n dest,\n `# ZAM Personal Kernel - ${name}\n\nThis is a ZAM personal instance. ZAM builds lasting skills through spaced\nrepetition during real work, not separate study sessions.\n\n## First time here?\nRun \\`zam setup\\` from the shell. When this repository includes\n\\`.agents/skills/setup/\\`, you can instead select \\`setup\\` through \\`/skills\\`\nor invoke \\`$setup\\`.\n\n## Regular use\nSelect the \\`zam\\` skill through \\`/skills\\` or invoke \\`$zam\\` to start a\nlearning session on whatever you are working on.\n\n## What lives here\n- \\`beliefs/\\` - your worldview, approved by git commit\n- \\`goals/\\` - your objectives, decomposed into tasks and learning tokens\n\n## Fast-changing data\nLearning tokens, cards, and review history live in local SQLite by default.\nUse \\`zam connector setup turso\\` to store cloud credentials in\n\\`~/.zam/credentials.json\\` and use a Turso database across machines.\n\n## Codex skills\nCodex discovers repository skills under \\`.agents/skills/\\`. Run\n\\`zam setup --force\\` after upgrading \\`zam-core\\` to refresh them.\n`,\n \"utf8\",\n );\n console.log(` write AGENTS.md`);\n}\n\nexport const setupCommand = new Command(\"setup\")\n .description(\n \"Distribute ZAM skill files into this personal instance and initialize the database\",\n )\n .option(\n \"--force\",\n \"overwrite existing skill files (use after upgrading zam)\",\n false,\n )\n .option(\"--skip-init\", \"skip database initialization\", false)\n .option(\"--skip-claude-md\", \"skip CLAUDE.md generation\", false)\n .option(\"--skip-agents-md\", \"skip AGENTS.md generation\", false)\n .action(\n async (opts: {\n force: boolean;\n skipInit: boolean;\n skipClaudeMd: boolean;\n skipAgentsMd: boolean;\n }) => {\n console.log(`Setting up ZAM in ${process.cwd()}\\n`);\n\n copySkills(opts.force);\n await initDatabase(opts.skipInit);\n writeClaudeMd(opts.skipClaudeMd);\n writeAgentsMd(opts.skipAgentsMd);\n\n console.log(\n \"\\nDone. Run `zam whoami --set <your-id>` to set your identity. Start the `zam` skill with `/zam` in Claude/Gemini-compatible clients or `$zam` (or `/skills`) in Codex.\",\n );\n },\n );\n","/**\n * `zam skill` — Manage agent skill entries (task recipes).\n */\n\nimport { Command } from \"commander\";\nimport {\n createAgentSkill,\n getAgentSkill,\n listAgentSkills,\n} from \"../../kernel/index.js\";\nimport { withDb } from \"./shared/db.js\";\n\nexport const skillCommand = new Command(\"skill\").description(\n \"Manage agent skill entries (task recipes)\",\n);\n\n// ── zam skill list ────────────────────────────────────────────────────────\n\nskillCommand\n .command(\"list\")\n .description(\"List all agent skills\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (opts) => {\n await withDb(async (db) => {\n const skills = await listAgentSkills(db);\n\n if (opts.json) {\n console.log(JSON.stringify(skills, null, 2));\n return;\n }\n\n if (skills.length === 0) {\n console.log(\"No agent skills registered yet.\");\n return;\n }\n\n console.log(`Agent Skills (${skills.length})`);\n console.log(\"─\".repeat(60));\n for (const s of skills) {\n console.log(\n ` ${s.slug.padEnd(30)} [${s.source}] ${s.description.slice(0, 40)}`,\n );\n console.log(\n ` ${s.steps.length} step(s) tokens: ${s.token_slugs.join(\", \") || \"none\"}`,\n );\n }\n });\n });\n\n// ── zam skill show ────────────────────────────────────────────────────────\n\nskillCommand\n .command(\"show\")\n .description(\"Show a specific agent skill\")\n .requiredOption(\"--slug <slug>\", \"Skill slug\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (opts) => {\n await withDb(async (db) => {\n const skill = await getAgentSkill(db, opts.slug);\n if (!skill) {\n console.error(`Skill not found: ${opts.slug}`);\n process.exit(1);\n }\n\n if (opts.json) {\n console.log(JSON.stringify(skill, null, 2));\n return;\n }\n\n console.log(`Skill: ${skill.slug}`);\n console.log(` Description: ${skill.description}`);\n console.log(` Source: ${skill.source}`);\n console.log(` Tokens: ${skill.token_slugs.join(\", \") || \"none\"}`);\n console.log(` Created: ${skill.created_at}`);\n console.log(`\\nSteps:`);\n skill.steps.forEach((step, i) => {\n console.log(` ${i + 1}. ${step}`);\n });\n });\n });\n\n// ── zam skill add ─────────────────────────────────────────────────────────\n\nskillCommand\n .command(\"add\")\n .description(\"Register a new agent skill\")\n .requiredOption(\"--slug <slug>\", \"Unique skill identifier\")\n .requiredOption(\"--description <text>\", \"One-sentence description\")\n .requiredOption(\"--steps <json>\", \"JSON array of step strings\")\n .option(\n \"--tokens <slugs>\",\n \"Comma-separated token slugs related to this skill\",\n )\n .option(\n \"--source <type>\",\n \"Source: learned | builtin (default: learned)\",\n \"learned\",\n )\n .option(\"--json\", \"Output as JSON\")\n .action(async (opts) => {\n await withDb(async (db) => {\n let steps: string[];\n try {\n steps = JSON.parse(opts.steps) as string[];\n if (!Array.isArray(steps))\n throw new Error(\"steps must be a JSON array\");\n } catch {\n console.error(\"Invalid --steps: must be a valid JSON array of strings\");\n process.exit(1);\n }\n\n const tokenSlugs = opts.tokens\n ? opts.tokens\n .split(\",\")\n .map((s: string) => s.trim())\n .filter(Boolean)\n : [];\n\n const skill = await createAgentSkill(db, {\n slug: opts.slug,\n description: opts.description,\n steps,\n token_slugs: tokenSlugs,\n source: opts.source as \"learned\" | \"builtin\",\n });\n\n if (opts.json) {\n console.log(JSON.stringify(skill, null, 2));\n } else {\n console.log(`Skill registered: ${skill.slug}`);\n console.log(` ${skill.steps.length} step(s) saved`);\n }\n });\n });\n","/**\n * `zam snapshot` — export / import / verify a portable SQL-text snapshot of the\n * learning database. (Increment 12, Phase 4.)\n *\n * Snapshots are safe to keep in a file-sync folder (Drive, OneDrive, iCloud):\n * unlike the live `~/.zam/zam.db` WAL database, a snapshot is plain SQL text and\n * is never written while half-applied. Export on one machine, import on another.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { Command } from \"commander\";\nimport {\n exportSnapshot,\n getSetting,\n importSnapshot,\n openDatabaseWithSync,\n verifySnapshot,\n} from \"../../kernel/index.js\";\n\n/** `zam-snapshot-2026-06-13T09-41-22.sql` — sorts chronologically. */\nfunction defaultOutName(): string {\n const stamp = new Date()\n .toISOString()\n .replace(/\\.\\d+Z$/, \"\")\n .replace(/:/g, \"-\");\n return `zam-snapshot-${stamp}.sql`;\n}\n\nfunction summarize(tables: Record<string, number>): {\n total: number;\n nonEmpty: string[];\n} {\n let total = 0;\n const nonEmpty: string[] = [];\n for (const [name, count] of Object.entries(tables)) {\n total += count;\n if (count > 0) nonEmpty.push(`${name}: ${count}`);\n }\n return { total, nonEmpty };\n}\n\nconst exportCmd = new Command(\"export\")\n .description(\"Write a portable SQL-text snapshot of the database\")\n .option(\"--out <file>\", \"Output file (use - for stdout)\")\n .action(async (opts: { out?: string }) => {\n let db: Awaited<ReturnType<typeof openDatabaseWithSync>> | undefined;\n try {\n db = await openDatabaseWithSync({ initialize: true });\n const snapshot = await exportSnapshot(db);\n // Default snapshots into the personal folder (which may be file-synced),\n // so cross-device moves work without copying the live database.\n const personalDir =\n (await getSetting(db, \"personal.workspace_dir\")) ||\n join(homedir(), \"Documents\", \"zam\");\n await db.close();\n db = undefined;\n\n const manifest = verifySnapshot(snapshot);\n const { total, nonEmpty } = summarize(manifest.tables);\n\n if (opts.out === \"-\") {\n process.stdout.write(snapshot);\n return;\n }\n\n const out = opts.out ?? join(personalDir, \"snapshots\", defaultOutName());\n const dir = dirname(out);\n if (dir && dir !== \".\" && !existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n writeFileSync(out, snapshot, \"utf-8\");\n\n console.log(`Snapshot written: ${out}`);\n console.log(\n ` ${total} row(s)${nonEmpty.length ? ` — ${nonEmpty.join(\", \")}` : \"\"}`,\n );\n } catch (err) {\n await db?.close();\n console.error(\"Error:\", (err as Error).message);\n process.exit(1);\n }\n });\n\nconst importCmd = new Command(\"import\")\n .description(\"Restore a snapshot into the database\")\n .argument(\"<file>\", \"Snapshot file to restore\")\n .option(\"--force\", \"Overwrite a non-empty database\", false)\n .action(async (file: string, opts: { force: boolean }) => {\n let db: Awaited<ReturnType<typeof openDatabaseWithSync>> | undefined;\n try {\n if (!existsSync(file)) {\n console.error(`Error: Snapshot file not found: ${file}`);\n process.exit(1);\n }\n const snapshot = readFileSync(file, \"utf-8\");\n\n db = await openDatabaseWithSync({ initialize: true });\n const result = await importSnapshot(db, snapshot, { force: opts.force });\n await db.close();\n db = undefined;\n\n const { nonEmpty } = summarize(result.tables);\n console.log(`Snapshot restored from ${file}`);\n console.log(\n ` ${result.total} row(s)${nonEmpty.length ? ` — ${nonEmpty.join(\", \")}` : \"\"}`,\n );\n } catch (err) {\n await db?.close();\n console.error(\"Error:\", (err as Error).message);\n process.exit(1);\n }\n });\n\nconst verifyCmd = new Command(\"verify\")\n .description(\"Check a snapshot's manifest and checksum without importing\")\n .argument(\"<file>\", \"Snapshot file to verify\")\n .action((file: string) => {\n try {\n if (!existsSync(file)) {\n console.error(`Error: Snapshot file not found: ${file}`);\n process.exit(1);\n }\n const manifest = verifySnapshot(readFileSync(file, \"utf-8\"));\n const { total, nonEmpty } = summarize(manifest.tables);\n console.log(`Valid snapshot (format v${manifest.version})`);\n console.log(` created: ${manifest.createdAt}`);\n console.log(\n ` ${total} row(s)${nonEmpty.length ? ` — ${nonEmpty.join(\", \")}` : \"\"}`,\n );\n } catch (err) {\n console.error(\"Error:\", (err as Error).message);\n process.exit(1);\n }\n });\n\nexport const snapshotCommand = new Command(\"snapshot\")\n .description(\"Export, import, or verify a portable database snapshot\")\n .addCommand(exportCmd)\n .addCommand(importCmd)\n .addCommand(verifyCmd);\n","/**\n * `zam stats` — Learning dashboard.\n */\n\nimport { Command } from \"commander\";\nimport { getDomainCompetence, getUserStats } from \"../../kernel/index.js\";\nimport { resolveUser } from \"./resolve-user.js\";\nimport { withDb } from \"./shared/db.js\";\n\nexport const statsCommand = new Command(\"stats\")\n .description(\"Show learning dashboard for a user\")\n .option(\"--user <id>\", \"User ID (default: whoami)\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (opts) => {\n await withDb(async (db) => {\n const userId = await resolveUser(opts, db);\n const stats = await getUserStats(db, userId);\n const domains = await getDomainCompetence(db, userId);\n\n if (opts.json) {\n console.log(JSON.stringify({ stats, domains }, null, 2));\n return;\n }\n\n console.log(`Learning Dashboard — ${stats.userId}`);\n console.log(\"═\".repeat(50));\n console.log(` Total tokens: ${stats.totalTokens}`);\n console.log(` Cards in deck: ${stats.cardsInDeck}`);\n console.log(` Due today: ${stats.dueToday}`);\n console.log(` Blocked: ${stats.blocked}`);\n console.log(` Mature: ${stats.mature}`);\n console.log(` Avg stability: ${stats.avgStability ?? \"N/A\"}`);\n console.log(` Total sessions: ${stats.totalSessions}`);\n console.log(` Last session: ${stats.lastSession ?? \"N/A\"}`);\n\n if (domains.length > 0) {\n console.log(\"\\nDomain Competence:\");\n console.log(\"─\".repeat(80));\n console.log(\n \" Domain Cards Mature Stability Retention Suggested Mode\",\n );\n console.log(` ${\"─\".repeat(74)}`);\n for (const d of domains) {\n console.log(\n ` ${d.domain.padEnd(17)} ${String(d.totalCards).padEnd(6)} ${String(d.matureCards).padEnd(7)} ${String(d.avgStability).padEnd(10)} ${(d.retentionRate * 100).toFixed(1).padStart(5)}% ${d.suggestedMode}`,\n );\n }\n }\n });\n });\n","/**\n * `zam token` — Token management subcommand group.\n */\n\nimport { Command } from \"commander\";\nimport type { BloomLevel, SymbiosisMode } from \"../../kernel/index.js\";\nimport {\n addPrerequisite,\n createToken,\n deleteToken,\n deprecateToken,\n findTokens,\n generateConceptFreeCue,\n getCard,\n getDependents,\n getPrerequisites,\n getTokenBySlug,\n getTokenDeleteImpact,\n listTokens,\n updateToken,\n} from \"../../kernel/index.js\";\nimport { resolveUser } from \"./resolve-user.js\";\nimport { jsonOut, withDb } from \"./shared/db.js\";\n\nexport const tokenCommand = new Command(\"token\").description(\n \"Manage knowledge tokens\",\n);\n\n// ── zam token register ────────────────────────────────────────────────────\n\ntokenCommand\n .command(\"register\")\n .description(\"Register a new knowledge token\")\n .requiredOption(\"--slug <slug>\", \"Unique token slug\")\n .requiredOption(\"--concept <concept>\", \"Concept description\")\n .option(\"--domain <domain>\", \"Knowledge domain\", \"\")\n .option(\"--bloom <level>\", \"Bloom taxonomy level (1-5)\", \"1\")\n .option(\"--source-link <link>\", \"Source file path or reference URL\", \"\")\n .option(\"--question <question>\", \"Specific question prompt for recall\", \"\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (opts) => {\n await withDb(async (db) => {\n // Token creation is the frontier model's job: the agent (Claude Code,\n // Copilot / Antigravity CLI, …) decomposes the concept into atomic units\n // and may pass an explicit --question. The local LLM is deliberately NOT\n // called here — it is reserved for REVIEW time, where it rephrases the\n // question freshly each session so the learner never memorizes a fixed\n // \"exact input → exact output\" pair (see ensureHighQualityQuestion()).\n let question: string | null = opts.question || null;\n if (!question) {\n question = generateConceptFreeCue(\n Number(opts.bloom) as BloomLevel,\n opts.slug,\n opts.domain,\n );\n }\n\n const token = await createToken(db, {\n slug: opts.slug,\n concept: opts.concept,\n domain: opts.domain,\n bloom_level: Number(opts.bloom) as BloomLevel,\n source_link: opts.sourceLink || null,\n question,\n });\n\n if (opts.json) {\n console.log(JSON.stringify(token, null, 2));\n } else {\n console.log(`Registered token: ${token.slug} (${token.id})`);\n console.log(` Concept: ${token.concept}`);\n console.log(` Domain: ${token.domain || \"(none)\"}`);\n console.log(` Bloom: ${token.bloom_level}`);\n console.log(` Question: ${token.question}`);\n if (token.source_link) {\n console.log(` Source: ${token.source_link}`);\n }\n }\n });\n });\n\n// ── zam token find ────────────────────────────────────────────────────────\n\ntokenCommand\n .command(\"find\")\n .description(\"Fuzzy search for tokens\")\n .requiredOption(\"--query <query>\", \"Search query\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (opts) => {\n await withDb(async (db) => {\n const results = await findTokens(db, opts.query);\n\n if (opts.json) {\n console.log(JSON.stringify(results, null, 2));\n return;\n }\n\n if (results.length === 0) {\n console.log(\"No tokens found.\");\n return;\n }\n\n console.log(`Found ${results.length} token(s):\\n`);\n console.log(\n \"Score Slug Concept Domain Bloom\",\n );\n console.log(\"─\".repeat(90));\n for (const t of results) {\n console.log(\n `${String(t.score).padEnd(6)} ${t.slug.padEnd(21)} ${t.concept.slice(0, 31).padEnd(31)} ${(t.domain || \"-\").padEnd(11)} ${t.bloom_level}`,\n );\n }\n });\n });\n\n// ── zam token list ────────────────────────────────────────────────────────\n\ntokenCommand\n .command(\"list\")\n .description(\"List all tokens\")\n .option(\"--domain <domain>\", \"Filter by domain\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (opts) => {\n await withDb(async (db) => {\n const tokens = await listTokens(\n db,\n opts.domain ? { domain: opts.domain } : undefined,\n );\n\n if (opts.json) {\n console.log(JSON.stringify(tokens, null, 2));\n return;\n }\n\n if (tokens.length === 0) {\n console.log(\"No tokens registered.\");\n return;\n }\n\n console.log(\n \"Slug Concept Domain Bloom\",\n );\n console.log(\"─\".repeat(80));\n for (const t of tokens) {\n console.log(\n `${t.slug.padEnd(21)} ${t.concept.slice(0, 31).padEnd(31)} ${(t.domain || \"-\").padEnd(11)} ${t.bloom_level}`,\n );\n }\n console.log(`\\n${tokens.length} token(s) total.`);\n });\n });\n\n// ── zam token edit ────────────────────────────────────────────────────────\n\ntokenCommand\n .command(\"edit\")\n .description(\"Edit a token's mutable fields\")\n .requiredOption(\"--slug <slug>\", \"Token slug\")\n .option(\"--concept <concept>\", \"Updated concept text\")\n .option(\"--domain <domain>\", \"Updated domain (blank allowed)\")\n .option(\"--bloom <level>\", \"Updated Bloom taxonomy level (1-5)\")\n .option(\"--context <context>\", \"Updated context (blank allowed)\")\n .option(\n \"--mode <mode>\",\n \"Updated symbiosis mode: shadowing | copilot | autonomy | none\",\n )\n .option(\n \"--source-link <link>\",\n \"Updated source file path or reference URL (blank allowed)\",\n )\n .option(\"--question <question>\", \"Updated question text (blank allowed)\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (opts) => {\n await withDb(async (db) => {\n const updates: {\n concept?: string;\n domain?: string;\n bloom_level?: BloomLevel;\n context?: string;\n symbiosis_mode?: SymbiosisMode | null;\n source_link?: string | null;\n question?: string | null;\n } = {};\n\n if (opts.concept !== undefined) updates.concept = opts.concept;\n if (opts.domain !== undefined) updates.domain = opts.domain;\n if (opts.bloom !== undefined)\n updates.bloom_level = Number(opts.bloom) as BloomLevel;\n if (opts.context !== undefined) updates.context = opts.context;\n if (opts.sourceLink !== undefined) {\n updates.source_link = opts.sourceLink === \"\" ? null : opts.sourceLink;\n }\n if (opts.question !== undefined) {\n updates.question = opts.question === \"\" ? null : opts.question;\n }\n if (opts.mode !== undefined) {\n const validModes = [\"shadowing\", \"copilot\", \"autonomy\", \"none\"];\n if (!validModes.includes(opts.mode)) {\n console.error(`Invalid --mode: ${opts.mode}`);\n process.exit(1);\n }\n updates.symbiosis_mode =\n opts.mode === \"none\" ? null : (opts.mode as SymbiosisMode);\n }\n\n const token = await updateToken(db, opts.slug, updates);\n\n if (opts.json) {\n jsonOut(token);\n return;\n }\n\n console.log(`Updated token: ${token.slug}`);\n console.log(` Concept: ${token.concept}`);\n console.log(` Domain: ${token.domain || \"(none)\"}`);\n console.log(` Bloom: ${token.bloom_level}`);\n console.log(` Question: ${token.question || \"(none)\"}`);\n console.log(` Context: ${token.context || \"(none)\"}`);\n console.log(` Mode: ${token.symbiosis_mode ?? \"none\"}`);\n console.log(` Source: ${token.source_link || \"(none)\"}`);\n });\n });\n\n// ── zam token prereq ─────────────────────────────────────────────────────\n\ntokenCommand\n .command(\"prereq\")\n .description(\"Add a prerequisite edge between tokens\")\n .requiredOption(\"--token <slug>\", \"Token that requires a prerequisite\")\n .requiredOption(\"--requires <slug>\", \"Required prerequisite token\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (opts) => {\n await withDb(async (db) => {\n const token = await getTokenBySlug(db, opts.token);\n if (!token) {\n console.error(`Token not found: ${opts.token}`);\n process.exit(1);\n }\n\n const requires = await getTokenBySlug(db, opts.requires);\n if (!requires) {\n console.error(`Prerequisite token not found: ${opts.requires}`);\n process.exit(1);\n }\n\n await addPrerequisite(db, token.id, requires.id);\n\n if (opts.json) {\n console.log(\n JSON.stringify(\n { token: opts.token, requires: opts.requires },\n null,\n 2,\n ),\n );\n } else {\n console.log(\n `Added prerequisite: ${opts.token} requires ${opts.requires}`,\n );\n }\n });\n });\n\n// ── zam token deprecate ───────────────────────────────────────────────────\n\ntokenCommand\n .command(\"deprecate\")\n .description(\n \"Mark a token as deprecated (excluded from reviews, not deleted)\",\n )\n .requiredOption(\"--slug <slug>\", \"Token slug to deprecate\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (opts) => {\n await withDb(async (db) => {\n const token = await deprecateToken(db, opts.slug);\n\n if (opts.json) {\n console.log(JSON.stringify(token, null, 2));\n } else {\n console.log(`Deprecated: ${token.slug}`);\n console.log(` Concept: ${token.concept}`);\n console.log(` At: ${token.deprecated_at}`);\n }\n });\n });\n\n// ── zam token delete ──────────────────────────────────────────────────────\n\ntokenCommand\n .command(\"delete\")\n .description(\"Hard-delete a token and its dependent learning data\")\n .requiredOption(\"--slug <slug>\", \"Token slug to delete\")\n .option(\"--force\", \"Actually delete the token\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (opts) => {\n await withDb(async (db) => {\n const impact = await getTokenDeleteImpact(db, opts.slug);\n\n if (!opts.force) {\n const preview = {\n slug: opts.slug,\n deleted: false,\n requiresForce: true,\n impact,\n };\n\n if (opts.json) {\n jsonOut(preview);\n return;\n }\n\n console.log(`Delete preview for ${opts.slug}:`);\n console.log(` Cards: ${impact.cards}`);\n console.log(` Review logs: ${impact.review_logs}`);\n console.log(\n ` Prereq edges from it: ${impact.prerequisite_edges_from_token}`,\n );\n console.log(\n ` Prereq edges to it: ${impact.prerequisite_edges_to_token}`,\n );\n console.log(` Session steps: ${impact.session_steps}`);\n console.log(` Sessions touched: ${impact.sessions_touched}`);\n console.log(` Agent skills updated: ${impact.agent_skills}`);\n console.log(\"\\nRe-run with --force to delete.\");\n return;\n }\n\n const result = await deleteToken(db, opts.slug);\n\n if (opts.json) {\n jsonOut({\n slug: result.token.slug,\n deleted: true,\n impact: result.impact,\n });\n return;\n }\n\n console.log(`Deleted token: ${result.token.slug}`);\n console.log(` Cards removed: ${result.impact.cards}`);\n console.log(` Review logs removed: ${result.impact.review_logs}`);\n console.log(` Session steps removed: ${result.impact.session_steps}`);\n console.log(` Agent skills updated: ${result.impact.agent_skills}`);\n });\n });\n\n// ── zam token status ─────────────────────────────────────────────────────\n\ntokenCommand\n .command(\"status\")\n .description(\"Show full status of a token for a user\")\n .requiredOption(\"--token <slug>\", \"Token slug\")\n .option(\"--user <id>\", \"User ID (default: whoami)\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (opts) => {\n await withDb(async (db) => {\n const userId = await resolveUser(opts, db);\n const token = await getTokenBySlug(db, opts.token);\n if (!token) {\n console.error(`Token not found: ${opts.token}`);\n process.exit(1);\n }\n\n const card = await getCard(db, token.id, userId);\n const prereqs = await getPrerequisites(db, token.id);\n const dependents = await getDependents(db, token.id);\n\n const status = {\n token,\n card: card ?? null,\n prerequisites: prereqs,\n dependents,\n };\n\n if (opts.json) {\n console.log(JSON.stringify(status, null, 2));\n return;\n }\n\n console.log(`Token: ${token.slug} (${token.id})`);\n console.log(` Concept: ${token.concept}`);\n console.log(` Question: ${token.question || \"(none)\"}`);\n console.log(` Domain: ${token.domain || \"(none)\"}`);\n console.log(` Bloom: ${token.bloom_level}`);\n if (token.source_link) {\n console.log(` Source: ${token.source_link}`);\n }\n console.log();\n\n if (card) {\n console.log(\"Card status:\");\n console.log(` State: ${card.state}`);\n console.log(` Due at: ${card.due_at}`);\n console.log(` Stability: ${card.stability}`);\n console.log(` Difficulty: ${card.difficulty}`);\n console.log(` Reps: ${card.reps}`);\n console.log(` Lapses: ${card.lapses}`);\n console.log(` Blocked: ${card.blocked ? \"Yes\" : \"No\"}`);\n } else {\n console.log(\"No card exists for this user yet.\");\n }\n\n console.log();\n if (prereqs.length > 0) {\n console.log(\"Prerequisites:\");\n for (const p of prereqs) {\n console.log(` - ${p.slug}: ${p.concept} (bloom ${p.bloom_level})`);\n }\n } else {\n console.log(\"No prerequisites.\");\n }\n\n if (dependents.length > 0) {\n console.log(\"\\nDependents:\");\n for (const d of dependents) {\n console.log(` - ${d.slug}: ${d.concept} (bloom ${d.bloom_level})`);\n }\n }\n });\n });\n","/**\n * `zam ui` — one-word launcher for the ZAM Desktop GUI (Tauri Studio).\n *\n * The desktop app is a Tauri shell that re-uses the compiled CLI bridge\n * (dist/cli/index.js), so it needs:\n * - a built CLI (npm run build at the repo root), and\n * - either a previously built native binary, or the Rust toolchain to\n * compile one.\n *\n * Usage:\n * zam ui launch the GUI (built binary if present, else guide)\n * zam ui --dev run in hot-reload dev mode (needs Rust)\n * zam ui --build build the native installer (needs Rust, one-time)\n * zam ui --shortcut create Desktop + Start-menu shortcuts to the GUI\n */\n\nimport { type SpawnSyncOptions, spawn, spawnSync } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { Command } from \"commander\";\nimport { hasCommand } from \"../../kernel/index.js\";\n\nconst C = {\n reset: \"\\x1b[0m\",\n red: \"\\x1b[31m\",\n green: \"\\x1b[32m\",\n yellow: \"\\x1b[33m\",\n cyan: \"\\x1b[36m\",\n dim: \"\\x1b[2m\",\n};\n\n/** Walk up from cwd and from this module to find the repo's `desktop/` dir. */\nfunction findDesktopDir(): string | null {\n const starts = [process.cwd(), dirname(fileURLToPath(import.meta.url))];\n for (const start of starts) {\n let dir = start;\n for (let i = 0; i < 10; i++) {\n if (existsSync(join(dir, \"desktop\", \"src-tauri\", \"tauri.conf.json\"))) {\n return join(dir, \"desktop\");\n }\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n }\n return null;\n}\n\n/** Locate a previously built native binary, if any. */\nfunction findBuiltApp(desktopDir: string): string | null {\n const releaseDir = join(desktopDir, \"src-tauri\", \"target\", \"release\");\n if (process.platform === \"win32\") {\n for (const name of [\"ZAM.exe\", \"zam.exe\", \"zam-desktop.exe\"]) {\n const p = join(releaseDir, name);\n if (existsSync(p)) return p;\n }\n } else if (process.platform === \"darwin\") {\n const app = join(releaseDir, \"bundle\", \"macos\", \"ZAM.app\");\n if (existsSync(app)) return app;\n } else {\n for (const name of [\"zam\", \"ZAM\", \"zam-desktop\"]) {\n const p = join(releaseDir, name);\n if (existsSync(p)) return p;\n }\n }\n return null;\n}\n\n/** Locate an app installed by a released ZAM desktop installer. */\nfunction findInstalledApp(): string | null {\n const candidates =\n process.platform === \"win32\"\n ? [\n process.env.LOCALAPPDATA &&\n join(process.env.LOCALAPPDATA, \"Programs\", \"ZAM\", \"ZAM.exe\"),\n process.env.ProgramFiles &&\n join(process.env.ProgramFiles, \"ZAM\", \"ZAM.exe\"),\n process.env[\"ProgramFiles(x86)\"] &&\n join(process.env[\"ProgramFiles(x86)\"], \"ZAM\", \"ZAM.exe\"),\n ]\n : process.platform === \"darwin\"\n ? [\"/Applications/ZAM.app\", join(homedir(), \"Applications\", \"ZAM.app\")]\n : [\"/opt/ZAM/zam\", \"/usr/bin/zam-desktop\"];\n\n return (\n candidates.find((candidate) => candidate && existsSync(candidate)) || null\n );\n}\n\n/** npm is npm.cmd on Windows, so child processes need a shell there. */\nfunction runNpm(args: string[], opts: SpawnSyncOptions): number {\n const res = spawnSync(\"npm\", args, {\n stdio: \"inherit\",\n shell: process.platform === \"win32\",\n ...opts,\n });\n return res.status ?? 1;\n}\n\nfunction ensureDesktopDeps(desktopDir: string): boolean {\n if (existsSync(join(desktopDir, \"node_modules\"))) return true;\n console.log(\n `${C.cyan}Installing desktop dependencies (one-time)...${C.reset}`,\n );\n return runNpm([\"install\"], { cwd: desktopDir }) === 0;\n}\n\nfunction prepareDesktopBridge(repoRoot: string): boolean {\n console.log(`${C.cyan}Preparing self-contained desktop bridge...${C.reset}`);\n return (\n runNpm([\"run\", \"desktop:prepare\", \"--\", \"--bundle-node\"], {\n cwd: repoRoot,\n }) === 0\n );\n}\n\nfunction requireRust(): boolean {\n if (hasCommand(\"cargo\")) return true;\n console.error(\n `${C.red}✗ The desktop GUI needs the Rust toolchain to compile.${C.reset}`,\n );\n console.error(\" Install it once, then re-run this command:\");\n console.error(\n ` ${C.cyan}winget install Rustlang.Rustup${C.reset} (or https://rustup.rs)`,\n );\n return false;\n}\n\n/**\n * On Windows the default MSVC Rust target needs the Visual Studio C++ linker\n * (link.exe), which rustup does NOT install. Detect it via vswhere so we fail\n * with guidance up front instead of after minutes of compiling.\n */\nfunction hasMsvcBuildTools(): boolean {\n if (process.platform !== \"win32\") return true;\n const pf86 = process.env[\"ProgramFiles(x86)\"] || \"C:\\\\Program Files (x86)\";\n const vswhere = join(\n pf86,\n \"Microsoft Visual Studio\",\n \"Installer\",\n \"vswhere.exe\",\n );\n if (!existsSync(vswhere)) return false;\n const res = spawnSync(\n vswhere,\n [\n \"-latest\",\n \"-products\",\n \"*\",\n \"-requires\",\n \"Microsoft.VisualStudio.Component.VC.Tools.x86.x64\",\n \"-property\",\n \"installationPath\",\n ],\n { encoding: \"utf8\" },\n );\n return (res.stdout ?? \"\").trim().length > 0;\n}\n\nfunction requireMsvcOnWindows(): boolean {\n if (hasMsvcBuildTools()) return true;\n console.error(\n `${C.red}✗ The MSVC C++ linker (link.exe) is missing.${C.reset}`,\n );\n console.error(\n \" Rust on Windows needs the Visual Studio Build Tools with the C++ workload\",\n );\n console.error(\" (rustup does not include it). Install it once (~a few GB),\");\n console.error(\" then open a NEW terminal and retry:\");\n console.error(\n ` ${C.cyan}winget install --id Microsoft.VisualStudio.2022.BuildTools -e --override \"--quiet --wait --add Microsoft.VisualStudio.Workload.VCTools --includeRecommended\"${C.reset}`,\n );\n return false;\n}\n\nfunction warnIfCliMissing(repoRoot: string): void {\n if (!existsSync(join(repoRoot, \"dist\", \"cli\", \"index.js\"))) {\n console.warn(\n `${C.yellow}⚠ CLI build not found (dist/cli/index.js). The GUI bridge needs it — run 'npm run build' at the repo root.${C.reset}`,\n );\n }\n}\n\nfunction launchApp(appPath: string, workingDir: string): void {\n console.log(`${C.green}✓ Launching ZAM Desktop...${C.reset}`);\n if (process.platform === \"darwin\" && appPath.endsWith(\".app\")) {\n spawn(\"open\", [appPath], {\n cwd: workingDir,\n detached: true,\n stdio: \"ignore\",\n }).unref();\n } else {\n spawn(appPath, [], {\n cwd: workingDir,\n detached: true,\n stdio: \"ignore\",\n windowsHide: true,\n }).unref();\n }\n}\n\nfunction createShortcuts(appPath: string, repoRoot: string): void {\n if (process.platform !== \"win32\") {\n console.error(\n `${C.red}✗ --shortcut is currently implemented for Windows only.${C.reset}`,\n );\n console.error(\n \" On macOS drag ZAM.app to the Dock; on Linux create a .desktop entry.\",\n );\n return;\n }\n // WScript.Shell creates a .lnk on the Desktop and in the Start menu.\n const ps = [\n \"$ws = New-Object -ComObject WScript.Shell\",\n \"foreach ($dir in @([Environment]::GetFolderPath('Desktop'), [Environment]::GetFolderPath('Programs'))) {\",\n \" $lnk = $ws.CreateShortcut((Join-Path $dir 'ZAM.lnk'))\",\n ` $lnk.TargetPath = '${appPath}'`,\n ` $lnk.WorkingDirectory = '${repoRoot}'`,\n ` $lnk.IconLocation = '${appPath},0'`,\n \" $lnk.Description = 'ZAM Active-Recall Studio'\",\n \" $lnk.Save()\",\n \"}\",\n ].join(\"\\n\");\n const res = spawnSync(\n \"powershell\",\n [\"-NoProfile\", \"-ExecutionPolicy\", \"Bypass\", \"-Command\", ps],\n { stdio: \"inherit\" },\n );\n if (res.status === 0) {\n console.log(\n `${C.green}✓ Created 'ZAM' shortcuts on your Desktop and in the Start menu.${C.reset}`,\n );\n } else {\n console.error(`${C.red}✗ Could not create shortcuts.${C.reset}`);\n }\n}\n\nexport const uiCommand = new Command(\"ui\")\n .description(\"Launch the ZAM Desktop GUI (Active-Recall Studio)\")\n .option(\"--dev\", \"Run in hot-reload development mode (needs Rust)\")\n .option(\n \"--build\",\n \"Build the native installer for your OS (needs Rust, one-time)\",\n )\n .option(\"--shortcut\", \"Create Desktop + Start-menu shortcuts to the GUI\")\n .action((opts) => {\n const installedApp = findInstalledApp();\n if (!opts.dev && !opts.build && !opts.shortcut && installedApp) {\n launchApp(installedApp, homedir());\n return;\n }\n\n const desktopDir = findDesktopDir();\n if (!desktopDir) {\n console.error(\n `${C.red}✗ Could not find the desktop/ app. Run 'zam ui' from inside the ZAM repository.${C.reset}`,\n );\n process.exit(1);\n }\n const repoRoot = dirname(desktopDir);\n\n // --build: compile the native installer.\n if (opts.build) {\n if (!requireRust()) process.exit(1);\n if (!requireMsvcOnWindows()) process.exit(1);\n if (!ensureDesktopDeps(desktopDir)) process.exit(1);\n if (!prepareDesktopBridge(repoRoot)) process.exit(1);\n console.log(\n `${C.cyan}Building the native ZAM installer (this takes a few minutes)...${C.reset}`,\n );\n const code = runNpm([\"run\", \"tauri\", \"build\"], { cwd: desktopDir });\n if (code === 0) {\n const bundle = join(\n desktopDir,\n \"src-tauri\",\n \"target\",\n \"release\",\n \"bundle\",\n );\n console.log(\n `\\n${C.green}✓ Done. Installer is in:${C.reset}\\n ${bundle}`,\n );\n console.log(\n `${C.dim}Run that installer once — it adds ZAM to the Start menu and Desktop automatically.${C.reset}`,\n );\n console.log(\n `${C.dim}The installer includes the CLI bridge and Node runtime.${C.reset}`,\n );\n }\n process.exit(code);\n }\n\n // --dev: hot-reload development mode.\n if (opts.dev) {\n if (!requireRust()) process.exit(1);\n if (!requireMsvcOnWindows()) process.exit(1);\n if (!ensureDesktopDeps(desktopDir)) process.exit(1);\n warnIfCliMissing(repoRoot);\n console.log(\n `${C.cyan}Starting ZAM Desktop in dev mode (Ctrl+C to stop)...${C.reset}`,\n );\n process.exit(runNpm([\"run\", \"tauri\", \"dev\"], { cwd: desktopDir }));\n }\n\n const builtApp = findBuiltApp(desktopDir);\n\n // --shortcut: needs a built binary to point at.\n if (opts.shortcut) {\n const shortcutTarget = installedApp || builtApp;\n if (!shortcutTarget) {\n console.error(\n `${C.red}✗ No built app yet. Build it first:${C.reset} ${C.cyan}zam ui --build${C.reset}`,\n );\n process.exit(1);\n }\n createShortcuts(shortcutTarget, dirname(shortcutTarget));\n return;\n }\n\n // Default: launch the built app, or guide the user to get one.\n if (builtApp) {\n launchApp(builtApp, repoRoot);\n return;\n }\n\n console.log(\n `${C.yellow}The ZAM Desktop GUI hasn't been built yet.${C.reset}\\n`,\n );\n if (hasCommand(\"cargo\")) {\n console.log(\"Pick one:\");\n console.log(\n ` ${C.cyan}zam ui --build${C.reset} Build a native installer (Start-menu + Desktop entry)`,\n );\n console.log(\n ` ${C.cyan}zam ui --dev${C.reset} Just run it now in dev mode`,\n );\n } else {\n console.log(\"To get a clickable Start-menu app, do this once:\");\n console.log(\n ` 1. Install Rust: ${C.cyan}winget install Rustlang.Rustup${C.reset}`,\n );\n console.log(` 2. Build the app: ${C.cyan}zam ui --build${C.reset}`);\n console.log(\n ` 3. Run the installer it prints — ZAM then lives in your Start menu.`,\n );\n console.log(\n `\\n${C.dim}After that, 'zam ui' launches it directly.${C.reset}`,\n );\n }\n });\n","/**\n * `zam update check` — has a newer ZAM been released, and how should this\n * install update? (Increment 12, Phase 5.)\n *\n * The decision (self-update vs defer to a package manager vs inform a developer\n * install) lives in the kernel; this command supplies the current version, the\n * latest version (fetched from GitHub releases unless `--latest` is given), and\n * the detected install channel.\n */\n\nimport { readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { Command } from \"commander\";\nimport {\n decideUpdate,\n getInstallChannel,\n type InstallChannel,\n type UpdateDecision,\n} from \"../../kernel/index.js\";\n\nconst GITHUB_REPO = \"zam-os/zam\";\nconst CHANNELS: InstallChannel[] = [\n \"developer\",\n \"direct\",\n \"winget\",\n \"homebrew\",\n];\n\nconst C = {\n reset: \"\\x1b[0m\",\n bold: \"\\x1b[1m\",\n cyan: \"\\x1b[36m\",\n dim: \"\\x1b[2m\",\n green: \"\\x1b[32m\",\n yellow: \"\\x1b[33m\",\n};\n\n/** Read this build's version from the nearest package.json. */\nfunction currentVersion(): string {\n const here = dirname(fileURLToPath(import.meta.url));\n for (const up of [\"..\", \"../..\", \"../../..\"]) {\n try {\n const pkg = JSON.parse(\n readFileSync(join(here, up, \"package.json\"), \"utf-8\"),\n ) as { version?: string };\n if (pkg.version) return pkg.version;\n } catch {\n // try the next candidate\n }\n }\n return \"0.0.0\";\n}\n\nasync function fetchLatestVersion(repo: string): Promise<string> {\n const res = await fetch(\n `https://api.github.com/repos/${repo}/releases/latest`,\n {\n headers: {\n Accept: \"application/vnd.github+json\",\n \"User-Agent\": \"zam-cli\",\n },\n },\n );\n if (!res.ok) {\n throw new Error(\n `Could not reach the release server (HTTP ${res.status}). ` +\n \"Pass --latest <version> to check offline.\",\n );\n }\n const data = (await res.json()) as { tag_name?: string };\n if (!data.tag_name) throw new Error(\"No published release found yet.\");\n return data.tag_name;\n}\n\nfunction render(decision: UpdateDecision): void {\n if (!decision.updateAvailable) {\n console.log(\n `${C.green}✓${C.reset} ZAM is up to date (${C.cyan}${decision.currentVersion}${C.reset}).`,\n );\n return;\n }\n\n console.log(\n `${C.yellow}↑${C.reset} ${C.bold}Update available${C.reset}: ` +\n `${C.dim}${decision.currentVersion}${C.reset} → ${C.cyan}${decision.latestVersion}${C.reset}`,\n );\n console.log(` ${decision.reason}`);\n if (decision.action === \"run-command\" || decision.action === \"inform\") {\n console.log(` Run: ${C.cyan}${decision.command}${C.reset}`);\n } else if (decision.action === \"self-update\") {\n console.log(\n ` ${C.dim}The desktop app can apply this update for you.${C.reset}`,\n );\n }\n}\n\nconst checkCmd = new Command(\"check\")\n .description(\"Check whether a newer ZAM has been released\")\n .option(\n \"--latest <version>\",\n \"Compare against this version instead of fetching\",\n )\n .option(\"--channel <channel>\", \"Override the detected install channel\")\n .option(\"--json\", \"Output as JSON\")\n .action(\n async (opts: { latest?: string; channel?: string; json?: boolean }) => {\n try {\n if (\n opts.channel &&\n !CHANNELS.includes(opts.channel as InstallChannel)\n ) {\n console.error(\n `Invalid --channel: ${opts.channel}. Use ${CHANNELS.join(\", \")}.`,\n );\n process.exit(1);\n }\n\n const current = currentVersion();\n const latest = opts.latest ?? (await fetchLatestVersion(GITHUB_REPO));\n const channel = (opts.channel as InstallChannel) ?? getInstallChannel();\n\n const decision = decideUpdate({\n currentVersion: current,\n latestVersion: latest,\n channel,\n });\n\n if (opts.json) {\n console.log(JSON.stringify(decision, null, 2));\n return;\n }\n render(decision);\n } catch (err) {\n console.error(\"Error:\", (err as Error).message);\n process.exit(1);\n }\n },\n );\n\nexport const updateCommand = new Command(\"update\")\n .description(\"Check for ZAM updates\")\n .addCommand(checkCmd);\n","/**\n * `zam whoami` — Manage default user identity.\n */\n\nimport { Command } from \"commander\";\nimport { deleteSetting, getSetting, setSetting } from \"../../kernel/index.js\";\nimport { withDb } from \"./shared/db.js\";\n\nexport const whoamiCommand = new Command(\"whoami\")\n .description(\"Show or set the default user identity\")\n .option(\"--set <id>\", \"Set the default user ID\")\n .option(\"--clear\", \"Remove the default user ID\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (opts) => {\n await withDb(async (db) => {\n if (opts.set) {\n await setSetting(db, \"user.id\", opts.set);\n if (opts.json) {\n console.log(JSON.stringify({ userId: opts.set }));\n } else {\n console.log(`Default user set to: ${opts.set}`);\n }\n return;\n }\n\n if (opts.clear) {\n const deleted = await deleteSetting(db, \"user.id\");\n if (opts.json) {\n console.log(JSON.stringify({ userId: null, cleared: deleted }));\n } else if (deleted) {\n console.log(\"Default user cleared.\");\n } else {\n console.log(\"No default user was set.\");\n }\n return;\n }\n\n const userId = await getSetting(db, \"user.id\");\n if (opts.json) {\n console.log(JSON.stringify({ userId: userId ?? null }));\n return;\n }\n\n if (userId) {\n console.log(userId);\n } else {\n console.log(\"No default user set. Use: zam whoami --set <id>\");\n }\n });\n });\n","/**\n * `zam workspace` — Workspace management commands.\n *\n * `zam workspace publish` initializes a Git repository inside the local sandbox\n * workspace and pushes it to GitHub, establishing a secure version-controlled backup\n * and change-managed team workflow.\n */\n\nimport { execSync } from \"node:child_process\";\nimport { existsSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { confirm, input } from \"@inquirer/prompts\";\nimport { Command } from \"commander\";\nimport { getSetting, hasCommand, openDatabase } from \"../../kernel/index.js\";\n\n/**\n * Execute a shell command inside a specific directory.\n */\nfunction runGit(cwd: string, args: string): string {\n try {\n return execSync(`git ${args}`, {\n cwd,\n stdio: \"pipe\",\n encoding: \"utf8\",\n }).trim();\n } catch (err) {\n throw new Error(`Git command failed: ${(err as Error).message}`);\n }\n}\n\nexport const workspaceCommand = new Command(\"workspace\").description(\n \"Manage your ZAM learning workspace\",\n);\n\nworkspaceCommand\n .command(\"publish\")\n .description(\"Publish your local workspace sandbox to GitHub\")\n .action(async () => {\n let db: Awaited<ReturnType<typeof openDatabase>> | undefined;\n let workspaceDir = \"\";\n\n try {\n db = await openDatabase();\n workspaceDir = (await getSetting(db, \"personal.workspace_dir\")) || \"\";\n await db.close();\n } catch {\n // Fallback if DB doesn't exist\n await db?.close();\n }\n\n if (!workspaceDir) {\n console.error(\n \"\\x1b[31m✗ No active workspace configured. Please run `zam init` first.\\x1b[0m\",\n );\n process.exit(1);\n }\n\n if (!existsSync(workspaceDir)) {\n console.error(\n `\\x1b[31m✗ Workspace directory does not exist: ${workspaceDir}\\x1b[0m`,\n );\n process.exit(1);\n }\n\n console.log(`\\nActive workspace: \\x1b[36m${workspaceDir}\\x1b[0m`);\n\n // ── Check Git command ────────────────────────────────────────────────────\n if (!hasCommand(\"git\")) {\n console.error(\n \"\\x1b[31m✗ Git command was not found on this system. Please install Git first.\\x1b[0m\",\n );\n process.exit(1);\n }\n\n // ── Setup .gitignore ─────────────────────────────────────────────────────\n const gitignorePath = join(workspaceDir, \".gitignore\");\n if (!existsSync(gitignorePath)) {\n writeFileSync(\n gitignorePath,\n \"node_modules/\\n.agent/\\n.agents/\\n.claude/\\n.gemini/\\n.goose/\\n*.log\\n\",\n \"utf8\",\n );\n }\n\n // ── Initialize Local Git Repo ────────────────────────────────────────────\n const hasGitRepo = existsSync(join(workspaceDir, \".git\"));\n if (!hasGitRepo) {\n console.log(\"Initializing local Git repository...\");\n runGit(workspaceDir, \"init -b main\");\n runGit(workspaceDir, \"add .\");\n runGit(\n workspaceDir,\n 'commit -m \"chore: initial workspace sandbox bootstrap\"',\n );\n console.log(\"\\x1b[32m✓ Local Git repository initialized.\\x1b[0m\");\n } else {\n console.log(\"Git repository is already initialized.\");\n }\n\n // ── GitHub Publishing options ────────────────────────────────────────────\n const repoName = await input({\n message: \"Choose a name for your GitHub repository:\",\n default: \"zam-personal\",\n });\n\n const isPrivate = await confirm({\n message: \"Should the repository be private?\",\n default: true,\n });\n\n const repoVisibility = isPrivate ? \"--private\" : \"--public\";\n\n // ── Method A: Using GitHub CLI (gh) ──────────────────────────────────────\n if (hasCommand(\"gh\")) {\n console.log(\"GitHub CLI detected! Automating repository creation...\");\n const proceedGh = await confirm({\n message:\n \"Would you like ZAM to create the repository using the GitHub CLI?\",\n default: true,\n });\n\n if (proceedGh) {\n try {\n console.log(`Creating GitHub repository ${repoName}...`);\n execSync(\n `gh repo create ${repoName} ${repoVisibility} --source=. --push`,\n {\n cwd: workspaceDir,\n stdio: \"inherit\",\n },\n );\n console.log(\n \"\\n\\x1b[32m✓ Successfully published workspace to GitHub!\\x1b[0m\",\n );\n process.exit(0);\n } catch (err) {\n console.warn(\n `\\x1b[33m⚠ GitHub CLI creation failed: ${(err as Error).message}\\x1b[0m`,\n );\n }\n }\n }\n\n // ── Method B: Manual Git setup instructions ──────────────────────────────\n console.log(\n \"\\n\\x1b[1mPlease create the repository manually on GitHub:\\x1b[0m\",\n );\n console.log(\" 1. Go to https://github.com/new\");\n console.log(` 2. Name it exactly: \\x1b[36m${repoName}\\x1b[0m`);\n console.log(\n ` 3. Choose \\x1b[36m${isPrivate ? \"Private\" : \"Public\"}\\x1b[0m`,\n );\n console.log(\n \" 4. Do NOT initialize it with README, .gitignore, or license\",\n );\n console.log(\" 5. Click 'Create repository'\\n\");\n\n const githubUrl = await input({\n message:\n \"Paste the repository Git URL (e.g. git@github.com:user/repo.git):\",\n });\n\n if (githubUrl) {\n try {\n console.log(\"Linking remote repository and pushing...\");\n // Check if origin already exists\n let hasOrigin = false;\n try {\n runGit(workspaceDir, \"remote get-url origin\");\n hasOrigin = true;\n } catch {}\n\n if (hasOrigin) {\n runGit(workspaceDir, `remote set-url origin ${githubUrl}`);\n } else {\n runGit(workspaceDir, `remote add origin ${githubUrl}`);\n }\n\n runGit(workspaceDir, \"push -u origin main\");\n console.log(\n \"\\x1b[32m✓ Successfully linked and pushed to GitHub!\\x1b[0m\",\n );\n } catch (err) {\n console.error(\n `\\x1b[31m✗ Push failed: ${(err as Error).message}\\x1b[0m`,\n );\n console.log(\n \"You can push manually later using: git push -u origin main\",\n );\n }\n }\n });\n"],"mappings":"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","names":["readFileSync","dirname","join","fileURLToPath","Command","existsSync","join","existsSync","mkdirSync","readFileSync","homedir","dirname","join","join","homedir","require","existsSync","readFileSync","db","dirname","mkdirSync","count","existsSync","readFileSync","writeFileSync","join","existsSync","join","readFileSync","t","input","writeFileSync","input","ulid","ulid","input","t","t","ulid","ulid","input","count","existsSync","mkdirSync","readFileSync","homedir","join","join","homedir","join","existsSync","mkdirSync","readFileSync","ulid","ulid","interval","dueAt","input","ulid","input","ulid","input","target","input","existsSync","readFileSync","dirname","join","anchorIndex","anchor","appendFileSync","existsSync","mkdirSync","readFileSync","writeFileSync","homedir","join","packageRoot","existsSync","mkdirSync","readFileSync","writeFileSync","homedir","dirname","join","existsSync","homedir","join","checkCmd","execSync","execSync","existsSync","resolve","resolve","input","currentVersion","existsSync","join","readdirSync","homedir","join","Command","existsSync","BLOOM_VERBS","input","existsSync","resolve","confirm","jsonOut","withDb","getReviewTarget","Command","join","homedir","readdirSync","t","appendFileSync","Command","Command","count","Command","Command","execSync","chmodSync","existsSync","writeFileSync","join","Command","installHook","join","existsSync","writeFileSync","chmodSync","Command","execSync","existsSync","mkdirSync","resolve","input","Command","resolve","Command","existsSync","tasks","tokens","t","mkdirSync","input","existsSync","mkdirSync","writeFileSync","homedir","join","input","Command","HOME","homedir","mkdirSync","join","existsSync","writeFileSync","Command","input","input","Command","BLOOM_VERBS","input","confirm","input","confirm","input","Command","input","execFileSync","execSync","writeFileSync","basename","join","Command","psSingleQuoted","basename","Command","execSync","join","writeFileSync","execFileSync","homedir","dirname","join","resolve","Command","C","join","homedir","Command","resolve","dirname","Command","Command","readFileSync","input","select","Command","Command","select","input","readFileSync","existsSync","Command","Command","existsSync","copyFileSync","existsSync","mkdirSync","writeFileSync","basename","dirname","join","fileURLToPath","Command","fileURLToPath","existsSync","join","mkdirSync","dirname","copyFileSync","basename","writeFileSync","Command","Command","Command","existsSync","mkdirSync","readFileSync","writeFileSync","homedir","dirname","join","Command","count","Command","join","homedir","dirname","existsSync","mkdirSync","writeFileSync","readFileSync","Command","Command","Command","Command","t","spawn","existsSync","homedir","dirname","join","fileURLToPath","Command","C","dirname","fileURLToPath","existsSync","join","homedir","spawn","Command","readFileSync","dirname","join","fileURLToPath","Command","C","dirname","fileURLToPath","pkg","readFileSync","join","render","Command","Command","Command","execSync","existsSync","writeFileSync","join","confirm","input","Command","execSync","Command","existsSync","join","writeFileSync","input","confirm","dirname","fileURLToPath","readFileSync","join","Command"]}