@equationalapplications/core-llm-wiki 7.7.7 → 7.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +94 -0
- package/dist/{chunk-46X3HO77.mjs → chunk-J2TWKOEE.mjs} +1190 -185
- package/dist/chunk-J2TWKOEE.mjs.map +1 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1862 -285
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +606 -35
- package/dist/index.mjs.map +1 -1
- package/dist/{testing-BIFNLUva.d.mts → testing-Kb1uVj1E.d.mts} +594 -7
- package/dist/{testing-BIFNLUva.d.ts → testing-Kb1uVj1E.d.ts} +594 -7
- package/dist/testing.d.mts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +1139 -197
- package/dist/testing.js.map +1 -1
- package/dist/testing.mjs +1 -1
- package/package.json +2 -2
- package/dist/chunk-46X3HO77.mjs.map +0 -1
|
@@ -214,6 +214,10 @@ interface HealResult {
|
|
|
214
214
|
remaining: number;
|
|
215
215
|
/** Heal candidates inside the recheck cooldown. */
|
|
216
216
|
deferred: number;
|
|
217
|
+
/** Present when a token budget stopped the pass early (spec §10.5). Unattempted candidates stay eligible. */
|
|
218
|
+
budgetStop?: {
|
|
219
|
+
requiredEstimate: number;
|
|
220
|
+
};
|
|
217
221
|
}
|
|
218
222
|
/**
|
|
219
223
|
* Opt-in evidence check for LLM-authored facts (spec §6). Default off: 7.x
|
|
@@ -232,6 +236,19 @@ interface GroundingConfig {
|
|
|
232
236
|
/** Characters retained per quote. Default 300. */
|
|
233
237
|
maxEvidenceChars?: number;
|
|
234
238
|
}
|
|
239
|
+
interface LibrarianGateConfig {
|
|
240
|
+
/** Neighbours fetched per candidate. Default 5. */
|
|
241
|
+
k?: number;
|
|
242
|
+
/** Cosine at or above which (with title Jaccard ≥ FUZZY_THRESHOLD) a candidate is a duplicate. Default 0.89 (calibrated against the 30 supersession scenarios). */
|
|
243
|
+
dupThreshold?: number;
|
|
244
|
+
/** Best-neighbour cosine below which a candidate is novel. Default 0.30 (calibrated against the 30 supersession scenarios). */
|
|
245
|
+
novelThreshold?: number;
|
|
246
|
+
}
|
|
247
|
+
/** `'legacy'` is the 7.x add-only librarian. `'ops'` is the spec §5.1 / §5.3 dispatcher. */
|
|
248
|
+
interface LibrarianConfig {
|
|
249
|
+
strategy?: 'legacy' | 'ops';
|
|
250
|
+
gate?: LibrarianGateConfig;
|
|
251
|
+
}
|
|
235
252
|
interface WikiConfig {
|
|
236
253
|
/**
|
|
237
254
|
* Prefix applied to every SQL table/index/trigger name. Must match
|
|
@@ -245,6 +262,12 @@ interface WikiConfig {
|
|
|
245
262
|
maxFtsResults?: number;
|
|
246
263
|
pruneEventsAfter?: number;
|
|
247
264
|
pruneRetainSoftDeletedFor?: number;
|
|
265
|
+
/**
|
|
266
|
+
* Days after `valid_to` before `runPrune` soft-deletes an expired or
|
|
267
|
+
* superseded fact (the soft-delete retention then hard-deletes it).
|
|
268
|
+
* Default null = keep history forever.
|
|
269
|
+
*/
|
|
270
|
+
pruneSupersededAfter?: number | null;
|
|
248
271
|
autoLibrarianThreshold?: number;
|
|
249
272
|
autoHealThreshold?: number;
|
|
250
273
|
orphanAfterDays?: number | null;
|
|
@@ -305,6 +328,21 @@ interface WikiConfig {
|
|
|
305
328
|
excludeDrafts?: boolean;
|
|
306
329
|
/** Evidence check for LLM-authored facts (spec §6). Default off. */
|
|
307
330
|
grounding?: GroundingConfig;
|
|
331
|
+
/** Emit an `llm_usage` diagnostic after every LLM text call. Default false. */
|
|
332
|
+
reportLlmUsage?: boolean;
|
|
333
|
+
/** Librarian strategy selection (spec 2026-09-29 §5.1). Default `{ strategy: 'legacy' }`. */
|
|
334
|
+
librarian?: LibrarianConfig;
|
|
335
|
+
/**
|
|
336
|
+
* `'auto'` (default): write() starts librarian/heal in the background when
|
|
337
|
+
* thresholds are crossed. `'deferred'`: write() only records the event; the
|
|
338
|
+
* host runs `runPendingMaintenance()` (spec 2026-09-29 §6). Pair with
|
|
339
|
+
* `librarian: { strategy: 'ops' }`: the legacy strategy reads only the
|
|
340
|
+
* newest 50 events per pass and advances the watermark past them, so a
|
|
341
|
+
* deferred backlog larger than that is never extracted.
|
|
342
|
+
*/
|
|
343
|
+
maintenance?: 'auto' | 'deferred';
|
|
344
|
+
/** `'auto'` mode only: also trigger the librarian when pending event text reaches ~this many tokens (chars/4). */
|
|
345
|
+
autoLibrarianTokenThreshold?: number;
|
|
308
346
|
}
|
|
309
347
|
interface ReadOptions {
|
|
310
348
|
maxResults?: number;
|
|
@@ -351,6 +389,18 @@ interface ReadOptions {
|
|
|
351
389
|
* Resolves call → `WikiConfig.excludeDrafts` → false.
|
|
352
390
|
*/
|
|
353
391
|
excludeDrafts?: boolean;
|
|
392
|
+
/**
|
|
393
|
+
* Valid-time snapshot (epoch ms): return facts live at this instant using
|
|
394
|
+
* current knowledge (spec §4.2). Omitted ⇒ current facts only.
|
|
395
|
+
* Throws `WikiInvalidReadOptions('asOf', …)` when not a finite number >= 0.
|
|
396
|
+
*/
|
|
397
|
+
asOf?: number;
|
|
398
|
+
/**
|
|
399
|
+
* Pack facts into roughly this many tokens (chars/4 estimate), most valuable
|
|
400
|
+
* per token first; the top fact is always kept (truncated if needed).
|
|
401
|
+
* Tasks and events are not affected. Spec 2026-09-29 §7.1.
|
|
402
|
+
*/
|
|
403
|
+
tokenBudget?: number;
|
|
354
404
|
}
|
|
355
405
|
interface WikiFact {
|
|
356
406
|
id: string;
|
|
@@ -425,6 +475,14 @@ interface WikiFact {
|
|
|
425
475
|
* `mapRowToFact` / `mapRowToTask`.
|
|
426
476
|
*/
|
|
427
477
|
trustTier?: 'unverified' | 'machine-confirmed' | 'human-reviewed';
|
|
478
|
+
/** Epoch ms the fact became true in the world. Absent ⇒ since `created_at`. */
|
|
479
|
+
valid_from?: number | null;
|
|
480
|
+
/** Epoch ms the fact stopped being true (exclusive). Absent ⇒ open-ended. */
|
|
481
|
+
valid_to?: number | null;
|
|
482
|
+
/** Id of the fact that replaced this one. Audit / `history()` only; reads never filter on it. */
|
|
483
|
+
superseded_by?: string | null;
|
|
484
|
+
/** Epoch ms the supersession was recorded (transaction time). Audit only. */
|
|
485
|
+
superseded_at?: number | null;
|
|
428
486
|
}
|
|
429
487
|
interface WikiTask {
|
|
430
488
|
id: string;
|
|
@@ -467,6 +525,8 @@ interface WikiEvent {
|
|
|
467
525
|
summary: string;
|
|
468
526
|
related_entry_id?: string | null;
|
|
469
527
|
created_at: number;
|
|
528
|
+
/** Real-world time of the event (epoch ms). `created_at` stays ingestion time and remains the ordering key. */
|
|
529
|
+
occurred_at?: number | null;
|
|
470
530
|
}
|
|
471
531
|
interface WikiEdge {
|
|
472
532
|
id: string;
|
|
@@ -499,6 +559,10 @@ interface GraphTraversalOptions {
|
|
|
499
559
|
* Resolves call → `WikiConfig.excludeDrafts` → false.
|
|
500
560
|
*/
|
|
501
561
|
excludeDrafts?: boolean;
|
|
562
|
+
/** Valid-time snapshot for traversal (epoch ms); an edge is walkable only when both endpoints are live at this instant. Omitted ⇒ now. */
|
|
563
|
+
asOf?: number;
|
|
564
|
+
/** Pack nodes (anchor first, then BFS order) into roughly this many tokens; edges to dropped nodes are removed. */
|
|
565
|
+
tokenBudget?: number;
|
|
502
566
|
}
|
|
503
567
|
interface GraphNeighborhood {
|
|
504
568
|
/** Anchor node first, then discovered neighbors ordered by depth ASC, then updated_at DESC. */
|
|
@@ -538,6 +602,22 @@ interface LLMProvider {
|
|
|
538
602
|
systemPrompt: string;
|
|
539
603
|
userPrompt: string;
|
|
540
604
|
}) => Promise<string>;
|
|
605
|
+
/**
|
|
606
|
+
* Optional. When present, core calls this instead of `generateText` and
|
|
607
|
+
* meters the reported usage (spec 2026-09-29 §6.3). Called with the provider
|
|
608
|
+
* as `this`. Omit `usage` (or return malformed numbers) to fall back to the
|
|
609
|
+
* chars/4 estimate.
|
|
610
|
+
*/
|
|
611
|
+
generateTextWithUsage?: (params: {
|
|
612
|
+
systemPrompt: string;
|
|
613
|
+
userPrompt: string;
|
|
614
|
+
}) => Promise<{
|
|
615
|
+
text: string;
|
|
616
|
+
usage?: {
|
|
617
|
+
inputTokens: number;
|
|
618
|
+
outputTokens: number;
|
|
619
|
+
};
|
|
620
|
+
}>;
|
|
541
621
|
/**
|
|
542
622
|
* Optional. When provided, enables semantic similarity search in `read()`.
|
|
543
623
|
* Must return a stable-dimension float array for any input text.
|
|
@@ -672,9 +752,9 @@ type WikiDiagnosticSeverity = 'info' | 'warn' | 'error';
|
|
|
672
752
|
* Closed for this release series, but new codes are added in minor versions:
|
|
673
753
|
* hosts must tolerate codes they do not recognize.
|
|
674
754
|
*/
|
|
675
|
-
type WikiDiagnosticCode = 'ingest_chunk_failed' | 'fact_rejected' | 'task_rejected' | 'fact_deduplicated' | 'edge_dropped' | 'embedding_failed' | 'hook_failed' | 'background_job_failed' | 'heal_skipped' | 'grounding_missing' | 'grounding_failed' | 'classification_low_confidence' | 'classification_invalid';
|
|
755
|
+
type WikiDiagnosticCode = 'ingest_chunk_failed' | 'fact_rejected' | 'task_rejected' | 'fact_deduplicated' | 'edge_dropped' | 'embedding_failed' | 'hook_failed' | 'background_job_failed' | 'heal_skipped' | 'grounding_missing' | 'grounding_failed' | 'classification_low_confidence' | 'classification_invalid' | 'llm_usage' | 'librarian_gate' | 'librarian_op_rejected' | 'contradicts_document' | 'resolve_failed' | 'read_budget' | 'event_retention_held';
|
|
676
756
|
/** The service run that emitted the diagnostic. */
|
|
677
|
-
type WikiDiagnosticOperation = 'ingest' | 'upsertGraph' | 'librarian' | 'heal' | 'ontologyBackfill' | 'reembed' | 'importDump' | 'write';
|
|
757
|
+
type WikiDiagnosticOperation = 'ingest' | 'upsertGraph' | 'librarian' | 'heal' | 'ontologyBackfill' | 'reembed' | 'importDump' | 'write' | 'supersede' | 'read' | 'prune';
|
|
678
758
|
/** `'auto'` when a write threshold started the run (auto-librarian / auto-heal); `'call'` when the host did. */
|
|
679
759
|
type WikiDiagnosticTrigger = 'call' | 'auto';
|
|
680
760
|
/** Identifiers only — never titles, bodies, quotes, LLM output, provider messages, or hashes of content. */
|
|
@@ -695,6 +775,24 @@ interface WikiDiagnosticDetail {
|
|
|
695
775
|
chunkIndexes?: number[];
|
|
696
776
|
/** Aggregated emissions only. */
|
|
697
777
|
count?: number;
|
|
778
|
+
/** `llm_usage` only. */
|
|
779
|
+
inputTokens?: number;
|
|
780
|
+
/** `llm_usage` only. */
|
|
781
|
+
outputTokens?: number;
|
|
782
|
+
/** `llm_usage` only: true when a figure is the chars/4 estimate. */
|
|
783
|
+
estimated?: boolean;
|
|
784
|
+
/** librarian_gate only. */
|
|
785
|
+
gateNoop?: number;
|
|
786
|
+
/** librarian_gate only. */
|
|
787
|
+
gateAdd?: number;
|
|
788
|
+
/** librarian_gate only. */
|
|
789
|
+
gateAmbiguous?: number;
|
|
790
|
+
/** read_budget only. */
|
|
791
|
+
candidates?: number;
|
|
792
|
+
/** read_budget only. */
|
|
793
|
+
packed?: number;
|
|
794
|
+
/** read_budget only. */
|
|
795
|
+
tokensUsed?: number;
|
|
698
796
|
}
|
|
699
797
|
interface WikiDiagnostic {
|
|
700
798
|
code: WikiDiagnosticCode;
|
|
@@ -818,6 +916,8 @@ interface FormatContextOptions {
|
|
|
818
916
|
includeTags?: boolean;
|
|
819
917
|
includeEntityIds?: boolean;
|
|
820
918
|
includeFactScores?: boolean;
|
|
919
|
+
/** Title + body only; overrides every include* flag. Default false. */
|
|
920
|
+
compact?: boolean;
|
|
821
921
|
factWeights?: {
|
|
822
922
|
confidence?: number;
|
|
823
923
|
accessCount?: number;
|
|
@@ -1050,6 +1150,22 @@ declare class WikiDraftNotFound extends Error {
|
|
|
1050
1150
|
readonly code: "WIKI_DRAFT_NOT_FOUND";
|
|
1051
1151
|
constructor();
|
|
1052
1152
|
}
|
|
1153
|
+
type WikiSupersedeReason = 'not_found' | 'already_superseded' | 'immutable_target' | 'cycle' | 'cross_entity';
|
|
1154
|
+
/** Thrown by `supersede()` (spec §4.3). Contextless like {@link WikiDraftNotFound}. */
|
|
1155
|
+
declare class WikiSupersedeError extends Error {
|
|
1156
|
+
readonly code: "WIKI_SUPERSEDE_REJECTED";
|
|
1157
|
+
readonly reason: WikiSupersedeReason;
|
|
1158
|
+
constructor(reason: WikiSupersedeReason);
|
|
1159
|
+
}
|
|
1160
|
+
/** A new fact to create as the replacement, or the id of an existing fact. */
|
|
1161
|
+
type SupersedeReplacement = string | {
|
|
1162
|
+
title: string;
|
|
1163
|
+
body: string;
|
|
1164
|
+
tags?: string[];
|
|
1165
|
+
confidence?: WikiFact['confidence'];
|
|
1166
|
+
source_type?: 'user_stated' | 'user_confirmed' | 'librarian_inferred';
|
|
1167
|
+
valid_from?: number;
|
|
1168
|
+
};
|
|
1053
1169
|
/** One page of `listDrafts`. `nextCursor` is opaque; pass it back unchanged. */
|
|
1054
1170
|
interface DraftPage {
|
|
1055
1171
|
facts: WikiFact[];
|
|
@@ -1092,6 +1208,62 @@ interface WikiInstructions {
|
|
|
1092
1208
|
heal: string;
|
|
1093
1209
|
ontologyBackfill: string;
|
|
1094
1210
|
}
|
|
1211
|
+
type MaintenanceJob = 'librarian' | 'heal' | 'reembed';
|
|
1212
|
+
interface PendingMaintenance {
|
|
1213
|
+
entityId: string;
|
|
1214
|
+
/** Events after the librarian watermark. */
|
|
1215
|
+
pendingEvents: number;
|
|
1216
|
+
/** ceil(sum of pending event summary chars / 4). */
|
|
1217
|
+
pendingTokensEstimate: number;
|
|
1218
|
+
/** Same rule as auto-heal: events since the heal checkpoint >= autoHealThreshold. */
|
|
1219
|
+
healDue: boolean;
|
|
1220
|
+
/**
|
|
1221
|
+
* Non-deleted facts (superseded history rows included, matching what
|
|
1222
|
+
* `runReembed` sweeps) with no stored embedding that are still retryable.
|
|
1223
|
+
* Always false without `embed`.
|
|
1224
|
+
*/
|
|
1225
|
+
reembedPending: boolean;
|
|
1226
|
+
}
|
|
1227
|
+
interface RunPendingMaintenanceOptions {
|
|
1228
|
+
/** Default: every entity with pending work. */
|
|
1229
|
+
entityIds?: string[];
|
|
1230
|
+
/** generateText tokens (provider-reported or chars/4). Omitted = unbounded. */
|
|
1231
|
+
tokenBudget?: number;
|
|
1232
|
+
/** Wall-clock milliseconds from the call. Checked between units; a unit in flight is never interrupted. */
|
|
1233
|
+
deadlineMs?: number;
|
|
1234
|
+
/** Default all three. */
|
|
1235
|
+
jobs?: MaintenanceJob[];
|
|
1236
|
+
}
|
|
1237
|
+
type MaintenanceStopReason = {
|
|
1238
|
+
reason: 'complete';
|
|
1239
|
+
} | {
|
|
1240
|
+
reason: 'deadline';
|
|
1241
|
+
} | {
|
|
1242
|
+
reason: 'budget_exhausted';
|
|
1243
|
+
} | {
|
|
1244
|
+
reason: 'budget_too_small';
|
|
1245
|
+
job: 'librarian' | 'heal';
|
|
1246
|
+
entityId: string;
|
|
1247
|
+
requiredEstimate: number;
|
|
1248
|
+
};
|
|
1249
|
+
interface EntityMaintenanceReport {
|
|
1250
|
+
entityId: string;
|
|
1251
|
+
librarianPasses: number;
|
|
1252
|
+
factsWritten: number;
|
|
1253
|
+
healPasses: number;
|
|
1254
|
+
reembedded: boolean;
|
|
1255
|
+
/** Set when a lock was held elsewhere; nothing ran for that job. */
|
|
1256
|
+
busy?: MaintenanceJob[];
|
|
1257
|
+
}
|
|
1258
|
+
interface RunPendingMaintenanceResult {
|
|
1259
|
+
perEntity: EntityMaintenanceReport[];
|
|
1260
|
+
tokensUsed: number;
|
|
1261
|
+
/** True when any usage figure was a chars/4 estimate. */
|
|
1262
|
+
estimated: boolean;
|
|
1263
|
+
/** null when no tokenBudget was given. */
|
|
1264
|
+
remaining: number | null;
|
|
1265
|
+
stoppedReason: MaintenanceStopReason;
|
|
1266
|
+
}
|
|
1095
1267
|
|
|
1096
1268
|
interface WikiOutboxEvent<T = unknown> {
|
|
1097
1269
|
id: string;
|
|
@@ -1147,6 +1319,36 @@ declare class OutboxRepository extends BaseRepository {
|
|
|
1147
1319
|
acknowledge(ids: string[]): Promise<void>;
|
|
1148
1320
|
}
|
|
1149
1321
|
|
|
1322
|
+
/**
|
|
1323
|
+
* Single definition of fact liveness (spec 2026-09-29 §4.2). Every read path
|
|
1324
|
+
* uses these so SQL and JS can never disagree.
|
|
1325
|
+
*
|
|
1326
|
+
* - 'asOf' — valid time using current knowledge: live at T when
|
|
1327
|
+
* COALESCE(valid_from, created_at) <= T < valid_to (valid_to NULL = open).
|
|
1328
|
+
* - 'current' — live now per the row's own validity columns. A row with both
|
|
1329
|
+
* columns NULL is always current; created_at is deliberately ignored so
|
|
1330
|
+
* existing rows (and fixtures with arbitrary created_at) stay current.
|
|
1331
|
+
*/
|
|
1332
|
+
type LiveMode = 'current' | 'asOf';
|
|
1333
|
+
|
|
1334
|
+
/** Subset of temporal columns that {@link EntryRepository.setTemporal} may write (spec 2026-09-29 §4.3). */
|
|
1335
|
+
type TemporalFields = {
|
|
1336
|
+
valid_from?: number | null;
|
|
1337
|
+
valid_to?: number | null;
|
|
1338
|
+
superseded_by?: string | null;
|
|
1339
|
+
superseded_at?: number | null;
|
|
1340
|
+
};
|
|
1341
|
+
/** Lightweight projection used by TemporalService for supersession chain walks. */
|
|
1342
|
+
type TemporalRow = {
|
|
1343
|
+
id: string;
|
|
1344
|
+
entity_id: string;
|
|
1345
|
+
source_type: WikiFact['source_type'];
|
|
1346
|
+
deleted_at: number | null;
|
|
1347
|
+
created_at: number;
|
|
1348
|
+
valid_from: number | null;
|
|
1349
|
+
valid_to: number | null;
|
|
1350
|
+
superseded_by: string | null;
|
|
1351
|
+
};
|
|
1150
1352
|
type EntryRowMetadata = {
|
|
1151
1353
|
id: string;
|
|
1152
1354
|
entity_id: string;
|
|
@@ -1370,6 +1572,23 @@ declare class EntryRepository extends BaseRepository {
|
|
|
1370
1572
|
* Used by MaintenanceService.doRunHeal().
|
|
1371
1573
|
*/
|
|
1372
1574
|
softDeleteByIds(ids: string[], entityId: string, tx: SQLiteAdapter): Promise<void>;
|
|
1575
|
+
/** Spec §4: write any subset of the four temporal columns. Absent key = untouched; null = clear. */
|
|
1576
|
+
setTemporal(id: string, entityId: string, fields: TemporalFields, tx: SQLiteAdapter, opts?: {
|
|
1577
|
+
outbox?: boolean;
|
|
1578
|
+
}): Promise<number>;
|
|
1579
|
+
findTemporalRow(id: string, tx?: SQLiteAdapter): Promise<TemporalRow | null>;
|
|
1580
|
+
/**
|
|
1581
|
+
* Ids of non-deleted facts NOT live at `t` (spec §4.2). In 'current' mode a
|
|
1582
|
+
* row with both validity columns NULL is always live, so the query is
|
|
1583
|
+
* restricted to rows that carry a validity column — served by the partial
|
|
1584
|
+
* entries_temporal_idx.
|
|
1585
|
+
*/
|
|
1586
|
+
findNonLiveIdsByEntityIds(entityIds: readonly string[], mode: LiveMode, t: number, tx?: SQLiteAdapter): Promise<Set<string>>;
|
|
1587
|
+
findSupersessionChainIds(entityId: string, factId: string, maxDepth: number, tx?: SQLiteAdapter): Promise<{
|
|
1588
|
+
predecessors: string[];
|
|
1589
|
+
successors: string[];
|
|
1590
|
+
}>;
|
|
1591
|
+
findExpiredIds(entityId: string, cutoff: number, tx?: SQLiteAdapter): Promise<string[]>;
|
|
1373
1592
|
/**
|
|
1374
1593
|
* Bulk soft-delete all entries for an entity.
|
|
1375
1594
|
* Stages DELETE outbox entries for each row in the same transaction.
|
|
@@ -1503,6 +1722,10 @@ declare class EntryRepository extends BaseRepository {
|
|
|
1503
1722
|
getLegacyMigrationSQL(): string;
|
|
1504
1723
|
findRecentByEntityIds(entityIds: readonly string[], limit: number, tx?: SQLiteAdapter, opts?: {
|
|
1505
1724
|
excludeDrafts?: boolean;
|
|
1725
|
+
live?: {
|
|
1726
|
+
mode: LiveMode;
|
|
1727
|
+
t: number;
|
|
1728
|
+
};
|
|
1506
1729
|
}): Promise<WikiFact[]>;
|
|
1507
1730
|
/** IDs of live draft facts for the given entities (spec §5.1). Callers pass ≤ 100 entity ids. */
|
|
1508
1731
|
findDraftIdsByEntityIds(entityIds: readonly string[], tx?: SQLiteAdapter): Promise<Set<string>>;
|
|
@@ -1577,6 +1800,13 @@ declare class EntryRepository extends BaseRepository {
|
|
|
1577
1800
|
id: string;
|
|
1578
1801
|
title: string;
|
|
1579
1802
|
}>>;
|
|
1803
|
+
/**
|
|
1804
|
+
* Count of live facts for `entityId` with no stored embedding that are still
|
|
1805
|
+
* retryable (`embedding_attempts < maxAttempts`). Backs the deferred
|
|
1806
|
+
* maintenance pending report's `reembedPending` flag and the reembed job's
|
|
1807
|
+
* entity selection (PR-C 2026-09-29).
|
|
1808
|
+
*/
|
|
1809
|
+
countReembedPending(entityId: string, maxAttempts: number, tx?: SQLiteAdapter): Promise<number>;
|
|
1580
1810
|
}
|
|
1581
1811
|
|
|
1582
1812
|
/**
|
|
@@ -1622,6 +1852,15 @@ declare class SourceRefIndexRepository extends BaseRepository {
|
|
|
1622
1852
|
findActiveByEntityAndHash(entityId: string, sourceHash: string, tx?: SQLiteAdapter): Promise<string | null>;
|
|
1623
1853
|
}
|
|
1624
1854
|
|
|
1855
|
+
/**
|
|
1856
|
+
* The op-based librarian's high-water mark on the `events` table. Stored
|
|
1857
|
+
* alongside `memory_checkpoint` / `heal_checkpoint` so an entity's
|
|
1858
|
+
* maintenance state stays in one row. See spec 2026-09-29 §4.1.
|
|
1859
|
+
*/
|
|
1860
|
+
type LibrarianWatermark = {
|
|
1861
|
+
at: number;
|
|
1862
|
+
id: string;
|
|
1863
|
+
};
|
|
1625
1864
|
declare class MetadataRepository extends BaseRepository {
|
|
1626
1865
|
getCheckpoint(entityId: string, tx: SQLiteAdapter): Promise<{
|
|
1627
1866
|
memory?: number;
|
|
@@ -1632,6 +1871,17 @@ declare class MetadataRepository extends BaseRepository {
|
|
|
1632
1871
|
heal?: number;
|
|
1633
1872
|
}, tx: SQLiteAdapter): Promise<void>;
|
|
1634
1873
|
deleteCheckpoint(entityId: string, tx: SQLiteAdapter): Promise<void>;
|
|
1874
|
+
/**
|
|
1875
|
+
* Read the op-based librarian's high-water mark. Returns `null` when the
|
|
1876
|
+
* entity has never had its watermark set.
|
|
1877
|
+
*/
|
|
1878
|
+
getLibrarianWatermark(entityId: string, tx: SQLiteAdapter): Promise<LibrarianWatermark | null>;
|
|
1879
|
+
/**
|
|
1880
|
+
* Write the op-based librarian's high-water mark. Uses `ON CONFLICT`
|
|
1881
|
+
* `DO UPDATE` so existing `memory_checkpoint` / `heal_checkpoint` rows
|
|
1882
|
+
* are preserved verbatim.
|
|
1883
|
+
*/
|
|
1884
|
+
setLibrarianWatermark(entityId: string, wm: LibrarianWatermark, tx: SQLiteAdapter): Promise<void>;
|
|
1635
1885
|
getMeta(key: string, tx?: SQLiteAdapter): Promise<string | null>;
|
|
1636
1886
|
setMeta(key: string, value: string, tx: SQLiteAdapter): Promise<void>;
|
|
1637
1887
|
deleteMeta(key: string, tx?: SQLiteAdapter): Promise<void>;
|
|
@@ -1773,6 +2023,13 @@ declare class SearchService {
|
|
|
1773
2023
|
* cannot index itself, such as upsertGraph inside a host transaction.
|
|
1774
2024
|
*/
|
|
1775
2025
|
markStale(entityId: string): void;
|
|
2026
|
+
/**
|
|
2027
|
+
* Runs syncEntries(id, []) for each entity marked stale when this is called,
|
|
2028
|
+
* so only those entities are rebuilt. Each rebuild still takes its own turn
|
|
2029
|
+
* on the sync chain, and like syncEntries this never rejects. With nothing
|
|
2030
|
+
* stale it resolves at once, without waiting on work already on the chain.
|
|
2031
|
+
*/
|
|
2032
|
+
syncStale(): Promise<void>;
|
|
1776
2033
|
/**
|
|
1777
2034
|
* Clears the parsed vector cache. Useful for mid-loop flush guarantees
|
|
1778
2035
|
* or memory pressure evictions.
|
|
@@ -1987,6 +2244,11 @@ interface NeighborhoodQueryOptions {
|
|
|
1987
2244
|
* intentionally start from a draft. Default false (drafts visible).
|
|
1988
2245
|
*/
|
|
1989
2246
|
excludeDrafts?: boolean;
|
|
2247
|
+
/** Liveness gate for discovered nodes: 'current' (live now) or 'asOf' (valid time T). Always supplied by GraphTraversalService. */
|
|
2248
|
+
live: {
|
|
2249
|
+
mode: LiveMode;
|
|
2250
|
+
t: number;
|
|
2251
|
+
};
|
|
1990
2252
|
}
|
|
1991
2253
|
declare class EdgeRepository extends BaseRepository {
|
|
1992
2254
|
/**
|
|
@@ -2077,6 +2339,40 @@ declare class EmbeddingService {
|
|
|
2077
2339
|
body: string;
|
|
2078
2340
|
tags: string | string[];
|
|
2079
2341
|
}, ctx?: EmbedDiagnosticContext): Promise<EmbedFactResult>;
|
|
2342
|
+
/**
|
|
2343
|
+
* Compute half: build the embed text, call embed(), validate the result,
|
|
2344
|
+
* mark any embed-time failure, and return the validated Float32 vector.
|
|
2345
|
+
*
|
|
2346
|
+
* Failure kinds: `no_provider`, `invalid_vector`, `float32_overflow`,
|
|
2347
|
+
* `provider_error`. All embed-time failures are marked via `markFailure`;
|
|
2348
|
+
* `no_provider` deliberately does not mark (spec §2.4).
|
|
2349
|
+
*
|
|
2350
|
+
* Storage errors are NOT possible here — that is `storeFactVector`'s domain.
|
|
2351
|
+
*/
|
|
2352
|
+
embedTextForFact(fact: {
|
|
2353
|
+
id: string;
|
|
2354
|
+
entity_id: string;
|
|
2355
|
+
title: string;
|
|
2356
|
+
body: string;
|
|
2357
|
+
tags: string | string[];
|
|
2358
|
+
}, ctx?: EmbedDiagnosticContext, opts?: {
|
|
2359
|
+
markFailures?: boolean;
|
|
2360
|
+
}): Promise<{
|
|
2361
|
+
ok: true;
|
|
2362
|
+
vector: Float32Array;
|
|
2363
|
+
} | {
|
|
2364
|
+
ok: false;
|
|
2365
|
+
kind: EmbedFailureKind;
|
|
2366
|
+
}>;
|
|
2367
|
+
/**
|
|
2368
|
+
* Storage half: persist the computed vector to the entry row, then fire the
|
|
2369
|
+
* `onEmbeddingPersisted` hook. Failure kinds: `storage_error` only — embed
|
|
2370
|
+
* failures do not originate here, so they cannot be marked as such (spec §3.2, D3).
|
|
2371
|
+
*/
|
|
2372
|
+
storeFactVector(fact: {
|
|
2373
|
+
id: string;
|
|
2374
|
+
entity_id: string;
|
|
2375
|
+
}, float32Vector: Float32Array, ctx?: EmbedDiagnosticContext): Promise<EmbedFactResult>;
|
|
2080
2376
|
private reportEmbed;
|
|
2081
2377
|
/** For callers that invoke `notifyEmbeddingPersisted` directly and catch its failure. */
|
|
2082
2378
|
reportHookFailed(ctx: EmbedDiagnosticContext, entityId: string, factId: string): void;
|
|
@@ -2161,6 +2457,12 @@ interface GroundingTrust {
|
|
|
2161
2457
|
last_verified_by?: string;
|
|
2162
2458
|
}
|
|
2163
2459
|
|
|
2460
|
+
type LabeledEvent = {
|
|
2461
|
+
label: string;
|
|
2462
|
+
event: WikiEvent;
|
|
2463
|
+
at: number;
|
|
2464
|
+
};
|
|
2465
|
+
|
|
2164
2466
|
declare class PromptService {
|
|
2165
2467
|
private globalOverrides?;
|
|
2166
2468
|
private grounding;
|
|
@@ -2216,6 +2518,28 @@ declare class PromptService {
|
|
|
2216
2518
|
systemPrompt: string;
|
|
2217
2519
|
userPrompt: string;
|
|
2218
2520
|
};
|
|
2521
|
+
/** Ops extract (spec §5.2): events only — no existing facts. */
|
|
2522
|
+
buildOpsExtractPrompt(events: LabeledEvent[], ontologyContext?: OntologyPromptContext | null): {
|
|
2523
|
+
systemPrompt: string;
|
|
2524
|
+
userPrompt: string;
|
|
2525
|
+
groundingCorpus?: string[];
|
|
2526
|
+
};
|
|
2527
|
+
/** Ops resolve (spec §5.4): only each item's own neighbours. */
|
|
2528
|
+
buildOpsResolvePrompt(items: Array<{
|
|
2529
|
+
item: number;
|
|
2530
|
+
candidate: {
|
|
2531
|
+
title: string;
|
|
2532
|
+
body: string;
|
|
2533
|
+
};
|
|
2534
|
+
existing: Array<{
|
|
2535
|
+
ref: string;
|
|
2536
|
+
title: string;
|
|
2537
|
+
body: string;
|
|
2538
|
+
}>;
|
|
2539
|
+
}>): {
|
|
2540
|
+
systemPrompt: string;
|
|
2541
|
+
userPrompt: string;
|
|
2542
|
+
};
|
|
2219
2543
|
/**
|
|
2220
2544
|
* The system prompt each writer would send, without hydrating data (spec
|
|
2221
2545
|
* §8.3). `buildSystemPrompt` with no variables hydrates only ontology
|
|
@@ -2456,6 +2780,22 @@ declare class EventRepository extends BaseRepository {
|
|
|
2456
2780
|
prune(entityId: string, cutoff: number): Promise<{
|
|
2457
2781
|
changes: number;
|
|
2458
2782
|
}>;
|
|
2783
|
+
/**
|
|
2784
|
+
* Watermark-guarded prune (spec 2026-09-29 competitive-memory §6): delete
|
|
2785
|
+
* events at or before `cutoff` **and** at-or-before the librarian watermark.
|
|
2786
|
+
* Events the librarian has not processed yet are retention-held, never
|
|
2787
|
+
* deleted. `wm = null` (no watermark yet) deletes nothing.
|
|
2788
|
+
* Used by runPrune under the deferred/ops strategies.
|
|
2789
|
+
*/
|
|
2790
|
+
pruneThrough(entityId: string, cutoff: number, wm: LibrarianWatermark | null): Promise<{
|
|
2791
|
+
changes: number;
|
|
2792
|
+
}>;
|
|
2793
|
+
/**
|
|
2794
|
+
* Count events at or before `cutoff` that are after the watermark — the
|
|
2795
|
+
* retention-held tail `pruneThrough` left in place. `wm = null` counts all
|
|
2796
|
+
* events at or before `cutoff` (every one of them is held back).
|
|
2797
|
+
*/
|
|
2798
|
+
countHeldBack(entityId: string, cutoff: number, wm: LibrarianWatermark | null): Promise<number>;
|
|
2459
2799
|
/**
|
|
2460
2800
|
* Return the total number of events stored for an entity.
|
|
2461
2801
|
* `tx` is optional — pass an active transaction handle for atomic reads.
|
|
@@ -2466,6 +2806,105 @@ declare class EventRepository extends BaseRepository {
|
|
|
2466
2806
|
* When limit is provided, fetches newest-first then reverses to preserve chronological order.
|
|
2467
2807
|
*/
|
|
2468
2808
|
getByEntityId(entityId: string, limit?: number): Promise<WikiEvent[]>;
|
|
2809
|
+
/**
|
|
2810
|
+
* Return events for `entityId` strictly after the watermark `(at, id)` in
|
|
2811
|
+
* chronological (ASC, id-ASC tie-break) order. Pass `wm = null` to read
|
|
2812
|
+
* from the beginning of the entity's event log. `limit` caps the result.
|
|
2813
|
+
*
|
|
2814
|
+
* Used by the op-based librarian (PR-B) to enumerate its unprocessed tail.
|
|
2815
|
+
*/
|
|
2816
|
+
getAfter(entityId: string, wm: LibrarianWatermark | null, limit?: number): Promise<WikiEvent[]>;
|
|
2817
|
+
/**
|
|
2818
|
+
* Count of events for `entityId` strictly after the watermark. Used as
|
|
2819
|
+
* the op-based librarian's bounded batch size and by the deferred-maintenance
|
|
2820
|
+
* pending report. Pass `wm = null` to count the entity's whole event log
|
|
2821
|
+
* (no watermark yet) — mirrors `getAfter` / `sumSummaryCharsAfter`.
|
|
2822
|
+
*/
|
|
2823
|
+
countAfter(entityId: string, wm: LibrarianWatermark | null): Promise<number>;
|
|
2824
|
+
/**
|
|
2825
|
+
* Return the event at a given chronological offset for `entityId` (0-based,
|
|
2826
|
+
* oldest first). Used by MaintenanceService.seedLibrarianWatermark to anchor
|
|
2827
|
+
* the watermark on a real row when a legacy DB first migrates to the
|
|
2828
|
+
* op-based librarian. The offset is clamped and truncated to defend against
|
|
2829
|
+
* hostile or fractional callers.
|
|
2830
|
+
*/
|
|
2831
|
+
getAtOffset(entityId: string, offset: number, tx?: SQLiteAdapter): Promise<WikiEvent | null>;
|
|
2832
|
+
/**
|
|
2833
|
+
* Sum of `summary` lengths (in characters) for events for `entityId`
|
|
2834
|
+
* strictly after the watermark. Pass `wm = null` to sum the entity's whole
|
|
2835
|
+
* event log (no watermark yet). Used by the op-based librarian's token
|
|
2836
|
+
* budget estimator (PR-B) and by the auto-trigger's pending-size check
|
|
2837
|
+
* (PR-C). SQLite's `LENGTH` returns character count for UTF-8 text input.
|
|
2838
|
+
*/
|
|
2839
|
+
sumSummaryCharsAfter(entityId: string, wm: LibrarianWatermark | null, tx?: SQLiteAdapter): Promise<number>;
|
|
2840
|
+
}
|
|
2841
|
+
|
|
2842
|
+
interface UsageRecord {
|
|
2843
|
+
inputTokens: number;
|
|
2844
|
+
outputTokens: number;
|
|
2845
|
+
/** True when either figure came from estimateTokens rather than the provider. */
|
|
2846
|
+
estimated: boolean;
|
|
2847
|
+
}
|
|
2848
|
+
/** One budget shared by every LLM call in a maintenance run. */
|
|
2849
|
+
declare class UsageMeter {
|
|
2850
|
+
readonly budget: number | undefined;
|
|
2851
|
+
used: number;
|
|
2852
|
+
estimated: boolean;
|
|
2853
|
+
constructor(budget?: number);
|
|
2854
|
+
get remaining(): number;
|
|
2855
|
+
fits(estimate: number): boolean;
|
|
2856
|
+
record(r: UsageRecord): void;
|
|
2857
|
+
}
|
|
2858
|
+
|
|
2859
|
+
/**
|
|
2860
|
+
* Librarian strategy seam (spec 2026-09-29 §5.1).
|
|
2861
|
+
*
|
|
2862
|
+
* The seam lets PR-B (ops librarian) plug in without `MaintenanceService`
|
|
2863
|
+
* editing the body. The verbatim legacy move lives in `legacy.ts`; the
|
|
2864
|
+
* dispatcher in `index.ts` is the only place that knows which strategies
|
|
2865
|
+
* exist. New strategies register there.
|
|
2866
|
+
*
|
|
2867
|
+
* `LibrarianStrategy` is the contract every implementation satisfies. The
|
|
2868
|
+
* pass is identified by its `(entityId, trigger, promptOverride?, meter?)`
|
|
2869
|
+
* context; the strategy returns what it processed so the caller can
|
|
2870
|
+
* advance checkpoints / watermarks.
|
|
2871
|
+
*/
|
|
2872
|
+
|
|
2873
|
+
/** Per-pass inputs the caller decides; the strategy cannot derive these. */
|
|
2874
|
+
interface LibrarianContext {
|
|
2875
|
+
entityId: string;
|
|
2876
|
+
trigger: WikiDiagnosticTrigger;
|
|
2877
|
+
promptOverride?: string;
|
|
2878
|
+
/** Optional meter (Phase C budgeted maintenance). Legacy honors it:
|
|
2879
|
+
* `callLlm` pre-flights the prompt estimate against it, usage is recorded
|
|
2880
|
+
* on every call, and the pass returns `budgetStop` when the budget is
|
|
2881
|
+
* exhausted (see `librarianBudget.test.ts`). */
|
|
2882
|
+
meter?: UsageMeter;
|
|
2883
|
+
}
|
|
2884
|
+
/**
|
|
2885
|
+
* Position in the event log a pass read through: the event's `created_at`
|
|
2886
|
+
* (epoch ms) and its id. Callers advance checkpoints / watermarks with it.
|
|
2887
|
+
*/
|
|
2888
|
+
interface EventCursor {
|
|
2889
|
+
at: number;
|
|
2890
|
+
id: string;
|
|
2891
|
+
}
|
|
2892
|
+
/**
|
|
2893
|
+
* What the strategy did. The shape is intentionally narrow: callers (lock
|
|
2894
|
+
* wrapper, deferred scheduler) only need to know whether work happened and
|
|
2895
|
+
* whether a budget error truncated it. PR-B adds its own watermark
|
|
2896
|
+
* semantics; the legacy `processedThrough` is an {@link EventCursor} for the
|
|
2897
|
+
* newest event the pass read (or null when there were no events).
|
|
2898
|
+
*/
|
|
2899
|
+
interface LibrarianResult {
|
|
2900
|
+
/** Newest event the pass processed (epoch ms + id), or `null` if the event log was empty. */
|
|
2901
|
+
processedThrough: EventCursor | null;
|
|
2902
|
+
/** Number of facts actually written (excludes deduped, rejected, failed-validation). */
|
|
2903
|
+
factsWritten: number;
|
|
2904
|
+
/** Set only when `callLlm` raised `WikiBudgetExhausted`. */
|
|
2905
|
+
budgetStop?: {
|
|
2906
|
+
requiredEstimate: number;
|
|
2907
|
+
};
|
|
2469
2908
|
}
|
|
2470
2909
|
|
|
2471
2910
|
declare const ONTOLOGY_BACKFILL_BATCH_SIZE = 25;
|
|
@@ -2574,6 +3013,39 @@ declare class MaintenanceService {
|
|
|
2574
3013
|
private forgetDryRun;
|
|
2575
3014
|
/** Core librarian pass (locks handled by {@link runLibrarian}). Package-internal orchestration hook. */
|
|
2576
3015
|
doRunLibrarian(entityId: string, promptOverride?: string, trigger?: WikiDiagnosticTrigger): Promise<void>;
|
|
3016
|
+
/**
|
|
3017
|
+
* Seam between the lock wrapper and the strategy dispatcher (spec 2026-09-29
|
|
3018
|
+
* §5.1). Builds the strategy deps from `this` and dispatches via
|
|
3019
|
+
* `runLibrarianStrategy` so PR-B can plug in `ops/` without touching this
|
|
3020
|
+
* class. Returns the strategy's `LibrarianResult` so deferred/budgeted
|
|
3021
|
+
* schedulers (PR-C) can advance watermarks; the existing void-returning
|
|
3022
|
+
* `doRunLibrarian` discards it.
|
|
3023
|
+
*
|
|
3024
|
+
* Spec §10.3: one place advances the watermark, for every strategy, only
|
|
3025
|
+
* after the pass resolved (its transaction committed) and never backwards.
|
|
3026
|
+
* A budget-stopped pass wrote nothing and must not move the watermark.
|
|
3027
|
+
*/
|
|
3028
|
+
runLibrarianPass(ctx: LibrarianContext): Promise<LibrarianResult>;
|
|
3029
|
+
/**
|
|
3030
|
+
* Strategy deps shared between legacy and ops librarians (spec §5.1). The
|
|
3031
|
+
* ops strategy (PR-B Task 8) reads/anchors the watermark through these two
|
|
3032
|
+
* hooks so the dispatcher itself never reaches into the metadata table —
|
|
3033
|
+
* the watermark invariant (one place advances, never backwards) lives here.
|
|
3034
|
+
*/
|
|
3035
|
+
private librarianDeps;
|
|
3036
|
+
/**
|
|
3037
|
+
* Persist `next` as the entity's librarian watermark when it is strictly
|
|
3038
|
+
* newer than the stored value, under the (created_at, id) ordering used by
|
|
3039
|
+
* the op-based librarian (spec §10.3). Never moves backwards.
|
|
3040
|
+
*/
|
|
3041
|
+
private advanceLibrarianWatermark;
|
|
3042
|
+
/**
|
|
3043
|
+
* Spec §10.3: first ops pass on a legacy DB starts after what the count
|
|
3044
|
+
* checkpoint already covered. No-op when a watermark already exists or the
|
|
3045
|
+
* memory checkpoint is 0; otherwise anchor the watermark to the event at
|
|
3046
|
+
* offset `min(memory_checkpoint, totalEvents) - 1`.
|
|
3047
|
+
*/
|
|
3048
|
+
seedLibrarianWatermark(entityId: string): Promise<void>;
|
|
2577
3049
|
/**
|
|
2578
3050
|
* Core heal pass (locks handled by {@link runHeal}). Package-internal orchestration hook.
|
|
2579
3051
|
*
|
|
@@ -2586,6 +3058,7 @@ declare class MaintenanceService {
|
|
|
2586
3058
|
batchSize?: number;
|
|
2587
3059
|
bodyTruncationChars?: number;
|
|
2588
3060
|
trigger?: WikiDiagnosticTrigger;
|
|
3061
|
+
meter?: UsageMeter;
|
|
2589
3062
|
}): Promise<HealResult>;
|
|
2590
3063
|
/** Core ontology backfill pass (locks handled by {@link runOntologyBackfill}). Package-internal orchestration hook. */
|
|
2591
3064
|
doRunOntologyBackfill(entityId: string, options?: {
|
|
@@ -2632,6 +3105,43 @@ declare class MaintenanceService {
|
|
|
2632
3105
|
private _sanitizeRankerError;
|
|
2633
3106
|
}
|
|
2634
3107
|
|
|
3108
|
+
/**
|
|
3109
|
+
* Read-side report for the deferred maintenance mode: which entities have
|
|
3110
|
+
* pending work (librarian events behind the watermark, heal backlog, unembedded
|
|
3111
|
+
* facts) without running anything. `run` executes the work (PR-C task 4).
|
|
3112
|
+
*/
|
|
3113
|
+
declare class MaintenanceScheduler {
|
|
3114
|
+
private db;
|
|
3115
|
+
private options;
|
|
3116
|
+
private maintenanceService;
|
|
3117
|
+
private metadataRepo;
|
|
3118
|
+
private eventRepo;
|
|
3119
|
+
private entryRepo;
|
|
3120
|
+
private jobManager;
|
|
3121
|
+
constructor(db: SQLiteAdapter, options: WikiOptions, maintenanceService: MaintenanceService, metadataRepo: MetadataRepository, eventRepo: EventRepository, entryRepo: EntryRepository, jobManager: JobManager);
|
|
3122
|
+
/**
|
|
3123
|
+
* Entities with **any** pending work only, sorted by `pendingEvents` desc
|
|
3124
|
+
* then `entityId` asc. Token estimate is ceil(pending summary chars / 4),
|
|
3125
|
+
* matching the auto-trigger's estimator (PR-B).
|
|
3126
|
+
*/
|
|
3127
|
+
getPending(entityIds?: string[]): Promise<PendingMaintenance[]>;
|
|
3128
|
+
/**
|
|
3129
|
+
* Execute pending maintenance (spec §6.2): fair-share rounds of at most one
|
|
3130
|
+
* unit per entity (librarian batch, else heal batch, else reembed), entities
|
|
3131
|
+
* ordered by `getPending` (pendingEvents desc, id asc). Holds the same
|
|
3132
|
+
* per-entity `JobManager` locks a manual run would; a busy entity is skipped
|
|
3133
|
+
* and reported, never thrown. Nothing is still running when this resolves.
|
|
3134
|
+
*
|
|
3135
|
+
* Stop precedence (spec §10 items 3-6): `deadline` > `budget_exhausted` >
|
|
3136
|
+
* `budget_too_small` > `complete`. `budget_too_small` means a job's smallest
|
|
3137
|
+
* unit needs more than the WHOLE budget — that job is skipped this run and
|
|
3138
|
+
* the run continues; `budget_exhausted` means a unit needs more than what
|
|
3139
|
+
* REMAINS — the run stops. The token budget meters `generateText` calls
|
|
3140
|
+
* only; embeddings are never metered.
|
|
3141
|
+
*/
|
|
3142
|
+
run(opts?: RunPendingMaintenanceOptions): Promise<RunPendingMaintenanceResult>;
|
|
3143
|
+
}
|
|
3144
|
+
|
|
2635
3145
|
declare class ImportExportService {
|
|
2636
3146
|
private db;
|
|
2637
3147
|
private entryRepo;
|
|
@@ -2676,7 +3186,7 @@ declare class RetrievalService {
|
|
|
2676
3186
|
* Stable tie-break sort: score desc → access_count desc → updated_at desc → id asc.
|
|
2677
3187
|
*/
|
|
2678
3188
|
private _tieBreakSort;
|
|
2679
|
-
private
|
|
3189
|
+
private _withoutIds;
|
|
2680
3190
|
/**
|
|
2681
3191
|
* Comparator for score + deterministic tie-break fields.
|
|
2682
3192
|
* Negative return means "a ranks ahead of b" for descending score order.
|
|
@@ -2705,6 +3215,10 @@ declare class WriteService {
|
|
|
2705
3215
|
private jobManager;
|
|
2706
3216
|
private maintenanceService;
|
|
2707
3217
|
constructor(db: SQLiteAdapter, options: WikiOptions, entryRepo: EntryRepository, eventRepo: EventRepository, metadataRepo: MetadataRepository, jobManager: JobManager, maintenanceService: MaintenanceService);
|
|
3218
|
+
private inflight;
|
|
3219
|
+
private track;
|
|
3220
|
+
/** Await every background job this instance started (spec §6.2). Loops because a finishing job can start another. */
|
|
3221
|
+
drain(): Promise<void>;
|
|
2708
3222
|
write(entityId: string, event: Omit<WikiEvent, 'id' | 'entity_id' | 'created_at'>): Promise<void>;
|
|
2709
3223
|
private runLibrarianThenMaybeHeal;
|
|
2710
3224
|
/**
|
|
@@ -2728,17 +3242,41 @@ declare class GraphTraversalService {
|
|
|
2728
3242
|
traverseGraph(entityId: string, options: GraphTraversalOptions): Promise<GraphNeighborhood>;
|
|
2729
3243
|
}
|
|
2730
3244
|
|
|
3245
|
+
/** Supersession and history (spec 2026-09-29 §4.3). */
|
|
3246
|
+
declare class TemporalService {
|
|
3247
|
+
private db;
|
|
3248
|
+
private options;
|
|
3249
|
+
private entryRepo;
|
|
3250
|
+
private searchService;
|
|
3251
|
+
private embeddingService;
|
|
3252
|
+
constructor(db: SQLiteAdapter, options: WikiOptions, entryRepo: EntryRepository, searchService: SearchService, embeddingService: EmbeddingService);
|
|
3253
|
+
/**
|
|
3254
|
+
* Link `oldId` → `newId` inside the caller's transaction. `newId` must
|
|
3255
|
+
* already exist. Throws WikiSupersedeError on any rule violation; the
|
|
3256
|
+
* caller's transaction then rolls back.
|
|
3257
|
+
*/
|
|
3258
|
+
supersedeInTx(tx: SQLiteAdapter, entityId: string, oldId: string, newId: string, t: number, now: number): Promise<void>;
|
|
3259
|
+
supersede(entityId: string, oldId: string, replacement: SupersedeReplacement, options?: {
|
|
3260
|
+
validFrom?: number;
|
|
3261
|
+
}): Promise<{
|
|
3262
|
+
newId: string;
|
|
3263
|
+
}>;
|
|
3264
|
+
history(entityId: string, factId: string): Promise<WikiFact[]>;
|
|
3265
|
+
}
|
|
3266
|
+
|
|
2731
3267
|
/** Typed escape hatch for tests — not part of the supported consumer API. */
|
|
2732
3268
|
interface WikiMemoryTestAccess {
|
|
2733
3269
|
embeddingService: EmbeddingService;
|
|
2734
3270
|
importExportService: ImportExportService;
|
|
2735
3271
|
ingestionService: IngestionService;
|
|
2736
3272
|
maintenanceService: MaintenanceService;
|
|
3273
|
+
maintenanceScheduler: MaintenanceScheduler;
|
|
2737
3274
|
retrievalService: RetrievalService;
|
|
2738
3275
|
searchService: SearchService;
|
|
2739
3276
|
writeService: WriteService;
|
|
2740
3277
|
promptService: PromptService;
|
|
2741
3278
|
graphTraversalService: GraphTraversalService;
|
|
3279
|
+
temporalService: TemporalService;
|
|
2742
3280
|
entryRepo: EntryRepository;
|
|
2743
3281
|
sourceRefIndexRepo: SourceRefIndexRepository;
|
|
2744
3282
|
metadataRepo: MetadataRepository;
|
|
@@ -2761,6 +3299,7 @@ declare class WikiMemory {
|
|
|
2761
3299
|
private jobManager;
|
|
2762
3300
|
private ingestionService;
|
|
2763
3301
|
private maintenanceService;
|
|
3302
|
+
private maintenanceScheduler;
|
|
2764
3303
|
private importExportService;
|
|
2765
3304
|
private retrievalService;
|
|
2766
3305
|
private writeService;
|
|
@@ -2769,6 +3308,7 @@ declare class WikiMemory {
|
|
|
2769
3308
|
private graphTraversalService;
|
|
2770
3309
|
private lintRepo;
|
|
2771
3310
|
private lintService;
|
|
3311
|
+
private temporalService;
|
|
2772
3312
|
private readonly okfTrustWrites;
|
|
2773
3313
|
constructor(db: SQLiteAdapter, options: WikiOptions);
|
|
2774
3314
|
/**
|
|
@@ -2884,6 +3424,17 @@ declare class WikiMemory {
|
|
|
2884
3424
|
traverseGraph(entityId: string, options: GraphTraversalOptions): Promise<GraphNeighborhood>;
|
|
2885
3425
|
getMemoryBundle(entityId: string): Promise<MemoryBundle>;
|
|
2886
3426
|
write(entityId: string, event: Omit<WikiEvent, 'id' | 'entity_id' | 'created_at'>): Promise<void>;
|
|
3427
|
+
/** Await auto-mode background librarian/heal jobs started by write(). No-op in 'deferred' mode. */
|
|
3428
|
+
drain(): Promise<void>;
|
|
3429
|
+
/**
|
|
3430
|
+
* Report which entities have pending maintenance work (librarian events
|
|
3431
|
+
* behind the watermark, heal backlog, unembedded facts) without running
|
|
3432
|
+
* anything. Entities with no pending work are omitted; sorted by
|
|
3433
|
+
* `pendingEvents` desc then `entityId` asc.
|
|
3434
|
+
*/
|
|
3435
|
+
getPendingMaintenance(entityIds?: string[]): Promise<PendingMaintenance[]>;
|
|
3436
|
+
/** Run pending librarian/heal/reembed work under an optional token budget and deadline (spec §6.2). Nothing runs after it resolves. */
|
|
3437
|
+
runPendingMaintenance(options?: RunPendingMaintenanceOptions): Promise<RunPendingMaintenanceResult>;
|
|
2887
3438
|
/**
|
|
2888
3439
|
* @param options.promptOverride - Applies only to this manual call. Does NOT affect
|
|
2889
3440
|
* WriteService-triggered auto-runs. For persistent prompt customization across auto-runs,
|
|
@@ -2942,6 +3493,28 @@ declare class WikiMemory {
|
|
|
2942
3493
|
getEntityStatus(entityId: string): EntityStatus;
|
|
2943
3494
|
subscribeEntityStatus(entityId: string, callback: (status: EntityStatus) => void): () => void;
|
|
2944
3495
|
clearVectorCache(): void;
|
|
3496
|
+
/**
|
|
3497
|
+
* Brings the keyword search index up to date with SQLite after a host
|
|
3498
|
+
* transaction that used `upsertGraph` has committed. Core never sees that
|
|
3499
|
+
* commit, so without this the nodes stay out of keyword, hybrid and
|
|
3500
|
+
* fallback retrieval until the entity's next core write.
|
|
3501
|
+
*
|
|
3502
|
+
* With `entityId`, rebuilds that entity if it is stale or has never been
|
|
3503
|
+
* indexed; otherwise it is a no-op that still waits for rebuilds already
|
|
3504
|
+
* queued. Without an argument, rebuilds every entity currently marked
|
|
3505
|
+
* stale; when none is, it resolves immediately and does not wait for rebuilds
|
|
3506
|
+
* already queued.
|
|
3507
|
+
*
|
|
3508
|
+
* Call only after the host's transaction commits: called inside it, the
|
|
3509
|
+
* rebuild may index rows that later roll back, or miss them and clear the
|
|
3510
|
+
* stale flag anyway. Serialized with core's internal index syncs and takes
|
|
3511
|
+
* no maintenance lock. Never rejects for a valid `entityId` — on failure the
|
|
3512
|
+
* entity stays stale and the next call retries it. Does not compute
|
|
3513
|
+
* embeddings; that remains the maintenance sweep's job.
|
|
3514
|
+
*
|
|
3515
|
+
* @throws {TypeError} when `entityId` is given but is not a non-empty string.
|
|
3516
|
+
*/
|
|
3517
|
+
syncSearchIndex(entityId?: string): Promise<void>;
|
|
2945
3518
|
exportDump(entityIds?: string[]): Promise<MemoryDump>;
|
|
2946
3519
|
/** Entity summary prose persisted from an OKF profile ≥ 1 import; null when none stored. */
|
|
2947
3520
|
getEntitySummary(entityId: string): Promise<string | null>;
|
|
@@ -2963,6 +3536,18 @@ declare class WikiMemory {
|
|
|
2963
3536
|
};
|
|
2964
3537
|
metadataReset?: boolean;
|
|
2965
3538
|
}>;
|
|
3539
|
+
/**
|
|
3540
|
+
* End `oldId`'s validity and link it to its replacement (spec §4.3). One
|
|
3541
|
+
* transaction. Throws `WikiSupersedeError` for missing, foreign, already
|
|
3542
|
+
* superseded, immutable-document, or cyclic targets.
|
|
3543
|
+
*/
|
|
3544
|
+
supersede(entityId: string, oldId: string, replacement: SupersedeReplacement, options?: {
|
|
3545
|
+
validFrom?: number;
|
|
3546
|
+
}): Promise<{
|
|
3547
|
+
newId: string;
|
|
3548
|
+
}>;
|
|
3549
|
+
/** The supersession chain containing `factId`, oldest first. [] when unknown. */
|
|
3550
|
+
history(entityId: string, factId: string): Promise<WikiFact[]>;
|
|
2966
3551
|
/**
|
|
2967
3552
|
* Full and partial ingestion both reject foreign-owned generated fact IDs with
|
|
2968
3553
|
* `WikiGraphNodeOwnershipConflict`. Such collisions are unexpected. Ingestion
|
|
@@ -2992,9 +3577,11 @@ declare class WikiMemory {
|
|
|
2992
3577
|
* MUST be called from inside an open `db.withTransactionAsync` callback —
|
|
2993
3578
|
* the third argument is the caller's `tx`. The method does not open a
|
|
2994
3579
|
* nested transaction, does not acquire any lock, and does not perform
|
|
2995
|
-
* post-commit work (search sync, embedding, cache eviction).
|
|
2996
|
-
*
|
|
2997
|
-
* (`
|
|
3580
|
+
* post-commit work (search sync, embedding, cache eviction). After the
|
|
3581
|
+
* transaction commits, call `syncSearchIndex(entityId)` — or
|
|
3582
|
+
* `syncSearchIndex()` after writing several entities in one transaction —
|
|
3583
|
+
* to make the new nodes keyword-searchable. Embeddings still come from the maintenance
|
|
3584
|
+
* sweep (`runLibrarian` / `runHeal` / `runOntologyBackfill` / `runPrune`,
|
|
2998
3585
|
* scoped via `listEntityIds`).
|
|
2999
3586
|
*
|
|
3000
3587
|
* Contract (full pre-flight validation lives inside
|
|
@@ -3154,4 +3741,4 @@ declare class WikiMemory {
|
|
|
3154
3741
|
setGeneratedByTask(taskId: string, entityId: string, actor: string): Promise<void>;
|
|
3155
3742
|
}
|
|
3156
3743
|
|
|
3157
|
-
export { type
|
|
3744
|
+
export { type ReembedResult as $, ONTOLOGY_BACKFILL_RECHECK_MS as A, type OntologyBackfillResult as B, type ChunkFailure as C, type DegradedRecord as D, type EmbedFactResult as E, type FormatContextOptions as F, type GraphNeighborhood as G, HEAL_BATCH_SIZE as H, type IngestDocumentResult as I, type OntologyConfig as J, type OntologyEdgeType as K, type LLMProvider as L, type MemoryBundle as M, type OntologyManifest as N, ONTOLOGY_BACKFILL_BATCH_SIZE as O, type OntologyMode as P, type OntologyNodeType as Q, type ReadOptions as R, type SQLiteAdapter as S, type OntologyPromptContext as T, type OntologyUpdates as U, type PendingMaintenance as V, type WikiOptions as W, type PendingSourceStatus as X, type PromptOverrides as Y, PromptService as Z, PrunePartialFailureError as _, type MemoryDump as a, type RunPendingMaintenanceOptions as a0, type RunPendingMaintenanceResult as a1, type SupersedeReplacement as a2, type VectorRanker as a3, type VectorRankerFallback as a4, type VectorRankerRankArgs as a5, type VectorRankerSemanticResult as a6, WikiBusyError as a7, type WikiBusyOperation as a8, type WikiCheckpoint as a9, validateManifest as aA, EmbeddingService as aB, ImportExportService as aC, IngestionService as aD, JobManager as aE, MaintenanceService as aF, RetrievalService as aG, SearchService as aH, WriteService as aI, type WikiConfig as aa, type WikiDiagnostic as ab, type WikiDiagnosticCode as ac, type WikiDiagnosticDetail as ad, type WikiDiagnosticOperation as ae, type WikiDiagnosticSeverity as af, type WikiDiagnosticTrigger as ag, WikiDraftNotFound as ah, WikiDuplicateHashError as ai, type WikiEdge as aj, type WikiEvent as ak, type WikiFact as al, WikiGraphNodeOwnershipConflict as am, WikiIngestEmptyError as an, type WikiInstructions as ao, WikiInvalidReadOptions as ap, type WikiLintReport as aq, type WikiMemoryTestAccess as ar, type WikiOutboxEvent as as, WikiParseError as at, WikiSourceRefHashCollision as au, WikiStrictOntologyViolation as av, WikiSupersedeError as aw, type WikiSupersedeReason as ax, type WikiTask as ay, WikiTransactionError as az, type FormattedMemoryDump as b, WikiMemory as c, type ClassifierAnswer as d, type ClassifierQuestion as e, type ClassifyRequest as f, type ClassifyResponse as g, type DraftPage as h, type EmbedFailureKind as i, type EmbeddingMarkerKind as j, type EntityMaintenanceReport as k, type EntityStatus as l, type ExtractedFact as m, type ExtractedFactEdge as n, type ExtractedFactWithOntology as o, type ExtractedTask as p, type GraphTraversalOptions as q, type GroundingConfig as r, HEAL_RECHECK_MS as s, HOOK_TIMEOUT_MARKER as t, type HealResult as u, type LibrarianConfig as v, type LibrarianGateConfig as w, type MaintenanceJob as x, type MaintenanceStopReason as y, ONTOLOGY_BACKFILL_MAX_PROMPT_CHARS as z };
|