@cavelang/store 0.1.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 ADDED
@@ -0,0 +1,91 @@
1
+ # @cavelang/store
2
+
3
+ CAVE persistence on the **Node.js builtin `node:sqlite`** — no native
4
+ dependencies. Implements the spec §13 storage model: the exact §13.1/§13.2
5
+ schema (`cave_claim`, `cave_context`, `cave_tag`, `cave_edge`, `cave_fts`
6
+ FTS5), append-only belief series, and inverse-aware reads.
7
+
8
+ ```ts
9
+ import { open } from '@cavelang/store'
10
+
11
+ const store = open('knowledge.db') // or open() for in-memory
12
+ store.ingest(`
13
+ packages/api PART-OF monorepo @ 50%
14
+ monorepo CONTAINS packages/api @ 90%
15
+ `)
16
+ store.currentBeliefs() // one row — one fact, one key, conf 0.9
17
+ store.reverse('packages/api') // [{ verb: 'CONTAINS', rel: 'PART-OF', source: 'monorepo' }]
18
+ store.exportText({ current: true }) // canonical CAVE text back out
19
+ ```
20
+
21
+ ## Semantics
22
+
23
+ - **Append-only** (§9.1): `ingest` only inserts; every row carries a
24
+ monotonic UUIDv7 in `id` and `tx`, so `MAX(tx)` per `claim_key` is the
25
+ current belief. Each ingest call is one SQLite transaction.
26
+ - **One row per fact** (§13.3): inverse writes are canonicalized before
27
+ keying (`@cavelang/canonical`), inverse *reads* are query-time views —
28
+ `forward()` uses the subject index, `reverse()` the object index with the
29
+ relation named via the registry's `inverseOf`. Nothing is materialized.
30
+ - **Registry persistence is in-band**: `REVERSE` and `X IS verb` claims are
31
+ ordinary rows; on open the store replays them (in tx order) on top of the
32
+ initial registry, which defaults to the standard §5.5 prelude pairs. The
33
+ replay predicate mirrors the canonicalizer exactly — qualifier-condition
34
+ rows never declare, and `X IS verb` needs a verb-shaped subject — so the
35
+ registry after reopen equals the registry at close.
36
+ - **Traversal defaults**: `forward`/`reverse`/`topicMembers`/`topicsOf`
37
+ read *current beliefs* and skip negated (`VERB NOT`) and retracted
38
+ (`@ 0%`) rows; opt back in with `{ negated: true, retracted: true }`.
39
+ Contradictions still coexist as rows (§9.4) — resolution belongs to the
40
+ query layer.
41
+
42
+ ## API
43
+
44
+ | Method | Spec | Purpose |
45
+ |---|---|---|
46
+ | `ingest(text, {strict})` | §13.4 | parse → canonicalize → append; lenient by default |
47
+ | `insertResult(result)` | | append a pre-canonicalized `@cavelang/canonical` result |
48
+ | `currentBeliefs({minConf})` | §13.5 | latest row per key |
49
+ | `currentBelief(key)` / `history(key)` | §9.1 | one fact's belief series |
50
+ | `claimsAbout(entity)` | §13.5 | both directions, all rows |
51
+ | `forward(entity)` / `reverse(entity)` | §13.3 | named traversal, inverse-aware |
52
+ | `byTag(key, value?)` | §13.5 | flat (`value` omitted → `IS NULL`) or scoped |
53
+ | `byContext(ctx)` | §13.5 | context filter |
54
+ | `topicMembers(t)` / `topicsOf(e)` | §11.2 | topic layer over `CONTAINS` |
55
+ | `search(q, {raw})` | §13.2 | FTS5; literal phrase by default |
56
+ | `edgesOf(id)` | §13.2 | qualifier/grouping edges with roles |
57
+ | `toClaim(row)` | | reconstruct the canonical claim + side tables |
58
+ | `exportText({current})` | | emit canonical CAVE text |
59
+ | `db` | | raw `DatabaseSync` — used by `@cavelang/query` |
60
+
61
+ ## Storage decisions
62
+
63
+ - **Terms are stored formatted**: entities as plain text (so the spec's
64
+ `WHERE subject = 'auth/middleware'` queries work verbatim), literals with
65
+ their delimiters (`` `<=` ``, `"…"`) so they never collide with
66
+ same-spelled entities and reconstruct losslessly.
67
+ - **`value_text` is the value as written** (including `~`, multiplier
68
+ letters and literal delimiters); `value_num`/`value_unit` hold the
69
+ normalized §13.4 forms. Same for `delta_*`.
70
+ - **`id` doubles as `tx`** by default: a UUIDv7 is both unique and
71
+ time-ordered, and per-row tx ids keep same-document belief updates
72
+ ordered by line.
73
+ - **`search()` phrase-quotes by default** — FTS5 would parse
74
+ `token-expiry` as a column filter; `{ raw: true }` opts into full MATCH
75
+ syntax.
76
+ - **Current-only export remaps edge endpoints** to the current row of each
77
+ endpoint's claim key: a superseded qualified parent keeps its `WHEN`
78
+ attached to the surviving belief, and orphaned condition claims are never
79
+ promoted to top-level facts.
80
+
81
+ ## Tests
82
+
83
+ ```
84
+ pnpm --filter @cavelang/store test
85
+ ```
86
+
87
+ Covers the §9.1 belief series, §5.5 one-fact-two-names invariants
88
+ (unified belief through either name, negation riding the row, no
89
+ materialized inverses), every §13.5 query, the §11.2 topic reads, edge
90
+ persistence, registry rebuild across reopen, transactional strict ingest
91
+ and export round-trips.
@@ -0,0 +1,18 @@
1
+ /**
2
+ * `@cavelang/store` — CAVE persistence on the Node.js builtin `node:sqlite`
3
+ * (spec §13).
4
+ *
5
+ * ```ts
6
+ * import { open } from '@cavelang/store'
7
+ *
8
+ * const store = open('knowledge.db')
9
+ * store.ingest('monorepo CONTAINS packages/api')
10
+ * store.reverse('packages/api')
11
+ * // → [{ verb: 'CONTAINS', rel: 'PART-OF', source: 'monorepo', … }]
12
+ * ```
13
+ */
14
+ export * as Row from './row.ts';
15
+ export * as Schema from './schema.ts';
16
+ export { open } from './store.ts';
17
+ export type { ForwardFact, IngestResult, ReverseFact, Store, TraverseOptions } from './store.ts';
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,GAAG,MAAM,UAAU,CAAA;AAC/B,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AACjC,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * `@cavelang/store` — CAVE persistence on the Node.js builtin `node:sqlite`
3
+ * (spec §13).
4
+ *
5
+ * ```ts
6
+ * import { open } from '@cavelang/store'
7
+ *
8
+ * const store = open('knowledge.db')
9
+ * store.ingest('monorepo CONTAINS packages/api')
10
+ * store.reverse('packages/api')
11
+ * // → [{ verb: 'CONTAINS', rel: 'PART-OF', source: 'monorepo', … }]
12
+ * ```
13
+ */
14
+ export * as Row from "./row.js";
15
+ export * as Schema from "./schema.js";
16
+ export { open } from "./store.js";
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,GAAG,MAAM,UAAU,CAAA;AAC/B,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Row mapping — canonical claims ↔ `cave_claim` rows.
3
+ *
4
+ * Terms are stored *formatted* (delimiters preserved): entities as plain
5
+ * text so §13.5 queries like `WHERE subject = 'auth/middleware'` work, code
6
+ * literals as `` `<=` `` and text literals as `"…"` so a literal never
7
+ * collides with a same-spelled entity. Values are stored as written
8
+ * (`value_text`, incl. `~`, multiplier letters and delimiters) alongside
9
+ * the normalized numeric value and unit (spec §13.4 step 9).
10
+ */
11
+ import { Claim, Value } from '@cavelang/core';
12
+ /** A `cave_claim` row. */
13
+ export type Row = {
14
+ readonly id: string;
15
+ readonly tx: string;
16
+ readonly subject: string;
17
+ readonly verb: string;
18
+ readonly negated: number;
19
+ readonly object: null | string;
20
+ readonly attribute: null | string;
21
+ readonly value_text: null | string;
22
+ readonly value_num: null | number;
23
+ readonly value_unit: null | string;
24
+ readonly value_approx: number;
25
+ readonly delta_text: null | string;
26
+ readonly delta_num: null | number;
27
+ readonly delta_unit: null | string;
28
+ readonly sigma_level: null | number;
29
+ readonly conf: number;
30
+ readonly importance: number;
31
+ readonly comment: null | string;
32
+ readonly raw_line: string;
33
+ readonly claim_key: string;
34
+ };
35
+ export type t = Row;
36
+ /** @returns term parsed back from its stored formatted text. */
37
+ export declare const parseTerm: (text: string) => Claim.Term;
38
+ /** @returns value parsed back from its stored as-written text. */
39
+ export declare const parseValue: (text: string) => Value.t;
40
+ /** Column values of a claim, in `cave_claim` insert order (id/tx excluded). */
41
+ export declare const toColumns: (claim: Claim.t) => {
42
+ subject: string;
43
+ verb: string;
44
+ negated: number;
45
+ object: null | string;
46
+ attribute: null | string;
47
+ valueText: null | string;
48
+ valueNum: null | number;
49
+ valueUnit: null | string;
50
+ valueApprox: number;
51
+ deltaText: null | string;
52
+ deltaNum: null | number;
53
+ deltaUnit: null | string;
54
+ sigmaLevel: number;
55
+ conf: number;
56
+ importance: number;
57
+ comment: null | string;
58
+ rawLine: string;
59
+ claimKey: string;
60
+ };
61
+ /**
62
+ * @returns canonical claim reconstructed from a row plus its side tables.
63
+ * `sigmaLevel` collapses to `undefined` at the semantic default of 2.
64
+ */
65
+ export declare const toClaim: (row: Row, contexts: readonly string[], tags: readonly {
66
+ key: string;
67
+ value: null | string;
68
+ }[]) => Claim.t;
69
+ //# sourceMappingURL=row.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"row.d.ts","sourceRoot":"","sources":["../../src/row.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAE7C,0BAA0B;AAC1B,MAAM,MAAM,GAAG,GAAG;IAChB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,MAAM,EAAE,IAAI,GAAG,MAAM,CAAA;IAC9B,QAAQ,CAAC,SAAS,EAAE,IAAI,GAAG,MAAM,CAAA;IACjC,QAAQ,CAAC,UAAU,EAAE,IAAI,GAAG,MAAM,CAAA;IAClC,QAAQ,CAAC,SAAS,EAAE,IAAI,GAAG,MAAM,CAAA;IACjC,QAAQ,CAAC,UAAU,EAAE,IAAI,GAAG,MAAM,CAAA;IAClC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,UAAU,EAAE,IAAI,GAAG,MAAM,CAAA;IAClC,QAAQ,CAAC,SAAS,EAAE,IAAI,GAAG,MAAM,CAAA;IACjC,QAAQ,CAAC,UAAU,EAAE,IAAI,GAAG,MAAM,CAAA;IAClC,QAAQ,CAAC,WAAW,EAAE,IAAI,GAAG,MAAM,CAAA;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,OAAO,EAAE,IAAI,GAAG,MAAM,CAAA;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAC3B,CAAA;AAED,MAAM,MAAM,CAAC,GAAG,GAAG,CAAA;AAEnB,gEAAgE;AAChE,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,KAAG,KAAK,CAAC,IAQ9C,CAAA;AAED,kEAAkE;AAClE,eAAO,MAAM,UAAU,GAAI,MAAM,MAAM,KAAG,KAAK,CAAC,CAQ/C,CAAA;AAED,+EAA+E;AAC/E,eAAO,MAAM,SAAS,GAAI,OAAO,KAAK,CAAC,CAAC,KAAG;IACzC,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,IAAI,GAAG,MAAM,CAAA;IACrB,SAAS,EAAE,IAAI,GAAG,MAAM,CAAA;IACxB,SAAS,EAAE,IAAI,GAAG,MAAM,CAAA;IACxB,QAAQ,EAAE,IAAI,GAAG,MAAM,CAAA;IACvB,SAAS,EAAE,IAAI,GAAG,MAAM,CAAA;IACxB,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,IAAI,GAAG,MAAM,CAAA;IACxB,QAAQ,EAAE,IAAI,GAAG,MAAM,CAAA;IACvB,SAAS,EAAE,IAAI,GAAG,MAAM,CAAA;IACxB,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,IAAI,GAAG,MAAM,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;CA2BjB,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,OAAO,GAClB,KAAK,GAAG,EACR,UAAU,SAAS,MAAM,EAAE,EAC3B,MAAM,SAAS;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,IAAI,GAAG,MAAM,CAAA;CAAE,EAAE,KACrD,KAAK,CAAC,CAkBL,CAAA"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Row mapping — canonical claims ↔ `cave_claim` rows.
3
+ *
4
+ * Terms are stored *formatted* (delimiters preserved): entities as plain
5
+ * text so §13.5 queries like `WHERE subject = 'auth/middleware'` work, code
6
+ * literals as `` `<=` `` and text literals as `"…"` so a literal never
7
+ * collides with a same-spelled entity. Values are stored as written
8
+ * (`value_text`, incl. `~`, multiplier letters and delimiters) alongside
9
+ * the normalized numeric value and unit (spec §13.4 step 9).
10
+ */
11
+ import { Claim, Value } from '@cavelang/core';
12
+ /** @returns term parsed back from its stored formatted text. */
13
+ export const parseTerm = (text) => {
14
+ if (text.length >= 2 && text.startsWith('`') && text.endsWith('`')) {
15
+ return Claim.code(text.slice(1, -1));
16
+ }
17
+ if (text.length >= 2 && text.startsWith('"') && text.endsWith('"')) {
18
+ return Claim.text(text.slice(1, -1));
19
+ }
20
+ return Claim.entity(text);
21
+ };
22
+ /** @returns value parsed back from its stored as-written text. */
23
+ export const parseValue = (text) => {
24
+ if (text.length >= 2 && text.startsWith('`') && text.endsWith('`')) {
25
+ return Value.ofCode(text.slice(1, -1));
26
+ }
27
+ if (text.length >= 2 && text.startsWith('"') && text.endsWith('"')) {
28
+ return Value.ofText(text.slice(1, -1));
29
+ }
30
+ return Value.parse(text);
31
+ };
32
+ /** Column values of a claim, in `cave_claim` insert order (id/tx excluded). */
33
+ export const toColumns = (claim) => {
34
+ const payload = claim.payload;
35
+ const value = payload.kind === 'attribute' ? payload.value :
36
+ payload.kind === 'metric' ? payload.value :
37
+ undefined;
38
+ return {
39
+ subject: Claim.formatTerm(claim.subject),
40
+ verb: claim.verb,
41
+ negated: claim.negated ? 1 : 0,
42
+ object: payload.kind === 'relation' ? Claim.formatTerm(payload.object) : null,
43
+ attribute: payload.kind === 'attribute' ? payload.attribute : null,
44
+ valueText: value === undefined ? null : Value.format(value),
45
+ valueNum: value?.num ?? null,
46
+ valueUnit: value?.unit ?? null,
47
+ valueApprox: value?.approx === true ? 1 : 0,
48
+ deltaText: claim.delta === undefined ? null : Value.format(claim.delta),
49
+ deltaNum: claim.delta?.num ?? null,
50
+ deltaUnit: claim.delta?.unit ?? null,
51
+ sigmaLevel: claim.sigmaLevel ?? 2,
52
+ conf: claim.conf,
53
+ importance: claim.importance ? 1 : 0,
54
+ comment: claim.comment ?? null,
55
+ rawLine: claim.raw,
56
+ claimKey: '' // filled by the store with Key.of on the canonical claim
57
+ };
58
+ };
59
+ /**
60
+ * @returns canonical claim reconstructed from a row plus its side tables.
61
+ * `sigmaLevel` collapses to `undefined` at the semantic default of 2.
62
+ */
63
+ export const toClaim = (row, contexts, tags) => Claim.of({
64
+ subject: parseTerm(row.subject),
65
+ verb: row.verb,
66
+ negated: row.negated !== 0,
67
+ payload: row.object !== null ? Claim.relation(parseTerm(row.object)) :
68
+ row.attribute !== null && row.value_text !== null ? Claim.attribute(row.attribute, parseValue(row.value_text)) :
69
+ row.value_text !== null ? Claim.metric(parseValue(row.value_text)) :
70
+ Claim.none,
71
+ contexts,
72
+ tags: tags.map(tag => tag.value === null ? { key: tag.key } : { key: tag.key, value: tag.value }),
73
+ conf: row.conf,
74
+ importance: row.importance !== 0,
75
+ ...row.delta_text !== null ? { delta: parseValue(row.delta_text) } : {},
76
+ ...row.sigma_level !== null && row.sigma_level !== 2 ? { sigmaLevel: row.sigma_level } : {},
77
+ ...row.comment !== null ? { comment: row.comment } : {},
78
+ raw: row.raw_line
79
+ });
80
+ //# sourceMappingURL=row.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"row.js","sourceRoot":"","sources":["../../src/row.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Storage schema (spec §13.1, §13.2) — verbatim from the specification,
3
+ * with `IF NOT EXISTS` added so opening an existing database is idempotent.
4
+ */
5
+ import type { DatabaseSync } from 'node:sqlite';
6
+ export declare const ddl = "\nCREATE TABLE IF NOT EXISTS cave_claim (\n id TEXT PRIMARY KEY, -- UUIDv7\n tx TEXT NOT NULL, -- UUIDv7, lexicographic = transaction order\n\n subject TEXT NOT NULL, -- canonical (primary) direction\n verb TEXT NOT NULL, -- canonical (primary) verb\n negated INTEGER NOT NULL DEFAULT 0,\n\n object TEXT, -- relation object, entity, literal\n attribute TEXT, -- for HAS attr: value\n value_text TEXT, -- value as written (incl. ~, multiplier, delimiters)\n value_num REAL, -- parsed numeric value when possible\n value_unit TEXT, -- normalized unit string\n value_approx INTEGER NOT NULL DEFAULT 0,\n\n delta_text TEXT,\n delta_num REAL,\n delta_unit TEXT,\n sigma_level REAL DEFAULT 2.0,\n\n conf REAL NOT NULL DEFAULT 1.0,\n importance INTEGER NOT NULL DEFAULT 0,\n\n comment TEXT,\n raw_line TEXT NOT NULL, -- exactly as written, incl. inverse form\n\n claim_key TEXT NOT NULL -- normalized key; shared by forward/inverse readings\n);\n\nCREATE INDEX IF NOT EXISTS idx_cave_claim_key_tx ON cave_claim (claim_key, tx);\nCREATE INDEX IF NOT EXISTS idx_cave_subject ON cave_claim (subject);\nCREATE INDEX IF NOT EXISTS idx_cave_verb ON cave_claim (verb);\nCREATE INDEX IF NOT EXISTS idx_cave_object ON cave_claim (object);\nCREATE INDEX IF NOT EXISTS idx_cave_attribute ON cave_claim (attribute);\nCREATE INDEX IF NOT EXISTS idx_cave_conf ON cave_claim (conf);\n\nCREATE TABLE IF NOT EXISTS cave_context (\n claim_id TEXT NOT NULL,\n context TEXT NOT NULL,\n FOREIGN KEY (claim_id) REFERENCES cave_claim(id)\n);\nCREATE INDEX IF NOT EXISTS idx_cave_context ON cave_context (context);\n\nCREATE TABLE IF NOT EXISTS cave_tag (\n claim_id TEXT NOT NULL,\n key TEXT NOT NULL,\n value TEXT, -- NULL for flat tags (spec \u00A713.2)\n FOREIGN KEY (claim_id) REFERENCES cave_claim(id)\n);\nCREATE INDEX IF NOT EXISTS idx_cave_tag_key ON cave_tag (key, value);\n\nCREATE TABLE IF NOT EXISTS cave_edge (\n parent_id TEXT NOT NULL,\n role TEXT NOT NULL, -- WHEN, VIA, BECAUSE, QUALIFIES\n child_id TEXT NOT NULL,\n FOREIGN KEY (parent_id) REFERENCES cave_claim(id),\n FOREIGN KEY (child_id) REFERENCES cave_claim(id)\n);\nCREATE INDEX IF NOT EXISTS idx_cave_edge_parent ON cave_edge (parent_id);\nCREATE INDEX IF NOT EXISTS idx_cave_edge_child ON cave_edge (child_id);\nCREATE INDEX IF NOT EXISTS idx_cave_edge_role ON cave_edge (role);\n\nCREATE VIRTUAL TABLE IF NOT EXISTS cave_fts USING fts5(\n claim_id, subject, verb, object, attribute, value_text, comment, raw_line\n);\n";
7
+ /** Creates all tables and indexes. */
8
+ export declare const init: (db: DatabaseSync) => void;
9
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/schema.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE/C,eAAO,MAAM,GAAG,uvFAkEf,CAAA;AAED,sCAAsC;AACtC,eAAO,MAAM,IAAI,GAAI,IAAI,YAAY,KAAG,IAEvC,CAAA"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Storage schema (spec §13.1, §13.2) — verbatim from the specification,
3
+ * with `IF NOT EXISTS` added so opening an existing database is idempotent.
4
+ */
5
+ export const ddl = `
6
+ CREATE TABLE IF NOT EXISTS cave_claim (
7
+ id TEXT PRIMARY KEY, -- UUIDv7
8
+ tx TEXT NOT NULL, -- UUIDv7, lexicographic = transaction order
9
+
10
+ subject TEXT NOT NULL, -- canonical (primary) direction
11
+ verb TEXT NOT NULL, -- canonical (primary) verb
12
+ negated INTEGER NOT NULL DEFAULT 0,
13
+
14
+ object TEXT, -- relation object, entity, literal
15
+ attribute TEXT, -- for HAS attr: value
16
+ value_text TEXT, -- value as written (incl. ~, multiplier, delimiters)
17
+ value_num REAL, -- parsed numeric value when possible
18
+ value_unit TEXT, -- normalized unit string
19
+ value_approx INTEGER NOT NULL DEFAULT 0,
20
+
21
+ delta_text TEXT,
22
+ delta_num REAL,
23
+ delta_unit TEXT,
24
+ sigma_level REAL DEFAULT 2.0,
25
+
26
+ conf REAL NOT NULL DEFAULT 1.0,
27
+ importance INTEGER NOT NULL DEFAULT 0,
28
+
29
+ comment TEXT,
30
+ raw_line TEXT NOT NULL, -- exactly as written, incl. inverse form
31
+
32
+ claim_key TEXT NOT NULL -- normalized key; shared by forward/inverse readings
33
+ );
34
+
35
+ CREATE INDEX IF NOT EXISTS idx_cave_claim_key_tx ON cave_claim (claim_key, tx);
36
+ CREATE INDEX IF NOT EXISTS idx_cave_subject ON cave_claim (subject);
37
+ CREATE INDEX IF NOT EXISTS idx_cave_verb ON cave_claim (verb);
38
+ CREATE INDEX IF NOT EXISTS idx_cave_object ON cave_claim (object);
39
+ CREATE INDEX IF NOT EXISTS idx_cave_attribute ON cave_claim (attribute);
40
+ CREATE INDEX IF NOT EXISTS idx_cave_conf ON cave_claim (conf);
41
+
42
+ CREATE TABLE IF NOT EXISTS cave_context (
43
+ claim_id TEXT NOT NULL,
44
+ context TEXT NOT NULL,
45
+ FOREIGN KEY (claim_id) REFERENCES cave_claim(id)
46
+ );
47
+ CREATE INDEX IF NOT EXISTS idx_cave_context ON cave_context (context);
48
+
49
+ CREATE TABLE IF NOT EXISTS cave_tag (
50
+ claim_id TEXT NOT NULL,
51
+ key TEXT NOT NULL,
52
+ value TEXT, -- NULL for flat tags (spec §13.2)
53
+ FOREIGN KEY (claim_id) REFERENCES cave_claim(id)
54
+ );
55
+ CREATE INDEX IF NOT EXISTS idx_cave_tag_key ON cave_tag (key, value);
56
+
57
+ CREATE TABLE IF NOT EXISTS cave_edge (
58
+ parent_id TEXT NOT NULL,
59
+ role TEXT NOT NULL, -- WHEN, VIA, BECAUSE, QUALIFIES
60
+ child_id TEXT NOT NULL,
61
+ FOREIGN KEY (parent_id) REFERENCES cave_claim(id),
62
+ FOREIGN KEY (child_id) REFERENCES cave_claim(id)
63
+ );
64
+ CREATE INDEX IF NOT EXISTS idx_cave_edge_parent ON cave_edge (parent_id);
65
+ CREATE INDEX IF NOT EXISTS idx_cave_edge_child ON cave_edge (child_id);
66
+ CREATE INDEX IF NOT EXISTS idx_cave_edge_role ON cave_edge (role);
67
+
68
+ CREATE VIRTUAL TABLE IF NOT EXISTS cave_fts USING fts5(
69
+ claim_id, subject, verb, object, attribute, value_text, comment, raw_line
70
+ );
71
+ `;
72
+ /** Creates all tables and indexes. */
73
+ export const init = (db) => {
74
+ db.exec(ddl);
75
+ };
76
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/schema.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,CAAC,MAAM,GAAG,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkElB,CAAA;AAED,sCAAsC;AACtC,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,EAAgB,EAAQ,EAAE;IAC7C,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AACd,CAAC,CAAA"}
@@ -0,0 +1,124 @@
1
+ /**
2
+ * The CAVE store (spec §13) — append-only claim persistence on the Node.js
3
+ * builtin `node:sqlite`.
4
+ *
5
+ * - one row per fact, canonical direction; inverses are query-time views
6
+ * over existing indexes, never materialized rows (spec §13.3);
7
+ * - current belief = latest tx per claim key (spec §9.1, §13.5);
8
+ * - the verb registry is rebuilt from stored in-band declaration claims on
9
+ * open, so a reopened database keeps its inverse vocabulary;
10
+ * - full-text search over subjects, objects, values, comments and raw
11
+ * lines via FTS5.
12
+ */
13
+ import { DatabaseSync } from 'node:sqlite';
14
+ import { Claim } from '@cavelang/core';
15
+ import * as Canonical from '@cavelang/canonical';
16
+ import * as Row from './row.ts';
17
+ export type IngestResult = {
18
+ /** ids of inserted claim rows, in document order. */
19
+ readonly ids: readonly string[];
20
+ readonly edges: number;
21
+ readonly problems: readonly Canonical.Problem[];
22
+ };
23
+ export type ForwardFact = {
24
+ /** Canonical (primary) verb. */
25
+ readonly verb: string;
26
+ readonly target: string;
27
+ readonly row: Row.t;
28
+ };
29
+ export type ReverseFact = {
30
+ /** Canonical (primary) verb of the stored row. */
31
+ readonly verb: string;
32
+ /** Inverse relation name, `undefined` when none is declared (spec §5.5). */
33
+ readonly rel?: string;
34
+ readonly source: string;
35
+ readonly row: Row.t;
36
+ };
37
+ export type TraverseOptions = {
38
+ /** Include `VERB NOT` rows (default `false`). */
39
+ readonly negated?: boolean;
40
+ /** Include rows whose current belief is `@ 0%` (default `false`). */
41
+ readonly retracted?: boolean;
42
+ };
43
+ export type Store = ReturnType<typeof open>;
44
+ /**
45
+ * Opens (creating if necessary) a CAVE store. The registry defaults to the
46
+ * standard §5.5 prelude pairs and is extended by any declaration claims
47
+ * already stored; pass `Canonical.Registry.empty` for a declaration-free
48
+ * start.
49
+ */
50
+ export declare const open: (path?: string, options?: {
51
+ registry?: Canonical.Registry.t;
52
+ }) => {
53
+ /** Raw database handle — used by `@cavelang/query`; treat as read-only. */
54
+ db: DatabaseSync;
55
+ /** Current verb registry (input registry + stored + ingested declarations). */
56
+ registry: () => Canonical.Registry.t;
57
+ /**
58
+ * Parses, canonicalizes and appends CAVE text. Lenient by default —
59
+ * problems are returned, valid lines still land (spec §1.6); pass
60
+ * `strict` to throw instead.
61
+ */
62
+ ingest(text: string, options_?: {
63
+ strict?: boolean;
64
+ }): IngestResult;
65
+ /** Appends an already-canonicalized result. */
66
+ insertResult: (result: Canonical.Result) => IngestResult;
67
+ /** Latest row per claim key (spec §13.5), oldest first. */
68
+ currentBeliefs(options_?: {
69
+ minConf?: number;
70
+ }): Row.t[];
71
+ /** Current belief for one claim key, `undefined` if the fact is unknown. */
72
+ currentBelief(claimKey: string): undefined | Row.t;
73
+ /** Full belief series of one claim key, oldest first (spec §9.1). */
74
+ history(claimKey: string): Row.t[];
75
+ /** All rows about an entity, both directions, newest first (spec §13.5). */
76
+ claimsAbout(entity: string): Row.t[];
77
+ /** Forward reads: current relational facts with `entity` as subject (spec §13.3). */
78
+ forward(entity: string, options_?: TraverseOptions): ForwardFact[];
79
+ /**
80
+ * Inverse reads (spec §13.3): current relational facts
81
+ * with `entity` as object, relation named via the registry's inverse
82
+ * when one is declared.
83
+ */
84
+ reverse(entity: string, options_?: TraverseOptions): ReverseFact[];
85
+ /** Flat tag (`value` omitted → `value IS NULL`) or scoped tag rows (spec §13.5). */
86
+ byTag(key: string, value?: string): Row.t[];
87
+ /** Rows carrying a context (spec §13.5), newest first. */
88
+ byContext(context: string): Row.t[];
89
+ /** Members of a topic — forward `CONTAINS` traversal (spec §11.2). */
90
+ topicMembers(topic: string, options_?: TraverseOptions): string[];
91
+ /** Topics containing an entity — the inverse `CONTAINS` read (spec §11.2). */
92
+ topicsOf(entity: string, options_?: TraverseOptions): string[];
93
+ /**
94
+ * Full-text search, newest first. The query is treated as a literal
95
+ * phrase by default (safe for terms like `token-expiry`, which FTS5
96
+ * would otherwise parse as a column filter); pass `raw` to use full
97
+ * FTS5 MATCH syntax.
98
+ */
99
+ search(query: string, options_?: {
100
+ raw?: boolean;
101
+ }): Row.t[];
102
+ /** Qualifier/grouping edges of a claim row (spec §13.2). */
103
+ edgesOf(parentId: string): {
104
+ role: string;
105
+ child: Row.t;
106
+ }[];
107
+ /** Reconstructs the full canonical claim of a row (side tables included). */
108
+ toClaim: (row: Row.t) => Claim.t;
109
+ /**
110
+ * Emits the store as canonical CAVE text — all rows in transaction
111
+ * order, or only current beliefs with `current`.
112
+ *
113
+ * In current-only export an edge endpoint may be a superseded row;
114
+ * dropping such edges would silently un-condition current claims and
115
+ * promote orphaned WHEN conditions to top-level facts. Instead each
116
+ * endpoint resolves to the *current row of its claim key*, and the
117
+ * resulting edges are deduplicated.
118
+ */
119
+ exportText(options_?: {
120
+ current?: boolean;
121
+ }): string;
122
+ close(): void;
123
+ };
124
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/store.ts"],"names":[],"mappings":"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"}