@equationalapplications/core-llm-wiki 7.7.0 → 7.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/db/sqliteCodes.ts","../src/types.ts","../src/utils/ids.ts","../src/utils/ontology.ts","../src/utils/embedding.ts","../src/utils/cosine.ts","../src/services/SearchService.ts","../src/services/JobManager.ts","../src/utils/pure.ts","../src/prompts.ts","../src/utils/healConstants.ts","../src/utils/grounding.ts","../src/services/PromptService.ts","../src/utils/chunkingDefaults.ts","../src/utils/diagnostics.ts","../src/services/IngestionService.ts","../src/utils/classifier.ts","../src/repositories/BaseRepository.ts","../src/repositories/MetadataRepository.ts","../src/services/BoundedLlmCall.ts","../src/services/MaintenanceService.ts","../src/services/ImportExportService.ts","../src/utils/embedDefaults.ts","../src/services/EmbeddingService.ts","../src/readOptions.ts","../src/services/RetrievalService.ts","../src/services/WriteService.ts"],"names":["rows","documents","result","entries","counts","entityId"],"mappings":"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","file":"chunk-VOSMYISQ.mjs","sourcesContent":["/**\n * SQLite primary result codes → symbolic name (https://sqlite.org/rescode.html),\n * so a numeric expo-sqlite code normalizes to the same shape as the string codes\n * better-sqlite3 / node:sqlite already report (e.g. both become 'SQLITE_BUSY').\n *\n * Dependency-free leaf module: shared by `db/serializedAdapter.ts` and `types.ts`\n * (via `WikiTransactionError`) so the mapping has a single source of truth.\n */\nconst SQLITE_RESULT_CODE_NAMES: Record<number, string> = {\n 1: 'SQLITE_ERROR', 2: 'SQLITE_INTERNAL', 3: 'SQLITE_PERM', 4: 'SQLITE_ABORT',\n 5: 'SQLITE_BUSY', 6: 'SQLITE_LOCKED', 7: 'SQLITE_NOMEM', 8: 'SQLITE_READONLY',\n 9: 'SQLITE_INTERRUPT', 10: 'SQLITE_IOERR', 11: 'SQLITE_CORRUPT', 12: 'SQLITE_NOTFOUND',\n 13: 'SQLITE_FULL', 14: 'SQLITE_CANTOPEN', 15: 'SQLITE_PROTOCOL', 16: 'SQLITE_EMPTY',\n 17: 'SQLITE_SCHEMA', 18: 'SQLITE_TOOBIG', 19: 'SQLITE_CONSTRAINT', 20: 'SQLITE_MISMATCH',\n 21: 'SQLITE_MISUSE', 22: 'SQLITE_NOLFS', 23: 'SQLITE_AUTH', 24: 'SQLITE_FORMAT',\n 25: 'SQLITE_RANGE', 26: 'SQLITE_NOTADB', 27: 'SQLITE_NOTICE', 28: 'SQLITE_WARNING',\n // Extended result codes (https://sqlite.org/rescode.html#extended_result_code_list).\n // 2067 = SQLITE_CONSTRAINT_UNIQUE — raised when a UNIQUE index/PRIMARY KEY\n // rejects an INSERT/UPDATE; expo-sqlite reports this as a numeric \"Error code N:\"\n // prefix and we normalize it back to the symbolic name so callers can branch on\n // the same string the rest of the ecosystem uses.\n 2067: 'SQLITE_CONSTRAINT_UNIQUE',\n 100: 'SQLITE_ROW', 101: 'SQLITE_DONE',\n};\n\n/** Falls back to `SQLITE_<n>` for a result code outside the known table. */\nexport function nameForSqliteResultCode(n: number): string {\n return SQLITE_RESULT_CODE_NAMES[n] ?? `SQLITE_${n}`;\n}\n\n/**\n * Best-effort SQLite code extraction. Driver-specific:\n * better-sqlite3 / node:sqlite: err.code === 'SQLITE_BUSY' (string, SQLITE_-prefixed)\n * expo-sqlite: err.message starts with 'Error code N: …' (numeric,\n * normalized here to the same symbolic name)\n */\nexport function extractSqliteCode(err: unknown): string | undefined {\n if (typeof err !== 'object' || err === null) return undefined;\n const { code, message } = err as { code?: unknown; message?: unknown };\n if (typeof code === 'string' && code.startsWith('SQLITE_')) return code;\n if (typeof message === 'string') {\n const m = /^Error code (\\d+):/.exec(message);\n if (m) return nameForSqliteResultCode(Number(m[1]));\n }\n return undefined;\n}\n","import { extractSqliteCode } from './db/sqliteCodes';\nimport type {\n OkfSource,\n OkfSourceUsageWindow,\n OkfVerifiedEntry,\n} from '@equationalapplications/core-okf';\n\n/**\n * Platform-agnostic SQLite driver interface.\n * Each platform package (wiki-expo, wiki-react) provides an adapter\n * that wraps its native driver behind this interface.\n */\nexport interface SQLiteAdapter {\n execAsync(sql: string): Promise<void>;\n /**\n * `changes` must report the number of rows the statement actually wrote.\n * It must be 0 when a conflict clause suppresses a write (INSERT OR IGNORE,\n * or ON CONFLICT DO UPDATE ... WHERE), and must never be nonzero for a\n * suppressed write. A permitted write that modifies no column value still\n * counts the row, as SQLite does.\n *\n * This count is load-bearing beyond ownership checks: edge insertion\n * (and therefore upsertGraph's public edgesWritten), metadata compare-and-set,\n * soft-delete success reporting, and maintenance sweep counts all read it.\n * An adapter that under-reports silently corrupts those results.\n */\n runAsync(sql: string, params?: unknown[]): Promise<{ changes: number; lastInsertRowId: number }>;\n getAllAsync<T>(sql: string, params?: unknown[]): Promise<T[]>;\n getFirstAsync<T>(sql: string, params?: unknown[]): Promise<T | null>;\n /**\n * Runs `fn` inside a transaction. A bare adapter implementation is not required to\n * serialize concurrent calls itself — `WikiMemory` wraps every adapter it's given in\n * `withSerializedTransactions` (see `db/serializedAdapter.ts`), which is what makes\n * transactions serialize in practice. Once wrapped, inside the callback use ONLY the\n * provided `tx` handle — never the outer database handle (captured via closure or\n * `this.db`). Calling the outer handle deadlocks against the transaction mutex;\n * calling `tx.withTransactionAsync` throws (nested transactions are unsupported).\n */\n withTransactionAsync<T>(fn: (tx: SQLiteAdapter) => Promise<T>): Promise<T>;\n closeAsync(): Promise<void>;\n}\n\nexport interface PromptOverrides {\n ingestSystemPrompt?: string;\n librarianSystemPrompt?: string;\n healSystemPrompt?: string;\n ontologyBackfillSystemPrompt?: string;\n}\n\nexport type OntologyMode = 'strict' | 'emergent' | 'off';\n\nexport interface OntologyNodeType {\n type: string;\n description: string;\n /** Optional parent type slug. One level only — the parent must exist in the\n * same manifest and must not itself declare a `parent_type`. */\n parent_type?: string;\n}\n\nexport interface OntologyEdgeType {\n type: string;\n source_type: string;\n target_type: string;\n description: string;\n}\n\n/**\n * Allowed node and edge types for an entity's ontology graph.\n * Persisted per entity and injected into librarian/ingest prompts when mode ≠ `off`.\n */\nexport interface OntologyManifest {\n node_types: OntologyNodeType[];\n edge_types: OntologyEdgeType[];\n}\n\n/**\n * Global ontology defaults and bootstrap manifests for known entities.\n * Per-entity mode and manifest overrides are stored in SQLite and managed via\n * `WikiMemory.getOntologyManifest` / `setOntologyManifest`.\n */\nexport interface OntologyConfig {\n /** Global default mode. Default: `'off'` (backward compatible — no typed extraction). */\n mode?: OntologyMode;\n /**\n * Bootstrap manifests for known entities at construction time.\n * Written to the database on first access if no row exists for that entity.\n */\n seedManifests?: Record<string, {\n manifest: OntologyManifest;\n mode?: OntologyMode;\n }>;\n /**\n * Engine default for `runOntologyBackfill`'s `classifier` option.\n * `'auto'` uses `llmProvider.classify` for node typing when present\n * (no edges are proposed); `'llm'` always uses `generateText`. Default `'llm'`.\n */\n backfillClassifier?: 'auto' | 'llm';\n /** Minimum classifier confidence to apply a node type. Finite, in [0, 1]. Default 0.5. */\n classifyMinConfidence?: number;\n}\n\nexport interface ExtractedFactEdge {\n edge_type: string;\n target_title: string;\n}\n\nexport interface OntologyUpdates {\n node_types?: OntologyNodeType[];\n edge_types?: OntologyEdgeType[];\n}\n\nexport interface OntologyPromptContext {\n ontologyManifest: string;\n ontologyModeInstructions: string;\n}\n\n/** Result of a single ontology backfill run. Omissions (facts the model declined\n * to classify) are derivable as scanned − typed − failedValidation. */\nexport interface OntologyBackfillResult {\n /** Untyped facts sent to the model this run. */\n scanned: number;\n /** Facts that received an okf_type. */\n typed: number;\n /** Model classifications rejected (unknown/duplicate id, non-manifest type). */\n failedValidation: number;\n /** Edges persisted. */\n edgesAdded: number;\n /** Untyped facts still eligible after this run — safe host convergence signal: loop while > 0.\n * Always 0 when ontology mode is 'off' (nothing is eligible for typing while\n * disabled), so 0 does not imply queue exhaustion in that mode. */\n remaining: number;\n /** Untyped facts inside the recheck cooldown. */\n deferred: number;\n /** Facts a batch could not process even alone, skipped so the pass could finish.\n * Stamped with the recheck cooldown, so they reappear as `deferred` next pass. */\n skipped: number;\n}\n\n/** Result of a single `runReembed` sweep. */\nexport interface ReembedResult {\n /** Facts successfully (re-)embedded this sweep. */\n embedded: number;\n /** Facts with a valid existing embedding left untouched because\n * `skipExisting` was in effect (and no dimension mismatch forced a re-embed). */\n skipped: number;\n /** Facts whose embed attempt ran and failed this sweep. Includes\n * `storage_error` failures, which are not backoff-tracked (a marker is\n * itself a DB write — see the reembed README section). Convergence loops\n * should test this counter, never `deferred`. */\n failed: number;\n /** Previously failed facts still inside their exponential backoff window\n * (60s doubling, capped at 24h), not attempted this sweep. Not an error;\n * a later sweep retries them once the window elapses. */\n deferred: number;\n /** Facts excluded for good: a `float32_overflow` failure or 5 failed\n * lifetime attempts. `{ force: true }` retries these anyway. */\n permanentlyFailed: number;\n}\n\n/**\n * L3 heal-success record: a fact the model emitted a verdict for under a\n * truncated view of its own body. `originalBodyChars` lets an operator flag\n * the fact for re-inspection; `truncatedBodyChars` is the L3 cap actually\n * applied. Emitted by `PromptService.buildHealPrompt`, surfaced via\n * `HealResult.degraded`, mutually exclusive with `HealResult.skipped` on\n * `id` (a fact can be either healed-under-degradation or dropped — never\n * both).\n */\nexport interface DegradedRecord {\n id: string;\n originalBodyChars: number;\n truncatedBodyChars: number;\n}\n\n/** Result of a single heal run. */\nexport interface HealResult {\n /**\n * Heal candidates sent to the model this run. Counts candidates whose batch\n * came back unusable and landed in `skipped` as well — they reached the\n * provider too, so this is provider exposure, not successful throughput.\n */\n scanned: number;\n /**\n * Facts whose confidence was lowered to `tentative` — the stale-inferred SQL\n * pass (`inferred` → `tentative`) plus any model-directed downgrades, deduped.\n */\n downgraded: number;\n /** Facts soft-deleted — the orphan-marking SQL pass plus model-directed deletes, deduped. */\n deleted: number;\n /** New facts synthesized by heal. */\n newFactsCreated: number;\n /**\n * Candidates that could not converge after the helper's full escalation\n * path. `reason` distinguishes genuine non-convergence\n * (`'non_convergent'` — terminal give-up at attemptLevel 3, parse error,\n * or model-config error) from transient provider failures\n * (`'call_error'` — non-truncation error originating in `call()` at\n * `batch.length === 1`). `doRunHeal` excludes `'call_error'` ids from\n * `markHealChecked`'s cooldown stamp so a momentary provider hiccup does\n * not lock the fact out for `HEAL_RECHECK_MS`. Mutually exclusive with\n * `degraded` on `id`.\n */\n skipped: Array<{ id: string; reason: 'non_convergent' | 'call_error' }>;\n /**\n * L3 heal successes: facts the model emitted a verdict for under a\n * truncated view of their own body. Each entry carries the truncation\n * magnitude so an operator can flag the fact for re-inspection. The\n * corresponding log line `[WikiMemory] heal healed under degraded\n * context ...` fires for each entry. Mutually exclusive with `skipped`\n * on `id` — the reconciliation step in doRunHeal drops any record\n * whose id also appears in `skipped` (a contradiction: degraded means\n * healed, skipped means dropped).\n */\n degraded: Array<DegradedRecord>;\n /**\n * Heal candidates still eligible after this run — convergence signal: loop while > 0.\n *\n * This does NOT mean what it means for OntologyBackfillResult. Untyped facts are\n * a finite backlog that drains permanently; heal's candidates are the live mutable\n * corpus. `remaining === 0` means \"every mutable fact is inside the recheck\n * cooldown\", not \"there is no more work\" — it climbs back as the cooldown lapses\n * and as new facts are written. A host loop terminates, but it converges to\n * \"corpus swept once this cooldown window\", not to a drained queue.\n */\n remaining: number;\n /** Heal candidates inside the recheck cooldown. */\n deferred: number;\n}\n\n/**\n * Opt-in evidence check for LLM-authored facts (spec §6). Default off: 7.x\n * write behavior is unchanged. In `'draft'` mode, writers in `writers` must\n * quote their source; a fact whose quotes are missing or not found is stored\n * as a `draft` instead of being rejected.\n */\nexport interface GroundingConfig {\n mode: 'off' | 'draft';\n /** Default `['ingest']`. The librarian and heal synthesize across events; measure their pass rates before opting them in. */\n writers?: Array<'ingest' | 'librarian' | 'heal'>;\n /** Quotes shorter than this (after whitespace normalization) count as absent. Default 20. */\n minEvidenceChars?: number;\n /** Quotes retained per fact. Retention only; every quote is checked. Default 3. */\n maxEvidence?: number;\n /** Characters retained per quote. Default 300. */\n maxEvidenceChars?: number;\n}\n\nexport interface WikiConfig {\n /**\n * Prefix applied to every SQL table/index/trigger name. Must match\n * `^[A-Za-z][A-Za-z0-9_]{0,30}_$` (letter, then alphanumeric/underscore,\n * ending in `_`, max 32 chars total) — enforced in the `WikiMemory` constructor.\n * Default: `'llm_wiki_'`.\n */\n tablePrefix?: string;\n maxResults?: number;\n /** @deprecated Use maxResults */\n maxFtsResults?: number;\n pruneEventsAfter?: number;\n pruneRetainSoftDeletedFor?: number;\n autoLibrarianThreshold?: number;\n autoHealThreshold?: number;\n orphanAfterDays?: number | null;\n staleInferredAfterDays?: number | null;\n maxChunkLength?: number;\n chunkOverlap?: number;\n chunkConcurrency?: number;\n /**\n * Maximum characters of `title + body + tags` passed to `llmProvider.embed()`\n * when embedding a fact. Longer input is clipped, not rejected.\n *\n * Default 6000 (~1,500 tokens), which fits common embedding windows including\n * nomic-embed-text's 2,048 tokens with headroom. Values above the 16,000\n * hard ceiling are clamped to it; the ceiling is a security control and\n * configuration cannot raise it.\n */\n maxEmbedChars?: number;\n /**\n * Max MiniSearch candidates passed to cosine scoring.\n * When set, MiniSearch pre-filters before the cosine scan.\n * Only applies when embed is provided and succeeds.\n * Default: undefined (full scan).\n */\n preFilterLimit?: number;\n /**\n * Hybrid blend weight (0.0–1.0).\n * 0.0 = pure keyword (skips embed() entirely).\n * 1.0 = pure semantic.\n * Values outside [0,1] are clamped. Ignored when embed is absent or throws.\n * Default: undefined (pure semantic when embed provided).\n */\n hybridWeight?: number;\n /**\n * Global prompt overrides for text generation calls (`ingestDocument`, `runLibrarian`, `runHeal`). Does not affect embedding generation. Runtime overrides on individual method calls take precedence.\n *\n * Returned verbatim by `getInstructions` and the `wiki_get_instructions` tool (`memory:read`): never put secrets, API keys or private data here.\n */\n prompts?: PromptOverrides;\n /**\n * When true, entry and task mutations append an event to the internal outbox table.\n * The table is always created; this flag only controls whether writes occur.\n * @default false\n */\n enableOutbox?: boolean;\n ontology?: OntologyConfig;\n /** Default node cap for traverseGraph(), unless overridden per-call. Default 20. */\n maxTraversalNodes?: number;\n /** Default minimum confidence tier for discovered traversal nodes. Default 'tentative'. */\n minTraversalConfidence?: 'certain' | 'inferred' | 'tentative';\n /** Default traversal direction. Default 'both'. */\n traversalDirection?: 'inbound' | 'outbound' | 'both';\n /** Default source_type dead-end list for discovered traversal nodes. Default []. */\n excludeSourceTypes?: Array<WikiFact['source_type']>;\n /**\n * Engine default for `ReadOptions.excludeDrafts` and\n * `GraphTraversalOptions.excludeDrafts`. Default false (drafts visible).\n */\n excludeDrafts?: boolean;\n /** Evidence check for LLM-authored facts (spec §6). Default off. */\n grounding?: GroundingConfig;\n}\n\nexport interface ReadOptions {\n maxResults?: number;\n /**\n * undefined → use WikiConfig.preFilterLimit (or no pre-filter if also unset).\n * null → explicitly disable a config-level preFilterLimit for this call.\n */\n preFilterLimit?: number | null;\n hybridWeight?: number;\n /**\n * Per-entity score multiplier for multi-entity reads. Missing entries default to 1.0.\n * Entities with weight 0 are skipped during scored retrieval unless\n * `includeZeroWeightEntities` is true; in that case they rank below all finite scores.\n * Only meaningful when `entityId` is an array; ignored for single-string calls.\n */\n tierWeights?: Record<string, number>;\n /**\n * When true, entities with a tier weight of 0 are included in scored retrieval\n * as bottom fillers (ranked below every finite-scored candidate).\n * When false (default), zero-weight entities are skipped entirely.\n * Only meaningful when `entityId` is an array; ignored for single-string calls.\n */\n includeZeroWeightEntities?: boolean;\n /**\n * Minimum number of results to retain from each named entity before the global\n * `maxResults` cut. Applied after scoring: the top-N scored results from each\n * named entity are reserved, then remaining slots fill by score as usual.\n *\n * An entity with fewer than N matching results contributes what it has — this is\n * not an error. Floors cannot resurrect a result excluded by `preFilterLimit`.\n *\n * Only meaningful when `entityId` is an array; ignored for single-string calls.\n * Ignored when `query` is empty — that path uses recency ordering and ignores\n * `tierWeights` as well.\n *\n * Throws `WikiInvalidReadOptions` when a floor cannot be satisfied by\n * construction: floors summing above `maxResults`, a floor on an entity excluded\n * by `tierWeights: 0`, or a floor keyed to an entity not in `entityId`.\n */\n tierFloors?: Record<string, number>;\n /**\n * When true, facts whose `lifecycle_status` is `'draft'` are excluded before\n * `maxResults`, `tierFloors` and every other cut, on every read path.\n * Resolves call → `WikiConfig.excludeDrafts` → false.\n */\n excludeDrafts?: boolean;\n}\n\nexport interface WikiFact {\n id: string;\n entity_id: string;\n title: string;\n body: string;\n tags: string[];\n confidence: 'certain' | 'inferred' | 'tentative';\n /**\n * Source type of this fact.\n * - 'immutable_document': From ingestDocument(), cannot be modified by system (librarian/heal).\n * Only removable via forget() or replaced via re-ingest.\n * - 'librarian_inferred': Created by runLibrarian() from events, or by runHeal() when synthesizing new inferred facts.\n * - 'user_stated': Direct user statement.\n * - 'user_confirmed': User-confirmed fact.\n */\n source_type: 'user_stated' | 'librarian_inferred' | 'user_confirmed' | 'immutable_document';\n source_hash: string | null;\n source_ref: string | null;\n created_at: number;\n updated_at: number;\n /**\n * Raw Float32Array bytes for the fact's embedding vector.\n * Set when the fact was fetched via exportDump() with blob preservation.\n * Accepted in importDump() as a real Uint8Array (in-memory round-trip),\n * a Node.js Buffer JSON shape `{ type: 'Buffer', data: number[] }`,\n * or a numeric-keyed plain object `{ 0: byte, 1: byte, ... }` produced\n * by JSON.stringify(Uint8Array).\n */\n embedding_blob?: Uint8Array | { type: 'Buffer'; data: number[] } | Record<string, number> | null;\n last_accessed_at: number | null;\n access_count: number;\n deleted_at: number | null;\n /**\n * Verbatim OKF `type:` frontmatter value when this fact originated from (or was\n * re-imported via) an OKF bundle. `null`/`undefined` for facts never touched by\n * OKF import. Distinct from `source_type`, which governs immutability rules.\n */\n okf_type?: string | null;\n // --- OKF v0.2 surface (additive; see spec §4.6) ---\n /** OKF v0.2 lifecycle state. Defaults to 'stable' on the SQL side. */\n lifecycle_status?: 'draft' | 'stable' | 'deprecated';\n /** Absolute YYYY-MM-DD cutoff for staleness. NULL = never stale. */\n stale_after?: number | null;\n /** Actor string per OKF v0.2 §7 (`<producer>/<version>`, `human:<id>`, `process:<id>`). */\n generated_by?: string | null;\n /** Full list of OKF v0.2 sources (provenance). */\n okf_sources?: OkfSource[];\n /** Chronological list of verification events. */\n okf_verified?: OkfVerifiedEntry[];\n /** Sibling-of-sources usage window object. */\n okf_usage_window?: OkfSourceUsageWindow | null;\n /** Convenience: epoch ms of the latest verifier. Derived; mirrored for query speed. */\n last_verified_at?: number | null;\n /** Convenience: actor string of the latest verifier. Derived; mirrored for query speed. */\n last_verified_by?: string | null;\n /**\n * Hydrated at read time: `isStaleAfter(stale_after, now)`. `true` once the\n * absolute stale_after cutoff has passed; `false` otherwise (including when\n * stale_after is null). Surfaced per spec §2.7 + §5.3 so hosts can render\n * staleness without recomputing. Always present on read paths that go\n * through `mapRowToFact` / `mapRowToTask`.\n */\n isStale?: boolean;\n /**\n * Hydrated at read time: `deriveTrustTier(okf_verified)`. `'human-reviewed'`\n * when any entry has `by: 'human:...'`, `'machine-confirmed'` when entries\n * exist without a human verifier, `'unverified'` when okf_verified is empty.\n * Surfaced per spec §2.7 + §5.3. Always present on read paths that go through\n * `mapRowToFact` / `mapRowToTask`.\n */\n trustTier?: 'unverified' | 'machine-confirmed' | 'human-reviewed';\n}\n\nexport interface WikiTask {\n id: string;\n entity_id: string;\n description: string;\n status: 'pending' | 'in_progress' | 'done' | 'abandoned';\n priority: number;\n created_at: number;\n updated_at: number;\n resolved_at: number | null;\n deleted_at: number | null;\n /** Verbatim OKF `type:` frontmatter value when this task originated from an OKF bundle. */\n okf_type?: string | null;\n // --- OKF v0.2 surface (additive; see spec §4.6) ---\n lifecycle_status?: 'draft' | 'stable' | 'deprecated';\n stale_after?: number | null;\n generated_by?: string | null;\n okf_sources?: OkfSource[];\n okf_verified?: OkfVerifiedEntry[];\n okf_usage_window?: OkfSourceUsageWindow | null;\n last_verified_at?: number | null;\n last_verified_by?: string | null;\n /**\n * Hydrated at read time: `isStaleAfter(stale_after, now)`. Mirrors\n * {@link WikiFact.isStale} (spec §2.5 + §5.3 treat stale_after symmetrically\n * for tasks and facts). Always present on read paths that go through\n * `mapRowToTask`.\n */\n isStale?: boolean;\n /**\n * Hydrated at read time: `deriveTrustTier(okf_verified)`. Mirrors\n * {@link WikiFact.trustTier}. Always present on read paths that go through\n * `mapRowToTask`.\n */\n trustTier?: 'unverified' | 'machine-confirmed' | 'human-reviewed';\n}\n\nexport interface WikiEvent {\n id: string;\n entity_id: string;\n event_type: 'observation' | 'decision' | 'action' | 'outcome';\n summary: string;\n related_entry_id?: string | null;\n created_at: number;\n}\n\nexport interface WikiEdge {\n id: string;\n entity_id: string;\n source_id: string;\n target_id: string;\n edge_type: string;\n created_at: number;\n}\n\nexport interface GraphTraversalOptions {\n sourceId: string;\n /** Hop count. Default 1. Clamped to [1, 3] regardless of input. */\n maxDepth?: number;\n /** Default 'both'. Falls back to WikiConfig.traversalDirection, then 'both'. */\n direction?: 'inbound' | 'outbound' | 'both';\n /**\n * Allowed edge types. `undefined` = no filter (all types).\n * `[]` (explicit empty array) = match nothing — distinct from `undefined`.\n */\n edgeTypes?: string[];\n /** Total node cap (anchor + neighbors). Default 20 via WikiConfig.maxTraversalNodes. */\n maxTraversalNodes?: number;\n /** Minimum confidence tier for *discovered* nodes. Does not gate the anchor. Default 'tentative'. */\n minTraversalConfidence?: 'certain' | 'inferred' | 'tentative';\n /** source_type values to dead-end on for *discovered* nodes. Does not gate the anchor. Default []. */\n excludeSourceTypes?: Array<WikiFact['source_type']>;\n /**\n * When true, draft facts are dead ends for *discovered* nodes (not\n * discovered, not traversed through). Does not gate the anchor.\n * Resolves call → `WikiConfig.excludeDrafts` → false.\n */\n excludeDrafts?: boolean;\n}\n\nexport interface GraphNeighborhood {\n /** Anchor node first, then discovered neighbors ordered by depth ASC, then updated_at DESC. */\n nodes: WikiFact[];\n /** Only edges where both endpoints are present in `nodes`. */\n edges: WikiEdge[];\n}\n\nexport interface WikiCheckpoint {\n entity_id: string;\n heal_checkpoint: number;\n memory_checkpoint: number;\n}\n\nexport interface ExtractedFact {\n title: string;\n body: string;\n tags: string[];\n confidence: 'certain' | 'inferred' | 'tentative';\n /** Quotes the model copied from its source; see `WikiConfig.grounding`. Never persisted. */\n evidence?: string[];\n}\n\nexport interface ExtractedFactWithOntology extends ExtractedFact {\n okf_type?: string;\n edges?: ExtractedFactEdge[];\n}\n\nexport interface ExtractedTask {\n description: string;\n priority: number;\n}\n\nexport interface LLMProvider {\n /**\n * Generates text using the developer's LLM of choice.\n * Expected to return the raw text response (typically a JSON string).\n * Called with the provider as `this`, so class-based adapters may keep\n * SDK handles and config on the instance.\n */\n generateText: (params: { systemPrompt: string; userPrompt: string }) => Promise<string>;\n /**\n * Optional. When provided, enables semantic similarity search in `read()`.\n * Must return a stable-dimension float array for any input text.\n * Called once per fact on creation/update, and once per `read()` query.\n * When absent or throws, `read()` falls back to MiniSearch.\n * Called with the provider as `this` (never detached), same as\n * `generateText`, so class-based adapters may read their own state.\n */\n embed?: (text: string) => Promise<number[]>;\n /**\n * Optional. The provider's hard output-token ceiling for `generateText`.\n * Core cannot observe it — the token budget lives entirely in the host's\n * adapter — so maintenance passes that generate response-size-proportional\n * output size their batches blind unless this is declared.\n *\n * When absent, batching falls back to a conservative default and adapts\n * downward on failure. When present, it is used as a sizing hint only and is\n * never trusted as a guarantee.\n */\n maxOutputTokens?: number;\n /**\n * Optional non-generative classifier (System-One models such as Jev,\n * OpenJev, or a local ONNX classifier). Core never calls it unless the host\n * opts in (e.g. `WikiConfig.ontology.backfillClassifier: 'auto'`); merely\n * providing it changes nothing (REQ-COMPAT-01.5). Output is validated as\n * untrusted.\n */\n classify?: (request: ClassifyRequest) => Promise<ClassifyResponse>;\n}\n\n/** One typed question for a classifier. Vendor-neutral (Jev `noul` ↔ `binary`). */\nexport type ClassifierQuestion =\n | { kind: 'choice'; options: string[]; instructions?: string }\n | { kind: 'binary'; instructions: string }\n | { kind: 'score'; levels: string[]; instructions?: string };\n\n/** One state evaluated against a map of questions (many questions per state, one state per call). */\nexport interface ClassifyRequest {\n state: string;\n questions: Record<string, ClassifierQuestion>;\n}\n\nexport type ClassifierAnswer =\n | { kind: 'choice'; choice: string; confidence: number; probabilities: Record<string, number> }\n | { kind: 'binary'; probability: number }\n | { kind: 'score'; score: number; confidence: number; probabilities: number[] };\n\nexport interface ClassifyResponse {\n answers: Record<string, ClassifierAnswer>;\n}\n\n/**\n * Result of semantic ranking for a single fact.\n */\nexport interface VectorRankerSemanticResult {\n id: string;\n /** Cosine similarity in [-1, 1] when exact; implementations MAY document other monotonic scales. */\n semanticScore: number;\n}\n\n/**\n * Arguments passed to VectorRanker.rankBySimilarity.\n */\nexport interface VectorRankerRankArgs {\n entityId: string;\n /**\n * Query embedding. Treat as readonly — core provides a defensive copy,\n * but adapters MUST NOT mutate this array. Mutation can corrupt\n * WikiMemory's internal vector cache and JS-cosine fallback path.\n */\n queryVec: Float32Array | number[];\n /**\n * When set (MiniSearch pre-filter path): ranker MUST only produce results for ids in this set.\n * When omitted (full-entity semantic path): ranker scopes by entityId per its backing store contract.\n */\n candidateIds?: readonly string[];\n /**\n * Upper bound on how many distinct fact ids should receive a semanticScore in this call.\n * WikiMemory derives this from maxResults / candidate cardinality / documented oversampling policy.\n */\n limit: number;\n}\n\n/**\n * Optional backend for semantic candidate scoring / top-k retrieval.\n * When omitted, WikiMemory scores rows with embedding_blob / embedding TEXT in JS (cosine).\n */\nexport interface VectorRanker {\n /**\n * Return semantic scores for facts in scope, sorted descending by semanticScore (stable tie-breaking\n * not required — WikiMemory reapplies existing tie-breakers after blending).\n * Implementations SHOULD omit facts with no usable vector; callers treat missing ids like today's\n * \"no embedding\" rows (pure semantic: -2; hybrid: keyword-only portion).\n */\n rankBySimilarity(args: VectorRankerRankArgs): Promise<VectorRankerSemanticResult[]>;\n\n /**\n * Called after a fact's embedding is successfully persisted to embedding_blob (or cleared).\n * Hosts use this to keep sqlite-vec / external indexes consistent with SQLite as source of truth.\n *\n * On deletion paths (forget, prune, hard-delete), core awaits this hook to ensure ANN cleanup\n * completes before the deletion call resolves (GDPR compliance). Hook failures or timeouts on\n * those paths reject the deletion call.\n *\n * Treat `vector` as readonly — core provides a defensive copy, but adapters MUST NOT mutate.\n *\n * Optional: if omitted, hosts MUST document \"index rebuilt separately\" and accept stale ANN until rebuild.\n */\n onEmbeddingPersisted?(event: {\n entityId: string;\n factId: string;\n vector: Float32Array | null; // null = embedding removed / unusable\n }): void | Promise<void>;\n}\n\n/**\n * Fallback policy when rankBySimilarity rejects.\n */\nexport type VectorRankerFallback = 'js-cosine' | 'keyword' | 'empty' | 'throw';\n\n/** Severity is fixed per code (spec §4.2.6). */\nexport type WikiDiagnosticSeverity = 'info' | 'warn' | 'error';\n\n/**\n * Closed for this release series, but new codes are added in minor versions:\n * hosts must tolerate codes they do not recognize.\n */\nexport type WikiDiagnosticCode =\n | 'ingest_chunk_failed'\n | 'fact_rejected'\n | 'task_rejected'\n | 'fact_deduplicated'\n | 'edge_dropped'\n | 'embedding_failed'\n | 'hook_failed'\n | 'background_job_failed'\n | 'heal_skipped'\n | 'grounding_missing'\n | 'grounding_failed'\n | 'classification_low_confidence'\n | 'classification_invalid';\n\n/** The service run that emitted the diagnostic. */\nexport type WikiDiagnosticOperation =\n | 'ingest' | 'upsertGraph' | 'librarian' | 'heal' | 'ontologyBackfill' | 'reembed' | 'importDump' | 'write';\n\n/** `'auto'` when a write threshold started the run (auto-librarian / auto-heal); `'call'` when the host did. */\nexport type WikiDiagnosticTrigger = 'call' | 'auto';\n\n/** Identifiers only — never titles, bodies, quotes, LLM output, provider messages, or hashes of content. */\nexport interface WikiDiagnosticDetail {\n factId?: string;\n sourceRef?: string;\n chunkIndex?: number;\n edgeType?: string;\n /** Manifest slug of the edge source, when resolved. */\n sourceNodeType?: string;\n /** Manifest slug of the edge target, when resolved. */\n targetNodeType?: string;\n /** Position of a rejected item in the LLM response array. */\n itemIndex?: number;\n /** Machine-readable sub-reason, e.g. `'target_not_found'`. */\n reason?: string;\n /** Aggregated `ingest_chunk_failed` only; the first 20 failed chunk indexes. */\n chunkIndexes?: number[];\n /** Aggregated emissions only. */\n count?: number;\n}\n\nexport interface WikiDiagnostic {\n code: WikiDiagnosticCode;\n severity: WikiDiagnosticSeverity;\n operation: WikiDiagnosticOperation;\n trigger: WikiDiagnosticTrigger;\n entityId: string;\n /** Epoch ms, sampled at emission. */\n at: number;\n /** Fixed template per code. Never contains content. */\n message: string;\n detail?: WikiDiagnosticDetail;\n}\n\nexport interface WikiOptions {\n config?: WikiConfig;\n llmProvider: LLMProvider;\n /**\n * Called when embedding-based retrieval is degraded or unavailable during `read()`.\n * This can happen when:\n * - `embed()` throws (e.g. network error, model unavailable) → falls back to keyword search\n * - `embed()` returns a vector with non-finite values (NaN / Infinity) → falls back to keyword search\n * - The query vector's dimension doesn't match stored embeddings (model switch;\n * resolve by calling `runReembed()`) → falls back to keyword search\n * - `vectorRanker` returns IDs that don't belong to the requested entity or don't exist\n * (ranker integrity issue; returned rows will be filtered out, reducing result count) →\n * may still use semantic ranking, but with degraded quality\n *\n * `read()` returns results (keyword fallback or degraded semantic) — this is a notification, not an error path.\n */\n onRetrievalFallback?: (error: Error) => void;\n\n /**\n * Optional backend for semantic candidate scoring / top-k retrieval.\n * When omitted, WikiMemory scores rows with embedding_blob / embedding TEXT in JS (cosine).\n */\n vectorRanker?: VectorRanker;\n\n /**\n * When rankBySimilarity throws. Default `'js-cosine'`.\n * Ignored when vectorRanker is undefined.\n */\n vectorRankerFallback?: VectorRankerFallback;\n\n /**\n * Called only when rankBySimilarity rejects (after embeddings path succeeded).\n * Invoked before applying vectorRankerFallback when that policy recovers or before rejecting when policy is 'throw'.\n */\n onVectorRankerFallback?: (info: {\n error: Error;\n /** Effective policy core will apply for this read (same as WikiOptions.vectorRankerFallback, default js-cosine). */\n policy: VectorRankerFallback;\n }) => void;\n\n /**\n * When true: after rankBySimilarity failure, once the recoverable fallback has finished\n * and read() will resolve, invoke onRetrievalFallback — after onVectorRankerFallback if set.\n * Ignored when vectorRankerFallback is 'throw'. Default false.\n */\n propagateRankerFailureToRetrievalFallback?: boolean;\n\n /**\n * When true (default), sanitize ranker errors before exposing via error.cause\n * to prevent credential leakage in host telemetry. Disable only when you\n * control the ranker implementation.\n *\n * Sanitization replaces error message/stack with a generic message preserving\n * only the error type (constructor name).\n */\n sanitizeRankerErrors?: boolean;\n\n /**\n * Timeout (ms) for onEmbeddingPersisted hook on GDPR deletion paths\n * (forget, _doPrune). Hook must complete within this window or the\n * deletion operation rejects. Default 30000.\n * Lower for interactive deletes; raise for slow remote ANN backends.\n */\n deletionHookTimeoutMs?: number;\n\n /**\n * Escape hatch: skip onEmbeddingPersisted on deletion paths entirely.\n * Use ONLY when the ANN backend is permanently decommissioned. Vectors\n * orphaned in the (unreachable) external index are accepted as a tradeoff.\n * NOT GDPR-safe for live indexes. Default false.\n */\n forceDeleteIgnoreRankerHook?: boolean;\n\n /**\n * Receives typed, content-free diagnostics for events core previously\n * dropped silently or only logged (spec §4). Synchronous; a returned promise\n * is ignored. A throwing or rejecting hook never affects the operation that\n * emitted the diagnostic. Existing console output is unchanged whether or\n * not this is set.\n */\n onDiagnostic?: (diagnostic: WikiDiagnostic) => void;\n}\n\nexport interface MemoryBundle {\n facts: WikiFact[];\n tasks: WikiTask[];\n events: WikiEvent[];\n edges?: WikiEdge[];\n /** Entity summary prose for OKF profile ≥ 1 round-trip. Omitted = no summary (Clanker default). */\n summary?: string;\n factScores?: Record<string, number>;\n metadata?: {\n query: string;\n entityIds: string[];\n tierWeights?: Record<string, number>;\n /** Sanitized per-entity result floors, when `tierFloors` was supplied and non-empty. */\n tierFloors?: Record<string, number>;\n };\n}\n\nexport interface MemoryDump {\n generatedAt: number;\n entities: Record<string, MemoryBundle>;\n}\n\nexport interface FormattedMemoryDump {\n manifest: string;\n files: Array<{ name: string; content: string }>;\n}\n\nexport interface FormatContextOptions {\n format?: 'markdown' | 'plain';\n maxFacts?: number;\n maxTasks?: number;\n maxEvents?: number;\n includeConfidence?: boolean;\n includeTags?: boolean;\n includeEntityIds?: boolean;\n includeFactScores?: boolean;\n factWeights?: {\n confidence?: number;\n accessCount?: number;\n recency?: number;\n };\n}\n\nexport interface EntityStatus {\n ingesting: boolean;\n librarian: boolean;\n heal: boolean;\n}\n\n/**\n * All operations that can appear in a {@link WikiBusyError}.\n *\n * @remarks **Breaking change from v2.x** — the union previously only contained\n * `'ingest' | 'librarian' | 'heal' | 'prune' | 'reembed'`. The values `'import'`\n * and `'forget'` were added in v3.0. `'ontologyBackfill'` was added afterward.\n * Exhaustive `switch` / narrowing on this type must be updated (or given a\n * `default` arm) to compile without errors.\n */\nexport type WikiBusyOperation =\n | 'ingest'\n | 'librarian'\n | 'heal'\n | 'prune'\n | 'reembed'\n | 'import'\n | 'forget'\n | 'ontologyBackfill';\n\n/**\n * Thrown when a background mutator is already running for the requested entity.\n */\nexport class WikiBusyError extends Error {\n readonly operation: WikiBusyOperation;\n readonly entityId: string;\n\n constructor(operation: WikiBusyOperation, entityId: string) {\n super(`${operation} already running for entity ${entityId}`);\n this.name = 'WikiBusyError';\n this.operation = operation;\n this.entityId = entityId;\n }\n}\n\n/**\n * Thrown by `ingestDocument({ onDuplicateHash: 'throw' })` when a different\n * source_ref in the same entity already holds the supplied source_hash against\n * a live row. Mirrors {@link WikiBusyError}'s anchoring of canonical metadata\n * on the error instance for stable observability.\n */\nexport class WikiDuplicateHashError extends Error {\n readonly canonical: string;\n readonly sourceHash: string;\n readonly entityId: string;\n\n constructor(params: { canonical: string; sourceHash: string; entityId: string }) {\n super(`Duplicate source hash for entity ${params.entityId}; another ref already holds this content`);\n this.name = 'WikiDuplicateHashError';\n this.canonical = params.canonical;\n this.sourceHash = params.sourceHash;\n this.entityId = params.entityId;\n }\n}\n\n/**\n * Thrown by `WikiMemory.upsertGraph` when the persisted ontology mode for the\n * entity is `'strict'` and a caller-supplied node or edge `type` does not\n * resolve against the entity's manifest. Mirrors {@link WikiBusyError}'s\n * anchoring of canonical metadata on the error instance for stable\n * observability. Per C4, the check is pre-flight and all-or-nothing — the\n * first invalid item throws; NONE are written.\n */\nexport class WikiStrictOntologyViolation extends Error {\n readonly entityId: string;\n readonly kind: 'node' | 'edge';\n readonly type: string;\n readonly code = 'WIKI_STRICT_ONTOLOGY_VIOLATION' as const;\n\n constructor(entityId: string, kind: 'node' | 'edge', type: string) {\n super(\n `Out-of-manifest ${kind} type \"${type}\" for entity \"${entityId}\" under strict mode.`,\n );\n this.entityId = entityId;\n this.kind = kind;\n this.type = type;\n this.name = 'WikiStrictOntologyViolation';\n }\n}\n\n/**\n * Thrown by `WikiMemory.upsertGraph`'s C2 probe when the supplied\n * `sourceHash` is already mapped to a *different* `sourceRef` for the same\n * entity. Indicates either a caller-side id-derivation collision, a race with\n * another writer, or — per the C2 known-limitation note in the spec — two\n * source files with genuinely identical content (byte-identical barrel\n * re-exports, blank stubs, vendored boilerplate). In all cases: fail loud.\n */\nexport class WikiSourceRefHashCollision extends Error {\n readonly entityId: string;\n readonly sourceHash: string;\n readonly existingSourceRef: string;\n readonly attemptedSourceRef: string;\n readonly code = 'WIKI_SOURCE_REF_HASH_COLLISION' as const;\n\n constructor(params: {\n entityId: string;\n sourceHash: string;\n existingSourceRef: string;\n attemptedSourceRef: string;\n }) {\n super(\n `Source hash \"${params.sourceHash}\" for entity \"${params.entityId}\" ` +\n `is already mapped to sourceRef \"${params.existingSourceRef}\"; ` +\n `cannot remap to \"${params.attemptedSourceRef}\".`,\n );\n this.entityId = params.entityId;\n this.sourceHash = params.sourceHash;\n this.existingSourceRef = params.existingSourceRef;\n this.attemptedSourceRef = params.attemptedSourceRef;\n this.name = 'WikiSourceRefHashCollision';\n }\n}\n\n/**\n * Thrown when a graph node ID is already owned by another entity.\n *\n * Raised by `WikiMemory.upsertGraph`'s node-ownership pre-flight and,\n * independently, by `EntryRepository.upsert` for every caller — which is why\n * `ingestDocument` can surface it too (it shares `upsertGraphCore` on its full\n * path and `EntryRepository.upsert` on its partial path).\n *\n * Deliberately carries NO context: no owner entity, node ID, stored content,\n * provenance, or `cause`. A rejection is reachable by whatever supplies the\n * node IDs, so the error must not become a channel for reading another\n * entity's identifiers. The `WIKI_`-prefixed code and fixed message also keep\n * it clear of `extractSqliteCode`, so it passes through the serialized\n * transaction wrapper unwrapped.\n */\nexport class WikiGraphNodeOwnershipConflict extends Error {\n readonly code = 'WIKI_GRAPH_NODE_OWNERSHIP_CONFLICT' as const;\n\n /**\n * Privacy-preserving constructor: accepts no arguments, so neither the foreign\n * owner, the conflicting node ID, the stored content, nor any provenance can\n * leak through this error. The fixed message and `code` are the entire signal.\n *\n * @returns a contextless `WikiGraphNodeOwnershipConflict` instance. See the\n * class-level JSDoc for the privacy rationale.\n */\n\n constructor() {\n super('Graph write rejected because a node ID is unavailable for this entity.');\n this.name = 'WikiGraphNodeOwnershipConflict';\n }\n}\n\n/**\n * Thrown by the serialized transaction wrapper when a SQLite driver error\n * escapes a transaction callback (nested BEGIN, SQLITE_BUSY, constraint\n * violation). Domain errors thrown from callback logic pass through unwrapped.\n * Stable `instanceof` target for observability, mirroring {@link WikiBusyError}.\n */\nexport class WikiTransactionError extends Error {\n /** Best-effort SQLite code lifted from the driver error, e.g. 'SQLITE_BUSY'. */\n readonly sqliteErrorCode?: string;\n\n constructor(message: string, options: { cause: unknown }) {\n super(message, options);\n this.name = 'WikiTransactionError';\n this.sqliteErrorCode = extractSqliteCode(options.cause);\n }\n}\n\nexport class PrunePartialFailureError extends Error {\n readonly deleted: number;\n readonly failedAt: string;\n readonly remaining: number;\n readonly deletedTasks: number;\n readonly deletedEvents: number;\n override readonly cause: Error;\n\n constructor(\n deleted: number,\n failedAt: string,\n remaining: number,\n cause: Error,\n deletedTasks: number = 0,\n deletedEvents: number = 0,\n ) {\n super(`Prune partially failed: deleted ${deleted}, failed at ${failedAt}, ${remaining} remaining`);\n this.name = 'PrunePartialFailureError';\n this.deleted = deleted;\n this.failedAt = failedAt;\n this.remaining = remaining;\n this.deletedTasks = deletedTasks;\n this.deletedEvents = deletedEvents;\n this.cause = cause;\n }\n}\n\nexport const HOOK_TIMEOUT_MARKER = Symbol('WikiMemoryHookTimeout');\n\n/**\n * Failure kinds eligible for a persisted embedding failure marker (spec §3.3).\n * `no_provider` never marks (nothing to retry against), and `storage_error`\n * never marks (D3 — a marker is itself a DB write). Defined here, neutral\n * between repositories and services, so EntryRepository can type-narrow the\n * marker kind without importing from services.\n */\nexport type EmbeddingMarkerKind =\n | 'invalid_vector'\n | 'float32_overflow'\n | 'provider_error';\n\n/**\n * Failure record for a single chunk that could not be ingested. Produced by\n * `IngestionService.ingestDocument` and surfaced on the result's `parseFailures`\n * array. `source === 'parse'` for `WikiParseError`-shaped failures (then `tier`\n * is set); `source === 'llm'` for `generateText` rejections (no `tier`).\n *\n * Note: `'ontologyContext'` is reserved but NEVER produced. `buildPromptContext`\n * failures are DB-systemic and propagate as raw throws, not as `parseFailures`.\n */\nexport interface ChunkFailure {\n chunkIndex: number;\n sourceRef: string;\n source: 'parse' | 'llm';\n tier?: 'strict' | 'repair' | 'all';\n position: number | null;\n message: string;\n}\n\n/**\n * Result of `IngestionService.ingestDocument`. The shape WIDENS relative to\n * earlier versions: `ingestedChunks` and `failedChunks` are always present;\n * `parseFailures` is present iff at least one chunk failed.\n *\n * Hosts that destructure `{ truncated, chunks }` see no behavior change.\n * Hosts pattern-matching the entire shape must update to the new fields.\n */\nexport interface IngestDocumentResult {\n truncated: boolean;\n chunks: number;\n ingestedChunks: number;\n failedChunks: number;\n duplicateOf?: string;\n parseFailures?: ChunkFailure[];\n}\n\n/**\n * Thrown by `parseJsonResponse` when both the strict scanner pass and the\n * container-aware repair pass fail to produce a parsable candidate.\n *\n * - `tier: 'strict'` — the existing scanner produced no usable slice (no\n * `{`/`[` at all, or no balanced close). `slice` is the full input text;\n * `position` is the offset of the first `{`/`[`, or `null` when none found.\n * - `tier: 'repair'` — tier 1 found a slice but `JSON.parse` failed; tier 2\n * produced no parsable candidate within `MAX_REPAIR_CANDIDATES`. `slice` is\n * the largest balanced span the walker found; `position` is the offset of\n * the first parse failure within that candidate when known.\n * - `tier: 'all'` — generic catch-all.\n */\nexport class WikiParseError extends Error {\n readonly tier: 'strict' | 'repair' | 'all';\n readonly position: number | null;\n readonly slice: string;\n\n constructor(\n message: string,\n opts: { tier: WikiParseError['tier']; position?: number | null; slice?: string },\n ) {\n super(message);\n this.name = 'WikiParseError';\n this.tier = opts.tier;\n this.position = opts.position ?? null;\n this.slice = opts.slice ?? '';\n }\n}\n\n/**\n * Thrown by `IngestionService.ingestDocument` when every chunk of a document\n * failed (either `parseJsonResponse` or `generateText`). A silent zero-fact\n * ingest is a worse regression than a typed throw — matches existing host\n * semantics (`aws-cloud-agent` Writer Lambda today sees `ingestDocument`\n * throw on any failure).\n */\nexport class WikiIngestEmptyError extends Error {\n readonly parseFailures: ChunkFailure[];\n readonly sourceRef: string;\n readonly chunks: number;\n\n constructor(params: { parseFailures: ChunkFailure[]; sourceRef: string; chunks: number }) {\n const summary = `All ${params.chunks} chunks failed for sourceRef \"${params.sourceRef}\"; see parseFailures for per-chunk detail`;\n super(summary);\n this.name = 'WikiIngestEmptyError';\n this.parseFailures = params.parseFailures;\n this.sourceRef = params.sourceRef;\n this.chunks = params.chunks;\n }\n}\n\n/**\n * Thrown by `read()` when `ReadOptions` contains a request that cannot be\n * satisfied by construction — as opposed to one that merely finds no data.\n */\nexport class WikiInvalidReadOptions extends Error {\n readonly field: string;\n readonly reason: string;\n\n constructor(field: string, reason: string) {\n super(`Invalid ReadOptions.${field}: ${reason}`);\n this.name = 'WikiInvalidReadOptions';\n this.field = field;\n this.reason = reason;\n Object.setPrototypeOf(this, WikiInvalidReadOptions.prototype);\n }\n}\n\n/**\n * Thrown by `promoteDraft` when no live draft with that id exists for the\n * entity: missing, soft-deleted, owned by another entity, or not a draft.\n * Contextless for the same reason as {@link WikiGraphNodeOwnershipConflict}.\n * The `WIKI_` code keeps it clear of `extractSqliteCode`, so it passes through\n * the serialized transaction wrapper unwrapped.\n */\nexport class WikiDraftNotFound extends Error {\n readonly code = 'WIKI_DRAFT_NOT_FOUND' as const;\n\n constructor() {\n super('No draft fact with that id exists for this entity.');\n this.name = 'WikiDraftNotFound';\n Object.setPrototypeOf(this, WikiDraftNotFound.prototype);\n }\n}\n\n/** One page of `listDrafts`. `nextCursor` is opaque; pass it back unchanged. */\nexport interface DraftPage {\n facts: WikiFact[];\n nextCursor: string | null;\n}\n\n/**\n * `pendingSources` status (spec §8.2). `partial`: live rows exist for the ref\n * but none carries a hash, which is the intended retry state after a partial\n * ingest. `current` is exactly the case where `hasChanged` returns false.\n */\nexport type PendingSourceStatus = 'new' | 'changed' | 'partial' | 'current';\n\n/** Read-only maintenance report for one entity (spec §8.1). Counts cover live rows only. */\nexport interface WikiLintReport {\n /** Edges whose source or target is missing, soft-deleted, or owned by another entity. */\n danglingEdges: number;\n /** Live-endpoint edges whose (source type, edge type, target type) is not in the effective manifest. 0 when ontology is off or the manifest is empty. */\n manifestViolations: number;\n /** Live facts with `okf_type` NULL. */\n untypedFacts: number;\n /** Live facts with `lifecycle_status = 'draft'`. */\n drafts: number;\n /** Live `librarian_inferred` facts with an empty `okf_verified`. */\n unverifiedInferred: number;\n /** Up to 20 ids each, ascending. */\n sample: { danglingEdgeIds: string[]; manifestViolationEdgeIds: string[] };\n}\n\n/**\n * Effective system prompts (spec §8.3): defaults with `WikiConfig.prompts`\n * overrides applied and the ontology block appended. Templates only: data\n * placeholders such as `{{documentChunk}}` stay verbatim, and no events,\n * chunks or facts are ever included. Overrides are returned as written, so\n * never put secrets or private data in `WikiConfig.prompts`.\n */\nexport interface WikiInstructions {\n ingest: string;\n librarian: string;\n heal: string;\n ontologyBackfill: string;\n}\n\n","type GetRandomValues = (bytes: Uint8Array) => void;\n\nlet _injectedGetRandomValues: GetRandomValues | null = null;\n\n/**\n * Inject a platform-specific `getRandomValues` implementation.\n * Call this once at module load time from the platform adapter\n * (e.g. expo-crypto's getRandomValues) when the global `crypto` API is\n * absent — Hermes / React Native being the primary case.\n * Pass `null` to clear a previously injected source.\n */\nexport function configureRandomSource(fn: GetRandomValues | null): void {\n _injectedGetRandomValues = fn;\n}\n\n/**\n * Generate a random ID with an optional prefix.\n * Resolution order:\n * 1. crypto.randomUUID (Web / Node 19+)\n * 2. crypto.getRandomValues (Web / Node / polyfilled global)\n * 3. injected source via configureRandomSource (e.g. expo-crypto in RN)\n * Throws if none is available — record IDs must always be cryptographically random.\n */\nexport function generateId(prefix: string = ''): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return prefix + crypto.randomUUID().replace(/-/g, '').substring(0, 24);\n }\n if (typeof crypto !== 'undefined' && typeof crypto.getRandomValues === 'function') {\n const bytes = new Uint8Array(16);\n crypto.getRandomValues(bytes);\n return prefix + Array.from(bytes).map((b) => b.toString(16).padStart(2, '0')).join('').substring(0, 24);\n }\n if (_injectedGetRandomValues) {\n const bytes = new Uint8Array(16);\n _injectedGetRandomValues(bytes);\n return prefix + Array.from(bytes).map((b) => b.toString(16).padStart(2, '0')).join('').substring(0, 24);\n }\n throw new Error(\n 'generateId: no cryptographically secure random source available ' +\n '(crypto.randomUUID and crypto.getRandomValues are both missing, and no configureRandomSource() injection was provided).',\n );\n}\n","import type {\n OntologyManifest,\n OntologyNodeType,\n OntologyUpdates,\n ExtractedFactEdge,\n} from '../types';\nimport { WikiStrictOntologyViolation } from '../types';\n\nexport function emptyManifest(): OntologyManifest {\n return { node_types: [], edge_types: [] };\n}\n\nexport function normalizeTitleKey(title: string): string {\n return title.trim().toLowerCase().replace(/\\s+/g, ' ');\n}\n\nexport function resolveNodeType(raw: string, manifest: OntologyManifest): string | null {\n const slug = raw.trim();\n if (!slug) return null;\n const hit = manifest.node_types.find(n => n.type.toLowerCase() === slug.toLowerCase());\n return hit?.type ?? null;\n}\n\nexport function resolveEdgeDefinitions(\n rawEdgeType: string,\n manifest: OntologyManifest,\n): OntologyManifest['edge_types'][number][] {\n const slug = rawEdgeType.trim();\n if (!slug) return [];\n return manifest.edge_types.filter(e => e.type.toLowerCase() === slug.toLowerCase());\n}\n\nfunction edgeTripleKey(type: string, sourceType: string, targetType: string): string {\n return `${type.trim().toLowerCase()}|${sourceType.trim().toLowerCase()}|${targetType.trim().toLowerCase()}`;\n}\n\n/**\n * True when `concreteType` satisfies a declared type: an exact\n * (case-insensitive) match, or a one-hop parent match — the concrete type's\n * `parent_type` equals the declared type. Never recursive (D1). Exact matches\n * short-circuit before the node lookup, so manifests with no `parent_type`\n * behave bit-for-bit as before.\n */\nexport function typeSatisfies(\n declaredType: string,\n concreteType: string,\n manifest: OntologyManifest,\n): boolean {\n const concrete = concreteType.trim().toLowerCase();\n const declared = declaredType.trim().toLowerCase();\n if (!concrete || !declared) return false;\n if (declared === concrete) return true;\n // `node_types` is typed non-optional but arrives from JSON.parse of a DB row\n // at runtime, so guard it the way validateManifest already does — and for the\n // same reason, `typeof`-check the fields rather than calling .trim() on them.\n // This runs inside the caller's transaction, so a TypeError here aborts an\n // ingest exactly like one in the merge path. Manifests reaching this point\n // have already passed validateManifest (getManifest:164, and seeds via D11),\n // so this is defense in depth, not the primary guard.\n const def = (manifest.node_types ?? []).find(\n n => typeof n?.type === 'string' && n.type.trim().toLowerCase() === concrete,\n );\n const parent = typeof def?.parent_type === 'string'\n ? def.parent_type.trim().toLowerCase()\n : '';\n return parent !== '' && parent === declared;\n}\n\n/**\n * True iff some manifest edge type matches `edgeType` (case-insensitive) and\n * accepts the concrete endpoint types, parent types included. An empty\n * endpoint type never satisfies (the triple cannot be in the manifest).\n */\nexport function edgeTripleAllowed(\n manifest: OntologyManifest,\n edgeType: string,\n sourceType: string,\n targetType: string,\n): boolean {\n const wanted = edgeType.trim().toLowerCase();\n return (manifest.edge_types ?? []).some((d) =>\n typeof d?.type === 'string'\n && d.type.trim().toLowerCase() === wanted\n && typeof d.source_type === 'string' && typeSatisfies(d.source_type, sourceType, manifest)\n && typeof d.target_type === 'string' && typeSatisfies(d.target_type, targetType, manifest));\n}\n\nexport function validateManifest(manifest: OntologyManifest): void {\n const nodeSlugs = new Set<string>();\n for (const node of manifest.node_types ?? []) {\n const type = node.type?.trim();\n if (!type) throw new Error('Ontology node type slug must be non-empty');\n const key = type.toLowerCase();\n if (nodeSlugs.has(key)) throw new Error(`Duplicate node type: ${type}`);\n nodeSlugs.add(key);\n }\n // D1: optional one-level parent inheritance. A parent must be a real,\n // distinct node in the same manifest, and must not itself have a parent.\n // The chain check also rejects 2-cycles, which self-parent alone misses.\n const parentOf = new Map<string, string | undefined>();\n for (const node of manifest.node_types ?? []) {\n const parent = typeof node.parent_type === 'string'\n ? node.parent_type.trim().toLowerCase()\n : undefined;\n parentOf.set(node.type.trim().toLowerCase(), parent);\n }\n for (const node of manifest.node_types ?? []) {\n // D10: absent means \"no parent\"; present-but-unusable is malformed.\n if (node.parent_type === undefined) continue;\n // Typed `string | undefined`, but this runs on JSON.parse output from\n // `entity_manifests.manifest_json` on every read (MetadataRepository:164),\n // so a legacy or hand-edited row can carry a number or `null`. Unguarded,\n // `.trim()` on those raises a bare TypeError instead of this error.\n if (typeof node.parent_type !== 'string' || !node.parent_type.trim()) {\n throw new Error(`Ontology parent_type must be a non-empty string when present: ${node.type}`);\n }\n const parentSlug = node.parent_type.trim().toLowerCase();\n if (parentSlug === node.type.trim().toLowerCase()) {\n throw new Error(`Self-parent: ${node.type}`);\n }\n if (!nodeSlugs.has(parentSlug)) {\n throw new Error(`Parent type not found: ${node.parent_type}`);\n }\n const grandparent = parentOf.get(parentSlug);\n if (grandparent) {\n throw new Error(`Parent chain too deep: ${node.type} → ${node.parent_type} → ${grandparent}`);\n }\n }\n const edgeKeys = new Set<string>();\n const edgeNames = new Map<string, string>();\n for (const edge of manifest.edge_types ?? []) {\n const edgeType = edge.type?.trim();\n const sourceType = edge.source_type?.trim();\n const targetType = edge.target_type?.trim();\n if (!edgeType) throw new Error('Ontology edge type slug must be non-empty');\n if (!sourceType || !targetType || !nodeSlugs.has(sourceType.toLowerCase()) || !nodeSlugs.has(targetType.toLowerCase())) {\n throw new Error(`Edge type ${edgeType} references unknown node type`);\n }\n const edgeKey = edgeTripleKey(edgeType, sourceType, targetType);\n if (edgeKeys.has(edgeKey)) {\n throw new Error(`Duplicate edge definition: ${edgeType} (${sourceType} → ${targetType})`);\n }\n edgeKeys.add(edgeKey);\n // Persisted edge_type values come from def.type verbatim, so every triple\n // sharing a name must agree on casing or storage ends up mixed.\n const canonical = edgeNames.get(edgeType.toLowerCase());\n if (canonical === undefined) {\n edgeNames.set(edgeType.toLowerCase(), edgeType);\n } else if (canonical !== edgeType) {\n throw new Error(`Inconsistent casing for edge type: ${edgeType} conflicts with ${canonical}`);\n }\n }\n}\n\n// D6: emergent updates are untrusted. `updates` is JSON.parse output, so\n// every field is `unknown` at runtime whatever the TS types say — `.trim()`\n// on a number or an object throws a TypeError straight out of the caller's\n// transaction, which is the failure D6 exists to prevent. Guard every read.\n//\n// Exported so the test suite can exercise the index's untrusted-input\n// contract directly, without going through mergeOntologyUpdates — whose\n// pre-existing node loop (utils/ontology.ts:176) is unchanged by this work.\nexport function buildDeclaresParentIndex(\n nodes: ReadonlyArray<OntologyNodeType>,\n): Map<string, boolean> {\n const declaresParent = new Map<string, boolean>();\n for (const n of nodes) {\n const slug = typeof n?.type === 'string' ? n.type.trim().toLowerCase() : '';\n if (!slug || declaresParent.has(slug)) continue;\n declaresParent.set(slug, n?.parent_type !== undefined);\n }\n return declaresParent;\n}\n\nexport function mergeOntologyUpdates(\n current: OntologyManifest,\n updates: OntologyUpdates,\n): OntologyManifest {\n const node_types = [...current.node_types];\n const edge_types = [...current.edge_types];\n const nodeSlugs = new Set(node_types.map(n => n.type.trim().toLowerCase()));\n const edgeKeys = new Set(edge_types.map(e => edgeTripleKey(e.type, e.source_type, e.target_type)));\n const edgeNames = new Map(edge_types.map(e => [e.type.trim().toLowerCase(), e.type.trim()]));\n\n // Index over current + proposed nodes, first-seen wins (mirrors the dedup in\n // the loop below). Value: did this slug declare a `parent_type` key at all?\n // Presence, not usability — a node that declared one cannot serve as a\n // parent, whether it is a real child or a malformed proposal.\n const declaresParent = buildDeclaresParentIndex([\n ...current.node_types,\n ...(updates.node_types ?? []),\n ]);\n\n for (const node of updates.node_types ?? []) {\n const type = node?.type?.trim();\n if (!type) continue;\n const key = type.toLowerCase();\n if (nodeSlugs.has(key)) continue;\n // Drop a non-string, blank, unresolvable, self-referential, or two-deep\n // parent rather than letting it throw inside the caller's transaction (D6).\n // `declaresParent.get(...) === false` is the whole gate: `undefined` means\n // the slug is unknown, `true` means that node declared a parent of its own.\n const rawParent = typeof node?.parent_type === 'string' ? node.parent_type.trim() : '';\n const parentSlug = rawParent.toLowerCase();\n const keepParent = parentSlug !== ''\n && parentSlug !== key\n && declaresParent.get(parentSlug) === false;\n node_types.push({\n type,\n description: String(node.description ?? ''),\n ...(keepParent ? { parent_type: rawParent } : {}),\n });\n nodeSlugs.add(key);\n }\n for (const edge of updates.edge_types ?? []) {\n const rawEdgeType = edge?.type?.trim();\n const sourceType = edge?.source_type?.trim();\n const targetType = edge?.target_type?.trim();\n if (!rawEdgeType || !sourceType || !targetType) continue;\n // First-seen casing wins for a given edge name, as with node types, so a\n // later triple spelled differently cannot make the manifest fail validation.\n const edgeType = edgeNames.get(rawEdgeType.toLowerCase()) ?? rawEdgeType;\n const edgeKey = edgeTripleKey(edgeType, sourceType, targetType);\n if (edgeKeys.has(edgeKey)) continue;\n if (!nodeSlugs.has(sourceType.toLowerCase()) || !nodeSlugs.has(targetType.toLowerCase())) continue;\n edgeNames.set(edgeType.toLowerCase(), edgeType);\n edge_types.push({\n type: edgeType,\n source_type: sourceType,\n target_type: targetType,\n description: String(edge.description ?? ''),\n });\n edgeKeys.add(edgeKey);\n }\n return { node_types, edge_types };\n}\n\nexport type EdgeDropReason =\n | 'no_source_type'\n | 'invalid_shape'\n | 'type_not_in_manifest'\n | 'target_not_found'\n | 'target_type_mismatch';\n\n/** A dropped LLM-proposed edge. Slugs only — `target_title` is content and is never recorded. */\nexport interface EdgeDrop {\n reason: EdgeDropReason;\n /** Source fact id when known; null while validating before the fact has an id. */\n sourceId: string | null;\n edgeType: string | null;\n sourceNodeType: string | null;\n targetNodeType: string | null;\n}\n\nexport function validateInlineEdges(\n sourceType: string,\n _targetType: string | null,\n edges: ExtractedFactEdge[],\n manifest: OntologyManifest,\n opts?: { strict?: boolean; entityId?: string; drops?: EdgeDrop[] },\n): ExtractedFactEdge[] {\n const strict = opts?.strict === true;\n const entityId = opts?.entityId ?? '';\n const drops = opts?.drops;\n const drop = (reason: EdgeDropReason, edgeType: string | null): void => {\n drops?.push({ reason, sourceId: null, edgeType, sourceNodeType: sourceType, targetNodeType: null });\n };\n if (!Array.isArray(edges)) {\n if (strict) throw new WikiStrictOntologyViolation(entityId, 'edge', '');\n drop('invalid_shape', null);\n return [];\n }\n const valid: ExtractedFactEdge[] = [];\n for (const edge of edges) {\n if (typeof edge?.edge_type !== 'string' || typeof edge?.target_title !== 'string') {\n if (strict) throw new WikiStrictOntologyViolation(entityId, 'edge', String(edge?.edge_type ?? ''));\n drop('invalid_shape', typeof edge?.edge_type === 'string' ? edge.edge_type : null);\n continue;\n }\n const defs = resolveEdgeDefinitions(edge.edge_type, manifest);\n const match = defs.find(d => typeSatisfies(d.source_type, sourceType, manifest));\n if (!match) {\n if (strict) throw new WikiStrictOntologyViolation(entityId, 'edge', edge.edge_type);\n drop('type_not_in_manifest', edge.edge_type);\n continue;\n }\n valid.push({ edge_type: match.type, target_title: edge.target_title });\n }\n return valid;\n}\n","export function parseEmbedding(\n blob: Uint8Array | null | undefined,\n text: string | null | undefined\n): Float32Array | null {\n if (blob && blob.byteLength > 0) {\n if (blob.byteLength % 4 !== 0) return null;\n // Copy into fresh ArrayBuffer — SQLite drivers may return pooled Buffer\n // objects that get reused across queries, silently corrupting cached vectors.\n const copy = new ArrayBuffer(blob.byteLength);\n new Uint8Array(copy).set(blob);\n const vector = new Float32Array(copy);\n for (const value of vector) {\n if (!Number.isFinite(value)) return null;\n }\n return vector;\n }\n if (text) {\n try {\n const arr: unknown = JSON.parse(text);\n if (!Array.isArray(arr) || !arr.every((v: unknown) => typeof v === 'number' && isFinite(v))) return null;\n const vector = new Float32Array(arr as number[]);\n for (const value of vector) {\n if (!Number.isFinite(value)) return null;\n }\n return vector;\n } catch { return null; }\n }\n return null;\n}\n","export function cosineSimilarity(a: ArrayLike<number>, b: ArrayLike<number>): number {\n let dot = 0, normA = 0, normB = 0;\n const len = Math.min(a.length, b.length);\n for (let i = 0; i < len; i++) {\n dot += a[i] * b[i];\n normA += a[i] * a[i];\n normB += b[i] * b[i];\n }\n const denom = Math.sqrt(normA) * Math.sqrt(normB);\n return denom === 0 ? 0 : dot / denom;\n}\n","import MiniSearch, { SearchResult } from 'minisearch';\nimport { EntryRepository } from '../repositories/EntryRepository';\nimport { cosineSimilarity } from '../utils/cosine';\nimport { parseEmbedding } from '../utils/embedding';\n\nexport interface ScoredRow {\n id: string;\n entity_id: string;\n score: number;\n updated_at: number | null;\n access_count: number | null;\n}\n\nexport interface RankSemanticArgs {\n entityId: string;\n queryVec: Float32Array | number[];\n candidateRows: Array<{\n id: string;\n entity_id: string;\n embedding_blob: Uint8Array | null;\n embedding: string | null;\n updated_at: number | null;\n access_count: number | null;\n }>;\n weight: number | undefined;\n miniSearchScores: Map<string, number> | undefined;\n populateCache: boolean;\n limit: number;\n skipSort?: boolean;\n}\n\nexport class SearchService {\n /**\n * Maximum number of entities whose parsed embedding vectors are held in\n * memory. This cap is intentionally conservative so the cache remains safe\n * on memory-constrained runtimes (e.g., mobile/Expo).\n */\n private static readonly MAX_VECTOR_CACHE_ENTITIES = 16;\n\n /**\n * Maximum number of fact vectors cached per entity. Keep this high enough to\n * preserve the parsed-embedding reuse optimization for common mid-sized\n * entities while still maintaining a bounded memory footprint.\n */\n private static readonly MAX_VECTOR_CACHE_FACTS_PER_ENTITY = 500;\n\n private miniSearch: MiniSearch<{ id: string; entity_id: string; title: string; body: string; tags: string }>;\n private miniSearchEntryIdsByEntity = new Map<string, Set<string>>();\n private vectorCache: Map<string, Map<string, Float32Array>> = new Map();\n\n /**\n * Serializes rebuilds. `rebuildIndex` awaits a repository read between\n * snapshotting the previous id set and discarding it, so two concurrent\n * sync() calls for one entity can interleave: a slow, stale read lands last\n * and discards documents the fresh read just added. Chaining also keeps\n * discard()/addAll() out of each other's way, which is what accrued the\n * auto-vacuum debt behind the TypeError in #64.\n */\n private syncChain: Promise<void> = Promise.resolve();\n\n constructor(private entryRepo: EntryRepository) {\n this.miniSearch = new MiniSearch({\n fields: ['title', 'body', 'tags'],\n storeFields: ['entity_id'],\n // Vacuuming is driven explicitly at the end of each serialized rebuild\n // (see sync). Auto-vacuum fires on its own schedule, asynchronously with\n // respect to the caller, and traversing the tree mid-rebuild is what\n // threw the uncaught TypeError in MiniSearch.performVacuuming (#64).\n autoVacuum: false,\n searchOptions: {\n boost: { title: 2 },\n fuzzy: 0.2,\n prefix: true,\n },\n });\n }\n\n /**\n * Rebuilds the search index and clears the vector cache for a given entity.\n * A direct replacement for manually syncing state after a DB transaction.\n *\n * Rebuilds are serialized per instance and never reject: the MiniSearch index\n * is a rebuildable cache over SQLite, so degraded keyword search is the\n * correct failure mode and killing the host process is not.\n */\n async sync(entityId?: string): Promise<void> {\n const work = this.syncChain.then(async () => {\n try {\n // evictCache is inside the guard, not after it: a throw escaping here\n // would reject `work`, and since the next sync() chains off `work`,\n // every later rebuild would reject too — the poisoned-chain form of\n // exactly the unhandled rejection this method exists to prevent. The\n // inner finally keeps eviction unconditional, as it was before.\n try {\n await this.rebuildIndex(entityId);\n await this.miniSearch.vacuum();\n } finally {\n this.evictCache(entityId);\n }\n } catch (err) {\n console.warn(`[WikiMemory] search index rebuild failed for ${entityId ?? '*'}:`, err);\n }\n });\n this.syncChain = work;\n return work;\n }\n\n /**\n * Clears the parsed vector cache. Useful for mid-loop flush guarantees\n * or memory pressure evictions.\n */\n evictCache(entityId?: string): void {\n if (entityId) {\n this.vectorCache.delete(entityId);\n } else {\n this.vectorCache.clear();\n }\n }\n\n /**\n * Fully resets the search service.\n */\n clearAll(): void {\n this.vectorCache.clear();\n this.miniSearch.removeAll();\n this.miniSearchEntryIdsByEntity.clear();\n }\n\n /**\n * Executes a keyword search against the active MiniSearch index.\n */\n searchKeyword(query: string, entityIds: string[], limit: number): SearchResult[] {\n const entityIdSet = new Set(entityIds);\n const results = this.miniSearch.search(query, {\n filter: (r) => entityIdSet.has(r.entity_id as string),\n combineWith: 'OR',\n });\n return results.slice(0, limit);\n }\n\n /**\n * Pre-fetches MiniSearch scores for candidate hydration, used during hybrid weighting.\n */\n getMiniSearchScores(query: string, entityIds: string[], preFilterLimit?: number): Map<string, number> {\n const entityIdSet = new Set(entityIds);\n let results = this.miniSearch.search(query, {\n filter: (r) => entityIdSet.has(r.entity_id as string),\n combineWith: 'OR',\n });\n\n if (preFilterLimit !== undefined) {\n results = results.slice(0, preFilterLimit);\n }\n\n if (results.length === 0) return new Map();\n\n const maxMsScore = Math.max(1, results[0]?.score ?? 1);\n return new Map(results.map((r) => [r.id, r.score / maxMsScore]));\n }\n\n /**\n * Score candidate rows using in-process JS cosine similarity.\n * Applies hybrid blending (if weight set) and tie-break sorting before returning.\n */\n async rankSemantic(args: RankSemanticArgs): Promise<ScoredRow[]> {\n const queryVec = args.queryVec instanceof Float32Array ? args.queryVec.slice() : Array.from(args.queryVec);\n const { entityId, candidateRows, weight, miniSearchScores, populateCache, limit, skipSort } = args;\n\n let entityCache = this.vectorCache.get(entityId);\n const tooLarge = populateCache && candidateRows.length > SearchService.MAX_VECTOR_CACHE_FACTS_PER_ENTITY;\n\n if (tooLarge && entityCache) {\n this.vectorCache.delete(entityId);\n entityCache = undefined;\n }\n\n const canCache = populateCache && !tooLarge;\n if (canCache && !entityCache) {\n entityCache = new Map<string, Float32Array>();\n }\n\n const scored = candidateRows.map((row) => {\n let vector = entityCache?.get(row.id) ?? parseEmbedding(row.embedding_blob, row.embedding);\n\n if (vector && canCache && entityCache && !entityCache.has(row.id)) {\n entityCache.set(row.id, vector);\n }\n\n let score = 0;\n if (vector && vector.length === queryVec.length) {\n const cosSim = cosineSimilarity(queryVec, vector);\n if (weight !== undefined) {\n const kwScore = miniSearchScores?.get(row.id) ?? 0;\n score = weight * Math.max(0, cosSim) + (1 - weight) * kwScore;\n } else {\n score = cosSim;\n }\n } else if (weight !== undefined && weight < 1) {\n const kwScore = miniSearchScores?.get(row.id) ?? 0;\n score = (1 - weight) * kwScore;\n } else {\n score = -2;\n }\n\n return {\n id: row.id,\n entity_id: row.entity_id,\n score,\n updated_at: row.updated_at,\n access_count: row.access_count,\n };\n });\n\n if (canCache && entityCache && entityCache.size > 0) {\n if (!this.vectorCache.has(entityId)) {\n if (this.vectorCache.size >= SearchService.MAX_VECTOR_CACHE_ENTITIES) {\n const oldestKey = this.vectorCache.keys().next().value as string | undefined;\n if (oldestKey !== undefined) this.vectorCache.delete(oldestKey);\n }\n this.vectorCache.set(entityId, entityCache);\n }\n }\n\n if (!skipSort) {\n this._tieBreakSort(scored);\n }\n\n return scored.slice(0, limit);\n }\n\n // --- Internal Index Management ---\n\n private async rebuildIndex(entityId?: string): Promise<void> {\n if (entityId) {\n const rows = await this.entryRepo.findMiniSearchRows(entityId);\n const previousIds = this.miniSearchEntryIdsByEntity.get(entityId);\n\n if (previousIds) {\n for (const id of previousIds) {\n this.miniSearch.discard(id);\n }\n }\n\n const documents = rows.map((row) => this.normalizeMiniSearchRow(row));\n if (documents.length > 0) {\n this.miniSearch.addAll(documents);\n }\n\n this.miniSearchEntryIdsByEntity.set(\n entityId,\n new Set(documents.map((document) => document.id))\n );\n return;\n }\n\n const rows = await this.entryRepo.findMiniSearchRows();\n this.miniSearch.removeAll();\n this.miniSearchEntryIdsByEntity.clear();\n\n const documents = rows.map((row) => this.normalizeMiniSearchRow(row));\n if (documents.length > 0) {\n this.miniSearch.addAll(documents);\n }\n\n for (const document of documents) {\n const ids = this.miniSearchEntryIdsByEntity.get(document.entity_id) ?? new Set<string>();\n ids.add(document.id);\n this.miniSearchEntryIdsByEntity.set(document.entity_id, ids);\n }\n }\n\n private normalizeMiniSearchRow(row: {\n id: string;\n entity_id: string;\n title: string;\n body: string;\n tags: string;\n }): { id: string; entity_id: string; title: string; body: string; tags: string } {\n return {\n id: row.id,\n entity_id: row.entity_id,\n title: row.title,\n body: row.body,\n tags: (() => {\n try {\n const parsed = JSON.parse(row.tags);\n return Array.isArray(parsed) ? parsed.join(' ') : row.tags;\n } catch {\n return row.tags;\n }\n })(),\n };\n }\n\n private _tieBreakSort(items: ScoredRow[]): void {\n items.sort((a, b) => this._compareScoredRows(a, b));\n }\n\n private _compareScoredRows(a: ScoredRow, b: ScoredRow): number {\n const scoreDiff = b.score - a.score;\n if (!Number.isNaN(scoreDiff) && scoreDiff !== 0) return scoreDiff;\n\n const accessCountDiff = (b.access_count ?? 0) - (a.access_count ?? 0);\n if (accessCountDiff !== 0) return accessCountDiff;\n\n const updatedAtDiff = (b.updated_at ?? 0) - (a.updated_at ?? 0);\n if (updatedAtDiff !== 0) return updatedAtDiff;\n\n return a.id.localeCompare(b.id);\n }\n}\n","import { EntityStatus, WikiBusyError, WikiBusyOperation } from '../types';\n\nexport type OperationType =\n | 'prune'\n | 'librarian'\n | 'heal'\n | 'ingest'\n | 'reembed'\n | 'global_reembed'\n | 'import'\n | 'global_import'\n | 'forget'\n | 'ontologyBackfill';\n\nexport class JobManager {\n private activeMaintenanceJobs = new Set<string>();\n private activeIngestJobs = new Map<string, Set<string>>();\n /**\n * Per-(entityId, sourceHash) promise-chain lock. Serializes ingest races\n * at the application level (the v9 partial UNIQUE index enforces it at\n * the DB level as defense-in-depth). Two callers holding the same hash\n * see FIFO order; different hashes never block one another.\n *\n * Keyed `${entityId}\\0${sourceHash}` so distinct (entityId, sourceHash)\n * pairs can never share a lock. A raw concatenation would let\n * (\"ab\", \"c…\") collide with (\"a\", \"bc…\"); the NUL separator makes that\n * impossible because neither component can contain NUL (entityIds are\n * user-supplied identifiers; sourceHashes are hex digests).\n */\n private hashLocks: Map<string, Promise<unknown>> = new Map();\n private statusSubscribers = new Map<\n string,\n Set<{ callback: (s: EntityStatus) => void; last: EntityStatus }>\n >();\n\n constructor(private prefix: string) {}\n\n private _hashLockKey(entityId: string, sourceHash: string): string {\n return `${entityId}\\0${sourceHash}`;\n }\n\n /**\n * Acquire a promise-chain lock scoped to one `(entityId, sourceHash)` pair.\n * Returns a zero-argument release closure that removes the current tail\n * from the chain. Releasing is idempotent so a holder that double-fires\n * (e.g. on a finally that races an explicit release) cannot unblock\n * the next holder prematurely.\n *\n * Documented ordering: ingest acquires the hash lock FIRST, then the\n * synchronous sourceRef ingest lock, and the release closure unwinds in\n * the opposite order (sourceRef first, hash second). Hash-then-sourceRef\n * is required because the v9 partial UNIQUE index conflicts on the\n * (entity_id, source_hash) pair regardless of source_ref, so two callers\n * with DIFFERENT source_refs racing the same hash are the exact case the\n * TOCTOU race fix needs to serialize.\n *\n * Mechanics: each holder owns a private `released` promise that resolves\n * only when THIS holder calls release(). The map stores the holder's\n * `released` promise as the \"tail\" — the NEXT caller awaits that tail\n * via `previous = this.hashLocks.get(key)`. The current caller gets\n * their unique release function once `previous` (the prior holder's\n * release signal) settles, so each holder is guaranteed a UNIQUE release\n * closure bound to their own `released` promise.\n */\n acquireHashLock(entityId: string, sourceHash: string): Promise<() => void> {\n const key = this._hashLockKey(entityId, sourceHash);\n const previous = this.hashLocks.get(key) ?? Promise.resolve();\n let resolveReleased!: () => void;\n const released = new Promise<void>((resolve) => { resolveReleased = resolve; });\n let fired = false;\n const release = () => {\n if (fired) return;\n fired = true;\n // Unlink from the map ONLY if we are still the current tail; otherwise\n // a fresh holder has already chained a new tail and ours would race.\n if (this.hashLocks.get(key) === released) {\n this.hashLocks.delete(key);\n }\n resolveReleased();\n };\n this.hashLocks.set(key, released);\n // Wait for the prior holder to release, then hand back OUR unique closure.\n return previous.then(() => release);\n }\n\n private _pruneKey(entityId: string) { return `${this.prefix}:${entityId}:prune`; }\n private _reembedKey(entityId: string) { return `${this.prefix}:${entityId}:reembed`; }\n private _globalReembedKey() { return `${this.prefix}:reembed`; }\n private _importKey(entityId: string) { return `${this.prefix}:${entityId}:import`; }\n private _globalImportKey() { return `${this.prefix}:import`; }\n private _forgetKey(entityId: string) { return `${this.prefix}:${entityId}:forget`; }\n private _librarianKey(entityId: string) { return `${this.prefix}:${entityId}:librarian`; }\n private _healKey(entityId: string) { return `${this.prefix}:${entityId}:heal`; }\n private _ontologyBackfillKey(entityId: string) { return `${this.prefix}:${entityId}:ontologyBackfill`; }\n\n /**\n * Lookup table for acquireLock/releaseLock's dynamic-dispatch branch.\n * Excludes 'ingest' | 'global_reembed' | 'global_import', which those\n * methods already handle via explicit if/else branches before reaching\n * this table.\n */\n private readonly lockKeyFns: Record<\n Exclude<OperationType, 'ingest' | 'global_reembed' | 'global_import'>,\n (entityId: string) => string\n > = {\n prune: (id) => this._pruneKey(id),\n librarian: (id) => this._librarianKey(id),\n heal: (id) => this._healKey(id),\n reembed: (id) => this._reembedKey(id),\n import: (id) => this._importKey(id),\n forget: (id) => this._forgetKey(id),\n ontologyBackfill: (id) => this._ontologyBackfillKey(id),\n };\n\n private _isReembedActive(entityId: string): boolean {\n return this.activeMaintenanceJobs.has(this._reembedKey(entityId)) ||\n this.activeMaintenanceJobs.has(this._globalReembedKey());\n }\n\n /**\n * True while any reembed sweep is in flight — per-entity or global.\n *\n * Read-only; acquires nothing. Callers that mutate embedding failure\n * markers across ALL entities (the dimension-promotion clear) must gate on\n * this and defer, rather than resurrect rows an in-flight sweep already\n * classified. See spec 2026-09-05-reembed-lock-scope-design.md §2.\n *\n * The global key `${prefix}:reembed` also ends in ':reembed', so the suffix\n * scan alone would already match it. The explicit check is kept because it\n * documents the intent and survives any future change to the global key's\n * format.\n */\n isAnyReembedActive(): boolean {\n return this.activeMaintenanceJobs.has(this._globalReembedKey()) ||\n this._isAnyMaintenanceActiveWithSuffix(':reembed');\n }\n\n private _isImportActiveFor(entityId: string): boolean {\n return this.activeMaintenanceJobs.has(this._importKey(entityId)) ||\n this.activeMaintenanceJobs.has(this._globalImportKey());\n }\n\n private _isForgetActiveFor(entityId: string): boolean {\n return this.activeMaintenanceJobs.has(this._forgetKey(entityId));\n }\n\n private _isAnyMaintenanceActiveWithSuffix(suffix: string): boolean {\n const entityKeyPrefix = `${this.prefix}:`;\n for (const k of this.activeMaintenanceJobs) {\n if (k.startsWith(entityKeyPrefix) && k.endsWith(suffix)) return true;\n }\n return false;\n }\n\n private _hasIngestJob(entityId: string, sourceRef?: string): boolean {\n return this.activeIngestJobs.get(entityId)?.has(sourceRef ?? '') ?? false;\n }\n\n private _addIngestJob(entityId: string, sourceRef?: string): void {\n const sourceKey = sourceRef ?? '';\n let refs = this.activeIngestJobs.get(entityId);\n if (!refs) {\n refs = new Set<string>();\n this.activeIngestJobs.set(entityId, refs);\n }\n refs.add(sourceKey);\n }\n\n private _removeIngestJob(entityId: string, sourceRef?: string): void {\n const sourceKey = sourceRef ?? '';\n const refs = this.activeIngestJobs.get(entityId);\n if (!refs) return;\n refs.delete(sourceKey);\n if (refs.size === 0) {\n this.activeIngestJobs.delete(entityId);\n }\n }\n\n private _isIngestActiveFor(entityId: string): boolean {\n return this.activeIngestJobs.has(entityId);\n }\n\n acquireLock(operation: OperationType, entityId: string, sourceRef?: string): void {\n let blockingOperation: WikiBusyOperation | null = null;\n\n if (operation !== 'global_import' && this.activeMaintenanceJobs.has(this._globalImportKey())) {\n throw new WikiBusyError('import', '*');\n }\n\n switch (operation) {\n case 'prune':\n if (this.activeMaintenanceJobs.has(this._pruneKey(entityId))) blockingOperation = 'prune';\n else if (this.activeMaintenanceJobs.has(this._librarianKey(entityId))) blockingOperation = 'librarian';\n else if (this.activeMaintenanceJobs.has(this._healKey(entityId))) blockingOperation = 'heal';\n else if (this.activeMaintenanceJobs.has(this._ontologyBackfillKey(entityId))) blockingOperation = 'ontologyBackfill';\n else if (this._isReembedActive(entityId)) blockingOperation = 'reembed';\n else if (this._isIngestActiveFor(entityId)) blockingOperation = 'ingest';\n else if (this._isImportActiveFor(entityId)) blockingOperation = 'import';\n else if (this._isForgetActiveFor(entityId)) blockingOperation = 'forget';\n break;\n\n case 'librarian':\n case 'heal':\n case 'ontologyBackfill': {\n const opKey = this.lockKeyFns[operation](entityId);\n if (this.activeMaintenanceJobs.has(opKey)) blockingOperation = operation;\n else if (this.activeMaintenanceJobs.has(this._pruneKey(entityId))) blockingOperation = 'prune';\n else if (this._isReembedActive(entityId)) blockingOperation = 'reembed';\n else if (this._isImportActiveFor(entityId)) blockingOperation = 'import';\n else if (this._isForgetActiveFor(entityId)) blockingOperation = 'forget';\n break;\n }\n\n case 'reembed':\n if (this.activeMaintenanceJobs.has(this._reembedKey(entityId))) blockingOperation = 'reembed';\n else if (this.activeMaintenanceJobs.has(this._globalReembedKey())) blockingOperation = 'reembed';\n else if (this.activeMaintenanceJobs.has(this._pruneKey(entityId))) blockingOperation = 'prune';\n else if (this.activeMaintenanceJobs.has(this._librarianKey(entityId))) blockingOperation = 'librarian';\n else if (this.activeMaintenanceJobs.has(this._healKey(entityId))) blockingOperation = 'heal';\n else if (this.activeMaintenanceJobs.has(this._ontologyBackfillKey(entityId))) blockingOperation = 'ontologyBackfill';\n else if (this._isIngestActiveFor(entityId)) blockingOperation = 'ingest';\n else if (this._isImportActiveFor(entityId)) blockingOperation = 'import';\n else if (this._isForgetActiveFor(entityId)) blockingOperation = 'forget';\n break;\n\n case 'global_reembed':\n if (this.activeMaintenanceJobs.has(this._globalReembedKey())) blockingOperation = 'reembed';\n else if (this._isAnyMaintenanceActiveWithSuffix(':reembed')) blockingOperation = 'reembed';\n else if (this._isAnyMaintenanceActiveWithSuffix(':prune')) blockingOperation = 'prune';\n else if (this._isAnyMaintenanceActiveWithSuffix(':librarian')) blockingOperation = 'librarian';\n else if (this._isAnyMaintenanceActiveWithSuffix(':heal')) blockingOperation = 'heal';\n else if (this._isAnyMaintenanceActiveWithSuffix(':ontologyBackfill')) blockingOperation = 'ontologyBackfill';\n else if (this.activeIngestJobs.size > 0) blockingOperation = 'ingest';\n else if (this._isAnyMaintenanceActiveWithSuffix(':import')) blockingOperation = 'import';\n else if (this._isAnyMaintenanceActiveWithSuffix(':forget')) blockingOperation = 'forget';\n break;\n\n case 'import':\n case 'forget': {\n const selfKey = operation === 'import' ? this._importKey(entityId) : this._forgetKey(entityId);\n if (this.activeMaintenanceJobs.has(selfKey)) blockingOperation = operation;\n else if (this.activeMaintenanceJobs.has(this._librarianKey(entityId))) blockingOperation = 'librarian';\n else if (this.activeMaintenanceJobs.has(this._healKey(entityId))) blockingOperation = 'heal';\n else if (this.activeMaintenanceJobs.has(this._ontologyBackfillKey(entityId))) blockingOperation = 'ontologyBackfill';\n else if (this.activeMaintenanceJobs.has(this._pruneKey(entityId))) blockingOperation = 'prune';\n else if (this._isReembedActive(entityId)) blockingOperation = 'reembed';\n else if (this._isIngestActiveFor(entityId)) blockingOperation = 'ingest';\n else if (this._isImportActiveFor(entityId)) blockingOperation = 'import';\n else if (this._isForgetActiveFor(entityId)) blockingOperation = 'forget';\n break;\n }\n\n case 'global_import':\n if (this.activeMaintenanceJobs.has(this._globalImportKey())) blockingOperation = 'import';\n break;\n\n case 'ingest': {\n const sourceKey = sourceRef ?? '';\n if (this._hasIngestJob(entityId, sourceKey)) blockingOperation = 'ingest';\n else if (this.activeMaintenanceJobs.has(this._pruneKey(entityId))) blockingOperation = 'prune';\n else if (this._isReembedActive(entityId)) blockingOperation = 'reembed';\n else if (this._isImportActiveFor(entityId)) blockingOperation = 'import';\n else if (this._isForgetActiveFor(entityId)) blockingOperation = 'forget';\n break;\n }\n }\n\n if (blockingOperation) {\n throw new WikiBusyError(\n blockingOperation,\n operation === 'global_reembed' || operation === 'global_import' ? '*' : entityId\n );\n }\n\n if (operation === 'ingest') {\n this._addIngestJob(entityId, sourceRef);\n } else if (operation === 'global_reembed') {\n this.activeMaintenanceJobs.add(this._globalReembedKey());\n } else if (operation === 'global_import') {\n this.activeMaintenanceJobs.add(this._globalImportKey());\n } else {\n this.activeMaintenanceJobs.add(this.lockKeyFns[operation as Exclude<OperationType, 'ingest' | 'global_reembed' | 'global_import'>](entityId));\n }\n\n this._notifyStatusSubscribers(entityId);\n }\n\n releaseLock(operation: OperationType, entityId: string, sourceRef?: string): void {\n if (operation === 'ingest') {\n this._removeIngestJob(entityId, sourceRef);\n } else if (operation === 'global_reembed') {\n this.activeMaintenanceJobs.delete(this._globalReembedKey());\n } else if (operation === 'global_import') {\n this.activeMaintenanceJobs.delete(this._globalImportKey());\n } else {\n this.activeMaintenanceJobs.delete(this.lockKeyFns[operation as Exclude<OperationType, 'ingest' | 'global_reembed' | 'global_import'>](entityId));\n }\n\n this._notifyStatusSubscribers(entityId);\n }\n\n /**\n * Returns true if acquireLock(operation, entityId) would throw WikiBusyError.\n * Use for non-throwing conflict checks (e.g. auto-trigger gating in write()).\n */\n isBlocked(operation: OperationType, entityId: string): boolean {\n if (operation !== 'global_import' && this.activeMaintenanceJobs.has(this._globalImportKey())) return true;\n\n switch (operation) {\n case 'librarian':\n case 'heal':\n case 'ontologyBackfill':\n return this.activeMaintenanceJobs.has(this.lockKeyFns[operation](entityId)) ||\n this.activeMaintenanceJobs.has(this._pruneKey(entityId)) ||\n this._isReembedActive(entityId) ||\n this._isImportActiveFor(entityId) ||\n this._isForgetActiveFor(entityId);\n case 'prune':\n return this.activeMaintenanceJobs.has(this._pruneKey(entityId)) ||\n this.activeMaintenanceJobs.has(this._librarianKey(entityId)) ||\n this.activeMaintenanceJobs.has(this._healKey(entityId)) ||\n this.activeMaintenanceJobs.has(this._ontologyBackfillKey(entityId)) ||\n this._isReembedActive(entityId) ||\n this._isIngestActiveFor(entityId) ||\n this._isImportActiveFor(entityId) ||\n this._isForgetActiveFor(entityId);\n case 'reembed':\n return this.activeMaintenanceJobs.has(this._reembedKey(entityId)) ||\n this.activeMaintenanceJobs.has(this._globalReembedKey()) ||\n this.activeMaintenanceJobs.has(this._pruneKey(entityId)) ||\n this.activeMaintenanceJobs.has(this._librarianKey(entityId)) ||\n this.activeMaintenanceJobs.has(this._healKey(entityId)) ||\n this.activeMaintenanceJobs.has(this._ontologyBackfillKey(entityId)) ||\n this._isIngestActiveFor(entityId) ||\n this._isImportActiveFor(entityId) ||\n this._isForgetActiveFor(entityId);\n case 'global_reembed':\n return this.activeMaintenanceJobs.has(this._globalReembedKey()) ||\n this._isAnyMaintenanceActiveWithSuffix(':reembed') ||\n this._isAnyMaintenanceActiveWithSuffix(':prune') ||\n this._isAnyMaintenanceActiveWithSuffix(':librarian') ||\n this._isAnyMaintenanceActiveWithSuffix(':heal') ||\n this._isAnyMaintenanceActiveWithSuffix(':ontologyBackfill') ||\n this.activeIngestJobs.size > 0 ||\n this._isAnyMaintenanceActiveWithSuffix(':import') ||\n this._isAnyMaintenanceActiveWithSuffix(':forget');\n case 'import':\n case 'forget': {\n const selfKey = operation === 'import' ? this._importKey(entityId) : this._forgetKey(entityId);\n return this.activeMaintenanceJobs.has(selfKey) ||\n this.activeMaintenanceJobs.has(this._librarianKey(entityId)) ||\n this.activeMaintenanceJobs.has(this._healKey(entityId)) ||\n this.activeMaintenanceJobs.has(this._ontologyBackfillKey(entityId)) ||\n this.activeMaintenanceJobs.has(this._pruneKey(entityId)) ||\n this._isReembedActive(entityId) ||\n this._isIngestActiveFor(entityId) ||\n this._isImportActiveFor(entityId) ||\n this._isForgetActiveFor(entityId);\n }\n case 'global_import':\n return this.activeMaintenanceJobs.has(this._globalImportKey());\n case 'ingest':\n return this._hasIngestJob(entityId) ||\n this.activeMaintenanceJobs.has(this._pruneKey(entityId)) ||\n this._isReembedActive(entityId) ||\n this._isImportActiveFor(entityId) ||\n this._isForgetActiveFor(entityId);\n default:\n return false;\n }\n }\n\n /**\n * Auto-heal historically only gated on the heal self-key. Keep that\n * permissiveness for write() auto-trigger paths — stricter checks stay in\n * acquireLock() — with one exception: reembed sweeps, which are excluded\n * structurally rather than by accident (see below).\n */\n tryAcquireAutoHealLock(entityId: string): boolean {\n // Heal must not run during a sweep. It is safe today only because heal\n // upserts blob-less facts and the marker clear is guarded by\n // `CASE WHEN excluded.embedding_blob IS NOT NULL` — an accident of the\n // current SQL, not a stated rule. Make the exclusion structural so a\n // future heal that carries blobs cannot silently resurrect rows an\n // in-flight sweep classified. Spec 2026-09-05 §3.3.\n //\n // A refused pass is not lost work: WriteService.maybeRunHeal holds its\n // checkpoint back, so the next write retries.\n if (this.isAnyReembedActive()) return false;\n\n const healKey = this._healKey(entityId);\n if (this.activeMaintenanceJobs.has(healKey)) return false;\n this.activeMaintenanceJobs.add(healKey);\n this._notifyStatusSubscribers(entityId);\n return true;\n }\n\n /**\n * Centralized ingest lock acquisition. Acquires the hash lock FIRST\n * (FIFO across callers racing the same hash), then the synchronous\n * sourceRef ingest lock (rejects cross-entity conflicts and busy\n * operations). Returns a single zero-argument release closure that\n * unwinds in the opposite order — sourceRef first, hash second — so\n * the sourceRef lock is freed the instant its work is done and only\n * the hash lock keeps serializing the duplicate-content race window.\n *\n * On a sourceRef conflict (WikiBusyError thrown synchronously by the\n * underlying acquireLock) the hash lock is released BEFORE the error\n * propagates, so the next caller in the hash chain is not held up by\n * a request that never reached the DB.\n */\n async acquireIngestLocks(\n entityId: string,\n sourceRef: string,\n sourceHash: string,\n ): Promise<() => void> {\n const releaseHash = await this.acquireHashLock(entityId, sourceHash);\n let sourceLockAcquired = false;\n try {\n this.acquireLock('ingest', entityId, sourceRef);\n sourceLockAcquired = true;\n } catch (err) {\n releaseHash();\n throw err;\n }\n return () => {\n try {\n if (sourceLockAcquired) this.releaseLock('ingest', entityId, sourceRef);\n } finally {\n releaseHash();\n }\n };\n }\n\n /**\n * Validates then acquires global + per-entity import locks atomically.\n * Validates all entities before acquiring any lock (same as current importDump semantics).\n */\n acquireImportLocks(entityIds: string[]): void {\n for (const entityId of entityIds) {\n if (this.activeMaintenanceJobs.has(this._importKey(entityId))) throw new WikiBusyError('import', entityId);\n if (this.activeMaintenanceJobs.has(this._librarianKey(entityId))) throw new WikiBusyError('librarian', entityId);\n if (this.activeMaintenanceJobs.has(this._healKey(entityId))) throw new WikiBusyError('heal', entityId);\n if (this.activeMaintenanceJobs.has(this._ontologyBackfillKey(entityId))) throw new WikiBusyError('ontologyBackfill', entityId);\n if (this.activeMaintenanceJobs.has(this._pruneKey(entityId))) throw new WikiBusyError('prune', entityId);\n if (this._isReembedActive(entityId)) throw new WikiBusyError('reembed', entityId);\n if (this._isIngestActiveFor(entityId)) throw new WikiBusyError('ingest', entityId);\n if (this._isForgetActiveFor(entityId)) throw new WikiBusyError('forget', entityId);\n }\n if (this.activeMaintenanceJobs.has(this._globalImportKey())) throw new WikiBusyError('import', '*');\n\n this.activeMaintenanceJobs.add(this._globalImportKey());\n for (const entityId of entityIds) {\n this.activeMaintenanceJobs.add(this._importKey(entityId));\n }\n }\n\n releaseImportLocks(entityIds: string[]): void {\n this.activeMaintenanceJobs.delete(this._globalImportKey());\n for (const entityId of entityIds) {\n this.activeMaintenanceJobs.delete(this._importKey(entityId));\n }\n }\n\n getEntityStatus(entityId: string): EntityStatus {\n return {\n ingesting: this._isIngestActiveFor(entityId),\n librarian: this.activeMaintenanceJobs.has(this._librarianKey(entityId)),\n heal: this.activeMaintenanceJobs.has(this._healKey(entityId)),\n };\n }\n\n subscribeEntityStatus(entityId: string, callback: (status: EntityStatus) => void): () => void {\n const initial = this.getEntityStatus(entityId);\n let set = this.statusSubscribers.get(entityId);\n if (!set) {\n set = new Set();\n this.statusSubscribers.set(entityId, set);\n }\n\n const entry = { callback, last: this._copyEntityStatus(initial) };\n set.add(entry);\n\n try {\n callback(this._copyEntityStatus(initial));\n } catch (err) {\n console.error(`[JobManager] callback error for entityId=\"${entityId}\" during initial emission`, err);\n }\n\n let active = true;\n return () => {\n if (!active) return;\n active = false;\n const s = this.statusSubscribers.get(entityId);\n if (!s) return;\n s.delete(entry);\n if (s.size === 0) this.statusSubscribers.delete(entityId);\n };\n }\n\n private _copyEntityStatus(s: EntityStatus): EntityStatus {\n return { ingesting: s.ingesting, librarian: s.librarian, heal: s.heal };\n }\n\n private _notifyStatusSubscribers(entityId: string): void {\n if (entityId === '*') return;\n\n const set = this.statusSubscribers.get(entityId);\n if (!set || set.size === 0) return;\n\n for (const entry of Array.from(set)) {\n if (!set.has(entry)) continue;\n const next = this.getEntityStatus(entityId);\n\n if (entry.last.ingesting === next.ingesting &&\n entry.last.librarian === next.librarian &&\n entry.last.heal === next.heal) {\n continue;\n }\n\n entry.last = this._copyEntityStatus(next);\n try {\n entry.callback(this._copyEntityStatus(next));\n } catch (err) {\n console.error(`[JobManager] callback error for entityId=\"${entityId}\" during transition emission`, err);\n }\n }\n }\n}\n","import type { ExtractedFact, ExtractedTask } from '../types';\nimport { WikiParseError } from '../types';\n\n/**\n * Maximum number of candidate substrings the tier-2 walker will try before\n * throwing `WikiParseError`. 5 covers the realistic case (a few bare quotes\n * produce a few candidate spans) without unbounded retry on truly broken\n * inputs.\n */\nconst MAX_REPAIR_CANDIDATES = 5;\n\n/**\n * Throws {@link WikiParseError} for the \"no JSON object/array found\" case.\n * Used at the two strict-tier throw sites that differ only in whether a\n * `[`/`{` was located: when `start === null`, no open bracket was found;\n * when `start` is a number, an open bracket was found but no balanced\n * close existed. Both share the user-facing diagnostic.\n */\nfunction throwNoJsonFound(text: string, start: number | null): never {\n throw new WikiParseError(\n 'No JSON object/array found in LLM response',\n { tier: 'strict', position: start, slice: text },\n );\n}\n\n/**\n * Extract JSON from an LLM response.\n *\n * Tier 1 (strict): the existing hand-rolled brace-matching scanner. Walks\n * `text` from the first `{` or `[` to its matching close, respecting `\\\"` and\n * `\\\\`. Correct whenever the input contains no unescaped `\"` inside string\n * bodies. Returns the parsed value via `JSON.parse`.\n *\n * Tier 2 (repair): triggered only when tier 1 throws. Re-walks the raw text\n * from `start` (NOT from the scanner's possibly-truncated slice) with a\n * container-context stack that classifies every `\"` as **structural** (open\n * or close a string) or **content** (needs `\\` prefix). Produces candidate\n * substrings at every position the container stack returns to empty and\n * tries each largest-first; the first that `JSON.parse` accepts is returned.\n *\n * Throws {@link WikiParseError} when both tiers fail. The error's `tier`\n * field distinguishes 'strict' (no scanner slice found) from 'repair'\n * (scanner slice found but unparsable) from 'all' (catch-all).\n */\nexport function parseJsonResponse<T>(text: string): T {\n const firstBrace = text.indexOf('{');\n const firstBracket = text.indexOf('[');\n\n let start: number;\n let openChar: string;\n\n const useBrace =\n firstBrace !== -1 && (firstBracket === -1 || firstBrace < firstBracket);\n\n if (useBrace) {\n start = firstBrace;\n openChar = '{';\n } else if (firstBracket !== -1) {\n start = firstBracket;\n openChar = '[';\n } else {\n throwNoJsonFound(text, null);\n }\n\n // Tier 1: try the existing scanner first. If `JSON.parse` succeeds we're done.\n const slice = scanJsonSlice(text, start, openChar);\n if (slice !== null) {\n try {\n return JSON.parse(slice) as T;\n } catch {\n // fall through to tier 2\n }\n }\n\n // Tier 2: container-aware walker over the raw text. The scanner's slice may\n // be arbitrarily truncated by a bare quote mid-string — running the walker\n // on the raw text from `start` is the only way to get a complete container\n // span to repair against. The walker validates via `JSON.parse` itself and\n // returns the already-parsed value, so we don't re-parse on the hot path.\n //\n // The walker runs twice under opposing comma-ambiguity policies — see\n // `containerAwareRepair` docstring. Both passes can produce parseable\n // JSON for the SAME input but with different shapes — e.g. for\n // `{\"title\":\"He said \"hi\"\",\"body\":\"ok\"}` the odd-parity pass swallows\n // `,\"body\":\"ok\"` into the title (parseable but wrong), while for\n // `{\"title\":\"24\" monitor\",\"body\":\"ok\"}` the even-parity pass does the\n // swallowing. When both parse, we prefer the pass that mutated the input\n // LESS (fewer content-quote escapes): the correct interpretation escapes\n // exactly the true bare quotes, while the swallowing one escapes the\n // structural quotes it consumes too. When only the odd-parity pass parsed\n // AND it never hit a comma-ambiguity position, the even-parity pass is\n // guaranteed to make identical decisions, so we skip it entirely. Each\n // pass is bounded by MAX_REPAIR_CANDIDATES.\n const repairOdd = containerAwareRepair(text, start, false);\n if (repairOdd.success !== null && !repairOdd.ambiguous) {\n return repairOdd.success as T;\n }\n const repairEven = containerAwareRepair(text, start, true);\n if (repairOdd.success !== null && repairEven.success !== null) {\n // Both policies produced a parseable candidate. Prefer the minimal\n // repair; on a tie (identical walks) keep the odd-parity result, which\n // matches the historical single-pass behavior.\n const pick = repairEven.escapes < repairOdd.escapes ? repairEven : repairOdd;\n return pick.success as T;\n }\n if (repairOdd.success !== null) {\n return repairOdd.success as T;\n }\n if (repairEven.success !== null) {\n return repairEven.success as T;\n }\n // Both policies failed to parse. Prefer the even-parity failed candidate\n // as the diagnostic — it's the original walker behavior and its failure\n // message matches what callers (and existing tests) expect on\n // balanced-but-invalid payloads like `{\"facts\":}`.\n const repair = repairEven.failed !== null ? repairEven : repairOdd;\n if (repair.failed !== null) {\n throw new WikiParseError(\n `Repair produced a candidate but JSON.parse rejected it: ${repair.failed.message}`,\n { tier: 'repair', position: repair.failed.position, slice: repair.failed.candidate },\n );\n }\n\n // Per spec (WikiParseError `tier: 'strict'`): a scanner that produced NO\n // usable slice (no balanced close) is a strict failure even when the\n // container-aware walker also finds nothing — the input is structurally\n // incomplete, not just unparseable.\n if (slice === null) {\n throwNoJsonFound(text, start);\n }\n\n throw new WikiParseError(\n 'No parsable JSON candidate found',\n { tier: 'all', position: start, slice: text },\n );\n}\n\n/**\n * Tier-1 scanner: returns the substring from `start` to the matching close\n * of the container opened by `openChar` at `start`, or `null` if no balanced\n * close exists. Pure function — extracted so `parseJsonResponse` reads as\n * the two-tier flow it implements.\n */\nfunction scanJsonSlice(text: string, start: number, openChar: string): string | null {\n const closeChar = openChar === '{' ? '}' : ']';\n let depth = 0;\n let inString = false;\n let escape = false;\n let end = -1;\n for (let i = start; i < text.length; i++) {\n const ch = text[i];\n if (escape) { escape = false; continue; }\n if (ch === '\\\\' && inString) { escape = true; continue; }\n if (ch === '\"') { inString = !inString; continue; }\n if (inString) continue;\n if (ch === openChar) { depth++; continue; }\n if (ch === closeChar) {\n depth--;\n if (depth === 0) { end = i; break; }\n }\n }\n if (end === -1) return null;\n // safeSlice lives in this same file and is the project's surrogate-pair-safe\n // string-slice helper (used by chunkText). Bare `text.slice(start, end + 1)`\n // can split a UTF-16 surrogate pair when `end` lands between the high and\n // low halves; the walker downstream then trips on a U+FFFD replacement char.\n return safeSlice(text, start, end + 1);\n}\n\n/**\n * Tier-2 walker: re-walks the raw text from `start` with a container-context\n * stack and a peek-ahead rule that classifies every `\"` as either structural\n * (opens/closes a string) or content (needs `\\` prefix). Produces candidate\n * substrings at every balanced container close and returns the first one\n * that `JSON.parse` would accept (largest balanced span first), or `null` if\n * no candidate parses.\n *\n * The walker tries two policies at comma-ambiguity positions (`\"X\"`,\n * `X` ends in a bare quote, peek-ahead is `,`):\n *\n * - `closeOnEvenParity=true` — treat the quote as STRUCTURAL CLOSE when the\n * bare-quote count is EVEN, content escape when ODD. This is the heuristic\n * that has historically matched LLM output (it works for `\"He said \"hi\", then left.\"`).\n * - `closeOnEvenParity=false` — the opposite flip. Required for inputs whose\n * real close is at an ODD count (e.g. `\"24\" monitor\",\"body\":\"ok\"}`), where\n * the model intended one literal `\"` inside the value string and the next\n * `\"` to be the structural close.\n *\n * `parseJsonResponse` runs both policies and accepts the first parse-success\n * from either; {@link MAX_REPAIR_CANDIDATES} bounds each policy's emissions\n * so the combined work stays small.\n */\ninterface ContainerFrame {\n container: 'object' | 'array';\n /**\n * For objects: `true` while the next string token starts a property NAME;\n * `false` while the next string token starts a property VALUE. Stays the\n * role through `,` (a `,` in an object leaves us expecting a key again) and\n * through `:` (a `:` leaves us expecting a value). Arrays always treat\n * every string as a value, so this flag is unused for arrays.\n */\n expectKey: boolean;\n}\n\ninterface RepairFailure {\n candidate: string;\n position: number | null;\n message: string;\n}\n\ninterface RepairResult {\n /** First candidate that JSON.parse accepted, or null if none parsed. */\n success: unknown | null;\n /** First candidate that JSON.parse rejected (best diagnostic), or null. */\n failed: RepairFailure | null;\n /** Number of content quotes this policy escaped (mutated) while walking.\n * Used to arbitrate when BOTH policies produce a parseable candidate:\n * the interpretation that mutated the input less is preferred. */\n escapes: number;\n /** True when the walk hit at least one comma-ambiguity position — the\n * only place the two policies' decisions can diverge. When false, the\n * opposing-policy pass is guaranteed to make identical decisions, so the\n * caller can skip it entirely. */\n ambiguous: boolean;\n}\n\nfunction containerAwareRepair(\n text: string,\n start: number,\n closeOnEvenParity: boolean,\n): RepairResult {\n // The walker produces a stream of balanced-span candidates in largest-first\n // order. We try each via `JSON.parse` at emission time so the success\n // path short-circuits without ever building the trailing-prefix out of\n // the walker; on a rejection we capture the first failure as the best\n // diagnostic and keep walking to find another candidate (bounded by\n // MAX_REPAIR_CANDIDATES). The `failed` slot is what callers use to\n // construct a `WikiParseError` with `tier: 'repair'` when nothing parses\n // — the public contract documents the slice + parse position in the\n // error.\n const stack: ContainerFrame[] = [];\n let inString = false;\n let stringRole: 'key' | 'value' | null = null;\n let escape = false;\n let i = start;\n // Output buffer; rebuilt as we walk, used to emit candidate substrings.\n let out = '';\n // Tracks bare quotes emitted as content so far inside the current string\n // token. Used to suppress a structural close on a `,` peek-ahead when the\n // body still has an open unescaped bare quote (`{\"body\":\"hi\", then...`}`);\n // closing prematurely puts the comma at structural level where JSON.parse\n // expects a property name. Reset on every structural close (or open).\n let bareQuoteCount = 0;\n // Best rejection seen so far — captured when JSON.parse rejects a\n // candidate so we can surface it on `WikiParseError(tier: 'repair')`.\n let bestFailed: RepairFailure | null = null;\n // Content quotes escaped so far this pass (see RepairResult.escapes).\n let escapes = 0;\n // Whether any comma-ambiguity position was reached (see\n // RepairResult.ambiguous).\n let ambiguous = false;\n // Captured successfully-parsed value of the first candidate that JSON.parse\n // accepted. Carried through the walker's short-circuit return so callers\n // can skip a second `JSON.parse` and `T`-cast on the hot success path.\n let bestSuccess: unknown = null;\n let attempts = 0;\n\n // Try `JSON.parse(candidate)` immediately on emission; capture the\n // failure as bestFailed (or the value as bestSuccess) and bump the\n // attempt counter. Returns true on success so the caller can short-circuit\n // out of the walk.\n //\n // `safeErrorToString` (defined in this same file) is the hardened\n // non-throwing coercion for the message field. `JSON.parse` always throws\n // a `SyntaxError`, but a hostile SyntaxError subclass with a throwing\n // `message` getter could still escape a raw `err.message` access —\n // delegating to `safeErrorToString` keeps the helper non-throwing.\n function tryEmitCandidate(candidate: string): boolean {\n attempts++;\n try {\n bestSuccess = JSON.parse(candidate);\n return true;\n } catch (err) {\n if (bestFailed === null) {\n bestFailed = {\n candidate,\n position: extractParsePosition(err),\n message: safeErrorToString(err),\n };\n }\n return false;\n }\n }\n\n while (i < text.length) {\n const ch = text[i];\n\n // Between top-level spans (stack empty after a failed candidate emit):\n // skip everything except a new container opener, and never accumulate\n // the inter-span text into `out` — sibling candidates must be\n // standalone spans, not span1 + prose + span2 concatenations that\n // JSON.parse can never accept.\n if (stack.length === 0 && !inString) {\n if (ch === '{' || ch === '[') {\n stack.push({ container: ch === '{' ? 'object' : 'array', expectKey: true });\n out += ch;\n }\n i++;\n continue;\n }\n\n if (escape) {\n out += ch;\n escape = false;\n i++;\n continue;\n }\n if (inString && ch === '\\\\') {\n out += ch;\n escape = true;\n i++;\n continue;\n }\n // Raw C0 control characters are invalid inside JSON strings, always.\n // Unlike the bare-quote case this repair is fully deterministic (no\n // comma-parity ambiguity — a control char inside a string body can\n // only be content), so both policy passes escape identically.\n if (inString) {\n const code = ch.charCodeAt(0);\n if (code < 0x20) {\n out += controlCharEscape(code);\n i++;\n continue;\n }\n }\n if (ch === '\"') {\n // Peek-ahead: skip whitespace, then look at the next non-whitespace char.\n let j = i + 1;\n while (j < text.length && (text[j] === ' ' || text[j] === '\\t' || text[j] === '\\n' || text[j] === '\\r')) {\n j++;\n }\n const next = j < text.length ? text[j] : '';\n\n if (!inString) {\n // A `\"` sitting at structural level right before a container close\n // is stray punctuation from a mis-tracked string boundary — emitting\n // it would open an unterminated string and guarantee JSON.parse\n // rejects the candidate. Skip the quote itself, preserve any\n // whitespace the peek-ahead skipped, emit the close, and pop.\n if (next === '}' || next === ']') {\n if (j > i + 1) out += text.slice(i + 1, j);\n out += next;\n i = j + 1;\n stack.pop();\n if (stack.length === 0) {\n if (tryEmitCandidate(out)) return { success: bestSuccess, failed: bestFailed, escapes, ambiguous };\n if (attempts >= MAX_REPAIR_CANDIDATES) break;\n out = '';\n }\n continue;\n }\n // Structural opening quote — always treated as opening (no escape).\n // Determine the string's role from the top frame: object + expectKey\n // → key, otherwise value. Arrays always treat strings as values.\n const top = stack[stack.length - 1];\n stringRole = top?.container === 'object' && top.expectKey ? 'key' : 'value';\n out += ch;\n inString = true;\n i++;\n continue;\n }\n\n // We're inside a string. Closing if next is one of , } ] : or another \" followed by :\n // Suppress the comma-only close when we have an open bare quote —\n // a `,` peek-ahead after an odd number of bare quotes means the\n // comma is body content, not a structural separator.\n //\n // Role-aware: `next === ':'` and `next === '\"' && text[j+1] === ':'`\n // are KEY-close signals (the `: ` is the JSON \"this string was a key\"\n // separator) and only fire for `stringRole === 'key'`. For value\n // strings, a `:` after the closing quote is body content (e.g.\n // `{\"body\":\"foo: \"bar\": baz\"}`) — closing prematurely there corrupts\n // the value. The `,` `}` `]` cases are value-close signals and always\n // apply.\n const commaOnly = next === ',';\n const isKeyClose = stringRole === 'key' && (\n next === ':' ||\n (next === '\"' && j + 1 < text.length && text[j + 1] === ':')\n );\n const isValueClose = !commaOnly && (\n next === ',' ||\n next === '}' ||\n next === ']'\n );\n // Comma-ambiguity: when the peek-ahead is `,` after at least one\n // bare-quote content escape, neither interpretation is structurally\n // implied — the comma is either a value separator OR content body.\n // The two passes diverge ONLY here (see the parameter docs on\n // `containerAwareRepair`): the `closeOnEvenParity=true` pass closes\n // on an even count (the legacy heuristic), the false pass on an odd\n // count. When `bareQuoteCount === 0` no ambiguity exists — the comma\n // must close — so both passes close and the caller can skip the\n // second pass entirely (see RepairResult.ambiguous).\n if (commaOnly && bareQuoteCount > 0) ambiguous = true;\n const shouldCommaClose =\n commaOnly && (\n bareQuoteCount === 0 ||\n (closeOnEvenParity\n ? bareQuoteCount % 2 === 0\n : bareQuoteCount % 2 === 1)\n );\n const isClosing =\n isKeyClose ||\n isValueClose ||\n shouldCommaClose;\n\n if (isClosing) {\n out += ch;\n inString = false;\n // Update the top frame's expectKey state. After closing a key, the\n // next string token is a value (separator is `:`) — expectKey=false.\n // After closing a value in an object, the next string token is a key\n // (separator is `,` or end-of-object) — expectKey=true. Array frames\n // ignore this flag (every string in an array is a value).\n const topFrame = stack[stack.length - 1];\n if (topFrame && topFrame.container === 'object') {\n topFrame.expectKey = stringRole === 'value';\n }\n stringRole = null;\n bareQuoteCount = 0;\n i++;\n continue;\n }\n\n // Content quote — escape it.\n out += '\\\\' + ch;\n bareQuoteCount++;\n escapes++;\n i++;\n continue;\n }\n if (!inString && (ch === '{' || ch === '[')) {\n // Push a new frame. Objects start expecting a key; arrays ignore the\n // flag (every string token is a value).\n stack.push({ container: ch === '{' ? 'object' : 'array', expectKey: true });\n out += ch;\n i++;\n continue;\n }\n if (!inString && ch === ',') {\n // A `,` in an object leaves us expecting a key. The string-close handler\n // already sets `expectKey=true` after a value close, so the only case\n // we need to handle here is the unit-structural case where the prior\n // element was a primitive (number, null, true, false, etc.) — its\n // position in the OUT stream is identical to a value close for the\n // purposes of the next string token.\n const topFrame = stack[stack.length - 1];\n if (topFrame && topFrame.container === 'object') {\n topFrame.expectKey = true;\n }\n out += ch;\n i++;\n continue;\n }\n if (!inString && (ch === '}' || ch === ']')) {\n out += ch;\n stack.pop();\n if (stack.length === 0) {\n // Balanced close at this position — try the candidate. The largest\n // outer span is the first one tried, so this short-circuits on the\n // success path. On a rejection, reset `out` so any trailing sibling\n // span is emitted standalone rather than concatenated onto the\n // already-rejected prefix.\n if (tryEmitCandidate(out)) return { success: bestSuccess, failed: bestFailed, escapes, ambiguous };\n if (attempts >= MAX_REPAIR_CANDIDATES) break;\n out = '';\n }\n i++;\n continue;\n }\n\n out += ch;\n i++;\n }\n\n return { success: null, failed: bestFailed, escapes, ambiguous };\n}\n\n/**\n * Maps a C0 control character's code point to its JSON string escape.\n * Uses the short forms JSON shares with JS (\\n, \\t, \\r, \\b, \\f) and\n * \\u00XX for everything else, exactly as JSON.stringify would.\n */\nfunction controlCharEscape(code: number): string {\n switch (code) {\n case 0x0A: return '\\\\n';\n case 0x09: return '\\\\t';\n case 0x0D: return '\\\\r';\n case 0x08: return '\\\\b';\n case 0x0C: return '\\\\f';\n default: return '\\\\u' + code.toString(16).padStart(4, '0');\n }\n}\n\n/**\n * Pulls the position offset out of a V8 `SyntaxError` message when present.\n * The V8 message format is `\"Unexpected token X in JSON at position N\"` (or\n * `\"Unexpected end of JSON input\"` with no position). We return `null` when\n * no position can be parsed — `WikiParseError.position` is `number | null`.\n *\n * Delegates the unknown→string coercion to `safeErrorToString` so a hostile\n * value (throwing toString, Proxy rejecting property access) can never throw\n * out of this helper and unwind the walker. JSON.parse always throws a\n * `SyntaxError`, so the defensive branch is rarely exercised in practice,\n * but the fallback is here to keep the walker non-throwing by construction.\n */\nfunction extractParsePosition(err: unknown): number | null {\n const match = /position\\s+(\\d+)/.exec(safeErrorToString(err));\n return match ? Number(match[1]) : null;\n}\n\n/**\n * Non-throwing coercion of an arbitrary JavaScript value to a string for\n * error-message reporting. JavaScript's `String(e)` returns `e.toString()`\n * for objects, which can throw if `toString` itself throws (e.g. an object\n * with a misbehaving prototype). Without this guard, a single provider-side\n * rejection can escape an `ingestDocument` per-chunk `catch` and tear down\n * `withConcurrency`, discarding every sibling chunk's results — the exact\n * silent-forever failure mode the partial-commit work exists to prevent.\n *\n * Falls back through:\n * - `Error.message` for `Error` instances (always available).\n * - `String(e)`, wrapped in try/catch.\n * - `Object.prototype.toString.call(e)` if `String(e)` threw (also wrapped).\n * - A static `[unstringifiable error]` marker as a final guarantee.\n */\nexport function safeErrorToString(e: unknown): string {\n // `e instanceof Error` invokes the `getPrototypeOf` trap on `e`. A Proxy\n // whose trap rejects turns the type-check itself into a throw point,\n // escaping every catch around this function body. Treat the trap throw\n // as \"not an Error\" and fall through to the String() / Object.prototype\n // paths, which themselves catch their own throws.\n let isErrorLike = false;\n try {\n isErrorLike = e instanceof Error;\n } catch {\n // hostile Proxy whose getPrototypeOf trap rejects — fall through\n }\n if (isErrorLike) {\n // Defensive: a hostile `Error` subclass or a tampered native Error could\n // set `message` to a non-string (e.g. `err.message = 42`) or make it a\n // throwing getter. `e.name` is similarly attacker-controllable. Coerce\n // both without unwinding so this helper is truly non-throwing.\n const msg = readErrorField(e, 'message');\n if (typeof msg === 'string' && msg.length > 0) return msg;\n const name = readErrorField(e, 'name');\n if (typeof name === 'string' && name.length > 0) return name;\n return '[Error]';\n }\n try {\n return String(e);\n } catch {\n try {\n return Object.prototype.toString.call(e);\n } catch {\n return '[unstringifiable error]';\n }\n }\n}\n\n/**\n * Read a fixed string-typed field off an `Error` instance without ever\n * throwing, even if a subclass installs a hostile getter. Internal helper\n * for `safeErrorToString`.\n */\nfunction readErrorField(e: unknown, key: 'message' | 'name'): unknown {\n try {\n return (e as Record<string, unknown>)[key];\n } catch {\n return undefined;\n }\n}\n\nexport function sanitizeRankerError(err: unknown, sanitizeRankerErrors: boolean | undefined): Error {\n // `err instanceof Error` invokes the `getPrototypeOf` trap on `err`. A\n // hostile Proxy (e.g. an injected VectorRanker returning one) whose trap\n // rejects would otherwise escape this \"sanitize\" function. Compute the\n // guard once — the property accesses below share the same hostile-input\n // surface and need their own guards.\n let isErrorLike = false;\n try {\n isErrorLike = err instanceof Error;\n } catch {\n /* hostile Proxy — treat as non-Error */\n }\n if (sanitizeRankerErrors === false) {\n // `String(err)` invokes the `toString` / `Symbol.toPrimitive` trap on\n // `err`; a hostile Proxy whose trap rejects would throw out of this\n // function, defeating the non-throwing contract. Delegate to the\n // hardened `safeErrorToString` helper which converges all coercion\n // paths onto the static `[unstringifiable error]` marker on throw.\n return isErrorLike ? (err as Error) : new Error(safeErrorToString(err));\n }\n // `errLike.constructor?.name` and `.cause` access can also throw on a\n // hostile Error subclass with throwing getters (optional chaining `?.`\n // only short-circuits null/undefined, not trap throws). Wrap each access\n // so the function's documented non-throwing contract holds for all\n // attacker-controlled inputs.\n let errLike: Error | null = null;\n if (isErrorLike) errLike = err as Error;\n let typeName: string;\n try {\n if (errLike) {\n const rawName: unknown = errLike.constructor?.name;\n typeName = typeof rawName === 'string' ? rawName : 'Error';\n } else {\n typeName = typeof err;\n }\n } catch {\n typeName = isErrorLike ? 'Error' : typeof err;\n }\n let innerCause: Error | undefined;\n if (errLike) {\n let cause: unknown;\n try { cause = errLike.cause; } catch { cause = undefined; }\n if (cause !== undefined) {\n let causeName: string;\n try {\n const rawCauseName: unknown = (cause as Error)?.constructor?.name;\n causeName = typeof rawCauseName === 'string' ? rawCauseName : typeof cause;\n } catch {\n causeName = typeof cause;\n }\n innerCause = new Error(`Caused by: ${causeName}`);\n }\n }\n const sanitized = new Error(\n `VectorRanker ${typeName} (message scrubbed for security)`,\n innerCause ? { cause: innerCause } : undefined,\n );\n try { sanitized.name = typeName; } catch { /* hostile name setter — leave default */ }\n return sanitized;\n}\n\n/**\n * Slices a string like `String.prototype.slice`, but clamps out-of-range\n * indices instead of relying on JS's implicit clamping, normalizes a\n * start-after-end range by swapping the two bounds, and nudges either bound\n * off a UTF-16 surrogate pair boundary so slicing never splits one code\n * point in half.\n *\n * @param value - The source string to slice.\n * @param start - Start index; negative counts from the end, out-of-range\n * values are clamped to `[0, value.length]`.\n * @param end - End index (exclusive); defaults to `value.length` when\n * omitted. Same clamping/negative-index rules as `start`.\n * @returns The sliced substring, never splitting a surrogate pair.\n */\nexport function safeSlice(value: string, start: number, end?: number): string {\n const length = value.length;\n let safeStart = start < 0 ? Math.max(length + start, 0) : Math.min(start, length);\n let safeEnd = end === undefined\n ? length\n : end < 0\n ? Math.max(length + end, 0)\n : Math.min(end, length);\n\n if (safeStart > safeEnd) {\n [safeStart, safeEnd] = [safeEnd, safeStart];\n }\n\n if (\n safeStart > 0 &&\n safeStart < length &&\n value.charCodeAt(safeStart) >= 0xDC00 &&\n value.charCodeAt(safeStart) <= 0xDFFF &&\n value.charCodeAt(safeStart - 1) >= 0xD800 &&\n value.charCodeAt(safeStart - 1) <= 0xDBFF\n ) {\n safeStart--;\n }\n\n if (\n safeEnd > 0 &&\n safeEnd < length &&\n value.charCodeAt(safeEnd - 1) >= 0xD800 &&\n value.charCodeAt(safeEnd - 1) <= 0xDBFF &&\n value.charCodeAt(safeEnd) >= 0xDC00 &&\n value.charCodeAt(safeEnd) <= 0xDFFF\n ) {\n safeEnd--;\n }\n\n return value.slice(safeStart, safeEnd);\n}\n\n/**\n * Splits `input` into chunks of at most `maxChunkLength` characters,\n * preferring to split on a paragraph break, then a sentence terminator,\n * then whitespace, falling back to a hard cut only when none of those are\n * found within the window. Consecutive chunks overlap by up to `overlap`\n * characters so context isn't lost at a chunk boundary. This is the exact\n * chunking algorithm `IngestionService.ingestDocument` uses before\n * embedding, so callers can reproduce ingest-time chunk boundaries exactly\n * given the same `maxChunkLength`/`overlap` (see `DEFAULT_MAX_CHUNK_LENGTH`\n * and `DEFAULT_CHUNK_OVERLAP` for the defaults ingest uses).\n *\n * @param input - The text to chunk; leading/trailing whitespace is trimmed\n * before chunking. Empty/whitespace-only input returns the empty result\n * below without validating `maxChunkLength`/`overlap`.\n * @param maxChunkLength - For non-empty input, maximum characters per chunk;\n * must be an integer >= 2.\n * @param overlap - For non-empty input, maximum number of characters each\n * chunk repeats from the end of the previous chunk; must be a\n * non-negative integer less than `maxChunkLength`. A chunk repeats fewer\n * characters when the previous chunk was shorter than `overlap`.\n * @returns `chunks` — the resulting chunk strings (empty array for\n * empty/whitespace-only input); `truncated` — `true` if any split had to\n * fall back to a hard cut (no paragraph/sentence/whitespace boundary\n * found in the window).\n */\nexport function chunkText(\n input: string,\n maxChunkLength: number,\n overlap: number\n): { chunks: string[]; truncated: boolean } {\n const text = input.trim();\n if (text.length === 0) return { chunks: [], truncated: false };\n if (!Number.isInteger(maxChunkLength) || maxChunkLength < 2) {\n throw new Error('maxChunkLength must be an integer >= 2');\n }\n if (!Number.isInteger(overlap) || overlap < 0 || overlap >= maxChunkLength) {\n throw new Error('overlap must be a non-negative integer < maxChunkLength');\n }\n\n const chunks: string[] = [];\n let truncated = false;\n let cursor = 0;\n const halfMax = Math.floor(maxChunkLength / 2);\n\n while (cursor < text.length) {\n const remaining = text.length - cursor;\n if (remaining <= maxChunkLength) {\n chunks.push(safeSlice(text, cursor, text.length));\n break;\n }\n\n const windowEnd = cursor + maxChunkLength;\n const minSplit = cursor + halfMax;\n\n // 1. paragraph break\n let splitPoint = -1;\n const paraIdx = text.lastIndexOf('\\n\\n', windowEnd);\n if (paraIdx >= minSplit && paraIdx + 2 <= windowEnd) {\n splitPoint = paraIdx + 2;\n }\n\n // 2. sentence terminator (single left-to-right pass, no lookahead regex)\n if (splitPoint === -1) {\n let lastTerm = -1;\n for (let i = minSplit; i < windowEnd - 1; i++) {\n const ch = text[i];\n if ((ch === '.' || ch === '!' || ch === '?') && /\\s/.test(text[i + 1])) {\n lastTerm = i + 2; // include the terminator + whitespace\n }\n }\n if (lastTerm !== -1 && lastTerm <= windowEnd) splitPoint = lastTerm;\n }\n\n // 3. whitespace\n if (splitPoint === -1) {\n for (let i = windowEnd - 1; i >= minSplit; i--) {\n if (/\\s/.test(text[i])) {\n splitPoint = i + 1;\n break;\n }\n }\n }\n\n // 4. hard cut\n if (splitPoint === -1) {\n truncated = true;\n splitPoint = windowEnd;\n }\n\n chunks.push(safeSlice(text, cursor, splitPoint));\n const next = Math.max(splitPoint - overlap, cursor + 1);\n cursor = next;\n }\n\n return { chunks, truncated };\n}\n\nexport async function withConcurrency<T>(tasks: Array<() => Promise<T>>, limit: number): Promise<T[]> {\n const results: T[] = new Array(tasks.length);\n let index = 0;\n let failed = false;\n let firstError: unknown;\n async function worker() {\n while (index < tasks.length && !failed) {\n const i = index++;\n try {\n results[i] = await tasks[i]();\n } catch (e) {\n if (!failed) { failed = true; firstError = e; }\n return;\n }\n }\n }\n const workerCount = tasks.length === 0 ? 0 : Math.min(Math.max(limit, 1), tasks.length);\n await Promise.allSettled(Array.from({ length: workerCount }, worker));\n if (failed) throw firstError;\n return results;\n}\n\nexport function clip(value: string, max: number): string {\n if (typeof value !== 'string') return '';\n const s = value.trim();\n return s.length <= max ? s : safeSlice(s, 0, max).trimEnd();\n}\n\nexport function validateTags(tags: any[]): string[] {\n if (!Array.isArray(tags)) return [];\n return tags\n .filter(t => typeof t === 'string')\n .map(t => t.trim().toLowerCase())\n .filter(t => t.length > 0 && t.length <= 40)\n .slice(0, 6);\n}\n\n/** Hard ceiling on evidence quotes per fact (spec §6.2). More than this makes the fact ungrounded. */\nexport const MAX_EVIDENCE_QUOTES = 10;\n\n/**\n * Normalize a fact's raw `evidence`: an array of strings, each trimmed, with\n * non-strings and empty entries ignored. Collection stops one entry past the\n * ceiling, which is enough to decide `too_many_quotes` without trimming an\n * unbounded array. Returns undefined when `raw` is not an array.\n */\nexport function normalizeEvidence(raw: unknown): string[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const out: string[] = [];\n for (const entry of raw) {\n if (typeof entry !== 'string') continue;\n const trimmed = entry.trim();\n if (!trimmed) continue;\n out.push(trimmed);\n if (out.length > MAX_EVIDENCE_QUOTES) break;\n }\n return out;\n}\n\nexport function validateFact(fact: any): ExtractedFact | null {\n if (typeof fact?.title !== 'string' || typeof fact?.body !== 'string') return null;\n const title = clip(fact.title, 80);\n const body = clip(fact.body, 800);\n if (!title || !body) return null;\n\n let confidence = fact.confidence;\n if (confidence !== 'certain' && confidence !== 'tentative') confidence = 'inferred';\n\n const valid: ExtractedFact = {\n ...fact,\n title,\n body,\n confidence,\n tags: validateTags(fact.tags)\n };\n const evidence = normalizeEvidence(fact.evidence);\n if (evidence) valid.evidence = evidence;\n else delete valid.evidence;\n return valid;\n}\n\nexport function validateTask(task: any): ExtractedTask | null {\n if (typeof task?.description !== 'string') return null;\n const description = clip(task.description, 200);\n if (!description) return null;\n\n let priority = task.priority;\n if (typeof priority !== 'number' || !isFinite(priority)) priority = 0;\n // Clamp priority to valid range 0-10 as documented in the prompt contract\n priority = Math.max(0, Math.min(10, Math.round(priority)));\n\n return {\n ...task,\n description,\n priority\n };\n}\n\n/** Why `validateFact` rejected `raw`. Only meaningful when `validateFact(raw)` returned null. */\nexport function factRejectionReason(raw: unknown): 'invalid_shape' | 'missing_title' | 'missing_body' {\n const fact = raw as { title?: unknown; body?: unknown } | null | undefined;\n if (typeof fact?.title !== 'string' || typeof fact?.body !== 'string') return 'invalid_shape';\n if (!clip(fact.title, 80)) return 'missing_title';\n return 'missing_body';\n}\n\n/** Why `validateTask` rejected `raw`. Only meaningful when `validateTask(raw)` returned null. */\nexport function taskRejectionReason(raw: unknown): 'invalid_shape' | 'missing_description' {\n const task = raw as { description?: unknown } | null | undefined;\n if (typeof task?.description !== 'string') return 'invalid_shape';\n return 'missing_description';\n}\n\nexport function normalizeSourceRef(value: string): string | null {\n if (typeof value !== 'string') return null;\n const cleaned = value.replace(/[^A-Za-z0-9._\\- ]/g, '').trim().slice(0, 255);\n return cleaned.length > 0 ? cleaned : null;\n}\n\nexport function normalizeSourceHash(value: unknown): string | null {\n if (typeof value !== 'string') return null;\n return /^[0-9a-f]{64}$/i.test(value) ? value.toLowerCase() : null;\n}\n\nexport function titleTokens(title: string): Set<string> {\n return new Set(title.toLowerCase().replace(/[^a-z0-9\\s]/g, '').split(/\\s+/).filter(t => t.length >= 3));\n}\n\nexport function jaccardScore(a: Set<string>, b: Set<string>): number {\n if (a.size === 0 && b.size === 0) return 0;\n const intersection = new Set([...a].filter(x => b.has(x)));\n const union = new Set([...a, ...b]);\n return intersection.size / union.size;\n}\n","import type { GroundingWriter, ResolvedGrounding } from './utils/grounding';\n\nexport const LIBRARIAN_SYSTEM_PROMPT = `You are a knowledge extraction agent. Your job is to analyze recent episodic events and extract stable facts and actionable tasks about the user or entity.\nReturn ONLY a valid JSON object matching this schema:\n{\n \"facts\": [{ \"title\": \"string (max 80 chars)\", \"body\": \"string (max 800 chars)\", \"tags\": [\"string\"], \"confidence\": \"certain|inferred|tentative\" }],\n \"tasks\": [{ \"description\": \"string\", \"priority\": \"number (0-10)\" }]\n}\nKeep facts concise. Do not return markdown, just raw JSON.`;\n\nexport const HEAL_SYSTEM_PROMPT = `You are a memory grooming agent. Your job is to review a full dump of facts and recent events to resolve contradictions, downgrade stale claims, and flag obsolete facts for deletion.\nReturn ONLY a valid JSON object matching this schema:\n{\n \"downgraded\": [\"string (fact IDs)\"],\n \"deleted\": [\"string (fact IDs)\"],\n \"newFacts\": [{ \"title\": \"string (max 80 chars)\", \"body\": \"string (max 800 chars)\", \"tags\": [\"string\"], \"confidence\": \"certain|inferred|tentative\" }]\n}\nDo not return markdown, just raw JSON.`;\n\nexport const INGEST_SYSTEM_PROMPT = `You are a document ingestion agent. Your job is to extract factual knowledge from the provided document chunk.\nReturn ONLY a valid JSON object matching this schema:\n{\n \"facts\": [{ \"title\": \"string (max 80 chars)\", \"body\": \"string (max 800 chars)\", \"tags\": [\"string\"], \"confidence\": \"certain|inferred|tentative\" }]\n}\nExtract verbatim factual content. JSON escaping rules: every literal \" character in the source must be escaped as \\\\\" inside any JSON string body, and every literal newline as \\\\n. Source prose containing quotes (e.g. a worked example with \"...\") must still be reproduced exactly — re-escape, do not omit. Do not return markdown, just raw JSON.`;\n\nexport const ONTOLOGY_BACKFILL_SYSTEM_PROMPT = `You are a knowledge classification agent. You will receive existing memory facts that currently have no ontology type. For each input fact { \"id\", \"title\", \"body\", \"tags\" }, assign the best matching okf_type from the ontology manifest and optionally propose edges to related facts by title.\nReturn ONLY a valid JSON object matching this schema:\n{\n \"classifications\": [\n { \"id\": \"string (input fact id, copied verbatim)\", \"okf_type\": \"string (manifest node type slug)\", \"edges\": [{ \"edge_type\": \"string\", \"target_title\": \"string\" }] }\n ]\n}\nIf no manifest type fits a fact, omit that fact from \"classifications\" entirely — do not guess.\nWhen echoing an existing fact's title verbatim into \"target_title\", preserve every JSON escape sequence (\\\\\", \\\\n, \\\\\\\\, \\\\/) exactly as it appeared in the input body — do not strip backslashes, do not add unescaped quotes. Do not return markdown, just raw JSON.`;\n\nconst GROUNDING_SOURCE: Record<GroundingWriter, { key: string; source: string }> = {\n ingest: { key: 'facts', source: 'the document chunk' },\n librarian: { key: 'facts', source: 'the \"summary\" text of the events' },\n heal: { key: 'newFacts', source: 'the \"summary\" text of the recent events or the \"body\" text of the document anchors' },\n};\n\n/** Evidence instruction appended to an in-scope writer's system prompt (spec §6.2). */\nexport function groundingEvidenceBlock(writer: GroundingWriter, cfg: ResolvedGrounding): string {\n const { key, source } = GROUNDING_SOURCE[writer];\n return `EVIDENCE REQUIREMENT: every object in \"${key}\" must also carry an \"evidence\" array of 1 to ${cfg.maxEvidence} quotes. Each quote must be an exact substring copied character-for-character from ${source} (the SOURCE section), at least ${cfg.minEvidenceChars} characters long. Do not paraphrase. Do not quote these instructions, the ontology manifest, or any existing fact. A fact whose quotes cannot be found in the SOURCE section is stored as an unreviewed draft.\n\"evidence\": [\"exact substring copied from the SOURCE section\"]`;\n}\n","/**\n * Shared constants for the heal pipeline.\n *\n * Both `PromptService.buildHealPrompt` (which applies the L0 anchor cap and\n * the L3 body truncation default) and `MaintenanceService.doRunHeal` (which\n * fetches tasks at the cap and looks up anchors with the overfetch sized off\n * it) read from this module. The spec (\"heal output-bounded convergence\n * ladder\") explicitly requires the values to match across the two callers —\n * if they drift, the L0 anchor slice and `_selectHealAnchors`'s overfetch\n * silently disagree with no test catching the gap.\n *\n * Lives in `utils/` rather than alongside `MaintenanceService` because\n * `PromptService` is constructed before `MaintenanceService` exists, and\n * importing from `MaintenanceService` would create a cycle at construction\n * time. A leaf constants module has no such risk.\n *\n * Heal-specific batch sizing, recheck cadence, and prompt char limits\n * (`HEAL_BATCH_SIZE`, `HEAL_RECHECK_MS`, `HEAL_MAX_PROMPT_CHARS`,\n * `HEAL_ANCHOR_SEARCH_OVERFETCH`) are not duplicated across files and stay\n * in `MaintenanceService.ts` — moving them here would expand this module's\n * surface without buying anything.\n */\n\n/** Cap on document anchors surfaced to the model at L0. */\nexport const HEAL_MAX_ANCHORS = 50;\n\n/** Per-candidate anchor ratio used at L0: `min(HEAL_MAX_ANCHORS, batch.length * HEAL_ANCHORS_PER_CANDIDATE)`. */\nexport const HEAL_ANCHORS_PER_CANDIDATE = 4;\n\n/**\n * Default body truncation cap applied at L3 only. A fact whose body is at or\n * below this cap passes through unchanged; a fact above it is sliced to this\n * length with a `...[truncated at N chars, original was M]` marker.\n */\nexport const HEAL_MAX_FACT_BODY_CHARS_L3 = 4_000;\n\n/**\n * Hard ceiling on the `allTasks` slice fed to the heal prompt at L0. Tasks\n * are entity-global (not batch-local), so this is a constant rather than a\n * function of batch length.\n */\nexport const HEAL_MAX_TASKS = 50;\n\n/**\n * Clip for a document anchor's body in the heal prompt. Bodies are shown only\n * when heal is a grounding writer (spec §6.2, rev 7). Host `upsertGraph` nodes\n * are anchors too and have no body limit, so the clip bounds the prompt.\n */\nexport const HEAL_ANCHOR_BODY_CHARS = 800;","import type { OkfVerifiedEntry } from '@equationalapplications/core-okf';\nimport type { GroundingConfig } from '../types';\nimport { MAX_EVIDENCE_QUOTES, safeSlice } from './pure';\n\nexport type GroundingWriter = 'ingest' | 'librarian' | 'heal';\n\nexport interface ResolvedGrounding {\n writers: ReadonlySet<GroundingWriter>;\n minEvidenceChars: number;\n maxEvidence: number;\n maxEvidenceChars: number;\n}\n\n/** Actor recorded in `okf_verified` for a fact that passed the check. `process:` keeps the trust tier at machine-confirmed. */\nexport const GROUNDING_VERIFIER = 'process:grounding-check';\n\nconst WRITERS: readonly GroundingWriter[] = ['ingest', 'librarian', 'heal'];\n\nfunction positiveInt(value: unknown, fallback: number): number {\n return typeof value === 'number' && Number.isFinite(value) && value >= 1 ? Math.floor(value) : fallback;\n}\n\n/** `null` means grounding is off: no prompt change, no checks, no status or trust writes (spec §6.5). */\nexport function resolveGrounding(config: GroundingConfig | undefined): ResolvedGrounding | null {\n if (!config || config.mode !== 'draft') return null;\n const writers: GroundingWriter[] = Array.isArray(config.writers)\n ? config.writers.filter((w): w is GroundingWriter => WRITERS.includes(w as GroundingWriter))\n : ['ingest'];\n return {\n writers: new Set(writers),\n minEvidenceChars: positiveInt(config.minEvidenceChars, 20),\n // Never ask for more quotes than checkGrounding accepts (MAX_EVIDENCE_QUOTES).\n maxEvidence: Math.min(MAX_EVIDENCE_QUOTES, positiveInt(config.maxEvidence, 3)),\n maxEvidenceChars: positiveInt(config.maxEvidenceChars, 300),\n };\n}\n\n/** Spec §6.4 step 1: NFKC, collapse every whitespace run to one space, trim. Case is preserved. */\nexport function normalizeForGrounding(text: string): string {\n return text.normalize('NFKC').replace(/\\s+/g, ' ').trim();\n}\n\n/**\n * Build the normalized corpus from the raw in-memory values the model was\n * shown (spec §6.3), one normalized string per part. Never pass serialized\n * prompt text: JSON escapes would cause false `quote_not_found`. Non-string\n * parts are ignored. Parts stay separate so a quote can only ground inside\n * a single source — joining them would let a quote stitched across the\n * boundary of two sources pass.\n */\nexport function buildGroundingCorpus(parts: readonly unknown[]): string[] {\n return parts.filter((p): p is string => typeof p === 'string').map(normalizeForGrounding);\n}\n\nexport type GroundingReason = 'no_evidence' | 'evidence_too_short' | 'quote_not_found' | 'too_many_quotes';\n\nexport type GroundingVerdict =\n | { status: 'grounded'; retained: string[] }\n | { status: 'missing'; reason: 'no_evidence' | 'evidence_too_short' }\n | { status: 'failed'; reason: 'quote_not_found' | 'too_many_quotes' };\n\n/**\n * Deterministic check (spec §6.2, §6.4). `evidence` is `validateFact`'s\n * normalized list; `normalizedCorpus` comes from {@link buildGroundingCorpus}.\n * A quote passes only inside a single corpus part; it cannot span two\n * sources. Every quote is checked before any retention cap applies.\n */\nexport function checkGrounding(\n evidence: readonly string[] | undefined,\n normalizedCorpus: readonly string[],\n cfg: ResolvedGrounding,\n): GroundingVerdict {\n const quotes = evidence ?? [];\n if (quotes.length > MAX_EVIDENCE_QUOTES) return { status: 'failed', reason: 'too_many_quotes' };\n if (quotes.length === 0) return { status: 'missing', reason: 'no_evidence' };\n const qualifying = quotes.map(normalizeForGrounding).filter((q) => q.length >= cfg.minEvidenceChars);\n if (qualifying.length === 0) return { status: 'missing', reason: 'evidence_too_short' };\n if (qualifying.some((q) => !normalizedCorpus.some((part) => part.includes(q)))) {\n return { status: 'failed', reason: 'quote_not_found' };\n }\n return {\n status: 'grounded',\n retained: qualifying.slice(0, cfg.maxEvidence).map((q) => safeSlice(q, 0, cfg.maxEvidenceChars)),\n };\n}\n\n/** Insert-time trust fields. Spread onto a new `WikiFact`; `EntryRepository.upsert` writes them on INSERT only. */\nexport interface GroundingTrust {\n lifecycle_status: 'stable' | 'draft';\n okf_verified?: OkfVerifiedEntry[];\n last_verified_at?: number;\n last_verified_by?: string;\n}\n\nexport interface GroundingOutcome {\n trust: GroundingTrust;\n /** Present exactly when the fact lands as a draft. */\n diagnostic?: { code: 'grounding_missing' | 'grounding_failed'; reason: GroundingReason };\n}\n\n/** Spec §6.5. */\nexport function groundingOutcome(verdict: GroundingVerdict, now: number): GroundingOutcome {\n if (verdict.status === 'grounded') {\n return {\n trust: {\n lifecycle_status: 'stable',\n okf_verified: [{ by: GROUNDING_VERIFIER, at: new Date(now).toISOString() }],\n last_verified_at: now,\n last_verified_by: GROUNDING_VERIFIER,\n },\n };\n }\n return {\n trust: { lifecycle_status: 'draft' },\n diagnostic: { code: verdict.status === 'missing' ? 'grounding_missing' : 'grounding_failed', reason: verdict.reason },\n };\n}\n","import {\n INGEST_SYSTEM_PROMPT,\n LIBRARIAN_SYSTEM_PROMPT,\n HEAL_SYSTEM_PROMPT,\n ONTOLOGY_BACKFILL_SYSTEM_PROMPT,\n groundingEvidenceBlock,\n} from '../prompts';\nimport type { DegradedRecord, PromptOverrides, OntologyPromptContext, WikiInstructions } from '../types';\nimport {\n HEAL_ANCHORS_PER_CANDIDATE,\n HEAL_ANCHOR_BODY_CHARS,\n HEAL_MAX_ANCHORS,\n HEAL_MAX_FACT_BODY_CHARS_L3,\n} from '../utils/healConstants';\nimport { safeSlice } from '../utils/pure';\nimport {\n buildGroundingCorpus,\n type GroundingWriter,\n type ResolvedGrounding,\n} from '../utils/grounding';\n\nexport class PromptService {\n constructor(\n private globalOverrides?: PromptOverrides,\n private grounding: ResolvedGrounding | null = null,\n ) {}\n\n /** The resolved grounding config when `writer` is in `grounding.writers`; otherwise null (spec §6.2). */\n groundingFor(writer: GroundingWriter): ResolvedGrounding | null {\n return this.grounding?.writers.has(writer) ? this.grounding : null;\n }\n\n /** Appended after any override and after ontology context, so it is always last. */\n private appendGrounding(systemPrompt: string, writer: GroundingWriter): string {\n const cfg = this.groundingFor(writer);\n return cfg ? `${systemPrompt}\\n\\n${groundingEvidenceBlock(writer, cfg)}` : systemPrompt;\n }\n\n private hydrate(template: string, variables: Record<string, unknown>): string {\n return template.replace(/\\{\\{\\s*(\\w+)\\s*\\}\\}/g, (_match, key) => {\n const value = variables[key];\n if (value === undefined) return _match;\n return typeof value === 'string' ? value : JSON.stringify(value, null, 2);\n });\n }\n\n private hasOntologyPlaceholders(template: string): boolean {\n return /\\{\\{\\s*ontology(?:Manifest|ModeInstructions)\\s*\\}\\}/.test(template);\n }\n\n private buildSystemPrompt(\n template: string,\n variables: Record<string, unknown>,\n ontologyContext: OntologyPromptContext | null | undefined,\n ): string {\n const shouldHydrate = Object.keys(variables).some((key) =>\n new RegExp(`\\\\{\\\\{\\\\s*${key}\\\\s*\\\\}\\\\}`).test(template),\n ) || (ontologyContext != null && this.hasOntologyPlaceholders(template));\n\n const hydrated = shouldHydrate\n ? this.hydrate(template, { ...variables, ...(ontologyContext ?? {}) })\n : template;\n\n return this.hasOntologyPlaceholders(template)\n ? (ontologyContext != null\n ? hydrated\n : hydrated.replace(/\\{\\{\\s*ontology(?:Manifest|ModeInstructions)\\s*\\}\\}/g, ''))\n : this.appendOntology(hydrated, ontologyContext);\n }\n\n private appendOntology(systemPrompt: string, ctx: OntologyPromptContext | null | undefined): string {\n if (!ctx) return systemPrompt;\n return `${systemPrompt}\\n\\n${ctx.ontologyModeInstructions}`;\n }\n\n buildIngestPrompt(\n documentChunk: string,\n runtimeOverride?: string,\n ontologyContext?: OntologyPromptContext | null,\n ): { systemPrompt: string; userPrompt: string } {\n const template = runtimeOverride ?? this.globalOverrides?.ingestSystemPrompt ?? INGEST_SYSTEM_PROMPT;\n const hasDocumentChunk = /\\{\\{\\s*documentChunk\\s*\\}\\}/.test(template);\n if (hasDocumentChunk || this.hasOntologyPlaceholders(template)) {\n return {\n systemPrompt: this.appendGrounding(this.buildSystemPrompt(template, { documentChunk }, ontologyContext), 'ingest'),\n userPrompt: hasDocumentChunk ? 'Please extract the facts.' : `Document Chunk:\\n${documentChunk}`,\n };\n }\n return {\n systemPrompt: this.appendGrounding(this.appendOntology(template, ontologyContext), 'ingest'),\n userPrompt: `Document Chunk:\\n${documentChunk}`,\n };\n }\n\n buildLibrarianPrompt(\n events: unknown[],\n currentFacts: unknown[],\n runtimeOverride?: string,\n ontologyContext?: OntologyPromptContext | null,\n ): { systemPrompt: string; userPrompt: string; groundingCorpus?: string[] } {\n const template = runtimeOverride ?? this.globalOverrides?.librarianSystemPrompt ?? LIBRARIAN_SYSTEM_PROMPT;\n const hasEvents = /\\{\\{\\s*events\\s*\\}\\}/.test(template);\n const hasCurrentFacts = /\\{\\{\\s*currentFacts\\s*\\}\\}/.test(template);\n // grounding: spec §6.3, event summaries only — the \"Current Facts\" shown\n // beside them are excluded so a new inference cannot be grounded by an\n // earlier one. A template that places {{currentFacts}} without {{events}}\n // never shows the events, so they are not in the corpus either.\n const eventsShown = hasEvents || !hasCurrentFacts;\n const corpusField = this.groundingFor('librarian')\n ? { groundingCorpus: buildGroundingCorpus(eventsShown ? events.map(summaryOf) : []) }\n : {};\n if (hasEvents || hasCurrentFacts || this.hasOntologyPlaceholders(template)) {\n return {\n systemPrompt: this.appendGrounding(this.buildSystemPrompt(template, { events, currentFacts }, ontologyContext), 'librarian'),\n userPrompt: (hasEvents || hasCurrentFacts)\n ? 'Please synthesize the context.'\n : `Events:\\n${JSON.stringify(events, null, 2)}\\n\\nCurrent Facts:\\n${JSON.stringify(currentFacts, null, 2)}`,\n ...corpusField,\n };\n }\n return {\n systemPrompt: this.appendGrounding(this.appendOntology(template, ontologyContext), 'librarian'),\n userPrompt: `Events:\\n${JSON.stringify(events, null, 2)}\\n\\nCurrent Facts:\\n${JSON.stringify(currentFacts, null, 2)}`,\n ...corpusField,\n };\n }\n\n /**\n * Heal-prompt level interpretation for the `attemptLevel` ladder.\n *\n * Caller contract: `documentAnchors` may be a slice sized for `batch.length`\n * or a larger set (e.g. a cache hit from `_selectHealAnchors`). This function\n * applies the prompt-side anchor cap `min(HEAL_MAX_ANCHORS=50, batch.length\n * * HEAL_ANCHORS_PER_CANDIDATE=4)` so the rendered prompt is bounded\n * regardless of caller input. `HEAL_MAX_ANCHORS` and\n * `HEAL_ANCHORS_PER_CANDIDATE` live here too — keeping the formula\n * co-located with its application avoids a \"MaintenanceService policy\"\n * import cycle (`PromptService` is constructed before `MaintenanceService`\n * exists) and makes the cap testable without a `MaintenanceService`\n * instance. Task 3 exports the same two constants from `MaintenanceService`\n * for caller-side overfetch sizing; the values must match.\n *\n * Level semantics:\n * - L0: allTasks + recentEvents + full candidate bodies; anchors re-capped\n * - L1: drop allTasks; recentEvents present; candidate bodies full\n * - L2: drop allTasks and recentEvents; candidate bodies full\n * - L3: drop allTasks and recentEvents; truncate each candidate body to\n * `bodyTruncationChars` and emit a `degraded` record per truncated fact\n */\n buildHealPrompt(\n healCandidates: unknown[],\n documentAnchors: unknown[],\n allTasks: unknown[],\n recentEvents: unknown[],\n runtimeOverride: string | undefined,\n attemptLevel: 0 | 1 | 2 | 3,\n bodyTruncationChars: number = HEAL_MAX_FACT_BODY_CHARS_L3,\n ): { prompts: { systemPrompt: string; userPrompt: string }; degraded: DegradedRecord[]; groundingCorpus?: string[] } {\n // L0: all context. L1: drop allTasks. L2: also drop recentEvents.\n const effectiveTasks = attemptLevel >= 1 ? [] : allTasks;\n const effectiveEvents = attemptLevel >= 2 ? [] : recentEvents;\n\n // L0 anchor cap: min(HEAL_MAX_ANCHORS, batch.length * HEAL_ANCHORS_PER_CANDIDATE).\n // The caller is responsible for sizing the documentAnchors slice; we re-cap\n // here in case the caller passed a superset (e.g. from _selectHealAnchors\n // cache). Constants live in utils/healConstants so PromptService and\n // MaintenanceService cannot drift apart (spec: \"values must match\").\n const maxAnchors = Math.max(1, Math.min(HEAL_MAX_ANCHORS, healCandidates.length * HEAL_ANCHORS_PER_CANDIDATE));\n const effectiveAnchors = documentAnchors.slice(0, maxAnchors);\n\n const template = runtimeOverride ?? this.globalOverrides?.healSystemPrompt ?? HEAL_SYSTEM_PROMPT;\n const hasRecentEvents = /\\{\\{\\s*recentEvents\\s*\\}\\}/.test(template);\n const hasDocumentAnchors = /\\{\\{\\s*documentAnchors\\s*\\}\\}/.test(template);\n const usesPlaceholders =\n /\\{\\{\\s*healCandidates\\s*\\}\\}/.test(template) ||\n hasDocumentAnchors ||\n /\\{\\{\\s*allTasks\\s*\\}\\}/.test(template) ||\n hasRecentEvents;\n\n // grounding: only when heal is a grounding writer do anchors show a\n // clipped body, and the corpus is built from exactly what this prompt\n // shows (spec §6.3, rev 7). A placeholder template shows a source only\n // when it places that source's placeholder. lifecycle_status decides\n // corpus membership but is never shown to the model.\n const healGrounding = this.groundingFor('heal');\n const promptAnchors = healGrounding ? effectiveAnchors.map(toGroundingAnchor) : effectiveAnchors;\n const eventsShown = !usesPlaceholders || hasRecentEvents;\n const anchorsShown = !usesPlaceholders || hasDocumentAnchors;\n const groundingCorpus = healGrounding\n ? buildGroundingCorpus([\n ...(eventsShown ? effectiveEvents.map(summaryOf) : []),\n ...(anchorsShown\n ? effectiveAnchors\n .map((a, i) => ({ status: (a as { lifecycle_status?: unknown } | null)?.lifecycle_status, shown: promptAnchors[i] }))\n .filter((x) => x.status !== 'draft')\n .map((x) => (x.shown as { body?: unknown } | null)?.body)\n : []),\n ])\n : null;\n\n // L3: truncate each candidate's body independently. A fact whose body\n // is already <= bodyTruncationChars passes through unchanged; the\n // caller sees that fact is absent from `degraded` and can treat the\n // result as if no truncation had occurred.\n const { shapedCandidates, degraded } = applyBodyTruncation(\n healCandidates,\n attemptLevel,\n bodyTruncationChars,\n );\n const corpusField = groundingCorpus !== null ? { groundingCorpus } : {}; // grounding\n\n if (usesPlaceholders) {\n return {\n prompts: {\n systemPrompt: this.appendGrounding(this.hydrate(template, {\n healCandidates: shapedCandidates,\n documentAnchors: promptAnchors,\n allTasks: effectiveTasks,\n recentEvents: effectiveEvents,\n }), 'heal'),\n userPrompt: 'Please heal the memory graph.',\n },\n degraded,\n ...corpusField,\n };\n }\n return {\n prompts: {\n systemPrompt: this.appendGrounding(template, 'heal'),\n userPrompt: `Heal Candidates:\\n${JSON.stringify(shapedCandidates, null, 2)}\\nDocument Anchors (DO NOT MODIFY OR DELETE):\\n${JSON.stringify(promptAnchors, null, 2)}\\nAll Tasks:\\n${JSON.stringify(effectiveTasks, null, 2)}\\nRecent Events:\\n${JSON.stringify(effectiveEvents, null, 2)}\\nThe following document anchors are provided for contradiction detection only. Do not include them in \\`downgraded\\`, \\`deleted\\`, or \\`newFacts\\`.`,\n },\n degraded,\n ...corpusField,\n };\n }\n\n buildOntologyBackfillPrompt(\n facts: unknown[],\n runtimeOverride?: string,\n ontologyContext?: OntologyPromptContext | null,\n ): { systemPrompt: string; userPrompt: string } {\n const template = runtimeOverride ?? this.globalOverrides?.ontologyBackfillSystemPrompt ?? ONTOLOGY_BACKFILL_SYSTEM_PROMPT;\n const hasFacts = /\\{\\{\\s*facts\\s*\\}\\}/.test(template);\n if (hasFacts || this.hasOntologyPlaceholders(template)) {\n return {\n systemPrompt: this.buildSystemPrompt(template, { facts }, ontologyContext),\n userPrompt: hasFacts ? 'Please classify the facts.' : `Facts:\\n${JSON.stringify(facts, null, 2)}`,\n };\n }\n return {\n systemPrompt: this.appendOntology(template, ontologyContext),\n userPrompt: `Facts:\\n${JSON.stringify(facts, null, 2)}`,\n };\n }\n\n /**\n * The system prompt each writer would send, without hydrating data (spec\n * §8.3). `buildSystemPrompt` with no variables hydrates only ontology\n * placeholders and leaves data placeholders verbatim; heal never receives\n * ontology context, matching `buildHealPrompt`.\n */\n buildInstructionTemplates(ontologyContext: OntologyPromptContext | null): WikiInstructions {\n const o = this.globalOverrides;\n return {\n ingest: this.appendGrounding(this.buildSystemPrompt(o?.ingestSystemPrompt ?? INGEST_SYSTEM_PROMPT, {}, ontologyContext), 'ingest'),\n librarian: this.appendGrounding(this.buildSystemPrompt(o?.librarianSystemPrompt ?? LIBRARIAN_SYSTEM_PROMPT, {}, ontologyContext), 'librarian'),\n heal: this.appendGrounding(o?.healSystemPrompt ?? HEAL_SYSTEM_PROMPT, 'heal'),\n ontologyBackfill: this.buildSystemPrompt(o?.ontologyBackfillSystemPrompt ?? ONTOLOGY_BACKFILL_SYSTEM_PROMPT, {}, ontologyContext),\n };\n }\n}\n\n/**\n * Truncate candidate bodies at L3 only. Each fact is sliced independently;\n * a fact whose body is at or below the cap passes through unchanged. The\n * trailing marker is what the post-reconcile log line references — an\n * operator scanning the log sees the truncation magnitude without\n * re-querying the fact.\n *\n * A candidate that needs truncation but lacks a string id passes through\n * untruncated: the upstream contract (`WikiFact.id` is a `TEXT PRIMARY KEY`)\n * guarantees string ids in practice, and truncating without an id would\n * emit a body the model can verdict under but with no DegradedRecord for\n * `MaintenanceService.doRunHeal` to reconcile — violating the\n * degraded ⊥ skipped invariant on id.\n */\nfunction applyBodyTruncation(\n candidates: unknown[],\n attemptLevel: 0 | 1 | 2 | 3,\n bodyTruncationChars: number,\n): { shapedCandidates: unknown[]; degraded: DegradedRecord[] } {\n if (attemptLevel < 3) {\n return { shapedCandidates: candidates, degraded: [] };\n }\n const shapedCandidates: unknown[] = [];\n const degraded: DegradedRecord[] = [];\n for (const c of candidates) {\n if (typeof c !== 'object' || c === null) {\n shapedCandidates.push(c);\n continue;\n }\n const fact = c as { id?: unknown; body?: unknown };\n const body = typeof fact.body === 'string' ? fact.body : '';\n if (body.length <= bodyTruncationChars) {\n shapedCandidates.push(c);\n continue;\n }\n // A candidate that needs L3 truncation must carry a string id so\n // doRunHeal can reconcile the truncation back to the source row\n // (`HealResult.degraded` is keyed by id, and degraded ⊥ skipped on id).\n // Without one the candidate passes through untruncated — the invariant\n // \"every truncated candidate has a DegradedRecord\" holds, and the\n // upstream contract (WikiFact.id is a TEXT PRIMARY KEY) means this\n // branch is defensive against future schema drift, not a happy path.\n if (typeof fact.id !== 'string') {\n shapedCandidates.push(c);\n continue;\n }\n const originalBodyChars = body.length;\n // `safeSlice` (utils/pure) keeps the boundary inside a UTF-16 surrogate\n // pair intact — a bare `String.prototype.slice` can land mid-codepoint and\n // emit a lone high surrogate that JSON.stringify turns into U+FFFD. The\n // same hazard is handled for `formatSkipError` log lines in\n // MaintenanceService. Bodies can be emoji-heavy. The returned prefix may\n // be one or two chars shorter than `bodyTruncationChars` when the cut\n // backs off the surrogate boundary, so `truncatedBodyChars` reads from\n // `prefix.length` rather than the requested limit.\n const prefix = safeSlice(body, 0, bodyTruncationChars);\n const truncatedBodyChars = prefix.length;\n const truncated = `${prefix}…[truncated at ${truncatedBodyChars} chars, original was ${originalBodyChars}]`;\n shapedCandidates.push({ ...fact, body: truncated });\n degraded.push({ id: fact.id, originalBodyChars, truncatedBodyChars });\n }\n return { shapedCandidates, degraded };\n}\n\n/** An event's `summary` — the only event field that enters a grounding corpus (spec §6.3). */\nfunction summaryOf(event: unknown): unknown {\n return (event as { summary?: unknown } | null)?.summary;\n}\n\n/** Prompt shape of a heal anchor when heal is a grounding writer: body clipped, lifecycle_status hidden. */\nfunction toGroundingAnchor(anchor: unknown): unknown {\n if (typeof anchor !== 'object' || anchor === null) return anchor;\n const a = anchor as { id?: unknown; title?: unknown; source_ref?: unknown; body?: unknown };\n return {\n id: a.id,\n title: a.title,\n source_ref: a.source_ref,\n body: typeof a.body === 'string' ? safeSlice(a.body, 0, HEAL_ANCHOR_BODY_CHARS) : '',\n };\n}\n","/**\n * Default maximum characters per chunk that `ingestDocument` uses when a\n * caller doesn't override `maxChunkLength` (directly or via\n * `WikiOptions.config.maxChunkLength`).\n */\nexport const DEFAULT_MAX_CHUNK_LENGTH = 12000;\n\n/**\n * Default/fallback character overlap between consecutive chunks.\n * `ingestDocument` uses this when a caller doesn't override `chunkOverlap`\n * (directly or via `WikiOptions.config.chunkOverlap`), and clamps the\n * effective overlap (including this default) to `maxChunkLength - 1` when\n * needed. The clamp is a no-op for the shipped defaults; it can also apply\n * when a custom `maxChunkLength` makes the resolved overlap too large.\n */\nexport const DEFAULT_CHUNK_OVERLAP = 400;\n","import type {\n WikiDiagnostic,\n WikiDiagnosticCode,\n WikiDiagnosticDetail,\n WikiDiagnosticOperation,\n WikiDiagnosticSeverity,\n WikiDiagnosticTrigger,\n WikiOptions,\n} from '../types';\nimport type { EdgeDrop } from './ontology';\n\n/** What a call site supplies; severity, message and timestamp are derived from `code`. */\nexport type WikiDiagnosticInput = Omit<WikiDiagnostic, 'severity' | 'message' | 'at'>;\n\ntype DiagnosticTarget = Pick<WikiOptions, 'onDiagnostic'>;\n\nconst SEVERITY: Record<WikiDiagnosticCode, WikiDiagnosticSeverity> = {\n ingest_chunk_failed: 'warn',\n fact_rejected: 'warn',\n task_rejected: 'warn',\n fact_deduplicated: 'info',\n edge_dropped: 'warn',\n embedding_failed: 'warn',\n hook_failed: 'warn',\n background_job_failed: 'error',\n heal_skipped: 'warn',\n grounding_missing: 'warn',\n grounding_failed: 'warn',\n classification_low_confidence: 'info',\n classification_invalid: 'warn',\n};\n\n// Fixed templates (REQ-DIAG-03): never interpolate content into these.\nconst MESSAGE: Record<WikiDiagnosticCode, string> = {\n ingest_chunk_failed: 'One or more document chunks failed to parse or generate.',\n fact_rejected: 'An extracted fact failed validation and was not written.',\n task_rejected: 'An extracted task failed validation and was not written.',\n fact_deduplicated: 'An extracted fact duplicated an existing fact and was not written.',\n edge_dropped: 'An extracted edge could not be resolved against the ontology and was not written.',\n embedding_failed: 'A fact could not be embedded.',\n hook_failed: 'A host hook threw or rejected.',\n background_job_failed: 'A background maintenance job failed.',\n heal_skipped: 'Heal skipped a candidate fact.',\n grounding_missing: 'A fact carried no qualifying evidence and was stored as a draft.',\n grounding_failed: 'A fact carried evidence not found in its source and was stored as a draft.',\n classification_low_confidence: 'A classifier answer was below the confidence threshold and was not applied.',\n classification_invalid: 'A classifier answer was invalid and was not applied.',\n};\n\nconst warnedNonFunction = new WeakSet<object>();\n\nfunction copyDetail(detail: WikiDiagnosticDetail): WikiDiagnosticDetail {\n const copy: WikiDiagnosticDetail = { ...detail };\n if (detail.chunkIndexes) copy.chunkIndexes = detail.chunkIndexes.slice();\n return copy;\n}\n\n/**\n * Deliver one diagnostic to the host hook. Never throws, never awaits, and\n * never writes to the console unless the hook itself misbehaves (REQ-DIAG-02).\n */\nexport function emitDiagnostic(options: DiagnosticTarget, input: WikiDiagnosticInput): void {\n const hook: unknown = options.onDiagnostic;\n if (hook === undefined || hook === null) return;\n if (typeof hook !== 'function') {\n if (!warnedNonFunction.has(options)) {\n warnedNonFunction.add(options);\n console.warn('[WikiMemory] onDiagnostic is not a function; diagnostics are disabled.');\n }\n return;\n }\n const diagnostic: WikiDiagnostic = {\n code: input.code,\n severity: SEVERITY[input.code],\n operation: input.operation,\n trigger: input.trigger,\n entityId: input.entityId,\n at: Date.now(),\n message: MESSAGE[input.code],\n ...(input.detail ? { detail: copyDetail(input.detail) } : {}),\n };\n try {\n const returned: unknown = (hook as (d: WikiDiagnostic) => unknown)(diagnostic);\n if (returned !== undefined) {\n // Promise.resolve never throws synchronously; a hostile thenable rejects instead.\n Promise.resolve(returned).catch((err: unknown) => {\n console.warn('[WikiMemory] onDiagnostic hook rejected:', err);\n });\n }\n } catch (err) {\n console.warn('[WikiMemory] onDiagnostic hook threw:', err);\n }\n}\n\n/**\n * Operation-scoped buffer (spec §4.2.4): push while the operation's\n * transaction is open, `flush` after it commits, `discard` (or simply drop the\n * buffer) when the operation throws.\n */\nexport class DiagnosticBuffer {\n private items: WikiDiagnosticInput[] = [];\n\n push(input: WikiDiagnosticInput): void {\n this.items.push(input);\n }\n\n get size(): number {\n return this.items.length;\n }\n\n flush(options: DiagnosticTarget): void {\n const pending = this.items;\n this.items = [];\n for (const input of pending) emitDiagnostic(options, input);\n }\n\n discard(): void {\n this.items = [];\n }\n}\n\n/** Map an `EdgeDrop` to an `edge_dropped` diagnostic input. Omits unknown locators instead of sending nulls. */\nexport function edgeDropDiagnostic(\n drop: EdgeDrop,\n ctx: {\n entityId: string;\n operation: WikiDiagnosticOperation;\n trigger: WikiDiagnosticTrigger;\n sourceRef?: string;\n factId?: string;\n },\n): WikiDiagnosticInput {\n const detail: WikiDiagnosticDetail = { reason: drop.reason };\n const factId = ctx.factId ?? drop.sourceId;\n if (factId) detail.factId = factId;\n if (drop.edgeType) detail.edgeType = drop.edgeType;\n if (drop.sourceNodeType) detail.sourceNodeType = drop.sourceNodeType;\n if (drop.targetNodeType) detail.targetNodeType = drop.targetNodeType;\n if (ctx.sourceRef) detail.sourceRef = ctx.sourceRef;\n return { code: 'edge_dropped', operation: ctx.operation, trigger: ctx.trigger, entityId: ctx.entityId, detail };\n}\n","import { chunkText, withConcurrency, validateFact, factRejectionReason, parseJsonResponse, normalizeSourceRef, normalizeSourceHash, safeErrorToString } from '../utils/pure';\nimport { normalizeTitleKey, typeSatisfies } from '../utils/ontology';\nimport { DiagnosticBuffer, emitDiagnostic, edgeDropDiagnostic } from '../utils/diagnostics';\nimport type { EdgeDrop } from '../utils/ontology';\nimport { generateId } from '../utils/ids';\nimport { WikiParseError, WikiIngestEmptyError, WikiDuplicateHashError, WikiTransactionError, WikiStrictOntologyViolation, WikiGraphNodeOwnershipConflict } from '../types';\nimport type { ChunkFailure, WikiOptions, ExtractedFact, ExtractedFactEdge, ExtractedFactWithOntology, WikiFact, OntologyUpdates, WikiEdge, IngestDocumentResult } from '../types';\nimport type { SQLiteAdapter } from '../types';\nimport { extractSqliteCode } from '../db/sqliteCodes';\nimport type { EntryRepository } from '../repositories/EntryRepository';\nimport type { SourceRefIndexRepository } from '../repositories/SourceRefIndexRepository';\nimport type { MetadataRepository } from '../repositories/MetadataRepository';\nimport type { EdgeRepository } from '../repositories/EdgeRepository';\nimport type { SearchService } from './SearchService';\nimport type { JobManager } from './JobManager';\nimport type { EmbeddingService } from './EmbeddingService';\nimport type { OntologyService, TitleIndexEntry } from './OntologyService';\nimport { PromptService } from './PromptService';\nimport { DEFAULT_MAX_CHUNK_LENGTH, DEFAULT_CHUNK_OVERLAP } from '../utils/chunkingDefaults';\nimport { resolveGrounding, buildGroundingCorpus, checkGrounding, groundingOutcome } from '../utils/grounding';\nimport type { GroundingTrust, GroundingVerdict } from '../utils/grounding';\n\ntype ChunkResult =\n | { status: 'ok'; facts: ExtractedFact[]; itemIndexes: number[]; rejected: Array<{ itemIndex: number; reason: ReturnType<typeof factRejectionReason> }>; verdicts: GroundingVerdict[]; ontology_updates?: OntologyUpdates }\n | { status: 'failed'; error: ChunkFailure };\n\n/** Shape returned by {@link IngestionService.ingestDocument} when no chunks\n * ran — used for both the `chunks.length === 0` early-return and the\n * `onDuplicateHash: 'skip'` early-return. `duplicateOf` is present as an own\n * key ONLY when the skip is owed to a duplicate-hash collision — hosts using\n * `'duplicateOf' in result` to detect that case must not see the key on the\n * empty-document path (matching the pre-widening contract). */\nfunction zeroChunkResult(duplicateOf?: string): IngestDocumentResult {\n const result: IngestDocumentResult = {\n truncated: false,\n chunks: 0,\n ingestedChunks: 0,\n failedChunks: 0,\n };\n if (duplicateOf !== undefined) result.duplicateOf = duplicateOf;\n return result;\n}\n\nexport class IngestionService {\n private promptService: PromptService;\n\n constructor(\n private db: SQLiteAdapter,\n private prefix: string,\n private options: WikiOptions,\n private entryRepo: EntryRepository,\n private sourceRefIndexRepo: SourceRefIndexRepository,\n private metadataRepo: MetadataRepository,\n private edgeRepo: EdgeRepository,\n private searchService: SearchService,\n private jobManager: JobManager,\n private embeddingService: EmbeddingService,\n promptService?: PromptService,\n private ontologyService?: OntologyService,\n ) {\n // Fallback for direct instantiation outside WikiMemory facade (e.g. isolated tests).\n this.promptService = promptService ?? new PromptService(this.options.config?.prompts, resolveGrounding(this.options.config?.grounding));\n }\n\n async ingestDocument(\n entityId: string,\n params: {\n sourceRef: string;\n sourceHash: string;\n documentChunk: string;\n maxChunkLength?: number;\n chunkOverlap?: number;\n chunkConcurrency?: number;\n promptOverride?: string;\n },\n opts?: { onDuplicateHash?: 'ingest' | 'skip' | 'throw' },\n ): Promise<IngestDocumentResult> {\n const sourceRef = normalizeSourceRef(params.sourceRef);\n if (!sourceRef) throw new Error('Invalid sourceRef');\n\n const sourceHash = normalizeSourceHash(params.sourceHash);\n if (!sourceHash) throw new Error('Invalid sourceHash (must be 64-char hex string)');\n\n const maxChunkLength = params.maxChunkLength ?? this.options.config?.maxChunkLength ?? DEFAULT_MAX_CHUNK_LENGTH;\n const rawOverlap = params.chunkOverlap ?? this.options.config?.chunkOverlap ?? DEFAULT_CHUNK_OVERLAP;\n const chunkOverlap = Math.min(\n Number.isFinite(rawOverlap) && rawOverlap >= 0 ? Math.floor(rawOverlap) : DEFAULT_CHUNK_OVERLAP,\n maxChunkLength - 1\n );\n\n const rawConcurrency = params.chunkConcurrency ?? this.options.config?.chunkConcurrency ?? 1;\n const chunkConcurrency = Number.isFinite(rawConcurrency) && rawConcurrency >= 1 ? Math.floor(rawConcurrency) : 1;\n\n if (typeof params.documentChunk !== 'string') {\n throw new Error(`documentChunk must be a string, received ${typeof params.documentChunk}`);\n }\n\n // Acquire the hash + sourceRef ingest locks BEFORE the duplicate pre-check\n // so concurrent same-hash callers serialize here. Two callers that both\n // observe no duplicate at the pre-check can otherwise both reach the\n // INSERT and trip the v9 UNIQUE constraint — see\n // docs/superpowers/specs/2026-08-07-dependabot-concurrency-release-hygiene-design.md §B.\n const releaseIngestLocks = await this.jobManager.acquireIngestLocks(entityId, sourceRef, sourceHash);\n\n try {\n // Duplicate-hash guard: runs AFTER acquireIngestLocks but BEFORE chunking\n // and any LLM call. With the per-hash lock held by the previous holder,\n // we are guaranteed to observe any committed write they made before\n // releasing. Early duplicate returns go through the `finally` block\n // below so both locks are released cleanly.\n const onDuplicateHash = opts?.onDuplicateHash ?? 'ingest';\n if (onDuplicateHash !== 'ingest') {\n // Source_ref_index is the source of truth for \"who currently holds\n // this hash\"; the pre-check queries it directly. At most one sourceRef\n // can hold a given hash, so the result is either null (no live ref)\n // or a single sourceRef (which cannot echo the incoming ref because\n // the source_ref_index row is the OTHER writer's).\n const canonical = await this.sourceRefIndexRepo.findActiveByEntityAndHash(entityId, sourceHash);\n if (canonical !== null && canonical !== sourceRef) {\n if (onDuplicateHash === 'throw') {\n throw new WikiDuplicateHashError({ canonical, sourceHash, entityId });\n }\n // 'skip'\n return zeroChunkResult(canonical);\n }\n }\n\n const { chunks, truncated } = chunkText(params.documentChunk, maxChunkLength, chunkOverlap);\n if (chunks.length === 0) return zeroChunkResult();\n\n // Hoist the ontology prompt context out of the per-chunk closure:\n // `buildPromptContext(entityId)` depends only on entityId and reads\n // the manifest ONCE; running it per chunk is N-1 wasted DB reads.\n // Hoisting also makes its DB-systemic nature structural — a fault\n // surfaces before any LLM tokens are spent, not buried under\n // `WikiIngestEmptyError` after the first LLM call. See spec §3.\n const ontologyContext = await this.ontologyService?.buildPromptContext(entityId) ?? null;\n const ingestGrounding = this.promptService.groundingFor('ingest');\n\n const chunkResults = await withConcurrency(\n chunks.map((chunk, chunkIndex) => async () => {\n // Prompt building is INTENTIONALLY outside the try — it's a\n // template-driven step whose failures (malformatted\n // `promptOverride`, configured-template regression) are systemic\n // and identical for every chunk. Surfacing as a raw throw means\n // the host sees the real cause on the first chunk instead of\n // after `chunks.length` LLM calls under a `WikiIngestEmptyError`.\n // See spec §3.\n const { systemPrompt, userPrompt } = this.promptService.buildIngestPrompt(\n chunk,\n params.promptOverride,\n ontologyContext,\n );\n try {\n const responseText = await this.options.llmProvider.generateText({ systemPrompt, userPrompt });\n const result = parseJsonResponse<{ facts: ExtractedFact[]; ontology_updates?: OntologyUpdates }>(responseText);\n const rawFacts: unknown[] = Array.isArray(result.facts) ? result.facts : [];\n const facts: ExtractedFact[] = [];\n const itemIndexes: number[] = [];\n const rejected: Array<{ itemIndex: number; reason: ReturnType<typeof factRejectionReason> }> = [];\n rawFacts.forEach((raw, itemIndex) => {\n const valid = validateFact(raw);\n if (valid) {\n facts.push(valid);\n itemIndexes.push(itemIndex);\n } else {\n rejected.push({ itemIndex, reason: factRejectionReason(raw) });\n }\n });\n // Spec §6.3: the ingest corpus is exactly the chunk the model was shown.\n const verdicts: GroundingVerdict[] = ingestGrounding\n ? (() => {\n const corpus = buildGroundingCorpus([chunk]);\n return facts.map((f) => checkGrounding(f.evidence, corpus, ingestGrounding));\n })()\n : [];\n\n return {\n status: 'ok' as const,\n facts,\n itemIndexes,\n rejected,\n verdicts,\n ontology_updates: result.ontology_updates,\n };\n } catch (e) {\n const failure: ChunkFailure = e instanceof WikiParseError\n ? {\n chunkIndex,\n sourceRef,\n source: 'parse',\n tier: e.tier,\n position: e.position,\n message: e.message,\n }\n : {\n chunkIndex,\n sourceRef,\n source: 'llm',\n // `safeErrorToString` is a non-throwing coercion: an LLM\n // provider may reject with a non-Error value, and even\n // `String(e)` itself can throw when `e.toString()` throws.\n // Letting such an exception escape this catch would cause\n // `withConcurrency` to reject, discarding every sibling\n // chunk's results — the exact failure mode this per-chunk\n // try/catch exists to prevent. Keeping the value in the\n // `ChunkFailure` preserves the typed diagnostic for\n // callers (see parseFailures) without unwinding the loop.\n position: null,\n message: safeErrorToString(e),\n };\n // Spec §2: log once per failure, NEVER include the raw response.\n // We deliberately omit `failure.message` here:\n // - For `source: 'parse'` the message is the parser's diagnostic\n // (safe) but in the interest of a single, narrow warn format we\n // surface only the tier (and position when known) on the log.\n // - For `source: 'llm'` the message is provider-controlled: an\n // LLM SDK commonly surfaces the raw response body, document\n // content, or a multi-megabyte HTTP error in `Error.message`.\n // Even a parser-diagnostic message that happens to share bytes\n // with a never-logged raw response would leak if we printed\n // it verbatim. The full message stays in `parseFailures` for\n // callers that want it; the warn line is intentionally narrow.\n const total = chunks.length;\n const tags: string[] = [];\n if (failure.tier) tags.push(`tier=${failure.tier}`);\n if (failure.position !== null) tags.push(`position=${failure.position}`);\n const tagsSuffix = tags.length > 0 ? `; ${tags.join(' ')}` : '';\n console.warn(\n `[WikiMemory] ingest chunk ${chunkIndex + 1}/${total} ${failure.source} failed (sourceRef=${sourceRef}${tagsSuffix})`,\n );\n return { status: 'failed' as const, error: failure };\n }\n }),\n chunkConcurrency\n );\n\n // Single pass: collect failures, dedup ok facts against the cross-chunk\n // `seen` set, and count `ingestedChunks` / `failedChunks` together.\n let ingestedChunks = 0;\n let failedChunks = 0;\n const failures: ChunkFailure[] = [];\n const seen = new Set<string>();\n const orderedChunkFacts: Array<{ facts: ExtractedFact[]; ontology_updates?: OntologyUpdates }> = [];\n // Keyed by fact object identity: the same objects flow through dedupe,\n // the full path and the partial path. Empty when grounding is off.\n const groundingLedger = new Map<ExtractedFact, { verdict: GroundingVerdict; chunkIndex: number; itemIndex: number }>();\n const diagBuffer = new DiagnosticBuffer();\n const diagBase = { entityId, operation: 'ingest' as const, trigger: 'call' as const };\n for (const [chunkIndex, slot] of chunkResults.entries()) {\n if (slot.status === 'failed') {\n failedChunks++;\n failures.push(slot.error);\n continue;\n }\n ingestedChunks++;\n for (const r of slot.rejected) {\n diagBuffer.push({ ...diagBase, code: 'fact_rejected', detail: { sourceRef, chunkIndex, itemIndex: r.itemIndex, reason: r.reason } });\n }\n const dedupedFacts: ExtractedFact[] = [];\n slot.facts.forEach((fact, k) => {\n const normalizedTitle = normalizeTitleKey(fact.title);\n if (!seen.has(normalizedTitle)) {\n seen.add(normalizedTitle);\n dedupedFacts.push(fact);\n if (ingestGrounding) groundingLedger.set(fact, { verdict: slot.verdicts[k], chunkIndex, itemIndex: slot.itemIndexes[k] });\n } else {\n diagBuffer.push({\n ...diagBase, code: 'fact_deduplicated',\n detail: { sourceRef, chunkIndex, itemIndex: slot.itemIndexes[k], reason: 'exact_title' },\n });\n }\n });\n orderedChunkFacts.push({ facts: dedupedFacts, ontology_updates: slot.ontology_updates });\n }\n\n for (const reason of ['parse', 'llm'] as const) {\n const ofReason = failures.filter((f) => f.source === reason);\n if (ofReason.length === 0) continue;\n diagBuffer.push({\n ...diagBase, code: 'ingest_chunk_failed',\n detail: {\n sourceRef, reason, count: ofReason.length,\n chunkIndexes: ofReason.map((f) => f.chunkIndex).sort((a, b) => a - b).slice(0, 20),\n },\n });\n }\n\n // Total failure: throw WikiIngestEmptyError before any persistence runs.\n // A silent zero-fact ingest is a worse regression than a typed throw.\n if (failedChunks === chunks.length) {\n throw new WikiIngestEmptyError({\n parseFailures: failures,\n sourceRef,\n chunks: chunks.length,\n });\n }\n\n const insertedFacts: Array<{ id: string; entity_id: string; title: string; body: string; tags: string }> = [];\n const deletedSourceFactIds: string[] = [];\n\n try {\n if (failedChunks === 0) {\n // Happy path — full upsertGraphCore supersession + ownership.\n const fullResult = await this.db.withTransactionAsync(async (tx) => {\n return await this.runFullUpsertGraph(entityId, sourceRef, sourceHash, orderedChunkFacts, tx, diagBuffer, groundingLedger);\n });\n deletedSourceFactIds.push(...fullResult.deletedSourceFactIds);\n insertedFacts.push(...fullResult.insertedFacts);\n } else {\n // Partial path — append dedup-only, NO supersession, NO ownership update.\n // See spec §4.2. `insertedFacts` carries the per-fact descriptors\n // the post-commit hook loop needs to fire `embedFact` after the\n // partial transaction commits — without this, partial-row facts\n // would never reach the embedding service and the vector ranker\n // would never be notified for them (despite them being live in\n // the entries table). See the copilot review note on\n // `embeddingService.embedFact` vs. the partial-path gate.\n const partialResult = await this.db.withTransactionAsync(async (tx) => {\n const flat: ExtractedFact[] = [];\n for (const slot of orderedChunkFacts) flat.push(...slot.facts);\n return await this.appendPartialFacts(entityId, sourceRef, flat, tx, diagBuffer, groundingLedger);\n });\n insertedFacts.push(...partialResult.insertedDescriptors);\n }\n } catch (err) {\n // A concurrent ingest for a DIFFERENT sourceRef beat us to the same\n // sourceHash between the pre-check above and this write — the\n // source_ref_index partial UNIQUE index (entity_id, source_hash)\n // rejected the upsert. Translate into the same duplicate-hash\n // outcome the pre-check would have produced, by mode. Any other\n // error re-throws unmodified. With the entries-level UNIQUE gone,\n // every UNIQUE violation inside this transaction originates from\n // source_ref_index, so the single check is sufficient.\n const sqliteCode = err instanceof WikiTransactionError\n ? err.sqliteErrorCode\n : extractSqliteCode(err);\n if (sqliteCode !== 'SQLITE_CONSTRAINT_UNIQUE') throw err;\n\n const canonical = await this.sourceRefIndexRepo.findActiveByEntityAndHash(entityId, sourceHash);\n // No other live ref holds this hash (e.g. a different constraint\n // fired, or the racing writer's row was itself rolled back) — the\n // UNIQUE violation isn't explained by a duplicate-hash race; surface\n // the original error rather than a misleading result.\n if (canonical === null) throw err;\n\n if (onDuplicateHash === 'throw' || onDuplicateHash === 'ingest') {\n throw new WikiDuplicateHashError({ canonical, sourceHash, entityId });\n }\n // 'skip'\n return zeroChunkResult(canonical);\n }\n\n // Post-commit (spec §4.2.4). The duplicate-hash `return zeroChunkResult(...)`\n // paths in the catch above leave without flushing: nothing was committed.\n diagBuffer.flush(this.options);\n\n await this.searchService.sync(entityId);\n\n // Post-commit hook loop. `notifyEmbeddingPersisted(entityId, factId, null)`\n // is the embedding-lifecycle retirement signal — only relevant on the\n // full path, which is the only path that calls `softDeleteBySource`.\n // `embedFact` runs for every newly-inserted fact on EITHER path: the\n // partial path appends live rows, and those rows must participate in\n // semantic retrieval just like full-path facts — otherwise a 6-of-7\n // partial commit would leave the embedded fields null until a later\n // full retry, and a vector ranker wouldn't be notified for them.\n // (The earlier gate `if (failedChunks === 0)` blocked both halves of\n // this block on the partial path and was the bug copilot flagged.)\n if (failedChunks === 0) {\n const uniqueDeletedSourceFactIds = Array.from(new Set(deletedSourceFactIds));\n for (const factId of uniqueDeletedSourceFactIds) {\n try {\n await this.embeddingService.notifyEmbeddingPersisted(entityId, factId, null);\n } catch (hookErr) {\n console.warn(`[WikiMemory] onEmbeddingPersisted hook failed during ingest for ${factId}:`, hookErr);\n emitDiagnostic(this.options, {\n entityId, operation: 'ingest', trigger: 'call', code: 'hook_failed',\n detail: { factId, reason: 'on_embedding_persisted' },\n });\n }\n }\n }\n\n for (const fact of insertedFacts) {\n await this.embeddingService.embedFact(fact, { operation: 'ingest', trigger: 'call' });\n }\n\n this.searchService.evictCache(entityId);\n\n const result: IngestDocumentResult = {\n truncated,\n chunks: chunks.length,\n ingestedChunks,\n failedChunks,\n };\n if (failedChunks > 0) result.parseFailures = failures;\n return result;\n\n } finally {\n releaseIngestLocks();\n }\n }\n\n /**\n * Reject the whole write when any incoming node ID is already owned by a\n * different entity. Runs entirely inside the supplied `tx`, through the\n * repository abstraction, and — being the first thing `upsertGraphCore`\n * does — before ontology resolution, which can itself persist a configured\n * seed manifest.\n *\n * The lookup has no deleted-row filter, so a soft-deleted foreign row keeps\n * its ID reserved. Only the lookup IDs are deduplicated; `params.nodes` and\n * the later write loops keep their ordering and counts.\n *\n * The error is deliberately contextless — see WikiGraphNodeOwnershipConflict.\n *\n * @param entityId - the entity the caller is writing on behalf of. Foreign\n * rows under a different entity trigger the rejection.\n * @param nodes - incoming node set; only the IDs are inspected, so callers\n * may pass the public `params.nodes` shape directly without slicing.\n * @param tx - the open transaction. Reuses the same handle every later\n * statement in `upsertGraphCore` runs against, so atomicity is enforced\n * by the host transaction's commit/rollback, not by this method.\n */\n private async assertGraphNodeOwnership(\n entityId: string,\n nodes: readonly { id: string }[],\n tx: SQLiteAdapter,\n ): Promise<void> {\n const ids = [...new Set(nodes.map(node => node.id))];\n const existing = await this.entryRepo.findExistingMetadataByIds(ids, tx);\n for (const row of existing) {\n if (row.entity_id !== entityId) {\n throw new WikiGraphNodeOwnershipConflict();\n }\n }\n }\n\n /**\n * Implements spec §2 data flow steps a–j with the host-facing\n * `{sourceRef, sourceHash, nodes, edges}` parameter shape. Shared between\n * `ingestDocument` (with `{ strict: false }` to preserve current behavior)\n * and `WikiMemory.upsertGraph` (which lets the persisted ontology mode\n * decide strictness).\n *\n * Runs ENTIRELY inside the supplied `tx`. Does not acquire locks, does not\n * open a nested transaction, does not perform post-commit work (search\n * sync, embedding, cache eviction). Those concerns remain in `ingestDocument`.\n *\n * The pre-flight validation (steps a–c) lives INSIDE this method per the\n * spec, so the public `WikiMemory.upsertGraph` can be a thin wrapper that\n * performs only the C2 probe before delegating.\n *\n * @returns Counts: nodesWritten (validated nodes persisted), edgesWritten\n * (manifest-valid edges persisted), superseded (prior facts soft-deleted\n * plus prior source-ref edges hard-deleted).\n *\n * Node-ownership pre-flight (spec §3, REQ-GRAPH-01): the first statement\n * is `assertGraphNodeOwnership(entityId, params.nodes, tx)`, which runs\n * before ontology resolution, seed-manifest persistence, and every other\n * write. A foreign-owned ID throws `WikiGraphNodeOwnershipConflict` with\n * no disclosed owner, node ID, or content; the caller's transaction\n * remains open and must be rolled back by the host. Soft-deleted foreign\n * rows keep their IDs reserved. Duplicate incoming IDs are deduplicated\n * only for the lookup; `params.nodes` and the write loops keep their\n * ordering and counts so success counts match the pre-change contract.\n */\n async upsertGraphCore(\n entityId: string,\n params: {\n sourceRef: string;\n sourceHash: string;\n nodes: readonly { id: string; type: string; title: string; body?: string; tags?: readonly string[]; confidence?: 'certain' | 'inferred' | 'tentative' }[];\n edges: readonly { type: string; sourceId: string; targetId: string; id?: string }[];\n },\n tx: SQLiteAdapter,\n opts?: {\n strict?: boolean;\n diag?: { buffer: DiagnosticBuffer; operation: 'ingest' | 'upsertGraph' };\n /** Insert-time trust by node id. Ingest-only (spec §6.5); the public upsertGraph never passes it, so host nodes are never grounded. */\n nodeTrust?: ReadonlyMap<string, GroundingTrust>;\n },\n ): Promise<{ nodesWritten: number; edgesWritten: number; superseded: number }> {\n // Node-ownership pre-flight FIRST — before ontology resolution and every\n // persistent mutation, so a rejected write leaves no seeded manifest\n // behind. Shared with ingestDocument's full path via runFullUpsertGraph;\n // that is intended. No bypass flag exists by design.\n await this.assertGraphNodeOwnership(entityId, params.nodes, tx);\n\n const now = Date.now();\n\n // (a) Resolve the effective ontology state through OntologyService rather\n // than reading metadataRepo.getManifest directly. OntologyService handles\n // the seedManifests contract (types.ts:65-66 — seeds are persisted on\n // first access when a tx is supplied, and cached otherwise) and the\n // ontologyConfig.mode fallback. Reading the repo directly here would\n // return null for an entity that has only a seedManifests entry, leaving\n // the strict mode silently unwritten and letting out-of-manifest data\n // through even when the host configured strict via the seed.\n const ontologyState = await this.ontologyService?.getEffectiveState(entityId, tx)\n ?? { mode: 'off' as const, manifest: { node_types: [], edge_types: [] } };\n let { mode, manifest } = ontologyState;\n // `opts.strict === false` overrides the persisted mode (used by\n // ingestDocument to preserve its pre-strict-mode silent-drop behavior).\n // `opts.strict === true` forces strict. `opts.strict === undefined`\n // follows the persisted mode.\n const strictEffective = opts?.strict === false\n ? false\n : opts?.strict === true || mode === 'strict';\n\n // (b) Pre-flight node validation — all-or-nothing under strict mode.\n // Build WikiFacts ready for upsert, with canonical okf_type.\n const wikiFacts: WikiFact[] = [];\n for (const node of params.nodes) {\n const factLike = { okf_type: node.type, edges: [] } as unknown as ExtractedFactWithOntology;\n const normalized = this.ontologyService?.validateAndNormalizeFact(factLike, manifest, {\n strict: strictEffective,\n entityId,\n }) ?? { okf_type: null, edges: [] };\n const wikiFact: WikiFact = {\n id: node.id,\n entity_id: entityId,\n title: node.title,\n body: node.body ?? '',\n // Public upsertGraph callers don't supply tags/confidence, so they\n // default to [] / 'certain' for deterministic AST-grade facts.\n // ingestDocument routes through this method for the LLM path and\n // forwards the LLM-supplied tags + confidence, preserving the prior\n // behavior (search filterability, heal-candidate selection, runReembed\n // embedding-text signal).\n tags: node.tags ? Array.from(node.tags) : [],\n confidence: node.confidence ?? 'certain',\n source_type: 'immutable_document',\n source_hash: params.sourceHash,\n source_ref: params.sourceRef,\n created_at: now,\n updated_at: now,\n last_accessed_at: null,\n access_count: 0,\n deleted_at: null,\n okf_type: normalized.okf_type,\n ...opts?.nodeTrust?.get(node.id),\n };\n wikiFacts.push(wikiFact);\n }\n\n // (c) Pre-flight edge validation, grouped by sourceId.\n // C3: dangling targetIds are stored verbatim. We only validate against\n // the manifest's (source_type, edge_type) lookup.\n const sourceIdToType = new Map<string, string | null>();\n for (const fact of wikiFacts) sourceIdToType.set(fact.id, fact.okf_type ?? null);\n\n // When the manifest is empty (no node_types AND no edge_types), the user\n // has expressed no constraints; edges pass through verbatim. This is\n // the documented \"no validation\" semantics — the host gets exactly the\n // edges it supplied, including dangling targetIds (C3).\n const hasConstraints = (manifest.node_types?.length ?? 0) > 0 || (manifest.edge_types?.length ?? 0) > 0;\n\n const validEdges: WikiEdge[] = [];\n for (const edge of params.edges) {\n if (!hasConstraints) {\n validEdges.push({\n id: edge.id ?? generateId(),\n entity_id: entityId,\n source_id: edge.sourceId,\n target_id: edge.targetId,\n edge_type: edge.type,\n created_at: now,\n });\n continue;\n }\n // Per spec step (c): \"for each source node `n` in `params.nodes`, validate\n // that node's outgoing edges\". Edges whose sourceId references a node\n // OUTSIDE this call's nodes (a prior sourceRef's node) cannot have their\n // source type resolved without a DB lookup, so they pass through verbatim\n // — same lenient treatment C3 gives dangling targetIds.\n if (!sourceIdToType.has(edge.sourceId)) {\n validEdges.push({\n id: edge.id ?? generateId(),\n entity_id: entityId,\n source_id: edge.sourceId,\n target_id: edge.targetId,\n edge_type: edge.type,\n created_at: now,\n });\n continue;\n }\n const sourceType = sourceIdToType.get(edge.sourceId);\n const candidates = (manifest.edge_types ?? []).filter(d =>\n d.type.toLowerCase() === edge.type.toLowerCase()\n && typeSatisfies(d.source_type, sourceType ?? '', manifest),\n );\n const match = candidates[0];\n if (!match) {\n if (strictEffective) throw new WikiStrictOntologyViolation(entityId, 'edge', edge.type);\n opts?.diag?.buffer.push({\n entityId, operation: opts.diag.operation, trigger: 'call', code: 'edge_dropped',\n detail: {\n reason: 'manifest_violation', factId: edge.sourceId, edgeType: edge.type,\n ...(sourceType ? { sourceNodeType: sourceType } : {}), sourceRef: params.sourceRef,\n },\n });\n continue;\n }\n validEdges.push({\n id: edge.id ?? generateId(),\n entity_id: entityId,\n source_id: edge.sourceId,\n target_id: edge.targetId,\n edge_type: match.type,\n created_at: now,\n });\n }\n\n // (d) Supersede prior facts for sourceRef.\n const deletedFactIds = await this.entryRepo.findIdsBySource(entityId, params.sourceRef, null, tx, false);\n await this.entryRepo.softDeleteBySource(entityId, tx, params.sourceRef, null);\n\n // (e) Supersede prior edges whose source is in deletedFactIds.\n const deletedEdgeCount = await this.edgeRepo.softDeleteBySourceFactIds(entityId, deletedFactIds, tx);\n\n // (f) Clear prior source_ref_index row for (entity, sourceRef).\n await this.sourceRefIndexRepo.softDeleteByEntityAndSourceRef(entityId, params.sourceRef, tx);\n\n // (g) Take ownership of (entity, hash).\n await this.sourceRefIndexRepo.upsert(entityId, params.sourceHash, params.sourceRef, tx);\n\n // (h) Write nodes (per-row outbox INSERT via entryRepo.upsert).\n for (const wikiFact of wikiFacts) {\n await this.entryRepo.upsert(wikiFact, tx);\n }\n\n // (i) Write edges (C3: dangling targets stored verbatim, no FK, no title-index resolution).\n // Count actual inserts via addIgnoreDuplicate; an edge whose id already\n // exists with the same (entity_id, source_id, target_id, edge_type) tuple\n // — e.g. a deterministic edge id reused across two distinct sourceRefs —\n // is silently skipped (returns false) and must NOT be counted as written.\n // Counting `validEdges.length` over-reports when caller-supplied edge ids\n // collide across sourceRefs, breaking the spec's C3 invariant that the\n // caller can rely on `edgesWritten` to assert \"did you drop anything?\".\n let edgesInsertedCount = 0;\n for (const edge of validEdges) {\n const inserted = await this.edgeRepo.addIgnoreDuplicate(edge, tx);\n if (inserted) edgesInsertedCount++;\n }\n\n // (j) Return counts.\n return {\n nodesWritten: wikiFacts.length,\n edgesWritten: edgesInsertedCount,\n superseded: deletedFactIds.length + deletedEdgeCount,\n };\n }\n\n /**\n * Full supersession + ownership path: identical to the pre-issue-#92 behavior\n * for the happy path. Called from the `failedChunks === 0` branch of\n * `ingestDocument`. Runs INSIDE the caller's tx.\n *\n * Returns `{ deletedSourceFactIds, insertedFacts }` so the caller can fire\n * post-commit hooks (embedding lifecycle) AFTER the transaction commits.\n * On the partial path the caller never invokes this method; the empty\n * arrays stay empty.\n */\n private async runFullUpsertGraph(\n entityId: string,\n sourceRef: string,\n sourceHash: string,\n orderedChunkFacts: Array<{ facts: ExtractedFact[]; ontology_updates?: OntologyUpdates }>,\n tx: SQLiteAdapter,\n diagBuffer: DiagnosticBuffer,\n groundingLedger: ReadonlyMap<ExtractedFact, { verdict: GroundingVerdict; chunkIndex: number; itemIndex: number }> = new Map(),\n ): Promise<{ deletedSourceFactIds: string[]; insertedFacts: Array<{ id: string; entity_id: string; title: string; body: string; tags: string }> }> {\n const deletedSourceFactIds: string[] = [];\n const insertedFacts: Array<{ id: string; entity_id: string; title: string; body: string; tags: string }> = [];\n const nodeTrust = new Map<string, GroundingTrust>();\n\n // Capture the IDs of facts about to be soft-deleted so we can fire\n // onEmbeddingPersisted hooks AFTER the transaction commits. The\n // capture happens BEFORE the softDelete, so even though\n // upsertGraphCore performs its own findIdsBySource for edge\n // supersession, the IDs here are the canonical \"what we retired\"\n // set for the embedding lifecycle.\n deletedSourceFactIds.push(...(await this.entryRepo.findIdsBySource(entityId, sourceRef, null, tx, false)));\n\n // Build title index from PRIOR facts EXCLUDING the current sourceRef.\n // Facts from this sourceRef are about to be superseded by\n // upsertGraphCore step (d); seeding them here would let resolveEdges\n // target a soon-to-be-retired fact and leave the new edge pointing\n // at a soft-deleted record (the new edge's source is fresh, so step\n // (e) only retires edges whose SOURCE is in the deleted-fact set).\n // The sourceRef exclusion is applied in SQL (via\n // findRecentByEntityId's excludeSourceRef param) so the 500-row\n // LIMIT applies to usable rows only — a re-ingest where the current\n // sourceRef owns most recent facts otherwise leaves the index empty\n // after the post-query filter, silently losing cross-sourceRef edges\n // that a first ingest would have resolved.\n const titleIndex = new Map<string, TitleIndexEntry>();\n const existingFacts = await this.entryRepo.findRecentByEntityId(entityId, 500, tx, sourceRef);\n for (const existing of existingFacts) {\n titleIndex.set(normalizeTitleKey(existing.title), {\n id: existing.id,\n okf_type: existing.okf_type ?? null,\n });\n }\n\n let ontologyState = await this.ontologyService?.getEffectiveState(entityId, tx)\n ?? { mode: 'off' as const, manifest: { node_types: [], edge_types: [] } };\n let { mode, manifest } = ontologyState;\n\n // Two-pass conversion of LLM extraction into host-facing shape.\n // Pass 1 (below) populates hostNodes and stages raw edge requests\n // for every replacement fact — facts from this ingest enter the\n // titleIndex as they're added, so forward references resolve in\n // pass 2 against the FINALIZED index. Pass 2 then resolves each\n // staged request into concrete hostEdges. upsertGraphCore owns the\n // persistence step.\n const hostNodes: { id: string; type: string; title: string; body: string; tags?: readonly string[]; confidence?: 'certain' | 'inferred' | 'tentative' }[] = [];\n const rawEdgeRequests: { sourceId: string; sourceType: string | null; edges: ExtractedFactEdge[] }[] = [];\n const now = Date.now();\n\n for (const { facts, ontology_updates } of orderedChunkFacts) {\n if (mode === 'emergent' && ontology_updates && this.ontologyService) {\n manifest = await this.ontologyService.mergeEmergentUpdates(entityId, ontology_updates, tx);\n ontologyState = await this.ontologyService.getEffectiveState(entityId, tx);\n mode = ontologyState.mode;\n }\n\n for (const fact of facts) {\n const ontologyFact = fact as ExtractedFactWithOntology;\n const id = generateId('fact_');\n const validationDrops: EdgeDrop[] = [];\n const normalized = this.ontologyService?.validateAndNormalizeFact(ontologyFact, manifest, { strict: false, drops: validationDrops })\n ?? { okf_type: null, edges: [] };\n for (const drop of validationDrops) {\n diagBuffer.push(edgeDropDiagnostic(drop, { entityId, operation: 'ingest', trigger: 'call', sourceRef, factId: id }));\n }\n\n hostNodes.push({\n id,\n type: ontologyFact.okf_type ?? '',\n title: fact.title,\n body: fact.body,\n // Forward the LLM-extracted tags/confidence through the\n // extracted-shape upsertGraphCore path so the entries row\n // stores them (search filterability, heal-candidate\n // selection, runReembed embedding-text signal). The public\n // WikiMemory.upsertGraph API doesn't accept tags/confidence\n // — host-supplied deterministic nodes default to [] and\n // 'certain' as documented.\n tags: fact.tags,\n confidence: fact.confidence,\n });\n const grounding = groundingLedger.get(fact);\n if (grounding) {\n const outcome = groundingOutcome(grounding.verdict, now);\n nodeTrust.set(id, outcome.trust);\n if (outcome.diagnostic) {\n diagBuffer.push({\n entityId, operation: 'ingest', trigger: 'call', code: outcome.diagnostic.code,\n detail: { factId: id, sourceRef, chunkIndex: grounding.chunkIndex, itemIndex: grounding.itemIndex, reason: outcome.diagnostic.reason },\n });\n }\n }\n insertedFacts.push({ id, entity_id: entityId, title: fact.title, body: fact.body, tags: JSON.stringify(fact.tags) });\n\n titleIndex.set(normalizeTitleKey(fact.title), { id, okf_type: normalized.okf_type });\n\n if (normalized.edges.length > 0) {\n rawEdgeRequests.push({ sourceId: id, sourceType: normalized.okf_type, edges: normalized.edges });\n }\n }\n }\n\n // Pass 2: resolve every staged edge against the finalized title\n // index. By this point the index contains both surviving prior\n // facts (excluding this sourceRef) AND every replacement fact from\n // this ingest, so forward references resolve correctly and no\n // resolved edge points at a fact that's about to be soft-deleted.\n const hostEdges: { type: string; sourceId: string; targetId: string }[] = [];\n for (const req of rawEdgeRequests) {\n const resolveDrops: EdgeDrop[] = [];\n const resolved = this.ontologyService?.resolveEdges(\n entityId, req.sourceId, req.sourceType, req.edges, manifest, titleIndex, now, resolveDrops,\n ) ?? [];\n for (const drop of resolveDrops) {\n diagBuffer.push(edgeDropDiagnostic(drop, { entityId, operation: 'ingest', trigger: 'call', sourceRef }));\n }\n for (const e of resolved) {\n hostEdges.push({ type: e.edge_type, sourceId: e.source_id, targetId: e.target_id });\n }\n }\n\n await this.upsertGraphCore(\n entityId,\n { sourceRef, sourceHash, nodes: hostNodes, edges: hostEdges },\n tx,\n { strict: false, diag: { buffer: diagBuffer, operation: 'ingest' }, ...(nodeTrust.size > 0 ? { nodeTrust } : {}) },\n );\n\n return { deletedSourceFactIds, insertedFacts };\n }\n\n /**\n * Partial-commit path for `ingestDocument`. Inserts ONLY facts whose\n * normalized title is not already in the live set for this (entityId,\n * sourceRef). Does NOT call `entryRepo.softDeleteBySource` (no\n * supersession) and does NOT call `sourceRefIndexRepo.upsert` (no\n * ownership). Edges are NOT resolved on this path (no ontology-context\n * build, no `resolveEdges`, no `mergeEmergentUpdates`). Stale edges from\n * prior attempts are recovered on the next full run's supersession.\n *\n * Source-hash is stored as NULL on partial rows. `findLatestSourceHash`\n * reads from the most recently updated live row for the sourceRef, so\n * storing the incoming hash here would cause `hasChanged` to return\n * `false` on a same-hash retry — the failed chunks would never get a\n * second chance. With NULL, a retry sees `storedHash === null`, `hasChanged`\n * returns `true`, and the partial commit's sibling rows remain live\n * (deduped, not superseded) for the next attempt to extend.\n *\n * Runs INSIDE the caller's `tx`. Does not open a nested transaction.\n * Returns `{ inserted, skippedDuplicate }` for observability.\n */\n private async appendPartialFacts(\n entityId: string,\n sourceRef: string,\n dedupedFacts: ExtractedFact[],\n tx: SQLiteAdapter,\n diagBuffer: DiagnosticBuffer,\n groundingLedger: ReadonlyMap<ExtractedFact, { verdict: GroundingVerdict; chunkIndex: number; itemIndex: number }> = new Map(),\n ): Promise<{\n inserted: number;\n skippedDuplicate: number;\n /** Descriptors for the rows this call actually inserted, in the same\n * shape `runFullUpsertGraph` returns — the post-commit hook loop\n * passes these to `embedFact`. Without them, partial-path inserts\n * would skip the embedding service entirely. */\n insertedDescriptors: Array<{ id: string; entity_id: string; title: string; body: string; tags: string }>;\n }> {\n // Partial rows are intentionally stored with `source_hash: null` so\n // `hasChanged` keeps returning true on every retry of the same hash —\n // the failed chunks get a second chance. The full path stamps the actual\n // hash via `runFullUpsertGraph`; this helper deliberately does not.\n // Load the live (sourceRef, *) rows so we can dedup by title against prior\n // partial attempts AND prior full attempts. includeDeleted=false matches\n // the pre-supersession dedup semantics of the full path. Per spec §4.2:\n // `findIdsBySource` returns the ids (already scoped to `entityId` and\n // excluding deleted rows); `findByIds` resolves titles — no entity filter\n // needed because the ids carry that scope already.\n const liveIds = await this.entryRepo.findIdsBySource(entityId, sourceRef, null, tx, false);\n const liveFacts = liveIds.length === 0\n ? []\n : await this.entryRepo.findByIds(liveIds, undefined, tx);\n const liveTitles = new Set(liveFacts.map((f) => normalizeTitleKey(f.title)));\n\n let inserted = 0;\n let skippedDuplicate = 0;\n const now = Date.now();\n const insertedDescriptors: Array<{ id: string; entity_id: string; title: string; body: string; tags: string }> = [];\n for (const fact of dedupedFacts) {\n const normalizedTitle = normalizeTitleKey(fact.title);\n if (liveTitles.has(normalizedTitle)) {\n diagBuffer.push({\n entityId, operation: 'ingest', trigger: 'call', code: 'fact_deduplicated',\n detail: { sourceRef, reason: 'exact_title' },\n });\n skippedDuplicate++;\n continue;\n }\n liveTitles.add(normalizedTitle);\n\n const id = generateId('fact_');\n const grounding = groundingLedger.get(fact);\n const outcome = grounding ? groundingOutcome(grounding.verdict, now) : null;\n if (grounding && outcome?.diagnostic) {\n diagBuffer.push({\n entityId, operation: 'ingest', trigger: 'call', code: outcome.diagnostic.code,\n detail: { factId: id, sourceRef, chunkIndex: grounding.chunkIndex, itemIndex: grounding.itemIndex, reason: outcome.diagnostic.reason },\n });\n }\n const wikiFact: WikiFact = {\n id,\n entity_id: entityId,\n title: fact.title,\n body: fact.body,\n tags: fact.tags,\n confidence: fact.confidence,\n source_type: 'immutable_document',\n // source_hash: null on partial rows — see method docstring. The\n // full path stamps the actual hash; partial rows stay hash-less so\n // `hasChanged` keeps returning true for retries.\n source_hash: null,\n source_ref: sourceRef,\n created_at: now,\n updated_at: now,\n last_accessed_at: null,\n access_count: 0,\n deleted_at: null,\n okf_type: null,\n ...outcome?.trust,\n };\n await this.entryRepo.upsert(wikiFact, tx);\n // Mirror the shape `runFullUpsertGraph` returns so the caller's\n // post-commit `embedFact` loop is path-agnostic.\n insertedDescriptors.push({\n id,\n entity_id: entityId,\n title: fact.title,\n body: fact.body,\n tags: JSON.stringify(fact.tags),\n });\n inserted++;\n }\n return { inserted, skippedDuplicate, insertedDescriptors };\n }\n}\n","import type { ClassifierAnswer, ClassifierQuestion } from '../types';\n\nexport type ClassifierRejection =\n | 'malformed'\n | 'missing_answer'\n | 'kind_mismatch'\n | 'choice_not_offered'\n | 'score_out_of_range'\n | 'invalid_probability';\n\ntype Checked = { ok: true; answer: ClassifierAnswer } | { ok: false; reason: ClassifierRejection };\n\nconst isUnit = (v: unknown): v is number => typeof v === 'number' && Number.isFinite(v) && v >= 0 && v <= 1;\n\n/**\n * Validate one answer from an untrusted classifier response (spec REQ-CLASS-02).\n * Never throws: hostile objects (throwing getters, Proxies) yield `malformed`.\n * Returns a fresh plain object, never the provider's own reference.\n */\nexport function validateClassifierAnswer(response: unknown, key: string, question: ClassifierQuestion): Checked {\n try {\n if (response === null || typeof response !== 'object') return { ok: false, reason: 'malformed' };\n const answers = (response as { answers?: unknown }).answers;\n if (answers === null || typeof answers !== 'object') return { ok: false, reason: 'missing_answer' };\n if (!Object.prototype.hasOwnProperty.call(answers, key)) return { ok: false, reason: 'missing_answer' };\n const raw = (answers as Record<string, unknown>)[key];\n if (raw === null || typeof raw !== 'object') return { ok: false, reason: 'missing_answer' };\n const a = raw as Record<string, unknown>;\n if (a.kind !== question.kind) return { ok: false, reason: 'kind_mismatch' };\n\n if (question.kind === 'choice') {\n if (typeof a.choice !== 'string' || !question.options.includes(a.choice)) return { ok: false, reason: 'choice_not_offered' };\n if (!isUnit(a.confidence)) return { ok: false, reason: 'invalid_probability' };\n const probs = a.probabilities;\n if (probs === null || typeof probs !== 'object' || Array.isArray(probs)) return { ok: false, reason: 'invalid_probability' };\n const probabilities: Record<string, number> = {};\n for (const [k, v] of Object.entries(probs as Record<string, unknown>)) {\n if (!isUnit(v)) return { ok: false, reason: 'invalid_probability' };\n probabilities[k] = v;\n }\n return { ok: true, answer: { kind: 'choice', choice: a.choice, confidence: a.confidence, probabilities } };\n }\n\n if (question.kind === 'binary') {\n if (!isUnit(a.probability)) return { ok: false, reason: 'invalid_probability' };\n return { ok: true, answer: { kind: 'binary', probability: a.probability } };\n }\n\n const maxScore = question.levels.length - 1;\n if (typeof a.score !== 'number' || !Number.isFinite(a.score) || a.score < 0 || a.score > maxScore) {\n return { ok: false, reason: 'score_out_of_range' };\n }\n if (!isUnit(a.confidence)) return { ok: false, reason: 'invalid_probability' };\n if (!Array.isArray(a.probabilities) || !a.probabilities.every(isUnit)) return { ok: false, reason: 'invalid_probability' };\n return { ok: true, answer: { kind: 'score', score: a.score, confidence: a.confidence, probabilities: a.probabilities.slice() } };\n } catch {\n return { ok: false, reason: 'malformed' };\n }\n}\n\n/** The classifier `state` for a fact: title, body, and tags when present. */\nexport function classifierStateForFact(fact: { title: string; body: string; tags: string[] }): string {\n const parts = [fact.title, fact.body];\n if (Array.isArray(fact.tags) && fact.tags.length > 0) parts.push(`Tags: ${fact.tags.join(', ')}`);\n return parts.join('\\n\\n');\n}\n","/**\n * Abstract base for all repositories.\n * Provides db accessor + prefix-aware helpers.\n */\nexport abstract class BaseRepository {\n protected db: import('../types').SQLiteAdapter;\n protected prefix: string;\n\n constructor(db: import('../types').SQLiteAdapter, prefix: string) {\n this.db = db;\n this.prefix = prefix;\n }\n\n /**\n * Return the DB executor for a given transaction handle.\n * If tx is provided, use it; otherwise fall back to this.db.\n */\n protected getExecutor(tx?: import('../types').SQLiteAdapter): import('../types').SQLiteAdapter {\n return tx ?? this.db;\n }\n}\n","import { BaseRepository } from './BaseRepository';\nimport type { SQLiteAdapter, OntologyManifest, OntologyMode, OntologyUpdates } from '../types';\nimport { emptyManifest, mergeOntologyUpdates, validateManifest } from '../utils/ontology';\n\n/** Meta-table key for an entity's OKF summary prose (profile v1 round-trip). */\nexport function entitySummaryMetaKey(entityId: string): string {\n return `entity_summary:${entityId}`;\n}\n\nexport class MetadataRepository extends BaseRepository {\n // CHECKPOINTS TABLE METHODS\n\n async getCheckpoint(entityId: string, tx: SQLiteAdapter): Promise<{ memory?: number; heal?: number }> {\n const executor = this.getExecutor(tx);\n const row = await executor.getFirstAsync<{\n memory_checkpoint: number | null;\n heal_checkpoint: number | null;\n }>(\n `SELECT memory_checkpoint, heal_checkpoint FROM ${this.prefix}checkpoints WHERE entity_id = ?`,\n [entityId],\n );\n if (!row) return {};\n return {\n memory: row.memory_checkpoint ?? undefined,\n heal: row.heal_checkpoint ?? undefined,\n };\n }\n\n async updateCheckpoint(\n entityId: string,\n updates: { memory?: number; heal?: number },\n tx: SQLiteAdapter,\n ): Promise<void> {\n const fields: string[] = [];\n const values: number[] = [];\n\n if (updates.memory !== undefined) {\n fields.push('memory_checkpoint = ?');\n values.push(updates.memory);\n }\n if (updates.heal !== undefined) {\n fields.push('heal_checkpoint = ?');\n values.push(updates.heal);\n }\n if (fields.length === 0) return;\n\n const executor = this.getExecutor(tx);\n await executor.runAsync(\n `INSERT INTO ${this.prefix}checkpoints (entity_id, memory_checkpoint, heal_checkpoint)\n VALUES (?, ?, ?)\n ON CONFLICT(entity_id) DO UPDATE SET ${fields.join(', ')}`,\n [entityId, updates.memory ?? 0, updates.heal ?? 0, ...values],\n );\n }\n\n async deleteCheckpoint(entityId: string, tx: SQLiteAdapter): Promise<void> {\n const executor = this.getExecutor(tx);\n await executor.runAsync(\n `DELETE FROM ${this.prefix}checkpoints WHERE entity_id = ?`,\n [entityId],\n );\n }\n\n // META TABLE METHODS\n\n async getMeta(key: string, tx?: SQLiteAdapter): Promise<string | null> {\n const executor = this.getExecutor(tx);\n const row = await executor.getFirstAsync<{ value: string }>(\n `SELECT value FROM ${this.prefix}meta WHERE key = ?`,\n [key],\n );\n return row ? row.value : null;\n }\n\n async setMeta(key: string, value: string, tx: SQLiteAdapter): Promise<void> {\n const executor = this.getExecutor(tx);\n await executor.runAsync(\n `INSERT INTO ${this.prefix}meta (key, value) VALUES (?, ?)\n ON CONFLICT(key) DO UPDATE SET value = excluded.value`,\n [key, value],\n );\n }\n\n async deleteMeta(key: string, tx?: SQLiteAdapter): Promise<void> {\n const executor = this.getExecutor(tx);\n await executor.runAsync(\n `DELETE FROM ${this.prefix}meta WHERE key = ?`,\n [key],\n );\n }\n\n async clearDimensionMismatch(tx: SQLiteAdapter): Promise<void> {\n const executor = this.getExecutor(tx);\n await executor.runAsync(\n `DELETE FROM ${this.prefix}meta WHERE key = 'embedding_dimension_mismatch'`,\n );\n }\n\n async tableExists(tableName: string, tx?: SQLiteAdapter): Promise<boolean> {\n const executor = this.getExecutor(tx);\n const row = await executor.getFirstAsync<{ name: string }>(\n `SELECT name FROM sqlite_master WHERE type='table' AND name=?`,\n [tableName],\n );\n return row != null;\n }\n\n async getTableDdl(tableName: string, tx?: SQLiteAdapter): Promise<string | null> {\n const executor = this.getExecutor(tx);\n const row = await executor.getFirstAsync<{ sql: string | null }>(\n `SELECT sql FROM sqlite_master WHERE type='table' AND name=?`,\n [tableName],\n );\n return row?.sql ?? null;\n }\n\n async vacuum(): Promise<void> {\n await this.db.execAsync(`PRAGMA wal_checkpoint(TRUNCATE)`);\n await this.db.execAsync(`VACUUM`);\n }\n\n /**\n * Returns the set of distinct `entity_id` values across entries/tasks/events.\n *\n * Deliberately widened from a prior `WHERE deleted_at IS NULL` form: the\n * returned set intentionally includes entities whose only rows are\n * soft-deleted, so the host's maintenance sweep can visit such\n * \"decommissioned-scope\" namespaces and reap the soft-deleted rows. Sorting\n * is `entity_id COLLATE BINARY` for stable, locale-independent ordering.\n */\n async getDistinctEntityIds(tx?: SQLiteAdapter): Promise<string[]> {\n const executor = this.getExecutor(tx);\n const rows = await executor.getAllAsync<{ entity_id: string }>(\n `SELECT DISTINCT entity_id FROM (\n SELECT entity_id FROM ${this.prefix}entries\n UNION\n SELECT entity_id FROM ${this.prefix}tasks\n UNION\n SELECT entity_id FROM ${this.prefix}events\n ) ORDER BY entity_id COLLATE BINARY`,\n );\n return rows.map(r => r.entity_id);\n }\n\n async getManifest(entityId: string, tx?: SQLiteAdapter): Promise<{\n mode: OntologyMode;\n manifest: OntologyManifest;\n } | null> {\n const executor = this.getExecutor(tx);\n const row = await executor.getFirstAsync<{\n mode: string;\n manifest_json: string;\n }>(`SELECT mode, manifest_json FROM ${this.prefix}entity_manifests WHERE entity_id = ?`, [entityId]);\n if (!row) return null;\n if (row.mode !== 'off' && row.mode !== 'strict' && row.mode !== 'emergent') {\n throw new Error(`Invalid ontology mode for entity ${entityId}: ${JSON.stringify(row.mode)}`);\n }\n let manifest: OntologyManifest;\n try {\n manifest = JSON.parse(row.manifest_json) as OntologyManifest;\n } catch (error) {\n throw new Error(`Invalid manifest_json for entity ${entityId}: ${(error as Error).message}`);\n }\n validateManifest(manifest);\n return {\n mode: row.mode,\n manifest,\n };\n }\n\n /**\n * Write an entity's manifest.\n *\n * `opts.ifAbsent` selects the conflict behaviour:\n * - omitted / `false` — upsert. An existing row is replaced.\n * - `true` — create-if-absent. An existing row is left exactly as it is.\n *\n * Returns whether this call actually wrote a row. Under `ifAbsent` a `false`\n * result means another writer got there first; the check and the write are one\n * statement, so there is no window between them.\n */\n async setManifest(\n entityId: string,\n data: { mode: OntologyMode; manifest: OntologyManifest },\n tx: SQLiteAdapter,\n opts?: { ifAbsent?: boolean },\n ): Promise<boolean> {\n validateManifest(data.manifest);\n const executor = this.getExecutor(tx);\n const conflictClause = opts?.ifAbsent\n ? 'ON CONFLICT(entity_id) DO NOTHING'\n : `ON CONFLICT(entity_id) DO UPDATE SET\n mode = excluded.mode, manifest_json = excluded.manifest_json, updated_at = excluded.updated_at`;\n const result = await executor.runAsync(\n `INSERT INTO ${this.prefix}entity_manifests (entity_id, mode, manifest_json, updated_at)\n VALUES (?, ?, ?, ?)\n ${conflictClause}`,\n [entityId, data.mode, JSON.stringify(data.manifest), Date.now()],\n );\n return result.changes > 0;\n }\n\n async mergeManifestUpdates(\n entityId: string,\n updates: OntologyUpdates,\n tx: SQLiteAdapter,\n ): Promise<OntologyManifest> {\n const current = (await this.getManifest(entityId, tx)) ?? {\n mode: 'emergent' as OntologyMode,\n manifest: emptyManifest(),\n };\n const merged = mergeOntologyUpdates(current.manifest, updates);\n await this.setManifest(entityId, { mode: current.mode, manifest: merged }, tx);\n return merged;\n }\n}\n","/**\n * Bounded LLM calls.\n *\n * Maintenance passes build prompts whose *response* size grows with corpus\n * size. Past a threshold the call fails permanently: every retry re-sends the\n * same oversized request, so there is no partial progress and no self-recovery.\n * Raising the host's token budget only postpones this — providers enforce a\n * hard output ceiling, and core cannot see it (`LLMProvider.generateText`\n * returns a bare string).\n *\n * `runBatched` owns batch sizing, failure detection, halve-and-retry splitting\n * and the skip decision. It knows nothing about facts, heal, or ontology — the\n * caller supplies the domain callbacks — so it is testable against a fake\n * `call` with no LLM and no database.\n */\n\n/**\n * Batch size when the provider declares no ceiling.\n *\n * Deliberately below ONTOLOGY_BACKFILL_BATCH_SIZE (25), a size already\n * observed to fail at a 9999-token ceiling. The absence of a hint must never\n * size *up*: starting large would make the split path do all the work, burning\n * API time and tokens on first attempts guaranteed to fail.\n */\nexport const DEFAULT_BATCH_SIZE = 10;\n\n/** Crude per-item output estimate. Its only job is to make the common case one\n * call rather than three; it is never trusted — the split path is always armed. */\nconst ESTIMATED_OUTPUT_TOKENS_PER_ITEM = 150;\n\n/** Headroom against the declared ceiling for preamble, JSON syntax, and the\n * estimate simply being wrong. */\nconst OUTPUT_BUDGET_FRACTION = 0.8;\n\nconst TRUNCATION_PATTERNS: RegExp[] = [\n /truncat/i,\n /token limit/i,\n /max(imum)?[ _-]?tokens?/i,\n /output limit/i,\n /length limit/i,\n /finish[_ ]?reason/i,\n];\n\n// A \"max tokens\" match paired with \"exceed(s)\" is a request-configuration\n// error (the caller asked for more than the model allows), not the provider\n// cutting a response short. Splitting the batch cannot fix it — the adapter\n// keeps requesting the same max tokens — so it must propagate instead of\n// being absorbed into a pile of skipped items.\nconst EXCEEDS_LIMIT_PATTERN = /exceed[a-z]*[^.]{0,40}\\b(model|context)?[ _-]?limit/i;\n\n/**\n * Whether a thrown error looks like the provider cut the response short.\n *\n * Core only sees a string or an Error, so this is string matching by\n * necessity. A false positive costs one wasted split; a false negative\n * propagates the error, which is the right outcome for a network or auth\n * failure that must not be silently absorbed into a pile of skipped items.\n *\n * The contract is explicit: this function must never throw. The\n * `err instanceof Error` check below invokes the `getPrototypeOf` trap on\n * `err`. A hostile Proxy whose trap rejects would otherwise throw out of\n * `runBatched` — and any throw inside `runBatched` is the silent-batch-\n * failure mode this whole helper exists to prevent. On a hostile trap, we\n * fall back to `false` (treat as not a truncation error): the consequence\n * is at most one wasted batch split, which is the correct trade-off.\n */\nfunction getErrorMessage(err: unknown): string | undefined {\n try {\n return err instanceof Error ? err.message : String(err ?? '');\n } catch {\n // hostile Proxy whose getPrototypeOf trap rejects\n return undefined;\n }\n}\n\nexport function isTruncationError(err: unknown): boolean {\n const message = getErrorMessage(err);\n if (message === undefined) return false;\n if (EXCEEDS_LIMIT_PATTERN.test(message)) return false;\n return TRUNCATION_PATTERNS.some((pattern) => pattern.test(message));\n}\n\n/**\n * Whether a thrown error looks like a model-config error — the caller\n * requested more output than the model allows, and re-running it in the\n * next pass produces the same failure. Distinguished from transient\n * provider failures (`ECONNRESET`, auth blip, 5xx) so the cooldown-stamp\n * filter in `doRunHeal` / `doRunOntologyBackfill` does not exclude these\n * facts from eligibility: a model-config bug is the host's problem to\n * fix, and a fact that errored this way can recover only when the host\n * does, so the cooldown stamp is the right behavior.\n *\n * Same Proxy-safety contract as `isTruncationError`: hostile\n * `getPrototypeOf` trap must not propagate out of this function.\n */\nexport function isConfigError(err: unknown): boolean {\n const message = getErrorMessage(err);\n if (message === undefined) return false;\n return EXCEEDS_LIMIT_PATTERN.test(message);\n}\n\nexport interface BuiltPrompt {\n systemPrompt: string;\n userPrompt: string;\n}\n\nexport interface RunBatchedArgs<TItem, TResult> {\n items: TItem[];\n /**\n * May be async: heal selects anchors per batch via a search + repository read.\n *\n * `attemptLevel` is the escalation level at which this build is being asked\n * to produce a prompt. trim()'s speculatives always pass `0` (they only\n * measure length). Real attempts pass the current escalation level: `0`\n * (normal), `1` (less shared context), `2` (less again), or `3` (last\n * resort — caller is expected to shrink or truncate the prompt itself).\n * Defaults to `0` so callers that don't care about the level are unchanged.\n */\n buildPrompt: (\n batch: TItem[],\n attemptLevel?: 0 | 1 | 2 | 3,\n ) => BuiltPrompt | Promise<BuiltPrompt>;\n call: (prompts: BuiltPrompt) => Promise<string>;\n /** Receives the batch so the caller can pair a response with the exact items\n * that produced it without this module knowing any domain shape, and the\n * exact prompt object that was sent (heal keys its grounding corpus to it).\n * Throwing is the signal that the response was unusable. */\n parse: (responseText: string, batch: TItem[], prompts: BuiltPrompt) => TResult;\n /** Provider output ceiling, when the host declares one. Sizing hint only. */\n maxOutputTokens?: number;\n /** Input bound, applied independently of output sizing. */\n maxPromptChars: number;\n /** Called once per skipped item, for operator-legible logging. */\n onSkip?: (item: TItem, err: unknown) => void;\n}\n\nexport interface RunBatchedOutcome<TItem, TResult> {\n results: TResult[];\n /**\n * Items that could not converge after the helper's full escalation path.\n * The discriminator separates genuine non-convergence (`'non_convergent'`\n * — terminal give-up at L3, parse error, or a model-config error) from\n * transient provider failures (`'call_error'` — non-truncation error\n * originating in `call()` at `batch.length === 1`). Callers that stamp a\n * cooldown on skipped facts (e.g. `doRunHeal`) must filter out the\n * `'call_error'` ids so a momentary 5xx doesn't lock the fact out for a\n * week.\n */\n skipped: Array<{ item: TItem; reason: 'non_convergent' | 'call_error' }>;\n /** Number of `call` attempts made, including failed ones. */\n batches: number;\n}\n\nexport function initialBatchSize(maxOutputTokens?: number): number {\n if (!maxOutputTokens || !Number.isFinite(maxOutputTokens) || maxOutputTokens <= 0) {\n return DEFAULT_BATCH_SIZE;\n }\n const estimate = Math.floor(\n (maxOutputTokens * OUTPUT_BUDGET_FRACTION) / ESTIMATED_OUTPUT_TOKENS_PER_ITEM,\n );\n // Only ever sizes up. Sizing down from a declared ceiling is left to the\n // split path, which measures reality instead of guessing.\n return Math.max(DEFAULT_BATCH_SIZE, estimate);\n}\n\nconst promptLength = (prompts: BuiltPrompt): number =>\n prompts.systemPrompt.length + prompts.userPrompt.length;\n\nexport async function runBatched<TItem, TResult>(\n args: RunBatchedArgs<TItem, TResult>,\n): Promise<RunBatchedOutcome<TItem, TResult>> {\n const { items, buildPrompt, call, parse, maxPromptChars, maxOutputTokens, onSkip } = args;\n\n const results: TResult[] = [];\n const skipped: Array<{ item: TItem; reason: 'non_convergent' | 'call_error' }> = [];\n let batches = 0;\n\n /**\n * Sticky downward adaptation. Ratchets down on failure and never climbs back\n * up within a run: without it, a 1177-fact backlog rediscovers the same\n * ceiling on every batch. Deliberately *not* touched by maxPromptChars\n * trimming — one dense batch should not shrink every later batch.\n */\n let batchSize = initialBatchSize(maxOutputTokens);\n\n /**\n * Longest prefix of `candidate` whose built prompt fits `maxPromptChars`. A\n * single item that exceeds the cap alone is still sent: deferring it would\n * starve it forever.\n *\n * `buildPrompt` is not assumed cheap — heal runs a keyword search and a\n * repository read on every call — so the overflow path binary-searches the\n * prefix length instead of dropping one item at a time. The whole batch is\n * tried first, which keeps the common case (it fits) at exactly one call and\n * bounds the overflow case at ~log2(n) + 1 instead of n.\n *\n * Prompt length is treated as non-decreasing in prefix length. That is the\n * same assumption the one-at-a-time walk made by stopping at the first fit;\n * if it is ever violated the result is a slightly different batch size, never\n * a lost item, and the split path stays armed either way.\n */\n const trim = async (candidate: TItem[]): Promise<{ batch: TItem[]; prompts: BuiltPrompt }> => {\n const whole = await buildPrompt(candidate);\n if (candidate.length <= 1 || promptLength(whole) <= maxPromptChars) {\n return { batch: candidate, prompts: whole };\n }\n\n let low = 2;\n let high = candidate.length - 1; // the full length is known not to fit\n let best: TItem[] | undefined;\n let bestPrompts: BuiltPrompt | undefined;\n\n while (low <= high) {\n const mid = Math.floor((low + high) / 2);\n const batch = candidate.slice(0, mid);\n const prompts = await buildPrompt(batch);\n if (promptLength(prompts) <= maxPromptChars) {\n best = batch;\n bestPrompts = prompts;\n low = mid + 1;\n } else {\n high = mid - 1;\n }\n }\n\n if (best && bestPrompts) return { batch: best, prompts: bestPrompts };\n\n const single = candidate.slice(0, 1);\n return { batch: single, prompts: await buildPrompt(single) };\n };\n\n const onFailure = async (\n batch: TItem[],\n err: unknown,\n attemptLevel: 0 | 1 | 2 | 3,\n fromCall: boolean,\n ): Promise<void> => {\n if (batch.length === 1) {\n // Gate: escalation only on a truncation-shaped error at the lowest batch\n // size, and only while the ladder has levels left. Anything else at this\n // point — parse error, exceeds-limit config error, or a non-truncation\n // call error — is a terminal give-up. A parse error is not retryable by\n // context-shedding (the JSON desync shape is the same at L1, L2, and L3);\n // escalating would burn three calls before reaching skip. The gate\n // prevents that.\n if (fromCall && isTruncationError(err) && attemptLevel < 3) {\n // Bypass trim: its prebuilt prompt is the L0 form, invalid at the new\n // level. attempt() will call buildPrompt(batch, attemptLevel + 1) to\n // produce the level-appropriate prompt.\n await attempt(batch, undefined, (attemptLevel + 1) as 0 | 1 | 2 | 3);\n } else {\n // Subreason: a non-truncation error originating in `call()` is a\n // transient provider failure (5xx, network reset, auth blip), not a\n // model capability failure or a model-config bug. Distinguishing it\n // lets orchestration callers (doRunHeal, doRunOntologyBackfill)\n // refuse to apply a recheck cooldown stamp to facts whose skip is\n // operationally reversible. EXCEEDS_LIMIT-shaped errors are\n // model-config bugs that retry identically every pass, so they stay\n // `'non_convergent'` and receive the cooldown stamp. See\n // docs/superpowers/specs/2026-08-17-...-design.md §\"Revision 1 —\n // call_error subreason\".\n const reason: 'non_convergent' | 'call_error' =\n fromCall && !isTruncationError(err) && !isConfigError(err) ? 'call_error' : 'non_convergent';\n skipped.push({ item: batch[0], reason });\n onSkip?.(batch[0], err);\n }\n return;\n }\n // Non-truncation call errors at batch.length > 1 are real errors (network,\n // auth) and must propagate rather than silently split/skip the corpus.\n // Parse errors always split — the JSON may parse after shedding context.\n if (fromCall && !isTruncationError(err)) throw err;\n // batch.length > 1: split path, unchanged. Sticky-down batchSize\n // adaptation and the inner trim/attempt loop at level 0 are preserved.\n const mid = Math.ceil(batch.length / 2);\n if (mid < batchSize) batchSize = mid;\n // Re-reads batchSize on every chunk rather than fixing it once: a nested\n // failure inside the first chunk can shrink batchSize further, and a later\n // chunk of this same batch must honor that smaller size too, not the size\n // this batch was split at before the shrink was discovered.\n //\n // Chunks go through `trim` rather than straight to `attempt`: a subset of a\n // trimmed batch is not automatically under maxPromptChars, because\n // buildPrompt is not required to be monotonic in batch size. Heal's is not\n // — it re-selects up to HEAL_MAX_ANCHORS anchors per batch, so a sub-batch\n // can match anchors the parent did not. Without this, the input bound held\n // only on first attempts.\n let i = 0;\n while (i < batch.length) {\n const size = Math.min(batchSize, batch.length - i);\n const trimmed = await trim(batch.slice(i, i + size));\n await attempt(trimmed.batch, trimmed.prompts);\n // trim always returns at least one item, so this advances.\n i += trimmed.batch.length;\n }\n };\n\n const attempt = async (\n batch: TItem[],\n prebuilt?: BuiltPrompt,\n attemptLevel: 0 | 1 | 2 | 3 = 0,\n ): Promise<void> => {\n if (batch.length === 0) return;\n // prebuilt is the L0 form from trim(); only valid at attemptLevel === 0.\n // The level-advance path in onFailure passes `undefined` to force a rebuild.\n const prompts =\n prebuilt && attemptLevel === 0\n ? prebuilt\n : (await buildPrompt(batch, attemptLevel));\n\n batches++;\n let responseText: string;\n try {\n responseText = await call(prompts);\n } catch (err) {\n // Non-truncation call errors: hand to onFailure (skips at batch.length===1,\n // throws at batch.length>1). Truncation errors also go to onFailure for\n // potential ladder escalation.\n await onFailure(batch, err, attemptLevel, true);\n return;\n }\n\n let result: TResult;\n try {\n result = parse(responseText, batch, prompts);\n } catch (err) {\n // A response truncated mid-JSON surfaces here rather than as a thrown\n // call error, depending on where the cut landed in the grammar.\n // Parse errors always split, never throw — the JSON may parse after\n // shedding context. The gate inside onFailure handles ladder escalation.\n await onFailure(batch, err, attemptLevel, false);\n return;\n }\n\n results.push(result);\n };\n\n let index = 0;\n while (index < items.length) {\n const { batch, prompts } = await trim(items.slice(index, index + batchSize));\n index += batch.length;\n await attempt(batch, prompts, 0);\n }\n\n return { results, skipped, batches };\n}\n","import { parseJsonResponse, validateFact, validateTask, titleTokens, jaccardScore, normalizeSourceRef, normalizeSourceHash, sanitizeRankerError, safeErrorToString, safeSlice, withConcurrency, factRejectionReason, taskRejectionReason } from '../utils/pure';\nimport { resolveGrounding, checkGrounding, groundingOutcome } from '../utils/grounding';\nimport { normalizeTitleKey } from '../utils/ontology';\nimport { validateClassifierAnswer, classifierStateForFact, type ClassifierRejection } from '../utils/classifier';\nimport { DiagnosticBuffer, emitDiagnostic, edgeDropDiagnostic } from '../utils/diagnostics';\nimport type { EdgeDrop } from '../utils/ontology';\nimport { PromptService } from './PromptService';\nimport type { OntologyService, TitleIndexEntry } from './OntologyService';\nimport { generateId } from '../utils/ids';\nimport { parseEmbedding } from '../utils/embedding';\nimport { PrunePartialFailureError } from '../types';\nimport { HOOK_TIMEOUT_MARKER } from '../types';\nimport type { WikiOptions, ExtractedFact, ExtractedFactEdge, ExtractedTask, ExtractedFactWithOntology, WikiFact, WikiTask, OntologyUpdates, OntologyBackfillResult, HealResult, DegradedRecord, ReembedResult, ClassifierQuestion, OntologyManifest, WikiDiagnosticTrigger } from '../types';\nimport type { SQLiteAdapter } from '../types';\nimport type { EntryRepository } from '../repositories/EntryRepository';\nimport type { SourceRefIndexRepository } from '../repositories/SourceRefIndexRepository';\nimport type { TaskRepository } from '../repositories/TaskRepository';\nimport type { EventRepository } from '../repositories/EventRepository';\nimport { entitySummaryMetaKey, type MetadataRepository } from '../repositories/MetadataRepository';\nimport type { SearchService } from './SearchService';\nimport type { JobManager } from './JobManager';\nimport type { EmbeddingService } from './EmbeddingService';\nimport { runBatched } from './BoundedLlmCall';\nimport type { BuiltPrompt } from './BoundedLlmCall';\nimport {\n HEAL_ANCHORS_PER_CANDIDATE,\n HEAL_MAX_ANCHORS,\n HEAL_MAX_FACT_BODY_CHARS_L3,\n HEAL_MAX_TASKS,\n} from '../utils/healConstants';\n\nconst FUZZY_THRESHOLD = 0.5;\nconst MIN_TOKENS_TO_QUALIFY = 3;\n\nexport const ONTOLOGY_BACKFILL_BATCH_SIZE = 25;\nexport const ONTOLOGY_BACKFILL_MAX_PROMPT_CHARS = 40_000;\nexport const ONTOLOGY_BACKFILL_RECHECK_MS = 7 * 24 * 60 * 60 * 1000;\n\n// Heal constants live in `utils/healConstants` so PromptService and\n// MaintenanceService cannot drift apart on the anchor cap formula\n// (spec: \"values must match\"). Re-exported here to preserve the existing\n// `MaintenanceService.HEAL_*` public surface that index.ts and other\n// downstream consumers already import.\nexport { HEAL_MAX_ANCHORS, HEAL_ANCHORS_PER_CANDIDATE, HEAL_MAX_FACT_BODY_CHARS_L3, HEAL_MAX_TASKS } from '../utils/healConstants';\n\n/** Search hits requested before the immutable_document filter is applied.\n * Overfetched because the index holds every fact, not only anchors. */\nconst HEAL_ANCHOR_SEARCH_OVERFETCH = 4;\n\n/** Input bound for heal, mirroring ONTOLOGY_BACKFILL_MAX_PROMPT_CHARS.\n * Independent of output batching: a small number of dense facts is still trimmed. */\nexport const HEAL_MAX_PROMPT_CHARS = 40_000;\n\n/**\n * Heal candidates fetched per pass. Bounds the pool runBatched draws from, not\n * the size of an individual LLM call — runBatched still packs ~10 candidates per\n * request and splits further on failure. At this default one pass costs roughly\n * 2-3 provider calls instead of an unbounded count (#67).\n */\nexport const HEAL_BATCH_SIZE = 25;\n\n/** Cooldown before an already-healed fact is offered again. Matches ontology backfill. */\nexport const HEAL_RECHECK_MS = 7 * 24 * 60 * 60 * 1000;\n\n/** Attempts after which a fact is considered permanently un-embeddable. */\nexport const MAX_EMBED_ATTEMPTS = 5;\n/** First retry delay after a recoverable embedding failure. */\nexport const EMBED_RETRY_BASE_MS = 60_000;\n/** Upper bound on the exponential retry delay. */\nexport const EMBED_RETRY_CAP_MS = 24 * 60 * 60 * 1000;\n\n/** Exponential backoff: base * 2^(attempts-1), capped. */\nexport function embedRetryDelayMs(attempts: number): number {\n const n = Math.max(1, Math.trunc(attempts || 0));\n const delay = EMBED_RETRY_BASE_MS * Math.pow(2, n - 1);\n return Math.min(delay, EMBED_RETRY_CAP_MS);\n}\n\nexport type ReembedDisposition = 'attempt' | 'defer' | 'permanent';\n\n/**\n * Decide what to do with one candidate row. Pure: no DB, no clock.\n *\n * `float32_overflow` is terminal because it is deterministic arithmetic on the\n * same vector — retrying can only produce the same overflow.\n */\nexport function classifyReembedRow(\n row: {\n embedding_failed_at?: number | null;\n embedding_failure_kind?: string | null;\n embedding_attempts?: number | null;\n },\n now: number,\n force: boolean,\n): ReembedDisposition {\n if (force) return 'attempt';\n\n const failedAt = row.embedding_failed_at;\n if (failedAt === null || failedAt === undefined) return 'attempt';\n\n if (row.embedding_failure_kind === 'float32_overflow') return 'permanent';\n\n const attempts = row.embedding_attempts ?? 0;\n if (attempts >= MAX_EMBED_ATTEMPTS) return 'permanent';\n\n return now - failedAt >= embedRetryDelayMs(attempts) ? 'attempt' : 'defer';\n}\n\n/** One parsed ontology-backfill response, paired with the facts that produced it. */\ninterface OntologyBackfillBatch {\n batch: WikiFact[];\n classifications: Array<{ id?: unknown; okf_type?: unknown; edges?: unknown }>;\n ontologyUpdates?: OntologyUpdates;\n}\n\n/** An immutable_document fact offered to heal purely for contradiction detection. */\ntype HealAnchor = { id: string; title: string; source_ref: string | null; body?: string; lifecycle_status?: string };\n\n/** One parsed heal response, paired with the candidates that produced it. */\ninterface HealBatch {\n batch: WikiFact[];\n downgraded: string[];\n deleted: string[];\n newFacts: ExtractedFact[];\n /** Corpus of the prompt that produced this response; null when heal is not a grounding writer. */\n corpus: string[] | null;\n}\n\n/**\n * Hard cap on skipped-item error text in the log. A provider response or\n * prompt artifact can carry a multi-MB message; one unbounded failure must\n * not flood stderr (or any downstream log-shipping pipeline) by being logged\n * once per skipped item.\n */\nconst SKIP_ERROR_LOG_CHARS = 4096;\n\n/**\n * Stringify an unknown error from `RunBatchedArgs.onSkip` for the log.\n * Exported for unit testing only — callers must always treat the return\n * value as a bounded, log-safe string. Internal callers feed this through\n * `console.warn` from heal/ontology-backfill `onSkip` paths.\n *\n * The callback receives `unknown`, so the value is not guaranteed to be a\n * `WikiParseError` with a small `.message`; a raw provider stack, an HTTP\n * error object, or a `string` is all possible. `String(err)` on a plain object\n * uses `Object.prototype.toString` and stays small, but `JSON.stringify` is\n * needed to surface anything structured, and the output is bounded either\n * way so a degenerate payload cannot slip through.\n *\n * Implementation note: every coercion path delegates to `safeErrorToString`,\n * which guarantees a non-throwing string return via a static\n * `[unstringifiable error]` marker. The previous hand-rolled chain had a\n * hole — `JSON.stringify` throws and the `catch` then ran\n * `Object.prototype.toString.call(err)`, which itself can throw (a Proxy\n * whose `get` trap rejects every property access — including\n * `Symbol.toStringTag`). That throw escaped the function and rejected the\n * surrounding `runBatched` operation wholesale. `safeErrorToString` was\n * hardened against this exact path; reuse it.\n */\nexport const formatSkipError = (err: unknown): string => {\n // Two goals:\n // 1. Surface structured provider errors as JSON when present\n // (e.g. `{code: 500, msg: 'oops'}` -> `\"{\"code\":500,\"msg\":\"oops\"}\"`).\n // 2. Never throw, regardless of what hostile value reaches us via\n // `onSkip` (Symbol, function, throwing toString, Proxy rejecting\n // property access, Error with bad message, etc).\n //\n // `safeErrorToString` is the hardened non-throwing helper; every path\n // either uses it directly or falls back to it. JSON.stringify failure\n // paths (throwing toJSON, circular structure, Proxy) all converge on\n // `safeErrorToString`, which itself wraps String() and\n // Object.prototype.toString.call() in nested try/catch.\n let base: string;\n // `err instanceof Error` invokes the `getPrototypeOf` trap on `err`. A\n // hostile Proxy (e.g. one passed through `onSkip` from a misbehaving\n // provider plugin) whose trap rejects would throw out of this function —\n // defeating the documented \"never throw\" contract. Treat the trap throw\n // as \"not an Error\" and fall through to the JSON.stringify / safeErrorToString\n // branch below.\n let isErrorLike = false;\n try {\n isErrorLike = err instanceof Error;\n } catch {\n // hostile Proxy whose getPrototypeOf trap rejects — fall through\n }\n if (isErrorLike || (typeof err !== 'object' && typeof err !== 'function')) {\n // Errors -> safeErrorToString (returns err.message verbatim, or .name,\n // or '[Error]' for hostile Error subclasses)\n // Primitives (string, number, boolean, bigint, undefined, symbol) ->\n // safeErrorToString (String() handles them all)\n base = safeErrorToString(err);\n } else {\n // null + plain objects + arrays -> try JSON.stringify to surface\n // structure. `null` JSON-stringifies to 'null', `typeof null ===\n // 'object'` so it lands here safely.\n try {\n const json = JSON.stringify(err);\n base = typeof json === 'string' ? json : safeErrorToString(err);\n } catch {\n base = safeErrorToString(err);\n }\n }\n if (base.length > SKIP_ERROR_LOG_CHARS) {\n // safeSlice (from utils/pure) never splits a UTF-16 surrogate pair at the\n // cut boundary — a bare String.slice can, leaving a lone high surrogate\n // that renders as U+FFFD in the log line.\n const truncated = safeSlice(base, 0, SKIP_ERROR_LOG_CHARS);\n return `${truncated}…[+${base.length - SKIP_ERROR_LOG_CHARS} chars truncated]`;\n }\n return base;\n};\n\nexport class MaintenanceService {\n private promptService: PromptService;\n\n constructor(\n private db: SQLiteAdapter,\n private prefix: string,\n private options: WikiOptions,\n private entryRepo: EntryRepository,\n private sourceRefIndexRepo: SourceRefIndexRepository,\n private taskRepo: TaskRepository,\n private eventRepo: EventRepository,\n private metadataRepo: MetadataRepository,\n private searchService: SearchService,\n private jobManager: JobManager,\n private embeddingService: EmbeddingService,\n promptService?: PromptService,\n private ontologyService?: OntologyService,\n ) {\n // Fallback for direct instantiation outside WikiMemory facade (e.g. isolated tests).\n this.promptService = promptService ?? new PromptService(this.options.config?.prompts, resolveGrounding(this.options.config?.grounding));\n }\n\n async runPrune(entityId: string, options?: { retainSoftDeletedFor?: number | null; retainEventsFor?: number | null; vacuum?: boolean }): Promise<{ entries: number; tasks: number; events: number }> {\n this.jobManager.acquireLock('prune', entityId);\n\n try {\n const retainSoftDeletedFor = options?.retainSoftDeletedFor !== undefined ? options.retainSoftDeletedFor : (this.options.config?.pruneRetainSoftDeletedFor ?? 7);\n const retainEventsFor = options?.retainEventsFor !== undefined ? options.retainEventsFor : (this.options.config?.pruneEventsAfter ?? 30);\n const vacuum = options?.vacuum ?? false;\n\n this._validatePruneDuration(retainSoftDeletedFor, 'retainSoftDeletedFor');\n this._validatePruneDuration(retainEventsFor, 'retainEventsFor');\n\n const now = Date.now();\n let deletedEntries = 0;\n let deletedTasks = 0;\n let deletedEvents = 0;\n\n if (retainSoftDeletedFor !== null) {\n const cutoff = now - retainSoftDeletedFor * 86400000;\n const entriesToDelete = await this.entryRepo.getPrunableMetadata(entityId, cutoff);\n\n const succeeded: Array<{ entity_id: string; id: string }> = [];\n let failure: { factId: string; cause: unknown } | null = null;\n\n for (const row of entriesToDelete) {\n try {\n await this.embeddingService.notifyEmbeddingPersistedOrThrow(row.entity_id, row.id, null);\n succeeded.push({ entity_id: row.entity_id, id: row.id });\n } catch (err) {\n failure = { factId: row.id, cause: err };\n break;\n }\n }\n\n const succeededIds = succeeded.map(r => r.id);\n\n await this.db.withTransactionAsync(async (tx) => {\n if (succeededIds.length > 0) {\n deletedEntries = await this.entryRepo.bulkDeletePruned(entityId, cutoff, succeededIds, tx);\n }\n deletedTasks = await this.taskRepo.bulkDeletePruned(entityId, cutoff, tx);\n });\n\n if (failure) {\n await this.searchService.sync(entityId);\n const remaining = entriesToDelete.length - succeeded.length - 1;\n const isTimeout = (failure.cause as any)?.[HOOK_TIMEOUT_MARKER] === true;\n\n if (isTimeout) {\n throw new PrunePartialFailureError(\n succeeded.length, failure.factId, remaining, new Error('Deletion hook timed out'), deletedTasks, 0\n );\n }\n\n const errMsg = (failure.cause as Error)?.message ?? '';\n const isValidationError = errMsg.startsWith('Invalid deletionHookTimeoutMs');\n const sanitizedCause = isValidationError ? failure.cause as Error : this._sanitizeRankerError(failure.cause);\n\n throw new PrunePartialFailureError(\n succeeded.length, failure.factId, remaining, sanitizedCause, deletedTasks, 0\n );\n }\n }\n\n if (retainEventsFor !== null) {\n const cutoff = now - retainEventsFor * 86400000;\n const eventResult = await this.eventRepo.prune(entityId, cutoff);\n deletedEvents = eventResult.changes;\n }\n\n if (vacuum) {\n await this.metadataRepo.vacuum();\n }\n\n await this.searchService.sync(entityId);\n return { entries: deletedEntries, tasks: deletedTasks, events: deletedEvents };\n } finally {\n this.jobManager.releaseLock('prune', entityId);\n }\n }\n\n async runLibrarian(entityId: string, options?: { promptOverride?: string }): Promise<void> {\n this.jobManager.acquireLock('librarian', entityId);\n try {\n await this.doRunLibrarian(entityId, options?.promptOverride);\n } finally {\n this.jobManager.releaseLock('librarian', entityId);\n }\n }\n\n async runHeal(\n entityId: string,\n options?: { promptOverride?: string; batchSize?: number; bodyTruncationChars?: number },\n ): Promise<HealResult> {\n this.jobManager.acquireLock('heal', entityId);\n try {\n return await this.doRunHeal(entityId, options);\n } finally {\n this.jobManager.releaseLock('heal', entityId);\n }\n }\n\n async runOntologyBackfill(\n entityId: string,\n options?: { promptOverride?: string; batchSize?: number; classifier?: 'auto' | 'llm' },\n ): Promise<OntologyBackfillResult> {\n this.jobManager.acquireLock('ontologyBackfill', entityId);\n try {\n return await this.doRunOntologyBackfill(entityId, options);\n } finally {\n this.jobManager.releaseLock('ontologyBackfill', entityId);\n }\n }\n\n /**\n * Re-embed facts, honouring per-row failure markers and exponential backoff.\n *\n * Marker lifecycle (spec §2): markers are cleared by a successful embed, by\n * an upsert carrying a valid blob, and by an embedding-dimension promotion.\n * A promotion revives rows for the NEXT sweep, not this one — reconciliation\n * runs after candidates were already classified.\n *\n * Residual, by design: swapping to a provider with the SAME dimension never\n * sets embedding_dimension_mismatch, so promotion never fires and markers\n * survive the swap. Use `runReembed({ force: true })` to clear that state —\n * `force` bypasses classification entirely and retries every row.\n *\n * Lock scope (spec 2026-09-05 §2): a marker mutation is legal while a sweep\n * is in flight if and only if it cannot resurrect a row the sweep has\n * classified. Mutations scoped to entities not under an active sweep key are\n * legal — the entity-scoped ingest/import lock checks enforce that. The one\n * mutation that spans every entity, `reconcileEmbeddingDimension`'s marker\n * clear, is made legal by DEFERRING (importDump gates on\n * `JobManager.isAnyReembedActive()`), never by widening a lock. Auto-heal is\n * excluded from sweeps for the same reason.\n */\n async runReembed(\n entityId?: string,\n opts?: { force?: boolean; skipExisting?: boolean },\n ): Promise<ReembedResult> {\n const embedFn = this.options.llmProvider.embed;\n // Same callability guard as EmbeddingService.tryEmbedFact (spec §2.4): a\n // misconfigured provider short-circuits the sweep instead of iterating and\n // marking every row.\n if (typeof embedFn !== 'function') {\n return { embedded: 0, skipped: 0, failed: 0, deferred: 0, permanentlyFailed: 0 };\n }\n\n const op = entityId ? 'reembed' : 'global_reembed';\n this.jobManager.acquireLock(op, entityId ?? '*');\n\n try {\n\n const rows = await this.entryRepo.findAllForReembed(entityId);\n this.searchService.evictCache(entityId);\n\n const skipExisting = opts?.skipExisting ?? false;\n let effectiveSkip = skipExisting;\n\n if (skipExisting) {\n const mismatchValue = await this.metadataRepo.getMeta('embedding_dimension_mismatch');\n if (mismatchValue) {\n if (entityId) {\n const mismatchDim = parseInt(mismatchValue, 10);\n const staleCount = await this.entryRepo.countStaleForEntity(entityId, mismatchDim);\n if (staleCount > 0) effectiveSkip = false;\n } else {\n effectiveSkip = false;\n }\n }\n }\n\n let embedded = 0;\n let skipped = 0;\n let failed = 0;\n let deferred = 0;\n let permanentlyFailed = 0;\n const force = opts?.force ?? false;\n // One clock snapshot for the whole sweep: backoff eligibility is decided\n // against sweep-start time, so rows whose window elapses mid-sweep stay\n // deferred until the next sweep. Keeps classifyReembedRow pure and the\n // sweep's deferral decisions deterministic for a single invocation.\n const now = Date.now();\n\n try {\n for (const row of rows) {\n const existingBlob = row.embedding_blob;\n const blobIsValid = !!existingBlob && existingBlob.byteLength > 0 && existingBlob.byteLength % 4 === 0;\n\n if (effectiveSkip && blobIsValid) {\n const vec = parseEmbedding(existingBlob, null);\n if (vec !== null && vec.every(v => Number.isFinite(v))) {\n skipped++;\n continue;\n }\n }\n\n const disposition = classifyReembedRow(row, now, force);\n if (disposition === 'defer') { deferred++; continue; }\n if (disposition === 'permanent') { permanentlyFailed++; continue; }\n\n const result = await this.embeddingService.tryEmbedFact(row, { operation: 'reembed', trigger: 'call' });\n if (result.ok) embedded++;\n else failed++;\n }\n\n if (embedded > 0) {\n await this.embeddingService.reconcileEmbeddingDimension();\n }\n } finally {\n this.searchService.evictCache(entityId);\n }\n\n return { embedded, skipped, failed, deferred, permanentlyFailed };\n } finally {\n this.jobManager.releaseLock(op, entityId ?? '*');\n }\n }\n\n async forget(\n entityId: string,\n params: { entryId?: string; taskId?: string; sourceRef?: string; sourceHash?: string; clearAll?: boolean },\n opts?: { dryRun?: boolean },\n ): Promise<{ deleted: { entries: number; tasks: number }; metadataReset?: boolean }> {\n if (params.clearAll && (params.entryId !== undefined || params.taskId !== undefined || params.sourceRef !== undefined || params.sourceHash !== undefined)) {\n throw new Error('forget() clearAll is mutually exclusive with entryId, taskId, sourceRef, and sourceHash');\n }\n\n // Dry-run: read-only, no lock, no outbox events, no embedding hooks.\n if (opts?.dryRun === true) {\n return this.forgetDryRun(entityId, params);\n }\n\n this.jobManager.acquireLock('forget', entityId);\n\n try {\n const now = Date.now();\n let deletedEntries = 0;\n let deletedTasks = 0;\n const deletedEntryIds: string[] = [];\n\n await this.db.withTransactionAsync(async (tx) => {\n if (params.clearAll) {\n deletedEntryIds.push(...await this.entryRepo.findIdsBySource(entityId, null, null, tx, true));\n deletedEntries = await this.entryRepo.bulkSoftDeleteByEntityId(entityId, tx);\n deletedTasks = await this.taskRepo.bulkSoftDeleteByEntityId(entityId, tx);\n // Mirror the clearAll to source_ref_index so the post-clearAll state\n // has no live index rows for the entity. Hard-delete via the soft-delete\n // path keeps the CDC contract identical to entries (outbox events are\n // not fired for source_ref_index, so this is purely an internal\n // invariant cleanup).\n // TODO: add a bulk source_ref_index soft-delete once the v9 backfill\n // gap is closed; for now, leaving the rows in place is safe because\n // the partial UNIQUE index excludes deleted_at != NULL rows from\n // re-ingest — a re-ingest would correctly take ownership.\n await this.metadataRepo.updateCheckpoint(entityId, { memory: 0, heal: 0 }, tx);\n await this.metadataRepo.deleteMeta(entitySummaryMetaKey(entityId), tx);\n } else {\n const hasIdSelectors = params.entryId !== undefined || params.taskId !== undefined;\n const hasSourceSelectors = params.sourceRef !== undefined || params.sourceHash !== undefined;\n\n if (hasIdSelectors && hasSourceSelectors) {\n throw new Error('forget() params are mutually exclusive: use entryId/taskId together, or sourceRef/sourceHash together, but not both in the same call');\n }\n\n const sourceRef = params.sourceRef !== undefined ? normalizeSourceRef(params.sourceRef) : null;\n if (params.sourceRef !== undefined && !sourceRef) throw new Error('Invalid sourceRef');\n\n const sourceHash = params.sourceHash !== undefined ? normalizeSourceHash(params.sourceHash) : null;\n if (params.sourceHash !== undefined && !sourceHash) throw new Error('Invalid sourceHash (must be 64-char hex string)');\n\n if (params.entryId) {\n const entryId = await this.entryRepo.findIdById(params.entryId, entityId, tx);\n if (entryId) deletedEntryIds.push(entryId);\n }\n\n if (sourceRef || sourceHash) {\n deletedEntryIds.push(...await this.entryRepo.findIdsBySource(entityId, sourceRef, sourceHash, tx, true));\n }\n\n const entryPromise = params.entryId ? this.entryRepo.softDelete(params.entryId, entityId, tx).then(r => r.changes > 0) : null;\n const taskDeletedPromise = params.taskId ? this.taskRepo.softDeleteById(params.taskId, entityId, tx).then(r => r.changes > 0) : null;\n const refPromise = (sourceRef || sourceHash) ? this.entryRepo.softDeleteBySource(entityId, tx, sourceRef, sourceHash) : null;\n // Soft-delete the source_ref_index row so a re-ingest of this\n // sourceRef+hash can take ownership. The pre-check at the start of\n // ingestDocument will now see no live ref and proceed. No-op when\n // the row is already soft-deleted or never existed.\n const sourceRefIndexPromise = sourceRef\n ? this.sourceRefIndexRepo.softDeleteByEntityAndSourceRef(entityId, sourceRef, tx).then(() => undefined)\n : null;\n\n const [entryResult, taskResult, refResult] = await Promise.all([\n entryPromise ?? Promise.resolve(false),\n taskDeletedPromise ?? Promise.resolve(false),\n refPromise ?? Promise.resolve(0),\n sourceRefIndexPromise ?? Promise.resolve(undefined),\n ]);\n\n if (entryResult) deletedEntries++;\n if (taskResult) deletedTasks++;\n deletedEntries += refResult;\n }\n });\n\n await this.searchService.sync(entityId);\n\n const uniqueDeletedIds = Array.from(new Set(deletedEntryIds));\n for (const factId of uniqueDeletedIds) {\n try {\n await this.embeddingService.notifyEmbeddingPersistedOrThrow(entityId, factId, null);\n } catch (hookErr) {\n const isTimeout = (hookErr as any)?.[HOOK_TIMEOUT_MARKER] === true;\n if (isTimeout) {\n throw new Error(`forget(${entityId}/${factId}) failed: ${(hookErr as Error).message}`);\n }\n const errMsg = (hookErr as Error)?.message ?? '';\n if (errMsg.startsWith('Invalid deletionHookTimeoutMs')) {\n throw new Error(`forget(${entityId}/${factId}) failed: ${errMsg}`, { cause: hookErr });\n }\n throw new Error(`forget(${entityId}/${factId}) failed: ANN cleanup hook rejected`, { cause: this._sanitizeRankerError(hookErr) });\n }\n }\n\n return params.clearAll\n ? { deleted: { entries: deletedEntries, tasks: deletedTasks }, metadataReset: true }\n : { deleted: { entries: deletedEntries, tasks: deletedTasks } };\n } finally {\n this.jobManager.releaseLock('forget', entityId);\n }\n }\n\n /**\n * Read-only dry-run preview of {@link forget}. Returns the same shape as a\n * real call would, without acquiring the lock, opening a transaction, staging\n * outbox events, or firing embedding hooks. Counts may be off-by-N during a\n * concurrent real forget — this is accepted, not considered a bug.\n *\n * `metadataReset` mirrors the real call: only `clearAll: true` returns true,\n * because only `clearAll` actually resets the metadata checkpoint.\n * `standard` (sourceRef/sourceHash) returns no metadataReset field, just like\n * the real call. `entryId`/`taskId` selectors are rejected with a clear error\n * (the spec keeps dry-run narrow).\n */\n private async forgetDryRun(\n entityId: string,\n params: { entryId?: string; taskId?: string; sourceRef?: string; sourceHash?: string; clearAll?: boolean },\n ): Promise<{ deleted: { entries: number; tasks: number }; metadataReset?: boolean }> {\n // Note: the clearAll mutual-exclusion check is performed by the public\n // forget() before dispatching here. forgetDryRun is private and unreachable\n // for callers that violate that contract, so it does not re-validate.\n\n if (params.entryId !== undefined || params.taskId !== undefined) {\n throw new Error('forget({ dryRun: true }) does not support entryId/taskId selectors; use sourceRef/sourceHash or clearAll');\n }\n\n if (params.clearAll) {\n const entries = await this.entryRepo.countLiveByEntityId(entityId);\n const tasks = await this.taskRepo.countLiveByEntityId(entityId);\n return { deleted: { entries, tasks }, metadataReset: true };\n }\n\n const sourceRef = params.sourceRef !== undefined ? normalizeSourceRef(params.sourceRef) : null;\n if (params.sourceRef !== undefined && !sourceRef) throw new Error('Invalid sourceRef');\n\n const sourceHash = params.sourceHash !== undefined ? normalizeSourceHash(params.sourceHash) : null;\n if (params.sourceHash !== undefined && !sourceHash) throw new Error('Invalid sourceHash (must be 64-char hex string)');\n\n // No source selectors supplied: the real call is a no-op (softDeleteBySource\n // is gated on `if (sourceRef || sourceHash)`). Mirror that — do NOT count all\n // live entries, which would silently mask a caller bug as a large blast radius.\n if (sourceRef === null && sourceHash === null) {\n return { deleted: { entries: 0, tasks: 0 } };\n }\n\n const entries = await this.entryRepo.countLiveBySource(entityId, sourceRef, sourceHash);\n return { deleted: { entries, tasks: 0 } };\n }\n\n /** Core librarian pass (locks handled by {@link runLibrarian}). Package-internal orchestration hook. */\n async doRunLibrarian(entityId: string, promptOverride?: string, trigger: WikiDiagnosticTrigger = 'call'): Promise<void> {\n const events = await this.eventRepo.getRecent(entityId, 50);\n const currentFactsRows = await this.entryRepo.findRecentByEntityId(entityId, 100);\n\n const currentFacts = currentFactsRows.map(f => {\n const { embedding: _embedding, embedding_blob: _blob, ...rest } = f as WikiFact & { embedding?: unknown; embedding_blob?: unknown };\n return {\n ...rest,\n tags: typeof rest.tags === 'string' ? JSON.parse(rest.tags) : rest.tags,\n };\n });\n\n const ontologyContext = await this.ontologyService?.buildPromptContext(entityId) ?? null;\n\n const promptEvents = events.reverse();\n const librarianGrounding = this.promptService.groundingFor('librarian');\n\n // groundingCorpus (spec §6.3) is built with the prompt, from the event\n // summaries that prompt actually shows.\n const { systemPrompt, userPrompt, groundingCorpus: librarianCorpus = [] } = this.promptService.buildLibrarianPrompt(\n promptEvents,\n currentFacts,\n promptOverride,\n ontologyContext,\n );\n\n const responseText = await this.options.llmProvider.generateText({ systemPrompt, userPrompt });\n\n const result = parseJsonResponse<{\n facts: ExtractedFact[];\n tasks: ExtractedTask[];\n ontology_updates?: OntologyUpdates;\n }>(responseText);\n const facts = Array.isArray(result.facts) ? result.facts : [];\n const tasks = Array.isArray(result.tasks) ? result.tasks : [];\n const ontologyUpdates = result.ontology_updates;\n\n const diagBuffer = new DiagnosticBuffer();\n const diagBase = { entityId, operation: 'librarian' as const, trigger };\n const validFacts: ExtractedFact[] = [];\n const validFactItemIndexes: number[] = [];\n facts.forEach((raw, itemIndex) => {\n const valid = validateFact(raw);\n if (valid) {\n validFacts.push(valid);\n validFactItemIndexes.push(itemIndex);\n } else {\n diagBuffer.push({ ...diagBase, code: 'fact_rejected', detail: { itemIndex, reason: factRejectionReason(raw) } });\n }\n });\n const validTasks: ExtractedTask[] = [];\n tasks.forEach((raw, itemIndex) => {\n const valid = validateTask(raw);\n if (valid) validTasks.push(valid);\n else diagBuffer.push({ ...diagBase, code: 'task_rejected', detail: { itemIndex, reason: taskRejectionReason(raw) } });\n });\n\n const now = Date.now();\n const insertedFacts: Array<{ id: string; entity_id: string; title: string; body: string; tags: string }> = [];\n\n await this.db.withTransactionAsync(async (tx) => {\n let { mode, manifest } = await this.ontologyService?.getEffectiveState(entityId, tx)\n ?? { mode: 'off' as const, manifest: { node_types: [], edge_types: [] } };\n\n if (mode === 'emergent' && ontologyUpdates && this.ontologyService) {\n manifest = await this.ontologyService.mergeEmergentUpdates(entityId, ontologyUpdates, tx);\n }\n\n const titleIndex = new Map<string, TitleIndexEntry>();\n for (const existing of currentFactsRows) {\n titleIndex.set(normalizeTitleKey(existing.title), {\n id: existing.id,\n okf_type: existing.okf_type ?? null,\n });\n }\n\n const factsForDedupe = await this.entryRepo.findRecentByEntityId(entityId, 100, tx);\n\n const pendingEdges: Array<{\n sourceId: string;\n sourceType: string | null;\n edges: ExtractedFactWithOntology['edges'];\n }> = [];\n\n for (const [k, fact] of validFacts.entries()) {\n const newTokens = titleTokens(fact.title);\n let skip = false;\n\n if (newTokens.size >= MIN_TOKENS_TO_QUALIFY) {\n for (const existing of factsForDedupe) {\n if (existing.source_type !== 'librarian_inferred') continue;\n const existingTokens = titleTokens(existing.title);\n if (existingTokens.size >= MIN_TOKENS_TO_QUALIFY) {\n if (jaccardScore(newTokens, existingTokens) >= FUZZY_THRESHOLD) {\n skip = true;\n break;\n }\n }\n }\n }\n\n if (skip) {\n diagBuffer.push({ ...diagBase, code: 'fact_deduplicated', detail: { itemIndex: validFactItemIndexes[k], reason: 'fuzzy_title' } });\n continue;\n }\n\n const ontologyFact = fact as ExtractedFactWithOntology;\n const id = generateId('fact_');\n const validationDrops: EdgeDrop[] = [];\n const normalized = this.ontologyService?.validateAndNormalizeFact(ontologyFact, manifest, { strict: false, drops: validationDrops })\n ?? { okf_type: null, edges: [] };\n for (const drop of validationDrops) diagBuffer.push(edgeDropDiagnostic(drop, { ...diagBase, factId: id }));\n\n const grounding = librarianGrounding\n ? groundingOutcome(checkGrounding(fact.evidence, librarianCorpus, librarianGrounding), now)\n : null;\n if (grounding?.diagnostic) {\n diagBuffer.push({ ...diagBase, code: grounding.diagnostic.code, detail: { factId: id, itemIndex: validFactItemIndexes[k], reason: grounding.diagnostic.reason } });\n }\n\n const factObj: WikiFact = {\n id, entity_id: entityId, title: fact.title, body: fact.body, tags: fact.tags, confidence: fact.confidence,\n source_type: 'librarian_inferred', source_hash: null, source_ref: null,\n created_at: now, updated_at: now, last_accessed_at: null, access_count: 0, deleted_at: null,\n okf_type: normalized.okf_type,\n ...grounding?.trust,\n };\n\n await this.entryRepo.upsert(factObj, tx);\n insertedFacts.push({ id, entity_id: entityId, title: fact.title, body: fact.body, tags: JSON.stringify(fact.tags) });\n factsForDedupe.push(factObj);\n\n titleIndex.set(normalizeTitleKey(fact.title), { id, okf_type: normalized.okf_type });\n\n if (normalized.edges.length > 0) {\n pendingEdges.push({ sourceId: id, sourceType: normalized.okf_type, edges: normalized.edges });\n }\n }\n\n for (const item of pendingEdges) {\n const resolveDrops: EdgeDrop[] = [];\n await this.ontologyService?.resolveAndPersistEdges(\n entityId, item.sourceId, item.sourceType, item.edges ?? [], manifest, titleIndex, tx, now, resolveDrops,\n );\n for (const drop of resolveDrops) diagBuffer.push(edgeDropDiagnostic(drop, diagBase));\n }\n\n for (const task of validTasks) {\n const id = generateId('task_');\n const taskObj: WikiTask = {\n id, entity_id: entityId, description: task.description, status: 'pending', priority: task.priority,\n created_at: now, updated_at: now, resolved_at: null, deleted_at: null\n };\n await this.taskRepo.upsert(taskObj, tx);\n }\n });\n\n diagBuffer.flush(this.options);\n\n await this.searchService.sync(entityId);\n\n for (const fact of insertedFacts) {\n await this.embeddingService.embedFact(fact, { operation: 'librarian', trigger });\n }\n\n this.searchService.evictCache(entityId);\n }\n\n /**\n * Core heal pass (locks handled by {@link runHeal}). Package-internal orchestration hook.\n *\n * Bounded: at most `batchSize` candidates per pass (#67). Loop on\n * `result.remaining > 0` for convergence — see {@link HealResult.remaining}\n * for what convergence means here.\n */\n async doRunHeal(\n entityId: string,\n options?: {\n promptOverride?: string;\n batchSize?: number;\n bodyTruncationChars?: number;\n trigger?: WikiDiagnosticTrigger;\n },\n ): Promise<HealResult> {\n const promptOverride = options?.promptOverride;\n const batchSize = options?.batchSize ?? HEAL_BATCH_SIZE;\n const trigger: WikiDiagnosticTrigger = options?.trigger ?? 'call';\n const diagBase = { entityId, operation: 'heal' as const, trigger };\n if (!Number.isInteger(batchSize) || batchSize < 1) {\n throw new Error('Invalid batchSize: must be an integer >= 1');\n }\n\n const bodyTruncationChars = options?.bodyTruncationChars ?? HEAL_MAX_FACT_BODY_CHARS_L3;\n if (!Number.isInteger(bodyTruncationChars) || bodyTruncationChars < 1) {\n throw new Error('Invalid bodyTruncationChars: must be an integer >= 1');\n }\n\n const now = Date.now();\n const recheckCutoff = now - HEAL_RECHECK_MS;\n const orphanAfterDays = this.options.config?.orphanAfterDays !== undefined ? this.options.config?.orphanAfterDays : 30;\n const staleInferredAfterDays = this.options.config?.staleInferredAfterDays !== undefined ? this.options.config?.staleInferredAfterDays : 60;\n const MS_PER_DAY = 24 * 60 * 60 * 1000;\n\n if (orphanAfterDays !== null && (typeof orphanAfterDays !== 'number' || !Number.isFinite(orphanAfterDays) || orphanAfterDays < 0)) {\n throw new Error('Invalid orphanAfterDays: must be a finite number >= 0 or null');\n }\n if (staleInferredAfterDays !== null && (typeof staleInferredAfterDays !== 'number' || !Number.isFinite(staleInferredAfterDays) || staleInferredAfterDays < 0)) {\n throw new Error('Invalid staleInferredAfterDays: must be a finite number >= 0 or null');\n }\n\n const orphanedIds: string[] = [];\n // The SQL passes below mutate rows before candidates are even selected, so\n // their ids are folded into the HealResult counters — otherwise a pass that\n // soft-deletes 50 orphans but offers no candidates reports `deleted: 0`.\n const staleDowngradedIds: string[] = [];\n\n await this.db.withTransactionAsync(async (tx) => {\n if (orphanAfterDays !== null) {\n const orphanThreshold = now - (orphanAfterDays * MS_PER_DAY);\n orphanedIds.push(...await this.entryRepo.markOrphaned(entityId, orphanThreshold, tx));\n }\n if (staleInferredAfterDays !== null) {\n const staleThreshold = now - (staleInferredAfterDays * MS_PER_DAY);\n staleDowngradedIds.push(...await this.entryRepo.downgradeStaleInferred(entityId, staleThreshold, tx));\n }\n });\n\n for (const factId of orphanedIds) {\n try {\n await this.embeddingService.notifyEmbeddingPersisted(entityId, factId, null);\n } catch (hookErr) {\n console.warn(`[WikiMemory] onEmbeddingPersisted hook failed during heal orphan pass for ${factId}:`, hookErr);\n emitDiagnostic(this.options, { ...diagBase, code: 'hook_failed', detail: { factId, reason: 'on_embedding_persisted' } });\n }\n }\n\n const healCandidates = await this.entryRepo.findHealCandidatesByEntityId(entityId, batchSize, recheckCutoff);\n if (healCandidates.length === 0) {\n // The orphan/stale SQL passes above may still have mutated rows, so the\n // search index sync must happen before returning — it did today, after\n // runBatched no-oped on an empty candidate list.\n await this.searchService.sync(entityId);\n this.searchService.evictCache(entityId);\n const counts = await this.entryRepo.countHealCandidatesByEntityId(entityId, recheckCutoff);\n return {\n scanned: 0,\n downgraded: staleDowngradedIds.length,\n deleted: orphanedIds.length,\n newFactsCreated: 0,\n skipped: [], degraded: [], remaining: counts.eligible, deferred: counts.deferred,\n };\n }\n // Cap applied once at fetch time. The bound is the one remaining\n // unbounded input to the heal prompt (#101's L0 fix). AllTasks is\n // entity-global; we don't re-fetch per level. L1+ levels omit the\n // array via buildHealPrompt's level logic.\n const allTasks = await this.taskRepo.findAllPending([entityId], HEAL_MAX_TASKS);\n const recentEvents = await this.eventRepo.getRecent(entityId, 20);\n\n const healGrounding = this.promptService.groundingFor('heal');\n\n const toPromptShape = (f: WikiFact) => {\n const { embedding: _embedding, embedding_blob: _blob, ...rest } = f as WikiFact & { embedding?: unknown; embedding_blob?: unknown };\n // grounding: spec §6.2 hides trust fields from a grounding writer only;\n // with heal outside grounding.writers the candidate shape is unchanged.\n const shown = healGrounding\n ? (({ lifecycle_status: _l, okf_verified: _v, last_verified_at: _a, last_verified_by: _b, ...r }) => r)(rest)\n : rest;\n return { ...shown, tags: typeof shown.tags === 'string' ? JSON.parse(shown.tags) : shown.tags };\n };\n\n // Anchor selection costs a keyword search plus a repository read, and\n // runBatched calls buildPrompt more than once per batch it actually sends —\n // while trimming to maxPromptChars, and again for each half when a batch is\n // split. Prefixes recur heavily across those paths, so memoizing by the\n // query the batch produces collapses the repeats. Scoped to this pass: the\n // index and the anchor rows can both change between heal runs.\n const anchorCache = new Map<string, HealAnchor[]>();\n\n // runBatched rebuilds prompts while trimming, splitting and escalating, so\n // the corpus is keyed to the exact prompt object each response came from.\n const corpusByPrompt = new WeakMap<BuiltPrompt, string[]>();\n\n // Captured in the doRunHeal scope so the buildPrompt lambda can push\n // L3 truncation records into it. Reconcile after runBatched returns:\n // any record whose id also ended up in outcome.skipped is a\n // contradiction (degraded = healed, skipped = dropped) and is dropped.\n // The post-reconcile log line fires for the survivors only.\n const degraded: DegradedRecord[] = [];\n\n const outcome = await runBatched<WikiFact, HealBatch>({\n items: healCandidates,\n buildPrompt: async (batch, attemptLevel = 0) => {\n const documentAnchors = await this._selectHealAnchors(\n entityId,\n batch,\n // Per-batch anchor cap: `batch.length * HEAL_ANCHORS_PER_CANDIDATE` (capped at\n // HEAL_MAX_ANCHORS) right-sizes the anchor lookup so a 1-fact batch does\n // not overfetch the same 200 keyword hits a 25-fact batch once did.\n // buildHealPrompt applies the matching cap on its side — values must match.\n Math.min(HEAL_MAX_ANCHORS, batch.length * HEAL_ANCHORS_PER_CANDIDATE),\n anchorCache,\n healGrounding !== null,\n );\n const { prompts, degraded: batchDegraded, groundingCorpus } = await this.promptService.buildHealPrompt(\n batch.map(toPromptShape),\n documentAnchors,\n allTasks,\n recentEvents,\n promptOverride,\n attemptLevel,\n bodyTruncationChars,\n );\n // L0 calls (including trim's speculatives) return degraded: [].\n // Only L3 real attempts can push here.\n degraded.push(...batchDegraded);\n if (groundingCorpus !== undefined) corpusByPrompt.set(prompts, groundingCorpus);\n return prompts;\n },\n call: (prompts) => this.options.llmProvider.generateText(prompts),\n parse: (responseText, batch, prompts) => {\n const result = parseJsonResponse<{ downgraded: string[], deleted: string[], newFacts: ExtractedFact[] }>(responseText);\n return {\n batch,\n downgraded: Array.isArray(result.downgraded) ? result.downgraded : [],\n deleted: Array.isArray(result.deleted) ? result.deleted : [],\n newFacts: Array.isArray(result.newFacts) ? result.newFacts : [],\n corpus: corpusByPrompt.get(prompts) ?? null,\n };\n },\n maxOutputTokens: this.options.llmProvider.maxOutputTokens,\n maxPromptChars: HEAL_MAX_PROMPT_CHARS,\n onSkip: (fact, err) => {\n console.warn(\n `[WikiMemory] heal skipped ${entityId}/${fact.id}: response could not be bounded: ${formatSkipError(err)}`,\n );\n },\n });\n\n // The mutable-ids guard is per batch: the model may only act on the\n // candidates it was actually offered in the call that produced the output.\n const safeDowngradedSet = new Set<string>();\n const safeDeletedSet = new Set<string>();\n const newFacts: ExtractedFact[] = [];\n // Position within the producing batch's response, not the merged list, so\n // a diagnostic's itemIndex points into an array the model actually returned.\n const newFactItemIndexes: number[] = [];\n const newFactCorpora: Array<string[] | null> = [];\n\n for (const batchResult of outcome.results) {\n const mutableIds = new Set(batchResult.batch.map(f => f.id));\n for (const id of batchResult.downgraded) if (mutableIds.has(id)) safeDowngradedSet.add(id);\n for (const id of batchResult.deleted) if (mutableIds.has(id)) safeDeletedSet.add(id);\n batchResult.newFacts.forEach((raw, itemIndex) => {\n newFacts.push(raw);\n newFactItemIndexes.push(itemIndex);\n newFactCorpora.push(batchResult.corpus);\n });\n }\n\n const safeDowngraded = Array.from(safeDowngradedSet);\n const safeDeleted = Array.from(safeDeletedSet);\n const diagBuffer = new DiagnosticBuffer();\n const validNewFacts: ExtractedFact[] = [];\n const validNewFactItemIndexes: number[] = [];\n const validNewFactCorpora: Array<string[] | null> = [];\n newFacts.forEach((raw, k) => {\n const itemIndex = newFactItemIndexes[k];\n const valid = validateFact(raw);\n if (valid) {\n validNewFacts.push(valid);\n validNewFactItemIndexes.push(itemIndex);\n validNewFactCorpora.push(newFactCorpora[k]);\n } else {\n diagBuffer.push({ ...diagBase, code: 'fact_rejected', detail: { itemIndex, reason: factRejectionReason(raw) } });\n }\n });\n\n const insertedFacts: Array<{ id: string; entity_id: string; title: string; body: string; tags: string }> = [];\n const uniqueDeletedFactIds = Array.from(new Set(safeDeleted));\n\n // Full-breadth, independent of batchSize. Seeding from healCandidates would\n // shrink dedupe to a batchSize window, letting a synthesized fact that\n // duplicates a librarian_inferred fact outside the window pass the Jaccard\n // check — and a convergence loop would then multiply those duplicates.\n //\n // Read inside the transaction, after softDeleteByIds. The query filters\n // deleted_at IS NULL, so rows this pass retires leave the corpus naturally\n // — no explicit safeDeletedSet filter needed. Ordering is load-bearing:\n // the read must follow softDeleteByIds, or a delete-plus-restate (heal's\n // normal output shape) would match the replacement against the row it\n // replaces, drop the replacement, and leave the fact gone entirely (#68).\n // Reading inside the transaction also closes the race with concurrent\n // librarian passes (#69): withSerializedTransactions ensures a librarian\n // transaction either commits entirely before this transaction begins or\n // entirely after it ends, so there is no interleaving point at which a\n // librarian insert could land unseen.\n await this.db.withTransactionAsync(async (tx) => {\n await this.entryRepo.downgradeByIds(safeDowngraded, entityId, tx);\n await this.entryRepo.softDeleteByIds(safeDeleted, entityId, tx);\n\n const healFactsForDedupe: Array<{ id: string; title: string }> =\n await this.entryRepo.findInferredTitlesByEntityId(entityId, tx);\n\n for (const [k, fact] of validNewFacts.entries()) {\n const newTokens = titleTokens(fact.title);\n let skip = false;\n\n if (newTokens.size >= MIN_TOKENS_TO_QUALIFY) {\n for (const existing of healFactsForDedupe) {\n // The query already restricts to librarian_inferred, so the\n // projected { id, title } rows carry everything the check needs.\n const existingTokens = titleTokens(existing.title);\n if (existingTokens.size >= MIN_TOKENS_TO_QUALIFY) {\n if (jaccardScore(newTokens, existingTokens) >= FUZZY_THRESHOLD) {\n skip = true;\n break;\n }\n }\n }\n }\n\n if (skip) {\n diagBuffer.push({ ...diagBase, code: 'fact_deduplicated', detail: { itemIndex: validNewFactItemIndexes[k], reason: 'fuzzy_title' } });\n continue;\n }\n\n const id = generateId('fact_');\n // A missing corpus is treated as empty, so every quote fails: fail closed.\n const grounding = healGrounding\n ? groundingOutcome(checkGrounding(fact.evidence, validNewFactCorpora[k] ?? [], healGrounding), now)\n : null;\n if (grounding?.diagnostic) {\n diagBuffer.push({ ...diagBase, code: grounding.diagnostic.code, detail: { factId: id, itemIndex: validNewFactItemIndexes[k], reason: grounding.diagnostic.reason } });\n }\n const factObj: WikiFact = {\n id, entity_id: entityId, title: fact.title, body: fact.body, tags: fact.tags, confidence: fact.confidence,\n source_type: 'librarian_inferred', source_hash: null, source_ref: null,\n created_at: now, updated_at: now, last_accessed_at: null, access_count: 0, deleted_at: null,\n ...grounding?.trust,\n };\n\n await this.entryRepo.upsert(factObj, tx);\n insertedFacts.push({ id, entity_id: entityId, title: fact.title, body: fact.body, tags: JSON.stringify(fact.tags) });\n healFactsForDedupe.push({ id, title: fact.title });\n }\n\n // Every candidate offered this pass is stamped, whether it landed in a\n // successful batch or in outcome.skipped: otherwise skipped facts stay at\n // the head of the updated_at ASC queue and starve everything behind them.\n // Facts heal just created are stamped too — without this each synthesized\n // fact is immediately an eligible candidate again and a host\n // `while (remaining > 0)` loop feeds on heal's own output.\n //\n // Transient-error ids (`reason: 'call_error'` from the runBatched helper,\n // added in Revision 1 of the ladder spec) are excluded from the stamp:\n // a momentary provider hiccup would otherwise lock a fact out of heals\n // for the full HEAL_RECHECK_MS window. The fact is reattempted as soon\n // as the host's scheduler runs heal again — `markHealChecked` skips\n // soft-deleted rows above, which is also correct (a deleted row is not\n // a candidate under any future pass).\n const callErrorIds = new Set(\n outcome.skipped.filter((s) => s.reason === 'call_error').map((s) => s.item.id),\n );\n await this.entryRepo.markHealChecked(\n [\n ...healCandidates.map((f) => f.id).filter((id) => !callErrorIds.has(id)),\n ...insertedFacts.map((f) => f.id),\n ],\n entityId,\n now,\n tx,\n );\n });\n\n for (const { item, reason } of outcome.skipped) {\n diagBuffer.push({ ...diagBase, code: 'heal_skipped', detail: { factId: item.id, reason } });\n }\n diagBuffer.flush(this.options);\n\n await this.searchService.sync(entityId);\n\n for (const factId of uniqueDeletedFactIds) {\n try {\n await this.embeddingService.notifyEmbeddingPersisted(entityId, factId, null);\n } catch (hookErr) {\n console.warn(`[WikiMemory] onEmbeddingPersisted hook failed during heal for ${factId}:`, hookErr);\n emitDiagnostic(this.options, { ...diagBase, code: 'hook_failed', detail: { factId, reason: 'on_embedding_persisted' } });\n }\n }\n\n for (const fact of insertedFacts) {\n await this.embeddingService.embedFact(fact, { operation: 'heal', trigger });\n }\n\n this.searchService.evictCache(entityId);\n\n // Reconcile: a degraded record for an id in outcome.skipped is a\n // contradiction (degraded = healed, skipped = dropped). Drop the\n // contradiction. The reconciliation makes the two arrays mutually\n // exclusive on id, which is the contract HealResult promises.\n const skippedIds = new Set(outcome.skipped.map(({ item }) => item.id));\n const healedDegraded = degraded.filter((d) => !skippedIds.has(d.id));\n\n // Post-reconcile log. A naive implementation that logs inside the\n // buildPrompt lambda would emit this warning for facts whose L3\n // attempt still failed; that warning is a property of the log\n // stream, not just the data shape, and the test suite locks it.\n for (const d of healedDegraded) {\n console.warn(\n `[WikiMemory] heal healed under degraded context ${entityId}/${d.id}: ` +\n `body truncated from ${d.originalBodyChars} to ${d.truncatedBodyChars} chars`,\n );\n }\n\n // Skipped candidates were sent to the provider too — they just came back\n // unusable, possibly after being split down to a batch of one. Counting\n // only successful batches would under-report provider exposure, which is\n // the number this field exists to report.\n let scanned = outcome.skipped.length;\n for (const batchResult of outcome.results) scanned += batchResult.batch.length;\n\n // Union rather than sum: the orphan pass runs before candidate selection so\n // its ids cannot also be model-deleted, but a fact the stale pass downgraded\n // can be downgraded again by the model in the same pass.\n const allDowngraded = new Set([...staleDowngradedIds, ...safeDowngraded]);\n const allDeleted = new Set([...orphanedIds, ...uniqueDeletedFactIds]);\n\n const counts = await this.entryRepo.countHealCandidatesByEntityId(entityId, recheckCutoff);\n return {\n scanned,\n downgraded: allDowngraded.size,\n deleted: allDeleted.size,\n newFactsCreated: insertedFacts.length,\n skipped: outcome.skipped.map(({ item, reason }) => ({ id: item.id, reason })),\n degraded: healedDegraded,\n remaining: counts.eligible,\n deferred: counts.deferred,\n };\n }\n\n /** Core ontology backfill pass (locks handled by {@link runOntologyBackfill}). Package-internal orchestration hook. */\n async doRunOntologyBackfill(\n entityId: string,\n options?: { promptOverride?: string; batchSize?: number; classifier?: 'auto' | 'llm' },\n ): Promise<OntologyBackfillResult> {\n const batchSize = options?.batchSize ?? ONTOLOGY_BACKFILL_BATCH_SIZE;\n if (!Number.isInteger(batchSize) || batchSize < 1) {\n throw new Error('Invalid batchSize: must be an integer >= 1');\n }\n\n const now = Date.now();\n const recheckCutoff = now - ONTOLOGY_BACKFILL_RECHECK_MS;\n const zeroed = { scanned: 0, typed: 0, failedValidation: 0, edgesAdded: 0, skipped: 0 };\n\n const ontologyService = this.ontologyService;\n if (!ontologyService) {\n return { ...zeroed, remaining: 0, deferred: 0 };\n }\n\n const { mode, manifest: effectiveManifest } = await ontologyService.getEffectiveState(entityId);\n if (mode === 'off') {\n // remaining stays 0: with ontology off nothing is eligible for typing, and\n // a host convergence loop (while remaining > 0) must terminate.\n const counts = await this.entryRepo.countUntypedByEntityId(entityId, recheckCutoff);\n return { ...zeroed, remaining: 0, deferred: counts.deferred };\n }\n\n const candidates = await this.entryRepo.findUntypedByEntityId(entityId, batchSize, recheckCutoff);\n if (candidates.length === 0) {\n const counts = await this.entryRepo.countUntypedByEntityId(entityId, recheckCutoff);\n return { ...zeroed, remaining: counts.eligible, deferred: counts.deferred };\n }\n\n // Spec §7.3 / REQ-COMPAT-01.5: capability alone never switches paths.\n const classifierMode = options?.classifier ?? this.options.config?.ontology?.backfillClassifier ?? 'llm';\n const classify = this.options.llmProvider.classify;\n if (classifierMode === 'auto' && typeof classify === 'function') {\n const slugs = effectiveManifest.node_types.map((n) => n.type);\n if (slugs.length > 0 && slugs.length <= 255) {\n return this._runClassifierBackfill(entityId, candidates, effectiveManifest, now, recheckCutoff);\n }\n }\n\n const ontologyContext = await ontologyService.buildPromptContext(entityId);\n\n // Payload guard: cap the full serialized prompt (system + user — manifest,\n // ids, tags, JSON syntax, overrides all counted) so dense facts cannot blow\n // a provider's context window. A single fact whose prompt alone exceeds the\n // cap is still sent by itself: deferring it would just re-defer forever and\n // starve it (spec Decision 2). Output size is bounded separately, by\n // runBatched — the two bounds are independent and both enforced.\n const toPromptShape = (f: WikiFact) => ({ id: f.id, title: f.title, body: f.body, tags: f.tags });\n const buildPrompt = (facts: WikiFact[]) => this.promptService.buildOntologyBackfillPrompt(\n facts.map(toPromptShape),\n options?.promptOverride,\n ontologyContext,\n );\n\n const outcome = await runBatched<WikiFact, OntologyBackfillBatch>({\n items: candidates,\n buildPrompt,\n call: (prompts) => this.options.llmProvider.generateText(prompts),\n parse: (responseText, batch) => {\n const parsed = parseJsonResponse<{\n classifications?: Array<{ id?: unknown; okf_type?: unknown; edges?: unknown }>;\n ontology_updates?: OntologyUpdates;\n }>(responseText);\n return {\n batch,\n classifications: Array.isArray(parsed.classifications) ? parsed.classifications : [],\n ontologyUpdates: parsed.ontology_updates,\n };\n },\n maxOutputTokens: this.options.llmProvider.maxOutputTokens,\n maxPromptChars: ONTOLOGY_BACKFILL_MAX_PROMPT_CHARS,\n onSkip: (fact, err) => {\n console.warn(\n `[WikiMemory] ontology backfill skipped ${entityId}/${fact.id}: response could not be bounded: ${formatSkipError(err)}`,\n );\n },\n });\n\n let typed = 0;\n let failedValidation = 0;\n let edgesAdded = 0;\n let scanned = 0;\n let abortedOntologyOff = false;\n\n for (const batchResult of outcome.results) {\n const applied = await this._applyOntologyBackfillBatch(entityId, batchResult, now);\n if (applied.abortedOntologyOff) {\n abortedOntologyOff = true;\n break;\n }\n typed += applied.typed;\n failedValidation += applied.failedValidation;\n edgesAdded += applied.edgesAdded;\n scanned += batchResult.batch.length;\n }\n\n if (abortedOntologyOff) {\n // remaining stays 0 so a host convergence loop (while remaining > 0)\n // still terminates, mirroring the mode === 'off' early path.\n //\n // The counters are NOT zeroed. A pass is now many transactions, so\n // batches applied before the flip are already committed — facts typed,\n // edges persisted, cooldowns stamped. Reporting zeros here would tell the\n // caller nothing happened while the database says otherwise. Only the\n // aborting batch and everything after it are dropped, and those wrote\n // nothing: the abort check runs before any write in the batch's\n // transaction.\n const counts = await this.entryRepo.countUntypedByEntityId(entityId, recheckCutoff);\n return {\n scanned,\n typed,\n failedValidation,\n edgesAdded,\n skipped: outcome.skipped.length,\n remaining: 0,\n deferred: counts.deferred,\n };\n }\n\n // Skipped facts get the same cooldown stamp as processed ones — except\n // transient-error ids (`reason: 'call_error'` from the runBatched helper,\n // added in Revision 1 of the ladder spec), which are excluded so a\n // momentary provider hiccup doesn't lock them out of backfill for a full\n // ONTOLOGY_BACKFILL_RECHECK_MS window. Without the stamp on the non-\n // transient cases, those would stay at the head of the updated_at ASC\n // queue and every later pass would re-attempt them first, starving\n // everything behind them.\n if (outcome.skipped.length > 0) {\n const callErrorIds = new Set(\n outcome.skipped.filter((s) => s.reason === 'call_error').map((s) => s.item.id),\n );\n await this.entryRepo.markOntologyChecked(\n outcome.skipped\n .filter(({ item }) => !callErrorIds.has(item.id))\n .map(({ item }) => item.id),\n entityId,\n now,\n this.db,\n );\n }\n\n this.searchService.evictCache(entityId);\n\n const counts = await this.entryRepo.countUntypedByEntityId(entityId, recheckCutoff);\n return {\n scanned,\n typed,\n failedValidation,\n edgesAdded,\n skipped: outcome.skipped.length,\n remaining: counts.eligible,\n deferred: counts.deferred,\n };\n }\n\n /**\n * Classifier-mode backfill (spec §7.3): one `choice` question per untyped\n * fact over the effective manifest's node-type slugs. Accepted answers go\n * through `_applyOntologyBackfillBatch` exactly like LLM classifications.\n * No edges are proposed.\n */\n private async _runClassifierBackfill(\n entityId: string,\n candidates: WikiFact[],\n manifest: OntologyManifest,\n now: number,\n recheckCutoff: number,\n ): Promise<OntologyBackfillResult> {\n // Call through the provider so a class-based provider keeps its `this`.\n const provider = this.options.llmProvider;\n const rawMin = this.options.config?.ontology?.classifyMinConfidence;\n const minConfidence = typeof rawMin === 'number' && Number.isFinite(rawMin) && rawMin >= 0 && rawMin <= 1 ? rawMin : 0.5;\n const rawConcurrency = this.options.config?.chunkConcurrency ?? 1;\n const concurrency = Number.isFinite(rawConcurrency) && rawConcurrency >= 1 ? Math.floor(rawConcurrency) : 1;\n\n // Manifest descriptions are host-authored ontology vocabulary, not fact content.\n const question: ClassifierQuestion = {\n kind: 'choice',\n options: manifest.node_types.map((n) => n.type),\n instructions:\n 'Choose the ontology node type that best describes this fact.\\n' +\n manifest.node_types.map((n) => `- ${n.type}: ${n.description}`).join('\\n'),\n };\n\n type Outcome =\n | { fact: WikiFact; kind: 'accepted'; okfType: string }\n | { fact: WikiFact; kind: 'low_confidence' }\n | { fact: WikiFact; kind: 'invalid'; reason: ClassifierRejection }\n | { fact: WikiFact; kind: 'threw' };\n\n const outcomes = await withConcurrency<Outcome>(\n candidates.map((fact) => async (): Promise<Outcome> => {\n let response: unknown;\n try {\n response = await provider.classify!({ state: classifierStateForFact(fact), questions: { okf_type: question } });\n } catch {\n return { fact, kind: 'threw' };\n }\n const checked = validateClassifierAnswer(response, 'okf_type', question);\n if (!checked.ok) return { fact, kind: 'invalid', reason: checked.reason };\n if (checked.answer.kind !== 'choice') return { fact, kind: 'invalid', reason: 'kind_mismatch' };\n if (checked.answer.confidence < minConfidence) return { fact, kind: 'low_confidence' };\n return { fact, kind: 'accepted', okfType: checked.answer.choice };\n }),\n concurrency,\n );\n\n // Thrown calls are transient (like `call_error`): no cooldown stamp.\n const attempted = outcomes.filter((o) => o.kind !== 'threw').map((o) => o.fact);\n const skipped = outcomes.length - attempted.length;\n const classifications = outcomes\n .filter((o): o is Extract<Outcome, { kind: 'accepted' }> => o.kind === 'accepted')\n .map((o) => ({ id: o.fact.id, okf_type: o.okfType }));\n const invalidCount = outcomes.filter((o) => o.kind === 'invalid').length;\n\n let typed = 0;\n let failedValidation = 0;\n let edgesAdded = 0;\n let aborted = false;\n if (attempted.length > 0) {\n const applied = await this._applyOntologyBackfillBatch(\n entityId,\n { batch: attempted, classifications, ontologyUpdates: undefined },\n now,\n );\n aborted = applied.abortedOntologyOff;\n if (!aborted) {\n typed = applied.typed;\n failedValidation = invalidCount + applied.failedValidation;\n edgesAdded = applied.edgesAdded;\n }\n }\n\n const diagBuffer = new DiagnosticBuffer();\n const diagBase = { entityId, operation: 'ontologyBackfill' as const, trigger: 'call' as const };\n for (const o of outcomes) {\n if (o.kind === 'low_confidence') {\n diagBuffer.push({ ...diagBase, code: 'classification_low_confidence', detail: { factId: o.fact.id, reason: 'below_threshold' } });\n } else if (o.kind === 'invalid') {\n diagBuffer.push({ ...diagBase, code: 'classification_invalid', detail: { factId: o.fact.id, reason: o.reason } });\n } else if (o.kind === 'threw') {\n diagBuffer.push({ ...diagBase, code: 'classification_invalid', detail: { factId: o.fact.id, reason: 'classify_threw' } });\n }\n }\n // After the apply transaction committed (spec §4.2.4). Classifier answers\n // are reported even on an ontology-off abort: they describe the provider,\n // not a write.\n diagBuffer.flush(this.options);\n\n const counts = await this.entryRepo.countUntypedByEntityId(entityId, recheckCutoff);\n if (aborted) {\n // Mirrors the LLM path: nothing from the aborted batch was written; the host loop terminates.\n return { scanned: 0, typed: 0, failedValidation: 0, edgesAdded: 0, skipped, remaining: 0, deferred: counts.deferred };\n }\n this.searchService.evictCache(entityId);\n return {\n scanned: candidates.length,\n typed,\n failedValidation,\n edgesAdded,\n skipped,\n remaining: counts.eligible,\n deferred: counts.deferred,\n };\n }\n\n /**\n * Applies one parsed backfill batch in its own transaction. Per-batch rather\n * than one transaction for the pass, so mergeEmergentUpdates semantics and\n * the mid-flight `mode === 'off'` abort check keep the shape they had when a\n * pass was a single call.\n */\n private async _applyOntologyBackfillBatch(\n entityId: string,\n batchResult: OntologyBackfillBatch,\n now: number,\n ): Promise<{ typed: number; failedValidation: number; edgesAdded: number; abortedOntologyOff: boolean }> {\n const ontologyService = this.ontologyService!;\n const { batch, classifications, ontologyUpdates } = batchResult;\n\n let typed = 0;\n let failedValidation = 0;\n let edgesAdded = 0;\n let abortedOntologyOff = false;\n const diagBuffer = new DiagnosticBuffer();\n const diagBase = { entityId, operation: 'ontologyBackfill' as const, trigger: 'call' as const };\n\n await this.db.withTransactionAsync(async (tx) => {\n let { mode: txMode, manifest } = await ontologyService.getEffectiveState(entityId, tx);\n\n // setOntologyManifest is not under this job lock, so ontology can be\n // disabled while generateText was in flight. Abort without typing facts\n // or stamping cooldowns.\n if (txMode === 'off') {\n abortedOntologyOff = true;\n return;\n }\n\n if (txMode === 'emergent' && ontologyUpdates) {\n manifest = await ontologyService.mergeEmergentUpdates(entityId, ontologyUpdates, tx);\n }\n\n // Full breadth, three columns only: an old fact's edge targets are its\n // contemporaries, which a recent-100 window would silently miss.\n const titleRows = await this.entryRepo.findTitleIndexByEntityId(entityId, tx);\n const titleIndex = new Map<string, TitleIndexEntry>();\n for (const row of titleRows) {\n titleIndex.set(normalizeTitleKey(row.title), { id: row.id, okf_type: row.okf_type });\n }\n\n const batchById = new Map(batch.map(f => [f.id, f]));\n const applied = new Set<string>();\n const pendingEdges: Array<{ sourceId: string; sourceType: string; edges: ExtractedFactEdge[] }> = [];\n\n for (const classification of classifications) {\n const fact = typeof classification.id === 'string' ? batchById.get(classification.id) : undefined;\n if (!fact || applied.has(fact.id)) {\n failedValidation++;\n continue;\n }\n applied.add(fact.id);\n\n const validationDrops: EdgeDrop[] = [];\n const normalized = ontologyService.validateAndNormalizeFact(\n {\n title: fact.title, body: fact.body, tags: fact.tags, confidence: fact.confidence,\n okf_type: classification.okf_type as string | undefined, edges: classification.edges as ExtractedFactEdge[] | undefined,\n } as ExtractedFactWithOntology,\n manifest,\n { strict: false, drops: validationDrops },\n );\n for (const drop of validationDrops) {\n diagBuffer.push(edgeDropDiagnostic(drop, { ...diagBase, factId: fact.id }));\n }\n if (!normalized.okf_type) {\n failedValidation++;\n continue;\n }\n\n const result = await this.entryRepo.updateOkfType(fact.id, entityId, normalized.okf_type, tx);\n // changes === 0 → typed concurrently between select and update; the\n // okf_type IS NULL guard left it untouched. Counted as an omission.\n if (result.changes === 0) continue;\n\n typed++;\n titleIndex.set(normalizeTitleKey(fact.title), { id: fact.id, okf_type: normalized.okf_type });\n if (normalized.edges.length > 0) {\n pendingEdges.push({ sourceId: fact.id, sourceType: normalized.okf_type, edges: normalized.edges });\n }\n }\n\n // Two-phase: edges resolve only after every batch fact has its new type,\n // so intra-batch targets pass the target-type check.\n for (const item of pendingEdges) {\n const resolveDrops: EdgeDrop[] = [];\n const added = await ontologyService.resolveAndPersistEdges(\n entityId, item.sourceId, item.sourceType, item.edges, manifest, titleIndex, tx, now, resolveDrops,\n );\n edgesAdded += added;\n for (const drop of resolveDrops) {\n diagBuffer.push(edgeDropDiagnostic(drop, diagBase));\n }\n }\n\n await this.entryRepo.markOntologyChecked(batch.map(f => f.id), entityId, now, tx);\n });\n\n diagBuffer.flush(this.options);\n\n return { typed, failedValidation, edgesAdded, abortedOntologyOff };\n }\n\n private _validatePruneDuration(value: number | null | undefined, name: string): void {\n if (value !== null && value !== undefined && (typeof value !== 'number' || !isFinite(value) || value < 0)) {\n throw new Error(`Invalid ${name}: must be a non-negative finite number or null`);\n }\n }\n\n /**\n * Anchors relevant to one batch of heal candidates.\n *\n * Heal used to pass every immutable_document fact for the entity — 2560 rows\n * against 31 candidates on the corpus behind #63 — which is what blew the\n * output ceiling. Anchors are now retrieved by keyword relevance to the batch\n * and capped.\n *\n * The MiniSearch index holds all facts, not only anchors, so hits are\n * overfetched and the source_type restriction is applied after retrieval, in\n * SQL. Search rank order is preserved through the filter.\n *\n * Accepted tradeoff: an anchor that contradicts a candidate while sharing no\n * vocabulary with it is now missed. Exhaustive-but-broken traded for\n * relevance-scoped-and-working.\n *\n * `cache` is keyed by the derived query rather than by the batch, so two\n * batches that reduce to the same query share one lookup. Caller-owned and\n * per-pass — see the call site in doRunHeal.\n */\n private async _selectHealAnchors(\n entityId: string,\n batch: WikiFact[],\n cap: number = HEAL_MAX_ANCHORS,\n cache?: Map<string, HealAnchor[]>,\n withBodies: boolean = false,\n ): Promise<HealAnchor[]> {\n const query = batch.map(f => f.title).join(' ').trim();\n if (!query) return [];\n\n const cached = cache?.get(query);\n if (cached) return cached;\n\n // Overfetch is sized off the cap we were given, not the global max —\n // a single-candidate query asks for fewer search hits.\n const hits = this.searchService.searchKeyword(\n query,\n [entityId],\n cap * HEAL_ANCHOR_SEARCH_OVERFETCH,\n );\n const hitIds = hits.map(h => h.id as string);\n\n const anchors: HealAnchor[] = [];\n if (hitIds.length > 0) {\n const rows = withBodies\n ? await this.entryRepo.findAnchorRowsByIds(entityId, hitIds, undefined, { withBody: true })\n : await this.entryRepo.findAnchorRowsByIds(entityId, hitIds);\n const byId = new Map(rows.map(r => [r.id, r]));\n\n for (const id of hitIds) {\n const row = byId.get(id);\n if (!row) continue;\n anchors.push(row);\n if (anchors.length >= cap) break;\n }\n }\n\n // Cached even when empty: a query that matched nothing still cost a search,\n // and the trim and split paths will ask for it again.\n cache?.set(query, anchors);\n return anchors;\n }\n\n private _sanitizeRankerError(err: unknown): Error {\n return sanitizeRankerError(err, this.options.sanitizeRankerErrors);\n }\n}\n","import type { SQLiteAdapter, MemoryBundle, MemoryDump, WikiFact } from '../types';\nimport type { EntryRepository } from '../repositories/EntryRepository';\nimport type { TaskRepository } from '../repositories/TaskRepository';\nimport type { EventRepository } from '../repositories/EventRepository';\nimport type { EdgeRepository } from '../repositories/EdgeRepository';\nimport { entitySummaryMetaKey, type MetadataRepository } from '../repositories/MetadataRepository';\nimport type { SearchService } from './SearchService';\nimport type { JobManager } from './JobManager';\nimport type { EmbeddingService } from './EmbeddingService';\nimport { clip, normalizeSourceRef } from '../utils/pure';\nimport { latestVerified } from '@equationalapplications/core-okf';\n\nconst MAX_EMBEDDING_BLOB_BYTES = 32 * 1024; // 8192-dim float32 ceiling\nconst IMPORT_TITLE_MAX = 500;\nconst IMPORT_BODY_MAX = 8000;\n\nexport class ImportExportService {\n constructor(\n private db: SQLiteAdapter,\n private entryRepo: EntryRepository,\n private taskRepo: TaskRepository,\n private eventRepo: EventRepository,\n private edgeRepo: EdgeRepository,\n private metadataRepo: MetadataRepository,\n private searchService: SearchService,\n private jobManager: JobManager,\n private embeddingService: EmbeddingService,\n ) {}\n\n async exportDump(entityIds?: string[]): Promise<MemoryDump> {\n let ids: string[];\n if (entityIds && entityIds.length > 0) {\n ids = Array.from(new Set(entityIds));\n } else {\n ids = await this.metadataRepo.getDistinctEntityIds();\n }\n\n const entities: Record<string, MemoryBundle> = {};\n const BATCH = 3;\n for (let i = 0; i < ids.length; i += BATCH) {\n const batch = ids.slice(i, i + BATCH);\n const batchResults = await Promise.all(\n batch.map(\n async (id): Promise<[string, MemoryBundle]> => [\n id,\n await this.getFullBundle(id, { includeBlobs: true }),\n ],\n ),\n );\n for (const [id, bundle] of batchResults) {\n entities[id] = bundle;\n }\n }\n\n return { generatedAt: Date.now(), entities };\n }\n\n async importDump(\n dump: MemoryDump,\n opts?: { merge?: boolean },\n ): Promise<void> {\n const merge = opts?.merge ?? false;\n const entityIds = Object.keys(dump.entities);\n\n this.jobManager.acquireImportLocks(entityIds);\n try {\n await this.assertNoLegacySourceTypes();\n for (const [entityId, bundle] of Object.entries(dump.entities)) {\n await this.doImportEntity(entityId, bundle, merge);\n }\n } finally {\n this.jobManager.releaseImportLocks(entityIds);\n }\n }\n\n async getFullBundle(\n entityId: string,\n opts?: { maxEvents?: number; includeBlobs?: boolean },\n ): Promise<MemoryBundle> {\n const [factsRaw, tasks, events, edges, summaryValue] = await Promise.all([\n opts?.includeBlobs\n ? this.entryRepo.findAllByEntityIdWithBlobs(entityId)\n : this.entryRepo.findAllByEntityId(entityId),\n this.taskRepo.findAllByEntityId(entityId),\n this.eventRepo.getByEntityId(entityId, opts?.maxEvents),\n this.edgeRepo.getByEntityId(entityId),\n this.metadataRepo.getMeta(entitySummaryMetaKey(entityId)),\n ]);\n\n const facts = factsRaw.map((f) => {\n const {\n embedding: _embedding,\n embedding_blob,\n ...rest\n } = f as WikiFact & { embedding?: unknown; embedding_blob?: Uint8Array };\n const safeBlobCopy =\n opts?.includeBlobs && embedding_blob\n ? (() => {\n const c = new ArrayBuffer(embedding_blob.byteLength);\n new Uint8Array(c).set(embedding_blob);\n return new Uint8Array(c);\n })()\n : undefined;\n\n const factBase = safeBlobCopy\n ? { ...rest, embedding_blob: safeBlobCopy }\n : rest;\n return {\n ...factBase,\n tags:\n typeof factBase.tags === 'string'\n ? JSON.parse(factBase.tags)\n : factBase.tags,\n };\n });\n\n return {\n facts,\n tasks,\n events,\n edges,\n ...(summaryValue != null ? { summary: summaryValue } : {}),\n };\n }\n\n /** Single-entity import transaction + post-processing; package-internal hook for tests. */\n async doImportEntity(\n entityId: string,\n bundle: MemoryBundle,\n merge: boolean,\n ): Promise<void> {\n const upsertedFactIds = new Set<string>();\n const upsertedDeletedFactIds = new Set<string>();\n const factsWithPreservedBlob = new Map<string, Uint8Array>();\n const preservedBlobDims = new Set<number>();\n const softDeletedFactIds: string[] = [];\n const clippedTextByFactId = new Map<string, { title: string; body: string }>();\n\n await this.db.withTransactionAsync(async (tx) => {\n if (!merge) {\n const deletedLiveFactIds = await this.entryRepo.findIdsBySource(\n entityId,\n null,\n null,\n tx,\n false,\n );\n softDeletedFactIds.push(...deletedLiveFactIds);\n await this.entryRepo.bulkSoftDeleteByEntityId(entityId, tx);\n await this.taskRepo.bulkSoftDeleteByEntityId(entityId, tx);\n await this.edgeRepo.bulkDeleteByEntityId(entityId, tx);\n await this.metadataRepo.deleteCheckpoint(entityId, tx);\n }\n\n if (bundle.summary !== undefined) {\n await this.metadataRepo.setMeta(entitySummaryMetaKey(entityId), bundle.summary, tx);\n } else if (!merge) {\n await this.metadataRepo.deleteMeta(entitySummaryMetaKey(entityId), tx);\n }\n\n const factIds = bundle.facts.map((fact) => fact.id);\n const existingFactsById = new Map<\n string,\n { id: string; entity_id: string; updated_at: number }\n >();\n const existingFacts = await this.entryRepo.findExistingMetadataByIds(\n factIds,\n tx,\n );\n for (const existingFact of existingFacts) {\n existingFactsById.set(existingFact.id, existingFact);\n }\n\n for (const fact of bundle.facts) {\n const sourceType = this._normalizeImportedSourceType(\n String(fact.source_type),\n {\n entityId,\n factId: fact.id,\n },\n );\n\n const safeUpdatedAt = Number.isFinite(fact.updated_at)\n ? fact.updated_at\n : 0;\n const existing = existingFactsById.get(fact.id);\n\n const rawBlobRaw = (fact as WikiFact & { embedding_blob?: unknown })\n .embedding_blob;\n let rawBlob: Uint8Array | null = null;\n\n if (rawBlobRaw instanceof Uint8Array) {\n if (rawBlobRaw.byteLength <= MAX_EMBEDDING_BLOB_BYTES) {\n rawBlob = rawBlobRaw;\n }\n } else if (\n rawBlobRaw !== null &&\n rawBlobRaw !== undefined &&\n typeof rawBlobRaw === 'object'\n ) {\n const obj = rawBlobRaw as Record<string, unknown>;\n if (obj['type'] === 'Buffer' && Array.isArray(obj['data'])) {\n const data = obj['data'] as number[];\n if (data.length <= MAX_EMBEDDING_BLOB_BYTES) {\n rawBlob = new Uint8Array(data);\n }\n } else if (!Array.isArray(rawBlobRaw)) {\n const entries = Object.keys(obj);\n if (entries.length > 0 && entries.every((k) => /^\\d+$/.test(k))) {\n const len = entries.length;\n if (len <= MAX_EMBEDDING_BLOB_BYTES) {\n rawBlob = new Uint8Array(len);\n for (let i = 0; i < len; i++) {\n rawBlob[i] = (obj[String(i)] as number) ?? 0;\n }\n }\n }\n }\n }\n\n if (rawBlob !== null && rawBlob.byteLength > MAX_EMBEDDING_BLOB_BYTES) {\n rawBlob = null; // Oversized blob — drop and let the fact re-embed normally.\n }\n\n let blobData: Uint8Array | null = null;\n if (\n rawBlob !== null &&\n rawBlob.byteLength > 0 &&\n rawBlob.byteLength % 4 === 0\n ) {\n const copy = new ArrayBuffer(rawBlob.byteLength);\n const alignedBlob = new Uint8Array(copy);\n alignedBlob.set(rawBlob);\n const floats = new Float32Array(copy, 0, rawBlob.byteLength / 4);\n\n let allFinite = true;\n for (let i = 0; i < floats.length; i++) {\n if (!isFinite(floats[i])) {\n allFinite = false;\n break;\n }\n }\n if (allFinite) {\n blobData = alignedBlob;\n }\n }\n\n if (existing) {\n if (existing.entity_id !== entityId) {\n this._warnCrossEntityCollision(\n 'entry',\n fact.id,\n existing.entity_id,\n entityId,\n );\n continue;\n }\n if (merge && safeUpdatedAt <= existing.updated_at) continue;\n }\n\n const safeTitle = clip(String(fact.title ?? ''), IMPORT_TITLE_MAX);\n const safeBody = clip(String(fact.body ?? ''), IMPORT_BODY_MAX);\n clippedTextByFactId.set(fact.id, { title: safeTitle, body: safeBody });\n\n // Normalize source_ref using the same rules as ingestDocument and the\n // startup migration. Persisting the raw value would let a later re-ingest\n // collide on shape mismatch (raw DB ref vs. normalized incoming ref) and\n // would skip soft-deletion on the default-path overwrite.\n // A non-null source_ref that normalizes to null (e.g. all-special-chars\n // or whitespace-only) is rejected to mirror ingestDocument — silently\n // coercing it to NULL would create a legacy row that many APIs\n // intentionally exclude.\n let normalizedSourceRef: string | null = null;\n if (fact.source_ref !== null && fact.source_ref !== undefined) {\n normalizedSourceRef = normalizeSourceRef(fact.source_ref);\n if (normalizedSourceRef === null) {\n throw new Error(\n `importDump: invalid source_ref ${JSON.stringify(fact.source_ref)} ` +\n `for entity \"${entityId}\" fact \"${fact.id}\" ` +\n `(must normalize to a non-empty string; see ingestDocument's sourceRef validation)`,\n );\n }\n }\n\n const factObj: WikiFact = {\n id: fact.id,\n entity_id: entityId,\n title: safeTitle,\n body: safeBody,\n tags: Array.isArray(fact.tags) ? fact.tags : [],\n confidence: fact.confidence,\n source_type: sourceType,\n source_hash: fact.source_hash,\n source_ref: normalizedSourceRef,\n created_at: fact.created_at,\n updated_at: safeUpdatedAt,\n last_accessed_at: fact.last_accessed_at,\n access_count: fact.access_count,\n deleted_at: fact.deleted_at,\n embedding_blob: blobData ?? undefined,\n okf_type: fact.okf_type ?? null,\n // OKF v0.2 — forwarded as-is; parseOkfBundle / the caller is responsible for\n // populating these per spec, importDump does not derive or validate them.\n lifecycle_status: fact.lifecycle_status ?? 'stable',\n stale_after: fact.stale_after ?? null,\n generated_by: fact.generated_by ?? null,\n okf_sources: fact.okf_sources ?? [],\n okf_verified: fact.okf_verified ?? [],\n okf_usage_window: fact.okf_usage_window ?? null,\n // last_verified_at/_by are DERIVED mirrors of `okf_verified` per spec\n // §5.3. Recomputing here (instead of trusting the payload field) closes\n // the invariant that a raw importDump cannot carry a\n // last_verified_by that contradicts its own okf_verified list.\n ...(() => {\n const latest = latestVerified(fact.okf_verified ?? [], Date.now());\n return { last_verified_at: latest?.at ?? null, last_verified_by: latest?.by ?? null };\n })(),\n };\n\n await this.entryRepo.upsertForImport(factObj, tx);\n\n if (blobData != null) {\n factsWithPreservedBlob.set(fact.id, blobData);\n if (!fact.deleted_at) preservedBlobDims.add(blobData.byteLength / 4);\n }\n\n existingFactsById.set(fact.id, {\n id: fact.id,\n entity_id: entityId,\n updated_at: safeUpdatedAt,\n });\n upsertedFactIds.add(fact.id);\n if (fact.deleted_at) upsertedDeletedFactIds.add(fact.id);\n }\n\n const taskIds = bundle.tasks.map((task) => task.id);\n const existingTasksById = new Map<\n string,\n { id: string; entity_id: string; updated_at: number }\n >();\n const existingTasks = await this.taskRepo.findExistingMetadataByIds(\n taskIds,\n tx,\n );\n\n for (const existingTask of existingTasks) {\n existingTasksById.set(existingTask.id, existingTask);\n }\n\n for (const task of bundle.tasks) {\n const safeUpdatedAt = Number.isFinite(task.updated_at)\n ? task.updated_at\n : 0;\n const existing = existingTasksById.get(task.id);\n\n if (existing) {\n if (existing.entity_id !== entityId) {\n this._warnCrossEntityCollision(\n 'task',\n task.id,\n existing.entity_id,\n entityId,\n );\n continue;\n }\n if (merge && safeUpdatedAt <= existing.updated_at) continue;\n }\n\n await this.taskRepo.upsertForImport(\n {\n id: task.id,\n entity_id: entityId,\n description: task.description,\n status: task.status,\n priority: task.priority,\n created_at: task.created_at,\n updated_at: safeUpdatedAt,\n resolved_at: task.resolved_at,\n deleted_at: task.deleted_at,\n okf_type: task.okf_type ?? null,\n // OKF v0.2\n lifecycle_status: task.lifecycle_status ?? 'stable',\n stale_after: task.stale_after ?? null,\n generated_by: task.generated_by ?? null,\n okf_sources: task.okf_sources ?? [],\n okf_verified: task.okf_verified ?? [],\n okf_usage_window: task.okf_usage_window ?? null,\n // Derived mirrors — see fact branch above; same invariant.\n ...(() => {\n const latest = latestVerified(task.okf_verified ?? [], Date.now());\n return { last_verified_at: latest?.at ?? null, last_verified_by: latest?.by ?? null };\n })(),\n },\n tx,\n safeUpdatedAt,\n );\n\n existingTasksById.set(task.id, {\n id: task.id,\n entity_id: entityId,\n updated_at: safeUpdatedAt,\n });\n }\n\n for (const event of bundle.events) {\n await this.eventRepo.addIgnoreDuplicate(\n {\n id: event.id,\n entity_id: entityId,\n event_type: event.event_type,\n summary: event.summary,\n related_entry_id: event.related_entry_id ?? null,\n created_at: event.created_at,\n },\n tx,\n );\n }\n\n for (const edge of bundle.edges ?? []) {\n await this.edgeRepo.addIgnoreDuplicate(\n {\n id: edge.id,\n entity_id: entityId,\n source_id: edge.source_id,\n target_id: edge.target_id,\n edge_type: edge.edge_type,\n created_at: edge.created_at,\n },\n tx,\n );\n }\n });\n\n await this.searchService.sync(entityId);\n\n for (const fact of bundle.facts) {\n if (\n !fact.deleted_at &&\n upsertedFactIds.has(fact.id) &&\n !factsWithPreservedBlob.has(fact.id)\n ) {\n const clipped = clippedTextByFactId.get(fact.id);\n const embedded = await this.embeddingService.embedFact({\n id: fact.id,\n entity_id: entityId,\n title: clipped?.title ?? fact.title,\n body: clipped?.body ?? fact.body,\n tags:\n Array.isArray(fact.tags) || typeof fact.tags === 'string'\n ? fact.tags\n : [],\n }, { operation: 'importDump', trigger: 'call' });\n if (!embedded) {\n await this.embeddingService.notifyEmbeddingPersisted(entityId, fact.id, null);\n }\n }\n }\n\n for (const fact of bundle.facts) {\n const blobData = factsWithPreservedBlob.get(fact.id);\n if (blobData && !fact.deleted_at && upsertedFactIds.has(fact.id)) {\n try {\n const float32Vector = new Float32Array(\n blobData.buffer,\n blobData.byteOffset,\n blobData.byteLength / 4,\n );\n await this.embeddingService.notifyEmbeddingPersisted(\n entityId,\n fact.id,\n float32Vector,\n );\n } catch (hookErr) {\n console.warn(\n `[WikiMemory] onEmbeddingPersisted hook failed for preserved-blob fact ${fact.id}:`,\n hookErr,\n );\n this.embeddingService.reportHookFailed(\n { operation: 'importDump', trigger: 'call' },\n entityId,\n fact.id,\n );\n }\n }\n }\n\n for (const factId of softDeletedFactIds) {\n if (!upsertedFactIds.has(factId) || upsertedDeletedFactIds.has(factId)) {\n try {\n await this.embeddingService.notifyEmbeddingPersisted(\n entityId,\n factId,\n null,\n );\n } catch (hookErr) {\n console.warn(\n `[WikiMemory] onEmbeddingPersisted(vector=null) hook failed for soft-deleted fact ${factId}:`,\n hookErr,\n );\n this.embeddingService.reportHookFailed(\n { operation: 'importDump', trigger: 'call' },\n entityId,\n factId,\n );\n }\n }\n }\n\n try {\n const canonicalDimValue = await this.metadataRepo.getMeta(\n 'embedding_dimension',\n );\n const canonicalDim = canonicalDimValue\n ? parseInt(canonicalDimValue, 10)\n : null;\n\n if (preservedBlobDims.size === 1) {\n const preservedDim = [...preservedBlobDims][0];\n if (canonicalDim === null || canonicalDim === preservedDim) {\n await this.embeddingService.storeEmbeddingDimension(preservedDim);\n const staleMismatchValue = await this.metadataRepo.getMeta(\n 'embedding_dimension_mismatch',\n );\n if (\n staleMismatchValue &&\n parseInt(staleMismatchValue, 10) !== preservedDim\n ) {\n await this.metadataRepo.setMeta(\n 'embedding_dimension_mismatch',\n String(preservedDim),\n this.db,\n );\n }\n // Dimension promotion clears embedding failure markers for EVERY\n // entity, but this import holds only entity-scoped locks — so it can\n // erase classifications a concurrent runReembed(otherEntity) just\n // made. Defer instead of widening the lock: the mismatch key is\n // sticky, so a later import or a productive sweep tail (one that\n // embeds > 0 rows — MaintenanceService runs the tail reconciliation\n // only `if (embedded > 0)`) completes the promotion.\n // Spec 2026-09-05-reembed-lock-scope-design.md §3.2.\n if (this.jobManager.isAnyReembedActive()) {\n console.info(\n '[WikiMemory] importDump: embedding-dimension promotion deferred; a reembed sweep is in flight',\n );\n } else {\n await this.embeddingService.reconcileEmbeddingDimension();\n }\n } else {\n await this.metadataRepo.setMeta(\n 'embedding_dimension_mismatch',\n String(canonicalDim),\n this.db,\n );\n }\n } else if (preservedBlobDims.size > 1) {\n if (canonicalDim === null) {\n const sortedPreservedBlobDims = [...preservedBlobDims].sort(\n (a, b) => a - b,\n );\n await this.embeddingService.storeEmbeddingDimension(\n sortedPreservedBlobDims[0],\n );\n await this.metadataRepo.setMeta(\n 'embedding_dimension_mismatch',\n String(sortedPreservedBlobDims[0]),\n this.db,\n );\n } else {\n await this.metadataRepo.setMeta(\n 'embedding_dimension_mismatch',\n String(canonicalDim),\n this.db,\n );\n }\n }\n } finally {\n this.searchService.evictCache(entityId);\n }\n }\n\n private _warnCrossEntityCollision(\n type: 'entry' | 'task',\n id: string,\n existingEntityId: string,\n targetEntityId: string,\n ): void {\n console.warn(\n `[WikiMemory] importDump: ${type} id ${JSON.stringify(id)} already belongs to entity ` +\n `${JSON.stringify(existingEntityId)}; skipping for entity ${JSON.stringify(targetEntityId)}`,\n );\n }\n\n private _normalizeImportedSourceType(\n raw: string,\n ctx?: { entityId: string; factId: string },\n ): WikiFact['source_type'] {\n if (raw === 'user_document') return 'immutable_document';\n if (raw === 'agent_inferred') return 'librarian_inferred';\n\n const allowed: WikiFact['source_type'][] = [\n 'user_stated',\n 'librarian_inferred',\n 'user_confirmed',\n 'immutable_document',\n ];\n if ((allowed as string[]).includes(raw))\n return raw as WikiFact['source_type'];\n\n const where =\n ctx !== undefined\n ? ` for entity \"${ctx.entityId}\" fact \"${ctx.factId}\"`\n : '';\n throw new Error(\n `importDump: invalid source_type \"${raw}\"${where} (expected one of: ${allowed.join(', ')}, or legacy aliases user_document / agent_inferred)`,\n );\n }\n\n public async assertNoLegacySourceTypes(): Promise<void> {\n if (!(await this.entryRepo.hasLegacySourceTypes())) return;\n\n const count = await this.entryRepo.countLegacySourceTypes();\n throw new Error(\n `Database contains ${count} entries with legacy source_type values ('user_document' or 'agent_inferred'). ` +\n `These enum values were renamed in this release. Running without migration would allow legacy 'user_document' facts to bypass ` +\n `immutability guards, causing data corruption.\\n\\n${this.entryRepo.getLegacyMigrationSQL()}\\n\\n` +\n `After running the migration SQL, restart your application.`,\n );\n }\n}\n","/**\n * Default clamp on embed input length, in characters (~1,500 tokens).\n * Chosen to fit common embedding windows including nomic-embed-text's 2,048 tokens.\n */\nexport const DEFAULT_MAX_EMBED_CHARS = 6_000;\n\n/**\n * Hard upper bound on embed input length, in characters.\n * An unbounded-input guard from `5e04bad fix(core): security hardening phase 2`.\n * Configuration may lower the effective limit but must never raise it past this.\n */\nexport const EMBED_CHARS_CEILING = 16_000;\n","import type { SQLiteAdapter, WikiOptions, EmbeddingMarkerKind, WikiDiagnosticOperation, WikiDiagnosticTrigger } from '../types';\nimport { HOOK_TIMEOUT_MARKER } from '../types';\nimport type { EntryRepository } from '../repositories/EntryRepository';\nimport type { MetadataRepository } from '../repositories/MetadataRepository';\nimport { clip } from '../utils/pure';\nimport { DEFAULT_MAX_EMBED_CHARS, EMBED_CHARS_CEILING } from '../utils/embedDefaults';\nimport { emitDiagnostic } from '../utils/diagnostics';\n\nexport type { EmbeddingMarkerKind };\n\nexport type EmbedFailureKind =\n | EmbeddingMarkerKind\n | 'no_provider'\n | 'storage_error';\n\nexport type EmbedFactResult =\n | { ok: true; dimension: number }\n | { ok: false; kind: EmbedFailureKind };\n\nexport interface EmbedDiagnosticContext {\n operation: WikiDiagnosticOperation;\n trigger: WikiDiagnosticTrigger;\n}\n\nexport class EmbeddingService {\n constructor(\n private db: SQLiteAdapter,\n private options: WikiOptions,\n private entryRepo: EntryRepository,\n private metadataRepo: MetadataRepository,\n ) {}\n\n async storeEmbeddingDimension(dim: number): Promise<void> {\n const existing = await this.metadataRepo.getMeta('embedding_dimension');\n if (existing) {\n const storedDim = parseInt(existing, 10);\n if (storedDim !== dim) {\n console.warn(\n `[WikiMemory] Embedding dimension mismatch: stored ${storedDim}, got ${dim}. ` +\n `Call runReembed() to rebuild embeddings with the new model.`,\n );\n await this.metadataRepo.setMeta('embedding_dimension_mismatch', String(dim), this.db);\n }\n // Do not clear embedding_dimension_mismatch here; only reconcileEmbeddingDimension()\n // may clear it after a full runReembed confirms all blobs match.\n } else {\n await this.metadataRepo.setMeta('embedding_dimension', String(dim), this.db);\n }\n }\n\n /**\n * Promotes embedding_dimension_mismatch to canonical embedding_dimension when\n * safe, and clears embedding failure markers as part of the same event.\n *\n * Marker reset (spec §2.3): a promoted dimension means a different model is\n * producing the vectors, so prior failures no longer predict future ones.\n * `float32_overflow` is cleared too — it is terminal only because retrying is\n * the same arithmetic on the same vector, and after a model change it is not.\n *\n * All three writes commit atomically; see the transaction note inline.\n *\n * Revived rows are NOT embedded here. They become eligible and are picked up\n * by the NEXT sweep, because runReembed calls this after its candidates were\n * already classified; same-sweep revival would be re-entrant.\n *\n * Caller contract (spec 2026-09-05 §3.2): callers must not invoke this while\n * a reembed sweep is in flight unless they hold that sweep's lock, because\n * the marker clear spans every entity. `runReembed`'s tail call is exempt —\n * by the tail, the sweep's classification phase is complete, so the clear\n * cannot resurrect a row THIS sweep classified; any overlap with a\n * concurrent import's entity-scoped, blob-guarded writes (an importDump of a\n * different entity can run during a per-entity sweep) is bounded redundant\n * work. External callers\n * gate on `JobManager.isAnyReembedActive()` and defer. This service\n * deliberately holds no `JobManager` reference: gating here instead of at\n * the call site would make `runReembed`'s own tail call see its own lock and\n * defer forever.\n */\n async reconcileEmbeddingDimension(): Promise<void> {\n const mismatchValue = await this.metadataRepo.getMeta('embedding_dimension_mismatch');\n if (!mismatchValue) return;\n\n const newDim = parseInt(mismatchValue, 10);\n const residualCount = await this.entryRepo.countStaleEmbeddings(newDim);\n if (residualCount === 0) {\n // One transaction for the whole promotion (spec §2.3): the three writes\n // are a single logical event. Committed separately, a failure after\n // clearDimensionMismatch would leave markers set with no mismatch key\n // left to re-trigger promotion, stranding those rows until `force: true`.\n // Safe to open here — both callers (runReembed, importDump's dimension\n // reconciliation) invoke this outside their own transactions, and the\n // adapter does not support nesting.\n await this.db.withTransactionAsync(async (tx) => {\n await this.metadataRepo.setMeta('embedding_dimension', mismatchValue, tx);\n await this.metadataRepo.clearDimensionMismatch(tx);\n await this.entryRepo.clearEmbeddingFailureMarkers(tx);\n });\n }\n }\n\n async tryEmbedFact(fact: {\n id: string;\n entity_id: string;\n title: string;\n body: string;\n tags: string | string[];\n }, ctx?: EmbedDiagnosticContext): Promise<EmbedFactResult> {\n // Callability, not truthiness: a truthy non-function would pass a `!embedFn`\n // guard, throw TypeError at the call, and be marked `provider_error` —\n // burning an attempt per sweep until a host config error permanently\n // excluded the fact. `no_provider` never marks. (spec §2.4)\n if (typeof this.options.llmProvider.embed !== 'function') return { ok: false, kind: 'no_provider' };\n let tagsStr: string;\n if (Array.isArray(fact.tags)) {\n tagsStr = fact.tags.join(' ');\n } else {\n try {\n const parsed = JSON.parse(fact.tags);\n tagsStr = Array.isArray(parsed) ? parsed.join(' ') : fact.tags;\n } catch {\n tagsStr = fact.tags;\n }\n }\n const configuredMaxEmbedChars = this.options.config?.maxEmbedChars;\n const maxEmbedChars = Number.isFinite(configuredMaxEmbedChars)\n ? Math.min(Math.max(0, Math.trunc(configuredMaxEmbedChars as number)), EMBED_CHARS_CEILING)\n : DEFAULT_MAX_EMBED_CHARS;\n const text = clip(`${fact.title} ${fact.body} ${tagsStr}`.trim(), maxEmbedChars);\n let float32Vector: Float32Array;\n try {\n const vector = await this.options.llmProvider.embed(text);\n if (vector.length === 0 || !vector.every(v => typeof v === 'number' && isFinite(v))) {\n console.warn(`[WikiMemory] embedFact: embed() returned an invalid vector for ${fact.id}; skipping.`);\n this.reportEmbed(ctx, fact, 'embedding_failed', 'invalid_vector');\n await this.markFailure(fact.id, 'invalid_vector');\n return { ok: false, kind: 'invalid_vector' };\n }\n float32Vector = new Float32Array(vector);\n let hasNonFinite = false;\n for (let i = 0; i < float32Vector.length; i++) {\n if (!isFinite(float32Vector[i])) {\n hasNonFinite = true;\n break;\n }\n }\n if (hasNonFinite) {\n console.warn(`[WikiMemory] embedFact: embed() returned values that overflow float32 for ${fact.id}; skipping.`);\n this.reportEmbed(ctx, fact, 'embedding_failed', 'float32_overflow');\n await this.markFailure(fact.id, 'float32_overflow');\n return { ok: false, kind: 'float32_overflow' };\n }\n } catch (err) {\n console.warn(`[WikiMemory] embedFact failed for ${fact.id}:`, err);\n this.reportEmbed(ctx, fact, 'embedding_failed', 'embed_threw');\n await this.markFailure(fact.id, 'provider_error');\n return { ok: false, kind: 'provider_error' };\n }\n\n // Storage is a separate failure domain: a DB error here is NOT an\n // embedding failure and must not be marked as one (spec §3.2, D3).\n try {\n await this.storeEmbeddingDimension(float32Vector.length);\n const blob = new Uint8Array(float32Vector.buffer);\n await this.entryRepo.updateEmbeddingBlob(fact.id, blob);\n } catch (err) {\n console.warn(`[WikiMemory] embedFact: persisting embedding failed for ${fact.id}:`, err);\n this.reportEmbed(ctx, fact, 'embedding_failed', 'persist_failed');\n return { ok: false, kind: 'storage_error' };\n }\n\n try {\n await this.notifyEmbeddingPersisted(fact.entity_id, fact.id, float32Vector);\n } catch (hookErr) {\n console.warn(`[WikiMemory] onEmbeddingPersisted hook failed for ${fact.id}:`, hookErr);\n this.reportEmbed(ctx, fact, 'hook_failed', 'on_embedding_persisted');\n }\n return { ok: true, dimension: float32Vector.length };\n }\n\n private reportEmbed(\n ctx: EmbedDiagnosticContext | undefined,\n fact: { id: string; entity_id: string },\n code: 'embedding_failed' | 'hook_failed',\n reason: 'invalid_vector' | 'float32_overflow' | 'embed_threw' | 'persist_failed' | 'on_embedding_persisted',\n ): void {\n if (!ctx) return;\n emitDiagnostic(this.options, {\n code, operation: ctx.operation, trigger: ctx.trigger, entityId: fact.entity_id,\n detail: { factId: fact.id, reason },\n });\n }\n\n /** For callers that invoke `notifyEmbeddingPersisted` directly and catch its failure. */\n reportHookFailed(ctx: EmbedDiagnosticContext, entityId: string, factId: string): void {\n this.reportEmbed(ctx, { id: factId, entity_id: entityId }, 'hook_failed', 'on_embedding_persisted');\n }\n\n /** Marker writes must never fail the caller. Only marker-eligible kinds reach here. */\n private async markFailure(id: string, kind: EmbeddingMarkerKind): Promise<void> {\n try {\n await this.entryRepo.markEmbeddingFailure(id, kind, Date.now());\n } catch (err) {\n console.warn(`[WikiMemory] failed to record embedding failure for ${id}:`, err);\n }\n }\n\n /**\n * Back-compatible boolean form. Kept because callers such as\n * ImportExportService branch on `if (!embedded)`; a discriminated result\n * object is always truthy and would silently disable that branch.\n */\n async embedFact(fact: {\n id: string;\n entity_id: string;\n title: string;\n body: string;\n tags: string | string[];\n }, ctx?: EmbedDiagnosticContext): Promise<boolean> {\n const result = await this.tryEmbedFact(fact, ctx);\n return result.ok;\n }\n\n async notifyEmbeddingPersisted(entityId: string, factId: string, vector: Float32Array | null): Promise<void> {\n if (!this.options.vectorRanker?.onEmbeddingPersisted) return;\n const vectorCopy = vector ? vector.slice() : null;\n await this.options.vectorRanker.onEmbeddingPersisted({\n entityId,\n factId,\n vector: vectorCopy,\n });\n }\n\n async notifyEmbeddingPersistedOrThrow(\n entityId: string,\n factId: string,\n vector: Float32Array | null,\n ): Promise<void> {\n if (!this.options.vectorRanker?.onEmbeddingPersisted) return;\n if (this.options.forceDeleteIgnoreRankerHook === true) return;\n\n const vectorCopy = vector ? vector.slice() : null;\n const rawTimeout = this.options.deletionHookTimeoutMs ?? 30_000;\n if (typeof rawTimeout !== 'number' || !Number.isFinite(rawTimeout) || rawTimeout <= 0) {\n throw new Error('Invalid deletionHookTimeoutMs: must be a positive finite number');\n }\n const timeoutMs = rawTimeout;\n\n let timeoutHandle: ReturnType<typeof setTimeout> | undefined;\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutHandle = setTimeout(() => {\n const timeoutError = new Error(`onEmbeddingPersisted timed out after ${timeoutMs}ms`);\n (timeoutError as any)[HOOK_TIMEOUT_MARKER] = true;\n reject(timeoutError);\n }, timeoutMs);\n });\n\n const hookPromise = Promise.resolve().then(() =>\n this.options.vectorRanker!.onEmbeddingPersisted!({\n entityId,\n factId,\n vector: vectorCopy,\n }),\n );\n\n try {\n await Promise.race([hookPromise, timeoutPromise]);\n } catch (err) {\n hookPromise.catch(() => {});\n throw err;\n } finally {\n if (timeoutHandle) clearTimeout(timeoutHandle);\n }\n }\n}\n","import { WikiInvalidReadOptions } from './types';\n\nexport function normalizeEntityIds(entityId: string | string[]): string[] {\n const input = Array.isArray(entityId) ? entityId : [entityId];\n const seen = new Set<string>();\n const normalized: string[] = [];\n\n for (const id of input) {\n if (seen.has(id)) continue;\n seen.add(id);\n normalized.push(id);\n }\n\n return normalized;\n}\n\nexport function sanitizeTierWeights(\n entityIds: readonly string[],\n tierWeights: Record<string, number> | undefined,\n): Record<string, number> | undefined {\n if (tierWeights === undefined) return undefined;\n\n const sanitized = Object.create(null) as Record<string, number>;\n for (const entityId of entityIds) {\n const raw = tierWeights[entityId];\n if (raw === undefined || !Number.isFinite(raw)) {\n sanitized[entityId] = 1;\n } else {\n sanitized[entityId] = Math.max(0, raw);\n }\n }\n return sanitized;\n}\n\nexport function applyTierWeight(\n score: number,\n entityId: string,\n sanitizedTierWeights: Record<string, number> | undefined,\n): number {\n const weight = sanitizedTierWeights?.[entityId] ?? 1;\n // Weight=0 → sentinel -Infinity so zero-weight entities always sort below any\n // finite score, including negative cosine values from the pure-semantic path.\n if (weight === 0) return -Infinity;\n return score * weight;\n}\n\nexport function shouldExposeReadMetadata(\n entityId: string | string[],\n): boolean {\n return Array.isArray(entityId);\n}\n\n/**\n * Validates and sanitizes `ReadOptions.tierFloors`.\n *\n * Throws `WikiInvalidReadOptions` for contradictions detectable without touching\n * data. Sanitizes value-shape noise. Never throws for data-dependent shortfalls —\n * an entity with fewer facts than its floor simply contributes what it has.\n */\nexport function validateTierFloors(\n entityIds: readonly string[],\n tierFloors: Record<string, number> | undefined,\n sanitizedTierWeights: Record<string, number> | undefined,\n includeZeroWeightEntities: boolean | undefined,\n maxResults: number,\n): Record<string, number> | undefined {\n if (tierFloors === undefined) return undefined;\n\n const known = new Set(entityIds);\n for (const key of Object.keys(tierFloors)) {\n // Per §4.2: non-finite values are sanitized away as absent. Filtering them\n // before key validation matches the documented rule and lets a typo like\n // { typo: NaN } fall through cleanly instead of tripping the \"key is not\n // one of the entity IDs\" check on a value the caller did not actually set.\n const raw = tierFloors[key];\n if (raw === undefined || !Number.isFinite(raw)) continue;\n if (!known.has(key)) {\n throw new WikiInvalidReadOptions(\n 'tierFloors',\n `\"${key}\" is not one of the entity IDs passed to read(); ` +\n `a floor on an unrequested entity can never be satisfied`,\n );\n }\n }\n\n const sanitized = Object.create(null) as Record<string, number>;\n let total = 0;\n for (const entityId of entityIds) {\n const raw = tierFloors[entityId];\n if (raw === undefined || !Number.isFinite(raw)) continue;\n const floor = Math.max(0, Math.trunc(raw));\n\n if (floor > 0 && includeZeroWeightEntities !== true && sanitizedTierWeights?.[entityId] === 0) {\n throw new WikiInvalidReadOptions(\n 'tierFloors',\n `\"${entityId}\" has tierWeight 0 and includeZeroWeightEntities is not set, ` +\n `so it is excluded from retrieval and its floor of ${floor} can never be met`,\n );\n }\n\n sanitized[entityId] = floor;\n total += floor;\n }\n\n if (total > maxResults) {\n throw new WikiInvalidReadOptions(\n 'tierFloors',\n `floors sum to ${total}, which exceeds maxResults (${maxResults})`,\n );\n }\n\n return sanitized;\n}\n\n/**\n * Selects up to `maxResults` rows, reserving each entity's top-N first.\n *\n * PRECONDITION: `sortedRows` must already be in final rank order (the caller's\n * tie-break sort). Selection order is restored from each row's position in the\n * input, so unsorted input yields silently wrong output rather than an error.\n *\n * Floors change which rows are selected, never the order they are returned in.\n */\nexport function selectWithFloors<T extends { id: string; entity_id: string }>(\n sortedRows: readonly T[],\n floors: Record<string, number> | undefined,\n maxResults: number,\n): T[] {\n if (maxResults <= 0) return [];\n if (floors === undefined || Object.keys(floors).length === 0) {\n return sortedRows.slice(0, maxResults);\n }\n\n const selected = new Set<number>();\n const taken = Object.create(null) as Record<string, number>;\n\n // Pass 1 — reserve each entity's top-N. Bounded by sum(floors) <= maxResults,\n // which validateTierFloors guarantees, so this cannot overflow the window.\n for (let i = 0; i < sortedRows.length; i++) {\n const entityId = sortedRows[i].entity_id;\n const floor = floors[entityId] ?? 0;\n if (floor <= 0) continue;\n const count = taken[entityId] ?? 0;\n if (count >= floor) continue;\n taken[entityId] = count + 1;\n selected.add(i);\n }\n\n // Pass 2 — fill the remaining slots in rank order.\n for (let i = 0; i < sortedRows.length && selected.size < maxResults; i++) {\n if (!selected.has(i)) selected.add(i);\n }\n\n // Restore global rank order: input was sorted, so index order is rank order.\n return Array.from(selected)\n .sort((a, b) => a - b)\n .map(i => sortedRows[i]);\n}\n","import type { SQLiteAdapter } from '../types';\nimport type { WikiOptions, MemoryBundle, WikiFact, ReadOptions } from '../types';\nimport { EntryRepository, EntryRowMetadata, EntryRowWithEmbeddings } from '../repositories/EntryRepository';\nimport type { TaskRepository } from '../repositories/TaskRepository';\nimport type { EventRepository } from '../repositories/EventRepository';\nimport type { MetadataRepository } from '../repositories/MetadataRepository';\nimport type { SearchService } from './SearchService';\nimport { applyTierWeight, normalizeEntityIds, sanitizeTierWeights, selectWithFloors, shouldExposeReadMetadata, validateTierFloors } from '../readOptions';\nimport { sanitizeRankerError, safeErrorToString } from '../utils/pure';\n\ntype ReadCandidateRowMetadata = EntryRowMetadata;\ntype ReadCandidateRowWithEmbeddings = EntryRowWithEmbeddings;\n\nconst EMPTY_ID_SET: ReadonlySet<string> = new Set<string>();\n\nexport class RetrievalService {\n constructor(\n private options: WikiOptions,\n private entryRepo: EntryRepository,\n private taskRepo: TaskRepository,\n private eventRepo: EventRepository,\n private metadataRepo: MetadataRepository,\n private searchService: SearchService,\n ) {}\n\n async read(entityId: string | string[], query: string, options?: ReadOptions): Promise<MemoryBundle> {\n const config = this.options.config;\n const entityIds = normalizeEntityIds(entityId);\n const sanitizedTierWeights = shouldExposeReadMetadata(entityId)\n ? sanitizeTierWeights(entityIds, options?.tierWeights)\n : undefined;\n const exposeMetadata = shouldExposeReadMetadata(entityId);\n\n if (entityIds.length === 0) {\n const empty: MemoryBundle = { facts: [], tasks: [], events: [], edges: [] };\n if (exposeMetadata) {\n empty.metadata = { query, entityIds: [] };\n if (sanitizedTierWeights && Object.keys(sanitizedTierWeights).length > 0) empty.metadata.tierWeights = sanitizedTierWeights;\n }\n return empty;\n }\n\n const MAX_ENTITY_IDS = 100;\n if (entityIds.length > MAX_ENTITY_IDS) {\n throw new RangeError(`read() accepts at most ${MAX_ENTITY_IDS} entity IDs; received ${entityIds.length}`);\n }\n const nullByteId = entityIds.find(id => id.includes('\\x00'));\n if (nullByteId !== undefined) {\n throw new TypeError(`entity_id values must not contain the null byte (\\\\x00); got \"${nullByteId}\"`);\n }\n\n const rawMaxResults = options?.maxResults ?? config?.maxResults ?? config?.maxFtsResults ?? 10;\n const maxResults = Number.isFinite(rawMaxResults)\n ? Math.max(0, Math.trunc(rawMaxResults))\n : 10;\n const excludeDrafts = (options?.excludeDrafts ?? config?.excludeDrafts ?? false) === true;\n const trimmedQuery = query.trim();\n // §3.3 — tierFloors is ignored on the empty-query recency path. Skipping\n // validation here keeps the public contract honest: an empty-query call\n // with floors that would otherwise be invalid must not throw, since the\n // floors are dropped before the cut anyway.\n const sanitizedTierFloors = trimmedQuery && exposeMetadata\n ? validateTierFloors(\n entityIds,\n options?.tierFloors,\n sanitizedTierWeights,\n options?.includeZeroWeightEntities,\n maxResults,\n )\n : undefined;\n const rawPreFilterLimit =\n options?.preFilterLimit === null\n ? undefined\n : (options?.preFilterLimit ?? config?.preFilterLimit);\n const effectivePreFilterLimit =\n rawPreFilterLimit === undefined\n ? undefined\n : Number.isFinite(rawPreFilterLimit)\n ? Math.max(0, Math.trunc(rawPreFilterLimit))\n : undefined;\n const hybridWeight = options?.hybridWeight ?? config?.hybridWeight;\n const weight = hybridWeight !== undefined && !Number.isNaN(hybridWeight)\n ? Math.max(0, Math.min(1, hybridWeight))\n : undefined;\n const skipEmbed = weight === 0;\n\n let facts: WikiFact[] = [];\n let scoreByFactId: Map<string, number> | undefined;\n\n if (maxResults === 0) {\n // Fast-path: a zero-capacity result window can never return any facts.\n // Skip embed(), DB scan, and sort — fall through to tasks/events fetch below.\n } else if (trimmedQuery) {\n let usedEmbed = false;\n const scoredEntityIds = this._filterScoredEntities(entityIds, sanitizedTierWeights, options?.includeZeroWeightEntities);\n\n // Spec §5.1: one SQLite read per call; status is never taken from an index.\n const draftIds: ReadonlySet<string> = excludeDrafts && scoredEntityIds.length > 0\n ? await this.entryRepo.findDraftIdsByEntityIds(scoredEntityIds)\n : EMPTY_ID_SET;\n const draftPad = draftIds.size;\n const padLimit = (n: number): number => (n >= Number.MAX_SAFE_INTEGER ? n : n + draftPad);\n\n // Fast-path: all entities zero-weight — skip embed(), DB mismatch query, and\n // cosine work entirely. usedEmbed=true suppresses the keyword fallback below.\n if (scoredEntityIds.length === 0) {\n usedEmbed = true;\n } else if (!skipEmbed && typeof this.options.llmProvider.embed === 'function') {\n let rankerShouldRethrow = false;\n let pendingRankerFallbackError: Error | undefined;\n try {\n const queryVec = await this.options.llmProvider.embed(trimmedQuery);\n\n // Validate that the provider returned a well-formed vector. An empty vector\n // would cause all facts to score 0 (silently bypassing the fallback), and\n // non-finite values (NaN, Infinity) make the sort comparator unstable.\n if (queryVec.length === 0 || !queryVec.every(v => typeof v === 'number' && isFinite(v))) {\n throw new Error(\n 'embed() returned an empty or non-finite vector. Falling back to keyword search.'\n );\n }\n\n // Detect embedding dimension mismatch: if stored dimension differs from the\n // query vector, existing fact embeddings were built with a different model and\n // cosine scoring would silently produce misleading rankings. Fall back to\n // MiniSearch until the caller runs runReembed().\n const storedDimValue = await this.metadataRepo.getMeta('embedding_dimension');\n if (storedDimValue) {\n const storedDim = parseInt(storedDimValue, 10);\n if (storedDim !== queryVec.length) {\n throw new Error(\n `Embedding dimension mismatch: stored ${storedDim}, query has ${queryVec.length}. ` +\n `Call runReembed() to rebuild embeddings with the new model.`\n );\n }\n }\n\n // Check whether any non-deleted fact for any scored entity has a blob whose\n // dimension differs from the query vector. Uses scoredEntityIds so zero-weight\n // (skipped) entities with stale embeddings do not force keyword fallback.\n const mismatchedCount = await this.entryRepo.countDimensionMismatched(scoredEntityIds, queryVec.length);\n if (mismatchedCount > 0) {\n throw new Error(\n `Some facts have embeddings that do not match the current model dimension. ` +\n `Call runReembed() to rebuild all embeddings consistently.`\n );\n }\n\n const useRanker = Boolean(this.options.vectorRanker);\n let candidateRows: ReadCandidateRowMetadata[] | ReadCandidateRowWithEmbeddings[] | null; // null = pre-filter returned 0 results\n // Composite cache keys (multi-entity join strings) are never invalidated by write/reembed paths.\n let populateCache = entityIds.length === 1;\n let miniSearchScores: Map<string, number> | undefined;\n\n if (effectivePreFilterLimit !== undefined) {\n populateCache = false; // partial scan — do not populate cache\n const preResults = this.searchService\n .searchKeyword(trimmedQuery, scoredEntityIds, Number.MAX_SAFE_INTEGER)\n .filter((r) => !draftIds.has(r.id));\n if (preResults.length === 0) {\n candidateRows = null; // empty pre-filter\n } else {\n const topKResults = preResults.slice(0, effectivePreFilterLimit);\n if (topKResults.length === 0) {\n // effectivePreFilterLimit is 0 — treat the same as no candidates\n // (avoids constructing an invalid \"WHERE id IN ()\" SQL clause)\n candidateRows = null;\n } else {\n const topKIds = topKResults.map(r => r.id);\n if (useRanker) {\n candidateRows = await this.entryRepo.findMetadataByIds(topKIds);\n } else {\n candidateRows = await this.entryRepo.findWithEmbeddingsByIds(topKIds);\n }\n if (weight !== undefined && weight < 1) {\n const maxMsScore = Math.max(1, topKResults[0]?.score ?? 1);\n miniSearchScores = new Map(topKResults.map(r => [r.id, r.score / maxMsScore]));\n }\n }\n }\n } else {\n // Full scan of scored entities\n // If vectorRanker is configured, skip embedding load for now (ranker will provide ranking)\n // Otherwise fetch embeddings for JS cosine ranking\n if (useRanker) {\n candidateRows = this._withoutDrafts(await this.entryRepo.findMetadataByEntityIds(scoredEntityIds), draftIds);\n } else {\n candidateRows = this._withoutDrafts(await this.entryRepo.findWithEmbeddingsByEntityIds(scoredEntityIds), draftIds);\n }\n // Collect MiniSearch scores for hybrid blend if weight is set and <1\n if (weight !== undefined && weight < 1) {\n miniSearchScores = this.searchService.getMiniSearchScores(trimmedQuery, scoredEntityIds);\n }\n }\n\n if (candidateRows === null) {\n // pre-filter returned 0 candidates — facts = [], skip phase 2, skip access tracking\n usedEmbed = true;\n } else {\n // Rank candidates: use vectorRanker if present, otherwise use JS cosine\n const entityCacheKey = entityIds.length === 1 ? entityIds[0] : entityIds.join('\\x00');\n let scored: Array<{ id: string; entity_id: string; score: number; updated_at?: number | null; access_count?: number | null }>;\n\n if (useRanker) {\n // Build per-entity candidate maps so each ranker call receives one entityId.\n const candidateRowsByEntity = new Map<string, ReadCandidateRowMetadata[]>();\n for (const row of candidateRows as ReadCandidateRowMetadata[]) {\n const rows = candidateRowsByEntity.get(row.entity_id) ?? [];\n rows.push(row);\n candidateRowsByEntity.set(row.entity_id, rows);\n }\n\n try {\n const rankerResultsByEntity = await Promise.all(\n scoredEntityIds.filter(id => (candidateRowsByEntity.get(id)?.length ?? 0) > 0).map(async scopedEntityId => {\n const rowsForEntity = candidateRowsByEntity.get(scopedEntityId) ?? [];\n const candidateIds = effectivePreFilterLimit !== undefined\n ? rowsForEntity.map(row => row.id)\n : undefined;\n const ranked = await this._rankWithVectorRanker({\n entityId: scopedEntityId,\n queryVec,\n candidateIds,\n candidateRows: rowsForEntity,\n weight,\n miniSearchScores,\n limit: padLimit(Math.max(maxResults * 2, maxResults + 50)),\n });\n return ranked.map(row => ({ ...row, entity_id: scopedEntityId }));\n }),\n );\n\n scored = rankerResultsByEntity.flat();\n\n // Build metadata map only for IDs returned by the ranker (not all candidates)\n // to keep memory proportional to the oversampled result size on constrained runtimes.\n const scoredIds = new Set(scored.map(s => s.id));\n const metadataById = new Map(\n (candidateRows as ReadCandidateRowMetadata[])\n .filter(row => scoredIds.has(row.id))\n .map(row => [row.id, row])\n );\n scored = scored.map(row => {\n const metadata = metadataById.get(row.id);\n return {\n ...row,\n updated_at: metadata?.updated_at ?? null,\n access_count: metadata?.access_count ?? null,\n };\n });\n\n // Backfill ranker-omitted rows per VectorRanker contract:\n // treat missing ids as \"no embedding\" (pure semantic: -2, hybrid: keyword-only)\n\n // Reserve per-entity floor shortfalls from omitted rows BEFORE\n // the global backfill pass. Without this reservation, the global\n // backfill budget caps at `maxResults - scored.length` (pure\n // semantic) or `maxResults` selected by kwScore (hybrid), and\n // either cap can silently drop every row from a floored entity\n // when the ranker returned no scores for it. selectWithFloors\n // cannot reserve a starved entity's floor from a `scored`\n // array that does not contain enough of its rows.\n type CandidateRow = typeof candidateRows[number];\n const floorShortfallByEntity: Record<string, number> = Object.create(null);\n let totalFloorShortfall = 0;\n if (sanitizedTierFloors) {\n const scoredCounts = new Map<string, number>();\n for (const s of scored) {\n scoredCounts.set(s.entity_id, (scoredCounts.get(s.entity_id) ?? 0) + 1);\n }\n for (const [entityId, floor] of Object.entries(sanitizedTierFloors)) {\n if (floor <= 0) continue;\n const currentCount = scoredCounts.get(entityId) ?? 0;\n const shortfall = Math.max(0, floor - currentCount);\n if (shortfall > 0) {\n floorShortfallByEntity[entityId] = shortfall;\n totalFloorShortfall += shortfall;\n }\n }\n }\n\n const reservedIds = new Set<string>();\n const reserved: Array<{ row: CandidateRow; kwScore: number }> = [];\n if (totalFloorShortfall > 0) {\n for (const [entityId, shortfall] of Object.entries(floorShortfallByEntity)) {\n const entityOmitted: Array<{ row: CandidateRow; kwScore: number }> = [];\n for (const row of candidateRows) {\n if (scoredIds.has(row.id) || reservedIds.has(row.id)) continue;\n if (row.entity_id !== entityId) continue;\n const kwScore = miniSearchScores?.get(row.id) ?? 0;\n entityOmitted.push({ row, kwScore });\n }\n // Sort within the floored entity by kwScore desc with the\n // shared tie-break. Within a single entity the kwScore\n // pool is small, so a full sort is fine here.\n entityOmitted.sort((a, b) => this._compareScoredRows(\n { id: a.row.id, score: a.kwScore, updated_at: a.row.updated_at, access_count: a.row.access_count },\n { id: b.row.id, score: b.kwScore, updated_at: b.row.updated_at, access_count: b.row.access_count },\n ));\n for (let i = 0; i < Math.min(shortfall, entityOmitted.length); i++) {\n reserved.push(entityOmitted[i]);\n reservedIds.add(entityOmitted[i].row.id);\n }\n }\n }\n\n const isHybrid = weight !== undefined && weight < 1;\n\n if (reserved.length > 0) {\n if (isHybrid) {\n for (const { row, kwScore } of reserved) {\n scored.push({\n id: row.id,\n entity_id: row.entity_id,\n score: (1 - weight) * kwScore,\n updated_at: row.updated_at,\n access_count: row.access_count,\n });\n }\n } else {\n for (const { row } of reserved) {\n scored.push({\n id: row.id,\n entity_id: row.entity_id,\n score: -2,\n updated_at: row.updated_at,\n access_count: row.access_count,\n });\n }\n }\n }\n\n // Compute the backfill budget AFTER the reserved rows have been\n // pushed into `scored`, so pure semantic fills only the slots the\n // reservation left over rather than over-materializing by\n // `reserved.length`. Hybrid keeps a global top-K of `maxResults`\n // selected by keyword score, unchanged.\n const maxBackfill = isHybrid\n ? maxResults\n : Math.max(0, maxResults - scored.length);\n\n if (maxBackfill > 0) {\n if (isHybrid) {\n // Hybrid mode: prioritize by keyword score using O(N log K) top-K selection\n // instead of O(N log N) full sort, since K (maxBackfill) is typically << N.\n const topK: Array<{ row: CandidateRow; kwScore: number }> = [];\n\n for (const row of candidateRows) {\n if (scoredIds.has(row.id) || reservedIds.has(row.id)) continue;\n const kwScore = miniSearchScores?.get(row.id) ?? 0;\n const candidate = { row, kwScore };\n\n if (topK.length < maxBackfill) {\n // Array not full yet - insert in sorted position (descending order)\n let insertIdx = topK.length;\n for (let i = 0; i < topK.length; i++) {\n const cmp = this._compareScoredRows(\n {\n id: candidate.row.id,\n score: candidate.kwScore,\n updated_at: candidate.row.updated_at,\n access_count: candidate.row.access_count,\n },\n {\n id: topK[i].row.id,\n score: topK[i].kwScore,\n updated_at: topK[i].row.updated_at,\n access_count: topK[i].row.access_count,\n }\n );\n if (cmp < 0) {\n insertIdx = i;\n break;\n }\n }\n topK.splice(insertIdx, 0, candidate);\n } else {\n const cmpWorst = this._compareScoredRows(\n {\n id: candidate.row.id,\n score: candidate.kwScore,\n updated_at: candidate.row.updated_at,\n access_count: candidate.row.access_count,\n },\n {\n id: topK[maxBackfill - 1].row.id,\n score: topK[maxBackfill - 1].kwScore,\n updated_at: topK[maxBackfill - 1].row.updated_at,\n access_count: topK[maxBackfill - 1].row.access_count,\n }\n );\n if (cmpWorst < 0) {\n // Found better candidate than current worst - replace worst and re-insert\n let insertIdx = maxBackfill - 1;\n for (let i = 0; i < topK.length; i++) {\n const cmp = this._compareScoredRows(\n {\n id: candidate.row.id,\n score: candidate.kwScore,\n updated_at: candidate.row.updated_at,\n access_count: candidate.row.access_count,\n },\n {\n id: topK[i].row.id,\n score: topK[i].kwScore,\n updated_at: topK[i].row.updated_at,\n access_count: topK[i].row.access_count,\n }\n );\n if (cmp < 0) {\n insertIdx = i;\n break;\n }\n }\n topK.splice(insertIdx, 0, candidate);\n topK.pop(); // Remove worst element\n }\n }\n }\n\n for (const { row, kwScore } of topK) {\n scored.push({\n id: row.id,\n entity_id: row.entity_id,\n score: (1 - weight) * kwScore,\n updated_at: row.updated_at,\n access_count: row.access_count,\n });\n }\n } else {\n // Pure semantic: all omitted rows share score -2.\n // Tie-break omitted rows deterministically before truncating.\n const omitted: Array<{ id: string; entity_id: string; score: number; updated_at: number | null; access_count: number | null }> = [];\n for (const row of candidateRows) {\n if (scoredIds.has(row.id) || reservedIds.has(row.id)) continue;\n omitted.push({ id: row.id, entity_id: row.entity_id, score: -2, updated_at: row.updated_at, access_count: row.access_count });\n }\n if (omitted.length > 0) {\n this._tieBreakSort(omitted);\n scored.push(...omitted.slice(0, maxBackfill));\n }\n }\n }\n } catch (rankerErr) {\n // `rankerErr instanceof Error` invokes the getPrototypeOf\n // trap on rankerErr. A hostile VectorRanker plugin could\n // return one whose trap rejects — treat as non-Error and\n // wrap in a synthetic Error so the fallback callback still\n // receives an Error instance.\n let isErrorLike = false;\n try {\n isErrorLike = rankerErr instanceof Error;\n } catch {\n // hostile Proxy — fall through\n }\n // `String(rankerErr)` invokes the `toString` /\n // `Symbol.toPrimitive` trap on rankerErr — a hostile Proxy\n // whose trap rejects would throw out of this catch and tear\n // down the retrieval. Delegate to the hardened\n // `safeErrorToString` helper (converges on the static\n // `[unstringifiable error]` marker on throw) to honor the\n // non-throwing contract this guard exists to provide.\n const rankerError = isErrorLike ? (rankerErr as Error) : new Error(safeErrorToString(rankerErr));\n const policy = this.options.vectorRankerFallback ?? 'js-cosine';\n\n this.options.onVectorRankerFallback?.({\n error: this._sanitizeRankerError(rankerError),\n policy,\n });\n\n if (policy === 'throw') {\n rankerShouldRethrow = true;\n throw rankerError;\n } else if (policy === 'js-cosine') {\n // If embeddings were skipped (vectorRanker was configured), fetch them now for fallback\n let fallbackRows = candidateRows;\n if (fallbackRows && fallbackRows.length > 0 && !('embedding_blob' in fallbackRows[0])) {\n const rowIds = fallbackRows.map(r => r.id);\n const embeddingRows = await this.entryRepo.findEmbeddingsByIds(rowIds);\n const embeddingsMap = new Map(embeddingRows.map(row => [row.id, row]));\n fallbackRows = fallbackRows.map(r => ({\n ...r,\n embedding_blob: embeddingsMap.get(r.id)?.embedding_blob ?? null,\n embedding: embeddingsMap.get(r.id)?.embedding ?? null,\n })) as ReadCandidateRowWithEmbeddings[];\n }\n scored = await this.searchService.rankSemantic({\n entityId: entityCacheKey,\n queryVec,\n candidateRows: fallbackRows as ReadCandidateRowWithEmbeddings[],\n weight,\n miniSearchScores,\n populateCache,\n limit: fallbackRows.length,\n skipSort: true, // read() re-sorts after applying tier weights\n });\n } else if (policy === 'keyword') {\n // Fall back to keyword-only results from MiniSearch. When\n // preFilterLimit was active, candidateRows was already\n // narrowed to the pre-filtered IDs (§3.5); restrict this\n // keyword call to that same set so a floor cannot resurrect\n // a fact excluded by preFilterLimit.\n //\n // Active floors force full materialization here too, mirroring\n // the JS-cosine path's `jsCosineNeedsTierSort` widening and\n // the ordinary keyword fallback's `hasActiveFloors` widening:\n // selectWithFloors can only reserve a starved entity's rows\n // if they survive this keyword call's oversampling limit, and\n // a pre-truncated top-K is exactly the starved window the\n // floor exists to correct.\n const hasActiveFloorsKeywordFallback = sanitizedTierFloors !== undefined &&\n Object.values(sanitizedTierFloors).some(f => f > 0);\n const keywordOversampledLimit = hasActiveFloorsKeywordFallback\n ? Number.MAX_SAFE_INTEGER\n : padLimit(Math.max(maxResults * 2, maxResults + 50));\n const preFilteredIds = effectivePreFilterLimit !== undefined\n ? new Set((candidateRows as ReadCandidateRowMetadata[]).map(r => r.id))\n : undefined;\n const keywordResults = this.searchService.searchKeyword(trimmedQuery, scoredEntityIds, keywordOversampledLimit);\n const topResults = preFilteredIds === undefined\n ? keywordResults\n : keywordResults.filter(r => preFilteredIds.has(r.id));\n const topResultIds = new Set(topResults.map(r => r.id));\n const candidateMap = new Map(candidateRows.filter(r => topResultIds.has(r.id)).map(row => [row.id, row]));\n scored = topResults.map(result => {\n const metadata = candidateMap.get(result.id);\n const entityForScore = metadata?.entity_id\n ?? (result as unknown as { entity_id: string }).entity_id\n ?? '';\n return {\n id: result.id,\n entity_id: entityForScore,\n score: result.score ?? 0,\n access_count: metadata?.access_count ?? null,\n updated_at: metadata?.updated_at ?? null,\n };\n });\n } else {\n // policy === 'empty'\n scored = [];\n }\n\n if (this.options.propagateRankerFailureToRetrievalFallback) {\n const mirrored = new Error('Vector ranker failed, falling back', {\n cause: this._sanitizeRankerError(rankerErr),\n });\n pendingRankerFallbackError = mirrored;\n }\n }\n } else {\n // Use in-process JS cosine similarity\n // At this point candidateRows must have embeddings (we fetched them because vectorRanker is not configured)\n // Materialize all candidates only when tier weights will actually change ranking —\n // i.e., at least one entity has a weight other than 1. A no-op weights object\n // (all values === 1, or empty after sanitization) preserves the hot-path behavior.\n // Active floors force materialization too: selectWithFloors can only reserve a\n // starved entity's rows if they survive the ranker's own limit, and a pre-truncated\n // top-K is exactly the starved window the floor exists to correct.\n const jsCosineNeedsTierSort = (sanitizedTierWeights !== undefined &&\n Object.values(sanitizedTierWeights).some(w => w !== 1)) ||\n (sanitizedTierFloors !== undefined &&\n Object.values(sanitizedTierFloors).some(f => f > 0));\n scored = await this.searchService.rankSemantic({\n entityId: entityCacheKey,\n queryVec,\n candidateRows: candidateRows as ReadCandidateRowWithEmbeddings[],\n weight,\n miniSearchScores,\n populateCache,\n limit: jsCosineNeedsTierSort ? candidateRows.length : maxResults,\n skipSort: jsCosineNeedsTierSort, // read() re-sorts after applying tier weights\n });\n }\n\n if (draftPad > 0) scored = scored.filter((s) => !draftIds.has(s.id));\n\n if (scored.length > 0) {\n // Apply tier weights before global sort and slice\n scored = scored.map(row => ({\n ...row,\n score: applyTierWeight(row.score, row.entity_id, sanitizedTierWeights),\n }));\n\n // Re-apply tie-break sorting after tier-weight application (applies to all paths including\n // vectorRankerFallback='keyword': applyTierWeight mutates scores so MiniSearch ordering is no longer valid)\n this._tieBreakSort(scored);\n\n // Phase 2: fetch full rows only for the top results\n const selectedScored = selectWithFloors(scored, sanitizedTierFloors, maxResults);\n const topIds = selectedScored.map(s => s.id);\n\n // Capture scores for exposure in metadata\n if (exposeMetadata && trimmedQuery) {\n scoreByFactId = new Map(selectedScored.map(s => [s.id, Number.isFinite(s.score) ? s.score : 0]));\n }\n\n if (topIds.length > 0) {\n const facts2 = await this._hydrateFactsByIds(topIds, entityIds);\n\n // Hydration can return fewer rows than ranked IDs when rows were concurrently\n // soft-deleted or filtered by deleted_at before phase 2 hydration completes.\n if (facts2.length < topIds.length) {\n const hydrationById = new Set(facts2.map(f => f.id));\n const missingIds = topIds.filter(id => !hydrationById.has(id));\n const missingCount = missingIds.length;\n const sample = missingIds.slice(0, 5);\n const sampleSuffix = sample.length > 0\n ? ` Missing ID sample: ${sample.join(', ')}${missingIds.length > sample.length ? ', ...' : ''}.`\n : '';\n const error = new Error(\n `Phase 2 fact hydration returned ${missingCount} fewer row(s) than ranked IDs. ` +\n `Rows may have been concurrently soft-deleted or filtered by deleted_at during hydration, ` +\n `or vector ranker output may include IDs that do not exist in requested entities.` +\n sampleSuffix\n );\n this.options.onRetrievalFallback?.(error);\n }\n facts = facts2;\n }\n // Ranker path completed — notify of any prior fallback now that hydration is done.\n // Fires outside the topIds.length>0 guard since scored.length>0 && maxResults>0\n // means topIds is always non-empty here, but the notification is harmless either way.\n if (pendingRankerFallbackError) {\n this.options.onRetrievalFallback?.(pendingRankerFallbackError);\n pendingRankerFallbackError = undefined;\n }\n usedEmbed = true;\n } else {\n // Empty scored results (ranker returned no matches)\n if (pendingRankerFallbackError) {\n this.options.onRetrievalFallback?.(pendingRankerFallbackError);\n pendingRankerFallbackError = undefined;\n }\n usedEmbed = true;\n }\n } // closes the candidateRows !== null else block\n } catch (err) {\n // `err instanceof Error` invokes the getPrototypeOf trap on err.\n // A hostile Proxy (e.g. from a VectorRanker plugin or a wrapped\n // inner-call result) whose trap rejects must not throw out of\n // this catch — it would tear down the entire retrieval operation.\n let isErrorLike = false;\n try {\n isErrorLike = err instanceof Error;\n } catch {\n // hostile Proxy — fall through\n }\n // Narrowed view: only valid when `isErrorLike` is true (guaranteed\n // by the try/catch above). Cast captures that runtime invariant\n // for the typechecker; the runtime is already proven correct.\n // `String(err)` invokes the `toString` / `Symbol.toPrimitive` trap\n // on err — delegate to the hardened `safeErrorToString` helper\n // so a hostile Proxy whose trap rejects cannot escape this catch.\n const error = isErrorLike ? (err as Error) : new Error(safeErrorToString(err));\n if (rankerShouldRethrow) {\n throw error;\n }\n // If Phase 2 failed and there's a pending ranker error, include it as cause\n if (pendingRankerFallbackError) {\n try {\n (error as any).cause = pendingRankerFallbackError;\n } catch {\n // Hostile or frozen error object — the assignment threw, so the\n // ranker diagnostic would otherwise be silently dropped. Surface\n // it as its own fallback notification instead of losing it.\n this.options.onRetrievalFallback?.(pendingRankerFallbackError);\n }\n pendingRankerFallbackError = undefined;\n }\n // Always notify of Phase 2 errors (ranker error attached as cause if present)\n this.options.onRetrievalFallback?.(error);\n }\n }\n\n if (!usedEmbed && scoredEntityIds.length > 0) {\n // embed absent or threw — fall back to MiniSearch with tier weight application.\n // Active floors force full materialization: selectWithFloors can only\n // reserve a starved entity's rows if they survive the keyword\n // oversampling limit, and a pre-truncated top-K is exactly the starved\n // window the floor exists to correct. Mirrors the JS-cosine path's\n // `jsCosineNeedsTierSort` widening.\n const hasActiveFloors = sanitizedTierFloors !== undefined &&\n Object.values(sanitizedTierFloors).some(f => f > 0);\n const fallbackOversampledLimit = hasActiveFloors\n ? Number.MAX_SAFE_INTEGER\n : padLimit(Math.max(maxResults * 2, maxResults + 50));\n const results = this.searchService\n .searchKeyword(trimmedQuery, scoredEntityIds, fallbackOversampledLimit)\n .filter((r) => !draftIds.has(r.id as string));\n const candidates = results.map(r => ({\n id: r.id as string,\n entity_id: (r as unknown as { entity_id: string }).entity_id,\n score: applyTierWeight(r.score ?? 0, (r as unknown as { entity_id: string }).entity_id, sanitizedTierWeights),\n updated_at: null as number | null,\n access_count: null as number | null,\n }));\n this._tieBreakSort(candidates);\n const topCandidates = selectWithFloors(candidates, sanitizedTierFloors, maxResults);\n const topIds = topCandidates.map(c => c.id);\n if (topIds.length > 0) {\n facts = await this._hydrateFactsByIds(topIds, entityIds);\n if (exposeMetadata) {\n scoreByFactId = new Map(topCandidates.map(c => [c.id, Number.isFinite(c.score) ? c.score : 0]));\n }\n }\n }\n\n if (facts.length > 0) {\n const ids = facts.map(f => f.id);\n const now = Date.now();\n await this.entryRepo.trackAccess(ids, now);\n }\n } else {\n // Empty query: use global recency ordering, ignore tier weights.\n // Pass `excludeDrafts` opts only when true; the default path keeps its\n // 2-arg call signature for callers that prefer the strict form.\n facts = excludeDrafts\n ? await this.entryRepo.findRecentByEntityIds(entityIds, maxResults, undefined, { excludeDrafts: true })\n : await this.entryRepo.findRecentByEntityIds(entityIds, maxResults);\n }\n\n const eventsLimit = Math.min(10 * entityIds.length, 100);\n const [tasks, events] = await Promise.all([\n this.taskRepo.findAllPending(entityIds as string[], entityIds.length === 1 ? undefined : Math.min(20 * entityIds.length, 200)),\n entityIds.length === 1\n ? this.eventRepo.getRecent(entityIds[0], eventsLimit)\n : this.eventRepo.getRecentForEntities(entityIds as string[], eventsLimit),\n ]);\n\n // Build factScores from captured scores\n let factScores: Record<string, number> | undefined;\n if (exposeMetadata && trimmedQuery && scoreByFactId) {\n factScores = Object.fromEntries(facts.map(fact => [fact.id, scoreByFactId!.get(fact.id) ?? 0]));\n }\n\n const bundle: MemoryBundle = { facts, tasks, events: events.reverse(), edges: [] };\n\n if (exposeMetadata) {\n bundle.metadata = { query, entityIds };\n if (sanitizedTierWeights && Object.keys(sanitizedTierWeights).length > 0) bundle.metadata.tierWeights = sanitizedTierWeights;\n if (sanitizedTierFloors && Object.keys(sanitizedTierFloors).length > 0) bundle.metadata.tierFloors = sanitizedTierFloors;\n if (factScores && Object.keys(factScores).length > 0) bundle.factScores = factScores;\n }\n\n return bundle;\n }\n\n /**\n * Returns entity IDs that will participate in scored retrieval.\n * Excludes zero-weight entities unless includeZeroWeightEntities is true.\n */\n private _filterScoredEntities(\n entityIds: readonly string[],\n sanitizedTierWeights: Record<string, number> | undefined,\n includeZeroWeightEntities?: boolean,\n ): string[] {\n return entityIds.filter(id => {\n const w = sanitizedTierWeights?.[id] ?? 1;\n return includeZeroWeightEntities === true || w !== 0;\n });\n }\n\n /**\n * Stable tie-break sort: score desc → access_count desc → updated_at desc → id asc.\n */\n private _tieBreakSort<T extends { id: string; score: number; updated_at?: number | null; access_count?: number | null }>(items: T[]): void {\n items.sort((a, b) => this._compareScoredRows(a, b));\n }\n\n private _withoutDrafts<T extends { id: string }>(rows: T[], draftIds: ReadonlySet<string>): T[] {\n return draftIds.size === 0 ? rows : rows.filter((row) => !draftIds.has(row.id));\n }\n\n /**\n * Comparator for score + deterministic tie-break fields.\n * Negative return means \"a ranks ahead of b\" for descending score order.\n */\n private _compareScoredRows(\n a: { id: string; score: number; updated_at?: number | null; access_count?: number | null },\n b: { id: string; score: number; updated_at?: number | null; access_count?: number | null },\n ): number {\n const scoreDiff = b.score - a.score;\n // isNaN guard: -Infinity - (-Infinity) = NaN; fall through to tie-break\n if (!Number.isNaN(scoreDiff) && scoreDiff !== 0) return scoreDiff;\n const accessCountDiff = (b.access_count ?? 0) - (a.access_count ?? 0);\n if (accessCountDiff !== 0) return accessCountDiff;\n const updatedAtDiff = (b.updated_at ?? 0) - (a.updated_at ?? 0);\n if (updatedAtDiff !== 0) return updatedAtDiff;\n return a.id.localeCompare(b.id);\n }\n\n /**\n * Hydrate full facts by ID. Pass scopedEntityIds to restrict to requested namespaces in SQL\n * (defense-in-depth against a rogue VectorRanker returning cross-entity IDs).\n */\n private async _hydrateFactsByIds(ids: readonly string[], scopedEntityIds?: readonly string[], tx?: SQLiteAdapter): Promise<WikiFact[]> {\n return this.entryRepo.findByIds(ids, scopedEntityIds, tx);\n }\n\n private _sanitizeRankerError(err: unknown): Error {\n return sanitizeRankerError(err, this.options.sanitizeRankerErrors);\n }\n\n /**\n * Delegate semantic ranking to the injected VectorRanker.\n * Caller should pass an oversampledLimit to preserve recall after re-ranking.\n * Returns scored results ready for hybrid blending and tie-break sorting.\n */\n private async _rankWithVectorRanker(args: {\n entityId: string;\n queryVec: Float32Array | number[];\n candidateIds: readonly string[] | undefined;\n candidateRows: ReadCandidateRowMetadata[];\n weight: number | undefined;\n miniSearchScores: Map<string, number> | undefined;\n limit: number;\n }): Promise<Array<{ id: string; entity_id: string; score: number }>> {\n const { entityId, candidateIds, candidateRows, weight, miniSearchScores, limit } = args;\n\n const ranker = this.options.vectorRanker;\n if (!ranker) {\n throw new Error('vectorRanker not configured');\n }\n\n const queryVecCopy = args.queryVec instanceof Float32Array\n ? args.queryVec.slice()\n : Array.from(args.queryVec);\n\n const rankerResults = await ranker.rankBySimilarity({\n entityId,\n queryVec: queryVecCopy,\n candidateIds,\n limit,\n });\n\n // Normalize ranker output: filter to allowed ids, drop non-finite scores, deduplicate\n // Stop collecting once limit valid results are found to protect against huge result sets\n const allowedIds = new Set(candidateRows.map(row => row.id));\n const seen = new Set<string>();\n const normalized: typeof rankerResults = [];\n\n for (const r of rankerResults) {\n if (normalized.length >= limit) break; // Early termination once limit reached\n if (seen.has(r.id)) continue;\n if (allowedIds && !allowedIds.has(r.id)) continue;\n if (!Number.isFinite(r.semanticScore)) continue;\n seen.add(r.id);\n normalized.push(r);\n }\n\n const entityIdByCandidateId = new Map(candidateRows.map(row => [row.id, row.entity_id]));\n\n // Convert ranker results to scored format, applying hybrid blending if weight is set\n const scored = normalized.map(r => {\n let score = r.semanticScore;\n if (weight !== undefined) {\n // Hybrid blending: floor semantic score at 0 for predictable weighted sum (no upper clamp)\n const kwScore = miniSearchScores?.get(r.id) ?? 0;\n score = weight * Math.max(0, r.semanticScore) + (1 - weight) * kwScore;\n }\n return {\n id: r.id,\n entity_id: entityIdByCandidateId.get(r.id)!, // allowedIds filter above guarantees membership\n score,\n };\n });\n\n // Caller handles backfill, metadata attachment, tie-break sorting, and final slice\n return scored;\n }\n}\n","import type { SQLiteAdapter } from '../types';\nimport type { WikiOptions, WikiEvent } from '../types';\nimport { WikiBusyError } from '../types';\nimport type { EntryRepository } from '../repositories/EntryRepository';\nimport type { EventRepository } from '../repositories/EventRepository';\nimport type { MetadataRepository } from '../repositories/MetadataRepository';\nimport type { JobManager } from './JobManager';\nimport type { MaintenanceService } from './MaintenanceService';\nimport { generateId } from '../utils/ids';\nimport { clip } from '../utils/pure';\nimport { emitDiagnostic } from '../utils/diagnostics';\n\nexport class WriteService {\n constructor(\n private db: SQLiteAdapter,\n private options: WikiOptions,\n private entryRepo: EntryRepository,\n private eventRepo: EventRepository,\n private metadataRepo: MetadataRepository,\n private jobManager: JobManager,\n private maintenanceService: MaintenanceService,\n ) {}\n\n async write(entityId: string, event: Omit<WikiEvent, 'id' | 'entity_id' | 'created_at'>): Promise<void> {\n if (typeof entityId !== 'string' || entityId.length === 0 || entityId.length > 200 || entityId.includes('\\0')) {\n throw new TypeError(\n `Invalid entityId: must be a non-empty string at most 200 chars with no null bytes; got ${JSON.stringify(entityId)}.`,\n );\n }\n if (event === null || typeof event !== 'object' || Array.isArray(event)) {\n throw new TypeError('Invalid event: must be a non-null object.');\n }\n if (typeof event.summary !== 'string') {\n throw new TypeError('Invalid event.summary: must be a string.');\n }\n const summary = clip(event.summary, 4000);\n\n let relatedEntryId: string | null = null;\n const rawRelatedEntryId = event.related_entry_id;\n if (rawRelatedEntryId != null && rawRelatedEntryId !== '') {\n if (\n typeof rawRelatedEntryId !== 'string' ||\n rawRelatedEntryId.length > 200 ||\n rawRelatedEntryId.includes('\\0')\n ) {\n relatedEntryId = null;\n } else {\n const existing = await this.entryRepo.findByIds([rawRelatedEntryId], [entityId]);\n relatedEntryId = existing.length > 0 ? rawRelatedEntryId : null;\n }\n }\n\n const id = generateId('evt_');\n const now = Date.now();\n\n let eventType = event.event_type;\n if (!['observation', 'decision', 'action', 'outcome'].includes(eventType)) {\n eventType = 'observation';\n }\n\n const newEvent: WikiEvent = {\n id,\n entity_id: entityId,\n event_type: eventType,\n summary,\n related_entry_id: relatedEntryId,\n created_at: now,\n };\n\n let shouldRunLibrarian = false;\n let librarianCount = 0;\n let prevMemoryCheckpoint = 0;\n let eventCount = 0;\n\n await this.db.withTransactionAsync(async (tx) => {\n await this.eventRepo.add(newEvent, tx);\n\n const threshold = this.options.config?.autoLibrarianThreshold || 20;\n\n const [count, cp] = await Promise.all([\n this.eventRepo.count(entityId, tx),\n this.metadataRepo.getCheckpoint(entityId, tx),\n ]);\n eventCount = count;\n\n let memoryCheckpoint = cp.memory ?? 0;\n if (memoryCheckpoint > count) memoryCheckpoint = 0;\n\n if (count - memoryCheckpoint >= threshold) {\n if (!this.jobManager.isBlocked('librarian', entityId)) {\n shouldRunLibrarian = true;\n librarianCount = count;\n prevMemoryCheckpoint = memoryCheckpoint;\n await this.metadataRepo.updateCheckpoint(entityId, { memory: count }, tx);\n }\n }\n });\n\n if (shouldRunLibrarian) {\n try {\n this.jobManager.acquireLock('librarian', entityId);\n const stage: { job: 'librarian' | 'heal' } = { job: 'librarian' };\n this.runLibrarianThenMaybeHeal(entityId, librarianCount, prevMemoryCheckpoint, stage)\n .catch((err: unknown) => {\n console.error(err);\n this.reportBackgroundFailure(entityId, stage.job);\n })\n .finally(() => {\n this.jobManager.releaseLock('librarian', entityId);\n });\n } catch (e) {\n if (!(e instanceof WikiBusyError)) throw e;\n await this.metadataRepo.updateCheckpoint(entityId, { memory: prevMemoryCheckpoint }, this.db);\n }\n } else if (!this.jobManager.isBlocked('librarian', entityId)) {\n // Auto-heal is evaluated on every write, not only on writes that also\n // trigger a librarian pass. doRunHeal is bounded to HEAL_BATCH_SIZE\n // candidates (#67) and a non-converged pass deliberately holds its\n // checkpoint back, so the gap stays above autoHealThreshold; gating the\n // retry on a librarian pass would stall a partial sweep until the next\n // librarian threshold crossing (another autoLibrarianThreshold events),\n // or forever if no further librarian pass runs.\n //\n // heal and librarian can overlap (deliberate mutex split in\n // JobManager.acquireLock). This check only reduces redundant passes — a\n // librarian pass already calls maybeRunHeal when it finishes, so losing\n // the race costs a duplicate pass, not correctness. Correctness rests on\n // heal's dedupe read being inside its transaction (#69).\n // tryAcquireAutoHealLock inside maybeRunHeal prevents a burst of writes\n // from stacking passes.\n this.maybeRunHeal(entityId, eventCount).catch((err: unknown) => {\n console.error(err);\n this.reportBackgroundFailure(entityId, 'heal');\n });\n }\n }\n\n private async runLibrarianThenMaybeHeal(entityId: string, currentEventCount: number, prevCheckpoint: number, stage: { job: 'librarian' | 'heal' }): Promise<void> {\n try {\n await this.maintenanceService.doRunLibrarian(entityId, undefined, 'auto');\n // Only advance checkpoint after successful librarian run\n await this.metadataRepo.updateCheckpoint(entityId, { memory: currentEventCount }, this.db);\n } catch (e) {\n // Rollback checkpoint on failure so events can be retried\n await this.metadataRepo.updateCheckpoint(entityId, { memory: prevCheckpoint }, this.db);\n throw e;\n }\n\n stage.job = 'heal';\n await this.maybeRunHeal(entityId, currentEventCount);\n }\n\n /**\n * Run one bounded auto-heal pass if the heal checkpoint has fallen\n * `autoHealThreshold` events behind. Called after every write (see\n * {@link write}) so a partial pass retries on the next write.\n */\n private async maybeRunHeal(entityId: string, currentEventCount: number): Promise<void> {\n const autoHealThreshold = this.options.config?.autoHealThreshold || 100;\n\n const cp = await this.metadataRepo.getCheckpoint(entityId, this.db);\n let healCheckpoint = cp.heal ?? 0;\n if (healCheckpoint > currentEventCount) healCheckpoint = 0;\n\n const shouldRunHeal = currentEventCount - healCheckpoint >= autoHealThreshold;\n\n if (shouldRunHeal && this.jobManager.tryAcquireAutoHealLock(entityId)) {\n try {\n const result = await this.maintenanceService.doRunHeal(entityId, { trigger: 'auto' });\n // Advance only when the pass converged. doRunHeal is bounded to\n // HEAL_BATCH_SIZE candidates (#67); advancing unconditionally would cap\n // auto-heal at one batch per autoHealThreshold events and leave most of\n // a large corpus never auto-healed. Held back, the checkpoint gap stays\n // above the threshold, so the next write runs another bounded pass —\n // cost per write stays bounded while the corpus still converges.\n //\n // Sits inside the try, after the call: on a throw the checkpoint is not\n // advanced, exactly as before this change.\n if (result.remaining === 0) {\n await this.metadataRepo.updateCheckpoint(entityId, { heal: currentEventCount }, this.db);\n }\n } finally {\n this.jobManager.releaseLock('heal', entityId);\n }\n }\n }\n\n private reportBackgroundFailure(entityId: string, job: 'librarian' | 'heal'): void {\n emitDiagnostic(this.options, {\n code: 'background_job_failed', operation: job, trigger: 'auto', entityId,\n detail: { reason: 'unhandled_rejection' },\n });\n }\n}\n"]}