@goondocks/myco 0.6.3 → 0.6.4

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.
Files changed (97) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/dist/{chunk-LDKXXKF6.js → chunk-2ZIBCEYO.js} +4 -4
  4. package/dist/{chunk-PQWQC3RF.js → chunk-4XVKZ3WA.js} +137 -146
  5. package/dist/chunk-4XVKZ3WA.js.map +1 -0
  6. package/dist/{chunk-25FY74AP.js → chunk-7WHF2OIZ.js} +2 -2
  7. package/dist/{chunk-JSK7L46L.js → chunk-ERG2IEWX.js} +22 -4
  8. package/dist/{chunk-JSK7L46L.js.map → chunk-ERG2IEWX.js.map} +1 -1
  9. package/dist/{chunk-RXJHB7W4.js → chunk-FPRXMJLT.js} +2 -2
  10. package/dist/{chunk-RY76WEN3.js → chunk-GENQ5QGP.js} +2 -2
  11. package/dist/{chunk-YG6MLLGL.js → chunk-HYVT345Y.js} +2 -2
  12. package/dist/{chunk-WBLTISAK.js → chunk-J4D4CROB.js} +32 -6
  13. package/dist/chunk-J4D4CROB.js.map +1 -0
  14. package/dist/{chunk-IWBWZQK6.js → chunk-MDLSAFPP.js} +2 -2
  15. package/dist/{chunk-WU4PCNIK.js → chunk-NL6WQO56.js} +2 -2
  16. package/dist/{chunk-DBMHUMG3.js → chunk-NLUE6CYG.js} +3 -3
  17. package/dist/{chunk-CQ4RKK67.js → chunk-O6PERU7U.js} +2 -2
  18. package/dist/{chunk-XNAM6Z4O.js → chunk-P723N2LP.js} +2 -2
  19. package/dist/{chunk-CK24O5YQ.js → chunk-QN4W3JUA.js} +2 -2
  20. package/dist/{chunk-ALBVNGCF.js → chunk-UP4P4OAA.js} +55 -44
  21. package/dist/{chunk-ALBVNGCF.js.map → chunk-UP4P4OAA.js.map} +1 -1
  22. package/dist/{chunk-CPVXNRGW.js → chunk-YIQLYIHW.js} +4 -4
  23. package/dist/{chunk-4WL5X7VS.js → chunk-YTFXA4RX.js} +3 -3
  24. package/dist/{chunk-RNWALAFP.js → chunk-Z74SDEKE.js} +2 -2
  25. package/dist/chunk-Z74SDEKE.js.map +1 -0
  26. package/dist/{cli-EGWAINIE.js → cli-IHILSS6N.js} +20 -20
  27. package/dist/{client-FDKJ4BY7.js → client-AGFNR2S4.js} +5 -5
  28. package/dist/{config-HDUFDOQN.js → config-IBS6KOLQ.js} +3 -3
  29. package/dist/{curate-OHIJFBYF.js → curate-3D4GHKJH.js} +9 -10
  30. package/dist/{curate-OHIJFBYF.js.map → curate-3D4GHKJH.js.map} +1 -1
  31. package/dist/{detect-providers-4U3ZPW5G.js → detect-providers-XEP4QA3R.js} +3 -3
  32. package/dist/{digest-I2XYCK2M.js → digest-7HLJXL77.js} +11 -11
  33. package/dist/{init-ZO2XQT6U.js → init-ARQ53JOR.js} +8 -8
  34. package/dist/{main-XZ6X4BUX.js → main-6AGPIMH2.js} +1972 -374
  35. package/dist/main-6AGPIMH2.js.map +1 -0
  36. package/dist/{rebuild-NAH4EW5B.js → rebuild-Q2ACEB6F.js} +9 -10
  37. package/dist/{rebuild-NAH4EW5B.js.map → rebuild-Q2ACEB6F.js.map} +1 -1
  38. package/dist/{reprocess-6FOP37XS.js → reprocess-CDEFGQOV.js} +11 -11
  39. package/dist/{restart-WSA4JSE3.js → restart-XCMILOL5.js} +6 -6
  40. package/dist/{search-QXJQUB35.js → search-7W25SKCB.js} +6 -6
  41. package/dist/{server-VXN3CJ4Y.js → server-6UDN35QN.js} +11 -11
  42. package/dist/{session-start-KQ4KCQMZ.js → session-start-K6IGAC7H.js} +9 -9
  43. package/dist/setup-digest-X5PN27F4.js +15 -0
  44. package/dist/setup-llm-S5OHQJXK.js +15 -0
  45. package/dist/src/cli.js +4 -4
  46. package/dist/src/daemon/main.js +4 -4
  47. package/dist/src/hooks/post-tool-use.js +5 -5
  48. package/dist/src/hooks/session-end.js +5 -5
  49. package/dist/src/hooks/session-start.js +4 -4
  50. package/dist/src/hooks/stop.js +7 -7
  51. package/dist/src/hooks/user-prompt-submit.js +5 -5
  52. package/dist/src/mcp/server.js +4 -4
  53. package/dist/src/prompts/extraction.md +4 -4
  54. package/dist/{stats-43OESUEB.js → stats-TTSDXGJV.js} +6 -6
  55. package/dist/ui/assets/index-08wKT7wS.css +1 -0
  56. package/dist/ui/assets/index-CMSMi4Jb.js +369 -0
  57. package/dist/ui/index.html +2 -2
  58. package/dist/{verify-IIAHBAAU.js → verify-TOWQHPBX.js} +6 -6
  59. package/dist/{version-NKOECSVH.js → version-36RVCQA6.js} +4 -4
  60. package/package.json +1 -1
  61. package/dist/chunk-PQWQC3RF.js.map +0 -1
  62. package/dist/chunk-RNWALAFP.js.map +0 -1
  63. package/dist/chunk-WBLTISAK.js.map +0 -1
  64. package/dist/main-XZ6X4BUX.js.map +0 -1
  65. package/dist/setup-digest-QNCM3PNQ.js +0 -15
  66. package/dist/setup-llm-EAOIUSPJ.js +0 -15
  67. package/dist/ui/assets/index-Bk4X_8-Z.css +0 -1
  68. package/dist/ui/assets/index-D3SY7ZHY.js +0 -299
  69. /package/dist/{chunk-LDKXXKF6.js.map → chunk-2ZIBCEYO.js.map} +0 -0
  70. /package/dist/{chunk-25FY74AP.js.map → chunk-7WHF2OIZ.js.map} +0 -0
  71. /package/dist/{chunk-RXJHB7W4.js.map → chunk-FPRXMJLT.js.map} +0 -0
  72. /package/dist/{chunk-RY76WEN3.js.map → chunk-GENQ5QGP.js.map} +0 -0
  73. /package/dist/{chunk-YG6MLLGL.js.map → chunk-HYVT345Y.js.map} +0 -0
  74. /package/dist/{chunk-IWBWZQK6.js.map → chunk-MDLSAFPP.js.map} +0 -0
  75. /package/dist/{chunk-WU4PCNIK.js.map → chunk-NL6WQO56.js.map} +0 -0
  76. /package/dist/{chunk-DBMHUMG3.js.map → chunk-NLUE6CYG.js.map} +0 -0
  77. /package/dist/{chunk-CQ4RKK67.js.map → chunk-O6PERU7U.js.map} +0 -0
  78. /package/dist/{chunk-XNAM6Z4O.js.map → chunk-P723N2LP.js.map} +0 -0
  79. /package/dist/{chunk-CK24O5YQ.js.map → chunk-QN4W3JUA.js.map} +0 -0
  80. /package/dist/{chunk-CPVXNRGW.js.map → chunk-YIQLYIHW.js.map} +0 -0
  81. /package/dist/{chunk-4WL5X7VS.js.map → chunk-YTFXA4RX.js.map} +0 -0
  82. /package/dist/{cli-EGWAINIE.js.map → cli-IHILSS6N.js.map} +0 -0
  83. /package/dist/{client-FDKJ4BY7.js.map → client-AGFNR2S4.js.map} +0 -0
  84. /package/dist/{config-HDUFDOQN.js.map → config-IBS6KOLQ.js.map} +0 -0
  85. /package/dist/{detect-providers-4U3ZPW5G.js.map → detect-providers-XEP4QA3R.js.map} +0 -0
  86. /package/dist/{digest-I2XYCK2M.js.map → digest-7HLJXL77.js.map} +0 -0
  87. /package/dist/{init-ZO2XQT6U.js.map → init-ARQ53JOR.js.map} +0 -0
  88. /package/dist/{reprocess-6FOP37XS.js.map → reprocess-CDEFGQOV.js.map} +0 -0
  89. /package/dist/{restart-WSA4JSE3.js.map → restart-XCMILOL5.js.map} +0 -0
  90. /package/dist/{search-QXJQUB35.js.map → search-7W25SKCB.js.map} +0 -0
  91. /package/dist/{server-VXN3CJ4Y.js.map → server-6UDN35QN.js.map} +0 -0
  92. /package/dist/{session-start-KQ4KCQMZ.js.map → session-start-K6IGAC7H.js.map} +0 -0
  93. /package/dist/{setup-digest-QNCM3PNQ.js.map → setup-digest-X5PN27F4.js.map} +0 -0
  94. /package/dist/{setup-llm-EAOIUSPJ.js.map → setup-llm-S5OHQJXK.js.map} +0 -0
  95. /package/dist/{stats-43OESUEB.js.map → stats-TTSDXGJV.js.map} +0 -0
  96. /package/dist/{verify-IIAHBAAU.js.map → verify-TOWQHPBX.js.map} +0 -0
  97. /package/dist/{version-NKOECSVH.js.map → version-36RVCQA6.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/daemon/server.ts","../src/daemon/router.ts","../src/daemon/static.ts","../src/daemon/lifecycle.ts","../src/daemon/batch.ts","../src/daemon/lineage.ts","../node_modules/chokidar/index.js","../node_modules/readdirp/index.js","../node_modules/chokidar/handler.js","../src/daemon/watcher.ts","../src/daemon/consolidation.ts","../src/daemon/port.ts","../src/capture/transcript-miner.ts","../src/artifacts/candidates.ts","../src/artifacts/slugify.ts","../src/daemon/api/config.ts","../src/daemon/api/stats.ts","../src/daemon/api/logs.ts","../src/daemon/api/restart.ts","../src/daemon/api/progress.ts","../src/daemon/api/operations.ts","../src/daemon/api/models.ts","../src/daemon/api/sessions.ts","../src/daemon/api/pipeline.ts","../src/daemon/api/digest.ts","../src/daemon/pipeline.ts","../src/daemon/pipeline-classify.ts","../src/daemon/main.ts"],"sourcesContent":["import http from 'node:http';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport type { DaemonLogger } from './logger.js';\nimport { getPluginVersion } from '../version.js';\nimport { Router, type RouteHandler } from './router.js';\nimport { resolveStaticFile } from './static.js';\nimport { DAEMON_EVICT_TIMEOUT_MS, DAEMON_EVICT_POLL_MS } from '../constants.js';\n\nconst DEFAULT_STATUS = 200;\n\nexport interface DaemonServerConfig {\n vaultDir: string;\n logger: DaemonLogger;\n uiDir?: string;\n}\n\nexport class DaemonServer {\n port = 0;\n readonly version: string;\n uiDir: string | null;\n private server: http.Server | null = null;\n private vaultDir: string;\n private logger: DaemonLogger;\n private router = new Router();\n\n constructor(config: DaemonServerConfig) {\n this.vaultDir = config.vaultDir;\n this.logger = config.logger;\n this.uiDir = config.uiDir ?? null;\n this.version = getPluginVersion();\n this.registerDefaultRoutes();\n }\n\n registerRoute(method: string, routePath: string, handler: RouteHandler): void {\n this.router.add(method, routePath, handler);\n }\n\n async start(port: number = 0): Promise<void> {\n return new Promise((resolve, reject) => {\n this.server = http.createServer((req, res) => this.handleRequest(req, res));\n this.server.on('error', reject);\n\n this.server.listen(port, '127.0.0.1', () => {\n const addr = this.server!.address() as { port: number };\n this.port = addr.port;\n this.writeDaemonJson();\n this.logger.info('daemon', 'Server started', { port: this.port, dashboard: `http://localhost:${this.port}/` });\n resolve();\n });\n });\n }\n\n async stop(): Promise<void> {\n return new Promise((resolve) => {\n this.removeDaemonJson();\n if (this.server) {\n this.server.close(() => {\n this.logger.info('daemon', 'Server stopped');\n resolve();\n });\n } else {\n resolve();\n }\n });\n }\n\n private registerDefaultRoutes(): void {\n this.registerRoute('GET', '/health', async () => ({\n body: {\n myco: true,\n version: this.version,\n pid: process.pid,\n uptime: process.uptime(),\n },\n }));\n }\n\n private async handleRequest(req: http.IncomingMessage, res: http.ServerResponse): Promise<void> {\n // API/daemon routes take priority over static files\n const match = this.router.match(req.method!, req.url!);\n\n if (match) {\n try {\n const body = (req.method === 'POST' || req.method === 'PUT') ? await readBody(req) : undefined;\n const result = await match.handler({\n body,\n query: match.query,\n params: match.params,\n pathname: match.pathname,\n });\n const status = result.status ?? DEFAULT_STATUS;\n const headers = { 'Content-Type': 'application/json', ...result.headers };\n res.writeHead(status, headers);\n res.end(JSON.stringify(result.body));\n } catch (error) {\n this.logger.error('daemon', 'Request handler error', {\n path: req.url,\n error: (error as Error).message,\n });\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: (error as Error).message }));\n }\n return;\n }\n\n // No API route matched — serve static files (dashboard SPA)\n if (this.uiDir && req.method === 'GET') {\n const pathname = new URL(req.url!, 'http://localhost').pathname;\n const result = resolveStaticFile(this.uiDir, pathname);\n if (result) {\n try {\n const content = await fs.promises.readFile(result.filePath);\n res.writeHead(200, {\n 'Content-Type': result.contentType,\n 'Cache-Control': result.cacheControl,\n });\n res.end(content);\n } catch {\n res.writeHead(404, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'not found' }));\n }\n return;\n }\n }\n\n res.writeHead(404, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'not found' }));\n }\n\n updateDaemonJsonSessions(sessions: string[]): void {\n const jsonPath = path.join(this.vaultDir, 'daemon.json');\n try {\n const info = JSON.parse(fs.readFileSync(jsonPath, 'utf-8'));\n info.sessions = sessions;\n fs.writeFileSync(jsonPath, JSON.stringify(info, null, 2));\n } catch { /* daemon.json may not exist during shutdown */ }\n }\n\n /**\n * Kill any existing daemon for this vault before taking over.\n * Prevents orphaned daemons when spawned from worktrees or plugin upgrades.\n * Must be called BEFORE resolvePort() so the old daemon releases the port.\n */\n async evictExistingDaemon(): Promise<void> {\n const jsonPath = path.join(this.vaultDir, 'daemon.json');\n let existingPid: number | undefined;\n try {\n const content = fs.readFileSync(jsonPath, 'utf-8');\n const info = JSON.parse(content);\n if (typeof info.pid === 'number' && info.pid !== process.pid) {\n existingPid = info.pid;\n }\n } catch { /* no daemon.json or invalid — nothing to evict */ }\n\n if (!existingPid) return;\n\n // Check if the process is alive\n try { process.kill(existingPid, 0); } catch { return; /* already dead */ }\n\n this.logger.info('daemon', 'Evicting existing daemon', { pid: existingPid });\n try { process.kill(existingPid, 'SIGTERM'); } catch { return; }\n\n // Give SIGTERM a grace period, then escalate to SIGKILL to guarantee port release\n const deadline = Date.now() + DAEMON_EVICT_TIMEOUT_MS;\n while (Date.now() < deadline) {\n await new Promise((r) => setTimeout(r, DAEMON_EVICT_POLL_MS));\n try { process.kill(existingPid, 0); } catch { return; /* dead */ }\n }\n\n this.logger.warn('daemon', 'Evicted daemon did not exit in time, sending SIGKILL', { pid: existingPid });\n try { process.kill(existingPid, 'SIGKILL'); } catch { return; }\n\n // Verify SIGKILL took effect\n await new Promise((r) => setTimeout(r, DAEMON_EVICT_POLL_MS));\n try { process.kill(existingPid, 0); } catch { return; /* dead */ }\n this.logger.warn('daemon', 'Evicted daemon still alive after SIGKILL', { pid: existingPid });\n }\n\n private writeDaemonJson(): void {\n const info = {\n pid: process.pid,\n port: this.port,\n started: new Date().toISOString(),\n sessions: [] as string[],\n };\n const jsonPath = path.join(this.vaultDir, 'daemon.json');\n fs.writeFileSync(jsonPath, JSON.stringify(info, null, 2));\n }\n\n private removeDaemonJson(): void {\n const jsonPath = path.join(this.vaultDir, 'daemon.json');\n try {\n const content = fs.readFileSync(jsonPath, 'utf-8');\n const info = JSON.parse(content);\n // Only delete if we still own the file — a successor daemon may have taken over.\n if (info.pid !== process.pid) return;\n fs.unlinkSync(jsonPath);\n } catch { /* already gone or unreadable */ }\n }\n}\n\nfunction readBody(req: http.IncomingMessage): Promise<unknown> {\n return new Promise((resolve, reject) => {\n let data = '';\n req.on('data', (chunk: string) => { data += chunk; });\n req.on('end', () => {\n try { resolve(data ? JSON.parse(data) : {}); }\n catch (e) { reject(e); }\n });\n req.on('error', reject);\n });\n}\n","export interface RouteRequest {\n body: unknown;\n query: Record<string, string>;\n params: Record<string, string>;\n pathname: string;\n}\n\nexport interface RouteResponse {\n status?: number;\n headers?: Record<string, string>;\n body: unknown;\n}\n\nexport type RouteHandler = (req: RouteRequest) => Promise<RouteResponse>;\n\ninterface RouteEntry {\n method: string;\n pattern: string;\n handler: RouteHandler;\n type: 'exact' | 'param' | 'prefix';\n segments?: string[];\n}\n\nexport interface RouteMatch {\n handler: RouteHandler;\n params: Record<string, string>;\n query: Record<string, string>;\n pathname: string;\n}\n\nexport class Router {\n private routes: RouteEntry[] = [];\n\n add(method: string, pattern: string, handler: RouteHandler): void {\n const type = pattern.includes(':') ? 'param'\n : pattern.endsWith('/*') ? 'prefix'\n : 'exact';\n const segments = type === 'param' ? pattern.split('/') : undefined;\n this.routes.push({ method, pattern, handler, type, segments });\n }\n\n /**\n * Match a request against registered routes.\n * Priority: exact > parameterized > prefix. Within parameterized routes,\n * first-registered wins if multiple patterns match at the same depth.\n */\n match(method: string, rawUrl: string): RouteMatch | undefined {\n const url = new URL(rawUrl, 'http://localhost');\n const pathname = url.pathname;\n const query: Record<string, string> = {};\n url.searchParams.forEach((v, k) => { query[k] = v; });\n\n // Priority: exact > param > prefix\n let paramMatch: RouteMatch | undefined;\n let prefixMatch: RouteMatch | undefined;\n\n for (const route of this.routes) {\n if (route.method !== method) continue;\n\n if (route.type === 'exact' && route.pattern === pathname) {\n return { handler: route.handler, params: {}, query, pathname };\n }\n\n if (route.type === 'param' && !paramMatch && route.segments) {\n const parts = pathname.split('/');\n if (parts.length === route.segments.length) {\n const params: Record<string, string> = {};\n let matched = true;\n for (let i = 0; i < route.segments.length; i++) {\n if (route.segments[i].startsWith(':')) {\n params[route.segments[i].slice(1)] = parts[i];\n } else if (route.segments[i] !== parts[i]) {\n matched = false;\n break;\n }\n }\n if (matched) {\n paramMatch = { handler: route.handler, params, query, pathname };\n }\n }\n }\n\n if (route.type === 'prefix' && !prefixMatch) {\n const prefix = route.pattern.slice(0, -1); // Remove trailing *\n if (pathname.startsWith(prefix)) {\n prefixMatch = { handler: route.handler, params: {}, query, pathname };\n }\n }\n }\n\n return paramMatch ?? prefixMatch;\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\n\nconst HASHED_ASSET_PREFIX = '/assets/';\nconst IMMUTABLE_CACHE = 'public, max-age=31536000, immutable';\nconst NO_CACHE = 'no-cache';\n\nexport const MIME_TYPES: Record<string, string> = {\n '.html': 'text/html',\n '.js': 'application/javascript',\n '.css': 'text/css',\n '.json': 'application/json',\n '.svg': 'image/svg+xml',\n '.png': 'image/png',\n '.ico': 'image/x-icon',\n '.woff': 'font/woff',\n '.woff2': 'font/woff2',\n '.ttf': 'font/ttf',\n};\n\nexport interface StaticFileResult {\n filePath: string;\n contentType: string;\n cacheControl: string;\n}\n\n/** Resolve a request to a file in the UI directory. Returns undefined if blocked (path traversal). */\nexport function resolveStaticFile(uiDir: string, pathname: string): StaticFileResult | undefined {\n // Strip leading slash to get relative path\n const relative = pathname.startsWith('/') ? pathname.slice(1) : pathname;\n\n // Resolve \"/\" to index.html\n const resolved = path.resolve(uiDir, relative || 'index.html');\n if (!resolved.startsWith(path.resolve(uiDir))) {\n return undefined;\n }\n\n // Serve the file if it exists\n if (fs.existsSync(resolved) && fs.statSync(resolved).isFile()) {\n const ext = path.extname(resolved);\n const contentType = MIME_TYPES[ext] ?? 'application/octet-stream';\n const cacheControl = pathname.startsWith(HASHED_ASSET_PREFIX) ? IMMUTABLE_CACHE : NO_CACHE;\n return { filePath: resolved, contentType, cacheControl };\n }\n\n // SPA fallback: serve index.html for any non-file path\n const indexPath = path.join(uiDir, 'index.html');\n if (fs.existsSync(indexPath)) {\n return { filePath: indexPath, contentType: 'text/html', cacheControl: NO_CACHE };\n }\n\n return undefined;\n}\n","export interface SessionMetadata {\n started_at: string;\n branch?: string;\n}\n\nexport interface RegisteredSession extends SessionMetadata {\n id: string;\n}\n\ninterface RegistryOptions {\n gracePeriod: number;\n onEmpty: () => void;\n}\n\nexport class SessionRegistry {\n private _sessions: Map<string, SessionMetadata> = new Map();\n private graceTimer: ReturnType<typeof setTimeout> | null = null;\n private gracePeriod: number;\n private onEmpty: () => void;\n\n constructor(options: RegistryOptions) {\n this.gracePeriod = options.gracePeriod;\n this.onEmpty = options.onEmpty;\n }\n\n get sessions(): string[] {\n return [...this._sessions.keys()];\n }\n\n register(sessionId: string, metadata?: SessionMetadata): void {\n if (!this._sessions.has(sessionId)) {\n this._sessions.set(sessionId, metadata ?? { started_at: new Date().toISOString() });\n }\n this.cancelGrace();\n }\n\n getSession(sessionId: string): RegisteredSession | undefined {\n const meta = this._sessions.get(sessionId);\n if (!meta) return undefined;\n return { id: sessionId, ...meta };\n }\n\n unregister(sessionId: string): void {\n this._sessions.delete(sessionId);\n if (this._sessions.size === 0) {\n this.startGrace();\n }\n }\n\n destroy(): void {\n this.cancelGrace();\n this._sessions.clear();\n }\n\n private startGrace(): void {\n this.cancelGrace();\n this.graceTimer = setTimeout(() => {\n if (this._sessions.size === 0) {\n this.onEmpty();\n }\n }, this.gracePeriod * 1000);\n }\n\n private cancelGrace(): void {\n if (this.graceTimer) {\n clearTimeout(this.graceTimer);\n this.graceTimer = null;\n }\n }\n}\n","export interface BatchEvent {\n type: string;\n session_id: string;\n timestamp: string;\n prompt?: string;\n tool_name?: string;\n tool_input?: unknown;\n output_preview?: string;\n [key: string]: unknown;\n}\n\ntype BatchClosedCallback = (events: BatchEvent[]) => void | Promise<void>;\n\nexport class BatchManager {\n private batches: Map<string, BatchEvent[]> = new Map();\n private onBatchClosed: BatchClosedCallback;\n\n constructor(onBatchClosed: BatchClosedCallback) {\n this.onBatchClosed = onBatchClosed;\n }\n\n addEvent(event: BatchEvent): void {\n const sid = event.session_id;\n\n if (event.type === 'user_prompt') {\n const current = this.batches.get(sid);\n if (current && current.length > 0) {\n // Fire-and-forget, but log errors\n Promise.resolve(this.onBatchClosed(current)).catch((err) => {\n console.error(`[mycod] batch callback error: ${(err as Error).message}`);\n });\n }\n this.batches.set(sid, [event]);\n } else {\n const current = this.batches.get(sid);\n if (current) {\n current.push(event);\n }\n }\n }\n\n finalize(sessionId: string): BatchEvent[] {\n const current = this.batches.get(sessionId);\n this.batches.delete(sessionId);\n return current ?? [];\n }\n\n hasOpenBatch(sessionId: string): boolean {\n return this.batches.has(sessionId) && this.batches.get(sessionId)!.length > 0;\n }\n\n batchSize(sessionId: string): number {\n return this.batches.get(sessionId)?.length ?? 0;\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport type { RegisteredSession } from './lifecycle.js';\n\nexport const LINEAGE_IMMEDIATE_GAP_SECONDS = 5;\nexport const LINEAGE_FALLBACK_MAX_HOURS = 24;\nexport const LINEAGE_SIMILARITY_THRESHOLD = 0.7;\nexport const LINEAGE_SIMILARITY_HIGH_CONFIDENCE = 0.9;\nexport const LINEAGE_SIMILARITY_CANDIDATES = 3;\nexport const LINEAGE_SIMILARITY_MAX_TOKENS = 8; // expects a single float score\n\nconst MS_PER_SECOND = 1000;\nconst MS_PER_HOUR = 3_600_000;\n\ninterface RecentSession {\n id: string;\n ended?: string;\n branch?: string;\n}\n\ninterface SessionContext {\n started_at: string;\n branch?: string;\n}\n\nexport interface LineageLink {\n parent: string;\n child: string;\n signal: 'clear' | 'clear_active' | 'inferred' | 'plan_reference' | 'semantic_similarity';\n confidence: 'high' | 'medium' | 'low';\n timestamp?: string;\n}\n\ninterface LineageState {\n links: LineageLink[];\n /** Maps session IDs to the artifact/plan IDs they produced. Used for plan_reference lineage detection. */\n sessionArtifacts: Record<string, string[]>;\n /** @deprecated Alias for sessionArtifacts — kept for backward compat with existing lineage.json files */\n sessionPlans?: Record<string, string[]>;\n}\n\nexport class LineageGraph {\n private state: LineageState;\n private filePath: string;\n\n constructor(vaultDir: string) {\n this.filePath = path.join(vaultDir, 'lineage.json');\n fs.mkdirSync(path.dirname(this.filePath), { recursive: true });\n this.state = this.load();\n }\n\n addLink(link: LineageLink): void {\n if (this.state.links.some((l) => l.parent === link.parent && l.child === link.child)) return;\n this.state.links.push({ ...link, timestamp: link.timestamp ?? new Date().toISOString() });\n this.persist();\n }\n\n /** Register an artifact (plan, spec, doc) as produced by a session. */\n registerArtifactForSession(sessionId: string, artifactId: string): void {\n if (!this.state.sessionArtifacts[sessionId]) this.state.sessionArtifacts[sessionId] = [];\n if (!this.state.sessionArtifacts[sessionId].includes(artifactId)) {\n this.state.sessionArtifacts[sessionId].push(artifactId);\n this.persist();\n }\n }\n\n /** @deprecated Use registerArtifactForSession instead */\n registerPlanForSession(sessionId: string, planId: string): void {\n this.registerArtifactForSession(sessionId, planId);\n }\n\n detectLineage(childSessionId: string, firstPrompt: string): LineageLink | null {\n for (const [sessionId, artifactIds] of Object.entries(this.state.sessionArtifacts)) {\n if (sessionId === childSessionId) continue;\n for (const artifactId of artifactIds) {\n if (firstPrompt.includes(artifactId)) {\n const link: LineageLink = { parent: sessionId, child: childSessionId, signal: 'plan_reference', confidence: 'high' };\n this.addLink(link);\n return link;\n }\n }\n }\n return null;\n }\n\n detectHeuristicParent(\n childSessionId: string,\n context: SessionContext,\n recentSessions: RecentSession[],\n activeSessions: RegisteredSession[],\n firstPrompt?: string,\n ): LineageLink | null {\n const startedAt = new Date(context.started_at).getTime();\n\n // Tier 1: session ended within LINEAGE_IMMEDIATE_GAP_SECONDS\n for (const session of recentSessions) {\n if (!session.ended) continue;\n const endedAt = new Date(session.ended).getTime();\n const gapSeconds = (startedAt - endedAt) / MS_PER_SECOND;\n if (gapSeconds >= 0 && gapSeconds <= LINEAGE_IMMEDIATE_GAP_SECONDS) {\n const link: LineageLink = { parent: session.id, child: childSessionId, signal: 'clear', confidence: 'high' };\n this.addLink(link);\n return link;\n }\n }\n\n // Tier 2: active session (race condition)\n for (const session of activeSessions) {\n if (session.id === childSessionId) continue;\n const link: LineageLink = { parent: session.id, child: childSessionId, signal: 'clear_active', confidence: 'high' };\n this.addLink(link);\n return link;\n }\n\n // Tier 3: recently completed session on same branch within LINEAGE_FALLBACK_MAX_HOURS\n if (context.branch) {\n for (const session of recentSessions) {\n if (!session.ended || !session.branch) continue;\n if (session.branch !== context.branch) continue;\n const endedAt = new Date(session.ended).getTime();\n const hoursAgo = (startedAt - endedAt) / MS_PER_HOUR;\n if (hoursAgo >= 0 && hoursAgo <= LINEAGE_FALLBACK_MAX_HOURS) {\n const link: LineageLink = { parent: session.id, child: childSessionId, signal: 'inferred', confidence: 'medium' };\n this.addLink(link);\n return link;\n }\n }\n }\n\n // Plan-reference detection (existing method)\n if (firstPrompt) {\n return this.detectLineage(childSessionId, firstPrompt);\n }\n\n return null;\n }\n\n getLinks(): LineageLink[] { return [...this.state.links]; }\n getChildren(sessionId: string): string[] { return this.state.links.filter((l) => l.parent === sessionId).map((l) => l.child); }\n getParent(sessionId: string): string | undefined { return this.state.links.find((l) => l.child === sessionId)?.parent; }\n\n private load(): LineageState {\n try {\n const raw = JSON.parse(fs.readFileSync(this.filePath, 'utf-8')) as Record<string, unknown>;\n // Migrate from old sessionPlans to sessionArtifacts\n const sessionArtifacts = (raw.sessionArtifacts ?? raw.sessionPlans ?? {}) as Record<string, string[]>;\n return { links: (raw.links ?? []) as LineageLink[], sessionArtifacts };\n }\n catch { return { links: [], sessionArtifacts: {} }; }\n }\n\n private persist(): void {\n const tmp = this.filePath + '.tmp';\n fs.writeFileSync(tmp, JSON.stringify(this.state, null, 2));\n fs.renameSync(tmp, this.filePath);\n }\n}\n","/*! chokidar - MIT License (c) 2012 Paul Miller (paulmillr.com) */\nimport { EventEmitter } from 'node:events';\nimport { stat as statcb, Stats } from 'node:fs';\nimport { readdir, stat } from 'node:fs/promises';\nimport * as sp from 'node:path';\nimport { readdirp, ReaddirpStream } from 'readdirp';\nimport { EMPTY_FN, EVENTS as EV, isIBMi, isWindows, NodeFsHandler, STR_CLOSE, STR_END, } from './handler.js';\nconst SLASH = '/';\nconst SLASH_SLASH = '//';\nconst ONE_DOT = '.';\nconst TWO_DOTS = '..';\nconst STRING_TYPE = 'string';\nconst BACK_SLASH_RE = /\\\\/g;\nconst DOUBLE_SLASH_RE = /\\/\\//g;\nconst DOT_RE = /\\..*\\.(sw[px])$|~$|\\.subl.*\\.tmp/;\nconst REPLACER_RE = /^\\.[/\\\\]/;\nfunction arrify(item) {\n return Array.isArray(item) ? item : [item];\n}\nconst isMatcherObject = (matcher) => typeof matcher === 'object' && matcher !== null && !(matcher instanceof RegExp);\nfunction createPattern(matcher) {\n if (typeof matcher === 'function')\n return matcher;\n if (typeof matcher === 'string')\n return (string) => matcher === string;\n if (matcher instanceof RegExp)\n return (string) => matcher.test(string);\n if (typeof matcher === 'object' && matcher !== null) {\n return (string) => {\n if (matcher.path === string)\n return true;\n if (matcher.recursive) {\n const relative = sp.relative(matcher.path, string);\n if (!relative) {\n return false;\n }\n return !relative.startsWith('..') && !sp.isAbsolute(relative);\n }\n return false;\n };\n }\n return () => false;\n}\nfunction normalizePath(path) {\n if (typeof path !== 'string')\n throw new Error('string expected');\n path = sp.normalize(path);\n path = path.replace(/\\\\/g, '/');\n let prepend = false;\n if (path.startsWith('//'))\n prepend = true;\n path = path.replace(DOUBLE_SLASH_RE, '/');\n if (prepend)\n path = '/' + path;\n return path;\n}\nfunction matchPatterns(patterns, testString, stats) {\n const path = normalizePath(testString);\n for (let index = 0; index < patterns.length; index++) {\n const pattern = patterns[index];\n if (pattern(path, stats)) {\n return true;\n }\n }\n return false;\n}\nfunction anymatch(matchers, testString) {\n if (matchers == null) {\n throw new TypeError('anymatch: specify first argument');\n }\n // Early cache for matchers.\n const matchersArray = arrify(matchers);\n const patterns = matchersArray.map((matcher) => createPattern(matcher));\n if (testString == null) {\n return (testString, stats) => {\n return matchPatterns(patterns, testString, stats);\n };\n }\n return matchPatterns(patterns, testString);\n}\nconst unifyPaths = (paths_) => {\n const paths = arrify(paths_).flat();\n if (!paths.every((p) => typeof p === STRING_TYPE)) {\n throw new TypeError(`Non-string provided as watch path: ${paths}`);\n }\n return paths.map(normalizePathToUnix);\n};\n// If SLASH_SLASH occurs at the beginning of path, it is not replaced\n// because \"//StoragePC/DrivePool/Movies\" is a valid network path\nconst toUnix = (string) => {\n let str = string.replace(BACK_SLASH_RE, SLASH);\n let prepend = false;\n if (str.startsWith(SLASH_SLASH)) {\n prepend = true;\n }\n str = str.replace(DOUBLE_SLASH_RE, SLASH);\n if (prepend) {\n str = SLASH + str;\n }\n return str;\n};\n// Our version of upath.normalize\n// TODO: this is not equal to path-normalize module - investigate why\nconst normalizePathToUnix = (path) => toUnix(sp.normalize(toUnix(path)));\n// TODO: refactor\nconst normalizeIgnored = (cwd = '') => (path) => {\n if (typeof path === 'string') {\n return normalizePathToUnix(sp.isAbsolute(path) ? path : sp.join(cwd, path));\n }\n else {\n return path;\n }\n};\nconst getAbsolutePath = (path, cwd) => {\n if (sp.isAbsolute(path)) {\n return path;\n }\n return sp.join(cwd, path);\n};\nconst EMPTY_SET = Object.freeze(new Set());\n/**\n * Directory entry.\n */\nclass DirEntry {\n path;\n _removeWatcher;\n items;\n constructor(dir, removeWatcher) {\n this.path = dir;\n this._removeWatcher = removeWatcher;\n this.items = new Set();\n }\n add(item) {\n const { items } = this;\n if (!items)\n return;\n if (item !== ONE_DOT && item !== TWO_DOTS)\n items.add(item);\n }\n async remove(item) {\n const { items } = this;\n if (!items)\n return;\n items.delete(item);\n if (items.size > 0)\n return;\n const dir = this.path;\n try {\n await readdir(dir);\n }\n catch (err) {\n if (this._removeWatcher) {\n this._removeWatcher(sp.dirname(dir), sp.basename(dir));\n }\n }\n }\n has(item) {\n const { items } = this;\n if (!items)\n return;\n return items.has(item);\n }\n getChildren() {\n const { items } = this;\n if (!items)\n return [];\n return [...items.values()];\n }\n dispose() {\n this.items.clear();\n this.path = '';\n this._removeWatcher = EMPTY_FN;\n this.items = EMPTY_SET;\n Object.freeze(this);\n }\n}\nconst STAT_METHOD_F = 'stat';\nconst STAT_METHOD_L = 'lstat';\nexport class WatchHelper {\n fsw;\n path;\n watchPath;\n fullWatchPath;\n dirParts;\n followSymlinks;\n statMethod;\n constructor(path, follow, fsw) {\n this.fsw = fsw;\n const watchPath = path;\n this.path = path = path.replace(REPLACER_RE, '');\n this.watchPath = watchPath;\n this.fullWatchPath = sp.resolve(watchPath);\n this.dirParts = [];\n this.dirParts.forEach((parts) => {\n if (parts.length > 1)\n parts.pop();\n });\n this.followSymlinks = follow;\n this.statMethod = follow ? STAT_METHOD_F : STAT_METHOD_L;\n }\n entryPath(entry) {\n return sp.join(this.watchPath, sp.relative(this.watchPath, entry.fullPath));\n }\n filterPath(entry) {\n const { stats } = entry;\n if (stats && stats.isSymbolicLink())\n return this.filterDir(entry);\n const resolvedPath = this.entryPath(entry);\n // TODO: what if stats is undefined? remove !\n return this.fsw._isntIgnored(resolvedPath, stats) && this.fsw._hasReadPermissions(stats);\n }\n filterDir(entry) {\n return this.fsw._isntIgnored(this.entryPath(entry), entry.stats);\n }\n}\n/**\n * Watches files & directories for changes. Emitted events:\n * `add`, `addDir`, `change`, `unlink`, `unlinkDir`, `all`, `error`\n *\n * new FSWatcher()\n * .add(directories)\n * .on('add', path => log('File', path, 'was added'))\n */\nexport class FSWatcher extends EventEmitter {\n closed;\n options;\n _closers;\n _ignoredPaths;\n _throttled;\n _streams;\n _symlinkPaths;\n _watched;\n _pendingWrites;\n _pendingUnlinks;\n _readyCount;\n _emitReady;\n _closePromise;\n _userIgnored;\n _readyEmitted;\n _emitRaw;\n _boundRemove;\n _nodeFsHandler;\n // Not indenting methods for history sake; for now.\n constructor(_opts = {}) {\n super();\n this.closed = false;\n this._closers = new Map();\n this._ignoredPaths = new Set();\n this._throttled = new Map();\n this._streams = new Set();\n this._symlinkPaths = new Map();\n this._watched = new Map();\n this._pendingWrites = new Map();\n this._pendingUnlinks = new Map();\n this._readyCount = 0;\n this._readyEmitted = false;\n const awf = _opts.awaitWriteFinish;\n const DEF_AWF = { stabilityThreshold: 2000, pollInterval: 100 };\n const opts = {\n // Defaults\n persistent: true,\n ignoreInitial: false,\n ignorePermissionErrors: false,\n interval: 100,\n binaryInterval: 300,\n followSymlinks: true,\n usePolling: false,\n // useAsync: false,\n atomic: true, // NOTE: overwritten later (depends on usePolling)\n ..._opts,\n // Change format\n ignored: _opts.ignored ? arrify(_opts.ignored) : arrify([]),\n awaitWriteFinish: awf === true ? DEF_AWF : typeof awf === 'object' ? { ...DEF_AWF, ...awf } : false,\n };\n // Always default to polling on IBM i because fs.watch() is not available on IBM i.\n if (isIBMi)\n opts.usePolling = true;\n // Editor atomic write normalization enabled by default with fs.watch\n if (opts.atomic === undefined)\n opts.atomic = !opts.usePolling;\n // opts.atomic = typeof _opts.atomic === 'number' ? _opts.atomic : 100;\n // Global override. Useful for developers, who need to force polling for all\n // instances of chokidar, regardless of usage / dependency depth\n const envPoll = process.env.CHOKIDAR_USEPOLLING;\n if (envPoll !== undefined) {\n const envLower = envPoll.toLowerCase();\n if (envLower === 'false' || envLower === '0')\n opts.usePolling = false;\n else if (envLower === 'true' || envLower === '1')\n opts.usePolling = true;\n else\n opts.usePolling = !!envLower;\n }\n const envInterval = process.env.CHOKIDAR_INTERVAL;\n if (envInterval)\n opts.interval = Number.parseInt(envInterval, 10);\n // This is done to emit ready only once, but each 'add' will increase that?\n let readyCalls = 0;\n this._emitReady = () => {\n readyCalls++;\n if (readyCalls >= this._readyCount) {\n this._emitReady = EMPTY_FN;\n this._readyEmitted = true;\n // use process.nextTick to allow time for listener to be bound\n process.nextTick(() => this.emit(EV.READY));\n }\n };\n this._emitRaw = (...args) => this.emit(EV.RAW, ...args);\n this._boundRemove = this._remove.bind(this);\n this.options = opts;\n this._nodeFsHandler = new NodeFsHandler(this);\n // You’re frozen when your heart’s not open.\n Object.freeze(opts);\n }\n _addIgnoredPath(matcher) {\n if (isMatcherObject(matcher)) {\n // return early if we already have a deeply equal matcher object\n for (const ignored of this._ignoredPaths) {\n if (isMatcherObject(ignored) &&\n ignored.path === matcher.path &&\n ignored.recursive === matcher.recursive) {\n return;\n }\n }\n }\n this._ignoredPaths.add(matcher);\n }\n _removeIgnoredPath(matcher) {\n this._ignoredPaths.delete(matcher);\n // now find any matcher objects with the matcher as path\n if (typeof matcher === 'string') {\n for (const ignored of this._ignoredPaths) {\n // TODO (43081j): make this more efficient.\n // probably just make a `this._ignoredDirectories` or some\n // such thing.\n if (isMatcherObject(ignored) && ignored.path === matcher) {\n this._ignoredPaths.delete(ignored);\n }\n }\n }\n }\n // Public methods\n /**\n * Adds paths to be watched on an existing FSWatcher instance.\n * @param paths_ file or file list. Other arguments are unused\n */\n add(paths_, _origAdd, _internal) {\n const { cwd } = this.options;\n this.closed = false;\n this._closePromise = undefined;\n let paths = unifyPaths(paths_);\n if (cwd) {\n paths = paths.map((path) => {\n const absPath = getAbsolutePath(path, cwd);\n // Check `path` instead of `absPath` because the cwd portion can't be a glob\n return absPath;\n });\n }\n paths.forEach((path) => {\n this._removeIgnoredPath(path);\n });\n this._userIgnored = undefined;\n if (!this._readyCount)\n this._readyCount = 0;\n this._readyCount += paths.length;\n Promise.all(paths.map(async (path) => {\n const res = await this._nodeFsHandler._addToNodeFs(path, !_internal, undefined, 0, _origAdd);\n if (res)\n this._emitReady();\n return res;\n })).then((results) => {\n if (this.closed)\n return;\n results.forEach((item) => {\n if (item)\n this.add(sp.dirname(item), sp.basename(_origAdd || item));\n });\n });\n return this;\n }\n /**\n * Close watchers or start ignoring events from specified paths.\n */\n unwatch(paths_) {\n if (this.closed)\n return this;\n const paths = unifyPaths(paths_);\n const { cwd } = this.options;\n paths.forEach((path) => {\n // convert to absolute path unless relative path already matches\n if (!sp.isAbsolute(path) && !this._closers.has(path)) {\n if (cwd)\n path = sp.join(cwd, path);\n path = sp.resolve(path);\n }\n this._closePath(path);\n this._addIgnoredPath(path);\n if (this._watched.has(path)) {\n this._addIgnoredPath({\n path,\n recursive: true,\n });\n }\n // reset the cached userIgnored anymatch fn\n // to make ignoredPaths changes effective\n this._userIgnored = undefined;\n });\n return this;\n }\n /**\n * Close watchers and remove all listeners from watched paths.\n */\n close() {\n if (this._closePromise) {\n return this._closePromise;\n }\n this.closed = true;\n // Memory management.\n this.removeAllListeners();\n const closers = [];\n this._closers.forEach((closerList) => closerList.forEach((closer) => {\n const promise = closer();\n if (promise instanceof Promise)\n closers.push(promise);\n }));\n this._streams.forEach((stream) => stream.destroy());\n this._userIgnored = undefined;\n this._readyCount = 0;\n this._readyEmitted = false;\n this._watched.forEach((dirent) => dirent.dispose());\n this._closers.clear();\n this._watched.clear();\n this._streams.clear();\n this._symlinkPaths.clear();\n this._throttled.clear();\n this._closePromise = closers.length\n ? Promise.all(closers).then(() => undefined)\n : Promise.resolve();\n return this._closePromise;\n }\n /**\n * Expose list of watched paths\n * @returns for chaining\n */\n getWatched() {\n const watchList = {};\n this._watched.forEach((entry, dir) => {\n const key = this.options.cwd ? sp.relative(this.options.cwd, dir) : dir;\n const index = key || ONE_DOT;\n watchList[index] = entry.getChildren().sort();\n });\n return watchList;\n }\n emitWithAll(event, args) {\n this.emit(event, ...args);\n if (event !== EV.ERROR)\n this.emit(EV.ALL, event, ...args);\n }\n // Common helpers\n // --------------\n /**\n * Normalize and emit events.\n * Calling _emit DOES NOT MEAN emit() would be called!\n * @param event Type of event\n * @param path File or directory path\n * @param stats arguments to be passed with event\n * @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag\n */\n async _emit(event, path, stats) {\n if (this.closed)\n return;\n const opts = this.options;\n if (isWindows)\n path = sp.normalize(path);\n if (opts.cwd)\n path = sp.relative(opts.cwd, path);\n const args = [path];\n if (stats != null)\n args.push(stats);\n const awf = opts.awaitWriteFinish;\n let pw;\n if (awf && (pw = this._pendingWrites.get(path))) {\n pw.lastChange = new Date();\n return this;\n }\n if (opts.atomic) {\n if (event === EV.UNLINK) {\n this._pendingUnlinks.set(path, [event, ...args]);\n setTimeout(() => {\n this._pendingUnlinks.forEach((entry, path) => {\n this.emit(...entry);\n this.emit(EV.ALL, ...entry);\n this._pendingUnlinks.delete(path);\n });\n }, typeof opts.atomic === 'number' ? opts.atomic : 100);\n return this;\n }\n if (event === EV.ADD && this._pendingUnlinks.has(path)) {\n event = EV.CHANGE;\n this._pendingUnlinks.delete(path);\n }\n }\n if (awf && (event === EV.ADD || event === EV.CHANGE) && this._readyEmitted) {\n const awfEmit = (err, stats) => {\n if (err) {\n event = EV.ERROR;\n args[0] = err;\n this.emitWithAll(event, args);\n }\n else if (stats) {\n // if stats doesn't exist the file must have been deleted\n if (args.length > 1) {\n args[1] = stats;\n }\n else {\n args.push(stats);\n }\n this.emitWithAll(event, args);\n }\n };\n this._awaitWriteFinish(path, awf.stabilityThreshold, event, awfEmit);\n return this;\n }\n if (event === EV.CHANGE) {\n const isThrottled = !this._throttle(EV.CHANGE, path, 50);\n if (isThrottled)\n return this;\n }\n if (opts.alwaysStat &&\n stats === undefined &&\n (event === EV.ADD || event === EV.ADD_DIR || event === EV.CHANGE)) {\n const fullPath = opts.cwd ? sp.join(opts.cwd, path) : path;\n let stats;\n try {\n stats = await stat(fullPath);\n }\n catch (err) {\n // do nothing\n }\n // Suppress event when fs_stat fails, to avoid sending undefined 'stat'\n if (!stats || this.closed)\n return;\n args.push(stats);\n }\n this.emitWithAll(event, args);\n return this;\n }\n /**\n * Common handler for errors\n * @returns The error if defined, otherwise the value of the FSWatcher instance's `closed` flag\n */\n _handleError(error) {\n const code = error && error.code;\n if (error &&\n code !== 'ENOENT' &&\n code !== 'ENOTDIR' &&\n (!this.options.ignorePermissionErrors || (code !== 'EPERM' && code !== 'EACCES'))) {\n this.emit(EV.ERROR, error);\n }\n return error || this.closed;\n }\n /**\n * Helper utility for throttling\n * @param actionType type being throttled\n * @param path being acted upon\n * @param timeout duration of time to suppress duplicate actions\n * @returns tracking object or false if action should be suppressed\n */\n _throttle(actionType, path, timeout) {\n if (!this._throttled.has(actionType)) {\n this._throttled.set(actionType, new Map());\n }\n const action = this._throttled.get(actionType);\n if (!action)\n throw new Error('invalid throttle');\n const actionPath = action.get(path);\n if (actionPath) {\n actionPath.count++;\n return false;\n }\n // eslint-disable-next-line prefer-const\n let timeoutObject;\n const clear = () => {\n const item = action.get(path);\n const count = item ? item.count : 0;\n action.delete(path);\n clearTimeout(timeoutObject);\n if (item)\n clearTimeout(item.timeoutObject);\n return count;\n };\n timeoutObject = setTimeout(clear, timeout);\n const thr = { timeoutObject, clear, count: 0 };\n action.set(path, thr);\n return thr;\n }\n _incrReadyCount() {\n return this._readyCount++;\n }\n /**\n * Awaits write operation to finish.\n * Polls a newly created file for size variations. When files size does not change for 'threshold' milliseconds calls callback.\n * @param path being acted upon\n * @param threshold Time in milliseconds a file size must be fixed before acknowledging write OP is finished\n * @param event\n * @param awfEmit Callback to be called when ready for event to be emitted.\n */\n _awaitWriteFinish(path, threshold, event, awfEmit) {\n const awf = this.options.awaitWriteFinish;\n if (typeof awf !== 'object')\n return;\n const pollInterval = awf.pollInterval;\n let timeoutHandler;\n let fullPath = path;\n if (this.options.cwd && !sp.isAbsolute(path)) {\n fullPath = sp.join(this.options.cwd, path);\n }\n const now = new Date();\n const writes = this._pendingWrites;\n function awaitWriteFinishFn(prevStat) {\n statcb(fullPath, (err, curStat) => {\n if (err || !writes.has(path)) {\n if (err && err.code !== 'ENOENT')\n awfEmit(err);\n return;\n }\n const now = Number(new Date());\n if (prevStat && curStat.size !== prevStat.size) {\n writes.get(path).lastChange = now;\n }\n const pw = writes.get(path);\n const df = now - pw.lastChange;\n if (df >= threshold) {\n writes.delete(path);\n awfEmit(undefined, curStat);\n }\n else {\n timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);\n }\n });\n }\n if (!writes.has(path)) {\n writes.set(path, {\n lastChange: now,\n cancelWait: () => {\n writes.delete(path);\n clearTimeout(timeoutHandler);\n return event;\n },\n });\n timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval);\n }\n }\n /**\n * Determines whether user has asked to ignore this path.\n */\n _isIgnored(path, stats) {\n if (this.options.atomic && DOT_RE.test(path))\n return true;\n if (!this._userIgnored) {\n const { cwd } = this.options;\n const ign = this.options.ignored;\n const ignored = (ign || []).map(normalizeIgnored(cwd));\n const ignoredPaths = [...this._ignoredPaths];\n const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];\n this._userIgnored = anymatch(list, undefined);\n }\n return this._userIgnored(path, stats);\n }\n _isntIgnored(path, stat) {\n return !this._isIgnored(path, stat);\n }\n /**\n * Provides a set of common helpers and properties relating to symlink handling.\n * @param path file or directory pattern being watched\n */\n _getWatchHelpers(path) {\n return new WatchHelper(path, this.options.followSymlinks, this);\n }\n // Directory helpers\n // -----------------\n /**\n * Provides directory tracking objects\n * @param directory path of the directory\n */\n _getWatchedDir(directory) {\n const dir = sp.resolve(directory);\n if (!this._watched.has(dir))\n this._watched.set(dir, new DirEntry(dir, this._boundRemove));\n return this._watched.get(dir);\n }\n // File helpers\n // ------------\n /**\n * Check for read permissions: https://stackoverflow.com/a/11781404/1358405\n */\n _hasReadPermissions(stats) {\n if (this.options.ignorePermissionErrors)\n return true;\n return Boolean(Number(stats.mode) & 0o400);\n }\n /**\n * Handles emitting unlink events for\n * files and directories, and via recursion, for\n * files and directories within directories that are unlinked\n * @param directory within which the following item is located\n * @param item base path of item/directory\n */\n _remove(directory, item, isDirectory) {\n // if what is being deleted is a directory, get that directory's paths\n // for recursive deleting and cleaning of watched object\n // if it is not a directory, nestedDirectoryChildren will be empty array\n const path = sp.join(directory, item);\n const fullPath = sp.resolve(path);\n isDirectory =\n isDirectory != null ? isDirectory : this._watched.has(path) || this._watched.has(fullPath);\n // prevent duplicate handling in case of arriving here nearly simultaneously\n // via multiple paths (such as _handleFile and _handleDir)\n if (!this._throttle('remove', path, 100))\n return;\n // if the only watched file is removed, watch for its return\n if (!isDirectory && this._watched.size === 1) {\n this.add(directory, item, true);\n }\n // This will create a new entry in the watched object in either case\n // so we got to do the directory check beforehand\n const wp = this._getWatchedDir(path);\n const nestedDirectoryChildren = wp.getChildren();\n // Recursively remove children directories / files.\n nestedDirectoryChildren.forEach((nested) => this._remove(path, nested));\n // Check if item was on the watched list and remove it\n const parent = this._getWatchedDir(directory);\n const wasTracked = parent.has(item);\n parent.remove(item);\n // Fixes issue #1042 -> Relative paths were detected and added as symlinks\n // (https://github.com/paulmillr/chokidar/blob/e1753ddbc9571bdc33b4a4af172d52cb6e611c10/lib/nodefs-handler.js#L612),\n // but never removed from the map in case the path was deleted.\n // This leads to an incorrect state if the path was recreated:\n // https://github.com/paulmillr/chokidar/blob/e1753ddbc9571bdc33b4a4af172d52cb6e611c10/lib/nodefs-handler.js#L553\n if (this._symlinkPaths.has(fullPath)) {\n this._symlinkPaths.delete(fullPath);\n }\n // If we wait for this file to be fully written, cancel the wait.\n let relPath = path;\n if (this.options.cwd)\n relPath = sp.relative(this.options.cwd, path);\n if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {\n const event = this._pendingWrites.get(relPath).cancelWait();\n if (event === EV.ADD)\n return;\n }\n // The Entry will either be a directory that just got removed\n // or a bogus entry to a file, in either case we have to remove it\n this._watched.delete(path);\n this._watched.delete(fullPath);\n const eventName = isDirectory ? EV.UNLINK_DIR : EV.UNLINK;\n if (wasTracked && !this._isIgnored(path))\n this._emit(eventName, path);\n // Avoid conflicts if we later create another file with the same name\n this._closePath(path);\n }\n /**\n * Closes all watchers for a path\n */\n _closePath(path) {\n this._closeFile(path);\n const dir = sp.dirname(path);\n this._getWatchedDir(dir).remove(sp.basename(path));\n }\n /**\n * Closes only file-specific watchers\n */\n _closeFile(path) {\n const closers = this._closers.get(path);\n if (!closers)\n return;\n closers.forEach((closer) => closer());\n this._closers.delete(path);\n }\n _addPathCloser(path, closer) {\n if (!closer)\n return;\n let list = this._closers.get(path);\n if (!list) {\n list = [];\n this._closers.set(path, list);\n }\n list.push(closer);\n }\n _readdirp(root, opts) {\n if (this.closed)\n return;\n const options = { type: EV.ALL, alwaysStat: true, lstat: true, ...opts, depth: 0 };\n let stream = readdirp(root, options);\n this._streams.add(stream);\n stream.once(STR_CLOSE, () => {\n stream = undefined;\n });\n stream.once(STR_END, () => {\n if (stream) {\n this._streams.delete(stream);\n stream = undefined;\n }\n });\n return stream;\n }\n}\n/**\n * Instantiates watcher with paths to be tracked.\n * @param paths file / directory paths\n * @param options opts, such as `atomic`, `awaitWriteFinish`, `ignored`, and others\n * @returns an instance of FSWatcher for chaining.\n * @example\n * const watcher = watch('.').on('all', (event, path) => { console.log(event, path); });\n * watch('.', { atomic: true, awaitWriteFinish: true, ignored: (f, stats) => stats?.isFile() && !f.endsWith('.js') })\n */\nexport function watch(paths, options = {}) {\n const watcher = new FSWatcher(options);\n watcher.add(paths);\n return watcher;\n}\nexport default { watch: watch, FSWatcher: FSWatcher };\n","import { lstat, readdir, realpath, stat } from 'node:fs/promises';\nimport { join as pjoin, relative as prelative, resolve as presolve, sep as psep } from 'node:path';\nimport { Readable } from 'node:stream';\nexport const EntryTypes = {\n FILE_TYPE: 'files',\n DIR_TYPE: 'directories',\n FILE_DIR_TYPE: 'files_directories',\n EVERYTHING_TYPE: 'all',\n};\nconst defaultOptions = {\n root: '.',\n fileFilter: (_entryInfo) => true,\n directoryFilter: (_entryInfo) => true,\n type: EntryTypes.FILE_TYPE,\n lstat: false,\n depth: 2147483648,\n alwaysStat: false,\n highWaterMark: 4096,\n};\nObject.freeze(defaultOptions);\nconst RECURSIVE_ERROR_CODE = 'READDIRP_RECURSIVE_ERROR';\nconst NORMAL_FLOW_ERRORS = new Set(['ENOENT', 'EPERM', 'EACCES', 'ELOOP', RECURSIVE_ERROR_CODE]);\nconst ALL_TYPES = [\n EntryTypes.DIR_TYPE,\n EntryTypes.EVERYTHING_TYPE,\n EntryTypes.FILE_DIR_TYPE,\n EntryTypes.FILE_TYPE,\n];\nconst DIR_TYPES = new Set([\n EntryTypes.DIR_TYPE,\n EntryTypes.EVERYTHING_TYPE,\n EntryTypes.FILE_DIR_TYPE,\n]);\nconst FILE_TYPES = new Set([\n EntryTypes.EVERYTHING_TYPE,\n EntryTypes.FILE_DIR_TYPE,\n EntryTypes.FILE_TYPE,\n]);\nconst isNormalFlowError = (error) => NORMAL_FLOW_ERRORS.has(error.code);\nconst wantBigintFsStats = process.platform === 'win32';\nconst emptyFn = (_entryInfo) => true;\nconst normalizeFilter = (filter) => {\n if (filter === undefined)\n return emptyFn;\n if (typeof filter === 'function')\n return filter;\n if (typeof filter === 'string') {\n const fl = filter.trim();\n return (entry) => entry.basename === fl;\n }\n if (Array.isArray(filter)) {\n const trItems = filter.map((item) => item.trim());\n return (entry) => trItems.some((f) => entry.basename === f);\n }\n return emptyFn;\n};\n/** Readable readdir stream, emitting new files as they're being listed. */\nexport class ReaddirpStream extends Readable {\n parents;\n reading;\n parent;\n _stat;\n _maxDepth;\n _wantsDir;\n _wantsFile;\n _wantsEverything;\n _root;\n _isDirent;\n _statsProp;\n _rdOptions;\n _fileFilter;\n _directoryFilter;\n constructor(options = {}) {\n super({\n objectMode: true,\n autoDestroy: true,\n highWaterMark: options.highWaterMark,\n });\n const opts = { ...defaultOptions, ...options };\n const { root, type } = opts;\n this._fileFilter = normalizeFilter(opts.fileFilter);\n this._directoryFilter = normalizeFilter(opts.directoryFilter);\n const statMethod = opts.lstat ? lstat : stat;\n // Use bigint stats if it's windows and stat() supports options (node 10+).\n if (wantBigintFsStats) {\n this._stat = (path) => statMethod(path, { bigint: true });\n }\n else {\n this._stat = statMethod;\n }\n this._maxDepth =\n opts.depth != null && Number.isSafeInteger(opts.depth) ? opts.depth : defaultOptions.depth;\n this._wantsDir = type ? DIR_TYPES.has(type) : false;\n this._wantsFile = type ? FILE_TYPES.has(type) : false;\n this._wantsEverything = type === EntryTypes.EVERYTHING_TYPE;\n this._root = presolve(root);\n this._isDirent = !opts.alwaysStat;\n this._statsProp = this._isDirent ? 'dirent' : 'stats';\n this._rdOptions = { encoding: 'utf8', withFileTypes: this._isDirent };\n // Launch stream with one parent, the root dir.\n this.parents = [this._exploreDir(root, 1)];\n this.reading = false;\n this.parent = undefined;\n }\n async _read(batch) {\n if (this.reading)\n return;\n this.reading = true;\n try {\n while (!this.destroyed && batch > 0) {\n const par = this.parent;\n const fil = par && par.files;\n if (fil && fil.length > 0) {\n const { path, depth } = par;\n const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path));\n const awaited = await Promise.all(slice);\n for (const entry of awaited) {\n if (!entry)\n continue;\n if (this.destroyed)\n return;\n const entryType = await this._getEntryType(entry);\n if (entryType === 'directory' && this._directoryFilter(entry)) {\n if (depth <= this._maxDepth) {\n this.parents.push(this._exploreDir(entry.fullPath, depth + 1));\n }\n if (this._wantsDir) {\n this.push(entry);\n batch--;\n }\n }\n else if ((entryType === 'file' || this._includeAsFile(entry)) &&\n this._fileFilter(entry)) {\n if (this._wantsFile) {\n this.push(entry);\n batch--;\n }\n }\n }\n }\n else {\n const parent = this.parents.pop();\n if (!parent) {\n this.push(null);\n break;\n }\n this.parent = await parent;\n if (this.destroyed)\n return;\n }\n }\n }\n catch (error) {\n this.destroy(error);\n }\n finally {\n this.reading = false;\n }\n }\n async _exploreDir(path, depth) {\n let files;\n try {\n files = await readdir(path, this._rdOptions);\n }\n catch (error) {\n this._onError(error);\n }\n return { files, depth, path };\n }\n async _formatEntry(dirent, path) {\n let entry;\n const basename = this._isDirent ? dirent.name : dirent;\n try {\n const fullPath = presolve(pjoin(path, basename));\n entry = { path: prelative(this._root, fullPath), fullPath, basename };\n entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);\n }\n catch (err) {\n this._onError(err);\n return;\n }\n return entry;\n }\n _onError(err) {\n if (isNormalFlowError(err) && !this.destroyed) {\n this.emit('warn', err);\n }\n else {\n this.destroy(err);\n }\n }\n async _getEntryType(entry) {\n // entry may be undefined, because a warning or an error were emitted\n // and the statsProp is undefined\n if (!entry && this._statsProp in entry) {\n return '';\n }\n const stats = entry[this._statsProp];\n if (stats.isFile())\n return 'file';\n if (stats.isDirectory())\n return 'directory';\n if (stats && stats.isSymbolicLink()) {\n const full = entry.fullPath;\n try {\n const entryRealPath = await realpath(full);\n const entryRealPathStats = await lstat(entryRealPath);\n if (entryRealPathStats.isFile()) {\n return 'file';\n }\n if (entryRealPathStats.isDirectory()) {\n const len = entryRealPath.length;\n if (full.startsWith(entryRealPath) && full.substr(len, 1) === psep) {\n const recursiveError = new Error(`Circular symlink detected: \"${full}\" points to \"${entryRealPath}\"`);\n // @ts-ignore\n recursiveError.code = RECURSIVE_ERROR_CODE;\n return this._onError(recursiveError);\n }\n return 'directory';\n }\n }\n catch (error) {\n this._onError(error);\n return '';\n }\n }\n }\n _includeAsFile(entry) {\n const stats = entry && entry[this._statsProp];\n return stats && this._wantsEverything && !stats.isDirectory();\n }\n}\n/**\n * Streaming version: Reads all files and directories in given root recursively.\n * Consumes ~constant small amount of RAM.\n * @param root Root directory\n * @param options Options to specify root (start directory), filters and recursion depth\n */\nexport function readdirp(root, options = {}) {\n // @ts-ignore\n let type = options.entryType || options.type;\n if (type === 'both')\n type = EntryTypes.FILE_DIR_TYPE; // backwards-compatibility\n if (type)\n options.type = type;\n if (!root) {\n throw new Error('readdirp: root argument is required. Usage: readdirp(root, options)');\n }\n else if (typeof root !== 'string') {\n throw new TypeError('readdirp: root argument must be a string. Usage: readdirp(root, options)');\n }\n else if (type && !ALL_TYPES.includes(type)) {\n throw new Error(`readdirp: Invalid type passed. Use one of ${ALL_TYPES.join(', ')}`);\n }\n options.root = root;\n return new ReaddirpStream(options);\n}\n/**\n * Promise version: Reads all files and directories in given root recursively.\n * Compared to streaming version, will consume a lot of RAM e.g. when 1 million files are listed.\n * @returns array of paths and their entry infos\n */\nexport function readdirpPromise(root, options = {}) {\n return new Promise((resolve, reject) => {\n const files = [];\n readdirp(root, options)\n .on('data', (entry) => files.push(entry))\n .on('end', () => resolve(files))\n .on('error', (error) => reject(error));\n });\n}\nexport default readdirp;\n","import { watch as fs_watch, unwatchFile, watchFile } from 'node:fs';\nimport { realpath as fsrealpath, lstat, open, stat } from 'node:fs/promises';\nimport { type as osType } from 'node:os';\nimport * as sp from 'node:path';\nexport const STR_DATA = 'data';\nexport const STR_END = 'end';\nexport const STR_CLOSE = 'close';\nexport const EMPTY_FN = () => { };\nexport const IDENTITY_FN = (val) => val;\nconst pl = process.platform;\nexport const isWindows = pl === 'win32';\nexport const isMacos = pl === 'darwin';\nexport const isLinux = pl === 'linux';\nexport const isFreeBSD = pl === 'freebsd';\nexport const isIBMi = osType() === 'OS400';\nexport const EVENTS = {\n ALL: 'all',\n READY: 'ready',\n ADD: 'add',\n CHANGE: 'change',\n ADD_DIR: 'addDir',\n UNLINK: 'unlink',\n UNLINK_DIR: 'unlinkDir',\n RAW: 'raw',\n ERROR: 'error',\n};\nconst EV = EVENTS;\nconst THROTTLE_MODE_WATCH = 'watch';\nconst statMethods = { lstat, stat };\nconst KEY_LISTENERS = 'listeners';\nconst KEY_ERR = 'errHandlers';\nconst KEY_RAW = 'rawEmitters';\nconst HANDLER_KEYS = [KEY_LISTENERS, KEY_ERR, KEY_RAW];\n// prettier-ignore\nconst binaryExtensions = new Set([\n '3dm', '3ds', '3g2', '3gp', '7z', 'a', 'aac', 'adp', 'afdesign', 'afphoto', 'afpub', 'ai',\n 'aif', 'aiff', 'alz', 'ape', 'apk', 'appimage', 'ar', 'arj', 'asf', 'au', 'avi',\n 'bak', 'baml', 'bh', 'bin', 'bk', 'bmp', 'btif', 'bz2', 'bzip2',\n 'cab', 'caf', 'cgm', 'class', 'cmx', 'cpio', 'cr2', 'cur', 'dat', 'dcm', 'deb', 'dex', 'djvu',\n 'dll', 'dmg', 'dng', 'doc', 'docm', 'docx', 'dot', 'dotm', 'dra', 'DS_Store', 'dsk', 'dts',\n 'dtshd', 'dvb', 'dwg', 'dxf',\n 'ecelp4800', 'ecelp7470', 'ecelp9600', 'egg', 'eol', 'eot', 'epub', 'exe',\n 'f4v', 'fbs', 'fh', 'fla', 'flac', 'flatpak', 'fli', 'flv', 'fpx', 'fst', 'fvt',\n 'g3', 'gh', 'gif', 'graffle', 'gz', 'gzip',\n 'h261', 'h263', 'h264', 'icns', 'ico', 'ief', 'img', 'ipa', 'iso',\n 'jar', 'jpeg', 'jpg', 'jpgv', 'jpm', 'jxr', 'key', 'ktx',\n 'lha', 'lib', 'lvp', 'lz', 'lzh', 'lzma', 'lzo',\n 'm3u', 'm4a', 'm4v', 'mar', 'mdi', 'mht', 'mid', 'midi', 'mj2', 'mka', 'mkv', 'mmr', 'mng',\n 'mobi', 'mov', 'movie', 'mp3',\n 'mp4', 'mp4a', 'mpeg', 'mpg', 'mpga', 'mxu',\n 'nef', 'npx', 'numbers', 'nupkg',\n 'o', 'odp', 'ods', 'odt', 'oga', 'ogg', 'ogv', 'otf', 'ott',\n 'pages', 'pbm', 'pcx', 'pdb', 'pdf', 'pea', 'pgm', 'pic', 'png', 'pnm', 'pot', 'potm',\n 'potx', 'ppa', 'ppam',\n 'ppm', 'pps', 'ppsm', 'ppsx', 'ppt', 'pptm', 'pptx', 'psd', 'pya', 'pyc', 'pyo', 'pyv',\n 'qt',\n 'rar', 'ras', 'raw', 'resources', 'rgb', 'rip', 'rlc', 'rmf', 'rmvb', 'rpm', 'rtf', 'rz',\n 's3m', 's7z', 'scpt', 'sgi', 'shar', 'snap', 'sil', 'sketch', 'slk', 'smv', 'snk', 'so',\n 'stl', 'suo', 'sub', 'swf',\n 'tar', 'tbz', 'tbz2', 'tga', 'tgz', 'thmx', 'tif', 'tiff', 'tlz', 'ttc', 'ttf', 'txz',\n 'udf', 'uvh', 'uvi', 'uvm', 'uvp', 'uvs', 'uvu',\n 'viv', 'vob',\n 'war', 'wav', 'wax', 'wbmp', 'wdp', 'weba', 'webm', 'webp', 'whl', 'wim', 'wm', 'wma',\n 'wmv', 'wmx', 'woff', 'woff2', 'wrm', 'wvx',\n 'xbm', 'xif', 'xla', 'xlam', 'xls', 'xlsb', 'xlsm', 'xlsx', 'xlt', 'xltm', 'xltx', 'xm',\n 'xmind', 'xpi', 'xpm', 'xwd', 'xz',\n 'z', 'zip', 'zipx',\n]);\nconst isBinaryPath = (filePath) => binaryExtensions.has(sp.extname(filePath).slice(1).toLowerCase());\n// TODO: emit errors properly. Example: EMFILE on Macos.\nconst foreach = (val, fn) => {\n if (val instanceof Set) {\n val.forEach(fn);\n }\n else {\n fn(val);\n }\n};\nconst addAndConvert = (main, prop, item) => {\n let container = main[prop];\n if (!(container instanceof Set)) {\n main[prop] = container = new Set([container]);\n }\n container.add(item);\n};\nconst clearItem = (cont) => (key) => {\n const set = cont[key];\n if (set instanceof Set) {\n set.clear();\n }\n else {\n delete cont[key];\n }\n};\nconst delFromSet = (main, prop, item) => {\n const container = main[prop];\n if (container instanceof Set) {\n container.delete(item);\n }\n else if (container === item) {\n delete main[prop];\n }\n};\nconst isEmptySet = (val) => (val instanceof Set ? val.size === 0 : !val);\nconst FsWatchInstances = new Map();\n/**\n * Instantiates the fs_watch interface\n * @param path to be watched\n * @param options to be passed to fs_watch\n * @param listener main event handler\n * @param errHandler emits info about errors\n * @param emitRaw emits raw event data\n * @returns {NativeFsWatcher}\n */\nfunction createFsWatchInstance(path, options, listener, errHandler, emitRaw) {\n const handleEvent = (rawEvent, evPath) => {\n listener(path);\n emitRaw(rawEvent, evPath, { watchedPath: path });\n // emit based on events occurring for files from a directory's watcher in\n // case the file's watcher misses it (and rely on throttling to de-dupe)\n if (evPath && path !== evPath) {\n fsWatchBroadcast(sp.resolve(path, evPath), KEY_LISTENERS, sp.join(path, evPath));\n }\n };\n try {\n return fs_watch(path, {\n persistent: options.persistent,\n }, handleEvent);\n }\n catch (error) {\n errHandler(error);\n return undefined;\n }\n}\n/**\n * Helper for passing fs_watch event data to a collection of listeners\n * @param fullPath absolute path bound to fs_watch instance\n */\nconst fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {\n const cont = FsWatchInstances.get(fullPath);\n if (!cont)\n return;\n foreach(cont[listenerType], (listener) => {\n listener(val1, val2, val3);\n });\n};\n/**\n * Instantiates the fs_watch interface or binds listeners\n * to an existing one covering the same file system entry\n * @param path\n * @param fullPath absolute path\n * @param options to be passed to fs_watch\n * @param handlers container for event listener functions\n */\nconst setFsWatchListener = (path, fullPath, options, handlers) => {\n const { listener, errHandler, rawEmitter } = handlers;\n let cont = FsWatchInstances.get(fullPath);\n let watcher;\n if (!options.persistent) {\n watcher = createFsWatchInstance(path, options, listener, errHandler, rawEmitter);\n if (!watcher)\n return;\n return watcher.close.bind(watcher);\n }\n if (cont) {\n addAndConvert(cont, KEY_LISTENERS, listener);\n addAndConvert(cont, KEY_ERR, errHandler);\n addAndConvert(cont, KEY_RAW, rawEmitter);\n }\n else {\n watcher = createFsWatchInstance(path, options, fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS), errHandler, // no need to use broadcast here\n fsWatchBroadcast.bind(null, fullPath, KEY_RAW));\n if (!watcher)\n return;\n watcher.on(EV.ERROR, async (error) => {\n const broadcastErr = fsWatchBroadcast.bind(null, fullPath, KEY_ERR);\n if (cont)\n cont.watcherUnusable = true; // documented since Node 10.4.1\n // Workaround for https://github.com/joyent/node/issues/4337\n if (isWindows && error.code === 'EPERM') {\n try {\n const fd = await open(path, 'r');\n await fd.close();\n broadcastErr(error);\n }\n catch (err) {\n // do nothing\n }\n }\n else {\n broadcastErr(error);\n }\n });\n cont = {\n listeners: listener,\n errHandlers: errHandler,\n rawEmitters: rawEmitter,\n watcher,\n };\n FsWatchInstances.set(fullPath, cont);\n }\n // const index = cont.listeners.indexOf(listener);\n // removes this instance's listeners and closes the underlying fs_watch\n // instance if there are no more listeners left\n return () => {\n delFromSet(cont, KEY_LISTENERS, listener);\n delFromSet(cont, KEY_ERR, errHandler);\n delFromSet(cont, KEY_RAW, rawEmitter);\n if (isEmptySet(cont.listeners)) {\n // Check to protect against issue gh-730.\n // if (cont.watcherUnusable) {\n cont.watcher.close();\n // }\n FsWatchInstances.delete(fullPath);\n HANDLER_KEYS.forEach(clearItem(cont));\n // @ts-ignore\n cont.watcher = undefined;\n Object.freeze(cont);\n }\n };\n};\n// fs_watchFile helpers\n// object to hold per-process fs_watchFile instances\n// (may be shared across chokidar FSWatcher instances)\nconst FsWatchFileInstances = new Map();\n/**\n * Instantiates the fs_watchFile interface or binds listeners\n * to an existing one covering the same file system entry\n * @param path to be watched\n * @param fullPath absolute path\n * @param options options to be passed to fs_watchFile\n * @param handlers container for event listener functions\n * @returns closer\n */\nconst setFsWatchFileListener = (path, fullPath, options, handlers) => {\n const { listener, rawEmitter } = handlers;\n let cont = FsWatchFileInstances.get(fullPath);\n // let listeners = new Set();\n // let rawEmitters = new Set();\n const copts = cont && cont.options;\n if (copts && (copts.persistent < options.persistent || copts.interval > options.interval)) {\n // \"Upgrade\" the watcher to persistence or a quicker interval.\n // This creates some unlikely edge case issues if the user mixes\n // settings in a very weird way, but solving for those cases\n // doesn't seem worthwhile for the added complexity.\n // listeners = cont.listeners;\n // rawEmitters = cont.rawEmitters;\n unwatchFile(fullPath);\n cont = undefined;\n }\n if (cont) {\n addAndConvert(cont, KEY_LISTENERS, listener);\n addAndConvert(cont, KEY_RAW, rawEmitter);\n }\n else {\n // TODO\n // listeners.add(listener);\n // rawEmitters.add(rawEmitter);\n cont = {\n listeners: listener,\n rawEmitters: rawEmitter,\n options,\n watcher: watchFile(fullPath, options, (curr, prev) => {\n foreach(cont.rawEmitters, (rawEmitter) => {\n rawEmitter(EV.CHANGE, fullPath, { curr, prev });\n });\n const currmtime = curr.mtimeMs;\n if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {\n foreach(cont.listeners, (listener) => listener(path, curr));\n }\n }),\n };\n FsWatchFileInstances.set(fullPath, cont);\n }\n // const index = cont.listeners.indexOf(listener);\n // Removes this instance's listeners and closes the underlying fs_watchFile\n // instance if there are no more listeners left.\n return () => {\n delFromSet(cont, KEY_LISTENERS, listener);\n delFromSet(cont, KEY_RAW, rawEmitter);\n if (isEmptySet(cont.listeners)) {\n FsWatchFileInstances.delete(fullPath);\n unwatchFile(fullPath);\n cont.options = cont.watcher = undefined;\n Object.freeze(cont);\n }\n };\n};\n/**\n * @mixin\n */\nexport class NodeFsHandler {\n fsw;\n _boundHandleError;\n constructor(fsW) {\n this.fsw = fsW;\n this._boundHandleError = (error) => fsW._handleError(error);\n }\n /**\n * Watch file for changes with fs_watchFile or fs_watch.\n * @param path to file or dir\n * @param listener on fs change\n * @returns closer for the watcher instance\n */\n _watchWithNodeFs(path, listener) {\n const opts = this.fsw.options;\n const directory = sp.dirname(path);\n const basename = sp.basename(path);\n const parent = this.fsw._getWatchedDir(directory);\n parent.add(basename);\n const absolutePath = sp.resolve(path);\n const options = {\n persistent: opts.persistent,\n };\n if (!listener)\n listener = EMPTY_FN;\n let closer;\n if (opts.usePolling) {\n const enableBin = opts.interval !== opts.binaryInterval;\n options.interval = enableBin && isBinaryPath(basename) ? opts.binaryInterval : opts.interval;\n closer = setFsWatchFileListener(path, absolutePath, options, {\n listener,\n rawEmitter: this.fsw._emitRaw,\n });\n }\n else {\n closer = setFsWatchListener(path, absolutePath, options, {\n listener,\n errHandler: this._boundHandleError,\n rawEmitter: this.fsw._emitRaw,\n });\n }\n return closer;\n }\n /**\n * Watch a file and emit add event if warranted.\n * @returns closer for the watcher instance\n */\n _handleFile(file, stats, initialAdd) {\n if (this.fsw.closed) {\n return;\n }\n const dirname = sp.dirname(file);\n const basename = sp.basename(file);\n const parent = this.fsw._getWatchedDir(dirname);\n // stats is always present\n let prevStats = stats;\n // if the file is already being watched, do nothing\n if (parent.has(basename))\n return;\n const listener = async (path, newStats) => {\n if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))\n return;\n if (!newStats || newStats.mtimeMs === 0) {\n try {\n const newStats = await stat(file);\n if (this.fsw.closed)\n return;\n // Check that change event was not fired because of changed only accessTime.\n const at = newStats.atimeMs;\n const mt = newStats.mtimeMs;\n if (!at || at <= mt || mt !== prevStats.mtimeMs) {\n this.fsw._emit(EV.CHANGE, file, newStats);\n }\n if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats.ino) {\n this.fsw._closeFile(path);\n prevStats = newStats;\n const closer = this._watchWithNodeFs(file, listener);\n if (closer)\n this.fsw._addPathCloser(path, closer);\n }\n else {\n prevStats = newStats;\n }\n }\n catch (error) {\n // Fix issues where mtime is null but file is still present\n this.fsw._remove(dirname, basename);\n }\n // add is about to be emitted if file not already tracked in parent\n }\n else if (parent.has(basename)) {\n // Check that change event was not fired because of changed only accessTime.\n const at = newStats.atimeMs;\n const mt = newStats.mtimeMs;\n if (!at || at <= mt || mt !== prevStats.mtimeMs) {\n this.fsw._emit(EV.CHANGE, file, newStats);\n }\n prevStats = newStats;\n }\n };\n // kick off the watcher\n const closer = this._watchWithNodeFs(file, listener);\n // emit an add event if we're supposed to\n if (!(initialAdd && this.fsw.options.ignoreInitial) && this.fsw._isntIgnored(file)) {\n if (!this.fsw._throttle(EV.ADD, file, 0))\n return;\n this.fsw._emit(EV.ADD, file, stats);\n }\n return closer;\n }\n /**\n * Handle symlinks encountered while reading a dir.\n * @param entry returned by readdirp\n * @param directory path of dir being read\n * @param path of this item\n * @param item basename of this item\n * @returns true if no more processing is needed for this entry.\n */\n async _handleSymlink(entry, directory, path, item) {\n if (this.fsw.closed) {\n return;\n }\n const full = entry.fullPath;\n const dir = this.fsw._getWatchedDir(directory);\n if (!this.fsw.options.followSymlinks) {\n // watch symlink directly (don't follow) and detect changes\n this.fsw._incrReadyCount();\n let linkPath;\n try {\n linkPath = await fsrealpath(path);\n }\n catch (e) {\n this.fsw._emitReady();\n return true;\n }\n if (this.fsw.closed)\n return;\n if (dir.has(item)) {\n if (this.fsw._symlinkPaths.get(full) !== linkPath) {\n this.fsw._symlinkPaths.set(full, linkPath);\n this.fsw._emit(EV.CHANGE, path, entry.stats);\n }\n }\n else {\n dir.add(item);\n this.fsw._symlinkPaths.set(full, linkPath);\n this.fsw._emit(EV.ADD, path, entry.stats);\n }\n this.fsw._emitReady();\n return true;\n }\n // don't follow the same symlink more than once\n if (this.fsw._symlinkPaths.has(full)) {\n return true;\n }\n this.fsw._symlinkPaths.set(full, true);\n }\n _handleRead(directory, initialAdd, wh, target, dir, depth, throttler) {\n // Normalize the directory name on Windows\n directory = sp.join(directory, '');\n const throttleKey = target ? `${directory}:${target}` : directory;\n throttler = this.fsw._throttle('readdir', throttleKey, 1000);\n if (!throttler)\n return;\n const previous = this.fsw._getWatchedDir(wh.path);\n const current = new Set();\n let stream = this.fsw._readdirp(directory, {\n fileFilter: (entry) => wh.filterPath(entry),\n directoryFilter: (entry) => wh.filterDir(entry),\n });\n if (!stream)\n return;\n stream\n .on(STR_DATA, async (entry) => {\n if (this.fsw.closed) {\n stream = undefined;\n return;\n }\n const item = entry.path;\n let path = sp.join(directory, item);\n current.add(item);\n if (entry.stats.isSymbolicLink() &&\n (await this._handleSymlink(entry, directory, path, item))) {\n return;\n }\n if (this.fsw.closed) {\n stream = undefined;\n return;\n }\n // Files that present in current directory snapshot\n // but absent in previous are added to watch list and\n // emit `add` event.\n if (item === target || (!target && !previous.has(item))) {\n this.fsw._incrReadyCount();\n // ensure relativeness of path is preserved in case of watcher reuse\n path = sp.join(dir, sp.relative(dir, path));\n this._addToNodeFs(path, initialAdd, wh, depth + 1);\n }\n })\n .on(EV.ERROR, this._boundHandleError);\n return new Promise((resolve, reject) => {\n if (!stream)\n return reject();\n stream.once(STR_END, () => {\n if (this.fsw.closed) {\n stream = undefined;\n return;\n }\n const wasThrottled = throttler ? throttler.clear() : false;\n resolve(undefined);\n // Files that absent in current directory snapshot\n // but present in previous emit `remove` event\n // and are removed from @watched[directory].\n previous\n .getChildren()\n .filter((item) => {\n return item !== directory && !current.has(item);\n })\n .forEach((item) => {\n this.fsw._remove(directory, item);\n });\n stream = undefined;\n // one more time for any missed in case changes came in extremely quickly\n if (wasThrottled)\n this._handleRead(directory, false, wh, target, dir, depth, throttler);\n });\n });\n }\n /**\n * Read directory to add / remove files from `@watched` list and re-read it on change.\n * @param dir fs path\n * @param stats\n * @param initialAdd\n * @param depth relative to user-supplied path\n * @param target child path targeted for watch\n * @param wh Common watch helpers for this path\n * @param realpath\n * @returns closer for the watcher instance.\n */\n async _handleDir(dir, stats, initialAdd, depth, target, wh, realpath) {\n const parentDir = this.fsw._getWatchedDir(sp.dirname(dir));\n const tracked = parentDir.has(sp.basename(dir));\n if (!(initialAdd && this.fsw.options.ignoreInitial) && !target && !tracked) {\n this.fsw._emit(EV.ADD_DIR, dir, stats);\n }\n // ensure dir is tracked (harmless if redundant)\n parentDir.add(sp.basename(dir));\n this.fsw._getWatchedDir(dir);\n let throttler;\n let closer;\n const oDepth = this.fsw.options.depth;\n if ((oDepth == null || depth <= oDepth) && !this.fsw._symlinkPaths.has(realpath)) {\n if (!target) {\n await this._handleRead(dir, initialAdd, wh, target, dir, depth, throttler);\n if (this.fsw.closed)\n return;\n }\n closer = this._watchWithNodeFs(dir, (dirPath, stats) => {\n // if current directory is removed, do nothing\n if (stats && stats.mtimeMs === 0)\n return;\n this._handleRead(dirPath, false, wh, target, dir, depth, throttler);\n });\n }\n return closer;\n }\n /**\n * Handle added file, directory, or glob pattern.\n * Delegates call to _handleFile / _handleDir after checks.\n * @param path to file or ir\n * @param initialAdd was the file added at watch instantiation?\n * @param priorWh depth relative to user-supplied path\n * @param depth Child path actually targeted for watch\n * @param target Child path actually targeted for watch\n */\n async _addToNodeFs(path, initialAdd, priorWh, depth, target) {\n const ready = this.fsw._emitReady;\n if (this.fsw._isIgnored(path) || this.fsw.closed) {\n ready();\n return false;\n }\n const wh = this.fsw._getWatchHelpers(path);\n if (priorWh) {\n wh.filterPath = (entry) => priorWh.filterPath(entry);\n wh.filterDir = (entry) => priorWh.filterDir(entry);\n }\n // evaluate what is at the path we're being asked to watch\n try {\n const stats = await statMethods[wh.statMethod](wh.watchPath);\n if (this.fsw.closed)\n return;\n if (this.fsw._isIgnored(wh.watchPath, stats)) {\n ready();\n return false;\n }\n const follow = this.fsw.options.followSymlinks;\n let closer;\n if (stats.isDirectory()) {\n const absPath = sp.resolve(path);\n const targetPath = follow ? await fsrealpath(path) : path;\n if (this.fsw.closed)\n return;\n closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);\n if (this.fsw.closed)\n return;\n // preserve this symlink's target path\n if (absPath !== targetPath && targetPath !== undefined) {\n this.fsw._symlinkPaths.set(absPath, targetPath);\n }\n }\n else if (stats.isSymbolicLink()) {\n const targetPath = follow ? await fsrealpath(path) : path;\n if (this.fsw.closed)\n return;\n const parent = sp.dirname(wh.watchPath);\n this.fsw._getWatchedDir(parent).add(wh.watchPath);\n this.fsw._emit(EV.ADD, wh.watchPath, stats);\n closer = await this._handleDir(parent, stats, initialAdd, depth, path, wh, targetPath);\n if (this.fsw.closed)\n return;\n // preserve this symlink's target path\n if (targetPath !== undefined) {\n this.fsw._symlinkPaths.set(sp.resolve(path), targetPath);\n }\n }\n else {\n closer = this._handleFile(wh.watchPath, stats, initialAdd);\n }\n ready();\n if (closer)\n this.fsw._addPathCloser(path, closer);\n return false;\n }\n catch (error) {\n if (this.fsw._handleError(error)) {\n ready();\n return path;\n }\n }\n }\n}\n","import { watch } from 'chokidar';\nimport type { FSWatcher } from 'chokidar';\nimport path from 'node:path';\nimport { FILE_WATCH_STABILITY_MS } from '../constants.js';\n\nexport interface PlanEvent {\n source: 'tool' | 'hook' | 'filesystem' | 'transcript';\n filePath?: string;\n sessionId?: string;\n detail: string;\n timestamp: string;\n}\n\ninterface WatcherConfig {\n projectRoot: string;\n watchPaths: string[];\n onPlan: (event: PlanEvent) => void;\n}\n\nexport class PlanWatcher {\n private config: WatcherConfig;\n private fsWatcher: FSWatcher | null = null;\n private knownPlans: Set<string> = new Set();\n\n constructor(config: WatcherConfig) {\n this.config = config;\n }\n\n checkToolEvent(event: { tool_name: string; tool_input?: any; session_id?: string }): void {\n if (event.tool_name === 'EnterPlanMode' || event.tool_name === 'ExitPlanMode') {\n this.config.onPlan({\n source: 'hook',\n sessionId: event.session_id,\n detail: `Plan mode ${event.tool_name === 'EnterPlanMode' ? 'entered' : 'exited'}`,\n timestamp: new Date().toISOString(),\n });\n return;\n }\n\n if (['Write', 'Edit', 'Read'].includes(event.tool_name) && event.tool_input) {\n const filePath = event.tool_input.file_path ?? event.tool_input.path;\n if (filePath && this.isInPlanDirectory(filePath)) {\n this.knownPlans.add(filePath);\n this.config.onPlan({\n source: 'tool',\n filePath,\n sessionId: event.session_id,\n detail: `${event.tool_name} on plan file: ${path.basename(filePath)}`,\n timestamp: new Date().toISOString(),\n });\n }\n }\n }\n\n startFileWatcher(): void {\n const absPaths = this.config.watchPaths.map((p) =>\n path.resolve(this.config.projectRoot, p),\n );\n this.fsWatcher = watch(absPaths, {\n ignoreInitial: true,\n persistent: true,\n depth: 3,\n awaitWriteFinish: { stabilityThreshold: FILE_WATCH_STABILITY_MS },\n });\n this.fsWatcher.on('add', (fp) => this.onFileChange(fp, 'created'));\n this.fsWatcher.on('change', (fp) => this.onFileChange(fp, 'modified'));\n }\n\n stopFileWatcher(): void {\n this.fsWatcher?.close();\n this.fsWatcher = null;\n }\n\n private onFileChange(absolutePath: string, action: string): void {\n const rel = path.relative(this.config.projectRoot, absolutePath);\n this.knownPlans.add(absolutePath);\n this.config.onPlan({\n source: 'filesystem',\n filePath: absolutePath,\n detail: `Plan file ${action}: ${rel}`,\n timestamp: new Date().toISOString(),\n });\n }\n\n private isInPlanDirectory(filePath: string): boolean {\n const abs = path.isAbsolute(filePath)\n ? filePath\n : path.resolve(this.config.projectRoot, filePath);\n return this.config.watchPaths.some((wp) =>\n abs.startsWith(path.resolve(this.config.projectRoot, wp)),\n );\n }\n}\n","/**\n * ConsolidationEngine — daemon pre-pass that finds clusters of related spores\n * and consolidates them into wisdom notes via LLM.\n *\n * Runs before each digest cycle (or on its own timer) to reduce spore noise\n * by merging semantically similar observations of the same type.\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { z } from 'zod';\n\nimport type { MycoIndex } from '@myco/index/sqlite.js';\nimport type { VectorIndex } from '@myco/index/vectors.js';\nimport type { LlmProvider, EmbeddingProvider } from '@myco/intelligence/llm.js';\nimport { generateEmbedding } from '@myco/intelligence/embeddings.js';\nimport { stripReasoningTokens, extractJson } from '@myco/intelligence/response.js';\nimport { isActiveSpore } from '@myco/vault/curation.js';\nimport { consolidateSpores } from '@myco/vault/consolidation.js';\nimport { loadPrompt, formatNotesForPrompt } from '@myco/prompts/index.js';\nimport { readLastTimestamp, appendTraceRecord } from './trace.js';\nimport {\n CONSOLIDATION_MIN_CLUSTER_SIZE,\n CONSOLIDATION_VECTOR_FETCH_LIMIT,\n CONSOLIDATION_MAX_TOKENS,\n EMBEDDING_INPUT_LIMIT,\n LLM_REASONING_MODE,\n} from '@myco/constants.js';\n\n// --- Types ---\n\nexport interface ConsolidationPassResult {\n timestamp: string;\n sporesChecked: number;\n clustersFound: number;\n consolidated: number;\n sporesSuperseded: number;\n durationMs: number;\n}\n\nexport interface ConsolidationEngineConfig {\n vaultDir: string;\n index: MycoIndex;\n vectorIndex: VectorIndex | null;\n llmProvider: LlmProvider | null;\n embeddingProvider: EmbeddingProvider | null;\n maxTokens?: number;\n log?: (level: 'debug' | 'info' | 'warn', message: string, data?: Record<string, unknown>) => void;\n}\n\n// --- Zod schema for LLM response ---\n\nconst consolidationResponseSchema = z.discriminatedUnion('consolidate', [\n z.object({ consolidate: z.literal(false), reason: z.string().optional() }),\n z.object({\n consolidate: z.literal(true),\n title: z.string(),\n content: z.string(),\n source_ids: z.array(z.string()),\n tags: z.array(z.string()).optional(),\n }),\n]);\n\n/** Path within digest/ to store the consolidation trace. */\nconst CONSOLIDATION_TRACE_FILENAME = 'consolidation-trace.jsonl';\n\n// --- ConsolidationEngine ---\n\nexport class ConsolidationEngine {\n private readonly deps: {\n vaultDir: string;\n index: MycoIndex;\n vectorIndex: VectorIndex | null;\n llmProvider: LlmProvider | null;\n embeddingProvider: EmbeddingProvider | null;\n };\n\n private readonly maxTokens: number;\n private log: NonNullable<ConsolidationEngineConfig['log']>;\n private lastTimestampCache: string | null | undefined = undefined;\n\n constructor(config: ConsolidationEngineConfig) {\n this.deps = {\n vaultDir: config.vaultDir,\n index: config.index,\n vectorIndex: config.vectorIndex,\n llmProvider: config.llmProvider,\n embeddingProvider: config.embeddingProvider,\n };\n this.maxTokens = config.maxTokens ?? CONSOLIDATION_MAX_TOKENS;\n this.log = config.log ?? (() => {});\n }\n\n /**\n * Read the timestamp of the last consolidation pass from the trace file.\n * Cached in memory after first read — subsequent calls are O(1).\n */\n getLastTimestamp(): string | null {\n if (this.lastTimestampCache !== undefined) return this.lastTimestampCache;\n\n const tracePath = path.join(this.deps.vaultDir, 'digest', CONSOLIDATION_TRACE_FILENAME);\n this.lastTimestampCache = readLastTimestamp(tracePath);\n return this.lastTimestampCache;\n }\n\n /**\n * Append a consolidation pass result as a JSON line to the trace file.\n * Updates the in-memory timestamp cache.\n */\n appendTrace(record: ConsolidationPassResult): void {\n const tracePath = path.join(this.deps.vaultDir, 'digest', CONSOLIDATION_TRACE_FILENAME);\n appendTraceRecord(tracePath, record as unknown as Record<string, unknown>);\n this.lastTimestampCache = record.timestamp;\n }\n\n /**\n * Run one consolidation pass.\n *\n * Algorithm:\n * 1. Early-exit if vectorIndex or llmProvider is absent.\n * 2. Query index for spores created since lastTimestamp.\n * 3. Filter for active spores.\n * 4. For each new spore (skip if already processed):\n * a. Embed it.\n * b. Vector-search for similar spores.\n * c. Fetch candidate notes; filter same-type + active + not-processed.\n * d. Include trigger spore in cluster if not already present.\n * e. Skip if cluster < CONSOLIDATION_MIN_CLUSTER_SIZE.\n * f. Ask LLM whether to consolidate.\n * g. If approved, call consolidateSpores(); track counts.\n * h. Mark cluster members as processed regardless of outcome.\n * 5. Append trace record, return result.\n *\n * Returns null if no new spores were found or dependencies are absent.\n */\n async runPass(): Promise<ConsolidationPassResult | null> {\n const { vaultDir, index, vectorIndex, llmProvider, embeddingProvider } = this.deps;\n\n if (!vectorIndex || !llmProvider || !embeddingProvider) {\n this.log('debug', 'ConsolidationEngine: skipped — vectorIndex, llmProvider, or embeddingProvider unavailable');\n return null;\n }\n\n const startTime = Date.now();\n const lastTimestamp = this.getLastTimestamp();\n\n // Query for spores created since last pass\n const allSpores = index.query({ type: 'spore', since: lastTimestamp ?? undefined });\n const newSpores = allSpores.filter((n) => isActiveSpore(n.frontmatter));\n\n this.log('debug', 'ConsolidationEngine: spores to check', {\n count: newSpores.length,\n lastTimestamp: lastTimestamp ?? 'never',\n });\n\n if (newSpores.length === 0) {\n return null;\n }\n\n const processedIds = new Set<string>();\n let clustersFound = 0;\n let consolidated = 0;\n let sporesSuperseded = 0;\n const template = loadPrompt('consolidation');\n\n for (const triggerSpore of newSpores) {\n if (processedIds.has(triggerSpore.id)) continue;\n\n const observationType = triggerSpore.frontmatter['observation_type'] as string | undefined;\n\n // Get embedding for similarity search — reuse stored vector if available\n let embedding: number[];\n const storedEmbedding = vectorIndex.getEmbedding(triggerSpore.id);\n if (storedEmbedding) {\n embedding = storedEmbedding;\n } else {\n try {\n const embeddingText = triggerSpore.content.slice(0, EMBEDDING_INPUT_LIMIT);\n const result = await generateEmbedding(embeddingProvider, embeddingText);\n embedding = result.embedding;\n } catch (err) {\n this.log('warn', 'ConsolidationEngine: embedding failed', { id: triggerSpore.id, error: String(err) });\n processedIds.add(triggerSpore.id);\n continue;\n }\n }\n\n // Vector search for similar spores\n const vectorResults = vectorIndex.search(embedding, {\n type: 'spore',\n limit: CONSOLIDATION_VECTOR_FETCH_LIMIT,\n });\n\n if (vectorResults.length === 0) {\n processedIds.add(triggerSpore.id);\n continue;\n }\n\n // Fetch candidates from index\n const candidateIds = vectorResults.map((r) => r.id);\n const candidateNotes = index.queryByIds(candidateIds);\n\n // Filter: same observation_type, active, not already processed\n const filtered = candidateNotes.filter((note) => {\n if (processedIds.has(note.id)) return false;\n if (!isActiveSpore(note.frontmatter)) return false;\n if (observationType && note.frontmatter['observation_type'] !== observationType) return false;\n return true;\n });\n\n // Build the cluster: include trigger spore if not already present\n const clusterMap = new Map(filtered.map((n) => [n.id, n]));\n if (!clusterMap.has(triggerSpore.id)) {\n clusterMap.set(triggerSpore.id, triggerSpore);\n }\n const cluster = Array.from(clusterMap.values());\n\n if (cluster.length < CONSOLIDATION_MIN_CLUSTER_SIZE) {\n this.log('debug', 'ConsolidationEngine: cluster too small — skipping', {\n triggerId: triggerSpore.id,\n clusterSize: cluster.length,\n minRequired: CONSOLIDATION_MIN_CLUSTER_SIZE,\n });\n cluster.forEach((n) => processedIds.add(n.id));\n continue;\n }\n\n clustersFound++;\n\n // Build consolidation prompt\n const candidatesText = formatNotesForPrompt(cluster);\n\n const prompt = template\n .replace('{{count}}', String(cluster.length))\n .replace('{{observation_type}}', observationType ?? 'unknown')\n .replace('{{candidates}}', candidatesText)\n .replace('{{maxTokens}}', String(this.maxTokens));\n\n // Ask LLM whether to consolidate\n let responseText: string;\n try {\n const response = await llmProvider.summarize(prompt, {\n maxTokens: this.maxTokens,\n reasoning: LLM_REASONING_MODE,\n });\n responseText = stripReasoningTokens(response.text);\n } catch (err) {\n this.log('warn', 'ConsolidationEngine: LLM call failed', {\n triggerId: triggerSpore.id,\n error: String(err),\n });\n cluster.forEach((n) => processedIds.add(n.id));\n continue;\n }\n\n // Parse LLM response\n let parsed: z.infer<typeof consolidationResponseSchema>;\n try {\n const raw = extractJson(responseText);\n const result = consolidationResponseSchema.safeParse(raw);\n if (!result.success) {\n this.log('warn', 'ConsolidationEngine: LLM response failed schema validation', {\n triggerId: triggerSpore.id,\n responseText,\n });\n cluster.forEach((n) => processedIds.add(n.id));\n continue;\n }\n parsed = result.data;\n } catch {\n this.log('warn', 'ConsolidationEngine: failed to parse LLM response', {\n triggerId: triggerSpore.id,\n responseText,\n });\n cluster.forEach((n) => processedIds.add(n.id));\n continue;\n }\n\n if (!parsed.consolidate) {\n this.log('debug', 'ConsolidationEngine: LLM declined to consolidate', {\n triggerId: triggerSpore.id,\n reason: (parsed as { reason?: string }).reason,\n });\n cluster.forEach((n) => processedIds.add(n.id));\n continue;\n }\n\n // Validate source_ids — must be a subset of cluster IDs\n const clusterIdSet = new Set(cluster.map((n) => n.id));\n const validSourceIds = parsed.source_ids.filter((id) => clusterIdSet.has(id));\n\n if (validSourceIds.length < CONSOLIDATION_MIN_CLUSTER_SIZE) {\n this.log('warn', 'ConsolidationEngine: insufficient valid source_ids after validation', {\n triggerId: triggerSpore.id,\n sourceIds: parsed.source_ids,\n validCount: validSourceIds.length,\n });\n cluster.forEach((n) => processedIds.add(n.id));\n continue;\n }\n\n // Call shared consolidation core\n try {\n const consolidateResult = await consolidateSpores(\n {\n sourceSporeIds: validSourceIds,\n consolidatedContent: parsed.content,\n observationType: observationType ?? 'gotcha',\n tags: parsed.tags,\n },\n {\n vaultDir,\n index,\n vectorIndex,\n embeddingProvider: embeddingProvider ?? null,\n },\n );\n\n consolidated++;\n sporesSuperseded += consolidateResult.sources_archived;\n\n this.log('info', 'ConsolidationEngine: consolidated cluster', {\n wisdomId: consolidateResult.wisdom_id,\n sourcesArchived: consolidateResult.sources_archived,\n clusterSize: cluster.length,\n });\n } catch (err) {\n this.log('warn', 'ConsolidationEngine: consolidateSpores failed', {\n triggerId: triggerSpore.id,\n error: String(err),\n });\n }\n\n cluster.forEach((n) => processedIds.add(n.id));\n }\n\n const passTimestamp = new Date().toISOString();\n const durationMs = Date.now() - startTime;\n\n const passResult: ConsolidationPassResult = {\n timestamp: passTimestamp,\n sporesChecked: newSpores.length,\n clustersFound,\n consolidated,\n sporesSuperseded,\n durationMs,\n };\n\n if (consolidated > 0) {\n // Only write trace records for passes that actually consolidated something\n this.appendTrace(passResult);\n } else {\n // Still advance the timestamp cache so we don't re-examine the same spores\n this.lastTimestampCache = passTimestamp;\n }\n\n this.log('info', 'ConsolidationEngine: pass complete', {\n sporesChecked: newSpores.length,\n clustersFound,\n consolidated,\n sporesSuperseded,\n durationMs,\n });\n\n return passResult;\n }\n}\n","import { createHash } from 'node:crypto';\nimport net from 'node:net';\n\nexport const PORT_RANGE_START = 19200;\nexport const PORT_RANGE_SIZE = 10000;\nconst PORT_RETRY_COUNT = 10;\n\n/** Derive a deterministic port from a vault path. */\nexport function derivePort(vaultPath: string): number {\n const hash = createHash('md5').update(vaultPath).digest();\n const num = hash.readUInt16LE(0);\n return PORT_RANGE_START + (num % PORT_RANGE_SIZE);\n}\n\n/** Resolve the port to bind: try config port, derive from path, or fall back to ephemeral. */\nexport async function resolvePort(\n configPort: number | null,\n vaultPath: string,\n): Promise<number> {\n const basePort = configPort ?? derivePort(vaultPath);\n\n for (let offset = 0; offset < PORT_RETRY_COUNT; offset++) {\n const candidate = basePort + offset;\n if (candidate > 65535) break;\n if (await isPortAvailable(candidate)) return candidate;\n }\n\n // All candidates taken — fall back to ephemeral\n return 0;\n}\n\nfunction isPortAvailable(port: number): Promise<boolean> {\n return new Promise((resolve) => {\n const server = net.createServer();\n server.once('error', () => resolve(false));\n server.once('listening', () => {\n server.close(() => resolve(true));\n });\n server.listen(port, '127.0.0.1');\n });\n}\n","import { AgentRegistry } from '../agents/registry.js';\nimport type { AgentAdapter } from '../agents/adapter.js';\nimport { PROMPT_PREVIEW_CHARS } from '../constants.js';\nimport fs from 'node:fs';\n\n// Re-export TranscriptTurn from its canonical home in agents/adapter.ts\nexport type { TranscriptTurn } from '../agents/adapter.js';\nimport type { TranscriptTurn } from '../agents/adapter.js';\n\ninterface TranscriptConfig {\n /** Additional agent adapters to register (useful for testing or custom agents) */\n additionalAdapters?: AgentAdapter[];\n}\n\nexport class TranscriptMiner {\n private registry: AgentRegistry;\n\n constructor(config?: TranscriptConfig) {\n this.registry = new AgentRegistry(config?.additionalAdapters);\n }\n\n /**\n * Extract all conversation turns for a session.\n * Convenience wrapper — delegates to getAllTurnsWithSource.\n */\n getAllTurns(sessionId: string): TranscriptTurn[] {\n return this.getAllTurnsWithSource(sessionId).turns;\n }\n\n /**\n * Extract turns using the hook-provided transcript path first (fast, no scanning),\n * then fall back to adapter registry scanning if the path isn't provided.\n */\n getAllTurnsWithSource(sessionId: string, transcriptPath?: string): { turns: TranscriptTurn[]; source: string } {\n // Primary: use the path provided by the hook (no directory scanning needed)\n if (transcriptPath) {\n const result = this.registry.parseTurnsFromPath(transcriptPath);\n if (result) return result;\n }\n\n // Fallback: scan known agent directories\n const result = this.registry.getTranscriptTurns(sessionId);\n if (result) return result;\n return { turns: [], source: 'none' };\n }\n}\n\n/**\n * Build turns from buffer events — the fallback when no agent transcript is available.\n * Buffer events come from hooks (user_prompt, tool_use) and lack AI responses.\n * Turns will have prompts and tool counts but no aiResponse.\n */\nexport function extractTurnsFromBuffer(events: Array<Record<string, unknown>>): TranscriptTurn[] {\n const turns: TranscriptTurn[] = [];\n let current: TranscriptTurn | null = null;\n\n for (const event of events) {\n const type = event.type as string;\n if (type === 'user_prompt') {\n if (current) turns.push(current);\n current = {\n prompt: String(event.prompt ?? '').slice(0, PROMPT_PREVIEW_CHARS),\n toolCount: 0,\n timestamp: String(event.timestamp ?? new Date().toISOString()),\n };\n } else if (type === 'tool_use') {\n if (current) current.toolCount++;\n }\n }\n if (current) turns.push(current);\n return turns;\n}\n","import { execFileSync } from 'node:child_process';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nexport interface ArtifactCandidate {\n path: string; // relative path from project root\n content: string; // full content read from disk\n}\n\n/** Filenames (case-insensitive) that are agent/plugin infrastructure, not project artifacts. */\nconst EXCLUDED_FILENAMES = new Set([\n 'claude.md',\n 'agents.md',\n 'gemini.md',\n 'readme.md',\n 'contributing.md',\n 'changelog.md',\n 'license.md',\n 'pull_request_template.md',\n]);\n\n/** Directory prefixes (relative to project root) that contain plugin/agent components or repo infrastructure. */\nconst EXCLUDED_PREFIXES = [\n 'commands/',\n 'skills/',\n 'hooks/',\n '.claude-plugin/',\n '.cursor-plugin/',\n '.claude/',\n '.github/',\n];\n\n/**\n * Returns true if a relative path belongs to plugin/agent infrastructure\n * that should never be captured as a project artifact.\n */\nexport function isExcludedPath(relativePath: string): boolean {\n const basename = path.basename(relativePath).toLowerCase();\n if (EXCLUDED_FILENAMES.has(basename)) return true;\n\n const normalized = relativePath.replace(/\\\\/g, '/');\n return EXCLUDED_PREFIXES.some((prefix) => normalized.startsWith(prefix));\n}\n\n/**\n * Filters a set of written/edited file paths by extension, gitignore,\n * and infrastructure exclusions, then reads final content from disk.\n *\n * Uses execFileSync (not exec) for git check-ignore — arguments are passed\n * as an array, so no shell injection risk.\n */\nexport function collectArtifactCandidates(\n filePaths: Set<string>,\n config: { artifact_extensions: string[] },\n projectRoot: string,\n): ArtifactCandidate[] {\n if (filePaths.size === 0) return [];\n\n // Filter by extension first (cheap)\n const extFiltered = [...filePaths].filter((absPath) =>\n config.artifact_extensions.includes(path.extname(absPath)),\n );\n\n if (extFiltered.length === 0) return [];\n\n // Batch git check-ignore: one subprocess instead of N\n const ignoredSet = getGitIgnored(extFiltered, projectRoot);\n\n const candidates: ArtifactCandidate[] = [];\n\n for (const absPath of extFiltered) {\n if (ignoredSet.has(absPath)) continue;\n\n try {\n const content = fs.readFileSync(absPath, 'utf-8');\n const relativePath = path.relative(projectRoot, absPath);\n\n // Skip plugin/agent infrastructure files\n if (isExcludedPath(relativePath)) continue;\n\n candidates.push({ path: relativePath, content });\n } catch {\n // File was deleted between event capture and now — skip\n }\n }\n\n return candidates;\n}\n\nfunction getGitIgnored(filePaths: string[], cwd: string): Set<string> {\n try {\n const result = execFileSync('git', ['check-ignore', ...filePaths], {\n cwd,\n stdio: ['pipe', 'pipe', 'pipe'],\n encoding: 'utf-8',\n });\n return new Set(result.trim().split('\\n').filter(Boolean));\n } catch {\n // exit 1 = none are ignored (or git not available)\n return new Set();\n }\n}\n","import crypto from 'node:crypto';\nimport path from 'node:path';\nimport { MAX_SLUG_LENGTH } from '../constants.js';\n\nexport function slugifyPath(relativePath: string): string {\n const ext = path.extname(relativePath);\n const withoutExt = ext ? relativePath.slice(0, -ext.length) : relativePath;\n\n let slug = withoutExt\n .replace(/[/\\\\]/g, '-')\n .toLowerCase()\n .replace(/\\s+/g, '-')\n .replace(/[^a-z0-9-]/g, '');\n\n if (slug.length > MAX_SLUG_LENGTH) {\n const hash = crypto\n .createHash('sha256')\n .update(relativePath)\n .digest('hex')\n .slice(0, 6);\n slug = slug.slice(0, MAX_SLUG_LENGTH) + '-' + hash;\n }\n\n return slug;\n}\n","import { loadConfig, saveConfig } from '../../config/loader.js';\nimport { MycoConfigSchema } from '../../config/schema.js';\nimport type { RouteResponse } from '../router.js';\n\nexport async function handleGetConfig(vaultDir: string): Promise<RouteResponse> {\n const config = loadConfig(vaultDir);\n return { body: config };\n}\n\nexport async function handlePutConfig(vaultDir: string, body: unknown): Promise<RouteResponse> {\n const result = MycoConfigSchema.safeParse(body);\n if (!result.success) {\n return {\n status: 400,\n body: { error: 'validation_failed', issues: result.error.issues },\n };\n }\n saveConfig(vaultDir, result.data);\n return { body: result.data };\n}\n","import { createHash } from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport type { MycoIndex } from '../../index/sqlite.js';\nimport type { VectorIndex } from '../../index/vectors.js';\nimport type { MycoConfig } from '../../config/schema.js';\nimport { gatherStats } from '../../services/stats.js';\nimport type { RouteResponse } from '../router.js';\nimport type { Metabolism } from '../digest.js';\nimport { CONFIG_FILENAME } from '../../config/loader.js';\n\nexport interface StatsHandlerDeps {\n vaultDir: string;\n index: MycoIndex;\n vectorIndex: VectorIndex | null;\n version: string;\n config: MycoConfig;\n configHash: string;\n metabolism?: Metabolism | null;\n}\n\nexport async function handleGetStats(deps: StatsHandlerDeps): Promise<RouteResponse> {\n const baseStats = gatherStats(deps.vaultDir, deps.index, deps.vectorIndex ?? undefined);\n\n // Digest state — match the spec's StatsResponse shape\n const digestConfig = deps.config.digest;\n const digest = {\n enabled: digestConfig.enabled,\n consolidation_enabled: digestConfig.consolidation.enabled,\n metabolism_state: deps.metabolism?.state ?? null,\n last_cycle: null as { timestamp: string; tier: number; substrate_count: number } | null,\n substrate_queue: 0,\n };\n\n return {\n body: {\n daemon: {\n ...baseStats.daemon,\n pid: baseStats.daemon?.pid ?? process.pid,\n port: baseStats.daemon?.port ?? 0,\n version: deps.version,\n uptime_seconds: process.uptime(),\n active_sessions: baseStats.daemon?.active_sessions ?? [],\n config_hash: deps.configHash,\n },\n vault: baseStats.vault,\n index: baseStats.index,\n digest,\n intelligence: {\n processor: {\n provider: deps.config.intelligence.llm.provider,\n model: deps.config.intelligence.llm.model,\n },\n digest: digestConfig.intelligence.provider ? {\n provider: digestConfig.intelligence.provider,\n model: digestConfig.intelligence.model ?? deps.config.intelligence.llm.model,\n } : null,\n embedding: {\n provider: deps.config.intelligence.embedding.provider,\n model: deps.config.intelligence.embedding.model,\n },\n },\n },\n };\n}\n\n/** Compute config hash from the YAML file on disk. Cache this at startup and after saves. */\nexport function computeConfigHash(vaultDir: string): string {\n try {\n const configPath = path.join(vaultDir, CONFIG_FILENAME);\n const raw = fs.readFileSync(configPath, 'utf-8');\n return createHash('md5').update(raw).digest('hex');\n } catch {\n return '';\n }\n}\n","import type { LogRingBuffer } from '../log-buffer.js';\nimport type { LogLevel } from '../logger.js';\nimport type { RouteResponse } from '../router.js';\n\nexport async function handleGetLogs(\n ringBuffer: LogRingBuffer,\n query: Record<string, string>,\n): Promise<RouteResponse> {\n const since = query.since || null;\n const level = query.level as LogLevel | undefined;\n const limit = query.limit ? parseInt(query.limit, 10) : undefined;\n\n const result = ringBuffer.since(since, { level, limit: isNaN(limit as number) ? undefined : limit });\n\n // Map `component` to `category` in the response entries —\n // the logger uses `component` internally; the API spec uses `category`\n const entries = result.entries.map((entry) => {\n const { component, ...rest } = entry;\n return { ...rest, category: component };\n });\n\n return {\n body: {\n entries,\n cursor: result.cursor,\n ...(result.cursor_reset ? { cursor_reset: true } : {}),\n },\n };\n}\n","import { spawn } from 'node:child_process';\nimport { z } from 'zod';\nimport type { RouteResponse } from '../router.js';\nimport type { ProgressTracker } from './progress.js';\n\nconst RestartBodySchema = z.object({\n force: z.boolean().optional(),\n}).optional();\n\n/** Delay before initiating shutdown — allows the HTTP response to flush. */\nconst RESTART_RESPONSE_FLUSH_MS = 500;\n/** Delay before the child process starts — allows the parent to fully release the port. */\nconst RESTART_CHILD_DELAY_SECONDS = 3;\n\nexport interface RestartHandlerDeps {\n vaultDir: string;\n progressTracker: ProgressTracker;\n}\n\nexport async function handleRestart(\n deps: RestartHandlerDeps,\n body: unknown,\n): Promise<RouteResponse> {\n const parsed = RestartBodySchema.safeParse(body);\n const force = parsed.success ? parsed.data?.force : false;\n\n // Check for active operations unless force is set\n if (!force && deps.progressTracker.hasActiveOperations()) {\n return {\n status: 409,\n body: { status: 'busy', message: 'Active operations in progress. Use force=true to override.' },\n };\n }\n\n // Schedule: respond → wait for flush → SIGTERM self → child starts after parent exits.\n // The child waits RESTART_CHILD_DELAY_SECONDS before starting to ensure the parent\n // has fully released the port and cleaned up daemon.json.\n const daemonScript = process.argv[1];\n const shellCmd = `sleep ${RESTART_CHILD_DELAY_SECONDS} && ${process.execPath} ${daemonScript} --vault ${deps.vaultDir}`;\n\n const child = spawn('/bin/sh', ['-c', shellCmd], {\n detached: true,\n stdio: 'ignore',\n });\n child.unref();\n\n // Schedule self-termination after response flushes\n setTimeout(() => {\n process.kill(process.pid, 'SIGTERM');\n }, RESTART_RESPONSE_FLUSH_MS);\n\n return { body: { status: 'restarting' } };\n}\n","import { randomUUID } from 'node:crypto';\nimport type { RouteResponse } from '../router.js';\n\n/** Maximum number of concurrently tracked operations. */\nconst MAX_CONCURRENT_OPERATIONS = 10;\n\n/** Time-to-live for completed/failed entries before cleanup (ms). */\nconst PROGRESS_TTL_MS = 5 * 60 * 1000;\n\nexport type ProgressStatus = 'running' | 'completed' | 'failed';\n\nexport interface ProgressEntry {\n token: string;\n type: string;\n status: ProgressStatus;\n percent?: number;\n message?: string;\n created: number;\n updated: number;\n}\n\nexport class ProgressTracker {\n private entries = new Map<string, ProgressEntry>();\n\n /**\n * Create a new tracked operation. Returns the existing token if an\n * operation of the same type is already running (duplicate prevention).\n * Throws if the maximum concurrent operations limit is reached.\n */\n /**\n * Create a new tracked operation or return existing one.\n * Returns `{ token, isNew }` — if `isNew` is false, the operation\n * was already running and the caller should NOT launch it again.\n * Throws if the maximum concurrent operations limit is reached.\n */\n create(type: string): { token: string; isNew: boolean } {\n // Lazy cleanup of stale completed/failed entries before checking limits\n this.cleanup();\n\n // Duplicate prevention: if an operation of the same type is already running, return its token\n for (const entry of this.entries.values()) {\n if (entry.type === type && entry.status === 'running') {\n return { token: entry.token, isNew: false };\n }\n }\n\n // Enforce concurrency limit (count only running entries)\n const runningCount = [...this.entries.values()].filter((e) => e.status === 'running').length;\n if (runningCount >= MAX_CONCURRENT_OPERATIONS) {\n throw new Error(`Maximum concurrent operations reached (${MAX_CONCURRENT_OPERATIONS})`);\n }\n\n const token = randomUUID();\n const now = Date.now();\n this.entries.set(token, {\n token,\n type,\n status: 'running',\n created: now,\n updated: now,\n });\n return { token, isNew: true };\n }\n\n /**\n * Update progress for a tracked operation.\n */\n update(token: string, data: { percent?: number; message?: string; status?: ProgressStatus }): void {\n const entry = this.entries.get(token);\n if (!entry) return;\n\n if (data.percent !== undefined) entry.percent = data.percent;\n if (data.message !== undefined) entry.message = data.message;\n if (data.status !== undefined) entry.status = data.status;\n entry.updated = Date.now();\n }\n\n /**\n * Get the current state of a tracked operation.\n */\n get(token: string): ProgressEntry | undefined {\n return this.entries.get(token);\n }\n\n /**\n * Check whether any operations are currently running.\n */\n hasActiveOperations(): boolean {\n for (const entry of this.entries.values()) {\n if (entry.status === 'running') return true;\n }\n return false;\n }\n\n /**\n * Remove completed/failed entries older than PROGRESS_TTL_MS.\n */\n cleanup(): void {\n const cutoff = Date.now() - PROGRESS_TTL_MS;\n for (const [token, entry] of this.entries) {\n if (entry.status !== 'running' && entry.updated < cutoff) {\n this.entries.delete(token);\n }\n }\n }\n}\n\nexport async function handleGetProgress(\n tracker: ProgressTracker,\n token: string,\n): Promise<RouteResponse> {\n const entry = tracker.get(token);\n if (!entry) {\n return { status: 404, body: { error: 'not_found', message: 'Progress token not found' } };\n }\n return { body: entry };\n}\n","/**\n * API handlers for long-running vault operations: curate, rebuild, digest.\n *\n * Each handler follows the thin-handler pattern: validate input, create a\n * progress token, fire-and-forget the operation with progress updates,\n * return the token immediately. Callers poll GET /api/progress/:token.\n *\n * Curate in dry-run mode is an exception: it runs synchronously and returns\n * results inline (no progress token).\n */\n\nimport { z } from 'zod';\nimport type { RouteResponse } from '../router.js';\nimport type { ProgressTracker } from './progress.js';\nimport type { MycoIndex } from '../../index/sqlite.js';\nimport type { VectorIndex } from '../../index/vectors.js';\nimport type { MycoConfig } from '../../config/schema.js';\nimport type { LlmProvider, EmbeddingProvider } from '../../intelligence/llm.js';\nimport type { PipelineManager } from '../pipeline.js';\nimport { runRebuild, runDigest, runReprocess } from '../../services/vault-ops.js';\nimport type { CurationDeps, CurationResult, ReprocessOptions } from '../../services/vault-ops.js';\n\n/** Percentage representing full completion. */\nconst PROGRESS_COMPLETE = 100;\n\n// --- Shared deps interface ---\n\nexport interface OperationHandlerDeps {\n vaultDir: string;\n config: MycoConfig;\n index: MycoIndex;\n vectorIndex: VectorIndex | null;\n llmProvider: LlmProvider;\n /** Digest-specific LLM provider (may differ from main llmProvider). */\n digestLlmProvider: LlmProvider;\n embeddingProvider: EmbeddingProvider;\n progressTracker: ProgressTracker;\n pipeline?: PipelineManager;\n log: (level: string, message: string, data?: Record<string, unknown>) => void;\n}\n\n// --- Request body schemas ---\n\nconst CurateBody = z.object({\n dry_run: z.boolean().optional(),\n}).optional();\n\nconst DigestBody = z.object({\n tier: z.number().int().positive().optional(),\n full: z.boolean().optional(),\n}).optional();\n\nconst ReprocessBody = z.object({\n session: z.string().optional(),\n date: z.string().optional(),\n failed: z.boolean().optional(),\n index_only: z.boolean().optional(),\n}).optional();\n\n// --- Rebuild ---\n\nexport async function handleRebuild(deps: OperationHandlerDeps): Promise<RouteResponse> {\n const { token, isNew } = deps.progressTracker.create('rebuild');\n\n if (!isNew) {\n return { body: { token, status: 'already_running' } };\n }\n\n // Fire-and-forget\n runRebuild(\n {\n vaultDir: deps.vaultDir,\n config: deps.config,\n index: deps.index,\n vectorIndex: deps.vectorIndex ?? undefined,\n pipeline: deps.pipeline,\n log: deps.log,\n },\n deps.embeddingProvider,\n (done, total) => {\n const percent = total > 0 ? Math.round((done / total) * PROGRESS_COMPLETE) : 0;\n deps.progressTracker.update(token, {\n percent,\n message: `Embedded ${done}/${total} notes`,\n });\n },\n ).then((result) => {\n deps.progressTracker.update(token, {\n status: 'completed',\n percent: PROGRESS_COMPLETE,\n message: `FTS: ${result.ftsCount}, embedded: ${result.embeddedCount}, failed: ${result.failedCount}, skipped: ${result.skippedCount}`,\n });\n deps.log('info', 'Rebuild completed via API', {\n fts: result.ftsCount,\n embedded: result.embeddedCount,\n failed: result.failedCount,\n });\n }).catch((err) => {\n deps.progressTracker.update(token, {\n status: 'failed',\n message: (err as Error).message,\n });\n deps.log('warn', 'Rebuild failed via API', { error: (err as Error).message });\n });\n\n return { body: { token } };\n}\n\n// --- Digest ---\n\nexport async function handleDigest(\n deps: OperationHandlerDeps,\n body: unknown,\n): Promise<RouteResponse> {\n const parsed = DigestBody.safeParse(body);\n if (!parsed.success) {\n return { status: 400, body: { error: 'validation_failed', issues: parsed.error.issues } };\n }\n\n if (!deps.config.digest.enabled) {\n return { status: 400, body: { error: 'digest_disabled', message: 'Digest is not enabled in myco.yaml' } };\n }\n\n const options = parsed.data;\n const { token, isNew } = deps.progressTracker.create('digest');\n\n if (!isNew) {\n return { body: { token, status: 'already_running' } };\n }\n\n // Resolve digest LLM provider: use digest-specific config if set, otherwise fall back to main\n // The daemon already has the main llmProvider; digest may use a different model.\n // For API-triggered digests, we use the daemon's main llmProvider. The daemon's\n // main.ts can pass a separate digestLlmProvider if needed.\n\n // Fire-and-forget\n runDigest(\n {\n vaultDir: deps.vaultDir,\n config: deps.config,\n index: deps.index,\n vectorIndex: deps.vectorIndex ?? undefined,\n pipeline: deps.pipeline,\n log: deps.log,\n },\n deps.digestLlmProvider,\n options ?? undefined,\n ).then((result) => {\n if (result) {\n deps.progressTracker.update(token, {\n status: 'completed',\n percent: PROGRESS_COMPLETE,\n message: `Tiers: [${result.tiersGenerated.join(', ')}], substrate: ${Object.values(result.substrate).flat().length} notes, ${(result.durationMs / 1000).toFixed(1)}s`,\n });\n deps.log('info', 'Digest completed via API', {\n tiers: result.tiersGenerated,\n duration: result.durationMs,\n });\n } else {\n deps.progressTracker.update(token, {\n status: 'completed',\n percent: PROGRESS_COMPLETE,\n message: 'No substrate found — nothing to digest',\n });\n }\n }).catch((err) => {\n deps.progressTracker.update(token, {\n status: 'failed',\n message: (err as Error).message,\n });\n deps.log('warn', 'Digest failed via API', { error: (err as Error).message });\n });\n\n return { body: { token } };\n}\n\n// --- Curate ---\n\n/**\n * Run curation. The curate logic is complex and tightly coupled to LLM providers.\n * Rather than fully extracting it, we accept a `runCuration` callback that the\n * daemon's main.ts wires up with its live instances.\n */\nexport async function handleCurate(\n deps: OperationHandlerDeps,\n body: unknown,\n runCuration: (curationDeps: CurationDeps, dryRun: boolean) => Promise<CurationResult>,\n): Promise<RouteResponse> {\n const parsed = CurateBody.safeParse(body);\n if (!parsed.success) {\n return { status: 400, body: { error: 'validation_failed', issues: parsed.error.issues } };\n }\n\n const isDryRun = parsed.data?.dry_run ?? false;\n\n if (!deps.vectorIndex) {\n return { status: 400, body: { error: 'vector_index_unavailable', message: 'Curate requires a working embedding provider' } };\n }\n\n const curationDeps: CurationDeps = {\n vaultDir: deps.vaultDir,\n config: deps.config,\n index: deps.index,\n vectorIndex: deps.vectorIndex,\n llmProvider: deps.llmProvider,\n embeddingProvider: deps.embeddingProvider,\n pipeline: deps.pipeline,\n log: deps.log,\n };\n\n // Dry run: synchronous response with results\n if (isDryRun) {\n try {\n const result = await runCuration(curationDeps, true);\n return { body: { dry_run: true, ...result } };\n } catch (err) {\n return { status: 500, body: { error: 'curation_failed', message: (err as Error).message } };\n }\n }\n\n // Full run: async with progress token\n const { token, isNew } = deps.progressTracker.create('curate');\n\n if (!isNew) {\n return { body: { token, status: 'already_running' } };\n }\n\n runCuration(curationDeps, false)\n .then((result) => {\n deps.progressTracker.update(token, {\n status: 'completed',\n percent: PROGRESS_COMPLETE,\n message: `Scanned: ${result.scanned}, clusters: ${result.clustersEvaluated}, superseded: ${result.superseded}`,\n });\n deps.log('info', 'Curation completed via API', { ...result });\n })\n .catch((err) => {\n deps.progressTracker.update(token, {\n status: 'failed',\n message: (err as Error).message,\n });\n deps.log('warn', 'Curation failed via API', { error: (err as Error).message });\n });\n\n return { body: { token } };\n}\n\n// --- Reprocess ---\n\nexport async function handleReprocess(\n deps: OperationHandlerDeps,\n body: unknown,\n): Promise<RouteResponse> {\n const parsed = ReprocessBody.safeParse(body);\n if (!parsed.success) {\n return { status: 400, body: { error: 'validation_failed', issues: parsed.error.issues } };\n }\n\n const options: ReprocessOptions = {\n session: parsed.data?.session,\n date: parsed.data?.date,\n failed: parsed.data?.failed,\n indexOnly: parsed.data?.index_only,\n };\n\n const { token, isNew } = deps.progressTracker.create('reprocess');\n\n if (!isNew) {\n return { body: { token, status: 'already_running' } };\n }\n\n runReprocess(\n {\n vaultDir: deps.vaultDir,\n config: deps.config,\n index: deps.index,\n vectorIndex: deps.vectorIndex ?? undefined,\n pipeline: deps.pipeline,\n log: deps.log,\n },\n deps.llmProvider,\n deps.embeddingProvider,\n options,\n (phase, done, total) => {\n const percent = total > 0 ? Math.round((done / total) * PROGRESS_COMPLETE) : 0;\n deps.progressTracker.update(token, {\n percent,\n message: `${phase}: ${done}/${total}`,\n });\n },\n ).then((result) => {\n const message = result.sessionsProcessed === 0\n ? `No matching sessions found (${result.sessionsFound} checked)`\n : `${result.sessionsProcessed} sessions, ${result.observationsExtracted} observations, ${result.summariesRegenerated} summaries`;\n deps.progressTracker.update(token, {\n status: 'completed',\n percent: PROGRESS_COMPLETE,\n message,\n });\n deps.log('info', 'Reprocess completed via API', { ...result });\n }).catch((err) => {\n deps.progressTracker.update(token, {\n status: 'failed',\n message: (err as Error).message,\n });\n deps.log('warn', 'Reprocess failed via API', { error: (err as Error).message });\n });\n\n return { body: { token } };\n}\n","import { OllamaBackend } from '../../intelligence/ollama.js';\nimport { LmStudioBackend } from '../../intelligence/lm-studio.js';\nimport type { RouteRequest, RouteResponse } from '../router.js';\n\nconst MODEL_LIST_TIMEOUT_MS = 5000;\n\n/** Well-known Anthropic models — no list API available locally. */\nconst ANTHROPIC_MODELS = [\n 'claude-opus-4-6',\n 'claude-sonnet-4-6',\n 'claude-haiku-4-5-20251001',\n];\n\n/** Patterns that indicate an embedding model (case-insensitive). */\nconst EMBEDDING_PATTERNS = [\n 'embed', 'bge-', 'nomic-embed', 'e5-', 'gte-', 'granite-embedding',\n];\n\n/** Filter models to only include embedding models. */\nfunction filterEmbeddingModels(models: string[]): string[] {\n return models.filter((m) => {\n const name = m.toLowerCase();\n return EMBEDDING_PATTERNS.some((p) => name.includes(p));\n });\n}\n\n/** Filter models to exclude embedding models (LLM-only). */\nfunction filterLlmModels(models: string[]): string[] {\n return models.filter((m) => {\n const name = m.toLowerCase();\n return !EMBEDDING_PATTERNS.some((p) => name.includes(p));\n });\n}\n\nexport async function handleGetModels(req: RouteRequest): Promise<RouteResponse> {\n const provider = req.query.provider;\n const type = req.query.type; // 'llm' | 'embedding' | undefined (all)\n\n if (!provider) {\n return { status: 400, body: { error: 'provider query parameter required' } };\n }\n\n let models: string[] = [];\n\n try {\n if (provider === 'ollama') {\n const backend = new OllamaBackend({ base_url: req.query.base_url });\n models = await backend.listModels(MODEL_LIST_TIMEOUT_MS);\n } else if (provider === 'lm-studio' || provider === 'openai-compatible') {\n const backend = new LmStudioBackend({ base_url: req.query.base_url });\n models = await backend.listModels(MODEL_LIST_TIMEOUT_MS);\n } else if (provider === 'anthropic') {\n models = ANTHROPIC_MODELS;\n }\n } catch {\n // Provider unreachable — return empty list\n }\n\n // Filter by type if requested\n if (type === 'embedding') {\n models = filterEmbeddingModels(models);\n } else if (type === 'llm') {\n models = filterLlmModels(models);\n }\n\n return { body: { provider, models } };\n}\n","import type { MycoIndex } from '../../index/sqlite.js';\nimport type { RouteResponse } from '../router.js';\nimport { SUMMARIZATION_FAILED_MARKER } from '../processor.js';\n\n/** Serve session list from the SQLite index — no disk I/O required. */\nexport function handleGetSessions(index: MycoIndex): RouteResponse {\n const notes = index.query({ type: 'session' });\n\n const dateSet = new Set<string>();\n const sessions: Array<{ id: string; date: string; title: string; hasFailed: boolean }> = [];\n\n for (const note of notes) {\n // path is \"sessions/YYYY-MM-DD/session-<id>.md\"\n const parts = note.path.split('/');\n const date = parts[1] ?? '';\n const filename = parts[2] ?? '';\n const id = filename.replace('session-', '').replace('.md', '');\n\n dateSet.add(date);\n sessions.push({\n id,\n date,\n title: note.title || id.slice(0, 8),\n hasFailed: note.content.includes(SUMMARIZATION_FAILED_MARKER),\n });\n }\n\n const dates = [...dateSet].sort().reverse();\n return { body: { sessions, dates } };\n}\n","/**\n * API handlers for pipeline health, items, circuits, and retry operations.\n *\n * Each handler follows the thin-handler pattern: validate input,\n * delegate to PipelineManager, return RouteResponse.\n */\n\nimport { z } from 'zod';\nimport type { RouteRequest, RouteResponse } from '../router.js';\nimport type { PipelineManager } from '../pipeline.js';\nimport { PIPELINE_PROVIDER_ROLES } from '../../constants.js';\n\n// --- Request body schemas ---\n\nconst RetryItemBody = z.object({\n type: z.string(),\n stage: z.string(),\n});\n\n// --- GET /api/pipeline/health ---\n\nexport function handlePipelineHealth(pipeline: PipelineManager): (req: RouteRequest) => Promise<RouteResponse> {\n return async () => {\n const health = pipeline.health();\n return { body: health };\n };\n}\n\n// --- GET /api/pipeline/items ---\n\nexport function handlePipelineItems(pipeline: PipelineManager): (req: RouteRequest) => Promise<RouteResponse> {\n return async (req) => {\n const { stage, status, type, limit, offset } = req.query;\n\n const parsedLimit = limit ? parseInt(limit, 10) : undefined;\n const parsedOffset = offset ? parseInt(offset, 10) : undefined;\n\n if (limit && (isNaN(parsedLimit!) || parsedLimit! < 0)) {\n return { status: 400, body: { error: 'invalid_limit', message: 'limit must be a non-negative integer' } };\n }\n if (offset && (isNaN(parsedOffset!) || parsedOffset! < 0)) {\n return { status: 400, body: { error: 'invalid_offset', message: 'offset must be a non-negative integer' } };\n }\n\n const result = pipeline.listItems({\n stage,\n status,\n type,\n limit: parsedLimit,\n offset: parsedOffset,\n });\n\n return { body: result };\n };\n}\n\n// --- GET /api/pipeline/items/:id ---\n\nexport function handlePipelineItemDetail(pipeline: PipelineManager): (req: RouteRequest) => Promise<RouteResponse> {\n return async (req) => {\n const { id } = req.params;\n const { type } = req.query;\n\n if (!type) {\n return { status: 400, body: { error: 'missing_type', message: 'query param \"type\" is required' } };\n }\n\n const stages = pipeline.getItemStatus(id, type);\n if (stages.length === 0) {\n return { status: 404, body: { error: 'not_found', message: `No work item found: ${id} (${type})` } };\n }\n\n const history = pipeline.getTransitionHistory(id, type);\n\n return { body: { id, type, stages, history } };\n };\n}\n\n// --- GET /api/pipeline/circuits ---\n\nexport function handlePipelineCircuits(pipeline: PipelineManager): (req: RouteRequest) => Promise<RouteResponse> {\n return async () => {\n const circuits = pipeline.listCircuits();\n return { body: circuits };\n };\n}\n\n// --- POST /api/pipeline/retry/:id ---\n\nexport function handlePipelineRetry(pipeline: PipelineManager): (req: RouteRequest) => Promise<RouteResponse> {\n return async (req) => {\n const { id } = req.params;\n const parsed = RetryItemBody.safeParse(req.body);\n\n if (!parsed.success) {\n return { status: 400, body: { error: 'validation_failed', issues: parsed.error.issues } };\n }\n\n const { type, stage } = parsed.data;\n const retried = pipeline.retryItem(id, type, stage);\n\n if (!retried) {\n return { status: 404, body: { error: 'not_poisoned', message: `Item ${id} is not poisoned at stage ${stage}` } };\n }\n\n return { body: { retried: true, id, type, stage } };\n };\n}\n\n// --- POST /api/pipeline/skip/:id ---\n\nexport function handlePipelineSkip(pipeline: PipelineManager): (req: RouteRequest) => Promise<RouteResponse> {\n return async (req) => {\n const { id } = req.params;\n const parsed = RetryItemBody.safeParse(req.body);\n\n if (!parsed.success) {\n return { status: 400, body: { error: 'validation_failed', issues: parsed.error.issues } };\n }\n\n const { type, stage } = parsed.data;\n const skipped = pipeline.skipItem(id, type, stage);\n\n if (!skipped) {\n return { status: 404, body: { error: 'not_skippable', message: `Item ${id} is not failed or poisoned at stage ${stage}` } };\n }\n\n return { body: { skipped: true, id, type, stage } };\n };\n}\n\n// --- POST /api/pipeline/retry-all ---\n\nexport function handlePipelineRetryAll(pipeline: PipelineManager): (req: RouteRequest) => Promise<RouteResponse> {\n return async () => {\n const count = pipeline.retryAllPoisoned();\n return { body: { retried: count } };\n };\n}\n\n// --- POST /api/pipeline/circuit/:provider/reset ---\n\nexport function handlePipelineCircuitReset(pipeline: PipelineManager): (req: RouteRequest) => Promise<RouteResponse> {\n return async (req) => {\n const { provider } = req.params;\n\n if (!(PIPELINE_PROVIDER_ROLES as readonly string[]).includes(provider)) {\n return {\n status: 400,\n body: {\n error: 'unknown_provider',\n message: `Unknown provider role '${provider}'. Valid roles: ${PIPELINE_PROVIDER_ROLES.join(', ')}`,\n },\n };\n }\n\n pipeline.resetCircuit(provider);\n const unblocked = pipeline.unblockItemsForCircuit(provider);\n\n return { body: { reset: true, provider, unblocked } };\n };\n}\n","/**\n * API handlers for digest health and manual triggering.\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport YAML from 'yaml';\nimport type { RouteRequest, RouteResponse } from '../router.js';\nimport type { DigestCycleResult } from '../digest.js';\nimport { readLastRecord } from '../trace.js';\n\n// --- POST /api/pipeline/digest/force ---\n\nexport function handleForceDigest(\n setForceDigest: () => void,\n): (req: RouteRequest) => Promise<RouteResponse> {\n return async () => {\n setForceDigest();\n return {\n body: {\n status: 'queued',\n message: 'Digest will run on next pipeline tick (upstream must be clear)',\n },\n };\n };\n}\n\n// --- GET /api/pipeline/digest-health ---\n\ninterface DigestHealthDeps {\n vaultDir: string;\n pipeline: { newSubstrateSinceLastDigest: () => number };\n minNotesForCycle: number;\n metabolismState: () => string;\n digestReady: () => boolean;\n cycleInProgress: () => boolean;\n}\n\n/** Read the `generated` timestamp from an extract file's frontmatter. */\nfunction readExtractTimestamp(extractPath: string): string | null {\n try {\n const content = fs.readFileSync(extractPath, 'utf-8');\n const fmMatch = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!fmMatch) return null;\n const fm = YAML.parse(fmMatch[1]) as Record<string, unknown>;\n return typeof fm.generated === 'string' ? fm.generated : null;\n } catch {\n return null;\n }\n}\n\nexport function handleDigestHealth(\n deps: DigestHealthDeps,\n): (req: RouteRequest) => Promise<RouteResponse> {\n return async () => {\n const tracePath = path.join(deps.vaultDir, 'digest', 'trace.jsonl');\n const lastCycle = readLastRecord<DigestCycleResult>(tracePath);\n\n // Trace may be stale if a cycle was interrupted before appendTrace().\n // Cross-check against extract files' generated timestamps.\n let lastCycleTimestamp = lastCycle?.timestamp ?? null;\n const digestDir = path.join(deps.vaultDir, 'digest');\n try {\n for (const file of fs.readdirSync(digestDir)) {\n if (!file.startsWith('extract-') || !file.endsWith('.md')) continue;\n const extractTs = readExtractTimestamp(path.join(digestDir, file));\n if (extractTs && (!lastCycleTimestamp || extractTs > lastCycleTimestamp)) {\n lastCycleTimestamp = extractTs;\n }\n }\n } catch {\n // digest dir may not exist\n }\n\n const substrateReady = deps.pipeline.newSubstrateSinceLastDigest();\n\n return {\n body: {\n last_cycle: lastCycleTimestamp ? {\n cycle_id: lastCycle?.cycleId ?? null,\n timestamp: lastCycleTimestamp,\n substrate_count: lastCycle ? Object.values(lastCycle.substrate).flat().length : null,\n tiers_generated: lastCycle?.tiersGenerated ?? null,\n duration_ms: lastCycle?.durationMs ?? null,\n model: lastCycle?.model ?? null,\n } : null,\n substrate_ready: substrateReady,\n substrate_threshold: deps.minNotesForCycle,\n metabolism_state: deps.metabolismState(),\n digest_ready: deps.digestReady(),\n cycle_in_progress: deps.cycleInProgress(),\n },\n };\n };\n}\n","/**\n * PipelineManager — SQLite-backed pipeline state for work item tracking,\n * stage transitions, and circuit breakers.\n *\n * Follows the same database pattern as MycoIndex (src/index/sqlite.ts):\n * better-sqlite3, WAL mode, CREATE IF NOT EXISTS for idempotency.\n */\n\nimport Database from 'better-sqlite3';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { walkMarkdownFiles } from '../vault/reader.js';\nimport type { PipelineStage, PipelineStatus, PipelineProviderRole } from '@myco/constants';\nimport type { PipelineConfig } from '@myco/config/schema';\nimport {\n PIPELINE_STAGES,\n PIPELINE_TICK_STAGES,\n ITEM_STAGE_MAP,\n PIPELINE_PARSE_MAX_RETRIES,\n PIPELINE_BACKOFF_MULTIPLIER,\n PIPELINE_ITEMS_DEFAULT_LIMIT,\n STAGE_PROVIDER_MAP,\n MS_PER_DAY,\n} from '@myco/constants';\nimport { classifyError } from '@myco/daemon/pipeline-classify';\n\n/** Database filename within the vault directory. */\nconst PIPELINE_DB_FILENAME = 'pipeline.db';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface CircuitState {\n provider_role: string;\n state: 'closed' | 'open' | 'half-open';\n failure_count: number;\n last_failure: string | null;\n last_error: string | null;\n opens_at: string | null;\n updated_at: string;\n}\n\nexport interface PipelineHealth {\n stages: Record<string, Record<string, number>>;\n circuits: Array<{\n provider_role: string;\n state: string;\n failure_count: number;\n last_error: string | null;\n }>;\n totals: {\n pending: number;\n processing: number;\n failed: number;\n blocked: number;\n poisoned: number;\n succeeded: number;\n };\n}\n\nexport interface AdvanceOptions {\n errorType?: 'transient' | 'config' | 'parse';\n errorMessage?: string;\n}\n\nexport interface StageStatus {\n stage: string;\n status: string;\n attempt: number;\n error_type: string | null;\n error_message: string | null;\n started_at: string | null;\n completed_at: string | null;\n output: string | null;\n}\n\nexport interface BatchItem {\n id: string;\n item_type: string;\n source_path: string | null;\n created_at: string;\n}\n\nexport interface PipelineItem {\n id: string;\n item_type: string;\n source_path: string | null;\n stage: string;\n status: string;\n attempt: number;\n error_type: string | null;\n error_message: string | null;\n started_at: string | null;\n completed_at: string | null;\n}\n\nexport interface TransitionRecord {\n id: number;\n work_item_id: string;\n item_type: string;\n stage: string;\n status: string;\n attempt: number;\n error_type: string | null;\n error_message: string | null;\n started_at: string | null;\n completed_at: string | null;\n output: string | null;\n created_at: string;\n}\n\nexport interface RebuildResult {\n registered: number;\n stages: Record<string, number>;\n}\n\n/** Minimal interface for vector index lookups during rebuild. */\nexport interface VectorHasCheck {\n has(id: string): boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Stage handlers interface\n// ---------------------------------------------------------------------------\n\n/**\n * Handlers called by tick() for each processable stage.\n * Digest is NOT here — it's gated by the metabolism timer, not the pipeline tick.\n */\nexport interface StageHandlers {\n extraction: (itemId: string, itemType: string, sourcePath: string | null) => Promise<Record<string, unknown> | void>;\n embedding: (itemId: string, itemType: string, sourcePath: string | null) => Promise<Record<string, unknown> | void>;\n consolidation: (itemId: string, itemType: string, sourcePath: string | null) => Promise<Record<string, unknown> | void>;\n}\n\n/** Optional logger for tick() diagnostics. */\nexport type TickLogger = (level: string, domain: string, message: string, data?: Record<string, unknown>) => void;\n\n// ---------------------------------------------------------------------------\n// Schema SQL\n// ---------------------------------------------------------------------------\n\nconst SCHEMA_SQL = `\n -- work_items: every piece of content in the pipeline\n CREATE TABLE IF NOT EXISTS work_items (\n id TEXT NOT NULL,\n item_type TEXT NOT NULL,\n source_path TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n PRIMARY KEY (id, item_type)\n );\n\n -- stage_transitions: append-only audit trail\n CREATE TABLE IF NOT EXISTS stage_transitions (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n work_item_id TEXT NOT NULL,\n item_type TEXT NOT NULL,\n stage TEXT NOT NULL,\n status TEXT NOT NULL,\n attempt INTEGER DEFAULT 1,\n error_type TEXT,\n error_message TEXT,\n started_at TEXT,\n completed_at TEXT,\n output TEXT,\n created_at TEXT NOT NULL,\n FOREIGN KEY (work_item_id, item_type) REFERENCES work_items(id, item_type)\n );\n\n -- stage_history: compacted transitions older than retention window\n CREATE TABLE IF NOT EXISTS stage_history (\n work_item_id TEXT NOT NULL,\n item_type TEXT NOT NULL,\n stage TEXT NOT NULL,\n total_attempts INTEGER,\n final_status TEXT NOT NULL,\n first_attempt TEXT NOT NULL,\n last_attempt TEXT NOT NULL,\n last_error TEXT,\n error_types TEXT,\n last_output TEXT,\n PRIMARY KEY (work_item_id, item_type, stage)\n );\n\n -- circuit_breakers: per-provider-role state\n CREATE TABLE IF NOT EXISTS circuit_breakers (\n provider_role TEXT PRIMARY KEY,\n state TEXT NOT NULL DEFAULT 'closed',\n failure_count INTEGER DEFAULT 0,\n last_failure TEXT,\n last_error TEXT,\n opens_at TEXT,\n updated_at TEXT NOT NULL\n );\n`;\n\nconst INDEXES_SQL = `\n CREATE INDEX IF NOT EXISTS idx_transitions_item_stage\n ON stage_transitions(work_item_id, item_type, stage);\n CREATE INDEX IF NOT EXISTS idx_transitions_status\n ON stage_transitions(status);\n CREATE INDEX IF NOT EXISTS idx_items_type\n ON work_items(item_type);\n`;\n\nconst VIEW_SQL = `\n CREATE VIEW IF NOT EXISTS pipeline_status AS\n WITH ranked AS (\n SELECT st.*,\n ROW_NUMBER() OVER (\n PARTITION BY st.work_item_id, st.item_type, st.stage\n ORDER BY st.id DESC\n ) AS rn\n FROM stage_transitions st\n )\n SELECT\n wi.id, wi.item_type, wi.source_path,\n r.stage, r.status, r.attempt,\n r.error_type, r.error_message,\n r.started_at, r.completed_at,\n r.output\n FROM work_items wi\n JOIN ranked r ON r.work_item_id = wi.id AND r.item_type = wi.item_type\n WHERE r.rn = 1;\n`;\n\n// ---------------------------------------------------------------------------\n// Health query SQL\n// ---------------------------------------------------------------------------\n\n/** Aggregate counts of stage x status from the pipeline_status view. */\nconst HEALTH_STAGE_STATUS_SQL = `\n SELECT stage, status, COUNT(*) as count\n FROM pipeline_status\n GROUP BY stage, status\n`;\n\n/** All circuit breaker rows. */\nconst HEALTH_CIRCUITS_SQL = `\n SELECT provider_role, state, failure_count, last_error\n FROM circuit_breakers\n`;\n\n// ---------------------------------------------------------------------------\n// PipelineManager\n// ---------------------------------------------------------------------------\n\nexport class PipelineManager {\n private db: Database.Database;\n private config: PipelineConfig;\n\n constructor(vaultDir: string, config: PipelineConfig) {\n const dbPath = path.join(vaultDir, PIPELINE_DB_FILENAME);\n this.db = new Database(dbPath);\n this.db.pragma('journal_mode = WAL');\n this.db.pragma('foreign_keys = ON');\n this.config = config;\n this.init();\n }\n\n private init(): void {\n // Drop the view before schema so CREATE VIEW IF NOT EXISTS picks up new columns\n this.db.exec('DROP VIEW IF EXISTS pipeline_status');\n\n this.db.exec(SCHEMA_SQL);\n\n // Migrations for existing databases\n try {\n this.db.exec('ALTER TABLE stage_transitions ADD COLUMN output TEXT');\n } catch {\n // Column already exists\n }\n try {\n this.db.exec('ALTER TABLE stage_history ADD COLUMN last_output TEXT');\n } catch {\n // Column already exists\n }\n\n this.db.exec(INDEXES_SQL);\n this.db.exec(VIEW_SQL);\n }\n\n /** Expose the underlying database for direct queries (used in tests and by higher-level methods). */\n getDb(): Database.Database {\n return this.db;\n }\n\n /** Read a PRAGMA value (used in tests to verify WAL mode and foreign keys). */\n getPragma(name: string): unknown {\n return this.db.pragma(name, { simple: true });\n }\n\n /** Quick check whether the pipeline has any registered work items. */\n isEmpty(): boolean {\n const row = this.db.prepare('SELECT 1 FROM work_items LIMIT 1').get();\n return !row;\n }\n\n /** Aggregate pipeline health: stage/status counts, circuit states, totals. */\n health(): PipelineHealth {\n const stageRows = this.db.prepare(HEALTH_STAGE_STATUS_SQL).all() as Array<{\n stage: string;\n status: string;\n count: number;\n }>;\n\n const stages: Record<string, Record<string, number>> = {};\n const totals: PipelineHealth['totals'] = {\n pending: 0,\n processing: 0,\n failed: 0,\n blocked: 0,\n poisoned: 0,\n succeeded: 0,\n };\n\n for (const row of stageRows) {\n if (!stages[row.stage]) {\n stages[row.stage] = {};\n }\n stages[row.stage][row.status] = row.count;\n\n // Accumulate into totals if the status is one we track\n if (row.status in totals) {\n totals[row.status as keyof typeof totals] += row.count;\n }\n }\n\n const circuitRows = this.db.prepare(HEALTH_CIRCUITS_SQL).all() as Array<{\n provider_role: string;\n state: string;\n failure_count: number;\n last_error: string | null;\n }>;\n\n const circuits = circuitRows.map((r) => ({\n provider_role: r.provider_role,\n state: r.state,\n failure_count: r.failure_count,\n last_error: r.last_error,\n }));\n\n return { stages, circuits, totals };\n }\n\n // -------------------------------------------------------------------------\n // Work item registration\n // -------------------------------------------------------------------------\n\n /**\n * Register a work item in the pipeline. Creates the work_items row and\n * initial stage_transitions for all applicable stages.\n *\n * Uses INSERT OR IGNORE for work_items (idempotency — re-registering is a no-op).\n * Checks if transitions already exist before inserting.\n */\n register(itemId: string, itemType: string, sourcePath?: string): void {\n const now = new Date().toISOString();\n\n // INSERT OR IGNORE — idempotent for the work_items row\n this.db\n .prepare(\n 'INSERT OR IGNORE INTO work_items (id, item_type, source_path, created_at, updated_at) VALUES (?, ?, ?, ?, ?)',\n )\n .run(itemId, itemType, sourcePath ?? null, now, now);\n\n // Check if transitions already exist (idempotency guard)\n const existingCount = this.db\n .prepare(\n 'SELECT COUNT(*) as cnt FROM stage_transitions WHERE work_item_id = ? AND item_type = ?',\n )\n .get(itemId, itemType) as { cnt: number };\n\n if (existingCount.cnt > 0) {\n return; // Already registered — skip transition creation\n }\n\n const applicableStages = ITEM_STAGE_MAP[itemType] ?? [];\n const insertStmt = this.db.prepare(\n 'INSERT INTO stage_transitions (work_item_id, item_type, stage, status, attempt, created_at) VALUES (?, ?, ?, ?, ?, ?)',\n );\n\n const insertAll = this.db.transaction(() => {\n for (const stage of PIPELINE_STAGES) {\n const status = applicableStages.includes(stage) ? 'pending' : 'skipped';\n insertStmt.run(itemId, itemType, stage, status, 1, now);\n }\n });\n insertAll();\n }\n\n // -------------------------------------------------------------------------\n // Stage transitions\n // -------------------------------------------------------------------------\n\n /**\n * Record a stage transition. Append-only — never updates existing rows.\n *\n * When status is 'failed': checks retry limits and may auto-poison.\n * When error_type is 'config': blocks all downstream stages.\n */\n advance(\n itemId: string,\n itemType: string,\n stage: string,\n status: string,\n error?: AdvanceOptions,\n output?: Record<string, unknown>,\n ): void {\n const now = new Date().toISOString();\n\n // Calculate attempt by counting prior transitions with 'failed' or 'processing' status\n const priorCount = this.db\n .prepare(\n `SELECT COUNT(*) as cnt FROM stage_transitions\n WHERE work_item_id = ? AND item_type = ? AND stage = ?\n AND status IN ('failed', 'processing')`,\n )\n .get(itemId, itemType, stage) as { cnt: number };\n\n const attempt = status === 'failed' || status === 'processing'\n ? Math.ceil((priorCount.cnt + 1) / 2) || 1\n : priorCount.cnt > 0\n ? Math.ceil(priorCount.cnt / 2) || 1\n : 1;\n\n let resolvedStatus = status;\n\n // Check for auto-poison on failure\n if (status === 'failed' && error?.errorType) {\n const maxRetries =\n error.errorType === 'transient'\n ? this.config.retry.transient_max\n : PIPELINE_PARSE_MAX_RETRIES;\n\n // Count prior failed transitions for this item+stage\n const failedCount = this.db\n .prepare(\n `SELECT COUNT(*) as cnt FROM stage_transitions\n WHERE work_item_id = ? AND item_type = ? AND stage = ? AND status = 'failed'`,\n )\n .get(itemId, itemType, stage) as { cnt: number };\n\n if (failedCount.cnt >= maxRetries) {\n resolvedStatus = 'poisoned';\n }\n }\n\n // Set started_at for processing, completed_at for terminal states\n const startedAt = status === 'processing' ? now : null;\n const completedAt = ['succeeded', 'failed', 'poisoned', 'blocked', 'skipped'].includes(resolvedStatus) ? now : null;\n const outputJson = status === 'succeeded' && output ? JSON.stringify(output) : null;\n\n this.db\n .prepare(\n `INSERT INTO stage_transitions\n (work_item_id, item_type, stage, status, attempt, error_type, error_message, started_at, completed_at, output, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n itemId,\n itemType,\n stage,\n resolvedStatus,\n attempt,\n error?.errorType ?? null,\n error?.errorMessage ?? null,\n startedAt,\n completedAt,\n outputJson,\n now,\n );\n\n // Update work_items.updated_at\n this.db\n .prepare('UPDATE work_items SET updated_at = ? WHERE id = ? AND item_type = ?')\n .run(now, itemId, itemType);\n\n // Block downstream stages when error_type is 'config'\n if (status === 'failed' && error?.errorType === 'config') {\n const stageIdx = PIPELINE_STAGES.indexOf(stage as PipelineStage);\n if (stageIdx >= 0) {\n const downstreamStages = PIPELINE_STAGES.slice(stageIdx + 1);\n for (const downstream of downstreamStages) {\n // Only block stages that are currently pending (not already skipped)\n const currentStatus = this.db\n .prepare(\n `SELECT status FROM stage_transitions\n WHERE work_item_id = ? AND item_type = ? AND stage = ?\n ORDER BY id DESC LIMIT 1`,\n )\n .get(itemId, itemType, downstream) as { status: string } | undefined;\n\n if (currentStatus && currentStatus.status === 'pending') {\n this.db\n .prepare(\n `INSERT INTO stage_transitions\n (work_item_id, item_type, stage, status, attempt, error_type, error_message, started_at, completed_at, created_at)\n VALUES (?, ?, ?, 'blocked', 1, 'config', ?, NULL, ?, ?)`,\n )\n .run(\n itemId,\n itemType,\n downstream,\n `blocked by ${stage} config failure`,\n now,\n now,\n );\n }\n }\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Status queries\n // -------------------------------------------------------------------------\n\n /**\n * Get current status for all stages of a work item.\n * Queries the pipeline_status view filtered by work_item_id and item_type.\n */\n getItemStatus(itemId: string, itemType: string): StageStatus[] {\n return this.db\n .prepare(\n `SELECT stage, status, attempt, error_type, error_message, started_at, completed_at, output\n FROM pipeline_status\n WHERE id = ? AND item_type = ?`,\n )\n .all(itemId, itemType) as StageStatus[];\n }\n\n // -------------------------------------------------------------------------\n // Batch queries\n // -------------------------------------------------------------------------\n\n /**\n * Get pending work items ready for processing at a given stage.\n *\n * Requirements:\n * - Only items where the requested stage is 'pending'\n * - Only items whose PREVIOUS stage (in PIPELINE_STAGES order) is 'succeeded' or 'skipped'\n * - Exclude items in backoff window\n * - Ordered by work_items.created_at ASC (oldest first)\n */\n nextBatch(stage: string, limit: number): BatchItem[] {\n const stageIdx = PIPELINE_STAGES.indexOf(stage as PipelineStage);\n const prevStage = stageIdx > 0 ? PIPELINE_STAGES[stageIdx - 1] : null;\n\n // Upstream check is conditional: first stage has no upstream requirement\n const upstreamCheck = prevStage\n ? `AND EXISTS (\n SELECT 1 FROM pipeline_status ps2\n WHERE ps2.id = ps.id AND ps2.item_type = ps.item_type\n AND ps2.stage = ? AND ps2.status IN ('succeeded', 'skipped')\n )`\n : '';\n\n // Pick up 'pending' items AND 'failed' items eligible for retry (backoff elapsed, under retry limit).\n // The pipeline_status view shows the latest transition status — failed items stay failed\n // until they're either retried (new pending transition) or poisoned (max retries exceeded).\n const sql = `\n SELECT ps.id, ps.item_type, ps.source_path, wi.created_at\n FROM pipeline_status ps\n JOIN work_items wi ON wi.id = ps.id AND wi.item_type = ps.item_type\n WHERE ps.stage = ? AND ps.status IN ('pending', 'failed')\n ${upstreamCheck}\n AND NOT EXISTS (\n SELECT 1 FROM stage_transitions st2\n WHERE st2.work_item_id = ps.id AND st2.item_type = ps.item_type\n AND st2.stage = ? AND st2.status = 'failed'\n AND st2.completed_at IS NOT NULL\n AND (julianday('now') - julianday(st2.completed_at)) * 86400000 <\n ? * POWER(?, (\n SELECT COUNT(*) FROM stage_transitions st3\n WHERE st3.work_item_id = ps.id AND st3.item_type = ps.item_type\n AND st3.stage = ? AND st3.status = 'failed'\n ) - 1)\n )\n ORDER BY wi.created_at ASC\n LIMIT ?`;\n\n const params: unknown[] = [stage];\n if (prevStage) {\n params.push(prevStage);\n }\n params.push(stage, this.config.retry.backoff_base_seconds * 1000, PIPELINE_BACKOFF_MULTIPLIER, stage, limit);\n\n return this.db.prepare(sql).all(...params) as BatchItem[];\n }\n\n // -------------------------------------------------------------------------\n // Circuit breakers\n // -------------------------------------------------------------------------\n\n /**\n * Get current state of a circuit breaker for the given provider role.\n * Returns the persisted row, or a synthetic default (closed, 0 failures)\n * if no row exists yet.\n */\n circuitState(providerRole: string): CircuitState {\n const row = this.db\n .prepare('SELECT * FROM circuit_breakers WHERE provider_role = ?')\n .get(providerRole) as CircuitState | undefined;\n\n if (row) {\n return row;\n }\n\n // Return a synthetic default — do not persist until first trip\n return {\n provider_role: providerRole,\n state: 'closed',\n failure_count: 0,\n last_failure: null,\n last_error: null,\n opens_at: null,\n updated_at: new Date().toISOString(),\n };\n }\n\n /**\n * Record a failure against a circuit breaker. Increments failure_count and\n * updates last_error / last_failure. If failure_count reaches the configured\n * failure_threshold, sets state to 'open' and calculates\n * opens_at = now + configured cooldown_seconds.\n */\n tripCircuit(providerRole: string, errorMessage: string): void {\n const now = new Date().toISOString();\n const current = this.circuitState(providerRole);\n const newFailureCount = current.failure_count + 1;\n\n const shouldOpen = newFailureCount >= this.config.circuit_breaker.failure_threshold;\n const newState = shouldOpen ? 'open' : 'closed';\n const opensAt = shouldOpen\n ? new Date(Date.now() + this.config.circuit_breaker.cooldown_seconds * 1000).toISOString()\n : null;\n\n this.db\n .prepare(\n `INSERT INTO circuit_breakers\n (provider_role, state, failure_count, last_failure, last_error, opens_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(provider_role) DO UPDATE SET\n state = excluded.state,\n failure_count = excluded.failure_count,\n last_failure = excluded.last_failure,\n last_error = excluded.last_error,\n opens_at = excluded.opens_at,\n updated_at = excluded.updated_at`,\n )\n .run(providerRole, newState, newFailureCount, now, errorMessage, opensAt, now);\n }\n\n /**\n * Re-open a circuit after a failed half-open probe with doubled cooldown.\n *\n * When a half-open probe fails, the circuit should re-open with a cooldown\n * of `previousCooldown * 2`, capped at the configured max_cooldown_seconds.\n * This implements exponential backoff for repeated probe failures.\n */\n reopenCircuit(providerRole: string, errorMessage: string): void {\n const now = new Date().toISOString();\n const current = this.circuitState(providerRole);\n\n // Calculate doubled cooldown from the previous opens_at window.\n // If we can determine the previous cooldown from the stored opens_at and last_failure,\n // double it. Otherwise fall back to the default cooldown.\n let previousCooldown = this.config.circuit_breaker.cooldown_seconds * 1000;\n if (current.last_failure && current.opens_at) {\n const lastFailureMs = new Date(current.last_failure).getTime();\n const opensAtMs = new Date(current.opens_at).getTime();\n const storedCooldown = opensAtMs - lastFailureMs;\n if (storedCooldown > 0) {\n previousCooldown = storedCooldown;\n }\n }\n\n const doubledCooldown = Math.min(\n previousCooldown * 2,\n this.config.circuit_breaker.max_cooldown_seconds * 1000,\n );\n\n const opensAt = new Date(Date.now() + doubledCooldown).toISOString();\n\n this.db\n .prepare(\n `INSERT INTO circuit_breakers\n (provider_role, state, failure_count, last_failure, last_error, opens_at, updated_at)\n VALUES (?, 'open', ?, ?, ?, ?, ?)\n ON CONFLICT(provider_role) DO UPDATE SET\n state = 'open',\n failure_count = excluded.failure_count,\n last_failure = excluded.last_failure,\n last_error = excluded.last_error,\n opens_at = excluded.opens_at,\n updated_at = excluded.updated_at`,\n )\n .run(providerRole, current.failure_count + 1, now, errorMessage, opensAt, now);\n }\n\n /**\n * Manually reset a circuit breaker to closed state.\n * Sets state='closed', failure_count=0, clears opens_at.\n */\n resetCircuit(providerRole: string): void {\n const now = new Date().toISOString();\n\n this.db\n .prepare(\n `INSERT INTO circuit_breakers\n (provider_role, state, failure_count, last_failure, last_error, opens_at, updated_at)\n VALUES (?, 'closed', 0, NULL, NULL, NULL, ?)\n ON CONFLICT(provider_role) DO UPDATE SET\n state = 'closed',\n failure_count = 0,\n opens_at = NULL,\n updated_at = excluded.updated_at`,\n )\n .run(providerRole, now);\n }\n\n /**\n * Check if an open circuit's cooldown has expired and is ready for a\n * half-open probe. If state is 'open' and current time >= opens_at,\n * transitions state to 'half-open' and returns true. Otherwise returns false.\n */\n probeCircuit(providerRole: string): boolean {\n const current = this.circuitState(providerRole);\n\n if (current.state !== 'open') {\n return false;\n }\n\n if (!current.opens_at) {\n return false;\n }\n\n const now = Date.now();\n const opensAt = new Date(current.opens_at).getTime();\n\n if (now < opensAt) {\n return false;\n }\n\n // Cooldown has expired — transition to half-open\n this.db\n .prepare(\n `UPDATE circuit_breakers\n SET state = 'half-open', updated_at = ?\n WHERE provider_role = ?`,\n )\n .run(new Date().toISOString(), providerRole);\n\n return true;\n }\n\n /**\n * When a circuit opens, find all stages that use this provider role and\n * insert new 'blocked' transitions for all items that currently have\n * 'pending' status at those stages.\n *\n * Returns the count of blocked items.\n */\n blockItemsForCircuit(providerRole: string): number {\n return this._transitionItemsForCircuit(providerRole, 'pending', 'blocked');\n }\n\n /**\n * When a circuit closes, find all stages that use this provider role and\n * insert new 'pending' transitions for all items that currently have\n * 'blocked' status at those stages.\n *\n * Returns the count of unblocked items.\n */\n unblockItemsForCircuit(providerRole: string): number {\n return this._transitionItemsForCircuit(providerRole, 'blocked', 'pending');\n }\n\n /**\n * Shared implementation for blockItemsForCircuit / unblockItemsForCircuit.\n * Finds all stages mapped to providerRole, selects items at fromStatus,\n * and inserts a new transition at toStatus.\n */\n private _transitionItemsForCircuit(\n providerRole: string,\n fromStatus: string,\n toStatus: string,\n ): number {\n const affectedStages = (Object.keys(STAGE_PROVIDER_MAP) as Array<keyof typeof STAGE_PROVIDER_MAP>)\n .filter((stage) => STAGE_PROVIDER_MAP[stage] === providerRole);\n\n if (affectedStages.length === 0) {\n return 0;\n }\n\n const now = new Date().toISOString();\n let transitionedCount = 0;\n\n // Blocking transitions include error context; unblocking transitions are clean\n const isBlocking = toStatus === 'blocked';\n\n const doTransition = this.db.transaction(() => {\n for (const stage of affectedStages) {\n const items = this.db\n .prepare(\n `SELECT id, item_type FROM pipeline_status\n WHERE stage = ? AND status = ?`,\n )\n .all(stage, fromStatus) as Array<{ id: string; item_type: string }>;\n\n for (const item of items) {\n if (isBlocking) {\n this.db\n .prepare(\n `INSERT INTO stage_transitions\n (work_item_id, item_type, stage, status, attempt, error_type, error_message, started_at, completed_at, created_at)\n VALUES (?, ?, ?, 'blocked', 1, 'config', ?, NULL, ?, ?)`,\n )\n .run(item.id, item.item_type, stage, `circuit open: ${providerRole}`, now, now);\n } else {\n this.db\n .prepare(\n `INSERT INTO stage_transitions\n (work_item_id, item_type, stage, status, attempt, error_type, error_message, started_at, completed_at, created_at)\n VALUES (?, ?, ?, 'pending', 1, NULL, NULL, NULL, NULL, ?)`,\n )\n .run(item.id, item.item_type, stage, now);\n }\n\n transitionedCount++;\n }\n }\n });\n\n doTransition();\n return transitionedCount;\n }\n\n // -------------------------------------------------------------------------\n // Compaction\n // -------------------------------------------------------------------------\n\n /**\n * Compact stage_transitions older than retentionDays into stage_history rows.\n *\n * For each (work_item_id, item_type, stage) group whose transitions are older\n * than the cutoff, inserts or replaces a stage_history row aggregating those\n * transitions, then deletes the original rows.\n *\n * Returns `{ compacted, deleted }`: compacted = number of groups written to\n * stage_history; deleted = number of transition rows removed.\n */\n compact(retentionDays: number = this.config.retention_days): { compacted: number; deleted: number } {\n const cutoff = new Date(Date.now() - retentionDays * MS_PER_DAY).toISOString();\n\n // Find all old transition rows, grouped by (work_item_id, item_type, stage).\n // We need the aggregate values per group as well as every individual error_type\n // so we can build the error_types JSON. Fetch the raw rows and aggregate in JS.\n const oldRows = this.db\n .prepare(\n `SELECT id, work_item_id, item_type, stage, status, attempt, error_type, output, created_at\n FROM stage_transitions\n WHERE created_at < ?\n ORDER BY id ASC`,\n )\n .all(cutoff) as Array<{\n id: number;\n work_item_id: string;\n item_type: string;\n stage: string;\n status: string;\n attempt: number;\n error_type: string | null;\n output: string | null;\n created_at: string;\n }>;\n\n if (oldRows.length === 0) {\n return { compacted: 0, deleted: 0 };\n }\n\n // Group rows by (work_item_id, item_type, stage)\n const groups = new Map<\n string,\n {\n work_item_id: string;\n item_type: string;\n stage: string;\n rows: typeof oldRows;\n }\n >();\n\n for (const row of oldRows) {\n const key = `${row.work_item_id}\\0${row.item_type}\\0${row.stage}`;\n const existing = groups.get(key);\n if (existing) {\n existing.rows.push(row);\n } else {\n groups.set(key, { work_item_id: row.work_item_id, item_type: row.item_type, stage: row.stage, rows: [row] });\n }\n }\n\n const upsertHistory = this.db.prepare(\n `INSERT OR REPLACE INTO stage_history\n (work_item_id, item_type, stage, total_attempts, final_status, first_attempt, last_attempt, last_error, error_types, last_output)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n );\n\n const deleteTransitions = this.db.prepare(\n 'DELETE FROM stage_transitions WHERE work_item_id = ? AND item_type = ? AND stage = ? AND created_at < ?',\n );\n\n let compacted = 0;\n let deleted = 0;\n\n const doCompact = this.db.transaction(() => {\n for (const group of groups.values()) {\n // Rows are ordered by id ASC; the last row is the latest\n const latestRow = group.rows[group.rows.length - 1];\n const earliestRow = group.rows[0];\n\n // Count error_types\n const errorTypeCounts: Record<string, number> = {};\n for (const row of group.rows) {\n if (row.error_type) {\n errorTypeCounts[row.error_type] = (errorTypeCounts[row.error_type] ?? 0) + 1;\n }\n }\n\n // Fetch last_error for the latest transition in the group\n const lastErrorRow = this.db\n .prepare(\n `SELECT error_message FROM stage_transitions\n WHERE work_item_id = ? AND item_type = ? AND stage = ?\n ORDER BY id DESC LIMIT 1`,\n )\n .get(group.work_item_id, group.item_type, group.stage) as { error_message: string | null } | undefined;\n\n // Find the last succeeded transition's output for compaction\n const lastSucceeded = group.rows.filter((r) => r.status === 'succeeded').pop();\n const lastOutput = lastSucceeded?.output ?? null;\n\n upsertHistory.run(\n group.work_item_id,\n group.item_type,\n group.stage,\n group.rows.length,\n latestRow.status,\n earliestRow.created_at,\n latestRow.created_at,\n lastErrorRow?.error_message ?? null,\n JSON.stringify(errorTypeCounts),\n lastOutput,\n );\n\n const deleteResult = deleteTransitions.run(\n group.work_item_id,\n group.item_type,\n group.stage,\n cutoff,\n );\n\n compacted++;\n deleted += deleteResult.changes;\n }\n });\n\n doCompact();\n return { compacted, deleted };\n }\n\n // -------------------------------------------------------------------------\n // Recovery\n // -------------------------------------------------------------------------\n\n /**\n * Recover stuck items on daemon startup.\n *\n * Finds all items currently in 'processing' status (via the pipeline_status view)\n * and inserts a new 'pending' transition for each, effectively resetting them\n * for reprocessing.\n *\n * Returns the count of recovered items.\n */\n recoverStuck(): number {\n const now = new Date().toISOString();\n\n // Find all item/stage pairs currently stuck in 'processing'\n const stuckItems = this.db\n .prepare(\n `SELECT id, item_type, stage FROM pipeline_status WHERE status = 'processing'`,\n )\n .all() as Array<{ id: string; item_type: string; stage: string }>;\n\n if (stuckItems.length === 0) {\n return 0;\n }\n\n const insertPending = this.db.prepare(\n `INSERT INTO stage_transitions\n (work_item_id, item_type, stage, status, attempt, error_type, error_message, started_at, completed_at, created_at)\n VALUES (?, ?, ?, 'pending', 1, NULL, NULL, NULL, NULL, ?)`,\n );\n\n const doRecover = this.db.transaction(() => {\n for (const item of stuckItems) {\n insertPending.run(item.id, item.item_type, item.stage, now);\n }\n });\n\n doRecover();\n return stuckItems.length;\n }\n\n // -------------------------------------------------------------------------\n // API query helpers\n // -------------------------------------------------------------------------\n\n /**\n * List work items from the pipeline_status view with optional filters and pagination.\n *\n * Filters: stage, status, item_type. All optional.\n * Returns rows ordered by work_items.created_at DESC (newest first).\n */\n listItems(filters: {\n stage?: string;\n status?: string;\n type?: string;\n limit?: number;\n offset?: number;\n }): { items: PipelineItem[]; total: number } {\n const conditions: string[] = [];\n const params: unknown[] = [];\n\n if (filters.stage) {\n conditions.push('ps.stage = ?');\n params.push(filters.stage);\n }\n if (filters.status) {\n conditions.push('ps.status = ?');\n params.push(filters.status);\n }\n if (filters.type) {\n conditions.push('ps.item_type = ?');\n params.push(filters.type);\n }\n\n const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';\n\n const countSql = `SELECT COUNT(*) as total FROM pipeline_status ps ${where}`;\n const countRow = this.db.prepare(countSql).get(...params) as { total: number };\n\n const limit = filters.limit ?? PIPELINE_ITEMS_DEFAULT_LIMIT;\n const offset = filters.offset ?? 0;\n\n const querySql = `\n SELECT ps.id, ps.item_type, ps.source_path, ps.stage, ps.status,\n ps.attempt, ps.error_type, ps.error_message, ps.started_at, ps.completed_at\n FROM pipeline_status ps\n JOIN work_items wi ON wi.id = ps.id AND wi.item_type = ps.item_type\n ${where}\n ORDER BY wi.created_at DESC\n LIMIT ? OFFSET ?\n `;\n\n const items = this.db.prepare(querySql).all(...params, limit, offset) as PipelineItem[];\n\n return { items, total: countRow.total };\n }\n\n /**\n * Get the full transition history for a single work item.\n * Returns all stage_transitions rows ordered by id ASC (oldest first).\n */\n getTransitionHistory(itemId: string, itemType: string): TransitionRecord[] {\n return this.db\n .prepare(\n `SELECT id, work_item_id, item_type, stage, status, attempt,\n error_type, error_message, started_at, completed_at, output, created_at\n FROM stage_transitions\n WHERE work_item_id = ? AND item_type = ?\n ORDER BY id ASC`,\n )\n .all(itemId, itemType) as TransitionRecord[];\n }\n\n /**\n * Retry a single poisoned work item by inserting a new 'pending' transition\n * at the specified stage. Returns true if the item was poisoned and retried,\n * false if the item was not found or not poisoned at that stage.\n */\n retryItem(itemId: string, itemType: string, stage: string): boolean {\n // Verify the item is actually poisoned at this stage\n const current = this.db\n .prepare(\n `SELECT status FROM pipeline_status\n WHERE id = ? AND item_type = ? AND stage = ?`,\n )\n .get(itemId, itemType, stage) as { status: string } | undefined;\n\n if (!current || current.status !== 'poisoned') {\n return false;\n }\n\n const now = new Date().toISOString();\n this.db\n .prepare(\n `INSERT INTO stage_transitions\n (work_item_id, item_type, stage, status, attempt, error_type, error_message, started_at, completed_at, created_at)\n VALUES (?, ?, ?, 'pending', 1, NULL, NULL, NULL, NULL, ?)`,\n )\n .run(itemId, itemType, stage, now);\n\n return true;\n }\n\n /**\n * Skip a poisoned or failed work item at the specified stage.\n * Inserts a 'skipped' transition so the item no longer counts as an error.\n * Returns true if the item was in an error state and was skipped.\n */\n skipItem(itemId: string, itemType: string, stage: string): boolean {\n const current = this.db\n .prepare(\n `SELECT status FROM pipeline_status\n WHERE id = ? AND item_type = ? AND stage = ?`,\n )\n .get(itemId, itemType, stage) as { status: string } | undefined;\n\n if (!current || (current.status !== 'poisoned' && current.status !== 'failed')) {\n return false;\n }\n\n const now = new Date().toISOString();\n this.db\n .prepare(\n `INSERT INTO stage_transitions\n (work_item_id, item_type, stage, status, attempt, error_type, error_message, started_at, completed_at, created_at)\n VALUES (?, ?, ?, 'skipped', 1, NULL, NULL, NULL, ?, ?)`,\n )\n .run(itemId, itemType, stage, now, now);\n\n return true;\n }\n\n /**\n * Retry all poisoned items by inserting new 'pending' transitions.\n * Returns the count of items retried.\n */\n retryAllPoisoned(): number {\n const poisonedItems = this.db\n .prepare(\n `SELECT id, item_type, stage FROM pipeline_status WHERE status = 'poisoned'`,\n )\n .all() as Array<{ id: string; item_type: string; stage: string }>;\n\n if (poisonedItems.length === 0) {\n return 0;\n }\n\n const now = new Date().toISOString();\n const insertPending = this.db.prepare(\n `INSERT INTO stage_transitions\n (work_item_id, item_type, stage, status, attempt, error_type, error_message, started_at, completed_at, created_at)\n VALUES (?, ?, ?, 'pending', 1, NULL, NULL, NULL, NULL, ?)`,\n );\n\n const doRetry = this.db.transaction(() => {\n for (const item of poisonedItems) {\n insertPending.run(item.id, item.item_type, item.stage, now);\n }\n });\n\n doRetry();\n return poisonedItems.length;\n }\n\n /**\n * List all circuit breaker rows from the database.\n */\n listCircuits(): CircuitState[] {\n return this.db\n .prepare('SELECT * FROM circuit_breakers ORDER BY provider_role ASC')\n .all() as CircuitState[];\n }\n\n // -------------------------------------------------------------------------\n // Tick processing\n // -------------------------------------------------------------------------\n\n private handlers: StageHandlers | null = null;\n private tickInProgress = false;\n private tickLogger: TickLogger | null = null;\n\n /** Register stage handlers called by tick(). Must be set before tick() is useful. */\n setHandlers(handlers: StageHandlers): void {\n this.handlers = handlers;\n }\n\n /** Set a logger for tick diagnostics. */\n setLogger(logger: TickLogger): void {\n this.tickLogger = logger;\n }\n\n /**\n * Process one tick of the pipeline: for each tick-processable stage\n * (extraction, embedding, consolidation), fetch a batch of pending items\n * and run the corresponding handler.\n *\n * Stages are processed sequentially; items within a batch run concurrently.\n *\n * Guarded by tickInProgress — if a tick is already running, returns immediately.\n */\n async tick(batchSize: number): Promise<void> {\n if (this.tickInProgress) {\n return;\n }\n\n if (!this.handlers) {\n return;\n }\n\n this.tickInProgress = true;\n try {\n for (const stage of PIPELINE_TICK_STAGES) {\n const providerRole = STAGE_PROVIDER_MAP[stage];\n\n // Check circuit breaker state for this stage's provider\n if (providerRole) {\n const circuit = this.circuitState(providerRole);\n\n if (circuit.state === 'open') {\n // Check if cooldown expired — allow a half-open probe\n const canProbe = this.probeCircuit(providerRole);\n if (!canProbe) {\n // Circuit still open, ensure items are blocked\n const blocked = this.blockItemsForCircuit(providerRole);\n if (blocked > 0) {\n this.tickLogger?.('debug', 'pipeline', `Circuit open for ${providerRole}, blocked ${blocked} items`, { stage, providerRole });\n }\n continue;\n }\n // Half-open: fall through to process one item as probe\n this.tickLogger?.('debug', 'pipeline', `Circuit half-open probe for ${providerRole}`, { stage, providerRole });\n }\n }\n\n const batch = this.nextBatch(stage, batchSize);\n if (batch.length === 0) {\n continue;\n }\n\n const handler = this.handlers[stage as keyof StageHandlers];\n if (!handler) {\n continue;\n }\n\n // Process batch items concurrently\n await Promise.all(\n batch.map(async (item) => {\n // Advance to processing\n this.advance(item.id, item.item_type, stage, 'processing');\n\n try {\n const output = await handler(item.id, item.item_type, item.source_path);\n // Handler succeeded\n this.advance(item.id, item.item_type, stage, 'succeeded', undefined, output ?? undefined);\n\n // If circuit was half-open and probe succeeded, reset it\n if (providerRole) {\n const circuitAfter = this.circuitState(providerRole);\n if (circuitAfter.state === 'half-open') {\n this.resetCircuit(providerRole);\n const unblocked = this.unblockItemsForCircuit(providerRole);\n this.tickLogger?.('info', 'pipeline', `Circuit closed after successful probe, unblocked ${unblocked} items`, { stage, providerRole });\n }\n }\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n const classified = classifyError(error);\n\n this.advance(item.id, item.item_type, stage, 'failed', {\n errorType: classified.type,\n errorMessage: error.message,\n });\n\n this.tickLogger?.('warn', 'pipeline', `Stage handler failed: ${stage}`, {\n itemId: item.id,\n itemType: item.item_type,\n errorType: classified.type,\n error: error.message,\n });\n\n // Trip circuit breaker on config errors\n if (classified.type === 'config' && providerRole) {\n const circuitBefore = this.circuitState(providerRole);\n\n if (circuitBefore.state === 'half-open') {\n // Half-open probe failed — re-open with doubled cooldown\n this.reopenCircuit(providerRole, error.message);\n const blocked = this.blockItemsForCircuit(providerRole);\n this.tickLogger?.('warn', 'pipeline', `Half-open probe failed for ${providerRole}, re-opened with doubled cooldown, blocked ${blocked} items`, { stage, providerRole });\n } else {\n this.tripCircuit(providerRole, error.message);\n const circuitAfter = this.circuitState(providerRole);\n if (circuitAfter.state === 'open') {\n const blocked = this.blockItemsForCircuit(providerRole);\n this.tickLogger?.('warn', 'pipeline', `Circuit opened for ${providerRole}, blocked ${blocked} items`, { stage, providerRole });\n }\n }\n }\n }\n }),\n );\n }\n } finally {\n this.tickInProgress = false;\n }\n }\n\n // -------------------------------------------------------------------------\n // Digest gating helpers\n // -------------------------------------------------------------------------\n\n /**\n * Check if any upstream stages (extraction, embedding, consolidation) have\n * active work items (pending, processing, or blocked — but not failed/poisoned).\n *\n * Used to gate the digest engine: digest should not run while upstream\n * stages still have work in flight.\n */\n hasUpstreamWork(): boolean {\n // Check 1: any item actively being processed at upstream stages\n const active = this.db\n .prepare(\n `SELECT COUNT(*) as cnt FROM pipeline_status\n WHERE stage IN ('extraction', 'embedding', 'consolidation')\n AND status IN ('pending', 'processing', 'blocked')`,\n )\n .get() as { cnt: number };\n if (active.cnt > 0) return true;\n\n // Check 2: any item with digest:pending where a prior stage is still\n // non-terminal (e.g., embedding:processing → not yet at consolidation).\n // Without this, digest runs while items are mid-pipeline.\n const midPipeline = this.db\n .prepare(\n `SELECT COUNT(*) as cnt FROM pipeline_status ps1\n WHERE ps1.stage = 'digest' AND ps1.status = 'pending'\n AND EXISTS (\n SELECT 1 FROM pipeline_status ps2\n WHERE ps2.id = ps1.id AND ps2.item_type = ps1.item_type\n AND ps2.stage != 'digest'\n AND ps2.status NOT IN ('succeeded', 'skipped', 'failed', 'poisoned')\n )`,\n )\n .get() as { cnt: number };\n return midPipeline.cnt > 0;\n }\n\n /**\n * Count items at digest:pending where ALL other stages for that item\n * are in a terminal state (succeeded, skipped, failed, or poisoned).\n *\n * Used to gate digest: only run when enough processed substrate has accumulated.\n */\n newSubstrateSinceLastDigest(): number {\n const result = this.db\n .prepare(\n `SELECT COUNT(*) as cnt FROM pipeline_status ps1\n WHERE ps1.stage = 'digest' AND ps1.status = 'pending'\n AND NOT EXISTS (\n SELECT 1 FROM pipeline_status ps2\n WHERE ps2.id = ps1.id AND ps2.item_type = ps1.item_type\n AND ps2.stage != 'digest'\n AND ps2.status NOT IN ('succeeded', 'skipped', 'failed', 'poisoned')\n )`,\n )\n .get() as { cnt: number };\n return result.cnt;\n }\n\n /**\n * Mark all digest:pending items as digest:succeeded after a successful cycle.\n * Returns the number of items advanced.\n */\n advanceDigestItems(output?: Record<string, unknown>): number {\n const items = this.db\n .prepare(\n `SELECT id, item_type FROM pipeline_status\n WHERE stage = 'digest' AND status = 'pending'`,\n )\n .all() as Array<{ id: string; item_type: string }>;\n\n const advanceAll = this.db.transaction(() => {\n for (const item of items) {\n this.advance(item.id, item.item_type, 'digest', 'succeeded', undefined, output);\n }\n });\n advanceAll();\n return items.length;\n }\n\n // -------------------------------------------------------------------------\n // Rebuild from vault\n // -------------------------------------------------------------------------\n\n /**\n * Walk the vault and infer pipeline stage completion from existing data.\n *\n * Used for first-run migration: when pipeline.db is empty but the vault\n * already has session, spore, and artifact files from prior processing.\n *\n * Algorithm:\n * 1. Walk sessions/, spores/, artifacts/ directories for .md files\n * 2. Register each as a work item with inferred stage statuses\n * 3. Check vector index for embedding status\n * 4. Check digest trace for digest status\n * 5. Infer extraction status for sessions (check if spores reference them)\n * 6. Mark spore consolidation as pending (cannot reliably infer)\n */\n rebuild(\n vaultDir: string,\n vectorIndex: VectorHasCheck | null,\n digestTracePath?: string,\n ): RebuildResult {\n const digestedIds = this.loadDigestedIds(digestTracePath);\n const sporeSessionIds = this.collectSporeSessionIds(vaultDir);\n const stages: Record<string, number> = {};\n let registered = 0;\n\n const bumpStage = (key: string): void => {\n stages[key] = (stages[key] ?? 0) + 1;\n };\n\n // Wrap all register() + advance() calls in a single transaction\n // to avoid thousands of individual commits during first-run migration.\n const runRebuild = this.db.transaction(() => {\n // --- Sessions ---\n const sessionsDir = path.join(vaultDir, 'sessions');\n for (const filePath of walkMarkdownFiles(sessionsDir)) {\n const filename = path.basename(filePath, '.md');\n // session-<id>.md → id = everything after \"session-\"\n const itemId = filename.startsWith('session-') ? filename.slice('session-'.length) : filename;\n const relativePath = path.relative(vaultDir, filePath);\n\n this.register(itemId, 'session', relativePath);\n registered++;\n\n // capture: file exists → succeeded\n this.advance(itemId, 'session', 'capture', 'succeeded');\n bumpStage('capture:succeeded');\n\n // extraction: check if any spore references this session\n if (sporeSessionIds.has(itemId) || sporeSessionIds.has(`session-${itemId}`)) {\n this.advance(itemId, 'session', 'extraction', 'succeeded');\n bumpStage('extraction:succeeded');\n } else {\n bumpStage('extraction:pending');\n }\n\n // embedding: check vector index\n if (vectorIndex?.has(itemId) || vectorIndex?.has(`session-${itemId}`)) {\n this.advance(itemId, 'session', 'embedding', 'succeeded');\n bumpStage('embedding:succeeded');\n } else {\n bumpStage('embedding:pending');\n }\n\n // digest: check trace\n if (digestedIds.has(itemId) || digestedIds.has(`session-${itemId}`)) {\n this.advance(itemId, 'session', 'digest', 'succeeded');\n bumpStage('digest:succeeded');\n } else {\n bumpStage('digest:pending');\n }\n }\n\n // --- Spores ---\n const sporesDir = path.join(vaultDir, 'spores');\n for (const filePath of walkMarkdownFiles(sporesDir)) {\n const itemId = path.basename(filePath, '.md');\n const relativePath = path.relative(vaultDir, filePath);\n\n this.register(itemId, 'spore', relativePath);\n registered++;\n\n // capture: file exists → succeeded\n this.advance(itemId, 'spore', 'capture', 'succeeded');\n bumpStage('capture:succeeded');\n\n // embedding: check vector index\n if (vectorIndex?.has(itemId)) {\n this.advance(itemId, 'spore', 'embedding', 'succeeded');\n bumpStage('embedding:succeeded');\n } else {\n bumpStage('embedding:pending');\n }\n\n // consolidation: cannot reliably infer → leave as pending\n bumpStage('consolidation:pending');\n\n // digest: check trace\n if (digestedIds.has(itemId)) {\n this.advance(itemId, 'spore', 'digest', 'succeeded');\n bumpStage('digest:succeeded');\n } else {\n bumpStage('digest:pending');\n }\n }\n\n // --- Artifacts ---\n const artifactsDir = path.join(vaultDir, 'artifacts');\n for (const filePath of walkMarkdownFiles(artifactsDir)) {\n const itemId = path.basename(filePath, '.md');\n const relativePath = path.relative(vaultDir, filePath);\n\n this.register(itemId, 'artifact', relativePath);\n registered++;\n\n // capture: file exists → succeeded\n this.advance(itemId, 'artifact', 'capture', 'succeeded');\n bumpStage('capture:succeeded');\n\n // embedding: check vector index\n if (vectorIndex?.has(itemId)) {\n this.advance(itemId, 'artifact', 'embedding', 'succeeded');\n bumpStage('embedding:succeeded');\n } else {\n bumpStage('embedding:pending');\n }\n\n // digest: check trace\n if (digestedIds.has(itemId)) {\n this.advance(itemId, 'artifact', 'digest', 'succeeded');\n bumpStage('digest:succeeded');\n } else {\n bumpStage('digest:pending');\n }\n }\n });\n runRebuild();\n\n return { registered, stages };\n }\n\n /**\n * Read digest trace JSONL and collect all note IDs that appear in any\n * substrate array. Returns an empty Set if the trace file doesn't exist.\n */\n private loadDigestedIds(tracePath?: string): Set<string> {\n const ids = new Set<string>();\n if (!tracePath) return ids;\n\n let content: string;\n try {\n content = fs.readFileSync(tracePath, 'utf-8').trim();\n } catch {\n return ids;\n }\n\n if (!content) return ids;\n\n for (const line of content.split('\\n')) {\n try {\n const record = JSON.parse(line) as {\n substrate?: {\n sessions?: string[];\n spores?: string[];\n plans?: string[];\n artifacts?: string[];\n team?: string[];\n };\n };\n if (record.substrate) {\n for (const arr of Object.values(record.substrate)) {\n if (Array.isArray(arr)) {\n for (const id of arr) {\n ids.add(id);\n }\n }\n }\n }\n } catch {\n // Skip malformed lines\n }\n }\n\n return ids;\n }\n\n /**\n * Walk spore files and collect session IDs they reference.\n * Used to infer whether extraction has been completed for a session.\n */\n private collectSporeSessionIds(vaultDir: string): Set<string> {\n const sessionIds = new Set<string>();\n const sporesDir = path.join(vaultDir, 'spores');\n\n for (const filePath of walkMarkdownFiles(sporesDir)) {\n try {\n const content = fs.readFileSync(filePath, 'utf-8');\n const fmMatch = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!fmMatch) continue;\n\n // Look for session field in frontmatter\n // Format: session: \"[[session-<id>]]\" or session: \"session-<id>\" or session: \"<id>\"\n const sessionMatch = fmMatch[1].match(/^session:\\s*(?:\"\\[\\[)?([^\"\\]]+)/m);\n if (sessionMatch) {\n const rawSession = sessionMatch[1].trim();\n sessionIds.add(rawSession);\n // Also add bare ID if it has session- prefix\n if (rawSession.startsWith('session-')) {\n sessionIds.add(rawSession.slice('session-'.length));\n }\n }\n } catch {\n // Skip unreadable files\n }\n }\n\n return sessionIds;\n }\n\n\n /** Close the database connection. */\n close(): void {\n this.db.close();\n }\n}\n","/**\n * Error classification for pipeline retry and circuit-breaker decisions.\n *\n * classifyError() inspects an error and returns:\n * - type: 'transient' | 'config' | 'parse'\n * - suggestedAction: human-readable hint for config/parse errors (displayed in dashboard)\n *\n * Priority order (highest to lowest):\n * 1. parse — SyntaxError, name='ParseError', empty content, schema validation\n * 2. config — ECONNREFUSED, 401, 403, model not found/loaded, resource exhaustion\n * 3. config — ENOTFOUND matching configuredHost\n * 4. transient — AbortError, ETIMEDOUT, ECONNRESET, 429, 500, 503, socket hang up\n * 5. transient — ENOTFOUND for well-known API hosts\n * 6. transient — fallback for all unrecognised errors\n */\n\nexport type ErrorType = 'transient' | 'config' | 'parse';\n\nexport interface ClassifyResult {\n type: ErrorType;\n suggestedAction?: string;\n}\n\nexport interface ClassifyContext {\n /** Hostname from the provider's baseUrl — used to distinguish custom vs well-known hosts on ENOTFOUND. */\n configuredHost?: string;\n /** Human-readable name of the provider (e.g. 'LM Studio', 'Anthropic'). */\n providerName?: string;\n /** Model identifier configured for this provider. */\n modelName?: string;\n /** Base URL of the provider (e.g. 'http://localhost:1234'). */\n baseUrl?: string;\n}\n\n/** Well-known API hostnames whose ENOTFOUND errors indicate a transient DNS issue, not misconfiguration. */\nconst WELL_KNOWN_API_HOSTS = ['api.anthropic.com', 'api.openai.com'];\n\n/** HTTP status substrings that indicate a transient server-side issue. */\nconst TRANSIENT_STATUS_PATTERNS = [' 429 ', ' 500 ', ' 503 '];\n\n/** Message substrings that indicate a missing/unloaded model (config). */\nconst MODEL_NOT_FOUND_PATTERNS = [\n 'model not found',\n 'model not loaded',\n 'no model loaded',\n];\n\n/** Message substrings that indicate a resource/load failure (config). */\nconst RESOURCE_FAILURE_PATTERNS = [\n 'model_load_failed',\n 'insufficient system resources',\n 'unsupported',\n 'not compatible',\n];\n\n/** Message substrings that indicate a transient network issue. */\nconst TRANSIENT_MESSAGE_PATTERNS = [\n 'socket hang up',\n];\n\n/** Node.js error codes that map to config errors. */\nconst CONFIG_ERROR_CODES = new Set(['ECONNREFUSED']);\n\n/** Node.js error codes that map to transient errors. */\nconst TRANSIENT_ERROR_CODES = new Set(['ETIMEDOUT', 'ECONNRESET']);\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction hasCode(err: Error, code: string): boolean {\n return (err as NodeJS.ErrnoException).code === code;\n}\n\nfunction hasAnyCode(err: Error, codes: Set<string>): boolean {\n const code = (err as NodeJS.ErrnoException).code;\n return code !== undefined && codes.has(code);\n}\n\nfunction messageContains(err: Error, patterns: string[]): boolean {\n const msg = err.message.toLowerCase();\n return patterns.some((p) => msg.includes(p.toLowerCase()));\n}\n\nfunction statusMatch(err: Error, patterns: string[]): boolean {\n // Match patterns with leading/trailing space to avoid false positives in\n // long numeric strings. Also handle end-of-string (e.g. \"failed: 401\").\n const msg = ' ' + err.message + ' ';\n return patterns.some((p) => msg.includes(p));\n}\n\n// ---------------------------------------------------------------------------\n// Suggested action builders\n// ---------------------------------------------------------------------------\n\nfunction connectionRefusedAction(ctx: ClassifyContext): string {\n const provider = ctx.providerName ?? 'the provider';\n const url = ctx.baseUrl ? ` at ${ctx.baseUrl}` : '';\n return `${provider} is not reachable${url}. Check that ${provider} is running and the baseUrl is correct.`;\n}\n\nfunction modelNotFoundAction(ctx: ClassifyContext): string {\n const model = ctx.modelName ? `'${ctx.modelName}'` : 'the configured model';\n const provider = ctx.providerName ?? 'the provider';\n return `Model ${model} was not found in ${provider}. Ensure the model is downloaded and loaded.`;\n}\n\nfunction resourceExhaustionAction(ctx: ClassifyContext): string {\n const provider = ctx.providerName ?? 'the provider';\n return `${provider} could not load the model due to insufficient resources. Try a smaller model or free up memory.`;\n}\n\nfunction authFailureAction(status: '401' | '403', ctx: ClassifyContext): string {\n const provider = ctx.providerName ?? 'the provider';\n if (status === '401') {\n return `Authentication failed for ${provider}. Check that the API key is set and valid.`;\n }\n return `Access denied (403) for ${provider}. Check API key permissions and account status.`;\n}\n\nfunction dnsFailureAction(ctx: ClassifyContext): string {\n const provider = ctx.providerName ?? 'the provider';\n const host = ctx.configuredHost ?? 'the configured host';\n return `Cannot resolve host '${host}' for ${provider}. Check the baseUrl hostname.`;\n}\n\n// ---------------------------------------------------------------------------\n// Main classifier\n// ---------------------------------------------------------------------------\n\nexport function classifyError(error: Error, context?: ClassifyContext): ClassifyResult {\n const ctx = context ?? {};\n\n // 1. Parse errors — structural/LLM output issues\n if (error instanceof SyntaxError) {\n return { type: 'parse', suggestedAction: 'LLM returned unparseable JSON. The response may be malformed or truncated.' };\n }\n if (error.name === 'ParseError') {\n return { type: 'parse', suggestedAction: 'LLM returned an empty or invalid response. Check model health and prompt.' };\n }\n const msgLower = error.message.toLowerCase();\n if (msgLower.includes('empty content') || msgLower.includes('schema validation')) {\n return { type: 'parse', suggestedAction: 'LLM returned an empty or schema-invalid response. Check model health and prompt.' };\n }\n // Reasoning-only response: after stripping <think> tags the response is empty\n if (msgLower.includes('only reasoning') || msgLower.includes('empty after strip') || msgLower.includes('observation extraction failed')) {\n return { type: 'parse', suggestedAction: 'LLM returned only reasoning tokens with no usable content. Check model reasoning settings.' };\n }\n // Missing expected fields in LLM/embedding response\n if (msgLower.includes('missing output') || msgLower.includes('no content in response') || msgLower.includes('summarization failed')) {\n return { type: 'parse', suggestedAction: 'LLM response is missing expected fields. Check provider health and model compatibility.' };\n }\n\n // 2. Config errors — connection refused\n if (hasCode(error, 'ECONNREFUSED') || hasAnyCode(error, CONFIG_ERROR_CODES)) {\n return { type: 'config', suggestedAction: connectionRefusedAction(ctx) };\n }\n\n // 3. Config errors — model not found / not loaded\n if (messageContains(error, MODEL_NOT_FOUND_PATTERNS)) {\n return { type: 'config', suggestedAction: modelNotFoundAction(ctx) };\n }\n\n // 4. Config errors — resource exhaustion / load failure\n if (messageContains(error, RESOURCE_FAILURE_PATTERNS)) {\n return { type: 'config', suggestedAction: resourceExhaustionAction(ctx) };\n }\n\n // 5. Config errors — auth failures (401, 403)\n if (statusMatch(error, [' 401 '])) {\n return { type: 'config', suggestedAction: authFailureAction('401', ctx) };\n }\n if (statusMatch(error, [' 403 '])) {\n return { type: 'config', suggestedAction: authFailureAction('403', ctx) };\n }\n // Also handle message ending with status code (e.g. \"failed: 401\")\n if (/ 401$/.test(error.message) || error.message.endsWith(' 401')) {\n return { type: 'config', suggestedAction: authFailureAction('401', ctx) };\n }\n if (/ 403$/.test(error.message) || error.message.endsWith(' 403')) {\n return { type: 'config', suggestedAction: authFailureAction('403', ctx) };\n }\n\n // 6. ENOTFOUND — distinguish config vs transient by hostname\n if (hasCode(error, 'ENOTFOUND')) {\n // If a configuredHost was provided and appears in the message, it's misconfiguration\n if (ctx.configuredHost && error.message.includes(ctx.configuredHost)) {\n return { type: 'config', suggestedAction: dnsFailureAction(ctx) };\n }\n // If the message contains a well-known API host, treat as transient DNS blip\n if (WELL_KNOWN_API_HOSTS.some((host) => error.message.includes(host))) {\n return { type: 'transient' };\n }\n // Unknown host with no configuredHost context — treat as config\n return { type: 'config', suggestedAction: dnsFailureAction(ctx) };\n }\n\n // 7. Transient errors — AbortError / timeout\n if (error.name === 'AbortError') {\n return { type: 'transient' };\n }\n if (hasAnyCode(error, TRANSIENT_ERROR_CODES)) {\n return { type: 'transient' };\n }\n\n // 8. Transient errors — rate limit / server error status codes\n if (statusMatch(error, TRANSIENT_STATUS_PATTERNS)) {\n return { type: 'transient' };\n }\n\n // 9. Transient errors — message patterns\n if (messageContains(error, TRANSIENT_MESSAGE_PATTERNS)) {\n return { type: 'transient' };\n }\n\n // 10. Default: transient (unknown errors are assumed recoverable)\n return { type: 'transient' };\n}\n","import { DaemonServer } from './server.js';\nimport { SessionRegistry } from './lifecycle.js';\nimport { DaemonLogger } from './logger.js';\nimport { loadConfig, saveConfig } from '../config/loader.js';\nimport { BatchManager, type BatchEvent } from './batch.js';\nimport { BufferProcessor, SUMMARIZATION_FAILED_MARKER, type Observation, type ClassifiedArtifact } from './processor.js';\nimport { VaultWriter } from '../vault/writer.js';\nimport { MycoIndex } from '../index/sqlite.js';\nimport { indexNote, rebuildIndex } from '../index/rebuild.js';\nimport { initFts } from '../index/fts.js';\nimport { createLlmProvider, createEmbeddingProvider } from '../intelligence/llm.js';\nimport type { EmbeddingProvider, LlmProvider } from '../intelligence/llm.js';\nimport { VectorIndex } from '../index/vectors.js';\nimport { generateEmbedding } from '../intelligence/embeddings.js';\nimport { LineageGraph } from './lineage.js';\nimport type { RegisteredSession } from './lifecycle.js';\nimport { PlanWatcher } from './watcher.js';\nimport { DigestEngine, Metabolism } from './digest.js';\nimport { ConsolidationEngine } from './consolidation.js';\nimport { resolvePort } from './port.js';\nimport { handleMycoContext } from '../mcp/tools/context.js';\nimport { EMBEDDING_INPUT_LIMIT, CONTENT_SNIPPET_CHARS, STALE_BUFFER_MAX_AGE_MS, LINEAGE_RECENT_SESSIONS_LIMIT, RELATED_SPORES_LIMIT, SESSION_CONTEXT_MAX_PLANS, PROMPT_CONTEXT_MAX_SPORES, PROMPT_CONTEXT_MIN_SIMILARITY, PROMPT_CONTEXT_MIN_LENGTH, CONTEXT_SESSION_PREVIEW_CHARS, estimateTokens } from '../constants.js';\nimport { TranscriptMiner, extractTurnsFromBuffer } from '../capture/transcript-miner.js';\nimport { createPerProjectAdapter, extensionForMimeType, type TranscriptTurn } from '../agents/adapter.js';\nimport { claudeCodeAdapter } from '../agents/claude-code.js';\nimport { EventBuffer } from '../capture/buffer.js';\nimport { formatSessionBody, CONVERSATION_HEADING, extractSection } from '../obsidian/formatter.js';\nimport { writeObservationNotes } from '../vault/observations.js';\nimport { checkSupersession } from '../vault/curation.js';\nimport { collectArtifactCandidates } from '../artifacts/candidates.js';\nimport { slugifyPath } from '../artifacts/slugify.js';\nimport { sessionNoteId, bareSessionId, sessionWikilink, sessionRelativePath } from '../vault/session-id.js';\nimport { handleGetConfig, handlePutConfig } from './api/config.js';\nimport { handleGetStats, computeConfigHash } from './api/stats.js';\nimport { handleGetLogs } from './api/logs.js';\nimport { handleRestart } from './api/restart.js';\nimport { ProgressTracker, handleGetProgress } from './api/progress.js';\nimport { handleRebuild, handleDigest, handleCurate, handleReprocess } from './api/operations.js';\nimport { handleGetModels } from './api/models.js';\nimport { handleGetSessions } from './api/sessions.js';\nimport {\n handlePipelineHealth,\n handlePipelineItems,\n handlePipelineItemDetail,\n handlePipelineCircuits,\n handlePipelineRetry,\n handlePipelineSkip,\n handlePipelineRetryAll,\n handlePipelineCircuitReset,\n} from './api/pipeline.js';\nimport { handleForceDigest, handleDigestHealth } from './api/digest.js';\nimport { PipelineManager } from './pipeline.js';\nimport type { OperationHandlerDeps } from './api/operations.js';\nimport { runCuration, updateTitleAndSummary } from '../services/vault-ops.js';\nimport { z } from 'zod';\nimport YAML from 'yaml';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { stripFrontmatter } from '../vault/frontmatter.js';\n\n\ninterface IndexDeps {\n index: MycoIndex;\n vaultDir: string;\n vectorIndex: VectorIndex | null;\n embeddingProvider: EmbeddingProvider;\n llmProvider: LlmProvider;\n logger: DaemonLogger;\n}\n\nfunction indexAndEmbed(\n relativePath: string,\n noteId: string,\n embeddingText: string,\n metadata: Record<string, string>,\n deps: IndexDeps,\n): void {\n indexNote(deps.index, deps.vaultDir, relativePath);\n if (deps.vectorIndex && embeddingText) {\n generateEmbedding(deps.embeddingProvider, embeddingText.slice(0, EMBEDDING_INPUT_LIMIT))\n .then((emb) => deps.vectorIndex!.upsert(noteId, emb.embedding, metadata))\n .catch((err) => deps.logger.debug('embeddings', 'Embedding failed', { id: noteId, error: (err as Error).message }));\n }\n}\n\nfunction writeObservations(\n observations: Observation[],\n sessionId: string,\n deps: IndexDeps & { vault: VaultWriter },\n): void {\n const written = writeObservationNotes(observations, sessionId, deps.vault, deps.index, deps.vaultDir);\n for (const note of written) {\n indexAndEmbed(note.path, note.id, `${note.observation.title}\\n${note.observation.content}`,\n { type: 'spore', importance: 'high', session_id: sessionId }, deps);\n deps.logger.info('processor', 'Observation written', { type: note.observation.type, title: note.observation.title, session_id: sessionId });\n }\n\n // Fire-and-forget supersession checks — sequential to avoid thundering herd on the LLM\n if (written.length > 0) {\n const curationDeps = {\n index: deps.index,\n vectorIndex: deps.vectorIndex,\n embeddingProvider: deps.embeddingProvider,\n llmProvider: deps.llmProvider,\n vaultDir: deps.vaultDir,\n log: ((level: string, msg: string, data?: Record<string, unknown>) => (deps.logger as any)[level]('curation', msg, data)) as Parameters<typeof checkSupersession>[1]['log'],\n };\n (async () => {\n for (const note of written) {\n try { await checkSupersession(note.id, curationDeps); }\n catch (err) { deps.logger.debug('curation', 'Supersession check failed', { id: note.id, error: (err as Error).message }); }\n }\n })();\n }\n}\n\nasync function captureArtifacts(\n candidates: Array<{ path: string; content: string }>,\n classified: ClassifiedArtifact[],\n sessionId: string,\n deps: IndexDeps & { vault: VaultWriter },\n lineage?: LineageGraph,\n): Promise<void> {\n const candidateMap = new Map(candidates.map((c) => [c.path, c]));\n\n for (const artifact of classified) {\n const candidate = candidateMap.get(artifact.source_path);\n if (!candidate) continue;\n\n const artifactId = slugifyPath(artifact.source_path);\n const artifactPath = deps.vault.writeArtifact({\n id: artifactId,\n artifact_type: artifact.artifact_type,\n source_path: artifact.source_path,\n title: artifact.title,\n session: sessionId,\n tags: artifact.tags,\n content: candidate.content,\n });\n indexAndEmbed(artifactPath, artifactId, `${artifact.title}\\n${candidate.content}`,\n { type: 'artifact', artifact_type: artifact.artifact_type, session_id: sessionId }, deps);\n deps.logger.info('processor', 'Artifact captured', {\n id: artifactId,\n type: artifact.artifact_type,\n source: artifact.source_path,\n });\n\n // Register artifact-session association for lineage detection.\n // Future sessions referencing this artifact ID link as children.\n lineage?.registerArtifactForSession(sessionId, artifactId);\n }\n}\n\nexport function migrateSporeFiles(vaultDir: string): number {\n const sporesDir = path.join(vaultDir, 'spores');\n if (!fs.existsSync(sporesDir)) return 0;\n\n let moved = 0;\n const entries = fs.readdirSync(sporesDir);\n\n for (const entry of entries) {\n const fullPath = path.join(sporesDir, entry);\n if (!entry.endsWith('.md')) continue;\n if (fs.statSync(fullPath).isDirectory()) continue;\n\n try {\n const content = fs.readFileSync(fullPath, 'utf-8');\n const fmMatch = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!fmMatch) continue;\n\n const parsed = YAML.parse(fmMatch[1]) as Record<string, unknown>;\n const obsType = parsed.observation_type as string | undefined;\n if (!obsType) continue;\n\n const normalizedType = obsType.replace(/_/g, '-');\n const targetDir = path.join(sporesDir, normalizedType);\n fs.mkdirSync(targetDir, { recursive: true });\n const targetPath = path.join(targetDir, entry);\n fs.renameSync(fullPath, targetPath);\n // Touch the file so Obsidian detects the move and re-indexes backlinks\n const now = new Date();\n fs.utimesSync(targetPath, now, now);\n moved++;\n } catch {\n // Skip files that can't be read or parsed\n }\n }\n\n return moved;\n}\n\nexport async function main(): Promise<void> {\n const vaultArg = process.argv.find((_, i) => process.argv[i - 1] === '--vault');\n if (!vaultArg) {\n process.stderr.write('Usage: mycod --vault <path>\\n');\n process.exit(1);\n }\n\n const vaultDir = path.resolve(vaultArg);\n const config = loadConfig(vaultDir);\n\n const logger = new DaemonLogger(path.join(vaultDir, 'logs'), {\n level: config.daemon.log_level,\n maxSize: config.daemon.max_log_size,\n });\n\n // Resolve dist/ui/ — walk up to find package.json (same strategy as prompts loader)\n let uiDir: string | null = null;\n {\n let dir = path.dirname(new URL(import.meta.url).pathname);\n for (let i = 0; i < 5; i++) {\n const candidate = path.join(dir, 'dist', 'ui');\n if (fs.existsSync(path.join(dir, 'package.json')) && fs.existsSync(candidate)) {\n uiDir = candidate;\n break;\n }\n dir = path.dirname(dir);\n }\n }\n if (uiDir) {\n logger.debug('daemon', 'Static UI directory found', { path: uiDir });\n }\n\n const server = new DaemonServer({ vaultDir, logger, uiDir: uiDir ?? undefined });\n\n // The daemon serves the dashboard UI and must stay running regardless of\n // active sessions. No auto-shutdown — runs until explicitly killed.\n const registry = new SessionRegistry({\n gracePeriod: 0,\n onEmpty: () => {},\n });\n\n // Batch processing setup\n const llmProvider = createLlmProvider(config.intelligence.llm);\n const embeddingProvider = createEmbeddingProvider(config.intelligence.embedding);\n\n let vectorIndex: VectorIndex | null = null;\n try {\n const testEmbed = await embeddingProvider.embed('test');\n vectorIndex = new VectorIndex(path.join(vaultDir, 'vectors.db'), testEmbed.dimensions);\n logger.info('embeddings', 'Vector index initialized', { dimensions: testEmbed.dimensions });\n } catch (error) {\n logger.warn('embeddings', 'Vector index unavailable', { error: (error as Error).message });\n }\n\n const processor = new BufferProcessor(llmProvider, config.intelligence.llm.context_window, config.capture);\n const vault = new VaultWriter(vaultDir);\n const index = new MycoIndex(path.join(vaultDir, 'index.db'));\n const lineageGraph = new LineageGraph(vaultDir);\n const pipeline = new PipelineManager(vaultDir, config.pipeline);\n\n // Recover any items stuck in 'processing' from a previous daemon crash\n const recoveredCount = pipeline.recoverStuck();\n if (recoveredCount > 0) {\n logger.info('pipeline', 'Recovered stuck pipeline items', { count: recoveredCount });\n }\n\n // First-run migration: if pipeline.db was just created (no work items),\n // rebuild from vault to catch up with existing content\n if (pipeline.isEmpty()) {\n logger.info('pipeline', 'First-run migration: rebuilding pipeline from vault');\n const result = pipeline.rebuild(vaultDir, vectorIndex, path.join(vaultDir, 'digest', 'trace.jsonl'));\n logger.info('pipeline', 'Pipeline rebuild complete', { registered: result.registered, stages: result.stages });\n }\n\n // Consolidation engine — declared here so pipeline handler can capture it.\n // Assigned later when digest.consolidation.enabled is true.\n let consolidationEngine: ConsolidationEngine | null = null;\n\n // Flag to ensure consolidationEngine.runPass() is called at most once per tick.\n // runPass() processes ALL pending spores, so calling it per-item is redundant.\n let consolidationPassRanThisTick = false;\n\n // Pipeline stage handlers\n pipeline.setHandlers({\n extraction: async (itemId, itemType, sourcePath) => {\n if (itemType !== 'session') return; // Only sessions have extraction\n\n logger.info('pipeline', 'Extraction started', { session_id: itemId });\n\n // 1. Read the session note to get conversation section and user\n const fullPath = sourcePath ? path.join(vaultDir, sourcePath) : null;\n if (!fullPath || !fs.existsSync(fullPath)) {\n throw new Error(`Session note not found: ${sourcePath}`);\n }\n const fileContent = fs.readFileSync(fullPath, 'utf-8');\n const { body, frontmatter } = stripFrontmatter(fileContent);\n const conversationMarkdown = extractSection(body, CONVERSATION_HEADING);\n const user = typeof frontmatter.user === 'string' && frontmatter.user ? frontmatter.user : undefined;\n\n if (!conversationMarkdown.trim()) {\n throw new Error(`No conversation content in session note: ${sourcePath}`);\n }\n\n // 2. Extract observations from conversation markdown (LLM call)\n const extractionResult = await processor.process(conversationMarkdown, itemId);\n if (extractionResult.degraded) {\n throw new Error(`Observation extraction failed for session ${itemId}`);\n }\n\n // 3. Generate summary + title from conversation (LLM call)\n const { summary: narrative, title } = await processor.summarizeSession(\n conversationMarkdown,\n itemId,\n user,\n );\n if (narrative.includes(SUMMARIZATION_FAILED_MARKER)) {\n throw new Error(`Summarization failed for session ${itemId}: ${narrative}`);\n }\n\n // 4. Write observation spore notes (skip supersession — that's consolidation stage)\n const written = writeObservationNotes(\n extractionResult.observations,\n itemId,\n vault,\n index,\n vaultDir,\n );\n for (const note of written) {\n indexAndEmbed(note.path, note.id, `${note.observation.title}\\n${note.observation.content}`,\n { type: 'spore', importance: 'high', session_id: itemId }, indexDeps);\n logger.info('pipeline', 'Spore written', { type: note.observation.type, title: note.observation.title, session_id: itemId });\n }\n\n // 5. Update session note with LLM-generated title + narrative + extraction metadata\n const fmEnd = fileContent.indexOf('---', 4);\n const parsedFm = YAML.parse(fileContent.slice(4, fmEnd)) as Record<string, unknown>;\n parsedFm.observations_count = written.length;\n parsedFm.summary_tokens = estimateTokens(narrative);\n parsedFm.extraction_model = config.intelligence.llm.model;\n const fmYaml = YAML.stringify(parsedFm, { defaultStringType: 'QUOTE_DOUBLE', defaultKeyType: 'PLAIN' }).trim();\n const updatedBody = updateTitleAndSummary(body, title, narrative);\n fs.writeFileSync(fullPath, `---\\n${fmYaml}\\n---\\n\\n${updatedBody}`, 'utf-8');\n\n // 6. Re-index the session note (FTS) to pick up new title/summary\n indexNote(index, vaultDir, sourcePath!);\n\n // 7. Register spores in pipeline\n for (const note of written) {\n pipeline.register(note.id, 'spore', note.path);\n pipeline.advance(note.id, 'spore', 'capture', 'succeeded');\n }\n\n logger.info('pipeline', 'Extraction completed', {\n session_id: itemId,\n observations: written.length,\n title,\n });\n\n return {\n observations: written.length,\n observation_ids: written.map((n) => n.id),\n summary_tokens: estimateTokens(narrative),\n title,\n model: config.intelligence.llm.model,\n };\n },\n embedding: async (itemId, itemType, sourcePath) => {\n if (!vectorIndex || !embeddingProvider) {\n throw new Error('Embedding provider or vector index not available');\n }\n if (!sourcePath) {\n throw new Error(`No source path for ${itemType}/${itemId}`);\n }\n\n const fullPath = path.join(vaultDir, sourcePath);\n if (!fs.existsSync(fullPath)) {\n throw new Error(`Vault note not found: ${sourcePath}`);\n }\n\n const fileContent = fs.readFileSync(fullPath, 'utf-8');\n\n // Parse frontmatter for metadata\n const { body, frontmatter } = stripFrontmatter(fileContent);\n\n // Extract embeddable text based on item type\n let embeddableText: string;\n if (itemType === 'session') {\n // For sessions: title + summary narrative (same pattern as runReprocess)\n const title = typeof frontmatter.title === 'string' ? frontmatter.title : '';\n const summary = typeof frontmatter.summary === 'string' ? frontmatter.summary : '';\n // Also try extracting narrative from the abstract callout in the body\n const calloutMatch = body.match(/> \\[!abstract\\] Summary\\n((?:> .*\\n?)*)/);\n const narrative = calloutMatch\n ? calloutMatch[1].replace(/^> /gm, '').trim()\n : '';\n embeddableText = `${title}\\n${narrative || summary}`.trim();\n } else {\n // For spores/artifacts: title from first heading + full body content\n const titleMatch = body.match(/^#\\s+(.+)$/m);\n const title = titleMatch ? titleMatch[1] : '';\n embeddableText = `${title}\\n${body}`.trim();\n }\n\n if (!embeddableText) {\n // Nothing to embed — empty content is not an error, just skip\n logger.debug('pipeline', 'No embeddable content, skipping', { id: itemId, type: itemType });\n return;\n }\n\n // Generate embedding\n const result = await generateEmbedding(\n embeddingProvider,\n embeddableText.slice(0, EMBEDDING_INPUT_LIMIT),\n );\n\n // Build metadata for vector index\n const metadata: Record<string, string> = {\n type: itemType,\n file_path: sourcePath,\n session_id: typeof frontmatter.session === 'string' ? frontmatter.session\n : typeof frontmatter.id === 'string' && itemType === 'session' ? frontmatter.id\n : '',\n branch: typeof frontmatter.branch === 'string' ? frontmatter.branch : '',\n };\n\n // Store in vectors.db\n vectorIndex.upsert(itemId, result.embedding, metadata);\n\n // Enrich session note frontmatter with embedding model\n if (itemType === 'session' && sourcePath) {\n vault.updateNoteFrontmatter(sourcePath, {\n embedding_model: config.intelligence.embedding.model,\n }, true);\n }\n\n logger.info('pipeline', 'Embedding stored', {\n id: itemId,\n type: itemType,\n dimensions: result.dimensions,\n });\n\n return {\n model: result.model,\n dimensions: result.dimensions,\n };\n },\n consolidation: async (itemId, itemType) => {\n if (itemType !== 'spore') return; // Sessions/artifacts skip consolidation\n\n // Check if this spore supersedes older ones\n const supersededIds = await checkSupersession(itemId, {\n index,\n vectorIndex,\n embeddingProvider,\n llmProvider,\n vaultDir,\n log: ((level: string, msg: string, data?: Record<string, unknown>) =>\n (logger as any)[level]('curation', msg, data)) as Parameters<typeof checkSupersession>[1]['log'],\n });\n\n // Run consolidation pass (clusters + wisdom synthesis) — once per tick,\n // since runPass() processes ALL pending spores.\n if (consolidationEngine && !consolidationPassRanThisTick) {\n consolidationPassRanThisTick = true;\n await consolidationEngine.runPass();\n }\n\n return {\n superseded: supersededIds ?? [],\n wisdom_created: null,\n candidates_evaluated: 0,\n };\n },\n });\n\n pipeline.setLogger((level, domain, message, data) => {\n const fn = logger[level as keyof typeof logger];\n if (typeof fn === 'function') (fn as typeof logger.info).call(logger, domain, message, data);\n });\n\n // Pipeline tick timer — processes extraction, embedding, consolidation\n const pipelineTickTimer = setInterval(async () => {\n try {\n consolidationPassRanThisTick = false;\n await pipeline.tick(config.pipeline.batch_size);\n } catch (err) {\n logger.error('pipeline', 'Pipeline tick failed', { error: (err as Error).message });\n }\n }, config.pipeline.tick_interval_seconds * 1000);\n\n const transcriptMiner = new TranscriptMiner({\n additionalAdapters: config.capture.transcript_paths.map((p) =>\n createPerProjectAdapter(p, claudeCodeAdapter.parseTurns),\n ),\n });\n\n let activeStopProcessing: Promise<void> | null = null;\n const indexDeps: IndexDeps = { index, vaultDir, vectorIndex, embeddingProvider, llmProvider, logger };\n\n const bufferDir = path.join(vaultDir, 'buffer');\n const sessionBuffers = new Map<string, EventBuffer>();\n const sessionFilePaths = new Map<string, Set<string>>();\n const capturedArtifactPaths = new Map<string, Set<string>>();\n\n // Clean up stale buffer files (>24h) on startup\n if (fs.existsSync(bufferDir)) {\n const cutoff = Date.now() - STALE_BUFFER_MAX_AGE_MS;\n for (const file of fs.readdirSync(bufferDir)) {\n const filePath = path.join(bufferDir, file);\n const stat = fs.statSync(filePath);\n if (stat.mtimeMs < cutoff) {\n fs.unlinkSync(filePath);\n logger.debug('daemon', 'Cleaned stale buffer', { file });\n }\n }\n }\n\n // Check for stale 'memory' type entries — migration happened but index wasn't rebuilt.\n // Deferred to after server starts so it doesn't block the health check.\n const needsMigrationReindex = index.query({ type: 'memory' }).length > 0;\n\n // Migrate flat spore files into type subdirectories\n const migrated = migrateSporeFiles(vaultDir);\n if (migrated > 0) {\n logger.info('daemon', 'Migrated spore files to type subdirectories', { count: migrated });\n // Rebuild FTS index to update stored paths (vectors are keyed by ID, unaffected)\n initFts(index);\n rebuildIndex(index, vaultDir);\n }\n\n // Route body schemas\n const RegisterBody = z.object({\n session_id: z.string(),\n branch: z.string().optional(),\n started_at: z.string().optional(),\n });\n const UnregisterBody = z.object({ session_id: z.string() });\n const EventBody = z.object({ type: z.string(), session_id: z.string() }).passthrough();\n const StopBody = z.object({\n session_id: z.string(),\n user: z.string().optional(),\n transcript_path: z.string().optional(),\n last_assistant_message: z.string().optional(),\n });\n const ContextBody = z.object({\n session_id: z.string().optional(),\n branch: z.string().optional(),\n files: z.array(z.string()).optional(),\n });\n\n const planWatcher = new PlanWatcher({\n projectRoot: process.cwd(),\n watchPaths: config.capture.artifact_watch,\n onPlan: (event) => {\n logger.info('watcher', 'Plan detected', { source: event.source, file: event.filePath });\n\n if (event.filePath) {\n try {\n const content = fs.readFileSync(event.filePath, 'utf-8');\n const relativePath = path.relative(vaultDir, event.filePath);\n const title = content.match(/^#\\s+(.+)$/m)?.[1] ?? path.basename(event.filePath);\n const planId = `plan-${path.basename(event.filePath, '.md')}`;\n indexAndEmbed(relativePath, planId, `${title}\\n${content}`, { type: 'plan' },\n indexDeps);\n\n // Register plan-session association for lineage detection.\n // When a future session's first prompt mentions this plan ID,\n // detectHeuristicParent links it as a child of this session.\n if (event.sessionId) {\n lineageGraph.registerArtifactForSession(event.sessionId, planId);\n logger.debug('lineage', 'Plan registered for session', { planId, session: event.sessionId });\n }\n\n logger.info('watcher', 'Plan indexed', { path: relativePath });\n } catch (err) {\n logger.debug('watcher', 'Plan index failed', { error: (err as Error).message });\n }\n }\n },\n });\n planWatcher.startFileWatcher();\n\n // Digest LLM provider: resolved once, used by both pipeline tick and operations API\n const digestLlmConfig = {\n provider: config.digest.intelligence.provider ?? config.intelligence.llm.provider,\n model: config.digest.intelligence.model ?? config.intelligence.llm.model,\n base_url: config.digest.intelligence.base_url ?? config.intelligence.llm.base_url,\n context_window: config.digest.intelligence.context_window,\n };\n const digestLlm = (config.digest.intelligence.model || config.digest.intelligence.provider)\n ? createLlmProvider(digestLlmConfig)\n : llmProvider;\n\n // Digest engine: synthesizes vault knowledge into tiered context extracts\n let metabolism: Metabolism | null = null;\n\n if (config.digest.enabled) {\n logger.debug('digest', 'Digest LLM config', digestLlmConfig);\n logger.debug('digest', `Using ${digestLlm.name} provider for digest`);\n\n const digestEngine = new DigestEngine({\n vaultDir,\n index,\n llmProvider: digestLlm,\n config,\n log: (level, message, data) => logger[level]('digest', message, data),\n });\n\n if (config.digest.consolidation.enabled) {\n consolidationEngine = new ConsolidationEngine({\n vaultDir,\n index,\n vectorIndex,\n embeddingProvider,\n llmProvider: digestLlm,\n maxTokens: config.digest.consolidation.max_tokens,\n log: (level, message, data) => logger[level]('consolidation', message, data),\n });\n\n logger.info('consolidation', 'Auto-consolidation enabled as pipeline stage');\n }\n\n metabolism = new Metabolism(config.digest.metabolism);\n\n // Digest is triggered by the pipeline tick, not by the metabolism timer directly.\n // The metabolism timer only controls cadence (active → cooldown → dormant).\n // When the metabolism says \"it's time\" it sets a flag; the pipeline tick checks\n // the flag and runs digest if upstream is clear. This avoids startup races\n // where the metabolism fires before the pipeline has processed upstream work.\n // Start true so digest runs on the first tick after upstream clears.\n // The hasUpstreamWork() check prevents premature execution.\n let digestReady = true;\n let forceDigest = false;\n\n metabolism.start(async () => {\n // Metabolism says it's time for a digest — set the flag for the pipeline tick\n digestReady = true;\n });\n\n // Register digest as a post-stages step in the pipeline tick\n const originalTick = pipeline.tick.bind(pipeline);\n pipeline.tick = async (batchSize: number) => {\n // Process upstream stages first (extraction, embedding, consolidation)\n await originalTick(batchSize);\n\n // Then check if digest should run\n if (!digestReady) return;\n if (pipeline.hasUpstreamWork()) {\n logger.debug('digest', 'Digest deferred — upstream stages pending');\n return;\n }\n\n // Substrate threshold gate: skip if not enough new knowledge (unless forced)\n if (!forceDigest) {\n const ready = pipeline.newSubstrateSinceLastDigest();\n if (ready < config.digest.substrate.min_notes_for_cycle) {\n logger.debug('digest', 'Digest deferred — insufficient substrate', {\n ready,\n threshold: config.digest.substrate.min_notes_for_cycle,\n });\n return;\n }\n }\n\n // Reset flags before running\n digestReady = false;\n forceDigest = false;\n\n try {\n const cycleResult = await digestEngine.runCycle();\n if (cycleResult) {\n metabolism!.onSubstrateFound();\n const digestOutput = {\n included_in_cycle: cycleResult.cycleId,\n tiers_generated: cycleResult.tiersGenerated,\n };\n const advanced = pipeline.advanceDigestItems(digestOutput);\n if (advanced > 0) {\n logger.debug('digest', `Advanced ${advanced} pipeline items to digest:succeeded`);\n }\n logger.info('digest', `Digest cycle ${cycleResult.cycleId}: ${cycleResult.tiersGenerated.length} tiers`);\n } else {\n metabolism!.onEmptyCycle();\n }\n } catch (err) {\n logger.warn('digest', 'Digest cycle failed', { error: (err as Error).message });\n metabolism!.onEmptyCycle();\n }\n };\n\n // Digest API routes\n server.registerRoute('POST', '/api/pipeline/digest/force', handleForceDigest(() => {\n forceDigest = true;\n }));\n server.registerRoute('GET', '/api/pipeline/digest-health', handleDigestHealth({\n vaultDir,\n pipeline,\n minNotesForCycle: config.digest.substrate.min_notes_for_cycle,\n metabolismState: () => metabolism?.state ?? 'disabled',\n digestReady: () => digestReady,\n cycleInProgress: () => digestEngine.isCycleInProgress,\n }));\n\n logger.info('digest', 'Digest enabled — controlled by pipeline tick');\n }\n\n const batchManager = new BatchManager(async (closedBatch: BatchEvent[]) => {\n if (closedBatch.length === 0) return;\n\n const sessionId = closedBatch[0].session_id;\n\n // Batch closure is now an event boundary marker — observation extraction\n // is deferred to the pipeline extraction stage (Task 10).\n logger.debug('processor', 'Batch closed (extraction deferred to pipeline)', {\n session_id: sessionId,\n events: closedBatch.length,\n });\n\n // Incremental artifact capture: process new markdown files at turn boundaries\n // instead of waiting for session end. Only classify files not yet captured.\n const allPaths = sessionFilePaths.get(sessionId);\n const alreadyCaptured = capturedArtifactPaths.get(sessionId) ?? new Set<string>();\n if (allPaths && allPaths.size > alreadyCaptured.size) {\n const newPaths = new Set([...allPaths].filter((p) => !alreadyCaptured.has(p)));\n const candidates = collectArtifactCandidates(\n newPaths,\n { artifact_extensions: config.capture.artifact_extensions },\n process.cwd(),\n );\n if (candidates.length > 0) {\n processor.classifyArtifacts(candidates, sessionId)\n .then((classified) => captureArtifacts(candidates, classified, sessionId, { vault, ...indexDeps }, lineageGraph))\n .then(() => {\n // Mark these paths as captured so we don't re-classify them\n if (!capturedArtifactPaths.has(sessionId)) {\n capturedArtifactPaths.set(sessionId, new Set());\n }\n const captured = capturedArtifactPaths.get(sessionId)!;\n for (const c of candidates) {\n // candidates have relative paths; sessionFilePaths has absolute paths\n const absPath = path.resolve(process.cwd(), c.path);\n captured.add(absPath);\n }\n })\n .catch((err) => logger.warn('processor', 'Incremental artifact capture failed', {\n session_id: sessionId, error: (err as Error).message,\n }));\n }\n }\n });\n\n // Session routes\n server.registerRoute('POST', '/sessions/register', async (req) => {\n const { session_id, branch, started_at } = RegisterBody.parse(req.body);\n const resolvedStartedAt = started_at ?? new Date().toISOString();\n registry.register(session_id, { started_at: resolvedStartedAt, branch });\n server.updateDaemonJsonSessions(registry.sessions);\n\n // Heuristic lineage detection\n try {\n const recentSessions = index.query({ type: 'session', limit: LINEAGE_RECENT_SESSIONS_LIMIT })\n .map((n) => {\n const fm = n.frontmatter as Record<string, unknown>;\n return { id: bareSessionId(n.id), ended: fm.ended as string | undefined, branch: fm.branch as string | undefined };\n });\n const activeSessions = registry.sessions\n .filter((s) => s !== session_id)\n .map((s) => registry.getSession(s))\n .filter((s): s is RegisteredSession => s !== undefined);\n const link = lineageGraph.detectHeuristicParent(session_id, {\n started_at: resolvedStartedAt,\n branch,\n }, recentSessions, activeSessions);\n if (link) {\n logger.info('lineage', 'Heuristic parent detected', { child: session_id, parent: link.parent, signal: link.signal });\n }\n } catch (err) {\n logger.debug('lineage', 'Heuristic detection failed', { error: (err as Error).message });\n }\n\n // Wake digest metabolism when a new session starts\n metabolism?.activate();\n\n logger.info('lifecycle', 'Session registered', { session_id, branch });\n return { body: { ok: true, sessions: registry.sessions } };\n });\n\n server.registerRoute('POST', '/sessions/unregister', async (req) => {\n const { session_id } = UnregisterBody.parse(req.body);\n registry.unregister(session_id);\n // Note: we do NOT delete the buffer FILE for THIS session. Session reload\n // (SessionEnd → SessionStart) reuses the same session_id, and deleting\n // would wipe all prior events.\n // We DO opportunistically clean stale buffers for OTHER sessions (>24h).\n try {\n const cutoff = Date.now() - STALE_BUFFER_MAX_AGE_MS;\n for (const file of fs.readdirSync(bufferDir)) {\n if (!file.endsWith('.jsonl')) continue;\n const bufferSessionId = file.replace('.jsonl', '');\n if (bufferSessionId === session_id) continue; // skip current session\n const filePath = path.join(bufferDir, file);\n const stat = fs.statSync(filePath);\n if (stat.mtimeMs < cutoff) {\n fs.unlinkSync(filePath);\n logger.debug('daemon', 'Cleaned stale buffer', { file });\n }\n }\n } catch { /* buffer dir may not exist */ }\n // We DO prune the in-memory Map entries to avoid unbounded growth.\n sessionBuffers.delete(session_id);\n sessionFilePaths.delete(session_id);\n capturedArtifactPaths.delete(session_id);\n server.updateDaemonJsonSessions(registry.sessions);\n logger.info('lifecycle', 'Session unregistered', { session_id });\n return { body: { ok: true, sessions: registry.sessions } };\n });\n\n // Event routes\n server.registerRoute('POST', '/events', async (req) => {\n const validated = EventBody.parse(req.body);\n const event = { ...validated, timestamp: validated.timestamp ?? new Date().toISOString() } as BatchEvent;\n logger.debug('hooks', 'Event received', { type: event.type, session_id: event.session_id });\n\n // Ensure session is registered (idempotent — handles daemon restarts mid-session)\n if (!registry.getSession(event.session_id)) {\n registry.register(event.session_id, { started_at: event.timestamp });\n logger.debug('lifecycle', 'Auto-registered session from event', { session_id: event.session_id });\n }\n\n // Persist to disk so events survive daemon restarts\n if (!sessionBuffers.has(event.session_id)) {\n sessionBuffers.set(event.session_id, new EventBuffer(bufferDir, event.session_id));\n }\n sessionBuffers.get(event.session_id)!.append(event as Record<string, unknown>);\n\n batchManager.addEvent(event);\n if (validated.type === 'tool_use') {\n const v = validated as Record<string, unknown>;\n planWatcher.checkToolEvent({ tool_name: String(v.tool_name ?? ''), tool_input: v.tool_input, session_id: validated.session_id });\n const toolName = String(v.tool_name ?? '');\n if (toolName === 'Write' || toolName === 'Edit') {\n const filePath = (v.tool_input as Record<string, unknown> | undefined)?.file_path as string | undefined;\n if (filePath) {\n if (!sessionFilePaths.has(event.session_id)) {\n sessionFilePaths.set(event.session_id, new Set());\n }\n sessionFilePaths.get(event.session_id)!.add(filePath);\n // Invalidate captured status so edits to already-captured files\n // trigger re-classification on the next turn boundary\n capturedArtifactPaths.get(event.session_id)?.delete(filePath);\n }\n }\n }\n return { body: { ok: true } };\n });\n\n server.registerRoute('POST', '/events/stop', async (req) => {\n const { session_id: sessionId, user, transcript_path: hookTranscriptPath, last_assistant_message: lastAssistantMessage } = StopBody.parse(req.body);\n // Ensure session is registered (handles daemon restarts mid-session)\n if (!registry.getSession(sessionId)) {\n registry.register(sessionId, { started_at: new Date().toISOString() });\n logger.debug('lifecycle', 'Auto-registered session from stop event', { session_id: sessionId });\n }\n const sessionMeta = registry.getSession(sessionId);\n logger.info('hooks', 'Stop received', { session_id: sessionId, has_transcript_path: !!hookTranscriptPath, has_response: !!lastAssistantMessage });\n\n // Respond immediately — the hook should not block on LLM processing.\n // Serialize stop processing: if a previous stop is still running, chain\n // the new one to run after it completes. This prevents concurrent\n // processStopEvent calls from racing on the same session file.\n const run = () => processStopEvent(sessionId, user, sessionMeta, hookTranscriptPath, lastAssistantMessage).catch((err) => {\n logger.error('processor', 'Stop processing failed', { session_id: sessionId, error: (err as Error).message });\n });\n\n // Chain onto any in-flight processing. Only the tail of the chain clears the variable.\n const prev = activeStopProcessing ?? Promise.resolve();\n activeStopProcessing = prev.then(run).finally(() => { activeStopProcessing = null; });\n\n return { body: { ok: true } };\n });\n\n /** Correlate buffer tool_use events with transcript turns by timestamp to populate toolBreakdown and files. */\n function enrichTurnsWithToolMetadata(turns: TranscriptTurn[], events: Array<Record<string, unknown>>): void {\n if (events.length === 0 || turns.length === 0) return;\n\n const toolEvents = events.filter((e) => e.type === 'tool_use');\n if (toolEvents.length === 0) return;\n\n // Linear merge: advance a cursor through sorted tool events as we iterate turns\n let cursor = 0;\n for (let i = 0; i < turns.length; i++) {\n const turnEnd = i + 1 < turns.length ? turns[i + 1].timestamp : null;\n const breakdown: Record<string, number> = {};\n const files = new Set<string>();\n\n while (cursor < toolEvents.length) {\n const ts = String(toolEvents[cursor].timestamp ?? '');\n if (turnEnd !== null && ts >= turnEnd) break;\n const evt = toolEvents[cursor];\n const toolName = String(evt.tool_name ?? evt.tool ?? 'unknown');\n breakdown[toolName] = (breakdown[toolName] ?? 0) + 1;\n const input = evt.tool_input as Record<string, unknown> | undefined;\n const filePath = input?.file_path ?? input?.path;\n if (typeof filePath === 'string') files.add(filePath);\n cursor++;\n }\n\n if (Object.keys(breakdown).length > 0) {\n turns[i].toolBreakdown = breakdown;\n if (files.size > 0) turns[i].files = [...files];\n }\n }\n }\n\n async function processStopEvent(\n sessionId: string,\n user: string | undefined,\n sessionMeta: RegisteredSession | undefined,\n hookTranscriptPath?: string,\n lastAssistantMessage?: string,\n ): Promise<void> {\n\n // --- Phase 1: Gather data (I/O only, no LLM) ---\n\n const lastBatch = batchManager.finalize(sessionId);\n\n // Tiered turn extraction:\n // 1. Read transcript for complete turns (with AI responses)\n // 2. Check buffer for prompts newer than the transcript's last turn\n // (captures turns the transcript missed, e.g., after context compaction)\n // 3. Fall back to buffer entirely if no transcript found\n const transcriptResult = transcriptMiner.getAllTurnsWithSource(sessionId, hookTranscriptPath);\n let allTurns = transcriptResult.turns;\n let turnSource = transcriptResult.source;\n\n const bufferEvents = sessionBuffers.get(sessionId)?.readAll() ?? [];\n\n if (allTurns.length === 0) {\n // No transcript — use buffer as primary source\n allTurns = extractTurnsFromBuffer(bufferEvents);\n turnSource = 'buffer';\n } else if (bufferEvents.length > 0) {\n // Transcript exists — check for buffer events newer than the last transcript turn.\n // These are prompts the transcript missed (e.g., after context compaction).\n const lastTranscriptTs = allTurns[allTurns.length - 1].timestamp;\n if (lastTranscriptTs) {\n const newerEvents = bufferEvents.filter((e) =>\n String(e.timestamp ?? '') > lastTranscriptTs,\n );\n if (newerEvents.length > 0) {\n const bufferTurns = extractTurnsFromBuffer(newerEvents);\n allTurns = [...allTurns, ...bufferTurns];\n turnSource = `${transcriptResult.source}+buffer`;\n logger.info('processor', 'Appended buffer turns missing from transcript', {\n session_id: sessionId, transcriptTurns: transcriptResult.turns.length, bufferTurns: bufferTurns.length,\n });\n }\n }\n }\n\n // Attach the last assistant message from the hook to the most recent turn\n // that doesn't already have an AI response. This captures the response\n // for turns the transcript missed (post-compaction) or buffer-sourced turns.\n if (lastAssistantMessage && allTurns.length > 0) {\n const lastTurn = allTurns[allTurns.length - 1];\n if (!lastTurn.aiResponse) {\n lastTurn.aiResponse = lastAssistantMessage;\n }\n }\n\n enrichTurnsWithToolMetadata(allTurns, bufferEvents);\n\n const ended = new Date().toISOString();\n let started = (allTurns.length > 0 && allTurns[0].timestamp) ? allTurns[0].timestamp : ended;\n\n // Find existing session file and clean up cross-date duplicates in one pass.\n const sessionsDir = path.join(vaultDir, 'sessions');\n const sessionFileName = `${sessionNoteId(sessionId)}.md`;\n let existingContent: string | undefined;\n const duplicatePaths: string[] = [];\n try {\n for (const dateDir of fs.readdirSync(sessionsDir)) {\n const candidate = path.join(sessionsDir, dateDir, sessionFileName);\n try {\n const content = fs.readFileSync(candidate, 'utf-8');\n if (!existingContent || content.length > existingContent.length) {\n existingContent = content;\n }\n duplicatePaths.push(candidate);\n } catch { /* file doesn't exist in this date dir */ }\n }\n } catch { /* sessions dir may not exist yet */ }\n\n let existingTurnCount = 0;\n let existingExtractionFields: Record<string, unknown> | null = null;\n if (existingContent) {\n const fmMatch = existingContent.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (fmMatch) {\n const parsed = YAML.parse(fmMatch[1]) as Record<string, unknown>;\n if (typeof parsed.started === 'string') started = parsed.started;\n // Preserve extraction-enriched frontmatter fields across stop-event rebuilds\n const extractionKeys = ['observations_count', 'summary_tokens', 'extraction_model', 'embedding_model'];\n const preserved: Record<string, unknown> = {};\n for (const key of extractionKeys) {\n if (parsed[key] !== undefined) preserved[key] = parsed[key];\n }\n if (Object.keys(preserved).length > 0) existingExtractionFields = preserved;\n }\n const turnMatches = existingContent.match(/^### Turn \\d+/gm);\n existingTurnCount = turnMatches?.length ?? 0;\n }\n\n // Collect artifact candidates (no LLM yet) — only files not already captured incrementally\n const writtenFiles = sessionFilePaths.get(sessionId) ?? new Set<string>();\n const alreadyCaptured = capturedArtifactPaths.get(sessionId) ?? new Set<string>();\n const uncapturedFiles = new Set([...writtenFiles].filter((p) => !alreadyCaptured.has(p)));\n const artifactCandidates = collectArtifactCandidates(\n uncapturedFiles,\n { artifact_extensions: config.capture.artifact_extensions },\n process.cwd(),\n );\n\n // Guard: never overwrite an existing session with zero turns — the transcript\n // is temporarily unreadable (daemon restart, file locked, etc.)\n if (allTurns.length === 0 && existingTurnCount > 0) {\n logger.warn('processor', 'Transcript unreadable, skipping rewrite to preserve existing data', { session_id: sessionId, existingTurns: existingTurnCount });\n return;\n }\n\n // Skip if no new turns AND no batch to process AND no artifacts to classify\n if (allTurns.length > 0 && allTurns.length === existingTurnCount && lastBatch.length === 0 && artifactCandidates.length === 0) {\n logger.debug('processor', 'No new turns, skipping session rewrite', { session_id: sessionId, turns: allTurns.length });\n return;\n }\n\n // --- Phase 2: Capture — write session note without LLM-generated content ---\n // LLM work (summary, title, observation extraction) is deferred to the\n // pipeline extraction stage (Task 10). The session note gets a placeholder\n // title and empty narrative; extraction will fill them in later.\n\n // Compute canonical path\n const date = started.slice(0, 10);\n const relativePath = sessionRelativePath(sessionId, date);\n const targetFullPath = path.join(vaultDir, relativePath);\n\n // Remove cross-date duplicates\n for (const dup of duplicatePaths) {\n if (dup !== targetFullPath) {\n try { fs.unlinkSync(dup); logger.debug('lifecycle', 'Removed duplicate session file', { path: dup }); } catch { /* already gone */ }\n }\n }\n\n // Write images to attachments\n const attachmentsDir = path.join(vaultDir, 'attachments');\n const hasImages = allTurns.some((t) => t.images?.length);\n if (hasImages) {\n fs.mkdirSync(attachmentsDir, { recursive: true });\n }\n const turnImageNames: Map<number, string[]> = new Map();\n for (let i = 0; i < allTurns.length; i++) {\n const turn = allTurns[i];\n if (!turn.images?.length) continue;\n const names: string[] = [];\n for (let j = 0; j < turn.images.length; j++) {\n const img = turn.images[j];\n const ext = extensionForMimeType(img.mediaType);\n const filename = `${bareSessionId(sessionId)}-t${i + 1}-${j + 1}.${ext}`;\n const filePath = path.join(attachmentsDir, filename);\n if (!fs.existsSync(filePath)) {\n fs.writeFileSync(filePath, Buffer.from(img.data, 'base64'));\n logger.debug('processor', 'Image saved', { filename, turn: i + 1 });\n }\n names.push(filename);\n }\n turnImageNames.set(i, names);\n }\n\n // Build session note. Preserve LLM-generated title + narrative if extraction\n // has already run (stop events fire repeatedly during a session, and each one\n // rebuilds the note from the transcript — without this, extraction results are lost).\n let title = `Session ${sessionId}`;\n let narrative = '';\n if (existingContent) {\n const existingTitle = existingContent.match(/^# (.+)$/m)?.[1];\n if (existingTitle && existingTitle !== `Session ${sessionId}`) {\n title = existingTitle;\n }\n const calloutMatch = existingContent.match(/> \\[!abstract\\] Summary\\n((?:> .*\\n?)*)/);\n if (calloutMatch) {\n narrative = calloutMatch[1].replace(/^> /gm, '').trim();\n }\n }\n\n // Query related spores for this session\n const relatedMemories = index.query({ type: 'spore', limit: RELATED_SPORES_LIMIT })\n .filter((n) => {\n const fm = n.frontmatter as Record<string, unknown>;\n return fm.session === sessionNoteId(sessionId) || fm.session === sessionId;\n })\n .map((n) => ({ id: n.id, title: n.title }));\n\n const summary = formatSessionBody({\n title,\n narrative,\n sessionId,\n user,\n started,\n ended,\n branch: sessionMeta?.branch,\n relatedMemories,\n turns: allTurns.map((t, i) => ({\n prompt: t.prompt,\n toolCount: t.toolCount,\n toolBreakdown: t.toolBreakdown,\n files: t.files,\n aiResponse: t.aiResponse,\n images: turnImageNames.get(i),\n })),\n });\n\n const parentId = lineageGraph.getParent(sessionId);\n const parentLink = parentId ? lineageGraph.getLinks().find((l) => l.child === sessionId) : undefined;\n\n vault.writeSession({\n id: sessionId,\n user,\n started,\n ended,\n branch: sessionMeta?.branch,\n parent: parentId ? sessionWikilink(parentId) : undefined,\n parent_reason: parentLink?.signal,\n tools_used: allTurns.reduce((sum, t) => sum + t.toolCount, 0),\n transcript_source: turnSource,\n transcript_path: hookTranscriptPath,\n summary,\n });\n\n // Restore extraction-enriched frontmatter fields lost during rebuild\n if (existingExtractionFields) {\n vault.updateNoteFrontmatter(relativePath, existingExtractionFields);\n }\n\n // FTS index immediately so the session is searchable right away\n indexNote(index, vaultDir, relativePath);\n\n logger.debug('processor', 'Session turns', { source: turnSource, total: allTurns.length });\n\n // --- Phase 3: Register in pipeline ---\n // Capture is complete: transcript read, session note written, images saved.\n // Register the session and advance capture to succeeded so the extraction\n // stage picks it up on the next pipeline tick.\n pipeline.register(sessionId, 'session', relativePath);\n pipeline.advance(sessionId, 'session', 'capture', 'succeeded');\n\n logger.info('processor', 'Session captured and registered in pipeline', { session_id: sessionId, path: relativePath });\n }\n\n // Session-start context: digest extract (if available) or structural facts.\n // Memories are injected per-prompt (more targeted, less noise).\n server.registerRoute('POST', '/context', async (req) => {\n const { session_id, branch } = ContextBody.parse(req.body);\n logger.debug('hooks', 'Session context query', { session_id });\n try {\n // Digest-first: serve pre-computed extract if available\n if (config.digest.enabled && config.digest.inject_tier) {\n const result = handleMycoContext(vaultDir, { tier: config.digest.inject_tier });\n\n if (result.generated !== undefined) {\n // Append session metadata that the agent needs regardless of context source\n const meta: string[] = [result.content];\n if (branch) meta.push(`\\nBranch:: \\`${branch}\\``);\n meta.push(`Session:: \\`${session_id}\\``);\n\n logger.debug('context', `Injecting digest extract (tier ${result.tier})`, { session_id, fallback: result.fallback });\n return { body: { text: meta.join('\\n\\n'), source: 'digest', tier: result.tier } };\n }\n // Fall through to layer-based injection if no extract exists yet\n }\n\n const parts: string[] = [];\n\n // Active plans — the agent needs to know what's in flight\n const plans = index.query({ type: 'plan' });\n const activePlans = plans.filter((p) => {\n const status = (p.frontmatter as Record<string, unknown>).status as string;\n return status === 'active' || status === 'in_progress';\n });\n if (activePlans.length > 0) {\n const planLines = activePlans.slice(0, SESSION_CONTEXT_MAX_PLANS).map((p) => {\n const status = (p.frontmatter as Record<string, unknown>).status as string;\n return `- **${p.title}** (${status}) \\`[${p.id}]\\``;\n });\n parts.push(`### Active Plans\\n${planLines.join('\\n')}`);\n }\n\n // Parent session summary — lineage continuity\n if (session_id) {\n const parentId = lineageGraph.getParent(session_id);\n if (parentId) {\n const parentNotes = index.queryByIds([sessionNoteId(parentId)]);\n if (parentNotes.length > 0) {\n const parent = parentNotes[0];\n parts.push(`### Previous Session\\n- **${parent.title}**: ${parent.content.slice(0, CONTEXT_SESSION_PREVIEW_CHARS)} \\`[${parent.id}]\\``);\n }\n }\n }\n\n // Branch info for awareness\n if (branch) {\n parts.push(`Branch:: \\`${branch}\\``);\n }\n\n // Always include the session ID so the agent can pass it to myco_remember\n parts.push(`Session:: \\`${session_id}\\``);\n\n if (parts.length > 0) {\n return { body: { text: parts.join('\\n\\n') } };\n }\n return { body: { text: '' } };\n } catch (error) {\n logger.error('daemon', 'Session context failed', { error: (error as Error).message });\n return { body: { text: '' } };\n }\n });\n\n // Per-prompt context: semantic search for spores relevant to THIS specific prompt.\n // This is the primary intelligence delivery — targeted, high-confidence, token-efficient.\n const PromptContextBody = z.object({\n prompt: z.string(),\n session_id: z.string().optional(),\n });\n\n server.registerRoute('POST', '/context/prompt', async (req) => {\n const { prompt, session_id } = PromptContextBody.parse(req.body);\n if (!prompt || prompt.length < PROMPT_CONTEXT_MIN_LENGTH || !vectorIndex) {\n return { body: { text: '' } };\n }\n\n try {\n const emb = await generateEmbedding(embeddingProvider, prompt.slice(0, EMBEDDING_INPUT_LIMIT));\n const results = vectorIndex.search(emb.embedding, {\n limit: PROMPT_CONTEXT_MAX_SPORES,\n type: 'spore',\n relativeThreshold: PROMPT_CONTEXT_MIN_SIMILARITY,\n });\n\n if (results.length === 0) return { body: { text: '' } };\n\n const noteMap = new Map(\n index.queryByIds(results.map((r) => r.id)).map((n) => [n.id, n]),\n );\n\n const lines: string[] = [];\n for (const r of results) {\n const note = noteMap.get(r.id);\n if (!note) continue;\n const fm = note.frontmatter as Record<string, unknown>;\n if (fm.status === 'superseded' || fm.status === 'archived') continue;\n const obsType = fm.observation_type as string ?? 'note';\n lines.push(`- [${obsType}] ${note.title}: ${note.content.slice(0, CONTENT_SNIPPET_CHARS)} \\`[${note.id}]\\``);\n }\n\n if (lines.length === 0) return { body: { text: '' } };\n\n const injected = `**Relevant spores for this task:**\\n${lines.join('\\n')}`;\n logger.debug('context', 'Prompt context injected', {\n session_id,\n spores: lines.length,\n prompt_preview: prompt.slice(0, 50),\n });\n\n return { body: { text: injected } };\n } catch (err) {\n logger.debug('context', 'Prompt context failed', { error: (err as Error).message });\n return { body: { text: '' } };\n }\n });\n\n // --- Dashboard API routes ---\n const progressTracker = new ProgressTracker();\n let configHash = computeConfigHash(vaultDir);\n\n server.registerRoute('GET', '/api/config', async () => handleGetConfig(vaultDir));\n server.registerRoute('PUT', '/api/config', async (req) => {\n const result = await handlePutConfig(vaultDir, req.body);\n if (!result.status || result.status < 400) {\n configHash = computeConfigHash(vaultDir);\n }\n return result;\n });\n server.registerRoute('GET', '/api/stats', async () => handleGetStats({\n vaultDir, index, vectorIndex, version: server.version, config, configHash, metabolism,\n }));\n server.registerRoute('GET', '/api/logs', async (req) => handleGetLogs(logger.getRingBuffer(), req.query));\n server.registerRoute('GET', '/api/models', async (req) => handleGetModels(req));\n server.registerRoute('POST', '/api/restart', async (req) => handleRestart({ vaultDir, progressTracker }, req.body));\n server.registerRoute('GET', '/api/progress/:token', async (req) => handleGetProgress(progressTracker, req.params.token));\n\n // --- Operations API routes ---\n const operationDeps: OperationHandlerDeps = {\n vaultDir,\n config,\n index,\n vectorIndex,\n llmProvider,\n digestLlmProvider: digestLlm,\n embeddingProvider,\n progressTracker,\n pipeline,\n log: (level, message, data) => {\n const fn = logger[level as keyof typeof logger];\n if (typeof fn === 'function') (fn as typeof logger.info).call(logger, 'operations', message, data);\n },\n };\n\n server.registerRoute('POST', '/api/rebuild', async () => handleRebuild(operationDeps));\n server.registerRoute('POST', '/api/digest', async (req) => handleDigest(operationDeps, req.body));\n server.registerRoute('POST', '/api/curate', async (req) => handleCurate(operationDeps, req.body, runCuration));\n server.registerRoute('POST', '/api/reprocess', async (req) => handleReprocess(operationDeps, req.body));\n\n server.registerRoute('GET', '/api/sessions', async () => handleGetSessions(index));\n\n // Pipeline API\n server.registerRoute('GET', '/api/pipeline/health', handlePipelineHealth(pipeline));\n server.registerRoute('GET', '/api/pipeline/items', handlePipelineItems(pipeline));\n server.registerRoute('GET', '/api/pipeline/items/:id', handlePipelineItemDetail(pipeline));\n server.registerRoute('GET', '/api/pipeline/circuits', handlePipelineCircuits(pipeline));\n server.registerRoute('POST', '/api/pipeline/retry/:id', handlePipelineRetry(pipeline));\n server.registerRoute('POST', '/api/pipeline/skip/:id', handlePipelineSkip(pipeline));\n server.registerRoute('POST', '/api/pipeline/retry-all', handlePipelineRetryAll(pipeline));\n server.registerRoute('POST', '/api/pipeline/circuit/:provider/reset', handlePipelineCircuitReset(pipeline));\n\n await server.evictExistingDaemon();\n const resolvedPort = await resolvePort(config.daemon.port, vaultDir);\n if (resolvedPort === 0) {\n logger.warn('daemon', 'All preferred ports occupied, using ephemeral port');\n }\n await server.start(resolvedPort);\n logger.info('daemon', 'Daemon ready', { vault: vaultDir, port: server.port });\n\n // Persist the resolved port to config if it was auto-derived\n if (config.daemon.port === null && resolvedPort !== 0) {\n try {\n config.daemon.port = resolvedPort;\n saveConfig(vaultDir, config);\n logger.info('daemon', 'Persisted auto-derived port to myco.yaml', { port: resolvedPort });\n } catch (err) {\n logger.warn('daemon', 'Failed to persist auto-derived port', { error: (err as Error).message });\n }\n }\n\n // Write portal file so users can find the dashboard URL in Obsidian\n try {\n const { loadTemplate } = await import('../templates/index.js');\n const portalContent = loadTemplate('portal', { port: String(server.port) });\n fs.writeFileSync(path.join(vaultDir, '_portal.md'), portalContent, 'utf-8');\n } catch { /* non-critical — template may be missing or vault read-only */ }\n\n // Background reindex after migration — runs after server is healthy\n if (needsMigrationReindex) {\n setImmediate(() => {\n logger.info('daemon', 'Rebuilding index after memories→spores migration (background)');\n initFts(index);\n rebuildIndex(index, vaultDir);\n logger.info('daemon', 'Migration reindex complete');\n });\n }\n\n const shutdown = async (signal: string) => {\n logger.info('daemon', `${signal} received`);\n // Wait for any active stop processing to finish before shutting down\n if (activeStopProcessing) {\n logger.info('daemon', 'Waiting for active stop processing to complete...');\n await activeStopProcessing;\n }\n metabolism?.stop();\n clearInterval(pipelineTickTimer);\n pipeline.close();\n planWatcher.stopFileWatcher();\n registry.destroy();\n await server.stop();\n vectorIndex?.close();\n index.close();\n logger.close();\n process.exit(0);\n };\n\n process.on('SIGTERM', () => shutdown('SIGTERM'));\n process.on('SIGINT', () => shutdown('SIGINT'));\n}\n\n"],"mappings":"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","names":["fs","path","relative","resolve","fs","path","fs","path","path","fs","readdir","stat","sp","path","basename","lstat","stat","lstat","stat","main","path","rawEmitter","listener","basename","dirname","newStats","closer","resolve","realpath","stats","relative","path","testString","readdir","stats","stat","now","path","path","path","path","resolve","result","fs","path","basename","path","path","createHash","fs","path","path","fs","createHash","runCuration","fs","path","fs","YAML","path","fs","path","path","runRebuild","fs","import_yaml","fs","path","path","fs","YAML","stat"]}