@workscribe/cli 2.0.0 → 2.0.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 +569 -195
- package/dist/index.js.map +1 -1
- package/package.json +1 -2
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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/005_session_summaries.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/capture/shell-syntax.ts","../src/capture/command-steps.ts","../src/summary/exclusions.ts","../src/normalize/compound.ts","../src/normalize/patterns.ts","../src/normalize/reclassify.ts","../src/db/migrations/006_reclassify_other.ts","../src/db/migrations/index.ts","../src/db/migrate.ts","../src/db/index.ts","../src/capture/redact.ts","../src/capture/git.ts","../src/capture/git-snapshot.ts","../src/capture/aider.ts","../src/capture/workscribe-command.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/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/utils/memoize.ts","../src/skills/agents.ts","../src/skills/detect.ts","../src/skills/state.ts","../src/skills/installer.ts","../src/skills/package-path.ts","../src/skills/report.ts","../src/skills/actions.ts","../src/summary/legacy-ai.ts","../src/cli/legacy-ai-cleanup.ts","../src/cli/init.ts","../src/utils/format.ts","../src/cli/notices.ts","../src/cli/status.ts","../src/summary/payload.ts","../src/summary/store.ts","../src/summary/contract/constants.ts","../src/summary/contract/utils.ts","../src/summary/contract/build.ts","../src/cli/events.ts","../src/sessions/grouper.ts","../src/sessions/detector.ts","../src/summary/write-back.ts","../src/utils/stdin.ts","../src/cli/session-summary.ts","../src/summary/git-commits.ts","../src/cli/sessions.ts","../src/summary/heading.ts","../src/ai/engines/template/constants.ts","../src/ai/engines/template/utils.ts","../src/ai/engines/template/describe.ts","../src/ai/engines/template/provider.ts","../src/summary/writer.ts","../src/integrations/webhook.ts","../src/integrations/slack.ts","../src/summary/webhook.ts","../src/summary/weekly.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/cli/skill.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 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","// Must produce exactly what sessionKey() in src/summary/store.ts produces — pinned by a test.\nexport const SESSION_KEY_SQL = \"COALESCE(repo_name, '') || '|' || started_at\"\n\nconst migration = {\n version: 5,\n description: 'Store session summaries per engine, keyed by repo and start time so they survive session rebuilds',\n sql: `\n CREATE TABLE IF NOT EXISTS session_summaries (\n session_key TEXT NOT NULL,\n engine TEXT NOT NULL,\n text TEXT NOT NULL,\n created_at TEXT NOT NULL,\n PRIMARY KEY (session_key, engine)\n );\n INSERT OR IGNORE INTO session_summaries (session_key, engine, text, created_at)\n SELECT ${SESSION_KEY_SQL}, 'legacy', summary, strftime('%Y-%m-%dT%H:%M:%fZ', 'now')\n FROM sessions\n WHERE summary IS NOT NULL;\n `,\n}\n\nexport default migration\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 /** A warning on stderr — keeps stdout clean for JSON output (summary.format=json) and pipes. */\n notice: (msg: string) => process.stderr.write(`${chalk.yellow('⚠')} ${msg}\\n`),\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 crypto from 'crypto'\nimport fs from 'fs'\nimport path from 'path'\nimport { CONFIG_PATH } from '../utils/paths'\nimport { debugLog } from '../utils/logger'\n\n/**\n * AI provider settings from Workscribe 1.x. 2.0 removed AI providers, so nothing writes these any more — they're\n * read only to tell 1.x users (see src/summary/legacy-ai.ts) and to keep a stored API key out of bug reports.\n */\nexport interface LegacyAiConfig {\n provider?: string\n apiKey?: string\n model?: string\n baseUrl?: string\n}\n\nexport interface WorkscribeConfig {\n ai?: LegacyAiConfig\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 summaries (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 // 1.x setting (\"template\" | \"ollama\" | \"provider\"). 2.0 always uses the template; read only to detect\n // old configs (src/summary/legacy-ai.ts).\n engine?: string\n }\n projects?: Record<string, string> // absolute path → display name override\n integrations?: {\n slackWebhook?: string\n webhook?: string\n }\n telemetry: {\n enabled: boolean\n installId: string\n }\n}\n\nconst DEFAULTS: WorkscribeConfig = {\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 telemetry: {\n enabled: true,\n installId: '',\n },\n}\n\nexport function readConfig(): WorkscribeConfig {\n if (!fs.existsSync(CONFIG_PATH)) return deepMerge(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 deepMerge(DEFAULTS, {})\n }\n}\n\nexport function writeConfig(config: WorkscribeConfig): void {\n // Previously safe to assume — writeConfig was only ever called after `init`\n // created the data directories, or by `config set` where init had already\n // run. CLI-05's fallback can now call this as the very first filesystem\n // touch for a user who skipped init entirely, so it can't assume the dir exists.\n fs.mkdirSync(path.dirname(CONFIG_PATH), { recursive: true, mode: 0o700 })\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\n// Generates and persists telemetry.installId on first use. Covers both a\n// fresh install and an existing user upgrading — deepMerge already backfills\n// the telemetry key itself, this just fills in the empty installId.\nexport function ensureInstallId(config: WorkscribeConfig): string {\n if (config.telemetry.installId) return config.telemetry.installId\n\n const installId = crypto.randomUUID()\n writeConfig({ ...config, telemetry: { ...config.telemetry, installId } })\n return installId\n}\n\n// Fallback for users who skip `init` entirely — which is exactly what an\n// existing user upgrading will typically do, since they never re-run it.\n// Presence of installId is the only state tracked; no separate \"notice\n// shown\" flag is needed since this is a no-op once installId is set.\nexport function ensureTelemetryFallback(): void {\n // Unlike init's explicit telemetry step, this runs unannounced ahead of\n // every command — it must never throw, however it fails, or a disk issue\n // (read-only $HOME, full disk, a locked-down CI sandbox) would crash the\n // user's actual command before it even starts.\n try {\n const config = readConfig()\n if (config.telemetry.installId) return\n\n config.telemetry.enabled = true\n config.telemetry.installId = ensureInstallId(config)\n\n process.stderr.write(\n '\\n Workscribe collects anonymous install stats (install ID, CLI version, platform, Node version).\\n Opt out: workscribe config set telemetry.enabled false\\n\\n'\n )\n } catch (error) {\n debugLog('ensureTelemetryFallback', error)\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 // structuredClone, not a shallow spread — any key overrides doesn't touch\n // (e.g. a config file written before a newer top-level key existed) must\n // still be an independent copy, not a shared reference back into the\n // caller's `defaults` object. A shallow spread here previously let any\n // caller that mutates a nested field on the returned config (e.g.\n // ensureTelemetryFallback) silently corrupt the module-level DEFAULTS\n // singleton for the rest of the process.\n const result = structuredClone(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 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","// Just enough shell syntax to find command boundaries in captured commands — quotes, escapes,\n// separators and substitutions — without a full parser. Pure and total: never throws.\n\ntype QuoteState = '\"' | \"'\" | null\n\ninterface QuotedCharacter {\n index: number\n quote: QuoteState\n}\n\n// `$(…)` and backticks run a command inside another, also inside double quotes. `<(…)` and `>(…)`\n// run one as a file, but only unquoted — inside double quotes they are plain text.\nconst COMMAND_SUBSTITUTION_OPENER = '$('\nconst PROCESS_SUBSTITUTION_OPENERS = ['<(', '>(']\n\n/**\n * Every character that is content rather than syntax, with the quote it sits in. Quote marks\n * themselves and backslash-escaped characters are skipped — they can't separate or substitute.\n */\nfunction* quotedCharacters(text: string): Generator<QuotedCharacter> {\n let quote: QuoteState = null\n for (let index = 0; index < text.length; index++) {\n const character = text[index]\n if (character === '\\\\' && quote !== \"'\") {\n index++\n continue\n }\n if (character === quote) {\n quote = null\n continue\n }\n if (quote === null && (character === '\"' || character === \"'\")) {\n quote = character\n continue\n }\n yield { index, quote }\n }\n}\n\nexport function isOutsideQuotes(text: string, position: number): boolean {\n for (const { index, quote } of quotedCharacters(text)) {\n if (index >= position) return quote === null\n }\n return true\n}\n\n/** A lone `&` runs the step before it in the background; `2>&1`, `&>` and `>&` are redirections, not separators. */\nfunction isRedirection(text: string, index: number): boolean {\n return text[index] === '&' && (text[index - 1] === '>' || text[index - 1] === '<' || text[index + 1] === '>')\n}\n\n/** Splits on any separator that sits outside single or double quotes. */\nexport function splitOutsideQuotes(text: string, separators: string[]): string[] {\n const parts: string[] = []\n let partStart = 0\n let skipUntil = 0\n for (const { index, quote } of quotedCharacters(text)) {\n if (quote !== null || index < skipUntil || isRedirection(text, index)) continue\n const separator = separators.find((candidate) => text.startsWith(candidate, index))\n if (!separator) continue\n parts.push(text.slice(partStart, index))\n partStart = index + separator.length\n skipUntil = partStart\n }\n parts.push(text.slice(partStart))\n return parts.map((part) => part.trim()).filter((part) => part !== '')\n}\n\n/** Command or process substitution outside single quotes: the shell runs another command inside this one. */\nexport function containsCommandSubstitution(text: string): boolean {\n for (const { index, quote } of quotedCharacters(text)) {\n if (quote === \"'\") continue\n if (text[index] === '`' || text.startsWith(COMMAND_SUBSTITUTION_OPENER, index)) return true\n if (quote === null && PROCESS_SUBSTITUTION_OPENERS.some((opener) => text.startsWith(opener, index))) return true\n }\n return false\n}\n\n// A `#` starts a comment only at the start of a word: `$#`, `${#x}` and `a#b` are not comments.\n// (bash and agents' shells treat it this way; interactive zsh only does with `interactivecomments` set.)\nconst WORD_BOUNDARY = /[\\s;&|()]/\n\n/** Where the first `# …` comment starts (outside quotes, at the start of a word), or -1. */\nexport function commentStart(text: string): number {\n for (const { index, quote } of quotedCharacters(text)) {\n if (quote !== null || text[index] !== '#') continue\n if (index === 0 || WORD_BOUNDARY.test(text[index - 1])) return index\n }\n return -1\n}\n\n/**\n * Removes `# …` comments up to the end of each line. Quote tracking restarts after each comment, so an\n * apostrophe inside one (`# let's check`) can't leave a quote \"open\" for the rest of the command.\n */\nexport function stripComments(text: string): string {\n let result = ''\n let rest = text\n for (let start = commentStart(rest); start !== -1; start = commentStart(rest)) {\n result += rest.slice(0, start)\n const lineEnd = rest.indexOf('\\n', start)\n if (lineEnd === -1) return result\n rest = rest.slice(lineEnd)\n }\n return result + rest\n}\n\n/**\n * The text with everything inside quotes (and the quote marks and escapes themselves) replaced by `_`, keeping\n * every position — so a pattern can be matched against the unquoted parts only and applied to the original.\n */\nexport function maskQuotedText(text: string): string {\n const masked = Array.from({ length: text.length }, () => '_')\n for (const { index, quote } of quotedCharacters(text)) {\n if (quote === null) masked[index] = text[index]\n }\n return masked.join('')\n}\n\nexport function startsWithWord(step: string, word: string): boolean {\n return step === word || step.startsWith(`${word} `) || step.startsWith(`${word}\\t`)\n}\n","// Breaks a captured shell command into the simple commands it runs, so each one can be classified or\n// filtered on its own — agents run things like `cd app && pnpm nx test shell 2>&1 | tail -40; npx tsc`.\n// Works on the raw command (heredocs and newlines are lost once whitespace is collapsed). Pure, never throws.\nimport {\n commentStart,\n containsCommandSubstitution,\n isOutsideQuotes,\n maskQuotedText,\n splitOutsideQuotes,\n startsWithWord,\n stripComments,\n} from './shell-syntax'\n\nconst STEP_SEPARATORS = ['&&', '||', ';', '\\n', '&']\nconst PIPE_SEPARATORS = ['|']\n/** Commands that only produce text. */\nexport const TEXT_SOURCES = ['echo', 'printf']\n// Steps that do no work of their own when they run nothing inside them\nconst GLUE_COMMANDS = ['cd', 'true', ':', ...TEXT_SOURCES]\n// `<<TAG`, `<<-TAG`, `<<'TAG'`, `<<\"TAG\"` — but not a `<<<` here-string\nconst HEREDOC_OPENER = /(?<!<)<<(?!<)-?\\s*(['\"]?)([A-Za-z_][A-Za-z0-9_]*)\\1/g\n// Words that wrap the command after them: `do npm test`, `if npm test`, `! grep x`, `time make`\nconst KEYWORD_PREFIX = /^(?:do|then|else|elif|if|while|until|time|!)\\s+/\n// Loop and case headers — shell structure, unless they run a command (`for f in $(npm test)`)\nconst STRUCTURE_HEADER = /^(?:for|select|case)\\s/\n// Closing keywords and bare keywords left over once a step is split\nconst STRUCTURE_KEYWORD = /^(?:done|fi|esac|\\}|\\)|do|then|else)$/\n// `NAME=value` before a command (or on its own); the value may be quoted or a `$(…)` substitution\nconst LEADING_ASSIGNMENT = /^[A-Za-z_][A-Za-z0-9_]*=(?:\"[^\"]*\"|'[^']*'|\\$\\([^)]*\\)|\\S*)(?:\\s+|$)/\n// `2>&1`, `> file`, `2>/dev/null`, `&> log`, `>> file`, `< input`\nconst REDIRECTION = /(?:^|\\s)(?:\\d*>>?|&>>?|<)\\s*(?:&\\d+|[^\\s;|&]+)/g\n// Package-runner forms that mean \"run this tool\", rewritten to `npx …` so the npx rules recognise them\nconst TOOL_RUNNER = /^(?:(?:pnpm|yarn|npm)\\s+exec|pnpm\\s+dlx|bunx)\\s+/\nconst FIRST_SUBSTITUTION = /\\$\\(([^()]*)\\)/\n// `$(…)` and backtick substitutions, for the commands inside them\nconst SUBSTITUTIONS = /\\$\\(([^()]*)\\)|`([^`]*)`/g\n\n/** The commands a line's `$(…)`/backtick substitutions run — what the shell executes from heredoc text. */\nfunction substitutionCommands(line: string): string[] {\n return [...line.matchAll(SUBSTITUTIONS)]\n .map((match) => (match[1] ?? match[2] ?? '').trim())\n .filter((command) => command !== '')\n}\n\n/**\n * Removes heredoc bodies, keeping the line that opens each one, so their text can't look like commands.\n * The shell still runs `$(…)` inside an unquoted heredoc (`<<EOF`, not `<<'EOF'`), so the commands inside\n * those substitutions stay — each on its own line, without the surrounding text (whose apostrophes and\n * other characters would otherwise be read as shell syntax).\n */\nexport function stripHeredocBodies(command: string): string {\n const kept: string[] = []\n const pending: { terminator: string; runsSubstitutions: boolean }[] = []\n for (const line of command.split('\\n')) {\n if (pending.length > 0) {\n if (line.trim() === pending[0].terminator) pending.shift()\n else if (pending[0].runsSubstitutions && containsCommandSubstitution(line))\n kept.push(...substitutionCommands(line))\n continue\n }\n kept.push(line)\n const comment = commentStart(line)\n for (const match of line.matchAll(HEREDOC_OPENER)) {\n // `\"a<<b\"` is text inside quotes, `\\<<` an escaped `<` and `# see <<EOF` a comment — none opens a heredoc\n const isEscaped = line[match.index - 1] === '\\\\'\n const isInComment = comment !== -1 && match.index > comment\n if (isEscaped || isInComment || !isOutsideQuotes(line, match.index)) continue\n pending.push({ terminator: match[2], runsSubstitutions: match[1] === '' })\n }\n }\n return kept.join('\\n')\n}\n\n/** The steps a shell runs: split on newlines, `&&`, `||`, `;` and a background `&`, outside quotes. */\nexport function splitSteps(command: string): string[] {\n return splitOutsideQuotes(command, STEP_SEPARATORS)\n}\n\nfunction countOf(text: string, character: string): number {\n return text.split(character).length - 1\n}\n\n/** `(cd app && npm test)` splits into `(cd app` and `npm test)` — drop the unbalanced group brackets. */\nfunction withoutGroupBrackets(step: string): string {\n let unwrapped = step\n while (unwrapped.startsWith('(') && countOf(unwrapped, '(') > countOf(unwrapped, ')')) {\n unwrapped = unwrapped.slice(1).trim()\n }\n while (unwrapped.endsWith(')') && countOf(unwrapped, ')') > countOf(unwrapped, '(')) {\n unwrapped = unwrapped.slice(0, -1).trim()\n }\n if (unwrapped.startsWith('{ ')) unwrapped = unwrapped.slice(2).trim()\n return unwrapped\n}\n\nfunction withoutKeywordPrefixes(step: string): string {\n let unwrapped = step\n while (KEYWORD_PREFIX.test(unwrapped)) unwrapped = unwrapped.replace(KEYWORD_PREFIX, '')\n return unwrapped\n}\n\nfunction withoutLeadingAssignments(step: string): string {\n let unwrapped = step\n while (LEADING_ASSIGNMENT.test(unwrapped)) unwrapped = unwrapped.replace(LEADING_ASSIGNMENT, '')\n return unwrapped\n}\n\n/** `d=node_modules/x` does nothing on its own; `f=$(npm test)` still runs `npm test`, so it stays. */\nfunction isPlainAssignment(step: string): boolean {\n return withoutLeadingAssignments(step) === '' && !containsCommandSubstitution(step)\n}\n\n/** Loop headers and closing keywords do no work — but a header that runs a command (`for f in $(ls)`) does. */\nfunction isShellStructure(step: string): boolean {\n if (STRUCTURE_KEYWORD.test(step)) return true\n return STRUCTURE_HEADER.test(step) && !containsCommandSubstitution(step)\n}\n\n/** Removes redirections (`2>&1`, `> out.txt`) outside quotes — a `>` inside a commit message is kept. */\nfunction withoutRedirections(command: string): string {\n const masked = maskQuotedText(command)\n let result = ''\n let copiedUpTo = 0\n for (const match of masked.matchAll(REDIRECTION)) {\n result += command.slice(copiedUpTo, match.index)\n copiedUpTo = match.index + match[0].length\n }\n return result + command.slice(copiedUpTo)\n}\n\n/**\n * The commands a captured shell line runs, in order: comments and heredoc bodies removed, split into steps,\n * group brackets and wrapping keywords (`do`, `then`, `if`…) removed, and loop headers, closing keywords and\n * plain assignments dropped.\n */\nexport function commandSteps(rawCommand: string): string[] {\n return splitSteps(stripComments(stripHeredocBodies(rawCommand)))\n .map((step) => withoutKeywordPrefixes(withoutGroupBrackets(step)))\n .filter((step) => step !== '' && !isShellStructure(step) && !isPlainAssignment(step))\n}\n\n/**\n * The command a step mainly runs, in a form the normalizer rules can match: leading assignments, everything\n * after the first `|`, and redirections removed; `pnpm exec tsc` read as `npx tsc`. For an assignment or a\n * loop header that runs a command (`f=$(find . -name x)`, `for f in $(npm test)`), the command inside.\n */\nexport function simpleCommandOf(step: string): string {\n const command = withoutLeadingAssignments(step)\n if (command === '' || STRUCTURE_HEADER.test(command)) return step.match(FIRST_SUBSTITUTION)?.[1]?.trim() ?? ''\n const [firstStage = ''] = splitOutsideQuotes(command, PIPE_SEPARATORS)\n return withoutRedirections(firstStage).replace(/\\s+/g, ' ').trim().replace(TOOL_RUNNER, 'npx ')\n}\n\n/**\n * Shell glue that does no work of its own — `cd`, `true`, `:`, or printing text — as long as it runs\n * nothing inside it and pipes nothing. Agents wrap commands in these (`… || true`, `; echo \"exit=$?\"`).\n */\nexport function isGlueStep(step: string): boolean {\n if (containsCommandSubstitution(step) || splitOutsideQuotes(step, PIPE_SEPARATORS).length > 1) return false\n return GLUE_COMMANDS.some((command) => startsWithWord(step, command))\n}\n","// Categories excluded from summary input 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 summary context for commands that don't fit known patterns\n// (e.g. docker compose up, make deploy, terraform apply).\n// Only a type import, so the template engine and the --json contract can use this without loading profiles or the DB.\nimport type { SessionPayload } from '../ai/types'\n\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 category of includeCategories) excluded.delete(category)\n return excluded\n}\n\n/** How many events of each excluded category the summary left out — for the footer under `workscribe summary`. */\nexport function countExcludedEvents(sessions: SessionPayload[], excluded: Set<string>): 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)) counts.set(event.category, (counts.get(event.category) ?? 0) + 1)\n }\n }\n return counts\n}\n","// Classifies compound shell commands — `cd app && pnpm nx test shell 2>&1 | tail -40; npx tsc` — by their most\n// telling step. Pure: the rule matcher is passed in, so this module doesn't load the rules (or the profiles).\nimport { commandSteps, isGlueStep, simpleCommandOf } from '../capture/command-steps'\nimport { DEFAULT_EXCLUDED_CATEGORIES } from '../summary/exclusions'\nimport type { NormalizedEvent } from './patterns'\n\nexport type MatchCommand = (command: string) => NormalizedEvent\n\nexport const UNCLASSIFIED: NormalizedEvent = { category: 'other', metadata: {} }\n\n// When a compound command runs several things, the event takes the step that says most about the work:\n// outcomes first, then routine work. `git status` (versioning) must never hide `npm test` next to it.\nexport const STEP_CATEGORY_PRIORITY = [\n 'testing',\n 'building',\n 'releasing',\n 'shipping',\n 'dependencies',\n 'database',\n 'infrastructure',\n 'running',\n 'files',\n 'versioning',\n]\n\n// Ranks after the priority list, lower is more telling: any other category, then ones summaries leave out, then `other`\nconst OTHER_CATEGORY_RANK = STEP_CATEGORY_PRIORITY.length\nconst EXCLUDED_CATEGORY_RANK = OTHER_CATEGORY_RANK + 1\nconst UNCLASSIFIED_RANK = EXCLUDED_CATEGORY_RANK + 1\n\nfunction rankOf(category: string): number {\n const index = STEP_CATEGORY_PRIORITY.indexOf(category)\n if (index !== -1) return index\n if (category === UNCLASSIFIED.category) return UNCLASSIFIED_RANK\n if (DEFAULT_EXCLUDED_CATEGORIES.has(category)) return EXCLUDED_CATEGORY_RANK\n return OTHER_CATEGORY_RANK\n}\n\n/** The most telling step's event; ties go to the earlier step. */\nfunction primaryStepEvent(steps: string[], matchCommand: MatchCommand): NormalizedEvent {\n const events = steps.map((step) => matchCommand(simpleCommandOf(step)))\n return events.reduce((best, event) => (rankOf(event.category) < rankOf(best.category) ? event : best), UNCLASSIFIED)\n}\n\n/**\n * A command the rules already recognise as it is, with nothing else to run, keeps that result. Otherwise it's\n * split into the commands it runs, shell glue (`cd`, `echo`, assignments, loop keywords) is set aside, and the\n * most telling step names the event — falling back to the whole command when no step is recognised either.\n */\nexport function classifyCompound(command: string, matchCommand: MatchCommand): NormalizedEvent {\n const wholeCommandEvent = matchCommand(command)\n const workSteps = commandSteps(command).filter((step) => !isGlueStep(step))\n const isRecognisedSingleCommand = workSteps.length <= 1 && wholeCommandEvent.category !== UNCLASSIFIED.category\n if (isRecognisedSingleCommand || workSteps.length === 0) return wholeCommandEvent\n\n const primaryEvent = primaryStepEvent(workSteps, matchCommand)\n return primaryEvent.category === UNCLASSIFIED.category ? wholeCommandEvent : primaryEvent\n}\n","import { loadAIToolRegistry } from '../config/registry'\nimport { getActiveProfileRules } from '../profiles/loader'\nimport { debugLog } from '../utils/logger'\nimport { classifyCompound, UNCLASSIFIED } from './compound'\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\n// Nx targets → categories: `nx build app`, `nx run app:test`, `nx run-many -t lint`, `nx affected --target=e2e`\nconst NX_TARGET_CATEGORIES: Record<string, string> = {\n build: 'building',\n test: 'testing',\n e2e: 'testing',\n lint: 'linting',\n serve: 'running',\n dev: 'running',\n}\nconst NX_COMMAND =\n /^(?:(?:npx|pnpm|yarn|bunx)\\s+)?nx\\s+(?:(?:run-many|affected)\\b.*?(?:-t|--targets?)[=\\s]+([\\w-]+)|run\\s+[\\w@./-]+:([\\w-]+)|([\\w-]+)\\b)/\n\nconst nxRule: Rule = {\n match(cmd) {\n const match = cmd.match(NX_COMMAND)\n const target = match?.[1] ?? match?.[2] ?? match?.[3]\n const category = target ? NX_TARGET_CATEGORIES[target] : undefined\n return category ? { category, metadata: { tool: 'nx', target } } : null\n },\n}\n\nconst BASE_RULES: Rule[] = [\n // ─── Git operations ───────────────────────────────────────────────────────\n makeRule(/^git\\s+commit\\b/, 'shipping', (_m, cmd) => {\n // -m \"…\" / -m '…' keep the whole message (an apostrophe inside double quotes is part of it);\n // an unquoted -m takes one word, so `-m wip --no-verify` is \"wip\", not \"wip --no-verify\"\n const msgMatch = cmd.match(/-m\\s+(?:\"([^\"]*)\"|'([^']*)'|(\\S+))/)\n const message = msgMatch ? (msgMatch[1] ?? msgMatch[2] ?? msgMatch[3]).trim() : null\n return { message: message || null }\n }),\n\n makeRule(/^git\\s+push\\b/, 'shipping', (_m, cmd) => {\n // Flags (-u, --force, …) aren't the remote or branch: `git push -u origin main` → origin/main\n const positional = cmd\n .split(/\\s+/)\n .slice(2)\n .filter((part) => !part.startsWith('-'))\n return { remote: positional[0] ?? 'origin', branch: positional[1] ?? 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 action: 'remove',\n })),\n\n makeRule(/^(yarn|pnpm)\\s+remove\\b/, 'dependencies', (m, cmd) => ({\n tool: m[1],\n packages: extractPackages(cmd, 'remove'),\n action: 'remove',\n })),\n\n makeRule(/^bun\\s+remove\\b/, 'dependencies', (_m, cmd) => ({\n tool: 'bun',\n packages: extractPackages(cmd, 'remove'),\n action: 'remove',\n })),\n\n makeRule(/^pip\\s+uninstall\\b/, 'dependencies', (_m, cmd) => ({\n tool: 'pip',\n packages: extractPackages(cmd, 'uninstall'),\n action: 'remove',\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 // ─── Nx (before the package-manager rules, which would read `pnpm nx` as `pnpm`) ─\n nxRule,\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\n// Built on first use, not at import: the active profiles come from the config and profile files, and\n// importing this module (via capture, or the database's migrations) shouldn't read either\nlet activeRules: Rule[] | null = null\n\nfunction getRules(): Rule[] {\n activeRules ??= buildRules(getActiveProfileRules())\n return activeRules\n}\n\nfunction matchRules(command: string): NormalizedEvent {\n // Strip `git -C <path>` prefix so rules match regardless of working directory flag\n const flattened = command\n .trim()\n .replace(/\\s+/g, ' ')\n .replace(/^(git)\\s+-C\\s+\\S+\\s+/, '$1 ')\n for (const rule of getRules()) {\n const result = rule.match(flattened)\n if (result) return result\n }\n return UNCLASSIFIED\n}\n\n/** Classifies a captured command — compound ones by their most telling step (see `./compound`). */\nexport function normalizeCommand(command: string): NormalizedEvent {\n return classifyCompound(command, matchRules)\n}\n","import type { NormalizedEvent } from './patterns'\n\nexport interface ReclassifyOptions {\n classify: (command: string) => NormalizedEvent\n /** `capture.aiTools` — when it's off, Workscribe doesn't record AI sessions, so none are created here either. */\n aiToolsEnabled: boolean\n}\n\n/**\n * The new category and metadata for a stored `other` event, or null to leave it alone. The metadata\n * replaces the old one entirely, so the `hint`/`tool` kept for unclassified commands doesn't linger.\n */\nexport function reclassifiedEvent(\n command: string,\n { classify, aiToolsEnabled }: ReclassifyOptions\n): NormalizedEvent | null {\n const event = classify(command)\n if (event.category === 'other') return null\n if (event.category === 'ai_session' && !aiToolsEnabled) return null\n return event\n}\n","// Reclassifies stored `other` events with the classifier as it is when this runs — so on an install that first\n// opens its database with a later release, later rules and the user's active profiles apply too. That's fine:\n// it only ever improves `other` rows, never touches any other row or a stored command, and skips what it can't classify.\nimport { normalizeCommand } from '../../normalize/patterns'\nimport { reclassifiedEvent } from '../../normalize/reclassify'\nimport { readConfig } from '../../config'\nimport { debugLog } from '../../utils/logger'\nimport type { Migration, MigrationDatabase } from '../migration-types'\n\ninterface UnclassifiedRow {\n id: number\n command: string\n}\n\nfunction classifyOrSkip(row: UnclassifiedRow, aiToolsEnabled: boolean): ReturnType<typeof reclassifiedEvent> {\n try {\n return reclassifiedEvent(row.command, { classify: normalizeCommand, aiToolsEnabled })\n } catch (error) {\n // Best-effort: this runs the first time any command opens the database after upgrading (even the\n // background capture), so one odd command must never fail the migration and lock the database out\n debugLog('migration-006', error)\n return null\n }\n}\n\nconst migration: Migration = {\n version: 6,\n description: 'Reclassify unclassified events now that compound commands are classified by their main step',\n sql: '',\n run(db: MigrationDatabase) {\n const aiToolsEnabled = readConfig().capture.aiTools !== false\n const rows = db.prepare(\"SELECT id, command FROM events WHERE category = 'other'\").all() as UnclassifiedRow[]\n const update = db.prepare('UPDATE events SET category = ?, metadata = ? WHERE id = ?')\n for (const row of rows) {\n const event = classifyOrSkip(row, aiToolsEnabled)\n if (!event) continue\n const metadata = Object.keys(event.metadata).length > 0 ? JSON.stringify(event.metadata) : null\n update.run(event.category, metadata, row.id)\n }\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'\nimport sessionSummaries from './005_session_summaries'\nimport reclassifyOther from './006_reclassify_other'\nimport type { Migration } from '../migration-types'\n\nexport type { Migration } from '../migration-types'\n\n// Ordered list — append only. Never modify or remove an existing entry.\nexport const MIGRATIONS: Migration[] = [\n initialSchema,\n semanticCategories,\n alerts,\n ideColumns,\n sessionSummaries,\n reclassifyOther,\n]\n","import type { Migration, MigrationDatabase } from './migration-types'\n\n/** An install from before the migration system already has the events table — record version 1 as applied. */\nfunction seedVersionOneForOldInstalls(db: MigrationDatabase): void {\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 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\nfunction isApplied(db: MigrationDatabase, version: number): boolean {\n return db.prepare('SELECT version FROM schema_migrations WHERE version = ?').get(version) !== undefined\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n\n/**\n * Applies each pending migration in order, each in its own transaction, so a failure leaves the database at\n * the previous version and the next run retries it. `BEGIN IMMEDIATE` takes the write lock up front and the\n * version is checked inside the transaction, so two processes starting at once (parallel captures from an\n * agent) can't both run a migration. Kept free of `node:sqlite` so tests can run it on any database.\n */\nexport function applyMigrations(db: MigrationDatabase, migrations: Migration[]): void {\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 seedVersionOneForOldInstalls(db)\n\n for (const migration of migrations) {\n if (isApplied(db, migration.version)) continue\n\n db.exec('BEGIN IMMEDIATE')\n try {\n if (isApplied(db, migration.version)) {\n db.exec('COMMIT')\n continue\n }\n if (migration.sql.trim()) db.exec(migration.sql)\n migration.run?.(db)\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 (error) {\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: ${errorMessage(error)}`, {\n cause: error,\n })\n }\n }\n}\n","import { DatabaseSync } from 'node:sqlite'\nimport fs from 'fs'\nimport { WORKSCRIBE_DIR, DB_PATH } from '../utils/paths'\nimport type { EventRow, SessionRow, SessionSummaryRow } from './types'\nimport { MIGRATIONS } from './migrations'\nimport { applyMigrations } from './migrate'\nimport type { StoredEngine } from '../ai/engine'\nexport type { EventRow, SessionRow, SessionSummaryRow } 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 try {\n fs.mkdirSync(WORKSCRIBE_DIR, { recursive: true })\n } catch (error) {\n // Rethrown as a clean, actionable message — callers reaching this\n // (explicit commands, or _capture/_hook's own try/catch) otherwise\n // only see a raw native stack trace with the real cause buried in it.\n throw new Error(`Could not create data directory ${WORKSCRIBE_DIR}: ${(error as Error).message}`)\n }\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 // Parallel captures (an agent running several commands at once) wait for the write lock instead of failing\n db.exec('PRAGMA busy_timeout = 5000')\n applyMigrations(db, MIGRATIONS)\n _db = db\n return _db\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 getLastEventForCwd(cwd: string): EventRow | undefined {\n const db = getDb()\n return db.prepare('SELECT * FROM events WHERE cwd = $cwd ORDER BY id DESC LIMIT 1').get({ cwd }) as\n | EventRow\n | 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 getSessionSummaries(sessionKey: string): SessionSummaryRow[] {\n const db = getDb()\n const stmt = db.prepare('SELECT * FROM session_summaries WHERE session_key = $session_key')\n return stmt.all({ session_key: sessionKey }) as unknown as SessionSummaryRow[]\n}\n\nexport function saveSessionSummary(sessionKey: string, engine: StoredEngine, text: string): void {\n const db = getDb()\n const stmt = db.prepare(`\n INSERT INTO session_summaries (session_key, engine, text, created_at)\n VALUES ($session_key, $engine, $text, $created_at)\n ON CONFLICT (session_key, engine) DO UPDATE SET text = excluded.text, created_at = excluded.created_at\n `)\n stmt.run({ session_key: sessionKey, engine, text, created_at: new Date().toISOString() })\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","// Recognises Workscribe's own commands inside compound shell input, so a coding agent running the\n// Workscribe skill (`cd repo && workscribe …`, `… | workscribe …`, heredocs) isn't captured as work.\n// Works on the raw command: heredocs and newlines are lost once whitespace is collapsed.\nimport { containsCommandSubstitution, splitOutsideQuotes, startsWithWord } from './shell-syntax'\nimport { commandSteps, isGlueStep, TEXT_SOURCES } from './command-steps'\n\nconst PIPE_SEPARATORS = ['|']\n\n/**\n * A step is Workscribe's when it starts with `workscribe` (whatever it's piped into), or when it only\n * pipes text into it (`echo … | workscribe …`). `npm test | workscribe note done` still ran the tests,\n * and so does `workscribe note \"$(npm test)\"`, so neither is.\n */\nfunction isWorkscribeStep(step: string): boolean {\n if (containsCommandSubstitution(step)) return false\n const stages = splitOutsideQuotes(step, PIPE_SEPARATORS)\n if (startsWithWord(stages[0] ?? '', 'workscribe')) return true\n const isTextOrWorkscribe = (stage: string): boolean =>\n startsWithWord(stage, 'workscribe') || TEXT_SOURCES.some((source) => startsWithWord(stage, source))\n return stages.every(isTextOrWorkscribe) && stages.some((stage) => startsWithWord(stage, 'workscribe'))\n}\n\n/**\n * True when the command does nothing but run Workscribe — possibly wrapped in shell glue (`cd`,\n * `|| true`, `; echo $?`), piped into, or with a heredoc. A command that also does real work\n * (`npm test && workscribe note …`) is not Workscribe-only.\n */\nexport function isWorkscribeOnlyCommand(rawCommand: string): boolean {\n const steps = commandSteps(rawCommand)\n const workSteps = steps.filter((step) => !isGlueStep(step))\n return workSteps.length > 0 && workSteps.every(isWorkscribeStep)\n}\n","import type { EventRow } from '../db/types'\nimport { isWorkscribeOnlyCommand } from './workscribe-command'\nimport { commandSteps, isGlueStep } from './command-steps'\n\nfunction normalizeForFilter(cmd: string): string {\n return cmd.trim().replace(/\\s+/g, ' ')\n}\n\nfunction isIgnoredStep(step: string, ignoreList: string[]): boolean {\n const normalized = normalizeForFilter(step)\n return ignoreList.includes(normalized) || ignoreList.includes(normalized.split(' ')[0])\n}\n\n/**\n * Returns true if the command should be dropped (noise / ignore list).\n *\n * The ignore list applies to each step of a compound command: `cd app && npm test` is kept because\n * `npm test` is real work, while `cd app && ls` is dropped. A step that does nothing on its own (`cd`,\n * `echo`) can't keep a command, but a command made only of such steps is dropped only if one of them is\n * on the ignore list — so `echo hi` on its own is still captured, as before.\n */\nexport function shouldFilter(command: string, ignoreList: string[]): boolean {\n const normalized = normalizeForFilter(command)\n if (!normalized) return true\n\n // Workscribe's own commands — always excluded, not user-configurable. Checked on the raw command so\n // compound ones an agent runs are caught too, while `workscribe note \"$(npm test)\"` still counts as work.\n if (isWorkscribeOnlyCommand(command)) return true\n\n const normalizedIgnore = ignoreList.map(normalizeForFilter)\n if (normalizedIgnore.includes(normalized)) return true\n\n const steps = commandSteps(command)\n const isQuiet = (step: string): boolean => isIgnoredStep(step, normalizedIgnore) || isGlueStep(step)\n return steps.every(isQuiet) && steps.some((step) => isIgnoredStep(step, normalizedIgnore))\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// task_run can double-capture: a shell task running in a hooked terminal\n// fires both this generic event and a richer shell-sourced one, with no\n// shared ID linking them. Shell events land first (precmd fires as the\n// command returns), so a short window here catches the same real action.\nexport const TASK_RUN_DEDUP_WINDOW_MS = 5_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, getLastEventForCwd } 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, TASK_RUN_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 // A shell task running in a hooked terminal already got captured with a\n // real category by the shell hook — skip the generic duplicate.\n if (opts.type === 'task_run') {\n const lastForCwd = getLastEventForCwd(cwd)\n if (lastForCwd && !lastForCwd.source) {\n const lastTime = new Date(lastForCwd.captured_at).getTime()\n if (Date.now() - lastTime < TASK_RUN_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 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}\ncompdef _workscribe 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'\nconst COMPLETIONS_MARKER = '# Workscribe completions'\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 // Invoking node directly (rather than executing workscribe's own shebang)\n // bypasses the `--disable-warning=ExperimentalWarning` flag postbuild.js\n // bakes into dist/index.js's shebang — shebang flags only apply when the\n // OS execs the file via its shebang line, not when node is invoked\n // explicitly. Without repeating the flag here, every pinned-node-path\n // invocation (the default whenever a version manager is detected) leaks\n // the node:sqlite ExperimentalWarning to stderr.\n const pinnedInvocation = `\"${nodePath}\" --disable-warning=ExperimentalWarning \"${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(COMPLETIONS_MARKER)\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 // installCompletions can be called more than once (e.g. isCompletionsInstalled\n // raced with a concurrent init, or a caller re-runs it to refresh the cache\n // file). The rcFile append must stay idempotent so repeated calls never grow\n // duplicate source lines.\n if (!isCompletionsInstalled(shell)) {\n const sourceLine =\n shell.name === 'zsh'\n ? `\\n${COMPLETIONS_MARKER}\\nautoload -Uz compinit && compinit\\nsource \"${cacheFile}\"\\n`\n : `\\n${COMPLETIONS_MARKER}\\nsource \"${cacheFile}\"\\n`\n fs.appendFileSync(shell.rcFile, sourceLine)\n }\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\nexport const HIDDEN_COMMANDS = new Set(['_capture', '_hook'])\n\n// _capture/_hook fire on every shell command as a detached background process\n// that must never add latency — startup checks (update check, telemetry) skip\n// those outright rather than relying on a cache alone.\nexport function shouldRunStartupChecks(invokedCommand: string | undefined): boolean {\n if (invokedCommand === undefined) return true\n return !HIDDEN_COMMANDS.has(invokedCommand)\n}\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","/** Caches a single-argument lookup by its string key for the lifetime of the returned function. */\nexport function memoize<Value>(lookup: (key: string) => Value): (key: string) => Value {\n // Boxed so a cached null/undefined result is told apart from a missing entry\n const cache = new Map<string, { value: Value }>()\n return (key) => {\n const cached = cache.get(key)\n if (cached) return cached.value\n const value = lookup(key)\n cache.set(key, { value })\n return value\n }\n}\n","import type { SkillAgent } from './types'\n\n/** Folder name the skill is installed under, inside each agent's skills folder. */\nexport const SKILL_NAME = 'workscribe'\n\n/** Marker file that identifies a Workscribe-installed copy of the skill. */\nexport const MARKER_FILE = '.workscribe-skill.json'\n\n// Skills folders checked against each vendor's docs (2026-10-26). If a vendor moves its folder,\n// only this table needs to change.\nexport const SKILL_AGENTS: SkillAgent[] = [\n {\n id: 'claude-code',\n name: 'Claude Code',\n skillsFolder: '.claude/skills',\n commands: ['claude'],\n homeFolders: ['.claude'],\n vscodeExtensionPrefixes: [],\n docsUrl: 'https://code.claude.com/docs/en/skills',\n },\n {\n id: 'codex',\n name: 'Codex',\n skillsFolder: '.agents/skills',\n commands: ['codex'],\n homeFolders: ['.codex'],\n vscodeExtensionPrefixes: [],\n docsUrl: 'https://learn.chatgpt.com/docs/build-skills',\n },\n {\n id: 'copilot',\n name: 'GitHub Copilot',\n skillsFolder: '.agents/skills',\n commands: ['copilot'],\n homeFolders: ['.copilot'],\n vscodeExtensionPrefixes: ['github.copilot-chat'],\n docsUrl: 'https://docs.github.com/en/copilot/how-tos/copilot-cli/customize-copilot/add-skills',\n },\n {\n id: 'cursor',\n name: 'Cursor',\n skillsFolder: '.cursor/skills',\n commands: ['cursor', 'cursor-agent'],\n homeFolders: ['.cursor'],\n vscodeExtensionPrefixes: [],\n docsUrl: 'https://cursor.com/docs/skills',\n },\n]\n\nexport const SKILL_AGENT_IDS = SKILL_AGENTS.map((agent) => agent.id)\n","import fs from 'fs'\nimport os from 'os'\nimport path from 'path'\nimport { isCommandInstalled } from '../capture/hooks/utils'\nimport { memoize } from '../utils/memoize'\nimport { SKILL_AGENTS } from './agents'\nimport type { SkillAgent } from './types'\n\n/** The I/O detection needs — injected so tests can describe a machine without touching the real one. */\nexport interface DetectionEnvironment {\n homeDir: string\n isCommandInstalled: (command: string) => boolean\n pathExists: (absolutePath: string) => boolean\n listDirectory: (absolutePath: string) => string[]\n}\n\nexport function defaultDetectionEnvironment(): DetectionEnvironment {\n return {\n homeDir: os.homedir(),\n // `which` spawns a process, so each command is looked up at most once per run\n isCommandInstalled: memoize(isCommandInstalled),\n pathExists: (absolutePath) => fs.existsSync(absolutePath),\n listDirectory: (absolutePath) => {\n try {\n return fs.readdirSync(absolutePath)\n } catch {\n return [] // a missing extensions folder just means no extensions\n }\n },\n }\n}\n\nfunction hasHomeFolder(agent: SkillAgent, environment: DetectionEnvironment): boolean {\n return agent.homeFolders.some((folder) => environment.pathExists(path.join(environment.homeDir, folder)))\n}\n\nfunction hasVscodeExtension(agent: SkillAgent, environment: DetectionEnvironment): boolean {\n if (agent.vscodeExtensionPrefixes.length === 0) return false\n const extensions = environment.listDirectory(path.join(environment.homeDir, '.vscode', 'extensions'))\n return extensions.some((extension) => agent.vscodeExtensionPrefixes.some((prefix) => extension.startsWith(prefix)))\n}\n\n/** Folder signals are checked first; `which` is only spawned when none of them found the agent. */\nexport function isAgentPresent(agent: SkillAgent, environment: DetectionEnvironment): boolean {\n return (\n hasHomeFolder(agent, environment) ||\n hasVscodeExtension(agent, environment) ||\n agent.commands.some((command) => environment.isCommandInstalled(command))\n )\n}\n\nexport function detectAgents(environment: DetectionEnvironment = defaultDetectionEnvironment()): SkillAgent[] {\n return SKILL_AGENTS.filter((agent) => isAgentPresent(agent, environment))\n}\n","import type { InstallOutcome, SkillAgent, SkillInstallState, SkillMarker, SkillsFolderGroup } from './types'\n\n/** One entry per distinct skills folder, in registry order — Codex and Copilot share `.agents/skills`. */\nexport function groupBySkillsFolder(agents: SkillAgent[]): SkillsFolderGroup[] {\n const groups = new Map<string, SkillAgent[]>()\n for (const agent of agents) groups.set(agent.skillsFolder, [...(groups.get(agent.skillsFolder) ?? []), agent])\n return [...groups.entries()].map(([skillsFolder, groupAgents]) => ({ skillsFolder, agents: groupAgents }))\n}\n\n/**\n * Names the agents a folder serves, noting any other agent that reads the same folder — installing or\n * removing for Codex also changes it for GitHub Copilot, and the message should say so.\n */\nexport function describeFolderAgents(group: SkillsFolderGroup, allAgents: SkillAgent[]): string {\n const sharers = allAgents.filter(\n (agent) => agent.skillsFolder === group.skillsFolder && !group.agents.includes(agent)\n )\n const names = joinAgentNames(group.agents)\n return sharers.length === 0 ? names : `${names} (folder shared with ${joinAgentNames(sharers)})`\n}\n\n/** The result `init` can report without asking: up to date, or a folder it doesn't own. Null means ask. */\nexport function outcomeWithoutPrompt(state: SkillInstallState): InstallOutcome | null {\n if (state.kind === 'installed') return 'up-to-date'\n if (state.kind === 'not-ours') return 'skipped-not-ours'\n return null\n}\n\n/** \"Codex\", \"Codex and GitHub Copilot\", \"Claude Code, Codex and Cursor\". */\nexport function joinAgentNames(agents: SkillAgent[]): string {\n const names = agents.map((agent) => agent.name)\n if (names.length <= 1) return names[0] ?? ''\n return `${names.slice(0, -1).join(', ')} and ${names[names.length - 1]}`\n}\n\n/** What's in an agent's `workscribe` skill folder, judged by its marker. */\nexport function describeInstallState(input: {\n folderExists: boolean\n marker: SkillMarker | null\n currentVersion: string\n}): SkillInstallState {\n if (!input.folderExists) return { kind: 'not-installed' }\n if (!input.marker) return { kind: 'not-ours' }\n if (input.marker.version === input.currentVersion) return { kind: 'installed', version: input.marker.version }\n return { kind: 'outdated', version: input.marker.version }\n}\n","import fs from 'fs'\nimport path from 'path'\nimport { MARKER_FILE, SKILL_NAME } from './agents'\nimport { describeInstallState } from './state'\nimport type { InstallOutcome, InstallSkillOptions, SkillInstallState, SkillMarker, UninstallOutcome } from './types'\n\nfunction isSkillMarker(value: unknown): value is SkillMarker {\n const candidate = value as Partial<SkillMarker> | null\n return typeof candidate?.version === 'string' && typeof candidate?.installedAt === 'string'\n}\n\nfunction readMarker(skillDir: string): SkillMarker | null {\n try {\n const parsed: unknown = JSON.parse(fs.readFileSync(path.join(skillDir, MARKER_FILE), 'utf-8'))\n return isSkillMarker(parsed) ? parsed : null\n } catch {\n return null // no marker, or not ours to read — either way it isn't a Workscribe install\n }\n}\n\n/** State of the Workscribe skill inside one agent skills folder (e.g. `~/.claude/skills`). */\nexport function readInstallState(skillsFolder: string, currentVersion: string): SkillInstallState {\n const skillDir = path.join(skillsFolder, SKILL_NAME)\n return describeInstallState({\n folderExists: fs.existsSync(skillDir),\n marker: readMarker(skillDir),\n currentVersion,\n })\n}\n\nfunction copyDirectory(from: string, to: string): void {\n fs.mkdirSync(to, { recursive: true })\n for (const entry of fs.readdirSync(from, { withFileTypes: true })) {\n const source = path.join(from, entry.name)\n const destination = path.join(to, entry.name)\n if (entry.isDirectory()) copyDirectory(source, destination)\n else fs.copyFileSync(source, destination)\n }\n}\n\n/**\n * Swaps a fully prepared copy into place: move any existing copy aside, rename the new one in, then\n * delete the old one — or put it back if the rename fails. A plain rename over a non-empty folder\n * fails on POSIX, and this way an interrupted install never leaves a half-written skill.\n */\nfunction swapInto(skillDir: string, preparedDir: string): void {\n const previousDir = path.join(path.dirname(skillDir), `.${SKILL_NAME}.old-${process.pid}`)\n fs.rmSync(previousDir, { recursive: true, force: true }) // left behind by a run that was killed\n const hadPrevious = fs.existsSync(skillDir)\n if (hadPrevious) fs.renameSync(skillDir, previousDir)\n try {\n fs.renameSync(preparedDir, skillDir)\n } catch (error) {\n if (hadPrevious) fs.renameSync(previousDir, skillDir)\n throw error\n }\n if (hadPrevious) fs.rmSync(previousDir, { recursive: true, force: true })\n}\n\nexport function installSkill(options: InstallSkillOptions): InstallOutcome {\n const state = readInstallState(options.skillsFolder, options.version)\n if (state.kind === 'installed') return 'up-to-date'\n if (state.kind === 'not-ours' && !options.force) return 'skipped-not-ours'\n\n fs.mkdirSync(options.skillsFolder, { recursive: true })\n const preparedDir = path.join(options.skillsFolder, `.${SKILL_NAME}.tmp-${process.pid}`)\n fs.rmSync(preparedDir, { recursive: true, force: true }) // left behind by a run that was killed\n try {\n copyDirectory(options.sourceDir, preparedDir)\n const marker: SkillMarker = { version: options.version, installedAt: new Date().toISOString() }\n fs.writeFileSync(path.join(preparedDir, MARKER_FILE), JSON.stringify(marker, null, 2))\n swapInto(path.join(options.skillsFolder, SKILL_NAME), preparedDir)\n } finally {\n fs.rmSync(preparedDir, { recursive: true, force: true })\n }\n return state.kind === 'not-installed' ? 'installed' : 'updated'\n}\n\n/** Removes the skill only if Workscribe installed it — a user's own `workscribe` skill is left alone. */\nexport function uninstallSkill(skillsFolder: string): UninstallOutcome {\n const skillDir = path.join(skillsFolder, SKILL_NAME)\n if (!fs.existsSync(skillDir)) return 'not-installed'\n if (!readMarker(skillDir)) return 'skipped-not-ours'\n fs.rmSync(skillDir, { recursive: true, force: true })\n return 'removed'\n}\n","import fs from 'fs'\nimport path from 'path'\nimport { SKILL_NAME } from './agents'\n\nconst SKILL_ENTRY_FILE = 'SKILL.md'\n\n/**\n * Where the skill shipped in this npm package lives. The bundle runs from `dist/`, so it's one level\n * up; the TypeScript sources run from `src/<folder>/`, so it's two. The first with a SKILL.md wins.\n */\nexport function packagedSkillCandidates(fromDirectory: string): string[] {\n return [\n path.join(fromDirectory, '..', 'skills', SKILL_NAME),\n path.join(fromDirectory, '..', '..', 'skills', SKILL_NAME),\n ]\n}\n\nexport function resolvePackagedSkillDir(fromDirectory: string = __dirname): string {\n const found = packagedSkillCandidates(fromDirectory).find((candidate) =>\n fs.existsSync(path.join(candidate, SKILL_ENTRY_FILE))\n )\n if (!found) {\n throw new Error(\n 'The Workscribe skill files are missing from this install. Reinstall it: npm install -g @workscribe/cli'\n )\n }\n return found\n}\n","// Friendly wording for skill install results and status, shared by `workscribe skill`, `init` and `status`.\nimport type { InstallOutcome, SkillInstallState, UninstallOutcome } from './types'\n\nexport type MessageLevel = 'success' | 'info' | 'warn'\n\nexport interface Message {\n level: MessageLevel\n text: string\n}\n\n/** `/Users/dev/.claude/skills` → `~/.claude/skills`, so paths read the way users type them. */\nexport function displayPath(absolutePath: string, homeDir: string): string {\n return absolutePath.startsWith(homeDir) ? `~${absolutePath.slice(homeDir.length)}` : absolutePath\n}\n\nexport function describeInstallOutcome(input: {\n outcome: InstallOutcome\n agents: string\n location: string\n version: string\n}): Message {\n switch (input.outcome) {\n case 'installed':\n return { level: 'success', text: `Installed the Workscribe skill for ${input.agents} (${input.location})` }\n case 'updated':\n return { level: 'success', text: `Updated the Workscribe skill for ${input.agents} to ${input.version}` }\n case 'up-to-date':\n return { level: 'info', text: `The Workscribe skill is already up to date for ${input.agents}` }\n case 'skipped-not-ours':\n return {\n level: 'warn',\n text:\n `Skipped ${input.agents} — ${input.location} already holds a workscribe skill that Workscribe didn't install. ` +\n 'Run workscribe skill install --force to replace it.',\n }\n }\n}\n\nexport function describeUninstallOutcome(input: {\n outcome: UninstallOutcome\n agents: string\n location: string\n}): Message {\n switch (input.outcome) {\n case 'removed':\n return { level: 'success', text: `Removed the Workscribe skill from ${input.agents} (${input.location})` }\n case 'not-installed':\n return { level: 'info', text: `The Workscribe skill isn't installed for ${input.agents}` }\n case 'skipped-not-ours':\n return {\n level: 'warn',\n text: `Left ${input.location} alone — that workscribe skill wasn't installed by Workscribe.`,\n }\n }\n}\n\n/** One status phrase per state, with the command that fixes it when something needs doing. */\nexport function describeSkillStatus(state: SkillInstallState, currentVersion: string): Message {\n switch (state.kind) {\n case 'installed':\n return { level: 'success', text: `installed (${state.version})` }\n case 'outdated':\n return {\n level: 'warn',\n text: `outdated (${state.version}; this CLI is ${currentVersion}) — run workscribe skill install`,\n }\n case 'not-installed':\n return { level: 'info', text: 'not installed — run workscribe skill install' }\n case 'not-ours':\n return {\n level: 'warn',\n text: 'a different workscribe skill is there — run workscribe skill install --force to replace it',\n }\n }\n}\n\n/** The reason from anything thrown — fs errors carry useful text like \"EACCES: permission denied\". */\nexport function reasonOf(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n\nexport function describeInstallFailure(input: { agents: string; location: string; error: unknown }): Message {\n return {\n level: 'warn',\n text:\n `Couldn't install the Workscribe skill for ${input.agents} (${reasonOf(input.error)}). ` +\n `Check you can write to ${input.location}, then run: workscribe skill install`,\n }\n}\n\nexport function describeUninstallFailure(input: { agents: string; location: string; error: unknown }): Message {\n return {\n level: 'warn',\n text:\n `Couldn't remove the Workscribe skill for ${input.agents} (${reasonOf(input.error)}). ` +\n `Delete it yourself: rm -rf ${input.location}`,\n }\n}\n\nexport const AFTER_INSTALL_HINT =\n 'Restart any agent that is already open, then ask it to \"summarize my work today\" (or type /workscribe in Claude Code).'\n","// Install, remove and report the skill one skills folder at a time, with friendly messages. Shared by\n// `workscribe skill`, `init`, `status` and `uninstall`; a failure in one folder is reported, never thrown,\n// so the rest of those commands carries on.\nimport os from 'os'\nimport path from 'path'\nimport chalk from 'chalk'\nimport { log } from '../utils/logger'\nimport { SKILL_AGENTS, SKILL_NAME } from './agents'\nimport { installSkill, readInstallState, uninstallSkill } from './installer'\nimport {\n describeInstallFailure,\n describeInstallOutcome,\n describeSkillStatus,\n describeUninstallFailure,\n describeUninstallOutcome,\n displayPath,\n type Message,\n type MessageLevel,\n} from './report'\nimport { describeFolderAgents, groupBySkillsFolder } from './state'\nimport type { SkillAgent, SkillsFolderGroup } from './types'\n\ndeclare const __WORKSCRIBE_VERSION__: string\n\n/** Width of the agent-name column in `skill status` and `workscribe status`. */\nexport const AGENT_NAME_COLUMN_WIDTH = 16\n\nconst STATUS_COLOURS: Record<MessageLevel, (text: string) => string> = {\n success: chalk.green,\n warn: chalk.yellow,\n info: chalk.dim,\n}\n\n/** Where a group's skill lives, and how messages should name the agents it serves. */\nexport interface FolderTarget {\n skillsFolder: string\n location: string\n agents: string\n}\n\nexport function describeTarget(group: SkillsFolderGroup, homeDir: string = os.homedir()): FolderTarget {\n const skillsFolder = path.join(homeDir, group.skillsFolder)\n return {\n skillsFolder,\n location: displayPath(path.join(skillsFolder, SKILL_NAME), homeDir),\n agents: describeFolderAgents(group, SKILL_AGENTS),\n }\n}\n\nexport function printMessage(message: Message): void {\n log[message.level](message.text)\n}\n\nexport function installIntoFolder(options: { target: FolderTarget; sourceDir: string; force?: boolean }): Message {\n const { target } = options\n try {\n const outcome = installSkill({\n sourceDir: options.sourceDir,\n skillsFolder: target.skillsFolder,\n version: __WORKSCRIBE_VERSION__,\n force: options.force,\n })\n return describeInstallOutcome({ ...target, outcome, version: __WORKSCRIBE_VERSION__ })\n } catch (error) {\n return describeInstallFailure({ ...target, error })\n }\n}\n\n/**\n * Removes Workscribe-installed copies from each agent's skills folder. `workscribe uninstall` passes\n * `reportMissing: false` so folders that never had the skill don't add noise.\n */\nexport function removeSkills(agents: SkillAgent[], options: { reportMissing: boolean }): void {\n for (const group of groupBySkillsFolder(agents)) {\n const target = describeTarget(group)\n try {\n const outcome = uninstallSkill(target.skillsFolder)\n if (outcome === 'not-installed' && !options.reportMissing) continue\n printMessage(describeUninstallOutcome({ ...target, outcome }))\n } catch (error) {\n printMessage(describeUninstallFailure({ ...target, error }))\n }\n }\n}\n\n/** \"Claude Code installed (2.0.0) ~/.claude/skills/workscribe\" */\nexport function formatAgentSkillLine(agent: SkillAgent, homeDir: string = os.homedir()): string {\n const location = displayPath(path.join(homeDir, agent.skillsFolder, SKILL_NAME), homeDir)\n const installState = readInstallState(path.join(homeDir, agent.skillsFolder), __WORKSCRIBE_VERSION__)\n const status = describeSkillStatus(installState, __WORKSCRIBE_VERSION__)\n return `${agent.name.padEnd(AGENT_NAME_COLUMN_WIDTH)} ${STATUS_COLOURS[status.level](status.text)} ${chalk.dim(location)}`\n}\n\nexport function formatUndetectedAgentLine(agent: SkillAgent): string {\n return `${agent.name.padEnd(AGENT_NAME_COLUMN_WIDTH)} ${chalk.dim('not detected')}`\n}\n","// Workscribe 2.0 removed AI providers (cloud and Ollama). These helpers spot 1.x settings so users hear about\n// it once per run, can't set them again by accident, and can have them (and any stored API key) removed.\nimport type { WorkscribeConfig } from '../config'\n\n/** The only `summary.engine` value 2.0 still means — setting it is harmless, so it isn't a leftover. */\nexport const TEMPLATE_ENGINE = 'template'\n\nconst LEGACY_AI_FIELDS = ['provider', 'apiKey', 'model', 'baseUrl'] as const\n\nconst REMOVED_HEADLINE = 'AI providers were removed in Workscribe 2.0 — summaries now use the offline template engine.'\n\nconst SKILL_HINT =\n 'For AI-written summaries, install the Workscribe skill and ask your coding agent:\\n workscribe skill install'\n\n/** Why `config set` refuses `ai.*` and `summary.engine`, and what to do instead. */\nexport const REMOVED_AI_SETTING_MESSAGE = `${REMOVED_HEADLINE}\\n${SKILL_HINT}`\n\nexport function hasLegacyAiSettings(config: WorkscribeConfig): boolean {\n const hasAiField = LEGACY_AI_FIELDS.some((field) => Boolean(config.ai?.[field]))\n const engine = config.summary?.engine\n return hasAiField || (engine !== undefined && engine !== TEMPLATE_ENGINE)\n}\n\n/** The once-per-run notice for a 1.x config, or null when there's nothing left over. `configPath` is shown as-is. */\nexport function describeLegacyAiSettings(config: WorkscribeConfig, configPath: string): string | null {\n if (!hasLegacyAiSettings(config)) return null\n return (\n `${REMOVED_HEADLINE}\\n${SKILL_HINT}\\n` +\n `Your old AI settings (including any API key) are still in ${configPath}. To remove them, run:\\n workscribe init`\n )\n}\n\n/** `ai`, `ai.<anything>`, `summary.engine` and anything under it, in any case — settings `config set` refuses. */\nexport function isRemovedAiSetting(key: string): boolean {\n const normalizedKey = key.toLowerCase()\n return ['ai', 'summary.engine'].some(\n (removed) => normalizedKey === removed || normalizedKey.startsWith(`${removed}.`)\n )\n}\n\n/** A copy of the config without the 1.x AI settings — what `init` saves when the user agrees to remove them. */\nexport function withoutLegacyAiSettings(config: WorkscribeConfig): WorkscribeConfig {\n const cleaned = structuredClone(config)\n delete cleaned.ai\n delete cleaned.summary.engine\n return cleaned\n}\n","import prompts from 'prompts'\nimport { log } from '../utils/logger'\nimport { writeConfig, type WorkscribeConfig } from '../config'\nimport { hasLegacyAiSettings, withoutLegacyAiSettings } from '../summary/legacy-ai'\n\n/** Part of `init`: 2.0 removed AI providers, so offer to delete the 1.x settings — they can include a stored API key. */\nexport async function offerLegacyAiCleanup(config: WorkscribeConfig): Promise<WorkscribeConfig> {\n if (!hasLegacyAiSettings(config)) return config\n log.plain('')\n const { removeLegacyAi } = await prompts({\n type: 'confirm',\n name: 'removeLegacyAi',\n message:\n 'Your config has AI provider settings from Workscribe 1.x (including any API key) that 2.0 no longer uses. Remove them?',\n initial: true,\n })\n if (!removeLegacyAi) {\n log.info('Kept the old AI settings — they are ignored, and workscribe init can remove them later')\n return config\n }\n const cleaned = withoutLegacyAiSettings(config)\n writeConfig(cleaned)\n log.success('Removed the old AI provider settings from your config')\n return cleaned\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, ensureInstallId, WorkscribeConfig } from '../config'\nimport { detectProfilesForDirectory } from '../profiles/loader'\nimport { installProfile, cacheManifest } from '../profiles/fetcher'\nimport { getDb } from '../db'\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'\nimport { detectAgents } from '../skills/detect'\nimport { readInstallState } from '../skills/installer'\nimport { resolvePackagedSkillDir } from '../skills/package-path'\nimport { describeInstallOutcome, reasonOf } from '../skills/report'\nimport { groupBySkillsFolder, outcomeWithoutPrompt } from '../skills/state'\nimport { describeTarget, installIntoFolder, printMessage } from '../skills/actions'\nimport { offerLegacyAiCleanup } from './legacy-ai-cleanup'\nimport type { SkillsFolderGroup } from '../skills/types'\n\ndeclare const __WORKSCRIBE_VERSION__: string\n\ntype Shell = { name: string; rcFile: string }\n\nconst TOTAL_STEPS = 5\n\nfunction detectShell(): Shell | 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\n// ── Step 1: Data directories ──────────────────────────────────────────────\nfunction runDataDirectoriesStep(): void {\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\n// ── Step 2: Database ──────────────────────────────────────────────────────\nasync function initDatabaseAndConfig(): Promise<WorkscribeConfig> {\n step(2, TOTAL_STEPS, 'Initialising database')\n const config = readConfig()\n getDb()\n log.success('Database ready')\n return offerLegacyAiCleanup(config)\n}\n\n// ── Telemetry (part of setup, no separate step) ────────────────────────────\nasync function runTelemetryStep(config: WorkscribeConfig): Promise<void> {\n log.plain('')\n log.plain(chalk.dim(' Workscribe can send anonymous install stats: a random install ID,'))\n log.plain(chalk.dim(' CLI version, OS platform, and Node.js version. No command, event, or'))\n log.plain(chalk.dim(' summary data is ever sent. Opt out anytime:'))\n log.plain(chalk.dim(' workscribe config set telemetry.enabled false'))\n log.plain('')\n const { telemetryEnabled } = await prompts({\n type: 'confirm',\n name: 'telemetryEnabled',\n message: 'Send anonymous install stats?',\n initial: true,\n })\n config.telemetry.enabled = telemetryEnabled\n config.telemetry.installId = ensureInstallId(config)\n}\n\n// ── Step 3: Shell hook + completions ──────────────────────────────────────\nasync function runShellHookStep(program: Command): Promise<Shell | null> {\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 return null\n }\n\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 return shell\n }\n\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 return shell\n}\n\n// ── Step 4: AI tools ──────────────────────────────────────────────────────\nasync function runAIToolsStep(): Promise<void> {\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 return\n }\n\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// ── Step 5: Agent skill ───────────────────────────────────────────────────\nasync function offerSkillInstall(group: SkillsFolderGroup, sourceDir: string): Promise<void> {\n const target = describeTarget(group)\n const state = readInstallState(target.skillsFolder, __WORKSCRIBE_VERSION__)\n const knownOutcome = outcomeWithoutPrompt(state)\n if (knownOutcome) {\n printMessage(describeInstallOutcome({ ...target, outcome: knownOutcome, version: __WORKSCRIBE_VERSION__ }))\n return\n }\n\n const { installSkill: shouldInstall } = await prompts({\n type: 'confirm',\n name: 'installSkill',\n message: `${state.kind === 'outdated' ? 'Update' : 'Install'} the Workscribe skill for ${target.agents}? Lets ${target.agents} summarize your work when you ask`,\n initial: true,\n })\n if (!shouldInstall) {\n log.info(`Skill skipped for ${target.agents} — run workscribe skill install any time`)\n return\n }\n printMessage(installIntoFolder({ target, sourceDir }))\n}\n\nasync function runAgentSkillStep(): Promise<void> {\n step(5, TOTAL_STEPS, 'Installing the Workscribe agent skill')\n\n const agents = detectAgents()\n if (agents.length === 0) {\n log.info('No coding agents detected — run workscribe skill install after installing one')\n return\n }\n\n let sourceDir: string\n try {\n sourceDir = resolvePackagedSkillDir()\n } catch (error) {\n log.warn(reasonOf(error)) // setup can carry on; the skill is optional\n return\n }\n for (const group of groupBySkillsFolder(agents)) {\n await offerSkillInstall(group, sourceDir)\n }\n}\n\n// Profile detection (part of environment scan, no separate step)\nasync function runProfileDetectionStep(config: WorkscribeConfig): Promise<void> {\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\n// ── What to do next ───────────────────────────────────────────────────────\nfunction printNextSteps(shell: Shell | null): void {\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 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(` For AI-written summaries, ask your coding agent to \"summarize my work today\"`)\n log.plain(` ${chalk.dim('(needs the Workscribe skill: workscribe skill install)')}`)\n log.plain('')\n log.plain(` Check capture is working:`)\n log.plain(` ${chalk.cyan('workscribe status')}`)\n\n log.plain('')\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 log.plain(chalk.bold('\\n Workscribe — Developer Work Journal\\n'))\n\n runDataDirectoriesStep()\n const config = await initDatabaseAndConfig()\n await runTelemetryStep(config)\n const shell = await runShellHookStep(program)\n await runAIToolsStep()\n await runAgentSkillStep()\n await runProfileDetectionStep(config)\n\n if (!fs.existsSync(CONFIG_PATH)) {\n writeConfig(config)\n }\n\n printNextSteps(shell)\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/** The local YYYY-MM-DD an ISO timestamp falls on — the same day rule sessions are grouped by. */\nexport function localDateOf(isoString: string): string {\n return localDateStr(new Date(isoString))\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","import os from 'os'\nimport { log } from '../utils/logger'\nimport { CONFIG_PATH } from '../utils/paths'\nimport { describeLegacyAiSettings } from '../summary/legacy-ai'\nimport { displayPath } from '../skills/report'\nimport type { WorkscribeConfig } from '../config'\n\n/** Tells a 1.x user, once per run, that their AI provider settings no longer do anything (stderr, so JSON output stays clean). */\nexport function printLegacyAiNotice(config: WorkscribeConfig): void {\n const notice = describeLegacyAiSettings(config, displayPath(CONFIG_PATH, os.homedir()))\n if (notice) log.notice(notice)\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'\nimport { detectAgents } from '../skills/detect'\nimport { formatAgentSkillLine } from '../skills/actions'\nimport { printLegacyAiNotice } from './notices'\n\n// Labelled on the first agent's row only, like the other status sections\nconst AGENT_SKILL_LABEL = 'Agent skill'\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 printLegacyAiNotice(config)\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 const agents = detectAgents()\n const skillHint = agents.length > 0 ? ' · AI-written ones via the agent skill below' : ''\n log.plain(` Summaries ${chalk.cyan('template')} ${chalk.dim(`(offline)${skillHint}`)}`)\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 agents.forEach((agent, index) => {\n const label = index === 0 ? AGENT_SKILL_LABEL : ''\n log.plain(` ${label.padEnd(AGENT_SKILL_LABEL.length)} ${formatAgentSkillLine(agent)}`)\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 os from 'os'\nimport path from 'path'\nimport { formatDate } from '../utils/format'\nimport type { DaySummaryPayload, EventPayload, SessionPayload } from '../ai/types'\nimport type { EventRow } from '../db/types'\nimport type { Session } from '../sessions/detector'\nimport type { WorkscribeConfig } from '../config'\n\n/** What sessionLocation needs to name a session that isn't in a git repo. */\nexport interface LocationContext {\n projects: Record<string, string>\n homeDir: string\n}\n\nexport function locationContextFrom(config: Pick<WorkscribeConfig, 'projects'>): LocationContext {\n return { projects: config.projects ?? {}, homeDir: os.homedir() }\n}\n\nconst DEFAULT_LOCATION_CONTEXT: LocationContext = { projects: {}, homeDir: os.homedir() }\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\n// Metadata is best-effort context for the summary — a corrupt or non-object row must not fail it\nfunction parseMetadata(raw: string | null): Record<string, unknown> {\n if (!raw) return {}\n try {\n const parsed: unknown = JSON.parse(raw)\n return isPlainObject(parsed) ? parsed : {}\n } catch {\n return {}\n }\n}\n\nexport function eventRowToPayload(row: EventRow): EventPayload {\n const metadata = parseMetadata(row.metadata)\n const payload: EventPayload = {\n category: row.category,\n metadata,\n exitCode: row.exit_code,\n durationMs: row.duration_ms,\n ...(row.source ? { source: row.source } : {}),\n }\n if (row.category !== 'other' || typeof metadata.hint !== 'string') return payload\n\n // Unclassified commands carry their raw hint separately so the prompt can show it on its own\n const { hint, tool: _tool, ...rest } = metadata\n return { ...payload, hint, metadata: rest }\n}\n\nfunction mostFrequentCwdOf(events: EventRow[]): string | null {\n const counts = new Map<string, number>()\n for (const event of events) counts.set(event.cwd, (counts.get(event.cwd) ?? 0) + 1)\n let best: string | null = null\n for (const [cwd, count] of counts) {\n if (best === null || count > (counts.get(best) ?? 0)) best = cwd\n }\n return best\n}\n\n/** The directory most of a session's events ran in, or null for a session with no events. */\nexport function mostFrequentCwd(session: Session): string | null {\n return mostFrequentCwdOf(session.events)\n}\n\n/**\n * A directory inside the session's repo, for git lookups. Agents often run `cd repo && …` from a\n * parent directory that isn't a repo, so the most-used directory overall can miss the repo entirely.\n */\nexport function repoCwd(session: Session): string | null {\n if (!session.repoName) return mostFrequentCwd(session)\n return mostFrequentCwdOf(session.events.filter((event) => event.repo_name === session.repoName))\n}\n\nfunction homeRelative(directory: string, homeDir: string): string {\n if (directory === homeDir) return '~'\n if (directory.startsWith(homeDir + path.sep)) return `~${directory.slice(homeDir.length)}`\n return directory\n}\n\n/**\n * The name a session is shown under: its repo, or — for work outside any git repo — the directory\n * most of its commands ran in (a config.projects name if one is set, else the home-relative path),\n * so the user can always tell where the work happened.\n */\nexport function sessionLocation(session: Session, context: LocationContext = DEFAULT_LOCATION_CONTEXT): string | null {\n if (session.repoName) return session.repoName\n const cwd = mostFrequentCwd(session)\n if (!cwd) return null\n return context.projects[cwd] ?? homeRelative(cwd, context.homeDir)\n}\n\nexport function sessionToPayload(\n session: Session,\n date: string,\n context: LocationContext = DEFAULT_LOCATION_CONTEXT\n): SessionPayload {\n return {\n date,\n project: sessionLocation(session, context),\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\nexport function buildDayPayload(\n date: string,\n sessions: Session[],\n context: LocationContext = DEFAULT_LOCATION_CONTEXT\n): DaySummaryPayload {\n return { date, sessions: sessions.map((session) => sessionToPayload(session, date, context)) }\n}\n","import type { StoredEngine } from '../ai/engine'\nimport type { SessionSummaryRow } from '../db/types'\n\n/** Engine name for summaries migrated from the 1.x `sessions.summary` column (written by a provider or Ollama). */\nexport const LEGACY_ENGINE = 'legacy' satisfies StoredEngine\n\n/** Engine name for summaries the Workscribe agent skill saved with `sessions summary set`. */\nexport const SKILL_ENGINE = 'skill' satisfies StoredEngine\n\n// Higher wins when picking what to show: richer sources first. Template rows rank 0 — templates are\n// rendered live, so any stored copy is a stale leftover and must never beat a fresh render.\nconst ENGINE_RANK: Record<StoredEngine, number> = { skill: 3, ollama: 2, provider: 2, legacy: 2, template: 0 }\n\n/** Summaries a 1.x AI provider or Ollama wrote. 2.0 no longer writes these, but still shows them for their sessions. */\nconst LEGACY_AI_ENGINES = new Set<string>(['provider', 'ollama', LEGACY_ENGINE])\n\n/** Identifies a session across rebuilds. Must match SESSION_KEY_SQL in migration 005. */\nexport function sessionKey(repoName: string | null, startedAt: string): string {\n return `${repoName ?? ''}|${startedAt}`\n}\n\nexport interface ParsedSessionKey {\n repoName: string | null\n startedAt: string\n}\n\n/** Reverses sessionKey(). Null for a malformed key: no `|`, or a start that isn't a timestamp. */\nexport function parseSessionKey(key: string): ParsedSessionKey | null {\n const separator = key.lastIndexOf('|')\n if (separator === -1) return null\n const startedAt = key.slice(separator + 1)\n if (startedAt === '' || Number.isNaN(new Date(startedAt).getTime())) return null\n const repoName = key.slice(0, separator)\n return { repoName: repoName === '' ? null : repoName, startedAt }\n}\n\nfunction newestFirst(first: SessionSummaryRow, second: SessionSummaryRow): number {\n return second.created_at.localeCompare(first.created_at)\n}\n\nexport interface SavedSummary {\n text: string\n fromSkill: boolean\n}\n\n/**\n * What `workscribe summary` can show for a session instead of rendering the template: a summary the agent\n * skill saved wins (it was written with more context), else one a 1.x AI provider wrote for that session.\n */\nexport function pickSavedSummary(rows: SessionSummaryRow[]): SavedSummary | null {\n const [newestSkill] = rows.filter((row) => row.engine === SKILL_ENGINE).sort(newestFirst)\n if (newestSkill) return { text: newestSkill.text, fromSkill: true }\n const [newestLegacy] = rows.filter((row) => LEGACY_AI_ENGINES.has(row.engine)).sort(newestFirst)\n return newestLegacy ? { text: newestLegacy.text, fromSkill: false } : null\n}\n\n/** The best stored summary for a session regardless of the configured engine (used by `context`). */\nexport function pickBestSummary(rows: SessionSummaryRow[]): string | null {\n // Rows come from the DB, so an engine name this build doesn't know is ignored like a template row\n const rank = (row: SessionSummaryRow): number => ENGINE_RANK[row.engine as StoredEngine] ?? 0\n const [best] = rows\n .filter((row) => rank(row) > 0)\n .sort((first, second) => rank(second) - rank(first) || newestFirst(first, second))\n return best?.text ?? null\n}\n","/**\n * Version of the `--json` contract read by coding agents and other tools. Fields may be added within a\n * version; renaming, removing or retyping a field bumps it. Tests pin the key sets.\n */\nexport const SCHEMA_VERSION = 1\n","import { eventRowToPayload } from '../payload'\nimport { buildExcludedSet } from '../exclusions'\nimport type { EventRow } from '../../db/types'\nimport type { GitCommit } from '../git-commits'\nimport type { CommitJson } from './types'\n\n/** Events the contract reports: the AI engines' exclusions apply, and notes go to `notes` instead. */\nexport function contractEvents(rows: EventRow[], includeCategories: string[]): EventRow[] {\n const excluded = buildExcludedSet(includeCategories)\n return rows.filter((row) => row.category !== 'note' && !excluded.has(row.category))\n}\n\nexport function collectNotes(rows: EventRow[]): string[] {\n return rows.flatMap((row) => {\n if (row.category !== 'note') return []\n const { text } = eventRowToPayload(row).metadata\n return typeof text === 'string' && text !== '' ? [text] : []\n })\n}\n\nfunction isFailedCommand(row: EventRow): boolean {\n return row.exit_code !== null && row.exit_code !== 0\n}\n\n/**\n * Commit subjects Workscribe captured itself: `git commit -m` messages and AI-session commits.\n * A `git commit` that failed (rejected by a hook, nothing staged) made no commit, so it is skipped.\n */\nexport function collectCapturedCommits(rows: EventRow[]): string[] {\n const subjects = rows.flatMap((row) => {\n const { metadata } = eventRowToPayload(row)\n if (row.category === 'shipping' && typeof metadata.message === 'string' && !isFailedCommand(row)) {\n return [metadata.message]\n }\n if (row.category === 'ai_session' && Array.isArray(metadata.commits)) {\n return metadata.commits.filter((subject): subject is string => typeof subject === 'string')\n }\n return []\n })\n return [...new Set(subjects.filter((subject) => subject !== ''))]\n}\n\n/**\n * Whether a captured subject is this git commit. Besides an exact match, it tolerates the two ways\n * events captured before the `-m` parsing fix were cut wrong — and only those, so a short `fix`\n * never matches `fix: something else`:\n * - stopped at an inner quote: `fix: don` for `fix: don't redirect`\n * - ran on into flags: `wip --no-verify` for `wip`\n */\nexport function isSameCommit(captured: string, gitSubject: string): boolean {\n if (captured === gitSubject) return true\n if (gitSubject.startsWith(captured)) return /^['\"]/.test(gitSubject.slice(captured.length))\n if (captured.startsWith(gitSubject)) return /^\\s+-/.test(captured.slice(gitSubject.length))\n return false\n}\n\n/**\n * Git commits first, oldest first and each listed even if subjects repeat (they are distinct commits),\n * then captured subjects git didn't return — amended, rebased or on another branch — with no hash.\n * Captured subjects git attributes only to other people are dropped: an AI session records every\n * commit that reached HEAD, including ones pulled or rebased in.\n */\nexport function mergeCommits(captured: string[], fromGit: GitCommit[], othersSubjects: string[] = []): CommitJson[] {\n const others = new Set(othersSubjects)\n const gitCommits: CommitJson[] = fromGit.map((commit) => ({ ...commit, source: 'git' }))\n const capturedOnly: CommitJson[] = captured\n .filter((subject) => !others.has(subject))\n .filter((subject) => !fromGit.some((commit) => isSameCommit(subject, commit.subject)))\n .map((subject) => ({ hash: null, subject, source: 'captured' }))\n return [...gitCommits, ...capturedOnly]\n}\n","import { eventRowToPayload, mostFrequentCwd, sessionLocation } from '../payload'\nimport { sessionKey } from '../store'\nimport { SCHEMA_VERSION } from './constants'\nimport { collectCapturedCommits, collectNotes, contractEvents, mergeCommits } from './utils'\nimport type { EventRow } from '../../db/types'\nimport type { Session } from '../../sessions/detector'\nimport type { EventJson, EventsJson, EventsJsonOptions, SessionJson, SessionJsonOptions, SessionsJson } from './types'\n\n/** Never includes the full command, the event's cwd or an IDE file path. */\nexport function eventToJson(row: EventRow): EventJson {\n const { category, metadata, hint, exitCode, durationMs } = eventRowToPayload(row)\n return {\n capturedAt: row.captured_at,\n category,\n metadata,\n ...(hint === undefined ? {} : { hint }),\n exitCode,\n durationMs,\n source: row.source,\n }\n}\n\nexport function sessionToJson(session: Session, { location, git, includeCategories }: SessionJsonOptions): SessionJson {\n return {\n key: sessionKey(session.repoName, session.startedAt),\n project: sessionLocation(session, location),\n repoName: session.repoName,\n repoPath: git.repoPath,\n cwd: mostFrequentCwd(session),\n branch: session.events[0]?.branch ?? null,\n startedAt: session.startedAt,\n endedAt: session.endedAt,\n durationMinutes: session.durationMinutes,\n eventCount: session.eventCount,\n notes: collectNotes(session.events),\n commits: mergeCommits(collectCapturedCommits(session.events), git.commits, git.othersSubjects),\n events: contractEvents(session.events, includeCategories).map(eventToJson),\n }\n}\n\nexport function buildSessionsJson(date: string, sessions: SessionJson[]): SessionsJson {\n return { schemaVersion: SCHEMA_VERSION, date, sessions }\n}\n\nexport function buildEventsJson(\n date: string,\n rows: EventRow[],\n { limit, includeCategories }: EventsJsonOptions\n): EventsJson {\n const events = contractEvents(rows, includeCategories)\n return { schemaVersion: SCHEMA_VERSION, date, total: events.length, events: events.slice(0, limit).map(eventToJson) }\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'\nimport { readConfig } from '../config'\nimport { buildEventsJson } from '../summary/contract/build'\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\nfunction isPositiveWholeNumber(value: number): boolean {\n return Number.isInteger(value) && value > 0\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 .option('--json', 'output the versioned JSON contract (structured events, no raw commands)')\n .action((options) => {\n let date = todayDate()\n if (options.date) {\n try {\n date = parseDate(options.date)\n } catch (error) {\n log.error((error as Error).message)\n process.exit(1)\n }\n }\n\n const events = getEventsForDate(date)\n\n if (options.json) {\n // Scripts call the JSON contract, so a bad --limit is an error rather than a silently odd list\n if (options.limit !== undefined && !isPositiveWholeNumber(options.limit)) {\n log.error('--limit must be a positive whole number')\n process.exit(1)\n }\n const includeCategories = readConfig().summary?.includeCategories ?? []\n log.plain(JSON.stringify(buildEventsJson(date, events, { limit: options.limit, includeCategories })))\n return\n }\n\n const limit = options.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","// Rules and messages for `workscribe sessions summary set` — pure; the command does the I/O.\n\nconst BYTES_PER_KB = 1024\nconst MAX_SKILL_SUMMARY_KB = 8\n\n/** Largest summary the agent skill may save for one session, in bytes. */\nexport const MAX_SKILL_SUMMARY_BYTES = MAX_SKILL_SUMMARY_KB * BYTES_PER_KB\n\n// Shown whenever no summary text arrives, so the fix is a copy-paste away\nconst SEND_TEXT_EXAMPLE = [\n 'Send the summary text into the command, for example:',\n '',\n \" workscribe sessions summary set --key '<key from workscribe sessions --json>' <<'EOF'\",\n ' ## my-project (main) — 1h 30m',\n ' - What you got done',\n ' EOF',\n].join('\\n')\n\nexport const INTERACTIVE_STDIN_MESSAGE = `This command saves summary text that is sent to it — it can't be typed in here.\\n${SEND_TEXT_EXAMPLE}`\n\nexport function stdinReadFailedMessage(error: unknown): string {\n return `Couldn't read the summary text that was sent in: ${(error as Error).message}`\n}\n\n/** `16384` → `16,384` — thousands separators only, no unit scaling. */\nfunction formatCount(count: number): string {\n return count.toLocaleString('en-US')\n}\n\n/** A friendly error for a summary that can't be saved, or null when it's fine. */\nexport function validateSkillSummary(text: string): string | null {\n if (text.trim() === '') return `Nothing to save — no summary text was received.\\n${SEND_TEXT_EXAMPLE}`\n const bytes = Buffer.byteLength(text, 'utf-8')\n if (bytes > MAX_SKILL_SUMMARY_BYTES) {\n return (\n `This summary is too long to save (${formatCount(bytes)} bytes; the limit is ` +\n `${formatCount(MAX_SKILL_SUMMARY_BYTES)}, about ${MAX_SKILL_SUMMARY_KB} KB). Shorten it and try again.`\n )\n }\n return null\n}\n","import fs from 'fs'\n\nconst STDIN_FILE_DESCRIPTOR = 0\n\n/** True when stdin is a terminal — reading it would wait for typing rather than piped input. */\nexport function isStdinInteractive(): boolean {\n return Boolean(process.stdin.isTTY)\n}\n\n/** Everything piped into the process. Throws if stdin can't be read. */\nexport function readAllStdin(): string {\n return fs.readFileSync(STDIN_FILE_DESCRIPTOR, 'utf-8')\n}\n","import { Command } from 'commander'\nimport { getOrBuildSessions } from '../sessions/detector'\nimport { saveSessionSummary } from '../db'\nimport { readConfig } from '../config'\nimport { redact } from '../capture/redact'\nimport { log } from '../utils/logger'\nimport { localDateOf } from '../utils/format'\nimport { SKILL_ENGINE, parseSessionKey, sessionKey } from '../summary/store'\nimport { INTERACTIVE_STDIN_MESSAGE, stdinReadFailedMessage, validateSkillSummary } from '../summary/write-back'\nimport { isStdinInteractive, readAllStdin } from '../utils/stdin'\nimport type { Session } from '../sessions/detector'\n\n// `workscribe sessions summary set` — how the Workscribe agent skill saves the summary it wrote.\n\nfunction fail(message: string): never {\n log.error(message)\n process.exit(1)\n}\n\n/** The session a key from `sessions --json` names, after rebuilding its day so the lookup is current. */\nfunction findSessionByKey(key: string): Session | null {\n const parsed = parseSessionKey(key)\n if (!parsed) return null\n return (\n getOrBuildSessions(localDateOf(parsed.startedAt)).find(\n (session) => sessionKey(session.repoName, session.startedAt) === key\n ) ?? null\n )\n}\n\n/** The summary text piped in, failing with a friendly message for a terminal or a read error. */\nfunction readSummaryText(): string {\n if (isStdinInteractive()) fail(INTERACTIVE_STDIN_MESSAGE)\n try {\n return readAllStdin()\n } catch (error) {\n fail(stdinReadFailedMessage(error))\n }\n}\n\nfunction saveSkillSummary(options: { key: string }): void {\n if (!parseSessionKey(options.key)) {\n fail(`That session key isn't valid: '${options.key}'. Copy a session's \"key\" from workscribe sessions --json.`)\n }\n\n const summaryText = readSummaryText()\n const problem = validateSkillSummary(summaryText)\n if (problem) fail(problem)\n\n const session = findSessionByKey(options.key)\n if (!session) {\n fail(\n 'No session matches this key — your activity may have changed since the sessions were listed. ' +\n 'Run workscribe sessions --json again and use the new key.'\n )\n }\n\n const text = redact(summaryText.trim(), readConfig().redact.extra)\n saveSessionSummary(options.key, SKILL_ENGINE, text)\n log.success(\n `Saved the summary for ${session.repoName ?? 'this session'} — workscribe summary, workscribe context and the VS Code status bar now show it.`\n )\n}\n\nexport function registerSummarySet(sessionsCommand: Command): void {\n sessionsCommand\n .command('summary')\n .description('Manage the summaries stored for sessions')\n .command('set')\n .description('Save a summary written by the Workscribe agent skill; the text is read from stdin')\n .requiredOption('--key <key>', 'the session key, from workscribe sessions --json')\n .action(saveSkillSummary)\n}\n","import { execFileSync } from 'child_process'\n\nconst GIT_TIMEOUT_MS = 3000\n// Commands are captured when they finish, so a `git commit` that opens a session is stamped after\n// its committer time — by however long the commit hooks ran. A commit closing a session can land\n// just after its event.\nconst WINDOW_LEAD_MS = 120_000\nconst WINDOW_TRAIL_MS = 60_000\n// How far back to look when checking who made a captured commit (pulled commits can be old)\nconst AUTHORSHIP_HISTORY_DEPTH = 500\n\nexport interface GitCommit {\n hash: string\n subject: string\n}\n\ninterface CommitWindow {\n repoRoot: string\n since: string\n until: string\n /** Only commits committed by this email (case-insensitive); all commits when null. */\n author: string | null\n}\n\n/** Runs git without a shell. Returns trimmed stdout, or null on any failure (no git, not a repo, timeout). */\nfunction runGit(cwd: string, args: string[]): string | null {\n try {\n return execFileSync('git', args, { cwd, timeout: GIT_TIMEOUT_MS, stdio: ['ignore', 'pipe', 'ignore'] })\n .toString()\n .trim()\n } catch {\n return null\n }\n}\n\nexport function getRepoRoot(cwd: string): string | null {\n return runGit(cwd, ['rev-parse', '--show-toplevel']) || null\n}\n\nexport function getUserEmail(repoRoot: string): string | null {\n return runGit(repoRoot, ['config', 'user.email']) || null\n}\n\n/**\n * Subjects in the last AUTHORSHIP_HISTORY_DEPTH commits on HEAD that only other people committed.\n * Empty without an author to compare against, or when git fails.\n */\nexport function getOthersSubjects(repoRoot: string, author: string | null): string[] {\n if (!author) return []\n const output = runGit(repoRoot, ['log', `-n${AUTHORSHIP_HISTORY_DEPTH}`, '--format=%ce%x09%s'])\n if (!output) return []\n\n const wantedAuthor = author.toLowerCase()\n const mine = new Set<string>()\n const theirs = new Set<string>()\n for (const line of output.split('\\n')) {\n const [email, ...subjectParts] = line.split('\\t')\n const subject = subjectParts.join('\\t')\n if (!subject) continue\n if (email?.toLowerCase() === wantedAuthor) mine.add(subject)\n else theirs.add(subject)\n }\n return [...theirs].filter((subject) => !mine.has(subject))\n}\n\n/**\n * Commits made during a session, oldest first. Window and author both use the *committer* (who made\n * the commit then — including cherry-picks of someone else's work) and only commits reachable from\n * HEAD are seen. `--since` also stops at the first commit older than the window, so after a rebase\n * that leaves dates out of order a few in-window commits can be missed. Captured commit messages\n * cover what this misses.\n */\nexport function getCommitsInWindow({ repoRoot, since, until, author }: CommitWindow): GitCommit[] {\n const shiftedBy = (iso: string, milliseconds: number): string =>\n new Date(new Date(iso).getTime() + milliseconds).toISOString()\n const output = runGit(repoRoot, [\n 'log',\n `--since=${shiftedBy(since, -WINDOW_LEAD_MS)}`,\n `--until=${shiftedBy(until, WINDOW_TRAIL_MS)}`,\n '--format=%h%x09%ce%x09%s',\n '--reverse',\n ])\n if (!output) return []\n\n const wantedAuthor = author?.toLowerCase() ?? null\n return output.split('\\n').flatMap((line) => {\n const [hash, email, ...subjectParts] = line.split('\\t')\n const subject = subjectParts.join('\\t')\n if (!hash || !subject) return []\n if (wantedAuthor && email?.toLowerCase() !== wantedAuthor) return []\n return [{ hash, subject }]\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'\nimport { registerSummarySet } from './session-summary'\nimport { readConfig } from '../config'\nimport { locationContextFrom, repoCwd } from '../summary/payload'\nimport { buildSessionsJson, sessionToJson } from '../summary/contract/build'\nimport { getCommitsInWindow, getOthersSubjects, getRepoRoot, getUserEmail } from '../summary/git-commits'\nimport { memoize } from '../utils/memoize'\nimport type { Session } from '../sessions/detector'\nimport type { SessionGitInfo } from '../summary/contract/types'\n\n/**\n * Looks up git facts for the session's repo — empty outside a git repo or when git fails.\n * Repo roots and emails are cached for the run so a day of sessions in one repo asks git once.\n */\nfunction createSessionGitLookup(): (session: Session) => SessionGitInfo {\n const repoRootOf = memoize(getRepoRoot)\n const emailOf = memoize(getUserEmail)\n const othersSubjectsOf = memoize((repoPath) => getOthersSubjects(repoPath, emailOf(repoPath)))\n return (session) => {\n const cwd = repoCwd(session)\n const repoPath = cwd ? repoRootOf(cwd) : null\n if (!repoPath) return { repoPath: null, commits: [], othersSubjects: [] }\n const author = emailOf(repoPath)\n const commits = getCommitsInWindow({ repoRoot: repoPath, since: session.startedAt, until: session.endedAt, author })\n return { repoPath, commits, othersSubjects: othersSubjectsOf(repoPath) }\n }\n}\n\nfunction printSessionsJson(date: string, sessions: Session[]): void {\n const config = readConfig()\n const options = {\n location: locationContextFrom(config),\n includeCategories: config.summary?.includeCategories ?? [],\n }\n const lookupGit = createSessionGitLookup()\n const sessionJsons = sessions.map((session) => sessionToJson(session, { ...options, git: lookupGit(session) }))\n log.plain(JSON.stringify(buildSessionsJson(date, sessionJsons)))\n}\n\nexport function registerSessions(program: Command): void {\n const sessionsCommand = program\n .command('sessions')\n .description('List detected work sessions')\n .option('--date <YYYY-MM-DD>', 'date to show sessions for (default: today)')\n .option('--json', 'output the versioned JSON contract (sessions with events, notes and commits)')\n .action((options) => {\n let date = todayDate()\n if (options.date) {\n try {\n date = parseDate(options.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 (options.json) {\n printSessionsJson(date, sessions)\n return\n }\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 registerSummarySet(sessionsCommand)\n}\n","import { formatDuration } from '../utils/format'\nimport type { SessionPayload } from '../ai/types'\n\n/** Shown when a session has neither a repo nor any events to name it by. */\nexport const UNKNOWN_LOCATION = 'unknown'\n\ntype HeadingFields = Pick<SessionPayload, 'project' | 'branch' | 'durationMinutes'>\n\n/** `project (branch) — duration`, as used in headings and the --verbose event listing. */\nexport function formatSessionLabel(session: HeadingFields): string {\n const branch = session.branch ? ` (${session.branch})` : ''\n return `${session.project ?? UNKNOWN_LOCATION}${branch} — ${formatDuration(session.durationMinutes)}`\n}\n\n/** The `## project (branch) — duration` line every session summary starts with. */\nexport function formatSessionHeading(session: HeadingFields): string {\n return `## ${formatSessionLabel(session)}`\n}\n","import type { OutcomeWording } from './types'\n\nexport const MAX_SESSION_BULLETS = 7\nexport const MAX_COMMIT_BULLETS = 3\nexport const MAX_DAY_BULLETS = 5\nexport const MAX_LISTED_PACKAGES = 6\n\n// Event sources that mean a coding agent ran the command (its hook captured it). Summaries count these,\n// but never name the tool.\nexport const AGENT_SOURCES = ['claude-code']\n\nexport const TEST_WORDING: OutcomeWording = {\n category: 'testing',\n resolved: 'Resolved failing tests',\n passing: 'Tests passing',\n failing: 'Tests still failing',\n ran: 'Ran tests',\n}\n\nexport const BUILD_WORDING: OutcomeWording = {\n category: 'building',\n resolved: 'Fixed a failing build',\n passing: 'Builds passing',\n failing: 'Build still failing',\n ran: 'Ran builds',\n}\n","import type { EventPayload } from '../../types'\n\nexport function pluralize(count: number, noun: string): string {\n return `${count} ${noun}${count === 1 ? '' : 's'}`\n}\n\n/** The non-empty strings in a metadata value — event metadata is untyped JSON. */\nexport function stringsIn(value: unknown): string[] {\n return Array.isArray(value) ? value.filter((item): item is string => typeof item === 'string' && item !== '') : []\n}\n\nexport function unique(values: string[]): string[] {\n return [...new Set(values)]\n}\n\nexport function eventsOf(events: EventPayload[], category: string): EventPayload[] {\n return events.filter((event) => event.category === category)\n}\n\nexport function toBulletList(bullets: string[]): string {\n return bullets.map((bullet) => `- ${bullet}`).join('\\n')\n}\n","import { buildExcludedSet } from '../../../summary/exclusions'\nimport {\n AGENT_SOURCES,\n BUILD_WORDING,\n MAX_COMMIT_BULLETS,\n MAX_LISTED_PACKAGES,\n MAX_SESSION_BULLETS,\n TEST_WORDING,\n} from './constants'\nimport { eventsOf, pluralize, stringsIn, unique } from './utils'\nimport type { EventPayload, SessionPayload } from '../../types'\nimport type { OutcomeWording } from './types'\n\nfunction describeNotes(events: EventPayload[]): string[] {\n return eventsOf(events, 'note').flatMap((event) => stringsIn([event.metadata.text]).map((text) => `Note: ${text}`))\n}\n\n/** Commit messages from `git commit -m` and from AI sessions, in order, without repeats. */\nexport function collectCommits(events: EventPayload[]): string[] {\n return unique(\n events.flatMap((event) => {\n if (event.category === 'shipping') return stringsIn([event.metadata.message])\n if (event.category === 'ai_session') return stringsIn(event.metadata.commits)\n return []\n })\n )\n}\n\nfunction describeCommits(commits: string[]): string[] {\n const bullets = commits.slice(0, MAX_COMMIT_BULLETS).map((message) => `Committed: ${message}`)\n const hiddenCount = commits.length - MAX_COMMIT_BULLETS\n if (hiddenCount > 0) bullets[MAX_COMMIT_BULLETS - 1] += `, plus ${pluralize(hiddenCount, 'more change')}`\n return bullets\n}\n\n/**\n * Pass/fail story for test or build runs. Commands captured through AI-tool hooks have no exit\n * code, so they count towards the run total but never decide the outcome.\n */\nexport function describeOutcome(events: EventPayload[], wording: OutcomeWording): string | null {\n const runs = eventsOf(events, wording.category)\n if (runs.length === 0) return null\n\n const runCount = pluralize(runs.length, 'run')\n const knownExitCodes = runs.map((run) => run.exitCode).filter((exitCode): exitCode is number => exitCode !== null)\n if (knownExitCodes.length === 0) return `${wording.ran} (${runCount})`\n if (knownExitCodes[knownExitCodes.length - 1] !== 0) return `${wording.failing} (${runCount})`\n if (knownExitCodes.some((exitCode) => exitCode !== 0)) return `${wording.resolved} (${runCount}, now passing)`\n return `${wording.passing} (${runCount})`\n}\n\nfunction listPackages(packages: string[]): string {\n const listed = packages.slice(0, MAX_LISTED_PACKAGES).join(', ')\n const hiddenCount = packages.length - MAX_LISTED_PACKAGES\n return `${listed}${hiddenCount > 0 ? `, plus ${hiddenCount} more` : ''}`\n}\n\n/** Removals (`npm uninstall`, `yarn remove`, …) carry action: 'remove' and are worded separately from additions. */\nfunction describeDependencies(events: EventPayload[]): string[] {\n const runs = eventsOf(events, 'dependencies')\n if (runs.length === 0) return []\n const isRemoval = (event: EventPayload): boolean => event.metadata.action === 'remove'\n const added = unique(runs.filter((event) => !isRemoval(event)).flatMap((event) => stringsIn(event.metadata.packages)))\n const removed = unique(runs.filter(isRemoval).flatMap((event) => stringsIn(event.metadata.packages)))\n if (added.length === 0 && removed.length === 0) return [`Installed dependencies (${pluralize(runs.length, 'run')})`]\n\n return [\n ...(added.length > 0 ? [`Added dependencies: ${listPackages(added)}`] : []),\n ...(removed.length > 0 ? [`Removed dependencies: ${listPackages(removed)}`] : []),\n ]\n}\n\nfunction describeReleases(events: EventPayload[]): string | null {\n const releases = eventsOf(events, 'releasing')\n if (releases.length === 0) return null\n const tools = unique(releases.flatMap((event) => stringsIn([event.metadata.tool])))\n return tools.length > 0 ? `Released / deployed (${tools.join(', ')})` : 'Released / deployed'\n}\n\nfunction describePushes(events: EventPayload[]): string | null {\n const targets = unique(\n eventsOf(events, 'shipping').flatMap((event) => {\n const [remote] = stringsIn([event.metadata.remote])\n if (!remote) return []\n const [branch] = stringsIn([event.metadata.branch])\n return [branch ? `${remote}/${branch}` : remote]\n })\n )\n return targets.length > 0 ? `Pushed to ${targets.join(', ')}` : null\n}\n\n/** Commands a coding agent ran in the session — counted from all of them, including ones the summary leaves out. */\nfunction describeAgentWork(events: EventPayload[]): string | null {\n const agentCommands = events.filter((event) => event.source !== undefined && AGENT_SOURCES.includes(event.source))\n return agentCommands.length > 0\n ? `Worked with an AI coding assistant (${pluralize(agentCommands.length, 'command')})`\n : null\n}\n\nfunction describeEdits(events: EventPayload[]): string | null {\n const saves = eventsOf(events, 'code_edit').length\n return saves > 0 ? `Edited files in the IDE (${pluralize(saves, 'save')})` : null\n}\n\n/** Notes are always kept; everything else follows the same exclusions as the AI payload. */\nfunction includedEvents(events: EventPayload[], includeCategories: string[]): EventPayload[] {\n const excluded = buildExcludedSet(includeCategories)\n return events.filter((event) => event.category === 'note' || !excluded.has(event.category))\n}\n\n/** Outcome bullets for one session, most important first, capped at MAX_SESSION_BULLETS. Empty if nothing notable happened. */\nexport function describeActivity(session: SessionPayload, includeCategories: string[] = []): string[] {\n const events = includedEvents(session.events, includeCategories)\n return [\n ...describeNotes(events),\n ...describeCommits(collectCommits(events)),\n describeOutcome(events, TEST_WORDING),\n describeOutcome(events, BUILD_WORDING),\n ...describeDependencies(events),\n describeReleases(events),\n describePushes(events),\n describeAgentWork(session.events),\n describeEdits(events),\n ]\n .filter((bullet): bullet is string => bullet !== null)\n .slice(0, MAX_SESSION_BULLETS)\n}\n\nexport function countIncludedEvents(session: SessionPayload, includeCategories: string[] = []): number {\n return includedEvents(session.events, includeCategories).length\n}\n\n/** Outcome bullets for one session, or a line saying where the work happened when nothing stands out. */\nexport function describeSession(session: SessionPayload, includeCategories: string[] = []): string[] {\n const bullets = describeActivity(session, includeCategories)\n if (bullets.length > 0) return bullets\n const commandCount = pluralize(countIncludedEvents(session, includeCategories), 'command')\n return [`Worked in ${session.project ?? 'an unknown location'} (${commandCount})`]\n}\n","import { formatSessionHeading, UNKNOWN_LOCATION } from '../../../summary/heading'\nimport { MAX_DAY_BULLETS } from './constants'\nimport { countIncludedEvents, describeActivity, describeSession } from './describe'\nimport { pluralize, toBulletList } from './utils'\nimport type { AIProvider, DaySummaryPayload, SessionPayload, WeekSummaryPayload } from '../../types'\n\n/** One entry per location for the day — several sessions in the same repo read as one block of work. */\nfunction mergeByLocation(sessions: SessionPayload[]): SessionPayload[] {\n const merged = new Map<string, SessionPayload>()\n for (const session of sessions) {\n const location = session.project ?? UNKNOWN_LOCATION\n const existing = merged.get(location)\n merged.set(\n location,\n existing\n ? {\n ...existing,\n events: [...existing.events, ...session.events],\n durationMinutes: existing.durationMinutes + session.durationMinutes,\n }\n : { ...session, project: location }\n )\n }\n return [...merged.values()]\n}\n\nfunction locationBullets(session: SessionPayload, includeCategories: string[]): string[] {\n const bullets = describeActivity(session, includeCategories)\n const lines = bullets.length > 0 ? bullets : [pluralize(countIncludedEvents(session, includeCategories), 'command')]\n return lines.map((line) => `${session.project}: ${line}`)\n}\n\n/** Takes the top bullet of every location, then the second, and so on — so one busy repo can't fill the day. */\nfunction pickDayBullets(sessions: SessionPayload[], includeCategories: string[]): string[] {\n const perLocation = mergeByLocation(sessions).map((session) => locationBullets(session, includeCategories))\n const longest = Math.max(0, ...perLocation.map((bullets) => bullets.length))\n const interleaved = Array.from({ length: longest }, (_unused, index) =>\n perLocation.flatMap((bullets) => (index < bullets.length ? [bullets[index]] : []))\n ).flat()\n return interleaved.slice(0, MAX_DAY_BULLETS)\n}\n\n/** Offline, deterministic summaries built from captured events — the default when no AI is configured. */\nexport class TemplateProvider implements AIProvider {\n constructor(private includeCategories: string[] = []) {}\n\n async summarize(payload: DaySummaryPayload): Promise<string> {\n const [onlySession, ...otherSessions] = payload.sessions\n if (onlySession && otherSessions.length === 0) {\n return toBulletList(describeSession(onlySession, this.includeCategories))\n }\n // `export` summarizes a whole day at once, so each session gets its own heading\n return payload.sessions\n .map(\n (session) =>\n `${formatSessionHeading(session)}\\n${toBulletList(describeSession(session, this.includeCategories))}`\n )\n .join('\\n\\n')\n }\n\n async summarizeWeek(payload: WeekSummaryPayload): Promise<string> {\n return payload.days\n .map((day) => `### ${day.date}\\n${toBulletList(pickDayBullets(day.sessions, this.includeCategories))}`)\n .join('\\n\\n')\n }\n\n async validate(): Promise<void> {\n // Nothing to reach — the template engine runs entirely offline\n }\n}\n","import { TemplateProvider } from '../ai/engines/template/provider'\nimport type { AIProvider } from '../ai/types'\nimport type { WorkscribeConfig } from '../config'\n\n/** What writes summaries since 2.0: the offline template engine, honouring summary.includeCategories. */\nexport function createSummaryWriter(config: WorkscribeConfig): AIProvider {\n return new TemplateProvider(config.summary?.includeCategories ?? [])\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 os from 'os'\nimport { log } from '../utils/logger'\nimport { postToWebhook } from '../integrations/webhook'\nimport { formatForSlack, isSlackWebhookUrl } from '../integrations/slack'\nimport type { WorkscribeConfig } from '../config'\n\nexport interface WebhookOptions {\n slack?: boolean\n webhook?: string\n}\n\ninterface PostSummaryInput {\n options: WebhookOptions\n config: WorkscribeConfig\n summary: string\n /** True when stdout carries JSON (summary.format=json): status lines then go to stderr so the JSON can be piped. */\n statusToStderr?: boolean\n}\n\n/** Posts a finished summary to --webhook, or to the configured Slack webhook with --slack. Never throws. */\nexport async function postSummary({\n options,\n config,\n summary,\n statusToStderr = false,\n}: PostSummaryInput): Promise<void> {\n const status = statusToStderr ? { info: log.notice, success: log.notice, warn: log.notice } : log\n const webhookUrl = options.webhook ?? (options.slack ? config.integrations?.slackWebhook : undefined)\n\n if (!webhookUrl) {\n if (options.slack && !config.integrations?.slackWebhook) {\n status.warn('--slack requires integrations.slackWebhook to be set in config')\n }\n return\n }\n\n try {\n status.info('Posting to webhook…')\n const body = isSlackWebhookUrl(webhookUrl) ? formatForSlack(summary, os.userInfo().username) : summary\n await postToWebhook(webhookUrl, body)\n status.success('Posted.')\n } catch (error) {\n log.error(`Webhook failed: ${(error as Error).message}`)\n }\n}\n","import { getOrBuildSessions } from '../sessions/detector'\nimport { log } from '../utils/logger'\nimport { todayDate, startOfWeek, eachDayOfRange } from '../utils/format'\nimport { buildDayPayload, locationContextFrom, type LocationContext } from './payload'\nimport { postSummary, type WebhookOptions } from './webhook'\nimport type { AIProvider, WeekSummaryPayload } from '../ai/types'\nimport type { WorkscribeConfig } from '../config'\n\nexport interface WeeklySummaryOptions extends WebhookOptions {\n /** Accepted for compatibility with 1.x scripts — weekly digests are always rendered fresh now. */\n fresh?: boolean\n}\n\ninterface RunWeeklySummaryInput {\n options: WeeklySummaryOptions\n config: WorkscribeConfig\n provider: AIProvider\n}\n\nfunction collectWeekDays(weekStart: string, today: string, context: LocationContext): WeekSummaryPayload['days'] {\n return eachDayOfRange(weekStart, today).flatMap((day) => {\n const sessions = getOrBuildSessions(day)\n if (sessions.length === 0) return []\n return [buildDayPayload(day, sessions, context)]\n })\n}\n\nasync function writeWeeklySummary(provider: AIProvider, payload: WeekSummaryPayload): Promise<string> {\n if (provider.summarizeWeek) return provider.summarizeWeek(payload)\n return provider.summarize({ date: payload.weekEnd, sessions: payload.days.flatMap((day) => day.sessions) })\n}\n\nfunction printSummary(summary: string): void {\n log.plain('')\n log.plain(summary)\n log.plain('')\n}\n\n/** Shared flow for `summary --week` and `week`: collect Mon–today, render the digest, post it. */\nexport async function runWeeklySummary({ options, config, provider }: RunWeeklySummaryInput): Promise<void> {\n const today = todayDate()\n const weekStart = startOfWeek(today)\n const days = collectWeekDays(weekStart, today, locationContextFrom(config))\n if (days.length === 0) {\n log.plain('No activity captured this week.')\n return\n }\n\n const summary = await writeWeeklySummary(provider, { weekStart, weekEnd: today, days })\n printSummary(summary)\n await postSummary({ options, config, summary })\n}\n","import { Command } from 'commander'\nimport chalk from 'chalk'\nimport { getOrBuildSessions } from '../sessions/detector'\nimport { readConfig } from '../config'\nimport { getSessionSummaries } from '../db'\nimport { log } from '../utils/logger'\nimport { todayDate, parseDate } from '../utils/format'\nimport type { AIProvider, DaySummaryPayload, SessionPayload } from '../ai/types'\nimport { buildExcludedSet, countExcludedEvents } from '../summary/exclusions'\nimport { sessionToPayload, locationContextFrom } from '../summary/payload'\nimport { formatSessionHeading, formatSessionLabel } from '../summary/heading'\nimport { sessionKey, pickSavedSummary, type SavedSummary } from '../summary/store'\nimport { createSummaryWriter } from '../summary/writer'\nimport { printLegacyAiNotice } from './notices'\nimport { postSummary } from '../summary/webhook'\nimport { runWeeklySummary } from '../summary/weekly'\n\ninterface SessionSummaryJson {\n project: string | null\n branch: string | null\n durationMinutes: number\n bullets: string[]\n}\n\n/** Parse 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 stripHeading(summary: string): string {\n return summary.replace(/^## .+\\n/, '')\n}\n\nfunction toJsonOutput(date: string, sessionPayloads: SessionPayload[], bulletsPerSession: string[]): string {\n const sessions: SessionSummaryJson[] = sessionPayloads.map((sessionPayload, index) => ({\n project: sessionPayload.project,\n branch: sessionPayload.branch,\n durationMinutes: sessionPayload.durationMinutes,\n bullets: parseBullets(bulletsPerSession[index]),\n }))\n return JSON.stringify({ date, sessions }, null, 2)\n}\n\nfunction printCapturedEvents(sessionPayloads: SessionPayload[], excluded: Set<string>): void {\n log.plain('')\n log.plain(chalk.bold(' Captured events (--verbose):'))\n for (const sessionPayload of sessionPayloads) {\n log.plain(chalk.dim(`\\n ${formatSessionLabel(sessionPayload)}`))\n for (const event of sessionPayload.events) {\n const tag = excluded.has(event.category) ? chalk.dim(` [excluded] ${event.category}`) : ` ${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\nfunction printExcludedFooter(sessionPayloads: SessionPayload[], excluded: Set<string>): void {\n const excludedCounts = countExcludedEvents(sessionPayloads, excluded)\n if (excludedCounts.size === 0) return\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\nasync function generateSessionSummary(input: {\n provider: AIProvider\n sessionPayload: SessionPayload\n date: string\n}): Promise<string> {\n const daySummaryPayload: DaySummaryPayload = { date: input.date, sessions: [input.sessionPayload] }\n try {\n const bullets = (await input.provider.summarize(daySummaryPayload)).trim()\n return `${formatSessionHeading(input.sessionPayload)}\\n${bullets}`\n } catch (error) {\n log.error(`Summary failed: ${(error as Error).message}`)\n process.exit(1)\n }\n}\n\n/** Says which sessions came from saved summaries, so it's clear why --fresh would change the output. */\nfunction printSavedNote(saved: (SavedSummary | null)[]): void {\n const fromSkill = saved.filter((entry) => entry?.fromSkill).length\n const fromLegacyProvider = saved.filter((entry) => entry && !entry.fromSkill).length\n const parts = [\n fromSkill > 0 ? `${fromSkill} written by the Workscribe agent skill` : null,\n fromLegacyProvider > 0 ? `${fromLegacyProvider} written by an AI provider in Workscribe 1.x` : null,\n ].filter((part): part is string => part !== null)\n if (parts.length === 0) return\n log.plain(chalk.dim(` (${parts.join(', ')} — use --fresh for the template summary)`))\n}\n\nexport function registerSummary(program: Command): void {\n program\n .command('summary')\n .description('Generate a work summary')\n .option('--date <YYYY-MM-DD>', 'date to summarize (default: today)')\n .option('--week', 'summarize the current week')\n .option('--fresh', 'ignore saved summaries and render the template')\n .option('--verbose', 'show all captured events, including those left out of the summary')\n .option('--slack', 'post summary to Slack webhook from config')\n .option('--webhook <url>', 'post summary to a custom webhook URL')\n .action(async (options) => {\n const config = readConfig()\n printLegacyAiNotice(config)\n const provider = createSummaryWriter(config)\n\n // ── Weekly branch ────────────────────────────────────────────────────────\n if (options.week) {\n try {\n await runWeeklySummary({ options, config, provider })\n } catch (error) {\n log.error((error as Error).message)\n process.exit(1)\n }\n return\n }\n\n // ── Daily branch ─────────────────────────────────────────────────────────\n let date = todayDate()\n if (options.date) {\n try {\n date = parseDate(options.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 sessionPayloads = sessions.map((session) => sessionToPayload(session, date, locationContextFrom(config)))\n const keys = sessions.map((session) => sessionKey(session.repoName, session.startedAt))\n const jsonMode = config.summary?.format === 'json'\n\n // A summary the agent skill (or a 1.x AI provider) saved — `--fresh` ignores both and renders the template\n const saved = keys.map((key) => (options.fresh ? null : pickSavedSummary(getSessionSummaries(key))))\n const needsGeneration = saved.some((entry) => entry === null)\n const excluded = buildExcludedSet(config.summary?.includeCategories ?? [])\n if (needsGeneration && options.verbose) {\n if (jsonMode) log.notice('--verbose is skipped when summary.format is json, to keep the JSON output clean')\n else printCapturedEvents(sessionPayloads, excluded)\n }\n\n const summaries: string[] = []\n for (const [index, sessionPayload] of sessionPayloads.entries()) {\n const savedSummary = saved[index]\n if (savedSummary) {\n summaries.push(savedSummary.text)\n continue\n }\n summaries.push(await generateSessionSummary({ provider, sessionPayload, date }))\n }\n\n const fullSummary = summaries.join('\\n\\n')\n if (jsonMode) {\n // Only the JSON on stdout, so it can be piped straight into another tool\n log.plain(toJsonOutput(date, sessionPayloads, summaries.map(stripHeading)))\n } else {\n log.plain('')\n log.plain(fullSummary)\n log.plain('')\n printSavedNote(saved)\n if (needsGeneration) printExcludedFooter(sessionPayloads, excluded)\n }\n\n await postSummary({ options, config, summary: fullSummary, statusToStderr: jsonMode })\n })\n}\n","import { Command } from 'commander'\nimport fs from 'fs'\nimport path from 'path'\nimport { getOrBuildSessions } from '../sessions/detector'\nimport { readConfig } from '../config'\nimport { log } from '../utils/logger'\nimport { todayDate, parseDate } from '../utils/format'\nimport { EXPORTS_DIR } from '../utils/paths'\nimport { buildDayPayload, locationContextFrom } from '../summary/payload'\nimport { createSummaryWriter } from '../summary/writer'\nimport { printLegacyAiNotice } from './notices'\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 (options) => {\n const config = readConfig()\n printLegacyAiNotice(config)\n\n let date = todayDate()\n if (options.date) {\n try {\n date = parseDate(options.date)\n } catch (error) {\n log.error((error 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 payload = buildDayPayload(date, sessions, locationContextFrom(config))\n const summary = await createSummaryWriter(config).summarize(payload)\n\n const outputPath = options.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 { REMOVED_AI_SETTING_MESSAGE, isRemovedAiSetting } from '../summary/legacy-ai'\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 session.idleTimeout 45)')\n .action((key: string, value: string) => {\n // Checked before reading or writing, so a refused key never touches config.json\n if (isRemovedAiSetting(key)) {\n log.error(REMOVED_AI_SETTING_MESSAGE)\n process.exit(1)\n }\n const config = readConfig()\n const updated = setConfigValue(config, key, value)\n writeConfig(updated)\n const isSensitive =\n key.toLowerCase().includes('key') || key.toLowerCase().includes('secret') || 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'\nimport { SKILL_AGENTS } from '../skills/agents'\nimport { removeSkills } from '../skills/actions'\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 // --hooks-only runs from npm preuninstall, which some package managers also run on upgrade — so\n // agent skills are only removed on a full uninstall, never silently during an upgrade\n if (opts.hooksOnly) return\n\n removeSkills(SKILL_AGENTS, { reportMissing: false })\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')} — then 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 { readConfig } from '../config'\nimport { log } from '../utils/logger'\nimport { runWeeklySummary } from '../summary/weekly'\nimport { createSummaryWriter } from '../summary/writer'\nimport { printLegacyAiNotice } from './notices'\n\nexport function registerWeek(program: Command): void {\n program\n .command('week')\n .description('Generate a weekly digest (Mon–today)')\n .option('--fresh', 'accepted for 1.x scripts — digests are always rendered fresh')\n .option('--slack', 'post to Slack webhook from config')\n .option('--webhook <url>', 'post to a custom webhook URL')\n .action(async (options) => {\n const config = readConfig()\n printLegacyAiNotice(config)\n try {\n await runWeeklySummary({ options, config, provider: createSummaryWriter(config) })\n } catch (error) {\n log.error((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>' // left over from a 1.x config\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 {\n getRecentSessionsByRepo,\n getLastSessionTouchingFile,\n getSessionBranch,\n getSessionSummaries,\n getEventsBySessionId,\n} from '../db'\nimport { getGitContext } from '../capture/git'\nimport { readConfig } from '../config'\nimport { formatDuration, timeAgo } from '../utils/format'\nimport { log } from '../utils/logger'\nimport { describeSession } from '../ai/engines/template/describe'\nimport { toBulletList } from '../ai/engines/template/utils'\nimport { sessionToPayload, locationContextFrom } from '../summary/payload'\nimport { formatSessionHeading } from '../summary/heading'\nimport { sessionKey, pickBestSummary } from '../summary/store'\nimport type { SessionRow } from '../db/types'\nimport type { Session } from '../sessions/detector'\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 sessionMinutes(session: SessionRow): number {\n return (new Date(session.ended_at).getTime() - new Date(session.started_at).getTime()) / 60000\n}\n\nfunction toSession(row: SessionRow): Session {\n return {\n id: row.id,\n date: row.date,\n startedAt: row.started_at,\n endedAt: row.ended_at,\n repoName: row.repo_name,\n durationMinutes: sessionMinutes(row),\n eventCount: row.event_count,\n summary: null,\n events: getEventsBySessionId(row.id),\n }\n}\n\n/** A template summary rendered from the session's current events — templates are never stored, so it can't go stale. */\nfunction renderTemplateSummary(row: SessionRow): string {\n const config = readConfig()\n const payload = sessionToPayload(toSession(row), row.date, locationContextFrom(config))\n const bullets = describeSession(payload, config.summary?.includeCategories ?? [])\n return `${formatSessionHeading(payload)}\\n${toBulletList(bullets)}`\n}\n\n/** The best stored summary (skill > AI > template), or a template one so the VS Code status bar is never empty. */\nfunction resolveContextSummary(row: SessionRow): string {\n return pickBestSummary(getSessionSummaries(sessionKey(row.repo_name, row.started_at))) ?? renderTemplateSummary(row)\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: sessionMinutes(session),\n branch: getSessionBranch(session.id),\n eventCount: session.event_count,\n summary: resolveContextSummary(session),\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 = sessionMinutes(session)\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 log.plain('')\n for (const line of resolveContextSummary(session).split('\\n')) {\n log.plain(` ${line}`)\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 { Command } from 'commander'\nimport chalk from 'chalk'\nimport { log } from '../utils/logger'\nimport { SKILL_AGENTS, SKILL_AGENT_IDS } from '../skills/agents'\nimport { detectAgents } from '../skills/detect'\nimport { resolvePackagedSkillDir } from '../skills/package-path'\nimport { groupBySkillsFolder, joinAgentNames } from '../skills/state'\nimport { AFTER_INSTALL_HINT, reasonOf } from '../skills/report'\nimport {\n describeTarget,\n formatAgentSkillLine,\n formatUndetectedAgentLine,\n installIntoFolder,\n printMessage,\n removeSkills,\n} from '../skills/actions'\nimport type { SkillAgent } from '../skills/types'\n\ninterface AgentOptions {\n agent?: string[]\n force?: boolean\n}\n\nfunction fail(message: string): never {\n log.error(message)\n process.exit(1)\n}\n\n/** The agents named with --agent (all must be known), or the given default. */\nfunction chooseAgents(options: {\n requested: string[] | undefined\n fallback: () => SkillAgent[]\n subcommand: 'install' | 'uninstall'\n}): SkillAgent[] {\n const { requested } = options\n if (!requested || requested.length === 0) return options.fallback()\n const unknown = requested.filter((id) => !SKILL_AGENT_IDS.includes(id))\n if (unknown.length > 0) {\n fail(\n `Unknown agent: ${unknown.join(', ')}. Choose from: ${SKILL_AGENT_IDS.join(', ')}. ` +\n `For example: workscribe skill ${options.subcommand} --agent claude-code`\n )\n }\n return SKILL_AGENTS.filter((agent) => requested.includes(agent.id))\n}\n\nfunction packagedSkillDir(): string {\n try {\n return resolvePackagedSkillDir()\n } catch (error) {\n fail(reasonOf(error))\n }\n}\n\nfunction installCommand(options: AgentOptions): void {\n const agents = chooseAgents({ requested: options.agent, fallback: detectAgents, subcommand: 'install' })\n if (agents.length === 0) {\n log.info(\n `No coding agents found. Workscribe can install its skill for ${joinAgentNames(SKILL_AGENTS)}. ` +\n \"If yours is installed somewhere Workscribe didn't look, name it: workscribe skill install --agent claude-code\"\n )\n return\n }\n const sourceDir = packagedSkillDir()\n for (const group of groupBySkillsFolder(agents)) {\n printMessage(installIntoFolder({ target: describeTarget(group), sourceDir, force: options.force }))\n }\n log.plain(chalk.dim(` ${AFTER_INSTALL_HINT}`))\n}\n\nfunction statusCommand(): void {\n const detected = new Set(detectAgents().map((agent) => agent.id))\n log.plain('')\n log.plain(chalk.bold(' Workscribe agent skill'))\n for (const agent of SKILL_AGENTS) {\n const line = detected.has(agent.id) ? formatAgentSkillLine(agent) : formatUndetectedAgentLine(agent)\n log.plain(` ${line}`)\n }\n log.plain('')\n}\n\nfunction uninstallCommand(options: AgentOptions): void {\n const agents = chooseAgents({ requested: options.agent, fallback: () => SKILL_AGENTS, subcommand: 'uninstall' })\n removeSkills(agents, { reportMissing: true })\n}\n\nexport function registerSkill(program: Command): void {\n const skill = program.command('skill').description('Install the Workscribe agent skill into your coding agents')\n const agentOption = `limit to these agents (${SKILL_AGENT_IDS.join(', ')})`\n\n skill\n .command('install')\n .description('Install or update the skill for every detected coding agent')\n .option('--agent <ids...>', agentOption)\n .option('--force', \"replace a workscribe skill that Workscribe didn't install\")\n .action(installCommand)\n\n skill\n .command('status')\n .description('Show which agents have the skill and whether it is up to date')\n .action(statusCommand)\n\n skill\n .command('uninstall')\n .description('Remove the skill Workscribe installed (never one you added yourself)')\n .option('--agent <ids...>', agentOption)\n .action(uninstallCommand)\n}\n","import fs from 'fs'\nimport os from 'os'\nimport { UPDATE_CHECK_PATH } from './paths'\nimport { readConfig, WorkscribeConfig } from '../config'\nimport { debugLog } from './logger'\n\nexport interface TelemetryPayload {\n installId: string\n cliVersion: string\n platform: string\n nodeVersion: string\n}\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 lastTelemetryPing?: number\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\n// Merges with whatever's already on disk rather than overwriting — checkForUpdate()\n// and pingTelemetry() each own one field in the same cache file and must not\n// silently wipe out the other's value when they write.\nfunction writeCache(updates: Partial<UpdateCache>): void {\n try {\n const current = readCache() ?? {}\n fs.writeFileSync(UPDATE_CHECK_PATH, JSON.stringify({ ...current, ...updates }), { 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\nexport function buildTelemetryPayload(config: WorkscribeConfig): TelemetryPayload {\n return {\n installId: config.telemetry.installId,\n cliVersion: __WORKSCRIBE_VERSION__,\n platform: os.platform(),\n nodeVersion: process.version,\n }\n}\n\nexport function pingTelemetry(): void {\n const config = readConfig()\n if (!config.telemetry.enabled || !config.telemetry.installId) return\n\n const cache = readCache()\n const now = Date.now()\n if (cache?.lastTelemetryPing && now - cache.lastTelemetryPing <= CHECK_INTERVAL_MS) return\n\n fetch('https://workscribe.co/api/telemetry/ping', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(buildTelemetryPayload(config)),\n })\n .then((response) => {\n // fetch() only rejects on network failure — a 4xx/5xx still resolves,\n // so without this check a server-side outage would silently look like\n // a successful ping and get throttled for a full day.\n if (!response.ok) {\n debugLog('pingTelemetry', new Error(`Ping failed with HTTP ${response.status}`))\n return\n }\n writeCache({ lastTelemetryPing: now })\n })\n .catch((error) => {\n debugLog('pingTelemetry', error)\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, shouldRunStartupChecks } from './cli/completions'\nimport { registerAlerts } from './cli/alerts'\nimport { registerContext } from './cli/context'\nimport { registerSkill } from './cli/skill'\nimport { checkForUpdate, pingTelemetry } from './utils/update-check'\nimport { ensureTelemetryFallback } from './config'\nimport { log } from './utils/logger'\n\nconst invokedCommand = process.argv[2]\nif (shouldRunStartupChecks(invokedCommand)) {\n checkForUpdate()\n // init handles its own telemetry disclosure via an interactive prompt —\n // the silent fallback is only for users who skip init entirely. Must run\n // before pingTelemetry() — otherwise a user's very first command would\n // generate the installId but the ping already read the old empty config\n // moments earlier, delaying the first ping to the next invocation.\n if (invokedCommand !== 'init') {\n ensureTelemetryFallback()\n }\n pingTelemetry()\n}\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)\nregisterSkill(program)\n\n// parseAsync (not parse) so a throw from either a sync or an async action\n// handler — e.g. getDb() failing to create its data directory — surfaces\n// here as a rejection instead of either an uncaught-exception stack trace\n// (sync actions) or an unhandled-rejection crash (async actions). _capture\n// and _hook already catch everything internally and never throw this far,\n// so this only ever engages for explicit user commands.\nprogram.parseAsync().catch((error: unknown) => {\n log.error(error instanceof Error ? error.message : String(error))\n process.exit(1)\n})\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","migration","fs","import_fs","chalk","fs","import_fs","import_os","import_path","path","os","fs","path","crypto","import_fs","import_path","path","fs","import_fs","import_path","path","fs","import_fs","import_path","step","step","step","migration","migration","fs","sessionKey","import_fs","fs","path","import_path","import_fs","import_child_process","path","fs","import_fs","import_path","step","PIPE_SEPARATORS","step","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","os","fs","path","import_fs","import_os","import_path","fs","path","import_fs","import_path","path","fs","import_fs","import_path","os","path","chalk","import_os","import_path","import_chalk","prompts","path","os","chalk","fs","prompts","import_fs","import_path","import_os","import_prompts","import_chalk","os","import_os","fs","chalk","import_fs","import_chalk","init_alerts","os","path","import_os","import_path","init_utils","init_utils","chalk","import_chalk","fs","import_fs","import_child_process","chalk","import_chalk","init_constants","init_utils","init_constants","init_utils","init_constants","init_utils","os","import_os","init_webhook","init_webhook","chalk","import_chalk","init_webhook","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","fs","path","os","chalk","import_fs","import_os","import_path","import_chalk","chalk","import_chalk","init_alerts","chalk","path","import_path","import_chalk","init_utils","fail","chalk","import_chalk","fs","os","import_fs","import_os","init_capture","init_config","init_alerts"]}
|
|
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/005_session_summaries.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/capture/shell-syntax.ts","../src/capture/command-steps.ts","../src/summary/exclusions.ts","../src/normalize/compound.ts","../src/normalize/patterns.ts","../src/normalize/reclassify.ts","../src/db/migrations/006_reclassify_other.ts","../src/db/migrations/index.ts","../src/db/migrate.ts","../src/db/session-lookup.ts","../src/db/index.ts","../src/capture/redact.ts","../src/capture/repo-name.ts","../src/capture/git.ts","../src/capture/git-snapshot.ts","../src/capture/aider.ts","../src/capture/workscribe-command.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/completion-scripts.ts","../src/utils/backup.ts","../src/capture/completions-block.ts","../src/capture/shell-hook.ts","../src/capture/hooks/utils.ts","../src/capture/hooks/claude-code-command.ts","../src/capture/hooks/claude-code.ts","../src/capture/hooks/index.ts","../src/cli/completions.ts","../src/utils/memoize.ts","../src/skills/agents.ts","../src/skills/detect.ts","../src/skills/state.ts","../src/skills/installer.ts","../src/skills/package-path.ts","../src/skills/report.ts","../src/skills/actions.ts","../src/summary/legacy-ai.ts","../src/cli/legacy-ai-cleanup.ts","../src/cli/init.ts","../src/utils/format.ts","../src/cli/notices.ts","../src/cli/status.ts","../src/summary/payload.ts","../src/summary/store.ts","../src/summary/contract/constants.ts","../src/summary/contract/utils.ts","../src/summary/contract/build.ts","../src/cli/events.ts","../src/sessions/grouper.ts","../src/sessions/detector.ts","../src/summary/write-back.ts","../src/utils/stdin.ts","../src/cli/session-summary.ts","../src/summary/git-commits.ts","../src/cli/sessions.ts","../src/summary/heading.ts","../src/ai/engines/template/constants.ts","../src/ai/engines/template/utils.ts","../src/ai/engines/template/describe.ts","../src/ai/engines/template/provider.ts","../src/summary/writer.ts","../src/integrations/webhook.ts","../src/integrations/slack.ts","../src/summary/webhook.ts","../src/summary/weekly.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/utils/working-directory.ts","../src/cli/note.ts","../src/cli/week.ts","../src/cli/bug-report.ts","../src/cli/alerts.ts","../src/cli/context.ts","../src/cli/skill.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 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","// Must produce exactly what sessionKey() in src/summary/store.ts produces — pinned by a test.\nexport const SESSION_KEY_SQL = \"COALESCE(repo_name, '') || '|' || started_at\"\n\nconst migration = {\n version: 5,\n description: 'Store session summaries per engine, keyed by repo and start time so they survive session rebuilds',\n sql: `\n CREATE TABLE IF NOT EXISTS session_summaries (\n session_key TEXT NOT NULL,\n engine TEXT NOT NULL,\n text TEXT NOT NULL,\n created_at TEXT NOT NULL,\n PRIMARY KEY (session_key, engine)\n );\n INSERT OR IGNORE INTO session_summaries (session_key, engine, text, created_at)\n SELECT ${SESSION_KEY_SQL}, 'legacy', summary, strftime('%Y-%m-%dT%H:%M:%fZ', 'now')\n FROM sessions\n WHERE summary IS NOT NULL;\n `,\n}\n\nexport default migration\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 /** A warning on stderr — keeps stdout clean for JSON output (summary.format=json) and pipes. */\n notice: (msg: string) => process.stderr.write(`${chalk.yellow('⚠')} ${msg}\\n`),\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 crypto from 'crypto'\nimport fs from 'fs'\nimport path from 'path'\nimport { CONFIG_PATH } from '../utils/paths'\nimport { debugLog } from '../utils/logger'\n\n/**\n * AI provider settings from Workscribe 1.x. 2.0 removed AI providers, so nothing writes these any more — they're\n * read only to tell 1.x users (see src/summary/legacy-ai.ts) and to keep a stored API key out of bug reports.\n */\nexport interface LegacyAiConfig {\n provider?: string\n apiKey?: string\n model?: string\n baseUrl?: string\n}\n\nexport interface WorkscribeConfig {\n ai?: LegacyAiConfig\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 summaries (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 // 1.x setting (\"template\" | \"ollama\" | \"provider\"). 2.0 always uses the template; read only to detect\n // old configs (src/summary/legacy-ai.ts).\n engine?: string\n }\n projects?: Record<string, string> // absolute path → display name override\n integrations?: {\n slackWebhook?: string\n webhook?: string\n }\n telemetry: {\n enabled: boolean\n installId: string\n }\n}\n\nconst DEFAULTS: WorkscribeConfig = {\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 telemetry: {\n enabled: true,\n installId: '',\n },\n}\n\nexport function readConfig(): WorkscribeConfig {\n if (!fs.existsSync(CONFIG_PATH)) return deepMerge(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 deepMerge(DEFAULTS, {})\n }\n}\n\nexport function writeConfig(config: WorkscribeConfig): void {\n // Previously safe to assume — writeConfig was only ever called after `init`\n // created the data directories, or by `config set` where init had already\n // run. CLI-05's fallback can now call this as the very first filesystem\n // touch for a user who skipped init entirely, so it can't assume the dir exists.\n fs.mkdirSync(path.dirname(CONFIG_PATH), { recursive: true, mode: 0o700 })\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\n// Generates and persists telemetry.installId on first use. Covers both a\n// fresh install and an existing user upgrading — deepMerge already backfills\n// the telemetry key itself, this just fills in the empty installId.\nexport function ensureInstallId(config: WorkscribeConfig): string {\n if (config.telemetry.installId) return config.telemetry.installId\n\n const installId = crypto.randomUUID()\n writeConfig({ ...config, telemetry: { ...config.telemetry, installId } })\n return installId\n}\n\n// Fallback for users who skip `init` entirely — which is exactly what an\n// existing user upgrading will typically do, since they never re-run it.\n// Presence of installId is the only state tracked; no separate \"notice\n// shown\" flag is needed since this is a no-op once installId is set.\nexport function ensureTelemetryFallback(): void {\n // Unlike init's explicit telemetry step, this runs unannounced ahead of\n // every command — it must never throw, however it fails, or a disk issue\n // (read-only $HOME, full disk, a locked-down CI sandbox) would crash the\n // user's actual command before it even starts.\n try {\n const config = readConfig()\n if (config.telemetry.installId) return\n\n config.telemetry.enabled = true\n config.telemetry.installId = ensureInstallId(config)\n\n process.stderr.write(\n '\\n Workscribe collects anonymous install stats (install ID, CLI version, platform, Node version).\\n Opt out: workscribe config set telemetry.enabled false\\n\\n'\n )\n } catch (error) {\n debugLog('ensureTelemetryFallback', error)\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 // structuredClone, not a shallow spread — any key overrides doesn't touch\n // (e.g. a config file written before a newer top-level key existed) must\n // still be an independent copy, not a shared reference back into the\n // caller's `defaults` object. A shallow spread here previously let any\n // caller that mutates a nested field on the returned config (e.g.\n // ensureTelemetryFallback) silently corrupt the module-level DEFAULTS\n // singleton for the rest of the process.\n const result = structuredClone(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 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","// Just enough shell syntax to find command boundaries in captured commands — quotes, escapes,\n// separators and substitutions — without a full parser. Pure and total: never throws.\n\ntype QuoteState = '\"' | \"'\" | null\n\ninterface QuotedCharacter {\n index: number\n quote: QuoteState\n}\n\n// `$(…)` and backticks run a command inside another, also inside double quotes. `<(…)` and `>(…)`\n// run one as a file, but only unquoted — inside double quotes they are plain text.\nconst COMMAND_SUBSTITUTION_OPENER = '$('\nconst PROCESS_SUBSTITUTION_OPENERS = ['<(', '>(']\n\n/**\n * Every character that is content rather than syntax, with the quote it sits in. Quote marks\n * themselves and backslash-escaped characters are skipped — they can't separate or substitute.\n */\nfunction* quotedCharacters(text: string): Generator<QuotedCharacter> {\n let quote: QuoteState = null\n for (let index = 0; index < text.length; index++) {\n const character = text[index]\n if (character === '\\\\' && quote !== \"'\") {\n index++\n continue\n }\n if (character === quote) {\n quote = null\n continue\n }\n if (quote === null && (character === '\"' || character === \"'\")) {\n quote = character\n continue\n }\n yield { index, quote }\n }\n}\n\nexport function isOutsideQuotes(text: string, position: number): boolean {\n for (const { index, quote } of quotedCharacters(text)) {\n if (index >= position) return quote === null\n }\n return true\n}\n\n/** A lone `&` runs the step before it in the background; `2>&1`, `&>` and `>&` are redirections, not separators. */\nfunction isRedirection(text: string, index: number): boolean {\n return text[index] === '&' && (text[index - 1] === '>' || text[index - 1] === '<' || text[index + 1] === '>')\n}\n\n/** Splits on any separator that sits outside single or double quotes. */\nexport function splitOutsideQuotes(text: string, separators: string[]): string[] {\n const parts: string[] = []\n let partStart = 0\n let skipUntil = 0\n for (const { index, quote } of quotedCharacters(text)) {\n if (quote !== null || index < skipUntil || isRedirection(text, index)) continue\n const separator = separators.find((candidate) => text.startsWith(candidate, index))\n if (!separator) continue\n parts.push(text.slice(partStart, index))\n partStart = index + separator.length\n skipUntil = partStart\n }\n parts.push(text.slice(partStart))\n return parts.map((part) => part.trim()).filter((part) => part !== '')\n}\n\n/** Command or process substitution outside single quotes: the shell runs another command inside this one. */\nexport function containsCommandSubstitution(text: string): boolean {\n for (const { index, quote } of quotedCharacters(text)) {\n if (quote === \"'\") continue\n if (text[index] === '`' || text.startsWith(COMMAND_SUBSTITUTION_OPENER, index)) return true\n if (quote === null && PROCESS_SUBSTITUTION_OPENERS.some((opener) => text.startsWith(opener, index))) return true\n }\n return false\n}\n\n// A `#` starts a comment only at the start of a word: `$#`, `${#x}` and `a#b` are not comments.\n// (bash and agents' shells treat it this way; interactive zsh only does with `interactivecomments` set.)\nconst WORD_BOUNDARY = /[\\s;&|()]/\n\n/** Where the first `# …` comment starts (outside quotes, at the start of a word), or -1. */\nexport function commentStart(text: string): number {\n for (const { index, quote } of quotedCharacters(text)) {\n if (quote !== null || text[index] !== '#') continue\n if (index === 0 || WORD_BOUNDARY.test(text[index - 1])) return index\n }\n return -1\n}\n\n/**\n * Removes `# …` comments up to the end of each line. Quote tracking restarts after each comment, so an\n * apostrophe inside one (`# let's check`) can't leave a quote \"open\" for the rest of the command.\n */\nexport function stripComments(text: string): string {\n let result = ''\n let rest = text\n for (let start = commentStart(rest); start !== -1; start = commentStart(rest)) {\n result += rest.slice(0, start)\n const lineEnd = rest.indexOf('\\n', start)\n if (lineEnd === -1) return result\n rest = rest.slice(lineEnd)\n }\n return result + rest\n}\n\n/**\n * The text with everything inside quotes (and the quote marks and escapes themselves) replaced by `_`, keeping\n * every position — so a pattern can be matched against the unquoted parts only and applied to the original.\n */\nexport function maskQuotedText(text: string): string {\n const masked = Array.from({ length: text.length }, () => '_')\n for (const { index, quote } of quotedCharacters(text)) {\n if (quote === null) masked[index] = text[index]\n }\n return masked.join('')\n}\n\nexport function startsWithWord(step: string, word: string): boolean {\n return step === word || step.startsWith(`${word} `) || step.startsWith(`${word}\\t`)\n}\n","// Breaks a captured shell command into the simple commands it runs, so each one can be classified or\n// filtered on its own — agents run things like `cd app && pnpm nx test shell 2>&1 | tail -40; npx tsc`.\n// Works on the raw command (heredocs and newlines are lost once whitespace is collapsed). Pure, never throws.\nimport {\n commentStart,\n containsCommandSubstitution,\n isOutsideQuotes,\n maskQuotedText,\n splitOutsideQuotes,\n startsWithWord,\n stripComments,\n} from './shell-syntax'\n\nconst STEP_SEPARATORS = ['&&', '||', ';', '\\n', '&']\nconst PIPE_SEPARATORS = ['|']\n/** Commands that only produce text. */\nexport const TEXT_SOURCES = ['echo', 'printf']\n// Steps that do no work of their own when they run nothing inside them\nconst GLUE_COMMANDS = ['cd', 'true', ':', ...TEXT_SOURCES]\n// `<<TAG`, `<<-TAG`, `<<'TAG'`, `<<\"TAG\"` — but not a `<<<` here-string\nconst HEREDOC_OPENER = /(?<!<)<<(?!<)-?\\s*(['\"]?)([A-Za-z_][A-Za-z0-9_]*)\\1/g\n// Words that wrap the command after them: `do npm test`, `if npm test`, `! grep x`, `time make`\nconst KEYWORD_PREFIX = /^(?:do|then|else|elif|if|while|until|time|!)\\s+/\n// Loop and case headers — shell structure, unless they run a command (`for f in $(npm test)`)\nconst STRUCTURE_HEADER = /^(?:for|select|case)\\s/\n// Closing keywords and bare keywords left over once a step is split\nconst STRUCTURE_KEYWORD = /^(?:done|fi|esac|\\}|\\)|do|then|else)$/\n// `NAME=value` before a command (or on its own); the value may be quoted or a `$(…)` substitution\nconst LEADING_ASSIGNMENT = /^[A-Za-z_][A-Za-z0-9_]*=(?:\"[^\"]*\"|'[^']*'|\\$\\([^)]*\\)|\\S*)(?:\\s+|$)/\n// `2>&1`, `> file`, `2>/dev/null`, `&> log`, `>> file`, `< input`\nconst REDIRECTION = /(?:^|\\s)(?:\\d*>>?|&>>?|<)\\s*(?:&\\d+|[^\\s;|&]+)/g\n// Package-runner forms that mean \"run this tool\", rewritten to `npx …` so the npx rules recognise them\nconst TOOL_RUNNER = /^(?:(?:pnpm|yarn|npm)\\s+exec|pnpm\\s+dlx|bunx)\\s+/\nconst FIRST_SUBSTITUTION = /\\$\\(([^()]*)\\)/\n// `$(…)` and backtick substitutions, for the commands inside them\nconst SUBSTITUTIONS = /\\$\\(([^()]*)\\)|`([^`]*)`/g\n\n/** The commands a line's `$(…)`/backtick substitutions run — what the shell executes from heredoc text. */\nfunction substitutionCommands(line: string): string[] {\n return [...line.matchAll(SUBSTITUTIONS)]\n .map((match) => (match[1] ?? match[2] ?? '').trim())\n .filter((command) => command !== '')\n}\n\n/**\n * Removes heredoc bodies, keeping the line that opens each one, so their text can't look like commands.\n * The shell still runs `$(…)` inside an unquoted heredoc (`<<EOF`, not `<<'EOF'`), so the commands inside\n * those substitutions stay — each on its own line, without the surrounding text (whose apostrophes and\n * other characters would otherwise be read as shell syntax).\n */\nexport function stripHeredocBodies(command: string): string {\n const kept: string[] = []\n const pending: { terminator: string; runsSubstitutions: boolean }[] = []\n for (const line of command.split('\\n')) {\n if (pending.length > 0) {\n if (line.trim() === pending[0].terminator) pending.shift()\n else if (pending[0].runsSubstitutions && containsCommandSubstitution(line))\n kept.push(...substitutionCommands(line))\n continue\n }\n kept.push(line)\n const comment = commentStart(line)\n for (const match of line.matchAll(HEREDOC_OPENER)) {\n // `\"a<<b\"` is text inside quotes, `\\<<` an escaped `<` and `# see <<EOF` a comment — none opens a heredoc\n const isEscaped = line[match.index - 1] === '\\\\'\n const isInComment = comment !== -1 && match.index > comment\n if (isEscaped || isInComment || !isOutsideQuotes(line, match.index)) continue\n pending.push({ terminator: match[2], runsSubstitutions: match[1] === '' })\n }\n }\n return kept.join('\\n')\n}\n\n/** The steps a shell runs: split on newlines, `&&`, `||`, `;` and a background `&`, outside quotes. */\nexport function splitSteps(command: string): string[] {\n return splitOutsideQuotes(command, STEP_SEPARATORS)\n}\n\nfunction countOf(text: string, character: string): number {\n return text.split(character).length - 1\n}\n\n/** `(cd app && npm test)` splits into `(cd app` and `npm test)` — drop the unbalanced group brackets. */\nfunction withoutGroupBrackets(step: string): string {\n let unwrapped = step\n while (unwrapped.startsWith('(') && countOf(unwrapped, '(') > countOf(unwrapped, ')')) {\n unwrapped = unwrapped.slice(1).trim()\n }\n while (unwrapped.endsWith(')') && countOf(unwrapped, ')') > countOf(unwrapped, '(')) {\n unwrapped = unwrapped.slice(0, -1).trim()\n }\n if (unwrapped.startsWith('{ ')) unwrapped = unwrapped.slice(2).trim()\n return unwrapped\n}\n\nfunction withoutKeywordPrefixes(step: string): string {\n let unwrapped = step\n while (KEYWORD_PREFIX.test(unwrapped)) unwrapped = unwrapped.replace(KEYWORD_PREFIX, '')\n return unwrapped\n}\n\nfunction withoutLeadingAssignments(step: string): string {\n let unwrapped = step\n while (LEADING_ASSIGNMENT.test(unwrapped)) unwrapped = unwrapped.replace(LEADING_ASSIGNMENT, '')\n return unwrapped\n}\n\n/** `d=node_modules/x` does nothing on its own; `f=$(npm test)` still runs `npm test`, so it stays. */\nfunction isPlainAssignment(step: string): boolean {\n return withoutLeadingAssignments(step) === '' && !containsCommandSubstitution(step)\n}\n\n/** Loop headers and closing keywords do no work — but a header that runs a command (`for f in $(ls)`) does. */\nfunction isShellStructure(step: string): boolean {\n if (STRUCTURE_KEYWORD.test(step)) return true\n return STRUCTURE_HEADER.test(step) && !containsCommandSubstitution(step)\n}\n\n/** Removes redirections (`2>&1`, `> out.txt`) outside quotes — a `>` inside a commit message is kept. */\nfunction withoutRedirections(command: string): string {\n const masked = maskQuotedText(command)\n let result = ''\n let copiedUpTo = 0\n for (const match of masked.matchAll(REDIRECTION)) {\n result += command.slice(copiedUpTo, match.index)\n copiedUpTo = match.index + match[0].length\n }\n return result + command.slice(copiedUpTo)\n}\n\n/**\n * The commands a captured shell line runs, in order: comments and heredoc bodies removed, split into steps,\n * group brackets and wrapping keywords (`do`, `then`, `if`…) removed, and loop headers, closing keywords and\n * plain assignments dropped.\n */\nexport function commandSteps(rawCommand: string): string[] {\n return splitSteps(stripComments(stripHeredocBodies(rawCommand)))\n .map((step) => withoutKeywordPrefixes(withoutGroupBrackets(step)))\n .filter((step) => step !== '' && !isShellStructure(step) && !isPlainAssignment(step))\n}\n\n/**\n * The command a step mainly runs, in a form the normalizer rules can match: leading assignments, everything\n * after the first `|`, and redirections removed; `pnpm exec tsc` read as `npx tsc`. For an assignment or a\n * loop header that runs a command (`f=$(find . -name x)`, `for f in $(npm test)`), the command inside.\n */\nexport function simpleCommandOf(step: string): string {\n const command = withoutLeadingAssignments(step)\n if (command === '' || STRUCTURE_HEADER.test(command)) return step.match(FIRST_SUBSTITUTION)?.[1]?.trim() ?? ''\n const [firstStage = ''] = splitOutsideQuotes(command, PIPE_SEPARATORS)\n return withoutRedirections(firstStage).replace(/\\s+/g, ' ').trim().replace(TOOL_RUNNER, 'npx ')\n}\n\n/**\n * Shell glue that does no work of its own — `cd`, `true`, `:`, or printing text — as long as it runs\n * nothing inside it and pipes nothing. Agents wrap commands in these (`… || true`, `; echo \"exit=$?\"`).\n */\nexport function isGlueStep(step: string): boolean {\n if (containsCommandSubstitution(step) || splitOutsideQuotes(step, PIPE_SEPARATORS).length > 1) return false\n return GLUE_COMMANDS.some((command) => startsWithWord(step, command))\n}\n","// Categories excluded from summary input 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 summary context for commands that don't fit known patterns\n// (e.g. docker compose up, make deploy, terraform apply).\n// Only a type import, so the template engine and the --json contract can use this without loading profiles or the DB.\nimport type { SessionPayload } from '../ai/types'\n\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 category of includeCategories) excluded.delete(category)\n return excluded\n}\n\n/** How many events of each excluded category the summary left out — for the footer under `workscribe summary`. */\nexport function countExcludedEvents(sessions: SessionPayload[], excluded: Set<string>): 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)) counts.set(event.category, (counts.get(event.category) ?? 0) + 1)\n }\n }\n return counts\n}\n","// Classifies compound shell commands — `cd app && pnpm nx test shell 2>&1 | tail -40; npx tsc` — by their most\n// telling step. Pure: the rule matcher is passed in, so this module doesn't load the rules (or the profiles).\nimport { commandSteps, isGlueStep, simpleCommandOf } from '../capture/command-steps'\nimport { DEFAULT_EXCLUDED_CATEGORIES } from '../summary/exclusions'\nimport type { NormalizedEvent } from './patterns'\n\nexport type MatchCommand = (command: string) => NormalizedEvent\n\nexport const UNCLASSIFIED: NormalizedEvent = { category: 'other', metadata: {} }\n\n// When a compound command runs several things, the event takes the step that says most about the work:\n// outcomes first, then routine work. `git status` (versioning) must never hide `npm test` next to it.\nexport const STEP_CATEGORY_PRIORITY = [\n 'testing',\n 'building',\n 'releasing',\n 'shipping',\n 'dependencies',\n 'database',\n 'infrastructure',\n 'running',\n 'files',\n 'versioning',\n]\n\n// Ranks after the priority list, lower is more telling: any other category, then ones summaries leave out, then `other`\nconst OTHER_CATEGORY_RANK = STEP_CATEGORY_PRIORITY.length\nconst EXCLUDED_CATEGORY_RANK = OTHER_CATEGORY_RANK + 1\nconst UNCLASSIFIED_RANK = EXCLUDED_CATEGORY_RANK + 1\n\nfunction rankOf(category: string): number {\n const index = STEP_CATEGORY_PRIORITY.indexOf(category)\n if (index !== -1) return index\n if (category === UNCLASSIFIED.category) return UNCLASSIFIED_RANK\n if (DEFAULT_EXCLUDED_CATEGORIES.has(category)) return EXCLUDED_CATEGORY_RANK\n return OTHER_CATEGORY_RANK\n}\n\n/** The most telling step's event; ties go to the earlier step. */\nfunction primaryStepEvent(steps: string[], matchCommand: MatchCommand): NormalizedEvent {\n const events = steps.map((step) => matchCommand(simpleCommandOf(step)))\n return events.reduce((best, event) => (rankOf(event.category) < rankOf(best.category) ? event : best), UNCLASSIFIED)\n}\n\n/**\n * A command the rules already recognise as it is, with nothing else to run, keeps that result. Otherwise it's\n * split into the commands it runs, shell glue (`cd`, `echo`, assignments, loop keywords) is set aside, and the\n * most telling step names the event — falling back to the whole command when no step is recognised either.\n */\nexport function classifyCompound(command: string, matchCommand: MatchCommand): NormalizedEvent {\n const wholeCommandEvent = matchCommand(command)\n const workSteps = commandSteps(command).filter((step) => !isGlueStep(step))\n const isRecognisedSingleCommand = workSteps.length <= 1 && wholeCommandEvent.category !== UNCLASSIFIED.category\n if (isRecognisedSingleCommand || workSteps.length === 0) return wholeCommandEvent\n\n const primaryEvent = primaryStepEvent(workSteps, matchCommand)\n return primaryEvent.category === UNCLASSIFIED.category ? wholeCommandEvent : primaryEvent\n}\n","import { loadAIToolRegistry } from '../config/registry'\nimport { getActiveProfileRules } from '../profiles/loader'\nimport { debugLog } from '../utils/logger'\nimport { classifyCompound, UNCLASSIFIED } from './compound'\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\n// Nx targets → categories: `nx build app`, `nx run app:test`, `nx run-many -t lint`, `nx affected --target=e2e`\nconst NX_TARGET_CATEGORIES: Record<string, string> = {\n build: 'building',\n test: 'testing',\n e2e: 'testing',\n lint: 'linting',\n serve: 'running',\n dev: 'running',\n}\nconst NX_COMMAND =\n /^(?:(?:npx|pnpm|yarn|bunx)\\s+)?nx\\s+(?:(?:run-many|affected)\\b.*?(?:-t|--targets?)[=\\s]+([\\w-]+)|run\\s+[\\w@./-]+:([\\w-]+)|([\\w-]+)\\b)/\n\nconst nxRule: Rule = {\n match(cmd) {\n const match = cmd.match(NX_COMMAND)\n const target = match?.[1] ?? match?.[2] ?? match?.[3]\n const category = target ? NX_TARGET_CATEGORIES[target] : undefined\n return category ? { category, metadata: { tool: 'nx', target } } : null\n },\n}\n\nconst BASE_RULES: Rule[] = [\n // ─── Git operations ───────────────────────────────────────────────────────\n makeRule(/^git\\s+commit\\b/, 'shipping', (_m, cmd) => {\n // -m \"…\" / -m '…' keep the whole message (an apostrophe inside double quotes is part of it);\n // an unquoted -m takes one word, so `-m wip --no-verify` is \"wip\", not \"wip --no-verify\"\n const msgMatch = cmd.match(/-m\\s+(?:\"([^\"]*)\"|'([^']*)'|(\\S+))/)\n const message = msgMatch ? (msgMatch[1] ?? msgMatch[2] ?? msgMatch[3]).trim() : null\n return { message: message || null }\n }),\n\n makeRule(/^git\\s+push\\b/, 'shipping', (_m, cmd) => {\n // Flags (-u, --force, …) aren't the remote or branch: `git push -u origin main` → origin/main\n const positional = cmd\n .split(/\\s+/)\n .slice(2)\n .filter((part) => !part.startsWith('-'))\n return { remote: positional[0] ?? 'origin', branch: positional[1] ?? 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 action: 'remove',\n })),\n\n makeRule(/^(yarn|pnpm)\\s+remove\\b/, 'dependencies', (m, cmd) => ({\n tool: m[1],\n packages: extractPackages(cmd, 'remove'),\n action: 'remove',\n })),\n\n makeRule(/^bun\\s+remove\\b/, 'dependencies', (_m, cmd) => ({\n tool: 'bun',\n packages: extractPackages(cmd, 'remove'),\n action: 'remove',\n })),\n\n makeRule(/^pip\\s+uninstall\\b/, 'dependencies', (_m, cmd) => ({\n tool: 'pip',\n packages: extractPackages(cmd, 'uninstall'),\n action: 'remove',\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 // ─── Nx (before the package-manager rules, which would read `pnpm nx` as `pnpm`) ─\n nxRule,\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\n// Built on first use, not at import: the active profiles come from the config and profile files, and\n// importing this module (via capture, or the database's migrations) shouldn't read either\nlet activeRules: Rule[] | null = null\n\nfunction getRules(): Rule[] {\n activeRules ??= buildRules(getActiveProfileRules())\n return activeRules\n}\n\nfunction matchRules(command: string): NormalizedEvent {\n // Strip `git -C <path>` prefix so rules match regardless of working directory flag\n const flattened = command\n .trim()\n .replace(/\\s+/g, ' ')\n .replace(/^(git)\\s+-C\\s+\\S+\\s+/, '$1 ')\n for (const rule of getRules()) {\n const result = rule.match(flattened)\n if (result) return result\n }\n return UNCLASSIFIED\n}\n\n/** Classifies a captured command — compound ones by their most telling step (see `./compound`). */\nexport function normalizeCommand(command: string): NormalizedEvent {\n return classifyCompound(command, matchRules)\n}\n","import type { NormalizedEvent } from './patterns'\n\nexport interface ReclassifyOptions {\n classify: (command: string) => NormalizedEvent\n /** `capture.aiTools` — when it's off, Workscribe doesn't record AI sessions, so none are created here either. */\n aiToolsEnabled: boolean\n}\n\n/**\n * The new category and metadata for a stored `other` event, or null to leave it alone. The metadata\n * replaces the old one entirely, so the `hint`/`tool` kept for unclassified commands doesn't linger.\n */\nexport function reclassifiedEvent(\n command: string,\n { classify, aiToolsEnabled }: ReclassifyOptions\n): NormalizedEvent | null {\n const event = classify(command)\n if (event.category === 'other') return null\n if (event.category === 'ai_session' && !aiToolsEnabled) return null\n return event\n}\n","// Reclassifies stored `other` events with the classifier as it is when this runs — so on an install that first\n// opens its database with a later release, later rules and the user's active profiles apply too. That's fine:\n// it only ever improves `other` rows, never touches any other row or a stored command, and skips what it can't classify.\nimport { normalizeCommand } from '../../normalize/patterns'\nimport { reclassifiedEvent } from '../../normalize/reclassify'\nimport { readConfig } from '../../config'\nimport { debugLog } from '../../utils/logger'\nimport type { Migration, MigrationDatabase } from '../migration-types'\n\ninterface UnclassifiedRow {\n id: number\n command: string\n}\n\nfunction classifyOrSkip(row: UnclassifiedRow, aiToolsEnabled: boolean): ReturnType<typeof reclassifiedEvent> {\n try {\n return reclassifiedEvent(row.command, { classify: normalizeCommand, aiToolsEnabled })\n } catch (error) {\n // Best-effort: this runs the first time any command opens the database after upgrading (even the\n // background capture), so one odd command must never fail the migration and lock the database out\n debugLog('migration-006', error)\n return null\n }\n}\n\nconst migration: Migration = {\n version: 6,\n description: 'Reclassify unclassified events now that compound commands are classified by their main step',\n sql: '',\n run(db: MigrationDatabase) {\n const aiToolsEnabled = readConfig().capture.aiTools !== false\n const rows = db.prepare(\"SELECT id, command FROM events WHERE category = 'other'\").all() as UnclassifiedRow[]\n const update = db.prepare('UPDATE events SET category = ?, metadata = ? WHERE id = ?')\n for (const row of rows) {\n const event = classifyOrSkip(row, aiToolsEnabled)\n if (!event) continue\n const metadata = Object.keys(event.metadata).length > 0 ? JSON.stringify(event.metadata) : null\n update.run(event.category, metadata, row.id)\n }\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'\nimport sessionSummaries from './005_session_summaries'\nimport reclassifyOther from './006_reclassify_other'\nimport type { Migration } from '../migration-types'\n\nexport type { Migration } from '../migration-types'\n\n// Ordered list — append only. Never modify or remove an existing entry.\nexport const MIGRATIONS: Migration[] = [\n initialSchema,\n semanticCategories,\n alerts,\n ideColumns,\n sessionSummaries,\n reclassifyOther,\n]\n","import type { Migration, MigrationDatabase } from './migration-types'\n\n/** An install from before the migration system already has the events table — record version 1 as applied. */\nfunction seedVersionOneForOldInstalls(db: MigrationDatabase): void {\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 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\nfunction isApplied(db: MigrationDatabase, version: number): boolean {\n return db.prepare('SELECT version FROM schema_migrations WHERE version = ?').get(version) !== undefined\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n\n/**\n * Applies each pending migration in order, each in its own transaction, so a failure leaves the database at\n * the previous version and the next run retries it. `BEGIN IMMEDIATE` takes the write lock up front and the\n * version is checked inside the transaction, so two processes starting at once (parallel captures from an\n * agent) can't both run a migration. Kept free of `node:sqlite` so tests can run it on any database.\n */\nexport function applyMigrations(db: MigrationDatabase, migrations: Migration[]): void {\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 seedVersionOneForOldInstalls(db)\n\n for (const migration of migrations) {\n if (isApplied(db, migration.version)) continue\n\n db.exec('BEGIN IMMEDIATE')\n try {\n if (isApplied(db, migration.version)) {\n db.exec('COMMIT')\n continue\n }\n if (migration.sql.trim()) db.exec(migration.sql)\n migration.run?.(db)\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 (error) {\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: ${errorMessage(error)}`, {\n cause: error,\n })\n }\n }\n}\n","import type { MigrationDatabase } from './migration-types'\nimport type { SessionRow } from './types'\n\n/** Which sessions belong to a repo — see `findRecentSessionsForRepo`. */\nexport interface RepoLookup {\n /** The name the current config gives the repo */\n repoName: string\n /** The repo's name in the other `git.qualifyRepoName` form, if it has one (only names from the remote do) */\n otherRepoName: string | null\n /** The repo's working tree, in each form a stored `cwd` may use; sessions under `otherRepoName` need activity in it */\n roots: string[]\n}\n\n// A session stored under the other name form counts only if one of its events ran in this repo's working tree, so\n// a same-named repo from another owner (the collision `qualifyRepoName` exists for) is never matched. `substr`\n// rather than LIKE, so `%` and `_` in a path aren't wildcards. The root comes in more than one form (resolved, and\n// through a symlink), passed as a JSON array.\nconst RECENT_SESSIONS_FOR_REPO = `\n SELECT s.* FROM sessions s\n WHERE s.repo_name = $repo_name\n OR (s.repo_name = $other_repo_name AND EXISTS (\n SELECT 1 FROM session_events se\n INNER JOIN events e ON e.id = se.event_id\n INNER JOIN json_each($roots) root\n WHERE se.session_id = s.id\n AND (e.cwd = root.value OR substr(e.cwd, 1, length(root.value) + 1) = root.value || '/')\n ))\n ORDER BY s.started_at DESC\n LIMIT $limit`\n\n/** The repo's latest sessions, newest first, under its configured name or — inside its own tree — the other form. */\nexport function findRecentSessionsForRepo(db: MigrationDatabase, lookup: RepoLookup, limit: number): SessionRow[] {\n return db.prepare(RECENT_SESSIONS_FOR_REPO).all({\n repo_name: lookup.repoName,\n other_repo_name: lookup.otherRepoName,\n roots: JSON.stringify(lookup.roots),\n limit,\n }) as SessionRow[]\n}\n","import { DatabaseSync } from 'node:sqlite'\nimport fs from 'fs'\nimport { WORKSCRIBE_DIR, DB_PATH } from '../utils/paths'\nimport type { EventRow, SessionRow, SessionSummaryRow } from './types'\nimport { MIGRATIONS } from './migrations'\nimport { applyMigrations } from './migrate'\nimport { findRecentSessionsForRepo, type RepoLookup } from './session-lookup'\nimport type { StoredEngine } from '../ai/engine'\nexport type { EventRow, SessionRow, SessionSummaryRow } 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 try {\n fs.mkdirSync(WORKSCRIBE_DIR, { recursive: true })\n } catch (error) {\n // Rethrown as a clean, actionable message — callers reaching this\n // (explicit commands, or _capture/_hook's own try/catch) otherwise\n // only see a raw native stack trace with the real cause buried in it.\n throw new Error(`Could not create data directory ${WORKSCRIBE_DIR}: ${(error as Error).message}`)\n }\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 // Parallel captures (an agent running several commands at once) wait for the write lock instead of failing\n db.exec('PRAGMA busy_timeout = 5000')\n applyMigrations(db, MIGRATIONS)\n _db = db\n return _db\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 getRecentSessionsForRepo(lookup: RepoLookup, limit: number): SessionRow[] {\n return findRecentSessionsForRepo(getDb(), lookup, limit)\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 getLastEventForCwd(cwd: string): EventRow | undefined {\n const db = getDb()\n return db.prepare('SELECT * FROM events WHERE cwd = $cwd ORDER BY id DESC LIMIT 1').get({ cwd }) as\n | EventRow\n | 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 getSessionSummaries(sessionKey: string): SessionSummaryRow[] {\n const db = getDb()\n const stmt = db.prepare('SELECT * FROM session_summaries WHERE session_key = $session_key')\n return stmt.all({ session_key: sessionKey }) as unknown as SessionSummaryRow[]\n}\n\nexport function saveSessionSummary(sessionKey: string, engine: StoredEngine, text: string): void {\n const db = getDb()\n const stmt = db.prepare(`\n INSERT INTO session_summaries (session_key, engine, text, created_at)\n VALUES ($session_key, $engine, $text, $created_at)\n ON CONFLICT (session_key, engine) DO UPDATE SET text = excluded.text, created_at = excluded.created_at\n `)\n stmt.run({ session_key: sessionKey, engine, text, created_at: new Date().toISOString() })\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","// How a repo's `origin` remote becomes a repo name, in both forms `git.qualifyRepoName` chooses between. Pure.\n\n/** The owner and repo parsed from an `origin` remote URL. */\nexport interface RemoteRepo {\n owner: string\n repo: string\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 '/'.\nexport function parseOwnerAndRepo(url: string): RemoteRepo | 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\n/** `owner/repo` when qualified, bare `repo` otherwise. */\nexport function formatRepoName(remote: RemoteRepo, qualify: boolean): string {\n return qualify ? `${remote.owner}/${remote.repo}` : remote.repo\n}\n","import { execSync } from 'child_process'\nimport path from 'path'\nimport fs from 'fs'\nimport type { WorkscribeConfig } from '../config'\nimport { formatRepoName, parseOwnerAndRepo, type RemoteRepo } from './repo-name'\n\n/** Everything known about the repo at a path — `root` and `remote` let `context` find the other name form too. */\nexport interface RepoContext {\n repoName: string | null\n branch: string | null\n root: string | null\n /** The `origin` remote, set only when `repoName` came from it (not an override, package.json or the folder) */\n remote: RemoteRepo | null\n}\n\n/** The settings that decide what a repo is called. */\nexport type RepoNamingConfig = Pick<WorkscribeConfig, 'projects' | 'git'>\n\nconst NOT_A_REPO: RepoContext = { repoName: null, branch: null, root: null, remote: null }\n\nfunction remoteOf(root: string): RemoteRepo | 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 return parseOwnerAndRepo(url)\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\nfunction currentBranch(cwd: string): string | null {\n try {\n return (\n execSync('git branch --show-current', {\n cwd,\n timeout: 2000,\n stdio: 'pipe',\n })\n .toString()\n .trim() || null\n )\n } catch {\n return null // Detached HEAD or not a git repo\n }\n}\n\n/** The repo's name, and the remote it came from — set only when the name did come from the remote. */\nfunction nameRepo(\n root: string,\n nameOverride: string | null,\n qualifyRepoName: boolean\n): Pick<RepoContext, 'repoName' | 'remote'> {\n if (nameOverride !== null) return { repoName: nameOverride, remote: null }\n const remote = remoteOf(root)\n if (remote) return { repoName: formatRepoName(remote, qualifyRepoName), remote }\n return { repoName: nameFromPackageJson(root) ?? path.basename(root), remote: null }\n}\n\n/**\n * The repo at `cwd`, named the way the config says: the `projects.<cwd>` override, else the `origin` remote in the\n * `git.qualifyRepoName` form, else package.json or the folder. Everything that stores or looks up a repo name uses\n * this, so shell, IDE, notes and `context` always agree.\n */\nexport function getRepoContext(cwd: string, config: RepoNamingConfig): RepoContext {\n let root: string\n try {\n root = execSync('git rev-parse --show-toplevel', {\n cwd,\n timeout: 2000,\n stdio: 'pipe',\n })\n .toString()\n .trim()\n } catch {\n return NOT_A_REPO\n }\n const naming = nameRepo(root, config.projects?.[cwd] ?? null, config.git.qualifyRepoName)\n return { ...naming, branch: currentBranch(cwd), root }\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","// Recognises Workscribe's own commands inside compound shell input, so a coding agent running the\n// Workscribe skill (`cd repo && workscribe …`, `… | workscribe …`, heredocs) isn't captured as work.\n// Works on the raw command: heredocs and newlines are lost once whitespace is collapsed.\nimport { containsCommandSubstitution, splitOutsideQuotes, startsWithWord } from './shell-syntax'\nimport { commandSteps, isGlueStep, TEXT_SOURCES } from './command-steps'\n\nconst PIPE_SEPARATORS = ['|']\n\n/**\n * A step is Workscribe's when it starts with `workscribe` (whatever it's piped into), or when it only\n * pipes text into it (`echo … | workscribe …`). `npm test | workscribe note done` still ran the tests,\n * and so does `workscribe note \"$(npm test)\"`, so neither is.\n */\nfunction isWorkscribeStep(step: string): boolean {\n if (containsCommandSubstitution(step)) return false\n const stages = splitOutsideQuotes(step, PIPE_SEPARATORS)\n if (startsWithWord(stages[0] ?? '', 'workscribe')) return true\n const isTextOrWorkscribe = (stage: string): boolean =>\n startsWithWord(stage, 'workscribe') || TEXT_SOURCES.some((source) => startsWithWord(stage, source))\n return stages.every(isTextOrWorkscribe) && stages.some((stage) => startsWithWord(stage, 'workscribe'))\n}\n\n/**\n * True when the command does nothing but run Workscribe — possibly wrapped in shell glue (`cd`,\n * `|| true`, `; echo $?`), piped into, or with a heredoc. A command that also does real work\n * (`npm test && workscribe note …`) is not Workscribe-only.\n */\nexport function isWorkscribeOnlyCommand(rawCommand: string): boolean {\n const steps = commandSteps(rawCommand)\n const workSteps = steps.filter((step) => !isGlueStep(step))\n return workSteps.length > 0 && workSteps.every(isWorkscribeStep)\n}\n","import type { EventRow } from '../db/types'\nimport { isWorkscribeOnlyCommand } from './workscribe-command'\nimport { commandSteps, isGlueStep } from './command-steps'\n\nfunction normalizeForFilter(cmd: string): string {\n return cmd.trim().replace(/\\s+/g, ' ')\n}\n\nfunction isIgnoredStep(step: string, ignoreList: string[]): boolean {\n const normalized = normalizeForFilter(step)\n return ignoreList.includes(normalized) || ignoreList.includes(normalized.split(' ')[0])\n}\n\n/**\n * Returns true if the command should be dropped (noise / ignore list).\n *\n * The ignore list applies to each step of a compound command: `cd app && npm test` is kept because\n * `npm test` is real work, while `cd app && ls` is dropped. A step that does nothing on its own (`cd`,\n * `echo`) can't keep a command, but a command made only of such steps is dropped only if one of them is\n * on the ignore list — so `echo hi` on its own is still captured, as before.\n */\nexport function shouldFilter(command: string, ignoreList: string[]): boolean {\n const normalized = normalizeForFilter(command)\n if (!normalized) return true\n\n // Workscribe's own commands — always excluded, not user-configurable. Checked on the raw command so\n // compound ones an agent runs are caught too, while `workscribe note \"$(npm test)\"` still counts as work.\n if (isWorkscribeOnlyCommand(command)) return true\n\n const normalizedIgnore = ignoreList.map(normalizeForFilter)\n if (normalizedIgnore.includes(normalized)) return true\n\n const steps = commandSteps(command)\n const isQuiet = (step: string): boolean => isIgnoredStep(step, normalizedIgnore) || isGlueStep(step)\n return steps.every(isQuiet) && steps.some((step) => isIgnoredStep(step, normalizedIgnore))\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// task_run can double-capture: a shell task running in a hooked terminal\n// fires both this generic event and a richer shell-sourced one, with no\n// shared ID linking them. Shell events land first (precmd fires as the\n// command returns), so a short window here catches the same real action.\nexport const TASK_RUN_DEDUP_WINDOW_MS = 5_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, getLastEventForCwd } from '../db'\nimport { redact } from './redact'\nimport { getRepoContext } 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, TASK_RUN_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 // A shell task running in a hooked terminal already got captured with a\n // real category by the shell hook — skip the generic duplicate.\n if (opts.type === 'task_run') {\n const lastForCwd = getLastEventForCwd(cwd)\n if (lastForCwd && !lastForCwd.source) {\n const lastTime = new Date(lastForCwd.captured_at).getTime()\n if (Date.now() - lastTime < TASK_RUN_DEDUP_WINDOW_MS) return\n }\n }\n\n const command = opts.command ?? opts.file ?? opts.type\n const { repoName, branch } = getRepoContext(cwd, config)\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 — named exactly as the IDE path, notes and `context` name it\n const { repoName, branch } = getRepoContext(cwd, config)\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 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}\ncompdef _workscribe 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'\n\n// Far more than two edits in one millisecond ever need; a bound so a broken file system can't loop forever\nconst MAX_BACKUP_ATTEMPTS = 100\n\n/**\n * Copies a file the user owns to `<file>.workscribe-backup-<time>` before Workscribe edits it, and returns the\n * backup's path. Never overwrites an earlier backup — two edits in the same millisecond (say the shell hook and\n * the completions block, one after the other) each keep their own copy.\n */\nexport function backUpFile(file: string): string {\n const base = `${file}.workscribe-backup-${Date.now()}`\n for (let attempt = 1; attempt <= MAX_BACKUP_ATTEMPTS; attempt++) {\n const backup = attempt === 1 ? base : `${base}-${attempt}`\n try {\n fs.copyFileSync(file, backup, fs.constants.COPYFILE_EXCL)\n return backup\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error\n }\n }\n throw new Error(`Couldn't back up ${file}: too many backups named ${base}`)\n}\n","// The `# Workscribe completions` block `init` adds to ~/.zshrc / ~/.bashrc. Pure text handling, so the rc-file\n// I/O in shell-hook.ts stays thin. The block guards its `source` line, so it does nothing — and prints nothing —\n// once the completion script is gone (e.g. after the package and its data folder are removed).\n//\n// This code edits the user's own rc files, so it only ever touches lines in the exact shapes Workscribe wrote:\n// a marker line directly followed by the line(s) below, sourcing Workscribe's own `completion.<shell>` script.\n// A marker on its own, or followed by anything else, is left alone.\n\nexport const COMPLETIONS_MARKER = '# Workscribe completions'\n\nconst ZSH_COMPINIT = 'autoload -Uz compinit && compinit'\n// Workscribe's own script: `<data folder>/completion.zsh` or `completion.bash`\nconst OWN_SCRIPT = '\"[^\"]*completion\\\\.(?:zsh|bash)\"'\n// The line(s) under the marker, in every shape Workscribe has written\nconst GUARDED_ZSH = new RegExp(`^if \\\\[ -f ${OWN_SCRIPT} \\\\]; then ${ZSH_COMPINIT}; source ${OWN_SCRIPT}; fi$`)\nconst GUARDED_BASH = new RegExp(`^\\\\[ -f ${OWN_SCRIPT} \\\\] && source ${OWN_SCRIPT}$`)\nconst UNGUARDED_SOURCE = new RegExp(`^source ${OWN_SCRIPT}$`)\n\n/** The block for a shell; `file` is the generated completion script it sources. */\nexport function completionsBlock(shellName: string, file: string): string {\n const guardedSource =\n shellName === 'zsh'\n ? `if [ -f \"${file}\" ]; then ${ZSH_COMPINIT}; source \"${file}\"; fi`\n : `[ -f \"${file}\" ] && source \"${file}\"`\n return `${COMPLETIONS_MARKER}\\n${guardedSource}`\n}\n\n/** Lines of a block: `first` is the marker line, `last` the line that sources the script (inclusive). */\ninterface BlockLines {\n first: number\n last: number\n}\n\n/** A file's lines, compared without a Windows `\\r` but written back with it. */\ninterface RcLines {\n lines: string[]\n lineEnding: '' | '\\r'\n}\n\nfunction splitLines(content: string): RcLines {\n return { lines: content.split('\\n'), lineEnding: content.includes('\\r\\n') ? '\\r' : '' }\n}\n\nfunction bare(line: string | undefined): string {\n return (line ?? '').replace(/\\r$/, '')\n}\n\n/** How many lines after the marker belong to the block, or 0 if what follows isn't a Workscribe block. */\nfunction blockLengthAfterMarker(lines: string[], markerIndex: number): number {\n const next = bare(lines[markerIndex + 1])\n if (GUARDED_ZSH.test(next) || GUARDED_BASH.test(next) || UNGUARDED_SOURCE.test(next)) return 1\n if (next === ZSH_COMPINIT && UNGUARDED_SOURCE.test(bare(lines[markerIndex + 2]))) return 2\n return 0\n}\n\n/** Every Workscribe completions block — older versions of `init` could append more than one. */\nfunction findBlocks(lines: string[]): BlockLines[] {\n const blocks: BlockLines[] = []\n for (let index = 0; index < lines.length; index++) {\n if (bare(lines[index]) !== COMPLETIONS_MARKER) continue\n const length = blockLengthAfterMarker(lines, index)\n if (length === 0) continue\n blocks.push({ first: index, last: index + length })\n index += length\n }\n return blocks\n}\n\nfunction blockText(lines: string[], block: BlockLines): string {\n return lines\n .slice(block.first, block.last + 1)\n .map(bare)\n .join('\\n')\n}\n\nexport function hasCompletionsBlock(content: string): boolean {\n return findBlocks(splitLines(content).lines).length > 0\n}\n\n/** There's a block that isn't the current one (typically an unguarded block from an older version), or several. */\nexport function isCompletionsBlockOutdated(content: string, currentBlock: string): boolean {\n const { lines } = splitLines(content)\n const blocks = findBlocks(lines)\n if (blocks.length === 0) return false\n return blocks.length > 1 || blockText(lines, blocks[0]) !== currentBlock\n}\n\n/**\n * Rebuilds the file from its lines: `replacement` takes the place of the first block, the other blocks go — each\n * with the one blank line `installCompletions` put before it — and every other line stays exactly as it was.\n */\nfunction rebuild(content: string, replacement: string | null): string {\n const { lines, lineEnding } = splitLines(content)\n const blocks = findBlocks(lines)\n if (blocks.length === 0) return content\n const dropped = new Set<number>()\n blocks.forEach((block, blockIndex) => {\n const isReplaced = blockIndex === 0 && replacement !== null\n for (let index = block.first; index <= block.last; index++) dropped.add(index)\n if (!isReplaced && block.first > 0 && bare(lines[block.first - 1]) === '') dropped.add(block.first - 1)\n })\n const replacementLines = replacement === null ? [] : replacement.split('\\n').map((line) => line + lineEnding)\n return lines\n .flatMap((line, index) => {\n if (replacement !== null && index === blocks[0].first) return replacementLines\n return dropped.has(index) ? [] : [line]\n })\n .join('\\n')\n}\n\n/** Replaces the first block with `newBlock` and removes any duplicates. */\nexport function replaceCompletionsBlock(content: string, newBlock: string): string {\n return rebuild(content, newBlock)\n}\n\n/** Removes every block (and the blank line before each), leaving the rest of the file as it was. */\nexport function removeCompletionsBlock(content: string): string {\n return rebuild(content, null)\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'\nimport { backUpFile } from '../utils/backup'\nimport {\n COMPLETIONS_MARKER,\n completionsBlock,\n hasCompletionsBlock,\n isCompletionsBlockOutdated,\n removeCompletionsBlock,\n replaceCompletionsBlock,\n} from './completions-block'\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\n/** A shell and the rc file `init` writes its hook (and completions) into. */\nexport type ShellTarget = { name: string; rcFile: string }\n\n/** Backs up an rc file before editing it, never overwriting an earlier backup, and says where it went. */\nfunction backUp(rcFile: string): void {\n log.info(`Backed up ${rcFile} → ${path.basename(backUpFile(rcFile))}`)\n}\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 backUp(rcFile)\n fs.appendFileSync(rcFile, `\\n${hookContent}\\n`)\n}\n\nexport function updateHook(rcFile: string, hookContent: string): void {\n backUp(rcFile)\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 backUp(rcFile)\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 // Invoking node directly (rather than executing workscribe's own shebang)\n // bypasses the `--disable-warning=ExperimentalWarning` flag postbuild.js\n // bakes into dist/index.js's shebang — shebang flags only apply when the\n // OS execs the file via its shebang line, not when node is invoked\n // explicitly. Without repeating the flag here, every pinned-node-path\n // invocation (the default whenever a version manager is detected) leaks\n // the node:sqlite ExperimentalWarning to stderr.\n const pinnedInvocation = `\"${nodePath}\" --disable-warning=ExperimentalWarning \"${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: ShellTarget): 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(COMPLETIONS_MARKER)\n } catch {\n return false\n }\n}\n\nconst FISH_COMPLETIONS_FILE = path.join(FISH_COMPLETIONS_DIR, 'workscribe.fish')\n\nfunction completionScriptFile(shellName: string): string {\n return path.join(WORKSCRIBE_DIR, `completion.${shellName}`)\n}\n\nfunction readRcFile(rcFile: string): string | null {\n try {\n return fs.readFileSync(rcFile, 'utf-8')\n } catch {\n return null // a missing rc file simply has no completions block\n }\n}\n\n/** (Re)writes the completion script itself — safe to run on every `init`, so a deleted data folder is repaired. */\nexport function writeCompletionScript(shell: ShellTarget, commands: CompletionCommand[]): void {\n if (shell.name === 'fish') {\n fs.mkdirSync(FISH_COMPLETIONS_DIR, { recursive: true })\n fs.writeFileSync(FISH_COMPLETIONS_FILE, fishCompletion(commands), { mode: 0o644 })\n return\n }\n const script = shell.name === 'zsh' ? zshCompletion(commands) : bashCompletion(commands)\n fs.mkdirSync(WORKSCRIBE_DIR, { recursive: true })\n fs.writeFileSync(completionScriptFile(shell.name), script, { mode: 0o644 })\n}\n\nexport function installCompletions(shell: ShellTarget, commands: CompletionCommand[]): void {\n writeCompletionScript(shell, commands)\n // installCompletions can be called more than once (e.g. isCompletionsInstalled raced with a concurrent init).\n // The rcFile append must stay idempotent so repeated calls never grow duplicate blocks.\n if (shell.name !== 'fish' && !isCompletionsInstalled(shell)) {\n fs.appendFileSync(shell.rcFile, `\\n${completionsBlock(shell.name, completionScriptFile(shell.name))}\\n`)\n }\n}\n\n/** The rc file has a completions block from an older version — one that errors once its script is deleted. */\nexport function isCompletionsOutdated(shell: ShellTarget): boolean {\n if (shell.name === 'fish') return false // fish completions are a standalone file, not an rc-file line\n const content = readRcFile(shell.rcFile)\n return (\n content !== null &&\n isCompletionsBlockOutdated(content, completionsBlock(shell.name, completionScriptFile(shell.name)))\n )\n}\n\nexport function updateCompletions(shell: ShellTarget): void {\n const content = readRcFile(shell.rcFile)\n if (content === null || !hasCompletionsBlock(content)) return\n backUp(shell.rcFile)\n fs.writeFileSync(\n shell.rcFile,\n replaceCompletionsBlock(content, completionsBlock(shell.name, completionScriptFile(shell.name)))\n )\n}\n\n/** Removes the completions block from an rc file, if it has one. Returns whether anything was removed. */\nexport function removeCompletions(rcFile: string): boolean {\n const content = readRcFile(rcFile)\n if (content === null || !hasCompletionsBlock(content)) return false\n backUp(rcFile)\n fs.writeFileSync(rcFile, removeCompletionsBlock(content))\n return true\n}\n\n/** Removes the fish completion file, if present. Returns whether anything was removed. */\nexport function removeFishCompletions(): boolean {\n if (!fs.existsSync(FISH_COMPLETIONS_FILE)) return false\n fs.rmSync(FISH_COMPLETIONS_FILE, { force: true })\n return true\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","// The command strings Workscribe writes into ~/.claude/settings.json, and how to read them back. Pure.\n//\n// Every command is guarded: when the binary (or the Node it's pinned to) is gone — say the package was removed\n// without `workscribe uninstall` — the hook exits 0 silently instead of erroring on every prompt and tool call.\n// `_hook` itself never exits non-zero, so the trailing `|| true` only ever hides a missing binary or a crash.\n\n// Identifies a workscribe hook entry in any of its forms — legacy bare, pinned, guarded — since all contain it\nexport const HOOK_MARKER = '_hook --source claude-code'\n\nconst GUARD_SUFFIX = ' || true'\n// The `test -x \"<path>\" && ` guards in front of a pinned command\nconst LEADING_PATH_GUARDS = /^(?:test -x \"[^\"]*\" && )+/\nconst BARE_GUARD = 'command -v workscribe >/dev/null 2>&1 && '\n\n/**\n * The command for one hook. Pinned (node and script paths known at install time) when possible, so it's immune to\n * PATH and Node-version drift; bare (`workscribe …`) otherwise. `args` follow the binary, e.g. `_hook --source …`.\n */\nexport function buildHookCommand(options: { nodePath: string; binaryPath: string | null; args: string }): string {\n if (!options.binaryPath) return `${BARE_GUARD}workscribe ${options.args}${GUARD_SUFFIX}`\n const { nodePath, binaryPath, args } = options\n return `test -x \"${nodePath}\" && test -x \"${binaryPath}\" && \"${nodePath}\" \"${binaryPath}\" ${args}${GUARD_SUFFIX}`\n}\n\nfunction withoutLeadingGuards(command: string): string {\n return command.trimStart().replace(LEADING_PATH_GUARDS, '')\n}\n\n/**\n * Pinned: invokes an absolute path (a Node interpreter) rather than the bare `workscribe` string — immune to\n * PATH/Node-version drift between install time and whatever environment the hook fires in.\n */\nexport function isPinnedCommand(command: string): boolean {\n const invocation = withoutLeadingGuards(command)\n return invocation.startsWith('\"') || invocation.startsWith('/')\n}\n\n/** Guarded: does nothing, silently, when the binary is gone. */\nexport function isGuardedCommand(command: string): boolean {\n const trimmed = command.trim()\n const hasLeadingGuard = LEADING_PATH_GUARDS.test(trimmed) || trimmed.startsWith(BARE_GUARD)\n return hasLeadingGuard && trimmed.endsWith(GUARD_SUFFIX)\n}\n\n/** The Node interpreter a pinned command runs (`\"<node>\" \"<workscribe>\" …`), or null for a bare command. */\nexport function pinnedNodePath(command: string): string | null {\n return withoutLeadingGuards(command).match(/^\"([^\"]+)\"/)?.[1] ?? null\n}\n","import fs from 'fs'\nimport path from 'path'\nimport os from 'os'\nimport { execFileSync } from 'child_process'\nimport type { AIHookIntegration, HookUninstallOutcome } from './types'\nimport { isCommandInstalled } from './utils'\nimport { resolveWorkscribeBinary } from '../shell-hook'\nimport { backUpFile } from '../../utils/backup'\nimport { buildHookCommand, HOOK_MARKER, isGuardedCommand, isPinnedCommand, pinnedNodePath } from './claude-code-command'\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\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 * 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 /** Every Workscribe hook exits silently when the binary is gone (false for hooks from Workscribe ≤ 2.0.0). */\n guarded: boolean\n /** A pinned hook's Node interpreter no longer exists (e.g. removed by a version manager) — capture is off. */\n nodeMissing: boolean\n /** Only meaningful when installed && !pinned; null otherwise. */\n confirmedBroken: boolean | null\n}\n\nfunction isExecutable(filePath: string): boolean {\n try {\n fs.accessSync(filePath, fs.constants.X_OK)\n return true\n } catch {\n return false\n }\n}\n\nfunction allWorkscribeCommands(): string[] {\n const { postToolUse, userPromptSubmit } = findWorkscribeHookCommands(readSettings())\n return [...postToolUse, ...userPromptSubmit]\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 allCommands = allWorkscribeCommands()\n if (allCommands.length === 0) {\n return { installed: false, pinned: true, guarded: true, nodeMissing: false, confirmedBroken: null }\n }\n\n const guarded = allCommands.every(isGuardedCommand)\n const nodePaths = allCommands.map(pinnedNodePath).filter((nodePath): nodePath is string => nodePath !== null)\n const nodeMissing = nodePaths.some((nodePath) => !isExecutable(nodePath))\n if (allCommands.every(isPinnedCommand)) {\n return { installed: true, pinned: true, guarded, nodeMissing, confirmedBroken: null }\n }\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, guarded, nodeMissing, confirmedBroken }\n}\n\n/** Reads settings.json without forgiving a parse error — uninstall must never overwrite a file it couldn't read. */\nfunction readSettingsStrictly(): Record<string, unknown> | 'missing' | 'unreadable' {\n if (!fs.existsSync(CLAUDE_SETTINGS_PATH)) return 'missing'\n try {\n const parsed: unknown = JSON.parse(fs.readFileSync(CLAUDE_SETTINGS_PATH, 'utf-8'))\n return parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)\n ? (parsed as Record<string, unknown>)\n : 'unreadable'\n } catch {\n return 'unreadable'\n }\n}\n\n/** The hooks object with Workscribe's entries removed, empty event arrays dropped — or null if there were none. */\nfunction hooksWithoutWorkscribe(hooks: Record<string, unknown>): Record<string, unknown> | null {\n let removedAny = false\n const remaining: Record<string, unknown> = {}\n for (const [eventName, entries] of Object.entries(hooks)) {\n if (!Array.isArray(entries)) {\n remaining[eventName] = entries\n continue\n }\n const kept = withoutWorkscribeEntries(entries)\n if (commandsForEvent(hooks, eventName).length > 0) removedAny = true\n if (kept.length > 0) remaining[eventName] = kept\n }\n return removedAny ? remaining : null\n}\n\n/**\n * Both events have a Workscribe hook, and every one is pinned, guarded, and pinned to a Node.js that still exists.\n * The guard keeps a hook whose Node a version manager removed quiet — and so quietly broken — unless `init` sees it.\n */\nfunction isHookCurrent(): boolean {\n const { postToolUse, userPromptSubmit } = findWorkscribeHookCommands(readSettings())\n if (postToolUse.length === 0 || userPromptSubmit.length === 0) return false\n return [...postToolUse, ...userPromptSubmit].every((command) => {\n const nodePath = pinnedNodePath(command)\n return isPinnedCommand(command) && isGuardedCommand(command) && nodePath !== null && isExecutable(nodePath)\n })\n}\n\nexport const claudeCodeIntegration: AIHookIntegration = {\n displayName: 'Claude Code',\n\n isInstalled() {\n return isCommandInstalled('claude')\n },\n\n // \"Installed\" means a *current* hook is present, not just any workscribe hook — so `workscribe init` offers to\n // update a stale one (unpinned, unguarded, or pinned to a Node that's gone) through its outdated-hook prompt\n isHookInstalled() {\n return isHookCurrent()\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 binaryPath = resolveWorkscribeBinary()\n const command = (args: string) => buildHookCommand({ nodePath: process.execPath, binaryPath, args })\n\n settings.hooks = {\n ...existingHooks,\n PostToolUse: [\n ...existingPostToolUse,\n {\n matcher: 'Bash',\n hooks: [{ type: 'command', command: command(HOOK_MARKER), async: true }],\n },\n ],\n UserPromptSubmit: [\n ...existingUserPromptSubmit,\n {\n hooks: [\n {\n type: 'command',\n command: command(`${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 // Some workscribe hook is present, but not all of them are current (pinned and guarded) — including a\n // half-installed one where only PostToolUse or only UserPromptSubmit exists\n isHookOutdated() {\n return allWorkscribeCommands().length > 0 && !isHookCurrent()\n },\n\n uninstall(): HookUninstallOutcome {\n const settings = readSettingsStrictly()\n if (settings === 'missing') return 'not-installed'\n if (settings === 'unreadable') return 'unreadable'\n const hooks = settings.hooks\n if (hooks === null || typeof hooks !== 'object' || Array.isArray(hooks)) return 'not-installed'\n const remainingHooks = hooksWithoutWorkscribe(hooks as Record<string, unknown>)\n if (!remainingHooks) return 'not-installed'\n\n const updated: Record<string, unknown> = { ...settings, hooks: remainingHooks }\n if (Object.keys(remainingHooks).length === 0) delete updated.hooks\n backUpFile(CLAUDE_SETTINGS_PATH)\n fs.writeFileSync(CLAUDE_SETTINGS_PATH, JSON.stringify(updated, null, 2))\n return 'removed'\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\nexport const HIDDEN_COMMANDS = new Set(['_capture', '_hook'])\n\n// _capture/_hook fire on every shell command as a detached background process\n// that must never add latency — startup checks (update check, telemetry) skip\n// those outright rather than relying on a cache alone.\nexport function shouldRunStartupChecks(invokedCommand: string | undefined): boolean {\n if (invokedCommand === undefined) return true\n return !HIDDEN_COMMANDS.has(invokedCommand)\n}\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","/** Caches a single-argument lookup by its string key for the lifetime of the returned function. */\nexport function memoize<Value>(lookup: (key: string) => Value): (key: string) => Value {\n // Boxed so a cached null/undefined result is told apart from a missing entry\n const cache = new Map<string, { value: Value }>()\n return (key) => {\n const cached = cache.get(key)\n if (cached) return cached.value\n const value = lookup(key)\n cache.set(key, { value })\n return value\n }\n}\n","import type { SkillAgent } from './types'\n\n/** Folder name the skill is installed under, inside each agent's skills folder. */\nexport const SKILL_NAME = 'workscribe'\n\n/** Marker file that identifies a Workscribe-installed copy of the skill. */\nexport const MARKER_FILE = '.workscribe-skill.json'\n\n// Skills folders checked against each vendor's docs (2026-10-26). If a vendor moves its folder,\n// only this table needs to change.\nexport const SKILL_AGENTS: SkillAgent[] = [\n {\n id: 'claude-code',\n name: 'Claude Code',\n skillsFolder: '.claude/skills',\n commands: ['claude'],\n homeFolders: ['.claude'],\n vscodeExtensionPrefixes: [],\n docsUrl: 'https://code.claude.com/docs/en/skills',\n },\n {\n id: 'codex',\n name: 'Codex',\n skillsFolder: '.agents/skills',\n commands: ['codex'],\n homeFolders: ['.codex'],\n vscodeExtensionPrefixes: [],\n docsUrl: 'https://learn.chatgpt.com/docs/build-skills',\n },\n {\n id: 'copilot',\n name: 'GitHub Copilot',\n skillsFolder: '.agents/skills',\n commands: ['copilot'],\n homeFolders: ['.copilot'],\n vscodeExtensionPrefixes: ['github.copilot-chat'],\n docsUrl: 'https://docs.github.com/en/copilot/how-tos/copilot-cli/customize-copilot/add-skills',\n },\n {\n id: 'cursor',\n name: 'Cursor',\n skillsFolder: '.cursor/skills',\n commands: ['cursor', 'cursor-agent'],\n homeFolders: ['.cursor'],\n vscodeExtensionPrefixes: [],\n docsUrl: 'https://cursor.com/docs/skills',\n },\n]\n\nexport const SKILL_AGENT_IDS = SKILL_AGENTS.map((agent) => agent.id)\n","import fs from 'fs'\nimport os from 'os'\nimport path from 'path'\nimport { isCommandInstalled } from '../capture/hooks/utils'\nimport { memoize } from '../utils/memoize'\nimport { SKILL_AGENTS } from './agents'\nimport type { SkillAgent } from './types'\n\n/** The I/O detection needs — injected so tests can describe a machine without touching the real one. */\nexport interface DetectionEnvironment {\n homeDir: string\n isCommandInstalled: (command: string) => boolean\n pathExists: (absolutePath: string) => boolean\n listDirectory: (absolutePath: string) => string[]\n}\n\nexport function defaultDetectionEnvironment(): DetectionEnvironment {\n return {\n homeDir: os.homedir(),\n // `which` spawns a process, so each command is looked up at most once per run\n isCommandInstalled: memoize(isCommandInstalled),\n pathExists: (absolutePath) => fs.existsSync(absolutePath),\n listDirectory: (absolutePath) => {\n try {\n return fs.readdirSync(absolutePath)\n } catch {\n return [] // a missing extensions folder just means no extensions\n }\n },\n }\n}\n\nfunction hasHomeFolder(agent: SkillAgent, environment: DetectionEnvironment): boolean {\n return agent.homeFolders.some((folder) => environment.pathExists(path.join(environment.homeDir, folder)))\n}\n\nfunction hasVscodeExtension(agent: SkillAgent, environment: DetectionEnvironment): boolean {\n if (agent.vscodeExtensionPrefixes.length === 0) return false\n const extensions = environment.listDirectory(path.join(environment.homeDir, '.vscode', 'extensions'))\n return extensions.some((extension) => agent.vscodeExtensionPrefixes.some((prefix) => extension.startsWith(prefix)))\n}\n\n/** Folder signals are checked first; `which` is only spawned when none of them found the agent. */\nexport function isAgentPresent(agent: SkillAgent, environment: DetectionEnvironment): boolean {\n return (\n hasHomeFolder(agent, environment) ||\n hasVscodeExtension(agent, environment) ||\n agent.commands.some((command) => environment.isCommandInstalled(command))\n )\n}\n\nexport function detectAgents(environment: DetectionEnvironment = defaultDetectionEnvironment()): SkillAgent[] {\n return SKILL_AGENTS.filter((agent) => isAgentPresent(agent, environment))\n}\n","import type { InstallOutcome, SkillAgent, SkillInstallState, SkillMarker, SkillsFolderGroup } from './types'\n\n/** One entry per distinct skills folder, in registry order — Codex and Copilot share `.agents/skills`. */\nexport function groupBySkillsFolder(agents: SkillAgent[]): SkillsFolderGroup[] {\n const groups = new Map<string, SkillAgent[]>()\n for (const agent of agents) groups.set(agent.skillsFolder, [...(groups.get(agent.skillsFolder) ?? []), agent])\n return [...groups.entries()].map(([skillsFolder, groupAgents]) => ({ skillsFolder, agents: groupAgents }))\n}\n\n/**\n * Names the agents a folder serves, noting any other agent that reads the same folder — installing or\n * removing for Codex also changes it for GitHub Copilot, and the message should say so.\n */\nexport function describeFolderAgents(group: SkillsFolderGroup, allAgents: SkillAgent[]): string {\n const sharers = allAgents.filter(\n (agent) => agent.skillsFolder === group.skillsFolder && !group.agents.includes(agent)\n )\n const names = joinAgentNames(group.agents)\n return sharers.length === 0 ? names : `${names} (folder shared with ${joinAgentNames(sharers)})`\n}\n\n/** The result `init` can report without asking: up to date, or a folder it doesn't own. Null means ask. */\nexport function outcomeWithoutPrompt(state: SkillInstallState): InstallOutcome | null {\n if (state.kind === 'installed') return 'up-to-date'\n if (state.kind === 'not-ours') return 'skipped-not-ours'\n return null\n}\n\n/** \"Codex\", \"Codex and GitHub Copilot\", \"Claude Code, Codex and Cursor\". */\nexport function joinAgentNames(agents: SkillAgent[]): string {\n const names = agents.map((agent) => agent.name)\n if (names.length <= 1) return names[0] ?? ''\n return `${names.slice(0, -1).join(', ')} and ${names[names.length - 1]}`\n}\n\n/** What's in an agent's `workscribe` skill folder, judged by its marker. */\nexport function describeInstallState(input: {\n folderExists: boolean\n marker: SkillMarker | null\n currentVersion: string\n}): SkillInstallState {\n if (!input.folderExists) return { kind: 'not-installed' }\n if (!input.marker) return { kind: 'not-ours' }\n if (input.marker.version === input.currentVersion) return { kind: 'installed', version: input.marker.version }\n return { kind: 'outdated', version: input.marker.version }\n}\n","import fs from 'fs'\nimport path from 'path'\nimport { MARKER_FILE, SKILL_NAME } from './agents'\nimport { describeInstallState } from './state'\nimport type { InstallOutcome, InstallSkillOptions, SkillInstallState, SkillMarker, UninstallOutcome } from './types'\n\nfunction isSkillMarker(value: unknown): value is SkillMarker {\n const candidate = value as Partial<SkillMarker> | null\n return typeof candidate?.version === 'string' && typeof candidate?.installedAt === 'string'\n}\n\nfunction readMarker(skillDir: string): SkillMarker | null {\n try {\n const parsed: unknown = JSON.parse(fs.readFileSync(path.join(skillDir, MARKER_FILE), 'utf-8'))\n return isSkillMarker(parsed) ? parsed : null\n } catch {\n return null // no marker, or not ours to read — either way it isn't a Workscribe install\n }\n}\n\n/** State of the Workscribe skill inside one agent skills folder (e.g. `~/.claude/skills`). */\nexport function readInstallState(skillsFolder: string, currentVersion: string): SkillInstallState {\n const skillDir = path.join(skillsFolder, SKILL_NAME)\n return describeInstallState({\n folderExists: fs.existsSync(skillDir),\n marker: readMarker(skillDir),\n currentVersion,\n })\n}\n\nfunction copyDirectory(from: string, to: string): void {\n fs.mkdirSync(to, { recursive: true })\n for (const entry of fs.readdirSync(from, { withFileTypes: true })) {\n const source = path.join(from, entry.name)\n const destination = path.join(to, entry.name)\n if (entry.isDirectory()) copyDirectory(source, destination)\n else fs.copyFileSync(source, destination)\n }\n}\n\n/**\n * Swaps a fully prepared copy into place: move any existing copy aside, rename the new one in, then\n * delete the old one — or put it back if the rename fails. A plain rename over a non-empty folder\n * fails on POSIX, and this way an interrupted install never leaves a half-written skill.\n */\nfunction swapInto(skillDir: string, preparedDir: string): void {\n const previousDir = path.join(path.dirname(skillDir), `.${SKILL_NAME}.old-${process.pid}`)\n fs.rmSync(previousDir, { recursive: true, force: true }) // left behind by a run that was killed\n const hadPrevious = fs.existsSync(skillDir)\n if (hadPrevious) fs.renameSync(skillDir, previousDir)\n try {\n fs.renameSync(preparedDir, skillDir)\n } catch (error) {\n if (hadPrevious) fs.renameSync(previousDir, skillDir)\n throw error\n }\n if (hadPrevious) fs.rmSync(previousDir, { recursive: true, force: true })\n}\n\nexport function installSkill(options: InstallSkillOptions): InstallOutcome {\n const state = readInstallState(options.skillsFolder, options.version)\n if (state.kind === 'installed') return 'up-to-date'\n if (state.kind === 'not-ours' && !options.force) return 'skipped-not-ours'\n\n fs.mkdirSync(options.skillsFolder, { recursive: true })\n const preparedDir = path.join(options.skillsFolder, `.${SKILL_NAME}.tmp-${process.pid}`)\n fs.rmSync(preparedDir, { recursive: true, force: true }) // left behind by a run that was killed\n try {\n copyDirectory(options.sourceDir, preparedDir)\n const marker: SkillMarker = { version: options.version, installedAt: new Date().toISOString() }\n fs.writeFileSync(path.join(preparedDir, MARKER_FILE), JSON.stringify(marker, null, 2))\n swapInto(path.join(options.skillsFolder, SKILL_NAME), preparedDir)\n } finally {\n fs.rmSync(preparedDir, { recursive: true, force: true })\n }\n return state.kind === 'not-installed' ? 'installed' : 'updated'\n}\n\n/** Removes the skill only if Workscribe installed it — a user's own `workscribe` skill is left alone. */\nexport function uninstallSkill(skillsFolder: string): UninstallOutcome {\n const skillDir = path.join(skillsFolder, SKILL_NAME)\n if (!fs.existsSync(skillDir)) return 'not-installed'\n if (!readMarker(skillDir)) return 'skipped-not-ours'\n fs.rmSync(skillDir, { recursive: true, force: true })\n return 'removed'\n}\n","import fs from 'fs'\nimport path from 'path'\nimport { SKILL_NAME } from './agents'\n\nconst SKILL_ENTRY_FILE = 'SKILL.md'\n\n/**\n * Where the skill shipped in this npm package lives. The bundle runs from `dist/`, so it's one level\n * up; the TypeScript sources run from `src/<folder>/`, so it's two. The first with a SKILL.md wins.\n */\nexport function packagedSkillCandidates(fromDirectory: string): string[] {\n return [\n path.join(fromDirectory, '..', 'skills', SKILL_NAME),\n path.join(fromDirectory, '..', '..', 'skills', SKILL_NAME),\n ]\n}\n\nexport function resolvePackagedSkillDir(fromDirectory: string = __dirname): string {\n const found = packagedSkillCandidates(fromDirectory).find((candidate) =>\n fs.existsSync(path.join(candidate, SKILL_ENTRY_FILE))\n )\n if (!found) {\n throw new Error(\n 'The Workscribe skill files are missing from this install. Reinstall it: npm install -g @workscribe/cli'\n )\n }\n return found\n}\n","// Friendly wording for skill install results and status, shared by `workscribe skill`, `init` and `status`.\nimport type { InstallOutcome, SkillInstallState, UninstallOutcome } from './types'\n\nexport type MessageLevel = 'success' | 'info' | 'warn'\n\nexport interface Message {\n level: MessageLevel\n text: string\n}\n\n/** `/Users/dev/.claude/skills` → `~/.claude/skills`, so paths read the way users type them. */\nexport function displayPath(absolutePath: string, homeDir: string): string {\n return absolutePath.startsWith(homeDir) ? `~${absolutePath.slice(homeDir.length)}` : absolutePath\n}\n\nexport function describeInstallOutcome(input: {\n outcome: InstallOutcome\n agents: string\n location: string\n version: string\n}): Message {\n switch (input.outcome) {\n case 'installed':\n return { level: 'success', text: `Installed the Workscribe skill for ${input.agents} (${input.location})` }\n case 'updated':\n return { level: 'success', text: `Updated the Workscribe skill for ${input.agents} to ${input.version}` }\n case 'up-to-date':\n return { level: 'info', text: `The Workscribe skill is already up to date for ${input.agents}` }\n case 'skipped-not-ours':\n return {\n level: 'warn',\n text:\n `Skipped ${input.agents} — ${input.location} already holds a workscribe skill that Workscribe didn't install. ` +\n 'Run workscribe skill install --force to replace it.',\n }\n }\n}\n\nexport function describeUninstallOutcome(input: {\n outcome: UninstallOutcome\n agents: string\n location: string\n}): Message {\n switch (input.outcome) {\n case 'removed':\n return { level: 'success', text: `Removed the Workscribe skill from ${input.agents} (${input.location})` }\n case 'not-installed':\n return { level: 'info', text: `The Workscribe skill isn't installed for ${input.agents}` }\n case 'skipped-not-ours':\n return {\n level: 'warn',\n text: `Left ${input.location} alone — that workscribe skill wasn't installed by Workscribe.`,\n }\n }\n}\n\n/** One status phrase per state, with the command that fixes it when something needs doing. */\nexport function describeSkillStatus(state: SkillInstallState, currentVersion: string): Message {\n switch (state.kind) {\n case 'installed':\n return { level: 'success', text: `installed (${state.version})` }\n case 'outdated':\n return {\n level: 'warn',\n text: `outdated (${state.version}; this CLI is ${currentVersion}) — run workscribe skill install`,\n }\n case 'not-installed':\n return { level: 'info', text: 'not installed — run workscribe skill install' }\n case 'not-ours':\n return {\n level: 'warn',\n text: 'a different workscribe skill is there — run workscribe skill install --force to replace it',\n }\n }\n}\n\n/** The reason from anything thrown — fs errors carry useful text like \"EACCES: permission denied\". */\nexport function reasonOf(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n\nexport function describeInstallFailure(input: { agents: string; location: string; error: unknown }): Message {\n return {\n level: 'warn',\n text:\n `Couldn't install the Workscribe skill for ${input.agents} (${reasonOf(input.error)}). ` +\n `Check you can write to ${input.location}, then run: workscribe skill install`,\n }\n}\n\nexport function describeUninstallFailure(input: { agents: string; location: string; error: unknown }): Message {\n return {\n level: 'warn',\n text:\n `Couldn't remove the Workscribe skill for ${input.agents} (${reasonOf(input.error)}). ` +\n `Delete it yourself: rm -rf ${input.location}`,\n }\n}\n\nexport const AFTER_INSTALL_HINT =\n 'Restart any agent that is already open, then ask it to \"summarize my work today\" (or type /workscribe in Claude Code).'\n","// Install, remove and report the skill one skills folder at a time, with friendly messages. Shared by\n// `workscribe skill`, `init`, `status` and `uninstall`; a failure in one folder is reported, never thrown,\n// so the rest of those commands carries on.\nimport os from 'os'\nimport path from 'path'\nimport chalk from 'chalk'\nimport { log } from '../utils/logger'\nimport { SKILL_AGENTS, SKILL_NAME } from './agents'\nimport { installSkill, readInstallState, uninstallSkill } from './installer'\nimport {\n describeInstallFailure,\n describeInstallOutcome,\n describeSkillStatus,\n describeUninstallFailure,\n describeUninstallOutcome,\n displayPath,\n type Message,\n type MessageLevel,\n} from './report'\nimport { describeFolderAgents, groupBySkillsFolder } from './state'\nimport type { SkillAgent, SkillsFolderGroup } from './types'\n\ndeclare const __WORKSCRIBE_VERSION__: string\n\n/** Width of the agent-name column in `skill status` and `workscribe status`. */\nexport const AGENT_NAME_COLUMN_WIDTH = 16\n\nconst STATUS_COLOURS: Record<MessageLevel, (text: string) => string> = {\n success: chalk.green,\n warn: chalk.yellow,\n info: chalk.dim,\n}\n\n/** Where a group's skill lives, and how messages should name the agents it serves. */\nexport interface FolderTarget {\n skillsFolder: string\n location: string\n agents: string\n}\n\nexport function describeTarget(group: SkillsFolderGroup, homeDir: string = os.homedir()): FolderTarget {\n const skillsFolder = path.join(homeDir, group.skillsFolder)\n return {\n skillsFolder,\n location: displayPath(path.join(skillsFolder, SKILL_NAME), homeDir),\n agents: describeFolderAgents(group, SKILL_AGENTS),\n }\n}\n\nexport function printMessage(message: Message): void {\n log[message.level](message.text)\n}\n\nexport function installIntoFolder(options: { target: FolderTarget; sourceDir: string; force?: boolean }): Message {\n const { target } = options\n try {\n const outcome = installSkill({\n sourceDir: options.sourceDir,\n skillsFolder: target.skillsFolder,\n version: __WORKSCRIBE_VERSION__,\n force: options.force,\n })\n return describeInstallOutcome({ ...target, outcome, version: __WORKSCRIBE_VERSION__ })\n } catch (error) {\n return describeInstallFailure({ ...target, error })\n }\n}\n\n/**\n * Removes Workscribe-installed copies from each agent's skills folder. `workscribe uninstall` passes\n * `reportMissing: false` so folders that never had the skill don't add noise.\n */\nexport function removeSkills(agents: SkillAgent[], options: { reportMissing: boolean }): void {\n for (const group of groupBySkillsFolder(agents)) {\n const target = describeTarget(group)\n try {\n const outcome = uninstallSkill(target.skillsFolder)\n if (outcome === 'not-installed' && !options.reportMissing) continue\n printMessage(describeUninstallOutcome({ ...target, outcome }))\n } catch (error) {\n printMessage(describeUninstallFailure({ ...target, error }))\n }\n }\n}\n\n/** \"Claude Code installed (2.0.0) ~/.claude/skills/workscribe\" */\nexport function formatAgentSkillLine(agent: SkillAgent, homeDir: string = os.homedir()): string {\n const location = displayPath(path.join(homeDir, agent.skillsFolder, SKILL_NAME), homeDir)\n const installState = readInstallState(path.join(homeDir, agent.skillsFolder), __WORKSCRIBE_VERSION__)\n const status = describeSkillStatus(installState, __WORKSCRIBE_VERSION__)\n return `${agent.name.padEnd(AGENT_NAME_COLUMN_WIDTH)} ${STATUS_COLOURS[status.level](status.text)} ${chalk.dim(location)}`\n}\n\nexport function formatUndetectedAgentLine(agent: SkillAgent): string {\n return `${agent.name.padEnd(AGENT_NAME_COLUMN_WIDTH)} ${chalk.dim('not detected')}`\n}\n","// Workscribe 2.0 removed AI providers (cloud and Ollama). These helpers spot 1.x settings so users hear about\n// it once per run, can't set them again by accident, and can have them (and any stored API key) removed.\nimport type { WorkscribeConfig } from '../config'\n\n/** The only `summary.engine` value 2.0 still means — setting it is harmless, so it isn't a leftover. */\nexport const TEMPLATE_ENGINE = 'template'\n\nconst LEGACY_AI_FIELDS = ['provider', 'apiKey', 'model', 'baseUrl'] as const\n\nconst REMOVED_HEADLINE = 'AI providers were removed in Workscribe 2.0 — summaries now use the offline template engine.'\n\nconst SKILL_HINT =\n 'For AI-written summaries, install the Workscribe skill and ask your coding agent:\\n workscribe skill install'\n\n/** Why `config set` refuses `ai.*` and `summary.engine`, and what to do instead. */\nexport const REMOVED_AI_SETTING_MESSAGE = `${REMOVED_HEADLINE}\\n${SKILL_HINT}`\n\nexport function hasLegacyAiSettings(config: WorkscribeConfig): boolean {\n const hasAiField = LEGACY_AI_FIELDS.some((field) => Boolean(config.ai?.[field]))\n const engine = config.summary?.engine\n return hasAiField || (engine !== undefined && engine !== TEMPLATE_ENGINE)\n}\n\n/** The once-per-run notice for a 1.x config, or null when there's nothing left over. `configPath` is shown as-is. */\nexport function describeLegacyAiSettings(config: WorkscribeConfig, configPath: string): string | null {\n if (!hasLegacyAiSettings(config)) return null\n return (\n `${REMOVED_HEADLINE}\\n${SKILL_HINT}\\n` +\n `Your old AI settings (including any API key) are still in ${configPath}. To remove them, run:\\n workscribe init`\n )\n}\n\n/** `ai`, `ai.<anything>`, `summary.engine` and anything under it, in any case — settings `config set` refuses. */\nexport function isRemovedAiSetting(key: string): boolean {\n const normalizedKey = key.toLowerCase()\n return ['ai', 'summary.engine'].some(\n (removed) => normalizedKey === removed || normalizedKey.startsWith(`${removed}.`)\n )\n}\n\n/** A copy of the config without the 1.x AI settings — what `init` saves when the user agrees to remove them. */\nexport function withoutLegacyAiSettings(config: WorkscribeConfig): WorkscribeConfig {\n const cleaned = structuredClone(config)\n delete cleaned.ai\n delete cleaned.summary.engine\n return cleaned\n}\n","import prompts from 'prompts'\nimport { log } from '../utils/logger'\nimport { writeConfig, type WorkscribeConfig } from '../config'\nimport { hasLegacyAiSettings, withoutLegacyAiSettings } from '../summary/legacy-ai'\n\n/** Part of `init`: 2.0 removed AI providers, so offer to delete the 1.x settings — they can include a stored API key. */\nexport async function offerLegacyAiCleanup(config: WorkscribeConfig): Promise<WorkscribeConfig> {\n if (!hasLegacyAiSettings(config)) return config\n log.plain('')\n const { removeLegacyAi } = await prompts({\n type: 'confirm',\n name: 'removeLegacyAi',\n message:\n 'Your config has AI provider settings from Workscribe 1.x (including any API key) that 2.0 no longer uses. Remove them?',\n initial: true,\n })\n if (!removeLegacyAi) {\n log.info('Kept the old AI settings — they are ignored, and workscribe init can remove them later')\n return config\n }\n const cleaned = withoutLegacyAiSettings(config)\n writeConfig(cleaned)\n log.success('Removed the old AI provider settings from your config')\n return cleaned\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, ensureInstallId, WorkscribeConfig } from '../config'\nimport { detectProfilesForDirectory } from '../profiles/loader'\nimport { installProfile, cacheManifest } from '../profiles/fetcher'\nimport { getDb } from '../db'\nimport { log } from '../utils/logger'\nimport { loadAIToolRegistry } from '../config/registry'\nimport {\n isHookInstalled,\n isHookOutdated,\n installHook,\n updateHook,\n isCompletionsInstalled,\n installCompletions,\n isCompletionsOutdated,\n updateCompletions,\n type ShellTarget,\n writeCompletionScript,\n resolveWorkscribeBinary,\n injectBinaryPath,\n} from '../capture/shell-hook'\nimport { AI_HOOK_INTEGRATIONS } from '../capture/hooks'\nimport { getPublicCommands } from './completions'\nimport { detectAgents } from '../skills/detect'\nimport { readInstallState } from '../skills/installer'\nimport { resolvePackagedSkillDir } from '../skills/package-path'\nimport { describeInstallOutcome, reasonOf } from '../skills/report'\nimport { groupBySkillsFolder, outcomeWithoutPrompt } from '../skills/state'\nimport { describeTarget, installIntoFolder, printMessage } from '../skills/actions'\nimport { offerLegacyAiCleanup } from './legacy-ai-cleanup'\nimport type { SkillsFolderGroup } from '../skills/types'\n\ndeclare const __WORKSCRIBE_VERSION__: string\n\ntype Shell = ShellTarget\n\nconst TOTAL_STEPS = 5\n\nfunction detectShell(): Shell | 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\n// ── Step 1: Data directories ──────────────────────────────────────────────\nfunction runDataDirectoriesStep(): void {\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\n// ── Step 2: Database ──────────────────────────────────────────────────────\nasync function initDatabaseAndConfig(): Promise<WorkscribeConfig> {\n step(2, TOTAL_STEPS, 'Initialising database')\n const config = readConfig()\n getDb()\n log.success('Database ready')\n return offerLegacyAiCleanup(config)\n}\n\n// ── Telemetry (part of setup, no separate step) ────────────────────────────\nasync function runTelemetryStep(config: WorkscribeConfig): Promise<void> {\n log.plain('')\n log.plain(chalk.dim(' Workscribe can send anonymous install stats: a random install ID,'))\n log.plain(chalk.dim(' CLI version, OS platform, and Node.js version. No command, event, or'))\n log.plain(chalk.dim(' summary data is ever sent. Opt out anytime:'))\n log.plain(chalk.dim(' workscribe config set telemetry.enabled false'))\n log.plain('')\n const { telemetryEnabled } = await prompts({\n type: 'confirm',\n name: 'telemetryEnabled',\n message: 'Send anonymous install stats?',\n initial: true,\n })\n config.telemetry.enabled = telemetryEnabled\n config.telemetry.installId = ensureInstallId(config)\n}\n\n// ── Step 3: Shell hook + completions ──────────────────────────────────────\nasync function runShellHookStep(program: Command): Promise<Shell | null> {\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 return null\n }\n\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 return shell\n }\n\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 — or repair: refresh the script, and guard an older unguarded rc block\n if (isCompletionsInstalled(shell)) {\n await refreshCompletions(shell, program)\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 return shell\n}\n\nasync function refreshCompletions(shell: Shell, program: Command): Promise<void> {\n try {\n writeCompletionScript(shell, getPublicCommands(program))\n } catch (error) {\n log.warn(`Could not refresh shell completions: ${(error as Error).message}`)\n }\n if (!isCompletionsOutdated(shell)) {\n log.info('Shell completions already installed')\n return\n }\n const { updateShellCompletions } = await prompts({\n type: 'confirm',\n name: 'updateShellCompletions',\n message: `Shell completions in ${shell.rcFile} are outdated (they error in new terminals if Workscribe is removed). Update?`,\n initial: true,\n })\n if (!updateShellCompletions) {\n log.info('Shell completions update skipped')\n return\n }\n updateCompletions(shell)\n log.success(`Shell completions updated in ${shell.rcFile}`)\n}\n\n// ── Step 4: AI tools ──────────────────────────────────────────────────────\nasync function runAIToolsStep(): Promise<void> {\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 return\n }\n\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 if (integration.isHookOutdated?.()) {\n // You opted in when you first installed it, so updating it defaults to yes\n const { updateAiHook } = await prompts({\n type: 'confirm',\n name: 'updateAiHook',\n message: `${integration.displayName} session hook is outdated. Update?`,\n initial: true,\n })\n if (updateAiHook) {\n integration.install()\n log.success(`${integration.displayName} session hook updated`)\n } else {\n log.info(`${integration.displayName} hook update skipped — re-run workscribe init to update later`)\n }\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// ── Step 5: Agent skill ───────────────────────────────────────────────────\nasync function offerSkillInstall(group: SkillsFolderGroup, sourceDir: string): Promise<void> {\n const target = describeTarget(group)\n const state = readInstallState(target.skillsFolder, __WORKSCRIBE_VERSION__)\n const knownOutcome = outcomeWithoutPrompt(state)\n if (knownOutcome) {\n printMessage(describeInstallOutcome({ ...target, outcome: knownOutcome, version: __WORKSCRIBE_VERSION__ }))\n return\n }\n\n const { installSkill: shouldInstall } = await prompts({\n type: 'confirm',\n name: 'installSkill',\n message: `${state.kind === 'outdated' ? 'Update' : 'Install'} the Workscribe skill for ${target.agents}? Lets ${target.agents} summarize your work when you ask`,\n initial: true,\n })\n if (!shouldInstall) {\n log.info(`Skill skipped for ${target.agents} — run workscribe skill install any time`)\n return\n }\n printMessage(installIntoFolder({ target, sourceDir }))\n}\n\nasync function runAgentSkillStep(): Promise<void> {\n step(5, TOTAL_STEPS, 'Installing the Workscribe agent skill')\n\n const agents = detectAgents()\n if (agents.length === 0) {\n log.info('No coding agents detected — run workscribe skill install after installing one')\n return\n }\n\n let sourceDir: string\n try {\n sourceDir = resolvePackagedSkillDir()\n } catch (error) {\n log.warn(reasonOf(error)) // setup can carry on; the skill is optional\n return\n }\n for (const group of groupBySkillsFolder(agents)) {\n await offerSkillInstall(group, sourceDir)\n }\n}\n\n// Profile detection (part of environment scan, no separate step)\nasync function runProfileDetectionStep(config: WorkscribeConfig): Promise<void> {\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\n// ── What to do next ───────────────────────────────────────────────────────\nfunction printNextSteps(shell: Shell | null): void {\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 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(` For AI-written summaries, ask your coding agent to \"summarize my work today\"`)\n log.plain(` ${chalk.dim('(needs the Workscribe skill: workscribe skill install)')}`)\n log.plain('')\n log.plain(` Check capture is working:`)\n log.plain(` ${chalk.cyan('workscribe status')}`)\n\n log.plain('')\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 log.plain(chalk.bold('\\n Workscribe — Developer Work Journal\\n'))\n\n runDataDirectoriesStep()\n const config = await initDatabaseAndConfig()\n await runTelemetryStep(config)\n const shell = await runShellHookStep(program)\n await runAIToolsStep()\n await runAgentSkillStep()\n await runProfileDetectionStep(config)\n\n if (!fs.existsSync(CONFIG_PATH)) {\n writeConfig(config)\n }\n\n printNextSteps(shell)\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/** The local YYYY-MM-DD an ISO timestamp falls on — the same day rule sessions are grouped by. */\nexport function localDateOf(isoString: string): string {\n return localDateStr(new Date(isoString))\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","import os from 'os'\nimport { log } from '../utils/logger'\nimport { CONFIG_PATH } from '../utils/paths'\nimport { describeLegacyAiSettings } from '../summary/legacy-ai'\nimport { displayPath } from '../skills/report'\nimport type { WorkscribeConfig } from '../config'\n\n/** Tells a 1.x user, once per run, that their AI provider settings no longer do anything (stderr, so JSON output stays clean). */\nexport function printLegacyAiNotice(config: WorkscribeConfig): void {\n const notice = describeLegacyAiSettings(config, displayPath(CONFIG_PATH, os.homedir()))\n if (notice) log.notice(notice)\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'\nimport { detectAgents } from '../skills/detect'\nimport { formatAgentSkillLine } from '../skills/actions'\nimport { printLegacyAiNotice } from './notices'\n\n// Labelled on the first agent's row only, like the other status sections\nconst AGENT_SKILL_LABEL = 'Agent skill'\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 printLegacyAiNotice(config)\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 const agents = detectAgents()\n const skillHint = agents.length > 0 ? ' · AI-written ones via the agent skill below' : ''\n log.plain(` Summaries ${chalk.cyan('template')} ${chalk.dim(`(offline)${skillHint}`)}`)\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 agents.forEach((agent, index) => {\n const label = index === 0 ? AGENT_SKILL_LABEL : ''\n log.plain(` ${label.padEnd(AGENT_SKILL_LABEL.length)} ${formatAgentSkillLine(agent)}`)\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 } else if (hookHealth.installed && hookHealth.nodeMissing) {\n log.plain('')\n log.plain(\n ` ${chalk.yellow('⚠')} The Node.js version the Claude Code hook uses is gone — Claude Code activity is not being captured.`\n )\n log.plain(chalk.dim(' Run workscribe init to repair it'))\n } else if (hookHealth.installed && !hookHealth.guarded) {\n log.plain('')\n log.plain(\n ` ${chalk.yellow('⚠')} Claude Code hook is from an older version — it will show errors in Claude Code if Workscribe is ever removed.`\n )\n log.plain(chalk.dim(' Run workscribe init to update 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 os from 'os'\nimport path from 'path'\nimport { formatDate } from '../utils/format'\nimport type { DaySummaryPayload, EventPayload, SessionPayload } from '../ai/types'\nimport type { EventRow } from '../db/types'\nimport type { Session } from '../sessions/detector'\nimport type { WorkscribeConfig } from '../config'\n\n/** What sessionLocation needs to name a session that isn't in a git repo. */\nexport interface LocationContext {\n projects: Record<string, string>\n homeDir: string\n}\n\nexport function locationContextFrom(config: Pick<WorkscribeConfig, 'projects'>): LocationContext {\n return { projects: config.projects ?? {}, homeDir: os.homedir() }\n}\n\nconst DEFAULT_LOCATION_CONTEXT: LocationContext = { projects: {}, homeDir: os.homedir() }\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\n// Metadata is best-effort context for the summary — a corrupt or non-object row must not fail it\nfunction parseMetadata(raw: string | null): Record<string, unknown> {\n if (!raw) return {}\n try {\n const parsed: unknown = JSON.parse(raw)\n return isPlainObject(parsed) ? parsed : {}\n } catch {\n return {}\n }\n}\n\nexport function eventRowToPayload(row: EventRow): EventPayload {\n const metadata = parseMetadata(row.metadata)\n const payload: EventPayload = {\n category: row.category,\n metadata,\n exitCode: row.exit_code,\n durationMs: row.duration_ms,\n ...(row.source ? { source: row.source } : {}),\n }\n if (row.category !== 'other' || typeof metadata.hint !== 'string') return payload\n\n // Unclassified commands carry their raw hint separately so the prompt can show it on its own\n const { hint, tool: _tool, ...rest } = metadata\n return { ...payload, hint, metadata: rest }\n}\n\nfunction mostFrequentCwdOf(events: EventRow[]): string | null {\n const counts = new Map<string, number>()\n for (const event of events) counts.set(event.cwd, (counts.get(event.cwd) ?? 0) + 1)\n let best: string | null = null\n for (const [cwd, count] of counts) {\n if (best === null || count > (counts.get(best) ?? 0)) best = cwd\n }\n return best\n}\n\n/** The directory most of a session's events ran in, or null for a session with no events. */\nexport function mostFrequentCwd(session: Session): string | null {\n return mostFrequentCwdOf(session.events)\n}\n\n/**\n * A directory inside the session's repo, for git lookups. Agents often run `cd repo && …` from a\n * parent directory that isn't a repo, so the most-used directory overall can miss the repo entirely.\n */\nexport function repoCwd(session: Session): string | null {\n if (!session.repoName) return mostFrequentCwd(session)\n return mostFrequentCwdOf(session.events.filter((event) => event.repo_name === session.repoName))\n}\n\nfunction homeRelative(directory: string, homeDir: string): string {\n if (directory === homeDir) return '~'\n if (directory.startsWith(homeDir + path.sep)) return `~${directory.slice(homeDir.length)}`\n return directory\n}\n\n/**\n * The name a session is shown under: its repo, or — for work outside any git repo — the directory\n * most of its commands ran in (a config.projects name if one is set, else the home-relative path),\n * so the user can always tell where the work happened.\n */\nexport function sessionLocation(session: Session, context: LocationContext = DEFAULT_LOCATION_CONTEXT): string | null {\n if (session.repoName) return session.repoName\n const cwd = mostFrequentCwd(session)\n if (!cwd) return null\n return context.projects[cwd] ?? homeRelative(cwd, context.homeDir)\n}\n\nexport function sessionToPayload(\n session: Session,\n date: string,\n context: LocationContext = DEFAULT_LOCATION_CONTEXT\n): SessionPayload {\n return {\n date,\n project: sessionLocation(session, context),\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\nexport function buildDayPayload(\n date: string,\n sessions: Session[],\n context: LocationContext = DEFAULT_LOCATION_CONTEXT\n): DaySummaryPayload {\n return { date, sessions: sessions.map((session) => sessionToPayload(session, date, context)) }\n}\n","import type { StoredEngine } from '../ai/engine'\nimport type { SessionSummaryRow } from '../db/types'\n\n/** Engine name for summaries migrated from the 1.x `sessions.summary` column (written by a provider or Ollama). */\nexport const LEGACY_ENGINE = 'legacy' satisfies StoredEngine\n\n/** Engine name for summaries the Workscribe agent skill saved with `sessions summary set`. */\nexport const SKILL_ENGINE = 'skill' satisfies StoredEngine\n\n// Higher wins when picking what to show: richer sources first. Template rows rank 0 — templates are\n// rendered live, so any stored copy is a stale leftover and must never beat a fresh render.\nconst ENGINE_RANK: Record<StoredEngine, number> = { skill: 3, ollama: 2, provider: 2, legacy: 2, template: 0 }\n\n/** Summaries a 1.x AI provider or Ollama wrote. 2.0 no longer writes these, but still shows them for their sessions. */\nconst LEGACY_AI_ENGINES = new Set<string>(['provider', 'ollama', LEGACY_ENGINE])\n\n/** Identifies a session across rebuilds. Must match SESSION_KEY_SQL in migration 005. */\nexport function sessionKey(repoName: string | null, startedAt: string): string {\n return `${repoName ?? ''}|${startedAt}`\n}\n\nexport interface ParsedSessionKey {\n repoName: string | null\n startedAt: string\n}\n\n/** Reverses sessionKey(). Null for a malformed key: no `|`, or a start that isn't a timestamp. */\nexport function parseSessionKey(key: string): ParsedSessionKey | null {\n const separator = key.lastIndexOf('|')\n if (separator === -1) return null\n const startedAt = key.slice(separator + 1)\n if (startedAt === '' || Number.isNaN(new Date(startedAt).getTime())) return null\n const repoName = key.slice(0, separator)\n return { repoName: repoName === '' ? null : repoName, startedAt }\n}\n\nfunction newestFirst(first: SessionSummaryRow, second: SessionSummaryRow): number {\n return second.created_at.localeCompare(first.created_at)\n}\n\nexport interface SavedSummary {\n text: string\n fromSkill: boolean\n}\n\n/**\n * What `workscribe summary` can show for a session instead of rendering the template: a summary the agent\n * skill saved wins (it was written with more context), else one a 1.x AI provider wrote for that session.\n */\nexport function pickSavedSummary(rows: SessionSummaryRow[]): SavedSummary | null {\n const [newestSkill] = rows.filter((row) => row.engine === SKILL_ENGINE).sort(newestFirst)\n if (newestSkill) return { text: newestSkill.text, fromSkill: true }\n const [newestLegacy] = rows.filter((row) => LEGACY_AI_ENGINES.has(row.engine)).sort(newestFirst)\n return newestLegacy ? { text: newestLegacy.text, fromSkill: false } : null\n}\n\n/** The best stored summary for a session regardless of the configured engine (used by `context`). */\nexport function pickBestSummary(rows: SessionSummaryRow[]): string | null {\n // Rows come from the DB, so an engine name this build doesn't know is ignored like a template row\n const rank = (row: SessionSummaryRow): number => ENGINE_RANK[row.engine as StoredEngine] ?? 0\n const [best] = rows\n .filter((row) => rank(row) > 0)\n .sort((first, second) => rank(second) - rank(first) || newestFirst(first, second))\n return best?.text ?? null\n}\n","/**\n * Version of the `--json` contract read by coding agents and other tools. Fields may be added within a\n * version; renaming, removing or retyping a field bumps it. Tests pin the key sets.\n */\nexport const SCHEMA_VERSION = 1\n","import { eventRowToPayload } from '../payload'\nimport { buildExcludedSet } from '../exclusions'\nimport type { EventRow } from '../../db/types'\nimport type { GitCommit } from '../git-commits'\nimport type { CommitJson } from './types'\n\n/** Events the contract reports: the AI engines' exclusions apply, and notes go to `notes` instead. */\nexport function contractEvents(rows: EventRow[], includeCategories: string[]): EventRow[] {\n const excluded = buildExcludedSet(includeCategories)\n return rows.filter((row) => row.category !== 'note' && !excluded.has(row.category))\n}\n\nexport function collectNotes(rows: EventRow[]): string[] {\n return rows.flatMap((row) => {\n if (row.category !== 'note') return []\n const { text } = eventRowToPayload(row).metadata\n return typeof text === 'string' && text !== '' ? [text] : []\n })\n}\n\nfunction isFailedCommand(row: EventRow): boolean {\n return row.exit_code !== null && row.exit_code !== 0\n}\n\n/**\n * Commit subjects Workscribe captured itself: `git commit -m` messages and AI-session commits.\n * A `git commit` that failed (rejected by a hook, nothing staged) made no commit, so it is skipped.\n */\nexport function collectCapturedCommits(rows: EventRow[]): string[] {\n const subjects = rows.flatMap((row) => {\n const { metadata } = eventRowToPayload(row)\n if (row.category === 'shipping' && typeof metadata.message === 'string' && !isFailedCommand(row)) {\n return [metadata.message]\n }\n if (row.category === 'ai_session' && Array.isArray(metadata.commits)) {\n return metadata.commits.filter((subject): subject is string => typeof subject === 'string')\n }\n return []\n })\n return [...new Set(subjects.filter((subject) => subject !== ''))]\n}\n\n/**\n * Whether a captured subject is this git commit. Besides an exact match, it tolerates the two ways\n * events captured before the `-m` parsing fix were cut wrong — and only those, so a short `fix`\n * never matches `fix: something else`:\n * - stopped at an inner quote: `fix: don` for `fix: don't redirect`\n * - ran on into flags: `wip --no-verify` for `wip`\n */\nexport function isSameCommit(captured: string, gitSubject: string): boolean {\n if (captured === gitSubject) return true\n if (gitSubject.startsWith(captured)) return /^['\"]/.test(gitSubject.slice(captured.length))\n if (captured.startsWith(gitSubject)) return /^\\s+-/.test(captured.slice(gitSubject.length))\n return false\n}\n\n/**\n * Git commits first, oldest first and each listed even if subjects repeat (they are distinct commits),\n * then captured subjects git didn't return — amended, rebased or on another branch — with no hash.\n * Captured subjects git attributes only to other people are dropped: an AI session records every\n * commit that reached HEAD, including ones pulled or rebased in.\n */\nexport function mergeCommits(captured: string[], fromGit: GitCommit[], othersSubjects: string[] = []): CommitJson[] {\n const others = new Set(othersSubjects)\n const gitCommits: CommitJson[] = fromGit.map((commit) => ({ ...commit, source: 'git' }))\n const capturedOnly: CommitJson[] = captured\n .filter((subject) => !others.has(subject))\n .filter((subject) => !fromGit.some((commit) => isSameCommit(subject, commit.subject)))\n .map((subject) => ({ hash: null, subject, source: 'captured' }))\n return [...gitCommits, ...capturedOnly]\n}\n","import { eventRowToPayload, mostFrequentCwd, sessionLocation } from '../payload'\nimport { sessionKey } from '../store'\nimport { SCHEMA_VERSION } from './constants'\nimport { collectCapturedCommits, collectNotes, contractEvents, mergeCommits } from './utils'\nimport type { EventRow } from '../../db/types'\nimport type { Session } from '../../sessions/detector'\nimport type { EventJson, EventsJson, EventsJsonOptions, SessionJson, SessionJsonOptions, SessionsJson } from './types'\n\n/** Never includes the full command, the event's cwd or an IDE file path. */\nexport function eventToJson(row: EventRow): EventJson {\n const { category, metadata, hint, exitCode, durationMs } = eventRowToPayload(row)\n return {\n capturedAt: row.captured_at,\n category,\n metadata,\n ...(hint === undefined ? {} : { hint }),\n exitCode,\n durationMs,\n source: row.source,\n }\n}\n\nexport function sessionToJson(session: Session, { location, git, includeCategories }: SessionJsonOptions): SessionJson {\n return {\n key: sessionKey(session.repoName, session.startedAt),\n project: sessionLocation(session, location),\n repoName: session.repoName,\n repoPath: git.repoPath,\n cwd: mostFrequentCwd(session),\n branch: session.events[0]?.branch ?? null,\n startedAt: session.startedAt,\n endedAt: session.endedAt,\n durationMinutes: session.durationMinutes,\n eventCount: session.eventCount,\n notes: collectNotes(session.events),\n commits: mergeCommits(collectCapturedCommits(session.events), git.commits, git.othersSubjects),\n events: contractEvents(session.events, includeCategories).map(eventToJson),\n }\n}\n\nexport function buildSessionsJson(date: string, sessions: SessionJson[]): SessionsJson {\n return { schemaVersion: SCHEMA_VERSION, date, sessions }\n}\n\nexport function buildEventsJson(\n date: string,\n rows: EventRow[],\n { limit, includeCategories }: EventsJsonOptions\n): EventsJson {\n const events = contractEvents(rows, includeCategories)\n return { schemaVersion: SCHEMA_VERSION, date, total: events.length, events: events.slice(0, limit).map(eventToJson) }\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'\nimport { readConfig } from '../config'\nimport { buildEventsJson } from '../summary/contract/build'\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\nfunction isPositiveWholeNumber(value: number): boolean {\n return Number.isInteger(value) && value > 0\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 .option('--json', 'output the versioned JSON contract (structured events, no raw commands)')\n .action((options) => {\n let date = todayDate()\n if (options.date) {\n try {\n date = parseDate(options.date)\n } catch (error) {\n log.error((error as Error).message)\n process.exit(1)\n }\n }\n\n const events = getEventsForDate(date)\n\n if (options.json) {\n // Scripts call the JSON contract, so a bad --limit is an error rather than a silently odd list\n if (options.limit !== undefined && !isPositiveWholeNumber(options.limit)) {\n log.error('--limit must be a positive whole number')\n process.exit(1)\n }\n const includeCategories = readConfig().summary?.includeCategories ?? []\n log.plain(JSON.stringify(buildEventsJson(date, events, { limit: options.limit, includeCategories })))\n return\n }\n\n const limit = options.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","// Rules and messages for `workscribe sessions summary set` — pure; the command does the I/O.\n\nconst BYTES_PER_KB = 1024\nconst MAX_SKILL_SUMMARY_KB = 8\n\n/** Largest summary the agent skill may save for one session, in bytes. */\nexport const MAX_SKILL_SUMMARY_BYTES = MAX_SKILL_SUMMARY_KB * BYTES_PER_KB\n\n// Shown whenever no summary text arrives, so the fix is a copy-paste away\nconst SEND_TEXT_EXAMPLE = [\n 'Send the summary text into the command, for example:',\n '',\n \" workscribe sessions summary set --key '<key from workscribe sessions --json>' <<'EOF'\",\n ' ## my-project (main) — 1h 30m',\n ' - What you got done',\n ' EOF',\n].join('\\n')\n\nexport const INTERACTIVE_STDIN_MESSAGE = `This command saves summary text that is sent to it — it can't be typed in here.\\n${SEND_TEXT_EXAMPLE}`\n\nexport function stdinReadFailedMessage(error: unknown): string {\n return `Couldn't read the summary text that was sent in: ${(error as Error).message}`\n}\n\n/** `16384` → `16,384` — thousands separators only, no unit scaling. */\nfunction formatCount(count: number): string {\n return count.toLocaleString('en-US')\n}\n\n/** A friendly error for a summary that can't be saved, or null when it's fine. */\nexport function validateSkillSummary(text: string): string | null {\n if (text.trim() === '') return `Nothing to save — no summary text was received.\\n${SEND_TEXT_EXAMPLE}`\n const bytes = Buffer.byteLength(text, 'utf-8')\n if (bytes > MAX_SKILL_SUMMARY_BYTES) {\n return (\n `This summary is too long to save (${formatCount(bytes)} bytes; the limit is ` +\n `${formatCount(MAX_SKILL_SUMMARY_BYTES)}, about ${MAX_SKILL_SUMMARY_KB} KB). Shorten it and try again.`\n )\n }\n return null\n}\n","import fs from 'fs'\n\nconst STDIN_FILE_DESCRIPTOR = 0\n\n/** True when stdin is a terminal — reading it would wait for typing rather than piped input. */\nexport function isStdinInteractive(): boolean {\n return Boolean(process.stdin.isTTY)\n}\n\n/** Everything piped into the process. Throws if stdin can't be read. */\nexport function readAllStdin(): string {\n return fs.readFileSync(STDIN_FILE_DESCRIPTOR, 'utf-8')\n}\n","import { Command } from 'commander'\nimport { getOrBuildSessions } from '../sessions/detector'\nimport { saveSessionSummary } from '../db'\nimport { readConfig } from '../config'\nimport { redact } from '../capture/redact'\nimport { log } from '../utils/logger'\nimport { localDateOf } from '../utils/format'\nimport { SKILL_ENGINE, parseSessionKey, sessionKey } from '../summary/store'\nimport { INTERACTIVE_STDIN_MESSAGE, stdinReadFailedMessage, validateSkillSummary } from '../summary/write-back'\nimport { isStdinInteractive, readAllStdin } from '../utils/stdin'\nimport type { Session } from '../sessions/detector'\n\n// `workscribe sessions summary set` — how the Workscribe agent skill saves the summary it wrote.\n\nfunction fail(message: string): never {\n log.error(message)\n process.exit(1)\n}\n\n/** The session a key from `sessions --json` names, after rebuilding its day so the lookup is current. */\nfunction findSessionByKey(key: string): Session | null {\n const parsed = parseSessionKey(key)\n if (!parsed) return null\n return (\n getOrBuildSessions(localDateOf(parsed.startedAt)).find(\n (session) => sessionKey(session.repoName, session.startedAt) === key\n ) ?? null\n )\n}\n\n/** The summary text piped in, failing with a friendly message for a terminal or a read error. */\nfunction readSummaryText(): string {\n if (isStdinInteractive()) fail(INTERACTIVE_STDIN_MESSAGE)\n try {\n return readAllStdin()\n } catch (error) {\n fail(stdinReadFailedMessage(error))\n }\n}\n\nfunction saveSkillSummary(options: { key: string }): void {\n if (!parseSessionKey(options.key)) {\n fail(`That session key isn't valid: '${options.key}'. Copy a session's \"key\" from workscribe sessions --json.`)\n }\n\n const summaryText = readSummaryText()\n const problem = validateSkillSummary(summaryText)\n if (problem) fail(problem)\n\n const session = findSessionByKey(options.key)\n if (!session) {\n fail(\n 'No session matches this key — your activity may have changed since the sessions were listed. ' +\n 'Run workscribe sessions --json again and use the new key.'\n )\n }\n\n const text = redact(summaryText.trim(), readConfig().redact.extra)\n saveSessionSummary(options.key, SKILL_ENGINE, text)\n log.success(\n `Saved the summary for ${session.repoName ?? 'this session'} — workscribe summary, workscribe context and the VS Code status bar now show it.`\n )\n}\n\nexport function registerSummarySet(sessionsCommand: Command): void {\n sessionsCommand\n .command('summary')\n .description('Manage the summaries stored for sessions')\n .command('set')\n .description('Save a summary written by the Workscribe agent skill; the text is read from stdin')\n .requiredOption('--key <key>', 'the session key, from workscribe sessions --json')\n .action(saveSkillSummary)\n}\n","import { execFileSync } from 'child_process'\n\nconst GIT_TIMEOUT_MS = 3000\n// Commands are captured when they finish, so a `git commit` that opens a session is stamped after\n// its committer time — by however long the commit hooks ran. A commit closing a session can land\n// just after its event.\nconst WINDOW_LEAD_MS = 120_000\nconst WINDOW_TRAIL_MS = 60_000\n// How far back to look when checking who made a captured commit (pulled commits can be old)\nconst AUTHORSHIP_HISTORY_DEPTH = 500\n\nexport interface GitCommit {\n hash: string\n subject: string\n}\n\ninterface CommitWindow {\n repoRoot: string\n since: string\n until: string\n /** Only commits committed by this email (case-insensitive); all commits when null. */\n author: string | null\n}\n\n/** Runs git without a shell. Returns trimmed stdout, or null on any failure (no git, not a repo, timeout). */\nfunction runGit(cwd: string, args: string[]): string | null {\n try {\n return execFileSync('git', args, { cwd, timeout: GIT_TIMEOUT_MS, stdio: ['ignore', 'pipe', 'ignore'] })\n .toString()\n .trim()\n } catch {\n return null\n }\n}\n\nexport function getRepoRoot(cwd: string): string | null {\n return runGit(cwd, ['rev-parse', '--show-toplevel']) || null\n}\n\nexport function getUserEmail(repoRoot: string): string | null {\n return runGit(repoRoot, ['config', 'user.email']) || null\n}\n\n/**\n * Subjects in the last AUTHORSHIP_HISTORY_DEPTH commits on HEAD that only other people committed.\n * Empty without an author to compare against, or when git fails.\n */\nexport function getOthersSubjects(repoRoot: string, author: string | null): string[] {\n if (!author) return []\n const output = runGit(repoRoot, ['log', `-n${AUTHORSHIP_HISTORY_DEPTH}`, '--format=%ce%x09%s'])\n if (!output) return []\n\n const wantedAuthor = author.toLowerCase()\n const mine = new Set<string>()\n const theirs = new Set<string>()\n for (const line of output.split('\\n')) {\n const [email, ...subjectParts] = line.split('\\t')\n const subject = subjectParts.join('\\t')\n if (!subject) continue\n if (email?.toLowerCase() === wantedAuthor) mine.add(subject)\n else theirs.add(subject)\n }\n return [...theirs].filter((subject) => !mine.has(subject))\n}\n\n/**\n * Commits made during a session, oldest first. Window and author both use the *committer* (who made\n * the commit then — including cherry-picks of someone else's work) and only commits reachable from\n * HEAD are seen. `--since` also stops at the first commit older than the window, so after a rebase\n * that leaves dates out of order a few in-window commits can be missed. Captured commit messages\n * cover what this misses.\n */\nexport function getCommitsInWindow({ repoRoot, since, until, author }: CommitWindow): GitCommit[] {\n const shiftedBy = (iso: string, milliseconds: number): string =>\n new Date(new Date(iso).getTime() + milliseconds).toISOString()\n const output = runGit(repoRoot, [\n 'log',\n `--since=${shiftedBy(since, -WINDOW_LEAD_MS)}`,\n `--until=${shiftedBy(until, WINDOW_TRAIL_MS)}`,\n '--format=%h%x09%ce%x09%s',\n '--reverse',\n ])\n if (!output) return []\n\n const wantedAuthor = author?.toLowerCase() ?? null\n return output.split('\\n').flatMap((line) => {\n const [hash, email, ...subjectParts] = line.split('\\t')\n const subject = subjectParts.join('\\t')\n if (!hash || !subject) return []\n if (wantedAuthor && email?.toLowerCase() !== wantedAuthor) return []\n return [{ hash, subject }]\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'\nimport { registerSummarySet } from './session-summary'\nimport { readConfig } from '../config'\nimport { locationContextFrom, repoCwd } from '../summary/payload'\nimport { buildSessionsJson, sessionToJson } from '../summary/contract/build'\nimport { getCommitsInWindow, getOthersSubjects, getRepoRoot, getUserEmail } from '../summary/git-commits'\nimport { memoize } from '../utils/memoize'\nimport type { Session } from '../sessions/detector'\nimport type { SessionGitInfo } from '../summary/contract/types'\n\n/**\n * Looks up git facts for the session's repo — empty outside a git repo or when git fails.\n * Repo roots and emails are cached for the run so a day of sessions in one repo asks git once.\n */\nfunction createSessionGitLookup(): (session: Session) => SessionGitInfo {\n const repoRootOf = memoize(getRepoRoot)\n const emailOf = memoize(getUserEmail)\n const othersSubjectsOf = memoize((repoPath) => getOthersSubjects(repoPath, emailOf(repoPath)))\n return (session) => {\n const cwd = repoCwd(session)\n const repoPath = cwd ? repoRootOf(cwd) : null\n if (!repoPath) return { repoPath: null, commits: [], othersSubjects: [] }\n const author = emailOf(repoPath)\n const commits = getCommitsInWindow({ repoRoot: repoPath, since: session.startedAt, until: session.endedAt, author })\n return { repoPath, commits, othersSubjects: othersSubjectsOf(repoPath) }\n }\n}\n\nfunction printSessionsJson(date: string, sessions: Session[]): void {\n const config = readConfig()\n const options = {\n location: locationContextFrom(config),\n includeCategories: config.summary?.includeCategories ?? [],\n }\n const lookupGit = createSessionGitLookup()\n const sessionJsons = sessions.map((session) => sessionToJson(session, { ...options, git: lookupGit(session) }))\n log.plain(JSON.stringify(buildSessionsJson(date, sessionJsons)))\n}\n\nexport function registerSessions(program: Command): void {\n const sessionsCommand = program\n .command('sessions')\n .description('List detected work sessions')\n .option('--date <YYYY-MM-DD>', 'date to show sessions for (default: today)')\n .option('--json', 'output the versioned JSON contract (sessions with events, notes and commits)')\n .action((options) => {\n let date = todayDate()\n if (options.date) {\n try {\n date = parseDate(options.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 (options.json) {\n printSessionsJson(date, sessions)\n return\n }\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 registerSummarySet(sessionsCommand)\n}\n","import { formatDuration } from '../utils/format'\nimport type { SessionPayload } from '../ai/types'\n\n/** Shown when a session has neither a repo nor any events to name it by. */\nexport const UNKNOWN_LOCATION = 'unknown'\n\ntype HeadingFields = Pick<SessionPayload, 'project' | 'branch' | 'durationMinutes'>\n\n/** `project (branch) — duration`, as used in headings and the --verbose event listing. */\nexport function formatSessionLabel(session: HeadingFields): string {\n const branch = session.branch ? ` (${session.branch})` : ''\n return `${session.project ?? UNKNOWN_LOCATION}${branch} — ${formatDuration(session.durationMinutes)}`\n}\n\n/** The `## project (branch) — duration` line every session summary starts with. */\nexport function formatSessionHeading(session: HeadingFields): string {\n return `## ${formatSessionLabel(session)}`\n}\n","import type { OutcomeWording } from './types'\n\nexport const MAX_SESSION_BULLETS = 7\nexport const MAX_COMMIT_BULLETS = 3\nexport const MAX_DAY_BULLETS = 5\nexport const MAX_LISTED_PACKAGES = 6\n\n// Event sources that mean a coding agent ran the command (its hook captured it). Summaries count these,\n// but never name the tool.\nexport const AGENT_SOURCES = ['claude-code']\n\nexport const TEST_WORDING: OutcomeWording = {\n category: 'testing',\n resolved: 'Resolved failing tests',\n passing: 'Tests passing',\n failing: 'Tests still failing',\n ran: 'Ran tests',\n}\n\nexport const BUILD_WORDING: OutcomeWording = {\n category: 'building',\n resolved: 'Fixed a failing build',\n passing: 'Builds passing',\n failing: 'Build still failing',\n ran: 'Ran builds',\n}\n","import type { EventPayload } from '../../types'\n\nexport function pluralize(count: number, noun: string): string {\n return `${count} ${noun}${count === 1 ? '' : 's'}`\n}\n\n/** The non-empty strings in a metadata value — event metadata is untyped JSON. */\nexport function stringsIn(value: unknown): string[] {\n return Array.isArray(value) ? value.filter((item): item is string => typeof item === 'string' && item !== '') : []\n}\n\nexport function unique(values: string[]): string[] {\n return [...new Set(values)]\n}\n\nexport function eventsOf(events: EventPayload[], category: string): EventPayload[] {\n return events.filter((event) => event.category === category)\n}\n\nexport function toBulletList(bullets: string[]): string {\n return bullets.map((bullet) => `- ${bullet}`).join('\\n')\n}\n","import { buildExcludedSet } from '../../../summary/exclusions'\nimport {\n AGENT_SOURCES,\n BUILD_WORDING,\n MAX_COMMIT_BULLETS,\n MAX_LISTED_PACKAGES,\n MAX_SESSION_BULLETS,\n TEST_WORDING,\n} from './constants'\nimport { eventsOf, pluralize, stringsIn, unique } from './utils'\nimport type { EventPayload, SessionPayload } from '../../types'\nimport type { OutcomeWording } from './types'\n\nfunction describeNotes(events: EventPayload[]): string[] {\n return eventsOf(events, 'note').flatMap((event) => stringsIn([event.metadata.text]).map((text) => `Note: ${text}`))\n}\n\n/** Commit messages from `git commit -m` and from AI sessions, in order, without repeats. */\nexport function collectCommits(events: EventPayload[]): string[] {\n return unique(\n events.flatMap((event) => {\n if (event.category === 'shipping') return stringsIn([event.metadata.message])\n if (event.category === 'ai_session') return stringsIn(event.metadata.commits)\n return []\n })\n )\n}\n\nfunction describeCommits(commits: string[]): string[] {\n const bullets = commits.slice(0, MAX_COMMIT_BULLETS).map((message) => `Committed: ${message}`)\n const hiddenCount = commits.length - MAX_COMMIT_BULLETS\n if (hiddenCount > 0) bullets[MAX_COMMIT_BULLETS - 1] += `, plus ${pluralize(hiddenCount, 'more change')}`\n return bullets\n}\n\n/**\n * Pass/fail story for test or build runs. Commands captured through AI-tool hooks have no exit\n * code, so they count towards the run total but never decide the outcome.\n */\nexport function describeOutcome(events: EventPayload[], wording: OutcomeWording): string | null {\n const runs = eventsOf(events, wording.category)\n if (runs.length === 0) return null\n\n const runCount = pluralize(runs.length, 'run')\n const knownExitCodes = runs.map((run) => run.exitCode).filter((exitCode): exitCode is number => exitCode !== null)\n if (knownExitCodes.length === 0) return `${wording.ran} (${runCount})`\n if (knownExitCodes[knownExitCodes.length - 1] !== 0) return `${wording.failing} (${runCount})`\n if (knownExitCodes.some((exitCode) => exitCode !== 0)) return `${wording.resolved} (${runCount}, now passing)`\n return `${wording.passing} (${runCount})`\n}\n\nfunction listPackages(packages: string[]): string {\n const listed = packages.slice(0, MAX_LISTED_PACKAGES).join(', ')\n const hiddenCount = packages.length - MAX_LISTED_PACKAGES\n return `${listed}${hiddenCount > 0 ? `, plus ${hiddenCount} more` : ''}`\n}\n\n/** Removals (`npm uninstall`, `yarn remove`, …) carry action: 'remove' and are worded separately from additions. */\nfunction describeDependencies(events: EventPayload[]): string[] {\n const runs = eventsOf(events, 'dependencies')\n if (runs.length === 0) return []\n const isRemoval = (event: EventPayload): boolean => event.metadata.action === 'remove'\n const added = unique(runs.filter((event) => !isRemoval(event)).flatMap((event) => stringsIn(event.metadata.packages)))\n const removed = unique(runs.filter(isRemoval).flatMap((event) => stringsIn(event.metadata.packages)))\n if (added.length === 0 && removed.length === 0) return [`Installed dependencies (${pluralize(runs.length, 'run')})`]\n\n return [\n ...(added.length > 0 ? [`Added dependencies: ${listPackages(added)}`] : []),\n ...(removed.length > 0 ? [`Removed dependencies: ${listPackages(removed)}`] : []),\n ]\n}\n\nfunction describeReleases(events: EventPayload[]): string | null {\n const releases = eventsOf(events, 'releasing')\n if (releases.length === 0) return null\n const tools = unique(releases.flatMap((event) => stringsIn([event.metadata.tool])))\n return tools.length > 0 ? `Released / deployed (${tools.join(', ')})` : 'Released / deployed'\n}\n\nfunction describePushes(events: EventPayload[]): string | null {\n const targets = unique(\n eventsOf(events, 'shipping').flatMap((event) => {\n const [remote] = stringsIn([event.metadata.remote])\n if (!remote) return []\n const [branch] = stringsIn([event.metadata.branch])\n return [branch ? `${remote}/${branch}` : remote]\n })\n )\n return targets.length > 0 ? `Pushed to ${targets.join(', ')}` : null\n}\n\n/** Commands a coding agent ran in the session — counted from all of them, including ones the summary leaves out. */\nfunction describeAgentWork(events: EventPayload[]): string | null {\n const agentCommands = events.filter((event) => event.source !== undefined && AGENT_SOURCES.includes(event.source))\n return agentCommands.length > 0\n ? `Worked with an AI coding assistant (${pluralize(agentCommands.length, 'command')})`\n : null\n}\n\nfunction describeEdits(events: EventPayload[]): string | null {\n const saves = eventsOf(events, 'code_edit').length\n return saves > 0 ? `Edited files in the IDE (${pluralize(saves, 'save')})` : null\n}\n\n/** Notes are always kept; everything else follows the same exclusions as the AI payload. */\nfunction includedEvents(events: EventPayload[], includeCategories: string[]): EventPayload[] {\n const excluded = buildExcludedSet(includeCategories)\n return events.filter((event) => event.category === 'note' || !excluded.has(event.category))\n}\n\n/** Outcome bullets for one session, most important first, capped at MAX_SESSION_BULLETS. Empty if nothing notable happened. */\nexport function describeActivity(session: SessionPayload, includeCategories: string[] = []): string[] {\n const events = includedEvents(session.events, includeCategories)\n return [\n ...describeNotes(events),\n ...describeCommits(collectCommits(events)),\n describeOutcome(events, TEST_WORDING),\n describeOutcome(events, BUILD_WORDING),\n ...describeDependencies(events),\n describeReleases(events),\n describePushes(events),\n describeAgentWork(session.events),\n describeEdits(events),\n ]\n .filter((bullet): bullet is string => bullet !== null)\n .slice(0, MAX_SESSION_BULLETS)\n}\n\nexport function countIncludedEvents(session: SessionPayload, includeCategories: string[] = []): number {\n return includedEvents(session.events, includeCategories).length\n}\n\n/** Outcome bullets for one session, or a line saying where the work happened when nothing stands out. */\nexport function describeSession(session: SessionPayload, includeCategories: string[] = []): string[] {\n const bullets = describeActivity(session, includeCategories)\n if (bullets.length > 0) return bullets\n const commandCount = pluralize(countIncludedEvents(session, includeCategories), 'command')\n return [`Worked in ${session.project ?? 'an unknown location'} (${commandCount})`]\n}\n","import { formatSessionHeading, UNKNOWN_LOCATION } from '../../../summary/heading'\nimport { MAX_DAY_BULLETS } from './constants'\nimport { countIncludedEvents, describeActivity, describeSession } from './describe'\nimport { pluralize, toBulletList } from './utils'\nimport type { AIProvider, DaySummaryPayload, SessionPayload, WeekSummaryPayload } from '../../types'\n\n/** One entry per location for the day — several sessions in the same repo read as one block of work. */\nfunction mergeByLocation(sessions: SessionPayload[]): SessionPayload[] {\n const merged = new Map<string, SessionPayload>()\n for (const session of sessions) {\n const location = session.project ?? UNKNOWN_LOCATION\n const existing = merged.get(location)\n merged.set(\n location,\n existing\n ? {\n ...existing,\n events: [...existing.events, ...session.events],\n durationMinutes: existing.durationMinutes + session.durationMinutes,\n }\n : { ...session, project: location }\n )\n }\n return [...merged.values()]\n}\n\nfunction locationBullets(session: SessionPayload, includeCategories: string[]): string[] {\n const bullets = describeActivity(session, includeCategories)\n const lines = bullets.length > 0 ? bullets : [pluralize(countIncludedEvents(session, includeCategories), 'command')]\n return lines.map((line) => `${session.project}: ${line}`)\n}\n\n/** Takes the top bullet of every location, then the second, and so on — so one busy repo can't fill the day. */\nfunction pickDayBullets(sessions: SessionPayload[], includeCategories: string[]): string[] {\n const perLocation = mergeByLocation(sessions).map((session) => locationBullets(session, includeCategories))\n const longest = Math.max(0, ...perLocation.map((bullets) => bullets.length))\n const interleaved = Array.from({ length: longest }, (_unused, index) =>\n perLocation.flatMap((bullets) => (index < bullets.length ? [bullets[index]] : []))\n ).flat()\n return interleaved.slice(0, MAX_DAY_BULLETS)\n}\n\n/** Offline, deterministic summaries built from captured events — the default when no AI is configured. */\nexport class TemplateProvider implements AIProvider {\n constructor(private includeCategories: string[] = []) {}\n\n async summarize(payload: DaySummaryPayload): Promise<string> {\n const [onlySession, ...otherSessions] = payload.sessions\n if (onlySession && otherSessions.length === 0) {\n return toBulletList(describeSession(onlySession, this.includeCategories))\n }\n // `export` summarizes a whole day at once, so each session gets its own heading\n return payload.sessions\n .map(\n (session) =>\n `${formatSessionHeading(session)}\\n${toBulletList(describeSession(session, this.includeCategories))}`\n )\n .join('\\n\\n')\n }\n\n async summarizeWeek(payload: WeekSummaryPayload): Promise<string> {\n return payload.days\n .map((day) => `### ${day.date}\\n${toBulletList(pickDayBullets(day.sessions, this.includeCategories))}`)\n .join('\\n\\n')\n }\n\n async validate(): Promise<void> {\n // Nothing to reach — the template engine runs entirely offline\n }\n}\n","import { TemplateProvider } from '../ai/engines/template/provider'\nimport type { AIProvider } from '../ai/types'\nimport type { WorkscribeConfig } from '../config'\n\n/** What writes summaries since 2.0: the offline template engine, honouring summary.includeCategories. */\nexport function createSummaryWriter(config: WorkscribeConfig): AIProvider {\n return new TemplateProvider(config.summary?.includeCategories ?? [])\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 os from 'os'\nimport { log } from '../utils/logger'\nimport { postToWebhook } from '../integrations/webhook'\nimport { formatForSlack, isSlackWebhookUrl } from '../integrations/slack'\nimport type { WorkscribeConfig } from '../config'\n\nexport interface WebhookOptions {\n slack?: boolean\n webhook?: string\n}\n\ninterface PostSummaryInput {\n options: WebhookOptions\n config: WorkscribeConfig\n summary: string\n /** True when stdout carries JSON (summary.format=json): status lines then go to stderr so the JSON can be piped. */\n statusToStderr?: boolean\n}\n\n/** Posts a finished summary to --webhook, or to the configured Slack webhook with --slack. Never throws. */\nexport async function postSummary({\n options,\n config,\n summary,\n statusToStderr = false,\n}: PostSummaryInput): Promise<void> {\n const status = statusToStderr ? { info: log.notice, success: log.notice, warn: log.notice } : log\n const webhookUrl = options.webhook ?? (options.slack ? config.integrations?.slackWebhook : undefined)\n\n if (!webhookUrl) {\n if (options.slack && !config.integrations?.slackWebhook) {\n status.warn('--slack requires integrations.slackWebhook to be set in config')\n }\n return\n }\n\n try {\n status.info('Posting to webhook…')\n const body = isSlackWebhookUrl(webhookUrl) ? formatForSlack(summary, os.userInfo().username) : summary\n await postToWebhook(webhookUrl, body)\n status.success('Posted.')\n } catch (error) {\n log.error(`Webhook failed: ${(error as Error).message}`)\n }\n}\n","import { getOrBuildSessions } from '../sessions/detector'\nimport { log } from '../utils/logger'\nimport { todayDate, startOfWeek, eachDayOfRange } from '../utils/format'\nimport { buildDayPayload, locationContextFrom, type LocationContext } from './payload'\nimport { postSummary, type WebhookOptions } from './webhook'\nimport type { AIProvider, WeekSummaryPayload } from '../ai/types'\nimport type { WorkscribeConfig } from '../config'\n\nexport interface WeeklySummaryOptions extends WebhookOptions {\n /** Accepted for compatibility with 1.x scripts — weekly digests are always rendered fresh now. */\n fresh?: boolean\n}\n\ninterface RunWeeklySummaryInput {\n options: WeeklySummaryOptions\n config: WorkscribeConfig\n provider: AIProvider\n}\n\nfunction collectWeekDays(weekStart: string, today: string, context: LocationContext): WeekSummaryPayload['days'] {\n return eachDayOfRange(weekStart, today).flatMap((day) => {\n const sessions = getOrBuildSessions(day)\n if (sessions.length === 0) return []\n return [buildDayPayload(day, sessions, context)]\n })\n}\n\nasync function writeWeeklySummary(provider: AIProvider, payload: WeekSummaryPayload): Promise<string> {\n if (provider.summarizeWeek) return provider.summarizeWeek(payload)\n return provider.summarize({ date: payload.weekEnd, sessions: payload.days.flatMap((day) => day.sessions) })\n}\n\nfunction printSummary(summary: string): void {\n log.plain('')\n log.plain(summary)\n log.plain('')\n}\n\n/** Shared flow for `summary --week` and `week`: collect Mon–today, render the digest, post it. */\nexport async function runWeeklySummary({ options, config, provider }: RunWeeklySummaryInput): Promise<void> {\n const today = todayDate()\n const weekStart = startOfWeek(today)\n const days = collectWeekDays(weekStart, today, locationContextFrom(config))\n if (days.length === 0) {\n log.plain('No activity captured this week.')\n return\n }\n\n const summary = await writeWeeklySummary(provider, { weekStart, weekEnd: today, days })\n printSummary(summary)\n await postSummary({ options, config, summary })\n}\n","import { Command } from 'commander'\nimport chalk from 'chalk'\nimport { getOrBuildSessions } from '../sessions/detector'\nimport { readConfig } from '../config'\nimport { getSessionSummaries } from '../db'\nimport { log } from '../utils/logger'\nimport { todayDate, parseDate } from '../utils/format'\nimport type { AIProvider, DaySummaryPayload, SessionPayload } from '../ai/types'\nimport { buildExcludedSet, countExcludedEvents } from '../summary/exclusions'\nimport { sessionToPayload, locationContextFrom } from '../summary/payload'\nimport { formatSessionHeading, formatSessionLabel } from '../summary/heading'\nimport { sessionKey, pickSavedSummary, type SavedSummary } from '../summary/store'\nimport { createSummaryWriter } from '../summary/writer'\nimport { printLegacyAiNotice } from './notices'\nimport { postSummary } from '../summary/webhook'\nimport { runWeeklySummary } from '../summary/weekly'\n\ninterface SessionSummaryJson {\n project: string | null\n branch: string | null\n durationMinutes: number\n bullets: string[]\n}\n\n/** Parse 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 stripHeading(summary: string): string {\n return summary.replace(/^## .+\\n/, '')\n}\n\nfunction toJsonOutput(date: string, sessionPayloads: SessionPayload[], bulletsPerSession: string[]): string {\n const sessions: SessionSummaryJson[] = sessionPayloads.map((sessionPayload, index) => ({\n project: sessionPayload.project,\n branch: sessionPayload.branch,\n durationMinutes: sessionPayload.durationMinutes,\n bullets: parseBullets(bulletsPerSession[index]),\n }))\n return JSON.stringify({ date, sessions }, null, 2)\n}\n\nfunction printCapturedEvents(sessionPayloads: SessionPayload[], excluded: Set<string>): void {\n log.plain('')\n log.plain(chalk.bold(' Captured events (--verbose):'))\n for (const sessionPayload of sessionPayloads) {\n log.plain(chalk.dim(`\\n ${formatSessionLabel(sessionPayload)}`))\n for (const event of sessionPayload.events) {\n const tag = excluded.has(event.category) ? chalk.dim(` [excluded] ${event.category}`) : ` ${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\nfunction printExcludedFooter(sessionPayloads: SessionPayload[], excluded: Set<string>): void {\n const excludedCounts = countExcludedEvents(sessionPayloads, excluded)\n if (excludedCounts.size === 0) return\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\nasync function generateSessionSummary(input: {\n provider: AIProvider\n sessionPayload: SessionPayload\n date: string\n}): Promise<string> {\n const daySummaryPayload: DaySummaryPayload = { date: input.date, sessions: [input.sessionPayload] }\n try {\n const bullets = (await input.provider.summarize(daySummaryPayload)).trim()\n return `${formatSessionHeading(input.sessionPayload)}\\n${bullets}`\n } catch (error) {\n log.error(`Summary failed: ${(error as Error).message}`)\n process.exit(1)\n }\n}\n\n/** Says which sessions came from saved summaries, so it's clear why --fresh would change the output. */\nfunction printSavedNote(saved: (SavedSummary | null)[]): void {\n const fromSkill = saved.filter((entry) => entry?.fromSkill).length\n const fromLegacyProvider = saved.filter((entry) => entry && !entry.fromSkill).length\n const parts = [\n fromSkill > 0 ? `${fromSkill} written by the Workscribe agent skill` : null,\n fromLegacyProvider > 0 ? `${fromLegacyProvider} written by an AI provider in Workscribe 1.x` : null,\n ].filter((part): part is string => part !== null)\n if (parts.length === 0) return\n log.plain(chalk.dim(` (${parts.join(', ')} — use --fresh for the template summary)`))\n}\n\nexport function registerSummary(program: Command): void {\n program\n .command('summary')\n .description('Generate a work summary')\n .option('--date <YYYY-MM-DD>', 'date to summarize (default: today)')\n .option('--week', 'summarize the current week')\n .option('--fresh', 'ignore saved summaries and render the template')\n .option('--verbose', 'show all captured events, including those left out of the summary')\n .option('--slack', 'post summary to Slack webhook from config')\n .option('--webhook <url>', 'post summary to a custom webhook URL')\n .action(async (options) => {\n const config = readConfig()\n printLegacyAiNotice(config)\n const provider = createSummaryWriter(config)\n\n // ── Weekly branch ────────────────────────────────────────────────────────\n if (options.week) {\n try {\n await runWeeklySummary({ options, config, provider })\n } catch (error) {\n log.error((error as Error).message)\n process.exit(1)\n }\n return\n }\n\n // ── Daily branch ─────────────────────────────────────────────────────────\n let date = todayDate()\n if (options.date) {\n try {\n date = parseDate(options.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 sessionPayloads = sessions.map((session) => sessionToPayload(session, date, locationContextFrom(config)))\n const keys = sessions.map((session) => sessionKey(session.repoName, session.startedAt))\n const jsonMode = config.summary?.format === 'json'\n\n // A summary the agent skill (or a 1.x AI provider) saved — `--fresh` ignores both and renders the template\n const saved = keys.map((key) => (options.fresh ? null : pickSavedSummary(getSessionSummaries(key))))\n const needsGeneration = saved.some((entry) => entry === null)\n const excluded = buildExcludedSet(config.summary?.includeCategories ?? [])\n if (needsGeneration && options.verbose) {\n if (jsonMode) log.notice('--verbose is skipped when summary.format is json, to keep the JSON output clean')\n else printCapturedEvents(sessionPayloads, excluded)\n }\n\n const summaries: string[] = []\n for (const [index, sessionPayload] of sessionPayloads.entries()) {\n const savedSummary = saved[index]\n if (savedSummary) {\n summaries.push(savedSummary.text)\n continue\n }\n summaries.push(await generateSessionSummary({ provider, sessionPayload, date }))\n }\n\n const fullSummary = summaries.join('\\n\\n')\n if (jsonMode) {\n // Only the JSON on stdout, so it can be piped straight into another tool\n log.plain(toJsonOutput(date, sessionPayloads, summaries.map(stripHeading)))\n } else {\n log.plain('')\n log.plain(fullSummary)\n log.plain('')\n printSavedNote(saved)\n if (needsGeneration) printExcludedFooter(sessionPayloads, excluded)\n }\n\n await postSummary({ options, config, summary: fullSummary, statusToStderr: jsonMode })\n })\n}\n","import { Command } from 'commander'\nimport fs from 'fs'\nimport path from 'path'\nimport { getOrBuildSessions } from '../sessions/detector'\nimport { readConfig } from '../config'\nimport { log } from '../utils/logger'\nimport { todayDate, parseDate } from '../utils/format'\nimport { EXPORTS_DIR } from '../utils/paths'\nimport { buildDayPayload, locationContextFrom } from '../summary/payload'\nimport { createSummaryWriter } from '../summary/writer'\nimport { printLegacyAiNotice } from './notices'\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 (options) => {\n const config = readConfig()\n printLegacyAiNotice(config)\n\n let date = todayDate()\n if (options.date) {\n try {\n date = parseDate(options.date)\n } catch (error) {\n log.error((error 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 payload = buildDayPayload(date, sessions, locationContextFrom(config))\n const summary = await createSummaryWriter(config).summarize(payload)\n\n const outputPath = options.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 { REMOVED_AI_SETTING_MESSAGE, isRemovedAiSetting } from '../summary/legacy-ai'\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 session.idleTimeout 45)')\n .action((key: string, value: string) => {\n // Checked before reading or writing, so a refused key never touches config.json\n if (isRemovedAiSetting(key)) {\n log.error(REMOVED_AI_SETTING_MESSAGE)\n process.exit(1)\n }\n const config = readConfig()\n const updated = setConfigValue(config, key, value)\n writeConfig(updated)\n const isSensitive =\n key.toLowerCase().includes('key') || key.toLowerCase().includes('secret') || 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, removeCompletions, removeFishCompletions, removeHook } from '../capture/shell-hook'\nimport { claudeCodeIntegration } from '../capture/hooks/claude-code'\nimport { log } from '../utils/logger'\nimport { SKILL_AGENTS } from '../skills/agents'\nimport { removeSkills } from '../skills/actions'\n\n// The rc files `init` may have added a completions block to — checked on their own, since a file can have the\n// completions block without the hook block\nfunction completionRcFiles(): string[] {\n return ['.zshrc', '.bashrc', '.bash_profile'].map((file) => path.join(os.homedir(), file))\n}\n\n/** Removes everything else `init` adds to your shell and tools: completions and the Claude Code session hook. */\nfunction removeCompletionsAndToolHooks(): void {\n for (const rcFile of completionRcFiles()) {\n if (removeCompletions(rcFile)) log.success(`Shell completions removed from ${rcFile}`)\n }\n if (removeFishCompletions()) log.success('Fish completions removed')\n\n // Not only when Claude Code is on PATH — someone who removed Claude Code can still have the hook in its settings\n const outcome = claudeCodeIntegration.uninstall?.()\n if (outcome === 'removed') log.success('Claude Code session hook removed from ~/.claude/settings.json')\n if (outcome === 'unreadable') {\n log.warn(\n \"Couldn't read ~/.claude/settings.json, so the Claude Code session hook was left in place. Fix the file's JSON, then run: workscribe uninstall --hooks-only\"\n )\n }\n}\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(\n 'Remove shell hooks, completions, the Claude Code hook and the agent skill; optionally delete all data'\n )\n .option(\n '--hooks-only',\n 'remove shell hooks, completions and the Claude Code hook only — keep the agent skill and skip the data prompt'\n )\n .action(async (options) => {\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 removeCompletionsAndToolHooks()\n\n // Agent skills are only removed on a full uninstall: `--hooks-only` is for clearing what runs in your\n // shell and tools, and the skill is something you chose to install into your coding agents\n if (options.hooksOnly) return\n\n removeSkills(SKILL_AGENTS, { reportMissing: false })\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')} — then 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 fs from 'fs'\nimport path from 'path'\n\n// The shell hook stores `--cwd \"$PWD\"`: the folder as you reached it, through any symlink (a symlinked `~/code`, or\n// macOS's `/tmp` → `/private/tmp`). Node's `process.cwd()` and `git rev-parse --show-toplevel` give the resolved\n// path. These helpers let `note` and `context` see paths the way capture stored them.\n\nfunction realPath(target: string): string | null {\n try {\n return fs.realpathSync(target)\n } catch {\n return null // the folder is gone, or never existed\n }\n}\n\n/** The folder you're in, as you reached it: `$PWD` when it's the same folder as `process.cwd()`, else that. */\nexport function currentDirectory(where = { pwd: process.env.PWD, cwd: process.cwd() }): string {\n if (where.pwd && realPath(where.pwd) === realPath(where.cwd)) return where.pwd\n return where.cwd\n}\n\n/**\n * The repo root in every form a stored event's `cwd` may use: git's resolved `root`, and the same folder as reached\n * from `cwd` — so a repo opened through a symlink still matches its own activity.\n */\nexport function rootForms(cwd: string, root: string): string[] {\n const resolvedCwd = realPath(cwd)\n if (!resolvedCwd) return [root]\n const reached = path.resolve(cwd, path.relative(resolvedCwd, root))\n return [...new Set([root, reached])]\n}\n","import { Command } from 'commander'\nimport { insertEvent } from '../db'\nimport { getRepoContext } from '../capture/git'\nimport { readConfig } from '../config'\nimport { currentDirectory } from '../utils/working-directory'\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 // As you reached it, like the shell hook's `$PWD`, so a `projects.<path>` override and `context` match it\n const directory = currentDirectory()\n const { repoName, branch } = getRepoContext(directory, readConfig())\n insertEvent({\n captured_at: new Date().toISOString(),\n command: 'workscribe note',\n cwd: directory,\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 { readConfig } from '../config'\nimport { log } from '../utils/logger'\nimport { runWeeklySummary } from '../summary/weekly'\nimport { createSummaryWriter } from '../summary/writer'\nimport { printLegacyAiNotice } from './notices'\n\nexport function registerWeek(program: Command): void {\n program\n .command('week')\n .description('Generate a weekly digest (Mon–today)')\n .option('--fresh', 'accepted for 1.x scripts — digests are always rendered fresh')\n .option('--slack', 'post to Slack webhook from config')\n .option('--webhook <url>', 'post to a custom webhook URL')\n .action(async (options) => {\n const config = readConfig()\n printLegacyAiNotice(config)\n try {\n await runWeeklySummary({ options, config, provider: createSummaryWriter(config) })\n } catch (error) {\n log.error((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>' // left over from a 1.x config\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 {\n getRecentSessionsForRepo,\n getLastSessionTouchingFile,\n getSessionBranch,\n getSessionSummaries,\n getEventsBySessionId,\n} from '../db'\nimport { getRepoContext } from '../capture/git'\nimport { formatRepoName } from '../capture/repo-name'\nimport { currentDirectory, rootForms } from '../utils/working-directory'\nimport { readConfig } from '../config'\nimport { formatDuration, timeAgo } from '../utils/format'\nimport { log } from '../utils/logger'\nimport { describeSession } from '../ai/engines/template/describe'\nimport { toBulletList } from '../ai/engines/template/utils'\nimport { sessionToPayload, locationContextFrom } from '../summary/payload'\nimport { formatSessionHeading } from '../summary/heading'\nimport { sessionKey, pickBestSummary } from '../summary/store'\nimport type { SessionRow } from '../db/types'\nimport type { Session } from '../sessions/detector'\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 sessionMinutes(session: SessionRow): number {\n return (new Date(session.ended_at).getTime() - new Date(session.started_at).getTime()) / 60000\n}\n\nfunction toSession(row: SessionRow): Session {\n return {\n id: row.id,\n date: row.date,\n startedAt: row.started_at,\n endedAt: row.ended_at,\n repoName: row.repo_name,\n durationMinutes: sessionMinutes(row),\n eventCount: row.event_count,\n summary: null,\n events: getEventsBySessionId(row.id),\n }\n}\n\n/** A template summary rendered from the session's current events — templates are never stored, so it can't go stale. */\nfunction renderTemplateSummary(row: SessionRow): string {\n const config = readConfig()\n const payload = sessionToPayload(toSession(row), row.date, locationContextFrom(config))\n const bullets = describeSession(payload, config.summary?.includeCategories ?? [])\n return `${formatSessionHeading(payload)}\\n${toBulletList(bullets)}`\n}\n\n/** The best stored summary (skill > AI > template), or a template one so the VS Code status bar is never empty. */\nfunction resolveContextSummary(row: SessionRow): string {\n return pickBestSummary(getSessionSummaries(sessionKey(row.repo_name, row.started_at))) ?? renderTemplateSummary(row)\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: sessionMinutes(session),\n branch: getSessionBranch(session.id),\n eventCount: session.event_count,\n summary: resolveContextSummary(session),\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 = sessionMinutes(session)\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 log.plain('')\n for (const line of resolveContextSummary(session).split('\\n')) {\n log.plain(` ${line}`)\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 config = readConfig()\n const directory = currentDirectory()\n const { repoName, root, remote } = getRepoContext(directory, config)\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 // Also finds sessions stored under the other name form — captured before the setting changed, or before WOR-118\n const otherRepoName = remote ? formatRepoName(remote, !config.git.qualifyRepoName) : null\n const roots = root ? rootForms(directory, root) : []\n const sessions = getRecentSessionsForRepo({ repoName, otherRepoName, roots }, 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 { Command } from 'commander'\nimport chalk from 'chalk'\nimport { log } from '../utils/logger'\nimport { SKILL_AGENTS, SKILL_AGENT_IDS } from '../skills/agents'\nimport { detectAgents } from '../skills/detect'\nimport { resolvePackagedSkillDir } from '../skills/package-path'\nimport { groupBySkillsFolder, joinAgentNames } from '../skills/state'\nimport { AFTER_INSTALL_HINT, reasonOf } from '../skills/report'\nimport {\n describeTarget,\n formatAgentSkillLine,\n formatUndetectedAgentLine,\n installIntoFolder,\n printMessage,\n removeSkills,\n} from '../skills/actions'\nimport type { SkillAgent } from '../skills/types'\n\ninterface AgentOptions {\n agent?: string[]\n force?: boolean\n}\n\nfunction fail(message: string): never {\n log.error(message)\n process.exit(1)\n}\n\n/** The agents named with --agent (all must be known), or the given default. */\nfunction chooseAgents(options: {\n requested: string[] | undefined\n fallback: () => SkillAgent[]\n subcommand: 'install' | 'uninstall'\n}): SkillAgent[] {\n const { requested } = options\n if (!requested || requested.length === 0) return options.fallback()\n const unknown = requested.filter((id) => !SKILL_AGENT_IDS.includes(id))\n if (unknown.length > 0) {\n fail(\n `Unknown agent: ${unknown.join(', ')}. Choose from: ${SKILL_AGENT_IDS.join(', ')}. ` +\n `For example: workscribe skill ${options.subcommand} --agent claude-code`\n )\n }\n return SKILL_AGENTS.filter((agent) => requested.includes(agent.id))\n}\n\nfunction packagedSkillDir(): string {\n try {\n return resolvePackagedSkillDir()\n } catch (error) {\n fail(reasonOf(error))\n }\n}\n\nfunction installCommand(options: AgentOptions): void {\n const agents = chooseAgents({ requested: options.agent, fallback: detectAgents, subcommand: 'install' })\n if (agents.length === 0) {\n log.info(\n `No coding agents found. Workscribe can install its skill for ${joinAgentNames(SKILL_AGENTS)}. ` +\n \"If yours is installed somewhere Workscribe didn't look, name it: workscribe skill install --agent claude-code\"\n )\n return\n }\n const sourceDir = packagedSkillDir()\n for (const group of groupBySkillsFolder(agents)) {\n printMessage(installIntoFolder({ target: describeTarget(group), sourceDir, force: options.force }))\n }\n log.plain(chalk.dim(` ${AFTER_INSTALL_HINT}`))\n}\n\nfunction statusCommand(): void {\n const detected = new Set(detectAgents().map((agent) => agent.id))\n log.plain('')\n log.plain(chalk.bold(' Workscribe agent skill'))\n for (const agent of SKILL_AGENTS) {\n const line = detected.has(agent.id) ? formatAgentSkillLine(agent) : formatUndetectedAgentLine(agent)\n log.plain(` ${line}`)\n }\n log.plain('')\n}\n\nfunction uninstallCommand(options: AgentOptions): void {\n const agents = chooseAgents({ requested: options.agent, fallback: () => SKILL_AGENTS, subcommand: 'uninstall' })\n removeSkills(agents, { reportMissing: true })\n}\n\nexport function registerSkill(program: Command): void {\n const skill = program.command('skill').description('Install the Workscribe agent skill into your coding agents')\n const agentOption = `limit to these agents (${SKILL_AGENT_IDS.join(', ')})`\n\n skill\n .command('install')\n .description('Install or update the skill for every detected coding agent')\n .option('--agent <ids...>', agentOption)\n .option('--force', \"replace a workscribe skill that Workscribe didn't install\")\n .action(installCommand)\n\n skill\n .command('status')\n .description('Show which agents have the skill and whether it is up to date')\n .action(statusCommand)\n\n skill\n .command('uninstall')\n .description('Remove the skill Workscribe installed (never one you added yourself)')\n .option('--agent <ids...>', agentOption)\n .action(uninstallCommand)\n}\n","import fs from 'fs'\nimport os from 'os'\nimport { UPDATE_CHECK_PATH } from './paths'\nimport { readConfig, WorkscribeConfig } from '../config'\nimport { debugLog } from './logger'\n\nexport interface TelemetryPayload {\n installId: string\n cliVersion: string\n platform: string\n nodeVersion: string\n}\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 lastTelemetryPing?: number\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\n// Merges with whatever's already on disk rather than overwriting — checkForUpdate()\n// and pingTelemetry() each own one field in the same cache file and must not\n// silently wipe out the other's value when they write.\nfunction writeCache(updates: Partial<UpdateCache>): void {\n try {\n const current = readCache() ?? {}\n fs.writeFileSync(UPDATE_CHECK_PATH, JSON.stringify({ ...current, ...updates }), { 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\nexport function buildTelemetryPayload(config: WorkscribeConfig): TelemetryPayload {\n return {\n installId: config.telemetry.installId,\n cliVersion: __WORKSCRIBE_VERSION__,\n platform: os.platform(),\n nodeVersion: process.version,\n }\n}\n\nexport function pingTelemetry(): void {\n const config = readConfig()\n if (!config.telemetry.enabled || !config.telemetry.installId) return\n\n const cache = readCache()\n const now = Date.now()\n if (cache?.lastTelemetryPing && now - cache.lastTelemetryPing <= CHECK_INTERVAL_MS) return\n\n fetch('https://workscribe.co/api/telemetry/ping', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(buildTelemetryPayload(config)),\n })\n .then((response) => {\n // fetch() only rejects on network failure — a 4xx/5xx still resolves,\n // so without this check a server-side outage would silently look like\n // a successful ping and get throttled for a full day.\n if (!response.ok) {\n debugLog('pingTelemetry', new Error(`Ping failed with HTTP ${response.status}`))\n return\n }\n writeCache({ lastTelemetryPing: now })\n })\n .catch((error) => {\n debugLog('pingTelemetry', error)\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, shouldRunStartupChecks } from './cli/completions'\nimport { registerAlerts } from './cli/alerts'\nimport { registerContext } from './cli/context'\nimport { registerSkill } from './cli/skill'\nimport { checkForUpdate, pingTelemetry } from './utils/update-check'\nimport { ensureTelemetryFallback } from './config'\nimport { log } from './utils/logger'\n\nconst invokedCommand = process.argv[2]\nif (shouldRunStartupChecks(invokedCommand)) {\n checkForUpdate()\n // init handles its own telemetry disclosure via an interactive prompt —\n // the silent fallback is only for users who skip init entirely. Must run\n // before pingTelemetry() — otherwise a user's very first command would\n // generate the installId but the ping already read the old empty config\n // moments earlier, delaying the first ping to the next invocation.\n if (invokedCommand !== 'init') {\n ensureTelemetryFallback()\n }\n pingTelemetry()\n}\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)\nregisterSkill(program)\n\n// parseAsync (not parse) so a throw from either a sync or an async action\n// handler — e.g. getDb() failing to create its data directory — surfaces\n// here as a rejection instead of either an uncaught-exception stack trace\n// (sync actions) or an unhandled-rejection crash (async actions). _capture\n// and _hook already catch everything internally and never throw this far,\n// so this only ever engages for explicit user commands.\nprogram.parseAsync().catch((error: unknown) => {\n log.error(error instanceof Error ? error.message : String(error))\n process.exit(1)\n})\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","migration","fs","import_fs","chalk","fs","import_fs","import_os","import_path","path","os","fs","path","crypto","import_fs","import_path","path","fs","import_fs","import_path","path","fs","import_fs","import_path","step","step","step","migration","migration","fs","sessionKey","import_fs","fs","path","import_path","import_fs","import_child_process","path","fs","import_fs","import_path","step","PIPE_SEPARATORS","step","fs","command","repoName","branch","import_fs","init_capture","fs","path","import_fs","import_path","init_alerts","parsed","init_alerts","fs","import_fs","path","fs","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","os","fs","path","import_fs","import_os","import_path","fs","path","import_fs","import_path","path","fs","import_fs","import_path","os","path","chalk","import_os","import_path","import_chalk","prompts","path","os","chalk","fs","prompts","import_fs","import_path","import_os","import_prompts","import_chalk","os","import_os","fs","chalk","import_fs","import_chalk","init_alerts","os","path","import_os","import_path","init_utils","init_utils","chalk","import_chalk","fs","import_fs","import_child_process","chalk","import_chalk","init_constants","init_utils","init_constants","init_utils","init_constants","init_utils","os","import_os","init_webhook","init_webhook","chalk","import_chalk","init_webhook","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","fs","path","import_fs","import_path","fs","path","os","chalk","import_fs","import_os","import_path","import_chalk","chalk","import_chalk","init_alerts","chalk","path","import_path","import_chalk","init_utils","fail","chalk","import_chalk","fs","os","import_fs","import_os","init_capture","init_config","init_alerts"]}
|