claude-memory-layer 2.4.5 → 2.4.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/services/lesson-host-service.ts", "../../src/extensions/vector/embedder.ts", "../../src/core/runtime-resource-telemetry.ts", "../../src/adapters/claude/hooks/prompt-injection-policy.ts", "../../src/extensions/mcp/lesson-ranking.ts", "../../src/extensions/mcp/hybrid-lesson-ranking.ts", "../../src/core/privacy/tag-parser.ts", "../../src/core/privacy/filter.ts", "../../src/core/operations/canonical-memory-access-service.ts", "../../src/core/operations/memory-asset-catalog-service.ts", "../../src/core/sqlite-wrapper.ts", "../../src/core/sqlite-read-snapshot.ts", "../../src/core/operations/memory-asset-permission-service.ts", "../../src/core/operations/governance-audit.ts", "../../src/core/operations/memory-asset-repository.ts", "../../src/core/operations/memory-asset-permissions.ts", "../../src/core/operations/canonical-memory-injection-service.ts", "../../src/core/operations/lesson-repository.ts", "../../src/core/types.ts", "../../src/core/ingest-source-clocks.ts", "../../src/core/retrieval-rollout.ts", "../../src/core/sqlite-event-store.ts", "../../src/core/canonical-key.ts", "../../src/core/citation-generator.ts", "../../src/core/registry/project-path.ts", "../../src/core/registry/git-utils.ts", "../../src/core/markdown-mirror.ts", "../../src/core/db-wrapper.ts", "../../src/core/vector-outbox.ts", "../../src/core/retrieval-debug-lanes.ts", "../../src/core/usefulness-evidence.ts", "../../src/core/retrieval-telemetry.ts", "../../src/core/usefulness-outcome-v2.ts", "../../src/core/memory-ref.ts", "../../src/core/retrieval-navigation.ts", "../../src/core/retrieval-trace-ledger.ts"],
4
- "sourcesContent": ["import { createHash, randomUUID } from 'crypto';\nimport { isAbsolute, join } from 'path';\nimport { z } from 'zod';\n\nimport { rankCuratedLessonsHybrid } from '../extensions/mcp/hybrid-lesson-ranking.js';\nimport { applyPrivacyFilter } from '../core/privacy/index.js';\nimport { CanonicalMemoryAccessService } from '../core/operations/canonical-memory-access-service.js';\nimport { CanonicalMemoryInjectionService } from '../core/operations/canonical-memory-injection-service.js';\nimport { LessonRepository } from '../core/operations/lesson-repository.js';\nimport { writeGovernanceAuditEntrySync } from '../core/operations/governance-audit.js';\nimport type { MemoryEvent, MemoryLesson } from '../core/types.js';\nimport { sqliteAll, sqliteGet, sqliteRun, type SQLiteDatabase } from '../core/sqlite-wrapper.js';\nimport { SQLiteEventStore } from '../core/sqlite-event-store.js';\nimport { getProjectStoragePath, hashProjectPath, normalizeProjectPath } from '../core/registry/project-path.js';\n\n// Hosts must check this installed-artifact capability before suppressing native lessons.\nexport const LESSON_HOST_CAPABILITIES = Object.freeze({ version: 1, nativeLessonOwnerMarker: true });\n\nconst Identifier = z.string().trim().min(1).max(240);\nconst Hash = z.string().regex(/^[a-f0-9]{64}$/i, 'payloadHash must be a SHA-256 hex digest');\nconst CandidatePayload = z.object({\n name: Identifier,\n trigger: Identifier,\n steps: z.array(Identifier).min(1).max(20),\n confidence: z.number().min(0).max(1),\n sourceSessionIds: z.array(Identifier).max(100),\n sourceEventIds: z.array(Identifier).min(1).max(100),\n failureModes: z.array(Identifier).max(20).default([]),\n skillCandidate: z.boolean().default(false),\n scope: Identifier,\n validation: z.array(Identifier).min(1).max(20),\n reconsiderWhen: Identifier,\n validVersions: z.array(Identifier).max(20).optional()\n}).strict();\nconst BaseRequest = z.object({ version: z.number().int(), requestId: Identifier, binding: z.unknown() }).strict();\nconst MutationBase = BaseRequest.extend({ generation: z.number().int().nonnegative() }).strict();\nconst CandidateMutation = MutationBase.extend({\n candidateId: Identifier,\n expectedRevision: z.number().int().positive(),\n payloadHash: Hash\n}).strict();\n\nexport interface VerifiedLessonHostBinding {\n projectHash: string;\n actorId: string;\n userId: string;\n machineId: string;\n sessionId: string;\n generation: number;\n capabilities: readonly ('lesson.read' | 'lesson.review' | 'lesson.manage')[];\n /** Verified host lifecycle state; DTOs cannot assert normal completion. */\n normalEndSessionIds?: readonly string[];\n}\n\nexport interface LessonHostServiceOptions {\n db: SQLiteDatabase;\n verifyBinding(binding: unknown): Promise<VerifiedLessonHostBinding> | VerifiedLessonHostBinding;\n /** Existing canonical ingestion boundary, supplied by openLessonHostService. */\n eventStore?: Pick<SQLiteEventStore, 'importEvents' | 'getSessionEvents'>;\n /** Injectable only for deterministic deadline tests. */\n now?: () => number;\n}\n\nexport interface OpenLessonHostServiceOptions {\n /** Canonical host-resolved project path; never accept this from a renderer DTO. */\n projectPath: string;\n verifyBinding(binding: unknown): Promise<VerifiedLessonHostBinding> | VerifiedLessonHostBinding;\n /** Test-only isolated root. Production uses CML's canonical project store. */\n isolatedStorageRoot?: string;\n}\n\nexport interface OpenLessonHostServiceResult {\n projectHash: string;\n service: LessonHostService;\n close(): Promise<void>;\n}\n\ntype Candidate = z.output<typeof CandidatePayload>;\ntype CandidateStatus = 'pending' | 'reviewed' | 'accepted' | 'rejected' | 'expired';\ninterface CandidateRow {\n candidate_id: string; project_hash: string; evidence_key: string; payload_hash: string;\n payload_json: string; evidence_refs_json: string; status: CandidateStatus; revision: number;\n generation: number; expires_at: string | null; duplicate_lesson_ids_json: string; created_at: string; updated_at: string;\n}\ninterface TraceRow { trace_id: string; project_hash: string; session_id: string; actor_id: string; machine_id: string; turn_id: string; request_id: string; generation: number; lesson_ids_json: string; lesson_revisions_json: string; phase: string; outcome: string; created_at: string; }\n\nfunction stableJson(value: unknown): string {\n if (Array.isArray(value)) return `[${value.map(stableJson).join(',')}]`;\n if (value && typeof value === 'object') {\n return `{${Object.entries(value as Record<string, unknown>).sort(([a], [b]) => a.localeCompare(b)).map(([key, item]) => `${JSON.stringify(key)}:${stableJson(item)}`).join(',')}}`;\n }\n return JSON.stringify(value);\n}\nfunction requestFingerprint(value: unknown): string {\n const { binding: _binding, ...intent } = (value && typeof value === 'object' ? value : {}) as Record<string, unknown>;\n return createHash('sha256').update(stableJson(intent)).digest('hex');\n}\n\nexport function hashLessonCandidatePayload(payload: unknown): string {\n return createHash('sha256').update(stableJson(CandidatePayload.parse(payload))).digest('hex');\n}\n\nfunction parseJson<T>(value: string, fallback: T): T {\n try { return JSON.parse(value) as T; } catch { return fallback; }\n}\nfunction sameBinding(left: VerifiedLessonHostBinding, right: VerifiedLessonHostBinding): boolean {\n return left.projectHash === right.projectHash && left.actorId === right.actorId && left.machineId === right.machineId && left.sessionId === right.sessionId && left.generation === right.generation;\n}\n\nfunction candidateFromRow(row: CandidateRow) {\n return {\n candidateId: row.candidate_id, evidenceKey: row.evidence_key, payloadHash: row.payload_hash,\n status: row.status, revision: row.revision, generation: row.generation,\n expiresAt: row.expires_at, createdAt: row.created_at, updatedAt: row.updated_at,\n evidenceRefs: parseJson<string[]>(row.evidence_refs_json, []), duplicateLessonIds: parseJson<string[]>(row.duplicate_lesson_ids_json, []), candidate: parseJson<Candidate>(row.payload_json, {} as Candidate)\n };\n}\n\nfunction assertCandidateSafe(candidate: Candidate): void {\n const text = [candidate.name, candidate.trigger, candidate.scope, candidate.reconsiderWhen, ...candidate.steps, ...candidate.validation, ...candidate.failureModes, ...(candidate.validVersions ?? [])].join('\\n');\n const privacy = applyPrivacyFilter(text, { excludePatterns: [], anonymize: false, privateTags: { enabled: true, marker: '[PRIVATE]', preserveLineCount: false, supportedFormats: ['xml'] } });\n const environmentSecret = /\\b(?:export\\s+)?[A-Z][A-Z0-9_]*(?:TOKEN|SECRET|PASSWORD|API_KEY)\\s*=\\s*(?!\\$[A-Z_])[\\S]+/;\n const credentialRule = /\\b(?:store|save|persist|remember|reuse|repeat)\\b.{0,80}\\b(?:credential|password|secret|api[ -]?key|access token)\\b|\\b(?:credential|password|secret|api[ -]?key|access token)\\b.{0,80}\\b(?:store|save|persist|remember|reuse|repeat)\\b/i;\n if (privacy.metadata.hasPrivateTags || privacy.metadata.hasUnmatchedTags || privacy.metadata.patternMatchCount > 0 || environmentSecret.test(text) || credentialRule.test(text) || /ignore (all )?previous instructions|system prompt|developer message/i.test(text)) {\n throw new Error('candidate contains private, credential-like, or forbidden instruction content');\n }\n}\n\nexport class LessonHostService {\n constructor(private readonly options: LessonHostServiceOptions) {}\n\n async recall(input: unknown) {\n const request = BaseRequest.extend({ turnId: Identifier, query: z.string().trim().min(1).max(8_000), limit: z.number().int().min(1).max(3).default(3) }).strict().parse(input);\n if (request.version !== 1) return { outcome: 'unsupported_version' as const };\n const binding = await this.readBinding(request.binding, 'lesson.read');\n const deadline = this.now() + 900;\n const repo = new LessonRepository(this.options.db);\n const eligible: Array<{ lesson: MemoryLesson; injectionMode: 'direct' | 'summary' | 'reference' }> = [];\n for (let offset = 0; ; offset += 100) {\n if (this.now() >= deadline) return { outcome: 'timeout' as const, lessonIds: [], lessons: [] };\n const page = await repo.list({ projectHash: binding.projectHash, limit: 100, offset });\n if (!page.length) break;\n const allowed = new CanonicalMemoryInjectionService(this.options.db).select({ projectHash: binding.projectHash, actorId: binding.actorId, lane: 'prompt', candidates: page.filter((lesson) => lesson.recallEnabled).map((value) => ({ canonicalType: 'lesson' as const, canonicalId: value.lessonId, value })) }).items;\n for (const item of allowed) eligible.push({ lesson: item.value, injectionMode: item.injectionMode });\n if (this.now() >= deadline) return { outcome: 'timeout' as const, lessonIds: [], lessons: [] };\n if (page.length < 100) break;\n await new Promise<void>((resolve) => setImmediate(resolve));\n }\n if (this.now() >= deadline) return { outcome: 'timeout' as const, lessonIds: [], lessons: [] };\n const selected = await rankCuratedLessonsHybrid(eligible.map(({ lesson }) => lesson), request.query, request.limit);\n const lessons = selected.map((lesson) => ({ lesson, injectionMode: eligible.find((item) => item.lesson.lessonId === lesson.lessonId)!.injectionMode }));\n if (this.now() >= deadline) return { outcome: 'timeout' as const, lessonIds: [], lessons: [] };\n const finalBinding = await this.readBinding(request.binding, 'lesson.read');\n if (!sameBinding(binding, finalBinding)) throw new Error('binding changed during recall');\n if (this.now() >= deadline) return { outcome: 'timeout' as const, lessonIds: [], lessons: [] };\n if (!this.validRecallSelection(lessons, finalBinding)) return { outcome: 'no_match' as const, lessonIds: [], lessons: [] };\n const traceId = randomUUID();\n const response = { outcome: lessons.length ? 'selected' as const : 'no_match' as const, traceId, lessonIds: lessons.map(({ lesson }) => lesson.lessonId), lessons: lessons.map(({ lesson, injectionMode }) => lessonBody(lesson, injectionMode)) };\n const fingerprint = requestFingerprint({ version: request.version, requestId: request.requestId, turnId: request.turnId, query: request.query, limit: request.limit });\n return this.options.db.transaction(() => { const replay = this.idempotent(request.requestId, finalBinding, 'recall', fingerprint); if (replay) return this.validRecallReplay(replay, finalBinding) ? replay : { outcome: 'no_match' as const, lessonIds: [], lessons: [] }; if (!this.validRecallSelection(lessons, finalBinding)) return { outcome: 'no_match' as const, lessonIds: [], lessons: [] }; this.writeTrace({ traceId, requestId: request.requestId, binding: finalBinding, turnId: request.turnId, phase: 'selected', outcome: response.outcome, lessons: lessons.map(({ lesson }) => lesson) }); this.remember(request.requestId, finalBinding, 'recall', fingerprint, response); return response; })();\n }\n\n async get(input: unknown) {\n const request = BaseRequest.extend({ lessonId: Identifier }).strict().parse(input);\n if (request.version !== 1) return { outcome: 'unsupported_version' as const };\n const binding = await this.readBinding(request.binding, 'lesson.read');\n const lesson = new LessonRepository(this.options.db).get(request.lessonId);\n if (!lesson || lesson.projectHash !== binding.projectHash || !this.canReadLesson(binding, lesson.lessonId)) return { outcome: 'not_found' as const };\n const response = { outcome: 'found' as const, lesson: lessonBody(lesson) };\n const fingerprint = requestFingerprint(request); return this.options.db.transaction(() => { const replay = this.idempotent(request.requestId, binding, 'get', fingerprint); if (replay) { const cached = replay as { lesson?: { lessonId?: string; revision?: number } }; return cached.lesson?.lessonId === lesson.lessonId && cached.lesson.revision === lesson.revision ? replay : { outcome: 'not_found' as const }; } this.writeTrace({ traceId: randomUUID(), requestId: request.requestId, binding, phase: 'read', outcome: 'read', lessons: [lesson] }); this.remember(request.requestId, binding, 'get', fingerprint, response); return response; })();\n }\n\n async recordRead(input: unknown) {\n const request = BaseRequest.extend({ lessonId: Identifier }).strict().parse(input);\n if (request.version !== 1) return { outcome: 'unsupported_version' as const };\n const binding = await this.readBinding(request.binding, 'lesson.read');\n const lesson = new LessonRepository(this.options.db).get(request.lessonId);\n if (!lesson || lesson.projectHash !== binding.projectHash || !this.canReadLesson(binding, lesson.lessonId)) return { outcome: 'not_found' as const };\n const traceId = randomUUID(); const response = { outcome: 'read' as const, traceId };\n const fingerprint = requestFingerprint(request); return this.options.db.transaction(() => { const replay = this.idempotent(request.requestId, binding, 'read', fingerprint); if (replay) return replay; this.writeTrace({ traceId, requestId: request.requestId, binding, phase: 'read', outcome: 'read', lessons: [lesson] }); this.remember(request.requestId, binding, 'read', fingerprint, response); return response; })();\n }\n\n async ackDelivery(input: unknown) {\n const request = BaseRequest.extend({ turnId: Identifier, traceId: Identifier, lessonIds: z.array(Identifier).max(3), lessonRevisions: z.array(z.object({ lessonId: Identifier, revision: z.number().int().positive() }).strict()).max(3) }).strict().parse(input);\n if (request.version !== 1) return { outcome: 'unsupported_version' as const };\n const binding = await this.readBinding(request.binding, 'lesson.read');\n const selected = sqliteGet<TraceRow>(this.options.db, `SELECT * FROM lesson_host_traces WHERE trace_id = ?`, [request.traceId]);\n const revisions = request.lessonRevisions.map(({ lessonId, revision }) => ({ lessonId, revision }));\n const current = revisions.every(({ lessonId, revision }) => { const lesson = new LessonRepository(this.options.db).get(lessonId); return lesson?.projectHash === binding.projectHash && lesson.revision === revision; });\n if (!selected || selected.project_hash !== binding.projectHash || selected.session_id !== binding.sessionId || selected.actor_id !== binding.actorId || selected.machine_id !== binding.machineId || selected.generation !== binding.generation || selected.turn_id !== request.turnId || selected.phase !== 'selected' || JSON.stringify(parseJson<string[]>(selected.lesson_ids_json, [])) !== JSON.stringify(request.lessonIds) || JSON.stringify(parseJson(selected.lesson_revisions_json, [])) !== JSON.stringify(revisions) || !current) return { outcome: 'invalid_ack' as const };\n const response = { outcome: 'delivered' as const, traceId: request.traceId };\n const fingerprint = requestFingerprint(request); return this.options.db.transaction(() => { const replay = this.idempotent(request.requestId, binding, 'delivered', fingerprint); if (replay) return replay; this.writeTrace({ traceId: randomUUID(), requestId: request.requestId, binding, turnId: request.turnId, phase: 'delivered', outcome: 'delivered', lessons: revisions.map(({ lessonId }) => new LessonRepository(this.options.db).get(lessonId)!) }); this.remember(request.requestId, binding, 'delivered', fingerprint, response); return response; })();\n }\n\n async enqueueCandidate(input: unknown) {\n const request = MutationBase.extend({ evidenceKey: Identifier, payloadHash: Hash.optional(), candidate: CandidatePayload, expiresAt: z.string().datetime().optional() }).strict().parse(input);\n if (request.version !== 1) return { outcome: 'unsupported_version' as const };\n const binding = await this.writeBinding(request.binding, request.generation, 'lesson.review');\n const candidate = CandidatePayload.parse(request.candidate); assertCandidateSafe(candidate); this.assertSourceEvents(binding.projectHash, candidate.sourceEventIds, candidate.sourceSessionIds);\n const computedHash = hashLessonCandidatePayload(candidate);\n if (request.payloadHash && request.payloadHash !== computedHash) throw new Error('payloadHash does not match canonical candidate payload');\n const fingerprint = requestFingerprint({ ...request, payloadHash: computedHash });\n return this.options.db.transaction(() => {\n const replay = this.idempotent(request.requestId, binding, 'enqueue', fingerprint); if (replay) return replay;\n this.expireCandidates(binding.projectHash);\n const existing = sqliteGet<CandidateRow>(this.options.db, `SELECT * FROM lesson_review_candidates WHERE project_hash = ? AND evidence_key = ?`, [binding.projectHash, request.evidenceKey]);\n if (!existing && sqliteGet<{ count: number }>(this.options.db, `SELECT COUNT(*) AS count FROM lesson_review_candidates WHERE project_hash=? AND status IN ('pending','reviewed')`, [binding.projectHash])!.count >= 20) throw new Error('pending candidate cap reached');\n const result = existing ? candidateFromRow(existing) : this.insertCandidate(binding, request.evidenceKey, computedHash, candidate, request.expiresAt);\n const response = { outcome: result.status, ...result }; this.remember(request.requestId, binding, 'enqueue', fingerprint, response); return response;\n })();\n }\n\n async appendNormalEndEvidence(input: unknown) {\n const request = MutationBase.extend({ evidenceKey: Identifier, sessionId: Identifier, content: z.string().trim().min(1).max(8_000), occurredAt: z.string().datetime().optional() }).strict().parse(input);\n if (request.version !== 1) return { outcome: 'unsupported_version' as const };\n const binding = await this.writeBinding(request.binding, request.generation, 'lesson.review');\n if (!this.options.eventStore || request.sessionId !== binding.sessionId || !binding.normalEndSessionIds?.includes(request.sessionId)) throw new Error('verified normal session completion is required');\n const filtered = applyPrivacyFilter(request.content, { excludePatterns: [], anonymize: false, privateTags: { enabled: true, marker: '[PRIVATE]', preserveLineCount: false, supportedFormats: ['xml'] } });\n if (filtered.metadata.hasPrivateTags || filtered.metadata.hasUnmatchedTags || /\\[PRIVATE\\]/.test(filtered.content) || Buffer.byteLength(filtered.content, 'utf8') > 8_000 || filtered.content.length === 0) throw new Error('evidence is not safely appendable');\n const fingerprint = requestFingerprint({ ...request, content: filtered.content });\n const replay = this.idempotent(request.requestId, binding, 'append-normal-end-evidence', fingerprint); if (replay) return replay;\n const contentHash = createHash('sha256').update(filtered.content).digest('hex');\n const prior = (await this.options.eventStore.getSessionEvents(request.sessionId)).find((event) => (event.metadata as { evidenceKey?: string; contentHash?: string } | undefined)?.evidenceKey === request.evidenceKey);\n if (prior) {\n if ((prior.metadata as { contentHash?: string } | undefined)?.contentHash !== contentHash || (prior.metadata as { scope?: { project?: { hash?: string } } } | undefined)?.scope?.project?.hash !== binding.projectHash) throw new Error('evidenceKey payload conflict');\n const response = { outcome: 'persisted' as const, eventId: prior.id, evidenceKey: request.evidenceKey, redacted: filtered.content !== request.content };\n this.options.db.transaction(() => this.remember(request.requestId, binding, 'append-normal-end-evidence', fingerprint, response))(); return response;\n }\n const finalBinding = await this.writeBinding(request.binding, request.generation, 'lesson.review');\n const eventId = randomUUID();\n const event: MemoryEvent = { id: eventId, eventType: 'tool_observation', sessionId: request.sessionId, timestamp: request.occurredAt ? new Date(request.occurredAt) : new Date(), content: filtered.content, canonicalKey: `host-normal-end:${finalBinding.projectHash}:${request.evidenceKey}`, dedupeKey: `host-normal-end:${finalBinding.projectHash}:${request.evidenceKey}`, metadata: { scope: { project: { hash: finalBinding.projectHash } }, source: 'lesson-host-normal-end', evidenceKey: request.evidenceKey, contentHash } };\n const persisted = await this.options.eventStore.importEvents([event]);\n if (persisted.inserted !== 1) throw new Error('evidenceKey already exists without a recoverable host idempotency record');\n const response = { outcome: 'persisted' as const, eventId, evidenceKey: request.evidenceKey, redacted: filtered.content !== request.content };\n this.options.db.transaction(() => { this.remember(request.requestId, binding, 'append-normal-end-evidence', fingerprint, response); })();\n return response;\n }\n\n async markReviewed(input: unknown) { return this.transition(input, 'reviewed', 'lesson.review'); }\n async rejectCandidate(input: unknown) { return this.transition(input, 'rejected', 'lesson.manage'); }\n\n async approveCandidate(input: unknown) {\n const request = CandidateMutation.parse(input);\n if (request.version !== 1) return { outcome: 'unsupported_version' as const };\n await this.writeBinding(request.binding, request.generation, 'lesson.manage');\n const fingerprint = requestFingerprint(request);\n // The final verifier call is immediately followed by the synchronous SQLite transaction.\n const finalBinding = await this.writeBinding(request.binding, request.generation, 'lesson.manage');\n const transaction = this.options.db.transaction(() => {\n const replay = this.idempotent(request.requestId, finalBinding, 'approve', fingerprint); if (replay) return replay;\n const row = this.requireCandidate(request.candidateId, finalBinding, request.expectedRevision, request.payloadHash, 'reviewed', false);\n const candidate = CandidatePayload.parse(parseJson(row.payload_json, {})); assertCandidateSafe(candidate); this.assertSourceEvents(finalBinding.projectHash, candidate.sourceEventIds, candidate.sourceSessionIds);\n const existing = sqliteGet<{ lesson_id: string; revision: number; recall_enabled: number }>(this.options.db, `SELECT lesson_id, revision, recall_enabled FROM memory_lessons WHERE project_hash = ? AND name = ?`, [finalBinding.projectHash, candidate.name]);\n if (existing) { const error = new Error('existing lesson requires an explicit merge proposal and lesson revision CAS') as Error & { code?: string }; error.code = 'merge_required'; throw error; }\n const now = new Date().toISOString(); const lessonId = randomUUID();\n sqliteRun(this.options.db, `INSERT INTO memory_lessons (lesson_id, project_hash, name, trigger, steps_json, confidence, source_session_ids, source_event_ids, failure_modes_json, skill_candidate, source_class, revision, recall_enabled, scope, validation_json, reconsider_when, valid_versions_json, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'curated', 1, 1, ?, ?, ?, ?, ?, ?)`, [lessonId, finalBinding.projectHash, candidate.name, candidate.trigger, JSON.stringify(candidate.steps), candidate.confidence, JSON.stringify(candidate.sourceSessionIds), JSON.stringify(candidate.sourceEventIds), JSON.stringify(candidate.failureModes), candidate.skillCandidate ? 1 : 0, candidate.scope, JSON.stringify(candidate.validation), candidate.reconsiderWhen, JSON.stringify(candidate.validVersions ?? []), now, now]);\n writeGovernanceAuditEntrySync(this.options.db, { operation: 'lesson_promote', actor: finalBinding.actorId, projectHash: finalBinding.projectHash, targetType: 'lesson', targetId: lessonId, afterJson: { lessonId, name: candidate.name, trigger: candidate.trigger, steps: candidate.steps, sourceClass: 'curated' }, sourceEventIds: candidate.sourceEventIds });\n const changed = sqliteRun(this.options.db, `UPDATE lesson_review_candidates SET status='accepted', revision=revision+1, updated_at=? WHERE candidate_id=? AND project_hash=? AND revision=? AND payload_hash=? AND status='reviewed'`, [now, row.candidate_id, finalBinding.projectHash, request.expectedRevision, request.payloadHash]);\n if (changed.changes !== 1) throw new Error('candidate changed before approval');\n const lesson = new LessonRepository(this.options.db).get(lessonId)!;\n const result = { outcome: 'accepted' as const, candidateId: row.candidate_id, lessonId, lessonRevision: lesson.revision }; this.remember(request.requestId, finalBinding, 'approve', fingerprint, result); return result;\n });\n return transaction();\n }\n\n async setRecallEnabled(input: unknown) {\n const request = MutationBase.extend({ lessonId: Identifier, expectedRevision: z.number().int().positive(), enabled: z.boolean() }).strict().parse(input);\n if (request.version !== 1) return { outcome: 'unsupported_version' as const };\n await this.writeBinding(request.binding, request.generation, 'lesson.manage');\n const binding = await this.writeBinding(request.binding, request.generation, 'lesson.manage');\n const fingerprint = requestFingerprint(request);\n return this.options.db.transaction(() => {\n const replay = this.idempotent(request.requestId, binding, 'set-recall', fingerprint); if (replay) return replay;\n const result = new LessonRepository(this.options.db).setRecallEnabled({ lessonId: request.lessonId, projectHash: binding.projectHash, expectedRevision: request.expectedRevision, enabled: request.enabled });\n if (!result) throw new Error('lesson revision conflict or lesson not found');\n const response = { outcome: 'updated' as const, lessonId: result.lessonId, revision: result.revision, recallEnabled: result.recallEnabled };\n this.remember(request.requestId, binding, 'set-recall', fingerprint, response); return response;\n })();\n }\n\n async listCandidates(input: unknown) {\n const request = BaseRequest.extend({ limit: z.number().int().min(1).max(100).default(100), offset: z.number().int().nonnegative().default(0) }).strict().parse(input); if (request.version !== 1) return { outcome: 'unsupported_version' as const };\n const binding = await this.readBinding(request.binding, 'lesson.manage'); this.expireCandidates(binding.projectHash);\n const rows = sqliteAll<CandidateRow>(this.options.db, `SELECT * FROM lesson_review_candidates WHERE project_hash = ? ORDER BY updated_at DESC LIMIT ? OFFSET ?`, [binding.projectHash, request.limit + 1, request.offset]);\n return { outcome: 'ok' as const, candidates: rows.slice(0, request.limit).map(candidateFromRow), nextOffset: rows.length > request.limit ? request.offset + request.limit : null };\n }\n\n async reviewStatus(input: unknown) {\n const request = BaseRequest.extend({ candidateId: Identifier }).strict().parse(input); if (request.version !== 1) return { outcome: 'unsupported_version' as const };\n const binding = await this.readBinding(request.binding, 'lesson.manage'); this.expireCandidates(binding.projectHash);\n const candidate = sqliteGet<CandidateRow>(this.options.db, `SELECT * FROM lesson_review_candidates WHERE candidate_id=? AND project_hash=?`, [request.candidateId, binding.projectHash]);\n return candidate ? { outcome: 'found' as const, candidate: candidateFromRow(candidate) } : { outcome: 'not_found' as const };\n }\n\n async listLessons(input: unknown) {\n const request = BaseRequest.extend({ limit: z.number().int().min(1).max(100).default(100), offset: z.number().int().nonnegative().default(0) }).strict().parse(input); if (request.version !== 1) return { outcome: 'unsupported_version' as const };\n const binding = await this.readBinding(request.binding, 'lesson.manage'); const lessons = await new LessonRepository(this.options.db).list({ projectHash: binding.projectHash, limit: request.limit + 1, offset: request.offset });\n return { outcome: 'ok' as const, lessons: lessons.slice(0, request.limit).map((lesson) => { const traces = sqliteAll<{ phase: string; created_at: string }>(this.options.db, `SELECT t.phase, t.created_at FROM lesson_host_traces t JOIN json_each(t.lesson_ids_json) ids ON ids.value=? WHERE t.project_hash=? ORDER BY t.created_at DESC`, [lesson.lessonId, binding.projectHash]); const latest = (phase: string) => traces.find((trace) => trace.phase === phase)?.created_at ?? null; return { lessonId: lesson.lessonId, name: lesson.name, trigger: lesson.trigger, steps: lesson.steps, failureModes: lesson.failureModes, scope: lesson.scope, validation: lesson.validation, reconsiderWhen: lesson.reconsiderWhen, validVersions: lesson.validVersions, revision: lesson.revision, recallEnabled: lesson.recallEnabled, sourceSessionIds: lesson.sourceSessionIds, sourceEventIds: lesson.sourceEventIds, createdAt: lesson.createdAt.toISOString(), updatedAt: lesson.updatedAt.toISOString(), lastSelectedAt: latest('selected'), lastDeliveredAt: latest('delivered'), lastReadAt: latest('read') }; }), nextOffset: lessons.length > request.limit ? request.offset + request.limit : null };\n }\n\n async listTraces(input: unknown) {\n const request = BaseRequest.extend({ limit: z.number().int().min(1).max(100).default(100), offset: z.number().int().nonnegative().default(0) }).strict().parse(input); if (request.version !== 1) return { outcome: 'unsupported_version' as const };\n const binding = await this.readBinding(request.binding, 'lesson.manage');\n const rows = sqliteAll<TraceRow>(this.options.db, `SELECT trace_id, project_hash, session_id, actor_id, machine_id, turn_id, request_id, generation, lesson_ids_json, lesson_revisions_json, phase, outcome, created_at FROM lesson_host_traces WHERE project_hash=? ORDER BY created_at DESC LIMIT ? OFFSET ?`, [binding.projectHash, request.limit + 1, request.offset]);\n return { outcome: 'ok' as const, traces: rows.slice(0, request.limit).map((row) => ({ traceId: row.trace_id, requestId: row.request_id, sessionId: row.session_id, actorId: row.actor_id, machineId: row.machine_id, turnId: row.turn_id, generation: row.generation, phase: row.phase, outcome: row.outcome, lessonIds: parseJson<string[]>(row.lesson_ids_json, []), lessonRevisions: parseJson<Array<{ lessonId: string; revision: number }>>(row.lesson_revisions_json, []), createdAt: row.created_at })), nextOffset: rows.length > request.limit ? request.offset + request.limit : null };\n }\n\n private async transition(input: unknown, target: 'reviewed' | 'rejected', capability: 'lesson.review' | 'lesson.manage') {\n const request = CandidateMutation.parse(input); if (request.version !== 1) return { outcome: 'unsupported_version' as const };\n const binding = await this.writeBinding(request.binding, request.generation, capability); const fingerprint = requestFingerprint(request);\n const current = target === 'reviewed' ? 'pending' : 'reviewed'; const now = new Date().toISOString(); await this.writeBinding(request.binding, request.generation, capability);\n return this.options.db.transaction(() => {\n const replay = this.idempotent(request.requestId, binding, target, fingerprint); if (replay) return replay;\n const requireGeneration = target === 'reviewed';\n this.requireCandidate(request.candidateId, binding, request.expectedRevision, request.payloadHash, current, requireGeneration);\n const changed = requireGeneration\n ? sqliteRun(this.options.db, `UPDATE lesson_review_candidates SET status=?, revision=revision+1, updated_at=? WHERE candidate_id=? AND project_hash=? AND revision=? AND payload_hash=? AND generation=? AND status=?`, [target, now, request.candidateId, binding.projectHash, request.expectedRevision, request.payloadHash, binding.generation, current])\n : sqliteRun(this.options.db, `UPDATE lesson_review_candidates SET status=?, revision=revision+1, updated_at=? WHERE candidate_id=? AND project_hash=? AND revision=? AND payload_hash=? AND status=?`, [target, now, request.candidateId, binding.projectHash, request.expectedRevision, request.payloadHash, current]);\n if (changed.changes !== 1) throw new Error('candidate revision, generation, or status conflict');\n const result = candidateFromRow(sqliteGet<CandidateRow>(this.options.db, `SELECT * FROM lesson_review_candidates WHERE candidate_id = ?`, [request.candidateId])!); const response = { outcome: target, ...result }; this.remember(request.requestId, binding, target, fingerprint, response); return response;\n })();\n }\n\n private async readBinding(token: unknown, capability: VerifiedLessonHostBinding['capabilities'][number]) { const binding = await this.options.verifyBinding(token); this.assertBinding(binding, capability); return binding; }\n private async writeBinding(token: unknown, generation: number, capability: VerifiedLessonHostBinding['capabilities'][number]) { const binding = await this.readBinding(token, capability); if (binding.generation !== generation) throw new Error('binding generation mismatch'); return binding; }\n private assertBinding(binding: VerifiedLessonHostBinding, capability: string) { if (!Identifier.safeParse(binding.projectHash).success || !Identifier.safeParse(binding.actorId).success || !binding.capabilities.includes(capability as never)) throw new Error('untrusted or unauthorized host binding'); }\n private canReadLesson(binding: VerifiedLessonHostBinding, lessonId: string): boolean { try { return new CanonicalMemoryAccessService(this.options.db).check({ projectHash: binding.projectHash, canonicalType: 'lesson', canonicalId: lessonId, requesterActorId: binding.actorId, permission: 'read' }).allowed; } catch { return false; } }\n private assertSourceEvents(projectHash: string, ids: string[], sourceSessionIds?: string[]) { const rows = sqliteAll<{ id: string; session_id: string; metadata: string }>(this.options.db, `SELECT id, session_id, metadata FROM events WHERE id IN (${ids.map(() => '?').join(',')})`, ids); if (rows.length !== ids.length) throw new Error('source event refs are unavailable'); for (const row of rows) { const metadata = parseJson<Record<string, unknown>>(row.metadata, {}); if ((metadata.scope as { project?: { hash?: string } } | undefined)?.project?.hash !== projectHash) throw new Error('source event project mismatch'); } if (sourceSessionIds) { const expected = new Set(rows.map((row) => row.session_id)); if (sourceSessionIds.length !== expected.size || sourceSessionIds.some((id) => !expected.has(id))) throw new Error('source session refs do not match source events'); } }\n private insertCandidate(binding: VerifiedLessonHostBinding, evidenceKey: string, payloadHash: string, candidate: Candidate, expiresAt?: string) { const candidateId = randomUUID(); const now = new Date().toISOString(); const maxExpiry = new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(); const expires = expiresAt && expiresAt < maxExpiry ? expiresAt : maxExpiry; const duplicateLessonIds = this.findDuplicateLessonIds(binding.projectHash, candidate); sqliteRun(this.options.db, `INSERT INTO lesson_review_candidates (candidate_id, project_hash, evidence_key, payload_hash, payload_json, evidence_refs_json, duplicate_lesson_ids_json, status, revision, generation, expires_at, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, 'pending', 1, ?, ?, ?, ?)`, [candidateId, binding.projectHash, evidenceKey, payloadHash, stableJson(candidate), JSON.stringify(candidate.sourceEventIds), JSON.stringify(duplicateLessonIds), binding.generation, expires, now, now]); return candidateFromRow(sqliteGet<CandidateRow>(this.options.db, `SELECT * FROM lesson_review_candidates WHERE candidate_id = ?`, [candidateId])!); }\n private requireCandidate(id: string, binding: VerifiedLessonHostBinding, revision: number, hash: string, status: CandidateStatus, requireGeneration: boolean) { const row = sqliteGet<CandidateRow>(this.options.db, `SELECT * FROM lesson_review_candidates WHERE candidate_id = ?`, [id]); if (!row || row.project_hash !== binding.projectHash || row.revision !== revision || row.payload_hash !== hash || row.status !== status || (requireGeneration && row.generation !== binding.generation)) throw new Error('candidate revision, generation, payload, or status conflict'); if (row.expires_at && row.expires_at <= new Date().toISOString()) { sqliteRun(this.options.db, `UPDATE lesson_review_candidates SET status='expired', revision=revision+1, updated_at=? WHERE candidate_id=?`, [new Date().toISOString(), id]); throw new Error('candidate has expired'); } return row; }\n private now(): number { return this.options.now?.() ?? Date.now(); }\n private validRecallReplay(replay: unknown, binding: VerifiedLessonHostBinding): boolean { const body = replay as { lessons?: Array<{ lessonId?: string; revision?: number; injectionMode?: 'direct' | 'summary' | 'reference' }> }; if (!Array.isArray(body.lessons)) return false; const current = body.lessons.map((item) => typeof item.lessonId === 'string' ? new LessonRepository(this.options.db).get(item.lessonId) : undefined); if (current.some((lesson, index) => !lesson || lesson.revision !== body.lessons![index]!.revision)) return false; return this.validRecallSelection(current.map((lesson, index) => ({ lesson: lesson!, injectionMode: body.lessons![index]!.injectionMode ?? 'direct' })), binding); }\n private validRecallSelection(selection: Array<{ lesson: MemoryLesson; injectionMode: 'direct' | 'summary' | 'reference' }>, binding: VerifiedLessonHostBinding): boolean { const current = selection.map(({ lesson }) => new LessonRepository(this.options.db).get(lesson.lessonId)); if (current.some((lesson, index) => !lesson || lesson.projectHash !== binding.projectHash || lesson.revision !== selection[index]!.lesson.revision || !lesson.recallEnabled || !this.canReadLesson(binding, lesson.lessonId))) return false; const allowed = new CanonicalMemoryInjectionService(this.options.db).select({ projectHash: binding.projectHash, actorId: binding.actorId, lane: 'prompt', candidates: current.map((lesson) => ({ canonicalType: 'lesson' as const, canonicalId: lesson!.lessonId, value: lesson! })) }).items; return allowed.length === selection.length && selection.every(({ lesson, injectionMode }) => allowed.some((item) => item.value.lessonId === lesson.lessonId && item.injectionMode === injectionMode)); }\n private findDuplicateLessonIds(projectHash: string, candidate: Candidate): string[] { const terms = new Set(`${candidate.name} ${candidate.trigger}`.toLowerCase().match(/[a-z0-9\uAC00-\uD7A3]{2,}/g) ?? []); return sqliteAll<{ lesson_id: string; name: string; trigger: string }>(this.options.db, `SELECT lesson_id, name, trigger FROM memory_lessons WHERE project_hash=?`, [projectHash]).filter((lesson) => { const other = new Set(`${lesson.name} ${lesson.trigger}`.toLowerCase().match(/[a-z0-9\uAC00-\uD7A3]{2,}/g) ?? []); let overlap = 0; for (const term of terms) if (other.has(term)) overlap += 1; return lesson.name === candidate.name || overlap >= 2 && overlap / Math.max(terms.size, other.size) >= 0.5; }).map((lesson) => lesson.lesson_id); }\n private expireCandidates(projectHash: string) { sqliteRun(this.options.db, `UPDATE lesson_review_candidates SET status='expired', revision=revision+1, updated_at=? WHERE project_hash=? AND status IN ('pending','reviewed') AND expires_at IS NOT NULL AND expires_at <= ?`, [new Date().toISOString(), projectHash, new Date().toISOString()]); }\n private writeTrace(input: { traceId: string; requestId: string; binding: VerifiedLessonHostBinding; turnId?: string; phase: string; outcome: string; lessons: MemoryLesson[] }) { sqliteRun(this.options.db, `INSERT INTO lesson_host_traces (trace_id, project_hash, session_id, actor_id, machine_id, generation, turn_id, request_id, phase, outcome, lesson_ids_json, lesson_revisions_json, query_text, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?)`, [input.traceId, input.binding.projectHash, input.binding.sessionId, input.binding.actorId, input.binding.machineId, input.binding.generation, input.turnId ?? null, input.requestId, input.phase, input.outcome, JSON.stringify(input.lessons.map((lesson) => lesson.lessonId)), JSON.stringify(input.lessons.map((lesson) => ({ lessonId: lesson.lessonId, revision: lesson.revision }))), new Date().toISOString()]); }\n private idempotent(requestId: string, binding: VerifiedLessonHostBinding, operation: string, fingerprint: string): unknown | null { const row = sqliteGet<{ operation: string; fingerprint: string; result_json: string }>(this.options.db, `SELECT operation, fingerprint, result_json FROM lesson_host_idempotency WHERE project_hash=? AND actor_id=? AND request_id=?`, [binding.projectHash, binding.actorId, requestId]); if (!row) return null; if (row.operation !== operation || row.fingerprint !== fingerprint) throw new Error('requestId payload conflict'); return parseJson(row.result_json, null); }\n private remember(requestId: string, binding: VerifiedLessonHostBinding, operation: string, fingerprint: string, result: unknown) { sqliteRun(this.options.db, `INSERT INTO lesson_host_idempotency (project_hash, actor_id, request_id, operation, fingerprint, result_json, created_at) VALUES (?, ?, ?, ?, ?, ?, ?)`, [binding.projectHash, binding.actorId, requestId, operation, fingerprint, JSON.stringify(result), new Date().toISOString()]); }\n}\n\nfunction lessonBody(lesson: MemoryLesson, injectionMode: 'direct' | 'summary' | 'reference' = 'direct') { if (injectionMode === 'reference') return { lessonId: lesson.lessonId, revision: lesson.revision, name: lesson.name, injectionMode }; if (injectionMode === 'summary') return { lessonId: lesson.lessonId, revision: lesson.revision, name: lesson.name, trigger: lesson.trigger, steps: lesson.steps.slice(0, 2), scope: lesson.scope, validation: lesson.validation, reconsiderWhen: lesson.reconsiderWhen, validVersions: lesson.validVersions, truncated: lesson.steps.length > 2 || lesson.failureModes.length > 0, detailReference: 'mem-lesson-get', injectionMode }; return { lessonId: lesson.lessonId, revision: lesson.revision, name: lesson.name, trigger: lesson.trigger, steps: lesson.steps, failureModes: lesson.failureModes, scope: lesson.scope, validation: lesson.validation, reconsiderWhen: lesson.reconsiderWhen, validVersions: lesson.validVersions, sourceSessionIds: lesson.sourceSessionIds, sourceEventIds: lesson.sourceEventIds, injectionMode }; }\nexport function createLessonHostService(options: LessonHostServiceOptions): LessonHostService { return new LessonHostService(options); }\n\n/**\n * Stable host-only opening boundary. Desktop/Happy supplies the canonical\n * project path after its own IPC/auth checks; renderer/model DTOs never open a\n * store. The optional isolated root exists solely for fixture stores.\n */\nexport async function openLessonHostService(options: OpenLessonHostServiceOptions): Promise<OpenLessonHostServiceResult> {\n if (!isAbsolute(options.projectPath)) throw new Error('host projectPath must be absolute');\n const projectPath = normalizeProjectPath(options.projectPath);\n const projectHash = hashProjectPath(projectPath);\n if (options.isolatedStorageRoot !== undefined && !isAbsolute(options.isolatedStorageRoot)) throw new Error('isolatedStorageRoot must be absolute');\n const storagePath = options.isolatedStorageRoot ? join(options.isolatedStorageRoot, projectHash) : getProjectStoragePath(projectPath);\n const store = new SQLiteEventStore(join(storagePath, 'events.sqlite'));\n await store.initialize();\n return { projectHash, service: createLessonHostService({ db: store.getDatabase(), verifyBinding: options.verifyBinding, eventStore: store }), close: async () => store.close() };\n}\n", "/**\n * Local Embedding Generator using @huggingface/transformers\n * AXIOMMIND Principle 7: Standard JSON format for vectors\n */\n\nimport { existsSync, readFileSync } from 'node:fs';\nimport { createRequire as createNodeRequire } from 'node:module';\nimport { dirname as pathDirname, join, parse } from 'node:path';\nimport { fileURLToPath as urlToFilePath, pathToFileURL } from 'node:url';\nimport {\n getRuntimeResourceTelemetry,\n opaqueBackendId,\n type RuntimeModelReleaseReason\n} from '../../core/runtime-resource-telemetry.js';\n\nexport interface EmbeddingResult {\n vector: number[];\n model: string;\n dimensions: number;\n}\n\ntype FeatureExtractionPipelineFactory = (\n task: 'feature-extraction',\n model: string\n) => Promise<NonNullable<Embedder['pipeline']>>;\n\nexport interface EmbeddingLifecycleTelemetry {\n recordModelLoad(resourceId: string, backendId: string, durationMs: number): void;\n recordModelLoadFailure(durationMs: number): void;\n recordModelActivity(): void;\n recordModelRelease(resourceId: string, reason: RuntimeModelReleaseReason): void;\n recordModelReleaseFailure(): void;\n}\n\nexport interface EmbedderOptions {\n telemetry?: EmbeddingLifecycleTelemetry;\n now?: () => number;\n loadPipeline?: () => Promise<FeatureExtractionPipelineFactory>;\n}\n\nexport const DEFAULT_EMBEDDING_MODEL = 'Xenova/multilingual-e5-small';\nexport const DEFAULT_EMBEDDING_FALLBACK_MODEL = 'intfloat/multilingual-e5-small';\nconst MANAGED_EMBEDDING_BACKEND_DIR = '.claude-memory-layer-embedding-backend';\nlet embedderResourceSequence = 0;\n\nexport class Embedder {\n private pipeline: (((input: string, options?: Record<string, unknown>) => Promise<{ data: Float32Array }>) & {\n dispose?: () => void | Promise<void>;\n }) | null = null;\n private readonly modelName: string;\n private activeModelName: string;\n private initialized = false;\n private initializationPromise: Promise<void> | null = null;\n private readonly telemetry: EmbeddingLifecycleTelemetry;\n private readonly now: () => number;\n private readonly loadPipeline: () => Promise<FeatureExtractionPipelineFactory>;\n private readonly resourceId: string;\n\n constructor(modelName: string = DEFAULT_EMBEDDING_MODEL, options: EmbedderOptions = {}) {\n this.modelName = modelName;\n this.activeModelName = modelName;\n this.telemetry = options.telemetry ?? getRuntimeResourceTelemetry();\n this.now = options.now ?? Date.now;\n this.loadPipeline = options.loadPipeline ?? loadTransformersPipeline;\n this.resourceId = `embedder-${++embedderResourceSequence}`;\n }\n\n /**\n * Initialize the embedding pipeline\n */\n async initialize(): Promise<void> {\n if (this.initialized) return;\n if (this.initializationPromise) return this.initializationPromise;\n\n const startedAt = this.now();\n this.initializationPromise = this.initializeOnce(startedAt);\n try {\n await this.initializationPromise;\n } finally {\n this.initializationPromise = null;\n }\n }\n\n private async initializeOnce(startedAt: number): Promise<void> {\n let pipeline: FeatureExtractionPipelineFactory;\n try {\n pipeline = await withSuppressedKnownTransformersWarnings(async () => {\n try {\n return await this.loadPipeline();\n } catch (error) {\n if (isMissingTransformersDependencyError(error)) {\n throw createEmbeddingBackendUnavailableError(error);\n }\n throw error;\n }\n });\n } catch (error) {\n this.telemetry.recordModelLoadFailure(this.now() - startedAt);\n throw error;\n }\n\n try {\n this.pipeline = await this.loadPipelineWithCorruptionRecovery(pipeline, this.modelName);\n this.activeModelName = this.modelName;\n this.initialized = true;\n this.telemetry.recordModelLoad(\n this.resourceId,\n opaqueBackendId(this.activeModelName),\n this.now() - startedAt\n );\n return;\n } catch (primaryError) {\n const fallbackModel = process.env.CLAUDE_MEMORY_EMBEDDING_FALLBACK_MODEL || DEFAULT_EMBEDDING_FALLBACK_MODEL;\n if (fallbackModel === this.modelName) {\n this.telemetry.recordModelLoadFailure(this.now() - startedAt);\n throw primaryError;\n }\n\n console.warn(`[Embedder] Primary model failed (${this.modelName}). Falling back to ${fallbackModel}`);\n try {\n this.pipeline = await this.loadPipelineWithCorruptionRecovery(pipeline, fallbackModel);\n this.activeModelName = fallbackModel;\n this.initialized = true;\n this.telemetry.recordModelLoad(\n this.resourceId,\n opaqueBackendId(this.activeModelName),\n this.now() - startedAt\n );\n } catch (fallbackError) {\n this.telemetry.recordModelLoadFailure(this.now() - startedAt);\n throw fallbackError;\n }\n }\n }\n\n /**\n * Load a model, self-healing a truncated/corrupted cache.\n *\n * @huggingface/transformers only checks whether a cached file *exists*\n * before skipping the download, not whether it is valid. A download\n * interrupted mid-write (killed process, lost connection) leaves a file\n * that exists but fails ONNX parsing \u2014 every future load hits the same\n * error forever, since nothing ever re-downloads it. This was observed on\n * a real machine after a global npm install: two ~450MB files, sizes not\n * matching the known-good ~470MB build, failing with\n * \"Load model from <path> failed:Protobuf parsing failed.\" on every\n * attempt. Detecting that shape, clearing the specific model's cache\n * directory, and retrying once converts a permanently stuck install into\n * one that repairs itself on the next start.\n */\n private async loadPipelineWithCorruptionRecovery(\n pipeline: FeatureExtractionPipelineFactory,\n modelName: string\n ): Promise<NonNullable<Embedder['pipeline']>> {\n try {\n return await withSuppressedKnownTransformersWarnings(() => pipeline('feature-extraction', modelName));\n } catch (error) {\n if (!isCorruptedModelCacheError(error)) throw error;\n\n const cleared = await clearModelCacheDirectory(modelName);\n if (!cleared) throw error;\n\n console.warn(`[Embedder] Detected a corrupted cache for ${modelName}; cleared it and retrying.`);\n return await withSuppressedKnownTransformersWarnings(() => pipeline('feature-extraction', modelName));\n }\n }\n\n // ~4 chars per token; 512 tokens * 4 = 2048, use 2000 to be safe\n private static readonly MAX_CHARS = 2000;\n\n private truncate(text: string): string {\n return text.length > Embedder.MAX_CHARS ? text.slice(0, Embedder.MAX_CHARS) : text;\n }\n\n /**\n * Generate embedding for a single text\n */\n async embed(text: string): Promise<EmbeddingResult> {\n await this.initialize();\n\n if (!this.pipeline) {\n throw new Error('Embedding pipeline not initialized');\n }\n\n const output = await this.pipeline(this.truncate(text), {\n pooling: 'mean',\n normalize: true,\n truncation: true,\n max_length: 512\n });\n this.telemetry.recordModelActivity();\n\n const vector = Array.from(output.data);\n\n return {\n vector,\n model: this.activeModelName,\n dimensions: vector.length\n };\n }\n\n /**\n * Generate embeddings for multiple texts in batch\n */\n async embedBatch(texts: string[]): Promise<EmbeddingResult[]> {\n await this.initialize();\n\n if (!this.pipeline) {\n throw new Error('Embedding pipeline not initialized');\n }\n\n const results: EmbeddingResult[] = [];\n\n // Process in batches of 32 for memory efficiency\n const batchSize = 32;\n for (let i = 0; i < texts.length; i += batchSize) {\n const batch = texts.slice(i, i + batchSize);\n\n for (const text of batch) {\n const output = await this.pipeline(this.truncate(text), {\n pooling: 'mean',\n normalize: true,\n truncation: true,\n max_length: 512\n });\n this.telemetry.recordModelActivity();\n\n const vector = Array.from(output.data);\n\n results.push({\n vector,\n model: this.activeModelName,\n dimensions: vector.length\n });\n }\n }\n\n return results;\n }\n\n /**\n * Get embedding dimensions for the current model\n */\n async getDimensions(): Promise<number> {\n const result = await this.embed('test');\n return result.dimensions;\n }\n\n /**\n * Check if embedder is ready\n */\n isReady(): boolean {\n return this.initialized && this.pipeline !== null;\n }\n\n /**\n * Get model name\n */\n getModelName(): string {\n return this.activeModelName;\n }\n\n /** Release the native ONNX model so a long-lived but idle MCP process does not retain it. */\n async dispose(reason: RuntimeModelReleaseReason = 'manual'): Promise<void> {\n const pipeline = this.pipeline;\n this.pipeline = null;\n this.initialized = false;\n this.activeModelName = this.modelName;\n if (!pipeline) return;\n try {\n await pipeline.dispose?.();\n this.telemetry.recordModelRelease(this.resourceId, reason);\n } catch (error) {\n this.telemetry.recordModelReleaseFailure();\n throw error;\n }\n }\n}\n\n// Singleton instance for reuse\nlet defaultEmbedder: Embedder | null = null;\n\nexport function getDefaultEmbedder(): Embedder {\n const envModel = process.env.CLAUDE_MEMORY_EMBEDDING_MODEL;\n if (!defaultEmbedder) {\n defaultEmbedder = new Embedder(envModel || undefined);\n }\n return defaultEmbedder;\n}\n\nexport async function disposeDefaultEmbedder(reason: RuntimeModelReleaseReason = 'process-shutdown'): Promise<void> {\n const embedder = defaultEmbedder;\n defaultEmbedder = null;\n await embedder?.dispose(reason);\n}\n\nlet transformersWarningSuppressionDepth = 0;\nlet originalConsoleWarn: typeof console.warn | null = null;\n\nexport async function withSuppressedKnownTransformersWarnings<T>(fn: () => Promise<T>): Promise<T> {\n if (transformersWarningSuppressionDepth === 0) {\n originalConsoleWarn = console.warn;\n console.warn = (...args: unknown[]) => {\n const message = args.map(String).join(' ');\n if (isKnownBenignTransformersWarning(message)) return;\n (originalConsoleWarn ?? console.warn)(...args);\n };\n }\n transformersWarningSuppressionDepth += 1;\n\n try {\n return await fn();\n } finally {\n transformersWarningSuppressionDepth -= 1;\n if (transformersWarningSuppressionDepth === 0 && originalConsoleWarn) {\n console.warn = originalConsoleWarn;\n originalConsoleWarn = null;\n }\n }\n}\n\nexport function isKnownBenignTransformersWarning(message: string): boolean {\n return message.includes('Unknown model class \"eurobert\"') ||\n message.includes('dtype not specified for \"model\"');\n}\n\nexport function isMissingTransformersDependencyError(error: unknown): boolean {\n const maybeError = error as { code?: unknown; message?: unknown } | null;\n const message = typeof maybeError?.message === 'string' ? maybeError.message : '';\n return maybeError?.code === 'ERR_MODULE_NOT_FOUND' &&\n message.includes(\"@huggingface/transformers\");\n}\n\nexport function createEmbeddingBackendUnavailableError(cause: unknown): Error & { cause?: unknown } {\n const error = new Error(\n [\n 'Required embedding backend is not installed.',\n '',\n 'Claude Memory Layer requires @huggingface/transformers for local semantic/vector embeddings.',\n 'The backend runs on CPU-only ONNX Runtime; CUDA is not required.',\n 'Reinstall globally with:',\n ' ONNXRUNTIME_NODE_INSTALL_CUDA=skip npm install -g claude-memory-layer@latest',\n '',\n 'If you are inside a local checkout or package directory, repair only the backend with:',\n ' ONNXRUNTIME_NODE_INSTALL_CUDA=skip node scripts/postinstall-embedding-backend.cjs'\n ].join('\\n')\n ) as Error & { cause?: unknown };\n error.cause = cause;\n return error;\n}\n\nfunction findPackageRoot(startUrl: string = import.meta.url): string | undefined {\n let currentDir = pathDirname(urlToFilePath(startUrl));\n const filesystemRoot = parse(currentDir).root;\n\n while (currentDir !== filesystemRoot) {\n const manifestPath = join(currentDir, 'package.json');\n if (existsSync(manifestPath)) {\n try {\n const manifest = JSON.parse(readFileSync(manifestPath, 'utf8')) as { name?: string };\n if (manifest.name === 'claude-memory-layer') return currentDir;\n } catch {\n // Continue upward when an unrelated package manifest is unreadable.\n }\n }\n currentDir = pathDirname(currentDir);\n }\n\n return undefined;\n}\n\nexport function resolveTransformersModuleSpecifier(\n packageRoot: string | undefined = findPackageRoot()\n): string {\n if (!packageRoot) return '@huggingface/transformers';\n\n const backendRoot = join(packageRoot, 'node_modules', MANAGED_EMBEDDING_BACKEND_DIR);\n const backendManifest = join(backendRoot, 'package.json');\n if (!existsSync(backendManifest)) return '@huggingface/transformers';\n\n try {\n const backendRequire = createNodeRequire(pathToFileURL(backendManifest));\n return pathToFileURL(backendRequire.resolve('@huggingface/transformers')).href;\n } catch {\n return '@huggingface/transformers';\n }\n}\n\ninterface TransformersModuleLike {\n pipeline: unknown;\n env?: { cacheDir?: string };\n default?: TransformersModuleLike;\n}\n\n/**\n * CJS interop: the managed-backend specifier is resolved with require\n * semantics, which picks transformers' `require` condition\n * (dist/transformers.node.cjs). `import()` of that CJS file exposes the real\n * exports under `default` when cjs-module-lexer cannot lex them as named\n * exports \u2014 leaving `namespace.pipeline` undefined (\"pipeline is not a\n * function\" at embed time). Unwrap `default` whenever it, not the namespace,\n * carries the pipeline.\n */\nexport function normalizeTransformersNamespace(namespace: TransformersModuleLike): TransformersModuleLike {\n if (typeof namespace.pipeline === 'function') return namespace;\n if (namespace.default && typeof namespace.default.pipeline === 'function') return namespace.default;\n return namespace;\n}\n\nasync function loadTransformersModule(): Promise<TransformersModuleLike> {\n const dynamicImport = new Function('specifier', 'return import(specifier)') as (\n specifier: string\n ) => Promise<TransformersModuleLike>;\n return normalizeTransformersNamespace(await dynamicImport(resolveTransformersModuleSpecifier()));\n}\n\nasync function loadTransformersPipeline(): Promise<FeatureExtractionPipelineFactory> {\n // Keep @huggingface/transformers lazy so importing MemoryService or pure\n // adapter helpers does not eagerly dlopen onnxruntime native bindings.\n const transformers = await loadTransformersModule();\n return transformers.pipeline as FeatureExtractionPipelineFactory;\n}\n\n/**\n * Matches ONNX Runtime's model-load failure text, which is how a truncated\n * download surfaces: the file exists (so nothing re-downloads it) but is not\n * a valid protobuf. Intentionally narrow \u2014 only errors that name onnx/protobuf\n * loading are treated as a corrupted cache; a model that is merely missing or\n * a network failure during download should surface as-is.\n */\nexport function isCorruptedModelCacheError(error: unknown): boolean {\n const message = error instanceof Error ? error.message : String(error);\n return /load model from .*failed/i.test(message)\n || /protobuf parsing failed/i.test(message)\n || /invalid[_ ]protobuf/i.test(message)\n || /onnxruntime[^a-z]*error/i.test(message);\n}\n\nasync function resolveTransformersCacheDir(): Promise<string | undefined> {\n const transformers = await loadTransformersModule();\n return transformers.env?.cacheDir;\n}\n\n/**\n * Delete a model's cache directory so the library re-downloads it from\n * scratch. Returns false (not true-with-no-op) when the cache directory\n * cannot even be determined, so the caller knows recovery was not actually\n * attempted and should surface the original error instead of retrying\n * against the same corrupted files.\n *\n * `cacheDir` is injectable so tests can exercise the path-safety logic\n * directly: the production caller (below) resolves it via an indirect\n * dynamic import of @huggingface/transformers, which \u2014 like the rest of this\n * file's lazy loading \u2014 does not share module state with a bundler/test\n * runner's own transformed import of the same package.\n */\nexport async function clearModelCacheDirectory(\n modelName: string,\n cacheDir?: string\n): Promise<boolean> {\n try {\n const resolvedCacheDirInput = cacheDir ?? await resolveTransformersCacheDir();\n if (!resolvedCacheDirInput) return false;\n\n const fs = await import('node:fs/promises');\n const path = await import('node:path');\n const modelDir = path.join(resolvedCacheDirInput, modelName);\n\n // Guard against a misconfigured cacheDir turning this into `rm -rf` of\n // something unrelated: only remove a path that actually resolves inside\n // the resolved cache directory.\n const resolvedCacheDir = path.resolve(resolvedCacheDirInput);\n const resolvedModelDir = path.resolve(modelDir);\n if (!resolvedModelDir.startsWith(resolvedCacheDir + path.sep)) return false;\n\n await fs.rm(resolvedModelDir, { recursive: true, force: true });\n return true;\n } catch {\n return false;\n }\n}\n", "import { execFileSync } from 'node:child_process';\nimport { createHash } from 'node:crypto';\nimport {\n existsSync,\n mkdirSync,\n readFileSync,\n readdirSync,\n renameSync,\n rmSync,\n writeFileSync\n} from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\n\nexport const RUNTIME_RESOURCE_TELEMETRY_SCHEMA_VERSION = 1;\nexport const LEGACY_RUNTIME_VERSION = 'legacy-or-uninstrumented';\n\nexport type RuntimeClientKind = 'mcp' | 'semantic-daemon' | 'cli' | 'dashboard' | 'unknown';\nexport type RuntimeModelReleaseReason =\n | 'idle-timeout'\n | 'daemon-idle-shutdown'\n | 'process-shutdown'\n | 'manual'\n | 'unknown';\n\nexport interface RuntimeLatencyAggregate {\n count: number;\n failedCount: number;\n totalMs: number;\n maxMs: number;\n}\n\nexport interface RuntimeResourceSnapshot {\n schemaVersion: 1;\n pid: number;\n ppid: number;\n version: string;\n client: RuntimeClientKind;\n processState: 'running' | 'stopped';\n startedAt: string;\n updatedAt: string;\n stoppedAt: string | null;\n model: {\n loaded: boolean;\n loadedInstances: number;\n backendId: string | null;\n loadCount: number;\n loadFailureCount: number;\n totalLoadDurationMs: number;\n lastLoadDurationMs: number | null;\n lastLoadedAt: string | null;\n releaseCount: number;\n releaseFailureCount: number;\n lastReleasedAt: string | null;\n lastReleaseReason: RuntimeModelReleaseReason | null;\n lastActivityAt: string | null;\n useCount: number;\n };\n retrieval: {\n cold: RuntimeLatencyAggregate;\n hot: RuntimeLatencyAggregate;\n };\n}\n\nexport interface RuntimeResourceTelemetryOptions {\n now?: () => number;\n pid?: number;\n ppid?: number;\n version?: string;\n telemetryDir?: string;\n persist?: boolean;\n}\n\nexport interface RuntimeRetrievalTelemetry {\n isModelLoaded(): boolean;\n now(): number;\n recordRetrieval(tier: 'cold' | 'hot', durationMs: number, succeeded: boolean): void;\n}\n\nconst RUNTIME_CLIENT_KINDS = new Set<RuntimeClientKind>([\n 'mcp',\n 'semantic-daemon',\n 'cli',\n 'dashboard',\n 'unknown'\n]);\nconst SAFE_RUNTIME_VERSION = /^[0-9A-Za-z][0-9A-Za-z.+-]{0,63}$/;\n\nfunction emptyLatencyAggregate(): RuntimeLatencyAggregate {\n return { count: 0, failedCount: 0, totalMs: 0, maxMs: 0 };\n}\n\nfunction runtimeVersion(): string {\n const value = process.env.CLAUDE_MEMORY_LAYER_VERSION?.trim();\n return sanitizeRuntimeVersion(value || 'development');\n}\n\nfunction sanitizeRuntimeVersion(value: string): string {\n return SAFE_RUNTIME_VERSION.test(value) ? value : 'unknown';\n}\n\nexport function defaultRuntimeTelemetryDir(): string {\n const configured = process.env.CLAUDE_MEMORY_RUNTIME_TELEMETRY_DIR?.trim();\n return configured || path.join(os.homedir(), '.claude-code', 'memory', 'runtime-resources');\n}\n\nexport function opaqueBackendId(modelName: string): string {\n return `sha256:${createHash('sha256').update(modelName).digest('hex').slice(0, 12)}`;\n}\n\nexport class RuntimeResourceTelemetry implements RuntimeRetrievalTelemetry {\n private readonly nowFn: () => number;\n private readonly telemetryDir: string;\n private readonly persistEnabled: boolean;\n private readonly loadedResources = new Set<string>();\n private registered = false;\n private snapshot: RuntimeResourceSnapshot;\n private lastPersistMs = Number.NEGATIVE_INFINITY;\n private persistDirty = false;\n private flushTimer: NodeJS.Timeout | null = null;\n\n constructor(options: RuntimeResourceTelemetryOptions = {}) {\n this.nowFn = options.now ?? Date.now;\n this.telemetryDir = options.telemetryDir ?? defaultRuntimeTelemetryDir();\n const telemetryDisabled = ['1', 'true', 'yes'].includes(\n String(process.env.CLAUDE_MEMORY_DISABLE_RUNTIME_TELEMETRY || '').toLowerCase()\n );\n this.persistEnabled = options.persist ?? !telemetryDisabled;\n const now = this.isoNow();\n this.snapshot = {\n schemaVersion: RUNTIME_RESOURCE_TELEMETRY_SCHEMA_VERSION,\n pid: options.pid ?? process.pid,\n ppid: options.ppid ?? process.ppid,\n version: sanitizeRuntimeVersion(options.version ?? runtimeVersion()),\n client: 'unknown',\n processState: 'running',\n startedAt: now,\n updatedAt: now,\n stoppedAt: null,\n model: {\n loaded: false,\n loadedInstances: 0,\n backendId: null,\n loadCount: 0,\n loadFailureCount: 0,\n totalLoadDurationMs: 0,\n lastLoadDurationMs: null,\n lastLoadedAt: null,\n releaseCount: 0,\n releaseFailureCount: 0,\n lastReleasedAt: null,\n lastReleaseReason: null,\n lastActivityAt: null,\n useCount: 0\n },\n retrieval: {\n cold: emptyLatencyAggregate(),\n hot: emptyLatencyAggregate()\n }\n };\n }\n\n now(): number {\n return this.nowFn();\n }\n\n registerProcess(client: RuntimeClientKind): void {\n this.registered = true;\n this.snapshot.client = client;\n this.snapshot.processState = 'running';\n this.snapshot.stoppedAt = null;\n this.touchAndPersist({ flush: true });\n }\n\n markProcessStopped(): void {\n this.snapshot.processState = 'stopped';\n this.snapshot.stoppedAt = this.isoNow();\n this.touchAndPersist({ flush: true });\n // The snapshot only matters while the process lives; leaving it behind\n // accretes one file per session forever and slows every runtime-status\n // read. A crash before this line is covered by age-based pruning on read.\n if (this.registered && this.persistEnabled) {\n try {\n rmSync(path.join(this.telemetryDir, `process-${this.snapshot.pid}.json`), { force: true });\n } catch {\n // Never let telemetry cleanup interfere with shutdown.\n }\n }\n }\n\n recordModelLoad(resourceId: string, backendId: string, durationMs: number): void {\n this.loadedResources.add(resourceId);\n const model = this.snapshot.model;\n model.backendId = backendId;\n model.loadCount += 1;\n model.totalLoadDurationMs += boundedDuration(durationMs);\n model.lastLoadDurationMs = boundedDuration(durationMs);\n model.lastLoadedAt = this.isoNow();\n model.lastActivityAt = model.lastLoadedAt;\n this.touchAndPersist();\n }\n\n recordModelLoadFailure(durationMs: number): void {\n const model = this.snapshot.model;\n model.loadFailureCount += 1;\n model.lastLoadDurationMs = boundedDuration(durationMs);\n model.lastActivityAt = this.isoNow();\n this.touchAndPersist();\n }\n\n recordModelActivity(): void {\n this.snapshot.model.useCount += 1;\n this.snapshot.model.lastActivityAt = this.isoNow();\n this.touchAndPersist();\n }\n\n recordModelRelease(resourceId: string, reason: RuntimeModelReleaseReason): void {\n this.loadedResources.delete(resourceId);\n const model = this.snapshot.model;\n model.releaseCount += 1;\n model.lastReleasedAt = this.isoNow();\n model.lastReleaseReason = reason;\n model.lastActivityAt = model.lastReleasedAt;\n this.touchAndPersist();\n }\n\n recordModelReleaseFailure(): void {\n this.snapshot.model.releaseFailureCount += 1;\n this.snapshot.model.lastActivityAt = this.isoNow();\n this.touchAndPersist();\n }\n\n isModelLoaded(): boolean {\n return this.loadedResources.size > 0;\n }\n\n recordRetrieval(tier: 'cold' | 'hot', durationMs: number, succeeded: boolean): void {\n const aggregate = this.snapshot.retrieval[tier];\n const duration = boundedDuration(durationMs);\n aggregate.count += 1;\n aggregate.totalMs += duration;\n aggregate.maxMs = Math.max(aggregate.maxMs, duration);\n if (!succeeded) aggregate.failedCount += 1;\n this.snapshot.model.lastActivityAt = this.isoNow();\n this.touchAndPersist();\n }\n\n getSnapshot(): RuntimeResourceSnapshot {\n return structuredClone(this.snapshot);\n }\n\n private isoNow(): string {\n return new Date(this.nowFn()).toISOString();\n }\n\n private touchAndPersist(options?: { flush?: boolean }): void {\n this.snapshot.updatedAt = this.isoNow();\n // The redundant snapshot fields are derived here so no mutation path can\n // persist a self-contradictory model state (loaded=true, instances=0).\n this.snapshot.model.loadedInstances = this.loadedResources.size;\n this.snapshot.model.loaded = this.loadedResources.size > 0;\n if (!this.registered || !this.persistEnabled) return;\n\n // recordModelActivity/recordRetrieval fire once per embedded text and per\n // retrieval; a synchronous mkdir+write+rename per event stalls the\n // embedding loop. Leading-edge write plus a trailing unref'd flush keeps\n // the file at most PERSIST_INTERVAL_MS stale, and lifecycle transitions\n // (register/stop) flush immediately.\n const nowMs = this.nowFn();\n if (options?.flush || nowMs - this.lastPersistMs >= PERSIST_INTERVAL_MS) {\n this.persistNow(nowMs);\n return;\n }\n this.persistDirty = true;\n if (this.flushTimer) return;\n this.flushTimer = setTimeout(() => {\n this.flushTimer = null;\n if (this.persistDirty) this.persistNow(this.nowFn());\n }, PERSIST_INTERVAL_MS);\n this.flushTimer.unref?.();\n }\n\n private persistNow(nowMs: number): void {\n this.persistDirty = false;\n this.lastPersistMs = nowMs;\n try {\n mkdirSync(this.telemetryDir, { recursive: true, mode: 0o700 });\n const target = path.join(this.telemetryDir, `process-${this.snapshot.pid}.json`);\n const temporary = `${target}.tmp-${process.pid}`;\n writeFileSync(temporary, `${JSON.stringify(this.snapshot)}\\n`, { encoding: 'utf8', mode: 0o600 });\n renameSync(temporary, target);\n } catch {\n // Runtime telemetry must never make retrieval or shutdown fail.\n }\n }\n}\n\nconst PERSIST_INTERVAL_MS = 1_000;\n\nlet processTelemetry = new RuntimeResourceTelemetry();\n\nexport function getRuntimeResourceTelemetry(): RuntimeResourceTelemetry {\n return processTelemetry;\n}\n\nexport function setRuntimeResourceTelemetryForTests(telemetry: RuntimeResourceTelemetry): void {\n processTelemetry = telemetry;\n}\n\nexport function registerRuntimeProcess(client: RuntimeClientKind): void {\n processTelemetry.registerProcess(client);\n}\n\nexport function markRuntimeProcessStopped(): void {\n processTelemetry.markProcessStopped();\n}\n\nfunction boundedDuration(value: number): number {\n if (!Number.isFinite(value) || value < 0) return 0;\n return Math.round(value * 1000) / 1000;\n}\n\ninterface ProcessRow {\n pid: number;\n ppid: number;\n rssKiB: number;\n command: string;\n}\n\nexport interface RuntimeResourceGroup {\n version: string;\n client: RuntimeClientKind;\n processCount: number;\n rssMiB: number;\n orphanCount: number;\n modelLoadedCount: number;\n modelUnloadedCount: number;\n modelStateUnavailableCount: number;\n modelLoadCount: number;\n modelReleaseCount: number;\n coldRetrievalCount: number;\n coldRetrievalAverageMs: number | null;\n hotRetrievalCount: number;\n hotRetrievalAverageMs: number | null;\n}\n\nexport interface RuntimeResourceReport {\n generatedAt: string;\n processLocal: Omit<RuntimeResourceSnapshot, 'pid' | 'ppid'>;\n observation: {\n supported: boolean;\n platform: NodeJS.Platform;\n reason?: 'unsupported-platform' | 'process-metrics-unavailable';\n processCount: number | null;\n rssMiB: number | null;\n versionMismatchProcessCount: number;\n uninstrumentedProcessCount: number;\n restartRecommended: boolean;\n recommendationReasons: Array<'mixed_runtime_versions' | 'uninstrumented_runtime' | 'orphan_mcp'>;\n groups: RuntimeResourceGroup[];\n };\n}\n\nexport interface CollectRuntimeResourceReportOptions {\n platform?: NodeJS.Platform;\n telemetryDir?: string;\n now?: () => number;\n readProcessTable?: () => string;\n localSnapshot?: RuntimeResourceSnapshot;\n}\n\nexport function collectRuntimeResourceReport(\n options: CollectRuntimeResourceReportOptions = {}\n): RuntimeResourceReport {\n const platform = options.platform ?? process.platform;\n const now = options.now ?? Date.now;\n const localSnapshot = options.localSnapshot ?? processTelemetry.getSnapshot();\n const processLocal = stripProcessIdentity(localSnapshot);\n\n if (platform !== 'darwin' && platform !== 'linux') {\n return {\n generatedAt: new Date(now()).toISOString(),\n processLocal,\n observation: {\n supported: false,\n platform,\n reason: 'unsupported-platform',\n processCount: null,\n rssMiB: null,\n versionMismatchProcessCount: 0,\n uninstrumentedProcessCount: 0,\n restartRecommended: false,\n recommendationReasons: [],\n groups: []\n }\n };\n }\n\n let rows: ProcessRow[];\n try {\n const raw = options.readProcessTable\n ? options.readProcessTable()\n : execFileSync('ps', ['-axo', 'pid=,ppid=,rss=,command='], {\n encoding: 'utf8',\n timeout: 5_000,\n maxBuffer: 8 * 1024 * 1024\n });\n rows = parseProcessTable(raw);\n } catch {\n return {\n generatedAt: new Date(now()).toISOString(),\n processLocal,\n observation: {\n supported: false,\n platform,\n reason: 'process-metrics-unavailable',\n processCount: null,\n rssMiB: null,\n versionMismatchProcessCount: 0,\n uninstrumentedProcessCount: 0,\n restartRecommended: false,\n recommendationReasons: [],\n groups: []\n }\n };\n }\n\n const snapshots = readRuntimeResourceSnapshots(options.telemetryDir ?? defaultRuntimeTelemetryDir(), now());\n const snapshotsByPid = new Map(\n snapshots\n .filter((snapshot) => snapshot.processState === 'running')\n .map((snapshot) => [snapshot.pid, snapshot])\n );\n // A snapshot alone is not proof that a PID still belongs to this product;\n // stale files plus PID reuse must not turn unrelated processes into samples.\n const candidates = rows.filter((row) => classifyRuntimeCommand(row.command) !== null);\n const groups = aggregateRuntimeResourceGroups(candidates, snapshotsByPid);\n const uninstrumentedProcessCount = groups\n .filter((group) => group.version === LEGACY_RUNTIME_VERSION)\n .reduce((sum, group) => sum + group.processCount, 0);\n const currentVersion = processLocal.version;\n const canCompareVersion = currentVersion !== 'development' && currentVersion !== 'unknown';\n const versionMismatchProcessCount = canCompareVersion\n ? groups\n .filter((group) => group.version !== LEGACY_RUNTIME_VERSION && group.version !== currentVersion)\n .reduce((sum, group) => sum + group.processCount, 0)\n : 0;\n const orphanCount = groups.reduce((sum, group) => sum + group.orphanCount, 0);\n const recommendationReasons: RuntimeResourceReport['observation']['recommendationReasons'] = [];\n if (versionMismatchProcessCount > 0) recommendationReasons.push('mixed_runtime_versions');\n if (uninstrumentedProcessCount > 0) recommendationReasons.push('uninstrumented_runtime');\n if (orphanCount > 0) recommendationReasons.push('orphan_mcp');\n\n return {\n generatedAt: new Date(now()).toISOString(),\n processLocal,\n observation: {\n supported: true,\n platform,\n processCount: candidates.length,\n rssMiB: roundMiB(candidates.reduce((sum, row) => sum + row.rssKiB, 0)),\n versionMismatchProcessCount,\n uninstrumentedProcessCount,\n restartRecommended: recommendationReasons.length > 0,\n recommendationReasons,\n groups\n }\n };\n}\n\n/** Snapshots older than this are crash leftovers \u2014 markProcessStopped never ran. */\nconst STALE_SNAPSHOT_MS = 7 * 24 * 60 * 60 * 1_000;\n\nexport function readRuntimeResourceSnapshots(directory: string, nowMs: number = Date.now()): RuntimeResourceSnapshot[] {\n if (!existsSync(directory)) return [];\n const snapshots: RuntimeResourceSnapshot[] = [];\n for (const entry of readdirSync(directory)) {\n if (!/^process-\\d+\\.json$/.test(entry)) continue;\n try {\n const parsed = JSON.parse(readFileSync(path.join(directory, entry), 'utf8')) as RuntimeResourceSnapshot;\n if (!isRuntimeResourceSnapshot(parsed)) continue;\n // A process SIGKILLed before markProcessStopped leaves a 'running' file\n // behind forever. Age it out (and best-effort delete it) so the\n // directory stays bounded and a reused PID months later cannot inherit\n // the dead process's counters.\n const updatedAtMs = Date.parse(parsed.updatedAt);\n if (Number.isFinite(updatedAtMs) && nowMs - updatedAtMs > STALE_SNAPSHOT_MS) {\n try {\n rmSync(path.join(directory, entry), { force: true });\n } catch {\n // Pruning is opportunistic; reading must not fail on it.\n }\n continue;\n }\n snapshots.push(parsed);\n } catch {\n // Ignore partial, corrupt, or incompatible telemetry snapshots.\n }\n }\n return snapshots;\n}\n\nfunction isRuntimeResourceSnapshot(value: RuntimeResourceSnapshot): boolean {\n return value?.schemaVersion === RUNTIME_RESOURCE_TELEMETRY_SCHEMA_VERSION\n && Number.isSafeInteger(value.pid)\n && value.pid > 0\n && SAFE_RUNTIME_VERSION.test(value.version)\n && RUNTIME_CLIENT_KINDS.has(value.client)\n && typeof value.model?.loaded === 'boolean';\n}\n\nfunction parseProcessTable(raw: string): ProcessRow[] {\n const rows: ProcessRow[] = [];\n for (const line of raw.split('\\n')) {\n const match = /^\\s*(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(.+)$/.exec(line);\n if (!match) continue;\n rows.push({\n pid: Number(match[1]),\n ppid: Number(match[2]),\n rssKiB: Number(match[3]),\n command: match[4]\n });\n }\n return rows;\n}\n\nfunction classifyRuntimeCommand(command: string): RuntimeClientKind | null {\n if (/(?:^|[\\\\/])semantic-daemon\\.(?:js|ts)(?:\\s|$)/.test(command)) return 'semantic-daemon';\n if (/claude-memory-layer-mcp|(?:^|[\\\\/])(?:dist|src)[\\\\/](?:extensions[\\\\/])?mcp[\\\\/]index\\.(?:js|ts)(?:\\s|$)/.test(command)) {\n return 'mcp';\n }\n return null;\n}\n\nfunction aggregateRuntimeResourceGroups(\n rows: ProcessRow[],\n snapshotsByPid: Map<number, RuntimeResourceSnapshot>\n): RuntimeResourceGroup[] {\n const groups = new Map<string, RuntimeResourceGroup & { coldTotalMs: number; hotTotalMs: number }>();\n\n for (const row of rows) {\n const commandKind = classifyRuntimeCommand(row.command);\n const candidateSnapshot = snapshotsByPid.get(row.pid);\n // PID reuse: a stale 'running' snapshot from a dead process must not lend\n // its counters to an unrelated product process that inherited the PID. If\n // the live command classifies as a different kind than the snapshot\n // recorded, trust the command and treat the process as uninstrumented.\n const snapshot = candidateSnapshot && commandKind !== null && candidateSnapshot.client !== commandKind\n ? undefined\n : candidateSnapshot;\n const client = snapshot?.client ?? commandKind ?? 'unknown';\n const version = snapshot?.version || LEGACY_RUNTIME_VERSION;\n const key = `${version}\\u0000${client}`;\n const group = groups.get(key) ?? {\n version,\n client,\n processCount: 0,\n rssMiB: 0,\n orphanCount: 0,\n modelLoadedCount: 0,\n modelUnloadedCount: 0,\n modelStateUnavailableCount: 0,\n modelLoadCount: 0,\n modelReleaseCount: 0,\n coldRetrievalCount: 0,\n coldRetrievalAverageMs: null,\n hotRetrievalCount: 0,\n hotRetrievalAverageMs: null,\n coldTotalMs: 0,\n hotTotalMs: 0\n };\n group.processCount += 1;\n group.rssMiB += row.rssKiB / 1024;\n // The semantic daemon is intentionally detached, so PPID 1 is expected for\n // that client. MCP stdio servers, in contrast, should retain a live parent.\n if (row.ppid === 1 && client === 'mcp') group.orphanCount += 1;\n if (snapshot) {\n if (snapshot.model.loaded) group.modelLoadedCount += 1;\n else group.modelUnloadedCount += 1;\n group.modelLoadCount += snapshot.model.loadCount;\n group.modelReleaseCount += snapshot.model.releaseCount;\n group.coldRetrievalCount += snapshot.retrieval.cold.count;\n group.coldTotalMs += snapshot.retrieval.cold.totalMs;\n group.hotRetrievalCount += snapshot.retrieval.hot.count;\n group.hotTotalMs += snapshot.retrieval.hot.totalMs;\n } else {\n group.modelStateUnavailableCount += 1;\n }\n groups.set(key, group);\n }\n\n return Array.from(groups.values())\n .map(({ coldTotalMs, hotTotalMs, ...group }) => ({\n ...group,\n rssMiB: Math.round(group.rssMiB * 10) / 10,\n coldRetrievalAverageMs: average(coldTotalMs, group.coldRetrievalCount),\n hotRetrievalAverageMs: average(hotTotalMs, group.hotRetrievalCount)\n }))\n .sort((a, b) => a.version.localeCompare(b.version) || a.client.localeCompare(b.client));\n}\n\nfunction average(total: number, count: number): number | null {\n return count === 0 ? null : Math.round((total / count) * 1000) / 1000;\n}\n\nfunction roundMiB(rssKiB: number): number {\n return Math.round((rssKiB / 1024) * 10) / 10;\n}\n\nfunction stripProcessIdentity(\n snapshot: RuntimeResourceSnapshot\n): Omit<RuntimeResourceSnapshot, 'pid' | 'ppid'> {\n const { pid: _pid, ppid: _ppid, ...safe } = snapshot;\n return safe;\n}\n", "export type HookMemorySource = 'semantic' | 'keyword' | 'graduated' | 'episode' | 'lesson' | 'unknown';\n\nexport interface HookMemoryCandidate {\n type: string;\n content: string;\n id?: string;\n sessionId?: string;\n score?: number;\n source?: HookMemorySource;\n fallback?: boolean;\n memoryLevel?: string;\n accessCount?: number;\n retrievalRankScore?: number;\n /** Same-session evidence expanded from a relevant retrieval seed. */\n episodeLinked?: boolean;\n /** The episode was reached through a strongly aligned prompt/tool seed. */\n episodeSeedAligned?: boolean;\n /** Every distinctive identifier anchor and at least four lexical clues matched the seed. */\n episodeSeedStrongAligned?: boolean;\n}\n\nexport interface HookInjectionPolicy {\n minScore: number;\n semanticMinScore: number;\n keywordMinScore: number;\n fallbackKeywordMinScore: number;\n /** Minimum adjacent-score drop used to retain an additional result. */\n scoreCliffGap: number;\n maxMemories: number;\n}\n\nconst LOW_SIGNAL_QUERY_TERMS = new Set([\n 'the', 'and', 'for', 'with', 'this', 'that', 'what', 'when', 'where', 'why', 'how',\n 'please', 'help', 'need', 'using', 'use', 'fix', 'update', 'change', 'memory',\n '\uADF8\uB9AC\uACE0', '\uADF8\uAC83', '\uADF8\uAC70', '\uC774\uAC83', '\uC774\uAC70', '\uD574\uC8FC\uC138\uC694', '\uD574\uC918', '\uC218\uC815', '\uAD6C\uD604', '\uAC1C\uC120',\n '\uD655\uC778', '\uD655\uC778\uD574\uC918', '\uD655\uC778\uD574\uC8FC\uC138\uC694', '\uBC29\uBC95', '\uAD00\uB828', '\uB0B4\uC6A9', '\uBB38\uC81C', '\uC6D0\uC778', '\uC791\uC5C5', '\uC9C4\uD589', '\uACC4\uD68D', '\uD6C8\uB828', '\uB2E4\uC74C', '\uC774\uBC88',\n '\uC54C\uB824\uC918', '\uC54C\uB824\uC8FC', '\uC54C\uB824', '\uC815\uB9AC\uD574\uC918', '\uC815\uB9AC', '\uC124\uBA85\uD574\uC918', '\uC124\uBA85', '\uC694\uC57D\uD574\uC918',\n '\uC694\uC57D', '\uBD80\uD0C1', '\uB300\uD574', '\uBB34\uC5C7', '\uC5B4\uB5BB', '\uC5B4\uB5BB\uAC8C', '\uC788\uC5B4', '\uB2E4\uC2DC',\n '\uCD5C\uC885', '\uACB0\uACFC', '\uD575\uC2EC', '\uADFC\uAC70', '\uB2F9\uC2DC', '\uACB0\uB860', '\uD574\uACB0', '\uC2E4\uC81C', '\uD655\uC778\uB41C', '\uACB0\uC815', '\uC0AC\uD56D',\n '\uBB50\uC57C', '\uBB50\uC608\uC694', '\uBB50\uC600\uC5B4', '\uBB50\uC600\uC5B4\uC694'\n]);\n\nexport function getHookInjectionPolicy(env: NodeJS.ProcessEnv = process.env): HookInjectionPolicy {\n const minScore = readScoreThreshold(env.CLAUDE_MEMORY_HOOK_INJECTION_MIN_SCORE, 0.65);\n const keywordMinScore = readNumber(\n env.CLAUDE_MEMORY_HOOK_KEYWORD_MIN_SCORE,\n Math.max(minScore, 0.7),\n { min: 0, max: 1 }\n );\n\n return {\n minScore,\n semanticMinScore: readScoreThreshold(env.CLAUDE_MEMORY_HOOK_SEMANTIC_MIN_SCORE, minScore),\n keywordMinScore,\n fallbackKeywordMinScore: readNumber(\n env.CLAUDE_MEMORY_HOOK_FALLBACK_KEYWORD_MIN_SCORE,\n Math.max(keywordMinScore, 0.8),\n { min: 0, max: 1 }\n ),\n scoreCliffGap: readNumber(env.CLAUDE_MEMORY_HOOK_SCORE_CLIFF_GAP, 0.08, { min: 0.01, max: 0.5 }),\n maxMemories: Math.max(1, Math.floor(readNumber(env.CLAUDE_MEMORY_HOOK_MAX_INJECTED, 5)))\n };\n}\n\nexport function filterHookInjectableMemories(\n candidates: HookMemoryCandidate[],\n policy: HookInjectionPolicy = getHookInjectionPolicy(),\n query?: string\n): HookMemoryCandidate[] {\n const ranked = rankHookCandidates(candidates, policy, query);\n const cliffBounded = query ? applyScoreCliff(ranked, policy.scoreCliffGap) : ranked;\n const bounded = cliffBounded.slice(0, policy.maxMemories).map(({ candidate }) => candidate);\n return query ? applyAnswerabilityGate(bounded, query) : bounded;\n}\n\n/**\n * specs/lesson-recall-hooks R3 \u2014 keep one query-covering lesson alive.\n *\n * Lessons score 0.65-0.8 by design (lexical coverage only) while transcript\n * evidence sits around 0.83, so the score cliff drops every lesson whenever a\n * good answer exists. Real traces: 196 prompts had a lesson candidate, 5 kept\n * it. A lesson is only reserved when it already passed scoreLessonEvidence's\n * own gate and the injection minimum, and never displaces another lesson.\n */\nexport function reserveLessonSlot(\n selected: HookMemoryCandidate[],\n candidates: HookMemoryCandidate[],\n policy: HookInjectionPolicy\n): HookMemoryCandidate[] {\n if (selected.some((candidate) => candidate.source === 'lesson')) return selected;\n const best = candidates\n .filter((candidate) => candidate.source === 'lesson' && (candidate.score ?? 0) >= policy.minScore)\n .sort((a, b) => (b.score ?? 0) - (a.score ?? 0))[0];\n if (!best) return selected;\n if (selected.length < policy.maxMemories) return [...selected, best];\n const weakest = selected.reduce((low, candidate, index) =>\n (candidate.score ?? 0) < (selected[low].score ?? 0) ? index : low, 0);\n return [...selected.slice(0, weakest), ...selected.slice(weakest + 1), best];\n}\n\n/** Select relevant seeds before episode expansion, without the final answerability gate. */\nexport function selectHookRetrievalSeeds(\n candidates: HookMemoryCandidate[],\n policy: HookInjectionPolicy = getHookInjectionPolicy(),\n query?: string\n): HookMemoryCandidate[] {\n const ranked = rankHookCandidates(candidates, policy, query);\n const cliffBounded = query ? applyScoreCliff(ranked, policy.scoreCliffGap) : ranked;\n return cliffBounded.slice(0, policy.maxMemories).map(({ candidate }) => candidate);\n}\n\n/**\n * Select prompt/tool seeds independently from answer ranking. Exact prompts\n * otherwise lose to answer-type utility bonuses before episode expansion,\n * preventing the response from the same turn from ever becoming a candidate.\n */\nexport function selectHookEpisodeSeeds(\n candidates: HookMemoryCandidate[],\n policy: HookInjectionPolicy = getHookInjectionPolicy(),\n query: string\n): HookMemoryCandidate[] {\n const queryTerms = meaningfulTerms(query);\n const queryAnchors = identifierAnchors(query);\n return candidates\n .filter((candidate) => candidate.type === 'user_prompt' || candidate.type === 'tool_observation')\n .filter((candidate) => hasQueryMemoryAlignment(query, candidate.content, 2))\n .map((candidate, index) => {\n const contentTerms = new Set(meaningfulTerms(candidate.content));\n const overlap = queryTerms.filter((term) => contentTerms.has(term)).length;\n const lowered = candidate.content.toLowerCase();\n const anchorCoverage = queryAnchors.length === 0\n ? 0\n : queryAnchors.filter((anchor) => lowered.includes(anchor.toLowerCase())).length / queryAnchors.length;\n const lexicalCoverage = overlap / Math.max(1, Math.min(queryTerms.length, 12));\n const score = candidate.score ?? 0;\n const normalThreshold = thresholdFor(candidate, policy);\n const hasDistinctiveAnchor = queryAnchors.some((anchor) =>\n anchor.length >= 6 && /[A-Za-z]/.test(anchor)\n );\n const fullyAnchored = queryAnchors.length > 0 && anchorCoverage === 1 && overlap >= 4 && hasDistinctiveAnchor;\n const usesStrongAnchorFloor = score < normalThreshold && fullyAnchored;\n return {\n candidate: {\n ...candidate,\n // Episode answers are filtered again by the normal semantic floor.\n // A fully anchored prompt that uses the lower seed-only floor needs\n // enough inherited score to compete there; counterfactual anchors\n // cannot take this path because their coverage is zero.\n score: usesStrongAnchorFloor ? Math.max(score, policy.semanticMinScore + 0.02) : score,\n episodeSeedAligned: true,\n episodeSeedStrongAligned: fullyAnchored\n },\n index,\n score: score + lexicalCoverage * 0.25 + anchorCoverage * 0.20,\n eligible: score >= normalThreshold || usesStrongAnchorFloor\n };\n })\n .filter((item) => item.eligible)\n .sort((a, b) => (b.score - a.score) || (a.index - b.index))\n .slice(0, policy.maxMemories)\n .map((item) => item.candidate);\n}\n\nfunction rankHookCandidates(\n candidates: HookMemoryCandidate[],\n policy: HookInjectionPolicy,\n query?: string\n): Array<{ candidate: HookMemoryCandidate; index: number; effectiveScore: number }> {\n return candidates\n .map((candidate, index) => ({ candidate, index }))\n .filter(({ candidate }) => isHookInjectableMemory(candidate, policy))\n .filter(({ candidate }) => !query || (\n candidate.source === 'episode' && candidate.episodeLinked && candidate.episodeSeedAligned\n ) || hasQueryMemoryAlignment(query, candidate.content, 2))\n // The rule-based session-summary generator emits a table of contents\n // (\"Session with N prompts. Topics discussed: ...\"), not a result. The\n // graduated lane already excludes this via scoreGraduatedEvidence; the\n // semantic/keyword lanes must exclude it too or it keeps winning the\n // evidenceUtilityBonus('session_summary') = 0.12 slot on session_summary's\n // own high type bonus alone, with nothing answerable inside it.\n .filter(({ candidate }) =>\n candidate.type !== 'session_summary' || !isPromptOnlySessionSummary(candidate.content)\n )\n .map(({ candidate, index }) => ({\n candidate,\n index,\n effectiveScore: Math.max(0,\n (candidate.score ?? 0)\n + (query ? evidenceUtilityBonus(candidate.type, query) : 0)\n + (query ? graduatedEvidenceBonus(candidate) : 0)\n + (candidate.source === 'episode' && candidate.episodeLinked && candidate.episodeSeedStrongAligned\n ? 0.42\n : candidate.source === 'episode' && candidate.episodeLinked && candidate.episodeSeedAligned ? 0.12 : 0)\n )\n }))\n .sort((a, b) => {\n const scoreDelta = b.effectiveScore - a.effectiveScore;\n return scoreDelta || a.index - b.index;\n });\n}\n\nfunction applyScoreCliff(\n ranked: Array<{ candidate: HookMemoryCandidate; index: number; effectiveScore: number }>,\n minimumGap: number\n): Array<{ candidate: HookMemoryCandidate; index: number; effectiveScore: number }> {\n if (ranked.length <= 1) return ranked;\n const effectiveMinimumGap = ranked[0].candidate.source === 'graduated'\n ? Math.min(minimumGap, 0.02)\n : minimumGap;\n for (let index = 1; index < ranked.length; index++) {\n const previous = ranked[index - 1].effectiveScore;\n const current = ranked[index].effectiveScore;\n if (previous - current >= effectiveMinimumGap) return ranked.slice(0, index);\n }\n // No clear relevance break: retain only the strongest result rather than\n // accumulating similarly scored but potentially unrelated context.\n return ranked.slice(0, 1);\n}\n\nfunction applyAnswerabilityGate(candidates: HookMemoryCandidate[], query: string): HookMemoryCandidate[] {\n const answerEvidence = candidates.filter((candidate) =>\n candidate.type === 'agent_response'\n || candidate.type === 'session_summary'\n || candidate.type === 'lesson'\n );\n if (answerEvidence.length > 0) {\n const toolEvidence = hasToolEvidenceIntent(query)\n ? candidates.filter((candidate) =>\n candidate.type === 'tool_observation' && toolEvidenceMatchesQueryAnchors(candidate, query)\n )\n : [];\n return [...answerEvidence, ...toolEvidence];\n }\n // No tool-only fallback. Injecting raw tool attempts because nothing better\n // survived ranking produced 131 traces whose memories were never used in an\n // answer (grounding 0.2%). Abstaining is cheaper than unusable context.\n return isContinuationQuery(query) ? candidates : [];\n}\n\n/**\n * A tool observation may only accompany an answer when the query's distinctive\n * identifiers actually occur in it. Queries without identifiers cannot be\n * verified this way, so they keep the intent-only behaviour.\n */\nfunction toolEvidenceMatchesQueryAnchors(candidate: HookMemoryCandidate, query: string): boolean {\n const anchors = identifierAnchors(query);\n if (anchors.length === 0) return true;\n const lowered = candidate.content.toLowerCase();\n return anchors.some((anchor) => lowered.includes(anchor.toLowerCase()));\n}\n\nfunction hasToolEvidenceIntent(query: string): boolean {\n // \"command\", \"log\", and \"output\" are deliberately absent: <task-notification>\n // payloads embed <output-file>, which made nearly every notification look like\n // a tool-evidence request. Retrieval queries are also enriched with the\n // previous turn, so generic words match far beyond the current question.\n return /\\b(?:kubectl|curl|psql|sql|stderr|stdout|traceback|stack\\s*trace|exit\\s*code)\\b|(?:\uBA85\uB839\uC5B4|\uC2A4\uD0DD\\s*\uD2B8\uB808\uC774\uC2A4|\uC885\uB8CC\\s*\uCF54\uB4DC|\uD130\uBBF8\uB110)/iu\n .test(query);\n}\n\nfunction evidenceUtilityBonus(type: string, query: string): number {\n // Lessons are human-reviewed runbooks rather than transcript, so they outrank\n // every derived evidence type.\n if (type === 'lesson') return 0.16;\n if (type === 'session_summary') return 0.12;\n if (type === 'agent_response') return 0.10;\n // Tool observations only earn a slot when the question actually asks for tool\n // evidence; otherwise they are pushed below answer evidence instead of\n // consuming the bounded injection budget.\n if (type === 'tool_observation') return hasToolEvidenceIntent(query) ? 0.03 : -0.15;\n if (type === 'user_prompt') return -0.10;\n return 0;\n}\n\nfunction graduatedEvidenceBonus(candidate: HookMemoryCandidate): number {\n // scoreGraduatedEvidence already includes a bounded level/access prior.\n // Applying the level bonus again here can let a broad L2 answer outrank a\n // more exact L1 answer, so calibrated graduated candidates get no second\n // promotion boost.\n if (candidate.source === 'graduated') return 0;\n if (candidate.type !== 'agent_response' && candidate.type !== 'session_summary') return 0;\n if (candidate.memoryLevel === 'L4') return 0.10;\n if (candidate.memoryLevel === 'L3') return 0.08;\n if (candidate.memoryLevel === 'L2') return 0.06;\n if (candidate.memoryLevel === 'L1') return 0.03;\n return 0;\n}\n\n/**\n * Deterministic score for the L1+ answer lane. It rewards query coverage and\n * exact identifier coverage; level/access are only small tie-breakers so a\n * frequently reused but wrong entity cannot win on graduation alone.\n */\nexport function scoreGraduatedEvidence(query: string, candidate: HookMemoryCandidate): number | null {\n if (candidate.type !== 'user_prompt' && candidate.type !== 'agent_response' && candidate.type !== 'session_summary') return null;\n if (!candidate.memoryLevel || candidate.memoryLevel === 'L0') return null;\n if (candidate.type === 'session_summary' && isPromptOnlySessionSummary(candidate.content)) return null;\n if (!hasQueryMemoryAlignment(query, candidate.content, 2)) return null;\n\n const queryTerms = meaningfulTerms(query);\n const contentTerms = new Set(meaningfulTerms(candidate.content));\n const overlap = queryTerms.filter((term) => contentTerms.has(term)).length;\n if (overlap < Math.min(3, queryTerms.length)) return null;\n const coverage = overlap / Math.max(1, Math.min(queryTerms.length, 8));\n const anchors = identifierAnchors(query);\n const lowered = candidate.content.toLowerCase();\n const matchedAnchors = anchors.filter((anchor) => lowered.includes(anchor.toLowerCase())).length;\n const anchorCoverage = anchors.length === 0 ? 0 : matchedAnchors / anchors.length;\n if (anchors.length >= 2 && matchedAnchors < Math.ceil(anchors.length * 0.6)) return null;\n if (candidate.type !== 'user_prompt' && isDiagnosticQuery(query) && !hasDiagnosticOutcome(candidate.content)) return null;\n\n const entities = entityAnchors(query);\n const matchedEntityPositions = entities\n .map((entity) => lowered.indexOf(entity))\n .filter((index) => index >= 0);\n const entityCoverage = entities.length === 0 ? 0 : matchedEntityPositions.length / entities.length;\n if (anchors.length > 0 && entities.length >= 2 && entityCoverage < 0.8) return null;\n const entityProximity = matchedEntityPositions.length < 2\n ? 0\n : 1 - Math.min(1,\n (Math.max(...matchedEntityPositions) - Math.min(...matchedEntityPositions)) / 2000\n );\n const levelPrior = candidate.memoryLevel === 'L4' ? 0.05\n : candidate.memoryLevel === 'L3' ? 0.045\n : candidate.memoryLevel === 'L2' ? 0.035\n : 0.015;\n const accessPrior = Math.min(0.02, Math.log2(Math.max(1, (candidate.accessCount ?? 0) + 1)) * 0.008);\n const rankPrior = Math.max(0, Math.min(1, candidate.retrievalRankScore ?? 0)) * 0.08;\n const base = candidate.type === 'user_prompt' ? 0.52 : 0.45;\n return Math.min(0.98,\n base\n + coverage * 0.20\n + anchorCoverage * 0.04\n + entityCoverage * 0.20\n + entityProximity * 0.10\n + rankPrior\n + levelPrior\n + accessPrior\n );\n}\n\nexport interface LessonEvidenceInput {\n lessonId: string;\n name: string;\n trigger?: string;\n steps: string[];\n failureModes?: string[];\n confidence: number;\n scope?: string;\n validation?: string[];\n reconsiderWhen?: string;\n validVersions?: string[];\n}\n\n/**\n * Render a curated lesson as injectable evidence, scored by query coverage.\n *\n * Lessons live outside the events table, so they reach the prompt only through\n * this lane. The score stays lexical and deterministic for the same reason the\n * graduated lane does: a reviewed runbook must not outrank exact evidence just\n * for being curated, so confidence is only a small tie-breaker.\n */\nexport function isExplicitlyProhibitedLessonQuery(query: string): boolean {\n // An exact identifier is not permission to suggest a procedure the caller\n // explicitly prohibited. Abstain conservatively; ordinary \"without\" clauses\n // remain searchable because they may describe the desired safety condition.\n return /\\b(?:do[ -]+not|don't|never)\\b|(?:^|[.!?;]\\s*)(?:please\\s+)?(?:skip|omit|ignore)\\b|(?:\uC0AC\uC6A9|\uC801\uC6A9|\uC2E4\uD589|\uD638\uCD9C|\uC124\uCE58|\uD65C\uC131\uD654|\uC7AC\uC2DC\uB3C4)(?:\\s*\uAE08\uC9C0|\uD558\uC9C0\\s*(?:\uC54A|\uB9D0))|\uAC74\uB108\uB6F0|\uBB34\uC2DC(?:\uD574|\uD558|\uD560)|\uC9C0\\s*\uB9C8(?:\uB77C|\uC138\uC694|\uC2ED\uC2DC\uC624)?(?:[.!?\\s]|$)/iu.test(query);\n}\n\n/** Remove only complete generic execution constraints from lexical scoring.\n * The caller's query and action restrictions remain unchanged everywhere else.\n * Targeted procedures, memory opt-outs and mixed clauses must reach the existing\n * conservative prohibition guard, including unknown additions to these lists.\n */\nfunction lessonScoringQuery(query: string): string {\n const korean = /^(?:\uB3C4\uAD6C\\s*\uD638\uCD9C|\uD30C\uC77C\\s*(?:\uC218\uC815|\uBCC0\uACBD))(?:(?:\\s*[/\u00B7,]\\s*|\\s*(?:\uBC0F|\uC640|\uACFC)\\s*)(?:\uB3C4\uAD6C\\s*\uD638\uCD9C|\uD30C\uC77C\\s*(?:\uC218\uC815|\uBCC0\uACBD)))*(?:\uC740|\uB294|\uC744|\uB97C)?\\s*(?:\uD558\uC9C0\\s*\uB9C8(?:\uC138\uC694|\uC2ED\uC2DC\uC624|\uB77C)|\uAE08\uC9C0)$/u;\n const readOnly = /^(?:\uC77D\uAE30\\s*\uC804\uC6A9\uC73C\uB85C\\s*\uD655\uC778\uD558\uACE0\\s*)?(?:\uD30C\uC77C(?:\\s*(?:\uC218\uC815|\uBCC0\uACBD))?|\uC124\uCE58|\uAD50\uD6C8\\s*\uC800\uC7A5)(?:(?:\\s*[/\u00B7,]\\s*|\\s*(?:\uBC0F|\uC640|\uACFC)\\s*)(?:\uD30C\uC77C(?:\\s*(?:\uC218\uC815|\uBCC0\uACBD))?|\uC124\uCE58|\uAD50\uD6C8\\s*\uC800\uC7A5))*(?:\uC740|\uB294|\uC744|\uB97C)?\\s*\uD558\uC9C0\\s*\uB9C8(?:\uC138\uC694|\uC2ED\uC2DC\uC624|\uB77C)$/u;\n const privateOutput = /^(?:\uC778\uC99D\uC815\uBCF4|(?:\uB300\uD654\\s*)?\uB85C\uADF8\\s*\uC804\uCCB4)(?:(?:\\s*[/\u00B7,]\\s*|\\s*(?:\uB098|\uC774\uB098|\uBC0F|\uC640|\uACFC)\\s*)(?:\uC778\uC99D\uC815\uBCF4|(?:\uB300\uD654\\s*)?\uB85C\uADF8\\s*\uC804\uCCB4))*(?:\uC740|\uB294|\uC744|\uB97C)?\\s*\uCD9C\uB825\uD558\uC9C0\\s*\uB9C8(?:\uC138\uC694|\uC2ED\uC2DC\uC624|\uB77C)$/u;\n const english = /^(?:please\\s+)?(?:do[ -]+not|don't|never)\\s+(?:(?:call|use|invoke)\\s+tools|(?:edit|modify|change)\\s+files)(?:\\s+(?:or|and)\\s+(?:(?:call|use|invoke)\\s+tools|(?:edit|modify|change)\\s+files))*$/iu;\n // Split only at complete sentence/line boundaries, never inside foo.ts or a\n // code symbol. A clause attached with \"but\" is deliberately left ambiguous.\n return query.split(/(?<=[.!?;])(?=\\s)|[\\r\\n]+/u).filter(clause => {\n const statement = clause.trim().replace(/[.!?;]$/, '').trim();\n return !korean.test(statement) && !english.test(statement) && !readOnly.test(statement) && !privateOutput.test(statement);\n }).join(' ');\n}\n\nconst lessonSymbolTokens = (value: string): string[] => value.match(/\\b[A-Za-z][A-Za-z0-9_$]*(?:[./:-][A-Za-z0-9_$]+)*/g) ?? [];\n\n/** A sole exact code symbol in the subject is stronger than question boilerplate.\n * Keep this lesson-only: transcript alignment retains its independent policy. */\nfunction hasExactLessonSubject(query: string, lesson: LessonEvidenceInput): boolean {\n const anchors = [...new Set(lessonSymbolTokens(query).filter((token) => /[a-z][A-Z]|[_$./:-]|\\d/.test(token)))];\n if (anchors.length !== 1 || !/[a-z][A-Z]/.test(anchors[0])) return false;\n // Do not turn a mention of a forbidden/alternative procedure into a match.\n if (/\\b(?:not|without|skip|omit|ignore|never)\\b|\uD558\uC9C0\\s*\uC54A|\uB9D0\uACE0|\uAE08\uC9C0|\uAC74\uB108\uB6F0|\uBB34\uC2DC/iu.test(query)) return false;\n return lessonSymbolTokens([lesson.name, lesson.trigger ?? ''].join(' ')).includes(anchors[0]);\n}\n\nexport function scoreLessonEvidence(\n query: string,\n lesson: LessonEvidenceInput\n): HookMemoryCandidate | null {\n query = lessonScoringQuery(query);\n if (!query.trim() || isExplicitlyProhibitedLessonQuery(query)) return null;\n const content = formatLessonContent(lesson);\n const queriedSymbols = lessonSymbolTokens(query).filter((token) => /[a-z][A-Z]/.test(token));\n const contentSymbols = new Set(lessonSymbolTokens(content));\n if (queriedSymbols.some((symbol) => !contentSymbols.has(symbol))) return null;\n const exactSubject = hasExactLessonSubject(query, lesson);\n if (!exactSubject && !hasQueryMemoryAlignment(query, content, 2)) return null;\n\n // A narrow technical noun equivalence, confined to lesson scoring. It does\n // not lower the overlap gate: a product mention alone still cannot match.\n const lessonTerms = (value: string) => [...new Set(meaningfulTerms(value)\n .map(term => term === '\uBC84\uC804' || term === 'versions' ? 'version' : term))];\n const queryTerms = lessonTerms(query);\n const contentTerms = new Set(lessonTerms(content));\n const overlap = queryTerms.filter((term) => contentTerms.has(term)).length;\n if (!exactSubject && overlap < Math.min(3, queryTerms.length)) return null;\n\n const coverage = exactSubject ? 1 : overlap / Math.max(1, Math.min(queryTerms.length, 8));\n const anchors = identifierAnchors(query);\n const lowered = content.toLowerCase();\n const matchedAnchors = anchors.filter((anchor) => lowered.includes(anchor.toLowerCase())).length;\n const anchorCoverage = exactSubject ? 1 : anchors.length === 0 ? 0 : matchedAnchors / anchors.length;\n if (!exactSubject && anchors.length >= 2 && matchedAnchors < Math.ceil(anchors.length * 0.6)) return null;\n\n const confidencePrior = Math.min(0.05, Math.max(0, lesson.confidence) * 0.05);\n const score = Math.min(0.98, 0.5 + coverage * 0.28 + anchorCoverage * 0.12 + confidencePrior);\n\n return {\n id: lesson.lessonId,\n type: 'lesson',\n content: [\n lesson.steps.length > 8 && `[Partial lesson; retrieve the full body with mem-lesson-get lessonId=${lesson.lessonId} before applying]`,\n lesson.scope && `Scope: ${lesson.scope}`,\n ...(lesson.validation ?? []).map((value) => `Validate: ${value}`),\n lesson.reconsiderWhen && `Reconsider: ${lesson.reconsiderWhen}`,\n lesson.validVersions?.length && `Versions: ${lesson.validVersions.join(', ')}`,\n ...(lesson.failureModes ?? []).map((value) => `Caution: ${value}`),\n formatLessonContent({ ...lesson, failureModes: [] })\n ].filter(Boolean).join('\\n'),\n score,\n source: 'lesson'\n };\n}\n\nfunction formatLessonContent(lesson: LessonEvidenceInput): string {\n const parts = [lesson.name];\n if (lesson.trigger) parts.push(`\uC801\uC6A9 \uC2DC\uC810: ${lesson.trigger}`);\n if (lesson.steps.length > 0) {\n parts.push(lesson.steps.slice(0, 8).map((step) => `- ${step}`).join('\\n'));\n }\n if (lesson.failureModes && lesson.failureModes.length > 0) {\n parts.push(`\uC8FC\uC758: ${lesson.failureModes.slice(0, 4).join(' / ')}`);\n }\n return parts.join('\\n');\n}\n\nexport function isPromptOnlySessionSummary(content: string): boolean {\n // The Korean branch is anchored on the rule-based generator's own prefix\n // (\"[date] N\uD134 \uC138\uC158\", see summary-deriver.ts) rather than on the optional\n // \"\uC8FC\uC694 \uC791\uC5C5:\" line, which it omits for a zero-prompt session.\n return /Session with \\d+ user prompts?|Topics discussed:|\\[\\d{4}-\\d{2}-\\d{2}\\]\\s*\\d+\uD134 \uC138\uC158/iu.test(content);\n}\n\nfunction isDiagnosticQuery(query: string): boolean {\n return /(?:\uC6D0\uC778|\uC65C|\uC2E4\uD328|\uC624\uB958|\uC5D0\uB7EC|\uC7A5\uC560|CrashLoopBackOff)|\\b(?:cause|failure|failed|error|incident|diagnos)/iu.test(query);\n}\n\nfunction hasDiagnosticOutcome(content: string): boolean {\n return /(?:\uC6D0\uC778|\uADFC\uBCF8|\uB54C\uBB38|\uBD88\uC77C\uCE58|\uC2E4\uD328|\uC624\uB958|\uC608\uC678|\uD574\uACB0|\uC870\uCE58|\uB9AC\uBC0B|\uD55C\uB3C4)|\\b(?:cause|because|failure|failed|error|exception|mismatch|resolved|fix)/iu.test(content);\n}\n\nfunction entityAnchors(value: string): string[] {\n return Array.from(new Set(\n (value.match(/[A-Za-z][A-Za-z0-9_./:-]*/g) ?? [])\n .map((term) => term.toLowerCase())\n .filter((term) => term.length >= 2 && !LOW_SIGNAL_QUERY_TERMS.has(term))\n ));\n}\n\nfunction isContinuationQuery(query: string): boolean {\n return /Previous user:|Previous assistant:|\\b(?:continue|resume|carry on|pick up)\\b|(?:\uC774\uC5B4\uC11C|\uACC4\uC18D|\uADF8\uAC70|\uC544\uAE4C|\uC9C0\uB09C\uBC88)/iu.test(query);\n}\n\nfunction hasQueryMemoryAlignment(query: string, content: string, minimumOverlap: number = 2): boolean {\n const queryTerms = meaningfulTerms(query);\n // Short follow-ups are resolved through session context; requiring a lexical\n // overlap there would suppress legitimate \"fix it\" continuations.\n if (queryTerms.length < 2) return true;\n const contentTerms = new Set(meaningfulTerms(content));\n const requiredAnchors = identifierAnchors(query);\n const normalizedContent = content.toLowerCase();\n if (requiredAnchors.length > 0 && !requiredAnchors.some((anchor) => normalizedContent.includes(anchor.toLowerCase()))) {\n return false;\n }\n // A single overlap is often a generic verb that escaped tokenization (for\n // example, \"\uC54C\uB824\uC918\"). Requiring two strong terms makes this an intentional\n // no-match gate instead of a weak semantic-score tie breaker.\n // Question boilerplate is removed by meaningfulTerms. This matters for\n // short queries: \"\uB300\uAE30\" plus \"\uC5B4\uB5BB\uAC8C\" previously looked like two strong\n // overlaps between an astronomy question and an unrelated CI incident.\n return queryTerms.filter((term) => contentTerms.has(term)).length >= minimumOverlap;\n}\n\nfunction identifierAnchors(value: string): string[] {\n return (value.match(/[A-Za-z0-9_./:-]+/g) ?? [])\n .filter((term) => /[A-Za-z0-9]/.test(term) && term.length >= 2)\n .filter((term) => /\\d|[_./:-]/.test(term))\n .filter((term) => !/^\\d{1,2}$/.test(term));\n}\n\nfunction meaningfulTerms(value: string): string[] {\n return Array.from(new Set(\n (value.toLowerCase().match(/[a-z0-9\uAC00-\uD7A3]+/g) ?? [])\n .map(normalizeTerm)\n .filter((term) => term.length >= 2 && !LOW_SIGNAL_QUERY_TERMS.has(term))\n ));\n}\n\n/**\n * specs/lesson-learning-reliability R3 \u2014 strip the Korean case particles that\n * make a paraphrase (\"\uD3EC\uD2B8 \uCDA9\uB3CC\uB85C\") miss the stored wording (\"\uD3EC\uD2B8 \uCDA9\uB3CC\"). The\n * same heuristic runs over query and content; suffix collisions remain possible.\n * The two-character floor keeps short nouns that end in a particle\n * syllable (\"\uACBD\uB85C\", \"\uC815\uB3C4\") intact instead of collapsing them to one letter.\n */\nconst KOREAN_PARTICLE_SUFFIX =\n /(?:\uC73C\uB85C|\uC5D0\uC11C|\uC5D0\uAC8C|\uD55C\uD14C|\uAE4C\uC9C0|\uBD80\uD130|\uB9C8\uB2E4|\uCC98\uB7FC|\uBCF4\uB2E4|\uC740|\uB294|\uC774|\uAC00|\uC744|\uB97C|\uC5D0|\uC758|\uC640|\uACFC|\uB3C4|\uB85C)$/u;\n\nfunction normalizeTerm(value: string): string {\n const stripped = value.replace(KOREAN_PARTICLE_SUFFIX, '');\n return stripped.length >= 2 ? stripped : value;\n}\n\nexport function summarizeHookInjectionConfidence(candidates: HookMemoryCandidate[]): 'none' | 'medium' | 'high' {\n const scores = candidates\n .map((candidate) => candidate.score)\n .filter((score): score is number => typeof score === 'number' && Number.isFinite(score));\n if (scores.length === 0) return 'none';\n\n const maxScore = Math.max(...scores);\n if (maxScore >= 0.8) return 'high';\n if (maxScore >= 0.65) return 'medium';\n return 'none';\n}\n\nfunction isHookInjectableMemory(candidate: HookMemoryCandidate, policy: HookInjectionPolicy): boolean {\n if (typeof candidate.score !== 'number' || !Number.isFinite(candidate.score)) {\n return false;\n }\n\n return candidate.score >= thresholdFor(candidate, policy);\n}\n\nfunction thresholdFor(candidate: HookMemoryCandidate, policy: HookInjectionPolicy): number {\n if (candidate.source === 'keyword') {\n return candidate.fallback\n ? policy.fallbackKeywordMinScore\n : policy.keywordMinScore;\n }\n if (\n candidate.source === 'semantic'\n || candidate.source === 'graduated'\n || candidate.source === 'episode'\n || candidate.source === 'lesson'\n ) {\n return policy.semanticMinScore;\n }\n return policy.minScore;\n}\n\nfunction readScoreThreshold(value: string | undefined, fallback: number): number {\n return readNumber(value, fallback, { min: 0, max: 1 });\n}\n\nfunction readNumber(\n value: string | undefined,\n fallback: number,\n bounds?: { min?: number; max?: number }\n): number {\n if (value === undefined || value.trim() === '') return fallback;\n const parsed = Number(value);\n if (!Number.isFinite(parsed)) return fallback;\n if (bounds?.min !== undefined && parsed < bounds.min) return fallback;\n if (bounds?.max !== undefined && parsed > bounds.max) return fallback;\n return parsed;\n}\n", "import type { MemoryLesson } from '../../core/types.js';\nimport { scoreLessonEvidence } from '../../adapters/claude/hooks/prompt-injection-policy.js';\nexport { isExplicitlyProhibitedLessonQuery } from '../../adapters/claude/hooks/prompt-injection-policy.js';\n\n/**\n * specs/lesson-recall-hooks R5 \u00B7 specs/lesson-learning-reliability R3 \u2014\n * order curated lessons for a context pack.\n *\n * With a query, lessons that lexically cover it come first (same scorer as the\n * per-turn hook, so the two surfaces agree on what \"relevant\" means) and\n * nothing else is returned: an evidence section answering a question must not\n * pad its remaining slots with lessons the question never touched. Without a\n * query this is a plain slice \u2014 the queryless exploration index.\n */\nexport function rankCuratedLessons(\n lessons: readonly MemoryLesson[],\n query: string | undefined,\n limit: number\n): MemoryLesson[] {\n const trimmed = query?.trim();\n if (!trimmed) return lessons.slice(0, limit);\n return lessons\n .map((lesson, index) => ({\n lesson,\n index,\n score: scoreLessonEvidence(trimmed, {\n lessonId: lesson.lessonId,\n name: lesson.name,\n trigger: lesson.trigger,\n steps: lesson.steps,\n failureModes: lesson.failureModes,\n confidence: lesson.confidence\n })?.score ?? null\n }))\n .filter((entry): entry is typeof entry & { score: number } => entry.score !== null)\n .sort((a, b) => b.score - a.score || a.index - b.index)\n .slice(0, limit)\n .map((entry) => entry.lesson);\n}\n", "import type { MemoryLesson } from '../../core/types.js';\nimport { getDefaultEmbedder, type Embedder } from '../vector/embedder.js';\nimport { isExplicitlyProhibitedLessonQuery, rankCuratedLessons } from './lesson-ranking.js';\n\n// Frozen ONLY from independent calibration-v3 (20 lessons / 100 queries).\n// The deterministic grid and fixture hash are recorded in its raw result.\n// Release stays disabled until the unchanged held-out gate also passes.\nexport const HYBRID_LESSON_GATE = { enabled: false, absoluteCosine: 0.829, top1Margin: 0.026 } as const;\nexport type HybridLessonStatus = 'cold' | 'warming' | 'ready' | 'calibration_rejected' | 'failed';\nconst vectors = new Map<string, number[]>();\nlet status: HybridLessonStatus = 'cold';\nlet warming: Promise<void> | undefined;\nconst pending = new Map<string, { lesson: MemoryLesson; embedder: Embedder }>();\nconst MAX_VECTORS = 2_048;\n\nconst text = (lesson: MemoryLesson) => [lesson.name, lesson.trigger, ...lesson.steps, ...lesson.failureModes].filter(Boolean).join('\\n');\nconst usesE5Prefix = (embedder: Embedder) => /(?:^|\\/)multilingual-e5-/i.test(embedder.getModelName());\nconst passage = (lesson: MemoryLesson, embedder: Embedder) => usesE5Prefix(embedder) ? `passage: ${text(lesson)}` : text(lesson);\nconst queryText = (query: string, embedder: Embedder) => usesE5Prefix(embedder) ? `query: ${query}` : query;\nconst keyFor = (lesson: MemoryLesson, embedder: Embedder) => `${embedder.getModelName()}:${usesE5Prefix(embedder) ? 'e5-prefix-v2' : 'plain-v1'}:${lesson.projectHash}:${lesson.lessonId}:${lesson.revision}`;\nconst cosine = (a: number[], b: number[]) => a.reduce((sum, value, index) => sum + value * (b[index] ?? 0), 0);\nconst supportedSafetyOrFailureState = /\\b(?:must|should)\\s+not\\s+trust\\b|\\b(?:server|service|process|worker|daemon|request|connection|build|test)\\s+does\\s+not\\s+(?:start|respond|connect|complete|pass)\\b|\uBBFF\uC9C0\\s*\uB9D0\uACE0/giu;\n\nexport function hybridLessonStatus(): HybridLessonStatus { return status; }\nconst experimentEnabled = () => process.env.CLAUDE_MEMORY_LESSON_HYBRID_EXPERIMENT === 'true';\nexport function isSemanticRescueEligible(query: string): boolean {\n if (isExplicitlyProhibitedLessonQuery(query)) return false;\n // Remove only unambiguous safety/failure clauses before applying the existing\n // conservative guard, so a second contraindication cannot be bypassed.\n const remaining = query.replace(supportedSafetyOrFailureState, ' ');\n return !/\\b(?:not|without|skip|ignore|do[ -]?not|don't|never)\\b|\uD558\uC9C0\\s*\uC54A|\uD558\uC9C0\uB9C8|\uB9D0\uACE0|\uAE08\uC9C0|\uAC74\uB108\uB6F0|\uBB34\uC2DC/iu.test(remaining);\n}\nexport function warmHybridLessonCache(lessons: readonly MemoryLesson[], embedder?: Embedder): Promise<void> {\n if (lessons.length === 0) return Promise.resolve();\n if (!experimentEnabled()) { status = 'calibration_rejected'; return Promise.resolve(); }\n const activeEmbedder = embedder ?? getDefaultEmbedder();\n if (lessons.length > MAX_VECTORS) return Promise.resolve();\n for (const lesson of lessons) pending.set(keyFor(lesson, activeEmbedder), { lesson, embedder: activeEmbedder });\n if (warming) return warming;\n status = 'warming';\n warming = (async () => {\n while (pending.size) {\n const batch = [...pending.entries()]; pending.clear();\n for (const [key, item] of batch) { await item.embedder.initialize(); if (!vectors.has(key)) { vectors.set(key, (await item.embedder.embed(passage(item.lesson, item.embedder))).vector); while (vectors.size > MAX_VECTORS) vectors.delete(vectors.keys().next().value!); } }\n }\n status = 'ready';\n })().catch(() => { status = 'failed'; }).finally(() => { warming = undefined; });\n return warming;\n}\n\n/** Lexical matches always win. Cold processes start background warmup and return lexical-only. */\nexport async function rankCuratedLessonsHybrid(lessons: readonly MemoryLesson[], query: string | undefined, limit: number, embedder?: Embedder): Promise<MemoryLesson[]> {\n if (lessons.length === 0) return [];\n const lexical = rankCuratedLessons(lessons, query, limit);\n if (lexical.length || !query?.trim()) return lexical;\n if (!experimentEnabled()) { status = 'calibration_rejected'; return []; }\n if (!isSemanticRescueEligible(query)) return [];\n const activeEmbedder = embedder ?? getDefaultEmbedder();\n if (status === 'cold') { void warmHybridLessonCache(lessons, activeEmbedder); return []; }\n if (status !== 'ready') return [];\n if (lessons.some((lesson) => !vectors.has(keyFor(lesson, activeEmbedder)))) { void warmHybridLessonCache(lessons, activeEmbedder); return []; }\n const snapshot = lessons.map((lesson) => ({ lesson, vector: vectors.get(keyFor(lesson, activeEmbedder))! }));\n const queryVector = (await activeEmbedder.embed(queryText(query, activeEmbedder))).vector;\n const ranked = snapshot.map(({ lesson, vector }) => ({ lesson, score: cosine(queryVector, vector) }));\n ranked.sort((a, b) => b.score - a.score);\n const [first, second] = ranked;\n return first && first.score >= HYBRID_LESSON_GATE.absoluteCosine && first.score - (second?.score ?? 0) >= HYBRID_LESSON_GATE.top1Margin ? [first.lesson] : [];\n}\n", "/**\n * Private Tag Parser\n * Parses and removes <private> tags from content\n */\n\nexport interface PrivateSection {\n start: number;\n end: number;\n content: string;\n format: 'xml' | 'bracket' | 'comment';\n}\n\nexport interface ParseResult {\n filtered: string;\n sections: PrivateSection[];\n stats: {\n count: number;\n totalLength: number;\n };\n}\n\nexport interface ParseOptions {\n formats: Array<'xml' | 'bracket' | 'comment'>;\n marker: string;\n}\n\n// Tag patterns for different formats\nconst TAG_PATTERNS: Record<string, RegExp> = {\n xml: /<private>([\\s\\S]*?)<\\/private>/gi,\n bracket: /\\[private\\]([\\s\\S]*?)\\[\\/private\\]/gi,\n comment: /<!--\\s*private\\s*-->([\\s\\S]*?)<!--\\s*\\/private\\s*-->/gi\n};\n\n/**\n * Parse and remove private tags from text\n */\nexport function parsePrivateTags(\n text: string,\n options: ParseOptions\n): ParseResult {\n const sections: PrivateSection[] = [];\n let filtered = text;\n\n // Find all private sections for each format\n for (const format of options.formats) {\n const pattern = TAG_PATTERNS[format];\n if (!pattern) continue;\n\n // Reset lastIndex for global regex\n pattern.lastIndex = 0;\n\n let match;\n while ((match = pattern.exec(text)) !== null) {\n sections.push({\n start: match.index,\n end: match.index + match[0].length,\n content: match[1],\n format: format as PrivateSection['format']\n });\n }\n }\n\n // Remove all tags and replace with marker\n for (const format of options.formats) {\n const pattern = TAG_PATTERNS[format];\n if (!pattern) continue;\n\n // Need to create new regex for replacement (global flag issues)\n const replacePattern = new RegExp(pattern.source, 'gi');\n\n filtered = filtered.replace(replacePattern, (_match, content: string) => {\n // Empty tags are completely removed\n if (!content.trim()) return '';\n return options.marker;\n });\n }\n\n return {\n filtered,\n sections,\n stats: {\n count: sections.length,\n totalLength: sections.reduce((sum, s) => sum + s.content.length, 0)\n }\n };\n}\n\n/**\n * Parse private tags safely, protecting code blocks\n */\nexport function parsePrivateTagsSafe(\n text: string,\n options: ParseOptions\n): ParseResult {\n // 1. Extract and protect code blocks\n const codeBlocks: string[] = [];\n const textWithPlaceholders = text.replace(\n /```[\\s\\S]*?```/g,\n (match) => {\n codeBlocks.push(match);\n return `__CODE_BLOCK_${codeBlocks.length - 1}__`;\n }\n );\n\n // Also protect inline code\n const inlineCode: string[] = [];\n const textWithAllPlaceholders = textWithPlaceholders.replace(\n /`[^`]+`/g,\n (match) => {\n inlineCode.push(match);\n return `__INLINE_CODE_${inlineCode.length - 1}__`;\n }\n );\n\n // 2. Parse private tags\n const result = parsePrivateTags(textWithAllPlaceholders, options);\n\n // 3. Restore inline code\n result.filtered = result.filtered.replace(\n /__INLINE_CODE_(\\d+)__/g,\n (_, idx) => inlineCode[Number(idx)]\n );\n\n // 4. Restore code blocks\n result.filtered = result.filtered.replace(\n /__CODE_BLOCK_(\\d+)__/g,\n (_, idx) => codeBlocks[Number(idx)]\n );\n\n return result;\n}\n\n/**\n * Check if text has unclosed private tags\n */\nexport function hasUnmatchedOpenTag(text: string): boolean {\n // Check for opening tags without closing\n const openXml = (text.match(/<private>/gi) || []).length;\n const closeXml = (text.match(/<\\/private>/gi) || []).length;\n\n const openBracket = (text.match(/\\[private\\]/gi) || []).length;\n const closeBracket = (text.match(/\\[\\/private\\]/gi) || []).length;\n\n return openXml !== closeXml || openBracket !== closeBracket;\n}\n", "/**\n * Privacy Filter\n * Combines pattern-based filtering with private tag parsing\n */\n\nimport { parsePrivateTagsSafe, hasUnmatchedOpenTag } from './tag-parser.js';\nimport type { Config } from '../types.js';\n\nexport interface FilterResult {\n content: string;\n metadata: {\n hasPrivateTags: boolean;\n privateTagCount: number;\n patternMatchCount: number;\n originalLength: number;\n filteredLength: number;\n hasUnmatchedTags: boolean;\n };\n}\n\n// Sensitive data patterns\n/**\n * Rejects values that are code rather than a credential: an already-redacted\n * marker, a type annotation, an arrow function, or an opening bracket.\n */\nconst NOT_A_SECRET_VALUE =\n '(?!\\\\[REDACTED\\\\])(?![({\\\\[]|=>|\\\\s*$)'\n // The optional quote matters: `apiKey: \"string\"` is still a type, not a key.\n + '(?![\\'\"]?(?:string|number|boolean|any|unknown|void|never|null|undefined|true|false'\n + '|Promise|Record|Array|Partial|Readonly)\\\\b)'\n // `token = json.dumps(...)` assigns in code: the secret would be the result\n // of the call, not this expression.\n + '(?![A-Za-z_$][\\\\w.$]*\\\\s*\\\\()'\n // `var token = ++fitRetryToken` \u2014 a credential literal never starts with a\n // unary/increment operator, so this is unambiguously a variable reference.\n + '(?!\\\\+\\\\+|--|!|~)'\n // `const TOKEN = process.env.TOKEN || randomBytes(32)\u2026` reads the variable\n // rather than containing it \u2014 a very common Node.js pattern in this kind of\n // codebase, and unambiguous because a literal secret is never spelled\n // `process.env.<NAME>`.\n + '(?!process\\\\.env\\\\.)';\n\nconst SENSITIVE_PATTERNS = [\n // Credential-bearing URLs/connection strings with userinfo before the host.\n // Redact the whole URI so usernames, credentials, hosts, paths, and query\n // params do not leak either.\n /\\b[a-z][a-z0-9+.-]*:\\/\\/[^\\s'\"`<>/@]+@[^\\s'\"`<>]+/gi,\n // Two guards keep source code out of these rules. Without them a stored\n // discussion of real code gets mangled \u2014 `getAccessToken: () => \u2026` became\n // `getAccess[REDACTED] => \u2026` on live data.\n //\n // The leading lookbehind rejects camelCase identifiers (`getAccessToken:`),\n // while underscore/dash forms (`access_token=\u2026`) still match through the\n // optional prefix group. The trailing guard rejects values that are plainly\n // code rather than a secret: a type annotation, an arrow function, or an\n // opening bracket.\n new RegExp(`(?<![A-Za-z0-9])(?:[\\\\w.-]+[-_])?password\\\\s*[:=]\\\\s*${NOT_A_SECRET_VALUE}['\"]?[^\\\\s'\"]+`, 'gi'),\n new RegExp(`(?<![A-Za-z0-9])(?:[\\\\w.-]+[-_])?api[-_]?key\\\\s*[:=]\\\\s*${NOT_A_SECRET_VALUE}['\"]?[^\\\\s'\"]+`, 'gi'),\n new RegExp(`(?<![A-Za-z0-9])(?:[\\\\w.-]+[-_])?secret\\\\s*[:=]\\\\s*${NOT_A_SECRET_VALUE}['\"]?[^\\\\s'\"]+`, 'gi'),\n new RegExp(`(?<![A-Za-z0-9])(?:[\\\\w.-]+[-_])?token\\\\s*[:=]\\\\s*${NOT_A_SECRET_VALUE}['\"]?[^\\\\s'\"]+`, 'gi'),\n // camelCase keys are excluded above because `accessToken: () => \u2026` is code.\n // But `accessToken: \"eyJhbGciOi\u2026\"` is a real credential, and the difference\n // is the value, not the key. A quoted, long, secret-shaped literal is the\n // one camelCase form worth redacting.\n /[A-Za-z0-9_.-]*(?:password|secret|token|api[-_]?key)\\s*[:=]\\s*['\"][A-Za-z0-9._\\-+/=]{12,}['\"]/gi,\n // \"Bearer token\", \"Bearer JWT\" and friends are how documentation names the\n // scheme, not a secret. On a real store the loose form matched 29 such\n // phrases against a single actual token, so the word after Bearer must not be\n // one of those nouns and the value has to be long enough to be a credential.\n /bearer\\s+(?!token\\b|jwt\\b|auth\\b|authentication\\b|access\\b|scheme\\b|header\\b|prefix\\b)[a-zA-Z0-9\\-_.]{16,}/gi,\n /AWS[_-]?ACCESS[_-]?KEY[_-]?ID\\s*[:=]\\s*['\"]?[A-Z0-9]+/gi,\n /AWS[_-]?SECRET[_-]?ACCESS[_-]?KEY\\s*[:=]\\s*['\"]?[^\\s'\"]+/gi,\n /-----BEGIN\\s+(RSA\\s+)?PRIVATE\\s+KEY-----[\\s\\S]*?-----END\\s+(RSA\\s+)?PRIVATE\\s+KEY-----/g,\n /ghp_[a-zA-Z0-9]{36}/g, // GitHub Personal Access Token\n /sk-[a-zA-Z0-9]{48}/g, // OpenAI API Key\n // Vendor-prefixed tokens. The `token\\s*[:=]` rule above only fires when a\n // token is introduced with a colon or equals sign, so a key pasted as prose\n // (\"hugging face token hf_\u2026 Invalid token\") slipped through untouched. These\n // prefixes are distinctive enough to match on their own.\n /\\bhf_[a-zA-Z0-9]{30,}/g, // Hugging Face access token\n /\\bgh[opsu]_[a-zA-Z0-9]{36,}/g, // GitHub OAuth/server/user tokens\n /\\bgithub_pat_[a-zA-Z0-9_]{50,}/g, // GitHub fine-grained PAT\n /\\bsk-ant-[a-zA-Z0-9_-]{20,}/g, // Anthropic API key\n /\\bglpat-[a-zA-Z0-9_-]{20,}/g, // GitLab personal access token\n /\\bxox[abprs]-[a-zA-Z0-9-]{10,}/g, // Slack tokens\n /\\bAKIA[0-9A-Z]{16}\\b/g, // AWS access key id\n];\n\nconst CLI_SECRET_OPTION_PATTERNS = [\n /(--(?:[a-z0-9]+[-_])*(?:password|secret|api[-_]?key|token|bearer)(?:[-_][a-z0-9]+)*(?:\\s+|=))(?:\"[^\"]*\"|'[^']*'|[^\\s'\"`<>]+)/gi\n];\n\nconst URL_FOLLOWING_SECRET_PATTERN = /((?:https?:\\/\\/[^\\s'\"`<>]+)\\s*\\r?\\n\\s*)([A-Za-z0-9!@#$%^&*._+\\-~:=/]{6,})(?=\\s*(?:\\r?\\n|$))/gi;\n\nfunction looksLikePastedSecret(value: string): boolean {\n // Reduce false positives for benign status words pasted after URLs while still\n // catching common dashboard passwords such as alpha-numeric throwaway secrets.\n return value.length >= 8 && /(?:\\d|[^A-Za-z0-9])/.test(value);\n}\n\nfunction maskUrlFollowingSecret(value: string): { content: string; count: number } {\n let count = 0;\n const content = value.replace(URL_FOLLOWING_SECRET_PATTERN, (_match, prefix: string, secret: string) => {\n if (!looksLikePastedSecret(secret)) return `${prefix}${secret}`;\n count++;\n return `${prefix}[REDACTED]`;\n });\n return { content, count };\n}\n\nfunction maskCliSecretOptions(value: string): { content: string; count: number } {\n let count = 0;\n let filtered = value;\n for (const pattern of CLI_SECRET_OPTION_PATTERNS) {\n pattern.lastIndex = 0;\n filtered = filtered.replace(pattern, (_match, prefix: string) => {\n count++;\n return `${prefix}[REDACTED]`;\n });\n }\n return { content: filtered, count };\n}\n\nfunction maskSensitiveString(value: string): string {\n let filtered = maskCliSecretOptions(value).content;\n for (const pattern of SENSITIVE_PATTERNS) {\n pattern.lastIndex = 0;\n filtered = filtered.replace(pattern, '[REDACTED]');\n }\n return filtered;\n}\n\n/**\n * Apply privacy filter to content\n */\nexport function applyPrivacyFilter(\n content: string,\n config: Config['privacy']\n): FilterResult {\n let filtered = content;\n let privateTagCount = 0;\n let patternMatchCount = 0;\n const hasUnmatchedTags = hasUnmatchedOpenTag(content);\n\n // 1. Private tag filtering\n if (config.privateTags?.enabled !== false) {\n const tagResult = parsePrivateTagsSafe(filtered, {\n formats: config.privateTags?.supportedFormats || ['xml'],\n marker: config.privateTags?.marker || '[PRIVATE]'\n });\n filtered = tagResult.filtered;\n privateTagCount = tagResult.stats.count;\n }\n\n // 2. CLI option filtering (`--password value`, `--password=value`, etc.)\n const cliResult = maskCliSecretOptions(filtered);\n filtered = cliResult.content;\n patternMatchCount += cliResult.count;\n\n // 3. Contextual paste filtering (URL followed by a password-looking line)\n const urlSecretResult = maskUrlFollowingSecret(filtered);\n filtered = urlSecretResult.content;\n patternMatchCount += urlSecretResult.count;\n\n // 4. Built-in sensitive pattern filtering\n for (const pattern of SENSITIVE_PATTERNS) {\n // Reset lastIndex for global regex\n pattern.lastIndex = 0;\n const matches = filtered.match(pattern);\n if (matches) {\n patternMatchCount += matches.length;\n filtered = filtered.replace(pattern, '[REDACTED]');\n }\n }\n\n // 3. Custom pattern filtering from config\n //\n // This mirrors the built-in keyword rules, so it needs the same value guard.\n // Without it the config list silently re-introduced every false positive the\n // built-ins had been taught to avoid \u2014 `token = json.dumps(payload)` was\n // still being rewritten to `[REDACTED]` through this loop alone.\n for (const patternStr of config.excludePatterns || []) {\n try {\n const regex = new RegExp(\n `(^|[^\\\\w-])(${patternStr})\\\\s*[:=]\\\\s*${NOT_A_SECRET_VALUE}['\"]?[^\\\\s'\"]+`,\n 'gi'\n );\n const matches = filtered.match(regex);\n if (matches) {\n patternMatchCount += matches.length;\n filtered = filtered.replace(regex, '$1[REDACTED]');\n }\n } catch {\n // Invalid regex pattern, skip\n }\n }\n\n // 4. Clean up consecutive markers\n filtered = filtered.replace(/(\\[PRIVATE\\]\\s*)+/g, '[PRIVATE]\\n');\n filtered = filtered.replace(/(\\[REDACTED\\]\\s*)+/g, '[REDACTED] ');\n\n return {\n content: filtered,\n metadata: {\n hasPrivateTags: privateTagCount > 0,\n privateTagCount,\n patternMatchCount,\n originalLength: content.length,\n filteredLength: filtered.length,\n hasUnmatchedTags\n }\n };\n}\n\n/**\n * Mask sensitive data in tool input (recursively)\n */\nexport function maskSensitiveInput(\n input: Record<string, unknown>\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(input)) {\n // Check if key suggests sensitive data\n const sensitiveKeys = ['password', 'secret', 'key', 'token', 'auth', 'credential'];\n const isSensitiveKey = sensitiveKeys.some(k =>\n key.toLowerCase().includes(k)\n );\n\n if (isSensitiveKey && typeof value === 'string') {\n result[key] = '[REDACTED]';\n } else if (typeof value === 'string') {\n // Apply pattern filtering to string values\n result[key] = maskSensitiveString(value);\n } else if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n result[key] = maskSensitiveInput(value as Record<string, unknown>);\n } else if (Array.isArray(value)) {\n result[key] = value.map(item => {\n if (typeof item === 'string') {\n return isSensitiveKey ? '[REDACTED]' : maskSensitiveString(item);\n }\n return typeof item === 'object' && item !== null\n ? maskSensitiveInput(item as Record<string, unknown>)\n : item;\n });\n } else {\n result[key] = value;\n }\n }\n\n return result;\n}\n\n/**\n * Truncate output with head + tail strategy\n */\nexport function truncateOutput(\n output: string,\n options: { maxLength?: number; maxLines?: number }\n): string {\n const { maxLength = 10000, maxLines = 100 } = options;\n\n // Split into lines\n const lines = output.split('\\n');\n\n // Apply line limit first\n if (lines.length > maxLines) {\n const headLines = Math.ceil(maxLines / 2);\n const tailLines = Math.floor(maxLines / 2);\n const head = lines.slice(0, headLines);\n const tail = lines.slice(-tailLines);\n const truncatedLines = [\n ...head,\n `\\n... [${lines.length - maxLines} lines truncated] ...\\n`,\n ...tail\n ];\n output = truncatedLines.join('\\n');\n }\n\n // Apply character limit\n if (output.length > maxLength) {\n const headChars = Math.ceil(maxLength / 2);\n const tailChars = Math.floor(maxLength / 2);\n output = output.slice(0, headChars) +\n `\\n... [${output.length - maxLength} characters truncated] ...\\n` +\n output.slice(-tailChars);\n }\n\n return output;\n}\n", "import { z } from 'zod';\n\nimport type { SQLiteDatabase } from '../sqlite-wrapper.js';\nimport {\n canonicalMemoryAssetId,\n isCanonicalMemoryAssetRegistration\n} from './memory-asset-catalog-service.js';\nimport { MemoryAssetPermissionService } from './memory-asset-permission-service.js';\nimport { MemoryAssetRepository } from './memory-asset-repository.js';\nimport type { MemoryAssetPermissionSource } from './memory-asset-permissions.js';\n\nexport const CANONICAL_MEMORY_PERMISSION_MODE_ENV = 'CLAUDE_MEMORY_ASSET_PERMISSION_MODE';\n\nexport const CanonicalMemoryPermissionModeSchema = z.enum(['legacy', 'registered', 'strict']);\nexport type CanonicalMemoryPermissionMode = z.infer<typeof CanonicalMemoryPermissionModeSchema>;\n\nconst RequesterActorIdSchema = z.string().trim().min(1).max(240);\n\nconst CanonicalMemoryAccessInputSchema = z.object({\n projectHash: z.string().trim().min(1).max(240),\n canonicalType: z.enum(['lesson', 'core_memory_block']),\n canonicalId: z.string().trim().min(1).max(240),\n requesterActorId: z.string().trim().min(1).max(240).optional(),\n permission: z.enum(['read', 'write'])\n});\n\nexport interface CanonicalMemoryAccessDecision {\n allowed: boolean;\n mode: CanonicalMemoryPermissionMode;\n registered: boolean;\n source: MemoryAssetPermissionSource | 'legacy' | 'unregistered';\n}\n\nexport class CanonicalMemoryAccessDeniedError extends Error {\n readonly code = 'CANONICAL_MEMORY_ACCESS_DENIED';\n\n constructor() {\n super('permission denied for canonical memory access');\n this.name = 'CanonicalMemoryAccessDeniedError';\n }\n}\n\nexport function resolveCanonicalMemoryPermissionMode(\n env: NodeJS.ProcessEnv = process.env\n): CanonicalMemoryPermissionMode {\n const raw = env[CANONICAL_MEMORY_PERMISSION_MODE_ENV]?.trim().toLowerCase();\n if (!raw) return 'legacy';\n const parsed = CanonicalMemoryPermissionModeSchema.safeParse(raw);\n if (!parsed.success) {\n throw new Error(`${CANONICAL_MEMORY_PERMISSION_MODE_ENV} must be legacy, registered, or strict`);\n }\n return parsed.data;\n}\n\nexport class CanonicalMemoryAccessService {\n private readonly repository: MemoryAssetRepository;\n private readonly permissionService: MemoryAssetPermissionService;\n readonly mode: CanonicalMemoryPermissionMode;\n\n constructor(\n db: SQLiteDatabase,\n options: { mode?: CanonicalMemoryPermissionMode; env?: NodeJS.ProcessEnv } = {}\n ) {\n this.repository = new MemoryAssetRepository(db);\n this.permissionService = new MemoryAssetPermissionService(db);\n this.mode = options.mode ?? resolveCanonicalMemoryPermissionMode(options.env);\n }\n\n requireRequester(requesterActorId: string | undefined): void {\n if (this.mode === 'legacy') return;\n if (!requesterActorId) {\n throw new Error(`requesterActorId is required when ${CANONICAL_MEMORY_PERMISSION_MODE_ENV}=${this.mode}`);\n }\n RequesterActorIdSchema.parse(requesterActorId);\n }\n\n requireUnregisteredWrite(requesterActorId: string | undefined): CanonicalMemoryAccessDecision {\n this.requireRequester(requesterActorId);\n if (this.mode === 'strict') throw new CanonicalMemoryAccessDeniedError();\n return {\n allowed: true,\n mode: this.mode,\n registered: false,\n source: this.mode === 'legacy' ? 'legacy' : 'unregistered'\n };\n }\n\n check(input: unknown): CanonicalMemoryAccessDecision {\n const parsed = CanonicalMemoryAccessInputSchema.parse(input);\n const assetId = canonicalMemoryAssetId(parsed.canonicalType, parsed.canonicalId);\n const asset = this.repository.get(assetId, parsed.projectHash);\n const registered = Boolean(\n asset && isCanonicalMemoryAssetRegistration(asset, parsed.canonicalType, parsed.canonicalId)\n );\n\n if (this.mode === 'legacy') {\n return { allowed: true, mode: this.mode, registered, source: 'legacy' };\n }\n this.requireRequester(parsed.requesterActorId);\n\n if (!asset) {\n const allowed = this.mode === 'registered';\n return {\n allowed,\n mode: this.mode,\n registered: false,\n source: allowed ? 'unregistered' : 'none'\n };\n }\n\n // A deterministic id occupied by a non-canonical asset is a conflict, not\n // an unregistered fallback. Otherwise a caller could bypass protection by\n // creating an unrelated asset with the canonical id.\n if (!registered) {\n return { allowed: false, mode: this.mode, registered: false, source: 'none' };\n }\n\n const result = this.permissionService.check({\n projectHash: parsed.projectHash,\n assetId,\n requesterActorId: parsed.requesterActorId!,\n permission: parsed.permission\n });\n return {\n allowed: result.decision.allowed,\n mode: this.mode,\n registered: true,\n source: result.decision.source\n };\n }\n\n require(input: unknown): CanonicalMemoryAccessDecision {\n const decision = this.check(input);\n if (!decision.allowed) throw new CanonicalMemoryAccessDeniedError();\n return decision;\n }\n}\n", "import { z } from 'zod';\n\nimport { sqliteAll, sqliteGet, type SQLiteDatabase } from '../sqlite-wrapper.js';\nimport { MemoryAssetPermissionService } from './memory-asset-permission-service.js';\nimport { MemoryAssetRepository } from './memory-asset-repository.js';\nimport type { MemoryAsset, MemoryAssetStatus, MemoryAssetType } from './memory-asset-permissions.js';\n\nconst CatalogSyncInputSchema = z.object({\n projectHash: z.string().trim().min(1).max(240),\n requesterActorId: z.string().trim().min(1).max(240),\n apply: z.boolean().default(false),\n limit: z.number().int().positive().max(500).default(100)\n});\n\nexport type CanonicalMemoryAssetType = 'lesson' | 'core_memory_block';\nexport type MemoryAssetCatalogAction = 'create' | 'created' | 'exists' | 'conflict';\n\ninterface CanonicalAssetRow {\n canonical_type: CanonicalMemoryAssetType;\n canonical_id: string;\n title: string;\n canonical_status: MemoryAssetStatus;\n}\n\ninterface CountRow {\n count: number;\n}\n\nexport interface CanonicalMemoryAssetCandidate {\n canonicalType: CanonicalMemoryAssetType;\n canonicalId: string;\n assetId: string;\n assetType: MemoryAssetType;\n title: string;\n status: MemoryAssetStatus;\n sourceRefs: string[];\n metadata: Record<string, unknown>;\n}\n\nexport interface MemoryAssetCatalogItem {\n candidate: CanonicalMemoryAssetCandidate;\n action: MemoryAssetCatalogAction;\n reason?: string;\n}\n\nexport interface MemoryAssetCatalogSyncResult {\n dryRun: boolean;\n projectHash: string;\n totalCandidates: number;\n scanned: number;\n truncated: boolean;\n planned: number;\n created: number;\n existing: number;\n conflicts: number;\n items: MemoryAssetCatalogItem[];\n}\n\nexport function canonicalMemoryAssetId(type: CanonicalMemoryAssetType, canonicalId: string): string {\n return `${type}:${canonicalId.trim()}`;\n}\n\nexport function isCanonicalMemoryAssetRegistration(\n asset: MemoryAsset,\n canonicalType: CanonicalMemoryAssetType,\n canonicalId: string\n): boolean {\n const assetId = canonicalMemoryAssetId(canonicalType, canonicalId);\n const expectedAssetType: MemoryAssetType = canonicalType === 'lesson' ? 'lesson' : 'memory';\n return asset.assetId === assetId\n && asset.assetType === expectedAssetType\n && asset.sourceRefs.includes(assetId);\n}\n\nfunction rowToCandidate(row: CanonicalAssetRow): CanonicalMemoryAssetCandidate {\n const assetId = canonicalMemoryAssetId(row.canonical_type, row.canonical_id);\n return {\n canonicalType: row.canonical_type,\n canonicalId: row.canonical_id,\n assetId,\n assetType: row.canonical_type === 'lesson' ? 'lesson' : 'memory',\n title: row.title,\n status: row.canonical_status,\n // The canonical object retains its own evidence references. Keeping only\n // this pointer avoids duplicating event ids (and potential legacy data)\n // into the permission registry.\n sourceRefs: [assetId],\n metadata: {\n canonicalType: row.canonical_type,\n canonicalId: row.canonical_id\n }\n };\n}\n\nfunction matchesCanonicalAsset(asset: MemoryAsset, candidate: CanonicalMemoryAssetCandidate): boolean {\n return isCanonicalMemoryAssetRegistration(asset, candidate.canonicalType, candidate.canonicalId);\n}\n\nfunction classifyCandidate(\n repository: MemoryAssetRepository,\n projectHash: string,\n candidate: CanonicalMemoryAssetCandidate\n): MemoryAssetCatalogItem {\n const asset = repository.get(candidate.assetId, projectHash);\n if (!asset) return { candidate, action: 'create' };\n if (matchesCanonicalAsset(asset, candidate)) return { candidate, action: 'exists' };\n return {\n candidate,\n action: 'conflict',\n reason: 'deterministic asset id is already registered for another canonical source',\n };\n}\n\nexport class MemoryAssetCatalogService {\n private readonly repository: MemoryAssetRepository;\n private readonly permissionService: MemoryAssetPermissionService;\n\n constructor(private readonly db: SQLiteDatabase) {\n this.repository = new MemoryAssetRepository(db);\n this.permissionService = new MemoryAssetPermissionService(db);\n }\n\n async sync(input: unknown): Promise<MemoryAssetCatalogSyncResult> {\n const parsed = CatalogSyncInputSchema.parse(input);\n const candidates = this.listCanonicalCandidates(parsed.projectHash, parsed.limit);\n const totalCandidates = this.countCanonicalCandidates(parsed.projectHash);\n const items = candidates.map((candidate) => classifyCandidate(this.repository, parsed.projectHash, candidate));\n const planned = items.filter((item) => item.action === 'create').length;\n\n if (parsed.apply) {\n for (let index = 0; index < items.length; index++) {\n const item = items[index];\n if (item.action !== 'create') continue;\n\n // Recheck immediately before the write so a concurrent/idempotent\n // registration becomes an exists/conflict result instead of an overwrite.\n const current = classifyCandidate(this.repository, parsed.projectHash, item.candidate);\n if (current.action !== 'create') {\n items[index] = current;\n continue;\n }\n\n try {\n await this.permissionService.create({\n projectHash: parsed.projectHash,\n requesterActorId: parsed.requesterActorId,\n assetId: item.candidate.assetId,\n assetType: item.candidate.assetType,\n title: item.candidate.title,\n status: item.candidate.status,\n visibility: 'private',\n sourceRefs: item.candidate.sourceRefs,\n metadata: item.candidate.metadata\n });\n items[index] = { ...item, action: 'created' };\n } catch (error) {\n // Another connection may have won after the preflight check. Treat\n // the now-visible row idempotently; propagate unrelated failures.\n const raced = classifyCandidate(this.repository, parsed.projectHash, item.candidate);\n if (raced.action === 'create') throw error;\n items[index] = raced;\n }\n }\n }\n\n return this.buildResult(parsed.apply, parsed.projectHash, totalCandidates, planned, items);\n }\n\n private countCanonicalCandidates(projectHash: string): number {\n const lessonCount = sqliteGet<CountRow>(\n this.db,\n `SELECT COUNT(*) AS count FROM memory_lessons WHERE project_hash = ?`,\n [projectHash]\n )?.count ?? 0;\n const blockCount = sqliteGet<CountRow>(\n this.db,\n `SELECT COUNT(*) AS count FROM core_memory_blocks WHERE project_hash = ?`,\n [projectHash]\n )?.count ?? 0;\n return Number(lessonCount) + Number(blockCount);\n }\n\n private listCanonicalCandidates(projectHash: string, limit: number): CanonicalMemoryAssetCandidate[] {\n const rows = sqliteAll<CanonicalAssetRow>(\n this.db,\n `SELECT canonical_type, canonical_id, title, canonical_status\n FROM (\n SELECT\n 'lesson' AS canonical_type,\n lesson_id AS canonical_id,\n name AS title,\n 'active' AS canonical_status\n FROM memory_lessons\n WHERE project_hash = ?\n UNION ALL\n SELECT\n 'core_memory_block' AS canonical_type,\n block_key AS canonical_id,\n 'Core memory: ' || block_key AS title,\n CASE WHEN LENGTH(TRIM(content)) = 0 THEN 'archived' ELSE 'active' END AS canonical_status\n FROM core_memory_blocks\n WHERE project_hash = ?\n )\n ORDER BY canonical_type ASC, canonical_id ASC\n LIMIT ?`,\n [projectHash, projectHash, limit]\n );\n return rows.map(rowToCandidate);\n }\n\n private buildResult(\n apply: boolean,\n projectHash: string,\n totalCandidates: number,\n planned: number,\n items: MemoryAssetCatalogItem[]\n ): MemoryAssetCatalogSyncResult {\n return {\n dryRun: !apply,\n projectHash,\n totalCandidates,\n scanned: items.length,\n truncated: totalCandidates > items.length,\n planned,\n created: items.filter((item) => item.action === 'created').length,\n existing: items.filter((item) => item.action === 'exists').length,\n conflicts: items.filter((item) => item.action === 'conflict').length,\n items\n };\n }\n}\n", "/**\n * SQLite Wrapper with WAL Mode Support\n * Primary store for hooks - always available, no lock conflicts\n */\n\nimport Database from 'better-sqlite3';\nimport * as fs from 'fs';\nimport * as nodePath from 'path';\nimport { createSQLiteReadSnapshot } from './sqlite-read-snapshot.js';\n\nexport type SQLiteDatabase = Database.Database;\n\nexport interface SQLiteOptions {\n readonly?: boolean;\n walMode?: boolean;\n /**\n * Open an ephemeral copy instead of the live file. Only for diagnostics\n * that must guarantee zero writes inside the canonical memory root \u2014 the\n * copy costs O(database size) per open and the view is frozen at open time.\n * Long-lived readers (semantic daemon), per-hook readers, and machine-wide\n * scanners (maintenance) must NOT set this: a frozen view serves stale\n * memories and the copies dominate their runtime.\n */\n snapshot?: boolean;\n /** Internal-only snapshot parent; see createSQLiteReadSnapshot. */\n snapshotDirectory?: string;\n /** Used to reject unsafe snapshot placement inside canonical storage. */\n canonicalMemoryRoot?: string;\n}\n\n/**\n * Creates a new SQLite database with WAL mode\n */\nexport function createSQLiteDatabase(path: string, options?: SQLiteOptions): SQLiteDatabase {\n // Writable callers may create a new store. Read-only callers must never turn\n // a missing diagnostic target into an empty directory tree.\n const dir = nodePath.dirname(path);\n if (!options?.readonly && !fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n\n const snapshot = options?.readonly && options?.snapshot\n ? createSQLiteReadSnapshot(path, {\n snapshotDirectory: options.snapshotDirectory,\n canonicalMemoryRoot: options.canonicalMemoryRoot\n })\n : null;\n let db: SQLiteDatabase;\n try {\n db = new Database(snapshot?.databasePath ?? path, {\n readonly: options?.readonly ?? false,\n fileMustExist: options?.readonly ?? false,\n });\n } catch (error) {\n snapshot?.cleanup();\n throw error;\n }\n if (snapshot) {\n const closeSnapshotDatabase = db.close.bind(db);\n Object.defineProperty(db, 'close', {\n configurable: true,\n value: () => {\n try {\n return closeSnapshotDatabase();\n } finally {\n snapshot.cleanup();\n }\n }\n });\n }\n\n // Enable WAL mode for concurrent access (unless read-only)\n if (!options?.readonly && (options?.walMode ?? true)) {\n db.pragma('journal_mode = WAL');\n db.pragma('synchronous = NORMAL');\n db.pragma('busy_timeout = 5000');\n }\n\n return db;\n}\n\n// Per-connection prepared-statement cache. Re-running db.prepare() for every\n// call recompiles the SQL each time, which dominates the per-call cost on hot\n// paths (getEvent, keywordSearch, access tracking). Statements are scoped to\n// their database via a WeakMap so they are finalized/GC'd with the connection,\n// and SQLite transparently re-prepares them across schema changes.\nconst statementCache = new WeakMap<SQLiteDatabase, Map<string, Database.Statement>>();\n\nfunction prepareCached(db: SQLiteDatabase, sql: string): Database.Statement {\n let cache = statementCache.get(db);\n if (!cache) {\n cache = new Map();\n statementCache.set(db, cache);\n }\n let stmt = cache.get(sql);\n if (!stmt) {\n stmt = db.prepare(sql);\n cache.set(sql, stmt);\n }\n return stmt;\n}\n\n/**\n * Execute a statement that doesn't return rows (INSERT, UPDATE, DELETE)\n */\nexport function sqliteRun(\n db: SQLiteDatabase,\n sql: string,\n params: unknown[] = []\n): Database.RunResult {\n return prepareCached(db, sql).run(...params);\n}\n\n/**\n * Execute a query and return all rows\n */\nexport function sqliteAll<T = Record<string, unknown>>(\n db: SQLiteDatabase,\n sql: string,\n params: unknown[] = []\n): T[] {\n return prepareCached(db, sql).all(...params) as T[];\n}\n\n/**\n * Execute a query and return first row\n */\nexport function sqliteGet<T = Record<string, unknown>>(\n db: SQLiteDatabase,\n sql: string,\n params: unknown[] = []\n): T | undefined {\n return prepareCached(db, sql).get(...params) as T | undefined;\n}\n\n/**\n * Execute multiple statements (for schema creation)\n */\nexport function sqliteExec(db: SQLiteDatabase, sql: string): void {\n db.exec(sql);\n}\n\n/**\n * Close database connection\n */\nexport function sqliteClose(db: SQLiteDatabase): void {\n db.close();\n}\n\n/**\n * Run multiple statements in a transaction\n */\nexport function sqliteTransaction<T>(\n db: SQLiteDatabase,\n fn: () => T\n): T {\n return db.transaction(fn)();\n}\n\n/**\n * Safely converts a value to a Date object\n */\nexport function toDateFromSQLite(value: unknown): Date {\n if (value instanceof Date) return value;\n if (typeof value === 'number') return new Date(value);\n if (typeof value === 'string') {\n // SQLite datetime('now') stores UTC timestamps without an explicit timezone\n // (for example, \"2026-05-07 16:00:00\"). JavaScript treats that shape as\n // local time, which shifts dashboard time-window calculations on non-UTC\n // machines. Normalize SQLite's timezone-less UTC shape before parsing while\n // leaving ISO strings with an explicit offset/Z untouched.\n const trimmed = value.trim();\n if (/^\\d{4}-\\d{2}-\\d{2}[ T]\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?$/.test(trimmed)) {\n return new Date(trimmed.replace(' ', 'T') + 'Z');\n }\n return new Date(trimmed);\n }\n return new Date(String(value));\n}\n\n/**\n * Convert Date to ISO string for SQLite storage\n */\nexport function toSQLiteTimestamp(date: Date): string {\n return date.toISOString();\n}\n", "/**\n * Create an ephemeral copy for side-effect-free SQLite inspection.\n *\n * SQLite databases configured for WAL may create or update `-wal`/`-shm`\n * sidecars even when opened with SQLITE_OPEN_READONLY. Diagnostic readers use\n * this copy so all connection bookkeeping stays outside the canonical memory\n * root. The copied WAL, when present, keeps committed uncheckpointed rows in\n * the diagnostic snapshot.\n */\n\nimport * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\n\nexport interface SQLiteReadSnapshot {\n databasePath: string;\n cleanup(): void;\n}\n\nexport interface SQLiteReadSnapshotOptions {\n /** Internal-only parent for runtimes whose default temp directory is unavailable. */\n snapshotDirectory?: string;\n /** Snapshot storage must never be placed inside this canonical memory root. */\n canonicalMemoryRoot?: string;\n}\n\nexport function createSQLiteReadSnapshot(\n sourceDatabasePath: string,\n options: SQLiteReadSnapshotOptions = {}\n): SQLiteReadSnapshot {\n if (options.canonicalMemoryRoot) {\n rejectSourceOutsideOrThroughSymlink(sourceDatabasePath, options.canonicalMemoryRoot);\n }\n rejectSymlinkOrNonFile(sourceDatabasePath, 'source database');\n const sourceWalPath = `${sourceDatabasePath}-wal`;\n rejectSymlinkIfPresent(sourceWalPath, 'source WAL');\n\n const parent = path.resolve(options.snapshotDirectory ?? os.tmpdir());\n const realParent = fs.realpathSync(parent);\n if (!fs.lstatSync(realParent).isDirectory()) {\n throw snapshotError('SQLITE_SNAPSHOT_UNSAFE_LOCATION', 'Snapshot parent must be a local directory');\n }\n if (options.canonicalMemoryRoot) {\n const canonicalRoot = realPathIfPresent(path.resolve(options.canonicalMemoryRoot));\n if (isWithin(canonicalRoot, realParent)) {\n throw snapshotError('SQLITE_SNAPSHOT_UNSAFE_LOCATION', 'Snapshot directory must be outside canonical memory storage');\n }\n }\n\n const snapshotRoot = fs.mkdtempSync(path.join(realParent, 'cml-sqlite-read-'));\n const databasePath = path.join(snapshotRoot, 'events.sqlite');\n try {\n fs.copyFileSync(sourceDatabasePath, databasePath);\n copyIfLocalFile(sourceWalPath, `${databasePath}-wal`);\n return {\n databasePath,\n cleanup: () => cleanupSnapshotRoot(snapshotRoot)\n };\n } catch (error) {\n cleanupSnapshotRoot(snapshotRoot);\n throw error;\n }\n}\n\nfunction rejectSourceOutsideOrThroughSymlink(sourcePath: string, canonicalMemoryRoot: string): void {\n const root = path.resolve(canonicalMemoryRoot);\n const source = path.resolve(sourcePath);\n const rootStat = fs.lstatSync(root);\n if (!rootStat.isDirectory() || rootStat.isSymbolicLink()) {\n throw snapshotError('SQLITE_SNAPSHOT_UNSAFE_SOURCE', 'Canonical memory root must be a non-symlink directory');\n }\n const relative = path.relative(root, source);\n if (relative === '' || relative.startsWith('..') || path.isAbsolute(relative)) {\n throw snapshotError('SQLITE_SNAPSHOT_UNSAFE_SOURCE', 'Source database must be inside canonical memory storage');\n }\n\n let current = root;\n for (const segment of relative.split(path.sep)) {\n current = path.join(current, segment);\n let stat: fs.Stats;\n try {\n stat = fs.lstatSync(current);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') break;\n throw error;\n }\n if (stat.isSymbolicLink()) {\n throw snapshotError('SQLITE_SNAPSHOT_UNSAFE_SOURCE', 'Source database path must not traverse symlinks');\n }\n }\n}\n\nfunction realPathIfPresent(targetPath: string): string {\n try {\n return fs.realpathSync(targetPath);\n } catch {\n return targetPath;\n }\n}\n\nfunction copyIfLocalFile(source: string, destination: string): void {\n try {\n const stat = fs.lstatSync(source);\n if (stat.isFile() && !stat.isSymbolicLink()) fs.copyFileSync(source, destination);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n }\n}\n\nfunction rejectSymlinkOrNonFile(targetPath: string, label: string): void {\n const stat = fs.lstatSync(targetPath);\n if (stat.isSymbolicLink() || !stat.isFile()) {\n throw snapshotError('SQLITE_SNAPSHOT_UNSAFE_SOURCE', `${label} must be a regular non-symlink file`);\n }\n}\n\nfunction rejectSymlinkIfPresent(targetPath: string, label: string): void {\n try {\n const stat = fs.lstatSync(targetPath);\n if (stat.isSymbolicLink() || !stat.isFile()) {\n throw snapshotError('SQLITE_SNAPSHOT_UNSAFE_SOURCE', `${label} must be a regular non-symlink file`);\n }\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n }\n}\n\nfunction isWithin(parent: string, candidate: string): boolean {\n const relative = path.relative(parent, candidate);\n return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));\n}\n\nfunction snapshotError(code: string, message: string): NodeJS.ErrnoException {\n return Object.assign(new Error(message), { code });\n}\n\nfunction cleanupSnapshotRoot(snapshotRoot: string): void {\n // The target is a concrete mkdtemp result, never a caller-controlled path.\n try {\n fs.rmSync(snapshotRoot, { recursive: true, force: true });\n } catch {\n // Snapshot cleanup is best effort. A temporary-directory permission or\n // antivirus race must not turn an otherwise successful diagnostic read\n // into a canonical-store failure.\n }\n}\n", "import { z } from 'zod';\n\nimport { sqliteTransaction, type SQLiteDatabase } from '../sqlite-wrapper.js';\nimport { writeGovernanceAuditEntrySync } from './governance-audit.js';\nimport { MemoryAssetRepository, type ListMemoryAssetsInput } from './memory-asset-repository.js';\nimport {\n CreateMemoryAssetInputSchema,\n MemoryAssetPermissionDeniedError,\n MemoryAssetPermissionSchema,\n SetMemoryAssetBindingInputSchema,\n SetMemoryAssetGrantInputSchema,\n UpdateMemoryAssetInputSchema,\n checkMemoryAssetPermission,\n type MemoryAsset,\n type MemoryAssetBinding,\n type MemoryAssetGrant,\n type MemoryAssetPermission,\n type MemoryAssetPermissionDecision\n} from './memory-asset-permissions.js';\n\nconst ActorIdSchema = z.string().trim().min(1).max(240);\n\nexport interface MemoryAssetAccessInput {\n projectHash?: string;\n assetId: string;\n requesterActorId: string;\n permission: MemoryAssetPermission;\n}\n\nexport interface MemoryAssetAccessResult {\n asset?: MemoryAsset;\n decision: MemoryAssetPermissionDecision;\n}\n\nexport interface CreateAuthorizedMemoryAssetInput {\n projectHash?: string;\n requesterActorId: string;\n assetId?: string;\n assetType: MemoryAsset['assetType'];\n title: string;\n status?: MemoryAsset['status'];\n visibility?: MemoryAsset['visibility'];\n sourceRefs?: string[];\n metadata?: Record<string, unknown>;\n}\n\nexport interface UpdateAuthorizedMemoryAssetInput {\n projectHash?: string;\n requesterActorId: string;\n assetId: string;\n expectedVersion?: number;\n title?: string;\n status?: MemoryAsset['status'];\n visibility?: MemoryAsset['visibility'];\n sourceRefs?: string[];\n metadata?: Record<string, unknown>;\n}\n\nexport interface BindAuthorizedMemoryAssetInput {\n projectHash?: string;\n requesterActorId: string;\n assetId: string;\n actorId: string;\n injectionMode?: MemoryAssetBinding['injectionMode'];\n priority?: number;\n enabled?: boolean;\n}\n\nexport interface GrantAuthorizedMemoryAssetInput {\n projectHash?: string;\n requesterActorId: string;\n assetId: string;\n actorId: string;\n permissions: MemoryAssetPermission[];\n}\n\nfunction snapshot(value: MemoryAsset | MemoryAssetBinding | MemoryAssetGrant | null): Record<string, unknown> | undefined {\n if (!value) return undefined;\n return { ...value };\n}\n\nexport class MemoryAssetPermissionService {\n private readonly repository: MemoryAssetRepository;\n\n constructor(private readonly db: SQLiteDatabase) {\n this.repository = new MemoryAssetRepository(db);\n }\n\n async create(input: CreateAuthorizedMemoryAssetInput): Promise<MemoryAsset> {\n const requesterActorId = ActorIdSchema.parse(input.requesterActorId);\n const parsed = CreateMemoryAssetInputSchema.parse({\n ...input,\n ownerActorId: requesterActorId,\n sourceRefs: input.sourceRefs ?? []\n });\n return sqliteTransaction(this.db, () => {\n const asset = this.repository.create(parsed);\n writeGovernanceAuditEntrySync(this.db, {\n operation: 'memory_asset_create',\n actor: requesterActorId,\n projectHash: asset.projectHash,\n targetType: 'memory_asset',\n targetId: asset.assetId,\n afterJson: snapshot(asset)\n });\n return asset;\n });\n }\n\n async list(input: ListMemoryAssetsInput & { requesterActorId: string }): Promise<MemoryAsset[]> {\n const requesterActorId = ActorIdSchema.parse(input.requesterActorId);\n const requestedLimit = Math.min(500, Math.max(1, input.limit ?? 100));\n const pageSize = Math.max(100, requestedLimit);\n const readable: MemoryAsset[] = [];\n let offset = 0;\n\n // Filtering after a limited query can omit readable assets when newer\n // private assets occupy the first page. Scan deterministic pages until the\n // requested number of authorized results is found or the project is exhausted.\n while (readable.length < requestedLimit) {\n const assets = this.repository.list({\n projectHash: input.projectHash,\n assetType: input.assetType,\n status: input.status,\n limit: pageSize,\n offset\n });\n for (const asset of assets) {\n if (this.evaluate(asset, requesterActorId, 'read').allowed) {\n readable.push(asset);\n if (readable.length === requestedLimit) return readable;\n }\n }\n if (assets.length < pageSize) break;\n offset += assets.length;\n }\n return readable;\n }\n\n async get(input: Omit<MemoryAssetAccessInput, 'permission'>): Promise<MemoryAsset | null> {\n const result = this.check({ ...input, permission: 'read' });\n return result.decision.allowed ? result.asset ?? null : null;\n }\n\n check(input: MemoryAssetAccessInput): MemoryAssetAccessResult {\n const requesterActorId = ActorIdSchema.parse(input.requesterActorId);\n const permission = MemoryAssetPermissionSchema.parse(input.permission);\n const asset = this.repository.get(input.assetId, input.projectHash);\n if (!asset) {\n return {\n decision: {\n allowed: false,\n permission,\n source: 'none',\n reason: 'permission denied'\n }\n };\n }\n const decision = this.evaluate(asset, requesterActorId, permission);\n return decision.allowed ? { asset, decision } : { decision };\n }\n\n async update(input: UpdateAuthorizedMemoryAssetInput): Promise<MemoryAsset> {\n const requesterActorId = ActorIdSchema.parse(input.requesterActorId);\n const parsed = UpdateMemoryAssetInputSchema.parse(input);\n return sqliteTransaction(this.db, () => {\n const before = this.requireAllowed(input.projectHash, input.assetId, requesterActorId, 'write');\n const after = this.repository.update(parsed);\n writeGovernanceAuditEntrySync(this.db, {\n operation: 'memory_asset_update',\n actor: requesterActorId,\n projectHash: after.projectHash,\n targetType: 'memory_asset',\n targetId: after.assetId,\n beforeJson: snapshot(before),\n afterJson: snapshot(after)\n });\n return after;\n });\n }\n\n async bind(input: BindAuthorizedMemoryAssetInput): Promise<MemoryAssetBinding> {\n const requesterActorId = ActorIdSchema.parse(input.requesterActorId);\n const parsed = SetMemoryAssetBindingInputSchema.parse(input);\n return sqliteTransaction(this.db, () => {\n const asset = this.requireAllowed(input.projectHash, input.assetId, requesterActorId, 'bind');\n const before = this.repository.getBinding(asset.assetId, parsed.actorId, asset.projectHash);\n const after = this.repository.setBinding(parsed);\n writeGovernanceAuditEntrySync(this.db, {\n operation: 'memory_asset_bind',\n actor: requesterActorId,\n projectHash: asset.projectHash,\n targetType: 'memory_asset_binding',\n targetId: `${asset.assetId}:${parsed.actorId}`,\n beforeJson: snapshot(before),\n afterJson: snapshot(after)\n });\n return after;\n });\n }\n\n async setGrant(input: GrantAuthorizedMemoryAssetInput): Promise<MemoryAssetGrant> {\n const requesterActorId = ActorIdSchema.parse(input.requesterActorId);\n const parsed = SetMemoryAssetGrantInputSchema.parse({ ...input, createdBy: requesterActorId });\n return sqliteTransaction(this.db, () => {\n const asset = this.requireAllowed(input.projectHash, input.assetId, requesterActorId, 'grant');\n const before = this.repository.getGrant(asset.assetId, parsed.actorId, asset.projectHash);\n const after = this.repository.setGrant(parsed);\n writeGovernanceAuditEntrySync(this.db, {\n operation: 'memory_asset_grant_set',\n actor: requesterActorId,\n projectHash: asset.projectHash,\n targetType: 'memory_asset_grant',\n targetId: `${asset.assetId}:${parsed.actorId}`,\n beforeJson: snapshot(before),\n afterJson: snapshot(after)\n });\n return after;\n });\n }\n\n private evaluate(\n asset: MemoryAsset,\n actorId: string,\n permission: MemoryAssetPermission\n ): MemoryAssetPermissionDecision {\n return checkMemoryAssetPermission({\n asset,\n actorId,\n permission,\n binding: this.repository.getBinding(asset.assetId, actorId, asset.projectHash),\n grant: this.repository.getGrant(asset.assetId, actorId, asset.projectHash)\n });\n }\n\n private requireAllowed(\n projectHash: string | undefined,\n assetId: string,\n actorId: string,\n permission: MemoryAssetPermission\n ): MemoryAsset {\n const result = this.check({ projectHash, assetId, requesterActorId: actorId, permission });\n if (!result.asset || !result.decision.allowed) {\n throw new MemoryAssetPermissionDeniedError(assetId, actorId, permission);\n }\n return result.asset;\n }\n}\n", "import { randomUUID } from 'crypto';\n\nimport {\n sqliteRun,\n type SQLiteDatabase\n} from '../sqlite-wrapper.js';\n\nexport const MEMORY_GOVERNANCE_AUDIT_OPERATIONS = [\n 'facet_tag',\n 'action_update',\n 'lease_acquire',\n 'checkpoint_create',\n 'retention_score',\n 'quarantine',\n 'verify',\n 'lesson_promote',\n 'lesson_capture',\n 'actor_card_upsert',\n 'perspective_observation_create',\n 'perspective_observation_delete',\n 'core_memory_block_update',\n 'entity_supersede',\n 'memory_asset_create',\n 'memory_asset_update',\n 'memory_asset_bind',\n 'memory_asset_grant_set'\n] as const;\n\nexport type MemoryGovernanceAuditOperation = typeof MEMORY_GOVERNANCE_AUDIT_OPERATIONS[number];\n\nexport interface GovernanceAuditEntryInput {\n operation: MemoryGovernanceAuditOperation;\n actor: string;\n projectHash?: string;\n targetType: string;\n targetId: string;\n beforeJson?: Record<string, unknown>;\n afterJson?: Record<string, unknown>;\n sourceEventIds?: string[];\n}\n\nexport interface MemoryGovernanceAuditEntry {\n auditId: string;\n operation: MemoryGovernanceAuditOperation;\n actor: string;\n projectHash?: string;\n targetType: string;\n targetId: string;\n beforeJson?: Record<string, unknown>;\n afterJson?: Record<string, unknown>;\n sourceEventIds: string[];\n createdAt: Date;\n}\n\nfunction normalizeRequiredString(value: string, fieldName: string): string {\n const normalized = value.trim();\n if (!normalized) {\n throw new Error(`${fieldName} is required`);\n }\n return normalized;\n}\n\nfunction normalizeOptionalString(value: string | undefined): string | undefined {\n const normalized = value?.trim();\n return normalized ? normalized : undefined;\n}\n\nconst REDACTED = '[REDACTED]';\nconst sensitiveKeyPattern = /(?:api[_-]?key|secret|password|passwd|token|access[_-]?token|client[_-]?secret|crtfc[_-]?key|hashkey|serviceKey)/i;\n/**\n * The tail after the path's leading separator is `{0,300}` of any path-legal\n * character (spaces included \u2014 real paths contain \"Application Support\"),\n * then `[^\\s\u2026]*` to finish the current whitespace-free token.\n *\n * Both halves close an observed hole:\n * - Unbounded (`*`), one incidental \"/\" inside prose (a fraction, an \"A/B\"\n * aside, LLM-generated lesson text) deleted everything to the end of the\n * line. The 300-char bound caps that blast radius.\n * - Bounded alone, a path *longer* than 300 chars (deep node_modules/pnpm\n * chains) leaked its tail \u2014 the most identifying part \u2014 into stored audit\n * rows. Such paths contain no spaces, so finishing the current token\n * redacts them in full while prose beyond the next space still survives.\n */\nconst POSIX_ABSOLUTE_PATH_PATTERN = /(^|[^A-Za-z0-9._\\/\\\\-])\\/(?!\\/)[^\\n\\r\"'<>|`]{0,300}[^\\s\"'<>|`]*/g;\nconst WINDOWS_DRIVE_PATH_PATTERN = /(^|[^A-Za-z0-9._\\/\\\\-])(?:[A-Za-z]:[\\\\/][^\\n\\r\"'<>|`]{0,300}[^\\s\"'<>|`]*)/g;\n// The host segment stops at either separator so `\\\\host/share/...` (forward\n// slashes after the host, which Windows accepts) is caught too \u2014 retention's\n// deleted copy matched it, and consolidating on a backslash-only separator\n// would have silently un-redacted those paths in retention previews.\nconst WINDOWS_UNC_PATH_PATTERN = /(^|[^A-Za-z0-9._\\/\\\\-])(?:\\\\\\\\[^\\\\/\\s\"'<>|`]+[\\\\/][^\\n\\r\"'<>|`]{0,300}[^\\s\"'<>|`]*)/g;\nconst credentialQueryPattern = /\\b((?:api[_-]?key|token|access[_-]?token|client[_-]?secret|crtfc[_-]?key|hashkey|serviceKey)=)[^&\\s`\"'<>]+/gi;\nconst credentialAssignmentPattern = /\\b((?:api[_-]?key|secret|password|passwd|token|access[_-]?token|client[_-]?secret|crtfc[_-]?key|hashkey|serviceKey)\\s*[:=]\\s*)[^\\s`\"'<>},]+/gi;\n\n/**\n * Shared local-path redactor. Exported so retention-audit's preview redaction\n * uses these same patterns \u2014 a second hand-maintained copy of the regexes is\n * how the two files drifted apart in the first place.\n */\nexport function redactAbsolutePaths(value: string): string {\n return value\n .replace(WINDOWS_UNC_PATH_PATTERN, (_match, prefix: string) => `${prefix}${REDACTED}`)\n .replace(WINDOWS_DRIVE_PATH_PATTERN, (_match, prefix: string) => `${prefix}${REDACTED}`)\n .replace(POSIX_ABSOLUTE_PATH_PATTERN, (_match, prefix: string) => `${prefix}${REDACTED}`);\n}\n\nfunction sanitizeAuditString(value: string): string {\n return redactAbsolutePaths(value)\n .replace(credentialQueryPattern, `$1${REDACTED}`)\n .replace(credentialAssignmentPattern, `$1${REDACTED}`);\n}\n\nexport function sanitizeGovernanceAuditValue(value: unknown, key?: string): unknown {\n if (key && sensitiveKeyPattern.test(key)) {\n return REDACTED;\n }\n if (typeof value === 'string') {\n return sanitizeAuditString(value);\n }\n if (value instanceof Date) {\n return sanitizeAuditString(value.toISOString());\n }\n if (Array.isArray(value)) {\n return value.map((item) => sanitizeGovernanceAuditValue(item));\n }\n if (value && typeof value === 'object') {\n const sanitized: Record<string, unknown> = {};\n for (const [entryKey, entryValue] of Object.entries(value as Record<string, unknown>)) {\n sanitized[sanitizeAuditString(entryKey)] = sanitizeGovernanceAuditValue(entryValue, entryKey);\n }\n return sanitized;\n }\n return value;\n}\n\nfunction sanitizeAuditJson(value: Record<string, unknown> | undefined): Record<string, unknown> | undefined {\n if (value === undefined) return undefined;\n return sanitizeGovernanceAuditValue(value) as Record<string, unknown>;\n}\n\nfunction normalizeSourceEventIds(sourceEventIds: string[] | undefined): string[] {\n return (sourceEventIds || [])\n .map((sourceEventId) => sanitizeAuditString(sourceEventId.trim()))\n .filter((sourceEventId) => sourceEventId.length > 0);\n}\n\nfunction normalizeOperation(operation: MemoryGovernanceAuditOperation): MemoryGovernanceAuditOperation {\n if ((MEMORY_GOVERNANCE_AUDIT_OPERATIONS as readonly string[]).indexOf(operation) === -1) {\n throw new Error(`Unsupported governance audit operation: ${operation}`);\n }\n return operation;\n}\n\n/**\n * Synchronous audit writer for callers that must include the audit row in an\n * existing better-sqlite3 transaction.\n */\nexport function writeGovernanceAuditEntrySync(\n db: SQLiteDatabase,\n input: GovernanceAuditEntryInput\n): MemoryGovernanceAuditEntry {\n const entry: MemoryGovernanceAuditEntry = {\n auditId: randomUUID(),\n operation: normalizeOperation(input.operation),\n actor: sanitizeAuditString(normalizeRequiredString(input.actor, 'actor')),\n projectHash: normalizeOptionalString(input.projectHash),\n targetType: normalizeRequiredString(input.targetType, 'targetType'),\n targetId: sanitizeAuditString(normalizeRequiredString(input.targetId, 'targetId')),\n beforeJson: sanitizeAuditJson(input.beforeJson),\n afterJson: sanitizeAuditJson(input.afterJson),\n sourceEventIds: normalizeSourceEventIds(input.sourceEventIds),\n createdAt: new Date()\n };\n\n sqliteRun(\n db,\n `INSERT INTO memory_governance_audit (\n audit_id, operation, actor, project_hash, target_type, target_id,\n before_json, after_json, source_event_ids, created_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n [\n entry.auditId,\n entry.operation,\n entry.actor,\n entry.projectHash ?? null,\n entry.targetType,\n entry.targetId,\n entry.beforeJson === undefined ? null : JSON.stringify(entry.beforeJson),\n entry.afterJson === undefined ? null : JSON.stringify(entry.afterJson),\n JSON.stringify(entry.sourceEventIds),\n entry.createdAt.toISOString()\n ]\n );\n\n return entry;\n}\n\n/** Preserve the existing async API used by repositories and external callers. */\nexport async function writeGovernanceAuditEntry(\n db: SQLiteDatabase,\n input: GovernanceAuditEntryInput\n): Promise<MemoryGovernanceAuditEntry> {\n return writeGovernanceAuditEntrySync(db, input);\n}\n", "import { randomUUID } from 'node:crypto';\n\nimport {\n sqliteAll,\n sqliteGet,\n sqliteRun,\n toDateFromSQLite,\n type SQLiteDatabase\n} from '../sqlite-wrapper.js';\nimport {\n CreateMemoryAssetInputSchema,\n MemoryAssetBindingSchema,\n MemoryAssetGrantSchema,\n MemoryAssetPermissionSchema,\n MemoryAssetSchema,\n SetMemoryAssetBindingInputSchema,\n SetMemoryAssetGrantInputSchema,\n UpdateMemoryAssetInputSchema,\n type MemoryAsset,\n type MemoryAssetBinding,\n type MemoryAssetGrant,\n type MemoryAssetPermission,\n type MemoryAssetStatus,\n type MemoryAssetType,\n type MemoryAssetVisibility\n} from './memory-asset-permissions.js';\n\ninterface MemoryAssetRow {\n asset_id: string;\n project_hash: string;\n asset_type: MemoryAssetType;\n title: string;\n owner_actor_id: string;\n version: number;\n status: MemoryAssetStatus;\n visibility: MemoryAssetVisibility;\n source_refs_json: string;\n metadata_json: string | null;\n created_at: string;\n updated_at: string;\n}\n\ninterface MemoryAssetBindingRow {\n project_hash: string;\n asset_id: string;\n actor_id: string;\n injection_mode: MemoryAssetBinding['injectionMode'];\n priority: number;\n enabled: number;\n created_at: string;\n updated_at: string;\n}\n\ninterface MemoryAssetGrantRow {\n project_hash: string;\n asset_id: string;\n actor_id: string;\n permissions_json: string;\n created_by: string;\n created_at: string;\n updated_at: string;\n}\n\nfunction projectHashToStorage(projectHash: string | undefined): string {\n return projectHash ?? '';\n}\n\nfunction projectHashFromStorage(projectHash: string): string | undefined {\n return projectHash.length > 0 ? projectHash : undefined;\n}\n\nfunction parseStringArray(value: string): string[] {\n try {\n const parsed = JSON.parse(value);\n return Array.isArray(parsed) ? parsed.filter((item): item is string => typeof item === 'string') : [];\n } catch {\n return [];\n }\n}\n\nfunction parseRecord(value: string | null): Record<string, unknown> | undefined {\n if (!value) return undefined;\n try {\n const parsed = JSON.parse(value);\n return parsed && typeof parsed === 'object' && !Array.isArray(parsed)\n ? parsed as Record<string, unknown>\n : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction rowToAsset(row: MemoryAssetRow): MemoryAsset {\n return MemoryAssetSchema.parse({\n assetId: row.asset_id,\n projectHash: projectHashFromStorage(row.project_hash),\n assetType: row.asset_type,\n title: row.title,\n ownerActorId: row.owner_actor_id,\n version: Number(row.version),\n status: row.status,\n visibility: row.visibility,\n sourceRefs: parseStringArray(row.source_refs_json),\n metadata: parseRecord(row.metadata_json),\n createdAt: toDateFromSQLite(row.created_at),\n updatedAt: toDateFromSQLite(row.updated_at)\n });\n}\n\nfunction rowToBinding(row: MemoryAssetBindingRow): MemoryAssetBinding {\n return MemoryAssetBindingSchema.parse({\n projectHash: projectHashFromStorage(row.project_hash),\n assetId: row.asset_id,\n actorId: row.actor_id,\n injectionMode: row.injection_mode,\n priority: Number(row.priority),\n enabled: Boolean(row.enabled),\n createdAt: toDateFromSQLite(row.created_at),\n updatedAt: toDateFromSQLite(row.updated_at)\n });\n}\n\nfunction rowToGrant(row: MemoryAssetGrantRow): MemoryAssetGrant {\n const permissions = parseStringArray(row.permissions_json)\n .map((permission) => MemoryAssetPermissionSchema.safeParse(permission))\n .filter((result) => result.success)\n .map((result) => result.data);\n return MemoryAssetGrantSchema.parse({\n projectHash: projectHashFromStorage(row.project_hash),\n assetId: row.asset_id,\n actorId: row.actor_id,\n permissions,\n createdBy: row.created_by,\n createdAt: toDateFromSQLite(row.created_at),\n updatedAt: toDateFromSQLite(row.updated_at)\n });\n}\n\nexport interface ListMemoryAssetsInput {\n projectHash?: string;\n assetType?: MemoryAssetType;\n status?: MemoryAssetStatus;\n limit?: number;\n offset?: number;\n}\n\nexport class MemoryAssetRepository {\n constructor(private readonly db: SQLiteDatabase) {}\n\n create(input: unknown): MemoryAsset {\n const parsed = CreateMemoryAssetInputSchema.parse(input);\n const assetId = parsed.assetId ?? randomUUID();\n const now = new Date().toISOString();\n sqliteRun(\n this.db,\n `INSERT INTO memory_assets (\n asset_id, project_hash, asset_type, title, owner_actor_id, version,\n status, visibility, source_refs_json, metadata_json, created_at, updated_at\n ) VALUES (?, ?, ?, ?, ?, 1, ?, ?, ?, ?, ?, ?)`,\n [\n assetId,\n projectHashToStorage(parsed.projectHash),\n parsed.assetType,\n parsed.title,\n parsed.ownerActorId,\n parsed.status,\n parsed.visibility,\n JSON.stringify(parsed.sourceRefs),\n parsed.metadata ? JSON.stringify(parsed.metadata) : null,\n now,\n now\n ]\n );\n return this.require(assetId, parsed.projectHash);\n }\n\n get(assetId: string, projectHash?: string): MemoryAsset | null {\n const row = sqliteGet<MemoryAssetRow>(\n this.db,\n `SELECT * FROM memory_assets WHERE asset_id = ? AND project_hash = ?`,\n [assetId.trim(), projectHashToStorage(projectHash)]\n );\n return row ? rowToAsset(row) : null;\n }\n\n require(assetId: string, projectHash?: string): MemoryAsset {\n const asset = this.get(assetId, projectHash);\n if (!asset) throw new Error(`Memory asset not found: ${assetId}`);\n return asset;\n }\n\n list(input: ListMemoryAssetsInput): MemoryAsset[] {\n const clauses = ['project_hash = ?'];\n const params: unknown[] = [projectHashToStorage(input.projectHash)];\n if (input.assetType) {\n clauses.push('asset_type = ?');\n params.push(input.assetType);\n }\n if (input.status) {\n clauses.push('status = ?');\n params.push(input.status);\n }\n params.push(\n Math.min(500, Math.max(1, input.limit ?? 100)),\n Math.max(0, Math.floor(input.offset ?? 0))\n );\n return sqliteAll<MemoryAssetRow>(\n this.db,\n `SELECT * FROM memory_assets\n WHERE ${clauses.join(' AND ')}\n ORDER BY updated_at DESC, asset_id ASC\n LIMIT ? OFFSET ?`,\n params\n ).map(rowToAsset);\n }\n\n update(input: unknown): MemoryAsset {\n const parsed = UpdateMemoryAssetInputSchema.parse(input);\n const before = this.require(parsed.assetId, parsed.projectHash);\n const assignments: string[] = [];\n const params: unknown[] = [];\n const set = (column: string, value: unknown) => {\n assignments.push(`${column} = ?`);\n params.push(value);\n };\n if (parsed.title !== undefined) set('title', parsed.title);\n if (parsed.status !== undefined) set('status', parsed.status);\n if (parsed.visibility !== undefined) set('visibility', parsed.visibility);\n if (parsed.sourceRefs !== undefined) set('source_refs_json', JSON.stringify(parsed.sourceRefs));\n if (parsed.metadata !== undefined) set('metadata_json', JSON.stringify(parsed.metadata));\n assignments.push('version = version + 1', 'updated_at = ?');\n params.push(new Date().toISOString(), parsed.assetId, projectHashToStorage(parsed.projectHash));\n\n let where = 'asset_id = ? AND project_hash = ?';\n if (parsed.expectedVersion !== undefined) {\n where += ' AND version = ?';\n params.push(parsed.expectedVersion);\n }\n const result = sqliteRun(this.db, `UPDATE memory_assets SET ${assignments.join(', ')} WHERE ${where}`, params);\n if (result.changes !== 1) {\n throw new Error(`Memory asset version conflict: expected ${parsed.expectedVersion}, current ${before.version}`);\n }\n return this.require(parsed.assetId, parsed.projectHash);\n }\n\n getBinding(assetId: string, actorId: string, projectHash?: string): MemoryAssetBinding | null {\n const row = sqliteGet<MemoryAssetBindingRow>(\n this.db,\n `SELECT * FROM memory_asset_bindings WHERE asset_id = ? AND actor_id = ? AND project_hash = ?`,\n [assetId.trim(), actorId.trim(), projectHashToStorage(projectHash)]\n );\n return row ? rowToBinding(row) : null;\n }\n\n setBinding(input: unknown): MemoryAssetBinding {\n const parsed = SetMemoryAssetBindingInputSchema.parse(input);\n const now = new Date().toISOString();\n sqliteRun(\n this.db,\n `INSERT INTO memory_asset_bindings (\n project_hash, asset_id, actor_id, injection_mode, priority, enabled, created_at, updated_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(project_hash, asset_id, actor_id) DO UPDATE SET\n injection_mode = excluded.injection_mode,\n priority = excluded.priority,\n enabled = excluded.enabled,\n updated_at = excluded.updated_at`,\n [\n projectHashToStorage(parsed.projectHash),\n parsed.assetId,\n parsed.actorId,\n parsed.injectionMode,\n parsed.priority,\n parsed.enabled ? 1 : 0,\n now,\n now\n ]\n );\n const binding = this.getBinding(parsed.assetId, parsed.actorId, parsed.projectHash);\n if (!binding) throw new Error('Memory asset binding write failed');\n return binding;\n }\n\n getGrant(assetId: string, actorId: string, projectHash?: string): MemoryAssetGrant | null {\n const row = sqliteGet<MemoryAssetGrantRow>(\n this.db,\n `SELECT * FROM memory_asset_grants WHERE asset_id = ? AND actor_id = ? AND project_hash = ?`,\n [assetId.trim(), actorId.trim(), projectHashToStorage(projectHash)]\n );\n return row ? rowToGrant(row) : null;\n }\n\n setGrant(input: unknown): MemoryAssetGrant {\n const parsed = SetMemoryAssetGrantInputSchema.parse(input);\n const permissions = Array.from(new Set<MemoryAssetPermission>(parsed.permissions)).sort();\n const now = new Date().toISOString();\n sqliteRun(\n this.db,\n `INSERT INTO memory_asset_grants (\n project_hash, asset_id, actor_id, permissions_json, created_by, created_at, updated_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(project_hash, asset_id, actor_id) DO UPDATE SET\n permissions_json = excluded.permissions_json,\n created_by = excluded.created_by,\n updated_at = excluded.updated_at`,\n [\n projectHashToStorage(parsed.projectHash),\n parsed.assetId,\n parsed.actorId,\n JSON.stringify(permissions),\n parsed.createdBy,\n now,\n now\n ]\n );\n const grant = this.getGrant(parsed.assetId, parsed.actorId, parsed.projectHash);\n if (!grant) throw new Error('Memory asset grant write failed');\n return grant;\n }\n}\n", "import { z } from 'zod';\n\nconst NonEmptyStringSchema = z.string().trim().min(1).max(240);\nconst OptionalProjectHashSchema = z.string().trim().min(1).max(240).optional();\nconst StringArraySchema = z.array(z.string().trim().min(1).max(240)).max(100).default([]);\n\nexport const MemoryAssetTypeSchema = z.enum(['memory', 'lesson', 'skill', 'wiki', 'code_graph']);\nexport type MemoryAssetType = z.infer<typeof MemoryAssetTypeSchema>;\n\nexport const MemoryAssetStatusSchema = z.enum(['candidate', 'active', 'deprecated', 'archived']);\nexport type MemoryAssetStatus = z.infer<typeof MemoryAssetStatusSchema>;\n\nexport const MemoryAssetVisibilitySchema = z.enum(['private', 'project', 'shared']);\nexport type MemoryAssetVisibility = z.infer<typeof MemoryAssetVisibilitySchema>;\n\nexport const MemoryAssetPermissionSchema = z.enum(['read', 'write', 'bind', 'grant']);\nexport type MemoryAssetPermission = z.infer<typeof MemoryAssetPermissionSchema>;\n\nexport const MemoryAssetInjectionModeSchema = z.enum(['direct', 'summary', 'tool', 'reference']);\nexport type MemoryAssetInjectionMode = z.infer<typeof MemoryAssetInjectionModeSchema>;\n\nexport const MemoryAssetSchema = z.object({\n assetId: NonEmptyStringSchema,\n projectHash: OptionalProjectHashSchema,\n assetType: MemoryAssetTypeSchema,\n title: NonEmptyStringSchema,\n ownerActorId: NonEmptyStringSchema,\n version: z.number().int().positive(),\n status: MemoryAssetStatusSchema,\n visibility: MemoryAssetVisibilitySchema,\n sourceRefs: StringArraySchema,\n metadata: z.record(z.unknown()).optional(),\n createdAt: z.date(),\n updatedAt: z.date()\n});\nexport type MemoryAsset = z.infer<typeof MemoryAssetSchema>;\n\nexport const CreateMemoryAssetInputSchema = z.object({\n assetId: NonEmptyStringSchema.optional(),\n projectHash: OptionalProjectHashSchema,\n assetType: MemoryAssetTypeSchema,\n title: NonEmptyStringSchema,\n ownerActorId: NonEmptyStringSchema,\n status: MemoryAssetStatusSchema.default('active'),\n visibility: MemoryAssetVisibilitySchema.default('private'),\n sourceRefs: StringArraySchema,\n metadata: z.record(z.unknown()).optional()\n});\nexport type CreateMemoryAssetInput = z.input<typeof CreateMemoryAssetInputSchema>;\n\nexport const UpdateMemoryAssetInputSchema = z.object({\n assetId: NonEmptyStringSchema,\n projectHash: OptionalProjectHashSchema,\n expectedVersion: z.number().int().positive().optional(),\n title: NonEmptyStringSchema.optional(),\n status: MemoryAssetStatusSchema.optional(),\n visibility: MemoryAssetVisibilitySchema.optional(),\n sourceRefs: StringArraySchema.optional(),\n metadata: z.record(z.unknown()).optional()\n}).refine(\n (input) => input.title !== undefined\n || input.status !== undefined\n || input.visibility !== undefined\n || input.sourceRefs !== undefined\n || input.metadata !== undefined,\n 'at least one asset field must be supplied'\n);\nexport type UpdateMemoryAssetInput = z.input<typeof UpdateMemoryAssetInputSchema>;\n\nexport const MemoryAssetBindingSchema = z.object({\n projectHash: OptionalProjectHashSchema,\n assetId: NonEmptyStringSchema,\n actorId: NonEmptyStringSchema,\n injectionMode: MemoryAssetInjectionModeSchema,\n priority: z.number().int().min(-1000).max(1000),\n enabled: z.boolean(),\n createdAt: z.date(),\n updatedAt: z.date()\n});\nexport type MemoryAssetBinding = z.infer<typeof MemoryAssetBindingSchema>;\n\nexport const SetMemoryAssetBindingInputSchema = z.object({\n projectHash: OptionalProjectHashSchema,\n assetId: NonEmptyStringSchema,\n actorId: NonEmptyStringSchema,\n injectionMode: MemoryAssetInjectionModeSchema.default('reference'),\n priority: z.number().int().min(-1000).max(1000).default(0),\n enabled: z.boolean().default(true)\n});\nexport type SetMemoryAssetBindingInput = z.input<typeof SetMemoryAssetBindingInputSchema>;\n\nexport const MemoryAssetGrantSchema = z.object({\n projectHash: OptionalProjectHashSchema,\n assetId: NonEmptyStringSchema,\n actorId: NonEmptyStringSchema,\n permissions: z.array(MemoryAssetPermissionSchema).max(4),\n createdBy: NonEmptyStringSchema,\n createdAt: z.date(),\n updatedAt: z.date()\n});\nexport type MemoryAssetGrant = z.infer<typeof MemoryAssetGrantSchema>;\n\nexport const SetMemoryAssetGrantInputSchema = z.object({\n projectHash: OptionalProjectHashSchema,\n assetId: NonEmptyStringSchema,\n actorId: NonEmptyStringSchema,\n permissions: z.array(MemoryAssetPermissionSchema).max(4),\n createdBy: NonEmptyStringSchema\n});\nexport type SetMemoryAssetGrantInput = z.input<typeof SetMemoryAssetGrantInputSchema>;\n\nexport type MemoryAssetPermissionSource = 'owner' | 'visibility' | 'binding' | 'grant' | 'none';\n\nexport interface MemoryAssetPermissionDecision {\n allowed: boolean;\n permission: MemoryAssetPermission;\n source: MemoryAssetPermissionSource;\n reason: string;\n}\n\nexport interface CheckMemoryAssetPermissionInput {\n asset: MemoryAsset;\n actorId: string;\n permission: MemoryAssetPermission;\n binding?: MemoryAssetBinding | null;\n grant?: MemoryAssetGrant | null;\n}\n\n/**\n * Small, deterministic permission core. Precedence deliberately follows\n * owner -> read visibility -> active binding -> explicit grant -> deny.\n * Bindings make an asset readable/injectable; they never confer mutation or\n * delegation rights.\n */\nexport function checkMemoryAssetPermission(input: CheckMemoryAssetPermissionInput): MemoryAssetPermissionDecision {\n const actorId = NonEmptyStringSchema.parse(input.actorId);\n const permission = MemoryAssetPermissionSchema.parse(input.permission);\n\n if (input.asset.ownerActorId === actorId) {\n return { allowed: true, permission, source: 'owner', reason: 'asset owner' };\n }\n\n if (permission === 'read' && (input.asset.visibility === 'project' || input.asset.visibility === 'shared')) {\n return { allowed: true, permission, source: 'visibility', reason: `${input.asset.visibility} visibility` };\n }\n\n if (\n permission === 'read'\n && input.binding?.actorId === actorId\n && input.binding.assetId === input.asset.assetId\n && input.binding.enabled\n ) {\n return { allowed: true, permission, source: 'binding', reason: 'active actor binding' };\n }\n\n if (\n input.grant?.actorId === actorId\n && input.grant.assetId === input.asset.assetId\n && input.grant.permissions.includes(permission)\n ) {\n return { allowed: true, permission, source: 'grant', reason: 'explicit actor grant' };\n }\n\n // Keep missing and inaccessible assets indistinguishable at the public\n // permission-check boundary. Allowed decisions still explain the winning\n // rule, while a denial never confirms that a private asset exists.\n return { allowed: false, permission, source: 'none', reason: 'permission denied' };\n}\n\nexport class MemoryAssetPermissionDeniedError extends Error {\n readonly code = 'MEMORY_ASSET_PERMISSION_DENIED';\n\n constructor(\n readonly assetId: string,\n readonly actorId: string,\n readonly permission: MemoryAssetPermission\n ) {\n super(`Permission denied: actor ${actorId} cannot ${permission} memory asset ${assetId}`);\n this.name = 'MemoryAssetPermissionDeniedError';\n }\n}\n", "import { z } from 'zod';\n\nimport type { SQLiteDatabase } from '../sqlite-wrapper.js';\nimport {\n canonicalMemoryAssetId,\n isCanonicalMemoryAssetRegistration,\n type CanonicalMemoryAssetType\n} from './memory-asset-catalog-service.js';\nimport {\n CANONICAL_MEMORY_PERMISSION_MODE_ENV,\n resolveCanonicalMemoryPermissionMode,\n type CanonicalMemoryPermissionMode\n} from './canonical-memory-access-service.js';\nimport { MemoryAssetRepository } from './memory-asset-repository.js';\nimport type { MemoryAssetInjectionMode } from './memory-asset-permissions.js';\n\nexport const CANONICAL_MEMORY_ACTOR_ID_ENV = 'CLAUDE_MEMORY_ACTOR_ID';\n\nconst ActorIdSchema = z.string().trim().min(1).max(240);\n\nexport type CanonicalMemoryInjectionLane = 'session_start' | 'prompt' | 'context_pack';\n\nexport interface CanonicalMemoryInjectionCandidate<T> {\n canonicalType: CanonicalMemoryAssetType;\n canonicalId: string;\n value: T;\n}\n\nexport interface CanonicalMemoryInjection<T> {\n value: T;\n injectionMode: Extract<MemoryAssetInjectionMode, 'direct' | 'summary' | 'reference'>;\n priority: number;\n}\n\nexport interface CanonicalMemoryInjectionSelection<T> {\n mode: CanonicalMemoryPermissionMode;\n items: CanonicalMemoryInjection<T>[];\n}\n\nexport function resolveCanonicalMemoryActorId(\n explicitActorId: unknown,\n env: NodeJS.ProcessEnv = process.env\n): string | undefined {\n const raw = typeof explicitActorId === 'string' && explicitActorId.trim().length > 0\n ? explicitActorId\n : env[CANONICAL_MEMORY_ACTOR_ID_ENV];\n const parsed = ActorIdSchema.safeParse(raw);\n return parsed.success ? parsed.data : undefined;\n}\n\nfunction injectionModeRank(mode: 'direct' | 'summary' | 'reference'): number {\n if (mode === 'direct') return 3;\n if (mode === 'summary') return 2;\n return 1;\n}\n\nexport class CanonicalMemoryInjectionService {\n private readonly repository: MemoryAssetRepository;\n private readonly env: NodeJS.ProcessEnv;\n readonly mode: CanonicalMemoryPermissionMode;\n\n constructor(\n db: SQLiteDatabase,\n options: { mode?: CanonicalMemoryPermissionMode; env?: NodeJS.ProcessEnv } = {}\n ) {\n this.repository = new MemoryAssetRepository(db);\n this.env = options.env ?? process.env;\n this.mode = options.mode ?? resolveCanonicalMemoryPermissionMode(this.env);\n }\n\n select<T>(input: {\n projectHash: string;\n actorId?: string;\n lane: CanonicalMemoryInjectionLane;\n candidates: CanonicalMemoryInjectionCandidate<T>[];\n }): CanonicalMemoryInjectionSelection<T> {\n const actorId = resolveCanonicalMemoryActorId(input.actorId, this.env);\n if (this.mode !== 'legacy' && !actorId) {\n throw new Error(`actor identity is required when ${CANONICAL_MEMORY_PERMISSION_MODE_ENV}=${this.mode}`);\n }\n\n // Lesson lifecycle eligibility is independent of legacy ACL compatibility.\n // Apply it before the legacy fast-path so disabled/version-conditional\n // lessons never enter any automatic injection lane.\n const candidates = input.candidates.filter((candidate) => {\n const lesson = candidate.value as Partial<{ recallEnabled: boolean; validVersions: string[] }>;\n return candidate.canonicalType !== 'lesson' || (lesson.recallEnabled !== false && (lesson.validVersions?.length ?? 0) === 0);\n });\n\n if (this.mode === 'legacy') {\n return {\n mode: this.mode,\n items: candidates.map((candidate) => ({\n value: candidate.value,\n injectionMode: 'direct',\n priority: 0\n }))\n };\n }\n\n const selected: Array<CanonicalMemoryInjection<T> & { canonicalId: string }> = [];\n for (const candidate of candidates) {\n const assetId = canonicalMemoryAssetId(candidate.canonicalType, candidate.canonicalId);\n const asset = this.repository.get(assetId, input.projectHash);\n const registered = Boolean(\n asset && isCanonicalMemoryAssetRegistration(asset, candidate.canonicalType, candidate.canonicalId)\n );\n\n if (!asset) {\n if (this.mode === 'registered') {\n selected.push({ value: candidate.value, injectionMode: 'direct', priority: 0, canonicalId: candidate.canonicalId });\n }\n continue;\n }\n if (!registered || asset.status !== 'active') continue;\n\n const binding = this.repository.getBinding(assetId, actorId!, input.projectHash);\n if (!binding?.enabled || binding.injectionMode === 'tool') continue;\n selected.push({\n value: candidate.value,\n injectionMode: binding.injectionMode,\n priority: binding.priority,\n canonicalId: candidate.canonicalId\n });\n }\n\n selected.sort((left, right) => (\n right.priority - left.priority\n || injectionModeRank(right.injectionMode) - injectionModeRank(left.injectionMode)\n || left.canonicalId.localeCompare(right.canonicalId)\n ));\n return {\n mode: this.mode,\n items: selected.map(({ canonicalId: _canonicalId, ...item }) => item)\n };\n }\n}\n", "import { randomUUID } from 'crypto';\nimport { z } from 'zod';\n\nimport {\n sqliteAll,\n sqliteGet,\n sqliteRun,\n toDateFromSQLite,\n type SQLiteDatabase\n} from '../sqlite-wrapper.js';\nimport {\n ListMemoryLessonsInputSchema,\n MemoryLessonSchema,\n UpsertMemoryLessonInputSchema,\n type MemoryLesson\n} from '../types.js';\nimport { sanitizeGovernanceAuditValue, writeGovernanceAuditEntry } from './governance-audit.js';\n\ninterface MemoryLessonRow {\n lesson_id: string;\n project_hash: string;\n name: string;\n trigger: string;\n steps_json: string;\n confidence: number;\n source_session_ids: string;\n source_event_ids: string;\n failure_modes_json: string;\n skill_candidate: number;\n source_class?: string;\n revision?: number;\n recall_enabled?: number;\n scope?: string | null;\n validation_json?: string;\n reconsider_when?: string | null;\n valid_versions_json?: string;\n created_at: string;\n updated_at: string;\n}\n\ntype ParsedLessonUpsert = z.output<typeof UpsertMemoryLessonInputSchema>;\n\nfunction parseStringArray(value: unknown): string[] {\n if (typeof value !== 'string') return [];\n try {\n const parsed = JSON.parse(value);\n return Array.isArray(parsed)\n ? parsed.filter((item): item is string => typeof item === 'string' && item.length > 0)\n : [];\n } catch {\n return [];\n }\n}\n\nfunction projectHashToStorage(projectHash: string | undefined): string {\n return projectHash ?? '';\n}\n\nfunction projectHashFromStorage(projectHash: string): string | undefined {\n return projectHash.length > 0 ? projectHash : undefined;\n}\n\nfunction sanitizeString(value: string): string {\n return String(sanitizeGovernanceAuditValue(value));\n}\n\nfunction sanitizeStringArray(values: string[]): string[] {\n return values.map(sanitizeString).filter((value) => value.length > 0);\n}\n\nfunction sanitizeParsedLesson(input: ParsedLessonUpsert): ParsedLessonUpsert {\n return {\n ...input,\n projectHash: input.projectHash ? sanitizeString(input.projectHash) : undefined,\n name: sanitizeString(input.name),\n trigger: sanitizeString(input.trigger),\n steps: sanitizeStringArray(input.steps),\n sourceSessionIds: sanitizeStringArray(input.sourceSessionIds),\n sourceEventIds: sanitizeStringArray(input.sourceEventIds),\n failureModes: sanitizeStringArray(input.failureModes),\n sourceClass: input.sourceClass,\n actor: input.actor ? sanitizeString(input.actor) : undefined\n };\n}\n\nfunction rowToLesson(row: MemoryLessonRow): MemoryLesson {\n return MemoryLessonSchema.parse({\n lessonId: row.lesson_id,\n projectHash: projectHashFromStorage(row.project_hash),\n name: row.name,\n trigger: row.trigger,\n steps: parseStringArray(row.steps_json),\n confidence: Number(row.confidence),\n sourceSessionIds: parseStringArray(row.source_session_ids),\n sourceEventIds: parseStringArray(row.source_event_ids),\n failureModes: parseStringArray(row.failure_modes_json),\n skillCandidate: Number(row.skill_candidate) === 1,\n sourceClass: row.source_class === 'curated' ? 'curated' : 'derived',\n revision: Number(row.revision ?? 1),\n recallEnabled: Number(row.recall_enabled ?? 1) === 1,\n scope: row.scope ?? undefined,\n validation: parseStringArray(row.validation_json),\n reconsiderWhen: row.reconsider_when ?? undefined,\n validVersions: parseStringArray(row.valid_versions_json),\n createdAt: toDateFromSQLite(row.created_at),\n updatedAt: toDateFromSQLite(row.updated_at)\n });\n}\n\nfunction lessonToAuditJson(lesson: MemoryLesson): Record<string, unknown> {\n return {\n lessonId: lesson.lessonId,\n projectHash: lesson.projectHash,\n name: lesson.name,\n trigger: lesson.trigger,\n steps: lesson.steps,\n confidence: lesson.confidence,\n sourceSessionIds: lesson.sourceSessionIds,\n sourceEventIds: lesson.sourceEventIds,\n failureModes: lesson.failureModes,\n skillCandidate: lesson.skillCandidate,\n sourceClass: lesson.sourceClass,\n revision: lesson.revision,\n recallEnabled: lesson.recallEnabled,\n scope: lesson.scope,\n validation: lesson.validation,\n reconsiderWhen: lesson.reconsiderWhen,\n validVersions: lesson.validVersions,\n createdAt: lesson.createdAt.toISOString(),\n updatedAt: lesson.updatedAt.toISOString()\n };\n}\n\nexport type LessonAuditOperation = 'lesson_promote' | 'lesson_capture';\n\nexport class LessonRepository {\n constructor(private readonly db: SQLiteDatabase) {}\n\n async upsert(input: unknown, auditOperation: LessonAuditOperation = 'lesson_promote'): Promise<MemoryLesson> {\n const parsed = sanitizeParsedLesson(UpsertMemoryLessonInputSchema.parse(input));\n const existingById = parsed.lessonId ? this.get(parsed.lessonId) : null;\n const existingByName = this.getByProjectAndName(parsed.projectHash, parsed.name);\n if (existingById && existingByName && existingById.lessonId !== existingByName.lessonId) {\n throw new Error('lesson name already exists for projectHash');\n }\n const existing = existingById ?? existingByName;\n const now = new Date().toISOString();\n\n if (existing) {\n if (projectHashToStorage(existing.projectHash) !== projectHashToStorage(parsed.projectHash)) {\n throw new Error('lesson projectHash mismatch');\n }\n sqliteRun(\n this.db,\n `UPDATE memory_lessons\n SET name = ?, trigger = ?, steps_json = ?, confidence = ?, source_session_ids = ?,\n source_event_ids = ?, failure_modes_json = ?, skill_candidate = ?, source_class = ?,\n revision = revision + 1, recall_enabled = ?, scope = ?, validation_json = ?, reconsider_when = ?, valid_versions_json = ?, updated_at = ?\n WHERE lesson_id = ? AND project_hash = ?`,\n [\n parsed.name,\n parsed.trigger,\n JSON.stringify(parsed.steps),\n parsed.confidence,\n JSON.stringify(parsed.sourceSessionIds),\n JSON.stringify(parsed.sourceEventIds),\n JSON.stringify(parsed.failureModes),\n parsed.skillCandidate ? 1 : 0,\n parsed.sourceClass,\n parsed.recallEnabled === undefined ? (existing.recallEnabled ? 1 : 0) : (parsed.recallEnabled ? 1 : 0),\n parsed.scope ?? existing.scope ?? null,\n JSON.stringify(parsed.validation ?? existing.validation),\n parsed.reconsiderWhen ?? existing.reconsiderWhen ?? null,\n JSON.stringify(parsed.validVersions ?? existing.validVersions),\n now,\n existing.lessonId,\n projectHashToStorage(existing.projectHash)\n ]\n );\n const saved = this.require(existing.lessonId);\n await this.auditLessonUpsert(parsed, existing, saved, auditOperation);\n return saved;\n }\n\n const lessonId = parsed.lessonId ?? randomUUID();\n sqliteRun(\n this.db,\n `INSERT INTO memory_lessons (\n lesson_id, project_hash, name, trigger, steps_json, confidence,\n source_session_ids, source_event_ids, failure_modes_json, skill_candidate,\n source_class, revision, recall_enabled, scope, validation_json, reconsider_when, valid_versions_json, created_at, updated_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n [\n lessonId,\n projectHashToStorage(parsed.projectHash),\n parsed.name,\n parsed.trigger,\n JSON.stringify(parsed.steps),\n parsed.confidence,\n JSON.stringify(parsed.sourceSessionIds),\n JSON.stringify(parsed.sourceEventIds),\n JSON.stringify(parsed.failureModes),\n parsed.skillCandidate ? 1 : 0,\n parsed.sourceClass,\n 1,\n parsed.recallEnabled === false ? 0 : 1,\n parsed.scope ?? null,\n JSON.stringify(parsed.validation ?? []),\n parsed.reconsiderWhen ?? null,\n JSON.stringify(parsed.validVersions ?? []),\n now,\n now\n ]\n );\n\n const saved = this.require(lessonId);\n await this.auditLessonUpsert(parsed, null, saved, auditOperation);\n return saved;\n }\n\n get(lessonId: string): MemoryLesson | null {\n const row = sqliteGet<MemoryLessonRow>(this.db, `SELECT * FROM memory_lessons WHERE lesson_id = ?`, [lessonId]);\n return row ? rowToLesson(row) : null;\n }\n\n async list(input: unknown): Promise<MemoryLesson[]> {\n const parsed = ListMemoryLessonsInputSchema.parse(input);\n const clauses = ['project_hash = ?'];\n const params: unknown[] = [projectHashToStorage(parsed.projectHash)];\n if (parsed.skillCandidate !== undefined) {\n clauses.push('skill_candidate = ?');\n params.push(parsed.skillCandidate ? 1 : 0);\n }\n params.push(parsed.limit, parsed.offset);\n const where = clauses.join(' AND ');\n const rows = sqliteAll<MemoryLessonRow>(\n this.db,\n `SELECT * FROM memory_lessons\n WHERE ${where}\n ORDER BY confidence DESC, updated_at DESC, lesson_id ASC\n LIMIT ? OFFSET ?`,\n params\n );\n return rows.map(rowToLesson);\n }\n\n setRecallEnabled(input: { lessonId: string; projectHash: string; expectedRevision: number; enabled: boolean }): MemoryLesson | null {\n const result = sqliteRun(\n this.db,\n `UPDATE memory_lessons\n SET recall_enabled = ?, revision = revision + 1, updated_at = ?\n WHERE lesson_id = ? AND project_hash = ? AND revision = ?`,\n [input.enabled ? 1 : 0, new Date().toISOString(), input.lessonId, projectHashToStorage(input.projectHash), input.expectedRevision]\n );\n return result.changes === 1 ? this.get(input.lessonId) : null;\n }\n\n getByProjectAndName(projectHash: string | undefined, name: string): MemoryLesson | null {\n const row = sqliteGet<MemoryLessonRow>(\n this.db,\n `SELECT * FROM memory_lessons WHERE project_hash = ? AND name = ?`,\n [projectHashToStorage(projectHash), name]\n );\n return row ? rowToLesson(row) : null;\n }\n\n private require(lessonId: string): MemoryLesson {\n const lesson = this.get(lessonId);\n if (!lesson) throw new Error(`Memory lesson not found: ${lessonId}`);\n return lesson;\n }\n\n private async auditLessonUpsert(\n input: ParsedLessonUpsert,\n before: MemoryLesson | null,\n after: MemoryLesson,\n operation: LessonAuditOperation\n ): Promise<void> {\n await writeGovernanceAuditEntry(this.db, {\n operation,\n actor: input.actor ?? 'cml-core',\n projectHash: input.projectHash,\n targetType: 'lesson',\n targetId: after.lessonId,\n beforeJson: before ? lessonToAuditJson(before) : undefined,\n afterJson: lessonToAuditJson(after),\n sourceEventIds: input.sourceEventIds\n });\n }\n}\n", "/**\n * Core types for claude-memory-layer plugin\n * Idris2 inspired: Complete, immutable type definitions with Zod validation\n */\n\nimport { z } from 'zod';\n\n// ============================================================\n// Event Types\n// ============================================================\n\nexport const EventTypeSchema = z.enum([\n 'user_prompt',\n 'agent_response',\n 'session_summary',\n 'tool_observation'\n]);\nexport type EventType = z.infer<typeof EventTypeSchema>;\n\n// ============================================================\n// Memory Event (L0 EventStore)\n// ============================================================\n\nexport const MemoryEventSchema = z.object({\n id: z.string().uuid(),\n eventType: EventTypeSchema,\n sessionId: z.string(),\n timestamp: z.date(),\n content: z.string(),\n canonicalKey: z.string(),\n dedupeKey: z.string(),\n metadata: z.record(z.unknown()).optional()\n});\nexport type MemoryEvent = z.infer<typeof MemoryEventSchema>;\n\n// Input for creating new events (id, dedupeKey generated automatically)\nexport const MemoryEventInputSchema = MemoryEventSchema.omit({\n id: true,\n dedupeKey: true,\n canonicalKey: true\n});\nexport type MemoryEventInput = z.infer<typeof MemoryEventInputSchema>;\n\n// ============================================================\n// Session\n// ============================================================\n\nexport const SessionSchema = z.object({\n id: z.string(),\n startedAt: z.date(),\n endedAt: z.date().optional(),\n projectPath: z.string().optional(),\n summary: z.string().optional(),\n tags: z.array(z.string()).optional()\n});\nexport type Session = z.infer<typeof SessionSchema>;\n\n// ============================================================\n// Insight (L1 Structured)\n// ============================================================\n\nexport const InsightTypeSchema = z.enum([\n 'preference',\n 'pattern',\n 'expertise'\n]);\nexport type InsightType = z.infer<typeof InsightTypeSchema>;\n\nexport const InsightSchema = z.object({\n id: z.string().uuid(),\n insightType: InsightTypeSchema,\n content: z.string(),\n canonicalKey: z.string(),\n confidence: z.number().min(0).max(1),\n sourceEvents: z.array(z.string().uuid()),\n createdAt: z.date(),\n lastUpdated: z.date()\n});\nexport type Insight = z.infer<typeof InsightSchema>;\n\n// ============================================================\n// Memory Match (Search Result)\n// ============================================================\n\nexport const MemoryMatchSchema = z.object({\n event: MemoryEventSchema,\n score: z.number().min(0).max(1),\n relevanceReason: z.string().optional()\n});\nexport type MemoryMatch = z.infer<typeof MemoryMatchSchema>;\n\n// ============================================================\n// Match Confidence (AXIOMMIND)\n// ============================================================\n\nexport const MatchConfidenceSchema = z.enum(['high', 'suggested', 'none']);\nexport type MatchConfidence = z.infer<typeof MatchConfidenceSchema>;\n\nexport const MatchResultSchema = z.object({\n match: MemoryMatchSchema.nullable(),\n confidence: MatchConfidenceSchema,\n gap: z.number().optional(),\n alternatives: z.array(MemoryMatchSchema).optional()\n});\nexport type MatchResult = z.infer<typeof MatchResultSchema>;\n\n// AXIOMMIND Matching Thresholds\nexport const MATCH_THRESHOLDS = {\n minCombinedScore: 0.92,\n minGap: 0.03,\n suggestionThreshold: 0.75\n} as const;\n\n// ============================================================\n// Memory Level (Graduation Pipeline)\n// ============================================================\n\nexport const MemoryLevelSchema = z.enum(['L0', 'L1', 'L2', 'L3', 'L4']);\nexport type MemoryLevel = z.infer<typeof MemoryLevelSchema>;\n\nexport const GraduationResultSchema = z.object({\n eventId: z.string().uuid(),\n fromLevel: MemoryLevelSchema,\n toLevel: MemoryLevelSchema,\n success: z.boolean(),\n reason: z.string().optional()\n});\nexport type GraduationResult = z.infer<typeof GraduationResultSchema>;\n\n// ============================================================\n// Evidence Span (AXIOMMIND Principle 4)\n// ============================================================\n\nexport const EvidenceSpanSchema = z.object({\n start: z.number().int().nonnegative(),\n end: z.number().int().positive(),\n confidence: z.number().min(0).max(1),\n matchType: z.enum(['exact', 'fuzzy', 'none']),\n originalQuote: z.string(),\n alignedText: z.string()\n});\nexport type EvidenceSpan = z.infer<typeof EvidenceSpanSchema>;\n\n// ============================================================\n// Memory Operations Config (AgentMemory-inspired operations layer)\n// ============================================================\n\nexport const PerspectiveConsolidationSpecialistKindSchema = z.enum([\n 'deduction',\n 'induction',\n 'contradiction',\n 'actor_card_maintenance'\n]);\nexport type PerspectiveConsolidationSpecialistKind = z.infer<typeof PerspectiveConsolidationSpecialistKindSchema>;\n\nexport const MemoryOperationsConfigSchema = z.object({\n enabled: z.boolean().default(false),\n facets: z.object({\n enabled: z.boolean().default(true)\n }).default({}),\n actions: z.object({\n enabled: z.boolean().default(true)\n }).default({}),\n retention: z.object({\n enabled: z.boolean().default(false),\n policyVersion: z.string().default('v1')\n }).default({}),\n graphExpansion: z.object({\n enabled: z.boolean().default(false),\n maxHops: z.number().int().min(0).max(5).default(1)\n }).default({}),\n codifyLite: z.object({\n enabled: z.boolean().default(false)\n }).default({}),\n lessons: z.object({\n enabled: z.boolean().default(false)\n }).default({}),\n perspectiveMemory: z.object({\n enabled: z.boolean().default(false),\n deriver: z.object({\n enabled: z.boolean().default(false),\n maxEventsPerBatch: z.number().int().positive().max(100).default(20),\n maxObserversPerSession: z.number().int().positive().max(50).default(5)\n }).default({}),\n specialists: z.object({\n enabled: z.boolean().default(false),\n enabledProjectHashes: z.array(z.string().trim().min(1)).max(100).default([]),\n enabledKinds: z.array(PerspectiveConsolidationSpecialistKindSchema).default([\n 'deduction',\n 'induction',\n 'contradiction',\n 'actor_card_maintenance'\n ]),\n maxSourceObservations: z.number().int().positive().max(100).default(20),\n maxDerivedObservations: z.number().int().min(0).max(20).default(5),\n maxCardUpdates: z.number().int().min(0).max(40).default(3)\n }).default({})\n }).default({})\n}).default({});\nexport type MemoryOperationsConfig = z.infer<typeof MemoryOperationsConfigSchema>;\n\n// ============================================================\n// Procedural Lesson Types (AgentMemory-inspired operations layer)\n// ============================================================\n\nconst MemoryLessonNonEmptyStringSchema = z.string()\n .transform((value) => value.trim())\n .pipe(z.string().min(1));\n\nconst MemoryLessonStringArraySchema = z.preprocess((value) => {\n if (!Array.isArray(value)) return value;\n return value\n .map((item) => typeof item === 'string' ? item.trim() : item)\n .filter((item) => typeof item !== 'string' || item.length > 0);\n}, z.array(MemoryLessonNonEmptyStringSchema)).default([]);\n\nexport const MemoryLessonSourceClassSchema = z.enum(['derived', 'curated']);\nexport type MemoryLessonSourceClass = z.infer<typeof MemoryLessonSourceClassSchema>;\n\nexport const MemoryLessonSchema = z.object({\n lessonId: z.string().uuid(),\n projectHash: MemoryLessonNonEmptyStringSchema.optional(),\n name: MemoryLessonNonEmptyStringSchema,\n trigger: MemoryLessonNonEmptyStringSchema,\n steps: MemoryLessonStringArraySchema.refine((steps) => steps.length > 0, 'steps must contain at least one step'),\n confidence: z.number().min(0).max(1),\n sourceSessionIds: MemoryLessonStringArraySchema,\n sourceEventIds: MemoryLessonStringArraySchema,\n failureModes: MemoryLessonStringArraySchema,\n skillCandidate: z.boolean().default(false),\n sourceClass: MemoryLessonSourceClassSchema.default('derived'),\n revision: z.number().int().positive().default(1),\n recallEnabled: z.boolean().default(true),\n scope: MemoryLessonNonEmptyStringSchema.optional(),\n validation: MemoryLessonStringArraySchema,\n reconsiderWhen: MemoryLessonNonEmptyStringSchema.optional(),\n validVersions: MemoryLessonStringArraySchema,\n createdAt: z.date(),\n updatedAt: z.date()\n});\nexport type MemoryLesson = z.infer<typeof MemoryLessonSchema>;\n\nexport const UpsertMemoryLessonInputSchema = z.object({\n lessonId: z.string().uuid().optional(),\n projectHash: MemoryLessonNonEmptyStringSchema.optional(),\n name: MemoryLessonNonEmptyStringSchema,\n trigger: MemoryLessonNonEmptyStringSchema,\n steps: MemoryLessonStringArraySchema.refine((steps) => steps.length > 0, 'steps must contain at least one step'),\n confidence: z.number().min(0).max(1).default(0.5),\n sourceSessionIds: MemoryLessonStringArraySchema,\n sourceEventIds: MemoryLessonStringArraySchema,\n failureModes: MemoryLessonStringArraySchema,\n skillCandidate: z.boolean().default(false),\n sourceClass: MemoryLessonSourceClassSchema.default('derived'),\n recallEnabled: z.boolean().optional(),\n scope: MemoryLessonNonEmptyStringSchema.optional(),\n validation: MemoryLessonStringArraySchema.optional(),\n reconsiderWhen: MemoryLessonNonEmptyStringSchema.optional(),\n validVersions: MemoryLessonStringArraySchema.optional(),\n actor: MemoryLessonNonEmptyStringSchema.optional()\n}).superRefine((value, ctx) => {\n if (value.sourceSessionIds.length === 0 && value.sourceEventIds.length === 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['sourceEventIds'],\n message: 'sourceSessionIds or sourceEventIds is required'\n });\n }\n});\nexport type UpsertMemoryLessonInput = z.input<typeof UpsertMemoryLessonInputSchema>;\n\nexport const ListMemoryLessonsInputSchema = z.object({\n projectHash: MemoryLessonNonEmptyStringSchema.optional(),\n skillCandidate: z.boolean().optional(),\n limit: z.number().int().positive().max(500).default(50),\n offset: z.number().int().nonnegative().default(0)\n});\nexport type ListMemoryLessonsInput = z.input<typeof ListMemoryLessonsInputSchema>;\n\n// ============================================================\n// Honcho-inspired Perspective Memory Types\n// ============================================================\n\nconst PerspectiveMemoryNonEmptyStringSchema = z.string()\n .transform((value) => value.trim())\n .pipe(z.string().min(1));\n\nconst PerspectiveMemoryOptionalStringSchema = z.preprocess((value) => {\n if (typeof value !== 'string') return value;\n const normalized = value.trim();\n return normalized.length > 0 ? normalized : undefined;\n}, PerspectiveMemoryNonEmptyStringSchema.optional());\n\nconst PerspectiveMemoryStringArraySchema = z.preprocess((value) => {\n if (!Array.isArray(value)) return value;\n return value\n .map((item) => typeof item === 'string' ? item.trim() : item)\n .filter((item) => typeof item !== 'string' || item.length > 0);\n}, z.array(PerspectiveMemoryNonEmptyStringSchema)).default([]);\n\nconst ActorCardSensitivePattern = /(?:\\b(?:api[_-]?key|secret|password|passwd|token|access[_-]?token|client[_-]?secret|bearer)\\b\\s*[:=])|(?:\\b(?:api[_-]?key|secret|password|passwd|token|access[_-]?token|client[_-]?secret|bearer)=)|(?:^|\\s)(?:\\/[A-Za-z0-9._-][^\\s`'\\\"]*)/i;\n\nexport const MemoryActorKindSchema = z.enum([\n 'user',\n 'assistant',\n 'subagent',\n 'tool',\n 'system',\n 'integration',\n 'unknown'\n]);\nexport type MemoryActorKind = z.infer<typeof MemoryActorKindSchema>;\n\nexport const SessionActorRoleSchema = z.enum([\n 'speaker',\n 'assistant',\n 'observer',\n 'tool',\n 'system',\n 'unknown'\n]);\nexport type SessionActorRole = z.infer<typeof SessionActorRoleSchema>;\n\nexport const PerspectiveObservationLevelSchema = z.enum([\n 'explicit',\n 'deductive',\n 'inductive',\n 'contradiction'\n]);\nexport type PerspectiveObservationLevel = z.infer<typeof PerspectiveObservationLevelSchema>;\n\nexport const PerspectiveObservationCreatedBySchema = z.enum(['rule', 'llm', 'manual', 'import']);\nexport type PerspectiveObservationCreatedBy = z.infer<typeof PerspectiveObservationCreatedBySchema>;\n\nexport const ActorCardEntryPrefixSchema = z.enum([\n 'IDENTITY',\n 'ATTRIBUTE',\n 'RELATIONSHIP',\n 'INSTRUCTION'\n]);\nexport type ActorCardEntryPrefix = z.infer<typeof ActorCardEntryPrefixSchema>;\n\nexport const ActorCardEntrySchema = z.string()\n .transform((value) => value.trim())\n .pipe(\n z.string()\n .min(1)\n .max(200, 'actor card entry must be at most 200 characters')\n .refine(\n (value) => /^(IDENTITY|ATTRIBUTE|RELATIONSHIP|INSTRUCTION):\\s*\\S/.test(value),\n 'actor card entry prefix must be one of IDENTITY:, ATTRIBUTE:, RELATIONSHIP:, or INSTRUCTION:'\n )\n .refine(\n (value) => !ActorCardSensitivePattern.test(value),\n 'actor card entry contains secret, redacted, sensitive, or path-like content'\n )\n );\nexport type ActorCardEntry = z.infer<typeof ActorCardEntrySchema>;\n\nexport const MemoryActorSchema = z.object({\n actorId: PerspectiveMemoryNonEmptyStringSchema,\n projectHash: PerspectiveMemoryOptionalStringSchema,\n kind: MemoryActorKindSchema,\n displayName: PerspectiveMemoryNonEmptyStringSchema,\n source: PerspectiveMemoryNonEmptyStringSchema,\n metadata: z.record(z.unknown()).optional(),\n createdAt: z.date(),\n updatedAt: z.date()\n});\nexport type MemoryActor = z.infer<typeof MemoryActorSchema>;\n\nexport const UpsertMemoryActorInputSchema = z.object({\n actorId: PerspectiveMemoryOptionalStringSchema,\n projectHash: PerspectiveMemoryOptionalStringSchema,\n kind: MemoryActorKindSchema.default('unknown'),\n displayName: PerspectiveMemoryNonEmptyStringSchema,\n source: PerspectiveMemoryNonEmptyStringSchema,\n metadata: z.record(z.unknown()).optional()\n});\nexport type UpsertMemoryActorInput = z.input<typeof UpsertMemoryActorInputSchema>;\n\nexport const ListMemoryActorsInputSchema = z.object({\n projectHash: PerspectiveMemoryOptionalStringSchema,\n kind: MemoryActorKindSchema.optional(),\n source: PerspectiveMemoryOptionalStringSchema,\n limit: z.number().int().positive().max(500).default(100)\n});\nexport type ListMemoryActorsInput = z.input<typeof ListMemoryActorsInputSchema>;\n\nexport const SessionActorSchema = z.object({\n projectHash: PerspectiveMemoryOptionalStringSchema,\n sessionId: PerspectiveMemoryNonEmptyStringSchema,\n actorId: PerspectiveMemoryNonEmptyStringSchema,\n roleInSession: SessionActorRoleSchema,\n observeSelf: z.boolean().default(true),\n observeOthers: z.boolean().default(false),\n joinedAt: z.date(),\n leftAt: z.date().optional(),\n metadata: z.record(z.unknown()).optional()\n});\nexport type SessionActor = z.infer<typeof SessionActorSchema>;\n\nexport const UpsertSessionActorInputSchema = z.object({\n projectHash: PerspectiveMemoryOptionalStringSchema,\n sessionId: PerspectiveMemoryNonEmptyStringSchema,\n actorId: PerspectiveMemoryNonEmptyStringSchema,\n roleInSession: SessionActorRoleSchema.default('unknown'),\n observeSelf: z.boolean().default(true),\n observeOthers: z.boolean().default(false),\n joinedAt: z.date().optional(),\n leftAt: z.date().optional(),\n metadata: z.record(z.unknown()).optional()\n});\nexport type UpsertSessionActorInput = z.input<typeof UpsertSessionActorInputSchema>;\n\nexport const ListSessionActorsInputSchema = z.object({\n projectHash: PerspectiveMemoryOptionalStringSchema,\n sessionId: PerspectiveMemoryNonEmptyStringSchema,\n limit: z.number().int().positive().max(500).default(100)\n});\nexport type ListSessionActorsInput = z.input<typeof ListSessionActorsInputSchema>;\n\nexport const SetSessionActorObservationPolicyInputSchema = z.object({\n projectHash: PerspectiveMemoryOptionalStringSchema,\n sessionId: PerspectiveMemoryNonEmptyStringSchema,\n actorId: PerspectiveMemoryNonEmptyStringSchema,\n observeSelf: z.boolean(),\n observeOthers: z.boolean()\n});\nexport type SetSessionActorObservationPolicyInput = z.input<typeof SetSessionActorObservationPolicyInputSchema>;\n\nexport const ActorCardSchema = z.object({\n cardId: z.string().uuid(),\n projectHash: PerspectiveMemoryOptionalStringSchema,\n observerActorId: PerspectiveMemoryNonEmptyStringSchema,\n observedActorId: PerspectiveMemoryNonEmptyStringSchema,\n entries: z.array(ActorCardEntrySchema).max(40),\n sourceEventIds: PerspectiveMemoryStringArraySchema,\n updatedBy: PerspectiveMemoryOptionalStringSchema,\n createdAt: z.date(),\n updatedAt: z.date()\n});\nexport type ActorCard = z.infer<typeof ActorCardSchema>;\n\nexport const UpsertActorCardInputSchema = z.object({\n projectHash: PerspectiveMemoryOptionalStringSchema,\n observerActorId: PerspectiveMemoryNonEmptyStringSchema,\n observedActorId: PerspectiveMemoryNonEmptyStringSchema,\n entries: z.array(ActorCardEntrySchema).min(1).max(40, 'actor card supports at most 40 entries'),\n sourceEventIds: PerspectiveMemoryStringArraySchema,\n updatedBy: PerspectiveMemoryOptionalStringSchema\n});\nexport type UpsertActorCardInput = z.input<typeof UpsertActorCardInputSchema>;\n\nexport const GetActorCardInputSchema = z.object({\n projectHash: PerspectiveMemoryOptionalStringSchema,\n observerActorId: PerspectiveMemoryNonEmptyStringSchema,\n observedActorId: PerspectiveMemoryNonEmptyStringSchema\n});\nexport type GetActorCardInput = z.input<typeof GetActorCardInputSchema>;\n\n// ============================================================\n// Core Memory Blocks (Letta-inspired always-injected, self-editable state)\n// ============================================================\n\nexport const CoreMemoryBlockKeySchema = z.enum(['project', 'user']);\nexport type CoreMemoryBlockKey = z.infer<typeof CoreMemoryBlockKeySchema>;\n\nexport const CORE_MEMORY_BLOCK_MAX_CHARS = 1200;\n\nexport const CoreMemoryBlockSchema = z.object({\n projectHash: PerspectiveMemoryOptionalStringSchema,\n blockKey: CoreMemoryBlockKeySchema,\n content: z.string().max(CORE_MEMORY_BLOCK_MAX_CHARS),\n sourceEventIds: PerspectiveMemoryStringArraySchema,\n updatedBy: PerspectiveMemoryOptionalStringSchema,\n createdAt: z.date(),\n updatedAt: z.date()\n});\nexport type CoreMemoryBlock = z.infer<typeof CoreMemoryBlockSchema>;\n\nexport const UpsertCoreMemoryBlockInputSchema = z.object({\n projectHash: PerspectiveMemoryOptionalStringSchema,\n blockKey: CoreMemoryBlockKeySchema,\n content: z.string().trim().max(\n CORE_MEMORY_BLOCK_MAX_CHARS,\n `core memory block supports at most ${CORE_MEMORY_BLOCK_MAX_CHARS} characters`\n ),\n sourceEventIds: PerspectiveMemoryStringArraySchema,\n updatedBy: PerspectiveMemoryOptionalStringSchema\n});\nexport type UpsertCoreMemoryBlockInput = z.input<typeof UpsertCoreMemoryBlockInputSchema>;\n\nexport const GetCoreMemoryBlockInputSchema = z.object({\n projectHash: PerspectiveMemoryOptionalStringSchema,\n blockKey: CoreMemoryBlockKeySchema.optional()\n});\nexport type GetCoreMemoryBlockInput = z.input<typeof GetCoreMemoryBlockInputSchema>;\n\nexport const PerspectiveObservationSchema = z.object({\n observationId: z.string().uuid(),\n projectHash: PerspectiveMemoryOptionalStringSchema,\n observerActorId: PerspectiveMemoryNonEmptyStringSchema,\n observedActorId: PerspectiveMemoryNonEmptyStringSchema,\n sessionId: PerspectiveMemoryOptionalStringSchema,\n level: PerspectiveObservationLevelSchema,\n content: PerspectiveMemoryNonEmptyStringSchema,\n confidence: z.number().min(0).max(1),\n sourceEventIds: PerspectiveMemoryStringArraySchema,\n sourceObservationIds: PerspectiveMemoryStringArraySchema,\n createdBy: PerspectiveObservationCreatedBySchema,\n metadata: z.record(z.unknown()).optional(),\n createdAt: z.date(),\n updatedAt: z.date(),\n deletedAt: z.date().optional()\n});\nexport type PerspectiveObservation = z.infer<typeof PerspectiveObservationSchema>;\n\nexport const CreatePerspectiveObservationInputSchema = z.object({\n observationId: z.string().uuid().optional(),\n projectHash: PerspectiveMemoryOptionalStringSchema,\n observerActorId: PerspectiveMemoryNonEmptyStringSchema,\n observedActorId: PerspectiveMemoryNonEmptyStringSchema,\n sessionId: PerspectiveMemoryOptionalStringSchema,\n level: PerspectiveObservationLevelSchema.default('explicit'),\n content: PerspectiveMemoryNonEmptyStringSchema,\n confidence: z.number().min(0).max(1).default(0.5),\n sourceEventIds: PerspectiveMemoryStringArraySchema,\n sourceObservationIds: PerspectiveMemoryStringArraySchema,\n createdBy: PerspectiveObservationCreatedBySchema.default('manual'),\n metadata: z.record(z.unknown()).optional(),\n actor: PerspectiveMemoryOptionalStringSchema\n}).superRefine((value, ctx) => {\n const hasEvidence = value.sourceEventIds.length > 0 || value.sourceObservationIds.length > 0;\n if ((value.createdBy !== 'manual' || value.level !== 'explicit') && !hasEvidence) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['sourceEventIds'],\n message: 'source evidence is required for non-manual or derived perspective observations'\n });\n }\n});\nexport type CreatePerspectiveObservationInput = z.input<typeof CreatePerspectiveObservationInputSchema>;\n\nexport const QueryPerspectiveObservationsInputSchema = z.object({\n projectHash: PerspectiveMemoryOptionalStringSchema,\n observerActorId: PerspectiveMemoryOptionalStringSchema,\n observedActorId: PerspectiveMemoryOptionalStringSchema,\n sessionId: PerspectiveMemoryOptionalStringSchema,\n levels: z.array(PerspectiveObservationLevelSchema).optional(),\n query: PerspectiveMemoryOptionalStringSchema,\n includeDeleted: z.boolean().default(false),\n limit: z.number().int().positive().max(500).default(50)\n});\nexport type QueryPerspectiveObservationsInput = z.input<typeof QueryPerspectiveObservationsInputSchema>;\n\nexport const DeletePerspectiveObservationInputSchema = z.object({\n projectHash: PerspectiveMemoryOptionalStringSchema,\n observationId: PerspectiveMemoryNonEmptyStringSchema,\n actor: PerspectiveMemoryNonEmptyStringSchema\n});\nexport type DeletePerspectiveObservationInput = z.input<typeof DeletePerspectiveObservationInputSchema>;\n\nexport const ListPerspectiveObservationsBySourceInputSchema = z.object({\n projectHash: PerspectiveMemoryOptionalStringSchema,\n sourceEventId: PerspectiveMemoryNonEmptyStringSchema,\n limit: z.number().int().positive().max(500).default(100)\n});\nexport type ListPerspectiveObservationsBySourceInput = z.input<typeof ListPerspectiveObservationsBySourceInputSchema>;\n\n// ============================================================\n// Configuration\n// ============================================================\n\nexport const ConfigSchema = z.object({\n storage: z.object({\n path: z.string().default('~/.claude-code/memory'),\n maxSizeMB: z.number().default(500)\n }).default({}),\n embedding: z.object({\n provider: z.enum(['local', 'openai']).default('local'),\n model: z.string().default('Xenova/multilingual-e5-small'),\n openaiModel: z.string().default('Xenova/multilingual-e5-small'),\n batchSize: z.number().default(32)\n }).default({}),\n retrieval: z.object({\n topK: z.number().default(5),\n minScore: z.number().default(0.7),\n maxTokens: z.number().default(2000)\n }).default({}),\n matching: z.object({\n minCombinedScore: z.number().default(0.92),\n minGap: z.number().default(0.03),\n suggestionThreshold: z.number().default(0.75),\n weights: z.object({\n semanticSimilarity: z.number().default(0.4),\n ftsScore: z.number().default(0.25),\n recencyBonus: z.number().default(0.2),\n statusWeight: z.number().default(0.15)\n }).default({})\n }).default({}),\n privacy: z.object({\n excludePatterns: z.array(z.string()).default(['password', 'secret', 'api_key', 'token', 'bearer']),\n anonymize: z.boolean().default(false),\n privateTags: z.object({\n enabled: z.boolean().default(true),\n marker: z.enum(['[PRIVATE]', '[REDACTED]', '']).default('[PRIVATE]'),\n preserveLineCount: z.boolean().default(false),\n supportedFormats: z.array(z.enum(['xml', 'bracket', 'comment'])).default(['xml'])\n }).default({})\n }).default({}),\n toolObservation: z.object({\n enabled: z.boolean().default(true),\n excludedTools: z.array(z.string()).default(['TodoWrite', 'TodoRead']),\n minOutputLength: z.number().default(100),\n maxOutputLength: z.number().default(10000),\n maxOutputLines: z.number().default(100),\n storeOnlyOnSuccess: z.boolean().default(false)\n }).default({}),\n features: z.object({\n autoSave: z.boolean().default(true),\n sessionSummary: z.boolean().default(true),\n insightExtraction: z.boolean().default(true),\n crossProjectLearning: z.boolean().default(false),\n singleWriterMode: z.boolean().default(true),\n sharedStore: z.object({\n enabled: z.boolean().default(true),\n autoPromote: z.boolean().default(true),\n searchShared: z.boolean().default(true),\n minConfidenceForPromotion: z.number().default(0.8),\n sharedStoragePath: z.string().default('~/.claude-code/memory/shared')\n }).default({})\n }).default({}),\n operations: MemoryOperationsConfigSchema,\n mode: z.enum(['session', 'endless']).default('session'),\n endless: z.object({\n enabled: z.boolean().default(false),\n workingSet: z.object({\n maxEvents: z.number().default(100),\n timeWindowHours: z.number().default(24),\n minRelevanceScore: z.number().default(0.5)\n }).default({}),\n consolidation: z.object({\n triggerIntervalMs: z.number().default(3600000),\n triggerEventCount: z.number().default(100),\n triggerIdleMs: z.number().default(1800000),\n useLLMSummarization: z.boolean().default(false)\n }).default({}),\n continuity: z.object({\n minScoreForSeamless: z.number().default(0.7),\n topicDecayHours: z.number().default(48)\n }).default({})\n }).optional()\n});\nexport type Config = z.infer<typeof ConfigSchema>;\n\n// ============================================================\n// Append Result (AXIOMMIND Principle 2: Append-only)\n// ============================================================\n\nexport type AppendResult =\n | { success: true; eventId: string; isDuplicate: false }\n | { success: true; eventId: string; isDuplicate: true }\n | { success: false; error: string };\n\n// ============================================================\n// Hook Input/Output Types\n// ============================================================\n\nexport interface SessionStartInput {\n session_id: string;\n cwd: string;\n actor_id?: string;\n}\n\nexport interface SessionStartOutput {\n hookSpecificOutput: {\n hookEventName: 'SessionStart';\n additionalContext?: string;\n };\n}\n\nexport interface UserPromptSubmitInput {\n session_id: string;\n prompt: string;\n actor_id?: string;\n}\n\nexport interface UserPromptSubmitOutput {\n hookSpecificOutput: {\n hookEventName: 'UserPromptSubmit';\n additionalContext?: string;\n };\n}\n\n// Stop Hook Input (matches actual Claude Code hook format)\nexport interface StopInput {\n session_id: string;\n transcript_path: string;\n cwd: string;\n permission_mode: string;\n hook_event_name: string;\n stop_hook_active: boolean;\n}\n\nexport interface SessionEndInput {\n session_id: string;\n}\n\n// PostToolUse Hook Input (matches actual Claude Code hook format)\nexport interface PostToolUseInput {\n session_id: string;\n hook_event_name: string;\n tool_name: string;\n tool_input: Record<string, unknown>;\n tool_use_id: string;\n // Claude Code sends tool_response as an object, not tool_output as string\n tool_response: {\n stdout?: string;\n stderr?: string;\n content?: string;\n interrupted?: boolean;\n isImage?: boolean;\n // For non-Bash tools, response may be a plain string or other format\n [key: string]: unknown;\n };\n cwd: string;\n transcript_path: string;\n permission_mode: string;\n}\n\n// ============================================================\n// Tool Observation Types\n// ============================================================\n\nexport const ToolMetadataSchema = z.object({\n filePath: z.string().optional(),\n fileType: z.string().optional(),\n lineCount: z.number().optional(),\n command: z.string().optional(),\n exitCode: z.number().optional(),\n pattern: z.string().optional(),\n matchCount: z.number().optional(),\n url: z.string().optional(),\n statusCode: z.number().optional()\n});\nexport type ToolMetadata = z.infer<typeof ToolMetadataSchema>;\n\nexport const ToolObservationPayloadSchema = z.object({\n toolName: z.string(),\n toolInput: z.record(z.unknown()),\n toolOutput: z.string(),\n durationMs: z.number(),\n success: z.boolean(),\n errorMessage: z.string().optional(),\n metadata: ToolMetadataSchema.optional()\n});\nexport type ToolObservationPayload = z.infer<typeof ToolObservationPayloadSchema>;\n\n// ============================================================\n// Vector Record\n// ============================================================\n\nexport interface VectorRecord {\n id: string;\n eventId: string;\n sessionId: string;\n eventType: string;\n content: string;\n vector: number[];\n timestamp: string;\n metadata?: Record<string, unknown>;\n}\n\n// ============================================================\n// Outbox Item (Single-Writer Pattern)\n// ============================================================\n\nexport interface OutboxItem {\n id: string;\n eventId: string;\n content: string;\n status: 'pending' | 'processing' | 'done' | 'failed';\n retryCount: number;\n createdAt: Date;\n errorMessage?: string;\n}\n\nexport interface OutboxStatsOptions {\n /** Processing rows older than this threshold are considered abandoned/stuck. */\n stuckThresholdMs?: number;\n /** Failed rows below this retry budget are counted as retryable; rows at/above it are counted as quarantined. */\n maxRetries?: number;\n /** Test hook for deterministic age calculations. */\n now?: Date;\n}\n\nexport interface OutboxQueueStats {\n pending: number;\n processing: number;\n failed: number;\n /** Failed rows that recovery can safely move back to pending without exposing payloads. */\n retryableFailed?: number;\n /** Failed rows at/above retry budget that need operator attention/quarantine handling. */\n quarantinedFailed?: number;\n total: number;\n stuckProcessing: number;\n /** Age in milliseconds for the oldest processing row, or null when none are processing. */\n oldestProcessingAgeMs: number | null;\n}\n\nexport interface OutboxStats {\n embedding: OutboxQueueStats;\n vector: OutboxQueueStats;\n}\n\nexport interface OutboxRecoveryOptions {\n /** Processing rows older than this threshold are considered abandoned. */\n stuckThresholdMs?: number;\n /** Retry failed rows whose retry_count is still below this value. */\n maxRetries?: number;\n /** Count rows that would be recovered/retried without mutating them. */\n dryRun?: boolean;\n /** Test hook for deterministic recovery cutoffs. */\n now?: Date;\n}\n\nexport interface OutboxRecoveryBucket {\n recoveredProcessing: number;\n retriedFailed: number;\n}\n\nexport interface OutboxRecoveryResult {\n embedding: OutboxRecoveryBucket;\n vector: OutboxRecoveryBucket;\n}\n\nexport interface ProjectScopeRepairOptions {\n /** Absolute or logical project path used to derive the expected project hash. */\n projectPath?: string;\n /** Explicit project hash override for hash-only repair flows. */\n projectHash?: string;\n /** Inspect and count changes without mutating event metadata. */\n dryRun?: boolean;\n /** Test hook for deterministic repair metadata. */\n now?: Date;\n}\n\nexport interface ProjectScopeRepairSample {\n eventId: string;\n action: 'repaired' | 'quarantined';\n reason: 'same-project-path' | 'session-project-path' | 'project-path-mismatch' | 'missing-project-scope' | 'scope-hash-mismatch' | 'content-project-mismatch';\n}\n\nexport interface ProjectScopeRepairResult {\n dryRun: boolean;\n projectHash: string;\n scanned: number;\n repaired: number;\n quarantined: number;\n alreadyScoped: number;\n skipped: number;\n samples: ProjectScopeRepairSample[];\n}\n\n// ============================================================\n// Entity Types (Task, Condition, Artifact)\n// ============================================================\n\nexport const EntityTypeSchema = z.enum(['task', 'condition', 'artifact', 'source_file']);\nexport type EntityType = z.infer<typeof EntityTypeSchema>;\n\nexport const TaskStatusSchema = z.enum([\n 'pending',\n 'in_progress',\n 'blocked',\n 'done',\n 'cancelled'\n]);\nexport type TaskStatus = z.infer<typeof TaskStatusSchema>;\n\nexport const TaskPrioritySchema = z.enum(['low', 'medium', 'high', 'critical']);\nexport type TaskPriority = z.infer<typeof TaskPrioritySchema>;\n\nexport const EntityStageSchema = z.enum([\n 'raw',\n 'working',\n 'candidate',\n 'verified',\n 'certified'\n]);\nexport type EntityStage = z.infer<typeof EntityStageSchema>;\n\nexport const EntityStatusSchema = z.enum([\n 'active',\n 'contested',\n 'deprecated',\n 'superseded'\n]);\nexport type EntityStatus = z.infer<typeof EntityStatusSchema>;\n\n// Base Entity schema\nexport const EntitySchema = z.object({\n entityId: z.string(),\n entityType: EntityTypeSchema,\n canonicalKey: z.string(),\n title: z.string(),\n stage: EntityStageSchema,\n status: EntityStatusSchema,\n currentJson: z.record(z.unknown()),\n titleNorm: z.string().optional(),\n searchText: z.string().optional(),\n createdAt: z.date(),\n updatedAt: z.date()\n});\nexport type Entity = z.infer<typeof EntitySchema>;\n\n// Task-specific current_json structure\nexport const TaskCurrentJsonSchema = z.object({\n status: TaskStatusSchema,\n priority: TaskPrioritySchema.optional(),\n blockers: z.array(z.string()).optional(),\n blockerSuggestions: z.array(z.string()).optional(),\n description: z.string().optional(),\n project: z.string().optional()\n});\nexport type TaskCurrentJson = z.infer<typeof TaskCurrentJsonSchema>;\n\n// Entity alias for canonical key lookup\nexport const EntityAliasSchema = z.object({\n entityType: EntityTypeSchema,\n canonicalKey: z.string(),\n entityId: z.string(),\n isPrimary: z.boolean()\n});\nexport type EntityAlias = z.infer<typeof EntityAliasSchema>;\n\n// ============================================================\n// Edge Types (Relationships)\n// ============================================================\n\nexport const NodeTypeSchema = z.enum(['entry', 'entity', 'event']);\nexport type NodeType = z.infer<typeof NodeTypeSchema>;\n\nexport const RelationTypeSchema = z.enum([\n 'evidence_of',\n 'blocked_by',\n 'blocked_by_suggested',\n 'resolves_to',\n 'derived_from',\n 'supersedes',\n 'source_of',\n 'touched_in'\n]);\nexport type RelationType = z.infer<typeof RelationTypeSchema>;\n\nexport const EdgeSchema = z.object({\n edgeId: z.string(),\n srcType: NodeTypeSchema,\n srcId: z.string(),\n relType: RelationTypeSchema,\n dstType: NodeTypeSchema,\n dstId: z.string(),\n metaJson: z.record(z.unknown()).optional(),\n createdAt: z.date()\n});\nexport type Edge = z.infer<typeof EdgeSchema>;\n\n// ============================================================\n// Task Event Types (SoT for Task Entity)\n// ============================================================\n\nexport const TaskEventTypeSchema = z.enum([\n 'task_created',\n 'task_status_changed',\n 'task_priority_changed',\n 'task_blockers_set',\n 'task_transition_rejected',\n 'condition_declared',\n 'artifact_declared',\n 'condition_resolved_to'\n]);\nexport type TaskEventType = z.infer<typeof TaskEventTypeSchema>;\n\nexport const BlockerModeSchema = z.enum(['replace', 'suggest']);\nexport type BlockerMode = z.infer<typeof BlockerModeSchema>;\n\nexport const BlockerKindSchema = z.enum(['task', 'condition', 'artifact']);\nexport type BlockerKind = z.infer<typeof BlockerKindSchema>;\n\nexport const BlockerRefSchema = z.object({\n kind: BlockerKindSchema,\n entityId: z.string(),\n rawText: z.string().optional(),\n confidence: z.number().min(0).max(1).optional(),\n candidates: z.array(z.string()).optional()\n});\nexport type BlockerRef = z.infer<typeof BlockerRefSchema>;\n\n// Task event payloads\nexport const TaskCreatedPayloadSchema = z.object({\n taskId: z.string(),\n title: z.string(),\n canonicalKey: z.string(),\n initialStatus: TaskStatusSchema,\n priority: TaskPrioritySchema.optional(),\n description: z.string().optional(),\n project: z.string().optional()\n});\nexport type TaskCreatedPayload = z.infer<typeof TaskCreatedPayloadSchema>;\n\nexport const TaskStatusChangedPayloadSchema = z.object({\n taskId: z.string(),\n fromStatus: TaskStatusSchema,\n toStatus: TaskStatusSchema,\n reason: z.string().optional()\n});\nexport type TaskStatusChangedPayload = z.infer<typeof TaskStatusChangedPayloadSchema>;\n\nexport const TaskBlockersSetPayloadSchema = z.object({\n taskId: z.string(),\n mode: BlockerModeSchema,\n blockers: z.array(BlockerRefSchema),\n sourceEntryId: z.string().optional()\n});\nexport type TaskBlockersSetPayload = z.infer<typeof TaskBlockersSetPayloadSchema>;\n\n// ============================================================\n// Entry Types (Immutable memory units)\n// ============================================================\n\nexport const EntryTypeSchema = z.enum([\n 'fact',\n 'decision',\n 'insight',\n 'task_note',\n 'reference',\n 'preference',\n 'pattern',\n 'troubleshooting'\n]);\nexport type EntryType = z.infer<typeof EntryTypeSchema>;\n\nexport const EntrySchema = z.object({\n entryId: z.string(),\n createdTs: z.date(),\n entryType: EntryTypeSchema,\n title: z.string(),\n contentJson: z.record(z.unknown()),\n stage: EntityStageSchema,\n status: EntityStatusSchema,\n supersededBy: z.string().optional(),\n buildId: z.string().optional(),\n evidenceJson: z.record(z.unknown()).optional(),\n canonicalKey: z.string()\n});\nexport type Entry = z.infer<typeof EntrySchema>;\n\n// ============================================================\n// Evidence Aligner V2 Types\n// ============================================================\n\nexport const ExtractedEvidenceSchema = z.object({\n messageIndex: z.number().int().nonnegative(),\n quote: z.string()\n});\nexport type ExtractedEvidence = z.infer<typeof ExtractedEvidenceSchema>;\n\nexport const AlignedEvidenceSchema = z.object({\n messageIndex: z.number().int().nonnegative(),\n quote: z.string(),\n spanStart: z.number().int().nonnegative(),\n spanEnd: z.number().int().positive(),\n quoteHash: z.string(),\n confidence: z.number().min(0).max(1),\n matchMethod: z.enum(['exact', 'normalized', 'fuzzy'])\n});\nexport type AlignedEvidence = z.infer<typeof AlignedEvidenceSchema>;\n\nexport const FailedEvidenceSchema = z.object({\n messageIndex: z.number().int().nonnegative(),\n quote: z.string(),\n failureReason: z.enum(['not_found', 'below_threshold', 'ambiguous', 'empty_quote', 'invalid_index'])\n});\nexport type FailedEvidence = z.infer<typeof FailedEvidenceSchema>;\n\nexport const EvidenceAlignResultSchema = z.discriminatedUnion('aligned', [\n z.object({ aligned: z.literal(true), evidence: AlignedEvidenceSchema }),\n z.object({ aligned: z.literal(false), evidence: FailedEvidenceSchema })\n]);\nexport type EvidenceAlignResult = z.infer<typeof EvidenceAlignResultSchema>;\n\n// ============================================================\n// Vector Outbox V2 Types\n// ============================================================\n\nexport const OutboxStatusSchema = z.enum(['pending', 'processing', 'done', 'failed']);\nexport type OutboxStatus = z.infer<typeof OutboxStatusSchema>;\n\nexport const OutboxItemKindSchema = z.enum(['entry', 'task_title', 'event', 'perspective_observation']);\nexport type OutboxItemKind = z.infer<typeof OutboxItemKindSchema>;\n\nexport const OutboxJobSchema = z.object({\n jobId: z.string(),\n itemKind: OutboxItemKindSchema,\n itemId: z.string(),\n embeddingVersion: z.string(),\n status: OutboxStatusSchema,\n retryCount: z.number().int().nonnegative(),\n error: z.string().optional(),\n createdAt: z.date(),\n updatedAt: z.date()\n});\nexport type OutboxJob = z.infer<typeof OutboxJobSchema>;\n\n// Valid state transitions for outbox\nexport const VALID_OUTBOX_TRANSITIONS: Array<{ from: OutboxStatus; to: OutboxStatus }> = [\n { from: 'pending', to: 'processing' },\n { from: 'processing', to: 'done' },\n { from: 'processing', to: 'failed' },\n { from: 'failed', to: 'pending' }\n];\n\n// ============================================================\n// Build Runs (Pipeline metadata)\n// ============================================================\n\nexport const BuildRunSchema = z.object({\n buildId: z.string(),\n startedAt: z.date(),\n finishedAt: z.date().optional(),\n extractorModel: z.string(),\n extractorPromptHash: z.string(),\n embedderModel: z.string(),\n embeddingVersion: z.string(),\n idrisVersion: z.string(),\n schemaVersion: z.string(),\n status: z.enum(['running', 'success', 'failed']),\n error: z.string().optional()\n});\nexport type BuildRun = z.infer<typeof BuildRunSchema>;\n\n// ============================================================\n// Pipeline Metrics\n// ============================================================\n\nexport const PipelineMetricSchema = z.object({\n id: z.string(),\n ts: z.date(),\n stage: z.string(),\n latencyMs: z.number(),\n success: z.boolean(),\n error: z.string().optional(),\n sessionId: z.string().optional()\n});\nexport type PipelineMetric = z.infer<typeof PipelineMetricSchema>;\n\n// ============================================================\n// Progressive Disclosure Types\n// ============================================================\n\n// Layer 1: Search Index (lightweight)\nexport const SearchIndexItemSchema = z.object({\n id: z.string(),\n summary: z.string().max(100),\n score: z.number(),\n type: z.enum(['user_prompt', 'agent_response', 'session_summary', 'tool_observation']),\n timestamp: z.date(),\n sessionId: z.string()\n});\nexport type SearchIndexItem = z.infer<typeof SearchIndexItemSchema>;\n\n// Layer 2: Timeline\nexport const TimelineItemSchema = z.object({\n id: z.string(),\n timestamp: z.date(),\n type: z.enum(['user_prompt', 'agent_response', 'session_summary', 'tool_observation']),\n preview: z.string().max(200),\n isTarget: z.boolean()\n});\nexport type TimelineItem = z.infer<typeof TimelineItemSchema>;\n\n// Layer 3: Full Detail\nexport const FullDetailSchema = z.object({\n id: z.string(),\n content: z.string(),\n type: z.enum(['user_prompt', 'agent_response', 'session_summary', 'tool_observation']),\n timestamp: z.date(),\n sessionId: z.string(),\n citationId: z.string().optional(),\n metadata: z.object({\n tokenCount: z.number(),\n hasCode: z.boolean(),\n files: z.array(z.string()).optional(),\n tools: z.array(z.string()).optional()\n })\n});\nexport type FullDetail = z.infer<typeof FullDetailSchema>;\n\n// Progressive Search Result\nexport const ProgressiveSearchResultSchema = z.object({\n index: z.array(SearchIndexItemSchema),\n timeline: z.array(TimelineItemSchema).optional(),\n details: z.array(FullDetailSchema).optional(),\n meta: z.object({\n totalMatches: z.number(),\n expandedCount: z.number(),\n estimatedTokens: z.number(),\n expansionReason: z.string().optional()\n })\n});\nexport type ProgressiveSearchResult = z.infer<typeof ProgressiveSearchResultSchema>;\n\n// Progressive Disclosure Config\nexport const ProgressiveDisclosureConfigSchema = z.object({\n enabled: z.boolean().default(true),\n layer1: z.object({\n topK: z.number().default(10),\n minScore: z.number().default(0.7)\n }).default({}),\n autoExpand: z.object({\n enabled: z.boolean().default(true),\n highConfidenceThreshold: z.number().default(0.92),\n scoreGapThreshold: z.number().default(0.1),\n maxAutoExpandCount: z.number().default(3)\n }).default({}),\n tokenBudget: z.object({\n maxTotalTokens: z.number().default(2000),\n layer1PerItem: z.number().default(50),\n layer2PerItem: z.number().default(40),\n layer3PerItem: z.number().default(500)\n }).default({})\n});\nexport type ProgressiveDisclosureConfig = z.infer<typeof ProgressiveDisclosureConfigSchema>;\n\n// ============================================================\n// Citation Types\n// ============================================================\n\nexport const CitationSchema = z.object({\n citationId: z.string().length(6),\n eventId: z.string(),\n createdAt: z.date()\n});\nexport type Citation = z.infer<typeof CitationSchema>;\n\nexport const CitationUsageSchema = z.object({\n usageId: z.string(),\n citationId: z.string(),\n sessionId: z.string(),\n usedAt: z.date(),\n context: z.string().optional()\n});\nexport type CitationUsage = z.infer<typeof CitationUsageSchema>;\n\nexport interface CitedSearchResult {\n event: MemoryEvent;\n citation: Citation;\n score: number;\n}\n\nexport interface CitationStats {\n usageCount: number;\n lastUsed: Date | null;\n}\n\n// ============================================================\n// Endless Mode Types\n// ============================================================\n\nexport const MemoryModeSchema = z.enum(['session', 'endless']);\nexport type MemoryMode = z.infer<typeof MemoryModeSchema>;\n\nexport const EndlessModeConfigSchema = z.object({\n enabled: z.boolean().default(false),\n\n workingSet: z.object({\n maxEvents: z.number().default(100),\n timeWindowHours: z.number().default(24),\n minRelevanceScore: z.number().default(0.5)\n }).default({}),\n\n consolidation: z.object({\n triggerIntervalMs: z.number().default(3600000), // 1 hour\n triggerEventCount: z.number().default(100),\n triggerIdleMs: z.number().default(1800000), // 30 minutes\n useLLMSummarization: z.boolean().default(false)\n }).default({}),\n\n continuity: z.object({\n minScoreForSeamless: z.number().default(0.7),\n topicDecayHours: z.number().default(48)\n }).default({})\n});\nexport type EndlessModeConfig = z.infer<typeof EndlessModeConfigSchema>;\n\n// Working Set Item\nexport const WorkingSetItemSchema = z.object({\n id: z.string(),\n eventId: z.string(),\n addedAt: z.date(),\n relevanceScore: z.number(),\n topics: z.array(z.string()).optional(),\n expiresAt: z.date()\n});\nexport type WorkingSetItem = z.infer<typeof WorkingSetItemSchema>;\n\n// Working Set\nexport interface WorkingSet {\n recentEvents: MemoryEvent[];\n lastActivity: Date;\n continuityScore: number;\n}\n\n// Consolidated Memory\nexport const ConsolidatedMemorySchema = z.object({\n memoryId: z.string(),\n summary: z.string(),\n topics: z.array(z.string()),\n sourceEvents: z.array(z.string()),\n confidence: z.number(),\n createdAt: z.date(),\n accessedAt: z.date().optional(),\n accessCount: z.number().default(0)\n});\nexport type ConsolidatedMemory = z.infer<typeof ConsolidatedMemorySchema>;\n\n// Consolidated Memory Input (for creation)\nexport interface ConsolidatedMemoryInput {\n summary: string;\n topics: string[];\n sourceEvents: string[];\n confidence: number;\n}\n\n// Long-term Rule (promoted from stable summaries)\nexport const ConsolidationRuleSchema = z.object({\n ruleId: z.string(),\n rule: z.string(),\n topics: z.array(z.string()),\n sourceMemoryIds: z.array(z.string()),\n sourceEvents: z.array(z.string()),\n confidence: z.number(),\n createdAt: z.date()\n});\nexport type ConsolidationRule = z.infer<typeof ConsolidationRuleSchema>;\n\nexport interface ConsolidationRuleInput {\n rule: string;\n topics: string[];\n sourceMemoryIds: string[];\n sourceEvents: string[];\n confidence: number;\n}\n\nexport interface ConsolidationCostQualityReport {\n beforeTokenEstimate: number;\n afterTokenEstimate: number;\n reductionRatio: number;\n qualityGuardPassed: boolean;\n details: string;\n}\n\n// Event Group (for consolidation)\nexport interface EventGroup {\n topics: string[];\n events: MemoryEvent[];\n}\n\n// Context Snapshot (for continuity calculation)\nexport interface ContextSnapshot {\n id: string;\n timestamp: number;\n topics: string[];\n files: string[];\n entities: string[];\n}\n\n// Transition Type\nexport const TransitionTypeSchema = z.enum(['seamless', 'topic_shift', 'break']);\nexport type TransitionType = z.infer<typeof TransitionTypeSchema>;\n\n// Continuity Score Result\nexport interface ContinuityScore {\n score: number;\n transitionType: TransitionType;\n}\n\n// Continuity Log\nexport const ContinuityLogSchema = z.object({\n logId: z.string(),\n fromContextId: z.string().optional(),\n toContextId: z.string().optional(),\n continuityScore: z.number(),\n transitionType: TransitionTypeSchema,\n createdAt: z.date()\n});\nexport type ContinuityLog = z.infer<typeof ContinuityLogSchema>;\n\n// Endless Mode Status\nexport interface EndlessModeStatus {\n mode: MemoryMode;\n workingSetSize: number;\n continuityScore: number;\n consolidatedCount: number;\n lastConsolidation: Date | null;\n}\n\n// ============================================================\n// Shared Store Types (Cross-Project Knowledge)\n// ============================================================\n\nexport const SharedEntryTypeSchema = z.enum([\n 'troubleshooting',\n 'best_practice',\n 'common_error'\n]);\nexport type SharedEntryType = z.infer<typeof SharedEntryTypeSchema>;\n\nexport const SharedTroubleshootingEntrySchema = z.object({\n entryId: z.string(),\n sourceProjectHash: z.string(),\n sourceEntryId: z.string(),\n title: z.string(),\n symptoms: z.array(z.string()),\n rootCause: z.string(),\n solution: z.string(),\n topics: z.array(z.string()),\n technologies: z.array(z.string()).optional(),\n confidence: z.number().min(0).max(1),\n usageCount: z.number().default(0),\n lastUsedAt: z.date().optional(),\n promotedAt: z.date(),\n createdAt: z.date()\n});\nexport type SharedTroubleshootingEntry = z.infer<typeof SharedTroubleshootingEntrySchema>;\n\nexport interface SharedTroubleshootingInput {\n sourceProjectHash: string;\n sourceEntryId: string;\n title: string;\n symptoms: string[];\n rootCause: string;\n solution: string;\n topics: string[];\n technologies?: string[];\n confidence: number;\n}\n\nexport const SharedStoreConfigSchema = z.object({\n enabled: z.boolean().default(true),\n autoPromote: z.boolean().default(true),\n searchShared: z.boolean().default(true),\n minConfidenceForPromotion: z.number().default(0.8),\n sharedStoragePath: z.string().default('~/.claude-code/memory/shared')\n});\nexport type SharedStoreConfig = z.infer<typeof SharedStoreConfigSchema>;\n\n// Shared search result\nexport interface SharedSearchResult {\n id: string;\n entryId: string;\n content: string;\n score: number;\n entryType: SharedEntryType;\n}\n", "import { sqliteAll, toDateFromSQLite, type SQLiteDatabase } from './sqlite-wrapper.js';\n\n/** Audit dimensions are enums, never arbitrary metadata or filesystem paths. */\nexport function safeSourceLabel(value: unknown): string {\n if (value == null || value === '') return 'native';\n return ['native', 'claude', 'claude-code', 'codex', 'hermes', 'import', 'manual'].includes(String(value))\n ? String(value) : 'other';\n}\n\nexport function safeClientLabel(value: unknown): string {\n return ['claude-hook', 'codex-hook', 'mcp', 'hermes', 'cli', 'dashboard'].includes(String(value))\n ? String(value) : 'unknown';\n}\n\n/** Reads clocks without initialization or migrations, suitable for audit snapshots. */\nexport function readIngestSourceClocks(db: SQLiteDatabase, options: { since?: Date; until?: Date } = {}) {\n const eventColumns = new Set(sqliteAll<{ name: string }>(db, 'PRAGMA table_info(events)').map((row) => row.name));\n const sourceExpression = eventColumns.has('metadata')\n ? `COALESCE(\n json_extract(CASE WHEN json_valid(metadata) THEN metadata ELSE '{}' END, '$.source'),\n 'native'\n )`\n : `'native'`;\n const occurredAtExpression = eventColumns.has('metadata')\n ? `COALESCE(\n json_extract(CASE WHEN json_valid(metadata) THEN metadata ELSE '{}' END, '$.originalTimestamp'),\n json_extract(CASE WHEN json_valid(metadata) THEN metadata ELSE '{}' END, '$.ingest.occurredAt')\n )`\n : 'NULL';\n const clauses: string[] = [];\n const params: unknown[] = [];\n if (options.since) {\n clauses.push('julianday(timestamp) >= julianday(?)');\n params.push(options.since.toISOString());\n }\n if (options.until) {\n clauses.push('julianday(timestamp) < julianday(?)');\n params.push(options.until.toISOString());\n }\n const where = clauses.length > 0 ? ` WHERE ${clauses.join(' AND ')}` : '';\n const rows = sqliteAll<{ source: string | null; timestamp: string; occurred_at: string | null }>(\n db,\n `SELECT\n ${sourceExpression} AS source,\n timestamp,\n ${occurredAtExpression} AS occurred_at\n FROM events${where}`,\n params\n );\n\n const bySource = new Map<string, {\n events: number;\n lags: number[];\n unknown: number;\n latestOccurredAt: number | null;\n latestIngestedAt: number | null;\n }>();\n for (const row of rows) {\n const source = safeSourceLabel(row.source);\n const entry = bySource.get(source)\n ?? { events: 0, lags: [], unknown: 0, latestOccurredAt: null, latestIngestedAt: null };\n entry.events += 1;\n const ingestedMs = toDateFromSQLite(row.timestamp ?? '').getTime();\n if (Number.isFinite(ingestedMs)) {\n entry.latestIngestedAt = entry.latestIngestedAt === null\n ? ingestedMs\n : Math.max(entry.latestIngestedAt, ingestedMs);\n }\n const occurredMs = row.occurred_at ? toDateFromSQLite(row.occurred_at).getTime() : NaN;\n if (Number.isFinite(occurredMs)) {\n entry.latestOccurredAt = entry.latestOccurredAt === null\n ? occurredMs\n : Math.max(entry.latestOccurredAt, occurredMs);\n if (Number.isFinite(ingestedMs)) entry.lags.push(Math.max(0, ingestedMs - occurredMs));\n } else {\n entry.unknown += 1;\n }\n bySource.set(source, entry);\n }\n\n return Array.from(bySource.entries())\n .map(([source, entry]) => {\n const sorted = [...entry.lags].sort((a, b) => a - b);\n return {\n source,\n events: entry.events,\n withSourceClock: entry.lags.length,\n unknownSourceClock: entry.unknown,\n latestOccurredAt: entry.latestOccurredAt === null ? null : new Date(entry.latestOccurredAt).toISOString(),\n latestIngestedAt: entry.latestIngestedAt === null ? null : new Date(entry.latestIngestedAt).toISOString(),\n maxLagMs: sorted.length > 0 ? sorted[sorted.length - 1] : null,\n medianLagMs: sorted.length > 0 ? sorted[Math.floor((sorted.length - 1) / 2)] : null\n };\n })\n .sort((a, b) => b.events - a.events);\n}\n", "/** Independent rollback switches. Readers and existing tables remain intact. */\nexport function retrievalRollout() {\n const enabled = (name: string) => !['0', 'false', 'off'].includes((process.env[name] ?? '').toLowerCase());\n return {\n typedTraceWrite: enabled('CML_TYPED_TRACE_WRITE'),\n usefulnessV3Write: enabled('CML_USEFULNESS_V3_WRITE'),\n usefulnessV3Ui: enabled('CML_USEFULNESS_V3_UI')\n };\n}\n", "import { readIngestSourceClocks } from './ingest-source-clocks.js';\nimport { retrievalRollout } from './retrieval-rollout.js';\n/**\n * SQLite-based EventStore implementation\n * Primary store for hooks - WAL mode enables concurrent access\n */\n\nimport { randomUUID } from 'crypto';\nimport {\n EventType,\n MemoryEvent,\n MemoryEventInput,\n Session,\n AppendResult,\n OutboxItem,\n OutboxStats,\n OutboxStatsOptions,\n OutboxRecoveryOptions,\n OutboxRecoveryResult,\n ProjectScopeRepairOptions,\n ProjectScopeRepairResult,\n ProjectScopeRepairSample\n} from './types.js';\nimport { makeCanonicalKey, makeDedupeKey } from './canonical-key.js';\nimport { generateCitationId } from './citation-generator.js';\nimport * as nodePath from 'path';\nimport { hashProjectPath, hashProjectPathIgnoringMarker } from './registry/project-path.js';\nimport {\n createSQLiteDatabase,\n sqliteRun,\n sqliteAll,\n sqliteGet,\n sqliteClose,\n sqliteExec,\n toDateFromSQLite,\n toSQLiteTimestamp,\n type SQLiteDatabase,\n type SQLiteOptions\n} from './sqlite-wrapper.js';\nimport { MarkdownMirror } from './markdown-mirror.js';\nimport { VectorOutbox, type OutboxConfig } from './vector-outbox.js';\nimport { normalizeRetrievalDebugLanes, type RetrievalDebugLane } from './retrieval-debug-lanes.js';\nimport { computeMemoryUsageEvidence, type EvidenceMatch } from './usefulness-evidence.js';\nimport {\n buildUsefulnessObservationV2,\n classifyReaskOutcome,\n parseToolOutcome,\n USEFULNESS_V2_EVALUATION_WINDOW_MS\n} from './usefulness-outcome-v2.js';\nimport {\n CURRENT_USEFULNESS_EVALUATOR_VERSION,\n LEGACY_ASSUMED_DELIVERY_EVALUATOR_VERSIONS,\n RETRIEVAL_TELEMETRY_SCHEMA_VERSION,\n deliveredFromStatus,\n emptyUsefulnessAggregateV2,\n normalizeDeliveryEvidence,\n normalizeDeliveryStatus,\n normalizeRequestId,\n normalizeUsefulnessMinimumSample,\n presentedOutcomeReason,\n normalizeRetrievalPresentationMode,\n normalizeRetrievalOutcomeDiagnostics,\n normalizeRetrievalTriggerType,\n normalizeTelemetryClient,\n type RecordReferenceNavigationInput,\n type RecordReferenceNavigationResult,\n type RetrievalPresentationMode,\n type RetrievalOutcomeDiagnostics,\n type RetrievalTelemetryContext,\n type RetrievalTelemetryStats,\n type RetrievalTriggerType,\n type DeliveryEvidenceSource,\n type DeliveryStatus,\n type MemoryUsefulnessObservationV2,\n type RetrievalClientCoverage,\n type UsefulnessAdoption,\n type RetrievalTraceItemInput,\n type TypedSelectionSummary,\n type UsefulnessAggregateV2,\n type UsefulnessRateV2\n} from './retrieval-telemetry.js';\nimport {\n normalizeMemoryKind,\n usefulnessRowKey,\n usefulnessRowKeySql,\n type MemoryKind\n} from './memory-ref.js';\nimport { recordReferenceNavigationOnDb } from './retrieval-navigation.js';\nimport {\n backfillTraceItems,\n ensureRetrievalTraceItemsSchema,\n normalizeTraceItems,\n readTraceItems,\n resolveMemoryRefKinds,\n summarizeTypedSelections,\n writeTraceItems,\n type TraceItemBackfillResult\n} from './retrieval-trace-ledger.js';\n\nexport interface SQLiteEventStoreOptions extends SQLiteOptions {\n markdownMirrorRoot?: string;\n vectorOutbox?: false | VectorOutbox | Partial<OutboxConfig>;\n}\n\nexport interface DerivationLiveness {\n graduation: {\n attempts: number;\n lastAttemptAt: string | null;\n lastSuccessAt: string | null;\n lastStatus: 'success' | 'not_eligible' | 'failed' | null;\n lastErrorCategory: 'graduation_failed' | null;\n };\n sources: {\n graduatedEvents: number;\n curatedLessons: number;\n };\n}\n\ntype QueryRewriteKind = 'none' | 'follow-up-context' | 'intent-rewrite';\n\ntype RetrievalTraceDetailRecord = {\n eventId: string;\n score: number;\n semanticScore?: number;\n lexicalScore?: number;\n recencyScore?: number;\n lanes?: RetrievalDebugLane[];\n};\n\nfunction normalizeRetrievalTraceDetails(details?: RetrievalTraceDetailRecord[]): RetrievalTraceDetailRecord[] {\n return (details || []).map((detail) => {\n const lanes = normalizeRetrievalDebugLanes((detail as { lanes?: unknown }).lanes);\n const normalized: RetrievalTraceDetailRecord = {\n eventId: detail.eventId,\n score: detail.score\n };\n if (detail.semanticScore !== undefined) normalized.semanticScore = detail.semanticScore;\n if (detail.lexicalScore !== undefined) normalized.lexicalScore = detail.lexicalScore;\n if (detail.recencyScore !== undefined) normalized.recencyScore = detail.recencyScore;\n if (lanes.length > 0) normalized.lanes = lanes;\n return normalized;\n });\n}\n\nfunction parseRetrievalTraceDetails(value: unknown): RetrievalTraceDetailRecord[] {\n if (typeof value !== 'string' || value.length === 0) return [];\n const parsed = JSON.parse(value);\n return Array.isArray(parsed) ? normalizeRetrievalTraceDetails(parsed as RetrievalTraceDetailRecord[]) : [];\n}\n\n/**\n * Read a trace's diagnostics.\n *\n * Rows written before the honest-default migration stored `runtime_error` as a\n * fallback for \"no diagnostics\", not as an observed exception. They are shown\n * as `legacy_unclassified` and never rewritten in place (specs R2).\n */\nfunction parseRetrievalOutcomeDiagnostics(row: Record<string, unknown>): RetrievalOutcomeDiagnostics {\n let value: unknown;\n try {\n value = typeof row.retrieval_diagnostics_json === 'string'\n ? JSON.parse(row.retrieval_diagnostics_json)\n : undefined;\n } catch {\n value = undefined;\n }\n const presented = presentedOutcomeReason(row.outcome_reason, row.telemetry_schema_version);\n const diagnostics = normalizeRetrievalOutcomeDiagnostics(value, presented);\n return Number(row.telemetry_schema_version) >= 2\n ? diagnostics\n : { ...diagnostics, outcomeReason: presented };\n}\n\nfunction normalizeQueryRewriteKind(value?: string | null): QueryRewriteKind {\n const normalized = (value || '').trim().toLowerCase();\n if (normalized === 'follow-up-context' || normalized === 'intent-rewrite') return normalized;\n return 'none';\n}\n\nconst REWRITTEN_QUERY_REWRITE_KIND_SQL = `LOWER(TRIM(COALESCE(query_rewrite_kind, 'none'))) IN ('follow-up-context', 'intent-rewrite')`;\nconst DEFAULT_OUTBOX_STUCK_THRESHOLD_MS = 5 * 60 * 1000;\nconst DEFAULT_OUTBOX_MAX_RETRIES = 3;\n// Re-exported for existing importers; the implementation moved next to the\n// navigation recorder so db-only callers can reuse both.\nexport { REFERENCE_ATTRIBUTION_WINDOW_MS } from './retrieval-navigation.js';\n// Bump when introducing an ordered migration that must run exactly once; gate\n// such migrations on the persisted PRAGMA user_version.\nconst SQLITE_SCHEMA_VERSION = 1;\n\nfunction emptyOutboxRecoveryResult(): OutboxRecoveryResult {\n return {\n embedding: { recoveredProcessing: 0, retriedFailed: 0 },\n vector: { recoveredProcessing: 0, retriedFailed: 0 }\n };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction getNestedRecord(root: Record<string, unknown> | undefined, path: string[]): Record<string, unknown> | undefined {\n let cursor: unknown = root;\n for (const key of path) {\n if (!isRecord(cursor)) return undefined;\n cursor = cursor[key];\n }\n return isRecord(cursor) ? cursor : undefined;\n}\n\nfunction getNestedString(root: Record<string, unknown> | undefined, path: string[]): string | undefined {\n let cursor: unknown = root;\n for (const key of path) {\n if (!isRecord(cursor)) return undefined;\n cursor = cursor[key];\n }\n return typeof cursor === 'string' && cursor.length > 0 ? cursor : undefined;\n}\n\nfunction metadataProjectHash(metadata: Record<string, unknown> | undefined): string | undefined {\n return getNestedString(metadata, ['scope', 'project', 'hash']);\n}\n\nfunction metadataProjectPaths(metadata: Record<string, unknown> | undefined): string[] {\n const candidates = [\n getNestedString(metadata, ['projectPath']),\n getNestedString(metadata, ['sourceProjectPath']),\n getNestedString(metadata, ['scope', 'project', 'path'])\n ];\n const paths: string[] = [];\n for (const value of candidates) {\n if (value && !paths.includes(value)) paths.push(value);\n }\n return paths;\n}\n\nfunction metadataProjectPath(metadata: Record<string, unknown> | undefined): string | undefined {\n return metadataProjectPaths(metadata)[0];\n}\n\nfunction isActiveQuarantinedMetadata(metadata: Record<string, unknown> | undefined): boolean {\n const quarantine = getNestedRecord(metadata, ['quarantine']);\n return quarantine?.status === 'active';\n}\n\nfunction activeQuarantineStatusExpression(column = 'metadata'): string {\n return `COALESCE(json_extract(CASE WHEN json_valid(${column}) THEN ${column} ELSE '{}' END, '$.quarantine.status'), '')`;\n}\n\nfunction notActiveQuarantinedSql(column = 'metadata'): string {\n return `${activeQuarantineStatusExpression(column)} != 'active'`;\n}\n\ninterface QuarantineReadOptions {\n includeQuarantined?: boolean;\n}\n\nexport interface RecentEventsReadOptions extends QuarantineReadOptions {\n /** Restrict to these event types. An empty/omitted list means \"any type\". */\n eventTypes?: EventType[];\n}\n\nfunction maybeQuarantinePredicate(options?: QuarantineReadOptions, column = 'metadata'): string {\n return options?.includeQuarantined ? '1=1' : notActiveQuarantinedSql(column);\n}\n\nfunction safeParseMetadataValue(value: unknown): Record<string, unknown> | undefined {\n if (!value) return undefined;\n if (typeof value === 'object') return isRecord(value) ? value : undefined;\n if (typeof value !== 'string') return undefined;\n try {\n const parsed = JSON.parse(value);\n return isRecord(parsed) ? parsed : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction isImportedOrLegacyScopedMetadata(metadata: Record<string, unknown> | undefined): boolean {\n if (!metadata) return false;\n return Boolean(\n metadata.importedFrom\n || metadata.sourceSessionId\n || metadata.sourceSessionHash\n || metadata.hermesSource\n || metadata.projectPath\n || metadata.sourceProjectPath\n || metadata.source === 'hermes'\n || metadata.source === 'claude'\n || metadata.source === 'codex'\n );\n}\n\nfunction addMetadataTag(metadata: Record<string, unknown>, tag: string): void {\n const current = Array.isArray(metadata.tags)\n ? metadata.tags.filter((value): value is string => typeof value === 'string')\n : [];\n if (!current.includes(tag)) metadata.tags = [...current, tag];\n}\n\nfunction buildRepairResult(projectHash: string, dryRun: boolean): ProjectScopeRepairResult {\n return {\n dryRun,\n projectHash,\n scanned: 0,\n repaired: 0,\n quarantined: 0,\n alreadyScoped: 0,\n skipped: 0,\n samples: []\n };\n}\n\nfunction normalizeRepoName(value: string): string {\n return value.replace(/\\.git$/i, '').trim().toLowerCase();\n}\n\nfunction projectBasename(projectPath?: string): string | undefined {\n if (!projectPath) return undefined;\n const trimmed = projectPath.replace(/[\\\\/]+$/, '');\n const basename = nodePath.basename(trimmed);\n return basename ? normalizeRepoName(basename) : undefined;\n}\n\nfunction isProjectScopeRepairExplanation(content: string): boolean {\n const normalized = content.toLowerCase();\n const hasRepairContext = /project[- ]scope|mis[- ]scoped|quarantine|contamination|legacy|\uC624\uC5FC|\uACA9\uB9AC|repair/.test(normalized);\n const hasExplanationContext = /example|detector|trap|not a .*project task|\uAE30\uC5B5|\uBA54\uBAA8\uB9AC|\uC124\uBA85|\uC218\uC815|\uAC80\uC99D/.test(normalized);\n return hasRepairContext && hasExplanationContext;\n}\n\nfunction hasConflictingContentProjectHint(content: string, projectPath?: string): boolean {\n const currentName = projectBasename(projectPath);\n if (!currentName) return false;\n if (isProjectScopeRepairExplanation(content)) return false;\n\n const githubRepoPattern = /github\\.com[:/]([^/\\s`'\"#)]+)\\/([^/\\s`'\"#)]+)(?:\\.git)?/gi;\n let githubMatch: RegExpExecArray | null;\n while ((githubMatch = githubRepoPattern.exec(content)) !== null) {\n const repo = normalizeRepoName(githubMatch[2] || '');\n if (repo && repo !== currentName) return true;\n }\n\n const workspacePathPattern = /\\/workspace\\/([^/\\s`'\"#)]+)/gi;\n let workspaceMatch: RegExpExecArray | null;\n while ((workspaceMatch = workspacePathPattern.exec(content)) !== null) {\n const repo = normalizeRepoName(workspaceMatch[1] || '');\n if (repo && repo !== currentName) return true;\n }\n\n return false;\n}\n\nexport class SQLiteEventStore {\n private db: SQLiteDatabase;\n private initialized = false;\n private readonly readOnly: boolean;\n private readonly markdownMirror: MarkdownMirror | null;\n private readonly vectorOutbox: VectorOutbox | null;\n\n constructor(dbPath: string, options?: SQLiteEventStoreOptions) {\n this.readOnly = options?.readonly ?? false;\n this.db = createSQLiteDatabase(dbPath, {\n readonly: this.readOnly,\n snapshot: options?.snapshot,\n snapshotDirectory: options?.snapshotDirectory,\n canonicalMemoryRoot: options?.canonicalMemoryRoot,\n walMode: !this.readOnly\n });\n this.markdownMirror = this.readOnly || !options?.markdownMirrorRoot\n ? null\n : new MarkdownMirror(options.markdownMirrorRoot);\n this.vectorOutbox = this.createVectorOutbox(options?.vectorOutbox);\n }\n\n private createVectorOutbox(option: SQLiteEventStoreOptions['vectorOutbox']): VectorOutbox | null {\n if (this.readOnly || option === false) return null;\n if (option instanceof VectorOutbox) return option;\n return new VectorOutbox(this.db, option ?? {});\n }\n\n private enqueueVectorOutboxEventSync(eventId: string, eventType: string): void {\n if (!this.vectorOutbox) return;\n if (eventType === 'tool_observation') return;\n this.vectorOutbox.enqueueSync('event', eventId);\n }\n\n private async enqueueVectorOutboxEvent(eventId: string, eventType: string): Promise<void> {\n this.enqueueVectorOutboxEventSync(eventId, eventType);\n }\n\n /**\n * Initialize database schema\n */\n async initialize(): Promise<void> {\n if (this.initialized) return;\n\n // In read-only mode, skip schema creation\n if (this.readOnly) {\n this.initialized = true;\n return;\n }\n\n // Create all tables in a single exec for efficiency\n sqliteExec(this.db, `\n -- L0 EventStore: Single Source of Truth (immutable, append-only)\n CREATE TABLE IF NOT EXISTS events (\n id TEXT PRIMARY KEY,\n event_type TEXT NOT NULL,\n session_id TEXT NOT NULL,\n timestamp TEXT NOT NULL,\n content TEXT NOT NULL,\n canonical_key TEXT NOT NULL,\n dedupe_key TEXT UNIQUE,\n metadata TEXT,\n access_count INTEGER DEFAULT 0,\n last_accessed_at TEXT\n );\n\n -- Dedup table for idempotency\n CREATE TABLE IF NOT EXISTS event_dedup (\n dedupe_key TEXT PRIMARY KEY,\n event_id TEXT NOT NULL,\n created_at TEXT DEFAULT (datetime('now'))\n );\n\n -- Session metadata\n CREATE TABLE IF NOT EXISTS sessions (\n id TEXT PRIMARY KEY,\n started_at TEXT NOT NULL,\n ended_at TEXT,\n project_path TEXT,\n summary TEXT,\n tags TEXT\n );\n\n -- Insights (derived data, rebuildable)\n CREATE TABLE IF NOT EXISTS insights (\n id TEXT PRIMARY KEY,\n insight_type TEXT NOT NULL,\n content TEXT NOT NULL,\n canonical_key TEXT NOT NULL,\n confidence REAL,\n source_events TEXT,\n created_at TEXT,\n last_updated TEXT\n );\n\n -- Embedding Outbox (Single-Writer Pattern)\n CREATE TABLE IF NOT EXISTS embedding_outbox (\n id TEXT PRIMARY KEY,\n event_id TEXT NOT NULL,\n content TEXT NOT NULL,\n status TEXT DEFAULT 'pending',\n retry_count INTEGER DEFAULT 0,\n created_at TEXT DEFAULT (datetime('now')),\n processed_at TEXT,\n error_message TEXT\n );\n\n -- Projection offset tracking\n CREATE TABLE IF NOT EXISTS projection_offsets (\n projection_name TEXT PRIMARY KEY,\n last_event_id TEXT,\n last_timestamp TEXT,\n updated_at TEXT DEFAULT (datetime('now'))\n );\n\n -- Memory level tracking\n CREATE TABLE IF NOT EXISTS memory_levels (\n event_id TEXT PRIMARY KEY,\n level TEXT NOT NULL DEFAULT 'L0',\n promoted_at TEXT DEFAULT (datetime('now'))\n );\n\n -- Entries (immutable memory units)\n CREATE TABLE IF NOT EXISTS entries (\n entry_id TEXT PRIMARY KEY,\n created_ts TEXT NOT NULL,\n entry_type TEXT NOT NULL,\n title TEXT NOT NULL,\n content_json TEXT NOT NULL,\n stage TEXT NOT NULL DEFAULT 'raw',\n status TEXT DEFAULT 'active',\n superseded_by TEXT,\n build_id TEXT,\n evidence_json TEXT,\n canonical_key TEXT,\n created_at TEXT DEFAULT (datetime('now'))\n );\n\n -- Entities (task/condition/artifact)\n CREATE TABLE IF NOT EXISTS entities (\n entity_id TEXT PRIMARY KEY,\n entity_type TEXT NOT NULL,\n canonical_key TEXT NOT NULL,\n title TEXT NOT NULL,\n stage TEXT NOT NULL DEFAULT 'raw',\n status TEXT NOT NULL DEFAULT 'active',\n current_json TEXT NOT NULL,\n title_norm TEXT,\n search_text TEXT,\n created_at TEXT DEFAULT (datetime('now')),\n updated_at TEXT DEFAULT (datetime('now'))\n );\n\n -- Entity aliases for canonical key lookup\n CREATE TABLE IF NOT EXISTS entity_aliases (\n entity_type TEXT NOT NULL,\n canonical_key TEXT NOT NULL,\n entity_id TEXT NOT NULL,\n is_primary INTEGER DEFAULT 0,\n created_at TEXT DEFAULT (datetime('now')),\n PRIMARY KEY(entity_type, canonical_key)\n );\n\n -- Edges (relationships between entries/entities) -- current-state projection\n CREATE TABLE IF NOT EXISTS edges (\n edge_id TEXT PRIMARY KEY,\n src_type TEXT NOT NULL,\n src_id TEXT NOT NULL,\n rel_type TEXT NOT NULL,\n dst_type TEXT NOT NULL,\n dst_id TEXT NOT NULL,\n meta_json TEXT,\n created_at TEXT DEFAULT (datetime('now'))\n );\n\n -- Bitemporal edge history (Zep/Graphiti-inspired), see\n -- docs/graph-temporal-edge-spike.md. edges above stays the fast\n -- current-state projection; this table is the append-only source for\n -- asOf/knownAt queries and is never hard-deleted.\n CREATE TABLE IF NOT EXISTS edge_history (\n history_id TEXT PRIMARY KEY,\n edge_id TEXT NOT NULL,\n edge_key TEXT NOT NULL,\n src_type TEXT NOT NULL,\n src_id TEXT NOT NULL,\n rel_type TEXT NOT NULL,\n dst_type TEXT NOT NULL,\n dst_id TEXT NOT NULL,\n weight REAL NOT NULL DEFAULT 0.5,\n status TEXT NOT NULL DEFAULT 'active',\n valid_from TEXT,\n valid_to TEXT,\n committed_at TEXT NOT NULL DEFAULT (datetime('now')),\n superseded_by_history_id TEXT,\n source_event_ids_json TEXT NOT NULL DEFAULT '[]',\n evidence_json TEXT NOT NULL DEFAULT '{}',\n meta_json TEXT NOT NULL DEFAULT '{}'\n );\n\n CREATE INDEX IF NOT EXISTS idx_edge_history_key_commit\n ON edge_history(edge_key, committed_at DESC, history_id DESC);\n CREATE INDEX IF NOT EXISTS idx_edge_history_valid\n ON edge_history(edge_key, valid_from, valid_to);\n CREATE INDEX IF NOT EXISTS idx_edge_history_src\n ON edge_history(src_id, rel_type, committed_at DESC);\n CREATE INDEX IF NOT EXISTS idx_edge_history_dst\n ON edge_history(dst_id, rel_type, committed_at DESC);\n CREATE INDEX IF NOT EXISTS idx_edge_history_status\n ON edge_history(status);\n\n -- Vector Outbox V2 Table\n CREATE TABLE IF NOT EXISTS vector_outbox (\n job_id TEXT PRIMARY KEY,\n item_kind TEXT NOT NULL,\n item_id TEXT NOT NULL,\n embedding_version TEXT NOT NULL,\n status TEXT NOT NULL DEFAULT 'pending',\n retry_count INTEGER DEFAULT 0,\n error TEXT,\n created_at TEXT DEFAULT (datetime('now')),\n updated_at TEXT DEFAULT (datetime('now')),\n UNIQUE(item_kind, item_id, embedding_version)\n );\n\n -- Build Runs\n CREATE TABLE IF NOT EXISTS build_runs (\n build_id TEXT PRIMARY KEY,\n started_at TEXT NOT NULL,\n finished_at TEXT,\n extractor_model TEXT NOT NULL,\n extractor_prompt_hash TEXT NOT NULL,\n embedder_model TEXT NOT NULL,\n embedding_version TEXT NOT NULL,\n idris_version TEXT NOT NULL,\n schema_version TEXT NOT NULL,\n status TEXT NOT NULL DEFAULT 'running',\n error TEXT\n );\n\n -- Pipeline Metrics\n CREATE TABLE IF NOT EXISTS pipeline_metrics (\n id TEXT PRIMARY KEY,\n ts TEXT NOT NULL,\n stage TEXT NOT NULL,\n latency_ms REAL NOT NULL,\n success INTEGER NOT NULL,\n error TEXT,\n session_id TEXT\n );\n\n -- Working Set table (active memory window)\n CREATE TABLE IF NOT EXISTS working_set (\n id TEXT PRIMARY KEY,\n event_id TEXT NOT NULL,\n added_at TEXT DEFAULT (datetime('now')),\n relevance_score REAL DEFAULT 1.0,\n topics TEXT,\n expires_at TEXT\n );\n\n -- Consolidated Memories table (long-term integrated memories)\n CREATE TABLE IF NOT EXISTS consolidated_memories (\n memory_id TEXT PRIMARY KEY,\n summary TEXT NOT NULL,\n topics TEXT,\n source_events TEXT,\n confidence REAL DEFAULT 0.5,\n created_at TEXT DEFAULT (datetime('now')),\n accessed_at TEXT,\n access_count INTEGER DEFAULT 0\n );\n\n -- Junction: consolidated memory -> source event id (indexed lookup that\n -- replaces per-event source_events LIKE scans during consolidation).\n CREATE TABLE IF NOT EXISTS consolidated_memory_events (\n memory_id TEXT NOT NULL,\n event_id TEXT NOT NULL,\n PRIMARY KEY (memory_id, event_id)\n );\n CREATE INDEX IF NOT EXISTS idx_cme_event ON consolidated_memory_events(event_id);\n\n -- Continuity Log table (tracks context transitions)\n CREATE TABLE IF NOT EXISTS continuity_log (\n log_id TEXT PRIMARY KEY,\n from_context_id TEXT,\n to_context_id TEXT,\n continuity_score REAL,\n transition_type TEXT,\n created_at TEXT DEFAULT (datetime('now'))\n );\n\n -- Consolidated Rules table (long-term stable memory)\n CREATE TABLE IF NOT EXISTS consolidated_rules (\n rule_id TEXT PRIMARY KEY,\n rule TEXT NOT NULL,\n topics TEXT,\n source_memory_ids TEXT,\n source_events TEXT,\n confidence REAL DEFAULT 0.5,\n created_at TEXT DEFAULT (datetime('now'))\n );\n\n -- Endless Mode Config table\n CREATE TABLE IF NOT EXISTS endless_config (\n key TEXT PRIMARY KEY,\n value TEXT,\n updated_at TEXT DEFAULT (datetime('now'))\n );\n\n -- Memory Helpfulness tracking\n CREATE TABLE IF NOT EXISTS memory_helpfulness (\n id TEXT PRIMARY KEY,\n event_id TEXT NOT NULL,\n session_id TEXT NOT NULL,\n retrieval_score REAL DEFAULT 0,\n query_preview TEXT,\n session_continued INTEGER DEFAULT 0,\n prompt_count_after INTEGER DEFAULT 0,\n tool_success_count INTEGER DEFAULT 0,\n tool_total_count INTEGER DEFAULT 0,\n was_reasked INTEGER DEFAULT 0,\n helpfulness_score REAL DEFAULT 0.5,\n memory_kind TEXT NOT NULL DEFAULT 'unknown',\n memory_project_id TEXT,\n delivery_status TEXT NOT NULL DEFAULT 'unknown',\n delivery_evidence TEXT NOT NULL DEFAULT 'none',\n delivered_at TEXT,\n presentation_mode TEXT NOT NULL DEFAULT 'unknown',\n trigger_type TEXT NOT NULL DEFAULT 'unknown',\n delivery_client TEXT NOT NULL DEFAULT 'unknown',\n created_at TEXT DEFAULT (datetime('now')),\n measured_at TEXT\n );\n\n -- Additive, versioned usefulness funnel. Raw dimensions stay separate;\n -- no unknown value is coerced to neutral or zero.\n CREATE TABLE IF NOT EXISTS memory_usefulness_observations_v2 (\n trace_id TEXT NOT NULL,\n event_id TEXT NOT NULL,\n observation_kind TEXT NOT NULL DEFAULT 'outcome',\n evaluator_version TEXT NOT NULL,\n presentation_mode TEXT NOT NULL,\n trigger_type TEXT NOT NULL,\n selected INTEGER NOT NULL,\n delivered INTEGER,\n adoption TEXT NOT NULL,\n content_overlap_score REAL,\n task_outcome TEXT NOT NULL,\n reask_outcome TEXT NOT NULL,\n explicit_feedback TEXT,\n confidence REAL NOT NULL,\n evaluated_at TEXT,\n memory_kind TEXT NOT NULL DEFAULT 'unknown',\n delivery_status TEXT NOT NULL DEFAULT 'unknown',\n delivery_evidence TEXT NOT NULL DEFAULT 'none',\n evaluation_window_ms INTEGER,\n evaluation_cutoff TEXT,\n -- Raw memory id and owning project. The event_id column holds a\n -- kind-qualified key for non-event memories (see usefulnessRowKey) so\n -- the primary key below cannot collapse a lesson onto an event that\n -- happens to share its id.\n memory_id TEXT,\n memory_project_id TEXT,\n PRIMARY KEY(trace_id, event_id, observation_kind, evaluator_version)\n );\n CREATE INDEX IF NOT EXISTS idx_usefulness_v2_evaluator_trigger\n ON memory_usefulness_observations_v2(evaluator_version, trigger_type, evaluated_at DESC);\n\n -- Retrieval trace log (query -> candidates -> selected for context)\n CREATE TABLE IF NOT EXISTS retrieval_traces (\n trace_id TEXT PRIMARY KEY,\n session_id TEXT,\n project_hash TEXT,\n query_text TEXT NOT NULL,\n raw_query_text TEXT,\n query_rewrite_kind TEXT,\n strategy TEXT,\n candidate_event_ids TEXT,\n selected_event_ids TEXT,\n candidate_details_json TEXT,\n selected_details_json TEXT,\n candidate_count INTEGER DEFAULT 0,\n selected_count INTEGER DEFAULT 0,\n confidence TEXT,\n fallback_trace TEXT,\n presentation_mode TEXT NOT NULL DEFAULT 'unknown',\n trigger_type TEXT NOT NULL DEFAULT 'unknown',\n delivery_client TEXT NOT NULL DEFAULT 'unknown',\n outcome_reason TEXT NOT NULL DEFAULT 'unknown',\n retrieval_diagnostics_json TEXT,\n request_id TEXT,\n evaluation_run_id TEXT,\n runtime_version TEXT,\n telemetry_schema_version INTEGER NOT NULL DEFAULT 0,\n created_at TEXT DEFAULT (datetime('now'))\n );\n\n -- Typed references for each trace (specs R1). The legacy id arrays above\n -- stay for old readers; these rows keep the memory kind so lessons are\n -- never mistaken for events.\n CREATE TABLE IF NOT EXISTS retrieval_trace_items (\n trace_id TEXT NOT NULL,\n item_key TEXT NOT NULL,\n memory_kind TEXT NOT NULL,\n memory_id TEXT NOT NULL,\n project_id TEXT,\n rank INTEGER,\n selected INTEGER NOT NULL DEFAULT 0,\n score REAL,\n content_hash TEXT,\n memory_version TEXT,\n deleted INTEGER NOT NULL DEFAULT 0,\n created_at TEXT DEFAULT (datetime('now')),\n PRIMARY KEY (trace_id, item_key)\n );\n\n -- Privacy-safe reference navigation. Target and trace identifiers are\n -- stored without copying source or transcript content.\n CREATE TABLE IF NOT EXISTS retrieval_navigation_events (\n navigation_id TEXT PRIMARY KEY,\n target_event_id TEXT NOT NULL,\n trace_id TEXT,\n delivery_session_id TEXT,\n presentation_mode TEXT NOT NULL DEFAULT 'reference',\n trigger_type TEXT NOT NULL DEFAULT 'unknown',\n memory_kind TEXT NOT NULL DEFAULT 'event',\n navigation_action TEXT NOT NULL,\n navigation_client TEXT NOT NULL DEFAULT 'unknown',\n attribution_outcome TEXT NOT NULL,\n attribution_reason TEXT NOT NULL,\n open_count INTEGER NOT NULL DEFAULT 1,\n first_opened_at TEXT NOT NULL,\n last_opened_at TEXT NOT NULL\n );\n\n -- Sync position tracking (for SQLite -> DuckDB sync)\n CREATE TABLE IF NOT EXISTS sync_positions (\n target_name TEXT PRIMARY KEY,\n last_event_id TEXT,\n last_timestamp TEXT,\n updated_at TEXT DEFAULT (datetime('now'))\n );\n\n -- Memory Operations: facet assignments (derived, rebuildable projection)\n CREATE TABLE IF NOT EXISTS memory_facets (\n id TEXT PRIMARY KEY,\n target_type TEXT NOT NULL,\n target_id TEXT NOT NULL,\n dimension TEXT NOT NULL,\n value TEXT NOT NULL,\n confidence REAL NOT NULL DEFAULT 1.0,\n source TEXT NOT NULL DEFAULT 'manual',\n evidence_event_ids TEXT NOT NULL DEFAULT '[]',\n project_hash TEXT NOT NULL DEFAULT '',\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n UNIQUE(target_type, target_id, dimension, value, source, project_hash)\n );\n\n -- Memory Operations: operational action projection\n CREATE TABLE IF NOT EXISTS memory_actions (\n action_id TEXT PRIMARY KEY,\n project_hash TEXT NOT NULL,\n title TEXT NOT NULL,\n status TEXT NOT NULL DEFAULT 'pending',\n priority INTEGER NOT NULL DEFAULT 0,\n source_event_ids TEXT NOT NULL DEFAULT '[]',\n related_entity_ids TEXT NOT NULL DEFAULT '[]',\n current_checkpoint_id TEXT,\n lease_id TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL\n );\n\n -- Memory Operations: action dependency/reference edges\n CREATE TABLE IF NOT EXISTS memory_action_edges (\n edge_id TEXT PRIMARY KEY,\n src_action_id TEXT NOT NULL,\n rel_type TEXT NOT NULL,\n dst_type TEXT NOT NULL,\n dst_id TEXT NOT NULL,\n confidence REAL NOT NULL DEFAULT 1.0,\n source TEXT NOT NULL DEFAULT 'manual',\n created_at TEXT NOT NULL,\n UNIQUE(src_action_id, rel_type, dst_type, dst_id, source)\n );\n\n -- Memory Operations: short-lived leases for operational work\n CREATE TABLE IF NOT EXISTS memory_leases (\n lease_id TEXT PRIMARY KEY,\n target_type TEXT NOT NULL,\n target_id TEXT NOT NULL,\n holder TEXT NOT NULL,\n expires_at TEXT NOT NULL,\n metadata_json TEXT,\n created_at TEXT NOT NULL,\n renewed_at TEXT,\n released_at TEXT\n );\n\n -- Memory Operations: resumable checkpoints for delegated or long-running work\n CREATE TABLE IF NOT EXISTS memory_checkpoints (\n checkpoint_id TEXT PRIMARY KEY,\n project_hash TEXT NOT NULL,\n action_id TEXT,\n session_id TEXT,\n title TEXT NOT NULL,\n summary TEXT NOT NULL,\n state_json TEXT NOT NULL,\n source_event_ids TEXT NOT NULL DEFAULT '[]',\n created_at TEXT NOT NULL,\n expires_at TEXT\n );\n\n -- Memory Operations: retention lifecycle score projection\n CREATE TABLE IF NOT EXISTS memory_retention_scores (\n score_id TEXT PRIMARY KEY,\n target_type TEXT NOT NULL,\n target_id TEXT NOT NULL,\n project_hash TEXT NOT NULL,\n policy_version TEXT NOT NULL,\n decision TEXT NOT NULL,\n lifecycle_score REAL NOT NULL,\n factors_json TEXT NOT NULL,\n reasons_json TEXT NOT NULL,\n dry_run_diff_json TEXT NOT NULL,\n source_event_ids TEXT NOT NULL DEFAULT '[]',\n evaluated_at TEXT NOT NULL,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n UNIQUE(target_type, target_id, project_hash, policy_version)\n );\n\n -- Memory Operations: procedural lessons derived from successful workflows\n CREATE TABLE IF NOT EXISTS memory_lessons (\n lesson_id TEXT PRIMARY KEY,\n project_hash TEXT NOT NULL DEFAULT '',\n name TEXT NOT NULL,\n trigger TEXT NOT NULL,\n steps_json TEXT NOT NULL,\n confidence REAL NOT NULL,\n source_session_ids TEXT NOT NULL DEFAULT '[]',\n source_event_ids TEXT NOT NULL DEFAULT '[]',\n failure_modes_json TEXT NOT NULL DEFAULT '[]',\n skill_candidate INTEGER NOT NULL DEFAULT 0,\n source_class TEXT NOT NULL DEFAULT 'derived',\n access_count INTEGER NOT NULL DEFAULT 0,\n last_accessed_at TEXT,\n revision INTEGER NOT NULL DEFAULT 1,\n recall_enabled INTEGER NOT NULL DEFAULT 1,\n scope TEXT,\n validation_json TEXT NOT NULL DEFAULT '[]',\n reconsider_when TEXT,\n valid_versions_json TEXT NOT NULL DEFAULT '[]',\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n UNIQUE(project_hash, name)\n );\n\n -- Authenticated host review queue. Candidate payloads are held apart\n -- from recallable lessons until an authenticated UI action accepts them.\n CREATE TABLE IF NOT EXISTS lesson_review_candidates (\n candidate_id TEXT PRIMARY KEY,\n project_hash TEXT NOT NULL,\n evidence_key TEXT NOT NULL,\n payload_hash TEXT NOT NULL,\n payload_json TEXT NOT NULL,\n evidence_refs_json TEXT NOT NULL,\n duplicate_lesson_ids_json TEXT NOT NULL DEFAULT '[]',\n status TEXT NOT NULL,\n revision INTEGER NOT NULL DEFAULT 1,\n generation INTEGER NOT NULL,\n expires_at TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n UNIQUE(project_hash, evidence_key)\n );\n CREATE INDEX IF NOT EXISTS idx_lesson_review_candidates_scope_status\n ON lesson_review_candidates(project_hash, status, updated_at DESC);\n\n -- Privacy-safe lifecycle trace: ids/outcomes only; never raw query,\n -- lesson body, evidence, or provider input.\n CREATE TABLE IF NOT EXISTS lesson_host_traces (\n trace_id TEXT PRIMARY KEY,\n project_hash TEXT NOT NULL,\n session_id TEXT NOT NULL,\n actor_id TEXT NOT NULL,\n machine_id TEXT NOT NULL,\n generation INTEGER NOT NULL,\n turn_id TEXT,\n request_id TEXT NOT NULL,\n phase TEXT NOT NULL,\n outcome TEXT NOT NULL,\n lesson_ids_json TEXT NOT NULL,\n lesson_revisions_json TEXT NOT NULL DEFAULT '[]',\n query_text TEXT,\n created_at TEXT NOT NULL\n );\n CREATE UNIQUE INDEX IF NOT EXISTS idx_lesson_host_trace_request\n ON lesson_host_traces(project_hash, actor_id, request_id, phase);\n\n CREATE TABLE IF NOT EXISTS lesson_host_idempotency (\n project_hash TEXT NOT NULL,\n actor_id TEXT NOT NULL,\n request_id TEXT NOT NULL,\n operation TEXT NOT NULL,\n fingerprint TEXT NOT NULL,\n result_json TEXT NOT NULL,\n created_at TEXT NOT NULL,\n PRIMARY KEY(project_hash, actor_id, request_id, operation)\n );\n\n -- Perspective Memory: privacy-safe actors/peers\n CREATE TABLE IF NOT EXISTS memory_actors (\n actor_id TEXT PRIMARY KEY,\n project_hash TEXT NOT NULL DEFAULT '',\n kind TEXT NOT NULL,\n display_name TEXT NOT NULL,\n source TEXT NOT NULL,\n metadata_json TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL\n );\n\n -- Perspective Memory: actors participating in a session and observation policy\n CREATE TABLE IF NOT EXISTS session_actors (\n project_hash TEXT NOT NULL DEFAULT '',\n session_id TEXT NOT NULL,\n actor_id TEXT NOT NULL,\n role_in_session TEXT NOT NULL,\n observe_self INTEGER NOT NULL DEFAULT 1,\n observe_others INTEGER NOT NULL DEFAULT 0,\n joined_at TEXT NOT NULL,\n left_at TEXT,\n metadata_json TEXT,\n PRIMARY KEY(project_hash, session_id, actor_id)\n );\n\n -- Perspective Memory: compact Honcho-style actor cards\n CREATE TABLE IF NOT EXISTS actor_cards (\n card_id TEXT PRIMARY KEY,\n project_hash TEXT NOT NULL DEFAULT '',\n observer_actor_id TEXT NOT NULL,\n observed_actor_id TEXT NOT NULL,\n entries_json TEXT NOT NULL,\n source_event_ids_json TEXT NOT NULL DEFAULT '[]',\n updated_by TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n UNIQUE(project_hash, observer_actor_id, observed_actor_id)\n );\n\n -- Core memory blocks: small, always-injected, agent-editable per-project\n -- resident context (Letta-style core memory), distinct from actor_cards'\n -- per-observer-pair perspective model.\n CREATE TABLE IF NOT EXISTS core_memory_blocks (\n project_hash TEXT NOT NULL DEFAULT '',\n block_key TEXT NOT NULL,\n content TEXT NOT NULL DEFAULT '',\n source_event_ids_json TEXT NOT NULL DEFAULT '[]',\n updated_by TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n PRIMARY KEY(project_hash, block_key)\n );\n\n -- Perspective Memory: observer -> observed claims with evidence pointers\n CREATE TABLE IF NOT EXISTS perspective_observations (\n observation_id TEXT PRIMARY KEY,\n project_hash TEXT NOT NULL DEFAULT '',\n observer_actor_id TEXT NOT NULL,\n observed_actor_id TEXT NOT NULL,\n session_id TEXT,\n level TEXT NOT NULL,\n content TEXT NOT NULL,\n confidence REAL NOT NULL,\n source_event_ids_json TEXT NOT NULL DEFAULT '[]',\n source_observation_ids_json TEXT NOT NULL DEFAULT '[]',\n created_by TEXT NOT NULL,\n metadata_json TEXT,\n content_hash TEXT NOT NULL,\n source_hash TEXT NOT NULL,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n deleted_at TEXT,\n UNIQUE(project_hash, observer_actor_id, observed_actor_id, level, content_hash, source_hash)\n );\n\n -- Memory Assets: project-scoped registry and minimal actor permissions.\n -- Asset content remains in its canonical subsystem; this table owns only\n -- lifecycle, provenance, and access-control metadata.\n CREATE TABLE IF NOT EXISTS memory_assets (\n asset_id TEXT NOT NULL,\n project_hash TEXT NOT NULL DEFAULT '',\n asset_type TEXT NOT NULL,\n title TEXT NOT NULL,\n owner_actor_id TEXT NOT NULL,\n version INTEGER NOT NULL DEFAULT 1,\n status TEXT NOT NULL DEFAULT 'active',\n visibility TEXT NOT NULL DEFAULT 'private',\n source_refs_json TEXT NOT NULL DEFAULT '[]',\n metadata_json TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n PRIMARY KEY(project_hash, asset_id)\n );\n\n -- An enabled binding makes a private asset readable/injectable for one\n -- actor. It does not grant write, bind, or delegation authority.\n CREATE TABLE IF NOT EXISTS memory_asset_bindings (\n project_hash TEXT NOT NULL DEFAULT '',\n asset_id TEXT NOT NULL,\n actor_id TEXT NOT NULL,\n injection_mode TEXT NOT NULL DEFAULT 'reference',\n priority INTEGER NOT NULL DEFAULT 0,\n enabled INTEGER NOT NULL DEFAULT 1,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n PRIMARY KEY(project_hash, asset_id, actor_id),\n FOREIGN KEY(project_hash, asset_id) REFERENCES memory_assets(project_hash, asset_id) ON DELETE CASCADE\n );\n\n -- Explicit grants are full replacements per asset/actor. An empty JSON\n -- permission list is therefore an auditable revocation tombstone.\n CREATE TABLE IF NOT EXISTS memory_asset_grants (\n project_hash TEXT NOT NULL DEFAULT '',\n asset_id TEXT NOT NULL,\n actor_id TEXT NOT NULL,\n permissions_json TEXT NOT NULL DEFAULT '[]',\n created_by TEXT NOT NULL,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n PRIMARY KEY(project_hash, asset_id, actor_id),\n FOREIGN KEY(project_hash, asset_id) REFERENCES memory_assets(project_hash, asset_id) ON DELETE CASCADE\n );\n\n -- Perspective Memory: FTS5 index for observation content queries.\n -- Use an external-content FTS table so the searchable projection stores the index,\n -- not a second raw copy of private observation text.\n CREATE VIRTUAL TABLE IF NOT EXISTS perspective_observations_fts USING fts5(\n content,\n observation_id UNINDEXED,\n content='perspective_observations',\n content_rowid='rowid',\n tokenize='porter unicode61'\n );\n\n -- Backfill the FTS table for writable legacy stores that predate the FTS projection.\n INSERT OR IGNORE INTO perspective_observations_fts(rowid, content, observation_id)\n SELECT rowid, content, observation_id FROM perspective_observations;\n\n CREATE TRIGGER IF NOT EXISTS perspective_observations_fts_insert AFTER INSERT ON perspective_observations BEGIN\n INSERT INTO perspective_observations_fts(rowid, content, observation_id) VALUES (NEW.rowid, NEW.content, NEW.observation_id);\n END;\n\n CREATE TRIGGER IF NOT EXISTS perspective_observations_fts_delete AFTER DELETE ON perspective_observations BEGIN\n INSERT INTO perspective_observations_fts(perspective_observations_fts, rowid, content, observation_id) VALUES('delete', OLD.rowid, OLD.content, OLD.observation_id);\n END;\n\n CREATE TRIGGER IF NOT EXISTS perspective_observations_fts_update AFTER UPDATE ON perspective_observations BEGIN\n INSERT INTO perspective_observations_fts(perspective_observations_fts, rowid, content, observation_id) VALUES('delete', OLD.rowid, OLD.content, OLD.observation_id);\n INSERT INTO perspective_observations_fts(rowid, content, observation_id) VALUES (NEW.rowid, NEW.content, NEW.observation_id);\n END;\n\n -- Memory Operations: governance/audit trail for state-changing operations\n CREATE TABLE IF NOT EXISTS memory_governance_audit (\n audit_id TEXT PRIMARY KEY,\n operation TEXT NOT NULL,\n actor TEXT NOT NULL,\n project_hash TEXT,\n target_type TEXT NOT NULL,\n target_id TEXT NOT NULL,\n before_json TEXT,\n after_json TEXT,\n source_event_ids TEXT NOT NULL DEFAULT '[]',\n created_at TEXT NOT NULL\n );\n\n -- Create indexes\n CREATE INDEX IF NOT EXISTS idx_events_session ON events(session_id);\n CREATE INDEX IF NOT EXISTS idx_events_timestamp ON events(timestamp);\n -- Serves getRecentEvents' event_type filter. Without it SQLite walks\n -- idx_events_timestamp backwards and evaluates the quarantine predicate\n -- on every visited row; a store holding fewer matching events than the\n -- limit then degrades into a full table scan on the SessionStart path.\n CREATE INDEX IF NOT EXISTS idx_events_type_timestamp ON events(event_type, timestamp);\n CREATE INDEX IF NOT EXISTS idx_entries_type ON entries(entry_type);\n CREATE INDEX IF NOT EXISTS idx_entries_stage ON entries(stage);\n CREATE INDEX IF NOT EXISTS idx_entries_canonical ON entries(canonical_key);\n CREATE INDEX IF NOT EXISTS idx_entities_type_key ON entities(entity_type, canonical_key);\n CREATE INDEX IF NOT EXISTS idx_entities_status ON entities(status);\n CREATE INDEX IF NOT EXISTS idx_edges_src ON edges(src_id, rel_type);\n CREATE INDEX IF NOT EXISTS idx_edges_dst ON edges(dst_id, rel_type);\n CREATE INDEX IF NOT EXISTS idx_edges_rel ON edges(rel_type);\n -- codify-lite session-file lane (Retriever.expandSessionFileLinks) filters\n -- touched_in edges by meta_json.sessionId on every retrieval; without this\n -- expression index the cost grows with total touched_in edge count.\n CREATE INDEX IF NOT EXISTS idx_edges_touched_in_session\n ON edges(json_extract(meta_json, '$.sessionId'))\n WHERE rel_type = 'touched_in';\n CREATE INDEX IF NOT EXISTS idx_outbox_status ON vector_outbox(status);\n CREATE INDEX IF NOT EXISTS idx_outbox_created ON vector_outbox(created_at);\n CREATE INDEX IF NOT EXISTS idx_working_set_expires ON working_set(expires_at);\n CREATE INDEX IF NOT EXISTS idx_working_set_relevance ON working_set(relevance_score);\n CREATE INDEX IF NOT EXISTS idx_consolidated_confidence ON consolidated_memories(confidence);\n CREATE INDEX IF NOT EXISTS idx_continuity_created ON continuity_log(created_at);\n CREATE INDEX IF NOT EXISTS idx_consolidated_rules_confidence ON consolidated_rules(confidence);\n CREATE INDEX IF NOT EXISTS idx_embedding_outbox_status ON embedding_outbox(status);\n CREATE INDEX IF NOT EXISTS idx_helpfulness_event ON memory_helpfulness(event_id);\n CREATE INDEX IF NOT EXISTS idx_helpfulness_session ON memory_helpfulness(session_id);\n CREATE INDEX IF NOT EXISTS idx_helpfulness_score ON memory_helpfulness(helpfulness_score DESC);\n CREATE INDEX IF NOT EXISTS idx_helpfulness_created_at ON memory_helpfulness(created_at);\n CREATE INDEX IF NOT EXISTS idx_helpfulness_measured_at ON memory_helpfulness(measured_at);\n CREATE INDEX IF NOT EXISTS idx_retrieval_traces_created_at ON retrieval_traces(created_at DESC);\n CREATE INDEX IF NOT EXISTS idx_retrieval_traces_project_hash ON retrieval_traces(project_hash);\n CREATE INDEX IF NOT EXISTS idx_retrieval_traces_session_id ON retrieval_traces(session_id);\n\n CREATE INDEX IF NOT EXISTS idx_retrieval_navigation_trace ON retrieval_navigation_events(trace_id);\n CREATE INDEX IF NOT EXISTS idx_retrieval_navigation_target_time ON retrieval_navigation_events(target_event_id, last_opened_at DESC);\n CREATE INDEX IF NOT EXISTS idx_memory_facets_project_dimension_value ON memory_facets(project_hash, dimension, value);\n CREATE INDEX IF NOT EXISTS idx_memory_facets_target ON memory_facets(target_type, target_id);\n CREATE INDEX IF NOT EXISTS idx_memory_facets_dimension_value_confidence ON memory_facets(dimension, value, confidence DESC);\n CREATE INDEX IF NOT EXISTS idx_memory_actions_project_status_priority ON memory_actions(project_hash, status, priority DESC, updated_at DESC);\n CREATE INDEX IF NOT EXISTS idx_memory_action_edges_src ON memory_action_edges(src_action_id, rel_type);\n CREATE INDEX IF NOT EXISTS idx_memory_action_edges_dst ON memory_action_edges(dst_type, dst_id);\n CREATE INDEX IF NOT EXISTS idx_memory_leases_target_expires ON memory_leases(target_type, target_id, expires_at);\n CREATE INDEX IF NOT EXISTS idx_memory_checkpoints_project_action_created ON memory_checkpoints(project_hash, action_id, created_at DESC);\n CREATE INDEX IF NOT EXISTS idx_memory_checkpoints_project_session_created ON memory_checkpoints(project_hash, session_id, created_at DESC);\n CREATE INDEX IF NOT EXISTS idx_memory_retention_scores_project_decision_score ON memory_retention_scores(project_hash, decision, lifecycle_score ASC, evaluated_at DESC);\n CREATE INDEX IF NOT EXISTS idx_memory_retention_scores_target ON memory_retention_scores(target_type, target_id, project_hash);\n CREATE INDEX IF NOT EXISTS idx_memory_retention_scores_policy_evaluated ON memory_retention_scores(policy_version, evaluated_at DESC);\n CREATE INDEX IF NOT EXISTS idx_memory_lessons_project_confidence ON memory_lessons(project_hash, confidence DESC, updated_at DESC);\n CREATE INDEX IF NOT EXISTS idx_memory_lessons_skill_candidate ON memory_lessons(project_hash, skill_candidate, confidence DESC);\n CREATE INDEX IF NOT EXISTS idx_memory_lessons_updated ON memory_lessons(updated_at DESC);\n CREATE INDEX IF NOT EXISTS idx_memory_actors_project_kind ON memory_actors(project_hash, kind, updated_at DESC);\n CREATE INDEX IF NOT EXISTS idx_memory_actors_source ON memory_actors(source, kind);\n CREATE INDEX IF NOT EXISTS idx_session_actors_session ON session_actors(project_hash, session_id, role_in_session);\n CREATE INDEX IF NOT EXISTS idx_session_actors_actor ON session_actors(actor_id, project_hash, session_id);\n CREATE INDEX IF NOT EXISTS idx_actor_cards_perspective ON actor_cards(project_hash, observer_actor_id, observed_actor_id);\n CREATE INDEX IF NOT EXISTS idx_actor_cards_updated ON actor_cards(updated_at DESC);\n CREATE INDEX IF NOT EXISTS idx_perspective_observations_perspective_level ON perspective_observations(project_hash, observer_actor_id, observed_actor_id, level, confidence DESC, updated_at DESC);\n CREATE INDEX IF NOT EXISTS idx_perspective_observations_session ON perspective_observations(project_hash, session_id, level, updated_at DESC);\n CREATE INDEX IF NOT EXISTS idx_perspective_observations_source_hash ON perspective_observations(project_hash, source_hash);\n CREATE INDEX IF NOT EXISTS idx_perspective_observations_deleted ON perspective_observations(deleted_at);\n CREATE INDEX IF NOT EXISTS idx_memory_assets_project_status ON memory_assets(project_hash, status, updated_at DESC);\n CREATE INDEX IF NOT EXISTS idx_memory_assets_owner ON memory_assets(project_hash, owner_actor_id, updated_at DESC);\n CREATE INDEX IF NOT EXISTS idx_memory_asset_bindings_actor ON memory_asset_bindings(project_hash, actor_id, enabled, priority DESC);\n CREATE INDEX IF NOT EXISTS idx_memory_asset_grants_actor ON memory_asset_grants(project_hash, actor_id, updated_at DESC);\n CREATE INDEX IF NOT EXISTS idx_memory_governance_audit_project_operation ON memory_governance_audit(project_hash, operation, created_at DESC);\n CREATE INDEX IF NOT EXISTS idx_memory_governance_audit_target ON memory_governance_audit(target_type, target_id, created_at DESC);\n\n -- FTS5 Full-Text Search for fast keyword search\n CREATE VIRTUAL TABLE IF NOT EXISTS events_fts USING fts5(\n content,\n event_id UNINDEXED,\n tokenize='porter unicode61'\n );\n\n -- Triggers to keep FTS in sync with events table\n CREATE TRIGGER IF NOT EXISTS events_fts_insert AFTER INSERT ON events BEGIN\n INSERT INTO events_fts(rowid, content, event_id) VALUES (NEW.rowid, NEW.content, NEW.id);\n END;\n\n CREATE TRIGGER IF NOT EXISTS events_fts_delete AFTER DELETE ON events BEGIN\n DELETE FROM events_fts WHERE rowid = OLD.rowid;\n END;\n\n CREATE TRIGGER IF NOT EXISTS events_fts_update AFTER UPDATE ON events BEGIN\n DELETE FROM events_fts WHERE rowid = OLD.rowid;\n INSERT INTO events_fts(rowid, content, event_id) VALUES (NEW.rowid, NEW.content, NEW.id);\n END;\n\n -- Reverse index for citation ids (a non-reversible hash of event id), so\n -- citation lookups are O(1) instead of scanning recent events and hashing\n -- each one. Populated lazily/self-healing by getEventByCitationId.\n CREATE TABLE IF NOT EXISTS event_citations (\n event_id TEXT PRIMARY KEY,\n citation_id TEXT NOT NULL\n );\n CREATE INDEX IF NOT EXISTS idx_event_citations_citation ON event_citations(citation_id);\n `);\n\n\n // Best-effort forward migration for action edge source ownership\n this.addColumnIfMissing('memory_action_edges', 'source', `TEXT NOT NULL DEFAULT 'manual'`);\n try {\n const edgeIndexes = sqliteAll<{ name: string; unique: number }>(this.db, `PRAGMA index_list(memory_action_edges)`, []);\n const hasSourceAwareUnique = edgeIndexes.some((index) => {\n if (Number(index.unique) !== 1) return false;\n if (!/^[A-Za-z0-9_]+$/.test(index.name)) return false;\n const escapedName = index.name.replace(/\"/g, '\"\"');\n const columns = sqliteAll<{ name: string }>(this.db, 'PRAGMA index_info(\"' + escapedName + '\")', [])\n .map((column) => column.name);\n return columns.length === 5\n && columns[0] === 'src_action_id'\n && columns[1] === 'rel_type'\n && columns[2] === 'dst_type'\n && columns[3] === 'dst_id'\n && columns[4] === 'source';\n });\n if (!hasSourceAwareUnique) {\n sqliteExec(this.db, `\n DROP TABLE IF EXISTS memory_action_edges_v2;\n CREATE TABLE memory_action_edges_v2 (\n edge_id TEXT PRIMARY KEY,\n src_action_id TEXT NOT NULL,\n rel_type TEXT NOT NULL,\n dst_type TEXT NOT NULL,\n dst_id TEXT NOT NULL,\n confidence REAL NOT NULL DEFAULT 1.0,\n source TEXT NOT NULL DEFAULT 'manual',\n created_at TEXT NOT NULL,\n UNIQUE(src_action_id, rel_type, dst_type, dst_id, source)\n );\n INSERT OR IGNORE INTO memory_action_edges_v2 (\n edge_id, src_action_id, rel_type, dst_type, dst_id, confidence, source, created_at\n )\n SELECT edge_id, src_action_id, rel_type, dst_type, dst_id, confidence, source, created_at\n FROM memory_action_edges;\n DROP TABLE memory_action_edges;\n ALTER TABLE memory_action_edges_v2 RENAME TO memory_action_edges;\n CREATE INDEX IF NOT EXISTS idx_memory_action_edges_src ON memory_action_edges(src_action_id, rel_type);\n CREATE INDEX IF NOT EXISTS idx_memory_action_edges_dst ON memory_action_edges(dst_type, dst_id);\n `);\n }\n } catch {\n // action edge table may not exist in partial migrations\n }\n\n // Best-effort forward migration for helpfulness evidence columns:\n // trace_id links each injected memory back to its retrieval_traces row\n // (question -> memory), content grounding measures whether later\n // assistant responses actually reused the memory's content.\n this.addColumnIfMissing('memory_helpfulness', 'trace_id', 'TEXT');\n this.addColumnIfMissing('memory_helpfulness', 'source', `TEXT DEFAULT 'user_prompt'`);\n this.addColumnIfMissing('memory_helpfulness', 'content_overlap_score', 'REAL');\n this.addColumnIfMissing('memory_helpfulness', 'evidence_json', 'TEXT');\n this.addColumnIfMissing('memory_helpfulness', 'injected_content', 'TEXT');\n this.addColumnIfMissing('memory_helpfulness', 'presentation_mode', `TEXT NOT NULL DEFAULT 'unknown'`);\n this.addColumnIfMissing('memory_helpfulness', 'trigger_type', `TEXT NOT NULL DEFAULT 'unknown'`);\n this.addColumnIfMissing('memory_helpfulness', 'delivery_client', `TEXT NOT NULL DEFAULT 'unknown'`);\n try {\n sqliteExec(this.db, `CREATE INDEX IF NOT EXISTS idx_helpfulness_trace ON memory_helpfulness(trace_id);`);\n } catch {\n // index/table may not exist in partial migrations\n }\n\n // Best-effort forward migration for retrieval trace detail columns\n this.addColumnIfMissing('retrieval_traces', 'selected_details_json', 'TEXT');\n this.addColumnIfMissing('retrieval_traces', 'candidate_details_json', 'TEXT');\n this.addColumnIfMissing('retrieval_traces', 'raw_query_text', 'TEXT');\n this.addColumnIfMissing('retrieval_traces', 'query_rewrite_kind', 'TEXT');\n this.addColumnIfMissing('retrieval_traces', 'presentation_mode', `TEXT NOT NULL DEFAULT 'unknown'`);\n this.addColumnIfMissing('retrieval_traces', 'trigger_type', `TEXT NOT NULL DEFAULT 'unknown'`);\n this.addColumnIfMissing('retrieval_traces', 'delivery_client', `TEXT NOT NULL DEFAULT 'unknown'`);\n // Legacy stores keep 'runtime_error' as the column default so their\n // existing rows are unchanged; readers present those as\n // `legacy_unclassified` instead of re-classifying them (specs R2).\n this.addColumnIfMissing('retrieval_traces', 'outcome_reason', `TEXT NOT NULL DEFAULT 'runtime_error'`);\n this.addColumnIfMissing('retrieval_traces', 'retrieval_diagnostics_json', 'TEXT');\n this.addColumnIfMissing('retrieval_traces', 'request_id', 'TEXT');\n this.addColumnIfMissing('retrieval_traces', 'evaluation_run_id', 'TEXT');\n this.addColumnIfMissing('retrieval_traces', 'runtime_version', 'TEXT');\n this.addColumnIfMissing('retrieval_traces', 'telemetry_schema_version', 'INTEGER NOT NULL DEFAULT 0');\n this.addColumnIfMissing('memory_helpfulness', 'memory_kind', `TEXT NOT NULL DEFAULT 'unknown'`);\n this.addColumnIfMissing('retrieval_navigation_events', 'memory_kind', `TEXT NOT NULL DEFAULT 'event'`);\n this.addColumnIfMissing('retrieval_navigation_events', 'memory_project_id', 'TEXT');\n this.addColumnIfMissing('memory_helpfulness', 'delivery_status', `TEXT NOT NULL DEFAULT 'unknown'`);\n this.addColumnIfMissing('memory_helpfulness', 'delivery_evidence', `TEXT NOT NULL DEFAULT 'none'`);\n this.addColumnIfMissing('memory_helpfulness', 'delivered_at', 'TEXT');\n this.addColumnIfMissing('memory_usefulness_observations_v2', 'memory_kind', `TEXT NOT NULL DEFAULT 'unknown'`);\n this.addColumnIfMissing('memory_usefulness_observations_v2', 'delivery_status', `TEXT NOT NULL DEFAULT 'unknown'`);\n this.addColumnIfMissing('memory_usefulness_observations_v2', 'delivery_evidence', `TEXT NOT NULL DEFAULT 'none'`);\n this.addColumnIfMissing('memory_usefulness_observations_v2', 'evaluation_window_ms', 'INTEGER');\n this.addColumnIfMissing('memory_usefulness_observations_v2', 'evaluation_cutoff', 'TEXT');\n // The raw memory id, kept beside the primary-key column. `event_id` has to\n // carry a kind-qualified key for non-event memories so an event and a\n // lesson sharing an id cannot overwrite each other on the existing primary\n // key; `memory_id` is what a reader joins on (specs R1, finding 2).\n this.addColumnIfMissing('memory_usefulness_observations_v2', 'memory_id', 'TEXT');\n this.addColumnIfMissing('memory_usefulness_observations_v2', 'memory_project_id', 'TEXT');\n this.addColumnIfMissing('memory_helpfulness', 'memory_project_id', 'TEXT');\n try {\n // Typed trace items are additive: an older store gains the table without\n // any change to the arrays its existing readers use.\n ensureRetrievalTraceItemsSchema(this.db);\n // Indexed only after the column migration above, so a legacy store that\n // predates request_id is not asked to index a column it lacks.\n sqliteExec(this.db, `CREATE INDEX IF NOT EXISTS idx_retrieval_traces_request_id ON retrieval_traces(request_id);`);\n } catch {\n // Partial migrations must not block store startup.\n }\n try {\n // One request must map to one trace even when two processes write at the\n // same moment. The partial index leaves the pre-existing rows with a NULL\n // request id untouched (specs R2, finding 9).\n sqliteExec(\n this.db,\n `CREATE UNIQUE INDEX IF NOT EXISTS idx_retrieval_traces_request_id_unique\n ON retrieval_traces(request_id) WHERE request_id IS NOT NULL;`\n );\n } catch {\n // A store that already contains duplicate request ids cannot take the\n // unique index. Leave its history intact: the transaction in\n // recordRetrievalTrace still serializes this process's own writers.\n }\n\n // Explicit curation reuses the existing lesson artifact while preserving\n // whether the item came from a reviewed/manual capture or a derivation.\n this.addColumnIfMissing('memory_lessons', 'source_class', `TEXT NOT NULL DEFAULT 'derived'`);\n // A lesson access used to be written against events.access_count, where it\n // matched no row and was silently lost. The typed access path now records\n // it here instead (specs R1).\n this.addColumnIfMissing('memory_lessons', 'access_count', 'INTEGER NOT NULL DEFAULT 0');\n this.addColumnIfMissing('memory_lessons', 'last_accessed_at', 'TEXT');\n this.addColumnIfMissing('memory_lessons', 'revision', 'INTEGER NOT NULL DEFAULT 1');\n this.addColumnIfMissing('memory_lessons', 'recall_enabled', 'INTEGER NOT NULL DEFAULT 1');\n this.addColumnIfMissing('memory_lessons', 'scope', 'TEXT');\n this.addColumnIfMissing('memory_lessons', 'validation_json', `TEXT NOT NULL DEFAULT '[]'`);\n this.addColumnIfMissing('memory_lessons', 'reconsider_when', 'TEXT');\n this.addColumnIfMissing('memory_lessons', 'valid_versions_json', `TEXT NOT NULL DEFAULT '[]'`);\n this.addColumnIfMissing('lesson_host_traces', 'machine_id', `TEXT NOT NULL DEFAULT ''`);\n this.addColumnIfMissing('lesson_host_traces', 'lesson_revisions_json', `TEXT NOT NULL DEFAULT '[]'`);\n this.addColumnIfMissing('lesson_review_candidates', 'duplicate_lesson_ids_json', `TEXT NOT NULL DEFAULT '[]'`);\n try {\n sqliteExec(this.db, `CREATE INDEX IF NOT EXISTS idx_memory_lessons_project_source_class ON memory_lessons(project_hash, source_class, updated_at DESC);`);\n sqliteExec(this.db, `CREATE INDEX IF NOT EXISTS idx_memory_lessons_project_recall ON memory_lessons(project_hash, recall_enabled, confidence DESC, updated_at DESC);`);\n } catch {\n // index/table may not exist in partial migrations\n }\n try {\n sqliteExec(this.db, `CREATE INDEX IF NOT EXISTS idx_retrieval_traces_query_rewrite_kind ON retrieval_traces(query_rewrite_kind);`);\n } catch {\n // index/table may not exist in partial migrations\n }\n\n // Forward-migrate the events table columns added over time. turn_id groups\n // events within a conversation turn; access_count/last_accessed_at back\n // access analytics.\n this.addColumnIfMissing('events', 'access_count', 'INTEGER DEFAULT 0');\n this.addColumnIfMissing('events', 'last_accessed_at', 'TEXT');\n this.addColumnIfMissing('events', 'turn_id', 'TEXT');\n\n // Create indexes for new columns if they don't exist\n try {\n sqliteExec(this.db, `\n CREATE INDEX IF NOT EXISTS idx_events_access_count ON events(access_count DESC);\n `);\n } catch (err: any) {\n // Index may already exist, ignore\n }\n\n try {\n sqliteExec(this.db, `\n CREATE INDEX IF NOT EXISTS idx_events_last_accessed ON events(last_accessed_at DESC);\n `);\n } catch (err: any) {\n // Index may already exist, ignore\n }\n\n try {\n sqliteExec(this.db, `\n CREATE INDEX IF NOT EXISTS idx_events_turn_id ON events(turn_id);\n `);\n } catch {\n // Index may already exist, ignore\n }\n\n // One-time backfill of the consolidated_memory_events junction from existing\n // source_events JSON (idempotent; skipped once the junction has any rows).\n const cmeCount = sqliteGet<{ c: number }>(this.db, `SELECT COUNT(*) as c FROM consolidated_memory_events`, []);\n if ((cmeCount?.c ?? 0) === 0) {\n sqliteExec(this.db, `\n INSERT OR IGNORE INTO consolidated_memory_events (memory_id, event_id)\n SELECT cm.memory_id, je.value\n FROM consolidated_memories cm, json_each(cm.source_events) je\n WHERE json_valid(cm.source_events);\n `);\n }\n\n // Stamp the schema version so future ordered migrations have an anchor to\n // gate on (PRAGMA user_version persists in the DB file). The migrations\n // above remain idempotent, so this is forward-looking rather than required.\n sqliteExec(this.db, `PRAGMA user_version = ${SQLITE_SCHEMA_VERSION}`);\n\n this.initialized = true;\n }\n\n /**\n * Append event to store (Append-only, Idempotent)\n */\n async append(input: MemoryEventInput): Promise<AppendResult> {\n await this.initialize();\n\n const canonicalKey = makeCanonicalKey(input.content);\n const dedupeKey = makeDedupeKey(input.content, input.sessionId);\n\n // Check for duplicate\n const existing = sqliteGet<{ event_id: string }>(\n this.db,\n `SELECT event_id FROM event_dedup WHERE dedupe_key = ?`,\n [dedupeKey]\n );\n\n if (existing) {\n try {\n await this.enqueueVectorOutboxEvent(existing.event_id, input.eventType);\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error)\n };\n }\n return {\n success: true,\n eventId: existing.event_id,\n isDuplicate: true\n };\n }\n\n const id = randomUUID();\n const timestamp = toSQLiteTimestamp(input.timestamp);\n\n try {\n // Extract turnId from metadata if present\n const metadata = input.metadata || {};\n const turnId = (metadata.turnId as string) || null;\n\n // Use transaction for atomicity\n const insertEvent = this.db.prepare(`\n INSERT INTO events (id, event_type, session_id, timestamp, content, canonical_key, dedupe_key, metadata, turn_id)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)\n `);\n\n const insertDedup = this.db.prepare(`\n INSERT INTO event_dedup (dedupe_key, event_id) VALUES (?, ?)\n `);\n\n const insertLevel = this.db.prepare(`\n INSERT INTO memory_levels (event_id, level) VALUES (?, 'L0')\n `);\n\n const transaction = this.db.transaction(() => {\n insertEvent.run(\n id,\n input.eventType,\n input.sessionId,\n timestamp,\n input.content,\n canonicalKey,\n dedupeKey,\n JSON.stringify(metadata),\n turnId\n );\n insertDedup.run(dedupeKey, id);\n insertLevel.run(id);\n this.enqueueVectorOutboxEventSync(id, input.eventType);\n });\n\n transaction();\n\n if (this.markdownMirror) {\n const event: MemoryEvent = {\n id,\n eventType: input.eventType,\n sessionId: input.sessionId,\n timestamp: input.timestamp,\n content: input.content,\n canonicalKey,\n dedupeKey,\n metadata\n };\n this.markdownMirror.append(event).catch((err) => {\n console.warn('[SQLiteEventStore] markdown mirror append failed:', err);\n });\n }\n\n return { success: true, eventId: id, isDuplicate: false };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error)\n };\n }\n }\n\n /**\n * Get session IDs that have events but no session_summary event.\n * Used to backfill summaries for sessions that ended without Stop hook.\n */\n async getSessionsWithoutSummary(currentSessionId: string, limit = 5): Promise<string[]> {\n await this.initialize();\n const rows = sqliteAll<{ session_id: string }>(\n this.db,\n `SELECT DISTINCT e.session_id\n FROM events e\n WHERE e.session_id != ?\n AND e.event_type != 'session_summary'\n AND e.session_id NOT IN (\n SELECT DISTINCT session_id FROM events WHERE event_type = 'session_summary'\n )\n GROUP BY e.session_id\n HAVING COUNT(*) >= 3\n ORDER BY MAX(e.timestamp) DESC\n LIMIT ?`,\n [currentSessionId, limit]\n );\n return rows.map((r) => r.session_id);\n }\n\n /**\n * Get events by session ID\n */\n async getSessionEvents(sessionId: string, options?: QuarantineReadOptions): Promise<MemoryEvent[]> {\n await this.initialize();\n\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM events WHERE session_id = ? AND ${maybeQuarantinePredicate(options)} ORDER BY timestamp ASC`,\n [sessionId]\n );\n\n return rows.map(this.rowToEvent);\n }\n\n /**\n * Get recent events, optionally restricted to a set of event types.\n *\n * The type filter exists because tool_observation is the overwhelming\n * majority of a real store (~84%). Callers that only want narrative events\n * would otherwise have to over-fetch by an order of magnitude \u2014 and load\n * every large tool payload along the way \u2014 just to reach a handful of\n * summaries.\n */\n async getRecentEvents(limit: number = 100, options?: RecentEventsReadOptions): Promise<MemoryEvent[]> {\n await this.initialize();\n\n const eventTypes = options?.eventTypes ?? [];\n const typePredicate = eventTypes.length > 0\n ? `AND event_type IN (${eventTypes.map(() => '?').join(', ')})`\n : '';\n\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM events\n WHERE ${maybeQuarantinePredicate(options)} ${typePredicate}\n ORDER BY timestamp DESC LIMIT ?`,\n [...eventTypes, limit]\n );\n\n return rows.map(this.rowToEvent);\n }\n\n /**\n * Aggregate event counts by type via SQL GROUP BY, instead of loading rows\n * into memory and counting in JS. Counts all events (the old recent-window\n * scan also under-counted stores larger than its cap).\n */\n async getEventTypeCounts(options?: QuarantineReadOptions): Promise<Array<{ eventType: string; count: number }>> {\n await this.initialize();\n const rows = sqliteAll<{ event_type: string; count: number }>(\n this.db,\n `SELECT event_type, COUNT(*) as count FROM events WHERE ${maybeQuarantinePredicate(options)} GROUP BY event_type`,\n []\n );\n return rows.map((row) => ({ eventType: row.event_type, count: row.count }));\n }\n\n /**\n * Fetch every event at/after an ISO timestamp (ascending), with no row cap.\n * For window-scoped analytics (KPI/usefulness) this fetches exactly the events\n * the window needs instead of an arbitrary \"most recent N\" slice that both\n * over-fetches sparse windows and truncates very active ones.\n */\n async getEventsAfter(sinceIso: string, options?: QuarantineReadOptions): Promise<MemoryEvent[]> {\n await this.initialize();\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM events WHERE timestamp >= ? AND ${maybeQuarantinePredicate(options)} ORDER BY timestamp ASC`,\n [sinceIso]\n );\n return rows.map((row) => this.rowToEvent(row));\n }\n\n /** Count distinct sessions via SQL instead of materializing a Set in JS. */\n async getDistinctSessionCount(options?: QuarantineReadOptions): Promise<number> {\n await this.initialize();\n const row = sqliteGet<{ count: number }>(\n this.db,\n `SELECT COUNT(DISTINCT session_id) as count FROM events WHERE ${maybeQuarantinePredicate(options)}`,\n []\n );\n return row?.count ?? 0;\n }\n\n /**\n * Per-day event counts (with type breakdown) since an ISO timestamp, computed\n * by SQL GROUP BY on the date prefix. Timestamps are stored as ISO-8601\n * strings, so substr(...,1,10) is the UTC day and `timestamp >= ?` compares\n * lexicographically.\n */\n async getDailyEventCounts(\n sinceIso: string,\n options?: QuarantineReadOptions\n ): Promise<Array<{ day: string; total: number; prompts: number; responses: number; tools: number }>> {\n await this.initialize();\n return sqliteAll<{ day: string; total: number; prompts: number; responses: number; tools: number }>(\n this.db,\n `SELECT substr(timestamp, 1, 10) as day,\n COUNT(*) as total,\n SUM(CASE WHEN event_type = 'user_prompt' THEN 1 ELSE 0 END) as prompts,\n SUM(CASE WHEN event_type = 'agent_response' THEN 1 ELSE 0 END) as responses,\n SUM(CASE WHEN event_type = 'tool_observation' THEN 1 ELSE 0 END) as tools\n FROM events\n WHERE timestamp >= ? AND ${maybeQuarantinePredicate(options)}\n GROUP BY day\n ORDER BY day ASC`,\n [sinceIso]\n );\n }\n\n /**\n * Get event by ID\n */\n async getEvent(id: string, options?: QuarantineReadOptions): Promise<MemoryEvent | null> {\n await this.initialize();\n\n const row = sqliteGet<Record<string, unknown>>(\n this.db,\n `SELECT * FROM events WHERE id = ? AND ${maybeQuarantinePredicate(options)}`,\n [id]\n );\n\n if (!row) return null;\n return this.rowToEvent(row);\n }\n\n /**\n * Batch-fetch events by id in a single query, applying the same quarantine\n * predicate as getEvent. Lets hot paths replace N sequential round-trips with\n * one. Missing ids are simply absent from the result (order not guaranteed).\n */\n async getEvents(ids: string[], options?: QuarantineReadOptions): Promise<MemoryEvent[]> {\n await this.initialize();\n if (ids.length === 0) return [];\n\n const placeholders = ids.map(() => '?').join(',');\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM events WHERE id IN (${placeholders}) AND ${maybeQuarantinePredicate(options)}`,\n ids\n );\n\n return rows.map((row) => this.rowToEvent(row));\n }\n\n /**\n * Resolve an event from its citation id via the reverse index, instead of\n * scanning recent events and hashing each one. The index is self-healing: a\n * miss triggers a one-time backfill of any events not yet indexed (covering\n * freshly appended events) before retrying.\n */\n async getEventByCitationId(citationId: string, options?: QuarantineReadOptions): Promise<MemoryEvent | null> {\n await this.initialize();\n if (!citationId) return null;\n\n let row = sqliteGet<{ event_id: string }>(\n this.db,\n `SELECT event_id FROM event_citations WHERE citation_id = ? LIMIT 1`,\n [citationId]\n );\n\n if (!row) {\n this.indexMissingCitations();\n row = sqliteGet<{ event_id: string }>(\n this.db,\n `SELECT event_id FROM event_citations WHERE citation_id = ? LIMIT 1`,\n [citationId]\n );\n }\n\n if (!row) return null;\n return this.getEvent(row.event_id, options);\n }\n\n /**\n * Backfill citation ids for any events not yet present in event_citations.\n * Gated on a cheap count comparison so the common (fully-indexed) path does no\n * work, and the scan only runs when there are genuinely new events to index.\n */\n private indexMissingCitations(): void {\n const eventCount = sqliteGet<{ c: number }>(this.db, `SELECT COUNT(*) as c FROM events`, [])?.c ?? 0;\n const indexedCount = sqliteGet<{ c: number }>(this.db, `SELECT COUNT(*) as c FROM event_citations`, [])?.c ?? 0;\n if (indexedCount >= eventCount) return;\n\n const unindexed = sqliteAll<{ id: string }>(\n this.db,\n `SELECT e.id FROM events e\n LEFT JOIN event_citations ec ON ec.event_id = e.id\n WHERE ec.event_id IS NULL`,\n []\n );\n if (unindexed.length === 0) return;\n\n const insert = this.db.prepare(`INSERT OR IGNORE INTO event_citations (event_id, citation_id) VALUES (?, ?)`);\n this.db.transaction(() => {\n for (const { id } of unindexed) {\n insert.run(id, generateCitationId(id));\n }\n })();\n }\n\n /**\n * Get events since a timestamp (for sync)\n */\n async getEventsSince(timestamp: string, limit: number = 1000, options?: QuarantineReadOptions): Promise<MemoryEvent[]> {\n await this.initialize();\n\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM events WHERE timestamp > ? AND ${maybeQuarantinePredicate(options)} ORDER BY timestamp ASC LIMIT ?`,\n [timestamp, limit]\n );\n\n return rows.map(this.rowToEvent);\n }\n\n /**\n * Get events since a SQLite rowid (for robust incremental replication).\n * Rowid is monotonic for append-only tables, independent of client timestamps.\n */\n async getEventsSinceRowid(\n lastRowid: number,\n limit: number = 1000,\n options?: QuarantineReadOptions\n ): Promise<Array<{ rowid: number; event: MemoryEvent }>> {\n await this.initialize();\n\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT rowid as _rowid, * FROM events WHERE rowid > ? AND ${maybeQuarantinePredicate(options)} ORDER BY rowid ASC LIMIT ?`,\n [lastRowid, limit]\n );\n\n return rows.map(row => ({\n rowid: row._rowid as number,\n event: this.rowToEvent(row)\n }));\n }\n\n /**\n * Import events with fixed IDs (used for cross-machine replication).\n * Idempotent: skips if event id or dedupeKey already exists.\n *\n * NOTE: This bypasses the append() id generation to preserve stable IDs.\n */\n async importEvents(events: MemoryEvent[]): Promise<{ inserted: number; skipped: number }> {\n if (events.length === 0) return { inserted: 0, skipped: 0 };\n if (this.readOnly) return { inserted: 0, skipped: events.length };\n\n await this.initialize();\n\n const getById = this.db.prepare(`SELECT id FROM events WHERE id = ?`);\n const getByDedupe = this.db.prepare(`SELECT event_id FROM event_dedup WHERE dedupe_key = ?`);\n\n const insertEvent = this.db.prepare(`\n INSERT INTO events (id, event_type, session_id, timestamp, content, canonical_key, dedupe_key, metadata, turn_id)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)\n `);\n\n const insertDedup = this.db.prepare(`\n INSERT INTO event_dedup (dedupe_key, event_id) VALUES (?, ?)\n `);\n\n const insertLevel = this.db.prepare(`\n INSERT INTO memory_levels (event_id, level) VALUES (?, 'L0')\n `);\n\n let inserted = 0;\n let skipped = 0;\n const insertedEvents: MemoryEvent[] = [];\n\n const tx = this.db.transaction((batch: MemoryEvent[]) => {\n for (const ev of batch) {\n // Skip if already present by id\n const existingById = getById.get(ev.id) as { id: string } | undefined;\n if (existingById) {\n skipped++;\n continue;\n }\n\n const canonicalKey = ev.canonicalKey || makeCanonicalKey(ev.content);\n const dedupeKey = ev.dedupeKey || makeDedupeKey(ev.content, ev.sessionId);\n\n // Skip if already present by dedupe key\n const existingByDedupe = getByDedupe.get(dedupeKey) as { event_id: string } | undefined;\n if (existingByDedupe) {\n skipped++;\n continue;\n }\n\n const metadata = ev.metadata || {};\n const turnId = (metadata as any).turnId as string | undefined;\n\n insertEvent.run(\n ev.id,\n ev.eventType,\n ev.sessionId,\n toSQLiteTimestamp(ev.timestamp),\n ev.content,\n canonicalKey,\n dedupeKey,\n JSON.stringify(metadata),\n turnId ?? null\n );\n\n insertDedup.run(dedupeKey, ev.id);\n insertLevel.run(ev.id);\n this.enqueueVectorOutboxEventSync(ev.id, ev.eventType);\n inserted++;\n insertedEvents.push(ev);\n }\n });\n\n tx(events);\n\n if (this.markdownMirror && insertedEvents.length > 0) {\n for (const ev of insertedEvents) {\n this.markdownMirror.append(ev).catch((err) => {\n console.warn('[SQLiteEventStore] markdown mirror append failed:', err);\n });\n }\n }\n\n return { inserted, skipped };\n }\n\n /**\n * Create or update session\n */\n async upsertSession(session: Partial<Session> & { id: string }): Promise<void> {\n await this.initialize();\n\n const existing = sqliteGet<{ id: string }>(\n this.db,\n `SELECT id FROM sessions WHERE id = ?`,\n [session.id]\n );\n\n if (!existing) {\n sqliteRun(\n this.db,\n `INSERT INTO sessions (id, started_at, project_path, tags)\n VALUES (?, ?, ?, ?)`,\n [\n session.id,\n toSQLiteTimestamp(session.startedAt || new Date()),\n session.projectPath || null,\n JSON.stringify(session.tags || [])\n ]\n );\n } else {\n const updates: string[] = [];\n const values: unknown[] = [];\n\n if (session.endedAt) {\n updates.push('ended_at = ?');\n values.push(toSQLiteTimestamp(session.endedAt));\n }\n if (session.summary) {\n updates.push('summary = ?');\n values.push(session.summary);\n }\n if (session.tags) {\n updates.push('tags = ?');\n values.push(JSON.stringify(session.tags));\n }\n\n if (updates.length > 0) {\n values.push(session.id);\n sqliteRun(\n this.db,\n `UPDATE sessions SET ${updates.join(', ')} WHERE id = ?`,\n values\n );\n }\n }\n }\n\n /**\n * Get session by ID\n */\n async getSession(id: string): Promise<Session | null> {\n await this.initialize();\n\n const row = sqliteGet<Record<string, unknown>>(\n this.db,\n `SELECT * FROM sessions WHERE id = ?`,\n [id]\n );\n\n if (!row) return null;\n\n return {\n id: row.id as string,\n startedAt: toDateFromSQLite(row.started_at),\n endedAt: row.ended_at ? toDateFromSQLite(row.ended_at) : undefined,\n projectPath: row.project_path as string | undefined,\n summary: row.summary as string | undefined,\n tags: row.tags ? JSON.parse(row.tags as string) : undefined\n };\n }\n\n /**\n * Get all sessions\n */\n async getAllSessions(): Promise<Session[]> {\n await this.initialize();\n\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM sessions ORDER BY started_at DESC`\n );\n\n return rows.map(row => ({\n id: row.id as string,\n startedAt: toDateFromSQLite(row.started_at),\n endedAt: row.ended_at ? toDateFromSQLite(row.ended_at) : undefined,\n projectPath: row.project_path as string | undefined,\n summary: row.summary as string | undefined,\n tags: row.tags ? JSON.parse(row.tags as string) : undefined\n }));\n }\n\n /**\n * Add to embedding outbox\n */\n async enqueueForEmbedding(eventId: string, content: string): Promise<string> {\n await this.initialize();\n\n const id = randomUUID();\n sqliteRun(\n this.db,\n `INSERT INTO embedding_outbox (id, event_id, content, status, retry_count)\n VALUES (?, ?, ?, 'pending', 0)`,\n [id, eventId, content]\n );\n\n return id;\n }\n\n /**\n * Get pending outbox items\n */\n async getPendingOutboxItems(limit: number = 32): Promise<OutboxItem[]> {\n await this.initialize();\n\n // Claim pending items atomically in a single UPDATE ... RETURNING. A\n // SELECT-then-UPDATE leaves a window where two concurrent workers (or a\n // worker plus processAll) both select the same rows before either marks them\n // 'processing', producing duplicate embedding work. The single statement\n // makes the claim race-free, matching VectorOutbox.claimJobs.\n const claimed = sqliteAll<Record<string, unknown>>(\n this.db,\n `UPDATE embedding_outbox\n SET status = 'processing', processed_at = datetime('now'), error_message = NULL\n WHERE id IN (\n SELECT id FROM embedding_outbox\n WHERE status = 'pending'\n ORDER BY created_at\n LIMIT ?\n )\n RETURNING *`,\n [limit]\n );\n\n if (claimed.length === 0) return [];\n\n // RETURNING does not guarantee row order; restore created_at ordering.\n claimed.sort((a, b) => String(a.created_at).localeCompare(String(b.created_at)));\n\n return claimed.map(row => ({\n id: row.id as string,\n eventId: row.event_id as string,\n content: row.content as string,\n status: 'processing' as const,\n retryCount: row.retry_count as number,\n createdAt: toDateFromSQLite(row.created_at),\n errorMessage: row.error_message as string | undefined\n }));\n }\n\n /**\n * Mark outbox items as done\n */\n async completeOutboxItems(ids: string[]): Promise<void> {\n if (ids.length === 0) return;\n\n const placeholders = ids.map(() => '?').join(',');\n sqliteRun(\n this.db,\n `DELETE FROM embedding_outbox WHERE id IN (${placeholders})`,\n ids\n );\n }\n\n /**\n * Clear embedding outbox (used for embedding model migration)\n */\n async clearEmbeddingOutbox(): Promise<void> {\n await this.initialize();\n sqliteRun(this.db, `DELETE FROM embedding_outbox`);\n }\n\n /**\n * Count total events\n */\n async countEvents(options?: QuarantineReadOptions): Promise<number> {\n await this.initialize();\n const row = sqliteGet<{ count: number }>(this.db, `SELECT COUNT(*) as count FROM events WHERE ${maybeQuarantinePredicate(options)}`);\n return row?.count || 0;\n }\n\n /**\n * Get events page in timestamp ascending order (stable migration/reindex scans)\n */\n async getEventsPage(limit: number = 1000, offset: number = 0, options?: QuarantineReadOptions): Promise<MemoryEvent[]> {\n await this.initialize();\n\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM events WHERE ${maybeQuarantinePredicate(options)} ORDER BY timestamp ASC LIMIT ? OFFSET ?`,\n [limit, offset]\n );\n\n return rows.map(this.rowToEvent);\n }\n\n /**\n * Mark outbox items as failed\n */\n async failOutboxItems(ids: string[], error: string): Promise<void> {\n if (ids.length === 0) return;\n\n const placeholders = ids.map(() => '?').join(',');\n sqliteRun(\n this.db,\n `UPDATE embedding_outbox\n SET status = CASE WHEN retry_count >= 3 THEN 'failed' ELSE 'pending' END,\n retry_count = retry_count + 1,\n error_message = ?\n WHERE id IN (${placeholders})`,\n [error, ...ids]\n );\n }\n\n /**\n * Recover abandoned outbox work after a worker/process crash.\n *\n * Rows in `processing` are claimed work. If the process exits before marking\n * them done/failed, they otherwise remain invisible to future processing.\n * Recovery is deliberately age-gated so an active worker is not disturbed.\n */\n async recoverStuckOutboxItems(options: OutboxRecoveryOptions = {}): Promise<OutboxRecoveryResult> {\n await this.initialize();\n\n const thresholdMs = Number.isFinite(options.stuckThresholdMs) && (options.stuckThresholdMs ?? 0) >= 0\n ? options.stuckThresholdMs!\n : DEFAULT_OUTBOX_STUCK_THRESHOLD_MS;\n const maxRetries = Number.isFinite(options.maxRetries) && (options.maxRetries ?? 0) > 0\n ? options.maxRetries!\n : DEFAULT_OUTBOX_MAX_RETRIES;\n const now = options.now ?? new Date();\n const threshold = new Date(now.getTime() - thresholdMs).toISOString();\n const result = emptyOutboxRecoveryResult();\n\n if (options.dryRun === true) {\n const embeddingRecovered = sqliteGet<{ count: number }>(\n this.db,\n `SELECT COUNT(*) AS count FROM embedding_outbox\n WHERE status = 'processing'\n AND datetime(COALESCE(processed_at, created_at)) < datetime(?)`,\n [threshold]\n );\n result.embedding.recoveredProcessing = Number(embeddingRecovered?.count ?? 0);\n\n const embeddingRetried = sqliteGet<{ count: number }>(\n this.db,\n `SELECT COUNT(*) AS count FROM embedding_outbox\n WHERE status = 'failed'\n AND retry_count < ?`,\n [maxRetries]\n );\n result.embedding.retriedFailed = Number(embeddingRetried?.count ?? 0);\n\n const vectorRecovered = sqliteGet<{ count: number }>(\n this.db,\n `SELECT COUNT(*) AS count FROM vector_outbox\n WHERE status = 'processing'\n AND datetime(updated_at) < datetime(?)`,\n [threshold]\n );\n result.vector.recoveredProcessing = Number(vectorRecovered?.count ?? 0);\n\n const vectorRetried = sqliteGet<{ count: number }>(\n this.db,\n `SELECT COUNT(*) AS count FROM vector_outbox\n WHERE status = 'failed'\n AND retry_count < ?`,\n [maxRetries]\n );\n result.vector.retriedFailed = Number(vectorRetried?.count ?? 0);\n\n return result;\n }\n\n const embeddingRecovered = sqliteRun(\n this.db,\n `UPDATE embedding_outbox\n SET status = 'pending', processed_at = NULL, error_message = NULL\n WHERE status = 'processing'\n AND datetime(COALESCE(processed_at, created_at)) < datetime(?)`,\n [threshold]\n );\n result.embedding.recoveredProcessing = Number(embeddingRecovered.changes ?? 0);\n\n const embeddingRetried = sqliteRun(\n this.db,\n `UPDATE embedding_outbox\n SET status = 'pending', error_message = NULL\n WHERE status = 'failed'\n AND retry_count < ?`,\n [maxRetries]\n );\n result.embedding.retriedFailed = Number(embeddingRetried.changes ?? 0);\n\n const vectorRecovered = sqliteRun(\n this.db,\n `UPDATE vector_outbox\n SET status = 'pending', updated_at = ?, error = NULL\n WHERE status = 'processing'\n AND datetime(updated_at) < datetime(?)`,\n [now.toISOString(), threshold]\n );\n result.vector.recoveredProcessing = Number(vectorRecovered.changes ?? 0);\n\n const vectorRetried = sqliteRun(\n this.db,\n `UPDATE vector_outbox\n SET status = 'pending', updated_at = ?, error = NULL\n WHERE status = 'failed'\n AND retry_count < ?`,\n [now.toISOString(), maxRetries]\n );\n result.vector.retriedFailed = Number(vectorRetried.changes ?? 0);\n\n return result;\n }\n\n\n /**\n * List event IDs for a given event type (used by maintenance/backfill tooling).\n */\n async listEventIdsByType(eventType: string): Promise<string[]> {\n await this.initialize();\n const rows = sqliteAll<{ id: string }>(\n this.db,\n `SELECT id FROM events WHERE event_type = ? ORDER BY timestamp ASC`,\n [eventType]\n );\n return rows.map((row) => row.id);\n }\n\n /**\n * Remove vector_outbox rows for the given event ids (item_kind = 'event').\n * Used after pruning already-embedded vectors so the outbox stops reporting\n * them as done work.\n */\n async removeVectorOutboxRowsForEventIds(eventIds: string[]): Promise<number> {\n if (eventIds.length === 0) return 0;\n await this.initialize();\n const placeholders = eventIds.map(() => '?').join(', ');\n const result = this.db.prepare(\n `DELETE FROM vector_outbox WHERE item_kind = 'event' AND item_id IN (${placeholders})`\n ).run(...eventIds);\n return Number(result.changes ?? 0);\n }\n\n /**\n * Repair legacy imported events that predate canonical project scope metadata.\n *\n * Same-project legacy rows are tagged with scope.project.hash. Rows that look\n * imported but cannot be proven to belong to this project are quarantined so\n * dashboard default reads/search do not surface cross-project contamination.\n */\n async repairLegacyProjectScope(options: ProjectScopeRepairOptions = {}): Promise<ProjectScopeRepairResult> {\n await this.initialize();\n\n const projectHash = options.projectHash || (options.projectPath ? hashProjectPath(options.projectPath) : undefined);\n if (!projectHash) {\n throw new Error('repairLegacyProjectScope requires projectPath or projectHash');\n }\n if (\n options.projectPath && options.projectHash\n && hashProjectPath(options.projectPath) !== options.projectHash\n // A store created before a .claude-memory-root marker was adopted is\n // keyed by the pre-marker (git-only) hash; addressing it by path + that\n // hash is consistent, not a different store.\n && hashProjectPathIgnoringMarker(options.projectPath) !== options.projectHash\n ) {\n throw new Error('repairLegacyProjectScope projectPath and projectHash refer to different project stores');\n }\n\n const dryRun = options.dryRun === true;\n const nowIso = (options.now || new Date()).toISOString();\n const result = buildRepairResult(projectHash, dryRun);\n\n const rows = sqliteAll<{\n id: string;\n content: string;\n metadata: string | null;\n session_project_path: string | null;\n }>(\n this.db,\n `SELECT e.id, e.content, e.metadata, s.project_path as session_project_path\n FROM events e\n LEFT JOIN sessions s ON s.id = e.session_id\n ORDER BY e.timestamp ASC`,\n []\n );\n\n const sample = (entry: ProjectScopeRepairSample) => {\n if (result.samples.length < 20) result.samples.push(entry);\n };\n\n for (const row of rows) {\n result.scanned++;\n\n let metadata: Record<string, unknown> = {};\n let metadataParseInvalid = false;\n if (row.metadata) {\n const parsed = safeParseMetadataValue(row.metadata);\n if (parsed) {\n metadata = parsed;\n } else {\n metadataParseInvalid = true;\n }\n }\n\n if (isActiveQuarantinedMetadata(metadata)) {\n result.skipped++;\n continue;\n }\n\n const currentHash = metadataProjectHash(metadata);\n const explicitPath = metadataProjectPath(metadata);\n const sessionProjectPath = typeof row.session_project_path === 'string' && row.session_project_path.length > 0\n ? row.session_project_path\n : undefined;\n const candidatePaths = metadataProjectPaths(metadata);\n if (sessionProjectPath && !candidatePaths.includes(sessionProjectPath)) {\n candidatePaths.push(sessionProjectPath);\n }\n const importedOrLegacy = metadataParseInvalid || isImportedOrLegacyScopedMetadata(metadata) || Boolean(sessionProjectPath);\n const pathHashes = candidatePaths.map((candidate) => {\n try {\n return {\n path: candidate,\n hash: hashProjectPath(candidate),\n // The hash the candidate had before any marker applied. A row\n // whose recorded path re-hashes elsewhere only because a\n // .claude-memory-root marker was adopted after the store filled\n // up is a basis shift, not cross-project contamination.\n preMarkerHash: hashProjectPathIgnoringMarker(candidate)\n };\n } catch {\n return { path: candidate, hash: undefined, preMarkerHash: undefined };\n }\n });\n const belongsToThisStore = (candidate: { hash?: string; preMarkerHash?: string }) =>\n candidate.hash === projectHash || candidate.preMarkerHash === projectHash;\n const matchingPath = pathHashes.find(belongsToThisStore);\n const foreignPath = pathHashes.find((candidate) => candidate.hash && !belongsToThisStore(candidate));\n\n let action: 'repaired' | 'quarantined' | 'skipped' = 'skipped';\n let reason: ProjectScopeRepairSample['reason'] | undefined;\n let observedProjectHash: string | undefined;\n\n if (foreignPath) {\n action = 'quarantined';\n reason = 'project-path-mismatch';\n observedProjectHash = foreignPath.hash;\n } else if (currentHash === projectHash && importedOrLegacy && hasConflictingContentProjectHint(row.content, options.projectPath)) {\n action = 'quarantined';\n reason = 'content-project-mismatch';\n } else if (currentHash === projectHash) {\n result.alreadyScoped++;\n continue;\n } else if (\n currentHash && currentHash !== projectHash\n // The stamp disagrees, but it is exactly the pre-marker hash of a\n // recorded path that provably belongs to this store: the hash basis\n // moved under the row (a .claude-memory-root marker was adopted), the\n // row did not move projects. Restamp instead of quarantining, or the\n // strict retrieval scope gate drops the row forever.\n && !(matchingPath && matchingPath.preMarkerHash === currentHash)\n ) {\n action = 'quarantined';\n reason = 'scope-hash-mismatch';\n observedProjectHash = currentHash;\n } else if (matchingPath) {\n action = 'repaired';\n reason = matchingPath.path === sessionProjectPath && matchingPath.path !== explicitPath\n ? 'session-project-path'\n : 'same-project-path';\n } else if (candidatePaths.length > 0) {\n action = 'quarantined';\n reason = 'project-path-mismatch';\n } else if (importedOrLegacy) {\n action = 'quarantined';\n reason = 'missing-project-scope';\n }\n\n if (action === 'skipped' || !reason) {\n result.skipped++;\n continue;\n }\n\n if (action === 'repaired') {\n const scope = isRecord(metadata.scope) ? { ...metadata.scope } : {};\n const project = isRecord(scope.project) ? { ...scope.project } : {};\n project.hash = projectHash;\n scope.project = project;\n metadata.scope = scope;\n metadata.repair = {\n ...(isRecord(metadata.repair) ? metadata.repair : {}),\n legacyProjectScope: {\n action,\n reason,\n repairedAt: nowIso\n }\n };\n addMetadataTag(metadata, `proj:${projectHash}`);\n result.repaired++;\n } else {\n metadata.quarantine = {\n ...(isRecord(metadata.quarantine) ? metadata.quarantine : {}),\n status: 'active',\n category: 'project-scope',\n reason,\n detectedAt: nowIso,\n expectedProjectHash: projectHash,\n ...(observedProjectHash ? { observedProjectHash } : {})\n };\n metadata.repair = {\n ...(isRecord(metadata.repair) ? metadata.repair : {}),\n legacyProjectScope: {\n action,\n reason,\n repairedAt: nowIso\n }\n };\n addMetadataTag(metadata, 'quarantine:project-scope');\n result.quarantined++;\n }\n\n sample({ eventId: row.id, action, reason });\n if (!dryRun) {\n sqliteRun(this.db, `UPDATE events SET metadata = ? WHERE id = ?`, [JSON.stringify(metadata), row.id]);\n }\n }\n\n return result;\n }\n\n /**\n * Get embedding/vector outbox health statistics\n */\n async getOutboxStats(options: OutboxStatsOptions = {}): Promise<OutboxStats> {\n await this.initialize();\n\n const thresholdMs = Number.isFinite(options.stuckThresholdMs) && (options.stuckThresholdMs ?? 0) >= 0\n ? options.stuckThresholdMs!\n : DEFAULT_OUTBOX_STUCK_THRESHOLD_MS;\n const maxRetries = Number.isFinite(options.maxRetries) && (options.maxRetries ?? 0) > 0\n ? options.maxRetries!\n : DEFAULT_OUTBOX_MAX_RETRIES;\n const now = options.now ?? new Date();\n const threshold = new Date(now.getTime() - thresholdMs).toISOString();\n\n const embeddingRows = sqliteAll<{ status: string; count: number }>(\n this.db,\n `SELECT status, COUNT(*) as count FROM embedding_outbox GROUP BY status`\n );\n const vectorRows = sqliteAll<{ status: string; count: number }>(\n this.db,\n `SELECT status, COUNT(*) as count FROM vector_outbox GROUP BY status`\n );\n\n const processingAgeMs = (value: unknown): number | null => {\n if (value === null || value === undefined) return null;\n const date = toDateFromSQLite(value);\n const time = date.getTime();\n if (!Number.isFinite(time)) return null;\n return Math.max(0, now.getTime() - time);\n };\n\n const fromRows = (\n rows: Array<{ status: string; count: number }>,\n stuckProcessing: number,\n oldestProcessingAgeMs: number | null,\n retryableFailed: number,\n quarantinedFailed: number\n ) => {\n const out = { pending: 0, processing: 0, failed: 0, retryableFailed, quarantinedFailed, total: 0, stuckProcessing, oldestProcessingAgeMs };\n for (const row of rows) {\n const key = row.status as 'pending' | 'processing' | 'failed' | 'done';\n if (key === 'pending' || key === 'processing' || key === 'failed') {\n out[key] += Number(row.count ?? 0);\n }\n out.total += Number(row.count ?? 0);\n }\n return out;\n };\n\n const embeddingStuck = sqliteGet<{ count: number }>(\n this.db,\n `SELECT COUNT(*) as count\n FROM embedding_outbox\n WHERE status = 'processing'\n AND datetime(COALESCE(processed_at, created_at)) < datetime(?)`,\n [threshold]\n );\n const embeddingOldest = sqliteGet<{ oldest: string | null }>(\n this.db,\n `SELECT MIN(datetime(COALESCE(processed_at, created_at))) as oldest\n FROM embedding_outbox\n WHERE status = 'processing'`\n );\n const embeddingRetryableFailed = sqliteGet<{ count: number }>(\n this.db,\n `SELECT COUNT(*) as count\n FROM embedding_outbox\n WHERE status = 'failed'\n AND retry_count < ?`,\n [maxRetries]\n );\n const embeddingQuarantinedFailed = sqliteGet<{ count: number }>(\n this.db,\n `SELECT COUNT(*) as count\n FROM embedding_outbox\n WHERE status = 'failed'\n AND retry_count >= ?`,\n [maxRetries]\n );\n\n const vectorStuck = sqliteGet<{ count: number }>(\n this.db,\n `SELECT COUNT(*) as count\n FROM vector_outbox\n WHERE status = 'processing'\n AND datetime(updated_at) < datetime(?)`,\n [threshold]\n );\n const vectorOldest = sqliteGet<{ oldest: string | null }>(\n this.db,\n `SELECT MIN(datetime(updated_at)) as oldest\n FROM vector_outbox\n WHERE status = 'processing'`\n );\n const vectorRetryableFailed = sqliteGet<{ count: number }>(\n this.db,\n `SELECT COUNT(*) as count\n FROM vector_outbox\n WHERE status = 'failed'\n AND retry_count < ?`,\n [maxRetries]\n );\n const vectorQuarantinedFailed = sqliteGet<{ count: number }>(\n this.db,\n `SELECT COUNT(*) as count\n FROM vector_outbox\n WHERE status = 'failed'\n AND retry_count >= ?`,\n [maxRetries]\n );\n\n return {\n embedding: fromRows(\n embeddingRows,\n Number(embeddingStuck?.count ?? 0),\n processingAgeMs(embeddingOldest?.oldest),\n Number(embeddingRetryableFailed?.count ?? 0),\n Number(embeddingQuarantinedFailed?.count ?? 0)\n ),\n vector: fromRows(\n vectorRows,\n Number(vectorStuck?.count ?? 0),\n processingAgeMs(vectorOldest?.oldest),\n Number(vectorRetryableFailed?.count ?? 0),\n Number(vectorQuarantinedFailed?.count ?? 0)\n )\n };\n }\n\n /**\n * Update memory level\n */\n async updateMemoryLevel(eventId: string, level: string): Promise<void> {\n await this.initialize();\n\n sqliteRun(\n this.db,\n `UPDATE memory_levels SET level = ?, promoted_at = datetime('now') WHERE event_id = ?`,\n [level, eventId]\n );\n }\n\n /**\n * Get memory level statistics\n */\n async getLevelStats(): Promise<Array<{ level: string; count: number }>> {\n await this.initialize();\n\n const rows = sqliteAll<{ level: string; count: number }>(\n this.db,\n `SELECT ml.level, COUNT(*) as count\n FROM memory_levels ml\n INNER JOIN events e ON e.id = ml.event_id\n WHERE ${notActiveQuarantinedSql('e.metadata')}\n GROUP BY ml.level`\n );\n\n return rows;\n }\n\n /**\n * Get events by memory level\n */\n async getEventsByLevel(level: string, options?: { limit?: number; offset?: number }): Promise<MemoryEvent[]> {\n await this.initialize();\n\n const limit = options?.limit || 50;\n const offset = options?.offset || 0;\n\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT e.* FROM events e\n INNER JOIN memory_levels ml ON e.id = ml.event_id\n WHERE ml.level = ?\n AND ${notActiveQuarantinedSql('e.metadata')}\n ORDER BY e.timestamp DESC\n LIMIT ? OFFSET ?`,\n [level, limit, offset]\n );\n\n return rows.map(row => this.rowToEvent(row));\n }\n\n /**\n * Return bounded graduation candidates in evidence order. Graduation only\n * benefits rows with durable access evidence, and ordering by creation time\n * would permanently starve an older memory in a busy project.\n */\n async getGraduationCandidates(level: string, options: { limit: number }): Promise<MemoryEvent[]> {\n await this.initialize();\n\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT e.* FROM events e\n INNER JOIN memory_levels ml ON e.id = ml.event_id\n WHERE ml.level = ?\n AND e.access_count > 0\n AND ${notActiveQuarantinedSql('e.metadata')}\n ORDER BY e.access_count DESC,\n COALESCE(e.last_accessed_at, e.timestamp) DESC,\n e.timestamp DESC\n LIMIT ?`,\n [level, options.limit]\n );\n\n return rows.map(row => this.rowToEvent(row));\n }\n\n /** Durable access evidence used to hydrate one-shot graduation workers. */\n async getGraduationMetrics(eventIds: string[]): Promise<Array<{\n eventId: string;\n accessCount: number;\n lastAccessed: Date;\n crossSessionRefs: number;\n confidence: number;\n }>> {\n await this.initialize();\n if (eventIds.length === 0) return [];\n const placeholders = eventIds.map(() => '?').join(', ');\n const rows = sqliteAll<{ id: string; access_count: number; last_accessed_at: string | null; timestamp: string }>(\n this.db,\n `SELECT id, access_count, last_accessed_at, timestamp\n FROM events\n WHERE id IN (${placeholders})\n AND access_count > 0\n AND ${notActiveQuarantinedSql('metadata')}`,\n eventIds\n );\n const sessionRows = sqliteAll<{ event_id: string; session_count: number }>(\n this.db,\n `SELECT event_id, COUNT(DISTINCT session_id) AS session_count\n FROM memory_helpfulness\n WHERE event_id IN (${placeholders})\n GROUP BY event_id`,\n eventIds\n );\n const sessionCounts = new Map(sessionRows.map((row) => [row.event_id, Number(row.session_count)]));\n return rows.map((row) => ({\n eventId: row.id,\n accessCount: Number(row.access_count),\n lastAccessed: toDateFromSQLite(row.last_accessed_at ?? row.timestamp),\n crossSessionRefs: Math.max(0, (sessionCounts.get(row.id) ?? 0) - 1),\n // Access is recorded only after the hook's strict injection filter.\n confidence: 1\n }));\n }\n\n /**\n * Persist an aggregate graduation attempt. The rows deliberately contain\n * no event content, project paths, prompt text, or underlying error text so\n * they can safely feed the productivity health report.\n */\n async recordGraduationRun(input: {\n startedAt: Date;\n finishedAt: Date;\n status: 'success' | 'not_eligible' | 'failed';\n evaluated: number;\n graduated: number;\n }): Promise<void> {\n await this.initialize();\n if (this.readOnly) return;\n\n const buildId = randomUUID();\n const status = input.status;\n const startedAt = input.startedAt.toISOString();\n const finishedAt = input.finishedAt.toISOString();\n const latencyMs = Math.max(0, input.finishedAt.getTime() - input.startedAt.getTime());\n\n sqliteRun(\n this.db,\n `INSERT INTO build_runs (\n build_id, started_at, finished_at, extractor_model, extractor_prompt_hash,\n embedder_model, embedding_version, idris_version, schema_version, status, error\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` ,\n [\n buildId,\n startedAt,\n finishedAt,\n 'graduation-rules',\n 'not-applicable',\n 'not-applicable',\n 'not-applicable',\n 'graduation-worker-v1',\n String(SQLITE_SCHEMA_VERSION),\n status,\n status === 'failed' ? 'graduation_failed' : null\n ]\n );\n\n sqliteRun(\n this.db,\n `INSERT INTO pipeline_metrics (id, ts, stage, latency_ms, success, error, session_id)\n VALUES (?, ?, ?, ?, ?, ?, ?)` ,\n [\n randomUUID(),\n finishedAt,\n 'graduation',\n latencyMs,\n status === 'failed' ? 0 : 1,\n status === 'failed' ? 'graduation_failed' : null,\n null\n ]\n );\n }\n\n /** Aggregate-only worker liveness for health/status surfaces. */\n async getDerivationLiveness(projectHash?: string): Promise<DerivationLiveness> {\n await this.initialize();\n\n const attempts = sqliteGet<{ count: number }>(\n this.db,\n `SELECT COUNT(*) AS count FROM build_runs WHERE idris_version = ?`,\n ['graduation-worker-v1']\n );\n const latest = sqliteGet<{ status: string; finished_at: string | null }>(\n this.db,\n `SELECT status, finished_at FROM build_runs\n WHERE idris_version = ?\n ORDER BY started_at DESC, build_id DESC\n LIMIT 1`,\n ['graduation-worker-v1']\n );\n const latestSuccessful = sqliteGet<{ finished_at: string | null }>(\n this.db,\n `SELECT finished_at FROM build_runs\n WHERE idris_version = ? AND status IN ('success', 'not_eligible')\n ORDER BY started_at DESC, build_id DESC\n LIMIT 1`,\n ['graduation-worker-v1']\n );\n const lastStatus = latest?.status === 'success' || latest?.status === 'not_eligible' || latest?.status === 'failed'\n ? latest.status\n : null;\n const graduatedEvents = sqliteGet<{ count: number }>(\n this.db,\n `SELECT COUNT(*) AS count\n FROM memory_levels ml\n INNER JOIN events e ON e.id = ml.event_id\n WHERE ml.level != 'L0' AND ${notActiveQuarantinedSql('e.metadata')}`\n );\n let curatedLessons = 0;\n try {\n const curated = sqliteGet<{ count: number }>(\n this.db,\n projectHash\n ? `SELECT COUNT(*) AS count FROM memory_lessons WHERE source_class = 'curated' AND project_hash = ?`\n : `SELECT COUNT(*) AS count FROM memory_lessons WHERE source_class = 'curated'`,\n projectHash ? [projectHash] : []\n );\n curatedLessons = Number(curated?.count ?? 0);\n } catch {\n // Older/read-only stores may predate the source_class migration.\n }\n\n return {\n graduation: {\n attempts: Number(attempts?.count ?? 0),\n lastAttemptAt: latest?.finished_at ?? null,\n lastSuccessAt: latestSuccessful?.finished_at ?? null,\n lastStatus,\n lastErrorCategory: lastStatus === 'failed' ? 'graduation_failed' : null\n },\n sources: {\n graduatedEvents: Number(graduatedEvents?.count ?? 0),\n curatedLessons\n }\n };\n }\n\n /**\n * Get memory level for a specific event\n */\n async getEventLevel(eventId: string): Promise<string | null> {\n await this.initialize();\n\n const row = sqliteGet<{ level: string }>(\n this.db,\n `SELECT level FROM memory_levels WHERE event_id = ?`,\n [eventId]\n );\n\n return row ? row.level : null;\n }\n\n /**\n * Get sync position for a target\n */\n async getSyncPosition(targetName: string): Promise<{ lastEventId: string | null; lastTimestamp: string | null }> {\n await this.initialize();\n\n const row = sqliteGet<{ last_event_id: string | null; last_timestamp: string | null }>(\n this.db,\n `SELECT last_event_id, last_timestamp FROM sync_positions WHERE target_name = ?`,\n [targetName]\n );\n\n return {\n lastEventId: row?.last_event_id ?? null,\n lastTimestamp: row?.last_timestamp ?? null\n };\n }\n\n /**\n * Update sync position for a target\n */\n async updateSyncPosition(targetName: string, lastEventId: string, lastTimestamp: string): Promise<void> {\n await this.initialize();\n\n sqliteRun(\n this.db,\n `INSERT OR REPLACE INTO sync_positions (target_name, last_event_id, last_timestamp, updated_at)\n VALUES (?, ?, ?, datetime('now'))`,\n [targetName, lastEventId, lastTimestamp]\n );\n }\n\n /**\n * Get config value for endless mode\n */\n async getEndlessConfig(key: string): Promise<unknown | null> {\n await this.initialize();\n\n const row = sqliteGet<{ value: string }>(\n this.db,\n `SELECT value FROM endless_config WHERE key = ?`,\n [key]\n );\n\n if (!row) return null;\n return JSON.parse(row.value);\n }\n\n /**\n * Set config value for endless mode\n */\n async setEndlessConfig(key: string, value: unknown): Promise<void> {\n await this.initialize();\n\n sqliteRun(\n this.db,\n `INSERT OR REPLACE INTO endless_config (key, value, updated_at)\n VALUES (?, ?, datetime('now'))`,\n [key, JSON.stringify(value)]\n );\n }\n\n /**\n * Increment access count for events\n */\n /**\n * Increment access counters for injected memories.\n *\n * Accepts typed references so a lesson id can no longer be used to update\n * `events.access_count` \u2014 that write matched no row and silently lost the\n * access signal for every lesson (specs R1). Bare strings stay supported for\n * callers that only ever hold event ids.\n */\n async incrementAccessCount(refs: Array<string | { kind: MemoryKind; id: string }>): Promise<void> {\n if (refs.length === 0 || this.readOnly) return;\n\n await this.initialize();\n\n // Each reference is counted against the table that actually owns it. A\n // lesson id never matched a row in `events`, so those writes were lost\n // entirely before the kind travelled with the reference (specs R1).\n const typed = refs\n .map((ref) => (typeof ref === 'string' ? { kind: 'event' as MemoryKind, id: ref } : ref))\n .filter((ref) => Boolean(ref?.id));\n const eventIds = Array.from(new Set(typed\n .filter((ref) => normalizeMemoryKind(ref.kind) === 'event')\n .map((ref) => ref.id)));\n const lessonIds = Array.from(new Set(typed\n .filter((ref) => normalizeMemoryKind(ref.kind) === 'lesson')\n .map((ref) => ref.id)));\n const currentTime = toSQLiteTimestamp(new Date());\n\n if (eventIds.length > 0) {\n sqliteRun(\n this.db,\n `UPDATE events\n SET access_count = access_count + 1,\n last_accessed_at = ?\n WHERE id IN (${eventIds.map(() => '?').join(',')})`,\n [currentTime, ...eventIds]\n );\n }\n if (lessonIds.length > 0 && this.hasTableColumn('memory_lessons', 'access_count')) {\n sqliteRun(\n this.db,\n `UPDATE memory_lessons\n SET access_count = access_count + 1,\n last_accessed_at = ?\n WHERE lesson_id IN (${lessonIds.map(() => '?').join(',')})`,\n [currentTime, ...lessonIds]\n );\n }\n }\n\n /**\n * Get most accessed memories (falls back to recent events if none accessed)\n */\n async getMostAccessed(limit: number = 10, options?: QuarantineReadOptions): Promise<MemoryEvent[]> {\n await this.initialize();\n\n // First try events with access_count > 0\n let rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM events\n WHERE access_count > 0\n AND ${maybeQuarantinePredicate(options)}\n ORDER BY access_count DESC, last_accessed_at DESC\n LIMIT ?`,\n [limit]\n );\n\n // Fallback: if no accessed events, show recent events\n if (rows.length === 0) {\n rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM events\n WHERE ${maybeQuarantinePredicate(options)}\n ORDER BY timestamp DESC\n LIMIT ?`,\n [limit]\n );\n }\n\n return rows.map(row => this.rowToEvent(row));\n }\n\n /**\n * Record a memory retrieval for helpfulness tracking\n */\n async recordRetrieval(\n eventId: string,\n sessionId: string,\n score: number,\n query: string,\n options?: {\n traceId?: string;\n source?: string;\n injectedContent?: string;\n /** Typed kind of the recorded memory. Defaults to `event`. */\n memoryKind?: MemoryKind;\n memoryProjectId?: string | null;\n /**\n * Delivery is not assumed. Selection records `formatted`; only a caller\n * with output evidence upgrades it via recordDeliveryOutcome (specs R3).\n */\n deliveryStatus?: DeliveryStatus;\n deliveryEvidence?: DeliveryEvidenceSource;\n } & RetrievalTelemetryContext\n ): Promise<void> {\n if (this.readOnly) return;\n await this.initialize();\n\n const id = randomUUID();\n // created_at needs millisecond precision: datetime('now') is second-only,\n // so the triggering prompt (stored moments earlier with an ISO ms\n // timestamp in the same second) would count as \"after\" the retrieval.\n sqliteRun(\n this.db,\n `INSERT INTO memory_helpfulness (\n id, event_id, session_id, retrieval_score, query_preview, trace_id, source,\n injected_content, memory_kind, delivery_status, delivery_evidence,\n presentation_mode, trigger_type, delivery_client, created_at, memory_project_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n [\n id, eventId, sessionId, score, query.slice(0, 200),\n options?.traceId || null,\n options?.source || 'user_prompt',\n options?.injectedContent ? options.injectedContent.slice(0, 2000) : null,\n normalizeMemoryKind(options?.memoryKind ?? 'event'),\n normalizeDeliveryStatus(options?.deliveryStatus ?? 'formatted'),\n normalizeDeliveryEvidence(options?.deliveryEvidence ?? 'context_formatted'),\n normalizeRetrievalPresentationMode(options?.presentationMode),\n normalizeRetrievalTriggerType(options?.triggerType),\n normalizeTelemetryClient(options?.deliveryClient),\n new Date().toISOString(),\n options?.memoryProjectId?.trim() || null\n ]\n );\n }\n\n /**\n * Record what actually happened to a delivery after selection (specs R3).\n *\n * Selection alone never sets delivered=true. A hook that successfully wrote\n * its context to stdout reports `emitted`; a write failure reports `failed`;\n * anything unobserved stays `unknown`. \"Emitted\" is not \"the model read it\" \u2014\n * only an explicit consumer acknowledgement is `acknowledged`.\n */\n async recordDeliveryOutcome(input: {\n traceId: string;\n status: DeliveryStatus;\n evidence: DeliveryEvidenceSource;\n deliveredAt?: Date;\n /** Omitted updates the whole trace; an empty list updates no items. */\n refs?: Array<{ kind: MemoryKind; id: string; projectId?: string | null }>;\n }): Promise<number> {\n if (input.refs?.length === 0) return 0;\n if (this.readOnly) return 0;\n await this.initialize();\n const traceId = input.traceId?.trim();\n if (!traceId) return 0;\n const status = normalizeDeliveryStatus(input.status);\n const evidence = normalizeDeliveryEvidence(input.evidence);\n const deliveredAt = (input.deliveredAt ?? new Date()).toISOString();\n const hasPositiveDelivery = deliveredFromStatus(status) === true;\n\n // A ref filter matches on kind *and* id. Filtering by id alone would move\n // the delivery status of an event that merely shares an id with the lesson\n // the caller actually delivered (finding 3).\n const hasHelpfulnessKind = this.hasTableColumn('memory_helpfulness', 'memory_kind');\n const params: unknown[] = [status, evidence, hasPositiveDelivery ? 1 : 0, deliveredAt, traceId];\n let refFilter = '';\n if (input.refs && input.refs.length > 0) {\n if (hasHelpfulnessKind) {\n refFilter = ` AND (${input.refs.map(() => `(event_id = ? AND COALESCE(memory_kind, 'event') = ? AND memory_project_id IS ?)`).join(' OR ')})`;\n for (const ref of input.refs) params.push(ref.id, normalizeMemoryKind(ref.kind), ref.projectId ?? null);\n } else {\n refFilter = ` AND event_id IN (${input.refs.map(() => '?').join(',')})`;\n params.push(...input.refs.map((ref) => ref.id));\n }\n }\n // Keep any already-evaluated observation consistent with the new evidence\n // rather than leaving a stale assumed value behind. The same ref scope\n // applies: updating every row of the trace would rewrite the delivery state\n // of items this call says nothing about.\n const delivered = deliveredFromStatus(status);\n const observationParams: unknown[] = [\n status, evidence, delivered === null ? null : delivered ? 1 : 0,\n traceId, CURRENT_USEFULNESS_EVALUATOR_VERSION\n ];\n let observationFilter = '';\n if (input.refs && input.refs.length > 0) {\n observationFilter = ` AND event_id IN (${input.refs.map(() => '?').join(',')})`;\n observationParams.push(...input.refs.map((ref) => usefulnessRowKey(normalizeMemoryKind(ref.kind), ref.id, ref.projectId)));\n }\n // Commit both representations together so a failed observation update\n // cannot leave navigation and usefulness reporting different delivery states.\n return this.runInImmediateTransaction(() => {\n if (retrievalRollout().usefulnessV3Write) {\n const deliveredValue = delivered === null ? null : delivered ? 1 : 0;\n // An evaluation based on different delivery evidence is stale, even\n // after its old window closed. Queue it for normal session evaluation\n // and clear derived claims until that evaluation has run.\n sqliteRun(this.db,\n `UPDATE memory_helpfulness SET measured_at = NULL\n WHERE trace_id = ?${refFilter} AND EXISTS (\n SELECT 1 FROM memory_usefulness_observations_v2 o\n WHERE o.trace_id = memory_helpfulness.trace_id\n AND o.event_id = ${usefulnessRowKeySql('memory_helpfulness')}\n AND o.evaluator_version = ? AND o.delivered IS NOT ?\n )`,\n [traceId, ...params.slice(5), CURRENT_USEFULNESS_EVALUATOR_VERSION, deliveredValue]);\n sqliteRun(this.db,\n `UPDATE memory_usefulness_observations_v2\n SET adoption = ?, task_outcome = 'unknown', content_overlap_score = NULL,\n reask_outcome = 'unknown', confidence = 0, evaluated_at = NULL, evaluation_cutoff = NULL\n WHERE trace_id = ? AND evaluator_version = ?${observationFilter} AND delivered IS NOT ?`,\n [delivered === false ? 'not_observed' : 'unknown', traceId,\n CURRENT_USEFULNESS_EVALUATOR_VERSION, ...observationParams.slice(5), deliveredValue]);\n }\n const result = sqliteRun(\n this.db,\n `UPDATE memory_helpfulness\n SET delivery_status = ?, delivery_evidence = ?,\n delivered_at = CASE WHEN ? = 1 THEN COALESCE(delivered_at, ?) ELSE delivered_at END\n WHERE trace_id = ?${refFilter}`,\n params\n );\n if (retrievalRollout().usefulnessV3Write) {\n sqliteRun(\n this.db,\n `UPDATE memory_usefulness_observations_v2\n SET delivery_status = ?, delivery_evidence = ?, delivered = ?\n WHERE trace_id = ? AND evaluator_version = ?${observationFilter}`,\n observationParams\n );\n }\n return Number(result?.changes ?? 0);\n });\n }\n\n /**\n * Get session IDs that have unevaluated retrievals (measured_at IS NULL).\n * Excludes the current session. Used to backfill sessions that ended without Stop hook.\n */\n async getUnevaluatedSessions(currentSessionId: string, limit = 5): Promise<string[]> {\n await this.initialize();\n const rows = sqliteAll<{ session_id: string }>(\n this.db,\n `SELECT DISTINCT session_id FROM memory_helpfulness\n WHERE measured_at IS NULL AND session_id != ?\n ORDER BY created_at DESC LIMIT ?`,\n [currentSessionId, limit]\n );\n return rows.map((r) => r.session_id);\n }\n\n /**\n * Evaluate helpfulness for all retrievals in a session\n * Called at session end - uses behavioral signals to compute score\n */\n async evaluateSessionHelpfulness(sessionId: string): Promise<void> {\n if (this.readOnly) return;\n await this.initialize();\n\n // Get all retrieval records for this session\n const retrievals = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM memory_helpfulness WHERE session_id = ? AND measured_at IS NULL`,\n [sessionId]\n );\n\n if (retrievals.length === 0) return;\n await this.evaluateRetrievalRows(sessionId, retrievals);\n }\n\n /**\n * Re-evaluate deliveries whose observation window had not closed yet when the\n * session was first evaluated (specs R3).\n *\n * A session that ends immediately after an injection is evaluated with only\n * the responses that existed at that moment; the 30-minute adoption window is\n * still open. This bounded pass revisits exactly those rows once the window\n * has actually elapsed, so a late response is not permanently recorded as\n * \"not observed\". It never widens the window and never re-scores a delivery\n * whose window was already complete.\n */\n async reevaluateBoundedUsefulness(options: {\n limit?: number;\n now?: Date;\n windowMs?: number;\n } = {}): Promise<{ sessionsReevaluated: number; rowsReevaluated: number; windowMs: number; cutoff: string }> {\n const windowMs = options.windowMs ?? USEFULNESS_V2_EVALUATION_WINDOW_MS;\n const now = options.now ?? new Date();\n const summary = { sessionsReevaluated: 0, rowsReevaluated: 0, windowMs, cutoff: now.toISOString() };\n if (this.readOnly) return summary;\n await this.initialize();\n if (!this.hasTableColumn('memory_usefulness_observations_v2', 'evaluation_cutoff')) return summary;\n\n const limit = Math.min(Math.max(options.limit ?? 200, 1), 5_000);\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT mh.* ${this.boundedReevaluationFromWhereSql()}\n ORDER BY mh.created_at ASC\n LIMIT ?`,\n [CURRENT_USEFULNESS_EVALUATOR_VERSION, now.toISOString(), limit]\n );\n if (rows.length === 0) return summary;\n\n const bySession = new Map<string, Record<string, unknown>[]>();\n for (const row of rows) {\n const sessionId = String(row.session_id || '');\n if (!sessionId) continue;\n const list = bySession.get(sessionId) ?? [];\n list.push(row);\n bySession.set(sessionId, list);\n }\n for (const [sessionId, sessionRows] of bySession) {\n await this.evaluateRetrievalRows(sessionId, sessionRows, { evaluatedAt: now });\n summary.sessionsReevaluated += 1;\n summary.rowsReevaluated += sessionRows.length;\n }\n return summary;\n }\n\n /**\n * Shared FROM/WHERE for the bounded re-evaluation pass: rows evaluated before\n * their adoption window closed, whose window has since elapsed.\n *\n * The window opens when the memory was actually delivered, not when it was\n * selected: a delivery recorded late (or never emitted) must not have its\n * adoption window measured from the selection instant (specs R3, finding 4).\n * Parameters, in order: evaluator version, \"now\".\n */\n private boundedReevaluationFromWhereSql(): string {\n const anchorSql = this.hasTableColumn('memory_helpfulness', 'delivered_at')\n ? `COALESCE(mh.delivered_at, mh.created_at)`\n : `mh.created_at`;\n return `FROM memory_helpfulness mh\n JOIN memory_usefulness_observations_v2 o\n ON o.trace_id = COALESCE(mh.trace_id, 'legacy:' || mh.id)\n AND o.event_id = ${usefulnessRowKeySql('mh')}\n AND o.evaluator_version = ?\n WHERE mh.measured_at IS NOT NULL\n AND o.evaluation_cutoff IS NOT NULL\n AND o.evaluation_window_ms IS NOT NULL\n -- window was still open at evaluation time ... (the 1ms slack keeps\n -- julianday's floating-point rounding from re-queuing a row whose\n -- cutoff already sits exactly on the window end)\n AND julianday(o.evaluation_cutoff) < julianday(${anchorSql}) + ((o.evaluation_window_ms - 1) / 86400000.0)\n -- ... and it has since elapsed\n AND julianday(?) >= julianday(${anchorSql}) + (o.evaluation_window_ms / 86400000.0)`;\n }\n\n /**\n * How many rows the bounded pass would revisit right now. Read-only, so a\n * scheduled job can preview its work without writing anything (specs R3).\n */\n async countPendingBoundedUsefulness(options: { now?: Date } = {}): Promise<{ pendingRows: number; cutoff: string }> {\n await this.initialize();\n const now = options.now ?? new Date();\n const cutoff = now.toISOString();\n if (!this.hasTable('memory_usefulness_observations_v2')\n || !this.hasTableColumn('memory_usefulness_observations_v2', 'evaluation_cutoff')) {\n return { pendingRows: 0, cutoff };\n }\n const row = sqliteGet<{ pending: number }>(\n this.db,\n `SELECT COUNT(*) AS pending ${this.boundedReevaluationFromWhereSql()}`,\n [CURRENT_USEFULNESS_EVALUATOR_VERSION, cutoff]\n );\n return { pendingRows: Number(row?.pending ?? 0), cutoff };\n }\n\n private async evaluateRetrievalRows(\n sessionId: string,\n retrievals: Record<string, unknown>[],\n options: { evaluatedAt?: Date } = {}\n ): Promise<void> {\n // Get session events to analyze behavior after retrieval\n const sessionEvents = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM events WHERE session_id = ? ORDER BY timestamp ASC`,\n [sessionId]\n );\n\n const promptEvents = sessionEvents.filter((e: any) => e.event_type === 'user_prompt');\n const toolEvents = sessionEvents.filter((e: any) => e.event_type === 'tool_observation');\n const responseEvents = sessionEvents.filter((e: any) => e.event_type === 'agent_response');\n\n // Look up the injected memories' content once so each retrieval can be\n // checked for content grounding against the responses that followed it.\n // Only event-kind rows can be hydrated from the events table; a lesson row\n // relies on its stored injected excerpt (specs R1).\n const retrievedEventIds = Array.from(new Set(retrievals\n .filter((r) => normalizeMemoryKind(r.memory_kind ?? 'event') === 'event')\n .map((r) => r.event_id as string)\n .filter(Boolean)));\n const memoryContentById = new Map<string, string>();\n for (let i = 0; i < retrievedEventIds.length; i += 100) {\n const chunk = retrievedEventIds.slice(i, i + 100);\n const rows = sqliteAll<{ id: string; content: string }>(\n this.db,\n `SELECT id, content FROM events WHERE id IN (${chunk.map(() => '?').join(',')})`,\n chunk\n );\n for (const row of rows) memoryContentById.set(row.id, row.content);\n }\n\n // Events store ISO timestamps while memory_helpfulness.created_at uses\n // SQLite datetime('now') (\"YYYY-MM-DD HH:MM:SS\", UTC). Comparing the raw\n // strings marks any same-day event as \"after\", so compare epoch millis.\n const toEpochMs = (value: unknown): number => {\n const raw = String(value || '');\n const iso = raw.includes('T') ? raw : `${raw.replace(' ', 'T')}Z`;\n const ms = new Date(iso).getTime();\n return Number.isFinite(ms) ? ms : 0;\n };\n\n for (const retrieval of retrievals) {\n // Adoption is measured from the moment the memory was actually delivered.\n // Before that instant nothing could have used it, and a delivery that was\n // never emitted has no anchor at all (specs R3, finding 4).\n const selectedAtMs = toEpochMs(retrieval.created_at);\n const deliveredAtMs = retrieval.delivered_at ? toEpochMs(retrieval.delivered_at) : 0;\n const retrievalTimeMs = deliveredAtMs > 0 ? deliveredAtMs : selectedAtMs;\n\n // 1. Session continued after retrieval?\n const eventsAfter = sessionEvents.filter((e: any) => toEpochMs(e.timestamp) > retrievalTimeMs);\n const sessionContinued = eventsAfter.length > 0 ? 1 : 0;\n\n // 2. How many prompts came after?\n const promptsAfter = promptEvents.filter((e: any) => toEpochMs(e.timestamp) > retrievalTimeMs);\n const promptCountAfter = promptsAfter.length;\n const toolOutcomesAfter = toolEvents\n .filter((e: any) => toEpochMs(e.timestamp) > retrievalTimeMs)\n .map((event) => parseToolOutcome(event.content));\n const measuredToolOutcomes = toolOutcomesAfter.filter((outcome) => outcome !== 'unknown');\n const toolSuccessCount = measuredToolOutcomes.filter((outcome) => outcome === 'success').length;\n const toolTotalCount = measuredToolOutcomes.length;\n const toolSuccessRatio = toolTotalCount > 0 ? toolSuccessCount / toolTotalCount : 0.5;\n\n // 3. Was a similar query asked again? (simple word overlap check)\n const queryWords = new Set((retrieval.query_preview as string || '').toLowerCase().split(/\\s+/).filter(w => w.length > 2));\n let wasReasked = 0;\n for (const p of promptsAfter) {\n const pWords = new Set((p.content as string).toLowerCase().split(/\\s+/).filter((w: string) => w.length > 2));\n let overlap = 0;\n for (const w of queryWords) {\n if (pWords.has(w)) overlap++;\n }\n if (queryWords.size > 0 && overlap / queryWords.size > 0.5) {\n wasReasked = 1;\n break;\n }\n }\n\n // 4. Content grounding: did the assistant responses after this\n // retrieval actually reuse the memory's content? This is the most\n // direct usefulness signal we have \u2014 the behavioral signals below\n // only approximate it.\n const responsesAfter = responseEvents\n .filter((e: any) => toEpochMs(e.timestamp) > retrievalTimeMs)\n .map((e: any) => ({ id: e.id as string, content: e.content as string, timestamp: e.timestamp }));\n // Grounding must be checked against what was actually injected into the\n // prompt (hooks truncate memories), not the full stored event \u2014 otherwise\n // facts the model never saw would count as \"used\". Full content is the\n // fallback for legacy rows recorded before the snapshot column existed.\n const memoryContent = (retrieval.injected_content as string)\n || memoryContentById.get(retrieval.event_id as string)\n || '';\n const presentationMode = normalizeRetrievalPresentationMode(retrieval.presentation_mode);\n let contentOverlapScore: number | null = null;\n let evidenceMatches: EvidenceMatch[] = [];\n if (presentationMode !== 'reference' && responsesAfter.length > 0 && memoryContent) {\n const evidence = computeMemoryUsageEvidence(memoryContent, responsesAfter);\n contentOverlapScore = evidence.contentOverlapScore;\n evidenceMatches = evidence.matches;\n }\n\n const v2WindowEndMs = retrievalTimeMs + USEFULNESS_V2_EVALUATION_WINDOW_MS;\n const evaluatedAt = options.evaluatedAt ?? new Date();\n const evaluationCutoffMs = Math.min(evaluatedAt.getTime(), v2WindowEndMs);\n const v2PromptsAfter = promptsAfter.filter((event) => toEpochMs(event.timestamp) <= evaluationCutoffMs);\n const v2ToolOutcomesAfter = toolEvents\n .filter((event) => {\n const eventTimeMs = toEpochMs(event.timestamp);\n return eventTimeMs > retrievalTimeMs && eventTimeMs <= evaluationCutoffMs;\n })\n .map((event) => parseToolOutcome(event.content));\n const v2ResponsesAfter = responsesAfter.filter((event) => toEpochMs(event.timestamp) <= evaluationCutoffMs);\n const v2Evidence = presentationMode !== 'reference' && v2ResponsesAfter.length > 0 && memoryContent\n ? computeMemoryUsageEvidence(memoryContent, v2ResponsesAfter)\n : null;\n const v2ContentOverlapScore = v2Evidence?.contentOverlapScore ?? null;\n\n // Kind-aware: an open of lesson X must not count as an open of the event\n // that happens to share its id (specs R1). A row whose own kind is\n // `unknown` (written before the typed columns existed) cannot narrow\n // anything, so it matches on id alone rather than excluding itself.\n const retrievalKind = normalizeMemoryKind(retrieval.memory_kind);\n const navigationKindClause = retrievalKind !== 'unknown'\n && this.hasTableColumn('retrieval_navigation_events', 'memory_kind')\n ? ` AND COALESCE(memory_kind, 'event') = ? AND memory_project_id IS ?`\n : '';\n const referenceOpened = presentationMode === 'reference' && Boolean(retrieval.trace_id) && Boolean(\n sqliteGet<{ opened: number }>(\n this.db,\n `SELECT 1 AS opened\n FROM retrieval_navigation_events\n WHERE trace_id = ? AND target_event_id = ? AND attribution_outcome = 'attributed'${navigationKindClause}\n AND julianday(first_opened_at) >= julianday(?)\n AND julianday(first_opened_at) <= julianday(?)\n LIMIT 1`,\n [...(navigationKindClause\n ? [retrieval.trace_id, retrieval.event_id, retrievalKind, retrieval.memory_project_id ?? null]\n : [retrieval.trace_id, retrieval.event_id]),\n new Date(retrievalTimeMs).toISOString(), new Date(evaluationCutoffMs).toISOString()]\n )\n );\n // Distinguish \"the reference was not opened\" from \"we cannot attribute\n // opens at all\": without a trace link no navigation can ever be\n // attributed to this delivery, so absence proves nothing (specs R3).\n const referenceAttributable = presentationMode === 'reference' && Boolean(retrieval.trace_id);\n\n // Calculate helpfulness score\n // Weights tuned for shopping-assistant-like corpora where sessions\n // continue on the same topic (was_reasked was over-penalising normal conversation flow)\n const retrievalScore = retrieval.retrieval_score as number || 0;\n // More prompts after retrieval = memory was actually useful to the conversation\n const promptNorm = Math.min(promptCountAfter / 2, 1.0);\n // When content grounding is measurable it dominates the score; the\n // legacy behavioral-only formula remains the fallback (e.g. session\n // ended right after retrieval, so no responses followed).\n // A reference index is navigation, not evidence. Absence of copied text\n // must not make it unhelpful: a deterministic open is positive and an\n // unopened reference remains neutral. Citation use is not inferred.\n const helpfulnessScore = presentationMode === 'reference'\n ? (referenceOpened ? 1 : 0.5)\n : contentOverlapScore !== null\n ? (\n 0.45 * contentOverlapScore +\n 0.20 * Math.min(retrievalScore, 1.0) +\n 0.15 * promptNorm +\n 0.10 * toolSuccessRatio +\n 0.10 * (sessionContinued ? 1.0 : 0.0)\n )\n : (\n 0.40 * Math.min(retrievalScore, 1.0) +\n 0.30 * promptNorm +\n 0.20 * toolSuccessRatio +\n 0.10 * (sessionContinued ? 1.0 : 0.0)\n );\n\n sqliteRun(\n this.db,\n `UPDATE memory_helpfulness\n SET session_continued = ?, prompt_count_after = ?,\n tool_success_count = ?, tool_total_count = ?,\n was_reasked = ?, helpfulness_score = ?,\n content_overlap_score = ?, evidence_json = ?,\n measured_at = datetime('now')\n WHERE id = ?`,\n [sessionContinued, promptCountAfter, toolSuccessCount, toolTotalCount,\n wasReasked, helpfulnessScore,\n contentOverlapScore,\n evidenceMatches.length > 0 ? JSON.stringify(evidenceMatches) : null,\n retrieval.id]\n );\n\n const triggerType = normalizeRetrievalTriggerType(retrieval.trigger_type ?? retrieval.source);\n const adoption = presentationMode === 'reference'\n ? (referenceOpened ? 'navigated' : referenceAttributable ? 'not_observed' : 'unknown')\n : presentationMode === 'evidence'\n ? (v2ContentOverlapScore === null ? 'unknown' : v2ContentOverlapScore >= 0.3 ? 'grounded' : 'not_observed')\n : 'unknown';\n // Delivery comes from recorded evidence only. A selection that was\n // formatted but never observed leaving the process stays unknown.\n const deliveryStatus = normalizeDeliveryStatus(retrieval.delivery_status);\n const deliveryEvidence = normalizeDeliveryEvidence(retrieval.delivery_evidence);\n const delivered = deliveredFromStatus(deliveryStatus);\n // Adoption requires delivery evidence. Text overlap in a later response\n // cannot be attributed to a memory that was only formatted, or whose\n // write failed: the model never saw it. Those stay `unknown` rather than\n // becoming grounded (or a \"task success\") on an assumption (specs R3,\n // finding 11). A `failed` delivery is a real observation of non-adoption.\n const evidencedAdoption: UsefulnessAdoption = delivered === true\n ? adoption\n : delivered === false\n ? 'not_observed'\n : 'unknown';\n await this.upsertUsefulnessObservationV2(buildUsefulnessObservationV2({\n traceId: String(retrieval.trace_id || `legacy:${retrieval.id}`),\n eventId: String(retrieval.event_id),\n memoryKind: normalizeMemoryKind(retrieval.memory_kind),\n memoryProjectId: (retrieval.memory_project_id as string | null | undefined) ?? null,\n presentationMode,\n triggerType,\n delivered,\n deliveryStatus,\n deliveryEvidence,\n adoption: evidencedAdoption,\n contentOverlapScore: presentationMode === 'evidence' ? v2ContentOverlapScore : null,\n toolOutcomes: v2ToolOutcomesAfter,\n reaskOutcome: classifyReaskOutcome(\n retrieval.query_preview,\n v2PromptsAfter.map((event) => event.content)\n ),\n evaluatedAt: evaluatedAt.toISOString(),\n evaluationWindowMs: USEFULNESS_V2_EVALUATION_WINDOW_MS,\n // The cutoff is what this evaluation could actually see. When it falls\n // short of the window end, reevaluateBoundedUsefulness revisits the row.\n evaluationCutoff: new Date(Math.min(evaluatedAt.getTime(), v2WindowEndMs)).toISOString()\n }));\n }\n }\n\n async upsertUsefulnessObservationV2(input: MemoryUsefulnessObservationV2): Promise<void> {\n if (this.readOnly) return;\n if (input.evaluatorVersion === CURRENT_USEFULNESS_EVALUATOR_VERSION && !retrievalRollout().usefulnessV3Write) return;\n await this.initialize();\n const delivered = input.delivered === null ? null : input.delivered ? 1 : 0;\n const overlapValue = input.contentOverlapScore === null ? null : Number(input.contentOverlapScore);\n const confidenceValue = Number(input.confidence);\n if ((overlapValue !== null && !Number.isFinite(overlapValue)) || !Number.isFinite(confidenceValue)) {\n throw new Error('v2 usefulness observation scores must be finite numbers');\n }\n const overlap = overlapValue === null ? null : Math.max(0, Math.min(1, overlapValue));\n const confidence = Math.max(0, Math.min(1, confidenceValue));\n if (!input.traceId.trim() || !input.eventId.trim() || !input.evaluatorVersion.trim()) {\n throw new Error('v2 usefulness observation requires trace, event, and evaluator version');\n }\n const hasTypedColumns = this.hasTableColumn('memory_usefulness_observations_v2', 'memory_kind');\n const hasMemoryIdColumn = this.hasTableColumn('memory_usefulness_observations_v2', 'memory_id');\n const memoryKind = normalizeMemoryKind(input.memoryKind ?? 'event');\n // Non-event memories are stored under a kind-qualified key. The primary key\n // is (trace_id, event_id, observation_kind, evaluator_version), so a lesson\n // and an event that share an id would otherwise overwrite one another \u2014\n // and an event-table join would claim the lesson row as a dangling event.\n const rowKey = hasTypedColumns && input.evaluatorVersion !== 'v2'\n ? usefulnessRowKey(memoryKind, input.eventId.trim(), input.memoryProjectId)\n : input.eventId.trim();\n const typedColumns = hasTypedColumns\n ? ', memory_kind, delivery_status, delivery_evidence, evaluation_window_ms, evaluation_cutoff'\n + (hasMemoryIdColumn ? ', memory_id, memory_project_id' : '')\n : '';\n const typedPlaceholders = hasTypedColumns\n ? ', ?, ?, ?, ?, ?' + (hasMemoryIdColumn ? ', ?, ?' : '')\n : '';\n const typedUpdates = hasTypedColumns\n ? `,\n memory_kind = excluded.memory_kind,\n delivery_status = excluded.delivery_status,\n delivery_evidence = excluded.delivery_evidence,\n evaluation_window_ms = excluded.evaluation_window_ms,\n evaluation_cutoff = excluded.evaluation_cutoff`\n + (hasMemoryIdColumn\n ? `,\n memory_id = excluded.memory_id,\n memory_project_id = excluded.memory_project_id`\n : '')\n : '';\n const typedValues = hasTypedColumns\n ? [\n memoryKind,\n normalizeDeliveryStatus(input.deliveryStatus),\n normalizeDeliveryEvidence(input.deliveryEvidence),\n typeof input.evaluationWindowMs === 'number' && Number.isFinite(input.evaluationWindowMs)\n ? Math.max(0, Math.floor(input.evaluationWindowMs))\n : null,\n input.evaluationCutoff ?? null,\n ...(hasMemoryIdColumn ? [input.eventId.trim(), input.memoryProjectId ?? null] : [])\n ]\n : [];\n sqliteRun(\n this.db,\n `INSERT INTO memory_usefulness_observations_v2 (\n trace_id, event_id, observation_kind, evaluator_version,\n presentation_mode, trigger_type, selected, delivered, adoption,\n content_overlap_score, task_outcome, reask_outcome, explicit_feedback,\n confidence, evaluated_at${typedColumns}\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?${typedPlaceholders})\n ON CONFLICT(trace_id, event_id, observation_kind, evaluator_version) DO UPDATE SET\n presentation_mode = excluded.presentation_mode,\n trigger_type = excluded.trigger_type,\n selected = excluded.selected,\n delivered = excluded.delivered,\n adoption = excluded.adoption,\n content_overlap_score = excluded.content_overlap_score,\n task_outcome = excluded.task_outcome,\n reask_outcome = excluded.reask_outcome,\n explicit_feedback = excluded.explicit_feedback,\n confidence = excluded.confidence,\n evaluated_at = excluded.evaluated_at${typedUpdates}`,\n [\n input.traceId.trim(), rowKey, 'outcome', input.evaluatorVersion.trim(),\n normalizeRetrievalPresentationMode(input.presentationMode),\n normalizeRetrievalTriggerType(input.triggerType),\n input.selected ? 1 : 0, delivered, input.adoption, overlap,\n input.taskOutcome, input.reaskOutcome, input.explicitFeedback, confidence,\n input.evaluatedAt, ...typedValues\n ]\n );\n }\n\n async getUsefulnessAggregateV2(options: {\n since?: Date;\n until?: Date;\n minimumSample?: number;\n evaluatorVersion?: string;\n includeSessionStart?: boolean;\n } = {}): Promise<UsefulnessAggregateV2> {\n await this.initialize();\n const minimumSample = normalizeUsefulnessMinimumSample(options.minimumSample);\n // Default to the delivery-evidence evaluator. v2 rows assumed delivery, so\n // they are readable on request but never averaged in by default (specs R3).\n const evaluatorVersion = options.evaluatorVersion?.trim() || CURRENT_USEFULNESS_EVALUATOR_VERSION;\n const base = emptyUsefulnessAggregateV2({\n minimumSample,\n evaluatorVersion,\n includeSessionStart: options.includeSessionStart,\n since: options.since,\n until: options.until,\n evaluationWindowMs: USEFULNESS_V2_EVALUATION_WINDOW_MS\n });\n if (!this.hasTable('memory_usefulness_observations_v2')) return base;\n const clauses = ['o.evaluator_version = ?'];\n const params: unknown[] = [evaluatorVersion];\n if (!options.includeSessionStart) clauses.push(`o.trigger_type != 'session_start'`);\n if (options.since) {\n clauses.push('datetime(COALESCE(t.created_at, o.evaluated_at)) >= datetime(?)');\n params.push(options.since.toISOString());\n }\n if (options.until) {\n clauses.push('datetime(COALESCE(t.created_at, o.evaluated_at)) < datetime(?)');\n params.push(options.until.toISOString());\n }\n const hasTypedColumns = this.hasTableColumn('memory_usefulness_observations_v2', 'memory_kind');\n const typedSelect = hasTypedColumns ? ', o.memory_kind, o.delivery_status' : '';\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT o.selected, o.delivered, o.presentation_mode, o.trigger_type, o.adoption, o.task_outcome,\n o.reask_outcome, o.explicit_feedback${typedSelect}\n FROM memory_usefulness_observations_v2 o\n LEFT JOIN retrieval_traces t ON t.trace_id = o.trace_id\n WHERE ${clauses.join(' AND ')}`,\n params\n );\n // Rows written by an evaluator generation that assumed delivery. Counted\n // and shown, never merged into this aggregate's rates.\n const legacyAssumedDeliveryRows = LEGACY_ASSUMED_DELIVERY_EVALUATOR_VERSIONS.includes(\n evaluatorVersion as typeof LEGACY_ASSUMED_DELIVERY_EVALUATOR_VERSIONS[number]\n )\n ? rows.length\n : Number(sqliteGet<{ count: number }>(\n this.db,\n `SELECT COUNT(*) AS count FROM memory_usefulness_observations_v2 o\n LEFT JOIN retrieval_traces t ON t.trace_id = o.trace_id\n WHERE ${clauses.join(' AND ')}`,\n ['v2', ...params.slice(1)]\n )?.count ?? 0);\n const traceClauses: string[] = [];\n const traceParams: unknown[] = [];\n if (!options.includeSessionStart) traceClauses.push(`trigger_type != 'session_start'`);\n if (options.since) {\n traceClauses.push('datetime(created_at) >= datetime(?)');\n traceParams.push(options.since.toISOString());\n }\n if (options.until) {\n traceClauses.push('datetime(created_at) < datetime(?)');\n traceParams.push(options.until.toISOString());\n }\n const traceTotals = this.hasTable('retrieval_traces')\n ? sqliteGet<{ eligible: number; selected: number }>(\n this.db,\n `SELECT COALESCE(SUM(candidate_count), 0) AS eligible,\n COALESCE(SUM(selected_count), 0) AS selected\n FROM retrieval_traces${traceClauses.length > 0 ? ` WHERE ${traceClauses.join(' AND ')}` : ''}`,\n traceParams\n )\n : undefined;\n const observedSelections = rows.filter((row) => Number(row.selected) === 1).length;\n const eligible = Number(traceTotals?.eligible ?? 0) > 0 ? Number(traceTotals?.eligible) : rows.length;\n const selected = Number(traceTotals?.eligible ?? 0) > 0 ? Number(traceTotals?.selected) : observedSelections;\n if (rows.length === 0) {\n return {\n ...base,\n legacyAssumedDeliveryRows,\n eligible,\n selected,\n rates: {\n ...base.rates,\n selectionYield: {\n numerator: selected,\n denominator: eligible,\n unknown: 0,\n value: eligible > 0 ? Math.round((selected / eligible) * 10_000) / 10_000 : null\n }\n }\n };\n }\n\n const observationCount = rows.length;\n const delivered = rows.filter((row) => Number(row.delivered) === 1).length;\n const deliveryUnknown = rows.filter((row) => row.delivered === null || row.delivered === undefined).length;\n // The headline grounding metric is deliberately narrow: evidence-mode\n // injections triggered by a user prompt. session_start has a different\n // delivery shape, and explicit_search / context_pack are tool calls whose\n // \"adoption\" means something else \u2014 averaging them together produced the\n // 9.1% figure the spec rejects in favour of 18.8% (specs \u00A73.4, R3).\n const allEvidenceRows = rows.filter((row) => row.presentation_mode === 'evidence');\n const evidenceRows = allEvidenceRows.filter((row) => row.trigger_type === 'user_prompt');\n const isEvaluatedAdoption = (row: Record<string, unknown>) =>\n row.adoption === 'grounded' || row.adoption === 'not_observed';\n const evidenceEvaluated = evidenceRows.filter(isEvaluatedAdoption).length;\n const evidenceGrounded = evidenceRows.filter((row) => row.adoption === 'grounded').length;\n const evidenceAllTriggersEvaluated = allEvidenceRows.filter(isEvaluatedAdoption).length;\n const evidenceAllTriggersGrounded = allEvidenceRows.filter((row) => row.adoption === 'grounded').length;\n const references = rows.filter((row) => row.presentation_mode === 'reference');\n const referencesNavigated = references.filter((row) => row.adoption === 'navigated').length;\n const referenceUnknown = references.filter((row) => row.adoption === 'unknown').length;\n const referencesEvaluated = references.length - referenceUnknown;\n const taskEvaluated = rows.filter((row) => row.task_outcome !== 'unknown').length;\n const taskSuccessful = rows.filter((row) => row.task_outcome === 'success').length;\n const explicitPositive = rows.filter((row) => row.explicit_feedback === 'positive').length;\n const explicitNegative = rows.filter((row) => row.explicit_feedback === 'negative').length;\n const feedbackEvaluated = explicitPositive + explicitNegative;\n const unknownByDimension = {\n delivery: deliveryUnknown,\n adoption: rows.filter((row) => row.adoption === 'unknown').length,\n taskOutcome: rows.filter((row) => row.task_outcome === 'unknown').length,\n reaskOutcome: rows.filter((row) => row.reask_outcome === 'unknown').length,\n explicitFeedback: observationCount - feedbackEvaluated\n };\n const rate = (numerator: number, denominator: number, unknown: number): UsefulnessRateV2 => ({\n numerator,\n denominator,\n unknown,\n value: denominator > 0 ? Math.round((numerator / denominator) * 10_000) / 10_000 : null\n });\n const deliveryStatusCounts = { ...base.deliveryStatusCounts };\n const selectedByKind = { ...base.selectedByKind };\n for (const row of rows) {\n deliveryStatusCounts[normalizeDeliveryStatus(row.delivery_status)] += 1;\n if (Number(row.selected) === 1) selectedByKind[normalizeMemoryKind(row.memory_kind ?? 'event')] += 1;\n }\n return {\n ...base,\n deliveryStatusCounts,\n selectedByKind,\n legacyAssumedDeliveryRows,\n eligible,\n selected,\n delivered,\n evidenceEvaluated,\n evidenceGrounded,\n evidenceAllTriggers: {\n evaluated: evidenceAllTriggersEvaluated,\n grounded: evidenceAllTriggersGrounded,\n unknown: allEvidenceRows.length - evidenceAllTriggersEvaluated\n },\n referencesEligible: references.length,\n referencesNavigated,\n taskOutcomesEvaluated: taskEvaluated,\n taskOutcomesSuccessful: taskSuccessful,\n explicitPositive,\n explicitNegative,\n unknown: Object.values(unknownByDimension).reduce((sum, count) => sum + count, 0),\n unknownByDimension,\n rates: {\n selectionYield: rate(selected, eligible, 0),\n deliveryRate: rate(delivered, observationCount - deliveryUnknown, deliveryUnknown),\n evidenceGrounding: rate(evidenceGrounded, evidenceEvaluated, evidenceRows.length - evidenceEvaluated),\n referenceNavigation: rate(referencesNavigated, referencesEvaluated, referenceUnknown),\n taskSuccess: rate(taskSuccessful, taskEvaluated, unknownByDimension.taskOutcome),\n explicitPositive: rate(explicitPositive, feedbackEvaluated, unknownByDimension.explicitFeedback)\n },\n sampleState: observationCount >= minimumSample ? 'sufficient' : 'insufficient_sample'\n };\n }\n\n /**\n * Get most helpful memories ranked by helpfulness score\n */\n async getHelpfulMemories(limit: number = 10): Promise<Array<{\n eventId: string;\n summary: string;\n helpfulnessScore: number;\n accessCount: number;\n evaluationCount: number;\n }>> {\n await this.initialize();\n\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT\n mh.event_id,\n AVG(mh.helpfulness_score) as avg_score,\n COUNT(*) as eval_count,\n e.content,\n e.access_count\n FROM memory_helpfulness mh\n JOIN events e ON e.id = mh.event_id\n WHERE mh.measured_at IS NOT NULL\n AND ${notActiveQuarantinedSql('e.metadata')}\n GROUP BY mh.event_id\n ORDER BY avg_score DESC\n LIMIT ?`,\n [limit]\n );\n\n return rows.map(r => ({\n eventId: r.event_id as string,\n summary: (r.content as string).substring(0, 200) + ((r.content as string).length > 200 ? '...' : ''),\n helpfulnessScore: Math.round((r.avg_score as number) * 100) / 100,\n accessCount: (r.access_count as number) || 0,\n evaluationCount: r.eval_count as number\n }));\n }\n\n /**\n * Get helpfulness statistics for dashboard\n */\n async getHelpfulnessStats(since?: Date, until?: Date): Promise<{\n avgScore: number;\n totalEvaluated: number;\n totalRetrievals: number;\n helpful: number;\n neutral: number;\n unhelpful: number;\n contentEvaluated: number;\n avgContentOverlap: number;\n groundedCount: number;\n }> {\n await this.initialize();\n\n const sinceIso = since?.toISOString();\n const untilIso = until?.toISOString();\n const timeClauses: string[] = [];\n const timeParams: string[] = [];\n if (sinceIso) {\n timeClauses.push('datetime(created_at) >= datetime(?)');\n timeParams.push(sinceIso);\n }\n if (untilIso) {\n timeClauses.push('datetime(created_at) < datetime(?)');\n timeParams.push(untilIso);\n }\n const timeWhere = timeClauses.length > 0 ? `WHERE ${timeClauses.join(' AND ')}` : '';\n const evaluatedWhere = timeClauses.length > 0\n ? `WHERE measured_at IS NOT NULL AND ${timeClauses.join(' AND ')}`\n : 'WHERE measured_at IS NOT NULL';\n\n // Read-only dashboards can open legacy DBs where the grounding-column\n // migration never ran; degrade to zeros instead of failing the query.\n const hasGroundingColumns = this.hasTableColumn('memory_helpfulness', 'content_overlap_score');\n const groundingSelect = hasGroundingColumns\n ? `COUNT(content_overlap_score) as content_evaluated,\n AVG(content_overlap_score) as avg_content_overlap,\n SUM(CASE WHEN content_overlap_score >= 0.3 THEN 1 ELSE 0 END) as grounded_count`\n : `0 as content_evaluated, 0 as avg_content_overlap, 0 as grounded_count`;\n\n const stats = sqliteGet<Record<string, unknown>>(\n this.db,\n `SELECT\n AVG(helpfulness_score) as avg_score,\n COUNT(*) as total_evaluated,\n SUM(CASE WHEN helpfulness_score >= 0.7 THEN 1 ELSE 0 END) as helpful,\n SUM(CASE WHEN helpfulness_score >= 0.4 AND helpfulness_score < 0.7 THEN 1 ELSE 0 END) as neutral,\n SUM(CASE WHEN helpfulness_score < 0.4 THEN 1 ELSE 0 END) as unhelpful,\n ${groundingSelect}\n FROM memory_helpfulness\n ${evaluatedWhere}`,\n timeParams\n );\n\n const totalRow = sqliteGet<Record<string, unknown>>(\n this.db,\n `SELECT COUNT(*) as total FROM memory_helpfulness ${timeWhere}`,\n timeParams\n );\n\n return {\n avgScore: Math.round(((stats?.avg_score as number) || 0) * 100) / 100,\n totalEvaluated: (stats?.total_evaluated as number) || 0,\n totalRetrievals: (totalRow?.total as number) || 0,\n helpful: (stats?.helpful as number) || 0,\n neutral: (stats?.neutral as number) || 0,\n unhelpful: (stats?.unhelpful as number) || 0,\n contentEvaluated: (stats?.content_evaluated as number) || 0,\n avgContentOverlap: Math.round(((stats?.avg_content_overlap as number) || 0) * 100) / 100,\n groundedCount: (stats?.grounded_count as number) || 0\n };\n }\n\n /**\n * Aggregate helpfulness by UTC day with one range scan.\n *\n * Both legacy SQLite timestamps (`YYYY-MM-DD HH:mm:ss`) and current ISO\n * timestamps share a sortable `YYYY-MM-DD` prefix. Date-only boundaries\n * therefore preserve compatibility while allowing idx_helpfulness_created_at\n * to serve the range predicate (unlike datetime(created_at)).\n */\n async getHelpfulnessStatsByDay(since: Date, until: Date): Promise<Array<{\n date: string;\n avgScore: number;\n totalEvaluated: number;\n totalRetrievals: number;\n helpful: number;\n neutral: number;\n unhelpful: number;\n }>> {\n await this.initialize();\n const sinceDay = since.toISOString().slice(0, 10);\n const untilDay = until.toISOString().slice(0, 10);\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT\n substr(created_at, 1, 10) AS date,\n AVG(CASE WHEN measured_at IS NOT NULL THEN helpfulness_score END) AS avg_score,\n SUM(CASE WHEN measured_at IS NOT NULL THEN 1 ELSE 0 END) AS total_evaluated,\n COUNT(*) AS total_retrievals,\n SUM(CASE WHEN measured_at IS NOT NULL AND helpfulness_score >= 0.7 THEN 1 ELSE 0 END) AS helpful,\n SUM(CASE WHEN measured_at IS NOT NULL AND helpfulness_score >= 0.4 AND helpfulness_score < 0.7 THEN 1 ELSE 0 END) AS neutral,\n SUM(CASE WHEN measured_at IS NOT NULL AND helpfulness_score < 0.4 THEN 1 ELSE 0 END) AS unhelpful\n FROM memory_helpfulness\n WHERE created_at >= ? AND created_at < ?\n GROUP BY substr(created_at, 1, 10)\n ORDER BY date ASC`,\n [sinceDay, untilDay]\n );\n\n return rows.map((row) => ({\n date: String(row.date || ''),\n avgScore: Math.round(((row.avg_score as number) || 0) * 100) / 100,\n totalEvaluated: (row.total_evaluated as number) || 0,\n totalRetrievals: (row.total_retrievals as number) || 0,\n helpful: (row.helpful as number) || 0,\n neutral: (row.neutral as number) || 0,\n unhelpful: (row.unhelpful as number) || 0\n }));\n }\n\n /**\n * Per-question usefulness history: each retrieval query (or session-start\n * injection batch) with the memories it injected, their measured\n * helpfulness, content grounding, and evidence snippets. Powers the\n * dashboard's evidence-history drill-down.\n */\n async getUsefulnessHistory(options: {\n limit?: number;\n offset?: number;\n sessionId?: string;\n withSelectionsOnly?: boolean;\n } = {}): Promise<Array<{\n traceId: string | null;\n kind: 'query' | 'session_start';\n sessionId: string | null;\n question: string;\n queryText: string | null;\n strategy: string | null;\n confidence: string | null;\n candidateCount: number;\n selectedCount: number;\n createdAt: Date;\n memories: Array<{\n eventId: string;\n eventType: string | null;\n summary: string;\n retrievalScore: number;\n helpfulnessScore: number | null;\n contentOverlapScore: number | null;\n evidence: EvidenceMatch[];\n measuredAt: string | null;\n source: string;\n presentationMode: RetrievalPresentationMode;\n }>;\n presentationMode: RetrievalPresentationMode;\n }>> {\n await this.initialize();\n\n const limit = Math.min(Math.max(options.limit ?? 20, 1), 100);\n const offset = Math.max(options.offset ?? 0, 0);\n\n // Read-only dashboards can open legacy DBs where the trace-link migration\n // (trace_id/source columns) never ran; fall back to trace-only history.\n const hasTraceLink = this.hasTableColumn('memory_helpfulness', 'trace_id');\n const hasTraceTrigger = this.hasTableColumn('retrieval_traces', 'trigger_type');\n const hasTracePresentation = this.hasTableColumn('retrieval_traces', 'presentation_mode');\n const traceKindSql = hasTraceTrigger\n ? `CASE WHEN trigger_type = 'session_start' THEN 'session_start' ELSE 'query' END`\n : `'query'`;\n\n const sessionFilterTrace = options.sessionId ? `AND session_id = ?` : '';\n const selectionFilter = options.withSelectionsOnly ? `AND selected_count > 0` : '';\n const params: unknown[] = [];\n if (options.sessionId) params.push(options.sessionId);\n if (hasTraceLink && options.sessionId) params.push(options.sessionId);\n params.push(limit, offset);\n\n // Unified, paginated timeline of \"questions\": retrieval traces plus\n // session-start injection batches (which have no retrieval_traces row).\n const sessionStartBranch = hasTraceLink\n ? `UNION ALL\n SELECT 'session_start' AS kind,\n COALESCE(trace_id, 'ss-' || session_id) AS id,\n session_id,\n MIN(created_at) AS created_at\n FROM memory_helpfulness\n WHERE source = 'session_start'\n AND (trace_id IS NULL OR NOT EXISTS (\n SELECT 1 FROM retrieval_traces rt WHERE rt.trace_id = memory_helpfulness.trace_id\n )) ${sessionFilterTrace}\n GROUP BY COALESCE(trace_id, 'ss-' || session_id), session_id`\n : '';\n const heads = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM (\n SELECT ${traceKindSql} AS kind, trace_id AS id, session_id, created_at\n FROM retrieval_traces\n WHERE 1=1 ${sessionFilterTrace} ${selectionFilter}\n ${sessionStartBranch}\n )\n ORDER BY created_at DESC\n LIMIT ? OFFSET ?`,\n params\n );\n\n const entries: Array<{\n traceId: string | null;\n kind: 'query' | 'session_start';\n sessionId: string | null;\n question: string;\n queryText: string | null;\n strategy: string | null;\n confidence: string | null;\n candidateCount: number;\n selectedCount: number;\n createdAt: Date;\n memories: Array<{\n eventId: string;\n eventType: string | null;\n summary: string;\n retrievalScore: number;\n helpfulnessScore: number | null;\n contentOverlapScore: number | null;\n evidence: EvidenceMatch[];\n measuredAt: string | null;\n source: string;\n presentationMode: RetrievalPresentationMode;\n }>;\n presentationMode: RetrievalPresentationMode;\n }> = [];\n\n for (const head of heads) {\n const kind = head.kind as 'query' | 'session_start';\n const headId = head.id as string;\n\n let trace: Record<string, unknown> | undefined;\n if (!headId.startsWith('ss-')) {\n trace = sqliteGet<Record<string, unknown>>(\n this.db,\n `SELECT * FROM retrieval_traces WHERE trace_id = ?`,\n [headId]\n );\n if (!trace && kind === 'query') continue;\n }\n\n // Helpfulness rows for this head: primary link via trace_id; legacy\n // fallback matches by session + selected event id within \u00B13 minutes.\n let helpRows: Record<string, unknown>[] = hasTraceLink\n ? sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM memory_helpfulness WHERE trace_id = ? ORDER BY created_at ASC`,\n [headId]\n )\n : [];\n if (helpRows.length === 0 && trace) {\n const selectedIds: string[] = (() => {\n try { return JSON.parse((trace.selected_event_ids as string) || '[]'); } catch { return []; }\n })();\n if (selectedIds.length > 0 && trace.session_id) {\n const legacyOnlyFilter = hasTraceLink ? `AND trace_id IS NULL` : '';\n helpRows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM memory_helpfulness\n WHERE session_id = ? ${legacyOnlyFilter}\n AND event_id IN (${selectedIds.map(() => '?').join(',')})\n AND ABS(strftime('%s', created_at) - strftime('%s', ?)) <= 180\n ORDER BY created_at ASC`,\n [trace.session_id, ...selectedIds, trace.created_at]\n );\n }\n }\n if (kind === 'session_start' && helpRows.length === 0 && !trace) {\n helpRows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM memory_helpfulness\n WHERE source = 'session_start' AND trace_id IS NULL AND session_id = ?\n ORDER BY created_at ASC`,\n [head.session_id]\n );\n }\n\n // Hydrate memory summaries. Lessons are not events: joining every id\n // against `events` rendered each injected lesson as \"no longer\n // available\", which is what made lesson selections look like data loss.\n const hasHelpfulnessKind = this.hasTableColumn('memory_helpfulness', 'memory_kind');\n const kindOf = (row: Record<string, unknown>): MemoryKind =>\n hasHelpfulnessKind ? normalizeMemoryKind(row.memory_kind) : 'event';\n const eventIds = Array.from(new Set(helpRows\n .filter((row) => kindOf(row) === 'event' || kindOf(row) === 'unknown')\n .map((row) => row.event_id as string)\n .filter(Boolean)));\n const lessonIds = Array.from(new Set(helpRows\n .filter((row) => kindOf(row) === 'lesson')\n .map((row) => row.event_id as string)\n .filter(Boolean)));\n const eventById = new Map<string, { content: string; event_type: string }>();\n if (eventIds.length > 0) {\n const rows = sqliteAll<{ id: string; content: string; event_type: string }>(\n this.db,\n `SELECT id, content, event_type FROM events WHERE id IN (${eventIds.map(() => '?').join(',')})`,\n eventIds\n );\n for (const row of rows) eventById.set(row.id, row);\n }\n if (lessonIds.length > 0 && this.hasTable('memory_lessons')) {\n const rows = sqliteAll<{ lesson_id: string; name: string; trigger: string }>(\n this.db,\n `SELECT lesson_id, name, trigger FROM memory_lessons WHERE lesson_id IN (${lessonIds.map(() => '?').join(',')})`,\n lessonIds\n );\n for (const row of rows) {\n eventById.set(row.lesson_id, {\n content: [row.name, row.trigger].filter(Boolean).join(' \u2014 '),\n event_type: 'lesson'\n });\n }\n }\n\n const memories = helpRows.map((row) => {\n const event = eventById.get(row.event_id as string);\n let evidence: EvidenceMatch[] = [];\n try {\n const parsed = JSON.parse((row.evidence_json as string) || '[]');\n if (Array.isArray(parsed)) evidence = parsed;\n } catch { /* legacy/corrupt rows have no evidence */ }\n const summary = event\n ? event.content.substring(0, 240) + (event.content.length > 240 ? '\u2026' : '')\n : '(event no longer available)';\n return {\n eventId: row.event_id as string,\n eventType: event?.event_type ?? null,\n summary,\n retrievalScore: (row.retrieval_score as number) ?? 0,\n helpfulnessScore: row.measured_at ? ((row.helpfulness_score as number) ?? null) : null,\n contentOverlapScore: (row.content_overlap_score as number) ?? null,\n evidence,\n measuredAt: (row.measured_at as string) ?? null,\n source: (row.source as string) || 'user_prompt',\n presentationMode: normalizeRetrievalPresentationMode(row.presentation_mode)\n };\n });\n\n if (trace) {\n entries.push({\n traceId: headId,\n kind,\n sessionId: (trace.session_id as string) ?? null,\n question: kind === 'session_start'\n ? (normalizeRetrievalPresentationMode(trace.presentation_mode) === 'core'\n ? 'Session start \u2014 core memory injected'\n : 'Session start \u2014 recent project context injected')\n : (trace.raw_query_text as string) || (trace.query_text as string) || '',\n queryText: (trace.query_text as string) ?? null,\n strategy: (trace.strategy as string) ?? null,\n confidence: (trace.confidence as string) ?? null,\n candidateCount: (trace.candidate_count as number) ?? 0,\n selectedCount: (trace.selected_count as number) ?? 0,\n createdAt: toDateFromSQLite(trace.created_at as string),\n presentationMode: hasTracePresentation\n ? normalizeRetrievalPresentationMode(trace.presentation_mode)\n : 'unknown',\n memories\n });\n } else {\n entries.push({\n traceId: headId.startsWith('ss-') ? null : headId,\n kind: 'session_start',\n sessionId: (head.session_id as string) ?? null,\n question: 'Session start \u2014 recent project context injected',\n queryText: null,\n strategy: 'session-start',\n confidence: null,\n candidateCount: memories.length,\n selectedCount: memories.length,\n createdAt: toDateFromSQLite(head.created_at as string),\n presentationMode: 'unknown',\n memories\n });\n }\n }\n\n return entries;\n }\n\n /**\n * Fast keyword search using FTS5\n * Returns events matching the search query, ranked by relevance\n */\n async keywordSearch(\n query: string,\n limit: number = 10,\n options?: { includeToolObservations?: boolean }\n ): Promise<Array<{event: MemoryEvent; rank: number}>> {\n await this.initialize();\n\n // tool_observation events typically outnumber prompts/answers several-fold\n // (they are kept as events but excluded from embedding), so an unfiltered\n // FTS query returns mostly raw tool output and crowds answer-type events\n // out of the limit window. Excluded by default to mirror the embedding\n // policy; callers that intentionally want tool evidence (episode seeding,\n // explicit eventType filters) opt in.\n const includeToolObservations = options?.includeToolObservations === true;\n const toolObservationSql = includeToolObservations ? '' : `AND e.event_type != 'tool_observation'`;\n\n // Escape special FTS5 characters and prepare search terms\n const searchTerms = query\n .replace(/['\"(){}[\\]^~*?:\\\\/-]/g, ' ') // Remove special chars\n .split(/\\s+/)\n .filter(term => term.length > 1) // Filter short terms\n .map(term => `\"${term}\"*`) // Prefix matching\n .join(' OR ');\n\n if (!searchTerms) {\n return [];\n }\n\n try {\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT e.*, fts.rank\n FROM events_fts fts\n JOIN events e ON e.id = fts.event_id\n WHERE events_fts MATCH ?\n AND ${notActiveQuarantinedSql('e.metadata')}\n ${toolObservationSql}\n ORDER BY fts.rank\n LIMIT ?`,\n [searchTerms, limit]\n );\n\n return rows.map(row => ({\n event: this.rowToEvent(row),\n rank: row.rank as number\n }));\n } catch (error: any) {\n // FTS table might not exist yet (old database)\n // Fallback to LIKE search\n const likePattern = `%${query}%`;\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT *, 0 as rank FROM events\n WHERE content LIKE ?\n AND ${notActiveQuarantinedSql()}\n ${includeToolObservations ? '' : `AND event_type != 'tool_observation'`}\n ORDER BY timestamp DESC\n LIMIT ?`,\n [likePattern, limit]\n );\n\n return rows.map(row => ({\n event: this.rowToEvent(row),\n rank: 0\n }));\n }\n }\n\n /**\n * Dedicated L1+ answer-evidence lane. Graduation alone is not sufficient:\n * prompts and raw tool output can be promoted for continuity, but only final\n * responses/summaries are allowed to compete as direct answer evidence.\n */\n async searchGraduatedEvidence(\n query: string,\n limit: number = 10\n ): Promise<Array<{ event: MemoryEvent; rank: number; level: string; accessCount: number }>> {\n await this.initialize();\n const searchTerms = query\n .replace(/['\"(){}[\\]^~*?:\\\\/-]/g, ' ')\n .split(/\\s+/)\n .filter(term => term.length > 1)\n .map(term => `\"${term}\"*`)\n .join(' OR ');\n if (!searchTerms) return [];\n\n try {\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT e.*, fts.rank, ml.level\n FROM events_fts fts\n JOIN events e ON e.id = fts.event_id\n JOIN memory_levels ml ON ml.event_id = e.id\n WHERE events_fts MATCH ?\n AND ml.level != 'L0'\n AND e.event_type IN ('user_prompt', 'agent_response', 'session_summary')\n AND ${notActiveQuarantinedSql('e.metadata')}\n ORDER BY fts.rank, ml.level DESC, e.access_count DESC\n LIMIT ?`,\n [searchTerms, limit]\n );\n return rows.map((row) => ({\n event: this.rowToEvent(row),\n rank: Number(row.rank),\n level: String(row.level),\n accessCount: Number(row.access_count ?? 0)\n }));\n } catch {\n return [];\n }\n }\n\n /**\n * Rebuild FTS index from existing events\n * Call this once after upgrading to FTS5\n */\n /**\n * Drop and recreate the events_fts virtual table + sync triggers, repopulating\n * from the current events table. Recreating the table (instead of issuing\n * DELETEs against it) sidesteps a quirk where older migrated FTS5 tables fail\n * with `no such column: T.event_id` on synthetic deletes. Safe to call inside\n * a transaction (pure DDL + INSERT...SELECT, no transaction control).\n */\n private recreateEventsFtsTable(): void {\n sqliteExec(this.db, `\n DROP TRIGGER IF EXISTS events_fts_insert;\n DROP TRIGGER IF EXISTS events_fts_delete;\n DROP TRIGGER IF EXISTS events_fts_update;\n DROP TABLE IF EXISTS events_fts;\n\n CREATE VIRTUAL TABLE events_fts USING fts5(\n content,\n event_id UNINDEXED,\n tokenize='porter unicode61'\n );\n\n INSERT INTO events_fts(rowid, content, event_id)\n SELECT rowid, content, id FROM events;\n\n CREATE TRIGGER events_fts_insert AFTER INSERT ON events BEGIN\n INSERT INTO events_fts(rowid, content, event_id) VALUES (NEW.rowid, NEW.content, NEW.id);\n END;\n\n CREATE TRIGGER events_fts_delete AFTER DELETE ON events BEGIN\n DELETE FROM events_fts WHERE rowid = OLD.rowid;\n END;\n\n CREATE TRIGGER events_fts_update AFTER UPDATE ON events BEGIN\n DELETE FROM events_fts WHERE rowid = OLD.rowid;\n INSERT INTO events_fts(rowid, content, event_id) VALUES (NEW.rowid, NEW.content, NEW.id);\n END;\n `);\n }\n\n async rebuildFtsIndex(): Promise<number> {\n await this.initialize();\n\n // Get count of events to index\n const countRow = sqliteGet<{count: number}>(this.db, 'SELECT COUNT(*) as count FROM events', []);\n const totalEvents = countRow?.count ?? 0;\n\n this.recreateEventsFtsTable();\n\n return totalEvents;\n }\n\n /**\n * Get database instance for direct access\n */\n getDatabase(): SQLiteDatabase {\n return this.db;\n }\n\n private hasTableColumn(tableName: string, columnName: string): boolean {\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(tableName)) return false;\n try {\n const rows = sqliteAll<{ name: string }>(this.db, `PRAGMA table_info(\"${tableName}\")`, []);\n return rows.some((row) => row.name === columnName);\n } catch {\n return false;\n }\n }\n\n private hasTable(tableName: string): boolean {\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(tableName)) return false;\n try {\n const rows = sqliteAll<{ name: string }>(\n this.db,\n `SELECT name FROM sqlite_master WHERE type = 'table' AND name = ? LIMIT 1`,\n [tableName]\n );\n return rows.length > 0;\n } catch {\n return false;\n }\n }\n\n /**\n * Add a column only when its table exists and the column is missing.\n *\n * Unlike a blind `try { ALTER } catch {}`, this distinguishes \"already\n * migrated\" / \"table not present yet\" (both safely skipped) from a genuine\n * failure (disk full, corruption), which is allowed to surface instead of\n * being silently swallowed as if the migration had succeeded.\n */\n private addColumnIfMissing(table: string, column: string, definition: string): void {\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(table) || !/^[A-Za-z_][A-Za-z0-9_]*$/.test(column)) {\n throw new Error(`Invalid identifier in migration: ${table}.${column}`);\n }\n if (!this.hasTable(table)) return;\n if (this.hasTableColumn(table, column)) return;\n sqliteExec(this.db, `ALTER TABLE ${table} ADD COLUMN ${column} ${definition};`);\n }\n\n\n async recordRetrievalTrace(input: {\n traceId?: string;\n sessionId?: string;\n projectHash?: string;\n queryText: string;\n rawQueryText?: string;\n queryRewriteKind?: string;\n strategy?: string;\n candidateEventIds: string[];\n selectedEventIds: string[];\n candidateDetails?: Array<{\n eventId: string;\n score: number;\n semanticScore?: number;\n lexicalScore?: number;\n recencyScore?: number;\n lanes?: RetrievalDebugLane[];\n }>;\n selectedDetails?: Array<{\n eventId: string;\n score: number;\n semanticScore?: number;\n lexicalScore?: number;\n recencyScore?: number;\n lanes?: RetrievalDebugLane[];\n }>;\n confidence?: string;\n fallbackTrace?: string[];\n presentationMode?: RetrievalPresentationMode;\n triggerType?: RetrievalTriggerType;\n deliveryClient?: string;\n outcomeDiagnostics?: RetrievalOutcomeDiagnostics;\n /** Typed references (specs R1). Preferred over the id arrays by new readers. */\n items?: RetrievalTraceItemInput[];\n /** Stable id of the caller request; a repeat write updates instead of duplicating. */\n requestId?: string;\n evaluationRunId?: string;\n runtimeVersion?: string;\n }): Promise<string | undefined> {\n if (this.readOnly) return undefined;\n await this.initialize();\n\n const requestId = normalizeRequestId(input.requestId);\n const queryRewriteKind = normalizeQueryRewriteKind(input.queryRewriteKind);\n const candidateDetails = normalizeRetrievalTraceDetails(input.candidateDetails);\n const selectedDetails = normalizeRetrievalTraceDetails(input.selectedDetails);\n // No diagnostics and no selection is \"we did not classify this\", not a\n // runtime failure. `runtime_error` is now written only by a caller that\n // actually caught an exception (specs R2).\n const outcomeDiagnostics = normalizeRetrievalOutcomeDiagnostics(\n input.outcomeDiagnostics,\n input.selectedEventIds.length > 0 ? 'selected' : 'unknown'\n );\n const values = [\n input.sessionId || null,\n input.projectHash || null,\n input.queryText,\n input.rawQueryText || null,\n queryRewriteKind,\n input.strategy || null,\n JSON.stringify(input.candidateEventIds || []),\n JSON.stringify(input.selectedEventIds || []),\n JSON.stringify(candidateDetails),\n JSON.stringify(selectedDetails),\n (input.candidateEventIds || []).length,\n (input.selectedEventIds || []).length,\n input.confidence || null,\n JSON.stringify(input.fallbackTrace || []),\n normalizeRetrievalPresentationMode(input.presentationMode),\n normalizeRetrievalTriggerType(input.triggerType),\n normalizeTelemetryClient(input.deliveryClient),\n outcomeDiagnostics.outcomeReason,\n JSON.stringify(outcomeDiagnostics),\n requestId,\n normalizeRequestId(input.evaluationRunId),\n input.runtimeVersion?.slice(0, 64) || null,\n RETRIEVAL_TELEMETRY_SCHEMA_VERSION\n ];\n\n const updateSql = `UPDATE retrieval_traces SET\n session_id = ?, project_hash = ?, query_text = ?, raw_query_text = ?,\n query_rewrite_kind = ?, strategy = ?, candidate_event_ids = ?, selected_event_ids = ?,\n candidate_details_json = ?, selected_details_json = ?, candidate_count = ?,\n selected_count = ?, confidence = ?, fallback_trace = ?, presentation_mode = ?,\n trigger_type = ?, delivery_client = ?, outcome_reason = ?, retrieval_diagnostics_json = ?,\n request_id = ?, evaluation_run_id = ?, runtime_version = ?, telemetry_schema_version = ?\n WHERE trace_id = ?`;\n const insertSql = `INSERT INTO retrieval_traces (\n session_id, project_hash, query_text, raw_query_text, query_rewrite_kind, strategy,\n candidate_event_ids, selected_event_ids, candidate_details_json, selected_details_json,\n candidate_count, selected_count, confidence, fallback_trace,\n presentation_mode, trigger_type, delivery_client, outcome_reason, retrieval_diagnostics_json,\n request_id, evaluation_run_id, runtime_version, telemetry_schema_version, trace_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`;\n\n // The same request can be traced twice (the orchestrator's automatic trace\n // plus an explicit hook trace). Collapsing on requestId keeps one request\n // equal to one row so client coverage is not double-counted.\n //\n // The lookup and the write run inside one immediate transaction and the\n // request id carries a unique index where the store allows one, so a\n // concurrent writer in another process cannot slip a second row in between\n // the SELECT and the INSERT (finding 9). Where the index could not be\n // created (a store that already holds duplicate request ids), the\n // transaction still serializes this process's own writers.\n const write = (): { traceId: string; replacedExisting: boolean } => {\n const existing = requestId\n ? sqliteGet<{ trace_id: string }>(\n this.db,\n `SELECT trace_id FROM retrieval_traces WHERE request_id = ? LIMIT 1`,\n [requestId]\n )\n : undefined;\n const resolvedTraceId = existing?.trace_id || input.traceId || randomUUID();\n if (existing) {\n sqliteRun(this.db, updateSql, [...values, resolvedTraceId]);\n return { traceId: resolvedTraceId, replacedExisting: true };\n }\n try {\n sqliteRun(this.db, insertSql, [...values, resolvedTraceId]);\n return { traceId: resolvedTraceId, replacedExisting: false };\n } catch (error) {\n // Lost the race against another writer holding the same request id:\n // adopt its row instead of creating a duplicate.\n if (!requestId) throw error;\n const raced = sqliteGet<{ trace_id: string }>(\n this.db,\n `SELECT trace_id FROM retrieval_traces WHERE request_id = ? LIMIT 1`,\n [requestId]\n );\n if (!raced) throw error;\n sqliteRun(this.db, updateSql, [...values, raced.trace_id]);\n return { traceId: raced.trace_id, replacedExisting: true };\n }\n };\n\n return this.runInImmediateTransaction(() => {\n const result = write();\n const hasExistingTypedItems = result.replacedExisting\n && readTraceItems(this.db, result.traceId).length > 0;\n if (retrievalRollout().typedTraceWrite || hasExistingTypedItems) {\n this.writeTypedTraceItems(result.traceId, input, { replaceExisting: result.replacedExisting });\n }\n return result.traceId;\n });\n }\n\n /**\n * Run `fn` inside an IMMEDIATE transaction when the connection allows it.\n *\n * A read-then-write that must stay atomic across processes needs the write\n * lock taken up front. Reuse an existing transaction, but never bypass a\n * failed lock acquisition: the arrays and typed ledger must commit together.\n */\n private runInImmediateTransaction<T>(fn: () => T): T {\n if (this.db.inTransaction) return fn();\n sqliteExec(this.db, 'BEGIN IMMEDIATE');\n try {\n const result = fn();\n sqliteExec(this.db, 'COMMIT');\n return result;\n } catch (error) {\n try {\n sqliteExec(this.db, 'ROLLBACK');\n } catch { /* the transaction was already resolved */ }\n throw error;\n }\n }\n\n /**\n * Persist the typed item rows for a trace. Callers that pass explicit items\n * keep their kinds; otherwise ids are resolved read-only against the local\n * tables so an untyped caller still produces correct rows instead of\n * defaulting every reference to \"event\".\n */\n private writeTypedTraceItems(\n traceId: string,\n input: {\n projectHash?: string;\n candidateEventIds: string[];\n selectedEventIds: string[];\n items?: RetrievalTraceItemInput[];\n },\n options: { replaceExisting?: boolean } = {}\n ): void {\n try {\n const projectId = input.projectHash || null;\n let items: RetrievalTraceItemInput[];\n if (input.items && input.items.length > 0) {\n items = input.items;\n } else {\n const selected = new Set(input.selectedEventIds || []);\n const all = Array.from(new Set([...(input.candidateEventIds || []), ...(input.selectedEventIds || [])]));\n const resolved = resolveMemoryRefKinds(this.db, all, { projectId });\n items = all.map((id, index) => {\n const ref = resolved.get(id);\n return {\n kind: ref?.resolution === 'resolved' ? ref.kind : 'unknown',\n id,\n projectId: ref?.projectId ?? projectId,\n rank: index,\n selected: selected.has(id),\n // Unresolved is not deleted: the row may predate a table or live in\n // a store this process cannot read. `deleted` records an observed\n // deletion only (specs R1).\n deleted: false\n };\n });\n }\n const normalized = normalizeTraceItems(items, { projectId });\n if (options.replaceExisting) {\n // A request-id replay replaces the legacy arrays wholesale. Replace\n // the typed rows wholesale too: the regular UPSERT intentionally keeps\n // selected/deleted monotonic and therefore cannot represent a selected\n // item becoming only a candidate on a corrected replay.\n sqliteRun(this.db, 'DELETE FROM retrieval_trace_items WHERE trace_id = ?', [traceId]);\n }\n writeTraceItems(this.db, traceId, normalized);\n } catch (error) {\n // Let the caller roll back both representations on any ledger failure.\n throw error;\n }\n }\n\n /** Typed references recorded for a trace (specs R1). */\n async getRetrievalTraceItems(traceId: string) {\n await this.initialize();\n return readTraceItems(this.db, traceId);\n }\n\n /**\n * Typed selection totals for a window. Traces written before the typed ledger\n * are resolved read-only; nothing is written by this call.\n */\n async getTypedSelectionSummary(options: { since?: Date; until?: Date; resolveLegacy?: boolean } = {}): Promise<TypedSelectionSummary> {\n await this.initialize();\n return summarizeTypedSelections(this.db, options);\n }\n\n /**\n * Explicit backfill of typed items for legacy traces. Defaults to a dry run;\n * read-only reports never call it.\n */\n async backfillRetrievalTraceItems(options: { dryRun?: boolean; limit?: number; since?: Date } = {}): Promise<TraceItemBackfillResult> {\n await this.initialize();\n if (this.readOnly && options.dryRun === false) {\n throw new Error('retrieval trace item backfill cannot run against a read-only store');\n }\n return options.dryRun === false\n ? this.runInImmediateTransaction(() => backfillTraceItems(this.db, options))\n : backfillTraceItems(this.db, options);\n }\n\n /**\n * Attribute a reference open to a recent reference delivery only when one\n * trace is the unique candidate. The 15-minute window is deliberately\n * bounded; an optional current session makes the boundary stricter. Client\n * labels are recorded for diagnostics but never used to guess attribution.\n * Repeated opens collapse into one row with an incremented count.\n */\n async recordReferenceNavigation(\n input: RecordReferenceNavigationInput\n ): Promise<RecordReferenceNavigationResult> {\n if (this.readOnly) {\n return { outcome: 'unattributed', traceId: null, repeated: false };\n }\n await this.initialize();\n return recordReferenceNavigationOnDb(this.db, input);\n }\n\n /**\n * Per-client instrumentation coverage (specs R2).\n *\n * Only requests this store actually saw can be counted. A client that never\n * writes telemetry has no row here at all, and a client whose rows lack a\n * request id reports coverage `unknown` \u2014 reporting 0% would assert an\n * observation we do not have.\n */\n async getRetrievalClientCoverage(options: { since?: Date; until?: Date } = {}): Promise<RetrievalClientCoverage[]> {\n await this.initialize();\n if (!this.hasTable('retrieval_traces')) return [];\n const hasRequestId = this.hasTableColumn('retrieval_traces', 'request_id');\n const clauses: string[] = [];\n const params: unknown[] = [];\n if (options.since) {\n clauses.push('julianday(created_at) >= julianday(?)');\n params.push(options.since.toISOString());\n }\n if (options.until) {\n clauses.push('julianday(created_at) < julianday(?)');\n params.push(options.until.toISOString());\n }\n const where = clauses.length > 0 ? ` WHERE ${clauses.join(' AND ')}` : '';\n const instrumentedSql = hasRequestId\n ? `COUNT(DISTINCT CASE WHEN request_id IS NOT NULL THEN request_id END)`\n : '0';\n const observedSql = hasRequestId\n ? `COUNT(DISTINCT COALESCE(request_id, trace_id))`\n : `COUNT(DISTINCT trace_id)`;\n const rows = sqliteAll<{ client: string; observed: number; instrumented: number; unknown_client: number }>(\n this.db,\n `SELECT COALESCE(delivery_client, 'unknown') AS client,\n ${observedSql} AS observed,\n ${instrumentedSql} AS instrumented,\n SUM(CASE WHEN delivery_client IS NULL OR delivery_client = 'unknown' THEN 1 ELSE 0 END) AS unknown_client\n FROM retrieval_traces${where}\n GROUP BY COALESCE(delivery_client, 'unknown')\n ORDER BY observed DESC`,\n params\n );\n return rows.map((row) => {\n const observed = Number(row.observed || 0);\n const instrumented = Number(row.instrumented || 0);\n const unobserved = Number(row.unknown_client || 0);\n return {\n client: String(row.client || 'unknown'),\n observedRequests: observed,\n instrumentedRequests: instrumented,\n unobservedOrUnknown: unobserved,\n coverage: observed > 0 && instrumented > 0\n ? Math.round((instrumented / observed) * 10_000) / 10_000\n : null,\n coverageState: observed > 0 && instrumented > 0 ? 'measured' : 'unknown'\n };\n });\n }\n\n /**\n * Per-source ingest clocks and lag (specs R4).\n *\n * `timestamp` is when this store wrote the row; importers additionally keep\n * the original conversation instant. Reporting them per source is what makes\n * an importer backlog visible instead of looking like \"old memories\". Rows\n * whose original instant is unknown are counted, never assumed lag-free.\n */\n async getIngestSourceClocks(options: { since?: Date; until?: Date } = {}): Promise<Array<{\n source: string;\n events: number;\n withSourceClock: number;\n unknownSourceClock: number;\n latestOccurredAt: string | null;\n latestIngestedAt: string | null;\n maxLagMs: number | null;\n medianLagMs: number | null;\n }>> {\n await this.initialize();\n if (!this.hasTable('events')) return [];\n return readIngestSourceClocks(this.db, options);\n }\n\n async getRetrievalTelemetryStats(): Promise<RetrievalTelemetryStats> {\n await this.initialize();\n\n const hasTracePresentation = this.hasTableColumn('retrieval_traces', 'presentation_mode');\n const hasTraceTrigger = this.hasTableColumn('retrieval_traces', 'trigger_type');\n const hasHelpfulnessTable = Boolean(sqliteGet<{ name: string }>(\n this.db,\n `SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'memory_helpfulness'`\n ));\n const hasHelpfulnessPresentation = hasHelpfulnessTable\n && this.hasTableColumn('memory_helpfulness', 'presentation_mode');\n const hasNavigationTable = Boolean(sqliteGet<{ name: string }>(\n this.db,\n `SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'retrieval_navigation_events'`\n ));\n const presentationSql = hasTracePresentation\n ? \"COALESCE(NULLIF(TRIM(presentation_mode), ''), 'unknown')\"\n : \"'unknown'\";\n const triggerSql = hasTraceTrigger\n ? \"COALESCE(NULLIF(TRIM(trigger_type), ''), 'unknown')\"\n : \"'unknown'\";\n\n const presentationRows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT ${presentationSql} AS label, COUNT(*) AS trace_count,\n COALESCE(SUM(selected_count), 0) AS item_count\n FROM retrieval_traces GROUP BY ${presentationSql} ORDER BY label ASC`\n );\n const triggerRows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT ${triggerSql} AS label, COUNT(*) AS trace_count,\n COALESCE(SUM(selected_count), 0) AS item_count\n FROM retrieval_traces GROUP BY ${triggerSql} ORDER BY label ASC`\n );\n const deliveryTotals = sqliteGet<Record<string, unknown>>(\n this.db,\n `SELECT COUNT(*) AS trace_count, COALESCE(SUM(selected_count), 0) AS item_count FROM retrieval_traces`\n );\n const legacyUnknownRows = hasHelpfulnessTable\n ? sqliteGet<{ count: number }>(\n this.db,\n hasHelpfulnessPresentation\n ? `SELECT COUNT(*) AS count FROM memory_helpfulness WHERE presentation_mode = 'unknown' OR presentation_mode IS NULL`\n : `SELECT COUNT(*) AS count FROM memory_helpfulness`\n )?.count ?? 0\n : 0;\n\n const evidence = hasHelpfulnessPresentation\n ? sqliteGet<Record<string, unknown>>(\n this.db,\n `SELECT COUNT(content_overlap_score) AS evaluated,\n SUM(CASE WHEN content_overlap_score >= 0.3 THEN 1 ELSE 0 END) AS grounded,\n AVG(content_overlap_score) AS average_overlap\n FROM memory_helpfulness\n WHERE presentation_mode = 'evidence'`\n )\n : undefined;\n const referenceEligible = hasTracePresentation\n ? Number(sqliteGet<{ count: number }>(\n this.db,\n `SELECT COUNT(*) AS count FROM retrieval_traces\n WHERE presentation_mode = 'reference' AND selected_count > 0`\n )?.count ?? 0)\n : 0;\n const navigation = hasNavigationTable\n ? sqliteGet<Record<string, unknown>>(\n this.db,\n `SELECT\n COUNT(DISTINCT CASE WHEN attribution_outcome = 'attributed' THEN trace_id END) AS navigated_traces,\n SUM(CASE WHEN attribution_outcome = 'attributed' THEN open_count ELSE 0 END) AS attributed_opens,\n SUM(CASE WHEN attribution_outcome = 'ambiguous' THEN open_count ELSE 0 END) AS ambiguous_opens,\n SUM(CASE WHEN attribution_outcome = 'unattributed' THEN open_count ELSE 0 END) AS unattributed_opens\n FROM retrieval_navigation_events`\n )\n : undefined;\n const evidenceEvaluated = Number(evidence?.evaluated || 0);\n const evidenceGrounded = Number(evidence?.grounded || 0);\n const navigatedTraces = Number(navigation?.navigated_traces || 0);\n\n return {\n deliveries: {\n totalTraces: Number(deliveryTotals?.trace_count || 0),\n totalItems: Number(deliveryTotals?.item_count || 0),\n byPresentation: presentationRows.map((row) => ({\n presentationMode: normalizeRetrievalPresentationMode(row.label),\n traceCount: Number(row.trace_count || 0),\n deliveredItemCount: Number(row.item_count || 0)\n })),\n byTrigger: triggerRows.map((row) => ({\n triggerType: normalizeRetrievalTriggerType(row.label),\n traceCount: Number(row.trace_count || 0),\n deliveredItemCount: Number(row.item_count || 0)\n })),\n legacyUnknownRows: Number(legacyUnknownRows)\n },\n evidenceGrounding: {\n evaluatedDeliveries: evidenceEvaluated,\n groundedDeliveries: evidenceGrounded,\n groundingRate: evidenceEvaluated > 0 ? evidenceGrounded / evidenceEvaluated : 0,\n averageContentOverlap: Number(evidence?.average_overlap || 0)\n },\n referenceNavigation: {\n eligibleTraces: referenceEligible,\n navigatedTraces,\n navigationRate: referenceEligible > 0 ? navigatedTraces / referenceEligible : 0,\n attributedOpenCount: Number(navigation?.attributed_opens || 0),\n ambiguousOpenCount: Number(navigation?.ambiguous_opens || 0),\n unattributedOpenCount: Number(navigation?.unattributed_opens || 0)\n }\n };\n }\n\n async getRecentRetrievalTraces(limit: number = 50): Promise<Array<{\n traceId: string;\n sessionId?: string;\n projectHash?: string;\n queryText: string;\n rawQueryText?: string;\n queryRewriteKind?: string;\n strategy?: string;\n candidateEventIds: string[];\n selectedEventIds: string[];\n candidateDetails: Array<{\n eventId: string;\n score: number;\n semanticScore?: number;\n lexicalScore?: number;\n recencyScore?: number;\n lanes?: RetrievalDebugLane[];\n }>;\n selectedDetails: Array<{\n eventId: string;\n score: number;\n semanticScore?: number;\n lexicalScore?: number;\n recencyScore?: number;\n lanes?: RetrievalDebugLane[];\n }>;\n candidateCount: number;\n selectedCount: number;\n confidence?: string;\n fallbackTrace: string[];\n presentationMode: RetrievalPresentationMode;\n triggerType: RetrievalTriggerType;\n deliveryClient: string;\n outcomeDiagnostics: RetrievalOutcomeDiagnostics;\n createdAt: Date;\n }>> {\n await this.initialize();\n\n try {\n const userQueryWhere = this.hasTableColumn('retrieval_traces', 'trigger_type')\n ? `WHERE COALESCE(trigger_type, 'unknown') != 'session_start'`\n : '';\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM retrieval_traces ${userQueryWhere} ORDER BY created_at DESC LIMIT ?`,\n [limit]\n );\n\n return rows.map((row) => ({\n traceId: row.trace_id as string,\n sessionId: (row.session_id as string) || undefined,\n projectHash: (row.project_hash as string) || undefined,\n queryText: row.query_text as string,\n rawQueryText: (row.raw_query_text as string) || undefined,\n queryRewriteKind: normalizeQueryRewriteKind(row.query_rewrite_kind as string | null),\n strategy: (row.strategy as string) || undefined,\n candidateEventIds: row.candidate_event_ids ? JSON.parse(row.candidate_event_ids as string) : [],\n selectedEventIds: row.selected_event_ids ? JSON.parse(row.selected_event_ids as string) : [],\n candidateDetails: parseRetrievalTraceDetails(row.candidate_details_json),\n selectedDetails: parseRetrievalTraceDetails(row.selected_details_json),\n candidateCount: Number(row.candidate_count || 0),\n selectedCount: Number(row.selected_count || 0),\n confidence: (row.confidence as string) || undefined,\n fallbackTrace: row.fallback_trace ? JSON.parse(row.fallback_trace as string) : [],\n presentationMode: normalizeRetrievalPresentationMode(row.presentation_mode),\n triggerType: normalizeRetrievalTriggerType(row.trigger_type),\n deliveryClient: normalizeTelemetryClient(row.delivery_client),\n outcomeDiagnostics: parseRetrievalOutcomeDiagnostics(row),\n createdAt: toDateFromSQLite(row.created_at),\n }));\n } catch (err: any) {\n if (err?.message?.includes('no such table')) return [];\n throw err;\n }\n }\n\n async getRetrievalTraceStats(): Promise<{\n totalQueries: number;\n avgCandidateCount: number;\n avgSelectedCount: number;\n selectionRate: number;\n rewrittenQueries: number;\n rewriteRate: number;\n rewrittenQueriesWithSelection: number;\n rawQueriesWithSelection: number;\n rewrittenSelectionRate: number;\n rawSelectionRate: number;\n avgSelectedCountForRewrittenQueries: number;\n avgSelectedCountForRawQueries: number;\n strategyBreakdown: Array<{\n strategy: string;\n totalQueries: number;\n queriesWithSelection: number;\n rewrittenQueries: number;\n rewriteRate: number;\n totalCandidateCount: number;\n totalSelectedCount: number;\n avgCandidateCount: number;\n avgSelectedCount: number;\n selectionRate: number;\n queryYieldRate: number;\n }>;\n }> {\n await this.initialize();\n\n try {\n const rewrittenQueryRewriteKindSql = this.hasTableColumn('retrieval_traces', 'query_rewrite_kind')\n ? REWRITTEN_QUERY_REWRITE_KIND_SQL\n : '0';\n const userQueryWhere = this.hasTableColumn('retrieval_traces', 'trigger_type')\n ? `WHERE COALESCE(trigger_type, 'unknown') != 'session_start'`\n : '';\n const row = sqliteGet<Record<string, unknown>>(\n this.db,\n `SELECT\n COUNT(*) as total_queries,\n AVG(candidate_count) as avg_candidate_count,\n AVG(selected_count) as avg_selected_count,\n SUM(CASE WHEN ${rewrittenQueryRewriteKindSql} THEN 1 ELSE 0 END) as rewritten_queries,\n SUM(CASE WHEN ${rewrittenQueryRewriteKindSql} AND selected_count > 0 THEN 1 ELSE 0 END) as rewritten_queries_with_selection,\n SUM(CASE WHEN NOT (${rewrittenQueryRewriteKindSql}) AND selected_count > 0 THEN 1 ELSE 0 END) as raw_queries_with_selection,\n AVG(CASE WHEN ${rewrittenQueryRewriteKindSql} THEN selected_count END) as avg_selected_count_for_rewritten_queries,\n AVG(CASE WHEN NOT (${rewrittenQueryRewriteKindSql}) THEN selected_count END) as avg_selected_count_for_raw_queries,\n CASE\n WHEN SUM(candidate_count) > 0 THEN (SUM(selected_count) * 1.0 / SUM(candidate_count))\n ELSE 0\n END as selection_rate\n FROM retrieval_traces\n ${userQueryWhere}`,\n []\n );\n\n const strategyColumnSql = this.hasTableColumn('retrieval_traces', 'strategy')\n ? \"COALESCE(NULLIF(TRIM(strategy), ''), 'unknown')\"\n : \"'unknown'\";\n const strategyRows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT\n ${strategyColumnSql} as strategy,\n COUNT(*) as total_queries,\n SUM(CASE WHEN selected_count > 0 THEN 1 ELSE 0 END) as queries_with_selection,\n SUM(CASE WHEN ${rewrittenQueryRewriteKindSql} THEN 1 ELSE 0 END) as rewritten_queries,\n SUM(candidate_count) as total_candidate_count,\n SUM(selected_count) as total_selected_count,\n AVG(candidate_count) as avg_candidate_count,\n AVG(selected_count) as avg_selected_count,\n CASE\n WHEN SUM(candidate_count) > 0 THEN (SUM(selected_count) * 1.0 / SUM(candidate_count))\n ELSE 0\n END as selection_rate\n FROM retrieval_traces\n ${userQueryWhere}\n GROUP BY ${strategyColumnSql}\n ORDER BY total_queries DESC, strategy ASC`,\n []\n );\n\n const strategyBreakdown = strategyRows.map((strategyRow) => {\n const strategyTotalQueries = Number(strategyRow.total_queries || 0);\n const strategyQueriesWithSelection = Number(strategyRow.queries_with_selection || 0);\n const strategyRewrittenQueries = Number(strategyRow.rewritten_queries || 0);\n return {\n strategy: String(strategyRow.strategy || 'unknown'),\n totalQueries: strategyTotalQueries,\n queriesWithSelection: strategyQueriesWithSelection,\n rewrittenQueries: strategyRewrittenQueries,\n rewriteRate: strategyTotalQueries > 0 ? strategyRewrittenQueries / strategyTotalQueries : 0,\n totalCandidateCount: Number(strategyRow.total_candidate_count || 0),\n totalSelectedCount: Number(strategyRow.total_selected_count || 0),\n avgCandidateCount: Number(strategyRow.avg_candidate_count || 0),\n avgSelectedCount: Number(strategyRow.avg_selected_count || 0),\n selectionRate: Number(strategyRow.selection_rate || 0),\n queryYieldRate: strategyTotalQueries > 0 ? strategyQueriesWithSelection / strategyTotalQueries : 0,\n };\n });\n\n const totalQueries = Number(row?.total_queries || 0);\n const rewrittenQueries = Number(row?.rewritten_queries || 0);\n const rawQueries = Math.max(0, totalQueries - rewrittenQueries);\n const rewrittenQueriesWithSelection = Number(row?.rewritten_queries_with_selection || 0);\n const rawQueriesWithSelection = Number(row?.raw_queries_with_selection || 0);\n\n return {\n totalQueries,\n avgCandidateCount: Number(row?.avg_candidate_count || 0),\n avgSelectedCount: Number(row?.avg_selected_count || 0),\n selectionRate: Number(row?.selection_rate || 0),\n rewrittenQueries,\n rewriteRate: totalQueries > 0 ? rewrittenQueries / totalQueries : 0,\n rewrittenQueriesWithSelection,\n rawQueriesWithSelection,\n rewrittenSelectionRate: rewrittenQueries > 0 ? rewrittenQueriesWithSelection / rewrittenQueries : 0,\n rawSelectionRate: rawQueries > 0 ? rawQueriesWithSelection / rawQueries : 0,\n avgSelectedCountForRewrittenQueries: Number(row?.avg_selected_count_for_rewritten_queries || 0),\n avgSelectedCountForRawQueries: Number(row?.avg_selected_count_for_raw_queries || 0),\n strategyBreakdown,\n };\n } catch (err: any) {\n if (err?.message?.includes('no such table')) {\n return {\n totalQueries: 0,\n avgCandidateCount: 0,\n avgSelectedCount: 0,\n selectionRate: 0,\n rewrittenQueries: 0,\n rewriteRate: 0,\n rewrittenQueriesWithSelection: 0,\n rawQueriesWithSelection: 0,\n rewrittenSelectionRate: 0,\n rawSelectionRate: 0,\n avgSelectedCountForRewrittenQueries: 0,\n avgSelectedCountForRawQueries: 0,\n strategyBreakdown: [],\n };\n }\n throw err;\n }\n }\n\n /**\n * Close database connection\n */\n async close(): Promise<void> {\n sqliteClose(this.db);\n }\n\n /**\n * Get events grouped by turn_id for a session\n * Returns turns ordered by first event timestamp (newest first)\n */\n async getSessionTurns(sessionId: string, options?: { limit?: number; offset?: number } & QuarantineReadOptions): Promise<Array<{\n turnId: string;\n events: MemoryEvent[];\n startedAt: Date;\n promptPreview: string;\n eventCount: number;\n toolCount: number;\n hasResponse: boolean;\n }>> {\n await this.initialize();\n\n const limit = options?.limit || 20;\n const offset = options?.offset || 0;\n\n // Get distinct turn_ids for this session, ordered by first event timestamp\n const turnRows = sqliteAll<{ turn_id: string; min_ts: string }>(\n this.db,\n `SELECT turn_id, MIN(timestamp) as min_ts\n FROM events\n WHERE session_id = ? AND turn_id IS NOT NULL\n AND ${maybeQuarantinePredicate(options)}\n GROUP BY turn_id\n ORDER BY min_ts DESC\n LIMIT ? OFFSET ?`,\n [sessionId, limit, offset]\n );\n\n const turns: Array<{\n turnId: string;\n events: MemoryEvent[];\n startedAt: Date;\n promptPreview: string;\n eventCount: number;\n toolCount: number;\n hasResponse: boolean;\n }> = [];\n\n for (const turnRow of turnRows) {\n const events = await this.getEventsByTurn(turnRow.turn_id, options);\n\n const promptEvent = events.find(e => e.eventType === 'user_prompt');\n const toolEvents = events.filter(e => e.eventType === 'tool_observation');\n const hasResponse = events.some(e => e.eventType === 'agent_response');\n\n turns.push({\n turnId: turnRow.turn_id,\n events,\n startedAt: toDateFromSQLite(turnRow.min_ts),\n promptPreview: promptEvent\n ? promptEvent.content.slice(0, 200) + (promptEvent.content.length > 200 ? '...' : '')\n : '(no prompt)',\n eventCount: events.length,\n toolCount: toolEvents.length,\n hasResponse\n });\n }\n\n return turns;\n }\n\n /**\n * Get all events for a specific turn_id\n */\n async getEventsByTurn(turnId: string, options?: QuarantineReadOptions): Promise<MemoryEvent[]> {\n await this.initialize();\n\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM events WHERE turn_id = ? AND ${maybeQuarantinePredicate(options)} ORDER BY timestamp ASC`,\n [turnId]\n );\n\n return rows.map(this.rowToEvent);\n }\n\n /**\n * Count total turns for a session\n */\n async countSessionTurns(sessionId: string, options?: QuarantineReadOptions): Promise<number> {\n await this.initialize();\n\n const row = sqliteGet<{ count: number }>(\n this.db,\n `SELECT COUNT(DISTINCT turn_id) as count\n FROM events\n WHERE session_id = ? AND turn_id IS NOT NULL\n AND ${maybeQuarantinePredicate(options)}`,\n [sessionId]\n );\n\n return row?.count || 0;\n }\n\n /**\n * Migrate existing events: backfill turn_id for events that have turnId in metadata\n * but no turn_id column value (for events stored before this migration)\n */\n async backfillTurnIds(): Promise<number> {\n await this.initialize();\n\n // Find events with turnId in metadata JSON but no turn_id column value\n const rows = sqliteAll<{ id: string; metadata: string }>(\n this.db,\n `SELECT id, metadata FROM events\n WHERE turn_id IS NULL AND metadata IS NOT NULL AND metadata LIKE '%turnId%'`\n );\n\n let updated = 0;\n for (const row of rows) {\n try {\n const metadata = JSON.parse(row.metadata);\n if (metadata.turnId) {\n sqliteRun(\n this.db,\n `UPDATE events SET turn_id = ? WHERE id = ?`,\n [metadata.turnId, row.id]\n );\n updated++;\n }\n } catch {\n // Skip rows with invalid JSON\n }\n }\n\n return updated;\n }\n\n /**\n * Delete a single event and everything keyed to it.\n *\n * Deliberately NOT sharing an implementation with `deleteSessionEvents`: that one deletes\n * by `session_id` so it is independent of how many events the session holds, while this one\n * keys on the id. Folding them into one id-list delete would expose the session path to the\n * SQL variable limit and break large sessions.\n *\n * The trigger-drop -> delete -> FTS-rebuild sequence is the same as the session delete and\n * for the same reason: the synthetic FTS delete can fail (`no such column: T.event_id`) on\n * older migrated tables and risks SQLITE_CORRUPT_VTAB. Running it inside a transaction means\n * a failure rolls back instead of leaving the index permanently desynced from its triggers.\n *\n * Returns whether a row was actually removed, so callers can answer 404 for unknown ids.\n * Vectors live in LanceDB and are not touched here \u2014 callers that need them gone must also\n * call `VectorStore.deleteEventEverywhere` (see the CLI redact path).\n */\n async deleteEventById(eventId: string): Promise<boolean> {\n await this.initialize();\n\n const relatedTables = ['event_dedup', 'memory_levels', 'embedding_queue', 'embedding_outbox', 'vector_outbox', 'event_citations']\n .filter((table) => this.hasTable(table) && this.hasTableColumn(table, 'event_id'));\n\n const runDelete = this.db.transaction((): number => {\n for (const triggerName of ['events_fts_delete', 'events_fts_update', 'events_fts_insert']) {\n sqliteRun(this.db, `DROP TRIGGER IF EXISTS ${triggerName}`);\n }\n\n for (const table of relatedTables) {\n sqliteRun(this.db, `DELETE FROM ${table} WHERE event_id = ?`, [eventId]);\n }\n\n const result = sqliteRun(this.db, `DELETE FROM events WHERE id = ?`, [eventId]);\n\n this.recreateEventsFtsTable();\n\n return result.changes || 0;\n });\n\n return runDelete() > 0;\n }\n\n /**\n * Delete all events for a session (for force reimport)\n */\n async deleteSessionEvents(sessionId: string): Promise<number> {\n await this.initialize();\n\n // Get event IDs first for cascading deletes\n const events = sqliteAll<{ id: string }>(\n this.db,\n `SELECT id FROM events WHERE session_id = ?`,\n [sessionId]\n );\n\n if (events.length === 0) return 0;\n\n const eventIds = events.map(e => e.id);\n const placeholders = eventIds.map(() => '?').join(',');\n\n // Run the trigger-drop -> delete -> FTS-rebuild -> trigger-recreate sequence\n // atomically. Outside a transaction, a crash or error after the triggers are\n // dropped would permanently desync the FTS index, so keyword search would\n // silently return stale results forever. Inside a transaction any failure\n // rolls back and the triggers/index stay consistent. We pre-check optional\n // table existence (instead of swallowing per-statement errors) so a genuine\n // failure is never mistaken for a benign \"table does not exist\".\n // Only the tables that both exist and key cascades on event_id. (vector_outbox\n // keys on item_id, not event_id; the previous code swallowed the resulting\n // error, so it was never cleaned here either \u2014 behavior preserved.)\n const relatedTables = ['event_dedup', 'memory_levels', 'embedding_queue', 'embedding_outbox', 'vector_outbox', 'event_citations']\n .filter((table) => this.hasTable(table) && this.hasTableColumn(table, 'event_id'));\n\n const runDelete = this.db.transaction((): number => {\n // Drop FTS sync triggers before the bulk delete so the synthetic FTS\n // delete (which can fail with `no such column: T.event_id` on older\n // migrated tables, and risks SQLITE_CORRUPT_VTAB) never fires mid-delete.\n for (const triggerName of ['events_fts_delete', 'events_fts_update', 'events_fts_insert']) {\n sqliteRun(this.db, `DROP TRIGGER IF EXISTS ${triggerName}`);\n }\n\n // Delete from related tables first.\n for (const table of relatedTables) {\n sqliteRun(this.db, `DELETE FROM ${table} WHERE event_id IN (${placeholders})`, eventIds);\n }\n\n // Delete events.\n const result = sqliteRun(this.db, `DELETE FROM events WHERE session_id = ?`, [sessionId]);\n\n // Recreate the FTS table + triggers from the remaining events. A failure\n // here aborts the whole transaction rather than leaving the index desynced\n // with its triggers permanently dropped.\n this.recreateEventsFtsTable();\n\n return result.changes || 0;\n });\n\n return runDelete();\n }\n\n /**\n * Convert database row to MemoryEvent\n */\n private rowToEvent(row: Record<string, unknown>): MemoryEvent {\n const event: any = {\n id: row.id as string,\n eventType: row.event_type as 'user_prompt' | 'agent_response' | 'session_summary',\n sessionId: row.session_id as string,\n timestamp: toDateFromSQLite(row.timestamp),\n content: row.content as string,\n canonicalKey: row.canonical_key as string,\n dedupeKey: row.dedupe_key as string,\n metadata: safeParseMetadataValue(row.metadata)\n };\n\n // Include access tracking fields if present\n if (row.access_count !== undefined) {\n event.access_count = row.access_count;\n }\n if (row.last_accessed_at !== undefined) {\n event.last_accessed_at = row.last_accessed_at;\n }\n // Include turn_id if present\n if (row.turn_id !== undefined && row.turn_id !== null) {\n event.turn_id = row.turn_id;\n }\n\n return event;\n }\n}\n", "/**\n * AXIOMMIND canonical_key.py port\n * Deterministic normalization ensuring identical titles always map to same keys\n */\n\nimport { createHash } from 'crypto';\n\nconst MAX_KEY_LENGTH = 200;\n\n/**\n * Convert text to a normalized canonical key\n *\n * Normalization steps:\n * 1. NFKC unicode normalization\n * 2. Lowercase conversion\n * 3. Punctuation removal\n * 4. Consecutive whitespace cleanup\n * 5. Context addition (optional)\n * 6. Long key truncation with MD5\n */\nexport function makeCanonicalKey(\n title: string,\n context?: { project?: string; sessionId?: string }\n): string {\n // Step 1: NFKC normalization\n let normalized = title.normalize('NFKC');\n\n // Step 2: Lowercase conversion\n normalized = normalized.toLowerCase();\n\n // Step 3: Punctuation removal (unicode compatible)\n normalized = normalized.replace(/[^\\p{L}\\p{N}\\s]/gu, '');\n\n // Step 4: Consecutive whitespace cleanup\n normalized = normalized.replace(/\\s+/g, ' ').trim();\n\n // Step 5: Context addition\n let key = normalized;\n if (context?.project) {\n key = `${context.project}::${key}`;\n }\n\n // Step 6: Long key handling\n if (key.length > MAX_KEY_LENGTH) {\n const hashSuffix = createHash('md5').update(key).digest('hex').slice(0, 8);\n key = key.slice(0, MAX_KEY_LENGTH - 9) + '_' + hashSuffix;\n }\n\n return key;\n}\n\n/**\n * Check if two texts have the same canonical key\n */\nexport function isSameCanonicalKey(a: string, b: string): boolean {\n return makeCanonicalKey(a) === makeCanonicalKey(b);\n}\n\n/**\n * Generate dedupe key (content + session for uniqueness)\n * AXIOMMIND Principle 3: Idempotency guarantee\n */\nexport function makeDedupeKey(content: string, sessionId: string): string {\n const contentHash = createHash('sha256').update(content).digest('hex');\n return `${sessionId}:${contentHash}`;\n}\n\n/**\n * Generate content hash for deduplication\n */\nexport function hashContent(content: string): string {\n return createHash('sha256').update(content).digest('hex');\n}\n\n// ============================================================\n// Entity Canonical Keys (Task Entity System)\n// ============================================================\n\nexport type EntityKeyType = 'task' | 'condition' | 'artifact' | 'source_file';\n\n/**\n * Normalize text for entity key generation\n */\nfunction normalizeForKey(text: string): string {\n return text\n .normalize('NFKC')\n .toLowerCase()\n .replace(/[^\\p{L}\\p{N}\\s]/gu, '')\n .replace(/\\s+/g, '_')\n .trim();\n}\n\n/**\n * Generate canonical key for entities\n * Format: {type}:{project}:{normalized_identifier}\n */\nexport function makeEntityCanonicalKey(\n entityType: EntityKeyType,\n identifier: string,\n context?: { project?: string }\n): string {\n const project = context?.project ?? 'default';\n\n switch (entityType) {\n case 'task':\n return `task:${project}:${normalizeForKey(identifier)}`;\n case 'condition':\n return `cond:${project}:${normalizeForKey(identifier)}`;\n case 'artifact':\n return makeArtifactKey(identifier);\n case 'source_file':\n return makeSourceFileKey(identifier, project);\n }\n}\n\n/**\n * Canonical key for a source file entity, scoped by project so the same\n * relative path in two different projects doesn't collide.\n * Format: file:{project}:{sha1(normalized_relative_path)}\n */\nexport function makeSourceFileKey(filePath: string, project = 'default'): string {\n const normalized = normalizeFilePath(filePath);\n const hash = createHash('sha1').update(normalized).digest('hex').slice(0, 16);\n return `file:${project}:${hash}`;\n}\n\n/**\n * Normalize a file path for stable identity across sessions:\n * backslashes to forward slashes, no leading \"./\", no trailing slash.\n */\nexport function normalizeFilePath(filePath: string): string {\n return filePath\n .replace(/\\\\/g, '/')\n .replace(/^\\.\\//, '')\n .replace(/\\/+$/, '');\n}\n\n/**\n * Generate canonical key for artifacts based on identifier pattern\n * - URL: art:url:{sha1(url)}\n * - JIRA key: art:jira:{key}\n * - GitHub issue: art:gh_issue:{repo}:{num}\n * - Generic: art:generic:{sha1(identifier)}\n */\nexport function makeArtifactKey(identifier: string): string {\n // URL pattern\n if (/^https?:\\/\\//.test(identifier)) {\n const hash = createHash('sha1').update(identifier).digest('hex').slice(0, 12);\n return `art:url:${hash}`;\n }\n\n // JIRA key pattern (e.g., PROJ-123)\n const jiraMatch = identifier.match(/^([A-Z]+-\\d+)$/);\n if (jiraMatch) {\n return `art:jira:${jiraMatch[1].toLowerCase()}`;\n }\n\n // GitHub issue pattern (e.g., owner/repo#123)\n const ghMatch = identifier.match(/^([^\\/]+\\/[^#]+)#(\\d+)$/);\n if (ghMatch) {\n return `art:gh_issue:${ghMatch[1]}:${ghMatch[2]}`;\n }\n\n // Generic identifier\n const hash = createHash('sha1').update(identifier).digest('hex').slice(0, 12);\n return `art:generic:${hash}`;\n}\n\n/**\n * Generate dedupe key for task events\n */\nexport function makeTaskEventDedupeKey(\n eventType: string,\n taskId: string,\n sessionId: string,\n additionalContext?: string\n): string {\n const parts = [eventType, taskId, sessionId];\n if (additionalContext) {\n parts.push(additionalContext);\n }\n const combined = parts.join(':');\n return createHash('sha256').update(combined).digest('hex');\n}\n\n/**\n * Parse entity canonical key to extract type and identifier\n */\nexport function parseEntityCanonicalKey(canonicalKey: string): {\n entityType: EntityKeyType;\n project?: string;\n identifier: string;\n} | null {\n const taskMatch = canonicalKey.match(/^task:([^:]+):(.+)$/);\n if (taskMatch) {\n return { entityType: 'task', project: taskMatch[1], identifier: taskMatch[2] };\n }\n\n const condMatch = canonicalKey.match(/^cond:([^:]+):(.+)$/);\n if (condMatch) {\n return { entityType: 'condition', project: condMatch[1], identifier: condMatch[2] };\n }\n\n const artMatch = canonicalKey.match(/^art:([^:]+):(.+)$/);\n if (artMatch) {\n return { entityType: 'artifact', identifier: artMatch[2] };\n }\n\n return null;\n}\n", "/**\n * Citation Generator\n * Generates unique, short citation IDs for memory references\n */\n\nimport { createHash } from 'crypto';\n\nconst ID_LENGTH = 6;\nconst CHARSET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n\n/**\n * Generate a citation ID from an event ID using SHA256\n */\nexport function generateCitationId(eventId: string): string {\n const hash = createHash('sha256')\n .update(eventId)\n .digest();\n\n let id = '';\n for (let i = 0; i < ID_LENGTH; i++) {\n id += CHARSET[hash[i] % CHARSET.length];\n }\n\n return id;\n}\n\n/**\n * Generate a unique citation ID with collision handling\n */\nexport async function generateUniqueCitationId(\n eventId: string,\n existsCheck: (id: string) => Promise<boolean>\n): Promise<string> {\n let id = generateCitationId(eventId);\n let attempt = 0;\n\n while (await existsCheck(id) && attempt < 10) {\n // Add salt and regenerate\n id = generateCitationId(`${eventId}:${attempt}`);\n attempt++;\n }\n\n if (attempt >= 10) {\n throw new Error('Failed to generate unique citation ID after 10 attempts');\n }\n\n return id;\n}\n\n/**\n * Format a citation ID for display\n */\nexport function formatCitationId(citationId: string): string {\n return `[mem:${citationId}]`;\n}\n\n/**\n * Parse a citation ID from formatted string\n */\nexport function parseCitationId(formatted: string): string | null {\n const match = formatted.match(/\\[?mem:([A-Za-z0-9]{6})\\]?/);\n return match ? match[1] : null;\n}\n", "/**\n * Project path registry utilities.\n *\n * These helpers are intentionally core-level and Claude-agnostic.\n */\n\nimport * as crypto from 'crypto';\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\n\nimport { runGit } from './git-utils.js';\n\n/**\n * Normalize and resolve a project path, handling symlinks when possible.\n */\nexport function normalizeProjectPath(projectPath: string): string {\n const expanded = projectPath.startsWith('~')\n ? path.join(os.homedir(), projectPath.slice(1))\n : projectPath;\n\n try {\n return fs.realpathSync(expanded);\n } catch {\n return path.resolve(expanded);\n }\n}\n\n/**\n * Cache of hash basis per normalized path. Git layout does not change within a\n * process run; a marker file can (the README tells users to `touch` it), so a\n * long-lived process (MCP server, dashboard) picks a new marker up only after\n * restart. Hooks are fresh processes and see it immediately.\n */\nconst hashBasisCache = new Map<string, string>();\n\n/**\n * Explicit convergence marker. A workspace product that creates one directory\n * per chat/instance (each often its own git repository) can drop this file at\n * the workspace root so every path beneath it shares one store. Without it,\n * each instance hashes to its own cold store and memory never accumulates\n * across instances.\n */\nexport const MEMORY_ROOT_MARKER = '.claude-memory-root';\n\n/**\n * The marker must be a regular file. A directory of the same name is ignored,\n * and an unreadable path (EACCES on a TCC-protected ancestor, a flaky mount)\n * degrades to \"no marker\" rather than failing resolution.\n */\nfunction markerFileExists(markerPath: string): boolean {\n try {\n return fs.statSync(markerPath, { throwIfNoEntry: false })?.isFile() ?? false;\n } catch {\n return false;\n }\n}\n\n/**\n * Find the nearest ancestor (including the directory itself) that carries the\n * convergence marker. Nearest wins so a nested workspace stays separate from\n * an outer one. Returns null when no marker exists \u2014 the common case, which\n * keeps default behavior untouched.\n *\n * The walk never accepts a marker at the home directory, the system temp\n * directory, or the filesystem root: a stray marker there would silently\n * collapse every project on the machine (or, for the world-writable temp\n * root, let any local process converge other users' temp projects) into one\n * store. Markers strictly below those ceilings are honored.\n */\nfunction findMemoryRootMarker(startDir: string): string | null {\n const ceilings = new Set([\n normalizeProjectPath(os.homedir()),\n normalizeProjectPath(os.tmpdir())\n ]);\n\n let current = startDir;\n for (;;) {\n if (ceilings.has(current) || path.dirname(current) === current) return null;\n if (markerFileExists(path.join(current, MEMORY_ROOT_MARKER))) return current;\n current = path.dirname(current);\n }\n}\n\nfunction computeHashBasisPath(normalizedPath: string): string {\n // Git convergence runs first, then the marker walk starts from the\n // git-resolved basis. This ordering is load-bearing three ways: a worktree\n // checked out outside the marker tree still reaches the marker through its\n // main checkout; a marker committed into a repository (and therefore\n // materialized in every worktree checkout) resolves to the main checkout\n // root instead of splitting each worktree onto a cold store; and a marker\n // in a repository subdirectory cannot detach that subtree from the store\n // the repository has been accumulating. The marker still outranks an\n // instance's *own* .git \u2014 the git basis of such an instance is its checkout\n // root, and the walk climbs from there to the workspace marker above it.\n const gitBasis = resolveGitBasisPath(normalizedPath);\n const markerRoot = findMemoryRootMarker(gitBasis);\n // Re-normalized because the basis may come from the plain path.resolve\n // fallback when the directory does not exist yet, so an existing ancestor\n // carrying the marker can still contain unresolved symlinks.\n return markerRoot !== null ? normalizeProjectPath(markerRoot) : gitBasis;\n}\n\n/** Cache of git-only basis per normalized path, shared by the marker-aware and marker-ignoring resolvers so the git spawn happens once. */\nconst gitBasisCache = new Map<string, string>();\n\nfunction resolveGitBasisPath(normalizedPath: string): string {\n const cached = gitBasisCache.get(normalizedPath);\n if (cached !== undefined) return cached;\n\n const basis = computeGitBasisPath(normalizedPath);\n boundedCacheSet(gitBasisCache, normalizedPath, basis);\n return basis;\n}\n\nfunction computeGitBasisPath(normalizedPath: string): string {\n // One spawn for both values: resolution runs in every short-lived hook\n // process and the git spawn dominates its cost. rev-parse prints results in\n // flag order. A bare repo (a common dir but no work tree) fails\n // --show-toplevel and with it the whole command \u2014 same outcome as the\n // previous separate guard: such a path keeps hashing to itself.\n const output = runGit(normalizedPath, ['rev-parse', '--git-common-dir', '--show-toplevel']);\n if (!output) return normalizedPath;\n const [commonDir, toplevel] = output.split('\\n').map((line) => line.trim());\n if (!commonDir || !toplevel) return normalizedPath;\n\n const absoluteCommonDir = path.isAbsolute(commonDir)\n ? commonDir\n : path.resolve(normalizedPath, commonDir);\n if (path.basename(absoluteCommonDir) !== '.git') return normalizedPath;\n const mainCheckoutRoot = normalizeProjectPath(path.dirname(absoluteCommonDir));\n\n // Every path inside one repository resolves onto the checkout that owns the\n // shared .git \u2014 a worktree, the checkout root, or any subdirectory of it.\n //\n // The root itself already hashes to this value, so existing project hashes\n // are unchanged. Subdirectories converge onto it: a session started from a\n // monorepo package or a vendored tree used to get its own hash, and with it\n // a cold store no other session in the repository could read.\n //\n // A nested repository owns its own .git, so its common dir differs and it\n // stays separate rather than folding into the outer checkout.\n return mainCheckoutRoot;\n}\n\n/**\n * Resolve the path a project hash should be derived from, so that every path\n * belonging to one repository \u2014 worktree, checkout root, or subdirectory \u2014\n * hashes to the main checkout that owns the shared .git. Nested repositories\n * and non-git paths hash to themselves.\n */\nfunction resolveHashBasisPath(normalizedPath: string): string {\n const cached = hashBasisCache.get(normalizedPath);\n if (cached !== undefined) return cached;\n\n const basis = computeHashBasisPath(normalizedPath);\n boundedCacheSet(hashBasisCache, normalizedPath, basis);\n return basis;\n}\n\n/**\n * Long-lived servers hash caller-supplied project strings, so the caches are\n * capped: past the cap they reset rather than grow for the process lifetime.\n * The working set is a handful of project roots, so a reset is a few extra\n * git spawns, not a correctness event.\n */\nconst MAX_PATH_CACHE_ENTRIES = 1_024;\n\nfunction boundedCacheSet(cache: Map<string, string>, key: string, value: string): void {\n if (cache.size >= MAX_PATH_CACHE_ENTRIES) cache.clear();\n cache.set(key, value);\n}\n\n/**\n * Resolve the durable on-disk anchor for per-project artifacts (e.g. the\n * markdown mirror): worktrees and subdirectories anchor onto the main checkout\n * they share a .git with, so artifacts survive worktree removal and land where\n * the project hash already points. Nested repositories and non-git paths\n * anchor onto themselves.\n */\nexport function resolveProjectAnchorPath(projectPath: string): string {\n return resolveHashBasisPath(normalizeProjectPath(projectPath));\n}\n\nfunction hashBasis(basis: string): string {\n return crypto.createHash('sha256')\n .update(basis)\n .digest('hex')\n .slice(0, 8);\n}\n\n/**\n * Generate a stable 8-character hash from a normalized project path.\n */\nexport function hashProjectPath(projectPath: string): string {\n return hashBasis(resolveHashBasisPath(normalizeProjectPath(projectPath)));\n}\n\n/**\n * The hash this path had before any .claude-memory-root marker applied: git\n * convergence only. A store created before a marker was adopted is keyed by\n * exactly this value, so repair and identity tooling use it to tell \"the hash\n * basis changed when the marker arrived\" apart from genuine cross-project\n * contamination.\n */\nexport function hashProjectPathIgnoringMarker(projectPath: string): string {\n return hashBasis(resolveGitBasisPath(normalizeProjectPath(projectPath)));\n}\n\n/**\n * The marker directory governing this path (via its git-resolved basis), or\n * null when no marker applies. Diagnostics use it to show *why* a path\n * converged where it did.\n */\nexport function resolveMemoryRootMarkerPath(projectPath: string): string | null {\n const gitBasis = resolveGitBasisPath(normalizeProjectPath(projectPath));\n const markerRoot = findMemoryRootMarker(gitBasis);\n return markerRoot !== null ? normalizeProjectPath(markerRoot) : null;\n}\n\n/**\n * Get the storage path for a project-local memory database.\n */\nexport function getProjectStoragePath(projectPath: string): string {\n const hash = hashProjectPath(projectPath);\n return path.join(os.homedir(), '.claude-code', 'memory', 'projects', hash);\n}\n\n/**\n * Resolve either an explicit project hash or a project path into a storage path.\n */\nexport function resolveProjectStoragePath(projectOrHash: string): string {\n const isHash = /^[a-f0-9]{8}$/.test(projectOrHash);\n return isHash\n ? path.join(os.homedir(), '.claude-code', 'memory', 'projects', projectOrHash)\n : getProjectStoragePath(projectOrHash);\n}\n", "/**\n * Low-level git helpers shared by project identity resolvers.\n */\n\nimport { execFileSync } from 'node:child_process';\n\n/**\n * These take precedence over `-C <dir>`, so an inherited value would silently\n * resolve a different repository than the one being asked about.\n */\nconst REPO_OVERRIDING_GIT_ENV = ['GIT_DIR', 'GIT_WORK_TREE', 'GIT_COMMON_DIR'];\n\n/** Run a read-only git command in the given directory. Returns trimmed stdout, or null on any failure. */\nexport function runGit(projectPath: string, args: string[]): string | null {\n const env = { ...process.env };\n for (const key of REPO_OVERRIDING_GIT_ENV) delete env[key];\n\n try {\n const output = execFileSync('git', ['-C', projectPath, ...args], {\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n timeout: 1_000,\n env\n }).trim();\n return output || null;\n } catch {\n return null;\n }\n}\n", "import * as fs from 'fs/promises';\nimport * as path from 'path';\nimport type { MemoryEvent } from './types.js';\n\nconst DEFAULT_NAMESPACE = 'default';\nconst DEFAULT_CATEGORY = 'uncategorized';\n\nexport function sanitizeSegment(input: unknown, fallback: string): string {\n const raw = String(input ?? '').trim().toLowerCase();\n const safe = raw\n .normalize('NFKD')\n .replace(/[^a-z0-9_-]+/g, '-')\n .replace(/^-+|-+$/g, '');\n\n if (!safe || safe === '.' || safe === '..') return fallback;\n return safe;\n}\n\nfunction getCategorySegments(metadata: Record<string, unknown> | undefined, eventType: string): string[] {\n const raw = metadata?.categoryPath;\n if (Array.isArray(raw) && raw.length > 0) {\n return raw.map((s) => sanitizeSegment(s, DEFAULT_CATEGORY));\n }\n const single = metadata?.category;\n if (typeof single === 'string' && single.trim()) {\n return [sanitizeSegment(single, DEFAULT_CATEGORY)];\n }\n return [sanitizeSegment(eventType, DEFAULT_CATEGORY)];\n}\n\nexport function buildMirrorPath(rootDir: string, event: MemoryEvent): string {\n const metadata = event.metadata as Record<string, unknown> | undefined;\n const namespace = sanitizeSegment(metadata?.namespace, DEFAULT_NAMESPACE);\n const categories = getCategorySegments(metadata, event.eventType);\n\n const d = event.timestamp;\n const yyyy = d.getFullYear();\n const mm = String(d.getMonth() + 1).padStart(2, '0');\n const dd = String(d.getDate()).padStart(2, '0');\n\n return path.join(rootDir, 'memory', namespace, ...categories, `${yyyy}-${mm}-${dd}.md`);\n}\n\nexport function formatMirrorEntry(event: MemoryEvent): string {\n const category = Array.isArray((event.metadata as any)?.categoryPath)\n ? ((event.metadata as any).categoryPath as unknown[]).join('/')\n : String((event.metadata as any)?.category ?? event.eventType);\n\n return [\n '',\n `- ts: ${event.timestamp.toISOString()}`,\n ` id: ${event.id}`,\n ` type: ${event.eventType}`,\n ` session: ${event.sessionId}`,\n ` category: ${category}`,\n ' content: |',\n ...event.content.split('\\n').map((line) => ` ${line}`)\n ].join('\\n') + '\\n';\n}\n\nexport class MarkdownMirror {\n constructor(private readonly rootDir: string) {}\n\n async append(event: MemoryEvent): Promise<string> {\n const outPath = buildMirrorPath(this.rootDir, event);\n await fs.mkdir(path.dirname(outPath), { recursive: true });\n await fs.appendFile(outPath, formatMirrorEntry(event), 'utf8');\n return outPath;\n }\n}\n", "/**\n * SQLite Database Wrapper\n * Provides Promise-based interface over better-sqlite3 synchronous API\n */\n\nimport BetterSqlite3 from 'better-sqlite3';\n\nexport type Database = BetterSqlite3.Database;\n\n/**\n * Safely converts a value to a Date object\n */\nexport function toDate(value: unknown): Date {\n if (value instanceof Date) return value;\n if (typeof value === 'string') return new Date(value);\n if (typeof value === 'number') return new Date(value);\n return new Date(String(value));\n}\n\nexport interface DatabaseOptions {\n readOnly?: boolean;\n}\n\n/**\n * Creates a new SQLite database connection.\n *\n * Applies the same connection pragmas as the primary sqlite-wrapper so handles\n * opened here don't fall back to rollback-journal mode with a 0ms busy timeout \u2014\n * which would throw SQLITE_BUSY the instant another process (vector worker,\n * mongo sync, or a second handle to the same file) holds a write lock.\n */\nexport function createDatabase(dbPath: string, options?: DatabaseOptions): Database {\n const db = new BetterSqlite3(dbPath, { readonly: options?.readOnly ?? false });\n db.pragma('busy_timeout = 5000');\n if (!options?.readOnly) {\n db.pragma('journal_mode = WAL');\n db.pragma('synchronous = NORMAL');\n }\n return db;\n}\n\n/**\n * Executes a statement that doesn't return rows\n */\nexport function dbRun(db: Database, sql: string, params: unknown[] = []): Promise<void> {\n db.prepare(sql).run(...(params as never[]));\n return Promise.resolve();\n}\n\n/**\n * Executes a query and returns all rows\n */\nexport function dbAll<T = Record<string, unknown>>(\n db: Database,\n sql: string,\n params: unknown[] = []\n): Promise<T[]> {\n return Promise.resolve(db.prepare(sql).all(...(params as never[])) as T[]);\n}\n\n/**\n * Closes the database connection\n */\nexport function dbClose(db: Database): Promise<void> {\n db.close();\n return Promise.resolve();\n}\n\n/**\n * Executes multiple statements\n */\nexport function dbExec(db: Database, sql: string): Promise<void> {\n db.exec(sql);\n return Promise.resolve();\n}\n", "/**\n * Vector Outbox V2 - Transactional Outbox Pattern\n * AXIOMMIND Principle 6: DuckDB \u2192 outbox \u2192 LanceDB unidirectional flow\n */\n\nimport { dbRun, dbAll, toDate, type Database } from './db-wrapper.js';\nimport { randomUUID } from 'crypto';\nimport type {\n OutboxJob,\n OutboxStatus,\n OutboxItemKind\n} from './types.js';\n\nexport interface OutboxConfig {\n embeddingVersion: string;\n maxRetries: number;\n stuckThresholdMs: number;\n cleanupDays: number;\n}\n\nconst DEFAULT_CONFIG: OutboxConfig = {\n embeddingVersion: 'v1',\n maxRetries: 3,\n stuckThresholdMs: 5 * 60 * 1000, // 5 minutes\n cleanupDays: 7\n};\n\nexport interface OutboxMetrics {\n pendingCount: number;\n processingCount: number;\n doneCount: number;\n failedCount: number;\n oldestPendingAge: number | null;\n}\n\nfunction isRetryableLanceCommitConflict(error: string): boolean {\n const normalized = error.toLowerCase();\n return normalized.includes('lance')\n && normalized.includes('commit')\n && normalized.includes('conflict');\n}\n\nexport interface OutboxEnqueueInput {\n itemKind: OutboxItemKind;\n itemId: string;\n embeddingVersion?: string;\n}\n\nexport type EnqueueResult =\n | { success: true; jobId: string; isNew: boolean }\n | { success: false; error: string };\n\nexport class VectorOutbox {\n private config: OutboxConfig;\n\n constructor(\n private db: Database,\n config?: Partial<OutboxConfig>\n ) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n }\n\n /**\n * Enqueue item for vectorization (idempotent).\n * Returns the already-existing job id when the same item/version has been enqueued before.\n */\n enqueueSync(\n itemKind: OutboxItemKind,\n itemId: string,\n embeddingVersion?: string\n ): string {\n const result = this.enqueueWithResultSync({ itemKind, itemId, embeddingVersion });\n if (result.success === false) {\n throw new Error(result.error);\n }\n return result.jobId;\n }\n\n async enqueue(\n itemKind: OutboxItemKind,\n itemId: string,\n embeddingVersion?: string\n ): Promise<string> {\n return this.enqueueSync(itemKind, itemId, embeddingVersion);\n }\n\n enqueueBatchSync(inputs: OutboxEnqueueInput[]): EnqueueResult[] {\n return inputs.map((input) => this.enqueueWithResultSync(input));\n }\n\n async enqueueBatch(inputs: OutboxEnqueueInput[]): Promise<EnqueueResult[]> {\n return this.enqueueBatchSync(inputs);\n }\n\n enqueueWithResultSync(input: OutboxEnqueueInput): EnqueueResult {\n const version = input.embeddingVersion ?? this.config.embeddingVersion;\n const jobId = randomUUID();\n const now = new Date().toISOString();\n\n try {\n const result = this.db.prepare(`INSERT INTO vector_outbox (\n job_id, item_kind, item_id, embedding_version, status, retry_count, created_at, updated_at\n ) VALUES (?, ?, ?, ?, 'pending', 0, ?, ?)\n ON CONFLICT (item_kind, item_id, embedding_version) DO NOTHING`).run(\n jobId,\n input.itemKind,\n input.itemId,\n version,\n now,\n now\n );\n\n const row = this.db.prepare(`SELECT job_id FROM vector_outbox\n WHERE item_kind = ? AND item_id = ? AND embedding_version = ?`).get(\n input.itemKind,\n input.itemId,\n version\n ) as { job_id: string } | undefined;\n\n if (!row) {\n return { success: false, error: 'vector outbox enqueue did not create or find a job' };\n }\n\n return { success: true, jobId: row.job_id, isNew: Number(result.changes ?? 0) > 0 };\n } catch (error) {\n return { success: false, error: error instanceof Error ? error.message : String(error) };\n }\n }\n\n async enqueueWithResult(input: OutboxEnqueueInput): Promise<EnqueueResult> {\n return this.enqueueWithResultSync(input);\n }\n\n /**\n * Claim pending jobs for processing\n */\n async claimJobs(limit: number = 32): Promise<OutboxJob[]> {\n const now = new Date().toISOString();\n\n // Atomic claim using UPDATE RETURNING\n const rows = await dbAll<Record<string, unknown>>(\n this.db,\n `UPDATE vector_outbox\n SET status = 'processing', updated_at = ?\n WHERE job_id IN (\n SELECT job_id FROM vector_outbox\n WHERE status = 'pending'\n ORDER BY created_at ASC\n LIMIT ?\n )\n RETURNING *`,\n [now, limit]\n );\n\n return rows.map(row => this.rowToJob(row));\n }\n\n /**\n * Mark job as done\n */\n async markDone(jobId: string): Promise<void> {\n await dbRun(\n this.db,\n `UPDATE vector_outbox\n SET status = 'done', updated_at = ?\n WHERE job_id = ?`,\n [new Date().toISOString(), jobId]\n );\n }\n\n /**\n * Mark job as failed\n */\n async markFailed(jobId: string, error: string): Promise<void> {\n const now = new Date().toISOString();\n\n // Check retry count\n const rows = await dbAll<{ retry_count: number }>(\n this.db,\n `SELECT retry_count FROM vector_outbox WHERE job_id = ?`,\n [jobId]\n );\n\n if (rows.length === 0) return;\n\n const retryCount = rows[0].retry_count;\n\n if (isRetryableLanceCommitConflict(error)) {\n await dbRun(\n this.db,\n `UPDATE vector_outbox\n SET status = 'pending', error = ?, updated_at = ?\n WHERE job_id = ?`,\n [error, now, jobId]\n );\n return;\n }\n\n const newStatus: OutboxStatus = retryCount >= this.config.maxRetries - 1\n ? 'failed'\n : 'pending'; // Will retry\n\n await dbRun(\n this.db,\n `UPDATE vector_outbox\n SET status = ?, error = ?, retry_count = retry_count + 1, updated_at = ?\n WHERE job_id = ?`,\n [newStatus, error, now, jobId]\n );\n }\n\n /**\n * Get job by ID\n */\n async getJob(jobId: string): Promise<OutboxJob | null> {\n const rows = await dbAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM vector_outbox WHERE job_id = ?`,\n [jobId]\n );\n\n if (rows.length === 0) return null;\n return this.rowToJob(rows[0]);\n }\n\n /**\n * Get jobs by status\n */\n async getJobsByStatus(status: OutboxStatus, limit: number = 100): Promise<OutboxJob[]> {\n const rows = await dbAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM vector_outbox\n WHERE status = ?\n ORDER BY created_at ASC\n LIMIT ?`,\n [status, limit]\n );\n\n return rows.map(row => this.rowToJob(row));\n }\n\n /**\n * Reconcile: recover stuck and retry failed jobs\n */\n async reconcile(referenceTime: Date = new Date()): Promise<{ recovered: number; retried: number }> {\n const stuckThreshold = new Date(referenceTime.getTime() - this.config.stuckThresholdMs);\n const nowIso = referenceTime.toISOString();\n\n // Recover stuck processing jobs\n const recovered = this.db.prepare(`UPDATE vector_outbox\n SET status = 'pending', updated_at = ?, error = NULL\n WHERE status = 'processing'\n AND updated_at < ?`).run(nowIso, stuckThreshold.toISOString());\n\n // Retry failed jobs that haven't exceeded max retries\n const retried = this.db.prepare(`UPDATE vector_outbox\n SET status = 'pending', updated_at = ?, error = NULL\n WHERE status = 'failed'\n AND retry_count < ?`).run(nowIso, this.config.maxRetries);\n\n return {\n recovered: Number(recovered.changes ?? 0),\n retried: Number(retried.changes ?? 0)\n };\n }\n\n /**\n * Cleanup old done jobs\n */\n async cleanup(referenceTime: Date = new Date()): Promise<number> {\n const threshold = new Date(referenceTime.getTime() - this.config.cleanupDays * 24 * 60 * 60 * 1000);\n\n const result = this.db.prepare(`DELETE FROM vector_outbox\n WHERE status = 'done'\n AND updated_at < ?`).run(threshold.toISOString());\n\n return Number(result.changes ?? 0);\n }\n\n /**\n * Get metrics\n */\n async getMetrics(): Promise<OutboxMetrics> {\n const statusCounts = await dbAll<{ status: string; count: number }>(\n this.db,\n `SELECT status, COUNT(*) as count\n FROM vector_outbox\n GROUP BY status`\n );\n\n const oldestPending = await dbAll<{ created_at: string }>(\n this.db,\n `SELECT created_at FROM vector_outbox\n WHERE status = 'pending'\n ORDER BY created_at ASC\n LIMIT 1`\n );\n\n const metrics: OutboxMetrics = {\n pendingCount: 0,\n processingCount: 0,\n doneCount: 0,\n failedCount: 0,\n oldestPendingAge: null\n };\n\n for (const row of statusCounts) {\n switch (row.status) {\n case 'pending':\n metrics.pendingCount = Number(row.count);\n break;\n case 'processing':\n metrics.processingCount = Number(row.count);\n break;\n case 'done':\n metrics.doneCount = Number(row.count);\n break;\n case 'failed':\n metrics.failedCount = Number(row.count);\n break;\n }\n }\n\n if (oldestPending.length > 0) {\n const oldestDate = new Date(oldestPending[0].created_at);\n metrics.oldestPendingAge = Date.now() - oldestDate.getTime();\n }\n\n return metrics;\n }\n\n /**\n * Validate state transition\n */\n isValidTransition(from: OutboxStatus, to: OutboxStatus): boolean {\n const validTransitions = [\n { from: 'pending', to: 'processing' },\n { from: 'processing', to: 'done' },\n { from: 'processing', to: 'failed' },\n { from: 'failed', to: 'pending' }\n ];\n\n return validTransitions.some(t => t.from === from && t.to === to);\n }\n\n /**\n * Convert database row to OutboxJob\n */\n private rowToJob(row: Record<string, unknown>): OutboxJob {\n return {\n jobId: row.job_id as string,\n itemKind: row.item_kind as OutboxItemKind,\n itemId: row.item_id as string,\n embeddingVersion: row.embedding_version as string,\n status: row.status as OutboxStatus,\n retryCount: row.retry_count as number,\n error: row.error as string | undefined,\n createdAt: toDate(row.created_at),\n updatedAt: toDate(row.updated_at)\n };\n }\n}\n", "/**\n * Privacy-safe retrieval lane metadata helpers.\n *\n * Lane details are intended for trace/debug surfaces. Keep them compact,\n * allow-listed, and free of raw private paths or credential-shaped values.\n */\n\nexport const RETRIEVAL_DEBUG_LANE_NAMES = [\n 'raw_event',\n 'session_event',\n 'session_summary',\n 'graph_path',\n 'facet_match'\n] as const;\n\nexport type RetrievalDebugLaneName = typeof RETRIEVAL_DEBUG_LANE_NAMES[number];\n\nexport interface RetrievalDebugLane {\n lane: RetrievalDebugLaneName;\n reason: string;\n score?: number;\n}\n\nconst RETRIEVAL_DEBUG_LANE_NAME_SET = new Set<string>(RETRIEVAL_DEBUG_LANE_NAMES);\n\nexport function isRetrievalDebugLaneName(value: unknown): value is RetrievalDebugLaneName {\n return typeof value === 'string' && RETRIEVAL_DEBUG_LANE_NAME_SET.has(value);\n}\n\nexport function normalizeRetrievalDebugLanes(value: unknown, maxItems = 6): RetrievalDebugLane[] {\n if (!Array.isArray(value) || maxItems <= 0) return [];\n\n const normalized: RetrievalDebugLane[] = [];\n const seen = new Set<string>();\n for (const item of value) {\n const lane = normalizeRetrievalDebugLane(item);\n if (!lane) continue;\n const key = [lane.lane, lane.reason, lane.score ?? ''].join('\\u0000');\n if (seen.has(key)) continue;\n seen.add(key);\n normalized.push(lane);\n if (normalized.length >= maxItems) break;\n }\n return normalized;\n}\n\nexport function normalizeRetrievalDebugLane(value: unknown): RetrievalDebugLane | null {\n if (!value || typeof value !== 'object') return null;\n const raw = value as Record<string, unknown>;\n if (!isRetrievalDebugLaneName(raw.lane)) return null;\n\n const reason = sanitizeRetrievalLaneReason(typeof raw.reason === 'string' ? raw.reason : '') || 'unspecified';\n const score = typeof raw.score === 'number' && Number.isFinite(raw.score)\n ? Math.max(0, Math.min(1, raw.score))\n : undefined;\n\n return score === undefined\n ? { lane: raw.lane, reason }\n : { lane: raw.lane, reason, score };\n}\n\nexport function sanitizeRetrievalLaneReason(value: string): string {\n return value\n .replace(/[\\r\\n\\t]+/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim()\n .replace(/[A-Za-z]:[\\\\/][^\\s'\"`<>)]*/g, '[path]')\n .replace(/\\/(?:Users|home|tmp|var\\/folders)\\/[^\\s'\"`<>)]*/g, '[path]')\n .replace(/\\\\\\\\[^\\s'\"`<>)]*/g, '[path]')\n .replace(/\\bBearer\\s+[^\\s'\"`,;]{6,}/gi, 'Bearer [REDACTED]')\n .replace(\n /([\"']?\\b(?:api[_-]?key|access[_-]?token|refresh[_-]?token|client[_-]?secret|token|secret|password|passwd|credential)[\"']?\\s*[:=]\\s*[\"']?)[^\\s\"'`,;}]{6,}/gi,\n '$1[REDACTED]'\n )\n .replace(\n /\\b(?:gh[pousr]_[A-Za-z0-9_]{8,}|github_pat_[A-Za-z0-9_]{8,}|glpat-[A-Za-z0-9_-]{8,}|xox[a-z]-[A-Za-z0-9-]{8,}|(?:AKIA|ASIA)[A-Z0-9]{12,}|AIza[0-9A-Za-z_-]{20,}|ya29\\.[0-9A-Za-z_-]+|sk-[A-Za-z0-9_-]{12,})\\b/g,\n '[REDACTED]'\n )\n .slice(0, 120);\n}\n", "/**\n * Usefulness Evidence\n *\n * Pure content-grounding analysis between an injected memory and the\n * assistant responses that followed it. Answers \"did the answer actually\n * use this memory?\" with a 0..1 grounding score plus the matched snippet\n * pairs that justify it, so the dashboard can show evidence per question.\n *\n * Handles both space-delimited text and CJK-heavy text (character bigrams).\n */\n\nexport interface ResponseDocument {\n id: string;\n content: string;\n}\n\nexport interface EvidenceMatch {\n /** Snippet of the memory that was found in a response */\n memorySnippet: string;\n /** The region of the response where the match occurred */\n responseSnippet: string;\n /** Event id of the matching agent_response */\n responseEventId: string;\n /** 0..1 similarity of this snippet match */\n similarity: number;\n matchType: 'exact' | 'term-overlap';\n}\n\nexport interface MemoryUsageEvidence {\n /** 0..1 \u2014 how strongly the responses are grounded in this memory */\n contentOverlapScore: number;\n /** Fraction of memory snippets that matched some response (0..1) */\n coverage: number;\n /** Best matches, strongest first */\n matches: EvidenceMatch[];\n}\n\nconst MAX_SNIPPETS = 40;\nconst MAX_MATCHES = 5;\nconst MIN_SNIPPET_LENGTH = 12;\nconst MAX_SNIPPET_LENGTH = 300;\nconst RESPONSE_CONTEXT_CHARS = 160;\nconst STRONG_MATCH_THRESHOLD = 0.55;\n// A snippet must carry at least this many informative tokens before any\n// match counts as evidence \u2014 otherwise a single generic word shared with the\n// answer (e.g. a \"## Configuration\" heading) scores as full grounding.\nconst MIN_SNIPPET_TOKENS = 3;\n\n/** Words too generic to signal grounding on their own. */\nconst STOP_TOKENS = new Set([\n 'the', 'and', 'for', 'that', 'this', 'with', 'from', 'have', 'has',\n 'was', 'were', 'are', 'not', 'but', 'you', 'your', 'can', 'will',\n 'should', 'would', 'could', 'when', 'what', 'which', 'their', 'there',\n 'then', 'than', 'into', 'over', 'also', 'only', 'some', 'such', 'use',\n 'used', 'using'\n]);\n\n/**\n * Lowercase and strip punctuation/markdown so the same phrasing matches even\n * when only punctuation differs. Applied consistently to memory snippets and\n * responses, so exact-containment stays valid.\n */\nfunction normalizeText(text: string): string {\n return text\n .toLowerCase()\n .replace(/[^a-z0-9\uAC00-\uD7A3\u4E00-\u9FFF\u3040-\u30FF\\s_/-]+/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n}\n\n// Latin/numeric identifiers (3+ chars) or runs of Hangul / CJK / kana.\nconst TOKEN_PATTERN = /[a-z0-9_/-]{3,}|[\uAC00-\uD7A3\u4E00-\u9FFF\u3040-\u30FF]+/g;\n\nfunction tokenize(text: string): string[] {\n const tokens: string[] = [];\n const wordMatches = text.match(TOKEN_PATTERN) || [];\n for (const rawMatch of wordMatches) {\n const raw = rawMatch.replace(/^[/-]+|[/-]+$/g, '');\n if (raw.length < 1) continue;\n if (/^[a-z0-9_/-]+$/.test(raw)) {\n if (raw.length >= 3 && !STOP_TOKENS.has(raw)) tokens.push(raw);\n continue;\n }\n // CJK run: split into character bigrams so partial phrasing still matches.\n if (raw.length === 1) {\n tokens.push(raw);\n continue;\n }\n for (let i = 0; i < raw.length - 1; i++) {\n tokens.push(raw.slice(i, i + 2));\n }\n }\n return tokens;\n}\n\n/**\n * Split memory content into candidate snippets worth searching for in\n * responses: lines and sentence-ish fragments of meaningful length.\n */\nexport function extractMemorySnippets(content: string): string[] {\n const seen = new Set<string>();\n const snippets: string[] = [];\n\n const push = (raw: string) => {\n const trimmed = raw.replace(/^[-*>\\d.\\s]+/, '').trim();\n if (trimmed.length < MIN_SNIPPET_LENGTH) return;\n const clipped = trimmed.slice(0, MAX_SNIPPET_LENGTH);\n const key = normalizeText(clipped);\n if (!key || key.length < MIN_SNIPPET_LENGTH || seen.has(key)) return;\n seen.add(key);\n snippets.push(clipped);\n };\n\n for (const line of content.split(/\\n+/)) {\n if (snippets.length >= MAX_SNIPPETS) break;\n const trimmedLine = line.trim();\n if (!trimmedLine) continue;\n // Markdown headings are structural labels, not facts \u2014 a heading word\n // reappearing in an answer says nothing about memory reuse.\n if (/^#{1,6}\\s/.test(trimmedLine)) continue;\n if (trimmedLine.length <= MAX_SNIPPET_LENGTH) {\n push(trimmedLine);\n continue;\n }\n // Long line: fall back to sentence-ish fragments.\n for (const sentence of trimmedLine.split(/(?<=[.!?\u3002])\\s+|;\\s+/)) {\n if (snippets.length >= MAX_SNIPPETS) break;\n push(sentence);\n }\n }\n\n return snippets;\n}\n\nfunction findResponseWindow(\n normalizedResponse: string,\n originalResponse: string,\n needle: string\n): string {\n const index = normalizedResponse.indexOf(needle);\n if (index < 0) {\n return originalResponse.slice(0, RESPONSE_CONTEXT_CHARS);\n }\n // The normalized text is not position-aligned with the original, so\n // approximate by proportional position \u2014 good enough for a preview snippet.\n const ratio = normalizedResponse.length > 0 ? index / normalizedResponse.length : 0;\n const approxStart = Math.max(0, Math.floor(originalResponse.length * ratio) - 40);\n return originalResponse.slice(approxStart, approxStart + RESPONSE_CONTEXT_CHARS).trim();\n}\n\nfunction findTermWindow(originalResponse: string, terms: string[]): string {\n const lower = originalResponse.toLowerCase();\n for (const term of terms) {\n const index = lower.indexOf(term);\n if (index >= 0) {\n const start = Math.max(0, index - 40);\n return originalResponse.slice(start, start + RESPONSE_CONTEXT_CHARS).trim();\n }\n }\n return originalResponse.slice(0, RESPONSE_CONTEXT_CHARS).trim();\n}\n\n/**\n * Compute how strongly a set of assistant responses is grounded in a\n * memory's content, with per-snippet match evidence.\n */\nexport function computeMemoryUsageEvidence(\n memoryContent: string,\n responses: ResponseDocument[]\n): MemoryUsageEvidence {\n const snippets = extractMemorySnippets(memoryContent);\n if (snippets.length === 0 || responses.length === 0) {\n return { contentOverlapScore: 0, coverage: 0, matches: [] };\n }\n\n const preparedResponses = responses\n .map((response) => ({\n id: response.id,\n original: response.content,\n normalized: normalizeText(response.content),\n tokenSet: new Set(tokenize(normalizeText(response.content)))\n }))\n .filter((response) => response.normalized.length > 0);\n\n if (preparedResponses.length === 0) {\n return { contentOverlapScore: 0, coverage: 0, matches: [] };\n }\n\n const matches: EvidenceMatch[] = [];\n let matchedSnippets = 0;\n let bestSimilarity = 0;\n\n let comparableSnippets = 0;\n for (const snippet of snippets) {\n const normalizedSnippet = normalizeText(snippet);\n const snippetTokens = tokenize(normalizedSnippet);\n if (snippetTokens.length < MIN_SNIPPET_TOKENS) continue;\n comparableSnippets++;\n\n let best: EvidenceMatch | null = null;\n\n for (const response of preparedResponses) {\n // 1) Exact normalized containment \u2014 the strongest possible signal.\n if (normalizedSnippet.length >= MIN_SNIPPET_LENGTH && response.normalized.includes(normalizedSnippet)) {\n best = {\n memorySnippet: snippet,\n responseSnippet: findResponseWindow(response.normalized, response.original, normalizedSnippet),\n responseEventId: response.id,\n similarity: 1,\n matchType: 'exact'\n };\n break;\n }\n\n // 2) Term containment \u2014 what fraction of the snippet's tokens appear\n // in the response. Discriminative for facts, robust to rephrasing.\n let hit = 0;\n const matchedTerms: string[] = [];\n for (const token of snippetTokens) {\n if (response.tokenSet.has(token)) {\n hit++;\n if (matchedTerms.length < 5 && token.length >= 3) matchedTerms.push(token);\n }\n }\n const containment = hit / snippetTokens.length;\n const similarity = containment * 0.9; // cap below exact-match confidence\n if (similarity >= STRONG_MATCH_THRESHOLD && (!best || similarity > best.similarity)) {\n best = {\n memorySnippet: snippet,\n responseSnippet: findTermWindow(response.original, matchedTerms),\n responseEventId: response.id,\n similarity: Math.round(similarity * 100) / 100,\n matchType: 'term-overlap'\n };\n }\n }\n\n if (best) {\n matchedSnippets++;\n bestSimilarity = Math.max(bestSimilarity, best.similarity);\n matches.push(best);\n }\n }\n\n if (comparableSnippets === 0) {\n return { contentOverlapScore: 0, coverage: 0, matches: [] };\n }\n\n const coverage = matchedSnippets / comparableSnippets;\n // Grounding blends \"at least one strong reuse\" with \"how much of the\n // memory was reused\". A single exact quote should already score well.\n const contentOverlapScore = Math.min(1, 0.65 * bestSimilarity + 0.35 * coverage);\n\n matches.sort((a, b) => b.similarity - a.similarity);\n\n return {\n contentOverlapScore: Math.round(contentOverlapScore * 100) / 100,\n coverage: Math.round(coverage * 100) / 100,\n matches: matches.slice(0, MAX_MATCHES)\n };\n}\n", "import type { MemoryKind } from './memory-ref.js';\n\nexport const RETRIEVAL_PRESENTATION_MODES = ['evidence', 'reference', 'core', 'unknown'] as const;\nexport type RetrievalPresentationMode = typeof RETRIEVAL_PRESENTATION_MODES[number];\n\nexport const RETRIEVAL_TRIGGER_TYPES = [\n 'session_start',\n 'user_prompt',\n 'explicit_search',\n 'context_pack',\n 'unknown'\n] as const;\nexport type RetrievalTriggerType = typeof RETRIEVAL_TRIGGER_TYPES[number];\n\nexport const REFERENCE_NAVIGATION_ACTIONS = ['source_ref', 'details', 'expand', 'source'] as const;\nexport type ReferenceNavigationAction = typeof REFERENCE_NAVIGATION_ACTIONS[number];\n\nexport type ReferenceNavigationOutcome = 'attributed' | 'ambiguous' | 'unattributed';\n\nexport const RETRIEVAL_OUTCOME_REASONS = [\n 'selected',\n 'no_project_events',\n 'freshness_gap',\n 'scope_filtered',\n 'no_keyword_candidates',\n 'no_vector_candidates',\n 'stale_vector_schema',\n 'below_score_threshold',\n 'quality_filtered',\n 'session_rescue_empty',\n 'context_pack_policy_filtered',\n // An empty selection with no diagnostics is not a failure. `runtime_error` is\n // reserved for a caught exception; anything else uncategorised is `unknown`.\n 'unknown',\n // Rows written before the schema carried an honest default. Readers surface\n // this instead of re-classifying old data (specs R2).\n 'legacy_unclassified',\n 'runtime_error'\n] as const;\n\nexport type RetrievalOutcomeReason = typeof RETRIEVAL_OUTCOME_REASONS[number];\n\nexport type UsefulnessAdoption = 'grounded' | 'navigated' | 'not_observed' | 'unknown';\nexport type UsefulnessTaskOutcome = 'success' | 'failure' | 'mixed' | 'unknown';\nexport type UsefulnessReaskOutcome = 'clarification' | 'repeat_failure' | 'topic_continuation' | 'none' | 'unknown';\nexport type UsefulnessExplicitFeedback = 'positive' | 'negative' | null;\n\n/**\n * Evaluator identity for the delivery-evidence generation. v2 rows assumed\n * delivery; they are kept but never averaged together with v3 (specs R3).\n */\nexport const CURRENT_USEFULNESS_EVALUATOR_VERSION = 'v3';\nexport const LEGACY_ASSUMED_DELIVERY_EVALUATOR_VERSIONS = ['v2'] as const;\n\nexport interface MemoryUsefulnessObservationV2 {\n traceId: string;\n /** Retained field name for schema compatibility; may hold any memory kind. */\n eventId: string;\n /** Typed kind of `eventId`. Defaults to `event` only for legacy rows. */\n memoryKind?: MemoryKind;\n /** Owning project of the memory; part of its scope-aware identity (specs R1). */\n memoryProjectId?: string | null;\n observationKind: 'outcome';\n presentationMode: RetrievalPresentationMode;\n triggerType: RetrievalTriggerType;\n selected: boolean;\n delivered: boolean | null;\n deliveryStatus?: DeliveryStatus;\n deliveryEvidence?: DeliveryEvidenceSource;\n adoption: UsefulnessAdoption;\n contentOverlapScore: number | null;\n taskOutcome: UsefulnessTaskOutcome;\n reaskOutcome: UsefulnessReaskOutcome;\n explicitFeedback: UsefulnessExplicitFeedback;\n confidence: number;\n evaluatedAt: string | null;\n evaluatorVersion: string;\n /** Observation window applied after delivery, in ms. */\n evaluationWindowMs?: number;\n /** End of the window this evaluation could actually see. */\n evaluationCutoff?: string | null;\n}\n\nexport interface UsefulnessRateV2 {\n numerator: number;\n denominator: number;\n unknown: number;\n value: number | null;\n}\n\nexport interface UsefulnessAggregateV2 {\n eligible: number;\n selected: number;\n delivered: number;\n evidenceEvaluated: number;\n evidenceGrounded: number;\n referencesEligible: number;\n referencesNavigated: number;\n taskOutcomesEvaluated: number;\n taskOutcomesSuccessful: number;\n explicitPositive: number;\n explicitNegative: number;\n unknown: number;\n unknownByDimension: {\n delivery: number;\n adoption: number;\n taskOutcome: number;\n reaskOutcome: number;\n explicitFeedback: number;\n };\n rates: {\n selectionYield: UsefulnessRateV2;\n deliveryRate: UsefulnessRateV2;\n evidenceGrounding: UsefulnessRateV2;\n referenceNavigation: UsefulnessRateV2;\n taskSuccess: UsefulnessRateV2;\n explicitPositive: UsefulnessRateV2;\n };\n sampleState: 'sufficient' | 'insufficient_sample';\n minimumSample: number;\n evaluatorVersion: string;\n excludesSessionStart: boolean;\n window: { since: string | null; until: string | null };\n /** Observed delivery evidence levels. `unknown` is never folded into 0. */\n deliveryStatusCounts: Record<DeliveryStatus, number>;\n /** Rows from an evaluator generation that assumed delivery (v2). */\n legacyAssumedDeliveryRows: number;\n /**\n * How the `delivered` values in this aggregate were obtained. A legacy\n * evaluator's rows are labelled `legacy_assumed` rather than presented as\n * observed delivery (specs R3).\n */\n deliveryEvidenceBasis: 'observed' | 'legacy_assumed';\n /** Selected memories by typed kind (specs R1). */\n selectedByKind: Record<MemoryKind, number>;\n /**\n * The population `evidenceGrounding` is measured over. The spec's headline\n * comparison is prompt-triggered evidence only; session_start, explicit\n * search and context-pack rows are reported separately, never averaged in.\n */\n evidenceGroundingScope: 'evidence/user_prompt';\n /** Same counts over every trigger, for transparency about what was excluded. */\n evidenceAllTriggers: { evaluated: number; grounded: number; unknown: number };\n /** Bounded observation window used by this evaluator, in ms. */\n evaluationWindowMs: number;\n /**\n * Every adoption/task signal below is a heuristic, not a confirmed outcome.\n * Surfaced in JSON and UI so a reader never reads them as measured causality.\n */\n heuristics: {\n grounding: 'text_overlap';\n groundingThreshold: number;\n taskOutcome: 'post_delivery_tool_success';\n note: string;\n };\n}\n\nexport const USEFULNESS_HEURISTIC_NOTE =\n 'Grounding is text overlap between the delivered excerpt and later responses; '\n + 'task outcome is post-delivery tool success. Both are heuristics, not verified causal effects.';\n\nexport function normalizeUsefulnessMinimumSample(value: unknown): number {\n if (typeof value !== 'number' || !Number.isFinite(value)) return 20;\n return Math.min(10_000, Math.max(1, Math.floor(value)));\n}\n\nexport function emptyUsefulnessAggregateV2(options: {\n minimumSample?: number;\n evaluatorVersion?: string;\n includeSessionStart?: boolean;\n since?: Date;\n until?: Date;\n evaluationWindowMs?: number;\n groundingThreshold?: number;\n} = {}): UsefulnessAggregateV2 {\n const rate = (): UsefulnessRateV2 => ({ numerator: 0, denominator: 0, unknown: 0, value: null });\n return {\n eligible: 0,\n selected: 0,\n delivered: 0,\n evidenceEvaluated: 0,\n evidenceGrounded: 0,\n referencesEligible: 0,\n referencesNavigated: 0,\n taskOutcomesEvaluated: 0,\n taskOutcomesSuccessful: 0,\n explicitPositive: 0,\n explicitNegative: 0,\n unknown: 0,\n unknownByDimension: { delivery: 0, adoption: 0, taskOutcome: 0, reaskOutcome: 0, explicitFeedback: 0 },\n rates: {\n selectionYield: rate(),\n deliveryRate: rate(),\n evidenceGrounding: rate(),\n referenceNavigation: rate(),\n taskSuccess: rate(),\n explicitPositive: rate()\n },\n sampleState: 'insufficient_sample',\n minimumSample: normalizeUsefulnessMinimumSample(options.minimumSample),\n evaluatorVersion: options.evaluatorVersion ?? CURRENT_USEFULNESS_EVALUATOR_VERSION,\n excludesSessionStart: options.includeSessionStart !== true,\n window: {\n since: options.since?.toISOString() ?? null,\n until: options.until?.toISOString() ?? null\n },\n deliveryStatusCounts: { unknown: 0, formatted: 0, emitted: 0, acknowledged: 0, failed: 0 },\n legacyAssumedDeliveryRows: 0,\n deliveryEvidenceBasis: LEGACY_ASSUMED_DELIVERY_EVALUATOR_VERSIONS.includes(\n (options.evaluatorVersion ?? CURRENT_USEFULNESS_EVALUATOR_VERSION) as typeof LEGACY_ASSUMED_DELIVERY_EVALUATOR_VERSIONS[number]\n )\n ? 'legacy_assumed'\n : 'observed',\n selectedByKind: { event: 0, lesson: 0, rule: 0, core: 0, unknown: 0 },\n evidenceGroundingScope: 'evidence/user_prompt',\n evidenceAllTriggers: { evaluated: 0, grounded: 0, unknown: 0 },\n evaluationWindowMs: options.evaluationWindowMs ?? 0,\n heuristics: {\n grounding: 'text_overlap',\n groundingThreshold: options.groundingThreshold ?? 0.3,\n taskOutcome: 'post_delivery_tool_success',\n note: USEFULNESS_HEURISTIC_NOTE\n }\n };\n}\n\nexport interface RetrievalOutcomeDiagnostics {\n outcomeReason: RetrievalOutcomeReason;\n laneCandidateCounts: Record<string, number>;\n filteredCounts: Record<string, number>;\n topScore: number | null;\n threshold: number;\n freshnessState: 'fresh' | 'stale' | 'unknown';\n}\n\nconst RETRIEVAL_OUTCOME_REASON_SET = new Set<string>(RETRIEVAL_OUTCOME_REASONS);\nconst DIAGNOSTIC_COUNT_KEYS = new Set([\n 'keyword', 'vector', 'summary', 'graph', 'session_rescue', 'shared',\n 'scope', 'quality', 'threshold', 'context_pack_policy'\n]);\n\nexport function normalizeRetrievalOutcomeReason(value: unknown): RetrievalOutcomeReason {\n return typeof value === 'string' && RETRIEVAL_OUTCOME_REASON_SET.has(value)\n ? value as RetrievalOutcomeReason\n : 'unknown';\n}\n\nexport function normalizeRetrievalOutcomeDiagnostics(\n value: unknown,\n fallbackReason: RetrievalOutcomeReason = 'unknown'\n): RetrievalOutcomeDiagnostics {\n const raw = value && typeof value === 'object' ? value as Record<string, unknown> : {};\n return {\n outcomeReason: RETRIEVAL_OUTCOME_REASON_SET.has(String(raw.outcomeReason))\n ? raw.outcomeReason as RetrievalOutcomeReason\n : fallbackReason,\n laneCandidateCounts: normalizeDiagnosticCounts(raw.laneCandidateCounts),\n filteredCounts: normalizeDiagnosticCounts(raw.filteredCounts),\n topScore: typeof raw.topScore === 'number' && Number.isFinite(raw.topScore)\n ? Math.max(0, Math.min(1, raw.topScore))\n : null,\n threshold: typeof raw.threshold === 'number' && Number.isFinite(raw.threshold)\n ? Math.max(0, Math.min(1, raw.threshold))\n : 0,\n freshnessState: raw.freshnessState === 'fresh' || raw.freshnessState === 'stale'\n ? raw.freshnessState\n : 'unknown'\n };\n}\n\nfunction normalizeDiagnosticCounts(value: unknown): Record<string, number> {\n if (!value || typeof value !== 'object') return {};\n return Object.fromEntries(Object.entries(value as Record<string, unknown>)\n .filter(([key, count]) => DIAGNOSTIC_COUNT_KEYS.has(key) && Number.isFinite(Number(count)))\n .map(([key, count]) => [key, Math.max(0, Math.min(1_000_000, Math.floor(Number(count))))]));\n}\n\n/**\n * Bumped whenever the trace ledger gains a field a reader must know about.\n * Version 2 is the first schema with typed trace items, honest unknown outcome\n * reasons and request metadata (specs/recent-memory-patterns-2026-09-06 R1-R2).\n */\nexport const RETRIEVAL_TELEMETRY_SCHEMA_VERSION = 2;\n\n/**\n * Rows without a schema version predate the honest-default migration. Their\n * stored `runtime_error` was a fallback, not an observed exception, so readers\n * present them as legacy instead of re-classifying the stored value.\n */\nexport function presentedOutcomeReason(\n storedReason: unknown,\n telemetrySchemaVersion: unknown\n): RetrievalOutcomeReason {\n const version = Number(telemetrySchemaVersion);\n const reason = normalizeRetrievalOutcomeReason(storedReason);\n if (Number.isFinite(version) && version >= 2) return reason;\n return reason === 'runtime_error' ? 'legacy_unclassified' : reason;\n}\n\n/**\n * How far a selected memory actually got. Selection alone is not delivery:\n * `formatted` means the text was built, `emitted` means the hook wrote it to\n * stdout successfully, `acknowledged` requires evidence the consumer read it.\n */\nexport const DELIVERY_STATUSES = ['unknown', 'formatted', 'emitted', 'acknowledged', 'failed'] as const;\nexport type DeliveryStatus = typeof DELIVERY_STATUSES[number];\n\n/** Where the delivery status came from. `legacy_assumed` is never a new write. */\nexport const DELIVERY_EVIDENCE_SOURCES = [\n 'none',\n 'context_formatted',\n 'hook_stdout',\n 'mcp_tool_result',\n 'consumer_ack',\n 'write_error',\n 'legacy_assumed'\n] as const;\nexport type DeliveryEvidenceSource = typeof DELIVERY_EVIDENCE_SOURCES[number];\n\nconst DELIVERY_STATUS_SET = new Set<string>(DELIVERY_STATUSES);\nconst DELIVERY_EVIDENCE_SET = new Set<string>(DELIVERY_EVIDENCE_SOURCES);\n\nexport function normalizeDeliveryStatus(value: unknown): DeliveryStatus {\n return typeof value === 'string' && DELIVERY_STATUS_SET.has(value)\n ? value as DeliveryStatus\n : 'unknown';\n}\n\nexport function normalizeDeliveryEvidence(value: unknown): DeliveryEvidenceSource {\n return typeof value === 'string' && DELIVERY_EVIDENCE_SET.has(value)\n ? value as DeliveryEvidenceSource\n : 'none';\n}\n\n/**\n * `delivered` stays null until evidence exists. Only an emitted/acknowledged\n * delivery is true and only an observed write failure is false \u2014 a formatted\n * but never-flushed context is unknown, not delivered.\n */\nexport function deliveredFromStatus(status: DeliveryStatus): boolean | null {\n if (status === 'emitted' || status === 'acknowledged') return true;\n if (status === 'failed') return false;\n return null;\n}\n\nexport interface RetrievalTelemetryContext {\n presentationMode?: RetrievalPresentationMode;\n triggerType?: RetrievalTriggerType;\n deliveryClient?: string;\n /** Stable id for the caller-visible request that produced this retrieval. */\n requestId?: string;\n /** Set only by offline/benchmark evaluation runs so they can be excluded. */\n evaluationRunId?: string;\n runtimeVersion?: string;\n}\n\n/** One typed reference inside a trace: a candidate, a selection, or both. */\nexport interface RetrievalTraceItemInput {\n kind: MemoryKind;\n id: string;\n projectId?: string | null;\n rank?: number;\n selected?: boolean;\n score?: number | null;\n /** Hash of the delivered excerpt. Never the excerpt itself. */\n contentHash?: string | null;\n memoryVersion?: string | null;\n deleted?: boolean;\n}\n\nexport interface RetrievalTraceItem {\n traceId: string;\n itemKey: string;\n memoryKind: MemoryKind;\n memoryId: string;\n projectId: string | null;\n rank: number | null;\n selected: boolean;\n score: number | null;\n contentHash: string | null;\n memoryVersion: string | null;\n deleted: boolean;\n}\n\n/** Typed selection totals for a fixed sample, with unresolved refs kept apart. */\nexport interface TypedSelectionSummary {\n byKind: Record<MemoryKind, number>;\n total: number;\n unresolved: number;\n ambiguous: number;\n /** Traces whose items were reconstructed by the read-only legacy resolver. */\n legacyResolvedTraces: number;\n typedTraces: number;\n}\n\nexport function emptyTypedSelectionSummary(): TypedSelectionSummary {\n return {\n byKind: { event: 0, lesson: 0, rule: 0, core: 0, unknown: 0 },\n total: 0,\n unresolved: 0,\n ambiguous: 0,\n legacyResolvedTraces: 0,\n typedTraces: 0\n };\n}\n\n/**\n * Per-client instrumentation coverage. A client whose requests we never see\n * cannot be reported as 0% coverage \u2014 that would claim an observation we do not\n * have \u2014 so `coverage` stays null with an explicit `unknown` state.\n */\nexport interface RetrievalClientCoverage {\n client: string;\n observedRequests: number;\n instrumentedRequests: number;\n unobservedOrUnknown: number;\n coverage: number | null;\n coverageState: 'measured' | 'unknown';\n}\n\nexport function normalizeRequestId(value: unknown): string | null {\n if (typeof value !== 'string') return null;\n const trimmed = value.trim().slice(0, 128);\n return /^[A-Za-z0-9_.:@-]{1,128}$/.test(trimmed) ? trimmed : null;\n}\n\nexport interface RecordReferenceNavigationInput {\n targetEventId: string;\n /** Typed kind of the opened memory. Defaults to `event` for legacy callers. */\n targetKind?: MemoryKind;\n targetProjectId?: string | null;\n action: ReferenceNavigationAction;\n navigationClient: string;\n /** Optional current delivery session. When supplied, attribution never crosses its boundary. */\n attributionSessionId?: string;\n openedAt?: Date;\n}\n\nexport interface RecordReferenceNavigationResult {\n outcome: ReferenceNavigationOutcome;\n traceId: string | null;\n repeated: boolean;\n}\n\nexport interface RetrievalPresentationBreakdown {\n presentationMode: RetrievalPresentationMode;\n traceCount: number;\n deliveredItemCount: number;\n}\n\nexport interface RetrievalTriggerBreakdown {\n triggerType: RetrievalTriggerType;\n traceCount: number;\n deliveredItemCount: number;\n}\n\nexport interface RetrievalTelemetryStats {\n deliveries: {\n totalTraces: number;\n totalItems: number;\n byPresentation: RetrievalPresentationBreakdown[];\n byTrigger: RetrievalTriggerBreakdown[];\n legacyUnknownRows: number;\n };\n evidenceGrounding: {\n evaluatedDeliveries: number;\n groundedDeliveries: number;\n groundingRate: number;\n averageContentOverlap: number;\n };\n referenceNavigation: {\n eligibleTraces: number;\n navigatedTraces: number;\n navigationRate: number;\n attributedOpenCount: number;\n ambiguousOpenCount: number;\n unattributedOpenCount: number;\n };\n}\n\nexport function normalizeRetrievalPresentationMode(value: unknown): RetrievalPresentationMode {\n return typeof value === 'string' && (RETRIEVAL_PRESENTATION_MODES as readonly string[]).includes(value)\n ? value as RetrievalPresentationMode\n : 'unknown';\n}\n\nexport function normalizeRetrievalTriggerType(value: unknown): RetrievalTriggerType {\n return typeof value === 'string' && (RETRIEVAL_TRIGGER_TYPES as readonly string[]).includes(value)\n ? value as RetrievalTriggerType\n : 'unknown';\n}\n\nexport function normalizeTelemetryClient(value: unknown): string {\n if (typeof value !== 'string') return 'unknown';\n const normalized = value.trim().toLowerCase().replace(/[^a-z0-9_-]+/g, '-').slice(0, 48);\n return normalized || 'unknown';\n}\n", "import type { MemoryKind } from './memory-ref.js';\nimport {\n CURRENT_USEFULNESS_EVALUATOR_VERSION,\n type DeliveryEvidenceSource,\n type DeliveryStatus,\n type MemoryUsefulnessObservationV2,\n type RetrievalPresentationMode,\n type RetrievalTriggerType,\n type UsefulnessAdoption,\n type UsefulnessReaskOutcome,\n type UsefulnessTaskOutcome\n} from './retrieval-telemetry.js';\n\nexport type ParsedToolOutcome = 'success' | 'failure' | 'unknown';\n\n/** Outcome signals are attributable only to the bounded task phase after delivery. */\nexport const USEFULNESS_V2_EVALUATION_WINDOW_MS = 30 * 60 * 1000;\n\nexport function parseToolOutcome(value: unknown): ParsedToolOutcome {\n let parsed = value;\n if (typeof value === 'string') {\n try {\n parsed = JSON.parse(value);\n } catch {\n return 'unknown';\n }\n }\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) return 'unknown';\n const record = parsed as Record<string, unknown>;\n if (typeof record.success === 'boolean') return record.success ? 'success' : 'failure';\n if (typeof record.ok === 'boolean') return record.ok ? 'success' : 'failure';\n if (typeof record.isError === 'boolean') return record.isError ? 'failure' : 'success';\n if (typeof record.status === 'string') {\n const status = record.status.trim().toLowerCase();\n if (['ok', 'success', 'succeeded', 'complete', 'completed'].includes(status)) return 'success';\n if (['error', 'failed', 'failure', 'cancelled', 'canceled'].includes(status)) return 'failure';\n }\n return 'unknown';\n}\n\nexport function deriveTaskOutcome(\n adoption: UsefulnessAdoption,\n toolOutcomes: ParsedToolOutcome[]\n): UsefulnessTaskOutcome {\n if (adoption !== 'grounded' && adoption !== 'navigated') return 'unknown';\n const measured = toolOutcomes.filter((outcome) => outcome !== 'unknown');\n if (measured.length === 0) return 'unknown';\n const successes = measured.filter((outcome) => outcome === 'success').length;\n const failures = measured.length - successes;\n if (successes > 0 && failures > 0) return 'mixed';\n return successes > 0 ? 'success' : 'failure';\n}\n\nexport function classifyReaskOutcome(\n originalQuery: unknown,\n promptsAfter: unknown[]\n): UsefulnessReaskOutcome {\n if (!Array.isArray(promptsAfter)) return 'unknown';\n if (promptsAfter.length === 0) return 'none';\n const query = typeof originalQuery === 'string' ? originalQuery.trim() : '';\n const prompts = promptsAfter.filter((value): value is string => typeof value === 'string' && value.trim().length > 0);\n if (prompts.length === 0) return 'unknown';\n const combined = prompts.join(' ').toLowerCase();\n if (/(clarify|what do you mean|more specific|explain more|\uBB34\uC2A8 \uB73B|\uC880 \uB354 \uC124\uBA85|\uAD6C\uCCB4\uC801\uC73C\uB85C|\uBA85\uD655\uD788)/i.test(combined)) {\n return 'clarification';\n }\n if (/(still|again|same error|doesn.t work|did not work|failed again|\uC5EC\uC804\uD788|\uB610 \uC2E4\uD328|\uAC19\uC740 \uC624\uB958|\uC548[\uB3FC\uB418]|\uC791\uB3D9\uD558\uC9C0 \uC54A)/i.test(combined)) {\n return 'repeat_failure';\n }\n if (!query) return 'unknown';\n const queryTokens = tokens(query);\n if (queryTokens.size === 0) return 'unknown';\n for (const prompt of prompts) {\n const promptTokens = tokens(prompt);\n const overlap = [...queryTokens].filter((token) => promptTokens.has(token)).length / queryTokens.size;\n if (overlap >= 0.35) return 'topic_continuation';\n }\n return 'none';\n}\n\nexport function buildUsefulnessObservationV2(input: {\n traceId: string;\n eventId: string;\n memoryKind?: MemoryKind;\n memoryProjectId?: string | null;\n presentationMode: RetrievalPresentationMode;\n triggerType: RetrievalTriggerType;\n delivered: boolean | null;\n deliveryStatus?: DeliveryStatus;\n deliveryEvidence?: DeliveryEvidenceSource;\n adoption: UsefulnessAdoption;\n contentOverlapScore: number | null;\n toolOutcomes: ParsedToolOutcome[];\n reaskOutcome: UsefulnessReaskOutcome;\n evaluatedAt: string | null;\n evaluatorVersion?: string;\n evaluationWindowMs?: number;\n evaluationCutoff?: string | null;\n}): MemoryUsefulnessObservationV2 {\n return {\n traceId: input.traceId,\n eventId: input.eventId,\n memoryKind: input.memoryKind ?? 'event',\n memoryProjectId: input.memoryProjectId ?? null,\n observationKind: 'outcome',\n presentationMode: input.presentationMode,\n triggerType: input.triggerType,\n selected: true,\n delivered: input.delivered,\n deliveryStatus: input.deliveryStatus ?? 'unknown',\n deliveryEvidence: input.deliveryEvidence ?? 'none',\n adoption: input.adoption,\n contentOverlapScore: input.contentOverlapScore,\n taskOutcome: deriveTaskOutcome(input.adoption, input.toolOutcomes),\n reaskOutcome: input.reaskOutcome,\n explicitFeedback: null,\n confidence: confidenceFor(input.presentationMode, input.adoption),\n evaluatedAt: input.evaluatedAt,\n evaluatorVersion: input.evaluatorVersion ?? CURRENT_USEFULNESS_EVALUATOR_VERSION,\n evaluationWindowMs: input.evaluationWindowMs ?? USEFULNESS_V2_EVALUATION_WINDOW_MS,\n evaluationCutoff: input.evaluationCutoff ?? null\n };\n}\n\nfunction confidenceFor(presentationMode: RetrievalPresentationMode, adoption: UsefulnessAdoption): number {\n if (presentationMode === 'reference') return adoption === 'navigated' ? 0.95 : 0.7;\n if (presentationMode === 'evidence') return adoption === 'grounded' ? 0.85 : 0.6;\n if (presentationMode === 'core') return 0.4;\n return 0.3;\n}\n\nfunction tokens(value: string): Set<string> {\n return new Set(value.toLowerCase().match(/[a-z0-9_/-]{3,}|[\uAC00-\uD7A3]{2,}/g) ?? []);\n}\n", "/**\n * Typed memory references (specs/recent-memory-patterns-2026-09-06 R1).\n *\n * The retrieval ledger historically stored every selected memory in\n * `retrieval_traces.selected_event_ids`, regardless of what kind of memory it\n * was. Lessons are not events, so an event-table join silently dropped them\n * (465 selections in the 2026-09-06 sample) and helpfulness/access writes keyed\n * by a lesson id updated nothing. A `MemoryRef` keeps the kind next to the id so\n * joins, access counters and evaluation populations stay type-correct.\n *\n * Nothing here copies memory content: only the kind, the id, the owning project\n * and an optional content hash travel with a reference.\n */\n\nexport const MEMORY_KINDS = ['event', 'lesson', 'rule', 'core', 'unknown'] as const;\nexport type MemoryKind = typeof MEMORY_KINDS[number];\n\nconst MEMORY_KIND_SET = new Set<string>(MEMORY_KINDS);\n\nexport interface MemoryRef {\n /**\n * Project scope that owns the memory. Must match the permission boundary the\n * memory was read under; `null` means the reference is store-local/global.\n */\n projectId: string | null;\n kind: MemoryKind;\n id: string;\n}\n\n/**\n * Why a reference could not be resolved to a single kind. Kept separate from\n * `kind` so an honestly unknown reference is never reported as a data loss.\n */\nexport type MemoryRefResolution =\n | 'resolved'\n | 'ambiguous'\n | 'unresolved'\n | 'deleted'\n | 'forbidden';\n\nexport interface ResolvedMemoryRef extends MemoryRef {\n resolution: MemoryRefResolution;\n /** Kinds the id matched. Length > 1 means ambiguous. */\n matchedKinds: MemoryKind[];\n}\n\nexport function normalizeMemoryKind(value: unknown): MemoryKind {\n return typeof value === 'string' && MEMORY_KIND_SET.has(value)\n ? value as MemoryKind\n : 'unknown';\n}\n\n/** Project segment of a scope-aware key. `-` means \"store-local / global\". */\nconst GLOBAL_SCOPE_SEGMENT = '-';\n\n/**\n * Kind-aware, scope-free key. Only safe where the owning project is already\n * fixed by context (a single project store, a single trace's own scope).\n */\nexport function memoryKindKey(ref: Pick<MemoryRef, 'kind' | 'id'>): string {\n return `${normalizeMemoryKind(ref.kind)}:${ref.id}`;\n}\n\n/**\n * Stable identity for a reference: project scope, kind, then id.\n *\n * Kind is part of the key so an event and a lesson that share an id remain two\n * distinct rows. The project scope is part of it too: the same kind/id pair in\n * two different projects is two different memories under two different\n * permission boundaries, and collapsing them would merge one project's\n * telemetry into another's (specs R1).\n */\nexport function memoryRefKey(ref: Pick<MemoryRef, 'kind' | 'id'> & { projectId?: string | null }): string {\n return JSON.stringify([ref.projectId?.trim() || null, normalizeMemoryKind(ref.kind), ref.id]);\n}\n\nexport function parseMemoryRefKey(\n key: string\n): { projectId: string | null; kind: MemoryKind; id: string } | null {\n if (key.startsWith('[')) {\n try {\n const value: unknown = JSON.parse(key);\n if (Array.isArray(value) && value.length === 3\n && (value[0] === null || typeof value[0] === 'string')\n && MEMORY_KIND_SET.has(value[1]) && typeof value[2] === 'string' && value[2].length > 0) {\n return { projectId: value[0], kind: value[1] as MemoryKind, id: value[2] };\n }\n } catch { /* malformed key */ }\n return null;\n }\n // Read the pre-release pipe form, but only emit unambiguous tuple keys.\n // Scan for the first unescaped `|`: a project id may legitimately contain an\n // escaped one.\n let scope = '';\n let index = 0;\n let closed = false;\n while (index < key.length) {\n const char = key[index];\n if (char === '\\\\' && index + 1 < key.length) {\n scope += key[index + 1];\n index += 2;\n continue;\n }\n if (char === '|') {\n closed = true;\n index += 1;\n break;\n }\n scope += char;\n index += 1;\n }\n if (!closed) return null;\n const rest = key.slice(index);\n const separator = rest.indexOf(':');\n if (separator <= 0 || separator === rest.length - 1) return null;\n const kind = rest.slice(0, separator);\n if (!MEMORY_KIND_SET.has(kind)) return null;\n return {\n projectId: scope === GLOBAL_SCOPE_SEGMENT ? null : scope,\n kind: kind as MemoryKind,\n id: rest.slice(separator + 1)\n };\n}\n\n/**\n * Core memory blocks are delivered as `core:<blockKey>` pseudo-ids by the\n * session-start hook. Recognize that shape so the ledger records them as core\n * blocks rather than as events that will never resolve.\n */\nexport function inferMemoryKindFromLegacyId(id: string): MemoryKind | null {\n if (id.startsWith('core:')) return 'core';\n return null;\n}\n\nexport function isEventRef(ref: Pick<MemoryRef, 'kind'>): boolean {\n return ref.kind === 'event';\n}\n\n/** Deduplicate refs by scope-aware typed key while preserving first-seen order. */\nexport function uniqueMemoryRefs<T extends Pick<MemoryRef, 'kind' | 'id'> & { projectId?: string | null }>(\n refs: T[]\n): T[] {\n const seen = new Set<string>();\n const out: T[] = [];\n for (const ref of refs) {\n if (!ref?.id) continue;\n const key = memoryRefKey(ref);\n if (seen.has(key)) continue;\n seen.add(key);\n out.push(ref);\n }\n return out;\n}\n\n/**\n * Row key for tables whose legacy identity column is `event_id`\n * (`memory_helpfulness`, `memory_usefulness_observations_v2`).\n *\n * New evaluator rows use the complete scope/kind/id tuple. Their memory_id\n * retains the original id; historical v2 observations keep their legacy keys.\n */\nexport function usefulnessRowKey(kind: MemoryKind | undefined, id: string, projectId?: string | null): string {\n return memoryRefKey({ kind: normalizeMemoryKind(kind ?? 'event'), id, projectId });\n}\n\n/** SQL expression mirroring `usefulnessRowKey` for a table alias. */\nexport function usefulnessRowKeySql(alias: string, kindColumn = 'memory_kind', idColumn = 'event_id'): string {\n return `json_array(NULLIF(TRIM(${alias}.memory_project_id), ''), COALESCE(${alias}.${kindColumn}, 'event'), ${alias}.${idColumn})`;\n}\n", "/**\n * Reference navigation telemetry.\n *\n * Split out of the event store so any caller holding a SQLite handle can record\n * that a delivered reference was actually opened, together with the typed kind\n * of the memory (specs/recent-memory-patterns-2026-09-06 R1/R3).\n */\n\nimport { randomUUID } from 'crypto';\nimport { normalizeMemoryKind } from './memory-ref.js';\nimport {\n normalizeRetrievalTriggerType,\n normalizeTelemetryClient,\n type RecordReferenceNavigationInput,\n type RecordReferenceNavigationResult\n} from './retrieval-telemetry.js';\nimport { readTraceItems } from './retrieval-trace-ledger.js';\nimport { sqliteAll, sqliteGet, sqliteRun, type SQLiteDatabase } from './sqlite-wrapper.js';\n\n/**\n * Attribution window for an opened reference. Deliberately short: a reference\n * opened long after delivery cannot be attributed to it with confidence.\n */\nexport const REFERENCE_ATTRIBUTION_WINDOW_MS = 15 * 60 * 1000;\n\nfunction tableExists(db: SQLiteDatabase, table: string): boolean {\n return sqliteAll<{ name: string }>(\n db,\n `SELECT name FROM sqlite_master WHERE type = 'table' AND name = ?`,\n [table]\n ).length > 0;\n}\n\nfunction columnExists(db: SQLiteDatabase, table: string, column: string): boolean {\n if (!tableExists(db, table)) return false;\n return sqliteAll<{ name: string }>(db, `PRAGMA table_info(${table})`)\n .some((row) => row.name === column);\n}\n\n/**\n * Reference navigation attribution (specs/recent-memory-patterns R1/R3).\n *\n * Kept as a database-level function so callers that hold only a SQLite handle \u2014\n * `mem-lesson-get`, `mem-source-ref`, `mem-details` \u2014 can record an opened\n * reference against the trace that delivered it, with the memory's typed kind.\n * Attribution is deliberately conservative: only a unique recent reference\n * delivery is attributed, everything else stays ambiguous or unattributed.\n */\nexport function recordReferenceNavigationOnDb(\n db: SQLiteDatabase,\n input: RecordReferenceNavigationInput\n): RecordReferenceNavigationResult {\n const openedAt = input.openedAt ?? new Date();\n const windowStart = new Date(openedAt.getTime() - REFERENCE_ATTRIBUTION_WINDOW_MS).toISOString();\n const openedAtIso = openedAt.toISOString();\n const targetKind = normalizeMemoryKind(input.targetKind ?? 'event');\n const targetProjectId = input.targetProjectId ?? null;\n const hasTypedItems = tableExists(db, 'retrieval_trace_items');\n // Attribution needs delivery evidence, not just selection. A trace whose\n // context was formatted but never emitted (or whose write failed) did not put\n // this reference in front of anyone, so an open cannot belong to it\n // (specs R3, finding 10). Stores whose helpfulness rows predate the delivery\n // columns cannot express this, and keep the older selection-based behaviour\n // rather than losing every attribution.\n const deliveryEvidenceAvailable = columnExists(db, 'memory_helpfulness', 'delivery_status');\n const deliveryClock = columnExists(db, 'memory_helpfulness', 'delivered_at')\n ? 'COALESCE(delivered_at, created_at)' : 'created_at';\n const wasDelivered = (traceId: string): boolean => {\n if (!deliveryEvidenceAvailable) return true;\n // A helpfulness row written before the typed columns carries kind\n // `unknown`; it cannot disprove the match, so it is admitted alongside an\n // exact kind match rather than excluded.\n const kindClause = columnExists(db, 'memory_helpfulness', 'memory_kind')\n ? ` AND COALESCE(memory_kind, 'event') IN (?, 'unknown')`\n : '';\n const scopeClause = columnExists(db, 'memory_helpfulness', 'memory_project_id')\n ? ' AND memory_project_id IS ?' : '';\n const params: unknown[] = [traceId, input.targetEventId];\n if (kindClause) params.push(targetKind);\n if (scopeClause) params.push(targetProjectId);\n params.push(windowStart, openedAtIso);\n const row = sqliteGet<{ delivered: number }>(\n db,\n `SELECT 1 AS delivered FROM memory_helpfulness\n WHERE trace_id = ? AND event_id = ?${kindClause}${scopeClause}\n AND delivery_status IN ('emitted', 'acknowledged')\n AND julianday(${deliveryClock}) >= julianday(?)\n AND julianday(${deliveryClock}) <= julianday(?)\n LIMIT 1`,\n params\n );\n if (row) return true;\n // An instrumented store needs positive delivery evidence. Absence is\n // unknown, and must never become attributed navigation by assumption.\n return false;\n };\n // New stores use the actual delivery clock. The trace can have been selected\n // much earlier; only legacy stores without delivery evidence use selection.\n const traceWindowClause = deliveryEvidenceAvailable\n ? `EXISTS (SELECT 1 FROM memory_helpfulness\n WHERE trace_id = retrieval_traces.trace_id\n AND delivery_status IN ('emitted', 'acknowledged')\n AND julianday(${deliveryClock}) >= julianday(?)\n AND julianday(${deliveryClock}) <= julianday(?))`\n : 'julianday(created_at) >= julianday(?) AND julianday(created_at) <= julianday(?)';\n const matchesTrace = (row: Record<string, unknown>): boolean => {\n if (input.attributionSessionId && row.session_id !== input.attributionSessionId) return false;\n // Prefer typed items so opening lesson X is never attributed to a trace\n // that merely delivered an event whose id happens to match (specs R1/R3).\n let selectedHere: boolean;\n if (hasTypedItems) {\n const typed = readTraceItems(db, String(row.trace_id || ''));\n if (typed.length > 0) {\n selectedHere = typed.some((item) =>\n item.selected && item.memoryId === input.targetEventId && item.memoryKind === targetKind && item.projectId === targetProjectId);\n return selectedHere && wasDelivered(String(row.trace_id || ''));\n }\n }\n try {\n const selected = JSON.parse(String(row.selected_event_ids || '[]'));\n selectedHere = Array.isArray(selected) && selected.includes(input.targetEventId);\n } catch {\n return false;\n }\n return selectedHere && wasDelivered(String(row.trace_id || ''));\n };\n\n // A page boundary does not prove uniqueness: a matching delivery can be\n // behind hundreds of unrelated traces. Scan stable pages until exhausted or\n // two matches prove ambiguity, keeping only those two candidates in memory.\n const candidates: Record<string, unknown>[] = [];\n let cursor: Record<string, unknown> | undefined;\n while (candidates.length < 2) {\n const cursorClause = cursor\n ? ' AND (created_at < ? OR (created_at = ? AND trace_id < ?))' : '';\n const page = sqliteAll<Record<string, unknown>>(\n db,\n `SELECT trace_id, session_id, trigger_type, selected_event_ids, created_at\n FROM retrieval_traces\n WHERE presentation_mode = 'reference' AND ${traceWindowClause}${cursorClause}\n ORDER BY created_at DESC, trace_id DESC LIMIT 500`,\n [windowStart, openedAtIso, ...(cursor ? [cursor.created_at, cursor.created_at, cursor.trace_id] : [])]\n );\n for (const row of page) {\n if (matchesTrace(row)) candidates.push(row);\n if (candidates.length === 2) break;\n }\n if (page.length < 500) break;\n cursor = page[page.length - 1];\n }\n const attributed = candidates.length === 1 ? candidates[0] : undefined;\n const traceId = attributed ? String(attributed.trace_id) : null;\n const outcome = candidates.length === 1\n ? 'attributed'\n : candidates.length > 1\n ? 'ambiguous'\n : 'unattributed';\n const reason = candidates.length === 1\n ? 'unique_recent_reference_delivery'\n : candidates.length > 1\n ? 'multiple_recent_reference_deliveries'\n : 'no_recent_reference_delivery';\n const navigationClient = normalizeTelemetryClient(input.navigationClient);\n\n const repeated = sqliteGet<{ navigation_id: string }>(\n db,\n `SELECT navigation_id\n FROM retrieval_navigation_events\n WHERE target_event_id = ?\n AND memory_kind = ?\n AND memory_project_id IS ?\n AND trace_id IS ?\n AND navigation_action = ?\n AND navigation_client = ?\n AND attribution_outcome = ?\n AND julianday(last_opened_at) >= julianday(?)\n AND julianday(last_opened_at) <= julianday(?)\n ORDER BY last_opened_at DESC\n LIMIT 1`,\n [input.targetEventId, targetKind, targetProjectId, traceId, input.action, navigationClient, outcome, windowStart, openedAtIso]\n );\n\n if (repeated) {\n sqliteRun(\n db,\n `UPDATE retrieval_navigation_events\n SET open_count = open_count + 1, last_opened_at = ?\n WHERE navigation_id = ?`,\n [openedAtIso, repeated.navigation_id]\n );\n return { outcome, traceId, repeated: true };\n }\n\n sqliteRun(\n db,\n `INSERT INTO retrieval_navigation_events (\n navigation_id, target_event_id, trace_id, delivery_session_id,\n presentation_mode, trigger_type, memory_kind, memory_project_id, navigation_action, navigation_client,\n attribution_outcome, attribution_reason, open_count, first_opened_at, last_opened_at\n ) VALUES (?, ?, ?, ?, 'reference', ?, ?, ?, ?, ?, ?, ?, 1, ?, ?)`,\n [\n randomUUID(),\n input.targetEventId,\n traceId,\n attributed?.session_id || input.attributionSessionId || null,\n normalizeRetrievalTriggerType(attributed?.trigger_type),\n targetKind,\n targetProjectId,\n input.action,\n navigationClient,\n outcome,\n reason,\n openedAtIso,\n openedAtIso\n ]\n );\n return { outcome, traceId, repeated: false };\n}\n", "/**\n * Typed retrieval ledger (specs/recent-memory-patterns-2026-09-06 R1).\n *\n * `retrieval_traces` keeps its legacy id arrays for old readers. Every new\n * write additionally lands in `retrieval_trace_items`, where each reference\n * carries its kind, owning project and rank. New readers prefer the typed rows;\n * a read-only resolver reconstructs kinds for legacy traces without ever\n * mutating them.\n */\n\nimport { createHash } from 'crypto';\nimport {\n MEMORY_KINDS,\n inferMemoryKindFromLegacyId,\n memoryRefKey,\n normalizeMemoryKind,\n type MemoryKind,\n type ResolvedMemoryRef\n} from './memory-ref.js';\nimport {\n emptyTypedSelectionSummary,\n type RetrievalTraceItem,\n type RetrievalTraceItemInput,\n type TypedSelectionSummary\n} from './retrieval-telemetry.js';\nimport { sqliteAll, sqliteExec, sqliteRun, type SQLiteDatabase } from './sqlite-wrapper.js';\n\nexport const RETRIEVAL_TRACE_ITEMS_DDL = `\n CREATE TABLE IF NOT EXISTS retrieval_trace_items (\n trace_id TEXT NOT NULL,\n item_key TEXT NOT NULL,\n memory_kind TEXT NOT NULL,\n memory_id TEXT NOT NULL,\n project_id TEXT,\n rank INTEGER,\n selected INTEGER NOT NULL DEFAULT 0,\n score REAL,\n content_hash TEXT,\n memory_version TEXT,\n deleted INTEGER NOT NULL DEFAULT 0,\n created_at TEXT DEFAULT (datetime('now')),\n PRIMARY KEY (trace_id, item_key)\n );\n CREATE INDEX IF NOT EXISTS idx_retrieval_trace_items_memory\n ON retrieval_trace_items(memory_kind, memory_id);\n CREATE INDEX IF NOT EXISTS idx_retrieval_trace_items_selected\n ON retrieval_trace_items(selected, memory_kind);\n`;\n\nexport function ensureRetrievalTraceItemsSchema(db: SQLiteDatabase): void {\n sqliteExec(db, RETRIEVAL_TRACE_ITEMS_DDL);\n}\n\n/** Content hash of the delivered excerpt. The excerpt itself is never stored. */\nexport function memoryContentHash(content: string | null | undefined): string | null {\n if (typeof content !== 'string' || content.length === 0) return null;\n return `sha256:${createHash('sha256').update(content).digest('hex').slice(0, 32)}`;\n}\n\nfunction tableExists(db: SQLiteDatabase, table: string): boolean {\n return sqliteAll<{ name: string }>(\n db,\n `SELECT name FROM sqlite_master WHERE type = 'table' AND name = ?`,\n [table]\n ).length > 0;\n}\n\n/**\n * Which memory tables actually contain an id. An id present in two tables stays\n * `unknown`/`ambiguous`: guessing a kind is exactly the failure mode that made\n * lesson selections look like dangling event ids.\n */\nexport function resolveMemoryRefKinds(\n db: SQLiteDatabase,\n ids: string[],\n options: { projectId?: string | null; allowedProjectIds?: string[] } = {}\n): Map<string, ResolvedMemoryRef> {\n const resolved = new Map<string, ResolvedMemoryRef>();\n const unique = Array.from(new Set(ids.filter((id) => typeof id === 'string' && id.length > 0)));\n if (unique.length === 0) return resolved;\n\n const matches = new Map<string, Set<MemoryKind>>();\n const projectById = new Map<string, string | null>();\n const addMatch = (id: string, kind: MemoryKind, projectId: string | null) => {\n const set = matches.get(id) ?? new Set<MemoryKind>();\n set.add(kind);\n matches.set(id, set);\n if (!projectById.has(id) || projectById.get(id) === null) projectById.set(id, projectId);\n };\n\n for (let i = 0; i < unique.length; i += 400) {\n const chunk = unique.slice(i, i + 400);\n const placeholders = chunk.map(() => '?').join(',');\n // The event store is one database per project, so an event's owning\n // project is the store's project scope rather than a per-row column.\n if (tableExists(db, 'events')) {\n for (const row of sqliteAll<{ id: string }>(\n db,\n `SELECT id FROM events WHERE id IN (${placeholders})`,\n chunk\n )) addMatch(row.id, 'event', options.projectId ?? null);\n }\n if (tableExists(db, 'memory_lessons')) {\n for (const row of sqliteAll<{ lesson_id: string; project_hash: string | null }>(\n db,\n `SELECT lesson_id, project_hash FROM memory_lessons WHERE lesson_id IN (${placeholders})`,\n chunk\n )) addMatch(row.lesson_id, 'lesson', row.project_hash ?? null);\n }\n if (tableExists(db, 'consolidated_rules')) {\n for (const row of sqliteAll<{ rule_id: string }>(\n db,\n `SELECT rule_id FROM consolidated_rules WHERE rule_id IN (${placeholders})`,\n chunk\n )) addMatch(row.rule_id, 'rule', null);\n }\n // Core blocks are delivered as the pseudo-id `core:<blockKey>`. The prefix\n // alone is a claim, not proof: resolve it against the block table so a\n // reference to a block that no longer exists is reported as unresolved\n // instead of being counted as a healthy core delivery (specs R1).\n if (tableExists(db, 'core_memory_blocks')) {\n const coreKeys = chunk\n .filter((id) => inferMemoryKindFromLegacyId(id) === 'core')\n .map((id) => id.slice('core:'.length));\n if (coreKeys.length > 0) {\n const corePlaceholders = coreKeys.map(() => '?').join(',');\n for (const row of sqliteAll<{ block_key: string; project_hash: string | null }>(\n db,\n `SELECT block_key, project_hash FROM core_memory_blocks WHERE block_key IN (${corePlaceholders})`,\n coreKeys\n )) {\n addMatch(\n `core:${row.block_key}`,\n 'core',\n row.project_hash && row.project_hash.length > 0 ? row.project_hash : (options.projectId ?? null)\n );\n }\n }\n }\n }\n\n const allowed = options.allowedProjectIds ? new Set(options.allowedProjectIds) : null;\n for (const id of unique) {\n const kinds = Array.from(matches.get(id) ?? []);\n const projectId = projectById.get(id) ?? null;\n if (kinds.length === 0) {\n resolved.set(id, { id, kind: 'unknown', projectId: options.projectId ?? null, resolution: 'unresolved', matchedKinds: [] });\n continue;\n }\n if (kinds.length > 1) {\n resolved.set(id, { id, kind: 'unknown', projectId, resolution: 'ambiguous', matchedKinds: kinds });\n continue;\n }\n // A reference the caller may not read is reported, never silently typed.\n if (allowed && projectId && !allowed.has(projectId)) {\n resolved.set(id, { id, kind: 'unknown', projectId, resolution: 'forbidden', matchedKinds: kinds });\n continue;\n }\n resolved.set(id, { id, kind: kinds[0], projectId, resolution: 'resolved', matchedKinds: kinds });\n }\n return resolved;\n}\n\nexport function normalizeTraceItems(\n items: RetrievalTraceItemInput[],\n defaults: { projectId?: string | null } = {}\n): RetrievalTraceItem[] {\n const byKey = new Map<string, RetrievalTraceItem>();\n items.forEach((item, index) => {\n if (!item || typeof item.id !== 'string' || item.id.length === 0) return;\n const kind = normalizeMemoryKind(item.kind);\n const projectId = item.projectId ?? defaults.projectId ?? null;\n // Scope-aware: the same kind/id in two projects is two memories under two\n // permission boundaries and must not collapse onto one row (specs R1).\n // The key is derived from the normalized identity. Accepting a caller's\n // arbitrary key would let two different refs collapse onto one row, or the\n // same ref occupy multiple rows with conflicting metadata.\n const itemKey = memoryRefKey({ projectId, kind, id: item.id });\n const score = typeof item.score === 'number' && Number.isFinite(item.score) ? item.score : null;\n const existing = byKey.get(itemKey);\n const normalized: RetrievalTraceItem = {\n traceId: '',\n itemKey,\n memoryKind: kind,\n memoryId: item.id,\n projectId,\n rank: typeof item.rank === 'number' && Number.isFinite(item.rank) ? Math.max(0, Math.floor(item.rank)) : index,\n selected: item.selected === true || existing?.selected === true,\n score: score ?? existing?.score ?? null,\n contentHash: item.contentHash ?? existing?.contentHash ?? null,\n memoryVersion: item.memoryVersion ?? existing?.memoryVersion ?? null,\n deleted: item.deleted === true || existing?.deleted === true\n };\n byKey.set(itemKey, existing ? { ...normalized, rank: existing.rank } : normalized);\n });\n return Array.from(byKey.values());\n}\n\nexport function writeTraceItems(\n db: SQLiteDatabase,\n traceId: string,\n items: RetrievalTraceItem[]\n): void {\n if (items.length === 0) return;\n for (const item of items) {\n sqliteRun(\n db,\n `INSERT INTO retrieval_trace_items (\n trace_id, item_key, memory_kind, memory_id, project_id, rank, selected, score,\n content_hash, memory_version, deleted\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(trace_id, item_key) DO UPDATE SET\n memory_kind = excluded.memory_kind,\n memory_id = excluded.memory_id,\n project_id = excluded.project_id,\n rank = excluded.rank,\n selected = MAX(retrieval_trace_items.selected, excluded.selected),\n score = COALESCE(excluded.score, retrieval_trace_items.score),\n content_hash = COALESCE(excluded.content_hash, retrieval_trace_items.content_hash),\n memory_version = COALESCE(excluded.memory_version, retrieval_trace_items.memory_version),\n deleted = MAX(retrieval_trace_items.deleted, excluded.deleted)`,\n [\n traceId, item.itemKey, item.memoryKind, item.memoryId, item.projectId,\n item.rank, item.selected ? 1 : 0, item.score,\n item.contentHash, item.memoryVersion, item.deleted ? 1 : 0\n ]\n );\n }\n}\n\nexport function readTraceItems(db: SQLiteDatabase, traceId: string): RetrievalTraceItem[] {\n if (!tableExists(db, 'retrieval_trace_items')) return [];\n return sqliteAll<Record<string, unknown>>(\n db,\n `SELECT * FROM retrieval_trace_items WHERE trace_id = ? ORDER BY rank ASC`,\n [traceId]\n ).map(rowToTraceItem);\n}\n\nfunction rowToTraceItem(row: Record<string, unknown>): RetrievalTraceItem {\n return {\n traceId: String(row.trace_id ?? ''),\n itemKey: String(row.item_key ?? ''),\n memoryKind: normalizeMemoryKind(row.memory_kind),\n memoryId: String(row.memory_id ?? ''),\n projectId: row.project_id === null || row.project_id === undefined ? null : String(row.project_id),\n rank: row.rank === null || row.rank === undefined ? null : Number(row.rank),\n selected: Number(row.selected) === 1,\n score: row.score === null || row.score === undefined ? null : Number(row.score),\n contentHash: row.content_hash === null || row.content_hash === undefined ? null : String(row.content_hash),\n memoryVersion: row.memory_version === null || row.memory_version === undefined ? null : String(row.memory_version),\n deleted: Number(row.deleted) === 1\n };\n}\n\n/**\n * Typed selections for a window. Traces that already have typed items are read\n * as-is; older traces are resolved read-only from their legacy arrays so a\n * report can reproduce the historical event/lesson split without a migration.\n */\nexport function summarizeTypedSelections(\n db: SQLiteDatabase,\n options: { since?: Date; until?: Date; resolveLegacy?: boolean } = {}\n): TypedSelectionSummary {\n const summary = emptyTypedSelectionSummary();\n if (!tableExists(db, 'retrieval_traces')) return summary;\n\n const clauses: string[] = [];\n const params: unknown[] = [];\n if (options.since) {\n clauses.push('julianday(created_at) >= julianday(?)');\n params.push(options.since.toISOString());\n }\n if (options.until) {\n clauses.push('julianday(created_at) < julianday(?)');\n params.push(options.until.toISOString());\n }\n const where = clauses.length > 0 ? ` WHERE ${clauses.join(' AND ')}` : '';\n const traces = sqliteAll<{ trace_id: string; selected_event_ids: string | null; project_hash: string | null }>(\n db,\n `SELECT trace_id, selected_event_ids, project_hash FROM retrieval_traces${where}`,\n params\n );\n\n const hasItems = tableExists(db, 'retrieval_trace_items');\n const legacyTraces: typeof traces = [];\n for (const trace of traces) {\n const typed = hasItems ? readTraceItems(db, trace.trace_id) : [];\n if (typed.length > 0) {\n summary.typedTraces += 1;\n for (const item of typed) {\n if (!item.selected) continue;\n summary.byKind[item.memoryKind] += 1;\n summary.total += 1;\n if (item.memoryKind === 'unknown') summary.unresolved += 1;\n }\n continue;\n }\n legacyTraces.push(trace);\n }\n\n if (options.resolveLegacy === false) return summary;\n\n const legacyIds: string[] = [];\n const perTrace: Array<{ traceId: string; ids: string[]; projectId: string | null }> = [];\n for (const trace of legacyTraces) {\n let ids: string[] = [];\n try {\n const parsed = JSON.parse(trace.selected_event_ids || '[]');\n if (Array.isArray(parsed)) ids = parsed.filter((id): id is string => typeof id === 'string');\n } catch { /* corrupt legacy array contributes nothing */ }\n if (ids.length === 0) continue;\n perTrace.push({ traceId: trace.trace_id, ids, projectId: trace.project_hash ?? null });\n legacyIds.push(...ids);\n }\n if (perTrace.length === 0) return summary;\n\n const resolvedById = resolveMemoryRefKinds(db, legacyIds);\n for (const entry of perTrace) {\n summary.legacyResolvedTraces += 1;\n for (const id of entry.ids) {\n const ref = resolvedById.get(id);\n const kind = ref?.resolution === 'resolved' ? ref.kind : 'unknown';\n summary.byKind[kind] += 1;\n summary.total += 1;\n if (ref?.resolution === 'ambiguous') summary.ambiguous += 1;\n else if (!ref || ref.resolution !== 'resolved') summary.unresolved += 1;\n }\n }\n return summary;\n}\n\nexport interface TraceItemBackfillResult {\n dryRun: boolean;\n scannedTraces: number;\n tracesWithItems: number;\n writtenItems: number;\n byKind: Record<MemoryKind, number>;\n unresolved: number;\n ambiguous: number;\n}\n\n/**\n * Explicit, opt-in backfill of typed items for legacy traces. Reports never\n * call this: reading is done with the resolver above so a read-only audit\n * cannot mutate a user's store.\n */\nexport function backfillTraceItems(\n db: SQLiteDatabase,\n options: { dryRun?: boolean; limit?: number; since?: Date } = {}\n): TraceItemBackfillResult {\n const dryRun = options.dryRun !== false;\n const limit = Math.min(Math.max(options.limit ?? 1000, 1), 100_000);\n const result: TraceItemBackfillResult = {\n dryRun,\n scannedTraces: 0,\n tracesWithItems: 0,\n writtenItems: 0,\n byKind: Object.fromEntries(MEMORY_KINDS.map((kind) => [kind, 0])) as Record<MemoryKind, number>,\n unresolved: 0,\n ambiguous: 0\n };\n if (!tableExists(db, 'retrieval_traces')) return result;\n if (!dryRun) ensureRetrievalTraceItemsSchema(db);\n // A dry run against a store that predates the typed table still previews\n // every legacy trace: creating the table just to count would be a write.\n const hasItemsTable = tableExists(db, 'retrieval_trace_items');\n if (!dryRun && !hasItemsTable) return result;\n\n const clauses: string[] = [];\n const params: unknown[] = [];\n if (options.since) {\n clauses.push('julianday(t.created_at) >= julianday(?)');\n params.push(options.since.toISOString());\n }\n if (hasItemsTable) {\n clauses.push('NOT EXISTS (SELECT 1 FROM retrieval_trace_items i WHERE i.trace_id = t.trace_id)');\n }\n // Empty traces never gain typed rows, so letting them consume the limit\n // would select the same empty batch forever. Filter usable arrays before\n // LIMIT, including corrupt legacy JSON and arrays without string IDs.\n clauses.push(`(${['candidate_event_ids', 'selected_event_ids'].map((column) =>\n `EXISTS (SELECT 1 FROM json_each(\n CASE WHEN json_valid(t.${column}) THEN\n CASE WHEN json_type(t.${column}) = 'array' THEN t.${column} ELSE '[]' END\n ELSE '[]' END\n ) AS id WHERE id.type = 'text' AND length(trim(id.value)) > 0)`\n ).join(' OR ')})`);\n params.push(limit);\n\n const traces = sqliteAll<{\n trace_id: string;\n selected_event_ids: string | null;\n candidate_event_ids: string | null;\n project_hash: string | null;\n }>(\n db,\n `SELECT t.trace_id, t.selected_event_ids, t.candidate_event_ids, t.project_hash\n FROM retrieval_traces t\n ${clauses.length > 0 ? `WHERE ${clauses.join(' AND ')}` : ''}\n ORDER BY t.created_at DESC\n LIMIT ?`,\n params\n );\n\n for (const trace of traces) {\n result.scannedTraces += 1;\n const selected = parseIdArray(trace.selected_event_ids);\n const candidates = parseIdArray(trace.candidate_event_ids);\n const all = Array.from(new Set([...candidates, ...selected]));\n if (all.length === 0) continue;\n const resolvedById = resolveMemoryRefKinds(db, all, { projectId: trace.project_hash ?? null });\n const items = normalizeTraceItems(\n all.map((id, index) => {\n const ref = resolvedById.get(id);\n if (ref?.resolution === 'ambiguous') result.ambiguous += 1;\n else if (!ref || ref.resolution !== 'resolved') result.unresolved += 1;\n const kind = ref?.resolution === 'resolved' ? ref.kind : 'unknown';\n result.byKind[kind] += 1;\n return {\n kind,\n id,\n projectId: ref?.projectId ?? trace.project_hash ?? null,\n rank: index,\n selected: selected.includes(id),\n // An id that resolves to no row today may have been deleted, may\n // predate a table, or may live in a store this reader cannot see.\n // `deleted` is reserved for an observed deletion; an unresolved\n // reference stays kind `unknown` and is counted as unresolved.\n deleted: false\n };\n }),\n { projectId: trace.project_hash ?? null }\n );\n result.tracesWithItems += 1;\n result.writtenItems += items.length;\n if (!dryRun) writeTraceItems(db, trace.trace_id, items);\n }\n return result;\n}\n\nfunction parseIdArray(value: string | null): string[] {\n if (!value) return [];\n try {\n const parsed = JSON.parse(value);\n return Array.isArray(parsed) ? parsed.filter((id): id is string => typeof id === 'string' && id.length > 0) : [];\n } catch {\n return [];\n }\n}\n"],
5
- "mappings": "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AAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KA6zBnB;AAID,SAAK,mBAAmB,uBAAuB,UAAU,gCAAgC;AACzF,QAAI;AACF,YAAM,cAAc,UAA4C,KAAK,IAAI,0CAA0C,CAAC,CAAC;AACrH,YAAM,uBAAuB,YAAY,KAAK,CAAC,UAAU;AACvD,YAAI,OAAO,MAAM,MAAM,MAAM,EAAG,QAAO;AACvC,YAAI,CAAC,kBAAkB,KAAK,MAAM,IAAI,EAAG,QAAO;AAChD,cAAM,cAAc,MAAM,KAAK,QAAQ,MAAM,IAAI;AACjD,cAAM,UAAU,UAA4B,KAAK,IAAI,wBAAwB,cAAc,MAAM,CAAC,CAAC,EAChG,IAAI,CAAC,WAAW,OAAO,IAAI;AAC9B,eAAO,QAAQ,WAAW,KACrB,QAAQ,CAAC,MAAM,mBACf,QAAQ,CAAC,MAAM,cACf,QAAQ,CAAC,MAAM,cACf,QAAQ,CAAC,MAAM,YACf,QAAQ,CAAC,MAAM;AAAA,MACtB,CAAC;AACD,UAAI,CAAC,sBAAsB;AACzB,mBAAW,KAAK,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAsBnB;AAAA,MACH;AAAA,IACF,QAAQ;AAAA,IAER;AAMA,SAAK,mBAAmB,sBAAsB,YAAY,MAAM;AAChE,SAAK,mBAAmB,sBAAsB,UAAU,4BAA4B;AACpF,SAAK,mBAAmB,sBAAsB,yBAAyB,MAAM;AAC7E,SAAK,mBAAmB,sBAAsB,iBAAiB,MAAM;AACrE,SAAK,mBAAmB,sBAAsB,oBAAoB,MAAM;AACxE,SAAK,mBAAmB,sBAAsB,qBAAqB,iCAAiC;AACpG,SAAK,mBAAmB,sBAAsB,gBAAgB,iCAAiC;AAC/F,SAAK,mBAAmB,sBAAsB,mBAAmB,iCAAiC;AAClG,QAAI;AACF,iBAAW,KAAK,IAAI,mFAAmF;AAAA,IACzG,QAAQ;AAAA,IAER;AAGA,SAAK,mBAAmB,oBAAoB,yBAAyB,MAAM;AAC3E,SAAK,mBAAmB,oBAAoB,0BAA0B,MAAM;AAC5E,SAAK,mBAAmB,oBAAoB,kBAAkB,MAAM;AACpE,SAAK,mBAAmB,oBAAoB,sBAAsB,MAAM;AACxE,SAAK,mBAAmB,oBAAoB,qBAAqB,iCAAiC;AAClG,SAAK,mBAAmB,oBAAoB,gBAAgB,iCAAiC;AAC7F,SAAK,mBAAmB,oBAAoB,mBAAmB,iCAAiC;AAIhG,SAAK,mBAAmB,oBAAoB,kBAAkB,uCAAuC;AACrG,SAAK,mBAAmB,oBAAoB,8BAA8B,MAAM;AAChF,SAAK,mBAAmB,oBAAoB,cAAc,MAAM;AAChE,SAAK,mBAAmB,oBAAoB,qBAAqB,MAAM;AACvE,SAAK,mBAAmB,oBAAoB,mBAAmB,MAAM;AACrE,SAAK,mBAAmB,oBAAoB,4BAA4B,4BAA4B;AACpG,SAAK,mBAAmB,sBAAsB,eAAe,iCAAiC;AAC9F,SAAK,mBAAmB,+BAA+B,eAAe,+BAA+B;AACrG,SAAK,mBAAmB,+BAA+B,qBAAqB,MAAM;AAClF,SAAK,mBAAmB,sBAAsB,mBAAmB,iCAAiC;AAClG,SAAK,mBAAmB,sBAAsB,qBAAqB,8BAA8B;AACjG,SAAK,mBAAmB,sBAAsB,gBAAgB,MAAM;AACpE,SAAK,mBAAmB,qCAAqC,eAAe,iCAAiC;AAC7G,SAAK,mBAAmB,qCAAqC,mBAAmB,iCAAiC;AACjH,SAAK,mBAAmB,qCAAqC,qBAAqB,8BAA8B;AAChH,SAAK,mBAAmB,qCAAqC,wBAAwB,SAAS;AAC9F,SAAK,mBAAmB,qCAAqC,qBAAqB,MAAM;AAKxF,SAAK,mBAAmB,qCAAqC,aAAa,MAAM;AAChF,SAAK,mBAAmB,qCAAqC,qBAAqB,MAAM;AACxF,SAAK,mBAAmB,sBAAsB,qBAAqB,MAAM;AACzE,QAAI;AAGF,sCAAgC,KAAK,EAAE;AAGvC,iBAAW,KAAK,IAAI,6FAA6F;AAAA,IACnH,QAAQ;AAAA,IAER;AACA,QAAI;AAIF;AAAA,QACE,KAAK;AAAA,QACL;AAAA;AAAA,MAEF;AAAA,IACF,QAAQ;AAAA,IAIR;AAIA,SAAK,mBAAmB,kBAAkB,gBAAgB,iCAAiC;AAI3F,SAAK,mBAAmB,kBAAkB,gBAAgB,4BAA4B;AACtF,SAAK,mBAAmB,kBAAkB,oBAAoB,MAAM;AACpE,SAAK,mBAAmB,kBAAkB,YAAY,4BAA4B;AAClF,SAAK,mBAAmB,kBAAkB,kBAAkB,4BAA4B;AACxF,SAAK,mBAAmB,kBAAkB,SAAS,MAAM;AACzD,SAAK,mBAAmB,kBAAkB,mBAAmB,4BAA4B;AACzF,SAAK,mBAAmB,kBAAkB,mBAAmB,MAAM;AACnE,SAAK,mBAAmB,kBAAkB,uBAAuB,4BAA4B;AAC7F,SAAK,mBAAmB,sBAAsB,cAAc,0BAA0B;AACtF,SAAK,mBAAmB,sBAAsB,yBAAyB,4BAA4B;AACnG,SAAK,mBAAmB,4BAA4B,6BAA6B,4BAA4B;AAC7G,QAAI;AACF,iBAAW,KAAK,IAAI,oIAAoI;AACxJ,iBAAW,KAAK,IAAI,iJAAiJ;AAAA,IACvK,QAAQ;AAAA,IAER;AACA,QAAI;AACF,iBAAW,KAAK,IAAI,6GAA6G;AAAA,IACnI,QAAQ;AAAA,IAER;AAKA,SAAK,mBAAmB,UAAU,gBAAgB,mBAAmB;AACrE,SAAK,mBAAmB,UAAU,oBAAoB,MAAM;AAC5D,SAAK,mBAAmB,UAAU,WAAW,MAAM;AAGnD,QAAI;AACF,iBAAW,KAAK,IAAI;AAAA;AAAA,OAEnB;AAAA,IACH,SAAS,KAAU;AAAA,IAEnB;AAEA,QAAI;AACF,iBAAW,KAAK,IAAI;AAAA;AAAA,OAEnB;AAAA,IACH,SAAS,KAAU;AAAA,IAEnB;AAEA,QAAI;AACF,iBAAW,KAAK,IAAI;AAAA;AAAA,OAEnB;AAAA,IACH,QAAQ;AAAA,IAER;AAIA,UAAM,WAAW,UAAyB,KAAK,IAAI,wDAAwD,CAAC,CAAC;AAC7G,SAAK,UAAU,KAAK,OAAO,GAAG;AAC5B,iBAAW,KAAK,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA,OAKnB;AAAA,IACH;AAKA,eAAW,KAAK,IAAI,yBAAyB,qBAAqB,EAAE;AAEpE,SAAK,cAAc;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAO,OAAgD;AAC3D,UAAM,KAAK,WAAW;AAEtB,UAAM,eAAe,iBAAiB,MAAM,OAAO;AACnD,UAAM,YAAY,cAAc,MAAM,SAAS,MAAM,SAAS;AAG9D,UAAM,WAAW;AAAA,MACf,KAAK;AAAA,MACL;AAAA,MACA,CAAC,SAAS;AAAA,IACZ;AAEA,QAAI,UAAU;AACZ,UAAI;AACF,cAAM,KAAK,yBAAyB,SAAS,UAAU,MAAM,SAAS;AAAA,MACxE,SAAS,OAAO;AACd,eAAO;AAAA,UACL,SAAS;AAAA,UACT,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,QAC9D;AAAA,MACF;AACA,aAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS,SAAS;AAAA,QAClB,aAAa;AAAA,MACf;AAAA,IACF;AAEA,UAAM,KAAKC,YAAW;AACtB,UAAM,YAAY,kBAAkB,MAAM,SAAS;AAEnD,QAAI;AAEF,YAAM,WAAW,MAAM,YAAY,CAAC;AACpC,YAAM,SAAU,SAAS,UAAqB;AAG9C,YAAM,cAAc,KAAK,GAAG,QAAQ;AAAA;AAAA;AAAA,OAGnC;AAED,YAAM,cAAc,KAAK,GAAG,QAAQ;AAAA;AAAA,OAEnC;AAED,YAAM,cAAc,KAAK,GAAG,QAAQ;AAAA;AAAA,OAEnC;AAED,YAAM,cAAc,KAAK,GAAG,YAAY,MAAM;AAC5C,oBAAY;AAAA,UACV;AAAA,UACA,MAAM;AAAA,UACN,MAAM;AAAA,UACN;AAAA,UACA,MAAM;AAAA,UACN;AAAA,UACA;AAAA,UACA,KAAK,UAAU,QAAQ;AAAA,UACvB;AAAA,QACF;AACA,oBAAY,IAAI,WAAW,EAAE;AAC7B,oBAAY,IAAI,EAAE;AAClB,aAAK,6BAA6B,IAAI,MAAM,SAAS;AAAA,MACvD,CAAC;AAED,kBAAY;AAEZ,UAAI,KAAK,gBAAgB;AACvB,cAAM,QAAqB;AAAA,UACzB;AAAA,UACA,WAAW,MAAM;AAAA,UACjB,WAAW,MAAM;AAAA,UACjB,WAAW,MAAM;AAAA,UACjB,SAAS,MAAM;AAAA,UACf;AAAA,UACA;AAAA,UACA;AAAA,QACF;AACA,aAAK,eAAe,OAAO,KAAK,EAAE,MAAM,CAAC,QAAQ;AAC/C,kBAAQ,KAAK,qDAAqD,GAAG;AAAA,QACvE,CAAC;AAAA,MACH;AAEA,aAAO,EAAE,SAAS,MAAM,SAAS,IAAI,aAAa,MAAM;AAAA,IAC1D,SAAS,OAAO;AACd,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,MAC9D;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,0BAA0B,kBAA0B,QAAQ,GAAsB;AACtF,UAAM,KAAK,WAAW;AACtB,UAAM,OAAO;AAAA,MACX,KAAK;AAAA,MACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAWA,CAAC,kBAAkB,KAAK;AAAA,IAC1B;AACA,WAAO,KAAK,IAAI,CAAC,MAAM,EAAE,UAAU;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAAiB,WAAmB,SAAyD;AACjG,UAAM,KAAK,WAAW;AAEtB,UAAM,OAAO;AAAA,MACX,KAAK;AAAA,MACL,iDAAiD,yBAAyB,OAAO,CAAC;AAAA,MAClF,CAAC,SAAS;AAAA,IACZ;AAEA,WAAO,KAAK,IAAI,KAAK,UAAU;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,gBAAgB,QAAgB,KAAK,SAA2D;AACpG,UAAM,KAAK,WAAW;AAEtB,UAAM,aAAa,SAAS,cAAc,CAAC;AAC3C,UAAM,gBAAgB,WAAW,SAAS,IACtC,sBAAsB,WAAW,IAAI,MAAM,GAAG,EAAE,KAAK,IAAI,CAAC,MAC1D;AAEJ,UAAM,OAAO;AAAA,MACX,KAAK;AAAA,MACL;AAAA,eACS,yBAAyB,OAAO,CAAC,IAAI,aAAa;AAAA;AAAA,MAE3D,CAAC,GAAG,YAAY,KAAK;AAAA,IACvB;AAEA,WAAO,KAAK,IAAI,KAAK,UAAU;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,mBAAmB,SAAuF;AAC9G,UAAM,KAAK,WAAW;AACtB,UAAM,OAAO;AAAA,MACX,KAAK;AAAA,MACL,0DAA0D,yBAAyB,OAAO,CAAC;AAAA,MAC3F,CAAC;AAAA,IACH;AACA,WAAO,KAAK,IAAI,CAAC,SAAS,EAAE,WAAW,IAAI,YAAY,OAAO,IAAI,MAAM,EAAE;AAAA,EAC5E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,eAAe,UAAkB,SAAyD;AAC9F,UAAM,KAAK,WAAW;AACtB,UAAM,OAAO;AAAA,MACX,KAAK;AAAA,MACL,iDAAiD,yBAAyB,OAAO,CAAC;AAAA,MAClF,CAAC,QAAQ;AAAA,IACX;AACA,WAAO,KAAK,IAAI,CAAC,QAAQ,KAAK,WAAW,GAAG,CAAC;AAAA,EAC/C;AAAA;AAAA,EAGA,MAAM,wBAAwB,SAAkD;AAC9E,UAAM,KAAK,WAAW;AACtB,UAAM,MAAM;AAAA,MACV,KAAK;AAAA,MACL,gEAAgE,yBAAyB,OAAO,CAAC;AAAA,MACjG,CAAC;AAAA,IACH;AACA,WAAO,KAAK,SAAS;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,oBACJ,UACA,SACmG;AACnG,UAAM,KAAK,WAAW;AACtB,WAAO;AAAA,MACL,KAAK;AAAA,MACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kCAM4B,yBAAyB,OAAO,CAAC;AAAA;AAAA;AAAA,MAG7D,CAAC,QAAQ;AAAA,IACX;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAS,IAAY,SAA8D;AACvF,UAAM,KAAK,WAAW;AAEtB,UAAM,MAAM;AAAA,MACV,KAAK;AAAA,MACL,yCAAyC,yBAAyB,OAAO,CAAC;AAAA,MAC1E,CAAC,EAAE;AAAA,IACL;AAEA,QAAI,CAAC,IAAK,QAAO;AACjB,WAAO,KAAK,WAAW,GAAG;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,UAAU,KAAe,SAAyD;AACtF,UAAM,KAAK,WAAW;AACtB,QAAI,IAAI,WAAW,EAAG,QAAO,CAAC;AAE9B,UAAM,eAAe,IAAI,IAAI,MAAM,GAAG,EAAE,KAAK,GAAG;AAChD,UAAM,OAAO;AAAA,MACX,KAAK;AAAA,MACL,qCAAqC,YAAY,SAAS,yBAAyB,OAAO,CAAC;AAAA,MAC3F;AAAA,IACF;AAEA,WAAO,KAAK,IAAI,CAAC,QAAQ,KAAK,WAAW,GAAG,CAAC;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,qBAAqB,YAAoB,SAA8D;AAC3G,UAAM,KAAK,WAAW;AACtB,QAAI,CAAC,WAAY,QAAO;AAExB,QAAI,MAAM;AAAA,MACR,KAAK;AAAA,MACL;AAAA,MACA,CAAC,UAAU;AAAA,IACb;AAEA,QAAI,CAAC,KAAK;AACR,WAAK,sBAAsB;AAC3B,YAAM;AAAA,QACJ,KAAK;AAAA,QACL;AAAA,QACA,CAAC,UAAU;AAAA,MACb;AAAA,IACF;AAEA,QAAI,CAAC,IAAK,QAAO;AACjB,WAAO,KAAK,SAAS,IAAI,UAAU,OAAO;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,wBAA8B;AACpC,UAAM,aAAa,UAAyB,KAAK,IAAI,oCAAoC,CAAC,CAAC,GAAG,KAAK;AACnG,UAAM,eAAe,UAAyB,KAAK,IAAI,6CAA6C,CAAC,CAAC,GAAG,KAAK;AAC9G,QAAI,gBAAgB,WAAY;AAEhC,UAAM,YAAY;AAAA,MAChB,KAAK;AAAA,MACL;AAAA;AAAA;AAAA,MAGA,CAAC;AAAA,IACH;AACA,QAAI,UAAU,WAAW,EAAG;AAE5B,UAAM,SAAS,KAAK,GAAG,QAAQ,6EAA6E;AAC5G,SAAK,GAAG,YAAY,MAAM;AACxB,iBAAW,EAAE,GAAG,KAAK,WAAW;AAC9B,eAAO,IAAI,IAAI,mBAAmB,EAAE,CAAC;AAAA,MACvC;AAAA,IACF,CAAC,EAAE;AAAA,EACL;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eAAe,WAAmB,QAAgB,KAAM,SAAyD;AACrH,UAAM,KAAK,WAAW;AAEtB,UAAM,OAAO;AAAA,MACX,KAAK;AAAA,MACL,gDAAgD,yBAAyB,OAAO,CAAC;AAAA,MACjF,CAAC,WAAW,KAAK;AAAA,IACnB;AAEA,WAAO,KAAK,IAAI,KAAK,UAAU;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,oBACJ,WACA,QAAgB,KAChB,SACuD;AACvD,UAAM,KAAK,WAAW;AAEtB,UAAM,OAAO;AAAA,MACX,KAAK;AAAA,MACL,6DAA6D,yBAAyB,OAAO,CAAC;AAAA,MAC9F,CAAC,WAAW,KAAK;AAAA,IACnB;AAEA,WAAO,KAAK,IAAI,UAAQ;AAAA,MACtB,OAAO,IAAI;AAAA,MACX,OAAO,KAAK,WAAW,GAAG;AAAA,IAC5B,EAAE;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,aAAa,QAAuE;AACxF,QAAI,OAAO,WAAW,EAAG,QAAO,EAAE,UAAU,GAAG,SAAS,EAAE;AAC1D,QAAI,KAAK,SAAU,QAAO,EAAE,UAAU,GAAG,SAAS,OAAO,OAAO;AAEhE,UAAM,KAAK,WAAW;AAEtB,UAAM,UAAU,KAAK,GAAG,QAAQ,oCAAoC;AACpE,UAAM,cAAc,KAAK,GAAG,QAAQ,uDAAuD;AAE3F,UAAM,cAAc,KAAK,GAAG,QAAQ;AAAA;AAAA;AAAA,KAGnC;AAED,UAAM,cAAc,KAAK,GAAG,QAAQ;AAAA;AAAA,KAEnC;AAED,UAAM,cAAc,KAAK,GAAG,QAAQ;AAAA;AAAA,KAEnC;AAED,QAAI,WAAW;AACf,QAAI,UAAU;AACd,UAAM,iBAAgC,CAAC;AAEvC,UAAM,KAAK,KAAK,GAAG,YAAY,CAAC,UAAyB;AACvD,iBAAW,MAAM,OAAO;AAEtB,cAAM,eAAe,QAAQ,IAAI,GAAG,EAAE;AACtC,YAAI,cAAc;AAChB;AACA;AAAA,QACF;AAEA,cAAM,eAAe,GAAG,gBAAgB,iBAAiB,GAAG,OAAO;AACnE,cAAM,YAAY,GAAG,aAAa,cAAc,GAAG,SAAS,GAAG,SAAS;AAGxE,cAAM,mBAAmB,YAAY,IAAI,SAAS;AAClD,YAAI,kBAAkB;AACpB;AACA;AAAA,QACF;AAEA,cAAM,WAAW,GAAG,YAAY,CAAC;AACjC,cAAM,SAAU,SAAiB;AAEjC,oBAAY;AAAA,UACV,GAAG;AAAA,UACH,GAAG;AAAA,UACH,GAAG;AAAA,UACH,kBAAkB,GAAG,SAAS;AAAA,UAC9B,GAAG;AAAA,UACH;AAAA,UACA;AAAA,UACA,KAAK,UAAU,QAAQ;AAAA,UACvB,UAAU;AAAA,QACZ;AAEA,oBAAY,IAAI,WAAW,GAAG,EAAE;AAChC,oBAAY,IAAI,GAAG,EAAE;AACrB,aAAK,6BAA6B,GAAG,IAAI,GAAG,SAAS;AACrD;AACA,uBAAe,KAAK,EAAE;AAAA,MACxB;AAAA,IACF,CAAC;AAED,OAAG,MAAM;AAET,QAAI,KAAK,kBAAkB,eAAe,SAAS,GAAG;AACpD,iBAAW,MAAM,gBAAgB;AAC/B,aAAK,eAAe,OAAO,EAAE,EAAE,MAAM,CAAC,QAAQ;AAC5C,kBAAQ,KAAK,qDAAqD,GAAG;AAAA,QACvE,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO,EAAE,UAAU,QAAQ;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAc,SAA2D;AAC7E,UAAM,KAAK,WAAW;AAEtB,UAAM,WAAW;AAAA,MACf,KAAK;AAAA,MACL;AAAA,MACA,CAAC,QAAQ,EAAE;AAAA,IACb;AAEA,QAAI,CAAC,UAAU;AACb;AAAA,QACE,KAAK;AAAA,QACL;AAAA;AAAA,QAEA;AAAA,UACE,QAAQ;AAAA,UACR,kBAAkB,QAAQ,aAAa,oBAAI,KAAK,CAAC;AAAA,UACjD,QAAQ,eAAe;AAAA,UACvB,KAAK,UAAU,QAAQ,QAAQ,CAAC,CAAC;AAAA,QACnC;AAAA,MACF;AAAA,IACF,OAAO;AACL,YAAM,UAAoB,CAAC;AAC3B,YAAM,SAAoB,CAAC;AAE3B,UAAI,QAAQ,SAAS;AACnB,gBAAQ,KAAK,cAAc;AAC3B,eAAO,KAAK,kBAAkB,QAAQ,OAAO,CAAC;AAAA,MAChD;AACA,UAAI,QAAQ,SAAS;AACnB,gBAAQ,KAAK,aAAa;AAC1B,eAAO,KAAK,QAAQ,OAAO;AAAA,MAC7B;AACA,UAAI,QAAQ,MAAM;AAChB,gBAAQ,KAAK,UAAU;AACvB,eAAO,KAAK,KAAK,UAAU,QAAQ,IAAI,CAAC;AAAA,MAC1C;AAEA,UAAI,QAAQ,SAAS,GAAG;AACtB,eAAO,KAAK,QAAQ,EAAE;AACtB;AAAA,UACE,KAAK;AAAA,UACL,uBAAuB,QAAQ,KAAK,IAAI,CAAC;AAAA,UACzC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAW,IAAqC;AACpD,UAAM,KAAK,WAAW;AAEtB,UAAM,MAAM;AAAA,MACV,KAAK;AAAA,MACL;AAAA,MACA,CAAC,EAAE;AAAA,IACL;AAEA,QAAI,CAAC,IAAK,QAAO;AAEjB,WAAO;AAAA,MACL,IAAI,IAAI;AAAA,MACR,WAAW,iBAAiB,IAAI,UAAU;AAAA,MAC1C,SAAS,IAAI,WAAW,iBAAiB,IAAI,QAAQ,IAAI;AAAA,MACzD,aAAa,IAAI;AAAA,MACjB,SAAS,IAAI;AAAA,MACb,MAAM,IAAI,OAAO,KAAK,MAAM,IAAI,IAAc,IAAI;AAAA,IACpD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAAqC;AACzC,UAAM,KAAK,WAAW;AAEtB,UAAM,OAAO;AAAA,MACX,KAAK;AAAA,MACL;AAAA,IACF;AAEA,WAAO,KAAK,IAAI,UAAQ;AAAA,MACtB,IAAI,IAAI;AAAA,MACR,WAAW,iBAAiB,IAAI,UAAU;AAAA,MAC1C,SAAS,IAAI,WAAW,iBAAiB,IAAI,QAAQ,IAAI;AAAA,MACzD,aAAa,IAAI;AAAA,MACjB,SAAS,IAAI;AAAA,MACb,MAAM,IAAI,OAAO,KAAK,MAAM,IAAI,IAAc,IAAI;AAAA,IACpD,EAAE;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,oBAAoB,SAAiB,SAAkC;AAC3E,UAAM,KAAK,WAAW;AAEtB,UAAM,KAAKA,YAAW;AACtB;AAAA,MACE,KAAK;AAAA,MACL;AAAA;AAAA,MAEA,CAAC,IAAI,SAAS,OAAO;AAAA,IACvB;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,sBAAsB,QAAgB,IAA2B;AACrE,UAAM,KAAK,WAAW;AAOtB,UAAM,UAAU;AAAA,MACd,KAAK;AAAA,MACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MASA,CAAC,KAAK;AAAA,IACR;AAEA,QAAI,QAAQ,WAAW,EAAG,QAAO,CAAC;AAGlC,YAAQ,KAAK,CAAC,GAAG,MAAM,OAAO,EAAE,UAAU,EAAE,cAAc,OAAO,EAAE,UAAU,CAAC,CAAC;AAE/E,WAAO,QAAQ,IAAI,UAAQ;AAAA,MACzB,IAAI,IAAI;AAAA,MACR,SAAS,IAAI;AAAA,MACb,SAAS,IAAI;AAAA,MACb,QAAQ;AAAA,MACR,YAAY,IAAI;AAAA,MAChB,WAAW,iBAAiB,IAAI,UAAU;AAAA,MAC1C,cAAc,IAAI;AAAA,IACpB,EAAE;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,oBAAoB,KAA8B;AACtD,QAAI,IAAI,WAAW,EAAG;AAEtB,UAAM,eAAe,IAAI,IAAI,MAAM,GAAG,EAAE,KAAK,GAAG;AAChD;AAAA,MACE,KAAK;AAAA,MACL,6CAA6C,YAAY;AAAA,MACzD;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,uBAAsC;AAC1C,UAAM,KAAK,WAAW;AACtB,cAAU,KAAK,IAAI,8BAA8B;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAY,SAAkD;AAClE,UAAM,KAAK,WAAW;AACtB,UAAM,MAAM,UAA6B,KAAK,IAAI,8CAA8C,yBAAyB,OAAO,CAAC,EAAE;AACnI,WAAO,KAAK,SAAS;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAc,QAAgB,KAAM,SAAiB,GAAG,SAAyD;AACrH,UAAM,KAAK,WAAW;AAEtB,UAAM,OAAO;AAAA,MACX,KAAK;AAAA,MACL,8BAA8B,yBAAyB,OAAO,CAAC;AAAA,MAC/D,CAAC,OAAO,MAAM;AAAA,IAChB;AAEA,WAAO,KAAK,IAAI,KAAK,UAAU;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBAAgB,KAAe,OAA8B;AACjE,QAAI,IAAI,WAAW,EAAG;AAEtB,UAAM,eAAe,IAAI,IAAI,MAAM,GAAG,EAAE,KAAK,GAAG;AAChD;AAAA,MACE,KAAK;AAAA,MACL;AAAA;AAAA;AAAA;AAAA,sBAIgB,YAAY;AAAA,MAC5B,CAAC,OAAO,GAAG,GAAG;AAAA,IAChB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,wBAAwB,UAAiC,CAAC,GAAkC;AAChG,UAAM,KAAK,WAAW;AAEtB,UAAM,cAAc,OAAO,SAAS,QAAQ,gBAAgB,MAAM,QAAQ,oBAAoB,MAAM,IAChG,QAAQ,mBACR;AACJ,UAAM,aAAa,OAAO,SAAS,QAAQ,UAAU,MAAM,QAAQ,cAAc,KAAK,IAClF,QAAQ,aACR;AACJ,UAAM,MAAM,QAAQ,OAAO,oBAAI,KAAK;AACpC,UAAM,YAAY,IAAI,KAAK,IAAI,QAAQ,IAAI,WAAW,EAAE,YAAY;AACpE,UAAM,SAAS,0BAA0B;AAEzC,QAAI,QAAQ,WAAW,MAAM;AAC3B,YAAMC,sBAAqB;AAAA,QACzB,KAAK;AAAA,QACL;AAAA;AAAA;AAAA,QAGA,CAAC,SAAS;AAAA,MACZ;AACA,aAAO,UAAU,sBAAsB,OAAOA,qBAAoB,SAAS,CAAC;AAE5E,YAAMC,oBAAmB;AAAA,QACvB,KAAK;AAAA,QACL;AAAA;AAAA;AAAA,QAGA,CAAC,UAAU;AAAA,MACb;AACA,aAAO,UAAU,gBAAgB,OAAOA,mBAAkB,SAAS,CAAC;AAEpE,YAAMC,mBAAkB;AAAA,QACtB,KAAK;AAAA,QACL;AAAA;AAAA;AAAA,QAGA,CAAC,SAAS;AAAA,MACZ;AACA,aAAO,OAAO,sBAAsB,OAAOA,kBAAiB,SAAS,CAAC;AAEtE,YAAMC,iBAAgB;AAAA,QACpB,KAAK;AAAA,QACL;AAAA;AAAA;AAAA,QAGA,CAAC,UAAU;AAAA,MACb;AACA,aAAO,OAAO,gBAAgB,OAAOA,gBAAe,SAAS,CAAC;AAE9D,aAAO;AAAA,IACT;AAEA,UAAM,qBAAqB;AAAA,MACzB,KAAK;AAAA,MACL;AAAA;AAAA;AAAA;AAAA,MAIA,CAAC,SAAS;AAAA,IACZ;AACA,WAAO,UAAU,sBAAsB,OAAO,mBAAmB,WAAW,CAAC;AAE7E,UAAM,mBAAmB;AAAA,MACvB,KAAK;AAAA,MACL;AAAA;AAAA;AAAA;AAAA,MAIA,CAAC,UAAU;AAAA,IACb;AACA,WAAO,UAAU,gBAAgB,OAAO,iBAAiB,WAAW,CAAC;AAErE,UAAM,kBAAkB;AAAA,MACtB,KAAK;AAAA,MACL;AAAA;AAAA;AAAA;AAAA,MAIA,CAAC,IAAI,YAAY,GAAG,SAAS;AAAA,IAC/B;AACA,WAAO,OAAO,sBAAsB,OAAO,gBAAgB,WAAW,CAAC;AAEvE,UAAM,gBAAgB;AAAA,MACpB,KAAK;AAAA,MACL;AAAA;AAAA;AAAA;AAAA,MAIA,CAAC,IAAI,YAAY,GAAG,UAAU;AAAA,IAChC;AACA,WAAO,OAAO,gBAAgB,OAAO,cAAc,WAAW,CAAC;AAE/D,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,mBAAmB,WAAsC;AAC7D,UAAM,KAAK,WAAW;AACtB,UAAM,OAAO;AAAA,MACX,KAAK;AAAA,MACL;AAAA,MACA,CAAC,SAAS;AAAA,IACZ;AACA,WAAO,KAAK,IAAI,CAAC,QAAQ,IAAI,EAAE;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,kCAAkC,UAAqC;AAC3E,QAAI,SAAS,WAAW,EAAG,QAAO;AAClC,UAAM,KAAK,WAAW;AACtB,UAAM,eAAe,SAAS,IAAI,MAAM,GAAG,EAAE,KAAK,IAAI;AACtD,UAAM,SAAS,KAAK,GAAG;AAAA,MACrB,uEAAuE,YAAY;AAAA,IACrF,EAAE,IAAI,GAAG,QAAQ;AACjB,WAAO,OAAO,OAAO,WAAW,CAAC;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,yBAAyB,UAAqC,CAAC,GAAsC;AACzG,UAAM,KAAK,WAAW;AAEtB,UAAM,cAAc,QAAQ,gBAAgB,QAAQ,cAAc,gBAAgB,QAAQ,WAAW,IAAI;AACzG,QAAI,CAAC,aAAa;AAChB,YAAM,IAAI,MAAM,8DAA8D;AAAA,IAChF;AACA,QACE,QAAQ,eAAe,QAAQ,eAC5B,gBAAgB,QAAQ,WAAW,MAAM,QAAQ,eAIjD,8BAA8B,QAAQ,WAAW,MAAM,QAAQ,aAClE;AACA,YAAM,IAAI,MAAM,wFAAwF;AAAA,IAC1G;AAEA,UAAM,SAAS,QAAQ,WAAW;AAClC,UAAM,UAAU,QAAQ,OAAO,oBAAI,KAAK,GAAG,YAAY;AACvD,UAAM,SAAS,kBAAkB,aAAa,MAAM;AAEpD,UAAM,OAAO;AAAA,MAMX,KAAK;AAAA,MACL;AAAA;AAAA;AAAA;AAAA,MAIA,CAAC;AAAA,IACH;AAEA,UAAM,SAAS,CAAC,UAAoC;AAClD,UAAI,OAAO,QAAQ,SAAS,GAAI,QAAO,QAAQ,KAAK,KAAK;AAAA,IAC3D;AAEA,eAAW,OAAO,MAAM;AACtB,aAAO;AAEP,UAAI,WAAoC,CAAC;AACzC,UAAI,uBAAuB;AAC3B,UAAI,IAAI,UAAU;AAChB,cAAM,SAAS,uBAAuB,IAAI,QAAQ;AAClD,YAAI,QAAQ;AACV,qBAAW;AAAA,QACb,OAAO;AACL,iCAAuB;AAAA,QACzB;AAAA,MACF;AAEA,UAAI,4BAA4B,QAAQ,GAAG;AACzC,eAAO;AACP;AAAA,MACF;AAEA,YAAM,cAAc,oBAAoB,QAAQ;AAChD,YAAM,eAAe,oBAAoB,QAAQ;AACjD,YAAM,qBAAqB,OAAO,IAAI,yBAAyB,YAAY,IAAI,qBAAqB,SAAS,IACzG,IAAI,uBACJ;AACJ,YAAM,iBAAiB,qBAAqB,QAAQ;AACpD,UAAI,sBAAsB,CAAC,eAAe,SAAS,kBAAkB,GAAG;AACtE,uBAAe,KAAK,kBAAkB;AAAA,MACxC;AACA,YAAM,mBAAmB,wBAAwB,iCAAiC,QAAQ,KAAK,QAAQ,kBAAkB;AACzH,YAAM,aAAa,eAAe,IAAI,CAAC,cAAc;AACnD,YAAI;AACF,iBAAO;AAAA,YACL,MAAM;AAAA,YACN,MAAM,gBAAgB,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,YAK/B,eAAe,8BAA8B,SAAS;AAAA,UACxD;AAAA,QACF,QAAQ;AACN,iBAAO,EAAE,MAAM,WAAW,MAAM,QAAW,eAAe,OAAU;AAAA,QACtE;AAAA,MACF,CAAC;AACD,YAAM,qBAAqB,CAAC,cAC1B,UAAU,SAAS,eAAe,UAAU,kBAAkB;AAChE,YAAM,eAAe,WAAW,KAAK,kBAAkB;AACvD,YAAM,cAAc,WAAW,KAAK,CAAC,cAAc,UAAU,QAAQ,CAAC,mBAAmB,SAAS,CAAC;AAEnG,UAAI,SAAiD;AACrD,UAAI;AACJ,UAAI;AAEJ,UAAI,aAAa;AACf,iBAAS;AACT,iBAAS;AACT,8BAAsB,YAAY;AAAA,MACpC,WAAW,gBAAgB,eAAe,oBAAoB,iCAAiC,IAAI,SAAS,QAAQ,WAAW,GAAG;AAChI,iBAAS;AACT,iBAAS;AAAA,MACX,WAAW,gBAAgB,aAAa;AACtC,eAAO;AACP;AAAA,MACF,WACE,eAAe,gBAAgB,eAM5B,EAAE,gBAAgB,aAAa,kBAAkB,cACpD;AACA,iBAAS;AACT,iBAAS;AACT,8BAAsB;AAAA,MACxB,WAAW,cAAc;AACvB,iBAAS;AACT,iBAAS,aAAa,SAAS,sBAAsB,aAAa,SAAS,eACvE,yBACA;AAAA,MACN,WAAW,eAAe,SAAS,GAAG;AACpC,iBAAS;AACT,iBAAS;AAAA,MACX,WAAW,kBAAkB;AAC3B,iBAAS;AACT,iBAAS;AAAA,MACX;AAEA,UAAI,WAAW,aAAa,CAAC,QAAQ;AACnC,eAAO;AACP;AAAA,MACF;AAEA,UAAI,WAAW,YAAY;AACzB,cAAM,QAAQ,SAAS,SAAS,KAAK,IAAI,EAAE,GAAG,SAAS,MAAM,IAAI,CAAC;AAClE,cAAM,UAAU,SAAS,MAAM,OAAO,IAAI,EAAE,GAAG,MAAM,QAAQ,IAAI,CAAC;AAClE,gBAAQ,OAAO;AACf,cAAM,UAAU;AAChB,iBAAS,QAAQ;AACjB,iBAAS,SAAS;AAAA,UAChB,GAAI,SAAS,SAAS,MAAM,IAAI,SAAS,SAAS,CAAC;AAAA,UACnD,oBAAoB;AAAA,YAClB;AAAA,YACA;AAAA,YACA,YAAY;AAAA,UACd;AAAA,QACF;AACA,uBAAe,UAAU,QAAQ,WAAW,EAAE;AAC9C,eAAO;AAAA,MACT,OAAO;AACL,iBAAS,aAAa;AAAA,UACpB,GAAI,SAAS,SAAS,UAAU,IAAI,SAAS,aAAa,CAAC;AAAA,UAC3D,QAAQ;AAAA,UACR,UAAU;AAAA,UACV;AAAA,UACA,YAAY;AAAA,UACZ,qBAAqB;AAAA,UACrB,GAAI,sBAAsB,EAAE,oBAAoB,IAAI,CAAC;AAAA,QACvD;AACA,iBAAS,SAAS;AAAA,UAChB,GAAI,SAAS,SAAS,MAAM,IAAI,SAAS,SAAS,CAAC;AAAA,UACnD,oBAAoB;AAAA,YAClB;AAAA,YACA;AAAA,YACA,YAAY;AAAA,UACd;AAAA,QACF;AACA,uBAAe,UAAU,0BAA0B;AACnD,eAAO;AAAA,MACT;AAEA,aAAO,EAAE,SAAS,IAAI,IAAI,QAAQ,OAAO,CAAC;AAC1C,UAAI,CAAC,QAAQ;AACX,kBAAU,KAAK,IAAI,+CAA+C,CAAC,KAAK,UAAU,QAAQ,GAAG,IAAI,EAAE,CAAC;AAAA,MACtG;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eAAe,UAA8B,CAAC,GAAyB;AAC3E,UAAM,KAAK,WAAW;AAEtB,UAAM,cAAc,OAAO,SAAS,QAAQ,gBAAgB,MAAM,QAAQ,oBAAoB,MAAM,IAChG,QAAQ,mBACR;AACJ,UAAM,aAAa,OAAO,SAAS,QAAQ,UAAU,MAAM,QAAQ,cAAc,KAAK,IAClF,QAAQ,aACR;AACJ,UAAM,MAAM,QAAQ,OAAO,oBAAI,KAAK;AACpC,UAAM,YAAY,IAAI,KAAK,IAAI,QAAQ,IAAI,WAAW,EAAE,YAAY;AAEpE,UAAM,gBAAgB;AAAA,MACpB,KAAK;AAAA,MACL;AAAA,IACF;AACA,UAAM,aAAa;AAAA,MACjB,KAAK;AAAA,MACL;AAAA,IACF;AAEA,UAAM,kBAAkB,CAAC,UAAkC;AACzD,UAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAClD,YAAM,OAAO,iBAAiB,KAAK;AACnC,YAAM,OAAO,KAAK,QAAQ;AAC1B,UAAI,CAAC,OAAO,SAAS,IAAI,EAAG,QAAO;AACnC,aAAO,KAAK,IAAI,GAAG,IAAI,QAAQ,IAAI,IAAI;AAAA,IACzC;AAEA,UAAM,WAAW,CACf,MACA,iBACA,uBACA,iBACA,sBACG;AACH,YAAM,MAAM,EAAE,SAAS,GAAG,YAAY,GAAG,QAAQ,GAAG,iBAAiB,mBAAmB,OAAO,GAAG,iBAAiB,sBAAsB;AACzI,iBAAW,OAAO,MAAM;AACtB,cAAM,MAAM,IAAI;AAChB,YAAI,QAAQ,aAAa,QAAQ,gBAAgB,QAAQ,UAAU;AACjE,cAAI,GAAG,KAAK,OAAO,IAAI,SAAS,CAAC;AAAA,QACnC;AACA,YAAI,SAAS,OAAO,IAAI,SAAS,CAAC;AAAA,MACpC;AACA,aAAO;AAAA,IACT;AAEA,UAAM,iBAAiB;AAAA,MACrB,KAAK;AAAA,MACL;AAAA;AAAA;AAAA;AAAA,MAIA,CAAC,SAAS;AAAA,IACZ;AACA,UAAM,kBAAkB;AAAA,MACtB,KAAK;AAAA,MACL;AAAA;AAAA;AAAA,IAGF;AACA,UAAM,2BAA2B;AAAA,MAC/B,KAAK;AAAA,MACL;AAAA;AAAA;AAAA;AAAA,MAIA,CAAC,UAAU;AAAA,IACb;AACA,UAAM,6BAA6B;AAAA,MACjC,KAAK;AAAA,MACL;AAAA;AAAA;AAAA;AAAA,MAIA,CAAC,UAAU;AAAA,IACb;AAEA,UAAM,cAAc;AAAA,MAClB,KAAK;AAAA,MACL;AAAA;AAAA;AAAA;AAAA,MAIA,CAAC,SAAS;AAAA,IACZ;AACA,UAAM,eAAe;AAAA,MACnB,KAAK;AAAA,MACL;AAAA;AAAA;AAAA,IAGF;AACA,UAAM,wBAAwB;AAAA,MAC5B,KAAK;AAAA,MACL;AAAA;AAAA;AAAA;AAAA,MAIA,CAAC,UAAU;AAAA,IACb;AACA,UAAM,0BAA0B;AAAA,MAC9B,KAAK;AAAA,MACL;AAAA;AAAA;AAAA;AAAA,MAIA,CAAC,UAAU;AAAA,IACb;AAEA,WAAO;AAAA,MACL,WAAW;AAAA,QACT;AAAA,QACA,OAAO,gBAAgB,SAAS,CAAC;AAAA,QACjC,gBAAgB,iBAAiB,MAAM;AAAA,QACvC,OAAO,0BAA0B,SAAS,CAAC;AAAA,QAC3C,OAAO,4BAA4B,SAAS,CAAC;AAAA,MAC/C;AAAA,MACA,QAAQ;AAAA,QACN;AAAA,QACA,OAAO,aAAa,SAAS,CAAC;AAAA,QAC9B,gBAAgB,cAAc,MAAM;AAAA,QACpC,OAAO,uBAAuB,SAAS,CAAC;AAAA,QACxC,OAAO,yBAAyB,SAAS,CAAC;AAAA,MAC5C;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,kBAAkB,SAAiB,OAA8B;AACrE,UAAM,KAAK,WAAW;AAEtB;AAAA,MACE,KAAK;AAAA,MACL;AAAA,MACA,CAAC,OAAO,OAAO;AAAA,IACjB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBAAkE;AACtE,UAAM,KAAK,WAAW;AAEtB,UAAM,OAAO;AAAA,MACX,KAAK;AAAA,MACL;AAAA;AAAA;AAAA,eAGS,wBAAwB,YAAY,CAAC;AAAA;AAAA,IAEhD;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAAiB,OAAe,SAAuE;AAC3G,UAAM,KAAK,WAAW;AAEtB,UAAM,QAAQ,SAAS,SAAS;AAChC,UAAM,SAAS,SAAS,UAAU;AAElC,UAAM,OAAO;AAAA,MACX,KAAK;AAAA,MACL;AAAA;AAAA;AAAA,eAGS,wBAAwB,YAAY,CAAC;AAAA;AAAA;AAAA,MAG9C,CAAC,OAAO,OAAO,MAAM;AAAA,IACvB;AAEA,WAAO,KAAK,IAAI,SAAO,KAAK,WAAW,GAAG,CAAC;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,wBAAwB,OAAe,SAAoD;AAC/F,UAAM,KAAK,WAAW;AAEtB,UAAM,OAAO;AAAA,MACX,KAAK;AAAA,MACL;AAAA;AAAA;AAAA;AAAA,eAIS,wBAAwB,YAAY,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,MAK9C,CAAC,OAAO,QAAQ,KAAK;AAAA,IACvB;AAEA,WAAO,KAAK,IAAI,SAAO,KAAK,WAAW,GAAG,CAAC;AAAA,EAC7C;AAAA;AAAA,EAGA,MAAM,qBAAqB,UAMvB;AACF,UAAM,KAAK,WAAW;AACtB,QAAI,SAAS,WAAW,EAAG,QAAO,CAAC;AACnC,UAAM,eAAe,SAAS,IAAI,MAAM,GAAG,EAAE,KAAK,IAAI;AACtD,UAAM,OAAO;AAAA,MACX,KAAK;AAAA,MACL;AAAA;AAAA,sBAEgB,YAAY;AAAA;AAAA,eAEnB,wBAAwB,UAAU,CAAC;AAAA,MAC5C;AAAA,IACF;AACA,UAAM,cAAc;AAAA,MAClB,KAAK;AAAA,MACL;AAAA;AAAA,4BAEsB,YAAY;AAAA;AAAA,MAElC;AAAA,IACF;AACA,UAAM,gBAAgB,IAAI,IAAI,YAAY,IAAI,CAAC,QAAQ,CAAC,IAAI,UAAU,OAAO,IAAI,aAAa,CAAC,CAAC,CAAC;AACjG,WAAO,KAAK,IAAI,CAAC,SAAS;AAAA,MACxB,SAAS,IAAI;AAAA,MACb,aAAa,OAAO,IAAI,YAAY;AAAA,MACpC,cAAc,iBAAiB,IAAI,oBAAoB,IAAI,SAAS;AAAA,MACpE,kBAAkB,KAAK,IAAI,IAAI,cAAc,IAAI,IAAI,EAAE,KAAK,KAAK,CAAC;AAAA;AAAA,MAElE,YAAY;AAAA,IACd,EAAE;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,oBAAoB,OAMR;AAChB,UAAM,KAAK,WAAW;AACtB,QAAI,KAAK,SAAU;AAEnB,UAAM,UAAUJ,YAAW;AAC3B,UAAMK,UAAS,MAAM;AACrB,UAAM,YAAY,MAAM,UAAU,YAAY;AAC9C,UAAM,aAAa,MAAM,WAAW,YAAY;AAChD,UAAM,YAAY,KAAK,IAAI,GAAG,MAAM,WAAW,QAAQ,IAAI,MAAM,UAAU,QAAQ,CAAC;AAEpF;AAAA,MACE,KAAK;AAAA,MACL;AAAA;AAAA;AAAA;AAAA,MAIA;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,OAAO,qBAAqB;AAAA,QAC5BA;AAAA,QACAA,YAAW,WAAW,sBAAsB;AAAA,MAC9C;AAAA,IACF;AAEA;AAAA,MACE,KAAK;AAAA,MACL;AAAA;AAAA,MAEA;AAAA,QACEL,YAAW;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,QACAK,YAAW,WAAW,IAAI;AAAA,QAC1BA,YAAW,WAAW,sBAAsB;AAAA,QAC5C;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,sBAAsB,aAAmD;AAC7E,UAAM,KAAK,WAAW;AAEtB,UAAM,WAAW;AAAA,MACf,KAAK;AAAA,MACL;AAAA,MACA,CAAC,sBAAsB;AAAA,IACzB;AACA,UAAM,SAAS;AAAA,MACb,KAAK;AAAA,MACL;AAAA;AAAA;AAAA;AAAA,MAIA,CAAC,sBAAsB;AAAA,IACzB;AACA,UAAM,mBAAmB;AAAA,MACvB,KAAK;AAAA,MACL;AAAA;AAAA;AAAA;AAAA,MAIA,CAAC,sBAAsB;AAAA,IACzB;AACA,UAAM,aAAa,QAAQ,WAAW,aAAa,QAAQ,WAAW,kBAAkB,QAAQ,WAAW,WACvG,OAAO,SACP;AACJ,UAAM,kBAAkB;AAAA,MACtB,KAAK;AAAA,MACL;AAAA;AAAA;AAAA,oCAG8B,wBAAwB,YAAY,CAAC;AAAA,IACrE;AACA,QAAI,iBAAiB;AACrB,QAAI;AACF,YAAM,UAAU;AAAA,QACd,KAAK;AAAA,QACL,cACI,qGACA;AAAA,QACJ,cAAc,CAAC,WAAW,IAAI,CAAC;AAAA,MACjC;AACA,uBAAiB,OAAO,SAAS,SAAS,CAAC;AAAA,IAC7C,QAAQ;AAAA,IAER;AAEA,WAAO;AAAA,MACL,YAAY;AAAA,QACV,UAAU,OAAO,UAAU,SAAS,CAAC;AAAA,QACrC,eAAe,QAAQ,eAAe;AAAA,QACtC,eAAe,kBAAkB,eAAe;AAAA,QAChD;AAAA,QACA,mBAAmB,eAAe,WAAW,sBAAsB;AAAA,MACrE;AAAA,MACA,SAAS;AAAA,QACP,iBAAiB,OAAO,iBAAiB,SAAS,CAAC;AAAA,QACnD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAc,SAAyC;AAC3D,UAAM,KAAK,WAAW;AAEtB,UAAM,MAAM;AAAA,MACV,KAAK;AAAA,MACL;AAAA,MACA,CAAC,OAAO;AAAA,IACV;AAEA,WAAO,MAAM,IAAI,QAAQ;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBAAgB,YAA2F;AAC/G,UAAM,KAAK,WAAW;AAEtB,UAAM,MAAM;AAAA,MACV,KAAK;AAAA,MACL;AAAA,MACA,CAAC,UAAU;AAAA,IACb;AAEA,WAAO;AAAA,MACL,aAAa,KAAK,iBAAiB;AAAA,MACnC,eAAe,KAAK,kBAAkB;AAAA,IACxC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,mBAAmB,YAAoB,aAAqB,eAAsC;AACtG,UAAM,KAAK,WAAW;AAEtB;AAAA,MACE,KAAK;AAAA,MACL;AAAA;AAAA,MAEA,CAAC,YAAY,aAAa,aAAa;AAAA,IACzC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAAiB,KAAsC;AAC3D,UAAM,KAAK,WAAW;AAEtB,UAAM,MAAM;AAAA,MACV,KAAK;AAAA,MACL;AAAA,MACA,CAAC,GAAG;AAAA,IACN;AAEA,QAAI,CAAC,IAAK,QAAO;AACjB,WAAO,KAAK,MAAM,IAAI,KAAK;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAAiB,KAAa,OAA+B;AACjE,UAAM,KAAK,WAAW;AAEtB;AAAA,MACE,KAAK;AAAA,MACL;AAAA;AAAA,MAEA,CAAC,KAAK,KAAK,UAAU,KAAK,CAAC;AAAA,IAC7B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,qBAAqB,MAAuE;AAChG,QAAI,KAAK,WAAW,KAAK,KAAK,SAAU;AAExC,UAAM,KAAK,WAAW;AAKtB,UAAM,QAAQ,KACX,IAAI,CAAC,QAAS,OAAO,QAAQ,WAAW,EAAE,MAAM,SAAuB,IAAI,IAAI,IAAI,GAAI,EACvF,OAAO,CAAC,QAAQ,QAAQ,KAAK,EAAE,CAAC;AACnC,UAAM,WAAW,MAAM,KAAK,IAAI,IAAI,MACjC,OAAO,CAAC,QAAQ,oBAAoB,IAAI,IAAI,MAAM,OAAO,EACzD,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;AACxB,UAAM,YAAY,MAAM,KAAK,IAAI,IAAI,MAClC,OAAO,CAAC,QAAQ,oBAAoB,IAAI,IAAI,MAAM,QAAQ,EAC1D,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;AACxB,UAAM,cAAc,kBAAkB,oBAAI,KAAK,CAAC;AAEhD,QAAI,SAAS,SAAS,GAAG;AACvB;AAAA,QACE,KAAK;AAAA,QACL;AAAA;AAAA;AAAA,wBAGgB,SAAS,IAAI,MAAM,GAAG,EAAE,KAAK,GAAG,CAAC;AAAA,QACjD,CAAC,aAAa,GAAG,QAAQ;AAAA,MAC3B;AAAA,IACF;AACA,QAAI,UAAU,SAAS,KAAK,KAAK,eAAe,kBAAkB,cAAc,GAAG;AACjF;AAAA,QACE,KAAK;AAAA,QACL;AAAA;AAAA;AAAA,+BAGuB,UAAU,IAAI,MAAM,GAAG,EAAE,KAAK,GAAG,CAAC;AAAA,QACzD,CAAC,aAAa,GAAG,SAAS;AAAA,MAC5B;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBAAgB,QAAgB,IAAI,SAAyD;AACjG,UAAM,KAAK,WAAW;AAGtB,QAAI,OAAO;AAAA,MACT,KAAK;AAAA,MACL;AAAA;AAAA,eAES,yBAAyB,OAAO,CAAC;AAAA;AAAA;AAAA,MAG1C,CAAC,KAAK;AAAA,IACR;AAGA,QAAI,KAAK,WAAW,GAAG;AACrB,aAAO;AAAA,QACL,KAAK;AAAA,QACL;AAAA,iBACS,yBAAyB,OAAO,CAAC;AAAA;AAAA;AAAA,QAG1C,CAAC,KAAK;AAAA,MACR;AAAA,IACF;AAEA,WAAO,KAAK,IAAI,SAAO,KAAK,WAAW,GAAG,CAAC;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBACJ,SACA,WACA,OACA,OACA,SAce;AACf,QAAI,KAAK,SAAU;AACnB,UAAM,KAAK,WAAW;AAEtB,UAAM,KAAKL,YAAW;AAItB;AAAA,MACE,KAAK;AAAA,MACL;AAAA;AAAA;AAAA;AAAA;AAAA,MAKA;AAAA,QACE;AAAA,QAAI;AAAA,QAAS;AAAA,QAAW;AAAA,QAAO,MAAM,MAAM,GAAG,GAAG;AAAA,QACjD,SAAS,WAAW;AAAA,QACpB,SAAS,UAAU;AAAA,QACnB,SAAS,kBAAkB,QAAQ,gBAAgB,MAAM,GAAG,GAAI,IAAI;AAAA,QACpE,oBAAoB,SAAS,cAAc,OAAO;AAAA,QAClD,wBAAwB,SAAS,kBAAkB,WAAW;AAAA,QAC9D,0BAA0B,SAAS,oBAAoB,mBAAmB;AAAA,QAC1E,mCAAmC,SAAS,gBAAgB;AAAA,QAC5D,8BAA8B,SAAS,WAAW;AAAA,QAClD,yBAAyB,SAAS,cAAc;AAAA,SAChD,oBAAI,KAAK,GAAE,YAAY;AAAA,QACvB,SAAS,iBAAiB,KAAK,KAAK;AAAA,MACtC;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,sBAAsB,OAOR;AAClB,QAAI,MAAM,MAAM,WAAW,EAAG,QAAO;AACrC,QAAI,KAAK,SAAU,QAAO;AAC1B,UAAM,KAAK,WAAW;AACtB,UAAM,UAAU,MAAM,SAAS,KAAK;AACpC,QAAI,CAAC,QAAS,QAAO;AACrB,UAAMK,UAAS,wBAAwB,MAAM,MAAM;AACnD,UAAM,WAAW,0BAA0B,MAAM,QAAQ;AACzD,UAAM,eAAe,MAAM,eAAe,oBAAI,KAAK,GAAG,YAAY;AAClE,UAAM,sBAAsB,oBAAoBA,OAAM,MAAM;AAK5D,UAAM,qBAAqB,KAAK,eAAe,sBAAsB,aAAa;AAClF,UAAM,SAAoB,CAACA,SAAQ,UAAU,sBAAsB,IAAI,GAAG,aAAa,OAAO;AAC9F,QAAI,YAAY;AAChB,QAAI,MAAM,QAAQ,MAAM,KAAK,SAAS,GAAG;AACvC,UAAI,oBAAoB;AACtB,oBAAY,SAAS,MAAM,KAAK,IAAI,MAAM,kFAAkF,EAAE,KAAK,MAAM,CAAC;AAC1I,mBAAW,OAAO,MAAM,KAAM,QAAO,KAAK,IAAI,IAAI,oBAAoB,IAAI,IAAI,GAAG,IAAI,aAAa,IAAI;AAAA,MACxG,OAAO;AACL,oBAAY,qBAAqB,MAAM,KAAK,IAAI,MAAM,GAAG,EAAE,KAAK,GAAG,CAAC;AACpE,eAAO,KAAK,GAAG,MAAM,KAAK,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC;AAAA,MAChD;AAAA,IACF;AAKA,UAAM,YAAY,oBAAoBA,OAAM;AAC5C,UAAM,oBAA+B;AAAA,MACnCA;AAAA,MAAQ;AAAA,MAAU,cAAc,OAAO,OAAO,YAAY,IAAI;AAAA,MAC9D;AAAA,MAAS;AAAA,IACX;AACA,QAAI,oBAAoB;AACxB,QAAI,MAAM,QAAQ,MAAM,KAAK,SAAS,GAAG;AACvC,0BAAoB,qBAAqB,MAAM,KAAK,IAAI,MAAM,GAAG,EAAE,KAAK,GAAG,CAAC;AAC5E,wBAAkB,KAAK,GAAG,MAAM,KAAK,IAAI,CAAC,QAAQ,iBAAiB,oBAAoB,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,SAAS,CAAC,CAAC;AAAA,IAC3H;AAGA,WAAO,KAAK,0BAA0B,MAAM;AAC1C,UAAI,iBAAiB,EAAE,mBAAmB;AACxC,cAAM,iBAAiB,cAAc,OAAO,OAAO,YAAY,IAAI;AAInE;AAAA,UAAU,KAAK;AAAA,UACb;AAAA,+BACqB,SAAS;AAAA;AAAA;AAAA,kCAGN,oBAAoB,oBAAoB,CAAC;AAAA;AAAA;AAAA,UAGjE,CAAC,SAAS,GAAG,OAAO,MAAM,CAAC,GAAG,sCAAsC,cAAc;AAAA,QAAC;AACrF;AAAA,UAAU,KAAK;AAAA,UACb;AAAA;AAAA;AAAA,yDAG+C,iBAAiB;AAAA,UAChE;AAAA,YAAC,cAAc,QAAQ,iBAAiB;AAAA,YAAW;AAAA,YACjD;AAAA,YAAsC,GAAG,kBAAkB,MAAM,CAAC;AAAA,YAAG;AAAA,UAAc;AAAA,QAAC;AAAA,MAC1F;AACA,YAAM,SAAS;AAAA,QACb,KAAK;AAAA,QACL;AAAA;AAAA;AAAA,6BAGqB,SAAS;AAAA,QAC9B;AAAA,MACF;AACA,UAAI,iBAAiB,EAAE,mBAAmB;AACxC;AAAA,UACE,KAAK;AAAA,UACL;AAAA;AAAA,yDAE+C,iBAAiB;AAAA,UAChE;AAAA,QACF;AAAA,MACF;AACA,aAAO,OAAO,QAAQ,WAAW,CAAC;AAAA,IACpC,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,uBAAuB,kBAA0B,QAAQ,GAAsB;AACnF,UAAM,KAAK,WAAW;AACtB,UAAM,OAAO;AAAA,MACX,KAAK;AAAA,MACL;AAAA;AAAA;AAAA,MAGA,CAAC,kBAAkB,KAAK;AAAA,IAC1B;AACA,WAAO,KAAK,IAAI,CAAC,MAAM,EAAE,UAAU;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,2BAA2B,WAAkC;AACjE,QAAI,KAAK,SAAU;AACnB,UAAM,KAAK,WAAW;AAGtB,UAAM,aAAa;AAAA,MACjB,KAAK;AAAA,MACL;AAAA,MACA,CAAC,SAAS;AAAA,IACZ;AAEA,QAAI,WAAW,WAAW,EAAG;AAC7B,UAAM,KAAK,sBAAsB,WAAW,UAAU;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,4BAA4B,UAI9B,CAAC,GAAwG;AAC3G,UAAM,WAAW,QAAQ,YAAY;AACrC,UAAM,MAAM,QAAQ,OAAO,oBAAI,KAAK;AACpC,UAAM,UAAU,EAAE,qBAAqB,GAAG,iBAAiB,GAAG,UAAU,QAAQ,IAAI,YAAY,EAAE;AAClG,QAAI,KAAK,SAAU,QAAO;AAC1B,UAAM,KAAK,WAAW;AACtB,QAAI,CAAC,KAAK,eAAe,qCAAqC,mBAAmB,EAAG,QAAO;AAE3F,UAAM,QAAQ,KAAK,IAAI,KAAK,IAAI,QAAQ,SAAS,KAAK,CAAC,GAAG,GAAK;AAC/D,UAAM,OAAO;AAAA,MACX,KAAK;AAAA,MACL,eAAe,KAAK,gCAAgC,CAAC;AAAA;AAAA;AAAA,MAGrD,CAAC,sCAAsC,IAAI,YAAY,GAAG,KAAK;AAAA,IACjE;AACA,QAAI,KAAK,WAAW,EAAG,QAAO;AAE9B,UAAM,YAAY,oBAAI,IAAuC;AAC7D,eAAW,OAAO,MAAM;AACtB,YAAM,YAAY,OAAO,IAAI,cAAc,EAAE;AAC7C,UAAI,CAAC,UAAW;AAChB,YAAM,OAAO,UAAU,IAAI,SAAS,KAAK,CAAC;AAC1C,WAAK,KAAK,GAAG;AACb,gBAAU,IAAI,WAAW,IAAI;AAAA,IAC/B;AACA,eAAW,CAAC,WAAW,WAAW,KAAK,WAAW;AAChD,YAAM,KAAK,sBAAsB,WAAW,aAAa,EAAE,aAAa,IAAI,CAAC;AAC7E,cAAQ,uBAAuB;AAC/B,cAAQ,mBAAmB,YAAY;AAAA,IACzC;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWQ,kCAA0C;AAChD,UAAM,YAAY,KAAK,eAAe,sBAAsB,cAAc,IACtE,6CACA;AACJ,WAAO;AAAA;AAAA;AAAA,2BAGgB,oBAAoB,IAAI,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0DAQM,SAAS;AAAA;AAAA,yCAE1B,SAAS;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,8BAA8B,UAA0B,CAAC,GAAqD;AAClH,UAAM,KAAK,WAAW;AACtB,UAAM,MAAM,QAAQ,OAAO,oBAAI,KAAK;AACpC,UAAM,SAAS,IAAI,YAAY;AAC/B,QAAI,CAAC,KAAK,SAAS,mCAAmC,KACjD,CAAC,KAAK,eAAe,qCAAqC,mBAAmB,GAAG;AACnF,aAAO,EAAE,aAAa,GAAG,OAAO;AAAA,IAClC;AACA,UAAM,MAAM;AAAA,MACV,KAAK;AAAA,MACL,8BAA8B,KAAK,gCAAgC,CAAC;AAAA,MACpE,CAAC,sCAAsC,MAAM;AAAA,IAC/C;AACA,WAAO,EAAE,aAAa,OAAO,KAAK,WAAW,CAAC,GAAG,OAAO;AAAA,EAC1D;AAAA,EAEA,MAAc,sBACZ,WACA,YACA,UAAkC,CAAC,GACpB;AAEf,UAAM,gBAAgB;AAAA,MACpB,KAAK;AAAA,MACL;AAAA,MACA,CAAC,SAAS;AAAA,IACZ;AAEA,UAAM,eAAe,cAAc,OAAO,CAAC,MAAW,EAAE,eAAe,aAAa;AACpF,UAAM,aAAa,cAAc,OAAO,CAAC,MAAW,EAAE,eAAe,kBAAkB;AACvF,UAAM,iBAAiB,cAAc,OAAO,CAAC,MAAW,EAAE,eAAe,gBAAgB;AAMzF,UAAM,oBAAoB,MAAM,KAAK,IAAI,IAAI,WAC1C,OAAO,CAAC,MAAM,oBAAoB,EAAE,eAAe,OAAO,MAAM,OAAO,EACvE,IAAI,CAAC,MAAM,EAAE,QAAkB,EAC/B,OAAO,OAAO,CAAC,CAAC;AACnB,UAAM,oBAAoB,oBAAI,IAAoB;AAClD,aAAS,IAAI,GAAG,IAAI,kBAAkB,QAAQ,KAAK,KAAK;AACtD,YAAM,QAAQ,kBAAkB,MAAM,GAAG,IAAI,GAAG;AAChD,YAAM,OAAO;AAAA,QACX,KAAK;AAAA,QACL,+CAA+C,MAAM,IAAI,MAAM,GAAG,EAAE,KAAK,GAAG,CAAC;AAAA,QAC7E;AAAA,MACF;AACA,iBAAW,OAAO,KAAM,mBAAkB,IAAI,IAAI,IAAI,IAAI,OAAO;AAAA,IACnE;AAKA,UAAM,YAAY,CAAC,UAA2B;AAC5C,YAAM,MAAM,OAAO,SAAS,EAAE;AAC9B,YAAM,MAAM,IAAI,SAAS,GAAG,IAAI,MAAM,GAAG,IAAI,QAAQ,KAAK,GAAG,CAAC;AAC9D,YAAM,KAAK,IAAI,KAAK,GAAG,EAAE,QAAQ;AACjC,aAAO,OAAO,SAAS,EAAE,IAAI,KAAK;AAAA,IACpC;AAEA,eAAW,aAAa,YAAY;AAIlC,YAAM,eAAe,UAAU,UAAU,UAAU;AACnD,YAAM,gBAAgB,UAAU,eAAe,UAAU,UAAU,YAAY,IAAI;AACnF,YAAM,kBAAkB,gBAAgB,IAAI,gBAAgB;AAG5D,YAAM,cAAc,cAAc,OAAO,CAAC,MAAW,UAAU,EAAE,SAAS,IAAI,eAAe;AAC7F,YAAM,mBAAmB,YAAY,SAAS,IAAI,IAAI;AAGtD,YAAM,eAAe,aAAa,OAAO,CAAC,MAAW,UAAU,EAAE,SAAS,IAAI,eAAe;AAC7F,YAAM,mBAAmB,aAAa;AACtC,YAAM,oBAAoB,WACvB,OAAO,CAAC,MAAW,UAAU,EAAE,SAAS,IAAI,eAAe,EAC3D,IAAI,CAAC,UAAU,iBAAiB,MAAM,OAAO,CAAC;AACjD,YAAM,uBAAuB,kBAAkB,OAAO,CAAC,YAAY,YAAY,SAAS;AACxF,YAAM,mBAAmB,qBAAqB,OAAO,CAAC,YAAY,YAAY,SAAS,EAAE;AACzF,YAAM,iBAAiB,qBAAqB;AAC5C,YAAM,mBAAmB,iBAAiB,IAAI,mBAAmB,iBAAiB;AAGlF,YAAM,aAAa,IAAI,KAAK,UAAU,iBAA2B,IAAI,YAAY,EAAE,MAAM,KAAK,EAAE,OAAO,OAAK,EAAE,SAAS,CAAC,CAAC;AACzH,UAAI,aAAa;AACjB,iBAAW,KAAK,cAAc;AAC5B,cAAM,SAAS,IAAI,IAAK,EAAE,QAAmB,YAAY,EAAE,MAAM,KAAK,EAAE,OAAO,CAAC,MAAc,EAAE,SAAS,CAAC,CAAC;AAC3G,YAAI,UAAU;AACd,mBAAW,KAAK,YAAY;AAC1B,cAAI,OAAO,IAAI,CAAC,EAAG;AAAA,QACrB;AACA,YAAI,WAAW,OAAO,KAAK,UAAU,WAAW,OAAO,KAAK;AAC1D,uBAAa;AACb;AAAA,QACF;AAAA,MACF;AAMA,YAAM,iBAAiB,eACpB,OAAO,CAAC,MAAW,UAAU,EAAE,SAAS,IAAI,eAAe,EAC3D,IAAI,CAAC,OAAY,EAAE,IAAI,EAAE,IAAc,SAAS,EAAE,SAAmB,WAAW,EAAE,UAAU,EAAE;AAKjG,YAAM,gBAAiB,UAAU,oBAC5B,kBAAkB,IAAI,UAAU,QAAkB,KAClD;AACL,YAAM,mBAAmB,mCAAmC,UAAU,iBAAiB;AACvF,UAAI,sBAAqC;AACzC,UAAI,kBAAmC,CAAC;AACxC,UAAI,qBAAqB,eAAe,eAAe,SAAS,KAAK,eAAe;AAClF,cAAM,WAAW,2BAA2B,eAAe,cAAc;AACzE,8BAAsB,SAAS;AAC/B,0BAAkB,SAAS;AAAA,MAC7B;AAEA,YAAM,gBAAgB,kBAAkB;AACxC,YAAM,cAAc,QAAQ,eAAe,oBAAI,KAAK;AACpD,YAAM,qBAAqB,KAAK,IAAI,YAAY,QAAQ,GAAG,aAAa;AACxE,YAAM,iBAAiB,aAAa,OAAO,CAAC,UAAU,UAAU,MAAM,SAAS,KAAK,kBAAkB;AACtG,YAAM,sBAAsB,WACzB,OAAO,CAAC,UAAU;AACjB,cAAM,cAAc,UAAU,MAAM,SAAS;AAC7C,eAAO,cAAc,mBAAmB,eAAe;AAAA,MACzD,CAAC,EACA,IAAI,CAAC,UAAU,iBAAiB,MAAM,OAAO,CAAC;AACjD,YAAM,mBAAmB,eAAe,OAAO,CAAC,UAAU,UAAU,MAAM,SAAS,KAAK,kBAAkB;AAC1G,YAAM,aAAa,qBAAqB,eAAe,iBAAiB,SAAS,KAAK,gBAClF,2BAA2B,eAAe,gBAAgB,IAC1D;AACJ,YAAM,wBAAwB,YAAY,uBAAuB;AAMjE,YAAM,gBAAgB,oBAAoB,UAAU,WAAW;AAC/D,YAAM,uBAAuB,kBAAkB,aAC1C,KAAK,eAAe,+BAA+B,aAAa,IACjE,uEACA;AACJ,YAAM,kBAAkB,qBAAqB,eAAe,QAAQ,UAAU,QAAQ,KAAK;AAAA,QACzF;AAAA,UACE,KAAK;AAAA,UACL;AAAA;AAAA,8FAEoF,oBAAoB;AAAA;AAAA;AAAA;AAAA,UAIxG;AAAA,YAAC,GAAI,uBACD,CAAC,UAAU,UAAU,UAAU,UAAU,eAAe,UAAU,qBAAqB,IAAI,IAC3F,CAAC,UAAU,UAAU,UAAU,QAAQ;AAAA,YAC3C,IAAI,KAAK,eAAe,EAAE,YAAY;AAAA,YAAG,IAAI,KAAK,kBAAkB,EAAE,YAAY;AAAA,UAAC;AAAA,QACrF;AAAA,MACF;AAIA,YAAM,wBAAwB,qBAAqB,eAAe,QAAQ,UAAU,QAAQ;AAK5F,YAAM,iBAAiB,UAAU,mBAA6B;AAE9D,YAAM,aAAa,KAAK,IAAI,mBAAmB,GAAG,CAAG;AAOrD,YAAM,mBAAmB,qBAAqB,cACzC,kBAAkB,IAAI,MACvB,wBAAwB,OAExB,OAAO,sBACP,MAAO,KAAK,IAAI,gBAAgB,CAAG,IACnC,OAAO,aACP,MAAO,mBACP,OAAQ,mBAAmB,IAAM,KAGjC,MAAO,KAAK,IAAI,gBAAgB,CAAG,IACnC,MAAO,aACP,MAAO,mBACP,OAAQ,mBAAmB,IAAM;AAGrC;AAAA,QACE,KAAK;AAAA,QACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAOA;AAAA,UAAC;AAAA,UAAkB;AAAA,UAAkB;AAAA,UAAkB;AAAA,UACtD;AAAA,UAAY;AAAA,UACZ;AAAA,UACA,gBAAgB,SAAS,IAAI,KAAK,UAAU,eAAe,IAAI;AAAA,UAC/D,UAAU;AAAA,QAAE;AAAA,MACf;AAEA,YAAM,cAAc,8BAA8B,UAAU,gBAAgB,UAAU,MAAM;AAC5F,YAAM,WAAW,qBAAqB,cACjC,kBAAkB,cAAc,wBAAwB,iBAAiB,YAC1E,qBAAqB,aAClB,0BAA0B,OAAO,YAAY,yBAAyB,MAAM,aAAa,iBAC1F;AAGN,YAAM,iBAAiB,wBAAwB,UAAU,eAAe;AACxE,YAAM,mBAAmB,0BAA0B,UAAU,iBAAiB;AAC9E,YAAM,YAAY,oBAAoB,cAAc;AAMpD,YAAM,oBAAwC,cAAc,OACxD,WACA,cAAc,QACZ,iBACA;AACN,YAAM,KAAK,8BAA8B,6BAA6B;AAAA,QACpE,SAAS,OAAO,UAAU,YAAY,UAAU,UAAU,EAAE,EAAE;AAAA,QAC9D,SAAS,OAAO,UAAU,QAAQ;AAAA,QAClC,YAAY,oBAAoB,UAAU,WAAW;AAAA,QACrD,iBAAkB,UAAU,qBAAmD;AAAA,QAC/E;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,UAAU;AAAA,QACV,qBAAqB,qBAAqB,aAAa,wBAAwB;AAAA,QAC/E,cAAc;AAAA,QACd,cAAc;AAAA,UACZ,UAAU;AAAA,UACV,eAAe,IAAI,CAAC,UAAU,MAAM,OAAO;AAAA,QAC7C;AAAA,QACA,aAAa,YAAY,YAAY;AAAA,QACrC,oBAAoB;AAAA;AAAA;AAAA,QAGpB,kBAAkB,IAAI,KAAK,KAAK,IAAI,YAAY,QAAQ,GAAG,aAAa,CAAC,EAAE,YAAY;AAAA,MACzF,CAAC,CAAC;AAAA,IACJ;AAAA,EACF;AAAA,EAEA,MAAM,8BAA8B,OAAqD;AACvF,QAAI,KAAK,SAAU;AACnB,QAAI,MAAM,qBAAqB,wCAAwC,CAAC,iBAAiB,EAAE,kBAAmB;AAC9G,UAAM,KAAK,WAAW;AACtB,UAAM,YAAY,MAAM,cAAc,OAAO,OAAO,MAAM,YAAY,IAAI;AAC1E,UAAM,eAAe,MAAM,wBAAwB,OAAO,OAAO,OAAO,MAAM,mBAAmB;AACjG,UAAM,kBAAkB,OAAO,MAAM,UAAU;AAC/C,QAAK,iBAAiB,QAAQ,CAAC,OAAO,SAAS,YAAY,KAAM,CAAC,OAAO,SAAS,eAAe,GAAG;AAClG,YAAM,IAAI,MAAM,yDAAyD;AAAA,IAC3E;AACA,UAAM,UAAU,iBAAiB,OAAO,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,YAAY,CAAC;AACpF,UAAM,aAAa,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,eAAe,CAAC;AAC3D,QAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,CAAC,MAAM,QAAQ,KAAK,KAAK,CAAC,MAAM,iBAAiB,KAAK,GAAG;AACpF,YAAM,IAAI,MAAM,wEAAwE;AAAA,IAC1F;AACA,UAAM,kBAAkB,KAAK,eAAe,qCAAqC,aAAa;AAC9F,UAAM,oBAAoB,KAAK,eAAe,qCAAqC,WAAW;AAC9F,UAAM,aAAa,oBAAoB,MAAM,cAAc,OAAO;AAKlE,UAAM,SAAS,mBAAmB,MAAM,qBAAqB,OACzD,iBAAiB,YAAY,MAAM,QAAQ,KAAK,GAAG,MAAM,eAAe,IACxE,MAAM,QAAQ,KAAK;AACvB,UAAM,eAAe,kBACjB,gGACG,oBAAoB,mCAAmC,MAC1D;AACJ,UAAM,oBAAoB,kBACtB,qBAAqB,oBAAoB,WAAW,MACpD;AACJ,UAAM,eAAe,kBACjB;AAAA;AAAA;AAAA;AAAA;AAAA,4DAMG,oBACC;AAAA;AAAA,2DAGA,MACJ;AACJ,UAAM,cAAc,kBAChB;AAAA,MACA;AAAA,MACA,wBAAwB,MAAM,cAAc;AAAA,MAC5C,0BAA0B,MAAM,gBAAgB;AAAA,MAChD,OAAO,MAAM,uBAAuB,YAAY,OAAO,SAAS,MAAM,kBAAkB,IACpF,KAAK,IAAI,GAAG,KAAK,MAAM,MAAM,kBAAkB,CAAC,IAChD;AAAA,MACJ,MAAM,oBAAoB;AAAA,MAC1B,GAAI,oBAAoB,CAAC,MAAM,QAAQ,KAAK,GAAG,MAAM,mBAAmB,IAAI,IAAI,CAAC;AAAA,IACnF,IACE,CAAC;AACL;AAAA,MACE,KAAK;AAAA,MACL;AAAA;AAAA;AAAA;AAAA,mCAI6B,YAAY;AAAA,8DACe,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,+CAYhC,YAAY;AAAA,MACrD;AAAA,QACE,MAAM,QAAQ,KAAK;AAAA,QAAG;AAAA,QAAQ;AAAA,QAAW,MAAM,iBAAiB,KAAK;AAAA,QACrE,mCAAmC,MAAM,gBAAgB;AAAA,QACzD,8BAA8B,MAAM,WAAW;AAAA,QAC/C,MAAM,WAAW,IAAI;AAAA,QAAG;AAAA,QAAW,MAAM;AAAA,QAAU;AAAA,QACnD,MAAM;AAAA,QAAa,MAAM;AAAA,QAAc,MAAM;AAAA,QAAkB;AAAA,QAC/D,MAAM;AAAA,QAAa,GAAG;AAAA,MACxB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,yBAAyB,UAM3B,CAAC,GAAmC;AACtC,UAAM,KAAK,WAAW;AACtB,UAAM,gBAAgB,iCAAiC,QAAQ,aAAa;AAG5E,UAAM,mBAAmB,QAAQ,kBAAkB,KAAK,KAAK;AAC7D,UAAM,OAAO,2BAA2B;AAAA,MACtC;AAAA,MACA;AAAA,MACA,qBAAqB,QAAQ;AAAA,MAC7B,OAAO,QAAQ;AAAA,MACf,OAAO,QAAQ;AAAA,MACf,oBAAoB;AAAA,IACtB,CAAC;AACD,QAAI,CAAC,KAAK,SAAS,mCAAmC,EAAG,QAAO;AAChE,UAAM,UAAU,CAAC,yBAAyB;AAC1C,UAAM,SAAoB,CAAC,gBAAgB;AAC3C,QAAI,CAAC,QAAQ,oBAAqB,SAAQ,KAAK,mCAAmC;AAClF,QAAI,QAAQ,OAAO;AACjB,cAAQ,KAAK,iEAAiE;AAC9E,aAAO,KAAK,QAAQ,MAAM,YAAY,CAAC;AAAA,IACzC;AACA,QAAI,QAAQ,OAAO;AACjB,cAAQ,KAAK,gEAAgE;AAC7E,aAAO,KAAK,QAAQ,MAAM,YAAY,CAAC;AAAA,IACzC;AACA,UAAM,kBAAkB,KAAK,eAAe,qCAAqC,aAAa;AAC9F,UAAM,cAAc,kBAAkB,uCAAuC;AAC7E,UAAM,OAAO;AAAA,MACX,KAAK;AAAA,MACL;AAAA,oDAC8C,WAAW;AAAA;AAAA;AAAA,eAGhD,QAAQ,KAAK,OAAO,CAAC;AAAA,MAC9B;AAAA,IACF;AAGA,UAAM,4BAA4B,2CAA2C;AAAA,MAC3E;AAAA,IACF,IACI,KAAK,SACL,OAAO;AAAA,MACP,KAAK;AAAA,MACL;AAAA;AAAA,iBAES,QAAQ,KAAK,OAAO,CAAC;AAAA,MAC9B,CAAC,MAAM,GAAG,OAAO,MAAM,CAAC,CAAC;AAAA,IAC3B,GAAG,SAAS,CAAC;AACf,UAAM,eAAyB,CAAC;AAChC,UAAM,cAAyB,CAAC;AAChC,QAAI,CAAC,QAAQ,oBAAqB,cAAa,KAAK,iCAAiC;AACrF,QAAI,QAAQ,OAAO;AACjB,mBAAa,KAAK,qCAAqC;AACvD,kBAAY,KAAK,QAAQ,MAAM,YAAY,CAAC;AAAA,IAC9C;AACA,QAAI,QAAQ,OAAO;AACjB,mBAAa,KAAK,oCAAoC;AACtD,kBAAY,KAAK,QAAQ,MAAM,YAAY,CAAC;AAAA,IAC9C;AACA,UAAM,cAAc,KAAK,SAAS,kBAAkB,IAChD;AAAA,MACA,KAAK;AAAA,MACL;AAAA;AAAA,gCAEwB,aAAa,SAAS,IAAI,UAAU,aAAa,KAAK,OAAO,CAAC,KAAK,EAAE;AAAA,MAC7F;AAAA,IACF,IACE;AACJ,UAAM,qBAAqB,KAAK,OAAO,CAAC,QAAQ,OAAO,IAAI,QAAQ,MAAM,CAAC,EAAE;AAC5E,UAAM,WAAW,OAAO,aAAa,YAAY,CAAC,IAAI,IAAI,OAAO,aAAa,QAAQ,IAAI,KAAK;AAC/F,UAAM,WAAW,OAAO,aAAa,YAAY,CAAC,IAAI,IAAI,OAAO,aAAa,QAAQ,IAAI;AAC1F,QAAI,KAAK,WAAW,GAAG;AACrB,aAAO;AAAA,QACL,GAAG;AAAA,QACH;AAAA,QACA;AAAA,QACA;AAAA,QACA,OAAO;AAAA,UACL,GAAG,KAAK;AAAA,UACR,gBAAgB;AAAA,YACd,WAAW;AAAA,YACX,aAAa;AAAA,YACb,SAAS;AAAA,YACT,OAAO,WAAW,IAAI,KAAK,MAAO,WAAW,WAAY,GAAM,IAAI,MAAS;AAAA,UAC9E;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,UAAM,mBAAmB,KAAK;AAC9B,UAAM,YAAY,KAAK,OAAO,CAAC,QAAQ,OAAO,IAAI,SAAS,MAAM,CAAC,EAAE;AACpE,UAAM,kBAAkB,KAAK,OAAO,CAAC,QAAQ,IAAI,cAAc,QAAQ,IAAI,cAAc,MAAS,EAAE;AAMpG,UAAM,kBAAkB,KAAK,OAAO,CAAC,QAAQ,IAAI,sBAAsB,UAAU;AACjF,UAAM,eAAe,gBAAgB,OAAO,CAAC,QAAQ,IAAI,iBAAiB,aAAa;AACvF,UAAM,sBAAsB,CAAC,QAC3B,IAAI,aAAa,cAAc,IAAI,aAAa;AAClD,UAAM,oBAAoB,aAAa,OAAO,mBAAmB,EAAE;AACnE,UAAM,mBAAmB,aAAa,OAAO,CAAC,QAAQ,IAAI,aAAa,UAAU,EAAE;AACnF,UAAM,+BAA+B,gBAAgB,OAAO,mBAAmB,EAAE;AACjF,UAAM,8BAA8B,gBAAgB,OAAO,CAAC,QAAQ,IAAI,aAAa,UAAU,EAAE;AACjG,UAAM,aAAa,KAAK,OAAO,CAAC,QAAQ,IAAI,sBAAsB,WAAW;AAC7E,UAAM,sBAAsB,WAAW,OAAO,CAAC,QAAQ,IAAI,aAAa,WAAW,EAAE;AACrF,UAAM,mBAAmB,WAAW,OAAO,CAAC,QAAQ,IAAI,aAAa,SAAS,EAAE;AAChF,UAAM,sBAAsB,WAAW,SAAS;AAChD,UAAM,gBAAgB,KAAK,OAAO,CAAC,QAAQ,IAAI,iBAAiB,SAAS,EAAE;AAC3E,UAAM,iBAAiB,KAAK,OAAO,CAAC,QAAQ,IAAI,iBAAiB,SAAS,EAAE;AAC5E,UAAM,mBAAmB,KAAK,OAAO,CAAC,QAAQ,IAAI,sBAAsB,UAAU,EAAE;AACpF,UAAM,mBAAmB,KAAK,OAAO,CAAC,QAAQ,IAAI,sBAAsB,UAAU,EAAE;AACpF,UAAM,oBAAoB,mBAAmB;AAC7C,UAAM,qBAAqB;AAAA,MACzB,UAAU;AAAA,MACV,UAAU,KAAK,OAAO,CAAC,QAAQ,IAAI,aAAa,SAAS,EAAE;AAAA,MAC3D,aAAa,KAAK,OAAO,CAAC,QAAQ,IAAI,iBAAiB,SAAS,EAAE;AAAA,MAClE,cAAc,KAAK,OAAO,CAAC,QAAQ,IAAI,kBAAkB,SAAS,EAAE;AAAA,MACpE,kBAAkB,mBAAmB;AAAA,IACvC;AACA,UAAM,OAAO,CAAC,WAAmB,aAAqB,aAAuC;AAAA,MAC3F;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,cAAc,IAAI,KAAK,MAAO,YAAY,cAAe,GAAM,IAAI,MAAS;AAAA,IACrF;AACA,UAAM,uBAAuB,EAAE,GAAG,KAAK,qBAAqB;AAC5D,UAAM,iBAAiB,EAAE,GAAG,KAAK,eAAe;AAChD,eAAW,OAAO,MAAM;AACtB,2BAAqB,wBAAwB,IAAI,eAAe,CAAC,KAAK;AACtE,UAAI,OAAO,IAAI,QAAQ,MAAM,EAAG,gBAAe,oBAAoB,IAAI,eAAe,OAAO,CAAC,KAAK;AAAA,IACrG;AACA,WAAO;AAAA,MACL,GAAG;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,qBAAqB;AAAA,QACnB,WAAW;AAAA,QACX,UAAU;AAAA,QACV,SAAS,gBAAgB,SAAS;AAAA,MACpC;AAAA,MACA,oBAAoB,WAAW;AAAA,MAC/B;AAAA,MACA,uBAAuB;AAAA,MACvB,wBAAwB;AAAA,MACxB;AAAA,MACA;AAAA,MACA,SAAS,OAAO,OAAO,kBAAkB,EAAE,OAAO,CAAC,KAAK,UAAU,MAAM,OAAO,CAAC;AAAA,MAChF;AAAA,MACA,OAAO;AAAA,QACL,gBAAgB,KAAK,UAAU,UAAU,CAAC;AAAA,QAC1C,cAAc,KAAK,WAAW,mBAAmB,iBAAiB,eAAe;AAAA,QACjF,mBAAmB,KAAK,kBAAkB,mBAAmB,aAAa,SAAS,iBAAiB;AAAA,QACpG,qBAAqB,KAAK,qBAAqB,qBAAqB,gBAAgB;AAAA,QACpF,aAAa,KAAK,gBAAgB,eAAe,mBAAmB,WAAW;AAAA,QAC/E,kBAAkB,KAAK,kBAAkB,mBAAmB,mBAAmB,gBAAgB;AAAA,MACjG;AAAA,MACA,aAAa,oBAAoB,gBAAgB,eAAe;AAAA,IAClE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,mBAAmB,QAAgB,IAMrC;AACF,UAAM,KAAK,WAAW;AAEtB,UAAM,OAAO;AAAA,MACX,KAAK;AAAA,MACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,eASS,wBAAwB,YAAY,CAAC;AAAA;AAAA;AAAA;AAAA,MAI9C,CAAC,KAAK;AAAA,IACR;AAEA,WAAO,KAAK,IAAI,QAAM;AAAA,MACpB,SAAS,EAAE;AAAA,MACX,SAAU,EAAE,QAAmB,UAAU,GAAG,GAAG,KAAM,EAAE,QAAmB,SAAS,MAAM,QAAQ;AAAA,MACjG,kBAAkB,KAAK,MAAO,EAAE,YAAuB,GAAG,IAAI;AAAA,MAC9D,aAAc,EAAE,gBAA2B;AAAA,MAC3C,iBAAiB,EAAE;AAAA,IACrB,EAAE;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,oBAAoB,OAAc,OAUrC;AACD,UAAM,KAAK,WAAW;AAEtB,UAAM,WAAW,OAAO,YAAY;AACpC,UAAM,WAAW,OAAO,YAAY;AACpC,UAAM,cAAwB,CAAC;AAC/B,UAAM,aAAuB,CAAC;AAC9B,QAAI,UAAU;AACZ,kBAAY,KAAK,qCAAqC;AACtD,iBAAW,KAAK,QAAQ;AAAA,IAC1B;AACA,QAAI,UAAU;AACZ,kBAAY,KAAK,oCAAoC;AACrD,iBAAW,KAAK,QAAQ;AAAA,IAC1B;AACA,UAAM,YAAY,YAAY,SAAS,IAAI,SAAS,YAAY,KAAK,OAAO,CAAC,KAAK;AAClF,UAAM,iBAAiB,YAAY,SAAS,IACxC,qCAAqC,YAAY,KAAK,OAAO,CAAC,KAC9D;AAIJ,UAAM,sBAAsB,KAAK,eAAe,sBAAsB,uBAAuB;AAC7F,UAAM,kBAAkB,sBACpB;AAAA;AAAA,4FAGA;AAEJ,UAAM,QAAQ;AAAA,MACZ,KAAK;AAAA,MACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,WAMK,eAAe;AAAA;AAAA,SAEjB,cAAc;AAAA,MACjB;AAAA,IACF;AAEA,UAAM,WAAW;AAAA,MACf,KAAK;AAAA,MACL,oDAAoD,SAAS;AAAA,MAC7D;AAAA,IACF;AAEA,WAAO;AAAA,MACL,UAAU,KAAK,OAAQ,OAAO,aAAwB,KAAK,GAAG,IAAI;AAAA,MAClE,gBAAiB,OAAO,mBAA8B;AAAA,MACtD,iBAAkB,UAAU,SAAoB;AAAA,MAChD,SAAU,OAAO,WAAsB;AAAA,MACvC,SAAU,OAAO,WAAsB;AAAA,MACvC,WAAY,OAAO,aAAwB;AAAA,MAC3C,kBAAmB,OAAO,qBAAgC;AAAA,MAC1D,mBAAmB,KAAK,OAAQ,OAAO,uBAAkC,KAAK,GAAG,IAAI;AAAA,MACrF,eAAgB,OAAO,kBAA6B;AAAA,IACtD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,yBAAyB,OAAa,OAQxC;AACF,UAAM,KAAK,WAAW;AACtB,UAAM,WAAW,MAAM,YAAY,EAAE,MAAM,GAAG,EAAE;AAChD,UAAM,WAAW,MAAM,YAAY,EAAE,MAAM,GAAG,EAAE;AAChD,UAAM,OAAO;AAAA,MACX,KAAK;AAAA,MACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAYA,CAAC,UAAU,QAAQ;AAAA,IACrB;AAEA,WAAO,KAAK,IAAI,CAAC,SAAS;AAAA,MACxB,MAAM,OAAO,IAAI,QAAQ,EAAE;AAAA,MAC3B,UAAU,KAAK,OAAQ,IAAI,aAAwB,KAAK,GAAG,IAAI;AAAA,MAC/D,gBAAiB,IAAI,mBAA8B;AAAA,MACnD,iBAAkB,IAAI,oBAA+B;AAAA,MACrD,SAAU,IAAI,WAAsB;AAAA,MACpC,SAAU,IAAI,WAAsB;AAAA,MACpC,WAAY,IAAI,aAAwB;AAAA,IAC1C,EAAE;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,qBAAqB,UAKvB,CAAC,GAwBD;AACF,UAAM,KAAK,WAAW;AAEtB,UAAM,QAAQ,KAAK,IAAI,KAAK,IAAI,QAAQ,SAAS,IAAI,CAAC,GAAG,GAAG;AAC5D,UAAM,SAAS,KAAK,IAAI,QAAQ,UAAU,GAAG,CAAC;AAI9C,UAAM,eAAe,KAAK,eAAe,sBAAsB,UAAU;AACzE,UAAM,kBAAkB,KAAK,eAAe,oBAAoB,cAAc;AAC9E,UAAM,uBAAuB,KAAK,eAAe,oBAAoB,mBAAmB;AACxF,UAAM,eAAe,kBACjB,mFACA;AAEJ,UAAM,qBAAqB,QAAQ,YAAY,uBAAuB;AACtE,UAAM,kBAAkB,QAAQ,qBAAqB,2BAA2B;AAChF,UAAM,SAAoB,CAAC;AAC3B,QAAI,QAAQ,UAAW,QAAO,KAAK,QAAQ,SAAS;AACpD,QAAI,gBAAgB,QAAQ,UAAW,QAAO,KAAK,QAAQ,SAAS;AACpE,WAAO,KAAK,OAAO,MAAM;AAIzB,UAAM,qBAAqB,eACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gBASQ,kBAAkB;AAAA,yEAE1B;AACJ,UAAM,QAAQ;AAAA,MACZ,KAAK;AAAA,MACL;AAAA,kBACY,YAAY;AAAA;AAAA,qBAET,kBAAkB,IAAI,eAAe;AAAA,WAC/C,kBAAkB;AAAA;AAAA;AAAA;AAAA,MAIvB;AAAA,IACF;AAEA,UAAM,UAwBD,CAAC;AAEN,eAAW,QAAQ,OAAO;AACxB,YAAM,OAAO,KAAK;AAClB,YAAM,SAAS,KAAK;AAEpB,UAAI;AACJ,UAAI,CAAC,OAAO,WAAW,KAAK,GAAG;AAC7B,gBAAQ;AAAA,UACN,KAAK;AAAA,UACL;AAAA,UACA,CAAC,MAAM;AAAA,QACT;AACA,YAAI,CAAC,SAAS,SAAS,QAAS;AAAA,MAClC;AAIA,UAAI,WAAsC,eACtC;AAAA,QACA,KAAK;AAAA,QACL;AAAA,QACA,CAAC,MAAM;AAAA,MACT,IACE,CAAC;AACL,UAAI,SAAS,WAAW,KAAK,OAAO;AAClC,cAAM,eAAyB,MAAM;AACnC,cAAI;AAAE,mBAAO,KAAK,MAAO,MAAM,sBAAiC,IAAI;AAAA,UAAG,QAAQ;AAAE,mBAAO,CAAC;AAAA,UAAG;AAAA,QAC9F,GAAG;AACH,YAAI,YAAY,SAAS,KAAK,MAAM,YAAY;AAC9C,gBAAM,mBAAmB,eAAe,yBAAyB;AACjE,qBAAW;AAAA,YACT,KAAK;AAAA,YACL;AAAA,oCACwB,gBAAgB;AAAA,kCAClB,YAAY,IAAI,MAAM,GAAG,EAAE,KAAK,GAAG,CAAC;AAAA;AAAA;AAAA,YAG1D,CAAC,MAAM,YAAY,GAAG,aAAa,MAAM,UAAU;AAAA,UACrD;AAAA,QACF;AAAA,MACF;AACA,UAAI,SAAS,mBAAmB,SAAS,WAAW,KAAK,CAAC,OAAO;AAC/D,mBAAW;AAAA,UACT,KAAK;AAAA,UACL;AAAA;AAAA;AAAA,UAGA,CAAC,KAAK,UAAU;AAAA,QAClB;AAAA,MACF;AAKA,YAAM,qBAAqB,KAAK,eAAe,sBAAsB,aAAa;AAClF,YAAM,SAAS,CAAC,QACd,qBAAqB,oBAAoB,IAAI,WAAW,IAAI;AAC9D,YAAM,WAAW,MAAM,KAAK,IAAI,IAAI,SACjC,OAAO,CAAC,QAAQ,OAAO,GAAG,MAAM,WAAW,OAAO,GAAG,MAAM,SAAS,EACpE,IAAI,CAAC,QAAQ,IAAI,QAAkB,EACnC,OAAO,OAAO,CAAC,CAAC;AACnB,YAAM,YAAY,MAAM,KAAK,IAAI,IAAI,SAClC,OAAO,CAAC,QAAQ,OAAO,GAAG,MAAM,QAAQ,EACxC,IAAI,CAAC,QAAQ,IAAI,QAAkB,EACnC,OAAO,OAAO,CAAC,CAAC;AACnB,YAAM,YAAY,oBAAI,IAAqD;AAC3E,UAAI,SAAS,SAAS,GAAG;AACvB,cAAM,OAAO;AAAA,UACX,KAAK;AAAA,UACL,2DAA2D,SAAS,IAAI,MAAM,GAAG,EAAE,KAAK,GAAG,CAAC;AAAA,UAC5F;AAAA,QACF;AACA,mBAAW,OAAO,KAAM,WAAU,IAAI,IAAI,IAAI,GAAG;AAAA,MACnD;AACA,UAAI,UAAU,SAAS,KAAK,KAAK,SAAS,gBAAgB,GAAG;AAC3D,cAAM,OAAO;AAAA,UACX,KAAK;AAAA,UACL,2EAA2E,UAAU,IAAI,MAAM,GAAG,EAAE,KAAK,GAAG,CAAC;AAAA,UAC7G;AAAA,QACF;AACA,mBAAW,OAAO,MAAM;AACtB,oBAAU,IAAI,IAAI,WAAW;AAAA,YAC3B,SAAS,CAAC,IAAI,MAAM,IAAI,OAAO,EAAE,OAAO,OAAO,EAAE,KAAK,UAAK;AAAA,YAC3D,YAAY;AAAA,UACd,CAAC;AAAA,QACH;AAAA,MACF;AAEA,YAAM,WAAW,SAAS,IAAI,CAAC,QAAQ;AACrC,cAAM,QAAQ,UAAU,IAAI,IAAI,QAAkB;AAClD,YAAI,WAA4B,CAAC;AACjC,YAAI;AACF,gBAAM,SAAS,KAAK,MAAO,IAAI,iBAA4B,IAAI;AAC/D,cAAI,MAAM,QAAQ,MAAM,EAAG,YAAW;AAAA,QACxC,QAAQ;AAAA,QAA6C;AACrD,cAAM,UAAU,QACZ,MAAM,QAAQ,UAAU,GAAG,GAAG,KAAK,MAAM,QAAQ,SAAS,MAAM,WAAM,MACtE;AACJ,eAAO;AAAA,UACL,SAAS,IAAI;AAAA,UACb,WAAW,OAAO,cAAc;AAAA,UAChC;AAAA,UACA,gBAAiB,IAAI,mBAA8B;AAAA,UACnD,kBAAkB,IAAI,cAAgB,IAAI,qBAAgC,OAAQ;AAAA,UAClF,qBAAsB,IAAI,yBAAoC;AAAA,UAC9D;AAAA,UACA,YAAa,IAAI,eAA0B;AAAA,UAC3C,QAAS,IAAI,UAAqB;AAAA,UAClC,kBAAkB,mCAAmC,IAAI,iBAAiB;AAAA,QAC5E;AAAA,MACF,CAAC;AAED,UAAI,OAAO;AACT,gBAAQ,KAAK;AAAA,UACX,SAAS;AAAA,UACT;AAAA,UACA,WAAY,MAAM,cAAyB;AAAA,UAC3C,UAAU,SAAS,kBACd,mCAAmC,MAAM,iBAAiB,MAAM,SAC/D,8CACA,yDACD,MAAM,kBAA8B,MAAM,cAAyB;AAAA,UACxE,WAAY,MAAM,cAAyB;AAAA,UAC3C,UAAW,MAAM,YAAuB;AAAA,UACxC,YAAa,MAAM,cAAyB;AAAA,UAC5C,gBAAiB,MAAM,mBAA8B;AAAA,UACrD,eAAgB,MAAM,kBAA6B;AAAA,UACnD,WAAW,iBAAiB,MAAM,UAAoB;AAAA,UACtD,kBAAkB,uBACd,mCAAmC,MAAM,iBAAiB,IAC1D;AAAA,UACJ;AAAA,QACF,CAAC;AAAA,MACH,OAAO;AACL,gBAAQ,KAAK;AAAA,UACX,SAAS,OAAO,WAAW,KAAK,IAAI,OAAO;AAAA,UAC3C,MAAM;AAAA,UACN,WAAY,KAAK,cAAyB;AAAA,UAC1C,UAAU;AAAA,UACV,WAAW;AAAA,UACX,UAAU;AAAA,UACV,YAAY;AAAA,UACZ,gBAAgB,SAAS;AAAA,UACzB,eAAe,SAAS;AAAA,UACxB,WAAW,iBAAiB,KAAK,UAAoB;AAAA,UACrD,kBAAkB;AAAA,UAClB;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,cACJ,OACA,QAAgB,IAChB,SACoD;AACpD,UAAM,KAAK,WAAW;AAQtB,UAAM,0BAA0B,SAAS,4BAA4B;AACrE,UAAM,qBAAqB,0BAA0B,KAAK;AAG1D,UAAM,cAAc,MACjB,QAAQ,yBAAyB,GAAG,EACpC,MAAM,KAAK,EACX,OAAO,UAAQ,KAAK,SAAS,CAAC,EAC9B,IAAI,UAAQ,IAAI,IAAI,IAAI,EACxB,KAAK,MAAM;AAEd,QAAI,CAAC,aAAa;AAChB,aAAO,CAAC;AAAA,IACV;AAEA,QAAI;AACF,YAAM,OAAO;AAAA,QACX,KAAK;AAAA,QACL;AAAA;AAAA;AAAA;AAAA,iBAIS,wBAAwB,YAAY,CAAC;AAAA,aACzC,kBAAkB;AAAA;AAAA;AAAA,QAGvB,CAAC,aAAa,KAAK;AAAA,MACrB;AAEA,aAAO,KAAK,IAAI,UAAQ;AAAA,QACtB,OAAO,KAAK,WAAW,GAAG;AAAA,QAC1B,MAAM,IAAI;AAAA,MACZ,EAAE;AAAA,IACJ,SAAS,OAAY;AAGnB,YAAM,cAAc,IAAI,KAAK;AAC7B,YAAM,OAAO;AAAA,QACX,KAAK;AAAA,QACL;AAAA;AAAA,iBAES,wBAAwB,CAAC;AAAA,aAC7B,0BAA0B,KAAK,sCAAsC;AAAA;AAAA;AAAA,QAG1E,CAAC,aAAa,KAAK;AAAA,MACrB;AAEA,aAAO,KAAK,IAAI,UAAQ;AAAA,QACtB,OAAO,KAAK,WAAW,GAAG;AAAA,QAC1B,MAAM;AAAA,MACR,EAAE;AAAA,IACJ;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,wBACJ,OACA,QAAgB,IAC0E;AAC1F,UAAM,KAAK,WAAW;AACtB,UAAM,cAAc,MACjB,QAAQ,yBAAyB,GAAG,EACpC,MAAM,KAAK,EACX,OAAO,UAAQ,KAAK,SAAS,CAAC,EAC9B,IAAI,UAAQ,IAAI,IAAI,IAAI,EACxB,KAAK,MAAM;AACd,QAAI,CAAC,YAAa,QAAO,CAAC;AAE1B,QAAI;AACF,YAAM,OAAO;AAAA,QACX,KAAK;AAAA,QACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAOS,wBAAwB,YAAY,CAAC;AAAA;AAAA;AAAA,QAG9C,CAAC,aAAa,KAAK;AAAA,MACrB;AACA,aAAO,KAAK,IAAI,CAAC,SAAS;AAAA,QACxB,OAAO,KAAK,WAAW,GAAG;AAAA,QAC1B,MAAM,OAAO,IAAI,IAAI;AAAA,QACrB,OAAO,OAAO,IAAI,KAAK;AAAA,QACvB,aAAa,OAAO,IAAI,gBAAgB,CAAC;AAAA,MAC3C,EAAE;AAAA,IACJ,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaQ,yBAA+B;AACrC,eAAW,KAAK,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KA2BnB;AAAA,EACH;AAAA,EAEA,MAAM,kBAAmC;AACvC,UAAM,KAAK,WAAW;AAGtB,UAAM,WAAW,UAA2B,KAAK,IAAI,wCAAwC,CAAC,CAAC;AAC/F,UAAM,cAAc,UAAU,SAAS;AAEvC,SAAK,uBAAuB;AAE5B,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,cAA8B;AAC5B,WAAO,KAAK;AAAA,EACd;AAAA,EAEQ,eAAe,WAAmB,YAA6B;AACrE,QAAI,CAAC,2BAA2B,KAAK,SAAS,EAAG,QAAO;AACxD,QAAI;AACF,YAAM,OAAO,UAA4B,KAAK,IAAI,sBAAsB,SAAS,MAAM,CAAC,CAAC;AACzF,aAAO,KAAK,KAAK,CAAC,QAAQ,IAAI,SAAS,UAAU;AAAA,IACnD,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEQ,SAAS,WAA4B;AAC3C,QAAI,CAAC,2BAA2B,KAAK,SAAS,EAAG,QAAO;AACxD,QAAI;AACF,YAAM,OAAO;AAAA,QACX,KAAK;AAAA,QACL;AAAA,QACA,CAAC,SAAS;AAAA,MACZ;AACA,aAAO,KAAK,SAAS;AAAA,IACvB,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,mBAAmB,OAAe,QAAgB,YAA0B;AAClF,QAAI,CAAC,2BAA2B,KAAK,KAAK,KAAK,CAAC,2BAA2B,KAAK,MAAM,GAAG;AACvF,YAAM,IAAI,MAAM,oCAAoC,KAAK,IAAI,MAAM,EAAE;AAAA,IACvE;AACA,QAAI,CAAC,KAAK,SAAS,KAAK,EAAG;AAC3B,QAAI,KAAK,eAAe,OAAO,MAAM,EAAG;AACxC,eAAW,KAAK,IAAI,eAAe,KAAK,eAAe,MAAM,IAAI,UAAU,GAAG;AAAA,EAChF;AAAA,EAGA,MAAM,qBAAqB,OAsCK;AAC9B,QAAI,KAAK,SAAU,QAAO;AAC1B,UAAM,KAAK,WAAW;AAEtB,UAAM,YAAY,mBAAmB,MAAM,SAAS;AACpD,UAAM,mBAAmB,0BAA0B,MAAM,gBAAgB;AACzE,UAAM,mBAAmB,+BAA+B,MAAM,gBAAgB;AAC9E,UAAM,kBAAkB,+BAA+B,MAAM,eAAe;AAI5E,UAAM,qBAAqB;AAAA,MACzB,MAAM;AAAA,MACN,MAAM,iBAAiB,SAAS,IAAI,aAAa;AAAA,IACnD;AACA,UAAM,SAAS;AAAA,MACb,MAAM,aAAa;AAAA,MACnB,MAAM,eAAe;AAAA,MACrB,MAAM;AAAA,MACN,MAAM,gBAAgB;AAAA,MACtB;AAAA,MACA,MAAM,YAAY;AAAA,MAClB,KAAK,UAAU,MAAM,qBAAqB,CAAC,CAAC;AAAA,MAC5C,KAAK,UAAU,MAAM,oBAAoB,CAAC,CAAC;AAAA,MAC3C,KAAK,UAAU,gBAAgB;AAAA,MAC/B,KAAK,UAAU,eAAe;AAAA,OAC7B,MAAM,qBAAqB,CAAC,GAAG;AAAA,OAC/B,MAAM,oBAAoB,CAAC,GAAG;AAAA,MAC/B,MAAM,cAAc;AAAA,MACpB,KAAK,UAAU,MAAM,iBAAiB,CAAC,CAAC;AAAA,MACxC,mCAAmC,MAAM,gBAAgB;AAAA,MACzD,8BAA8B,MAAM,WAAW;AAAA,MAC/C,yBAAyB,MAAM,cAAc;AAAA,MAC7C,mBAAmB;AAAA,MACnB,KAAK,UAAU,kBAAkB;AAAA,MACjC;AAAA,MACA,mBAAmB,MAAM,eAAe;AAAA,MACxC,MAAM,gBAAgB,MAAM,GAAG,EAAE,KAAK;AAAA,MACtC;AAAA,IACF;AAEA,UAAM,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQlB,UAAM,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkBlB,UAAM,QAAQ,MAAsD;AAClE,YAAM,WAAW,YACb;AAAA,QACA,KAAK;AAAA,QACL;AAAA,QACA,CAAC,SAAS;AAAA,MACZ,IACE;AACJ,YAAM,kBAAkB,UAAU,YAAY,MAAM,WAAWL,YAAW;AAC1E,UAAI,UAAU;AACZ,kBAAU,KAAK,IAAI,WAAW,CAAC,GAAG,QAAQ,eAAe,CAAC;AAC1D,eAAO,EAAE,SAAS,iBAAiB,kBAAkB,KAAK;AAAA,MAC5D;AACA,UAAI;AACF,kBAAU,KAAK,IAAI,WAAW,CAAC,GAAG,QAAQ,eAAe,CAAC;AAC1D,eAAO,EAAE,SAAS,iBAAiB,kBAAkB,MAAM;AAAA,MAC7D,SAAS,OAAO;AAGd,YAAI,CAAC,UAAW,OAAM;AACtB,cAAM,QAAQ;AAAA,UACZ,KAAK;AAAA,UACL;AAAA,UACA,CAAC,SAAS;AAAA,QACZ;AACA,YAAI,CAAC,MAAO,OAAM;AAClB,kBAAU,KAAK,IAAI,WAAW,CAAC,GAAG,QAAQ,MAAM,QAAQ,CAAC;AACzD,eAAO,EAAE,SAAS,MAAM,UAAU,kBAAkB,KAAK;AAAA,MAC3D;AAAA,IACF;AAEA,WAAO,KAAK,0BAA0B,MAAM;AAC1C,YAAM,SAAS,MAAM;AACrB,YAAM,wBAAwB,OAAO,oBAChC,eAAe,KAAK,IAAI,OAAO,OAAO,EAAE,SAAS;AACtD,UAAI,iBAAiB,EAAE,mBAAmB,uBAAuB;AAC/D,aAAK,qBAAqB,OAAO,SAAS,OAAO,EAAE,iBAAiB,OAAO,iBAAiB,CAAC;AAAA,MAC/F;AACA,aAAO,OAAO;AAAA,IAChB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,0BAA6B,IAAgB;AACnD,QAAI,KAAK,GAAG,cAAe,QAAO,GAAG;AACrC,eAAW,KAAK,IAAI,iBAAiB;AACrC,QAAI;AACF,YAAM,SAAS,GAAG;AAClB,iBAAW,KAAK,IAAI,QAAQ;AAC5B,aAAO;AAAA,IACT,SAAS,OAAO;AACd,UAAI;AACF,mBAAW,KAAK,IAAI,UAAU;AAAA,MAChC,QAAQ;AAAA,MAA6C;AACrD,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,qBACN,SACA,OAMA,UAAyC,CAAC,GACpC;AACN,QAAI;AACF,YAAM,YAAY,MAAM,eAAe;AACvC,UAAI;AACJ,UAAI,MAAM,SAAS,MAAM,MAAM,SAAS,GAAG;AACzC,gBAAQ,MAAM;AAAA,MAChB,OAAO;AACL,cAAM,WAAW,IAAI,IAAI,MAAM,oBAAoB,CAAC,CAAC;AACrD,cAAM,MAAM,MAAM,KAAK,oBAAI,IAAI,CAAC,GAAI,MAAM,qBAAqB,CAAC,GAAI,GAAI,MAAM,oBAAoB,CAAC,CAAE,CAAC,CAAC;AACvG,cAAM,WAAW,sBAAsB,KAAK,IAAI,KAAK,EAAE,UAAU,CAAC;AAClE,gBAAQ,IAAI,IAAI,CAAC,IAAI,UAAU;AAC7B,gBAAM,MAAM,SAAS,IAAI,EAAE;AAC3B,iBAAO;AAAA,YACL,MAAM,KAAK,eAAe,aAAa,IAAI,OAAO;AAAA,YAClD;AAAA,YACA,WAAW,KAAK,aAAa;AAAA,YAC7B,MAAM;AAAA,YACN,UAAU,SAAS,IAAI,EAAE;AAAA;AAAA;AAAA;AAAA,YAIzB,SAAS;AAAA,UACX;AAAA,QACF,CAAC;AAAA,MACH;AACA,YAAM,aAAa,oBAAoB,OAAO,EAAE,UAAU,CAAC;AAC3D,UAAI,QAAQ,iBAAiB;AAK3B,kBAAU,KAAK,IAAI,wDAAwD,CAAC,OAAO,CAAC;AAAA,MACtF;AACA,sBAAgB,KAAK,IAAI,SAAS,UAAU;AAAA,IAC9C,SAAS,OAAO;AAEd,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,uBAAuB,SAAiB;AAC5C,UAAM,KAAK,WAAW;AACtB,WAAO,eAAe,KAAK,IAAI,OAAO;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,yBAAyB,UAAmE,CAAC,GAAmC;AACpI,UAAM,KAAK,WAAW;AACtB,WAAO,yBAAyB,KAAK,IAAI,OAAO;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,4BAA4B,UAA8D,CAAC,GAAqC;AACpI,UAAM,KAAK,WAAW;AACtB,QAAI,KAAK,YAAY,QAAQ,WAAW,OAAO;AAC7C,YAAM,IAAI,MAAM,oEAAoE;AAAA,IACtF;AACA,WAAO,QAAQ,WAAW,QACtB,KAAK,0BAA0B,MAAM,mBAAmB,KAAK,IAAI,OAAO,CAAC,IACzE,mBAAmB,KAAK,IAAI,OAAO;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,0BACJ,OAC0C;AAC1C,QAAI,KAAK,UAAU;AACjB,aAAO,EAAE,SAAS,gBAAgB,SAAS,MAAM,UAAU,MAAM;AAAA,IACnE;AACA,UAAM,KAAK,WAAW;AACtB,WAAO,8BAA8B,KAAK,IAAI,KAAK;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,2BAA2B,UAA0C,CAAC,GAAuC;AACjH,UAAM,KAAK,WAAW;AACtB,QAAI,CAAC,KAAK,SAAS,kBAAkB,EAAG,QAAO,CAAC;AAChD,UAAM,eAAe,KAAK,eAAe,oBAAoB,YAAY;AACzE,UAAM,UAAoB,CAAC;AAC3B,UAAM,SAAoB,CAAC;AAC3B,QAAI,QAAQ,OAAO;AACjB,cAAQ,KAAK,uCAAuC;AACpD,aAAO,KAAK,QAAQ,MAAM,YAAY,CAAC;AAAA,IACzC;AACA,QAAI,QAAQ,OAAO;AACjB,cAAQ,KAAK,sCAAsC;AACnD,aAAO,KAAK,QAAQ,MAAM,YAAY,CAAC;AAAA,IACzC;AACA,UAAM,QAAQ,QAAQ,SAAS,IAAI,UAAU,QAAQ,KAAK,OAAO,CAAC,KAAK;AACvE,UAAM,kBAAkB,eACpB,yEACA;AACJ,UAAM,cAAc,eAChB,mDACA;AACJ,UAAM,OAAO;AAAA,MACX,KAAK;AAAA,MACL;AAAA,gBACU,WAAW;AAAA,gBACX,eAAe;AAAA;AAAA,8BAED,KAAK;AAAA;AAAA;AAAA,MAG7B;AAAA,IACF;AACA,WAAO,KAAK,IAAI,CAAC,QAAQ;AACvB,YAAM,WAAW,OAAO,IAAI,YAAY,CAAC;AACzC,YAAM,eAAe,OAAO,IAAI,gBAAgB,CAAC;AACjD,YAAM,aAAa,OAAO,IAAI,kBAAkB,CAAC;AACjD,aAAO;AAAA,QACL,QAAQ,OAAO,IAAI,UAAU,SAAS;AAAA,QACtC,kBAAkB;AAAA,QAClB,sBAAsB;AAAA,QACtB,qBAAqB;AAAA,QACrB,UAAU,WAAW,KAAK,eAAe,IACrC,KAAK,MAAO,eAAe,WAAY,GAAM,IAAI,MACjD;AAAA,QACJ,eAAe,WAAW,KAAK,eAAe,IAAI,aAAa;AAAA,MACjE;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,sBAAsB,UAA0C,CAAC,GASnE;AACF,UAAM,KAAK,WAAW;AACtB,QAAI,CAAC,KAAK,SAAS,QAAQ,EAAG,QAAO,CAAC;AACtC,WAAO,uBAAuB,KAAK,IAAI,OAAO;AAAA,EAChD;AAAA,EAEA,MAAM,6BAA+D;AACnE,UAAM,KAAK,WAAW;AAEtB,UAAM,uBAAuB,KAAK,eAAe,oBAAoB,mBAAmB;AACxF,UAAM,kBAAkB,KAAK,eAAe,oBAAoB,cAAc;AAC9E,UAAM,sBAAsB,QAAQ;AAAA,MAClC,KAAK;AAAA,MACL;AAAA,IACF,CAAC;AACD,UAAM,6BAA6B,uBAC9B,KAAK,eAAe,sBAAsB,mBAAmB;AAClE,UAAM,qBAAqB,QAAQ;AAAA,MACjC,KAAK;AAAA,MACL;AAAA,IACF,CAAC;AACD,UAAM,kBAAkB,uBACpB,6DACA;AACJ,UAAM,aAAa,kBACf,wDACA;AAEJ,UAAM,mBAAmB;AAAA,MACvB,KAAK;AAAA,MACL,UAAU,eAAe;AAAA;AAAA,wCAES,eAAe;AAAA,IACnD;AACA,UAAM,cAAc;AAAA,MAClB,KAAK;AAAA,MACL,UAAU,UAAU;AAAA;AAAA,wCAEc,UAAU;AAAA,IAC9C;AACA,UAAM,iBAAiB;AAAA,MACrB,KAAK;AAAA,MACL;AAAA,IACF;AACA,UAAM,oBAAoB,sBACtB;AAAA,MACE,KAAK;AAAA,MACL,6BACI,sHACA;AAAA,IACN,GAAG,SAAS,IACZ;AAEJ,UAAM,WAAW,6BACb;AAAA,MACE,KAAK;AAAA,MACL;AAAA;AAAA;AAAA;AAAA;AAAA,IAKF,IACA;AACJ,UAAM,oBAAoB,uBACtB,OAAO;AAAA,MACL,KAAK;AAAA,MACL;AAAA;AAAA,IAEF,GAAG,SAAS,CAAC,IACb;AACJ,UAAM,aAAa,qBACf;AAAA,MACE,KAAK;AAAA,MACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMF,IACA;AACJ,UAAM,oBAAoB,OAAO,UAAU,aAAa,CAAC;AACzD,UAAM,mBAAmB,OAAO,UAAU,YAAY,CAAC;AACvD,UAAM,kBAAkB,OAAO,YAAY,oBAAoB,CAAC;AAEhE,WAAO;AAAA,MACL,YAAY;AAAA,QACV,aAAa,OAAO,gBAAgB,eAAe,CAAC;AAAA,QACpD,YAAY,OAAO,gBAAgB,cAAc,CAAC;AAAA,QAClD,gBAAgB,iBAAiB,IAAI,CAAC,SAAS;AAAA,UAC7C,kBAAkB,mCAAmC,IAAI,KAAK;AAAA,UAC9D,YAAY,OAAO,IAAI,eAAe,CAAC;AAAA,UACvC,oBAAoB,OAAO,IAAI,cAAc,CAAC;AAAA,QAChD,EAAE;AAAA,QACF,WAAW,YAAY,IAAI,CAAC,SAAS;AAAA,UACnC,aAAa,8BAA8B,IAAI,KAAK;AAAA,UACpD,YAAY,OAAO,IAAI,eAAe,CAAC;AAAA,UACvC,oBAAoB,OAAO,IAAI,cAAc,CAAC;AAAA,QAChD,EAAE;AAAA,QACF,mBAAmB,OAAO,iBAAiB;AAAA,MAC7C;AAAA,MACA,mBAAmB;AAAA,QACjB,qBAAqB;AAAA,QACrB,oBAAoB;AAAA,QACpB,eAAe,oBAAoB,IAAI,mBAAmB,oBAAoB;AAAA,QAC9E,uBAAuB,OAAO,UAAU,mBAAmB,CAAC;AAAA,MAC9D;AAAA,MACA,qBAAqB;AAAA,QACnB,gBAAgB;AAAA,QAChB;AAAA,QACA,gBAAgB,oBAAoB,IAAI,kBAAkB,oBAAoB;AAAA,QAC9E,qBAAqB,OAAO,YAAY,oBAAoB,CAAC;AAAA,QAC7D,oBAAoB,OAAO,YAAY,mBAAmB,CAAC;AAAA,QAC3D,uBAAuB,OAAO,YAAY,sBAAsB,CAAC;AAAA,MACnE;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,yBAAyB,QAAgB,IAmC3C;AACF,UAAM,KAAK,WAAW;AAEtB,QAAI;AACF,YAAM,iBAAiB,KAAK,eAAe,oBAAoB,cAAc,IACzE,+DACA;AACJ,YAAM,OAAO;AAAA,QACX,KAAK;AAAA,QACL,kCAAkC,cAAc;AAAA,QAChD,CAAC,KAAK;AAAA,MACR;AAEA,aAAO,KAAK,IAAI,CAAC,SAAS;AAAA,QACxB,SAAS,IAAI;AAAA,QACb,WAAY,IAAI,cAAyB;AAAA,QACzC,aAAc,IAAI,gBAA2B;AAAA,QAC7C,WAAW,IAAI;AAAA,QACf,cAAe,IAAI,kBAA6B;AAAA,QAChD,kBAAkB,0BAA0B,IAAI,kBAAmC;AAAA,QACnF,UAAW,IAAI,YAAuB;AAAA,QACtC,mBAAmB,IAAI,sBAAsB,KAAK,MAAM,IAAI,mBAA6B,IAAI,CAAC;AAAA,QAC9F,kBAAkB,IAAI,qBAAqB,KAAK,MAAM,IAAI,kBAA4B,IAAI,CAAC;AAAA,QAC3F,kBAAkB,2BAA2B,IAAI,sBAAsB;AAAA,QACvE,iBAAiB,2BAA2B,IAAI,qBAAqB;AAAA,QACrE,gBAAgB,OAAO,IAAI,mBAAmB,CAAC;AAAA,QAC/C,eAAe,OAAO,IAAI,kBAAkB,CAAC;AAAA,QAC7C,YAAa,IAAI,cAAyB;AAAA,QAC1C,eAAe,IAAI,iBAAiB,KAAK,MAAM,IAAI,cAAwB,IAAI,CAAC;AAAA,QAChF,kBAAkB,mCAAmC,IAAI,iBAAiB;AAAA,QAC1E,aAAa,8BAA8B,IAAI,YAAY;AAAA,QAC3D,gBAAgB,yBAAyB,IAAI,eAAe;AAAA,QAC5D,oBAAoB,iCAAiC,GAAG;AAAA,QACxD,WAAW,iBAAiB,IAAI,UAAU;AAAA,MAC5C,EAAE;AAAA,IACJ,SAAS,KAAU;AACjB,UAAI,KAAK,SAAS,SAAS,eAAe,EAAG,QAAO,CAAC;AACrD,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,yBA0BH;AACD,UAAM,KAAK,WAAW;AAEtB,QAAI;AACF,YAAM,+BAA+B,KAAK,eAAe,oBAAoB,oBAAoB,IAC7F,mCACA;AACJ,YAAM,iBAAiB,KAAK,eAAe,oBAAoB,cAAc,IACzE,+DACA;AACJ,YAAM,MAAM;AAAA,QACV,KAAK;AAAA,QACL;AAAA;AAAA;AAAA;AAAA,0BAIkB,4BAA4B;AAAA,0BAC5B,4BAA4B;AAAA,+BACvB,4BAA4B;AAAA,0BACjC,4BAA4B;AAAA,+BACvB,4BAA4B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,WAMhD,cAAc;AAAA,QACjB,CAAC;AAAA,MACH;AAEA,YAAM,oBAAoB,KAAK,eAAe,oBAAoB,UAAU,IACxE,oDACA;AACJ,YAAM,eAAe;AAAA,QACnB,KAAK;AAAA,QACL;AAAA,YACI,iBAAiB;AAAA;AAAA;AAAA,0BAGH,4BAA4B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,WAU3C,cAAc;AAAA,oBACL,iBAAiB;AAAA;AAAA,QAE7B,CAAC;AAAA,MACH;AAEA,YAAM,oBAAoB,aAAa,IAAI,CAAC,gBAAgB;AAC1D,cAAM,uBAAuB,OAAO,YAAY,iBAAiB,CAAC;AAClE,cAAM,+BAA+B,OAAO,YAAY,0BAA0B,CAAC;AACnF,cAAM,2BAA2B,OAAO,YAAY,qBAAqB,CAAC;AAC1E,eAAO;AAAA,UACL,UAAU,OAAO,YAAY,YAAY,SAAS;AAAA,UAClD,cAAc;AAAA,UACd,sBAAsB;AAAA,UACtB,kBAAkB;AAAA,UAClB,aAAa,uBAAuB,IAAI,2BAA2B,uBAAuB;AAAA,UAC1F,qBAAqB,OAAO,YAAY,yBAAyB,CAAC;AAAA,UAClE,oBAAoB,OAAO,YAAY,wBAAwB,CAAC;AAAA,UAChE,mBAAmB,OAAO,YAAY,uBAAuB,CAAC;AAAA,UAC9D,kBAAkB,OAAO,YAAY,sBAAsB,CAAC;AAAA,UAC5D,eAAe,OAAO,YAAY,kBAAkB,CAAC;AAAA,UACrD,gBAAgB,uBAAuB,IAAI,+BAA+B,uBAAuB;AAAA,QACnG;AAAA,MACF,CAAC;AAED,YAAM,eAAe,OAAO,KAAK,iBAAiB,CAAC;AACnD,YAAM,mBAAmB,OAAO,KAAK,qBAAqB,CAAC;AAC3D,YAAM,aAAa,KAAK,IAAI,GAAG,eAAe,gBAAgB;AAC9D,YAAM,gCAAgC,OAAO,KAAK,oCAAoC,CAAC;AACvF,YAAM,0BAA0B,OAAO,KAAK,8BAA8B,CAAC;AAE3E,aAAO;AAAA,QACL;AAAA,QACA,mBAAmB,OAAO,KAAK,uBAAuB,CAAC;AAAA,QACvD,kBAAkB,OAAO,KAAK,sBAAsB,CAAC;AAAA,QACrD,eAAe,OAAO,KAAK,kBAAkB,CAAC;AAAA,QAC9C;AAAA,QACA,aAAa,eAAe,IAAI,mBAAmB,eAAe;AAAA,QAClE;AAAA,QACA;AAAA,QACA,wBAAwB,mBAAmB,IAAI,gCAAgC,mBAAmB;AAAA,QAClG,kBAAkB,aAAa,IAAI,0BAA0B,aAAa;AAAA,QAC1E,qCAAqC,OAAO,KAAK,4CAA4C,CAAC;AAAA,QAC9F,+BAA+B,OAAO,KAAK,sCAAsC,CAAC;AAAA,QAClF;AAAA,MACF;AAAA,IACF,SAAS,KAAU;AACjB,UAAI,KAAK,SAAS,SAAS,eAAe,GAAG;AAC3C,eAAO;AAAA,UACL,cAAc;AAAA,UACd,mBAAmB;AAAA,UACnB,kBAAkB;AAAA,UAClB,eAAe;AAAA,UACf,kBAAkB;AAAA,UAClB,aAAa;AAAA,UACb,+BAA+B;AAAA,UAC/B,yBAAyB;AAAA,UACzB,wBAAwB;AAAA,UACxB,kBAAkB;AAAA,UAClB,qCAAqC;AAAA,UACrC,+BAA+B;AAAA,UAC/B,mBAAmB,CAAC;AAAA,QACtB;AAAA,MACF;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QAAuB;AAC3B,gBAAY,KAAK,EAAE;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,gBAAgB,WAAmB,SAQrC;AACF,UAAM,KAAK,WAAW;AAEtB,UAAM,QAAQ,SAAS,SAAS;AAChC,UAAM,SAAS,SAAS,UAAU;AAGlC,UAAM,WAAW;AAAA,MACf,KAAK;AAAA,MACL;AAAA;AAAA;AAAA,eAGS,yBAAyB,OAAO,CAAC;AAAA;AAAA;AAAA;AAAA,MAI1C,CAAC,WAAW,OAAO,MAAM;AAAA,IAC3B;AAEA,UAAM,QAQD,CAAC;AAEN,eAAW,WAAW,UAAU;AAC9B,YAAM,SAAS,MAAM,KAAK,gBAAgB,QAAQ,SAAS,OAAO;AAElE,YAAM,cAAc,OAAO,KAAK,OAAK,EAAE,cAAc,aAAa;AAClE,YAAM,aAAa,OAAO,OAAO,OAAK,EAAE,cAAc,kBAAkB;AACxE,YAAM,cAAc,OAAO,KAAK,OAAK,EAAE,cAAc,gBAAgB;AAErE,YAAM,KAAK;AAAA,QACT,QAAQ,QAAQ;AAAA,QAChB;AAAA,QACA,WAAW,iBAAiB,QAAQ,MAAM;AAAA,QAC1C,eAAe,cACX,YAAY,QAAQ,MAAM,GAAG,GAAG,KAAK,YAAY,QAAQ,SAAS,MAAM,QAAQ,MAChF;AAAA,QACJ,YAAY,OAAO;AAAA,QACnB,WAAW,WAAW;AAAA,QACtB;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBAAgB,QAAgB,SAAyD;AAC7F,UAAM,KAAK,WAAW;AAEtB,UAAM,OAAO;AAAA,MACX,KAAK;AAAA,MACL,8CAA8C,yBAAyB,OAAO,CAAC;AAAA,MAC/E,CAAC,MAAM;AAAA,IACT;AAEA,WAAO,KAAK,IAAI,KAAK,UAAU;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,kBAAkB,WAAmB,SAAkD;AAC3F,UAAM,KAAK,WAAW;AAEtB,UAAM,MAAM;AAAA,MACV,KAAK;AAAA,MACL;AAAA;AAAA;AAAA,eAGS,yBAAyB,OAAO,CAAC;AAAA,MAC1C,CAAC,SAAS;AAAA,IACZ;AAEA,WAAO,KAAK,SAAS;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,kBAAmC;AACvC,UAAM,KAAK,WAAW;AAGtB,UAAM,OAAO;AAAA,MACX,KAAK;AAAA,MACL;AAAA;AAAA,IAEF;AAEA,QAAI,UAAU;AACd,eAAW,OAAO,MAAM;AACtB,UAAI;AACF,cAAM,WAAW,KAAK,MAAM,IAAI,QAAQ;AACxC,YAAI,SAAS,QAAQ;AACnB;AAAA,YACE,KAAK;AAAA,YACL;AAAA,YACA,CAAC,SAAS,QAAQ,IAAI,EAAE;AAAA,UAC1B;AACA;AAAA,QACF;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBA,MAAM,gBAAgB,SAAmC;AACvD,UAAM,KAAK,WAAW;AAEtB,UAAM,gBAAgB,CAAC,eAAe,iBAAiB,mBAAmB,oBAAoB,iBAAiB,iBAAiB,EAC7H,OAAO,CAAC,UAAU,KAAK,SAAS,KAAK,KAAK,KAAK,eAAe,OAAO,UAAU,CAAC;AAEnF,UAAM,YAAY,KAAK,GAAG,YAAY,MAAc;AAClD,iBAAW,eAAe,CAAC,qBAAqB,qBAAqB,mBAAmB,GAAG;AACzF,kBAAU,KAAK,IAAI,0BAA0B,WAAW,EAAE;AAAA,MAC5D;AAEA,iBAAW,SAAS,eAAe;AACjC,kBAAU,KAAK,IAAI,eAAe,KAAK,uBAAuB,CAAC,OAAO,CAAC;AAAA,MACzE;AAEA,YAAM,SAAS,UAAU,KAAK,IAAI,mCAAmC,CAAC,OAAO,CAAC;AAE9E,WAAK,uBAAuB;AAE5B,aAAO,OAAO,WAAW;AAAA,IAC3B,CAAC;AAED,WAAO,UAAU,IAAI;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,oBAAoB,WAAoC;AAC5D,UAAM,KAAK,WAAW;AAGtB,UAAM,SAAS;AAAA,MACb,KAAK;AAAA,MACL;AAAA,MACA,CAAC,SAAS;AAAA,IACZ;AAEA,QAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,UAAM,WAAW,OAAO,IAAI,OAAK,EAAE,EAAE;AACrC,UAAM,eAAe,SAAS,IAAI,MAAM,GAAG,EAAE,KAAK,GAAG;AAYrD,UAAM,gBAAgB,CAAC,eAAe,iBAAiB,mBAAmB,oBAAoB,iBAAiB,iBAAiB,EAC7H,OAAO,CAAC,UAAU,KAAK,SAAS,KAAK,KAAK,KAAK,eAAe,OAAO,UAAU,CAAC;AAEnF,UAAM,YAAY,KAAK,GAAG,YAAY,MAAc;AAIlD,iBAAW,eAAe,CAAC,qBAAqB,qBAAqB,mBAAmB,GAAG;AACzF,kBAAU,KAAK,IAAI,0BAA0B,WAAW,EAAE;AAAA,MAC5D;AAGA,iBAAW,SAAS,eAAe;AACjC,kBAAU,KAAK,IAAI,eAAe,KAAK,uBAAuB,YAAY,KAAK,QAAQ;AAAA,MACzF;AAGA,YAAM,SAAS,UAAU,KAAK,IAAI,2CAA2C,CAAC,SAAS,CAAC;AAKxF,WAAK,uBAAuB;AAE5B,aAAO,OAAO,WAAW;AAAA,IAC3B,CAAC;AAED,WAAO,UAAU;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKQ,WAAW,KAA2C;AAC5D,UAAM,QAAa;AAAA,MACjB,IAAI,IAAI;AAAA,MACR,WAAW,IAAI;AAAA,MACf,WAAW,IAAI;AAAA,MACf,WAAW,iBAAiB,IAAI,SAAS;AAAA,MACzC,SAAS,IAAI;AAAA,MACb,cAAc,IAAI;AAAA,MAClB,WAAW,IAAI;AAAA,MACf,UAAU,uBAAuB,IAAI,QAAQ;AAAA,IAC/C;AAGA,QAAI,IAAI,iBAAiB,QAAW;AAClC,YAAM,eAAe,IAAI;AAAA,IAC3B;AACA,QAAI,IAAI,qBAAqB,QAAW;AACtC,YAAM,mBAAmB,IAAI;AAAA,IAC/B;AAEA,QAAI,IAAI,YAAY,UAAa,IAAI,YAAY,MAAM;AACrD,YAAM,UAAU,IAAI;AAAA,IACtB;AAEA,WAAO;AAAA,EACT;AACF;;;ArBltKO,IAAM,2BAA2B,OAAO,OAAO,EAAE,SAAS,GAAG,yBAAyB,KAAK,CAAC;AAEnG,IAAM,aAAaM,GAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG;AACnD,IAAM,OAAOA,GAAE,OAAO,EAAE,MAAM,mBAAmB,0CAA0C;AAC3F,IAAM,mBAAmBA,GAAE,OAAO;AAAA,EAChC,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAOA,GAAE,MAAM,UAAU,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE;AAAA,EACxC,YAAYA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC;AAAA,EACnC,kBAAkBA,GAAE,MAAM,UAAU,EAAE,IAAI,GAAG;AAAA,EAC7C,gBAAgBA,GAAE,MAAM,UAAU,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG;AAAA,EAClD,cAAcA,GAAE,MAAM,UAAU,EAAE,IAAI,EAAE,EAAE,QAAQ,CAAC,CAAC;AAAA,EACpD,gBAAgBA,GAAE,QAAQ,EAAE,QAAQ,KAAK;AAAA,EACzC,OAAO;AAAA,EACP,YAAYA,GAAE,MAAM,UAAU,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE;AAAA,EAC7C,gBAAgB;AAAA,EAChB,eAAeA,GAAE,MAAM,UAAU,EAAE,IAAI,EAAE,EAAE,SAAS;AACtD,CAAC,EAAE,OAAO;AACV,IAAM,cAAcA,GAAE,OAAO,EAAE,SAASA,GAAE,OAAO,EAAE,IAAI,GAAG,WAAW,YAAY,SAASA,GAAE,QAAQ,EAAE,CAAC,EAAE,OAAO;AAChH,IAAM,eAAe,YAAY,OAAO,EAAE,YAAYA,GAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,EAAE,OAAO;AAC/F,IAAM,oBAAoB,aAAa,OAAO;AAAA,EAC5C,aAAa;AAAA,EACb,kBAAkBA,GAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,EAC5C,aAAa;AACf,CAAC,EAAE,OAAO;AA8CV,SAAS,WAAW,OAAwB;AAC1C,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,IAAI,MAAM,IAAI,UAAU,EAAE,KAAK,GAAG,CAAC;AACpE,MAAI,SAAS,OAAO,UAAU,UAAU;AACtC,WAAO,IAAI,OAAO,QAAQ,KAAgC,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,KAAK,IAAI,MAAM,GAAG,KAAK,UAAU,GAAG,CAAC,IAAI,WAAW,IAAI,CAAC,EAAE,EAAE,KAAK,GAAG,CAAC;AAAA,EACjL;AACA,SAAO,KAAK,UAAU,KAAK;AAC7B;AACA,SAAS,mBAAmB,OAAwB;AAClD,QAAM,EAAE,SAAS,UAAU,GAAG,OAAO,IAAK,SAAS,OAAO,UAAU,WAAW,QAAQ,CAAC;AACxF,SAAOC,YAAW,QAAQ,EAAE,OAAO,WAAW,MAAM,CAAC,EAAE,OAAO,KAAK;AACrE;AAEO,SAAS,2BAA2B,SAA0B;AACnE,SAAOA,YAAW,QAAQ,EAAE,OAAO,WAAW,iBAAiB,MAAM,OAAO,CAAC,CAAC,EAAE,OAAO,KAAK;AAC9F;AAEA,SAAS,UAAa,OAAe,UAAgB;AACnD,MAAI;AAAE,WAAO,KAAK,MAAM,KAAK;AAAA,EAAQ,QAAQ;AAAE,WAAO;AAAA,EAAU;AAClE;AACA,SAAS,YAAY,MAAiC,OAA2C;AAC/F,SAAO,KAAK,gBAAgB,MAAM,eAAe,KAAK,YAAY,MAAM,WAAW,KAAK,cAAc,MAAM,aAAa,KAAK,cAAc,MAAM,aAAa,KAAK,eAAe,MAAM;AAC3L;AAEA,SAAS,iBAAiB,KAAmB;AAC3C,SAAO;AAAA,IACL,aAAa,IAAI;AAAA,IAAc,aAAa,IAAI;AAAA,IAAc,aAAa,IAAI;AAAA,IAC/E,QAAQ,IAAI;AAAA,IAAQ,UAAU,IAAI;AAAA,IAAU,YAAY,IAAI;AAAA,IAC5D,WAAW,IAAI;AAAA,IAAY,WAAW,IAAI;AAAA,IAAY,WAAW,IAAI;AAAA,IACrE,cAAc,UAAoB,IAAI,oBAAoB,CAAC,CAAC;AAAA,IAAG,oBAAoB,UAAoB,IAAI,2BAA2B,CAAC,CAAC;AAAA,IAAG,WAAW,UAAqB,IAAI,cAAc,CAAC,CAAc;AAAA,EAC9M;AACF;AAEA,SAAS,oBAAoB,WAA4B;AACvD,QAAMC,QAAO,CAAC,UAAU,MAAM,UAAU,SAAS,UAAU,OAAO,UAAU,gBAAgB,GAAG,UAAU,OAAO,GAAG,UAAU,YAAY,GAAG,UAAU,cAAc,GAAI,UAAU,iBAAiB,CAAC,CAAE,EAAE,KAAK,IAAI;AACjN,QAAM,UAAU,mBAAmBA,OAAM,EAAE,iBAAiB,CAAC,GAAG,WAAW,OAAO,aAAa,EAAE,SAAS,MAAM,QAAQ,aAAa,mBAAmB,OAAO,kBAAkB,CAAC,KAAK,EAAE,EAAE,CAAC;AAC5L,QAAM,oBAAoB;AAC1B,QAAM,iBAAiB;AACvB,MAAI,QAAQ,SAAS,kBAAkB,QAAQ,SAAS,oBAAoB,QAAQ,SAAS,oBAAoB,KAAK,kBAAkB,KAAKA,KAAI,KAAK,eAAe,KAAKA,KAAI,KAAK,uEAAuE,KAAKA,KAAI,GAAG;AACpQ,UAAM,IAAI,MAAM,+EAA+E;AAAA,EACjG;AACF;AAEO,IAAM,oBAAN,MAAwB;AAAA,EAC7B,YAA6B,SAAmC;AAAnC;AAAA,EAAoC;AAAA,EAApC;AAAA,EAE7B,MAAM,OAAO,OAAgB;AAC3B,UAAM,UAAU,YAAY,OAAO,EAAE,QAAQ,YAAY,OAAOF,GAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,IAAI,GAAK,GAAG,OAAOA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,KAAK;AAC7K,QAAI,QAAQ,YAAY,EAAG,QAAO,EAAE,SAAS,sBAA+B;AAC5E,UAAM,UAAU,MAAM,KAAK,YAAY,QAAQ,SAAS,aAAa;AACrE,UAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,UAAM,OAAO,IAAI,iBAAiB,KAAK,QAAQ,EAAE;AACjD,UAAM,WAA+F,CAAC;AACtG,aAAS,SAAS,KAAK,UAAU,KAAK;AACpC,UAAI,KAAK,IAAI,KAAK,SAAU,QAAO,EAAE,SAAS,WAAoB,WAAW,CAAC,GAAG,SAAS,CAAC,EAAE;AAC7F,YAAM,OAAO,MAAM,KAAK,KAAK,EAAE,aAAa,QAAQ,aAAa,OAAO,KAAK,OAAO,CAAC;AACrF,UAAI,CAAC,KAAK,OAAQ;AAClB,YAAM,UAAU,IAAI,gCAAgC,KAAK,QAAQ,EAAE,EAAE,OAAO,EAAE,aAAa,QAAQ,aAAa,SAAS,QAAQ,SAAS,MAAM,UAAU,YAAY,KAAK,OAAO,CAAC,WAAW,OAAO,aAAa,EAAE,IAAI,CAAC,WAAW,EAAE,eAAe,UAAmB,aAAa,MAAM,UAAU,MAAM,EAAE,EAAE,CAAC,EAAE;AAClT,iBAAW,QAAQ,QAAS,UAAS,KAAK,EAAE,QAAQ,KAAK,OAAO,eAAe,KAAK,cAAc,CAAC;AACnG,UAAI,KAAK,IAAI,KAAK,SAAU,QAAO,EAAE,SAAS,WAAoB,WAAW,CAAC,GAAG,SAAS,CAAC,EAAE;AAC7F,UAAI,KAAK,SAAS,IAAK;AACvB,YAAM,IAAI,QAAc,CAACG,aAAY,aAAaA,QAAO,CAAC;AAAA,IAC5D;AACA,QAAI,KAAK,IAAI,KAAK,SAAU,QAAO,EAAE,SAAS,WAAoB,WAAW,CAAC,GAAG,SAAS,CAAC,EAAE;AAC7F,UAAM,WAAW,MAAM,yBAAyB,SAAS,IAAI,CAAC,EAAE,OAAO,MAAM,MAAM,GAAG,QAAQ,OAAO,QAAQ,KAAK;AAClH,UAAM,UAAU,SAAS,IAAI,CAAC,YAAY,EAAE,QAAQ,eAAe,SAAS,KAAK,CAAC,SAAS,KAAK,OAAO,aAAa,OAAO,QAAQ,EAAG,cAAc,EAAE;AACtJ,QAAI,KAAK,IAAI,KAAK,SAAU,QAAO,EAAE,SAAS,WAAoB,WAAW,CAAC,GAAG,SAAS,CAAC,EAAE;AAC7F,UAAM,eAAe,MAAM,KAAK,YAAY,QAAQ,SAAS,aAAa;AAC1E,QAAI,CAAC,YAAY,SAAS,YAAY,EAAG,OAAM,IAAI,MAAM,+BAA+B;AACxF,QAAI,KAAK,IAAI,KAAK,SAAU,QAAO,EAAE,SAAS,WAAoB,WAAW,CAAC,GAAG,SAAS,CAAC,EAAE;AAC7F,QAAI,CAAC,KAAK,qBAAqB,SAAS,YAAY,EAAG,QAAO,EAAE,SAAS,YAAqB,WAAW,CAAC,GAAG,SAAS,CAAC,EAAE;AACzH,UAAM,UAAUC,YAAW;AAC3B,UAAM,WAAW,EAAE,SAAS,QAAQ,SAAS,aAAsB,YAAqB,SAAS,WAAW,QAAQ,IAAI,CAAC,EAAE,OAAO,MAAM,OAAO,QAAQ,GAAG,SAAS,QAAQ,IAAI,CAAC,EAAE,QAAQ,cAAc,MAAM,WAAW,QAAQ,aAAa,CAAC,EAAE;AACjP,UAAM,cAAc,mBAAmB,EAAE,SAAS,QAAQ,SAAS,WAAW,QAAQ,WAAW,QAAQ,QAAQ,QAAQ,OAAO,QAAQ,OAAO,OAAO,QAAQ,MAAM,CAAC;AACrK,WAAO,KAAK,QAAQ,GAAG,YAAY,MAAM;AAAE,YAAM,SAAS,KAAK,WAAW,QAAQ,WAAW,cAAc,UAAU,WAAW;AAAG,UAAI,OAAQ,QAAO,KAAK,kBAAkB,QAAQ,YAAY,IAAI,SAAS,EAAE,SAAS,YAAqB,WAAW,CAAC,GAAG,SAAS,CAAC,EAAE;AAAG,UAAI,CAAC,KAAK,qBAAqB,SAAS,YAAY,EAAG,QAAO,EAAE,SAAS,YAAqB,WAAW,CAAC,GAAG,SAAS,CAAC,EAAE;AAAG,WAAK,WAAW,EAAE,SAAS,WAAW,QAAQ,WAAW,SAAS,cAAc,QAAQ,QAAQ,QAAQ,OAAO,YAAY,SAAS,SAAS,SAAS,SAAS,QAAQ,IAAI,CAAC,EAAE,OAAO,MAAM,MAAM,EAAE,CAAC;AAAG,WAAK,SAAS,QAAQ,WAAW,cAAc,UAAU,aAAa,QAAQ;AAAG,aAAO;AAAA,IAAU,CAAC,EAAE;AAAA,EACtrB;AAAA,EAEA,MAAM,IAAI,OAAgB;AACxB,UAAM,UAAU,YAAY,OAAO,EAAE,UAAU,WAAW,CAAC,EAAE,OAAO,EAAE,MAAM,KAAK;AACjF,QAAI,QAAQ,YAAY,EAAG,QAAO,EAAE,SAAS,sBAA+B;AAC5E,UAAM,UAAU,MAAM,KAAK,YAAY,QAAQ,SAAS,aAAa;AACrE,UAAM,SAAS,IAAI,iBAAiB,KAAK,QAAQ,EAAE,EAAE,IAAI,QAAQ,QAAQ;AACzE,QAAI,CAAC,UAAU,OAAO,gBAAgB,QAAQ,eAAe,CAAC,KAAK,cAAc,SAAS,OAAO,QAAQ,EAAG,QAAO,EAAE,SAAS,YAAqB;AACnJ,UAAM,WAAW,EAAE,SAAS,SAAkB,QAAQ,WAAW,MAAM,EAAE;AACzE,UAAM,cAAc,mBAAmB,OAAO;AAAG,WAAO,KAAK,QAAQ,GAAG,YAAY,MAAM;AAAE,YAAM,SAAS,KAAK,WAAW,QAAQ,WAAW,SAAS,OAAO,WAAW;AAAG,UAAI,QAAQ;AAAE,cAAM,SAAS;AAAiE,eAAO,OAAO,QAAQ,aAAa,OAAO,YAAY,OAAO,OAAO,aAAa,OAAO,WAAW,SAAS,EAAE,SAAS,YAAqB;AAAA,MAAG;AAAE,WAAK,WAAW,EAAE,SAASA,YAAW,GAAG,WAAW,QAAQ,WAAW,SAAS,OAAO,QAAQ,SAAS,QAAQ,SAAS,CAAC,MAAM,EAAE,CAAC;AAAG,WAAK,SAAS,QAAQ,WAAW,SAAS,OAAO,aAAa,QAAQ;AAAG,aAAO;AAAA,IAAU,CAAC,EAAE;AAAA,EAChoB;AAAA,EAEA,MAAM,WAAW,OAAgB;AAC/B,UAAM,UAAU,YAAY,OAAO,EAAE,UAAU,WAAW,CAAC,EAAE,OAAO,EAAE,MAAM,KAAK;AACjF,QAAI,QAAQ,YAAY,EAAG,QAAO,EAAE,SAAS,sBAA+B;AAC5E,UAAM,UAAU,MAAM,KAAK,YAAY,QAAQ,SAAS,aAAa;AACrE,UAAM,SAAS,IAAI,iBAAiB,KAAK,QAAQ,EAAE,EAAE,IAAI,QAAQ,QAAQ;AACzE,QAAI,CAAC,UAAU,OAAO,gBAAgB,QAAQ,eAAe,CAAC,KAAK,cAAc,SAAS,OAAO,QAAQ,EAAG,QAAO,EAAE,SAAS,YAAqB;AACnJ,UAAM,UAAUA,YAAW;AAAG,UAAM,WAAW,EAAE,SAAS,QAAiB,QAAQ;AACnF,UAAM,cAAc,mBAAmB,OAAO;AAAG,WAAO,KAAK,QAAQ,GAAG,YAAY,MAAM;AAAE,YAAM,SAAS,KAAK,WAAW,QAAQ,WAAW,SAAS,QAAQ,WAAW;AAAG,UAAI,OAAQ,QAAO;AAAQ,WAAK,WAAW,EAAE,SAAS,WAAW,QAAQ,WAAW,SAAS,OAAO,QAAQ,SAAS,QAAQ,SAAS,CAAC,MAAM,EAAE,CAAC;AAAG,WAAK,SAAS,QAAQ,WAAW,SAAS,QAAQ,aAAa,QAAQ;AAAG,aAAO;AAAA,IAAU,CAAC,EAAE;AAAA,EACha;AAAA,EAEA,MAAM,YAAY,OAAgB;AAChC,UAAM,UAAU,YAAY,OAAO,EAAE,QAAQ,YAAY,SAAS,YAAY,WAAWJ,GAAE,MAAM,UAAU,EAAE,IAAI,CAAC,GAAG,iBAAiBA,GAAE,MAAMA,GAAE,OAAO,EAAE,UAAU,YAAY,UAAUA,GAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,KAAK;AAChQ,QAAI,QAAQ,YAAY,EAAG,QAAO,EAAE,SAAS,sBAA+B;AAC5E,UAAM,UAAU,MAAM,KAAK,YAAY,QAAQ,SAAS,aAAa;AACrE,UAAM,WAAW,UAAoB,KAAK,QAAQ,IAAI,uDAAuD,CAAC,QAAQ,OAAO,CAAC;AAC9H,UAAM,YAAY,QAAQ,gBAAgB,IAAI,CAAC,EAAE,UAAU,SAAS,OAAO,EAAE,UAAU,SAAS,EAAE;AAClG,UAAM,UAAU,UAAU,MAAM,CAAC,EAAE,UAAU,SAAS,MAAM;AAAE,YAAM,SAAS,IAAI,iBAAiB,KAAK,QAAQ,EAAE,EAAE,IAAI,QAAQ;AAAG,aAAO,QAAQ,gBAAgB,QAAQ,eAAe,OAAO,aAAa;AAAA,IAAU,CAAC;AACvN,QAAI,CAAC,YAAY,SAAS,iBAAiB,QAAQ,eAAe,SAAS,eAAe,QAAQ,aAAa,SAAS,aAAa,QAAQ,WAAW,SAAS,eAAe,QAAQ,aAAa,SAAS,eAAe,QAAQ,cAAc,SAAS,YAAY,QAAQ,UAAU,SAAS,UAAU,cAAc,KAAK,UAAU,UAAoB,SAAS,iBAAiB,CAAC,CAAC,CAAC,MAAM,KAAK,UAAU,QAAQ,SAAS,KAAK,KAAK,UAAU,UAAU,SAAS,uBAAuB,CAAC,CAAC,CAAC,MAAM,KAAK,UAAU,SAAS,KAAK,CAAC,QAAS,QAAO,EAAE,SAAS,cAAuB;AACxjB,UAAM,WAAW,EAAE,SAAS,aAAsB,SAAS,QAAQ,QAAQ;AAC3E,UAAM,cAAc,mBAAmB,OAAO;AAAG,WAAO,KAAK,QAAQ,GAAG,YAAY,MAAM;AAAE,YAAM,SAAS,KAAK,WAAW,QAAQ,WAAW,SAAS,aAAa,WAAW;AAAG,UAAI,OAAQ,QAAO;AAAQ,WAAK,WAAW,EAAE,SAASI,YAAW,GAAG,WAAW,QAAQ,WAAW,SAAS,QAAQ,QAAQ,QAAQ,OAAO,aAAa,SAAS,aAAa,SAAS,UAAU,IAAI,CAAC,EAAE,SAAS,MAAM,IAAI,iBAAiB,KAAK,QAAQ,EAAE,EAAE,IAAI,QAAQ,CAAE,EAAE,CAAC;AAAG,WAAK,SAAS,QAAQ,WAAW,SAAS,aAAa,aAAa,QAAQ;AAAG,aAAO;AAAA,IAAU,CAAC,EAAE;AAAA,EACviB;AAAA,EAEA,MAAM,iBAAiB,OAAgB;AACrC,UAAM,UAAU,aAAa,OAAO,EAAE,aAAa,YAAY,aAAa,KAAK,SAAS,GAAG,WAAW,kBAAkB,WAAWJ,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,KAAK;AAC7L,QAAI,QAAQ,YAAY,EAAG,QAAO,EAAE,SAAS,sBAA+B;AAC5E,UAAM,UAAU,MAAM,KAAK,aAAa,QAAQ,SAAS,QAAQ,YAAY,eAAe;AAC5F,UAAM,YAAY,iBAAiB,MAAM,QAAQ,SAAS;AAAG,wBAAoB,SAAS;AAAG,SAAK,mBAAmB,QAAQ,aAAa,UAAU,gBAAgB,UAAU,gBAAgB;AAC9L,UAAM,eAAe,2BAA2B,SAAS;AACzD,QAAI,QAAQ,eAAe,QAAQ,gBAAgB,aAAc,OAAM,IAAI,MAAM,wDAAwD;AACzI,UAAM,cAAc,mBAAmB,EAAE,GAAG,SAAS,aAAa,aAAa,CAAC;AAChF,WAAO,KAAK,QAAQ,GAAG,YAAY,MAAM;AACvC,YAAM,SAAS,KAAK,WAAW,QAAQ,WAAW,SAAS,WAAW,WAAW;AAAG,UAAI,OAAQ,QAAO;AACvG,WAAK,iBAAiB,QAAQ,WAAW;AACzC,YAAM,WAAW,UAAwB,KAAK,QAAQ,IAAI,sFAAsF,CAAC,QAAQ,aAAa,QAAQ,WAAW,CAAC;AAC1L,UAAI,CAAC,YAAY,UAA6B,KAAK,QAAQ,IAAI,oHAAoH,CAAC,QAAQ,WAAW,CAAC,EAAG,SAAS,GAAI,OAAM,IAAI,MAAM,+BAA+B;AACvQ,YAAM,SAAS,WAAW,iBAAiB,QAAQ,IAAI,KAAK,gBAAgB,SAAS,QAAQ,aAAa,cAAc,WAAW,QAAQ,SAAS;AACpJ,YAAM,WAAW,EAAE,SAAS,OAAO,QAAQ,GAAG,OAAO;AAAG,WAAK,SAAS,QAAQ,WAAW,SAAS,WAAW,aAAa,QAAQ;AAAG,aAAO;AAAA,IAC9I,CAAC,EAAE;AAAA,EACL;AAAA,EAEA,MAAM,wBAAwB,OAAgB;AAC5C,UAAM,UAAU,aAAa,OAAO,EAAE,aAAa,YAAY,WAAW,YAAY,SAASA,GAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,IAAI,GAAK,GAAG,YAAYA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,KAAK;AACxM,QAAI,QAAQ,YAAY,EAAG,QAAO,EAAE,SAAS,sBAA+B;AAC5E,UAAM,UAAU,MAAM,KAAK,aAAa,QAAQ,SAAS,QAAQ,YAAY,eAAe;AAC5F,QAAI,CAAC,KAAK,QAAQ,cAAc,QAAQ,cAAc,QAAQ,aAAa,CAAC,QAAQ,qBAAqB,SAAS,QAAQ,SAAS,EAAG,OAAM,IAAI,MAAM,gDAAgD;AACtM,UAAM,WAAW,mBAAmB,QAAQ,SAAS,EAAE,iBAAiB,CAAC,GAAG,WAAW,OAAO,aAAa,EAAE,SAAS,MAAM,QAAQ,aAAa,mBAAmB,OAAO,kBAAkB,CAAC,KAAK,EAAE,EAAE,CAAC;AACxM,QAAI,SAAS,SAAS,kBAAkB,SAAS,SAAS,oBAAoB,cAAc,KAAK,SAAS,OAAO,KAAK,OAAO,WAAW,SAAS,SAAS,MAAM,IAAI,OAAS,SAAS,QAAQ,WAAW,EAAG,OAAM,IAAI,MAAM,mCAAmC;AAC/P,UAAM,cAAc,mBAAmB,EAAE,GAAG,SAAS,SAAS,SAAS,QAAQ,CAAC;AAChF,UAAM,SAAS,KAAK,WAAW,QAAQ,WAAW,SAAS,8BAA8B,WAAW;AAAG,QAAI,OAAQ,QAAO;AAC1H,UAAM,cAAcC,YAAW,QAAQ,EAAE,OAAO,SAAS,OAAO,EAAE,OAAO,KAAK;AAC9E,UAAM,SAAS,MAAM,KAAK,QAAQ,WAAW,iBAAiB,QAAQ,SAAS,GAAG,KAAK,CAACI,WAAWA,OAAM,UAAyE,gBAAgB,QAAQ,WAAW;AACrN,QAAI,OAAO;AACT,UAAK,MAAM,UAAmD,gBAAgB,eAAgB,MAAM,UAAsE,OAAO,SAAS,SAAS,QAAQ,YAAa,OAAM,IAAI,MAAM,8BAA8B;AACtQ,YAAMC,YAAW,EAAE,SAAS,aAAsB,SAAS,MAAM,IAAI,aAAa,QAAQ,aAAa,UAAU,SAAS,YAAY,QAAQ,QAAQ;AACtJ,WAAK,QAAQ,GAAG,YAAY,MAAM,KAAK,SAAS,QAAQ,WAAW,SAAS,8BAA8B,aAAaA,SAAQ,CAAC,EAAE;AAAG,aAAOA;AAAA,IAC9I;AACA,UAAM,eAAe,MAAM,KAAK,aAAa,QAAQ,SAAS,QAAQ,YAAY,eAAe;AACjG,UAAM,UAAUF,YAAW;AAC3B,UAAM,QAAqB,EAAE,IAAI,SAAS,WAAW,oBAAoB,WAAW,QAAQ,WAAW,WAAW,QAAQ,aAAa,IAAI,KAAK,QAAQ,UAAU,IAAI,oBAAI,KAAK,GAAG,SAAS,SAAS,SAAS,cAAc,mBAAmB,aAAa,WAAW,IAAI,QAAQ,WAAW,IAAI,WAAW,mBAAmB,aAAa,WAAW,IAAI,QAAQ,WAAW,IAAI,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,YAAY,EAAE,GAAG,QAAQ,0BAA0B,aAAa,QAAQ,aAAa,YAAY,EAAE;AACxgB,UAAM,YAAY,MAAM,KAAK,QAAQ,WAAW,aAAa,CAAC,KAAK,CAAC;AACpE,QAAI,UAAU,aAAa,EAAG,OAAM,IAAI,MAAM,0EAA0E;AACxH,UAAM,WAAW,EAAE,SAAS,aAAsB,SAAS,aAAa,QAAQ,aAAa,UAAU,SAAS,YAAY,QAAQ,QAAQ;AAC5I,SAAK,QAAQ,GAAG,YAAY,MAAM;AAAE,WAAK,SAAS,QAAQ,WAAW,SAAS,8BAA8B,aAAa,QAAQ;AAAA,IAAG,CAAC,EAAE;AACvI,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,aAAa,OAAgB;AAAE,WAAO,KAAK,WAAW,OAAO,YAAY,eAAe;AAAA,EAAG;AAAA,EACjG,MAAM,gBAAgB,OAAgB;AAAE,WAAO,KAAK,WAAW,OAAO,YAAY,eAAe;AAAA,EAAG;AAAA,EAEpG,MAAM,iBAAiB,OAAgB;AACrC,UAAM,UAAU,kBAAkB,MAAM,KAAK;AAC7C,QAAI,QAAQ,YAAY,EAAG,QAAO,EAAE,SAAS,sBAA+B;AAC5E,UAAM,KAAK,aAAa,QAAQ,SAAS,QAAQ,YAAY,eAAe;AAC5E,UAAM,cAAc,mBAAmB,OAAO;AAE9C,UAAM,eAAe,MAAM,KAAK,aAAa,QAAQ,SAAS,QAAQ,YAAY,eAAe;AACjG,UAAM,cAAc,KAAK,QAAQ,GAAG,YAAY,MAAM;AACpD,YAAM,SAAS,KAAK,WAAW,QAAQ,WAAW,cAAc,WAAW,WAAW;AAAG,UAAI,OAAQ,QAAO;AAC5G,YAAM,MAAM,KAAK,iBAAiB,QAAQ,aAAa,cAAc,QAAQ,kBAAkB,QAAQ,aAAa,YAAY,KAAK;AACrI,YAAM,YAAY,iBAAiB,MAAM,UAAU,IAAI,cAAc,CAAC,CAAC,CAAC;AAAG,0BAAoB,SAAS;AAAG,WAAK,mBAAmB,aAAa,aAAa,UAAU,gBAAgB,UAAU,gBAAgB;AACjN,YAAM,WAAW,UAA2E,KAAK,QAAQ,IAAI,sGAAsG,CAAC,aAAa,aAAa,UAAU,IAAI,CAAC;AAC7P,UAAI,UAAU;AAAE,cAAM,QAAQ,IAAI,MAAM,6EAA6E;AAAgC,cAAM,OAAO;AAAkB,cAAM;AAAA,MAAO;AACjM,YAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AAAG,YAAM,WAAWA,YAAW;AAClE,gBAAU,KAAK,QAAQ,IAAI,iXAAiX,CAAC,UAAU,aAAa,aAAa,UAAU,MAAM,UAAU,SAAS,KAAK,UAAU,UAAU,KAAK,GAAG,UAAU,YAAY,KAAK,UAAU,UAAU,gBAAgB,GAAG,KAAK,UAAU,UAAU,cAAc,GAAG,KAAK,UAAU,UAAU,YAAY,GAAG,UAAU,iBAAiB,IAAI,GAAG,UAAU,OAAO,KAAK,UAAU,UAAU,UAAU,GAAG,UAAU,gBAAgB,KAAK,UAAU,UAAU,iBAAiB,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC;AACpzB,oCAA8B,KAAK,QAAQ,IAAI,EAAE,WAAW,kBAAkB,OAAO,aAAa,SAAS,aAAa,aAAa,aAAa,YAAY,UAAU,UAAU,UAAU,WAAW,EAAE,UAAU,MAAM,UAAU,MAAM,SAAS,UAAU,SAAS,OAAO,UAAU,OAAO,aAAa,UAAU,GAAG,gBAAgB,UAAU,eAAe,CAAC;AACjW,YAAM,UAAU,UAAU,KAAK,QAAQ,IAAI,4LAA4L,CAAC,KAAK,IAAI,cAAc,aAAa,aAAa,QAAQ,kBAAkB,QAAQ,WAAW,CAAC;AACvU,UAAI,QAAQ,YAAY,EAAG,OAAM,IAAI,MAAM,mCAAmC;AAC9E,YAAM,SAAS,IAAI,iBAAiB,KAAK,QAAQ,EAAE,EAAE,IAAI,QAAQ;AACjE,YAAM,SAAS,EAAE,SAAS,YAAqB,aAAa,IAAI,cAAc,UAAU,gBAAgB,OAAO,SAAS;AAAG,WAAK,SAAS,QAAQ,WAAW,cAAc,WAAW,aAAa,MAAM;AAAG,aAAO;AAAA,IACpN,CAAC;AACD,WAAO,YAAY;AAAA,EACrB;AAAA,EAEA,MAAM,iBAAiB,OAAgB;AACrC,UAAM,UAAU,aAAa,OAAO,EAAE,UAAU,YAAY,kBAAkBJ,GAAE,OAAO,EAAE,IAAI,EAAE,SAAS,GAAG,SAASA,GAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,KAAK;AACvJ,QAAI,QAAQ,YAAY,EAAG,QAAO,EAAE,SAAS,sBAA+B;AAC5E,UAAM,KAAK,aAAa,QAAQ,SAAS,QAAQ,YAAY,eAAe;AAC5E,UAAM,UAAU,MAAM,KAAK,aAAa,QAAQ,SAAS,QAAQ,YAAY,eAAe;AAC5F,UAAM,cAAc,mBAAmB,OAAO;AAC9C,WAAO,KAAK,QAAQ,GAAG,YAAY,MAAM;AACvC,YAAM,SAAS,KAAK,WAAW,QAAQ,WAAW,SAAS,cAAc,WAAW;AAAG,UAAI,OAAQ,QAAO;AAC1G,YAAM,SAAS,IAAI,iBAAiB,KAAK,QAAQ,EAAE,EAAE,iBAAiB,EAAE,UAAU,QAAQ,UAAU,aAAa,QAAQ,aAAa,kBAAkB,QAAQ,kBAAkB,SAAS,QAAQ,QAAQ,CAAC;AAC5M,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,8CAA8C;AAC3E,YAAM,WAAW,EAAE,SAAS,WAAoB,UAAU,OAAO,UAAU,UAAU,OAAO,UAAU,eAAe,OAAO,cAAc;AAC1I,WAAK,SAAS,QAAQ,WAAW,SAAS,cAAc,aAAa,QAAQ;AAAG,aAAO;AAAA,IACzF,CAAC,EAAE;AAAA,EACL;AAAA,EAEA,MAAM,eAAe,OAAgB;AACnC,UAAM,UAAU,YAAY,OAAO,EAAE,OAAOA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,GAAG,GAAG,QAAQA,GAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,KAAK;AAAG,QAAI,QAAQ,YAAY,EAAG,QAAO,EAAE,SAAS,sBAA+B;AACnP,UAAM,UAAU,MAAM,KAAK,YAAY,QAAQ,SAAS,eAAe;AAAG,SAAK,iBAAiB,QAAQ,WAAW;AACnH,UAAM,OAAO,UAAwB,KAAK,QAAQ,IAAI,2GAA2G,CAAC,QAAQ,aAAa,QAAQ,QAAQ,GAAG,QAAQ,MAAM,CAAC;AACzN,WAAO,EAAE,SAAS,MAAe,YAAY,KAAK,MAAM,GAAG,QAAQ,KAAK,EAAE,IAAI,gBAAgB,GAAG,YAAY,KAAK,SAAS,QAAQ,QAAQ,QAAQ,SAAS,QAAQ,QAAQ,KAAK;AAAA,EACnL;AAAA,EAEA,MAAM,aAAa,OAAgB;AACjC,UAAM,UAAU,YAAY,OAAO,EAAE,aAAa,WAAW,CAAC,EAAE,OAAO,EAAE,MAAM,KAAK;AAAG,QAAI,QAAQ,YAAY,EAAG,QAAO,EAAE,SAAS,sBAA+B;AACnK,UAAM,UAAU,MAAM,KAAK,YAAY,QAAQ,SAAS,eAAe;AAAG,SAAK,iBAAiB,QAAQ,WAAW;AACnH,UAAM,YAAY,UAAwB,KAAK,QAAQ,IAAI,kFAAkF,CAAC,QAAQ,aAAa,QAAQ,WAAW,CAAC;AACvL,WAAO,YAAY,EAAE,SAAS,SAAkB,WAAW,iBAAiB,SAAS,EAAE,IAAI,EAAE,SAAS,YAAqB;AAAA,EAC7H;AAAA,EAEA,MAAM,YAAY,OAAgB;AAChC,UAAM,UAAU,YAAY,OAAO,EAAE,OAAOA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,GAAG,GAAG,QAAQA,GAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,KAAK;AAAG,QAAI,QAAQ,YAAY,EAAG,QAAO,EAAE,SAAS,sBAA+B;AACnP,UAAM,UAAU,MAAM,KAAK,YAAY,QAAQ,SAAS,eAAe;AAAG,UAAM,UAAU,MAAM,IAAI,iBAAiB,KAAK,QAAQ,EAAE,EAAE,KAAK,EAAE,aAAa,QAAQ,aAAa,OAAO,QAAQ,QAAQ,GAAG,QAAQ,QAAQ,OAAO,CAAC;AACjO,WAAO,EAAE,SAAS,MAAe,SAAS,QAAQ,MAAM,GAAG,QAAQ,KAAK,EAAE,IAAI,CAAC,WAAW;AAAE,YAAM,SAAS,UAAiD,KAAK,QAAQ,IAAI,iKAAiK,CAAC,OAAO,UAAU,QAAQ,WAAW,CAAC;AAAG,YAAM,SAAS,CAAC,UAAkB,OAAO,KAAK,CAAC,UAAU,MAAM,UAAU,KAAK,GAAG,cAAc;AAAM,aAAO,EAAE,UAAU,OAAO,UAAU,MAAM,OAAO,MAAM,SAAS,OAAO,SAAS,OAAO,OAAO,OAAO,cAAc,OAAO,cAAc,OAAO,OAAO,OAAO,YAAY,OAAO,YAAY,gBAAgB,OAAO,gBAAgB,eAAe,OAAO,eAAe,UAAU,OAAO,UAAU,eAAe,OAAO,eAAe,kBAAkB,OAAO,kBAAkB,gBAAgB,OAAO,gBAAgB,WAAW,OAAO,UAAU,YAAY,GAAG,WAAW,OAAO,UAAU,YAAY,GAAG,gBAAgB,OAAO,UAAU,GAAG,iBAAiB,OAAO,WAAW,GAAG,YAAY,OAAO,MAAM,EAAE;AAAA,IAAG,CAAC,GAAG,YAAY,QAAQ,SAAS,QAAQ,QAAQ,QAAQ,SAAS,QAAQ,QAAQ,KAAK;AAAA,EAC7oC;AAAA,EAEA,MAAM,WAAW,OAAgB;AAC/B,UAAM,UAAU,YAAY,OAAO,EAAE,OAAOA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,GAAG,GAAG,QAAQA,GAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,KAAK;AAAG,QAAI,QAAQ,YAAY,EAAG,QAAO,EAAE,SAAS,sBAA+B;AACnP,UAAM,UAAU,MAAM,KAAK,YAAY,QAAQ,SAAS,eAAe;AACvE,UAAM,OAAO,UAAoB,KAAK,QAAQ,IAAI,+PAA+P,CAAC,QAAQ,aAAa,QAAQ,QAAQ,GAAG,QAAQ,MAAM,CAAC;AACzW,WAAO,EAAE,SAAS,MAAe,QAAQ,KAAK,MAAM,GAAG,QAAQ,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,SAAS,IAAI,UAAU,WAAW,IAAI,YAAY,WAAW,IAAI,YAAY,SAAS,IAAI,UAAU,WAAW,IAAI,YAAY,QAAQ,IAAI,SAAS,YAAY,IAAI,YAAY,OAAO,IAAI,OAAO,SAAS,IAAI,SAAS,WAAW,UAAoB,IAAI,iBAAiB,CAAC,CAAC,GAAG,iBAAiB,UAAyD,IAAI,uBAAuB,CAAC,CAAC,GAAG,WAAW,IAAI,WAAW,EAAE,GAAG,YAAY,KAAK,SAAS,QAAQ,QAAQ,QAAQ,SAAS,QAAQ,QAAQ,KAAK;AAAA,EAClkB;AAAA,EAEA,MAAc,WAAW,OAAgB,QAAiC,YAA+C;AACvH,UAAM,UAAU,kBAAkB,MAAM,KAAK;AAAG,QAAI,QAAQ,YAAY,EAAG,QAAO,EAAE,SAAS,sBAA+B;AAC5H,UAAM,UAAU,MAAM,KAAK,aAAa,QAAQ,SAAS,QAAQ,YAAY,UAAU;AAAG,UAAM,cAAc,mBAAmB,OAAO;AACxI,UAAM,UAAU,WAAW,aAAa,YAAY;AAAY,UAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AAAG,UAAM,KAAK,aAAa,QAAQ,SAAS,QAAQ,YAAY,UAAU;AAC7K,WAAO,KAAK,QAAQ,GAAG,YAAY,MAAM;AACvC,YAAM,SAAS,KAAK,WAAW,QAAQ,WAAW,SAAS,QAAQ,WAAW;AAAG,UAAI,OAAQ,QAAO;AACpG,YAAM,oBAAoB,WAAW;AACrC,WAAK,iBAAiB,QAAQ,aAAa,SAAS,QAAQ,kBAAkB,QAAQ,aAAa,SAAS,iBAAiB;AAC7H,YAAM,UAAU,oBACZ,UAAU,KAAK,QAAQ,IAAI,2LAA2L,CAAC,QAAQ,KAAK,QAAQ,aAAa,QAAQ,aAAa,QAAQ,kBAAkB,QAAQ,aAAa,QAAQ,YAAY,OAAO,CAAC,IACzV,UAAU,KAAK,QAAQ,IAAI,0KAA0K,CAAC,QAAQ,KAAK,QAAQ,aAAa,QAAQ,aAAa,QAAQ,kBAAkB,QAAQ,aAAa,OAAO,CAAC;AACxT,UAAI,QAAQ,YAAY,EAAG,OAAM,IAAI,MAAM,oDAAoD;AAC/F,YAAM,SAAS,iBAAiB,UAAwB,KAAK,QAAQ,IAAI,iEAAiE,CAAC,QAAQ,WAAW,CAAC,CAAE;AAAG,YAAM,WAAW,EAAE,SAAS,QAAQ,GAAG,OAAO;AAAG,WAAK,SAAS,QAAQ,WAAW,SAAS,QAAQ,aAAa,QAAQ;AAAG,aAAO;AAAA,IACxS,CAAC,EAAE;AAAA,EACL;AAAA,EAEA,MAAc,YAAY,OAAgB,YAA+D;AAAE,UAAM,UAAU,MAAM,KAAK,QAAQ,cAAc,KAAK;AAAG,SAAK,cAAc,SAAS,UAAU;AAAG,WAAO;AAAA,EAAS;AAAA,EAC7N,MAAc,aAAa,OAAgB,YAAoB,YAA+D;AAAE,UAAM,UAAU,MAAM,KAAK,YAAY,OAAO,UAAU;AAAG,QAAI,QAAQ,eAAe,WAAY,OAAM,IAAI,MAAM,6BAA6B;AAAG,WAAO;AAAA,EAAS;AAAA,EAC1R,cAAc,SAAoC,YAAoB;AAAE,QAAI,CAAC,WAAW,UAAU,QAAQ,WAAW,EAAE,WAAW,CAAC,WAAW,UAAU,QAAQ,OAAO,EAAE,WAAW,CAAC,QAAQ,aAAa,SAAS,UAAmB,EAAG,OAAM,IAAI,MAAM,wCAAwC;AAAA,EAAG;AAAA,EACpS,cAAc,SAAoC,UAA2B;AAAE,QAAI;AAAE,aAAO,IAAI,6BAA6B,KAAK,QAAQ,EAAE,EAAE,MAAM,EAAE,aAAa,QAAQ,aAAa,eAAe,UAAU,aAAa,UAAU,kBAAkB,QAAQ,SAAS,YAAY,OAAO,CAAC,EAAE;AAAA,IAAS,QAAQ;AAAE,aAAO;AAAA,IAAO;AAAA,EAAE;AAAA,EACpU,mBAAmB,aAAqB,KAAe,kBAA6B;AAAE,UAAM,OAAO,UAAgE,KAAK,QAAQ,IAAI,4DAA4D,IAAI,IAAI,MAAM,GAAG,EAAE,KAAK,GAAG,CAAC,KAAK,GAAG;AAAG,QAAI,KAAK,WAAW,IAAI,OAAQ,OAAM,IAAI,MAAM,mCAAmC;AAAG,eAAW,OAAO,MAAM;AAAE,YAAM,WAAW,UAAmC,IAAI,UAAU,CAAC,CAAC;AAAG,UAAK,SAAS,OAAuD,SAAS,SAAS,YAAa,OAAM,IAAI,MAAM,+BAA+B;AAAA,IAAG;AAAE,QAAI,kBAAkB;AAAE,YAAM,WAAW,IAAI,IAAI,KAAK,IAAI,CAAC,QAAQ,IAAI,UAAU,CAAC;AAAG,UAAI,iBAAiB,WAAW,SAAS,QAAQ,iBAAiB,KAAK,CAAC,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC,EAAG,OAAM,IAAI,MAAM,gDAAgD;AAAA,IAAG;AAAA,EAAE;AAAA,EACn2B,gBAAgB,SAAoC,aAAqB,aAAqB,WAAsB,WAAoB;AAAE,UAAM,cAAcI,YAAW;AAAG,UAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AAAG,UAAM,YAAY,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,KAAK,KAAK,GAAI,EAAE,YAAY;AAAG,UAAM,UAAU,aAAa,YAAY,YAAY,YAAY;AAAW,UAAM,qBAAqB,KAAK,uBAAuB,QAAQ,aAAa,SAAS;AAAG,cAAU,KAAK,QAAQ,IAAI,uRAAuR,CAAC,aAAa,QAAQ,aAAa,aAAa,aAAa,WAAW,SAAS,GAAG,KAAK,UAAU,UAAU,cAAc,GAAG,KAAK,UAAU,kBAAkB,GAAG,QAAQ,YAAY,SAAS,KAAK,GAAG,CAAC;AAAG,WAAO,iBAAiB,UAAwB,KAAK,QAAQ,IAAI,iEAAiE,CAAC,WAAW,CAAC,CAAE;AAAA,EAAG;AAAA,EACxlC,iBAAiB,IAAY,SAAoC,UAAkB,MAAcG,SAAyB,mBAA4B;AAAE,UAAM,MAAM,UAAwB,KAAK,QAAQ,IAAI,iEAAiE,CAAC,EAAE,CAAC;AAAG,QAAI,CAAC,OAAO,IAAI,iBAAiB,QAAQ,eAAe,IAAI,aAAa,YAAY,IAAI,iBAAiB,QAAQ,IAAI,WAAWA,WAAW,qBAAqB,IAAI,eAAe,QAAQ,WAAa,OAAM,IAAI,MAAM,6DAA6D;AAAG,QAAI,IAAI,cAAc,IAAI,eAAc,oBAAI,KAAK,GAAE,YAAY,GAAG;AAAE,gBAAU,KAAK,QAAQ,IAAI,gHAAgH,EAAC,oBAAI,KAAK,GAAE,YAAY,GAAG,EAAE,CAAC;AAAG,YAAM,IAAI,MAAM,uBAAuB;AAAA,IAAG;AAAE,WAAO;AAAA,EAAK;AAAA,EACt1B,MAAc;AAAE,WAAO,KAAK,QAAQ,MAAM,KAAK,KAAK,IAAI;AAAA,EAAG;AAAA,EAC3D,kBAAkB,QAAiB,SAA6C;AAAE,UAAM,OAAO;AAA6H,QAAI,CAAC,MAAM,QAAQ,KAAK,OAAO,EAAG,QAAO;AAAO,UAAM,UAAU,KAAK,QAAQ,IAAI,CAAC,SAAS,OAAO,KAAK,aAAa,WAAW,IAAI,iBAAiB,KAAK,QAAQ,EAAE,EAAE,IAAI,KAAK,QAAQ,IAAI,MAAS;AAAG,QAAI,QAAQ,KAAK,CAAC,QAAQ,UAAU,CAAC,UAAU,OAAO,aAAa,KAAK,QAAS,KAAK,EAAG,QAAQ,EAAG,QAAO;AAAO,WAAO,KAAK,qBAAqB,QAAQ,IAAI,CAAC,QAAQ,WAAW,EAAE,QAAiB,eAAe,KAAK,QAAS,KAAK,EAAG,iBAAiB,SAAS,EAAE,GAAG,OAAO;AAAA,EAAG;AAAA,EACtrB,qBAAqB,WAA+F,SAA6C;AAAE,UAAM,UAAU,UAAU,IAAI,CAAC,EAAE,OAAO,MAAM,IAAI,iBAAiB,KAAK,QAAQ,EAAE,EAAE,IAAI,OAAO,QAAQ,CAAC;AAAG,QAAI,QAAQ,KAAK,CAAC,QAAQ,UAAU,CAAC,UAAU,OAAO,gBAAgB,QAAQ,eAAe,OAAO,aAAa,UAAU,KAAK,EAAG,OAAO,YAAY,CAAC,OAAO,iBAAiB,CAAC,KAAK,cAAc,SAAS,OAAO,QAAQ,CAAC,EAAG,QAAO;AAAO,UAAM,UAAU,IAAI,gCAAgC,KAAK,QAAQ,EAAE,EAAE,OAAO,EAAE,aAAa,QAAQ,aAAa,SAAS,QAAQ,SAAS,MAAM,UAAU,YAAY,QAAQ,IAAI,CAAC,YAAY,EAAE,eAAe,UAAmB,aAAa,OAAQ,UAAU,OAAO,OAAQ,EAAE,EAAE,CAAC,EAAE;AAAO,WAAO,QAAQ,WAAW,UAAU,UAAU,UAAU,MAAM,CAAC,EAAE,QAAQ,cAAc,MAAM,QAAQ,KAAK,CAAC,SAAS,KAAK,MAAM,aAAa,OAAO,YAAY,KAAK,kBAAkB,aAAa,CAAC;AAAA,EAAG;AAAA,EACj+B,uBAAuB,aAAqB,WAAgC;AAAE,UAAM,QAAQ,IAAI,IAAI,GAAG,UAAU,IAAI,IAAI,UAAU,OAAO,GAAG,YAAY,EAAE,MAAM,kBAAkB,KAAK,CAAC,CAAC;AAAG,WAAO,UAAgE,KAAK,QAAQ,IAAI,4EAA4E,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC,WAAW;AAAE,YAAM,QAAQ,IAAI,IAAI,GAAG,OAAO,IAAI,IAAI,OAAO,OAAO,GAAG,YAAY,EAAE,MAAM,kBAAkB,KAAK,CAAC,CAAC;AAAG,UAAI,UAAU;AAAG,iBAAW,QAAQ,MAAO,KAAI,MAAM,IAAI,IAAI,EAAG,YAAW;AAAG,aAAO,OAAO,SAAS,UAAU,QAAQ,WAAW,KAAK,UAAU,KAAK,IAAI,MAAM,MAAM,MAAM,IAAI,KAAK;AAAA,IAAK,CAAC,EAAE,IAAI,CAAC,WAAW,OAAO,SAAS;AAAA,EAAG;AAAA,EAC9sB,iBAAiB,aAAqB;AAAE,cAAU,KAAK,QAAQ,IAAI,oMAAoM,EAAC,oBAAI,KAAK,GAAE,YAAY,GAAG,cAAa,oBAAI,KAAK,GAAE,YAAY,CAAC,CAAC;AAAA,EAAG;AAAA,EAC3U,WAAW,OAA6J;AAAE,cAAU,KAAK,QAAQ,IAAI,mQAAmQ,CAAC,MAAM,SAAS,MAAM,QAAQ,aAAa,MAAM,QAAQ,WAAW,MAAM,QAAQ,SAAS,MAAM,QAAQ,WAAW,MAAM,QAAQ,YAAY,MAAM,UAAU,MAAM,MAAM,WAAW,MAAM,OAAO,MAAM,SAAS,KAAK,UAAU,MAAM,QAAQ,IAAI,CAAC,WAAW,OAAO,QAAQ,CAAC,GAAG,KAAK,UAAU,MAAM,QAAQ,IAAI,CAAC,YAAY,EAAE,UAAU,OAAO,UAAU,UAAU,OAAO,SAAS,EAAE,CAAC,IAAG,oBAAI,KAAK,GAAE,YAAY,CAAC,CAAC;AAAA,EAAG;AAAA,EACh2B,WAAW,WAAmB,SAAoC,WAAmB,aAAqC;AAAE,UAAM,MAAM,UAA2E,KAAK,QAAQ,IAAI,gIAAgI,CAAC,QAAQ,aAAa,QAAQ,SAAS,SAAS,CAAC;AAAG,QAAI,CAAC,IAAK,QAAO;AAAM,QAAI,IAAI,cAAc,aAAa,IAAI,gBAAgB,YAAa,OAAM,IAAI,MAAM,4BAA4B;AAAG,WAAO,UAAU,IAAI,aAAa,IAAI;AAAA,EAAG;AAAA,EAC3kB,SAAS,WAAmB,SAAoC,WAAmB,aAAqB,QAAiB;AAAE,cAAU,KAAK,QAAQ,IAAI,0JAA0J,CAAC,QAAQ,aAAa,QAAQ,SAAS,WAAW,WAAW,aAAa,KAAK,UAAU,MAAM,IAAG,oBAAI,KAAK,GAAE,YAAY,CAAC,CAAC;AAAA,EAAG;AACxb;AAEA,SAAS,WAAW,QAAsB,gBAAoD,UAAU;AAAE,MAAI,kBAAkB,YAAa,QAAO,EAAE,UAAU,OAAO,UAAU,UAAU,OAAO,UAAU,MAAM,OAAO,MAAM,cAAc;AAAG,MAAI,kBAAkB,UAAW,QAAO,EAAE,UAAU,OAAO,UAAU,UAAU,OAAO,UAAU,MAAM,OAAO,MAAM,SAAS,OAAO,SAAS,OAAO,OAAO,MAAM,MAAM,GAAG,CAAC,GAAG,OAAO,OAAO,OAAO,YAAY,OAAO,YAAY,gBAAgB,OAAO,gBAAgB,eAAe,OAAO,eAAe,WAAW,OAAO,MAAM,SAAS,KAAK,OAAO,aAAa,SAAS,GAAG,iBAAiB,kBAAkB,cAAc;AAAG,SAAO,EAAE,UAAU,OAAO,UAAU,UAAU,OAAO,UAAU,MAAM,OAAO,MAAM,SAAS,OAAO,SAAS,OAAO,OAAO,OAAO,cAAc,OAAO,cAAc,OAAO,OAAO,OAAO,YAAY,OAAO,YAAY,gBAAgB,OAAO,gBAAgB,eAAe,OAAO,eAAe,kBAAkB,OAAO,kBAAkB,gBAAgB,OAAO,gBAAgB,cAAc;AAAG;AACthC,SAAS,wBAAwB,SAAsD;AAAE,SAAO,IAAI,kBAAkB,OAAO;AAAG;AAOvI,eAAsB,sBAAsB,SAA6E;AACvH,MAAI,CAACC,YAAW,QAAQ,WAAW,EAAG,OAAM,IAAI,MAAM,mCAAmC;AACzF,QAAM,cAAc,qBAAqB,QAAQ,WAAW;AAC5D,QAAM,cAAc,gBAAgB,WAAW;AAC/C,MAAI,QAAQ,wBAAwB,UAAa,CAACA,YAAW,QAAQ,mBAAmB,EAAG,OAAM,IAAI,MAAM,sCAAsC;AACjJ,QAAM,cAAc,QAAQ,sBAAsBC,MAAK,QAAQ,qBAAqB,WAAW,IAAI,sBAAsB,WAAW;AACpI,QAAM,QAAQ,IAAI,iBAAiBA,MAAK,aAAa,eAAe,CAAC;AACrE,QAAM,MAAM,WAAW;AACvB,SAAO,EAAE,aAAa,SAAS,wBAAwB,EAAE,IAAI,MAAM,YAAY,GAAG,eAAe,QAAQ,eAAe,YAAY,MAAM,CAAC,GAAG,OAAO,YAAY,MAAM,MAAM,EAAE;AACjL;",
4
+ "sourcesContent": ["import { createHash, randomUUID } from 'crypto';\nimport { isAbsolute, join } from 'path';\nimport { z } from 'zod';\n\nimport { rankCuratedLessonsHybrid } from '../extensions/mcp/hybrid-lesson-ranking.js';\nimport { applyPrivacyFilter } from '../core/privacy/index.js';\nimport { CanonicalMemoryAccessService } from '../core/operations/canonical-memory-access-service.js';\nimport { CanonicalMemoryInjectionService } from '../core/operations/canonical-memory-injection-service.js';\nimport { LessonRepository } from '../core/operations/lesson-repository.js';\nimport { writeGovernanceAuditEntrySync } from '../core/operations/governance-audit.js';\nimport type { MemoryEvent, MemoryLesson } from '../core/types.js';\nimport { sqliteAll, sqliteGet, sqliteRun, type SQLiteDatabase } from '../core/sqlite-wrapper.js';\nimport { SQLiteEventStore } from '../core/sqlite-event-store.js';\nimport { getProjectStoragePath, hashProjectPath, normalizeProjectPath } from '../core/registry/project-path.js';\n\n// Hosts must check this installed-artifact capability before suppressing native lessons.\nexport const LESSON_HOST_CAPABILITIES = Object.freeze({ version: 1, nativeLessonOwnerMarker: true });\n\nconst Identifier = z.string().trim().min(1).max(240);\nconst Hash = z.string().regex(/^[a-f0-9]{64}$/i, 'payloadHash must be a SHA-256 hex digest');\nconst CandidatePayload = z.object({\n name: Identifier,\n trigger: Identifier,\n steps: z.array(Identifier).min(1).max(20),\n confidence: z.number().min(0).max(1),\n sourceSessionIds: z.array(Identifier).max(100),\n sourceEventIds: z.array(Identifier).min(1).max(100),\n failureModes: z.array(Identifier).max(20).default([]),\n skillCandidate: z.boolean().default(false),\n scope: Identifier,\n validation: z.array(Identifier).min(1).max(20),\n reconsiderWhen: Identifier,\n validVersions: z.array(Identifier).max(20).optional()\n}).strict();\nconst BaseRequest = z.object({ version: z.number().int(), requestId: Identifier, binding: z.unknown() }).strict();\nconst MutationBase = BaseRequest.extend({ generation: z.number().int().nonnegative() }).strict();\nconst CandidateMutation = MutationBase.extend({\n candidateId: Identifier,\n expectedRevision: z.number().int().positive(),\n payloadHash: Hash\n}).strict();\n\nexport interface VerifiedLessonHostBinding {\n projectHash: string;\n actorId: string;\n userId: string;\n machineId: string;\n sessionId: string;\n generation: number;\n capabilities: readonly ('lesson.read' | 'lesson.review' | 'lesson.manage')[];\n /** Verified host lifecycle state; DTOs cannot assert normal completion. */\n normalEndSessionIds?: readonly string[];\n}\n\nexport interface LessonHostServiceOptions {\n db: SQLiteDatabase;\n verifyBinding(binding: unknown): Promise<VerifiedLessonHostBinding> | VerifiedLessonHostBinding;\n /** Existing canonical ingestion boundary, supplied by openLessonHostService. */\n eventStore?: Pick<SQLiteEventStore, 'importEvents' | 'getSessionEvents'>;\n /** Injectable only for deterministic deadline tests. */\n now?: () => number;\n}\n\nexport interface OpenLessonHostServiceOptions {\n /** Canonical host-resolved project path; never accept this from a renderer DTO. */\n projectPath: string;\n verifyBinding(binding: unknown): Promise<VerifiedLessonHostBinding> | VerifiedLessonHostBinding;\n /** Test-only isolated root. Production uses CML's canonical project store. */\n isolatedStorageRoot?: string;\n}\n\nexport interface OpenLessonHostServiceResult {\n projectHash: string;\n service: LessonHostService;\n close(): Promise<void>;\n}\n\ntype Candidate = z.output<typeof CandidatePayload>;\ntype CandidateStatus = 'pending' | 'reviewed' | 'accepted' | 'rejected' | 'expired';\ninterface CandidateRow {\n candidate_id: string; project_hash: string; evidence_key: string; payload_hash: string;\n payload_json: string; evidence_refs_json: string; status: CandidateStatus; revision: number;\n generation: number; expires_at: string | null; duplicate_lesson_ids_json: string; created_at: string; updated_at: string;\n}\ninterface TraceRow { trace_id: string; project_hash: string; session_id: string; actor_id: string; machine_id: string; turn_id: string; request_id: string; generation: number; lesson_ids_json: string; lesson_revisions_json: string; phase: string; outcome: string; created_at: string; }\n\nfunction stableJson(value: unknown): string {\n if (Array.isArray(value)) return `[${value.map(stableJson).join(',')}]`;\n if (value && typeof value === 'object') {\n return `{${Object.entries(value as Record<string, unknown>).sort(([a], [b]) => a.localeCompare(b)).map(([key, item]) => `${JSON.stringify(key)}:${stableJson(item)}`).join(',')}}`;\n }\n return JSON.stringify(value);\n}\nfunction requestFingerprint(value: unknown): string {\n const { binding: _binding, ...intent } = (value && typeof value === 'object' ? value : {}) as Record<string, unknown>;\n return createHash('sha256').update(stableJson(intent)).digest('hex');\n}\n\nexport function hashLessonCandidatePayload(payload: unknown): string {\n return createHash('sha256').update(stableJson(CandidatePayload.parse(payload))).digest('hex');\n}\n\nfunction parseJson<T>(value: string, fallback: T): T {\n try { return JSON.parse(value) as T; } catch { return fallback; }\n}\nfunction sameBinding(left: VerifiedLessonHostBinding, right: VerifiedLessonHostBinding): boolean {\n return left.projectHash === right.projectHash && left.actorId === right.actorId && left.machineId === right.machineId && left.sessionId === right.sessionId && left.generation === right.generation;\n}\n\nfunction candidateFromRow(row: CandidateRow) {\n return {\n candidateId: row.candidate_id, evidenceKey: row.evidence_key, payloadHash: row.payload_hash,\n status: row.status, revision: row.revision, generation: row.generation,\n expiresAt: row.expires_at, createdAt: row.created_at, updatedAt: row.updated_at,\n evidenceRefs: parseJson<string[]>(row.evidence_refs_json, []), duplicateLessonIds: parseJson<string[]>(row.duplicate_lesson_ids_json, []), candidate: parseJson<Candidate>(row.payload_json, {} as Candidate)\n };\n}\n\nfunction assertCandidateSafe(candidate: Candidate): void {\n const text = [candidate.name, candidate.trigger, candidate.scope, candidate.reconsiderWhen, ...candidate.steps, ...candidate.validation, ...candidate.failureModes, ...(candidate.validVersions ?? [])].join('\\n');\n const privacy = applyPrivacyFilter(text, { excludePatterns: [], anonymize: false, privateTags: { enabled: true, marker: '[PRIVATE]', preserveLineCount: false, supportedFormats: ['xml'] } });\n const environmentSecret = /\\b(?:export\\s+)?[A-Z][A-Z0-9_]*(?:TOKEN|SECRET|PASSWORD|API_KEY)\\s*=\\s*(?!\\$[A-Z_])[\\S]+/;\n const credentialRule = /\\b(?:store|save|persist|remember|reuse|repeat)\\b.{0,80}\\b(?:credential|password|secret|api[ -]?key|access token)\\b|\\b(?:credential|password|secret|api[ -]?key|access token)\\b.{0,80}\\b(?:store|save|persist|remember|reuse|repeat)\\b/i;\n if (privacy.metadata.hasPrivateTags || privacy.metadata.hasUnmatchedTags || privacy.metadata.patternMatchCount > 0 || environmentSecret.test(text) || credentialRule.test(text) || /ignore (all )?previous instructions|system prompt|developer message/i.test(text)) {\n throw new Error('candidate contains private, credential-like, or forbidden instruction content');\n }\n}\n\nexport class LessonHostService {\n constructor(private readonly options: LessonHostServiceOptions) {}\n\n async recall(input: unknown) {\n const request = BaseRequest.extend({ turnId: Identifier, query: z.string().trim().min(1).max(8_000), limit: z.number().int().min(1).max(3).default(3) }).strict().parse(input);\n if (request.version !== 1) return { outcome: 'unsupported_version' as const };\n const binding = await this.readBinding(request.binding, 'lesson.read');\n const deadline = this.now() + 900;\n const repo = new LessonRepository(this.options.db);\n const eligible: Array<{ lesson: MemoryLesson; injectionMode: 'direct' | 'summary' | 'reference' }> = [];\n for (let offset = 0; ; offset += 100) {\n if (this.now() >= deadline) return { outcome: 'timeout' as const, lessonIds: [], lessons: [] };\n const page = await repo.list({ projectHash: binding.projectHash, limit: 100, offset });\n if (!page.length) break;\n const allowed = new CanonicalMemoryInjectionService(this.options.db).select({ projectHash: binding.projectHash, actorId: binding.actorId, lane: 'prompt', candidates: page.filter((lesson) => lesson.recallEnabled).map((value) => ({ canonicalType: 'lesson' as const, canonicalId: value.lessonId, value })) }).items;\n for (const item of allowed) eligible.push({ lesson: item.value, injectionMode: item.injectionMode });\n if (this.now() >= deadline) return { outcome: 'timeout' as const, lessonIds: [], lessons: [] };\n if (page.length < 100) break;\n await new Promise<void>((resolve) => setImmediate(resolve));\n }\n if (this.now() >= deadline) return { outcome: 'timeout' as const, lessonIds: [], lessons: [] };\n const selected = await rankCuratedLessonsHybrid(eligible.map(({ lesson }) => lesson), request.query, request.limit);\n const lessons = selected.map((lesson) => ({ lesson, injectionMode: eligible.find((item) => item.lesson.lessonId === lesson.lessonId)!.injectionMode }));\n if (this.now() >= deadline) return { outcome: 'timeout' as const, lessonIds: [], lessons: [] };\n const finalBinding = await this.readBinding(request.binding, 'lesson.read');\n if (!sameBinding(binding, finalBinding)) throw new Error('binding changed during recall');\n if (this.now() >= deadline) return { outcome: 'timeout' as const, lessonIds: [], lessons: [] };\n if (!this.validRecallSelection(lessons, finalBinding)) return { outcome: 'no_match' as const, lessonIds: [], lessons: [] };\n const traceId = randomUUID();\n const response = { outcome: lessons.length ? 'selected' as const : 'no_match' as const, traceId, lessonIds: lessons.map(({ lesson }) => lesson.lessonId), lessons: lessons.map(({ lesson, injectionMode }) => lessonBody(lesson, injectionMode)) };\n const fingerprint = requestFingerprint({ version: request.version, requestId: request.requestId, turnId: request.turnId, query: request.query, limit: request.limit });\n return this.options.db.transaction(() => { const replay = this.idempotent(request.requestId, finalBinding, 'recall', fingerprint); if (replay) return this.validRecallReplay(replay, finalBinding) ? replay : { outcome: 'no_match' as const, lessonIds: [], lessons: [] }; if (!this.validRecallSelection(lessons, finalBinding)) return { outcome: 'no_match' as const, lessonIds: [], lessons: [] }; this.writeTrace({ traceId, requestId: request.requestId, binding: finalBinding, turnId: request.turnId, phase: 'selected', outcome: response.outcome, lessons: lessons.map(({ lesson }) => lesson) }); this.remember(request.requestId, finalBinding, 'recall', fingerprint, response); return response; })();\n }\n\n async get(input: unknown) {\n const request = BaseRequest.extend({ lessonId: Identifier }).strict().parse(input);\n if (request.version !== 1) return { outcome: 'unsupported_version' as const };\n const binding = await this.readBinding(request.binding, 'lesson.read');\n const lesson = new LessonRepository(this.options.db).get(request.lessonId);\n if (!lesson || lesson.projectHash !== binding.projectHash || !this.canReadLesson(binding, lesson.lessonId)) return { outcome: 'not_found' as const };\n const response = { outcome: 'found' as const, lesson: lessonBody(lesson) };\n const fingerprint = requestFingerprint(request); return this.options.db.transaction(() => { const replay = this.idempotent(request.requestId, binding, 'get', fingerprint); if (replay) { const cached = replay as { lesson?: { lessonId?: string; revision?: number } }; return cached.lesson?.lessonId === lesson.lessonId && cached.lesson.revision === lesson.revision ? replay : { outcome: 'not_found' as const }; } this.writeTrace({ traceId: randomUUID(), requestId: request.requestId, binding, phase: 'read', outcome: 'read', lessons: [lesson] }); this.remember(request.requestId, binding, 'get', fingerprint, response); return response; })();\n }\n\n async recordRead(input: unknown) {\n const request = BaseRequest.extend({ lessonId: Identifier }).strict().parse(input);\n if (request.version !== 1) return { outcome: 'unsupported_version' as const };\n const binding = await this.readBinding(request.binding, 'lesson.read');\n const lesson = new LessonRepository(this.options.db).get(request.lessonId);\n if (!lesson || lesson.projectHash !== binding.projectHash || !this.canReadLesson(binding, lesson.lessonId)) return { outcome: 'not_found' as const };\n const traceId = randomUUID(); const response = { outcome: 'read' as const, traceId };\n const fingerprint = requestFingerprint(request); return this.options.db.transaction(() => { const replay = this.idempotent(request.requestId, binding, 'read', fingerprint); if (replay) return replay; this.writeTrace({ traceId, requestId: request.requestId, binding, phase: 'read', outcome: 'read', lessons: [lesson] }); this.remember(request.requestId, binding, 'read', fingerprint, response); return response; })();\n }\n\n async ackDelivery(input: unknown) {\n const request = BaseRequest.extend({ turnId: Identifier, traceId: Identifier, lessonIds: z.array(Identifier).max(3), lessonRevisions: z.array(z.object({ lessonId: Identifier, revision: z.number().int().positive() }).strict()).max(3) }).strict().parse(input);\n if (request.version !== 1) return { outcome: 'unsupported_version' as const };\n const binding = await this.readBinding(request.binding, 'lesson.read');\n const selected = sqliteGet<TraceRow>(this.options.db, `SELECT * FROM lesson_host_traces WHERE trace_id = ?`, [request.traceId]);\n const revisions = request.lessonRevisions.map(({ lessonId, revision }) => ({ lessonId, revision }));\n const current = revisions.every(({ lessonId, revision }) => { const lesson = new LessonRepository(this.options.db).get(lessonId); return lesson?.projectHash === binding.projectHash && lesson.revision === revision; });\n if (!selected || selected.project_hash !== binding.projectHash || selected.session_id !== binding.sessionId || selected.actor_id !== binding.actorId || selected.machine_id !== binding.machineId || selected.generation !== binding.generation || selected.turn_id !== request.turnId || selected.phase !== 'selected' || JSON.stringify(parseJson<string[]>(selected.lesson_ids_json, [])) !== JSON.stringify(request.lessonIds) || JSON.stringify(parseJson(selected.lesson_revisions_json, [])) !== JSON.stringify(revisions) || !current) return { outcome: 'invalid_ack' as const };\n const response = { outcome: 'delivered' as const, traceId: request.traceId };\n const fingerprint = requestFingerprint(request); return this.options.db.transaction(() => { const replay = this.idempotent(request.requestId, binding, 'delivered', fingerprint); if (replay) return replay; this.writeTrace({ traceId: randomUUID(), requestId: request.requestId, binding, turnId: request.turnId, phase: 'delivered', outcome: 'delivered', lessons: revisions.map(({ lessonId }) => new LessonRepository(this.options.db).get(lessonId)!) }); this.remember(request.requestId, binding, 'delivered', fingerprint, response); return response; })();\n }\n\n async enqueueCandidate(input: unknown) {\n const request = MutationBase.extend({ evidenceKey: Identifier, payloadHash: Hash.optional(), candidate: CandidatePayload, expiresAt: z.string().datetime().optional() }).strict().parse(input);\n if (request.version !== 1) return { outcome: 'unsupported_version' as const };\n const binding = await this.writeBinding(request.binding, request.generation, 'lesson.review');\n const candidate = CandidatePayload.parse(request.candidate); assertCandidateSafe(candidate); this.assertSourceEvents(binding.projectHash, candidate.sourceEventIds, candidate.sourceSessionIds);\n const computedHash = hashLessonCandidatePayload(candidate);\n if (request.payloadHash && request.payloadHash !== computedHash) throw new Error('payloadHash does not match canonical candidate payload');\n const fingerprint = requestFingerprint({ ...request, payloadHash: computedHash });\n return this.options.db.transaction(() => {\n const replay = this.idempotent(request.requestId, binding, 'enqueue', fingerprint); if (replay) return replay;\n this.expireCandidates(binding.projectHash);\n const existing = sqliteGet<CandidateRow>(this.options.db, `SELECT * FROM lesson_review_candidates WHERE project_hash = ? AND evidence_key = ?`, [binding.projectHash, request.evidenceKey]);\n if (!existing && sqliteGet<{ count: number }>(this.options.db, `SELECT COUNT(*) AS count FROM lesson_review_candidates WHERE project_hash=? AND status IN ('pending','reviewed')`, [binding.projectHash])!.count >= 20) throw new Error('pending candidate cap reached');\n const result = existing ? candidateFromRow(existing) : this.insertCandidate(binding, request.evidenceKey, computedHash, candidate, request.expiresAt);\n const response = { outcome: result.status, ...result }; this.remember(request.requestId, binding, 'enqueue', fingerprint, response); return response;\n })();\n }\n\n async appendNormalEndEvidence(input: unknown) {\n const request = MutationBase.extend({ evidenceKey: Identifier, sessionId: Identifier, content: z.string().trim().min(1).max(8_000), occurredAt: z.string().datetime().optional() }).strict().parse(input);\n if (request.version !== 1) return { outcome: 'unsupported_version' as const };\n const binding = await this.writeBinding(request.binding, request.generation, 'lesson.review');\n if (!this.options.eventStore || request.sessionId !== binding.sessionId || !binding.normalEndSessionIds?.includes(request.sessionId)) throw new Error('verified normal session completion is required');\n const filtered = applyPrivacyFilter(request.content, { excludePatterns: [], anonymize: false, privateTags: { enabled: true, marker: '[PRIVATE]', preserveLineCount: false, supportedFormats: ['xml'] } });\n if (filtered.metadata.hasPrivateTags || filtered.metadata.hasUnmatchedTags || /\\[PRIVATE\\]/.test(filtered.content) || Buffer.byteLength(filtered.content, 'utf8') > 8_000 || filtered.content.length === 0) throw new Error('evidence is not safely appendable');\n const fingerprint = requestFingerprint({ ...request, content: filtered.content });\n const replay = this.idempotent(request.requestId, binding, 'append-normal-end-evidence', fingerprint); if (replay) return replay;\n const contentHash = createHash('sha256').update(filtered.content).digest('hex');\n const prior = (await this.options.eventStore.getSessionEvents(request.sessionId)).find((event) => (event.metadata as { evidenceKey?: string; contentHash?: string } | undefined)?.evidenceKey === request.evidenceKey);\n if (prior) {\n if ((prior.metadata as { contentHash?: string } | undefined)?.contentHash !== contentHash || (prior.metadata as { scope?: { project?: { hash?: string } } } | undefined)?.scope?.project?.hash !== binding.projectHash) throw new Error('evidenceKey payload conflict');\n const response = { outcome: 'persisted' as const, eventId: prior.id, evidenceKey: request.evidenceKey, redacted: filtered.content !== request.content };\n this.options.db.transaction(() => this.remember(request.requestId, binding, 'append-normal-end-evidence', fingerprint, response))(); return response;\n }\n const finalBinding = await this.writeBinding(request.binding, request.generation, 'lesson.review');\n const eventId = randomUUID();\n const event: MemoryEvent = { id: eventId, eventType: 'tool_observation', sessionId: request.sessionId, timestamp: request.occurredAt ? new Date(request.occurredAt) : new Date(), content: filtered.content, canonicalKey: `host-normal-end:${finalBinding.projectHash}:${request.evidenceKey}`, dedupeKey: `host-normal-end:${finalBinding.projectHash}:${request.evidenceKey}`, metadata: { scope: { project: { hash: finalBinding.projectHash } }, source: 'lesson-host-normal-end', evidenceKey: request.evidenceKey, contentHash } };\n const persisted = await this.options.eventStore.importEvents([event]);\n if (persisted.inserted !== 1) throw new Error('evidenceKey already exists without a recoverable host idempotency record');\n const response = { outcome: 'persisted' as const, eventId, evidenceKey: request.evidenceKey, redacted: filtered.content !== request.content };\n this.options.db.transaction(() => { this.remember(request.requestId, binding, 'append-normal-end-evidence', fingerprint, response); })();\n return response;\n }\n\n async markReviewed(input: unknown) { return this.transition(input, 'reviewed', 'lesson.review'); }\n async rejectCandidate(input: unknown) { return this.transition(input, 'rejected', 'lesson.manage'); }\n\n async approveCandidate(input: unknown) {\n const request = CandidateMutation.parse(input);\n if (request.version !== 1) return { outcome: 'unsupported_version' as const };\n await this.writeBinding(request.binding, request.generation, 'lesson.manage');\n const fingerprint = requestFingerprint(request);\n // The final verifier call is immediately followed by the synchronous SQLite transaction.\n const finalBinding = await this.writeBinding(request.binding, request.generation, 'lesson.manage');\n const transaction = this.options.db.transaction(() => {\n const replay = this.idempotent(request.requestId, finalBinding, 'approve', fingerprint); if (replay) return replay;\n const row = this.requireCandidate(request.candidateId, finalBinding, request.expectedRevision, request.payloadHash, 'reviewed', false);\n const candidate = CandidatePayload.parse(parseJson(row.payload_json, {})); assertCandidateSafe(candidate); this.assertSourceEvents(finalBinding.projectHash, candidate.sourceEventIds, candidate.sourceSessionIds);\n const existing = sqliteGet<{ lesson_id: string; revision: number; recall_enabled: number }>(this.options.db, `SELECT lesson_id, revision, recall_enabled FROM memory_lessons WHERE project_hash = ? AND name = ?`, [finalBinding.projectHash, candidate.name]);\n if (existing) { const error = new Error('existing lesson requires an explicit merge proposal and lesson revision CAS') as Error & { code?: string }; error.code = 'merge_required'; throw error; }\n const now = new Date().toISOString(); const lessonId = randomUUID();\n sqliteRun(this.options.db, `INSERT INTO memory_lessons (lesson_id, project_hash, name, trigger, steps_json, confidence, source_session_ids, source_event_ids, failure_modes_json, skill_candidate, source_class, revision, recall_enabled, scope, validation_json, reconsider_when, valid_versions_json, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'curated', 1, 1, ?, ?, ?, ?, ?, ?)`, [lessonId, finalBinding.projectHash, candidate.name, candidate.trigger, JSON.stringify(candidate.steps), candidate.confidence, JSON.stringify(candidate.sourceSessionIds), JSON.stringify(candidate.sourceEventIds), JSON.stringify(candidate.failureModes), candidate.skillCandidate ? 1 : 0, candidate.scope, JSON.stringify(candidate.validation), candidate.reconsiderWhen, JSON.stringify(candidate.validVersions ?? []), now, now]);\n writeGovernanceAuditEntrySync(this.options.db, { operation: 'lesson_promote', actor: finalBinding.actorId, projectHash: finalBinding.projectHash, targetType: 'lesson', targetId: lessonId, afterJson: { lessonId, name: candidate.name, trigger: candidate.trigger, steps: candidate.steps, sourceClass: 'curated' }, sourceEventIds: candidate.sourceEventIds });\n const changed = sqliteRun(this.options.db, `UPDATE lesson_review_candidates SET status='accepted', revision=revision+1, updated_at=? WHERE candidate_id=? AND project_hash=? AND revision=? AND payload_hash=? AND status='reviewed'`, [now, row.candidate_id, finalBinding.projectHash, request.expectedRevision, request.payloadHash]);\n if (changed.changes !== 1) throw new Error('candidate changed before approval');\n const lesson = new LessonRepository(this.options.db).get(lessonId)!;\n const result = { outcome: 'accepted' as const, candidateId: row.candidate_id, lessonId, lessonRevision: lesson.revision }; this.remember(request.requestId, finalBinding, 'approve', fingerprint, result); return result;\n });\n return transaction();\n }\n\n async setRecallEnabled(input: unknown) {\n const request = MutationBase.extend({ lessonId: Identifier, expectedRevision: z.number().int().positive(), enabled: z.boolean() }).strict().parse(input);\n if (request.version !== 1) return { outcome: 'unsupported_version' as const };\n await this.writeBinding(request.binding, request.generation, 'lesson.manage');\n const binding = await this.writeBinding(request.binding, request.generation, 'lesson.manage');\n const fingerprint = requestFingerprint(request);\n return this.options.db.transaction(() => {\n const replay = this.idempotent(request.requestId, binding, 'set-recall', fingerprint); if (replay) return replay;\n const result = new LessonRepository(this.options.db).setRecallEnabled({ lessonId: request.lessonId, projectHash: binding.projectHash, expectedRevision: request.expectedRevision, enabled: request.enabled });\n if (!result) throw new Error('lesson revision conflict or lesson not found');\n const response = { outcome: 'updated' as const, lessonId: result.lessonId, revision: result.revision, recallEnabled: result.recallEnabled };\n this.remember(request.requestId, binding, 'set-recall', fingerprint, response); return response;\n })();\n }\n\n async listCandidates(input: unknown) {\n const request = BaseRequest.extend({ limit: z.number().int().min(1).max(100).default(100), offset: z.number().int().nonnegative().default(0) }).strict().parse(input); if (request.version !== 1) return { outcome: 'unsupported_version' as const };\n const binding = await this.readBinding(request.binding, 'lesson.manage'); this.expireCandidates(binding.projectHash);\n const rows = sqliteAll<CandidateRow>(this.options.db, `SELECT * FROM lesson_review_candidates WHERE project_hash = ? ORDER BY updated_at DESC LIMIT ? OFFSET ?`, [binding.projectHash, request.limit + 1, request.offset]);\n return { outcome: 'ok' as const, candidates: rows.slice(0, request.limit).map(candidateFromRow), nextOffset: rows.length > request.limit ? request.offset + request.limit : null };\n }\n\n async reviewStatus(input: unknown) {\n const request = BaseRequest.extend({ candidateId: Identifier }).strict().parse(input); if (request.version !== 1) return { outcome: 'unsupported_version' as const };\n const binding = await this.readBinding(request.binding, 'lesson.manage'); this.expireCandidates(binding.projectHash);\n const candidate = sqliteGet<CandidateRow>(this.options.db, `SELECT * FROM lesson_review_candidates WHERE candidate_id=? AND project_hash=?`, [request.candidateId, binding.projectHash]);\n return candidate ? { outcome: 'found' as const, candidate: candidateFromRow(candidate) } : { outcome: 'not_found' as const };\n }\n\n async listLessons(input: unknown) {\n const request = BaseRequest.extend({ limit: z.number().int().min(1).max(100).default(100), offset: z.number().int().nonnegative().default(0) }).strict().parse(input); if (request.version !== 1) return { outcome: 'unsupported_version' as const };\n const binding = await this.readBinding(request.binding, 'lesson.manage'); const lessons = await new LessonRepository(this.options.db).list({ projectHash: binding.projectHash, limit: request.limit + 1, offset: request.offset });\n return { outcome: 'ok' as const, lessons: lessons.slice(0, request.limit).map((lesson) => { const traces = sqliteAll<{ phase: string; created_at: string }>(this.options.db, `SELECT t.phase, t.created_at FROM lesson_host_traces t JOIN json_each(t.lesson_ids_json) ids ON ids.value=? WHERE t.project_hash=? ORDER BY t.created_at DESC`, [lesson.lessonId, binding.projectHash]); const latest = (phase: string) => traces.find((trace) => trace.phase === phase)?.created_at ?? null; return { lessonId: lesson.lessonId, name: lesson.name, trigger: lesson.trigger, steps: lesson.steps, failureModes: lesson.failureModes, scope: lesson.scope, validation: lesson.validation, reconsiderWhen: lesson.reconsiderWhen, validVersions: lesson.validVersions, revision: lesson.revision, recallEnabled: lesson.recallEnabled, sourceSessionIds: lesson.sourceSessionIds, sourceEventIds: lesson.sourceEventIds, createdAt: lesson.createdAt.toISOString(), updatedAt: lesson.updatedAt.toISOString(), lastSelectedAt: latest('selected'), lastDeliveredAt: latest('delivered'), lastReadAt: latest('read') }; }), nextOffset: lessons.length > request.limit ? request.offset + request.limit : null };\n }\n\n async listTraces(input: unknown) {\n const request = BaseRequest.extend({ limit: z.number().int().min(1).max(100).default(100), offset: z.number().int().nonnegative().default(0) }).strict().parse(input); if (request.version !== 1) return { outcome: 'unsupported_version' as const };\n const binding = await this.readBinding(request.binding, 'lesson.manage');\n const rows = sqliteAll<TraceRow>(this.options.db, `SELECT trace_id, project_hash, session_id, actor_id, machine_id, turn_id, request_id, generation, lesson_ids_json, lesson_revisions_json, phase, outcome, created_at FROM lesson_host_traces WHERE project_hash=? ORDER BY created_at DESC LIMIT ? OFFSET ?`, [binding.projectHash, request.limit + 1, request.offset]);\n return { outcome: 'ok' as const, traces: rows.slice(0, request.limit).map((row) => ({ traceId: row.trace_id, requestId: row.request_id, sessionId: row.session_id, actorId: row.actor_id, machineId: row.machine_id, turnId: row.turn_id, generation: row.generation, phase: row.phase, outcome: row.outcome, lessonIds: parseJson<string[]>(row.lesson_ids_json, []), lessonRevisions: parseJson<Array<{ lessonId: string; revision: number }>>(row.lesson_revisions_json, []), createdAt: row.created_at })), nextOffset: rows.length > request.limit ? request.offset + request.limit : null };\n }\n\n private async transition(input: unknown, target: 'reviewed' | 'rejected', capability: 'lesson.review' | 'lesson.manage') {\n const request = CandidateMutation.parse(input); if (request.version !== 1) return { outcome: 'unsupported_version' as const };\n const binding = await this.writeBinding(request.binding, request.generation, capability); const fingerprint = requestFingerprint(request);\n const current = target === 'reviewed' ? 'pending' : 'reviewed'; const now = new Date().toISOString(); await this.writeBinding(request.binding, request.generation, capability);\n return this.options.db.transaction(() => {\n const replay = this.idempotent(request.requestId, binding, target, fingerprint); if (replay) return replay;\n const requireGeneration = target === 'reviewed';\n this.requireCandidate(request.candidateId, binding, request.expectedRevision, request.payloadHash, current, requireGeneration);\n const changed = requireGeneration\n ? sqliteRun(this.options.db, `UPDATE lesson_review_candidates SET status=?, revision=revision+1, updated_at=? WHERE candidate_id=? AND project_hash=? AND revision=? AND payload_hash=? AND generation=? AND status=?`, [target, now, request.candidateId, binding.projectHash, request.expectedRevision, request.payloadHash, binding.generation, current])\n : sqliteRun(this.options.db, `UPDATE lesson_review_candidates SET status=?, revision=revision+1, updated_at=? WHERE candidate_id=? AND project_hash=? AND revision=? AND payload_hash=? AND status=?`, [target, now, request.candidateId, binding.projectHash, request.expectedRevision, request.payloadHash, current]);\n if (changed.changes !== 1) throw new Error('candidate revision, generation, or status conflict');\n const result = candidateFromRow(sqliteGet<CandidateRow>(this.options.db, `SELECT * FROM lesson_review_candidates WHERE candidate_id = ?`, [request.candidateId])!); const response = { outcome: target, ...result }; this.remember(request.requestId, binding, target, fingerprint, response); return response;\n })();\n }\n\n private async readBinding(token: unknown, capability: VerifiedLessonHostBinding['capabilities'][number]) { const binding = await this.options.verifyBinding(token); this.assertBinding(binding, capability); return binding; }\n private async writeBinding(token: unknown, generation: number, capability: VerifiedLessonHostBinding['capabilities'][number]) { const binding = await this.readBinding(token, capability); if (binding.generation !== generation) throw new Error('binding generation mismatch'); return binding; }\n private assertBinding(binding: VerifiedLessonHostBinding, capability: string) { if (!Identifier.safeParse(binding.projectHash).success || !Identifier.safeParse(binding.actorId).success || !binding.capabilities.includes(capability as never)) throw new Error('untrusted or unauthorized host binding'); }\n private canReadLesson(binding: VerifiedLessonHostBinding, lessonId: string): boolean { try { return new CanonicalMemoryAccessService(this.options.db).check({ projectHash: binding.projectHash, canonicalType: 'lesson', canonicalId: lessonId, requesterActorId: binding.actorId, permission: 'read' }).allowed; } catch { return false; } }\n private assertSourceEvents(projectHash: string, ids: string[], sourceSessionIds?: string[]) { const rows = sqliteAll<{ id: string; session_id: string; metadata: string }>(this.options.db, `SELECT id, session_id, metadata FROM events WHERE id IN (${ids.map(() => '?').join(',')})`, ids); if (rows.length !== ids.length) throw new Error('source event refs are unavailable'); for (const row of rows) { const metadata = parseJson<Record<string, unknown>>(row.metadata, {}); if ((metadata.scope as { project?: { hash?: string } } | undefined)?.project?.hash !== projectHash) throw new Error('source event project mismatch'); } if (sourceSessionIds) { const expected = new Set(rows.map((row) => row.session_id)); if (sourceSessionIds.length !== expected.size || sourceSessionIds.some((id) => !expected.has(id))) throw new Error('source session refs do not match source events'); } }\n private insertCandidate(binding: VerifiedLessonHostBinding, evidenceKey: string, payloadHash: string, candidate: Candidate, expiresAt?: string) { const candidateId = randomUUID(); const now = new Date().toISOString(); const maxExpiry = new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(); const expires = expiresAt && expiresAt < maxExpiry ? expiresAt : maxExpiry; const duplicateLessonIds = this.findDuplicateLessonIds(binding.projectHash, candidate); sqliteRun(this.options.db, `INSERT INTO lesson_review_candidates (candidate_id, project_hash, evidence_key, payload_hash, payload_json, evidence_refs_json, duplicate_lesson_ids_json, status, revision, generation, expires_at, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, 'pending', 1, ?, ?, ?, ?)`, [candidateId, binding.projectHash, evidenceKey, payloadHash, stableJson(candidate), JSON.stringify(candidate.sourceEventIds), JSON.stringify(duplicateLessonIds), binding.generation, expires, now, now]); return candidateFromRow(sqliteGet<CandidateRow>(this.options.db, `SELECT * FROM lesson_review_candidates WHERE candidate_id = ?`, [candidateId])!); }\n private requireCandidate(id: string, binding: VerifiedLessonHostBinding, revision: number, hash: string, status: CandidateStatus, requireGeneration: boolean) { const row = sqliteGet<CandidateRow>(this.options.db, `SELECT * FROM lesson_review_candidates WHERE candidate_id = ?`, [id]); if (!row || row.project_hash !== binding.projectHash || row.revision !== revision || row.payload_hash !== hash || row.status !== status || (requireGeneration && row.generation !== binding.generation)) throw new Error('candidate revision, generation, payload, or status conflict'); if (row.expires_at && row.expires_at <= new Date().toISOString()) { sqliteRun(this.options.db, `UPDATE lesson_review_candidates SET status='expired', revision=revision+1, updated_at=? WHERE candidate_id=?`, [new Date().toISOString(), id]); throw new Error('candidate has expired'); } return row; }\n private now(): number { return this.options.now?.() ?? Date.now(); }\n private validRecallReplay(replay: unknown, binding: VerifiedLessonHostBinding): boolean { const body = replay as { lessons?: Array<{ lessonId?: string; revision?: number; injectionMode?: 'direct' | 'summary' | 'reference' }> }; if (!Array.isArray(body.lessons)) return false; const current = body.lessons.map((item) => typeof item.lessonId === 'string' ? new LessonRepository(this.options.db).get(item.lessonId) : undefined); if (current.some((lesson, index) => !lesson || lesson.revision !== body.lessons![index]!.revision)) return false; return this.validRecallSelection(current.map((lesson, index) => ({ lesson: lesson!, injectionMode: body.lessons![index]!.injectionMode ?? 'direct' })), binding); }\n private validRecallSelection(selection: Array<{ lesson: MemoryLesson; injectionMode: 'direct' | 'summary' | 'reference' }>, binding: VerifiedLessonHostBinding): boolean { const current = selection.map(({ lesson }) => new LessonRepository(this.options.db).get(lesson.lessonId)); if (current.some((lesson, index) => !lesson || lesson.projectHash !== binding.projectHash || lesson.revision !== selection[index]!.lesson.revision || !lesson.recallEnabled || !this.canReadLesson(binding, lesson.lessonId))) return false; const allowed = new CanonicalMemoryInjectionService(this.options.db).select({ projectHash: binding.projectHash, actorId: binding.actorId, lane: 'prompt', candidates: current.map((lesson) => ({ canonicalType: 'lesson' as const, canonicalId: lesson!.lessonId, value: lesson! })) }).items; return allowed.length === selection.length && selection.every(({ lesson, injectionMode }) => allowed.some((item) => item.value.lessonId === lesson.lessonId && item.injectionMode === injectionMode)); }\n private findDuplicateLessonIds(projectHash: string, candidate: Candidate): string[] { const terms = new Set(`${candidate.name} ${candidate.trigger}`.toLowerCase().match(/[a-z0-9\uAC00-\uD7A3]{2,}/g) ?? []); return sqliteAll<{ lesson_id: string; name: string; trigger: string }>(this.options.db, `SELECT lesson_id, name, trigger FROM memory_lessons WHERE project_hash=?`, [projectHash]).filter((lesson) => { const other = new Set(`${lesson.name} ${lesson.trigger}`.toLowerCase().match(/[a-z0-9\uAC00-\uD7A3]{2,}/g) ?? []); let overlap = 0; for (const term of terms) if (other.has(term)) overlap += 1; return lesson.name === candidate.name || overlap >= 2 && overlap / Math.max(terms.size, other.size) >= 0.5; }).map((lesson) => lesson.lesson_id); }\n private expireCandidates(projectHash: string) { sqliteRun(this.options.db, `UPDATE lesson_review_candidates SET status='expired', revision=revision+1, updated_at=? WHERE project_hash=? AND status IN ('pending','reviewed') AND expires_at IS NOT NULL AND expires_at <= ?`, [new Date().toISOString(), projectHash, new Date().toISOString()]); }\n private writeTrace(input: { traceId: string; requestId: string; binding: VerifiedLessonHostBinding; turnId?: string; phase: string; outcome: string; lessons: MemoryLesson[] }) { sqliteRun(this.options.db, `INSERT INTO lesson_host_traces (trace_id, project_hash, session_id, actor_id, machine_id, generation, turn_id, request_id, phase, outcome, lesson_ids_json, lesson_revisions_json, query_text, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?)`, [input.traceId, input.binding.projectHash, input.binding.sessionId, input.binding.actorId, input.binding.machineId, input.binding.generation, input.turnId ?? null, input.requestId, input.phase, input.outcome, JSON.stringify(input.lessons.map((lesson) => lesson.lessonId)), JSON.stringify(input.lessons.map((lesson) => ({ lessonId: lesson.lessonId, revision: lesson.revision }))), new Date().toISOString()]); }\n private idempotent(requestId: string, binding: VerifiedLessonHostBinding, operation: string, fingerprint: string): unknown | null { const row = sqliteGet<{ operation: string; fingerprint: string; result_json: string }>(this.options.db, `SELECT operation, fingerprint, result_json FROM lesson_host_idempotency WHERE project_hash=? AND actor_id=? AND request_id=?`, [binding.projectHash, binding.actorId, requestId]); if (!row) return null; if (row.operation !== operation || row.fingerprint !== fingerprint) throw new Error('requestId payload conflict'); return parseJson(row.result_json, null); }\n private remember(requestId: string, binding: VerifiedLessonHostBinding, operation: string, fingerprint: string, result: unknown) { sqliteRun(this.options.db, `INSERT INTO lesson_host_idempotency (project_hash, actor_id, request_id, operation, fingerprint, result_json, created_at) VALUES (?, ?, ?, ?, ?, ?, ?)`, [binding.projectHash, binding.actorId, requestId, operation, fingerprint, JSON.stringify(result), new Date().toISOString()]); }\n}\n\nfunction lessonBody(lesson: MemoryLesson, injectionMode: 'direct' | 'summary' | 'reference' = 'direct') { if (injectionMode === 'reference') return { lessonId: lesson.lessonId, revision: lesson.revision, name: lesson.name, injectionMode }; if (injectionMode === 'summary') return { lessonId: lesson.lessonId, revision: lesson.revision, name: lesson.name, trigger: lesson.trigger, steps: lesson.steps.slice(0, 2), scope: lesson.scope, validation: lesson.validation, reconsiderWhen: lesson.reconsiderWhen, validVersions: lesson.validVersions, truncated: lesson.steps.length > 2 || lesson.failureModes.length > 0, detailReference: 'mem-lesson-get', injectionMode }; return { lessonId: lesson.lessonId, revision: lesson.revision, name: lesson.name, trigger: lesson.trigger, steps: lesson.steps, failureModes: lesson.failureModes, scope: lesson.scope, validation: lesson.validation, reconsiderWhen: lesson.reconsiderWhen, validVersions: lesson.validVersions, sourceSessionIds: lesson.sourceSessionIds, sourceEventIds: lesson.sourceEventIds, injectionMode }; }\nexport function createLessonHostService(options: LessonHostServiceOptions): LessonHostService { return new LessonHostService(options); }\n\n/**\n * Stable host-only opening boundary. Desktop/Happy supplies the canonical\n * project path after its own IPC/auth checks; renderer/model DTOs never open a\n * store. The optional isolated root exists solely for fixture stores.\n */\nexport async function openLessonHostService(options: OpenLessonHostServiceOptions): Promise<OpenLessonHostServiceResult> {\n if (!isAbsolute(options.projectPath)) throw new Error('host projectPath must be absolute');\n const projectPath = normalizeProjectPath(options.projectPath);\n const projectHash = hashProjectPath(projectPath);\n if (options.isolatedStorageRoot !== undefined && !isAbsolute(options.isolatedStorageRoot)) throw new Error('isolatedStorageRoot must be absolute');\n const storagePath = options.isolatedStorageRoot ? join(options.isolatedStorageRoot, projectHash) : getProjectStoragePath(projectPath);\n const store = new SQLiteEventStore(join(storagePath, 'events.sqlite'));\n await store.initialize();\n return { projectHash, service: createLessonHostService({ db: store.getDatabase(), verifyBinding: options.verifyBinding, eventStore: store }), close: async () => store.close() };\n}\n", "/**\n * Local Embedding Generator using @huggingface/transformers\n * AXIOMMIND Principle 7: Standard JSON format for vectors\n */\n\nimport { existsSync, readFileSync } from 'node:fs';\nimport { createRequire as createNodeRequire } from 'node:module';\nimport { dirname as pathDirname, join, parse } from 'node:path';\nimport { fileURLToPath as urlToFilePath, pathToFileURL } from 'node:url';\nimport {\n getRuntimeResourceTelemetry,\n opaqueBackendId,\n type RuntimeModelReleaseReason\n} from '../../core/runtime-resource-telemetry.js';\n\nexport interface EmbeddingResult {\n vector: number[];\n model: string;\n dimensions: number;\n}\n\ntype FeatureExtractionPipelineFactory = (\n task: 'feature-extraction',\n model: string\n) => Promise<NonNullable<Embedder['pipeline']>>;\n\nexport interface EmbeddingLifecycleTelemetry {\n recordModelLoad(resourceId: string, backendId: string, durationMs: number): void;\n recordModelLoadFailure(durationMs: number): void;\n recordModelActivity(): void;\n recordModelRelease(resourceId: string, reason: RuntimeModelReleaseReason): void;\n recordModelReleaseFailure(): void;\n}\n\nexport interface EmbedderOptions {\n telemetry?: EmbeddingLifecycleTelemetry;\n now?: () => number;\n loadPipeline?: () => Promise<FeatureExtractionPipelineFactory>;\n}\n\nexport const DEFAULT_EMBEDDING_MODEL = 'Xenova/multilingual-e5-small';\nexport const DEFAULT_EMBEDDING_FALLBACK_MODEL = 'intfloat/multilingual-e5-small';\nconst MANAGED_EMBEDDING_BACKEND_DIR = '.claude-memory-layer-embedding-backend';\nlet embedderResourceSequence = 0;\n\nexport class Embedder {\n private pipeline: (((input: string, options?: Record<string, unknown>) => Promise<{ data: Float32Array }>) & {\n dispose?: () => void | Promise<void>;\n }) | null = null;\n private readonly modelName: string;\n private activeModelName: string;\n private initialized = false;\n private initializationPromise: Promise<void> | null = null;\n private readonly telemetry: EmbeddingLifecycleTelemetry;\n private readonly now: () => number;\n private readonly loadPipeline: () => Promise<FeatureExtractionPipelineFactory>;\n private readonly resourceId: string;\n\n constructor(modelName: string = DEFAULT_EMBEDDING_MODEL, options: EmbedderOptions = {}) {\n this.modelName = modelName;\n this.activeModelName = modelName;\n this.telemetry = options.telemetry ?? getRuntimeResourceTelemetry();\n this.now = options.now ?? Date.now;\n this.loadPipeline = options.loadPipeline ?? loadTransformersPipeline;\n this.resourceId = `embedder-${++embedderResourceSequence}`;\n }\n\n /**\n * Initialize the embedding pipeline\n */\n async initialize(): Promise<void> {\n if (this.initialized) return;\n if (this.initializationPromise) return this.initializationPromise;\n\n const startedAt = this.now();\n this.initializationPromise = this.initializeOnce(startedAt);\n try {\n await this.initializationPromise;\n } finally {\n this.initializationPromise = null;\n }\n }\n\n private async initializeOnce(startedAt: number): Promise<void> {\n let pipeline: FeatureExtractionPipelineFactory;\n try {\n pipeline = await withSuppressedKnownTransformersWarnings(async () => {\n try {\n return await this.loadPipeline();\n } catch (error) {\n if (isMissingTransformersDependencyError(error)) {\n throw createEmbeddingBackendUnavailableError(error);\n }\n throw error;\n }\n });\n } catch (error) {\n this.telemetry.recordModelLoadFailure(this.now() - startedAt);\n throw error;\n }\n\n try {\n this.pipeline = await this.loadPipelineWithCorruptionRecovery(pipeline, this.modelName);\n this.activeModelName = this.modelName;\n this.initialized = true;\n this.telemetry.recordModelLoad(\n this.resourceId,\n opaqueBackendId(this.activeModelName),\n this.now() - startedAt\n );\n return;\n } catch (primaryError) {\n const fallbackModel = process.env.CLAUDE_MEMORY_EMBEDDING_FALLBACK_MODEL || DEFAULT_EMBEDDING_FALLBACK_MODEL;\n if (fallbackModel === this.modelName) {\n this.telemetry.recordModelLoadFailure(this.now() - startedAt);\n throw primaryError;\n }\n\n console.warn(`[Embedder] Primary model failed (${this.modelName}). Falling back to ${fallbackModel}`);\n try {\n this.pipeline = await this.loadPipelineWithCorruptionRecovery(pipeline, fallbackModel);\n this.activeModelName = fallbackModel;\n this.initialized = true;\n this.telemetry.recordModelLoad(\n this.resourceId,\n opaqueBackendId(this.activeModelName),\n this.now() - startedAt\n );\n } catch (fallbackError) {\n this.telemetry.recordModelLoadFailure(this.now() - startedAt);\n throw fallbackError;\n }\n }\n }\n\n /**\n * Load a model, self-healing a truncated/corrupted cache.\n *\n * @huggingface/transformers only checks whether a cached file *exists*\n * before skipping the download, not whether it is valid. A download\n * interrupted mid-write (killed process, lost connection) leaves a file\n * that exists but fails ONNX parsing \u2014 every future load hits the same\n * error forever, since nothing ever re-downloads it. This was observed on\n * a real machine after a global npm install: two ~450MB files, sizes not\n * matching the known-good ~470MB build, failing with\n * \"Load model from <path> failed:Protobuf parsing failed.\" on every\n * attempt. Detecting that shape, clearing the specific model's cache\n * directory, and retrying once converts a permanently stuck install into\n * one that repairs itself on the next start.\n */\n private async loadPipelineWithCorruptionRecovery(\n pipeline: FeatureExtractionPipelineFactory,\n modelName: string\n ): Promise<NonNullable<Embedder['pipeline']>> {\n try {\n return await withSuppressedKnownTransformersWarnings(() => pipeline('feature-extraction', modelName));\n } catch (error) {\n if (!isCorruptedModelCacheError(error)) throw error;\n\n const cleared = await clearModelCacheDirectory(modelName);\n if (!cleared) throw error;\n\n console.warn(`[Embedder] Detected a corrupted cache for ${modelName}; cleared it and retrying.`);\n return await withSuppressedKnownTransformersWarnings(() => pipeline('feature-extraction', modelName));\n }\n }\n\n // ~4 chars per token; 512 tokens * 4 = 2048, use 2000 to be safe\n private static readonly MAX_CHARS = 2000;\n\n private truncate(text: string): string {\n return text.length > Embedder.MAX_CHARS ? text.slice(0, Embedder.MAX_CHARS) : text;\n }\n\n /**\n * Generate embedding for a single text\n */\n async embed(text: string): Promise<EmbeddingResult> {\n await this.initialize();\n\n if (!this.pipeline) {\n throw new Error('Embedding pipeline not initialized');\n }\n\n const output = await this.pipeline(this.truncate(text), {\n pooling: 'mean',\n normalize: true,\n truncation: true,\n max_length: 512\n });\n this.telemetry.recordModelActivity();\n\n const vector = Array.from(output.data);\n\n return {\n vector,\n model: this.activeModelName,\n dimensions: vector.length\n };\n }\n\n /**\n * Generate embeddings for multiple texts in batch\n */\n async embedBatch(texts: string[]): Promise<EmbeddingResult[]> {\n await this.initialize();\n\n if (!this.pipeline) {\n throw new Error('Embedding pipeline not initialized');\n }\n\n const results: EmbeddingResult[] = [];\n\n // Process in batches of 32 for memory efficiency\n const batchSize = 32;\n for (let i = 0; i < texts.length; i += batchSize) {\n const batch = texts.slice(i, i + batchSize);\n\n for (const text of batch) {\n const output = await this.pipeline(this.truncate(text), {\n pooling: 'mean',\n normalize: true,\n truncation: true,\n max_length: 512\n });\n this.telemetry.recordModelActivity();\n\n const vector = Array.from(output.data);\n\n results.push({\n vector,\n model: this.activeModelName,\n dimensions: vector.length\n });\n }\n }\n\n return results;\n }\n\n /**\n * Get embedding dimensions for the current model\n */\n async getDimensions(): Promise<number> {\n const result = await this.embed('test');\n return result.dimensions;\n }\n\n /**\n * Check if embedder is ready\n */\n isReady(): boolean {\n return this.initialized && this.pipeline !== null;\n }\n\n /**\n * Get model name\n */\n getModelName(): string {\n return this.activeModelName;\n }\n\n /** Release the native ONNX model so a long-lived but idle MCP process does not retain it. */\n async dispose(reason: RuntimeModelReleaseReason = 'manual'): Promise<void> {\n const pipeline = this.pipeline;\n this.pipeline = null;\n this.initialized = false;\n this.activeModelName = this.modelName;\n if (!pipeline) return;\n try {\n await pipeline.dispose?.();\n this.telemetry.recordModelRelease(this.resourceId, reason);\n } catch (error) {\n this.telemetry.recordModelReleaseFailure();\n throw error;\n }\n }\n}\n\n// Singleton instance for reuse\nlet defaultEmbedder: Embedder | null = null;\n\nexport function getDefaultEmbedder(): Embedder {\n const envModel = process.env.CLAUDE_MEMORY_EMBEDDING_MODEL;\n if (!defaultEmbedder) {\n defaultEmbedder = new Embedder(envModel || undefined);\n }\n return defaultEmbedder;\n}\n\nexport async function disposeDefaultEmbedder(reason: RuntimeModelReleaseReason = 'process-shutdown'): Promise<void> {\n const embedder = defaultEmbedder;\n defaultEmbedder = null;\n await embedder?.dispose(reason);\n}\n\nlet transformersWarningSuppressionDepth = 0;\nlet originalConsoleWarn: typeof console.warn | null = null;\n\nexport async function withSuppressedKnownTransformersWarnings<T>(fn: () => Promise<T>): Promise<T> {\n if (transformersWarningSuppressionDepth === 0) {\n originalConsoleWarn = console.warn;\n console.warn = (...args: unknown[]) => {\n const message = args.map(String).join(' ');\n if (isKnownBenignTransformersWarning(message)) return;\n (originalConsoleWarn ?? console.warn)(...args);\n };\n }\n transformersWarningSuppressionDepth += 1;\n\n try {\n return await fn();\n } finally {\n transformersWarningSuppressionDepth -= 1;\n if (transformersWarningSuppressionDepth === 0 && originalConsoleWarn) {\n console.warn = originalConsoleWarn;\n originalConsoleWarn = null;\n }\n }\n}\n\nexport function isKnownBenignTransformersWarning(message: string): boolean {\n return message.includes('Unknown model class \"eurobert\"') ||\n message.includes('dtype not specified for \"model\"');\n}\n\nexport function isMissingTransformersDependencyError(error: unknown): boolean {\n const maybeError = error as { code?: unknown; message?: unknown } | null;\n const message = typeof maybeError?.message === 'string' ? maybeError.message : '';\n return maybeError?.code === 'ERR_MODULE_NOT_FOUND' &&\n message.includes(\"@huggingface/transformers\");\n}\n\nexport function createEmbeddingBackendUnavailableError(cause: unknown): Error & { cause?: unknown } {\n const error = new Error(\n [\n 'Required embedding backend is not installed.',\n '',\n 'Claude Memory Layer requires @huggingface/transformers for local semantic/vector embeddings.',\n 'The backend runs on CPU-only ONNX Runtime; CUDA is not required.',\n 'Reinstall globally with:',\n ' ONNXRUNTIME_NODE_INSTALL_CUDA=skip npm install -g claude-memory-layer@latest',\n '',\n 'If you are inside a local checkout or package directory, repair only the backend with:',\n ' ONNXRUNTIME_NODE_INSTALL_CUDA=skip node scripts/postinstall-embedding-backend.cjs'\n ].join('\\n')\n ) as Error & { cause?: unknown };\n error.cause = cause;\n return error;\n}\n\nfunction findPackageRoot(startUrl: string = import.meta.url): string | undefined {\n let currentDir = pathDirname(urlToFilePath(startUrl));\n const filesystemRoot = parse(currentDir).root;\n\n while (currentDir !== filesystemRoot) {\n const manifestPath = join(currentDir, 'package.json');\n if (existsSync(manifestPath)) {\n try {\n const manifest = JSON.parse(readFileSync(manifestPath, 'utf8')) as { name?: string };\n if (manifest.name === 'claude-memory-layer') return currentDir;\n } catch {\n // Continue upward when an unrelated package manifest is unreadable.\n }\n }\n currentDir = pathDirname(currentDir);\n }\n\n return undefined;\n}\n\nexport function resolveTransformersModuleSpecifier(\n packageRoot: string | undefined = findPackageRoot()\n): string {\n if (!packageRoot) return '@huggingface/transformers';\n\n const backendRoot = join(packageRoot, 'node_modules', MANAGED_EMBEDDING_BACKEND_DIR);\n const backendManifest = join(backendRoot, 'package.json');\n if (!existsSync(backendManifest)) return '@huggingface/transformers';\n\n try {\n const backendRequire = createNodeRequire(pathToFileURL(backendManifest));\n return pathToFileURL(backendRequire.resolve('@huggingface/transformers')).href;\n } catch {\n return '@huggingface/transformers';\n }\n}\n\ninterface TransformersModuleLike {\n pipeline: unknown;\n env?: { cacheDir?: string };\n default?: TransformersModuleLike;\n}\n\n/**\n * CJS interop: the managed-backend specifier is resolved with require\n * semantics, which picks transformers' `require` condition\n * (dist/transformers.node.cjs). `import()` of that CJS file exposes the real\n * exports under `default` when cjs-module-lexer cannot lex them as named\n * exports \u2014 leaving `namespace.pipeline` undefined (\"pipeline is not a\n * function\" at embed time). Unwrap `default` whenever it, not the namespace,\n * carries the pipeline.\n */\nexport function normalizeTransformersNamespace(namespace: TransformersModuleLike): TransformersModuleLike {\n if (typeof namespace.pipeline === 'function') return namespace;\n if (namespace.default && typeof namespace.default.pipeline === 'function') return namespace.default;\n return namespace;\n}\n\nasync function loadTransformersModule(): Promise<TransformersModuleLike> {\n const dynamicImport = new Function('specifier', 'return import(specifier)') as (\n specifier: string\n ) => Promise<TransformersModuleLike>;\n return normalizeTransformersNamespace(await dynamicImport(resolveTransformersModuleSpecifier()));\n}\n\nasync function loadTransformersPipeline(): Promise<FeatureExtractionPipelineFactory> {\n // Keep @huggingface/transformers lazy so importing MemoryService or pure\n // adapter helpers does not eagerly dlopen onnxruntime native bindings.\n const transformers = await loadTransformersModule();\n return transformers.pipeline as FeatureExtractionPipelineFactory;\n}\n\n/**\n * Matches ONNX Runtime's model-load failure text, which is how a truncated\n * download surfaces: the file exists (so nothing re-downloads it) but is not\n * a valid protobuf. Intentionally narrow \u2014 only errors that name onnx/protobuf\n * loading are treated as a corrupted cache; a model that is merely missing or\n * a network failure during download should surface as-is.\n */\nexport function isCorruptedModelCacheError(error: unknown): boolean {\n const message = error instanceof Error ? error.message : String(error);\n return /load model from .*failed/i.test(message)\n || /protobuf parsing failed/i.test(message)\n || /invalid[_ ]protobuf/i.test(message)\n || /onnxruntime[^a-z]*error/i.test(message);\n}\n\nasync function resolveTransformersCacheDir(): Promise<string | undefined> {\n const transformers = await loadTransformersModule();\n return transformers.env?.cacheDir;\n}\n\n/**\n * Delete a model's cache directory so the library re-downloads it from\n * scratch. Returns false (not true-with-no-op) when the cache directory\n * cannot even be determined, so the caller knows recovery was not actually\n * attempted and should surface the original error instead of retrying\n * against the same corrupted files.\n *\n * `cacheDir` is injectable so tests can exercise the path-safety logic\n * directly: the production caller (below) resolves it via an indirect\n * dynamic import of @huggingface/transformers, which \u2014 like the rest of this\n * file's lazy loading \u2014 does not share module state with a bundler/test\n * runner's own transformed import of the same package.\n */\nexport async function clearModelCacheDirectory(\n modelName: string,\n cacheDir?: string\n): Promise<boolean> {\n try {\n const resolvedCacheDirInput = cacheDir ?? await resolveTransformersCacheDir();\n if (!resolvedCacheDirInput) return false;\n\n const fs = await import('node:fs/promises');\n const path = await import('node:path');\n const modelDir = path.join(resolvedCacheDirInput, modelName);\n\n // Guard against a misconfigured cacheDir turning this into `rm -rf` of\n // something unrelated: only remove a path that actually resolves inside\n // the resolved cache directory.\n const resolvedCacheDir = path.resolve(resolvedCacheDirInput);\n const resolvedModelDir = path.resolve(modelDir);\n if (!resolvedModelDir.startsWith(resolvedCacheDir + path.sep)) return false;\n\n await fs.rm(resolvedModelDir, { recursive: true, force: true });\n return true;\n } catch {\n return false;\n }\n}\n", "import { execFileSync } from 'node:child_process';\nimport { createHash } from 'node:crypto';\nimport {\n existsSync,\n mkdirSync,\n readFileSync,\n readdirSync,\n renameSync,\n rmSync,\n writeFileSync\n} from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\n\nexport const RUNTIME_RESOURCE_TELEMETRY_SCHEMA_VERSION = 1;\nexport const LEGACY_RUNTIME_VERSION = 'legacy-or-uninstrumented';\n\nexport type RuntimeClientKind = 'mcp' | 'semantic-daemon' | 'cli' | 'dashboard' | 'unknown';\nexport type RuntimeModelReleaseReason =\n | 'idle-timeout'\n | 'daemon-idle-shutdown'\n | 'process-shutdown'\n | 'manual'\n | 'unknown';\n\nexport interface RuntimeLatencyAggregate {\n count: number;\n failedCount: number;\n totalMs: number;\n maxMs: number;\n}\n\nexport interface RuntimeResourceSnapshot {\n schemaVersion: 1;\n pid: number;\n ppid: number;\n version: string;\n client: RuntimeClientKind;\n processState: 'running' | 'stopped';\n startedAt: string;\n updatedAt: string;\n stoppedAt: string | null;\n model: {\n loaded: boolean;\n loadedInstances: number;\n backendId: string | null;\n loadCount: number;\n loadFailureCount: number;\n totalLoadDurationMs: number;\n lastLoadDurationMs: number | null;\n lastLoadedAt: string | null;\n releaseCount: number;\n releaseFailureCount: number;\n lastReleasedAt: string | null;\n lastReleaseReason: RuntimeModelReleaseReason | null;\n lastActivityAt: string | null;\n useCount: number;\n };\n retrieval: {\n cold: RuntimeLatencyAggregate;\n hot: RuntimeLatencyAggregate;\n };\n}\n\nexport interface RuntimeResourceTelemetryOptions {\n now?: () => number;\n pid?: number;\n ppid?: number;\n version?: string;\n telemetryDir?: string;\n persist?: boolean;\n}\n\nexport interface RuntimeRetrievalTelemetry {\n isModelLoaded(): boolean;\n now(): number;\n recordRetrieval(tier: 'cold' | 'hot', durationMs: number, succeeded: boolean): void;\n}\n\nconst RUNTIME_CLIENT_KINDS = new Set<RuntimeClientKind>([\n 'mcp',\n 'semantic-daemon',\n 'cli',\n 'dashboard',\n 'unknown'\n]);\nconst SAFE_RUNTIME_VERSION = /^[0-9A-Za-z][0-9A-Za-z.+-]{0,63}$/;\n\nfunction emptyLatencyAggregate(): RuntimeLatencyAggregate {\n return { count: 0, failedCount: 0, totalMs: 0, maxMs: 0 };\n}\n\nfunction runtimeVersion(): string {\n const value = process.env.CLAUDE_MEMORY_LAYER_VERSION?.trim();\n return sanitizeRuntimeVersion(value || 'development');\n}\n\nfunction sanitizeRuntimeVersion(value: string): string {\n return SAFE_RUNTIME_VERSION.test(value) ? value : 'unknown';\n}\n\nexport function defaultRuntimeTelemetryDir(): string {\n const configured = process.env.CLAUDE_MEMORY_RUNTIME_TELEMETRY_DIR?.trim();\n return configured || path.join(os.homedir(), '.claude-code', 'memory', 'runtime-resources');\n}\n\nexport function opaqueBackendId(modelName: string): string {\n return `sha256:${createHash('sha256').update(modelName).digest('hex').slice(0, 12)}`;\n}\n\nexport class RuntimeResourceTelemetry implements RuntimeRetrievalTelemetry {\n private readonly nowFn: () => number;\n private readonly telemetryDir: string;\n private readonly persistEnabled: boolean;\n private readonly loadedResources = new Set<string>();\n private registered = false;\n private snapshot: RuntimeResourceSnapshot;\n private lastPersistMs = Number.NEGATIVE_INFINITY;\n private persistDirty = false;\n private flushTimer: NodeJS.Timeout | null = null;\n\n constructor(options: RuntimeResourceTelemetryOptions = {}) {\n this.nowFn = options.now ?? Date.now;\n this.telemetryDir = options.telemetryDir ?? defaultRuntimeTelemetryDir();\n const telemetryDisabled = ['1', 'true', 'yes'].includes(\n String(process.env.CLAUDE_MEMORY_DISABLE_RUNTIME_TELEMETRY || '').toLowerCase()\n );\n this.persistEnabled = options.persist ?? !telemetryDisabled;\n const now = this.isoNow();\n this.snapshot = {\n schemaVersion: RUNTIME_RESOURCE_TELEMETRY_SCHEMA_VERSION,\n pid: options.pid ?? process.pid,\n ppid: options.ppid ?? process.ppid,\n version: sanitizeRuntimeVersion(options.version ?? runtimeVersion()),\n client: 'unknown',\n processState: 'running',\n startedAt: now,\n updatedAt: now,\n stoppedAt: null,\n model: {\n loaded: false,\n loadedInstances: 0,\n backendId: null,\n loadCount: 0,\n loadFailureCount: 0,\n totalLoadDurationMs: 0,\n lastLoadDurationMs: null,\n lastLoadedAt: null,\n releaseCount: 0,\n releaseFailureCount: 0,\n lastReleasedAt: null,\n lastReleaseReason: null,\n lastActivityAt: null,\n useCount: 0\n },\n retrieval: {\n cold: emptyLatencyAggregate(),\n hot: emptyLatencyAggregate()\n }\n };\n }\n\n now(): number {\n return this.nowFn();\n }\n\n registerProcess(client: RuntimeClientKind): void {\n this.registered = true;\n this.snapshot.client = client;\n this.snapshot.processState = 'running';\n this.snapshot.stoppedAt = null;\n this.touchAndPersist({ flush: true });\n }\n\n markProcessStopped(): void {\n this.snapshot.processState = 'stopped';\n this.snapshot.stoppedAt = this.isoNow();\n this.touchAndPersist({ flush: true });\n // The snapshot only matters while the process lives; leaving it behind\n // accretes one file per session forever and slows every runtime-status\n // read. A crash before this line is covered by age-based pruning on read.\n if (this.registered && this.persistEnabled) {\n try {\n rmSync(path.join(this.telemetryDir, `process-${this.snapshot.pid}.json`), { force: true });\n } catch {\n // Never let telemetry cleanup interfere with shutdown.\n }\n }\n }\n\n recordModelLoad(resourceId: string, backendId: string, durationMs: number): void {\n this.loadedResources.add(resourceId);\n const model = this.snapshot.model;\n model.backendId = backendId;\n model.loadCount += 1;\n model.totalLoadDurationMs += boundedDuration(durationMs);\n model.lastLoadDurationMs = boundedDuration(durationMs);\n model.lastLoadedAt = this.isoNow();\n model.lastActivityAt = model.lastLoadedAt;\n this.touchAndPersist();\n }\n\n recordModelLoadFailure(durationMs: number): void {\n const model = this.snapshot.model;\n model.loadFailureCount += 1;\n model.lastLoadDurationMs = boundedDuration(durationMs);\n model.lastActivityAt = this.isoNow();\n this.touchAndPersist();\n }\n\n recordModelActivity(): void {\n this.snapshot.model.useCount += 1;\n this.snapshot.model.lastActivityAt = this.isoNow();\n this.touchAndPersist();\n }\n\n recordModelRelease(resourceId: string, reason: RuntimeModelReleaseReason): void {\n this.loadedResources.delete(resourceId);\n const model = this.snapshot.model;\n model.releaseCount += 1;\n model.lastReleasedAt = this.isoNow();\n model.lastReleaseReason = reason;\n model.lastActivityAt = model.lastReleasedAt;\n this.touchAndPersist();\n }\n\n recordModelReleaseFailure(): void {\n this.snapshot.model.releaseFailureCount += 1;\n this.snapshot.model.lastActivityAt = this.isoNow();\n this.touchAndPersist();\n }\n\n isModelLoaded(): boolean {\n return this.loadedResources.size > 0;\n }\n\n recordRetrieval(tier: 'cold' | 'hot', durationMs: number, succeeded: boolean): void {\n const aggregate = this.snapshot.retrieval[tier];\n const duration = boundedDuration(durationMs);\n aggregate.count += 1;\n aggregate.totalMs += duration;\n aggregate.maxMs = Math.max(aggregate.maxMs, duration);\n if (!succeeded) aggregate.failedCount += 1;\n this.snapshot.model.lastActivityAt = this.isoNow();\n this.touchAndPersist();\n }\n\n getSnapshot(): RuntimeResourceSnapshot {\n return structuredClone(this.snapshot);\n }\n\n private isoNow(): string {\n return new Date(this.nowFn()).toISOString();\n }\n\n private touchAndPersist(options?: { flush?: boolean }): void {\n this.snapshot.updatedAt = this.isoNow();\n // The redundant snapshot fields are derived here so no mutation path can\n // persist a self-contradictory model state (loaded=true, instances=0).\n this.snapshot.model.loadedInstances = this.loadedResources.size;\n this.snapshot.model.loaded = this.loadedResources.size > 0;\n if (!this.registered || !this.persistEnabled) return;\n\n // recordModelActivity/recordRetrieval fire once per embedded text and per\n // retrieval; a synchronous mkdir+write+rename per event stalls the\n // embedding loop. Leading-edge write plus a trailing unref'd flush keeps\n // the file at most PERSIST_INTERVAL_MS stale, and lifecycle transitions\n // (register/stop) flush immediately.\n const nowMs = this.nowFn();\n if (options?.flush || nowMs - this.lastPersistMs >= PERSIST_INTERVAL_MS) {\n this.persistNow(nowMs);\n return;\n }\n this.persistDirty = true;\n if (this.flushTimer) return;\n this.flushTimer = setTimeout(() => {\n this.flushTimer = null;\n if (this.persistDirty) this.persistNow(this.nowFn());\n }, PERSIST_INTERVAL_MS);\n this.flushTimer.unref?.();\n }\n\n private persistNow(nowMs: number): void {\n this.persistDirty = false;\n this.lastPersistMs = nowMs;\n try {\n mkdirSync(this.telemetryDir, { recursive: true, mode: 0o700 });\n const target = path.join(this.telemetryDir, `process-${this.snapshot.pid}.json`);\n const temporary = `${target}.tmp-${process.pid}`;\n writeFileSync(temporary, `${JSON.stringify(this.snapshot)}\\n`, { encoding: 'utf8', mode: 0o600 });\n renameSync(temporary, target);\n } catch {\n // Runtime telemetry must never make retrieval or shutdown fail.\n }\n }\n}\n\nconst PERSIST_INTERVAL_MS = 1_000;\n\nlet processTelemetry = new RuntimeResourceTelemetry();\n\nexport function getRuntimeResourceTelemetry(): RuntimeResourceTelemetry {\n return processTelemetry;\n}\n\nexport function setRuntimeResourceTelemetryForTests(telemetry: RuntimeResourceTelemetry): void {\n processTelemetry = telemetry;\n}\n\nexport function registerRuntimeProcess(client: RuntimeClientKind): void {\n processTelemetry.registerProcess(client);\n}\n\nexport function markRuntimeProcessStopped(): void {\n processTelemetry.markProcessStopped();\n}\n\nfunction boundedDuration(value: number): number {\n if (!Number.isFinite(value) || value < 0) return 0;\n return Math.round(value * 1000) / 1000;\n}\n\ninterface ProcessRow {\n pid: number;\n ppid: number;\n rssKiB: number;\n command: string;\n}\n\nexport interface RuntimeResourceGroup {\n version: string;\n client: RuntimeClientKind;\n processCount: number;\n rssMiB: number;\n orphanCount: number;\n modelLoadedCount: number;\n modelUnloadedCount: number;\n modelStateUnavailableCount: number;\n modelLoadCount: number;\n modelReleaseCount: number;\n coldRetrievalCount: number;\n coldRetrievalAverageMs: number | null;\n hotRetrievalCount: number;\n hotRetrievalAverageMs: number | null;\n}\n\nexport interface RuntimeResourceReport {\n generatedAt: string;\n processLocal: Omit<RuntimeResourceSnapshot, 'pid' | 'ppid'>;\n observation: {\n supported: boolean;\n platform: NodeJS.Platform;\n reason?: 'unsupported-platform' | 'process-metrics-unavailable';\n processCount: number | null;\n rssMiB: number | null;\n versionMismatchProcessCount: number;\n uninstrumentedProcessCount: number;\n restartRecommended: boolean;\n recommendationReasons: Array<'mixed_runtime_versions' | 'uninstrumented_runtime' | 'orphan_mcp'>;\n groups: RuntimeResourceGroup[];\n };\n}\n\nexport interface CollectRuntimeResourceReportOptions {\n platform?: NodeJS.Platform;\n telemetryDir?: string;\n now?: () => number;\n readProcessTable?: () => string;\n localSnapshot?: RuntimeResourceSnapshot;\n}\n\nexport function collectRuntimeResourceReport(\n options: CollectRuntimeResourceReportOptions = {}\n): RuntimeResourceReport {\n const platform = options.platform ?? process.platform;\n const now = options.now ?? Date.now;\n const localSnapshot = options.localSnapshot ?? processTelemetry.getSnapshot();\n const processLocal = stripProcessIdentity(localSnapshot);\n\n if (platform !== 'darwin' && platform !== 'linux') {\n return {\n generatedAt: new Date(now()).toISOString(),\n processLocal,\n observation: {\n supported: false,\n platform,\n reason: 'unsupported-platform',\n processCount: null,\n rssMiB: null,\n versionMismatchProcessCount: 0,\n uninstrumentedProcessCount: 0,\n restartRecommended: false,\n recommendationReasons: [],\n groups: []\n }\n };\n }\n\n let rows: ProcessRow[];\n try {\n const raw = options.readProcessTable\n ? options.readProcessTable()\n : execFileSync('ps', ['-axo', 'pid=,ppid=,rss=,command='], {\n encoding: 'utf8',\n timeout: 5_000,\n maxBuffer: 8 * 1024 * 1024\n });\n rows = parseProcessTable(raw);\n } catch {\n return {\n generatedAt: new Date(now()).toISOString(),\n processLocal,\n observation: {\n supported: false,\n platform,\n reason: 'process-metrics-unavailable',\n processCount: null,\n rssMiB: null,\n versionMismatchProcessCount: 0,\n uninstrumentedProcessCount: 0,\n restartRecommended: false,\n recommendationReasons: [],\n groups: []\n }\n };\n }\n\n const snapshots = readRuntimeResourceSnapshots(options.telemetryDir ?? defaultRuntimeTelemetryDir(), now());\n const snapshotsByPid = new Map(\n snapshots\n .filter((snapshot) => snapshot.processState === 'running')\n .map((snapshot) => [snapshot.pid, snapshot])\n );\n // A snapshot alone is not proof that a PID still belongs to this product;\n // stale files plus PID reuse must not turn unrelated processes into samples.\n const candidates = rows.filter((row) => classifyRuntimeCommand(row.command) !== null);\n const groups = aggregateRuntimeResourceGroups(candidates, snapshotsByPid);\n const uninstrumentedProcessCount = groups\n .filter((group) => group.version === LEGACY_RUNTIME_VERSION)\n .reduce((sum, group) => sum + group.processCount, 0);\n const currentVersion = processLocal.version;\n const canCompareVersion = currentVersion !== 'development' && currentVersion !== 'unknown';\n const versionMismatchProcessCount = canCompareVersion\n ? groups\n .filter((group) => group.version !== LEGACY_RUNTIME_VERSION && group.version !== currentVersion)\n .reduce((sum, group) => sum + group.processCount, 0)\n : 0;\n const orphanCount = groups.reduce((sum, group) => sum + group.orphanCount, 0);\n const recommendationReasons: RuntimeResourceReport['observation']['recommendationReasons'] = [];\n if (versionMismatchProcessCount > 0) recommendationReasons.push('mixed_runtime_versions');\n if (uninstrumentedProcessCount > 0) recommendationReasons.push('uninstrumented_runtime');\n if (orphanCount > 0) recommendationReasons.push('orphan_mcp');\n\n return {\n generatedAt: new Date(now()).toISOString(),\n processLocal,\n observation: {\n supported: true,\n platform,\n processCount: candidates.length,\n rssMiB: roundMiB(candidates.reduce((sum, row) => sum + row.rssKiB, 0)),\n versionMismatchProcessCount,\n uninstrumentedProcessCount,\n restartRecommended: recommendationReasons.length > 0,\n recommendationReasons,\n groups\n }\n };\n}\n\n/** Snapshots older than this are crash leftovers \u2014 markProcessStopped never ran. */\nconst STALE_SNAPSHOT_MS = 7 * 24 * 60 * 60 * 1_000;\n\nexport function readRuntimeResourceSnapshots(directory: string, nowMs: number = Date.now()): RuntimeResourceSnapshot[] {\n if (!existsSync(directory)) return [];\n const snapshots: RuntimeResourceSnapshot[] = [];\n for (const entry of readdirSync(directory)) {\n if (!/^process-\\d+\\.json$/.test(entry)) continue;\n try {\n const parsed = JSON.parse(readFileSync(path.join(directory, entry), 'utf8')) as RuntimeResourceSnapshot;\n if (!isRuntimeResourceSnapshot(parsed)) continue;\n // A process SIGKILLed before markProcessStopped leaves a 'running' file\n // behind forever. Age it out (and best-effort delete it) so the\n // directory stays bounded and a reused PID months later cannot inherit\n // the dead process's counters.\n const updatedAtMs = Date.parse(parsed.updatedAt);\n if (Number.isFinite(updatedAtMs) && nowMs - updatedAtMs > STALE_SNAPSHOT_MS) {\n try {\n rmSync(path.join(directory, entry), { force: true });\n } catch {\n // Pruning is opportunistic; reading must not fail on it.\n }\n continue;\n }\n snapshots.push(parsed);\n } catch {\n // Ignore partial, corrupt, or incompatible telemetry snapshots.\n }\n }\n return snapshots;\n}\n\nfunction isRuntimeResourceSnapshot(value: RuntimeResourceSnapshot): boolean {\n return value?.schemaVersion === RUNTIME_RESOURCE_TELEMETRY_SCHEMA_VERSION\n && Number.isSafeInteger(value.pid)\n && value.pid > 0\n && SAFE_RUNTIME_VERSION.test(value.version)\n && RUNTIME_CLIENT_KINDS.has(value.client)\n && typeof value.model?.loaded === 'boolean';\n}\n\nfunction parseProcessTable(raw: string): ProcessRow[] {\n const rows: ProcessRow[] = [];\n for (const line of raw.split('\\n')) {\n const match = /^\\s*(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(.+)$/.exec(line);\n if (!match) continue;\n rows.push({\n pid: Number(match[1]),\n ppid: Number(match[2]),\n rssKiB: Number(match[3]),\n command: match[4]\n });\n }\n return rows;\n}\n\nfunction classifyRuntimeCommand(command: string): RuntimeClientKind | null {\n if (/(?:^|[\\\\/])semantic-daemon\\.(?:js|ts)(?:\\s|$)/.test(command)) return 'semantic-daemon';\n if (/claude-memory-layer-mcp|(?:^|[\\\\/])(?:dist|src)[\\\\/](?:extensions[\\\\/])?mcp[\\\\/]index\\.(?:js|ts)(?:\\s|$)/.test(command)) {\n return 'mcp';\n }\n return null;\n}\n\nfunction aggregateRuntimeResourceGroups(\n rows: ProcessRow[],\n snapshotsByPid: Map<number, RuntimeResourceSnapshot>\n): RuntimeResourceGroup[] {\n const groups = new Map<string, RuntimeResourceGroup & { coldTotalMs: number; hotTotalMs: number }>();\n\n for (const row of rows) {\n const commandKind = classifyRuntimeCommand(row.command);\n const candidateSnapshot = snapshotsByPid.get(row.pid);\n // PID reuse: a stale 'running' snapshot from a dead process must not lend\n // its counters to an unrelated product process that inherited the PID. If\n // the live command classifies as a different kind than the snapshot\n // recorded, trust the command and treat the process as uninstrumented.\n const snapshot = candidateSnapshot && commandKind !== null && candidateSnapshot.client !== commandKind\n ? undefined\n : candidateSnapshot;\n const client = snapshot?.client ?? commandKind ?? 'unknown';\n const version = snapshot?.version || LEGACY_RUNTIME_VERSION;\n const key = `${version}\\u0000${client}`;\n const group = groups.get(key) ?? {\n version,\n client,\n processCount: 0,\n rssMiB: 0,\n orphanCount: 0,\n modelLoadedCount: 0,\n modelUnloadedCount: 0,\n modelStateUnavailableCount: 0,\n modelLoadCount: 0,\n modelReleaseCount: 0,\n coldRetrievalCount: 0,\n coldRetrievalAverageMs: null,\n hotRetrievalCount: 0,\n hotRetrievalAverageMs: null,\n coldTotalMs: 0,\n hotTotalMs: 0\n };\n group.processCount += 1;\n group.rssMiB += row.rssKiB / 1024;\n // The semantic daemon is intentionally detached, so PPID 1 is expected for\n // that client. MCP stdio servers, in contrast, should retain a live parent.\n if (row.ppid === 1 && client === 'mcp') group.orphanCount += 1;\n if (snapshot) {\n if (snapshot.model.loaded) group.modelLoadedCount += 1;\n else group.modelUnloadedCount += 1;\n group.modelLoadCount += snapshot.model.loadCount;\n group.modelReleaseCount += snapshot.model.releaseCount;\n group.coldRetrievalCount += snapshot.retrieval.cold.count;\n group.coldTotalMs += snapshot.retrieval.cold.totalMs;\n group.hotRetrievalCount += snapshot.retrieval.hot.count;\n group.hotTotalMs += snapshot.retrieval.hot.totalMs;\n } else {\n group.modelStateUnavailableCount += 1;\n }\n groups.set(key, group);\n }\n\n return Array.from(groups.values())\n .map(({ coldTotalMs, hotTotalMs, ...group }) => ({\n ...group,\n rssMiB: Math.round(group.rssMiB * 10) / 10,\n coldRetrievalAverageMs: average(coldTotalMs, group.coldRetrievalCount),\n hotRetrievalAverageMs: average(hotTotalMs, group.hotRetrievalCount)\n }))\n .sort((a, b) => a.version.localeCompare(b.version) || a.client.localeCompare(b.client));\n}\n\nfunction average(total: number, count: number): number | null {\n return count === 0 ? null : Math.round((total / count) * 1000) / 1000;\n}\n\nfunction roundMiB(rssKiB: number): number {\n return Math.round((rssKiB / 1024) * 10) / 10;\n}\n\nfunction stripProcessIdentity(\n snapshot: RuntimeResourceSnapshot\n): Omit<RuntimeResourceSnapshot, 'pid' | 'ppid'> {\n const { pid: _pid, ppid: _ppid, ...safe } = snapshot;\n return safe;\n}\n", "export type HookMemorySource = 'semantic' | 'keyword' | 'graduated' | 'episode' | 'lesson' | 'unknown';\n\nexport interface HookMemoryCandidate {\n type: string;\n content: string;\n id?: string;\n sessionId?: string;\n score?: number;\n source?: HookMemorySource;\n fallback?: boolean;\n memoryLevel?: string;\n accessCount?: number;\n retrievalRankScore?: number;\n /** Same-session evidence expanded from a relevant retrieval seed. */\n episodeLinked?: boolean;\n /** The episode was reached through a strongly aligned prompt/tool seed. */\n episodeSeedAligned?: boolean;\n /** Every distinctive identifier anchor and at least four lexical clues matched the seed. */\n episodeSeedStrongAligned?: boolean;\n}\n\nexport interface HookInjectionPolicy {\n minScore: number;\n semanticMinScore: number;\n keywordMinScore: number;\n fallbackKeywordMinScore: number;\n /** Minimum adjacent-score drop used to retain an additional result. */\n scoreCliffGap: number;\n maxMemories: number;\n}\n\nconst LOW_SIGNAL_QUERY_TERMS = new Set([\n 'the', 'and', 'for', 'with', 'this', 'that', 'what', 'when', 'where', 'why', 'how',\n 'please', 'help', 'need', 'using', 'use', 'fix', 'update', 'change', 'memory',\n '\uADF8\uB9AC\uACE0', '\uADF8\uAC83', '\uADF8\uAC70', '\uC774\uAC83', '\uC774\uAC70', '\uD574\uC8FC\uC138\uC694', '\uD574\uC918', '\uC218\uC815', '\uAD6C\uD604', '\uAC1C\uC120',\n '\uD655\uC778', '\uD655\uC778\uD574\uC918', '\uD655\uC778\uD574\uC8FC\uC138\uC694', '\uBC29\uBC95', '\uAD00\uB828', '\uB0B4\uC6A9', '\uBB38\uC81C', '\uC6D0\uC778', '\uC791\uC5C5', '\uC9C4\uD589', '\uACC4\uD68D', '\uD6C8\uB828', '\uB2E4\uC74C', '\uC774\uBC88',\n '\uC54C\uB824\uC918', '\uC54C\uB824\uC8FC', '\uC54C\uB824', '\uC815\uB9AC\uD574\uC918', '\uC815\uB9AC', '\uC124\uBA85\uD574\uC918', '\uC124\uBA85', '\uC694\uC57D\uD574\uC918',\n '\uC694\uC57D', '\uBD80\uD0C1', '\uB300\uD574', '\uBB34\uC5C7', '\uC5B4\uB5BB', '\uC5B4\uB5BB\uAC8C', '\uC788\uC5B4', '\uB2E4\uC2DC',\n '\uCD5C\uC885', '\uACB0\uACFC', '\uD575\uC2EC', '\uADFC\uAC70', '\uB2F9\uC2DC', '\uACB0\uB860', '\uD574\uACB0', '\uC2E4\uC81C', '\uD655\uC778\uB41C', '\uACB0\uC815', '\uC0AC\uD56D',\n '\uBB50\uC57C', '\uBB50\uC608\uC694', '\uBB50\uC600\uC5B4', '\uBB50\uC600\uC5B4\uC694'\n]);\n\nexport function getHookInjectionPolicy(env: NodeJS.ProcessEnv = process.env): HookInjectionPolicy {\n const minScore = readScoreThreshold(env.CLAUDE_MEMORY_HOOK_INJECTION_MIN_SCORE, 0.65);\n const keywordMinScore = readNumber(\n env.CLAUDE_MEMORY_HOOK_KEYWORD_MIN_SCORE,\n Math.max(minScore, 0.7),\n { min: 0, max: 1 }\n );\n\n return {\n minScore,\n semanticMinScore: readScoreThreshold(env.CLAUDE_MEMORY_HOOK_SEMANTIC_MIN_SCORE, minScore),\n keywordMinScore,\n fallbackKeywordMinScore: readNumber(\n env.CLAUDE_MEMORY_HOOK_FALLBACK_KEYWORD_MIN_SCORE,\n Math.max(keywordMinScore, 0.8),\n { min: 0, max: 1 }\n ),\n scoreCliffGap: readNumber(env.CLAUDE_MEMORY_HOOK_SCORE_CLIFF_GAP, 0.08, { min: 0.01, max: 0.5 }),\n maxMemories: Math.max(1, Math.floor(readNumber(env.CLAUDE_MEMORY_HOOK_MAX_INJECTED, 5)))\n };\n}\n\nexport function filterHookInjectableMemories(\n candidates: HookMemoryCandidate[],\n policy: HookInjectionPolicy = getHookInjectionPolicy(),\n query?: string\n): HookMemoryCandidate[] {\n const ranked = rankHookCandidates(candidates, policy, query);\n const cliffBounded = query ? applyScoreCliff(ranked, policy.scoreCliffGap) : ranked;\n const bounded = cliffBounded.slice(0, policy.maxMemories).map(({ candidate }) => candidate);\n return query ? applyAnswerabilityGate(bounded, query) : bounded;\n}\n\n/**\n * specs/lesson-recall-hooks R3 \u2014 keep one query-covering lesson alive.\n *\n * Lessons score 0.65-0.8 by design (lexical coverage only) while transcript\n * evidence sits around 0.83, so the score cliff drops every lesson whenever a\n * good answer exists. Real traces: 196 prompts had a lesson candidate, 5 kept\n * it. A lesson is only reserved when it already passed scoreLessonEvidence's\n * own gate and the injection minimum, and never displaces another lesson.\n */\nexport function reserveLessonSlot(\n selected: HookMemoryCandidate[],\n candidates: HookMemoryCandidate[],\n policy: HookInjectionPolicy\n): HookMemoryCandidate[] {\n if (selected.some((candidate) => candidate.source === 'lesson')) return selected;\n const best = candidates\n .filter((candidate) => candidate.source === 'lesson' && (candidate.score ?? 0) >= policy.minScore)\n .sort((a, b) => (b.score ?? 0) - (a.score ?? 0))[0];\n if (!best) return selected;\n if (selected.length < policy.maxMemories) return [...selected, best];\n const weakest = selected.reduce((low, candidate, index) =>\n (candidate.score ?? 0) < (selected[low].score ?? 0) ? index : low, 0);\n return [...selected.slice(0, weakest), ...selected.slice(weakest + 1), best];\n}\n\n/** Select relevant seeds before episode expansion, without the final answerability gate. */\nexport function selectHookRetrievalSeeds(\n candidates: HookMemoryCandidate[],\n policy: HookInjectionPolicy = getHookInjectionPolicy(),\n query?: string\n): HookMemoryCandidate[] {\n const ranked = rankHookCandidates(candidates, policy, query);\n const cliffBounded = query ? applyScoreCliff(ranked, policy.scoreCliffGap) : ranked;\n return cliffBounded.slice(0, policy.maxMemories).map(({ candidate }) => candidate);\n}\n\n/**\n * Select prompt/tool seeds independently from answer ranking. Exact prompts\n * otherwise lose to answer-type utility bonuses before episode expansion,\n * preventing the response from the same turn from ever becoming a candidate.\n */\nexport function selectHookEpisodeSeeds(\n candidates: HookMemoryCandidate[],\n policy: HookInjectionPolicy = getHookInjectionPolicy(),\n query: string\n): HookMemoryCandidate[] {\n const queryTerms = meaningfulTerms(query);\n const queryAnchors = identifierAnchors(query);\n return candidates\n .filter((candidate) => candidate.type === 'user_prompt' || candidate.type === 'tool_observation')\n .filter((candidate) => hasQueryMemoryAlignment(query, candidate.content, 2))\n .map((candidate, index) => {\n const contentTerms = new Set(meaningfulTerms(candidate.content));\n const overlap = queryTerms.filter((term) => contentTerms.has(term)).length;\n const lowered = candidate.content.toLowerCase();\n const anchorCoverage = queryAnchors.length === 0\n ? 0\n : queryAnchors.filter((anchor) => lowered.includes(anchor.toLowerCase())).length / queryAnchors.length;\n const lexicalCoverage = overlap / Math.max(1, Math.min(queryTerms.length, 12));\n const score = candidate.score ?? 0;\n const normalThreshold = thresholdFor(candidate, policy);\n const hasDistinctiveAnchor = queryAnchors.some((anchor) =>\n anchor.length >= 6 && /[A-Za-z]/.test(anchor)\n );\n const fullyAnchored = queryAnchors.length > 0 && anchorCoverage === 1 && overlap >= 4 && hasDistinctiveAnchor;\n const usesStrongAnchorFloor = score < normalThreshold && fullyAnchored;\n return {\n candidate: {\n ...candidate,\n // Episode answers are filtered again by the normal semantic floor.\n // A fully anchored prompt that uses the lower seed-only floor needs\n // enough inherited score to compete there; counterfactual anchors\n // cannot take this path because their coverage is zero.\n score: usesStrongAnchorFloor ? Math.max(score, policy.semanticMinScore + 0.02) : score,\n episodeSeedAligned: true,\n episodeSeedStrongAligned: fullyAnchored\n },\n index,\n score: score + lexicalCoverage * 0.25 + anchorCoverage * 0.20,\n eligible: score >= normalThreshold || usesStrongAnchorFloor\n };\n })\n .filter((item) => item.eligible)\n .sort((a, b) => (b.score - a.score) || (a.index - b.index))\n .slice(0, policy.maxMemories)\n .map((item) => item.candidate);\n}\n\nfunction rankHookCandidates(\n candidates: HookMemoryCandidate[],\n policy: HookInjectionPolicy,\n query?: string\n): Array<{ candidate: HookMemoryCandidate; index: number; effectiveScore: number }> {\n return candidates\n .map((candidate, index) => ({ candidate, index }))\n .filter(({ candidate }) => isHookInjectableMemory(candidate, policy))\n .filter(({ candidate }) => !query || (\n candidate.source === 'episode' && candidate.episodeLinked && candidate.episodeSeedAligned\n ) || hasQueryMemoryAlignment(query, candidate.content, 2))\n // The rule-based session-summary generator emits a table of contents\n // (\"Session with N prompts. Topics discussed: ...\"), not a result. The\n // graduated lane already excludes this via scoreGraduatedEvidence; the\n // semantic/keyword lanes must exclude it too or it keeps winning the\n // evidenceUtilityBonus('session_summary') = 0.12 slot on session_summary's\n // own high type bonus alone, with nothing answerable inside it.\n .filter(({ candidate }) =>\n candidate.type !== 'session_summary' || !isPromptOnlySessionSummary(candidate.content)\n )\n .map(({ candidate, index }) => ({\n candidate,\n index,\n effectiveScore: Math.max(0,\n (candidate.score ?? 0)\n + (query ? evidenceUtilityBonus(candidate.type, query) : 0)\n + (query ? graduatedEvidenceBonus(candidate) : 0)\n + (candidate.source === 'episode' && candidate.episodeLinked && candidate.episodeSeedStrongAligned\n ? 0.42\n : candidate.source === 'episode' && candidate.episodeLinked && candidate.episodeSeedAligned ? 0.12 : 0)\n )\n }))\n .sort((a, b) => {\n const scoreDelta = b.effectiveScore - a.effectiveScore;\n return scoreDelta || a.index - b.index;\n });\n}\n\nfunction applyScoreCliff(\n ranked: Array<{ candidate: HookMemoryCandidate; index: number; effectiveScore: number }>,\n minimumGap: number\n): Array<{ candidate: HookMemoryCandidate; index: number; effectiveScore: number }> {\n if (ranked.length <= 1) return ranked;\n const effectiveMinimumGap = ranked[0].candidate.source === 'graduated'\n ? Math.min(minimumGap, 0.02)\n : minimumGap;\n for (let index = 1; index < ranked.length; index++) {\n const previous = ranked[index - 1].effectiveScore;\n const current = ranked[index].effectiveScore;\n if (previous - current >= effectiveMinimumGap) return ranked.slice(0, index);\n }\n // No clear relevance break: retain only the strongest result rather than\n // accumulating similarly scored but potentially unrelated context.\n return ranked.slice(0, 1);\n}\n\nfunction applyAnswerabilityGate(candidates: HookMemoryCandidate[], query: string): HookMemoryCandidate[] {\n const answerEvidence = candidates.filter((candidate) =>\n candidate.type === 'agent_response'\n || candidate.type === 'session_summary'\n || candidate.type === 'lesson'\n );\n if (answerEvidence.length > 0) {\n const toolEvidence = hasToolEvidenceIntent(query)\n ? candidates.filter((candidate) =>\n candidate.type === 'tool_observation' && toolEvidenceMatchesQueryAnchors(candidate, query)\n )\n : [];\n return [...answerEvidence, ...toolEvidence];\n }\n // No tool-only fallback. Injecting raw tool attempts because nothing better\n // survived ranking produced 131 traces whose memories were never used in an\n // answer (grounding 0.2%). Abstaining is cheaper than unusable context.\n return isContinuationQuery(query) ? candidates : [];\n}\n\n/**\n * A tool observation may only accompany an answer when the query's distinctive\n * identifiers actually occur in it. Queries without identifiers cannot be\n * verified this way, so they keep the intent-only behaviour.\n */\nfunction toolEvidenceMatchesQueryAnchors(candidate: HookMemoryCandidate, query: string): boolean {\n const anchors = identifierAnchors(query);\n if (anchors.length === 0) return true;\n const lowered = candidate.content.toLowerCase();\n return anchors.some((anchor) => lowered.includes(anchor.toLowerCase()));\n}\n\nfunction hasToolEvidenceIntent(query: string): boolean {\n // \"command\", \"log\", and \"output\" are deliberately absent: <task-notification>\n // payloads embed <output-file>, which made nearly every notification look like\n // a tool-evidence request. Retrieval queries are also enriched with the\n // previous turn, so generic words match far beyond the current question.\n return /\\b(?:kubectl|curl|psql|sql|stderr|stdout|traceback|stack\\s*trace|exit\\s*code)\\b|(?:\uBA85\uB839\uC5B4|\uC2A4\uD0DD\\s*\uD2B8\uB808\uC774\uC2A4|\uC885\uB8CC\\s*\uCF54\uB4DC|\uD130\uBBF8\uB110)/iu\n .test(query);\n}\n\nfunction evidenceUtilityBonus(type: string, query: string): number {\n // Lessons are human-reviewed runbooks rather than transcript, so they outrank\n // every derived evidence type.\n if (type === 'lesson') return 0.16;\n if (type === 'session_summary') return 0.12;\n if (type === 'agent_response') return 0.10;\n // Tool observations only earn a slot when the question actually asks for tool\n // evidence; otherwise they are pushed below answer evidence instead of\n // consuming the bounded injection budget.\n if (type === 'tool_observation') return hasToolEvidenceIntent(query) ? 0.03 : -0.15;\n if (type === 'user_prompt') return -0.10;\n return 0;\n}\n\nfunction graduatedEvidenceBonus(candidate: HookMemoryCandidate): number {\n // scoreGraduatedEvidence already includes a bounded level/access prior.\n // Applying the level bonus again here can let a broad L2 answer outrank a\n // more exact L1 answer, so calibrated graduated candidates get no second\n // promotion boost.\n if (candidate.source === 'graduated') return 0;\n if (candidate.type !== 'agent_response' && candidate.type !== 'session_summary') return 0;\n if (candidate.memoryLevel === 'L4') return 0.10;\n if (candidate.memoryLevel === 'L3') return 0.08;\n if (candidate.memoryLevel === 'L2') return 0.06;\n if (candidate.memoryLevel === 'L1') return 0.03;\n return 0;\n}\n\n/**\n * Deterministic score for the L1+ answer lane. It rewards query coverage and\n * exact identifier coverage; level/access are only small tie-breakers so a\n * frequently reused but wrong entity cannot win on graduation alone.\n */\nexport function scoreGraduatedEvidence(query: string, candidate: HookMemoryCandidate): number | null {\n if (candidate.type !== 'user_prompt' && candidate.type !== 'agent_response' && candidate.type !== 'session_summary') return null;\n if (!candidate.memoryLevel || candidate.memoryLevel === 'L0') return null;\n if (candidate.type === 'session_summary' && isPromptOnlySessionSummary(candidate.content)) return null;\n if (!hasQueryMemoryAlignment(query, candidate.content, 2)) return null;\n\n const queryTerms = meaningfulTerms(query);\n const contentTerms = new Set(meaningfulTerms(candidate.content));\n const overlap = queryTerms.filter((term) => contentTerms.has(term)).length;\n if (overlap < Math.min(3, queryTerms.length)) return null;\n const coverage = overlap / Math.max(1, Math.min(queryTerms.length, 8));\n const anchors = identifierAnchors(query);\n const lowered = candidate.content.toLowerCase();\n const matchedAnchors = anchors.filter((anchor) => lowered.includes(anchor.toLowerCase())).length;\n const anchorCoverage = anchors.length === 0 ? 0 : matchedAnchors / anchors.length;\n if (anchors.length >= 2 && matchedAnchors < Math.ceil(anchors.length * 0.6)) return null;\n if (candidate.type !== 'user_prompt' && isDiagnosticQuery(query) && !hasDiagnosticOutcome(candidate.content)) return null;\n\n const entities = entityAnchors(query);\n const matchedEntityPositions = entities\n .map((entity) => lowered.indexOf(entity))\n .filter((index) => index >= 0);\n const entityCoverage = entities.length === 0 ? 0 : matchedEntityPositions.length / entities.length;\n if (anchors.length > 0 && entities.length >= 2 && entityCoverage < 0.8) return null;\n const entityProximity = matchedEntityPositions.length < 2\n ? 0\n : 1 - Math.min(1,\n (Math.max(...matchedEntityPositions) - Math.min(...matchedEntityPositions)) / 2000\n );\n const levelPrior = candidate.memoryLevel === 'L4' ? 0.05\n : candidate.memoryLevel === 'L3' ? 0.045\n : candidate.memoryLevel === 'L2' ? 0.035\n : 0.015;\n const accessPrior = Math.min(0.02, Math.log2(Math.max(1, (candidate.accessCount ?? 0) + 1)) * 0.008);\n const rankPrior = Math.max(0, Math.min(1, candidate.retrievalRankScore ?? 0)) * 0.08;\n const base = candidate.type === 'user_prompt' ? 0.52 : 0.45;\n return Math.min(0.98,\n base\n + coverage * 0.20\n + anchorCoverage * 0.04\n + entityCoverage * 0.20\n + entityProximity * 0.10\n + rankPrior\n + levelPrior\n + accessPrior\n );\n}\n\nexport interface LessonEvidenceInput {\n lessonId: string;\n name: string;\n trigger?: string;\n steps: string[];\n failureModes?: string[];\n confidence: number;\n scope?: string;\n validation?: string[];\n reconsiderWhen?: string;\n validVersions?: string[];\n}\n\n/**\n * Render a curated lesson as injectable evidence, scored by query coverage.\n *\n * Lessons live outside the events table, so they reach the prompt only through\n * this lane. The score stays lexical and deterministic for the same reason the\n * graduated lane does: a reviewed runbook must not outrank exact evidence just\n * for being curated, so confidence is only a small tie-breaker.\n */\nexport function isExplicitlyProhibitedLessonQuery(query: string): boolean {\n // An exact identifier is not permission to suggest a procedure the caller\n // explicitly prohibited. Abstain conservatively; ordinary \"without\" clauses\n // remain searchable because they may describe the desired safety condition.\n return /\\b(?:do[ -]+not|don't|never)\\b|(?:^|[.!?;]\\s*)(?:please\\s+)?(?:skip|omit|ignore)\\b|(?:\uC0AC\uC6A9|\uC801\uC6A9|\uC2E4\uD589|\uD638\uCD9C|\uC124\uCE58|\uD65C\uC131\uD654|\uC7AC\uC2DC\uB3C4)(?:\\s*\uAE08\uC9C0|\uD558\uC9C0\\s*(?:\uC54A|\uB9D0))|\uAC74\uB108\uB6F0|\uBB34\uC2DC(?:\uD574|\uD558|\uD560)|\uC9C0\\s*\uB9C8(?:\uB77C|\uC138\uC694|\uC2ED\uC2DC\uC624)?(?:[.!?\\s]|$)/iu.test(query);\n}\n\n/** Remove only complete generic execution constraints from lexical scoring.\n * The caller's query and action restrictions remain unchanged everywhere else.\n * Targeted procedures, memory opt-outs and mixed clauses must reach the existing\n * conservative prohibition guard, including unknown additions to these lists.\n */\nfunction lessonScoringQuery(query: string): string {\n const korean = /^(?:\uB3C4\uAD6C\\s*\uD638\uCD9C|\uD30C\uC77C\\s*(?:\uC218\uC815|\uBCC0\uACBD))(?:(?:\\s*[/\u00B7,]\\s*|\\s*(?:\uBC0F|\uC640|\uACFC)\\s*)(?:\uB3C4\uAD6C\\s*\uD638\uCD9C|\uD30C\uC77C\\s*(?:\uC218\uC815|\uBCC0\uACBD)))*(?:\uC740|\uB294|\uC744|\uB97C)?\\s*(?:\uD558\uC9C0\\s*\uB9C8(?:\uC138\uC694|\uC2ED\uC2DC\uC624|\uB77C)|\uAE08\uC9C0)$/u;\n const readOnly = /^(?:\uC77D\uAE30\\s*\uC804\uC6A9\uC73C\uB85C\\s*\uD655\uC778\uD558\uACE0\\s*)?(?:\uD30C\uC77C(?:\\s*(?:\uC218\uC815|\uBCC0\uACBD))?|\uC124\uCE58|\uAD50\uD6C8\\s*\uC800\uC7A5)(?:(?:\\s*[/\u00B7,]\\s*|\\s*(?:\uBC0F|\uC640|\uACFC)\\s*)(?:\uD30C\uC77C(?:\\s*(?:\uC218\uC815|\uBCC0\uACBD))?|\uC124\uCE58|\uAD50\uD6C8\\s*\uC800\uC7A5))*(?:\uC740|\uB294|\uC744|\uB97C)?\\s*\uD558\uC9C0\\s*\uB9C8(?:\uC138\uC694|\uC2ED\uC2DC\uC624|\uB77C)$/u;\n const privateOutput = /^(?:\uC778\uC99D\uC815\uBCF4|(?:\uB300\uD654\\s*)?\uB85C\uADF8\\s*\uC804\uCCB4)(?:(?:\\s*[/\u00B7,]\\s*|\\s*(?:\uB098|\uC774\uB098|\uBC0F|\uC640|\uACFC)\\s*)(?:\uC778\uC99D\uC815\uBCF4|(?:\uB300\uD654\\s*)?\uB85C\uADF8\\s*\uC804\uCCB4))*(?:\uC740|\uB294|\uC744|\uB97C)?\\s*\uCD9C\uB825\uD558\uC9C0\\s*\uB9C8(?:\uC138\uC694|\uC2ED\uC2DC\uC624|\uB77C)$/u;\n const english = /^(?:please\\s+)?(?:do[ -]+not|don't|never)\\s+(?:(?:call|use|invoke)\\s+tools|(?:edit|modify|change)\\s+files)(?:\\s+(?:or|and)\\s+(?:(?:call|use|invoke)\\s+tools|(?:edit|modify|change)\\s+files))*$/iu;\n // Split only at complete sentence/line boundaries, never inside foo.ts or a\n // code symbol. A clause attached with \"but\" is deliberately left ambiguous.\n return query.split(/(?<=[.!?;])(?=\\s)|[\\r\\n]+/u).filter(clause => {\n const statement = clause.trim().replace(/[.!?;]$/, '').trim();\n return !korean.test(statement) && !english.test(statement) && !readOnly.test(statement) && !privateOutput.test(statement);\n }).join(' ');\n}\n\nconst lessonSymbolTokens = (value: string): string[] => value.match(/\\b[A-Za-z][A-Za-z0-9_$]*(?:[./:-][A-Za-z0-9_$]+)*/g) ?? [];\n\n/** A sole exact code symbol in the subject is stronger than question boilerplate.\n * Keep this lesson-only: transcript alignment retains its independent policy. */\nfunction hasExactLessonSubject(query: string, lesson: LessonEvidenceInput): boolean {\n const anchors = [...new Set(lessonSymbolTokens(query).filter((token) => /[a-z][A-Z]|[_$./:-]|\\d/.test(token)))];\n if (anchors.length !== 1 || !/[a-z][A-Z]/.test(anchors[0])) return false;\n // Do not turn a mention of a forbidden/alternative procedure into a match.\n if (/\\b(?:not|without|skip|omit|ignore|never)\\b|\uD558\uC9C0\\s*\uC54A|\uB9D0\uACE0|\uAE08\uC9C0|\uAC74\uB108\uB6F0|\uBB34\uC2DC/iu.test(query)) return false;\n return lessonSymbolTokens([lesson.name, lesson.trigger ?? ''].join(' ')).includes(anchors[0]);\n}\n\nexport function scoreLessonEvidence(\n query: string,\n lesson: LessonEvidenceInput\n): HookMemoryCandidate | null {\n query = lessonScoringQuery(query);\n if (!query.trim() || isExplicitlyProhibitedLessonQuery(query)) return null;\n const content = formatLessonContent(lesson);\n const queriedSymbols = lessonSymbolTokens(query).filter((token) => /[a-z][A-Z]/.test(token));\n const contentSymbols = new Set(lessonSymbolTokens(content));\n if (queriedSymbols.some((symbol) => !contentSymbols.has(symbol))) return null;\n const exactSubject = hasExactLessonSubject(query, lesson);\n if (!exactSubject && !hasQueryMemoryAlignment(query, content, 2)) return null;\n\n // A narrow technical noun equivalence, confined to lesson scoring. It does\n // not lower the overlap gate: a product mention alone still cannot match.\n const lessonTerms = (value: string) => [...new Set(meaningfulTerms(value)\n .map(term => term === '\uBC84\uC804' || term === 'versions' ? 'version' : term))];\n const queryTerms = lessonTerms(query);\n const contentTerms = new Set(lessonTerms(content));\n const overlap = queryTerms.filter((term) => contentTerms.has(term)).length;\n // A query with no meaningful term (\"\uC751 \uC9C4\uD589 \uD574\uC918\") has nothing to match; without\n // this, min(3, 0) lets every lesson through at the base score.\n if (!exactSubject && (queryTerms.length === 0 || overlap < Math.min(3, queryTerms.length))) return null;\n\n const coverage = exactSubject ? 1 : overlap / Math.max(1, Math.min(queryTerms.length, 8));\n const anchors = identifierAnchors(query);\n const lowered = content.toLowerCase();\n const matchedAnchors = anchors.filter((anchor) => lowered.includes(anchor.toLowerCase())).length;\n const anchorCoverage = exactSubject ? 1 : anchors.length === 0 ? 0 : matchedAnchors / anchors.length;\n if (!exactSubject && anchors.length >= 2 && matchedAnchors < Math.ceil(anchors.length * 0.6)) return null;\n\n const confidencePrior = Math.min(0.05, Math.max(0, lesson.confidence) * 0.05);\n const score = Math.min(0.98, 0.5 + coverage * 0.28 + anchorCoverage * 0.12 + confidencePrior);\n\n return {\n id: lesson.lessonId,\n type: 'lesson',\n content: [\n lesson.steps.length > 8 && `[Partial lesson; retrieve the full body with mem-lesson-get lessonId=${lesson.lessonId} before applying]`,\n lesson.scope && `Scope: ${lesson.scope}`,\n ...(lesson.validation ?? []).map((value) => `Validate: ${value}`),\n lesson.reconsiderWhen && `Reconsider: ${lesson.reconsiderWhen}`,\n lesson.validVersions?.length && `Versions: ${lesson.validVersions.join(', ')}`,\n ...(lesson.failureModes ?? []).map((value) => `Caution: ${value}`),\n formatLessonContent({ ...lesson, failureModes: [] })\n ].filter(Boolean).join('\\n'),\n score,\n source: 'lesson'\n };\n}\n\nfunction formatLessonContent(lesson: LessonEvidenceInput): string {\n const parts = [lesson.name];\n if (lesson.trigger) parts.push(`\uC801\uC6A9 \uC2DC\uC810: ${lesson.trigger}`);\n if (lesson.steps.length > 0) {\n parts.push(lesson.steps.slice(0, 8).map((step) => `- ${step}`).join('\\n'));\n }\n if (lesson.failureModes && lesson.failureModes.length > 0) {\n parts.push(`\uC8FC\uC758: ${lesson.failureModes.slice(0, 4).join(' / ')}`);\n }\n return parts.join('\\n');\n}\n\nexport function isPromptOnlySessionSummary(content: string): boolean {\n // The Korean branch is anchored on the rule-based generator's own prefix\n // (\"[date] N\uD134 \uC138\uC158\", see summary-deriver.ts) rather than on the optional\n // \"\uC8FC\uC694 \uC791\uC5C5:\" line, which it omits for a zero-prompt session.\n return /Session with \\d+ user prompts?|Topics discussed:|\\[\\d{4}-\\d{2}-\\d{2}\\]\\s*\\d+\uD134 \uC138\uC158/iu.test(content);\n}\n\nfunction isDiagnosticQuery(query: string): boolean {\n return /(?:\uC6D0\uC778|\uC65C|\uC2E4\uD328|\uC624\uB958|\uC5D0\uB7EC|\uC7A5\uC560|CrashLoopBackOff)|\\b(?:cause|failure|failed|error|incident|diagnos)/iu.test(query);\n}\n\nfunction hasDiagnosticOutcome(content: string): boolean {\n return /(?:\uC6D0\uC778|\uADFC\uBCF8|\uB54C\uBB38|\uBD88\uC77C\uCE58|\uC2E4\uD328|\uC624\uB958|\uC608\uC678|\uD574\uACB0|\uC870\uCE58|\uB9AC\uBC0B|\uD55C\uB3C4)|\\b(?:cause|because|failure|failed|error|exception|mismatch|resolved|fix)/iu.test(content);\n}\n\nfunction entityAnchors(value: string): string[] {\n return Array.from(new Set(\n (value.match(/[A-Za-z][A-Za-z0-9_./:-]*/g) ?? [])\n .map((term) => term.toLowerCase())\n .filter((term) => term.length >= 2 && !LOW_SIGNAL_QUERY_TERMS.has(term))\n ));\n}\n\nfunction isContinuationQuery(query: string): boolean {\n return /Previous user:|Previous assistant:|\\b(?:continue|resume|carry on|pick up)\\b|(?:\uC774\uC5B4\uC11C|\uACC4\uC18D|\uADF8\uAC70|\uC544\uAE4C|\uC9C0\uB09C\uBC88)/iu.test(query);\n}\n\nfunction hasQueryMemoryAlignment(query: string, content: string, minimumOverlap: number = 2): boolean {\n const queryTerms = meaningfulTerms(query);\n // Short follow-ups are resolved through session context; requiring a lexical\n // overlap there would suppress legitimate \"fix it\" continuations.\n if (queryTerms.length < 2) return true;\n const contentTerms = new Set(meaningfulTerms(content));\n const requiredAnchors = identifierAnchors(query);\n const normalizedContent = content.toLowerCase();\n if (requiredAnchors.length > 0 && !requiredAnchors.some((anchor) => normalizedContent.includes(anchor.toLowerCase()))) {\n return false;\n }\n // A single overlap is often a generic verb that escaped tokenization (for\n // example, \"\uC54C\uB824\uC918\"). Requiring two strong terms makes this an intentional\n // no-match gate instead of a weak semantic-score tie breaker.\n // Question boilerplate is removed by meaningfulTerms. This matters for\n // short queries: \"\uB300\uAE30\" plus \"\uC5B4\uB5BB\uAC8C\" previously looked like two strong\n // overlaps between an astronomy question and an unrelated CI incident.\n return queryTerms.filter((term) => contentTerms.has(term)).length >= minimumOverlap;\n}\n\nfunction identifierAnchors(value: string): string[] {\n return (value.match(/[A-Za-z0-9_./:-]+/g) ?? [])\n .filter((term) => /[A-Za-z0-9]/.test(term) && term.length >= 2)\n .filter((term) => /\\d|[_./:-]/.test(term))\n .filter((term) => !/^\\d{1,2}$/.test(term));\n}\n\nfunction meaningfulTerms(value: string): string[] {\n return Array.from(new Set(\n (value.toLowerCase().match(/[a-z0-9\uAC00-\uD7A3]+/g) ?? [])\n .map(normalizeTerm)\n .filter((term) => term.length >= 2 && !LOW_SIGNAL_QUERY_TERMS.has(term))\n ));\n}\n\n/**\n * specs/lesson-learning-reliability R3 \u2014 strip the Korean case particles that\n * make a paraphrase (\"\uD3EC\uD2B8 \uCDA9\uB3CC\uB85C\") miss the stored wording (\"\uD3EC\uD2B8 \uCDA9\uB3CC\"). The\n * same heuristic runs over query and content; suffix collisions remain possible.\n * The two-character floor keeps short nouns that end in a particle\n * syllable (\"\uACBD\uB85C\", \"\uC815\uB3C4\") intact instead of collapsing them to one letter.\n */\nconst KOREAN_PARTICLE_SUFFIX =\n /(?:\uC73C\uB85C|\uC5D0\uC11C|\uC5D0\uAC8C|\uD55C\uD14C|\uAE4C\uC9C0|\uBD80\uD130|\uB9C8\uB2E4|\uCC98\uB7FC|\uBCF4\uB2E4|\uC740|\uB294|\uC774|\uAC00|\uC744|\uB97C|\uC5D0|\uC758|\uC640|\uACFC|\uB3C4|\uB85C)$/u;\n\nfunction normalizeTerm(value: string): string {\n const stripped = value.replace(KOREAN_PARTICLE_SUFFIX, '');\n return stripped.length >= 2 ? stripped : value;\n}\n\nexport function summarizeHookInjectionConfidence(candidates: HookMemoryCandidate[]): 'none' | 'medium' | 'high' {\n const scores = candidates\n .map((candidate) => candidate.score)\n .filter((score): score is number => typeof score === 'number' && Number.isFinite(score));\n if (scores.length === 0) return 'none';\n\n const maxScore = Math.max(...scores);\n if (maxScore >= 0.8) return 'high';\n if (maxScore >= 0.65) return 'medium';\n return 'none';\n}\n\nfunction isHookInjectableMemory(candidate: HookMemoryCandidate, policy: HookInjectionPolicy): boolean {\n if (typeof candidate.score !== 'number' || !Number.isFinite(candidate.score)) {\n return false;\n }\n\n return candidate.score >= thresholdFor(candidate, policy);\n}\n\nfunction thresholdFor(candidate: HookMemoryCandidate, policy: HookInjectionPolicy): number {\n if (candidate.source === 'keyword') {\n return candidate.fallback\n ? policy.fallbackKeywordMinScore\n : policy.keywordMinScore;\n }\n if (\n candidate.source === 'semantic'\n || candidate.source === 'graduated'\n || candidate.source === 'episode'\n || candidate.source === 'lesson'\n ) {\n return policy.semanticMinScore;\n }\n return policy.minScore;\n}\n\nfunction readScoreThreshold(value: string | undefined, fallback: number): number {\n return readNumber(value, fallback, { min: 0, max: 1 });\n}\n\nfunction readNumber(\n value: string | undefined,\n fallback: number,\n bounds?: { min?: number; max?: number }\n): number {\n if (value === undefined || value.trim() === '') return fallback;\n const parsed = Number(value);\n if (!Number.isFinite(parsed)) return fallback;\n if (bounds?.min !== undefined && parsed < bounds.min) return fallback;\n if (bounds?.max !== undefined && parsed > bounds.max) return fallback;\n return parsed;\n}\n", "import type { MemoryLesson } from '../../core/types.js';\nimport { scoreLessonEvidence } from '../../adapters/claude/hooks/prompt-injection-policy.js';\nexport { isExplicitlyProhibitedLessonQuery } from '../../adapters/claude/hooks/prompt-injection-policy.js';\n\n/**\n * specs/lesson-recall-hooks R5 \u00B7 specs/lesson-learning-reliability R3 \u2014\n * order curated lessons for a context pack.\n *\n * With a query, lessons that lexically cover it come first (same scorer as the\n * per-turn hook, so the two surfaces agree on what \"relevant\" means) and\n * nothing else is returned: an evidence section answering a question must not\n * pad its remaining slots with lessons the question never touched. Without a\n * query this is a plain slice \u2014 the queryless exploration index.\n */\nexport function rankCuratedLessons(\n lessons: readonly MemoryLesson[],\n query: string | undefined,\n limit: number\n): MemoryLesson[] {\n const trimmed = query?.trim();\n if (!trimmed) return lessons.slice(0, limit);\n return lessons\n .map((lesson, index) => ({\n lesson,\n index,\n score: scoreLessonEvidence(trimmed, {\n lessonId: lesson.lessonId,\n name: lesson.name,\n trigger: lesson.trigger,\n steps: lesson.steps,\n failureModes: lesson.failureModes,\n confidence: lesson.confidence\n })?.score ?? null\n }))\n .filter((entry): entry is typeof entry & { score: number } => entry.score !== null)\n .sort((a, b) => b.score - a.score || a.index - b.index)\n .slice(0, limit)\n .map((entry) => entry.lesson);\n}\n", "import type { MemoryLesson } from '../../core/types.js';\nimport { getDefaultEmbedder, type Embedder } from '../vector/embedder.js';\nimport { isExplicitlyProhibitedLessonQuery, rankCuratedLessons } from './lesson-ranking.js';\n\n// Frozen ONLY from independent calibration-v3 (20 lessons / 100 queries).\n// The deterministic grid and fixture hash are recorded in its raw result.\n// Release stays disabled until the unchanged held-out gate also passes.\nexport const HYBRID_LESSON_GATE = { enabled: false, absoluteCosine: 0.829, top1Margin: 0.026 } as const;\nexport type HybridLessonStatus = 'cold' | 'warming' | 'ready' | 'calibration_rejected' | 'failed';\nconst vectors = new Map<string, number[]>();\nlet status: HybridLessonStatus = 'cold';\nlet warming: Promise<void> | undefined;\nconst pending = new Map<string, { lesson: MemoryLesson; embedder: Embedder }>();\nconst MAX_VECTORS = 2_048;\n\nconst text = (lesson: MemoryLesson) => [lesson.name, lesson.trigger, ...lesson.steps, ...lesson.failureModes].filter(Boolean).join('\\n');\nconst usesE5Prefix = (embedder: Embedder) => /(?:^|\\/)multilingual-e5-/i.test(embedder.getModelName());\nconst passage = (lesson: MemoryLesson, embedder: Embedder) => usesE5Prefix(embedder) ? `passage: ${text(lesson)}` : text(lesson);\nconst queryText = (query: string, embedder: Embedder) => usesE5Prefix(embedder) ? `query: ${query}` : query;\nconst keyFor = (lesson: MemoryLesson, embedder: Embedder) => `${embedder.getModelName()}:${usesE5Prefix(embedder) ? 'e5-prefix-v2' : 'plain-v1'}:${lesson.projectHash}:${lesson.lessonId}:${lesson.revision}`;\nconst cosine = (a: number[], b: number[]) => a.reduce((sum, value, index) => sum + value * (b[index] ?? 0), 0);\nconst supportedSafetyOrFailureState = /\\b(?:must|should)\\s+not\\s+trust\\b|\\b(?:server|service|process|worker|daemon|request|connection|build|test)\\s+does\\s+not\\s+(?:start|respond|connect|complete|pass)\\b|\uBBFF\uC9C0\\s*\uB9D0\uACE0/giu;\n\nexport function hybridLessonStatus(): HybridLessonStatus { return status; }\nconst experimentEnabled = () => process.env.CLAUDE_MEMORY_LESSON_HYBRID_EXPERIMENT === 'true';\nexport function isSemanticRescueEligible(query: string): boolean {\n if (isExplicitlyProhibitedLessonQuery(query)) return false;\n // Remove only unambiguous safety/failure clauses before applying the existing\n // conservative guard, so a second contraindication cannot be bypassed.\n const remaining = query.replace(supportedSafetyOrFailureState, ' ');\n return !/\\b(?:not|without|skip|ignore|do[ -]?not|don't|never)\\b|\uD558\uC9C0\\s*\uC54A|\uD558\uC9C0\uB9C8|\uB9D0\uACE0|\uAE08\uC9C0|\uAC74\uB108\uB6F0|\uBB34\uC2DC/iu.test(remaining);\n}\nexport function warmHybridLessonCache(lessons: readonly MemoryLesson[], embedder?: Embedder): Promise<void> {\n if (lessons.length === 0) return Promise.resolve();\n if (!experimentEnabled()) { status = 'calibration_rejected'; return Promise.resolve(); }\n const activeEmbedder = embedder ?? getDefaultEmbedder();\n if (lessons.length > MAX_VECTORS) return Promise.resolve();\n for (const lesson of lessons) pending.set(keyFor(lesson, activeEmbedder), { lesson, embedder: activeEmbedder });\n if (warming) return warming;\n status = 'warming';\n warming = (async () => {\n while (pending.size) {\n const batch = [...pending.entries()]; pending.clear();\n for (const [key, item] of batch) { await item.embedder.initialize(); if (!vectors.has(key)) { vectors.set(key, (await item.embedder.embed(passage(item.lesson, item.embedder))).vector); while (vectors.size > MAX_VECTORS) vectors.delete(vectors.keys().next().value!); } }\n }\n status = 'ready';\n })().catch(() => { status = 'failed'; }).finally(() => { warming = undefined; });\n return warming;\n}\n\n/** Lexical matches always win. Cold processes start background warmup and return lexical-only. */\nexport async function rankCuratedLessonsHybrid(lessons: readonly MemoryLesson[], query: string | undefined, limit: number, embedder?: Embedder): Promise<MemoryLesson[]> {\n if (lessons.length === 0) return [];\n const lexical = rankCuratedLessons(lessons, query, limit);\n if (lexical.length || !query?.trim()) return lexical;\n if (!experimentEnabled()) { status = 'calibration_rejected'; return []; }\n if (!isSemanticRescueEligible(query)) return [];\n const activeEmbedder = embedder ?? getDefaultEmbedder();\n if (status === 'cold') { void warmHybridLessonCache(lessons, activeEmbedder); return []; }\n if (status !== 'ready') return [];\n if (lessons.some((lesson) => !vectors.has(keyFor(lesson, activeEmbedder)))) { void warmHybridLessonCache(lessons, activeEmbedder); return []; }\n const snapshot = lessons.map((lesson) => ({ lesson, vector: vectors.get(keyFor(lesson, activeEmbedder))! }));\n const queryVector = (await activeEmbedder.embed(queryText(query, activeEmbedder))).vector;\n const ranked = snapshot.map(({ lesson, vector }) => ({ lesson, score: cosine(queryVector, vector) }));\n ranked.sort((a, b) => b.score - a.score);\n const [first, second] = ranked;\n return first && first.score >= HYBRID_LESSON_GATE.absoluteCosine && first.score - (second?.score ?? 0) >= HYBRID_LESSON_GATE.top1Margin ? [first.lesson] : [];\n}\n", "/**\n * Private Tag Parser\n * Parses and removes <private> tags from content\n */\n\nexport interface PrivateSection {\n start: number;\n end: number;\n content: string;\n format: 'xml' | 'bracket' | 'comment';\n}\n\nexport interface ParseResult {\n filtered: string;\n sections: PrivateSection[];\n stats: {\n count: number;\n totalLength: number;\n };\n}\n\nexport interface ParseOptions {\n formats: Array<'xml' | 'bracket' | 'comment'>;\n marker: string;\n}\n\n// Tag patterns for different formats\nconst TAG_PATTERNS: Record<string, RegExp> = {\n xml: /<private>([\\s\\S]*?)<\\/private>/gi,\n bracket: /\\[private\\]([\\s\\S]*?)\\[\\/private\\]/gi,\n comment: /<!--\\s*private\\s*-->([\\s\\S]*?)<!--\\s*\\/private\\s*-->/gi\n};\n\n/**\n * Parse and remove private tags from text\n */\nexport function parsePrivateTags(\n text: string,\n options: ParseOptions\n): ParseResult {\n const sections: PrivateSection[] = [];\n let filtered = text;\n\n // Find all private sections for each format\n for (const format of options.formats) {\n const pattern = TAG_PATTERNS[format];\n if (!pattern) continue;\n\n // Reset lastIndex for global regex\n pattern.lastIndex = 0;\n\n let match;\n while ((match = pattern.exec(text)) !== null) {\n sections.push({\n start: match.index,\n end: match.index + match[0].length,\n content: match[1],\n format: format as PrivateSection['format']\n });\n }\n }\n\n // Remove all tags and replace with marker\n for (const format of options.formats) {\n const pattern = TAG_PATTERNS[format];\n if (!pattern) continue;\n\n // Need to create new regex for replacement (global flag issues)\n const replacePattern = new RegExp(pattern.source, 'gi');\n\n filtered = filtered.replace(replacePattern, (_match, content: string) => {\n // Empty tags are completely removed\n if (!content.trim()) return '';\n return options.marker;\n });\n }\n\n return {\n filtered,\n sections,\n stats: {\n count: sections.length,\n totalLength: sections.reduce((sum, s) => sum + s.content.length, 0)\n }\n };\n}\n\n/**\n * Parse private tags safely, protecting code blocks\n */\nexport function parsePrivateTagsSafe(\n text: string,\n options: ParseOptions\n): ParseResult {\n // 1. Extract and protect code blocks\n const codeBlocks: string[] = [];\n const textWithPlaceholders = text.replace(\n /```[\\s\\S]*?```/g,\n (match) => {\n codeBlocks.push(match);\n return `__CODE_BLOCK_${codeBlocks.length - 1}__`;\n }\n );\n\n // Also protect inline code\n const inlineCode: string[] = [];\n const textWithAllPlaceholders = textWithPlaceholders.replace(\n /`[^`]+`/g,\n (match) => {\n inlineCode.push(match);\n return `__INLINE_CODE_${inlineCode.length - 1}__`;\n }\n );\n\n // 2. Parse private tags\n const result = parsePrivateTags(textWithAllPlaceholders, options);\n\n // 3. Restore inline code\n result.filtered = result.filtered.replace(\n /__INLINE_CODE_(\\d+)__/g,\n (_, idx) => inlineCode[Number(idx)]\n );\n\n // 4. Restore code blocks\n result.filtered = result.filtered.replace(\n /__CODE_BLOCK_(\\d+)__/g,\n (_, idx) => codeBlocks[Number(idx)]\n );\n\n return result;\n}\n\n/**\n * Check if text has unclosed private tags\n */\nexport function hasUnmatchedOpenTag(text: string): boolean {\n // Check for opening tags without closing\n const openXml = (text.match(/<private>/gi) || []).length;\n const closeXml = (text.match(/<\\/private>/gi) || []).length;\n\n const openBracket = (text.match(/\\[private\\]/gi) || []).length;\n const closeBracket = (text.match(/\\[\\/private\\]/gi) || []).length;\n\n return openXml !== closeXml || openBracket !== closeBracket;\n}\n", "/**\n * Privacy Filter\n * Combines pattern-based filtering with private tag parsing\n */\n\nimport { parsePrivateTagsSafe, hasUnmatchedOpenTag } from './tag-parser.js';\nimport type { Config } from '../types.js';\n\nexport interface FilterResult {\n content: string;\n metadata: {\n hasPrivateTags: boolean;\n privateTagCount: number;\n patternMatchCount: number;\n originalLength: number;\n filteredLength: number;\n hasUnmatchedTags: boolean;\n };\n}\n\n// Sensitive data patterns\n/**\n * Rejects values that are code rather than a credential: an already-redacted\n * marker, a type annotation, an arrow function, or an opening bracket.\n */\nconst NOT_A_SECRET_VALUE =\n '(?!\\\\[REDACTED\\\\])(?![({\\\\[]|=>|\\\\s*$)'\n // The optional quote matters: `apiKey: \"string\"` is still a type, not a key.\n + '(?![\\'\"]?(?:string|number|boolean|any|unknown|void|never|null|undefined|true|false'\n + '|Promise|Record|Array|Partial|Readonly)\\\\b)'\n // `token = json.dumps(...)` assigns in code: the secret would be the result\n // of the call, not this expression.\n + '(?![A-Za-z_$][\\\\w.$]*\\\\s*\\\\()'\n // `var token = ++fitRetryToken` \u2014 a credential literal never starts with a\n // unary/increment operator, so this is unambiguously a variable reference.\n + '(?!\\\\+\\\\+|--|!|~)'\n // `const TOKEN = process.env.TOKEN || randomBytes(32)\u2026` reads the variable\n // rather than containing it \u2014 a very common Node.js pattern in this kind of\n // codebase, and unambiguous because a literal secret is never spelled\n // `process.env.<NAME>`.\n + '(?!process\\\\.env\\\\.)';\n\nconst SENSITIVE_PATTERNS = [\n // Credential-bearing URLs/connection strings with userinfo before the host.\n // Redact the whole URI so usernames, credentials, hosts, paths, and query\n // params do not leak either.\n /\\b[a-z][a-z0-9+.-]*:\\/\\/[^\\s'\"`<>/@]+@[^\\s'\"`<>]+/gi,\n // Two guards keep source code out of these rules. Without them a stored\n // discussion of real code gets mangled \u2014 `getAccessToken: () => \u2026` became\n // `getAccess[REDACTED] => \u2026` on live data.\n //\n // The leading lookbehind rejects camelCase identifiers (`getAccessToken:`),\n // while underscore/dash forms (`access_token=\u2026`) still match through the\n // optional prefix group. The trailing guard rejects values that are plainly\n // code rather than a secret: a type annotation, an arrow function, or an\n // opening bracket.\n new RegExp(`(?<![A-Za-z0-9])(?:[\\\\w.-]+[-_])?password\\\\s*[:=]\\\\s*${NOT_A_SECRET_VALUE}['\"]?[^\\\\s'\"]+`, 'gi'),\n new RegExp(`(?<![A-Za-z0-9])(?:[\\\\w.-]+[-_])?api[-_]?key\\\\s*[:=]\\\\s*${NOT_A_SECRET_VALUE}['\"]?[^\\\\s'\"]+`, 'gi'),\n new RegExp(`(?<![A-Za-z0-9])(?:[\\\\w.-]+[-_])?secret\\\\s*[:=]\\\\s*${NOT_A_SECRET_VALUE}['\"]?[^\\\\s'\"]+`, 'gi'),\n new RegExp(`(?<![A-Za-z0-9])(?:[\\\\w.-]+[-_])?token\\\\s*[:=]\\\\s*${NOT_A_SECRET_VALUE}['\"]?[^\\\\s'\"]+`, 'gi'),\n // camelCase keys are excluded above because `accessToken: () => \u2026` is code.\n // But `accessToken: \"eyJhbGciOi\u2026\"` is a real credential, and the difference\n // is the value, not the key. A quoted, long, secret-shaped literal is the\n // one camelCase form worth redacting.\n /[A-Za-z0-9_.-]*(?:password|secret|token|api[-_]?key)\\s*[:=]\\s*['\"][A-Za-z0-9._\\-+/=]{12,}['\"]/gi,\n // \"Bearer token\", \"Bearer JWT\" and friends are how documentation names the\n // scheme, not a secret. On a real store the loose form matched 29 such\n // phrases against a single actual token, so the word after Bearer must not be\n // one of those nouns and the value has to be long enough to be a credential.\n /bearer\\s+(?!token\\b|jwt\\b|auth\\b|authentication\\b|access\\b|scheme\\b|header\\b|prefix\\b)[a-zA-Z0-9\\-_.]{16,}/gi,\n /AWS[_-]?ACCESS[_-]?KEY[_-]?ID\\s*[:=]\\s*['\"]?[A-Z0-9]+/gi,\n /AWS[_-]?SECRET[_-]?ACCESS[_-]?KEY\\s*[:=]\\s*['\"]?[^\\s'\"]+/gi,\n /-----BEGIN\\s+(RSA\\s+)?PRIVATE\\s+KEY-----[\\s\\S]*?-----END\\s+(RSA\\s+)?PRIVATE\\s+KEY-----/g,\n /ghp_[a-zA-Z0-9]{36}/g, // GitHub Personal Access Token\n /sk-[a-zA-Z0-9]{48}/g, // OpenAI API Key\n // Vendor-prefixed tokens. The `token\\s*[:=]` rule above only fires when a\n // token is introduced with a colon or equals sign, so a key pasted as prose\n // (\"hugging face token hf_\u2026 Invalid token\") slipped through untouched. These\n // prefixes are distinctive enough to match on their own.\n /\\bhf_[a-zA-Z0-9]{30,}/g, // Hugging Face access token\n /\\bgh[opsu]_[a-zA-Z0-9]{36,}/g, // GitHub OAuth/server/user tokens\n /\\bgithub_pat_[a-zA-Z0-9_]{50,}/g, // GitHub fine-grained PAT\n /\\bsk-ant-[a-zA-Z0-9_-]{20,}/g, // Anthropic API key\n /\\bglpat-[a-zA-Z0-9_-]{20,}/g, // GitLab personal access token\n /\\bxox[abprs]-[a-zA-Z0-9-]{10,}/g, // Slack tokens\n /\\bAKIA[0-9A-Z]{16}\\b/g, // AWS access key id\n];\n\nconst CLI_SECRET_OPTION_PATTERNS = [\n /(--(?:[a-z0-9]+[-_])*(?:password|secret|api[-_]?key|token|bearer)(?:[-_][a-z0-9]+)*(?:\\s+|=))(?:\"[^\"]*\"|'[^']*'|[^\\s'\"`<>]+)/gi\n];\n\nconst URL_FOLLOWING_SECRET_PATTERN = /((?:https?:\\/\\/[^\\s'\"`<>]+)\\s*\\r?\\n\\s*)([A-Za-z0-9!@#$%^&*._+\\-~:=/]{6,})(?=\\s*(?:\\r?\\n|$))/gi;\n\nfunction looksLikePastedSecret(value: string): boolean {\n // Reduce false positives for benign status words pasted after URLs while still\n // catching common dashboard passwords such as alpha-numeric throwaway secrets.\n return value.length >= 8 && /(?:\\d|[^A-Za-z0-9])/.test(value);\n}\n\nfunction maskUrlFollowingSecret(value: string): { content: string; count: number } {\n let count = 0;\n const content = value.replace(URL_FOLLOWING_SECRET_PATTERN, (_match, prefix: string, secret: string) => {\n if (!looksLikePastedSecret(secret)) return `${prefix}${secret}`;\n count++;\n return `${prefix}[REDACTED]`;\n });\n return { content, count };\n}\n\nfunction maskCliSecretOptions(value: string): { content: string; count: number } {\n let count = 0;\n let filtered = value;\n for (const pattern of CLI_SECRET_OPTION_PATTERNS) {\n pattern.lastIndex = 0;\n filtered = filtered.replace(pattern, (_match, prefix: string) => {\n count++;\n return `${prefix}[REDACTED]`;\n });\n }\n return { content: filtered, count };\n}\n\nfunction maskSensitiveString(value: string): string {\n let filtered = maskCliSecretOptions(value).content;\n for (const pattern of SENSITIVE_PATTERNS) {\n pattern.lastIndex = 0;\n filtered = filtered.replace(pattern, '[REDACTED]');\n }\n return filtered;\n}\n\n/**\n * Apply privacy filter to content\n */\nexport function applyPrivacyFilter(\n content: string,\n config: Config['privacy']\n): FilterResult {\n let filtered = content;\n let privateTagCount = 0;\n let patternMatchCount = 0;\n const hasUnmatchedTags = hasUnmatchedOpenTag(content);\n\n // 1. Private tag filtering\n if (config.privateTags?.enabled !== false) {\n const tagResult = parsePrivateTagsSafe(filtered, {\n formats: config.privateTags?.supportedFormats || ['xml'],\n marker: config.privateTags?.marker || '[PRIVATE]'\n });\n filtered = tagResult.filtered;\n privateTagCount = tagResult.stats.count;\n }\n\n // 2. CLI option filtering (`--password value`, `--password=value`, etc.)\n const cliResult = maskCliSecretOptions(filtered);\n filtered = cliResult.content;\n patternMatchCount += cliResult.count;\n\n // 3. Contextual paste filtering (URL followed by a password-looking line)\n const urlSecretResult = maskUrlFollowingSecret(filtered);\n filtered = urlSecretResult.content;\n patternMatchCount += urlSecretResult.count;\n\n // 4. Built-in sensitive pattern filtering\n for (const pattern of SENSITIVE_PATTERNS) {\n // Reset lastIndex for global regex\n pattern.lastIndex = 0;\n const matches = filtered.match(pattern);\n if (matches) {\n patternMatchCount += matches.length;\n filtered = filtered.replace(pattern, '[REDACTED]');\n }\n }\n\n // 3. Custom pattern filtering from config\n //\n // This mirrors the built-in keyword rules, so it needs the same value guard.\n // Without it the config list silently re-introduced every false positive the\n // built-ins had been taught to avoid \u2014 `token = json.dumps(payload)` was\n // still being rewritten to `[REDACTED]` through this loop alone.\n for (const patternStr of config.excludePatterns || []) {\n try {\n const regex = new RegExp(\n `(^|[^\\\\w-])(${patternStr})\\\\s*[:=]\\\\s*${NOT_A_SECRET_VALUE}['\"]?[^\\\\s'\"]+`,\n 'gi'\n );\n const matches = filtered.match(regex);\n if (matches) {\n patternMatchCount += matches.length;\n filtered = filtered.replace(regex, '$1[REDACTED]');\n }\n } catch {\n // Invalid regex pattern, skip\n }\n }\n\n // 4. Clean up consecutive markers\n filtered = filtered.replace(/(\\[PRIVATE\\]\\s*)+/g, '[PRIVATE]\\n');\n filtered = filtered.replace(/(\\[REDACTED\\]\\s*)+/g, '[REDACTED] ');\n\n return {\n content: filtered,\n metadata: {\n hasPrivateTags: privateTagCount > 0,\n privateTagCount,\n patternMatchCount,\n originalLength: content.length,\n filteredLength: filtered.length,\n hasUnmatchedTags\n }\n };\n}\n\n/**\n * Mask sensitive data in tool input (recursively)\n */\nexport function maskSensitiveInput(\n input: Record<string, unknown>\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(input)) {\n // Check if key suggests sensitive data\n const sensitiveKeys = ['password', 'secret', 'key', 'token', 'auth', 'credential'];\n const isSensitiveKey = sensitiveKeys.some(k =>\n key.toLowerCase().includes(k)\n );\n\n if (isSensitiveKey && typeof value === 'string') {\n result[key] = '[REDACTED]';\n } else if (typeof value === 'string') {\n // Apply pattern filtering to string values\n result[key] = maskSensitiveString(value);\n } else if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n result[key] = maskSensitiveInput(value as Record<string, unknown>);\n } else if (Array.isArray(value)) {\n result[key] = value.map(item => {\n if (typeof item === 'string') {\n return isSensitiveKey ? '[REDACTED]' : maskSensitiveString(item);\n }\n return typeof item === 'object' && item !== null\n ? maskSensitiveInput(item as Record<string, unknown>)\n : item;\n });\n } else {\n result[key] = value;\n }\n }\n\n return result;\n}\n\n/**\n * Truncate output with head + tail strategy\n */\nexport function truncateOutput(\n output: string,\n options: { maxLength?: number; maxLines?: number }\n): string {\n const { maxLength = 10000, maxLines = 100 } = options;\n\n // Split into lines\n const lines = output.split('\\n');\n\n // Apply line limit first\n if (lines.length > maxLines) {\n const headLines = Math.ceil(maxLines / 2);\n const tailLines = Math.floor(maxLines / 2);\n const head = lines.slice(0, headLines);\n const tail = lines.slice(-tailLines);\n const truncatedLines = [\n ...head,\n `\\n... [${lines.length - maxLines} lines truncated] ...\\n`,\n ...tail\n ];\n output = truncatedLines.join('\\n');\n }\n\n // Apply character limit\n if (output.length > maxLength) {\n const headChars = Math.ceil(maxLength / 2);\n const tailChars = Math.floor(maxLength / 2);\n output = output.slice(0, headChars) +\n `\\n... [${output.length - maxLength} characters truncated] ...\\n` +\n output.slice(-tailChars);\n }\n\n return output;\n}\n", "import { z } from 'zod';\n\nimport type { SQLiteDatabase } from '../sqlite-wrapper.js';\nimport {\n canonicalMemoryAssetId,\n isCanonicalMemoryAssetRegistration\n} from './memory-asset-catalog-service.js';\nimport { MemoryAssetPermissionService } from './memory-asset-permission-service.js';\nimport { MemoryAssetRepository } from './memory-asset-repository.js';\nimport type { MemoryAssetPermissionSource } from './memory-asset-permissions.js';\n\nexport const CANONICAL_MEMORY_PERMISSION_MODE_ENV = 'CLAUDE_MEMORY_ASSET_PERMISSION_MODE';\n\nexport const CanonicalMemoryPermissionModeSchema = z.enum(['legacy', 'registered', 'strict']);\nexport type CanonicalMemoryPermissionMode = z.infer<typeof CanonicalMemoryPermissionModeSchema>;\n\nconst RequesterActorIdSchema = z.string().trim().min(1).max(240);\n\nconst CanonicalMemoryAccessInputSchema = z.object({\n projectHash: z.string().trim().min(1).max(240),\n canonicalType: z.enum(['lesson', 'core_memory_block']),\n canonicalId: z.string().trim().min(1).max(240),\n requesterActorId: z.string().trim().min(1).max(240).optional(),\n permission: z.enum(['read', 'write'])\n});\n\nexport interface CanonicalMemoryAccessDecision {\n allowed: boolean;\n mode: CanonicalMemoryPermissionMode;\n registered: boolean;\n source: MemoryAssetPermissionSource | 'legacy' | 'unregistered';\n}\n\nexport class CanonicalMemoryAccessDeniedError extends Error {\n readonly code = 'CANONICAL_MEMORY_ACCESS_DENIED';\n\n constructor() {\n super('permission denied for canonical memory access');\n this.name = 'CanonicalMemoryAccessDeniedError';\n }\n}\n\nexport function resolveCanonicalMemoryPermissionMode(\n env: NodeJS.ProcessEnv = process.env\n): CanonicalMemoryPermissionMode {\n const raw = env[CANONICAL_MEMORY_PERMISSION_MODE_ENV]?.trim().toLowerCase();\n if (!raw) return 'legacy';\n const parsed = CanonicalMemoryPermissionModeSchema.safeParse(raw);\n if (!parsed.success) {\n throw new Error(`${CANONICAL_MEMORY_PERMISSION_MODE_ENV} must be legacy, registered, or strict`);\n }\n return parsed.data;\n}\n\nexport class CanonicalMemoryAccessService {\n private readonly repository: MemoryAssetRepository;\n private readonly permissionService: MemoryAssetPermissionService;\n readonly mode: CanonicalMemoryPermissionMode;\n\n constructor(\n db: SQLiteDatabase,\n options: { mode?: CanonicalMemoryPermissionMode; env?: NodeJS.ProcessEnv } = {}\n ) {\n this.repository = new MemoryAssetRepository(db);\n this.permissionService = new MemoryAssetPermissionService(db);\n this.mode = options.mode ?? resolveCanonicalMemoryPermissionMode(options.env);\n }\n\n requireRequester(requesterActorId: string | undefined): void {\n if (this.mode === 'legacy') return;\n if (!requesterActorId) {\n throw new Error(`requesterActorId is required when ${CANONICAL_MEMORY_PERMISSION_MODE_ENV}=${this.mode}`);\n }\n RequesterActorIdSchema.parse(requesterActorId);\n }\n\n requireUnregisteredWrite(requesterActorId: string | undefined): CanonicalMemoryAccessDecision {\n this.requireRequester(requesterActorId);\n if (this.mode === 'strict') throw new CanonicalMemoryAccessDeniedError();\n return {\n allowed: true,\n mode: this.mode,\n registered: false,\n source: this.mode === 'legacy' ? 'legacy' : 'unregistered'\n };\n }\n\n check(input: unknown): CanonicalMemoryAccessDecision {\n const parsed = CanonicalMemoryAccessInputSchema.parse(input);\n const assetId = canonicalMemoryAssetId(parsed.canonicalType, parsed.canonicalId);\n const asset = this.repository.get(assetId, parsed.projectHash);\n const registered = Boolean(\n asset && isCanonicalMemoryAssetRegistration(asset, parsed.canonicalType, parsed.canonicalId)\n );\n\n if (this.mode === 'legacy') {\n return { allowed: true, mode: this.mode, registered, source: 'legacy' };\n }\n this.requireRequester(parsed.requesterActorId);\n\n if (!asset) {\n const allowed = this.mode === 'registered';\n return {\n allowed,\n mode: this.mode,\n registered: false,\n source: allowed ? 'unregistered' : 'none'\n };\n }\n\n // A deterministic id occupied by a non-canonical asset is a conflict, not\n // an unregistered fallback. Otherwise a caller could bypass protection by\n // creating an unrelated asset with the canonical id.\n if (!registered) {\n return { allowed: false, mode: this.mode, registered: false, source: 'none' };\n }\n\n const result = this.permissionService.check({\n projectHash: parsed.projectHash,\n assetId,\n requesterActorId: parsed.requesterActorId!,\n permission: parsed.permission\n });\n return {\n allowed: result.decision.allowed,\n mode: this.mode,\n registered: true,\n source: result.decision.source\n };\n }\n\n require(input: unknown): CanonicalMemoryAccessDecision {\n const decision = this.check(input);\n if (!decision.allowed) throw new CanonicalMemoryAccessDeniedError();\n return decision;\n }\n}\n", "import { z } from 'zod';\n\nimport { sqliteAll, sqliteGet, type SQLiteDatabase } from '../sqlite-wrapper.js';\nimport { MemoryAssetPermissionService } from './memory-asset-permission-service.js';\nimport { MemoryAssetRepository } from './memory-asset-repository.js';\nimport type { MemoryAsset, MemoryAssetStatus, MemoryAssetType } from './memory-asset-permissions.js';\n\nconst CatalogSyncInputSchema = z.object({\n projectHash: z.string().trim().min(1).max(240),\n requesterActorId: z.string().trim().min(1).max(240),\n apply: z.boolean().default(false),\n limit: z.number().int().positive().max(500).default(100)\n});\n\nexport type CanonicalMemoryAssetType = 'lesson' | 'core_memory_block';\nexport type MemoryAssetCatalogAction = 'create' | 'created' | 'exists' | 'conflict';\n\ninterface CanonicalAssetRow {\n canonical_type: CanonicalMemoryAssetType;\n canonical_id: string;\n title: string;\n canonical_status: MemoryAssetStatus;\n}\n\ninterface CountRow {\n count: number;\n}\n\nexport interface CanonicalMemoryAssetCandidate {\n canonicalType: CanonicalMemoryAssetType;\n canonicalId: string;\n assetId: string;\n assetType: MemoryAssetType;\n title: string;\n status: MemoryAssetStatus;\n sourceRefs: string[];\n metadata: Record<string, unknown>;\n}\n\nexport interface MemoryAssetCatalogItem {\n candidate: CanonicalMemoryAssetCandidate;\n action: MemoryAssetCatalogAction;\n reason?: string;\n}\n\nexport interface MemoryAssetCatalogSyncResult {\n dryRun: boolean;\n projectHash: string;\n totalCandidates: number;\n scanned: number;\n truncated: boolean;\n planned: number;\n created: number;\n existing: number;\n conflicts: number;\n items: MemoryAssetCatalogItem[];\n}\n\nexport function canonicalMemoryAssetId(type: CanonicalMemoryAssetType, canonicalId: string): string {\n return `${type}:${canonicalId.trim()}`;\n}\n\nexport function isCanonicalMemoryAssetRegistration(\n asset: MemoryAsset,\n canonicalType: CanonicalMemoryAssetType,\n canonicalId: string\n): boolean {\n const assetId = canonicalMemoryAssetId(canonicalType, canonicalId);\n const expectedAssetType: MemoryAssetType = canonicalType === 'lesson' ? 'lesson' : 'memory';\n return asset.assetId === assetId\n && asset.assetType === expectedAssetType\n && asset.sourceRefs.includes(assetId);\n}\n\nfunction rowToCandidate(row: CanonicalAssetRow): CanonicalMemoryAssetCandidate {\n const assetId = canonicalMemoryAssetId(row.canonical_type, row.canonical_id);\n return {\n canonicalType: row.canonical_type,\n canonicalId: row.canonical_id,\n assetId,\n assetType: row.canonical_type === 'lesson' ? 'lesson' : 'memory',\n title: row.title,\n status: row.canonical_status,\n // The canonical object retains its own evidence references. Keeping only\n // this pointer avoids duplicating event ids (and potential legacy data)\n // into the permission registry.\n sourceRefs: [assetId],\n metadata: {\n canonicalType: row.canonical_type,\n canonicalId: row.canonical_id\n }\n };\n}\n\nfunction matchesCanonicalAsset(asset: MemoryAsset, candidate: CanonicalMemoryAssetCandidate): boolean {\n return isCanonicalMemoryAssetRegistration(asset, candidate.canonicalType, candidate.canonicalId);\n}\n\nfunction classifyCandidate(\n repository: MemoryAssetRepository,\n projectHash: string,\n candidate: CanonicalMemoryAssetCandidate\n): MemoryAssetCatalogItem {\n const asset = repository.get(candidate.assetId, projectHash);\n if (!asset) return { candidate, action: 'create' };\n if (matchesCanonicalAsset(asset, candidate)) return { candidate, action: 'exists' };\n return {\n candidate,\n action: 'conflict',\n reason: 'deterministic asset id is already registered for another canonical source',\n };\n}\n\nexport class MemoryAssetCatalogService {\n private readonly repository: MemoryAssetRepository;\n private readonly permissionService: MemoryAssetPermissionService;\n\n constructor(private readonly db: SQLiteDatabase) {\n this.repository = new MemoryAssetRepository(db);\n this.permissionService = new MemoryAssetPermissionService(db);\n }\n\n async sync(input: unknown): Promise<MemoryAssetCatalogSyncResult> {\n const parsed = CatalogSyncInputSchema.parse(input);\n const candidates = this.listCanonicalCandidates(parsed.projectHash, parsed.limit);\n const totalCandidates = this.countCanonicalCandidates(parsed.projectHash);\n const items = candidates.map((candidate) => classifyCandidate(this.repository, parsed.projectHash, candidate));\n const planned = items.filter((item) => item.action === 'create').length;\n\n if (parsed.apply) {\n for (let index = 0; index < items.length; index++) {\n const item = items[index];\n if (item.action !== 'create') continue;\n\n // Recheck immediately before the write so a concurrent/idempotent\n // registration becomes an exists/conflict result instead of an overwrite.\n const current = classifyCandidate(this.repository, parsed.projectHash, item.candidate);\n if (current.action !== 'create') {\n items[index] = current;\n continue;\n }\n\n try {\n await this.permissionService.create({\n projectHash: parsed.projectHash,\n requesterActorId: parsed.requesterActorId,\n assetId: item.candidate.assetId,\n assetType: item.candidate.assetType,\n title: item.candidate.title,\n status: item.candidate.status,\n visibility: 'private',\n sourceRefs: item.candidate.sourceRefs,\n metadata: item.candidate.metadata\n });\n items[index] = { ...item, action: 'created' };\n } catch (error) {\n // Another connection may have won after the preflight check. Treat\n // the now-visible row idempotently; propagate unrelated failures.\n const raced = classifyCandidate(this.repository, parsed.projectHash, item.candidate);\n if (raced.action === 'create') throw error;\n items[index] = raced;\n }\n }\n }\n\n return this.buildResult(parsed.apply, parsed.projectHash, totalCandidates, planned, items);\n }\n\n private countCanonicalCandidates(projectHash: string): number {\n const lessonCount = sqliteGet<CountRow>(\n this.db,\n `SELECT COUNT(*) AS count FROM memory_lessons WHERE project_hash = ?`,\n [projectHash]\n )?.count ?? 0;\n const blockCount = sqliteGet<CountRow>(\n this.db,\n `SELECT COUNT(*) AS count FROM core_memory_blocks WHERE project_hash = ?`,\n [projectHash]\n )?.count ?? 0;\n return Number(lessonCount) + Number(blockCount);\n }\n\n private listCanonicalCandidates(projectHash: string, limit: number): CanonicalMemoryAssetCandidate[] {\n const rows = sqliteAll<CanonicalAssetRow>(\n this.db,\n `SELECT canonical_type, canonical_id, title, canonical_status\n FROM (\n SELECT\n 'lesson' AS canonical_type,\n lesson_id AS canonical_id,\n name AS title,\n 'active' AS canonical_status\n FROM memory_lessons\n WHERE project_hash = ?\n UNION ALL\n SELECT\n 'core_memory_block' AS canonical_type,\n block_key AS canonical_id,\n 'Core memory: ' || block_key AS title,\n CASE WHEN LENGTH(TRIM(content)) = 0 THEN 'archived' ELSE 'active' END AS canonical_status\n FROM core_memory_blocks\n WHERE project_hash = ?\n )\n ORDER BY canonical_type ASC, canonical_id ASC\n LIMIT ?`,\n [projectHash, projectHash, limit]\n );\n return rows.map(rowToCandidate);\n }\n\n private buildResult(\n apply: boolean,\n projectHash: string,\n totalCandidates: number,\n planned: number,\n items: MemoryAssetCatalogItem[]\n ): MemoryAssetCatalogSyncResult {\n return {\n dryRun: !apply,\n projectHash,\n totalCandidates,\n scanned: items.length,\n truncated: totalCandidates > items.length,\n planned,\n created: items.filter((item) => item.action === 'created').length,\n existing: items.filter((item) => item.action === 'exists').length,\n conflicts: items.filter((item) => item.action === 'conflict').length,\n items\n };\n }\n}\n", "/**\n * SQLite Wrapper with WAL Mode Support\n * Primary store for hooks - always available, no lock conflicts\n */\n\nimport Database from 'better-sqlite3';\nimport * as fs from 'fs';\nimport * as nodePath from 'path';\nimport { createSQLiteReadSnapshot } from './sqlite-read-snapshot.js';\n\nexport type SQLiteDatabase = Database.Database;\n\nexport interface SQLiteOptions {\n readonly?: boolean;\n walMode?: boolean;\n /**\n * Open an ephemeral copy instead of the live file. Only for diagnostics\n * that must guarantee zero writes inside the canonical memory root \u2014 the\n * copy costs O(database size) per open and the view is frozen at open time.\n * Long-lived readers (semantic daemon), per-hook readers, and machine-wide\n * scanners (maintenance) must NOT set this: a frozen view serves stale\n * memories and the copies dominate their runtime.\n */\n snapshot?: boolean;\n /** Internal-only snapshot parent; see createSQLiteReadSnapshot. */\n snapshotDirectory?: string;\n /** Used to reject unsafe snapshot placement inside canonical storage. */\n canonicalMemoryRoot?: string;\n}\n\n/**\n * Creates a new SQLite database with WAL mode\n */\nexport function createSQLiteDatabase(path: string, options?: SQLiteOptions): SQLiteDatabase {\n // Writable callers may create a new store. Read-only callers must never turn\n // a missing diagnostic target into an empty directory tree.\n const dir = nodePath.dirname(path);\n if (!options?.readonly && !fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n\n const snapshot = options?.readonly && options?.snapshot\n ? createSQLiteReadSnapshot(path, {\n snapshotDirectory: options.snapshotDirectory,\n canonicalMemoryRoot: options.canonicalMemoryRoot\n })\n : null;\n let db: SQLiteDatabase;\n try {\n db = new Database(snapshot?.databasePath ?? path, {\n readonly: options?.readonly ?? false,\n fileMustExist: options?.readonly ?? false,\n });\n } catch (error) {\n snapshot?.cleanup();\n throw error;\n }\n if (snapshot) {\n const closeSnapshotDatabase = db.close.bind(db);\n Object.defineProperty(db, 'close', {\n configurable: true,\n value: () => {\n try {\n return closeSnapshotDatabase();\n } finally {\n snapshot.cleanup();\n }\n }\n });\n }\n\n // Enable WAL mode for concurrent access (unless read-only)\n if (!options?.readonly && (options?.walMode ?? true)) {\n db.pragma('journal_mode = WAL');\n db.pragma('synchronous = NORMAL');\n db.pragma('busy_timeout = 5000');\n }\n\n return db;\n}\n\n// Per-connection prepared-statement cache. Re-running db.prepare() for every\n// call recompiles the SQL each time, which dominates the per-call cost on hot\n// paths (getEvent, keywordSearch, access tracking). Statements are scoped to\n// their database via a WeakMap so they are finalized/GC'd with the connection,\n// and SQLite transparently re-prepares them across schema changes.\nconst statementCache = new WeakMap<SQLiteDatabase, Map<string, Database.Statement>>();\n\nfunction prepareCached(db: SQLiteDatabase, sql: string): Database.Statement {\n let cache = statementCache.get(db);\n if (!cache) {\n cache = new Map();\n statementCache.set(db, cache);\n }\n let stmt = cache.get(sql);\n if (!stmt) {\n stmt = db.prepare(sql);\n cache.set(sql, stmt);\n }\n return stmt;\n}\n\n/**\n * Execute a statement that doesn't return rows (INSERT, UPDATE, DELETE)\n */\nexport function sqliteRun(\n db: SQLiteDatabase,\n sql: string,\n params: unknown[] = []\n): Database.RunResult {\n return prepareCached(db, sql).run(...params);\n}\n\n/**\n * Execute a query and return all rows\n */\nexport function sqliteAll<T = Record<string, unknown>>(\n db: SQLiteDatabase,\n sql: string,\n params: unknown[] = []\n): T[] {\n return prepareCached(db, sql).all(...params) as T[];\n}\n\n/**\n * Execute a query and return first row\n */\nexport function sqliteGet<T = Record<string, unknown>>(\n db: SQLiteDatabase,\n sql: string,\n params: unknown[] = []\n): T | undefined {\n return prepareCached(db, sql).get(...params) as T | undefined;\n}\n\n/**\n * Execute multiple statements (for schema creation)\n */\nexport function sqliteExec(db: SQLiteDatabase, sql: string): void {\n db.exec(sql);\n}\n\n/**\n * Close database connection\n */\nexport function sqliteClose(db: SQLiteDatabase): void {\n db.close();\n}\n\n/**\n * Run multiple statements in a transaction\n */\nexport function sqliteTransaction<T>(\n db: SQLiteDatabase,\n fn: () => T\n): T {\n return db.transaction(fn)();\n}\n\n/**\n * Safely converts a value to a Date object\n */\nexport function toDateFromSQLite(value: unknown): Date {\n if (value instanceof Date) return value;\n if (typeof value === 'number') return new Date(value);\n if (typeof value === 'string') {\n // SQLite datetime('now') stores UTC timestamps without an explicit timezone\n // (for example, \"2026-05-07 16:00:00\"). JavaScript treats that shape as\n // local time, which shifts dashboard time-window calculations on non-UTC\n // machines. Normalize SQLite's timezone-less UTC shape before parsing while\n // leaving ISO strings with an explicit offset/Z untouched.\n const trimmed = value.trim();\n if (/^\\d{4}-\\d{2}-\\d{2}[ T]\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?$/.test(trimmed)) {\n return new Date(trimmed.replace(' ', 'T') + 'Z');\n }\n return new Date(trimmed);\n }\n return new Date(String(value));\n}\n\n/**\n * Convert Date to ISO string for SQLite storage\n */\nexport function toSQLiteTimestamp(date: Date): string {\n return date.toISOString();\n}\n", "/**\n * Create an ephemeral copy for side-effect-free SQLite inspection.\n *\n * SQLite databases configured for WAL may create or update `-wal`/`-shm`\n * sidecars even when opened with SQLITE_OPEN_READONLY. Diagnostic readers use\n * this copy so all connection bookkeeping stays outside the canonical memory\n * root. The copied WAL, when present, keeps committed uncheckpointed rows in\n * the diagnostic snapshot.\n */\n\nimport * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\n\nexport interface SQLiteReadSnapshot {\n databasePath: string;\n cleanup(): void;\n}\n\nexport interface SQLiteReadSnapshotOptions {\n /** Internal-only parent for runtimes whose default temp directory is unavailable. */\n snapshotDirectory?: string;\n /** Snapshot storage must never be placed inside this canonical memory root. */\n canonicalMemoryRoot?: string;\n}\n\nexport function createSQLiteReadSnapshot(\n sourceDatabasePath: string,\n options: SQLiteReadSnapshotOptions = {}\n): SQLiteReadSnapshot {\n if (options.canonicalMemoryRoot) {\n rejectSourceOutsideOrThroughSymlink(sourceDatabasePath, options.canonicalMemoryRoot);\n }\n rejectSymlinkOrNonFile(sourceDatabasePath, 'source database');\n const sourceWalPath = `${sourceDatabasePath}-wal`;\n rejectSymlinkIfPresent(sourceWalPath, 'source WAL');\n\n const parent = path.resolve(options.snapshotDirectory ?? os.tmpdir());\n const realParent = fs.realpathSync(parent);\n if (!fs.lstatSync(realParent).isDirectory()) {\n throw snapshotError('SQLITE_SNAPSHOT_UNSAFE_LOCATION', 'Snapshot parent must be a local directory');\n }\n if (options.canonicalMemoryRoot) {\n const canonicalRoot = realPathIfPresent(path.resolve(options.canonicalMemoryRoot));\n if (isWithin(canonicalRoot, realParent)) {\n throw snapshotError('SQLITE_SNAPSHOT_UNSAFE_LOCATION', 'Snapshot directory must be outside canonical memory storage');\n }\n }\n\n const snapshotRoot = fs.mkdtempSync(path.join(realParent, 'cml-sqlite-read-'));\n const databasePath = path.join(snapshotRoot, 'events.sqlite');\n try {\n fs.copyFileSync(sourceDatabasePath, databasePath);\n copyIfLocalFile(sourceWalPath, `${databasePath}-wal`);\n return {\n databasePath,\n cleanup: () => cleanupSnapshotRoot(snapshotRoot)\n };\n } catch (error) {\n cleanupSnapshotRoot(snapshotRoot);\n throw error;\n }\n}\n\nfunction rejectSourceOutsideOrThroughSymlink(sourcePath: string, canonicalMemoryRoot: string): void {\n const root = path.resolve(canonicalMemoryRoot);\n const source = path.resolve(sourcePath);\n const rootStat = fs.lstatSync(root);\n if (!rootStat.isDirectory() || rootStat.isSymbolicLink()) {\n throw snapshotError('SQLITE_SNAPSHOT_UNSAFE_SOURCE', 'Canonical memory root must be a non-symlink directory');\n }\n const relative = path.relative(root, source);\n if (relative === '' || relative.startsWith('..') || path.isAbsolute(relative)) {\n throw snapshotError('SQLITE_SNAPSHOT_UNSAFE_SOURCE', 'Source database must be inside canonical memory storage');\n }\n\n let current = root;\n for (const segment of relative.split(path.sep)) {\n current = path.join(current, segment);\n let stat: fs.Stats;\n try {\n stat = fs.lstatSync(current);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') break;\n throw error;\n }\n if (stat.isSymbolicLink()) {\n throw snapshotError('SQLITE_SNAPSHOT_UNSAFE_SOURCE', 'Source database path must not traverse symlinks');\n }\n }\n}\n\nfunction realPathIfPresent(targetPath: string): string {\n try {\n return fs.realpathSync(targetPath);\n } catch {\n return targetPath;\n }\n}\n\nfunction copyIfLocalFile(source: string, destination: string): void {\n try {\n const stat = fs.lstatSync(source);\n if (stat.isFile() && !stat.isSymbolicLink()) fs.copyFileSync(source, destination);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n }\n}\n\nfunction rejectSymlinkOrNonFile(targetPath: string, label: string): void {\n const stat = fs.lstatSync(targetPath);\n if (stat.isSymbolicLink() || !stat.isFile()) {\n throw snapshotError('SQLITE_SNAPSHOT_UNSAFE_SOURCE', `${label} must be a regular non-symlink file`);\n }\n}\n\nfunction rejectSymlinkIfPresent(targetPath: string, label: string): void {\n try {\n const stat = fs.lstatSync(targetPath);\n if (stat.isSymbolicLink() || !stat.isFile()) {\n throw snapshotError('SQLITE_SNAPSHOT_UNSAFE_SOURCE', `${label} must be a regular non-symlink file`);\n }\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n }\n}\n\nfunction isWithin(parent: string, candidate: string): boolean {\n const relative = path.relative(parent, candidate);\n return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));\n}\n\nfunction snapshotError(code: string, message: string): NodeJS.ErrnoException {\n return Object.assign(new Error(message), { code });\n}\n\nfunction cleanupSnapshotRoot(snapshotRoot: string): void {\n // The target is a concrete mkdtemp result, never a caller-controlled path.\n try {\n fs.rmSync(snapshotRoot, { recursive: true, force: true });\n } catch {\n // Snapshot cleanup is best effort. A temporary-directory permission or\n // antivirus race must not turn an otherwise successful diagnostic read\n // into a canonical-store failure.\n }\n}\n", "import { z } from 'zod';\n\nimport { sqliteTransaction, type SQLiteDatabase } from '../sqlite-wrapper.js';\nimport { writeGovernanceAuditEntrySync } from './governance-audit.js';\nimport { MemoryAssetRepository, type ListMemoryAssetsInput } from './memory-asset-repository.js';\nimport {\n CreateMemoryAssetInputSchema,\n MemoryAssetPermissionDeniedError,\n MemoryAssetPermissionSchema,\n SetMemoryAssetBindingInputSchema,\n SetMemoryAssetGrantInputSchema,\n UpdateMemoryAssetInputSchema,\n checkMemoryAssetPermission,\n type MemoryAsset,\n type MemoryAssetBinding,\n type MemoryAssetGrant,\n type MemoryAssetPermission,\n type MemoryAssetPermissionDecision\n} from './memory-asset-permissions.js';\n\nconst ActorIdSchema = z.string().trim().min(1).max(240);\n\nexport interface MemoryAssetAccessInput {\n projectHash?: string;\n assetId: string;\n requesterActorId: string;\n permission: MemoryAssetPermission;\n}\n\nexport interface MemoryAssetAccessResult {\n asset?: MemoryAsset;\n decision: MemoryAssetPermissionDecision;\n}\n\nexport interface CreateAuthorizedMemoryAssetInput {\n projectHash?: string;\n requesterActorId: string;\n assetId?: string;\n assetType: MemoryAsset['assetType'];\n title: string;\n status?: MemoryAsset['status'];\n visibility?: MemoryAsset['visibility'];\n sourceRefs?: string[];\n metadata?: Record<string, unknown>;\n}\n\nexport interface UpdateAuthorizedMemoryAssetInput {\n projectHash?: string;\n requesterActorId: string;\n assetId: string;\n expectedVersion?: number;\n title?: string;\n status?: MemoryAsset['status'];\n visibility?: MemoryAsset['visibility'];\n sourceRefs?: string[];\n metadata?: Record<string, unknown>;\n}\n\nexport interface BindAuthorizedMemoryAssetInput {\n projectHash?: string;\n requesterActorId: string;\n assetId: string;\n actorId: string;\n injectionMode?: MemoryAssetBinding['injectionMode'];\n priority?: number;\n enabled?: boolean;\n}\n\nexport interface GrantAuthorizedMemoryAssetInput {\n projectHash?: string;\n requesterActorId: string;\n assetId: string;\n actorId: string;\n permissions: MemoryAssetPermission[];\n}\n\nfunction snapshot(value: MemoryAsset | MemoryAssetBinding | MemoryAssetGrant | null): Record<string, unknown> | undefined {\n if (!value) return undefined;\n return { ...value };\n}\n\nexport class MemoryAssetPermissionService {\n private readonly repository: MemoryAssetRepository;\n\n constructor(private readonly db: SQLiteDatabase) {\n this.repository = new MemoryAssetRepository(db);\n }\n\n async create(input: CreateAuthorizedMemoryAssetInput): Promise<MemoryAsset> {\n const requesterActorId = ActorIdSchema.parse(input.requesterActorId);\n const parsed = CreateMemoryAssetInputSchema.parse({\n ...input,\n ownerActorId: requesterActorId,\n sourceRefs: input.sourceRefs ?? []\n });\n return sqliteTransaction(this.db, () => {\n const asset = this.repository.create(parsed);\n writeGovernanceAuditEntrySync(this.db, {\n operation: 'memory_asset_create',\n actor: requesterActorId,\n projectHash: asset.projectHash,\n targetType: 'memory_asset',\n targetId: asset.assetId,\n afterJson: snapshot(asset)\n });\n return asset;\n });\n }\n\n async list(input: ListMemoryAssetsInput & { requesterActorId: string }): Promise<MemoryAsset[]> {\n const requesterActorId = ActorIdSchema.parse(input.requesterActorId);\n const requestedLimit = Math.min(500, Math.max(1, input.limit ?? 100));\n const pageSize = Math.max(100, requestedLimit);\n const readable: MemoryAsset[] = [];\n let offset = 0;\n\n // Filtering after a limited query can omit readable assets when newer\n // private assets occupy the first page. Scan deterministic pages until the\n // requested number of authorized results is found or the project is exhausted.\n while (readable.length < requestedLimit) {\n const assets = this.repository.list({\n projectHash: input.projectHash,\n assetType: input.assetType,\n status: input.status,\n limit: pageSize,\n offset\n });\n for (const asset of assets) {\n if (this.evaluate(asset, requesterActorId, 'read').allowed) {\n readable.push(asset);\n if (readable.length === requestedLimit) return readable;\n }\n }\n if (assets.length < pageSize) break;\n offset += assets.length;\n }\n return readable;\n }\n\n async get(input: Omit<MemoryAssetAccessInput, 'permission'>): Promise<MemoryAsset | null> {\n const result = this.check({ ...input, permission: 'read' });\n return result.decision.allowed ? result.asset ?? null : null;\n }\n\n check(input: MemoryAssetAccessInput): MemoryAssetAccessResult {\n const requesterActorId = ActorIdSchema.parse(input.requesterActorId);\n const permission = MemoryAssetPermissionSchema.parse(input.permission);\n const asset = this.repository.get(input.assetId, input.projectHash);\n if (!asset) {\n return {\n decision: {\n allowed: false,\n permission,\n source: 'none',\n reason: 'permission denied'\n }\n };\n }\n const decision = this.evaluate(asset, requesterActorId, permission);\n return decision.allowed ? { asset, decision } : { decision };\n }\n\n async update(input: UpdateAuthorizedMemoryAssetInput): Promise<MemoryAsset> {\n const requesterActorId = ActorIdSchema.parse(input.requesterActorId);\n const parsed = UpdateMemoryAssetInputSchema.parse(input);\n return sqliteTransaction(this.db, () => {\n const before = this.requireAllowed(input.projectHash, input.assetId, requesterActorId, 'write');\n const after = this.repository.update(parsed);\n writeGovernanceAuditEntrySync(this.db, {\n operation: 'memory_asset_update',\n actor: requesterActorId,\n projectHash: after.projectHash,\n targetType: 'memory_asset',\n targetId: after.assetId,\n beforeJson: snapshot(before),\n afterJson: snapshot(after)\n });\n return after;\n });\n }\n\n async bind(input: BindAuthorizedMemoryAssetInput): Promise<MemoryAssetBinding> {\n const requesterActorId = ActorIdSchema.parse(input.requesterActorId);\n const parsed = SetMemoryAssetBindingInputSchema.parse(input);\n return sqliteTransaction(this.db, () => {\n const asset = this.requireAllowed(input.projectHash, input.assetId, requesterActorId, 'bind');\n const before = this.repository.getBinding(asset.assetId, parsed.actorId, asset.projectHash);\n const after = this.repository.setBinding(parsed);\n writeGovernanceAuditEntrySync(this.db, {\n operation: 'memory_asset_bind',\n actor: requesterActorId,\n projectHash: asset.projectHash,\n targetType: 'memory_asset_binding',\n targetId: `${asset.assetId}:${parsed.actorId}`,\n beforeJson: snapshot(before),\n afterJson: snapshot(after)\n });\n return after;\n });\n }\n\n async setGrant(input: GrantAuthorizedMemoryAssetInput): Promise<MemoryAssetGrant> {\n const requesterActorId = ActorIdSchema.parse(input.requesterActorId);\n const parsed = SetMemoryAssetGrantInputSchema.parse({ ...input, createdBy: requesterActorId });\n return sqliteTransaction(this.db, () => {\n const asset = this.requireAllowed(input.projectHash, input.assetId, requesterActorId, 'grant');\n const before = this.repository.getGrant(asset.assetId, parsed.actorId, asset.projectHash);\n const after = this.repository.setGrant(parsed);\n writeGovernanceAuditEntrySync(this.db, {\n operation: 'memory_asset_grant_set',\n actor: requesterActorId,\n projectHash: asset.projectHash,\n targetType: 'memory_asset_grant',\n targetId: `${asset.assetId}:${parsed.actorId}`,\n beforeJson: snapshot(before),\n afterJson: snapshot(after)\n });\n return after;\n });\n }\n\n private evaluate(\n asset: MemoryAsset,\n actorId: string,\n permission: MemoryAssetPermission\n ): MemoryAssetPermissionDecision {\n return checkMemoryAssetPermission({\n asset,\n actorId,\n permission,\n binding: this.repository.getBinding(asset.assetId, actorId, asset.projectHash),\n grant: this.repository.getGrant(asset.assetId, actorId, asset.projectHash)\n });\n }\n\n private requireAllowed(\n projectHash: string | undefined,\n assetId: string,\n actorId: string,\n permission: MemoryAssetPermission\n ): MemoryAsset {\n const result = this.check({ projectHash, assetId, requesterActorId: actorId, permission });\n if (!result.asset || !result.decision.allowed) {\n throw new MemoryAssetPermissionDeniedError(assetId, actorId, permission);\n }\n return result.asset;\n }\n}\n", "import { randomUUID } from 'crypto';\n\nimport {\n sqliteRun,\n type SQLiteDatabase\n} from '../sqlite-wrapper.js';\n\nexport const MEMORY_GOVERNANCE_AUDIT_OPERATIONS = [\n 'facet_tag',\n 'action_update',\n 'lease_acquire',\n 'checkpoint_create',\n 'retention_score',\n 'quarantine',\n 'verify',\n 'lesson_promote',\n 'lesson_capture',\n 'actor_card_upsert',\n 'perspective_observation_create',\n 'perspective_observation_delete',\n 'core_memory_block_update',\n 'entity_supersede',\n 'memory_asset_create',\n 'memory_asset_update',\n 'memory_asset_bind',\n 'memory_asset_grant_set'\n] as const;\n\nexport type MemoryGovernanceAuditOperation = typeof MEMORY_GOVERNANCE_AUDIT_OPERATIONS[number];\n\nexport interface GovernanceAuditEntryInput {\n operation: MemoryGovernanceAuditOperation;\n actor: string;\n projectHash?: string;\n targetType: string;\n targetId: string;\n beforeJson?: Record<string, unknown>;\n afterJson?: Record<string, unknown>;\n sourceEventIds?: string[];\n}\n\nexport interface MemoryGovernanceAuditEntry {\n auditId: string;\n operation: MemoryGovernanceAuditOperation;\n actor: string;\n projectHash?: string;\n targetType: string;\n targetId: string;\n beforeJson?: Record<string, unknown>;\n afterJson?: Record<string, unknown>;\n sourceEventIds: string[];\n createdAt: Date;\n}\n\nfunction normalizeRequiredString(value: string, fieldName: string): string {\n const normalized = value.trim();\n if (!normalized) {\n throw new Error(`${fieldName} is required`);\n }\n return normalized;\n}\n\nfunction normalizeOptionalString(value: string | undefined): string | undefined {\n const normalized = value?.trim();\n return normalized ? normalized : undefined;\n}\n\nconst REDACTED = '[REDACTED]';\nconst sensitiveKeyPattern = /(?:api[_-]?key|secret|password|passwd|token|access[_-]?token|client[_-]?secret|crtfc[_-]?key|hashkey|serviceKey)/i;\n/**\n * The tail after the path's leading separator is `{0,300}` of any path-legal\n * character (spaces included \u2014 real paths contain \"Application Support\"),\n * then `[^\\s\u2026]*` to finish the current whitespace-free token.\n *\n * Both halves close an observed hole:\n * - Unbounded (`*`), one incidental \"/\" inside prose (a fraction, an \"A/B\"\n * aside, LLM-generated lesson text) deleted everything to the end of the\n * line. The 300-char bound caps that blast radius.\n * - Bounded alone, a path *longer* than 300 chars (deep node_modules/pnpm\n * chains) leaked its tail \u2014 the most identifying part \u2014 into stored audit\n * rows. Such paths contain no spaces, so finishing the current token\n * redacts them in full while prose beyond the next space still survives.\n */\nconst POSIX_ABSOLUTE_PATH_PATTERN = /(^|[^A-Za-z0-9._\\/\\\\-])\\/(?!\\/)[^\\n\\r\"'<>|`]{0,300}[^\\s\"'<>|`]*/g;\nconst WINDOWS_DRIVE_PATH_PATTERN = /(^|[^A-Za-z0-9._\\/\\\\-])(?:[A-Za-z]:[\\\\/][^\\n\\r\"'<>|`]{0,300}[^\\s\"'<>|`]*)/g;\n// The host segment stops at either separator so `\\\\host/share/...` (forward\n// slashes after the host, which Windows accepts) is caught too \u2014 retention's\n// deleted copy matched it, and consolidating on a backslash-only separator\n// would have silently un-redacted those paths in retention previews.\nconst WINDOWS_UNC_PATH_PATTERN = /(^|[^A-Za-z0-9._\\/\\\\-])(?:\\\\\\\\[^\\\\/\\s\"'<>|`]+[\\\\/][^\\n\\r\"'<>|`]{0,300}[^\\s\"'<>|`]*)/g;\nconst credentialQueryPattern = /\\b((?:api[_-]?key|token|access[_-]?token|client[_-]?secret|crtfc[_-]?key|hashkey|serviceKey)=)[^&\\s`\"'<>]+/gi;\nconst credentialAssignmentPattern = /\\b((?:api[_-]?key|secret|password|passwd|token|access[_-]?token|client[_-]?secret|crtfc[_-]?key|hashkey|serviceKey)\\s*[:=]\\s*)[^\\s`\"'<>},]+/gi;\n\n/**\n * Shared local-path redactor. Exported so retention-audit's preview redaction\n * uses these same patterns \u2014 a second hand-maintained copy of the regexes is\n * how the two files drifted apart in the first place.\n */\nexport function redactAbsolutePaths(value: string): string {\n return value\n .replace(WINDOWS_UNC_PATH_PATTERN, (_match, prefix: string) => `${prefix}${REDACTED}`)\n .replace(WINDOWS_DRIVE_PATH_PATTERN, (_match, prefix: string) => `${prefix}${REDACTED}`)\n .replace(POSIX_ABSOLUTE_PATH_PATTERN, (_match, prefix: string) => `${prefix}${REDACTED}`);\n}\n\nfunction sanitizeAuditString(value: string): string {\n return redactAbsolutePaths(value)\n .replace(credentialQueryPattern, `$1${REDACTED}`)\n .replace(credentialAssignmentPattern, `$1${REDACTED}`);\n}\n\nexport function sanitizeGovernanceAuditValue(value: unknown, key?: string): unknown {\n if (key && sensitiveKeyPattern.test(key)) {\n return REDACTED;\n }\n if (typeof value === 'string') {\n return sanitizeAuditString(value);\n }\n if (value instanceof Date) {\n return sanitizeAuditString(value.toISOString());\n }\n if (Array.isArray(value)) {\n return value.map((item) => sanitizeGovernanceAuditValue(item));\n }\n if (value && typeof value === 'object') {\n const sanitized: Record<string, unknown> = {};\n for (const [entryKey, entryValue] of Object.entries(value as Record<string, unknown>)) {\n sanitized[sanitizeAuditString(entryKey)] = sanitizeGovernanceAuditValue(entryValue, entryKey);\n }\n return sanitized;\n }\n return value;\n}\n\nfunction sanitizeAuditJson(value: Record<string, unknown> | undefined): Record<string, unknown> | undefined {\n if (value === undefined) return undefined;\n return sanitizeGovernanceAuditValue(value) as Record<string, unknown>;\n}\n\nfunction normalizeSourceEventIds(sourceEventIds: string[] | undefined): string[] {\n return (sourceEventIds || [])\n .map((sourceEventId) => sanitizeAuditString(sourceEventId.trim()))\n .filter((sourceEventId) => sourceEventId.length > 0);\n}\n\nfunction normalizeOperation(operation: MemoryGovernanceAuditOperation): MemoryGovernanceAuditOperation {\n if ((MEMORY_GOVERNANCE_AUDIT_OPERATIONS as readonly string[]).indexOf(operation) === -1) {\n throw new Error(`Unsupported governance audit operation: ${operation}`);\n }\n return operation;\n}\n\n/**\n * Synchronous audit writer for callers that must include the audit row in an\n * existing better-sqlite3 transaction.\n */\nexport function writeGovernanceAuditEntrySync(\n db: SQLiteDatabase,\n input: GovernanceAuditEntryInput\n): MemoryGovernanceAuditEntry {\n const entry: MemoryGovernanceAuditEntry = {\n auditId: randomUUID(),\n operation: normalizeOperation(input.operation),\n actor: sanitizeAuditString(normalizeRequiredString(input.actor, 'actor')),\n projectHash: normalizeOptionalString(input.projectHash),\n targetType: normalizeRequiredString(input.targetType, 'targetType'),\n targetId: sanitizeAuditString(normalizeRequiredString(input.targetId, 'targetId')),\n beforeJson: sanitizeAuditJson(input.beforeJson),\n afterJson: sanitizeAuditJson(input.afterJson),\n sourceEventIds: normalizeSourceEventIds(input.sourceEventIds),\n createdAt: new Date()\n };\n\n sqliteRun(\n db,\n `INSERT INTO memory_governance_audit (\n audit_id, operation, actor, project_hash, target_type, target_id,\n before_json, after_json, source_event_ids, created_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n [\n entry.auditId,\n entry.operation,\n entry.actor,\n entry.projectHash ?? null,\n entry.targetType,\n entry.targetId,\n entry.beforeJson === undefined ? null : JSON.stringify(entry.beforeJson),\n entry.afterJson === undefined ? null : JSON.stringify(entry.afterJson),\n JSON.stringify(entry.sourceEventIds),\n entry.createdAt.toISOString()\n ]\n );\n\n return entry;\n}\n\n/** Preserve the existing async API used by repositories and external callers. */\nexport async function writeGovernanceAuditEntry(\n db: SQLiteDatabase,\n input: GovernanceAuditEntryInput\n): Promise<MemoryGovernanceAuditEntry> {\n return writeGovernanceAuditEntrySync(db, input);\n}\n", "import { randomUUID } from 'node:crypto';\n\nimport {\n sqliteAll,\n sqliteGet,\n sqliteRun,\n toDateFromSQLite,\n type SQLiteDatabase\n} from '../sqlite-wrapper.js';\nimport {\n CreateMemoryAssetInputSchema,\n MemoryAssetBindingSchema,\n MemoryAssetGrantSchema,\n MemoryAssetPermissionSchema,\n MemoryAssetSchema,\n SetMemoryAssetBindingInputSchema,\n SetMemoryAssetGrantInputSchema,\n UpdateMemoryAssetInputSchema,\n type MemoryAsset,\n type MemoryAssetBinding,\n type MemoryAssetGrant,\n type MemoryAssetPermission,\n type MemoryAssetStatus,\n type MemoryAssetType,\n type MemoryAssetVisibility\n} from './memory-asset-permissions.js';\n\ninterface MemoryAssetRow {\n asset_id: string;\n project_hash: string;\n asset_type: MemoryAssetType;\n title: string;\n owner_actor_id: string;\n version: number;\n status: MemoryAssetStatus;\n visibility: MemoryAssetVisibility;\n source_refs_json: string;\n metadata_json: string | null;\n created_at: string;\n updated_at: string;\n}\n\ninterface MemoryAssetBindingRow {\n project_hash: string;\n asset_id: string;\n actor_id: string;\n injection_mode: MemoryAssetBinding['injectionMode'];\n priority: number;\n enabled: number;\n created_at: string;\n updated_at: string;\n}\n\ninterface MemoryAssetGrantRow {\n project_hash: string;\n asset_id: string;\n actor_id: string;\n permissions_json: string;\n created_by: string;\n created_at: string;\n updated_at: string;\n}\n\nfunction projectHashToStorage(projectHash: string | undefined): string {\n return projectHash ?? '';\n}\n\nfunction projectHashFromStorage(projectHash: string): string | undefined {\n return projectHash.length > 0 ? projectHash : undefined;\n}\n\nfunction parseStringArray(value: string): string[] {\n try {\n const parsed = JSON.parse(value);\n return Array.isArray(parsed) ? parsed.filter((item): item is string => typeof item === 'string') : [];\n } catch {\n return [];\n }\n}\n\nfunction parseRecord(value: string | null): Record<string, unknown> | undefined {\n if (!value) return undefined;\n try {\n const parsed = JSON.parse(value);\n return parsed && typeof parsed === 'object' && !Array.isArray(parsed)\n ? parsed as Record<string, unknown>\n : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction rowToAsset(row: MemoryAssetRow): MemoryAsset {\n return MemoryAssetSchema.parse({\n assetId: row.asset_id,\n projectHash: projectHashFromStorage(row.project_hash),\n assetType: row.asset_type,\n title: row.title,\n ownerActorId: row.owner_actor_id,\n version: Number(row.version),\n status: row.status,\n visibility: row.visibility,\n sourceRefs: parseStringArray(row.source_refs_json),\n metadata: parseRecord(row.metadata_json),\n createdAt: toDateFromSQLite(row.created_at),\n updatedAt: toDateFromSQLite(row.updated_at)\n });\n}\n\nfunction rowToBinding(row: MemoryAssetBindingRow): MemoryAssetBinding {\n return MemoryAssetBindingSchema.parse({\n projectHash: projectHashFromStorage(row.project_hash),\n assetId: row.asset_id,\n actorId: row.actor_id,\n injectionMode: row.injection_mode,\n priority: Number(row.priority),\n enabled: Boolean(row.enabled),\n createdAt: toDateFromSQLite(row.created_at),\n updatedAt: toDateFromSQLite(row.updated_at)\n });\n}\n\nfunction rowToGrant(row: MemoryAssetGrantRow): MemoryAssetGrant {\n const permissions = parseStringArray(row.permissions_json)\n .map((permission) => MemoryAssetPermissionSchema.safeParse(permission))\n .filter((result) => result.success)\n .map((result) => result.data);\n return MemoryAssetGrantSchema.parse({\n projectHash: projectHashFromStorage(row.project_hash),\n assetId: row.asset_id,\n actorId: row.actor_id,\n permissions,\n createdBy: row.created_by,\n createdAt: toDateFromSQLite(row.created_at),\n updatedAt: toDateFromSQLite(row.updated_at)\n });\n}\n\nexport interface ListMemoryAssetsInput {\n projectHash?: string;\n assetType?: MemoryAssetType;\n status?: MemoryAssetStatus;\n limit?: number;\n offset?: number;\n}\n\nexport class MemoryAssetRepository {\n constructor(private readonly db: SQLiteDatabase) {}\n\n create(input: unknown): MemoryAsset {\n const parsed = CreateMemoryAssetInputSchema.parse(input);\n const assetId = parsed.assetId ?? randomUUID();\n const now = new Date().toISOString();\n sqliteRun(\n this.db,\n `INSERT INTO memory_assets (\n asset_id, project_hash, asset_type, title, owner_actor_id, version,\n status, visibility, source_refs_json, metadata_json, created_at, updated_at\n ) VALUES (?, ?, ?, ?, ?, 1, ?, ?, ?, ?, ?, ?)`,\n [\n assetId,\n projectHashToStorage(parsed.projectHash),\n parsed.assetType,\n parsed.title,\n parsed.ownerActorId,\n parsed.status,\n parsed.visibility,\n JSON.stringify(parsed.sourceRefs),\n parsed.metadata ? JSON.stringify(parsed.metadata) : null,\n now,\n now\n ]\n );\n return this.require(assetId, parsed.projectHash);\n }\n\n get(assetId: string, projectHash?: string): MemoryAsset | null {\n const row = sqliteGet<MemoryAssetRow>(\n this.db,\n `SELECT * FROM memory_assets WHERE asset_id = ? AND project_hash = ?`,\n [assetId.trim(), projectHashToStorage(projectHash)]\n );\n return row ? rowToAsset(row) : null;\n }\n\n require(assetId: string, projectHash?: string): MemoryAsset {\n const asset = this.get(assetId, projectHash);\n if (!asset) throw new Error(`Memory asset not found: ${assetId}`);\n return asset;\n }\n\n list(input: ListMemoryAssetsInput): MemoryAsset[] {\n const clauses = ['project_hash = ?'];\n const params: unknown[] = [projectHashToStorage(input.projectHash)];\n if (input.assetType) {\n clauses.push('asset_type = ?');\n params.push(input.assetType);\n }\n if (input.status) {\n clauses.push('status = ?');\n params.push(input.status);\n }\n params.push(\n Math.min(500, Math.max(1, input.limit ?? 100)),\n Math.max(0, Math.floor(input.offset ?? 0))\n );\n return sqliteAll<MemoryAssetRow>(\n this.db,\n `SELECT * FROM memory_assets\n WHERE ${clauses.join(' AND ')}\n ORDER BY updated_at DESC, asset_id ASC\n LIMIT ? OFFSET ?`,\n params\n ).map(rowToAsset);\n }\n\n update(input: unknown): MemoryAsset {\n const parsed = UpdateMemoryAssetInputSchema.parse(input);\n const before = this.require(parsed.assetId, parsed.projectHash);\n const assignments: string[] = [];\n const params: unknown[] = [];\n const set = (column: string, value: unknown) => {\n assignments.push(`${column} = ?`);\n params.push(value);\n };\n if (parsed.title !== undefined) set('title', parsed.title);\n if (parsed.status !== undefined) set('status', parsed.status);\n if (parsed.visibility !== undefined) set('visibility', parsed.visibility);\n if (parsed.sourceRefs !== undefined) set('source_refs_json', JSON.stringify(parsed.sourceRefs));\n if (parsed.metadata !== undefined) set('metadata_json', JSON.stringify(parsed.metadata));\n assignments.push('version = version + 1', 'updated_at = ?');\n params.push(new Date().toISOString(), parsed.assetId, projectHashToStorage(parsed.projectHash));\n\n let where = 'asset_id = ? AND project_hash = ?';\n if (parsed.expectedVersion !== undefined) {\n where += ' AND version = ?';\n params.push(parsed.expectedVersion);\n }\n const result = sqliteRun(this.db, `UPDATE memory_assets SET ${assignments.join(', ')} WHERE ${where}`, params);\n if (result.changes !== 1) {\n throw new Error(`Memory asset version conflict: expected ${parsed.expectedVersion}, current ${before.version}`);\n }\n return this.require(parsed.assetId, parsed.projectHash);\n }\n\n getBinding(assetId: string, actorId: string, projectHash?: string): MemoryAssetBinding | null {\n const row = sqliteGet<MemoryAssetBindingRow>(\n this.db,\n `SELECT * FROM memory_asset_bindings WHERE asset_id = ? AND actor_id = ? AND project_hash = ?`,\n [assetId.trim(), actorId.trim(), projectHashToStorage(projectHash)]\n );\n return row ? rowToBinding(row) : null;\n }\n\n setBinding(input: unknown): MemoryAssetBinding {\n const parsed = SetMemoryAssetBindingInputSchema.parse(input);\n const now = new Date().toISOString();\n sqliteRun(\n this.db,\n `INSERT INTO memory_asset_bindings (\n project_hash, asset_id, actor_id, injection_mode, priority, enabled, created_at, updated_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(project_hash, asset_id, actor_id) DO UPDATE SET\n injection_mode = excluded.injection_mode,\n priority = excluded.priority,\n enabled = excluded.enabled,\n updated_at = excluded.updated_at`,\n [\n projectHashToStorage(parsed.projectHash),\n parsed.assetId,\n parsed.actorId,\n parsed.injectionMode,\n parsed.priority,\n parsed.enabled ? 1 : 0,\n now,\n now\n ]\n );\n const binding = this.getBinding(parsed.assetId, parsed.actorId, parsed.projectHash);\n if (!binding) throw new Error('Memory asset binding write failed');\n return binding;\n }\n\n getGrant(assetId: string, actorId: string, projectHash?: string): MemoryAssetGrant | null {\n const row = sqliteGet<MemoryAssetGrantRow>(\n this.db,\n `SELECT * FROM memory_asset_grants WHERE asset_id = ? AND actor_id = ? AND project_hash = ?`,\n [assetId.trim(), actorId.trim(), projectHashToStorage(projectHash)]\n );\n return row ? rowToGrant(row) : null;\n }\n\n setGrant(input: unknown): MemoryAssetGrant {\n const parsed = SetMemoryAssetGrantInputSchema.parse(input);\n const permissions = Array.from(new Set<MemoryAssetPermission>(parsed.permissions)).sort();\n const now = new Date().toISOString();\n sqliteRun(\n this.db,\n `INSERT INTO memory_asset_grants (\n project_hash, asset_id, actor_id, permissions_json, created_by, created_at, updated_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(project_hash, asset_id, actor_id) DO UPDATE SET\n permissions_json = excluded.permissions_json,\n created_by = excluded.created_by,\n updated_at = excluded.updated_at`,\n [\n projectHashToStorage(parsed.projectHash),\n parsed.assetId,\n parsed.actorId,\n JSON.stringify(permissions),\n parsed.createdBy,\n now,\n now\n ]\n );\n const grant = this.getGrant(parsed.assetId, parsed.actorId, parsed.projectHash);\n if (!grant) throw new Error('Memory asset grant write failed');\n return grant;\n }\n}\n", "import { z } from 'zod';\n\nconst NonEmptyStringSchema = z.string().trim().min(1).max(240);\nconst OptionalProjectHashSchema = z.string().trim().min(1).max(240).optional();\nconst StringArraySchema = z.array(z.string().trim().min(1).max(240)).max(100).default([]);\n\nexport const MemoryAssetTypeSchema = z.enum(['memory', 'lesson', 'skill', 'wiki', 'code_graph']);\nexport type MemoryAssetType = z.infer<typeof MemoryAssetTypeSchema>;\n\nexport const MemoryAssetStatusSchema = z.enum(['candidate', 'active', 'deprecated', 'archived']);\nexport type MemoryAssetStatus = z.infer<typeof MemoryAssetStatusSchema>;\n\nexport const MemoryAssetVisibilitySchema = z.enum(['private', 'project', 'shared']);\nexport type MemoryAssetVisibility = z.infer<typeof MemoryAssetVisibilitySchema>;\n\nexport const MemoryAssetPermissionSchema = z.enum(['read', 'write', 'bind', 'grant']);\nexport type MemoryAssetPermission = z.infer<typeof MemoryAssetPermissionSchema>;\n\nexport const MemoryAssetInjectionModeSchema = z.enum(['direct', 'summary', 'tool', 'reference']);\nexport type MemoryAssetInjectionMode = z.infer<typeof MemoryAssetInjectionModeSchema>;\n\nexport const MemoryAssetSchema = z.object({\n assetId: NonEmptyStringSchema,\n projectHash: OptionalProjectHashSchema,\n assetType: MemoryAssetTypeSchema,\n title: NonEmptyStringSchema,\n ownerActorId: NonEmptyStringSchema,\n version: z.number().int().positive(),\n status: MemoryAssetStatusSchema,\n visibility: MemoryAssetVisibilitySchema,\n sourceRefs: StringArraySchema,\n metadata: z.record(z.unknown()).optional(),\n createdAt: z.date(),\n updatedAt: z.date()\n});\nexport type MemoryAsset = z.infer<typeof MemoryAssetSchema>;\n\nexport const CreateMemoryAssetInputSchema = z.object({\n assetId: NonEmptyStringSchema.optional(),\n projectHash: OptionalProjectHashSchema,\n assetType: MemoryAssetTypeSchema,\n title: NonEmptyStringSchema,\n ownerActorId: NonEmptyStringSchema,\n status: MemoryAssetStatusSchema.default('active'),\n visibility: MemoryAssetVisibilitySchema.default('private'),\n sourceRefs: StringArraySchema,\n metadata: z.record(z.unknown()).optional()\n});\nexport type CreateMemoryAssetInput = z.input<typeof CreateMemoryAssetInputSchema>;\n\nexport const UpdateMemoryAssetInputSchema = z.object({\n assetId: NonEmptyStringSchema,\n projectHash: OptionalProjectHashSchema,\n expectedVersion: z.number().int().positive().optional(),\n title: NonEmptyStringSchema.optional(),\n status: MemoryAssetStatusSchema.optional(),\n visibility: MemoryAssetVisibilitySchema.optional(),\n sourceRefs: StringArraySchema.optional(),\n metadata: z.record(z.unknown()).optional()\n}).refine(\n (input) => input.title !== undefined\n || input.status !== undefined\n || input.visibility !== undefined\n || input.sourceRefs !== undefined\n || input.metadata !== undefined,\n 'at least one asset field must be supplied'\n);\nexport type UpdateMemoryAssetInput = z.input<typeof UpdateMemoryAssetInputSchema>;\n\nexport const MemoryAssetBindingSchema = z.object({\n projectHash: OptionalProjectHashSchema,\n assetId: NonEmptyStringSchema,\n actorId: NonEmptyStringSchema,\n injectionMode: MemoryAssetInjectionModeSchema,\n priority: z.number().int().min(-1000).max(1000),\n enabled: z.boolean(),\n createdAt: z.date(),\n updatedAt: z.date()\n});\nexport type MemoryAssetBinding = z.infer<typeof MemoryAssetBindingSchema>;\n\nexport const SetMemoryAssetBindingInputSchema = z.object({\n projectHash: OptionalProjectHashSchema,\n assetId: NonEmptyStringSchema,\n actorId: NonEmptyStringSchema,\n injectionMode: MemoryAssetInjectionModeSchema.default('reference'),\n priority: z.number().int().min(-1000).max(1000).default(0),\n enabled: z.boolean().default(true)\n});\nexport type SetMemoryAssetBindingInput = z.input<typeof SetMemoryAssetBindingInputSchema>;\n\nexport const MemoryAssetGrantSchema = z.object({\n projectHash: OptionalProjectHashSchema,\n assetId: NonEmptyStringSchema,\n actorId: NonEmptyStringSchema,\n permissions: z.array(MemoryAssetPermissionSchema).max(4),\n createdBy: NonEmptyStringSchema,\n createdAt: z.date(),\n updatedAt: z.date()\n});\nexport type MemoryAssetGrant = z.infer<typeof MemoryAssetGrantSchema>;\n\nexport const SetMemoryAssetGrantInputSchema = z.object({\n projectHash: OptionalProjectHashSchema,\n assetId: NonEmptyStringSchema,\n actorId: NonEmptyStringSchema,\n permissions: z.array(MemoryAssetPermissionSchema).max(4),\n createdBy: NonEmptyStringSchema\n});\nexport type SetMemoryAssetGrantInput = z.input<typeof SetMemoryAssetGrantInputSchema>;\n\nexport type MemoryAssetPermissionSource = 'owner' | 'visibility' | 'binding' | 'grant' | 'none';\n\nexport interface MemoryAssetPermissionDecision {\n allowed: boolean;\n permission: MemoryAssetPermission;\n source: MemoryAssetPermissionSource;\n reason: string;\n}\n\nexport interface CheckMemoryAssetPermissionInput {\n asset: MemoryAsset;\n actorId: string;\n permission: MemoryAssetPermission;\n binding?: MemoryAssetBinding | null;\n grant?: MemoryAssetGrant | null;\n}\n\n/**\n * Small, deterministic permission core. Precedence deliberately follows\n * owner -> read visibility -> active binding -> explicit grant -> deny.\n * Bindings make an asset readable/injectable; they never confer mutation or\n * delegation rights.\n */\nexport function checkMemoryAssetPermission(input: CheckMemoryAssetPermissionInput): MemoryAssetPermissionDecision {\n const actorId = NonEmptyStringSchema.parse(input.actorId);\n const permission = MemoryAssetPermissionSchema.parse(input.permission);\n\n if (input.asset.ownerActorId === actorId) {\n return { allowed: true, permission, source: 'owner', reason: 'asset owner' };\n }\n\n if (permission === 'read' && (input.asset.visibility === 'project' || input.asset.visibility === 'shared')) {\n return { allowed: true, permission, source: 'visibility', reason: `${input.asset.visibility} visibility` };\n }\n\n if (\n permission === 'read'\n && input.binding?.actorId === actorId\n && input.binding.assetId === input.asset.assetId\n && input.binding.enabled\n ) {\n return { allowed: true, permission, source: 'binding', reason: 'active actor binding' };\n }\n\n if (\n input.grant?.actorId === actorId\n && input.grant.assetId === input.asset.assetId\n && input.grant.permissions.includes(permission)\n ) {\n return { allowed: true, permission, source: 'grant', reason: 'explicit actor grant' };\n }\n\n // Keep missing and inaccessible assets indistinguishable at the public\n // permission-check boundary. Allowed decisions still explain the winning\n // rule, while a denial never confirms that a private asset exists.\n return { allowed: false, permission, source: 'none', reason: 'permission denied' };\n}\n\nexport class MemoryAssetPermissionDeniedError extends Error {\n readonly code = 'MEMORY_ASSET_PERMISSION_DENIED';\n\n constructor(\n readonly assetId: string,\n readonly actorId: string,\n readonly permission: MemoryAssetPermission\n ) {\n super(`Permission denied: actor ${actorId} cannot ${permission} memory asset ${assetId}`);\n this.name = 'MemoryAssetPermissionDeniedError';\n }\n}\n", "import { z } from 'zod';\n\nimport type { SQLiteDatabase } from '../sqlite-wrapper.js';\nimport {\n canonicalMemoryAssetId,\n isCanonicalMemoryAssetRegistration,\n type CanonicalMemoryAssetType\n} from './memory-asset-catalog-service.js';\nimport {\n CANONICAL_MEMORY_PERMISSION_MODE_ENV,\n resolveCanonicalMemoryPermissionMode,\n type CanonicalMemoryPermissionMode\n} from './canonical-memory-access-service.js';\nimport { MemoryAssetRepository } from './memory-asset-repository.js';\nimport type { MemoryAssetInjectionMode } from './memory-asset-permissions.js';\n\nexport const CANONICAL_MEMORY_ACTOR_ID_ENV = 'CLAUDE_MEMORY_ACTOR_ID';\n\nconst ActorIdSchema = z.string().trim().min(1).max(240);\n\nexport type CanonicalMemoryInjectionLane = 'session_start' | 'prompt' | 'context_pack';\n\nexport interface CanonicalMemoryInjectionCandidate<T> {\n canonicalType: CanonicalMemoryAssetType;\n canonicalId: string;\n value: T;\n}\n\nexport interface CanonicalMemoryInjection<T> {\n value: T;\n injectionMode: Extract<MemoryAssetInjectionMode, 'direct' | 'summary' | 'reference'>;\n priority: number;\n}\n\nexport interface CanonicalMemoryInjectionSelection<T> {\n mode: CanonicalMemoryPermissionMode;\n items: CanonicalMemoryInjection<T>[];\n}\n\nexport function resolveCanonicalMemoryActorId(\n explicitActorId: unknown,\n env: NodeJS.ProcessEnv = process.env\n): string | undefined {\n const raw = typeof explicitActorId === 'string' && explicitActorId.trim().length > 0\n ? explicitActorId\n : env[CANONICAL_MEMORY_ACTOR_ID_ENV];\n const parsed = ActorIdSchema.safeParse(raw);\n return parsed.success ? parsed.data : undefined;\n}\n\nfunction injectionModeRank(mode: 'direct' | 'summary' | 'reference'): number {\n if (mode === 'direct') return 3;\n if (mode === 'summary') return 2;\n return 1;\n}\n\nexport class CanonicalMemoryInjectionService {\n private readonly repository: MemoryAssetRepository;\n private readonly env: NodeJS.ProcessEnv;\n readonly mode: CanonicalMemoryPermissionMode;\n\n constructor(\n db: SQLiteDatabase,\n options: { mode?: CanonicalMemoryPermissionMode; env?: NodeJS.ProcessEnv } = {}\n ) {\n this.repository = new MemoryAssetRepository(db);\n this.env = options.env ?? process.env;\n this.mode = options.mode ?? resolveCanonicalMemoryPermissionMode(this.env);\n }\n\n select<T>(input: {\n projectHash: string;\n actorId?: string;\n lane: CanonicalMemoryInjectionLane;\n candidates: CanonicalMemoryInjectionCandidate<T>[];\n }): CanonicalMemoryInjectionSelection<T> {\n const actorId = resolveCanonicalMemoryActorId(input.actorId, this.env);\n if (this.mode !== 'legacy' && !actorId) {\n throw new Error(`actor identity is required when ${CANONICAL_MEMORY_PERMISSION_MODE_ENV}=${this.mode}`);\n }\n\n // Lesson lifecycle eligibility is independent of legacy ACL compatibility.\n // Apply it before the legacy fast-path so disabled/version-conditional\n // lessons never enter any automatic injection lane.\n const candidates = input.candidates.filter((candidate) => {\n const lesson = candidate.value as Partial<{ recallEnabled: boolean; validVersions: string[] }>;\n return candidate.canonicalType !== 'lesson' || (lesson.recallEnabled !== false && (lesson.validVersions?.length ?? 0) === 0);\n });\n\n if (this.mode === 'legacy') {\n return {\n mode: this.mode,\n items: candidates.map((candidate) => ({\n value: candidate.value,\n injectionMode: 'direct',\n priority: 0\n }))\n };\n }\n\n const selected: Array<CanonicalMemoryInjection<T> & { canonicalId: string }> = [];\n for (const candidate of candidates) {\n const assetId = canonicalMemoryAssetId(candidate.canonicalType, candidate.canonicalId);\n const asset = this.repository.get(assetId, input.projectHash);\n const registered = Boolean(\n asset && isCanonicalMemoryAssetRegistration(asset, candidate.canonicalType, candidate.canonicalId)\n );\n\n if (!asset) {\n if (this.mode === 'registered') {\n selected.push({ value: candidate.value, injectionMode: 'direct', priority: 0, canonicalId: candidate.canonicalId });\n }\n continue;\n }\n if (!registered || asset.status !== 'active') continue;\n\n const binding = this.repository.getBinding(assetId, actorId!, input.projectHash);\n if (!binding?.enabled || binding.injectionMode === 'tool') continue;\n selected.push({\n value: candidate.value,\n injectionMode: binding.injectionMode,\n priority: binding.priority,\n canonicalId: candidate.canonicalId\n });\n }\n\n selected.sort((left, right) => (\n right.priority - left.priority\n || injectionModeRank(right.injectionMode) - injectionModeRank(left.injectionMode)\n || left.canonicalId.localeCompare(right.canonicalId)\n ));\n return {\n mode: this.mode,\n items: selected.map(({ canonicalId: _canonicalId, ...item }) => item)\n };\n }\n}\n", "import { randomUUID } from 'crypto';\nimport { z } from 'zod';\n\nimport {\n sqliteAll,\n sqliteGet,\n sqliteRun,\n toDateFromSQLite,\n type SQLiteDatabase\n} from '../sqlite-wrapper.js';\nimport {\n ListMemoryLessonsInputSchema,\n MemoryLessonSchema,\n UpsertMemoryLessonInputSchema,\n type MemoryLesson\n} from '../types.js';\nimport { sanitizeGovernanceAuditValue, writeGovernanceAuditEntry } from './governance-audit.js';\n\ninterface MemoryLessonRow {\n lesson_id: string;\n project_hash: string;\n name: string;\n trigger: string;\n steps_json: string;\n confidence: number;\n source_session_ids: string;\n source_event_ids: string;\n failure_modes_json: string;\n skill_candidate: number;\n source_class?: string;\n revision?: number;\n recall_enabled?: number;\n scope?: string | null;\n validation_json?: string;\n reconsider_when?: string | null;\n valid_versions_json?: string;\n created_at: string;\n updated_at: string;\n}\n\ntype ParsedLessonUpsert = z.output<typeof UpsertMemoryLessonInputSchema>;\n\nfunction parseStringArray(value: unknown): string[] {\n if (typeof value !== 'string') return [];\n try {\n const parsed = JSON.parse(value);\n return Array.isArray(parsed)\n ? parsed.filter((item): item is string => typeof item === 'string' && item.length > 0)\n : [];\n } catch {\n return [];\n }\n}\n\nfunction projectHashToStorage(projectHash: string | undefined): string {\n return projectHash ?? '';\n}\n\nfunction projectHashFromStorage(projectHash: string): string | undefined {\n return projectHash.length > 0 ? projectHash : undefined;\n}\n\nfunction sanitizeString(value: string): string {\n return String(sanitizeGovernanceAuditValue(value));\n}\n\nfunction sanitizeStringArray(values: string[]): string[] {\n return values.map(sanitizeString).filter((value) => value.length > 0);\n}\n\nfunction sanitizeParsedLesson(input: ParsedLessonUpsert): ParsedLessonUpsert {\n return {\n ...input,\n projectHash: input.projectHash ? sanitizeString(input.projectHash) : undefined,\n name: sanitizeString(input.name),\n trigger: sanitizeString(input.trigger),\n steps: sanitizeStringArray(input.steps),\n sourceSessionIds: sanitizeStringArray(input.sourceSessionIds),\n sourceEventIds: sanitizeStringArray(input.sourceEventIds),\n failureModes: sanitizeStringArray(input.failureModes),\n sourceClass: input.sourceClass,\n actor: input.actor ? sanitizeString(input.actor) : undefined\n };\n}\n\nfunction rowToLesson(row: MemoryLessonRow): MemoryLesson {\n return MemoryLessonSchema.parse({\n lessonId: row.lesson_id,\n projectHash: projectHashFromStorage(row.project_hash),\n name: row.name,\n trigger: row.trigger,\n steps: parseStringArray(row.steps_json),\n confidence: Number(row.confidence),\n sourceSessionIds: parseStringArray(row.source_session_ids),\n sourceEventIds: parseStringArray(row.source_event_ids),\n failureModes: parseStringArray(row.failure_modes_json),\n skillCandidate: Number(row.skill_candidate) === 1,\n sourceClass: row.source_class === 'curated' ? 'curated' : 'derived',\n revision: Number(row.revision ?? 1),\n recallEnabled: Number(row.recall_enabled ?? 1) === 1,\n scope: row.scope ?? undefined,\n validation: parseStringArray(row.validation_json),\n reconsiderWhen: row.reconsider_when ?? undefined,\n validVersions: parseStringArray(row.valid_versions_json),\n createdAt: toDateFromSQLite(row.created_at),\n updatedAt: toDateFromSQLite(row.updated_at)\n });\n}\n\nfunction lessonToAuditJson(lesson: MemoryLesson): Record<string, unknown> {\n return {\n lessonId: lesson.lessonId,\n projectHash: lesson.projectHash,\n name: lesson.name,\n trigger: lesson.trigger,\n steps: lesson.steps,\n confidence: lesson.confidence,\n sourceSessionIds: lesson.sourceSessionIds,\n sourceEventIds: lesson.sourceEventIds,\n failureModes: lesson.failureModes,\n skillCandidate: lesson.skillCandidate,\n sourceClass: lesson.sourceClass,\n revision: lesson.revision,\n recallEnabled: lesson.recallEnabled,\n scope: lesson.scope,\n validation: lesson.validation,\n reconsiderWhen: lesson.reconsiderWhen,\n validVersions: lesson.validVersions,\n createdAt: lesson.createdAt.toISOString(),\n updatedAt: lesson.updatedAt.toISOString()\n };\n}\n\nexport type LessonAuditOperation = 'lesson_promote' | 'lesson_capture';\n\nexport class LessonRepository {\n constructor(private readonly db: SQLiteDatabase) {}\n\n async upsert(input: unknown, auditOperation: LessonAuditOperation = 'lesson_promote'): Promise<MemoryLesson> {\n const parsed = sanitizeParsedLesson(UpsertMemoryLessonInputSchema.parse(input));\n const existingById = parsed.lessonId ? this.get(parsed.lessonId) : null;\n const existingByName = this.getByProjectAndName(parsed.projectHash, parsed.name);\n if (existingById && existingByName && existingById.lessonId !== existingByName.lessonId) {\n throw new Error('lesson name already exists for projectHash');\n }\n const existing = existingById ?? existingByName;\n const now = new Date().toISOString();\n\n if (existing) {\n if (projectHashToStorage(existing.projectHash) !== projectHashToStorage(parsed.projectHash)) {\n throw new Error('lesson projectHash mismatch');\n }\n sqliteRun(\n this.db,\n `UPDATE memory_lessons\n SET name = ?, trigger = ?, steps_json = ?, confidence = ?, source_session_ids = ?,\n source_event_ids = ?, failure_modes_json = ?, skill_candidate = ?, source_class = ?,\n revision = revision + 1, recall_enabled = ?, scope = ?, validation_json = ?, reconsider_when = ?, valid_versions_json = ?, updated_at = ?\n WHERE lesson_id = ? AND project_hash = ?`,\n [\n parsed.name,\n parsed.trigger,\n JSON.stringify(parsed.steps),\n parsed.confidence,\n JSON.stringify(parsed.sourceSessionIds),\n JSON.stringify(parsed.sourceEventIds),\n JSON.stringify(parsed.failureModes),\n parsed.skillCandidate ? 1 : 0,\n parsed.sourceClass,\n parsed.recallEnabled === undefined ? (existing.recallEnabled ? 1 : 0) : (parsed.recallEnabled ? 1 : 0),\n parsed.scope ?? existing.scope ?? null,\n JSON.stringify(parsed.validation ?? existing.validation),\n parsed.reconsiderWhen ?? existing.reconsiderWhen ?? null,\n JSON.stringify(parsed.validVersions ?? existing.validVersions),\n now,\n existing.lessonId,\n projectHashToStorage(existing.projectHash)\n ]\n );\n const saved = this.require(existing.lessonId);\n await this.auditLessonUpsert(parsed, existing, saved, auditOperation);\n return saved;\n }\n\n const lessonId = parsed.lessonId ?? randomUUID();\n sqliteRun(\n this.db,\n `INSERT INTO memory_lessons (\n lesson_id, project_hash, name, trigger, steps_json, confidence,\n source_session_ids, source_event_ids, failure_modes_json, skill_candidate,\n source_class, revision, recall_enabled, scope, validation_json, reconsider_when, valid_versions_json, created_at, updated_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n [\n lessonId,\n projectHashToStorage(parsed.projectHash),\n parsed.name,\n parsed.trigger,\n JSON.stringify(parsed.steps),\n parsed.confidence,\n JSON.stringify(parsed.sourceSessionIds),\n JSON.stringify(parsed.sourceEventIds),\n JSON.stringify(parsed.failureModes),\n parsed.skillCandidate ? 1 : 0,\n parsed.sourceClass,\n 1,\n parsed.recallEnabled === false ? 0 : 1,\n parsed.scope ?? null,\n JSON.stringify(parsed.validation ?? []),\n parsed.reconsiderWhen ?? null,\n JSON.stringify(parsed.validVersions ?? []),\n now,\n now\n ]\n );\n\n const saved = this.require(lessonId);\n await this.auditLessonUpsert(parsed, null, saved, auditOperation);\n return saved;\n }\n\n get(lessonId: string): MemoryLesson | null {\n const row = sqliteGet<MemoryLessonRow>(this.db, `SELECT * FROM memory_lessons WHERE lesson_id = ?`, [lessonId]);\n return row ? rowToLesson(row) : null;\n }\n\n async list(input: unknown): Promise<MemoryLesson[]> {\n const parsed = ListMemoryLessonsInputSchema.parse(input);\n const clauses = ['project_hash = ?'];\n const params: unknown[] = [projectHashToStorage(parsed.projectHash)];\n if (parsed.skillCandidate !== undefined) {\n clauses.push('skill_candidate = ?');\n params.push(parsed.skillCandidate ? 1 : 0);\n }\n params.push(parsed.limit, parsed.offset);\n const where = clauses.join(' AND ');\n const rows = sqliteAll<MemoryLessonRow>(\n this.db,\n `SELECT * FROM memory_lessons\n WHERE ${where}\n ORDER BY confidence DESC, updated_at DESC, lesson_id ASC\n LIMIT ? OFFSET ?`,\n params\n );\n return rows.map(rowToLesson);\n }\n\n setRecallEnabled(input: { lessonId: string; projectHash: string; expectedRevision: number; enabled: boolean }): MemoryLesson | null {\n const result = sqliteRun(\n this.db,\n `UPDATE memory_lessons\n SET recall_enabled = ?, revision = revision + 1, updated_at = ?\n WHERE lesson_id = ? AND project_hash = ? AND revision = ?`,\n [input.enabled ? 1 : 0, new Date().toISOString(), input.lessonId, projectHashToStorage(input.projectHash), input.expectedRevision]\n );\n return result.changes === 1 ? this.get(input.lessonId) : null;\n }\n\n getByProjectAndName(projectHash: string | undefined, name: string): MemoryLesson | null {\n const row = sqliteGet<MemoryLessonRow>(\n this.db,\n `SELECT * FROM memory_lessons WHERE project_hash = ? AND name = ?`,\n [projectHashToStorage(projectHash), name]\n );\n return row ? rowToLesson(row) : null;\n }\n\n private require(lessonId: string): MemoryLesson {\n const lesson = this.get(lessonId);\n if (!lesson) throw new Error(`Memory lesson not found: ${lessonId}`);\n return lesson;\n }\n\n private async auditLessonUpsert(\n input: ParsedLessonUpsert,\n before: MemoryLesson | null,\n after: MemoryLesson,\n operation: LessonAuditOperation\n ): Promise<void> {\n await writeGovernanceAuditEntry(this.db, {\n operation,\n actor: input.actor ?? 'cml-core',\n projectHash: input.projectHash,\n targetType: 'lesson',\n targetId: after.lessonId,\n beforeJson: before ? lessonToAuditJson(before) : undefined,\n afterJson: lessonToAuditJson(after),\n sourceEventIds: input.sourceEventIds\n });\n }\n}\n", "/**\n * Core types for claude-memory-layer plugin\n * Idris2 inspired: Complete, immutable type definitions with Zod validation\n */\n\nimport { z } from 'zod';\n\n// ============================================================\n// Event Types\n// ============================================================\n\nexport const EventTypeSchema = z.enum([\n 'user_prompt',\n 'agent_response',\n 'session_summary',\n 'tool_observation'\n]);\nexport type EventType = z.infer<typeof EventTypeSchema>;\n\n// ============================================================\n// Memory Event (L0 EventStore)\n// ============================================================\n\nexport const MemoryEventSchema = z.object({\n id: z.string().uuid(),\n eventType: EventTypeSchema,\n sessionId: z.string(),\n timestamp: z.date(),\n content: z.string(),\n canonicalKey: z.string(),\n dedupeKey: z.string(),\n metadata: z.record(z.unknown()).optional()\n});\nexport type MemoryEvent = z.infer<typeof MemoryEventSchema>;\n\n// Input for creating new events (id, dedupeKey generated automatically)\nexport const MemoryEventInputSchema = MemoryEventSchema.omit({\n id: true,\n dedupeKey: true,\n canonicalKey: true\n});\nexport type MemoryEventInput = z.infer<typeof MemoryEventInputSchema>;\n\n// ============================================================\n// Session\n// ============================================================\n\nexport const SessionSchema = z.object({\n id: z.string(),\n startedAt: z.date(),\n endedAt: z.date().optional(),\n projectPath: z.string().optional(),\n summary: z.string().optional(),\n tags: z.array(z.string()).optional()\n});\nexport type Session = z.infer<typeof SessionSchema>;\n\n// ============================================================\n// Insight (L1 Structured)\n// ============================================================\n\nexport const InsightTypeSchema = z.enum([\n 'preference',\n 'pattern',\n 'expertise'\n]);\nexport type InsightType = z.infer<typeof InsightTypeSchema>;\n\nexport const InsightSchema = z.object({\n id: z.string().uuid(),\n insightType: InsightTypeSchema,\n content: z.string(),\n canonicalKey: z.string(),\n confidence: z.number().min(0).max(1),\n sourceEvents: z.array(z.string().uuid()),\n createdAt: z.date(),\n lastUpdated: z.date()\n});\nexport type Insight = z.infer<typeof InsightSchema>;\n\n// ============================================================\n// Memory Match (Search Result)\n// ============================================================\n\nexport const MemoryMatchSchema = z.object({\n event: MemoryEventSchema,\n score: z.number().min(0).max(1),\n relevanceReason: z.string().optional()\n});\nexport type MemoryMatch = z.infer<typeof MemoryMatchSchema>;\n\n// ============================================================\n// Match Confidence (AXIOMMIND)\n// ============================================================\n\nexport const MatchConfidenceSchema = z.enum(['high', 'suggested', 'none']);\nexport type MatchConfidence = z.infer<typeof MatchConfidenceSchema>;\n\nexport const MatchResultSchema = z.object({\n match: MemoryMatchSchema.nullable(),\n confidence: MatchConfidenceSchema,\n gap: z.number().optional(),\n alternatives: z.array(MemoryMatchSchema).optional()\n});\nexport type MatchResult = z.infer<typeof MatchResultSchema>;\n\n// AXIOMMIND Matching Thresholds\nexport const MATCH_THRESHOLDS = {\n minCombinedScore: 0.92,\n minGap: 0.03,\n suggestionThreshold: 0.75\n} as const;\n\n// ============================================================\n// Memory Level (Graduation Pipeline)\n// ============================================================\n\nexport const MemoryLevelSchema = z.enum(['L0', 'L1', 'L2', 'L3', 'L4']);\nexport type MemoryLevel = z.infer<typeof MemoryLevelSchema>;\n\nexport const GraduationResultSchema = z.object({\n eventId: z.string().uuid(),\n fromLevel: MemoryLevelSchema,\n toLevel: MemoryLevelSchema,\n success: z.boolean(),\n reason: z.string().optional()\n});\nexport type GraduationResult = z.infer<typeof GraduationResultSchema>;\n\n// ============================================================\n// Evidence Span (AXIOMMIND Principle 4)\n// ============================================================\n\nexport const EvidenceSpanSchema = z.object({\n start: z.number().int().nonnegative(),\n end: z.number().int().positive(),\n confidence: z.number().min(0).max(1),\n matchType: z.enum(['exact', 'fuzzy', 'none']),\n originalQuote: z.string(),\n alignedText: z.string()\n});\nexport type EvidenceSpan = z.infer<typeof EvidenceSpanSchema>;\n\n// ============================================================\n// Memory Operations Config (AgentMemory-inspired operations layer)\n// ============================================================\n\nexport const PerspectiveConsolidationSpecialistKindSchema = z.enum([\n 'deduction',\n 'induction',\n 'contradiction',\n 'actor_card_maintenance'\n]);\nexport type PerspectiveConsolidationSpecialistKind = z.infer<typeof PerspectiveConsolidationSpecialistKindSchema>;\n\nexport const MemoryOperationsConfigSchema = z.object({\n enabled: z.boolean().default(false),\n facets: z.object({\n enabled: z.boolean().default(true)\n }).default({}),\n actions: z.object({\n enabled: z.boolean().default(true)\n }).default({}),\n retention: z.object({\n enabled: z.boolean().default(false),\n policyVersion: z.string().default('v1')\n }).default({}),\n graphExpansion: z.object({\n enabled: z.boolean().default(false),\n maxHops: z.number().int().min(0).max(5).default(1)\n }).default({}),\n codifyLite: z.object({\n enabled: z.boolean().default(false)\n }).default({}),\n lessons: z.object({\n enabled: z.boolean().default(false)\n }).default({}),\n perspectiveMemory: z.object({\n enabled: z.boolean().default(false),\n deriver: z.object({\n enabled: z.boolean().default(false),\n maxEventsPerBatch: z.number().int().positive().max(100).default(20),\n maxObserversPerSession: z.number().int().positive().max(50).default(5)\n }).default({}),\n specialists: z.object({\n enabled: z.boolean().default(false),\n enabledProjectHashes: z.array(z.string().trim().min(1)).max(100).default([]),\n enabledKinds: z.array(PerspectiveConsolidationSpecialistKindSchema).default([\n 'deduction',\n 'induction',\n 'contradiction',\n 'actor_card_maintenance'\n ]),\n maxSourceObservations: z.number().int().positive().max(100).default(20),\n maxDerivedObservations: z.number().int().min(0).max(20).default(5),\n maxCardUpdates: z.number().int().min(0).max(40).default(3)\n }).default({})\n }).default({})\n}).default({});\nexport type MemoryOperationsConfig = z.infer<typeof MemoryOperationsConfigSchema>;\n\n// ============================================================\n// Procedural Lesson Types (AgentMemory-inspired operations layer)\n// ============================================================\n\nconst MemoryLessonNonEmptyStringSchema = z.string()\n .transform((value) => value.trim())\n .pipe(z.string().min(1));\n\nconst MemoryLessonStringArraySchema = z.preprocess((value) => {\n if (!Array.isArray(value)) return value;\n return value\n .map((item) => typeof item === 'string' ? item.trim() : item)\n .filter((item) => typeof item !== 'string' || item.length > 0);\n}, z.array(MemoryLessonNonEmptyStringSchema)).default([]);\n\nexport const MemoryLessonSourceClassSchema = z.enum(['derived', 'curated']);\nexport type MemoryLessonSourceClass = z.infer<typeof MemoryLessonSourceClassSchema>;\n\nexport const MemoryLessonSchema = z.object({\n lessonId: z.string().uuid(),\n projectHash: MemoryLessonNonEmptyStringSchema.optional(),\n name: MemoryLessonNonEmptyStringSchema,\n trigger: MemoryLessonNonEmptyStringSchema,\n steps: MemoryLessonStringArraySchema.refine((steps) => steps.length > 0, 'steps must contain at least one step'),\n confidence: z.number().min(0).max(1),\n sourceSessionIds: MemoryLessonStringArraySchema,\n sourceEventIds: MemoryLessonStringArraySchema,\n failureModes: MemoryLessonStringArraySchema,\n skillCandidate: z.boolean().default(false),\n sourceClass: MemoryLessonSourceClassSchema.default('derived'),\n revision: z.number().int().positive().default(1),\n recallEnabled: z.boolean().default(true),\n scope: MemoryLessonNonEmptyStringSchema.optional(),\n validation: MemoryLessonStringArraySchema,\n reconsiderWhen: MemoryLessonNonEmptyStringSchema.optional(),\n validVersions: MemoryLessonStringArraySchema,\n createdAt: z.date(),\n updatedAt: z.date()\n});\nexport type MemoryLesson = z.infer<typeof MemoryLessonSchema>;\n\nexport const UpsertMemoryLessonInputSchema = z.object({\n lessonId: z.string().uuid().optional(),\n projectHash: MemoryLessonNonEmptyStringSchema.optional(),\n name: MemoryLessonNonEmptyStringSchema,\n trigger: MemoryLessonNonEmptyStringSchema,\n steps: MemoryLessonStringArraySchema.refine((steps) => steps.length > 0, 'steps must contain at least one step'),\n confidence: z.number().min(0).max(1).default(0.5),\n sourceSessionIds: MemoryLessonStringArraySchema,\n sourceEventIds: MemoryLessonStringArraySchema,\n failureModes: MemoryLessonStringArraySchema,\n skillCandidate: z.boolean().default(false),\n sourceClass: MemoryLessonSourceClassSchema.default('derived'),\n recallEnabled: z.boolean().optional(),\n scope: MemoryLessonNonEmptyStringSchema.optional(),\n validation: MemoryLessonStringArraySchema.optional(),\n reconsiderWhen: MemoryLessonNonEmptyStringSchema.optional(),\n validVersions: MemoryLessonStringArraySchema.optional(),\n actor: MemoryLessonNonEmptyStringSchema.optional()\n}).superRefine((value, ctx) => {\n if (value.sourceSessionIds.length === 0 && value.sourceEventIds.length === 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['sourceEventIds'],\n message: 'sourceSessionIds or sourceEventIds is required'\n });\n }\n});\nexport type UpsertMemoryLessonInput = z.input<typeof UpsertMemoryLessonInputSchema>;\n\nexport const ListMemoryLessonsInputSchema = z.object({\n projectHash: MemoryLessonNonEmptyStringSchema.optional(),\n skillCandidate: z.boolean().optional(),\n limit: z.number().int().positive().max(500).default(50),\n offset: z.number().int().nonnegative().default(0)\n});\nexport type ListMemoryLessonsInput = z.input<typeof ListMemoryLessonsInputSchema>;\n\n// ============================================================\n// Honcho-inspired Perspective Memory Types\n// ============================================================\n\nconst PerspectiveMemoryNonEmptyStringSchema = z.string()\n .transform((value) => value.trim())\n .pipe(z.string().min(1));\n\nconst PerspectiveMemoryOptionalStringSchema = z.preprocess((value) => {\n if (typeof value !== 'string') return value;\n const normalized = value.trim();\n return normalized.length > 0 ? normalized : undefined;\n}, PerspectiveMemoryNonEmptyStringSchema.optional());\n\nconst PerspectiveMemoryStringArraySchema = z.preprocess((value) => {\n if (!Array.isArray(value)) return value;\n return value\n .map((item) => typeof item === 'string' ? item.trim() : item)\n .filter((item) => typeof item !== 'string' || item.length > 0);\n}, z.array(PerspectiveMemoryNonEmptyStringSchema)).default([]);\n\nconst ActorCardSensitivePattern = /(?:\\b(?:api[_-]?key|secret|password|passwd|token|access[_-]?token|client[_-]?secret|bearer)\\b\\s*[:=])|(?:\\b(?:api[_-]?key|secret|password|passwd|token|access[_-]?token|client[_-]?secret|bearer)=)|(?:^|\\s)(?:\\/[A-Za-z0-9._-][^\\s`'\\\"]*)/i;\n\nexport const MemoryActorKindSchema = z.enum([\n 'user',\n 'assistant',\n 'subagent',\n 'tool',\n 'system',\n 'integration',\n 'unknown'\n]);\nexport type MemoryActorKind = z.infer<typeof MemoryActorKindSchema>;\n\nexport const SessionActorRoleSchema = z.enum([\n 'speaker',\n 'assistant',\n 'observer',\n 'tool',\n 'system',\n 'unknown'\n]);\nexport type SessionActorRole = z.infer<typeof SessionActorRoleSchema>;\n\nexport const PerspectiveObservationLevelSchema = z.enum([\n 'explicit',\n 'deductive',\n 'inductive',\n 'contradiction'\n]);\nexport type PerspectiveObservationLevel = z.infer<typeof PerspectiveObservationLevelSchema>;\n\nexport const PerspectiveObservationCreatedBySchema = z.enum(['rule', 'llm', 'manual', 'import']);\nexport type PerspectiveObservationCreatedBy = z.infer<typeof PerspectiveObservationCreatedBySchema>;\n\nexport const ActorCardEntryPrefixSchema = z.enum([\n 'IDENTITY',\n 'ATTRIBUTE',\n 'RELATIONSHIP',\n 'INSTRUCTION'\n]);\nexport type ActorCardEntryPrefix = z.infer<typeof ActorCardEntryPrefixSchema>;\n\nexport const ActorCardEntrySchema = z.string()\n .transform((value) => value.trim())\n .pipe(\n z.string()\n .min(1)\n .max(200, 'actor card entry must be at most 200 characters')\n .refine(\n (value) => /^(IDENTITY|ATTRIBUTE|RELATIONSHIP|INSTRUCTION):\\s*\\S/.test(value),\n 'actor card entry prefix must be one of IDENTITY:, ATTRIBUTE:, RELATIONSHIP:, or INSTRUCTION:'\n )\n .refine(\n (value) => !ActorCardSensitivePattern.test(value),\n 'actor card entry contains secret, redacted, sensitive, or path-like content'\n )\n );\nexport type ActorCardEntry = z.infer<typeof ActorCardEntrySchema>;\n\nexport const MemoryActorSchema = z.object({\n actorId: PerspectiveMemoryNonEmptyStringSchema,\n projectHash: PerspectiveMemoryOptionalStringSchema,\n kind: MemoryActorKindSchema,\n displayName: PerspectiveMemoryNonEmptyStringSchema,\n source: PerspectiveMemoryNonEmptyStringSchema,\n metadata: z.record(z.unknown()).optional(),\n createdAt: z.date(),\n updatedAt: z.date()\n});\nexport type MemoryActor = z.infer<typeof MemoryActorSchema>;\n\nexport const UpsertMemoryActorInputSchema = z.object({\n actorId: PerspectiveMemoryOptionalStringSchema,\n projectHash: PerspectiveMemoryOptionalStringSchema,\n kind: MemoryActorKindSchema.default('unknown'),\n displayName: PerspectiveMemoryNonEmptyStringSchema,\n source: PerspectiveMemoryNonEmptyStringSchema,\n metadata: z.record(z.unknown()).optional()\n});\nexport type UpsertMemoryActorInput = z.input<typeof UpsertMemoryActorInputSchema>;\n\nexport const ListMemoryActorsInputSchema = z.object({\n projectHash: PerspectiveMemoryOptionalStringSchema,\n kind: MemoryActorKindSchema.optional(),\n source: PerspectiveMemoryOptionalStringSchema,\n limit: z.number().int().positive().max(500).default(100)\n});\nexport type ListMemoryActorsInput = z.input<typeof ListMemoryActorsInputSchema>;\n\nexport const SessionActorSchema = z.object({\n projectHash: PerspectiveMemoryOptionalStringSchema,\n sessionId: PerspectiveMemoryNonEmptyStringSchema,\n actorId: PerspectiveMemoryNonEmptyStringSchema,\n roleInSession: SessionActorRoleSchema,\n observeSelf: z.boolean().default(true),\n observeOthers: z.boolean().default(false),\n joinedAt: z.date(),\n leftAt: z.date().optional(),\n metadata: z.record(z.unknown()).optional()\n});\nexport type SessionActor = z.infer<typeof SessionActorSchema>;\n\nexport const UpsertSessionActorInputSchema = z.object({\n projectHash: PerspectiveMemoryOptionalStringSchema,\n sessionId: PerspectiveMemoryNonEmptyStringSchema,\n actorId: PerspectiveMemoryNonEmptyStringSchema,\n roleInSession: SessionActorRoleSchema.default('unknown'),\n observeSelf: z.boolean().default(true),\n observeOthers: z.boolean().default(false),\n joinedAt: z.date().optional(),\n leftAt: z.date().optional(),\n metadata: z.record(z.unknown()).optional()\n});\nexport type UpsertSessionActorInput = z.input<typeof UpsertSessionActorInputSchema>;\n\nexport const ListSessionActorsInputSchema = z.object({\n projectHash: PerspectiveMemoryOptionalStringSchema,\n sessionId: PerspectiveMemoryNonEmptyStringSchema,\n limit: z.number().int().positive().max(500).default(100)\n});\nexport type ListSessionActorsInput = z.input<typeof ListSessionActorsInputSchema>;\n\nexport const SetSessionActorObservationPolicyInputSchema = z.object({\n projectHash: PerspectiveMemoryOptionalStringSchema,\n sessionId: PerspectiveMemoryNonEmptyStringSchema,\n actorId: PerspectiveMemoryNonEmptyStringSchema,\n observeSelf: z.boolean(),\n observeOthers: z.boolean()\n});\nexport type SetSessionActorObservationPolicyInput = z.input<typeof SetSessionActorObservationPolicyInputSchema>;\n\nexport const ActorCardSchema = z.object({\n cardId: z.string().uuid(),\n projectHash: PerspectiveMemoryOptionalStringSchema,\n observerActorId: PerspectiveMemoryNonEmptyStringSchema,\n observedActorId: PerspectiveMemoryNonEmptyStringSchema,\n entries: z.array(ActorCardEntrySchema).max(40),\n sourceEventIds: PerspectiveMemoryStringArraySchema,\n updatedBy: PerspectiveMemoryOptionalStringSchema,\n createdAt: z.date(),\n updatedAt: z.date()\n});\nexport type ActorCard = z.infer<typeof ActorCardSchema>;\n\nexport const UpsertActorCardInputSchema = z.object({\n projectHash: PerspectiveMemoryOptionalStringSchema,\n observerActorId: PerspectiveMemoryNonEmptyStringSchema,\n observedActorId: PerspectiveMemoryNonEmptyStringSchema,\n entries: z.array(ActorCardEntrySchema).min(1).max(40, 'actor card supports at most 40 entries'),\n sourceEventIds: PerspectiveMemoryStringArraySchema,\n updatedBy: PerspectiveMemoryOptionalStringSchema\n});\nexport type UpsertActorCardInput = z.input<typeof UpsertActorCardInputSchema>;\n\nexport const GetActorCardInputSchema = z.object({\n projectHash: PerspectiveMemoryOptionalStringSchema,\n observerActorId: PerspectiveMemoryNonEmptyStringSchema,\n observedActorId: PerspectiveMemoryNonEmptyStringSchema\n});\nexport type GetActorCardInput = z.input<typeof GetActorCardInputSchema>;\n\n// ============================================================\n// Core Memory Blocks (Letta-inspired always-injected, self-editable state)\n// ============================================================\n\nexport const CoreMemoryBlockKeySchema = z.enum(['project', 'user']);\nexport type CoreMemoryBlockKey = z.infer<typeof CoreMemoryBlockKeySchema>;\n\nexport const CORE_MEMORY_BLOCK_MAX_CHARS = 1200;\n\nexport const CoreMemoryBlockSchema = z.object({\n projectHash: PerspectiveMemoryOptionalStringSchema,\n blockKey: CoreMemoryBlockKeySchema,\n content: z.string().max(CORE_MEMORY_BLOCK_MAX_CHARS),\n sourceEventIds: PerspectiveMemoryStringArraySchema,\n updatedBy: PerspectiveMemoryOptionalStringSchema,\n createdAt: z.date(),\n updatedAt: z.date()\n});\nexport type CoreMemoryBlock = z.infer<typeof CoreMemoryBlockSchema>;\n\nexport const UpsertCoreMemoryBlockInputSchema = z.object({\n projectHash: PerspectiveMemoryOptionalStringSchema,\n blockKey: CoreMemoryBlockKeySchema,\n content: z.string().trim().max(\n CORE_MEMORY_BLOCK_MAX_CHARS,\n `core memory block supports at most ${CORE_MEMORY_BLOCK_MAX_CHARS} characters`\n ),\n sourceEventIds: PerspectiveMemoryStringArraySchema,\n updatedBy: PerspectiveMemoryOptionalStringSchema\n});\nexport type UpsertCoreMemoryBlockInput = z.input<typeof UpsertCoreMemoryBlockInputSchema>;\n\nexport const GetCoreMemoryBlockInputSchema = z.object({\n projectHash: PerspectiveMemoryOptionalStringSchema,\n blockKey: CoreMemoryBlockKeySchema.optional()\n});\nexport type GetCoreMemoryBlockInput = z.input<typeof GetCoreMemoryBlockInputSchema>;\n\nexport const PerspectiveObservationSchema = z.object({\n observationId: z.string().uuid(),\n projectHash: PerspectiveMemoryOptionalStringSchema,\n observerActorId: PerspectiveMemoryNonEmptyStringSchema,\n observedActorId: PerspectiveMemoryNonEmptyStringSchema,\n sessionId: PerspectiveMemoryOptionalStringSchema,\n level: PerspectiveObservationLevelSchema,\n content: PerspectiveMemoryNonEmptyStringSchema,\n confidence: z.number().min(0).max(1),\n sourceEventIds: PerspectiveMemoryStringArraySchema,\n sourceObservationIds: PerspectiveMemoryStringArraySchema,\n createdBy: PerspectiveObservationCreatedBySchema,\n metadata: z.record(z.unknown()).optional(),\n createdAt: z.date(),\n updatedAt: z.date(),\n deletedAt: z.date().optional()\n});\nexport type PerspectiveObservation = z.infer<typeof PerspectiveObservationSchema>;\n\nexport const CreatePerspectiveObservationInputSchema = z.object({\n observationId: z.string().uuid().optional(),\n projectHash: PerspectiveMemoryOptionalStringSchema,\n observerActorId: PerspectiveMemoryNonEmptyStringSchema,\n observedActorId: PerspectiveMemoryNonEmptyStringSchema,\n sessionId: PerspectiveMemoryOptionalStringSchema,\n level: PerspectiveObservationLevelSchema.default('explicit'),\n content: PerspectiveMemoryNonEmptyStringSchema,\n confidence: z.number().min(0).max(1).default(0.5),\n sourceEventIds: PerspectiveMemoryStringArraySchema,\n sourceObservationIds: PerspectiveMemoryStringArraySchema,\n createdBy: PerspectiveObservationCreatedBySchema.default('manual'),\n metadata: z.record(z.unknown()).optional(),\n actor: PerspectiveMemoryOptionalStringSchema\n}).superRefine((value, ctx) => {\n const hasEvidence = value.sourceEventIds.length > 0 || value.sourceObservationIds.length > 0;\n if ((value.createdBy !== 'manual' || value.level !== 'explicit') && !hasEvidence) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['sourceEventIds'],\n message: 'source evidence is required for non-manual or derived perspective observations'\n });\n }\n});\nexport type CreatePerspectiveObservationInput = z.input<typeof CreatePerspectiveObservationInputSchema>;\n\nexport const QueryPerspectiveObservationsInputSchema = z.object({\n projectHash: PerspectiveMemoryOptionalStringSchema,\n observerActorId: PerspectiveMemoryOptionalStringSchema,\n observedActorId: PerspectiveMemoryOptionalStringSchema,\n sessionId: PerspectiveMemoryOptionalStringSchema,\n levels: z.array(PerspectiveObservationLevelSchema).optional(),\n query: PerspectiveMemoryOptionalStringSchema,\n includeDeleted: z.boolean().default(false),\n limit: z.number().int().positive().max(500).default(50)\n});\nexport type QueryPerspectiveObservationsInput = z.input<typeof QueryPerspectiveObservationsInputSchema>;\n\nexport const DeletePerspectiveObservationInputSchema = z.object({\n projectHash: PerspectiveMemoryOptionalStringSchema,\n observationId: PerspectiveMemoryNonEmptyStringSchema,\n actor: PerspectiveMemoryNonEmptyStringSchema\n});\nexport type DeletePerspectiveObservationInput = z.input<typeof DeletePerspectiveObservationInputSchema>;\n\nexport const ListPerspectiveObservationsBySourceInputSchema = z.object({\n projectHash: PerspectiveMemoryOptionalStringSchema,\n sourceEventId: PerspectiveMemoryNonEmptyStringSchema,\n limit: z.number().int().positive().max(500).default(100)\n});\nexport type ListPerspectiveObservationsBySourceInput = z.input<typeof ListPerspectiveObservationsBySourceInputSchema>;\n\n// ============================================================\n// Configuration\n// ============================================================\n\nexport const ConfigSchema = z.object({\n storage: z.object({\n path: z.string().default('~/.claude-code/memory'),\n maxSizeMB: z.number().default(500)\n }).default({}),\n embedding: z.object({\n provider: z.enum(['local', 'openai']).default('local'),\n model: z.string().default('Xenova/multilingual-e5-small'),\n openaiModel: z.string().default('Xenova/multilingual-e5-small'),\n batchSize: z.number().default(32)\n }).default({}),\n retrieval: z.object({\n topK: z.number().default(5),\n minScore: z.number().default(0.7),\n maxTokens: z.number().default(2000)\n }).default({}),\n matching: z.object({\n minCombinedScore: z.number().default(0.92),\n minGap: z.number().default(0.03),\n suggestionThreshold: z.number().default(0.75),\n weights: z.object({\n semanticSimilarity: z.number().default(0.4),\n ftsScore: z.number().default(0.25),\n recencyBonus: z.number().default(0.2),\n statusWeight: z.number().default(0.15)\n }).default({})\n }).default({}),\n privacy: z.object({\n excludePatterns: z.array(z.string()).default(['password', 'secret', 'api_key', 'token', 'bearer']),\n anonymize: z.boolean().default(false),\n privateTags: z.object({\n enabled: z.boolean().default(true),\n marker: z.enum(['[PRIVATE]', '[REDACTED]', '']).default('[PRIVATE]'),\n preserveLineCount: z.boolean().default(false),\n supportedFormats: z.array(z.enum(['xml', 'bracket', 'comment'])).default(['xml'])\n }).default({})\n }).default({}),\n toolObservation: z.object({\n enabled: z.boolean().default(true),\n excludedTools: z.array(z.string()).default(['TodoWrite', 'TodoRead']),\n minOutputLength: z.number().default(100),\n maxOutputLength: z.number().default(10000),\n maxOutputLines: z.number().default(100),\n storeOnlyOnSuccess: z.boolean().default(false)\n }).default({}),\n features: z.object({\n autoSave: z.boolean().default(true),\n sessionSummary: z.boolean().default(true),\n insightExtraction: z.boolean().default(true),\n crossProjectLearning: z.boolean().default(false),\n singleWriterMode: z.boolean().default(true),\n sharedStore: z.object({\n enabled: z.boolean().default(true),\n autoPromote: z.boolean().default(true),\n searchShared: z.boolean().default(true),\n minConfidenceForPromotion: z.number().default(0.8),\n sharedStoragePath: z.string().default('~/.claude-code/memory/shared')\n }).default({})\n }).default({}),\n operations: MemoryOperationsConfigSchema,\n mode: z.enum(['session', 'endless']).default('session'),\n endless: z.object({\n enabled: z.boolean().default(false),\n workingSet: z.object({\n maxEvents: z.number().default(100),\n timeWindowHours: z.number().default(24),\n minRelevanceScore: z.number().default(0.5)\n }).default({}),\n consolidation: z.object({\n triggerIntervalMs: z.number().default(3600000),\n triggerEventCount: z.number().default(100),\n triggerIdleMs: z.number().default(1800000),\n useLLMSummarization: z.boolean().default(false)\n }).default({}),\n continuity: z.object({\n minScoreForSeamless: z.number().default(0.7),\n topicDecayHours: z.number().default(48)\n }).default({})\n }).optional()\n});\nexport type Config = z.infer<typeof ConfigSchema>;\n\n// ============================================================\n// Append Result (AXIOMMIND Principle 2: Append-only)\n// ============================================================\n\nexport type AppendResult =\n | { success: true; eventId: string; isDuplicate: false }\n | { success: true; eventId: string; isDuplicate: true }\n | { success: false; error: string };\n\n// ============================================================\n// Hook Input/Output Types\n// ============================================================\n\nexport interface SessionStartInput {\n session_id: string;\n cwd: string;\n actor_id?: string;\n}\n\nexport interface SessionStartOutput {\n hookSpecificOutput: {\n hookEventName: 'SessionStart';\n additionalContext?: string;\n };\n}\n\nexport interface UserPromptSubmitInput {\n session_id: string;\n prompt: string;\n actor_id?: string;\n}\n\nexport interface UserPromptSubmitOutput {\n hookSpecificOutput: {\n hookEventName: 'UserPromptSubmit';\n additionalContext?: string;\n };\n}\n\n// Stop Hook Input (matches actual Claude Code hook format)\nexport interface StopInput {\n session_id: string;\n transcript_path: string;\n cwd: string;\n permission_mode: string;\n hook_event_name: string;\n stop_hook_active: boolean;\n}\n\nexport interface SessionEndInput {\n session_id: string;\n}\n\n// PostToolUse Hook Input (matches actual Claude Code hook format)\nexport interface PostToolUseInput {\n session_id: string;\n hook_event_name: string;\n tool_name: string;\n tool_input: Record<string, unknown>;\n tool_use_id: string;\n // Claude Code sends tool_response as an object, not tool_output as string\n tool_response: {\n stdout?: string;\n stderr?: string;\n content?: string;\n interrupted?: boolean;\n isImage?: boolean;\n // For non-Bash tools, response may be a plain string or other format\n [key: string]: unknown;\n };\n cwd: string;\n transcript_path: string;\n permission_mode: string;\n}\n\n// ============================================================\n// Tool Observation Types\n// ============================================================\n\nexport const ToolMetadataSchema = z.object({\n filePath: z.string().optional(),\n fileType: z.string().optional(),\n lineCount: z.number().optional(),\n command: z.string().optional(),\n exitCode: z.number().optional(),\n pattern: z.string().optional(),\n matchCount: z.number().optional(),\n url: z.string().optional(),\n statusCode: z.number().optional()\n});\nexport type ToolMetadata = z.infer<typeof ToolMetadataSchema>;\n\nexport const ToolObservationPayloadSchema = z.object({\n toolName: z.string(),\n toolInput: z.record(z.unknown()),\n toolOutput: z.string(),\n durationMs: z.number(),\n success: z.boolean(),\n errorMessage: z.string().optional(),\n metadata: ToolMetadataSchema.optional()\n});\nexport type ToolObservationPayload = z.infer<typeof ToolObservationPayloadSchema>;\n\n// ============================================================\n// Vector Record\n// ============================================================\n\nexport interface VectorRecord {\n id: string;\n eventId: string;\n sessionId: string;\n eventType: string;\n content: string;\n vector: number[];\n timestamp: string;\n metadata?: Record<string, unknown>;\n}\n\n// ============================================================\n// Outbox Item (Single-Writer Pattern)\n// ============================================================\n\nexport interface OutboxItem {\n id: string;\n eventId: string;\n content: string;\n status: 'pending' | 'processing' | 'done' | 'failed';\n retryCount: number;\n createdAt: Date;\n errorMessage?: string;\n}\n\nexport interface OutboxStatsOptions {\n /** Processing rows older than this threshold are considered abandoned/stuck. */\n stuckThresholdMs?: number;\n /** Failed rows below this retry budget are counted as retryable; rows at/above it are counted as quarantined. */\n maxRetries?: number;\n /** Test hook for deterministic age calculations. */\n now?: Date;\n}\n\nexport interface OutboxQueueStats {\n pending: number;\n processing: number;\n failed: number;\n /** Failed rows that recovery can safely move back to pending without exposing payloads. */\n retryableFailed?: number;\n /** Failed rows at/above retry budget that need operator attention/quarantine handling. */\n quarantinedFailed?: number;\n total: number;\n stuckProcessing: number;\n /** Age in milliseconds for the oldest processing row, or null when none are processing. */\n oldestProcessingAgeMs: number | null;\n}\n\nexport interface OutboxStats {\n embedding: OutboxQueueStats;\n vector: OutboxQueueStats;\n}\n\nexport interface OutboxRecoveryOptions {\n /** Processing rows older than this threshold are considered abandoned. */\n stuckThresholdMs?: number;\n /** Retry failed rows whose retry_count is still below this value. */\n maxRetries?: number;\n /** Count rows that would be recovered/retried without mutating them. */\n dryRun?: boolean;\n /** Test hook for deterministic recovery cutoffs. */\n now?: Date;\n}\n\nexport interface OutboxRecoveryBucket {\n recoveredProcessing: number;\n retriedFailed: number;\n}\n\nexport interface OutboxRecoveryResult {\n embedding: OutboxRecoveryBucket;\n vector: OutboxRecoveryBucket;\n}\n\nexport interface ProjectScopeRepairOptions {\n /** Absolute or logical project path used to derive the expected project hash. */\n projectPath?: string;\n /** Explicit project hash override for hash-only repair flows. */\n projectHash?: string;\n /** Inspect and count changes without mutating event metadata. */\n dryRun?: boolean;\n /** Test hook for deterministic repair metadata. */\n now?: Date;\n}\n\nexport interface ProjectScopeRepairSample {\n eventId: string;\n action: 'repaired' | 'quarantined';\n reason: 'same-project-path' | 'session-project-path' | 'project-path-mismatch' | 'missing-project-scope' | 'scope-hash-mismatch' | 'content-project-mismatch';\n}\n\nexport interface ProjectScopeRepairResult {\n dryRun: boolean;\n projectHash: string;\n scanned: number;\n repaired: number;\n quarantined: number;\n alreadyScoped: number;\n skipped: number;\n samples: ProjectScopeRepairSample[];\n}\n\n// ============================================================\n// Entity Types (Task, Condition, Artifact)\n// ============================================================\n\nexport const EntityTypeSchema = z.enum(['task', 'condition', 'artifact', 'source_file']);\nexport type EntityType = z.infer<typeof EntityTypeSchema>;\n\nexport const TaskStatusSchema = z.enum([\n 'pending',\n 'in_progress',\n 'blocked',\n 'done',\n 'cancelled'\n]);\nexport type TaskStatus = z.infer<typeof TaskStatusSchema>;\n\nexport const TaskPrioritySchema = z.enum(['low', 'medium', 'high', 'critical']);\nexport type TaskPriority = z.infer<typeof TaskPrioritySchema>;\n\nexport const EntityStageSchema = z.enum([\n 'raw',\n 'working',\n 'candidate',\n 'verified',\n 'certified'\n]);\nexport type EntityStage = z.infer<typeof EntityStageSchema>;\n\nexport const EntityStatusSchema = z.enum([\n 'active',\n 'contested',\n 'deprecated',\n 'superseded'\n]);\nexport type EntityStatus = z.infer<typeof EntityStatusSchema>;\n\n// Base Entity schema\nexport const EntitySchema = z.object({\n entityId: z.string(),\n entityType: EntityTypeSchema,\n canonicalKey: z.string(),\n title: z.string(),\n stage: EntityStageSchema,\n status: EntityStatusSchema,\n currentJson: z.record(z.unknown()),\n titleNorm: z.string().optional(),\n searchText: z.string().optional(),\n createdAt: z.date(),\n updatedAt: z.date()\n});\nexport type Entity = z.infer<typeof EntitySchema>;\n\n// Task-specific current_json structure\nexport const TaskCurrentJsonSchema = z.object({\n status: TaskStatusSchema,\n priority: TaskPrioritySchema.optional(),\n blockers: z.array(z.string()).optional(),\n blockerSuggestions: z.array(z.string()).optional(),\n description: z.string().optional(),\n project: z.string().optional()\n});\nexport type TaskCurrentJson = z.infer<typeof TaskCurrentJsonSchema>;\n\n// Entity alias for canonical key lookup\nexport const EntityAliasSchema = z.object({\n entityType: EntityTypeSchema,\n canonicalKey: z.string(),\n entityId: z.string(),\n isPrimary: z.boolean()\n});\nexport type EntityAlias = z.infer<typeof EntityAliasSchema>;\n\n// ============================================================\n// Edge Types (Relationships)\n// ============================================================\n\nexport const NodeTypeSchema = z.enum(['entry', 'entity', 'event']);\nexport type NodeType = z.infer<typeof NodeTypeSchema>;\n\nexport const RelationTypeSchema = z.enum([\n 'evidence_of',\n 'blocked_by',\n 'blocked_by_suggested',\n 'resolves_to',\n 'derived_from',\n 'supersedes',\n 'source_of',\n 'touched_in'\n]);\nexport type RelationType = z.infer<typeof RelationTypeSchema>;\n\nexport const EdgeSchema = z.object({\n edgeId: z.string(),\n srcType: NodeTypeSchema,\n srcId: z.string(),\n relType: RelationTypeSchema,\n dstType: NodeTypeSchema,\n dstId: z.string(),\n metaJson: z.record(z.unknown()).optional(),\n createdAt: z.date()\n});\nexport type Edge = z.infer<typeof EdgeSchema>;\n\n// ============================================================\n// Task Event Types (SoT for Task Entity)\n// ============================================================\n\nexport const TaskEventTypeSchema = z.enum([\n 'task_created',\n 'task_status_changed',\n 'task_priority_changed',\n 'task_blockers_set',\n 'task_transition_rejected',\n 'condition_declared',\n 'artifact_declared',\n 'condition_resolved_to'\n]);\nexport type TaskEventType = z.infer<typeof TaskEventTypeSchema>;\n\nexport const BlockerModeSchema = z.enum(['replace', 'suggest']);\nexport type BlockerMode = z.infer<typeof BlockerModeSchema>;\n\nexport const BlockerKindSchema = z.enum(['task', 'condition', 'artifact']);\nexport type BlockerKind = z.infer<typeof BlockerKindSchema>;\n\nexport const BlockerRefSchema = z.object({\n kind: BlockerKindSchema,\n entityId: z.string(),\n rawText: z.string().optional(),\n confidence: z.number().min(0).max(1).optional(),\n candidates: z.array(z.string()).optional()\n});\nexport type BlockerRef = z.infer<typeof BlockerRefSchema>;\n\n// Task event payloads\nexport const TaskCreatedPayloadSchema = z.object({\n taskId: z.string(),\n title: z.string(),\n canonicalKey: z.string(),\n initialStatus: TaskStatusSchema,\n priority: TaskPrioritySchema.optional(),\n description: z.string().optional(),\n project: z.string().optional()\n});\nexport type TaskCreatedPayload = z.infer<typeof TaskCreatedPayloadSchema>;\n\nexport const TaskStatusChangedPayloadSchema = z.object({\n taskId: z.string(),\n fromStatus: TaskStatusSchema,\n toStatus: TaskStatusSchema,\n reason: z.string().optional()\n});\nexport type TaskStatusChangedPayload = z.infer<typeof TaskStatusChangedPayloadSchema>;\n\nexport const TaskBlockersSetPayloadSchema = z.object({\n taskId: z.string(),\n mode: BlockerModeSchema,\n blockers: z.array(BlockerRefSchema),\n sourceEntryId: z.string().optional()\n});\nexport type TaskBlockersSetPayload = z.infer<typeof TaskBlockersSetPayloadSchema>;\n\n// ============================================================\n// Entry Types (Immutable memory units)\n// ============================================================\n\nexport const EntryTypeSchema = z.enum([\n 'fact',\n 'decision',\n 'insight',\n 'task_note',\n 'reference',\n 'preference',\n 'pattern',\n 'troubleshooting'\n]);\nexport type EntryType = z.infer<typeof EntryTypeSchema>;\n\nexport const EntrySchema = z.object({\n entryId: z.string(),\n createdTs: z.date(),\n entryType: EntryTypeSchema,\n title: z.string(),\n contentJson: z.record(z.unknown()),\n stage: EntityStageSchema,\n status: EntityStatusSchema,\n supersededBy: z.string().optional(),\n buildId: z.string().optional(),\n evidenceJson: z.record(z.unknown()).optional(),\n canonicalKey: z.string()\n});\nexport type Entry = z.infer<typeof EntrySchema>;\n\n// ============================================================\n// Evidence Aligner V2 Types\n// ============================================================\n\nexport const ExtractedEvidenceSchema = z.object({\n messageIndex: z.number().int().nonnegative(),\n quote: z.string()\n});\nexport type ExtractedEvidence = z.infer<typeof ExtractedEvidenceSchema>;\n\nexport const AlignedEvidenceSchema = z.object({\n messageIndex: z.number().int().nonnegative(),\n quote: z.string(),\n spanStart: z.number().int().nonnegative(),\n spanEnd: z.number().int().positive(),\n quoteHash: z.string(),\n confidence: z.number().min(0).max(1),\n matchMethod: z.enum(['exact', 'normalized', 'fuzzy'])\n});\nexport type AlignedEvidence = z.infer<typeof AlignedEvidenceSchema>;\n\nexport const FailedEvidenceSchema = z.object({\n messageIndex: z.number().int().nonnegative(),\n quote: z.string(),\n failureReason: z.enum(['not_found', 'below_threshold', 'ambiguous', 'empty_quote', 'invalid_index'])\n});\nexport type FailedEvidence = z.infer<typeof FailedEvidenceSchema>;\n\nexport const EvidenceAlignResultSchema = z.discriminatedUnion('aligned', [\n z.object({ aligned: z.literal(true), evidence: AlignedEvidenceSchema }),\n z.object({ aligned: z.literal(false), evidence: FailedEvidenceSchema })\n]);\nexport type EvidenceAlignResult = z.infer<typeof EvidenceAlignResultSchema>;\n\n// ============================================================\n// Vector Outbox V2 Types\n// ============================================================\n\nexport const OutboxStatusSchema = z.enum(['pending', 'processing', 'done', 'failed']);\nexport type OutboxStatus = z.infer<typeof OutboxStatusSchema>;\n\nexport const OutboxItemKindSchema = z.enum(['entry', 'task_title', 'event', 'perspective_observation']);\nexport type OutboxItemKind = z.infer<typeof OutboxItemKindSchema>;\n\nexport const OutboxJobSchema = z.object({\n jobId: z.string(),\n itemKind: OutboxItemKindSchema,\n itemId: z.string(),\n embeddingVersion: z.string(),\n status: OutboxStatusSchema,\n retryCount: z.number().int().nonnegative(),\n error: z.string().optional(),\n createdAt: z.date(),\n updatedAt: z.date()\n});\nexport type OutboxJob = z.infer<typeof OutboxJobSchema>;\n\n// Valid state transitions for outbox\nexport const VALID_OUTBOX_TRANSITIONS: Array<{ from: OutboxStatus; to: OutboxStatus }> = [\n { from: 'pending', to: 'processing' },\n { from: 'processing', to: 'done' },\n { from: 'processing', to: 'failed' },\n { from: 'failed', to: 'pending' }\n];\n\n// ============================================================\n// Build Runs (Pipeline metadata)\n// ============================================================\n\nexport const BuildRunSchema = z.object({\n buildId: z.string(),\n startedAt: z.date(),\n finishedAt: z.date().optional(),\n extractorModel: z.string(),\n extractorPromptHash: z.string(),\n embedderModel: z.string(),\n embeddingVersion: z.string(),\n idrisVersion: z.string(),\n schemaVersion: z.string(),\n status: z.enum(['running', 'success', 'failed']),\n error: z.string().optional()\n});\nexport type BuildRun = z.infer<typeof BuildRunSchema>;\n\n// ============================================================\n// Pipeline Metrics\n// ============================================================\n\nexport const PipelineMetricSchema = z.object({\n id: z.string(),\n ts: z.date(),\n stage: z.string(),\n latencyMs: z.number(),\n success: z.boolean(),\n error: z.string().optional(),\n sessionId: z.string().optional()\n});\nexport type PipelineMetric = z.infer<typeof PipelineMetricSchema>;\n\n// ============================================================\n// Progressive Disclosure Types\n// ============================================================\n\n// Layer 1: Search Index (lightweight)\nexport const SearchIndexItemSchema = z.object({\n id: z.string(),\n summary: z.string().max(100),\n score: z.number(),\n type: z.enum(['user_prompt', 'agent_response', 'session_summary', 'tool_observation']),\n timestamp: z.date(),\n sessionId: z.string()\n});\nexport type SearchIndexItem = z.infer<typeof SearchIndexItemSchema>;\n\n// Layer 2: Timeline\nexport const TimelineItemSchema = z.object({\n id: z.string(),\n timestamp: z.date(),\n type: z.enum(['user_prompt', 'agent_response', 'session_summary', 'tool_observation']),\n preview: z.string().max(200),\n isTarget: z.boolean()\n});\nexport type TimelineItem = z.infer<typeof TimelineItemSchema>;\n\n// Layer 3: Full Detail\nexport const FullDetailSchema = z.object({\n id: z.string(),\n content: z.string(),\n type: z.enum(['user_prompt', 'agent_response', 'session_summary', 'tool_observation']),\n timestamp: z.date(),\n sessionId: z.string(),\n citationId: z.string().optional(),\n metadata: z.object({\n tokenCount: z.number(),\n hasCode: z.boolean(),\n files: z.array(z.string()).optional(),\n tools: z.array(z.string()).optional()\n })\n});\nexport type FullDetail = z.infer<typeof FullDetailSchema>;\n\n// Progressive Search Result\nexport const ProgressiveSearchResultSchema = z.object({\n index: z.array(SearchIndexItemSchema),\n timeline: z.array(TimelineItemSchema).optional(),\n details: z.array(FullDetailSchema).optional(),\n meta: z.object({\n totalMatches: z.number(),\n expandedCount: z.number(),\n estimatedTokens: z.number(),\n expansionReason: z.string().optional()\n })\n});\nexport type ProgressiveSearchResult = z.infer<typeof ProgressiveSearchResultSchema>;\n\n// Progressive Disclosure Config\nexport const ProgressiveDisclosureConfigSchema = z.object({\n enabled: z.boolean().default(true),\n layer1: z.object({\n topK: z.number().default(10),\n minScore: z.number().default(0.7)\n }).default({}),\n autoExpand: z.object({\n enabled: z.boolean().default(true),\n highConfidenceThreshold: z.number().default(0.92),\n scoreGapThreshold: z.number().default(0.1),\n maxAutoExpandCount: z.number().default(3)\n }).default({}),\n tokenBudget: z.object({\n maxTotalTokens: z.number().default(2000),\n layer1PerItem: z.number().default(50),\n layer2PerItem: z.number().default(40),\n layer3PerItem: z.number().default(500)\n }).default({})\n});\nexport type ProgressiveDisclosureConfig = z.infer<typeof ProgressiveDisclosureConfigSchema>;\n\n// ============================================================\n// Citation Types\n// ============================================================\n\nexport const CitationSchema = z.object({\n citationId: z.string().length(6),\n eventId: z.string(),\n createdAt: z.date()\n});\nexport type Citation = z.infer<typeof CitationSchema>;\n\nexport const CitationUsageSchema = z.object({\n usageId: z.string(),\n citationId: z.string(),\n sessionId: z.string(),\n usedAt: z.date(),\n context: z.string().optional()\n});\nexport type CitationUsage = z.infer<typeof CitationUsageSchema>;\n\nexport interface CitedSearchResult {\n event: MemoryEvent;\n citation: Citation;\n score: number;\n}\n\nexport interface CitationStats {\n usageCount: number;\n lastUsed: Date | null;\n}\n\n// ============================================================\n// Endless Mode Types\n// ============================================================\n\nexport const MemoryModeSchema = z.enum(['session', 'endless']);\nexport type MemoryMode = z.infer<typeof MemoryModeSchema>;\n\nexport const EndlessModeConfigSchema = z.object({\n enabled: z.boolean().default(false),\n\n workingSet: z.object({\n maxEvents: z.number().default(100),\n timeWindowHours: z.number().default(24),\n minRelevanceScore: z.number().default(0.5)\n }).default({}),\n\n consolidation: z.object({\n triggerIntervalMs: z.number().default(3600000), // 1 hour\n triggerEventCount: z.number().default(100),\n triggerIdleMs: z.number().default(1800000), // 30 minutes\n useLLMSummarization: z.boolean().default(false)\n }).default({}),\n\n continuity: z.object({\n minScoreForSeamless: z.number().default(0.7),\n topicDecayHours: z.number().default(48)\n }).default({})\n});\nexport type EndlessModeConfig = z.infer<typeof EndlessModeConfigSchema>;\n\n// Working Set Item\nexport const WorkingSetItemSchema = z.object({\n id: z.string(),\n eventId: z.string(),\n addedAt: z.date(),\n relevanceScore: z.number(),\n topics: z.array(z.string()).optional(),\n expiresAt: z.date()\n});\nexport type WorkingSetItem = z.infer<typeof WorkingSetItemSchema>;\n\n// Working Set\nexport interface WorkingSet {\n recentEvents: MemoryEvent[];\n lastActivity: Date;\n continuityScore: number;\n}\n\n// Consolidated Memory\nexport const ConsolidatedMemorySchema = z.object({\n memoryId: z.string(),\n summary: z.string(),\n topics: z.array(z.string()),\n sourceEvents: z.array(z.string()),\n confidence: z.number(),\n createdAt: z.date(),\n accessedAt: z.date().optional(),\n accessCount: z.number().default(0)\n});\nexport type ConsolidatedMemory = z.infer<typeof ConsolidatedMemorySchema>;\n\n// Consolidated Memory Input (for creation)\nexport interface ConsolidatedMemoryInput {\n summary: string;\n topics: string[];\n sourceEvents: string[];\n confidence: number;\n}\n\n// Long-term Rule (promoted from stable summaries)\nexport const ConsolidationRuleSchema = z.object({\n ruleId: z.string(),\n rule: z.string(),\n topics: z.array(z.string()),\n sourceMemoryIds: z.array(z.string()),\n sourceEvents: z.array(z.string()),\n confidence: z.number(),\n createdAt: z.date()\n});\nexport type ConsolidationRule = z.infer<typeof ConsolidationRuleSchema>;\n\nexport interface ConsolidationRuleInput {\n rule: string;\n topics: string[];\n sourceMemoryIds: string[];\n sourceEvents: string[];\n confidence: number;\n}\n\nexport interface ConsolidationCostQualityReport {\n beforeTokenEstimate: number;\n afterTokenEstimate: number;\n reductionRatio: number;\n qualityGuardPassed: boolean;\n details: string;\n}\n\n// Event Group (for consolidation)\nexport interface EventGroup {\n topics: string[];\n events: MemoryEvent[];\n}\n\n// Context Snapshot (for continuity calculation)\nexport interface ContextSnapshot {\n id: string;\n timestamp: number;\n topics: string[];\n files: string[];\n entities: string[];\n}\n\n// Transition Type\nexport const TransitionTypeSchema = z.enum(['seamless', 'topic_shift', 'break']);\nexport type TransitionType = z.infer<typeof TransitionTypeSchema>;\n\n// Continuity Score Result\nexport interface ContinuityScore {\n score: number;\n transitionType: TransitionType;\n}\n\n// Continuity Log\nexport const ContinuityLogSchema = z.object({\n logId: z.string(),\n fromContextId: z.string().optional(),\n toContextId: z.string().optional(),\n continuityScore: z.number(),\n transitionType: TransitionTypeSchema,\n createdAt: z.date()\n});\nexport type ContinuityLog = z.infer<typeof ContinuityLogSchema>;\n\n// Endless Mode Status\nexport interface EndlessModeStatus {\n mode: MemoryMode;\n workingSetSize: number;\n continuityScore: number;\n consolidatedCount: number;\n lastConsolidation: Date | null;\n}\n\n// ============================================================\n// Shared Store Types (Cross-Project Knowledge)\n// ============================================================\n\nexport const SharedEntryTypeSchema = z.enum([\n 'troubleshooting',\n 'best_practice',\n 'common_error'\n]);\nexport type SharedEntryType = z.infer<typeof SharedEntryTypeSchema>;\n\nexport const SharedTroubleshootingEntrySchema = z.object({\n entryId: z.string(),\n sourceProjectHash: z.string(),\n sourceEntryId: z.string(),\n title: z.string(),\n symptoms: z.array(z.string()),\n rootCause: z.string(),\n solution: z.string(),\n topics: z.array(z.string()),\n technologies: z.array(z.string()).optional(),\n confidence: z.number().min(0).max(1),\n usageCount: z.number().default(0),\n lastUsedAt: z.date().optional(),\n promotedAt: z.date(),\n createdAt: z.date()\n});\nexport type SharedTroubleshootingEntry = z.infer<typeof SharedTroubleshootingEntrySchema>;\n\nexport interface SharedTroubleshootingInput {\n sourceProjectHash: string;\n sourceEntryId: string;\n title: string;\n symptoms: string[];\n rootCause: string;\n solution: string;\n topics: string[];\n technologies?: string[];\n confidence: number;\n}\n\nexport const SharedStoreConfigSchema = z.object({\n enabled: z.boolean().default(true),\n autoPromote: z.boolean().default(true),\n searchShared: z.boolean().default(true),\n minConfidenceForPromotion: z.number().default(0.8),\n sharedStoragePath: z.string().default('~/.claude-code/memory/shared')\n});\nexport type SharedStoreConfig = z.infer<typeof SharedStoreConfigSchema>;\n\n// Shared search result\nexport interface SharedSearchResult {\n id: string;\n entryId: string;\n content: string;\n score: number;\n entryType: SharedEntryType;\n}\n", "import { sqliteAll, toDateFromSQLite, type SQLiteDatabase } from './sqlite-wrapper.js';\n\n/** Audit dimensions are enums, never arbitrary metadata or filesystem paths. */\nexport function safeSourceLabel(value: unknown): string {\n if (value == null || value === '') return 'native';\n return ['native', 'claude', 'claude-code', 'codex', 'hermes', 'import', 'manual'].includes(String(value))\n ? String(value) : 'other';\n}\n\nexport function safeClientLabel(value: unknown): string {\n return ['claude-hook', 'codex-hook', 'mcp', 'hermes', 'cli', 'dashboard'].includes(String(value))\n ? String(value) : 'unknown';\n}\n\n/** Reads clocks without initialization or migrations, suitable for audit snapshots. */\nexport function readIngestSourceClocks(db: SQLiteDatabase, options: { since?: Date; until?: Date } = {}) {\n const eventColumns = new Set(sqliteAll<{ name: string }>(db, 'PRAGMA table_info(events)').map((row) => row.name));\n const sourceExpression = eventColumns.has('metadata')\n ? `COALESCE(\n json_extract(CASE WHEN json_valid(metadata) THEN metadata ELSE '{}' END, '$.source'),\n 'native'\n )`\n : `'native'`;\n const occurredAtExpression = eventColumns.has('metadata')\n ? `COALESCE(\n json_extract(CASE WHEN json_valid(metadata) THEN metadata ELSE '{}' END, '$.originalTimestamp'),\n json_extract(CASE WHEN json_valid(metadata) THEN metadata ELSE '{}' END, '$.ingest.occurredAt')\n )`\n : 'NULL';\n const clauses: string[] = [];\n const params: unknown[] = [];\n if (options.since) {\n clauses.push('julianday(timestamp) >= julianday(?)');\n params.push(options.since.toISOString());\n }\n if (options.until) {\n clauses.push('julianday(timestamp) < julianday(?)');\n params.push(options.until.toISOString());\n }\n const where = clauses.length > 0 ? ` WHERE ${clauses.join(' AND ')}` : '';\n const rows = sqliteAll<{ source: string | null; timestamp: string; occurred_at: string | null }>(\n db,\n `SELECT\n ${sourceExpression} AS source,\n timestamp,\n ${occurredAtExpression} AS occurred_at\n FROM events${where}`,\n params\n );\n\n const bySource = new Map<string, {\n events: number;\n lags: number[];\n unknown: number;\n latestOccurredAt: number | null;\n latestIngestedAt: number | null;\n }>();\n for (const row of rows) {\n const source = safeSourceLabel(row.source);\n const entry = bySource.get(source)\n ?? { events: 0, lags: [], unknown: 0, latestOccurredAt: null, latestIngestedAt: null };\n entry.events += 1;\n const ingestedMs = toDateFromSQLite(row.timestamp ?? '').getTime();\n if (Number.isFinite(ingestedMs)) {\n entry.latestIngestedAt = entry.latestIngestedAt === null\n ? ingestedMs\n : Math.max(entry.latestIngestedAt, ingestedMs);\n }\n const occurredMs = row.occurred_at ? toDateFromSQLite(row.occurred_at).getTime() : NaN;\n if (Number.isFinite(occurredMs)) {\n entry.latestOccurredAt = entry.latestOccurredAt === null\n ? occurredMs\n : Math.max(entry.latestOccurredAt, occurredMs);\n if (Number.isFinite(ingestedMs)) entry.lags.push(Math.max(0, ingestedMs - occurredMs));\n } else {\n entry.unknown += 1;\n }\n bySource.set(source, entry);\n }\n\n return Array.from(bySource.entries())\n .map(([source, entry]) => {\n const sorted = [...entry.lags].sort((a, b) => a - b);\n return {\n source,\n events: entry.events,\n withSourceClock: entry.lags.length,\n unknownSourceClock: entry.unknown,\n latestOccurredAt: entry.latestOccurredAt === null ? null : new Date(entry.latestOccurredAt).toISOString(),\n latestIngestedAt: entry.latestIngestedAt === null ? null : new Date(entry.latestIngestedAt).toISOString(),\n maxLagMs: sorted.length > 0 ? sorted[sorted.length - 1] : null,\n medianLagMs: sorted.length > 0 ? sorted[Math.floor((sorted.length - 1) / 2)] : null\n };\n })\n .sort((a, b) => b.events - a.events);\n}\n", "/** Independent rollback switches. Readers and existing tables remain intact. */\nexport function retrievalRollout() {\n const enabled = (name: string) => !['0', 'false', 'off'].includes((process.env[name] ?? '').toLowerCase());\n return {\n typedTraceWrite: enabled('CML_TYPED_TRACE_WRITE'),\n usefulnessV3Write: enabled('CML_USEFULNESS_V3_WRITE'),\n usefulnessV3Ui: enabled('CML_USEFULNESS_V3_UI')\n };\n}\n", "import { readIngestSourceClocks } from './ingest-source-clocks.js';\nimport { retrievalRollout } from './retrieval-rollout.js';\n/**\n * SQLite-based EventStore implementation\n * Primary store for hooks - WAL mode enables concurrent access\n */\n\nimport { randomUUID } from 'crypto';\nimport {\n EventType,\n MemoryEvent,\n MemoryEventInput,\n Session,\n AppendResult,\n OutboxItem,\n OutboxStats,\n OutboxStatsOptions,\n OutboxRecoveryOptions,\n OutboxRecoveryResult,\n ProjectScopeRepairOptions,\n ProjectScopeRepairResult,\n ProjectScopeRepairSample\n} from './types.js';\nimport { makeCanonicalKey, makeDedupeKey } from './canonical-key.js';\nimport { generateCitationId } from './citation-generator.js';\nimport * as nodePath from 'path';\nimport { hashProjectPath, hashProjectPathIgnoringMarker } from './registry/project-path.js';\nimport {\n createSQLiteDatabase,\n sqliteRun,\n sqliteAll,\n sqliteGet,\n sqliteClose,\n sqliteExec,\n toDateFromSQLite,\n toSQLiteTimestamp,\n type SQLiteDatabase,\n type SQLiteOptions\n} from './sqlite-wrapper.js';\nimport { MarkdownMirror } from './markdown-mirror.js';\nimport { VectorOutbox, type OutboxConfig } from './vector-outbox.js';\nimport { normalizeRetrievalDebugLanes, type RetrievalDebugLane } from './retrieval-debug-lanes.js';\nimport { computeMemoryUsageEvidence, type EvidenceMatch } from './usefulness-evidence.js';\nimport {\n buildUsefulnessObservationV2,\n classifyReaskOutcome,\n parseToolOutcome,\n USEFULNESS_V2_EVALUATION_WINDOW_MS\n} from './usefulness-outcome-v2.js';\nimport {\n CURRENT_USEFULNESS_EVALUATOR_VERSION,\n LEGACY_ASSUMED_DELIVERY_EVALUATOR_VERSIONS,\n RETRIEVAL_TELEMETRY_SCHEMA_VERSION,\n deliveredFromStatus,\n emptyUsefulnessAggregateV2,\n normalizeDeliveryEvidence,\n normalizeDeliveryStatus,\n normalizeRequestId,\n normalizeUsefulnessMinimumSample,\n presentedOutcomeReason,\n normalizeRetrievalPresentationMode,\n normalizeRetrievalOutcomeDiagnostics,\n normalizeRetrievalTriggerType,\n normalizeTelemetryClient,\n type RecordReferenceNavigationInput,\n type RecordReferenceNavigationResult,\n type RetrievalPresentationMode,\n type RetrievalOutcomeDiagnostics,\n type RetrievalTelemetryContext,\n type RetrievalTelemetryStats,\n type RetrievalTriggerType,\n type DeliveryEvidenceSource,\n type DeliveryStatus,\n type MemoryUsefulnessObservationV2,\n type RetrievalClientCoverage,\n type UsefulnessAdoption,\n type RetrievalTraceItemInput,\n type TypedSelectionSummary,\n type UsefulnessAggregateV2,\n type UsefulnessRateV2\n} from './retrieval-telemetry.js';\nimport {\n normalizeMemoryKind,\n usefulnessRowKey,\n usefulnessRowKeySql,\n type MemoryKind\n} from './memory-ref.js';\nimport { recordReferenceNavigationOnDb } from './retrieval-navigation.js';\nimport {\n backfillTraceItems,\n ensureRetrievalTraceItemsSchema,\n normalizeTraceItems,\n readTraceItems,\n resolveMemoryRefKinds,\n summarizeTypedSelections,\n writeTraceItems,\n type TraceItemBackfillResult\n} from './retrieval-trace-ledger.js';\n\nexport interface SQLiteEventStoreOptions extends SQLiteOptions {\n markdownMirrorRoot?: string;\n vectorOutbox?: false | VectorOutbox | Partial<OutboxConfig>;\n}\n\nexport interface DerivationLiveness {\n graduation: {\n attempts: number;\n lastAttemptAt: string | null;\n lastSuccessAt: string | null;\n lastStatus: 'success' | 'not_eligible' | 'failed' | null;\n lastErrorCategory: 'graduation_failed' | null;\n };\n sources: {\n graduatedEvents: number;\n curatedLessons: number;\n };\n}\n\ntype QueryRewriteKind = 'none' | 'follow-up-context' | 'intent-rewrite';\n\ntype RetrievalTraceDetailRecord = {\n eventId: string;\n score: number;\n semanticScore?: number;\n lexicalScore?: number;\n recencyScore?: number;\n lanes?: RetrievalDebugLane[];\n};\n\nfunction normalizeRetrievalTraceDetails(details?: RetrievalTraceDetailRecord[]): RetrievalTraceDetailRecord[] {\n return (details || []).map((detail) => {\n const lanes = normalizeRetrievalDebugLanes((detail as { lanes?: unknown }).lanes);\n const normalized: RetrievalTraceDetailRecord = {\n eventId: detail.eventId,\n score: detail.score\n };\n if (detail.semanticScore !== undefined) normalized.semanticScore = detail.semanticScore;\n if (detail.lexicalScore !== undefined) normalized.lexicalScore = detail.lexicalScore;\n if (detail.recencyScore !== undefined) normalized.recencyScore = detail.recencyScore;\n if (lanes.length > 0) normalized.lanes = lanes;\n return normalized;\n });\n}\n\nfunction parseRetrievalTraceDetails(value: unknown): RetrievalTraceDetailRecord[] {\n if (typeof value !== 'string' || value.length === 0) return [];\n const parsed = JSON.parse(value);\n return Array.isArray(parsed) ? normalizeRetrievalTraceDetails(parsed as RetrievalTraceDetailRecord[]) : [];\n}\n\n/**\n * Read a trace's diagnostics.\n *\n * Rows written before the honest-default migration stored `runtime_error` as a\n * fallback for \"no diagnostics\", not as an observed exception. They are shown\n * as `legacy_unclassified` and never rewritten in place (specs R2).\n */\nfunction parseRetrievalOutcomeDiagnostics(row: Record<string, unknown>): RetrievalOutcomeDiagnostics {\n let value: unknown;\n try {\n value = typeof row.retrieval_diagnostics_json === 'string'\n ? JSON.parse(row.retrieval_diagnostics_json)\n : undefined;\n } catch {\n value = undefined;\n }\n const presented = presentedOutcomeReason(row.outcome_reason, row.telemetry_schema_version);\n const diagnostics = normalizeRetrievalOutcomeDiagnostics(value, presented);\n return Number(row.telemetry_schema_version) >= 2\n ? diagnostics\n : { ...diagnostics, outcomeReason: presented };\n}\n\nfunction normalizeQueryRewriteKind(value?: string | null): QueryRewriteKind {\n const normalized = (value || '').trim().toLowerCase();\n if (normalized === 'follow-up-context' || normalized === 'intent-rewrite') return normalized;\n return 'none';\n}\n\nconst REWRITTEN_QUERY_REWRITE_KIND_SQL = `LOWER(TRIM(COALESCE(query_rewrite_kind, 'none'))) IN ('follow-up-context', 'intent-rewrite')`;\nconst DEFAULT_OUTBOX_STUCK_THRESHOLD_MS = 5 * 60 * 1000;\nconst DEFAULT_OUTBOX_MAX_RETRIES = 3;\n// Re-exported for existing importers; the implementation moved next to the\n// navigation recorder so db-only callers can reuse both.\nexport { REFERENCE_ATTRIBUTION_WINDOW_MS } from './retrieval-navigation.js';\n// Bump when introducing an ordered migration that must run exactly once; gate\n// such migrations on the persisted PRAGMA user_version.\nconst SQLITE_SCHEMA_VERSION = 1;\n\nfunction emptyOutboxRecoveryResult(): OutboxRecoveryResult {\n return {\n embedding: { recoveredProcessing: 0, retriedFailed: 0 },\n vector: { recoveredProcessing: 0, retriedFailed: 0 }\n };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction getNestedRecord(root: Record<string, unknown> | undefined, path: string[]): Record<string, unknown> | undefined {\n let cursor: unknown = root;\n for (const key of path) {\n if (!isRecord(cursor)) return undefined;\n cursor = cursor[key];\n }\n return isRecord(cursor) ? cursor : undefined;\n}\n\nfunction getNestedString(root: Record<string, unknown> | undefined, path: string[]): string | undefined {\n let cursor: unknown = root;\n for (const key of path) {\n if (!isRecord(cursor)) return undefined;\n cursor = cursor[key];\n }\n return typeof cursor === 'string' && cursor.length > 0 ? cursor : undefined;\n}\n\nfunction metadataProjectHash(metadata: Record<string, unknown> | undefined): string | undefined {\n return getNestedString(metadata, ['scope', 'project', 'hash']);\n}\n\nfunction metadataProjectPaths(metadata: Record<string, unknown> | undefined): string[] {\n const candidates = [\n getNestedString(metadata, ['projectPath']),\n getNestedString(metadata, ['sourceProjectPath']),\n getNestedString(metadata, ['scope', 'project', 'path'])\n ];\n const paths: string[] = [];\n for (const value of candidates) {\n if (value && !paths.includes(value)) paths.push(value);\n }\n return paths;\n}\n\nfunction metadataProjectPath(metadata: Record<string, unknown> | undefined): string | undefined {\n return metadataProjectPaths(metadata)[0];\n}\n\nfunction isActiveQuarantinedMetadata(metadata: Record<string, unknown> | undefined): boolean {\n const quarantine = getNestedRecord(metadata, ['quarantine']);\n return quarantine?.status === 'active';\n}\n\nfunction activeQuarantineStatusExpression(column = 'metadata'): string {\n return `COALESCE(json_extract(CASE WHEN json_valid(${column}) THEN ${column} ELSE '{}' END, '$.quarantine.status'), '')`;\n}\n\nfunction notActiveQuarantinedSql(column = 'metadata'): string {\n return `${activeQuarantineStatusExpression(column)} != 'active'`;\n}\n\ninterface QuarantineReadOptions {\n includeQuarantined?: boolean;\n}\n\nexport interface RecentEventsReadOptions extends QuarantineReadOptions {\n /** Restrict to these event types. An empty/omitted list means \"any type\". */\n eventTypes?: EventType[];\n}\n\nfunction maybeQuarantinePredicate(options?: QuarantineReadOptions, column = 'metadata'): string {\n return options?.includeQuarantined ? '1=1' : notActiveQuarantinedSql(column);\n}\n\nfunction safeParseMetadataValue(value: unknown): Record<string, unknown> | undefined {\n if (!value) return undefined;\n if (typeof value === 'object') return isRecord(value) ? value : undefined;\n if (typeof value !== 'string') return undefined;\n try {\n const parsed = JSON.parse(value);\n return isRecord(parsed) ? parsed : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction isImportedOrLegacyScopedMetadata(metadata: Record<string, unknown> | undefined): boolean {\n if (!metadata) return false;\n return Boolean(\n metadata.importedFrom\n || metadata.sourceSessionId\n || metadata.sourceSessionHash\n || metadata.hermesSource\n || metadata.projectPath\n || metadata.sourceProjectPath\n || metadata.source === 'hermes'\n || metadata.source === 'claude'\n || metadata.source === 'codex'\n );\n}\n\nfunction addMetadataTag(metadata: Record<string, unknown>, tag: string): void {\n const current = Array.isArray(metadata.tags)\n ? metadata.tags.filter((value): value is string => typeof value === 'string')\n : [];\n if (!current.includes(tag)) metadata.tags = [...current, tag];\n}\n\nfunction buildRepairResult(projectHash: string, dryRun: boolean): ProjectScopeRepairResult {\n return {\n dryRun,\n projectHash,\n scanned: 0,\n repaired: 0,\n quarantined: 0,\n alreadyScoped: 0,\n skipped: 0,\n samples: []\n };\n}\n\nfunction normalizeRepoName(value: string): string {\n return value.replace(/\\.git$/i, '').trim().toLowerCase();\n}\n\nfunction projectBasename(projectPath?: string): string | undefined {\n if (!projectPath) return undefined;\n const trimmed = projectPath.replace(/[\\\\/]+$/, '');\n const basename = nodePath.basename(trimmed);\n return basename ? normalizeRepoName(basename) : undefined;\n}\n\nfunction isProjectScopeRepairExplanation(content: string): boolean {\n const normalized = content.toLowerCase();\n const hasRepairContext = /project[- ]scope|mis[- ]scoped|quarantine|contamination|legacy|\uC624\uC5FC|\uACA9\uB9AC|repair/.test(normalized);\n const hasExplanationContext = /example|detector|trap|not a .*project task|\uAE30\uC5B5|\uBA54\uBAA8\uB9AC|\uC124\uBA85|\uC218\uC815|\uAC80\uC99D/.test(normalized);\n return hasRepairContext && hasExplanationContext;\n}\n\nfunction hasConflictingContentProjectHint(content: string, projectPath?: string): boolean {\n const currentName = projectBasename(projectPath);\n if (!currentName) return false;\n if (isProjectScopeRepairExplanation(content)) return false;\n\n const githubRepoPattern = /github\\.com[:/]([^/\\s`'\"#)]+)\\/([^/\\s`'\"#)]+)(?:\\.git)?/gi;\n let githubMatch: RegExpExecArray | null;\n while ((githubMatch = githubRepoPattern.exec(content)) !== null) {\n const repo = normalizeRepoName(githubMatch[2] || '');\n if (repo && repo !== currentName) return true;\n }\n\n const workspacePathPattern = /\\/workspace\\/([^/\\s`'\"#)]+)/gi;\n let workspaceMatch: RegExpExecArray | null;\n while ((workspaceMatch = workspacePathPattern.exec(content)) !== null) {\n const repo = normalizeRepoName(workspaceMatch[1] || '');\n if (repo && repo !== currentName) return true;\n }\n\n return false;\n}\n\nexport class SQLiteEventStore {\n private db: SQLiteDatabase;\n private initialized = false;\n private readonly readOnly: boolean;\n private readonly markdownMirror: MarkdownMirror | null;\n private readonly vectorOutbox: VectorOutbox | null;\n\n constructor(dbPath: string, options?: SQLiteEventStoreOptions) {\n this.readOnly = options?.readonly ?? false;\n this.db = createSQLiteDatabase(dbPath, {\n readonly: this.readOnly,\n snapshot: options?.snapshot,\n snapshotDirectory: options?.snapshotDirectory,\n canonicalMemoryRoot: options?.canonicalMemoryRoot,\n walMode: !this.readOnly\n });\n this.markdownMirror = this.readOnly || !options?.markdownMirrorRoot\n ? null\n : new MarkdownMirror(options.markdownMirrorRoot);\n this.vectorOutbox = this.createVectorOutbox(options?.vectorOutbox);\n }\n\n private createVectorOutbox(option: SQLiteEventStoreOptions['vectorOutbox']): VectorOutbox | null {\n if (this.readOnly || option === false) return null;\n if (option instanceof VectorOutbox) return option;\n return new VectorOutbox(this.db, option ?? {});\n }\n\n private enqueueVectorOutboxEventSync(eventId: string, eventType: string): void {\n if (!this.vectorOutbox) return;\n if (eventType === 'tool_observation') return;\n this.vectorOutbox.enqueueSync('event', eventId);\n }\n\n private async enqueueVectorOutboxEvent(eventId: string, eventType: string): Promise<void> {\n this.enqueueVectorOutboxEventSync(eventId, eventType);\n }\n\n /**\n * Initialize database schema\n */\n async initialize(): Promise<void> {\n if (this.initialized) return;\n\n // In read-only mode, skip schema creation\n if (this.readOnly) {\n this.initialized = true;\n return;\n }\n\n // Create all tables in a single exec for efficiency\n sqliteExec(this.db, `\n -- L0 EventStore: Single Source of Truth (immutable, append-only)\n CREATE TABLE IF NOT EXISTS events (\n id TEXT PRIMARY KEY,\n event_type TEXT NOT NULL,\n session_id TEXT NOT NULL,\n timestamp TEXT NOT NULL,\n content TEXT NOT NULL,\n canonical_key TEXT NOT NULL,\n dedupe_key TEXT UNIQUE,\n metadata TEXT,\n access_count INTEGER DEFAULT 0,\n last_accessed_at TEXT\n );\n\n -- Dedup table for idempotency\n CREATE TABLE IF NOT EXISTS event_dedup (\n dedupe_key TEXT PRIMARY KEY,\n event_id TEXT NOT NULL,\n created_at TEXT DEFAULT (datetime('now'))\n );\n\n -- Session metadata\n CREATE TABLE IF NOT EXISTS sessions (\n id TEXT PRIMARY KEY,\n started_at TEXT NOT NULL,\n ended_at TEXT,\n project_path TEXT,\n summary TEXT,\n tags TEXT\n );\n\n -- Insights (derived data, rebuildable)\n CREATE TABLE IF NOT EXISTS insights (\n id TEXT PRIMARY KEY,\n insight_type TEXT NOT NULL,\n content TEXT NOT NULL,\n canonical_key TEXT NOT NULL,\n confidence REAL,\n source_events TEXT,\n created_at TEXT,\n last_updated TEXT\n );\n\n -- Embedding Outbox (Single-Writer Pattern)\n CREATE TABLE IF NOT EXISTS embedding_outbox (\n id TEXT PRIMARY KEY,\n event_id TEXT NOT NULL,\n content TEXT NOT NULL,\n status TEXT DEFAULT 'pending',\n retry_count INTEGER DEFAULT 0,\n created_at TEXT DEFAULT (datetime('now')),\n processed_at TEXT,\n error_message TEXT\n );\n\n -- Projection offset tracking\n CREATE TABLE IF NOT EXISTS projection_offsets (\n projection_name TEXT PRIMARY KEY,\n last_event_id TEXT,\n last_timestamp TEXT,\n updated_at TEXT DEFAULT (datetime('now'))\n );\n\n -- Memory level tracking\n CREATE TABLE IF NOT EXISTS memory_levels (\n event_id TEXT PRIMARY KEY,\n level TEXT NOT NULL DEFAULT 'L0',\n promoted_at TEXT DEFAULT (datetime('now'))\n );\n\n -- Entries (immutable memory units)\n CREATE TABLE IF NOT EXISTS entries (\n entry_id TEXT PRIMARY KEY,\n created_ts TEXT NOT NULL,\n entry_type TEXT NOT NULL,\n title TEXT NOT NULL,\n content_json TEXT NOT NULL,\n stage TEXT NOT NULL DEFAULT 'raw',\n status TEXT DEFAULT 'active',\n superseded_by TEXT,\n build_id TEXT,\n evidence_json TEXT,\n canonical_key TEXT,\n created_at TEXT DEFAULT (datetime('now'))\n );\n\n -- Entities (task/condition/artifact)\n CREATE TABLE IF NOT EXISTS entities (\n entity_id TEXT PRIMARY KEY,\n entity_type TEXT NOT NULL,\n canonical_key TEXT NOT NULL,\n title TEXT NOT NULL,\n stage TEXT NOT NULL DEFAULT 'raw',\n status TEXT NOT NULL DEFAULT 'active',\n current_json TEXT NOT NULL,\n title_norm TEXT,\n search_text TEXT,\n created_at TEXT DEFAULT (datetime('now')),\n updated_at TEXT DEFAULT (datetime('now'))\n );\n\n -- Entity aliases for canonical key lookup\n CREATE TABLE IF NOT EXISTS entity_aliases (\n entity_type TEXT NOT NULL,\n canonical_key TEXT NOT NULL,\n entity_id TEXT NOT NULL,\n is_primary INTEGER DEFAULT 0,\n created_at TEXT DEFAULT (datetime('now')),\n PRIMARY KEY(entity_type, canonical_key)\n );\n\n -- Edges (relationships between entries/entities) -- current-state projection\n CREATE TABLE IF NOT EXISTS edges (\n edge_id TEXT PRIMARY KEY,\n src_type TEXT NOT NULL,\n src_id TEXT NOT NULL,\n rel_type TEXT NOT NULL,\n dst_type TEXT NOT NULL,\n dst_id TEXT NOT NULL,\n meta_json TEXT,\n created_at TEXT DEFAULT (datetime('now'))\n );\n\n -- Bitemporal edge history (Zep/Graphiti-inspired), see\n -- docs/graph-temporal-edge-spike.md. edges above stays the fast\n -- current-state projection; this table is the append-only source for\n -- asOf/knownAt queries and is never hard-deleted.\n CREATE TABLE IF NOT EXISTS edge_history (\n history_id TEXT PRIMARY KEY,\n edge_id TEXT NOT NULL,\n edge_key TEXT NOT NULL,\n src_type TEXT NOT NULL,\n src_id TEXT NOT NULL,\n rel_type TEXT NOT NULL,\n dst_type TEXT NOT NULL,\n dst_id TEXT NOT NULL,\n weight REAL NOT NULL DEFAULT 0.5,\n status TEXT NOT NULL DEFAULT 'active',\n valid_from TEXT,\n valid_to TEXT,\n committed_at TEXT NOT NULL DEFAULT (datetime('now')),\n superseded_by_history_id TEXT,\n source_event_ids_json TEXT NOT NULL DEFAULT '[]',\n evidence_json TEXT NOT NULL DEFAULT '{}',\n meta_json TEXT NOT NULL DEFAULT '{}'\n );\n\n CREATE INDEX IF NOT EXISTS idx_edge_history_key_commit\n ON edge_history(edge_key, committed_at DESC, history_id DESC);\n CREATE INDEX IF NOT EXISTS idx_edge_history_valid\n ON edge_history(edge_key, valid_from, valid_to);\n CREATE INDEX IF NOT EXISTS idx_edge_history_src\n ON edge_history(src_id, rel_type, committed_at DESC);\n CREATE INDEX IF NOT EXISTS idx_edge_history_dst\n ON edge_history(dst_id, rel_type, committed_at DESC);\n CREATE INDEX IF NOT EXISTS idx_edge_history_status\n ON edge_history(status);\n\n -- Vector Outbox V2 Table\n CREATE TABLE IF NOT EXISTS vector_outbox (\n job_id TEXT PRIMARY KEY,\n item_kind TEXT NOT NULL,\n item_id TEXT NOT NULL,\n embedding_version TEXT NOT NULL,\n status TEXT NOT NULL DEFAULT 'pending',\n retry_count INTEGER DEFAULT 0,\n error TEXT,\n created_at TEXT DEFAULT (datetime('now')),\n updated_at TEXT DEFAULT (datetime('now')),\n UNIQUE(item_kind, item_id, embedding_version)\n );\n\n -- Build Runs\n CREATE TABLE IF NOT EXISTS build_runs (\n build_id TEXT PRIMARY KEY,\n started_at TEXT NOT NULL,\n finished_at TEXT,\n extractor_model TEXT NOT NULL,\n extractor_prompt_hash TEXT NOT NULL,\n embedder_model TEXT NOT NULL,\n embedding_version TEXT NOT NULL,\n idris_version TEXT NOT NULL,\n schema_version TEXT NOT NULL,\n status TEXT NOT NULL DEFAULT 'running',\n error TEXT\n );\n\n -- Pipeline Metrics\n CREATE TABLE IF NOT EXISTS pipeline_metrics (\n id TEXT PRIMARY KEY,\n ts TEXT NOT NULL,\n stage TEXT NOT NULL,\n latency_ms REAL NOT NULL,\n success INTEGER NOT NULL,\n error TEXT,\n session_id TEXT\n );\n\n -- Working Set table (active memory window)\n CREATE TABLE IF NOT EXISTS working_set (\n id TEXT PRIMARY KEY,\n event_id TEXT NOT NULL,\n added_at TEXT DEFAULT (datetime('now')),\n relevance_score REAL DEFAULT 1.0,\n topics TEXT,\n expires_at TEXT\n );\n\n -- Consolidated Memories table (long-term integrated memories)\n CREATE TABLE IF NOT EXISTS consolidated_memories (\n memory_id TEXT PRIMARY KEY,\n summary TEXT NOT NULL,\n topics TEXT,\n source_events TEXT,\n confidence REAL DEFAULT 0.5,\n created_at TEXT DEFAULT (datetime('now')),\n accessed_at TEXT,\n access_count INTEGER DEFAULT 0\n );\n\n -- Junction: consolidated memory -> source event id (indexed lookup that\n -- replaces per-event source_events LIKE scans during consolidation).\n CREATE TABLE IF NOT EXISTS consolidated_memory_events (\n memory_id TEXT NOT NULL,\n event_id TEXT NOT NULL,\n PRIMARY KEY (memory_id, event_id)\n );\n CREATE INDEX IF NOT EXISTS idx_cme_event ON consolidated_memory_events(event_id);\n\n -- Continuity Log table (tracks context transitions)\n CREATE TABLE IF NOT EXISTS continuity_log (\n log_id TEXT PRIMARY KEY,\n from_context_id TEXT,\n to_context_id TEXT,\n continuity_score REAL,\n transition_type TEXT,\n created_at TEXT DEFAULT (datetime('now'))\n );\n\n -- Consolidated Rules table (long-term stable memory)\n CREATE TABLE IF NOT EXISTS consolidated_rules (\n rule_id TEXT PRIMARY KEY,\n rule TEXT NOT NULL,\n topics TEXT,\n source_memory_ids TEXT,\n source_events TEXT,\n confidence REAL DEFAULT 0.5,\n created_at TEXT DEFAULT (datetime('now'))\n );\n\n -- Endless Mode Config table\n CREATE TABLE IF NOT EXISTS endless_config (\n key TEXT PRIMARY KEY,\n value TEXT,\n updated_at TEXT DEFAULT (datetime('now'))\n );\n\n -- Memory Helpfulness tracking\n CREATE TABLE IF NOT EXISTS memory_helpfulness (\n id TEXT PRIMARY KEY,\n event_id TEXT NOT NULL,\n session_id TEXT NOT NULL,\n retrieval_score REAL DEFAULT 0,\n query_preview TEXT,\n session_continued INTEGER DEFAULT 0,\n prompt_count_after INTEGER DEFAULT 0,\n tool_success_count INTEGER DEFAULT 0,\n tool_total_count INTEGER DEFAULT 0,\n was_reasked INTEGER DEFAULT 0,\n helpfulness_score REAL DEFAULT 0.5,\n memory_kind TEXT NOT NULL DEFAULT 'unknown',\n memory_project_id TEXT,\n delivery_status TEXT NOT NULL DEFAULT 'unknown',\n delivery_evidence TEXT NOT NULL DEFAULT 'none',\n delivered_at TEXT,\n presentation_mode TEXT NOT NULL DEFAULT 'unknown',\n trigger_type TEXT NOT NULL DEFAULT 'unknown',\n delivery_client TEXT NOT NULL DEFAULT 'unknown',\n created_at TEXT DEFAULT (datetime('now')),\n measured_at TEXT\n );\n\n -- Additive, versioned usefulness funnel. Raw dimensions stay separate;\n -- no unknown value is coerced to neutral or zero.\n CREATE TABLE IF NOT EXISTS memory_usefulness_observations_v2 (\n trace_id TEXT NOT NULL,\n event_id TEXT NOT NULL,\n observation_kind TEXT NOT NULL DEFAULT 'outcome',\n evaluator_version TEXT NOT NULL,\n presentation_mode TEXT NOT NULL,\n trigger_type TEXT NOT NULL,\n selected INTEGER NOT NULL,\n delivered INTEGER,\n adoption TEXT NOT NULL,\n content_overlap_score REAL,\n task_outcome TEXT NOT NULL,\n reask_outcome TEXT NOT NULL,\n explicit_feedback TEXT,\n confidence REAL NOT NULL,\n evaluated_at TEXT,\n memory_kind TEXT NOT NULL DEFAULT 'unknown',\n delivery_status TEXT NOT NULL DEFAULT 'unknown',\n delivery_evidence TEXT NOT NULL DEFAULT 'none',\n evaluation_window_ms INTEGER,\n evaluation_cutoff TEXT,\n -- Raw memory id and owning project. The event_id column holds a\n -- kind-qualified key for non-event memories (see usefulnessRowKey) so\n -- the primary key below cannot collapse a lesson onto an event that\n -- happens to share its id.\n memory_id TEXT,\n memory_project_id TEXT,\n PRIMARY KEY(trace_id, event_id, observation_kind, evaluator_version)\n );\n CREATE INDEX IF NOT EXISTS idx_usefulness_v2_evaluator_trigger\n ON memory_usefulness_observations_v2(evaluator_version, trigger_type, evaluated_at DESC);\n\n -- Retrieval trace log (query -> candidates -> selected for context)\n CREATE TABLE IF NOT EXISTS retrieval_traces (\n trace_id TEXT PRIMARY KEY,\n session_id TEXT,\n project_hash TEXT,\n query_text TEXT NOT NULL,\n raw_query_text TEXT,\n query_rewrite_kind TEXT,\n strategy TEXT,\n candidate_event_ids TEXT,\n selected_event_ids TEXT,\n candidate_details_json TEXT,\n selected_details_json TEXT,\n candidate_count INTEGER DEFAULT 0,\n selected_count INTEGER DEFAULT 0,\n confidence TEXT,\n fallback_trace TEXT,\n presentation_mode TEXT NOT NULL DEFAULT 'unknown',\n trigger_type TEXT NOT NULL DEFAULT 'unknown',\n delivery_client TEXT NOT NULL DEFAULT 'unknown',\n outcome_reason TEXT NOT NULL DEFAULT 'unknown',\n retrieval_diagnostics_json TEXT,\n request_id TEXT,\n evaluation_run_id TEXT,\n runtime_version TEXT,\n telemetry_schema_version INTEGER NOT NULL DEFAULT 0,\n created_at TEXT DEFAULT (datetime('now'))\n );\n\n -- Typed references for each trace (specs R1). The legacy id arrays above\n -- stay for old readers; these rows keep the memory kind so lessons are\n -- never mistaken for events.\n CREATE TABLE IF NOT EXISTS retrieval_trace_items (\n trace_id TEXT NOT NULL,\n item_key TEXT NOT NULL,\n memory_kind TEXT NOT NULL,\n memory_id TEXT NOT NULL,\n project_id TEXT,\n rank INTEGER,\n selected INTEGER NOT NULL DEFAULT 0,\n score REAL,\n content_hash TEXT,\n memory_version TEXT,\n deleted INTEGER NOT NULL DEFAULT 0,\n created_at TEXT DEFAULT (datetime('now')),\n PRIMARY KEY (trace_id, item_key)\n );\n\n -- Privacy-safe reference navigation. Target and trace identifiers are\n -- stored without copying source or transcript content.\n CREATE TABLE IF NOT EXISTS retrieval_navigation_events (\n navigation_id TEXT PRIMARY KEY,\n target_event_id TEXT NOT NULL,\n trace_id TEXT,\n delivery_session_id TEXT,\n presentation_mode TEXT NOT NULL DEFAULT 'reference',\n trigger_type TEXT NOT NULL DEFAULT 'unknown',\n memory_kind TEXT NOT NULL DEFAULT 'event',\n navigation_action TEXT NOT NULL,\n navigation_client TEXT NOT NULL DEFAULT 'unknown',\n attribution_outcome TEXT NOT NULL,\n attribution_reason TEXT NOT NULL,\n open_count INTEGER NOT NULL DEFAULT 1,\n first_opened_at TEXT NOT NULL,\n last_opened_at TEXT NOT NULL\n );\n\n -- Sync position tracking (for SQLite -> DuckDB sync)\n CREATE TABLE IF NOT EXISTS sync_positions (\n target_name TEXT PRIMARY KEY,\n last_event_id TEXT,\n last_timestamp TEXT,\n updated_at TEXT DEFAULT (datetime('now'))\n );\n\n -- Memory Operations: facet assignments (derived, rebuildable projection)\n CREATE TABLE IF NOT EXISTS memory_facets (\n id TEXT PRIMARY KEY,\n target_type TEXT NOT NULL,\n target_id TEXT NOT NULL,\n dimension TEXT NOT NULL,\n value TEXT NOT NULL,\n confidence REAL NOT NULL DEFAULT 1.0,\n source TEXT NOT NULL DEFAULT 'manual',\n evidence_event_ids TEXT NOT NULL DEFAULT '[]',\n project_hash TEXT NOT NULL DEFAULT '',\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n UNIQUE(target_type, target_id, dimension, value, source, project_hash)\n );\n\n -- Memory Operations: operational action projection\n CREATE TABLE IF NOT EXISTS memory_actions (\n action_id TEXT PRIMARY KEY,\n project_hash TEXT NOT NULL,\n title TEXT NOT NULL,\n status TEXT NOT NULL DEFAULT 'pending',\n priority INTEGER NOT NULL DEFAULT 0,\n source_event_ids TEXT NOT NULL DEFAULT '[]',\n related_entity_ids TEXT NOT NULL DEFAULT '[]',\n current_checkpoint_id TEXT,\n lease_id TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL\n );\n\n -- Memory Operations: action dependency/reference edges\n CREATE TABLE IF NOT EXISTS memory_action_edges (\n edge_id TEXT PRIMARY KEY,\n src_action_id TEXT NOT NULL,\n rel_type TEXT NOT NULL,\n dst_type TEXT NOT NULL,\n dst_id TEXT NOT NULL,\n confidence REAL NOT NULL DEFAULT 1.0,\n source TEXT NOT NULL DEFAULT 'manual',\n created_at TEXT NOT NULL,\n UNIQUE(src_action_id, rel_type, dst_type, dst_id, source)\n );\n\n -- Memory Operations: short-lived leases for operational work\n CREATE TABLE IF NOT EXISTS memory_leases (\n lease_id TEXT PRIMARY KEY,\n target_type TEXT NOT NULL,\n target_id TEXT NOT NULL,\n holder TEXT NOT NULL,\n expires_at TEXT NOT NULL,\n metadata_json TEXT,\n created_at TEXT NOT NULL,\n renewed_at TEXT,\n released_at TEXT\n );\n\n -- Memory Operations: resumable checkpoints for delegated or long-running work\n CREATE TABLE IF NOT EXISTS memory_checkpoints (\n checkpoint_id TEXT PRIMARY KEY,\n project_hash TEXT NOT NULL,\n action_id TEXT,\n session_id TEXT,\n title TEXT NOT NULL,\n summary TEXT NOT NULL,\n state_json TEXT NOT NULL,\n source_event_ids TEXT NOT NULL DEFAULT '[]',\n created_at TEXT NOT NULL,\n expires_at TEXT\n );\n\n -- Memory Operations: retention lifecycle score projection\n CREATE TABLE IF NOT EXISTS memory_retention_scores (\n score_id TEXT PRIMARY KEY,\n target_type TEXT NOT NULL,\n target_id TEXT NOT NULL,\n project_hash TEXT NOT NULL,\n policy_version TEXT NOT NULL,\n decision TEXT NOT NULL,\n lifecycle_score REAL NOT NULL,\n factors_json TEXT NOT NULL,\n reasons_json TEXT NOT NULL,\n dry_run_diff_json TEXT NOT NULL,\n source_event_ids TEXT NOT NULL DEFAULT '[]',\n evaluated_at TEXT NOT NULL,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n UNIQUE(target_type, target_id, project_hash, policy_version)\n );\n\n -- Memory Operations: procedural lessons derived from successful workflows\n CREATE TABLE IF NOT EXISTS memory_lessons (\n lesson_id TEXT PRIMARY KEY,\n project_hash TEXT NOT NULL DEFAULT '',\n name TEXT NOT NULL,\n trigger TEXT NOT NULL,\n steps_json TEXT NOT NULL,\n confidence REAL NOT NULL,\n source_session_ids TEXT NOT NULL DEFAULT '[]',\n source_event_ids TEXT NOT NULL DEFAULT '[]',\n failure_modes_json TEXT NOT NULL DEFAULT '[]',\n skill_candidate INTEGER NOT NULL DEFAULT 0,\n source_class TEXT NOT NULL DEFAULT 'derived',\n access_count INTEGER NOT NULL DEFAULT 0,\n last_accessed_at TEXT,\n revision INTEGER NOT NULL DEFAULT 1,\n recall_enabled INTEGER NOT NULL DEFAULT 1,\n scope TEXT,\n validation_json TEXT NOT NULL DEFAULT '[]',\n reconsider_when TEXT,\n valid_versions_json TEXT NOT NULL DEFAULT '[]',\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n UNIQUE(project_hash, name)\n );\n\n -- Authenticated host review queue. Candidate payloads are held apart\n -- from recallable lessons until an authenticated UI action accepts them.\n CREATE TABLE IF NOT EXISTS lesson_review_candidates (\n candidate_id TEXT PRIMARY KEY,\n project_hash TEXT NOT NULL,\n evidence_key TEXT NOT NULL,\n payload_hash TEXT NOT NULL,\n payload_json TEXT NOT NULL,\n evidence_refs_json TEXT NOT NULL,\n duplicate_lesson_ids_json TEXT NOT NULL DEFAULT '[]',\n status TEXT NOT NULL,\n revision INTEGER NOT NULL DEFAULT 1,\n generation INTEGER NOT NULL,\n expires_at TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n UNIQUE(project_hash, evidence_key)\n );\n CREATE INDEX IF NOT EXISTS idx_lesson_review_candidates_scope_status\n ON lesson_review_candidates(project_hash, status, updated_at DESC);\n\n -- Privacy-safe lifecycle trace: ids/outcomes only; never raw query,\n -- lesson body, evidence, or provider input.\n CREATE TABLE IF NOT EXISTS lesson_host_traces (\n trace_id TEXT PRIMARY KEY,\n project_hash TEXT NOT NULL,\n session_id TEXT NOT NULL,\n actor_id TEXT NOT NULL,\n machine_id TEXT NOT NULL,\n generation INTEGER NOT NULL,\n turn_id TEXT,\n request_id TEXT NOT NULL,\n phase TEXT NOT NULL,\n outcome TEXT NOT NULL,\n lesson_ids_json TEXT NOT NULL,\n lesson_revisions_json TEXT NOT NULL DEFAULT '[]',\n query_text TEXT,\n created_at TEXT NOT NULL\n );\n CREATE UNIQUE INDEX IF NOT EXISTS idx_lesson_host_trace_request\n ON lesson_host_traces(project_hash, actor_id, request_id, phase);\n\n CREATE TABLE IF NOT EXISTS lesson_host_idempotency (\n project_hash TEXT NOT NULL,\n actor_id TEXT NOT NULL,\n request_id TEXT NOT NULL,\n operation TEXT NOT NULL,\n fingerprint TEXT NOT NULL,\n result_json TEXT NOT NULL,\n created_at TEXT NOT NULL,\n PRIMARY KEY(project_hash, actor_id, request_id, operation)\n );\n\n -- Perspective Memory: privacy-safe actors/peers\n CREATE TABLE IF NOT EXISTS memory_actors (\n actor_id TEXT PRIMARY KEY,\n project_hash TEXT NOT NULL DEFAULT '',\n kind TEXT NOT NULL,\n display_name TEXT NOT NULL,\n source TEXT NOT NULL,\n metadata_json TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL\n );\n\n -- Perspective Memory: actors participating in a session and observation policy\n CREATE TABLE IF NOT EXISTS session_actors (\n project_hash TEXT NOT NULL DEFAULT '',\n session_id TEXT NOT NULL,\n actor_id TEXT NOT NULL,\n role_in_session TEXT NOT NULL,\n observe_self INTEGER NOT NULL DEFAULT 1,\n observe_others INTEGER NOT NULL DEFAULT 0,\n joined_at TEXT NOT NULL,\n left_at TEXT,\n metadata_json TEXT,\n PRIMARY KEY(project_hash, session_id, actor_id)\n );\n\n -- Perspective Memory: compact Honcho-style actor cards\n CREATE TABLE IF NOT EXISTS actor_cards (\n card_id TEXT PRIMARY KEY,\n project_hash TEXT NOT NULL DEFAULT '',\n observer_actor_id TEXT NOT NULL,\n observed_actor_id TEXT NOT NULL,\n entries_json TEXT NOT NULL,\n source_event_ids_json TEXT NOT NULL DEFAULT '[]',\n updated_by TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n UNIQUE(project_hash, observer_actor_id, observed_actor_id)\n );\n\n -- Core memory blocks: small, always-injected, agent-editable per-project\n -- resident context (Letta-style core memory), distinct from actor_cards'\n -- per-observer-pair perspective model.\n CREATE TABLE IF NOT EXISTS core_memory_blocks (\n project_hash TEXT NOT NULL DEFAULT '',\n block_key TEXT NOT NULL,\n content TEXT NOT NULL DEFAULT '',\n source_event_ids_json TEXT NOT NULL DEFAULT '[]',\n updated_by TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n PRIMARY KEY(project_hash, block_key)\n );\n\n -- Perspective Memory: observer -> observed claims with evidence pointers\n CREATE TABLE IF NOT EXISTS perspective_observations (\n observation_id TEXT PRIMARY KEY,\n project_hash TEXT NOT NULL DEFAULT '',\n observer_actor_id TEXT NOT NULL,\n observed_actor_id TEXT NOT NULL,\n session_id TEXT,\n level TEXT NOT NULL,\n content TEXT NOT NULL,\n confidence REAL NOT NULL,\n source_event_ids_json TEXT NOT NULL DEFAULT '[]',\n source_observation_ids_json TEXT NOT NULL DEFAULT '[]',\n created_by TEXT NOT NULL,\n metadata_json TEXT,\n content_hash TEXT NOT NULL,\n source_hash TEXT NOT NULL,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n deleted_at TEXT,\n UNIQUE(project_hash, observer_actor_id, observed_actor_id, level, content_hash, source_hash)\n );\n\n -- Memory Assets: project-scoped registry and minimal actor permissions.\n -- Asset content remains in its canonical subsystem; this table owns only\n -- lifecycle, provenance, and access-control metadata.\n CREATE TABLE IF NOT EXISTS memory_assets (\n asset_id TEXT NOT NULL,\n project_hash TEXT NOT NULL DEFAULT '',\n asset_type TEXT NOT NULL,\n title TEXT NOT NULL,\n owner_actor_id TEXT NOT NULL,\n version INTEGER NOT NULL DEFAULT 1,\n status TEXT NOT NULL DEFAULT 'active',\n visibility TEXT NOT NULL DEFAULT 'private',\n source_refs_json TEXT NOT NULL DEFAULT '[]',\n metadata_json TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n PRIMARY KEY(project_hash, asset_id)\n );\n\n -- An enabled binding makes a private asset readable/injectable for one\n -- actor. It does not grant write, bind, or delegation authority.\n CREATE TABLE IF NOT EXISTS memory_asset_bindings (\n project_hash TEXT NOT NULL DEFAULT '',\n asset_id TEXT NOT NULL,\n actor_id TEXT NOT NULL,\n injection_mode TEXT NOT NULL DEFAULT 'reference',\n priority INTEGER NOT NULL DEFAULT 0,\n enabled INTEGER NOT NULL DEFAULT 1,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n PRIMARY KEY(project_hash, asset_id, actor_id),\n FOREIGN KEY(project_hash, asset_id) REFERENCES memory_assets(project_hash, asset_id) ON DELETE CASCADE\n );\n\n -- Explicit grants are full replacements per asset/actor. An empty JSON\n -- permission list is therefore an auditable revocation tombstone.\n CREATE TABLE IF NOT EXISTS memory_asset_grants (\n project_hash TEXT NOT NULL DEFAULT '',\n asset_id TEXT NOT NULL,\n actor_id TEXT NOT NULL,\n permissions_json TEXT NOT NULL DEFAULT '[]',\n created_by TEXT NOT NULL,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n PRIMARY KEY(project_hash, asset_id, actor_id),\n FOREIGN KEY(project_hash, asset_id) REFERENCES memory_assets(project_hash, asset_id) ON DELETE CASCADE\n );\n\n -- Perspective Memory: FTS5 index for observation content queries.\n -- Use an external-content FTS table so the searchable projection stores the index,\n -- not a second raw copy of private observation text.\n CREATE VIRTUAL TABLE IF NOT EXISTS perspective_observations_fts USING fts5(\n content,\n observation_id UNINDEXED,\n content='perspective_observations',\n content_rowid='rowid',\n tokenize='porter unicode61'\n );\n\n -- Backfill the FTS table for writable legacy stores that predate the FTS projection.\n INSERT OR IGNORE INTO perspective_observations_fts(rowid, content, observation_id)\n SELECT rowid, content, observation_id FROM perspective_observations;\n\n CREATE TRIGGER IF NOT EXISTS perspective_observations_fts_insert AFTER INSERT ON perspective_observations BEGIN\n INSERT INTO perspective_observations_fts(rowid, content, observation_id) VALUES (NEW.rowid, NEW.content, NEW.observation_id);\n END;\n\n CREATE TRIGGER IF NOT EXISTS perspective_observations_fts_delete AFTER DELETE ON perspective_observations BEGIN\n INSERT INTO perspective_observations_fts(perspective_observations_fts, rowid, content, observation_id) VALUES('delete', OLD.rowid, OLD.content, OLD.observation_id);\n END;\n\n CREATE TRIGGER IF NOT EXISTS perspective_observations_fts_update AFTER UPDATE ON perspective_observations BEGIN\n INSERT INTO perspective_observations_fts(perspective_observations_fts, rowid, content, observation_id) VALUES('delete', OLD.rowid, OLD.content, OLD.observation_id);\n INSERT INTO perspective_observations_fts(rowid, content, observation_id) VALUES (NEW.rowid, NEW.content, NEW.observation_id);\n END;\n\n -- Memory Operations: governance/audit trail for state-changing operations\n CREATE TABLE IF NOT EXISTS memory_governance_audit (\n audit_id TEXT PRIMARY KEY,\n operation TEXT NOT NULL,\n actor TEXT NOT NULL,\n project_hash TEXT,\n target_type TEXT NOT NULL,\n target_id TEXT NOT NULL,\n before_json TEXT,\n after_json TEXT,\n source_event_ids TEXT NOT NULL DEFAULT '[]',\n created_at TEXT NOT NULL\n );\n\n -- Create indexes\n CREATE INDEX IF NOT EXISTS idx_events_session ON events(session_id);\n CREATE INDEX IF NOT EXISTS idx_events_timestamp ON events(timestamp);\n -- Serves getRecentEvents' event_type filter. Without it SQLite walks\n -- idx_events_timestamp backwards and evaluates the quarantine predicate\n -- on every visited row; a store holding fewer matching events than the\n -- limit then degrades into a full table scan on the SessionStart path.\n CREATE INDEX IF NOT EXISTS idx_events_type_timestamp ON events(event_type, timestamp);\n CREATE INDEX IF NOT EXISTS idx_entries_type ON entries(entry_type);\n CREATE INDEX IF NOT EXISTS idx_entries_stage ON entries(stage);\n CREATE INDEX IF NOT EXISTS idx_entries_canonical ON entries(canonical_key);\n CREATE INDEX IF NOT EXISTS idx_entities_type_key ON entities(entity_type, canonical_key);\n CREATE INDEX IF NOT EXISTS idx_entities_status ON entities(status);\n CREATE INDEX IF NOT EXISTS idx_edges_src ON edges(src_id, rel_type);\n CREATE INDEX IF NOT EXISTS idx_edges_dst ON edges(dst_id, rel_type);\n CREATE INDEX IF NOT EXISTS idx_edges_rel ON edges(rel_type);\n -- codify-lite session-file lane (Retriever.expandSessionFileLinks) filters\n -- touched_in edges by meta_json.sessionId on every retrieval; without this\n -- expression index the cost grows with total touched_in edge count.\n CREATE INDEX IF NOT EXISTS idx_edges_touched_in_session\n ON edges(json_extract(meta_json, '$.sessionId'))\n WHERE rel_type = 'touched_in';\n CREATE INDEX IF NOT EXISTS idx_outbox_status ON vector_outbox(status);\n CREATE INDEX IF NOT EXISTS idx_outbox_created ON vector_outbox(created_at);\n CREATE INDEX IF NOT EXISTS idx_working_set_expires ON working_set(expires_at);\n CREATE INDEX IF NOT EXISTS idx_working_set_relevance ON working_set(relevance_score);\n CREATE INDEX IF NOT EXISTS idx_consolidated_confidence ON consolidated_memories(confidence);\n CREATE INDEX IF NOT EXISTS idx_continuity_created ON continuity_log(created_at);\n CREATE INDEX IF NOT EXISTS idx_consolidated_rules_confidence ON consolidated_rules(confidence);\n CREATE INDEX IF NOT EXISTS idx_embedding_outbox_status ON embedding_outbox(status);\n CREATE INDEX IF NOT EXISTS idx_helpfulness_event ON memory_helpfulness(event_id);\n CREATE INDEX IF NOT EXISTS idx_helpfulness_session ON memory_helpfulness(session_id);\n CREATE INDEX IF NOT EXISTS idx_helpfulness_score ON memory_helpfulness(helpfulness_score DESC);\n CREATE INDEX IF NOT EXISTS idx_helpfulness_created_at ON memory_helpfulness(created_at);\n CREATE INDEX IF NOT EXISTS idx_helpfulness_measured_at ON memory_helpfulness(measured_at);\n CREATE INDEX IF NOT EXISTS idx_retrieval_traces_created_at ON retrieval_traces(created_at DESC);\n CREATE INDEX IF NOT EXISTS idx_retrieval_traces_project_hash ON retrieval_traces(project_hash);\n CREATE INDEX IF NOT EXISTS idx_retrieval_traces_session_id ON retrieval_traces(session_id);\n\n CREATE INDEX IF NOT EXISTS idx_retrieval_navigation_trace ON retrieval_navigation_events(trace_id);\n CREATE INDEX IF NOT EXISTS idx_retrieval_navigation_target_time ON retrieval_navigation_events(target_event_id, last_opened_at DESC);\n CREATE INDEX IF NOT EXISTS idx_memory_facets_project_dimension_value ON memory_facets(project_hash, dimension, value);\n CREATE INDEX IF NOT EXISTS idx_memory_facets_target ON memory_facets(target_type, target_id);\n CREATE INDEX IF NOT EXISTS idx_memory_facets_dimension_value_confidence ON memory_facets(dimension, value, confidence DESC);\n CREATE INDEX IF NOT EXISTS idx_memory_actions_project_status_priority ON memory_actions(project_hash, status, priority DESC, updated_at DESC);\n CREATE INDEX IF NOT EXISTS idx_memory_action_edges_src ON memory_action_edges(src_action_id, rel_type);\n CREATE INDEX IF NOT EXISTS idx_memory_action_edges_dst ON memory_action_edges(dst_type, dst_id);\n CREATE INDEX IF NOT EXISTS idx_memory_leases_target_expires ON memory_leases(target_type, target_id, expires_at);\n CREATE INDEX IF NOT EXISTS idx_memory_checkpoints_project_action_created ON memory_checkpoints(project_hash, action_id, created_at DESC);\n CREATE INDEX IF NOT EXISTS idx_memory_checkpoints_project_session_created ON memory_checkpoints(project_hash, session_id, created_at DESC);\n CREATE INDEX IF NOT EXISTS idx_memory_retention_scores_project_decision_score ON memory_retention_scores(project_hash, decision, lifecycle_score ASC, evaluated_at DESC);\n CREATE INDEX IF NOT EXISTS idx_memory_retention_scores_target ON memory_retention_scores(target_type, target_id, project_hash);\n CREATE INDEX IF NOT EXISTS idx_memory_retention_scores_policy_evaluated ON memory_retention_scores(policy_version, evaluated_at DESC);\n CREATE INDEX IF NOT EXISTS idx_memory_lessons_project_confidence ON memory_lessons(project_hash, confidence DESC, updated_at DESC);\n CREATE INDEX IF NOT EXISTS idx_memory_lessons_skill_candidate ON memory_lessons(project_hash, skill_candidate, confidence DESC);\n CREATE INDEX IF NOT EXISTS idx_memory_lessons_updated ON memory_lessons(updated_at DESC);\n CREATE INDEX IF NOT EXISTS idx_memory_actors_project_kind ON memory_actors(project_hash, kind, updated_at DESC);\n CREATE INDEX IF NOT EXISTS idx_memory_actors_source ON memory_actors(source, kind);\n CREATE INDEX IF NOT EXISTS idx_session_actors_session ON session_actors(project_hash, session_id, role_in_session);\n CREATE INDEX IF NOT EXISTS idx_session_actors_actor ON session_actors(actor_id, project_hash, session_id);\n CREATE INDEX IF NOT EXISTS idx_actor_cards_perspective ON actor_cards(project_hash, observer_actor_id, observed_actor_id);\n CREATE INDEX IF NOT EXISTS idx_actor_cards_updated ON actor_cards(updated_at DESC);\n CREATE INDEX IF NOT EXISTS idx_perspective_observations_perspective_level ON perspective_observations(project_hash, observer_actor_id, observed_actor_id, level, confidence DESC, updated_at DESC);\n CREATE INDEX IF NOT EXISTS idx_perspective_observations_session ON perspective_observations(project_hash, session_id, level, updated_at DESC);\n CREATE INDEX IF NOT EXISTS idx_perspective_observations_source_hash ON perspective_observations(project_hash, source_hash);\n CREATE INDEX IF NOT EXISTS idx_perspective_observations_deleted ON perspective_observations(deleted_at);\n CREATE INDEX IF NOT EXISTS idx_memory_assets_project_status ON memory_assets(project_hash, status, updated_at DESC);\n CREATE INDEX IF NOT EXISTS idx_memory_assets_owner ON memory_assets(project_hash, owner_actor_id, updated_at DESC);\n CREATE INDEX IF NOT EXISTS idx_memory_asset_bindings_actor ON memory_asset_bindings(project_hash, actor_id, enabled, priority DESC);\n CREATE INDEX IF NOT EXISTS idx_memory_asset_grants_actor ON memory_asset_grants(project_hash, actor_id, updated_at DESC);\n CREATE INDEX IF NOT EXISTS idx_memory_governance_audit_project_operation ON memory_governance_audit(project_hash, operation, created_at DESC);\n CREATE INDEX IF NOT EXISTS idx_memory_governance_audit_target ON memory_governance_audit(target_type, target_id, created_at DESC);\n\n -- FTS5 Full-Text Search for fast keyword search\n CREATE VIRTUAL TABLE IF NOT EXISTS events_fts USING fts5(\n content,\n event_id UNINDEXED,\n tokenize='porter unicode61'\n );\n\n -- Triggers to keep FTS in sync with events table\n CREATE TRIGGER IF NOT EXISTS events_fts_insert AFTER INSERT ON events BEGIN\n INSERT INTO events_fts(rowid, content, event_id) VALUES (NEW.rowid, NEW.content, NEW.id);\n END;\n\n CREATE TRIGGER IF NOT EXISTS events_fts_delete AFTER DELETE ON events BEGIN\n DELETE FROM events_fts WHERE rowid = OLD.rowid;\n END;\n\n CREATE TRIGGER IF NOT EXISTS events_fts_update AFTER UPDATE ON events BEGIN\n DELETE FROM events_fts WHERE rowid = OLD.rowid;\n INSERT INTO events_fts(rowid, content, event_id) VALUES (NEW.rowid, NEW.content, NEW.id);\n END;\n\n -- Reverse index for citation ids (a non-reversible hash of event id), so\n -- citation lookups are O(1) instead of scanning recent events and hashing\n -- each one. Populated lazily/self-healing by getEventByCitationId.\n CREATE TABLE IF NOT EXISTS event_citations (\n event_id TEXT PRIMARY KEY,\n citation_id TEXT NOT NULL\n );\n CREATE INDEX IF NOT EXISTS idx_event_citations_citation ON event_citations(citation_id);\n `);\n\n\n // Best-effort forward migration for action edge source ownership\n this.addColumnIfMissing('memory_action_edges', 'source', `TEXT NOT NULL DEFAULT 'manual'`);\n try {\n const edgeIndexes = sqliteAll<{ name: string; unique: number }>(this.db, `PRAGMA index_list(memory_action_edges)`, []);\n const hasSourceAwareUnique = edgeIndexes.some((index) => {\n if (Number(index.unique) !== 1) return false;\n if (!/^[A-Za-z0-9_]+$/.test(index.name)) return false;\n const escapedName = index.name.replace(/\"/g, '\"\"');\n const columns = sqliteAll<{ name: string }>(this.db, 'PRAGMA index_info(\"' + escapedName + '\")', [])\n .map((column) => column.name);\n return columns.length === 5\n && columns[0] === 'src_action_id'\n && columns[1] === 'rel_type'\n && columns[2] === 'dst_type'\n && columns[3] === 'dst_id'\n && columns[4] === 'source';\n });\n if (!hasSourceAwareUnique) {\n sqliteExec(this.db, `\n DROP TABLE IF EXISTS memory_action_edges_v2;\n CREATE TABLE memory_action_edges_v2 (\n edge_id TEXT PRIMARY KEY,\n src_action_id TEXT NOT NULL,\n rel_type TEXT NOT NULL,\n dst_type TEXT NOT NULL,\n dst_id TEXT NOT NULL,\n confidence REAL NOT NULL DEFAULT 1.0,\n source TEXT NOT NULL DEFAULT 'manual',\n created_at TEXT NOT NULL,\n UNIQUE(src_action_id, rel_type, dst_type, dst_id, source)\n );\n INSERT OR IGNORE INTO memory_action_edges_v2 (\n edge_id, src_action_id, rel_type, dst_type, dst_id, confidence, source, created_at\n )\n SELECT edge_id, src_action_id, rel_type, dst_type, dst_id, confidence, source, created_at\n FROM memory_action_edges;\n DROP TABLE memory_action_edges;\n ALTER TABLE memory_action_edges_v2 RENAME TO memory_action_edges;\n CREATE INDEX IF NOT EXISTS idx_memory_action_edges_src ON memory_action_edges(src_action_id, rel_type);\n CREATE INDEX IF NOT EXISTS idx_memory_action_edges_dst ON memory_action_edges(dst_type, dst_id);\n `);\n }\n } catch {\n // action edge table may not exist in partial migrations\n }\n\n // Best-effort forward migration for helpfulness evidence columns:\n // trace_id links each injected memory back to its retrieval_traces row\n // (question -> memory), content grounding measures whether later\n // assistant responses actually reused the memory's content.\n this.addColumnIfMissing('memory_helpfulness', 'trace_id', 'TEXT');\n this.addColumnIfMissing('memory_helpfulness', 'source', `TEXT DEFAULT 'user_prompt'`);\n this.addColumnIfMissing('memory_helpfulness', 'content_overlap_score', 'REAL');\n this.addColumnIfMissing('memory_helpfulness', 'evidence_json', 'TEXT');\n this.addColumnIfMissing('memory_helpfulness', 'injected_content', 'TEXT');\n this.addColumnIfMissing('memory_helpfulness', 'presentation_mode', `TEXT NOT NULL DEFAULT 'unknown'`);\n this.addColumnIfMissing('memory_helpfulness', 'trigger_type', `TEXT NOT NULL DEFAULT 'unknown'`);\n this.addColumnIfMissing('memory_helpfulness', 'delivery_client', `TEXT NOT NULL DEFAULT 'unknown'`);\n try {\n sqliteExec(this.db, `CREATE INDEX IF NOT EXISTS idx_helpfulness_trace ON memory_helpfulness(trace_id);`);\n } catch {\n // index/table may not exist in partial migrations\n }\n\n // Best-effort forward migration for retrieval trace detail columns\n this.addColumnIfMissing('retrieval_traces', 'selected_details_json', 'TEXT');\n this.addColumnIfMissing('retrieval_traces', 'candidate_details_json', 'TEXT');\n this.addColumnIfMissing('retrieval_traces', 'raw_query_text', 'TEXT');\n this.addColumnIfMissing('retrieval_traces', 'query_rewrite_kind', 'TEXT');\n this.addColumnIfMissing('retrieval_traces', 'presentation_mode', `TEXT NOT NULL DEFAULT 'unknown'`);\n this.addColumnIfMissing('retrieval_traces', 'trigger_type', `TEXT NOT NULL DEFAULT 'unknown'`);\n this.addColumnIfMissing('retrieval_traces', 'delivery_client', `TEXT NOT NULL DEFAULT 'unknown'`);\n // Legacy stores keep 'runtime_error' as the column default so their\n // existing rows are unchanged; readers present those as\n // `legacy_unclassified` instead of re-classifying them (specs R2).\n this.addColumnIfMissing('retrieval_traces', 'outcome_reason', `TEXT NOT NULL DEFAULT 'runtime_error'`);\n this.addColumnIfMissing('retrieval_traces', 'retrieval_diagnostics_json', 'TEXT');\n this.addColumnIfMissing('retrieval_traces', 'request_id', 'TEXT');\n this.addColumnIfMissing('retrieval_traces', 'evaluation_run_id', 'TEXT');\n this.addColumnIfMissing('retrieval_traces', 'runtime_version', 'TEXT');\n this.addColumnIfMissing('retrieval_traces', 'telemetry_schema_version', 'INTEGER NOT NULL DEFAULT 0');\n this.addColumnIfMissing('memory_helpfulness', 'memory_kind', `TEXT NOT NULL DEFAULT 'unknown'`);\n this.addColumnIfMissing('retrieval_navigation_events', 'memory_kind', `TEXT NOT NULL DEFAULT 'event'`);\n this.addColumnIfMissing('retrieval_navigation_events', 'memory_project_id', 'TEXT');\n this.addColumnIfMissing('memory_helpfulness', 'delivery_status', `TEXT NOT NULL DEFAULT 'unknown'`);\n this.addColumnIfMissing('memory_helpfulness', 'delivery_evidence', `TEXT NOT NULL DEFAULT 'none'`);\n this.addColumnIfMissing('memory_helpfulness', 'delivered_at', 'TEXT');\n this.addColumnIfMissing('memory_usefulness_observations_v2', 'memory_kind', `TEXT NOT NULL DEFAULT 'unknown'`);\n this.addColumnIfMissing('memory_usefulness_observations_v2', 'delivery_status', `TEXT NOT NULL DEFAULT 'unknown'`);\n this.addColumnIfMissing('memory_usefulness_observations_v2', 'delivery_evidence', `TEXT NOT NULL DEFAULT 'none'`);\n this.addColumnIfMissing('memory_usefulness_observations_v2', 'evaluation_window_ms', 'INTEGER');\n this.addColumnIfMissing('memory_usefulness_observations_v2', 'evaluation_cutoff', 'TEXT');\n // The raw memory id, kept beside the primary-key column. `event_id` has to\n // carry a kind-qualified key for non-event memories so an event and a\n // lesson sharing an id cannot overwrite each other on the existing primary\n // key; `memory_id` is what a reader joins on (specs R1, finding 2).\n this.addColumnIfMissing('memory_usefulness_observations_v2', 'memory_id', 'TEXT');\n this.addColumnIfMissing('memory_usefulness_observations_v2', 'memory_project_id', 'TEXT');\n this.addColumnIfMissing('memory_helpfulness', 'memory_project_id', 'TEXT');\n try {\n // Typed trace items are additive: an older store gains the table without\n // any change to the arrays its existing readers use.\n ensureRetrievalTraceItemsSchema(this.db);\n // Indexed only after the column migration above, so a legacy store that\n // predates request_id is not asked to index a column it lacks.\n sqliteExec(this.db, `CREATE INDEX IF NOT EXISTS idx_retrieval_traces_request_id ON retrieval_traces(request_id);`);\n } catch {\n // Partial migrations must not block store startup.\n }\n try {\n // One request must map to one trace even when two processes write at the\n // same moment. The partial index leaves the pre-existing rows with a NULL\n // request id untouched (specs R2, finding 9).\n sqliteExec(\n this.db,\n `CREATE UNIQUE INDEX IF NOT EXISTS idx_retrieval_traces_request_id_unique\n ON retrieval_traces(request_id) WHERE request_id IS NOT NULL;`\n );\n } catch {\n // A store that already contains duplicate request ids cannot take the\n // unique index. Leave its history intact: the transaction in\n // recordRetrievalTrace still serializes this process's own writers.\n }\n\n // Explicit curation reuses the existing lesson artifact while preserving\n // whether the item came from a reviewed/manual capture or a derivation.\n this.addColumnIfMissing('memory_lessons', 'source_class', `TEXT NOT NULL DEFAULT 'derived'`);\n // A lesson access used to be written against events.access_count, where it\n // matched no row and was silently lost. The typed access path now records\n // it here instead (specs R1).\n this.addColumnIfMissing('memory_lessons', 'access_count', 'INTEGER NOT NULL DEFAULT 0');\n this.addColumnIfMissing('memory_lessons', 'last_accessed_at', 'TEXT');\n this.addColumnIfMissing('memory_lessons', 'revision', 'INTEGER NOT NULL DEFAULT 1');\n this.addColumnIfMissing('memory_lessons', 'recall_enabled', 'INTEGER NOT NULL DEFAULT 1');\n this.addColumnIfMissing('memory_lessons', 'scope', 'TEXT');\n this.addColumnIfMissing('memory_lessons', 'validation_json', `TEXT NOT NULL DEFAULT '[]'`);\n this.addColumnIfMissing('memory_lessons', 'reconsider_when', 'TEXT');\n this.addColumnIfMissing('memory_lessons', 'valid_versions_json', `TEXT NOT NULL DEFAULT '[]'`);\n this.addColumnIfMissing('lesson_host_traces', 'machine_id', `TEXT NOT NULL DEFAULT ''`);\n this.addColumnIfMissing('lesson_host_traces', 'lesson_revisions_json', `TEXT NOT NULL DEFAULT '[]'`);\n this.addColumnIfMissing('lesson_review_candidates', 'duplicate_lesson_ids_json', `TEXT NOT NULL DEFAULT '[]'`);\n try {\n sqliteExec(this.db, `CREATE INDEX IF NOT EXISTS idx_memory_lessons_project_source_class ON memory_lessons(project_hash, source_class, updated_at DESC);`);\n sqliteExec(this.db, `CREATE INDEX IF NOT EXISTS idx_memory_lessons_project_recall ON memory_lessons(project_hash, recall_enabled, confidence DESC, updated_at DESC);`);\n } catch {\n // index/table may not exist in partial migrations\n }\n try {\n sqliteExec(this.db, `CREATE INDEX IF NOT EXISTS idx_retrieval_traces_query_rewrite_kind ON retrieval_traces(query_rewrite_kind);`);\n } catch {\n // index/table may not exist in partial migrations\n }\n\n // Forward-migrate the events table columns added over time. turn_id groups\n // events within a conversation turn; access_count/last_accessed_at back\n // access analytics.\n this.addColumnIfMissing('events', 'access_count', 'INTEGER DEFAULT 0');\n this.addColumnIfMissing('events', 'last_accessed_at', 'TEXT');\n this.addColumnIfMissing('events', 'turn_id', 'TEXT');\n\n // Create indexes for new columns if they don't exist\n try {\n sqliteExec(this.db, `\n CREATE INDEX IF NOT EXISTS idx_events_access_count ON events(access_count DESC);\n `);\n } catch (err: any) {\n // Index may already exist, ignore\n }\n\n try {\n sqliteExec(this.db, `\n CREATE INDEX IF NOT EXISTS idx_events_last_accessed ON events(last_accessed_at DESC);\n `);\n } catch (err: any) {\n // Index may already exist, ignore\n }\n\n try {\n sqliteExec(this.db, `\n CREATE INDEX IF NOT EXISTS idx_events_turn_id ON events(turn_id);\n `);\n } catch {\n // Index may already exist, ignore\n }\n\n // One-time backfill of the consolidated_memory_events junction from existing\n // source_events JSON (idempotent; skipped once the junction has any rows).\n const cmeCount = sqliteGet<{ c: number }>(this.db, `SELECT COUNT(*) as c FROM consolidated_memory_events`, []);\n if ((cmeCount?.c ?? 0) === 0) {\n sqliteExec(this.db, `\n INSERT OR IGNORE INTO consolidated_memory_events (memory_id, event_id)\n SELECT cm.memory_id, je.value\n FROM consolidated_memories cm, json_each(cm.source_events) je\n WHERE json_valid(cm.source_events);\n `);\n }\n\n // Stamp the schema version so future ordered migrations have an anchor to\n // gate on (PRAGMA user_version persists in the DB file). The migrations\n // above remain idempotent, so this is forward-looking rather than required.\n sqliteExec(this.db, `PRAGMA user_version = ${SQLITE_SCHEMA_VERSION}`);\n\n this.initialized = true;\n }\n\n /**\n * Append event to store (Append-only, Idempotent)\n */\n async append(input: MemoryEventInput): Promise<AppendResult> {\n await this.initialize();\n\n const canonicalKey = makeCanonicalKey(input.content);\n const dedupeKey = makeDedupeKey(input.content, input.sessionId);\n\n // Check for duplicate\n const existing = sqliteGet<{ event_id: string }>(\n this.db,\n `SELECT event_id FROM event_dedup WHERE dedupe_key = ?`,\n [dedupeKey]\n );\n\n if (existing) {\n try {\n await this.enqueueVectorOutboxEvent(existing.event_id, input.eventType);\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error)\n };\n }\n return {\n success: true,\n eventId: existing.event_id,\n isDuplicate: true\n };\n }\n\n const id = randomUUID();\n const timestamp = toSQLiteTimestamp(input.timestamp);\n\n try {\n // Extract turnId from metadata if present\n const metadata = input.metadata || {};\n const turnId = (metadata.turnId as string) || null;\n\n // Use transaction for atomicity\n const insertEvent = this.db.prepare(`\n INSERT INTO events (id, event_type, session_id, timestamp, content, canonical_key, dedupe_key, metadata, turn_id)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)\n `);\n\n const insertDedup = this.db.prepare(`\n INSERT INTO event_dedup (dedupe_key, event_id) VALUES (?, ?)\n `);\n\n const insertLevel = this.db.prepare(`\n INSERT INTO memory_levels (event_id, level) VALUES (?, 'L0')\n `);\n\n const transaction = this.db.transaction(() => {\n insertEvent.run(\n id,\n input.eventType,\n input.sessionId,\n timestamp,\n input.content,\n canonicalKey,\n dedupeKey,\n JSON.stringify(metadata),\n turnId\n );\n insertDedup.run(dedupeKey, id);\n insertLevel.run(id);\n this.enqueueVectorOutboxEventSync(id, input.eventType);\n });\n\n transaction();\n\n if (this.markdownMirror) {\n const event: MemoryEvent = {\n id,\n eventType: input.eventType,\n sessionId: input.sessionId,\n timestamp: input.timestamp,\n content: input.content,\n canonicalKey,\n dedupeKey,\n metadata\n };\n this.markdownMirror.append(event).catch((err) => {\n console.warn('[SQLiteEventStore] markdown mirror append failed:', err);\n });\n }\n\n return { success: true, eventId: id, isDuplicate: false };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error)\n };\n }\n }\n\n /**\n * Get session IDs that have events but no session_summary event.\n * Used to backfill summaries for sessions that ended without Stop hook.\n */\n async getSessionsWithoutSummary(currentSessionId: string, limit = 5): Promise<string[]> {\n await this.initialize();\n const rows = sqliteAll<{ session_id: string }>(\n this.db,\n `SELECT DISTINCT e.session_id\n FROM events e\n WHERE e.session_id != ?\n AND e.event_type != 'session_summary'\n AND e.session_id NOT IN (\n SELECT DISTINCT session_id FROM events WHERE event_type = 'session_summary'\n )\n GROUP BY e.session_id\n HAVING COUNT(*) >= 3\n ORDER BY MAX(e.timestamp) DESC\n LIMIT ?`,\n [currentSessionId, limit]\n );\n return rows.map((r) => r.session_id);\n }\n\n /**\n * Get events by session ID\n */\n async getSessionEvents(sessionId: string, options?: QuarantineReadOptions): Promise<MemoryEvent[]> {\n await this.initialize();\n\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM events WHERE session_id = ? AND ${maybeQuarantinePredicate(options)} ORDER BY timestamp ASC`,\n [sessionId]\n );\n\n return rows.map(this.rowToEvent);\n }\n\n /**\n * Get recent events, optionally restricted to a set of event types.\n *\n * The type filter exists because tool_observation is the overwhelming\n * majority of a real store (~84%). Callers that only want narrative events\n * would otherwise have to over-fetch by an order of magnitude \u2014 and load\n * every large tool payload along the way \u2014 just to reach a handful of\n * summaries.\n */\n async getRecentEvents(limit: number = 100, options?: RecentEventsReadOptions): Promise<MemoryEvent[]> {\n await this.initialize();\n\n const eventTypes = options?.eventTypes ?? [];\n const typePredicate = eventTypes.length > 0\n ? `AND event_type IN (${eventTypes.map(() => '?').join(', ')})`\n : '';\n\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM events\n WHERE ${maybeQuarantinePredicate(options)} ${typePredicate}\n ORDER BY timestamp DESC LIMIT ?`,\n [...eventTypes, limit]\n );\n\n return rows.map(this.rowToEvent);\n }\n\n /**\n * Aggregate event counts by type via SQL GROUP BY, instead of loading rows\n * into memory and counting in JS. Counts all events (the old recent-window\n * scan also under-counted stores larger than its cap).\n */\n async getEventTypeCounts(options?: QuarantineReadOptions): Promise<Array<{ eventType: string; count: number }>> {\n await this.initialize();\n const rows = sqliteAll<{ event_type: string; count: number }>(\n this.db,\n `SELECT event_type, COUNT(*) as count FROM events WHERE ${maybeQuarantinePredicate(options)} GROUP BY event_type`,\n []\n );\n return rows.map((row) => ({ eventType: row.event_type, count: row.count }));\n }\n\n /**\n * Fetch every event at/after an ISO timestamp (ascending), with no row cap.\n * For window-scoped analytics (KPI/usefulness) this fetches exactly the events\n * the window needs instead of an arbitrary \"most recent N\" slice that both\n * over-fetches sparse windows and truncates very active ones.\n */\n async getEventsAfter(sinceIso: string, options?: QuarantineReadOptions): Promise<MemoryEvent[]> {\n await this.initialize();\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM events WHERE timestamp >= ? AND ${maybeQuarantinePredicate(options)} ORDER BY timestamp ASC`,\n [sinceIso]\n );\n return rows.map((row) => this.rowToEvent(row));\n }\n\n /** Count distinct sessions via SQL instead of materializing a Set in JS. */\n async getDistinctSessionCount(options?: QuarantineReadOptions): Promise<number> {\n await this.initialize();\n const row = sqliteGet<{ count: number }>(\n this.db,\n `SELECT COUNT(DISTINCT session_id) as count FROM events WHERE ${maybeQuarantinePredicate(options)}`,\n []\n );\n return row?.count ?? 0;\n }\n\n /**\n * Per-day event counts (with type breakdown) since an ISO timestamp, computed\n * by SQL GROUP BY on the date prefix. Timestamps are stored as ISO-8601\n * strings, so substr(...,1,10) is the UTC day and `timestamp >= ?` compares\n * lexicographically.\n */\n async getDailyEventCounts(\n sinceIso: string,\n options?: QuarantineReadOptions\n ): Promise<Array<{ day: string; total: number; prompts: number; responses: number; tools: number }>> {\n await this.initialize();\n return sqliteAll<{ day: string; total: number; prompts: number; responses: number; tools: number }>(\n this.db,\n `SELECT substr(timestamp, 1, 10) as day,\n COUNT(*) as total,\n SUM(CASE WHEN event_type = 'user_prompt' THEN 1 ELSE 0 END) as prompts,\n SUM(CASE WHEN event_type = 'agent_response' THEN 1 ELSE 0 END) as responses,\n SUM(CASE WHEN event_type = 'tool_observation' THEN 1 ELSE 0 END) as tools\n FROM events\n WHERE timestamp >= ? AND ${maybeQuarantinePredicate(options)}\n GROUP BY day\n ORDER BY day ASC`,\n [sinceIso]\n );\n }\n\n /**\n * Get event by ID\n */\n async getEvent(id: string, options?: QuarantineReadOptions): Promise<MemoryEvent | null> {\n await this.initialize();\n\n const row = sqliteGet<Record<string, unknown>>(\n this.db,\n `SELECT * FROM events WHERE id = ? AND ${maybeQuarantinePredicate(options)}`,\n [id]\n );\n\n if (!row) return null;\n return this.rowToEvent(row);\n }\n\n /**\n * Batch-fetch events by id in a single query, applying the same quarantine\n * predicate as getEvent. Lets hot paths replace N sequential round-trips with\n * one. Missing ids are simply absent from the result (order not guaranteed).\n */\n async getEvents(ids: string[], options?: QuarantineReadOptions): Promise<MemoryEvent[]> {\n await this.initialize();\n if (ids.length === 0) return [];\n\n const placeholders = ids.map(() => '?').join(',');\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM events WHERE id IN (${placeholders}) AND ${maybeQuarantinePredicate(options)}`,\n ids\n );\n\n return rows.map((row) => this.rowToEvent(row));\n }\n\n /**\n * Resolve an event from its citation id via the reverse index, instead of\n * scanning recent events and hashing each one. The index is self-healing: a\n * miss triggers a one-time backfill of any events not yet indexed (covering\n * freshly appended events) before retrying.\n */\n async getEventByCitationId(citationId: string, options?: QuarantineReadOptions): Promise<MemoryEvent | null> {\n await this.initialize();\n if (!citationId) return null;\n\n let row = sqliteGet<{ event_id: string }>(\n this.db,\n `SELECT event_id FROM event_citations WHERE citation_id = ? LIMIT 1`,\n [citationId]\n );\n\n if (!row) {\n this.indexMissingCitations();\n row = sqliteGet<{ event_id: string }>(\n this.db,\n `SELECT event_id FROM event_citations WHERE citation_id = ? LIMIT 1`,\n [citationId]\n );\n }\n\n if (!row) return null;\n return this.getEvent(row.event_id, options);\n }\n\n /**\n * Backfill citation ids for any events not yet present in event_citations.\n * Gated on a cheap count comparison so the common (fully-indexed) path does no\n * work, and the scan only runs when there are genuinely new events to index.\n */\n private indexMissingCitations(): void {\n const eventCount = sqliteGet<{ c: number }>(this.db, `SELECT COUNT(*) as c FROM events`, [])?.c ?? 0;\n const indexedCount = sqliteGet<{ c: number }>(this.db, `SELECT COUNT(*) as c FROM event_citations`, [])?.c ?? 0;\n if (indexedCount >= eventCount) return;\n\n const unindexed = sqliteAll<{ id: string }>(\n this.db,\n `SELECT e.id FROM events e\n LEFT JOIN event_citations ec ON ec.event_id = e.id\n WHERE ec.event_id IS NULL`,\n []\n );\n if (unindexed.length === 0) return;\n\n const insert = this.db.prepare(`INSERT OR IGNORE INTO event_citations (event_id, citation_id) VALUES (?, ?)`);\n this.db.transaction(() => {\n for (const { id } of unindexed) {\n insert.run(id, generateCitationId(id));\n }\n })();\n }\n\n /**\n * Get events since a timestamp (for sync)\n */\n async getEventsSince(timestamp: string, limit: number = 1000, options?: QuarantineReadOptions): Promise<MemoryEvent[]> {\n await this.initialize();\n\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM events WHERE timestamp > ? AND ${maybeQuarantinePredicate(options)} ORDER BY timestamp ASC LIMIT ?`,\n [timestamp, limit]\n );\n\n return rows.map(this.rowToEvent);\n }\n\n /**\n * Get events since a SQLite rowid (for robust incremental replication).\n * Rowid is monotonic for append-only tables, independent of client timestamps.\n */\n async getEventsSinceRowid(\n lastRowid: number,\n limit: number = 1000,\n options?: QuarantineReadOptions\n ): Promise<Array<{ rowid: number; event: MemoryEvent }>> {\n await this.initialize();\n\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT rowid as _rowid, * FROM events WHERE rowid > ? AND ${maybeQuarantinePredicate(options)} ORDER BY rowid ASC LIMIT ?`,\n [lastRowid, limit]\n );\n\n return rows.map(row => ({\n rowid: row._rowid as number,\n event: this.rowToEvent(row)\n }));\n }\n\n /**\n * Import events with fixed IDs (used for cross-machine replication).\n * Idempotent: skips if event id or dedupeKey already exists.\n *\n * NOTE: This bypasses the append() id generation to preserve stable IDs.\n */\n async importEvents(events: MemoryEvent[]): Promise<{ inserted: number; skipped: number }> {\n if (events.length === 0) return { inserted: 0, skipped: 0 };\n if (this.readOnly) return { inserted: 0, skipped: events.length };\n\n await this.initialize();\n\n const getById = this.db.prepare(`SELECT id FROM events WHERE id = ?`);\n const getByDedupe = this.db.prepare(`SELECT event_id FROM event_dedup WHERE dedupe_key = ?`);\n\n const insertEvent = this.db.prepare(`\n INSERT INTO events (id, event_type, session_id, timestamp, content, canonical_key, dedupe_key, metadata, turn_id)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)\n `);\n\n const insertDedup = this.db.prepare(`\n INSERT INTO event_dedup (dedupe_key, event_id) VALUES (?, ?)\n `);\n\n const insertLevel = this.db.prepare(`\n INSERT INTO memory_levels (event_id, level) VALUES (?, 'L0')\n `);\n\n let inserted = 0;\n let skipped = 0;\n const insertedEvents: MemoryEvent[] = [];\n\n const tx = this.db.transaction((batch: MemoryEvent[]) => {\n for (const ev of batch) {\n // Skip if already present by id\n const existingById = getById.get(ev.id) as { id: string } | undefined;\n if (existingById) {\n skipped++;\n continue;\n }\n\n const canonicalKey = ev.canonicalKey || makeCanonicalKey(ev.content);\n const dedupeKey = ev.dedupeKey || makeDedupeKey(ev.content, ev.sessionId);\n\n // Skip if already present by dedupe key\n const existingByDedupe = getByDedupe.get(dedupeKey) as { event_id: string } | undefined;\n if (existingByDedupe) {\n skipped++;\n continue;\n }\n\n const metadata = ev.metadata || {};\n const turnId = (metadata as any).turnId as string | undefined;\n\n insertEvent.run(\n ev.id,\n ev.eventType,\n ev.sessionId,\n toSQLiteTimestamp(ev.timestamp),\n ev.content,\n canonicalKey,\n dedupeKey,\n JSON.stringify(metadata),\n turnId ?? null\n );\n\n insertDedup.run(dedupeKey, ev.id);\n insertLevel.run(ev.id);\n this.enqueueVectorOutboxEventSync(ev.id, ev.eventType);\n inserted++;\n insertedEvents.push(ev);\n }\n });\n\n tx(events);\n\n if (this.markdownMirror && insertedEvents.length > 0) {\n for (const ev of insertedEvents) {\n this.markdownMirror.append(ev).catch((err) => {\n console.warn('[SQLiteEventStore] markdown mirror append failed:', err);\n });\n }\n }\n\n return { inserted, skipped };\n }\n\n /**\n * Create or update session\n */\n async upsertSession(session: Partial<Session> & { id: string }): Promise<void> {\n await this.initialize();\n\n const existing = sqliteGet<{ id: string }>(\n this.db,\n `SELECT id FROM sessions WHERE id = ?`,\n [session.id]\n );\n\n if (!existing) {\n sqliteRun(\n this.db,\n `INSERT INTO sessions (id, started_at, project_path, tags)\n VALUES (?, ?, ?, ?)`,\n [\n session.id,\n toSQLiteTimestamp(session.startedAt || new Date()),\n session.projectPath || null,\n JSON.stringify(session.tags || [])\n ]\n );\n } else {\n const updates: string[] = [];\n const values: unknown[] = [];\n\n if (session.endedAt) {\n updates.push('ended_at = ?');\n values.push(toSQLiteTimestamp(session.endedAt));\n }\n if (session.summary) {\n updates.push('summary = ?');\n values.push(session.summary);\n }\n if (session.tags) {\n updates.push('tags = ?');\n values.push(JSON.stringify(session.tags));\n }\n\n if (updates.length > 0) {\n values.push(session.id);\n sqliteRun(\n this.db,\n `UPDATE sessions SET ${updates.join(', ')} WHERE id = ?`,\n values\n );\n }\n }\n }\n\n /**\n * Get session by ID\n */\n async getSession(id: string): Promise<Session | null> {\n await this.initialize();\n\n const row = sqliteGet<Record<string, unknown>>(\n this.db,\n `SELECT * FROM sessions WHERE id = ?`,\n [id]\n );\n\n if (!row) return null;\n\n return {\n id: row.id as string,\n startedAt: toDateFromSQLite(row.started_at),\n endedAt: row.ended_at ? toDateFromSQLite(row.ended_at) : undefined,\n projectPath: row.project_path as string | undefined,\n summary: row.summary as string | undefined,\n tags: row.tags ? JSON.parse(row.tags as string) : undefined\n };\n }\n\n /**\n * Get all sessions\n */\n async getAllSessions(): Promise<Session[]> {\n await this.initialize();\n\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM sessions ORDER BY started_at DESC`\n );\n\n return rows.map(row => ({\n id: row.id as string,\n startedAt: toDateFromSQLite(row.started_at),\n endedAt: row.ended_at ? toDateFromSQLite(row.ended_at) : undefined,\n projectPath: row.project_path as string | undefined,\n summary: row.summary as string | undefined,\n tags: row.tags ? JSON.parse(row.tags as string) : undefined\n }));\n }\n\n /**\n * Add to embedding outbox\n */\n async enqueueForEmbedding(eventId: string, content: string): Promise<string> {\n await this.initialize();\n\n const id = randomUUID();\n sqliteRun(\n this.db,\n `INSERT INTO embedding_outbox (id, event_id, content, status, retry_count)\n VALUES (?, ?, ?, 'pending', 0)`,\n [id, eventId, content]\n );\n\n return id;\n }\n\n /**\n * Get pending outbox items\n */\n async getPendingOutboxItems(limit: number = 32): Promise<OutboxItem[]> {\n await this.initialize();\n\n // Claim pending items atomically in a single UPDATE ... RETURNING. A\n // SELECT-then-UPDATE leaves a window where two concurrent workers (or a\n // worker plus processAll) both select the same rows before either marks them\n // 'processing', producing duplicate embedding work. The single statement\n // makes the claim race-free, matching VectorOutbox.claimJobs.\n const claimed = sqliteAll<Record<string, unknown>>(\n this.db,\n `UPDATE embedding_outbox\n SET status = 'processing', processed_at = datetime('now'), error_message = NULL\n WHERE id IN (\n SELECT id FROM embedding_outbox\n WHERE status = 'pending'\n ORDER BY created_at\n LIMIT ?\n )\n RETURNING *`,\n [limit]\n );\n\n if (claimed.length === 0) return [];\n\n // RETURNING does not guarantee row order; restore created_at ordering.\n claimed.sort((a, b) => String(a.created_at).localeCompare(String(b.created_at)));\n\n return claimed.map(row => ({\n id: row.id as string,\n eventId: row.event_id as string,\n content: row.content as string,\n status: 'processing' as const,\n retryCount: row.retry_count as number,\n createdAt: toDateFromSQLite(row.created_at),\n errorMessage: row.error_message as string | undefined\n }));\n }\n\n /**\n * Mark outbox items as done\n */\n async completeOutboxItems(ids: string[]): Promise<void> {\n if (ids.length === 0) return;\n\n const placeholders = ids.map(() => '?').join(',');\n sqliteRun(\n this.db,\n `DELETE FROM embedding_outbox WHERE id IN (${placeholders})`,\n ids\n );\n }\n\n /**\n * Clear embedding outbox (used for embedding model migration)\n */\n async clearEmbeddingOutbox(): Promise<void> {\n await this.initialize();\n sqliteRun(this.db, `DELETE FROM embedding_outbox`);\n }\n\n /**\n * Count total events\n */\n async countEvents(options?: QuarantineReadOptions): Promise<number> {\n await this.initialize();\n const row = sqliteGet<{ count: number }>(this.db, `SELECT COUNT(*) as count FROM events WHERE ${maybeQuarantinePredicate(options)}`);\n return row?.count || 0;\n }\n\n /**\n * Get events page in timestamp ascending order (stable migration/reindex scans)\n */\n async getEventsPage(limit: number = 1000, offset: number = 0, options?: QuarantineReadOptions): Promise<MemoryEvent[]> {\n await this.initialize();\n\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM events WHERE ${maybeQuarantinePredicate(options)} ORDER BY timestamp ASC LIMIT ? OFFSET ?`,\n [limit, offset]\n );\n\n return rows.map(this.rowToEvent);\n }\n\n /**\n * Mark outbox items as failed\n */\n async failOutboxItems(ids: string[], error: string): Promise<void> {\n if (ids.length === 0) return;\n\n const placeholders = ids.map(() => '?').join(',');\n sqliteRun(\n this.db,\n `UPDATE embedding_outbox\n SET status = CASE WHEN retry_count >= 3 THEN 'failed' ELSE 'pending' END,\n retry_count = retry_count + 1,\n error_message = ?\n WHERE id IN (${placeholders})`,\n [error, ...ids]\n );\n }\n\n /**\n * Recover abandoned outbox work after a worker/process crash.\n *\n * Rows in `processing` are claimed work. If the process exits before marking\n * them done/failed, they otherwise remain invisible to future processing.\n * Recovery is deliberately age-gated so an active worker is not disturbed.\n */\n async recoverStuckOutboxItems(options: OutboxRecoveryOptions = {}): Promise<OutboxRecoveryResult> {\n await this.initialize();\n\n const thresholdMs = Number.isFinite(options.stuckThresholdMs) && (options.stuckThresholdMs ?? 0) >= 0\n ? options.stuckThresholdMs!\n : DEFAULT_OUTBOX_STUCK_THRESHOLD_MS;\n const maxRetries = Number.isFinite(options.maxRetries) && (options.maxRetries ?? 0) > 0\n ? options.maxRetries!\n : DEFAULT_OUTBOX_MAX_RETRIES;\n const now = options.now ?? new Date();\n const threshold = new Date(now.getTime() - thresholdMs).toISOString();\n const result = emptyOutboxRecoveryResult();\n\n if (options.dryRun === true) {\n const embeddingRecovered = sqliteGet<{ count: number }>(\n this.db,\n `SELECT COUNT(*) AS count FROM embedding_outbox\n WHERE status = 'processing'\n AND datetime(COALESCE(processed_at, created_at)) < datetime(?)`,\n [threshold]\n );\n result.embedding.recoveredProcessing = Number(embeddingRecovered?.count ?? 0);\n\n const embeddingRetried = sqliteGet<{ count: number }>(\n this.db,\n `SELECT COUNT(*) AS count FROM embedding_outbox\n WHERE status = 'failed'\n AND retry_count < ?`,\n [maxRetries]\n );\n result.embedding.retriedFailed = Number(embeddingRetried?.count ?? 0);\n\n const vectorRecovered = sqliteGet<{ count: number }>(\n this.db,\n `SELECT COUNT(*) AS count FROM vector_outbox\n WHERE status = 'processing'\n AND datetime(updated_at) < datetime(?)`,\n [threshold]\n );\n result.vector.recoveredProcessing = Number(vectorRecovered?.count ?? 0);\n\n const vectorRetried = sqliteGet<{ count: number }>(\n this.db,\n `SELECT COUNT(*) AS count FROM vector_outbox\n WHERE status = 'failed'\n AND retry_count < ?`,\n [maxRetries]\n );\n result.vector.retriedFailed = Number(vectorRetried?.count ?? 0);\n\n return result;\n }\n\n const embeddingRecovered = sqliteRun(\n this.db,\n `UPDATE embedding_outbox\n SET status = 'pending', processed_at = NULL, error_message = NULL\n WHERE status = 'processing'\n AND datetime(COALESCE(processed_at, created_at)) < datetime(?)`,\n [threshold]\n );\n result.embedding.recoveredProcessing = Number(embeddingRecovered.changes ?? 0);\n\n const embeddingRetried = sqliteRun(\n this.db,\n `UPDATE embedding_outbox\n SET status = 'pending', error_message = NULL\n WHERE status = 'failed'\n AND retry_count < ?`,\n [maxRetries]\n );\n result.embedding.retriedFailed = Number(embeddingRetried.changes ?? 0);\n\n const vectorRecovered = sqliteRun(\n this.db,\n `UPDATE vector_outbox\n SET status = 'pending', updated_at = ?, error = NULL\n WHERE status = 'processing'\n AND datetime(updated_at) < datetime(?)`,\n [now.toISOString(), threshold]\n );\n result.vector.recoveredProcessing = Number(vectorRecovered.changes ?? 0);\n\n const vectorRetried = sqliteRun(\n this.db,\n `UPDATE vector_outbox\n SET status = 'pending', updated_at = ?, error = NULL\n WHERE status = 'failed'\n AND retry_count < ?`,\n [now.toISOString(), maxRetries]\n );\n result.vector.retriedFailed = Number(vectorRetried.changes ?? 0);\n\n return result;\n }\n\n\n /**\n * List event IDs for a given event type (used by maintenance/backfill tooling).\n */\n async listEventIdsByType(eventType: string): Promise<string[]> {\n await this.initialize();\n const rows = sqliteAll<{ id: string }>(\n this.db,\n `SELECT id FROM events WHERE event_type = ? ORDER BY timestamp ASC`,\n [eventType]\n );\n return rows.map((row) => row.id);\n }\n\n /**\n * Remove vector_outbox rows for the given event ids (item_kind = 'event').\n * Used after pruning already-embedded vectors so the outbox stops reporting\n * them as done work.\n */\n async removeVectorOutboxRowsForEventIds(eventIds: string[]): Promise<number> {\n if (eventIds.length === 0) return 0;\n await this.initialize();\n const placeholders = eventIds.map(() => '?').join(', ');\n const result = this.db.prepare(\n `DELETE FROM vector_outbox WHERE item_kind = 'event' AND item_id IN (${placeholders})`\n ).run(...eventIds);\n return Number(result.changes ?? 0);\n }\n\n /**\n * Repair legacy imported events that predate canonical project scope metadata.\n *\n * Same-project legacy rows are tagged with scope.project.hash. Rows that look\n * imported but cannot be proven to belong to this project are quarantined so\n * dashboard default reads/search do not surface cross-project contamination.\n */\n async repairLegacyProjectScope(options: ProjectScopeRepairOptions = {}): Promise<ProjectScopeRepairResult> {\n await this.initialize();\n\n const projectHash = options.projectHash || (options.projectPath ? hashProjectPath(options.projectPath) : undefined);\n if (!projectHash) {\n throw new Error('repairLegacyProjectScope requires projectPath or projectHash');\n }\n if (\n options.projectPath && options.projectHash\n && hashProjectPath(options.projectPath) !== options.projectHash\n // A store created before a .claude-memory-root marker was adopted is\n // keyed by the pre-marker (git-only) hash; addressing it by path + that\n // hash is consistent, not a different store.\n && hashProjectPathIgnoringMarker(options.projectPath) !== options.projectHash\n ) {\n throw new Error('repairLegacyProjectScope projectPath and projectHash refer to different project stores');\n }\n\n const dryRun = options.dryRun === true;\n const nowIso = (options.now || new Date()).toISOString();\n const result = buildRepairResult(projectHash, dryRun);\n\n const rows = sqliteAll<{\n id: string;\n content: string;\n metadata: string | null;\n session_project_path: string | null;\n }>(\n this.db,\n `SELECT e.id, e.content, e.metadata, s.project_path as session_project_path\n FROM events e\n LEFT JOIN sessions s ON s.id = e.session_id\n ORDER BY e.timestamp ASC`,\n []\n );\n\n const sample = (entry: ProjectScopeRepairSample) => {\n if (result.samples.length < 20) result.samples.push(entry);\n };\n\n for (const row of rows) {\n result.scanned++;\n\n let metadata: Record<string, unknown> = {};\n let metadataParseInvalid = false;\n if (row.metadata) {\n const parsed = safeParseMetadataValue(row.metadata);\n if (parsed) {\n metadata = parsed;\n } else {\n metadataParseInvalid = true;\n }\n }\n\n if (isActiveQuarantinedMetadata(metadata)) {\n result.skipped++;\n continue;\n }\n\n const currentHash = metadataProjectHash(metadata);\n const explicitPath = metadataProjectPath(metadata);\n const sessionProjectPath = typeof row.session_project_path === 'string' && row.session_project_path.length > 0\n ? row.session_project_path\n : undefined;\n const candidatePaths = metadataProjectPaths(metadata);\n if (sessionProjectPath && !candidatePaths.includes(sessionProjectPath)) {\n candidatePaths.push(sessionProjectPath);\n }\n const importedOrLegacy = metadataParseInvalid || isImportedOrLegacyScopedMetadata(metadata) || Boolean(sessionProjectPath);\n const pathHashes = candidatePaths.map((candidate) => {\n try {\n return {\n path: candidate,\n hash: hashProjectPath(candidate),\n // The hash the candidate had before any marker applied. A row\n // whose recorded path re-hashes elsewhere only because a\n // .claude-memory-root marker was adopted after the store filled\n // up is a basis shift, not cross-project contamination.\n preMarkerHash: hashProjectPathIgnoringMarker(candidate)\n };\n } catch {\n return { path: candidate, hash: undefined, preMarkerHash: undefined };\n }\n });\n const belongsToThisStore = (candidate: { hash?: string; preMarkerHash?: string }) =>\n candidate.hash === projectHash || candidate.preMarkerHash === projectHash;\n const matchingPath = pathHashes.find(belongsToThisStore);\n const foreignPath = pathHashes.find((candidate) => candidate.hash && !belongsToThisStore(candidate));\n\n let action: 'repaired' | 'quarantined' | 'skipped' = 'skipped';\n let reason: ProjectScopeRepairSample['reason'] | undefined;\n let observedProjectHash: string | undefined;\n\n if (foreignPath) {\n action = 'quarantined';\n reason = 'project-path-mismatch';\n observedProjectHash = foreignPath.hash;\n } else if (currentHash === projectHash && importedOrLegacy && hasConflictingContentProjectHint(row.content, options.projectPath)) {\n action = 'quarantined';\n reason = 'content-project-mismatch';\n } else if (currentHash === projectHash) {\n result.alreadyScoped++;\n continue;\n } else if (\n currentHash && currentHash !== projectHash\n // The stamp disagrees, but it is exactly the pre-marker hash of a\n // recorded path that provably belongs to this store: the hash basis\n // moved under the row (a .claude-memory-root marker was adopted), the\n // row did not move projects. Restamp instead of quarantining, or the\n // strict retrieval scope gate drops the row forever.\n && !(matchingPath && matchingPath.preMarkerHash === currentHash)\n ) {\n action = 'quarantined';\n reason = 'scope-hash-mismatch';\n observedProjectHash = currentHash;\n } else if (matchingPath) {\n action = 'repaired';\n reason = matchingPath.path === sessionProjectPath && matchingPath.path !== explicitPath\n ? 'session-project-path'\n : 'same-project-path';\n } else if (candidatePaths.length > 0) {\n action = 'quarantined';\n reason = 'project-path-mismatch';\n } else if (importedOrLegacy) {\n action = 'quarantined';\n reason = 'missing-project-scope';\n }\n\n if (action === 'skipped' || !reason) {\n result.skipped++;\n continue;\n }\n\n if (action === 'repaired') {\n const scope = isRecord(metadata.scope) ? { ...metadata.scope } : {};\n const project = isRecord(scope.project) ? { ...scope.project } : {};\n project.hash = projectHash;\n scope.project = project;\n metadata.scope = scope;\n metadata.repair = {\n ...(isRecord(metadata.repair) ? metadata.repair : {}),\n legacyProjectScope: {\n action,\n reason,\n repairedAt: nowIso\n }\n };\n addMetadataTag(metadata, `proj:${projectHash}`);\n result.repaired++;\n } else {\n metadata.quarantine = {\n ...(isRecord(metadata.quarantine) ? metadata.quarantine : {}),\n status: 'active',\n category: 'project-scope',\n reason,\n detectedAt: nowIso,\n expectedProjectHash: projectHash,\n ...(observedProjectHash ? { observedProjectHash } : {})\n };\n metadata.repair = {\n ...(isRecord(metadata.repair) ? metadata.repair : {}),\n legacyProjectScope: {\n action,\n reason,\n repairedAt: nowIso\n }\n };\n addMetadataTag(metadata, 'quarantine:project-scope');\n result.quarantined++;\n }\n\n sample({ eventId: row.id, action, reason });\n if (!dryRun) {\n sqliteRun(this.db, `UPDATE events SET metadata = ? WHERE id = ?`, [JSON.stringify(metadata), row.id]);\n }\n }\n\n return result;\n }\n\n /**\n * Get embedding/vector outbox health statistics\n */\n async getOutboxStats(options: OutboxStatsOptions = {}): Promise<OutboxStats> {\n await this.initialize();\n\n const thresholdMs = Number.isFinite(options.stuckThresholdMs) && (options.stuckThresholdMs ?? 0) >= 0\n ? options.stuckThresholdMs!\n : DEFAULT_OUTBOX_STUCK_THRESHOLD_MS;\n const maxRetries = Number.isFinite(options.maxRetries) && (options.maxRetries ?? 0) > 0\n ? options.maxRetries!\n : DEFAULT_OUTBOX_MAX_RETRIES;\n const now = options.now ?? new Date();\n const threshold = new Date(now.getTime() - thresholdMs).toISOString();\n\n const embeddingRows = sqliteAll<{ status: string; count: number }>(\n this.db,\n `SELECT status, COUNT(*) as count FROM embedding_outbox GROUP BY status`\n );\n const vectorRows = sqliteAll<{ status: string; count: number }>(\n this.db,\n `SELECT status, COUNT(*) as count FROM vector_outbox GROUP BY status`\n );\n\n const processingAgeMs = (value: unknown): number | null => {\n if (value === null || value === undefined) return null;\n const date = toDateFromSQLite(value);\n const time = date.getTime();\n if (!Number.isFinite(time)) return null;\n return Math.max(0, now.getTime() - time);\n };\n\n const fromRows = (\n rows: Array<{ status: string; count: number }>,\n stuckProcessing: number,\n oldestProcessingAgeMs: number | null,\n retryableFailed: number,\n quarantinedFailed: number\n ) => {\n const out = { pending: 0, processing: 0, failed: 0, retryableFailed, quarantinedFailed, total: 0, stuckProcessing, oldestProcessingAgeMs };\n for (const row of rows) {\n const key = row.status as 'pending' | 'processing' | 'failed' | 'done';\n if (key === 'pending' || key === 'processing' || key === 'failed') {\n out[key] += Number(row.count ?? 0);\n }\n out.total += Number(row.count ?? 0);\n }\n return out;\n };\n\n const embeddingStuck = sqliteGet<{ count: number }>(\n this.db,\n `SELECT COUNT(*) as count\n FROM embedding_outbox\n WHERE status = 'processing'\n AND datetime(COALESCE(processed_at, created_at)) < datetime(?)`,\n [threshold]\n );\n const embeddingOldest = sqliteGet<{ oldest: string | null }>(\n this.db,\n `SELECT MIN(datetime(COALESCE(processed_at, created_at))) as oldest\n FROM embedding_outbox\n WHERE status = 'processing'`\n );\n const embeddingRetryableFailed = sqliteGet<{ count: number }>(\n this.db,\n `SELECT COUNT(*) as count\n FROM embedding_outbox\n WHERE status = 'failed'\n AND retry_count < ?`,\n [maxRetries]\n );\n const embeddingQuarantinedFailed = sqliteGet<{ count: number }>(\n this.db,\n `SELECT COUNT(*) as count\n FROM embedding_outbox\n WHERE status = 'failed'\n AND retry_count >= ?`,\n [maxRetries]\n );\n\n const vectorStuck = sqliteGet<{ count: number }>(\n this.db,\n `SELECT COUNT(*) as count\n FROM vector_outbox\n WHERE status = 'processing'\n AND datetime(updated_at) < datetime(?)`,\n [threshold]\n );\n const vectorOldest = sqliteGet<{ oldest: string | null }>(\n this.db,\n `SELECT MIN(datetime(updated_at)) as oldest\n FROM vector_outbox\n WHERE status = 'processing'`\n );\n const vectorRetryableFailed = sqliteGet<{ count: number }>(\n this.db,\n `SELECT COUNT(*) as count\n FROM vector_outbox\n WHERE status = 'failed'\n AND retry_count < ?`,\n [maxRetries]\n );\n const vectorQuarantinedFailed = sqliteGet<{ count: number }>(\n this.db,\n `SELECT COUNT(*) as count\n FROM vector_outbox\n WHERE status = 'failed'\n AND retry_count >= ?`,\n [maxRetries]\n );\n\n return {\n embedding: fromRows(\n embeddingRows,\n Number(embeddingStuck?.count ?? 0),\n processingAgeMs(embeddingOldest?.oldest),\n Number(embeddingRetryableFailed?.count ?? 0),\n Number(embeddingQuarantinedFailed?.count ?? 0)\n ),\n vector: fromRows(\n vectorRows,\n Number(vectorStuck?.count ?? 0),\n processingAgeMs(vectorOldest?.oldest),\n Number(vectorRetryableFailed?.count ?? 0),\n Number(vectorQuarantinedFailed?.count ?? 0)\n )\n };\n }\n\n /**\n * Update memory level\n */\n async updateMemoryLevel(eventId: string, level: string): Promise<void> {\n await this.initialize();\n\n sqliteRun(\n this.db,\n `UPDATE memory_levels SET level = ?, promoted_at = datetime('now') WHERE event_id = ?`,\n [level, eventId]\n );\n }\n\n /**\n * Get memory level statistics\n */\n async getLevelStats(): Promise<Array<{ level: string; count: number }>> {\n await this.initialize();\n\n const rows = sqliteAll<{ level: string; count: number }>(\n this.db,\n `SELECT ml.level, COUNT(*) as count\n FROM memory_levels ml\n INNER JOIN events e ON e.id = ml.event_id\n WHERE ${notActiveQuarantinedSql('e.metadata')}\n GROUP BY ml.level`\n );\n\n return rows;\n }\n\n /**\n * Get events by memory level\n */\n async getEventsByLevel(level: string, options?: { limit?: number; offset?: number }): Promise<MemoryEvent[]> {\n await this.initialize();\n\n const limit = options?.limit || 50;\n const offset = options?.offset || 0;\n\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT e.* FROM events e\n INNER JOIN memory_levels ml ON e.id = ml.event_id\n WHERE ml.level = ?\n AND ${notActiveQuarantinedSql('e.metadata')}\n ORDER BY e.timestamp DESC\n LIMIT ? OFFSET ?`,\n [level, limit, offset]\n );\n\n return rows.map(row => this.rowToEvent(row));\n }\n\n /**\n * Return bounded graduation candidates in evidence order. Graduation only\n * benefits rows with durable access evidence, and ordering by creation time\n * would permanently starve an older memory in a busy project.\n */\n async getGraduationCandidates(level: string, options: { limit: number }): Promise<MemoryEvent[]> {\n await this.initialize();\n\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT e.* FROM events e\n INNER JOIN memory_levels ml ON e.id = ml.event_id\n WHERE ml.level = ?\n AND e.access_count > 0\n AND ${notActiveQuarantinedSql('e.metadata')}\n ORDER BY e.access_count DESC,\n COALESCE(e.last_accessed_at, e.timestamp) DESC,\n e.timestamp DESC\n LIMIT ?`,\n [level, options.limit]\n );\n\n return rows.map(row => this.rowToEvent(row));\n }\n\n /** Durable access evidence used to hydrate one-shot graduation workers. */\n async getGraduationMetrics(eventIds: string[]): Promise<Array<{\n eventId: string;\n accessCount: number;\n lastAccessed: Date;\n crossSessionRefs: number;\n confidence: number;\n }>> {\n await this.initialize();\n if (eventIds.length === 0) return [];\n const placeholders = eventIds.map(() => '?').join(', ');\n const rows = sqliteAll<{ id: string; access_count: number; last_accessed_at: string | null; timestamp: string }>(\n this.db,\n `SELECT id, access_count, last_accessed_at, timestamp\n FROM events\n WHERE id IN (${placeholders})\n AND access_count > 0\n AND ${notActiveQuarantinedSql('metadata')}`,\n eventIds\n );\n const sessionRows = sqliteAll<{ event_id: string; session_count: number }>(\n this.db,\n `SELECT event_id, COUNT(DISTINCT session_id) AS session_count\n FROM memory_helpfulness\n WHERE event_id IN (${placeholders})\n GROUP BY event_id`,\n eventIds\n );\n const sessionCounts = new Map(sessionRows.map((row) => [row.event_id, Number(row.session_count)]));\n return rows.map((row) => ({\n eventId: row.id,\n accessCount: Number(row.access_count),\n lastAccessed: toDateFromSQLite(row.last_accessed_at ?? row.timestamp),\n crossSessionRefs: Math.max(0, (sessionCounts.get(row.id) ?? 0) - 1),\n // Access is recorded only after the hook's strict injection filter.\n confidence: 1\n }));\n }\n\n /**\n * Persist an aggregate graduation attempt. The rows deliberately contain\n * no event content, project paths, prompt text, or underlying error text so\n * they can safely feed the productivity health report.\n */\n async recordGraduationRun(input: {\n startedAt: Date;\n finishedAt: Date;\n status: 'success' | 'not_eligible' | 'failed';\n evaluated: number;\n graduated: number;\n }): Promise<void> {\n await this.initialize();\n if (this.readOnly) return;\n\n const buildId = randomUUID();\n const status = input.status;\n const startedAt = input.startedAt.toISOString();\n const finishedAt = input.finishedAt.toISOString();\n const latencyMs = Math.max(0, input.finishedAt.getTime() - input.startedAt.getTime());\n\n sqliteRun(\n this.db,\n `INSERT INTO build_runs (\n build_id, started_at, finished_at, extractor_model, extractor_prompt_hash,\n embedder_model, embedding_version, idris_version, schema_version, status, error\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` ,\n [\n buildId,\n startedAt,\n finishedAt,\n 'graduation-rules',\n 'not-applicable',\n 'not-applicable',\n 'not-applicable',\n 'graduation-worker-v1',\n String(SQLITE_SCHEMA_VERSION),\n status,\n status === 'failed' ? 'graduation_failed' : null\n ]\n );\n\n sqliteRun(\n this.db,\n `INSERT INTO pipeline_metrics (id, ts, stage, latency_ms, success, error, session_id)\n VALUES (?, ?, ?, ?, ?, ?, ?)` ,\n [\n randomUUID(),\n finishedAt,\n 'graduation',\n latencyMs,\n status === 'failed' ? 0 : 1,\n status === 'failed' ? 'graduation_failed' : null,\n null\n ]\n );\n }\n\n /** Aggregate-only worker liveness for health/status surfaces. */\n async getDerivationLiveness(projectHash?: string): Promise<DerivationLiveness> {\n await this.initialize();\n\n const attempts = sqliteGet<{ count: number }>(\n this.db,\n `SELECT COUNT(*) AS count FROM build_runs WHERE idris_version = ?`,\n ['graduation-worker-v1']\n );\n const latest = sqliteGet<{ status: string; finished_at: string | null }>(\n this.db,\n `SELECT status, finished_at FROM build_runs\n WHERE idris_version = ?\n ORDER BY started_at DESC, build_id DESC\n LIMIT 1`,\n ['graduation-worker-v1']\n );\n const latestSuccessful = sqliteGet<{ finished_at: string | null }>(\n this.db,\n `SELECT finished_at FROM build_runs\n WHERE idris_version = ? AND status IN ('success', 'not_eligible')\n ORDER BY started_at DESC, build_id DESC\n LIMIT 1`,\n ['graduation-worker-v1']\n );\n const lastStatus = latest?.status === 'success' || latest?.status === 'not_eligible' || latest?.status === 'failed'\n ? latest.status\n : null;\n const graduatedEvents = sqliteGet<{ count: number }>(\n this.db,\n `SELECT COUNT(*) AS count\n FROM memory_levels ml\n INNER JOIN events e ON e.id = ml.event_id\n WHERE ml.level != 'L0' AND ${notActiveQuarantinedSql('e.metadata')}`\n );\n let curatedLessons = 0;\n try {\n const curated = sqliteGet<{ count: number }>(\n this.db,\n projectHash\n ? `SELECT COUNT(*) AS count FROM memory_lessons WHERE source_class = 'curated' AND project_hash = ?`\n : `SELECT COUNT(*) AS count FROM memory_lessons WHERE source_class = 'curated'`,\n projectHash ? [projectHash] : []\n );\n curatedLessons = Number(curated?.count ?? 0);\n } catch {\n // Older/read-only stores may predate the source_class migration.\n }\n\n return {\n graduation: {\n attempts: Number(attempts?.count ?? 0),\n lastAttemptAt: latest?.finished_at ?? null,\n lastSuccessAt: latestSuccessful?.finished_at ?? null,\n lastStatus,\n lastErrorCategory: lastStatus === 'failed' ? 'graduation_failed' : null\n },\n sources: {\n graduatedEvents: Number(graduatedEvents?.count ?? 0),\n curatedLessons\n }\n };\n }\n\n /**\n * Get memory level for a specific event\n */\n async getEventLevel(eventId: string): Promise<string | null> {\n await this.initialize();\n\n const row = sqliteGet<{ level: string }>(\n this.db,\n `SELECT level FROM memory_levels WHERE event_id = ?`,\n [eventId]\n );\n\n return row ? row.level : null;\n }\n\n /**\n * Get sync position for a target\n */\n async getSyncPosition(targetName: string): Promise<{ lastEventId: string | null; lastTimestamp: string | null }> {\n await this.initialize();\n\n const row = sqliteGet<{ last_event_id: string | null; last_timestamp: string | null }>(\n this.db,\n `SELECT last_event_id, last_timestamp FROM sync_positions WHERE target_name = ?`,\n [targetName]\n );\n\n return {\n lastEventId: row?.last_event_id ?? null,\n lastTimestamp: row?.last_timestamp ?? null\n };\n }\n\n /**\n * Update sync position for a target\n */\n async updateSyncPosition(targetName: string, lastEventId: string, lastTimestamp: string): Promise<void> {\n await this.initialize();\n\n sqliteRun(\n this.db,\n `INSERT OR REPLACE INTO sync_positions (target_name, last_event_id, last_timestamp, updated_at)\n VALUES (?, ?, ?, datetime('now'))`,\n [targetName, lastEventId, lastTimestamp]\n );\n }\n\n /**\n * Get config value for endless mode\n */\n async getEndlessConfig(key: string): Promise<unknown | null> {\n await this.initialize();\n\n const row = sqliteGet<{ value: string }>(\n this.db,\n `SELECT value FROM endless_config WHERE key = ?`,\n [key]\n );\n\n if (!row) return null;\n return JSON.parse(row.value);\n }\n\n /**\n * Set config value for endless mode\n */\n async setEndlessConfig(key: string, value: unknown): Promise<void> {\n await this.initialize();\n\n sqliteRun(\n this.db,\n `INSERT OR REPLACE INTO endless_config (key, value, updated_at)\n VALUES (?, ?, datetime('now'))`,\n [key, JSON.stringify(value)]\n );\n }\n\n /**\n * Increment access count for events\n */\n /**\n * Increment access counters for injected memories.\n *\n * Accepts typed references so a lesson id can no longer be used to update\n * `events.access_count` \u2014 that write matched no row and silently lost the\n * access signal for every lesson (specs R1). Bare strings stay supported for\n * callers that only ever hold event ids.\n */\n async incrementAccessCount(refs: Array<string | { kind: MemoryKind; id: string }>): Promise<void> {\n if (refs.length === 0 || this.readOnly) return;\n\n await this.initialize();\n\n // Each reference is counted against the table that actually owns it. A\n // lesson id never matched a row in `events`, so those writes were lost\n // entirely before the kind travelled with the reference (specs R1).\n const typed = refs\n .map((ref) => (typeof ref === 'string' ? { kind: 'event' as MemoryKind, id: ref } : ref))\n .filter((ref) => Boolean(ref?.id));\n const eventIds = Array.from(new Set(typed\n .filter((ref) => normalizeMemoryKind(ref.kind) === 'event')\n .map((ref) => ref.id)));\n const lessonIds = Array.from(new Set(typed\n .filter((ref) => normalizeMemoryKind(ref.kind) === 'lesson')\n .map((ref) => ref.id)));\n const currentTime = toSQLiteTimestamp(new Date());\n\n if (eventIds.length > 0) {\n sqliteRun(\n this.db,\n `UPDATE events\n SET access_count = access_count + 1,\n last_accessed_at = ?\n WHERE id IN (${eventIds.map(() => '?').join(',')})`,\n [currentTime, ...eventIds]\n );\n }\n if (lessonIds.length > 0 && this.hasTableColumn('memory_lessons', 'access_count')) {\n sqliteRun(\n this.db,\n `UPDATE memory_lessons\n SET access_count = access_count + 1,\n last_accessed_at = ?\n WHERE lesson_id IN (${lessonIds.map(() => '?').join(',')})`,\n [currentTime, ...lessonIds]\n );\n }\n }\n\n /**\n * Get most accessed memories (falls back to recent events if none accessed)\n */\n async getMostAccessed(limit: number = 10, options?: QuarantineReadOptions): Promise<MemoryEvent[]> {\n await this.initialize();\n\n // First try events with access_count > 0\n let rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM events\n WHERE access_count > 0\n AND ${maybeQuarantinePredicate(options)}\n ORDER BY access_count DESC, last_accessed_at DESC\n LIMIT ?`,\n [limit]\n );\n\n // Fallback: if no accessed events, show recent events\n if (rows.length === 0) {\n rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM events\n WHERE ${maybeQuarantinePredicate(options)}\n ORDER BY timestamp DESC\n LIMIT ?`,\n [limit]\n );\n }\n\n return rows.map(row => this.rowToEvent(row));\n }\n\n /**\n * Record a memory retrieval for helpfulness tracking\n */\n async recordRetrieval(\n eventId: string,\n sessionId: string,\n score: number,\n query: string,\n options?: {\n traceId?: string;\n source?: string;\n injectedContent?: string;\n /** Typed kind of the recorded memory. Defaults to `event`. */\n memoryKind?: MemoryKind;\n memoryProjectId?: string | null;\n /**\n * Delivery is not assumed. Selection records `formatted`; only a caller\n * with output evidence upgrades it via recordDeliveryOutcome (specs R3).\n */\n deliveryStatus?: DeliveryStatus;\n deliveryEvidence?: DeliveryEvidenceSource;\n } & RetrievalTelemetryContext\n ): Promise<void> {\n if (this.readOnly) return;\n await this.initialize();\n\n const id = randomUUID();\n // created_at needs millisecond precision: datetime('now') is second-only,\n // so the triggering prompt (stored moments earlier with an ISO ms\n // timestamp in the same second) would count as \"after\" the retrieval.\n sqliteRun(\n this.db,\n `INSERT INTO memory_helpfulness (\n id, event_id, session_id, retrieval_score, query_preview, trace_id, source,\n injected_content, memory_kind, delivery_status, delivery_evidence,\n presentation_mode, trigger_type, delivery_client, created_at, memory_project_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n [\n id, eventId, sessionId, score, query.slice(0, 200),\n options?.traceId || null,\n options?.source || 'user_prompt',\n options?.injectedContent ? options.injectedContent.slice(0, 2000) : null,\n normalizeMemoryKind(options?.memoryKind ?? 'event'),\n normalizeDeliveryStatus(options?.deliveryStatus ?? 'formatted'),\n normalizeDeliveryEvidence(options?.deliveryEvidence ?? 'context_formatted'),\n normalizeRetrievalPresentationMode(options?.presentationMode),\n normalizeRetrievalTriggerType(options?.triggerType),\n normalizeTelemetryClient(options?.deliveryClient),\n new Date().toISOString(),\n options?.memoryProjectId?.trim() || null\n ]\n );\n }\n\n /**\n * Record what actually happened to a delivery after selection (specs R3).\n *\n * Selection alone never sets delivered=true. A hook that successfully wrote\n * its context to stdout reports `emitted`; a write failure reports `failed`;\n * anything unobserved stays `unknown`. \"Emitted\" is not \"the model read it\" \u2014\n * only an explicit consumer acknowledgement is `acknowledged`.\n */\n async recordDeliveryOutcome(input: {\n traceId: string;\n status: DeliveryStatus;\n evidence: DeliveryEvidenceSource;\n deliveredAt?: Date;\n /** Omitted updates the whole trace; an empty list updates no items. */\n refs?: Array<{ kind: MemoryKind; id: string; projectId?: string | null }>;\n }): Promise<number> {\n if (input.refs?.length === 0) return 0;\n if (this.readOnly) return 0;\n await this.initialize();\n const traceId = input.traceId?.trim();\n if (!traceId) return 0;\n const status = normalizeDeliveryStatus(input.status);\n const evidence = normalizeDeliveryEvidence(input.evidence);\n const deliveredAt = (input.deliveredAt ?? new Date()).toISOString();\n const hasPositiveDelivery = deliveredFromStatus(status) === true;\n\n // A ref filter matches on kind *and* id. Filtering by id alone would move\n // the delivery status of an event that merely shares an id with the lesson\n // the caller actually delivered (finding 3).\n const hasHelpfulnessKind = this.hasTableColumn('memory_helpfulness', 'memory_kind');\n const params: unknown[] = [status, evidence, hasPositiveDelivery ? 1 : 0, deliveredAt, traceId];\n let refFilter = '';\n if (input.refs && input.refs.length > 0) {\n if (hasHelpfulnessKind) {\n refFilter = ` AND (${input.refs.map(() => `(event_id = ? AND COALESCE(memory_kind, 'event') = ? AND memory_project_id IS ?)`).join(' OR ')})`;\n for (const ref of input.refs) params.push(ref.id, normalizeMemoryKind(ref.kind), ref.projectId ?? null);\n } else {\n refFilter = ` AND event_id IN (${input.refs.map(() => '?').join(',')})`;\n params.push(...input.refs.map((ref) => ref.id));\n }\n }\n // Keep any already-evaluated observation consistent with the new evidence\n // rather than leaving a stale assumed value behind. The same ref scope\n // applies: updating every row of the trace would rewrite the delivery state\n // of items this call says nothing about.\n const delivered = deliveredFromStatus(status);\n const observationParams: unknown[] = [\n status, evidence, delivered === null ? null : delivered ? 1 : 0,\n traceId, CURRENT_USEFULNESS_EVALUATOR_VERSION\n ];\n let observationFilter = '';\n if (input.refs && input.refs.length > 0) {\n observationFilter = ` AND event_id IN (${input.refs.map(() => '?').join(',')})`;\n observationParams.push(...input.refs.map((ref) => usefulnessRowKey(normalizeMemoryKind(ref.kind), ref.id, ref.projectId)));\n }\n // Commit both representations together so a failed observation update\n // cannot leave navigation and usefulness reporting different delivery states.\n return this.runInImmediateTransaction(() => {\n if (retrievalRollout().usefulnessV3Write) {\n const deliveredValue = delivered === null ? null : delivered ? 1 : 0;\n // An evaluation based on different delivery evidence is stale, even\n // after its old window closed. Queue it for normal session evaluation\n // and clear derived claims until that evaluation has run.\n sqliteRun(this.db,\n `UPDATE memory_helpfulness SET measured_at = NULL\n WHERE trace_id = ?${refFilter} AND EXISTS (\n SELECT 1 FROM memory_usefulness_observations_v2 o\n WHERE o.trace_id = memory_helpfulness.trace_id\n AND o.event_id = ${usefulnessRowKeySql('memory_helpfulness')}\n AND o.evaluator_version = ? AND o.delivered IS NOT ?\n )`,\n [traceId, ...params.slice(5), CURRENT_USEFULNESS_EVALUATOR_VERSION, deliveredValue]);\n sqliteRun(this.db,\n `UPDATE memory_usefulness_observations_v2\n SET adoption = ?, task_outcome = 'unknown', content_overlap_score = NULL,\n reask_outcome = 'unknown', confidence = 0, evaluated_at = NULL, evaluation_cutoff = NULL\n WHERE trace_id = ? AND evaluator_version = ?${observationFilter} AND delivered IS NOT ?`,\n [delivered === false ? 'not_observed' : 'unknown', traceId,\n CURRENT_USEFULNESS_EVALUATOR_VERSION, ...observationParams.slice(5), deliveredValue]);\n }\n const result = sqliteRun(\n this.db,\n `UPDATE memory_helpfulness\n SET delivery_status = ?, delivery_evidence = ?,\n delivered_at = CASE WHEN ? = 1 THEN COALESCE(delivered_at, ?) ELSE delivered_at END\n WHERE trace_id = ?${refFilter}`,\n params\n );\n if (retrievalRollout().usefulnessV3Write) {\n sqliteRun(\n this.db,\n `UPDATE memory_usefulness_observations_v2\n SET delivery_status = ?, delivery_evidence = ?, delivered = ?\n WHERE trace_id = ? AND evaluator_version = ?${observationFilter}`,\n observationParams\n );\n }\n return Number(result?.changes ?? 0);\n });\n }\n\n /**\n * Get session IDs that have unevaluated retrievals (measured_at IS NULL).\n * Excludes the current session. Used to backfill sessions that ended without Stop hook.\n */\n async getUnevaluatedSessions(currentSessionId: string, limit = 5): Promise<string[]> {\n await this.initialize();\n const rows = sqliteAll<{ session_id: string }>(\n this.db,\n `SELECT DISTINCT session_id FROM memory_helpfulness\n WHERE measured_at IS NULL AND session_id != ?\n ORDER BY created_at DESC LIMIT ?`,\n [currentSessionId, limit]\n );\n return rows.map((r) => r.session_id);\n }\n\n /**\n * Evaluate helpfulness for all retrievals in a session\n * Called at session end - uses behavioral signals to compute score\n */\n async evaluateSessionHelpfulness(sessionId: string): Promise<void> {\n if (this.readOnly) return;\n await this.initialize();\n\n // Get all retrieval records for this session\n const retrievals = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM memory_helpfulness WHERE session_id = ? AND measured_at IS NULL`,\n [sessionId]\n );\n\n if (retrievals.length === 0) return;\n await this.evaluateRetrievalRows(sessionId, retrievals);\n }\n\n /**\n * Re-evaluate deliveries whose observation window had not closed yet when the\n * session was first evaluated (specs R3).\n *\n * A session that ends immediately after an injection is evaluated with only\n * the responses that existed at that moment; the 30-minute adoption window is\n * still open. This bounded pass revisits exactly those rows once the window\n * has actually elapsed, so a late response is not permanently recorded as\n * \"not observed\". It never widens the window and never re-scores a delivery\n * whose window was already complete.\n */\n async reevaluateBoundedUsefulness(options: {\n limit?: number;\n now?: Date;\n windowMs?: number;\n } = {}): Promise<{ sessionsReevaluated: number; rowsReevaluated: number; windowMs: number; cutoff: string }> {\n const windowMs = options.windowMs ?? USEFULNESS_V2_EVALUATION_WINDOW_MS;\n const now = options.now ?? new Date();\n const summary = { sessionsReevaluated: 0, rowsReevaluated: 0, windowMs, cutoff: now.toISOString() };\n if (this.readOnly) return summary;\n await this.initialize();\n if (!this.hasTableColumn('memory_usefulness_observations_v2', 'evaluation_cutoff')) return summary;\n\n const limit = Math.min(Math.max(options.limit ?? 200, 1), 5_000);\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT mh.* ${this.boundedReevaluationFromWhereSql()}\n ORDER BY mh.created_at ASC\n LIMIT ?`,\n [CURRENT_USEFULNESS_EVALUATOR_VERSION, now.toISOString(), limit]\n );\n if (rows.length === 0) return summary;\n\n const bySession = new Map<string, Record<string, unknown>[]>();\n for (const row of rows) {\n const sessionId = String(row.session_id || '');\n if (!sessionId) continue;\n const list = bySession.get(sessionId) ?? [];\n list.push(row);\n bySession.set(sessionId, list);\n }\n for (const [sessionId, sessionRows] of bySession) {\n await this.evaluateRetrievalRows(sessionId, sessionRows, { evaluatedAt: now });\n summary.sessionsReevaluated += 1;\n summary.rowsReevaluated += sessionRows.length;\n }\n return summary;\n }\n\n /**\n * Shared FROM/WHERE for the bounded re-evaluation pass: rows evaluated before\n * their adoption window closed, whose window has since elapsed.\n *\n * The window opens when the memory was actually delivered, not when it was\n * selected: a delivery recorded late (or never emitted) must not have its\n * adoption window measured from the selection instant (specs R3, finding 4).\n * Parameters, in order: evaluator version, \"now\".\n */\n private boundedReevaluationFromWhereSql(): string {\n const anchorSql = this.hasTableColumn('memory_helpfulness', 'delivered_at')\n ? `COALESCE(mh.delivered_at, mh.created_at)`\n : `mh.created_at`;\n return `FROM memory_helpfulness mh\n JOIN memory_usefulness_observations_v2 o\n ON o.trace_id = COALESCE(mh.trace_id, 'legacy:' || mh.id)\n AND o.event_id = ${usefulnessRowKeySql('mh')}\n AND o.evaluator_version = ?\n WHERE mh.measured_at IS NOT NULL\n AND o.evaluation_cutoff IS NOT NULL\n AND o.evaluation_window_ms IS NOT NULL\n -- window was still open at evaluation time ... (the 1ms slack keeps\n -- julianday's floating-point rounding from re-queuing a row whose\n -- cutoff already sits exactly on the window end)\n AND julianday(o.evaluation_cutoff) < julianday(${anchorSql}) + ((o.evaluation_window_ms - 1) / 86400000.0)\n -- ... and it has since elapsed\n AND julianday(?) >= julianday(${anchorSql}) + (o.evaluation_window_ms / 86400000.0)`;\n }\n\n /**\n * How many rows the bounded pass would revisit right now. Read-only, so a\n * scheduled job can preview its work without writing anything (specs R3).\n */\n async countPendingBoundedUsefulness(options: { now?: Date } = {}): Promise<{ pendingRows: number; cutoff: string }> {\n await this.initialize();\n const now = options.now ?? new Date();\n const cutoff = now.toISOString();\n if (!this.hasTable('memory_usefulness_observations_v2')\n || !this.hasTableColumn('memory_usefulness_observations_v2', 'evaluation_cutoff')) {\n return { pendingRows: 0, cutoff };\n }\n const row = sqliteGet<{ pending: number }>(\n this.db,\n `SELECT COUNT(*) AS pending ${this.boundedReevaluationFromWhereSql()}`,\n [CURRENT_USEFULNESS_EVALUATOR_VERSION, cutoff]\n );\n return { pendingRows: Number(row?.pending ?? 0), cutoff };\n }\n\n private async evaluateRetrievalRows(\n sessionId: string,\n retrievals: Record<string, unknown>[],\n options: { evaluatedAt?: Date } = {}\n ): Promise<void> {\n // Get session events to analyze behavior after retrieval\n const sessionEvents = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM events WHERE session_id = ? ORDER BY timestamp ASC`,\n [sessionId]\n );\n\n const promptEvents = sessionEvents.filter((e: any) => e.event_type === 'user_prompt');\n const toolEvents = sessionEvents.filter((e: any) => e.event_type === 'tool_observation');\n const responseEvents = sessionEvents.filter((e: any) => e.event_type === 'agent_response');\n\n // Look up the injected memories' content once so each retrieval can be\n // checked for content grounding against the responses that followed it.\n // Only event-kind rows can be hydrated from the events table; a lesson row\n // relies on its stored injected excerpt (specs R1).\n const retrievedEventIds = Array.from(new Set(retrievals\n .filter((r) => normalizeMemoryKind(r.memory_kind ?? 'event') === 'event')\n .map((r) => r.event_id as string)\n .filter(Boolean)));\n const memoryContentById = new Map<string, string>();\n for (let i = 0; i < retrievedEventIds.length; i += 100) {\n const chunk = retrievedEventIds.slice(i, i + 100);\n const rows = sqliteAll<{ id: string; content: string }>(\n this.db,\n `SELECT id, content FROM events WHERE id IN (${chunk.map(() => '?').join(',')})`,\n chunk\n );\n for (const row of rows) memoryContentById.set(row.id, row.content);\n }\n\n // Events store ISO timestamps while memory_helpfulness.created_at uses\n // SQLite datetime('now') (\"YYYY-MM-DD HH:MM:SS\", UTC). Comparing the raw\n // strings marks any same-day event as \"after\", so compare epoch millis.\n const toEpochMs = (value: unknown): number => {\n const raw = String(value || '');\n const iso = raw.includes('T') ? raw : `${raw.replace(' ', 'T')}Z`;\n const ms = new Date(iso).getTime();\n return Number.isFinite(ms) ? ms : 0;\n };\n\n for (const retrieval of retrievals) {\n // Adoption is measured from the moment the memory was actually delivered.\n // Before that instant nothing could have used it, and a delivery that was\n // never emitted has no anchor at all (specs R3, finding 4).\n const selectedAtMs = toEpochMs(retrieval.created_at);\n const deliveredAtMs = retrieval.delivered_at ? toEpochMs(retrieval.delivered_at) : 0;\n const retrievalTimeMs = deliveredAtMs > 0 ? deliveredAtMs : selectedAtMs;\n\n // 1. Session continued after retrieval?\n const eventsAfter = sessionEvents.filter((e: any) => toEpochMs(e.timestamp) > retrievalTimeMs);\n const sessionContinued = eventsAfter.length > 0 ? 1 : 0;\n\n // 2. How many prompts came after?\n const promptsAfter = promptEvents.filter((e: any) => toEpochMs(e.timestamp) > retrievalTimeMs);\n const promptCountAfter = promptsAfter.length;\n const toolOutcomesAfter = toolEvents\n .filter((e: any) => toEpochMs(e.timestamp) > retrievalTimeMs)\n .map((event) => parseToolOutcome(event.content));\n const measuredToolOutcomes = toolOutcomesAfter.filter((outcome) => outcome !== 'unknown');\n const toolSuccessCount = measuredToolOutcomes.filter((outcome) => outcome === 'success').length;\n const toolTotalCount = measuredToolOutcomes.length;\n const toolSuccessRatio = toolTotalCount > 0 ? toolSuccessCount / toolTotalCount : 0.5;\n\n // 3. Was a similar query asked again? (simple word overlap check)\n const queryWords = new Set((retrieval.query_preview as string || '').toLowerCase().split(/\\s+/).filter(w => w.length > 2));\n let wasReasked = 0;\n for (const p of promptsAfter) {\n const pWords = new Set((p.content as string).toLowerCase().split(/\\s+/).filter((w: string) => w.length > 2));\n let overlap = 0;\n for (const w of queryWords) {\n if (pWords.has(w)) overlap++;\n }\n if (queryWords.size > 0 && overlap / queryWords.size > 0.5) {\n wasReasked = 1;\n break;\n }\n }\n\n // 4. Content grounding: did the assistant responses after this\n // retrieval actually reuse the memory's content? This is the most\n // direct usefulness signal we have \u2014 the behavioral signals below\n // only approximate it.\n const responsesAfter = responseEvents\n .filter((e: any) => toEpochMs(e.timestamp) > retrievalTimeMs)\n .map((e: any) => ({ id: e.id as string, content: e.content as string, timestamp: e.timestamp }));\n // Grounding must be checked against what was actually injected into the\n // prompt (hooks truncate memories), not the full stored event \u2014 otherwise\n // facts the model never saw would count as \"used\". Full content is the\n // fallback for legacy rows recorded before the snapshot column existed.\n const memoryContent = (retrieval.injected_content as string)\n || memoryContentById.get(retrieval.event_id as string)\n || '';\n const presentationMode = normalizeRetrievalPresentationMode(retrieval.presentation_mode);\n let contentOverlapScore: number | null = null;\n let evidenceMatches: EvidenceMatch[] = [];\n if (presentationMode !== 'reference' && responsesAfter.length > 0 && memoryContent) {\n const evidence = computeMemoryUsageEvidence(memoryContent, responsesAfter);\n contentOverlapScore = evidence.contentOverlapScore;\n evidenceMatches = evidence.matches;\n }\n\n const v2WindowEndMs = retrievalTimeMs + USEFULNESS_V2_EVALUATION_WINDOW_MS;\n const evaluatedAt = options.evaluatedAt ?? new Date();\n const evaluationCutoffMs = Math.min(evaluatedAt.getTime(), v2WindowEndMs);\n const v2PromptsAfter = promptsAfter.filter((event) => toEpochMs(event.timestamp) <= evaluationCutoffMs);\n const v2ToolOutcomesAfter = toolEvents\n .filter((event) => {\n const eventTimeMs = toEpochMs(event.timestamp);\n return eventTimeMs > retrievalTimeMs && eventTimeMs <= evaluationCutoffMs;\n })\n .map((event) => parseToolOutcome(event.content));\n const v2ResponsesAfter = responsesAfter.filter((event) => toEpochMs(event.timestamp) <= evaluationCutoffMs);\n const v2Evidence = presentationMode !== 'reference' && v2ResponsesAfter.length > 0 && memoryContent\n ? computeMemoryUsageEvidence(memoryContent, v2ResponsesAfter)\n : null;\n const v2ContentOverlapScore = v2Evidence?.contentOverlapScore ?? null;\n\n // Kind-aware: an open of lesson X must not count as an open of the event\n // that happens to share its id (specs R1). A row whose own kind is\n // `unknown` (written before the typed columns existed) cannot narrow\n // anything, so it matches on id alone rather than excluding itself.\n const retrievalKind = normalizeMemoryKind(retrieval.memory_kind);\n const navigationKindClause = retrievalKind !== 'unknown'\n && this.hasTableColumn('retrieval_navigation_events', 'memory_kind')\n ? ` AND COALESCE(memory_kind, 'event') = ? AND memory_project_id IS ?`\n : '';\n const referenceOpened = presentationMode === 'reference' && Boolean(retrieval.trace_id) && Boolean(\n sqliteGet<{ opened: number }>(\n this.db,\n `SELECT 1 AS opened\n FROM retrieval_navigation_events\n WHERE trace_id = ? AND target_event_id = ? AND attribution_outcome = 'attributed'${navigationKindClause}\n AND julianday(first_opened_at) >= julianday(?)\n AND julianday(first_opened_at) <= julianday(?)\n LIMIT 1`,\n [...(navigationKindClause\n ? [retrieval.trace_id, retrieval.event_id, retrievalKind, retrieval.memory_project_id ?? null]\n : [retrieval.trace_id, retrieval.event_id]),\n new Date(retrievalTimeMs).toISOString(), new Date(evaluationCutoffMs).toISOString()]\n )\n );\n // Distinguish \"the reference was not opened\" from \"we cannot attribute\n // opens at all\": without a trace link no navigation can ever be\n // attributed to this delivery, so absence proves nothing (specs R3).\n const referenceAttributable = presentationMode === 'reference' && Boolean(retrieval.trace_id);\n\n // Calculate helpfulness score\n // Weights tuned for shopping-assistant-like corpora where sessions\n // continue on the same topic (was_reasked was over-penalising normal conversation flow)\n const retrievalScore = retrieval.retrieval_score as number || 0;\n // More prompts after retrieval = memory was actually useful to the conversation\n const promptNorm = Math.min(promptCountAfter / 2, 1.0);\n // When content grounding is measurable it dominates the score; the\n // legacy behavioral-only formula remains the fallback (e.g. session\n // ended right after retrieval, so no responses followed).\n // A reference index is navigation, not evidence. Absence of copied text\n // must not make it unhelpful: a deterministic open is positive and an\n // unopened reference remains neutral. Citation use is not inferred.\n const helpfulnessScore = presentationMode === 'reference'\n ? (referenceOpened ? 1 : 0.5)\n : contentOverlapScore !== null\n ? (\n 0.45 * contentOverlapScore +\n 0.20 * Math.min(retrievalScore, 1.0) +\n 0.15 * promptNorm +\n 0.10 * toolSuccessRatio +\n 0.10 * (sessionContinued ? 1.0 : 0.0)\n )\n : (\n 0.40 * Math.min(retrievalScore, 1.0) +\n 0.30 * promptNorm +\n 0.20 * toolSuccessRatio +\n 0.10 * (sessionContinued ? 1.0 : 0.0)\n );\n\n sqliteRun(\n this.db,\n `UPDATE memory_helpfulness\n SET session_continued = ?, prompt_count_after = ?,\n tool_success_count = ?, tool_total_count = ?,\n was_reasked = ?, helpfulness_score = ?,\n content_overlap_score = ?, evidence_json = ?,\n measured_at = datetime('now')\n WHERE id = ?`,\n [sessionContinued, promptCountAfter, toolSuccessCount, toolTotalCount,\n wasReasked, helpfulnessScore,\n contentOverlapScore,\n evidenceMatches.length > 0 ? JSON.stringify(evidenceMatches) : null,\n retrieval.id]\n );\n\n const triggerType = normalizeRetrievalTriggerType(retrieval.trigger_type ?? retrieval.source);\n const adoption = presentationMode === 'reference'\n ? (referenceOpened ? 'navigated' : referenceAttributable ? 'not_observed' : 'unknown')\n : presentationMode === 'evidence'\n ? (v2ContentOverlapScore === null ? 'unknown' : v2ContentOverlapScore >= 0.3 ? 'grounded' : 'not_observed')\n : 'unknown';\n // Delivery comes from recorded evidence only. A selection that was\n // formatted but never observed leaving the process stays unknown.\n const deliveryStatus = normalizeDeliveryStatus(retrieval.delivery_status);\n const deliveryEvidence = normalizeDeliveryEvidence(retrieval.delivery_evidence);\n const delivered = deliveredFromStatus(deliveryStatus);\n // Adoption requires delivery evidence. Text overlap in a later response\n // cannot be attributed to a memory that was only formatted, or whose\n // write failed: the model never saw it. Those stay `unknown` rather than\n // becoming grounded (or a \"task success\") on an assumption (specs R3,\n // finding 11). A `failed` delivery is a real observation of non-adoption.\n const evidencedAdoption: UsefulnessAdoption = delivered === true\n ? adoption\n : delivered === false\n ? 'not_observed'\n : 'unknown';\n await this.upsertUsefulnessObservationV2(buildUsefulnessObservationV2({\n traceId: String(retrieval.trace_id || `legacy:${retrieval.id}`),\n eventId: String(retrieval.event_id),\n memoryKind: normalizeMemoryKind(retrieval.memory_kind),\n memoryProjectId: (retrieval.memory_project_id as string | null | undefined) ?? null,\n presentationMode,\n triggerType,\n delivered,\n deliveryStatus,\n deliveryEvidence,\n adoption: evidencedAdoption,\n contentOverlapScore: presentationMode === 'evidence' ? v2ContentOverlapScore : null,\n toolOutcomes: v2ToolOutcomesAfter,\n reaskOutcome: classifyReaskOutcome(\n retrieval.query_preview,\n v2PromptsAfter.map((event) => event.content)\n ),\n evaluatedAt: evaluatedAt.toISOString(),\n evaluationWindowMs: USEFULNESS_V2_EVALUATION_WINDOW_MS,\n // The cutoff is what this evaluation could actually see. When it falls\n // short of the window end, reevaluateBoundedUsefulness revisits the row.\n evaluationCutoff: new Date(Math.min(evaluatedAt.getTime(), v2WindowEndMs)).toISOString()\n }));\n }\n }\n\n async upsertUsefulnessObservationV2(input: MemoryUsefulnessObservationV2): Promise<void> {\n if (this.readOnly) return;\n if (input.evaluatorVersion === CURRENT_USEFULNESS_EVALUATOR_VERSION && !retrievalRollout().usefulnessV3Write) return;\n await this.initialize();\n const delivered = input.delivered === null ? null : input.delivered ? 1 : 0;\n const overlapValue = input.contentOverlapScore === null ? null : Number(input.contentOverlapScore);\n const confidenceValue = Number(input.confidence);\n if ((overlapValue !== null && !Number.isFinite(overlapValue)) || !Number.isFinite(confidenceValue)) {\n throw new Error('v2 usefulness observation scores must be finite numbers');\n }\n const overlap = overlapValue === null ? null : Math.max(0, Math.min(1, overlapValue));\n const confidence = Math.max(0, Math.min(1, confidenceValue));\n if (!input.traceId.trim() || !input.eventId.trim() || !input.evaluatorVersion.trim()) {\n throw new Error('v2 usefulness observation requires trace, event, and evaluator version');\n }\n const hasTypedColumns = this.hasTableColumn('memory_usefulness_observations_v2', 'memory_kind');\n const hasMemoryIdColumn = this.hasTableColumn('memory_usefulness_observations_v2', 'memory_id');\n const memoryKind = normalizeMemoryKind(input.memoryKind ?? 'event');\n // Non-event memories are stored under a kind-qualified key. The primary key\n // is (trace_id, event_id, observation_kind, evaluator_version), so a lesson\n // and an event that share an id would otherwise overwrite one another \u2014\n // and an event-table join would claim the lesson row as a dangling event.\n const rowKey = hasTypedColumns && input.evaluatorVersion !== 'v2'\n ? usefulnessRowKey(memoryKind, input.eventId.trim(), input.memoryProjectId)\n : input.eventId.trim();\n const typedColumns = hasTypedColumns\n ? ', memory_kind, delivery_status, delivery_evidence, evaluation_window_ms, evaluation_cutoff'\n + (hasMemoryIdColumn ? ', memory_id, memory_project_id' : '')\n : '';\n const typedPlaceholders = hasTypedColumns\n ? ', ?, ?, ?, ?, ?' + (hasMemoryIdColumn ? ', ?, ?' : '')\n : '';\n const typedUpdates = hasTypedColumns\n ? `,\n memory_kind = excluded.memory_kind,\n delivery_status = excluded.delivery_status,\n delivery_evidence = excluded.delivery_evidence,\n evaluation_window_ms = excluded.evaluation_window_ms,\n evaluation_cutoff = excluded.evaluation_cutoff`\n + (hasMemoryIdColumn\n ? `,\n memory_id = excluded.memory_id,\n memory_project_id = excluded.memory_project_id`\n : '')\n : '';\n const typedValues = hasTypedColumns\n ? [\n memoryKind,\n normalizeDeliveryStatus(input.deliveryStatus),\n normalizeDeliveryEvidence(input.deliveryEvidence),\n typeof input.evaluationWindowMs === 'number' && Number.isFinite(input.evaluationWindowMs)\n ? Math.max(0, Math.floor(input.evaluationWindowMs))\n : null,\n input.evaluationCutoff ?? null,\n ...(hasMemoryIdColumn ? [input.eventId.trim(), input.memoryProjectId ?? null] : [])\n ]\n : [];\n sqliteRun(\n this.db,\n `INSERT INTO memory_usefulness_observations_v2 (\n trace_id, event_id, observation_kind, evaluator_version,\n presentation_mode, trigger_type, selected, delivered, adoption,\n content_overlap_score, task_outcome, reask_outcome, explicit_feedback,\n confidence, evaluated_at${typedColumns}\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?${typedPlaceholders})\n ON CONFLICT(trace_id, event_id, observation_kind, evaluator_version) DO UPDATE SET\n presentation_mode = excluded.presentation_mode,\n trigger_type = excluded.trigger_type,\n selected = excluded.selected,\n delivered = excluded.delivered,\n adoption = excluded.adoption,\n content_overlap_score = excluded.content_overlap_score,\n task_outcome = excluded.task_outcome,\n reask_outcome = excluded.reask_outcome,\n explicit_feedback = excluded.explicit_feedback,\n confidence = excluded.confidence,\n evaluated_at = excluded.evaluated_at${typedUpdates}`,\n [\n input.traceId.trim(), rowKey, 'outcome', input.evaluatorVersion.trim(),\n normalizeRetrievalPresentationMode(input.presentationMode),\n normalizeRetrievalTriggerType(input.triggerType),\n input.selected ? 1 : 0, delivered, input.adoption, overlap,\n input.taskOutcome, input.reaskOutcome, input.explicitFeedback, confidence,\n input.evaluatedAt, ...typedValues\n ]\n );\n }\n\n async getUsefulnessAggregateV2(options: {\n since?: Date;\n until?: Date;\n minimumSample?: number;\n evaluatorVersion?: string;\n includeSessionStart?: boolean;\n } = {}): Promise<UsefulnessAggregateV2> {\n await this.initialize();\n const minimumSample = normalizeUsefulnessMinimumSample(options.minimumSample);\n // Default to the delivery-evidence evaluator. v2 rows assumed delivery, so\n // they are readable on request but never averaged in by default (specs R3).\n const evaluatorVersion = options.evaluatorVersion?.trim() || CURRENT_USEFULNESS_EVALUATOR_VERSION;\n const base = emptyUsefulnessAggregateV2({\n minimumSample,\n evaluatorVersion,\n includeSessionStart: options.includeSessionStart,\n since: options.since,\n until: options.until,\n evaluationWindowMs: USEFULNESS_V2_EVALUATION_WINDOW_MS\n });\n if (!this.hasTable('memory_usefulness_observations_v2')) return base;\n const clauses = ['o.evaluator_version = ?'];\n const params: unknown[] = [evaluatorVersion];\n if (!options.includeSessionStart) clauses.push(`o.trigger_type != 'session_start'`);\n if (options.since) {\n clauses.push('datetime(COALESCE(t.created_at, o.evaluated_at)) >= datetime(?)');\n params.push(options.since.toISOString());\n }\n if (options.until) {\n clauses.push('datetime(COALESCE(t.created_at, o.evaluated_at)) < datetime(?)');\n params.push(options.until.toISOString());\n }\n const hasTypedColumns = this.hasTableColumn('memory_usefulness_observations_v2', 'memory_kind');\n const typedSelect = hasTypedColumns ? ', o.memory_kind, o.delivery_status' : '';\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT o.selected, o.delivered, o.presentation_mode, o.trigger_type, o.adoption, o.task_outcome,\n o.reask_outcome, o.explicit_feedback${typedSelect}\n FROM memory_usefulness_observations_v2 o\n LEFT JOIN retrieval_traces t ON t.trace_id = o.trace_id\n WHERE ${clauses.join(' AND ')}`,\n params\n );\n // Rows written by an evaluator generation that assumed delivery. Counted\n // and shown, never merged into this aggregate's rates.\n const legacyAssumedDeliveryRows = LEGACY_ASSUMED_DELIVERY_EVALUATOR_VERSIONS.includes(\n evaluatorVersion as typeof LEGACY_ASSUMED_DELIVERY_EVALUATOR_VERSIONS[number]\n )\n ? rows.length\n : Number(sqliteGet<{ count: number }>(\n this.db,\n `SELECT COUNT(*) AS count FROM memory_usefulness_observations_v2 o\n LEFT JOIN retrieval_traces t ON t.trace_id = o.trace_id\n WHERE ${clauses.join(' AND ')}`,\n ['v2', ...params.slice(1)]\n )?.count ?? 0);\n const traceClauses: string[] = [];\n const traceParams: unknown[] = [];\n if (!options.includeSessionStart) traceClauses.push(`trigger_type != 'session_start'`);\n if (options.since) {\n traceClauses.push('datetime(created_at) >= datetime(?)');\n traceParams.push(options.since.toISOString());\n }\n if (options.until) {\n traceClauses.push('datetime(created_at) < datetime(?)');\n traceParams.push(options.until.toISOString());\n }\n const traceTotals = this.hasTable('retrieval_traces')\n ? sqliteGet<{ eligible: number; selected: number }>(\n this.db,\n `SELECT COALESCE(SUM(candidate_count), 0) AS eligible,\n COALESCE(SUM(selected_count), 0) AS selected\n FROM retrieval_traces${traceClauses.length > 0 ? ` WHERE ${traceClauses.join(' AND ')}` : ''}`,\n traceParams\n )\n : undefined;\n const observedSelections = rows.filter((row) => Number(row.selected) === 1).length;\n const eligible = Number(traceTotals?.eligible ?? 0) > 0 ? Number(traceTotals?.eligible) : rows.length;\n const selected = Number(traceTotals?.eligible ?? 0) > 0 ? Number(traceTotals?.selected) : observedSelections;\n if (rows.length === 0) {\n return {\n ...base,\n legacyAssumedDeliveryRows,\n eligible,\n selected,\n rates: {\n ...base.rates,\n selectionYield: {\n numerator: selected,\n denominator: eligible,\n unknown: 0,\n value: eligible > 0 ? Math.round((selected / eligible) * 10_000) / 10_000 : null\n }\n }\n };\n }\n\n const observationCount = rows.length;\n const delivered = rows.filter((row) => Number(row.delivered) === 1).length;\n const deliveryUnknown = rows.filter((row) => row.delivered === null || row.delivered === undefined).length;\n // The headline grounding metric is deliberately narrow: evidence-mode\n // injections triggered by a user prompt. session_start has a different\n // delivery shape, and explicit_search / context_pack are tool calls whose\n // \"adoption\" means something else \u2014 averaging them together produced the\n // 9.1% figure the spec rejects in favour of 18.8% (specs \u00A73.4, R3).\n const allEvidenceRows = rows.filter((row) => row.presentation_mode === 'evidence');\n const evidenceRows = allEvidenceRows.filter((row) => row.trigger_type === 'user_prompt');\n const isEvaluatedAdoption = (row: Record<string, unknown>) =>\n row.adoption === 'grounded' || row.adoption === 'not_observed';\n const evidenceEvaluated = evidenceRows.filter(isEvaluatedAdoption).length;\n const evidenceGrounded = evidenceRows.filter((row) => row.adoption === 'grounded').length;\n const evidenceAllTriggersEvaluated = allEvidenceRows.filter(isEvaluatedAdoption).length;\n const evidenceAllTriggersGrounded = allEvidenceRows.filter((row) => row.adoption === 'grounded').length;\n const references = rows.filter((row) => row.presentation_mode === 'reference');\n const referencesNavigated = references.filter((row) => row.adoption === 'navigated').length;\n const referenceUnknown = references.filter((row) => row.adoption === 'unknown').length;\n const referencesEvaluated = references.length - referenceUnknown;\n const taskEvaluated = rows.filter((row) => row.task_outcome !== 'unknown').length;\n const taskSuccessful = rows.filter((row) => row.task_outcome === 'success').length;\n const explicitPositive = rows.filter((row) => row.explicit_feedback === 'positive').length;\n const explicitNegative = rows.filter((row) => row.explicit_feedback === 'negative').length;\n const feedbackEvaluated = explicitPositive + explicitNegative;\n const unknownByDimension = {\n delivery: deliveryUnknown,\n adoption: rows.filter((row) => row.adoption === 'unknown').length,\n taskOutcome: rows.filter((row) => row.task_outcome === 'unknown').length,\n reaskOutcome: rows.filter((row) => row.reask_outcome === 'unknown').length,\n explicitFeedback: observationCount - feedbackEvaluated\n };\n const rate = (numerator: number, denominator: number, unknown: number): UsefulnessRateV2 => ({\n numerator,\n denominator,\n unknown,\n value: denominator > 0 ? Math.round((numerator / denominator) * 10_000) / 10_000 : null\n });\n const deliveryStatusCounts = { ...base.deliveryStatusCounts };\n const selectedByKind = { ...base.selectedByKind };\n for (const row of rows) {\n deliveryStatusCounts[normalizeDeliveryStatus(row.delivery_status)] += 1;\n if (Number(row.selected) === 1) selectedByKind[normalizeMemoryKind(row.memory_kind ?? 'event')] += 1;\n }\n return {\n ...base,\n deliveryStatusCounts,\n selectedByKind,\n legacyAssumedDeliveryRows,\n eligible,\n selected,\n delivered,\n evidenceEvaluated,\n evidenceGrounded,\n evidenceAllTriggers: {\n evaluated: evidenceAllTriggersEvaluated,\n grounded: evidenceAllTriggersGrounded,\n unknown: allEvidenceRows.length - evidenceAllTriggersEvaluated\n },\n referencesEligible: references.length,\n referencesNavigated,\n taskOutcomesEvaluated: taskEvaluated,\n taskOutcomesSuccessful: taskSuccessful,\n explicitPositive,\n explicitNegative,\n unknown: Object.values(unknownByDimension).reduce((sum, count) => sum + count, 0),\n unknownByDimension,\n rates: {\n selectionYield: rate(selected, eligible, 0),\n deliveryRate: rate(delivered, observationCount - deliveryUnknown, deliveryUnknown),\n evidenceGrounding: rate(evidenceGrounded, evidenceEvaluated, evidenceRows.length - evidenceEvaluated),\n referenceNavigation: rate(referencesNavigated, referencesEvaluated, referenceUnknown),\n taskSuccess: rate(taskSuccessful, taskEvaluated, unknownByDimension.taskOutcome),\n explicitPositive: rate(explicitPositive, feedbackEvaluated, unknownByDimension.explicitFeedback)\n },\n sampleState: observationCount >= minimumSample ? 'sufficient' : 'insufficient_sample'\n };\n }\n\n /**\n * Get most helpful memories ranked by helpfulness score\n */\n async getHelpfulMemories(limit: number = 10): Promise<Array<{\n eventId: string;\n summary: string;\n helpfulnessScore: number;\n accessCount: number;\n evaluationCount: number;\n }>> {\n await this.initialize();\n\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT\n mh.event_id,\n AVG(mh.helpfulness_score) as avg_score,\n COUNT(*) as eval_count,\n e.content,\n e.access_count\n FROM memory_helpfulness mh\n JOIN events e ON e.id = mh.event_id\n WHERE mh.measured_at IS NOT NULL\n AND ${notActiveQuarantinedSql('e.metadata')}\n GROUP BY mh.event_id\n ORDER BY avg_score DESC\n LIMIT ?`,\n [limit]\n );\n\n return rows.map(r => ({\n eventId: r.event_id as string,\n summary: (r.content as string).substring(0, 200) + ((r.content as string).length > 200 ? '...' : ''),\n helpfulnessScore: Math.round((r.avg_score as number) * 100) / 100,\n accessCount: (r.access_count as number) || 0,\n evaluationCount: r.eval_count as number\n }));\n }\n\n /**\n * Get helpfulness statistics for dashboard\n */\n async getHelpfulnessStats(since?: Date, until?: Date): Promise<{\n avgScore: number;\n totalEvaluated: number;\n totalRetrievals: number;\n helpful: number;\n neutral: number;\n unhelpful: number;\n contentEvaluated: number;\n avgContentOverlap: number;\n groundedCount: number;\n }> {\n await this.initialize();\n\n const sinceIso = since?.toISOString();\n const untilIso = until?.toISOString();\n const timeClauses: string[] = [];\n const timeParams: string[] = [];\n if (sinceIso) {\n timeClauses.push('datetime(created_at) >= datetime(?)');\n timeParams.push(sinceIso);\n }\n if (untilIso) {\n timeClauses.push('datetime(created_at) < datetime(?)');\n timeParams.push(untilIso);\n }\n const timeWhere = timeClauses.length > 0 ? `WHERE ${timeClauses.join(' AND ')}` : '';\n const evaluatedWhere = timeClauses.length > 0\n ? `WHERE measured_at IS NOT NULL AND ${timeClauses.join(' AND ')}`\n : 'WHERE measured_at IS NOT NULL';\n\n // Read-only dashboards can open legacy DBs where the grounding-column\n // migration never ran; degrade to zeros instead of failing the query.\n const hasGroundingColumns = this.hasTableColumn('memory_helpfulness', 'content_overlap_score');\n const groundingSelect = hasGroundingColumns\n ? `COUNT(content_overlap_score) as content_evaluated,\n AVG(content_overlap_score) as avg_content_overlap,\n SUM(CASE WHEN content_overlap_score >= 0.3 THEN 1 ELSE 0 END) as grounded_count`\n : `0 as content_evaluated, 0 as avg_content_overlap, 0 as grounded_count`;\n\n const stats = sqliteGet<Record<string, unknown>>(\n this.db,\n `SELECT\n AVG(helpfulness_score) as avg_score,\n COUNT(*) as total_evaluated,\n SUM(CASE WHEN helpfulness_score >= 0.7 THEN 1 ELSE 0 END) as helpful,\n SUM(CASE WHEN helpfulness_score >= 0.4 AND helpfulness_score < 0.7 THEN 1 ELSE 0 END) as neutral,\n SUM(CASE WHEN helpfulness_score < 0.4 THEN 1 ELSE 0 END) as unhelpful,\n ${groundingSelect}\n FROM memory_helpfulness\n ${evaluatedWhere}`,\n timeParams\n );\n\n const totalRow = sqliteGet<Record<string, unknown>>(\n this.db,\n `SELECT COUNT(*) as total FROM memory_helpfulness ${timeWhere}`,\n timeParams\n );\n\n return {\n avgScore: Math.round(((stats?.avg_score as number) || 0) * 100) / 100,\n totalEvaluated: (stats?.total_evaluated as number) || 0,\n totalRetrievals: (totalRow?.total as number) || 0,\n helpful: (stats?.helpful as number) || 0,\n neutral: (stats?.neutral as number) || 0,\n unhelpful: (stats?.unhelpful as number) || 0,\n contentEvaluated: (stats?.content_evaluated as number) || 0,\n avgContentOverlap: Math.round(((stats?.avg_content_overlap as number) || 0) * 100) / 100,\n groundedCount: (stats?.grounded_count as number) || 0\n };\n }\n\n /**\n * Aggregate helpfulness by UTC day with one range scan.\n *\n * Both legacy SQLite timestamps (`YYYY-MM-DD HH:mm:ss`) and current ISO\n * timestamps share a sortable `YYYY-MM-DD` prefix. Date-only boundaries\n * therefore preserve compatibility while allowing idx_helpfulness_created_at\n * to serve the range predicate (unlike datetime(created_at)).\n */\n async getHelpfulnessStatsByDay(since: Date, until: Date): Promise<Array<{\n date: string;\n avgScore: number;\n totalEvaluated: number;\n totalRetrievals: number;\n helpful: number;\n neutral: number;\n unhelpful: number;\n }>> {\n await this.initialize();\n const sinceDay = since.toISOString().slice(0, 10);\n const untilDay = until.toISOString().slice(0, 10);\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT\n substr(created_at, 1, 10) AS date,\n AVG(CASE WHEN measured_at IS NOT NULL THEN helpfulness_score END) AS avg_score,\n SUM(CASE WHEN measured_at IS NOT NULL THEN 1 ELSE 0 END) AS total_evaluated,\n COUNT(*) AS total_retrievals,\n SUM(CASE WHEN measured_at IS NOT NULL AND helpfulness_score >= 0.7 THEN 1 ELSE 0 END) AS helpful,\n SUM(CASE WHEN measured_at IS NOT NULL AND helpfulness_score >= 0.4 AND helpfulness_score < 0.7 THEN 1 ELSE 0 END) AS neutral,\n SUM(CASE WHEN measured_at IS NOT NULL AND helpfulness_score < 0.4 THEN 1 ELSE 0 END) AS unhelpful\n FROM memory_helpfulness\n WHERE created_at >= ? AND created_at < ?\n GROUP BY substr(created_at, 1, 10)\n ORDER BY date ASC`,\n [sinceDay, untilDay]\n );\n\n return rows.map((row) => ({\n date: String(row.date || ''),\n avgScore: Math.round(((row.avg_score as number) || 0) * 100) / 100,\n totalEvaluated: (row.total_evaluated as number) || 0,\n totalRetrievals: (row.total_retrievals as number) || 0,\n helpful: (row.helpful as number) || 0,\n neutral: (row.neutral as number) || 0,\n unhelpful: (row.unhelpful as number) || 0\n }));\n }\n\n /**\n * Per-question usefulness history: each retrieval query (or session-start\n * injection batch) with the memories it injected, their measured\n * helpfulness, content grounding, and evidence snippets. Powers the\n * dashboard's evidence-history drill-down.\n */\n async getUsefulnessHistory(options: {\n limit?: number;\n offset?: number;\n sessionId?: string;\n withSelectionsOnly?: boolean;\n } = {}): Promise<Array<{\n traceId: string | null;\n kind: 'query' | 'session_start';\n sessionId: string | null;\n question: string;\n queryText: string | null;\n strategy: string | null;\n confidence: string | null;\n candidateCount: number;\n selectedCount: number;\n createdAt: Date;\n memories: Array<{\n eventId: string;\n eventType: string | null;\n summary: string;\n retrievalScore: number;\n helpfulnessScore: number | null;\n contentOverlapScore: number | null;\n evidence: EvidenceMatch[];\n measuredAt: string | null;\n source: string;\n presentationMode: RetrievalPresentationMode;\n }>;\n presentationMode: RetrievalPresentationMode;\n }>> {\n await this.initialize();\n\n const limit = Math.min(Math.max(options.limit ?? 20, 1), 100);\n const offset = Math.max(options.offset ?? 0, 0);\n\n // Read-only dashboards can open legacy DBs where the trace-link migration\n // (trace_id/source columns) never ran; fall back to trace-only history.\n const hasTraceLink = this.hasTableColumn('memory_helpfulness', 'trace_id');\n const hasTraceTrigger = this.hasTableColumn('retrieval_traces', 'trigger_type');\n const hasTracePresentation = this.hasTableColumn('retrieval_traces', 'presentation_mode');\n const traceKindSql = hasTraceTrigger\n ? `CASE WHEN trigger_type = 'session_start' THEN 'session_start' ELSE 'query' END`\n : `'query'`;\n\n const sessionFilterTrace = options.sessionId ? `AND session_id = ?` : '';\n const selectionFilter = options.withSelectionsOnly ? `AND selected_count > 0` : '';\n const params: unknown[] = [];\n if (options.sessionId) params.push(options.sessionId);\n if (hasTraceLink && options.sessionId) params.push(options.sessionId);\n params.push(limit, offset);\n\n // Unified, paginated timeline of \"questions\": retrieval traces plus\n // session-start injection batches (which have no retrieval_traces row).\n const sessionStartBranch = hasTraceLink\n ? `UNION ALL\n SELECT 'session_start' AS kind,\n COALESCE(trace_id, 'ss-' || session_id) AS id,\n session_id,\n MIN(created_at) AS created_at\n FROM memory_helpfulness\n WHERE source = 'session_start'\n AND (trace_id IS NULL OR NOT EXISTS (\n SELECT 1 FROM retrieval_traces rt WHERE rt.trace_id = memory_helpfulness.trace_id\n )) ${sessionFilterTrace}\n GROUP BY COALESCE(trace_id, 'ss-' || session_id), session_id`\n : '';\n const heads = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM (\n SELECT ${traceKindSql} AS kind, trace_id AS id, session_id, created_at\n FROM retrieval_traces\n WHERE 1=1 ${sessionFilterTrace} ${selectionFilter}\n ${sessionStartBranch}\n )\n ORDER BY created_at DESC\n LIMIT ? OFFSET ?`,\n params\n );\n\n const entries: Array<{\n traceId: string | null;\n kind: 'query' | 'session_start';\n sessionId: string | null;\n question: string;\n queryText: string | null;\n strategy: string | null;\n confidence: string | null;\n candidateCount: number;\n selectedCount: number;\n createdAt: Date;\n memories: Array<{\n eventId: string;\n eventType: string | null;\n summary: string;\n retrievalScore: number;\n helpfulnessScore: number | null;\n contentOverlapScore: number | null;\n evidence: EvidenceMatch[];\n measuredAt: string | null;\n source: string;\n presentationMode: RetrievalPresentationMode;\n }>;\n presentationMode: RetrievalPresentationMode;\n }> = [];\n\n for (const head of heads) {\n const kind = head.kind as 'query' | 'session_start';\n const headId = head.id as string;\n\n let trace: Record<string, unknown> | undefined;\n if (!headId.startsWith('ss-')) {\n trace = sqliteGet<Record<string, unknown>>(\n this.db,\n `SELECT * FROM retrieval_traces WHERE trace_id = ?`,\n [headId]\n );\n if (!trace && kind === 'query') continue;\n }\n\n // Helpfulness rows for this head: primary link via trace_id; legacy\n // fallback matches by session + selected event id within \u00B13 minutes.\n let helpRows: Record<string, unknown>[] = hasTraceLink\n ? sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM memory_helpfulness WHERE trace_id = ? ORDER BY created_at ASC`,\n [headId]\n )\n : [];\n if (helpRows.length === 0 && trace) {\n const selectedIds: string[] = (() => {\n try { return JSON.parse((trace.selected_event_ids as string) || '[]'); } catch { return []; }\n })();\n if (selectedIds.length > 0 && trace.session_id) {\n const legacyOnlyFilter = hasTraceLink ? `AND trace_id IS NULL` : '';\n helpRows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM memory_helpfulness\n WHERE session_id = ? ${legacyOnlyFilter}\n AND event_id IN (${selectedIds.map(() => '?').join(',')})\n AND ABS(strftime('%s', created_at) - strftime('%s', ?)) <= 180\n ORDER BY created_at ASC`,\n [trace.session_id, ...selectedIds, trace.created_at]\n );\n }\n }\n if (kind === 'session_start' && helpRows.length === 0 && !trace) {\n helpRows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM memory_helpfulness\n WHERE source = 'session_start' AND trace_id IS NULL AND session_id = ?\n ORDER BY created_at ASC`,\n [head.session_id]\n );\n }\n\n // Hydrate memory summaries. Lessons are not events: joining every id\n // against `events` rendered each injected lesson as \"no longer\n // available\", which is what made lesson selections look like data loss.\n const hasHelpfulnessKind = this.hasTableColumn('memory_helpfulness', 'memory_kind');\n const kindOf = (row: Record<string, unknown>): MemoryKind =>\n hasHelpfulnessKind ? normalizeMemoryKind(row.memory_kind) : 'event';\n const eventIds = Array.from(new Set(helpRows\n .filter((row) => kindOf(row) === 'event' || kindOf(row) === 'unknown')\n .map((row) => row.event_id as string)\n .filter(Boolean)));\n const lessonIds = Array.from(new Set(helpRows\n .filter((row) => kindOf(row) === 'lesson')\n .map((row) => row.event_id as string)\n .filter(Boolean)));\n const eventById = new Map<string, { content: string; event_type: string }>();\n if (eventIds.length > 0) {\n const rows = sqliteAll<{ id: string; content: string; event_type: string }>(\n this.db,\n `SELECT id, content, event_type FROM events WHERE id IN (${eventIds.map(() => '?').join(',')})`,\n eventIds\n );\n for (const row of rows) eventById.set(row.id, row);\n }\n if (lessonIds.length > 0 && this.hasTable('memory_lessons')) {\n const rows = sqliteAll<{ lesson_id: string; name: string; trigger: string }>(\n this.db,\n `SELECT lesson_id, name, trigger FROM memory_lessons WHERE lesson_id IN (${lessonIds.map(() => '?').join(',')})`,\n lessonIds\n );\n for (const row of rows) {\n eventById.set(row.lesson_id, {\n content: [row.name, row.trigger].filter(Boolean).join(' \u2014 '),\n event_type: 'lesson'\n });\n }\n }\n\n const memories = helpRows.map((row) => {\n const event = eventById.get(row.event_id as string);\n let evidence: EvidenceMatch[] = [];\n try {\n const parsed = JSON.parse((row.evidence_json as string) || '[]');\n if (Array.isArray(parsed)) evidence = parsed;\n } catch { /* legacy/corrupt rows have no evidence */ }\n const summary = event\n ? event.content.substring(0, 240) + (event.content.length > 240 ? '\u2026' : '')\n : '(event no longer available)';\n return {\n eventId: row.event_id as string,\n eventType: event?.event_type ?? null,\n summary,\n retrievalScore: (row.retrieval_score as number) ?? 0,\n helpfulnessScore: row.measured_at ? ((row.helpfulness_score as number) ?? null) : null,\n contentOverlapScore: (row.content_overlap_score as number) ?? null,\n evidence,\n measuredAt: (row.measured_at as string) ?? null,\n source: (row.source as string) || 'user_prompt',\n presentationMode: normalizeRetrievalPresentationMode(row.presentation_mode)\n };\n });\n\n if (trace) {\n entries.push({\n traceId: headId,\n kind,\n sessionId: (trace.session_id as string) ?? null,\n question: kind === 'session_start'\n ? (normalizeRetrievalPresentationMode(trace.presentation_mode) === 'core'\n ? 'Session start \u2014 core memory injected'\n : 'Session start \u2014 recent project context injected')\n : (trace.raw_query_text as string) || (trace.query_text as string) || '',\n queryText: (trace.query_text as string) ?? null,\n strategy: (trace.strategy as string) ?? null,\n confidence: (trace.confidence as string) ?? null,\n candidateCount: (trace.candidate_count as number) ?? 0,\n selectedCount: (trace.selected_count as number) ?? 0,\n createdAt: toDateFromSQLite(trace.created_at as string),\n presentationMode: hasTracePresentation\n ? normalizeRetrievalPresentationMode(trace.presentation_mode)\n : 'unknown',\n memories\n });\n } else {\n entries.push({\n traceId: headId.startsWith('ss-') ? null : headId,\n kind: 'session_start',\n sessionId: (head.session_id as string) ?? null,\n question: 'Session start \u2014 recent project context injected',\n queryText: null,\n strategy: 'session-start',\n confidence: null,\n candidateCount: memories.length,\n selectedCount: memories.length,\n createdAt: toDateFromSQLite(head.created_at as string),\n presentationMode: 'unknown',\n memories\n });\n }\n }\n\n return entries;\n }\n\n /**\n * Fast keyword search using FTS5\n * Returns events matching the search query, ranked by relevance\n */\n async keywordSearch(\n query: string,\n limit: number = 10,\n options?: { includeToolObservations?: boolean }\n ): Promise<Array<{event: MemoryEvent; rank: number}>> {\n await this.initialize();\n\n // tool_observation events typically outnumber prompts/answers several-fold\n // (they are kept as events but excluded from embedding), so an unfiltered\n // FTS query returns mostly raw tool output and crowds answer-type events\n // out of the limit window. Excluded by default to mirror the embedding\n // policy; callers that intentionally want tool evidence (episode seeding,\n // explicit eventType filters) opt in.\n const includeToolObservations = options?.includeToolObservations === true;\n const toolObservationSql = includeToolObservations ? '' : `AND e.event_type != 'tool_observation'`;\n\n // Escape special FTS5 characters and prepare search terms\n const searchTerms = query\n .replace(/['\"(){}[\\]^~*?:\\\\/-]/g, ' ') // Remove special chars\n .split(/\\s+/)\n .filter(term => term.length > 1) // Filter short terms\n .map(term => `\"${term}\"*`) // Prefix matching\n .join(' OR ');\n\n if (!searchTerms) {\n return [];\n }\n\n try {\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT e.*, fts.rank\n FROM events_fts fts\n JOIN events e ON e.id = fts.event_id\n WHERE events_fts MATCH ?\n AND ${notActiveQuarantinedSql('e.metadata')}\n ${toolObservationSql}\n ORDER BY fts.rank\n LIMIT ?`,\n [searchTerms, limit]\n );\n\n return rows.map(row => ({\n event: this.rowToEvent(row),\n rank: row.rank as number\n }));\n } catch (error: any) {\n // FTS table might not exist yet (old database)\n // Fallback to LIKE search\n const likePattern = `%${query}%`;\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT *, 0 as rank FROM events\n WHERE content LIKE ?\n AND ${notActiveQuarantinedSql()}\n ${includeToolObservations ? '' : `AND event_type != 'tool_observation'`}\n ORDER BY timestamp DESC\n LIMIT ?`,\n [likePattern, limit]\n );\n\n return rows.map(row => ({\n event: this.rowToEvent(row),\n rank: 0\n }));\n }\n }\n\n /**\n * Dedicated L1+ answer-evidence lane. Graduation alone is not sufficient:\n * prompts and raw tool output can be promoted for continuity, but only final\n * responses/summaries are allowed to compete as direct answer evidence.\n */\n async searchGraduatedEvidence(\n query: string,\n limit: number = 10\n ): Promise<Array<{ event: MemoryEvent; rank: number; level: string; accessCount: number }>> {\n await this.initialize();\n const searchTerms = query\n .replace(/['\"(){}[\\]^~*?:\\\\/-]/g, ' ')\n .split(/\\s+/)\n .filter(term => term.length > 1)\n .map(term => `\"${term}\"*`)\n .join(' OR ');\n if (!searchTerms) return [];\n\n try {\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT e.*, fts.rank, ml.level\n FROM events_fts fts\n JOIN events e ON e.id = fts.event_id\n JOIN memory_levels ml ON ml.event_id = e.id\n WHERE events_fts MATCH ?\n AND ml.level != 'L0'\n AND e.event_type IN ('user_prompt', 'agent_response', 'session_summary')\n AND ${notActiveQuarantinedSql('e.metadata')}\n ORDER BY fts.rank, ml.level DESC, e.access_count DESC\n LIMIT ?`,\n [searchTerms, limit]\n );\n return rows.map((row) => ({\n event: this.rowToEvent(row),\n rank: Number(row.rank),\n level: String(row.level),\n accessCount: Number(row.access_count ?? 0)\n }));\n } catch {\n return [];\n }\n }\n\n /**\n * Rebuild FTS index from existing events\n * Call this once after upgrading to FTS5\n */\n /**\n * Drop and recreate the events_fts virtual table + sync triggers, repopulating\n * from the current events table. Recreating the table (instead of issuing\n * DELETEs against it) sidesteps a quirk where older migrated FTS5 tables fail\n * with `no such column: T.event_id` on synthetic deletes. Safe to call inside\n * a transaction (pure DDL + INSERT...SELECT, no transaction control).\n */\n private recreateEventsFtsTable(): void {\n sqliteExec(this.db, `\n DROP TRIGGER IF EXISTS events_fts_insert;\n DROP TRIGGER IF EXISTS events_fts_delete;\n DROP TRIGGER IF EXISTS events_fts_update;\n DROP TABLE IF EXISTS events_fts;\n\n CREATE VIRTUAL TABLE events_fts USING fts5(\n content,\n event_id UNINDEXED,\n tokenize='porter unicode61'\n );\n\n INSERT INTO events_fts(rowid, content, event_id)\n SELECT rowid, content, id FROM events;\n\n CREATE TRIGGER events_fts_insert AFTER INSERT ON events BEGIN\n INSERT INTO events_fts(rowid, content, event_id) VALUES (NEW.rowid, NEW.content, NEW.id);\n END;\n\n CREATE TRIGGER events_fts_delete AFTER DELETE ON events BEGIN\n DELETE FROM events_fts WHERE rowid = OLD.rowid;\n END;\n\n CREATE TRIGGER events_fts_update AFTER UPDATE ON events BEGIN\n DELETE FROM events_fts WHERE rowid = OLD.rowid;\n INSERT INTO events_fts(rowid, content, event_id) VALUES (NEW.rowid, NEW.content, NEW.id);\n END;\n `);\n }\n\n async rebuildFtsIndex(): Promise<number> {\n await this.initialize();\n\n // Get count of events to index\n const countRow = sqliteGet<{count: number}>(this.db, 'SELECT COUNT(*) as count FROM events', []);\n const totalEvents = countRow?.count ?? 0;\n\n this.recreateEventsFtsTable();\n\n return totalEvents;\n }\n\n /**\n * Get database instance for direct access\n */\n getDatabase(): SQLiteDatabase {\n return this.db;\n }\n\n private hasTableColumn(tableName: string, columnName: string): boolean {\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(tableName)) return false;\n try {\n const rows = sqliteAll<{ name: string }>(this.db, `PRAGMA table_info(\"${tableName}\")`, []);\n return rows.some((row) => row.name === columnName);\n } catch {\n return false;\n }\n }\n\n private hasTable(tableName: string): boolean {\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(tableName)) return false;\n try {\n const rows = sqliteAll<{ name: string }>(\n this.db,\n `SELECT name FROM sqlite_master WHERE type = 'table' AND name = ? LIMIT 1`,\n [tableName]\n );\n return rows.length > 0;\n } catch {\n return false;\n }\n }\n\n /**\n * Add a column only when its table exists and the column is missing.\n *\n * Unlike a blind `try { ALTER } catch {}`, this distinguishes \"already\n * migrated\" / \"table not present yet\" (both safely skipped) from a genuine\n * failure (disk full, corruption), which is allowed to surface instead of\n * being silently swallowed as if the migration had succeeded.\n */\n private addColumnIfMissing(table: string, column: string, definition: string): void {\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(table) || !/^[A-Za-z_][A-Za-z0-9_]*$/.test(column)) {\n throw new Error(`Invalid identifier in migration: ${table}.${column}`);\n }\n if (!this.hasTable(table)) return;\n if (this.hasTableColumn(table, column)) return;\n sqliteExec(this.db, `ALTER TABLE ${table} ADD COLUMN ${column} ${definition};`);\n }\n\n\n async recordRetrievalTrace(input: {\n traceId?: string;\n sessionId?: string;\n projectHash?: string;\n queryText: string;\n rawQueryText?: string;\n queryRewriteKind?: string;\n strategy?: string;\n candidateEventIds: string[];\n selectedEventIds: string[];\n candidateDetails?: Array<{\n eventId: string;\n score: number;\n semanticScore?: number;\n lexicalScore?: number;\n recencyScore?: number;\n lanes?: RetrievalDebugLane[];\n }>;\n selectedDetails?: Array<{\n eventId: string;\n score: number;\n semanticScore?: number;\n lexicalScore?: number;\n recencyScore?: number;\n lanes?: RetrievalDebugLane[];\n }>;\n confidence?: string;\n fallbackTrace?: string[];\n presentationMode?: RetrievalPresentationMode;\n triggerType?: RetrievalTriggerType;\n deliveryClient?: string;\n outcomeDiagnostics?: RetrievalOutcomeDiagnostics;\n /** Typed references (specs R1). Preferred over the id arrays by new readers. */\n items?: RetrievalTraceItemInput[];\n /** Stable id of the caller request; a repeat write updates instead of duplicating. */\n requestId?: string;\n evaluationRunId?: string;\n runtimeVersion?: string;\n }): Promise<string | undefined> {\n if (this.readOnly) return undefined;\n await this.initialize();\n\n const requestId = normalizeRequestId(input.requestId);\n const queryRewriteKind = normalizeQueryRewriteKind(input.queryRewriteKind);\n const candidateDetails = normalizeRetrievalTraceDetails(input.candidateDetails);\n const selectedDetails = normalizeRetrievalTraceDetails(input.selectedDetails);\n // No diagnostics and no selection is \"we did not classify this\", not a\n // runtime failure. `runtime_error` is now written only by a caller that\n // actually caught an exception (specs R2).\n const outcomeDiagnostics = normalizeRetrievalOutcomeDiagnostics(\n input.outcomeDiagnostics,\n input.selectedEventIds.length > 0 ? 'selected' : 'unknown'\n );\n const values = [\n input.sessionId || null,\n input.projectHash || null,\n input.queryText,\n input.rawQueryText || null,\n queryRewriteKind,\n input.strategy || null,\n JSON.stringify(input.candidateEventIds || []),\n JSON.stringify(input.selectedEventIds || []),\n JSON.stringify(candidateDetails),\n JSON.stringify(selectedDetails),\n (input.candidateEventIds || []).length,\n (input.selectedEventIds || []).length,\n input.confidence || null,\n JSON.stringify(input.fallbackTrace || []),\n normalizeRetrievalPresentationMode(input.presentationMode),\n normalizeRetrievalTriggerType(input.triggerType),\n normalizeTelemetryClient(input.deliveryClient),\n outcomeDiagnostics.outcomeReason,\n JSON.stringify(outcomeDiagnostics),\n requestId,\n normalizeRequestId(input.evaluationRunId),\n input.runtimeVersion?.slice(0, 64) || null,\n RETRIEVAL_TELEMETRY_SCHEMA_VERSION\n ];\n\n const updateSql = `UPDATE retrieval_traces SET\n session_id = ?, project_hash = ?, query_text = ?, raw_query_text = ?,\n query_rewrite_kind = ?, strategy = ?, candidate_event_ids = ?, selected_event_ids = ?,\n candidate_details_json = ?, selected_details_json = ?, candidate_count = ?,\n selected_count = ?, confidence = ?, fallback_trace = ?, presentation_mode = ?,\n trigger_type = ?, delivery_client = ?, outcome_reason = ?, retrieval_diagnostics_json = ?,\n request_id = ?, evaluation_run_id = ?, runtime_version = ?, telemetry_schema_version = ?\n WHERE trace_id = ?`;\n const insertSql = `INSERT INTO retrieval_traces (\n session_id, project_hash, query_text, raw_query_text, query_rewrite_kind, strategy,\n candidate_event_ids, selected_event_ids, candidate_details_json, selected_details_json,\n candidate_count, selected_count, confidence, fallback_trace,\n presentation_mode, trigger_type, delivery_client, outcome_reason, retrieval_diagnostics_json,\n request_id, evaluation_run_id, runtime_version, telemetry_schema_version, trace_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`;\n\n // The same request can be traced twice (the orchestrator's automatic trace\n // plus an explicit hook trace). Collapsing on requestId keeps one request\n // equal to one row so client coverage is not double-counted.\n //\n // The lookup and the write run inside one immediate transaction and the\n // request id carries a unique index where the store allows one, so a\n // concurrent writer in another process cannot slip a second row in between\n // the SELECT and the INSERT (finding 9). Where the index could not be\n // created (a store that already holds duplicate request ids), the\n // transaction still serializes this process's own writers.\n const write = (): { traceId: string; replacedExisting: boolean } => {\n const existing = requestId\n ? sqliteGet<{ trace_id: string }>(\n this.db,\n `SELECT trace_id FROM retrieval_traces WHERE request_id = ? LIMIT 1`,\n [requestId]\n )\n : undefined;\n const resolvedTraceId = existing?.trace_id || input.traceId || randomUUID();\n if (existing) {\n sqliteRun(this.db, updateSql, [...values, resolvedTraceId]);\n return { traceId: resolvedTraceId, replacedExisting: true };\n }\n try {\n sqliteRun(this.db, insertSql, [...values, resolvedTraceId]);\n return { traceId: resolvedTraceId, replacedExisting: false };\n } catch (error) {\n // Lost the race against another writer holding the same request id:\n // adopt its row instead of creating a duplicate.\n if (!requestId) throw error;\n const raced = sqliteGet<{ trace_id: string }>(\n this.db,\n `SELECT trace_id FROM retrieval_traces WHERE request_id = ? LIMIT 1`,\n [requestId]\n );\n if (!raced) throw error;\n sqliteRun(this.db, updateSql, [...values, raced.trace_id]);\n return { traceId: raced.trace_id, replacedExisting: true };\n }\n };\n\n return this.runInImmediateTransaction(() => {\n const result = write();\n const hasExistingTypedItems = result.replacedExisting\n && readTraceItems(this.db, result.traceId).length > 0;\n if (retrievalRollout().typedTraceWrite || hasExistingTypedItems) {\n this.writeTypedTraceItems(result.traceId, input, { replaceExisting: result.replacedExisting });\n }\n return result.traceId;\n });\n }\n\n /**\n * Run `fn` inside an IMMEDIATE transaction when the connection allows it.\n *\n * A read-then-write that must stay atomic across processes needs the write\n * lock taken up front. Reuse an existing transaction, but never bypass a\n * failed lock acquisition: the arrays and typed ledger must commit together.\n */\n private runInImmediateTransaction<T>(fn: () => T): T {\n if (this.db.inTransaction) return fn();\n sqliteExec(this.db, 'BEGIN IMMEDIATE');\n try {\n const result = fn();\n sqliteExec(this.db, 'COMMIT');\n return result;\n } catch (error) {\n try {\n sqliteExec(this.db, 'ROLLBACK');\n } catch { /* the transaction was already resolved */ }\n throw error;\n }\n }\n\n /**\n * Persist the typed item rows for a trace. Callers that pass explicit items\n * keep their kinds; otherwise ids are resolved read-only against the local\n * tables so an untyped caller still produces correct rows instead of\n * defaulting every reference to \"event\".\n */\n private writeTypedTraceItems(\n traceId: string,\n input: {\n projectHash?: string;\n candidateEventIds: string[];\n selectedEventIds: string[];\n items?: RetrievalTraceItemInput[];\n },\n options: { replaceExisting?: boolean } = {}\n ): void {\n try {\n const projectId = input.projectHash || null;\n let items: RetrievalTraceItemInput[];\n if (input.items && input.items.length > 0) {\n items = input.items;\n } else {\n const selected = new Set(input.selectedEventIds || []);\n const all = Array.from(new Set([...(input.candidateEventIds || []), ...(input.selectedEventIds || [])]));\n const resolved = resolveMemoryRefKinds(this.db, all, { projectId });\n items = all.map((id, index) => {\n const ref = resolved.get(id);\n return {\n kind: ref?.resolution === 'resolved' ? ref.kind : 'unknown',\n id,\n projectId: ref?.projectId ?? projectId,\n rank: index,\n selected: selected.has(id),\n // Unresolved is not deleted: the row may predate a table or live in\n // a store this process cannot read. `deleted` records an observed\n // deletion only (specs R1).\n deleted: false\n };\n });\n }\n const normalized = normalizeTraceItems(items, { projectId });\n if (options.replaceExisting) {\n // A request-id replay replaces the legacy arrays wholesale. Replace\n // the typed rows wholesale too: the regular UPSERT intentionally keeps\n // selected/deleted monotonic and therefore cannot represent a selected\n // item becoming only a candidate on a corrected replay.\n sqliteRun(this.db, 'DELETE FROM retrieval_trace_items WHERE trace_id = ?', [traceId]);\n }\n writeTraceItems(this.db, traceId, normalized);\n } catch (error) {\n // Let the caller roll back both representations on any ledger failure.\n throw error;\n }\n }\n\n /** Typed references recorded for a trace (specs R1). */\n async getRetrievalTraceItems(traceId: string) {\n await this.initialize();\n return readTraceItems(this.db, traceId);\n }\n\n /**\n * Typed selection totals for a window. Traces written before the typed ledger\n * are resolved read-only; nothing is written by this call.\n */\n async getTypedSelectionSummary(options: { since?: Date; until?: Date; resolveLegacy?: boolean } = {}): Promise<TypedSelectionSummary> {\n await this.initialize();\n return summarizeTypedSelections(this.db, options);\n }\n\n /**\n * Explicit backfill of typed items for legacy traces. Defaults to a dry run;\n * read-only reports never call it.\n */\n async backfillRetrievalTraceItems(options: { dryRun?: boolean; limit?: number; since?: Date } = {}): Promise<TraceItemBackfillResult> {\n await this.initialize();\n if (this.readOnly && options.dryRun === false) {\n throw new Error('retrieval trace item backfill cannot run against a read-only store');\n }\n return options.dryRun === false\n ? this.runInImmediateTransaction(() => backfillTraceItems(this.db, options))\n : backfillTraceItems(this.db, options);\n }\n\n /**\n * Attribute a reference open to a recent reference delivery only when one\n * trace is the unique candidate. The 15-minute window is deliberately\n * bounded; an optional current session makes the boundary stricter. Client\n * labels are recorded for diagnostics but never used to guess attribution.\n * Repeated opens collapse into one row with an incremented count.\n */\n async recordReferenceNavigation(\n input: RecordReferenceNavigationInput\n ): Promise<RecordReferenceNavigationResult> {\n if (this.readOnly) {\n return { outcome: 'unattributed', traceId: null, repeated: false };\n }\n await this.initialize();\n return recordReferenceNavigationOnDb(this.db, input);\n }\n\n /**\n * Per-client instrumentation coverage (specs R2).\n *\n * Only requests this store actually saw can be counted. A client that never\n * writes telemetry has no row here at all, and a client whose rows lack a\n * request id reports coverage `unknown` \u2014 reporting 0% would assert an\n * observation we do not have.\n */\n async getRetrievalClientCoverage(options: { since?: Date; until?: Date } = {}): Promise<RetrievalClientCoverage[]> {\n await this.initialize();\n if (!this.hasTable('retrieval_traces')) return [];\n const hasRequestId = this.hasTableColumn('retrieval_traces', 'request_id');\n const clauses: string[] = [];\n const params: unknown[] = [];\n if (options.since) {\n clauses.push('julianday(created_at) >= julianday(?)');\n params.push(options.since.toISOString());\n }\n if (options.until) {\n clauses.push('julianday(created_at) < julianday(?)');\n params.push(options.until.toISOString());\n }\n const where = clauses.length > 0 ? ` WHERE ${clauses.join(' AND ')}` : '';\n const instrumentedSql = hasRequestId\n ? `COUNT(DISTINCT CASE WHEN request_id IS NOT NULL THEN request_id END)`\n : '0';\n const observedSql = hasRequestId\n ? `COUNT(DISTINCT COALESCE(request_id, trace_id))`\n : `COUNT(DISTINCT trace_id)`;\n const rows = sqliteAll<{ client: string; observed: number; instrumented: number; unknown_client: number }>(\n this.db,\n `SELECT COALESCE(delivery_client, 'unknown') AS client,\n ${observedSql} AS observed,\n ${instrumentedSql} AS instrumented,\n SUM(CASE WHEN delivery_client IS NULL OR delivery_client = 'unknown' THEN 1 ELSE 0 END) AS unknown_client\n FROM retrieval_traces${where}\n GROUP BY COALESCE(delivery_client, 'unknown')\n ORDER BY observed DESC`,\n params\n );\n return rows.map((row) => {\n const observed = Number(row.observed || 0);\n const instrumented = Number(row.instrumented || 0);\n const unobserved = Number(row.unknown_client || 0);\n return {\n client: String(row.client || 'unknown'),\n observedRequests: observed,\n instrumentedRequests: instrumented,\n unobservedOrUnknown: unobserved,\n coverage: observed > 0 && instrumented > 0\n ? Math.round((instrumented / observed) * 10_000) / 10_000\n : null,\n coverageState: observed > 0 && instrumented > 0 ? 'measured' : 'unknown'\n };\n });\n }\n\n /**\n * Per-source ingest clocks and lag (specs R4).\n *\n * `timestamp` is when this store wrote the row; importers additionally keep\n * the original conversation instant. Reporting them per source is what makes\n * an importer backlog visible instead of looking like \"old memories\". Rows\n * whose original instant is unknown are counted, never assumed lag-free.\n */\n async getIngestSourceClocks(options: { since?: Date; until?: Date } = {}): Promise<Array<{\n source: string;\n events: number;\n withSourceClock: number;\n unknownSourceClock: number;\n latestOccurredAt: string | null;\n latestIngestedAt: string | null;\n maxLagMs: number | null;\n medianLagMs: number | null;\n }>> {\n await this.initialize();\n if (!this.hasTable('events')) return [];\n return readIngestSourceClocks(this.db, options);\n }\n\n async getRetrievalTelemetryStats(): Promise<RetrievalTelemetryStats> {\n await this.initialize();\n\n const hasTracePresentation = this.hasTableColumn('retrieval_traces', 'presentation_mode');\n const hasTraceTrigger = this.hasTableColumn('retrieval_traces', 'trigger_type');\n const hasHelpfulnessTable = Boolean(sqliteGet<{ name: string }>(\n this.db,\n `SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'memory_helpfulness'`\n ));\n const hasHelpfulnessPresentation = hasHelpfulnessTable\n && this.hasTableColumn('memory_helpfulness', 'presentation_mode');\n const hasNavigationTable = Boolean(sqliteGet<{ name: string }>(\n this.db,\n `SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'retrieval_navigation_events'`\n ));\n const presentationSql = hasTracePresentation\n ? \"COALESCE(NULLIF(TRIM(presentation_mode), ''), 'unknown')\"\n : \"'unknown'\";\n const triggerSql = hasTraceTrigger\n ? \"COALESCE(NULLIF(TRIM(trigger_type), ''), 'unknown')\"\n : \"'unknown'\";\n\n const presentationRows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT ${presentationSql} AS label, COUNT(*) AS trace_count,\n COALESCE(SUM(selected_count), 0) AS item_count\n FROM retrieval_traces GROUP BY ${presentationSql} ORDER BY label ASC`\n );\n const triggerRows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT ${triggerSql} AS label, COUNT(*) AS trace_count,\n COALESCE(SUM(selected_count), 0) AS item_count\n FROM retrieval_traces GROUP BY ${triggerSql} ORDER BY label ASC`\n );\n const deliveryTotals = sqliteGet<Record<string, unknown>>(\n this.db,\n `SELECT COUNT(*) AS trace_count, COALESCE(SUM(selected_count), 0) AS item_count FROM retrieval_traces`\n );\n const legacyUnknownRows = hasHelpfulnessTable\n ? sqliteGet<{ count: number }>(\n this.db,\n hasHelpfulnessPresentation\n ? `SELECT COUNT(*) AS count FROM memory_helpfulness WHERE presentation_mode = 'unknown' OR presentation_mode IS NULL`\n : `SELECT COUNT(*) AS count FROM memory_helpfulness`\n )?.count ?? 0\n : 0;\n\n const evidence = hasHelpfulnessPresentation\n ? sqliteGet<Record<string, unknown>>(\n this.db,\n `SELECT COUNT(content_overlap_score) AS evaluated,\n SUM(CASE WHEN content_overlap_score >= 0.3 THEN 1 ELSE 0 END) AS grounded,\n AVG(content_overlap_score) AS average_overlap\n FROM memory_helpfulness\n WHERE presentation_mode = 'evidence'`\n )\n : undefined;\n const referenceEligible = hasTracePresentation\n ? Number(sqliteGet<{ count: number }>(\n this.db,\n `SELECT COUNT(*) AS count FROM retrieval_traces\n WHERE presentation_mode = 'reference' AND selected_count > 0`\n )?.count ?? 0)\n : 0;\n const navigation = hasNavigationTable\n ? sqliteGet<Record<string, unknown>>(\n this.db,\n `SELECT\n COUNT(DISTINCT CASE WHEN attribution_outcome = 'attributed' THEN trace_id END) AS navigated_traces,\n SUM(CASE WHEN attribution_outcome = 'attributed' THEN open_count ELSE 0 END) AS attributed_opens,\n SUM(CASE WHEN attribution_outcome = 'ambiguous' THEN open_count ELSE 0 END) AS ambiguous_opens,\n SUM(CASE WHEN attribution_outcome = 'unattributed' THEN open_count ELSE 0 END) AS unattributed_opens\n FROM retrieval_navigation_events`\n )\n : undefined;\n const evidenceEvaluated = Number(evidence?.evaluated || 0);\n const evidenceGrounded = Number(evidence?.grounded || 0);\n const navigatedTraces = Number(navigation?.navigated_traces || 0);\n\n return {\n deliveries: {\n totalTraces: Number(deliveryTotals?.trace_count || 0),\n totalItems: Number(deliveryTotals?.item_count || 0),\n byPresentation: presentationRows.map((row) => ({\n presentationMode: normalizeRetrievalPresentationMode(row.label),\n traceCount: Number(row.trace_count || 0),\n deliveredItemCount: Number(row.item_count || 0)\n })),\n byTrigger: triggerRows.map((row) => ({\n triggerType: normalizeRetrievalTriggerType(row.label),\n traceCount: Number(row.trace_count || 0),\n deliveredItemCount: Number(row.item_count || 0)\n })),\n legacyUnknownRows: Number(legacyUnknownRows)\n },\n evidenceGrounding: {\n evaluatedDeliveries: evidenceEvaluated,\n groundedDeliveries: evidenceGrounded,\n groundingRate: evidenceEvaluated > 0 ? evidenceGrounded / evidenceEvaluated : 0,\n averageContentOverlap: Number(evidence?.average_overlap || 0)\n },\n referenceNavigation: {\n eligibleTraces: referenceEligible,\n navigatedTraces,\n navigationRate: referenceEligible > 0 ? navigatedTraces / referenceEligible : 0,\n attributedOpenCount: Number(navigation?.attributed_opens || 0),\n ambiguousOpenCount: Number(navigation?.ambiguous_opens || 0),\n unattributedOpenCount: Number(navigation?.unattributed_opens || 0)\n }\n };\n }\n\n async getRecentRetrievalTraces(limit: number = 50): Promise<Array<{\n traceId: string;\n sessionId?: string;\n projectHash?: string;\n queryText: string;\n rawQueryText?: string;\n queryRewriteKind?: string;\n strategy?: string;\n candidateEventIds: string[];\n selectedEventIds: string[];\n candidateDetails: Array<{\n eventId: string;\n score: number;\n semanticScore?: number;\n lexicalScore?: number;\n recencyScore?: number;\n lanes?: RetrievalDebugLane[];\n }>;\n selectedDetails: Array<{\n eventId: string;\n score: number;\n semanticScore?: number;\n lexicalScore?: number;\n recencyScore?: number;\n lanes?: RetrievalDebugLane[];\n }>;\n candidateCount: number;\n selectedCount: number;\n confidence?: string;\n fallbackTrace: string[];\n presentationMode: RetrievalPresentationMode;\n triggerType: RetrievalTriggerType;\n deliveryClient: string;\n outcomeDiagnostics: RetrievalOutcomeDiagnostics;\n createdAt: Date;\n }>> {\n await this.initialize();\n\n try {\n const userQueryWhere = this.hasTableColumn('retrieval_traces', 'trigger_type')\n ? `WHERE COALESCE(trigger_type, 'unknown') != 'session_start'`\n : '';\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM retrieval_traces ${userQueryWhere} ORDER BY created_at DESC LIMIT ?`,\n [limit]\n );\n\n return rows.map((row) => ({\n traceId: row.trace_id as string,\n sessionId: (row.session_id as string) || undefined,\n projectHash: (row.project_hash as string) || undefined,\n queryText: row.query_text as string,\n rawQueryText: (row.raw_query_text as string) || undefined,\n queryRewriteKind: normalizeQueryRewriteKind(row.query_rewrite_kind as string | null),\n strategy: (row.strategy as string) || undefined,\n candidateEventIds: row.candidate_event_ids ? JSON.parse(row.candidate_event_ids as string) : [],\n selectedEventIds: row.selected_event_ids ? JSON.parse(row.selected_event_ids as string) : [],\n candidateDetails: parseRetrievalTraceDetails(row.candidate_details_json),\n selectedDetails: parseRetrievalTraceDetails(row.selected_details_json),\n candidateCount: Number(row.candidate_count || 0),\n selectedCount: Number(row.selected_count || 0),\n confidence: (row.confidence as string) || undefined,\n fallbackTrace: row.fallback_trace ? JSON.parse(row.fallback_trace as string) : [],\n presentationMode: normalizeRetrievalPresentationMode(row.presentation_mode),\n triggerType: normalizeRetrievalTriggerType(row.trigger_type),\n deliveryClient: normalizeTelemetryClient(row.delivery_client),\n outcomeDiagnostics: parseRetrievalOutcomeDiagnostics(row),\n createdAt: toDateFromSQLite(row.created_at),\n }));\n } catch (err: any) {\n if (err?.message?.includes('no such table')) return [];\n throw err;\n }\n }\n\n async getRetrievalTraceStats(): Promise<{\n totalQueries: number;\n avgCandidateCount: number;\n avgSelectedCount: number;\n selectionRate: number;\n rewrittenQueries: number;\n rewriteRate: number;\n rewrittenQueriesWithSelection: number;\n rawQueriesWithSelection: number;\n rewrittenSelectionRate: number;\n rawSelectionRate: number;\n avgSelectedCountForRewrittenQueries: number;\n avgSelectedCountForRawQueries: number;\n strategyBreakdown: Array<{\n strategy: string;\n totalQueries: number;\n queriesWithSelection: number;\n rewrittenQueries: number;\n rewriteRate: number;\n totalCandidateCount: number;\n totalSelectedCount: number;\n avgCandidateCount: number;\n avgSelectedCount: number;\n selectionRate: number;\n queryYieldRate: number;\n }>;\n }> {\n await this.initialize();\n\n try {\n const rewrittenQueryRewriteKindSql = this.hasTableColumn('retrieval_traces', 'query_rewrite_kind')\n ? REWRITTEN_QUERY_REWRITE_KIND_SQL\n : '0';\n const userQueryWhere = this.hasTableColumn('retrieval_traces', 'trigger_type')\n ? `WHERE COALESCE(trigger_type, 'unknown') != 'session_start'`\n : '';\n const row = sqliteGet<Record<string, unknown>>(\n this.db,\n `SELECT\n COUNT(*) as total_queries,\n AVG(candidate_count) as avg_candidate_count,\n AVG(selected_count) as avg_selected_count,\n SUM(CASE WHEN ${rewrittenQueryRewriteKindSql} THEN 1 ELSE 0 END) as rewritten_queries,\n SUM(CASE WHEN ${rewrittenQueryRewriteKindSql} AND selected_count > 0 THEN 1 ELSE 0 END) as rewritten_queries_with_selection,\n SUM(CASE WHEN NOT (${rewrittenQueryRewriteKindSql}) AND selected_count > 0 THEN 1 ELSE 0 END) as raw_queries_with_selection,\n AVG(CASE WHEN ${rewrittenQueryRewriteKindSql} THEN selected_count END) as avg_selected_count_for_rewritten_queries,\n AVG(CASE WHEN NOT (${rewrittenQueryRewriteKindSql}) THEN selected_count END) as avg_selected_count_for_raw_queries,\n CASE\n WHEN SUM(candidate_count) > 0 THEN (SUM(selected_count) * 1.0 / SUM(candidate_count))\n ELSE 0\n END as selection_rate\n FROM retrieval_traces\n ${userQueryWhere}`,\n []\n );\n\n const strategyColumnSql = this.hasTableColumn('retrieval_traces', 'strategy')\n ? \"COALESCE(NULLIF(TRIM(strategy), ''), 'unknown')\"\n : \"'unknown'\";\n const strategyRows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT\n ${strategyColumnSql} as strategy,\n COUNT(*) as total_queries,\n SUM(CASE WHEN selected_count > 0 THEN 1 ELSE 0 END) as queries_with_selection,\n SUM(CASE WHEN ${rewrittenQueryRewriteKindSql} THEN 1 ELSE 0 END) as rewritten_queries,\n SUM(candidate_count) as total_candidate_count,\n SUM(selected_count) as total_selected_count,\n AVG(candidate_count) as avg_candidate_count,\n AVG(selected_count) as avg_selected_count,\n CASE\n WHEN SUM(candidate_count) > 0 THEN (SUM(selected_count) * 1.0 / SUM(candidate_count))\n ELSE 0\n END as selection_rate\n FROM retrieval_traces\n ${userQueryWhere}\n GROUP BY ${strategyColumnSql}\n ORDER BY total_queries DESC, strategy ASC`,\n []\n );\n\n const strategyBreakdown = strategyRows.map((strategyRow) => {\n const strategyTotalQueries = Number(strategyRow.total_queries || 0);\n const strategyQueriesWithSelection = Number(strategyRow.queries_with_selection || 0);\n const strategyRewrittenQueries = Number(strategyRow.rewritten_queries || 0);\n return {\n strategy: String(strategyRow.strategy || 'unknown'),\n totalQueries: strategyTotalQueries,\n queriesWithSelection: strategyQueriesWithSelection,\n rewrittenQueries: strategyRewrittenQueries,\n rewriteRate: strategyTotalQueries > 0 ? strategyRewrittenQueries / strategyTotalQueries : 0,\n totalCandidateCount: Number(strategyRow.total_candidate_count || 0),\n totalSelectedCount: Number(strategyRow.total_selected_count || 0),\n avgCandidateCount: Number(strategyRow.avg_candidate_count || 0),\n avgSelectedCount: Number(strategyRow.avg_selected_count || 0),\n selectionRate: Number(strategyRow.selection_rate || 0),\n queryYieldRate: strategyTotalQueries > 0 ? strategyQueriesWithSelection / strategyTotalQueries : 0,\n };\n });\n\n const totalQueries = Number(row?.total_queries || 0);\n const rewrittenQueries = Number(row?.rewritten_queries || 0);\n const rawQueries = Math.max(0, totalQueries - rewrittenQueries);\n const rewrittenQueriesWithSelection = Number(row?.rewritten_queries_with_selection || 0);\n const rawQueriesWithSelection = Number(row?.raw_queries_with_selection || 0);\n\n return {\n totalQueries,\n avgCandidateCount: Number(row?.avg_candidate_count || 0),\n avgSelectedCount: Number(row?.avg_selected_count || 0),\n selectionRate: Number(row?.selection_rate || 0),\n rewrittenQueries,\n rewriteRate: totalQueries > 0 ? rewrittenQueries / totalQueries : 0,\n rewrittenQueriesWithSelection,\n rawQueriesWithSelection,\n rewrittenSelectionRate: rewrittenQueries > 0 ? rewrittenQueriesWithSelection / rewrittenQueries : 0,\n rawSelectionRate: rawQueries > 0 ? rawQueriesWithSelection / rawQueries : 0,\n avgSelectedCountForRewrittenQueries: Number(row?.avg_selected_count_for_rewritten_queries || 0),\n avgSelectedCountForRawQueries: Number(row?.avg_selected_count_for_raw_queries || 0),\n strategyBreakdown,\n };\n } catch (err: any) {\n if (err?.message?.includes('no such table')) {\n return {\n totalQueries: 0,\n avgCandidateCount: 0,\n avgSelectedCount: 0,\n selectionRate: 0,\n rewrittenQueries: 0,\n rewriteRate: 0,\n rewrittenQueriesWithSelection: 0,\n rawQueriesWithSelection: 0,\n rewrittenSelectionRate: 0,\n rawSelectionRate: 0,\n avgSelectedCountForRewrittenQueries: 0,\n avgSelectedCountForRawQueries: 0,\n strategyBreakdown: [],\n };\n }\n throw err;\n }\n }\n\n /**\n * Close database connection\n */\n async close(): Promise<void> {\n sqliteClose(this.db);\n }\n\n /**\n * Get events grouped by turn_id for a session\n * Returns turns ordered by first event timestamp (newest first)\n */\n async getSessionTurns(sessionId: string, options?: { limit?: number; offset?: number } & QuarantineReadOptions): Promise<Array<{\n turnId: string;\n events: MemoryEvent[];\n startedAt: Date;\n promptPreview: string;\n eventCount: number;\n toolCount: number;\n hasResponse: boolean;\n }>> {\n await this.initialize();\n\n const limit = options?.limit || 20;\n const offset = options?.offset || 0;\n\n // Get distinct turn_ids for this session, ordered by first event timestamp\n const turnRows = sqliteAll<{ turn_id: string; min_ts: string }>(\n this.db,\n `SELECT turn_id, MIN(timestamp) as min_ts\n FROM events\n WHERE session_id = ? AND turn_id IS NOT NULL\n AND ${maybeQuarantinePredicate(options)}\n GROUP BY turn_id\n ORDER BY min_ts DESC\n LIMIT ? OFFSET ?`,\n [sessionId, limit, offset]\n );\n\n const turns: Array<{\n turnId: string;\n events: MemoryEvent[];\n startedAt: Date;\n promptPreview: string;\n eventCount: number;\n toolCount: number;\n hasResponse: boolean;\n }> = [];\n\n for (const turnRow of turnRows) {\n const events = await this.getEventsByTurn(turnRow.turn_id, options);\n\n const promptEvent = events.find(e => e.eventType === 'user_prompt');\n const toolEvents = events.filter(e => e.eventType === 'tool_observation');\n const hasResponse = events.some(e => e.eventType === 'agent_response');\n\n turns.push({\n turnId: turnRow.turn_id,\n events,\n startedAt: toDateFromSQLite(turnRow.min_ts),\n promptPreview: promptEvent\n ? promptEvent.content.slice(0, 200) + (promptEvent.content.length > 200 ? '...' : '')\n : '(no prompt)',\n eventCount: events.length,\n toolCount: toolEvents.length,\n hasResponse\n });\n }\n\n return turns;\n }\n\n /**\n * Get all events for a specific turn_id\n */\n async getEventsByTurn(turnId: string, options?: QuarantineReadOptions): Promise<MemoryEvent[]> {\n await this.initialize();\n\n const rows = sqliteAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM events WHERE turn_id = ? AND ${maybeQuarantinePredicate(options)} ORDER BY timestamp ASC`,\n [turnId]\n );\n\n return rows.map(this.rowToEvent);\n }\n\n /**\n * Count total turns for a session\n */\n async countSessionTurns(sessionId: string, options?: QuarantineReadOptions): Promise<number> {\n await this.initialize();\n\n const row = sqliteGet<{ count: number }>(\n this.db,\n `SELECT COUNT(DISTINCT turn_id) as count\n FROM events\n WHERE session_id = ? AND turn_id IS NOT NULL\n AND ${maybeQuarantinePredicate(options)}`,\n [sessionId]\n );\n\n return row?.count || 0;\n }\n\n /**\n * Migrate existing events: backfill turn_id for events that have turnId in metadata\n * but no turn_id column value (for events stored before this migration)\n */\n async backfillTurnIds(): Promise<number> {\n await this.initialize();\n\n // Find events with turnId in metadata JSON but no turn_id column value\n const rows = sqliteAll<{ id: string; metadata: string }>(\n this.db,\n `SELECT id, metadata FROM events\n WHERE turn_id IS NULL AND metadata IS NOT NULL AND metadata LIKE '%turnId%'`\n );\n\n let updated = 0;\n for (const row of rows) {\n try {\n const metadata = JSON.parse(row.metadata);\n if (metadata.turnId) {\n sqliteRun(\n this.db,\n `UPDATE events SET turn_id = ? WHERE id = ?`,\n [metadata.turnId, row.id]\n );\n updated++;\n }\n } catch {\n // Skip rows with invalid JSON\n }\n }\n\n return updated;\n }\n\n /**\n * Delete a single event and everything keyed to it.\n *\n * Deliberately NOT sharing an implementation with `deleteSessionEvents`: that one deletes\n * by `session_id` so it is independent of how many events the session holds, while this one\n * keys on the id. Folding them into one id-list delete would expose the session path to the\n * SQL variable limit and break large sessions.\n *\n * The trigger-drop -> delete -> FTS-rebuild sequence is the same as the session delete and\n * for the same reason: the synthetic FTS delete can fail (`no such column: T.event_id`) on\n * older migrated tables and risks SQLITE_CORRUPT_VTAB. Running it inside a transaction means\n * a failure rolls back instead of leaving the index permanently desynced from its triggers.\n *\n * Returns whether a row was actually removed, so callers can answer 404 for unknown ids.\n * Vectors live in LanceDB and are not touched here \u2014 callers that need them gone must also\n * call `VectorStore.deleteEventEverywhere` (see the CLI redact path).\n */\n async deleteEventById(eventId: string): Promise<boolean> {\n await this.initialize();\n\n const relatedTables = ['event_dedup', 'memory_levels', 'embedding_queue', 'embedding_outbox', 'vector_outbox', 'event_citations']\n .filter((table) => this.hasTable(table) && this.hasTableColumn(table, 'event_id'));\n\n const runDelete = this.db.transaction((): number => {\n for (const triggerName of ['events_fts_delete', 'events_fts_update', 'events_fts_insert']) {\n sqliteRun(this.db, `DROP TRIGGER IF EXISTS ${triggerName}`);\n }\n\n for (const table of relatedTables) {\n sqliteRun(this.db, `DELETE FROM ${table} WHERE event_id = ?`, [eventId]);\n }\n\n const result = sqliteRun(this.db, `DELETE FROM events WHERE id = ?`, [eventId]);\n\n this.recreateEventsFtsTable();\n\n return result.changes || 0;\n });\n\n return runDelete() > 0;\n }\n\n /**\n * Delete all events for a session (for force reimport)\n */\n async deleteSessionEvents(sessionId: string): Promise<number> {\n await this.initialize();\n\n // Get event IDs first for cascading deletes\n const events = sqliteAll<{ id: string }>(\n this.db,\n `SELECT id FROM events WHERE session_id = ?`,\n [sessionId]\n );\n\n if (events.length === 0) return 0;\n\n const eventIds = events.map(e => e.id);\n const placeholders = eventIds.map(() => '?').join(',');\n\n // Run the trigger-drop -> delete -> FTS-rebuild -> trigger-recreate sequence\n // atomically. Outside a transaction, a crash or error after the triggers are\n // dropped would permanently desync the FTS index, so keyword search would\n // silently return stale results forever. Inside a transaction any failure\n // rolls back and the triggers/index stay consistent. We pre-check optional\n // table existence (instead of swallowing per-statement errors) so a genuine\n // failure is never mistaken for a benign \"table does not exist\".\n // Only the tables that both exist and key cascades on event_id. (vector_outbox\n // keys on item_id, not event_id; the previous code swallowed the resulting\n // error, so it was never cleaned here either \u2014 behavior preserved.)\n const relatedTables = ['event_dedup', 'memory_levels', 'embedding_queue', 'embedding_outbox', 'vector_outbox', 'event_citations']\n .filter((table) => this.hasTable(table) && this.hasTableColumn(table, 'event_id'));\n\n const runDelete = this.db.transaction((): number => {\n // Drop FTS sync triggers before the bulk delete so the synthetic FTS\n // delete (which can fail with `no such column: T.event_id` on older\n // migrated tables, and risks SQLITE_CORRUPT_VTAB) never fires mid-delete.\n for (const triggerName of ['events_fts_delete', 'events_fts_update', 'events_fts_insert']) {\n sqliteRun(this.db, `DROP TRIGGER IF EXISTS ${triggerName}`);\n }\n\n // Delete from related tables first.\n for (const table of relatedTables) {\n sqliteRun(this.db, `DELETE FROM ${table} WHERE event_id IN (${placeholders})`, eventIds);\n }\n\n // Delete events.\n const result = sqliteRun(this.db, `DELETE FROM events WHERE session_id = ?`, [sessionId]);\n\n // Recreate the FTS table + triggers from the remaining events. A failure\n // here aborts the whole transaction rather than leaving the index desynced\n // with its triggers permanently dropped.\n this.recreateEventsFtsTable();\n\n return result.changes || 0;\n });\n\n return runDelete();\n }\n\n /**\n * Convert database row to MemoryEvent\n */\n private rowToEvent(row: Record<string, unknown>): MemoryEvent {\n const event: any = {\n id: row.id as string,\n eventType: row.event_type as 'user_prompt' | 'agent_response' | 'session_summary',\n sessionId: row.session_id as string,\n timestamp: toDateFromSQLite(row.timestamp),\n content: row.content as string,\n canonicalKey: row.canonical_key as string,\n dedupeKey: row.dedupe_key as string,\n metadata: safeParseMetadataValue(row.metadata)\n };\n\n // Include access tracking fields if present\n if (row.access_count !== undefined) {\n event.access_count = row.access_count;\n }\n if (row.last_accessed_at !== undefined) {\n event.last_accessed_at = row.last_accessed_at;\n }\n // Include turn_id if present\n if (row.turn_id !== undefined && row.turn_id !== null) {\n event.turn_id = row.turn_id;\n }\n\n return event;\n }\n}\n", "/**\n * AXIOMMIND canonical_key.py port\n * Deterministic normalization ensuring identical titles always map to same keys\n */\n\nimport { createHash } from 'crypto';\n\nconst MAX_KEY_LENGTH = 200;\n\n/**\n * Convert text to a normalized canonical key\n *\n * Normalization steps:\n * 1. NFKC unicode normalization\n * 2. Lowercase conversion\n * 3. Punctuation removal\n * 4. Consecutive whitespace cleanup\n * 5. Context addition (optional)\n * 6. Long key truncation with MD5\n */\nexport function makeCanonicalKey(\n title: string,\n context?: { project?: string; sessionId?: string }\n): string {\n // Step 1: NFKC normalization\n let normalized = title.normalize('NFKC');\n\n // Step 2: Lowercase conversion\n normalized = normalized.toLowerCase();\n\n // Step 3: Punctuation removal (unicode compatible)\n normalized = normalized.replace(/[^\\p{L}\\p{N}\\s]/gu, '');\n\n // Step 4: Consecutive whitespace cleanup\n normalized = normalized.replace(/\\s+/g, ' ').trim();\n\n // Step 5: Context addition\n let key = normalized;\n if (context?.project) {\n key = `${context.project}::${key}`;\n }\n\n // Step 6: Long key handling\n if (key.length > MAX_KEY_LENGTH) {\n const hashSuffix = createHash('md5').update(key).digest('hex').slice(0, 8);\n key = key.slice(0, MAX_KEY_LENGTH - 9) + '_' + hashSuffix;\n }\n\n return key;\n}\n\n/**\n * Check if two texts have the same canonical key\n */\nexport function isSameCanonicalKey(a: string, b: string): boolean {\n return makeCanonicalKey(a) === makeCanonicalKey(b);\n}\n\n/**\n * Generate dedupe key (content + session for uniqueness)\n * AXIOMMIND Principle 3: Idempotency guarantee\n */\nexport function makeDedupeKey(content: string, sessionId: string): string {\n const contentHash = createHash('sha256').update(content).digest('hex');\n return `${sessionId}:${contentHash}`;\n}\n\n/**\n * Generate content hash for deduplication\n */\nexport function hashContent(content: string): string {\n return createHash('sha256').update(content).digest('hex');\n}\n\n// ============================================================\n// Entity Canonical Keys (Task Entity System)\n// ============================================================\n\nexport type EntityKeyType = 'task' | 'condition' | 'artifact' | 'source_file';\n\n/**\n * Normalize text for entity key generation\n */\nfunction normalizeForKey(text: string): string {\n return text\n .normalize('NFKC')\n .toLowerCase()\n .replace(/[^\\p{L}\\p{N}\\s]/gu, '')\n .replace(/\\s+/g, '_')\n .trim();\n}\n\n/**\n * Generate canonical key for entities\n * Format: {type}:{project}:{normalized_identifier}\n */\nexport function makeEntityCanonicalKey(\n entityType: EntityKeyType,\n identifier: string,\n context?: { project?: string }\n): string {\n const project = context?.project ?? 'default';\n\n switch (entityType) {\n case 'task':\n return `task:${project}:${normalizeForKey(identifier)}`;\n case 'condition':\n return `cond:${project}:${normalizeForKey(identifier)}`;\n case 'artifact':\n return makeArtifactKey(identifier);\n case 'source_file':\n return makeSourceFileKey(identifier, project);\n }\n}\n\n/**\n * Canonical key for a source file entity, scoped by project so the same\n * relative path in two different projects doesn't collide.\n * Format: file:{project}:{sha1(normalized_relative_path)}\n */\nexport function makeSourceFileKey(filePath: string, project = 'default'): string {\n const normalized = normalizeFilePath(filePath);\n const hash = createHash('sha1').update(normalized).digest('hex').slice(0, 16);\n return `file:${project}:${hash}`;\n}\n\n/**\n * Normalize a file path for stable identity across sessions:\n * backslashes to forward slashes, no leading \"./\", no trailing slash.\n */\nexport function normalizeFilePath(filePath: string): string {\n return filePath\n .replace(/\\\\/g, '/')\n .replace(/^\\.\\//, '')\n .replace(/\\/+$/, '');\n}\n\n/**\n * Generate canonical key for artifacts based on identifier pattern\n * - URL: art:url:{sha1(url)}\n * - JIRA key: art:jira:{key}\n * - GitHub issue: art:gh_issue:{repo}:{num}\n * - Generic: art:generic:{sha1(identifier)}\n */\nexport function makeArtifactKey(identifier: string): string {\n // URL pattern\n if (/^https?:\\/\\//.test(identifier)) {\n const hash = createHash('sha1').update(identifier).digest('hex').slice(0, 12);\n return `art:url:${hash}`;\n }\n\n // JIRA key pattern (e.g., PROJ-123)\n const jiraMatch = identifier.match(/^([A-Z]+-\\d+)$/);\n if (jiraMatch) {\n return `art:jira:${jiraMatch[1].toLowerCase()}`;\n }\n\n // GitHub issue pattern (e.g., owner/repo#123)\n const ghMatch = identifier.match(/^([^\\/]+\\/[^#]+)#(\\d+)$/);\n if (ghMatch) {\n return `art:gh_issue:${ghMatch[1]}:${ghMatch[2]}`;\n }\n\n // Generic identifier\n const hash = createHash('sha1').update(identifier).digest('hex').slice(0, 12);\n return `art:generic:${hash}`;\n}\n\n/**\n * Generate dedupe key for task events\n */\nexport function makeTaskEventDedupeKey(\n eventType: string,\n taskId: string,\n sessionId: string,\n additionalContext?: string\n): string {\n const parts = [eventType, taskId, sessionId];\n if (additionalContext) {\n parts.push(additionalContext);\n }\n const combined = parts.join(':');\n return createHash('sha256').update(combined).digest('hex');\n}\n\n/**\n * Parse entity canonical key to extract type and identifier\n */\nexport function parseEntityCanonicalKey(canonicalKey: string): {\n entityType: EntityKeyType;\n project?: string;\n identifier: string;\n} | null {\n const taskMatch = canonicalKey.match(/^task:([^:]+):(.+)$/);\n if (taskMatch) {\n return { entityType: 'task', project: taskMatch[1], identifier: taskMatch[2] };\n }\n\n const condMatch = canonicalKey.match(/^cond:([^:]+):(.+)$/);\n if (condMatch) {\n return { entityType: 'condition', project: condMatch[1], identifier: condMatch[2] };\n }\n\n const artMatch = canonicalKey.match(/^art:([^:]+):(.+)$/);\n if (artMatch) {\n return { entityType: 'artifact', identifier: artMatch[2] };\n }\n\n return null;\n}\n", "/**\n * Citation Generator\n * Generates unique, short citation IDs for memory references\n */\n\nimport { createHash } from 'crypto';\n\nconst ID_LENGTH = 6;\nconst CHARSET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n\n/**\n * Generate a citation ID from an event ID using SHA256\n */\nexport function generateCitationId(eventId: string): string {\n const hash = createHash('sha256')\n .update(eventId)\n .digest();\n\n let id = '';\n for (let i = 0; i < ID_LENGTH; i++) {\n id += CHARSET[hash[i] % CHARSET.length];\n }\n\n return id;\n}\n\n/**\n * Generate a unique citation ID with collision handling\n */\nexport async function generateUniqueCitationId(\n eventId: string,\n existsCheck: (id: string) => Promise<boolean>\n): Promise<string> {\n let id = generateCitationId(eventId);\n let attempt = 0;\n\n while (await existsCheck(id) && attempt < 10) {\n // Add salt and regenerate\n id = generateCitationId(`${eventId}:${attempt}`);\n attempt++;\n }\n\n if (attempt >= 10) {\n throw new Error('Failed to generate unique citation ID after 10 attempts');\n }\n\n return id;\n}\n\n/**\n * Format a citation ID for display\n */\nexport function formatCitationId(citationId: string): string {\n return `[mem:${citationId}]`;\n}\n\n/**\n * Parse a citation ID from formatted string\n */\nexport function parseCitationId(formatted: string): string | null {\n const match = formatted.match(/\\[?mem:([A-Za-z0-9]{6})\\]?/);\n return match ? match[1] : null;\n}\n", "/**\n * Project path registry utilities.\n *\n * These helpers are intentionally core-level and Claude-agnostic.\n */\n\nimport * as crypto from 'crypto';\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\n\nimport { runGit } from './git-utils.js';\n\n/**\n * Normalize and resolve a project path, handling symlinks when possible.\n */\nexport function normalizeProjectPath(projectPath: string): string {\n const expanded = projectPath.startsWith('~')\n ? path.join(os.homedir(), projectPath.slice(1))\n : projectPath;\n\n try {\n return fs.realpathSync(expanded);\n } catch {\n return path.resolve(expanded);\n }\n}\n\n/**\n * Cache of hash basis per normalized path. Git layout does not change within a\n * process run; a marker file can (the README tells users to `touch` it), so a\n * long-lived process (MCP server, dashboard) picks a new marker up only after\n * restart. Hooks are fresh processes and see it immediately.\n */\nconst hashBasisCache = new Map<string, string>();\n\n/**\n * Explicit convergence marker. A workspace product that creates one directory\n * per chat/instance (each often its own git repository) can drop this file at\n * the workspace root so every path beneath it shares one store. Without it,\n * each instance hashes to its own cold store and memory never accumulates\n * across instances.\n */\nexport const MEMORY_ROOT_MARKER = '.claude-memory-root';\n\n/**\n * The marker must be a regular file. A directory of the same name is ignored,\n * and an unreadable path (EACCES on a TCC-protected ancestor, a flaky mount)\n * degrades to \"no marker\" rather than failing resolution.\n */\nfunction markerFileExists(markerPath: string): boolean {\n try {\n return fs.statSync(markerPath, { throwIfNoEntry: false })?.isFile() ?? false;\n } catch {\n return false;\n }\n}\n\n/**\n * Find the nearest ancestor (including the directory itself) that carries the\n * convergence marker. Nearest wins so a nested workspace stays separate from\n * an outer one. Returns null when no marker exists \u2014 the common case, which\n * keeps default behavior untouched.\n *\n * The walk never accepts a marker at the home directory, the system temp\n * directory, or the filesystem root: a stray marker there would silently\n * collapse every project on the machine (or, for the world-writable temp\n * root, let any local process converge other users' temp projects) into one\n * store. Markers strictly below those ceilings are honored.\n */\nfunction findMemoryRootMarker(startDir: string): string | null {\n const ceilings = new Set([\n normalizeProjectPath(os.homedir()),\n normalizeProjectPath(os.tmpdir())\n ]);\n\n let current = startDir;\n for (;;) {\n if (ceilings.has(current) || path.dirname(current) === current) return null;\n if (markerFileExists(path.join(current, MEMORY_ROOT_MARKER))) return current;\n current = path.dirname(current);\n }\n}\n\nfunction computeHashBasisPath(normalizedPath: string): string {\n // Git convergence runs first, then the marker walk starts from the\n // git-resolved basis. This ordering is load-bearing three ways: a worktree\n // checked out outside the marker tree still reaches the marker through its\n // main checkout; a marker committed into a repository (and therefore\n // materialized in every worktree checkout) resolves to the main checkout\n // root instead of splitting each worktree onto a cold store; and a marker\n // in a repository subdirectory cannot detach that subtree from the store\n // the repository has been accumulating. The marker still outranks an\n // instance's *own* .git \u2014 the git basis of such an instance is its checkout\n // root, and the walk climbs from there to the workspace marker above it.\n const gitBasis = resolveGitBasisPath(normalizedPath);\n const markerRoot = findMemoryRootMarker(gitBasis);\n // Re-normalized because the basis may come from the plain path.resolve\n // fallback when the directory does not exist yet, so an existing ancestor\n // carrying the marker can still contain unresolved symlinks.\n return markerRoot !== null ? normalizeProjectPath(markerRoot) : gitBasis;\n}\n\n/** Cache of git-only basis per normalized path, shared by the marker-aware and marker-ignoring resolvers so the git spawn happens once. */\nconst gitBasisCache = new Map<string, string>();\n\nfunction resolveGitBasisPath(normalizedPath: string): string {\n const cached = gitBasisCache.get(normalizedPath);\n if (cached !== undefined) return cached;\n\n const basis = computeGitBasisPath(normalizedPath);\n boundedCacheSet(gitBasisCache, normalizedPath, basis);\n return basis;\n}\n\nfunction computeGitBasisPath(normalizedPath: string): string {\n // One spawn for both values: resolution runs in every short-lived hook\n // process and the git spawn dominates its cost. rev-parse prints results in\n // flag order. A bare repo (a common dir but no work tree) fails\n // --show-toplevel and with it the whole command \u2014 same outcome as the\n // previous separate guard: such a path keeps hashing to itself.\n const output = runGit(normalizedPath, ['rev-parse', '--git-common-dir', '--show-toplevel']);\n if (!output) return normalizedPath;\n const [commonDir, toplevel] = output.split('\\n').map((line) => line.trim());\n if (!commonDir || !toplevel) return normalizedPath;\n\n const absoluteCommonDir = path.isAbsolute(commonDir)\n ? commonDir\n : path.resolve(normalizedPath, commonDir);\n if (path.basename(absoluteCommonDir) !== '.git') return normalizedPath;\n const mainCheckoutRoot = normalizeProjectPath(path.dirname(absoluteCommonDir));\n\n // Every path inside one repository resolves onto the checkout that owns the\n // shared .git \u2014 a worktree, the checkout root, or any subdirectory of it.\n //\n // The root itself already hashes to this value, so existing project hashes\n // are unchanged. Subdirectories converge onto it: a session started from a\n // monorepo package or a vendored tree used to get its own hash, and with it\n // a cold store no other session in the repository could read.\n //\n // A nested repository owns its own .git, so its common dir differs and it\n // stays separate rather than folding into the outer checkout.\n return mainCheckoutRoot;\n}\n\n/**\n * Resolve the path a project hash should be derived from, so that every path\n * belonging to one repository \u2014 worktree, checkout root, or subdirectory \u2014\n * hashes to the main checkout that owns the shared .git. Nested repositories\n * and non-git paths hash to themselves.\n */\nfunction resolveHashBasisPath(normalizedPath: string): string {\n const cached = hashBasisCache.get(normalizedPath);\n if (cached !== undefined) return cached;\n\n const basis = computeHashBasisPath(normalizedPath);\n boundedCacheSet(hashBasisCache, normalizedPath, basis);\n return basis;\n}\n\n/**\n * Long-lived servers hash caller-supplied project strings, so the caches are\n * capped: past the cap they reset rather than grow for the process lifetime.\n * The working set is a handful of project roots, so a reset is a few extra\n * git spawns, not a correctness event.\n */\nconst MAX_PATH_CACHE_ENTRIES = 1_024;\n\nfunction boundedCacheSet(cache: Map<string, string>, key: string, value: string): void {\n if (cache.size >= MAX_PATH_CACHE_ENTRIES) cache.clear();\n cache.set(key, value);\n}\n\n/**\n * Resolve the durable on-disk anchor for per-project artifacts (e.g. the\n * markdown mirror): worktrees and subdirectories anchor onto the main checkout\n * they share a .git with, so artifacts survive worktree removal and land where\n * the project hash already points. Nested repositories and non-git paths\n * anchor onto themselves.\n */\nexport function resolveProjectAnchorPath(projectPath: string): string {\n return resolveHashBasisPath(normalizeProjectPath(projectPath));\n}\n\nfunction hashBasis(basis: string): string {\n return crypto.createHash('sha256')\n .update(basis)\n .digest('hex')\n .slice(0, 8);\n}\n\n/**\n * Generate a stable 8-character hash from a normalized project path.\n */\nexport function hashProjectPath(projectPath: string): string {\n return hashBasis(resolveHashBasisPath(normalizeProjectPath(projectPath)));\n}\n\n/**\n * The hash this path had before any .claude-memory-root marker applied: git\n * convergence only. A store created before a marker was adopted is keyed by\n * exactly this value, so repair and identity tooling use it to tell \"the hash\n * basis changed when the marker arrived\" apart from genuine cross-project\n * contamination.\n */\nexport function hashProjectPathIgnoringMarker(projectPath: string): string {\n return hashBasis(resolveGitBasisPath(normalizeProjectPath(projectPath)));\n}\n\n/**\n * The marker directory governing this path (via its git-resolved basis), or\n * null when no marker applies. Diagnostics use it to show *why* a path\n * converged where it did.\n */\nexport function resolveMemoryRootMarkerPath(projectPath: string): string | null {\n const gitBasis = resolveGitBasisPath(normalizeProjectPath(projectPath));\n const markerRoot = findMemoryRootMarker(gitBasis);\n return markerRoot !== null ? normalizeProjectPath(markerRoot) : null;\n}\n\n/**\n * Get the storage path for a project-local memory database.\n */\nexport function getProjectStoragePath(projectPath: string): string {\n const hash = hashProjectPath(projectPath);\n return path.join(os.homedir(), '.claude-code', 'memory', 'projects', hash);\n}\n\n/**\n * Resolve either an explicit project hash or a project path into a storage path.\n */\nexport function resolveProjectStoragePath(projectOrHash: string): string {\n const isHash = /^[a-f0-9]{8}$/.test(projectOrHash);\n return isHash\n ? path.join(os.homedir(), '.claude-code', 'memory', 'projects', projectOrHash)\n : getProjectStoragePath(projectOrHash);\n}\n", "/**\n * Low-level git helpers shared by project identity resolvers.\n */\n\nimport { execFileSync } from 'node:child_process';\n\n/**\n * These take precedence over `-C <dir>`, so an inherited value would silently\n * resolve a different repository than the one being asked about.\n */\nconst REPO_OVERRIDING_GIT_ENV = ['GIT_DIR', 'GIT_WORK_TREE', 'GIT_COMMON_DIR'];\n\n/** Run a read-only git command in the given directory. Returns trimmed stdout, or null on any failure. */\nexport function runGit(projectPath: string, args: string[]): string | null {\n const env = { ...process.env };\n for (const key of REPO_OVERRIDING_GIT_ENV) delete env[key];\n\n try {\n const output = execFileSync('git', ['-C', projectPath, ...args], {\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n timeout: 1_000,\n env\n }).trim();\n return output || null;\n } catch {\n return null;\n }\n}\n", "import * as fs from 'fs/promises';\nimport * as path from 'path';\nimport type { MemoryEvent } from './types.js';\n\nconst DEFAULT_NAMESPACE = 'default';\nconst DEFAULT_CATEGORY = 'uncategorized';\n\nexport function sanitizeSegment(input: unknown, fallback: string): string {\n const raw = String(input ?? '').trim().toLowerCase();\n const safe = raw\n .normalize('NFKD')\n .replace(/[^a-z0-9_-]+/g, '-')\n .replace(/^-+|-+$/g, '');\n\n if (!safe || safe === '.' || safe === '..') return fallback;\n return safe;\n}\n\nfunction getCategorySegments(metadata: Record<string, unknown> | undefined, eventType: string): string[] {\n const raw = metadata?.categoryPath;\n if (Array.isArray(raw) && raw.length > 0) {\n return raw.map((s) => sanitizeSegment(s, DEFAULT_CATEGORY));\n }\n const single = metadata?.category;\n if (typeof single === 'string' && single.trim()) {\n return [sanitizeSegment(single, DEFAULT_CATEGORY)];\n }\n return [sanitizeSegment(eventType, DEFAULT_CATEGORY)];\n}\n\nexport function buildMirrorPath(rootDir: string, event: MemoryEvent): string {\n const metadata = event.metadata as Record<string, unknown> | undefined;\n const namespace = sanitizeSegment(metadata?.namespace, DEFAULT_NAMESPACE);\n const categories = getCategorySegments(metadata, event.eventType);\n\n const d = event.timestamp;\n const yyyy = d.getFullYear();\n const mm = String(d.getMonth() + 1).padStart(2, '0');\n const dd = String(d.getDate()).padStart(2, '0');\n\n return path.join(rootDir, 'memory', namespace, ...categories, `${yyyy}-${mm}-${dd}.md`);\n}\n\nexport function formatMirrorEntry(event: MemoryEvent): string {\n const category = Array.isArray((event.metadata as any)?.categoryPath)\n ? ((event.metadata as any).categoryPath as unknown[]).join('/')\n : String((event.metadata as any)?.category ?? event.eventType);\n\n return [\n '',\n `- ts: ${event.timestamp.toISOString()}`,\n ` id: ${event.id}`,\n ` type: ${event.eventType}`,\n ` session: ${event.sessionId}`,\n ` category: ${category}`,\n ' content: |',\n ...event.content.split('\\n').map((line) => ` ${line}`)\n ].join('\\n') + '\\n';\n}\n\nexport class MarkdownMirror {\n constructor(private readonly rootDir: string) {}\n\n async append(event: MemoryEvent): Promise<string> {\n const outPath = buildMirrorPath(this.rootDir, event);\n await fs.mkdir(path.dirname(outPath), { recursive: true });\n await fs.appendFile(outPath, formatMirrorEntry(event), 'utf8');\n return outPath;\n }\n}\n", "/**\n * SQLite Database Wrapper\n * Provides Promise-based interface over better-sqlite3 synchronous API\n */\n\nimport BetterSqlite3 from 'better-sqlite3';\n\nexport type Database = BetterSqlite3.Database;\n\n/**\n * Safely converts a value to a Date object\n */\nexport function toDate(value: unknown): Date {\n if (value instanceof Date) return value;\n if (typeof value === 'string') return new Date(value);\n if (typeof value === 'number') return new Date(value);\n return new Date(String(value));\n}\n\nexport interface DatabaseOptions {\n readOnly?: boolean;\n}\n\n/**\n * Creates a new SQLite database connection.\n *\n * Applies the same connection pragmas as the primary sqlite-wrapper so handles\n * opened here don't fall back to rollback-journal mode with a 0ms busy timeout \u2014\n * which would throw SQLITE_BUSY the instant another process (vector worker,\n * mongo sync, or a second handle to the same file) holds a write lock.\n */\nexport function createDatabase(dbPath: string, options?: DatabaseOptions): Database {\n const db = new BetterSqlite3(dbPath, { readonly: options?.readOnly ?? false });\n db.pragma('busy_timeout = 5000');\n if (!options?.readOnly) {\n db.pragma('journal_mode = WAL');\n db.pragma('synchronous = NORMAL');\n }\n return db;\n}\n\n/**\n * Executes a statement that doesn't return rows\n */\nexport function dbRun(db: Database, sql: string, params: unknown[] = []): Promise<void> {\n db.prepare(sql).run(...(params as never[]));\n return Promise.resolve();\n}\n\n/**\n * Executes a query and returns all rows\n */\nexport function dbAll<T = Record<string, unknown>>(\n db: Database,\n sql: string,\n params: unknown[] = []\n): Promise<T[]> {\n return Promise.resolve(db.prepare(sql).all(...(params as never[])) as T[]);\n}\n\n/**\n * Closes the database connection\n */\nexport function dbClose(db: Database): Promise<void> {\n db.close();\n return Promise.resolve();\n}\n\n/**\n * Executes multiple statements\n */\nexport function dbExec(db: Database, sql: string): Promise<void> {\n db.exec(sql);\n return Promise.resolve();\n}\n", "/**\n * Vector Outbox V2 - Transactional Outbox Pattern\n * AXIOMMIND Principle 6: DuckDB \u2192 outbox \u2192 LanceDB unidirectional flow\n */\n\nimport { dbRun, dbAll, toDate, type Database } from './db-wrapper.js';\nimport { randomUUID } from 'crypto';\nimport type {\n OutboxJob,\n OutboxStatus,\n OutboxItemKind\n} from './types.js';\n\nexport interface OutboxConfig {\n embeddingVersion: string;\n maxRetries: number;\n stuckThresholdMs: number;\n cleanupDays: number;\n}\n\nconst DEFAULT_CONFIG: OutboxConfig = {\n embeddingVersion: 'v1',\n maxRetries: 3,\n stuckThresholdMs: 5 * 60 * 1000, // 5 minutes\n cleanupDays: 7\n};\n\nexport interface OutboxMetrics {\n pendingCount: number;\n processingCount: number;\n doneCount: number;\n failedCount: number;\n oldestPendingAge: number | null;\n}\n\nfunction isRetryableLanceCommitConflict(error: string): boolean {\n const normalized = error.toLowerCase();\n return normalized.includes('lance')\n && normalized.includes('commit')\n && normalized.includes('conflict');\n}\n\nexport interface OutboxEnqueueInput {\n itemKind: OutboxItemKind;\n itemId: string;\n embeddingVersion?: string;\n}\n\nexport type EnqueueResult =\n | { success: true; jobId: string; isNew: boolean }\n | { success: false; error: string };\n\nexport class VectorOutbox {\n private config: OutboxConfig;\n\n constructor(\n private db: Database,\n config?: Partial<OutboxConfig>\n ) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n }\n\n /**\n * Enqueue item for vectorization (idempotent).\n * Returns the already-existing job id when the same item/version has been enqueued before.\n */\n enqueueSync(\n itemKind: OutboxItemKind,\n itemId: string,\n embeddingVersion?: string\n ): string {\n const result = this.enqueueWithResultSync({ itemKind, itemId, embeddingVersion });\n if (result.success === false) {\n throw new Error(result.error);\n }\n return result.jobId;\n }\n\n async enqueue(\n itemKind: OutboxItemKind,\n itemId: string,\n embeddingVersion?: string\n ): Promise<string> {\n return this.enqueueSync(itemKind, itemId, embeddingVersion);\n }\n\n enqueueBatchSync(inputs: OutboxEnqueueInput[]): EnqueueResult[] {\n return inputs.map((input) => this.enqueueWithResultSync(input));\n }\n\n async enqueueBatch(inputs: OutboxEnqueueInput[]): Promise<EnqueueResult[]> {\n return this.enqueueBatchSync(inputs);\n }\n\n enqueueWithResultSync(input: OutboxEnqueueInput): EnqueueResult {\n const version = input.embeddingVersion ?? this.config.embeddingVersion;\n const jobId = randomUUID();\n const now = new Date().toISOString();\n\n try {\n const result = this.db.prepare(`INSERT INTO vector_outbox (\n job_id, item_kind, item_id, embedding_version, status, retry_count, created_at, updated_at\n ) VALUES (?, ?, ?, ?, 'pending', 0, ?, ?)\n ON CONFLICT (item_kind, item_id, embedding_version) DO NOTHING`).run(\n jobId,\n input.itemKind,\n input.itemId,\n version,\n now,\n now\n );\n\n const row = this.db.prepare(`SELECT job_id FROM vector_outbox\n WHERE item_kind = ? AND item_id = ? AND embedding_version = ?`).get(\n input.itemKind,\n input.itemId,\n version\n ) as { job_id: string } | undefined;\n\n if (!row) {\n return { success: false, error: 'vector outbox enqueue did not create or find a job' };\n }\n\n return { success: true, jobId: row.job_id, isNew: Number(result.changes ?? 0) > 0 };\n } catch (error) {\n return { success: false, error: error instanceof Error ? error.message : String(error) };\n }\n }\n\n async enqueueWithResult(input: OutboxEnqueueInput): Promise<EnqueueResult> {\n return this.enqueueWithResultSync(input);\n }\n\n /**\n * Claim pending jobs for processing\n */\n async claimJobs(limit: number = 32): Promise<OutboxJob[]> {\n const now = new Date().toISOString();\n\n // Atomic claim using UPDATE RETURNING\n const rows = await dbAll<Record<string, unknown>>(\n this.db,\n `UPDATE vector_outbox\n SET status = 'processing', updated_at = ?\n WHERE job_id IN (\n SELECT job_id FROM vector_outbox\n WHERE status = 'pending'\n ORDER BY created_at ASC\n LIMIT ?\n )\n RETURNING *`,\n [now, limit]\n );\n\n return rows.map(row => this.rowToJob(row));\n }\n\n /**\n * Mark job as done\n */\n async markDone(jobId: string): Promise<void> {\n await dbRun(\n this.db,\n `UPDATE vector_outbox\n SET status = 'done', updated_at = ?\n WHERE job_id = ?`,\n [new Date().toISOString(), jobId]\n );\n }\n\n /**\n * Mark job as failed\n */\n async markFailed(jobId: string, error: string): Promise<void> {\n const now = new Date().toISOString();\n\n // Check retry count\n const rows = await dbAll<{ retry_count: number }>(\n this.db,\n `SELECT retry_count FROM vector_outbox WHERE job_id = ?`,\n [jobId]\n );\n\n if (rows.length === 0) return;\n\n const retryCount = rows[0].retry_count;\n\n if (isRetryableLanceCommitConflict(error)) {\n await dbRun(\n this.db,\n `UPDATE vector_outbox\n SET status = 'pending', error = ?, updated_at = ?\n WHERE job_id = ?`,\n [error, now, jobId]\n );\n return;\n }\n\n const newStatus: OutboxStatus = retryCount >= this.config.maxRetries - 1\n ? 'failed'\n : 'pending'; // Will retry\n\n await dbRun(\n this.db,\n `UPDATE vector_outbox\n SET status = ?, error = ?, retry_count = retry_count + 1, updated_at = ?\n WHERE job_id = ?`,\n [newStatus, error, now, jobId]\n );\n }\n\n /**\n * Get job by ID\n */\n async getJob(jobId: string): Promise<OutboxJob | null> {\n const rows = await dbAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM vector_outbox WHERE job_id = ?`,\n [jobId]\n );\n\n if (rows.length === 0) return null;\n return this.rowToJob(rows[0]);\n }\n\n /**\n * Get jobs by status\n */\n async getJobsByStatus(status: OutboxStatus, limit: number = 100): Promise<OutboxJob[]> {\n const rows = await dbAll<Record<string, unknown>>(\n this.db,\n `SELECT * FROM vector_outbox\n WHERE status = ?\n ORDER BY created_at ASC\n LIMIT ?`,\n [status, limit]\n );\n\n return rows.map(row => this.rowToJob(row));\n }\n\n /**\n * Reconcile: recover stuck and retry failed jobs\n */\n async reconcile(referenceTime: Date = new Date()): Promise<{ recovered: number; retried: number }> {\n const stuckThreshold = new Date(referenceTime.getTime() - this.config.stuckThresholdMs);\n const nowIso = referenceTime.toISOString();\n\n // Recover stuck processing jobs\n const recovered = this.db.prepare(`UPDATE vector_outbox\n SET status = 'pending', updated_at = ?, error = NULL\n WHERE status = 'processing'\n AND updated_at < ?`).run(nowIso, stuckThreshold.toISOString());\n\n // Retry failed jobs that haven't exceeded max retries\n const retried = this.db.prepare(`UPDATE vector_outbox\n SET status = 'pending', updated_at = ?, error = NULL\n WHERE status = 'failed'\n AND retry_count < ?`).run(nowIso, this.config.maxRetries);\n\n return {\n recovered: Number(recovered.changes ?? 0),\n retried: Number(retried.changes ?? 0)\n };\n }\n\n /**\n * Cleanup old done jobs\n */\n async cleanup(referenceTime: Date = new Date()): Promise<number> {\n const threshold = new Date(referenceTime.getTime() - this.config.cleanupDays * 24 * 60 * 60 * 1000);\n\n const result = this.db.prepare(`DELETE FROM vector_outbox\n WHERE status = 'done'\n AND updated_at < ?`).run(threshold.toISOString());\n\n return Number(result.changes ?? 0);\n }\n\n /**\n * Get metrics\n */\n async getMetrics(): Promise<OutboxMetrics> {\n const statusCounts = await dbAll<{ status: string; count: number }>(\n this.db,\n `SELECT status, COUNT(*) as count\n FROM vector_outbox\n GROUP BY status`\n );\n\n const oldestPending = await dbAll<{ created_at: string }>(\n this.db,\n `SELECT created_at FROM vector_outbox\n WHERE status = 'pending'\n ORDER BY created_at ASC\n LIMIT 1`\n );\n\n const metrics: OutboxMetrics = {\n pendingCount: 0,\n processingCount: 0,\n doneCount: 0,\n failedCount: 0,\n oldestPendingAge: null\n };\n\n for (const row of statusCounts) {\n switch (row.status) {\n case 'pending':\n metrics.pendingCount = Number(row.count);\n break;\n case 'processing':\n metrics.processingCount = Number(row.count);\n break;\n case 'done':\n metrics.doneCount = Number(row.count);\n break;\n case 'failed':\n metrics.failedCount = Number(row.count);\n break;\n }\n }\n\n if (oldestPending.length > 0) {\n const oldestDate = new Date(oldestPending[0].created_at);\n metrics.oldestPendingAge = Date.now() - oldestDate.getTime();\n }\n\n return metrics;\n }\n\n /**\n * Validate state transition\n */\n isValidTransition(from: OutboxStatus, to: OutboxStatus): boolean {\n const validTransitions = [\n { from: 'pending', to: 'processing' },\n { from: 'processing', to: 'done' },\n { from: 'processing', to: 'failed' },\n { from: 'failed', to: 'pending' }\n ];\n\n return validTransitions.some(t => t.from === from && t.to === to);\n }\n\n /**\n * Convert database row to OutboxJob\n */\n private rowToJob(row: Record<string, unknown>): OutboxJob {\n return {\n jobId: row.job_id as string,\n itemKind: row.item_kind as OutboxItemKind,\n itemId: row.item_id as string,\n embeddingVersion: row.embedding_version as string,\n status: row.status as OutboxStatus,\n retryCount: row.retry_count as number,\n error: row.error as string | undefined,\n createdAt: toDate(row.created_at),\n updatedAt: toDate(row.updated_at)\n };\n }\n}\n", "/**\n * Privacy-safe retrieval lane metadata helpers.\n *\n * Lane details are intended for trace/debug surfaces. Keep them compact,\n * allow-listed, and free of raw private paths or credential-shaped values.\n */\n\nexport const RETRIEVAL_DEBUG_LANE_NAMES = [\n 'raw_event',\n 'session_event',\n 'session_summary',\n 'graph_path',\n 'facet_match'\n] as const;\n\nexport type RetrievalDebugLaneName = typeof RETRIEVAL_DEBUG_LANE_NAMES[number];\n\nexport interface RetrievalDebugLane {\n lane: RetrievalDebugLaneName;\n reason: string;\n score?: number;\n}\n\nconst RETRIEVAL_DEBUG_LANE_NAME_SET = new Set<string>(RETRIEVAL_DEBUG_LANE_NAMES);\n\nexport function isRetrievalDebugLaneName(value: unknown): value is RetrievalDebugLaneName {\n return typeof value === 'string' && RETRIEVAL_DEBUG_LANE_NAME_SET.has(value);\n}\n\nexport function normalizeRetrievalDebugLanes(value: unknown, maxItems = 6): RetrievalDebugLane[] {\n if (!Array.isArray(value) || maxItems <= 0) return [];\n\n const normalized: RetrievalDebugLane[] = [];\n const seen = new Set<string>();\n for (const item of value) {\n const lane = normalizeRetrievalDebugLane(item);\n if (!lane) continue;\n const key = [lane.lane, lane.reason, lane.score ?? ''].join('\\u0000');\n if (seen.has(key)) continue;\n seen.add(key);\n normalized.push(lane);\n if (normalized.length >= maxItems) break;\n }\n return normalized;\n}\n\nexport function normalizeRetrievalDebugLane(value: unknown): RetrievalDebugLane | null {\n if (!value || typeof value !== 'object') return null;\n const raw = value as Record<string, unknown>;\n if (!isRetrievalDebugLaneName(raw.lane)) return null;\n\n const reason = sanitizeRetrievalLaneReason(typeof raw.reason === 'string' ? raw.reason : '') || 'unspecified';\n const score = typeof raw.score === 'number' && Number.isFinite(raw.score)\n ? Math.max(0, Math.min(1, raw.score))\n : undefined;\n\n return score === undefined\n ? { lane: raw.lane, reason }\n : { lane: raw.lane, reason, score };\n}\n\nexport function sanitizeRetrievalLaneReason(value: string): string {\n return value\n .replace(/[\\r\\n\\t]+/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim()\n .replace(/[A-Za-z]:[\\\\/][^\\s'\"`<>)]*/g, '[path]')\n .replace(/\\/(?:Users|home|tmp|var\\/folders)\\/[^\\s'\"`<>)]*/g, '[path]')\n .replace(/\\\\\\\\[^\\s'\"`<>)]*/g, '[path]')\n .replace(/\\bBearer\\s+[^\\s'\"`,;]{6,}/gi, 'Bearer [REDACTED]')\n .replace(\n /([\"']?\\b(?:api[_-]?key|access[_-]?token|refresh[_-]?token|client[_-]?secret|token|secret|password|passwd|credential)[\"']?\\s*[:=]\\s*[\"']?)[^\\s\"'`,;}]{6,}/gi,\n '$1[REDACTED]'\n )\n .replace(\n /\\b(?:gh[pousr]_[A-Za-z0-9_]{8,}|github_pat_[A-Za-z0-9_]{8,}|glpat-[A-Za-z0-9_-]{8,}|xox[a-z]-[A-Za-z0-9-]{8,}|(?:AKIA|ASIA)[A-Z0-9]{12,}|AIza[0-9A-Za-z_-]{20,}|ya29\\.[0-9A-Za-z_-]+|sk-[A-Za-z0-9_-]{12,})\\b/g,\n '[REDACTED]'\n )\n .slice(0, 120);\n}\n", "/**\n * Usefulness Evidence\n *\n * Pure content-grounding analysis between an injected memory and the\n * assistant responses that followed it. Answers \"did the answer actually\n * use this memory?\" with a 0..1 grounding score plus the matched snippet\n * pairs that justify it, so the dashboard can show evidence per question.\n *\n * Handles both space-delimited text and CJK-heavy text (character bigrams).\n */\n\nexport interface ResponseDocument {\n id: string;\n content: string;\n}\n\nexport interface EvidenceMatch {\n /** Snippet of the memory that was found in a response */\n memorySnippet: string;\n /** The region of the response where the match occurred */\n responseSnippet: string;\n /** Event id of the matching agent_response */\n responseEventId: string;\n /** 0..1 similarity of this snippet match */\n similarity: number;\n matchType: 'exact' | 'term-overlap';\n}\n\nexport interface MemoryUsageEvidence {\n /** 0..1 \u2014 how strongly the responses are grounded in this memory */\n contentOverlapScore: number;\n /** Fraction of memory snippets that matched some response (0..1) */\n coverage: number;\n /** Best matches, strongest first */\n matches: EvidenceMatch[];\n}\n\nconst MAX_SNIPPETS = 40;\nconst MAX_MATCHES = 5;\nconst MIN_SNIPPET_LENGTH = 12;\nconst MAX_SNIPPET_LENGTH = 300;\nconst RESPONSE_CONTEXT_CHARS = 160;\nconst STRONG_MATCH_THRESHOLD = 0.55;\n// A snippet must carry at least this many informative tokens before any\n// match counts as evidence \u2014 otherwise a single generic word shared with the\n// answer (e.g. a \"## Configuration\" heading) scores as full grounding.\nconst MIN_SNIPPET_TOKENS = 3;\n\n/** Words too generic to signal grounding on their own. */\nconst STOP_TOKENS = new Set([\n 'the', 'and', 'for', 'that', 'this', 'with', 'from', 'have', 'has',\n 'was', 'were', 'are', 'not', 'but', 'you', 'your', 'can', 'will',\n 'should', 'would', 'could', 'when', 'what', 'which', 'their', 'there',\n 'then', 'than', 'into', 'over', 'also', 'only', 'some', 'such', 'use',\n 'used', 'using'\n]);\n\n/**\n * Lowercase and strip punctuation/markdown so the same phrasing matches even\n * when only punctuation differs. Applied consistently to memory snippets and\n * responses, so exact-containment stays valid.\n */\nfunction normalizeText(text: string): string {\n return text\n .toLowerCase()\n .replace(/[^a-z0-9\uAC00-\uD7A3\u4E00-\u9FFF\u3040-\u30FF\\s_/-]+/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n}\n\n// Latin/numeric identifiers (3+ chars) or runs of Hangul / CJK / kana.\nconst TOKEN_PATTERN = /[a-z0-9_/-]{3,}|[\uAC00-\uD7A3\u4E00-\u9FFF\u3040-\u30FF]+/g;\n\nfunction tokenize(text: string): string[] {\n const tokens: string[] = [];\n const wordMatches = text.match(TOKEN_PATTERN) || [];\n for (const rawMatch of wordMatches) {\n const raw = rawMatch.replace(/^[/-]+|[/-]+$/g, '');\n if (raw.length < 1) continue;\n if (/^[a-z0-9_/-]+$/.test(raw)) {\n if (raw.length >= 3 && !STOP_TOKENS.has(raw)) tokens.push(raw);\n continue;\n }\n // CJK run: split into character bigrams so partial phrasing still matches.\n if (raw.length === 1) {\n tokens.push(raw);\n continue;\n }\n for (let i = 0; i < raw.length - 1; i++) {\n tokens.push(raw.slice(i, i + 2));\n }\n }\n return tokens;\n}\n\n/**\n * Split memory content into candidate snippets worth searching for in\n * responses: lines and sentence-ish fragments of meaningful length.\n */\nexport function extractMemorySnippets(content: string): string[] {\n const seen = new Set<string>();\n const snippets: string[] = [];\n\n const push = (raw: string) => {\n const trimmed = raw.replace(/^[-*>\\d.\\s]+/, '').trim();\n if (trimmed.length < MIN_SNIPPET_LENGTH) return;\n const clipped = trimmed.slice(0, MAX_SNIPPET_LENGTH);\n const key = normalizeText(clipped);\n if (!key || key.length < MIN_SNIPPET_LENGTH || seen.has(key)) return;\n seen.add(key);\n snippets.push(clipped);\n };\n\n for (const line of content.split(/\\n+/)) {\n if (snippets.length >= MAX_SNIPPETS) break;\n const trimmedLine = line.trim();\n if (!trimmedLine) continue;\n // Markdown headings are structural labels, not facts \u2014 a heading word\n // reappearing in an answer says nothing about memory reuse.\n if (/^#{1,6}\\s/.test(trimmedLine)) continue;\n if (trimmedLine.length <= MAX_SNIPPET_LENGTH) {\n push(trimmedLine);\n continue;\n }\n // Long line: fall back to sentence-ish fragments.\n for (const sentence of trimmedLine.split(/(?<=[.!?\u3002])\\s+|;\\s+/)) {\n if (snippets.length >= MAX_SNIPPETS) break;\n push(sentence);\n }\n }\n\n return snippets;\n}\n\nfunction findResponseWindow(\n normalizedResponse: string,\n originalResponse: string,\n needle: string\n): string {\n const index = normalizedResponse.indexOf(needle);\n if (index < 0) {\n return originalResponse.slice(0, RESPONSE_CONTEXT_CHARS);\n }\n // The normalized text is not position-aligned with the original, so\n // approximate by proportional position \u2014 good enough for a preview snippet.\n const ratio = normalizedResponse.length > 0 ? index / normalizedResponse.length : 0;\n const approxStart = Math.max(0, Math.floor(originalResponse.length * ratio) - 40);\n return originalResponse.slice(approxStart, approxStart + RESPONSE_CONTEXT_CHARS).trim();\n}\n\nfunction findTermWindow(originalResponse: string, terms: string[]): string {\n const lower = originalResponse.toLowerCase();\n for (const term of terms) {\n const index = lower.indexOf(term);\n if (index >= 0) {\n const start = Math.max(0, index - 40);\n return originalResponse.slice(start, start + RESPONSE_CONTEXT_CHARS).trim();\n }\n }\n return originalResponse.slice(0, RESPONSE_CONTEXT_CHARS).trim();\n}\n\n/**\n * Compute how strongly a set of assistant responses is grounded in a\n * memory's content, with per-snippet match evidence.\n */\nexport function computeMemoryUsageEvidence(\n memoryContent: string,\n responses: ResponseDocument[]\n): MemoryUsageEvidence {\n const snippets = extractMemorySnippets(memoryContent);\n if (snippets.length === 0 || responses.length === 0) {\n return { contentOverlapScore: 0, coverage: 0, matches: [] };\n }\n\n const preparedResponses = responses\n .map((response) => ({\n id: response.id,\n original: response.content,\n normalized: normalizeText(response.content),\n tokenSet: new Set(tokenize(normalizeText(response.content)))\n }))\n .filter((response) => response.normalized.length > 0);\n\n if (preparedResponses.length === 0) {\n return { contentOverlapScore: 0, coverage: 0, matches: [] };\n }\n\n const matches: EvidenceMatch[] = [];\n let matchedSnippets = 0;\n let bestSimilarity = 0;\n\n let comparableSnippets = 0;\n for (const snippet of snippets) {\n const normalizedSnippet = normalizeText(snippet);\n const snippetTokens = tokenize(normalizedSnippet);\n if (snippetTokens.length < MIN_SNIPPET_TOKENS) continue;\n comparableSnippets++;\n\n let best: EvidenceMatch | null = null;\n\n for (const response of preparedResponses) {\n // 1) Exact normalized containment \u2014 the strongest possible signal.\n if (normalizedSnippet.length >= MIN_SNIPPET_LENGTH && response.normalized.includes(normalizedSnippet)) {\n best = {\n memorySnippet: snippet,\n responseSnippet: findResponseWindow(response.normalized, response.original, normalizedSnippet),\n responseEventId: response.id,\n similarity: 1,\n matchType: 'exact'\n };\n break;\n }\n\n // 2) Term containment \u2014 what fraction of the snippet's tokens appear\n // in the response. Discriminative for facts, robust to rephrasing.\n let hit = 0;\n const matchedTerms: string[] = [];\n for (const token of snippetTokens) {\n if (response.tokenSet.has(token)) {\n hit++;\n if (matchedTerms.length < 5 && token.length >= 3) matchedTerms.push(token);\n }\n }\n const containment = hit / snippetTokens.length;\n const similarity = containment * 0.9; // cap below exact-match confidence\n if (similarity >= STRONG_MATCH_THRESHOLD && (!best || similarity > best.similarity)) {\n best = {\n memorySnippet: snippet,\n responseSnippet: findTermWindow(response.original, matchedTerms),\n responseEventId: response.id,\n similarity: Math.round(similarity * 100) / 100,\n matchType: 'term-overlap'\n };\n }\n }\n\n if (best) {\n matchedSnippets++;\n bestSimilarity = Math.max(bestSimilarity, best.similarity);\n matches.push(best);\n }\n }\n\n if (comparableSnippets === 0) {\n return { contentOverlapScore: 0, coverage: 0, matches: [] };\n }\n\n const coverage = matchedSnippets / comparableSnippets;\n // Grounding blends \"at least one strong reuse\" with \"how much of the\n // memory was reused\". A single exact quote should already score well.\n const contentOverlapScore = Math.min(1, 0.65 * bestSimilarity + 0.35 * coverage);\n\n matches.sort((a, b) => b.similarity - a.similarity);\n\n return {\n contentOverlapScore: Math.round(contentOverlapScore * 100) / 100,\n coverage: Math.round(coverage * 100) / 100,\n matches: matches.slice(0, MAX_MATCHES)\n };\n}\n", "import type { MemoryKind } from './memory-ref.js';\n\nexport const RETRIEVAL_PRESENTATION_MODES = ['evidence', 'reference', 'core', 'unknown'] as const;\nexport type RetrievalPresentationMode = typeof RETRIEVAL_PRESENTATION_MODES[number];\n\nexport const RETRIEVAL_TRIGGER_TYPES = [\n 'session_start',\n 'user_prompt',\n 'explicit_search',\n 'context_pack',\n 'unknown'\n] as const;\nexport type RetrievalTriggerType = typeof RETRIEVAL_TRIGGER_TYPES[number];\n\nexport const REFERENCE_NAVIGATION_ACTIONS = ['source_ref', 'details', 'expand', 'source'] as const;\nexport type ReferenceNavigationAction = typeof REFERENCE_NAVIGATION_ACTIONS[number];\n\nexport type ReferenceNavigationOutcome = 'attributed' | 'ambiguous' | 'unattributed';\n\nexport const RETRIEVAL_OUTCOME_REASONS = [\n 'selected',\n 'no_project_events',\n 'freshness_gap',\n 'scope_filtered',\n 'no_keyword_candidates',\n 'no_vector_candidates',\n 'stale_vector_schema',\n 'below_score_threshold',\n 'quality_filtered',\n 'session_rescue_empty',\n 'context_pack_policy_filtered',\n // An empty selection with no diagnostics is not a failure. `runtime_error` is\n // reserved for a caught exception; anything else uncategorised is `unknown`.\n 'unknown',\n // Rows written before the schema carried an honest default. Readers surface\n // this instead of re-classifying old data (specs R2).\n 'legacy_unclassified',\n 'runtime_error'\n] as const;\n\nexport type RetrievalOutcomeReason = typeof RETRIEVAL_OUTCOME_REASONS[number];\n\nexport type UsefulnessAdoption = 'grounded' | 'navigated' | 'not_observed' | 'unknown';\nexport type UsefulnessTaskOutcome = 'success' | 'failure' | 'mixed' | 'unknown';\nexport type UsefulnessReaskOutcome = 'clarification' | 'repeat_failure' | 'topic_continuation' | 'none' | 'unknown';\nexport type UsefulnessExplicitFeedback = 'positive' | 'negative' | null;\n\n/**\n * Evaluator identity for the delivery-evidence generation. v2 rows assumed\n * delivery; they are kept but never averaged together with v3 (specs R3).\n */\nexport const CURRENT_USEFULNESS_EVALUATOR_VERSION = 'v3';\nexport const LEGACY_ASSUMED_DELIVERY_EVALUATOR_VERSIONS = ['v2'] as const;\n\nexport interface MemoryUsefulnessObservationV2 {\n traceId: string;\n /** Retained field name for schema compatibility; may hold any memory kind. */\n eventId: string;\n /** Typed kind of `eventId`. Defaults to `event` only for legacy rows. */\n memoryKind?: MemoryKind;\n /** Owning project of the memory; part of its scope-aware identity (specs R1). */\n memoryProjectId?: string | null;\n observationKind: 'outcome';\n presentationMode: RetrievalPresentationMode;\n triggerType: RetrievalTriggerType;\n selected: boolean;\n delivered: boolean | null;\n deliveryStatus?: DeliveryStatus;\n deliveryEvidence?: DeliveryEvidenceSource;\n adoption: UsefulnessAdoption;\n contentOverlapScore: number | null;\n taskOutcome: UsefulnessTaskOutcome;\n reaskOutcome: UsefulnessReaskOutcome;\n explicitFeedback: UsefulnessExplicitFeedback;\n confidence: number;\n evaluatedAt: string | null;\n evaluatorVersion: string;\n /** Observation window applied after delivery, in ms. */\n evaluationWindowMs?: number;\n /** End of the window this evaluation could actually see. */\n evaluationCutoff?: string | null;\n}\n\nexport interface UsefulnessRateV2 {\n numerator: number;\n denominator: number;\n unknown: number;\n value: number | null;\n}\n\nexport interface UsefulnessAggregateV2 {\n eligible: number;\n selected: number;\n delivered: number;\n evidenceEvaluated: number;\n evidenceGrounded: number;\n referencesEligible: number;\n referencesNavigated: number;\n taskOutcomesEvaluated: number;\n taskOutcomesSuccessful: number;\n explicitPositive: number;\n explicitNegative: number;\n unknown: number;\n unknownByDimension: {\n delivery: number;\n adoption: number;\n taskOutcome: number;\n reaskOutcome: number;\n explicitFeedback: number;\n };\n rates: {\n selectionYield: UsefulnessRateV2;\n deliveryRate: UsefulnessRateV2;\n evidenceGrounding: UsefulnessRateV2;\n referenceNavigation: UsefulnessRateV2;\n taskSuccess: UsefulnessRateV2;\n explicitPositive: UsefulnessRateV2;\n };\n sampleState: 'sufficient' | 'insufficient_sample';\n minimumSample: number;\n evaluatorVersion: string;\n excludesSessionStart: boolean;\n window: { since: string | null; until: string | null };\n /** Observed delivery evidence levels. `unknown` is never folded into 0. */\n deliveryStatusCounts: Record<DeliveryStatus, number>;\n /** Rows from an evaluator generation that assumed delivery (v2). */\n legacyAssumedDeliveryRows: number;\n /**\n * How the `delivered` values in this aggregate were obtained. A legacy\n * evaluator's rows are labelled `legacy_assumed` rather than presented as\n * observed delivery (specs R3).\n */\n deliveryEvidenceBasis: 'observed' | 'legacy_assumed';\n /** Selected memories by typed kind (specs R1). */\n selectedByKind: Record<MemoryKind, number>;\n /**\n * The population `evidenceGrounding` is measured over. The spec's headline\n * comparison is prompt-triggered evidence only; session_start, explicit\n * search and context-pack rows are reported separately, never averaged in.\n */\n evidenceGroundingScope: 'evidence/user_prompt';\n /** Same counts over every trigger, for transparency about what was excluded. */\n evidenceAllTriggers: { evaluated: number; grounded: number; unknown: number };\n /** Bounded observation window used by this evaluator, in ms. */\n evaluationWindowMs: number;\n /**\n * Every adoption/task signal below is a heuristic, not a confirmed outcome.\n * Surfaced in JSON and UI so a reader never reads them as measured causality.\n */\n heuristics: {\n grounding: 'text_overlap';\n groundingThreshold: number;\n taskOutcome: 'post_delivery_tool_success';\n note: string;\n };\n}\n\nexport const USEFULNESS_HEURISTIC_NOTE =\n 'Grounding is text overlap between the delivered excerpt and later responses; '\n + 'task outcome is post-delivery tool success. Both are heuristics, not verified causal effects.';\n\nexport function normalizeUsefulnessMinimumSample(value: unknown): number {\n if (typeof value !== 'number' || !Number.isFinite(value)) return 20;\n return Math.min(10_000, Math.max(1, Math.floor(value)));\n}\n\nexport function emptyUsefulnessAggregateV2(options: {\n minimumSample?: number;\n evaluatorVersion?: string;\n includeSessionStart?: boolean;\n since?: Date;\n until?: Date;\n evaluationWindowMs?: number;\n groundingThreshold?: number;\n} = {}): UsefulnessAggregateV2 {\n const rate = (): UsefulnessRateV2 => ({ numerator: 0, denominator: 0, unknown: 0, value: null });\n return {\n eligible: 0,\n selected: 0,\n delivered: 0,\n evidenceEvaluated: 0,\n evidenceGrounded: 0,\n referencesEligible: 0,\n referencesNavigated: 0,\n taskOutcomesEvaluated: 0,\n taskOutcomesSuccessful: 0,\n explicitPositive: 0,\n explicitNegative: 0,\n unknown: 0,\n unknownByDimension: { delivery: 0, adoption: 0, taskOutcome: 0, reaskOutcome: 0, explicitFeedback: 0 },\n rates: {\n selectionYield: rate(),\n deliveryRate: rate(),\n evidenceGrounding: rate(),\n referenceNavigation: rate(),\n taskSuccess: rate(),\n explicitPositive: rate()\n },\n sampleState: 'insufficient_sample',\n minimumSample: normalizeUsefulnessMinimumSample(options.minimumSample),\n evaluatorVersion: options.evaluatorVersion ?? CURRENT_USEFULNESS_EVALUATOR_VERSION,\n excludesSessionStart: options.includeSessionStart !== true,\n window: {\n since: options.since?.toISOString() ?? null,\n until: options.until?.toISOString() ?? null\n },\n deliveryStatusCounts: { unknown: 0, formatted: 0, emitted: 0, acknowledged: 0, failed: 0 },\n legacyAssumedDeliveryRows: 0,\n deliveryEvidenceBasis: LEGACY_ASSUMED_DELIVERY_EVALUATOR_VERSIONS.includes(\n (options.evaluatorVersion ?? CURRENT_USEFULNESS_EVALUATOR_VERSION) as typeof LEGACY_ASSUMED_DELIVERY_EVALUATOR_VERSIONS[number]\n )\n ? 'legacy_assumed'\n : 'observed',\n selectedByKind: { event: 0, lesson: 0, rule: 0, core: 0, unknown: 0 },\n evidenceGroundingScope: 'evidence/user_prompt',\n evidenceAllTriggers: { evaluated: 0, grounded: 0, unknown: 0 },\n evaluationWindowMs: options.evaluationWindowMs ?? 0,\n heuristics: {\n grounding: 'text_overlap',\n groundingThreshold: options.groundingThreshold ?? 0.3,\n taskOutcome: 'post_delivery_tool_success',\n note: USEFULNESS_HEURISTIC_NOTE\n }\n };\n}\n\nexport interface RetrievalOutcomeDiagnostics {\n outcomeReason: RetrievalOutcomeReason;\n laneCandidateCounts: Record<string, number>;\n filteredCounts: Record<string, number>;\n topScore: number | null;\n threshold: number;\n freshnessState: 'fresh' | 'stale' | 'unknown';\n}\n\nconst RETRIEVAL_OUTCOME_REASON_SET = new Set<string>(RETRIEVAL_OUTCOME_REASONS);\nconst DIAGNOSTIC_COUNT_KEYS = new Set([\n 'keyword', 'vector', 'summary', 'graph', 'session_rescue', 'shared',\n 'scope', 'quality', 'threshold', 'context_pack_policy'\n]);\n\nexport function normalizeRetrievalOutcomeReason(value: unknown): RetrievalOutcomeReason {\n return typeof value === 'string' && RETRIEVAL_OUTCOME_REASON_SET.has(value)\n ? value as RetrievalOutcomeReason\n : 'unknown';\n}\n\nexport function normalizeRetrievalOutcomeDiagnostics(\n value: unknown,\n fallbackReason: RetrievalOutcomeReason = 'unknown'\n): RetrievalOutcomeDiagnostics {\n const raw = value && typeof value === 'object' ? value as Record<string, unknown> : {};\n return {\n outcomeReason: RETRIEVAL_OUTCOME_REASON_SET.has(String(raw.outcomeReason))\n ? raw.outcomeReason as RetrievalOutcomeReason\n : fallbackReason,\n laneCandidateCounts: normalizeDiagnosticCounts(raw.laneCandidateCounts),\n filteredCounts: normalizeDiagnosticCounts(raw.filteredCounts),\n topScore: typeof raw.topScore === 'number' && Number.isFinite(raw.topScore)\n ? Math.max(0, Math.min(1, raw.topScore))\n : null,\n threshold: typeof raw.threshold === 'number' && Number.isFinite(raw.threshold)\n ? Math.max(0, Math.min(1, raw.threshold))\n : 0,\n freshnessState: raw.freshnessState === 'fresh' || raw.freshnessState === 'stale'\n ? raw.freshnessState\n : 'unknown'\n };\n}\n\nfunction normalizeDiagnosticCounts(value: unknown): Record<string, number> {\n if (!value || typeof value !== 'object') return {};\n return Object.fromEntries(Object.entries(value as Record<string, unknown>)\n .filter(([key, count]) => DIAGNOSTIC_COUNT_KEYS.has(key) && Number.isFinite(Number(count)))\n .map(([key, count]) => [key, Math.max(0, Math.min(1_000_000, Math.floor(Number(count))))]));\n}\n\n/**\n * Bumped whenever the trace ledger gains a field a reader must know about.\n * Version 2 is the first schema with typed trace items, honest unknown outcome\n * reasons and request metadata (specs/recent-memory-patterns-2026-09-06 R1-R2).\n */\nexport const RETRIEVAL_TELEMETRY_SCHEMA_VERSION = 2;\n\n/**\n * Rows without a schema version predate the honest-default migration. Their\n * stored `runtime_error` was a fallback, not an observed exception, so readers\n * present them as legacy instead of re-classifying the stored value.\n */\nexport function presentedOutcomeReason(\n storedReason: unknown,\n telemetrySchemaVersion: unknown\n): RetrievalOutcomeReason {\n const version = Number(telemetrySchemaVersion);\n const reason = normalizeRetrievalOutcomeReason(storedReason);\n if (Number.isFinite(version) && version >= 2) return reason;\n return reason === 'runtime_error' ? 'legacy_unclassified' : reason;\n}\n\n/**\n * How far a selected memory actually got. Selection alone is not delivery:\n * `formatted` means the text was built, `emitted` means the hook wrote it to\n * stdout successfully, `acknowledged` requires evidence the consumer read it.\n */\nexport const DELIVERY_STATUSES = ['unknown', 'formatted', 'emitted', 'acknowledged', 'failed'] as const;\nexport type DeliveryStatus = typeof DELIVERY_STATUSES[number];\n\n/** Where the delivery status came from. `legacy_assumed` is never a new write. */\nexport const DELIVERY_EVIDENCE_SOURCES = [\n 'none',\n 'context_formatted',\n 'hook_stdout',\n 'mcp_tool_result',\n 'consumer_ack',\n 'write_error',\n 'legacy_assumed'\n] as const;\nexport type DeliveryEvidenceSource = typeof DELIVERY_EVIDENCE_SOURCES[number];\n\nconst DELIVERY_STATUS_SET = new Set<string>(DELIVERY_STATUSES);\nconst DELIVERY_EVIDENCE_SET = new Set<string>(DELIVERY_EVIDENCE_SOURCES);\n\nexport function normalizeDeliveryStatus(value: unknown): DeliveryStatus {\n return typeof value === 'string' && DELIVERY_STATUS_SET.has(value)\n ? value as DeliveryStatus\n : 'unknown';\n}\n\nexport function normalizeDeliveryEvidence(value: unknown): DeliveryEvidenceSource {\n return typeof value === 'string' && DELIVERY_EVIDENCE_SET.has(value)\n ? value as DeliveryEvidenceSource\n : 'none';\n}\n\n/**\n * `delivered` stays null until evidence exists. Only an emitted/acknowledged\n * delivery is true and only an observed write failure is false \u2014 a formatted\n * but never-flushed context is unknown, not delivered.\n */\nexport function deliveredFromStatus(status: DeliveryStatus): boolean | null {\n if (status === 'emitted' || status === 'acknowledged') return true;\n if (status === 'failed') return false;\n return null;\n}\n\nexport interface RetrievalTelemetryContext {\n presentationMode?: RetrievalPresentationMode;\n triggerType?: RetrievalTriggerType;\n deliveryClient?: string;\n /** Stable id for the caller-visible request that produced this retrieval. */\n requestId?: string;\n /** Set only by offline/benchmark evaluation runs so they can be excluded. */\n evaluationRunId?: string;\n runtimeVersion?: string;\n}\n\n/** One typed reference inside a trace: a candidate, a selection, or both. */\nexport interface RetrievalTraceItemInput {\n kind: MemoryKind;\n id: string;\n projectId?: string | null;\n rank?: number;\n selected?: boolean;\n score?: number | null;\n /** Hash of the delivered excerpt. Never the excerpt itself. */\n contentHash?: string | null;\n memoryVersion?: string | null;\n deleted?: boolean;\n}\n\nexport interface RetrievalTraceItem {\n traceId: string;\n itemKey: string;\n memoryKind: MemoryKind;\n memoryId: string;\n projectId: string | null;\n rank: number | null;\n selected: boolean;\n score: number | null;\n contentHash: string | null;\n memoryVersion: string | null;\n deleted: boolean;\n}\n\n/** Typed selection totals for a fixed sample, with unresolved refs kept apart. */\nexport interface TypedSelectionSummary {\n byKind: Record<MemoryKind, number>;\n total: number;\n unresolved: number;\n ambiguous: number;\n /** Traces whose items were reconstructed by the read-only legacy resolver. */\n legacyResolvedTraces: number;\n typedTraces: number;\n}\n\nexport function emptyTypedSelectionSummary(): TypedSelectionSummary {\n return {\n byKind: { event: 0, lesson: 0, rule: 0, core: 0, unknown: 0 },\n total: 0,\n unresolved: 0,\n ambiguous: 0,\n legacyResolvedTraces: 0,\n typedTraces: 0\n };\n}\n\n/**\n * Per-client instrumentation coverage. A client whose requests we never see\n * cannot be reported as 0% coverage \u2014 that would claim an observation we do not\n * have \u2014 so `coverage` stays null with an explicit `unknown` state.\n */\nexport interface RetrievalClientCoverage {\n client: string;\n observedRequests: number;\n instrumentedRequests: number;\n unobservedOrUnknown: number;\n coverage: number | null;\n coverageState: 'measured' | 'unknown';\n}\n\nexport function normalizeRequestId(value: unknown): string | null {\n if (typeof value !== 'string') return null;\n const trimmed = value.trim().slice(0, 128);\n return /^[A-Za-z0-9_.:@-]{1,128}$/.test(trimmed) ? trimmed : null;\n}\n\nexport interface RecordReferenceNavigationInput {\n targetEventId: string;\n /** Typed kind of the opened memory. Defaults to `event` for legacy callers. */\n targetKind?: MemoryKind;\n targetProjectId?: string | null;\n action: ReferenceNavigationAction;\n navigationClient: string;\n /** Optional current delivery session. When supplied, attribution never crosses its boundary. */\n attributionSessionId?: string;\n openedAt?: Date;\n}\n\nexport interface RecordReferenceNavigationResult {\n outcome: ReferenceNavigationOutcome;\n traceId: string | null;\n repeated: boolean;\n}\n\nexport interface RetrievalPresentationBreakdown {\n presentationMode: RetrievalPresentationMode;\n traceCount: number;\n deliveredItemCount: number;\n}\n\nexport interface RetrievalTriggerBreakdown {\n triggerType: RetrievalTriggerType;\n traceCount: number;\n deliveredItemCount: number;\n}\n\nexport interface RetrievalTelemetryStats {\n deliveries: {\n totalTraces: number;\n totalItems: number;\n byPresentation: RetrievalPresentationBreakdown[];\n byTrigger: RetrievalTriggerBreakdown[];\n legacyUnknownRows: number;\n };\n evidenceGrounding: {\n evaluatedDeliveries: number;\n groundedDeliveries: number;\n groundingRate: number;\n averageContentOverlap: number;\n };\n referenceNavigation: {\n eligibleTraces: number;\n navigatedTraces: number;\n navigationRate: number;\n attributedOpenCount: number;\n ambiguousOpenCount: number;\n unattributedOpenCount: number;\n };\n}\n\nexport function normalizeRetrievalPresentationMode(value: unknown): RetrievalPresentationMode {\n return typeof value === 'string' && (RETRIEVAL_PRESENTATION_MODES as readonly string[]).includes(value)\n ? value as RetrievalPresentationMode\n : 'unknown';\n}\n\nexport function normalizeRetrievalTriggerType(value: unknown): RetrievalTriggerType {\n return typeof value === 'string' && (RETRIEVAL_TRIGGER_TYPES as readonly string[]).includes(value)\n ? value as RetrievalTriggerType\n : 'unknown';\n}\n\nexport function normalizeTelemetryClient(value: unknown): string {\n if (typeof value !== 'string') return 'unknown';\n const normalized = value.trim().toLowerCase().replace(/[^a-z0-9_-]+/g, '-').slice(0, 48);\n return normalized || 'unknown';\n}\n", "import type { MemoryKind } from './memory-ref.js';\nimport {\n CURRENT_USEFULNESS_EVALUATOR_VERSION,\n type DeliveryEvidenceSource,\n type DeliveryStatus,\n type MemoryUsefulnessObservationV2,\n type RetrievalPresentationMode,\n type RetrievalTriggerType,\n type UsefulnessAdoption,\n type UsefulnessReaskOutcome,\n type UsefulnessTaskOutcome\n} from './retrieval-telemetry.js';\n\nexport type ParsedToolOutcome = 'success' | 'failure' | 'unknown';\n\n/** Outcome signals are attributable only to the bounded task phase after delivery. */\nexport const USEFULNESS_V2_EVALUATION_WINDOW_MS = 30 * 60 * 1000;\n\nexport function parseToolOutcome(value: unknown): ParsedToolOutcome {\n let parsed = value;\n if (typeof value === 'string') {\n try {\n parsed = JSON.parse(value);\n } catch {\n return 'unknown';\n }\n }\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) return 'unknown';\n const record = parsed as Record<string, unknown>;\n if (typeof record.success === 'boolean') return record.success ? 'success' : 'failure';\n if (typeof record.ok === 'boolean') return record.ok ? 'success' : 'failure';\n if (typeof record.isError === 'boolean') return record.isError ? 'failure' : 'success';\n if (typeof record.status === 'string') {\n const status = record.status.trim().toLowerCase();\n if (['ok', 'success', 'succeeded', 'complete', 'completed'].includes(status)) return 'success';\n if (['error', 'failed', 'failure', 'cancelled', 'canceled'].includes(status)) return 'failure';\n }\n return 'unknown';\n}\n\nexport function deriveTaskOutcome(\n adoption: UsefulnessAdoption,\n toolOutcomes: ParsedToolOutcome[]\n): UsefulnessTaskOutcome {\n if (adoption !== 'grounded' && adoption !== 'navigated') return 'unknown';\n const measured = toolOutcomes.filter((outcome) => outcome !== 'unknown');\n if (measured.length === 0) return 'unknown';\n const successes = measured.filter((outcome) => outcome === 'success').length;\n const failures = measured.length - successes;\n if (successes > 0 && failures > 0) return 'mixed';\n return successes > 0 ? 'success' : 'failure';\n}\n\nexport function classifyReaskOutcome(\n originalQuery: unknown,\n promptsAfter: unknown[]\n): UsefulnessReaskOutcome {\n if (!Array.isArray(promptsAfter)) return 'unknown';\n if (promptsAfter.length === 0) return 'none';\n const query = typeof originalQuery === 'string' ? originalQuery.trim() : '';\n const prompts = promptsAfter.filter((value): value is string => typeof value === 'string' && value.trim().length > 0);\n if (prompts.length === 0) return 'unknown';\n const combined = prompts.join(' ').toLowerCase();\n if (/(clarify|what do you mean|more specific|explain more|\uBB34\uC2A8 \uB73B|\uC880 \uB354 \uC124\uBA85|\uAD6C\uCCB4\uC801\uC73C\uB85C|\uBA85\uD655\uD788)/i.test(combined)) {\n return 'clarification';\n }\n if (/(still|again|same error|doesn.t work|did not work|failed again|\uC5EC\uC804\uD788|\uB610 \uC2E4\uD328|\uAC19\uC740 \uC624\uB958|\uC548[\uB3FC\uB418]|\uC791\uB3D9\uD558\uC9C0 \uC54A)/i.test(combined)) {\n return 'repeat_failure';\n }\n if (!query) return 'unknown';\n const queryTokens = tokens(query);\n if (queryTokens.size === 0) return 'unknown';\n for (const prompt of prompts) {\n const promptTokens = tokens(prompt);\n const overlap = [...queryTokens].filter((token) => promptTokens.has(token)).length / queryTokens.size;\n if (overlap >= 0.35) return 'topic_continuation';\n }\n return 'none';\n}\n\nexport function buildUsefulnessObservationV2(input: {\n traceId: string;\n eventId: string;\n memoryKind?: MemoryKind;\n memoryProjectId?: string | null;\n presentationMode: RetrievalPresentationMode;\n triggerType: RetrievalTriggerType;\n delivered: boolean | null;\n deliveryStatus?: DeliveryStatus;\n deliveryEvidence?: DeliveryEvidenceSource;\n adoption: UsefulnessAdoption;\n contentOverlapScore: number | null;\n toolOutcomes: ParsedToolOutcome[];\n reaskOutcome: UsefulnessReaskOutcome;\n evaluatedAt: string | null;\n evaluatorVersion?: string;\n evaluationWindowMs?: number;\n evaluationCutoff?: string | null;\n}): MemoryUsefulnessObservationV2 {\n return {\n traceId: input.traceId,\n eventId: input.eventId,\n memoryKind: input.memoryKind ?? 'event',\n memoryProjectId: input.memoryProjectId ?? null,\n observationKind: 'outcome',\n presentationMode: input.presentationMode,\n triggerType: input.triggerType,\n selected: true,\n delivered: input.delivered,\n deliveryStatus: input.deliveryStatus ?? 'unknown',\n deliveryEvidence: input.deliveryEvidence ?? 'none',\n adoption: input.adoption,\n contentOverlapScore: input.contentOverlapScore,\n taskOutcome: deriveTaskOutcome(input.adoption, input.toolOutcomes),\n reaskOutcome: input.reaskOutcome,\n explicitFeedback: null,\n confidence: confidenceFor(input.presentationMode, input.adoption),\n evaluatedAt: input.evaluatedAt,\n evaluatorVersion: input.evaluatorVersion ?? CURRENT_USEFULNESS_EVALUATOR_VERSION,\n evaluationWindowMs: input.evaluationWindowMs ?? USEFULNESS_V2_EVALUATION_WINDOW_MS,\n evaluationCutoff: input.evaluationCutoff ?? null\n };\n}\n\nfunction confidenceFor(presentationMode: RetrievalPresentationMode, adoption: UsefulnessAdoption): number {\n if (presentationMode === 'reference') return adoption === 'navigated' ? 0.95 : 0.7;\n if (presentationMode === 'evidence') return adoption === 'grounded' ? 0.85 : 0.6;\n if (presentationMode === 'core') return 0.4;\n return 0.3;\n}\n\nfunction tokens(value: string): Set<string> {\n return new Set(value.toLowerCase().match(/[a-z0-9_/-]{3,}|[\uAC00-\uD7A3]{2,}/g) ?? []);\n}\n", "/**\n * Typed memory references (specs/recent-memory-patterns-2026-09-06 R1).\n *\n * The retrieval ledger historically stored every selected memory in\n * `retrieval_traces.selected_event_ids`, regardless of what kind of memory it\n * was. Lessons are not events, so an event-table join silently dropped them\n * (465 selections in the 2026-09-06 sample) and helpfulness/access writes keyed\n * by a lesson id updated nothing. A `MemoryRef` keeps the kind next to the id so\n * joins, access counters and evaluation populations stay type-correct.\n *\n * Nothing here copies memory content: only the kind, the id, the owning project\n * and an optional content hash travel with a reference.\n */\n\nexport const MEMORY_KINDS = ['event', 'lesson', 'rule', 'core', 'unknown'] as const;\nexport type MemoryKind = typeof MEMORY_KINDS[number];\n\nconst MEMORY_KIND_SET = new Set<string>(MEMORY_KINDS);\n\nexport interface MemoryRef {\n /**\n * Project scope that owns the memory. Must match the permission boundary the\n * memory was read under; `null` means the reference is store-local/global.\n */\n projectId: string | null;\n kind: MemoryKind;\n id: string;\n}\n\n/**\n * Why a reference could not be resolved to a single kind. Kept separate from\n * `kind` so an honestly unknown reference is never reported as a data loss.\n */\nexport type MemoryRefResolution =\n | 'resolved'\n | 'ambiguous'\n | 'unresolved'\n | 'deleted'\n | 'forbidden';\n\nexport interface ResolvedMemoryRef extends MemoryRef {\n resolution: MemoryRefResolution;\n /** Kinds the id matched. Length > 1 means ambiguous. */\n matchedKinds: MemoryKind[];\n}\n\nexport function normalizeMemoryKind(value: unknown): MemoryKind {\n return typeof value === 'string' && MEMORY_KIND_SET.has(value)\n ? value as MemoryKind\n : 'unknown';\n}\n\n/** Project segment of a scope-aware key. `-` means \"store-local / global\". */\nconst GLOBAL_SCOPE_SEGMENT = '-';\n\n/**\n * Kind-aware, scope-free key. Only safe where the owning project is already\n * fixed by context (a single project store, a single trace's own scope).\n */\nexport function memoryKindKey(ref: Pick<MemoryRef, 'kind' | 'id'>): string {\n return `${normalizeMemoryKind(ref.kind)}:${ref.id}`;\n}\n\n/**\n * Stable identity for a reference: project scope, kind, then id.\n *\n * Kind is part of the key so an event and a lesson that share an id remain two\n * distinct rows. The project scope is part of it too: the same kind/id pair in\n * two different projects is two different memories under two different\n * permission boundaries, and collapsing them would merge one project's\n * telemetry into another's (specs R1).\n */\nexport function memoryRefKey(ref: Pick<MemoryRef, 'kind' | 'id'> & { projectId?: string | null }): string {\n return JSON.stringify([ref.projectId?.trim() || null, normalizeMemoryKind(ref.kind), ref.id]);\n}\n\nexport function parseMemoryRefKey(\n key: string\n): { projectId: string | null; kind: MemoryKind; id: string } | null {\n if (key.startsWith('[')) {\n try {\n const value: unknown = JSON.parse(key);\n if (Array.isArray(value) && value.length === 3\n && (value[0] === null || typeof value[0] === 'string')\n && MEMORY_KIND_SET.has(value[1]) && typeof value[2] === 'string' && value[2].length > 0) {\n return { projectId: value[0], kind: value[1] as MemoryKind, id: value[2] };\n }\n } catch { /* malformed key */ }\n return null;\n }\n // Read the pre-release pipe form, but only emit unambiguous tuple keys.\n // Scan for the first unescaped `|`: a project id may legitimately contain an\n // escaped one.\n let scope = '';\n let index = 0;\n let closed = false;\n while (index < key.length) {\n const char = key[index];\n if (char === '\\\\' && index + 1 < key.length) {\n scope += key[index + 1];\n index += 2;\n continue;\n }\n if (char === '|') {\n closed = true;\n index += 1;\n break;\n }\n scope += char;\n index += 1;\n }\n if (!closed) return null;\n const rest = key.slice(index);\n const separator = rest.indexOf(':');\n if (separator <= 0 || separator === rest.length - 1) return null;\n const kind = rest.slice(0, separator);\n if (!MEMORY_KIND_SET.has(kind)) return null;\n return {\n projectId: scope === GLOBAL_SCOPE_SEGMENT ? null : scope,\n kind: kind as MemoryKind,\n id: rest.slice(separator + 1)\n };\n}\n\n/**\n * Core memory blocks are delivered as `core:<blockKey>` pseudo-ids by the\n * session-start hook. Recognize that shape so the ledger records them as core\n * blocks rather than as events that will never resolve.\n */\nexport function inferMemoryKindFromLegacyId(id: string): MemoryKind | null {\n if (id.startsWith('core:')) return 'core';\n return null;\n}\n\nexport function isEventRef(ref: Pick<MemoryRef, 'kind'>): boolean {\n return ref.kind === 'event';\n}\n\n/** Deduplicate refs by scope-aware typed key while preserving first-seen order. */\nexport function uniqueMemoryRefs<T extends Pick<MemoryRef, 'kind' | 'id'> & { projectId?: string | null }>(\n refs: T[]\n): T[] {\n const seen = new Set<string>();\n const out: T[] = [];\n for (const ref of refs) {\n if (!ref?.id) continue;\n const key = memoryRefKey(ref);\n if (seen.has(key)) continue;\n seen.add(key);\n out.push(ref);\n }\n return out;\n}\n\n/**\n * Row key for tables whose legacy identity column is `event_id`\n * (`memory_helpfulness`, `memory_usefulness_observations_v2`).\n *\n * New evaluator rows use the complete scope/kind/id tuple. Their memory_id\n * retains the original id; historical v2 observations keep their legacy keys.\n */\nexport function usefulnessRowKey(kind: MemoryKind | undefined, id: string, projectId?: string | null): string {\n return memoryRefKey({ kind: normalizeMemoryKind(kind ?? 'event'), id, projectId });\n}\n\n/** SQL expression mirroring `usefulnessRowKey` for a table alias. */\nexport function usefulnessRowKeySql(alias: string, kindColumn = 'memory_kind', idColumn = 'event_id'): string {\n return `json_array(NULLIF(TRIM(${alias}.memory_project_id), ''), COALESCE(${alias}.${kindColumn}, 'event'), ${alias}.${idColumn})`;\n}\n", "/**\n * Reference navigation telemetry.\n *\n * Split out of the event store so any caller holding a SQLite handle can record\n * that a delivered reference was actually opened, together with the typed kind\n * of the memory (specs/recent-memory-patterns-2026-09-06 R1/R3).\n */\n\nimport { randomUUID } from 'crypto';\nimport { normalizeMemoryKind } from './memory-ref.js';\nimport {\n normalizeRetrievalTriggerType,\n normalizeTelemetryClient,\n type RecordReferenceNavigationInput,\n type RecordReferenceNavigationResult\n} from './retrieval-telemetry.js';\nimport { readTraceItems } from './retrieval-trace-ledger.js';\nimport { sqliteAll, sqliteGet, sqliteRun, type SQLiteDatabase } from './sqlite-wrapper.js';\n\n/**\n * Attribution window for an opened reference. Deliberately short: a reference\n * opened long after delivery cannot be attributed to it with confidence.\n */\nexport const REFERENCE_ATTRIBUTION_WINDOW_MS = 15 * 60 * 1000;\n\nfunction tableExists(db: SQLiteDatabase, table: string): boolean {\n return sqliteAll<{ name: string }>(\n db,\n `SELECT name FROM sqlite_master WHERE type = 'table' AND name = ?`,\n [table]\n ).length > 0;\n}\n\nfunction columnExists(db: SQLiteDatabase, table: string, column: string): boolean {\n if (!tableExists(db, table)) return false;\n return sqliteAll<{ name: string }>(db, `PRAGMA table_info(${table})`)\n .some((row) => row.name === column);\n}\n\n/**\n * Reference navigation attribution (specs/recent-memory-patterns R1/R3).\n *\n * Kept as a database-level function so callers that hold only a SQLite handle \u2014\n * `mem-lesson-get`, `mem-source-ref`, `mem-details` \u2014 can record an opened\n * reference against the trace that delivered it, with the memory's typed kind.\n * Attribution is deliberately conservative: only a unique recent reference\n * delivery is attributed, everything else stays ambiguous or unattributed.\n */\nexport function recordReferenceNavigationOnDb(\n db: SQLiteDatabase,\n input: RecordReferenceNavigationInput\n): RecordReferenceNavigationResult {\n const openedAt = input.openedAt ?? new Date();\n const windowStart = new Date(openedAt.getTime() - REFERENCE_ATTRIBUTION_WINDOW_MS).toISOString();\n const openedAtIso = openedAt.toISOString();\n const targetKind = normalizeMemoryKind(input.targetKind ?? 'event');\n const targetProjectId = input.targetProjectId ?? null;\n const hasTypedItems = tableExists(db, 'retrieval_trace_items');\n // Attribution needs delivery evidence, not just selection. A trace whose\n // context was formatted but never emitted (or whose write failed) did not put\n // this reference in front of anyone, so an open cannot belong to it\n // (specs R3, finding 10). Stores whose helpfulness rows predate the delivery\n // columns cannot express this, and keep the older selection-based behaviour\n // rather than losing every attribution.\n const deliveryEvidenceAvailable = columnExists(db, 'memory_helpfulness', 'delivery_status');\n const deliveryClock = columnExists(db, 'memory_helpfulness', 'delivered_at')\n ? 'COALESCE(delivered_at, created_at)' : 'created_at';\n const wasDelivered = (traceId: string): boolean => {\n if (!deliveryEvidenceAvailable) return true;\n // A helpfulness row written before the typed columns carries kind\n // `unknown`; it cannot disprove the match, so it is admitted alongside an\n // exact kind match rather than excluded.\n const kindClause = columnExists(db, 'memory_helpfulness', 'memory_kind')\n ? ` AND COALESCE(memory_kind, 'event') IN (?, 'unknown')`\n : '';\n const scopeClause = columnExists(db, 'memory_helpfulness', 'memory_project_id')\n ? ' AND memory_project_id IS ?' : '';\n const params: unknown[] = [traceId, input.targetEventId];\n if (kindClause) params.push(targetKind);\n if (scopeClause) params.push(targetProjectId);\n params.push(windowStart, openedAtIso);\n const row = sqliteGet<{ delivered: number }>(\n db,\n `SELECT 1 AS delivered FROM memory_helpfulness\n WHERE trace_id = ? AND event_id = ?${kindClause}${scopeClause}\n AND delivery_status IN ('emitted', 'acknowledged')\n AND julianday(${deliveryClock}) >= julianday(?)\n AND julianday(${deliveryClock}) <= julianday(?)\n LIMIT 1`,\n params\n );\n if (row) return true;\n // An instrumented store needs positive delivery evidence. Absence is\n // unknown, and must never become attributed navigation by assumption.\n return false;\n };\n // New stores use the actual delivery clock. The trace can have been selected\n // much earlier; only legacy stores without delivery evidence use selection.\n const traceWindowClause = deliveryEvidenceAvailable\n ? `EXISTS (SELECT 1 FROM memory_helpfulness\n WHERE trace_id = retrieval_traces.trace_id\n AND delivery_status IN ('emitted', 'acknowledged')\n AND julianday(${deliveryClock}) >= julianday(?)\n AND julianday(${deliveryClock}) <= julianday(?))`\n : 'julianday(created_at) >= julianday(?) AND julianday(created_at) <= julianday(?)';\n const matchesTrace = (row: Record<string, unknown>): boolean => {\n if (input.attributionSessionId && row.session_id !== input.attributionSessionId) return false;\n // Prefer typed items so opening lesson X is never attributed to a trace\n // that merely delivered an event whose id happens to match (specs R1/R3).\n let selectedHere: boolean;\n if (hasTypedItems) {\n const typed = readTraceItems(db, String(row.trace_id || ''));\n if (typed.length > 0) {\n selectedHere = typed.some((item) =>\n item.selected && item.memoryId === input.targetEventId && item.memoryKind === targetKind && item.projectId === targetProjectId);\n return selectedHere && wasDelivered(String(row.trace_id || ''));\n }\n }\n try {\n const selected = JSON.parse(String(row.selected_event_ids || '[]'));\n selectedHere = Array.isArray(selected) && selected.includes(input.targetEventId);\n } catch {\n return false;\n }\n return selectedHere && wasDelivered(String(row.trace_id || ''));\n };\n\n // A page boundary does not prove uniqueness: a matching delivery can be\n // behind hundreds of unrelated traces. Scan stable pages until exhausted or\n // two matches prove ambiguity, keeping only those two candidates in memory.\n const candidates: Record<string, unknown>[] = [];\n let cursor: Record<string, unknown> | undefined;\n while (candidates.length < 2) {\n const cursorClause = cursor\n ? ' AND (created_at < ? OR (created_at = ? AND trace_id < ?))' : '';\n const page = sqliteAll<Record<string, unknown>>(\n db,\n `SELECT trace_id, session_id, trigger_type, selected_event_ids, created_at\n FROM retrieval_traces\n WHERE presentation_mode = 'reference' AND ${traceWindowClause}${cursorClause}\n ORDER BY created_at DESC, trace_id DESC LIMIT 500`,\n [windowStart, openedAtIso, ...(cursor ? [cursor.created_at, cursor.created_at, cursor.trace_id] : [])]\n );\n for (const row of page) {\n if (matchesTrace(row)) candidates.push(row);\n if (candidates.length === 2) break;\n }\n if (page.length < 500) break;\n cursor = page[page.length - 1];\n }\n const attributed = candidates.length === 1 ? candidates[0] : undefined;\n const traceId = attributed ? String(attributed.trace_id) : null;\n const outcome = candidates.length === 1\n ? 'attributed'\n : candidates.length > 1\n ? 'ambiguous'\n : 'unattributed';\n const reason = candidates.length === 1\n ? 'unique_recent_reference_delivery'\n : candidates.length > 1\n ? 'multiple_recent_reference_deliveries'\n : 'no_recent_reference_delivery';\n const navigationClient = normalizeTelemetryClient(input.navigationClient);\n\n const repeated = sqliteGet<{ navigation_id: string }>(\n db,\n `SELECT navigation_id\n FROM retrieval_navigation_events\n WHERE target_event_id = ?\n AND memory_kind = ?\n AND memory_project_id IS ?\n AND trace_id IS ?\n AND navigation_action = ?\n AND navigation_client = ?\n AND attribution_outcome = ?\n AND julianday(last_opened_at) >= julianday(?)\n AND julianday(last_opened_at) <= julianday(?)\n ORDER BY last_opened_at DESC\n LIMIT 1`,\n [input.targetEventId, targetKind, targetProjectId, traceId, input.action, navigationClient, outcome, windowStart, openedAtIso]\n );\n\n if (repeated) {\n sqliteRun(\n db,\n `UPDATE retrieval_navigation_events\n SET open_count = open_count + 1, last_opened_at = ?\n WHERE navigation_id = ?`,\n [openedAtIso, repeated.navigation_id]\n );\n return { outcome, traceId, repeated: true };\n }\n\n sqliteRun(\n db,\n `INSERT INTO retrieval_navigation_events (\n navigation_id, target_event_id, trace_id, delivery_session_id,\n presentation_mode, trigger_type, memory_kind, memory_project_id, navigation_action, navigation_client,\n attribution_outcome, attribution_reason, open_count, first_opened_at, last_opened_at\n ) VALUES (?, ?, ?, ?, 'reference', ?, ?, ?, ?, ?, ?, ?, 1, ?, ?)`,\n [\n randomUUID(),\n input.targetEventId,\n traceId,\n attributed?.session_id || input.attributionSessionId || null,\n normalizeRetrievalTriggerType(attributed?.trigger_type),\n targetKind,\n targetProjectId,\n input.action,\n navigationClient,\n outcome,\n reason,\n openedAtIso,\n openedAtIso\n ]\n );\n return { outcome, traceId, repeated: false };\n}\n", "/**\n * Typed retrieval ledger (specs/recent-memory-patterns-2026-09-06 R1).\n *\n * `retrieval_traces` keeps its legacy id arrays for old readers. Every new\n * write additionally lands in `retrieval_trace_items`, where each reference\n * carries its kind, owning project and rank. New readers prefer the typed rows;\n * a read-only resolver reconstructs kinds for legacy traces without ever\n * mutating them.\n */\n\nimport { createHash } from 'crypto';\nimport {\n MEMORY_KINDS,\n inferMemoryKindFromLegacyId,\n memoryRefKey,\n normalizeMemoryKind,\n type MemoryKind,\n type ResolvedMemoryRef\n} from './memory-ref.js';\nimport {\n emptyTypedSelectionSummary,\n type RetrievalTraceItem,\n type RetrievalTraceItemInput,\n type TypedSelectionSummary\n} from './retrieval-telemetry.js';\nimport { sqliteAll, sqliteExec, sqliteRun, type SQLiteDatabase } from './sqlite-wrapper.js';\n\nexport const RETRIEVAL_TRACE_ITEMS_DDL = `\n CREATE TABLE IF NOT EXISTS retrieval_trace_items (\n trace_id TEXT NOT NULL,\n item_key TEXT NOT NULL,\n memory_kind TEXT NOT NULL,\n memory_id TEXT NOT NULL,\n project_id TEXT,\n rank INTEGER,\n selected INTEGER NOT NULL DEFAULT 0,\n score REAL,\n content_hash TEXT,\n memory_version TEXT,\n deleted INTEGER NOT NULL DEFAULT 0,\n created_at TEXT DEFAULT (datetime('now')),\n PRIMARY KEY (trace_id, item_key)\n );\n CREATE INDEX IF NOT EXISTS idx_retrieval_trace_items_memory\n ON retrieval_trace_items(memory_kind, memory_id);\n CREATE INDEX IF NOT EXISTS idx_retrieval_trace_items_selected\n ON retrieval_trace_items(selected, memory_kind);\n`;\n\nexport function ensureRetrievalTraceItemsSchema(db: SQLiteDatabase): void {\n sqliteExec(db, RETRIEVAL_TRACE_ITEMS_DDL);\n}\n\n/** Content hash of the delivered excerpt. The excerpt itself is never stored. */\nexport function memoryContentHash(content: string | null | undefined): string | null {\n if (typeof content !== 'string' || content.length === 0) return null;\n return `sha256:${createHash('sha256').update(content).digest('hex').slice(0, 32)}`;\n}\n\nfunction tableExists(db: SQLiteDatabase, table: string): boolean {\n return sqliteAll<{ name: string }>(\n db,\n `SELECT name FROM sqlite_master WHERE type = 'table' AND name = ?`,\n [table]\n ).length > 0;\n}\n\n/**\n * Which memory tables actually contain an id. An id present in two tables stays\n * `unknown`/`ambiguous`: guessing a kind is exactly the failure mode that made\n * lesson selections look like dangling event ids.\n */\nexport function resolveMemoryRefKinds(\n db: SQLiteDatabase,\n ids: string[],\n options: { projectId?: string | null; allowedProjectIds?: string[] } = {}\n): Map<string, ResolvedMemoryRef> {\n const resolved = new Map<string, ResolvedMemoryRef>();\n const unique = Array.from(new Set(ids.filter((id) => typeof id === 'string' && id.length > 0)));\n if (unique.length === 0) return resolved;\n\n const matches = new Map<string, Set<MemoryKind>>();\n const projectById = new Map<string, string | null>();\n const addMatch = (id: string, kind: MemoryKind, projectId: string | null) => {\n const set = matches.get(id) ?? new Set<MemoryKind>();\n set.add(kind);\n matches.set(id, set);\n if (!projectById.has(id) || projectById.get(id) === null) projectById.set(id, projectId);\n };\n\n for (let i = 0; i < unique.length; i += 400) {\n const chunk = unique.slice(i, i + 400);\n const placeholders = chunk.map(() => '?').join(',');\n // The event store is one database per project, so an event's owning\n // project is the store's project scope rather than a per-row column.\n if (tableExists(db, 'events')) {\n for (const row of sqliteAll<{ id: string }>(\n db,\n `SELECT id FROM events WHERE id IN (${placeholders})`,\n chunk\n )) addMatch(row.id, 'event', options.projectId ?? null);\n }\n if (tableExists(db, 'memory_lessons')) {\n for (const row of sqliteAll<{ lesson_id: string; project_hash: string | null }>(\n db,\n `SELECT lesson_id, project_hash FROM memory_lessons WHERE lesson_id IN (${placeholders})`,\n chunk\n )) addMatch(row.lesson_id, 'lesson', row.project_hash ?? null);\n }\n if (tableExists(db, 'consolidated_rules')) {\n for (const row of sqliteAll<{ rule_id: string }>(\n db,\n `SELECT rule_id FROM consolidated_rules WHERE rule_id IN (${placeholders})`,\n chunk\n )) addMatch(row.rule_id, 'rule', null);\n }\n // Core blocks are delivered as the pseudo-id `core:<blockKey>`. The prefix\n // alone is a claim, not proof: resolve it against the block table so a\n // reference to a block that no longer exists is reported as unresolved\n // instead of being counted as a healthy core delivery (specs R1).\n if (tableExists(db, 'core_memory_blocks')) {\n const coreKeys = chunk\n .filter((id) => inferMemoryKindFromLegacyId(id) === 'core')\n .map((id) => id.slice('core:'.length));\n if (coreKeys.length > 0) {\n const corePlaceholders = coreKeys.map(() => '?').join(',');\n for (const row of sqliteAll<{ block_key: string; project_hash: string | null }>(\n db,\n `SELECT block_key, project_hash FROM core_memory_blocks WHERE block_key IN (${corePlaceholders})`,\n coreKeys\n )) {\n addMatch(\n `core:${row.block_key}`,\n 'core',\n row.project_hash && row.project_hash.length > 0 ? row.project_hash : (options.projectId ?? null)\n );\n }\n }\n }\n }\n\n const allowed = options.allowedProjectIds ? new Set(options.allowedProjectIds) : null;\n for (const id of unique) {\n const kinds = Array.from(matches.get(id) ?? []);\n const projectId = projectById.get(id) ?? null;\n if (kinds.length === 0) {\n resolved.set(id, { id, kind: 'unknown', projectId: options.projectId ?? null, resolution: 'unresolved', matchedKinds: [] });\n continue;\n }\n if (kinds.length > 1) {\n resolved.set(id, { id, kind: 'unknown', projectId, resolution: 'ambiguous', matchedKinds: kinds });\n continue;\n }\n // A reference the caller may not read is reported, never silently typed.\n if (allowed && projectId && !allowed.has(projectId)) {\n resolved.set(id, { id, kind: 'unknown', projectId, resolution: 'forbidden', matchedKinds: kinds });\n continue;\n }\n resolved.set(id, { id, kind: kinds[0], projectId, resolution: 'resolved', matchedKinds: kinds });\n }\n return resolved;\n}\n\nexport function normalizeTraceItems(\n items: RetrievalTraceItemInput[],\n defaults: { projectId?: string | null } = {}\n): RetrievalTraceItem[] {\n const byKey = new Map<string, RetrievalTraceItem>();\n items.forEach((item, index) => {\n if (!item || typeof item.id !== 'string' || item.id.length === 0) return;\n const kind = normalizeMemoryKind(item.kind);\n const projectId = item.projectId ?? defaults.projectId ?? null;\n // Scope-aware: the same kind/id in two projects is two memories under two\n // permission boundaries and must not collapse onto one row (specs R1).\n // The key is derived from the normalized identity. Accepting a caller's\n // arbitrary key would let two different refs collapse onto one row, or the\n // same ref occupy multiple rows with conflicting metadata.\n const itemKey = memoryRefKey({ projectId, kind, id: item.id });\n const score = typeof item.score === 'number' && Number.isFinite(item.score) ? item.score : null;\n const existing = byKey.get(itemKey);\n const normalized: RetrievalTraceItem = {\n traceId: '',\n itemKey,\n memoryKind: kind,\n memoryId: item.id,\n projectId,\n rank: typeof item.rank === 'number' && Number.isFinite(item.rank) ? Math.max(0, Math.floor(item.rank)) : index,\n selected: item.selected === true || existing?.selected === true,\n score: score ?? existing?.score ?? null,\n contentHash: item.contentHash ?? existing?.contentHash ?? null,\n memoryVersion: item.memoryVersion ?? existing?.memoryVersion ?? null,\n deleted: item.deleted === true || existing?.deleted === true\n };\n byKey.set(itemKey, existing ? { ...normalized, rank: existing.rank } : normalized);\n });\n return Array.from(byKey.values());\n}\n\nexport function writeTraceItems(\n db: SQLiteDatabase,\n traceId: string,\n items: RetrievalTraceItem[]\n): void {\n if (items.length === 0) return;\n for (const item of items) {\n sqliteRun(\n db,\n `INSERT INTO retrieval_trace_items (\n trace_id, item_key, memory_kind, memory_id, project_id, rank, selected, score,\n content_hash, memory_version, deleted\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(trace_id, item_key) DO UPDATE SET\n memory_kind = excluded.memory_kind,\n memory_id = excluded.memory_id,\n project_id = excluded.project_id,\n rank = excluded.rank,\n selected = MAX(retrieval_trace_items.selected, excluded.selected),\n score = COALESCE(excluded.score, retrieval_trace_items.score),\n content_hash = COALESCE(excluded.content_hash, retrieval_trace_items.content_hash),\n memory_version = COALESCE(excluded.memory_version, retrieval_trace_items.memory_version),\n deleted = MAX(retrieval_trace_items.deleted, excluded.deleted)`,\n [\n traceId, item.itemKey, item.memoryKind, item.memoryId, item.projectId,\n item.rank, item.selected ? 1 : 0, item.score,\n item.contentHash, item.memoryVersion, item.deleted ? 1 : 0\n ]\n );\n }\n}\n\nexport function readTraceItems(db: SQLiteDatabase, traceId: string): RetrievalTraceItem[] {\n if (!tableExists(db, 'retrieval_trace_items')) return [];\n return sqliteAll<Record<string, unknown>>(\n db,\n `SELECT * FROM retrieval_trace_items WHERE trace_id = ? ORDER BY rank ASC`,\n [traceId]\n ).map(rowToTraceItem);\n}\n\nfunction rowToTraceItem(row: Record<string, unknown>): RetrievalTraceItem {\n return {\n traceId: String(row.trace_id ?? ''),\n itemKey: String(row.item_key ?? ''),\n memoryKind: normalizeMemoryKind(row.memory_kind),\n memoryId: String(row.memory_id ?? ''),\n projectId: row.project_id === null || row.project_id === undefined ? null : String(row.project_id),\n rank: row.rank === null || row.rank === undefined ? null : Number(row.rank),\n selected: Number(row.selected) === 1,\n score: row.score === null || row.score === undefined ? null : Number(row.score),\n contentHash: row.content_hash === null || row.content_hash === undefined ? null : String(row.content_hash),\n memoryVersion: row.memory_version === null || row.memory_version === undefined ? null : String(row.memory_version),\n deleted: Number(row.deleted) === 1\n };\n}\n\n/**\n * Typed selections for a window. Traces that already have typed items are read\n * as-is; older traces are resolved read-only from their legacy arrays so a\n * report can reproduce the historical event/lesson split without a migration.\n */\nexport function summarizeTypedSelections(\n db: SQLiteDatabase,\n options: { since?: Date; until?: Date; resolveLegacy?: boolean } = {}\n): TypedSelectionSummary {\n const summary = emptyTypedSelectionSummary();\n if (!tableExists(db, 'retrieval_traces')) return summary;\n\n const clauses: string[] = [];\n const params: unknown[] = [];\n if (options.since) {\n clauses.push('julianday(created_at) >= julianday(?)');\n params.push(options.since.toISOString());\n }\n if (options.until) {\n clauses.push('julianday(created_at) < julianday(?)');\n params.push(options.until.toISOString());\n }\n const where = clauses.length > 0 ? ` WHERE ${clauses.join(' AND ')}` : '';\n const traces = sqliteAll<{ trace_id: string; selected_event_ids: string | null; project_hash: string | null }>(\n db,\n `SELECT trace_id, selected_event_ids, project_hash FROM retrieval_traces${where}`,\n params\n );\n\n const hasItems = tableExists(db, 'retrieval_trace_items');\n const legacyTraces: typeof traces = [];\n for (const trace of traces) {\n const typed = hasItems ? readTraceItems(db, trace.trace_id) : [];\n if (typed.length > 0) {\n summary.typedTraces += 1;\n for (const item of typed) {\n if (!item.selected) continue;\n summary.byKind[item.memoryKind] += 1;\n summary.total += 1;\n if (item.memoryKind === 'unknown') summary.unresolved += 1;\n }\n continue;\n }\n legacyTraces.push(trace);\n }\n\n if (options.resolveLegacy === false) return summary;\n\n const legacyIds: string[] = [];\n const perTrace: Array<{ traceId: string; ids: string[]; projectId: string | null }> = [];\n for (const trace of legacyTraces) {\n let ids: string[] = [];\n try {\n const parsed = JSON.parse(trace.selected_event_ids || '[]');\n if (Array.isArray(parsed)) ids = parsed.filter((id): id is string => typeof id === 'string');\n } catch { /* corrupt legacy array contributes nothing */ }\n if (ids.length === 0) continue;\n perTrace.push({ traceId: trace.trace_id, ids, projectId: trace.project_hash ?? null });\n legacyIds.push(...ids);\n }\n if (perTrace.length === 0) return summary;\n\n const resolvedById = resolveMemoryRefKinds(db, legacyIds);\n for (const entry of perTrace) {\n summary.legacyResolvedTraces += 1;\n for (const id of entry.ids) {\n const ref = resolvedById.get(id);\n const kind = ref?.resolution === 'resolved' ? ref.kind : 'unknown';\n summary.byKind[kind] += 1;\n summary.total += 1;\n if (ref?.resolution === 'ambiguous') summary.ambiguous += 1;\n else if (!ref || ref.resolution !== 'resolved') summary.unresolved += 1;\n }\n }\n return summary;\n}\n\nexport interface TraceItemBackfillResult {\n dryRun: boolean;\n scannedTraces: number;\n tracesWithItems: number;\n writtenItems: number;\n byKind: Record<MemoryKind, number>;\n unresolved: number;\n ambiguous: number;\n}\n\n/**\n * Explicit, opt-in backfill of typed items for legacy traces. Reports never\n * call this: reading is done with the resolver above so a read-only audit\n * cannot mutate a user's store.\n */\nexport function backfillTraceItems(\n db: SQLiteDatabase,\n options: { dryRun?: boolean; limit?: number; since?: Date } = {}\n): TraceItemBackfillResult {\n const dryRun = options.dryRun !== false;\n const limit = Math.min(Math.max(options.limit ?? 1000, 1), 100_000);\n const result: TraceItemBackfillResult = {\n dryRun,\n scannedTraces: 0,\n tracesWithItems: 0,\n writtenItems: 0,\n byKind: Object.fromEntries(MEMORY_KINDS.map((kind) => [kind, 0])) as Record<MemoryKind, number>,\n unresolved: 0,\n ambiguous: 0\n };\n if (!tableExists(db, 'retrieval_traces')) return result;\n if (!dryRun) ensureRetrievalTraceItemsSchema(db);\n // A dry run against a store that predates the typed table still previews\n // every legacy trace: creating the table just to count would be a write.\n const hasItemsTable = tableExists(db, 'retrieval_trace_items');\n if (!dryRun && !hasItemsTable) return result;\n\n const clauses: string[] = [];\n const params: unknown[] = [];\n if (options.since) {\n clauses.push('julianday(t.created_at) >= julianday(?)');\n params.push(options.since.toISOString());\n }\n if (hasItemsTable) {\n clauses.push('NOT EXISTS (SELECT 1 FROM retrieval_trace_items i WHERE i.trace_id = t.trace_id)');\n }\n // Empty traces never gain typed rows, so letting them consume the limit\n // would select the same empty batch forever. Filter usable arrays before\n // LIMIT, including corrupt legacy JSON and arrays without string IDs.\n clauses.push(`(${['candidate_event_ids', 'selected_event_ids'].map((column) =>\n `EXISTS (SELECT 1 FROM json_each(\n CASE WHEN json_valid(t.${column}) THEN\n CASE WHEN json_type(t.${column}) = 'array' THEN t.${column} ELSE '[]' END\n ELSE '[]' END\n ) AS id WHERE id.type = 'text' AND length(trim(id.value)) > 0)`\n ).join(' OR ')})`);\n params.push(limit);\n\n const traces = sqliteAll<{\n trace_id: string;\n selected_event_ids: string | null;\n candidate_event_ids: string | null;\n project_hash: string | null;\n }>(\n db,\n `SELECT t.trace_id, t.selected_event_ids, t.candidate_event_ids, t.project_hash\n FROM retrieval_traces t\n ${clauses.length > 0 ? `WHERE ${clauses.join(' AND ')}` : ''}\n ORDER BY t.created_at DESC\n LIMIT ?`,\n params\n );\n\n for (const trace of traces) {\n result.scannedTraces += 1;\n const selected = parseIdArray(trace.selected_event_ids);\n const candidates = parseIdArray(trace.candidate_event_ids);\n const all = Array.from(new Set([...candidates, ...selected]));\n if (all.length === 0) continue;\n const resolvedById = resolveMemoryRefKinds(db, all, { projectId: trace.project_hash ?? null });\n const items = normalizeTraceItems(\n all.map((id, index) => {\n const ref = resolvedById.get(id);\n if (ref?.resolution === 'ambiguous') result.ambiguous += 1;\n else if (!ref || ref.resolution !== 'resolved') result.unresolved += 1;\n const kind = ref?.resolution === 'resolved' ? ref.kind : 'unknown';\n result.byKind[kind] += 1;\n return {\n kind,\n id,\n projectId: ref?.projectId ?? trace.project_hash ?? null,\n rank: index,\n selected: selected.includes(id),\n // An id that resolves to no row today may have been deleted, may\n // predate a table, or may live in a store this reader cannot see.\n // `deleted` is reserved for an observed deletion; an unresolved\n // reference stays kind `unknown` and is counted as unresolved.\n deleted: false\n };\n }),\n { projectId: trace.project_hash ?? null }\n );\n result.tracesWithItems += 1;\n result.writtenItems += items.length;\n if (!dryRun) writeTraceItems(db, trace.trace_id, items);\n }\n return result;\n}\n\nfunction parseIdArray(value: string | null): string[] {\n if (!value) return [];\n try {\n const parsed = JSON.parse(value);\n return Array.isArray(parsed) ? parsed.filter((id): id is string => typeof id === 'string' && id.length > 0) : [];\n } catch {\n return [];\n }\n}\n"],
5
+ "mappings": "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AAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;A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",
6
6
  "names": ["createHash", "randomUUID", "isAbsolute", "join", "z", "existsSync", "readFileSync", "join", "text", "join", "existsSync", "readFileSync", "fs", "path", "snapshot", "text", "z", "z", "fs", "os", "path", "relative", "path", "snapshot", "z", "randomUUID", "randomUUID", "z", "z", "z", "z", "ActorIdSchema", "z", "randomUUID", "z", "z", "z", "parseStringArray", "projectHashToStorage", "projectHashFromStorage", "saved", "randomUUID", "randomUUID", "createHash", "createHash", "createHash", "nodePath", "fs", "os", "path", "fs", "path", "randomUUID", "status", "text", "tokens", "status", "status", "randomUUID", "tableExists", "traceId", "randomUUID", "path", "basename", "randomUUID", "embeddingRecovered", "embeddingRetried", "vectorRecovered", "vectorRetried", "status", "z", "createHash", "text", "resolve", "randomUUID", "event", "response", "status", "isAbsolute", "join"]
7
7
  }