@workscribe/cli 1.14.0 → 1.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/utils/node-version.ts","../src/capture/index.ts","../src/db/index.ts","../src/utils/paths.ts","../src/db/migrations/001_initial_schema.ts","../src/db/migrations/002_semantic_categories.ts","../src/db/migrations/003_alerts.ts","../src/db/migrations/004_ide_columns.ts","../src/db/migrations/index.ts","../src/capture/redact.ts","../src/capture/git.ts","../src/capture/git-snapshot.ts","../src/capture/aider.ts","../src/config/registry.ts","../src/config/ai-tools.json","../src/utils/logger.ts","../src/profiles/loader.ts","../src/config/index.ts","../src/profiles/schema.ts","../src/profiles/fetcher.ts","../src/utils/fetch.ts","../src/normalize/patterns.ts","../src/capture/filter.ts","../src/capture/ide.ts","../src/cli/capture.ts","../src/capture/detect-secrets.ts","../src/db/alerts.ts","../src/cli/hook.ts","../src/cli/init.ts","../src/utils/format.ts","../src/ai/prompt.ts","../src/ai/generic-provider.ts","../src/ai/provider-config.ts","../src/ai/router.ts","../src/capture/shell-hook.ts","../src/utils/completion-scripts.ts","../src/capture/hooks/claude-code.ts","../src/capture/hooks/utils.ts","../src/capture/hooks/index.ts","../src/cli/completions.ts","../src/cli/status.ts","../src/cli/events.ts","../src/cli/sessions.ts","../src/sessions/grouper.ts","../src/sessions/detector.ts","../src/cli/summary.ts","../src/integrations/webhook.ts","../src/integrations/slack.ts","../src/cli/export.ts","../src/cli/config.ts","../src/cli/pause.ts","../src/cli/undo.ts","../src/cli/clear.ts","../src/cli/uninstall.ts","../src/cli/profile.ts","../src/cli/note.ts","../src/cli/week.ts","../src/cli/bug-report.ts","../src/cli/alerts.ts","../src/cli/context.ts","../src/utils/update-check.ts"],"sourcesContent":["import { Command } from 'commander'\nimport { assertNodeVersion } from './utils/node-version'\n\nassertNodeVersion(process.versions.node)\nimport { registerCapture } from './cli/capture'\nimport { registerHook } from './cli/hook'\n\ndeclare const __WORKSCRIBE_VERSION__: string\nimport { registerInit } from './cli/init'\nimport { registerStatus } from './cli/status'\nimport { registerEvents } from './cli/events'\nimport { registerSessions } from './cli/sessions'\nimport { registerSummary } from './cli/summary'\nimport { registerExport } from './cli/export'\nimport { registerConfig } from './cli/config'\nimport { registerPause } from './cli/pause'\nimport { registerUndo } from './cli/undo'\nimport { registerClear } from './cli/clear'\nimport { registerUninstall } from './cli/uninstall'\nimport { registerProfile } from './cli/profile'\nimport { registerNote } from './cli/note'\nimport { registerWeek } from './cli/week'\nimport { registerBugReport } from './cli/bug-report'\nimport { registerCompletions } from './cli/completions'\nimport { registerAlerts } from './cli/alerts'\nimport { registerContext } from './cli/context'\nimport { checkForUpdate } from './utils/update-check'\n\ncheckForUpdate()\n\nconst program = new Command()\n\nprogram.name('workscribe').description('Automatic developer work journal').version(__WORKSCRIBE_VERSION__)\n\nregisterCapture(program)\nregisterHook(program)\nregisterInit(program)\nregisterStatus(program)\nregisterEvents(program)\nregisterSessions(program)\nregisterSummary(program)\nregisterExport(program)\nregisterConfig(program)\nregisterPause(program)\nregisterUndo(program)\nregisterClear(program)\nregisterUninstall(program)\nregisterProfile(program)\nregisterNote(program)\nregisterWeek(program)\nregisterBugReport(program)\nregisterCompletions(program)\nregisterAlerts(program)\nregisterContext(program)\n\nprogram.parse()\n","export type VersionManager = 'nvm' | 'volta' | 'fnm' | 'mise' | 'asdf' | 'nodenv'\n\nexport function detectVersionManager(): VersionManager | null {\n if (process.env.NVM_DIR) return 'nvm'\n if (process.env.VOLTA_HOME) return 'volta'\n if (process.env.FNM_DIR) return 'fnm'\n if (process.env.MISE_DATA_DIR || process.env.MISE_SHELL) return 'mise'\n if (process.env.ASDF_DIR || process.env.ASDF_DATA_DIR) return 'asdf'\n if (process.env.NODENV_ROOT) return 'nodenv'\n return null\n}\n\nconst UPGRADE_COMMANDS: Record<VersionManager, string> = {\n nvm: 'nvm install 22 && nvm use 22',\n volta: 'volta install node@22',\n fnm: 'fnm install 22 && fnm use 22',\n mise: 'mise use --global node@22',\n asdf: 'asdf install nodejs 22 && asdf global nodejs 22',\n nodenv: 'nodenv install 22 && nodenv global 22',\n}\n\nexport function assertNodeVersion(nodeVersion: string): void {\n const major = Number(nodeVersion.split('.')[0])\n if (major < 22) {\n const manager = detectVersionManager()\n const upgradeHint = manager\n ? `Upgrade with ${manager}:\\n ${UPGRADE_COMMANDS[manager]}`\n : 'Download the latest version from https://nodejs.org'\n process.stderr.write(`workscribe requires Node.js 22 or later (you have v${nodeVersion}).\\n\\n${upgradeHint}\\n`)\n process.exit(1)\n }\n}\n","import fs from 'fs'\nimport { insertEvent, getLastEvent, getLastEventForFile } from '../db'\nimport { redact } from './redact'\nimport { getGitContext } from './git'\nimport { getCommitsSince } from './git-snapshot'\nimport { readLastAiderPrompt } from './aider'\nimport { normalizeCommand } from '../normalize/patterns'\nimport { readConfig } from '../config'\nimport { shouldFilter, isDuplicate } from './filter'\nimport { IDE_DEDUP_WINDOW_MS } from './ide'\nimport { PAUSE_FLAG_PATH } from '../utils/paths'\nimport { loadAIToolRegistry } from '../config/registry'\n\nexport function captureCommand(opts: {\n command?: string\n cwd: string\n exitCode: number | null\n durationMs: number | null\n gitBefore?: string\n source?: string\n type?: string\n file?: string\n}): void {\n // Check pause flag before any I/O\n if (fs.existsSync(PAUSE_FLAG_PATH)) return\n\n const config = readConfig()\n const { cwd, exitCode, durationMs } = opts\n\n // ─── IDE event path ──────────────────────────────────────────────────────────\n // When --type is provided, the caller has already classified the event.\n // Skip normalization and noise filtering — these are first-party signals.\n if (opts.type) {\n // For file-save events, deduplicate per-file with a longer window (30s) to\n // absorb rapid auto-saves of the same file.\n if (opts.type === 'code_edit' && opts.file) {\n const lastForFile = getLastEventForFile(opts.file, cwd)\n if (lastForFile) {\n const lastTime = new Date(lastForFile.captured_at).getTime()\n if (Date.now() - lastTime < IDE_DEDUP_WINDOW_MS) return\n }\n }\n\n const command = opts.command ?? opts.file ?? opts.type\n const nameOverride = config.projects?.[cwd] ?? null\n const { repoName, branch } = getGitContext(cwd, nameOverride, config.git.qualifyRepoName)\n\n insertEvent({\n captured_at: new Date().toISOString(),\n command,\n cwd,\n exit_code: exitCode,\n duration_ms: durationMs,\n repo_name: repoName,\n branch,\n category: opts.type,\n metadata: null,\n source: opts.source ?? null,\n file_path: opts.file ?? null,\n })\n return\n }\n\n // ─── Shell event path ─────────────────────────────────────────────────────────\n const command = opts.command as string\n\n // 1. Filter noise commands\n if (shouldFilter(command, config.capture.ignore)) return\n\n // 2. Deduplicate: same command + same cwd within 5 seconds\n const last = getLastEvent()\n if (isDuplicate(command, cwd, last ?? undefined)) return\n\n // 3. Redact sensitive patterns\n const safeCommand = redact(command, config.redact.extra)\n\n // 4. Extract git context (with optional per-project name override)\n const nameOverride = config.projects?.[cwd] ?? null\n const { repoName, branch } = getGitContext(cwd, nameOverride)\n\n // 5. Normalize to typed event\n const { category, metadata } = normalizeCommand(safeCommand)\n\n if (category === 'ai_session' && config.capture.aiTools === false) return\n\n // Hint passthrough: preserve context for unrecognised commands so the AI can describe them\n if (category === 'other') {\n const firstToken = safeCommand.trim().split(/\\s+/)[0]\n if (firstToken) metadata.tool = firstToken\n metadata.hint = safeCommand.trim().slice(0, 120)\n }\n\n // 6. For ai_session events, enrich metadata\n if (category === 'ai_session') {\n // 6a. Commits made during the session\n if (opts.gitBefore) {\n const commits = getCommitsSince(opts.gitBefore, cwd)\n if (commits.length > 0) metadata.commits = commits\n }\n\n // 6b. Last user prompt from history file (e.g. Aider)\n if (config.capture.includeAiderPrompt !== false) {\n const toolEntry = loadAIToolRegistry().find((entry) => entry.tool === metadata.tool)\n if (toolEntry?.contextSource === 'history-file') {\n const prompt = readLastAiderPrompt(cwd)\n if (prompt) metadata.prompt = prompt\n }\n }\n }\n\n // 7. Persist\n insertEvent({\n captured_at: new Date().toISOString(),\n command: safeCommand,\n cwd,\n exit_code: exitCode,\n duration_ms: durationMs,\n repo_name: repoName,\n branch,\n category,\n metadata: Object.keys(metadata).length > 0 ? JSON.stringify(metadata) : null,\n source: opts.source ?? null,\n file_path: null,\n })\n}\n","import { DatabaseSync } from 'node:sqlite'\nimport fs from 'fs'\nimport { WORKSCRIBE_DIR, DB_PATH } from '../utils/paths'\nimport type { EventRow, SessionRow } from './types'\nimport { MIGRATIONS } from './migrations'\nexport type { EventRow, SessionRow } from './types'\n\nlet _db: DatabaseSync | null = null\n\nexport function getDb(): DatabaseSync {\n if (_db) return _db\n\n // Ensure ~/.workscribe/ exists\n if (!fs.existsSync(WORKSCRIBE_DIR)) {\n fs.mkdirSync(WORKSCRIBE_DIR, { recursive: true })\n }\n\n // Don't assign to _db until after migrations succeed — if applyMigrations\n // throws, _db stays null so the next call retries cleanly instead of\n // returning a partially-initialised singleton.\n const db = new DatabaseSync(DB_PATH)\n try {\n fs.chmodSync(DB_PATH, 0o600)\n } catch {\n /* ignore if already correct */\n }\n db.exec('PRAGMA journal_mode = WAL')\n db.exec('PRAGMA foreign_keys = ON')\n applyMigrations(db)\n _db = db\n return _db\n}\n\nfunction applyMigrations(db: DatabaseSync): void {\n // Create the migration tracking table if this is the first run\n db.exec(`\n CREATE TABLE IF NOT EXISTS schema_migrations (\n version INTEGER PRIMARY KEY,\n applied_at TEXT NOT NULL DEFAULT (datetime('now'))\n )\n `)\n\n // Bootstrap: if the events table already exists but schema_migrations is\n // empty, this is an existing install that predates the migration system.\n // Seed version 1 as applied so we don't re-run the initial schema.\n const hasEvents = db.prepare(\"SELECT name FROM sqlite_master WHERE type='table' AND name='events'\").get()\n const hasVersion1 = db.prepare('SELECT version FROM schema_migrations WHERE version = 1').get()\n\n if (hasEvents && !hasVersion1) {\n db.prepare(\"INSERT INTO schema_migrations (version, applied_at) VALUES ($version, datetime('now'))\").run({\n version: 1,\n })\n }\n\n // Collect already-applied versions\n const applied = new Set(\n (db.prepare('SELECT version FROM schema_migrations').all() as { version: number }[]).map((row) => row.version)\n )\n\n // Apply each pending migration in order, wrapped in a transaction so a\n // partial failure leaves the DB cleanly at the previous version.\n for (const migration of MIGRATIONS) {\n if (applied.has(migration.version)) continue\n\n db.exec('BEGIN')\n try {\n db.exec(migration.sql)\n db.prepare(\"INSERT INTO schema_migrations (version, applied_at) VALUES ($version, datetime('now'))\").run({\n version: migration.version,\n })\n db.exec('COMMIT')\n } catch (err) {\n try {\n db.exec('ROLLBACK')\n } catch {\n /* already rolled back or connection lost */\n }\n throw new Error(`Migration ${migration.version} (${migration.description}) failed: ${(err as Error).message}`)\n }\n }\n}\n\n// ─── Typed query helpers ──────────────────────────────────────────────────────\n\nexport function insertEvent(params: {\n captured_at: string\n command: string\n cwd: string\n exit_code: number | null\n duration_ms: number | null\n repo_name: string | null\n branch: string | null\n category: string\n metadata: string | null\n source: string | null\n file_path: string | null\n}): void {\n const db = getDb()\n const stmt = db.prepare(`\n INSERT INTO events (captured_at, command, cwd, exit_code, duration_ms, repo_name, branch, category, metadata, source, file_path)\n VALUES ($captured_at, $command, $cwd, $exit_code, $duration_ms, $repo_name, $branch, $category, $metadata, $source, $file_path)\n `)\n stmt.run(params)\n}\n\nexport function getRecentSessionsByRepo(repoName: string, limit: number): SessionRow[] {\n const db = getDb()\n return db\n .prepare('SELECT * FROM sessions WHERE repo_name = $repo_name ORDER BY started_at DESC LIMIT $limit')\n .all({ repo_name: repoName, limit }) as unknown as SessionRow[]\n}\n\nexport function getLastSessionTouchingFile(filePath: string): SessionRow | undefined {\n const db = getDb()\n return db\n .prepare(\n `SELECT s.* FROM sessions s\n INNER JOIN session_events se ON se.session_id = s.id\n INNER JOIN events e ON e.id = se.event_id\n WHERE e.file_path = $file_path\n ORDER BY s.started_at DESC\n LIMIT 1`\n )\n .get({ file_path: filePath }) as SessionRow | undefined\n}\n\nexport function getSessionBranch(sessionId: number): string | null {\n const db = getDb()\n const row = db\n .prepare(\n `SELECT e.branch FROM events e\n INNER JOIN session_events se ON se.event_id = e.id\n WHERE se.session_id = $session_id AND e.branch IS NOT NULL\n ORDER BY e.captured_at DESC\n LIMIT 1`\n )\n .get({ session_id: sessionId }) as { branch: string } | undefined\n return row?.branch ?? null\n}\n\nexport function getLastEventForFile(filePath: string, cwd: string): EventRow | undefined {\n const db = getDb()\n return db\n .prepare('SELECT * FROM events WHERE file_path = $file_path AND cwd = $cwd ORDER BY id DESC LIMIT 1')\n .get({ file_path: filePath, cwd }) as EventRow | undefined\n}\n\nexport function getLastEvent(): EventRow | undefined {\n const db = getDb()\n const stmt = db.prepare('SELECT * FROM events ORDER BY id DESC LIMIT 1')\n return stmt.get() as EventRow | undefined\n}\n\nexport function getEventsForDate(date: string): EventRow[] {\n const db = getDb()\n const stmt = db.prepare(`\n SELECT * FROM events\n WHERE date(captured_at, 'localtime') = $date\n ORDER BY captured_at ASC\n `)\n return stmt.all({ date }) as unknown as EventRow[]\n}\n\nexport function getRecentEvents(limit = 20): EventRow[] {\n const db = getDb()\n const stmt = db.prepare('SELECT * FROM events ORDER BY captured_at DESC LIMIT $limit')\n return stmt.all({ limit }) as unknown as EventRow[]\n}\n\nexport function getEventCount(): number {\n const db = getDb()\n const stmt = db.prepare('SELECT COUNT(*) as count FROM events')\n const row = stmt.get() as { count: number }\n return row.count\n}\n\nexport function insertSession(params: {\n date: string\n started_at: string\n ended_at: string\n repo_name: string | null\n event_count: number\n summary: string | null\n}): number {\n const db = getDb()\n const stmt = db.prepare(`\n INSERT INTO sessions (date, started_at, ended_at, repo_name, event_count, summary)\n VALUES ($date, $started_at, $ended_at, $repo_name, $event_count, $summary)\n `)\n const result = stmt.run(params)\n return Number(result.lastInsertRowid)\n}\n\nexport function insertSessionEvent(sessionId: number, eventId: number): void {\n const db = getDb()\n const stmt = db.prepare(`\n INSERT OR IGNORE INTO session_events (session_id, event_id) VALUES ($session_id, $event_id)\n `)\n stmt.run({ session_id: sessionId, event_id: eventId })\n}\n\nexport function getEventsBySessionId(sessionId: number): EventRow[] {\n const db = getDb()\n const stmt = db.prepare(`\n SELECT e.* FROM events e\n INNER JOIN session_events se ON se.event_id = e.id\n WHERE se.session_id = $session_id\n ORDER BY e.captured_at ASC\n `)\n return stmt.all({ session_id: sessionId }) as unknown as EventRow[]\n}\n\nexport function getSessionsForDate(date: string): SessionRow[] {\n const db = getDb()\n const stmt = db.prepare('SELECT * FROM sessions WHERE date = $date ORDER BY started_at ASC')\n return stmt.all({ date }) as unknown as SessionRow[]\n}\n\nexport function updateSessionSummary(sessionId: number, summary: string): void {\n const db = getDb()\n const stmt = db.prepare('UPDATE sessions SET summary = $summary WHERE id = $id')\n stmt.run({ summary, id: sessionId })\n}\n\nexport function getLastEventIds(n: number): number[] {\n const db = getDb()\n const rows = db.prepare('SELECT id FROM events ORDER BY id DESC LIMIT $n').all({ n }) as { id: number }[]\n return rows.map((row) => row.id)\n}\n\nexport function getEventsByIds(ids: number[]): EventRow[] {\n if (ids.length === 0) return []\n const db = getDb()\n const placeholders = ids.map(() => '?').join(', ')\n return db\n .prepare(`SELECT * FROM events WHERE id IN (${placeholders}) ORDER BY id DESC`)\n .all(...ids) as unknown as EventRow[]\n}\n\nexport function deleteEventsByIds(ids: number[]): void {\n if (ids.length === 0) return\n const db = getDb()\n const placeholders = ids.map(() => '?').join(', ')\n\n const affectedDates = db\n .prepare(`SELECT DISTINCT date(captured_at, 'localtime') as date FROM events WHERE id IN (${placeholders})`)\n .all(...ids) as { date: string }[]\n\n db.prepare(`DELETE FROM events WHERE id IN (${placeholders})`).run(...ids)\n\n for (const { date } of affectedDates) {\n clearSessionsForDate(date)\n }\n}\n\nexport function deleteEventsForDate(date: string): number {\n const db = getDb()\n // Clear sessions (and session_events) before deleting events — FK constraint order\n clearSessionsForDate(date)\n const result = db.prepare(`DELETE FROM events WHERE date(captured_at, 'localtime') = $date`).run({ date }) as {\n changes: number\n }\n return result.changes\n}\n\nexport function getOtherEventToolCounts(days: number): { tool: string; count: number }[] {\n const db = getDb()\n return db\n .prepare(\n `SELECT json_extract(metadata, '$.tool') as tool, COUNT(*) as count\n FROM events\n WHERE category = 'other'\n AND captured_at >= datetime('now', $offset)\n AND json_extract(metadata, '$.tool') IS NOT NULL\n GROUP BY tool\n ORDER BY count DESC`\n )\n .all({ offset: `-${days} days` }) as { tool: string; count: number }[]\n}\n\nexport function getRecentOtherRate(days: number): { total: number; otherCount: number } {\n const db = getDb()\n const row = db\n .prepare(\n `SELECT COUNT(*) as total,\n SUM(CASE WHEN category = 'other' THEN 1 ELSE 0 END) as otherCount\n FROM events\n WHERE captured_at >= datetime('now', $offset)`\n )\n .get({ offset: `-${days} days` }) as { total: number; otherCount: number }\n return row\n}\n\nexport function clearSessionsForDate(date: string): void {\n const db = getDb()\n // Remove session_events first due to FK constraint\n db.prepare(\n `\n DELETE FROM session_events WHERE session_id IN (\n SELECT id FROM sessions WHERE date = $date\n )\n `\n ).run({ date })\n db.prepare('DELETE FROM sessions WHERE date = $date').run({ date })\n}\n","import path from 'path'\nimport os from 'os'\nimport fs from 'fs'\n\nconst LEGACY_DIR = path.join(os.homedir(), '.workscribe')\n\n// Existing installs keep ~/.workscribe/ — fresh installs use XDG Base Directory spec\nconst USE_XDG = !fs.existsSync(LEGACY_DIR)\n\nconst xdgDataDir = USE_XDG\n ? path.join(process.env.XDG_DATA_HOME ?? path.join(os.homedir(), '.local', 'share'), 'workscribe')\n : LEGACY_DIR\n\nconst xdgConfigDir = USE_XDG\n ? path.join(process.env.XDG_CONFIG_HOME ?? path.join(os.homedir(), '.config'), 'workscribe')\n : LEGACY_DIR\n\nconst xdgStateDir = USE_XDG\n ? path.join(process.env.XDG_STATE_HOME ?? path.join(os.homedir(), '.local', 'state'), 'workscribe')\n : LEGACY_DIR\n\n// All directories that must exist for Workscribe to function (deduplicated for legacy installs).\n// LEGACY_DIR (~/.workscribe) is always included so the alerts signal file has a predictable\n// location that shell hooks can check without knowing the XDG paths.\nexport const REQUIRED_DIRS: string[] = [...new Set([xdgDataDir, xdgConfigDir, xdgStateDir, LEGACY_DIR])]\n\nexport const WORKSCRIBE_DIR = xdgDataDir\nexport const DB_PATH = path.join(xdgDataDir, 'workscribe.db')\nexport const CONFIG_PATH = path.join(xdgConfigDir, 'config.json')\nexport const DEBUG_LOG_PATH = path.join(xdgStateDir, 'debug.log')\nexport const UPDATE_CHECK_PATH = path.join(xdgStateDir, 'update-check.json')\nexport const EXPORTS_DIR = path.join(xdgDataDir, 'exports')\nexport const PAUSE_FLAG_PATH = path.join(xdgStateDir, 'paused')\nexport const WEEKLY_CACHE_DIR = path.join(xdgDataDir, 'weekly-cache')\nexport const PROFILES_DIR = path.join(xdgDataDir, 'profiles')\n// Fixed at ~/.workscribe/alerts.pending so shell hooks can check it without knowing XDG paths.\n// Content is irrelevant — its presence signals pending alerts.\nexport const ALERTS_PENDING_PATH = path.join(LEGACY_DIR, 'alerts.pending')\n","export default {\n version: 1,\n description: 'initial schema',\n sql: `\n CREATE TABLE IF NOT EXISTS events (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n captured_at TEXT NOT NULL,\n command TEXT NOT NULL,\n cwd TEXT NOT NULL,\n exit_code INTEGER,\n duration_ms INTEGER,\n repo_name TEXT,\n branch TEXT,\n category TEXT NOT NULL DEFAULT 'other',\n metadata TEXT\n );\n\n CREATE INDEX IF NOT EXISTS idx_events_captured_at ON events(captured_at);\n CREATE INDEX IF NOT EXISTS idx_events_repo_name ON events(repo_name);\n\n CREATE TABLE IF NOT EXISTS sessions (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n date TEXT NOT NULL,\n started_at TEXT NOT NULL,\n ended_at TEXT NOT NULL,\n repo_name TEXT,\n event_count INTEGER NOT NULL DEFAULT 0,\n summary TEXT\n );\n\n CREATE INDEX IF NOT EXISTS idx_sessions_date ON sessions(date);\n\n CREATE TABLE IF NOT EXISTS session_events (\n session_id INTEGER NOT NULL REFERENCES sessions(id),\n event_id INTEGER NOT NULL REFERENCES events(id),\n PRIMARY KEY (session_id, event_id)\n );\n `,\n}\n","const migration = {\n version: 2,\n description: 'Rename granular categories to 13 universal semantic categories',\n sql: `\n UPDATE events SET category = 'shipping' WHERE category IN ('code_commit','code_push','code_merge');\n UPDATE events SET category = 'versioning' WHERE category IN ('code_pull','branch_switch','code_stash','git_other');\n UPDATE events SET category = 'building' WHERE category = 'build';\n UPDATE events SET category = 'running' WHERE category IN ('server_run','script_run');\n UPDATE events SET category = 'testing' WHERE category = 'test_run';\n UPDATE events SET category = 'linting' WHERE category = 'lint_run';\n UPDATE events SET category = 'dependencies' WHERE category IN ('dependency_install','dependency_remove');\n UPDATE events SET category = 'infrastructure' WHERE category = 'infrastructure';\n UPDATE events SET category = 'files' WHERE category IN ('file_ops','environment');\n UPDATE events SET category = 'exploring' WHERE category IN ('code_search','code_read');\n `,\n}\n\nexport default migration\n","const migration = {\n version: 3,\n description: 'Add alerts table for AI session secret detection',\n sql: `\n CREATE TABLE IF NOT EXISTS alerts (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n created_at INTEGER NOT NULL,\n tool TEXT NOT NULL,\n session_id TEXT,\n context TEXT NOT NULL,\n cleared INTEGER NOT NULL DEFAULT 0\n );\n CREATE INDEX IF NOT EXISTS alerts_cleared ON alerts (cleared);\n `,\n}\n\nexport default migration\n","const migration = {\n version: 4,\n description: 'Add source and file_path columns to events for IDE integration',\n sql: `\n ALTER TABLE events ADD COLUMN source TEXT;\n ALTER TABLE events ADD COLUMN file_path TEXT;\n CREATE INDEX IF NOT EXISTS idx_events_file_path ON events (file_path, cwd);\n `,\n}\n\nexport default migration\n","import initialSchema from './001_initial_schema'\nimport semanticCategories from './002_semantic_categories'\nimport alerts from './003_alerts'\nimport ideColumns from './004_ide_columns'\n\nexport interface Migration {\n version: number\n description: string\n sql: string\n}\n\n// Ordered list — append only. Never modify or remove an existing entry.\nexport const MIGRATIONS: Migration[] = [initialSchema, semanticCategories, alerts, ideColumns]\n","// Patterns that match known sensitive values\nconst BUILTIN_PATTERNS: RegExp[] = [\n // AWS access keys\n /AKIA[0-9A-Z]{16}/g,\n // AWS secret access keys (40 char base64-ish after common env vars)\n /(?<=AWS_SECRET_ACCESS_KEY[=\\s]+)\\S+/gi,\n // GitHub tokens\n /ghp_[a-zA-Z0-9]{36}/g,\n /github_pat_[a-zA-Z0-9_]{82}/g,\n // GitLab tokens\n /glpat-[a-zA-Z0-9\\-]{20}/g,\n // Generic JWTs (three base64url segments)\n /eyJ[a-zA-Z0-9_-]+\\.eyJ[a-zA-Z0-9_-]+\\.[a-zA-Z0-9_-]+/g,\n // Slack tokens and incoming webhook URLs\n /xox[baprs]-[a-zA-Z0-9\\-]+/g,\n /https:\\/\\/hooks\\.slack\\.com\\/services\\/[A-Z0-9]+\\/[A-Z0-9]+\\/[a-zA-Z0-9]+/g,\n // Stripe keys\n /sk_(live|test)_[a-zA-Z0-9]{24,}/g,\n // Values after long-form secret flags (single-char flags like -t/-p/-k are too ambiguous)\n /(?<=--(password|passwd|secret|token|key|api[-_]?key|auth[-_]?token)\\s+)\\S+/gi,\n // export VAR=VALUE where VAR looks sensitive\n /(?<=export\\s+(?:[A-Z_]*(?:TOKEN|SECRET|KEY|PASSWORD|PASS|AUTH|CREDENTIAL)[A-Z_]*)=)\\S+/gi,\n // Inline assignment: VAR_WITH_SENSITIVE_KEYWORD=value cmd (e.g. API_KEY=secret npm start)\n // Lookbehind matches only the variable-name= prefix, so only the value is replaced\n /(?<=[A-Z_][A-Z0-9_]*(?:TOKEN|SECRET|KEY|PASSWORD|PASS|AUTH|CREDENTIAL)[A-Z0-9_]*=)\\S+/gi,\n // Credentials embedded in connection string URLs (e.g. DATABASE_URL=postgres://user:pass@host/db)\n // Matches the password segment between :// user : password @ — preserves scheme and host\n /(?<=[a-zA-Z][a-zA-Z0-9+.-]*:\\/\\/[^:@\\s/]+:)[^@\\s]+(?=@)/g,\n]\n\nexport function redact(command: string, extraPatterns: string[] = []): string {\n let result = command\n\n const allPatterns = [...BUILTIN_PATTERNS]\n\n for (const pattern of extraPatterns) {\n try {\n allPatterns.push(new RegExp(pattern, 'g'))\n } catch {\n // Invalid regex — skip silently\n }\n }\n\n for (const pattern of allPatterns) {\n // Reset lastIndex for global regexes\n pattern.lastIndex = 0\n result = result.replace(pattern, '[REDACTED]')\n }\n\n return result\n}\n","import { execSync } from 'child_process'\nimport path from 'path'\nimport fs from 'fs'\n\nexport interface GitContext {\n repoName: string | null\n branch: string | null\n}\n\n// Handles SSH (git@host:owner/repo.git), HTTPS (https://host/owner/repo.git),\n// and bare git:// / ssh:// forms uniformly by normalizing the SSH scp-like\n// syntax's first ':' to '/' (but not the '://' in URLs with a real scheme),\n// then splitting on '/'.\nfunction parseOwnerAndRepo(url: string): { owner: string; repo: string } | null {\n const normalized = url.trim().replace(/^[^/]+:(?!\\/\\/)/, (match) => match.replace(':', '/'))\n const segments = normalized.split('/').filter(Boolean)\n if (segments.length < 2) return null\n const repo = segments[segments.length - 1].replace(/\\.git$/, '')\n const owner = segments[segments.length - 2]\n return owner && repo ? { owner, repo } : null\n}\n\nfunction nameFromRemote(root: string, qualifyWithOwner: boolean): string | null {\n try {\n const url = execSync('git remote get-url origin', {\n cwd: root,\n timeout: 2000,\n stdio: 'pipe',\n })\n .toString()\n .trim()\n const parsed = parseOwnerAndRepo(url)\n if (!parsed) return null\n return qualifyWithOwner ? `${parsed.owner}/${parsed.repo}` : parsed.repo\n } catch {\n return null\n }\n}\n\nfunction nameFromPackageJson(root: string): string | null {\n try {\n const raw = fs.readFileSync(path.join(root, 'package.json'), 'utf-8')\n const pkg = JSON.parse(raw) as { name?: string }\n if (!pkg.name) return null\n return pkg.name.replace(/^@[^/]+\\//, '')\n } catch {\n return null\n }\n}\n\nexport function getGitContext(cwd: string, nameOverride?: string | null, qualifyRepoName = false): GitContext {\n try {\n const root = execSync('git rev-parse --show-toplevel', {\n cwd,\n timeout: 2000,\n stdio: 'pipe',\n })\n .toString()\n .trim()\n\n const repoName =\n nameOverride ?? nameFromRemote(root, qualifyRepoName) ?? nameFromPackageJson(root) ?? path.basename(root)\n\n let branch: string | null = null\n try {\n branch =\n execSync('git branch --show-current', {\n cwd,\n timeout: 2000,\n stdio: 'pipe',\n })\n .toString()\n .trim() || null\n } catch {\n // Detached HEAD or not a git repo\n }\n\n return { repoName, branch }\n } catch {\n return { repoName: null, branch: null }\n }\n}\n","import { execSync } from 'child_process'\n\n/**\n * Returns commit subject lines for all commits made between `sha` and HEAD.\n * Returns an empty array if sha is empty, HEAD hasn't moved, or git fails.\n */\nexport function getCommitsSince(sha: string, cwd: string): string[] {\n if (!sha) return []\n try {\n const out = execSync(`git log ${sha}..HEAD --format=%s`, { cwd, timeout: 3000 }).toString().trim()\n return out ? out.split('\\n').filter(Boolean) : []\n } catch {\n return []\n }\n}\n","import fs from 'fs'\nimport path from 'path'\n\nconst HISTORY_FILE = '.aider.chat.history.md'\nconst PROMPT_MAX_LENGTH = 200\n\nexport function readLastAiderPrompt(cwd: string): string | null {\n try {\n const histPath = path.join(cwd, HISTORY_FILE)\n const content = fs.readFileSync(histPath, 'utf-8')\n const matches = [...content.matchAll(/^#### (.+)$/gm)]\n if (!matches.length) return null\n return matches[matches.length - 1][1].trim().slice(0, PROMPT_MAX_LENGTH)\n } catch {\n return null\n }\n}\n","import fs from 'fs'\nimport os from 'os'\nimport path from 'path'\nimport BUILTIN_TOOLS from './ai-tools.json'\nimport { debugLog } from '../utils/logger'\n\nexport interface AIToolEntry {\n tool: string\n displayName: string\n pattern: string\n hook: string | null\n contextSource: 'hook' | 'history-file' | 'sqlite' | null\n historyFormat: 'jsonl' | 'json' | 'markdown' | 'sqlite' | null\n securityWarning: string | null\n}\n\nconst USER_REGISTRY_PATH = path.join(os.homedir(), '.workscribe', 'ai-tools.json')\n\nexport function loadAIToolRegistry(): AIToolEntry[] {\n let userEntries: AIToolEntry[] = []\n\n try {\n if (fs.existsSync(USER_REGISTRY_PATH)) {\n const raw = fs.readFileSync(USER_REGISTRY_PATH, 'utf-8')\n const parsed = JSON.parse(raw)\n if (Array.isArray(parsed)) {\n userEntries = parsed\n .filter((entry) => typeof entry.tool === 'string' && typeof entry.pattern === 'string')\n .map((entry) => ({\n tool: entry.tool as string,\n displayName: (entry.displayName as string | undefined) ?? (entry.tool as string),\n pattern: entry.pattern as string,\n hook: (entry.hook as string | null | undefined) ?? null,\n contextSource: (entry.contextSource as AIToolEntry['contextSource'] | undefined) ?? null,\n historyFormat: (entry.historyFormat as AIToolEntry['historyFormat'] | undefined) ?? null,\n securityWarning: (entry.securityWarning as string | null | undefined) ?? null,\n }))\n }\n }\n } catch {\n debugLog('registry', 'Failed to load user AI tool registry — using built-ins only')\n }\n\n if (userEntries.length === 0) return BUILTIN_TOOLS as AIToolEntry[]\n\n const userToolSlugs = new Set(userEntries.map((entry) => entry.tool))\n const filteredBuiltins = (BUILTIN_TOOLS as AIToolEntry[]).filter((entry) => !userToolSlugs.has(entry.tool))\n return [...filteredBuiltins, ...userEntries]\n}\n","[\n {\n \"tool\": \"claude\",\n \"displayName\": \"Claude Code\",\n \"pattern\": \"^claude\\\\b\",\n \"hook\": \"claude-code\",\n \"contextSource\": \"hook\",\n \"historyFormat\": null,\n \"securityWarning\": null\n },\n {\n \"tool\": \"aider\",\n \"displayName\": \"Aider\",\n \"pattern\": \"^aider\\\\b\",\n \"hook\": null,\n \"contextSource\": \"history-file\",\n \"historyFormat\": \"markdown\",\n \"securityWarning\": null\n },\n {\n \"tool\": \"codex\",\n \"displayName\": \"Codex CLI\",\n \"pattern\": \"^codex\\\\b\",\n \"hook\": null,\n \"contextSource\": \"history-file\",\n \"historyFormat\": \"jsonl\",\n \"securityWarning\": null\n },\n {\n \"tool\": \"gemini\",\n \"displayName\": \"Gemini CLI\",\n \"pattern\": \"^gemini\\\\b\",\n \"hook\": null,\n \"contextSource\": \"history-file\",\n \"historyFormat\": \"json\",\n \"securityWarning\": null\n },\n {\n \"tool\": \"gh copilot\",\n \"displayName\": \"GitHub Copilot\",\n \"pattern\": \"^gh\\\\s+copilot\\\\b\",\n \"hook\": null,\n \"contextSource\": \"history-file\",\n \"historyFormat\": \"jsonl\",\n \"securityWarning\": null\n },\n {\n \"tool\": \"amazon-q\",\n \"displayName\": \"Amazon Q\",\n \"pattern\": \"^q\\\\s+(chat|dev)\\\\b\",\n \"hook\": null,\n \"contextSource\": \"history-file\",\n \"historyFormat\": \"json\",\n \"securityWarning\": null\n },\n {\n \"tool\": \"opencode\",\n \"displayName\": \"OpenCode\",\n \"pattern\": \"^opencode\\\\b\",\n \"hook\": null,\n \"contextSource\": \"sqlite\",\n \"historyFormat\": \"sqlite\",\n \"securityWarning\": null\n },\n {\n \"tool\": \"kilo\",\n \"displayName\": \"Kilo Code\",\n \"pattern\": \"^kilo\\\\b\",\n \"hook\": null,\n \"contextSource\": null,\n \"historyFormat\": null,\n \"securityWarning\": null\n },\n {\n \"tool\": \"grok\",\n \"displayName\": \"Grok Build\",\n \"pattern\": \"^grok\\\\b\",\n \"hook\": null,\n \"contextSource\": null,\n \"historyFormat\": null,\n \"securityWarning\": \"Grok Build was found to silently upload entire local git repositories — including .env files and untracked secrets — to Google Cloud Storage without user disclosure (July 2026 incident). Workscribe does not read Grok Build session files. Consider whether this tool is appropriate for use in repositories containing sensitive credentials.\"\n },\n {\n \"tool\": \"continue\",\n \"displayName\": \"Continue\",\n \"pattern\": \"^continue\\\\b\",\n \"hook\": null,\n \"contextSource\": null,\n \"historyFormat\": null,\n \"securityWarning\": null\n },\n {\n \"tool\": \"cody\",\n \"displayName\": \"Cody\",\n \"pattern\": \"^cody\\\\b\",\n \"hook\": null,\n \"contextSource\": null,\n \"historyFormat\": null,\n \"securityWarning\": null\n },\n {\n \"tool\": \"cursor\",\n \"displayName\": \"Cursor\",\n \"pattern\": \"^cursor\\\\b\",\n \"hook\": null,\n \"contextSource\": null,\n \"historyFormat\": null,\n \"securityWarning\": null\n }\n]\n","import chalk from 'chalk'\nimport fs from 'fs'\nimport { DEBUG_LOG_PATH } from './paths'\n\nconst isDebug = process.env.WORKSCRIBE_DEBUG === '1'\n\nexport const log = {\n info: (msg: string) => console.log(chalk.cyan('→'), msg),\n success: (msg: string) => console.log(chalk.green('✓'), msg),\n warn: (msg: string) => console.log(chalk.yellow('⚠'), msg),\n error: (msg: string) => console.error(chalk.red('✗'), msg),\n plain: (msg: string) => console.log(msg),\n}\n\nexport function debugLog(context: string, error: unknown): void {\n if (!isDebug) return\n const entry = `[${new Date().toISOString()}] [${context}] ${error instanceof Error ? error.stack : String(error)}\\n`\n try {\n fs.appendFileSync(DEBUG_LOG_PATH, entry, { mode: 0o600 })\n } catch {\n // If we can't write to the debug log, silently ignore\n }\n}\n","import fs from 'fs'\nimport path from 'path'\nimport { PROFILES_DIR } from '../utils/paths'\nimport { readConfig } from '../config'\nimport { isValidProfile } from './schema'\nimport type { Profile, ManifestEntry, ProfileRule } from './schema'\nimport { readCachedManifest } from './fetcher'\nimport { debugLog } from '../utils/logger'\n\n// Matches the Rule interface in patterns.ts — structural compatibility without circular import\ninterface CompiledRule {\n match(cmd: string): { category: string; metadata: Record<string, unknown> } | null\n}\n\nfunction compileRule(profileName: string, rule: ProfileRule): CompiledRule | null {\n let regex: RegExp\n try {\n regex = new RegExp(rule.pattern)\n } catch {\n debugLog('profiles', `Profile \"${profileName}\": invalid pattern \"${rule.pattern}\" — skipping rule`)\n return null\n }\n\n return {\n match(cmd: string) {\n const match = cmd.match(regex)\n if (!match) return null\n const metadata: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(rule.metadata ?? {})) {\n metadata[key] = value.replace(/\\$(\\d+)/g, (_, index: string) => match[Number(index)] ?? '')\n }\n return { category: rule.category, metadata }\n },\n }\n}\n\nfunction loadProfileFromDisk(name: string): Profile | null {\n const filePath = path.join(PROFILES_DIR, `${name}.json`)\n if (!fs.existsSync(filePath)) {\n debugLog('profiles', `Profile \"${name}\" not found in cache — run: workscribe profile add ${name}`)\n return null\n }\n let candidate: unknown\n try {\n candidate = JSON.parse(fs.readFileSync(filePath, 'utf-8'))\n } catch {\n debugLog('profiles', `Profile \"${name}\" contains invalid JSON — skipping`)\n return null\n }\n if (!isValidProfile(candidate)) {\n debugLog('profiles', `Profile \"${name}\" failed schema validation — skipping`)\n return null\n }\n return candidate\n}\n\nfunction loadUserProfiles(): Profile[] {\n if (!fs.existsSync(PROFILES_DIR)) return []\n const activeNames = new Set(readConfig().capture.profiles)\n return fs\n .readdirSync(PROFILES_DIR)\n .filter((file) => file.endsWith('.json') && file !== 'manifest.json')\n .filter((file) => {\n const name = file.replace(/\\.json$/, '')\n return !activeNames.has(name) // avoid double-loading names already in config\n })\n .flatMap((file) => {\n const candidate = loadProfileFromDisk(file.replace(/\\.json$/, ''))\n return candidate ? [candidate] : []\n })\n .filter((profile) => fs.existsSync(path.join(PROFILES_DIR, `${profile.name}.json`)))\n}\n\nexport function getActiveProfileRules(): CompiledRule[] {\n const activeNames = readConfig().capture.profiles\n if (activeNames.length === 0) return []\n\n return activeNames.flatMap((name) => {\n const profile = loadProfileFromDisk(name)\n if (!profile) return []\n return profile.rules.flatMap((rule) => {\n const compiled = compileRule(profile.name, rule)\n return compiled ? [compiled] : []\n })\n })\n}\n\nexport function getActiveProfileAiContexts(): string[] {\n const activeNames = readConfig().capture.profiles\n if (activeNames.length === 0) return []\n\n return activeNames.flatMap((name) => {\n const profile = loadProfileFromDisk(name)\n return profile?.aiContext ? [profile.aiContext] : []\n })\n}\n\nexport function getCachedProfiles(): Profile[] {\n if (!fs.existsSync(PROFILES_DIR)) return []\n return fs\n .readdirSync(PROFILES_DIR)\n .filter((file) => file.endsWith('.json') && file !== 'manifest.json')\n .flatMap((file) => {\n const profile = loadProfileFromDisk(file.replace(/\\.json$/, ''))\n return profile ? [profile] : []\n })\n}\n\nexport function detectProfilesForDirectory(dir: string): ManifestEntry[] {\n const manifest = readCachedManifest()\n if (!manifest) return []\n\n const activeNames = new Set(readConfig().capture.profiles)\n\n return manifest.filter((entry) => {\n if (activeNames.has(entry.name)) return false\n const indicatorFiles = entry.detect?.files ?? []\n return indicatorFiles.length > 0 && indicatorFiles.every((file) => fs.existsSync(path.join(dir, file)))\n })\n}\n\nexport { loadUserProfiles }\n","import fs from 'fs'\nimport { CONFIG_PATH } from '../utils/paths'\n\nexport interface WorkscribeConfig {\n ai: {\n provider: string // 'anthropic' | 'openai' | 'ollama' | 'openai-compatible'\n apiKey: string\n model: string\n baseUrl: string\n }\n session: {\n idleTimeout: number // minutes\n }\n git: {\n // When true, repo_name is \"owner/repo\" instead of bare \"repo\". Off by\n // default — bare names are nicer for the common case of one repo per\n // name. Turn on if you work across repos whose bare names collide\n // (e.g. an org that names plugin repos after the tool they target:\n // workscribe/vscode, workscribe/nvim, ...).\n qualifyRepoName: boolean\n }\n capture: {\n ignore: string[]\n aiTools: boolean\n includeAiderPrompt: boolean\n profiles: string[]\n }\n redact: {\n extra: string[]\n }\n summary: {\n format: 'markdown' | 'json'\n // Categories re-included in the AI payload (overrides built-in exclusions).\n // Excluded by default: exploring, other, linting.\n // Example: [\"linting\"] to include lint pass/fail in summaries.\n includeCategories?: string[]\n }\n projects?: Record<string, string> // absolute path → display name override\n integrations?: {\n slackWebhook?: string\n webhook?: string\n }\n}\n\nconst DEFAULTS: WorkscribeConfig = {\n ai: {\n provider: '',\n apiKey: '',\n model: '',\n baseUrl: '',\n },\n session: {\n idleTimeout: 30,\n },\n git: {\n qualifyRepoName: false,\n },\n capture: {\n ignore: ['cd', 'ls', 'll', 'la', 'ls -la', 'ls -l', 'ls -a', 'pwd', 'clear', 'exit', 'history', 'man'],\n aiTools: true,\n includeAiderPrompt: true,\n profiles: [],\n },\n redact: {\n extra: [],\n },\n summary: {\n format: 'markdown',\n },\n}\n\nexport function readConfig(): WorkscribeConfig {\n if (!fs.existsSync(CONFIG_PATH)) return { ...DEFAULTS }\n try {\n const raw = fs.readFileSync(CONFIG_PATH, 'utf-8')\n const parsed = JSON.parse(raw)\n return deepMerge(DEFAULTS, parsed)\n } catch {\n return { ...DEFAULTS }\n }\n}\n\nexport function writeConfig(config: WorkscribeConfig): void {\n fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2), { encoding: 'utf-8', mode: 0o600 })\n // Enforce permissions on existing files (mode only applies on creation above)\n try {\n fs.chmodSync(CONFIG_PATH, 0o600)\n } catch {\n /* ignore */\n }\n}\n\nexport function getConfigValue(config: WorkscribeConfig, key: string): unknown {\n const parts = key.split('.')\n let cur: unknown = config\n for (const part of parts) {\n if (cur == null || typeof cur !== 'object') return undefined\n cur = (cur as Record<string, unknown>)[part]\n }\n return cur\n}\n\nexport function setConfigValue(config: WorkscribeConfig, key: string, value: string): WorkscribeConfig {\n const parts = key.split('.')\n const result = JSON.parse(JSON.stringify(config)) as WorkscribeConfig\n let cur = result as unknown as Record<string, unknown>\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i]\n if (cur[part] == null || typeof cur[part] !== 'object') {\n cur[part] = {}\n }\n cur = cur[part] as Record<string, unknown>\n }\n const lastKey = parts[parts.length - 1]\n // Coerce value type\n if (value === 'true') cur[lastKey] = true\n else if (value === 'false') cur[lastKey] = false\n else if (!isNaN(Number(value))) cur[lastKey] = Number(value)\n else cur[lastKey] = value\n return result\n}\n\nfunction deepMerge<T extends object>(defaults: T, overrides: Partial<T>): T {\n const result = { ...defaults }\n for (const key of Object.keys(overrides) as (keyof T)[]) {\n const val = overrides[key]\n if (val !== null && typeof val === 'object' && !Array.isArray(val) && typeof defaults[key] === 'object') {\n result[key] = deepMerge(defaults[key] as object, val as object) as T[keyof T]\n } else if (val !== undefined) {\n result[key] = val as T[keyof T]\n }\n }\n return result\n}\n","export interface ProfileRule {\n pattern: string\n category: string\n metadata?: Record<string, string>\n}\n\nexport interface Profile {\n name: string\n displayName: string\n version: string\n detect?: { files?: string[] }\n rules: ProfileRule[]\n aiContext?: string\n}\n\nexport interface ManifestEntry {\n name: string\n displayName: string\n tags: string[]\n description: string\n keywords: string[]\n detect?: { files?: string[] }\n}\n\nfunction isNonEmptyString(value: unknown): value is string {\n return typeof value === 'string' && value.length > 0\n}\n\nfunction isValidRule(rule: unknown): boolean {\n if (!rule || typeof rule !== 'object') return false\n const { pattern, category } = rule as Record<string, unknown>\n return isNonEmptyString(pattern) && isNonEmptyString(category)\n}\n\nexport function isValidProfile(candidate: unknown): candidate is Profile {\n if (!candidate || typeof candidate !== 'object') return false\n const { name, displayName, version, rules } = candidate as Record<string, unknown>\n if (!isNonEmptyString(name) || !isNonEmptyString(displayName) || !isNonEmptyString(version)) return false\n if (!Array.isArray(rules)) return false\n return rules.every(isValidRule)\n}\n\nexport function isValidManifest(m: unknown): m is ManifestEntry[] {\n return (\n Array.isArray(m) &&\n m.every((e) => e && typeof e === 'object' && typeof (e as Record<string, unknown>).name === 'string')\n )\n}\n","import fs from 'fs'\nimport path from 'path'\nimport { PROFILES_DIR } from '../utils/paths'\nimport { isValidProfile, isValidManifest } from './schema'\nimport type { ManifestEntry, Profile } from './schema'\nimport { debugLog } from '../utils/logger'\nimport { fetchWithTimeout } from '../utils/fetch'\n\nconst REGISTRY_BASE = 'https://raw.githubusercontent.com/workscribe/profiles/main'\n\nfunction manifestCachePath(): string {\n return path.join(PROFILES_DIR, 'manifest.json')\n}\n\nexport async function fetchManifest(): Promise<ManifestEntry[]> {\n const response = await fetchWithTimeout(`${REGISTRY_BASE}/manifest.json`, {})\n if (!response.ok) throw new Error(`Registry unreachable (${response.status})`)\n const data: unknown = await response.json()\n if (!isValidManifest(data)) throw new Error('Manifest format unrecognised')\n return data\n}\n\nexport async function fetchProfile(name: string): Promise<Profile> {\n const response = await fetchWithTimeout(`${REGISTRY_BASE}/${name}.json`, {})\n if (response.status === 404) throw new Error(`Profile \"${name}\" not found in registry`)\n if (!response.ok) throw new Error(`Registry unreachable (${response.status})`)\n const data: unknown = await response.json()\n if (!isValidProfile(data)) throw new Error(`Profile \"${name}\" failed schema validation`)\n return data\n}\n\nexport async function installProfile(name: string): Promise<void> {\n ensureProfilesDir()\n const profile = await fetchProfile(name)\n const dest = path.join(PROFILES_DIR, `${name}.json`)\n fs.writeFileSync(dest, JSON.stringify(profile, null, 2), { encoding: 'utf-8', mode: 0o600 })\n debugLog('profiles', `Installed profile \"${name}\" to ${dest}`)\n}\n\nexport async function cacheManifest(): Promise<ManifestEntry[]> {\n ensureProfilesDir()\n const manifest = await fetchManifest()\n fs.writeFileSync(manifestCachePath(), JSON.stringify(manifest, null, 2), { encoding: 'utf-8', mode: 0o600 })\n return manifest\n}\n\nexport function readCachedManifest(): ManifestEntry[] | null {\n if (!fs.existsSync(manifestCachePath())) return null\n try {\n const data: unknown = JSON.parse(fs.readFileSync(manifestCachePath(), 'utf-8'))\n return isValidManifest(data) ? data : null\n } catch {\n return null\n }\n}\n\nfunction ensureProfilesDir(): void {\n if (!fs.existsSync(PROFILES_DIR)) {\n fs.mkdirSync(PROFILES_DIR, { recursive: true, mode: 0o700 })\n }\n}\n","const DEFAULT_TIMEOUT_MS = 30_000\n\nconst NETWORK_ERROR_CODES = new Set([\n 'ENOTFOUND',\n 'ECONNREFUSED',\n 'ECONNRESET',\n 'ETIMEDOUT',\n 'EHOSTUNREACH',\n 'ENETUNREACH',\n])\n\nfunction isNetworkError(err: unknown): boolean {\n if (!(err instanceof Error)) return false\n const cause = (err as Error & { cause?: unknown }).cause\n const code =\n (err as NodeJS.ErrnoException).code ?? (cause instanceof Error ? (cause as NodeJS.ErrnoException).code : undefined)\n return NETWORK_ERROR_CODES.has(code ?? '')\n}\n\nexport async function fetchWithTimeout(\n url: string,\n init: RequestInit,\n timeoutMs = DEFAULT_TIMEOUT_MS\n): Promise<Response> {\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), timeoutMs)\n try {\n return await fetch(url, { ...init, signal: controller.signal })\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n throw new Error(`Request timed out after ${timeoutMs / 1000}s`)\n }\n if (isNetworkError(err)) {\n throw new Error(\"No internet connection — try again when you're online\")\n }\n throw err\n } finally {\n clearTimeout(timer)\n }\n}\n","import { loadAIToolRegistry } from '../config/registry'\nimport { getActiveProfileRules } from '../profiles/loader'\nimport { debugLog } from '../utils/logger'\n\nexport interface NormalizedEvent {\n category: string\n metadata: Record<string, unknown>\n}\n\ninterface Rule {\n match(cmd: string): NormalizedEvent | null\n}\n\nfunction makeRule(\n pattern: RegExp,\n category: string,\n extract: (match: RegExpMatchArray, cmd: string) => Record<string, unknown> = () => ({})\n): Rule {\n return {\n match(cmd) {\n const m = cmd.match(pattern)\n if (!m) return null\n return { category, metadata: extract(m, cmd) }\n },\n }\n}\n\n// Extract package names from install commands like: npm install foo bar\nfunction extractPackages(cmd: string, afterKeyword: string): string[] {\n const idx = cmd.indexOf(afterKeyword)\n if (idx === -1) return []\n return cmd\n .slice(idx + afterKeyword.length)\n .trim()\n .split(/\\s+/)\n .filter((part) => part && !part.startsWith('-'))\n}\n\nconst BASE_RULES: Rule[] = [\n // ─── Git operations ───────────────────────────────────────────────────────\n makeRule(/^git\\s+commit\\b/, 'shipping', (_m, cmd) => {\n const msgMatch = cmd.match(/-m\\s+[\"']?([^\"']+)[\"']?/)\n return { message: msgMatch ? msgMatch[1].trim() : null }\n }),\n\n makeRule(/^git\\s+push\\b/, 'shipping', (_m, cmd) => {\n const parts = cmd.split(/\\s+/)\n return { remote: parts[2] ?? 'origin', branch: parts[3] ?? null }\n }),\n\n makeRule(/^git\\s+(pull|fetch)\\b/, 'versioning', (_m, cmd) => {\n const parts = cmd.split(/\\s+/)\n return { subcommand: parts[1], remote: parts[2] ?? 'origin' }\n }),\n\n makeRule(/^git\\s+(checkout|switch)\\b/, 'versioning', (_m, cmd) => {\n const parts = cmd.split(/\\s+/)\n const branch = parts.find((part) => !part.startsWith('-') && part !== 'git' && part !== parts[1])\n return { branch: branch ?? null }\n }),\n\n makeRule(/^git\\s+(merge|rebase)\\b/, 'shipping', (_m, cmd) => {\n const parts = cmd.split(/\\s+/)\n return { subcommand: parts[1], target: parts[2] ?? null }\n }),\n\n makeRule(/^git\\s+stash\\b/, 'versioning', (_m, cmd) => {\n const parts = cmd.split(/\\s+/)\n return { subcommand: parts[2] ?? 'push' }\n }),\n\n makeRule(/^git\\s+/, 'versioning', (_m, cmd) => {\n const parts = cmd.split(/\\s+/)\n return { subcommand: parts[1] ?? null }\n }),\n\n // ─── Releasing ────────────────────────────────────────────────────────────\n makeRule(/^npm\\s+publish\\b/, 'releasing', () => ({ tool: 'npm' })),\n makeRule(/^cargo\\s+publish\\b/, 'releasing', () => ({ tool: 'cargo' })),\n makeRule(/^gem\\s+push\\b/, 'releasing', () => ({ tool: 'gem' })),\n makeRule(/^docker\\s+push\\b/, 'releasing', (_m, cmd) => ({ tool: 'docker', image: cmd.split(/\\s+/)[2] ?? null })),\n makeRule(/^gh\\s+release\\b/, 'releasing', (_m, cmd) => ({ tool: 'gh', subcommand: cmd.split(/\\s+/)[2] ?? null })),\n makeRule(/^fly\\s+(deploy|launch)\\b/, 'releasing', (match) => ({ tool: 'fly', subcommand: match[1] })),\n makeRule(/^vercel\\s+(deploy|build|--prod)\\b/, 'releasing', () => ({ tool: 'vercel' })),\n makeRule(/^netlify\\s+deploy\\b/, 'releasing', () => ({ tool: 'netlify' })),\n makeRule(/^railway\\s+up\\b/, 'releasing', () => ({ tool: 'railway' })),\n makeRule(/^wrangler\\s+deploy\\b/, 'releasing', () => ({ tool: 'wrangler' })),\n\n // ─── Dependencies ─────────────────────────────────────────────────────────\n makeRule(/^npm\\s+(install|i|add)\\b/, 'dependencies', (_m, cmd) => ({\n tool: 'npm',\n packages: extractPackages(cmd, cmd.includes('install') ? 'install' : cmd.includes(' i ') ? ' i ' : 'add'),\n })),\n\n makeRule(/^(yarn|pnpm)\\s+(install|add)\\b/, 'dependencies', (m, cmd) => ({\n tool: m[1],\n packages: extractPackages(cmd, 'add'),\n })),\n\n makeRule(/^bun\\s+(install|add)\\b/, 'dependencies', (_m, cmd) => ({\n tool: 'bun',\n packages: extractPackages(cmd, 'add'),\n })),\n\n makeRule(/^pip\\s+(install)\\b/, 'dependencies', (_m, cmd) => ({\n tool: 'pip',\n packages: extractPackages(cmd, 'install'),\n })),\n\n makeRule(/^cargo\\s+add\\b/, 'dependencies', (_m, cmd) => ({\n tool: 'cargo',\n packages: extractPackages(cmd, 'add'),\n })),\n\n makeRule(/^(brew)\\s+install\\b/, 'dependencies', (_m, cmd) => ({\n tool: 'brew',\n packages: extractPackages(cmd, 'install'),\n })),\n\n makeRule(/^go\\s+get\\b/, 'dependencies', (_m, cmd) => ({\n tool: 'go',\n packages: extractPackages(cmd, 'get'),\n })),\n\n makeRule(/^npm\\s+(uninstall|remove|rm)\\b/, 'dependencies', (_m, cmd) => ({\n tool: 'npm',\n packages: extractPackages(cmd, cmd.split(/\\s+/)[1]),\n })),\n\n makeRule(/^(yarn|pnpm)\\s+remove\\b/, 'dependencies', (m, cmd) => ({\n tool: m[1],\n packages: extractPackages(cmd, 'remove'),\n })),\n\n makeRule(/^bun\\s+remove\\b/, 'dependencies', (_m, cmd) => ({\n tool: 'bun',\n packages: extractPackages(cmd, 'remove'),\n })),\n\n makeRule(/^pip\\s+uninstall\\b/, 'dependencies', (_m, cmd) => ({\n tool: 'pip',\n packages: extractPackages(cmd, 'uninstall'),\n })),\n\n // Runtime version managers\n makeRule(/^nvm\\b/, 'dependencies', (_m, cmd) => ({ tool: 'nvm', subcommand: cmd.split(/\\s+/)[1] ?? null })),\n makeRule(/^(fnm|volta)\\b/, 'dependencies', (m, cmd) => ({ tool: m[1], subcommand: cmd.split(/\\s+/)[1] ?? null })),\n makeRule(/^(rbenv|pyenv|asdf)\\b/, 'dependencies', (m, cmd) => ({\n tool: m[1],\n subcommand: cmd.split(/\\s+/)[1] ?? null,\n })),\n\n // ─── Tests ────────────────────────────────────────────────────────────────\n makeRule(/^npm\\s+(test|run\\s+test)\\b/, 'testing', () => ({ tool: 'npm' })),\n makeRule(/^yarn\\s+test\\b/, 'testing', () => ({ tool: 'yarn' })),\n makeRule(/^pnpm\\s+test\\b/, 'testing', () => ({ tool: 'pnpm' })),\n makeRule(/^bun\\s+test\\b/, 'testing', () => ({ tool: 'bun' })),\n makeRule(/^(jest|vitest)\\b/, 'testing', (match) => ({ tool: match[1] })),\n makeRule(/^pytest\\b/, 'testing', () => ({ tool: 'pytest' })),\n makeRule(/^go\\s+test\\b/, 'testing', () => ({ tool: 'go' })),\n makeRule(/^cargo\\s+test\\b/, 'testing', () => ({ tool: 'cargo' })),\n makeRule(/^rspec\\b/, 'testing', () => ({ tool: 'rspec' })),\n makeRule(/^(php\\s+)?phpunit\\b/, 'testing', () => ({ tool: 'phpunit' })),\n\n // ─── Build ────────────────────────────────────────────────────────────────\n makeRule(/^npm\\s+run\\s+build\\b/, 'building', () => ({ tool: 'npm' })),\n makeRule(/^(yarn|pnpm)\\s+build\\b/, 'building', (match) => ({ tool: match[1] })),\n makeRule(/^bun\\s+run\\s+build\\b/, 'building', () => ({ tool: 'bun' })),\n makeRule(/^(make|gmake)\\b/, 'building', (match) => ({ tool: match[1] })),\n makeRule(/^cargo\\s+build\\b/, 'building', () => ({ tool: 'cargo' })),\n makeRule(/^go\\s+build\\b/, 'building', () => ({ tool: 'go' })),\n makeRule(/^docker\\s+build\\b/, 'building', () => ({ tool: 'docker' })),\n makeRule(/^(mvn|gradle)\\b/, 'building', (match) => ({ tool: match[1] })),\n\n // ─── Dev server / running ─────────────────────────────────────────────────\n makeRule(/^npm\\s+run\\s+(dev|start|serve)\\b/, 'running', (_m, cmd) => ({\n tool: 'npm',\n script: cmd.split(/\\s+/)[2],\n })),\n makeRule(/^(yarn|pnpm)\\s+(dev|start)\\b/, 'running', (match) => ({ tool: match[1], script: match[2] })),\n makeRule(/^bun\\s+run\\s+(dev|start|serve)\\b/, 'running', (_m, cmd) => ({\n tool: 'bun',\n script: cmd.split(/\\s+/)[2],\n })),\n makeRule(/^python\\s+.*manage\\.py\\s+runserver\\b/, 'running', () => ({ tool: 'django' })),\n\n // ─── Infrastructure ───────────────────────────────────────────────────────\n makeRule(/^ssh\\b/, 'infrastructure', (_m, cmd) => {\n const parts = cmd.split(/\\s+/)\n return { tool: 'ssh', target: parts[parts.length - 1] }\n }),\n\n makeRule(/^kubectl\\b/, 'infrastructure', (_m, cmd) => {\n const parts = cmd.split(/\\s+/)\n return { tool: 'kubectl', subcommand: parts[1] ?? null }\n }),\n\n makeRule(/^(helm|terraform|pulumi)\\b/, 'infrastructure', (m, cmd) => {\n const parts = cmd.split(/\\s+/)\n return { tool: m[1], subcommand: parts[1] ?? null }\n }),\n\n makeRule(/^docker\\s+(run|compose|ps|stop|start|rm|exec)\\b/, 'infrastructure', (_m, cmd) => {\n const parts = cmd.split(/\\s+/)\n return { tool: 'docker', subcommand: parts[1] }\n }),\n\n makeRule(/^(aws|gcloud|az)\\b/, 'infrastructure', (m, cmd) => {\n const parts = cmd.split(/\\s+/)\n return { tool: m[1], subcommand: parts[1] ?? null }\n }),\n\n // ─── Database ─────────────────────────────────────────────────────────────\n makeRule(/^(psql|pgcli)\\b/, 'database', (m) => ({ tool: m[1] })),\n makeRule(/^(mysql|mycli)\\b/, 'database', (m) => ({ tool: m[1] })),\n makeRule(/^sqlite3\\b/, 'database', () => ({ tool: 'sqlite3' })),\n makeRule(/^(mongosh|mongo)\\b/, 'database', (m) => ({ tool: m[1] })),\n makeRule(/^redis-cli\\b/, 'database', () => ({ tool: 'redis-cli' })),\n\n // ─── npx ─────────────────────────────────────────────────────────────────\n makeRule(/^npx\\s+(jest|vitest|mocha|ava|tap)\\b/, 'testing', (_m, cmd) => ({\n tool: cmd.split(/\\s+/)[1],\n })),\n makeRule(/^npx\\s+tsc\\b/, 'building', () => ({ tool: 'tsc' })),\n makeRule(/^npx\\s+(eslint|tslint|biome)\\b/, 'linting', (_m, cmd) => ({\n tool: cmd.split(/\\s+/)[1],\n })),\n makeRule(/^npx\\s+(prettier|dprint)\\b/, 'linting', (_m, cmd) => ({\n tool: cmd.split(/\\s+/)[1],\n })),\n makeRule(/^npx\\s+\\S+/, 'running', (_m, cmd) => ({\n tool: cmd.split(/\\s+/)[1],\n })),\n\n // ─── Scripts ──────────────────────────────────────────────────────────────\n makeRule(/^(bash|sh|zsh|fish)\\s+\\S+/, 'running', (match) => ({ shell: match[1] })),\n makeRule(/^node\\s+\\S+\\.(?:js|mjs|cjs)\\b/, 'running', () => ({ runtime: 'node' })),\n makeRule(/^python3?\\s+\\S+\\.py\\b/, 'running', () => ({ runtime: 'python' })),\n\n // ─── Linting / code quality ───────────────────────────────────────────────\n makeRule(/^(eslint|tslint|biome)\\b/, 'linting', (match) => ({ tool: match[1] })),\n makeRule(/^(prettier|dprint)\\b/, 'linting', (match) => ({ tool: match[1] })),\n\n // ─── generic run scripts ──────────────────────────────────────────────────\n makeRule(/^npm\\s+run\\s+\\S+/, 'running', (_m, cmd) => ({\n tool: 'npm',\n script: cmd.split(/\\s+/)[2],\n })),\n\n makeRule(/^bun\\s+run\\s+\\S+/, 'running', (_m, cmd) => ({\n tool: 'bun',\n script: cmd.split(/\\s+/)[2],\n })),\n\n // ─── Code search ─────────────────────────────────────────────────────────\n makeRule(/^(grep|egrep|fgrep)\\b/, 'exploring', (match) => ({ tool: match[1] })),\n makeRule(/^(rg|ag|ack|ripgrep)\\b/, 'exploring', (match) => ({ tool: match[1] })),\n makeRule(/^find\\s/, 'exploring', () => ({ tool: 'find' })),\n\n // ─── Code read ────────────────────────────────────────────────────────────\n makeRule(/^(cat|bat|less|more)\\s+\\S+/, 'exploring', (match) => ({ tool: match[1] })),\n makeRule(/^(head|tail)\\b/, 'exploring', (match) => ({ tool: match[1] })),\n\n // ─── File operations ──────────────────────────────────────────────────────\n makeRule(/^(cp|rsync)\\b/, 'files', (match) => ({ tool: match[1] })),\n makeRule(/^(mv)\\b/, 'files', () => ({ tool: 'mv' })),\n makeRule(/^(rm|rmdir)\\b/, 'files', (match) => ({ tool: match[1] })),\n makeRule(/^(mkdir|touch|ln)\\b/, 'files', (match) => ({ tool: match[1] })),\n makeRule(/^(chmod|chown|chgrp)\\b/, 'files', (match) => ({ tool: match[1] })),\n\n // ─── Environment ──────────────────────────────────────────────────────────\n makeRule(/^export\\s+\\w+=/, 'files', (_m, cmd) => {\n const varName = cmd.match(/^export\\s+(\\w+)=/)?.[1] ?? null\n return { variable: varName }\n }),\n makeRule(/^source\\s+/, 'files', () => ({})),\n]\n\nfunction aiToolRules(): Rule[] {\n return loadAIToolRegistry().flatMap((entry) => {\n try {\n return [makeRule(new RegExp(entry.pattern), 'ai_session', () => ({ tool: entry.tool }))]\n } catch {\n debugLog('registry', `Skipping tool \"${entry.tool}\" — invalid pattern: ${entry.pattern}`)\n return []\n }\n })\n}\n\nexport function buildRules(profileRules: Array<{ match(cmd: string): NormalizedEvent | null }> = []): Rule[] {\n return [...BASE_RULES, ...profileRules, ...aiToolRules()]\n}\n\nexport const RULES: Rule[] = buildRules(getActiveProfileRules())\n\nexport function normalizeCommand(command: string): NormalizedEvent {\n let trimmed = command.trim().replace(/\\s+/g, ' ')\n\n // Strip `git -C <path>` prefix so rules match regardless of working directory flag\n trimmed = trimmed.replace(/^(git)\\s+-C\\s+\\S+\\s+/, '$1 ')\n\n for (const rule of RULES) {\n const result = rule.match(trimmed)\n if (result) return result\n }\n\n return { category: 'other', metadata: {} }\n}\n","import type { EventRow } from '../db/types'\n\nfunction normalizeForFilter(cmd: string): string {\n return cmd.trim().replace(/\\s+/g, ' ')\n}\n\n// Always filtered regardless of user config — internal tool noise\nconst BUILTIN_IGNORE = new Set(['workscribe'])\n\n/**\n * Returns true if the command should be dropped (noise / ignore list).\n */\nexport function shouldFilter(command: string, ignoreList: string[]): boolean {\n const normalized = normalizeForFilter(command)\n if (!normalized) return true\n\n const baseCmd = normalized.split(' ')[0]\n\n // Built-in filter: always excluded, not user-configurable\n if (BUILTIN_IGNORE.has(baseCmd)) return true\n\n // User-configurable ignore list\n const normalizedIgnore = ignoreList.map(normalizeForFilter)\n if (normalizedIgnore.includes(normalized)) return true\n if (normalizedIgnore.includes(baseCmd)) return true\n\n return false\n}\n\n/**\n * Returns true if this command is a duplicate of the last event\n * (same command + same cwd within the dedup window).\n */\nexport function isDuplicate(\n command: string,\n cwd: string,\n lastEvent: Pick<EventRow, 'command' | 'cwd' | 'captured_at'> | undefined,\n dedupWindowMs = 5000,\n now = Date.now()\n): boolean {\n if (!lastEvent) return false\n const lastTime = new Date(lastEvent.captured_at).getTime()\n return lastEvent.command === normalizeForFilter(command) && lastEvent.cwd === cwd && now - lastTime < dedupWindowMs\n}\n","// Per-file dedup window for IDE file-save events.\n// Prevents duplicate captures when an IDE auto-saves the same file repeatedly.\nexport const IDE_DEDUP_WINDOW_MS = 30_000\n\n// Valid event type strings sent by IDE integrations via `workscribe _capture --type <type>`.\nexport const IDE_EVENT_TYPES = new Set(['code_edit', 'debug_start', 'debug_end', 'task_run'])\n\nexport function isIdeEventType(type: string): boolean {\n return IDE_EVENT_TYPES.has(type)\n}\n","import { Command } from 'commander'\nimport { captureCommand } from '../capture'\nimport { debugLog } from '../utils/logger'\n\nconst CAPTURE_HANG_TIMEOUT_MS = 5_000\n\nexport function registerCapture(program: Command): void {\n // Internal command — called by the shell hook and IDE integrations, not by the user\n program\n .command('_capture')\n .description('Internal: capture a shell command or IDE event (called by shell hook or IDE plugin)')\n .option('--cmd <command>', 'command that was executed (shell events)')\n .option('--cwd <path>', 'working directory')\n .option('--exit <code>', 'exit code', parseInt)\n .option('--duration <ms>', 'duration in milliseconds', parseInt)\n .option('--git-before <sha>', 'git HEAD SHA before this command ran')\n .option('--type <type>', 'event type override — skips normalization (IDE integrations)')\n .option('--source <source>', 'event source identifier (e.g. vscode, neovim, jupyter)')\n .option('--file <path>', 'file path for code_edit events')\n .action((opts) => {\n // Prevent background process accumulation if the process hangs (e.g. SQLite locked).\n // unref() allows a natural exit to happen immediately without waiting for the timer.\n const hangGuard = setTimeout(() => process.exit(0), CAPTURE_HANG_TIMEOUT_MS)\n hangGuard.unref()\n\n // Never surface errors to the terminal — this runs silently in the background\n try {\n if (!opts.cwd) return\n // Require either a shell command or a typed IDE event\n if (!opts.cmd && !opts.type) return\n captureCommand({\n command: opts.cmd,\n cwd: opts.cwd,\n exitCode: opts.exit ?? null,\n durationMs: opts.duration ?? null,\n gitBefore: opts.gitBefore ?? undefined,\n source: opts.source ?? undefined,\n type: opts.type ?? undefined,\n file: opts.file ?? undefined,\n })\n } catch (err) {\n debugLog('_capture', err)\n }\n })\n}\n","import { redact } from './redact'\n\nexport function containsSecrets(text: string): boolean {\n return redact(text) !== text\n}\n","import fs from 'fs'\nimport path from 'path'\nimport { getDb } from './index'\nimport { ALERTS_PENDING_PATH } from '../utils/paths'\n\nexport interface AlertRow {\n id: number\n created_at: number\n tool: string\n session_id: string | null\n context: string\n cleared: number\n}\n\nexport function insertAlert(tool: string, sessionId: string | null, context: string): void {\n getDb()\n .prepare(\n `INSERT INTO alerts (created_at, tool, session_id, context)\n VALUES ($created_at, $tool, $session_id, $context)`\n )\n .run({ created_at: Date.now(), tool, session_id: sessionId ?? null, context })\n\n fs.mkdirSync(path.dirname(ALERTS_PENDING_PATH), { recursive: true })\n fs.writeFileSync(ALERTS_PENDING_PATH, '', { flag: 'w' })\n}\n\nexport function getPendingAlerts(): AlertRow[] {\n return getDb()\n .prepare('SELECT * FROM alerts WHERE cleared = 0 ORDER BY created_at DESC')\n .all() as unknown as AlertRow[]\n}\n\nexport function hasPendingAlerts(): boolean {\n const row = getDb().prepare('SELECT COUNT(*) as count FROM alerts WHERE cleared = 0').get() as {\n count: number | bigint\n }\n return Number(row.count) > 0\n}\n\nexport function clearAlerts(): number {\n const result = getDb().prepare('UPDATE alerts SET cleared = 1 WHERE cleared = 0').run()\n try {\n fs.unlinkSync(ALERTS_PENDING_PATH)\n } catch {\n // File may already be absent\n }\n return Number(result.changes)\n}\n","import { Command } from 'commander'\nimport { captureCommand } from '../capture'\nimport { readConfig } from '../config'\nimport { debugLog } from '../utils/logger'\nimport { containsSecrets } from '../capture/detect-secrets'\nimport { insertAlert } from '../db/alerts'\n\n/** Parses a Claude Code PostToolUse stdin payload. Returns null if required fields are missing. */\nexport function parseHookPayload(raw: string): { command: string; cwd: string } | null {\n if (!raw.trim()) return null\n const payload = JSON.parse(raw) as Record<string, unknown>\n const toolInput = payload.tool_input as Record<string, unknown> | undefined\n const command = typeof toolInput?.command === 'string' ? toolInput.command : null\n const cwd = typeof payload.cwd === 'string' ? payload.cwd : null\n if (!command || !cwd) return null\n return { command, cwd }\n}\n\ninterface UserPromptPayload {\n session_id: string\n prompt: string\n cwd: string\n}\n\n/** Parses a Claude Code UserPromptSubmit stdin payload. Returns null if required fields are missing. */\nexport function parseUserPromptPayload(raw: string): UserPromptPayload | null {\n if (!raw.trim()) return null\n const payload = JSON.parse(raw) as Record<string, unknown>\n const prompt = typeof payload.prompt === 'string' ? payload.prompt : null\n const sessionId = typeof payload.session_id === 'string' ? payload.session_id : ''\n const cwd = typeof payload.cwd === 'string' ? payload.cwd : ''\n if (!prompt) return null\n return { session_id: sessionId, prompt, cwd }\n}\n\nexport function registerHook(program: Command): void {\n // Internal command — called by AI tool hooks (e.g. Claude Code PostToolUse), not by the user\n program\n .command('_hook')\n .description('Internal: capture events from AI tool hooks (stdin JSON payload)')\n .option('--source <source>', 'hook source identifier (e.g. claude-code)')\n .option('--event <event>', 'hook event type (PostToolUse or UserPromptSubmit)', 'PostToolUse')\n .action((opts: { source?: string; event: string }) => {\n let raw = ''\n process.stdin.setEncoding('utf-8')\n process.stdin.on('data', (chunk: string) => {\n raw += chunk\n })\n process.stdin.on('end', () => {\n try {\n if (opts.event === 'UserPromptSubmit') {\n const parsed = parseUserPromptPayload(raw)\n if (!parsed) return\n if (containsSecrets(parsed.prompt)) {\n insertAlert(\n opts.source ?? 'unknown',\n parsed.session_id || null,\n 'Possible credential detected in prompt submitted to AI tool'\n )\n // Claude Code reads this JSON and injects systemMessage into Claude's context\n process.stdout.write(\n JSON.stringify({\n systemMessage:\n 'Workscribe detected a possible credential in your prompt. ' +\n 'Run `workscribe alerts` for details.',\n })\n )\n }\n return\n }\n\n // Default: PostToolUse — capture the shell command\n if (readConfig().capture.aiTools === false) return\n const parsed = parseHookPayload(raw)\n if (!parsed) return\n captureCommand({\n command: parsed.command,\n cwd: parsed.cwd,\n exitCode: null,\n durationMs: null,\n source: opts.source,\n })\n } catch (err) {\n debugLog('_hook', err)\n }\n })\n })\n}\n","import { Command } from 'commander'\nimport fs from 'fs'\nimport path from 'path'\nimport os from 'os'\nimport prompts from 'prompts'\nimport chalk from 'chalk'\nimport { CONFIG_PATH, PROFILES_DIR, REQUIRED_DIRS } from '../utils/paths'\nimport { readConfig, writeConfig } from '../config'\nimport { detectProfilesForDirectory } from '../profiles/loader'\nimport { installProfile, cacheManifest } from '../profiles/fetcher'\nimport { getDb } from '../db'\nimport { getProvider } from '../ai/router'\nimport { log } from '../utils/logger'\nimport { loadAIToolRegistry } from '../config/registry'\nimport {\n isHookInstalled,\n isHookOutdated,\n installHook,\n updateHook,\n isCompletionsInstalled,\n installCompletions,\n resolveWorkscribeBinary,\n injectBinaryPath,\n} from '../capture/shell-hook'\nimport { AI_HOOK_INTEGRATIONS } from '../capture/hooks'\nimport { getPublicCommands } from './completions'\n\nfunction detectShell(): { name: string; rcFile: string } | null {\n const shell = process.env.SHELL ?? ''\n if (shell.includes('zsh')) return { name: 'zsh', rcFile: path.join(os.homedir(), '.zshrc') }\n if (shell.includes('bash')) return { name: 'bash', rcFile: path.join(os.homedir(), '.bashrc') }\n if (shell.includes('fish')) {\n const confDir = path.join(os.homedir(), '.config', 'fish', 'conf.d')\n return { name: 'fish', rcFile: path.join(confDir, 'workscribe.fish') }\n }\n return null\n}\n\nfunction step(current: number, total: number, label: string): void {\n log.plain(chalk.bold(`\\n [${current}/${total}] ${label}`))\n}\n\nexport function registerInit(program: Command): void {\n program\n .command('init')\n .description('Set up Workscribe and install or update shell hooks')\n .action(async () => {\n const TOTAL_STEPS = 5\n log.plain(chalk.bold('\\n Workscribe — Developer Work Journal\\n'))\n\n // ── Step 1: Data directories ──────────────────────────────────────────────\n step(1, TOTAL_STEPS, 'Creating data directories')\n\n for (const dir of REQUIRED_DIRS) {\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true, mode: 0o700 })\n log.success(`Created ${dir}`)\n } else {\n try {\n fs.chmodSync(dir, 0o700)\n } catch {\n /* ignore */\n }\n log.info(`${dir} already exists`)\n }\n }\n\n if (!fs.existsSync(PROFILES_DIR)) {\n fs.mkdirSync(PROFILES_DIR, { recursive: true, mode: 0o700 })\n }\n\n // ── Step 2: Database ──────────────────────────────────────────────────────\n step(2, TOTAL_STEPS, 'Initialising database')\n getDb()\n log.success('Database ready')\n\n // ── Step 3: Shell hook + completions ──────────────────────────────────────\n step(3, TOTAL_STEPS, 'Installing shell hook')\n\n const shell = detectShell()\n if (!shell) {\n log.warn('Could not detect shell. Supported: zsh, bash, fish')\n log.plain(\n ` Manually add the hook from: ${chalk.cyan('shell/hook.zsh')}, ${chalk.cyan('shell/hook.bash')}, or ${chalk.cyan('shell/hook.fish')}`\n )\n } else {\n const hookFile = path.join(__dirname, '..', 'shell', `hook.${shell.name}`)\n if (!fs.existsSync(hookFile)) {\n log.warn(`Hook template not found at ${hookFile}`)\n } else {\n const hookContent = fs.readFileSync(hookFile, 'utf-8')\n const binaryPath = resolveWorkscribeBinary()\n const hookWithPath = binaryPath ? injectBinaryPath(hookContent, binaryPath) : hookContent\n\n // For fish: ensure conf.d directory exists before touching the file\n if (shell.name === 'fish') {\n const confDir = path.dirname(shell.rcFile)\n if (!fs.existsSync(confDir)) fs.mkdirSync(confDir, { recursive: true })\n }\n\n if (!fs.existsSync(shell.rcFile)) fs.writeFileSync(shell.rcFile, '')\n\n if (!isHookInstalled(shell.rcFile)) {\n log.plain('')\n log.plain(chalk.dim(' Workscribe adds a lightweight hook to your shell that captures each'))\n log.plain(chalk.dim(' command you run — the text, exit code, duration, and working directory.'))\n log.plain(chalk.dim(' It runs in the background and adds no latency to your terminal.'))\n log.plain(chalk.dim(' Credentials and secrets are redacted before anything is stored.'))\n log.plain('')\n installHook(shell.rcFile, hookWithPath)\n log.success(`Shell hook installed in ${shell.rcFile}`)\n } else if (isHookOutdated(shell.rcFile, hookWithPath)) {\n const { update } = await prompts({\n type: 'confirm',\n name: 'update',\n message: `Shell hook in ${shell.rcFile} is outdated. Update?`,\n initial: true,\n })\n if (update) {\n updateHook(shell.rcFile, hookWithPath)\n log.success(`Shell hook updated in ${shell.rcFile}`)\n } else {\n log.info('Shell hook update skipped')\n }\n } else {\n log.info(`Shell hook up to date in ${shell.rcFile}`)\n }\n\n // Offer completions install\n if (isCompletionsInstalled(shell)) {\n log.info('Shell completions already installed')\n } else {\n const { installComps } = await prompts({\n type: 'confirm',\n name: 'installComps',\n message: 'Install shell completions (tab-complete workscribe commands)?',\n initial: true,\n })\n if (installComps) {\n try {\n installCompletions(shell, getPublicCommands(program))\n log.success('Shell completions installed')\n } catch (error) {\n log.warn(`Completions install failed: ${(error as Error).message}`)\n }\n }\n }\n }\n }\n\n // ── Step 4: AI tools ──────────────────────────────────────────────────────\n step(4, TOTAL_STEPS, 'Detecting AI coding tools')\n\n const installedTools = loadAIToolRegistry().filter(\n (entry) => entry.hook !== null && AI_HOOK_INTEGRATIONS[entry.hook!]?.isInstalled()\n )\n\n if (installedTools.length === 0) {\n log.info('No AI coding tools detected — re-run workscribe init after installing one')\n } else {\n for (const tool of installedTools) {\n const integration = AI_HOOK_INTEGRATIONS[tool.hook!]!\n\n if (integration.isHookInstalled()) {\n log.info(`${integration.displayName} session hook already installed`)\n } else {\n const { install } = await prompts({\n type: 'confirm',\n name: 'install',\n message: `${integration.displayName} detected. Install session capture hook?`,\n initial: false,\n })\n if (install) {\n integration.install()\n log.success(`${integration.displayName} session hook installed`)\n } else {\n log.info(`${integration.displayName} hook skipped — re-run workscribe init to install later`)\n }\n }\n }\n }\n\n // Profile detection (part of environment scan, no separate step)\n const config = readConfig()\n try {\n await cacheManifest()\n const detected = detectProfilesForDirectory(process.cwd())\n const alreadyActive = new Set(config.capture.profiles)\n const toPrompt = detected.filter((entry) => !alreadyActive.has(entry.name))\n\n if (toPrompt.length > 0) {\n log.plain('')\n for (const entry of toPrompt) {\n const { install } = await prompts({\n type: 'confirm',\n name: 'install',\n message: `${entry.displayName} project detected. Enable the ${entry.displayName} profile?`,\n initial: true,\n })\n if (install) {\n await installProfile(entry.name)\n config.capture.profiles = [...new Set([...config.capture.profiles, entry.name])]\n log.success(`${entry.displayName} profile enabled`)\n }\n }\n writeConfig(config)\n } else if (detected.length === 0) {\n log.info('No project profiles detected — run workscribe profile detect from your project directory')\n }\n } catch {\n log.info('Could not reach profile registry — run workscribe profile detect after connecting')\n }\n\n // ── Step 5: AI provider ───────────────────────────────────────────────────\n step(5, TOTAL_STEPS, 'Configuring AI provider')\n\n let providerConfigured = !!config.ai.provider\n\n if (config.ai.provider) {\n log.info(`AI provider already configured: ${chalk.cyan(config.ai.provider)}`)\n } else {\n log.plain('')\n const { provider } = await prompts({\n type: 'select',\n name: 'provider',\n message: 'Which AI provider do you want to use?',\n choices: [\n { title: 'Anthropic (Claude) — requires API key', value: 'anthropic' },\n { title: 'OpenAI — requires API key', value: 'openai' },\n { title: 'Ollama (local) — free, runs on your machine', value: 'ollama' },\n { title: 'Other (OpenAI-compatible) — Groq, Together, Mistral…', value: 'openai-compatible' },\n { title: 'Skip — configure later', value: 'skip' },\n ],\n })\n\n if (!provider || provider === 'skip') {\n providerConfigured = false\n log.info('Skipped — run later: workscribe config set ai.provider <provider>')\n } else {\n config.ai.provider = provider\n\n if (provider === 'ollama') {\n log.plain(`\\n ${chalk.dim('Make sure Ollama is running: ollama serve')}`)\n log.plain(\n ` ${chalk.dim('Default model: llama3 (change with: workscribe config set ai.model <model>)')}\\n`\n )\n } else {\n const { apiKey } = await prompts({\n type: 'password',\n name: 'apiKey',\n message: `Enter your ${provider === 'openai-compatible' ? '' : provider + ' '}API key:`,\n })\n if (apiKey) config.ai.apiKey = apiKey\n\n if (provider === 'openai-compatible') {\n const { baseUrl } = await prompts({\n type: 'text',\n name: 'baseUrl',\n message: 'Enter the base URL (e.g. https://api.groq.com/openai/v1):',\n })\n if (baseUrl) config.ai.baseUrl = baseUrl\n }\n }\n\n log.plain('')\n log.info(`Validating ${chalk.cyan(provider)} connection…`)\n try {\n const testProvider = getProvider(config)\n await testProvider.validate()\n log.success('API key verified')\n writeConfig(config)\n providerConfigured = true\n } catch (error) {\n log.warn(`Validation failed: ${(error as Error).message}`)\n const { retry } = await prompts({\n type: 'confirm',\n name: 'retry',\n message: 'Save anyway and configure later?',\n initial: false,\n })\n if (retry) {\n writeConfig(config)\n providerConfigured = false\n log.info('Config saved — run workscribe config set ai.apiKey <key> to update')\n } else {\n log.info('API key not saved — run workscribe init again to configure')\n providerConfigured = false\n }\n }\n }\n }\n\n // ── Config file ───────────────────────────────────────────────────────────\n if (!fs.existsSync(CONFIG_PATH)) {\n writeConfig(config)\n }\n\n // ── What to do next ───────────────────────────────────────────────────────\n log.plain('')\n log.plain(chalk.bold(' Setup complete!'))\n log.plain('')\n\n if (shell) {\n log.plain(` Activate capture now:`)\n if (shell.name === 'fish') {\n log.plain(` Restart your terminal`)\n log.plain(` ${chalk.dim(`or run: source ${shell.rcFile}`)}`)\n } else {\n log.plain(` ${chalk.cyan(`source ${shell.rcFile}`)}`)\n log.plain(` Or restart your terminal.`)\n }\n log.plain('')\n }\n\n if (providerConfigured) {\n log.plain(` Then run a few commands and generate your first summary:`)\n log.plain(` ${chalk.cyan('workscribe summary')}`)\n log.plain('')\n log.plain(` Check capture is working:`)\n log.plain(` ${chalk.cyan('workscribe status')}`)\n } else {\n log.plain(` Before generating summaries, configure an AI provider:`)\n log.plain(` ${chalk.cyan('workscribe config set ai.provider anthropic')}`)\n log.plain(` ${chalk.cyan('workscribe config set ai.apiKey <your-key>')}`)\n log.plain('')\n log.plain(` Then run:`)\n log.plain(` ${chalk.cyan('workscribe summary')}`)\n }\n\n log.plain('')\n })\n}\n","export function formatDuration(minutes: number): string {\n if (minutes < 60) return `${Math.round(minutes)}m`\n const h = Math.floor(minutes / 60)\n const m = Math.round(minutes % 60)\n return m > 0 ? `${h}h ${m}m` : `${h}h`\n}\n\nexport function formatDate(isoString: string): string {\n return new Date(isoString).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })\n}\n\nexport function todayDate(): string {\n return localDateStr(new Date())\n}\n\nexport function parseDate(input: string): string {\n // Accepts YYYY-MM-DD, returns YYYY-MM-DD. Throws on invalid.\n const d = new Date(input + 'T00:00:00')\n if (isNaN(d.getTime())) throw new Error(`Invalid date: ${input}`)\n return input\n}\n\nfunction localDateStr(d: Date): string {\n const y = d.getFullYear()\n const m = String(d.getMonth() + 1).padStart(2, '0')\n const day = String(d.getDate()).padStart(2, '0')\n return `${y}-${m}-${day}`\n}\n\n// Returns Monday of the ISO week containing dateStr (YYYY-MM-DD)\nexport function startOfWeek(dateStr: string): string {\n const d = new Date(dateStr + 'T00:00:00')\n const day = d.getDay() // 0=Sun\n const diff = day === 0 ? -6 : 1 - day\n d.setDate(d.getDate() + diff)\n return localDateStr(d)\n}\n\n// Returns all YYYY-MM-DD strings from start to end inclusive\nexport function eachDayOfRange(start: string, end: string): string[] {\n const days: string[] = []\n const cur = new Date(start + 'T00:00:00')\n const last = new Date(end + 'T00:00:00')\n while (cur <= last) {\n days.push(localDateStr(cur))\n cur.setDate(cur.getDate() + 1)\n }\n return days\n}\n\nexport function timeAgo(isoString: string, now = Date.now()): string {\n const elapsedMs = now - new Date(isoString).getTime()\n const minutes = Math.floor(elapsedMs / 60000)\n if (minutes < 2) return 'just now'\n if (minutes < 60) return `${minutes} minutes ago`\n const hours = Math.floor(minutes / 60)\n if (hours < 24) return hours === 1 ? '1 hour ago' : `${hours} hours ago`\n const days = Math.floor(hours / 24)\n if (days === 1) return 'yesterday'\n return `${days} days ago`\n}\n\n// Returns ISO week string YYYY-WW for a date\nexport function isoWeekKey(dateStr: string): string {\n const d = new Date(dateStr + 'T00:00:00')\n const jan4 = new Date(d.getFullYear(), 0, 4)\n const weekNum = Math.ceil(((d.getTime() - jan4.getTime()) / 86400000 + jan4.getDay() + 1) / 7)\n return `${d.getFullYear()}-W${String(weekNum).padStart(2, '0')}`\n}\n","import type { DaySummaryPayload, WeekSummaryPayload } from './types'\nimport { formatDuration } from '../utils/format'\nimport { getActiveProfileAiContexts } from '../profiles/loader'\n\nexport const SYSTEM_PROMPT = `You write short developer work summaries. Focus on what the developer accomplished and what changed — not which tools or commands were used.\n\nHere is an example:\n\nINPUT:\nProject: api-service\nBranch: feature/auth\nDuration: 2h 00m\nEvents:\n - versioning {\"branch\":\"feature/auth\"}\n - 2x dependencies {\"tool\":\"npm\",\"packages\":[\"bcrypt\",\"jsonwebtoken\"]}\n - 8x testing [failed]\n - testing\n - 2x files {\"tool\":\"mkdir\"}\n - shipping {\"message\":\"fix: auth token validation\"}\n - shipping {\"remote\":\"origin\",\"branch\":\"feature/auth\"}\n\nOUTPUT:\n- Added authentication dependencies (bcrypt, JWT)\n- Debugged and resolved failing auth tests\n- Committed and pushed the token validation fix\n\nRULES — follow these exactly:\n\n1. Interpret repeated events as patterns, not individual steps.\n - Many testing [failed] followed by a passing test = debugging a failure. Say \"resolved failing X tests\", not \"ran tests multiple times\".\n - Many versioning events = branch housekeeping. Fold into context, do not list each git command.\n\n2. Omit utility commands entirely. File size checks, file reads, grep searches, and cat commands are research steps — they are not outcomes and must not appear in the summary.\n\n3. Do not name the AI tool. For ai_session events: focus on what was built or committed. If a commits array is present in metadata, use those commit messages. Never write \"via Claude Code\", \"using Claude Code\", or similar — omit the tool name entirely.\n\n4. For other events with a hint field: describe the developer's intent, not the raw command.\n\n5. For dependencies events: infer the purpose from package names and describe the domain (bcrypt/jsonwebtoken → authentication, prisma/pg → database, jest/vitest → testing). For unfamiliar packages, name them directly.\n\n6. Fold supporting events into the narrative. Building, shipping, versioning, and file operations are context — only make them a bullet when they are the primary activity (e.g. a standalone build fix or deploy with no accompanying commits).\n\n7. Stick to what the events show. Do not infer subject matter from the branch name. Do not add details not derivable from the events.\n\n8. For code_edit events: these represent file saves from an IDE integration. Describe what was being built based on repository context (branch name, commit messages). Never list individual filenames.\n\nMaximum 5 bullets. Output ONLY the bullet points, nothing else.`\n\nexport function getSystemPrompt(): string {\n const contexts = getActiveProfileAiContexts()\n if (contexts.length === 0) return SYSTEM_PROMPT\n return SYSTEM_PROMPT + '\\n\\n' + contexts.join('\\n')\n}\n\n// Categories excluded from the AI payload by default:\n// - exploring/note: handled separately (notes rendered before event list; exploring is raw file reads)\n// - linting: lint/format runs are support noise, not meaningful work outcomes\n// `other` is intentionally kept — hints give the AI context for commands that don't fit known patterns\n// (e.g. docker compose up, make deploy, terraform apply). The prompt instructs the model to omit\n// utility commands (wc, head) within that category.\nexport const DEFAULT_EXCLUDED_CATEGORIES = new Set(['exploring', 'note', 'linting'])\n\nexport function buildExcludedSet(includeCategories: string[] = []): Set<string> {\n const excluded = new Set(DEFAULT_EXCLUDED_CATEGORIES)\n for (const cat of includeCategories) excluded.delete(cat)\n return excluded\n}\n\nexport function countExcludedEvents(\n sessions: DaySummaryPayload['sessions'],\n excluded: Set<string>\n): Map<string, number> {\n const counts = new Map<string, number>()\n for (const session of sessions) {\n for (const event of session.events) {\n if (excluded.has(event.category)) {\n counts.set(event.category, (counts.get(event.category) ?? 0) + 1)\n }\n }\n }\n return counts\n}\n\nexport function buildUserMessage(payload: DaySummaryPayload, includeCategories: string[] = []): string {\n const excluded = buildExcludedSet(includeCategories)\n const lines: string[] = [`Date: ${payload.date}`, '']\n\n for (const session of payload.sessions) {\n lines.push(`Project: ${session.project ?? 'unknown'}`)\n if (session.branch) lines.push(`Branch: ${session.branch}`)\n lines.push(`Duration: ${formatDuration(session.durationMinutes)}`)\n\n for (const event of session.events) {\n if (event.category === 'note') {\n lines.push(`NOTE: ${event.metadata.text as string}`)\n }\n }\n\n lines.push('Events:')\n\n // Aggregate repeated events so the model sees \"3x build\" not 3 separate build lines\n const counts = new Map<string, number>()\n for (const event of session.events) {\n if (excluded.has(event.category)) continue\n const failed = event.exitCode !== null && event.exitCode !== 0 ? ' [failed]' : ''\n let key: string\n if (event.category === 'code_edit') {\n // Strip file paths — AI should describe intent from context, not enumerate files\n key = `code_edit${failed}`\n } else if (event.hint) {\n key = `other [${event.hint}]${failed}`\n } else {\n const meta = Object.keys(event.metadata).length > 0 ? ` ${JSON.stringify(event.metadata)}` : ''\n key = `${event.category}${meta}${failed}`\n }\n counts.set(key, (counts.get(key) ?? 0) + 1)\n }\n\n for (const [key, count] of counts) {\n lines.push(` - ${count > 1 ? `${count}x ` : ''}${key}`)\n }\n\n lines.push('')\n }\n\n return lines.join('\\n')\n}\n\nexport const WEEKLY_SYSTEM_PROMPT = `You write short weekly developer summaries. Here is an example:\n\nINPUT:\nWeek: 2026-05-18 to 2026-05-22\n\nMonday 2026-05-18:\n Project: api-service (feature/auth) — 2h 10m\n Events: 3x code_commit, 2x test_run, dependency_install\n\nTuesday 2026-05-19:\n Project: api-service (feature/auth) — 1h 30m\n Events: 2x code_commit, test_run, build\n\nWednesday 2026-05-20:\n Project: dashboard (main) — 3h 00m\n Events: 4x code_commit, 2x build, test_run\n\nThursday 2026-05-21:\n Project: api-service (feature/auth) — 1h 00m\n Events: code_commit {\"message\":\"feat: merge auth\"}, branch_switch\n\nFriday 2026-05-22:\n Project: dashboard (main) — 2h 00m\n Events: 3x code_commit, build\n\nOUTPUT:\n## Week of 18 May — 9h 40m across 2 projects\n\n**api-service** (Mon–Thu): Built and shipped the auth feature — JWT setup, token validation fixes, and final merge.\n**dashboard** (Wed, Fri): Active development across 7 commits with builds passing.\n\nNow summarise the following week. Output ONLY the summary — a one-line header then one bullet per active project. Maximum 4 bullets.`\n\nconst DAY_NAMES = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']\n\nexport function buildWeeklyMessage(payload: WeekSummaryPayload): string {\n const lines: string[] = [`Week: ${payload.weekStart} to ${payload.weekEnd}`, '']\n\n for (const { date, sessions } of payload.days) {\n const dayName = DAY_NAMES[new Date(date + 'T00:00:00').getDay()]\n lines.push(`${dayName} ${date}:`)\n\n for (const session of sessions) {\n const project = session.project ?? 'unknown'\n const branch = session.branch ? ` (${session.branch})` : ''\n lines.push(` Project: ${project}${branch} — ${formatDuration(session.durationMinutes)}`)\n\n for (const event of session.events) {\n if (event.category === 'note') {\n lines.push(` NOTE: ${event.metadata.text as string}`)\n }\n }\n\n const excluded = buildExcludedSet()\n const counts = new Map<string, number>()\n for (const event of session.events) {\n if (excluded.has(event.category)) continue\n const failed = event.exitCode !== null && event.exitCode !== 0 ? ' [failed]' : ''\n let key: string\n if (event.category === 'code_edit') {\n key = `code_edit${failed}`\n } else if (event.hint) {\n key = `other [${event.hint}]${failed}`\n } else {\n const meta = Object.keys(event.metadata).length > 0 ? ` ${JSON.stringify(event.metadata)}` : ''\n key = `${event.category}${meta}${failed}`\n }\n counts.set(key, (counts.get(key) ?? 0) + 1)\n }\n const eventLine = [...counts.entries()].map(([key, count]) => `${count > 1 ? `${count}x ` : ''}${key}`).join(', ')\n lines.push(` Events: ${eventLine}`)\n }\n\n lines.push('')\n }\n\n return lines.join('\\n')\n}\n","import type { AIProvider, DaySummaryPayload, WeekSummaryPayload } from './types'\nimport { getSystemPrompt, buildUserMessage, WEEKLY_SYSTEM_PROMPT, buildWeeklyMessage } from './prompt'\nimport { fetchWithTimeout } from '../utils/fetch'\nimport type { ProviderConfig } from './provider-config'\n\nexport class GenericProvider implements AIProvider {\n constructor(\n private config: ProviderConfig,\n private model: string,\n private apiKey: string,\n private baseUrl: string,\n private includeCategories: string[] = []\n ) {}\n\n private async call(system: string, userMsg: string, maxTokens: number): Promise<string> {\n const response = await fetchWithTimeout(this.config.chatUrl(this.baseUrl, this.apiKey, this.model), {\n method: 'POST',\n headers: this.config.headers(this.apiKey),\n body: JSON.stringify(this.config.buildChatBody(this.model, system, userMsg, maxTokens)),\n })\n if (!response.ok) {\n throw new Error(this.config.chatError(response.status, await response.text()))\n }\n return this.config.parseText(await response.json())\n }\n\n async summarize(payload: DaySummaryPayload): Promise<string> {\n return this.call(getSystemPrompt(), buildUserMessage(payload, this.includeCategories), this.config.dailyTokens)\n }\n\n async summarizeWeek(payload: WeekSummaryPayload): Promise<string> {\n return this.call(WEEKLY_SYSTEM_PROMPT, buildWeeklyMessage(payload), this.config.weeklyTokens)\n }\n\n async validate(): Promise<void> {\n const isPost = this.config.validateMethod === 'POST'\n const response = await fetchWithTimeout(this.config.validateUrl(this.baseUrl, this.apiKey, this.model), {\n method: this.config.validateMethod,\n headers: isPost ? this.config.headers(this.apiKey) : undefined,\n body:\n isPost && this.config.buildValidateBody ? JSON.stringify(this.config.buildValidateBody(this.model)) : undefined,\n })\n if (!response.ok) {\n throw new Error(this.config.validateError(response.status, await response.text(), this.baseUrl))\n }\n }\n}\n","export interface ProviderConfig {\n defaultModel: string\n defaultBaseUrl: string\n dailyTokens: number\n weeklyTokens: number\n // apiKey and model are provided for providers that embed them in the URL (e.g. Gemini)\n chatUrl: (baseUrl: string, apiKey: string, model: string) => string\n validateUrl: (baseUrl: string, apiKey: string, model: string) => string\n validateMethod: 'GET' | 'POST'\n headers: (apiKey: string) => Record<string, string>\n buildChatBody: (model: string, system: string, userMsg: string, maxTokens: number) => object\n buildValidateBody?: (model: string) => object\n parseText: (json: unknown) => string\n chatError: (status: number, body: string) => string\n validateError: (status: number, body: string, baseUrl: string) => string\n}\n\nexport const PROVIDER_CONFIGS: Record<string, ProviderConfig> = {\n anthropic: {\n defaultModel: 'claude-haiku-4-5-20251001',\n defaultBaseUrl: 'https://api.anthropic.com/v1',\n dailyTokens: 1024,\n weeklyTokens: 1024,\n chatUrl: (baseUrl) => `${baseUrl}/messages`,\n validateUrl: (baseUrl) => `${baseUrl}/messages`,\n validateMethod: 'POST',\n headers: (apiKey) => ({\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n 'anthropic-version': '2023-06-01',\n }),\n buildChatBody: (model, system, userMsg, maxTokens) => ({\n model,\n max_tokens: maxTokens,\n system,\n messages: [{ role: 'user', content: userMsg }],\n }),\n buildValidateBody: (model) => ({\n model,\n max_tokens: 1,\n messages: [{ role: 'user', content: '.' }],\n }),\n parseText: (json) => {\n const data = json as { content: Array<{ type: string; text: string }> }\n return data.content.find((b) => b.type === 'text')?.text ?? ''\n },\n chatError: (status, body) => `Anthropic API error ${status}: ${body}`,\n validateError: (status, body) => `Anthropic API error ${status}: ${body}`,\n },\n\n openai: {\n defaultModel: 'gpt-4o-mini',\n defaultBaseUrl: 'https://api.openai.com/v1',\n dailyTokens: 1024,\n weeklyTokens: 1024,\n chatUrl: (baseUrl) => `${baseUrl}/chat/completions`,\n validateUrl: (baseUrl) => `${baseUrl}/chat/completions`,\n validateMethod: 'POST',\n headers: (apiKey) => ({\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n }),\n buildChatBody: (model, system, userMsg, maxTokens) => ({\n model,\n messages: [\n { role: 'system', content: system },\n { role: 'user', content: userMsg },\n ],\n max_tokens: maxTokens,\n }),\n buildValidateBody: (model) => ({\n model,\n messages: [{ role: 'user', content: '.' }],\n max_tokens: 1,\n }),\n parseText: (json) => {\n const data = json as { choices: Array<{ message: { content: string } }> }\n return data.choices[0]?.message?.content ?? ''\n },\n chatError: (status, body) => `OpenAI API error ${status}: ${body}`,\n validateError: (status, body) => `OpenAI API error ${status}: ${body}`,\n },\n\n ollama: {\n defaultModel: 'llama3',\n defaultBaseUrl: 'http://localhost:11434',\n dailyTokens: 300,\n weeklyTokens: 400,\n chatUrl: (baseUrl) => `${baseUrl}/api/chat`,\n validateUrl: (baseUrl) => `${baseUrl}/api/tags`,\n validateMethod: 'GET',\n headers: () => ({ 'Content-Type': 'application/json' }),\n buildChatBody: (model, system, userMsg, maxTokens) => ({\n model,\n stream: false,\n messages: [\n { role: 'system', content: system },\n { role: 'user', content: userMsg },\n ],\n options: { num_predict: maxTokens, temperature: 0.3 },\n }),\n parseText: (json) => {\n return (json as { message: { content: string } }).message?.content ?? ''\n },\n chatError: (status, body) => `Ollama error ${status}: ${body}. Is Ollama running? Try: ollama serve`,\n validateError: (_status, _body, baseUrl) =>\n `Ollama is not reachable at ${baseUrl}. Is it running? Try: ollama serve`,\n },\n\n gemini: {\n defaultModel: 'gemini-2.0-flash-lite',\n defaultBaseUrl: 'https://generativelanguage.googleapis.com/v1beta',\n dailyTokens: 1024,\n weeklyTokens: 1024,\n // API key and model are embedded in the URL — not in headers\n chatUrl: (baseUrl, apiKey, model) => `${baseUrl}/models/${model}:generateContent?key=${apiKey}`,\n validateUrl: (baseUrl, apiKey, model) => `${baseUrl}/models/${model}:generateContent?key=${apiKey}`,\n validateMethod: 'POST',\n headers: () => ({ 'Content-Type': 'application/json' }),\n buildChatBody: (_model, system, userMsg, maxTokens) => ({\n system_instruction: { parts: [{ text: system }] },\n contents: [{ role: 'user', parts: [{ text: userMsg }] }],\n generationConfig: { maxOutputTokens: maxTokens, temperature: 0.3 },\n }),\n buildValidateBody: () => ({\n contents: [{ role: 'user', parts: [{ text: '.' }] }],\n generationConfig: { maxOutputTokens: 1 },\n }),\n parseText: (json) => {\n const data = json as { candidates: Array<{ content: { parts: Array<{ text: string }> } }> }\n return data.candidates?.[0]?.content?.parts?.[0]?.text ?? ''\n },\n chatError: (status, body) => `Gemini API error ${status}: ${body}`,\n validateError: (status, body) => `Gemini API error ${status}: ${body}`,\n },\n\n groq: {\n defaultModel: 'llama-3.1-8b-instant',\n defaultBaseUrl: 'https://api.groq.com/openai/v1',\n dailyTokens: 1024,\n weeklyTokens: 1024,\n chatUrl: (baseUrl) => `${baseUrl}/chat/completions`,\n validateUrl: (baseUrl) => `${baseUrl}/models`,\n validateMethod: 'GET',\n headers: (apiKey) => ({\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n }),\n buildChatBody: (model, system, userMsg, maxTokens) => ({\n model,\n messages: [\n { role: 'system', content: system },\n { role: 'user', content: userMsg },\n ],\n max_tokens: maxTokens,\n }),\n parseText: (json) => {\n const data = json as { choices: Array<{ message: { content: string } }> }\n return data.choices?.[0]?.message?.content ?? ''\n },\n chatError: (status, body) => `Groq API error ${status}: ${body}`,\n validateError: (status, body) => `Groq API error ${status}: ${body}`,\n },\n}\n","import type { AIProvider } from './types'\nimport type { WorkscribeConfig } from '../config'\nimport { GenericProvider } from './generic-provider'\nimport { PROVIDER_CONFIGS } from './provider-config'\n\nexport function getProvider(config: WorkscribeConfig): AIProvider {\n const { provider, apiKey = '', model, baseUrl } = config.ai\n\n if (!provider) {\n throw new Error(\n 'No AI provider configured.\\nRun: workscribe config set ai.provider <anthropic|openai|gemini|groq|ollama|openai-compatible>'\n )\n }\n\n const configKey = provider === 'openai-compatible' ? 'openai' : provider\n const providerConfig = PROVIDER_CONFIGS[configKey]\n\n if (!providerConfig) {\n throw new Error(\n `Unknown provider: \"${provider}\"\\nSupported providers: anthropic, openai, gemini, groq, ollama, openai-compatible`\n )\n }\n\n if (provider !== 'ollama' && !apiKey) {\n throw new Error(`${provider} requires an API key.\\nRun: workscribe config set ai.apiKey <your-key>`)\n }\n\n if (provider === 'openai-compatible' && !baseUrl) {\n throw new Error('openai-compatible requires a base URL.\\nRun: workscribe config set ai.baseUrl <url>')\n }\n\n return new GenericProvider(\n providerConfig,\n model || providerConfig.defaultModel,\n apiKey,\n baseUrl || providerConfig.defaultBaseUrl,\n config.summary?.includeCategories ?? []\n )\n}\n","import fs from 'fs'\nimport path from 'path'\nimport os from 'os'\nimport { execFileSync } from 'child_process'\nimport { log } from '../utils/logger'\nimport { CompletionCommand, bashCompletion, zshCompletion, fishCompletion } from '../utils/completion-scripts'\nimport { WORKSCRIBE_DIR } from '../utils/paths'\n\nconst FISH_COMPLETIONS_DIR = path.join(os.homedir(), '.config', 'fish', 'completions')\n\nconst HOOK_START = '# workscribe:hook:start'\nconst HOOK_END = '# workscribe:hook:end'\nconst HOOK_PREAMBLE = '# Workscribe — developer work journal'\n\nexport function getInstalledHookBlock(rcFile: string): string | null {\n if (!fs.existsSync(rcFile)) return null\n const content = fs.readFileSync(rcFile, 'utf-8')\n const startIdx = content.indexOf(HOOK_START)\n const endIdx = content.indexOf(HOOK_END)\n if (startIdx === -1 || endIdx === -1) return null\n return content.slice(startIdx, endIdx + HOOK_END.length)\n}\n\nexport function isHookInstalled(rcFile: string): boolean {\n return getInstalledHookBlock(rcFile) !== null\n}\n\nexport function isHookOutdated(rcFile: string, hookContent: string): boolean {\n const installed = getInstalledHookBlock(rcFile)\n if (!installed) return false\n return installed.trim() !== hookContent.trim()\n}\n\nexport function installHook(rcFile: string, hookContent: string): void {\n const backup = `${rcFile}.workscribe-backup-${Date.now()}`\n fs.copyFileSync(rcFile, backup)\n log.info(`Backed up ${rcFile} → ${path.basename(backup)}`)\n fs.appendFileSync(rcFile, `\\n${hookContent}\\n`)\n}\n\nexport function updateHook(rcFile: string, hookContent: string): void {\n const backup = `${rcFile}.workscribe-backup-${Date.now()}`\n fs.copyFileSync(rcFile, backup)\n log.info(`Backed up ${rcFile} → ${path.basename(backup)}`)\n const content = fs.readFileSync(rcFile, 'utf-8')\n const startIdx = content.indexOf(HOOK_START)\n const endIdx = content.indexOf(HOOK_END) + HOOK_END.length\n fs.writeFileSync(rcFile, content.slice(0, startIdx) + hookContent + content.slice(endIdx))\n}\n\nexport function removeHook(rcFile: string): void {\n const backup = `${rcFile}.workscribe-backup-${Date.now()}`\n fs.copyFileSync(rcFile, backup)\n log.info(`Backed up ${rcFile} → ${path.basename(backup)}`)\n const content = fs.readFileSync(rcFile, 'utf-8')\n const startIdx = content.indexOf(HOOK_START)\n const endIdx = content.indexOf(HOOK_END) + HOOK_END.length\n // Also remove the preamble comment lines that installHook writes before HOOK_START\n const preambleIdx = content.lastIndexOf(HOOK_PREAMBLE, startIdx)\n const blockStart = preambleIdx !== -1 ? preambleIdx : startIdx\n const before = content.slice(0, blockStart).replace(/\\n+$/, '\\n')\n const after = content.slice(endIdx).replace(/^\\n/, '')\n fs.writeFileSync(rcFile, before + after)\n}\n\nexport function resolveWorkscribeBinary(): string | null {\n try {\n const resolved = execFileSync('which', ['workscribe'], { encoding: 'utf-8' }).trim()\n return resolved || null\n } catch {\n return null\n }\n}\n\nexport function injectBinaryPath(hookContent: string, binaryPath: string): string {\n return hookContent\n .replace('command -v workscribe > /dev/null 2>&1 || return 0', `[[ -x \"${binaryPath}\" ]] || return 0`)\n .replace('command -v workscribe &>/dev/null || return 0', `[[ -x \"${binaryPath}\" ]] || return 0`)\n .replace('type -q workscribe\\n or return 0', `test -x \"${binaryPath}\"\\n or return 0`)\n .replaceAll('command workscribe _capture', `\"${binaryPath}\" _capture`)\n .replaceAll('command workscribe alerts', `\"${binaryPath}\" alerts`)\n}\n\nexport function isCompletionsInstalled(shell: { name: string; rcFile: string }): boolean {\n if (shell.name === 'fish') {\n return fs.existsSync(path.join(FISH_COMPLETIONS_DIR, 'workscribe.fish'))\n }\n try {\n return fs.readFileSync(shell.rcFile, 'utf-8').includes('workscribe completions')\n } catch {\n return false\n }\n}\n\nexport function installCompletions(shell: { name: string; rcFile: string }, commands: CompletionCommand[]): void {\n if (shell.name === 'fish') {\n if (!fs.existsSync(FISH_COMPLETIONS_DIR)) {\n fs.mkdirSync(FISH_COMPLETIONS_DIR, { recursive: true })\n }\n fs.writeFileSync(path.join(FISH_COMPLETIONS_DIR, 'workscribe.fish'), fishCompletion(commands), { mode: 0o644 })\n } else {\n const script = shell.name === 'zsh' ? zshCompletion(commands) : bashCompletion(commands)\n const cacheFile = path.join(WORKSCRIBE_DIR, `completion.${shell.name}`)\n fs.writeFileSync(cacheFile, script, { mode: 0o644 })\n const sourceLine =\n shell.name === 'zsh'\n ? `\\n# Workscribe completions\\nautoload -Uz compinit && compinit\\nsource \"${cacheFile}\"\\n`\n : `\\n# Workscribe completions\\nsource \"${cacheFile}\"\\n`\n fs.appendFileSync(shell.rcFile, sourceLine)\n }\n}\n","export interface CompletionCommand {\n name: string\n description: string\n}\n\nexport function bashCompletion(commands: CompletionCommand[]): string {\n const names = commands.map((command) => command.name).join(' ')\n return `\\\n_workscribe_completion() {\n local cur=\"\\${COMP_WORDS[COMP_CWORD]}\"\n local prev=\"\\${COMP_WORDS[COMP_CWORD-1]}\"\n local commands=\"${names}\"\n case \"$prev\" in\n completions) COMPREPLY=( $(compgen -W \"bash zsh fish\" -- \"$cur\") ); return ;;\n config) COMPREPLY=( $(compgen -W \"get set list\" -- \"$cur\") ); return ;;\n profile) COMPREPLY=( $(compgen -W \"list add remove update detect suggest\" -- \"$cur\") ); return ;;\n esac\n COMPREPLY=( $(compgen -W \"$commands\" -- \"$cur\") )\n}\ncomplete -F _workscribe_completion workscribe`\n}\n\nexport function zshCompletion(commands: CompletionCommand[]): string {\n const commandList = commands.map((command) => ` '${command.name}:${command.description}'`).join('\\n')\n return `\\\n#compdef workscribe\n_workscribe() {\n local state\n _arguments '1: :->command' '*: :->args'\n case $state in\n command)\n local -a commands\n commands=(\n${commandList}\n )\n _describe 'command' commands\n ;;\n args)\n case $words[2] in\n completions) local -a shells; shells=('bash' 'zsh' 'fish'); _describe 'shell' shells ;;\n config) local -a sub; sub=('get:Get a value' 'set:Set a value' 'list:List all values'); _describe 'subcommand' sub ;;\n profile) local -a sub; sub=('list' 'add' 'remove' 'update' 'detect' 'suggest'); _describe 'subcommand' sub ;;\n esac\n ;;\n esac\n}\n_workscribe`\n}\n\nexport function fishCompletion(commands: CompletionCommand[]): string {\n const lines = [\n 'complete -c workscribe -f',\n ...commands.map(\n (command) =>\n `complete -c workscribe -n \"__fish_use_subcommand\" -a ${command.name.padEnd(12)} -d \"${command.description}\"`\n ),\n 'complete -c workscribe -n \"__fish_seen_subcommand_from completions\" -a \"bash zsh fish\"',\n 'complete -c workscribe -n \"__fish_seen_subcommand_from config\" -a \"get set list\"',\n 'complete -c workscribe -n \"__fish_seen_subcommand_from profile\" -a \"list add remove update detect suggest\"',\n ]\n return lines.join('\\n')\n}\n","import fs from 'fs'\nimport path from 'path'\nimport os from 'os'\nimport type { AIHookIntegration } from './types'\nimport { isCommandInstalled } from './utils'\n\nconst CLAUDE_SETTINGS_PATH = path.join(os.homedir(), '.claude', 'settings.json')\n\nfunction readSettings(): Record<string, unknown> {\n if (!fs.existsSync(CLAUDE_SETTINGS_PATH)) return {}\n try {\n return JSON.parse(fs.readFileSync(CLAUDE_SETTINGS_PATH, 'utf-8')) as Record<string, unknown>\n } catch {\n return {}\n }\n}\n\nexport const claudeCodeIntegration: AIHookIntegration = {\n displayName: 'Claude Code',\n\n isInstalled() {\n return isCommandInstalled('claude')\n },\n\n isHookInstalled() {\n const settings = readSettings()\n const hooks = (settings.hooks ?? {}) as Record<string, unknown>\n const postToolUse = (hooks.PostToolUse ?? []) as unknown[]\n const hasPostToolUse = postToolUse.some((entry) => {\n const entryHooks = ((entry as Record<string, unknown>).hooks ?? []) as unknown[]\n return entryHooks.some((hookItem) => {\n const hook = hookItem as Record<string, unknown>\n return typeof hook.command === 'string' && hook.command.includes('workscribe _hook')\n })\n })\n const userPromptSubmit = (hooks.UserPromptSubmit ?? []) as unknown[]\n const hasUserPromptSubmit = userPromptSubmit.some((entry) => {\n const entryHooks = ((entry as Record<string, unknown>).hooks ?? []) as unknown[]\n return entryHooks.some((hookItem) => {\n const hook = hookItem as Record<string, unknown>\n return typeof hook.command === 'string' && hook.command.includes('workscribe _hook')\n })\n })\n return hasPostToolUse && hasUserPromptSubmit\n },\n\n install() {\n const settings = readSettings()\n const existingHooks = (settings.hooks ?? {}) as Record<string, unknown>\n const existingPostToolUse = (existingHooks.PostToolUse ?? []) as unknown[]\n const existingUserPromptSubmit = (existingHooks.UserPromptSubmit ?? []) as unknown[]\n settings.hooks = {\n ...existingHooks,\n PostToolUse: [\n ...existingPostToolUse,\n {\n matcher: 'Bash',\n hooks: [{ type: 'command', command: 'workscribe _hook --source claude-code', async: true }],\n },\n ],\n UserPromptSubmit: [\n ...existingUserPromptSubmit,\n {\n hooks: [\n {\n type: 'command',\n command: 'workscribe _hook --source claude-code --event UserPromptSubmit',\n },\n ],\n },\n ],\n }\n fs.mkdirSync(path.dirname(CLAUDE_SETTINGS_PATH), { recursive: true })\n fs.writeFileSync(CLAUDE_SETTINGS_PATH, JSON.stringify(settings, null, 2))\n },\n}\n","import { execSync } from 'child_process'\n\n/** Returns true if the given CLI command is available on PATH */\nexport function isCommandInstalled(cmd: string): boolean {\n try {\n execSync(`which ${cmd}`, { stdio: 'ignore' })\n return true\n } catch {\n return false\n }\n}\n","import type { AIHookIntegration } from './types'\nimport { claudeCodeIntegration } from './claude-code'\n\n/**\n * Registry of AI tool hook integrations, keyed by the \"hook\" field in src/config/ai-tools.json.\n * Adding support for a new tool = add a new entry here and a corresponding integration file.\n */\nexport const AI_HOOK_INTEGRATIONS: Record<string, AIHookIntegration> = {\n 'claude-code': claudeCodeIntegration,\n}\n","import { Command } from 'commander'\nimport { log } from '../utils/logger'\nimport { CompletionCommand, bashCompletion, zshCompletion, fishCompletion } from '../utils/completion-scripts'\n\nexport type { CompletionCommand }\nexport { bashCompletion, zshCompletion, fishCompletion }\n\nconst HIDDEN_COMMANDS = new Set(['_capture', '_hook'])\n\nexport function getPublicCommands(program: Command): CompletionCommand[] {\n return program.commands\n .filter((command) => !HIDDEN_COMMANDS.has(command.name()))\n .map((command) => ({ name: command.name(), description: command.description() }))\n}\n\nexport function registerCompletions(program: Command): void {\n program\n .command('completions [shell]')\n .description('Print shell completion script (bash, zsh, fish)')\n .action((shell?: string) => {\n const detected = shell ?? (process.env.SHELL ?? '').split('/').at(-1)\n\n if (!detected || !['bash', 'zsh', 'fish'].includes(detected)) {\n log.error(`Unknown shell: \"${detected ?? ''}\". Supported: bash, zsh, fish`)\n log.plain(` Usage: workscribe completions <bash|zsh|fish>`)\n process.exit(1)\n }\n\n const commands = getPublicCommands(program)\n const script =\n detected === 'bash'\n ? bashCompletion(commands)\n : detected === 'zsh'\n ? zshCompletion(commands)\n : fishCompletion(commands)\n\n process.stdout.write(script + '\\n')\n })\n}\n","import { Command } from 'commander'\nimport fs from 'fs'\nimport chalk from 'chalk'\nimport { getEventCount, getLastEvent, getRecentOtherRate } from '../db'\nimport { readConfig } from '../config'\nimport { log } from '../utils/logger'\nimport { formatDate, todayDate } from '../utils/format'\nimport { getEventsForDate } from '../db'\nimport { PAUSE_FLAG_PATH } from '../utils/paths'\nimport { getPendingAlerts } from '../db/alerts'\n\nexport function registerStatus(program: Command): void {\n program\n .command('status')\n .description('Show capture status and event counts')\n .action(() => {\n const config = readConfig()\n const total = getEventCount()\n const todayEvents = getEventsForDate(todayDate())\n const last = getLastEvent()\n const isPaused = fs.existsSync(PAUSE_FLAG_PATH)\n\n log.plain('')\n log.plain(chalk.bold(' Workscribe Status'))\n log.plain('')\n\n if (isPaused) {\n log.plain(` Capture ${chalk.yellow('paused')} ${chalk.dim('(run: workscribe resume)')}`)\n } else {\n log.plain(` Capture ${chalk.green('active')}`)\n }\n\n log.plain(` Events today ${chalk.cyan(String(todayEvents.length))}`)\n log.plain(` Events total ${chalk.cyan(String(total))}`)\n\n if (last) {\n log.plain(` Last event ${formatDate(last.captured_at)} ${chalk.dim(last.command.slice(0, 60))}`)\n }\n\n log.plain('')\n log.plain(\n ` AI provider ${config.ai.provider ? chalk.cyan(config.ai.provider) : chalk.yellow('not configured')}`\n )\n if (config.ai.model) log.plain(` Model ${chalk.dim(config.ai.model)}`)\n\n const activeProfiles = config.capture.profiles\n log.plain(\n ` Profiles ${activeProfiles.length > 0 ? chalk.cyan(activeProfiles.join(', ')) : chalk.dim('none')}`\n )\n\n const pendingAlerts = getPendingAlerts()\n if (pendingAlerts.length > 0) {\n log.plain('')\n log.plain(\n ` ${chalk.yellow('!')} ${chalk.yellow(String(pendingAlerts.length))} pending security alert${pendingAlerts.length === 1 ? '' : 's'}` +\n chalk.dim(' (run: workscribe alerts)')\n )\n }\n\n const { total: weekTotal, otherCount } = getRecentOtherRate(7)\n if (weekTotal > 0) {\n const otherPct = Math.round((otherCount / weekTotal) * 100)\n if (otherPct >= 25) {\n log.plain('')\n log.plain(\n ` ${chalk.yellow('⚠')} ${otherCount} of ${weekTotal} events (${otherPct}%) are uncategorised this week.`\n )\n log.plain(\n chalk.dim(\n ' Run workscribe profile detect — scan current directory for matching profiles\\n' +\n ' Run workscribe profile suggest — analyse your command history'\n )\n )\n }\n }\n\n log.plain('')\n })\n}\n","import { Command } from 'commander'\nimport chalk from 'chalk'\nimport { getEventsForDate } from '../db'\nimport { log } from '../utils/logger'\nimport { todayDate, parseDate, formatDate } from '../utils/format'\nimport { loadAIToolRegistry } from '../config/registry'\n\nconst CATEGORY_COLORS: Record<string, (s: string) => string> = {\n shipping: chalk.green,\n versioning: chalk.blue,\n building: chalk.cyan,\n running: chalk.white,\n testing: chalk.magenta,\n linting: chalk.yellow,\n dependencies: chalk.yellow,\n infrastructure: chalk.red,\n releasing: chalk.bold.green,\n database: chalk.bold.blue,\n files: chalk.dim.yellow,\n exploring: chalk.dim.cyan,\n ai_session: chalk.bold.magenta,\n other: chalk.gray,\n}\n\nconst AI_TOOL_DISPLAY_NAMES: Record<string, string> = Object.fromEntries(\n loadAIToolRegistry().map((entry) => [entry.tool, entry.displayName])\n)\n\nexport function registerEvents(program: Command): void {\n program\n .command('events')\n .description('List captured events')\n .option('--date <YYYY-MM-DD>', 'date to list events for (default: today)')\n .option('--limit <n>', 'max events to show', parseInt)\n .action((opts) => {\n let date = todayDate()\n if (opts.date) {\n try {\n date = parseDate(opts.date)\n } catch (e) {\n log.error((e as Error).message)\n process.exit(1)\n }\n }\n\n const events = getEventsForDate(date)\n const limit = opts.limit ?? events.length\n\n if (events.length === 0) {\n log.plain(`No events captured for ${date}`)\n return\n }\n\n log.plain('')\n log.plain(chalk.bold(` Events for ${date} (${events.length} total)`))\n log.plain('')\n\n for (const event of events.slice(0, limit)) {\n const colorFn = CATEGORY_COLORS[event.category] ?? chalk.gray\n const time = formatDate(event.captured_at)\n const category = colorFn(event.category.padEnd(20))\n const repo = event.repo_name ? chalk.dim(` [${event.repo_name}]`) : ''\n const exitBadge = event.exit_code && event.exit_code !== 0 ? chalk.red(` ✗${event.exit_code}`) : ''\n\n let cmdDisplay: string\n if (event.category === 'ai_session') {\n let meta: Record<string, unknown> = {}\n try {\n meta = event.metadata ? (JSON.parse(event.metadata) as Record<string, unknown>) : {}\n } catch {\n /* ignore */\n }\n const toolKey = typeof meta.tool === 'string' ? meta.tool : ''\n const toolName = AI_TOOL_DISPLAY_NAMES[toolKey] ?? toolKey\n cmdDisplay = chalk.white(toolName.padEnd(20)) + chalk.magenta(' ✦')\n } else {\n cmdDisplay = chalk.dim(event.command.slice(0, 55))\n }\n\n log.plain(` ${chalk.dim(time)} ${category} ${cmdDisplay}${repo}${exitBadge}`)\n }\n\n if (limit < events.length) {\n log.plain('')\n log.plain(chalk.dim(` … and ${events.length - limit} more (remove --limit to see all)`))\n }\n\n log.plain('')\n })\n}\n","import { Command } from 'commander'\nimport chalk from 'chalk'\nimport { getOrBuildSessions } from '../sessions/detector'\nimport { log } from '../utils/logger'\nimport { todayDate, parseDate, formatDate, formatDuration } from '../utils/format'\n\nexport function registerSessions(program: Command): void {\n program\n .command('sessions')\n .description('List detected work sessions')\n .option('--date <YYYY-MM-DD>', 'date to show sessions for (default: today)')\n .action((opts) => {\n let date = todayDate()\n if (opts.date) {\n try {\n date = parseDate(opts.date)\n } catch (error) {\n log.error((error as Error).message)\n process.exit(1)\n }\n }\n\n const sessions = getOrBuildSessions(date)\n\n if (sessions.length === 0) {\n log.plain(`No sessions detected for ${date}`)\n return\n }\n\n log.plain('')\n log.plain(chalk.bold(` Sessions for ${date} (${sessions.length} session${sessions.length > 1 ? 's' : ''})`))\n log.plain('')\n\n for (const session of sessions) {\n const start = formatDate(session.startedAt)\n const end = formatDate(session.endedAt)\n const duration = formatDuration(session.durationMinutes)\n const repo = session.repoName ? chalk.cyan(session.repoName) : chalk.gray('no repo')\n log.plain(\n ` ${chalk.dim(start)} – ${chalk.dim(end)} ${repo} ${chalk.dim(duration)} ${chalk.dim(session.eventCount + ' events')}`\n )\n\n for (const event of session.events) {\n if (event.category === 'note') {\n let text = ''\n try {\n text = (JSON.parse(event.metadata ?? '{}') as { text?: string }).text ?? ''\n } catch {\n /* ignore malformed metadata */\n }\n if (text) log.plain(` ${chalk.yellow('note')} ${chalk.dim(text)}`)\n }\n }\n }\n\n log.plain('')\n })\n}\n","import type { EventRow } from '../db/types'\n\n// captured_at is set at command completion (precmd fires after the command exits).\n// A long-running command's captured_at is its end time, so the gap between it and\n// the prior event equals the command's full duration — falsely triggering the idle\n// threshold. We use its start time (completion − duration) for gap calculation instead.\nexport const LONG_RUNNING_THRESHOLD_MS = 5 * 60 * 1000 // 5 minutes\n\n/**\n * Split a sorted list of events into groups separated by idle gaps.\n */\nexport function splitByIdleGap(events: EventRow[], idleMs: number): EventRow[][] {\n if (events.length === 0) return []\n const groups: EventRow[][] = [[events[0]]]\n\n for (let i = 1; i < events.length; i++) {\n const prev = new Date(events[i - 1].captured_at).getTime()\n const currCompleted = new Date(events[i].captured_at).getTime()\n const currDuration = events[i].duration_ms ?? 0\n const currEffective = currDuration >= LONG_RUNNING_THRESHOLD_MS ? currCompleted - currDuration : currCompleted\n\n if (currEffective - prev >= idleMs) {\n groups.push([events[i]])\n } else {\n groups[groups.length - 1].push(events[i])\n }\n }\n\n return groups\n}\n\n// A repo switch only starts a new sub-session if the gap since the last event\n// exceeds this threshold. A quick check in another repo and back should not\n// fragment the session.\nexport const REPO_SWITCH_GAP_MS = 10 * 60 * 1000 // 10 minutes\n\n/**\n * Split a list of events into groups by consecutive repo_name.\n * A repo change only creates a new group if the gap since the previous\n * event is at least `gapMs` (default 0 — splits on every repo change,\n * matching pre-WOR-72 behavior for callers that don't pass a threshold).\n */\nexport function splitByRepo(events: EventRow[], gapMs = 0): EventRow[][] {\n if (events.length === 0) return []\n const groups: EventRow[][] = [[events[0]]]\n\n for (let i = 1; i < events.length; i++) {\n const prevRepo = events[i - 1].repo_name\n const currRepo = events[i].repo_name\n const prevTime = new Date(events[i - 1].captured_at).getTime()\n const currTime = new Date(events[i].captured_at).getTime()\n const gap = currTime - prevTime\n\n if (currRepo !== prevRepo && gap >= gapMs) {\n groups.push([events[i]])\n } else {\n groups[groups.length - 1].push(events[i])\n }\n }\n\n return groups\n}\n\nexport function minutesBetween(start: string, end: string): number {\n return (new Date(end).getTime() - new Date(start).getTime()) / 60000\n}\n","import type { EventRow } from '../db/types'\nimport {\n insertSession,\n insertSessionEvent,\n clearSessionsForDate,\n getSessionsForDate,\n getEventsForDate,\n getEventsBySessionId,\n} from '../db'\nimport { readConfig } from '../config'\nimport { splitByIdleGap, splitByRepo, minutesBetween, REPO_SWITCH_GAP_MS } from './grouper'\n\nexport interface Session {\n id: number\n date: string\n startedAt: string\n endedAt: string\n repoName: string | null\n durationMinutes: number\n eventCount: number\n summary: string | null\n events: EventRow[]\n}\n\nexport function getOrBuildSessions(date: string): Session[] {\n // Check if sessions already exist for this date\n const existing = getSessionsForDate(date)\n const events = getEventsForDate(date)\n\n if (events.length === 0) return []\n\n // If sessions exist and event count matches, use cached\n const cachedEventCount = existing.reduce((sum, sessionRow) => sum + sessionRow.event_count, 0)\n if (existing.length > 0 && cachedEventCount === events.length) {\n return existing.map((sessionRow) => ({\n id: sessionRow.id,\n date: sessionRow.date,\n startedAt: sessionRow.started_at,\n endedAt: sessionRow.ended_at,\n repoName: sessionRow.repo_name,\n durationMinutes: minutesBetween(sessionRow.started_at, sessionRow.ended_at),\n eventCount: sessionRow.event_count,\n summary: sessionRow.summary,\n events: getEventsBySessionId(sessionRow.id),\n }))\n }\n\n // Preserve any cached summaries before clearing — keyed by repo+start time\n // so they can be restored to matching sessions after rebuild\n const savedSummaries = new Map<string, string>()\n for (const s of existing) {\n if (s.summary) savedSummaries.set(`${s.repo_name}|${s.started_at}`, s.summary)\n }\n\n // Rebuild sessions\n clearSessionsForDate(date)\n return buildSessions(date, events, savedSummaries)\n}\n\nfunction buildSessions(date: string, events: EventRow[], savedSummaries: Map<string, string> = new Map()): Session[] {\n const config = readConfig()\n const idleMs = config.session.idleTimeout * 60 * 1000\n\n const sessions: Session[] = []\n const timeGroups = splitByIdleGap(events, idleMs)\n\n for (const group of timeGroups) {\n if (group.length === 0) continue\n\n const repoGroups = splitByRepo(group, REPO_SWITCH_GAP_MS)\n\n for (const repoGroup of repoGroups) {\n if (repoGroup.length === 0) continue\n\n const first = repoGroup[0]\n const last = repoGroup[repoGroup.length - 1]\n const repoName = last.repo_name ?? first.repo_name ?? null\n\n // Restore a previously generated summary if the session boundaries match\n const summary = savedSummaries.get(`${repoName}|${first.captured_at}`) ?? null\n\n const sessionId = insertSession({\n date,\n started_at: first.captured_at,\n ended_at: last.captured_at,\n repo_name: repoName,\n event_count: repoGroup.length,\n summary,\n })\n\n for (const event of repoGroup) {\n insertSessionEvent(sessionId, event.id)\n }\n\n sessions.push({\n id: sessionId,\n date,\n startedAt: first.captured_at,\n endedAt: last.captured_at,\n repoName,\n durationMinutes: minutesBetween(first.captured_at, last.captured_at),\n eventCount: repoGroup.length,\n summary,\n events: repoGroup,\n })\n }\n }\n\n return sessions\n}\n","import { Command } from 'commander'\nimport chalk from 'chalk'\nimport fs from 'fs'\nimport os from 'os'\nimport path from 'path'\nimport { getOrBuildSessions } from '../sessions/detector'\nimport { getProvider } from '../ai/router'\nimport { readConfig } from '../config'\nimport { updateSessionSummary } from '../db'\nimport { log } from '../utils/logger'\nimport {\n todayDate,\n parseDate,\n formatDate,\n formatDuration,\n startOfWeek,\n eachDayOfRange,\n isoWeekKey,\n} from '../utils/format'\nimport { postToWebhook } from '../integrations/webhook'\nimport { formatForSlack, isSlackWebhookUrl } from '../integrations/slack'\nimport { WEEKLY_CACHE_DIR } from '../utils/paths'\nimport type { DaySummaryPayload, SessionPayload, EventPayload, WeekSummaryPayload } from '../ai/types'\nimport type { EventRow } from '../db'\nimport { buildExcludedSet, countExcludedEvents } from '../ai/prompt'\n\ninterface SessionSummaryJson {\n project: string | null\n branch: string | null\n durationMinutes: number\n bullets: string[]\n}\n\n/** Parse AI bullet output into a clean string array. Handles both - and • prefixes. */\nexport function parseBullets(text: string): string[] {\n return text\n .split('\\n')\n .map((line) => line.replace(/^[•\\-]\\s*/, '').trim())\n .filter(Boolean)\n}\n\nfunction eventRowToPayload(row: EventRow): EventPayload {\n let metadata: Record<string, unknown> = {}\n try {\n if (row.metadata) metadata = JSON.parse(row.metadata)\n } catch {\n /* ignore */\n }\n const payload: EventPayload = {\n category: row.category,\n metadata,\n exitCode: row.exit_code,\n durationMs: row.duration_ms,\n }\n if (row.category === 'other' && typeof metadata.hint === 'string') {\n payload.hint = metadata.hint\n const { hint: _hint, tool: _tool, ...rest } = metadata\n payload.metadata = rest\n }\n return payload\n}\n\nfunction sessionToPayload(s: ReturnType<typeof getOrBuildSessions>[number], date: string): SessionPayload {\n return {\n date,\n project: s.repoName,\n branch: s.events[0]?.branch ?? null,\n startTime: formatDate(s.startedAt),\n endTime: formatDate(s.endedAt),\n durationMinutes: s.durationMinutes,\n events: s.events.map(eventRowToPayload),\n }\n}\n\nasync function handleWebhook(\n opts: { slack?: boolean; webhook?: string },\n config: ReturnType<typeof readConfig>,\n summary: string\n): Promise<void> {\n const webhookUrl = opts.webhook ?? (opts.slack ? config.integrations?.slackWebhook : undefined)\n\n if (webhookUrl) {\n try {\n log.info('Posting to webhook…')\n const username = os.userInfo().username\n const body = isSlackWebhookUrl(webhookUrl) ? formatForSlack(summary, username) : summary\n await postToWebhook(webhookUrl, body)\n log.success('Posted.')\n } catch (error) {\n log.error(`Webhook failed: ${(error as Error).message}`)\n }\n } else if (opts.slack && !config.integrations?.slackWebhook) {\n log.warn('--slack requires integrations.slackWebhook to be set in config')\n }\n}\n\nexport function registerSummary(program: Command): void {\n program\n .command('summary')\n .description('Generate an AI work summary')\n .option('--date <YYYY-MM-DD>', 'date to summarize (default: today)')\n .option('--week', 'summarize the current week')\n .option('--fresh', 'bypass cache and regenerate')\n .option('--verbose', 'show all captured events including those not sent to AI')\n .option('--slack', 'post summary to Slack webhook from config')\n .option('--webhook <url>', 'post summary to a custom webhook URL')\n .action(async (opts) => {\n const config = readConfig()\n let provider\n try {\n provider = getProvider(config)\n } catch (error) {\n log.error((error as Error).message)\n process.exit(1)\n }\n\n // ── Weekly branch ────────────────────────────────────────────────────────\n if (opts.week) {\n const today = todayDate()\n const weekStart = startOfWeek(today)\n const days = eachDayOfRange(weekStart, today)\n\n const weeklyDays: WeekSummaryPayload['days'] = []\n for (const day of days) {\n const sessions = getOrBuildSessions(day)\n if (sessions.length > 0) {\n weeklyDays.push({ date: day, sessions: sessions.map((session) => sessionToPayload(session, day)) })\n }\n }\n\n if (weeklyDays.length === 0) {\n log.plain('No activity captured this week.')\n return\n }\n\n const cacheKey = isoWeekKey(today)\n const cacheFile = path.join(WEEKLY_CACHE_DIR, `${cacheKey}.md`)\n\n if (!opts.fresh && fs.existsSync(cacheFile)) {\n const cached = fs.readFileSync(cacheFile, 'utf-8')\n log.plain('')\n log.plain(cached)\n log.plain('')\n log.plain(chalk.dim(' (cached — use --fresh to regenerate)'))\n await handleWebhook(opts, config, cached)\n return\n }\n\n const payload: WeekSummaryPayload = { weekStart, weekEnd: today, days: weeklyDays }\n\n log.plain('')\n log.info(`Generating weekly summary via ${chalk.cyan(config.ai.provider)}…`)\n\n try {\n const summary = provider.summarizeWeek\n ? await provider.summarizeWeek(payload)\n : await provider.summarize({ date: today, sessions: weeklyDays.flatMap((day) => day.sessions) })\n\n log.plain('')\n log.plain(summary)\n log.plain('')\n\n fs.mkdirSync(WEEKLY_CACHE_DIR, { recursive: true })\n fs.writeFileSync(cacheFile, summary, { encoding: 'utf-8', mode: 0o600 })\n\n await handleWebhook(opts, config, summary)\n } catch (error) {\n log.error(`Weekly summary failed [${config.ai.provider}]: ${(error as Error).message}`)\n process.exit(1)\n }\n return\n }\n\n // ── Daily branch ─────────────────────────────────────────────────────────\n let date = todayDate()\n if (opts.date) {\n try {\n date = parseDate(opts.date)\n } catch (error) {\n log.error((error as Error).message)\n process.exit(1)\n }\n }\n\n const sessions = getOrBuildSessions(date)\n\n if (sessions.length === 0) {\n log.plain(`No activity captured for ${date}`)\n return\n }\n\n const jsonMode = config.summary?.format === 'json'\n\n if (!opts.fresh) {\n const allCached = sessions.every((session) => session.summary)\n if (allCached) {\n const fullSummary = sessions.map((session) => session.summary!).join('\\n\\n')\n log.plain('')\n if (jsonMode) {\n const jsonOut: SessionSummaryJson[] = sessions.map((session) => ({\n project: session.repoName,\n branch: session.events[0]?.branch ?? null,\n durationMinutes: session.durationMinutes,\n bullets: parseBullets(session.summary!.replace(/^## .+\\n/, '')),\n }))\n log.plain(JSON.stringify({ date, sessions: jsonOut }, null, 2))\n } else {\n log.plain(fullSummary)\n }\n log.plain('')\n log.plain(chalk.dim(' (cached — use --fresh to regenerate)'))\n await handleWebhook(opts, config, fullSummary)\n return\n }\n }\n\n const excluded = buildExcludedSet(config.summary?.includeCategories ?? [])\n const allSessionPayloads = sessions.map((session) => sessionToPayload(session, date))\n\n if (opts.verbose) {\n log.plain('')\n log.plain(chalk.bold(' Captured events (--verbose):'))\n for (const sessionPayload of allSessionPayloads) {\n const branch = sessionPayload.branch ? ` (${sessionPayload.branch})` : ''\n log.plain(\n chalk.dim(\n `\\n ${sessionPayload.project ?? 'unknown'}${branch} — ${formatDuration(sessionPayload.durationMinutes)}`\n )\n )\n for (const event of sessionPayload.events) {\n const tag = excluded.has(event.category)\n ? chalk.dim(` [excluded] ${event.category}`)\n : ` ${event.category}`\n const hint = event.hint ? chalk.dim(` [${event.hint}]`) : ''\n const meta = Object.keys(event.metadata).length > 0 ? chalk.dim(` ${JSON.stringify(event.metadata)}`) : ''\n log.plain(` ${tag}${hint}${meta}`)\n }\n }\n log.plain('')\n }\n\n log.plain('')\n log.info(`Generating summary via ${chalk.cyan(config.ai.provider)}…`)\n\n const allSummaries: string[] = []\n const jsonSessions: SessionSummaryJson[] = []\n\n for (let index = 0; index < sessions.length; index++) {\n const session = sessions[index]\n const sessionPayload: DaySummaryPayload = { date, sessions: [allSessionPayloads[index]] }\n try {\n const bullets = await provider.summarize(sessionPayload)\n const project = session.repoName ?? 'unknown'\n const branch = session.events[0]?.branch ? ` (${session.events[0].branch})` : ''\n const duration = formatDuration(session.durationMinutes)\n const heading = `## ${project}${branch} — ${duration}`\n const summary = `${heading}\\n${bullets.trim()}`\n allSummaries.push(summary)\n updateSessionSummary(session.id, summary)\n if (jsonMode) {\n jsonSessions.push({\n project: session.repoName,\n branch: session.events[0]?.branch ?? null,\n durationMinutes: session.durationMinutes,\n bullets: parseBullets(bullets),\n })\n }\n } catch (error) {\n log.error(`Summary failed [${config.ai.provider}]: ${(error as Error).message}`)\n process.exit(1)\n }\n }\n\n const fullSummary = allSummaries.join('\\n\\n')\n log.plain('')\n if (jsonMode) {\n log.plain(JSON.stringify({ date, sessions: jsonSessions }, null, 2))\n } else {\n log.plain(fullSummary)\n }\n log.plain('')\n\n const excludedCounts = countExcludedEvents(allSessionPayloads, excluded)\n if (excludedCounts.size > 0) {\n const total = [...excludedCounts.values()].reduce((sum, count) => sum + count, 0)\n const breakdown = [...excludedCounts.entries()].map(([category, count]) => `${category} ×${count}`).join(', ')\n log.plain(chalk.dim(` ℹ ${total} event${total === 1 ? '' : 's'} not included in summary (${breakdown})`))\n log.plain(chalk.dim(' Use --verbose to inspect · workscribe config set summary.includeCategories to opt in'))\n log.plain('')\n }\n\n await handleWebhook(opts, config, fullSummary)\n })\n}\n","import { fetchWithTimeout } from '../utils/fetch'\n\nexport async function postToWebhook(url: string, text: string): Promise<void> {\n const response = await fetchWithTimeout(\n url,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ text }),\n },\n 10_000\n )\n\n if (!response.ok) {\n const body = await response.text()\n throw new Error(`Webhook POST failed ${response.status}: ${body}`)\n }\n}\n","/**\n * Converts workscribe markdown summary output to Slack mrkdwn format.\n *\n * Rules:\n * ## heading → *heading* (bold)\n * - bullet → • bullet\n *\n * An optional username is prepended as a dim header line so recipients\n * can tell who sent the summary in shared channels.\n */\nexport function formatForSlack(markdown: string, username?: string): string {\n const body = markdown.replace(/^## (.+)$/gm, '*$1*').replace(/^- /gm, '• ')\n return username ? `_${username}_\\n${body}` : body\n}\n\nexport function isSlackWebhookUrl(url: string): boolean {\n return url.startsWith('https://hooks.slack.com/')\n}\n","import { Command } from 'commander'\nimport fs from 'fs'\nimport path from 'path'\nimport { getOrBuildSessions } from '../sessions/detector'\nimport { getProvider } from '../ai/router'\nimport { readConfig } from '../config'\nimport { log } from '../utils/logger'\nimport { todayDate, parseDate, formatDate } from '../utils/format'\nimport { EXPORTS_DIR } from '../utils/paths'\nimport type { DaySummaryPayload, SessionPayload, EventPayload } from '../ai/types'\nimport type { EventRow } from '../db'\n\nfunction eventRowToPayload(row: EventRow): EventPayload {\n let metadata: Record<string, unknown> = {}\n try {\n if (row.metadata) metadata = JSON.parse(row.metadata)\n } catch {\n /* ignore */\n }\n const payload: EventPayload = {\n category: row.category,\n metadata,\n exitCode: row.exit_code,\n durationMs: row.duration_ms,\n }\n if (row.category === 'other' && typeof metadata.hint === 'string') {\n payload.hint = metadata.hint\n const { hint: _h, tool: _t, ...rest } = metadata\n payload.metadata = rest\n }\n return payload\n}\n\nexport function registerExport(program: Command): void {\n program\n .command('export')\n .description('Export work summary as a markdown file')\n .option('--date <YYYY-MM-DD>', 'date to export (default: today)')\n .option('--output <path>', 'output file path (default: ~/.workscribe/exports/)')\n .action(async (opts) => {\n let date = todayDate()\n if (opts.date) {\n try {\n date = parseDate(opts.date)\n } catch (e) {\n log.error((e as Error).message)\n process.exit(1)\n }\n }\n\n const sessions = getOrBuildSessions(date)\n if (sessions.length === 0) {\n log.plain(`No activity captured for ${date}`)\n return\n }\n\n const config = readConfig()\n let provider\n try {\n provider = getProvider(config)\n } catch (e) {\n log.error((e as Error).message)\n process.exit(1)\n }\n\n const sessionPayloads: SessionPayload[] = sessions.map((session) => ({\n date,\n project: session.repoName,\n branch: session.events[0]?.branch ?? null,\n startTime: formatDate(session.startedAt),\n endTime: formatDate(session.endedAt),\n durationMinutes: session.durationMinutes,\n events: session.events.map(eventRowToPayload),\n }))\n\n const payload: DaySummaryPayload = { date, sessions: sessionPayloads }\n\n log.info(`Generating summary via ${config.ai.provider}…`)\n const summary = await provider.summarize(payload)\n\n const outputPath = opts.output ?? path.join(EXPORTS_DIR, `workscribe-${date}.md`)\n\n if (!fs.existsSync(EXPORTS_DIR)) fs.mkdirSync(EXPORTS_DIR, { recursive: true, mode: 0o700 })\n\n fs.writeFileSync(outputPath, `# Work Summary — ${date}\\n\\n${summary}\\n`, { encoding: 'utf-8', mode: 0o600 })\n log.success(`Saved: ${outputPath}`)\n })\n}\n","import { Command } from 'commander'\nimport chalk from 'chalk'\nimport { readConfig, writeConfig, getConfigValue, setConfigValue } from '../config'\nimport { log } from '../utils/logger'\n\nexport function registerConfig(program: Command): void {\n const configCmd = program\n .command('config')\n .description('View or update Workscribe configuration')\n .action(() => {\n const config = readConfig()\n log.plain('')\n log.plain(chalk.bold(' Workscribe Config'))\n log.plain('')\n printConfig(config, ' ')\n log.plain('')\n })\n\n configCmd\n .command('set <key> <value>')\n .description('Set a config value (e.g. workscribe config set ai.provider anthropic)')\n .action((key: string, value: string) => {\n const config = readConfig()\n const updated = setConfigValue(config, key, value)\n writeConfig(updated)\n const isSensitive =\n key === 'ai.apiKey' ||\n key.toLowerCase().includes('key') ||\n key.toLowerCase().includes('secret') ||\n key.toLowerCase().includes('token')\n const displayValue = isSensitive ? '[set]' : chalk.yellow(value)\n log.success(`Set ${chalk.cyan(key)} = ${displayValue}`)\n })\n\n configCmd\n .command('get <key>')\n .description('Get a config value')\n .action((key: string) => {\n const config = readConfig()\n const value = getConfigValue(config, key)\n if (value === undefined) {\n log.warn(`Key not found: ${key}`)\n } else {\n const lastSegment = key.split('.').pop() ?? ''\n if (SENSITIVE_KEYS.has(lastSegment) && typeof value === 'string' && value.length > 0) {\n log.plain(`${value.slice(0, 4)}${'*'.repeat(8)} (${value.length} chars)`)\n } else {\n log.plain(String(value))\n }\n }\n })\n}\n\nconst SENSITIVE_KEYS = new Set([\n 'apiKey',\n 'api_key',\n 'secret',\n 'token',\n 'password',\n 'passwd',\n 'webhook',\n 'slackWebhook',\n])\n\nfunction maskValue(key: string, value: unknown): string {\n if (SENSITIVE_KEYS.has(key) && typeof value === 'string' && value.length > 0) {\n return chalk.dim(`${value.slice(0, 4)}${'*'.repeat(8)} (${value.length} chars)`)\n }\n if (Array.isArray(value)) return `[${(value as unknown[]).join(', ')}]`\n return String(value) || chalk.dim('(not set)')\n}\n\nfunction printConfig(obj: unknown, indent: string): void {\n if (typeof obj !== 'object' || obj === null) return\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\n if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n log.plain(`${indent}${chalk.bold(key)}:`)\n printConfig(value, indent + ' ')\n } else {\n log.plain(`${indent}${chalk.dim(key)}: ${chalk.yellow(maskValue(key, value))}`)\n }\n }\n}\n","import { Command } from 'commander'\nimport fs from 'fs'\nimport { PAUSE_FLAG_PATH } from '../utils/paths'\nimport { log } from '../utils/logger'\n\nexport function registerPause(program: Command): void {\n program\n .command('pause')\n .description('Pause capture temporarily')\n .action(() => {\n if (fs.existsSync(PAUSE_FLAG_PATH)) {\n log.info('Capture is already paused. Run workscribe resume to restart.')\n return\n }\n fs.writeFileSync(PAUSE_FLAG_PATH, '', { mode: 0o600 })\n log.success('Capture paused. Run workscribe resume to restart.')\n })\n\n program\n .command('resume')\n .description('Resume capture after a pause')\n .action(() => {\n if (!fs.existsSync(PAUSE_FLAG_PATH)) {\n log.info('Capture is not paused.')\n return\n }\n fs.rmSync(PAUSE_FLAG_PATH)\n log.success('Capture resumed.')\n })\n}\n","import { Command } from 'commander'\nimport { getLastEventIds, getEventsByIds, deleteEventsByIds } from '../db'\nimport { log } from '../utils/logger'\n\nexport function registerUndo(program: Command): void {\n program\n .command('undo')\n .description('Remove the last N captured events')\n .option('-n, --count <number>', 'number of events to remove', '1')\n .option('--dry-run', 'preview what would be deleted without deleting')\n .action((opts) => {\n const count = parseInt(opts.count, 10)\n if (isNaN(count) || count < 1) {\n log.error('--count must be a positive integer')\n process.exit(1)\n }\n\n const ids = getLastEventIds(count)\n if (ids.length === 0) {\n log.plain('No events to undo.')\n return\n }\n\n const events = getEventsByIds(ids)\n log.plain('')\n log.plain(`Events to remove (${events.length}):`)\n for (const e of events) {\n log.plain(` ${e.captured_at} ${e.category} ${e.command}`)\n }\n log.plain('')\n\n if (opts.dryRun) {\n log.plain('Dry run — nothing deleted.')\n return\n }\n\n deleteEventsByIds(ids)\n log.success(`Removed ${ids.length} event${ids.length > 1 ? 's' : ''}.`)\n })\n}\n","import { Command } from 'commander'\nimport chalk from 'chalk'\nimport prompts from 'prompts'\nimport { getEventsForDate, deleteEventsForDate } from '../db'\nimport { log } from '../utils/logger'\nimport { todayDate, parseDate } from '../utils/format'\n\nexport function registerClear(program: Command): void {\n program\n .command('clear')\n .description('Delete all captured events for a date')\n .option('--date <YYYY-MM-DD>', 'date to clear (default: today)')\n .option('--dry-run', 'preview what would be deleted without deleting')\n .option('--yes', 'skip confirmation prompt')\n .action(async (opts) => {\n let date = todayDate()\n if (opts.date) {\n try {\n date = parseDate(opts.date)\n } catch (e) {\n log.error((e as Error).message)\n process.exit(1)\n }\n }\n\n const events = getEventsForDate(date)\n\n if (events.length === 0) {\n log.plain(`No events found for ${date}.`)\n return\n }\n\n log.plain('')\n log.plain(chalk.bold(` Events for ${date} (${events.length} total)`))\n log.plain('')\n\n // Show a compact summary by category\n const counts = new Map<string, number>()\n for (const e of events) counts.set(e.category, (counts.get(e.category) ?? 0) + 1)\n for (const [cat, n] of counts) {\n log.plain(` ${chalk.dim(String(n).padStart(4))} ${cat}`)\n }\n log.plain('')\n\n if (opts.dryRun) {\n log.plain(chalk.dim(' Dry run — nothing deleted.'))\n log.plain('')\n return\n }\n\n if (!opts.yes) {\n const { confirm } = await prompts({\n type: 'confirm',\n name: 'confirm',\n message: `Delete all ${events.length} events for ${date}?`,\n initial: false,\n })\n if (!confirm) {\n log.plain('Cancelled.')\n return\n }\n }\n\n const deleted = deleteEventsForDate(date)\n log.success(`Cleared ${deleted} event${deleted !== 1 ? 's' : ''} for ${date}.`)\n })\n}\n","import { Command } from 'commander'\nimport fs from 'fs'\nimport path from 'path'\nimport os from 'os'\nimport prompts from 'prompts'\nimport chalk from 'chalk'\nimport { WORKSCRIBE_DIR, REQUIRED_DIRS } from '../utils/paths'\nimport { isHookInstalled, removeHook } from '../capture/shell-hook'\nimport { log } from '../utils/logger'\n\nfunction detectShellRcFiles(): { name: string; rcFile: string }[] {\n const candidates = [\n { name: 'zsh', rcFile: path.join(os.homedir(), '.zshrc') },\n { name: 'bash', rcFile: path.join(os.homedir(), '.bashrc') },\n { name: 'bash', rcFile: path.join(os.homedir(), '.bash_profile') },\n { name: 'fish', rcFile: path.join(os.homedir(), '.config', 'fish', 'conf.d', 'workscribe.fish') },\n ]\n return candidates.filter((candidate) => fs.existsSync(candidate.rcFile) && isHookInstalled(candidate.rcFile))\n}\n\nexport function registerUninstall(program: Command): void {\n program\n .command('uninstall')\n .description('Remove shell hooks and optionally delete all Workscribe data')\n .option('--hooks-only', 'remove shell hooks only, skip data deletion prompt (used by npm preuninstall)')\n .action(async (opts) => {\n log.plain(chalk.bold('\\n Workscribe — Uninstall\\n'))\n\n // 1. Remove shell hooks from any rc files that have them\n const hooked = detectShellRcFiles()\n if (hooked.length === 0) {\n log.info('No shell hooks found')\n } else {\n for (const { name, rcFile } of hooked) {\n if (name === 'fish') {\n // The conf.d file is ours entirely — delete it rather than leaving an empty file\n fs.unlinkSync(rcFile)\n log.success(`Shell hook removed: ${rcFile}`)\n log.plain(` ${chalk.dim('Restart your terminal to take effect')}`)\n } else {\n removeHook(rcFile)\n log.success(`Shell hook removed from ${rcFile}`)\n log.plain(` ${chalk.dim(`Run: source ${rcFile}`)} (or restart your terminal to take effect)`)\n log.plain(\n ` ${chalk.dim(`${name === 'zsh' ? 'unfunction' : 'unset -f'} _workscribe_preexec _workscribe_precmd`)}`\n )\n }\n }\n }\n\n if (opts.hooksOnly) return\n\n // 2. Optionally delete all Workscribe data directories\n const existingDirs = [...new Set(REQUIRED_DIRS)].filter((dir) => fs.existsSync(dir))\n\n if (existingDirs.length > 0) {\n log.plain('')\n const { deleteData } = await prompts({\n type: 'confirm',\n name: 'deleteData',\n message: `Delete all Workscribe data in ${WORKSCRIBE_DIR}? (database, config, exports)`,\n initial: false,\n })\n\n if (deleteData) {\n for (const dir of existingDirs) {\n fs.rmSync(dir, { recursive: true, force: true })\n log.success(`Deleted ${dir}`)\n }\n } else {\n log.info(`Data kept at ${WORKSCRIBE_DIR}`)\n }\n }\n\n log.plain('')\n log.plain(` ${chalk.dim('npm uninstall -g @workscribe/cli')} — remove the CLI itself`)\n log.plain('')\n })\n}\n","import { Command } from 'commander'\nimport fs from 'fs'\nimport path from 'path'\nimport chalk from 'chalk'\nimport { readConfig, writeConfig } from '../config'\nimport { PROFILES_DIR } from '../utils/paths'\nimport { getCachedProfiles, detectProfilesForDirectory } from '../profiles/loader'\nimport { installProfile, cacheManifest, readCachedManifest } from '../profiles/fetcher'\nimport { getOtherEventToolCounts } from '../db'\nimport { log } from '../utils/logger'\n\nconst MIN_SUGGEST_COUNT = 5\n\nexport function registerProfile(program: Command): void {\n const profile = program.command('profile').description('Manage stack profiles for better command tracking')\n\n // ─── list ─────────────────────────────────────────────────────────────────\n profile\n .command('list')\n .description('List available profiles from the registry')\n .action(async () => {\n const config = readConfig()\n const activeNames = new Set(config.capture.profiles)\n\n let manifest = readCachedManifest()\n let offline = false\n\n if (!manifest) {\n try {\n manifest = await cacheManifest()\n } catch {\n offline = true\n manifest = getCachedProfiles().map((p) => ({\n name: p.name,\n displayName: p.displayName,\n tags: [],\n description: '',\n keywords: [],\n detect: p.detect,\n }))\n }\n } else {\n // Refresh in background — best effort, don't block output\n cacheManifest().catch(() => undefined)\n }\n\n if (offline) {\n log.warn('Registry unreachable — showing installed profiles only')\n }\n\n if (manifest.length === 0) {\n log.plain('No profiles available. Check your connection and try again.')\n return\n }\n\n // Group by tag\n const grouped = new Map<string, typeof manifest>()\n for (const entry of manifest) {\n const tag = entry.tags[0] ?? 'other'\n if (!grouped.has(tag)) grouped.set(tag, [])\n grouped.get(tag)!.push(entry)\n }\n\n log.plain('')\n for (const [tag, entries] of grouped) {\n log.plain(chalk.bold(` ${tag.charAt(0).toUpperCase() + tag.slice(1)} profiles`))\n log.plain(chalk.dim(' ' + '─'.repeat(60)))\n for (const entry of entries) {\n const badge = activeNames.has(entry.name) ? chalk.green(' [active]') : ''\n const installed = fs.existsSync(path.join(PROFILES_DIR, `${entry.name}.json`)) ? chalk.dim(' installed') : ''\n log.plain(` ${chalk.cyan(entry.name.padEnd(18))} ${entry.displayName.padEnd(28)}${badge}${installed}`)\n if (entry.description) log.plain(` ${chalk.dim(' '.repeat(18) + entry.description)}`)\n }\n log.plain('')\n }\n })\n\n // ─── add ──────────────────────────────────────────────────────────────────\n profile\n .command('add <names...>')\n .description('Install one or more profiles from the registry')\n .action(async (names: string[]) => {\n const config = readConfig()\n const activeNames = new Set(config.capture.profiles)\n\n for (const name of names) {\n if (activeNames.has(name)) {\n log.info(`Profile \"${name}\" is already active`)\n continue\n }\n try {\n log.plain(`Fetching ${chalk.cyan(name)}…`)\n await installProfile(name)\n activeNames.add(name)\n log.success(`Profile \"${name}\" installed`)\n } catch (err) {\n log.error(`Failed to install \"${name}\": ${(err as Error).message}`)\n }\n }\n\n config.capture.profiles = [...activeNames]\n writeConfig(config)\n })\n\n // ─── remove ───────────────────────────────────────────────────────────────\n profile\n .command('remove <names...>')\n .description('Uninstall one or more profiles')\n .action((names: string[]) => {\n const config = readConfig()\n const activeNames = new Set(config.capture.profiles)\n\n for (const name of names) {\n if (!activeNames.has(name)) {\n log.warn(`Profile \"${name}\" is not active`)\n continue\n }\n activeNames.delete(name)\n const cachePath = path.join(PROFILES_DIR, `${name}.json`)\n if (fs.existsSync(cachePath)) fs.unlinkSync(cachePath)\n log.success(`Profile \"${name}\" removed`)\n }\n\n config.capture.profiles = [...activeNames]\n writeConfig(config)\n })\n\n // ─── update ───────────────────────────────────────────────────────────────\n profile\n .command('update [name]')\n .description('Re-fetch installed profiles from the registry')\n .action(async (name?: string) => {\n const config = readConfig()\n const toUpdate = name ? [name] : config.capture.profiles\n\n if (toUpdate.length === 0) {\n log.plain('No profiles installed. Run workscribe profile add <name> first.')\n return\n }\n\n for (const profileName of toUpdate) {\n try {\n log.plain(`Updating ${chalk.cyan(profileName)}…`)\n await installProfile(profileName)\n log.success(`${profileName} updated`)\n } catch (err) {\n log.error(`Failed to update \"${profileName}\": ${(err as Error).message}`)\n }\n }\n })\n\n // ─── detect ───────────────────────────────────────────────────────────────\n profile\n .command('detect')\n .description('Scan the current directory and suggest matching profiles')\n .action(() => {\n const cwd = process.cwd()\n const matches = detectProfilesForDirectory(cwd)\n\n if (matches.length === 0) {\n const cached = readCachedManifest()\n if (!cached) {\n log.plain('No manifest cached. Run workscribe profile list to fetch it first.')\n } else {\n log.plain(`No profiles detected for ${chalk.dim(cwd)}`)\n log.plain(chalk.dim('Run workscribe profile list to browse available profiles.'))\n }\n return\n }\n\n log.plain('')\n log.plain(chalk.bold(' Profiles detected for this directory:'))\n log.plain('')\n for (const entry of matches) {\n const files = entry.detect?.files?.join(', ') ?? ''\n log.plain(` ${chalk.cyan(entry.name.padEnd(18))} ${entry.displayName} ${chalk.dim('(' + files + ')')}`)\n }\n log.plain('')\n log.plain(` Run: ${chalk.cyan('workscribe profile add ' + matches.map((e) => e.name).join(' '))}`)\n log.plain('')\n })\n\n // ─── suggest ──────────────────────────────────────────────────────────────\n profile\n .command('suggest')\n .description('Analyse recent unclassified commands and suggest profiles')\n .option('--days <n>', 'number of days to analyse', '30')\n .action((opts) => {\n const days = Math.max(1, parseInt(opts.days as string, 10) || 30)\n const toolCounts = getOtherEventToolCounts(days)\n\n if (toolCounts.length === 0) {\n log.plain('No unclassified commands found in the last ' + days + ' days.')\n return\n }\n\n const manifest = readCachedManifest()\n if (!manifest) {\n log.plain('No manifest cached. Run workscribe profile list first.')\n return\n }\n\n const config = readConfig()\n const activeNames = new Set(config.capture.profiles)\n\n // Match tool counts against manifest keywords\n const suggestions: { entry: (typeof manifest)[number]; count: number }[] = []\n for (const entry of manifest) {\n if (activeNames.has(entry.name)) continue\n const matchedCount = toolCounts\n .filter((toolCount) =>\n entry.keywords.some((keyword) => toolCount.tool.toLowerCase().includes(keyword.toLowerCase()))\n )\n .reduce((total, toolCount) => total + toolCount.count, 0)\n if (matchedCount >= MIN_SUGGEST_COUNT) {\n suggestions.push({ entry, count: matchedCount })\n }\n }\n\n suggestions.sort((a, b) => b.count - a.count)\n\n if (suggestions.length === 0) {\n const activeEntries = manifest.filter((entry) => activeNames.has(entry.name))\n const isToolCoveredByActiveProfile = (tool: string) =>\n activeEntries.some((entry) =>\n entry.keywords.some((keyword) => tool.toLowerCase().includes(keyword.toLowerCase()))\n )\n const uncoveredTools = toolCounts.filter((toolCount) => !isToolCoveredByActiveProfile(toolCount.tool))\n\n if (uncoveredTools.length === 0) {\n log.plain('')\n log.plain('Your active profiles cover all unclassified commands.')\n log.plain(chalk.dim(' Future captures will be classified correctly.'))\n log.plain('')\n } else {\n log.plain('')\n log.plain('No profile matches found for your unclassified commands.')\n log.plain('')\n log.plain(chalk.dim(' Top unclassified tools:'))\n for (const { tool, count } of uncoveredTools.slice(0, 5)) {\n log.plain(chalk.dim(` ${tool.padEnd(24)} ${count} event${count === 1 ? '' : 's'}`))\n }\n log.plain('')\n log.plain(chalk.dim(' Run workscribe events --category other to review them.'))\n log.plain('')\n }\n return\n }\n\n log.plain('')\n log.plain(chalk.bold(` Analysed last ${days} days of unclassified commands:`))\n log.plain('')\n for (const { entry, count } of suggestions) {\n log.plain(\n ` ${chalk.cyan(entry.name.padEnd(18))} ${String(count).padStart(4)} commands → ${entry.displayName}`\n )\n }\n log.plain('')\n log.plain(\n ` Run: ${chalk.cyan('workscribe profile add ' + suggestions.map((suggestion) => suggestion.entry.name).join(' '))}`\n )\n log.plain('')\n\n const allCoveredEntries = [\n ...manifest.filter((entry) => activeNames.has(entry.name)),\n ...suggestions.map((suggestion) => suggestion.entry),\n ]\n const isToolCoveredAfterInstall = (tool: string) =>\n allCoveredEntries.some((entry) =>\n entry.keywords.some((keyword) => tool.toLowerCase().includes(keyword.toLowerCase()))\n )\n const stillUncovered = toolCounts.filter((toolCount) => !isToolCoveredAfterInstall(toolCount.tool)).slice(0, 5)\n if (stillUncovered.length > 0) {\n log.plain(chalk.dim(' Still uncovered after installing:'))\n for (const { tool, count } of stillUncovered) {\n log.plain(chalk.dim(` ${tool.padEnd(24)} ${count} event${count === 1 ? '' : 's'}`))\n }\n log.plain('')\n }\n })\n}\n","import { Command } from 'commander'\nimport { insertEvent } from '../db'\nimport { getGitContext } from '../capture/git'\nimport { log } from '../utils/logger'\n\nexport function registerNote(program: Command): void {\n program\n .command('note <text>')\n .description('Attach a free-text annotation to the current session')\n .action((text: string) => {\n const { repoName, branch } = getGitContext(process.cwd())\n insertEvent({\n captured_at: new Date().toISOString(),\n command: 'workscribe note',\n cwd: process.cwd(),\n exit_code: null,\n duration_ms: null,\n repo_name: repoName,\n branch,\n category: 'note',\n metadata: JSON.stringify({ text }),\n source: null,\n file_path: null,\n })\n log.success(`Note saved${repoName ? ` to ${repoName}` : ''}`)\n })\n}\n","import { Command } from 'commander'\nimport chalk from 'chalk'\nimport fs from 'fs'\nimport path from 'path'\nimport os from 'os'\nimport { getOrBuildSessions } from '../sessions/detector'\nimport { getProvider } from '../ai/router'\nimport { readConfig } from '../config'\nimport { log } from '../utils/logger'\nimport { todayDate, startOfWeek, eachDayOfRange, isoWeekKey, formatDate } from '../utils/format'\nimport { postToWebhook } from '../integrations/webhook'\nimport { formatForSlack, isSlackWebhookUrl } from '../integrations/slack'\nimport { WEEKLY_CACHE_DIR } from '../utils/paths'\nimport type { WeekSummaryPayload, SessionPayload, EventPayload } from '../ai/types'\nimport type { EventRow } from '../db'\n\nfunction eventRowToPayload(row: EventRow): EventPayload {\n let metadata: Record<string, unknown> = {}\n try {\n if (row.metadata) metadata = JSON.parse(row.metadata)\n } catch {\n /* ignore */\n }\n const payload: EventPayload = {\n category: row.category,\n metadata,\n exitCode: row.exit_code,\n durationMs: row.duration_ms,\n }\n if (row.category === 'other' && typeof metadata.hint === 'string') {\n payload.hint = metadata.hint\n const { hint: _hint, tool: _tool, ...rest } = metadata\n payload.metadata = rest\n }\n return payload\n}\n\nfunction sessionToPayload(session: ReturnType<typeof getOrBuildSessions>[number], date: string): SessionPayload {\n return {\n date,\n project: session.repoName,\n branch: session.events[0]?.branch ?? null,\n startTime: formatDate(session.startedAt),\n endTime: formatDate(session.endedAt),\n durationMinutes: session.durationMinutes,\n events: session.events.map(eventRowToPayload),\n }\n}\n\nasync function postSummary(\n opts: { slack?: boolean; webhook?: string },\n config: ReturnType<typeof readConfig>,\n summary: string\n): Promise<void> {\n const webhookUrl = opts.webhook ?? (opts.slack ? config.integrations?.slackWebhook : undefined)\n if (!webhookUrl) {\n if (opts.slack) log.warn('--slack requires integrations.slackWebhook to be set in config')\n return\n }\n try {\n log.info('Posting to webhook…')\n const username = os.userInfo().username\n const body = isSlackWebhookUrl(webhookUrl) ? formatForSlack(summary, username) : summary\n await postToWebhook(webhookUrl, body)\n log.success('Posted.')\n } catch (error) {\n log.error(`Webhook failed: ${(error as Error).message}`)\n }\n}\n\nexport function registerWeek(program: Command): void {\n program\n .command('week')\n .description('Generate an AI weekly digest (Mon–today)')\n .option('--fresh', 'bypass cache and regenerate')\n .option('--slack', 'post to Slack webhook from config')\n .option('--webhook <url>', 'post to a custom webhook URL')\n .action(async (opts) => {\n const config = readConfig()\n let provider\n try {\n provider = getProvider(config)\n } catch (error) {\n log.error((error as Error).message)\n process.exit(1)\n }\n\n const today = todayDate()\n const weekStart = startOfWeek(today)\n const days = eachDayOfRange(weekStart, today)\n\n const weeklyDays: WeekSummaryPayload['days'] = []\n for (const day of days) {\n const sessions = getOrBuildSessions(day)\n if (sessions.length > 0) {\n weeklyDays.push({ date: day, sessions: sessions.map((session) => sessionToPayload(session, day)) })\n }\n }\n\n if (weeklyDays.length === 0) {\n log.plain('No activity captured this week.')\n return\n }\n\n const cacheKey = isoWeekKey(today)\n const cacheFile = path.join(WEEKLY_CACHE_DIR, `${cacheKey}.md`)\n\n if (!opts.fresh && fs.existsSync(cacheFile)) {\n const cached = fs.readFileSync(cacheFile, 'utf-8')\n log.plain('')\n log.plain(cached)\n log.plain('')\n log.plain(chalk.dim(' (cached — use --fresh to regenerate)'))\n await postSummary(opts, config, cached)\n return\n }\n\n const payload: WeekSummaryPayload = { weekStart, weekEnd: today, days: weeklyDays }\n\n log.plain('')\n log.info(`Generating weekly digest via ${chalk.cyan(config.ai.provider)}…`)\n\n try {\n const summary = provider.summarizeWeek\n ? await provider.summarizeWeek(payload)\n : await provider.summarize({ date: today, sessions: weeklyDays.flatMap((day) => day.sessions) })\n\n log.plain('')\n log.plain(summary)\n log.plain('')\n\n fs.mkdirSync(WEEKLY_CACHE_DIR, { recursive: true })\n fs.writeFileSync(cacheFile, summary, { encoding: 'utf-8', mode: 0o600 })\n\n await postSummary(opts, config, summary)\n } catch (error) {\n log.error(`Weekly digest failed [${config.ai.provider}]: ${(error as Error).message}`)\n process.exit(1)\n }\n })\n}\n","import { Command } from 'commander'\nimport fs from 'fs'\nimport os from 'os'\nimport path from 'path'\nimport chalk from 'chalk'\nimport { WORKSCRIBE_DIR, DEBUG_LOG_PATH, CONFIG_PATH } from '../utils/paths'\nimport { readConfig } from '../config'\nimport { log } from '../utils/logger'\n\ndeclare const __WORKSCRIBE_VERSION__: string\n\nconst GITHUB_ISSUES_URL = 'https://github.com/workscribe/workscribe/issues/new'\nconst DEBUG_LOG_TAIL_LINES = 100\n\nfunction tailFile(filePath: string, lines: number): string {\n if (!fs.existsSync(filePath)) return '(no debug log found — set WORKSCRIBE_DEBUG=1 to enable)'\n const content = fs.readFileSync(filePath, 'utf-8')\n const allLines = content.split('\\n')\n return allLines.slice(-lines).join('\\n')\n}\n\nfunction redactConfig(): string {\n try {\n const config = readConfig()\n if (config.ai.apiKey) config.ai.apiKey = '<redacted>'\n if (config.integrations?.slackWebhook) config.integrations.slackWebhook = '<redacted>'\n if (config.integrations?.webhook) config.integrations.webhook = '<redacted>'\n return JSON.stringify(config, null, 2)\n } catch {\n return '(could not read config)'\n }\n}\n\nexport function registerBugReport(program: Command): void {\n program\n .command('bug-report')\n .description('Generate a diagnostic report for filing a bug')\n .action(() => {\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-')\n const reportPath = path.join(WORKSCRIBE_DIR, `bug-report-${timestamp}.txt`)\n\n const systemInfo = [\n `Workscribe version : ${__WORKSCRIBE_VERSION__}`,\n `Node.js version : ${process.version}`,\n `Platform : ${process.platform}`,\n `Architecture : ${process.arch}`,\n `OS release : ${os.release()}`,\n `Config path : ${CONFIG_PATH}`,\n `Data directory : ${WORKSCRIBE_DIR}`,\n ].join('\\n')\n\n const report = [\n '=== Workscribe Bug Report ===',\n `Generated: ${new Date().toISOString()}`,\n '',\n '--- System ---',\n systemInfo,\n '',\n '--- Config (secrets redacted) ---',\n redactConfig(),\n '',\n `--- Debug log (last ${DEBUG_LOG_TAIL_LINES} lines) ---`,\n tailFile(DEBUG_LOG_PATH, DEBUG_LOG_TAIL_LINES),\n ].join('\\n')\n\n try {\n if (!fs.existsSync(WORKSCRIBE_DIR)) {\n fs.mkdirSync(WORKSCRIBE_DIR, { recursive: true, mode: 0o700 })\n }\n fs.writeFileSync(reportPath, report, { mode: 0o600 })\n } catch (error) {\n log.error(`Could not write report: ${(error as Error).message}`)\n process.exit(1)\n }\n\n const params = new URLSearchParams({\n title: `Bug report — workscribe ${__WORKSCRIBE_VERSION__}`,\n body: `<!-- Attach ${path.basename(reportPath)} or paste the relevant sections below -->\\n\\n**Describe the issue:**\\n\\n**Steps to reproduce:**\\n\\n**Expected behaviour:**`,\n })\n\n log.success(`Report written to: ${chalk.cyan(reportPath)}`)\n log.plain('')\n log.plain(` Open a GitHub issue:`)\n log.plain(` ${chalk.cyan(`${GITHUB_ISSUES_URL}?${params}`)}`)\n log.plain('')\n log.plain(chalk.dim(` Attach the report or paste the relevant sections into the issue.`))\n log.plain('')\n })\n}\n","import { Command } from 'commander'\nimport chalk from 'chalk'\nimport { getPendingAlerts, clearAlerts, hasPendingAlerts } from '../db/alerts'\nimport { log } from '../utils/logger'\n\nfunction formatTimestamp(ms: number): string {\n return new Date(ms).toLocaleString([], {\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n })\n}\n\nexport function registerAlerts(program: Command): void {\n const alertsCmd = program\n .command('alerts')\n .description('Show and manage security alerts from AI session monitoring')\n .option('--check', 'Print warning if alerts are pending (used by shell hooks)')\n .action((opts: { check?: boolean }) => {\n if (opts.check) {\n if (hasPendingAlerts()) {\n log.plain(\n chalk.yellow(' [workscribe] Possible credentials detected in an AI session.') +\n chalk.dim(' Run workscribe alerts for details.')\n )\n }\n return\n }\n\n const alerts = getPendingAlerts()\n if (alerts.length === 0) {\n log.plain('')\n log.plain(' No pending security alerts.')\n log.plain('')\n return\n }\n\n log.plain('')\n log.plain(chalk.bold(' Security Alerts') + chalk.dim(` (${alerts.length} pending)`))\n log.plain('')\n\n for (const alert of alerts) {\n log.plain(` ${chalk.yellow('!')} ${chalk.dim(formatTimestamp(alert.created_at))} ${chalk.cyan(alert.tool)}`)\n log.plain(` ${alert.context}`)\n if (alert.session_id) log.plain(` ${chalk.dim('Session: ' + alert.session_id)}`)\n log.plain('')\n }\n\n log.plain(chalk.dim(' Run workscribe alerts clear to dismiss all alerts'))\n log.plain('')\n })\n\n alertsCmd\n .command('clear')\n .description('Dismiss all pending security alerts')\n .action(() => {\n const count = clearAlerts()\n if (count === 0) {\n log.plain(' No pending alerts to clear.')\n } else {\n log.plain(` ${count} alert${count === 1 ? '' : 's'} cleared.`)\n }\n })\n}\n","import path from 'path'\nimport { Command } from 'commander'\nimport chalk from 'chalk'\nimport { getRecentSessionsByRepo, getLastSessionTouchingFile, getSessionBranch } from '../db'\nimport { getGitContext } from '../capture/git'\nimport { readConfig } from '../config'\nimport { formatDuration, timeAgo } from '../utils/format'\nimport { log } from '../utils/logger'\nimport type { SessionRow } from '../db/types'\n\nexport interface SessionContextJson {\n date: string\n startedAt: string\n endedAt: string\n timeAgo: string\n durationMinutes: number\n branch: string | null\n eventCount: number\n summary: string | null\n}\n\nfunction toContextJson(session: SessionRow): SessionContextJson {\n return {\n date: session.date,\n startedAt: session.started_at,\n endedAt: session.ended_at,\n timeAgo: timeAgo(session.started_at),\n durationMinutes: (new Date(session.ended_at).getTime() - new Date(session.started_at).getTime()) / 60000,\n branch: getSessionBranch(session.id),\n eventCount: session.event_count,\n summary: session.summary,\n }\n}\n\nfunction printSessionContext(session: SessionRow, heading: string): void {\n const ago = timeAgo(session.started_at)\n const branch = getSessionBranch(session.id)\n const durationMinutes = (new Date(session.ended_at).getTime() - new Date(session.started_at).getTime()) / 60000\n\n log.plain('')\n log.plain(` ${chalk.bold(heading)}: ${chalk.cyan(ago)}`)\n log.plain('')\n log.plain(` Date ${session.date}`)\n log.plain(` Duration ${formatDuration(durationMinutes)}`)\n if (branch) log.plain(` Branch ${chalk.dim(branch)}`)\n log.plain(` Events ${session.event_count}`)\n\n if (session.summary) {\n log.plain('')\n for (const line of session.summary.split('\\n')) {\n log.plain(` ${line}`)\n }\n } else {\n log.plain('')\n log.plain(chalk.dim(` No summary — run: workscribe summary ${session.date}`))\n }\n\n log.plain('')\n}\n\nexport function registerContext(program: Command): void {\n program\n .command('context')\n .description('Show the last session for the current repo')\n .option('--file <path>', 'narrow to last session that touched this file')\n .option('--json', 'output as JSON instead of formatted text — null when no session is found')\n .action((opts) => {\n if (opts.file) {\n const normalizedFile = path.normalize(opts.file)\n const session = getLastSessionTouchingFile(normalizedFile)\n if (!session) {\n if (opts.json) log.plain(JSON.stringify(null))\n else log.plain(` No sessions found touching ${normalizedFile}`)\n return\n }\n if (opts.json) {\n log.plain(JSON.stringify(toContextJson(session)))\n return\n }\n printSessionContext(session, `Last session touching ${path.basename(normalizedFile)}`)\n return\n }\n\n const { repoName } = getGitContext(process.cwd(), null, readConfig().git.qualifyRepoName)\n if (!repoName) {\n if (opts.json) log.plain(JSON.stringify(null))\n else log.plain(' Not in a git repository. Run workscribe context from a project directory.')\n return\n }\n\n const sessions = getRecentSessionsByRepo(repoName, 1)\n if (sessions.length === 0) {\n if (opts.json) log.plain(JSON.stringify(null))\n else log.plain(` No sessions found for ${repoName}`)\n return\n }\n\n if (opts.json) {\n log.plain(JSON.stringify(toContextJson(sessions[0])))\n return\n }\n printSessionContext(sessions[0], `Last session on ${repoName}`)\n })\n}\n","import fs from 'fs'\nimport { UPDATE_CHECK_PATH } from './paths'\n\ndeclare const __WORKSCRIBE_VERSION__: string\n\nconst CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000\n\ninterface UpdateCache {\n lastChecked: number\n latestVersion: string\n}\n\nfunction readCache(): UpdateCache | null {\n try {\n return JSON.parse(fs.readFileSync(UPDATE_CHECK_PATH, 'utf-8')) as UpdateCache\n } catch {\n return null\n }\n}\n\nfunction writeCache(cache: UpdateCache): void {\n try {\n fs.writeFileSync(UPDATE_CHECK_PATH, JSON.stringify(cache), { mode: 0o600 })\n } catch {\n // Not critical — silently skip if the data dir doesn't exist yet\n }\n}\n\nfunction isNewer(latest: string, current: string): boolean {\n const parse = (version: string) => version.replace(/^v/, '').split('.').map(Number)\n const [latestMajor, latestMinor, latestPatch] = parse(latest)\n const [currentMajor, currentMinor, currentPatch] = parse(current)\n if (latestMajor !== currentMajor) return latestMajor > currentMajor\n if (latestMinor !== currentMinor) return latestMinor > currentMinor\n return latestPatch > currentPatch\n}\n\nexport function checkForUpdate(): void {\n const current = __WORKSCRIBE_VERSION__\n const cache = readCache()\n\n if (cache && isNewer(cache.latestVersion, current)) {\n process.stderr.write(\n `\\n Update available ${current} → ${cache.latestVersion}\\n Run: npm install -g @workscribe/cli\\n\\n`\n )\n }\n\n const now = Date.now()\n if (!cache || now - cache.lastChecked > CHECK_INTERVAL_MS) {\n fetch('https://registry.npmjs.org/@workscribe/cli/latest')\n .then((response) => response.json())\n .then((data: unknown) => {\n const latest = (data as { version?: string }).version\n if (latest) writeCache({ lastChecked: now, latestVersion: latest })\n })\n .catch(() => {\n // Network unavailable — will retry next run\n })\n }\n}\n"],"mappings":"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","names":["import_fs","import_fs","path","os","fs","migration","migration","fs","migration","import_path","import_fs","fs","path","import_child_process","import_fs","import_path","path","fs","import_fs","import_os","import_path","import_fs","chalk","fs","path","os","fs","import_fs","import_path","import_fs","fs","import_fs","import_path","path","fs","path","fs","fs","path","fs","command","nameOverride","repoName","branch","program","import_fs","import_path","fs","path","program","parsed","import_fs","import_path","import_os","import_chalk","import_fs","import_path","import_os","import_child_process","path","os","fs","import_fs","import_path","import_os","import_child_process","path","os","fs","program","path","os","chalk","program","fs","prompts","import_fs","import_chalk","program","fs","chalk","import_chalk","chalk","program","import_chalk","program","chalk","import_chalk","import_fs","import_os","import_path","os","program","sessions","path","fs","chalk","fullSummary","import_fs","import_path","eventRowToPayload","program","path","fs","import_chalk","program","chalk","import_fs","program","fs","program","import_chalk","import_prompts","program","chalk","prompts","import_fs","import_path","import_os","import_prompts","import_chalk","path","os","fs","program","chalk","prompts","import_fs","import_path","import_chalk","program","chalk","fs","path","program","import_chalk","import_fs","import_path","import_os","eventRowToPayload","sessionToPayload","os","program","path","fs","chalk","import_fs","import_os","import_path","import_chalk","fs","program","path","os","chalk","import_chalk","program","chalk","import_path","import_chalk","chalk","program","path","import_fs","fs"]}
1
+ {"version":3,"sources":["../src/utils/paths.ts","../src/db/migrations/001_initial_schema.ts","../src/db/migrations/002_semantic_categories.ts","../src/db/migrations/003_alerts.ts","../src/db/migrations/004_ide_columns.ts","../src/db/migrations/index.ts","../src/db/index.ts","../src/capture/redact.ts","../src/capture/git.ts","../src/capture/git-snapshot.ts","../src/capture/aider.ts","../src/config/ai-tools.json","../src/utils/logger.ts","../src/config/registry.ts","../src/config/index.ts","../src/profiles/schema.ts","../src/utils/fetch.ts","../src/profiles/fetcher.ts","../src/profiles/loader.ts","../src/normalize/patterns.ts","../src/capture/filter.ts","../src/capture/ide.ts","../src/capture/index.ts","../src/cli/capture.ts","../src/capture/detect-secrets.ts","../src/db/alerts.ts","../src/cli/hook.ts","../src/utils/format.ts","../src/ai/prompt.ts","../src/ai/generic-provider.ts","../src/ai/provider-config.ts","../src/ai/router.ts","../src/utils/completion-scripts.ts","../src/capture/shell-hook.ts","../src/capture/hooks/utils.ts","../src/capture/hooks/claude-code.ts","../src/capture/hooks/index.ts","../src/cli/completions.ts","../src/cli/init.ts","../src/cli/status.ts","../src/cli/events.ts","../src/sessions/grouper.ts","../src/sessions/detector.ts","../src/cli/sessions.ts","../src/integrations/webhook.ts","../src/integrations/slack.ts","../src/cli/summary.ts","../src/cli/export.ts","../src/cli/config.ts","../src/cli/pause.ts","../src/cli/undo.ts","../src/cli/clear.ts","../src/cli/uninstall.ts","../src/cli/profile.ts","../src/cli/note.ts","../src/cli/week.ts","../src/cli/bug-report.ts","../src/cli/alerts.ts","../src/cli/context.ts","../src/utils/update-check.ts","../src/main.ts","../src/utils/node-version.ts","../src/index.ts"],"sourcesContent":["import path from 'path'\nimport os from 'os'\nimport fs from 'fs'\n\nconst LEGACY_DIR = path.join(os.homedir(), '.workscribe')\n\n// Existing installs keep ~/.workscribe/ — fresh installs use XDG Base Directory spec\nconst USE_XDG = !fs.existsSync(LEGACY_DIR)\n\nconst xdgDataDir = USE_XDG\n ? path.join(process.env.XDG_DATA_HOME ?? path.join(os.homedir(), '.local', 'share'), 'workscribe')\n : LEGACY_DIR\n\nconst xdgConfigDir = USE_XDG\n ? path.join(process.env.XDG_CONFIG_HOME ?? path.join(os.homedir(), '.config'), 'workscribe')\n : LEGACY_DIR\n\nconst xdgStateDir = USE_XDG\n ? path.join(process.env.XDG_STATE_HOME ?? path.join(os.homedir(), '.local', 'state'), 'workscribe')\n : LEGACY_DIR\n\n// All directories that must exist for Workscribe to function (deduplicated for legacy installs).\n// LEGACY_DIR (~/.workscribe) is always included so the alerts signal file has a predictable\n// location that shell hooks can check without knowing the XDG paths.\nexport const REQUIRED_DIRS: string[] = [...new Set([xdgDataDir, xdgConfigDir, xdgStateDir, LEGACY_DIR])]\n\nexport const WORKSCRIBE_DIR = xdgDataDir\nexport const DB_PATH = path.join(xdgDataDir, 'workscribe.db')\nexport const CONFIG_PATH = path.join(xdgConfigDir, 'config.json')\nexport const DEBUG_LOG_PATH = path.join(xdgStateDir, 'debug.log')\nexport const UPDATE_CHECK_PATH = path.join(xdgStateDir, 'update-check.json')\nexport const EXPORTS_DIR = path.join(xdgDataDir, 'exports')\nexport const PAUSE_FLAG_PATH = path.join(xdgStateDir, 'paused')\nexport const WEEKLY_CACHE_DIR = path.join(xdgDataDir, 'weekly-cache')\nexport const PROFILES_DIR = path.join(xdgDataDir, 'profiles')\n// Fixed at ~/.workscribe/alerts.pending so shell hooks can check it without knowing XDG paths.\n// Content is irrelevant — its presence signals pending alerts.\nexport const ALERTS_PENDING_PATH = path.join(LEGACY_DIR, 'alerts.pending')\n","export default {\n version: 1,\n description: 'initial schema',\n sql: `\n CREATE TABLE IF NOT EXISTS events (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n captured_at TEXT NOT NULL,\n command TEXT NOT NULL,\n cwd TEXT NOT NULL,\n exit_code INTEGER,\n duration_ms INTEGER,\n repo_name TEXT,\n branch TEXT,\n category TEXT NOT NULL DEFAULT 'other',\n metadata TEXT\n );\n\n CREATE INDEX IF NOT EXISTS idx_events_captured_at ON events(captured_at);\n CREATE INDEX IF NOT EXISTS idx_events_repo_name ON events(repo_name);\n\n CREATE TABLE IF NOT EXISTS sessions (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n date TEXT NOT NULL,\n started_at TEXT NOT NULL,\n ended_at TEXT NOT NULL,\n repo_name TEXT,\n event_count INTEGER NOT NULL DEFAULT 0,\n summary TEXT\n );\n\n CREATE INDEX IF NOT EXISTS idx_sessions_date ON sessions(date);\n\n CREATE TABLE IF NOT EXISTS session_events (\n session_id INTEGER NOT NULL REFERENCES sessions(id),\n event_id INTEGER NOT NULL REFERENCES events(id),\n PRIMARY KEY (session_id, event_id)\n );\n `,\n}\n","const migration = {\n version: 2,\n description: 'Rename granular categories to 13 universal semantic categories',\n sql: `\n UPDATE events SET category = 'shipping' WHERE category IN ('code_commit','code_push','code_merge');\n UPDATE events SET category = 'versioning' WHERE category IN ('code_pull','branch_switch','code_stash','git_other');\n UPDATE events SET category = 'building' WHERE category = 'build';\n UPDATE events SET category = 'running' WHERE category IN ('server_run','script_run');\n UPDATE events SET category = 'testing' WHERE category = 'test_run';\n UPDATE events SET category = 'linting' WHERE category = 'lint_run';\n UPDATE events SET category = 'dependencies' WHERE category IN ('dependency_install','dependency_remove');\n UPDATE events SET category = 'infrastructure' WHERE category = 'infrastructure';\n UPDATE events SET category = 'files' WHERE category IN ('file_ops','environment');\n UPDATE events SET category = 'exploring' WHERE category IN ('code_search','code_read');\n `,\n}\n\nexport default migration\n","const migration = {\n version: 3,\n description: 'Add alerts table for AI session secret detection',\n sql: `\n CREATE TABLE IF NOT EXISTS alerts (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n created_at INTEGER NOT NULL,\n tool TEXT NOT NULL,\n session_id TEXT,\n context TEXT NOT NULL,\n cleared INTEGER NOT NULL DEFAULT 0\n );\n CREATE INDEX IF NOT EXISTS alerts_cleared ON alerts (cleared);\n `,\n}\n\nexport default migration\n","const migration = {\n version: 4,\n description: 'Add source and file_path columns to events for IDE integration',\n sql: `\n ALTER TABLE events ADD COLUMN source TEXT;\n ALTER TABLE events ADD COLUMN file_path TEXT;\n CREATE INDEX IF NOT EXISTS idx_events_file_path ON events (file_path, cwd);\n `,\n}\n\nexport default migration\n","import initialSchema from './001_initial_schema'\nimport semanticCategories from './002_semantic_categories'\nimport alerts from './003_alerts'\nimport ideColumns from './004_ide_columns'\n\nexport interface Migration {\n version: number\n description: string\n sql: string\n}\n\n// Ordered list — append only. Never modify or remove an existing entry.\nexport const MIGRATIONS: Migration[] = [initialSchema, semanticCategories, alerts, ideColumns]\n","import { DatabaseSync } from 'node:sqlite'\nimport fs from 'fs'\nimport { WORKSCRIBE_DIR, DB_PATH } from '../utils/paths'\nimport type { EventRow, SessionRow } from './types'\nimport { MIGRATIONS } from './migrations'\nexport type { EventRow, SessionRow } from './types'\n\nlet _db: DatabaseSync | null = null\n\nexport function getDb(): DatabaseSync {\n if (_db) return _db\n\n // Ensure ~/.workscribe/ exists\n if (!fs.existsSync(WORKSCRIBE_DIR)) {\n fs.mkdirSync(WORKSCRIBE_DIR, { recursive: true })\n }\n\n // Don't assign to _db until after migrations succeed — if applyMigrations\n // throws, _db stays null so the next call retries cleanly instead of\n // returning a partially-initialised singleton.\n const db = new DatabaseSync(DB_PATH)\n try {\n fs.chmodSync(DB_PATH, 0o600)\n } catch {\n /* ignore if already correct */\n }\n db.exec('PRAGMA journal_mode = WAL')\n db.exec('PRAGMA foreign_keys = ON')\n applyMigrations(db)\n _db = db\n return _db\n}\n\nfunction applyMigrations(db: DatabaseSync): void {\n // Create the migration tracking table if this is the first run\n db.exec(`\n CREATE TABLE IF NOT EXISTS schema_migrations (\n version INTEGER PRIMARY KEY,\n applied_at TEXT NOT NULL DEFAULT (datetime('now'))\n )\n `)\n\n // Bootstrap: if the events table already exists but schema_migrations is\n // empty, this is an existing install that predates the migration system.\n // Seed version 1 as applied so we don't re-run the initial schema.\n const hasEvents = db.prepare(\"SELECT name FROM sqlite_master WHERE type='table' AND name='events'\").get()\n const hasVersion1 = db.prepare('SELECT version FROM schema_migrations WHERE version = 1').get()\n\n if (hasEvents && !hasVersion1) {\n db.prepare(\"INSERT INTO schema_migrations (version, applied_at) VALUES ($version, datetime('now'))\").run({\n version: 1,\n })\n }\n\n // Collect already-applied versions\n const applied = new Set(\n (db.prepare('SELECT version FROM schema_migrations').all() as { version: number }[]).map((row) => row.version)\n )\n\n // Apply each pending migration in order, wrapped in a transaction so a\n // partial failure leaves the DB cleanly at the previous version.\n for (const migration of MIGRATIONS) {\n if (applied.has(migration.version)) continue\n\n db.exec('BEGIN')\n try {\n db.exec(migration.sql)\n db.prepare(\"INSERT INTO schema_migrations (version, applied_at) VALUES ($version, datetime('now'))\").run({\n version: migration.version,\n })\n db.exec('COMMIT')\n } catch (err) {\n try {\n db.exec('ROLLBACK')\n } catch {\n /* already rolled back or connection lost */\n }\n throw new Error(`Migration ${migration.version} (${migration.description}) failed: ${(err as Error).message}`)\n }\n }\n}\n\n// ─── Typed query helpers ──────────────────────────────────────────────────────\n\nexport function insertEvent(params: {\n captured_at: string\n command: string\n cwd: string\n exit_code: number | null\n duration_ms: number | null\n repo_name: string | null\n branch: string | null\n category: string\n metadata: string | null\n source: string | null\n file_path: string | null\n}): void {\n const db = getDb()\n const stmt = db.prepare(`\n INSERT INTO events (captured_at, command, cwd, exit_code, duration_ms, repo_name, branch, category, metadata, source, file_path)\n VALUES ($captured_at, $command, $cwd, $exit_code, $duration_ms, $repo_name, $branch, $category, $metadata, $source, $file_path)\n `)\n stmt.run(params)\n}\n\nexport function getRecentSessionsByRepo(repoName: string, limit: number): SessionRow[] {\n const db = getDb()\n return db\n .prepare('SELECT * FROM sessions WHERE repo_name = $repo_name ORDER BY started_at DESC LIMIT $limit')\n .all({ repo_name: repoName, limit }) as unknown as SessionRow[]\n}\n\nexport function getLastSessionTouchingFile(filePath: string): SessionRow | undefined {\n const db = getDb()\n return db\n .prepare(\n `SELECT s.* FROM sessions s\n INNER JOIN session_events se ON se.session_id = s.id\n INNER JOIN events e ON e.id = se.event_id\n WHERE e.file_path = $file_path\n ORDER BY s.started_at DESC\n LIMIT 1`\n )\n .get({ file_path: filePath }) as SessionRow | undefined\n}\n\nexport function getSessionBranch(sessionId: number): string | null {\n const db = getDb()\n const row = db\n .prepare(\n `SELECT e.branch FROM events e\n INNER JOIN session_events se ON se.event_id = e.id\n WHERE se.session_id = $session_id AND e.branch IS NOT NULL\n ORDER BY e.captured_at DESC\n LIMIT 1`\n )\n .get({ session_id: sessionId }) as { branch: string } | undefined\n return row?.branch ?? null\n}\n\nexport function getLastEventForFile(filePath: string, cwd: string): EventRow | undefined {\n const db = getDb()\n return db\n .prepare('SELECT * FROM events WHERE file_path = $file_path AND cwd = $cwd ORDER BY id DESC LIMIT 1')\n .get({ file_path: filePath, cwd }) as EventRow | undefined\n}\n\nexport function getLastEvent(): EventRow | undefined {\n const db = getDb()\n const stmt = db.prepare('SELECT * FROM events ORDER BY id DESC LIMIT 1')\n return stmt.get() as EventRow | undefined\n}\n\nexport function getEventsForDate(date: string): EventRow[] {\n const db = getDb()\n const stmt = db.prepare(`\n SELECT * FROM events\n WHERE date(captured_at, 'localtime') = $date\n ORDER BY captured_at ASC\n `)\n return stmt.all({ date }) as unknown as EventRow[]\n}\n\nexport function getRecentEvents(limit = 20): EventRow[] {\n const db = getDb()\n const stmt = db.prepare('SELECT * FROM events ORDER BY captured_at DESC LIMIT $limit')\n return stmt.all({ limit }) as unknown as EventRow[]\n}\n\nexport function getEventCount(): number {\n const db = getDb()\n const stmt = db.prepare('SELECT COUNT(*) as count FROM events')\n const row = stmt.get() as { count: number }\n return row.count\n}\n\nexport function insertSession(params: {\n date: string\n started_at: string\n ended_at: string\n repo_name: string | null\n event_count: number\n summary: string | null\n}): number {\n const db = getDb()\n const stmt = db.prepare(`\n INSERT INTO sessions (date, started_at, ended_at, repo_name, event_count, summary)\n VALUES ($date, $started_at, $ended_at, $repo_name, $event_count, $summary)\n `)\n const result = stmt.run(params)\n return Number(result.lastInsertRowid)\n}\n\nexport function insertSessionEvent(sessionId: number, eventId: number): void {\n const db = getDb()\n const stmt = db.prepare(`\n INSERT OR IGNORE INTO session_events (session_id, event_id) VALUES ($session_id, $event_id)\n `)\n stmt.run({ session_id: sessionId, event_id: eventId })\n}\n\nexport function getEventsBySessionId(sessionId: number): EventRow[] {\n const db = getDb()\n const stmt = db.prepare(`\n SELECT e.* FROM events e\n INNER JOIN session_events se ON se.event_id = e.id\n WHERE se.session_id = $session_id\n ORDER BY e.captured_at ASC\n `)\n return stmt.all({ session_id: sessionId }) as unknown as EventRow[]\n}\n\nexport function getSessionsForDate(date: string): SessionRow[] {\n const db = getDb()\n const stmt = db.prepare('SELECT * FROM sessions WHERE date = $date ORDER BY started_at ASC')\n return stmt.all({ date }) as unknown as SessionRow[]\n}\n\nexport function updateSessionSummary(sessionId: number, summary: string): void {\n const db = getDb()\n const stmt = db.prepare('UPDATE sessions SET summary = $summary WHERE id = $id')\n stmt.run({ summary, id: sessionId })\n}\n\nexport function getLastEventIds(n: number): number[] {\n const db = getDb()\n const rows = db.prepare('SELECT id FROM events ORDER BY id DESC LIMIT $n').all({ n }) as { id: number }[]\n return rows.map((row) => row.id)\n}\n\nexport function getEventsByIds(ids: number[]): EventRow[] {\n if (ids.length === 0) return []\n const db = getDb()\n const placeholders = ids.map(() => '?').join(', ')\n return db\n .prepare(`SELECT * FROM events WHERE id IN (${placeholders}) ORDER BY id DESC`)\n .all(...ids) as unknown as EventRow[]\n}\n\nexport function deleteEventsByIds(ids: number[]): void {\n if (ids.length === 0) return\n const db = getDb()\n const placeholders = ids.map(() => '?').join(', ')\n\n const affectedDates = db\n .prepare(`SELECT DISTINCT date(captured_at, 'localtime') as date FROM events WHERE id IN (${placeholders})`)\n .all(...ids) as { date: string }[]\n\n db.prepare(`DELETE FROM events WHERE id IN (${placeholders})`).run(...ids)\n\n for (const { date } of affectedDates) {\n clearSessionsForDate(date)\n }\n}\n\nexport function deleteEventsForDate(date: string): number {\n const db = getDb()\n // Clear sessions (and session_events) before deleting events — FK constraint order\n clearSessionsForDate(date)\n const result = db.prepare(`DELETE FROM events WHERE date(captured_at, 'localtime') = $date`).run({ date }) as {\n changes: number\n }\n return result.changes\n}\n\nexport function getOtherEventToolCounts(days: number): { tool: string; count: number }[] {\n const db = getDb()\n return db\n .prepare(\n `SELECT json_extract(metadata, '$.tool') as tool, COUNT(*) as count\n FROM events\n WHERE category = 'other'\n AND captured_at >= datetime('now', $offset)\n AND json_extract(metadata, '$.tool') IS NOT NULL\n GROUP BY tool\n ORDER BY count DESC`\n )\n .all({ offset: `-${days} days` }) as { tool: string; count: number }[]\n}\n\nexport function getRecentOtherRate(days: number): { total: number; otherCount: number } {\n const db = getDb()\n const row = db\n .prepare(\n `SELECT COUNT(*) as total,\n SUM(CASE WHEN category = 'other' THEN 1 ELSE 0 END) as otherCount\n FROM events\n WHERE captured_at >= datetime('now', $offset)`\n )\n .get({ offset: `-${days} days` }) as { total: number; otherCount: number }\n return row\n}\n\nexport function clearSessionsForDate(date: string): void {\n const db = getDb()\n // Remove session_events first due to FK constraint\n db.prepare(\n `\n DELETE FROM session_events WHERE session_id IN (\n SELECT id FROM sessions WHERE date = $date\n )\n `\n ).run({ date })\n db.prepare('DELETE FROM sessions WHERE date = $date').run({ date })\n}\n","// Patterns that match known sensitive values\nconst BUILTIN_PATTERNS: RegExp[] = [\n // AWS access keys\n /AKIA[0-9A-Z]{16}/g,\n // AWS secret access keys (40 char base64-ish after common env vars)\n /(?<=AWS_SECRET_ACCESS_KEY[=\\s]+)\\S+/gi,\n // GitHub tokens\n /ghp_[a-zA-Z0-9]{36}/g,\n /github_pat_[a-zA-Z0-9_]{82}/g,\n // GitLab tokens\n /glpat-[a-zA-Z0-9\\-]{20}/g,\n // Generic JWTs (three base64url segments)\n /eyJ[a-zA-Z0-9_-]+\\.eyJ[a-zA-Z0-9_-]+\\.[a-zA-Z0-9_-]+/g,\n // Slack tokens and incoming webhook URLs\n /xox[baprs]-[a-zA-Z0-9\\-]+/g,\n /https:\\/\\/hooks\\.slack\\.com\\/services\\/[A-Z0-9]+\\/[A-Z0-9]+\\/[a-zA-Z0-9]+/g,\n // Stripe keys\n /sk_(live|test)_[a-zA-Z0-9]{24,}/g,\n // Values after long-form secret flags (single-char flags like -t/-p/-k are too ambiguous)\n /(?<=--(password|passwd|secret|token|key|api[-_]?key|auth[-_]?token)\\s+)\\S+/gi,\n // export VAR=VALUE where VAR looks sensitive\n /(?<=export\\s+(?:[A-Z_]*(?:TOKEN|SECRET|KEY|PASSWORD|PASS|AUTH|CREDENTIAL)[A-Z_]*)=)\\S+/gi,\n // Inline assignment: VAR_WITH_SENSITIVE_KEYWORD=value cmd (e.g. API_KEY=secret npm start)\n // Lookbehind matches only the variable-name= prefix, so only the value is replaced\n /(?<=[A-Z_][A-Z0-9_]*(?:TOKEN|SECRET|KEY|PASSWORD|PASS|AUTH|CREDENTIAL)[A-Z0-9_]*=)\\S+/gi,\n // Credentials embedded in connection string URLs (e.g. DATABASE_URL=postgres://user:pass@host/db)\n // Matches the password segment between :// user : password @ — preserves scheme and host\n /(?<=[a-zA-Z][a-zA-Z0-9+.-]*:\\/\\/[^:@\\s/]+:)[^@\\s]+(?=@)/g,\n]\n\nexport function redact(command: string, extraPatterns: string[] = []): string {\n let result = command\n\n const allPatterns = [...BUILTIN_PATTERNS]\n\n for (const pattern of extraPatterns) {\n try {\n allPatterns.push(new RegExp(pattern, 'g'))\n } catch {\n // Invalid regex — skip silently\n }\n }\n\n for (const pattern of allPatterns) {\n // Reset lastIndex for global regexes\n pattern.lastIndex = 0\n result = result.replace(pattern, '[REDACTED]')\n }\n\n return result\n}\n","import { execSync } from 'child_process'\nimport path from 'path'\nimport fs from 'fs'\n\nexport interface GitContext {\n repoName: string | null\n branch: string | null\n}\n\n// Handles SSH (git@host:owner/repo.git), HTTPS (https://host/owner/repo.git),\n// and bare git:// / ssh:// forms uniformly by normalizing the SSH scp-like\n// syntax's first ':' to '/' (but not the '://' in URLs with a real scheme),\n// then splitting on '/'.\nfunction parseOwnerAndRepo(url: string): { owner: string; repo: string } | null {\n const normalized = url.trim().replace(/^[^/]+:(?!\\/\\/)/, (match) => match.replace(':', '/'))\n const segments = normalized.split('/').filter(Boolean)\n if (segments.length < 2) return null\n const repo = segments[segments.length - 1].replace(/\\.git$/, '')\n const owner = segments[segments.length - 2]\n return owner && repo ? { owner, repo } : null\n}\n\nfunction nameFromRemote(root: string, qualifyWithOwner: boolean): string | null {\n try {\n const url = execSync('git remote get-url origin', {\n cwd: root,\n timeout: 2000,\n stdio: 'pipe',\n })\n .toString()\n .trim()\n const parsed = parseOwnerAndRepo(url)\n if (!parsed) return null\n return qualifyWithOwner ? `${parsed.owner}/${parsed.repo}` : parsed.repo\n } catch {\n return null\n }\n}\n\nfunction nameFromPackageJson(root: string): string | null {\n try {\n const raw = fs.readFileSync(path.join(root, 'package.json'), 'utf-8')\n const pkg = JSON.parse(raw) as { name?: string }\n if (!pkg.name) return null\n return pkg.name.replace(/^@[^/]+\\//, '')\n } catch {\n return null\n }\n}\n\nexport function getGitContext(cwd: string, nameOverride?: string | null, qualifyRepoName = false): GitContext {\n try {\n const root = execSync('git rev-parse --show-toplevel', {\n cwd,\n timeout: 2000,\n stdio: 'pipe',\n })\n .toString()\n .trim()\n\n const repoName =\n nameOverride ?? nameFromRemote(root, qualifyRepoName) ?? nameFromPackageJson(root) ?? path.basename(root)\n\n let branch: string | null = null\n try {\n branch =\n execSync('git branch --show-current', {\n cwd,\n timeout: 2000,\n stdio: 'pipe',\n })\n .toString()\n .trim() || null\n } catch {\n // Detached HEAD or not a git repo\n }\n\n return { repoName, branch }\n } catch {\n return { repoName: null, branch: null }\n }\n}\n","import { execSync } from 'child_process'\n\n/**\n * Returns commit subject lines for all commits made between `sha` and HEAD.\n * Returns an empty array if sha is empty, HEAD hasn't moved, or git fails.\n */\nexport function getCommitsSince(sha: string, cwd: string): string[] {\n if (!sha) return []\n try {\n const out = execSync(`git log ${sha}..HEAD --format=%s`, { cwd, timeout: 3000 }).toString().trim()\n return out ? out.split('\\n').filter(Boolean) : []\n } catch {\n return []\n }\n}\n","import fs from 'fs'\nimport path from 'path'\n\nconst HISTORY_FILE = '.aider.chat.history.md'\nconst PROMPT_MAX_LENGTH = 200\n\nexport function readLastAiderPrompt(cwd: string): string | null {\n try {\n const histPath = path.join(cwd, HISTORY_FILE)\n const content = fs.readFileSync(histPath, 'utf-8')\n const matches = [...content.matchAll(/^#### (.+)$/gm)]\n if (!matches.length) return null\n return matches[matches.length - 1][1].trim().slice(0, PROMPT_MAX_LENGTH)\n } catch {\n return null\n }\n}\n","[\n {\n \"tool\": \"claude\",\n \"displayName\": \"Claude Code\",\n \"pattern\": \"^claude\\\\b\",\n \"hook\": \"claude-code\",\n \"contextSource\": \"hook\",\n \"historyFormat\": null,\n \"securityWarning\": null\n },\n {\n \"tool\": \"aider\",\n \"displayName\": \"Aider\",\n \"pattern\": \"^aider\\\\b\",\n \"hook\": null,\n \"contextSource\": \"history-file\",\n \"historyFormat\": \"markdown\",\n \"securityWarning\": null\n },\n {\n \"tool\": \"codex\",\n \"displayName\": \"Codex CLI\",\n \"pattern\": \"^codex\\\\b\",\n \"hook\": null,\n \"contextSource\": \"history-file\",\n \"historyFormat\": \"jsonl\",\n \"securityWarning\": null\n },\n {\n \"tool\": \"gemini\",\n \"displayName\": \"Gemini CLI\",\n \"pattern\": \"^gemini\\\\b\",\n \"hook\": null,\n \"contextSource\": \"history-file\",\n \"historyFormat\": \"json\",\n \"securityWarning\": null\n },\n {\n \"tool\": \"gh copilot\",\n \"displayName\": \"GitHub Copilot\",\n \"pattern\": \"^gh\\\\s+copilot\\\\b\",\n \"hook\": null,\n \"contextSource\": \"history-file\",\n \"historyFormat\": \"jsonl\",\n \"securityWarning\": null\n },\n {\n \"tool\": \"amazon-q\",\n \"displayName\": \"Amazon Q\",\n \"pattern\": \"^q\\\\s+(chat|dev)\\\\b\",\n \"hook\": null,\n \"contextSource\": \"history-file\",\n \"historyFormat\": \"json\",\n \"securityWarning\": null\n },\n {\n \"tool\": \"opencode\",\n \"displayName\": \"OpenCode\",\n \"pattern\": \"^opencode\\\\b\",\n \"hook\": null,\n \"contextSource\": \"sqlite\",\n \"historyFormat\": \"sqlite\",\n \"securityWarning\": null\n },\n {\n \"tool\": \"kilo\",\n \"displayName\": \"Kilo Code\",\n \"pattern\": \"^kilo\\\\b\",\n \"hook\": null,\n \"contextSource\": null,\n \"historyFormat\": null,\n \"securityWarning\": null\n },\n {\n \"tool\": \"grok\",\n \"displayName\": \"Grok Build\",\n \"pattern\": \"^grok\\\\b\",\n \"hook\": null,\n \"contextSource\": null,\n \"historyFormat\": null,\n \"securityWarning\": \"Grok Build was found to silently upload entire local git repositories — including .env files and untracked secrets — to Google Cloud Storage without user disclosure (July 2026 incident). Workscribe does not read Grok Build session files. Consider whether this tool is appropriate for use in repositories containing sensitive credentials.\"\n },\n {\n \"tool\": \"continue\",\n \"displayName\": \"Continue\",\n \"pattern\": \"^continue\\\\b\",\n \"hook\": null,\n \"contextSource\": null,\n \"historyFormat\": null,\n \"securityWarning\": null\n },\n {\n \"tool\": \"cody\",\n \"displayName\": \"Cody\",\n \"pattern\": \"^cody\\\\b\",\n \"hook\": null,\n \"contextSource\": null,\n \"historyFormat\": null,\n \"securityWarning\": null\n },\n {\n \"tool\": \"cursor\",\n \"displayName\": \"Cursor\",\n \"pattern\": \"^cursor\\\\b\",\n \"hook\": null,\n \"contextSource\": null,\n \"historyFormat\": null,\n \"securityWarning\": null\n }\n]\n","import chalk from 'chalk'\nimport fs from 'fs'\nimport { DEBUG_LOG_PATH } from './paths'\n\nconst isDebug = process.env.WORKSCRIBE_DEBUG === '1'\n\nexport const log = {\n info: (msg: string) => console.log(chalk.cyan('→'), msg),\n success: (msg: string) => console.log(chalk.green('✓'), msg),\n warn: (msg: string) => console.log(chalk.yellow('⚠'), msg),\n error: (msg: string) => console.error(chalk.red('✗'), msg),\n plain: (msg: string) => console.log(msg),\n}\n\nexport function debugLog(context: string, error: unknown): void {\n if (!isDebug) return\n const entry = `[${new Date().toISOString()}] [${context}] ${error instanceof Error ? error.stack : String(error)}\\n`\n try {\n fs.appendFileSync(DEBUG_LOG_PATH, entry, { mode: 0o600 })\n } catch {\n // If we can't write to the debug log, silently ignore\n }\n}\n","import fs from 'fs'\nimport os from 'os'\nimport path from 'path'\nimport BUILTIN_TOOLS from './ai-tools.json'\nimport { debugLog } from '../utils/logger'\n\nexport interface AIToolEntry {\n tool: string\n displayName: string\n pattern: string\n hook: string | null\n contextSource: 'hook' | 'history-file' | 'sqlite' | null\n historyFormat: 'jsonl' | 'json' | 'markdown' | 'sqlite' | null\n securityWarning: string | null\n}\n\nconst USER_REGISTRY_PATH = path.join(os.homedir(), '.workscribe', 'ai-tools.json')\n\nexport function loadAIToolRegistry(): AIToolEntry[] {\n let userEntries: AIToolEntry[] = []\n\n try {\n if (fs.existsSync(USER_REGISTRY_PATH)) {\n const raw = fs.readFileSync(USER_REGISTRY_PATH, 'utf-8')\n const parsed = JSON.parse(raw)\n if (Array.isArray(parsed)) {\n userEntries = parsed\n .filter((entry) => typeof entry.tool === 'string' && typeof entry.pattern === 'string')\n .map((entry) => ({\n tool: entry.tool as string,\n displayName: (entry.displayName as string | undefined) ?? (entry.tool as string),\n pattern: entry.pattern as string,\n hook: (entry.hook as string | null | undefined) ?? null,\n contextSource: (entry.contextSource as AIToolEntry['contextSource'] | undefined) ?? null,\n historyFormat: (entry.historyFormat as AIToolEntry['historyFormat'] | undefined) ?? null,\n securityWarning: (entry.securityWarning as string | null | undefined) ?? null,\n }))\n }\n }\n } catch {\n debugLog('registry', 'Failed to load user AI tool registry — using built-ins only')\n }\n\n if (userEntries.length === 0) return BUILTIN_TOOLS as AIToolEntry[]\n\n const userToolSlugs = new Set(userEntries.map((entry) => entry.tool))\n const filteredBuiltins = (BUILTIN_TOOLS as AIToolEntry[]).filter((entry) => !userToolSlugs.has(entry.tool))\n return [...filteredBuiltins, ...userEntries]\n}\n","import fs from 'fs'\nimport { CONFIG_PATH } from '../utils/paths'\n\nexport interface WorkscribeConfig {\n ai: {\n provider: string // 'anthropic' | 'openai' | 'ollama' | 'openai-compatible'\n apiKey: string\n model: string\n baseUrl: string\n }\n session: {\n idleTimeout: number // minutes\n }\n git: {\n // When true, repo_name is \"owner/repo\" instead of bare \"repo\". Off by\n // default — bare names are nicer for the common case of one repo per\n // name. Turn on if you work across repos whose bare names collide\n // (e.g. an org that names plugin repos after the tool they target:\n // workscribe/vscode, workscribe/nvim, ...).\n qualifyRepoName: boolean\n }\n capture: {\n ignore: string[]\n aiTools: boolean\n includeAiderPrompt: boolean\n profiles: string[]\n }\n redact: {\n extra: string[]\n }\n summary: {\n format: 'markdown' | 'json'\n // Categories re-included in the AI payload (overrides built-in exclusions).\n // Excluded by default: exploring, other, linting.\n // Example: [\"linting\"] to include lint pass/fail in summaries.\n includeCategories?: string[]\n }\n projects?: Record<string, string> // absolute path → display name override\n integrations?: {\n slackWebhook?: string\n webhook?: string\n }\n}\n\nconst DEFAULTS: WorkscribeConfig = {\n ai: {\n provider: '',\n apiKey: '',\n model: '',\n baseUrl: '',\n },\n session: {\n idleTimeout: 30,\n },\n git: {\n qualifyRepoName: false,\n },\n capture: {\n ignore: ['cd', 'ls', 'll', 'la', 'ls -la', 'ls -l', 'ls -a', 'pwd', 'clear', 'exit', 'history', 'man'],\n aiTools: true,\n includeAiderPrompt: true,\n profiles: [],\n },\n redact: {\n extra: [],\n },\n summary: {\n format: 'markdown',\n },\n}\n\nexport function readConfig(): WorkscribeConfig {\n if (!fs.existsSync(CONFIG_PATH)) return { ...DEFAULTS }\n try {\n const raw = fs.readFileSync(CONFIG_PATH, 'utf-8')\n const parsed = JSON.parse(raw)\n return deepMerge(DEFAULTS, parsed)\n } catch {\n return { ...DEFAULTS }\n }\n}\n\nexport function writeConfig(config: WorkscribeConfig): void {\n fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2), { encoding: 'utf-8', mode: 0o600 })\n // Enforce permissions on existing files (mode only applies on creation above)\n try {\n fs.chmodSync(CONFIG_PATH, 0o600)\n } catch {\n /* ignore */\n }\n}\n\nexport function getConfigValue(config: WorkscribeConfig, key: string): unknown {\n const parts = key.split('.')\n let cur: unknown = config\n for (const part of parts) {\n if (cur == null || typeof cur !== 'object') return undefined\n cur = (cur as Record<string, unknown>)[part]\n }\n return cur\n}\n\nexport function setConfigValue(config: WorkscribeConfig, key: string, value: string): WorkscribeConfig {\n const parts = key.split('.')\n const result = JSON.parse(JSON.stringify(config)) as WorkscribeConfig\n let cur = result as unknown as Record<string, unknown>\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i]\n if (cur[part] == null || typeof cur[part] !== 'object') {\n cur[part] = {}\n }\n cur = cur[part] as Record<string, unknown>\n }\n const lastKey = parts[parts.length - 1]\n // Coerce value type\n if (value === 'true') cur[lastKey] = true\n else if (value === 'false') cur[lastKey] = false\n else if (!isNaN(Number(value))) cur[lastKey] = Number(value)\n else cur[lastKey] = value\n return result\n}\n\nfunction deepMerge<T extends object>(defaults: T, overrides: Partial<T>): T {\n const result = { ...defaults }\n for (const key of Object.keys(overrides) as (keyof T)[]) {\n const val = overrides[key]\n if (val !== null && typeof val === 'object' && !Array.isArray(val) && typeof defaults[key] === 'object') {\n result[key] = deepMerge(defaults[key] as object, val as object) as T[keyof T]\n } else if (val !== undefined) {\n result[key] = val as T[keyof T]\n }\n }\n return result\n}\n","export interface ProfileRule {\n pattern: string\n category: string\n metadata?: Record<string, string>\n}\n\nexport interface Profile {\n name: string\n displayName: string\n version: string\n detect?: { files?: string[] }\n rules: ProfileRule[]\n aiContext?: string\n}\n\nexport interface ManifestEntry {\n name: string\n displayName: string\n tags: string[]\n description: string\n keywords: string[]\n detect?: { files?: string[] }\n}\n\nfunction isNonEmptyString(value: unknown): value is string {\n return typeof value === 'string' && value.length > 0\n}\n\nfunction isValidRule(rule: unknown): boolean {\n if (!rule || typeof rule !== 'object') return false\n const { pattern, category } = rule as Record<string, unknown>\n return isNonEmptyString(pattern) && isNonEmptyString(category)\n}\n\nexport function isValidProfile(candidate: unknown): candidate is Profile {\n if (!candidate || typeof candidate !== 'object') return false\n const { name, displayName, version, rules } = candidate as Record<string, unknown>\n if (!isNonEmptyString(name) || !isNonEmptyString(displayName) || !isNonEmptyString(version)) return false\n if (!Array.isArray(rules)) return false\n return rules.every(isValidRule)\n}\n\nexport function isValidManifest(m: unknown): m is ManifestEntry[] {\n return (\n Array.isArray(m) &&\n m.every((e) => e && typeof e === 'object' && typeof (e as Record<string, unknown>).name === 'string')\n )\n}\n","const DEFAULT_TIMEOUT_MS = 30_000\n\nconst NETWORK_ERROR_CODES = new Set([\n 'ENOTFOUND',\n 'ECONNREFUSED',\n 'ECONNRESET',\n 'ETIMEDOUT',\n 'EHOSTUNREACH',\n 'ENETUNREACH',\n])\n\nfunction isNetworkError(err: unknown): boolean {\n if (!(err instanceof Error)) return false\n const cause = (err as Error & { cause?: unknown }).cause\n const code =\n (err as NodeJS.ErrnoException).code ?? (cause instanceof Error ? (cause as NodeJS.ErrnoException).code : undefined)\n return NETWORK_ERROR_CODES.has(code ?? '')\n}\n\nexport async function fetchWithTimeout(\n url: string,\n init: RequestInit,\n timeoutMs = DEFAULT_TIMEOUT_MS\n): Promise<Response> {\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), timeoutMs)\n try {\n return await fetch(url, { ...init, signal: controller.signal })\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n throw new Error(`Request timed out after ${timeoutMs / 1000}s`)\n }\n if (isNetworkError(err)) {\n throw new Error(\"No internet connection — try again when you're online\")\n }\n throw err\n } finally {\n clearTimeout(timer)\n }\n}\n","import fs from 'fs'\nimport path from 'path'\nimport { PROFILES_DIR } from '../utils/paths'\nimport { isValidProfile, isValidManifest } from './schema'\nimport type { ManifestEntry, Profile } from './schema'\nimport { debugLog } from '../utils/logger'\nimport { fetchWithTimeout } from '../utils/fetch'\n\nconst REGISTRY_BASE = 'https://raw.githubusercontent.com/workscribe/profiles/main'\n\nfunction manifestCachePath(): string {\n return path.join(PROFILES_DIR, 'manifest.json')\n}\n\nexport async function fetchManifest(): Promise<ManifestEntry[]> {\n const response = await fetchWithTimeout(`${REGISTRY_BASE}/manifest.json`, {})\n if (!response.ok) throw new Error(`Registry unreachable (${response.status})`)\n const data: unknown = await response.json()\n if (!isValidManifest(data)) throw new Error('Manifest format unrecognised')\n return data\n}\n\nexport async function fetchProfile(name: string): Promise<Profile> {\n const response = await fetchWithTimeout(`${REGISTRY_BASE}/${name}.json`, {})\n if (response.status === 404) throw new Error(`Profile \"${name}\" not found in registry`)\n if (!response.ok) throw new Error(`Registry unreachable (${response.status})`)\n const data: unknown = await response.json()\n if (!isValidProfile(data)) throw new Error(`Profile \"${name}\" failed schema validation`)\n return data\n}\n\nexport async function installProfile(name: string): Promise<void> {\n ensureProfilesDir()\n const profile = await fetchProfile(name)\n const dest = path.join(PROFILES_DIR, `${name}.json`)\n fs.writeFileSync(dest, JSON.stringify(profile, null, 2), { encoding: 'utf-8', mode: 0o600 })\n debugLog('profiles', `Installed profile \"${name}\" to ${dest}`)\n}\n\nexport async function cacheManifest(): Promise<ManifestEntry[]> {\n ensureProfilesDir()\n const manifest = await fetchManifest()\n fs.writeFileSync(manifestCachePath(), JSON.stringify(manifest, null, 2), { encoding: 'utf-8', mode: 0o600 })\n return manifest\n}\n\nexport function readCachedManifest(): ManifestEntry[] | null {\n if (!fs.existsSync(manifestCachePath())) return null\n try {\n const data: unknown = JSON.parse(fs.readFileSync(manifestCachePath(), 'utf-8'))\n return isValidManifest(data) ? data : null\n } catch {\n return null\n }\n}\n\nfunction ensureProfilesDir(): void {\n if (!fs.existsSync(PROFILES_DIR)) {\n fs.mkdirSync(PROFILES_DIR, { recursive: true, mode: 0o700 })\n }\n}\n","import fs from 'fs'\nimport path from 'path'\nimport { PROFILES_DIR } from '../utils/paths'\nimport { readConfig } from '../config'\nimport { isValidProfile } from './schema'\nimport type { Profile, ManifestEntry, ProfileRule } from './schema'\nimport { readCachedManifest } from './fetcher'\nimport { debugLog } from '../utils/logger'\n\n// Matches the Rule interface in patterns.ts — structural compatibility without circular import\ninterface CompiledRule {\n match(cmd: string): { category: string; metadata: Record<string, unknown> } | null\n}\n\nfunction compileRule(profileName: string, rule: ProfileRule): CompiledRule | null {\n let regex: RegExp\n try {\n regex = new RegExp(rule.pattern)\n } catch {\n debugLog('profiles', `Profile \"${profileName}\": invalid pattern \"${rule.pattern}\" — skipping rule`)\n return null\n }\n\n return {\n match(cmd: string) {\n const match = cmd.match(regex)\n if (!match) return null\n const metadata: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(rule.metadata ?? {})) {\n metadata[key] = value.replace(/\\$(\\d+)/g, (_, index: string) => match[Number(index)] ?? '')\n }\n return { category: rule.category, metadata }\n },\n }\n}\n\nfunction loadProfileFromDisk(name: string): Profile | null {\n const filePath = path.join(PROFILES_DIR, `${name}.json`)\n if (!fs.existsSync(filePath)) {\n debugLog('profiles', `Profile \"${name}\" not found in cache — run: workscribe profile add ${name}`)\n return null\n }\n let candidate: unknown\n try {\n candidate = JSON.parse(fs.readFileSync(filePath, 'utf-8'))\n } catch {\n debugLog('profiles', `Profile \"${name}\" contains invalid JSON — skipping`)\n return null\n }\n if (!isValidProfile(candidate)) {\n debugLog('profiles', `Profile \"${name}\" failed schema validation — skipping`)\n return null\n }\n return candidate\n}\n\nfunction loadUserProfiles(): Profile[] {\n if (!fs.existsSync(PROFILES_DIR)) return []\n const activeNames = new Set(readConfig().capture.profiles)\n return fs\n .readdirSync(PROFILES_DIR)\n .filter((file) => file.endsWith('.json') && file !== 'manifest.json')\n .filter((file) => {\n const name = file.replace(/\\.json$/, '')\n return !activeNames.has(name) // avoid double-loading names already in config\n })\n .flatMap((file) => {\n const candidate = loadProfileFromDisk(file.replace(/\\.json$/, ''))\n return candidate ? [candidate] : []\n })\n .filter((profile) => fs.existsSync(path.join(PROFILES_DIR, `${profile.name}.json`)))\n}\n\nexport function getActiveProfileRules(): CompiledRule[] {\n const activeNames = readConfig().capture.profiles\n if (activeNames.length === 0) return []\n\n return activeNames.flatMap((name) => {\n const profile = loadProfileFromDisk(name)\n if (!profile) return []\n return profile.rules.flatMap((rule) => {\n const compiled = compileRule(profile.name, rule)\n return compiled ? [compiled] : []\n })\n })\n}\n\nexport function getActiveProfileAiContexts(): string[] {\n const activeNames = readConfig().capture.profiles\n if (activeNames.length === 0) return []\n\n return activeNames.flatMap((name) => {\n const profile = loadProfileFromDisk(name)\n return profile?.aiContext ? [profile.aiContext] : []\n })\n}\n\nexport function getCachedProfiles(): Profile[] {\n if (!fs.existsSync(PROFILES_DIR)) return []\n return fs\n .readdirSync(PROFILES_DIR)\n .filter((file) => file.endsWith('.json') && file !== 'manifest.json')\n .flatMap((file) => {\n const profile = loadProfileFromDisk(file.replace(/\\.json$/, ''))\n return profile ? [profile] : []\n })\n}\n\nexport function detectProfilesForDirectory(dir: string): ManifestEntry[] {\n const manifest = readCachedManifest()\n if (!manifest) return []\n\n const activeNames = new Set(readConfig().capture.profiles)\n\n return manifest.filter((entry) => {\n if (activeNames.has(entry.name)) return false\n const indicatorFiles = entry.detect?.files ?? []\n return indicatorFiles.length > 0 && indicatorFiles.every((file) => fs.existsSync(path.join(dir, file)))\n })\n}\n\nexport { loadUserProfiles }\n","import { loadAIToolRegistry } from '../config/registry'\nimport { getActiveProfileRules } from '../profiles/loader'\nimport { debugLog } from '../utils/logger'\n\nexport interface NormalizedEvent {\n category: string\n metadata: Record<string, unknown>\n}\n\ninterface Rule {\n match(cmd: string): NormalizedEvent | null\n}\n\nfunction makeRule(\n pattern: RegExp,\n category: string,\n extract: (match: RegExpMatchArray, cmd: string) => Record<string, unknown> = () => ({})\n): Rule {\n return {\n match(cmd) {\n const m = cmd.match(pattern)\n if (!m) return null\n return { category, metadata: extract(m, cmd) }\n },\n }\n}\n\n// Extract package names from install commands like: npm install foo bar\nfunction extractPackages(cmd: string, afterKeyword: string): string[] {\n const idx = cmd.indexOf(afterKeyword)\n if (idx === -1) return []\n return cmd\n .slice(idx + afterKeyword.length)\n .trim()\n .split(/\\s+/)\n .filter((part) => part && !part.startsWith('-'))\n}\n\nconst BASE_RULES: Rule[] = [\n // ─── Git operations ───────────────────────────────────────────────────────\n makeRule(/^git\\s+commit\\b/, 'shipping', (_m, cmd) => {\n const msgMatch = cmd.match(/-m\\s+[\"']?([^\"']+)[\"']?/)\n return { message: msgMatch ? msgMatch[1].trim() : null }\n }),\n\n makeRule(/^git\\s+push\\b/, 'shipping', (_m, cmd) => {\n const parts = cmd.split(/\\s+/)\n return { remote: parts[2] ?? 'origin', branch: parts[3] ?? null }\n }),\n\n makeRule(/^git\\s+(pull|fetch)\\b/, 'versioning', (_m, cmd) => {\n const parts = cmd.split(/\\s+/)\n return { subcommand: parts[1], remote: parts[2] ?? 'origin' }\n }),\n\n makeRule(/^git\\s+(checkout|switch)\\b/, 'versioning', (_m, cmd) => {\n const parts = cmd.split(/\\s+/)\n const branch = parts.find((part) => !part.startsWith('-') && part !== 'git' && part !== parts[1])\n return { branch: branch ?? null }\n }),\n\n makeRule(/^git\\s+(merge|rebase)\\b/, 'shipping', (_m, cmd) => {\n const parts = cmd.split(/\\s+/)\n return { subcommand: parts[1], target: parts[2] ?? null }\n }),\n\n makeRule(/^git\\s+stash\\b/, 'versioning', (_m, cmd) => {\n const parts = cmd.split(/\\s+/)\n return { subcommand: parts[2] ?? 'push' }\n }),\n\n makeRule(/^git\\s+/, 'versioning', (_m, cmd) => {\n const parts = cmd.split(/\\s+/)\n return { subcommand: parts[1] ?? null }\n }),\n\n // ─── Releasing ────────────────────────────────────────────────────────────\n makeRule(/^npm\\s+publish\\b/, 'releasing', () => ({ tool: 'npm' })),\n makeRule(/^cargo\\s+publish\\b/, 'releasing', () => ({ tool: 'cargo' })),\n makeRule(/^gem\\s+push\\b/, 'releasing', () => ({ tool: 'gem' })),\n makeRule(/^docker\\s+push\\b/, 'releasing', (_m, cmd) => ({ tool: 'docker', image: cmd.split(/\\s+/)[2] ?? null })),\n makeRule(/^gh\\s+release\\b/, 'releasing', (_m, cmd) => ({ tool: 'gh', subcommand: cmd.split(/\\s+/)[2] ?? null })),\n makeRule(/^fly\\s+(deploy|launch)\\b/, 'releasing', (match) => ({ tool: 'fly', subcommand: match[1] })),\n makeRule(/^vercel\\s+(deploy|build|--prod)\\b/, 'releasing', () => ({ tool: 'vercel' })),\n makeRule(/^netlify\\s+deploy\\b/, 'releasing', () => ({ tool: 'netlify' })),\n makeRule(/^railway\\s+up\\b/, 'releasing', () => ({ tool: 'railway' })),\n makeRule(/^wrangler\\s+deploy\\b/, 'releasing', () => ({ tool: 'wrangler' })),\n\n // ─── Dependencies ─────────────────────────────────────────────────────────\n makeRule(/^npm\\s+(install|i|add)\\b/, 'dependencies', (_m, cmd) => ({\n tool: 'npm',\n packages: extractPackages(cmd, cmd.includes('install') ? 'install' : cmd.includes(' i ') ? ' i ' : 'add'),\n })),\n\n makeRule(/^(yarn|pnpm)\\s+(install|add)\\b/, 'dependencies', (m, cmd) => ({\n tool: m[1],\n packages: extractPackages(cmd, 'add'),\n })),\n\n makeRule(/^bun\\s+(install|add)\\b/, 'dependencies', (_m, cmd) => ({\n tool: 'bun',\n packages: extractPackages(cmd, 'add'),\n })),\n\n makeRule(/^pip\\s+(install)\\b/, 'dependencies', (_m, cmd) => ({\n tool: 'pip',\n packages: extractPackages(cmd, 'install'),\n })),\n\n makeRule(/^cargo\\s+add\\b/, 'dependencies', (_m, cmd) => ({\n tool: 'cargo',\n packages: extractPackages(cmd, 'add'),\n })),\n\n makeRule(/^(brew)\\s+install\\b/, 'dependencies', (_m, cmd) => ({\n tool: 'brew',\n packages: extractPackages(cmd, 'install'),\n })),\n\n makeRule(/^go\\s+get\\b/, 'dependencies', (_m, cmd) => ({\n tool: 'go',\n packages: extractPackages(cmd, 'get'),\n })),\n\n makeRule(/^npm\\s+(uninstall|remove|rm)\\b/, 'dependencies', (_m, cmd) => ({\n tool: 'npm',\n packages: extractPackages(cmd, cmd.split(/\\s+/)[1]),\n })),\n\n makeRule(/^(yarn|pnpm)\\s+remove\\b/, 'dependencies', (m, cmd) => ({\n tool: m[1],\n packages: extractPackages(cmd, 'remove'),\n })),\n\n makeRule(/^bun\\s+remove\\b/, 'dependencies', (_m, cmd) => ({\n tool: 'bun',\n packages: extractPackages(cmd, 'remove'),\n })),\n\n makeRule(/^pip\\s+uninstall\\b/, 'dependencies', (_m, cmd) => ({\n tool: 'pip',\n packages: extractPackages(cmd, 'uninstall'),\n })),\n\n // Runtime version managers\n makeRule(/^nvm\\b/, 'dependencies', (_m, cmd) => ({ tool: 'nvm', subcommand: cmd.split(/\\s+/)[1] ?? null })),\n makeRule(/^(fnm|volta)\\b/, 'dependencies', (m, cmd) => ({ tool: m[1], subcommand: cmd.split(/\\s+/)[1] ?? null })),\n makeRule(/^(rbenv|pyenv|asdf)\\b/, 'dependencies', (m, cmd) => ({\n tool: m[1],\n subcommand: cmd.split(/\\s+/)[1] ?? null,\n })),\n\n // ─── Tests ────────────────────────────────────────────────────────────────\n makeRule(/^npm\\s+(test|run\\s+test)\\b/, 'testing', () => ({ tool: 'npm' })),\n makeRule(/^yarn\\s+test\\b/, 'testing', () => ({ tool: 'yarn' })),\n makeRule(/^pnpm\\s+test\\b/, 'testing', () => ({ tool: 'pnpm' })),\n makeRule(/^bun\\s+test\\b/, 'testing', () => ({ tool: 'bun' })),\n makeRule(/^(jest|vitest)\\b/, 'testing', (match) => ({ tool: match[1] })),\n makeRule(/^pytest\\b/, 'testing', () => ({ tool: 'pytest' })),\n makeRule(/^go\\s+test\\b/, 'testing', () => ({ tool: 'go' })),\n makeRule(/^cargo\\s+test\\b/, 'testing', () => ({ tool: 'cargo' })),\n makeRule(/^rspec\\b/, 'testing', () => ({ tool: 'rspec' })),\n makeRule(/^(php\\s+)?phpunit\\b/, 'testing', () => ({ tool: 'phpunit' })),\n\n // ─── Build ────────────────────────────────────────────────────────────────\n makeRule(/^npm\\s+run\\s+build\\b/, 'building', () => ({ tool: 'npm' })),\n makeRule(/^(yarn|pnpm)\\s+build\\b/, 'building', (match) => ({ tool: match[1] })),\n makeRule(/^bun\\s+run\\s+build\\b/, 'building', () => ({ tool: 'bun' })),\n makeRule(/^(make|gmake)\\b/, 'building', (match) => ({ tool: match[1] })),\n makeRule(/^cargo\\s+build\\b/, 'building', () => ({ tool: 'cargo' })),\n makeRule(/^go\\s+build\\b/, 'building', () => ({ tool: 'go' })),\n makeRule(/^docker\\s+build\\b/, 'building', () => ({ tool: 'docker' })),\n makeRule(/^(mvn|gradle)\\b/, 'building', (match) => ({ tool: match[1] })),\n\n // ─── Dev server / running ─────────────────────────────────────────────────\n makeRule(/^npm\\s+run\\s+(dev|start|serve)\\b/, 'running', (_m, cmd) => ({\n tool: 'npm',\n script: cmd.split(/\\s+/)[2],\n })),\n makeRule(/^(yarn|pnpm)\\s+(dev|start)\\b/, 'running', (match) => ({ tool: match[1], script: match[2] })),\n makeRule(/^bun\\s+run\\s+(dev|start|serve)\\b/, 'running', (_m, cmd) => ({\n tool: 'bun',\n script: cmd.split(/\\s+/)[2],\n })),\n makeRule(/^python\\s+.*manage\\.py\\s+runserver\\b/, 'running', () => ({ tool: 'django' })),\n\n // ─── Infrastructure ───────────────────────────────────────────────────────\n makeRule(/^ssh\\b/, 'infrastructure', (_m, cmd) => {\n const parts = cmd.split(/\\s+/)\n return { tool: 'ssh', target: parts[parts.length - 1] }\n }),\n\n makeRule(/^kubectl\\b/, 'infrastructure', (_m, cmd) => {\n const parts = cmd.split(/\\s+/)\n return { tool: 'kubectl', subcommand: parts[1] ?? null }\n }),\n\n makeRule(/^(helm|terraform|pulumi)\\b/, 'infrastructure', (m, cmd) => {\n const parts = cmd.split(/\\s+/)\n return { tool: m[1], subcommand: parts[1] ?? null }\n }),\n\n makeRule(/^docker\\s+(run|compose|ps|stop|start|rm|exec)\\b/, 'infrastructure', (_m, cmd) => {\n const parts = cmd.split(/\\s+/)\n return { tool: 'docker', subcommand: parts[1] }\n }),\n\n makeRule(/^(aws|gcloud|az)\\b/, 'infrastructure', (m, cmd) => {\n const parts = cmd.split(/\\s+/)\n return { tool: m[1], subcommand: parts[1] ?? null }\n }),\n\n // ─── Database ─────────────────────────────────────────────────────────────\n makeRule(/^(psql|pgcli)\\b/, 'database', (m) => ({ tool: m[1] })),\n makeRule(/^(mysql|mycli)\\b/, 'database', (m) => ({ tool: m[1] })),\n makeRule(/^sqlite3\\b/, 'database', () => ({ tool: 'sqlite3' })),\n makeRule(/^(mongosh|mongo)\\b/, 'database', (m) => ({ tool: m[1] })),\n makeRule(/^redis-cli\\b/, 'database', () => ({ tool: 'redis-cli' })),\n\n // ─── npx ─────────────────────────────────────────────────────────────────\n makeRule(/^npx\\s+(jest|vitest|mocha|ava|tap)\\b/, 'testing', (_m, cmd) => ({\n tool: cmd.split(/\\s+/)[1],\n })),\n makeRule(/^npx\\s+tsc\\b/, 'building', () => ({ tool: 'tsc' })),\n makeRule(/^npx\\s+(eslint|tslint|biome)\\b/, 'linting', (_m, cmd) => ({\n tool: cmd.split(/\\s+/)[1],\n })),\n makeRule(/^npx\\s+(prettier|dprint)\\b/, 'linting', (_m, cmd) => ({\n tool: cmd.split(/\\s+/)[1],\n })),\n makeRule(/^npx\\s+\\S+/, 'running', (_m, cmd) => ({\n tool: cmd.split(/\\s+/)[1],\n })),\n\n // ─── Scripts ──────────────────────────────────────────────────────────────\n makeRule(/^(bash|sh|zsh|fish)\\s+\\S+/, 'running', (match) => ({ shell: match[1] })),\n makeRule(/^node\\s+\\S+\\.(?:js|mjs|cjs)\\b/, 'running', () => ({ runtime: 'node' })),\n makeRule(/^python3?\\s+\\S+\\.py\\b/, 'running', () => ({ runtime: 'python' })),\n\n // ─── Linting / code quality ───────────────────────────────────────────────\n makeRule(/^(eslint|tslint|biome)\\b/, 'linting', (match) => ({ tool: match[1] })),\n makeRule(/^(prettier|dprint)\\b/, 'linting', (match) => ({ tool: match[1] })),\n\n // ─── generic run scripts ──────────────────────────────────────────────────\n makeRule(/^npm\\s+run\\s+\\S+/, 'running', (_m, cmd) => ({\n tool: 'npm',\n script: cmd.split(/\\s+/)[2],\n })),\n\n makeRule(/^bun\\s+run\\s+\\S+/, 'running', (_m, cmd) => ({\n tool: 'bun',\n script: cmd.split(/\\s+/)[2],\n })),\n\n // ─── Code search ─────────────────────────────────────────────────────────\n makeRule(/^(grep|egrep|fgrep)\\b/, 'exploring', (match) => ({ tool: match[1] })),\n makeRule(/^(rg|ag|ack|ripgrep)\\b/, 'exploring', (match) => ({ tool: match[1] })),\n makeRule(/^find\\s/, 'exploring', () => ({ tool: 'find' })),\n\n // ─── Code read ────────────────────────────────────────────────────────────\n makeRule(/^(cat|bat|less|more)\\s+\\S+/, 'exploring', (match) => ({ tool: match[1] })),\n makeRule(/^(head|tail)\\b/, 'exploring', (match) => ({ tool: match[1] })),\n\n // ─── File operations ──────────────────────────────────────────────────────\n makeRule(/^(cp|rsync)\\b/, 'files', (match) => ({ tool: match[1] })),\n makeRule(/^(mv)\\b/, 'files', () => ({ tool: 'mv' })),\n makeRule(/^(rm|rmdir)\\b/, 'files', (match) => ({ tool: match[1] })),\n makeRule(/^(mkdir|touch|ln)\\b/, 'files', (match) => ({ tool: match[1] })),\n makeRule(/^(chmod|chown|chgrp)\\b/, 'files', (match) => ({ tool: match[1] })),\n\n // ─── Environment ──────────────────────────────────────────────────────────\n makeRule(/^export\\s+\\w+=/, 'files', (_m, cmd) => {\n const varName = cmd.match(/^export\\s+(\\w+)=/)?.[1] ?? null\n return { variable: varName }\n }),\n makeRule(/^source\\s+/, 'files', () => ({})),\n]\n\nfunction aiToolRules(): Rule[] {\n return loadAIToolRegistry().flatMap((entry) => {\n try {\n return [makeRule(new RegExp(entry.pattern), 'ai_session', () => ({ tool: entry.tool }))]\n } catch {\n debugLog('registry', `Skipping tool \"${entry.tool}\" — invalid pattern: ${entry.pattern}`)\n return []\n }\n })\n}\n\nexport function buildRules(profileRules: Array<{ match(cmd: string): NormalizedEvent | null }> = []): Rule[] {\n return [...BASE_RULES, ...profileRules, ...aiToolRules()]\n}\n\nexport const RULES: Rule[] = buildRules(getActiveProfileRules())\n\nexport function normalizeCommand(command: string): NormalizedEvent {\n let trimmed = command.trim().replace(/\\s+/g, ' ')\n\n // Strip `git -C <path>` prefix so rules match regardless of working directory flag\n trimmed = trimmed.replace(/^(git)\\s+-C\\s+\\S+\\s+/, '$1 ')\n\n for (const rule of RULES) {\n const result = rule.match(trimmed)\n if (result) return result\n }\n\n return { category: 'other', metadata: {} }\n}\n","import type { EventRow } from '../db/types'\n\nfunction normalizeForFilter(cmd: string): string {\n return cmd.trim().replace(/\\s+/g, ' ')\n}\n\n// Always filtered regardless of user config — internal tool noise\nconst BUILTIN_IGNORE = new Set(['workscribe'])\n\n/**\n * Returns true if the command should be dropped (noise / ignore list).\n */\nexport function shouldFilter(command: string, ignoreList: string[]): boolean {\n const normalized = normalizeForFilter(command)\n if (!normalized) return true\n\n const baseCmd = normalized.split(' ')[0]\n\n // Built-in filter: always excluded, not user-configurable\n if (BUILTIN_IGNORE.has(baseCmd)) return true\n\n // User-configurable ignore list\n const normalizedIgnore = ignoreList.map(normalizeForFilter)\n if (normalizedIgnore.includes(normalized)) return true\n if (normalizedIgnore.includes(baseCmd)) return true\n\n return false\n}\n\n/**\n * Returns true if this command is a duplicate of the last event\n * (same command + same cwd within the dedup window).\n */\nexport function isDuplicate(\n command: string,\n cwd: string,\n lastEvent: Pick<EventRow, 'command' | 'cwd' | 'captured_at'> | undefined,\n dedupWindowMs = 5000,\n now = Date.now()\n): boolean {\n if (!lastEvent) return false\n const lastTime = new Date(lastEvent.captured_at).getTime()\n return lastEvent.command === normalizeForFilter(command) && lastEvent.cwd === cwd && now - lastTime < dedupWindowMs\n}\n","// Per-file dedup window for IDE file-save events.\n// Prevents duplicate captures when an IDE auto-saves the same file repeatedly.\nexport const IDE_DEDUP_WINDOW_MS = 30_000\n\n// Valid event type strings sent by IDE integrations via `workscribe _capture --type <type>`.\nexport const IDE_EVENT_TYPES = new Set(['code_edit', 'debug_start', 'debug_end', 'task_run'])\n\nexport function isIdeEventType(type: string): boolean {\n return IDE_EVENT_TYPES.has(type)\n}\n","import fs from 'fs'\nimport { insertEvent, getLastEvent, getLastEventForFile } from '../db'\nimport { redact } from './redact'\nimport { getGitContext } from './git'\nimport { getCommitsSince } from './git-snapshot'\nimport { readLastAiderPrompt } from './aider'\nimport { normalizeCommand } from '../normalize/patterns'\nimport { readConfig } from '../config'\nimport { shouldFilter, isDuplicate } from './filter'\nimport { IDE_DEDUP_WINDOW_MS } from './ide'\nimport { PAUSE_FLAG_PATH } from '../utils/paths'\nimport { loadAIToolRegistry } from '../config/registry'\n\nexport function captureCommand(opts: {\n command?: string\n cwd: string\n exitCode: number | null\n durationMs: number | null\n gitBefore?: string\n source?: string\n type?: string\n file?: string\n}): void {\n // Check pause flag before any I/O\n if (fs.existsSync(PAUSE_FLAG_PATH)) return\n\n const config = readConfig()\n const { cwd, exitCode, durationMs } = opts\n\n // ─── IDE event path ──────────────────────────────────────────────────────────\n // When --type is provided, the caller has already classified the event.\n // Skip normalization and noise filtering — these are first-party signals.\n if (opts.type) {\n // For file-save events, deduplicate per-file with a longer window (30s) to\n // absorb rapid auto-saves of the same file.\n if (opts.type === 'code_edit' && opts.file) {\n const lastForFile = getLastEventForFile(opts.file, cwd)\n if (lastForFile) {\n const lastTime = new Date(lastForFile.captured_at).getTime()\n if (Date.now() - lastTime < IDE_DEDUP_WINDOW_MS) return\n }\n }\n\n const command = opts.command ?? opts.file ?? opts.type\n const nameOverride = config.projects?.[cwd] ?? null\n const { repoName, branch } = getGitContext(cwd, nameOverride, config.git.qualifyRepoName)\n\n insertEvent({\n captured_at: new Date().toISOString(),\n command,\n cwd,\n exit_code: exitCode,\n duration_ms: durationMs,\n repo_name: repoName,\n branch,\n category: opts.type,\n metadata: null,\n source: opts.source ?? null,\n file_path: opts.file ?? null,\n })\n return\n }\n\n // ─── Shell event path ─────────────────────────────────────────────────────────\n const command = opts.command as string\n\n // 1. Filter noise commands\n if (shouldFilter(command, config.capture.ignore)) return\n\n // 2. Deduplicate: same command + same cwd within 5 seconds\n const last = getLastEvent()\n if (isDuplicate(command, cwd, last ?? undefined)) return\n\n // 3. Redact sensitive patterns\n const safeCommand = redact(command, config.redact.extra)\n\n // 4. Extract git context (with optional per-project name override)\n const nameOverride = config.projects?.[cwd] ?? null\n const { repoName, branch } = getGitContext(cwd, nameOverride)\n\n // 5. Normalize to typed event\n const { category, metadata } = normalizeCommand(safeCommand)\n\n if (category === 'ai_session' && config.capture.aiTools === false) return\n\n // Hint passthrough: preserve context for unrecognised commands so the AI can describe them\n if (category === 'other') {\n const firstToken = safeCommand.trim().split(/\\s+/)[0]\n if (firstToken) metadata.tool = firstToken\n metadata.hint = safeCommand.trim().slice(0, 120)\n }\n\n // 6. For ai_session events, enrich metadata\n if (category === 'ai_session') {\n // 6a. Commits made during the session\n if (opts.gitBefore) {\n const commits = getCommitsSince(opts.gitBefore, cwd)\n if (commits.length > 0) metadata.commits = commits\n }\n\n // 6b. Last user prompt from history file (e.g. Aider)\n if (config.capture.includeAiderPrompt !== false) {\n const toolEntry = loadAIToolRegistry().find((entry) => entry.tool === metadata.tool)\n if (toolEntry?.contextSource === 'history-file') {\n const prompt = readLastAiderPrompt(cwd)\n if (prompt) metadata.prompt = prompt\n }\n }\n }\n\n // 7. Persist\n insertEvent({\n captured_at: new Date().toISOString(),\n command: safeCommand,\n cwd,\n exit_code: exitCode,\n duration_ms: durationMs,\n repo_name: repoName,\n branch,\n category,\n metadata: Object.keys(metadata).length > 0 ? JSON.stringify(metadata) : null,\n source: opts.source ?? null,\n file_path: null,\n })\n}\n","import { Command } from 'commander'\nimport { captureCommand } from '../capture'\nimport { debugLog } from '../utils/logger'\n\nconst CAPTURE_HANG_TIMEOUT_MS = 5_000\n\nexport function registerCapture(program: Command): void {\n // Internal command — called by the shell hook and IDE integrations, not by the user\n program\n .command('_capture')\n .description('Internal: capture a shell command or IDE event (called by shell hook or IDE plugin)')\n .option('--cmd <command>', 'command that was executed (shell events)')\n .option('--cwd <path>', 'working directory')\n .option('--exit <code>', 'exit code', parseInt)\n .option('--duration <ms>', 'duration in milliseconds', parseInt)\n .option('--git-before <sha>', 'git HEAD SHA before this command ran')\n .option('--type <type>', 'event type override — skips normalization (IDE integrations)')\n .option('--source <source>', 'event source identifier (e.g. vscode, neovim, jupyter)')\n .option('--file <path>', 'file path for code_edit events')\n .action((opts) => {\n // Prevent background process accumulation if the process hangs (e.g. SQLite locked).\n // unref() allows a natural exit to happen immediately without waiting for the timer.\n const hangGuard = setTimeout(() => process.exit(0), CAPTURE_HANG_TIMEOUT_MS)\n hangGuard.unref()\n\n // Never surface errors to the terminal — this runs silently in the background\n try {\n if (!opts.cwd) return\n // Require either a shell command or a typed IDE event\n if (!opts.cmd && !opts.type) return\n captureCommand({\n command: opts.cmd,\n cwd: opts.cwd,\n exitCode: opts.exit ?? null,\n durationMs: opts.duration ?? null,\n gitBefore: opts.gitBefore ?? undefined,\n source: opts.source ?? undefined,\n type: opts.type ?? undefined,\n file: opts.file ?? undefined,\n })\n } catch (err) {\n debugLog('_capture', err)\n }\n })\n}\n","import { redact } from './redact'\n\nexport function containsSecrets(text: string): boolean {\n return redact(text) !== text\n}\n","import fs from 'fs'\nimport path from 'path'\nimport { getDb } from './index'\nimport { ALERTS_PENDING_PATH } from '../utils/paths'\n\nexport interface AlertRow {\n id: number\n created_at: number\n tool: string\n session_id: string | null\n context: string\n cleared: number\n}\n\nexport function insertAlert(tool: string, sessionId: string | null, context: string): void {\n getDb()\n .prepare(\n `INSERT INTO alerts (created_at, tool, session_id, context)\n VALUES ($created_at, $tool, $session_id, $context)`\n )\n .run({ created_at: Date.now(), tool, session_id: sessionId ?? null, context })\n\n fs.mkdirSync(path.dirname(ALERTS_PENDING_PATH), { recursive: true })\n fs.writeFileSync(ALERTS_PENDING_PATH, '', { flag: 'w' })\n}\n\nexport function getPendingAlerts(): AlertRow[] {\n return getDb()\n .prepare('SELECT * FROM alerts WHERE cleared = 0 ORDER BY created_at DESC')\n .all() as unknown as AlertRow[]\n}\n\nexport function hasPendingAlerts(): boolean {\n const row = getDb().prepare('SELECT COUNT(*) as count FROM alerts WHERE cleared = 0').get() as {\n count: number | bigint\n }\n return Number(row.count) > 0\n}\n\nexport function clearAlerts(): number {\n const result = getDb().prepare('UPDATE alerts SET cleared = 1 WHERE cleared = 0').run()\n try {\n fs.unlinkSync(ALERTS_PENDING_PATH)\n } catch {\n // File may already be absent\n }\n return Number(result.changes)\n}\n","import { Command } from 'commander'\nimport { captureCommand } from '../capture'\nimport { readConfig } from '../config'\nimport { debugLog } from '../utils/logger'\nimport { containsSecrets } from '../capture/detect-secrets'\nimport { insertAlert } from '../db/alerts'\n\n/** Parses a Claude Code PostToolUse stdin payload. Returns null if required fields are missing. */\nexport function parseHookPayload(raw: string): { command: string; cwd: string } | null {\n if (!raw.trim()) return null\n const payload = JSON.parse(raw) as Record<string, unknown>\n const toolInput = payload.tool_input as Record<string, unknown> | undefined\n const command = typeof toolInput?.command === 'string' ? toolInput.command : null\n const cwd = typeof payload.cwd === 'string' ? payload.cwd : null\n if (!command || !cwd) return null\n return { command, cwd }\n}\n\ninterface UserPromptPayload {\n session_id: string\n prompt: string\n cwd: string\n}\n\n/** Parses a Claude Code UserPromptSubmit stdin payload. Returns null if required fields are missing. */\nexport function parseUserPromptPayload(raw: string): UserPromptPayload | null {\n if (!raw.trim()) return null\n const payload = JSON.parse(raw) as Record<string, unknown>\n const prompt = typeof payload.prompt === 'string' ? payload.prompt : null\n const sessionId = typeof payload.session_id === 'string' ? payload.session_id : ''\n const cwd = typeof payload.cwd === 'string' ? payload.cwd : ''\n if (!prompt) return null\n return { session_id: sessionId, prompt, cwd }\n}\n\nexport function registerHook(program: Command): void {\n // Internal command — called by AI tool hooks (e.g. Claude Code PostToolUse), not by the user\n program\n .command('_hook')\n .description('Internal: capture events from AI tool hooks (stdin JSON payload)')\n .option('--source <source>', 'hook source identifier (e.g. claude-code)')\n .option('--event <event>', 'hook event type (PostToolUse or UserPromptSubmit)', 'PostToolUse')\n .action((opts: { source?: string; event: string }) => {\n let raw = ''\n process.stdin.setEncoding('utf-8')\n process.stdin.on('data', (chunk: string) => {\n raw += chunk\n })\n process.stdin.on('end', () => {\n try {\n if (opts.event === 'UserPromptSubmit') {\n const parsed = parseUserPromptPayload(raw)\n if (!parsed) return\n if (containsSecrets(parsed.prompt)) {\n insertAlert(\n opts.source ?? 'unknown',\n parsed.session_id || null,\n 'Possible credential detected in prompt submitted to AI tool'\n )\n // Claude Code reads this JSON and injects systemMessage into Claude's context\n process.stdout.write(\n JSON.stringify({\n systemMessage:\n 'Workscribe detected a possible credential in your prompt. ' +\n 'Run `workscribe alerts` for details.',\n })\n )\n }\n return\n }\n\n // Default: PostToolUse — capture the shell command\n if (readConfig().capture.aiTools === false) return\n const parsed = parseHookPayload(raw)\n if (!parsed) return\n captureCommand({\n command: parsed.command,\n cwd: parsed.cwd,\n exitCode: null,\n durationMs: null,\n source: opts.source,\n })\n } catch (err) {\n debugLog('_hook', err)\n }\n })\n })\n}\n","export function formatDuration(minutes: number): string {\n if (minutes < 60) return `${Math.round(minutes)}m`\n const h = Math.floor(minutes / 60)\n const m = Math.round(minutes % 60)\n return m > 0 ? `${h}h ${m}m` : `${h}h`\n}\n\nexport function formatDate(isoString: string): string {\n return new Date(isoString).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })\n}\n\nexport function todayDate(): string {\n return localDateStr(new Date())\n}\n\nexport function parseDate(input: string): string {\n // Accepts YYYY-MM-DD, returns YYYY-MM-DD. Throws on invalid.\n const d = new Date(input + 'T00:00:00')\n if (isNaN(d.getTime())) throw new Error(`Invalid date: ${input}`)\n return input\n}\n\nfunction localDateStr(d: Date): string {\n const y = d.getFullYear()\n const m = String(d.getMonth() + 1).padStart(2, '0')\n const day = String(d.getDate()).padStart(2, '0')\n return `${y}-${m}-${day}`\n}\n\n// Returns Monday of the ISO week containing dateStr (YYYY-MM-DD)\nexport function startOfWeek(dateStr: string): string {\n const d = new Date(dateStr + 'T00:00:00')\n const day = d.getDay() // 0=Sun\n const diff = day === 0 ? -6 : 1 - day\n d.setDate(d.getDate() + diff)\n return localDateStr(d)\n}\n\n// Returns all YYYY-MM-DD strings from start to end inclusive\nexport function eachDayOfRange(start: string, end: string): string[] {\n const days: string[] = []\n const cur = new Date(start + 'T00:00:00')\n const last = new Date(end + 'T00:00:00')\n while (cur <= last) {\n days.push(localDateStr(cur))\n cur.setDate(cur.getDate() + 1)\n }\n return days\n}\n\nexport function timeAgo(isoString: string, now = Date.now()): string {\n const elapsedMs = now - new Date(isoString).getTime()\n const minutes = Math.floor(elapsedMs / 60000)\n if (minutes < 2) return 'just now'\n if (minutes < 60) return `${minutes} minutes ago`\n const hours = Math.floor(minutes / 60)\n if (hours < 24) return hours === 1 ? '1 hour ago' : `${hours} hours ago`\n const days = Math.floor(hours / 24)\n if (days === 1) return 'yesterday'\n return `${days} days ago`\n}\n\n// Returns ISO week string YYYY-WW for a date\nexport function isoWeekKey(dateStr: string): string {\n const d = new Date(dateStr + 'T00:00:00')\n const jan4 = new Date(d.getFullYear(), 0, 4)\n const weekNum = Math.ceil(((d.getTime() - jan4.getTime()) / 86400000 + jan4.getDay() + 1) / 7)\n return `${d.getFullYear()}-W${String(weekNum).padStart(2, '0')}`\n}\n","import type { DaySummaryPayload, WeekSummaryPayload } from './types'\nimport { formatDuration } from '../utils/format'\nimport { getActiveProfileAiContexts } from '../profiles/loader'\n\nexport const SYSTEM_PROMPT = `You write short developer work summaries. Focus on what the developer accomplished and what changed — not which tools or commands were used.\n\nHere is an example:\n\nINPUT:\nProject: api-service\nBranch: feature/auth\nDuration: 2h 00m\nEvents:\n - versioning {\"branch\":\"feature/auth\"}\n - 2x dependencies {\"tool\":\"npm\",\"packages\":[\"bcrypt\",\"jsonwebtoken\"]}\n - 8x testing [failed]\n - testing\n - 2x files {\"tool\":\"mkdir\"}\n - shipping {\"message\":\"fix: auth token validation\"}\n - shipping {\"remote\":\"origin\",\"branch\":\"feature/auth\"}\n\nOUTPUT:\n- Added authentication dependencies (bcrypt, JWT)\n- Debugged and resolved failing auth tests\n- Committed and pushed the token validation fix\n\nRULES — follow these exactly:\n\n1. Interpret repeated events as patterns, not individual steps.\n - Many testing [failed] followed by a passing test = debugging a failure. Say \"resolved failing X tests\", not \"ran tests multiple times\".\n - Many versioning events = branch housekeeping. Fold into context, do not list each git command.\n\n2. Omit utility commands entirely. File size checks, file reads, grep searches, and cat commands are research steps — they are not outcomes and must not appear in the summary.\n\n3. Do not name the AI tool. For ai_session events: focus on what was built or committed. If a commits array is present in metadata, use those commit messages. Never write \"via Claude Code\", \"using Claude Code\", or similar — omit the tool name entirely.\n\n4. For other events with a hint field: describe the developer's intent, not the raw command.\n\n5. For dependencies events: infer the purpose from package names and describe the domain (bcrypt/jsonwebtoken → authentication, prisma/pg → database, jest/vitest → testing). For unfamiliar packages, name them directly.\n\n6. Fold supporting events into the narrative. Building, shipping, versioning, and file operations are context — only make them a bullet when they are the primary activity (e.g. a standalone build fix or deploy with no accompanying commits).\n\n7. Stick to what the events show. Do not infer subject matter from the branch name. Do not add details not derivable from the events.\n\n8. For code_edit events: these represent file saves from an IDE integration. Describe what was being built based on repository context (branch name, commit messages). Never list individual filenames.\n\nMaximum 5 bullets. Output ONLY the bullet points, nothing else.`\n\nexport function getSystemPrompt(): string {\n const contexts = getActiveProfileAiContexts()\n if (contexts.length === 0) return SYSTEM_PROMPT\n return SYSTEM_PROMPT + '\\n\\n' + contexts.join('\\n')\n}\n\n// Categories excluded from the AI payload by default:\n// - exploring/note: handled separately (notes rendered before event list; exploring is raw file reads)\n// - linting: lint/format runs are support noise, not meaningful work outcomes\n// `other` is intentionally kept — hints give the AI context for commands that don't fit known patterns\n// (e.g. docker compose up, make deploy, terraform apply). The prompt instructs the model to omit\n// utility commands (wc, head) within that category.\nexport const DEFAULT_EXCLUDED_CATEGORIES = new Set(['exploring', 'note', 'linting'])\n\nexport function buildExcludedSet(includeCategories: string[] = []): Set<string> {\n const excluded = new Set(DEFAULT_EXCLUDED_CATEGORIES)\n for (const cat of includeCategories) excluded.delete(cat)\n return excluded\n}\n\nexport function countExcludedEvents(\n sessions: DaySummaryPayload['sessions'],\n excluded: Set<string>\n): Map<string, number> {\n const counts = new Map<string, number>()\n for (const session of sessions) {\n for (const event of session.events) {\n if (excluded.has(event.category)) {\n counts.set(event.category, (counts.get(event.category) ?? 0) + 1)\n }\n }\n }\n return counts\n}\n\nexport function buildUserMessage(payload: DaySummaryPayload, includeCategories: string[] = []): string {\n const excluded = buildExcludedSet(includeCategories)\n const lines: string[] = [`Date: ${payload.date}`, '']\n\n for (const session of payload.sessions) {\n lines.push(`Project: ${session.project ?? 'unknown'}`)\n if (session.branch) lines.push(`Branch: ${session.branch}`)\n lines.push(`Duration: ${formatDuration(session.durationMinutes)}`)\n\n for (const event of session.events) {\n if (event.category === 'note') {\n lines.push(`NOTE: ${event.metadata.text as string}`)\n }\n }\n\n lines.push('Events:')\n\n // Aggregate repeated events so the model sees \"3x build\" not 3 separate build lines\n const counts = new Map<string, number>()\n for (const event of session.events) {\n if (excluded.has(event.category)) continue\n const failed = event.exitCode !== null && event.exitCode !== 0 ? ' [failed]' : ''\n let key: string\n if (event.category === 'code_edit') {\n // Strip file paths — AI should describe intent from context, not enumerate files\n key = `code_edit${failed}`\n } else if (event.hint) {\n key = `other [${event.hint}]${failed}`\n } else {\n const meta = Object.keys(event.metadata).length > 0 ? ` ${JSON.stringify(event.metadata)}` : ''\n key = `${event.category}${meta}${failed}`\n }\n counts.set(key, (counts.get(key) ?? 0) + 1)\n }\n\n for (const [key, count] of counts) {\n lines.push(` - ${count > 1 ? `${count}x ` : ''}${key}`)\n }\n\n lines.push('')\n }\n\n return lines.join('\\n')\n}\n\nexport const WEEKLY_SYSTEM_PROMPT = `You write short weekly developer summaries. Here is an example:\n\nINPUT:\nWeek: 2026-05-18 to 2026-05-22\n\nMonday 2026-05-18:\n Project: api-service (feature/auth) — 2h 10m\n Events: 3x code_commit, 2x test_run, dependency_install\n\nTuesday 2026-05-19:\n Project: api-service (feature/auth) — 1h 30m\n Events: 2x code_commit, test_run, build\n\nWednesday 2026-05-20:\n Project: dashboard (main) — 3h 00m\n Events: 4x code_commit, 2x build, test_run\n\nThursday 2026-05-21:\n Project: api-service (feature/auth) — 1h 00m\n Events: code_commit {\"message\":\"feat: merge auth\"}, branch_switch\n\nFriday 2026-05-22:\n Project: dashboard (main) — 2h 00m\n Events: 3x code_commit, build\n\nOUTPUT:\n## Week of 18 May — 9h 40m across 2 projects\n\n**api-service** (Mon–Thu): Built and shipped the auth feature — JWT setup, token validation fixes, and final merge.\n**dashboard** (Wed, Fri): Active development across 7 commits with builds passing.\n\nNow summarise the following week. Output ONLY the summary — a one-line header then one bullet per active project. Maximum 4 bullets.`\n\nconst DAY_NAMES = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']\n\nexport function buildWeeklyMessage(payload: WeekSummaryPayload): string {\n const lines: string[] = [`Week: ${payload.weekStart} to ${payload.weekEnd}`, '']\n\n for (const { date, sessions } of payload.days) {\n const dayName = DAY_NAMES[new Date(date + 'T00:00:00').getDay()]\n lines.push(`${dayName} ${date}:`)\n\n for (const session of sessions) {\n const project = session.project ?? 'unknown'\n const branch = session.branch ? ` (${session.branch})` : ''\n lines.push(` Project: ${project}${branch} — ${formatDuration(session.durationMinutes)}`)\n\n for (const event of session.events) {\n if (event.category === 'note') {\n lines.push(` NOTE: ${event.metadata.text as string}`)\n }\n }\n\n const excluded = buildExcludedSet()\n const counts = new Map<string, number>()\n for (const event of session.events) {\n if (excluded.has(event.category)) continue\n const failed = event.exitCode !== null && event.exitCode !== 0 ? ' [failed]' : ''\n let key: string\n if (event.category === 'code_edit') {\n key = `code_edit${failed}`\n } else if (event.hint) {\n key = `other [${event.hint}]${failed}`\n } else {\n const meta = Object.keys(event.metadata).length > 0 ? ` ${JSON.stringify(event.metadata)}` : ''\n key = `${event.category}${meta}${failed}`\n }\n counts.set(key, (counts.get(key) ?? 0) + 1)\n }\n const eventLine = [...counts.entries()].map(([key, count]) => `${count > 1 ? `${count}x ` : ''}${key}`).join(', ')\n lines.push(` Events: ${eventLine}`)\n }\n\n lines.push('')\n }\n\n return lines.join('\\n')\n}\n","import type { AIProvider, DaySummaryPayload, WeekSummaryPayload } from './types'\nimport { getSystemPrompt, buildUserMessage, WEEKLY_SYSTEM_PROMPT, buildWeeklyMessage } from './prompt'\nimport { fetchWithTimeout } from '../utils/fetch'\nimport type { ProviderConfig } from './provider-config'\n\nexport class GenericProvider implements AIProvider {\n constructor(\n private config: ProviderConfig,\n private model: string,\n private apiKey: string,\n private baseUrl: string,\n private includeCategories: string[] = []\n ) {}\n\n private async call(system: string, userMsg: string, maxTokens: number): Promise<string> {\n const response = await fetchWithTimeout(this.config.chatUrl(this.baseUrl, this.apiKey, this.model), {\n method: 'POST',\n headers: this.config.headers(this.apiKey),\n body: JSON.stringify(this.config.buildChatBody(this.model, system, userMsg, maxTokens)),\n })\n if (!response.ok) {\n throw new Error(this.config.chatError(response.status, await response.text()))\n }\n return this.config.parseText(await response.json())\n }\n\n async summarize(payload: DaySummaryPayload): Promise<string> {\n return this.call(getSystemPrompt(), buildUserMessage(payload, this.includeCategories), this.config.dailyTokens)\n }\n\n async summarizeWeek(payload: WeekSummaryPayload): Promise<string> {\n return this.call(WEEKLY_SYSTEM_PROMPT, buildWeeklyMessage(payload), this.config.weeklyTokens)\n }\n\n async validate(): Promise<void> {\n const isPost = this.config.validateMethod === 'POST'\n const response = await fetchWithTimeout(this.config.validateUrl(this.baseUrl, this.apiKey, this.model), {\n method: this.config.validateMethod,\n headers: isPost ? this.config.headers(this.apiKey) : undefined,\n body:\n isPost && this.config.buildValidateBody ? JSON.stringify(this.config.buildValidateBody(this.model)) : undefined,\n })\n if (!response.ok) {\n throw new Error(this.config.validateError(response.status, await response.text(), this.baseUrl))\n }\n }\n}\n","export interface ProviderConfig {\n defaultModel: string\n defaultBaseUrl: string\n dailyTokens: number\n weeklyTokens: number\n // apiKey and model are provided for providers that embed them in the URL (e.g. Gemini)\n chatUrl: (baseUrl: string, apiKey: string, model: string) => string\n validateUrl: (baseUrl: string, apiKey: string, model: string) => string\n validateMethod: 'GET' | 'POST'\n headers: (apiKey: string) => Record<string, string>\n buildChatBody: (model: string, system: string, userMsg: string, maxTokens: number) => object\n buildValidateBody?: (model: string) => object\n parseText: (json: unknown) => string\n chatError: (status: number, body: string) => string\n validateError: (status: number, body: string, baseUrl: string) => string\n}\n\nexport const PROVIDER_CONFIGS: Record<string, ProviderConfig> = {\n anthropic: {\n defaultModel: 'claude-haiku-4-5-20251001',\n defaultBaseUrl: 'https://api.anthropic.com/v1',\n dailyTokens: 1024,\n weeklyTokens: 1024,\n chatUrl: (baseUrl) => `${baseUrl}/messages`,\n validateUrl: (baseUrl) => `${baseUrl}/messages`,\n validateMethod: 'POST',\n headers: (apiKey) => ({\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n 'anthropic-version': '2023-06-01',\n }),\n buildChatBody: (model, system, userMsg, maxTokens) => ({\n model,\n max_tokens: maxTokens,\n system,\n messages: [{ role: 'user', content: userMsg }],\n }),\n buildValidateBody: (model) => ({\n model,\n max_tokens: 1,\n messages: [{ role: 'user', content: '.' }],\n }),\n parseText: (json) => {\n const data = json as { content: Array<{ type: string; text: string }> }\n return data.content.find((b) => b.type === 'text')?.text ?? ''\n },\n chatError: (status, body) => `Anthropic API error ${status}: ${body}`,\n validateError: (status, body) => `Anthropic API error ${status}: ${body}`,\n },\n\n openai: {\n defaultModel: 'gpt-4o-mini',\n defaultBaseUrl: 'https://api.openai.com/v1',\n dailyTokens: 1024,\n weeklyTokens: 1024,\n chatUrl: (baseUrl) => `${baseUrl}/chat/completions`,\n validateUrl: (baseUrl) => `${baseUrl}/chat/completions`,\n validateMethod: 'POST',\n headers: (apiKey) => ({\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n }),\n buildChatBody: (model, system, userMsg, maxTokens) => ({\n model,\n messages: [\n { role: 'system', content: system },\n { role: 'user', content: userMsg },\n ],\n max_tokens: maxTokens,\n }),\n buildValidateBody: (model) => ({\n model,\n messages: [{ role: 'user', content: '.' }],\n max_tokens: 1,\n }),\n parseText: (json) => {\n const data = json as { choices: Array<{ message: { content: string } }> }\n return data.choices[0]?.message?.content ?? ''\n },\n chatError: (status, body) => `OpenAI API error ${status}: ${body}`,\n validateError: (status, body) => `OpenAI API error ${status}: ${body}`,\n },\n\n ollama: {\n defaultModel: 'llama3',\n defaultBaseUrl: 'http://localhost:11434',\n dailyTokens: 300,\n weeklyTokens: 400,\n chatUrl: (baseUrl) => `${baseUrl}/api/chat`,\n validateUrl: (baseUrl) => `${baseUrl}/api/tags`,\n validateMethod: 'GET',\n headers: () => ({ 'Content-Type': 'application/json' }),\n buildChatBody: (model, system, userMsg, maxTokens) => ({\n model,\n stream: false,\n messages: [\n { role: 'system', content: system },\n { role: 'user', content: userMsg },\n ],\n options: { num_predict: maxTokens, temperature: 0.3 },\n }),\n parseText: (json) => {\n return (json as { message: { content: string } }).message?.content ?? ''\n },\n chatError: (status, body) => `Ollama error ${status}: ${body}. Is Ollama running? Try: ollama serve`,\n validateError: (_status, _body, baseUrl) =>\n `Ollama is not reachable at ${baseUrl}. Is it running? Try: ollama serve`,\n },\n\n gemini: {\n defaultModel: 'gemini-2.0-flash-lite',\n defaultBaseUrl: 'https://generativelanguage.googleapis.com/v1beta',\n dailyTokens: 1024,\n weeklyTokens: 1024,\n // API key and model are embedded in the URL — not in headers\n chatUrl: (baseUrl, apiKey, model) => `${baseUrl}/models/${model}:generateContent?key=${apiKey}`,\n validateUrl: (baseUrl, apiKey, model) => `${baseUrl}/models/${model}:generateContent?key=${apiKey}`,\n validateMethod: 'POST',\n headers: () => ({ 'Content-Type': 'application/json' }),\n buildChatBody: (_model, system, userMsg, maxTokens) => ({\n system_instruction: { parts: [{ text: system }] },\n contents: [{ role: 'user', parts: [{ text: userMsg }] }],\n generationConfig: { maxOutputTokens: maxTokens, temperature: 0.3 },\n }),\n buildValidateBody: () => ({\n contents: [{ role: 'user', parts: [{ text: '.' }] }],\n generationConfig: { maxOutputTokens: 1 },\n }),\n parseText: (json) => {\n const data = json as { candidates: Array<{ content: { parts: Array<{ text: string }> } }> }\n return data.candidates?.[0]?.content?.parts?.[0]?.text ?? ''\n },\n chatError: (status, body) => `Gemini API error ${status}: ${body}`,\n validateError: (status, body) => `Gemini API error ${status}: ${body}`,\n },\n\n groq: {\n defaultModel: 'llama-3.1-8b-instant',\n defaultBaseUrl: 'https://api.groq.com/openai/v1',\n dailyTokens: 1024,\n weeklyTokens: 1024,\n chatUrl: (baseUrl) => `${baseUrl}/chat/completions`,\n validateUrl: (baseUrl) => `${baseUrl}/models`,\n validateMethod: 'GET',\n headers: (apiKey) => ({\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n }),\n buildChatBody: (model, system, userMsg, maxTokens) => ({\n model,\n messages: [\n { role: 'system', content: system },\n { role: 'user', content: userMsg },\n ],\n max_tokens: maxTokens,\n }),\n parseText: (json) => {\n const data = json as { choices: Array<{ message: { content: string } }> }\n return data.choices?.[0]?.message?.content ?? ''\n },\n chatError: (status, body) => `Groq API error ${status}: ${body}`,\n validateError: (status, body) => `Groq API error ${status}: ${body}`,\n },\n}\n","import type { AIProvider } from './types'\nimport type { WorkscribeConfig } from '../config'\nimport { GenericProvider } from './generic-provider'\nimport { PROVIDER_CONFIGS } from './provider-config'\n\nexport function getProvider(config: WorkscribeConfig): AIProvider {\n const { provider, apiKey = '', model, baseUrl } = config.ai\n\n if (!provider) {\n throw new Error(\n 'No AI provider configured.\\nRun: workscribe config set ai.provider <anthropic|openai|gemini|groq|ollama|openai-compatible>'\n )\n }\n\n const configKey = provider === 'openai-compatible' ? 'openai' : provider\n const providerConfig = PROVIDER_CONFIGS[configKey]\n\n if (!providerConfig) {\n throw new Error(\n `Unknown provider: \"${provider}\"\\nSupported providers: anthropic, openai, gemini, groq, ollama, openai-compatible`\n )\n }\n\n if (provider !== 'ollama' && !apiKey) {\n throw new Error(`${provider} requires an API key.\\nRun: workscribe config set ai.apiKey <your-key>`)\n }\n\n if (provider === 'openai-compatible' && !baseUrl) {\n throw new Error('openai-compatible requires a base URL.\\nRun: workscribe config set ai.baseUrl <url>')\n }\n\n return new GenericProvider(\n providerConfig,\n model || providerConfig.defaultModel,\n apiKey,\n baseUrl || providerConfig.defaultBaseUrl,\n config.summary?.includeCategories ?? []\n )\n}\n","export interface CompletionCommand {\n name: string\n description: string\n}\n\nexport function bashCompletion(commands: CompletionCommand[]): string {\n const names = commands.map((command) => command.name).join(' ')\n return `\\\n_workscribe_completion() {\n local cur=\"\\${COMP_WORDS[COMP_CWORD]}\"\n local prev=\"\\${COMP_WORDS[COMP_CWORD-1]}\"\n local commands=\"${names}\"\n case \"$prev\" in\n completions) COMPREPLY=( $(compgen -W \"bash zsh fish\" -- \"$cur\") ); return ;;\n config) COMPREPLY=( $(compgen -W \"get set list\" -- \"$cur\") ); return ;;\n profile) COMPREPLY=( $(compgen -W \"list add remove update detect suggest\" -- \"$cur\") ); return ;;\n esac\n COMPREPLY=( $(compgen -W \"$commands\" -- \"$cur\") )\n}\ncomplete -F _workscribe_completion workscribe`\n}\n\nexport function zshCompletion(commands: CompletionCommand[]): string {\n const commandList = commands.map((command) => ` '${command.name}:${command.description}'`).join('\\n')\n return `\\\n#compdef workscribe\n_workscribe() {\n local state\n _arguments '1: :->command' '*: :->args'\n case $state in\n command)\n local -a commands\n commands=(\n${commandList}\n )\n _describe 'command' commands\n ;;\n args)\n case $words[2] in\n completions) local -a shells; shells=('bash' 'zsh' 'fish'); _describe 'shell' shells ;;\n config) local -a sub; sub=('get:Get a value' 'set:Set a value' 'list:List all values'); _describe 'subcommand' sub ;;\n profile) local -a sub; sub=('list' 'add' 'remove' 'update' 'detect' 'suggest'); _describe 'subcommand' sub ;;\n esac\n ;;\n esac\n}\n_workscribe`\n}\n\nexport function fishCompletion(commands: CompletionCommand[]): string {\n const lines = [\n 'complete -c workscribe -f',\n ...commands.map(\n (command) =>\n `complete -c workscribe -n \"__fish_use_subcommand\" -a ${command.name.padEnd(12)} -d \"${command.description}\"`\n ),\n 'complete -c workscribe -n \"__fish_seen_subcommand_from completions\" -a \"bash zsh fish\"',\n 'complete -c workscribe -n \"__fish_seen_subcommand_from config\" -a \"get set list\"',\n 'complete -c workscribe -n \"__fish_seen_subcommand_from profile\" -a \"list add remove update detect suggest\"',\n ]\n return lines.join('\\n')\n}\n","import fs from 'fs'\nimport path from 'path'\nimport os from 'os'\nimport { execFileSync } from 'child_process'\nimport { log } from '../utils/logger'\nimport { CompletionCommand, bashCompletion, zshCompletion, fishCompletion } from '../utils/completion-scripts'\nimport { WORKSCRIBE_DIR } from '../utils/paths'\n\nconst FISH_COMPLETIONS_DIR = path.join(os.homedir(), '.config', 'fish', 'completions')\n\nconst HOOK_START = '# workscribe:hook:start'\nconst HOOK_END = '# workscribe:hook:end'\nconst HOOK_PREAMBLE = '# Workscribe — developer work journal'\n\nexport function getInstalledHookBlock(rcFile: string): string | null {\n if (!fs.existsSync(rcFile)) return null\n const content = fs.readFileSync(rcFile, 'utf-8')\n const startIdx = content.indexOf(HOOK_START)\n const endIdx = content.indexOf(HOOK_END)\n if (startIdx === -1 || endIdx === -1) return null\n return content.slice(startIdx, endIdx + HOOK_END.length)\n}\n\nexport function isHookInstalled(rcFile: string): boolean {\n return getInstalledHookBlock(rcFile) !== null\n}\n\nexport function isHookOutdated(rcFile: string, hookContent: string): boolean {\n const installed = getInstalledHookBlock(rcFile)\n if (!installed) return false\n return installed.trim() !== hookContent.trim()\n}\n\nexport function installHook(rcFile: string, hookContent: string): void {\n const backup = `${rcFile}.workscribe-backup-${Date.now()}`\n fs.copyFileSync(rcFile, backup)\n log.info(`Backed up ${rcFile} → ${path.basename(backup)}`)\n fs.appendFileSync(rcFile, `\\n${hookContent}\\n`)\n}\n\nexport function updateHook(rcFile: string, hookContent: string): void {\n const backup = `${rcFile}.workscribe-backup-${Date.now()}`\n fs.copyFileSync(rcFile, backup)\n log.info(`Backed up ${rcFile} → ${path.basename(backup)}`)\n const content = fs.readFileSync(rcFile, 'utf-8')\n const startIdx = content.indexOf(HOOK_START)\n const endIdx = content.indexOf(HOOK_END) + HOOK_END.length\n fs.writeFileSync(rcFile, content.slice(0, startIdx) + hookContent + content.slice(endIdx))\n}\n\nexport function removeHook(rcFile: string): void {\n const backup = `${rcFile}.workscribe-backup-${Date.now()}`\n fs.copyFileSync(rcFile, backup)\n log.info(`Backed up ${rcFile} → ${path.basename(backup)}`)\n const content = fs.readFileSync(rcFile, 'utf-8')\n const startIdx = content.indexOf(HOOK_START)\n const endIdx = content.indexOf(HOOK_END) + HOOK_END.length\n // Also remove the preamble comment lines that installHook writes before HOOK_START\n const preambleIdx = content.lastIndexOf(HOOK_PREAMBLE, startIdx)\n const blockStart = preambleIdx !== -1 ? preambleIdx : startIdx\n const before = content.slice(0, blockStart).replace(/\\n+$/, '\\n')\n const after = content.slice(endIdx).replace(/^\\n/, '')\n fs.writeFileSync(rcFile, before + after)\n}\n\nexport function resolveWorkscribeBinary(): string | null {\n try {\n const resolved = execFileSync('which', ['workscribe'], { encoding: 'utf-8' }).trim()\n return resolved || null\n } catch {\n return null\n }\n}\n\n/**\n * nodePath pins the Node interpreter alongside the workscribe script path.\n * Without it, workscribe's own shebang (`#!/usr/bin/env -S node ...`) still\n * dynamically resolves `node` via whatever PATH is active in the shell at\n * capture time — so a hardcoded binaryPath alone doesn't protect against a\n * stale/wrong default Node version in that shell, only against the\n * workscribe script itself moving. nodePath should be process.execPath,\n * captured at `workscribe init` time when it's guaranteed to be 22+.\n */\nexport function injectBinaryPath(hookContent: string, binaryPath: string, nodePath: string): string {\n const pinnedInvocation = `\"${nodePath}\" \"${binaryPath}\"`\n return hookContent\n .replace('command -v workscribe > /dev/null 2>&1 || return 0', `[[ -x \"${binaryPath}\" ]] || return 0`)\n .replace('command -v workscribe &>/dev/null || return 0', `[[ -x \"${binaryPath}\" ]] || return 0`)\n .replace('type -q workscribe\\n or return 0', `test -x \"${binaryPath}\"\\n or return 0`)\n .replaceAll('command workscribe _capture', `${pinnedInvocation} _capture`)\n .replaceAll('command workscribe alerts', `${pinnedInvocation} alerts`)\n}\n\nexport function isCompletionsInstalled(shell: { name: string; rcFile: string }): boolean {\n if (shell.name === 'fish') {\n return fs.existsSync(path.join(FISH_COMPLETIONS_DIR, 'workscribe.fish'))\n }\n try {\n return fs.readFileSync(shell.rcFile, 'utf-8').includes('workscribe completions')\n } catch {\n return false\n }\n}\n\nexport function installCompletions(shell: { name: string; rcFile: string }, commands: CompletionCommand[]): void {\n if (shell.name === 'fish') {\n if (!fs.existsSync(FISH_COMPLETIONS_DIR)) {\n fs.mkdirSync(FISH_COMPLETIONS_DIR, { recursive: true })\n }\n fs.writeFileSync(path.join(FISH_COMPLETIONS_DIR, 'workscribe.fish'), fishCompletion(commands), { mode: 0o644 })\n } else {\n const script = shell.name === 'zsh' ? zshCompletion(commands) : bashCompletion(commands)\n const cacheFile = path.join(WORKSCRIBE_DIR, `completion.${shell.name}`)\n fs.writeFileSync(cacheFile, script, { mode: 0o644 })\n const sourceLine =\n shell.name === 'zsh'\n ? `\\n# Workscribe completions\\nautoload -Uz compinit && compinit\\nsource \"${cacheFile}\"\\n`\n : `\\n# Workscribe completions\\nsource \"${cacheFile}\"\\n`\n fs.appendFileSync(shell.rcFile, sourceLine)\n }\n}\n","import { execSync } from 'child_process'\n\n/** Returns true if the given CLI command is available on PATH */\nexport function isCommandInstalled(cmd: string): boolean {\n try {\n execSync(`which ${cmd}`, { stdio: 'ignore' })\n return true\n } catch {\n return false\n }\n}\n","import fs from 'fs'\nimport path from 'path'\nimport os from 'os'\nimport { execFileSync } from 'child_process'\nimport type { AIHookIntegration } from './types'\nimport { isCommandInstalled } from './utils'\nimport { resolveWorkscribeBinary } from '../shell-hook'\n\nconst CLAUDE_SETTINGS_PATH = path.join(os.homedir(), '.claude', 'settings.json')\n\n// Identifies a workscribe hook entry regardless of whether it's the legacy\n// bare `workscribe _hook ...` form or the pinned `\"<node>\" \"<workscribe>\" _hook ...`\n// form below — both contain this exact substring.\nconst HOOK_MARKER = '_hook --source claude-code'\n\nfunction readSettings(): Record<string, unknown> {\n if (!fs.existsSync(CLAUDE_SETTINGS_PATH)) return {}\n try {\n return JSON.parse(fs.readFileSync(CLAUDE_SETTINGS_PATH, 'utf-8')) as Record<string, unknown>\n } catch {\n return {}\n }\n}\n\nfunction commandsForEvent(hooks: Record<string, unknown>, eventName: string): string[] {\n const entries = (hooks[eventName] ?? []) as unknown[]\n const commands: string[] = []\n for (const entry of entries) {\n const entryHooks = ((entry as Record<string, unknown>).hooks ?? []) as unknown[]\n for (const hookItem of entryHooks) {\n const hook = hookItem as Record<string, unknown>\n if (typeof hook.command === 'string' && hook.command.includes(HOOK_MARKER)) {\n commands.push(hook.command)\n }\n }\n }\n return commands\n}\n\nfunction findWorkscribeHookCommands(settings: Record<string, unknown>): {\n postToolUse: string[]\n userPromptSubmit: string[]\n} {\n const hooks = (settings.hooks ?? {}) as Record<string, unknown>\n return {\n postToolUse: commandsForEvent(hooks, 'PostToolUse'),\n userPromptSubmit: commandsForEvent(hooks, 'UserPromptSubmit'),\n }\n}\n\n/**\n * A command is \"pinned\" if it starts with an absolute path (to a node\n * interpreter) rather than the bare `workscribe` string. Pinned commands are\n * immune to PATH/Node-version drift between install time and whatever\n * environment the hook actually fires in — the same class of hardening\n * WOR-75 applied to the shell hook, extended here to also cover the Node\n * interpreter itself, not just the workscribe script path.\n */\nfunction isPinnedCommand(command: string): boolean {\n const trimmed = command.trimStart()\n return trimmed.startsWith('\"') || trimmed.startsWith('/')\n}\n\n/**\n * Strips any existing workscribe hook entries out of a hooks array for one\n * event type, so install() can be called repeatedly — fresh install or\n * repairing a stale/unpinned one — without ever accumulating duplicates.\n */\nfunction withoutWorkscribeEntries(entries: unknown[]): unknown[] {\n return entries\n .map((entry) => {\n const record = entry as Record<string, unknown>\n const entryHooks = (record.hooks ?? []) as unknown[]\n const filteredHooks = entryHooks.filter((hookItem) => {\n const hook = hookItem as Record<string, unknown>\n return !(typeof hook.command === 'string' && hook.command.includes(HOOK_MARKER))\n })\n return { ...record, hooks: filteredHooks }\n })\n .filter((entry) => ((entry as Record<string, unknown>).hooks as unknown[]).length > 0)\n}\n\nexport interface ClaudeCodeHookHealth {\n installed: boolean\n pinned: boolean\n /** Only meaningful when installed && !pinned; null otherwise. */\n confirmedBroken: boolean | null\n}\n\n/**\n * Checks whether an installed Claude Code hook uses the pinned (safe) or\n * bare (vulnerable to Node-version/PATH drift) command form, and — for bare\n * commands only — attempts a live probe to confirm whether it's actually\n * broken right now. The probe is best-effort: it inherits this process's own\n * environment, which can't perfectly replicate whatever environment Claude\n * Code invokes hooks in, but a failure here is still strong evidence of a\n * real, currently-happening problem rather than a theoretical risk.\n */\nexport function checkHookHealth(): ClaudeCodeHookHealth {\n const { postToolUse, userPromptSubmit } = findWorkscribeHookCommands(readSettings())\n const allCommands = [...postToolUse, ...userPromptSubmit]\n if (allCommands.length === 0) return { installed: false, pinned: true, confirmedBroken: null }\n\n if (allCommands.every(isPinnedCommand)) return { installed: true, pinned: true, confirmedBroken: null }\n\n let confirmedBroken: boolean\n try {\n execFileSync('workscribe', ['--version'], { stdio: 'ignore', timeout: 2000 })\n confirmedBroken = false\n } catch {\n confirmedBroken = true\n }\n\n return { installed: true, pinned: false, confirmedBroken }\n}\n\nexport const claudeCodeIntegration: AIHookIntegration = {\n displayName: 'Claude Code',\n\n isInstalled() {\n return isCommandInstalled('claude')\n },\n\n // \"Installed\" means a *correctly pinned* hook is present, not just any\n // workscribe hook — this is deliberate: it makes `workscribe init`'s\n // existing prompt-and-install flow naturally offer to repair a stale,\n // unpinned hook from before this fix, with no new UI code needed there.\n isHookInstalled() {\n const { postToolUse, userPromptSubmit } = findWorkscribeHookCommands(readSettings())\n if (postToolUse.length === 0 || userPromptSubmit.length === 0) return false\n return [...postToolUse, ...userPromptSubmit].every(isPinnedCommand)\n },\n\n install() {\n const settings = readSettings()\n const existingHooks = (settings.hooks ?? {}) as Record<string, unknown>\n const existingPostToolUse = withoutWorkscribeEntries((existingHooks.PostToolUse ?? []) as unknown[])\n const existingUserPromptSubmit = withoutWorkscribeEntries((existingHooks.UserPromptSubmit ?? []) as unknown[])\n\n const workscribeBinary = resolveWorkscribeBinary()\n const baseCommand = workscribeBinary ? `\"${process.execPath}\" \"${workscribeBinary}\"` : 'workscribe'\n\n settings.hooks = {\n ...existingHooks,\n PostToolUse: [\n ...existingPostToolUse,\n {\n matcher: 'Bash',\n hooks: [{ type: 'command', command: `${baseCommand} ${HOOK_MARKER}`, async: true }],\n },\n ],\n UserPromptSubmit: [\n ...existingUserPromptSubmit,\n {\n hooks: [\n {\n type: 'command',\n command: `${baseCommand} ${HOOK_MARKER} --event UserPromptSubmit`,\n },\n ],\n },\n ],\n }\n fs.mkdirSync(path.dirname(CLAUDE_SETTINGS_PATH), { recursive: true })\n fs.writeFileSync(CLAUDE_SETTINGS_PATH, JSON.stringify(settings, null, 2))\n },\n}\n","import type { AIHookIntegration } from './types'\nimport { claudeCodeIntegration } from './claude-code'\n\n/**\n * Registry of AI tool hook integrations, keyed by the \"hook\" field in src/config/ai-tools.json.\n * Adding support for a new tool = add a new entry here and a corresponding integration file.\n */\nexport const AI_HOOK_INTEGRATIONS: Record<string, AIHookIntegration> = {\n 'claude-code': claudeCodeIntegration,\n}\n","import { Command } from 'commander'\nimport { log } from '../utils/logger'\nimport { CompletionCommand, bashCompletion, zshCompletion, fishCompletion } from '../utils/completion-scripts'\n\nexport type { CompletionCommand }\nexport { bashCompletion, zshCompletion, fishCompletion }\n\nconst HIDDEN_COMMANDS = new Set(['_capture', '_hook'])\n\nexport function getPublicCommands(program: Command): CompletionCommand[] {\n return program.commands\n .filter((command) => !HIDDEN_COMMANDS.has(command.name()))\n .map((command) => ({ name: command.name(), description: command.description() }))\n}\n\nexport function registerCompletions(program: Command): void {\n program\n .command('completions [shell]')\n .description('Print shell completion script (bash, zsh, fish)')\n .action((shell?: string) => {\n const detected = shell ?? (process.env.SHELL ?? '').split('/').at(-1)\n\n if (!detected || !['bash', 'zsh', 'fish'].includes(detected)) {\n log.error(`Unknown shell: \"${detected ?? ''}\". Supported: bash, zsh, fish`)\n log.plain(` Usage: workscribe completions <bash|zsh|fish>`)\n process.exit(1)\n }\n\n const commands = getPublicCommands(program)\n const script =\n detected === 'bash'\n ? bashCompletion(commands)\n : detected === 'zsh'\n ? zshCompletion(commands)\n : fishCompletion(commands)\n\n process.stdout.write(script + '\\n')\n })\n}\n","import { Command } from 'commander'\nimport fs from 'fs'\nimport path from 'path'\nimport os from 'os'\nimport prompts from 'prompts'\nimport chalk from 'chalk'\nimport { CONFIG_PATH, PROFILES_DIR, REQUIRED_DIRS } from '../utils/paths'\nimport { readConfig, writeConfig } from '../config'\nimport { detectProfilesForDirectory } from '../profiles/loader'\nimport { installProfile, cacheManifest } from '../profiles/fetcher'\nimport { getDb } from '../db'\nimport { getProvider } from '../ai/router'\nimport { log } from '../utils/logger'\nimport { loadAIToolRegistry } from '../config/registry'\nimport {\n isHookInstalled,\n isHookOutdated,\n installHook,\n updateHook,\n isCompletionsInstalled,\n installCompletions,\n resolveWorkscribeBinary,\n injectBinaryPath,\n} from '../capture/shell-hook'\nimport { AI_HOOK_INTEGRATIONS } from '../capture/hooks'\nimport { getPublicCommands } from './completions'\n\nfunction detectShell(): { name: string; rcFile: string } | null {\n const shell = process.env.SHELL ?? ''\n if (shell.includes('zsh')) return { name: 'zsh', rcFile: path.join(os.homedir(), '.zshrc') }\n if (shell.includes('bash')) return { name: 'bash', rcFile: path.join(os.homedir(), '.bashrc') }\n if (shell.includes('fish')) {\n const confDir = path.join(os.homedir(), '.config', 'fish', 'conf.d')\n return { name: 'fish', rcFile: path.join(confDir, 'workscribe.fish') }\n }\n return null\n}\n\nfunction step(current: number, total: number, label: string): void {\n log.plain(chalk.bold(`\\n [${current}/${total}] ${label}`))\n}\n\nexport function registerInit(program: Command): void {\n program\n .command('init')\n .description('Set up Workscribe and install or update shell hooks')\n .action(async () => {\n const TOTAL_STEPS = 5\n log.plain(chalk.bold('\\n Workscribe — Developer Work Journal\\n'))\n\n // ── Step 1: Data directories ──────────────────────────────────────────────\n step(1, TOTAL_STEPS, 'Creating data directories')\n\n for (const dir of REQUIRED_DIRS) {\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true, mode: 0o700 })\n log.success(`Created ${dir}`)\n } else {\n try {\n fs.chmodSync(dir, 0o700)\n } catch {\n /* ignore */\n }\n log.info(`${dir} already exists`)\n }\n }\n\n if (!fs.existsSync(PROFILES_DIR)) {\n fs.mkdirSync(PROFILES_DIR, { recursive: true, mode: 0o700 })\n }\n\n // ── Step 2: Database ──────────────────────────────────────────────────────\n step(2, TOTAL_STEPS, 'Initialising database')\n getDb()\n log.success('Database ready')\n\n // ── Step 3: Shell hook + completions ──────────────────────────────────────\n step(3, TOTAL_STEPS, 'Installing shell hook')\n\n const shell = detectShell()\n if (!shell) {\n log.warn('Could not detect shell. Supported: zsh, bash, fish')\n log.plain(\n ` Manually add the hook from: ${chalk.cyan('shell/hook.zsh')}, ${chalk.cyan('shell/hook.bash')}, or ${chalk.cyan('shell/hook.fish')}`\n )\n } else {\n const hookFile = path.join(__dirname, '..', 'shell', `hook.${shell.name}`)\n if (!fs.existsSync(hookFile)) {\n log.warn(`Hook template not found at ${hookFile}`)\n } else {\n const hookContent = fs.readFileSync(hookFile, 'utf-8')\n const binaryPath = resolveWorkscribeBinary()\n const hookWithPath = binaryPath ? injectBinaryPath(hookContent, binaryPath, process.execPath) : hookContent\n\n // For fish: ensure conf.d directory exists before touching the file\n if (shell.name === 'fish') {\n const confDir = path.dirname(shell.rcFile)\n if (!fs.existsSync(confDir)) fs.mkdirSync(confDir, { recursive: true })\n }\n\n if (!fs.existsSync(shell.rcFile)) fs.writeFileSync(shell.rcFile, '')\n\n if (!isHookInstalled(shell.rcFile)) {\n log.plain('')\n log.plain(chalk.dim(' Workscribe adds a lightweight hook to your shell that captures each'))\n log.plain(chalk.dim(' command you run — the text, exit code, duration, and working directory.'))\n log.plain(chalk.dim(' It runs in the background and adds no latency to your terminal.'))\n log.plain(chalk.dim(' Credentials and secrets are redacted before anything is stored.'))\n log.plain('')\n installHook(shell.rcFile, hookWithPath)\n log.success(`Shell hook installed in ${shell.rcFile}`)\n } else if (isHookOutdated(shell.rcFile, hookWithPath)) {\n const { update } = await prompts({\n type: 'confirm',\n name: 'update',\n message: `Shell hook in ${shell.rcFile} is outdated. Update?`,\n initial: true,\n })\n if (update) {\n updateHook(shell.rcFile, hookWithPath)\n log.success(`Shell hook updated in ${shell.rcFile}`)\n } else {\n log.info('Shell hook update skipped')\n }\n } else {\n log.info(`Shell hook up to date in ${shell.rcFile}`)\n }\n\n // Offer completions install\n if (isCompletionsInstalled(shell)) {\n log.info('Shell completions already installed')\n } else {\n const { installComps } = await prompts({\n type: 'confirm',\n name: 'installComps',\n message: 'Install shell completions (tab-complete workscribe commands)?',\n initial: true,\n })\n if (installComps) {\n try {\n installCompletions(shell, getPublicCommands(program))\n log.success('Shell completions installed')\n } catch (error) {\n log.warn(`Completions install failed: ${(error as Error).message}`)\n }\n }\n }\n }\n }\n\n // ── Step 4: AI tools ──────────────────────────────────────────────────────\n step(4, TOTAL_STEPS, 'Detecting AI coding tools')\n\n const installedTools = loadAIToolRegistry().filter(\n (entry) => entry.hook !== null && AI_HOOK_INTEGRATIONS[entry.hook!]?.isInstalled()\n )\n\n if (installedTools.length === 0) {\n log.info('No AI coding tools detected — re-run workscribe init after installing one')\n } else {\n for (const tool of installedTools) {\n const integration = AI_HOOK_INTEGRATIONS[tool.hook!]!\n\n if (integration.isHookInstalled()) {\n log.info(`${integration.displayName} session hook already installed`)\n } else {\n const { install } = await prompts({\n type: 'confirm',\n name: 'install',\n message: `${integration.displayName} detected. Install session capture hook?`,\n initial: false,\n })\n if (install) {\n integration.install()\n log.success(`${integration.displayName} session hook installed`)\n } else {\n log.info(`${integration.displayName} hook skipped — re-run workscribe init to install later`)\n }\n }\n }\n }\n\n // Profile detection (part of environment scan, no separate step)\n const config = readConfig()\n try {\n await cacheManifest()\n const detected = detectProfilesForDirectory(process.cwd())\n const alreadyActive = new Set(config.capture.profiles)\n const toPrompt = detected.filter((entry) => !alreadyActive.has(entry.name))\n\n if (toPrompt.length > 0) {\n log.plain('')\n for (const entry of toPrompt) {\n const { install } = await prompts({\n type: 'confirm',\n name: 'install',\n message: `${entry.displayName} project detected. Enable the ${entry.displayName} profile?`,\n initial: true,\n })\n if (install) {\n await installProfile(entry.name)\n config.capture.profiles = [...new Set([...config.capture.profiles, entry.name])]\n log.success(`${entry.displayName} profile enabled`)\n }\n }\n writeConfig(config)\n } else if (detected.length === 0) {\n log.info('No project profiles detected — run workscribe profile detect from your project directory')\n }\n } catch {\n log.info('Could not reach profile registry — run workscribe profile detect after connecting')\n }\n\n // ── Step 5: AI provider ───────────────────────────────────────────────────\n step(5, TOTAL_STEPS, 'Configuring AI provider')\n\n let providerConfigured = !!config.ai.provider\n\n if (config.ai.provider) {\n log.info(`AI provider already configured: ${chalk.cyan(config.ai.provider)}`)\n } else {\n log.plain('')\n const { provider } = await prompts({\n type: 'select',\n name: 'provider',\n message: 'Which AI provider do you want to use?',\n choices: [\n { title: 'Anthropic (Claude) — requires API key', value: 'anthropic' },\n { title: 'OpenAI — requires API key', value: 'openai' },\n { title: 'Ollama (local) — free, runs on your machine', value: 'ollama' },\n { title: 'Other (OpenAI-compatible) — Groq, Together, Mistral…', value: 'openai-compatible' },\n { title: 'Skip — configure later', value: 'skip' },\n ],\n })\n\n if (!provider || provider === 'skip') {\n providerConfigured = false\n log.info('Skipped — run later: workscribe config set ai.provider <provider>')\n } else {\n config.ai.provider = provider\n\n if (provider === 'ollama') {\n log.plain(`\\n ${chalk.dim('Make sure Ollama is running: ollama serve')}`)\n log.plain(\n ` ${chalk.dim('Default model: llama3 (change with: workscribe config set ai.model <model>)')}\\n`\n )\n } else {\n const { apiKey } = await prompts({\n type: 'password',\n name: 'apiKey',\n message: `Enter your ${provider === 'openai-compatible' ? '' : provider + ' '}API key:`,\n })\n if (apiKey) config.ai.apiKey = apiKey\n\n if (provider === 'openai-compatible') {\n const { baseUrl } = await prompts({\n type: 'text',\n name: 'baseUrl',\n message: 'Enter the base URL (e.g. https://api.groq.com/openai/v1):',\n })\n if (baseUrl) config.ai.baseUrl = baseUrl\n }\n }\n\n log.plain('')\n log.info(`Validating ${chalk.cyan(provider)} connection…`)\n try {\n const testProvider = getProvider(config)\n await testProvider.validate()\n log.success('API key verified')\n writeConfig(config)\n providerConfigured = true\n } catch (error) {\n log.warn(`Validation failed: ${(error as Error).message}`)\n const { retry } = await prompts({\n type: 'confirm',\n name: 'retry',\n message: 'Save anyway and configure later?',\n initial: false,\n })\n if (retry) {\n writeConfig(config)\n providerConfigured = false\n log.info('Config saved — run workscribe config set ai.apiKey <key> to update')\n } else {\n log.info('API key not saved — run workscribe init again to configure')\n providerConfigured = false\n }\n }\n }\n }\n\n // ── Config file ───────────────────────────────────────────────────────────\n if (!fs.existsSync(CONFIG_PATH)) {\n writeConfig(config)\n }\n\n // ── What to do next ───────────────────────────────────────────────────────\n log.plain('')\n log.plain(chalk.bold(' Setup complete!'))\n log.plain('')\n\n if (shell) {\n log.plain(` Activate capture now:`)\n if (shell.name === 'fish') {\n log.plain(` Restart your terminal`)\n log.plain(` ${chalk.dim(`or run: source ${shell.rcFile}`)}`)\n } else {\n log.plain(` ${chalk.cyan(`source ${shell.rcFile}`)}`)\n log.plain(` Or restart your terminal.`)\n }\n log.plain('')\n }\n\n if (providerConfigured) {\n log.plain(` Then run a few commands and generate your first summary:`)\n log.plain(` ${chalk.cyan('workscribe summary')}`)\n log.plain('')\n log.plain(` Check capture is working:`)\n log.plain(` ${chalk.cyan('workscribe status')}`)\n } else {\n log.plain(` Before generating summaries, configure an AI provider:`)\n log.plain(` ${chalk.cyan('workscribe config set ai.provider anthropic')}`)\n log.plain(` ${chalk.cyan('workscribe config set ai.apiKey <your-key>')}`)\n log.plain('')\n log.plain(` Then run:`)\n log.plain(` ${chalk.cyan('workscribe summary')}`)\n }\n\n log.plain('')\n })\n}\n","import { Command } from 'commander'\nimport fs from 'fs'\nimport chalk from 'chalk'\nimport { getEventCount, getLastEvent, getRecentOtherRate } from '../db'\nimport { readConfig } from '../config'\nimport { log } from '../utils/logger'\nimport { formatDate, todayDate } from '../utils/format'\nimport { getEventsForDate } from '../db'\nimport { PAUSE_FLAG_PATH } from '../utils/paths'\nimport { getPendingAlerts } from '../db/alerts'\nimport { checkHookHealth } from '../capture/hooks/claude-code'\n\nexport function registerStatus(program: Command): void {\n program\n .command('status')\n .description('Show capture status and event counts')\n .action(() => {\n const config = readConfig()\n const total = getEventCount()\n const todayEvents = getEventsForDate(todayDate())\n const last = getLastEvent()\n const isPaused = fs.existsSync(PAUSE_FLAG_PATH)\n\n log.plain('')\n log.plain(chalk.bold(' Workscribe Status'))\n log.plain('')\n\n if (isPaused) {\n log.plain(` Capture ${chalk.yellow('paused')} ${chalk.dim('(run: workscribe resume)')}`)\n } else {\n log.plain(` Capture ${chalk.green('active')}`)\n }\n\n log.plain(` Events today ${chalk.cyan(String(todayEvents.length))}`)\n log.plain(` Events total ${chalk.cyan(String(total))}`)\n\n if (last) {\n log.plain(` Last event ${formatDate(last.captured_at)} ${chalk.dim(last.command.slice(0, 60))}`)\n }\n\n log.plain('')\n log.plain(\n ` AI provider ${config.ai.provider ? chalk.cyan(config.ai.provider) : chalk.yellow('not configured')}`\n )\n if (config.ai.model) log.plain(` Model ${chalk.dim(config.ai.model)}`)\n\n const activeProfiles = config.capture.profiles\n log.plain(\n ` Profiles ${activeProfiles.length > 0 ? chalk.cyan(activeProfiles.join(', ')) : chalk.dim('none')}`\n )\n\n const pendingAlerts = getPendingAlerts()\n if (pendingAlerts.length > 0) {\n log.plain('')\n log.plain(\n ` ${chalk.yellow('!')} ${chalk.yellow(String(pendingAlerts.length))} pending security alert${pendingAlerts.length === 1 ? '' : 's'}` +\n chalk.dim(' (run: workscribe alerts)')\n )\n }\n\n const hookHealth = checkHookHealth()\n if (hookHealth.installed && !hookHealth.pinned) {\n log.plain('')\n if (hookHealth.confirmedBroken) {\n log.plain(\n ` ${chalk.yellow('⚠')} Claude Code hook is using an unpinned command and is failing right now — Claude Code activity is not being captured.`\n )\n } else {\n log.plain(\n ` ${chalk.yellow('⚠')} Claude Code hook is using an unpinned command, which can silently break if your default Node version changes.`\n )\n }\n log.plain(chalk.dim(' Run workscribe init to repair it'))\n }\n\n const { total: weekTotal, otherCount } = getRecentOtherRate(7)\n if (weekTotal > 0) {\n const otherPct = Math.round((otherCount / weekTotal) * 100)\n if (otherPct >= 25) {\n log.plain('')\n log.plain(\n ` ${chalk.yellow('⚠')} ${otherCount} of ${weekTotal} events (${otherPct}%) are uncategorised this week.`\n )\n log.plain(\n chalk.dim(\n ' Run workscribe profile detect — scan current directory for matching profiles\\n' +\n ' Run workscribe profile suggest — analyse your command history'\n )\n )\n }\n }\n\n log.plain('')\n })\n}\n","import { Command } from 'commander'\nimport chalk from 'chalk'\nimport { getEventsForDate } from '../db'\nimport { log } from '../utils/logger'\nimport { todayDate, parseDate, formatDate } from '../utils/format'\nimport { loadAIToolRegistry } from '../config/registry'\n\nconst CATEGORY_COLORS: Record<string, (s: string) => string> = {\n shipping: chalk.green,\n versioning: chalk.blue,\n building: chalk.cyan,\n running: chalk.white,\n testing: chalk.magenta,\n linting: chalk.yellow,\n dependencies: chalk.yellow,\n infrastructure: chalk.red,\n releasing: chalk.bold.green,\n database: chalk.bold.blue,\n files: chalk.dim.yellow,\n exploring: chalk.dim.cyan,\n ai_session: chalk.bold.magenta,\n other: chalk.gray,\n}\n\nconst AI_TOOL_DISPLAY_NAMES: Record<string, string> = Object.fromEntries(\n loadAIToolRegistry().map((entry) => [entry.tool, entry.displayName])\n)\n\nexport function registerEvents(program: Command): void {\n program\n .command('events')\n .description('List captured events')\n .option('--date <YYYY-MM-DD>', 'date to list events for (default: today)')\n .option('--limit <n>', 'max events to show', parseInt)\n .action((opts) => {\n let date = todayDate()\n if (opts.date) {\n try {\n date = parseDate(opts.date)\n } catch (e) {\n log.error((e as Error).message)\n process.exit(1)\n }\n }\n\n const events = getEventsForDate(date)\n const limit = opts.limit ?? events.length\n\n if (events.length === 0) {\n log.plain(`No events captured for ${date}`)\n return\n }\n\n log.plain('')\n log.plain(chalk.bold(` Events for ${date} (${events.length} total)`))\n log.plain('')\n\n for (const event of events.slice(0, limit)) {\n const colorFn = CATEGORY_COLORS[event.category] ?? chalk.gray\n const time = formatDate(event.captured_at)\n const category = colorFn(event.category.padEnd(20))\n const repo = event.repo_name ? chalk.dim(` [${event.repo_name}]`) : ''\n const exitBadge = event.exit_code && event.exit_code !== 0 ? chalk.red(` ✗${event.exit_code}`) : ''\n\n let cmdDisplay: string\n if (event.category === 'ai_session') {\n let meta: Record<string, unknown> = {}\n try {\n meta = event.metadata ? (JSON.parse(event.metadata) as Record<string, unknown>) : {}\n } catch {\n /* ignore */\n }\n const toolKey = typeof meta.tool === 'string' ? meta.tool : ''\n const toolName = AI_TOOL_DISPLAY_NAMES[toolKey] ?? toolKey\n cmdDisplay = chalk.white(toolName.padEnd(20)) + chalk.magenta(' ✦')\n } else {\n cmdDisplay = chalk.dim(event.command.slice(0, 55))\n }\n\n log.plain(` ${chalk.dim(time)} ${category} ${cmdDisplay}${repo}${exitBadge}`)\n }\n\n if (limit < events.length) {\n log.plain('')\n log.plain(chalk.dim(` … and ${events.length - limit} more (remove --limit to see all)`))\n }\n\n log.plain('')\n })\n}\n","import type { EventRow } from '../db/types'\n\n// captured_at is set at command completion (precmd fires after the command exits).\n// A long-running command's captured_at is its end time, so the gap between it and\n// the prior event equals the command's full duration — falsely triggering the idle\n// threshold. We use its start time (completion − duration) for gap calculation instead.\nexport const LONG_RUNNING_THRESHOLD_MS = 5 * 60 * 1000 // 5 minutes\n\n/**\n * Split a sorted list of events into groups separated by idle gaps.\n */\nexport function splitByIdleGap(events: EventRow[], idleMs: number): EventRow[][] {\n if (events.length === 0) return []\n const groups: EventRow[][] = [[events[0]]]\n\n for (let i = 1; i < events.length; i++) {\n const prev = new Date(events[i - 1].captured_at).getTime()\n const currCompleted = new Date(events[i].captured_at).getTime()\n const currDuration = events[i].duration_ms ?? 0\n const currEffective = currDuration >= LONG_RUNNING_THRESHOLD_MS ? currCompleted - currDuration : currCompleted\n\n if (currEffective - prev >= idleMs) {\n groups.push([events[i]])\n } else {\n groups[groups.length - 1].push(events[i])\n }\n }\n\n return groups\n}\n\n// A repo switch only starts a new sub-session if the gap since the last event\n// exceeds this threshold. A quick check in another repo and back should not\n// fragment the session.\nexport const REPO_SWITCH_GAP_MS = 10 * 60 * 1000 // 10 minutes\n\n/**\n * Split a list of events into groups by consecutive repo_name.\n * A repo change only creates a new group if the gap since the previous\n * event is at least `gapMs` (default 0 — splits on every repo change,\n * matching pre-WOR-72 behavior for callers that don't pass a threshold).\n */\nexport function splitByRepo(events: EventRow[], gapMs = 0): EventRow[][] {\n if (events.length === 0) return []\n const groups: EventRow[][] = [[events[0]]]\n\n for (let i = 1; i < events.length; i++) {\n const prevRepo = events[i - 1].repo_name\n const currRepo = events[i].repo_name\n const prevTime = new Date(events[i - 1].captured_at).getTime()\n const currTime = new Date(events[i].captured_at).getTime()\n const gap = currTime - prevTime\n\n if (currRepo !== prevRepo && gap >= gapMs) {\n groups.push([events[i]])\n } else {\n groups[groups.length - 1].push(events[i])\n }\n }\n\n return groups\n}\n\nexport function minutesBetween(start: string, end: string): number {\n return (new Date(end).getTime() - new Date(start).getTime()) / 60000\n}\n","import type { EventRow } from '../db/types'\nimport {\n insertSession,\n insertSessionEvent,\n clearSessionsForDate,\n getSessionsForDate,\n getEventsForDate,\n getEventsBySessionId,\n} from '../db'\nimport { readConfig } from '../config'\nimport { splitByIdleGap, splitByRepo, minutesBetween, REPO_SWITCH_GAP_MS } from './grouper'\n\nexport interface Session {\n id: number\n date: string\n startedAt: string\n endedAt: string\n repoName: string | null\n durationMinutes: number\n eventCount: number\n summary: string | null\n events: EventRow[]\n}\n\nexport function getOrBuildSessions(date: string): Session[] {\n // Check if sessions already exist for this date\n const existing = getSessionsForDate(date)\n const events = getEventsForDate(date)\n\n if (events.length === 0) return []\n\n // If sessions exist and event count matches, use cached\n const cachedEventCount = existing.reduce((sum, sessionRow) => sum + sessionRow.event_count, 0)\n if (existing.length > 0 && cachedEventCount === events.length) {\n return existing.map((sessionRow) => ({\n id: sessionRow.id,\n date: sessionRow.date,\n startedAt: sessionRow.started_at,\n endedAt: sessionRow.ended_at,\n repoName: sessionRow.repo_name,\n durationMinutes: minutesBetween(sessionRow.started_at, sessionRow.ended_at),\n eventCount: sessionRow.event_count,\n summary: sessionRow.summary,\n events: getEventsBySessionId(sessionRow.id),\n }))\n }\n\n // Preserve any cached summaries before clearing — keyed by repo+start time\n // so they can be restored to matching sessions after rebuild\n const savedSummaries = new Map<string, string>()\n for (const s of existing) {\n if (s.summary) savedSummaries.set(`${s.repo_name}|${s.started_at}`, s.summary)\n }\n\n // Rebuild sessions\n clearSessionsForDate(date)\n return buildSessions(date, events, savedSummaries)\n}\n\nfunction buildSessions(date: string, events: EventRow[], savedSummaries: Map<string, string> = new Map()): Session[] {\n const config = readConfig()\n const idleMs = config.session.idleTimeout * 60 * 1000\n\n const sessions: Session[] = []\n const timeGroups = splitByIdleGap(events, idleMs)\n\n for (const group of timeGroups) {\n if (group.length === 0) continue\n\n const repoGroups = splitByRepo(group, REPO_SWITCH_GAP_MS)\n\n for (const repoGroup of repoGroups) {\n if (repoGroup.length === 0) continue\n\n const first = repoGroup[0]\n const last = repoGroup[repoGroup.length - 1]\n const repoName = last.repo_name ?? first.repo_name ?? null\n\n // Restore a previously generated summary if the session boundaries match\n const summary = savedSummaries.get(`${repoName}|${first.captured_at}`) ?? null\n\n const sessionId = insertSession({\n date,\n started_at: first.captured_at,\n ended_at: last.captured_at,\n repo_name: repoName,\n event_count: repoGroup.length,\n summary,\n })\n\n for (const event of repoGroup) {\n insertSessionEvent(sessionId, event.id)\n }\n\n sessions.push({\n id: sessionId,\n date,\n startedAt: first.captured_at,\n endedAt: last.captured_at,\n repoName,\n durationMinutes: minutesBetween(first.captured_at, last.captured_at),\n eventCount: repoGroup.length,\n summary,\n events: repoGroup,\n })\n }\n }\n\n return sessions\n}\n","import { Command } from 'commander'\nimport chalk from 'chalk'\nimport { getOrBuildSessions } from '../sessions/detector'\nimport { log } from '../utils/logger'\nimport { todayDate, parseDate, formatDate, formatDuration } from '../utils/format'\n\nexport function registerSessions(program: Command): void {\n program\n .command('sessions')\n .description('List detected work sessions')\n .option('--date <YYYY-MM-DD>', 'date to show sessions for (default: today)')\n .action((opts) => {\n let date = todayDate()\n if (opts.date) {\n try {\n date = parseDate(opts.date)\n } catch (error) {\n log.error((error as Error).message)\n process.exit(1)\n }\n }\n\n const sessions = getOrBuildSessions(date)\n\n if (sessions.length === 0) {\n log.plain(`No sessions detected for ${date}`)\n return\n }\n\n log.plain('')\n log.plain(chalk.bold(` Sessions for ${date} (${sessions.length} session${sessions.length > 1 ? 's' : ''})`))\n log.plain('')\n\n for (const session of sessions) {\n const start = formatDate(session.startedAt)\n const end = formatDate(session.endedAt)\n const duration = formatDuration(session.durationMinutes)\n const repo = session.repoName ? chalk.cyan(session.repoName) : chalk.gray('no repo')\n log.plain(\n ` ${chalk.dim(start)} – ${chalk.dim(end)} ${repo} ${chalk.dim(duration)} ${chalk.dim(session.eventCount + ' events')}`\n )\n\n for (const event of session.events) {\n if (event.category === 'note') {\n let text = ''\n try {\n text = (JSON.parse(event.metadata ?? '{}') as { text?: string }).text ?? ''\n } catch {\n /* ignore malformed metadata */\n }\n if (text) log.plain(` ${chalk.yellow('note')} ${chalk.dim(text)}`)\n }\n }\n }\n\n log.plain('')\n })\n}\n","import { fetchWithTimeout } from '../utils/fetch'\n\nexport async function postToWebhook(url: string, text: string): Promise<void> {\n const response = await fetchWithTimeout(\n url,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ text }),\n },\n 10_000\n )\n\n if (!response.ok) {\n const body = await response.text()\n throw new Error(`Webhook POST failed ${response.status}: ${body}`)\n }\n}\n","/**\n * Converts workscribe markdown summary output to Slack mrkdwn format.\n *\n * Rules:\n * ## heading → *heading* (bold)\n * - bullet → • bullet\n *\n * An optional username is prepended as a dim header line so recipients\n * can tell who sent the summary in shared channels.\n */\nexport function formatForSlack(markdown: string, username?: string): string {\n const body = markdown.replace(/^## (.+)$/gm, '*$1*').replace(/^- /gm, '• ')\n return username ? `_${username}_\\n${body}` : body\n}\n\nexport function isSlackWebhookUrl(url: string): boolean {\n return url.startsWith('https://hooks.slack.com/')\n}\n","import { Command } from 'commander'\nimport chalk from 'chalk'\nimport fs from 'fs'\nimport os from 'os'\nimport path from 'path'\nimport { getOrBuildSessions } from '../sessions/detector'\nimport { getProvider } from '../ai/router'\nimport { readConfig } from '../config'\nimport { updateSessionSummary } from '../db'\nimport { log } from '../utils/logger'\nimport {\n todayDate,\n parseDate,\n formatDate,\n formatDuration,\n startOfWeek,\n eachDayOfRange,\n isoWeekKey,\n} from '../utils/format'\nimport { postToWebhook } from '../integrations/webhook'\nimport { formatForSlack, isSlackWebhookUrl } from '../integrations/slack'\nimport { WEEKLY_CACHE_DIR } from '../utils/paths'\nimport type { DaySummaryPayload, SessionPayload, EventPayload, WeekSummaryPayload } from '../ai/types'\nimport type { EventRow } from '../db'\nimport { buildExcludedSet, countExcludedEvents } from '../ai/prompt'\n\ninterface SessionSummaryJson {\n project: string | null\n branch: string | null\n durationMinutes: number\n bullets: string[]\n}\n\n/** Parse AI bullet output into a clean string array. Handles both - and • prefixes. */\nexport function parseBullets(text: string): string[] {\n return text\n .split('\\n')\n .map((line) => line.replace(/^[•\\-]\\s*/, '').trim())\n .filter(Boolean)\n}\n\nfunction eventRowToPayload(row: EventRow): EventPayload {\n let metadata: Record<string, unknown> = {}\n try {\n if (row.metadata) metadata = JSON.parse(row.metadata)\n } catch {\n /* ignore */\n }\n const payload: EventPayload = {\n category: row.category,\n metadata,\n exitCode: row.exit_code,\n durationMs: row.duration_ms,\n }\n if (row.category === 'other' && typeof metadata.hint === 'string') {\n payload.hint = metadata.hint\n const { hint: _hint, tool: _tool, ...rest } = metadata\n payload.metadata = rest\n }\n return payload\n}\n\nfunction sessionToPayload(s: ReturnType<typeof getOrBuildSessions>[number], date: string): SessionPayload {\n return {\n date,\n project: s.repoName,\n branch: s.events[0]?.branch ?? null,\n startTime: formatDate(s.startedAt),\n endTime: formatDate(s.endedAt),\n durationMinutes: s.durationMinutes,\n events: s.events.map(eventRowToPayload),\n }\n}\n\nasync function handleWebhook(\n opts: { slack?: boolean; webhook?: string },\n config: ReturnType<typeof readConfig>,\n summary: string\n): Promise<void> {\n const webhookUrl = opts.webhook ?? (opts.slack ? config.integrations?.slackWebhook : undefined)\n\n if (webhookUrl) {\n try {\n log.info('Posting to webhook…')\n const username = os.userInfo().username\n const body = isSlackWebhookUrl(webhookUrl) ? formatForSlack(summary, username) : summary\n await postToWebhook(webhookUrl, body)\n log.success('Posted.')\n } catch (error) {\n log.error(`Webhook failed: ${(error as Error).message}`)\n }\n } else if (opts.slack && !config.integrations?.slackWebhook) {\n log.warn('--slack requires integrations.slackWebhook to be set in config')\n }\n}\n\nexport function registerSummary(program: Command): void {\n program\n .command('summary')\n .description('Generate an AI work summary')\n .option('--date <YYYY-MM-DD>', 'date to summarize (default: today)')\n .option('--week', 'summarize the current week')\n .option('--fresh', 'bypass cache and regenerate')\n .option('--verbose', 'show all captured events including those not sent to AI')\n .option('--slack', 'post summary to Slack webhook from config')\n .option('--webhook <url>', 'post summary to a custom webhook URL')\n .action(async (opts) => {\n const config = readConfig()\n let provider\n try {\n provider = getProvider(config)\n } catch (error) {\n log.error((error as Error).message)\n process.exit(1)\n }\n\n // ── Weekly branch ────────────────────────────────────────────────────────\n if (opts.week) {\n const today = todayDate()\n const weekStart = startOfWeek(today)\n const days = eachDayOfRange(weekStart, today)\n\n const weeklyDays: WeekSummaryPayload['days'] = []\n for (const day of days) {\n const sessions = getOrBuildSessions(day)\n if (sessions.length > 0) {\n weeklyDays.push({ date: day, sessions: sessions.map((session) => sessionToPayload(session, day)) })\n }\n }\n\n if (weeklyDays.length === 0) {\n log.plain('No activity captured this week.')\n return\n }\n\n const cacheKey = isoWeekKey(today)\n const cacheFile = path.join(WEEKLY_CACHE_DIR, `${cacheKey}.md`)\n\n if (!opts.fresh && fs.existsSync(cacheFile)) {\n const cached = fs.readFileSync(cacheFile, 'utf-8')\n log.plain('')\n log.plain(cached)\n log.plain('')\n log.plain(chalk.dim(' (cached — use --fresh to regenerate)'))\n await handleWebhook(opts, config, cached)\n return\n }\n\n const payload: WeekSummaryPayload = { weekStart, weekEnd: today, days: weeklyDays }\n\n log.plain('')\n log.info(`Generating weekly summary via ${chalk.cyan(config.ai.provider)}…`)\n\n try {\n const summary = provider.summarizeWeek\n ? await provider.summarizeWeek(payload)\n : await provider.summarize({ date: today, sessions: weeklyDays.flatMap((day) => day.sessions) })\n\n log.plain('')\n log.plain(summary)\n log.plain('')\n\n fs.mkdirSync(WEEKLY_CACHE_DIR, { recursive: true })\n fs.writeFileSync(cacheFile, summary, { encoding: 'utf-8', mode: 0o600 })\n\n await handleWebhook(opts, config, summary)\n } catch (error) {\n log.error(`Weekly summary failed [${config.ai.provider}]: ${(error as Error).message}`)\n process.exit(1)\n }\n return\n }\n\n // ── Daily branch ─────────────────────────────────────────────────────────\n let date = todayDate()\n if (opts.date) {\n try {\n date = parseDate(opts.date)\n } catch (error) {\n log.error((error as Error).message)\n process.exit(1)\n }\n }\n\n const sessions = getOrBuildSessions(date)\n\n if (sessions.length === 0) {\n log.plain(`No activity captured for ${date}`)\n return\n }\n\n const jsonMode = config.summary?.format === 'json'\n\n if (!opts.fresh) {\n const allCached = sessions.every((session) => session.summary)\n if (allCached) {\n const fullSummary = sessions.map((session) => session.summary!).join('\\n\\n')\n log.plain('')\n if (jsonMode) {\n const jsonOut: SessionSummaryJson[] = sessions.map((session) => ({\n project: session.repoName,\n branch: session.events[0]?.branch ?? null,\n durationMinutes: session.durationMinutes,\n bullets: parseBullets(session.summary!.replace(/^## .+\\n/, '')),\n }))\n log.plain(JSON.stringify({ date, sessions: jsonOut }, null, 2))\n } else {\n log.plain(fullSummary)\n }\n log.plain('')\n log.plain(chalk.dim(' (cached — use --fresh to regenerate)'))\n await handleWebhook(opts, config, fullSummary)\n return\n }\n }\n\n const excluded = buildExcludedSet(config.summary?.includeCategories ?? [])\n const allSessionPayloads = sessions.map((session) => sessionToPayload(session, date))\n\n if (opts.verbose) {\n log.plain('')\n log.plain(chalk.bold(' Captured events (--verbose):'))\n for (const sessionPayload of allSessionPayloads) {\n const branch = sessionPayload.branch ? ` (${sessionPayload.branch})` : ''\n log.plain(\n chalk.dim(\n `\\n ${sessionPayload.project ?? 'unknown'}${branch} — ${formatDuration(sessionPayload.durationMinutes)}`\n )\n )\n for (const event of sessionPayload.events) {\n const tag = excluded.has(event.category)\n ? chalk.dim(` [excluded] ${event.category}`)\n : ` ${event.category}`\n const hint = event.hint ? chalk.dim(` [${event.hint}]`) : ''\n const meta = Object.keys(event.metadata).length > 0 ? chalk.dim(` ${JSON.stringify(event.metadata)}`) : ''\n log.plain(` ${tag}${hint}${meta}`)\n }\n }\n log.plain('')\n }\n\n log.plain('')\n log.info(`Generating summary via ${chalk.cyan(config.ai.provider)}…`)\n\n const allSummaries: string[] = []\n const jsonSessions: SessionSummaryJson[] = []\n\n for (let index = 0; index < sessions.length; index++) {\n const session = sessions[index]\n const sessionPayload: DaySummaryPayload = { date, sessions: [allSessionPayloads[index]] }\n try {\n const bullets = await provider.summarize(sessionPayload)\n const project = session.repoName ?? 'unknown'\n const branch = session.events[0]?.branch ? ` (${session.events[0].branch})` : ''\n const duration = formatDuration(session.durationMinutes)\n const heading = `## ${project}${branch} — ${duration}`\n const summary = `${heading}\\n${bullets.trim()}`\n allSummaries.push(summary)\n updateSessionSummary(session.id, summary)\n if (jsonMode) {\n jsonSessions.push({\n project: session.repoName,\n branch: session.events[0]?.branch ?? null,\n durationMinutes: session.durationMinutes,\n bullets: parseBullets(bullets),\n })\n }\n } catch (error) {\n log.error(`Summary failed [${config.ai.provider}]: ${(error as Error).message}`)\n process.exit(1)\n }\n }\n\n const fullSummary = allSummaries.join('\\n\\n')\n log.plain('')\n if (jsonMode) {\n log.plain(JSON.stringify({ date, sessions: jsonSessions }, null, 2))\n } else {\n log.plain(fullSummary)\n }\n log.plain('')\n\n const excludedCounts = countExcludedEvents(allSessionPayloads, excluded)\n if (excludedCounts.size > 0) {\n const total = [...excludedCounts.values()].reduce((sum, count) => sum + count, 0)\n const breakdown = [...excludedCounts.entries()].map(([category, count]) => `${category} ×${count}`).join(', ')\n log.plain(chalk.dim(` ℹ ${total} event${total === 1 ? '' : 's'} not included in summary (${breakdown})`))\n log.plain(chalk.dim(' Use --verbose to inspect · workscribe config set summary.includeCategories to opt in'))\n log.plain('')\n }\n\n await handleWebhook(opts, config, fullSummary)\n })\n}\n","import { Command } from 'commander'\nimport fs from 'fs'\nimport path from 'path'\nimport { getOrBuildSessions } from '../sessions/detector'\nimport { getProvider } from '../ai/router'\nimport { readConfig } from '../config'\nimport { log } from '../utils/logger'\nimport { todayDate, parseDate, formatDate } from '../utils/format'\nimport { EXPORTS_DIR } from '../utils/paths'\nimport type { DaySummaryPayload, SessionPayload, EventPayload } from '../ai/types'\nimport type { EventRow } from '../db'\n\nfunction eventRowToPayload(row: EventRow): EventPayload {\n let metadata: Record<string, unknown> = {}\n try {\n if (row.metadata) metadata = JSON.parse(row.metadata)\n } catch {\n /* ignore */\n }\n const payload: EventPayload = {\n category: row.category,\n metadata,\n exitCode: row.exit_code,\n durationMs: row.duration_ms,\n }\n if (row.category === 'other' && typeof metadata.hint === 'string') {\n payload.hint = metadata.hint\n const { hint: _h, tool: _t, ...rest } = metadata\n payload.metadata = rest\n }\n return payload\n}\n\nexport function registerExport(program: Command): void {\n program\n .command('export')\n .description('Export work summary as a markdown file')\n .option('--date <YYYY-MM-DD>', 'date to export (default: today)')\n .option('--output <path>', 'output file path (default: ~/.workscribe/exports/)')\n .action(async (opts) => {\n let date = todayDate()\n if (opts.date) {\n try {\n date = parseDate(opts.date)\n } catch (e) {\n log.error((e as Error).message)\n process.exit(1)\n }\n }\n\n const sessions = getOrBuildSessions(date)\n if (sessions.length === 0) {\n log.plain(`No activity captured for ${date}`)\n return\n }\n\n const config = readConfig()\n let provider\n try {\n provider = getProvider(config)\n } catch (e) {\n log.error((e as Error).message)\n process.exit(1)\n }\n\n const sessionPayloads: SessionPayload[] = sessions.map((session) => ({\n date,\n project: session.repoName,\n branch: session.events[0]?.branch ?? null,\n startTime: formatDate(session.startedAt),\n endTime: formatDate(session.endedAt),\n durationMinutes: session.durationMinutes,\n events: session.events.map(eventRowToPayload),\n }))\n\n const payload: DaySummaryPayload = { date, sessions: sessionPayloads }\n\n log.info(`Generating summary via ${config.ai.provider}…`)\n const summary = await provider.summarize(payload)\n\n const outputPath = opts.output ?? path.join(EXPORTS_DIR, `workscribe-${date}.md`)\n\n if (!fs.existsSync(EXPORTS_DIR)) fs.mkdirSync(EXPORTS_DIR, { recursive: true, mode: 0o700 })\n\n fs.writeFileSync(outputPath, `# Work Summary — ${date}\\n\\n${summary}\\n`, { encoding: 'utf-8', mode: 0o600 })\n log.success(`Saved: ${outputPath}`)\n })\n}\n","import { Command } from 'commander'\nimport chalk from 'chalk'\nimport { readConfig, writeConfig, getConfigValue, setConfigValue } from '../config'\nimport { log } from '../utils/logger'\n\nexport function registerConfig(program: Command): void {\n const configCmd = program\n .command('config')\n .description('View or update Workscribe configuration')\n .action(() => {\n const config = readConfig()\n log.plain('')\n log.plain(chalk.bold(' Workscribe Config'))\n log.plain('')\n printConfig(config, ' ')\n log.plain('')\n })\n\n configCmd\n .command('set <key> <value>')\n .description('Set a config value (e.g. workscribe config set ai.provider anthropic)')\n .action((key: string, value: string) => {\n const config = readConfig()\n const updated = setConfigValue(config, key, value)\n writeConfig(updated)\n const isSensitive =\n key === 'ai.apiKey' ||\n key.toLowerCase().includes('key') ||\n key.toLowerCase().includes('secret') ||\n key.toLowerCase().includes('token')\n const displayValue = isSensitive ? '[set]' : chalk.yellow(value)\n log.success(`Set ${chalk.cyan(key)} = ${displayValue}`)\n })\n\n configCmd\n .command('get <key>')\n .description('Get a config value')\n .action((key: string) => {\n const config = readConfig()\n const value = getConfigValue(config, key)\n if (value === undefined) {\n log.warn(`Key not found: ${key}`)\n } else {\n const lastSegment = key.split('.').pop() ?? ''\n if (SENSITIVE_KEYS.has(lastSegment) && typeof value === 'string' && value.length > 0) {\n log.plain(`${value.slice(0, 4)}${'*'.repeat(8)} (${value.length} chars)`)\n } else {\n log.plain(String(value))\n }\n }\n })\n}\n\nconst SENSITIVE_KEYS = new Set([\n 'apiKey',\n 'api_key',\n 'secret',\n 'token',\n 'password',\n 'passwd',\n 'webhook',\n 'slackWebhook',\n])\n\nfunction maskValue(key: string, value: unknown): string {\n if (SENSITIVE_KEYS.has(key) && typeof value === 'string' && value.length > 0) {\n return chalk.dim(`${value.slice(0, 4)}${'*'.repeat(8)} (${value.length} chars)`)\n }\n if (Array.isArray(value)) return `[${(value as unknown[]).join(', ')}]`\n return String(value) || chalk.dim('(not set)')\n}\n\nfunction printConfig(obj: unknown, indent: string): void {\n if (typeof obj !== 'object' || obj === null) return\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\n if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n log.plain(`${indent}${chalk.bold(key)}:`)\n printConfig(value, indent + ' ')\n } else {\n log.plain(`${indent}${chalk.dim(key)}: ${chalk.yellow(maskValue(key, value))}`)\n }\n }\n}\n","import { Command } from 'commander'\nimport fs from 'fs'\nimport { PAUSE_FLAG_PATH } from '../utils/paths'\nimport { log } from '../utils/logger'\n\nexport function registerPause(program: Command): void {\n program\n .command('pause')\n .description('Pause capture temporarily')\n .action(() => {\n if (fs.existsSync(PAUSE_FLAG_PATH)) {\n log.info('Capture is already paused. Run workscribe resume to restart.')\n return\n }\n fs.writeFileSync(PAUSE_FLAG_PATH, '', { mode: 0o600 })\n log.success('Capture paused. Run workscribe resume to restart.')\n })\n\n program\n .command('resume')\n .description('Resume capture after a pause')\n .action(() => {\n if (!fs.existsSync(PAUSE_FLAG_PATH)) {\n log.info('Capture is not paused.')\n return\n }\n fs.rmSync(PAUSE_FLAG_PATH)\n log.success('Capture resumed.')\n })\n}\n","import { Command } from 'commander'\nimport { getLastEventIds, getEventsByIds, deleteEventsByIds } from '../db'\nimport { log } from '../utils/logger'\n\nexport function registerUndo(program: Command): void {\n program\n .command('undo')\n .description('Remove the last N captured events')\n .option('-n, --count <number>', 'number of events to remove', '1')\n .option('--dry-run', 'preview what would be deleted without deleting')\n .action((opts) => {\n const count = parseInt(opts.count, 10)\n if (isNaN(count) || count < 1) {\n log.error('--count must be a positive integer')\n process.exit(1)\n }\n\n const ids = getLastEventIds(count)\n if (ids.length === 0) {\n log.plain('No events to undo.')\n return\n }\n\n const events = getEventsByIds(ids)\n log.plain('')\n log.plain(`Events to remove (${events.length}):`)\n for (const e of events) {\n log.plain(` ${e.captured_at} ${e.category} ${e.command}`)\n }\n log.plain('')\n\n if (opts.dryRun) {\n log.plain('Dry run — nothing deleted.')\n return\n }\n\n deleteEventsByIds(ids)\n log.success(`Removed ${ids.length} event${ids.length > 1 ? 's' : ''}.`)\n })\n}\n","import { Command } from 'commander'\nimport chalk from 'chalk'\nimport prompts from 'prompts'\nimport { getEventsForDate, deleteEventsForDate } from '../db'\nimport { log } from '../utils/logger'\nimport { todayDate, parseDate } from '../utils/format'\n\nexport function registerClear(program: Command): void {\n program\n .command('clear')\n .description('Delete all captured events for a date')\n .option('--date <YYYY-MM-DD>', 'date to clear (default: today)')\n .option('--dry-run', 'preview what would be deleted without deleting')\n .option('--yes', 'skip confirmation prompt')\n .action(async (opts) => {\n let date = todayDate()\n if (opts.date) {\n try {\n date = parseDate(opts.date)\n } catch (e) {\n log.error((e as Error).message)\n process.exit(1)\n }\n }\n\n const events = getEventsForDate(date)\n\n if (events.length === 0) {\n log.plain(`No events found for ${date}.`)\n return\n }\n\n log.plain('')\n log.plain(chalk.bold(` Events for ${date} (${events.length} total)`))\n log.plain('')\n\n // Show a compact summary by category\n const counts = new Map<string, number>()\n for (const e of events) counts.set(e.category, (counts.get(e.category) ?? 0) + 1)\n for (const [cat, n] of counts) {\n log.plain(` ${chalk.dim(String(n).padStart(4))} ${cat}`)\n }\n log.plain('')\n\n if (opts.dryRun) {\n log.plain(chalk.dim(' Dry run — nothing deleted.'))\n log.plain('')\n return\n }\n\n if (!opts.yes) {\n const { confirm } = await prompts({\n type: 'confirm',\n name: 'confirm',\n message: `Delete all ${events.length} events for ${date}?`,\n initial: false,\n })\n if (!confirm) {\n log.plain('Cancelled.')\n return\n }\n }\n\n const deleted = deleteEventsForDate(date)\n log.success(`Cleared ${deleted} event${deleted !== 1 ? 's' : ''} for ${date}.`)\n })\n}\n","import { Command } from 'commander'\nimport fs from 'fs'\nimport path from 'path'\nimport os from 'os'\nimport prompts from 'prompts'\nimport chalk from 'chalk'\nimport { WORKSCRIBE_DIR, REQUIRED_DIRS } from '../utils/paths'\nimport { isHookInstalled, removeHook } from '../capture/shell-hook'\nimport { log } from '../utils/logger'\n\nfunction detectShellRcFiles(): { name: string; rcFile: string }[] {\n const candidates = [\n { name: 'zsh', rcFile: path.join(os.homedir(), '.zshrc') },\n { name: 'bash', rcFile: path.join(os.homedir(), '.bashrc') },\n { name: 'bash', rcFile: path.join(os.homedir(), '.bash_profile') },\n { name: 'fish', rcFile: path.join(os.homedir(), '.config', 'fish', 'conf.d', 'workscribe.fish') },\n ]\n return candidates.filter((candidate) => fs.existsSync(candidate.rcFile) && isHookInstalled(candidate.rcFile))\n}\n\nexport function registerUninstall(program: Command): void {\n program\n .command('uninstall')\n .description('Remove shell hooks and optionally delete all Workscribe data')\n .option('--hooks-only', 'remove shell hooks only, skip data deletion prompt (used by npm preuninstall)')\n .action(async (opts) => {\n log.plain(chalk.bold('\\n Workscribe — Uninstall\\n'))\n\n // 1. Remove shell hooks from any rc files that have them\n const hooked = detectShellRcFiles()\n if (hooked.length === 0) {\n log.info('No shell hooks found')\n } else {\n for (const { name, rcFile } of hooked) {\n if (name === 'fish') {\n // The conf.d file is ours entirely — delete it rather than leaving an empty file\n fs.unlinkSync(rcFile)\n log.success(`Shell hook removed: ${rcFile}`)\n log.plain(` ${chalk.dim('Restart your terminal to take effect')}`)\n } else {\n removeHook(rcFile)\n log.success(`Shell hook removed from ${rcFile}`)\n log.plain(` ${chalk.dim(`Run: source ${rcFile}`)} (or restart your terminal to take effect)`)\n log.plain(\n ` ${chalk.dim(`${name === 'zsh' ? 'unfunction' : 'unset -f'} _workscribe_preexec _workscribe_precmd`)}`\n )\n }\n }\n }\n\n if (opts.hooksOnly) return\n\n // 2. Optionally delete all Workscribe data directories\n const existingDirs = [...new Set(REQUIRED_DIRS)].filter((dir) => fs.existsSync(dir))\n\n if (existingDirs.length > 0) {\n log.plain('')\n const { deleteData } = await prompts({\n type: 'confirm',\n name: 'deleteData',\n message: `Delete all Workscribe data in ${WORKSCRIBE_DIR}? (database, config, exports)`,\n initial: false,\n })\n\n if (deleteData) {\n for (const dir of existingDirs) {\n fs.rmSync(dir, { recursive: true, force: true })\n log.success(`Deleted ${dir}`)\n }\n } else {\n log.info(`Data kept at ${WORKSCRIBE_DIR}`)\n }\n }\n\n log.plain('')\n log.plain(` ${chalk.dim('npm uninstall -g @workscribe/cli')} — remove the CLI itself`)\n log.plain('')\n })\n}\n","import { Command } from 'commander'\nimport fs from 'fs'\nimport path from 'path'\nimport chalk from 'chalk'\nimport { readConfig, writeConfig } from '../config'\nimport { PROFILES_DIR } from '../utils/paths'\nimport { getCachedProfiles, detectProfilesForDirectory } from '../profiles/loader'\nimport { installProfile, cacheManifest, readCachedManifest } from '../profiles/fetcher'\nimport { getOtherEventToolCounts } from '../db'\nimport { log } from '../utils/logger'\n\nconst MIN_SUGGEST_COUNT = 5\n\nexport function registerProfile(program: Command): void {\n const profile = program.command('profile').description('Manage stack profiles for better command tracking')\n\n // ─── list ─────────────────────────────────────────────────────────────────\n profile\n .command('list')\n .description('List available profiles from the registry')\n .action(async () => {\n const config = readConfig()\n const activeNames = new Set(config.capture.profiles)\n\n let manifest = readCachedManifest()\n let offline = false\n\n if (!manifest) {\n try {\n manifest = await cacheManifest()\n } catch {\n offline = true\n manifest = getCachedProfiles().map((p) => ({\n name: p.name,\n displayName: p.displayName,\n tags: [],\n description: '',\n keywords: [],\n detect: p.detect,\n }))\n }\n } else {\n // Refresh in background — best effort, don't block output\n cacheManifest().catch(() => undefined)\n }\n\n if (offline) {\n log.warn('Registry unreachable — showing installed profiles only')\n }\n\n if (manifest.length === 0) {\n log.plain('No profiles available. Check your connection and try again.')\n return\n }\n\n // Group by tag\n const grouped = new Map<string, typeof manifest>()\n for (const entry of manifest) {\n const tag = entry.tags[0] ?? 'other'\n if (!grouped.has(tag)) grouped.set(tag, [])\n grouped.get(tag)!.push(entry)\n }\n\n log.plain('')\n for (const [tag, entries] of grouped) {\n log.plain(chalk.bold(` ${tag.charAt(0).toUpperCase() + tag.slice(1)} profiles`))\n log.plain(chalk.dim(' ' + '─'.repeat(60)))\n for (const entry of entries) {\n const badge = activeNames.has(entry.name) ? chalk.green(' [active]') : ''\n const installed = fs.existsSync(path.join(PROFILES_DIR, `${entry.name}.json`)) ? chalk.dim(' installed') : ''\n log.plain(` ${chalk.cyan(entry.name.padEnd(18))} ${entry.displayName.padEnd(28)}${badge}${installed}`)\n if (entry.description) log.plain(` ${chalk.dim(' '.repeat(18) + entry.description)}`)\n }\n log.plain('')\n }\n })\n\n // ─── add ──────────────────────────────────────────────────────────────────\n profile\n .command('add <names...>')\n .description('Install one or more profiles from the registry')\n .action(async (names: string[]) => {\n const config = readConfig()\n const activeNames = new Set(config.capture.profiles)\n\n for (const name of names) {\n if (activeNames.has(name)) {\n log.info(`Profile \"${name}\" is already active`)\n continue\n }\n try {\n log.plain(`Fetching ${chalk.cyan(name)}…`)\n await installProfile(name)\n activeNames.add(name)\n log.success(`Profile \"${name}\" installed`)\n } catch (err) {\n log.error(`Failed to install \"${name}\": ${(err as Error).message}`)\n }\n }\n\n config.capture.profiles = [...activeNames]\n writeConfig(config)\n })\n\n // ─── remove ───────────────────────────────────────────────────────────────\n profile\n .command('remove <names...>')\n .description('Uninstall one or more profiles')\n .action((names: string[]) => {\n const config = readConfig()\n const activeNames = new Set(config.capture.profiles)\n\n for (const name of names) {\n if (!activeNames.has(name)) {\n log.warn(`Profile \"${name}\" is not active`)\n continue\n }\n activeNames.delete(name)\n const cachePath = path.join(PROFILES_DIR, `${name}.json`)\n if (fs.existsSync(cachePath)) fs.unlinkSync(cachePath)\n log.success(`Profile \"${name}\" removed`)\n }\n\n config.capture.profiles = [...activeNames]\n writeConfig(config)\n })\n\n // ─── update ───────────────────────────────────────────────────────────────\n profile\n .command('update [name]')\n .description('Re-fetch installed profiles from the registry')\n .action(async (name?: string) => {\n const config = readConfig()\n const toUpdate = name ? [name] : config.capture.profiles\n\n if (toUpdate.length === 0) {\n log.plain('No profiles installed. Run workscribe profile add <name> first.')\n return\n }\n\n for (const profileName of toUpdate) {\n try {\n log.plain(`Updating ${chalk.cyan(profileName)}…`)\n await installProfile(profileName)\n log.success(`${profileName} updated`)\n } catch (err) {\n log.error(`Failed to update \"${profileName}\": ${(err as Error).message}`)\n }\n }\n })\n\n // ─── detect ───────────────────────────────────────────────────────────────\n profile\n .command('detect')\n .description('Scan the current directory and suggest matching profiles')\n .action(() => {\n const cwd = process.cwd()\n const matches = detectProfilesForDirectory(cwd)\n\n if (matches.length === 0) {\n const cached = readCachedManifest()\n if (!cached) {\n log.plain('No manifest cached. Run workscribe profile list to fetch it first.')\n } else {\n log.plain(`No profiles detected for ${chalk.dim(cwd)}`)\n log.plain(chalk.dim('Run workscribe profile list to browse available profiles.'))\n }\n return\n }\n\n log.plain('')\n log.plain(chalk.bold(' Profiles detected for this directory:'))\n log.plain('')\n for (const entry of matches) {\n const files = entry.detect?.files?.join(', ') ?? ''\n log.plain(` ${chalk.cyan(entry.name.padEnd(18))} ${entry.displayName} ${chalk.dim('(' + files + ')')}`)\n }\n log.plain('')\n log.plain(` Run: ${chalk.cyan('workscribe profile add ' + matches.map((e) => e.name).join(' '))}`)\n log.plain('')\n })\n\n // ─── suggest ──────────────────────────────────────────────────────────────\n profile\n .command('suggest')\n .description('Analyse recent unclassified commands and suggest profiles')\n .option('--days <n>', 'number of days to analyse', '30')\n .action((opts) => {\n const days = Math.max(1, parseInt(opts.days as string, 10) || 30)\n const toolCounts = getOtherEventToolCounts(days)\n\n if (toolCounts.length === 0) {\n log.plain('No unclassified commands found in the last ' + days + ' days.')\n return\n }\n\n const manifest = readCachedManifest()\n if (!manifest) {\n log.plain('No manifest cached. Run workscribe profile list first.')\n return\n }\n\n const config = readConfig()\n const activeNames = new Set(config.capture.profiles)\n\n // Match tool counts against manifest keywords\n const suggestions: { entry: (typeof manifest)[number]; count: number }[] = []\n for (const entry of manifest) {\n if (activeNames.has(entry.name)) continue\n const matchedCount = toolCounts\n .filter((toolCount) =>\n entry.keywords.some((keyword) => toolCount.tool.toLowerCase().includes(keyword.toLowerCase()))\n )\n .reduce((total, toolCount) => total + toolCount.count, 0)\n if (matchedCount >= MIN_SUGGEST_COUNT) {\n suggestions.push({ entry, count: matchedCount })\n }\n }\n\n suggestions.sort((a, b) => b.count - a.count)\n\n if (suggestions.length === 0) {\n const activeEntries = manifest.filter((entry) => activeNames.has(entry.name))\n const isToolCoveredByActiveProfile = (tool: string) =>\n activeEntries.some((entry) =>\n entry.keywords.some((keyword) => tool.toLowerCase().includes(keyword.toLowerCase()))\n )\n const uncoveredTools = toolCounts.filter((toolCount) => !isToolCoveredByActiveProfile(toolCount.tool))\n\n if (uncoveredTools.length === 0) {\n log.plain('')\n log.plain('Your active profiles cover all unclassified commands.')\n log.plain(chalk.dim(' Future captures will be classified correctly.'))\n log.plain('')\n } else {\n log.plain('')\n log.plain('No profile matches found for your unclassified commands.')\n log.plain('')\n log.plain(chalk.dim(' Top unclassified tools:'))\n for (const { tool, count } of uncoveredTools.slice(0, 5)) {\n log.plain(chalk.dim(` ${tool.padEnd(24)} ${count} event${count === 1 ? '' : 's'}`))\n }\n log.plain('')\n log.plain(chalk.dim(' Run workscribe events --category other to review them.'))\n log.plain('')\n }\n return\n }\n\n log.plain('')\n log.plain(chalk.bold(` Analysed last ${days} days of unclassified commands:`))\n log.plain('')\n for (const { entry, count } of suggestions) {\n log.plain(\n ` ${chalk.cyan(entry.name.padEnd(18))} ${String(count).padStart(4)} commands → ${entry.displayName}`\n )\n }\n log.plain('')\n log.plain(\n ` Run: ${chalk.cyan('workscribe profile add ' + suggestions.map((suggestion) => suggestion.entry.name).join(' '))}`\n )\n log.plain('')\n\n const allCoveredEntries = [\n ...manifest.filter((entry) => activeNames.has(entry.name)),\n ...suggestions.map((suggestion) => suggestion.entry),\n ]\n const isToolCoveredAfterInstall = (tool: string) =>\n allCoveredEntries.some((entry) =>\n entry.keywords.some((keyword) => tool.toLowerCase().includes(keyword.toLowerCase()))\n )\n const stillUncovered = toolCounts.filter((toolCount) => !isToolCoveredAfterInstall(toolCount.tool)).slice(0, 5)\n if (stillUncovered.length > 0) {\n log.plain(chalk.dim(' Still uncovered after installing:'))\n for (const { tool, count } of stillUncovered) {\n log.plain(chalk.dim(` ${tool.padEnd(24)} ${count} event${count === 1 ? '' : 's'}`))\n }\n log.plain('')\n }\n })\n}\n","import { Command } from 'commander'\nimport { insertEvent } from '../db'\nimport { getGitContext } from '../capture/git'\nimport { log } from '../utils/logger'\n\nexport function registerNote(program: Command): void {\n program\n .command('note <text>')\n .description('Attach a free-text annotation to the current session')\n .action((text: string) => {\n const { repoName, branch } = getGitContext(process.cwd())\n insertEvent({\n captured_at: new Date().toISOString(),\n command: 'workscribe note',\n cwd: process.cwd(),\n exit_code: null,\n duration_ms: null,\n repo_name: repoName,\n branch,\n category: 'note',\n metadata: JSON.stringify({ text }),\n source: null,\n file_path: null,\n })\n log.success(`Note saved${repoName ? ` to ${repoName}` : ''}`)\n })\n}\n","import { Command } from 'commander'\nimport chalk from 'chalk'\nimport fs from 'fs'\nimport path from 'path'\nimport os from 'os'\nimport { getOrBuildSessions } from '../sessions/detector'\nimport { getProvider } from '../ai/router'\nimport { readConfig } from '../config'\nimport { log } from '../utils/logger'\nimport { todayDate, startOfWeek, eachDayOfRange, isoWeekKey, formatDate } from '../utils/format'\nimport { postToWebhook } from '../integrations/webhook'\nimport { formatForSlack, isSlackWebhookUrl } from '../integrations/slack'\nimport { WEEKLY_CACHE_DIR } from '../utils/paths'\nimport type { WeekSummaryPayload, SessionPayload, EventPayload } from '../ai/types'\nimport type { EventRow } from '../db'\n\nfunction eventRowToPayload(row: EventRow): EventPayload {\n let metadata: Record<string, unknown> = {}\n try {\n if (row.metadata) metadata = JSON.parse(row.metadata)\n } catch {\n /* ignore */\n }\n const payload: EventPayload = {\n category: row.category,\n metadata,\n exitCode: row.exit_code,\n durationMs: row.duration_ms,\n }\n if (row.category === 'other' && typeof metadata.hint === 'string') {\n payload.hint = metadata.hint\n const { hint: _hint, tool: _tool, ...rest } = metadata\n payload.metadata = rest\n }\n return payload\n}\n\nfunction sessionToPayload(session: ReturnType<typeof getOrBuildSessions>[number], date: string): SessionPayload {\n return {\n date,\n project: session.repoName,\n branch: session.events[0]?.branch ?? null,\n startTime: formatDate(session.startedAt),\n endTime: formatDate(session.endedAt),\n durationMinutes: session.durationMinutes,\n events: session.events.map(eventRowToPayload),\n }\n}\n\nasync function postSummary(\n opts: { slack?: boolean; webhook?: string },\n config: ReturnType<typeof readConfig>,\n summary: string\n): Promise<void> {\n const webhookUrl = opts.webhook ?? (opts.slack ? config.integrations?.slackWebhook : undefined)\n if (!webhookUrl) {\n if (opts.slack) log.warn('--slack requires integrations.slackWebhook to be set in config')\n return\n }\n try {\n log.info('Posting to webhook…')\n const username = os.userInfo().username\n const body = isSlackWebhookUrl(webhookUrl) ? formatForSlack(summary, username) : summary\n await postToWebhook(webhookUrl, body)\n log.success('Posted.')\n } catch (error) {\n log.error(`Webhook failed: ${(error as Error).message}`)\n }\n}\n\nexport function registerWeek(program: Command): void {\n program\n .command('week')\n .description('Generate an AI weekly digest (Mon–today)')\n .option('--fresh', 'bypass cache and regenerate')\n .option('--slack', 'post to Slack webhook from config')\n .option('--webhook <url>', 'post to a custom webhook URL')\n .action(async (opts) => {\n const config = readConfig()\n let provider\n try {\n provider = getProvider(config)\n } catch (error) {\n log.error((error as Error).message)\n process.exit(1)\n }\n\n const today = todayDate()\n const weekStart = startOfWeek(today)\n const days = eachDayOfRange(weekStart, today)\n\n const weeklyDays: WeekSummaryPayload['days'] = []\n for (const day of days) {\n const sessions = getOrBuildSessions(day)\n if (sessions.length > 0) {\n weeklyDays.push({ date: day, sessions: sessions.map((session) => sessionToPayload(session, day)) })\n }\n }\n\n if (weeklyDays.length === 0) {\n log.plain('No activity captured this week.')\n return\n }\n\n const cacheKey = isoWeekKey(today)\n const cacheFile = path.join(WEEKLY_CACHE_DIR, `${cacheKey}.md`)\n\n if (!opts.fresh && fs.existsSync(cacheFile)) {\n const cached = fs.readFileSync(cacheFile, 'utf-8')\n log.plain('')\n log.plain(cached)\n log.plain('')\n log.plain(chalk.dim(' (cached — use --fresh to regenerate)'))\n await postSummary(opts, config, cached)\n return\n }\n\n const payload: WeekSummaryPayload = { weekStart, weekEnd: today, days: weeklyDays }\n\n log.plain('')\n log.info(`Generating weekly digest via ${chalk.cyan(config.ai.provider)}…`)\n\n try {\n const summary = provider.summarizeWeek\n ? await provider.summarizeWeek(payload)\n : await provider.summarize({ date: today, sessions: weeklyDays.flatMap((day) => day.sessions) })\n\n log.plain('')\n log.plain(summary)\n log.plain('')\n\n fs.mkdirSync(WEEKLY_CACHE_DIR, { recursive: true })\n fs.writeFileSync(cacheFile, summary, { encoding: 'utf-8', mode: 0o600 })\n\n await postSummary(opts, config, summary)\n } catch (error) {\n log.error(`Weekly digest failed [${config.ai.provider}]: ${(error as Error).message}`)\n process.exit(1)\n }\n })\n}\n","import { Command } from 'commander'\nimport fs from 'fs'\nimport os from 'os'\nimport path from 'path'\nimport chalk from 'chalk'\nimport { WORKSCRIBE_DIR, DEBUG_LOG_PATH, CONFIG_PATH } from '../utils/paths'\nimport { readConfig } from '../config'\nimport { log } from '../utils/logger'\n\ndeclare const __WORKSCRIBE_VERSION__: string\n\nconst GITHUB_ISSUES_URL = 'https://github.com/workscribe/workscribe/issues/new'\nconst DEBUG_LOG_TAIL_LINES = 100\n\nfunction tailFile(filePath: string, lines: number): string {\n if (!fs.existsSync(filePath)) return '(no debug log found — set WORKSCRIBE_DEBUG=1 to enable)'\n const content = fs.readFileSync(filePath, 'utf-8')\n const allLines = content.split('\\n')\n return allLines.slice(-lines).join('\\n')\n}\n\nfunction redactConfig(): string {\n try {\n const config = readConfig()\n if (config.ai.apiKey) config.ai.apiKey = '<redacted>'\n if (config.integrations?.slackWebhook) config.integrations.slackWebhook = '<redacted>'\n if (config.integrations?.webhook) config.integrations.webhook = '<redacted>'\n return JSON.stringify(config, null, 2)\n } catch {\n return '(could not read config)'\n }\n}\n\nexport function registerBugReport(program: Command): void {\n program\n .command('bug-report')\n .description('Generate a diagnostic report for filing a bug')\n .action(() => {\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-')\n const reportPath = path.join(WORKSCRIBE_DIR, `bug-report-${timestamp}.txt`)\n\n const systemInfo = [\n `Workscribe version : ${__WORKSCRIBE_VERSION__}`,\n `Node.js version : ${process.version}`,\n `Platform : ${process.platform}`,\n `Architecture : ${process.arch}`,\n `OS release : ${os.release()}`,\n `Config path : ${CONFIG_PATH}`,\n `Data directory : ${WORKSCRIBE_DIR}`,\n ].join('\\n')\n\n const report = [\n '=== Workscribe Bug Report ===',\n `Generated: ${new Date().toISOString()}`,\n '',\n '--- System ---',\n systemInfo,\n '',\n '--- Config (secrets redacted) ---',\n redactConfig(),\n '',\n `--- Debug log (last ${DEBUG_LOG_TAIL_LINES} lines) ---`,\n tailFile(DEBUG_LOG_PATH, DEBUG_LOG_TAIL_LINES),\n ].join('\\n')\n\n try {\n if (!fs.existsSync(WORKSCRIBE_DIR)) {\n fs.mkdirSync(WORKSCRIBE_DIR, { recursive: true, mode: 0o700 })\n }\n fs.writeFileSync(reportPath, report, { mode: 0o600 })\n } catch (error) {\n log.error(`Could not write report: ${(error as Error).message}`)\n process.exit(1)\n }\n\n const params = new URLSearchParams({\n title: `Bug report — workscribe ${__WORKSCRIBE_VERSION__}`,\n body: `<!-- Attach ${path.basename(reportPath)} or paste the relevant sections below -->\\n\\n**Describe the issue:**\\n\\n**Steps to reproduce:**\\n\\n**Expected behaviour:**`,\n })\n\n log.success(`Report written to: ${chalk.cyan(reportPath)}`)\n log.plain('')\n log.plain(` Open a GitHub issue:`)\n log.plain(` ${chalk.cyan(`${GITHUB_ISSUES_URL}?${params}`)}`)\n log.plain('')\n log.plain(chalk.dim(` Attach the report or paste the relevant sections into the issue.`))\n log.plain('')\n })\n}\n","import { Command } from 'commander'\nimport chalk from 'chalk'\nimport { getPendingAlerts, clearAlerts, hasPendingAlerts } from '../db/alerts'\nimport { log } from '../utils/logger'\n\nfunction formatTimestamp(ms: number): string {\n return new Date(ms).toLocaleString([], {\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n })\n}\n\nexport function registerAlerts(program: Command): void {\n const alertsCmd = program\n .command('alerts')\n .description('Show and manage security alerts from AI session monitoring')\n .option('--check', 'Print warning if alerts are pending (used by shell hooks)')\n .action((opts: { check?: boolean }) => {\n if (opts.check) {\n if (hasPendingAlerts()) {\n log.plain(\n chalk.yellow(' [workscribe] Possible credentials detected in an AI session.') +\n chalk.dim(' Run workscribe alerts for details.')\n )\n }\n return\n }\n\n const alerts = getPendingAlerts()\n if (alerts.length === 0) {\n log.plain('')\n log.plain(' No pending security alerts.')\n log.plain('')\n return\n }\n\n log.plain('')\n log.plain(chalk.bold(' Security Alerts') + chalk.dim(` (${alerts.length} pending)`))\n log.plain('')\n\n for (const alert of alerts) {\n log.plain(` ${chalk.yellow('!')} ${chalk.dim(formatTimestamp(alert.created_at))} ${chalk.cyan(alert.tool)}`)\n log.plain(` ${alert.context}`)\n if (alert.session_id) log.plain(` ${chalk.dim('Session: ' + alert.session_id)}`)\n log.plain('')\n }\n\n log.plain(chalk.dim(' Run workscribe alerts clear to dismiss all alerts'))\n log.plain('')\n })\n\n alertsCmd\n .command('clear')\n .description('Dismiss all pending security alerts')\n .action(() => {\n const count = clearAlerts()\n if (count === 0) {\n log.plain(' No pending alerts to clear.')\n } else {\n log.plain(` ${count} alert${count === 1 ? '' : 's'} cleared.`)\n }\n })\n}\n","import path from 'path'\nimport { Command } from 'commander'\nimport chalk from 'chalk'\nimport { getRecentSessionsByRepo, getLastSessionTouchingFile, getSessionBranch } from '../db'\nimport { getGitContext } from '../capture/git'\nimport { readConfig } from '../config'\nimport { formatDuration, timeAgo } from '../utils/format'\nimport { log } from '../utils/logger'\nimport type { SessionRow } from '../db/types'\n\nexport interface SessionContextJson {\n date: string\n startedAt: string\n endedAt: string\n timeAgo: string\n durationMinutes: number\n branch: string | null\n eventCount: number\n summary: string | null\n}\n\nfunction toContextJson(session: SessionRow): SessionContextJson {\n return {\n date: session.date,\n startedAt: session.started_at,\n endedAt: session.ended_at,\n timeAgo: timeAgo(session.started_at),\n durationMinutes: (new Date(session.ended_at).getTime() - new Date(session.started_at).getTime()) / 60000,\n branch: getSessionBranch(session.id),\n eventCount: session.event_count,\n summary: session.summary,\n }\n}\n\nfunction printSessionContext(session: SessionRow, heading: string): void {\n const ago = timeAgo(session.started_at)\n const branch = getSessionBranch(session.id)\n const durationMinutes = (new Date(session.ended_at).getTime() - new Date(session.started_at).getTime()) / 60000\n\n log.plain('')\n log.plain(` ${chalk.bold(heading)}: ${chalk.cyan(ago)}`)\n log.plain('')\n log.plain(` Date ${session.date}`)\n log.plain(` Duration ${formatDuration(durationMinutes)}`)\n if (branch) log.plain(` Branch ${chalk.dim(branch)}`)\n log.plain(` Events ${session.event_count}`)\n\n if (session.summary) {\n log.plain('')\n for (const line of session.summary.split('\\n')) {\n log.plain(` ${line}`)\n }\n } else {\n log.plain('')\n log.plain(chalk.dim(` No summary — run: workscribe summary ${session.date}`))\n }\n\n log.plain('')\n}\n\nexport function registerContext(program: Command): void {\n program\n .command('context')\n .description('Show the last session for the current repo')\n .option('--file <path>', 'narrow to last session that touched this file')\n .option('--json', 'output as JSON instead of formatted text — null when no session is found')\n .action((opts) => {\n if (opts.file) {\n const normalizedFile = path.normalize(opts.file)\n const session = getLastSessionTouchingFile(normalizedFile)\n if (!session) {\n if (opts.json) log.plain(JSON.stringify(null))\n else log.plain(` No sessions found touching ${normalizedFile}`)\n return\n }\n if (opts.json) {\n log.plain(JSON.stringify(toContextJson(session)))\n return\n }\n printSessionContext(session, `Last session touching ${path.basename(normalizedFile)}`)\n return\n }\n\n const { repoName } = getGitContext(process.cwd(), null, readConfig().git.qualifyRepoName)\n if (!repoName) {\n if (opts.json) log.plain(JSON.stringify(null))\n else log.plain(' Not in a git repository. Run workscribe context from a project directory.')\n return\n }\n\n const sessions = getRecentSessionsByRepo(repoName, 1)\n if (sessions.length === 0) {\n if (opts.json) log.plain(JSON.stringify(null))\n else log.plain(` No sessions found for ${repoName}`)\n return\n }\n\n if (opts.json) {\n log.plain(JSON.stringify(toContextJson(sessions[0])))\n return\n }\n printSessionContext(sessions[0], `Last session on ${repoName}`)\n })\n}\n","import fs from 'fs'\nimport { UPDATE_CHECK_PATH } from './paths'\n\ndeclare const __WORKSCRIBE_VERSION__: string\n\nconst CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000\n\ninterface UpdateCache {\n lastChecked: number\n latestVersion: string\n}\n\nfunction readCache(): UpdateCache | null {\n try {\n return JSON.parse(fs.readFileSync(UPDATE_CHECK_PATH, 'utf-8')) as UpdateCache\n } catch {\n return null\n }\n}\n\nfunction writeCache(cache: UpdateCache): void {\n try {\n fs.writeFileSync(UPDATE_CHECK_PATH, JSON.stringify(cache), { mode: 0o600 })\n } catch {\n // Not critical — silently skip if the data dir doesn't exist yet\n }\n}\n\nfunction isNewer(latest: string, current: string): boolean {\n const parse = (version: string) => version.replace(/^v/, '').split('.').map(Number)\n const [latestMajor, latestMinor, latestPatch] = parse(latest)\n const [currentMajor, currentMinor, currentPatch] = parse(current)\n if (latestMajor !== currentMajor) return latestMajor > currentMajor\n if (latestMinor !== currentMinor) return latestMinor > currentMinor\n return latestPatch > currentPatch\n}\n\nexport function checkForUpdate(): void {\n const current = __WORKSCRIBE_VERSION__\n const cache = readCache()\n\n if (cache && isNewer(cache.latestVersion, current)) {\n process.stderr.write(\n `\\n Update available ${current} → ${cache.latestVersion}\\n Run: npm install -g @workscribe/cli\\n\\n`\n )\n }\n\n const now = Date.now()\n if (!cache || now - cache.lastChecked > CHECK_INTERVAL_MS) {\n fetch('https://registry.npmjs.org/@workscribe/cli/latest')\n .then((response) => response.json())\n .then((data: unknown) => {\n const latest = (data as { version?: string }).version\n if (latest) writeCache({ lastChecked: now, latestVersion: latest })\n })\n .catch(() => {\n // Network unavailable — will retry next run\n })\n }\n}\n","import { Command } from 'commander'\nimport { registerCapture } from './cli/capture'\nimport { registerHook } from './cli/hook'\n\ndeclare const __WORKSCRIBE_VERSION__: string\nimport { registerInit } from './cli/init'\nimport { registerStatus } from './cli/status'\nimport { registerEvents } from './cli/events'\nimport { registerSessions } from './cli/sessions'\nimport { registerSummary } from './cli/summary'\nimport { registerExport } from './cli/export'\nimport { registerConfig } from './cli/config'\nimport { registerPause } from './cli/pause'\nimport { registerUndo } from './cli/undo'\nimport { registerClear } from './cli/clear'\nimport { registerUninstall } from './cli/uninstall'\nimport { registerProfile } from './cli/profile'\nimport { registerNote } from './cli/note'\nimport { registerWeek } from './cli/week'\nimport { registerBugReport } from './cli/bug-report'\nimport { registerCompletions } from './cli/completions'\nimport { registerAlerts } from './cli/alerts'\nimport { registerContext } from './cli/context'\nimport { checkForUpdate } from './utils/update-check'\n\ncheckForUpdate()\n\nconst program = new Command()\n\nprogram.name('workscribe').description('Automatic developer work journal').version(__WORKSCRIBE_VERSION__)\n\nregisterCapture(program)\nregisterHook(program)\nregisterInit(program)\nregisterStatus(program)\nregisterEvents(program)\nregisterSessions(program)\nregisterSummary(program)\nregisterExport(program)\nregisterConfig(program)\nregisterPause(program)\nregisterUndo(program)\nregisterClear(program)\nregisterUninstall(program)\nregisterProfile(program)\nregisterNote(program)\nregisterWeek(program)\nregisterBugReport(program)\nregisterCompletions(program)\nregisterAlerts(program)\nregisterContext(program)\n\nprogram.parse()\n","export type VersionManager = 'nvm' | 'volta' | 'fnm' | 'mise' | 'asdf' | 'nodenv'\n\nexport function detectVersionManager(): VersionManager | null {\n if (process.env.NVM_DIR) return 'nvm'\n if (process.env.VOLTA_HOME) return 'volta'\n if (process.env.FNM_DIR) return 'fnm'\n if (process.env.MISE_DATA_DIR || process.env.MISE_SHELL) return 'mise'\n if (process.env.ASDF_DIR || process.env.ASDF_DATA_DIR) return 'asdf'\n if (process.env.NODENV_ROOT) return 'nodenv'\n return null\n}\n\nconst UPGRADE_COMMANDS: Record<VersionManager, string> = {\n nvm: 'nvm install 22 && nvm use 22',\n volta: 'volta install node@22',\n fnm: 'fnm install 22 && fnm use 22',\n mise: 'mise use --global node@22',\n asdf: 'asdf install nodejs 22 && asdf global nodejs 22',\n nodenv: 'nodenv install 22 && nodenv global 22',\n}\n\nexport function assertNodeVersion(nodeVersion: string): void {\n const major = Number(nodeVersion.split('.')[0])\n if (major < 22) {\n const manager = detectVersionManager()\n const upgradeHint = manager\n ? `Upgrade with ${manager}:\\n ${UPGRADE_COMMANDS[manager]}`\n : 'Download the latest version from https://nodejs.org'\n process.stderr.write(`workscribe requires Node.js 22 or later (you have v${nodeVersion}).\\n\\n${upgradeHint}\\n`)\n process.exit(1)\n }\n}\n","// This file must import nothing beyond assertNodeVersion. ES import\n// statements are hoisted and execute before any of a module's own top-level\n// code, regardless of source order — so `import`-ing anything that\n// transitively loads node:sqlite (e.g. src/cli/capture.ts -> src/db/index.ts)\n// would load and crash on Node < 22 before assertNodeVersion ever runs.\n// require() is not hoisted, so the rest of the CLI is only loaded after the\n// version check passes.\nimport { assertNodeVersion } from './utils/node-version'\n\nassertNodeVersion(process.versions.node)\n\n// eslint-disable-next-line @typescript-eslint/no-require-imports -- must not be a static import (see file comment above)\nrequire('./main')\n"],"mappings":"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","names":["path","os","fs","migration","migration","fs","migration","import_fs","fs","path","import_path","import_fs","import_child_process","path","fs","import_fs","import_path","fs","import_fs","chalk","fs","import_fs","import_os","import_path","path","os","fs","import_fs","path","fs","import_fs","import_path","path","fs","import_fs","import_path","fs","command","nameOverride","repoName","branch","import_fs","init_capture","fs","path","import_fs","import_path","init_alerts","parsed","init_alerts","fs","path","import_fs","import_path","import_os","import_child_process","os","import_child_process","fs","import_fs","import_path","import_os","import_child_process","path","os","path","os","chalk","fs","prompts","import_fs","import_path","import_os","import_chalk","fs","chalk","import_fs","import_chalk","init_alerts","chalk","import_chalk","chalk","import_chalk","os","sessions","path","fs","chalk","fullSummary","import_chalk","import_fs","import_os","import_path","eventRowToPayload","path","fs","import_fs","import_path","chalk","import_chalk","init_config","fs","import_fs","chalk","prompts","import_chalk","import_prompts","path","os","fs","chalk","prompts","import_fs","import_path","import_os","import_prompts","import_chalk","chalk","fs","path","import_fs","import_path","import_chalk","eventRowToPayload","sessionToPayload","os","path","fs","chalk","import_chalk","import_fs","import_path","import_os","fs","path","os","chalk","import_fs","import_os","import_path","import_chalk","chalk","import_chalk","init_alerts","chalk","path","import_path","import_chalk","fs","import_fs","init_capture","init_config","init_alerts"]}