@equationalapplications/core-llm-wiki 7.1.2 → 7.1.3
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 +36 -3
- package/dist/{chunk-ZU7K6NAU.mjs → chunk-TTECJ3S3.mjs} +59 -3
- package/dist/chunk-TTECJ3S3.mjs.map +1 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +113 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +58 -5
- package/dist/index.mjs.map +1 -1
- package/dist/{testing-CA7723qk.d.mts → testing-DYeMd9d1.d.mts} +110 -1
- package/dist/{testing-CA7723qk.d.ts → testing-DYeMd9d1.d.ts} +110 -1
- package/dist/testing.d.mts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +56 -0
- package/dist/testing.js.map +1 -1
- package/dist/testing.mjs +1 -1
- package/package.json +2 -2
- package/dist/chunk-ZU7K6NAU.mjs.map +0 -1
|
@@ -8,6 +8,18 @@ import { SearchResult } from 'minisearch';
|
|
|
8
8
|
*/
|
|
9
9
|
interface SQLiteAdapter {
|
|
10
10
|
execAsync(sql: string): Promise<void>;
|
|
11
|
+
/**
|
|
12
|
+
* `changes` must report the number of rows the statement actually wrote.
|
|
13
|
+
* It must be 0 when a conflict clause suppresses a write (INSERT OR IGNORE,
|
|
14
|
+
* or ON CONFLICT DO UPDATE ... WHERE), and must never be nonzero for a
|
|
15
|
+
* suppressed write. A permitted write that modifies no column value still
|
|
16
|
+
* counts the row, as SQLite does.
|
|
17
|
+
*
|
|
18
|
+
* This count is load-bearing beyond ownership checks: edge insertion
|
|
19
|
+
* (and therefore upsertGraph's public edgesWritten), metadata compare-and-set,
|
|
20
|
+
* soft-delete success reporting, and maintenance sweep counts all read it.
|
|
21
|
+
* An adapter that under-reports silently corrupts those results.
|
|
22
|
+
*/
|
|
11
23
|
runAsync(sql: string, params?: unknown[]): Promise<{
|
|
12
24
|
changes: number;
|
|
13
25
|
lastInsertRowId: number;
|
|
@@ -740,6 +752,33 @@ declare class WikiSourceRefHashCollision extends Error {
|
|
|
740
752
|
attemptedSourceRef: string;
|
|
741
753
|
});
|
|
742
754
|
}
|
|
755
|
+
/**
|
|
756
|
+
* Thrown when a graph node ID is already owned by another entity.
|
|
757
|
+
*
|
|
758
|
+
* Raised by `WikiMemory.upsertGraph`'s node-ownership pre-flight and,
|
|
759
|
+
* independently, by `EntryRepository.upsert` for every caller — which is why
|
|
760
|
+
* `ingestDocument` can surface it too (it shares `upsertGraphCore` on its full
|
|
761
|
+
* path and `EntryRepository.upsert` on its partial path).
|
|
762
|
+
*
|
|
763
|
+
* Deliberately carries NO context: no owner entity, node ID, stored content,
|
|
764
|
+
* provenance, or `cause`. A rejection is reachable by whatever supplies the
|
|
765
|
+
* node IDs, so the error must not become a channel for reading another
|
|
766
|
+
* entity's identifiers. The `WIKI_`-prefixed code and fixed message also keep
|
|
767
|
+
* it clear of `extractSqliteCode`, so it passes through the serialized
|
|
768
|
+
* transaction wrapper unwrapped.
|
|
769
|
+
*/
|
|
770
|
+
declare class WikiGraphNodeOwnershipConflict extends Error {
|
|
771
|
+
readonly code: "WIKI_GRAPH_NODE_OWNERSHIP_CONFLICT";
|
|
772
|
+
/**
|
|
773
|
+
* Privacy-preserving constructor: accepts no arguments, so neither the foreign
|
|
774
|
+
* owner, the conflicting node ID, the stored content, nor any provenance can
|
|
775
|
+
* leak through this error. The fixed message and `code` are the entire signal.
|
|
776
|
+
*
|
|
777
|
+
* @returns a contextless `WikiGraphNodeOwnershipConflict` instance. See the
|
|
778
|
+
* class-level JSDoc for the privacy rationale.
|
|
779
|
+
*/
|
|
780
|
+
constructor();
|
|
781
|
+
}
|
|
743
782
|
/**
|
|
744
783
|
* Thrown by the serialized transaction wrapper when a SQLite driver error
|
|
745
784
|
* escapes a transaction callback (nested BEGIN, SQLITE_BUSY, constraint
|
|
@@ -965,6 +1004,26 @@ declare class EntryRepository extends BaseRepository {
|
|
|
965
1004
|
* diagnostic that inflates runReembed's permanentlyFailed counter. A conflict
|
|
966
1005
|
* with no blob leaves marker state alone, matching the "absent means don't
|
|
967
1006
|
* touch" semantics used for embedding_blob itself.
|
|
1007
|
+
*
|
|
1008
|
+
* Graph node ownership (spec §2.4 + §3, REQ-OWN-01 + REQ-GRAPH-01): entry
|
|
1009
|
+
* IDs share one database-wide namespace, so an ID stays owned by its
|
|
1010
|
+
* existing entity for as long as the row exists — soft deletion included.
|
|
1011
|
+
* The pre-write lookup already reads the existing row for OKF metadata; we
|
|
1012
|
+
* project `entity_id` off that same SELECT and reject the write before
|
|
1013
|
+
* any outbox payload construction when the stored owner differs from
|
|
1014
|
+
* `fact.entity_id`. Soft-deleted foreign rows keep their IDs reserved;
|
|
1015
|
+
* permanent reservation is NOT introduced, so a physically absent ID may
|
|
1016
|
+
* still be inserted under the requested entity. The ON CONFLICT UPDATE SET
|
|
1017
|
+
* clause carries a final `WHERE entries.entity_id = excluded.entity_id`
|
|
1018
|
+
* guard so the database itself refuses a cross-owner row overwrite even if
|
|
1019
|
+
* a future caller bypasses the pre-write check. When `runAsync` reports
|
|
1020
|
+
* 0 changes (a legitimate conflict-suppressed write, OR an adapter that
|
|
1021
|
+
* under-reports a permitted write) we re-read the stored owner; only a
|
|
1022
|
+
* foreign owner throws — this is local defensive behavior, not permission
|
|
1023
|
+
* for adapters to under-report. The thrown error is
|
|
1024
|
+
* `WikiGraphNodeOwnershipConflict` (no owner, node ID, or stored content
|
|
1025
|
+
* is disclosed). Upserts that pass both gates retain existing same-entity
|
|
1026
|
+
* update + resurrection semantics.
|
|
968
1027
|
*/
|
|
969
1028
|
upsert(fact: WikiFact, tx: SQLiteAdapter): Promise<{
|
|
970
1029
|
changes: number;
|
|
@@ -1814,6 +1873,28 @@ declare class IngestionService {
|
|
|
1814
1873
|
}, opts?: {
|
|
1815
1874
|
onDuplicateHash?: 'ingest' | 'skip' | 'throw';
|
|
1816
1875
|
}): Promise<IngestDocumentResult>;
|
|
1876
|
+
/**
|
|
1877
|
+
* Reject the whole write when any incoming node ID is already owned by a
|
|
1878
|
+
* different entity. Runs entirely inside the supplied `tx`, through the
|
|
1879
|
+
* repository abstraction, and — being the first thing `upsertGraphCore`
|
|
1880
|
+
* does — before ontology resolution, which can itself persist a configured
|
|
1881
|
+
* seed manifest.
|
|
1882
|
+
*
|
|
1883
|
+
* The lookup has no deleted-row filter, so a soft-deleted foreign row keeps
|
|
1884
|
+
* its ID reserved. Only the lookup IDs are deduplicated; `params.nodes` and
|
|
1885
|
+
* the later write loops keep their ordering and counts.
|
|
1886
|
+
*
|
|
1887
|
+
* The error is deliberately contextless — see WikiGraphNodeOwnershipConflict.
|
|
1888
|
+
*
|
|
1889
|
+
* @param entityId - the entity the caller is writing on behalf of. Foreign
|
|
1890
|
+
* rows under a different entity trigger the rejection.
|
|
1891
|
+
* @param nodes - incoming node set; only the IDs are inspected, so callers
|
|
1892
|
+
* may pass the public `params.nodes` shape directly without slicing.
|
|
1893
|
+
* @param tx - the open transaction. Reuses the same handle every later
|
|
1894
|
+
* statement in `upsertGraphCore` runs against, so atomicity is enforced
|
|
1895
|
+
* by the host transaction's commit/rollback, not by this method.
|
|
1896
|
+
*/
|
|
1897
|
+
private assertGraphNodeOwnership;
|
|
1817
1898
|
/**
|
|
1818
1899
|
* Implements spec §2 data flow steps a–j with the host-facing
|
|
1819
1900
|
* `{sourceRef, sourceHash, nodes, edges}` parameter shape. Shared between
|
|
@@ -1832,6 +1913,16 @@ declare class IngestionService {
|
|
|
1832
1913
|
* @returns Counts: nodesWritten (validated nodes persisted), edgesWritten
|
|
1833
1914
|
* (manifest-valid edges persisted), superseded (prior facts soft-deleted
|
|
1834
1915
|
* plus prior source-ref edges hard-deleted).
|
|
1916
|
+
*
|
|
1917
|
+
* Node-ownership pre-flight (spec §3, REQ-GRAPH-01): the first statement
|
|
1918
|
+
* is `assertGraphNodeOwnership(entityId, params.nodes, tx)`, which runs
|
|
1919
|
+
* before ontology resolution, seed-manifest persistence, and every other
|
|
1920
|
+
* write. A foreign-owned ID throws `WikiGraphNodeOwnershipConflict` with
|
|
1921
|
+
* no disclosed owner, node ID, or content; the caller's transaction
|
|
1922
|
+
* remains open and must be rolled back by the host. Soft-deleted foreign
|
|
1923
|
+
* rows keep their IDs reserved. Duplicate incoming IDs are deduplicated
|
|
1924
|
+
* only for the lookup; `params.nodes` and the write loops keep their
|
|
1925
|
+
* ordering and counts so success counts match the pre-change contract.
|
|
1835
1926
|
*/
|
|
1836
1927
|
upsertGraphCore(entityId: string, params: {
|
|
1837
1928
|
sourceRef: string;
|
|
@@ -2451,6 +2542,11 @@ declare class WikiMemory {
|
|
|
2451
2542
|
metadataReset?: boolean;
|
|
2452
2543
|
}>;
|
|
2453
2544
|
/**
|
|
2545
|
+
* Full and partial ingestion both reject foreign-owned generated fact IDs with
|
|
2546
|
+
* `WikiGraphNodeOwnershipConflict`. Such collisions are unexpected. Ingestion
|
|
2547
|
+
* may already have persisted ontology or other state before rejection; unlike
|
|
2548
|
+
* direct graph preflight, it relies on transaction rollback for atomicity.
|
|
2549
|
+
*
|
|
2454
2550
|
* @param params.promptOverride - Overrides the system prompt for this ingest call only.
|
|
2455
2551
|
* For persistent customization, set `options.config.prompts.ingestSystemPrompt` at
|
|
2456
2552
|
* WikiMemory construction time.
|
|
@@ -2490,6 +2586,19 @@ declare class WikiMemory {
|
|
|
2490
2586
|
* or edge `type` throws `WikiStrictOntologyViolation` (pre-flight,
|
|
2491
2587
|
* all-or-nothing — NONE written on failure).
|
|
2492
2588
|
*
|
|
2589
|
+
* Entry IDs share one database-wide namespace. Existing rows, including
|
|
2590
|
+
* soft-deleted rows, reserve their IDs for their entity; same-entity updates
|
|
2591
|
+
* and resurrection remain supported. Hosts authenticate callers and select
|
|
2592
|
+
* the authorized entity ID; entity-qualified IDs are optional, not required.
|
|
2593
|
+
* After the live-only C2 probe above, a foreign node ID throws the fixed,
|
|
2594
|
+
* privacy-preserving `WikiGraphNodeOwnershipConflict` before persistent writes
|
|
2595
|
+
* (including seed manifests). Deleted source mappings do not trigger C2.
|
|
2596
|
+
*
|
|
2597
|
+
* Propagate later failures to roll back the host transaction. In particular,
|
|
2598
|
+
* foreign edge-ID collisions remain late bare `Error`s: the foreign edge is
|
|
2599
|
+
* not overwritten, but catching and committing can retain earlier writes.
|
|
2600
|
+
* This method neither commits nor rolls back the caller's transaction.
|
|
2601
|
+
*
|
|
2493
2602
|
* @returns Counts: nodesWritten (validated nodes persisted), edgesWritten
|
|
2494
2603
|
* (manifest-valid edges persisted), superseded (prior facts soft-deleted
|
|
2495
2604
|
* plus prior source-ref edges hard-deleted).
|
|
@@ -2604,4 +2713,4 @@ declare class WikiMemory {
|
|
|
2604
2713
|
setGeneratedByTask(taskId: string, entityId: string, actor: string): Promise<void>;
|
|
2605
2714
|
}
|
|
2606
2715
|
|
|
2607
|
-
export {
|
|
2716
|
+
export { WikiGraphNodeOwnershipConflict as $, type ReembedResult as A, type VectorRankerFallback 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 VectorRankerRankArgs as J, type VectorRankerSemanticResult as K, type LLMProvider as L, type MemoryBundle as M, WikiBusyError as N, type OntologyManifest as O, type PromptOverrides as P, type WikiBusyOperation as Q, type ReadOptions as R, type SQLiteAdapter as S, type WikiCheckpoint as T, type WikiConfig as U, type VectorRanker as V, type WikiOptions as W, WikiDuplicateHashError as X, type WikiEdge as Y, type WikiEvent as Z, type WikiFact as _, type MemoryDump as a, WikiIngestEmptyError as a0, WikiInvalidReadOptions as a1, type WikiMemoryTestAccess as a2, type WikiOutboxEvent as a3, WikiParseError as a4, WikiSourceRefHashCollision as a5, WikiStrictOntologyViolation as a6, type WikiTask as a7, WikiTransactionError as a8, EmbeddingService as a9, ImportExportService as aa, IngestionService as ab, JobManager as ac, MaintenanceService as ad, RetrievalService as ae, SearchService as af, WriteService as ag, type FormattedMemoryDump as b, WikiMemory as c, type EmbedFailureKind as d, type EmbeddingMarkerKind as e, type EntityStatus as f, type ExtractedFact as g, type ExtractedFactEdge as h, type ExtractedFactWithOntology as i, type ExtractedTask as j, type GraphTraversalOptions as k, HEAL_RECHECK_MS as l, HOOK_TIMEOUT_MARKER as m, type HealResult as n, ONTOLOGY_BACKFILL_BATCH_SIZE as o, ONTOLOGY_BACKFILL_MAX_PROMPT_CHARS as p, ONTOLOGY_BACKFILL_RECHECK_MS as q, type OntologyBackfillResult as r, type OntologyConfig as s, type OntologyEdgeType as t, type OntologyMode as u, type OntologyNodeType as v, type OntologyPromptContext as w, type OntologyUpdates as x, PromptService as y, PrunePartialFailureError as z };
|
|
@@ -8,6 +8,18 @@ import { SearchResult } from 'minisearch';
|
|
|
8
8
|
*/
|
|
9
9
|
interface SQLiteAdapter {
|
|
10
10
|
execAsync(sql: string): Promise<void>;
|
|
11
|
+
/**
|
|
12
|
+
* `changes` must report the number of rows the statement actually wrote.
|
|
13
|
+
* It must be 0 when a conflict clause suppresses a write (INSERT OR IGNORE,
|
|
14
|
+
* or ON CONFLICT DO UPDATE ... WHERE), and must never be nonzero for a
|
|
15
|
+
* suppressed write. A permitted write that modifies no column value still
|
|
16
|
+
* counts the row, as SQLite does.
|
|
17
|
+
*
|
|
18
|
+
* This count is load-bearing beyond ownership checks: edge insertion
|
|
19
|
+
* (and therefore upsertGraph's public edgesWritten), metadata compare-and-set,
|
|
20
|
+
* soft-delete success reporting, and maintenance sweep counts all read it.
|
|
21
|
+
* An adapter that under-reports silently corrupts those results.
|
|
22
|
+
*/
|
|
11
23
|
runAsync(sql: string, params?: unknown[]): Promise<{
|
|
12
24
|
changes: number;
|
|
13
25
|
lastInsertRowId: number;
|
|
@@ -740,6 +752,33 @@ declare class WikiSourceRefHashCollision extends Error {
|
|
|
740
752
|
attemptedSourceRef: string;
|
|
741
753
|
});
|
|
742
754
|
}
|
|
755
|
+
/**
|
|
756
|
+
* Thrown when a graph node ID is already owned by another entity.
|
|
757
|
+
*
|
|
758
|
+
* Raised by `WikiMemory.upsertGraph`'s node-ownership pre-flight and,
|
|
759
|
+
* independently, by `EntryRepository.upsert` for every caller — which is why
|
|
760
|
+
* `ingestDocument` can surface it too (it shares `upsertGraphCore` on its full
|
|
761
|
+
* path and `EntryRepository.upsert` on its partial path).
|
|
762
|
+
*
|
|
763
|
+
* Deliberately carries NO context: no owner entity, node ID, stored content,
|
|
764
|
+
* provenance, or `cause`. A rejection is reachable by whatever supplies the
|
|
765
|
+
* node IDs, so the error must not become a channel for reading another
|
|
766
|
+
* entity's identifiers. The `WIKI_`-prefixed code and fixed message also keep
|
|
767
|
+
* it clear of `extractSqliteCode`, so it passes through the serialized
|
|
768
|
+
* transaction wrapper unwrapped.
|
|
769
|
+
*/
|
|
770
|
+
declare class WikiGraphNodeOwnershipConflict extends Error {
|
|
771
|
+
readonly code: "WIKI_GRAPH_NODE_OWNERSHIP_CONFLICT";
|
|
772
|
+
/**
|
|
773
|
+
* Privacy-preserving constructor: accepts no arguments, so neither the foreign
|
|
774
|
+
* owner, the conflicting node ID, the stored content, nor any provenance can
|
|
775
|
+
* leak through this error. The fixed message and `code` are the entire signal.
|
|
776
|
+
*
|
|
777
|
+
* @returns a contextless `WikiGraphNodeOwnershipConflict` instance. See the
|
|
778
|
+
* class-level JSDoc for the privacy rationale.
|
|
779
|
+
*/
|
|
780
|
+
constructor();
|
|
781
|
+
}
|
|
743
782
|
/**
|
|
744
783
|
* Thrown by the serialized transaction wrapper when a SQLite driver error
|
|
745
784
|
* escapes a transaction callback (nested BEGIN, SQLITE_BUSY, constraint
|
|
@@ -965,6 +1004,26 @@ declare class EntryRepository extends BaseRepository {
|
|
|
965
1004
|
* diagnostic that inflates runReembed's permanentlyFailed counter. A conflict
|
|
966
1005
|
* with no blob leaves marker state alone, matching the "absent means don't
|
|
967
1006
|
* touch" semantics used for embedding_blob itself.
|
|
1007
|
+
*
|
|
1008
|
+
* Graph node ownership (spec §2.4 + §3, REQ-OWN-01 + REQ-GRAPH-01): entry
|
|
1009
|
+
* IDs share one database-wide namespace, so an ID stays owned by its
|
|
1010
|
+
* existing entity for as long as the row exists — soft deletion included.
|
|
1011
|
+
* The pre-write lookup already reads the existing row for OKF metadata; we
|
|
1012
|
+
* project `entity_id` off that same SELECT and reject the write before
|
|
1013
|
+
* any outbox payload construction when the stored owner differs from
|
|
1014
|
+
* `fact.entity_id`. Soft-deleted foreign rows keep their IDs reserved;
|
|
1015
|
+
* permanent reservation is NOT introduced, so a physically absent ID may
|
|
1016
|
+
* still be inserted under the requested entity. The ON CONFLICT UPDATE SET
|
|
1017
|
+
* clause carries a final `WHERE entries.entity_id = excluded.entity_id`
|
|
1018
|
+
* guard so the database itself refuses a cross-owner row overwrite even if
|
|
1019
|
+
* a future caller bypasses the pre-write check. When `runAsync` reports
|
|
1020
|
+
* 0 changes (a legitimate conflict-suppressed write, OR an adapter that
|
|
1021
|
+
* under-reports a permitted write) we re-read the stored owner; only a
|
|
1022
|
+
* foreign owner throws — this is local defensive behavior, not permission
|
|
1023
|
+
* for adapters to under-report. The thrown error is
|
|
1024
|
+
* `WikiGraphNodeOwnershipConflict` (no owner, node ID, or stored content
|
|
1025
|
+
* is disclosed). Upserts that pass both gates retain existing same-entity
|
|
1026
|
+
* update + resurrection semantics.
|
|
968
1027
|
*/
|
|
969
1028
|
upsert(fact: WikiFact, tx: SQLiteAdapter): Promise<{
|
|
970
1029
|
changes: number;
|
|
@@ -1814,6 +1873,28 @@ declare class IngestionService {
|
|
|
1814
1873
|
}, opts?: {
|
|
1815
1874
|
onDuplicateHash?: 'ingest' | 'skip' | 'throw';
|
|
1816
1875
|
}): Promise<IngestDocumentResult>;
|
|
1876
|
+
/**
|
|
1877
|
+
* Reject the whole write when any incoming node ID is already owned by a
|
|
1878
|
+
* different entity. Runs entirely inside the supplied `tx`, through the
|
|
1879
|
+
* repository abstraction, and — being the first thing `upsertGraphCore`
|
|
1880
|
+
* does — before ontology resolution, which can itself persist a configured
|
|
1881
|
+
* seed manifest.
|
|
1882
|
+
*
|
|
1883
|
+
* The lookup has no deleted-row filter, so a soft-deleted foreign row keeps
|
|
1884
|
+
* its ID reserved. Only the lookup IDs are deduplicated; `params.nodes` and
|
|
1885
|
+
* the later write loops keep their ordering and counts.
|
|
1886
|
+
*
|
|
1887
|
+
* The error is deliberately contextless — see WikiGraphNodeOwnershipConflict.
|
|
1888
|
+
*
|
|
1889
|
+
* @param entityId - the entity the caller is writing on behalf of. Foreign
|
|
1890
|
+
* rows under a different entity trigger the rejection.
|
|
1891
|
+
* @param nodes - incoming node set; only the IDs are inspected, so callers
|
|
1892
|
+
* may pass the public `params.nodes` shape directly without slicing.
|
|
1893
|
+
* @param tx - the open transaction. Reuses the same handle every later
|
|
1894
|
+
* statement in `upsertGraphCore` runs against, so atomicity is enforced
|
|
1895
|
+
* by the host transaction's commit/rollback, not by this method.
|
|
1896
|
+
*/
|
|
1897
|
+
private assertGraphNodeOwnership;
|
|
1817
1898
|
/**
|
|
1818
1899
|
* Implements spec §2 data flow steps a–j with the host-facing
|
|
1819
1900
|
* `{sourceRef, sourceHash, nodes, edges}` parameter shape. Shared between
|
|
@@ -1832,6 +1913,16 @@ declare class IngestionService {
|
|
|
1832
1913
|
* @returns Counts: nodesWritten (validated nodes persisted), edgesWritten
|
|
1833
1914
|
* (manifest-valid edges persisted), superseded (prior facts soft-deleted
|
|
1834
1915
|
* plus prior source-ref edges hard-deleted).
|
|
1916
|
+
*
|
|
1917
|
+
* Node-ownership pre-flight (spec §3, REQ-GRAPH-01): the first statement
|
|
1918
|
+
* is `assertGraphNodeOwnership(entityId, params.nodes, tx)`, which runs
|
|
1919
|
+
* before ontology resolution, seed-manifest persistence, and every other
|
|
1920
|
+
* write. A foreign-owned ID throws `WikiGraphNodeOwnershipConflict` with
|
|
1921
|
+
* no disclosed owner, node ID, or content; the caller's transaction
|
|
1922
|
+
* remains open and must be rolled back by the host. Soft-deleted foreign
|
|
1923
|
+
* rows keep their IDs reserved. Duplicate incoming IDs are deduplicated
|
|
1924
|
+
* only for the lookup; `params.nodes` and the write loops keep their
|
|
1925
|
+
* ordering and counts so success counts match the pre-change contract.
|
|
1835
1926
|
*/
|
|
1836
1927
|
upsertGraphCore(entityId: string, params: {
|
|
1837
1928
|
sourceRef: string;
|
|
@@ -2451,6 +2542,11 @@ declare class WikiMemory {
|
|
|
2451
2542
|
metadataReset?: boolean;
|
|
2452
2543
|
}>;
|
|
2453
2544
|
/**
|
|
2545
|
+
* Full and partial ingestion both reject foreign-owned generated fact IDs with
|
|
2546
|
+
* `WikiGraphNodeOwnershipConflict`. Such collisions are unexpected. Ingestion
|
|
2547
|
+
* may already have persisted ontology or other state before rejection; unlike
|
|
2548
|
+
* direct graph preflight, it relies on transaction rollback for atomicity.
|
|
2549
|
+
*
|
|
2454
2550
|
* @param params.promptOverride - Overrides the system prompt for this ingest call only.
|
|
2455
2551
|
* For persistent customization, set `options.config.prompts.ingestSystemPrompt` at
|
|
2456
2552
|
* WikiMemory construction time.
|
|
@@ -2490,6 +2586,19 @@ declare class WikiMemory {
|
|
|
2490
2586
|
* or edge `type` throws `WikiStrictOntologyViolation` (pre-flight,
|
|
2491
2587
|
* all-or-nothing — NONE written on failure).
|
|
2492
2588
|
*
|
|
2589
|
+
* Entry IDs share one database-wide namespace. Existing rows, including
|
|
2590
|
+
* soft-deleted rows, reserve their IDs for their entity; same-entity updates
|
|
2591
|
+
* and resurrection remain supported. Hosts authenticate callers and select
|
|
2592
|
+
* the authorized entity ID; entity-qualified IDs are optional, not required.
|
|
2593
|
+
* After the live-only C2 probe above, a foreign node ID throws the fixed,
|
|
2594
|
+
* privacy-preserving `WikiGraphNodeOwnershipConflict` before persistent writes
|
|
2595
|
+
* (including seed manifests). Deleted source mappings do not trigger C2.
|
|
2596
|
+
*
|
|
2597
|
+
* Propagate later failures to roll back the host transaction. In particular,
|
|
2598
|
+
* foreign edge-ID collisions remain late bare `Error`s: the foreign edge is
|
|
2599
|
+
* not overwritten, but catching and committing can retain earlier writes.
|
|
2600
|
+
* This method neither commits nor rolls back the caller's transaction.
|
|
2601
|
+
*
|
|
2493
2602
|
* @returns Counts: nodesWritten (validated nodes persisted), edgesWritten
|
|
2494
2603
|
* (manifest-valid edges persisted), superseded (prior facts soft-deleted
|
|
2495
2604
|
* plus prior source-ref edges hard-deleted).
|
|
@@ -2604,4 +2713,4 @@ declare class WikiMemory {
|
|
|
2604
2713
|
setGeneratedByTask(taskId: string, entityId: string, actor: string): Promise<void>;
|
|
2605
2714
|
}
|
|
2606
2715
|
|
|
2607
|
-
export {
|
|
2716
|
+
export { WikiGraphNodeOwnershipConflict as $, type ReembedResult as A, type VectorRankerFallback 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 VectorRankerRankArgs as J, type VectorRankerSemanticResult as K, type LLMProvider as L, type MemoryBundle as M, WikiBusyError as N, type OntologyManifest as O, type PromptOverrides as P, type WikiBusyOperation as Q, type ReadOptions as R, type SQLiteAdapter as S, type WikiCheckpoint as T, type WikiConfig as U, type VectorRanker as V, type WikiOptions as W, WikiDuplicateHashError as X, type WikiEdge as Y, type WikiEvent as Z, type WikiFact as _, type MemoryDump as a, WikiIngestEmptyError as a0, WikiInvalidReadOptions as a1, type WikiMemoryTestAccess as a2, type WikiOutboxEvent as a3, WikiParseError as a4, WikiSourceRefHashCollision as a5, WikiStrictOntologyViolation as a6, type WikiTask as a7, WikiTransactionError as a8, EmbeddingService as a9, ImportExportService as aa, IngestionService as ab, JobManager as ac, MaintenanceService as ad, RetrievalService as ae, SearchService as af, WriteService as ag, type FormattedMemoryDump as b, WikiMemory as c, type EmbedFailureKind as d, type EmbeddingMarkerKind as e, type EntityStatus as f, type ExtractedFact as g, type ExtractedFactEdge as h, type ExtractedFactWithOntology as i, type ExtractedTask as j, type GraphTraversalOptions as k, HEAL_RECHECK_MS as l, HOOK_TIMEOUT_MARKER as m, type HealResult as n, ONTOLOGY_BACKFILL_BATCH_SIZE as o, ONTOLOGY_BACKFILL_MAX_PROMPT_CHARS as p, ONTOLOGY_BACKFILL_RECHECK_MS as q, type OntologyBackfillResult as r, type OntologyConfig as s, type OntologyEdgeType as t, type OntologyMode as u, type OntologyNodeType as v, type OntologyPromptContext as w, type OntologyUpdates as x, PromptService as y, PrunePartialFailureError as z };
|
package/dist/testing.d.mts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { a9 as EmbeddingService, aa as ImportExportService, ab as IngestionService, ac as JobManager, ac as JobManagerType, ad as MaintenanceService, ae as RetrievalService, af as SearchService, af as SearchServiceType, a2 as WikiMemoryTestAccess, ag as WriteService } from './testing-DYeMd9d1.mjs';
|
|
2
2
|
import '@equationalapplications/core-okf';
|
|
3
3
|
import 'minisearch';
|
package/dist/testing.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { a9 as EmbeddingService, aa as ImportExportService, ab as IngestionService, ac as JobManager, ac as JobManagerType, ad as MaintenanceService, ae as RetrievalService, af as SearchService, af as SearchServiceType, a2 as WikiMemoryTestAccess, ag as WriteService } from './testing-DYeMd9d1.js';
|
|
2
2
|
import '@equationalapplications/core-okf';
|
|
3
3
|
import 'minisearch';
|
package/dist/testing.js
CHANGED
|
@@ -90,6 +90,21 @@ var WikiStrictOntologyViolation = class extends Error {
|
|
|
90
90
|
this.name = "WikiStrictOntologyViolation";
|
|
91
91
|
}
|
|
92
92
|
};
|
|
93
|
+
var WikiGraphNodeOwnershipConflict = class extends Error {
|
|
94
|
+
/**
|
|
95
|
+
* Privacy-preserving constructor: accepts no arguments, so neither the foreign
|
|
96
|
+
* owner, the conflicting node ID, the stored content, nor any provenance can
|
|
97
|
+
* leak through this error. The fixed message and `code` are the entire signal.
|
|
98
|
+
*
|
|
99
|
+
* @returns a contextless `WikiGraphNodeOwnershipConflict` instance. See the
|
|
100
|
+
* class-level JSDoc for the privacy rationale.
|
|
101
|
+
*/
|
|
102
|
+
constructor() {
|
|
103
|
+
super("Graph write rejected because a node ID is unavailable for this entity.");
|
|
104
|
+
this.code = "WIKI_GRAPH_NODE_OWNERSHIP_CONFLICT";
|
|
105
|
+
this.name = "WikiGraphNodeOwnershipConflict";
|
|
106
|
+
}
|
|
107
|
+
};
|
|
93
108
|
var WikiTransactionError = class extends Error {
|
|
94
109
|
constructor(message, options) {
|
|
95
110
|
super(message, options);
|
|
@@ -1738,6 +1753,36 @@ var IngestionService = class {
|
|
|
1738
1753
|
releaseIngestLocks();
|
|
1739
1754
|
}
|
|
1740
1755
|
}
|
|
1756
|
+
/**
|
|
1757
|
+
* Reject the whole write when any incoming node ID is already owned by a
|
|
1758
|
+
* different entity. Runs entirely inside the supplied `tx`, through the
|
|
1759
|
+
* repository abstraction, and — being the first thing `upsertGraphCore`
|
|
1760
|
+
* does — before ontology resolution, which can itself persist a configured
|
|
1761
|
+
* seed manifest.
|
|
1762
|
+
*
|
|
1763
|
+
* The lookup has no deleted-row filter, so a soft-deleted foreign row keeps
|
|
1764
|
+
* its ID reserved. Only the lookup IDs are deduplicated; `params.nodes` and
|
|
1765
|
+
* the later write loops keep their ordering and counts.
|
|
1766
|
+
*
|
|
1767
|
+
* The error is deliberately contextless — see WikiGraphNodeOwnershipConflict.
|
|
1768
|
+
*
|
|
1769
|
+
* @param entityId - the entity the caller is writing on behalf of. Foreign
|
|
1770
|
+
* rows under a different entity trigger the rejection.
|
|
1771
|
+
* @param nodes - incoming node set; only the IDs are inspected, so callers
|
|
1772
|
+
* may pass the public `params.nodes` shape directly without slicing.
|
|
1773
|
+
* @param tx - the open transaction. Reuses the same handle every later
|
|
1774
|
+
* statement in `upsertGraphCore` runs against, so atomicity is enforced
|
|
1775
|
+
* by the host transaction's commit/rollback, not by this method.
|
|
1776
|
+
*/
|
|
1777
|
+
async assertGraphNodeOwnership(entityId, nodes, tx) {
|
|
1778
|
+
const ids = [...new Set(nodes.map((node) => node.id))];
|
|
1779
|
+
const existing = await this.entryRepo.findExistingMetadataByIds(ids, tx);
|
|
1780
|
+
for (const row of existing) {
|
|
1781
|
+
if (row.entity_id !== entityId) {
|
|
1782
|
+
throw new WikiGraphNodeOwnershipConflict();
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1741
1786
|
/**
|
|
1742
1787
|
* Implements spec §2 data flow steps a–j with the host-facing
|
|
1743
1788
|
* `{sourceRef, sourceHash, nodes, edges}` parameter shape. Shared between
|
|
@@ -1756,8 +1801,19 @@ var IngestionService = class {
|
|
|
1756
1801
|
* @returns Counts: nodesWritten (validated nodes persisted), edgesWritten
|
|
1757
1802
|
* (manifest-valid edges persisted), superseded (prior facts soft-deleted
|
|
1758
1803
|
* plus prior source-ref edges hard-deleted).
|
|
1804
|
+
*
|
|
1805
|
+
* Node-ownership pre-flight (spec §3, REQ-GRAPH-01): the first statement
|
|
1806
|
+
* is `assertGraphNodeOwnership(entityId, params.nodes, tx)`, which runs
|
|
1807
|
+
* before ontology resolution, seed-manifest persistence, and every other
|
|
1808
|
+
* write. A foreign-owned ID throws `WikiGraphNodeOwnershipConflict` with
|
|
1809
|
+
* no disclosed owner, node ID, or content; the caller's transaction
|
|
1810
|
+
* remains open and must be rolled back by the host. Soft-deleted foreign
|
|
1811
|
+
* rows keep their IDs reserved. Duplicate incoming IDs are deduplicated
|
|
1812
|
+
* only for the lookup; `params.nodes` and the write loops keep their
|
|
1813
|
+
* ordering and counts so success counts match the pre-change contract.
|
|
1759
1814
|
*/
|
|
1760
1815
|
async upsertGraphCore(entityId, params, tx, opts) {
|
|
1816
|
+
await this.assertGraphNodeOwnership(entityId, params.nodes, tx);
|
|
1761
1817
|
const now = Date.now();
|
|
1762
1818
|
const ontologyState = await this.ontologyService?.getEffectiveState(entityId, tx) ?? { mode: "off", manifest: { node_types: [], edge_types: [] } };
|
|
1763
1819
|
let { mode, manifest } = ontologyState;
|