zam-core 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/cli/index.ts","../../src/cli/commands/init.ts","../../src/kernel/db/connection.ts","../../src/kernel/db/schema.ts","../../src/kernel/models/token.ts","../../src/kernel/models/prerequisite.ts","../../src/kernel/models/card.ts","../../src/kernel/models/review.ts","../../src/kernel/models/session.ts","../../src/kernel/models/agent-skill.ts","../../src/kernel/models/settings.ts","../../src/kernel/scheduler/fsrs.ts","../../src/kernel/scheduler/blocker.ts","../../src/kernel/scheduler/interleaver.ts","../../src/kernel/scheduler/queue.ts","../../src/kernel/recall/prompter.ts","../../src/kernel/recall/evaluator.ts","../../src/kernel/analytics/stats.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/goals/engine.ts","../../src/kernel/goals/parser.ts","../../src/kernel/connectors/azure-devops.ts","../../src/cli/commands/setup.ts","../../src/cli/commands/token.ts","../../src/cli/commands/resolve-user.ts","../../src/cli/commands/card.ts","../../src/cli/commands/session.ts","../../src/cli/commands/stats.ts","../../src/cli/commands/review.ts","../../src/cli/commands/bridge.ts","../../src/cli/commands/skill.ts","../../src/cli/commands/monitor.ts","../../src/cli/commands/settings.ts","../../src/cli/commands/whoami.ts","../../src/cli/commands/connector.ts","../../src/cli/commands/goal.ts"],"sourcesContent":["import { Command } from \"commander\";\r\nimport { initCommand } from \"./commands/init.js\";\r\nimport { setupCommand } from \"./commands/setup.js\";\r\nimport { tokenCommand } from \"./commands/token.js\";\r\nimport { cardCommand } from \"./commands/card.js\";\r\nimport { sessionCommand } from \"./commands/session.js\";\r\nimport { statsCommand } from \"./commands/stats.js\";\r\nimport { reviewCommand } from \"./commands/review.js\";\r\nimport { bridgeCommand } from \"./commands/bridge.js\";\r\nimport { skillCommand } from \"./commands/skill.js\";\r\nimport { monitorCommand } from \"./commands/monitor.js\";\r\nimport { settingsCommand } from \"./commands/settings.js\";\r\nimport { whoamiCommand } from \"./commands/whoami.js\";\r\nimport { connectorCommand } from \"./commands/connector.js\";\r\nimport { goalCommand } from \"./commands/goal.js\";\r\n\r\nconst program = new Command();\r\n\r\nprogram\r\n .name(\"zam\")\r\n .description(\r\n \"The Symbiotic Learning Kernel: Elevating Human Intelligence through AI Collaboration.\",\r\n )\r\n .version(\"0.3.0\");\r\n\r\nprogram.addCommand(initCommand);\r\nprogram.addCommand(setupCommand);\r\nprogram.addCommand(tokenCommand);\r\nprogram.addCommand(cardCommand);\r\nprogram.addCommand(sessionCommand);\r\nprogram.addCommand(statsCommand);\r\nprogram.addCommand(reviewCommand);\r\nprogram.addCommand(bridgeCommand);\r\nprogram.addCommand(skillCommand);\r\nprogram.addCommand(monitorCommand);\r\nprogram.addCommand(settingsCommand);\r\nprogram.addCommand(whoamiCommand);\r\nprogram.addCommand(connectorCommand);\r\nprogram.addCommand(goalCommand);\r\n\r\nprogram.parse();\r\n","/**\r\n * `zam init` — Initialize ~/.zam/ directory and database.\r\n */\r\n\r\nimport { Command } from \"commander\";\r\nimport { openDatabase, getDefaultDbPath } from \"../../kernel/index.js\";\r\n\r\nexport const initCommand = new Command(\"init\")\r\n .description(\"Initialize the ZAM database and config directory\")\r\n .action(() => {\r\n try {\r\n const dbPath = getDefaultDbPath();\r\n const db = openDatabase({ initialize: true });\r\n db.close();\r\n console.log(`Initialized ZAM database at ${dbPath}`);\r\n } catch (err) {\r\n console.error(\"Failed to initialize:\", (err as Error).message);\r\n process.exit(1);\r\n }\r\n });\r\n","import Database, { type Database as DatabaseType } from \"libsql\";\r\nimport { existsSync, mkdirSync } from \"node:fs\";\r\nimport { homedir } from \"node:os\";\r\nimport { dirname, join } from \"node:path\";\r\nimport { SCHEMA } from \"./schema.js\";\r\n\r\nconst DEFAULT_DB_DIR = join(homedir(), \".zam\");\r\nconst DEFAULT_DB_PATH = join(DEFAULT_DB_DIR, \"zam.db\");\r\n\r\nexport interface ConnectionOptions {\r\n /** Path to the SQLite database file. Defaults to ~/.zam/zam.db */\r\n dbPath?: string;\r\n /** If true, create the directory and run schema migrations on open */\r\n initialize?: boolean;\r\n /** Turso sync URL for cloud replication (e.g. libsql://db-name.turso.io) */\r\n syncUrl?: string;\r\n /** Turso auth token for cloud replication */\r\n authToken?: string;\r\n}\r\n\r\n/**\r\n * Open (or create) the ZAM database.\r\n * Uses WAL mode for concurrent access from AI CLI and user CLI.\r\n * When syncUrl is provided, enables embedded replica sync with Turso.\r\n */\r\nexport function openDatabase(options: ConnectionOptions = {}): DatabaseType {\r\n const dbPath = options.dbPath ?? DEFAULT_DB_PATH;\r\n\r\n if (options.initialize) {\r\n const dir = dirname(dbPath);\r\n if (!existsSync(dir)) {\r\n mkdirSync(dir, { recursive: true });\r\n }\r\n }\r\n\r\n // Build constructor options for libsql\r\n const dbOpts: Record<string, unknown> = {};\r\n if (options.syncUrl) {\r\n dbOpts.syncUrl = options.syncUrl;\r\n }\r\n if (options.authToken) {\r\n dbOpts.authToken = options.authToken;\r\n }\r\n\r\n const db = new Database(dbPath, dbOpts as Database.Options);\r\n\r\n // Enable WAL mode and foreign keys\r\n db.pragma(\"journal_mode = WAL\");\r\n db.pragma(\"foreign_keys = ON\");\r\n db.pragma(\"busy_timeout = 5000\");\r\n\r\n if (options.initialize) {\r\n db.exec(SCHEMA);\r\n }\r\n\r\n runMigrations(db);\r\n\r\n // Sync after migrations if cloud is configured\r\n if (options.syncUrl) {\r\n (db as unknown as { sync: () => void }).sync();\r\n }\r\n\r\n return db;\r\n}\r\n\r\n/**\r\n * Open the database with Turso cloud sync auto-detected from stored settings.\r\n * Reads turso.url and turso.token from user_config. If present, reopens\r\n * the database with embedded replica sync enabled.\r\n */\r\nexport function openDatabaseWithSync(options: Omit<ConnectionOptions, \"syncUrl\" | \"authToken\"> = {}): DatabaseType {\r\n // First open locally to read settings\r\n const db = openDatabase(options);\r\n const syncUrl = db.prepare(\"SELECT value FROM user_config WHERE key = ?\").get(\"turso.url\") as { value: string } | undefined;\r\n const authToken = db.prepare(\"SELECT value FROM user_config WHERE key = ?\").get(\"turso.token\") as { value: string } | undefined;\r\n\r\n if (!syncUrl || !authToken) return db;\r\n\r\n // Reopen with sync enabled\r\n db.close();\r\n return openDatabase({ ...options, syncUrl: syncUrl.value, authToken: authToken.value });\r\n}\r\n\r\n/** Get the default database path */\r\nexport function getDefaultDbPath(): string {\r\n return DEFAULT_DB_PATH;\r\n}\r\n\r\n/**\r\n * Run incremental schema migrations on every open.\r\n * Each migration is idempotent — safe to run repeatedly.\r\n */\r\nfunction runMigrations(db: DatabaseType): void {\r\n // M001: add execution_context to sessions\r\n const sessionCols = db.pragma(\"table_info(sessions)\") as Array<{ name: string }>;\r\n if (sessionCols.length > 0 && !sessionCols.some((c) => c.name === \"execution_context\")) {\r\n db.exec(\r\n `ALTER TABLE sessions ADD COLUMN execution_context TEXT NOT NULL DEFAULT 'shell'`,\r\n );\r\n }\r\n\r\n // M002: add deprecated_at to tokens\r\n const tokenCols = db.pragma(\"table_info(tokens)\") as Array<{ name: string }>;\r\n if (tokenCols.length > 0 && !tokenCols.some((c) => c.name === \"deprecated_at\")) {\r\n db.exec(`ALTER TABLE tokens ADD COLUMN deprecated_at TEXT`);\r\n }\r\n\r\n // M003: create agent_skills table (idempotent via IF NOT EXISTS in SCHEMA,\r\n // but also needed for databases that skipped the init path)\r\n db.exec(`\r\n CREATE TABLE IF NOT EXISTS agent_skills (\r\n id TEXT PRIMARY KEY,\r\n slug TEXT NOT NULL UNIQUE,\r\n description TEXT NOT NULL,\r\n steps TEXT NOT NULL DEFAULT '[]',\r\n token_slugs TEXT NOT NULL DEFAULT '[]',\r\n source TEXT NOT NULL DEFAULT 'learned',\r\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\r\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\r\n )\r\n `);\r\n}\r\n","/**\r\n * ZAM Learning Kernel — SQLite Schema\r\n *\r\n * Evolves the PoC's schema with:\r\n * - FSRS scheduling fields (replaces SM-2's ef/interval_days)\r\n * - Bloom taxonomy levels on tokens\r\n * - Symbiosis modes (shadowing/copilot/autonomy)\r\n * - ULID-based IDs\r\n * - Immutable review log\r\n */\r\n\r\nexport const SCHEMA = `\r\n-- Use WAL mode for concurrent reads (AI CLI + user CLI)\r\nPRAGMA journal_mode = WAL;\r\nPRAGMA foreign_keys = ON;\r\n\r\n-- Knowledge tokens: atomic concepts/facts with Bloom levels\r\nCREATE TABLE IF NOT EXISTS tokens (\r\n id TEXT PRIMARY KEY,\r\n slug TEXT UNIQUE NOT NULL,\r\n concept TEXT NOT NULL,\r\n domain TEXT NOT NULL DEFAULT '',\r\n bloom_level INTEGER NOT NULL DEFAULT 1 CHECK (bloom_level BETWEEN 1 AND 5),\r\n context TEXT NOT NULL DEFAULT '',\r\n symbiosis_mode TEXT CHECK (symbiosis_mode IN ('shadowing', 'copilot', 'autonomy')),\r\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\r\n updated_at TEXT NOT NULL DEFAULT (datetime('now')),\r\n deprecated_at TEXT\r\n);\r\n\r\n-- Prerequisite dependency graph: \"to learn A, first know B\"\r\nCREATE TABLE IF NOT EXISTS prerequisites (\r\n token_id TEXT NOT NULL REFERENCES tokens(id) ON DELETE CASCADE,\r\n requires_id TEXT NOT NULL REFERENCES tokens(id) ON DELETE CASCADE,\r\n PRIMARY KEY (token_id, requires_id)\r\n);\r\n\r\n-- Per-user scheduling state for each token (FSRS fields)\r\nCREATE TABLE IF NOT EXISTS cards (\r\n id TEXT PRIMARY KEY,\r\n token_id TEXT NOT NULL REFERENCES tokens(id) ON DELETE CASCADE,\r\n user_id TEXT NOT NULL,\r\n stability REAL NOT NULL DEFAULT 0.0,\r\n difficulty REAL NOT NULL DEFAULT 0.5,\r\n elapsed_days REAL NOT NULL DEFAULT 0.0,\r\n scheduled_days REAL NOT NULL DEFAULT 0.0,\r\n reps INTEGER NOT NULL DEFAULT 0,\r\n lapses INTEGER NOT NULL DEFAULT 0,\r\n state TEXT NOT NULL DEFAULT 'new' CHECK (state IN ('new', 'learning', 'review', 'relearning')),\r\n due_at TEXT NOT NULL DEFAULT (datetime('now')),\r\n last_review_at TEXT,\r\n blocked INTEGER NOT NULL DEFAULT 0,\r\n UNIQUE(token_id, user_id)\r\n);\r\n\r\n-- Immutable review log: every rating event\r\nCREATE TABLE IF NOT EXISTS review_logs (\r\n id TEXT PRIMARY KEY,\r\n card_id TEXT NOT NULL REFERENCES cards(id) ON DELETE CASCADE,\r\n token_id TEXT NOT NULL REFERENCES tokens(id) ON DELETE CASCADE,\r\n user_id TEXT NOT NULL,\r\n rating INTEGER NOT NULL CHECK (rating BETWEEN 1 AND 4),\r\n response_time_ms INTEGER,\r\n reviewed_at TEXT NOT NULL DEFAULT (datetime('now')),\r\n scheduled_at TEXT NOT NULL,\r\n session_id TEXT REFERENCES sessions(id)\r\n);\r\n\r\n-- Work+learning sessions\r\nCREATE TABLE IF NOT EXISTS sessions (\r\n id TEXT PRIMARY KEY,\r\n user_id TEXT NOT NULL,\r\n task TEXT NOT NULL,\r\n started_at TEXT NOT NULL DEFAULT (datetime('now')),\r\n completed_at TEXT\r\n);\r\n\r\n-- Steps within a session: who did what\r\nCREATE TABLE IF NOT EXISTS session_steps (\r\n id TEXT PRIMARY KEY,\r\n session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,\r\n token_id TEXT NOT NULL REFERENCES tokens(id) ON DELETE CASCADE,\r\n done_by TEXT NOT NULL CHECK (done_by IN ('user', 'agent')),\r\n rating INTEGER CHECK (rating BETWEEN 1 AND 4),\r\n notes TEXT,\r\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\r\n);\r\n\r\n-- User configuration\r\nCREATE TABLE IF NOT EXISTS user_config (\r\n key TEXT PRIMARY KEY,\r\n value TEXT NOT NULL,\r\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\r\n);\r\n\r\n-- Agent skills: task recipes the agent learns from user guidance\r\nCREATE TABLE IF NOT EXISTS agent_skills (\r\n id TEXT PRIMARY KEY,\r\n slug TEXT NOT NULL UNIQUE,\r\n description TEXT NOT NULL,\r\n steps TEXT NOT NULL DEFAULT '[]', -- JSON array of step strings\r\n token_slugs TEXT NOT NULL DEFAULT '[]', -- JSON array of related token slugs\r\n source TEXT NOT NULL DEFAULT 'learned'\r\n CHECK(source IN ('learned', 'builtin')),\r\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\r\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\r\n);\r\n\r\n-- Performance indexes\r\nCREATE INDEX IF NOT EXISTS idx_tokens_domain ON tokens(domain);\r\nCREATE INDEX IF NOT EXISTS idx_tokens_slug ON tokens(slug);\r\nCREATE INDEX IF NOT EXISTS idx_prereqs_token ON prerequisites(token_id);\r\nCREATE INDEX IF NOT EXISTS idx_prereqs_requires ON prerequisites(requires_id);\r\nCREATE INDEX IF NOT EXISTS idx_cards_user_due ON cards(user_id, blocked, due_at);\r\nCREATE INDEX IF NOT EXISTS idx_cards_token_user ON cards(token_id, user_id);\r\nCREATE INDEX IF NOT EXISTS idx_review_logs_card ON review_logs(card_id);\r\nCREATE INDEX IF NOT EXISTS idx_review_logs_user ON review_logs(user_id, reviewed_at);\r\nCREATE INDEX IF NOT EXISTS idx_session_steps_session ON session_steps(session_id);\r\n`;\r\n","/**\r\n * Token repository — typed wrappers around the tokens table.\r\n *\r\n * Tokens are atomic knowledge concepts with Bloom taxonomy levels\r\n * and optional symbiosis modes (shadowing / copilot / autonomy).\r\n */\r\n\r\nimport type { Database } from \"libsql\";\r\nimport { ulid } from \"ulid\";\r\n\r\n// ── Types ────────────────────────────────────────────────────────────────────\r\n\r\nexport type BloomLevel = 1 | 2 | 3 | 4 | 5;\r\n\r\nexport type SymbiosisMode = \"shadowing\" | \"copilot\" | \"autonomy\";\r\n\r\nexport interface Token {\r\n id: string;\r\n slug: string;\r\n concept: string;\r\n domain: string;\r\n bloom_level: BloomLevel;\r\n context: string;\r\n symbiosis_mode: SymbiosisMode | null;\r\n created_at: string;\r\n updated_at: string;\r\n deprecated_at: string | null;\r\n}\r\n\r\nexport interface CreateTokenInput {\r\n slug: string;\r\n concept: string;\r\n domain?: string;\r\n bloom_level?: BloomLevel;\r\n context?: string;\r\n symbiosis_mode?: SymbiosisMode | null;\r\n}\r\n\r\nexport interface ListTokensOptions {\r\n domain?: string;\r\n}\r\n\r\n// ── Scored result from fuzzy search ──────────────────────────────────────────\r\n\r\nexport interface ScoredToken extends Token {\r\n score: number;\r\n}\r\n\r\n// ── Functions ────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Create a new knowledge token.\r\n * Throws if a token with the same slug already exists.\r\n */\r\nexport function createToken(db: Database, input: CreateTokenInput): Token {\r\n const id = ulid();\r\n const now = new Date().toISOString();\r\n\r\n const bloom = input.bloom_level ?? 1;\r\n if (bloom < 1 || bloom > 5) {\r\n throw new Error(`bloom_level must be between 1 and 5, got ${bloom}`);\r\n }\r\n\r\n db.prepare(`\r\n INSERT INTO tokens (id, slug, concept, domain, bloom_level, context, symbiosis_mode, created_at, updated_at)\r\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)\r\n `).run(\r\n id,\r\n input.slug,\r\n input.concept,\r\n input.domain ?? \"\",\r\n bloom,\r\n input.context ?? \"\",\r\n input.symbiosis_mode ?? null,\r\n now,\r\n now,\r\n );\r\n\r\n return getTokenById(db, id)!;\r\n}\r\n\r\n/**\r\n * Look up a token by its unique slug.\r\n * Returns undefined if not found.\r\n */\r\nexport function getTokenBySlug(db: Database, slug: string): Token | undefined {\r\n return db.prepare(\"SELECT * FROM tokens WHERE slug = ?\").get(slug) as Token | undefined;\r\n}\r\n\r\n/**\r\n * Look up a token by its ULID.\r\n * Returns undefined if not found.\r\n */\r\nexport function getTokenById(db: Database, id: string): Token | undefined {\r\n return db.prepare(\"SELECT * FROM tokens WHERE id = ?\").get(id) as Token | undefined;\r\n}\r\n\r\n/**\r\n * Mark a token as deprecated. Deprecated tokens are excluded from review queues\r\n * and search results but are not deleted — they can still be consulted.\r\n *\r\n * Throws if the token does not exist or is already deprecated.\r\n */\r\nexport function deprecateToken(db: Database, slug: string): Token {\r\n const token = getTokenBySlug(db, slug);\r\n if (!token) {\r\n throw new Error(`Token not found: ${slug}`);\r\n }\r\n if (token.deprecated_at) {\r\n throw new Error(`Token already deprecated: ${slug}`);\r\n }\r\n\r\n const now = new Date().toISOString();\r\n db.prepare(\"UPDATE tokens SET deprecated_at = ?, updated_at = ? WHERE slug = ?\").run(\r\n now,\r\n now,\r\n slug,\r\n );\r\n\r\n return getTokenBySlug(db, slug)!;\r\n}\r\n\r\n/**\r\n * Fuzzy search for tokens by keyword query.\r\n *\r\n * Ported from the PoC's find-token command: splits the query into word\r\n * tokens, scores each database token by word overlap plus a substring\r\n * bonus on the concept field, and returns all matches sorted by score\r\n * descending.\r\n */\r\nexport function findTokens(db: Database, query: string): ScoredToken[] {\r\n const normalised = query.toLowerCase();\r\n const qTokens = new Set(\r\n normalised\r\n .split(/[\\s,.\\-_/\\\\:;!?()\\[\\]{}]+/)\r\n .filter((t) => t.length > 2),\r\n );\r\n\r\n const tokens = db\r\n .prepare(\"SELECT * FROM tokens WHERE deprecated_at IS NULL\")\r\n .all() as Token[];\r\n\r\n const scored: ScoredToken[] = [];\r\n\r\n for (const t of tokens) {\r\n const words = (t.slug + \" \" + t.concept + \" \" + t.domain)\r\n .toLowerCase()\r\n .split(/[\\s,.\\-_/\\\\:;!?()\\[\\]{}]+/)\r\n .filter(Boolean);\r\n\r\n let score = 0;\r\n for (const w of words) {\r\n if (qTokens.has(w)) score++;\r\n }\r\n\r\n // Substring bonus: if the concept contains the start of the query\r\n if (t.concept.toLowerCase().includes(normalised.slice(0, 25))) {\r\n score += 3;\r\n }\r\n\r\n if (score > 0) {\r\n scored.push({ score, ...t });\r\n }\r\n }\r\n\r\n scored.sort((a, b) => b.score - a.score);\r\n return scored;\r\n}\r\n\r\n/**\r\n * List all tokens, optionally filtered by domain.\r\n * Results are ordered by bloom_level then slug.\r\n */\r\nexport function listTokens(db: Database, options?: ListTokensOptions): Token[] {\r\n if (options?.domain) {\r\n return db\r\n .prepare(\r\n \"SELECT * FROM tokens WHERE domain = ? AND deprecated_at IS NULL ORDER BY bloom_level, slug\",\r\n )\r\n .all(options.domain) as Token[];\r\n }\r\n return db\r\n .prepare(\r\n \"SELECT * FROM tokens WHERE deprecated_at IS NULL ORDER BY bloom_level, domain, slug\",\r\n )\r\n .all() as Token[];\r\n}\r\n","/**\r\n * Prerequisite repository — typed wrappers around the prerequisites table.\r\n *\r\n * Models the dependency graph: \"to learn token A, first know token B.\"\r\n */\r\n\r\nimport type { Database } from \"libsql\";\r\n\r\n// ── Types ────────────────────────────────────────────────────────────────────\r\n\r\nexport interface Prerequisite {\r\n token_id: string;\r\n requires_id: string;\r\n}\r\n\r\n/** A prerequisite row joined with the token it points to. */\r\nexport interface PrerequisiteWithToken extends Prerequisite {\r\n slug: string;\r\n concept: string;\r\n domain: string;\r\n bloom_level: number;\r\n}\r\n\r\n// ── Functions ────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Add a prerequisite edge: tokenId requires requiresId.\r\n *\r\n * Idempotent — silently ignores duplicate edges.\r\n * Throws if either token ID does not exist (FK constraint).\r\n * Throws if a token is declared as its own prerequisite.\r\n */\r\nexport function addPrerequisite(\r\n db: Database,\r\n tokenId: string,\r\n requiresId: string,\r\n): void {\r\n if (tokenId === requiresId) {\r\n throw new Error(\"A token cannot be a prerequisite of itself\");\r\n }\r\n\r\n db.prepare(\r\n \"INSERT OR IGNORE INTO prerequisites (token_id, requires_id) VALUES (?, ?)\",\r\n ).run(tokenId, requiresId);\r\n}\r\n\r\n/**\r\n * Get the direct prerequisites of a token — \"what does token X require?\"\r\n *\r\n * Returns prerequisite rows joined with the required token's details.\r\n */\r\nexport function getPrerequisites(\r\n db: Database,\r\n tokenId: string,\r\n): PrerequisiteWithToken[] {\r\n return db\r\n .prepare(\r\n `SELECT p.token_id, p.requires_id, t.slug, t.concept, t.domain, t.bloom_level\r\n FROM prerequisites p\r\n JOIN tokens t ON t.id = p.requires_id\r\n WHERE p.token_id = ?`,\r\n )\r\n .all(tokenId) as PrerequisiteWithToken[];\r\n}\r\n\r\n/**\r\n * Get the direct dependents of a token — \"what depends on token X?\"\r\n *\r\n * Returns prerequisite rows joined with the dependent token's details.\r\n */\r\nexport function getDependents(\r\n db: Database,\r\n tokenId: string,\r\n): PrerequisiteWithToken[] {\r\n return db\r\n .prepare(\r\n `SELECT p.token_id, p.requires_id, t.slug, t.concept, t.domain, t.bloom_level\r\n FROM prerequisites p\r\n JOIN tokens t ON t.id = p.token_id\r\n WHERE p.requires_id = ?`,\r\n )\r\n .all(tokenId) as PrerequisiteWithToken[];\r\n}\r\n","/**\r\n * Card repository — typed wrappers around the cards table.\r\n *\r\n * Each card tracks one user's scheduling state for one token,\r\n * using FSRS fields (stability, difficulty, elapsed_days, etc.).\r\n */\r\n\r\nimport type { Database } from \"libsql\";\r\nimport { ulid } from \"ulid\";\r\n\r\n// ── Types ────────────────────────────────────────────────────────────────────\r\n\r\nexport type CardState = \"new\" | \"learning\" | \"review\" | \"relearning\";\r\n\r\nexport interface Card {\r\n id: string;\r\n token_id: string;\r\n user_id: string;\r\n stability: number;\r\n difficulty: number;\r\n elapsed_days: number;\r\n scheduled_days: number;\r\n reps: number;\r\n lapses: number;\r\n state: CardState;\r\n due_at: string;\r\n last_review_at: string | null;\r\n blocked: number; // 0 or 1\r\n}\r\n\r\nexport interface UpdateCardInput {\r\n stability?: number;\r\n difficulty?: number;\r\n elapsed_days?: number;\r\n scheduled_days?: number;\r\n reps?: number;\r\n lapses?: number;\r\n state?: CardState;\r\n due_at?: string;\r\n last_review_at?: string | null;\r\n blocked?: number;\r\n}\r\n\r\n/** A due card joined with its token details. */\r\nexport interface DueCard extends Card {\r\n slug: string;\r\n concept: string;\r\n domain: string;\r\n bloom_level: number;\r\n}\r\n\r\n/** A blocked card joined with its token details. */\r\nexport interface BlockedCard extends Card {\r\n slug: string;\r\n concept: string;\r\n domain: string;\r\n bloom_level: number;\r\n}\r\n\r\n// ── Functions ────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Ensure a card exists for the given token+user pair.\r\n *\r\n * If one already exists, return it. Otherwise create a new card with\r\n * default FSRS values (due immediately) and return it.\r\n *\r\n * Ported from the PoC's ensureCard helper.\r\n */\r\nexport function ensureCard(\r\n db: Database,\r\n tokenId: string,\r\n userId: string,\r\n): Card {\r\n const existing = db\r\n .prepare(\"SELECT * FROM cards WHERE token_id = ? AND user_id = ?\")\r\n .get(tokenId, userId) as Card | undefined;\r\n\r\n if (existing) return existing;\r\n\r\n const id = ulid();\r\n const now = new Date().toISOString();\r\n\r\n db.prepare(\r\n `INSERT INTO cards (id, token_id, user_id, due_at)\r\n VALUES (?, ?, ?, ?)`,\r\n ).run(id, tokenId, userId, now);\r\n\r\n return db\r\n .prepare(\"SELECT * FROM cards WHERE id = ?\")\r\n .get(id) as Card;\r\n}\r\n\r\n/**\r\n * Get a card by token+user. Returns undefined if no card exists.\r\n */\r\nexport function getCard(\r\n db: Database,\r\n tokenId: string,\r\n userId: string,\r\n): Card | undefined {\r\n return db\r\n .prepare(\"SELECT * FROM cards WHERE token_id = ? AND user_id = ?\")\r\n .get(tokenId, userId) as Card | undefined;\r\n}\r\n\r\n/**\r\n * Update a card's scheduling fields.\r\n *\r\n * Only the fields present in `updates` are changed. Throws if the card\r\n * does not exist.\r\n */\r\nexport function updateCard(\r\n db: Database,\r\n cardId: string,\r\n updates: UpdateCardInput,\r\n): Card {\r\n const fields: string[] = [];\r\n const values: unknown[] = [];\r\n\r\n if (updates.stability !== undefined) {\r\n fields.push(\"stability = ?\");\r\n values.push(updates.stability);\r\n }\r\n if (updates.difficulty !== undefined) {\r\n fields.push(\"difficulty = ?\");\r\n values.push(updates.difficulty);\r\n }\r\n if (updates.elapsed_days !== undefined) {\r\n fields.push(\"elapsed_days = ?\");\r\n values.push(updates.elapsed_days);\r\n }\r\n if (updates.scheduled_days !== undefined) {\r\n fields.push(\"scheduled_days = ?\");\r\n values.push(updates.scheduled_days);\r\n }\r\n if (updates.reps !== undefined) {\r\n fields.push(\"reps = ?\");\r\n values.push(updates.reps);\r\n }\r\n if (updates.lapses !== undefined) {\r\n fields.push(\"lapses = ?\");\r\n values.push(updates.lapses);\r\n }\r\n if (updates.state !== undefined) {\r\n fields.push(\"state = ?\");\r\n values.push(updates.state);\r\n }\r\n if (updates.due_at !== undefined) {\r\n fields.push(\"due_at = ?\");\r\n values.push(updates.due_at);\r\n }\r\n if (updates.last_review_at !== undefined) {\r\n fields.push(\"last_review_at = ?\");\r\n values.push(updates.last_review_at);\r\n }\r\n if (updates.blocked !== undefined) {\r\n fields.push(\"blocked = ?\");\r\n values.push(updates.blocked);\r\n }\r\n\r\n if (fields.length === 0) {\r\n throw new Error(\"updateCard called with no fields to update\");\r\n }\r\n\r\n values.push(cardId);\r\n\r\n const result = db\r\n .prepare(`UPDATE cards SET ${fields.join(\", \")} WHERE id = ?`)\r\n .run(...values);\r\n\r\n if (result.changes === 0) {\r\n throw new Error(`Card not found: ${cardId}`);\r\n }\r\n\r\n return db.prepare(\"SELECT * FROM cards WHERE id = ?\").get(cardId) as Card;\r\n}\r\n\r\n/**\r\n * Get all cards that are due for review.\r\n *\r\n * A card is due when it is not blocked and due_at <= now.\r\n * Results are ordered by bloom_level ascending (fundamentals first),\r\n * then by due_at ascending (oldest first).\r\n *\r\n * Ported from the PoC's due-tokens command.\r\n */\r\nexport function getDueCards(\r\n db: Database,\r\n userId: string,\r\n now?: string,\r\n): DueCard[] {\r\n const cutoff = now ?? new Date().toISOString();\r\n\r\n return db\r\n .prepare(\r\n `SELECT c.*, t.slug, t.concept, t.domain, t.bloom_level\r\n FROM cards c\r\n JOIN tokens t ON t.id = c.token_id\r\n WHERE c.user_id = ? AND c.blocked = 0 AND c.due_at <= ?\r\n ORDER BY t.bloom_level ASC, c.due_at ASC`,\r\n )\r\n .all(userId, cutoff) as DueCard[];\r\n}\r\n\r\n/**\r\n * Get all blocked cards for a user.\r\n *\r\n * Returns cards joined with their token details so the caller can\r\n * see what is waiting and why.\r\n */\r\nexport function getBlockedCards(\r\n db: Database,\r\n userId: string,\r\n): BlockedCard[] {\r\n return db\r\n .prepare(\r\n `SELECT c.*, t.slug, t.concept, t.domain, t.bloom_level\r\n FROM cards c\r\n JOIN tokens t ON t.id = c.token_id\r\n WHERE c.user_id = ? AND c.blocked = 1\r\n ORDER BY t.bloom_level ASC, t.slug ASC`,\r\n )\r\n .all(userId) as BlockedCard[];\r\n}\r\n","/**\r\n * Review log repository — typed wrappers around the review_logs table.\r\n *\r\n * The review log is immutable: every rating event is appended, never\r\n * updated or deleted. This provides a complete audit trail of a user's\r\n * learning history.\r\n */\r\n\r\nimport type { Database } from \"libsql\";\r\nimport { ulid } from \"ulid\";\r\n\r\n// ── Types ────────────────────────────────────────────────────────────────────\r\n\r\nexport interface ReviewLog {\r\n id: string;\r\n card_id: string;\r\n token_id: string;\r\n user_id: string;\r\n rating: number; // 1-4\r\n response_time_ms: number | null;\r\n reviewed_at: string;\r\n scheduled_at: string;\r\n session_id: string | null;\r\n}\r\n\r\nexport interface CreateReviewInput {\r\n card_id: string;\r\n token_id: string;\r\n user_id: string;\r\n rating: number; // 1-4\r\n scheduled_at: string;\r\n response_time_ms?: number | null;\r\n session_id?: string | null;\r\n}\r\n\r\nexport interface ListReviewsOptions {\r\n /** Maximum number of reviews to return. */\r\n limit?: number;\r\n /** Return reviews after this ISO timestamp. */\r\n after?: string;\r\n /** Return reviews before this ISO timestamp. */\r\n before?: string;\r\n}\r\n\r\n// ── Functions ────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Log an immutable review event.\r\n *\r\n * Validates that the rating is between 1 and 4 (matching the schema CHECK).\r\n * Returns the created review log entry.\r\n */\r\nexport function logReview(db: Database, input: CreateReviewInput): ReviewLog {\r\n if (input.rating < 1 || input.rating > 4) {\r\n throw new Error(`Rating must be between 1 and 4, got ${input.rating}`);\r\n }\r\n\r\n const id = ulid();\r\n const now = new Date().toISOString();\r\n\r\n db.prepare(\r\n `INSERT INTO review_logs (id, card_id, token_id, user_id, rating, response_time_ms, reviewed_at, scheduled_at, session_id)\r\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,\r\n ).run(\r\n id,\r\n input.card_id,\r\n input.token_id,\r\n input.user_id,\r\n input.rating,\r\n input.response_time_ms ?? null,\r\n now,\r\n input.scheduled_at,\r\n input.session_id ?? null,\r\n );\r\n\r\n return db.prepare(\"SELECT * FROM review_logs WHERE id = ?\").get(id) as ReviewLog;\r\n}\r\n\r\n/**\r\n * Get all reviews for a specific card, ordered by reviewed_at ascending.\r\n */\r\nexport function getReviewsForCard(db: Database, cardId: string): ReviewLog[] {\r\n return db\r\n .prepare(\r\n \"SELECT * FROM review_logs WHERE card_id = ? ORDER BY reviewed_at ASC\",\r\n )\r\n .all(cardId) as ReviewLog[];\r\n}\r\n\r\n/**\r\n * Get reviews for a user, with optional filtering.\r\n *\r\n * Results are ordered by reviewed_at descending (most recent first).\r\n */\r\nexport function getReviewsForUser(\r\n db: Database,\r\n userId: string,\r\n options?: ListReviewsOptions,\r\n): ReviewLog[] {\r\n const conditions = [\"user_id = ?\"];\r\n const params: unknown[] = [userId];\r\n\r\n if (options?.after) {\r\n conditions.push(\"reviewed_at > ?\");\r\n params.push(options.after);\r\n }\r\n if (options?.before) {\r\n conditions.push(\"reviewed_at < ?\");\r\n params.push(options.before);\r\n }\r\n\r\n let sql = `SELECT * FROM review_logs WHERE ${conditions.join(\" AND \")} ORDER BY reviewed_at DESC`;\r\n\r\n if (options?.limit) {\r\n sql += \" LIMIT ?\";\r\n params.push(options.limit);\r\n }\r\n\r\n return db.prepare(sql).all(...params) as ReviewLog[];\r\n}\r\n","/**\r\n * Session repository — typed wrappers around sessions and session_steps.\r\n *\r\n * A session represents a work+learning episode. Steps within a session\r\n * record which tokens were touched and by whom (user or agent).\r\n */\r\n\r\nimport type { Database } from \"libsql\";\r\nimport { ulid } from \"ulid\";\r\n\r\n// ── Types ────────────────────────────────────────────────────────────────────\r\n\r\nexport type ExecutionContext = \"shell\" | \"ui\" | \"reallife\";\r\n\r\nexport interface Session {\r\n id: string;\r\n user_id: string;\r\n task: string;\r\n execution_context: ExecutionContext;\r\n started_at: string;\r\n completed_at: string | null;\r\n}\r\n\r\nexport interface SessionStep {\r\n id: string;\r\n session_id: string;\r\n token_id: string;\r\n done_by: \"user\" | \"agent\";\r\n rating: number | null; // 1-4 or null\r\n notes: string | null;\r\n created_at: string;\r\n}\r\n\r\nexport interface CreateSessionInput {\r\n user_id: string;\r\n task: string;\r\n execution_context?: ExecutionContext;\r\n}\r\n\r\nexport interface LogStepInput {\r\n session_id: string;\r\n token_id: string;\r\n done_by: \"user\" | \"agent\";\r\n rating?: number | null;\r\n notes?: string | null;\r\n}\r\n\r\n/** A step joined with its token details, returned by getSessionSummary. */\r\nexport interface StepWithToken extends SessionStep {\r\n slug: string;\r\n concept: string;\r\n domain: string;\r\n bloom_level: number;\r\n}\r\n\r\nexport interface SessionSummary {\r\n session: Session;\r\n steps: StepWithToken[];\r\n}\r\n\r\n// ── Functions ────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Start a new session. Returns the created session.\r\n *\r\n * Ported from the PoC's start-session command.\r\n */\r\nexport function startSession(db: Database, input: CreateSessionInput): Session {\r\n const id = ulid();\r\n const now = new Date().toISOString();\r\n const ctx = input.execution_context ?? \"shell\";\r\n\r\n db.prepare(\r\n `INSERT INTO sessions (id, user_id, task, execution_context, started_at)\r\n VALUES (?, ?, ?, ?, ?)`,\r\n ).run(id, input.user_id, input.task, ctx, now);\r\n\r\n return db.prepare(\"SELECT * FROM sessions WHERE id = ?\").get(id) as Session;\r\n}\r\n\r\n/**\r\n * End a session by setting its completed_at timestamp.\r\n *\r\n * Throws if the session does not exist or is already completed.\r\n *\r\n * Ported from the PoC's end-session command.\r\n */\r\nexport function endSession(db: Database, sessionId: string): Session {\r\n const session = db.prepare(\"SELECT * FROM sessions WHERE id = ?\").get(sessionId) as\r\n | Session\r\n | undefined;\r\n\r\n if (!session) {\r\n throw new Error(`Session not found: ${sessionId}`);\r\n }\r\n if (session.completed_at) {\r\n throw new Error(`Session already completed: ${sessionId}`);\r\n }\r\n\r\n const now = new Date().toISOString();\r\n db.prepare(\"UPDATE sessions SET completed_at = ? WHERE id = ?\").run(now, sessionId);\r\n\r\n return db.prepare(\"SELECT * FROM sessions WHERE id = ?\").get(sessionId) as Session;\r\n}\r\n\r\n/**\r\n * Log a step within a session.\r\n *\r\n * Validates that done_by is 'user' or 'agent' and that the rating\r\n * (if provided) is between 1 and 4.\r\n *\r\n * Ported from the PoC's log-step command.\r\n */\r\nexport function logStep(db: Database, input: LogStepInput): SessionStep {\r\n if (input.done_by !== \"user\" && input.done_by !== \"agent\") {\r\n throw new Error(`done_by must be 'user' or 'agent', got '${input.done_by}'`);\r\n }\r\n if (input.rating != null && (input.rating < 1 || input.rating > 4)) {\r\n throw new Error(`Rating must be between 1 and 4, got ${input.rating}`);\r\n }\r\n\r\n // Verify the session exists\r\n const session = db.prepare(\"SELECT id FROM sessions WHERE id = ?\").get(input.session_id);\r\n if (!session) {\r\n throw new Error(`Session not found: ${input.session_id}`);\r\n }\r\n\r\n const id = ulid();\r\n const now = new Date().toISOString();\r\n\r\n db.prepare(\r\n `INSERT INTO session_steps (id, session_id, token_id, done_by, rating, notes, created_at)\r\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\r\n ).run(\r\n id,\r\n input.session_id,\r\n input.token_id,\r\n input.done_by,\r\n input.rating ?? null,\r\n input.notes ?? null,\r\n now,\r\n );\r\n\r\n return db.prepare(\"SELECT * FROM session_steps WHERE id = ?\").get(id) as SessionStep;\r\n}\r\n\r\n/**\r\n * Get a full session summary: the session record plus all steps\r\n * joined with their token details.\r\n *\r\n * Ported from the PoC's session-summary command.\r\n * Throws if the session does not exist.\r\n */\r\nexport function getSessionSummary(\r\n db: Database,\r\n sessionId: string,\r\n): SessionSummary {\r\n const session = db\r\n .prepare(\"SELECT * FROM sessions WHERE id = ?\")\r\n .get(sessionId) as Session | undefined;\r\n\r\n if (!session) {\r\n throw new Error(`Session not found: ${sessionId}`);\r\n }\r\n\r\n const steps = db\r\n .prepare(\r\n `SELECT ss.*, t.slug, t.concept, t.domain, t.bloom_level\r\n FROM session_steps ss\r\n JOIN tokens t ON t.id = ss.token_id\r\n WHERE ss.session_id = ?\r\n ORDER BY ss.created_at ASC`,\r\n )\r\n .all(sessionId) as StepWithToken[];\r\n\r\n return { session, steps };\r\n}\r\n","/**\r\n * Agent skills: task recipes the agent learns from user guidance.\r\n *\r\n * When the agent cannot execute a step, it admits it, asks for guidance,\r\n * and saves the successful approach here. Skills are linked to tokens so\r\n * FSRS decay naturally resurfaces them for review — automation ≠ retention.\r\n */\r\n\r\nimport type { Database } from \"libsql\";\r\nimport { ulid } from \"ulid\";\r\n\r\n// ── Types ────────────────────────────────────────────────────────────────────\r\n\r\nexport type SkillSource = \"learned\" | \"builtin\";\r\n\r\nexport interface AgentSkill {\r\n id: string;\r\n slug: string;\r\n description: string;\r\n steps: string[]; // parsed from JSON\r\n token_slugs: string[]; // parsed from JSON\r\n source: SkillSource;\r\n created_at: string;\r\n updated_at: string;\r\n}\r\n\r\n/** Raw DB row — steps and token_slugs are stored as JSON strings */\r\ninterface AgentSkillRow {\r\n id: string;\r\n slug: string;\r\n description: string;\r\n steps: string;\r\n token_slugs: string;\r\n source: SkillSource;\r\n created_at: string;\r\n updated_at: string;\r\n}\r\n\r\nexport interface CreateAgentSkillInput {\r\n slug: string;\r\n description: string;\r\n steps: string[];\r\n token_slugs?: string[];\r\n source?: SkillSource;\r\n}\r\n\r\n// ── Helpers ──────────────────────────────────────────────────────────────────\r\n\r\nfunction parseRow(row: AgentSkillRow): AgentSkill {\r\n return {\r\n ...row,\r\n steps: JSON.parse(row.steps) as string[],\r\n token_slugs: JSON.parse(row.token_slugs) as string[],\r\n };\r\n}\r\n\r\n// ── Functions ────────────────────────────────────────────────────────────────\r\n\r\nexport function createAgentSkill(\r\n db: Database,\r\n input: CreateAgentSkillInput,\r\n): AgentSkill {\r\n const existing = db\r\n .prepare(\"SELECT * FROM agent_skills WHERE slug = ?\")\r\n .get(input.slug) as AgentSkillRow | undefined;\r\n\r\n if (existing) {\r\n throw new Error(`Agent skill already exists: ${input.slug}`);\r\n }\r\n\r\n const id = ulid();\r\n const now = new Date().toISOString();\r\n\r\n db.prepare(\r\n `INSERT INTO agent_skills (id, slug, description, steps, token_slugs, source, created_at, updated_at)\r\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,\r\n ).run(\r\n id,\r\n input.slug,\r\n input.description,\r\n JSON.stringify(input.steps),\r\n JSON.stringify(input.token_slugs ?? []),\r\n input.source ?? \"learned\",\r\n now,\r\n now,\r\n );\r\n\r\n return parseRow(\r\n db.prepare(\"SELECT * FROM agent_skills WHERE id = ?\").get(id) as AgentSkillRow,\r\n );\r\n}\r\n\r\nexport function getAgentSkill(\r\n db: Database,\r\n slug: string,\r\n): AgentSkill | undefined {\r\n const row = db\r\n .prepare(\"SELECT * FROM agent_skills WHERE slug = ?\")\r\n .get(slug) as AgentSkillRow | undefined;\r\n\r\n return row ? parseRow(row) : undefined;\r\n}\r\n\r\nexport function listAgentSkills(db: Database): AgentSkill[] {\r\n const rows = db\r\n .prepare(\"SELECT * FROM agent_skills ORDER BY created_at ASC\")\r\n .all() as AgentSkillRow[];\r\n\r\n return rows.map(parseRow);\r\n}\r\n","/**\r\n * User settings — key/value store backed by the user_config table.\r\n */\r\n\r\nimport type { Database } from \"libsql\";\r\n\r\nexport interface UserSetting {\r\n key: string;\r\n value: string;\r\n updated_at: string;\r\n}\r\n\r\n/** Get a single setting by key. Returns undefined if not set. */\r\nexport function getSetting(db: Database, key: string): string | undefined {\r\n const row = db\r\n .prepare(\"SELECT value FROM user_config WHERE key = ?\")\r\n .get(key) as { value: string } | undefined;\r\n return row?.value;\r\n}\r\n\r\n/** Get all settings as a key-value map. */\r\nexport function getAllSettings(db: Database): Record<string, string> {\r\n const rows = db\r\n .prepare(\"SELECT key, value FROM user_config ORDER BY key\")\r\n .all() as { key: string; value: string }[];\r\n const map: Record<string, string> = {};\r\n for (const row of rows) {\r\n map[row.key] = row.value;\r\n }\r\n return map;\r\n}\r\n\r\n/** Get all settings with metadata. */\r\nexport function getAllSettingsDetailed(db: Database): UserSetting[] {\r\n return db\r\n .prepare(\"SELECT key, value, updated_at FROM user_config ORDER BY key\")\r\n .all() as UserSetting[];\r\n}\r\n\r\n/** Set a setting (insert or update). */\r\nexport function setSetting(db: Database, key: string, value: string): void {\r\n db.prepare(\r\n `INSERT INTO user_config (key, value, updated_at)\r\n VALUES (?, ?, datetime('now'))\r\n ON CONFLICT(key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at`,\r\n ).run(key, value);\r\n}\r\n\r\n/** Delete a setting. Returns true if it existed. */\r\nexport function deleteSetting(db: Database, key: string): boolean {\r\n const result = db.prepare(\"DELETE FROM user_config WHERE key = ?\").run(key);\r\n return result.changes > 0;\r\n}\r\n","/**\r\n * FSRS-5 — Free Spaced Repetition Scheduler (v5)\r\n *\r\n * Pure-function implementation of the FSRS algorithm that replaces\r\n * the PoC's SM-2 scheduler. This is the mathematical heart of ZAM's\r\n * spaced-repetition engine.\r\n *\r\n * Reference: https://github.com/open-spaced-repetition/fsrs4anki/wiki/The-Algorithm\r\n */\r\n\r\n// ── Rating scale ────────────────────────────────────────────────────────────\r\n\r\n/** 1 = Again (forgot), 2 = Hard, 3 = Good, 4 = Easy */\r\nexport type Rating = 1 | 2 | 3 | 4;\r\n\r\n// ── Card states ─────────────────────────────────────────────────────────────\r\n\r\nexport type CardState = \"new\" | \"learning\" | \"review\" | \"relearning\";\r\n\r\n// ── Scheduling card ─────────────────────────────────────────────────────────\r\n\r\nexport interface SchedulingCard {\r\n /** Memory stability in days — expected half-life of recall probability. */\r\n stability: number;\r\n /** Intrinsic difficulty on a 1–10 scale. */\r\n difficulty: number;\r\n /** Days elapsed since the last review. */\r\n elapsedDays: number;\r\n /** Currently scheduled interval in days. */\r\n scheduledDays: number;\r\n /** Count of successful consecutive reviews. */\r\n reps: number;\r\n /** Times the card was forgotten (rated Again). */\r\n lapses: number;\r\n /** Current learning state. */\r\n state: CardState;\r\n /** When the card is next due. */\r\n dueAt: Date;\r\n /** When the card was last reviewed (null for new cards). */\r\n lastReviewAt: Date | null;\r\n}\r\n\r\n// ── Parameters ──────────────────────────────────────────────────────────────\r\n\r\nexport interface FSRSParameters {\r\n /** 19 optimised weight parameters (w0 – w18). */\r\n w: number[];\r\n /** Target retention rate, e.g. 0.9 means we aim for 90% recall. */\r\n requestRetention: number;\r\n}\r\n\r\n// ── FSRS-5 default weights ──────────────────────────────────────────────────\r\n\r\nconst DEFAULT_W: number[] = [\r\n 0.4072, 1.1829, 3.1262, 15.4722, // w0–w3: initial stability per rating\r\n 7.2102, 0.5316, 1.0651, // w4–w6: difficulty\r\n 0.0092, 1.5988, 0.1176, 1.0014, // w7–w10: stability after forgetting\r\n 2.0032, 0.0266, 0.3077, 0.15, // w11–w14: stability increase\r\n 0.0, 2.7849, 0.3477, 0.6831, // w15–w18: additional parameters\r\n];\r\n\r\nconst DEFAULT_REQUEST_RETENTION = 0.9;\r\n\r\n// ── FSRS object returned by the factory ─────────────────────────────────────\r\n\r\nexport interface FSRS {\r\n /** Return a fully updated card after applying a rating. Pure function. */\r\n schedule(card: SchedulingCard, rating: Rating, now?: Date): SchedulingCard;\r\n /** The parameters baked into this instance. */\r\n readonly params: Readonly<FSRSParameters>;\r\n}\r\n\r\n// ── Helpers ─────────────────────────────────────────────────────────────────\r\n\r\n/** Clamp a number to [lo, hi]. */\r\nfunction clamp(value: number, lo: number, hi: number): number {\r\n return Math.min(hi, Math.max(lo, value));\r\n}\r\n\r\n/** Days between two Date objects (may be fractional). */\r\nfunction daysBetween(a: Date, b: Date): number {\r\n return (b.getTime() - a.getTime()) / (1000 * 60 * 60 * 24);\r\n}\r\n\r\n// ── Core FSRS-5 formulas ────────────────────────────────────────────────────\r\n\r\n/**\r\n * Initial stability for a brand-new card.\r\n * S₀ = w[rating - 1]\r\n */\r\nfunction initialStability(w: number[], rating: Rating): number {\r\n return w[rating - 1];\r\n}\r\n\r\n/**\r\n * Initial difficulty for a brand-new card.\r\n * D₀(rating) = w4 - exp(w5 * (rating - 1)) + 1\r\n * Clamped to [1, 10].\r\n */\r\nfunction initialDifficulty(w: number[], rating: Rating): number {\r\n return clamp(w[4] - Math.exp(w[5] * (rating - 1)) + 1, 1, 10);\r\n}\r\n\r\n/**\r\n * Updated difficulty after a review.\r\n * D' = w7 * D₀(3) + (1 - w7) * (D - w6 * (rating - 3))\r\n * Clamped to [1, 10].\r\n */\r\nfunction nextDifficulty(w: number[], d: number, rating: Rating): number {\r\n const d0ForGood = initialDifficulty(w, 3);\r\n const updated = w[7] * d0ForGood + (1 - w[7]) * (d - w[6] * (rating - 3));\r\n return clamp(updated, 1, 10);\r\n}\r\n\r\n/**\r\n * Retrievability — probability of recall.\r\n * R = (1 + elapsed / (9 * S))^(-1)\r\n */\r\nfunction retrievability(elapsed: number, stability: number): number {\r\n if (stability <= 0) return 0;\r\n return Math.pow(1 + elapsed / (9 * stability), -1);\r\n}\r\n\r\n/**\r\n * Stability after a **successful** recall (rating >= 2).\r\n * S' = S * (exp(w8) * (11 - D) * S^(-w9) * (exp(w10 * (1 - R)) - 1) * hard_penalty * easy_bonus + 1)\r\n */\r\nfunction stabilityAfterSuccess(\r\n w: number[],\r\n s: number,\r\n d: number,\r\n r: number,\r\n rating: Rating,\r\n): number {\r\n const hardPenalty = rating === 2 ? w[15] : 1;\r\n const easyBonus = rating === 4 ? w[16] : 1;\r\n\r\n const inner =\r\n Math.exp(w[8]) *\r\n (11 - d) *\r\n Math.pow(s, -w[9]) *\r\n (Math.exp(w[10] * (1 - r)) - 1) *\r\n hardPenalty *\r\n easyBonus;\r\n\r\n return s * (inner + 1);\r\n}\r\n\r\n/**\r\n * Stability after **forgetting** (rating = 1).\r\n * S' = w11 * D^(-w12) * ((S+1)^w13 - 1) * exp(w14 * (1 - R))\r\n */\r\nfunction stabilityAfterForgetting(\r\n w: number[],\r\n s: number,\r\n d: number,\r\n r: number,\r\n): number {\r\n return (\r\n w[11] *\r\n Math.pow(d, -w[12]) *\r\n (Math.pow(s + 1, w[13]) - 1) *\r\n Math.exp(w[14] * (1 - r))\r\n );\r\n}\r\n\r\n/**\r\n * Optimal interval given new stability and target retention.\r\n * I = 9 * S' * (1/requestRetention - 1)\r\n * Minimum 1 day.\r\n */\r\nfunction nextInterval(stability: number, requestRetention: number): number {\r\n const interval = 9 * stability * (1 / requestRetention - 1);\r\n return Math.max(1, Math.round(interval));\r\n}\r\n\r\n// ── Factory ─────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Create a new card with default initial values.\r\n */\r\nexport function createEmptyCard(now?: Date): SchedulingCard {\r\n const ts = now ?? new Date();\r\n return {\r\n stability: 0,\r\n difficulty: 0,\r\n elapsedDays: 0,\r\n scheduledDays: 0,\r\n reps: 0,\r\n lapses: 0,\r\n state: \"new\",\r\n dueAt: ts,\r\n lastReviewAt: null,\r\n };\r\n}\r\n\r\n/**\r\n * Create an FSRS scheduler instance.\r\n *\r\n * All scheduling is done through pure functions — no side effects,\r\n * no database access, no mutation of the input card.\r\n */\r\nexport function createFSRS(params?: Partial<FSRSParameters>): FSRS {\r\n const resolvedParams: FSRSParameters = {\r\n w: params?.w ?? [...DEFAULT_W],\r\n requestRetention: params?.requestRetention ?? DEFAULT_REQUEST_RETENTION,\r\n };\r\n\r\n function schedule(\r\n card: SchedulingCard,\r\n rating: Rating,\r\n now?: Date,\r\n ): SchedulingCard {\r\n const reviewTime = now ?? new Date();\r\n const w = resolvedParams.w;\r\n\r\n // Compute elapsed days since last review (or 0 for new cards).\r\n const elapsed =\r\n card.lastReviewAt !== null\r\n ? Math.max(0, daysBetween(card.lastReviewAt, reviewTime))\r\n : 0;\r\n\r\n // ── New card ──────────────────────────────────────────────────────\r\n if (card.state === \"new\") {\r\n const s = initialStability(w, rating);\r\n const d = initialDifficulty(w, rating);\r\n const interval = nextInterval(s, resolvedParams.requestRetention);\r\n\r\n const dueAt = new Date(reviewTime);\r\n dueAt.setDate(dueAt.getDate() + interval);\r\n\r\n // New cards always move to \"learning\" after first rating.\r\n\r\n return {\r\n stability: s,\r\n difficulty: d,\r\n elapsedDays: 0,\r\n scheduledDays: interval,\r\n reps: rating >= 2 ? 1 : 0,\r\n lapses: rating === 1 ? 1 : 0,\r\n state: \"learning\",\r\n dueAt,\r\n lastReviewAt: reviewTime,\r\n };\r\n }\r\n\r\n // ── Existing card (learning / review / relearning) ───────────────\r\n\r\n const r = retrievability(elapsed, card.stability);\r\n\r\n let newStability: number;\r\n let newDifficulty: number;\r\n let newReps: number;\r\n let newLapses: number;\r\n let newState: CardState;\r\n\r\n if (rating === 1) {\r\n // Forgot — apply forgetting formula\r\n newStability = stabilityAfterForgetting(w, card.stability, card.difficulty, r);\r\n newDifficulty = nextDifficulty(w, card.difficulty, rating);\r\n newReps = 0;\r\n newLapses = card.lapses + 1;\r\n newState = \"relearning\";\r\n } else {\r\n // Recalled — apply success formula\r\n newStability = stabilityAfterSuccess(w, card.stability, card.difficulty, r, rating);\r\n newDifficulty = nextDifficulty(w, card.difficulty, rating);\r\n newReps = card.reps + 1;\r\n newLapses = card.lapses;\r\n // Successful recall transitions any state to review.\r\n newState = \"review\";\r\n }\r\n\r\n const interval = nextInterval(newStability, resolvedParams.requestRetention);\r\n\r\n const dueAt = new Date(reviewTime);\r\n dueAt.setDate(dueAt.getDate() + interval);\r\n\r\n return {\r\n stability: newStability,\r\n difficulty: newDifficulty,\r\n elapsedDays: elapsed,\r\n scheduledDays: interval,\r\n reps: newReps,\r\n lapses: newLapses,\r\n state: newState,\r\n dueAt,\r\n lastReviewAt: reviewTime,\r\n };\r\n }\r\n\r\n return {\r\n schedule,\r\n params: Object.freeze(resolvedParams),\r\n };\r\n}\r\n","/**\r\n * Cascade Block & Unblock — prerequisite-aware blocking logic.\r\n *\r\n * Ported from the PoC's cascade-block and unblock-ready commands.\r\n *\r\n * When a user rates a token as \"forgot\" (rating 1) and that token has\r\n * prerequisites, we block the token and surface its prerequisites into\r\n * the active deck. When all prerequisites are met, we unblock.\r\n */\r\n\r\nimport type { Database } from \"libsql\";\r\nimport { ensureCard } from \"../models/card.js\";\r\nimport { getTokenBySlug } from \"../models/token.js\";\r\nimport { getPrerequisites } from \"../models/prerequisite.js\";\r\n\r\n// ── Types ────────────────────────────────────────────────────────────────────\r\n\r\nexport interface CascadeBlockResult {\r\n blockedSlug: string;\r\n prerequisites: Array<{ slug: string; concept: string; bloomLevel: number }>;\r\n}\r\n\r\nexport interface UnblockResult {\r\n unblocked: Array<{ slug: string; concept: string }>;\r\n}\r\n\r\n// ── Functions ────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Block a token and surface its prerequisites.\r\n *\r\n * Called when a user rates a token as \"forgot\" (rating 1). The token is\r\n * marked as blocked so it won't appear in review queues. All direct\r\n * prerequisites are ensured to have cards (unblocked, due now) so they\r\n * appear in the user's next review session.\r\n *\r\n * @param db - Database connection\r\n * @param userId - The user whose card to block\r\n * @param tokenSlug - Slug of the token the user forgot\r\n * @returns Info about what was blocked and which prerequisites were surfaced\r\n */\r\nexport function cascadeBlock(\r\n db: Database,\r\n userId: string,\r\n tokenSlug: string,\r\n): CascadeBlockResult {\r\n const token = getTokenBySlug(db, tokenSlug);\r\n if (!token) {\r\n throw new Error(`Unknown token slug: ${tokenSlug}`);\r\n }\r\n\r\n // Ensure a card exists, then block it\r\n ensureCard(db, token.id, userId);\r\n db.prepare(\r\n \"UPDATE cards SET blocked = 1 WHERE token_id = ? AND user_id = ?\",\r\n ).run(token.id, userId);\r\n\r\n // Surface all direct prerequisites — ensure cards exist (unblocked, due now)\r\n const prereqs = getPrerequisites(db, token.id);\r\n const surfaced: Array<{ slug: string; concept: string; bloomLevel: number }> = [];\r\n\r\n for (const prereq of prereqs) {\r\n // ensureCard creates a new card if missing (defaults: blocked=0, due_at=now)\r\n const card = ensureCard(db, prereq.requires_id, userId);\r\n\r\n // If the prerequisite card was somehow blocked with no prereqs of its own,\r\n // make sure it's unblocked and due now so it surfaces\r\n if (card.blocked === 1) {\r\n const prereqOfPrereq = db\r\n .prepare(\"SELECT COUNT(*) as n FROM prerequisites WHERE token_id = ?\")\r\n .get(prereq.requires_id) as { n: number };\r\n\r\n // Only force-unblock if it has no prerequisites of its own\r\n if (prereqOfPrereq.n === 0) {\r\n const now = new Date().toISOString();\r\n db.prepare(\r\n \"UPDATE cards SET blocked = 0, due_at = ? WHERE token_id = ? AND user_id = ?\",\r\n ).run(now, prereq.requires_id, userId);\r\n }\r\n }\r\n\r\n surfaced.push({\r\n slug: prereq.slug,\r\n concept: prereq.concept,\r\n bloomLevel: prereq.bloom_level,\r\n });\r\n }\r\n\r\n return {\r\n blockedSlug: tokenSlug,\r\n prerequisites: surfaced,\r\n };\r\n}\r\n\r\n/**\r\n * Scan all blocked cards for a user and unblock any whose prerequisites are met.\r\n *\r\n * A blocked card is ready to unblock when ALL of its direct prerequisites have:\r\n * - reps >= 1 (the user has successfully recalled it at least once)\r\n * - blocked = 0 (the prerequisite itself is not blocked)\r\n *\r\n * If a blocked card has no prerequisites at all, it is unblocked immediately\r\n * (it was likely blocked in error or its prerequisites were removed).\r\n *\r\n * @param db - Database connection\r\n * @param userId - The user whose blocked cards to check\r\n * @returns List of cards that were unblocked\r\n */\r\nexport function unblockReady(\r\n db: Database,\r\n userId: string,\r\n): UnblockResult {\r\n const blockedCards = db\r\n .prepare(\r\n `SELECT c.token_id, t.slug, t.concept\r\n FROM cards c\r\n JOIN tokens t ON t.id = c.token_id\r\n WHERE c.user_id = ? AND c.blocked = 1`,\r\n )\r\n .all(userId) as Array<{ token_id: string; slug: string; concept: string }>;\r\n\r\n const unblocked: Array<{ slug: string; concept: string }> = [];\r\n\r\n for (const card of blockedCards) {\r\n const totalPrereqs = db\r\n .prepare(\"SELECT COUNT(*) as n FROM prerequisites WHERE token_id = ?\")\r\n .get(card.token_id) as { n: number };\r\n\r\n const metPrereqs = db\r\n .prepare(\r\n `SELECT COUNT(*) as n FROM cards c\r\n JOIN prerequisites p ON p.requires_id = c.token_id\r\n WHERE p.token_id = ? AND c.user_id = ? AND c.reps >= 1 AND c.blocked = 0`,\r\n )\r\n .get(card.token_id, userId) as { n: number };\r\n\r\n if (totalPrereqs.n === 0 || metPrereqs.n === totalPrereqs.n) {\r\n const now = new Date().toISOString();\r\n db.prepare(\r\n \"UPDATE cards SET blocked = 0, due_at = ? WHERE token_id = ? AND user_id = ?\",\r\n ).run(now, card.token_id, userId);\r\n\r\n unblocked.push({ slug: card.slug, concept: card.concept });\r\n }\r\n }\r\n\r\n return { unblocked };\r\n}\r\n","/**\r\n * Cross-domain interleaving — prevents same-domain streaks in review queues.\r\n *\r\n * Given an array of items with a `domain` field, reorders them using a\r\n * round-robin strategy so that consecutive items come from different domains.\r\n * This leverages the interleaving effect: mixing topics during practice\r\n * strengthens discrimination and long-term retention.\r\n */\r\n\r\n// ── Types ────────────────────────────────────────────────────────────────────\r\n\r\nexport interface QueueItem {\r\n cardId: string;\r\n tokenId: string;\r\n domain: string;\r\n}\r\n\r\n// ── Functions ────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Reorder items so no domain appears more than `maxConsecutive` times in a row.\r\n *\r\n * Algorithm: group items by domain, then round-robin across domain groups.\r\n * Each round picks one item from each non-exhausted domain. Within a domain,\r\n * the original order is preserved (so urgency sorting survives).\r\n *\r\n * If a domain has more items than others, its extras will appear after all\r\n * other domains are exhausted — but the `maxConsecutive` cap is still\r\n * respected by inserting items from the largest remaining domains first.\r\n *\r\n * @param items - Array of items to interleave. Not mutated.\r\n * @param maxConsecutive - Max consecutive items from the same domain. Defaults to 2.\r\n * @returns A new array with the same items in interleaved order.\r\n */\r\nexport function interleave<T extends { domain: string }>(\r\n items: T[],\r\n maxConsecutive: number = 2,\r\n): T[] {\r\n if (items.length <= 1) return [...items];\r\n\r\n // Group items by domain, preserving original order within each group\r\n const byDomain = new Map<string, T[]>();\r\n for (const item of items) {\r\n const group = byDomain.get(item.domain);\r\n if (group) {\r\n group.push(item);\r\n } else {\r\n byDomain.set(item.domain, [item]);\r\n }\r\n }\r\n\r\n // If there's only one domain, no interleaving possible\r\n if (byDomain.size === 1) return [...items];\r\n\r\n const result: T[] = [];\r\n let consecutiveCount = 0;\r\n let lastDomain: string | null = null;\r\n\r\n // Track how many items we've consumed from each domain\r\n const cursors = new Map<string, number>();\r\n for (const domain of byDomain.keys()) {\r\n cursors.set(domain, 0);\r\n }\r\n\r\n // Round-robin: sort domains by remaining count (largest first) each round\r\n while (result.length < items.length) {\r\n // Get domains that still have items, sorted by remaining count descending\r\n const activeDomains = [...byDomain.entries()]\r\n .filter(([domain]) => cursors.get(domain)! < byDomain.get(domain)!.length)\r\n .sort((a, b) => {\r\n const remainA = a[1].length - cursors.get(a[0])!;\r\n const remainB = b[1].length - cursors.get(b[0])!;\r\n return remainB - remainA;\r\n });\r\n\r\n if (activeDomains.length === 0) break;\r\n\r\n let pickedThisRound = false;\r\n\r\n for (const [domain, group] of activeDomains) {\r\n const cursor = cursors.get(domain)!;\r\n if (cursor >= group.length) continue;\r\n\r\n // Check if adding from this domain would exceed maxConsecutive\r\n if (domain === lastDomain && consecutiveCount >= maxConsecutive) {\r\n // Try to find another domain first\r\n continue;\r\n }\r\n\r\n // Pick one item from this domain\r\n result.push(group[cursor]);\r\n cursors.set(domain, cursor + 1);\r\n pickedThisRound = true;\r\n\r\n if (domain === lastDomain) {\r\n consecutiveCount++;\r\n } else {\r\n lastDomain = domain;\r\n consecutiveCount = 1;\r\n }\r\n\r\n break;\r\n }\r\n\r\n // If we couldn't pick without exceeding maxConsecutive, we must accept\r\n // a streak from whatever domain has items left\r\n if (!pickedThisRound) {\r\n for (const [domain, group] of activeDomains) {\r\n const cursor = cursors.get(domain)!;\r\n if (cursor >= group.length) continue;\r\n\r\n result.push(group[cursor]);\r\n cursors.set(domain, cursor + 1);\r\n\r\n if (domain === lastDomain) {\r\n consecutiveCount++;\r\n } else {\r\n lastDomain = domain;\r\n consecutiveCount = 1;\r\n }\r\n\r\n break;\r\n }\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n","/**\r\n * Review Queue Builder — assembles a session's review queue.\r\n *\r\n * Combines due-card fetching, new-card selection, urgency sorting,\r\n * and cross-domain interleaving into a single ready-to-review queue.\r\n */\r\n\r\nimport type { Database } from \"libsql\";\r\nimport { interleave } from \"./interleaver.js\";\r\n\r\n// ── Types ────────────────────────────────────────────────────────────────────\r\n\r\nexport interface ReviewQueueOptions {\r\n userId: string;\r\n maxNew?: number; // default 10\r\n maxReviews?: number; // default 50\r\n now?: Date;\r\n}\r\n\r\nexport interface ReviewQueueItem {\r\n cardId: string;\r\n tokenId: string;\r\n slug: string;\r\n concept: string;\r\n domain: string;\r\n bloomLevel: number;\r\n state: string; // 'new' | 'learning' | 'review' | 'relearning'\r\n dueAt: string;\r\n}\r\n\r\nexport interface ReviewQueue {\r\n items: ReviewQueueItem[];\r\n newCount: number;\r\n reviewCount: number;\r\n relearnCount: number;\r\n totalDomains: string[];\r\n}\r\n\r\n// ── Internal row type from SQL queries ───────────────────────────────────────\r\n\r\ninterface CardRow {\r\n card_id: string;\r\n token_id: string;\r\n slug: string;\r\n concept: string;\r\n domain: string;\r\n bloom_level: number;\r\n state: string;\r\n due_at: string;\r\n}\r\n\r\n// ── Functions ────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Build a review queue for a user's study session.\r\n *\r\n * The queue is assembled in stages:\r\n * 1. Fetch all due cards (not blocked, due_at <= now, state in review/relearning/learning)\r\n * 2. Fetch new cards (state = 'new', not blocked) up to maxNew\r\n * 3. Sort overdue cards by urgency — most overdue first\r\n * 4. Apply cross-domain interleaving to prevent same-domain streaks\r\n * 5. Intersperse new cards at regular intervals (every 5th position)\r\n * 6. Cap total at maxReviews\r\n *\r\n * @param db - Database connection\r\n * @param options - Queue building options\r\n * @returns The assembled review queue with metadata\r\n */\r\nexport function buildReviewQueue(\r\n db: Database,\r\n options: ReviewQueueOptions,\r\n): ReviewQueue {\r\n const maxNew = options.maxNew ?? 10;\r\n const maxReviews = options.maxReviews ?? 50;\r\n const now = options.now ?? new Date();\r\n const nowISO = now.toISOString();\r\n\r\n // ── Step 1: Fetch due cards (review, relearning, learning — not new) ───\r\n const dueRows = db\r\n .prepare(\r\n `SELECT\r\n c.id AS card_id,\r\n c.token_id AS token_id,\r\n t.slug AS slug,\r\n t.concept AS concept,\r\n t.domain AS domain,\r\n t.bloom_level AS bloom_level,\r\n c.state AS state,\r\n c.due_at AS due_at\r\n FROM cards c\r\n JOIN tokens t ON t.id = c.token_id\r\n WHERE c.user_id = ?\r\n AND c.blocked = 0\r\n AND c.due_at <= ?\r\n AND c.state IN ('review', 'relearning', 'learning')\r\n AND t.deprecated_at IS NULL\r\n ORDER BY c.due_at ASC`,\r\n )\r\n .all(options.userId, nowISO) as CardRow[];\r\n\r\n // ── Step 2: Fetch new cards ────────────────────────────────────────────\r\n const newRows = db\r\n .prepare(\r\n `SELECT\r\n c.id AS card_id,\r\n c.token_id AS token_id,\r\n t.slug AS slug,\r\n t.concept AS concept,\r\n t.domain AS domain,\r\n t.bloom_level AS bloom_level,\r\n c.state AS state,\r\n c.due_at AS due_at\r\n FROM cards c\r\n JOIN tokens t ON t.id = c.token_id\r\n WHERE c.user_id = ?\r\n AND c.blocked = 0\r\n AND c.state = 'new'\r\n AND t.deprecated_at IS NULL\r\n ORDER BY t.bloom_level ASC, t.slug ASC\r\n LIMIT ?`,\r\n )\r\n .all(options.userId, maxNew) as CardRow[];\r\n\r\n // ── Step 3: Sort overdue cards by urgency (most overdue first) ─────────\r\n const nowMs = now.getTime();\r\n const sortedDue = [...dueRows].sort((a, b) => {\r\n const overdueA = nowMs - new Date(a.due_at).getTime();\r\n const overdueB = nowMs - new Date(b.due_at).getTime();\r\n return overdueB - overdueA; // most overdue first\r\n });\r\n\r\n // ── Step 4: Apply cross-domain interleaving to due cards ───────────────\r\n const interleavedDue = interleave(\r\n sortedDue.map((row) => ({ ...rowToItem(row), domain: row.domain })),\r\n );\r\n\r\n // ── Step 5: Intersperse new cards at regular intervals ─────────────────\r\n const newItems = newRows.map(rowToItem);\r\n const merged = intersperseNew(interleavedDue, newItems, 5);\r\n\r\n // ── Step 6: Cap total at maxReviews ────────────────────────────────────\r\n const capped = merged.slice(0, maxReviews);\r\n\r\n // ── Compute metadata ──────────────────────────────────────────────────\r\n let newCount = 0;\r\n let reviewCount = 0;\r\n let relearnCount = 0;\r\n const domainSet = new Set<string>();\r\n\r\n for (const item of capped) {\r\n domainSet.add(item.domain);\r\n switch (item.state) {\r\n case \"new\":\r\n newCount++;\r\n break;\r\n case \"relearning\":\r\n relearnCount++;\r\n break;\r\n default:\r\n reviewCount++;\r\n break;\r\n }\r\n }\r\n\r\n return {\r\n items: capped,\r\n newCount,\r\n reviewCount,\r\n relearnCount,\r\n totalDomains: [...domainSet].sort(),\r\n };\r\n}\r\n\r\n// ── Helpers ──────────────────────────────────────────────────────────────────\r\n\r\n/** Convert a SQL row to a ReviewQueueItem. */\r\nfunction rowToItem(row: CardRow): ReviewQueueItem {\r\n return {\r\n cardId: row.card_id,\r\n tokenId: row.token_id,\r\n slug: row.slug,\r\n concept: row.concept,\r\n domain: row.domain,\r\n bloomLevel: row.bloom_level,\r\n state: row.state,\r\n dueAt: row.due_at,\r\n };\r\n}\r\n\r\n/**\r\n * Intersperse new cards into the review queue at regular intervals.\r\n *\r\n * Instead of front-loading or back-loading new cards, places one new card\r\n * every `interval` positions (e.g., positions 4, 9, 14, ...).\r\n * This gives the user a mix of familiar reviews and new material.\r\n *\r\n * @param reviews - The interleaved review cards\r\n * @param newCards - New cards to intersperse\r\n * @param interval - Place a new card every N positions (default 5)\r\n * @returns Merged array with new cards interspersed\r\n */\r\nfunction intersperseNew(\r\n reviews: ReviewQueueItem[],\r\n newCards: ReviewQueueItem[],\r\n interval: number,\r\n): ReviewQueueItem[] {\r\n if (newCards.length === 0) return [...reviews];\r\n if (reviews.length === 0) return [...newCards];\r\n\r\n const result: ReviewQueueItem[] = [];\r\n let reviewIdx = 0;\r\n let newIdx = 0;\r\n\r\n // Position counter tracks where we are in the final queue\r\n let position = 0;\r\n\r\n while (reviewIdx < reviews.length || newIdx < newCards.length) {\r\n // Insert a new card every `interval` positions (0-indexed: at 4, 9, 14, ...)\r\n if (\r\n newIdx < newCards.length &&\r\n position > 0 &&\r\n position % interval === interval - 1\r\n ) {\r\n result.push(newCards[newIdx]);\r\n newIdx++;\r\n } else if (reviewIdx < reviews.length) {\r\n result.push(reviews[reviewIdx]);\r\n reviewIdx++;\r\n } else if (newIdx < newCards.length) {\r\n // No more reviews — append remaining new cards\r\n result.push(newCards[newIdx]);\r\n newIdx++;\r\n }\r\n\r\n position++;\r\n }\r\n\r\n return result;\r\n}\r\n","/**\r\n * Active Recall Prompt Generation\r\n *\r\n * Generates review prompts from tokens, adapting the question style\r\n * to the token's Bloom taxonomy level. This is NOT an LLM call —\r\n * it's template-based prompt assembly for the CLI and bridge.\r\n */\r\n\r\nexport type BloomLevel = 1 | 2 | 3 | 4 | 5;\r\n\r\nexport interface RecallPrompt {\r\n cardId: string;\r\n tokenId: string;\r\n slug: string;\r\n question: string;\r\n concept: string;\r\n domain: string;\r\n bloomLevel: BloomLevel;\r\n bloomVerb: string;\r\n hints: string[];\r\n}\r\n\r\nconst BLOOM_VERBS: Record<BloomLevel, string> = {\r\n 1: \"Remember\",\r\n 2: \"Understand\",\r\n 3: \"Apply\",\r\n 4: \"Analyze\",\r\n 5: \"Synthesize\",\r\n};\r\n\r\nconst BLOOM_PROMPTS: Record<BloomLevel, (concept: string) => string> = {\r\n 1: (c) => `What is: ${c}?`,\r\n 2: (c) => `Explain how this works: ${c}`,\r\n 3: (c) => `Apply this concept: ${c}`,\r\n 4: (c) => `Analyze the trade-offs: ${c}`,\r\n 5: (c) => `Design a solution using: ${c}`,\r\n};\r\n\r\nexport interface PromptInput {\r\n cardId: string;\r\n tokenId: string;\r\n slug: string;\r\n concept: string;\r\n domain: string;\r\n bloomLevel: BloomLevel;\r\n}\r\n\r\n/**\r\n * Generate a recall prompt for a token at its Bloom level.\r\n * When called from the CLI, the prompt is rendered in the terminal.\r\n * When called from the AI bridge, the JSON is returned for the AI to present conversationally.\r\n */\r\nexport function generatePrompt(input: PromptInput): RecallPrompt {\r\n const bloom = (input.bloomLevel >= 1 && input.bloomLevel <= 5\r\n ? input.bloomLevel\r\n : 1) as BloomLevel;\r\n\r\n return {\r\n cardId: input.cardId,\r\n tokenId: input.tokenId,\r\n slug: input.slug,\r\n question: BLOOM_PROMPTS[bloom](input.concept),\r\n concept: input.concept,\r\n domain: input.domain,\r\n bloomLevel: bloom,\r\n bloomVerb: BLOOM_VERBS[bloom],\r\n hints: [],\r\n };\r\n}\r\n","/**\r\n * Rating Evaluator\r\n *\r\n * Processes a user's self-assessment rating after a recall attempt.\r\n * Coordinates between FSRS scheduling, review logging, and blocking.\r\n */\r\n\r\nimport type { Database } from \"libsql\";\r\nimport { ulid } from \"ulid\";\r\nimport { updateCard } from \"../models/card.js\";\r\nimport type { Rating, SchedulingCard } from \"../scheduler/fsrs.js\";\r\nimport { createFSRS } from \"../scheduler/fsrs.js\";\r\n\r\nexport interface EvaluateInput {\r\n cardId: string;\r\n tokenId: string;\r\n userId: string;\r\n rating: Rating;\r\n sessionId?: string;\r\n responseTimeMs?: number;\r\n}\r\n\r\nexport interface EvaluateResult {\r\n nextDueAt: string;\r\n stability: number;\r\n difficulty: number;\r\n state: string;\r\n scheduledDays: number;\r\n reps: number;\r\n lapses: number;\r\n}\r\n\r\n/**\r\n * Process a rating: update the card via FSRS, log the review.\r\n * Returns the updated scheduling state.\r\n *\r\n * Note: blocking logic (cascade-block) is handled separately by the caller\r\n * when rating === 1 and the token has prerequisites.\r\n */\r\nexport function evaluateRating(\r\n db: Database,\r\n input: EvaluateInput,\r\n): EvaluateResult {\r\n // Get current card state\r\n const card = db\r\n .prepare(\"SELECT * FROM cards WHERE id = ?\")\r\n .get(input.cardId) as {\r\n stability: number;\r\n difficulty: number;\r\n elapsed_days: number;\r\n scheduled_days: number;\r\n reps: number;\r\n lapses: number;\r\n state: string;\r\n due_at: string;\r\n last_review_at: string | null;\r\n } | undefined;\r\n\r\n if (!card) {\r\n throw new Error(`Card not found: ${input.cardId}`);\r\n }\r\n\r\n const now = new Date();\r\n const fsrs = createFSRS();\r\n\r\n // Build scheduling card from DB state\r\n const schedulingCard: SchedulingCard = {\r\n stability: card.stability,\r\n difficulty: card.difficulty,\r\n elapsedDays: card.elapsed_days,\r\n scheduledDays: card.scheduled_days,\r\n reps: card.reps,\r\n lapses: card.lapses,\r\n state: card.state as SchedulingCard[\"state\"],\r\n dueAt: new Date(card.due_at),\r\n lastReviewAt: card.last_review_at ? new Date(card.last_review_at) : null,\r\n };\r\n\r\n // Run FSRS\r\n const updated = fsrs.schedule(schedulingCard, input.rating, now);\r\n\r\n // Update the card in the DB\r\n updateCard(db, input.cardId, {\r\n stability: updated.stability,\r\n difficulty: updated.difficulty,\r\n elapsed_days: updated.elapsedDays,\r\n scheduled_days: updated.scheduledDays,\r\n reps: updated.reps,\r\n lapses: updated.lapses,\r\n state: updated.state,\r\n due_at: updated.dueAt.toISOString(),\r\n last_review_at: now.toISOString(),\r\n });\r\n\r\n // Log the review (immutable)\r\n db.prepare(\r\n `INSERT INTO review_logs (id, card_id, token_id, user_id, rating, response_time_ms, reviewed_at, scheduled_at, session_id)\r\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,\r\n ).run(\r\n ulid(),\r\n input.cardId,\r\n input.tokenId,\r\n input.userId,\r\n input.rating,\r\n input.responseTimeMs ?? null,\r\n now.toISOString(),\r\n card.due_at,\r\n input.sessionId ?? null,\r\n );\r\n\r\n return {\r\n nextDueAt: updated.dueAt.toISOString(),\r\n stability: updated.stability,\r\n difficulty: updated.difficulty,\r\n state: updated.state,\r\n scheduledDays: updated.scheduledDays,\r\n reps: updated.reps,\r\n lapses: updated.lapses,\r\n };\r\n}\r\n","/**\r\n * Learning Analytics\r\n *\r\n * Progress statistics, competence tracking, and session summaries.\r\n * Ported from PoC's `stats` command with additions for FSRS and symbiosis modes.\r\n */\r\n\r\nimport type { Database } from \"libsql\";\r\n\r\nexport interface UserStats {\r\n userId: string;\r\n totalTokens: number;\r\n cardsInDeck: number;\r\n dueToday: number;\r\n blocked: number;\r\n mature: number;\r\n avgStability: number | null;\r\n totalSessions: number;\r\n lastSession: string | null;\r\n}\r\n\r\nexport interface DomainCompetence {\r\n domain: string;\r\n totalCards: number;\r\n matureCards: number;\r\n avgStability: number;\r\n retentionRate: number;\r\n suggestedMode: \"shadowing\" | \"copilot\" | \"autonomy\";\r\n}\r\n\r\nfunction q(db: Database, sql: string, ...params: unknown[]) {\r\n return db.prepare(sql).get(...params) as Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * Get overall learning stats for a user (ported from PoC's `stats` command).\r\n */\r\nexport function getUserStats(db: Database, userId: string): UserStats {\r\n return {\r\n userId,\r\n totalTokens: (q(db, \"SELECT COUNT(*) as n FROM tokens\") as { n: number }).n,\r\n cardsInDeck: (q(db, \"SELECT COUNT(*) as n FROM cards WHERE user_id = ?\", userId) as { n: number }).n,\r\n dueToday: (q(\r\n db,\r\n \"SELECT COUNT(*) as n FROM cards WHERE user_id = ? AND blocked = 0 AND due_at <= datetime('now')\",\r\n userId,\r\n ) as { n: number }).n,\r\n blocked: (q(db, \"SELECT COUNT(*) as n FROM cards WHERE user_id = ? AND blocked = 1\", userId) as { n: number }).n,\r\n mature: (q(\r\n db,\r\n \"SELECT COUNT(*) as n FROM cards WHERE user_id = ? AND reps >= 3 AND stability >= 21\",\r\n userId,\r\n ) as { n: number }).n,\r\n avgStability: (() => {\r\n const v = q(db, \"SELECT AVG(stability) as v FROM cards WHERE user_id = ? AND reps > 0\", userId) as { v: number | null };\r\n return v.v ? Math.round(v.v * 100) / 100 : null;\r\n })(),\r\n totalSessions: (q(db, \"SELECT COUNT(*) as n FROM sessions WHERE user_id = ?\", userId) as { n: number }).n,\r\n lastSession: (() => {\r\n const r = db\r\n .prepare(\r\n \"SELECT started_at FROM sessions WHERE user_id = ? ORDER BY started_at DESC LIMIT 1\",\r\n )\r\n .get(userId) as { started_at: string } | undefined;\r\n return r?.started_at ?? null;\r\n })(),\r\n };\r\n}\r\n\r\n/**\r\n * Get competence per domain for a user.\r\n * Used to suggest symbiosis mode transitions.\r\n */\r\nexport function getDomainCompetence(\r\n db: Database,\r\n userId: string,\r\n): DomainCompetence[] {\r\n const domains = db\r\n .prepare(\r\n `SELECT DISTINCT t.domain FROM cards c\r\n JOIN tokens t ON t.id = c.token_id\r\n WHERE c.user_id = ? AND t.domain != ''`,\r\n )\r\n .all(userId) as { domain: string }[];\r\n\r\n return domains.map((d) => {\r\n const total = (q(\r\n db,\r\n `SELECT COUNT(*) as n FROM cards c\r\n JOIN tokens t ON t.id = c.token_id\r\n WHERE c.user_id = ? AND t.domain = ?`,\r\n userId,\r\n d.domain,\r\n ) as { n: number }).n;\r\n\r\n const mature = (q(\r\n db,\r\n `SELECT COUNT(*) as n FROM cards c\r\n JOIN tokens t ON t.id = c.token_id\r\n WHERE c.user_id = ? AND t.domain = ? AND c.reps >= 3 AND c.stability >= 21`,\r\n userId,\r\n d.domain,\r\n ) as { n: number }).n;\r\n\r\n const avgStab = (q(\r\n db,\r\n `SELECT AVG(c.stability) as v FROM cards c\r\n JOIN tokens t ON t.id = c.token_id\r\n WHERE c.user_id = ? AND t.domain = ? AND c.reps > 0`,\r\n userId,\r\n d.domain,\r\n ) as { v: number | null }).v ?? 0;\r\n\r\n // Estimate retention from review history\r\n const reviews = q(\r\n db,\r\n `SELECT COUNT(*) as total,\r\n SUM(CASE WHEN rating >= 2 THEN 1 ELSE 0 END) as passed\r\n FROM review_logs\r\n WHERE user_id = ? AND token_id IN (SELECT id FROM tokens WHERE domain = ?)`,\r\n userId,\r\n d.domain,\r\n ) as { total: number; passed: number };\r\n\r\n const retentionRate =\r\n reviews.total > 0 ? reviews.passed / reviews.total : 0;\r\n\r\n let suggestedMode: DomainCompetence[\"suggestedMode\"];\r\n if (retentionRate > 0.9 && avgStab > 30) {\r\n suggestedMode = \"autonomy\";\r\n } else if (retentionRate > 0.7 && avgStab > 7) {\r\n suggestedMode = \"copilot\";\r\n } else {\r\n suggestedMode = \"shadowing\";\r\n }\r\n\r\n return {\r\n domain: d.domain,\r\n totalCards: total,\r\n matureCards: mature,\r\n avgStability: Math.round(avgStab * 100) / 100,\r\n retentionRate: Math.round(retentionRate * 1000) / 1000,\r\n suggestedMode,\r\n };\r\n });\r\n}\r\n","/**\r\n * Monitor log analyzer — maps observed shell commands to token ratings.\r\n *\r\n * Pure functions, no DB or filesystem access. Takes parsed command records\r\n * and a token-to-pattern mapping, returns ratings with evidence.\r\n */\r\n\r\n// ── Types ────────────────────────────────────────────────────────────────────\r\n\r\nexport interface MonitorEvent {\r\n type: \"command_start\" | \"command_end\" | \"monitor_meta\";\r\n ts: string;\r\n seq?: number;\r\n pid?: number;\r\n command?: string;\r\n cwd?: string;\r\n exit_code?: number;\r\n event?: \"start\" | \"stop\";\r\n session_id?: string;\r\n shell?: string;\r\n}\r\n\r\nexport interface CommandRecord {\r\n seq: number;\r\n pid: number;\r\n command: string;\r\n cwd: string;\r\n startedAt: string;\r\n endedAt: string | null;\r\n durationMs: number | null;\r\n exitCode: number | null;\r\n}\r\n\r\nexport interface TokenPattern {\r\n slug: string;\r\n patterns: string[]; // command prefixes or regex strings\r\n}\r\n\r\nexport interface ObservationRating {\r\n tokenSlug: string;\r\n rating: 1 | 2 | 3 | 4 | null;\r\n confidence: \"high\" | \"medium\" | \"low\";\r\n evidence: {\r\n matchedCommands: number;\r\n helpSeeking: boolean;\r\n errorCount: number;\r\n selfCorrections: number;\r\n medianGapMs: number | null;\r\n thinkingGapMs: number | null;\r\n };\r\n matchedCommandTexts: string[];\r\n}\r\n\r\nexport interface AnalysisResult {\r\n ratings: ObservationRating[];\r\n unmatchedCommands: string[];\r\n timeSpan: { start: string; end: string; durationMs: number } | null;\r\n}\r\n\r\n// ── Parsing ──────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Parse a JSONL string into MonitorEvent objects.\r\n * Skips malformed lines silently.\r\n */\r\nexport function parseMonitorLog(jsonl: string): MonitorEvent[] {\r\n const events: MonitorEvent[] = [];\r\n for (const line of jsonl.split(\"\\n\")) {\r\n const trimmed = line.trim();\r\n if (!trimmed) continue;\r\n try {\r\n events.push(JSON.parse(trimmed) as MonitorEvent);\r\n } catch {\r\n // skip malformed lines\r\n }\r\n }\r\n return events;\r\n}\r\n\r\n/**\r\n * Pair command_start and command_end events by (pid, seq) into CommandRecords.\r\n */\r\nexport function pairCommands(events: MonitorEvent[]): CommandRecord[] {\r\n const starts = new Map<string, MonitorEvent>();\r\n const records: CommandRecord[] = [];\r\n\r\n for (const e of events) {\r\n if (e.type === \"command_start\" && e.seq != null) {\r\n const key = `${e.pid ?? 0}:${e.seq}`;\r\n starts.set(key, e);\r\n } else if (e.type === \"command_end\" && e.seq != null) {\r\n const key = `${e.pid ?? 0}:${e.seq}`;\r\n const start = starts.get(key);\r\n if (start) {\r\n const startMs = new Date(start.ts).getTime();\r\n const endMs = new Date(e.ts).getTime();\r\n records.push({\r\n seq: e.seq,\r\n pid: e.pid ?? 0,\r\n command: start.command ?? \"\",\r\n cwd: start.cwd ?? \"\",\r\n startedAt: start.ts,\r\n endedAt: e.ts,\r\n durationMs: endMs - startMs,\r\n exitCode: e.exit_code ?? null,\r\n });\r\n starts.delete(key);\r\n }\r\n }\r\n }\r\n\r\n // Remaining unpaired starts (monitoring stopped mid-command)\r\n for (const [, start] of starts) {\r\n records.push({\r\n seq: start.seq ?? 0,\r\n pid: start.pid ?? 0,\r\n command: start.command ?? \"\",\r\n cwd: start.cwd ?? \"\",\r\n startedAt: start.ts,\r\n endedAt: null,\r\n durationMs: null,\r\n exitCode: null,\r\n });\r\n }\r\n\r\n records.sort((a, b) => new Date(a.startedAt).getTime() - new Date(b.startedAt).getTime());\r\n return records;\r\n}\r\n\r\n// ── Analysis ─────────────────────────────────────────────────────────────────\r\n\r\nconst HELP_PATTERNS = [\"--help\", \"man \", \"tldr \", \"help \"];\r\nconst HELP_WINDOW_MS = 60_000;\r\nconst RETRY_WINDOW_MS = 30_000;\r\n\r\nfunction matchesToken(command: string, patterns: string[]): boolean {\r\n const lower = command.toLowerCase();\r\n return patterns.some((p) => lower.includes(p.toLowerCase()));\r\n}\r\n\r\nfunction isHelpCommand(command: string): boolean {\r\n const lower = command.toLowerCase();\r\n return HELP_PATTERNS.some((p) => lower.includes(p));\r\n}\r\n\r\nfunction commandPrefix(command: string): string {\r\n return command.split(/\\s+/).slice(0, 2).join(\" \").toLowerCase();\r\n}\r\n\r\nfunction computeMedian(values: number[]): number | null {\r\n if (values.length === 0) return null;\r\n const sorted = [...values].sort((a, b) => a - b);\r\n const mid = Math.floor(sorted.length / 2);\r\n return sorted.length % 2 !== 0 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;\r\n}\r\n\r\n/**\r\n * Analyze observed commands against token patterns and produce ratings.\r\n */\r\nexport function analyzeObservation(\r\n commands: CommandRecord[],\r\n tokenPatterns: TokenPattern[],\r\n): AnalysisResult {\r\n const matchedSet = new Set<number>(); // indices of commands matched to any token\r\n const ratings: ObservationRating[] = [];\r\n\r\n for (const tp of tokenPatterns) {\r\n const matchIndices: number[] = [];\r\n const matchedTexts: string[] = [];\r\n\r\n for (let i = 0; i < commands.length; i++) {\r\n if (matchesToken(commands[i].command, tp.patterns)) {\r\n matchIndices.push(i);\r\n matchedTexts.push(commands[i].command);\r\n matchedSet.add(i);\r\n }\r\n }\r\n\r\n if (matchIndices.length === 0) {\r\n ratings.push({\r\n tokenSlug: tp.slug,\r\n rating: null,\r\n confidence: \"low\",\r\n evidence: {\r\n matchedCommands: 0,\r\n helpSeeking: false,\r\n errorCount: 0,\r\n selfCorrections: 0,\r\n medianGapMs: null,\r\n thinkingGapMs: null,\r\n },\r\n matchedCommandTexts: [],\r\n });\r\n continue;\r\n }\r\n\r\n // Help-seeking: any help command within HELP_WINDOW_MS before a matched command\r\n let helpSeeking = false;\r\n for (const mi of matchIndices) {\r\n const matchTime = new Date(commands[mi].startedAt).getTime();\r\n for (let j = 0; j < commands.length; j++) {\r\n if (j === mi) continue;\r\n const cmdTime = new Date(commands[j].startedAt).getTime();\r\n if (cmdTime >= matchTime - HELP_WINDOW_MS && cmdTime < matchTime) {\r\n if (isHelpCommand(commands[j].command)) {\r\n helpSeeking = true;\r\n break;\r\n }\r\n }\r\n }\r\n if (helpSeeking) break;\r\n }\r\n\r\n // Error count: matched commands with non-zero exit code\r\n let errorCount = 0;\r\n for (const mi of matchIndices) {\r\n if (commands[mi].exitCode != null && commands[mi].exitCode !== 0) {\r\n errorCount++;\r\n }\r\n }\r\n\r\n // Self-corrections: same command prefix run multiple times with different args\r\n let selfCorrections = 0;\r\n const prefixGroups = new Map<string, number>();\r\n for (const mi of matchIndices) {\r\n const prefix = commandPrefix(commands[mi].command);\r\n prefixGroups.set(prefix, (prefixGroups.get(prefix) ?? 0) + 1);\r\n }\r\n for (const count of prefixGroups.values()) {\r\n if (count > 1) selfCorrections += count - 1;\r\n }\r\n\r\n // Speed: inter-command gaps between matched commands\r\n const gaps: number[] = [];\r\n for (let k = 1; k < matchIndices.length; k++) {\r\n const prev = commands[matchIndices[k - 1]];\r\n const curr = commands[matchIndices[k]];\r\n if (prev.endedAt) {\r\n const gap = new Date(curr.startedAt).getTime() - new Date(prev.endedAt).getTime();\r\n if (gap >= 0) gaps.push(gap);\r\n }\r\n }\r\n\r\n // Thinking gap: time before first matched command from previous command's end\r\n let thinkingGapMs: number | null = null;\r\n const firstMatchIdx = matchIndices[0];\r\n if (firstMatchIdx > 0) {\r\n const prev = commands[firstMatchIdx - 1];\r\n if (prev.endedAt) {\r\n thinkingGapMs =\r\n new Date(commands[firstMatchIdx].startedAt).getTime() -\r\n new Date(prev.endedAt).getTime();\r\n }\r\n }\r\n\r\n const medianGapMs = computeMedian(gaps);\r\n\r\n // Determine rating\r\n const rating = inferRating({\r\n helpSeeking,\r\n errorCount,\r\n selfCorrections,\r\n medianGapMs,\r\n thinkingGapMs,\r\n matchedCommands: matchIndices.length,\r\n });\r\n\r\n // Confidence: more matched commands = higher confidence\r\n const confidence =\r\n matchIndices.length >= 3 ? \"high\" : matchIndices.length >= 2 ? \"medium\" : \"low\";\r\n\r\n ratings.push({\r\n tokenSlug: tp.slug,\r\n rating,\r\n confidence,\r\n evidence: {\r\n matchedCommands: matchIndices.length,\r\n helpSeeking,\r\n errorCount,\r\n selfCorrections,\r\n medianGapMs,\r\n thinkingGapMs,\r\n },\r\n matchedCommandTexts: matchedTexts,\r\n });\r\n }\r\n\r\n // Unmatched commands\r\n const unmatchedCommands: string[] = [];\r\n for (let i = 0; i < commands.length; i++) {\r\n if (!matchedSet.has(i) && !isHelpCommand(commands[i].command)) {\r\n unmatchedCommands.push(commands[i].command);\r\n }\r\n }\r\n\r\n // Time span\r\n let timeSpan: AnalysisResult[\"timeSpan\"] = null;\r\n if (commands.length > 0) {\r\n const first = commands[0];\r\n const last = commands[commands.length - 1];\r\n const endTs = last.endedAt ?? last.startedAt;\r\n timeSpan = {\r\n start: first.startedAt,\r\n end: endTs,\r\n durationMs: new Date(endTs).getTime() - new Date(first.startedAt).getTime(),\r\n };\r\n }\r\n\r\n return { ratings, unmatchedCommands, timeSpan };\r\n}\r\n\r\n// ── Rating Inference ─────────────────────────────────────────────────────────\r\n\r\ninterface RatingSignals {\r\n helpSeeking: boolean;\r\n errorCount: number;\r\n selfCorrections: number;\r\n medianGapMs: number | null;\r\n thinkingGapMs: number | null;\r\n matchedCommands: number;\r\n}\r\n\r\nfunction inferRating(signals: RatingSignals): 1 | 2 | 3 | 4 {\r\n const { helpSeeking, errorCount, selfCorrections, medianGapMs, thinkingGapMs } = signals;\r\n\r\n // Count negative signals\r\n let negatives = 0;\r\n if (helpSeeking) negatives += 2;\r\n if (errorCount >= 3) negatives += 3;\r\n else if (errorCount >= 1) negatives += 1;\r\n if (selfCorrections >= 2) negatives += 2;\r\n else if (selfCorrections >= 1) negatives += 1;\r\n if (medianGapMs != null && medianGapMs > 30_000) negatives += 2;\r\n else if (medianGapMs != null && medianGapMs > 10_000) negatives += 1;\r\n if (thinkingGapMs != null && thinkingGapMs > 30_000) negatives += 1;\r\n\r\n if (negatives >= 5) return 1;\r\n if (negatives >= 3) return 2;\r\n if (negatives >= 1) return 3;\r\n return 4;\r\n}\r\n","/**\r\n * Monitor I/O — read/write JSONL files for shell observation.\r\n *\r\n * Monitor logs live at ~/.zam/monitor/<session-id>.jsonl.\r\n * Separated from analyzer.ts so the analyzer remains pure-function testable.\r\n */\r\n\r\nimport { existsSync, mkdirSync, readFileSync, appendFileSync, statSync } from \"node:fs\";\r\nimport { homedir } from \"node:os\";\r\nimport { join } from \"node:path\";\r\nimport type { MonitorEvent } from \"./analyzer.js\";\r\nimport { parseMonitorLog } from \"./analyzer.js\";\r\n\r\nconst MONITOR_DIR = join(homedir(), \".zam\", \"monitor\");\r\n\r\n/** Get the monitor directory path. */\r\nexport function getMonitorDir(): string {\r\n return MONITOR_DIR;\r\n}\r\n\r\n/** Get the JSONL file path for a session. */\r\nexport function getMonitorPath(sessionId: string): string {\r\n return join(MONITOR_DIR, `${sessionId}.jsonl`);\r\n}\r\n\r\n/** Ensure the monitor directory exists (mode 0700 for privacy). */\r\nexport function ensureMonitorDir(): void {\r\n if (!existsSync(MONITOR_DIR)) {\r\n mkdirSync(MONITOR_DIR, { recursive: true, mode: 0o700 });\r\n }\r\n}\r\n\r\n/** Append a single event to the session's JSONL file. */\r\nexport function writeMonitorEvent(sessionId: string, event: MonitorEvent): void {\r\n ensureMonitorDir();\r\n const path = getMonitorPath(sessionId);\r\n appendFileSync(path, JSON.stringify(event) + \"\\n\");\r\n}\r\n\r\n/** Read and parse all events from a session's monitor log. */\r\nexport function readMonitorLog(sessionId: string): MonitorEvent[] {\r\n const path = getMonitorPath(sessionId);\r\n if (!existsSync(path)) {\r\n return [];\r\n }\r\n const content = readFileSync(path, \"utf-8\");\r\n return parseMonitorLog(content);\r\n}\r\n\r\n/** Check if a monitor log exists for a session. */\r\nexport function monitorLogExists(sessionId: string): boolean {\r\n return existsSync(getMonitorPath(sessionId));\r\n}\r\n\r\n/** Get basic stats about a monitor log without full parsing. */\r\nexport function getMonitorLogStats(sessionId: string): {\r\n exists: boolean;\r\n sizeBytes: number;\r\n lineCount: number;\r\n} {\r\n const path = getMonitorPath(sessionId);\r\n if (!existsSync(path)) {\r\n return { exists: false, sizeBytes: 0, lineCount: 0 };\r\n }\r\n const stat = statSync(path);\r\n const content = readFileSync(path, \"utf-8\");\r\n const lineCount = content.split(\"\\n\").filter((l) => l.trim()).length;\r\n return { exists: true, sizeBytes: stat.size, lineCount };\r\n}\r\n","/**\r\n * Shell hook code generation for zsh and bash.\r\n *\r\n * Pure functions that return shell code strings. The CLI command\r\n * `zam monitor start/stop` calls these and prints to stdout.\r\n * The user wraps with `eval \"$(zam monitor start ...)\"`.\r\n */\r\n\r\n/**\r\n * Generate zsh hooks that capture commands to a JSONL file.\r\n * Uses $EPOCHREALTIME for sub-second timestamp precision.\r\n */\r\nexport function generateZshHooks(monitorFile: string, sessionId: string): string {\r\n return `\r\n# ZAM monitor hooks for session ${sessionId}\r\nexport __ZAM_MONITOR_FILE=\"${monitorFile}\"\r\nexport __ZAM_MONITOR_SEQ=0\r\nexport __ZAM_MONITOR_SESSION=\"${sessionId}\"\r\n\r\n__zam_ts() {\r\n if [[ -n \"\\${EPOCHREALTIME:-}\" ]]; then\r\n local sec=\"\\${EPOCHREALTIME%%.*}\"\r\n local frac=\"\\${EPOCHREALTIME##*.}\"\r\n frac=\"\\${frac:0:3}\"\r\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\"\r\n else\r\n date -u '+%Y-%m-%dT%H:%M:%SZ'\r\n fi\r\n}\r\n\r\n__zam_preexec() {\r\n (( __ZAM_MONITOR_SEQ++ ))\r\n local cmd=\"\\${1//\\\\\"/\\\\\\\\\\\\\"}\"\r\n local cwd=\"\\${PWD//\\\\\"/\\\\\\\\\\\\\"}\"\r\n local ts=\"$(__zam_ts)\"\r\n printf '{\"type\":\"command_start\",\"ts\":\"%s\",\"command\":\"%s\",\"cwd\":\"%s\",\"seq\":%d,\"pid\":%d}\\\\n' \\\\\r\n \"\\$ts\" \"\\$cmd\" \"\\$cwd\" \"\\$__ZAM_MONITOR_SEQ\" \"\\$\\$\" \\\\\r\n >> \"\\$__ZAM_MONITOR_FILE\"\r\n}\r\n\r\n__zam_precmd() {\r\n local exit_code=\\$?\r\n [[ \\$__ZAM_MONITOR_SEQ -eq 0 ]] && return\r\n local ts=\"$(__zam_ts)\"\r\n printf '{\"type\":\"command_end\",\"ts\":\"%s\",\"exit_code\":%d,\"seq\":%d,\"pid\":%d}\\\\n' \\\\\r\n \"\\$ts\" \"\\$exit_code\" \"\\$__ZAM_MONITOR_SEQ\" \"\\$\\$\" \\\\\r\n >> \"\\$__ZAM_MONITOR_FILE\"\r\n}\r\n\r\nautoload -Uz add-zsh-hook\r\nadd-zsh-hook preexec __zam_preexec\r\nadd-zsh-hook precmd __zam_precmd\r\n\r\necho \"ZAM monitor active for session \\$__ZAM_MONITOR_SESSION\"\r\n`.trim();\r\n}\r\n\r\n/**\r\n * Generate bash hooks that capture commands to a JSONL file.\r\n * Uses DEBUG trap for preexec, PROMPT_COMMAND for precmd.\r\n */\r\nexport function generateBashHooks(monitorFile: string, sessionId: string): string {\r\n return `\r\n# ZAM monitor hooks for session ${sessionId}\r\nexport __ZAM_MONITOR_FILE=\"${monitorFile}\"\r\nexport __ZAM_MONITOR_SEQ=0\r\nexport __ZAM_MONITOR_SESSION=\"${sessionId}\"\r\nexport __ZAM_MONITOR_CMD_ACTIVE=0\r\n\r\n__zam_ts() {\r\n date -u '+%Y-%m-%dT%H:%M:%SZ'\r\n}\r\n\r\n__zam_debug_trap() {\r\n [[ \"\\$__ZAM_MONITOR_CMD_ACTIVE\" -eq 1 ]] && return\r\n __ZAM_MONITOR_CMD_ACTIVE=1\r\n (( __ZAM_MONITOR_SEQ++ ))\r\n local cmd=\"\\${BASH_COMMAND//\\\\\"/\\\\\\\\\\\\\"}\"\r\n local cwd=\"\\${PWD//\\\\\"/\\\\\\\\\\\\\"}\"\r\n local ts=\"$(__zam_ts)\"\r\n printf '{\"type\":\"command_start\",\"ts\":\"%s\",\"command\":\"%s\",\"cwd\":\"%s\",\"seq\":%d,\"pid\":%d}\\\\n' \\\\\r\n \"\\$ts\" \"\\$cmd\" \"\\$cwd\" \"\\$__ZAM_MONITOR_SEQ\" \"\\$\\$\" \\\\\r\n >> \"\\$__ZAM_MONITOR_FILE\"\r\n}\r\n\r\n__zam_prompt_cmd() {\r\n local exit_code=\\$?\r\n if [[ \"\\$__ZAM_MONITOR_CMD_ACTIVE\" -eq 1 ]]; then\r\n __ZAM_MONITOR_CMD_ACTIVE=0\r\n local ts=\"$(__zam_ts)\"\r\n printf '{\"type\":\"command_end\",\"ts\":\"%s\",\"exit_code\":%d,\"seq\":%d,\"pid\":%d}\\\\n' \\\\\r\n \"\\$ts\" \"\\$exit_code\" \"\\$__ZAM_MONITOR_SEQ\" \"\\$\\$\" \\\\\r\n >> \"\\$__ZAM_MONITOR_FILE\"\r\n fi\r\n}\r\n\r\ntrap '__zam_debug_trap' DEBUG\r\nPROMPT_COMMAND=\"__zam_prompt_cmd;\\${PROMPT_COMMAND:-}\"\r\n\r\necho \"ZAM monitor active for session \\$__ZAM_MONITOR_SESSION\"\r\n`.trim();\r\n}\r\n\r\n/** Generate zsh code to remove monitor hooks. */\r\nexport function generateZshUnhooks(): string {\r\n return `\r\n# Remove ZAM monitor hooks\r\nadd-zsh-hook -d preexec __zam_preexec 2>/dev/null\r\nadd-zsh-hook -d precmd __zam_precmd 2>/dev/null\r\nunset -f __zam_preexec __zam_precmd __zam_ts 2>/dev/null\r\nunset __ZAM_MONITOR_FILE __ZAM_MONITOR_SEQ __ZAM_MONITOR_SESSION 2>/dev/null\r\necho \"ZAM monitor stopped.\"\r\n`.trim();\r\n}\r\n\r\n/** Generate bash code to remove monitor hooks. */\r\nexport function generateBashUnhooks(): string {\r\n return `\r\n# Remove ZAM monitor hooks\r\ntrap - DEBUG\r\nPROMPT_COMMAND=\"\\${PROMPT_COMMAND/__zam_prompt_cmd;/}\"\r\nunset -f __zam_debug_trap __zam_prompt_cmd __zam_ts 2>/dev/null\r\nunset __ZAM_MONITOR_FILE __ZAM_MONITOR_SEQ __ZAM_MONITOR_SESSION __ZAM_MONITOR_CMD_ACTIVE 2>/dev/null\r\necho \"ZAM monitor stopped.\"\r\n`.trim();\r\n}\r\n","/**\r\n * Skill Discovery — identifies recurring non-standard command patterns\r\n * across multiple sessions and proposes them as minimal reusable skills.\r\n *\r\n * The key insight from Increment 2: \"The human's demonstrated competence\r\n * is the gate for automation — not the other way around.\" A pattern must\r\n * appear consistently across sessions before being proposed as a skill.\r\n *\r\n * Pure functions — no DB access. Callers provide command records and\r\n * existing skills; this module returns proposed skills.\r\n */\r\n\r\nimport type { CommandRecord } from \"./analyzer.js\";\r\n\r\n// ── Types ────────────────────────────────────────────────────────────────────\r\n\r\nexport interface CommandSequence {\r\n /** The ordered command prefixes forming the pattern (e.g., [\"git checkout\", \"npm install\", \"npm run build\"]) */\r\n steps: string[];\r\n /** How many sessions contained this sequence */\r\n sessionCount: number;\r\n /** Total occurrences across all sessions */\r\n totalOccurrences: number;\r\n /** Example full commands from the most recent occurrence */\r\n examples: string[];\r\n}\r\n\r\nexport interface SkillProposal {\r\n /** Suggested slug for the skill */\r\n slug: string;\r\n /** Human-readable description of what the pattern does */\r\n description: string;\r\n /** The command steps forming the skill */\r\n steps: string[];\r\n /** How many sessions demonstrated this pattern */\r\n sessionCount: number;\r\n /** Confidence that this is a real, repeatable skill */\r\n confidence: \"high\" | \"medium\" | \"low\";\r\n /** Example commands from actual usage */\r\n examples: string[];\r\n}\r\n\r\nexport interface DiscoveryOptions {\r\n /** Minimum number of sessions a pattern must appear in (default: 2) */\r\n minSessions?: number;\r\n /** Minimum sequence length to consider (default: 2) */\r\n minSequenceLength?: number;\r\n /** Maximum sequence length to consider (default: 5) */\r\n maxSequenceLength?: number;\r\n /** Existing skill slugs to exclude from proposals */\r\n existingSkillSlugs?: string[];\r\n}\r\n\r\n// ── Discovery ────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Discover recurring command patterns across multiple sessions.\r\n *\r\n * Takes a map of session ID → command records, finds command sequences\r\n * that appear in multiple sessions, and proposes them as skills.\r\n *\r\n * @param sessionCommands - Map of session ID to that session's commands\r\n * @param options - Discovery configuration\r\n * @returns Array of skill proposals, sorted by confidence then session count\r\n */\r\nexport function discoverSkills(\r\n sessionCommands: Map<string, CommandRecord[]>,\r\n options: DiscoveryOptions = {},\r\n): SkillProposal[] {\r\n const minSessions = options.minSessions ?? 2;\r\n const minLen = options.minSequenceLength ?? 2;\r\n const maxLen = options.maxSequenceLength ?? 5;\r\n const existing = new Set(options.existingSkillSlugs ?? []);\r\n\r\n // Step 1: Extract normalized command sequences from each session\r\n const sessionSequences = new Map<string, string[][]>();\r\n for (const [sessionId, commands] of sessionCommands) {\r\n const sequences = extractSequences(commands, minLen, maxLen);\r\n if (sequences.length > 0) {\r\n sessionSequences.set(sessionId, sequences);\r\n }\r\n }\r\n\r\n // Step 2: Count how many sessions contain each unique sequence\r\n const sequenceIndex = new Map<string, CommandSequence>();\r\n\r\n for (const [, sequences] of sessionSequences) {\r\n // Deduplicate within a session — count each sequence once per session\r\n const seen = new Set<string>();\r\n for (const seq of sequences) {\r\n const key = seq.join(\" → \");\r\n if (seen.has(key)) continue;\r\n seen.add(key);\r\n\r\n const entry = sequenceIndex.get(key);\r\n if (entry) {\r\n entry.sessionCount++;\r\n entry.totalOccurrences++;\r\n } else {\r\n sequenceIndex.set(key, {\r\n steps: seq,\r\n sessionCount: 1,\r\n totalOccurrences: 1,\r\n examples: [],\r\n });\r\n }\r\n }\r\n }\r\n\r\n // Step 3: Collect examples from the most recent session for qualifying sequences\r\n const lastSessionId = [...sessionCommands.keys()].pop();\r\n if (lastSessionId) {\r\n const lastCommands = sessionCommands.get(lastSessionId)!;\r\n for (const [key, entry] of sequenceIndex) {\r\n if (entry.sessionCount >= minSessions) {\r\n entry.examples = findExamplesForSequence(lastCommands, entry.steps);\r\n }\r\n }\r\n }\r\n\r\n // Step 4: Filter to patterns that appear in enough sessions\r\n const candidates = [...sequenceIndex.values()].filter(\r\n (s) => s.sessionCount >= minSessions,\r\n );\r\n\r\n // Step 5: Remove subsequences of longer patterns (prefer maximal patterns)\r\n const pruned = removeSubsequences(candidates);\r\n\r\n // Step 6: Convert to skill proposals\r\n const proposals: SkillProposal[] = [];\r\n for (const seq of pruned) {\r\n const slug = generateSlug(seq.steps);\r\n\r\n // Skip if this skill already exists\r\n if (existing.has(slug)) continue;\r\n\r\n proposals.push({\r\n slug,\r\n description: describeSequence(seq.steps),\r\n steps: seq.steps,\r\n sessionCount: seq.sessionCount,\r\n confidence: seq.sessionCount >= 4 ? \"high\" : seq.sessionCount >= 3 ? \"medium\" : \"low\",\r\n examples: seq.examples,\r\n });\r\n }\r\n\r\n // Sort: high confidence first, then by session count\r\n const confidenceOrder = { high: 0, medium: 1, low: 2 };\r\n proposals.sort((a, b) => {\r\n const confDiff = confidenceOrder[a.confidence] - confidenceOrder[b.confidence];\r\n if (confDiff !== 0) return confDiff;\r\n return b.sessionCount - a.sessionCount;\r\n });\r\n\r\n return proposals;\r\n}\r\n\r\n// ── Helpers ──────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Normalize a command to its tool + subcommand prefix.\r\n * \"git checkout -b feat/foo\" → \"git checkout\"\r\n * \"npm run build\" → \"npm run build\"\r\n * \"docker compose up -d\" → \"docker compose up\"\r\n */\r\nfunction normalizeCommand(command: string): string {\r\n const parts = command.trim().split(/\\s+/);\r\n\r\n // Known multi-word tools\r\n const multiWord = [\"docker compose\", \"npm run\", \"npx\", \"git\"];\r\n const lower = command.toLowerCase();\r\n\r\n for (const mw of multiWord) {\r\n if (lower.startsWith(mw) && parts.length >= mw.split(\" \").length + 1) {\r\n return parts.slice(0, mw.split(\" \").length + 1).join(\" \").toLowerCase();\r\n }\r\n }\r\n\r\n // Default: first two words\r\n return parts.slice(0, Math.min(2, parts.length)).join(\" \").toLowerCase();\r\n}\r\n\r\n/**\r\n * Extract all command subsequences of length minLen..maxLen from a session.\r\n * Uses normalized command prefixes for comparison.\r\n */\r\nfunction extractSequences(\r\n commands: CommandRecord[],\r\n minLen: number,\r\n maxLen: number,\r\n): string[][] {\r\n // Filter out trivial commands\r\n const filtered = commands.filter((c) => {\r\n const lower = c.command.toLowerCase().trim();\r\n return (\r\n lower.length > 0 &&\r\n !lower.startsWith(\"cd \") &&\r\n lower !== \"cd\" &&\r\n lower !== \"ls\" &&\r\n lower !== \"pwd\" &&\r\n lower !== \"clear\" &&\r\n lower !== \"exit\" &&\r\n !lower.startsWith(\"echo \")\r\n );\r\n });\r\n\r\n const normalized = filtered.map((c) => normalizeCommand(c.command));\r\n const sequences: string[][] = [];\r\n\r\n for (let len = minLen; len <= maxLen; len++) {\r\n for (let i = 0; i <= normalized.length - len; i++) {\r\n const seq = normalized.slice(i, i + len);\r\n // Only include if at least 2 distinct commands (not just \"git commit\" repeated)\r\n if (new Set(seq).size >= 2) {\r\n sequences.push(seq);\r\n }\r\n }\r\n }\r\n\r\n return sequences;\r\n}\r\n\r\n/**\r\n * Find example full commands for a given normalized sequence in a command list.\r\n */\r\nfunction findExamplesForSequence(\r\n commands: CommandRecord[],\r\n steps: string[],\r\n): string[] {\r\n const normalized = commands.map((c) => ({\r\n norm: normalizeCommand(c.command),\r\n full: c.command,\r\n }));\r\n\r\n for (let i = 0; i <= normalized.length - steps.length; i++) {\r\n let match = true;\r\n for (let j = 0; j < steps.length; j++) {\r\n if (normalized[i + j].norm !== steps[j]) {\r\n match = false;\r\n break;\r\n }\r\n }\r\n if (match) {\r\n return normalized.slice(i, i + steps.length).map((n) => n.full);\r\n }\r\n }\r\n\r\n return [];\r\n}\r\n\r\n/**\r\n * Remove sequences that are strict subsequences of longer qualifying sequences.\r\n */\r\nfunction removeSubsequences(candidates: CommandSequence[]): CommandSequence[] {\r\n // Sort by length descending so we check long sequences first\r\n const sorted = [...candidates].sort((a, b) => b.steps.length - a.steps.length);\r\n const result: CommandSequence[] = [];\r\n\r\n for (const candidate of sorted) {\r\n const key = candidate.steps.join(\" → \");\r\n const isSubsequence = result.some((longer) => {\r\n const longerKey = longer.steps.join(\" → \");\r\n return longerKey.includes(key) && longerKey !== key;\r\n });\r\n\r\n if (!isSubsequence) {\r\n result.push(candidate);\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * Generate a slug from command steps.\r\n * [\"git checkout\", \"npm install\", \"npm run build\"] → \"checkout-install-build\"\r\n */\r\nfunction generateSlug(steps: string[]): string {\r\n return steps\r\n .map((s) => {\r\n const parts = s.split(/\\s+/);\r\n return parts[parts.length - 1]; // last word of each step\r\n })\r\n .join(\"-\");\r\n}\r\n\r\n/**\r\n * Generate a human-readable description of what a command sequence does.\r\n */\r\nfunction describeSequence(steps: string[]): string {\r\n return `Recurring pattern: ${steps.join(\" → \")}`;\r\n}\r\n","/**\r\n * Goal Engine — manages goal lifecycle via markdown files.\r\n *\r\n * Goals live as markdown files in a directory (typically the personal repo's\r\n * goals/ folder). The engine reads, creates, and updates these files.\r\n * It does not depend on the database — goals are git-tracked, not DB-tracked.\r\n */\r\n\r\nimport { readdirSync, readFileSync, writeFileSync, existsSync } from \"node:fs\";\r\nimport { join, basename } from \"node:path\";\r\nimport {\r\n parseGoalFile,\r\n serializeGoal,\r\n extractTasks,\r\n extractTokenRefs,\r\n} from \"./parser.js\";\r\nimport type { Goal, GoalStatus } from \"./parser.js\";\r\n\r\n// ── Types ────────────────────────────────────────────────────────────────────\r\n\r\nexport interface GoalSummary {\r\n slug: string;\r\n title: string;\r\n status: GoalStatus;\r\n parent: string | null;\r\n taskCount: number;\r\n tasksDone: number;\r\n tokenCount: number;\r\n}\r\n\r\nexport interface CreateGoalInput {\r\n slug: string;\r\n title: string;\r\n status?: GoalStatus;\r\n parent?: string;\r\n description?: string;\r\n}\r\n\r\n// ── Functions ────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * List all goals in the goals directory.\r\n * Returns summaries sorted by status (active first) then title.\r\n */\r\nexport function listGoals(goalsDir: string): GoalSummary[] {\r\n if (!existsSync(goalsDir)) return [];\r\n\r\n const files = readdirSync(goalsDir).filter(\r\n (f) => f.endsWith(\".md\") && f !== \"README.md\",\r\n );\r\n\r\n const summaries: GoalSummary[] = [];\r\n\r\n for (const file of files) {\r\n const filePath = join(goalsDir, file);\r\n const content = readFileSync(filePath, \"utf-8\");\r\n const slug = basename(file, \".md\");\r\n const goal = parseGoalFile(content, slug, filePath);\r\n const tasks = extractTasks(goal.body);\r\n const tokens = extractTokenRefs(goal.body);\r\n\r\n summaries.push({\r\n slug: goal.slug,\r\n title: goal.title,\r\n status: goal.status,\r\n parent: goal.parent,\r\n taskCount: tasks.length,\r\n tasksDone: tasks.filter((t) => t.done).length,\r\n tokenCount: tokens.length,\r\n });\r\n }\r\n\r\n const statusOrder: Record<GoalStatus, number> = {\r\n active: 0,\r\n paused: 1,\r\n completed: 2,\r\n abandoned: 3,\r\n };\r\n\r\n summaries.sort((a, b) => {\r\n const statusDiff = statusOrder[a.status] - statusOrder[b.status];\r\n if (statusDiff !== 0) return statusDiff;\r\n return a.title.localeCompare(b.title);\r\n });\r\n\r\n return summaries;\r\n}\r\n\r\n/**\r\n * Get a single goal by slug (filename without .md).\r\n * Returns undefined if the file doesn't exist.\r\n */\r\nexport function getGoal(goalsDir: string, slug: string): Goal | undefined {\r\n const filePath = join(goalsDir, `${slug}.md`);\r\n if (!existsSync(filePath)) return undefined;\r\n\r\n const content = readFileSync(filePath, \"utf-8\");\r\n return parseGoalFile(content, slug, filePath);\r\n}\r\n\r\n/**\r\n * Create a new goal file. Throws if a goal with this slug already exists.\r\n */\r\nexport function createGoal(goalsDir: string, input: CreateGoalInput): Goal {\r\n const filePath = join(goalsDir, `${input.slug}.md`);\r\n\r\n if (existsSync(filePath)) {\r\n throw new Error(`Goal already exists: ${input.slug}`);\r\n }\r\n\r\n const now = new Date().toISOString().slice(0, 10);\r\n\r\n const goal: Goal = {\r\n slug: input.slug,\r\n title: input.title,\r\n status: input.status ?? \"active\",\r\n parent: input.parent ?? null,\r\n created: now,\r\n updated: now,\r\n body: input.description\r\n ? `## Description\\n${input.description}\\n\\n## Tasks\\n\\n## Tokens`\r\n : \"## Description\\n\\n## Tasks\\n\\n## Tokens\",\r\n filePath,\r\n };\r\n\r\n writeFileSync(filePath, serializeGoal(goal), \"utf-8\");\r\n return goal;\r\n}\r\n\r\n/**\r\n * Update a goal's status. Writes the updated file back to disk.\r\n */\r\nexport function updateGoalStatus(\r\n goalsDir: string,\r\n slug: string,\r\n status: GoalStatus,\r\n): Goal {\r\n const goal = getGoal(goalsDir, slug);\r\n if (!goal) throw new Error(`Goal not found: ${slug}`);\r\n\r\n goal.status = status;\r\n goal.updated = new Date().toISOString().slice(0, 10);\r\n\r\n writeFileSync(goal.filePath, serializeGoal(goal), \"utf-8\");\r\n return goal;\r\n}\r\n\r\n/**\r\n * Get the goal tree — goals organized by parent relationships.\r\n * Returns root goals (no parent) with nested children.\r\n */\r\nexport function getGoalTree(goalsDir: string): Array<GoalSummary & { children: GoalSummary[] }> {\r\n const all = listGoals(goalsDir);\r\n const bySlug = new Map(all.map((g) => [g.slug, g]));\r\n\r\n const roots: Array<GoalSummary & { children: GoalSummary[] }> = [];\r\n const children = new Map<string, GoalSummary[]>();\r\n\r\n for (const g of all) {\r\n if (g.parent && bySlug.has(g.parent)) {\r\n const list = children.get(g.parent) ?? [];\r\n list.push(g);\r\n children.set(g.parent, list);\r\n }\r\n }\r\n\r\n for (const g of all) {\r\n if (!g.parent || !bySlug.has(g.parent)) {\r\n roots.push({ ...g, children: children.get(g.slug) ?? [] });\r\n }\r\n }\r\n\r\n return roots;\r\n}\r\n","/**\r\n * Goal file parser — reads markdown files with YAML-style frontmatter.\r\n *\r\n * Goals are persisted as markdown files in the personal repo.\r\n * Each file has simple key: value frontmatter (no nested structures)\r\n * and a markdown body with description, tasks, and token references.\r\n */\r\n\r\n// ── Types ────────────────────────────────────────────────────────────────────\r\n\r\nexport type GoalStatus = \"active\" | \"completed\" | \"paused\" | \"abandoned\";\r\n\r\nexport interface Goal {\r\n slug: string; // derived from filename (e.g., \"learn-rust\" from \"learn-rust.md\")\r\n title: string;\r\n status: GoalStatus;\r\n parent: string | null; // slug of parent goal\r\n created: string; // ISO date\r\n updated: string; // ISO date\r\n body: string; // markdown body after frontmatter\r\n filePath: string; // absolute path to the file\r\n}\r\n\r\nexport interface GoalFrontmatter {\r\n title?: string;\r\n status?: string;\r\n parent?: string;\r\n created?: string;\r\n updated?: string;\r\n}\r\n\r\n// ── Parser ───────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Parse a goal markdown file into a Goal object.\r\n *\r\n * Expected format:\r\n * ```\r\n * ---\r\n * title: Learn Rust fundamentals\r\n * status: active\r\n * parent: become-systems-programmer\r\n * created: 2026-03-28\r\n * updated: 2026-03-28\r\n * ---\r\n *\r\n * ## Description\r\n * ...\r\n * ```\r\n *\r\n * @param content - Raw file content\r\n * @param slug - Goal slug (derived from filename by caller)\r\n * @param filePath - Absolute path to the file\r\n */\r\nexport function parseGoalFile(content: string, slug: string, filePath: string): Goal {\r\n const { frontmatter, body } = splitFrontmatter(content);\r\n\r\n const validStatuses: GoalStatus[] = [\"active\", \"completed\", \"paused\", \"abandoned\"];\r\n const status = validStatuses.includes(frontmatter.status as GoalStatus)\r\n ? (frontmatter.status as GoalStatus)\r\n : \"active\";\r\n\r\n const now = new Date().toISOString().slice(0, 10);\r\n\r\n return {\r\n slug,\r\n title: frontmatter.title || slug,\r\n status,\r\n parent: frontmatter.parent || null,\r\n created: frontmatter.created || now,\r\n updated: frontmatter.updated || now,\r\n body,\r\n filePath,\r\n };\r\n}\r\n\r\n/**\r\n * Serialize a Goal back to markdown with frontmatter.\r\n */\r\nexport function serializeGoal(goal: Goal): string {\r\n const lines = [\r\n \"---\",\r\n `title: ${goal.title}`,\r\n `status: ${goal.status}`,\r\n ];\r\n\r\n if (goal.parent) {\r\n lines.push(`parent: ${goal.parent}`);\r\n }\r\n\r\n lines.push(`created: ${goal.created}`);\r\n lines.push(`updated: ${goal.updated}`);\r\n lines.push(\"---\");\r\n lines.push(\"\");\r\n\r\n if (goal.body.trim()) {\r\n lines.push(goal.body.trim());\r\n lines.push(\"\");\r\n }\r\n\r\n return lines.join(\"\\n\");\r\n}\r\n\r\n/**\r\n * Extract tasks (checklist items) from goal body.\r\n * Returns items like { text: \"Complete Rustlings\", done: false }.\r\n */\r\nexport function extractTasks(body: string): Array<{ text: string; done: boolean }> {\r\n const tasks: Array<{ text: string; done: boolean }> = [];\r\n const taskRegex = /^[-*]\\s+\\[([ xX])\\]\\s+(.+)$/gm;\r\n let match: RegExpExecArray | null;\r\n\r\n while ((match = taskRegex.exec(body)) !== null) {\r\n tasks.push({\r\n done: match[1] !== \" \",\r\n text: match[2].trim(),\r\n });\r\n }\r\n\r\n return tasks;\r\n}\r\n\r\n/**\r\n * Extract token references from goal body.\r\n * Looks for lines like `- token/slug` under a \"## Tokens\" section.\r\n */\r\nexport function extractTokenRefs(body: string): string[] {\r\n const tokensSection = body.match(/## Tokens\\n([\\s\\S]*?)(?=\\n## |\\n*$)/);\r\n if (!tokensSection) return [];\r\n\r\n const refs: string[] = [];\r\n const lines = tokensSection[1].split(\"\\n\");\r\n\r\n for (const line of lines) {\r\n const match = line.match(/^[-*]\\s+(\\S+)/);\r\n if (match) {\r\n refs.push(match[1]);\r\n }\r\n }\r\n\r\n return refs;\r\n}\r\n\r\n// ── Internal helpers ─────────────────────────────────────────────────────────\r\n\r\nfunction splitFrontmatter(content: string): { frontmatter: GoalFrontmatter; body: string } {\r\n const trimmed = content.trim();\r\n\r\n if (!trimmed.startsWith(\"---\")) {\r\n return { frontmatter: {}, body: trimmed };\r\n }\r\n\r\n const endIndex = trimmed.indexOf(\"---\", 3);\r\n if (endIndex === -1) {\r\n return { frontmatter: {}, body: trimmed };\r\n }\r\n\r\n const fmBlock = trimmed.slice(3, endIndex).trim();\r\n const body = trimmed.slice(endIndex + 3).trim();\r\n\r\n const frontmatter: GoalFrontmatter = {};\r\n for (const line of fmBlock.split(\"\\n\")) {\r\n const colonIndex = line.indexOf(\":\");\r\n if (colonIndex === -1) continue;\r\n\r\n const key = line.slice(0, colonIndex).trim();\r\n const value = line.slice(colonIndex + 1).trim();\r\n\r\n if (key && value) {\r\n (frontmatter as Record<string, string>)[key] = value;\r\n }\r\n }\r\n\r\n return { frontmatter, body };\r\n}\r\n","/**\r\n * Azure DevOps connector — fetches work items from ADO boards.\r\n */\r\n\r\nimport type { Database } from \"libsql\";\r\nimport { getSetting } from \"../models/settings.js\";\r\n\r\nexport interface ADOConfig {\r\n orgUrl: string;\r\n project: string;\r\n pat: string;\r\n}\r\n\r\nexport interface WorkItem {\r\n id: number;\r\n title: string;\r\n state: string;\r\n type: string;\r\n assignedTo: string;\r\n}\r\n\r\n/** Load ADO config from user settings. Returns null if not configured. */\r\nexport function loadADOConfig(db: Database): ADOConfig | null {\r\n const orgUrl = getSetting(db, \"ado.org_url\");\r\n const project = getSetting(db, \"ado.project\");\r\n const pat = getSetting(db, \"ado.pat\");\r\n\r\n if (!orgUrl || !project || !pat) return null;\r\n\r\n return { orgUrl: orgUrl.replace(/\\/+$/, \"\"), project, pat };\r\n}\r\n\r\nfunction authHeader(pat: string): string {\r\n return `Basic ${Buffer.from(`:${pat}`).toString(\"base64\")}`;\r\n}\r\n\r\n/**\r\n * Fetch active work items assigned to the current user.\r\n * Uses WIQL to query, then batch-fetches work item details.\r\n */\r\nexport async function fetchActiveWorkItems(config: ADOConfig): Promise<WorkItem[]> {\r\n const { orgUrl, project, pat } = config;\r\n\r\n // Step 1: WIQL query for work item IDs\r\n const wiqlUrl = `${orgUrl}/${project}/_apis/wit/wiql?api-version=7.1`;\r\n const wiqlBody = {\r\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`,\r\n };\r\n\r\n const wiqlRes = await fetch(wiqlUrl, {\r\n method: \"POST\",\r\n headers: {\r\n Authorization: authHeader(pat),\r\n \"Content-Type\": \"application/json\",\r\n },\r\n body: JSON.stringify(wiqlBody),\r\n });\r\n\r\n if (!wiqlRes.ok) {\r\n const text = await wiqlRes.text();\r\n throw new Error(`ADO WIQL query failed (${wiqlRes.status}): ${text}`);\r\n }\r\n\r\n const wiqlData = (await wiqlRes.json()) as { workItems: { id: number }[] };\r\n const ids = wiqlData.workItems.map((wi) => wi.id);\r\n\r\n if (ids.length === 0) return [];\r\n\r\n // Step 2: Batch fetch work item details (max 200 per request)\r\n const batchIds = ids.slice(0, 200);\r\n const fields = \"System.Id,System.Title,System.State,System.WorkItemType,System.AssignedTo\";\r\n const detailUrl = `${orgUrl}/${project}/_apis/wit/workitems?ids=${batchIds.join(\",\")}&fields=${fields}&api-version=7.1`;\r\n\r\n const detailRes = await fetch(detailUrl, {\r\n headers: { Authorization: authHeader(pat) },\r\n });\r\n\r\n if (!detailRes.ok) {\r\n const text = await detailRes.text();\r\n throw new Error(`ADO work items fetch failed (${detailRes.status}): ${text}`);\r\n }\r\n\r\n const detailData = (await detailRes.json()) as {\r\n value: Array<{\r\n id: number;\r\n fields: {\r\n \"System.Title\": string;\r\n \"System.State\": string;\r\n \"System.WorkItemType\": string;\r\n \"System.AssignedTo\"?: { displayName: string };\r\n };\r\n }>;\r\n };\r\n\r\n return detailData.value.map((wi) => ({\r\n id: wi.id,\r\n title: wi.fields[\"System.Title\"],\r\n state: wi.fields[\"System.State\"],\r\n type: wi.fields[\"System.WorkItemType\"],\r\n assignedTo: wi.fields[\"System.AssignedTo\"]?.displayName ?? \"\",\r\n }));\r\n}\r\n","/**\r\n * `zam setup` — Distribute skill files from the zam package into the current\r\n * personal instance's .claude/ and .gemini/ directories, and optionally\r\n * initialize the ZAM database and generate a CLAUDE.md.\r\n *\r\n * Run this once after cloning a ZAM personal instance, and again after\r\n * upgrading zam (with --force) to refresh the skill files.\r\n */\r\n\r\nimport { Command } from \"commander\";\r\nimport { fileURLToPath } from \"url\";\r\nimport { existsSync, mkdirSync, copyFileSync, writeFileSync } from \"fs\";\r\nimport { join, dirname, basename } from \"path\";\r\nimport { openDatabase, getDefaultDbPath } from \"../../kernel/index.js\";\r\n\r\n// The compiled CLI lives at dist/cli/index.js inside the package.\r\n// Two levels up from there is the package root (dist/ → package root).\r\n// This same relative path also works when running via `tsx src/cli/index.ts`\r\n// (src/ → package root), so no branch logic is needed.\r\nconst packageRoot = fileURLToPath(new URL(\"../..\", import.meta.url));\r\n\r\nconst SKILL_PAIRS: Array<{ from: string; to: string }> = [\r\n {\r\n from: join(packageRoot, \".claude\", \"skills\", \"zam\", \"SKILL.md\"),\r\n to: join(\".claude\", \"skills\", \"zam\", \"SKILL.md\"),\r\n },\r\n {\r\n from: join(packageRoot, \".gemini\", \"skills\", \"zam\", \"SKILL.md\"),\r\n to: join(\".gemini\", \"skills\", \"zam\", \"SKILL.md\"),\r\n },\r\n];\r\n\r\nfunction copySkills(force: boolean): void {\r\n const cwd = process.cwd();\r\n let anyAction = false;\r\n\r\n for (const { from, to } of SKILL_PAIRS) {\r\n const dest = join(cwd, to);\r\n\r\n if (!existsSync(from)) {\r\n console.warn(` warn source not found, skipping: ${from}`);\r\n continue;\r\n }\r\n\r\n if (existsSync(dest) && !force) {\r\n console.log(` skip ${to} (already present — use --force to update)`);\r\n continue;\r\n }\r\n\r\n mkdirSync(dirname(dest), { recursive: true });\r\n copyFileSync(from, dest);\r\n console.log(` copy ${to}`);\r\n anyAction = true;\r\n }\r\n\r\n if (!anyAction && !force) {\r\n console.log(\r\n \"\\nSkill files are already up to date. Run with --force to overwrite.\",\r\n );\r\n }\r\n}\r\n\r\nfunction initDatabase(skipInit: boolean): void {\r\n if (skipInit) return;\r\n\r\n try {\r\n const dbPath = getDefaultDbPath();\r\n const db = openDatabase({ initialize: true });\r\n db.close();\r\n console.log(` init ZAM database at ${dbPath}`);\r\n } catch (err) {\r\n // Database may already exist — not an error during setup.\r\n const msg = (err as Error).message;\r\n if (!msg.includes(\"already\")) {\r\n console.warn(` warn database init: ${msg}`);\r\n } else {\r\n console.log(` skip database already initialized`);\r\n }\r\n }\r\n}\r\n\r\nfunction writeClaudeMd(skipClaudeMd: boolean): void {\r\n if (skipClaudeMd) return;\r\n\r\n const dest = join(process.cwd(), \"CLAUDE.md\");\r\n if (existsSync(dest)) {\r\n console.log(` skip CLAUDE.md (already present)`);\r\n return;\r\n }\r\n\r\n const name = basename(process.cwd());\r\n writeFileSync(\r\n dest,\r\n `# ZAM Personal Kernel — ${name}\r\n\r\nThis is a ZAM personal instance. ZAM builds lasting skills through spaced\r\nrepetition during real work — not separate study sessions.\r\n\r\n## First time here?\r\nRun \\`/setup\\` in Claude Code or Gemini CLI to complete first-time setup.\r\n\r\n## Regular use\r\nRun \\`/zam\\` to start a learning session on whatever you are working on.\r\n\r\n## What lives here\r\n- \\`beliefs/\\` — your worldview, approved by git commit\r\n- \\`goals/\\` — your objectives, decomposed into tasks and learning tokens\r\n\r\n## Fast-changing data\r\nLearning tokens, cards, and review history live in \\`~/.zam/zam.db\\` (local\r\nSQLite, not committed to git). Use \\`zam connector setup turso\\` to enable\r\ncloud sync across machines.\r\n`,\r\n \"utf8\",\r\n );\r\n console.log(` write CLAUDE.md`);\r\n}\r\n\r\nexport const setupCommand = new Command(\"setup\")\r\n .description(\r\n \"Distribute ZAM skill files into this personal instance and initialize the database\",\r\n )\r\n .option(\r\n \"--force\",\r\n \"overwrite existing skill files (use after upgrading zam)\",\r\n false,\r\n )\r\n .option(\"--skip-init\", \"skip database initialization\", false)\r\n .option(\"--skip-claude-md\", \"skip CLAUDE.md generation\", false)\r\n .action(\r\n (opts: { force: boolean; skipInit: boolean; skipClaudeMd: boolean }) => {\r\n console.log(`Setting up ZAM in ${process.cwd()}\\n`);\r\n\r\n copySkills(opts.force);\r\n initDatabase(opts.skipInit);\r\n writeClaudeMd(opts.skipClaudeMd);\r\n\r\n console.log(\r\n \"\\nDone. Run `zam whoami --set <your-id>` to set your identity, then open Claude Code or Gemini CLI and run /zam to start a learning session.\",\r\n );\r\n },\r\n );\r\n","/**\r\n * `zam token` — Token management subcommand group.\r\n */\r\n\r\nimport { Command } from \"commander\";\r\nimport type { Database } from \"libsql\";\r\nimport {\r\n openDatabase,\r\n createToken,\r\n findTokens,\r\n listTokens,\r\n getTokenBySlug,\r\n addPrerequisite,\r\n getPrerequisites,\r\n getDependents,\r\n ensureCard,\r\n getCard,\r\n deprecateToken,\r\n} from \"../../kernel/index.js\";\r\nimport type { BloomLevel } from \"../../kernel/index.js\";\r\nimport { resolveUser } from \"./resolve-user.js\";\r\n\r\nfunction withDb(fn: (db: Database) => void): void {\r\n let db: Database | undefined;\r\n try {\r\n db = openDatabase();\r\n fn(db);\r\n } catch (err) {\r\n console.error(\"Error:\", (err as Error).message);\r\n process.exit(1);\r\n } finally {\r\n db?.close();\r\n }\r\n}\r\n\r\nexport const tokenCommand = new Command(\"token\")\r\n .description(\"Manage knowledge tokens\");\r\n\r\n// ── zam token register ────────────────────────────────────────────────────\r\n\r\ntokenCommand\r\n .command(\"register\")\r\n .description(\"Register a new knowledge token\")\r\n .requiredOption(\"--slug <slug>\", \"Unique token slug\")\r\n .requiredOption(\"--concept <concept>\", \"Concept description\")\r\n .option(\"--domain <domain>\", \"Knowledge domain\", \"\")\r\n .option(\"--bloom <level>\", \"Bloom taxonomy level (1-5)\", \"1\")\r\n .option(\"--json\", \"Output as JSON\")\r\n .action((opts) => {\r\n withDb((db) => {\r\n const token = createToken(db, {\r\n slug: opts.slug,\r\n concept: opts.concept,\r\n domain: opts.domain,\r\n bloom_level: Number(opts.bloom) as BloomLevel,\r\n });\r\n\r\n if (opts.json) {\r\n console.log(JSON.stringify(token, null, 2));\r\n } else {\r\n console.log(`Registered token: ${token.slug} (${token.id})`);\r\n console.log(` Concept: ${token.concept}`);\r\n console.log(` Domain: ${token.domain || \"(none)\"}`);\r\n console.log(` Bloom: ${token.bloom_level}`);\r\n }\r\n });\r\n });\r\n\r\n// ── zam token find ────────────────────────────────────────────────────────\r\n\r\ntokenCommand\r\n .command(\"find\")\r\n .description(\"Fuzzy search for tokens\")\r\n .requiredOption(\"--query <query>\", \"Search query\")\r\n .option(\"--json\", \"Output as JSON\")\r\n .action((opts) => {\r\n withDb((db) => {\r\n const results = findTokens(db, opts.query);\r\n\r\n if (opts.json) {\r\n console.log(JSON.stringify(results, null, 2));\r\n return;\r\n }\r\n\r\n if (results.length === 0) {\r\n console.log(\"No tokens found.\");\r\n return;\r\n }\r\n\r\n console.log(`Found ${results.length} token(s):\\n`);\r\n console.log(\r\n \"Score Slug Concept Domain Bloom\",\r\n );\r\n console.log(\"─\".repeat(90));\r\n for (const t of results) {\r\n console.log(\r\n `${String(t.score).padEnd(6)} ${t.slug.padEnd(21)} ${t.concept.slice(0, 31).padEnd(31)} ${(t.domain || \"-\").padEnd(11)} ${t.bloom_level}`,\r\n );\r\n }\r\n });\r\n });\r\n\r\n// ── zam token list ────────────────────────────────────────────────────────\r\n\r\ntokenCommand\r\n .command(\"list\")\r\n .description(\"List all tokens\")\r\n .option(\"--domain <domain>\", \"Filter by domain\")\r\n .option(\"--json\", \"Output as JSON\")\r\n .action((opts) => {\r\n withDb((db) => {\r\n const tokens = listTokens(db, opts.domain ? { domain: opts.domain } : undefined);\r\n\r\n if (opts.json) {\r\n console.log(JSON.stringify(tokens, null, 2));\r\n return;\r\n }\r\n\r\n if (tokens.length === 0) {\r\n console.log(\"No tokens registered.\");\r\n return;\r\n }\r\n\r\n console.log(\r\n \"Slug Concept Domain Bloom\",\r\n );\r\n console.log(\"─\".repeat(80));\r\n for (const t of tokens) {\r\n console.log(\r\n `${t.slug.padEnd(21)} ${t.concept.slice(0, 31).padEnd(31)} ${(t.domain || \"-\").padEnd(11)} ${t.bloom_level}`,\r\n );\r\n }\r\n console.log(`\\n${tokens.length} token(s) total.`);\r\n });\r\n });\r\n\r\n// ── zam token prereq ─────────────────────────────────────────────────────\r\n\r\ntokenCommand\r\n .command(\"prereq\")\r\n .description(\"Add a prerequisite edge between tokens\")\r\n .requiredOption(\"--token <slug>\", \"Token that requires a prerequisite\")\r\n .requiredOption(\"--requires <slug>\", \"Required prerequisite token\")\r\n .option(\"--json\", \"Output as JSON\")\r\n .action((opts) => {\r\n withDb((db) => {\r\n const token = getTokenBySlug(db, opts.token);\r\n if (!token) {\r\n console.error(`Token not found: ${opts.token}`);\r\n process.exit(1);\r\n }\r\n\r\n const requires = getTokenBySlug(db, opts.requires);\r\n if (!requires) {\r\n console.error(`Prerequisite token not found: ${opts.requires}`);\r\n process.exit(1);\r\n }\r\n\r\n addPrerequisite(db, token.id, requires.id);\r\n\r\n if (opts.json) {\r\n console.log(JSON.stringify({ token: opts.token, requires: opts.requires }, null, 2));\r\n } else {\r\n console.log(`Added prerequisite: ${opts.token} requires ${opts.requires}`);\r\n }\r\n });\r\n });\r\n\r\n// ── zam token deprecate ───────────────────────────────────────────────────\r\n\r\ntokenCommand\r\n .command(\"deprecate\")\r\n .description(\"Mark a token as deprecated (excluded from reviews, not deleted)\")\r\n .requiredOption(\"--slug <slug>\", \"Token slug to deprecate\")\r\n .option(\"--json\", \"Output as JSON\")\r\n .action((opts) => {\r\n withDb((db) => {\r\n const token = deprecateToken(db, opts.slug);\r\n\r\n if (opts.json) {\r\n console.log(JSON.stringify(token, null, 2));\r\n } else {\r\n console.log(`Deprecated: ${token.slug}`);\r\n console.log(` Concept: ${token.concept}`);\r\n console.log(` At: ${token.deprecated_at}`);\r\n }\r\n });\r\n });\r\n\r\n// ── zam token status ─────────────────────────────────────────────────────\r\n\r\ntokenCommand\r\n .command(\"status\")\r\n .description(\"Show full status of a token for a user\")\r\n .requiredOption(\"--token <slug>\", \"Token slug\")\r\n .option(\"--user <id>\", \"User ID (default: whoami)\")\r\n .option(\"--json\", \"Output as JSON\")\r\n .action((opts) => {\r\n withDb((db) => {\r\n const userId = resolveUser(opts, db);\r\n const token = getTokenBySlug(db, opts.token);\r\n if (!token) {\r\n console.error(`Token not found: ${opts.token}`);\r\n process.exit(1);\r\n }\r\n\r\n const card = getCard(db, token.id, userId);\r\n const prereqs = getPrerequisites(db, token.id);\r\n const dependents = getDependents(db, token.id);\r\n\r\n const status = {\r\n token,\r\n card: card ?? null,\r\n prerequisites: prereqs,\r\n dependents,\r\n };\r\n\r\n if (opts.json) {\r\n console.log(JSON.stringify(status, null, 2));\r\n return;\r\n }\r\n\r\n console.log(`Token: ${token.slug} (${token.id})`);\r\n console.log(` Concept: ${token.concept}`);\r\n console.log(` Domain: ${token.domain || \"(none)\"}`);\r\n console.log(` Bloom: ${token.bloom_level}`);\r\n console.log();\r\n\r\n if (card) {\r\n console.log(\"Card status:\");\r\n console.log(` State: ${card.state}`);\r\n console.log(` Due at: ${card.due_at}`);\r\n console.log(` Stability: ${card.stability}`);\r\n console.log(` Difficulty: ${card.difficulty}`);\r\n console.log(` Reps: ${card.reps}`);\r\n console.log(` Lapses: ${card.lapses}`);\r\n console.log(` Blocked: ${card.blocked ? \"Yes\" : \"No\"}`);\r\n } else {\r\n console.log(\"No card exists for this user yet.\");\r\n }\r\n\r\n console.log();\r\n if (prereqs.length > 0) {\r\n console.log(\"Prerequisites:\");\r\n for (const p of prereqs) {\r\n console.log(` - ${p.slug}: ${p.concept} (bloom ${p.bloom_level})`);\r\n }\r\n } else {\r\n console.log(\"No prerequisites.\");\r\n }\r\n\r\n if (dependents.length > 0) {\r\n console.log(\"\\nDependents:\");\r\n for (const d of dependents) {\r\n console.log(` - ${d.slug}: ${d.concept} (bloom ${d.bloom_level})`);\r\n }\r\n }\r\n });\r\n });\r\n","/**\r\n * Resolve the active user ID from --user flag or stored whoami setting.\r\n */\r\n\r\nimport type { Database } from \"libsql\";\r\nimport { getSetting } from \"../../kernel/index.js\";\r\n\r\nexport interface ResolveUserOptions {\r\n /** If true, output JSON error instead of console.error (for bridge commands). */\r\n json?: boolean;\r\n}\r\n\r\n/**\r\n * Returns the user ID from the explicit --user flag, or falls back to the\r\n * stored `user.id` setting. Exits with an error if neither is available.\r\n */\r\nexport function resolveUser(\r\n opts: { user?: string },\r\n db: Database,\r\n resolveOpts?: ResolveUserOptions,\r\n): string {\r\n if (opts.user) return opts.user;\r\n\r\n const stored = getSetting(db, \"user.id\");\r\n if (stored) return stored;\r\n\r\n const message = 'No user specified. Set a default with: zam whoami --set <id>';\r\n if (resolveOpts?.json) {\r\n console.log(JSON.stringify({ error: message }, null, 2));\r\n } else {\r\n console.error(message);\r\n }\r\n process.exit(1);\r\n}\r\n","/**\r\n * `zam card` — Card scheduling subcommand group.\r\n */\r\n\r\nimport { Command } from \"commander\";\r\nimport type { Database } from \"libsql\";\r\nimport {\r\n openDatabase,\r\n getDueCards,\r\n getTokenBySlug,\r\n ensureCard,\r\n evaluateRating,\r\n cascadeBlock,\r\n unblockReady,\r\n getPrerequisites,\r\n} from \"../../kernel/index.js\";\r\nimport type { Rating } from \"../../kernel/index.js\";\r\nimport { resolveUser } from \"./resolve-user.js\";\r\n\r\nfunction withDb(fn: (db: Database) => void): void {\r\n let db: Database | undefined;\r\n try {\r\n db = openDatabase();\r\n fn(db);\r\n } catch (err) {\r\n console.error(\"Error:\", (err as Error).message);\r\n process.exit(1);\r\n } finally {\r\n db?.close();\r\n }\r\n}\r\n\r\nexport const cardCommand = new Command(\"card\")\r\n .description(\"Manage spaced-repetition cards\");\r\n\r\n// ── zam card due ──────────────────────────────────────────────────────────\r\n\r\ncardCommand\r\n .command(\"due\")\r\n .description(\"Show due tokens for a user\")\r\n .option(\"--user <id>\", \"User ID (default: whoami)\")\r\n .option(\"--json\", \"Output as JSON\")\r\n .option(\"--summary\", \"Show only counts per domain (no slugs or concepts)\")\r\n .action((opts) => {\r\n withDb((db) => {\r\n const userId = resolveUser(opts, db);\r\n const dueCards = getDueCards(db, userId);\r\n\r\n if (opts.json) {\r\n console.log(JSON.stringify(dueCards, null, 2));\r\n return;\r\n }\r\n\r\n if (dueCards.length === 0) {\r\n console.log(\"No cards due for review.\");\r\n return;\r\n }\r\n\r\n if (opts.summary) {\r\n const byDomain = new Map<string, { count: number; blooms: number[] }>();\r\n for (const c of dueCards) {\r\n const d = c.domain || \"general\";\r\n const entry = byDomain.get(d) ?? { count: 0, blooms: [] };\r\n entry.count++;\r\n entry.blooms.push(c.bloom_level);\r\n byDomain.set(d, entry);\r\n }\r\n console.log(`${dueCards.length} card(s) due:\\n`);\r\n console.log(\r\n \"Domain Count Bloom levels\",\r\n );\r\n console.log(\"─\".repeat(45));\r\n for (const [domain, { count, blooms }] of [...byDomain.entries()].sort()) {\r\n const bloomStr = blooms.sort().join(\", \");\r\n console.log(\r\n `${domain.padEnd(16)} ${String(count).padEnd(6)} ${bloomStr}`,\r\n );\r\n }\r\n return;\r\n }\r\n\r\n console.log(`${dueCards.length} card(s) due:\\n`);\r\n console.log(\r\n \"Slug Concept Domain Bloom State\",\r\n );\r\n console.log(\"─\".repeat(90));\r\n for (const c of dueCards) {\r\n console.log(\r\n `${c.slug.padEnd(21)} ${c.concept.slice(0, 31).padEnd(31)} ${(c.domain || \"-\").padEnd(11)} ${String(c.bloom_level).padEnd(6)} ${c.state}`,\r\n );\r\n }\r\n });\r\n });\r\n\r\n// ── zam card update ───────────────────────────────────────────────────────\r\n\r\ncardCommand\r\n .command(\"update\")\r\n .description(\"Apply a rating to a card\")\r\n .option(\"--user <id>\", \"User ID (default: whoami)\")\r\n .requiredOption(\"--token <slug>\", \"Token slug\")\r\n .requiredOption(\"--rating <n>\", \"Rating (1=Again, 2=Hard, 3=Good, 4=Easy)\")\r\n .option(\"--json\", \"Output as JSON\")\r\n .option(\"--quiet\", \"Suppress output (exit code only)\")\r\n .action((opts) => {\r\n withDb((db) => {\r\n const userId = resolveUser(opts, db);\r\n const token = getTokenBySlug(db, opts.token);\r\n if (!token) {\r\n console.error(`Token not found: ${opts.token}`);\r\n process.exit(1);\r\n }\r\n\r\n const card = ensureCard(db, token.id, userId);\r\n const rating = Number(opts.rating) as Rating;\r\n\r\n if (rating < 1 || rating > 4) {\r\n console.error(\"Rating must be between 1 and 4.\");\r\n process.exit(1);\r\n }\r\n\r\n const result = evaluateRating(db, {\r\n cardId: card.id,\r\n tokenId: token.id,\r\n userId,\r\n rating,\r\n });\r\n\r\n // If rating is 1 (forgot) and token has prerequisites, cascade block\r\n if (rating === 1) {\r\n const prereqs = getPrerequisites(db, token.id);\r\n if (prereqs.length > 0) {\r\n const blockResult = cascadeBlock(db, userId, token.slug);\r\n if (opts.quiet) return;\r\n if (opts.json) {\r\n console.log(JSON.stringify({ evaluation: result, blocked: blockResult }, null, 2));\r\n } else {\r\n console.log(`Rated ${token.slug} as Again (1) — next due: ${result.nextDueAt}`);\r\n console.log(`Blocked ${blockResult.blockedSlug}. Prerequisites surfaced:`);\r\n for (const p of blockResult.prerequisites) {\r\n console.log(` - ${p.slug}: ${p.concept}`);\r\n }\r\n }\r\n return;\r\n }\r\n }\r\n\r\n if (opts.quiet) return;\r\n if (opts.json) {\r\n console.log(JSON.stringify(result, null, 2));\r\n } else {\r\n const ratingLabels: Record<number, string> = { 1: \"Again\", 2: \"Hard\", 3: \"Good\", 4: \"Easy\" };\r\n console.log(`Rated ${token.slug} as ${ratingLabels[rating]} (${rating})`);\r\n console.log(` Next due: ${result.nextDueAt}`);\r\n console.log(` Stability: ${result.stability.toFixed(2)}`);\r\n console.log(` State: ${result.state}`);\r\n console.log(` Reps: ${result.reps}`);\r\n }\r\n });\r\n });\r\n\r\n// ── zam card unblock ──────────────────────────────────────────────────────\r\n\r\ncardCommand\r\n .command(\"unblock\")\r\n .description(\"Unblock cards whose prerequisites are met\")\r\n .option(\"--user <id>\", \"User ID (default: whoami)\")\r\n .option(\"--json\", \"Output as JSON\")\r\n .option(\"--quiet\", \"Suppress output (exit code only)\")\r\n .action((opts) => {\r\n withDb((db) => {\r\n const userId = resolveUser(opts, db);\r\n const result = unblockReady(db, userId);\r\n\r\n if (opts.quiet) return;\r\n if (opts.json) {\r\n console.log(JSON.stringify(result, null, 2));\r\n return;\r\n }\r\n\r\n if (result.unblocked.length === 0) {\r\n console.log(\"No cards ready to unblock.\");\r\n } else {\r\n console.log(`Unblocked ${result.unblocked.length} card(s):`);\r\n for (const u of result.unblocked) {\r\n console.log(` - ${u.slug}: ${u.concept}`);\r\n }\r\n }\r\n });\r\n });\r\n","/**\r\n * `zam session` — Session management subcommand group.\r\n *\r\n * Session start follows the two-phase flow from Increment 2:\r\n * Phase 1 — Repetition: review due cards (pure recall first, skippable)\r\n * Phase 2 — Task execution: pick a work item from ADO or enter a custom task\r\n */\r\n\r\nimport { Command } from \"commander\";\r\nimport type { Database } from \"libsql\";\r\nimport { select, input } from \"@inquirer/prompts\";\r\nimport {\r\n openDatabase,\r\n startSession,\r\n logStep,\r\n endSession,\r\n getSessionSummary,\r\n getTokenBySlug,\r\n loadADOConfig,\r\n fetchActiveWorkItems,\r\n buildReviewQueue,\r\n generatePrompt,\r\n evaluateRating,\r\n cascadeBlock,\r\n getPrerequisites,\r\n getSetting,\r\n} from \"../../kernel/index.js\";\r\nimport type { ExecutionContext, Rating, BloomLevel } from \"../../kernel/index.js\";\r\nimport { resolveUser } from \"./resolve-user.js\";\r\n\r\nfunction withDb(fn: (db: Database) => void): void {\r\n let db: Database | undefined;\r\n try {\r\n db = openDatabase();\r\n fn(db);\r\n } catch (err) {\r\n console.error(\"Error:\", (err as Error).message);\r\n process.exit(1);\r\n } finally {\r\n db?.close();\r\n }\r\n}\r\n\r\nexport const sessionCommand = new Command(\"session\")\r\n .description(\"Manage learning sessions\");\r\n\r\n// ── zam session start ─────────────────────────────────────────────────────\r\n\r\nsessionCommand\r\n .command(\"start\")\r\n .description(\"Start a new learning session (review → task)\")\r\n .option(\"--user <id>\", \"User ID (default: whoami)\")\r\n .option(\"--task <description>\", \"Task description (interactive if omitted)\")\r\n .option(\"--context <level>\", \"Execution context: shell | ui | reallife (default: shell)\", \"shell\")\r\n .option(\"--skip-review\", \"Skip the repetition phase and go straight to task selection\")\r\n .option(\"--review-minutes <n>\", \"Maximum minutes for the repetition phase (default: 20)\", \"20\")\r\n .option(\"--json\", \"Output as JSON\")\r\n .option(\"--quiet\", \"Output only the session ID\")\r\n .action(async (opts) => {\r\n let db: Database | undefined;\r\n try {\r\n db = openDatabase();\r\n\r\n const validContexts = [\"shell\", \"ui\", \"reallife\"];\r\n if (!validContexts.includes(opts.context)) {\r\n console.error(`Invalid context: ${opts.context}. Must be one of: ${validContexts.join(\", \")}`);\r\n process.exit(1);\r\n }\r\n\r\n const userId = resolveUser(opts, db);\r\n const reviewMinutes = Number(opts.reviewMinutes);\r\n\r\n // ── Phase 1: Repetition ────────────────────────────────────────────\r\n if (!opts.skipReview && !opts.quiet && !opts.json) {\r\n const reviewResults = await runRepetitionPhase(db, userId, reviewMinutes);\r\n if (reviewResults.reviewed > 0) {\r\n console.log();\r\n }\r\n }\r\n\r\n // ── Phase 2: Task Selection ────────────────────────────────────────\r\n let task: string = opts.task;\r\n\r\n if (!task && !opts.quiet && !opts.json) {\r\n task = await selectTask(db);\r\n }\r\n\r\n if (!task) {\r\n // Fallback for --quiet/--json without --task\r\n console.error(\"Task description is required. Use --task or run interactively.\");\r\n process.exit(1);\r\n }\r\n\r\n const session = startSession(db, {\r\n user_id: userId,\r\n task,\r\n execution_context: opts.context as ExecutionContext,\r\n });\r\n\r\n db.close();\r\n\r\n if (opts.quiet) {\r\n console.log(session.id);\r\n } else if (opts.json) {\r\n console.log(JSON.stringify(session, null, 2));\r\n } else {\r\n console.log(`\\nSession started: ${session.id}`);\r\n console.log(` User: ${session.user_id}`);\r\n console.log(` Task: ${session.task}`);\r\n console.log(` Context: ${session.execution_context}`);\r\n console.log(` Started: ${session.started_at}`);\r\n }\r\n } catch (err) {\r\n db?.close();\r\n if ((err as Error).name === \"ExitPromptError\") {\r\n console.log(\"\\nSession cancelled.\");\r\n process.exit(0);\r\n }\r\n console.error(\"Error:\", (err as Error).message);\r\n process.exit(1);\r\n }\r\n });\r\n\r\n// ── Phase 1: Repetition ─────────────────────────────────────────────────────\r\n\r\ninterface RepetitionResult {\r\n reviewed: number;\r\n skipped: boolean;\r\n}\r\n\r\nasync function runRepetitionPhase(\r\n db: Database,\r\n userId: string,\r\n maxMinutes: number,\r\n): Promise<RepetitionResult> {\r\n const queue = buildReviewQueue(db, { userId });\r\n\r\n if (queue.items.length === 0) {\r\n console.log(\"No cards due for review — moving to task selection.\\n\");\r\n return { reviewed: 0, skipped: false };\r\n }\r\n\r\n console.log(\"═\".repeat(50));\r\n console.log(\"Phase 1: Repetition\");\r\n console.log(\"═\".repeat(50));\r\n console.log(`${queue.items.length} card(s) due`);\r\n console.log(` New: ${queue.newCount} Review: ${queue.reviewCount} Relearn: ${queue.relearnCount}`);\r\n console.log(` Domains: ${queue.totalDomains.join(\", \")}`);\r\n console.log(` Time limit: ${maxMinutes} minutes (skip anytime with 's')`);\r\n console.log();\r\n\r\n const startTime = Date.now();\r\n const timeLimitMs = maxMinutes * 60 * 1000;\r\n let reviewed = 0;\r\n\r\n for (const item of queue.items) {\r\n // Check time limit\r\n if (Date.now() - startTime >= timeLimitMs) {\r\n console.log(`\\nTime limit reached (${maxMinutes} min). Moving to task selection.`);\r\n break;\r\n }\r\n\r\n reviewed++;\r\n\r\n const prompt = generatePrompt({\r\n cardId: item.cardId,\r\n tokenId: item.tokenId,\r\n slug: item.slug,\r\n concept: item.concept,\r\n domain: item.domain,\r\n bloomLevel: item.bloomLevel as BloomLevel,\r\n });\r\n\r\n const elapsed = Math.round((Date.now() - startTime) / 60000);\r\n console.log(`[${reviewed}/${queue.items.length}] ${prompt.bloomVerb} (Bloom ${prompt.bloomLevel}) — ${elapsed}/${maxMinutes} min`);\r\n console.log(`Domain: ${prompt.domain || \"(none)\"}`);\r\n console.log(`\\n ${prompt.question}\\n`);\r\n\r\n const rating = await select({\r\n message: \"How did you do?\",\r\n choices: [\r\n { name: \"1 - Again (forgot)\", value: 1 },\r\n { name: \"2 - Hard\", value: 2 },\r\n { name: \"3 - Good\", value: 3 },\r\n { name: \"4 - Easy\", value: 4 },\r\n { name: \"s - Skip to task selection\", value: 0 },\r\n ],\r\n }) as number;\r\n\r\n if (rating === 0) {\r\n console.log(\"Skipping to task selection.\");\r\n reviewed--; // Don't count the skipped card\r\n return { reviewed, skipped: true };\r\n }\r\n\r\n const evalResult = evaluateRating(db, {\r\n cardId: item.cardId,\r\n tokenId: item.tokenId,\r\n userId,\r\n rating: rating as Rating,\r\n });\r\n\r\n if (rating === 1) {\r\n const prereqs = getPrerequisites(db, item.tokenId);\r\n if (prereqs.length > 0) {\r\n const blockResult = cascadeBlock(db, userId, item.slug);\r\n console.log(` Blocked ${blockResult.blockedSlug}. Review these prerequisites:`);\r\n for (const p of blockResult.prerequisites) {\r\n console.log(` - ${p.slug}: ${p.concept}`);\r\n }\r\n }\r\n }\r\n\r\n const ratingLabels: Record<number, string> = { 1: \"Again\", 2: \"Hard\", 3: \"Good\", 4: \"Easy\" };\r\n console.log(` ${ratingLabels[rating]} — next due: ${evalResult.nextDueAt}\\n`);\r\n }\r\n\r\n if (reviewed > 0) {\r\n console.log(\"─\".repeat(50));\r\n console.log(`Repetition complete — ${reviewed} card(s) reviewed.`);\r\n }\r\n\r\n return { reviewed, skipped: false };\r\n}\r\n\r\n// ── Phase 2: Task Selection ─────────────────────────────────────────────────\r\n\r\nasync function selectTask(db: Database): Promise<string> {\r\n console.log(\"═\".repeat(50));\r\n console.log(\"Phase 2: Task Selection\");\r\n console.log(\"═\".repeat(50));\r\n\r\n const adoConfig = loadADOConfig(db);\r\n\r\n if (adoConfig) {\r\n const items = await fetchActiveWorkItems(adoConfig);\r\n\r\n if (items.length > 0) {\r\n const choices = items.map((wi) => ({\r\n name: `[${wi.type}] ${wi.title} (${wi.state})`,\r\n value: `[ADO-${wi.id}] ${wi.title}`,\r\n }));\r\n choices.push({ name: \"Enter a custom task...\", value: \"__custom__\" });\r\n\r\n const picked = await select({\r\n message: `${items.length} active work item(s) — pick one:`,\r\n choices,\r\n });\r\n\r\n if (picked !== \"__custom__\") return picked;\r\n } else {\r\n console.log(\"No active work items found in Azure DevOps.\");\r\n }\r\n }\r\n\r\n return input({ message: \"Task description:\" });\r\n}\r\n\r\n// ── zam session log ───────────────────────────────────────────────────────\r\n\r\nsessionCommand\r\n .command(\"log\")\r\n .description(\"Log a step within a session\")\r\n .requiredOption(\"--session <id>\", \"Session ID\")\r\n .requiredOption(\"--token <slug>\", \"Token slug\")\r\n .requiredOption(\"--done-by <who>\", \"Who performed the step (user or agent)\")\r\n .option(\"--rating <n>\", \"Rating (1-4)\")\r\n .option(\"--json\", \"Output as JSON\")\r\n .option(\"--quiet\", \"Suppress output (exit code only)\")\r\n .action((opts) => {\r\n withDb((db) => {\r\n const token = getTokenBySlug(db, opts.token);\r\n if (!token) {\r\n console.error(`Token not found: ${opts.token}`);\r\n process.exit(1);\r\n }\r\n\r\n const step = logStep(db, {\r\n session_id: opts.session,\r\n token_id: token.id,\r\n done_by: opts.doneBy as \"user\" | \"agent\",\r\n rating: opts.rating ? Number(opts.rating) : undefined,\r\n });\r\n\r\n if (opts.quiet) return;\r\n if (opts.json) {\r\n console.log(JSON.stringify(step, null, 2));\r\n } else {\r\n console.log(`Step logged: ${step.id}`);\r\n console.log(` Token: ${opts.token}`);\r\n console.log(` Done by: ${step.done_by}`);\r\n if (step.rating != null) {\r\n console.log(` Rating: ${step.rating}`);\r\n }\r\n }\r\n });\r\n });\r\n\r\n// ── zam session end ───────────────────────────────────────────────────────\r\n\r\nsessionCommand\r\n .command(\"end\")\r\n .description(\"End a session and show summary\")\r\n .requiredOption(\"--session <id>\", \"Session ID\")\r\n .option(\"--json\", \"Output as JSON\")\r\n .action((opts) => {\r\n withDb((db) => {\r\n endSession(db, opts.session);\r\n const summary = getSessionSummary(db, opts.session);\r\n\r\n if (opts.json) {\r\n console.log(JSON.stringify(summary, null, 2));\r\n return;\r\n }\r\n\r\n console.log(`Session ${summary.session.id} completed.`);\r\n console.log(` Task: ${summary.session.task}`);\r\n console.log(` Started: ${summary.session.started_at}`);\r\n console.log(` Completed: ${summary.session.completed_at}`);\r\n console.log(` Steps: ${summary.steps.length}`);\r\n\r\n if (summary.steps.length > 0) {\r\n console.log(\"\\nSteps:\");\r\n console.log(\r\n \" Token Done by Rating Concept\",\r\n );\r\n console.log(\" \" + \"─\".repeat(70));\r\n for (const s of summary.steps) {\r\n console.log(\r\n ` ${s.slug.padEnd(21)} ${s.done_by.padEnd(8)} ${String(s.rating ?? \"-\").padEnd(7)} ${s.concept.slice(0, 30)}`,\r\n );\r\n }\r\n }\r\n });\r\n });\r\n","/**\r\n * `zam stats` — Learning dashboard.\r\n */\r\n\r\nimport { Command } from \"commander\";\r\nimport type { Database } from \"libsql\";\r\nimport {\r\n openDatabase,\r\n getUserStats,\r\n getDomainCompetence,\r\n} from \"../../kernel/index.js\";\r\nimport { resolveUser } from \"./resolve-user.js\";\r\n\r\nfunction withDb(fn: (db: Database) => void): void {\r\n let db: Database | undefined;\r\n try {\r\n db = openDatabase();\r\n fn(db);\r\n } catch (err) {\r\n console.error(\"Error:\", (err as Error).message);\r\n process.exit(1);\r\n } finally {\r\n db?.close();\r\n }\r\n}\r\n\r\nexport const statsCommand = new Command(\"stats\")\r\n .description(\"Show learning dashboard for a user\")\r\n .option(\"--user <id>\", \"User ID (default: whoami)\")\r\n .option(\"--json\", \"Output as JSON\")\r\n .action((opts) => {\r\n withDb((db) => {\r\n const userId = resolveUser(opts, db);\r\n const stats = getUserStats(db, userId);\r\n const domains = getDomainCompetence(db, userId);\r\n\r\n if (opts.json) {\r\n console.log(JSON.stringify({ stats, domains }, null, 2));\r\n return;\r\n }\r\n\r\n console.log(`Learning Dashboard — ${stats.userId}`);\r\n console.log(\"═\".repeat(50));\r\n console.log(` Total tokens: ${stats.totalTokens}`);\r\n console.log(` Cards in deck: ${stats.cardsInDeck}`);\r\n console.log(` Due today: ${stats.dueToday}`);\r\n console.log(` Blocked: ${stats.blocked}`);\r\n console.log(` Mature: ${stats.mature}`);\r\n console.log(` Avg stability: ${stats.avgStability ?? \"N/A\"}`);\r\n console.log(` Total sessions: ${stats.totalSessions}`);\r\n console.log(` Last session: ${stats.lastSession ?? \"N/A\"}`);\r\n\r\n if (domains.length > 0) {\r\n console.log(\"\\nDomain Competence:\");\r\n console.log(\"─\".repeat(80));\r\n console.log(\r\n \" Domain Cards Mature Stability Retention Suggested Mode\",\r\n );\r\n console.log(\" \" + \"─\".repeat(74));\r\n for (const d of domains) {\r\n console.log(\r\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}`,\r\n );\r\n }\r\n }\r\n });\r\n });\r\n","/**\r\n * `zam review` — Interactive review session.\r\n */\r\n\r\nimport { Command } from \"commander\";\r\nimport type { Database } from \"libsql\";\r\nimport { select, input } from \"@inquirer/prompts\";\r\nimport {\r\n openDatabase,\r\n buildReviewQueue,\r\n generatePrompt,\r\n evaluateRating,\r\n cascadeBlock,\r\n getPrerequisites,\r\n} from \"../../kernel/index.js\";\r\nimport type { Rating, BloomLevel } from \"../../kernel/index.js\";\r\nimport { resolveUser } from \"./resolve-user.js\";\r\n\r\nexport const reviewCommand = new Command(\"review\")\r\n .description(\"Start an interactive review session\")\r\n .option(\"--user <id>\", \"User ID (default: whoami)\")\r\n .option(\"--max-new <n>\", \"Maximum new cards\", \"10\")\r\n .option(\"--max-reviews <n>\", \"Maximum review cards\", \"50\")\r\n .action(async (opts) => {\r\n let db: Database | undefined;\r\n try {\r\n db = openDatabase();\r\n const userId = resolveUser(opts, db);\r\n\r\n const queue = buildReviewQueue(db, {\r\n userId,\r\n maxNew: Number(opts.maxNew),\r\n maxReviews: Number(opts.maxReviews),\r\n });\r\n\r\n if (queue.items.length === 0) {\r\n console.log(\"No cards due for review. You're all caught up!\");\r\n db.close();\r\n return;\r\n }\r\n\r\n console.log(`\\nReview session: ${queue.items.length} card(s)`);\r\n console.log(` New: ${queue.newCount} Review: ${queue.reviewCount} Relearn: ${queue.relearnCount}`);\r\n console.log(` Domains: ${queue.totalDomains.join(\", \")}`);\r\n console.log();\r\n\r\n let completed = 0;\r\n const results: Array<{\r\n slug: string;\r\n rating: number;\r\n nextDue: string;\r\n }> = [];\r\n\r\n for (const item of queue.items) {\r\n completed++;\r\n\r\n const prompt = generatePrompt({\r\n cardId: item.cardId,\r\n tokenId: item.tokenId,\r\n slug: item.slug,\r\n concept: item.concept,\r\n domain: item.domain,\r\n bloomLevel: item.bloomLevel as BloomLevel,\r\n });\r\n\r\n console.log(`\\n[${ completed }/${queue.items.length}] ${prompt.bloomVerb} (Bloom ${prompt.bloomLevel})`);\r\n console.log(`Domain: ${prompt.domain || \"(none)\"}`);\r\n console.log(`\\n ${prompt.question}\\n`);\r\n\r\n const rating = await select({\r\n message: \"How did you do?\",\r\n choices: [\r\n { name: \"1 - Again (forgot)\", value: 1 },\r\n { name: \"2 - Hard\", value: 2 },\r\n { name: \"3 - Good\", value: 3 },\r\n { name: \"4 - Easy\", value: 4 },\r\n ],\r\n }) as Rating;\r\n\r\n const evalResult = evaluateRating(db, {\r\n cardId: item.cardId,\r\n tokenId: item.tokenId,\r\n userId,\r\n rating,\r\n });\r\n\r\n // If rating 1 and token has prereqs, cascade block\r\n if (rating === 1) {\r\n const prereqs = getPrerequisites(db, item.tokenId);\r\n if (prereqs.length > 0) {\r\n const blockResult = cascadeBlock(db, userId, item.slug);\r\n console.log(` Blocked ${blockResult.blockedSlug}. Review these prerequisites:`);\r\n for (const p of blockResult.prerequisites) {\r\n console.log(` - ${p.slug}: ${p.concept}`);\r\n }\r\n }\r\n }\r\n\r\n const ratingLabels: Record<number, string> = { 1: \"Again\", 2: \"Hard\", 3: \"Good\", 4: \"Easy\" };\r\n console.log(` ${ratingLabels[rating]} — next due: ${evalResult.nextDueAt}`);\r\n\r\n results.push({\r\n slug: item.slug,\r\n rating,\r\n nextDue: evalResult.nextDueAt,\r\n });\r\n }\r\n\r\n // Session summary\r\n console.log(\"\\n\" + \"═\".repeat(50));\r\n console.log(\"Review session complete!\");\r\n console.log(` Cards reviewed: ${results.length}`);\r\n\r\n const avgRating = results.reduce((s, r) => s + r.rating, 0) / results.length;\r\n console.log(` Average rating: ${avgRating.toFixed(1)}`);\r\n\r\n const forgot = results.filter((r) => r.rating === 1).length;\r\n if (forgot > 0) {\r\n console.log(` Forgot: ${forgot} card(s)`);\r\n }\r\n\r\n db.close();\r\n } catch (err) {\r\n db?.close();\r\n // User cancelled with Ctrl+C — exit gracefully\r\n if ((err as Error).name === \"ExitPromptError\") {\r\n console.log(\"\\nReview session cancelled.\");\r\n process.exit(0);\r\n }\r\n console.error(\"Error:\", (err as Error).message);\r\n process.exit(1);\r\n }\r\n });\r\n","/**\r\n * `zam bridge` — Machine-readable JSON protocol for AI integration.\r\n *\r\n * All output is valid JSON only. No human-readable formatting.\r\n * Errors are also JSON: { \"error\": \"message\" }\r\n */\r\n\r\nimport { Command } from \"commander\";\r\nimport type { Database } from \"libsql\";\r\nimport {\r\n openDatabase,\r\n getDueCards,\r\n buildReviewQueue,\r\n generatePrompt,\r\n evaluateRating,\r\n ensureCard,\r\n createToken,\r\n getTokenBySlug,\r\n cascadeBlock,\r\n getPrerequisites,\r\n getAgentSkill,\r\n listAgentSkills,\r\n readMonitorLog,\r\n pairCommands,\r\n analyzeObservation,\r\n monitorLogExists,\r\n discoverSkills,\r\n} from \"../../kernel/index.js\";\r\nimport type { Rating, BloomLevel, TokenPattern } from \"../../kernel/index.js\";\r\nimport { readdirSync } from \"node:fs\";\r\nimport { homedir } from \"node:os\";\r\nimport { join } from \"node:path\";\r\nimport { resolveUser } from \"./resolve-user.js\";\r\n\r\nfunction jsonOut(data: unknown): void {\r\n console.log(JSON.stringify(data, null, 2));\r\n}\r\n\r\nfunction jsonError(message: string): never {\r\n console.log(JSON.stringify({ error: message }, null, 2));\r\n process.exit(1);\r\n}\r\n\r\nfunction withDb(fn: (db: Database) => void): void {\r\n let db: Database | undefined;\r\n try {\r\n db = openDatabase();\r\n fn(db);\r\n } catch (err) {\r\n db?.close();\r\n jsonError((err as Error).message);\r\n } finally {\r\n db?.close();\r\n }\r\n}\r\n\r\nexport const bridgeCommand = new Command(\"bridge\")\r\n .description(\"Machine-readable JSON protocol for AI integration\");\r\n\r\n// ── zam bridge check-due ──────────────────────────────────────────────────\r\n\r\nbridgeCommand\r\n .command(\"check-due\")\r\n .description(\"Check due cards for a user (JSON)\")\r\n .option(\"--user <id>\", \"User ID (default: whoami)\")\r\n .action((opts) => {\r\n withDb((db) => {\r\n const userId = resolveUser(opts, db, { json: true });\r\n const dueCards = getDueCards(db, userId);\r\n const domains = [...new Set(dueCards.map((c) => c.domain).filter(Boolean))].sort();\r\n\r\n jsonOut({\r\n userId,\r\n dueCount: dueCards.length,\r\n domains,\r\n cards: dueCards.map((c) => ({\r\n cardId: c.id,\r\n tokenId: c.token_id,\r\n slug: c.slug,\r\n concept: c.concept,\r\n domain: c.domain,\r\n bloomLevel: c.bloom_level,\r\n state: c.state,\r\n dueAt: c.due_at,\r\n })),\r\n });\r\n });\r\n });\r\n\r\n// ── zam bridge get-review ─────────────────────────────────────────────────\r\n\r\nbridgeCommand\r\n .command(\"get-review\")\r\n .description(\"Get next review card with prompt (JSON)\")\r\n .option(\"--user <id>\", \"User ID (default: whoami)\")\r\n .action((opts) => {\r\n withDb((db) => {\r\n const userId = resolveUser(opts, db, { json: true });\r\n const queue = buildReviewQueue(db, { userId, maxReviews: 1, maxNew: 1 });\r\n\r\n if (queue.items.length === 0) {\r\n jsonOut({\r\n userId,\r\n hasReview: false,\r\n card: null,\r\n prompt: null,\r\n queueSize: 0,\r\n });\r\n return;\r\n }\r\n\r\n const item = queue.items[0];\r\n const prompt = generatePrompt({\r\n cardId: item.cardId,\r\n tokenId: item.tokenId,\r\n slug: item.slug,\r\n concept: item.concept,\r\n domain: item.domain,\r\n bloomLevel: item.bloomLevel as BloomLevel,\r\n });\r\n\r\n // Get full queue size for context\r\n const fullQueue = buildReviewQueue(db, { userId });\r\n\r\n jsonOut({\r\n userId,\r\n hasReview: true,\r\n card: item,\r\n prompt,\r\n queueSize: fullQueue.items.length,\r\n });\r\n });\r\n });\r\n\r\n// ── zam bridge submit ─────────────────────────────────────────────────────\r\n\r\nbridgeCommand\r\n .command(\"submit\")\r\n .description(\"Submit a rating for a card (JSON)\")\r\n .option(\"--user <id>\", \"User ID (default: whoami)\")\r\n .requiredOption(\"--card-id <id>\", \"Card ID\")\r\n .requiredOption(\"--rating <n>\", \"Rating (1-4)\")\r\n .action((opts) => {\r\n withDb((db) => {\r\n const userId = resolveUser(opts, db, { json: true });\r\n const rating = Number(opts.rating) as Rating;\r\n if (rating < 1 || rating > 4) {\r\n jsonError(\"Rating must be between 1 and 4\");\r\n }\r\n\r\n // Look up the card to get tokenId\r\n const card = db\r\n .prepare(\"SELECT * FROM cards WHERE id = ?\")\r\n .get(opts.cardId) as { id: string; token_id: string; user_id: string } | undefined;\r\n\r\n if (!card) {\r\n jsonError(`Card not found: ${opts.cardId}`);\r\n }\r\n\r\n const result = evaluateRating(db, {\r\n cardId: opts.cardId,\r\n tokenId: card!.token_id,\r\n userId,\r\n rating,\r\n });\r\n\r\n let blocked = null;\r\n if (rating === 1) {\r\n const token = db\r\n .prepare(\"SELECT slug FROM tokens WHERE id = ?\")\r\n .get(card!.token_id) as { slug: string } | undefined;\r\n\r\n if (token) {\r\n const prereqs = getPrerequisites(db, card!.token_id);\r\n if (prereqs.length > 0) {\r\n blocked = cascadeBlock(db, userId, token.slug);\r\n }\r\n }\r\n }\r\n\r\n jsonOut({\r\n success: true,\r\n rating,\r\n evaluation: result,\r\n blocked,\r\n });\r\n });\r\n });\r\n\r\n// ── zam bridge get-skill ──────────────────────────────────────────────────\r\n\r\nbridgeCommand\r\n .command(\"get-skill\")\r\n .description(\"Get an agent skill by slug (JSON)\")\r\n .requiredOption(\"--slug <slug>\", \"Skill slug\")\r\n .action((opts) => {\r\n withDb((db) => {\r\n const skill = getAgentSkill(db, opts.slug);\r\n if (!skill) {\r\n jsonError(`Skill not found: ${opts.slug}`);\r\n }\r\n\r\n jsonOut({\r\n slug: skill!.slug,\r\n description: skill!.description,\r\n steps: skill!.steps,\r\n tokenSlugs: skill!.token_slugs,\r\n source: skill!.source,\r\n });\r\n });\r\n });\r\n\r\n// ── zam bridge get-monitor ────────────────────────────────────────────────\r\n\r\nbridgeCommand\r\n .command(\"get-monitor\")\r\n .description(\"Read monitor log for a session (JSON)\")\r\n .requiredOption(\"--session <id>\", \"Session ID\")\r\n .action((opts) => {\r\n if (!monitorLogExists(opts.session)) {\r\n jsonOut({ sessionId: opts.session, exists: false, commands: [], timeSpan: null });\r\n return;\r\n }\r\n\r\n const events = readMonitorLog(opts.session);\r\n const commands = pairCommands(events);\r\n\r\n let timeSpan: { start: string; end: string; durationMs: number } | null = null;\r\n if (commands.length > 0) {\r\n const first = commands[0];\r\n const last = commands[commands.length - 1];\r\n const endTs = last.endedAt ?? last.startedAt;\r\n timeSpan = {\r\n start: first.startedAt,\r\n end: endTs,\r\n durationMs: new Date(endTs).getTime() - new Date(first.startedAt).getTime(),\r\n };\r\n }\r\n\r\n jsonOut({\r\n sessionId: opts.session,\r\n exists: true,\r\n commands: commands.map((c) => ({\r\n seq: c.seq,\r\n command: c.command,\r\n cwd: c.cwd,\r\n startedAt: c.startedAt,\r\n endedAt: c.endedAt,\r\n durationMs: c.durationMs,\r\n exitCode: c.exitCode,\r\n })),\r\n timeSpan,\r\n });\r\n });\r\n\r\n// ── zam bridge analyze-monitor ───────────────────────────────────────────\r\n\r\nbridgeCommand\r\n .command(\"analyze-monitor\")\r\n .description(\"Analyze monitor log with token patterns from stdin (JSON)\")\r\n .requiredOption(\"--session <id>\", \"Session ID\")\r\n .action(async (opts) => {\r\n try {\r\n if (!monitorLogExists(opts.session)) {\r\n jsonOut({ sessionId: opts.session, ratings: [], unmatchedCommands: [], timeSpan: null });\r\n return;\r\n }\r\n\r\n // Read token patterns from stdin\r\n const chunks: Buffer[] = [];\r\n for await (const chunk of process.stdin) {\r\n chunks.push(chunk as Buffer);\r\n }\r\n const raw = Buffer.concat(chunks).toString(\"utf-8\").trim();\r\n\r\n if (!raw) {\r\n jsonError(\"No input received on stdin. Pipe JSON with token patterns.\");\r\n }\r\n\r\n let data: { patterns: TokenPattern[] };\r\n try {\r\n data = JSON.parse(raw);\r\n } catch {\r\n jsonError(\"Invalid JSON input\");\r\n }\r\n\r\n if (!Array.isArray(data!.patterns)) {\r\n jsonError(\"JSON must include 'patterns' array\");\r\n }\r\n\r\n const events = readMonitorLog(opts.session);\r\n const commands = pairCommands(events);\r\n const result = analyzeObservation(commands, data!.patterns);\r\n\r\n jsonOut({\r\n sessionId: opts.session,\r\n ...result,\r\n });\r\n } catch (err) {\r\n jsonError((err as Error).message);\r\n }\r\n });\r\n\r\n// ── zam bridge add-token ──────────────────────────────────────────────────\r\n\r\nbridgeCommand\r\n .command(\"add-token\")\r\n .description(\"Create a token + card from JSON stdin\")\r\n .option(\"--user <id>\", \"User ID (default: whoami)\")\r\n .action(async (opts) => {\r\n let db: Database | undefined;\r\n try {\r\n // Read JSON from stdin\r\n const chunks: Buffer[] = [];\r\n for await (const chunk of process.stdin) {\r\n chunks.push(chunk as Buffer);\r\n }\r\n const raw = Buffer.concat(chunks).toString(\"utf-8\").trim();\r\n\r\n if (!raw) {\r\n jsonError(\"No input received on stdin. Pipe JSON with token data.\");\r\n }\r\n\r\n let data: {\r\n slug: string;\r\n concept: string;\r\n domain?: string;\r\n bloom_level?: number;\r\n context?: string;\r\n symbiosis_mode?: string | null;\r\n };\r\n\r\n try {\r\n data = JSON.parse(raw);\r\n } catch {\r\n jsonError(\"Invalid JSON input\");\r\n }\r\n\r\n if (!data!.slug || !data!.concept) {\r\n jsonError(\"JSON must include 'slug' and 'concept' fields\");\r\n }\r\n\r\n db = openDatabase();\r\n const userId = resolveUser(opts, db, { json: true });\r\n\r\n const token = createToken(db, {\r\n slug: data!.slug,\r\n concept: data!.concept,\r\n domain: data!.domain,\r\n bloom_level: (data!.bloom_level ?? 1) as BloomLevel,\r\n context: data!.context,\r\n symbiosis_mode: data!.symbiosis_mode as \"shadowing\" | \"copilot\" | \"autonomy\" | null | undefined,\r\n });\r\n\r\n const card = ensureCard(db, token.id, userId);\r\n\r\n jsonOut({\r\n success: true,\r\n token,\r\n card: {\r\n id: card.id,\r\n tokenId: card.token_id,\r\n userId: card.user_id,\r\n state: card.state,\r\n dueAt: card.due_at,\r\n blocked: card.blocked,\r\n },\r\n });\r\n\r\n db.close();\r\n } catch (err) {\r\n db?.close();\r\n // If it's already a JSON error exit, let it propagate\r\n if ((err as Error).message) {\r\n jsonError((err as Error).message);\r\n }\r\n }\r\n });\r\n\r\n// ── zam bridge discover-skills ──────────────────────────────────────────────\r\n\r\nbridgeCommand\r\n .command(\"discover-skills\")\r\n .description(\"Analyze monitor logs across sessions to discover recurring patterns\")\r\n .option(\"--min-sessions <n>\", \"Minimum sessions a pattern must appear in (default: 2)\", \"2\")\r\n .option(\"--limit <n>\", \"Max number of sessions to analyze (default: 20)\", \"20\")\r\n .action((opts) => {\r\n try {\r\n const monitorDir = join(homedir(), \".zam\", \"monitor\");\r\n let files: string[];\r\n try {\r\n files = readdirSync(monitorDir).filter((f) => f.endsWith(\".jsonl\"));\r\n } catch {\r\n jsonOut({ proposals: [], message: \"No monitor logs found.\" });\r\n return;\r\n }\r\n\r\n if (files.length === 0) {\r\n jsonOut({ proposals: [], message: \"No monitor logs found.\" });\r\n return;\r\n }\r\n\r\n // Take the most recent N sessions by file modification time\r\n const limit = Number(opts.limit);\r\n const sorted = files\r\n .map((f) => ({ name: f, path: join(monitorDir, f) }))\r\n .sort((a, b) => b.name.localeCompare(a.name)) // ULID session IDs sort chronologically\r\n .slice(0, limit);\r\n\r\n // Load and parse each session's commands\r\n const sessionCommands = new Map<string, ReturnType<typeof pairCommands>>();\r\n for (const file of sorted) {\r\n const sessionId = file.name.replace(\".jsonl\", \"\");\r\n const events = readMonitorLog(sessionId);\r\n const commands = pairCommands(events);\r\n if (commands.length > 0) {\r\n sessionCommands.set(sessionId, commands);\r\n }\r\n }\r\n\r\n if (sessionCommands.size === 0) {\r\n jsonOut({ proposals: [], message: \"No command data in monitor logs.\" });\r\n return;\r\n }\r\n\r\n // Get existing skills to exclude\r\n let existingSkillSlugs: string[] = [];\r\n let db;\r\n try {\r\n db = openDatabase();\r\n existingSkillSlugs = listAgentSkills(db).map((s) => s.slug);\r\n } catch {\r\n // DB not available — proceed without exclusion\r\n } finally {\r\n db?.close();\r\n }\r\n\r\n const proposals = discoverSkills(sessionCommands, {\r\n minSessions: Number(opts.minSessions),\r\n existingSkillSlugs,\r\n });\r\n\r\n jsonOut({\r\n sessionsAnalyzed: sessionCommands.size,\r\n proposals,\r\n });\r\n } catch (err) {\r\n jsonError((err as Error).message);\r\n }\r\n });\r\n","/**\r\n * `zam skill` — Manage agent skill entries (task recipes).\r\n */\r\n\r\nimport { Command } from \"commander\";\r\nimport type { Database } from \"libsql\";\r\nimport {\r\n openDatabase,\r\n createAgentSkill,\r\n getAgentSkill,\r\n listAgentSkills,\r\n} from \"../../kernel/index.js\";\r\n\r\nfunction withDb(fn: (db: Database) => void): void {\r\n let db: Database | undefined;\r\n try {\r\n db = openDatabase();\r\n fn(db);\r\n } catch (err) {\r\n console.error(\"Error:\", (err as Error).message);\r\n process.exit(1);\r\n } finally {\r\n db?.close();\r\n }\r\n}\r\n\r\nexport const skillCommand = new Command(\"skill\")\r\n .description(\"Manage agent skill entries (task recipes)\");\r\n\r\n// ── zam skill list ────────────────────────────────────────────────────────\r\n\r\nskillCommand\r\n .command(\"list\")\r\n .description(\"List all agent skills\")\r\n .option(\"--json\", \"Output as JSON\")\r\n .action((opts) => {\r\n withDb((db) => {\r\n const skills = listAgentSkills(db);\r\n\r\n if (opts.json) {\r\n console.log(JSON.stringify(skills, null, 2));\r\n return;\r\n }\r\n\r\n if (skills.length === 0) {\r\n console.log(\"No agent skills registered yet.\");\r\n return;\r\n }\r\n\r\n console.log(`Agent Skills (${skills.length})`);\r\n console.log(\"─\".repeat(60));\r\n for (const s of skills) {\r\n console.log(` ${s.slug.padEnd(30)} [${s.source}] ${s.description.slice(0, 40)}`);\r\n console.log(` ${s.steps.length} step(s) tokens: ${s.token_slugs.join(\", \") || \"none\"}`);\r\n }\r\n });\r\n });\r\n\r\n// ── zam skill show ────────────────────────────────────────────────────────\r\n\r\nskillCommand\r\n .command(\"show\")\r\n .description(\"Show a specific agent skill\")\r\n .requiredOption(\"--slug <slug>\", \"Skill slug\")\r\n .option(\"--json\", \"Output as JSON\")\r\n .action((opts) => {\r\n withDb((db) => {\r\n const skill = getAgentSkill(db, opts.slug);\r\n if (!skill) {\r\n console.error(`Skill not found: ${opts.slug}`);\r\n process.exit(1);\r\n }\r\n\r\n if (opts.json) {\r\n console.log(JSON.stringify(skill, null, 2));\r\n return;\r\n }\r\n\r\n console.log(`Skill: ${skill.slug}`);\r\n console.log(` Description: ${skill.description}`);\r\n console.log(` Source: ${skill.source}`);\r\n console.log(` Tokens: ${skill.token_slugs.join(\", \") || \"none\"}`);\r\n console.log(` Created: ${skill.created_at}`);\r\n console.log(`\\nSteps:`);\r\n skill.steps.forEach((step, i) => {\r\n console.log(` ${i + 1}. ${step}`);\r\n });\r\n });\r\n });\r\n\r\n// ── zam skill add ─────────────────────────────────────────────────────────\r\n\r\nskillCommand\r\n .command(\"add\")\r\n .description(\"Register a new agent skill\")\r\n .requiredOption(\"--slug <slug>\", \"Unique skill identifier\")\r\n .requiredOption(\"--description <text>\", \"One-sentence description\")\r\n .requiredOption(\"--steps <json>\", \"JSON array of step strings\")\r\n .option(\"--tokens <slugs>\", \"Comma-separated token slugs related to this skill\")\r\n .option(\"--source <type>\", \"Source: learned | builtin (default: learned)\", \"learned\")\r\n .option(\"--json\", \"Output as JSON\")\r\n .action((opts) => {\r\n withDb((db) => {\r\n let steps: string[];\r\n try {\r\n steps = JSON.parse(opts.steps) as string[];\r\n if (!Array.isArray(steps)) throw new Error(\"steps must be a JSON array\");\r\n } catch {\r\n console.error(\"Invalid --steps: must be a valid JSON array of strings\");\r\n process.exit(1);\r\n }\r\n\r\n const tokenSlugs = opts.tokens\r\n ? opts.tokens.split(\",\").map((s: string) => s.trim()).filter(Boolean)\r\n : [];\r\n\r\n const skill = createAgentSkill(db, {\r\n slug: opts.slug,\r\n description: opts.description,\r\n steps,\r\n token_slugs: tokenSlugs,\r\n source: opts.source as \"learned\" | \"builtin\",\r\n });\r\n\r\n if (opts.json) {\r\n console.log(JSON.stringify(skill, null, 2));\r\n } else {\r\n console.log(`Skill registered: ${skill.slug}`);\r\n console.log(` ${skill.steps.length} step(s) saved`);\r\n }\r\n });\r\n });\r\n","/**\r\n * `zam monitor` — Shell observation for real-time task monitoring.\r\n *\r\n * Installs shell hooks (zsh/bash) that capture commands with timing,\r\n * exit codes, and working directory to a JSONL file. The agent reads\r\n * this log to infer ratings for knowledge tokens.\r\n *\r\n * Usage:\r\n * eval \"$(zam monitor start --session <id>)\" # install hooks\r\n * eval \"$(zam monitor stop --session <id>)\" # remove hooks\r\n * zam monitor status --session <id> # check log stats\r\n */\r\n\r\nimport { Command } from \"commander\";\r\nimport { basename, join } from \"node:path\";\r\nimport { execSync } from \"node:child_process\";\r\nimport { writeFileSync, unlinkSync } from \"node:fs\";\r\nimport { tmpdir } from \"node:os\";\r\nimport type { Database } from \"libsql\";\r\nimport {\r\n openDatabase,\r\n ensureMonitorDir,\r\n getMonitorPath,\r\n writeMonitorEvent,\r\n readMonitorLog,\r\n pairCommands,\r\n monitorLogExists,\r\n getMonitorLogStats,\r\n generateZshHooks,\r\n generateBashHooks,\r\n generateZshUnhooks,\r\n generateBashUnhooks,\r\n getSetting,\r\n setSetting,\r\n} from \"../../kernel/index.js\";\r\nimport type { MonitorEvent } from \"../../kernel/index.js\";\r\n\r\nfunction detectShell(): \"zsh\" | \"bash\" {\r\n const shell = process.env.SHELL ?? \"\";\r\n return basename(shell) === \"bash\" ? \"bash\" : \"zsh\";\r\n}\r\n\r\nexport const monitorCommand = new Command(\"monitor\")\r\n .description(\"Shell observation for real-time task monitoring\");\r\n\r\n// ── zam monitor start ─────────────────────────────────────────────────────\r\n\r\nmonitorCommand\r\n .command(\"start\")\r\n .description(\"Output shell hook code to install monitoring (wrap with eval)\")\r\n .requiredOption(\"--session <id>\", \"Session ID to monitor\")\r\n .option(\"--shell <type>\", \"Shell type: zsh | bash (auto-detected from $SHELL)\")\r\n .action((opts) => {\r\n // Validate session exists\r\n let db: Database | undefined;\r\n try {\r\n db = openDatabase();\r\n const session = db\r\n .prepare(\"SELECT id, completed_at FROM sessions WHERE id = ?\")\r\n .get(opts.session) as { id: string; completed_at: string | null } | undefined;\r\n\r\n if (!session) {\r\n console.error(`# Error: Session not found: ${opts.session}`);\r\n process.exit(1);\r\n }\r\n if (session.completed_at) {\r\n console.error(`# Error: Session already completed: ${opts.session}`);\r\n process.exit(1);\r\n }\r\n } catch (err) {\r\n console.error(`# Error: ${(err as Error).message}`);\r\n process.exit(1);\r\n } finally {\r\n db?.close();\r\n }\r\n\r\n ensureMonitorDir();\r\n const monitorFile = getMonitorPath(opts.session);\r\n\r\n // Write initial meta event\r\n const meta: MonitorEvent = {\r\n type: \"monitor_meta\",\r\n ts: new Date().toISOString(),\r\n event: \"start\",\r\n session_id: opts.session,\r\n shell: opts.shell ?? detectShell(),\r\n pid: process.pid,\r\n };\r\n writeMonitorEvent(opts.session, meta);\r\n\r\n // Output hook code to stdout\r\n const shell = opts.shell ?? detectShell();\r\n if (shell === \"bash\") {\r\n console.log(generateBashHooks(monitorFile, opts.session));\r\n } else {\r\n console.log(generateZshHooks(monitorFile, opts.session));\r\n }\r\n });\r\n\r\n// ── zam monitor stop ──────────────────────────────────────────────────────\r\n\r\nmonitorCommand\r\n .command(\"stop\")\r\n .description(\"Output shell code to remove monitoring hooks (wrap with eval)\")\r\n .requiredOption(\"--session <id>\", \"Session ID\")\r\n .option(\"--shell <type>\", \"Shell type: zsh | bash (auto-detected from $SHELL)\")\r\n .action((opts) => {\r\n // Write stop meta event\r\n if (monitorLogExists(opts.session)) {\r\n const meta: MonitorEvent = {\r\n type: \"monitor_meta\",\r\n ts: new Date().toISOString(),\r\n event: \"stop\",\r\n session_id: opts.session,\r\n };\r\n writeMonitorEvent(opts.session, meta);\r\n }\r\n\r\n const shell = opts.shell ?? detectShell();\r\n if (shell === \"bash\") {\r\n console.log(generateBashUnhooks());\r\n } else {\r\n console.log(generateZshUnhooks());\r\n }\r\n });\r\n\r\n// ── zam monitor status ────────────────────────────────────────────────────\r\n\r\nmonitorCommand\r\n .command(\"status\")\r\n .description(\"Show monitoring status for a session\")\r\n .requiredOption(\"--session <id>\", \"Session ID\")\r\n .option(\"--json\", \"Output as JSON\")\r\n .action((opts) => {\r\n const stats = getMonitorLogStats(opts.session);\r\n\r\n if (!stats.exists) {\r\n if (opts.json) {\r\n console.log(JSON.stringify({ exists: false }));\r\n } else {\r\n console.log(`No monitor log found for session ${opts.session}`);\r\n }\r\n return;\r\n }\r\n\r\n const events = readMonitorLog(opts.session);\r\n const commands = pairCommands(events);\r\n const errors = commands.filter((c) => c.exitCode != null && c.exitCode !== 0).length;\r\n\r\n const meta = events.find((e) => e.type === \"monitor_meta\" && e.event === \"start\");\r\n const stopped = events.some((e) => e.type === \"monitor_meta\" && e.event === \"stop\");\r\n\r\n const result = {\r\n sessionId: opts.session,\r\n exists: true,\r\n active: !stopped,\r\n shell: meta?.shell ?? \"unknown\",\r\n totalCommands: commands.length,\r\n errors,\r\n sizeBytes: stats.sizeBytes,\r\n timeSpan: commands.length > 0\r\n ? {\r\n start: commands[0].startedAt,\r\n end: commands[commands.length - 1].endedAt ?? commands[commands.length - 1].startedAt,\r\n }\r\n : null,\r\n };\r\n\r\n if (opts.json) {\r\n console.log(JSON.stringify(result, null, 2));\r\n return;\r\n }\r\n\r\n console.log(`Monitor: ${opts.session}`);\r\n console.log(` Status: ${result.active ? \"active\" : \"stopped\"}`);\r\n console.log(` Shell: ${result.shell}`);\r\n console.log(` Commands: ${result.totalCommands}`);\r\n console.log(` Errors: ${result.errors}`);\r\n if (result.timeSpan) {\r\n console.log(` From: ${result.timeSpan.start}`);\r\n console.log(` To: ${result.timeSpan.end}`);\r\n }\r\n });\r\n\r\n// ── zam monitor open ─────────────────────────────────────────────────────\r\n\r\n/**\r\n * Resolve the `zam` binary path — built CLI if available, otherwise tsx source.\r\n * This ensures the eval in the spawned terminal uses the correct entrypoint.\r\n */\r\nfunction resolveZamBin(): string {\r\n try {\r\n // Prefer the built CLI (installed via npm link or global install)\r\n const which = execSync(\"which zam 2>/dev/null\", { encoding: \"utf-8\" }).trim();\r\n if (which) return which;\r\n } catch {\r\n // not installed globally\r\n }\r\n // Fallback: use absolute path to the built CLI or source\r\n const projectRoot = join(import.meta.dirname, \"..\", \"..\", \"..\");\r\n return `npx --prefix ${JSON.stringify(projectRoot)} tsx ${join(projectRoot, \"src/cli/index.ts\")}`;\r\n}\r\n\r\n/**\r\n * Detect whether iTerm2 is running (preferred on macOS).\r\n */\r\nfunction isItermRunning(): boolean {\r\n try {\r\n const result = execSync(\r\n \"osascript -e 'tell application \\\"System Events\\\" to (name of processes) contains \\\"iTerm2\\\"' 2>/dev/null\",\r\n { encoding: \"utf-8\" },\r\n ).trim();\r\n return result === \"true\";\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\nmonitorCommand\r\n .command(\"open\")\r\n .description(\"Open a new monitored terminal window for a session\")\r\n .requiredOption(\"--session <id>\", \"Session ID to monitor\")\r\n .option(\"--dir <path>\", \"Working directory (defaults to cwd)\")\r\n .option(\"--shell <type>\", \"Shell type: zsh | bash (auto-detected from $SHELL)\")\r\n .action((opts) => {\r\n // Validate session exists\r\n let db: Database | undefined;\r\n try {\r\n db = openDatabase();\r\n const session = db\r\n .prepare(\"SELECT id, completed_at FROM sessions WHERE id = ?\")\r\n .get(opts.session) as { id: string; completed_at: string | null } | undefined;\r\n\r\n if (!session) {\r\n console.error(`Error: Session not found: ${opts.session}`);\r\n process.exit(1);\r\n }\r\n if (session.completed_at) {\r\n console.error(`Error: Session already completed: ${opts.session}`);\r\n process.exit(1);\r\n }\r\n\r\n // Save monitor preference so the agent knows to default to terminal\r\n if (!getSetting(db, \"monitor_method\")) {\r\n setSetting(db, \"monitor_method\", \"terminal\");\r\n }\r\n } catch (err) {\r\n console.error(`Error: ${(err as Error).message}`);\r\n process.exit(1);\r\n } finally {\r\n db?.close();\r\n }\r\n\r\n const dir = opts.dir ?? process.cwd();\r\n const zamBin = resolveZamBin();\r\n const shellSetup = `cd ${JSON.stringify(dir)} && eval \"$(${zamBin} monitor start --session ${opts.session})\"`;\r\n\r\n if (process.platform === \"darwin\") {\r\n openMacTerminal(shellSetup, opts.session, dir);\r\n } else {\r\n console.log(`Run this in a new terminal:\\n`);\r\n console.log(` ${shellSetup}\\n`);\r\n console.log(`(Automatic terminal opening is only supported on macOS for now.)`);\r\n }\r\n });\r\n\r\n/**\r\n * Open a macOS terminal window via AppleScript.\r\n * Uses a temp .scpt file to avoid shell quoting hell.\r\n */\r\nfunction openMacTerminal(shellSetup: string, sessionId: string, dir: string): void {\r\n const useIterm = isItermRunning();\r\n const escaped = shellSetup.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\r\n\r\n const appleScript = useIterm\r\n ? `tell application \"iTerm2\"\r\n activate\r\n set newWindow to (create window with default profile)\r\n tell current session of newWindow\r\n write text \"${escaped}\"\r\n end tell\r\nend tell`\r\n : `tell application \"Terminal\"\r\n activate\r\n do script \"${escaped}\"\r\nend tell`;\r\n\r\n const tmpFile = join(tmpdir(), `zam-monitor-${sessionId}.scpt`);\r\n try {\r\n writeFileSync(tmpFile, appleScript);\r\n execSync(`osascript ${JSON.stringify(tmpFile)}`, { stdio: \"ignore\" });\r\n console.log(`Opened ${useIterm ? \"iTerm2\" : \"Terminal.app\"} window with monitoring for session ${sessionId}`);\r\n console.log(` Directory: ${dir}`);\r\n } catch (err) {\r\n console.error(`Failed to open terminal: ${(err as Error).message}`);\r\n console.log(`\\nRun this manually in a new terminal:\\n`);\r\n console.log(` ${shellSetup}`);\r\n } finally {\r\n try { unlinkSync(tmpFile); } catch { /* ignore */ }\r\n }\r\n}\r\n","/**\r\n * `zam settings` — User settings management.\r\n */\r\n\r\nimport { Command } from \"commander\";\r\nimport type { Database } from \"libsql\";\r\nimport {\r\n openDatabase,\r\n getSetting,\r\n getAllSettings,\r\n getAllSettingsDetailed,\r\n setSetting,\r\n deleteSetting,\r\n} from \"../../kernel/index.js\";\r\n\r\nfunction withDb(fn: (db: Database) => void): void {\r\n let db: Database | undefined;\r\n try {\r\n db = openDatabase();\r\n fn(db);\r\n } catch (err) {\r\n console.error(\"Error:\", (err as Error).message);\r\n process.exit(1);\r\n } finally {\r\n db?.close();\r\n }\r\n}\r\n\r\nexport const settingsCommand = new Command(\"settings\")\r\n .description(\"Manage user settings\");\r\n\r\n// ── zam settings show ─────────────────────────────────────────────────────\r\n\r\nsettingsCommand\r\n .command(\"show\")\r\n .description(\"Show all settings\")\r\n .option(\"--json\", \"Output as JSON\")\r\n .action((opts) => {\r\n withDb((db) => {\r\n if (opts.json) {\r\n console.log(JSON.stringify(getAllSettings(db), null, 2));\r\n return;\r\n }\r\n\r\n const settings = getAllSettingsDetailed(db);\r\n if (settings.length === 0) {\r\n console.log(\"No settings configured.\");\r\n return;\r\n }\r\n\r\n console.log(\"Settings:\\n\");\r\n console.log(\"Key Value Updated\");\r\n console.log(\"─\".repeat(65));\r\n for (const s of settings) {\r\n console.log(\r\n `${s.key.padEnd(20)} ${s.value.padEnd(20)} ${s.updated_at}`,\r\n );\r\n }\r\n });\r\n });\r\n\r\n// ── zam settings get ──────────────────────────────────────────────────────\r\n\r\nsettingsCommand\r\n .command(\"get\")\r\n .description(\"Get a single setting\")\r\n .requiredOption(\"--key <key>\", \"Setting key\")\r\n .option(\"--json\", \"Output as JSON\")\r\n .action((opts) => {\r\n withDb((db) => {\r\n const value = getSetting(db, opts.key);\r\n\r\n if (opts.json) {\r\n console.log(JSON.stringify({ key: opts.key, value: value ?? null }));\r\n return;\r\n }\r\n\r\n if (value === undefined) {\r\n console.log(`Not set: ${opts.key}`);\r\n } else {\r\n console.log(value);\r\n }\r\n });\r\n });\r\n\r\n// ── zam settings set ──────────────────────────────────────────────────────\r\n\r\nsettingsCommand\r\n .command(\"set\")\r\n .description(\"Set a setting\")\r\n .requiredOption(\"--key <key>\", \"Setting key\")\r\n .requiredOption(\"--value <value>\", \"Setting value\")\r\n .option(\"--quiet\", \"Suppress output\")\r\n .action((opts) => {\r\n withDb((db) => {\r\n setSetting(db, opts.key, opts.value);\r\n if (!opts.quiet) {\r\n console.log(`Set ${opts.key} = ${opts.value}`);\r\n }\r\n });\r\n });\r\n\r\n// ── zam settings delete ───────────────────────────────────────────────────\r\n\r\nsettingsCommand\r\n .command(\"delete\")\r\n .description(\"Delete a setting\")\r\n .requiredOption(\"--key <key>\", \"Setting key\")\r\n .option(\"--quiet\", \"Suppress output\")\r\n .action((opts) => {\r\n withDb((db) => {\r\n const deleted = deleteSetting(db, opts.key);\r\n if (!opts.quiet) {\r\n if (deleted) {\r\n console.log(`Deleted: ${opts.key}`);\r\n } else {\r\n console.log(`Not found: ${opts.key}`);\r\n }\r\n }\r\n });\r\n });\r\n","/**\r\n * `zam whoami` — Manage default user identity.\r\n */\r\n\r\nimport { Command } from \"commander\";\r\nimport type { Database } from \"libsql\";\r\nimport {\r\n openDatabase,\r\n getSetting,\r\n setSetting,\r\n deleteSetting,\r\n} from \"../../kernel/index.js\";\r\n\r\nfunction withDb(fn: (db: Database) => void): void {\r\n let db: Database | undefined;\r\n try {\r\n db = openDatabase();\r\n fn(db);\r\n } catch (err) {\r\n console.error(\"Error:\", (err as Error).message);\r\n process.exit(1);\r\n } finally {\r\n db?.close();\r\n }\r\n}\r\n\r\nexport const whoamiCommand = new Command(\"whoami\")\r\n .description(\"Show or set the default user identity\")\r\n .option(\"--set <id>\", \"Set the default user ID\")\r\n .option(\"--clear\", \"Remove the default user ID\")\r\n .option(\"--json\", \"Output as JSON\")\r\n .action((opts) => {\r\n withDb((db) => {\r\n if (opts.set) {\r\n setSetting(db, \"user.id\", opts.set);\r\n if (opts.json) {\r\n console.log(JSON.stringify({ userId: opts.set }));\r\n } else {\r\n console.log(`Default user set to: ${opts.set}`);\r\n }\r\n return;\r\n }\r\n\r\n if (opts.clear) {\r\n const deleted = deleteSetting(db, \"user.id\");\r\n if (opts.json) {\r\n console.log(JSON.stringify({ userId: null, cleared: deleted }));\r\n } else if (deleted) {\r\n console.log(\"Default user cleared.\");\r\n } else {\r\n console.log(\"No default user was set.\");\r\n }\r\n return;\r\n }\r\n\r\n const userId = getSetting(db, \"user.id\");\r\n if (opts.json) {\r\n console.log(JSON.stringify({ userId: userId ?? null }));\r\n return;\r\n }\r\n\r\n if (userId) {\r\n console.log(userId);\r\n } else {\r\n console.log(\"No default user set. Use: zam whoami --set <id>\");\r\n }\r\n });\r\n });\r\n","/**\r\n * `zam connector` — Manage external service connectors.\r\n */\r\n\r\nimport { Command } from \"commander\";\r\nimport type { Database } from \"libsql\";\r\nimport { input, password } from \"@inquirer/prompts\";\r\nimport {\r\n openDatabase,\r\n openDatabaseWithSync,\r\n getSetting,\r\n setSetting,\r\n deleteSetting,\r\n} from \"../../kernel/index.js\";\r\nimport {\r\n loadADOConfig,\r\n fetchActiveWorkItems,\r\n} from \"../../kernel/connectors/azure-devops.js\";\r\n\r\nfunction withDb(fn: (db: Database) => void): void {\r\n let db: Database | undefined;\r\n try {\r\n db = openDatabase();\r\n fn(db);\r\n } catch (err) {\r\n console.error(\"Error:\", (err as Error).message);\r\n process.exit(1);\r\n } finally {\r\n db?.close();\r\n }\r\n}\r\n\r\nexport const connectorCommand = new Command(\"connector\")\r\n .description(\"Manage external service connectors\");\r\n\r\n// ── zam connector setup ado ─────────────────────────────────────────────────\r\n\r\nconnectorCommand\r\n .command(\"setup\")\r\n .description(\"Configure a connector\")\r\n .argument(\"<type>\", \"Connector type (ado, turso)\")\r\n .action(async (type) => {\r\n if (type === \"turso\") {\r\n return setupTurso();\r\n }\r\n if (type !== \"ado\") {\r\n console.error(`Unknown connector type: ${type}. Supported: ado, turso`);\r\n process.exit(1);\r\n }\r\n\r\n let db: Database | undefined;\r\n try {\r\n const orgUrl = await input({\r\n message: \"Organization URL (e.g. https://dev.azure.com/myorg):\",\r\n });\r\n const project = await input({\r\n message: \"Project name:\",\r\n });\r\n const pat = await password({\r\n message: \"Personal Access Token:\",\r\n });\r\n\r\n if (!orgUrl || !project || !pat) {\r\n console.error(\"All fields are required.\");\r\n process.exit(1);\r\n }\r\n\r\n db = openDatabase();\r\n setSetting(db, \"ado.org_url\", orgUrl.replace(/\\/+$/, \"\"));\r\n setSetting(db, \"ado.project\", project);\r\n setSetting(db, \"ado.pat\", pat);\r\n db.close();\r\n\r\n console.log(`Azure DevOps connector configured for ${orgUrl}/${project}`);\r\n } catch (err) {\r\n db?.close();\r\n if ((err as Error).name === \"ExitPromptError\") {\r\n console.log(\"\\nSetup cancelled.\");\r\n process.exit(0);\r\n }\r\n console.error(\"Error:\", (err as Error).message);\r\n process.exit(1);\r\n }\r\n });\r\n\r\n// ── zam connector tasks ─────────────────────────────────────────────────────\r\n\r\nconnectorCommand\r\n .command(\"tasks\")\r\n .description(\"List active tasks from connected board\")\r\n .option(\"--json\", \"Output as JSON\")\r\n .action(async (opts) => {\r\n let db: Database | undefined;\r\n try {\r\n db = openDatabase();\r\n const config = loadADOConfig(db);\r\n db.close();\r\n\r\n if (!config) {\r\n console.error(\"No connector configured. Run: zam connector setup ado\");\r\n process.exit(1);\r\n }\r\n\r\n const items = await fetchActiveWorkItems(config);\r\n\r\n if (opts.json) {\r\n console.log(JSON.stringify(items, null, 2));\r\n return;\r\n }\r\n\r\n if (items.length === 0) {\r\n console.log(\"No active work items assigned to you.\");\r\n return;\r\n }\r\n\r\n console.log(`${items.length} active work item(s):\\n`);\r\n console.log(\r\n \"ID Type State Title\",\r\n );\r\n console.log(\"─\".repeat(80));\r\n for (const wi of items) {\r\n console.log(\r\n `${String(wi.id).padEnd(8)} ${wi.type.padEnd(13)} ${wi.state.padEnd(11)} ${wi.title.slice(0, 45)}`,\r\n );\r\n }\r\n } catch (err) {\r\n db?.close();\r\n console.error(\"Error:\", (err as Error).message);\r\n process.exit(1);\r\n }\r\n });\r\n\r\n// ── zam connector clear ─────────────────────────────────────────────────────\r\n\r\nconnectorCommand\r\n .command(\"clear\")\r\n .description(\"Remove a connector configuration\")\r\n .argument(\"<type>\", \"Connector type (ado, turso)\")\r\n .action((type) => {\r\n if (type === \"turso\") {\r\n withDb((db) => {\r\n deleteSetting(db, \"turso.url\");\r\n deleteSetting(db, \"turso.token\");\r\n console.log(\"Turso cloud sync removed. Database remains local-only.\");\r\n });\r\n return;\r\n }\r\n\r\n if (type !== \"ado\") {\r\n console.error(`Unknown connector type: ${type}. Supported: ado, turso`);\r\n process.exit(1);\r\n }\r\n\r\n withDb((db) => {\r\n deleteSetting(db, \"ado.org_url\");\r\n deleteSetting(db, \"ado.project\");\r\n deleteSetting(db, \"ado.pat\");\r\n console.log(\"Azure DevOps connector removed.\");\r\n });\r\n });\r\n\r\n// ── zam connector sync ──────────────────────────────────────────────────────\r\n\r\nconnectorCommand\r\n .command(\"sync\")\r\n .description(\"Trigger a manual sync with Turso cloud database\")\r\n .action(() => {\r\n let db: Database | undefined;\r\n try {\r\n db = openDatabaseWithSync();\r\n const url = getSetting(db, \"turso.url\");\r\n if (!url) {\r\n console.error(\"No Turso cloud database configured. Run: zam connector setup turso\");\r\n process.exit(1);\r\n }\r\n (db as unknown as { sync: () => void }).sync();\r\n console.log(`Synced with ${url}`);\r\n db.close();\r\n } catch (err) {\r\n db?.close();\r\n console.error(\"Error:\", (err as Error).message);\r\n process.exit(1);\r\n }\r\n });\r\n\r\n// ── Turso setup helper ──────────────────────────────────────────────────────\r\n\r\nasync function setupTurso(): Promise<void> {\r\n let db: Database | undefined;\r\n try {\r\n const url = await input({\r\n message: \"Turso database URL (e.g. libsql://my-db-user.turso.io):\",\r\n });\r\n const token = await password({\r\n message: \"Auth token:\",\r\n });\r\n\r\n if (!url || !token) {\r\n console.error(\"Both URL and token are required.\");\r\n process.exit(1);\r\n }\r\n\r\n db = openDatabase();\r\n setSetting(db, \"turso.url\", url);\r\n setSetting(db, \"turso.token\", token);\r\n db.close();\r\n\r\n // Verify by opening with sync\r\n db = openDatabaseWithSync();\r\n (db as unknown as { sync: () => void }).sync();\r\n db.close();\r\n\r\n console.log(`Turso cloud sync configured and verified: ${url}`);\r\n } catch (err) {\r\n db?.close();\r\n if ((err as Error).name === \"ExitPromptError\") {\r\n console.log(\"\\nSetup cancelled.\");\r\n process.exit(0);\r\n }\r\n console.error(\"Error:\", (err as Error).message);\r\n process.exit(1);\r\n }\r\n}\r\n","/**\r\n * `zam goal` — Goal management subcommand group.\r\n *\r\n * Goals are markdown files in the personal repo's goals/ directory.\r\n * The directory is configured via the `personal.goals_dir` setting,\r\n * or defaults to `./goals` relative to the current working directory.\r\n */\r\n\r\nimport { Command } from \"commander\";\r\nimport { existsSync, mkdirSync } from \"node:fs\";\r\nimport { resolve } from \"node:path\";\r\nimport { input, select } from \"@inquirer/prompts\";\r\nimport {\r\n openDatabase,\r\n getSetting,\r\n listGoals,\r\n getGoal,\r\n createGoal,\r\n updateGoalStatus,\r\n getGoalTree,\r\n extractTasks,\r\n extractTokenRefs,\r\n} from \"../../kernel/index.js\";\r\nimport type { GoalStatus } from \"../../kernel/index.js\";\r\n\r\nfunction resolveGoalsDir(): string {\r\n let goalsDir: string | undefined;\r\n\r\n let db;\r\n try {\r\n db = openDatabase();\r\n goalsDir = getSetting(db, \"personal.goals_dir\");\r\n } catch {\r\n // DB not available — fall back to default\r\n } finally {\r\n db?.close();\r\n }\r\n\r\n return goalsDir ? resolve(goalsDir) : resolve(\"goals\");\r\n}\r\n\r\nexport const goalCommand = new Command(\"goal\")\r\n .description(\"Manage learning goals (markdown files)\");\r\n\r\n// ── zam goal list ────────────────────────────────────────────────────────────\r\n\r\ngoalCommand\r\n .command(\"list\")\r\n .description(\"List all goals\")\r\n .option(\"--status <status>\", \"Filter by status (active, completed, paused, abandoned)\")\r\n .option(\"--tree\", \"Show goals as a tree with parent/child relationships\")\r\n .option(\"--json\", \"Output as JSON\")\r\n .action((opts) => {\r\n const goalsDir = resolveGoalsDir();\r\n\r\n if (!existsSync(goalsDir)) {\r\n console.error(`Goals directory not found: ${goalsDir}`);\r\n console.error(\"Set it with: zam settings set personal.goals_dir /path/to/goals\");\r\n process.exit(1);\r\n }\r\n\r\n if (opts.tree) {\r\n const tree = getGoalTree(goalsDir);\r\n const filtered = opts.status\r\n ? tree.filter((g) => g.status === opts.status)\r\n : tree;\r\n\r\n if (opts.json) {\r\n console.log(JSON.stringify(filtered, null, 2));\r\n return;\r\n }\r\n\r\n if (filtered.length === 0) {\r\n console.log(\"No goals found.\");\r\n return;\r\n }\r\n\r\n for (const root of filtered) {\r\n printGoalLine(root, 0);\r\n for (const child of root.children) {\r\n printGoalLine(child, 1);\r\n }\r\n }\r\n return;\r\n }\r\n\r\n let goals = listGoals(goalsDir);\r\n\r\n if (opts.status) {\r\n goals = goals.filter((g) => g.status === opts.status);\r\n }\r\n\r\n if (opts.json) {\r\n console.log(JSON.stringify(goals, null, 2));\r\n return;\r\n }\r\n\r\n if (goals.length === 0) {\r\n console.log(\"No goals found.\");\r\n return;\r\n }\r\n\r\n console.log(\"Goals:\");\r\n console.log(\" \" + \"─\".repeat(70));\r\n for (const g of goals) {\r\n printGoalLine(g, 0);\r\n }\r\n });\r\n\r\nfunction printGoalLine(\r\n g: { slug: string; title: string; status: string; taskCount: number; tasksDone: number },\r\n indent: number,\r\n): void {\r\n const prefix = \" \".repeat(indent + 1);\r\n const statusIcon: Record<string, string> = {\r\n active: \"[*]\",\r\n paused: \"[-]\",\r\n completed: \"[x]\",\r\n abandoned: \"[ ]\",\r\n };\r\n const icon = statusIcon[g.status] || \"[ ]\";\r\n const tasks = g.taskCount > 0 ? ` (${g.tasksDone}/${g.taskCount} tasks)` : \"\";\r\n console.log(`${prefix}${icon} ${g.title}${tasks} — ${g.slug}`);\r\n}\r\n\r\n// ── zam goal show ────────────────────────────────────────────────────────────\r\n\r\ngoalCommand\r\n .command(\"show <slug>\")\r\n .description(\"Show a goal's details\")\r\n .option(\"--json\", \"Output as JSON\")\r\n .action((slug, opts) => {\r\n const goalsDir = resolveGoalsDir();\r\n const goal = getGoal(goalsDir, slug);\r\n\r\n if (!goal) {\r\n console.error(`Goal not found: ${slug}`);\r\n process.exit(1);\r\n }\r\n\r\n if (opts.json) {\r\n const tasks = extractTasks(goal.body);\r\n const tokens = extractTokenRefs(goal.body);\r\n console.log(JSON.stringify({ ...goal, tasks, tokens }, null, 2));\r\n return;\r\n }\r\n\r\n console.log(`Title: ${goal.title}`);\r\n console.log(`Slug: ${goal.slug}`);\r\n console.log(`Status: ${goal.status}`);\r\n if (goal.parent) console.log(`Parent: ${goal.parent}`);\r\n console.log(`Created: ${goal.created}`);\r\n console.log(`Updated: ${goal.updated}`);\r\n\r\n const tasks = extractTasks(goal.body);\r\n if (tasks.length > 0) {\r\n console.log(`\\nTasks (${tasks.filter((t) => t.done).length}/${tasks.length}):`);\r\n for (const t of tasks) {\r\n console.log(` [${t.done ? \"x\" : \" \"}] ${t.text}`);\r\n }\r\n }\r\n\r\n const tokens = extractTokenRefs(goal.body);\r\n if (tokens.length > 0) {\r\n console.log(`\\nTokens:`);\r\n for (const ref of tokens) {\r\n console.log(` - ${ref}`);\r\n }\r\n }\r\n\r\n if (goal.body) {\r\n console.log(`\\n${\"─\".repeat(50)}`);\r\n console.log(goal.body);\r\n }\r\n });\r\n\r\n// ── zam goal create ──────────────────────────────────────────────────────────\r\n\r\ngoalCommand\r\n .command(\"create\")\r\n .description(\"Create a new goal\")\r\n .option(\"--slug <slug>\", \"Goal slug (used as filename)\")\r\n .option(\"--title <title>\", \"Goal title\")\r\n .option(\"--parent <slug>\", \"Parent goal slug\")\r\n .option(\"--description <text>\", \"Goal description\")\r\n .option(\"--json\", \"Output as JSON\")\r\n .action(async (opts) => {\r\n const goalsDir = resolveGoalsDir();\r\n\r\n if (!existsSync(goalsDir)) {\r\n mkdirSync(goalsDir, { recursive: true });\r\n }\r\n\r\n let slug = opts.slug;\r\n let title = opts.title;\r\n const parent = opts.parent;\r\n const description = opts.description;\r\n\r\n // Interactive mode if slug or title not provided\r\n if (!slug || !title) {\r\n try {\r\n if (!title) {\r\n title = await input({ message: \"Goal title:\" });\r\n }\r\n if (!slug) {\r\n const suggested = title\r\n .toLowerCase()\r\n .replace(/[^a-z0-9]+/g, \"-\")\r\n .replace(/^-|-$/g, \"\");\r\n slug = await input({\r\n message: \"Goal slug (filename):\",\r\n default: suggested,\r\n });\r\n }\r\n } catch (err) {\r\n if ((err as Error).name === \"ExitPromptError\") {\r\n console.log(\"\\nCancelled.\");\r\n process.exit(0);\r\n }\r\n throw err;\r\n }\r\n }\r\n\r\n const goal = createGoal(goalsDir, { slug, title, parent, description });\r\n\r\n if (opts.json) {\r\n console.log(JSON.stringify(goal, null, 2));\r\n return;\r\n }\r\n\r\n console.log(`Goal created: ${goal.slug}`);\r\n console.log(` Title: ${goal.title}`);\r\n console.log(` Status: ${goal.status}`);\r\n console.log(` File: ${goal.filePath}`);\r\n });\r\n\r\n// ── zam goal status ──────────────────────────────────────────────────────────\r\n\r\ngoalCommand\r\n .command(\"status <slug> <status>\")\r\n .description(\"Update a goal's status (active, paused, completed, abandoned)\")\r\n .option(\"--json\", \"Output as JSON\")\r\n .action((slug, status, opts) => {\r\n const validStatuses: GoalStatus[] = [\"active\", \"completed\", \"paused\", \"abandoned\"];\r\n if (!validStatuses.includes(status)) {\r\n console.error(`Invalid status: ${status}. Must be one of: ${validStatuses.join(\", \")}`);\r\n process.exit(1);\r\n }\r\n\r\n const goalsDir = resolveGoalsDir();\r\n const goal = updateGoalStatus(goalsDir, slug, status);\r\n\r\n if (opts.json) {\r\n console.log(JSON.stringify(goal, null, 2));\r\n return;\r\n }\r\n\r\n console.log(`Goal ${slug} updated to: ${status}`);\r\n });\r\n"],"mappings":"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","names":["Command","input","ulid","ulid","ulid","input","ulid","input","interval","dueAt","input","ulid","input","ulid","existsSync","mkdirSync","homedir","join","join","homedir","join","existsSync","mkdirSync","readFileSync","existsSync","join","existsSync","join","readFileSync","input","Command","existsSync","mkdirSync","writeFileSync","join","dirname","basename","join","existsSync","mkdirSync","dirname","basename","writeFileSync","Command","Command","Command","Command","withDb","Command","Command","withDb","Command","Command","withDb","Command","Command","select","Command","select","Command","readdirSync","homedir","join","withDb","Command","join","homedir","readdirSync","Command","withDb","Command","Command","basename","join","writeFileSync","basename","Command","join","writeFileSync","Command","withDb","Command","Command","withDb","Command","Command","input","withDb","Command","input","Command","existsSync","mkdirSync","input","Command","existsSync","tasks","tokens","mkdirSync","input","Command"]}